diff --git a/docker/Dockerfile b/docker/Dockerfile index 38fe9c79e..44fc98afb 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM polardbx/polardbxbasejava:20221129 +FROM polardbx-opensource-registry.cn-beijing.cr.aliyuncs.com/polardbx/polardbxbasejava:20221129 WORKDIR /home/admin diff --git a/polardbx-calcite/pom.xml b/polardbx-calcite/pom.xml index dd15cd601..9eede5d3f 100644 --- a/polardbx-calcite/pom.xml +++ b/polardbx-calcite/pom.xml @@ -39,6 +39,12 @@ limitations under the License. org.apache.calcite.avatica avatica-core ${avatica.core.version} + + + org.apache.httpcomponents + httpcore + + org.apache.calcite @@ -51,11 +57,6 @@ limitations under the License. ${avatica-serve.version} test - - commons-dbcp - commons-dbcp - ${commons-dbcp.version} - org.apache.commons commons-lang3 @@ -95,6 +96,7 @@ limitations under the License. com.yahoo.datasketches sketches-core ${sketches-core.version} + provided junit @@ -164,17 +166,20 @@ limitations under the License. 9.3-1102-jdbc3 test - - org.slf4j - slf4j-api - compile - - - - org.slf4j - slf4j-log4j12 - test - + + + ch.qos.logback + logback-classic + + + org.slf4j + slf4j-api + ${slf4j_version} + + + org.slf4j + log4j-over-slf4j + sqlline @@ -203,6 +208,11 @@ limitations under the License. ${mockito.verison} test + + com.alibaba.polardbx + polardbx-net + ${parent.version} + @@ -302,24 +312,6 @@ limitations under the License. - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - verify - - jar-no-fork - test-jar-no-fork - - - - org.apache.maven.plugins maven-dependency-plugin diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java b/polardbx-calcite/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java index 8e7ecdfac..b44e6145a 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java @@ -16,6 +16,11 @@ */ package org.apache.calcite.adapter.jdbc; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; import org.apache.calcite.avatica.AvaticaUtils; import org.apache.calcite.avatica.SqlType; import org.apache.calcite.linq4j.tree.Expression; @@ -38,12 +43,7 @@ import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.util.Util; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Multimap; - +import javax.sql.DataSource; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -53,7 +53,6 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import javax.sql.DataSource; /** * Implementation of {@link Schema} that is backed by a JDBC data source. @@ -186,12 +185,7 @@ public static SqlDialect createDialect(SqlDialectFactory dialectFactory, /** Creates a JDBC data source with the given specification. */ public static DataSource dataSource(String url, String driverClassName, String username, String password) { - if (url.startsWith("jdbc:hsqldb:")) { - // Prevent hsqldb from screwing up java.util.logging. - System.setProperty("hsqldb.reconfig_logging", "false"); - } - return JdbcUtils.DataSourcePool.INSTANCE.get(url, driverClassName, username, - password); + throw new IllegalAccessError(); } public boolean isMutable() { diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java b/polardbx-calcite/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java index 0fe1761a4..a2359ed10 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java @@ -16,23 +16,17 @@ */ package org.apache.calcite.adapter.jdbc; +import com.google.common.collect.ImmutableList; +import com.google.common.primitives.Ints; import org.apache.calcite.avatica.ColumnMetaData; import org.apache.calcite.avatica.util.DateTimeUtils; import org.apache.calcite.linq4j.function.Function0; import org.apache.calcite.linq4j.function.Function1; import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlDialectFactory; -import org.apache.calcite.util.ImmutableNullableList; import org.apache.calcite.util.Pair; -import org.apache.commons.dbcp.BasicDataSource; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableList; -import com.google.common.primitives.Ints; - +import javax.sql.DataSource; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.Date; @@ -46,193 +40,162 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; -import javax.annotation.Nonnull; -import javax.sql.DataSource; /** * Utilities for the JDBC provider. */ final class JdbcUtils { - private JdbcUtils() { - throw new AssertionError("no instances!"); - } - - /** Pool of dialects. */ - static class DialectPool { - final Map> map0 = new IdentityHashMap<>(); - final Map map = new HashMap<>(); - - public static final DialectPool INSTANCE = new DialectPool(); - - // TODO: Discuss why we need a pool. If we do, I'd like to improve performance - synchronized SqlDialect get(SqlDialectFactory dialectFactory, DataSource dataSource) { - Map dialectMap = map0.get(dataSource); - if (dialectMap != null) { - final SqlDialect sqlDialect = dialectMap.get(dialectFactory); - if (sqlDialect != null) { - return sqlDialect; - } - } - Connection connection = null; - try { - connection = dataSource.getConnection(); - DatabaseMetaData metaData = connection.getMetaData(); - String productName = metaData.getDatabaseProductName(); - String productVersion = metaData.getDatabaseProductVersion(); - List key = ImmutableList.of(productName, productVersion, dialectFactory); - SqlDialect dialect = map.get(key); - if (dialect == null) { - dialect = dialectFactory.create(metaData); - map.put(key, dialect); - if (dialectMap == null) { - dialectMap = new IdentityHashMap<>(); - map0.put(dataSource, dialectMap); - } - dialectMap.put(dialectFactory, dialect); - } - connection.close(); - connection = null; - return dialect; - } catch (SQLException e) { - throw new RuntimeException(e); - } finally { - if (connection != null) { - try { - connection.close(); - } catch (SQLException e) { - // ignore - } - } - } - } - } - - /** Builder that calls {@link ResultSet#getObject(int)} for every column, - * or {@code getXxx} if the result type is a primitive {@code xxx}, - * and returns an array of objects for each row. */ - static class ObjectArrayRowBuilder implements Function0 { - private final ResultSet resultSet; - private final int columnCount; - private final ColumnMetaData.Rep[] reps; - private final int[] types; - - ObjectArrayRowBuilder(ResultSet resultSet, ColumnMetaData.Rep[] reps, - int[] types) - throws SQLException { - this.resultSet = resultSet; - this.reps = reps; - this.types = types; - this.columnCount = resultSet.getMetaData().getColumnCount(); + private JdbcUtils() { + throw new AssertionError("no instances!"); } - public static Function1> factory( - final List> list) { - return new Function1>() { - public Function0 apply(ResultSet resultSet) { - try { - return new ObjectArrayRowBuilder( - resultSet, - Pair.left(list).toArray(new ColumnMetaData.Rep[list.size()]), - Ints.toArray(Pair.right(list))); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - }; - } - - public Object[] apply() { - try { - final Object[] values = new Object[columnCount]; - for (int i = 0; i < columnCount; i++) { - values[i] = value(i); + /** + * Pool of dialects. + */ + static class DialectPool { + final Map> map0 = new IdentityHashMap<>(); + final Map map = new HashMap<>(); + + public static final DialectPool INSTANCE = new DialectPool(); + + // TODO: Discuss why we need a pool. If we do, I'd like to improve performance + synchronized SqlDialect get(SqlDialectFactory dialectFactory, DataSource dataSource) { + Map dialectMap = map0.get(dataSource); + if (dialectMap != null) { + final SqlDialect sqlDialect = dialectMap.get(dialectFactory); + if (sqlDialect != null) { + return sqlDialect; + } + } + Connection connection = null; + try { + connection = dataSource.getConnection(); + DatabaseMetaData metaData = connection.getMetaData(); + String productName = metaData.getDatabaseProductName(); + String productVersion = metaData.getDatabaseProductVersion(); + List key = ImmutableList.of(productName, productVersion, dialectFactory); + SqlDialect dialect = map.get(key); + if (dialect == null) { + dialect = dialectFactory.create(metaData); + map.put(key, dialect); + if (dialectMap == null) { + dialectMap = new IdentityHashMap<>(); + map0.put(dataSource, dialectMap); + } + dialectMap.put(dialectFactory, dialect); + } + connection.close(); + connection = null; + return dialect; + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + // ignore + } + } + } } - return values; - } catch (SQLException e) { - throw new RuntimeException(e); - } } /** - * Gets a value from a given column in a JDBC result set. - * - * @param i Ordinal of column (1-based, per JDBC) + * Builder that calls {@link ResultSet#getObject(int)} for every column, + * or {@code getXxx} if the result type is a primitive {@code xxx}, + * and returns an array of objects for each row. */ - private Object value(int i) throws SQLException { - // MySQL returns timestamps shifted into local time. Using - // getTimestamp(int, Calendar) with a UTC calendar should prevent this, - // but does not. So we shift explicitly. - switch (types[i]) { - case Types.TIMESTAMP: - return shift(resultSet.getTimestamp(i + 1)); - case Types.TIME: - return shift(resultSet.getTime(i + 1)); - case Types.DATE: - return shift(resultSet.getDate(i + 1)); - } - return reps[i].jdbcGet(resultSet, i + 1); - } + static class ObjectArrayRowBuilder implements Function0 { + private final ResultSet resultSet; + private final int columnCount; + private final ColumnMetaData.Rep[] reps; + private final int[] types; + + ObjectArrayRowBuilder(ResultSet resultSet, ColumnMetaData.Rep[] reps, + int[] types) + throws SQLException { + this.resultSet = resultSet; + this.reps = reps; + this.types = types; + this.columnCount = resultSet.getMetaData().getColumnCount(); + } - private static Timestamp shift(Timestamp v) { - if (v == null) { - return null; - } - long time = v.getTime(); - int offset = TimeZone.getDefault().getOffset(time); - return new Timestamp(time + offset); - } + public static Function1> factory( + final List> list) { + return new Function1>() { + public Function0 apply(ResultSet resultSet) { + try { + return new ObjectArrayRowBuilder( + resultSet, + Pair.left(list).toArray(new ColumnMetaData.Rep[list.size()]), + Ints.toArray(Pair.right(list))); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + }; + } - private static Time shift(Time v) { - if (v == null) { - return null; - } - long time = v.getTime(); - int offset = TimeZone.getDefault().getOffset(time); - return new Time((time + offset) % DateTimeUtils.MILLIS_PER_DAY); - } + public Object[] apply() { + try { + final Object[] values = new Object[columnCount]; + for (int i = 0; i < columnCount; i++) { + values[i] = value(i); + } + return values; + } catch (SQLException e) { + throw new RuntimeException(e); + } + } - private static Date shift(Date v) { - if (v == null) { - return null; - } - long time = v.getTime(); - int offset = TimeZone.getDefault().getOffset(time); - return new Date(time + offset); - } - } + /** + * Gets a value from a given column in a JDBC result set. + * + * @param i Ordinal of column (1-based, per JDBC) + */ + private Object value(int i) throws SQLException { + // MySQL returns timestamps shifted into local time. Using + // getTimestamp(int, Calendar) with a UTC calendar should prevent this, + // but does not. So we shift explicitly. + switch (types[i]) { + case Types.TIMESTAMP: + return shift(resultSet.getTimestamp(i + 1)); + case Types.TIME: + return shift(resultSet.getTime(i + 1)); + case Types.DATE: + return shift(resultSet.getDate(i + 1)); + } + return reps[i].jdbcGet(resultSet, i + 1); + } - /** Ensures that if two data sources have the same definition, they will use - * the same object. - * - *

This in turn makes it easier to cache - * {@link org.apache.calcite.sql.SqlDialect} objects. Otherwise, each time we - * see a new data source, we have to open a connection to find out what - * database product and version it is. */ - static class DataSourcePool { - public static final DataSourcePool INSTANCE = new DataSourcePool(); + private static Timestamp shift(Timestamp v) { + if (v == null) { + return null; + } + long time = v.getTime(); + int offset = TimeZone.getDefault().getOffset(time); + return new Timestamp(time + offset); + } - private final LoadingCache, BasicDataSource> cache = - CacheBuilder.newBuilder().softValues().build( - new CacheLoader, BasicDataSource>() { - @Override public BasicDataSource load(@Nonnull List key) { - BasicDataSource dataSource = new BasicDataSource(); - dataSource.setUrl(key.get(0)); - dataSource.setUsername(key.get(1)); - dataSource.setPassword(key.get(2)); - dataSource.setDriverClassName(key.get(3)); - return dataSource; - } - }); + private static Time shift(Time v) { + if (v == null) { + return null; + } + long time = v.getTime(); + int offset = TimeZone.getDefault().getOffset(time); + return new Time((time + offset) % DateTimeUtils.MILLIS_PER_DAY); + } - public DataSource get(String url, String driverClassName, - String username, String password) { - // Get data source objects from a cache, so that we don't have to sniff - // out what kind of database they are quite as often. - final List key = - ImmutableNullableList.of(url, username, password, driverClassName); - return cache.getUnchecked(key); + private static Date shift(Date v) { + if (v == null) { + return null; + } + long time = v.getTime(); + int offset = TimeZone.getDefault().getOffset(time); + return new Date(time + offset); + } } - } } // End JdbcUtils.java diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/plan/RelOptUtil.java b/polardbx-calcite/src/main/java/org/apache/calcite/plan/RelOptUtil.java index 9aa33c713..586d39887 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/plan/RelOptUtil.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/plan/RelOptUtil.java @@ -35,6 +35,7 @@ import org.apache.calcite.rel.RelShuttle; import org.apache.calcite.rel.RelVisitor; import org.apache.calcite.rel.RelWriter; +import org.apache.calcite.rel.core.Aggregate; import org.apache.calcite.rel.core.AggregateCall; import org.apache.calcite.rel.core.Calc; import org.apache.calcite.rel.core.Correlate; @@ -2819,6 +2820,64 @@ public static MultiJoin projectMultiJoin( multiJoin.getPostJoinFilter()); } + + /** + * Checks whether the given {@link RelNode} tree contains any aggregate operations. + * + * @param node The relational expression node to inspect + * @return True if an aggregate operation is found in the node or its subtree; False otherwise + */ + public static boolean containsAgg(RelNode node) { + // If the node is a HepRelVertex, replace it with its current rel + if (isHepRelVertex(node)) { + node = ((HepRelVertex) node).getCurrentRel(); + } + + try { + RelVisitor visitor = createAggregateFinder(); + // Traverse the node and its children + visitor.go(node); + // If no aggregate is found, return false + return false; + } catch (Util.FoundOne e) { + // If an aggregate is found, return true + return true; + } + } + + /** + * Helper method to check if the provided node is an instance of {@link HepRelVertex}. + * + * @param node The relational expression node to examine + * @return True if the node is a HepRelVertex; False otherwise + */ + private static boolean isHepRelVertex(RelNode node) { + return node instanceof HepRelVertex; + } + /** + * Constructs a {@link RelVisitor} that finds instances of aggregate operations ({@link Aggregate}). + * + * @return A visitor instance to search for aggregates + */ + private static RelVisitor createAggregateFinder() { + return new RelVisitor() { + @Override + public void visit(RelNode node, int ordinal, RelNode parent) { + // If the node is a HepRelVertex, replace it with its current rel + if (isHepRelVertex(node)) { + node = ((HepRelVertex) node).getCurrentRel(); + } + // Check if the node is an aggregate operation + if (node instanceof Aggregate) { + // Throw a marker exception to signal that an aggregate was found + throw Util.FoundOne.NULL; + } + // Continue visiting child nodes + super.visit(node, ordinal, parent); + } + }; + } + public static T addTrait( T rel, RelTrait trait) { //noinspection unchecked @@ -3301,7 +3360,7 @@ public static RelNode projectMapping( * @param project the project to be tested * @return true if the project has no subquery */ - static boolean notSubquery(LogicalProject project) { + public static boolean notSubquery(LogicalProject project) { for (RexNode r : project.getProjects()) { if (RexUtil.containsCorrelation(r)) { return false; } if (RexUtil.hasSubQuery(r)) { return false;} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/plan/volcano/TopDownRuleDriver.java b/polardbx-calcite/src/main/java/org/apache/calcite/plan/volcano/TopDownRuleDriver.java index da88116e6..21fe3a080 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/plan/volcano/TopDownRuleDriver.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/plan/volcano/TopDownRuleDriver.java @@ -205,6 +205,7 @@ private void clearProcessed(RelSet set) { RelSubset optimizingGroup = null; boolean canPassThrough = node instanceof PhysicalNode && !passThroughCache.contains(node); + boolean passThroughSuccess = false; if (!canPassThrough && subset.taskState != null) { optimizingGroup = subset; } else { @@ -229,9 +230,14 @@ private void clearProcessed(RelSet set) { Task task = getOptimizeInputTask(node, otherSubset); if (task != null) { tasks.push(task); + passThroughSuccess = true; } } } + // if pass through failed, optimizingGroup current subset + if ((!passThroughSuccess) && subset.taskState == RelSubset.OptimizeState.OPTIMIZING && optimizingGroup == null) { + optimizingGroup = subset; + } if (optimizingGroup == null) { // FIXME // In case some implementations use rules to convert between different physical conventions. @@ -281,7 +287,6 @@ void log(Task task) { if (!first) { builder.append(")"); } - LOGGER.debug(builder.toString()); } diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rel/core/TableScan.java b/polardbx-calcite/src/main/java/org/apache/calcite/rel/core/TableScan.java index 8b65158b3..2596b56a7 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/rel/core/TableScan.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rel/core/TableScan.java @@ -137,6 +137,7 @@ protected TableScan(RelInput input) { this(input.getCluster(), input.getTraitSet(), input.getTable("table")); this.flashback = input.getExpression("flashback"); this.indexNode = RexUtil.deSeriIndexHint(input.getStringList("index")); + this.flashbackOperator = input.getSqlOperator("flashbackOperator"); } //~ Methods ---------------------------------------------------------------- @@ -176,8 +177,9 @@ public ImmutableIntList identity() { @Override public RelWriter explainTerms(RelWriter pw) { return super.explainTerms(pw) .item("table", table.getQualifiedName()) - .itemIf("index", RexUtil.seriIndexHint(indexNode), indexNode!=null) + .itemIf("index", RexUtil.seriIndexHint(indexNode), indexNode != null) .item("flashback", flashback) + .itemIf("flashbackOperator", flashbackOperator, flashbackOperator != null) ; } diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rel/ddl/AlterTableArchivePartition.java b/polardbx-calcite/src/main/java/org/apache/calcite/rel/ddl/AlterTableArchivePartition.java new file mode 100644 index 000000000..3324b404c --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rel/ddl/AlterTableArchivePartition.java @@ -0,0 +1,35 @@ +package org.apache.calcite.rel.ddl; + +import org.apache.calcite.plan.Convention; +import org.apache.calcite.plan.RelOptCluster; +import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.DDL; +import org.apache.calcite.sql.SqlDdl; +import org.apache.calcite.sql.SqlNode; + +import java.util.List; + +/** + * @author wumu + */ +public class AlterTableArchivePartition extends DDL { + + protected AlterTableArchivePartition(RelOptCluster cluster, RelTraitSet traits, SqlDdl ddl, SqlNode tableName) { + super(cluster, traits, null); + this.sqlNode = ddl; + this.setTableName(tableName); + } + + public static AlterTableArchivePartition create(RelOptCluster cluster, SqlDdl ddl, SqlNode tableName) { + return new AlterTableArchivePartition(cluster, cluster.traitSet(), ddl, tableName); + } + + @Override + public AlterTableArchivePartition copy( + RelTraitSet traitSet, List inputs) { + assert traitSet.containsIfApplicable(Convention.NONE); + return new AlterTableArchivePartition(this.getCluster(), traitSet, this.ddl, getTableName()); + } +} + diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rel/ddl/AlterTableGroupOptimizePartition.java b/polardbx-calcite/src/main/java/org/apache/calcite/rel/ddl/AlterTableGroupOptimizePartition.java new file mode 100644 index 000000000..f8826d0b2 --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rel/ddl/AlterTableGroupOptimizePartition.java @@ -0,0 +1,43 @@ +package org.apache.calcite.rel.ddl; + +import org.apache.calcite.plan.Convention; +import org.apache.calcite.plan.RelOptCluster; +import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.sql.SqlDdl; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.parser.SqlParserPos; + +import java.util.List; + +public class AlterTableGroupOptimizePartition extends AlterTableGroupDdl { + + protected AlterTableGroupOptimizePartition(RelOptCluster cluster, RelTraitSet traits, SqlDdl ddl, + RelDataType rowType, + String tableGroupName) { + super(cluster, traits, ddl, rowType); + this.tableGroupName = tableGroupName; + this.sqlNode = ddl; + this.setTableName(new SqlIdentifier(tableGroupName, SqlParserPos.ZERO)); + } + + public static AlterTableGroupOptimizePartition create(RelOptCluster cluster, RelTraitSet traits, SqlDdl ddl, + RelDataType rowType, + String tableGroupName) { + + return new AlterTableGroupOptimizePartition(cluster, traits, ddl, rowType, tableGroupName); + } + + @Override + public AlterTableGroupOptimizePartition copy( + RelTraitSet traitSet, List inputs) { + assert traitSet.containsIfApplicable(Convention.NONE); + return new AlterTableGroupOptimizePartition(this.getCluster(), traitSet, this.ddl, rowType, tableGroupName); + } + + @Override + public String getTableGroupName() { + return tableGroupName; + } +} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rel/logical/LogicalSemiJoin.java b/polardbx-calcite/src/main/java/org/apache/calcite/rel/logical/LogicalSemiJoin.java index ccab1e0a7..4c97be9bf 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/rel/logical/LogicalSemiJoin.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rel/logical/LogicalSemiJoin.java @@ -411,8 +411,12 @@ public RexNode visitCall(RexCall call) { return null; } if (relBuilder.peek().getRowType().getFieldCount() > this.getOperands().size()) { - if (operator.getKind() != EXISTS && operator.getKind() != NOT_EXISTS - && operator.getKind() != SCALAR_QUERY) { + if (operator.getKind() == EXISTS || operator.getKind() == NOT_EXISTS) { + if (!RelOptUtil.containsAgg(relBuilder.peek()) && + !(relBuilder.peek() instanceof LogicalProject)) { + relBuilder.project(rexBuilder.makeInputRef(relBuilder.peek(), 0)); + } + } else if (operator.getKind() != SCALAR_QUERY) { List rexNodes = Lists.newArrayList(); for (int i = 0; i < this.getOperands().size(); i++) { rexNodes.add(rexBuilder.makeInputRef(relBuilder.peek(), i)); diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java b/polardbx-calcite/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java index 81a4eb786..3a737dd98 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java @@ -44,6 +44,7 @@ * targeted at any particular engine or calling convention. */ public class LogicalSort extends Sort { + private final SortOptimizationContext sortOptimizationContext = new SortOptimizationContext(); protected boolean ignore = false; protected LogicalSort(RelOptCluster cluster, RelTraitSet traitSet, @@ -97,11 +98,13 @@ public static LogicalSort create(RelTraitSet traitSet, RelNode input, RelCollati RelCollation newCollation, RexNode offset, RexNode fetch) { LogicalSort logicalSort = new LogicalSort(getCluster(), traitSet, newInput, newCollation, offset, fetch, ignore); + logicalSort.sortOptimizationContext.copyFrom(sortOptimizationContext); return logicalSort; } public Sort copy(RelNode newInput, RelCollation newCollation) { LogicalSort logicalSort = new LogicalSort(getCluster(), traitSet, newInput, newCollation, offset, fetch, ignore); + logicalSort.sortOptimizationContext.copyFrom(sortOptimizationContext); return logicalSort; } @@ -142,6 +145,10 @@ public boolean isIgnore() { public void setIgnore(boolean ignore) { this.ignore = ignore; } + + public SortOptimizationContext getSortOptimizationContext() { + return sortOptimizationContext; + } } // End LogicalSort.java diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rel/logical/SortOptimizationContext.java b/polardbx-calcite/src/main/java/org/apache/calcite/rel/logical/SortOptimizationContext.java new file mode 100644 index 000000000..7d46644d7 --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rel/logical/SortOptimizationContext.java @@ -0,0 +1,20 @@ +package org.apache.calcite.rel.logical; + +public class SortOptimizationContext { + private boolean isSortPushed = false; + + public SortOptimizationContext() {} + + void copyFrom(SortOptimizationContext aggOptimizationContext) { + this.isSortPushed = aggOptimizationContext.isSortPushed; + } + + public boolean isSortPushed() { + return isSortPushed; + } + + public void setSortPushed(boolean sortPushed) { + isSortPushed = sortPushed; + } + +} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java b/polardbx-calcite/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java index 2f375ee4a..a05b39435 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rel/metadata/RelMdSelectivity.java @@ -100,6 +100,13 @@ public Double getSelectivity(Sort rel, RelMetadataQuery mq, public Double getSelectivity(Correlate rel, RelMetadataQuery mq, RexNode predicate) { + if (predicate == null || rel == null) { + return 1.0D; + } + int maxIndex = RexUtil.findMaxIndex(predicate); + if (maxIndex >= rel.getLeft().getRowType().getFieldCount()) { + return 1.0D; + } return mq.getSelectivity(rel.getLeft(), predicate); } diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java b/polardbx-calcite/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java index b46e8b9f9..87a491a08 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java @@ -65,6 +65,7 @@ import org.apache.calcite.sql.SqlBinaryOperator; import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlCallParam; +import org.apache.calcite.sql.SqlDelete; import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlDynamicParam; import org.apache.calcite.sql.SqlIdentifier; @@ -395,9 +396,15 @@ public Result result(SqlNode node, Collection clauses, return new Result(node, clauses, alias4, rel.getRowType(), aliases); } final String alias5; + /** + * set existForceIndex = true when forced index exists to make neededAlias not null, + * otherwise alias will be implicit in asFrom() + */ + boolean existForceIndex = node.getKind() == SqlKind.IDENTIFIER && ((SqlIdentifier)node).indexNode != null; if (alias2 == null || !alias2.equals(alias4) - || !dialect.hasImplicitTableAlias()) { + || !dialect.hasImplicitTableAlias() + || existForceIndex) { alias5 = alias4; } else { alias5 = null; @@ -1435,7 +1442,7 @@ public SqlNode asFrom() { //} // MySQL only support syntax showed above. // So that we must put AS OF in front of alias and index_hint_list behind alias - if (node instanceof SqlIdentifier && ((SqlIdentifier) node).flashback != null + if (node instanceof SqlIdentifier && ((SqlIdentifier) node).indexNode != null) { // Move index hint from identifier to alias final SqlIdentifier identifier = (SqlIdentifier) node; diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rel/rules/CalcRelSplitter.java b/polardbx-calcite/src/main/java/org/apache/calcite/rel/rules/CalcRelSplitter.java index 2677755ad..f193139b1 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/rel/rules/CalcRelSplitter.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rel/rules/CalcRelSplitter.java @@ -404,16 +404,21 @@ private int chooseLevels( // For dynamic rex node (constant value), pull up its level to avoid project calculation. int maxLevel = Integer.MIN_VALUE; + int[] maxRefLevel = new int[exprLevels.length]; + Arrays.fill(maxRefLevel, Integer.MAX_VALUE); for (int i = 0; i < exprLevels.length; i++) { maxLevel = Math.max(maxLevel, exprLevels[i]); + for (int j : RexUtil.LocalRefFinder.findAllLocalRefs(exprs[i])) { + maxRefLevel[j] = Math.min(maxRefLevel[j], exprLevels[i]); + } } + for (int i = 0; i < exprs.length; i++) { RexNode rexNode = exprs[i]; if (rexNode instanceof RexDynamicParam) { - exprLevels[i] = maxLevel; + exprLevels[i] = Math.min(maxRefLevel[i], maxLevel); } } - return levelCount; } diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rel/rules/FilterAggregateTransposeRule.java b/polardbx-calcite/src/main/java/org/apache/calcite/rel/rules/FilterAggregateTransposeRule.java index f65d874b1..8471a5ae3 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/rel/rules/FilterAggregateTransposeRule.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rel/rules/FilterAggregateTransposeRule.java @@ -92,6 +92,13 @@ public void onMatch(RelOptRuleCall call) { final Filter filterRel = call.rel(0); final Aggregate aggRel = call.rel(1); + if (aggRel.getGroupCount() == 0) { + // We can not push the Filter pass the Aggregate without group keys. The whole + // input dataset would be the only group if there is no GROUP BY. Think about the case: + // 'select count(*) from T1 having false', the result is expected to be an empty set, + // but it would return zero if we push the Filter pass the Aggregate. + return; + } final List conditions = RelOptUtil.conjunctions(filterRel.getCondition()); final RexBuilder rexBuilder = filterRel.getCluster().getRexBuilder(); diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rex/RexBuilder.java b/polardbx-calcite/src/main/java/org/apache/calcite/rex/RexBuilder.java index b90caa7f3..2da52809d 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/rex/RexBuilder.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rex/RexBuilder.java @@ -16,6 +16,7 @@ */ package org.apache.calcite.rex; +import com.alibaba.polardbx.common.datatype.Decimal; import com.alibaba.polardbx.common.datatype.UInt64; import com.google.common.base.Function; import com.google.common.base.Preconditions; @@ -906,6 +907,12 @@ public RexLiteral makeFlag(Enum flag) { SqlTypeName.SYMBOL); } + public RexLiteral makeCharNullLiteral() { + RelDataType type = typeFactory.createSqlType(SqlTypeName.CHAR); + type = typeFactory.createTypeWithNullability(type, true); + return new RexLiteral(null, type, SqlTypeName.CHAR); + } + /** * Internal method to create a call to a literal. Code outside this package * should call one of the type-specific methods such as @@ -1635,6 +1642,10 @@ private static Object clean(Object o, RelDataType type) { if (o instanceof BigDecimal) { return o; } + if (o instanceof Decimal) { + // avoid precision loss + return ((Decimal) o).toBigDecimal(); + } return new BigDecimal(((Number) o).longValue()); case FLOAT: if (o instanceof BigDecimal) { diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/rex/RexUtil.java b/polardbx-calcite/src/main/java/org/apache/calcite/rex/RexUtil.java index 643d6f7a5..ce6e0372a 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/rex/RexUtil.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/rex/RexUtil.java @@ -16,25 +16,39 @@ */ package org.apache.calcite.rex; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.jdbc.RawString; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.util.RexMemoryLimitHelper; import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; -import com.google.common.collect.*; -import com.alibaba.polardbx.common.exception.TddlRuntimeException; -import com.alibaba.polardbx.common.exception.code.ErrorCode; -import com.alibaba.polardbx.common.utils.logger.Logger; -import com.alibaba.polardbx.common.utils.logger.LoggerFactory; -import com.alibaba.polardbx.util.RexMemoryLimitHelper; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import org.apache.calcite.linq4j.function.Predicate1; import org.apache.calcite.plan.RelOptPredicateList; import org.apache.calcite.plan.RelOptUtil; -import org.apache.calcite.rel.*; -import org.apache.calcite.rel.core.*; +import org.apache.calcite.rel.RelCollation; +import org.apache.calcite.rel.RelCollations; +import org.apache.calcite.rel.RelFieldCollation; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.RelVisitor; +import org.apache.calcite.rel.core.AggregateCall; +import org.apache.calcite.rel.core.CorrelationId; +import org.apache.calcite.rel.core.Filter; +import org.apache.calcite.rel.core.Join; +import org.apache.calcite.rel.core.Project; import org.apache.calcite.rel.logical.LogicalFilter; import org.apache.calcite.rel.logical.LogicalProject; +import org.apache.calcite.rel.logical.LogicalTableScan; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.rel.type.RelDataTypeFamily; @@ -42,7 +56,17 @@ import org.apache.calcite.rex.RexTableInputRef.RelTableRef; import org.apache.calcite.runtime.PredicateImpl; import org.apache.calcite.schema.Schemas; -import org.apache.calcite.sql.*; +import org.apache.calcite.sql.SqlAggFunction; +import org.apache.calcite.sql.SqlBinaryOperator; +import org.apache.calcite.sql.SqlFunction; +import org.apache.calcite.sql.SqlIndexHint; +import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlNodeList; +import org.apache.calcite.sql.SqlOperator; +import org.apache.calcite.sql.SqlPostfixOperator; +import org.apache.calcite.sql.SqlPrefixOperator; import org.apache.calcite.sql.dialect.MysqlSqlDialect; import org.apache.calcite.sql.fun.SqlCaseOperator; import org.apache.calcite.sql.fun.SqlCastFunction; @@ -52,7 +76,6 @@ import org.apache.calcite.sql.type.SqlTypeFamily; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.sql.type.SqlTypeUtil; -import org.apache.calcite.sql.util.SqlString; import org.apache.calcite.sql.validate.SqlValidatorUtil; import org.apache.calcite.sql2rel.CorrelationReferenceFinder; import org.apache.calcite.util.ControlFlowException; @@ -61,12 +84,26 @@ import org.apache.calcite.util.Pair; import org.apache.calcite.util.Util; import org.apache.calcite.util.mapping.Mappings; -import org.apache.http.protocol.ExecutionContext; import javax.annotation.Nonnull; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; +import static org.apache.calcite.sql.type.SqlTypeName.CHAR_TYPES; +import static org.apache.calcite.sql.type.SqlTypeName.INT_TYPES; + /** * Utility methods concerning row-expressions. */ @@ -596,8 +633,14 @@ protected RexNode handle(RexFieldAccess fieldAccess) { (RexCorrelVariable) fieldAccess.getReferenceExpr(); if (v.getId().equals(id)) { RexCorrelVariable newRexCor = new RexCorrelVariable(v.getId(), type); - int newIndex = shiftIndex.get(fieldAccess.getField().getIndex()); - RexFieldAccess newRexField = new RexFieldAccess(newRexCor, type.getFieldList().get(newIndex)); + RexFieldAccess newRexField; + if(shiftIndex.containsKey(fieldAccess.getField().getIndex())){ + int newIndex = shiftIndex.get(fieldAccess.getField().getIndex()); + newRexField = new RexFieldAccess(newRexCor, type.getFieldList().get(newIndex)); + }else{ + newRexField = new RexFieldAccess(newRexCor, type.getFieldList().get(fieldAccess.getField().getIndex())); + } + return newRexField; } return fieldAccess; @@ -2936,6 +2979,85 @@ public Void visitDynamicParam(RexDynamicParam dynamicParam) { } } + public static class EqualAndInExprFinder extends RexVisitorImpl { + private Map> map = Maps.newHashMap(); + private List fields; + + public EqualAndInExprFinder(LogicalTableScan scan) { + super(true); + fields = scan.getRowType().getFieldList(); + } + + public Void visitCall(RexCall call) { + if (call.getKind() == SqlKind.EQUALS) { + if (call.getOperands().get(0) instanceof RexInputRef && + call.getOperands().get(1) instanceof RexDynamicParam) { + RexInputRef ref = (RexInputRef) call.getOperands().get(0); + RexDynamicParam param = (RexDynamicParam) call.getOperands().get(1); + RelDataType type = fields.get(ref.getIndex()).getType(); + if (CHAR_TYPES.contains(type.getSqlTypeName()) && + INT_TYPES.contains(param.getType().getSqlTypeName())) { + if (map.get("int2char") == null) { + map.put("int2char", Sets.newHashSet()); + } + map.get("int2char").add(param.getIndex()); + } else if (INT_TYPES.contains(type.getSqlTypeName()) + && CHAR_TYPES.contains(param.getType().getSqlTypeName())) { + if (map.get("char2int") == null) { + map.put("char2int", Sets.newHashSet()); + } + map.get("char2int").add(param.getIndex()); + } + } else if (call.getOperands().get(1) instanceof RexInputRef && + call.getOperands().get(0) instanceof RexDynamicParam) { + RexInputRef ref = (RexInputRef) call.getOperands().get(1); + RexDynamicParam param = (RexDynamicParam) call.getOperands().get(0); + RelDataType type = fields.get(ref.getIndex()).getType(); + if (CHAR_TYPES.contains(type.getSqlTypeName()) + && INT_TYPES.contains(param.getType().getSqlTypeName())) { + if (map.get("int2char") == null) { + map.put("int2char", Sets.newHashSet()); + } + map.get("int2char").add(param.getIndex()); + } else if (INT_TYPES.contains(type.getSqlTypeName()) + && CHAR_TYPES.contains(param.getType().getSqlTypeName())) { + if (map.get("char2int") == null) { + map.put("char2int", Sets.newHashSet()); + } + map.get("char2int").add(param.getIndex()); + } + } + } else if (call.getKind() == SqlKind.IN) { + if (call.getOperands().get(0) instanceof RexInputRef && + call.getOperands().get(1).getKind() == SqlKind.ROW && + ((RexCall) call.getOperands().get(1)).getOperands().get(0) instanceof RexDynamicParam) { + RexInputRef ref = (RexInputRef) call.getOperands().get(0); + RexDynamicParam param = + (RexDynamicParam) ((RexCall) call.getOperands().get(1)).getOperands().get(0); + RelDataType type = fields.get(ref.getIndex()).getType(); + if (CHAR_TYPES.contains(type.getSqlTypeName())) { + if (map.get("int2char") == null) { + map.put("int2char", Sets.newHashSet()); + } + map.get("int2char").add(param.getIndex()); + } else if (INT_TYPES.contains(type.getSqlTypeName())) { + if (map.get("char2int") == null) { + map.put("char2int", Sets.newHashSet()); + } + map.get("char2int").add(param.getIndex()); + } + } + } else { + return super.visitCall(call); + } + return null; + } + + public Map> getMap() { + return map; + } + } + public static class SubQueryCounter extends RexVisitorImpl { private int subqueryCount = 0; @@ -3192,6 +3314,30 @@ public List getSubQueries() { } } + static public class LocalRefFinder extends RexVisitorImpl { + private Set rexLocalRefs = Sets.newHashSet(); + + protected LocalRefFinder() { + super(true); + } + + @Override + public Void visitLocalRef(RexLocalRef localRef) { + rexLocalRefs.add(localRef.getIndex()); + return null; + } + + public Set getRexLocalRefs() { + return rexLocalRefs; + } + + public static Set findAllLocalRefs(RexNode rexNode) { + LocalRefFinder localRefFinder = new LocalRefFinder(); + rexNode.accept(localRefFinder); + return localRefFinder.getRexLocalRefs(); + } + } + static public class AllIndexInFinder extends RexVisitorImpl { private List indexList = Lists.newArrayList(); diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTable.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTable.java index 197e3129e..cae22244a 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTable.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTable.java @@ -369,6 +369,10 @@ public boolean isExpireLocalPartition() { return alters != null && alters.size() == 1 && alters.get(0) instanceof SqlAlterTableExpireLocalPartition; } + public boolean isCleanupExpiredData() { + return alters != null && alters.size() == 1 && alters.get(0) instanceof SqlAlterTableCleanupExpiredData; + } + public boolean isAlterIndexVisibility() { return alters != null && alters.size() == 1 @@ -480,6 +484,10 @@ public boolean isModifyPartitionValues() { return alters.size() > 0 && alters.get(0) instanceof SqlAlterTableModifyPartitionValues; } + public boolean isOptimizePartition() { + return alters.size() > 0 && alters.get(0) instanceof SqlAlterTableOptimizePartition; + } + public List getLogicalReferencedTables() { return logicalReferencedTables; } diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableArchivePartition.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableArchivePartition.java new file mode 100644 index 000000000..7e40f13e7 --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableArchivePartition.java @@ -0,0 +1,100 @@ +package org.apache.calcite.sql; + +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.util.SqlString; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +/** + * @author wumu + */ +public class SqlAlterTableArchivePartition extends SqlAlterTable { + + private final SqlIdentifier originTableName; + + private Set targetPartitions; + private final boolean subPartitionsArchive; + + public SqlAlterTableArchivePartition(SqlIdentifier tableName, + String sql, + Set targetPartitions, + boolean subPartitionsArchive) { + super(null, tableName, null, sql, null, new ArrayList<>(), SqlParserPos.ZERO); + originTableName = tableName; + this.targetPartitions = targetPartitions; + this.subPartitionsArchive = subPartitionsArchive; + } + + @Override + public SqlIdentifier getOriginTableName() { + return originTableName; + } + + @Override + public List getOperandList() { + return Arrays.asList(name); + } + + @Override + public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { + unparse(writer, leftPrec, rightPrec, false); + } + + @Override + public void unparse(SqlWriter writer, int leftPrec, int rightPrec, boolean withOriginTableName) { + final SqlWriter.Frame frame = writer.startList(SqlWriter.FrameTypeEnum.SELECT, "ALTER TABLE", ""); + + name.unparse(writer, leftPrec, rightPrec); + + writer.endList(frame); + } + + @Override + public void setTargetTable(SqlIdentifier sqlIdentifier) { + this.name = sqlIdentifier; + } + + private String prepare() { + return getSourceSql(); + } + + public String getSchemaName() { + return originTableName.getComponent(0).getLastName(); + } + + public String getPrimaryTableName() { + return originTableName.getComponent(1).getLastName(); + } + + @Override + public SqlNode getTargetTable() { + return super.getTargetTable(); + } + + @Override + public String toString() { + return prepare(); + } + + @Override + public SqlString toSqlString(SqlDialect dialect) { + String sql = prepare(); + return new SqlString(dialect, sql); + } + + public Set getTargetPartitions() { + return targetPartitions; + } + + public void setTargetPartitions(Set targetPartitions) { + this.targetPartitions = targetPartitions; + } + + public boolean isSubPartitionsArchive() { + return subPartitionsArchive; + } + +} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableCleanupExpiredData.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableCleanupExpiredData.java new file mode 100644 index 000000000..b649b7627 --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableCleanupExpiredData.java @@ -0,0 +1,46 @@ +package org.apache.calcite.sql; + +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.util.SqlString; + +import java.util.List; + +/** + * see com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlStatementParser.java:7484 + * key words: "EXPIRE" + * + * @author guxu + */ +public class SqlAlterTableCleanupExpiredData extends SqlAlterSpecification { + + private static final SqlOperator OPERATOR = new SqlSpecialOperator("CLEANUP EXPIRED DATA", SqlKind.CLEANUP_EXPIRED_DATA); + + public SqlAlterTableCleanupExpiredData(SqlParserPos pos, List partitions) { + super(pos); + } + + @Override + public SqlOperator getOperator() { + return OPERATOR; + } + + @Override + public List getOperandList() { + return null; + } + + + @Override + public String toString() { + return "CLEANUP EXPIRED DATA"; + } + + @Override + public SqlString toSqlString(SqlDialect dialect) { + return new SqlString(dialect ,toString()); + } + + + @Override + public boolean supportFileStorage() { return true;} +} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableModifyTtlOptions.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableModifyTtlOptions.java new file mode 100644 index 000000000..af919a60c --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableModifyTtlOptions.java @@ -0,0 +1,163 @@ +package org.apache.calcite.sql; + +import com.alibaba.polardbx.druid.DbType; +import com.alibaba.polardbx.druid.sql.SQLUtils; +import org.apache.calcite.sql.parser.SqlParserPos; + +import java.util.ArrayList; +import java.util.List; + +/**. + * + * @author chenghui.lch + */ +public class SqlAlterTableModifyTtlOptions extends SqlAlterSpecification { + + private static final SqlOperator OPERATOR = new SqlSpecialOperator("MODIFY TTL", SqlKind.MODIFY_TTL); + + private String ttlEnable = null; + private SqlNode ttlExpr = null; + private SqlNode ttlJob = null; + private String archiveTableSchema = null; + private String archiveTableName = null; + private String archiveKind = null; + private Integer arcPreAllocate = null; + private Integer arcPostAllocate = null; + + public SqlAlterTableModifyTtlOptions(SqlParserPos pos) { + super(pos); + } + + @Override + public SqlOperator getOperator() { + return OPERATOR; + } + + @Override + public List getOperandList() { + List opList = new ArrayList<>(); + opList.add(ttlExpr); + opList.add(ttlJob); + return opList; + } + + @Override + public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { + final SqlWriter.Frame frame = writer.startList(SqlWriter.FrameTypeEnum.SELECT, "MODIFY TTL", ""); + + if (ttlEnable != null) { + writer.print(" TTL_ENABLE = "); + writer.print(String.format("'%s'", ttlEnable)); + writer.print(" "); + } + + if (ttlExpr != null) { + writer.print(" TTL_EXPR = "); + ttlExpr.unparse(writer,leftPrec, rightPrec); + writer.print(" "); + } + + if (ttlJob != null) { + writer.print(" TTL_JOB = "); + ttlJob.unparse(writer,leftPrec, rightPrec); + writer.print(" "); + } + + if (archiveTableSchema != null) { + writer.print(" ARCHIVE_TABLE_SCHEMA = "); + writer.print(String.format("'%s'", archiveTableSchema)); + writer.print(" "); + } + + if (archiveTableName != null) { + writer.print(" ARCHIVE_TABLE_NAME = "); + writer.print(String.format("'%s'", archiveTableSchema)); + writer.print(" "); + } + + if (archiveKind != null) { + writer.print(" ARCHIVE_KIND = "); + writer.print(String.format("'%s'", archiveKind)); + writer.print(" "); + } + + if (arcPreAllocate != null) { + writer.print(" ARC_PRE_ALLOCATE = "); + writer.print(arcPreAllocate); + writer.print(" "); + } + + if (arcPostAllocate != null) { + writer.print(" ARC_POST_ALLOCATE = "); + writer.print(arcPostAllocate); + writer.print(" "); + } + + writer.endList(frame); + } + + public String getTtlEnable() { + return ttlEnable; + } + + public void setTtlEnable(String ttlEnable) { + this.ttlEnable = ttlEnable; + } + + public SqlNode getTtlExpr() { + return ttlExpr; + } + + public void setTtlExpr(SqlNode ttlExpr) { + this.ttlExpr = ttlExpr; + } + + public SqlNode getTtlJob() { + return ttlJob; + } + + public void setTtlJob(SqlNode ttlJob) { + this.ttlJob = ttlJob; + } + + public String getArchiveTableName() { + return archiveTableName; + } + + public void setArchiveTableName(String archiveTableName) { + this.archiveTableName = archiveTableName; + } + + public String getArchiveTableSchema() { + return archiveTableSchema; + } + + public void setArchiveTableSchema(String archiveTableSchema) { + this.archiveTableSchema = archiveTableSchema; + } + + public String getArchiveKind() { + return archiveKind; + } + + public void setArchiveKind(String archiveKind) { + this.archiveKind = archiveKind; + } + + public Integer getArcPreAllocate() { + return arcPreAllocate; + } + + public void setArcPreAllocate(Integer arcPreAllocate) { + this.arcPreAllocate = arcPreAllocate; + } + + public Integer getArcPostAllocate() { + return arcPostAllocate; + } + + public void setArcPostAllocate(Integer arcPostAllocate) { + this.arcPostAllocate = arcPostAllocate; + } + +} \ No newline at end of file diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableMovePartition.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableMovePartition.java index 226b4cc96..5753381cf 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableMovePartition.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableMovePartition.java @@ -17,7 +17,6 @@ package org.apache.calcite.sql; import org.apache.calcite.sql.parser.SqlParserPos; -import org.eclipse.jetty.util.BlockingCallback; import java.util.List; import java.util.Map; diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableOptimizePartition.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableOptimizePartition.java new file mode 100644 index 000000000..f10afd261 --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableOptimizePartition.java @@ -0,0 +1,90 @@ +package org.apache.calcite.sql; + +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.druid.sql.ast.SQLExpr; +import com.alibaba.polardbx.druid.sql.ast.SQLName; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.validate.SqlValidator; +import org.apache.calcite.sql.validate.SqlValidatorScope; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author chenghui.lch + */ +public class SqlAlterTableOptimizePartition extends SqlAlterSpecification { + + private static final SqlOperator OPERATOR = new SqlSpecialOperator("OPTIMIZE PARTITION", SqlKind.OPTIMIZE_PARTITION); + + protected final List partitions; + + protected SqlNode parent; + protected boolean isSubPartition; + + public SqlAlterTableOptimizePartition(SqlParserPos pos, List partitions, boolean isSubPartition) { + super(pos); + this.partitions = partitions; + this.isSubPartition = isSubPartition; + } + + @Override + public SqlOperator getOperator() { + return OPERATOR; + } + + @Override + public List getOperandList() { + return this.partitions; + } + + @Override + public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { + final SqlWriter.Frame frame = writer.startList(SqlWriter.FrameTypeEnum.SELECT, "OPTIMIZE", ""); + + writer.keyword("PARTITION"); + final SqlWriter.Frame partFrame = writer.startList(SqlWriter.FrameTypeEnum.SELECT, "(", ")"); + int i = 0; + for (SqlNode sqlNode : partitions) { + sqlNode.unparse(writer, leftPrec, rightPrec); + i++; + if (i < partitions.size()) { + writer.sep(","); + } + } + writer.endList(partFrame); + + writer.endList(frame); + } + + public List getPartitions() { + return partitions; + } + + public SqlNode getParent() { + return parent; + } + + public void setParent(SqlNode parent) { + this.parent = parent; + } + + @Override + public void validate(SqlValidator validator, SqlValidatorScope scope) { + validator.setColumnReferenceExpansion(false); + if (GeneralUtil.isNotEmpty(partitions)) { + List partDefs = new ArrayList<>(); + partDefs.addAll(partitions); + int partColCnt = -1; + SqlPartitionBy.validatePartitionDefs(validator, scope, partDefs, partColCnt, -1, true, false); + } + } + + public boolean isSubPartition() { + return isSubPartition; + } + + public void setSubPartition(boolean subPartition) { + isSubPartition = subPartition; + } +} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableRemoveTtlOptions.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableRemoveTtlOptions.java new file mode 100644 index 000000000..b6d1c550c --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlAlterTableRemoveTtlOptions.java @@ -0,0 +1,36 @@ +package org.apache.calcite.sql; + +import org.apache.calcite.sql.parser.SqlParserPos; + +import java.util.ArrayList; +import java.util.List; + +/**. + * + * @author chenghui.lch + */ +public class SqlAlterTableRemoveTtlOptions extends SqlAlterSpecification { + + private static final SqlOperator OPERATOR = new SqlSpecialOperator("REMOVE TTL", SqlKind.REMOVE_TTL); + + public SqlAlterTableRemoveTtlOptions(SqlParserPos pos) { + super(pos); + } + + @Override + public SqlOperator getOperator() { + return OPERATOR; + } + + @Override + public List getOperandList() { + List opList = new ArrayList<>(); + return opList; + } + + @Override + public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { + final SqlWriter.Frame frame = writer.startList(SqlWriter.FrameTypeEnum.SELECT, "REMOVE TTL", ""); + writer.endList(frame); + } +} \ No newline at end of file diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlBaseline.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlBaseline.java index c5101b936..f9a034837 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlBaseline.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlBaseline.java @@ -38,20 +38,17 @@ public class SqlBaseline extends SqlDal { private String operation; private List baselineIds = new ArrayList<>(); - private SqlSelect select; - private SqlNode statement; + private SqlNode select; private String sql; private String parameterizedSql; private String hint; - public SqlBaseline(SqlParserPos pos, String operation, List baselineIds, SqlSelect select, - SqlNode statement) { + public SqlBaseline(SqlParserPos pos, String operation, List baselineIds, SqlNode select) { super(pos); this.operands = new ArrayList<>(0); this.operation = operation; this.baselineIds.addAll(baselineIds); this.select = select; - this.statement = statement; this.operator = new SqlBaselineOperator(operation); } @@ -72,14 +69,6 @@ public void setBaselineIds(List baselineIds) { this.baselineIds.addAll(baselineIds); } - public SqlSelect getSelect() { - return select; - } - - public void setSelect(SqlSelect select) { - this.select = select; - } - public String getHint() { return hint; } diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCheckColumnarIndex.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCheckColumnarIndex.java index b6c8273d2..af437c877 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCheckColumnarIndex.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCheckColumnarIndex.java @@ -39,12 +39,16 @@ public class SqlCheckColumnarIndex extends SqlDdl { // Use DDL here to utilize a private SqlIdentifier tableName; private String extraCmd; - public SqlCheckColumnarIndex(SqlParserPos pos, SqlIdentifier indexName, SqlIdentifier tableName, String extraCmd) { + private List extras; + + public SqlCheckColumnarIndex(SqlParserPos pos, SqlIdentifier indexName, SqlIdentifier tableName, String extraCmd, + List extras) { super(OPERATOR, pos); this.name = indexName; this.indexName = indexName; this.tableName = tableName; this.extraCmd = extraCmd; + this.extras = extras; } public SqlIdentifier getIndexName() { @@ -136,19 +140,23 @@ public RelDataType deriveType(SqlValidator validator, SqlValidatorScope scope, S @Override public SqlNode clone(SqlParserPos pos) { - return new SqlCheckColumnarIndex(this.pos, indexName, tableName, extraCmd); + return new SqlCheckColumnarIndex(this.pos, indexName, tableName, extraCmd, extras); } public SqlCheckColumnarIndex replaceIndexName(SqlIdentifier newIndexName) { - return new SqlCheckColumnarIndex(pos, newIndexName, tableName, extraCmd); + return new SqlCheckColumnarIndex(pos, newIndexName, tableName, extraCmd, extras); } public boolean withTableName() { return null != tableName; } + public List getExtras() { + return extras; + } + public enum CheckCciExtraCmd { - UNKNOWN, DEFAULT, CHECK, LOCK, CLEAR, SHOW, META; + UNKNOWN, DEFAULT, CHECK, LOCK, CLEAR, SHOW, META, INCREMENT, SNAPSHOT; private static final Map VALUE_MAP = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); static { @@ -157,6 +165,8 @@ public enum CheckCciExtraCmd { VALUE_MAP.put("CLEAR", CLEAR); VALUE_MAP.put("SHOW", SHOW); VALUE_MAP.put("META", META); + VALUE_MAP.put("INCREMENT", INCREMENT); + VALUE_MAP.put("SNAPSHOT", SNAPSHOT); } public static CheckCciExtraCmd of(String stringVal) { diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCheckColumnarSnapshot.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCheckColumnarSnapshot.java new file mode 100644 index 000000000..0eba7ca0f --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCheckColumnarSnapshot.java @@ -0,0 +1,79 @@ +package org.apache.calcite.sql; + +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rel.type.RelDataTypeFieldImpl; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.calcite.sql.validate.SqlValidator; +import org.apache.calcite.sql.validate.SqlValidatorScope; + +import java.util.ArrayList; +import java.util.List; + +public class SqlCheckColumnarSnapshot extends SqlDal { + + private static final SqlSpecialOperator OPERATOR = new SqlCheckColumnarSnapshotOperator(); + + private SqlNode tableName; + + public SqlCheckColumnarSnapshot(SqlParserPos pos, SqlNode tableName) { + super(pos); + this.tableName = tableName; + } + + public SqlNode getTableName() { + return tableName; + } + + public void setTableNames(SqlNode tableName) { + this.tableName = tableName; + } + + @Override + public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { + final SqlWriter.Frame selectFrame = writer.startList(SqlWriter.FrameTypeEnum.SELECT); + writer.sep("CHECK COLUMNAR SNAPSHOT"); + tableName.unparse(writer, leftPrec, rightPrec); + writer.endList(selectFrame); + } + + @Override + public SqlOperator getOperator() { + return OPERATOR; + } + + @Override + public SqlKind getKind() { + return SqlKind.CHECK_COLUMNAR_SNAPSHOT; + } + + @Override + public void validate(SqlValidator validator, SqlValidatorScope scope) { + } + + public static class SqlCheckColumnarSnapshotOperator extends SqlSpecialOperator { + + public SqlCheckColumnarSnapshotOperator() { + super("CHECK_COLUMNAR_SNAPSHOT", SqlKind.CHECK_COLUMNAR_SNAPSHOT); + } + + @Override + public RelDataType deriveType(SqlValidator validator, SqlValidatorScope scope, SqlCall call) { + final RelDataTypeFactory typeFactory = validator.getTypeFactory(); + List columns = new ArrayList<>(); + columns.add( + new RelDataTypeFieldImpl("Columnar_Index_Name", 0, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + columns.add(new RelDataTypeFieldImpl("Partition_Name", 1, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + columns.add(new RelDataTypeFieldImpl("Result", 2, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + columns.add(new RelDataTypeFieldImpl("Diff", 3, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + columns.add(new RelDataTypeFieldImpl("Advice", 4, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + return typeFactory.createStructType(columns); + } + } + + @Override + public SqlNode clone(SqlParserPos pos) { + return new SqlCheckColumnarSnapshot(this.pos, tableName); + } +} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCreateIndex.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCreateIndex.java index e9fbb4dd4..d984ab226 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCreateIndex.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCreateIndex.java @@ -17,6 +17,7 @@ package org.apache.calcite.sql; import com.alibaba.polardbx.common.ColumnarTableOptions; +import com.alibaba.polardbx.common.ColumnarOptions; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.druid.sql.ast.SQLExpr; @@ -35,10 +36,8 @@ import org.apache.calcite.sql.pretty.SqlPrettyWriter; import org.apache.calcite.sql.util.SqlString; import org.apache.calcite.util.ImmutableNullableList; -import org.apache.commons.collections.CollectionUtils; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -90,6 +89,7 @@ public class SqlCreateIndex extends SqlCreate { private SqlCreateTable primaryTableNode; private final boolean withImplicitTableGroup; private boolean visible = true; + private final Map columnarOptions; private SqlCreateIndex(SqlParserPos pos, SqlIdentifier indexName, @@ -117,7 +117,8 @@ private SqlCreateIndex(SqlParserPos pos, boolean withImplicitTableGroup, SqlNode engineName, List dictColumns, - boolean visible) { + boolean visible, + Map columnarOptions) { super(OPERATOR, pos, false, false); this.indexName = indexName; this.originIndexName = originIndexName; @@ -146,6 +147,7 @@ private SqlCreateIndex(SqlParserPos pos, this.engineName = engineName; this.dictColumns = dictColumns; this.visible = visible; + this.columnarOptions = columnarOptions; } public SqlCreateIndex(SqlParserPos pos, @@ -179,7 +181,8 @@ public SqlCreateIndex(SqlParserPos pos, boolean withImplicitTableGroup, SqlNode engineName, List dictColumns, - boolean visible) { + boolean visible, + Map columnarOptions) { super(OPERATOR, pos, replace, ifNotExists); this.name = name; this.originTableName = originTableName; @@ -210,6 +213,7 @@ public SqlCreateIndex(SqlParserPos pos, this.engineName = engineName; this.dictColumns = dictColumns; this.visible = visible; + this.columnarOptions = columnarOptions; } public static SqlCreateIndex createLocalIndex(SqlIdentifier indexName, SqlIdentifier tableName, @@ -246,7 +250,8 @@ public static SqlCreateIndex createLocalIndex(SqlIdentifier indexName, SqlIdenti withImplicitTableGroup, null, null, - true); + true, + null); } public static SqlCreateIndex createGlobalIndex(SqlParserPos pos, SqlIdentifier indexName, SqlIdentifier table, @@ -284,7 +289,8 @@ public static SqlCreateIndex createGlobalIndex(SqlParserPos pos, SqlIdentifier i withImplicitTableGroup, null, null, - visible); + visible, + null); } public static SqlCreateIndex createClusteredIndex(SqlParserPos pos, SqlIdentifier indexName, SqlIdentifier table, @@ -323,7 +329,8 @@ public static SqlCreateIndex createClusteredIndex(SqlParserPos pos, SqlIdentifie withImplicitTableGroup, null, null, - visible); + visible, + null); } public static SqlCreateIndex createColumnarIndex(SqlParserPos pos, SqlIdentifier indexName, SqlIdentifier table, @@ -339,7 +346,8 @@ public static SqlCreateIndex createColumnarIndex(SqlParserPos pos, SqlIdentifier boolean withImplicitTableGroup, SqlNode engineName, List dictKeys, - boolean visible) { + boolean visible, + Map columnarOptions) { return new SqlCreateIndex(pos, indexName, indexName, @@ -366,7 +374,8 @@ public static SqlCreateIndex createColumnarIndex(SqlParserPos pos, SqlIdentifier withImplicitTableGroup, engineName, dictKeys, - visible); + visible, + columnarOptions); } public SqlNode getEngineName() { @@ -744,7 +753,8 @@ public SqlNode clone(SqlParserPos pos) { withImplicitTableGroup, engineName, dictColumns, - visible); + visible, + columnarOptions); } public SqlCreateIndex rebuildCovering(Collection coveringColumns) { @@ -787,7 +797,8 @@ public SqlCreateIndex rebuildCovering(Collection coveringColumns) { withImplicitTableGroup, engineName, dictColumns, - this.visible); + this.visible, + columnarOptions); } /** @@ -824,7 +835,8 @@ public SqlCreateIndex rebuildToGsi(SqlIdentifier newName, SqlNode dbPartition) { withImplicitTableGroup, engineName, dictColumns, - this.visible); + this.visible, + columnarOptions); } /** @@ -861,7 +873,8 @@ public SqlCreateIndex rebuildToGsiNewPartition(SqlIdentifier newName, SqlNode ne withImplicitTableGroup, engineName, dictColumns, - this.visible); + this.visible, + columnarOptions); } public SqlCreateIndex rebuildToExplicitLocal(SqlIdentifier newName, String sql) { @@ -891,7 +904,8 @@ public SqlCreateIndex rebuildToExplicitLocal(SqlIdentifier newName, String sql) withImplicitTableGroup, engineName, dictColumns, - this.visible); + this.visible, + columnarOptions); } public SqlCreateIndex replaceTableName(SqlIdentifier newTableName) { @@ -921,7 +935,8 @@ public SqlCreateIndex replaceTableName(SqlIdentifier newTableName) { withImplicitTableGroup, engineName, dictColumns, - this.visible); + this.visible, + columnarOptions); } public SqlCreateIndex replaceIndexName(SqlIdentifier newIndexName) { @@ -951,20 +966,24 @@ public SqlCreateIndex replaceIndexName(SqlIdentifier newIndexName) { withImplicitTableGroup, engineName, dictColumns, - this.visible); + this.visible, + columnarOptions); } /** * columnar index options */ public Map getColumnarOptions() { - Map options = new HashMap<>(); - if (CollectionUtils.isNotEmpty(dictColumns)) { - String columns = dictColumns.stream() - .map(sqlIndexColumnName -> SqlIdentifier.surroundWithBacktick(sqlIndexColumnName.getColumnNameStr())) - .collect(Collectors.joining(",")); - options.put(ColumnarTableOptions.DICTIONARY_COLUMNS, columns); + Map options = columnarOptions; + // Normalize dict columns. + String dictColumnStr = options.get(ColumnarOptions.DICTIONARY_COLUMNS); + if (null != dictColumnStr) { + dictColumnStr = SQLUtils.splitNamesByComma(dictColumnStr.toLowerCase()).stream() + .map(SqlIdentifier::surroundWithBacktick) + .collect(Collectors.joining(",")); + options.put(ColumnarOptions.DICTIONARY_COLUMNS, dictColumnStr); } + return options; } diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCreateTable.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCreateTable.java index ca20cf251..f6d1f9e19 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCreateTable.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlCreateTable.java @@ -35,13 +35,13 @@ import com.alibaba.polardbx.druid.sql.ast.SQLOrderingSpecification; import com.alibaba.polardbx.druid.sql.ast.SQLPartitionByRange; import com.alibaba.polardbx.druid.sql.ast.SQLStatement; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.polardbx.druid.sql.ast.statement.SQLAssignItem; -import com.alibaba.polardbx.druid.sql.ast.statement.SQLCharacterDataType; import com.alibaba.polardbx.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.polardbx.druid.sql.ast.statement.SQLColumnPrimaryKey; import com.alibaba.polardbx.druid.sql.ast.statement.SQLColumnUniqueKey; @@ -63,6 +63,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +import lombok.Data; import org.apache.calcite.linq4j.Enumerator; import org.apache.calcite.linq4j.Linq4j; import org.apache.calcite.linq4j.QueryProvider; @@ -106,6 +107,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TreeMap; @@ -115,7 +117,6 @@ import static com.alibaba.polardbx.common.TddlConstants.IMPLICIT_COL_NAME; import static com.alibaba.polardbx.common.TddlConstants.IMPLICIT_KEY_NAME; -import static com.alibaba.polardbx.common.TddlConstants.UGSI_PK_INDEX_NAME; import static com.alibaba.polardbx.common.exception.code.ErrorCode.ERR_CREATE_SELECT_WITH_OSS; /** @@ -164,6 +165,17 @@ public class SqlCreateTable extends SqlCreate { private List> fullTextKeys; private List> spatialKeys; private List> foreignKeys; + + public List getLocalIndexes() { + return localIndexes; + } + + public void setLocalIndexes( + List localIndexes) { + this.localIndexes = localIndexes; + } + + private List localIndexes; private List checks; private List logicalReferencedTables = null; @@ -200,6 +212,12 @@ public class SqlCreateTable extends SqlCreate { private SqlNode sqlPartition = null; private SqlNode localPartition = null; + // for row-level ttl definition + private String ttlEnable = null; + private SqlNode ttlExpr = null; + private SqlNode ttlJob = null; + private SqlNode ttlDefinition = null; + private SqlNode tableGroupName = null; private boolean withImplicitTableGroup = false; private SqlNode joinGroupName = null; @@ -208,6 +226,9 @@ public class SqlCreateTable extends SqlCreate { private Engine engine = null; private ArchiveMode archiveMode; + /** + * the target table + */ private String loadTableName = null; private String loadTableSchema = null; @@ -225,6 +246,11 @@ public class SqlCreateTable extends SqlCreate { boolean replaceInto = false; protected boolean onlyConvertTableMode = false; + @Data + public static class PrepareSqlStringOptions { + protected boolean ttlDefinitionAllowed = false; + } + public void setIgnore(boolean ignore) { this.ignore = ignore; } @@ -443,7 +469,8 @@ public SqlCreateTable(SqlParserPos pos, boolean replace, boolean ifNotExists, Sq boolean pushDownForeignKeys, boolean replaceInto, String rowFormat, - boolean uniqueShardingKey) { + boolean uniqueShardingKey, + SqlNode ttlDefinition) { super(OPERATOR, pos, replace, ifNotExists); this.name = name; this.likeTableName = likeTableName; @@ -503,6 +530,8 @@ public SqlCreateTable(SqlParserPos pos, boolean replace, boolean ifNotExists, Sq this.replaceInto = replaceInto; this.rowFormat = rowFormat; this.uniqueShardingKey = uniqueShardingKey; + this.ttlDefinition = ttlDefinition; + } public boolean shouldLoad() { @@ -825,6 +854,38 @@ public void setDBPartition(boolean newPartitionDb) { DbPartition = newPartitionDb; } + public String getTtlEnable() { + return ttlEnable; + } + + public void setTtlEnable(String ttlEnable) { + this.ttlEnable = ttlEnable; + } + + public SqlNode getTtlExpr() { + return ttlExpr; + } + + public void setTtlExpr(SqlNode ttlExpr) { + this.ttlExpr = ttlExpr; + } + + public SqlNode getTtlJob() { + return ttlJob; + } + + public void setTtlJob(SqlNode ttlJob) { + this.ttlJob = ttlJob; + } + + public SqlNode getTtlDefinition() { + return ttlDefinition; + } + + public void setTtlDefinition(SqlNode ttlDefinition) { + this.ttlDefinition = ttlDefinition; + } + /** * Column definition. */ @@ -1077,7 +1138,8 @@ public SqlCreateTable clone(SqlParserPos pos) { pushDownForeignKeys, replaceInto, rowFormat, - uniqueShardingKey); + uniqueShardingKey, + ttlDefinition); ret.setWithImplicitTableGroup(withImplicitTableGroup); return ret; } @@ -1238,6 +1300,7 @@ private void addLocalIndexesForShardKeys(MySqlCreateTableStatement stmt, Set partKeyList = shardKeys.stream().collect(Collectors.toList()); List subPartKeyList = subPartKeys.stream().collect(Collectors.toList()); @@ -1256,18 +1319,18 @@ private void addLocalIndexesForShardKeys(MySqlCreateTableStatement stmt, Setof(), false, partStrategy, partKeyList, false, ""); } } } - if (useSubPartBy) { + if (useSubPartBy && !isCreateTtlTmpTbl) { // addCompositeIndex(subPartKeys, stmt); SqlCreateTable.addCompositeIndexForAutoTbl(null, stmt, false, ImmutableList.of(), false, subpartStrategy, subPartKeyList, false, ""); - if (usePartBy && addPartColIndexLater) { + if (usePartBy && addPartColIndexLater && !isCreateTtlTmpTbl) { SqlCreateTable.addCompositeIndexForAutoTbl(null, stmt, false, ImmutableList.of(), false, partStrategy, partKeyList, false, ""); } @@ -1283,6 +1346,30 @@ public void addLocalPartitionSuffix(MySqlCreateTableStatement stmt) { Lists.newArrayList(new SQLCommentHint("!50500 PARTITION BY " + localPartitionSuffix.toString()))); } + protected boolean isCreateTtlTmpTable(MySqlCreateTableStatement stmt) { + boolean isCreateTtlTmpTbl = false; + List options = stmt.getTableOptions(); + for (int i = 0; i < options.size(); i++) { + SQLAssignItem option = options.get(i); + SQLExpr key = option.getTarget(); + SQLExpr val = option.getValue(); + if (key instanceof SQLIdentifierExpr) { + SQLIdentifierExpr keyId = (SQLIdentifierExpr) key; + String keyIdStr = SQLUtils.normalize(keyId.getName()); + if (keyIdStr.equalsIgnoreCase("TTL_TEMPORARY")) { + if (val instanceof SQLCharExpr) { + SQLCharExpr valStrExpr = (SQLCharExpr) val; + String valStrExprVal = SQLUtils.normalizeNoTrim(valStrExpr.getText()); + if (valStrExprVal != null && valStrExprVal.equalsIgnoreCase("Y")) { + isCreateTtlTmpTbl = true; + } + } + } + } + } + return isCreateTtlTmpTbl; + } + private static void removePolarDBXExclusiveFeature(MySqlCreateTableStatement stmt) { final Iterator iterator = stmt.getTableElementList().iterator(); while (iterator.hasNext()) { @@ -1323,17 +1410,17 @@ private static void removeLBACAttr(final MySqlCreateTableStatement stmt) { } } Iterator optionIterator = stmt.getTableOptions().iterator(); - while (optionIterator.hasNext()){ + while (optionIterator.hasNext()) { SQLAssignItem item = optionIterator.next(); //去除表的安全策略 if (item.getTarget() instanceof SQLIdentifierExpr && - "SECURITY POLICY".equalsIgnoreCase(((SQLIdentifierExpr) item.getTarget()).getName())){ + "SECURITY POLICY".equalsIgnoreCase(((SQLIdentifierExpr) item.getTarget()).getName())) { optionIterator.remove(); } } } - private String prepare() { + private String prepare(PrepareSqlStringOptions options) { List statementList = SQLUtils.parseStatementsWithDefaultFeatures(sourceSql, JdbcConstants.MYSQL); MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0); Set shardKeys = new HashSet<>(); @@ -1363,6 +1450,37 @@ private String prepare() { stmt.setPartitioning(null); } + // local partition + if (localPartition == null) { + stmt.setLocalPartitioning(null); + } + + // remove all ttl options for physql template + List tableOptions = stmt.getTableOptions(); + List tableNewOptions = new ArrayList<>(); + if (tableOptions != null) { + for (int i = 0; i < tableOptions.size(); i++) { + SQLAssignItem item = tableOptions.get(i); + SQLExpr key = item.getTarget(); + if (key instanceof SQLIdentifierExpr) { + SQLIdentifierExpr id = (SQLIdentifierExpr) key; + String keyVal = id.getName(); + if (keyVal.equalsIgnoreCase("TTL_ENABLE") + || keyVal.equalsIgnoreCase("TTL_LEVEL") + || keyVal.equalsIgnoreCase("TTL_EXPR") + || keyVal.equalsIgnoreCase("TTL_JOB") + || keyVal.equalsIgnoreCase("TTL")) { + if (options == null || !options.isTtlDefinitionAllowed()) { + continue; + } + } + } + tableNewOptions.add(item); + } + tableOptions.clear(); + tableOptions.addAll(tableNewOptions); + } + if (localPartitionSuffix != null) { addLocalPartitionSuffix(stmt); } @@ -1469,6 +1587,9 @@ public static void addForeignKeyIndex(Set shardKeys, MySqlCreateTableSta } + /** + * 注:mysql8.0 函数索引会返回null,需注意返回值 + */ public static String getIndexColumnName(final SQLSelectOrderByItem indexColumnDef) { final SQLExpr expr = indexColumnDef.getExpr(); @@ -1527,18 +1648,22 @@ public static void addIndex(Map indexColumnDefMap, M final String k = SQLUtils.normalizeNoTrim(((SQLIdentifierExpr) expr).getSimpleName()); // Do not add local index for foreign key column - unindexedColumns.remove(k); + if (k != null) { + unindexedColumns.remove(k); + } } } else if (sqlTableElement instanceof MySqlTableIndex && !((MySqlTableIndex) sqlTableElement).isGlobal()) { final String k = getIndexColumnName(((MySqlTableIndex) sqlTableElement).getColumns().get(0)); // Do not add local index for first column of existing local index - unindexedColumns.remove(k); + if (k != null) { + unindexedColumns.remove(k); + } // Store existing index name Optional.ofNullable(((MySqlTableIndex) sqlTableElement).getName()) .map(in -> SQLUtils.normalizeNoTrim(in.getSimpleName())).ifPresent(existingIndexNames::add); - if (gsi && indexColumns.contains(k) && needAddIndexColumns) { // Filter preliminarily + if (gsi && k != null && indexColumns.contains(k) && needAddIndexColumns) { // Filter preliminarily final Set elementColumns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); for (SQLSelectOrderByItem column : ((MySqlTableIndex) sqlTableElement).getColumns()) { final String one = getIndexColumnName(column); @@ -1546,10 +1671,7 @@ public static void addIndex(Map indexColumnDefMap, M } if (indexColumns.equals(elementColumns)) { if (isUniqueIndex) { - if (!((MySqlTableIndex) sqlTableElement).getName().getSimpleName() - .equalsIgnoreCase(UGSI_PK_INDEX_NAME)) { - it.remove(); // Need to be replaced with MySqlUnique - } + it.remove(); // Need to be replaced with MySqlUnique } else { needAddIndexColumns = false; ((MySqlTableIndex) sqlTableElement).setIndexType(indexType); @@ -1561,13 +1683,15 @@ public static void addIndex(Map indexColumnDefMap, M final String k = getIndexColumnName(((MySqlKey) sqlTableElement).getColumns().get(0)); // Do not add local index for first column of existing local index - unindexedColumns.remove(k); + if (k != null) { + unindexedColumns.remove(k); + } // Store existing index name Optional.ofNullable(((MySqlKey) sqlTableElement).getName()) .map(in -> SQLUtils.normalizeNoTrim(in.getSimpleName())).ifPresent(existingIndexNames::add); - if (gsi && indexColumns.contains(k) && needAddIndexColumns) { // Filter preliminarily + if (gsi && k != null && indexColumns.contains(k) && needAddIndexColumns) { // Filter preliminarily final Set elementColumns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); for (SQLSelectOrderByItem column : ((MySqlKey) sqlTableElement).getColumns()) { final String one = getIndexColumnName(column); @@ -1576,11 +1700,7 @@ public static void addIndex(Map indexColumnDefMap, M if (indexColumns.equals(elementColumns)) { if (isUniqueIndex && !(sqlTableElement instanceof MySqlUnique) && !(sqlTableElement instanceof MySqlPrimaryKey)) { - // never remove implicit pk info - if (!((MySqlKey) sqlTableElement).getName().getSimpleName() - .equalsIgnoreCase(UGSI_PK_INDEX_NAME)) { - it.remove(); // Need to be replaced with MySqlUnique - } + it.remove(); // Need to be replaced with MySqlUnique } else if (sqlTableElement instanceof MySqlPrimaryKey) { needAddIndexColumns = false; } else { @@ -2063,6 +2183,14 @@ public static Set getPartitionKeys(SqlNode partitionBy, return allPartColNameSet; } + public String toSqlStringForCdc(PrepareSqlStringOptions options) { + return prepare(options); + } + + protected String prepare() { + return prepare(null); + } + @Override public String toString() { return prepare(); @@ -2505,6 +2633,7 @@ public static void addCompositeIndex(Map indexColumn boolean autoShardIndexAlreadyExists = false; boolean needAddIndexColumns = isGsi; final Iterator it = stmt.getTableElementList().iterator(); + while (it.hasNext()) { final SQLTableElement sqlTableElement = it.next(); if (sqlTableElement instanceof SQLColumnDefinition) { @@ -2538,10 +2667,12 @@ public static void addCompositeIndex(Map indexColumn shardingColumnDefMap.put(columnName, columnDef); } - } else if (sqlTableElement instanceof MySqlTableIndex && !((MySqlTableIndex) sqlTableElement).isGlobal()) { - if (((MySqlTableIndex) sqlTableElement).getColumns().size() > 0) { + } else if (sqlTableElement instanceof MySqlTableIndex) { + if (!((MySqlTableIndex) sqlTableElement).isGlobal() + && ((MySqlTableIndex) sqlTableElement).getColumns().size() > 0) { List indexingColumnsName = ((MySqlTableIndex) sqlTableElement).getColumns() - .stream().map(SqlCreateTable::getIndexColumnName).collect(Collectors.toList()); + .stream().map(SqlCreateTable::getIndexColumnName).filter(Objects::nonNull) + .collect(Collectors.toList()); if (listContainsIgnoreCase(indexingColumnsName, shardingKey)) { autoShardIndexAlreadyExists = true; @@ -2553,18 +2684,19 @@ public static void addCompositeIndex(Map indexColumn if (indexColumns.equals(elementColumns)) { if (isUniqueIndex) { - if (!((MySqlTableIndex) sqlTableElement).getName().getSimpleName() - .equalsIgnoreCase(UGSI_PK_INDEX_NAME)) { - it.remove(); // Need to be replaced with MySqlUnique - } + it.remove(); // Need to be replaced with MySqlUnique } else { needAddIndexColumns = false; } } } } - } else if (sqlTableElement instanceof MySqlKey && !(sqlTableElement instanceof MySqlUnique - && ((MySqlUnique) sqlTableElement).isGlobal())) { + final MySqlTableIndex tableIndex = (MySqlTableIndex) sqlTableElement; + if (tableIndex.getName() != null) { + final String indexName = ((SQLIdentifierExpr) tableIndex.getName()).normalizedName(); + existingIndexNames.add(indexName); + } + } else if (sqlTableElement instanceof MySqlKey) { // if (((MySqlKey) sqlTableElement).getColumns().size() > 1) { // existIndexList.add(sqlTableElement); @@ -2588,9 +2720,12 @@ public static void addCompositeIndex(Map indexColumn // // } - if (((MySqlKey) sqlTableElement).getColumns().size() > 0) { + if (!(sqlTableElement instanceof MySqlUnique + && ((MySqlUnique) sqlTableElement).isGlobal()) + && ((MySqlKey) sqlTableElement).getColumns().size() > 0) { List indexingColumnsName = ((MySqlKey) sqlTableElement).getColumns() - .stream().map(SqlCreateTable::getIndexColumnName).collect(Collectors.toList()); + .stream().map(SqlCreateTable::getIndexColumnName).filter(Objects::nonNull) + .collect(Collectors.toList()); if (listContainsIgnoreCase(indexingColumnsName, shardingKey)) { autoShardIndexAlreadyExists = true; @@ -2603,11 +2738,7 @@ public static void addCompositeIndex(Map indexColumn if (indexColumns.equals(elementColumns)) { if (isUniqueIndex && !(sqlTableElement instanceof MySqlUnique) && !(sqlTableElement instanceof MySqlPrimaryKey)) { - // never remove implicit pk info - if (!((MySqlKey) sqlTableElement).getName().getSimpleName() - .equalsIgnoreCase(UGSI_PK_INDEX_NAME)) { - it.remove(); // Need to be replaced with MySqlUnique - } + it.remove(); // Need to be replaced with MySqlUnique } else if (sqlTableElement instanceof MySqlPrimaryKey) { needAddIndexColumns = false; } else { @@ -2617,6 +2748,11 @@ public static void addCompositeIndex(Map indexColumn } } } + final MySqlKey tableIndex = (MySqlKey) sqlTableElement; + if (tableIndex.getName() != null) { + final String indexName = ((SQLIdentifierExpr) tableIndex.getName()).normalizedName(); + existingIndexNames.add(indexName); + } } else if (sqlTableElement instanceof MysqlForeignKey) { // Store existing index name Optional.ofNullable(((MysqlForeignKey) sqlTableElement).getName()) @@ -2690,7 +2826,8 @@ public static void addCompositeIndex(Map indexColumn buildUnifiedIndexColumnDef(orderedIndexColumnNames, indexColumnDefMap, columnDefMap); List indexingColumnsName = - indexColumnList.stream().map(SqlCreateTable::getIndexColumnName).collect(Collectors.toList()); + indexColumnList.stream().map(SqlCreateTable::getIndexColumnName).filter(Objects::nonNull) + .collect(Collectors.toList()); if (listContainsIgnoreCase(indexingColumnsName, shardingKey)) { autoShardIndexAlreadyExists = true; @@ -2714,7 +2851,8 @@ public static void addCompositeIndex(Map indexColumn buildUnifiedIndexColumnDef(indexColumnDefMap.keySet(), indexColumnDefMap, columnDefMap); List indexingColumnsName = - indexColumnList.stream().map(SqlCreateTable::getIndexColumnName).collect(Collectors.toList()); + indexColumnList.stream().map(SqlCreateTable::getIndexColumnName).filter(Objects::nonNull) + .collect(Collectors.toList()); if (listContainsIgnoreCase(indexingColumnsName, shardingKey)) { autoShardIndexAlreadyExists = true; @@ -2736,7 +2874,7 @@ public static void addCompositeIndex(Map indexColumn // if (!indexAlreadExists) { if (!autoShardIndexAlreadyExists || addFkIndex) { List indexColumnInfos = - preparAutoCompositeIndexs(shardingKey, columnDefMap, 191); + prepareAutoCompositeIndexes(shardingKey, columnDefMap, 191); Set orderedIndexColumnNames = new LinkedHashSet<>(shardingKey); final String suffix = buildUnifyIndexName(orderedIndexColumnNames, 45); @@ -2767,15 +2905,15 @@ public static void addCompositeIndex(Map indexColumn } public static String buildForeignKeyName(String foreignKeyIndexName, Set existingIndexNames, - String suffix) { + String suffix) { return foreignKeyIndexName == null ? buildForeignKeyIndexName(existingIndexNames, suffix) : SqlIdentifier.surroundWithBacktick(foreignKeyIndexName); } - private static List preparAutoCompositeIndexs(List shardKeys, - Map columnDefMap, - int maxLen) { + private static List prepareAutoCompositeIndexes(List shardKeys, + Map columnDefMap, + int maxLen) { int totalIndexLen = 0; int totalCharTypeIndexLen = 0; int charTypeCount = 0; @@ -2945,6 +3083,7 @@ public int getColTypeLen() { public boolean isCharType() { return isCharType; } + } // End SqlCreateTable.java diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlDataTypeSpec.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlDataTypeSpec.java index dd258330f..a31c9d95a 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlDataTypeSpec.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlDataTypeSpec.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.charset.CharsetName; import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.rpc.result.XResultUtil; import com.google.common.base.Preconditions; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeFactory; @@ -437,10 +438,15 @@ public void unparse( writer.endList(frame); } } else if (sqlTypeName.allowsPrec() && (precision >= 0)) { + // 15 is the default precision, + // see org.apache.calcite.rel.type.RelDataTypeSystemImpl.getDefaultPrecision for more details. + if (SqlTypeName.APPROX_TYPES.contains(sqlTypeName) && precision == 15) { + return; + } final SqlWriter.Frame frame = writer.startList(SqlWriter.FrameTypeEnum.FUN_CALL, "(", ")"); writer.print(precision); - if (sqlTypeName.allowsScale() && (scale >= 0)) { + if (sqlTypeName.allowsScale() && (scale >= 0) && scale < XResultUtil.DECIMAL_NOT_SPECIFIED) { writer.sep(",", true); writer.print(scale); } diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlDelete.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlDelete.java index 6661ba006..32b9709fc 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlDelete.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlDelete.java @@ -402,6 +402,46 @@ public SqlNodeList getAliases() { return aliases; } + /** + * get force index from sqlDelete + * @return SqlIdentifier + */ + public SqlIdentifier getForceIndex() { + if (sourceSelect == null || sourceSelect.getFrom() == null || !(sourceSelect + .getFrom() instanceof SqlIdentifier)) { + return null; + } + + SqlNodeList indexNodes = (SqlNodeList) ((SqlIdentifier) sourceSelect.getFrom()).indexNode; + + if (indexNodes == null || indexNodes.size() == 0) { + return null; + } + + // get first force index hint + SqlIndexHint sqlIndexHint = null; + for (SqlNode node : indexNodes) { + if (node instanceof SqlIndexHint && ((SqlIndexHint) node).forceIndex()) { + sqlIndexHint = (SqlIndexHint) node; + break; + } + } + + if (sqlIndexHint == null) { + return null; + } + + SqlNodeList indexList = sqlIndexHint.getIndexList(); + + if (indexList != null && + indexList.size() > 0 && + indexList.get(0) instanceof SqlIdentifier) { + return (SqlIdentifier) indexList.get(0); + } + + return null; + } + public void setWithTableAlias(boolean withTableAlias) { this.withTableAlias = withTableAlias; } @@ -433,6 +473,7 @@ public boolean isWithTableAlias() { */ writer.keyword("FROM"); targetTable.unparse(writer, opLeft, opRight); + if (alias != null) { writer.keyword("AS"); alias.unparse(writer, opLeft, opRight); @@ -508,7 +549,6 @@ public boolean singleTable() { return false; } - public SqlNode getSourceTableNode() { if (fromUsing()) { return using; @@ -584,6 +624,12 @@ public SqlDelete initTableInfo(TableInfo srcInfo) { this.subQueryTableMap = subQueryTableMap; this.withTableAlias = withAlias.get(); + if (this.sourceTables.size() == 1 && this.getSourceSelect().getFrom() != null + && this.getSourceSelect().getFrom().getKind() == SqlKind.AS) { + // set this.withTableAlias = true when single table delete with force index + setWithTableAlias(true); + } + this.sourceTableCollected = true; return this; diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlFunction.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlFunction.java index acb328cf8..ab5767e88 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlFunction.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlFunction.java @@ -69,6 +69,7 @@ public String apply(Integer a0) { NON_PUSHDOWN_FUNCTION.add(NEXTVAL_FUNC_NAME); NON_PUSHDOWN_FUNCTION.add(CURRVAL_FUNC_NAME); NON_PUSHDOWN_FUNCTION.add("PART_ROUTE"); + NON_PUSHDOWN_FUNCTION.add("TIME_TO_TSO"); // Information Functions NON_PUSHDOWN_FUNCTION.add("CONNECTION_ID"); @@ -136,6 +137,11 @@ public String apply(Integer a0) { DYNAMIC_FUNCTION.add("USER"); DYNAMIC_FUNCTION.add("VERSION"); + DYNAMIC_FUNCTION.add("GET_LOCK"); + DYNAMIC_FUNCTION.add("IS_FREE_LOCK"); + DYNAMIC_FUNCTION.add("IS_USED_LOCK"); + DYNAMIC_FUNCTION.add("RELEASE_ALL_LOCKS"); + DYNAMIC_FUNCTION.add("RELEASE_LOCK"); } public static boolean isDynamic(SqlFunction func) { diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlIndexDefinition.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlIndexDefinition.java index 876bbb312..8bcfb343c 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlIndexDefinition.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlIndexDefinition.java @@ -75,6 +75,8 @@ public class SqlIndexDefinition extends SqlCall { private final SqlNode engineName; private final List dictColumns; private final boolean withImplicitTableGroup; + // Key should be lowercase. + private final Map columnarOptions; public SqlIndexDefinition(SqlParserPos pos, boolean hasConstraint, @@ -101,7 +103,8 @@ public SqlIndexDefinition(SqlParserPos pos, SqlNode engineName, List dictColumns, boolean withImplicitTableGroup, - boolean visible) { + boolean visible, + Map columnarOptions) { super(pos); this.hasConstraint = hasConstraint; this.uniqueConstraint = uniqueConstraint; @@ -128,6 +131,7 @@ public SqlIndexDefinition(SqlParserPos pos, this.dictColumns = dictColumns; this.withImplicitTableGroup = withImplicitTableGroup; this.visible = visible; + this.columnarOptions = columnarOptions; } public SqlIndexDefinition(SqlParserPos pos, @@ -157,7 +161,8 @@ public SqlIndexDefinition(SqlParserPos pos, SqlNode engineName, List dictColumns, boolean withImplicitTableGroup, - boolean visible) { + boolean visible, + Map columnarOptions) { super(pos); this.hasConstraint = hasConstraint; this.uniqueConstraint = uniqueConstraint; @@ -186,6 +191,7 @@ public SqlIndexDefinition(SqlParserPos pos, this.dictColumns = dictColumns; this.withImplicitTableGroup = withImplicitTableGroup; this.visible = visible; + this.columnarOptions = columnarOptions; } public static SqlIndexDefinition localIndex(SqlParserPos pos, boolean hasConstraint, @@ -217,7 +223,8 @@ public static SqlIndexDefinition localIndex(SqlParserPos pos, boolean hasConstra null, null, false, - true); + true, + null); } public static SqlIndexDefinition localIndex(SqlParserPos pos, boolean hasConstraint, @@ -250,7 +257,8 @@ public static SqlIndexDefinition localIndex(SqlParserPos pos, boolean hasConstra null, null, withImplicitTableGroup, - true); + true, + null); } public static SqlIndexDefinition globalIndex(SqlParserPos pos, boolean hasConstraint, @@ -286,7 +294,8 @@ public static SqlIndexDefinition globalIndex(SqlParserPos pos, boolean hasConstr null, null, withImplicitTablegroup, - visible); + visible, + null); } public static SqlIndexDefinition clusteredIndex(SqlParserPos pos, boolean hasConstraint, @@ -322,7 +331,8 @@ public static SqlIndexDefinition clusteredIndex(SqlParserPos pos, boolean hasCon null, null, withImplicitTablegroup, - visible); + visible, + null); } public static SqlIndexDefinition columnarIndex(SqlParserPos pos, boolean hasConstraint, @@ -334,7 +344,8 @@ public static SqlIndexDefinition columnarIndex(SqlParserPos pos, boolean hasCons List clusteredKeys, List options, SqlNode tableGroupName, SqlNode engineName, List dictColumns, - boolean withImplicitTablegroup, boolean visible) { + boolean withImplicitTablegroup, boolean visible, + Map columnarOptions) { return new SqlIndexDefinition(pos, hasConstraint, uniqueConstraint, @@ -360,7 +371,8 @@ public static SqlIndexDefinition columnarIndex(SqlParserPos pos, boolean hasCons engineName, dictColumns, withImplicitTablegroup, - visible); + visible, + columnarOptions); } @Override @@ -417,7 +429,6 @@ public void unparse(SqlWriter writer, int leftPrec, int rightPrec, boolean withO if (writer instanceof SqlPrettyWriter) { ((SqlPrettyWriter) writer).setQuoteAllIdentifiers(false); } - if (null != dbPartitionBy) { writer.keyword("DBPARTITION BY"); dbPartitionBy.unparse(writer, leftPrec, rightPrec); @@ -631,6 +642,10 @@ public SqlNode getOriginPartitioning() { return originPartitioning; } + public Map getColumnarOptions() { + return columnarOptions; + } + public SqlIndexDefinition replacePartitioning(SqlNode newPartition) { return new SqlIndexDefinition(pos, hasConstraint, @@ -659,7 +674,8 @@ public SqlIndexDefinition replacePartitioning(SqlNode newPartition) { engineName, dictColumns, withImplicitTableGroup, - visible); + visible, + columnarOptions); } public SqlIndexDefinition replaceCovering(Collection coveringColumns) { @@ -700,7 +716,8 @@ public SqlIndexDefinition replaceCovering(Collection coveringColumns) { engineName, dictColumns, withImplicitTableGroup, - this.visible); + this.visible, + columnarOptions); } public SqlIndexDefinition mergeCovering(Collection coveringColumns) { @@ -755,7 +772,8 @@ public SqlIndexDefinition mergeCovering(Collection coveringColumns) { engineName, dictColumns, withImplicitTableGroup, - visible); + visible, + columnarOptions); } } @@ -795,7 +813,8 @@ public SqlIndexDefinition rebuildToGsi(SqlIdentifier newName, SqlNode dbPartitio engineName, dictColumns, withImplicitTableGroup, - visible); + visible, + columnarOptions); } /** @@ -833,7 +852,8 @@ public SqlIndexDefinition rebuildToGsiNewPartition(SqlIdentifier newName, SqlNod engineName, dictColumns, withImplicitTableGroup, - visible); + visible, + columnarOptions); } public SqlIndexDefinition rebuildToExplicitLocal(SqlIdentifier newName) { @@ -864,7 +884,8 @@ public SqlIndexDefinition rebuildToExplicitLocal(SqlIdentifier newName) { engineName, dictColumns, withImplicitTableGroup, - visible); + visible, + columnarOptions); } public SqlNode getPartitioning() { diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlIndexHintOperator.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlIndexHintOperator.java index 87d8eb1c1..2b94317da 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlIndexHintOperator.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlIndexHintOperator.java @@ -23,6 +23,7 @@ import org.apache.calcite.util.Litmus; import java.util.List; +import java.util.Objects; /** * @@ -108,9 +109,22 @@ public void unparse( if (call.operandCount() > 2) { SqlWriter.Frame frameFunc = writer.startList(SqlWriter.FrameTypeEnum.FUN_CALL, "(", ")"); for (int i = 0; i < sqlNodeList.size(); i++) { - SqlCharStringLiteral sqlNode = (SqlCharStringLiteral)sqlNodeList.get(i); - String value2 = sqlNode.getNlsString().getValue(); - writer.sep(value2); + SqlNode node = sqlNodeList.get(i); + if (node instanceof SqlCharStringLiteral){ + SqlCharStringLiteral sqlNode = (SqlCharStringLiteral)node; + String value2 = sqlNode.getNlsString().getValue(); + writer.sep(value2); + } else if (node instanceof SqlIdentifier){ + SqlIdentifier sqlNode = (SqlIdentifier)node; + String value2 = sqlNode.getLastName(); + writer.sep(value2); + } else { + throw new IllegalArgumentException("not support sql hint:" + node); + } + if(Objects.equals(value0, "FORCE INDEX")){ + // force index only support one index + break; + } if (i != sqlNodeList.size() - 1) { writer.sep(","); } diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlKind.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlKind.java index 30362e943..cd5684838 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlKind.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlKind.java @@ -1022,6 +1022,20 @@ public enum SqlKind { */ SINGLE_VALUE, + /** + * The {@code JSON_OBJECTAGG} aggregate function. + */ + JSON_OBJECTAGG, + + JSON_OBJECT_GLOBALAGG, + + /** + * The {@code JSON_ARRAYAGG} aggregate function. + */ + JSON_ARRAYAGG, + + JSON_ARRAY_GLOBALAGG, + /** * The {code __FIRST_VALUE} internal aggregate function. */ @@ -1596,6 +1610,8 @@ public enum SqlKind { SHOW_DDL_JOBS, + SHOW_DDL_ENGINE, + SHOW_DDL_RESULTS, SHOW_SCHEDULE_RESULTS, @@ -1696,6 +1712,8 @@ public enum SqlKind { CHECK_COLUMNAR_PARTITION, + CHECK_COLUMNAR_SNAPSHOT, + CHECK_COLUMNAR_INDEX, // As a special DDL. CHECK_GLOBAL_INDEX, // As a special DDL. @@ -1750,6 +1768,8 @@ public enum SqlKind { TERMINATE_REBALANCE_JOB, + RESUME_REBALANCE_JOB, + SKIP_REBALANCE_SUBJOB, REMOVE_DDL_JOB, @@ -1831,6 +1851,11 @@ public enum SqlKind { */ EXCHANGE_PARTITION, + /** + * partition management: optimize partition. + */ + OPTIMIZE_PARTITION, + /** * partition management: alter table group split into partitions xxx by hot value(xxx[,..,xxx]) */ @@ -1841,6 +1866,10 @@ public enum SqlKind { */ MODIFY_SUBPARTITION, + MODIFY_TTL, + + REMOVE_TTL, + /** * partition management: create new tablegroup */ @@ -1932,6 +1961,11 @@ public enum SqlKind { */ REPARTITION_LOCAL_PARTITION, + /** + * expire local partition + */ + CLEANUP_EXPIRED_DATA, + LOCAL_PARTITION, CREATE_FUNCTION, @@ -2071,6 +2105,7 @@ public enum SqlKind { SHOW_DDL_STATUS, SHOW_REBALANCE_BACKFILL, SHOW_DDL_JOBS, + SHOW_DDL_ENGINE, SHOW_DDL_RESULTS, SHOW_SCHEDULE_RESULTS, SHOW_LOCALITY_INFO, @@ -2123,6 +2158,7 @@ public enum SqlKind { CHECK_GLOBAL_INDEX, CHECK_COLUMNAR_INDEX, CHECK_COLUMNAR_PARTITION, + CHECK_COLUMNAR_SNAPSHOT, ANALYZE_TABLE, OPTIMIZE_TABLE); @@ -2134,6 +2170,7 @@ public enum SqlKind { PAUSE_REBALANCE_JOB, ROLLBACK_DDL_JOB, TERMINATE_REBALANCE_JOB, + RESUME_REBALANCE_JOB, SKIP_REBALANCE_SUBJOB, REMOVE_DDL_JOB, INSPECT_DDL_JOB_CACHE, diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlOptimizeTable.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlOptimizeTable.java index ca2e54b57..8d70c3006 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlOptimizeTable.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlOptimizeTable.java @@ -16,7 +16,6 @@ package org.apache.calcite.sql; -import java.util.ArrayList; import java.util.LinkedList; import java.util.List; diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlOptimizeTableDdl.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlOptimizeTableDdl.java index 6af6ea901..c0345d266 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlOptimizeTableDdl.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlOptimizeTableDdl.java @@ -17,10 +17,12 @@ package org.apache.calcite.sql; import com.google.common.base.Joiner; +import groovy.sql.Sql; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.validate.SqlValidator; import org.apache.calcite.sql.validate.SqlValidatorScope; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -31,11 +33,11 @@ public class SqlOptimizeTableDdl extends SqlDdl { // Use DDL here to utilize asy private static final SqlSpecialOperator OPERATOR = new SqlOptimizeTable.SqlOptimizeTableOperator(); - private final List tableNames; - private final boolean noWriteToBinlog; - private final boolean local; + private List tableNames; + private final boolean noWriteToBinlog; + private final boolean local; - public SqlOptimizeTableDdl(SqlParserPos pos, List tableNames, boolean noWriteToBinlog, boolean local){ + public SqlOptimizeTableDdl(SqlParserPos pos, List tableNames, boolean noWriteToBinlog, boolean local) { super(OPERATOR, pos); this.name = tableNames.get(0); this.tableNames = tableNames; @@ -43,6 +45,14 @@ public SqlOptimizeTableDdl(SqlParserPos pos, List tableNames, boolean n this.local = local; } + @Override + public void setTargetTable(SqlNode sqlIdentifier) { + super.setTargetTable(sqlIdentifier); + List newTableNames = new ArrayList<>(); + newTableNames.add(name); + this.tableNames = newTableNames; + } + @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { final SqlWriter.Frame selectFrame = writer.startList(SqlWriter.FrameTypeEnum.SELECT); @@ -68,7 +78,7 @@ public SqlOperator getOperator() { @Override public List getOperandList() { - return Arrays.asList(name); + return tableNames; } @Override diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlResumeRebalanceJob.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlResumeRebalanceJob.java new file mode 100644 index 000000000..30dd12f7f --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlResumeRebalanceJob.java @@ -0,0 +1,90 @@ +package org.apache.calcite.sql; + +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rel.type.RelDataTypeFieldImpl; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.calcite.sql.validate.SqlValidator; +import org.apache.calcite.sql.validate.SqlValidatorScope; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * @author wumu + */ +public class SqlResumeRebalanceJob extends SqlDal implements DdlJobUtility { + + private static final SqlSpecialOperator OPERATOR = new SqlResumeRebalanceJobOperator(); + private boolean all; + private List jobIds = new ArrayList<>(); + + public SqlResumeRebalanceJob(SqlParserPos pos, boolean all) { + super(pos); + this.operands = new ArrayList<>(0); + this.all = all; + } + + @Override + public boolean isAll() { + return all; + } + + public void setAll(boolean all) { + this.all = all; + } + + @Override + public List getJobIds() { + return jobIds; + } + + public void setJobIds(List jobIds) { + this.jobIds.clear(); + this.jobIds.addAll(jobIds); + } + + @Override + public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { + final SqlWriter.Frame selectFrame = writer.startList(SqlWriter.FrameTypeEnum.SELECT); + writer.sep("RESUME REBALANCE"); + if (isAll()) { + writer.print("ALL"); + } else { + writer.print(StringUtils.join(jobIds, ",")); + } + writer.endList(selectFrame); + } + + @Override + public SqlOperator getOperator() { + return OPERATOR; + } + + @Override + public SqlKind getKind() { + return SqlKind.RESUME_REBALANCE_JOB; + } + + public static class SqlResumeRebalanceJobOperator extends SqlSpecialOperator { + + public SqlResumeRebalanceJobOperator() { + super("RESUME_REBALANCE_JOB", SqlKind.RESUME_REBALANCE_JOB); + } + + @Override + public RelDataType deriveType(SqlValidator validator, SqlValidatorScope scope, SqlCall call) { + final RelDataTypeFactory typeFactory = validator.getTypeFactory(); + List columns = new LinkedList<>(); + + columns.add(new RelDataTypeFieldImpl("JOB_ID", 0, typeFactory.createSqlType(SqlTypeName.INTEGER))); + columns.add(new RelDataTypeFieldImpl("STATUS", 1, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + + return typeFactory.createStructType(columns); + } + } + +} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlShowDdlEngine.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlShowDdlEngine.java new file mode 100644 index 000000000..94f0ebc38 --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlShowDdlEngine.java @@ -0,0 +1,98 @@ +package org.apache.calcite.sql; + +import lombok.Getter; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rel.type.RelDataTypeFieldImpl; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.calcite.sql.validate.SqlValidator; +import org.apache.calcite.sql.validate.SqlValidatorScope; + +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + */ +public class SqlShowDdlEngine extends SqlShow { + + private SqlSpecialOperator operator; + + private boolean full; + + public SqlShowDdlEngine(SqlParserPos pos, List specialIdentifiers, + boolean full) { + super(pos, specialIdentifiers); + this.full = full; + } + + public boolean isFull() { + return full; + } + + public void setFull(boolean full) { + this.full = full; + } + + @Override + protected boolean showWhere() { + return false; + } + + @Override + public SqlOperator getOperator() { + if (null == operator) { + operator = new SqlShowDdlEngineOperator(this.full); + } + return operator; + } + + @Override + public SqlKind getShowKind() { + return SqlKind.SHOW_DDL_ENGINE; + } + + public static class SqlShowDdlEngineOperator extends SqlSpecialOperator { + + private boolean full; + + public SqlShowDdlEngineOperator(boolean full) { + super("SHOW_DDL_ENGINE", SqlKind.SHOW_DDL_ENGINE); + this.full = full; + } + + @Override + public RelDataType deriveType(SqlValidator validator, SqlValidatorScope scope, SqlCall call) { + final RelDataTypeFactory typeFactory = validator.getTypeFactory(); + List columns = new LinkedList<>(); + + columns.add(new RelDataTypeFieldImpl("JOB_ID", 0, typeFactory.createSqlType(SqlTypeName.INTEGER))); + if (full) { + columns.add( + new RelDataTypeFieldImpl("PARENT_JOB_ID", 1, typeFactory.createSqlType(SqlTypeName.INTEGER))); + } + columns.add(new RelDataTypeFieldImpl("SERVER", 2, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + columns.add(new RelDataTypeFieldImpl("OBJECT_SCHEMA", 3, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + columns.add(new RelDataTypeFieldImpl("OBJECT_NAME", 4, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + if (full) { + columns.add( + new RelDataTypeFieldImpl("NEW_OBJECT_NAME", 5, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + } + columns.add(new RelDataTypeFieldImpl("JOB_TYPE", 6, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + columns.add(new RelDataTypeFieldImpl("PHASE", 7, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + columns.add(new RelDataTypeFieldImpl("STATE", 8, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + columns.add(new RelDataTypeFieldImpl("PROGRESS", 9, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + if (full) { + columns.add(new RelDataTypeFieldImpl("DDL_STMT", 10, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + } + columns.add(new RelDataTypeFieldImpl("GMT_CREATED", 11, typeFactory.createSqlType(SqlTypeName.TIMESTAMP))); + columns.add(new RelDataTypeFieldImpl("GMT_MODIFIED", 12, typeFactory.createSqlType(SqlTypeName.TIMESTAMP))); + columns.add(new RelDataTypeFieldImpl("REMARK", 13, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + columns.add( + new RelDataTypeFieldImpl("BACKFILL_PROGRESS", 14, typeFactory.createSqlType(SqlTypeName.VARCHAR))); + + return typeFactory.createStructType(columns); + } + } +} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlStartReplicaCheck.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlStartReplicaCheck.java index d8db2e6d0..b8b0e444a 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlStartReplicaCheck.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlStartReplicaCheck.java @@ -38,6 +38,7 @@ public class SqlStartReplicaCheck extends SqlDal { private SqlNode dbName; private SqlNode tableName; private SqlNode channel; + private SqlNode mode; public SqlStartReplicaCheck(SqlParserPos pos, SqlNode channel, SqlNode dbName) { super(pos); @@ -69,6 +70,14 @@ public void setChannel(SqlNode channel) { this.channel = channel; } + public SqlNode getMode() { + return mode; + } + + public void setMode(SqlNode mode) { + this.mode = mode; + } + @Override public SqlOperator getOperator() { return OPERATOR; @@ -83,9 +92,13 @@ public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { tableName.unparse(writer, 0, 0); } if (channel != null) { - writer.keyword("FOR CHANNEL"); + writer.keyword("CHANNEL="); channel.unparse(writer, 0, 0); } + if (mode != null) { + writer.keyword("MODE="); + mode.unparse(writer, 0, 0); + } } public static class SqlStartReplicaCheckOperator extends SqlSpecialOperator { diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlTimeToLiveDefinitionExpr.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlTimeToLiveDefinitionExpr.java new file mode 100644 index 000000000..0670913ca --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlTimeToLiveDefinitionExpr.java @@ -0,0 +1,180 @@ +package org.apache.calcite.sql; + +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.util.SqlVisitor; +import org.apache.calcite.sql.validate.SqlValidator; +import org.apache.calcite.sql.validate.SqlValidatorScope; +import org.apache.calcite.util.EqualsContext; +import org.apache.calcite.util.Litmus; + +/** + * @author chenghui.lch + */ +public class SqlTimeToLiveDefinitionExpr extends SqlNode { + + protected SqlNode ttlEnableExpr; + protected SqlNode ttlExpr; + protected SqlNode ttlJobExpr; + protected SqlNode ttlFilterExpr; + protected SqlNode archiveTypeExpr; + protected SqlNode archiveTableSchemaExpr; + protected SqlNode archiveTableNameExpr; + protected SqlNode archiveTablePreAllocateExpr; + protected SqlNode archiveTablePostAllocateExpr; + + public SqlTimeToLiveDefinitionExpr() { + super(SqlParserPos.ZERO); + } + + @Override + public SqlNode clone(SqlParserPos pos) { + return null; + } + + @Override + public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { + +// final SqlWriter.Frame startFrame = writer.startList(SqlWriter.FrameTypeEnum.SIMPLE); + + writer.print("TTL_DEFINITION("); + if (ttlEnableExpr != null) { + writer.print("TTL_ENABLE = "); + ttlEnableExpr.unparse(writer, leftPrec, rightPrec); + } + if (ttlExpr != null) { + writer.print(", "); + writer.print("TTL_EXPR = "); + ttlExpr.unparse(writer, leftPrec, rightPrec); + } + if (ttlJobExpr != null) { + writer.print(", "); + writer.print("TTL_JOB = "); + ttlJobExpr.unparse(writer, leftPrec, rightPrec); + } + if (ttlFilterExpr != null) { + writer.print(", "); + writer.print("TTL_FILTER = "); + ttlFilterExpr.unparse(writer, leftPrec, rightPrec); + } + if (archiveTypeExpr != null) { + writer.print(", "); + writer.print("ARCHIVE_TYPE = "); + archiveTypeExpr.unparse(writer, leftPrec, rightPrec); + } + + if (archiveTableSchemaExpr != null) { + writer.print(", "); + writer.print("ARCHIVE_TABLE_SCHEMA = "); + archiveTableSchemaExpr.unparse(writer, leftPrec, rightPrec); + } + + if (archiveTableNameExpr != null) { + writer.print(", "); + writer.print("ARCHIVE_TABLE_NAME = "); + archiveTableNameExpr.unparse(writer, leftPrec, rightPrec); + } + + if (archiveTablePreAllocateExpr != null) { + writer.print(", "); + writer.print("ARCHIVE_TABLE_PRE_ALLOCATE = "); + archiveTablePreAllocateExpr.unparse(writer, leftPrec, rightPrec); + } + + if (archiveTablePostAllocateExpr != null) { + writer.print(", "); + writer.print("ARCHIVE_TABLE_POST_ALLOCATE = "); + archiveTablePostAllocateExpr.unparse(writer, leftPrec, rightPrec); + } + + writer.print(")"); + } + + @Override + public void validate(SqlValidator validator, SqlValidatorScope scope) { + + } + + @Override + public R accept(SqlVisitor visitor) { + return null; + } + + @Override + public boolean equalsDeep(SqlNode node, Litmus litmus, EqualsContext context) { + return false; + } + + + public SqlNode getTtlExpr() { + return ttlExpr; + } + + public void setTtlExpr(SqlNode ttlExpr) { + this.ttlExpr = ttlExpr; + } + + public SqlNode getTtlJobExpr() { + return ttlJobExpr; + } + + public void setTtlJobExpr(SqlNode ttlJobExpr) { + this.ttlJobExpr = ttlJobExpr; + } + + public SqlNode getTtlFilterExpr() { + return ttlFilterExpr; + } + + public void setTtlFilterExpr(SqlNode ttlFilterExpr) { + this.ttlFilterExpr = ttlFilterExpr; + } + + public SqlNode getArchiveTypeExpr() { + return archiveTypeExpr; + } + + public void setArchiveTypeExpr(SqlNode archiveTypeExpr) { + this.archiveTypeExpr = archiveTypeExpr; + } + + public SqlNode getArchiveTableSchemaExpr() { + return archiveTableSchemaExpr; + } + + public void setArchiveTableSchemaExpr(SqlNode archiveTableSchemaExpr) { + this.archiveTableSchemaExpr = archiveTableSchemaExpr; + } + + + public SqlNode getArchiveTablePreAllocateExpr() { + return archiveTablePreAllocateExpr; + } + + public void setArchiveTablePreAllocateExpr(SqlNode archiveTablePreAllocateExpr) { + this.archiveTablePreAllocateExpr = archiveTablePreAllocateExpr; + } + + public SqlNode getArchiveTablePostAllocateExpr() { + return archiveTablePostAllocateExpr; + } + + public void setArchiveTablePostAllocateExpr(SqlNode archiveTablePostAllocateExpr) { + this.archiveTablePostAllocateExpr = archiveTablePostAllocateExpr; + } + + public SqlNode getTtlEnableExpr() { + return ttlEnableExpr; + } + + public void setTtlEnableExpr(SqlNode ttlEnableExpr) { + this.ttlEnableExpr = ttlEnableExpr; + } + + public SqlNode getArchiveTableNameExpr() { + return archiveTableNameExpr; + } + + public void setArchiveTableNameExpr(SqlNode archiveTableNameExpr) { + this.archiveTableNameExpr = archiveTableNameExpr; + } +} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlTimeToLiveExpr.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlTimeToLiveExpr.java new file mode 100644 index 000000000..908148245 --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlTimeToLiveExpr.java @@ -0,0 +1,98 @@ +package org.apache.calcite.sql; + +import com.alibaba.polardbx.druid.sql.SQLUtils; +import com.google.common.base.Joiner; +import org.apache.calcite.sql.dialect.MysqlSqlDialect; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.util.SqlVisitor; +import org.apache.calcite.sql.validate.SqlValidator; +import org.apache.calcite.sql.validate.SqlValidatorScope; +import org.apache.calcite.util.EqualsContext; +import org.apache.calcite.util.Litmus; +import org.apache.commons.lang.StringUtils; + +/** + * @author chenghui.lch + */ +public class SqlTimeToLiveExpr extends SqlNode { + + protected SqlNode column; + protected SqlNode expireAfter; + protected SqlNode unit; + protected SqlNode timezone; + + public SqlTimeToLiveExpr() { + super(SqlParserPos.ZERO); + } + + @Override + public SqlNode clone(SqlParserPos pos) { + return null; + } + + @Override + public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { + +// final SqlWriter.Frame startFrame = writer.startList(SqlWriter.FrameTypeEnum.SIMPLE); + + writer.print(column.toSqlString(MysqlSqlDialect.DEFAULT, false).getSql()); + writer.print(" "); + writer.print("EXPIRE AFTER "); + writer.print(expireAfter.toSqlString(MysqlSqlDialect.DEFAULT, false).getSql()); + writer.print(" "); + writer.print(SQLUtils.normalize(unit.toSqlString(MysqlSqlDialect.DEFAULT, false).getSql())); + if (timezone != null) { + writer.print(" "); + writer.print("TIMEZONE "); + writer.print(timezone.toSqlString(MysqlSqlDialect.DEFAULT, false).getSql()); + } +// writer.endList(startFrame); + } + + @Override + public void validate(SqlValidator validator, SqlValidatorScope scope) { + + } + + @Override + public R accept(SqlVisitor visitor) { + return null; + } + + @Override + public boolean equalsDeep(SqlNode node, Litmus litmus, EqualsContext context) { + return false; + } + + public SqlNode getColumn() { + return column; + } + + public void setColumn(SqlNode column) { + this.column = column; + } + + public SqlNode getExpireAfter() { + return expireAfter; + } + + public void setExpireAfter(SqlNode expireAfter) { + this.expireAfter = expireAfter; + } + + public SqlNode getUnit() { + return unit; + } + + public void setUnit(SqlNode unit) { + this.unit = unit; + } + + public SqlNode getTimezone() { + return timezone; + } + + public void setTimezone(SqlNode timezone) { + this.timezone = timezone; + } +} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlTimeToLiveJobExpr.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlTimeToLiveJobExpr.java new file mode 100644 index 000000000..6505472b1 --- /dev/null +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/SqlTimeToLiveJobExpr.java @@ -0,0 +1,69 @@ +package org.apache.calcite.sql; + +import org.apache.calcite.sql.dialect.MysqlSqlDialect; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.util.SqlVisitor; +import org.apache.calcite.sql.validate.SqlValidator; +import org.apache.calcite.sql.validate.SqlValidatorScope; +import org.apache.calcite.util.EqualsContext; +import org.apache.calcite.util.Litmus; + +/** + * @author chenghui.lch + */ +public class SqlTimeToLiveJobExpr extends SqlNode { + + protected SqlNode cron; + protected SqlNode timezone; + + public SqlTimeToLiveJobExpr() { + super(SqlParserPos.ZERO); + } + + @Override + public SqlNode clone(SqlParserPos pos) { + return null; + } + + @Override + public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { + writer.print("CRON "); + writer.print(cron.toSqlString(MysqlSqlDialect.DEFAULT, false).getSql()); + if (timezone != null) { + writer.print(" "); + writer.print("TIMEZONE "); + writer.print(timezone.toSqlString(MysqlSqlDialect.DEFAULT, false).getSql()); + } + } + + @Override + public void validate(SqlValidator validator, SqlValidatorScope scope) { + + } + + @Override + public R accept(SqlVisitor visitor) { + return null; + } + + @Override + public boolean equalsDeep(SqlNode node, Litmus litmus, EqualsContext context) { + return false; + } + + public SqlNode getCron() { + return cron; + } + + public void setCron(SqlNode cron) { + this.cron = cron; + } + + public SqlNode getTimezone() { + return timezone; + } + + public void setTimezone(SqlNode timezone) { + this.timezone = timezone; + } +} diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/fun/SqlCheckSumV2Function.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/fun/SqlCheckSumV2Function.java index 98f7dbcf7..5fba7d154 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/fun/SqlCheckSumV2Function.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/fun/SqlCheckSumV2Function.java @@ -45,7 +45,6 @@ public SqlCheckSumV2Function() { false); } - @Override public RelDataType deriveType( SqlValidator validator, diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java index b23336c74..fa141e46c 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java @@ -67,17 +67,17 @@ public BasicSqlType(RelDataTypeSystem typeSystem, SqlTypeName typeName, computeDigest(); } - /** - * Constructs a type with precision/length and scale. - * - * @param typeName Type name - */ - public BasicSqlType(RelDataTypeSystem typeSystem, SqlTypeName typeName, - int precision, int scale) { - this(typeSystem, typeName, true, precision, scale); + /** + * Constructs a type with precision/length and scale. + * + * @param typeName Type name + */ + public BasicSqlType(RelDataTypeSystem typeSystem, SqlTypeName typeName, + int precision, int scale) { + this(typeSystem, typeName, true, precision, scale); // assert typeName.allowsPrecScale(true, true); - computeDigest(); - } + computeDigest(); + } /** * Internal constructor. @@ -181,8 +181,8 @@ protected void generateTypeString(StringBuilder sb, boolean withDetail) { boolean printPrecision = precision != PRECISION_NOT_SPECIFIED; boolean printScale = scale != SCALE_NOT_SPECIFIED; - if (SqlTypeName.DATETIME_TYPES.contains(typeName)) { - // for time/datetime/timestamp, we should print fsp(scale) rather than precision. + if (SqlTypeName.DATETIME_TYPES.contains(typeName) || SqlTypeName.APPROX_TYPES.contains(typeName)) { + // for time/datetime/timestamp/float/real/double, we should print fsp(scale) rather than precision. if (getScale() >= 0) { sb.append('('); sb.append(getScale()); diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/OperandTypes.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/OperandTypes.java index f3fd33a37..8f0896398 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/OperandTypes.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/OperandTypes.java @@ -256,6 +256,26 @@ public boolean test(Integer number) { } }); + public static final FamilyOperandTypeChecker STRING_OPTIONAL_NUMERIC = + family(ImmutableList.of(SqlTypeFamily.STRING, SqlTypeFamily.NUMERIC), + new PredicateImpl() { + // Second operand optional (operand index 0, 1) + @Override + public boolean test(Integer number) { + return number == 1; + } + }); + + public static final FamilyOperandTypeChecker BINARY_OPTIONAL_NUMERIC = + family(ImmutableList.of(SqlTypeFamily.BINARY, SqlTypeFamily.NUMERIC), + new PredicateImpl() { + // Second operand optional (operand index 0, 1) + @Override + public boolean test(Integer number) { + return number == 1; + } + }); + public static final FamilyOperandTypeChecker ANY_STRING_STRING = family(SqlTypeFamily.ANY, SqlTypeFamily.STRING, SqlTypeFamily.STRING); diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/SqlTypeFactoryImpl.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/SqlTypeFactoryImpl.java index 0ee71650d..12fe4fc06 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/SqlTypeFactoryImpl.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/SqlTypeFactoryImpl.java @@ -50,6 +50,7 @@ public RelDataType createSqlType(SqlTypeName typeName) { } assertBasic(typeName); RelDataType newType = new BasicSqlType(typeSystem, typeName); + newType = SqlTypeUtil.addCharsetAndCollation(newType, this); return canonize(newType); } diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/SqlTypeName.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/SqlTypeName.java index 8271c5fbf..61afcd6f9 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/SqlTypeName.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/type/SqlTypeName.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.charset.CharsetName; import com.alibaba.polardbx.common.datatype.DecimalTypeBase; +import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.time.MySQLTimeTypeUtil; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -69,9 +70,9 @@ public enum SqlTypeName { YEAR(PrecScale.NO_NO, false, Types.INTEGER, SqlTypeFamily.NUMERIC), DECIMAL(PrecScale.NO_NO | PrecScale.YES_NO | PrecScale.YES_YES, false, Types.DECIMAL, SqlTypeFamily.NUMERIC), - FLOAT(PrecScale.NO_NO, false, Types.FLOAT, SqlTypeFamily.NUMERIC), + FLOAT(PrecScale.NO_NO | PrecScale.YES_NO | PrecScale.YES_YES, false, Types.FLOAT, SqlTypeFamily.NUMERIC), REAL(PrecScale.NO_NO, false, Types.REAL, SqlTypeFamily.NUMERIC), - DOUBLE(PrecScale.NO_NO, false, Types.DOUBLE, SqlTypeFamily.NUMERIC), + DOUBLE(PrecScale.NO_NO | PrecScale.YES_NO | PrecScale.YES_YES, false, Types.DOUBLE, SqlTypeFamily.NUMERIC), UNSIGNED(PrecScale.NO_NO, false, Types.BIGINT, SqlTypeFamily.NUMERIC), SIGNED(PrecScale.NO_NO, false, Types.BIGINT, SqlTypeFamily.NUMERIC), @@ -416,6 +417,9 @@ public boolean allowsPrecNoScale() { } public boolean allowsPrec() { + if (SqlTypeName.APPROX_TYPES.contains(this) && !DynamicConfig.getInstance().isEnableFloatingTypePrecision()) { + return false; + } return allowsPrecScale(true, true) || allowsPrecScale(true, false); } diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java index bc3fcc42f..88f99e743 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java @@ -5444,6 +5444,10 @@ public void validateDdl( } if (GeneralUtil.isNotEmpty(createTable.getColumnarKeys())) { + //support columnar index in UT +// if (!ConfigDataMode.isPolarDbX()) { +// throw new NotSupportException("Creating Clustered Columnar Index on DRDS mode"); +// } createTable.getColumnarKeys().forEach(s -> gsiNames.add(s.getKey().getLastName())); } @@ -7411,13 +7415,6 @@ private String removeDbPrefix(String currentSchema, SqlNameMatcher sqlNameMatche } public void validateUpdate(SqlUpdate call) { - if (call.getSourceExpressionList() != null) { - for (SqlNode node : call.getSourceExpressionList()) { - if (node instanceof SqlSelect) { // Don't allow sub-query in update set clause. - throw newValidationError(node, RESOURCE.updateNotSupport(node.toString())); - } - } - } if (call.singleTable()) { final SqlValidatorNamespace targetNamespace = getNamespace(call); validateNamespace(targetNamespace, unknownType); diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java b/polardbx-calcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java index a4f7a5e07..76a66a14d 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java @@ -88,6 +88,7 @@ import org.apache.calcite.rel.ddl.AlterStoragePool; import org.apache.calcite.rel.ddl.AlterSystemSetConfig; import org.apache.calcite.rel.ddl.AlterTable; +import org.apache.calcite.rel.ddl.AlterTableArchivePartition; import org.apache.calcite.rel.ddl.AlterTableGroupAddPartition; import org.apache.calcite.rel.ddl.AlterTableGroupAddTable; import org.apache.calcite.rel.ddl.AlterTableGroupDropPartition; @@ -95,6 +96,7 @@ import org.apache.calcite.rel.ddl.AlterTableGroupMergePartition; import org.apache.calcite.rel.ddl.AlterTableGroupModifyPartition; import org.apache.calcite.rel.ddl.AlterTableGroupMovePartition; +import org.apache.calcite.rel.ddl.AlterTableGroupOptimizePartition; import org.apache.calcite.rel.ddl.AlterTableGroupRenamePartition; import org.apache.calcite.rel.ddl.AlterTableGroupReorgPartition; import org.apache.calcite.rel.ddl.AlterTableGroupSetLocality; @@ -229,6 +231,7 @@ import org.apache.calcite.sql.SqlAlterSystemSetConfig; import org.apache.calcite.sql.SqlAlterTable; import org.apache.calcite.sql.SqlAlterTableAddPartition; +import org.apache.calcite.sql.SqlAlterTableArchivePartition; import org.apache.calcite.sql.SqlAlterTableDropPartition; import org.apache.calcite.sql.SqlAlterTableExtractPartition; import org.apache.calcite.sql.SqlAlterTableGroup; @@ -245,6 +248,7 @@ import org.apache.calcite.sql.SqlAlterTableModifyPartitionValues; import org.apache.calcite.sql.SqlAlterTableModifySubPartitionValues; import org.apache.calcite.sql.SqlAlterTableMovePartition; +import org.apache.calcite.sql.SqlAlterTableOptimizePartition; import org.apache.calcite.sql.SqlAlterTablePartitionCount; import org.apache.calcite.sql.SqlAlterTablePartitionKey; import org.apache.calcite.sql.SqlAlterTableRemovePartitioning; @@ -3179,7 +3183,28 @@ protected final void createAggImpl(Blackboard bb, final AggConverter aggConverte final RelNode inputRel = bb.root; // Project the expressions required by agg and having. - bb.setRoot(RelOptUtil.createProject(inputRel, preExprs, true).setHints(inputRel.getHints()), false); + RelNode rel = RelOptUtil.createProject(inputRel, preExprs, true).setHints(inputRel.getHints()); + CorrelationUse correlationUse = null; + if (rel instanceof LogicalProject) { + Map exprIndex = Maps.newHashMap(); + correlationUse = getCorrelationUse(bb, rel, exprIndex, firstValueForSubquery, firstValueTarget); + if (correlationUse != null) { + // update correlation id rowtype + RelDataType newType = ((Project) rel).getInput().getRowType(); + RelNode newrel = + RexUtil.replaceRexFieldAccess(correlationUse.r, exprIndex, correlationUse.id, newType); + correlationUse = new CorrelationUse(correlationUse.id, correlationUse.requiredColumns, newrel); + } + } + + if (correlationUse == null) { + bb.setRoot(rel, false); + } else { + LogicalProject logicalProject = (LogicalProject) correlationUse.r; + bb.setRoot( + LogicalProject.create(logicalProject.getInput(), logicalProject.getProjects(), rel.getRowType(), + ImmutableSet.of(correlationUse.id)), false); + } bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection); // REVIEW jvs 31-Oct-2007: doesn't the declaration of @@ -3334,7 +3359,7 @@ protected RelNode createAggregate(Blackboard bb, ImmutableBitSet groupSet, Immut } if (isNotNullOperands.size() > 0) { relNode = LogicalFilter.create( - relNode, RexUtil.composeConjunction(rexBuilder, isNotNullOperands, true)); + relNode, RexUtil.composeConjunction(rexBuilder, isNotNullOperands, true)); } } return LogicalAggregate.create(relNode, groupSet, groupSets, aggregateCalls); @@ -3754,7 +3779,8 @@ private RelNode convertAlterTable(SqlAlterTable query) { || (alterSpecItem instanceof SqlAlterTableDropPartition) || (alterSpecItem instanceof SqlAlterTableModifyPartitionValues) || (alterSpecItem instanceof SqlAlterTableTruncatePartition) - || (alterSpecItem instanceof SqlAlterTableReorgPartition); + || (alterSpecItem instanceof SqlAlterTableReorgPartition) + || (alterSpecItem instanceof SqlAlterTableOptimizePartition); if (!changePartition) { query = checkAndRewriteGsiName(query); @@ -3778,7 +3804,7 @@ private RelNode convertAlterTable(SqlAlterTable query) { || o instanceof SqlAlterTableExtractPartition || o instanceof SqlAlterTableMergePartition || o instanceof SqlAlterTableMovePartition || o instanceof SqlAlterTableAddPartition || o instanceof SqlAlterTableDropPartition || o instanceof SqlAlterTableModifyPartitionValues - || o instanceof SqlAlterTableTruncatePartition) + || o instanceof SqlAlterTableTruncatePartition || o instanceof SqlAlterTableOptimizePartition) .findFirst(); if (mergeSplitItem.isPresent()) { throw new RuntimeException( @@ -3795,6 +3821,8 @@ private RelNode convertAlterTable(SqlAlterTable query) { return AlterTablePartitionCount.create(getCluster(), query, query.getOperandList().get(0)); } else if (query instanceof SqlAlterTableRemovePartitioning) { return AlterTableRemovePartitioning.create(getCluster(), query, query.getOperandList().get(0)); + } else if (query instanceof SqlAlterTableArchivePartition) { + return AlterTableArchivePartition.create(getCluster(), query, query.getOperandList().get(0)); } return AlterTable.create(getCluster(), query, query.getOperandList().get(0), new HashMap<>()); @@ -3954,6 +3982,9 @@ private RelNode convertAlterTableGroup(SqlAlterTableGroup query) { } else if (item instanceof SqlAlterTableTruncatePartition) { return AlterTableGroupTruncatePartition.create(getCluster(), getCluster().traitSetOf(Convention.NONE), query, targetRowType, tableGroupName); + } else if (item instanceof SqlAlterTableOptimizePartition) { + return AlterTableGroupOptimizePartition.create(getCluster(), getCluster().traitSetOf(Convention.NONE), + query, targetRowType, tableGroupName); } else if (item instanceof SqlAlterTableReorgPartition) { return AlterTableGroupReorgPartition.create(getCluster(), getCluster().traitSetOf(Convention.NONE), query, targetRowType, partRexInfoCtxByLevel, tableGroupName); @@ -4701,6 +4732,8 @@ public Map> getRexInfoFromSqlAlterSpecByLevel( } else if (sqlAlterSpecifications.get(0) instanceof SqlAlterTableTruncatePartition) { + } else if (sqlAlterSpecifications.get(0) instanceof SqlAlterTableOptimizePartition) { + } else if (sqlAlterSpecifications.get(0) instanceof SqlAlterTableModifyPartitionValues) { SqlAlterTableModifyPartitionValues modifyPartition = (SqlAlterTableModifyPartitionValues) sqlAlterSpecifications.get(0); @@ -5410,9 +5443,15 @@ protected RelNode convertDelete(SqlDelete call) { ImmutableList.of(), ImmutableList.of()); } + protected void checkSubqueryInSetClause(SqlUpdate call) { + + } + protected RelNode convertUpdate(SqlUpdate call) { interceptDMLAllTableSql(call); + checkSubqueryInSetClause(call); + // Source table info // Map column to table it belongs to final Map aliasTableMap = new HashMap<>(); diff --git a/polardbx-calcite/src/main/java/org/apache/calcite/util/javac/JaninoCompiler.java b/polardbx-calcite/src/main/java/org/apache/calcite/util/javac/JaninoCompiler.java index a84fbdbb9..064cca4cc 100644 --- a/polardbx-calcite/src/main/java/org/apache/calcite/util/javac/JaninoCompiler.java +++ b/polardbx-calcite/src/main/java/org/apache/calcite/util/javac/JaninoCompiler.java @@ -16,10 +16,10 @@ */ package org.apache.calcite.util.javac; +import org.codehaus.commons.compiler.util.resource.MapResourceFinder; +import org.codehaus.commons.compiler.util.resource.ResourceFinder; import org.codehaus.janino.JavaSourceClassLoader; import org.codehaus.janino.util.ClassFile; -import org.codehaus.janino.util.resource.MapResourceFinder; -import org.codehaus.janino.util.resource.ResourceFinder; import java.io.File; import java.io.FileOutputStream; diff --git a/polardbx-calcite/src/test/java/org/apache/calcite/sql/SqlCheckColumnarIndexTest.java b/polardbx-calcite/src/test/java/org/apache/calcite/sql/SqlCheckColumnarIndexTest.java new file mode 100644 index 000000000..f8e50bc40 --- /dev/null +++ b/polardbx-calcite/src/test/java/org/apache/calcite/sql/SqlCheckColumnarIndexTest.java @@ -0,0 +1,44 @@ +package org.apache.calcite.sql; + +import org.apache.calcite.sql.dialect.CalciteSqlDialect; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.pretty.SqlPrettyWriter; +import org.apache.calcite.sql.validate.SqlValidator; +import org.apache.calcite.sql.validate.SqlValidatorScope; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; + +public class SqlCheckColumnarIndexTest { + @Test + public void testNormalCase() { + SqlParserPos pos = SqlParserPos.ZERO; + String indexNameStr = "test_index"; + SqlIdentifier indexName = new SqlIdentifier(indexNameStr, pos); + String tableNameStr = "test_table"; + SqlIdentifier tableName = new SqlIdentifier(tableNameStr, pos); + String extraCmd = "increment"; + List extras = new ArrayList<>(); + extras.add(100L); + extras.add(200L); + + SqlCheckColumnarIndex sqlCheckColumnarIndex = new SqlCheckColumnarIndex(pos, indexName, tableName, extraCmd, extras); + + assertEquals(indexNameStr, sqlCheckColumnarIndex.getIndexName().toString()); + assertEquals(tableNameStr, sqlCheckColumnarIndex.getTableName().toString()); + assertEquals(extraCmd, sqlCheckColumnarIndex.getExtraCmd()); + assertEquals(extras, sqlCheckColumnarIndex.getExtras()); + + SqlValidator validator = mock(SqlValidator.class); + SqlValidatorScope scope = mock(SqlValidatorScope.class); + sqlCheckColumnarIndex.validate(validator, scope); + + SqlPrettyWriter writer = new SqlPrettyWriter(CalciteSqlDialect.DEFAULT); + sqlCheckColumnarIndex.unparse(writer, 0, 0); + assertEquals("CHECK COLUMNAR INDEX \"test_index\"\nON \"test_table\"\nINCREMENT", writer.toString()); + } +} diff --git a/polardbx-common/pom.xml b/polardbx-common/pom.xml index 9910129de..c34cde549 100644 --- a/polardbx-common/pom.xml +++ b/polardbx-common/pom.xml @@ -30,24 +30,12 @@ fastjson - mysql - mysql-connector-java - - - - - commons-logging - commons-logging-api - provided + com.alibaba + druid - log4j - log4j - provided + mysql + mysql-connector-java @@ -121,51 +109,23 @@ slf4j-simple org.slf4j - - org.apache.arrow - arrow-vector - - - org.apache.arrow - arrow-memory-netty - org.apache.hadoop - hadoop-client + hadoop-common + + + + org.apache.hadoop + hadoop-hdfs-client ${hadoop.version} - - - commons-logging - commons-logging - - - slf4j-api - org.slf4j - - - jsr311-api - javax.ws.rs - - - slf4j-reload4j - org.slf4j - - com.aliyun.oss aliyun-sdk-oss - 3.10.2 - - - commons-logging - commons-logging - - @@ -177,22 +137,16 @@ com.emc.ecs nfs-client - - - org.roaringbitmap - RoaringBitmap - - - - com.github.ben-manes.caffeine - caffeine - org.mockito mockito-inline test + + org.roaringbitmap + RoaringBitmap + @@ -232,27 +186,26 @@ mac - + - Version Calculation - generate-sources - - exec - - - ${basedir}/../saveVersion.sh - - - - - - + --> + diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/ArchiveMode.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ArchiveMode.java index c9fc9b6c2..4dcb6ac11 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/ArchiveMode.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ArchiveMode.java @@ -21,7 +21,8 @@ public enum ArchiveMode { EMPTY, TTL, - LOADING; + LOADING, + ; public static ArchiveMode of(String archiveMode) { if (TStringUtil.isEmpty(archiveMode)) { diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/ColumnarOptions.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ColumnarOptions.java new file mode 100644 index 000000000..4ebb9933d --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ColumnarOptions.java @@ -0,0 +1,9 @@ +package com.alibaba.polardbx.common; + +public class ColumnarOptions { + public static final String DICTIONARY_COLUMNS = "DICTIONARY_COLUMNS"; + public static final String TYPE = "TYPE"; + public static final String SNAPSHOT_RETENTION_DAYS = "SNAPSHOT_RETENTION_DAYS"; + public static final String AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL = "AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL"; + public static final String COLUMNAR_PURGE_SAVE_MS = "COLUMNAR_PURGE_SAVE_MS"; +} diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/ColumnarTableOptions.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ColumnarTableOptions.java index cee81209c..8728ec83e 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/ColumnarTableOptions.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ColumnarTableOptions.java @@ -18,4 +18,9 @@ public class ColumnarTableOptions { public static final String DICTIONARY_COLUMNS = "DICTIONARY_COLUMNS"; + public static final String TYPE = "type"; + public static final String SNAPSHOT_RETENTION_DAYS = "snapshot_retention_days"; + public static final String DEFAULT_SNAPSHOT_RETENTION_DAYS = "7"; + public static final String AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL = "auto_gen_columnar_snapshot_interval"; + public static final String DEFAULT_AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL = "30"; } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/Engine.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/Engine.java index 21639977a..0fe0a6949 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/Engine.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/Engine.java @@ -35,7 +35,8 @@ public enum Engine { ABS, OSS, NFS, - MEMORY; + MEMORY, + COLUMNAR; public static final Engine DEFAULT_COLUMNAR_ENGINE = OSS; @@ -94,6 +95,7 @@ public static boolean supportColumnar(Engine engine) { case NFS: case S3: case ABS: + case COLUMNAR: return true; default: return false; diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/IInnerConnection.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/IInnerConnection.java index 57fd1e89e..843519309 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/IInnerConnection.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/IInnerConnection.java @@ -18,9 +18,10 @@ import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; +import java.sql.Connection; import java.util.function.Consumer; -public interface IInnerConnection { +public interface IInnerConnection extends Connection { ITransactionPolicy getTrxPolicy(); void setTrxPolicy(ITransactionPolicy trxPolicy); diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/IInnerConnectionManager.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/IInnerConnectionManager.java index 798c4fe70..628590cf3 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/IInnerConnectionManager.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/IInnerConnectionManager.java @@ -20,7 +20,7 @@ import java.sql.SQLException; public interface IInnerConnectionManager { - Connection getConnection() throws SQLException; + IInnerConnection getConnection() throws SQLException; - Connection getConnection(String schema) throws SQLException; + IInnerConnection getConnection(String schema) throws SQLException; } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/MergedStorageInfo.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/MergedStorageInfo.java new file mode 100644 index 000000000..462702ddf --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/MergedStorageInfo.java @@ -0,0 +1,68 @@ +/* + * 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 com.alibaba.polardbx.common; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class MergedStorageInfo { + private final boolean supportXA; + private final boolean supportTso; + private final boolean supportPurgeTso; + private final boolean supportTsoHeartbeat; + private final boolean supportCtsTransaction; + private final boolean supportAsyncCommit; + private final boolean supportLizard1PCTransaction; + private final boolean supportDeadlockDetection; + private final boolean supportMdlDeadlockDetection; + private final boolean supportsBloomFilter; + private final boolean supportOpenSSL; + private final boolean supportSharedReadView; + private final boolean supportsReturning; + private final boolean supportsBackfillReturning; + private final boolean supportsAlterType; + private final boolean readOnly; + private final boolean lowerCaseTableNames; + private final boolean supportHyperLogLog; + private final boolean lessMy56Version; + private final boolean supportXxHash; + private final boolean isMysql80; + + /** + * FastChecker: generate checksum on xdb node + * Since: 5.4.13 fix + * Requirement: XDB supports HASHCHECK function + */ + private final boolean supportFastChecker; + + private final boolean supportChangeSet; + + private final boolean supportXOptForAutoSp; + + private final boolean supportXRpc; + + private final boolean supportMarkDistributed; + + private final boolean supportXOptForPhysicalBackfill; + + private final boolean supportSyncPoint; + + private final boolean supportFlashbackArea; +} diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/TddlConstants.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/TddlConstants.java index 99ca31c9a..7aae53ce2 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/TddlConstants.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/TddlConstants.java @@ -16,6 +16,11 @@ package com.alibaba.polardbx.common; +/** + * The key differentiator between variables in the {@TddlConstants} class + * and those in the {@ConnectionProperties} class is that the former are not + * eligible for configuration through set instructions. + */ public class TddlConstants { public static final long DEFAULT_TABLE_META_EXPIRE_TIME = 300 * 1000; @@ -88,4 +93,10 @@ public class TddlConstants { public static final String BLACK_LIST_CONF = "BLACK_LIST_CONF"; public static final String ENABLE_JAVA_UDF = "ENABLE_JAVA_UDF"; + + public static final String ENABLE_SELECT_INTO_OUTFILE = "ENABLE_SELECT_INTO_OUTFILE"; + + public static final String ENABLE_LOAD_DATA_FILE = "ENABLE_LOAD_DATA_FILE"; + + public static final String ENABLE_STRICT_SET_GLOBAL = "ENABLE_STRICT_SET_GLOBAL"; } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/CdcDDLContext.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/CdcDDLContext.java index 2a8fcf344..921ad8c9b 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/CdcDDLContext.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/CdcDDLContext.java @@ -65,5 +65,12 @@ public class CdcDDLContext { private final Map> newTableTopology; private final Pair tablesExtInfoPair; - private Long versionId; + private final Long versionId; + /** + * 提交的tso结果,加了CDC_MARK_RECORD_COMMIT_TSO标记并成功执行才会存储 + */ + + private Long commitTso; + + private boolean sequenceDdl; } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/CdcManagerHelper.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/CdcManagerHelper.java index 5aa62b859..258b6e243 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/CdcManagerHelper.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/CdcManagerHelper.java @@ -61,7 +61,7 @@ public void notifyDdl(String schemaName, String tableName, String sqlKind, Strin Long jobId = job == null ? null : job.getId(); DdlType ddlType = job == null ? null : typeTransfer(job.getType()); CdcDDLContext context = new CdcDDLContext(schemaName, tableName, sqlKind, ddlSql, visibility, jobId, null, - ddlType, false, extendParams, job, false, null, null); + ddlType, false, extendParams, job, false, null, null, null, null, false); cdcManager.notifyDdl(context); } @@ -73,7 +73,17 @@ public void notifyDdlNew(String schemaName, String tableName, String sqlKind, St CdcDdlMarkVisibility visibility, Map extendParams) { CdcDDLContext context = new CdcDDLContext(schemaName, tableName, sqlKind, ddlSql, visibility, jobId, taskId, - ddlType, true, extendParams, null, false, null, null); + ddlType, true, extendParams, null, false, null, null, null, null, false); + cdcManager.notifyDdl(context); + } + + public void notifySequenceDdl(String schemaName, String tableName, String sqlKind, String ddlSql, DdlType ddlType, + Long jobId, + Long taskId, + CdcDdlMarkVisibility visibility, + Map extendParams) { + CdcDDLContext context = new CdcDDLContext(schemaName, tableName, sqlKind, ddlSql, visibility, jobId, taskId, + ddlType, true, extendParams, null, false, null, null, null, null, true); cdcManager.notifyDdl(context); } @@ -132,7 +142,7 @@ public void notifyDdlNew(String schemaName, String tableName, String sqlKind, St Long jobId, Long taskId, CdcDdlMarkVisibility visibility, Map extendParams, boolean isRefreshTableMetaInfo, Map> newTableTopology) { CdcDDLContext context = new CdcDDLContext(schemaName, tableName, sqlKind, ddlSql, visibility, jobId, taskId, - ddlType, true, extendParams, null, isRefreshTableMetaInfo, newTableTopology, null); + ddlType, true, extendParams, null, isRefreshTableMetaInfo, newTableTopology, null, null, null, false); cdcManager.notifyDdl(context); } @@ -142,7 +152,8 @@ public void notifyDdlNew(String schemaName, String tableName, String sqlKind, St boolean isRefreshTableMetaInfo, Map> newTableTopology, Pair cdcMetaPair) { CdcDDLContext context = new CdcDDLContext(schemaName, tableName, sqlKind, ddlSql, visibility, jobId, taskId, - ddlType, true, extendParams, null, isRefreshTableMetaInfo, newTableTopology, cdcMetaPair); + ddlType, true, extendParams, null, isRefreshTableMetaInfo, newTableTopology, cdcMetaPair, null, null, + false); cdcManager.notifyDdl(context); } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/ICdcManager.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/ICdcManager.java index fbead4d47..d6017b0b4 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/ICdcManager.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/ICdcManager.java @@ -64,14 +64,17 @@ public interface ICdcManager { String CDC_ORIGINAL_DDL = "original_ddl"; String CDC_IS_GSI = "CDC_IS_GSI"; + String CDC_IS_CCI = "CDC_IS_CCI"; String CDC_GSI_PRIMARY_TABLE = "CDC_GSI_PRIMARY_TABLE"; String CDC_GROUP_NAME = "cdc_group_name"; String CDC_ACTUAL_ALTER_TABLE_GROUP_FLAG = "cdc_actual_alter_table_group_flag"; String CDC_TABLE_GROUP_MANUAL_CREATE_FLAG = "cdc_table_group_manual_create_flag"; String CDC_DDL_SCOPE = "cdc_ddl_scope"; String POLARDBX_SERVER_ID = "polardbx_server_id"; + String SQL_LOG_BIN = "sql_log_bin"; String DDL_ID = "DDL_ID"; String EXCHANGE_NAMES_MAPPING = "EXCHANGE_NAMES_MAPPING"; + String CDC_MARK_RECORD_COMMIT_TSO = "cdc_mark_record_commit_tso"; /** * 发送Cdc通用指令 diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/RplConstants.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/RplConstants.java index aa2c3cc9f..64e7aa95f 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/RplConstants.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/RplConstants.java @@ -31,4 +31,6 @@ public class RplConstants { public static final String RPL_FULL_VALID_DB = "dbName"; public static final String RPL_FULL_VALID_TB = "tbName"; + + public static final String RPL_FULL_VALID_MODE = "mode"; } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/entity/DDLExtInfo.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/entity/DDLExtInfo.java index 5b7d24cd7..756cc998b 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/entity/DDLExtInfo.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/cdc/entity/DDLExtInfo.java @@ -19,6 +19,9 @@ import com.alibaba.polardbx.common.cdc.DdlScope; import lombok.Getter; +import java.util.HashMap; +import java.util.Map; + /** * Created by ziyang.lb **/ @@ -52,6 +55,7 @@ public class DDLExtInfo { private String sqlMode = null; private String originalDdl = null; private Boolean isGsi = false; + private Boolean isCci = false; private String groupName = null; @Getter private Boolean foreignKeysDdl = false; @@ -64,6 +68,8 @@ public class DDLExtInfo { @Getter private Long ddlId; + private Map polarxVariables = new HashMap<>(); + public Long getTaskId() { return taskId; } @@ -128,6 +134,14 @@ public void setGsi(Boolean gsi) { isGsi = gsi; } + public Boolean getCci() { + return isCci; + } + + public void setCci(Boolean cci) { + isCci = cci; + } + public String getGroupName() { return groupName; } @@ -171,4 +185,12 @@ public void setEnableImplicitTableGroup(boolean enableImplicitTableGroup) { public void setDdlId(Long ddlId) { this.ddlId = ddlId; } + + public Map getPolarxVariables() { + return polarxVariables; + } + + public void addPolarxVariable(String key, Object value) { + this.polarxVariables.put(key, value); + } } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/charset/CollationName.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/charset/CollationName.java index ae9e8574d..4b56bc67a 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/charset/CollationName.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/charset/CollationName.java @@ -640,6 +640,9 @@ public static CollationName defaultNumericCollation() { .put(new MixCollationKey(UTF8_BIN, LATIN1_SPANISH_CI), UTF8_BIN) .put(new MixCollationKey(UTF8_BIN, BIG5_BIN), UTF8_BIN) .put(new MixCollationKey(UTF8_BIN, BIG5_CHINESE_CI), UTF8_BIN) + .put(new MixCollationKey(UTF8_BIN, UTF8_GENERAL_CI), UTF8_BIN) + .put(new MixCollationKey(UTF8_BIN, UTF8_UNICODE_CI), UTF8_BIN) + .put(new MixCollationKey(UTF8_BIN, UTF8_GENERAL_MYSQL500_CI), UTF8_BIN) .put(new MixCollationKey(UTF8_UNICODE_CI, UTF8MB4_GENERAL_CI), UTF8MB4_GENERAL_CI) .put(new MixCollationKey(UTF8_UNICODE_CI, UTF8MB4_BIN), UTF8MB4_BIN) .put(new MixCollationKey(UTF8_UNICODE_CI, UTF8MB4_UNICODE_CI), UTF8MB4_UNICODE_CI) @@ -683,7 +686,6 @@ public static CollationName defaultNumericCollation() { .put(new MixCollationKey(UTF8MB4_GENERAL_CI, LATIN1_SPANISH_CI), UTF8MB4_GENERAL_CI) .put(new MixCollationKey(UTF8MB4_GENERAL_CI, BIG5_BIN), UTF8MB4_GENERAL_CI) .put(new MixCollationKey(UTF8MB4_GENERAL_CI, BIG5_CHINESE_CI), UTF8MB4_GENERAL_CI) - .put(new MixCollationKey(UTF8MB4_BIN, UTF8MB4_GENERAL_CI), UTF8MB4_BIN) .put(new MixCollationKey(UTF8MB4_BIN, UTF16LE_GENERAL_CI), UTF16LE_GENERAL_CI) .put(new MixCollationKey(UTF8MB4_BIN, UTF16LE_BIN), UTF16LE_BIN) .put(new MixCollationKey(UTF8MB4_BIN, ASCII_GENERAL_CI), UTF8MB4_BIN) @@ -704,6 +706,11 @@ public static CollationName defaultNumericCollation() { .put(new MixCollationKey(UTF8MB4_BIN, LATIN1_SPANISH_CI), UTF8MB4_BIN) .put(new MixCollationKey(UTF8MB4_BIN, BIG5_BIN), UTF8MB4_BIN) .put(new MixCollationKey(UTF8MB4_BIN, BIG5_CHINESE_CI), UTF8MB4_BIN) + .put(new MixCollationKey(UTF8MB4_BIN, UTF8MB4_GENERAL_CI), UTF8MB4_BIN) + .put(new MixCollationKey(UTF8MB4_BIN, UTF8MB4_UNICODE_CI), UTF8MB4_BIN) + .put(new MixCollationKey(UTF8MB4_BIN, UTF8MB4_UNICODE_520_CI), UTF8MB4_BIN) + .put(new MixCollationKey(UTF8MB4_BIN, UTF8MB4_0900_AI_CI), UTF8MB4_BIN) + .put(new MixCollationKey(UTF8MB4_BIN, UTF8MB4_ZH_0900_AS_CS), UTF8MB4_BIN) .put(new MixCollationKey(UTF8MB4_UNICODE_CI, UTF16LE_GENERAL_CI), UTF16LE_GENERAL_CI) .put(new MixCollationKey(UTF8MB4_UNICODE_CI, UTF16LE_BIN), UTF16LE_BIN) .put(new MixCollationKey(UTF8MB4_UNICODE_CI, ASCII_GENERAL_CI), UTF8MB4_UNICODE_CI) @@ -764,6 +771,8 @@ public static CollationName defaultNumericCollation() { .put(new MixCollationKey(UTF16_BIN, LATIN1_SPANISH_CI), UTF16_BIN) .put(new MixCollationKey(UTF16_BIN, BIG5_BIN), UTF16_BIN) .put(new MixCollationKey(UTF16_BIN, BIG5_CHINESE_CI), UTF16_BIN) + .put(new MixCollationKey(UTF16_BIN, UTF16_GENERAL_CI), UTF16_BIN) + .put(new MixCollationKey(UTF16_BIN, UTF16_UNICODE_CI), UTF16_BIN) .put(new MixCollationKey(UTF16_UNICODE_CI, UTF16LE_GENERAL_CI), UTF16LE_GENERAL_CI) .put(new MixCollationKey(UTF16_UNICODE_CI, UTF16LE_BIN), UTF16LE_BIN) .put(new MixCollationKey(UTF16_UNICODE_CI, ASCII_GENERAL_CI), UTF16_UNICODE_CI) @@ -826,6 +835,7 @@ public static CollationName defaultNumericCollation() { .put(new MixCollationKey(UTF16LE_BIN, LATIN1_SPANISH_CI), UTF16LE_BIN) .put(new MixCollationKey(UTF16LE_BIN, BIG5_BIN), UTF16LE_BIN) .put(new MixCollationKey(UTF16LE_BIN, BIG5_CHINESE_CI), UTF16LE_BIN) + .put(new MixCollationKey(UTF16LE_BIN, UTF16LE_GENERAL_CI), UTF16LE_BIN) .put(new MixCollationKey(UTF32_GENERAL_CI, ASCII_GENERAL_CI), UTF32_GENERAL_CI) .put(new MixCollationKey(UTF32_GENERAL_CI, ASCII_BIN), UTF32_GENERAL_CI) .put(new MixCollationKey(UTF32_GENERAL_CI, BINARY), BINARY) @@ -862,6 +872,8 @@ public static CollationName defaultNumericCollation() { .put(new MixCollationKey(UTF32_BIN, LATIN1_SPANISH_CI), UTF32_BIN) .put(new MixCollationKey(UTF32_BIN, BIG5_BIN), UTF32_BIN) .put(new MixCollationKey(UTF32_BIN, BIG5_CHINESE_CI), UTF32_BIN) + .put(new MixCollationKey(UTF32_BIN, UTF32_GENERAL_CI), UTF32_BIN) + .put(new MixCollationKey(UTF32_BIN, UTF32_UNICODE_CI), UTF32_BIN) .put(new MixCollationKey(UTF32_UNICODE_CI, ASCII_GENERAL_CI), UTF32_UNICODE_CI) .put(new MixCollationKey(UTF32_UNICODE_CI, ASCII_BIN), UTF32_UNICODE_CI) .put(new MixCollationKey(UTF32_UNICODE_CI, BINARY), BINARY) @@ -901,7 +913,6 @@ public static CollationName defaultNumericCollation() { // should be compatible with it. .put(new MixCollationKey(UTF8MB4_0900_AI_CI, UTF8MB4_GENERAL_CI), UTF8MB4_0900_AI_CI) .put(new MixCollationKey(UTF8MB4_0900_AI_CI, UTF8MB4_UNICODE_CI), UTF8MB4_0900_AI_CI) - .put(new MixCollationKey(UTF8MB4_0900_AI_CI, UTF8MB4_BIN), UTF8MB4_BIN) .put(new MixCollationKey(UTF8MB4_0900_AI_CI, UTF8_GENERAL_CI), UTF8MB4_0900_AI_CI) .put(new MixCollationKey(UTF8MB4_0900_AI_CI, UTF8_BIN), UTF8MB4_0900_AI_CI) .put(new MixCollationKey(UTF8MB4_0900_AI_CI, UTF8_UNICODE_CI), UTF8MB4_0900_AI_CI) @@ -960,6 +971,18 @@ public static CollationName defaultNumericCollation() { .put(new MixCollationKey(UTF8MB4_UNICODE_520_CI, LATIN1_SPANISH_CI), UTF8MB4_UNICODE_520_CI) .put(new MixCollationKey(UTF8MB4_UNICODE_520_CI, BIG5_BIN), UTF8MB4_UNICODE_520_CI) .put(new MixCollationKey(UTF8MB4_UNICODE_520_CI, BIG5_CHINESE_CI), UTF8MB4_UNICODE_520_CI) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_SWEDISH_CI), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_GERMAN1_CI), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_DANISH_CI), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_GERMAN2_CI), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_GENERAL_CI), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_GENERAL_CS), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_SPANISH_CI), LATIN1_BIN) + .put(new MixCollationKey(GB18030_BIN, GB18030_UNICODE_520_CI), GB18030_BIN) + .put(new MixCollationKey(GB18030_BIN, GB18030_CHINESE_CI), GB18030_BIN) + .put(new MixCollationKey(ASCII_BIN, ASCII_GENERAL_CI), ASCII_BIN) + .put(new MixCollationKey(GBK_BIN, GBK_CHINESE_CI), GBK_BIN) + .put(new MixCollationKey(BIG5_BIN, BIG5_CHINESE_CI), BIG5_BIN) .build(); private static class MixCollationKey { diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/columnar/ColumnarOption.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/columnar/ColumnarOption.java new file mode 100644 index 000000000..fd29772c8 --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/columnar/ColumnarOption.java @@ -0,0 +1,89 @@ +package com.alibaba.polardbx.common.columnar; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; + +import java.util.function.Consumer; + +/** + * @author yaozhili + */ +public class ColumnarOption { + private final String key; + private final String defaultValue; + private final String description; + private final Consumer setIndex; + private final Consumer setGlobal; + private final Consumer validator; + + /** + * @param key option key + * @param defaultValue default value of this option + * @param description description of this option + * @param setIndex Define what will be done when an index option is set. An exception should be thrown if fails. + * Null means this option is immutable, and should be declared when index is created, and set index option is not supported. + * @param setGlobal Define what will be done when a global option is set. An exception should be thrown if fails. + * Null means set global option is not supported. + * @param validator Validate the setting value. Throw an exception if fail to validate. + */ + public ColumnarOption(String key, String defaultValue, String description, + Consumer setIndex, + Consumer setGlobal, + Consumer validator) { + this.key = key; + this.defaultValue = defaultValue; + this.description = description; + this.setIndex = setIndex; + this.setGlobal = setGlobal; + this.validator = validator; + } + + public void handle(Param param) { + if (null == setGlobal && null == setIndex) { + throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, param.key.toUpperCase() + + " is not supported to set dynamically."); + } + if (null != validator) { + validator.accept(param); + } + if (null == param.tableId || 0 == param.tableId) { + if (null == setGlobal) { + throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, param.key.toUpperCase() + + " is not supported to set global, please specify a particular columnar index."); + } + setGlobal.accept(param); + } else { + if (null == setIndex) { + throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, param.key.toUpperCase() + + " is not supported to set for a particular index, " + + "please call columnar_config_set(key, value) to set a global config."); + } + setIndex.accept(param); + } + } + + public String getDefault() { + return defaultValue; + } + + public static class Param { + public String key; + public String value; + public String schemaName; + public String tableName; + public String indexName; + public Long tableId; + public Object serverConnection; + + public Param shallowCopy() { + Param newParam = new Param(); + newParam.key = this.key; + newParam.value = this.value; + newParam.schemaName = this.schemaName; + newParam.tableName = this.tableName; + newParam.indexName = this.indexName; + newParam.tableId = this.tableId; + return newParam; + } + } +} diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/columnar/ColumnarUtils.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/columnar/ColumnarUtils.java new file mode 100644 index 000000000..30acd2bf9 --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/columnar/ColumnarUtils.java @@ -0,0 +1,35 @@ +package com.alibaba.polardbx.common.columnar; + +import com.alibaba.polardbx.common.cdc.CdcDDLContext; +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.common.ddl.newengine.DdlType; + +import java.util.HashMap; +import java.util.Map; + +import static com.alibaba.polardbx.common.cdc.ICdcManager.CDC_MARK_RECORD_COMMIT_TSO; +import static com.alibaba.polardbx.common.cdc.ICdcManager.DDL_ID; + +public class ColumnarUtils { + + /** + * 添加cdc打标事件,默认DdlType.IGNORED标记,后续cdc检测到该类打标,可以优化处理,不会改变元数据 + * + * @param sql 打标sql + * @return tso + */ + public static Long AddCDCMarkEvent(String sql, String sqlKind) { + Map params = new HashMap<>(); + params.put(CDC_MARK_RECORD_COMMIT_TSO, "true"); + //打标信息metadb会记录DDL_ID,但是没有应用到事件中 + params.put(DDL_ID, 1L); + + CdcDDLContext context = new CdcDDLContext("polardbx", "polardbx_function", sqlKind, + sql, CdcDdlMarkVisibility.Protected, null, null, + DdlType.IGNORED, true, params, null, false, null, null, null, null, false); + CdcManagerHelper.getInstance().notifyDdlWithContext(context); + + return context.getCommitTso(); + } +} diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/ServerVariables.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/ServerVariables.java index 426149b6b..8ee3e6071 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/ServerVariables.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/ServerVariables.java @@ -68,9 +68,18 @@ public class ServerVariables { ConnectionProperties.ENABLE_TRX_IDLE_TIMEOUT_TASK, ConnectionProperties.TRX_IDLE_TIMEOUT_TASK_INTERVAL); + public static final Set MODIFIABLE_SYNC_POINT_PARAM = ImmutableSet.of( + ConnectionProperties.ENABLE_SYNC_POINT, + ConnectionProperties.SYNC_POINT_TASK_INTERVAL); + public static final Set MODIFIABLE_TIMER_TASK_PARAM; + public static final String ENABLE_POLARX_SYNC_POINT = "enable_polarx_sync_point"; + static { + variables.add(ENABLE_POLARX_SYNC_POINT); + variables.add("opt_flashback_area"); + variables.add("innodb_txn_retention"); variables.add("activate_all_roles_on_login"); variables.add("admin_address"); variables.add("admin_port"); @@ -1048,7 +1057,9 @@ public class ServerVariables { variables.add("warning_count"); variables.add("weak_consensus_mode"); variables.add("windowing_use_high_precision"); + variables.add("polarx_sync_point_timeout"); variables.add("xa_detach_on_prepare"); + variables.add("innodb_rds_faster_ddl"); readonlyVariables.add("audit_log_current_session"); readonlyVariables.add("audit_log_filter_id"); @@ -1231,6 +1242,8 @@ public class ServerVariables { readonlyVariables.add("warning_count"); readonlyVariables.add("version_tokens_session_number"); + writableVariables.add("opt_flashback_area"); + writableVariables.add("innodb_txn_retention"); writableVariables.add("auto_increment_increment"); writableVariables.add("auto_increment_offset"); writableVariables.add("autocommit"); @@ -1642,6 +1655,9 @@ public class ServerVariables { mysqlBothVariables.add("wait_timeout"); mysqlBothVariables.add("windowing_use_high_precision"); mysqlBothVariables.add("xa_detach_on_prepare"); + + mysqlGlobalVariables.add("opt_flashback_area"); + mysqlGlobalVariables.add("innodb_txn_retention"); mysqlGlobalVariables.add("Ndb_conflict_last_conflict_epoch"); mysqlGlobalVariables.add("Ndb_replica_max_replicated_epoch"); mysqlGlobalVariables.add("Ndb_slave_max_replicated_epoch"); @@ -2649,6 +2665,9 @@ public class ServerVariables { mysqlGlobalVariables.add("version_compile_os"); mysqlGlobalVariables.add("version_compile_zlib"); mysqlGlobalVariables.add("weak_consensus_mode"); + mysqlGlobalVariables.add(ENABLE_POLARX_SYNC_POINT); + mysqlGlobalVariables.add("polarx_sync_point_timeout"); + mysqlSessionVariables.add("debug_sync"); mysqlSessionVariables.add("error_count"); mysqlSessionVariables.add("external_user"); @@ -2681,6 +2700,11 @@ public class ServerVariables { mysqlSessionVariables.add("transaction_allow_batching"); mysqlSessionVariables.add("use_secondary_engine"); mysqlSessionVariables.add("warning_count"); + + mysqlDynamicVariables.add("polarx_sync_point_timeout"); + mysqlDynamicVariables.add(ENABLE_POLARX_SYNC_POINT); + mysqlDynamicVariables.add("opt_flashback_area"); + mysqlDynamicVariables.add("innodb_txn_retention"); mysqlDynamicVariables.add("activate_all_roles_on_login"); mysqlDynamicVariables.add("admin_ssl_ca"); mysqlDynamicVariables.add("admin_ssl_capath"); @@ -3592,6 +3616,9 @@ public class ServerVariables { globalBannedVariables.add("auto_increment_increment"); globalBannedVariables.add("super_write"); + // 禁止全局设置: + globalBannedVariables.add("file_list"); + ImmutableSet.Builder modifiableTimerTaskVarBuilder = new ImmutableSet.Builder<>(); for (String modifiableTimerTaskParam : MODIFIABLE_PURGE_TRANS_PARAM) { @@ -3609,6 +3636,10 @@ public class ServerVariables { for (String modifiableTimerTaskParam : MODIFIABLE_TRX_IDLE_TIMEOUT_PARAM) { modifiableTimerTaskVarBuilder.add(modifiableTimerTaskParam); } + + for (String modifiableTimerTaskParam : MODIFIABLE_SYNC_POINT_PARAM) { + modifiableTimerTaskVarBuilder.add(modifiableTimerTaskParam); + } MODIFIABLE_TIMER_TASK_PARAM = modifiableTimerTaskVarBuilder.build(); } @@ -3668,7 +3699,7 @@ public static boolean isGlobalBanned(String variable) { return globalBannedVariables.contains(variable.toLowerCase()); } - public static boolean isGlobalBlackList(String variable) { + public static boolean isVariablesBlackList(String variable) { return DynamicConfig.getInstance().getBlacklistConf().contains(variable.toLowerCase()); } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/SystemTables.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/SystemTables.java index b2a8cd6c6..1d7add075 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/SystemTables.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/SystemTables.java @@ -75,6 +75,19 @@ public class SystemTables { public static final String DRDS_SYSTABLE_VIEW = "__drds__systable__view__"; public static final String DRDS_SYSTEM_SCALEOUT_OUTLINE = "__drds__systable__scaleout__outline__"; public static final String DRDS_SYSTEM_SCALEOUT_BACKFILL_OBJECTS = "__drds__systable__scaleout__backfill_objects__"; + public static final String DRDS_SYSTABLE_SCALEOUT_CHECKER_REPORTS = "__drds__systable__scaleout_checker_reports__"; + + //record all nodes for mpp + public static final String DRDS_NODEINFO_TABLE_NAME = "__drds__nodestatus__"; + + + // Sync point table. + public static final String POLARDBX_SYNC_POINT_TB = "__polardbx_sync_point__"; + + //~----------- Depreciated Tables ----------- + + public static final String DRDS__SYSTEM__OUTLINE = "__drds__system__outline__"; + public static final String DRDS_SYSTEM_FAILED_DDL = "__drds__system__failed__ddl__"; static { Set systemTableSet = new HashSet<>(); @@ -106,6 +119,10 @@ public class SystemTables { register(systemTableSet, DRDS_SYSTEM_SCALEOUT_BACKFILL_OBJECTS); register(systemTableSet, DRDS_SYSTABLE_VIEW); register(systemTableSet, DRDS_SYSTABLE_LOCKING_FUNCTION); + register(systemTableSet, POLARDBX_GLOBAL_TX_LOG_TABLE_PREFIX); + register(systemTableSet, POLARDBX_GLOBAL_TX_LOG_TABLE_ARCHIVE_TABLE); + register(systemTableSet, POLARDBX_SYNC_POINT_TB); + try { // magic number 512 // Test after adding SystemTables diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/TransactionAttribute.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/TransactionAttribute.java index 0bb0df180..574ebc425 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/TransactionAttribute.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/constants/TransactionAttribute.java @@ -21,6 +21,39 @@ import java.util.concurrent.atomic.AtomicLong; public class TransactionAttribute { + public enum FormatId { + NORMAL(1), + RECOVER(2), + ARCHIVE(3), + IGNORE_BINLOG(4), + TSO_OPT_SR(5), + TSO_OPT(6), + ASYNC_COMMIT(7); + + private final int id; + + FormatId(int id) { + this.id = id; + } + + public int id() { + return id; + } + + public static FormatId fromId(int id) { + for (FormatId formatId : FormatId.values()) { + if (formatId.id == id) { + return formatId; + } + } + return null; + } + + public static boolean isUserTransaction(int id) { + return id == NORMAL.id || id == ARCHIVE.id || id == IGNORE_BINLOG.id || id == TSO_OPT_SR.id + || id == TSO_OPT.id || id == ASYNC_COMMIT.id; + } + } public static final IsolationLevel DEFAULT_ISOLATION_LEVEL = IsolationLevel.READ_COMMITTED; @@ -32,6 +65,15 @@ public class TransactionAttribute { public static final ITransactionPolicy DEFAULT_TRANSACTION_POLICY_MYSQL56 = ITransactionPolicy.ALLOW_READ_CROSS_DB; + /** + * Default Transaction Policy for PolarDB-X Instances CDC to ignore all binlog events + */ + public static final ITransactionPolicy DEFAULT_IGNORE_BINLOG_TRANSACTION = + ITransactionPolicy.IGNORE_BINLOG_TRANSACTION; + + /** + * DRDS 事务策略 + */ public static final String DRDS_TRANSACTION_POLICY = "drds_transaction_policy"; public static final String SHARE_READ_VIEW = "share_read_view"; @@ -83,7 +125,7 @@ public class TransactionAttribute { public static final int DEFAULT_COLUMNAR_TSO_PURGE_INTERVAL = 60000; /** - * Default Columnar TSO update Interval in milliseconds: 10 seconds + * Default Columnar TSO update Interval in milliseconds: 3 seconds */ public static final int DEFAULT_COLUMNAR_TSO_UPDATE_INTERVAL = 3000; diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/datatype/Decimal.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/datatype/Decimal.java index 719cd3881..4046f0b1c 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/datatype/Decimal.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/datatype/Decimal.java @@ -157,7 +157,7 @@ public Decimal multiply(Decimal d) { public Decimal divide(Decimal d) { DecimalStructure to = new DecimalStructure(); FastDecimalUtils - .div(this.decimalStructure, d.decimalStructure, to, DecimalStructure.DIV_PRECISION_INCREMENT_DEFAULT, true); + .div(this.decimalStructure, d.decimalStructure, to, DecimalStructure.getDefaultDivPrecisionIncrement(), true); return new Decimal(to); } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/datatype/DecimalTypeBase.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/datatype/DecimalTypeBase.java index 1f1b136f7..05f8b1662 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/datatype/DecimalTypeBase.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/datatype/DecimalTypeBase.java @@ -16,11 +16,15 @@ package com.alibaba.polardbx.common.datatype; +import com.alibaba.polardbx.common.properties.DynamicConfig; + public class DecimalTypeBase { public static final int DEFAULT_SCALE = 0; // for divide precision. - public final static int DEFAULT_DIV_PRECISION_INCREMENT = 4; + public static int getDefaultDivPrecisionIncrement() { + return DynamicConfig.getInstance().getCnDivPrecisionIncrement(); + } public final static String DIV_PRECISION_INCREMENT = "div_precision_increment"; // decimal memory @@ -40,7 +44,6 @@ public class DecimalTypeBase { public static final int E_DEC_DEC64 = 32; public static final int E_DEC_DEC128 = 33; - public static final int DIV_PRECISION_INCREMENT_DEFAULT = 4; public static final byte[] BUFF_OFFSETS = { 0, 4, 8, 12, 16, 20, 24, 28, 32 }; @@ -98,6 +101,10 @@ public class DecimalTypeBase { public static int[] POW_10 = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + public static long[] POW_10_LONG = { + 1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, 100000000L, 1000000000L, 10000000000L, + 100000000000L, 1000000000000L}; + /** * Get the occupied bytes from digits (1~10). */ diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/Job.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/Job.java index 9d4cfb90e..233d3357f 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/Job.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/Job.java @@ -23,7 +23,8 @@ public enum JobSource { } public enum JobType { - UNSUPPORTED, CREATE_TABLE, ALTER_TABLE, DROP_TABLE, RENAME_TABLE, TRUNCATE_TABLE, CREATE_INDEX, DROP_INDEX, + UNSUPPORTED, CREATE_TABLE, ALTER_TABLE, DROP_TABLE, RENAME_TABLE, TRUNCATE_TABLE, OPTIMIZE_TABLE, CREATE_INDEX, + DROP_INDEX, CREATE_GLOBAL_INDEX, ALTER_GLOBAL_INDEX, DROP_GLOBAL_INDEX, RENAME_GLOBAL_INDEX, CHECK_GLOBAL_INDEX, CHECK_COLUMNAR_INDEX, MOVE_TABLE, ALTER_TABLEGROUP, DRAIN_NODE, ALTER_TABLE_SET_TABLEGROUP, ALTER_TABLEGROUP_ADD_TABLE, diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/newengine/DdlConstants.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/newengine/DdlConstants.java index 59abe6b4c..f39331356 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/newengine/DdlConstants.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/newengine/DdlConstants.java @@ -71,7 +71,7 @@ public class DdlConstants { public static final int MIN_LOGICAL_DDL_PARALLELISM = 1; public static final int MAX_LOGICAL_DDL_PARALLELISM = 16; - public static final int DEFAULT_LOGICAL_DDL_PARALLELISM = 4; + public static final int DEFAULT_LOGICAL_DDL_PARALLELISM = 8; public static final int MIN_ALLOWED_TABLE_SHARDS_PER_DB = 1; public static final int MAX_ALLOWED_TABLE_SHARDS_PER_DB = 65535; diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/newengine/DdlType.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/newengine/DdlType.java index a0a9f0e83..4e1a631a5 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/newengine/DdlType.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/ddl/newengine/DdlType.java @@ -63,12 +63,12 @@ public enum DdlType { ALTER_TABLEGROUP_ADD_TABLE, ALTER_TABLE_RENAME_PARTITION, - ALTER_TABLE_ADD_COLUMN, - ALTER_TABLE_DROP_COLUMN, - ALTER_TABLE_MODIFY_COLUMN, - ALTER_TABLE_CHANGE_COLUMN, + MERGE_TABLEGROUP, - MERGE_TABLEGROUP; + /** + * 忽略的ddl类型,实际不是ddl + */ + IGNORED; public enum AlterColumnSpecification { AlterColumnName, diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/eventlogger/EventLogger.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/eventlogger/EventLogger.java index 0941c2646..81573f13f 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/eventlogger/EventLogger.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/eventlogger/EventLogger.java @@ -16,16 +16,21 @@ package com.alibaba.polardbx.common.eventlogger; +import com.alibaba.polardbx.common.constants.TransactionAttribute; import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import java.util.concurrent.atomic.AtomicLong; + public class EventLogger { private final static Logger logger = LoggerFactory.getLogger("event", true); private final static String LOG_FORMAT = "%s %s %s"; + public static final AtomicLong LAST_LOG_CCI_SNAPSHOT = new AtomicLong(0); + public static void log(EventType type, String msg) { if (EventType.isTrxEvent(type) && !DynamicConfig.getInstance().isEnableTrxEventLog()) { return; @@ -33,4 +38,16 @@ public static void log(EventType type, String msg) { String logContent = String.format(LOG_FORMAT, type.getLevel().name(), type.name(), msg); logger.info(logContent); } + + public static void logCciSnapshot(long num) { + long lastLogTime = LAST_LOG_CCI_SNAPSHOT.get(); + if (shouldWriteEventLog(lastLogTime) && LAST_LOG_CCI_SNAPSHOT.compareAndSet(lastLogTime, System.nanoTime())) { + EventLogger.log(EventType.CCI_SNAPSHOT, "Found " + num + " cci snapshots"); + } + } + + public static boolean shouldWriteEventLog(long lastLogTime) { + // Write event log every 7 * 24 hours. + return lastLogTime == 0 || ((System.nanoTime() - lastLogTime) / 1000000000) > 604800; + } } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/eventlogger/EventType.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/eventlogger/EventType.java index 61231da08..ded7f7c72 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/eventlogger/EventType.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/eventlogger/EventType.java @@ -24,6 +24,8 @@ public enum EventType { */ REBALANCE_INFO(EventLevel.INFO), + DDL_MPP_INFO(EventLevel.INFO), + /** * 用于统计一些DDL发生的次数 */ @@ -97,6 +99,15 @@ public enum EventType { INIT_OSS(EventLevel.INFO), CLOSE_OSS(EventLevel.INFO), + /** + * Usage statistics for TTL 2.0 + */ + CREATE_TTL_DEFINITION(EventLevel.INFO), + CREATE_TTL_DEFINITION_WITH_ARCHIVE_TABLE(EventLevel.INFO), + CREATE_CCI_ARCHIVE_TABLE(EventLevel.INFO), + DROP_CCI_ARCHIVE_TABLE(EventLevel.INFO), + CLEANUP_EXPIRED_DATA(EventLevel.INFO), + OPTIMIZER_ALERT(EventLevel.INFO), AUTO_SP(EventLevel.INFO), @@ -107,7 +118,9 @@ public enum EventType { TRX_RECOVER(EventLevel.INFO), TRX_INFO(EventLevel.INFO), TRX_ERR(EventLevel.INFO), - + COLUMNAR_ERR(EventLevel.INFO), + CCI_SNAPSHOT(EventLevel.INFO), + METRICS(EventLevel.INFO), CDC_WARN(EventLevel.WARN); private final EventLevel level; diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/exception/code/ErrorCode.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/exception/code/ErrorCode.java index d3512268e..bb33f12b6 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/exception/code/ErrorCode.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/exception/code/ErrorCode.java @@ -890,6 +890,8 @@ public enum ErrorCode { ERR_CREATE_SELECT_WITH_OSS(ErrorType.Executor, 4668), + ERR_CREATE_TABLE_WITH_TTL(ErrorType.Executor, 4710), + // ============= server 从4700下标开始================ ERR_SERVER(ErrorType.Server, 4700), @@ -955,6 +957,8 @@ public enum ErrorCode { // 事务超时 ERR_TRANS_IDLE_TIMEOUT(ErrorType.Transaction, 5016), + + ERR_FLASHBACK_AREA(ErrorType.Transaction, 5017), // ================权限相关异常从5101开始================== /** * 暂时不支持的权限点 @@ -1256,6 +1260,8 @@ public enum ErrorCode { ERR_REPLICA_NOT_SUPPORT(ErrorType.CDC, 9205), ERR_INSTANCE_READ_ONLY_OPTION_SET_FAILED(ErrorType.CDC, 9206), + ERR_CDC_INVALID_PARAMS(ErrorType.CDC, 9207), + ERR_SQL_LOG_BIN_NOT_SUPPORT_AUTO_COMMIT(ErrorType.CDC, 9208), ERR_PARTITION_MANAGEMENT(ErrorType.Executor, 9300), @@ -1306,6 +1312,13 @@ public enum ErrorCode { ERR_REDUNDANCY_SUBPARTITION_DEFINITION(ErrorType.Executor, 9339), ERR_AUTO_CREATE_TABLEGROUP(ErrorType.Executor, 9340), + // ============= TTL Exceptions, Error Code from 9380 ~ 9399 ================ + ERR_TTL(ErrorType.Executor, 9380), + ERR_TTL_INTERRUPTED(ErrorType.Executor, 9381), + ERR_TTL_TABLE_NOT_FOUND(ErrorType.Executor, 9382), + ERR_TTL_COLUMN_NOT_FOUND(ErrorType.Executor, 9383), + ERR_TTL_PARAMS(ErrorType.Executor, 9384), + // ============= 私有协议 从10000下标开始================ ERR_X_PROTOCOL_BAD_PACKET(ErrorType.Xprotocol, 10000), @@ -1341,7 +1354,11 @@ public enum ErrorCode { ERR_LOAD_DEL_FILE(ErrorType.ColumnarAccess, 12003), ERR_LOAD_ORC_FILE(ErrorType.ColumnarAccess, 12004), ERR_COLUMNAR_SNAPSHOT(ErrorType.GMS, 12005), - ERR_COLUMNAR_SCHEMA(ErrorType.GMS, 12006); + ERR_COLUMNAR_SCHEMA(ErrorType.GMS, 12006), + + ERR_COLUMNAR_DROP_PARTITION(ErrorType.Executor, 12011), + ERR_COLUMNAR_MODIFY_PARTITION_DROP_VALUE(ErrorType.Executor, 12012), + ERR_COLUMNAR_TRUNCATE_PARTITION(ErrorType.Executor, 12013); private static final String errorMessagePre = "ERR-CODE: [PXC-"; private final int code; diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/IConnection.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/IConnection.java index d17a25162..0eeb8c7da 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/IConnection.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/IConnection.java @@ -19,6 +19,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Statement; import java.util.Map; import java.util.concurrent.Executor; @@ -113,4 +114,22 @@ default int getShareReadViewSeq() { void discard(Throwable t); void kill() throws SQLException; + + default IConnection enableFlashbackArea(boolean enable) throws SQLException { + if (enable) { + this.executeLater("SET query_via_flashback_area = 1"); + } + return this; + } + + default void disableFlashbackArea() throws SQLException { + try (Statement stmt = createStatement()) { + stmt.execute("SET query_via_flashback_area = 0"); + } catch (Throwable t) { + // For safety, discard connection. + discard(t); + throw t; + } + } + } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ITransactionPolicy.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ITransactionPolicy.java index efa20b327..c4d515a51 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ITransactionPolicy.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ITransactionPolicy.java @@ -18,7 +18,6 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; -import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.TStringUtil; import java.util.EnumSet; @@ -44,7 +43,7 @@ enum TransactionClass { AUTO_COMMIT_SINGLE_SHARD, /** - * XA transaction with Commit TimeStamp. + * XA transaction with TSO as commit_seq. */ XA_TSO, @@ -70,7 +69,8 @@ enum TransactionClass { AUTO_COMMIT_TSO, - ARCHIVE; + ARCHIVE, + IGNORE_BINLOG_TRANSACTION; public boolean isA(EnumSet set) { return set.contains(this); @@ -83,7 +83,8 @@ public boolean isA(EnumSet set) { TransactionClass.TSO_READONLY, TransactionClass.AUTO_COMMIT_SINGLE_SHARD, TSO_2PC_OPT, - TransactionClass.ARCHIVE); + TransactionClass.ARCHIVE, + TransactionClass.IGNORE_BINLOG_TRANSACTION); public static final EnumSet EXPLICIT_TRANSACTION = EnumSet .of(TransactionClass.XA, @@ -92,7 +93,8 @@ public boolean isA(EnumSet set) { TransactionClass.ALLOW_READ_CROSS_DB, TransactionClass.COBAR_STYLE, TSO_2PC_OPT, - TransactionClass.ARCHIVE); + TransactionClass.ARCHIVE, + TransactionClass.IGNORE_BINLOG_TRANSACTION); public static final EnumSet TSO_TRANSACTION = EnumSet .of(TransactionClass.TSO, @@ -116,7 +118,8 @@ public boolean isA(EnumSet set) { TransactionClass.XA_TSO, TransactionClass.TSO, TSO_2PC_OPT, - TransactionClass.ARCHIVE); + TransactionClass.ARCHIVE, + TransactionClass.IGNORE_BINLOG_TRANSACTION); public static final EnumSet SUPPORT_PARALLEL_GET_CONNECTION_TRANSACTION = EnumSet .of(TransactionClass.XA, @@ -126,7 +129,8 @@ public boolean isA(EnumSet set) { TransactionClass.AUTO_COMMIT_SINGLE_SHARD, TransactionClass.AUTO_COMMIT_TSO, TransactionClass.TSO_READONLY, - TransactionClass.ARCHIVE); + TransactionClass.ARCHIVE, + TransactionClass.IGNORE_BINLOG_TRANSACTION); public static final EnumSet ALLOW_GROUP_PARALLELISM_WITHOUT_SHARE_READVIEW_TRANSACTION = EnumSet.of(TransactionClass.AUTO_COMMIT, @@ -138,19 +142,24 @@ public boolean isA(EnumSet set) { NoTransaction NO_TRANSACTION = new NoTransaction(); DefaultPolicy XA = new DefaultPolicy(TransactionClass.XA); Tso TSO = new Tso(); - DefaultPolicy ARCHIVE = new DefaultPolicy(TransactionClass.ARCHIVE); - - TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly); - - default TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly, boolean isSingleShard) { - return getTransactionType(isAutoCommit, isReadOnly); - } + DefaultPolicy BEST_EFFORT = new DefaultPolicy(TransactionClass.BEST_EFFORT); + Archive ARCHIVE = new Archive(); + DefaultPolicy IGNORE_BINLOG_TRANSACTION = new DefaultPolicy(TransactionClass.IGNORE_BINLOG_TRANSACTION); + + /** + * If isAutoCommit is true but isForbidAutoCommitTrx is true, + * it means this session is in autocommit mode, + * but we will not create an autocommit transaction object. + */ + TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly, boolean isSingleShard, + boolean isForbidAutoCommitTrx); class Free implements ITransactionPolicy { @Override - public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly) { - if (isAutoCommit) { + public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly, boolean isSingleShard, + boolean isForbidAutoCommitTrx) { + if (isAutoCommit && !isForbidAutoCommitTrx) { return TransactionClass.AUTO_COMMIT; } @@ -166,8 +175,9 @@ public String toString() { class AllowRead implements ITransactionPolicy { @Override - public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly) { - if (isAutoCommit) { + public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly, boolean isSingleShard, + boolean isForbidAutoCommitTrx) { + if (isAutoCommit && !isForbidAutoCommitTrx) { return TransactionClass.AUTO_COMMIT; } @@ -181,19 +191,14 @@ public String toString() { } class Tso implements ITransactionPolicy { - @Override - public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly) { - return getTransactionType(isAutoCommit, isReadOnly, false); - } - - @Override - public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly, boolean isSingleShard) { + public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly, boolean isSingleShard, + boolean isForbidAutoCommitTrx) { if (isSingleShard && isReadOnly) { return TransactionClass.AUTO_COMMIT_SINGLE_SHARD; } else if (isReadOnly) { return TransactionClass.TSO_READONLY; - } else if (isAutoCommit && !DynamicConfig.getInstance().isForbidAutoCommitTrx()) { + } else if (isAutoCommit && !isForbidAutoCommitTrx) { return TransactionClass.AUTO_COMMIT; } else { return TransactionClass.TSO; @@ -209,7 +214,11 @@ public String toString() { class NoTransaction implements ITransactionPolicy { @Override - public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly) { + public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly, boolean isSingleShard, + boolean isForbidAutoCommitTrx) { + if (isForbidAutoCommitTrx) { + return TransactionClass.TSO; + } return TransactionClass.AUTO_COMMIT; } @@ -229,14 +238,10 @@ public DefaultPolicy(TransactionClass type) { this.auto = false; } - public DefaultPolicy(TransactionClass type, boolean auto) { - this.type = type; - this.auto = auto; - } - @Override - public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly) { - if (!auto && isAutoCommit && !DynamicConfig.getInstance().isForbidAutoCommitTrx()) { + public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly, boolean isSingleShard, + boolean isForbidAutoCommitTrx) { + if (!auto && isAutoCommit && !isForbidAutoCommitTrx) { return TransactionClass.AUTO_COMMIT; } return type; @@ -248,6 +253,20 @@ public String toString() { } } + class Archive implements ITransactionPolicy { + + @Override + public TransactionClass getTransactionType(boolean isAutoCommit, boolean isReadOnly, boolean isSingleShard, + boolean isForbidAutoCommitTrx) { + return TransactionClass.ARCHIVE; + } + + @Override + public String toString() { + return "ARCHIVE"; + } + } + static ITransactionPolicy of(String name) { if (TStringUtil.isEmpty(name)) { return null; @@ -269,6 +288,8 @@ static ITransactionPolicy of(String name) { return ITransactionPolicy.NO_TRANSACTION; case "ARCHIVE": return ITransactionPolicy.ARCHIVE; + case "IGNORE_BINLOG_TRANSACTION": + return ITransactionPolicy.IGNORE_BINLOG_TRANSACTION; default: throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, "Unknown transaction policy: " + name); } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ParameterContext.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ParameterContext.java index 50c70d4f8..a676bae12 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ParameterContext.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ParameterContext.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.common.jdbc; +import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -84,7 +85,12 @@ public String toString() { } else if (args[i] instanceof RawString) { buffer.append(((RawString) args[i]).display()); } else { - buffer.append(args[i]); + if (DynamicConfig.getInstance().isEnableChangeParamTypeByMeta() + && this.parameterMethod == ParameterMethod.setString) { + buffer.append("'").append(args[i]).append("'"); + } else { + buffer.append(args[i]); + } } if (i != args.length - 1) { buffer.append(", "); diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ShareReadViewPolicy.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ShareReadViewPolicy.java index 77a03c9f2..add1c5919 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ShareReadViewPolicy.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/jdbc/ShareReadViewPolicy.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.DynamicConfig; import java.sql.Connection; @@ -28,13 +29,16 @@ public enum ShareReadViewPolicy { DEFAULT; public static boolean supportTxIsolation(int isolationLevel) { - return isolationLevel == Connection.TRANSACTION_REPEATABLE_READ; + return isolationLevel == Connection.TRANSACTION_REPEATABLE_READ || + (DynamicConfig.getInstance().isEnableShareReadviewInRc() + && isolationLevel == Connection.TRANSACTION_READ_COMMITTED); } public static void checkTxIsolation(int isolationLevel) { - if (isolationLevel != Connection.TRANSACTION_REPEATABLE_READ) { + if (!supportTxIsolation(isolationLevel)) { throw new TddlRuntimeException(ErrorCode.ERR_TRANS, - "Share read view is only supported in repeatable-read."); + "Share read view is only supported in repeatable-read. " + + "Or in read-committed when ENABLE_SHARE_READVIEW_IN_RC is true."); } } } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/mock/MockStatus.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/mock/MockStatus.java new file mode 100644 index 000000000..0067944c6 --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/mock/MockStatus.java @@ -0,0 +1,13 @@ +package com.alibaba.polardbx.common.mock; + +public class MockStatus { + private static volatile boolean mock = false; + + public static boolean isMock() { + return mock; + } + + public static void setMock(boolean mock) { + MockStatus.mock = mock; + } +} diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/IDeltaReadOption.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/IDeltaReadOption.java new file mode 100644 index 000000000..52d44d23b --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/IDeltaReadOption.java @@ -0,0 +1,4 @@ +package com.alibaba.polardbx.common.oss; + +public interface IDeltaReadOption { +} diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/Constants.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/Constants.java index df9921746..126149800 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/Constants.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/Constants.java @@ -45,12 +45,12 @@ private Constants() { // Number of simultaneous connections to oss public static final String MAXIMUM_CONNECTIONS_KEY = "fs.oss.connection.maximum"; - public static final int MAXIMUM_CONNECTIONS_DEFAULT = 32; + public static final int MAXIMUM_CONNECTIONS_DEFAULT = 2048; // Connect to oss over ssl public static final String SECURE_CONNECTIONS_KEY = "fs.oss.connection.secure.enabled"; - public static final boolean SECURE_CONNECTIONS_DEFAULT = true; + public static final boolean SECURE_CONNECTIONS_DEFAULT = false; // Use a custom endpoint public static final String ENDPOINT_KEY = "fs.oss.endpoint"; diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/FSOSSInputStream.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/FSOSSInputStream.java new file mode 100644 index 000000000..346e94f2f --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/FSOSSInputStream.java @@ -0,0 +1,88 @@ +package com.alibaba.polardbx.common.oss.filesystem; + +import org.apache.hadoop.fs.FSInputStream; +import org.jetbrains.annotations.NotNull; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class FSOSSInputStream extends FSInputStream { + private final OSSFileSystemStore ossFileSystemStore; + private final String ossKeyPath; + + private final int bufferSize; + private InputStream inputStream; + + private final long contentLength; + private long pos; + + public FSOSSInputStream(OSSFileSystemStore ossFileSystemStore, String ossKeyPath, int bufferSize) { + this.ossFileSystemStore = ossFileSystemStore; + this.ossKeyPath = ossKeyPath; + this.bufferSize = bufferSize; + this.inputStream = new BufferedInputStream(ossFileSystemStore.retrieve(ossKeyPath, 0, -1), bufferSize); + this.pos = 0; + this.contentLength = ossFileSystemStore.getOssFileLength(ossKeyPath); + } + + @Override + public void seek(long pos) throws IOException { + if (pos < 0) { + return; + } + close(); + InputStream inputStream1 = + new BufferedInputStream(ossFileSystemStore.retrieve(ossKeyPath, pos, -1), bufferSize); + this.pos = pos; + this.inputStream = inputStream1; + } + + @Override + public long getPos() { + return pos; + } + + @Override + public boolean seekToNewSource(long targetPos) throws IOException { + throw new IOException("seekToNewSource is not supported!"); + } + + @Override + public int read() throws IOException { + int data = inputStream.read(); + pos++; + return data; + } + + @Override + public int read(byte @NotNull [] b) throws IOException { + int num = inputStream.read(b); + pos += num; + return num; + } + + @Override + public int read(byte @NotNull [] b, int off, int len) throws IOException { + int num = inputStream.read(b, off, len); + pos += num; + return num; + } + + @Override + public long skip(long n) throws IOException { + long num = inputStream.skip(n); + pos += num; + return num; + } + + @Override + public int available() throws IOException { + return (int) (contentLength - pos); + } + + @Override + public void close() throws IOException { + inputStream.close(); + } +} diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/GuavaFileSystemRateLimiter.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/GuavaFileSystemRateLimiter.java index e6cf41597..b8847a947 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/GuavaFileSystemRateLimiter.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/GuavaFileSystemRateLimiter.java @@ -16,7 +16,7 @@ package com.alibaba.polardbx.common.oss.filesystem; -import org.apache.curator.shaded.com.google.common.util.concurrent.RateLimiter; +import com.google.common.util.concurrent.RateLimiter; import java.io.IOException; import java.util.concurrent.TimeUnit; @@ -77,7 +77,7 @@ public void acquireRead(int permit) throws IOException { "read timeout for rate limiter: %s s with max rate: %s bytes/s", ACQUIRE_TIMEOUT_IN_SECOND, this.readRate) - ); + ); } } } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/OSSInputStream.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/OSSInputStream.java index 5b81ed1d5..8c93a8f3a 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/OSSInputStream.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/OSSInputStream.java @@ -49,6 +49,7 @@ public class OSSInputStream extends FSInputStream { private long contentLength; private long position; private long partRemaining; + private long latestPartSize; private byte[] buffer; private int maxReadAheadPartNumber; private long expectNextPos; @@ -109,7 +110,7 @@ private synchronized void reopen(long pos, long downloadPartSize) throws IOExcep } boolean isRandomIO = true; - if (pos == this.expectNextPos) { + if (pos == this.expectNextPos && partSize == latestPartSize) { isRandomIO = false; } else { //new seek, remove cache buffers if its byteStart is not equal to pos @@ -182,6 +183,7 @@ private synchronized void reopen(long pos, long downloadPartSize) throws IOExcep } position = pos; partRemaining = partSize; + latestPartSize = partSize; } /** diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/cache/FileMergeCacheManager.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/cache/FileMergeCacheManager.java index 20893e8c3..032136d62 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/cache/FileMergeCacheManager.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/oss/filesystem/cache/FileMergeCacheManager.java @@ -32,6 +32,7 @@ import com.alibaba.polardbx.common.Engine; import com.alibaba.polardbx.common.properties.FileConfig; +import com.alibaba.polardbx.common.utils.ConcurrentHashSet; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; @@ -50,7 +51,6 @@ import io.airlift.slice.SizeOf; import io.airlift.slice.Slice; import org.apache.hadoop.fs.Path; -import org.eclipse.jetty.util.ConcurrentHashSet; import java.io.Closeable; import java.io.File; diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/privilege/MySQLPrivilegesName.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/privilege/MySQLPrivilegesName.java new file mode 100644 index 000000000..314f0b274 --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/privilege/MySQLPrivilegesName.java @@ -0,0 +1,67 @@ +package com.alibaba.polardbx.common.privilege; + +public enum MySQLPrivilegesName { + ALTER("Alter", "Tables", "To alter the table"), + ALTER_ROUTINE("Alter routine", "Functions,Procedures", "To alter or drop stored functions/procedures"), + CREATE("Create", "Databases,Tables,Indexes", "To create new databases and tables"), + CREATE_ROUTINE("Create routine", "Databases", "To use CREATE FUNCTION/PROCEDURE"), + CREATE_TEMPORARY_TABLES("Create temporary tables", "Databases", "To use CREATE TEMPORARY TABLE"), + CREATE_VIEW("Create view", "Tables", "To create new views"), + CREATE_USER("Create user", "Server Admin", "To create new users"), + DELETE("Delete", "Tables", "To delete existing rows"), + DROP("Drop", "Databases,Tables", "To drop databases, tables, and views"), + EVENT("Event", "Server Admin", "To create, alter, drop and execute events"), + EXECUTE("Execute", "Functions,Procedures", "To execute stored routines"), + FILE("File", "File access on server", "To read and write files on the server"), + GRANT_OPTION("Grant option", "Databases,Tables,Functions,Procedures", + "To give to other users those privileges you possess"), + INDEX("Index", "Tables", "To create or drop indexes"), + INSERT("Insert", "Tables", "To insert data into tables"), + LOCK_TABLES("Lock tables", "Databases", "To use LOCK TABLES (together with SELECT privilege)"), + PROCESS("Process", "Server Admin", "To view the plain text of currently executing queries"), + PROXY("Proxy", "Server Admin", "To make proxy user possible"), + REFERENCES("References", "Databases,Tables", "To have references on tables"), + RELOAD("Reload", "Server Admin", "To reload or refresh tables, logs and privileges"), + REPLICATION_CLIENT("Replication client", "Server Admin", "To ask where the slave or master servers are"), + REPLICATION_SLAVE("Replication slave", "Server Admin", "To read binary log events from the master"), + SELECT("Select", "Tables", "To retrieve rows from table"), + SHOW_DATABASES("Show databases", "Server Admin", "To see all databases with SHOW DATABASES"), + SHOW_VIEW("Show view", "Tables", "To see views with SHOW CREATE VIEW"), + SHUTDOWN("Shutdown", "Server Admin", "To shut down the server"), + SUPER("Super", "Server Admin", "To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."), + TRIGGER("Trigger", "Tables", "To use triggers"), + CREATE_TABLESPACE("Create tablespace", "Server Admin", "To create/alter/drop tablespaces"), + UPDATE("Update", "Tables", "To update existing rows"), + USAGE("Usage", "Server Admin", "No privileges - allow connect only"); + + private final String privilege; + private final String context; + private final String comment; + + MySQLPrivilegesName(String privilege, String context, String comment) { + this.privilege = privilege; + this.context = context; + this.comment = comment; + } + + public String getPrivilege() { + return privilege; + } + + public String getContext() { + return context; + } + + public String getComment() { + return comment; + } + + @Override + public String toString() { + return "DatabasePrivilege{" + + "privilege='" + privilege + '\'' + + ", context='" + context + '\'' + + ", comment='" + comment + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/ColumnarConfig.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/ColumnarConfig.java new file mode 100644 index 000000000..8aac908ae --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/ColumnarConfig.java @@ -0,0 +1,39 @@ +package com.alibaba.polardbx.common.properties; + +import com.alibaba.polardbx.common.columnar.ColumnarOption; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; + +import java.util.Map; + +/** + * Declare options in ColumnarOptions, and define them in ColumnarConfigHandler. + * @author yaozhili + */ +public final class ColumnarConfig { + public static String DEFAULT = "DEFAULT"; + public static String SNAPSHOT = "SNAPSHOT"; + private static Map CONFIG = null; + + synchronized public static void init(Map config) { + CONFIG = config; + } + + public static ColumnarOption get(String k) { + return null == CONFIG ? null : CONFIG.get(k); + } + + public static String getValue(String key, Map indexConfig, Map globalConfig) { + String val = null; + if (null != indexConfig) { + val = indexConfig.get(key); + } + if (null == val && null != globalConfig) { + val = globalConfig.get(key); + } + if (null == val && CONFIG.containsKey(key)) { + val = CONFIG.get(key).getDefault(); + } + return val; + } +} diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/ConnectionParams.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/ConnectionParams.java index 64ad01c15..5561216c8 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/ConnectionParams.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/ConnectionParams.java @@ -296,6 +296,14 @@ public class ConnectionParams { Attribute.DEFAULT_PURE_ASYNC_DDL_MODE, false); + /** + * Label if return job_id on async_ddl_mode when submit ddl + */ + public static final BooleanConfigParam RETURN_JOB_ID_ON_ASYNC_DDL_MODE = + new BooleanConfigParam(ConnectionProperties.RETURN_JOB_ID_ON_ASYNC_DDL_MODE, + false, + false); + /** * Check if the "INSTANT ADD COLUMN" feature is supported. */ @@ -421,11 +429,49 @@ public class ConnectionParams { false, false); + /** + * 在事务时,DML忽略串行执行策略规则,详情请见ExecUtils.getQueryConcurrencyPolicy + */ + public final static BooleanConfigParam ENABLE_DML_GROUP_CONCURRENT_IN_TRANSACTION = new BooleanConfigParam( + ConnectionProperties.ENABLE_DML_GROUP_CONCURRENT_IN_TRANSACTION, + false, + true); + + /** + * 指定 DML 执行策略, PUSHDOWN, DETERMINISTIC_PUSHDOWN, LOGICAL + */ public final static StringConfigParam DML_EXECUTION_STRATEGY = new StringConfigParam( ConnectionProperties.DML_EXECUTION_STRATEGY, null, false); + /** + * 是否下推 WHERE 条件中包含目标表子查询的 DELETE/UPDATE 语句 + */ + public final static BooleanConfigParam DML_PUSH_MODIFY_WITH_SUBQUERY_CONDITION_OF_TARGET = new BooleanConfigParam( + ConnectionProperties.DML_PUSH_MODIFY_WITH_SUBQUERY_CONDITION_OF_TARGET, + true, + false); + + /** + * 是否禁止 SET 子句中包含子查询的 UPDATE 语句 + */ + public final static BooleanConfigParam DML_FORBID_UPDATE_WITH_SUBQUERY_IN_SET = new BooleanConfigParam( + ConnectionProperties.DML_FORBID_UPDATE_WITH_SUBQUERY_IN_SET, + true, + false); + + /** + * 是否禁止 SET 子句中包含子查询的 UPDATE 语句 下推执行, + */ + public final static BooleanConfigParam DML_FORBID_PUSH_DOWN_UPDATE_WITH_SUBQUERY_IN_SET = new BooleanConfigParam( + ConnectionProperties.DML_FORBID_PUSH_DOWN_UPDATE_WITH_SUBQUERY_IN_SET, + true, + false); + + /** + * 是否下推 INSERT IGNORE / REPLACE / UPSERT + */ public final static BooleanConfigParam DML_PUSH_DUPLICATE_CHECK = new BooleanConfigParam( ConnectionProperties.DML_PUSH_DUPLICATE_CHECK, true, @@ -462,6 +508,31 @@ public class ConnectionParams { true, false); + /** + * 是否使用 returning 优化包含 order by limit 的 update / delete + */ + public final static BooleanConfigParam OPTIMIZE_MODIFY_TOP_N_BY_RETURNING = new BooleanConfigParam( + ConnectionProperties.OPTIMIZE_MODIFY_TOP_N_BY_RETURNING, + false, + false); + + /** + * 是否使用 returning 优化需要逻辑执行的 DELETE + */ + public final static BooleanConfigParam OPTIMIZE_DELETE_BY_RETURNING = new BooleanConfigParam( + ConnectionProperties.OPTIMIZE_DELETE_BY_RETURNING, + false, + false); + + /** + * 是否为局部 UK 使用全表扫描检查冲突的插入值 + * 对新购实例默认为 false + */ + public final static BooleanConfigParam DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = new BooleanConfigParam( + ConnectionProperties.DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN, + true, + false); + /** * 是否使用 GSI 检查冲突的插入值 */ @@ -718,7 +789,23 @@ public class ConnectionParams { */ public final static BooleanConfigParam FORBID_DDL_WITH_CCI = new BooleanConfigParam( ConnectionProperties.FORBID_DDL_WITH_CCI, - true, + false, + true); + + /** + * 是否在执行repartition的时候重建CCI + */ + public final static BooleanConfigParam REBUILD_CCI_WHEN_REPARTITION = new BooleanConfigParam( + ConnectionProperties.REBUILD_CCI_WHEN_REPARTITION, + false, + true); + + /** + * 是否允许在 CCI 上执行 DROP/TRUNCATE PARTITION 删除/清空数据,会造成主表和分区表数据不一致 + */ + public final static BooleanConfigParam ENABLE_DROP_TRUNCATE_CCI_PARTITION = new BooleanConfigParam( + ConnectionProperties.ENABLE_DROP_TRUNCATE_CCI_PARTITION, + false, true); /** @@ -1119,6 +1206,20 @@ public class ConnectionParams { true ); + public static final IntConfigParam COLUMNAR_TSO_UPDATE_DELAY = new IntConfigParam( + ConnectionProperties.COLUMNAR_TSO_UPDATE_DELAY, + 0, + null, + 0, // no delay by default + true + ); + + public static final BooleanConfigParam ENABLE_COLUMNAR_DEBUG = new BooleanConfigParam( + ConnectionProperties.ENABLE_COLUMNAR_DEBUG, + false, + true + ); + /** * 开始清理事务日志的时间段(默认 00:00-00:10) */ @@ -1132,6 +1233,14 @@ public class ConnectionParams { false, true); + /** + * copy modify with HINT NODE(0) TO SINGLE GROUP + */ + public static final BooleanConfigParam COPY_MODIFY_NODE0_TO_SINGLE = new BooleanConfigParam( + ConnectionProperties.COPY_MODIFY_NODE0_TO_SINGLE, + false, + true); + public static void addSupportedParam(ConfigParam param) { SUPPORTED_PARAMS.put(param.getName(), param); } @@ -1253,6 +1362,11 @@ public static void addSupportedParam(ConfigParam param) { true, false); + public static final BooleanConfigParam SCALE_OUT_GENERATE_MULTIPLE_TO_GROUP_JOB = + new BooleanConfigParam(ConnectionProperties.SCALE_OUT_GENERATE_MULTIPLE_TO_GROUP_JOB, + true, + false); + public final static BooleanConfigParam BACKFILL_USE_RETURNING = new BooleanConfigParam( ConnectionProperties.BACKFILL_USE_RETURNING, true, @@ -1297,12 +1411,27 @@ public static void addSupportedParam(ConfigParam param) { 1L, Long.MAX_VALUE, 1000000L, false); /** - * max physcial table sample size for backfill + * max physcial table sample rows for backfill */ - public static final LongConfigParam BACKFILL_MAX_SAMPLE_SIZE = - new LongConfigParam(ConnectionProperties.BACKFILL_MAX_SAMPLE_SIZE, + public static final LongConfigParam BACKFILL_MAX_SAMPLE_ROWS = + new LongConfigParam(ConnectionProperties.BACKFILL_MAX_SAMPLE_ROWS, 10000L, Long.MAX_VALUE, 100000L, false); + /** + * max physcial table sample rows for backfill pk range task + */ + public static final LongConfigParam BACKFILL_MAX_SAMPLE_ROWS_FOR_PK_RANGE = + new LongConfigParam(ConnectionProperties.BACKFILL_MAX_SAMPLE_ROWS_FOR_PK_RANGE, + 10000L, Long.MAX_VALUE, 100000L, false); + + public static final StringConfigParam BACKFILL_MAX_PK_RANGE_SIZE = + new StringConfigParam(ConnectionProperties.BACKFILL_MAX_PK_RANGE_SIZE, + "64kB", + false); + + public static final StringConfigParam BACKFILL_MAX_TASK_PK_RANGE_SIZE = + new StringConfigParam(ConnectionProperties.BACKFILL_MAX_TASK_PK_RANGE_SIZE, + "64MB", false); /** * check target table after scaleout's backfill */ @@ -1321,6 +1450,63 @@ public static void addSupportedParam(ConfigParam param) { true, false); + public static final BooleanConfigParam GSI_BACKFILL_OVERRIDE_DDL_PARAMS = + new BooleanConfigParam(ConnectionProperties.GSI_BACKFILL_OVERRIDE_DDL_PARAMS, + true, + false); + + /** + * GSI backfill build local index later + */ + public static final BooleanConfigParam GSI_BUILD_LOCAL_INDEX_LATER = + new BooleanConfigParam(ConnectionProperties.GSI_BUILD_LOCAL_INDEX_LATER, + false, + false); + + /** + * GSI backfill use pk range split + */ + public static final BooleanConfigParam GSI_BACKFILL_BY_PK_RANGE = + new BooleanConfigParam(ConnectionProperties.GSI_BACKFILL_BY_PK_RANGE, + false, + false); + + /** + * GSI backfill use pk range split + */ + public static final BooleanConfigParam GSI_BACKFILL_BY_PARTITION = + new BooleanConfigParam(ConnectionProperties.GSI_BACKFILL_BY_PARTITION, + false, + false); + + /** + * GSI backfill max paramllesim + */ + public static final IntConfigParam GSI_JOB_MAX_PARALLELISM = + new IntConfigParam(ConnectionProperties.GSI_JOB_MAX_PARALLELISM, + 1, + 4096, + 4, + false); + + /** + * GSI backfill max paramllesim + */ + public static final IntConfigParam GSI_PK_RANGE_CPU_ACQUIRE = + new IntConfigParam(ConnectionProperties.GSI_PK_RANGE_CPU_ACQUIRE, + 1, + 100, + 10, + false); + + /** + * GSI backfill max paramllesim + */ + public static final BooleanConfigParam GSI_PK_RANGE_LOCK_READ = + new BooleanConfigParam(ConnectionProperties.GSI_PK_RANGE_LOCK_READ, + true, + false); + public static IntConfigParam FASTCHECKER_THREAD_POOL_SIZE = new IntConfigParam(ConnectionProperties.FASTCHECKER_THREAD_POOL_SIZE, 1, 10, 1, false); @@ -1329,13 +1515,6 @@ public static void addSupportedParam(ConfigParam param) { new IntConfigParam(ConnectionProperties.FASTCHECKER_BATCH_TIMEOUT_RETRY_TIMES, 1, 10, 4, false); - /** - * CHECK GLOBAL INDEX use fastchecker - */ - public static BooleanConfigParam CHECK_GLOBAL_INDEX_USE_FASTCHECKER = - new BooleanConfigParam(ConnectionProperties.CHECK_GLOBAL_INDEX_USE_FASTCHECKER, - true, - false); /** * check whether enable the scaleout feature, could disable/enable it from diamond/metadb @@ -1401,12 +1580,12 @@ public static void addSupportedParam(ConfigParam param) { ConnectionProperties.SCALEOUT_TASK_PARALLELISM, -1L, Long.MAX_VALUE, - 0L, + 16L, false); public static final LongConfigParam TABLEGROUP_TASK_PARALLELISM = new LongConfigParam( ConnectionProperties.TABLEGROUP_TASK_PARALLELISM, - -1L, 1024L, 0L, false); + -1L, 1024L, 16L, false); /** * batch size for scaleout check procedure @@ -1506,6 +1685,14 @@ public static void addSupportedParam(ConfigParam param) { false, false); + public static final BooleanConfigParam UNIQUE_GSI_WITH_PRIMARY_KEY = new BooleanConfigParam( + ConnectionProperties.UNIQUE_GSI_WITH_PRIMARY_KEY, + true, + false); + + /** + * allow change/modify columns in which is also in GSI. + */ public static final BooleanConfigParam ALLOW_LOOSE_ALTER_COLUMN_WITH_GSI = new BooleanConfigParam( ConnectionProperties.ALLOW_LOOSE_ALTER_COLUMN_WITH_GSI, false, @@ -1599,7 +1786,7 @@ public static void addSupportedParam(ConfigParam param) { public static final LongConfigParam GSI_BACKFILL_BATCH_SIZE = new LongConfigParam( ConnectionProperties.GSI_BACKFILL_BATCH_SIZE, 16L, - 4096L, + 1024L * 1024, 1024L, false); @@ -1923,7 +2110,7 @@ public static void addSupportedParam(ConfigParam param) { ConnectionProperties.SKIP_PHYSICAL_ANALYZE, false, true); public static final IntConfigParam STATISTIC_EXPIRE_TIME = new IntConfigParam( - ConnectionProperties.STATISTIC_EXPIRE_TIME, 1, null, 8 * 24 * 60 * 60, true); + ConnectionProperties.STATISTIC_EXPIRE_TIME, 1, null, 4 * 24 * 60 * 60, true); public static final LongConfigParam CACHELINE_INDICATE_UPDATE_TIME = new LongConfigParam( ConnectionProperties.CACHELINE_INDICATE_UPDATE_TIME, 1L, null, 0L, true); @@ -1937,11 +2124,14 @@ public static void addSupportedParam(ConfigParam param) { public static final FloatConfigParam SAMPLE_PERCENTAGE = new FloatConfigParam( ConnectionProperties.SAMPLE_PERCENTAGE, -1f, 100f, -1f, true); + public static final StringConfigParam DN_HINT = new StringConfigParam( + ConnectionProperties.DN_HINT, "", true); + public static final FloatConfigParam BACKFILL_MAX_SAMPLE_PERCENTAGE = new FloatConfigParam( ConnectionProperties.BACKFILL_MAX_SAMPLE_PERCENTAGE, -1f, 100f, 10f, true); public static final BooleanConfigParam ENABLE_INNODB_BTREE_SAMPLING = new BooleanConfigParam( - ConnectionProperties.ENABLE_INNODB_BTREE_SAMPLING, false, true); + ConnectionProperties.ENABLE_INNODB_BTREE_SAMPLING, true, true); public static final IntConfigParam HISTOGRAM_MAX_SAMPLE_SIZE = new IntConfigParam( ConnectionProperties.HISTOGRAM_MAX_SAMPLE_SIZE, 1000, Integer.MAX_VALUE, 100000, true); @@ -1956,7 +2146,7 @@ public static void addSupportedParam(ConfigParam param) { ConnectionProperties.ENABLE_BKA_JOIN, true, true); public static final BooleanConfigParam ENABLE_REMOVE_JOIN_CONDITION = new BooleanConfigParam( - ConnectionProperties.ENABLE_REMOVE_JOIN_CONDITION, true, true); + ConnectionProperties.ENABLE_REMOVE_JOIN_CONDITION, false, true); public static final BooleanConfigParam ENABLE_BKA_PRUNING = new BooleanConfigParam( ConnectionProperties.ENABLE_BKA_PRUNING, true, true); @@ -2041,6 +2231,12 @@ public static void addSupportedParam(ConfigParam param) { public static final BooleanConfigParam ENABLE_LV_SUBQUERY_UNWRAP = new BooleanConfigParam( ConnectionProperties.ENABLE_LV_SUBQUERY_UNWRAP, true, true); + public static final BooleanConfigParam ENABLE_AUTO_FORCE_INDEX = new BooleanConfigParam( + ConnectionProperties.ENABLE_AUTO_FORCE_INDEX, false, true); + + public static final BooleanConfigParam ENABLE_DELETE_FORCE_CC_INDEX = new BooleanConfigParam( + ConnectionProperties.ENABLE_DELETE_FORCE_CC_INDEX, false, true); + public static final BooleanConfigParam EXPLAIN_PRUNING_DETAIL = new BooleanConfigParam( ConnectionProperties.EXPLAIN_PRUNING_DETAIL, false, true); @@ -2059,8 +2255,11 @@ public static void addSupportedParam(ConfigParam param) { public static final BooleanConfigParam ENABLE_SORT_AGG = new BooleanConfigParam( ConnectionProperties.ENABLE_SORT_AGG, true, true); - public static final BooleanConfigParam PARTIAL_AGG_ONLY = new BooleanConfigParam( - ConnectionProperties.PARTIAL_AGG_ONLY, false, true); + public static final BooleanConfigParam PREFER_PUSH_AGG = new BooleanConfigParam( + ConnectionProperties.PREFER_PUSH_AGG, true, true); + + public static final BooleanConfigParam PREFER_PARTIAL_AGG = new BooleanConfigParam( + ConnectionProperties.PREFER_PARTIAL_AGG, true, true); public static final IntConfigParam PARTIAL_AGG_SHARD = new IntConfigParam( ConnectionProperties.PARTIAL_AGG_SHARD, 0, Integer.MAX_VALUE, 6, true); @@ -2068,6 +2267,15 @@ public static void addSupportedParam(ConfigParam param) { public static final BooleanConfigParam ENABLE_PARTIAL_AGG = new BooleanConfigParam( ConnectionProperties.ENABLE_PARTIAL_AGG, true, true); + public static final BooleanConfigParam ENABLE_TOPN = new BooleanConfigParam( + ConnectionProperties.ENABLE_TOPN, true, true); + + public static final BooleanConfigParam ENABLE_LIMIT = new BooleanConfigParam( + ConnectionProperties.ENABLE_LIMIT, true, true); + + public static final BooleanConfigParam ENABLE_PARTIAL_LIMIT = new BooleanConfigParam( + ConnectionProperties.ENABLE_PARTIAL_LIMIT, true, true); + public static final FloatConfigParam PARTIAL_AGG_SELECTIVITY_THRESHOLD = new FloatConfigParam( ConnectionProperties.PARTIAL_AGG_SELECTIVITY_THRESHOLD, 0f, 1f, 0.2f, true); @@ -2128,8 +2336,8 @@ public static void addSupportedParam(ConfigParam param) { public static final BooleanConfigParam ENABLE_PUSH_AGG = new BooleanConfigParam( ConnectionProperties.ENABLE_PUSH_AGG, true, true); - public static final IntConfigParam PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD = new IntConfigParam( - ConnectionProperties.PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD, 0, Integer.MAX_VALUE, 10000, true); + public static final LongConfigParam PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD = new LongConfigParam( + ConnectionProperties.PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD, 0L, Long.MAX_VALUE, 10000L, true); public static final BooleanConfigParam ENABLE_CBO_PUSH_AGG = new BooleanConfigParam( ConnectionProperties.ENABLE_CBO_PUSH_AGG, true, true); @@ -2232,9 +2440,13 @@ public static void addSupportedParam(ConfigParam param) { false, true); + public static final LongConfigParam HOT_GSI_EVOLUTION_THRESHOLD = + new LongConfigParam(ConnectionProperties.HOT_GSI_EVOLUTION_THRESHOLD, + 0L, 10000000L, 10000L, true); + public static final BooleanConfigParam ENABLE_EXPRESSION_CONSTANT_FOLD = new BooleanConfigParam(ConnectionProperties.ENABLE_EXPRESSION_CONSTANT_FOLD, - false, true); + true, true); public static final BooleanConfigParam ENABLE_SPM_BACKGROUND_TASK = new BooleanConfigParam( ConnectionProperties.ENABLE_SPM_BACKGROUND_TASK, @@ -2394,6 +2606,12 @@ public static void addSupportedParam(ConfigParam param) { public static final BooleanConfigParam INSERT_SELECT_SELF_BY_PARALLEL = new BooleanConfigParam( ConnectionProperties.INSERT_SELECT_SELF_BY_PARALLEL, false, true); + /** + * 是否允许 Insert select 包含flash black时下推执行。RR隔离级别,dn insert select会变成当前读,默认不允许下推 + */ + public static final BooleanConfigParam ENABLE_INSERT_SELECT_WITH_FLASHBACK_PUSH_DOWN = new BooleanConfigParam( + ConnectionProperties.ENABLE_INSERT_SELECT_WITH_FLASHBACK_PUSH_DOWN, false, true); + /** * 是否允许 Insert 列重复 */ @@ -2575,9 +2793,12 @@ public static void addSupportedParam(ConfigParam param) { public static final IntConfigParam POLARDBX_PARALLELISM = new IntConfigParam( ConnectionProperties.POLARDBX_PARALLELISM, 0, 128, -1, true); - public static final BooleanConfigParam POLARDBX_SLAVE_INSTANCE_FIRST = new BooleanConfigParam( - ConnectionProperties.POLARDBX_SLAVE_INSTANCE_FIRST, true, true); - + /** + * 0 - close + * 1 - sql + * 2 - pipeline + * 3 - operator + */ public static final IntConfigParam MPP_METRIC_LEVEL = new IntConfigParam( ConnectionProperties.MPP_METRIC_LEVEL, 0, 3, 3, true); @@ -2654,14 +2875,6 @@ public static void addSupportedParam(ConfigParam param) { true, true); - /** - * where use plan cache for columnar plan - */ - public static final BooleanConfigParam ENABLE_COLUMNAR_PLAN_CACHE = new BooleanConfigParam( - ConnectionProperties.ENABLE_COLUMNAR_PLAN_CACHE, - false, - true); - public static final BooleanConfigParam ENABLE_COLUMNAR_PULL_UP_PROJECT = new BooleanConfigParam( ConnectionProperties.ENABLE_COLUMNAR_PULL_UP_PROJECT, true, @@ -2771,6 +2984,12 @@ public static void addSupportedParam(ConfigParam param) { true ); + public static final BooleanConfigParam BROADCAST_RANDOM_READ_IN_LOGICALVIEW = new BooleanConfigParam( + ConnectionProperties.BROADCAST_RANDOM_READ_IN_LOGICALVIEW, + false, + true + ); + public static final BooleanConfigParam ENABLE_LOCAL_PARTITION_WISE_JOIN = new BooleanConfigParam( ConnectionProperties.ENABLE_LOCAL_PARTITION_WISE_JOIN, true, true); @@ -2941,18 +3160,18 @@ public static void addSupportedParam(ConfigParam param) { 256 * 1024 * 1024L, true); /** - * x-protocol max DN concurrent. (default 500) (default 2000 for columnar) + * x-protocol max DN concurrent. (default 2000) (default 2000 for columnar) */ public static final LongConfigParam XPROTO_MAX_DN_CONCURRENT = new LongConfigParam( ConnectionProperties.XPROTO_MAX_DN_CONCURRENT, 1L, Long.MAX_VALUE, 2000L, true); /** - * x-protocol max wait connection per DN. (default 100) (default 200 for columnar) + * x-protocol max wait connection per DN. (default 2000) (default 200 for columnar) */ public static final LongConfigParam XPROTO_MAX_DN_WAIT_CONNECTION = new LongConfigParam( ConnectionProperties.XPROTO_MAX_DN_WAIT_CONNECTION, 1L, Long.MAX_VALUE, - 100L, true); + 2000L, true); /** * X-Protocol always keep upper filter when use XPlan. (default true) @@ -3042,8 +3261,18 @@ public static class ConnectionParamValues { public static final BooleanConfigParam ENABLE_OSS_MOCK_COLUMNAR = new BooleanConfigParam( ConnectionProperties.ENABLE_OSS_MOCK_COLUMNAR, false, true); + public static final BooleanConfigParam ENABLE_COLUMNAR_CORRELATE = new BooleanConfigParam( + ConnectionProperties.ENABLE_COLUMNAR_CORRELATE, false, true); + public static final BooleanConfigParam ENABLE_COLUMNAR_OPTIMIZER = new BooleanConfigParam( - ConnectionProperties.ENABLE_COLUMNAR_OPTIMIZER, true, true); + ConnectionProperties.ENABLE_COLUMNAR_OPTIMIZER, false, true); + + /** + * The parameter ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR is influenced by ALLOW_COLUMNAR_BIND_MASTER, + * and under normal circumstances, it is advised not to set the ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR variable. + */ + public static final BooleanConfigParam ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR = new BooleanConfigParam( + ConnectionProperties.ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR, false, true); public static final StringConfigParam EXECUTOR_MODE = new StringConfigParam( ConnectionProperties.EXECUTOR_MODE, "NONE", true); @@ -3221,11 +3450,8 @@ public static class ConnectionParamValues { new BooleanConfigParam(ConnectionProperties.STATISTICS_DUMP_IGNORE_STRING, false, true); /** - * 是否开启 SELECT INTO OUTFILE 默认关闭 + * Use the range-format to show hash/key partitions */ - public static final BooleanConfigParam ENABLE_SELECT_INTO_OUTFILE = - new BooleanConfigParam(ConnectionProperties.ENABLE_SELECT_INTO_OUTFILE, false, true); - public static final BooleanConfigParam SHOW_HASH_PARTITIONS_BY_RANGE = new BooleanConfigParam( ConnectionProperties.SHOW_HASH_PARTITIONS_BY_RANGE, false, @@ -3296,12 +3522,16 @@ public static class ConnectionParamValues { true ); - public static final BooleanConfigParam ENABLE_PARTITION_MANAGEMENT = new BooleanConfigParam( - ConnectionProperties.ENABLE_PARTITION_MANAGEMENT, + /** + * Running time window of balancer + */ + public static final BooleanConfigParam SHOW_DDL_ENGINE_RESOURCES = new BooleanConfigParam( + ConnectionProperties.SHOW_DDL_ENGINE_RESOURCES, false, true ); + /** * Allow move the single table with locality='balance_single_table=on' during scale-out/scale-in */ @@ -3509,11 +3739,18 @@ public static class ConnectionParamValues { public static final IntConfigParam AUTO_COLLECT_NDV_SKETCH = new IntConfigParam( ConnectionProperties.AUTO_COLLECT_NDV_SKETCH, 1, Integer.MAX_VALUE, 24, true); - public static final BooleanConfigParam ENABLE_NDV_USE_COLUMNAR = new BooleanConfigParam( - ConnectionProperties.ENABLE_NDV_USE_COLUMNAR, false, true); + /** + * call com.alibaba.polardbx.optimizer.config.table.statistic.inf.NDVSketchService#updateAllShardParts + * using 'analyze table', for test only + */ + public static final BooleanConfigParam ANALYZE_TEST_UPDATE = new BooleanConfigParam( + ConnectionProperties.ANALYZE_TEST_UPDATE, false, true); public static final BooleanConfigParam ENABLE_MPP_NDV_USE_COLUMNAR = new BooleanConfigParam( - ConnectionProperties.ENABLE_MPP_NDV_USE_COLUMNAR, false, true); + ConnectionProperties.ENABLE_MPP_NDV_USE_COLUMNAR, true, true); + + public static final BooleanConfigParam MPP_NDV_USE_COLUMNAR_LIMIT = new BooleanConfigParam( + ConnectionProperties.MPP_NDV_USE_COLUMNAR_LIMIT, true, true); /** * expire time(sec) for ndv sketch info @@ -3611,6 +3848,9 @@ public static class ConnectionParamValues { public static final BooleanConfigParam ENABLE_LOGICALVIEW_COST = new BooleanConfigParam( ConnectionProperties.ENABLE_LOGICALVIEW_COST, true, true); + public static final StringConfigParam DEFAULT_TTL_SCHEDULE_CRON_EXPR = new StringConfigParam( + ConnectionProperties.DEFAULT_TTL_SCHEDULE_CRON_EXPR, "0 0 1 * * ? *", true); + public static final BooleanConfigParam TABLEGROUP_REORG_CHECK_AFTER_BACKFILL = new BooleanConfigParam( ConnectionProperties.TABLEGROUP_REORG_CHECK_AFTER_BACKFILL, true, true); @@ -3672,7 +3912,7 @@ public static class ConnectionParamValues { new IntConfigParam(ConnectionProperties.CHANGE_SET_APPLY_BATCH, 1, 10 * 1024, 128, false); public static final LongConfigParam CHANGE_SET_MEMORY_LIMIT = new LongConfigParam( - ConnectionProperties.CHANGE_SET_MEMORY_LIMIT, 1024L, 16 * 1024 * 1024L, 1024 * 1024L, false); + ConnectionProperties.CHANGE_SET_MEMORY_LIMIT, 1024L, 16 * 1024 * 1024L, 4 * 1024 * 1024L, false); public static final BooleanConfigParam CN_ENABLE_CHANGESET = new BooleanConfigParam(ConnectionProperties.CN_ENABLE_CHANGESET, true, true); @@ -3845,6 +4085,25 @@ public static class ConnectionParamValues { public static final BooleanConfigParam ENABLE_DECIMAL_FAST_VEC = new BooleanConfigParam( ConnectionProperties.ENABLE_DECIMAL_FAST_VEC, false, true); + /** + * perform type conversion automatically + * when then column type does not match vectorized IN expression value type + */ + public static final BooleanConfigParam ENABLE_IN_VEC_AUTO_TYPE = new BooleanConfigParam( + ConnectionProperties.ENABLE_IN_VEC_AUTO_TYPE, false, true); + + /** + * enable short-circuit evaluation in AndVectorizedExpression + */ + public static final BooleanConfigParam ENABLE_AND_FAST_VEC = new BooleanConfigParam( + ConnectionProperties.ENABLE_AND_FAST_VEC, false, true); + + /** + * enable short-circuit evaluation in OrVectorizedExpression + */ + public static final BooleanConfigParam ENABLE_OR_FAST_VEC = new BooleanConfigParam( + ConnectionProperties.ENABLE_OR_FAST_VEC, false, true); + public static final BooleanConfigParam ENABLE_UNIQUE_HASH_KEY = new BooleanConfigParam( ConnectionProperties.ENABLE_UNIQUE_HASH_KEY, false, true); @@ -3873,12 +4132,21 @@ public static class ConnectionParamValues { public static final BooleanConfigParam ALLOW_REPLACE_ARCHIVE_TABLE = new BooleanConfigParam( ConnectionProperties.ALLOW_REPLACE_ARCHIVE_TABLE, false, true); + public static final BooleanConfigParam CHECK_ARCHIVE_PARTITION_READY = new BooleanConfigParam( + ConnectionProperties.CHECK_ARCHIVE_PARTITION_READY, true, true); + /** * Allow create table like a file-store table. */ public static final BooleanConfigParam ALLOW_CREATE_TABLE_LIKE_FILE_STORE = new BooleanConfigParam( ConnectionProperties.ALLOW_CREATE_TABLE_LIKE_FILE_STORE, false, true); + /** + * Label if allow create table like a ttl-defined table and auto ignore the ttl definition + */ + public static final BooleanConfigParam ALLOW_CREATE_TABLE_LIKE_IGNORE_ARCHIVE_CCI = new BooleanConfigParam( + ConnectionProperties.ALLOW_CREATE_TABLE_LIKE_IGNORE_ARCHIVE_CCI, false, true); + public static final BooleanConfigParam ENABLE_PARTITIONS_HEATMAP_COLLECTION = new BooleanConfigParam( ConnectionProperties.ENABLE_PARTITIONS_HEATMAP_COLLECTION, true, true); @@ -3897,6 +4165,9 @@ public static class ConnectionParamValues { ConnectionProperties.PARTITIONS_HEATMAP_COLLECTION_MAX_SINGLE_LOGIC_SCHEMA_COUNT, 0, Integer.MAX_VALUE, 8000, true); + public static final BooleanConfigParam ENABLE_LOG_SYSTEM_METRICS = new BooleanConfigParam( + ConnectionProperties.ENABLE_LOG_SYSTEM_METRICS, true, true); + /** * the MAX size of IN expr being pruned */ @@ -3906,9 +4177,6 @@ public static class ConnectionParamValues { public static final IntConfigParam MAX_IN_PRUNE_CACHE_SIZE = new IntConfigParam( ConnectionProperties.MAX_IN_PRUNE_CACHE_SIZE, 0, Integer.MAX_VALUE, 200, true); - public static final IntConfigParam MAX_IN_PRUNE_CACHE_TABLE_SIZE = new IntConfigParam( - ConnectionProperties.MAX_IN_PRUNE_CACHE_TABLE_SIZE, 0, Integer.MAX_VALUE, 10, true); - public static final IntConfigParam REBALANCE_TASK_PARALISM = new IntConfigParam( ConnectionProperties.REBALANCE_TASK_PARALISM, 1, 64, 2, true); @@ -4116,6 +4384,47 @@ public static class ConnectionParamValues { public static final IntConfigParam PREFETCH_EXECUTE_POLICY = new IntConfigParam( ConnectionProperties.PREFETCH_EXECUTE_POLICY, -1, 3, -1, true); + /** + * Controls whether range scan is enabled. + * The parameter is initially set to enabled (true) and is mutable (true). + */ + public static final BooleanConfigParam ENABLE_RANGE_SCAN = new BooleanConfigParam( + ConnectionProperties.ENABLE_RANGE_SCAN, true, true); + + /** + * Controls whether range scan is enabled for dml. + * The parameter is initially set to disabled (false) and is mutable (true). + */ + public static final BooleanConfigParam ENABLE_RANGE_SCAN_FOR_DML = new BooleanConfigParam( + ConnectionProperties.ENABLE_RANGE_SCAN_FOR_DML, false, true); + + /** + * Controls the range scan mode. + * The parameter is initially set to empty (decided automatically) and is mutable (true). + */ + public static final StringConfigParam RANGE_SCAN_MODE = new StringConfigParam( + ConnectionProperties.RANGE_SCAN_MODE, + "", + true + ); + + /** + * Controls the range scan adaptive policy. + * The parameter is initially set to empty (decided automatically) and is mutable (true). + */ + public static final StringConfigParam RANGE_SCAN_ADAPTIVE_POLICY = new StringConfigParam( + ConnectionProperties.RANGE_SCAN_ADAPTIVE_POLICY, + "", + true + ); + + /** + * Controls the limit of using range scan serialized mode. + * The parameter is initially set to 100 and is mutable (true). + */ + public static final IntConfigParam RANGE_SCAN_SERIALIZE_LIMIT = new IntConfigParam( + ConnectionProperties.RANGE_SCAN_SERIALIZE_LIMIT, 0, Integer.MAX_VALUE, 100, true); + public static final BooleanConfigParam ENABLE_REPLICA = new BooleanConfigParam( ConnectionProperties.ENABLE_REPLICA, true, true); @@ -4229,6 +4538,13 @@ public static class ConnectionParamValues { 10000, true ); + + public static final BooleanConfigParam ENABLE_COLUMNAR_MULTI_VERSION_PARTITION = new BooleanConfigParam( + ConnectionProperties.ENABLE_COLUMNAR_MULTI_VERSION_PARTITION, + true, + true + ); + /** * The policy of table scan: IO_PRIORITY, FILTER_PRIORITY, IO_ON_DEMAND. */ @@ -4250,10 +4566,11 @@ public static class ConnectionParamValues { /** * To enable the usage of in-flight block cache. + * May lead to concurrency safety issues. */ public static final BooleanConfigParam ENABLE_USE_IN_FLIGHT_BLOCK_CACHE = new BooleanConfigParam( ConnectionProperties.ENABLE_USE_IN_FLIGHT_BLOCK_CACHE, - true, + false, true ); @@ -4281,11 +4598,13 @@ public static class ConnectionParamValues { /** * If disabled, SliceBlock with dictionary will be converted to - * SliceBlock with values + * SliceBlock with values. + *

+ * Merging a large number of local dictionaries can cause performance regression. */ public static final BooleanConfigParam ENABLE_COLUMNAR_SLICE_DICT = new BooleanConfigParam( ConnectionProperties.ENABLE_COLUMNAR_SLICE_DICT, - true, + false, true ); @@ -4369,6 +4688,14 @@ public static class ConnectionParamValues { true ); + public static final LongConfigParam PREHEATED_CACHE_MAX_ENTRIES = new LongConfigParam( + ConnectionProperties.PREHEATED_CACHE_MAX_ENTRIES, + 16L, + Long.MAX_VALUE, + 4096L, + true + ); + public static final BooleanConfigParam ENABLE_BLOCK_BUILDER_BATCH_WRITING = new BooleanConfigParam( ConnectionProperties.ENABLE_BLOCK_BUILDER_BATCH_WRITING, true, @@ -4468,6 +4795,13 @@ public static class ConnectionParamValues { false ); + public static final BooleanConfigParam ENABLE_STANDBY_BACKFILL = new BooleanConfigParam( + ConnectionProperties.ENABLE_STANDBY_BACKFILL, + true, + false + ); + + public static final BooleanConfigParam ENABLE_ROLLBACK_TO_READY = new BooleanConfigParam( ConnectionProperties.ENABLE_ROLLBACK_TO_READY, true, @@ -4530,7 +4864,7 @@ public static class ConnectionParamValues { public static final BooleanConfigParam PHYSICAL_BACKFILL_ENABLE = new BooleanConfigParam( ConnectionProperties.PHYSICAL_BACKFILL_ENABLE, - false, + true, true); public static final BooleanConfigParam PHYSICAL_BACKFILL_FROM_FOLLOWER = new BooleanConfigParam( @@ -4582,11 +4916,32 @@ public static class ConnectionParamValues { true, true); + public static final LongConfigParam PHYSICAL_BACKFILL_IMPORT_TABLESPACE_IO_ADVISE = new LongConfigParam( + ConnectionProperties.PHYSICAL_BACKFILL_IMPORT_TABLESPACE_IO_ADVISE, + 10L, + 100L, + 40L, + true); + + public static final LongConfigParam PHYSICAL_BACKFILL_PIPELINE_SIZE = new LongConfigParam( + ConnectionProperties.PHYSICAL_BACKFILL_PIPELINE_SIZE, + -1L, Long.MAX_VALUE, -1L, true); + + public final static BooleanConfigParam DISCARD_TABLESPACE_USE_GROUP_CONCURRENT_BLOCK = new BooleanConfigParam( + ConnectionProperties.DISCARD_TABLESPACE_USE_GROUP_CONCURRENT_BLOCK, + true, + false); + public static final BooleanConfigParam PHYSICAL_BACKFILL_SPEED_TEST = new BooleanConfigParam( ConnectionProperties.PHYSICAL_BACKFILL_SPEED_TEST, false, true); + public static final BooleanConfigParam ANALYZE_TABLE_AFTER_IMPORT_TABLESPACE = new BooleanConfigParam( + ConnectionProperties.ANALYZE_TABLE_AFTER_IMPORT_TABLESPACE, + true, + true); + /** * rebalance start point */ @@ -4615,7 +4970,7 @@ public static class ConnectionParamValues { public static final BooleanConfigParam ENABLE_DEADLOCK_DETECTION_80 = new BooleanConfigParam( ConnectionProperties.ENABLE_DEADLOCK_DETECTION_80, - false, + true, true ); @@ -4792,10 +5147,10 @@ public static class ConnectionParamValues { ); /** - * Enable oss table scan only returns deleted data in orc files. + * Enable oss table scan only returns deleted data in orc/csv files. */ - public static final BooleanConfigParam ENABLE_ORC_DELETED_SCAN = new BooleanConfigParam( - ConnectionProperties.ENABLE_ORC_DELETED_SCAN, + public static final BooleanConfigParam ENABLE_OSS_DELETED_SCAN = new BooleanConfigParam( + ConnectionProperties.ENABLE_OSS_DELETED_SCAN, false, true ); @@ -4809,12 +5164,6 @@ public static class ConnectionParamValues { true ); - public static final StringConfigParam FORCE_READ_ORC_FILE = new StringConfigParam( - ConnectionProperties.FORCE_READ_ORC_FILE, - null, - true - ); - public static final BooleanConfigParam READ_CSV_ONLY = new BooleanConfigParam( ConnectionProperties.READ_CSV_ONLY, false, @@ -4827,8 +5176,20 @@ public static class ConnectionParamValues { true ); - public static final BooleanConfigParam ENABLE_FAST_CCI_CHECKER = new BooleanConfigParam( - ConnectionProperties.ENABLE_FAST_CCI_CHECKER, + public static final BooleanConfigParam READ_SPECIFIED_COLUMNAR_FILES = new BooleanConfigParam( + ConnectionProperties.READ_SPECIFIED_COLUMNAR_FILES, + false, + true + ); + + public static final BooleanConfigParam CCI_INCREMENTAL_CHECK = new BooleanConfigParam( + ConnectionProperties.CCI_INCREMENTAL_CHECK, + false, + true + ); + + public static final BooleanConfigParam ENABLE_CCI_FAST_CHECKER = new BooleanConfigParam( + ConnectionProperties.ENABLE_CCI_FAST_CHECKER, true, true ); @@ -4839,6 +5200,12 @@ public static class ConnectionParamValues { true ); + public static final BooleanConfigParam ENABLE_ACCURATE_REL_TYPE_TO_DATA_TYPE = new BooleanConfigParam( + ConnectionProperties.ENABLE_ACCURATE_REL_TYPE_TO_DATA_TYPE, + false, + true + ); + public static final BooleanConfigParam FORCE_2PC_DURING_CCI_CHECK = new BooleanConfigParam( ConnectionProperties.FORCE_2PC_DURING_CCI_CHECK, false, @@ -4853,7 +5220,7 @@ public static class ConnectionParamValues { public static final BooleanConfigParam ENABLE_AUTO_COMMIT_TSO = new BooleanConfigParam( ConnectionProperties.ENABLE_AUTO_COMMIT_TSO, - true, + false, true ); @@ -4863,6 +5230,348 @@ public static class ConnectionParamValues { true ); - public static final BooleanConfigParam ENABLE_SINGLE_SHARD_WRITE = new BooleanConfigParam( - ConnectionProperties.ENABLE_SINGLE_SHARD_WRITE, true, true); + public static final BooleanConfigParam FORBID_AUTO_COMMIT_TRX = new BooleanConfigParam( + ConnectionProperties.FORBID_AUTO_COMMIT_TRX, + false, + true + ); + + public static final BooleanConfigParam ENABLE_EXTERNAL_CONSISTENCY_FOR_WRITE_TRX = new BooleanConfigParam( + ConnectionProperties.ENABLE_EXTERNAL_CONSISTENCY_FOR_WRITE_TRX, + false, + true + ); + + public static final BooleanConfigParam ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION = new BooleanConfigParam( + ConnectionProperties.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION, + false, + true); + + //列存查询文件最新的append记录默认使用子查询方式,false情况使用join方式 + public static final BooleanConfigParam SHOW_COLUMNAR_STATUS_USE_SUB_QUERY = new BooleanConfigParam( + ConnectionProperties.SHOW_COLUMNAR_STATUS_USE_SUB_QUERY, + true, + true); + + public static final IntConfigParam TTL_GLOBAL_SELECT_WORKER_COUNT = new IntConfigParam( + ConnectionProperties.TTL_GLOBAL_SELECT_WORKER_COUNT, + 1, + 1024, + 4, + true + ); + + public static final IntConfigParam TTL_GLOBAL_DELETE_WORKER_COUNT = new IntConfigParam( + ConnectionProperties.TTL_GLOBAL_DELETE_WORKER_COUNT, + 1, + 1024, + 0, + true + ); + + public static final BooleanConfigParam TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB = new BooleanConfigParam( + ConnectionProperties.TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB, + false, + true + ); + + public static final BooleanConfigParam TTL_ENABLE_AUTO_EXEC_OPTIMIZE_TABLE_AFTER_ARCHIVING = new BooleanConfigParam( + ConnectionProperties.TTL_ENABLE_AUTO_EXEC_OPTIMIZE_TABLE_AFTER_ARCHIVING, + true, + true + ); + + public static final LongConfigParam TTL_TMP_TBL_MAX_DATA_LENGTH = new LongConfigParam( + ConnectionProperties.TTL_TMP_TBL_MAX_DATA_LENGTH, + 134217728L /*128M*/, + Long.MAX_VALUE, + 34359738368L, + true + ); + + public static final IntConfigParam TTL_OPTIMIZE_TABLE_PARALLELISM = new IntConfigParam( + ConnectionProperties.TTL_OPTIMIZE_TABLE_PARALLELISM, + 1, + Integer.MAX_VALUE, + 4, + true + ); + + public static final IntConfigParam TTL_TBL_MAX_DATA_FREE_PERCENT = new IntConfigParam( + ConnectionProperties.TTL_TBL_MAX_DATA_FREE_PERCENT, + 1, + Integer.MAX_VALUE, + 40, + true + ); + + public static final IntConfigParam TTL_INTRA_TASK_INTERRUPTION_MAX_WAIT_TIME = new IntConfigParam( + ConnectionProperties.TTL_INTRA_TASK_INTERRUPTION_MAX_WAIT_TIME, + 1, + Integer.MAX_VALUE, + 5000, + true + ); + + public static final IntConfigParam TTL_INTRA_TASK_MONITOR_EACH_ROUTE_WAIT_TIME = new IntConfigParam( + ConnectionProperties.TTL_INTRA_TASK_MONITOR_EACH_ROUTE_WAIT_TIME, + 1, + Integer.MAX_VALUE, + 1000, + true + ); + + public static final IntConfigParam TTL_SCHEDULED_JOB_MAX_PARALLELISM = new IntConfigParam( + ConnectionProperties.TTL_SCHEDULED_JOB_MAX_PARALLELISM, + 1, + 128, + 2, + true + ); + + public static final BooleanConfigParam TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = new BooleanConfigParam( + ConnectionProperties.TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL, + false, + true); + + public static final StringConfigParam TTL_DEBUG_CCI_SKIP_DDL_TASKS = + new StringConfigParam(ConnectionProperties.TTL_DEBUG_CCI_SKIP_DDL_TASKS, + "", + false); + + public static final IntConfigParam TTL_JOB_DEFAULT_BATCH_SIZE = new IntConfigParam( + ConnectionProperties.TTL_JOB_DEFAULT_BATCH_SIZE, + 1, + Integer.MAX_VALUE, + 256, + true); + + /** + * The interval count for computing minCleanupBound base on lowerBound(normalized minVal of ttl_col), + * that means the delta = ttlMinCleanupBoundIntervalCount * ttlUnit, is the delta interval between + * minCleanupBound and the lowerBound, default is 3 + */ + public static final IntConfigParam TTL_CLEANUP_BOUND_INTERVAL_COUNT = new IntConfigParam( + ConnectionProperties.TTL_CLEANUP_BOUND_INTERVAL_COUNT, + 1, + Integer.MAX_VALUE, + 3, + true); + + /** + * Stop ttl-job scheduling for all ttl tables, used for handling critical situation + */ + public static final BooleanConfigParam TTL_STOP_ALL_JOB_SCHEDULING = new BooleanConfigParam( + ConnectionProperties.TTL_STOP_ALL_JOB_SCHEDULING, + false, + true); + + /** + * Label if use archive trans policy for all trans of ttl-job + */ + public static final BooleanConfigParam TTL_USE_ARCHIVE_TRANS_POLICY = new BooleanConfigParam( + ConnectionProperties.TTL_USE_ARCHIVE_TRANS_POLICY, + true, + true); + + /** + * The default merge_union_size for the select sql of fetch ttl-col lower bound + */ + public static final IntConfigParam TTL_SELECT_MERGE_UNION_SIZE = new IntConfigParam( + ConnectionProperties.TTL_SELECT_MERGE_UNION_SIZE, + 1, + 64, + 2, + true + ); + + /** + * The label if use merge_concurrent for the select sql of fetch ttl-col lower bound + */ + public static final BooleanConfigParam TTL_SELECT_MERGE_CONCURRENT = new BooleanConfigParam( + ConnectionProperties.TTL_SELECT_MERGE_CONCURRENT, + true, + true); + + public static final StringConfigParam TTL_SELECT_STMT_HINT = + new StringConfigParam(ConnectionProperties.TTL_SELECT_STMT_HINT, + "/*+TDDL: GROUP_CONCURRENT_BLOCK=true PREFETCH_EXECUTE_POLICY=1 MERGE_UNION_SIZE=2 */", + false); + + public static final StringConfigParam TTL_DELETE_STMT_HINT = + new StringConfigParam(ConnectionProperties.TTL_DELETE_STMT_HINT, + "/*+TDDL:cmd_extra(SOCKET_TIMEOUT=1800000)*/", + false); + + public static final StringConfigParam TTL_INSERT_STMT_HINT = + new StringConfigParam(ConnectionProperties.TTL_INSERT_STMT_HINT, + "/*+TDDL:cmd_extra(SOCKET_TIMEOUT=1800000)*/", + false); + + public static final StringConfigParam TTL_OPTIMIZE_TABLE_STMT_HINT = + new StringConfigParam(ConnectionProperties.TTL_OPTIMIZE_TABLE_STMT_HINT, + "/*+TDDL:cmd_extra(ENABLE_ASYNC_DDL=true, PURE_ASYNC_DDL_MODE=true, RETURN_JOB_ID_ON_ASYNC_DDL_MODE=true, OPTIMIZE_TABLE_PARALLELISM=4, SOCKET_TIMEOUT=1800000)*/", + false); + + public static final StringConfigParam TTL_ALTER_ADD_PART_STMT_HINT = + new StringConfigParam(ConnectionProperties.TTL_ALTER_ADD_PART_STMT_HINT, + "/*+TDDL:cmd_extra(SOCKET_TIMEOUT=1800000)*/", + false); + + public static final LongConfigParam TTL_GROUP_PARALLELISM_ON_DQL_CONN = + new LongConfigParam(ConnectionProperties.TTL_GROUP_PARALLELISM_ON_DQL_CONN, + 0L, + 1024L, + 1L, + false); + + public static final LongConfigParam TTL_GROUP_PARALLELISM_ON_DML_CONN = + new LongConfigParam(ConnectionProperties.TTL_GROUP_PARALLELISM_ON_DML_CONN, + 0L, + 1024L, + 0L, + false); + + public static final BooleanConfigParam TTL_ADD_MAXVAL_PART_ON_CCI_CREATING = + new BooleanConfigParam(ConnectionProperties.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING, + true, + true); + + public static final BooleanConfigParam TTL_FORCE_DROP_ARCHIVE_CCI = + new BooleanConfigParam(ConnectionProperties.TTL_FORCE_DROP_ARCHIVE_CCI, + false, + true); + + public static final BooleanConfigParam TTL_FORCE_DROP_ARCHIVE_CCI_VIEW = + new BooleanConfigParam(ConnectionProperties.TTL_FORCE_DROP_ARCHIVE_CCI_VIEW, + false, + true); + + public static final LongConfigParam TTL_MAX_WAIT_ACQUIRE_RATE_PERMITS_PERIODS = + new LongConfigParam(ConnectionProperties.TTL_MAX_WAIT_ACQUIRE_RATE_PERMITS_PERIODS, + 0L, + Long.MAX_VALUE, + 5000L, + false); + + public static final LongConfigParam TTL_CLEANUP_ROWS_SPEED_LIMIT_EACH_DN = + new LongConfigParam(ConnectionProperties.TTL_CLEANUP_ROWS_SPEED_LIMIT_EACH_DN, + 0L, + Long.MAX_VALUE, + 1024L, + false); + + public static final BooleanConfigParam TTL_ENABLE_CLEANUP_ROWS_SPEED_LIMIT = + new BooleanConfigParam(ConnectionProperties.TTL_ENABLE_CLEANUP_ROWS_SPEED_LIMIT, + true, + true); + + public static final BooleanConfigParam TTL_IGNORE_MAINTAIN_WINDOW_IN_DDL_JOB = + new BooleanConfigParam(ConnectionProperties.TTL_IGNORE_MAINTAIN_WINDOW_IN_DDL_JOB, + true, + true); + + /** + * The ratio of global-delete-worker / rw-dn-count, default is 2 + */ + public static final IntConfigParam TTL_GLOBAL_WORKER_DN_RATIO = new IntConfigParam( + ConnectionProperties.TTL_GLOBAL_WORKER_DN_RATIO, + 1, + 128, + 2, + true + ); + + public static final IntConfigParam TTL_DEFAULT_ARC_PRE_ALLOCATE_COUNT = new IntConfigParam( + ConnectionProperties.TTL_DEFAULT_ARC_PRE_ALLOCATE_COUNT, + 1, + 8192, + 12, + true + ); + + public static final IntConfigParam TTL_DEFAULT_ARC_POST_ALLOCATE_COUNT = new IntConfigParam( + ConnectionProperties.TTL_DEFAULT_ARC_POST_ALLOCATE_COUNT, + 1, + 8192, + 64, + true + ); + + public static final BooleanConfigParam TTL_ENABLE_AUTO_ADD_PARTS_FOR_ARC_CCI = + new BooleanConfigParam(ConnectionProperties.TTL_ENABLE_AUTO_ADD_PARTS_FOR_ARC_CCI, + true, + true); + + public static final StringConfigParam TTL_DEBUG_CURRENT_DATETIME = + new StringConfigParam(ConnectionProperties.TTL_DEBUG_CURRENT_DATETIME, + "", + false); + + + public static final BooleanConfigParam TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = + new BooleanConfigParam(ConnectionProperties.TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI, + true, + true); + + /** + * Columnar storage read-only instance's maximum sustainable QPS + */ + public static final LongConfigParam COLUMNAR_CLUSTER_MAXIMUM_QPS = + new LongConfigParam(ConnectionProperties.COLUMNAR_CLUSTER_MAXIMUM_QPS, + -1L, + Long.MAX_VALUE, + -1L, + true); + + /** + * Columnar storage read-only instance's maximum sustainable concurrency + */ + public static final LongConfigParam COLUMNAR_CLUSTER_MAXIMUM_CONCURRENCY = + new LongConfigParam(ConnectionProperties.COLUMNAR_CLUSTER_MAXIMUM_CONCURRENCY, + -1L, + Long.MAX_VALUE, + -1L, + true); + + /** + * The size of the time window required to calculate QPS for columnar storage read-only instances + */ + public static final LongConfigParam COLUMNAR_QPS_WINDOW_PERIOD = + new LongConfigParam(ConnectionProperties.COLUMNAR_QPS_WINDOW_PERIOD, + 1000L, + Long.MAX_VALUE, + 5000L, + true); + + public static final LongConfigParam MPP_QUERY_RESULT_MAX_WAIT_IN_MILLIS = + new LongConfigParam(ConnectionProperties.MPP_QUERY_RESULT_MAX_WAIT_IN_MILLIS, + 1L, + Long.MAX_VALUE, + 10L, + true); + /** + * 等待列存同步的超时时间 + */ + public static final LongConfigParam WAIT_FOR_COLUMNAR_COMMIT_MS = new LongConfigParam( + ConnectionProperties.WAIT_FOR_COLUMNAR_COMMIT_MS, + 0L, + Long.MAX_VALUE, + 60000L, + true + ); + + public static final IntConfigParam CN_DIV_PRECISION_INCREMENT = new IntConfigParam( + ConnectionProperties.CN_DIV_PRECISION_INCREMENT, + 0, + 30, + 4, + true + ); + + public static final BooleanConfigParam ENABLE_DRDS_TYPE_SYSTEM = new BooleanConfigParam( + ConnectionProperties.ENABLE_DRDS_TYPE_SYSTEM, + false, + true); + } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/ConnectionProperties.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/ConnectionProperties.java index 5c89c64dd..9e056e8ea 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/ConnectionProperties.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/ConnectionProperties.java @@ -22,7 +22,15 @@ * @author Dreamond */ public class ConnectionProperties { + /** + * Generate columnar snapshots automatically. + */ + public static final String ENABLE_AUTO_GEN_COLUMNAR_SNAPSHOT = "ENABLE_AUTO_GEN_COLUMNAR_SNAPSHOT"; + public static final String AUTO_GEN_COLUMNAR_SNAPSHOT_PARALLELISM = "AUTO_GEN_COLUMNAR_SNAPSHOT_PARALLELISM"; + /** + * CoronaDB PlanCache + */ public static final String PLAN_CACHE = "PLAN_CACHE"; public static final String PHY_SQL_TEMPLATE_CACHE = "PHY_SQL_TEMPLATE_CACHE"; public static final String PREPARE_OPTIMIZE = "PREPARE_OPTIMIZE"; @@ -125,8 +133,34 @@ public class ConnectionProperties { public static final String FIRST_THEN_CONCURRENT_POLICY = "FIRST_THEN_CONCURRENT_POLICY"; + /** + * 在事务时,DML忽略串行执行策略规则,详情请见ExecUtils.getQueryConcurrencyPolicy + */ + public static final String ENABLE_DML_GROUP_CONCURRENT_IN_TRANSACTION = + "ENABLE_DML_GROUP_CONCURRENT_IN_TRANSACTION"; + + /** + * 指定 DML 执行策略, PUSHDOWN, DETERMINISTIC_PUSHDOWN, LOGICAL + */ public static final String DML_EXECUTION_STRATEGY = "DML_EXECUTION_STRATEGY"; + /** + * 是否下推 WHERE 条件中包含目标表子查询的 DELETE/UPDATE 语句 + */ + public final static String DML_PUSH_MODIFY_WITH_SUBQUERY_CONDITION_OF_TARGET = + "DML_PUSH_MODIFY_WITH_SUBQUERY_CONDITION_OF_TARGET"; + + /** + * 是否禁止 SET 子句中包含子查询的 UPDATE 语句 + */ + public final static String DML_FORBID_UPDATE_WITH_SUBQUERY_IN_SET = "DML_FORBID_UPDATE_WITH_SUBQUERY_IN_SET"; + + public final static String DML_FORBID_PUSH_DOWN_UPDATE_WITH_SUBQUERY_IN_SET = + "DML_FORBID_PUSH_DOWN_UPDATE_WITH_SUBQUERY_IN_SET"; + + /** + * 是否下推 INSERT IGNORE / REPLACE / UPSERT + */ public static final String DML_PUSH_DUPLICATE_CHECK = "DML_PUSH_DUPLICATE_CHECK"; public static final String DML_SKIP_TRIVIAL_UPDATE = "DML_SKIP_TRIVIAL_UPDATE"; @@ -144,6 +178,22 @@ public class ConnectionProperties { */ public static final String DML_USE_RETURNING = "DML_USE_RETURNING"; + /** + * 是否使用 returning 优化包含 order by limit 的 update / delete + */ + public static final String OPTIMIZE_MODIFY_TOP_N_BY_RETURNING = "OPTIMIZE_MODIFY_TOP_N_BY_RETURNING"; + + /** + * 是否使用 returning 优化需要逻辑执行的 DELETE + */ + public static final String OPTIMIZE_DELETE_BY_RETURNING = "OPTIMIZE_DELETE_BY_RETURNING"; + + /** + * 是否为局部 UK 使用全表扫描检查冲突的插入值 + */ + public static final String DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = + "DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN"; + /** * 是否使用 GSI 检查冲突的插入值 */ @@ -212,6 +262,16 @@ public class ConnectionProperties { */ public static final String FORBID_DDL_WITH_CCI = "FORBID_DDL_WITH_CCI"; + /** + * 是否在执行repartition的时候重建CCI + */ + public static final String REBUILD_CCI_WHEN_REPARTITION = "REBUILD_CCI_WHEN_REPARTITION"; + + /** + * 是否允许在 CCI 上执行 DROP/TRUNCATE PARTITION 删除/清空数据,会造成主表和分区表数据不一致 + */ + public static final String ENABLE_DROP_TRUNCATE_CCI_PARTITION = "ENABLE_DROP_TRUNCATE_CCI_PARTITION"; + /** * 在 RelocateWriter 中是否通过 PartitionField 判断拆分键是否变化 */ @@ -593,6 +653,11 @@ public class ConnectionProperties { */ public static final String COLUMNAR_TSO_UPDATE_INTERVAL = "COLUMNAR_TSO_UPDATE_INTERVAL"; + /** + * 主动为主实例增加一个 tso 加载延迟,通过读一个更早的 tso 来规避加载增量数据导致的延迟,单位为毫秒 + */ + public static final String COLUMNAR_TSO_UPDATE_DELAY = "COLUMNAR_TSO_UPDATE_DELAY"; + /** * 默认事务清理开始时间(在该时间段内随机) */ @@ -649,6 +714,9 @@ public class ConnectionProperties { */ public static final String INSERT_SELECT_SELF_BY_PARALLEL = "INSERT_SELECT_SELF_BY_PARALLEL"; + public static final String ENABLE_INSERT_SELECT_WITH_FLASHBACK_PUSH_DOWN = + "ENABLE_INSERT_SELECT_WITH_FLASHBACK_PUSH_DOWN"; + /** * 是否允许 Insert 列重复 */ @@ -756,6 +824,8 @@ public class ConnectionProperties { public static final String SAMPLE_PERCENTAGE = "SAMPLE_PERCENTAGE"; + public static final String DN_HINT = "DN_HINT"; + /** * backfill sample_percentage */ @@ -861,6 +931,10 @@ public class ConnectionProperties { public static final String ENABLE_LV_SUBQUERY_UNWRAP = "ENABLE_LV_SUBQUERY_UNWRAP"; + public static final String ENABLE_AUTO_FORCE_INDEX = "ENABLE_AUTO_FORCE_INDEX"; + + public static final String ENABLE_DELETE_FORCE_CC_INDEX = "ENABLE_DELETE_FORCE_CC_INDEX"; + public static final String EXPLAIN_PRUNING_DETAIL = "EXPLAIN_PRUNING_DETAIL"; public static final String ENABLE_FILTER_REORDER = "ENABLE_FILTER_REORDER"; @@ -880,7 +954,9 @@ public class ConnectionProperties { public static final String ENABLE_SORT_AGG = "ENABLE_SORT_AGG"; - public static final String PARTIAL_AGG_ONLY = "PARTIAL_AGG_ONLY"; + public static final String PREFER_PUSH_AGG = "PREFER_PUSH_AGG"; + + public static final String PREFER_PARTIAL_AGG = "PREFER_PARTIAL_AGG"; public static final String PARTIAL_AGG_SHARD = "PARTIAL_AGG_SHARD"; @@ -889,6 +965,12 @@ public class ConnectionProperties { */ public static final String ENABLE_PARTIAL_AGG = "ENABLE_PARTIAL_AGG"; + public static final String ENABLE_TOPN = "ENABLE_TOPN"; + + public static final String ENABLE_LIMIT = "ENABLE_LIMIT"; + + public static final String ENABLE_PARTIAL_LIMIT = "ENABLE_PARTIAL_LIMIT"; + public static final String PARTIAL_AGG_SELECTIVITY_THRESHOLD = "PARTIAL_AGG_SELECTIVITY_THRESHOLD"; public static final String PARTIAL_AGG_BUCKET_THRESHOLD = "PARTIAL_AGG_BUCKET_THRESHOLD"; @@ -989,6 +1071,11 @@ public class ConnectionProperties { */ public static final String PUSHDOWN_HINT_ON_BROADCAST = "PUSHDOWN_HINT_ON_BROADCAST"; + /** + * copy modify with HINT NODE(0) TO SINGLE GROUP + */ + public static final String COPY_MODIFY_NODE0_TO_SINGLE = "COPY_MODIFY_NODE0_TO_SINGLE"; + /** * allow Global Secondary Index DDL or DML on MySQL 5.6 */ @@ -1091,7 +1178,13 @@ public class ConnectionProperties { /** * max sample size of backfill physical table */ - public static final String BACKFILL_MAX_SAMPLE_SIZE = "BACKFILL_MAX_SAMPLE_SIZE"; + public static final String BACKFILL_MAX_SAMPLE_ROWS = "BACKFILL_MAX_SAMPLE_ROWS"; + + public static final String BACKFILL_MAX_SAMPLE_ROWS_FOR_PK_RANGE = "BACKFILL_MAX_SAMPLE_ROWS_FOR_PK_RANGE"; + + public static final String BACKFILL_MAX_PK_RANGE_SIZE = "BACKFILL_MAX_PK_RANGE_SIZE"; + + public static final String BACKFILL_MAX_TASK_PK_RANGE_SIZE = "BACKFILL_MAX_TASK_PK_RANGE_SIZE"; public static final String BACKFILL_USE_RETURNING = "BACKFILL_USE_RETURNING"; @@ -1119,9 +1212,20 @@ public class ConnectionProperties { public static final String GSI_BACKFILL_USE_FASTCHECKER = "GSI_BACKFILL_USE_FASTCHECKER"; - public static final String CHECK_GLOBAL_INDEX_USE_FASTCHECKER = "CHECK_GLOBAL_INDEX_USE_FASTCHECKER"; + public static final String GSI_BACKFILL_OVERRIDE_DDL_PARAMS = "GSI_BACKFILL_OVERRIDE_DDL_PARAMS"; + + public static final String GSI_BUILD_LOCAL_INDEX_LATER = "GSI_BUILD_LOCAL_INDEX_LATER"; + + public static final String GSI_BACKFILL_BY_PK_RANGE = "GSI_BACKFILL_BY_PK_RANGE"; + + public static final String GSI_BACKFILL_BY_PARTITION = "GSI_BACKFILL_BY_PARTITION"; + + public static final String GSI_JOB_MAX_PARALLELISM = "GSI_JOB_MAX_PARALLELISM"; + + public static final String GSI_PK_RANGE_CPU_ACQUIRE = "GSI_PK_RANGE_CPU_ACQUIRE"; + + public static final String GSI_PK_RANGE_LOCK_READ = "GSI_PK_RANGE_LOCK_READ"; - public static final String FASTCHECKER_RETRY_TIMES = "FASTCHECKER_RETRY_TIMES"; /** * fastChecker use thread pool to control parallelism * each thread pool corresponds to a storage inst node @@ -1200,6 +1304,11 @@ public class ConnectionProperties { public static final String SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE = "SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE"; + public static final String SCALE_OUT_GENERATE_MULTIPLE_TO_GROUP_JOB = + "SCALE_OUT_GENERATE_MULTIPLE_TO_GROUP_JOB"; + /** + * retry time when scaleout task fail + */ public static final String SCALEOUT_TASK_RETRY_TIME = "SCALEOUT_TASK_RETRY_TIME"; public static final String ALLOW_DROP_DATABASE_IN_SCALEOUT_PHASE = "ALLOW_DROP_DATABASE_IN_SCALEOUT_PHASE"; @@ -1224,6 +1333,11 @@ public class ConnectionProperties { */ public static final String ALLOW_DROP_OR_MODIFY_PART_UNIQUE_WITH_GSI = "ALLOW_DROP_OR_MODIFY_PART_UNIQUE_WITH_GSI"; + public static final String UNIQUE_GSI_WITH_PRIMARY_KEY = "UNIQUE_GSI_WITH_PRIMARY_KEY"; + + /** + * allow change/modify columns in which is also in GSI. + */ public static final String ALLOW_LOOSE_ALTER_COLUMN_WITH_GSI = "ALLOW_LOOSE_ALTER_COLUMN_WITH_GSI"; /** @@ -1464,6 +1578,10 @@ public class ConnectionProperties { public static final String ENABLE_SPM_EVOLUTION_BY_TIME = "ENABLE_SPM_EVOLUTION_BY_TIME"; + public static final String ENABLE_HOT_GSI_EVOLUTION = "ENABLE_HOT_GSI_EVOLUTION"; + + public static final String HOT_GSI_EVOLUTION_THRESHOLD = "HOT_GSI_EVOLUTION_THRESHOLD"; + public static final String ENABLE_SPM_BACKGROUND_TASK = "ENABLE_SPM_BACKGROUND_TASK"; public static final String SPM_MAX_BASELINE_SIZE = "SPM_MAX_BASELINE_SIZE"; @@ -1535,6 +1653,11 @@ public class ConnectionProperties { */ public static final String PURE_ASYNC_DDL_MODE = "PURE_ASYNC_DDL_MODE"; + /** + * Label if return job_id on async_ddl_mode when submit ddl + */ + public static final String RETURN_JOB_ID_ON_ASYNC_DDL_MODE = "RETURN_JOB_ID_ON_ASYNC_DDL_MODE"; + public static final String ENABLE_OPERATE_SUBJOB = "ENABLE_OPERATE_SUBJOB"; public static final String SKIP_VALIDATE_STORAGE_INST_IDLE = "SKIP_VALIDATE_STORAGE_INST_IDLE"; @@ -1674,7 +1797,7 @@ public class ConnectionProperties { public static final String POLARDBX_PARALLELISM = "POLARDBX_PARALLELISM"; - public static final String POLARDBX_SLAVE_INSTANCE_FIRST = "POLARDBX_SLAVE_INSTANCE_FIRST"; + public static final String ALLOW_COLUMNAR_BIND_MASTER = "ALLOW_COLUMNAR_BIND_MASTER"; public static final String SEGMENTED = "SEGMENTED"; @@ -1791,11 +1914,16 @@ public class ConnectionProperties { public static final String MPP_ELAPSED_QUERY_THRESHOLD_MILLS = "MPP_ELAPSED_QUERY_THRESHOLD_MILLS"; + public static final String ENABLE_MPP_UI = "ENABLE_MPP_UI"; + public static final String MPP_METRIC_LEVEL = "MPP_METRIC_LEVEL"; public static final String MPP_QUERY_NEED_RESERVE = "MPP_QUERY_NEED_RESERVE"; public static final String ENABLE_MODIFY_SHARDING_COLUMN = "ENABLE_MODIFY_SHARDING_COLUMN"; + + public static final String NDV_ALIKE_PRECENTAGE_THRESHOLD = "NDV_ALIKE_PRECENTAGE_THRESHOLD"; + public static final String ENABLE_MODIFY_LIMIT_OFFSET_NOT_ZERO = "ENABLE_MODIFY_LIMIT_OFFSET_NOT_ZERO"; /** * Allow multi update/delete cross db @@ -1814,6 +1942,10 @@ public class ConnectionProperties { public static final String ENABLE_INDEX_SKYLINE = "ENABLE_INDEX_SKYLINE"; public static final String ENABLE_MERGE_INDEX = "ENABLE_MERGE_INDEX"; public static final String ENABLE_OSS_INDEX_SELECTION = "ENABLE_OSS_INDEX_SELECTION"; + + /** + * whether to use plan cache for columnar plan + */ public static final String ENABLE_COLUMNAR_PLAN_CACHE = "ENABLE_COLUMNAR_PLAN_CACHE"; public static final String ENABLE_COLUMNAR_PULL_UP_PROJECT = "ENABLE_COLUMNAR_PULL_UP_PROJECT"; /** @@ -1935,13 +2067,16 @@ public class ConnectionProperties { public static final String WORKLOAD_CPU_THRESHOLD = "WORKLOAD_CPU_THRESHOLD"; public static final String WORKLOAD_MEMORY_THRESHOLD = "WORKLOAD_MEMORY_THRESHOLD"; public static final String WORKLOAD_IO_THRESHOLD = "WORKLOAD_IO_THRESHOLD"; + public static final String WORKLOAD_OSS_NET_THRESHOLD = "WORKLOAD_OSS_NET_THRESHOLD"; public static final String WORKLOAD_COLUMNAR_ROW_THRESHOLD = "WORKLOAD_COLUMNAR_ROW_THRESHOLD"; public static final String WORKLOAD_TYPE = "WORKLOAD_TYPE"; public static final String ENABLE_OSS_MOCK_COLUMNAR = "ENABLE_OSS_MOCK_COLUMNAR"; + public static final String ENABLE_COLUMNAR_CORRELATE = "ENABLE_COLUMNAR_CORRELATE"; public static final String ENABLE_COLUMNAR_OPTIMIZER = "ENABLE_COLUMNAR_OPTIMIZER"; + public static final String ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR = "ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR"; public static final String EXECUTOR_MODE = "EXECUTOR_MODE"; public static final String ENABLE_MASTER_MPP = "ENABLE_MASTER_MPP"; public static final String ENABLE_TEMP_TABLE_JOIN = "ENABLE_TEMP_TABLE_JOIN"; @@ -1981,6 +2116,8 @@ public class ConnectionProperties { public static final String SPILL_OUTPUT_MAX_BUFFER_SIZE = "SPILL_OUTPUT_MAX_BUFFER_SIZE"; public static final String SUPPORT_READ_FOLLOWER_STRATEGY = "SUPPORT_READ_FOLLOWER_STRATEGY"; public static final String ENABLE_BROADCAST_RANDOM_READ = "ENABLE_BROADCAST_RANDOM_READ"; + public static final String BROADCAST_RANDOM_READ_IN_LOGICALVIEW = + "BROADCAST_RANDOM_READ_IN_LOGICALVIEW"; public static final String ENABLE_LOCAL_PARTITION_WISE_JOIN = "ENABLE_LOCAL_PARTITION_WISE_JOIN"; @@ -2043,9 +2180,8 @@ public class ConnectionProperties { */ public static final String STATISTICS_DUMP_IGNORE_STRING = "STATISTICS_DUMP_IGNORE_STRING"; /** - * 是否开启 SELECT INTO OUTFILE 默认关闭 + * Use range-format to show hash/key partitioned table */ - public static final String ENABLE_SELECT_INTO_OUTFILE = "ENABLE_SELECT_INTO_OUTFILE"; public static final String SHOW_HASH_PARTITIONS_BY_RANGE = "SHOW_HASH_PARTITIONS_BY_RANGE"; public static final String SHOW_TABLE_GROUP_NAME = "SHOW_TABLE_GROUP_NAME"; public static final String MAX_PHYSICAL_PARTITION_COUNT = "MAX_PHYSICAL_PARTITION_COUNT"; @@ -2076,10 +2212,7 @@ public class ConnectionProperties { public static final String BALANCER_MAX_PARTITION_SIZE = "BALANCER_MAX_PARTITION_SIZE"; public static final String BALANCER_WINDOW = "BALANCER_WINDOW"; - /** - * switch for partition management - */ - public static final String ENABLE_PARTITION_MANAGEMENT = "ENABLE_PARTITION_MANAGEMENT"; + public static final String SHOW_DDL_ENGINE_RESOURCES = "SHOW_DDL_ENGINE_RESOURCES"; /** * Allow move the single table with locality='balance_single_table=on' during scale-out/scale-in @@ -2110,6 +2243,7 @@ public class ConnectionProperties { public static final String ENABLE_OPTIMIZER_ALERT = "ENABLE_OPTIMIZER_ALERT"; public static final String ENABLE_OPTIMIZER_ALERT_LOG = "ENABLE_OPTIMIZER_ALERT_LOG"; public static final String OPTIMIZER_ALERT_LOG_INTERVAL = "OPTIMIZER_ALERT_LOG_INTERVAL"; + public static final String ALERT_BKA_BASE = "ALERT_BKA_BASE"; public static final String ALERT_TP_BASE = "ALERT_TP_BASE"; @@ -2167,9 +2301,11 @@ public class ConnectionProperties { public static final String STORAGE_HA_CONNECT_TIMEOUT = "STORAGE_HA_CONNECT_TIMEOUT"; public static final String ENABLE_HA_CHECK_TASK_LOG = "ENABLE_HA_CHECK_TASK_LOG"; - public static final String ENABLE_NDV_USE_COLUMNAR = "ENABLE_NDV_USE_COLUMNAR"; + public static final String ANALYZE_TEST_UPDATE = "ANALYZE_TEST_UPDATE"; public static final String ENABLE_MPP_NDV_USE_COLUMNAR = "ENABLE_MPP_NDV_USE_COLUMNAR"; + + public static final String MPP_NDV_USE_COLUMNAR_LIMIT = "MPP_NDV_USE_COLUMNAR_LIMIT"; /** * ndv sketch expire time */ @@ -2207,6 +2343,10 @@ public class ConnectionProperties { public static final String SCHEDULER_MAX_WORKER_COUNT = "SCHEDULER_MAX_WORKER_COUNT"; public static final String DEFAULT_LOCAL_PARTITION_SCHEDULE_CRON_EXPR = "DEFAULT_LOCAL_PARTITION_SCHEDULE_CRON_EXPR"; + + public static final String DEFAULT_TTL_SCHEDULE_CRON_EXPR = + "DEFAULT_TTL_SCHEDULE_CRON_EXPR"; + /** * check target table after alter tablegroup's backfill */ @@ -2282,6 +2422,7 @@ public class ConnectionProperties { public static final String ENABLE_OSS_DELAY_MATERIALIZATION = "ENABLE_OSS_DELAY_MATERIALIZATION"; public static final String ENABLE_OSS_ZERO_COPY = "ENABLE_OSS_ZERO_COPY"; public static final String ENABLE_OSS_COMPATIBLE = "ENABLE_OSS_COMPATIBLE"; + public static final String OSS_STREAM_BUFFER_SIZE = "OSS_STREAM_BUFFER_SIZE"; public static final String ENABLE_PAIRWISE_SHUFFLE_COMPATIBLE = "ENABLE_PAIRWISE_SHUFFLE_COMPATIBLE"; @@ -2293,6 +2434,9 @@ public class ConnectionProperties { "ENABLE_OSS_FILE_CONCURRENT_SPLIT_ROUND_ROBIN"; public static final String ENABLE_REUSE_VECTOR = "ENABLE_REUSE_VECTOR"; public static final String ENABLE_DECIMAL_FAST_VEC = "ENABLE_DECIMAL_FAST_VEC"; + public static final String ENABLE_IN_VEC_AUTO_TYPE = "ENABLE_IN_VEC_AUTO_TYPE"; + public static final String ENABLE_AND_FAST_VEC = "ENABLE_AND_FAST_VEC"; + public static final String ENABLE_OR_FAST_VEC = "ENABLE_OR_FAST_VEC"; public static final String ENABLE_UNIQUE_HASH_KEY = "ENABLE_UNIQUE_HASH_KEY"; public static final String ENABLE_PRUNE_EXCHANGE_PARTITION = "ENABLE_PRUNE_EXCHANGE_PARTITION"; public static final String BLOCK_BUILDER_CAPACITY = "BLOCK_BUILDER_CAPACITY"; @@ -2302,7 +2446,13 @@ public class ConnectionProperties { public static final String OSS_FILE_ORDER = "OSS_FILE_ORDER"; public static final String MAX_SESSION_PREPARED_STMT_COUNT = "MAX_SESSION_PREPARED_STMT_COUNT"; public static final String ALLOW_REPLACE_ARCHIVE_TABLE = "ALLOW_REPLACE_ARCHIVE_TABLE"; + + public static final String CHECK_ARCHIVE_PARTITION_READY = "CHECK_ARCHIVE_PARTITION_READY"; + public static final String ALLOW_CREATE_TABLE_LIKE_FILE_STORE = "ALLOW_CREATE_TABLE_LIKE_FILE_STORE"; + + public static final String ALLOW_CREATE_TABLE_LIKE_IGNORE_ARCHIVE_CCI = "ALLOW_CREATE_TABLE_LIKE_IGNORE_ARCHIVE_CCI"; + /** * is enable collect partitions heatmap, dynamic, default:true */ @@ -2331,6 +2481,9 @@ public class ConnectionProperties { */ public static final String ENABLE_EXTREME_PERFORMANCE = "ENABLE_EXTREME_PERFORMANCE"; public static final String ENABLE_CLEAN_FAILED_PLAN = "ENABLE_CLEAN_FAILED_PLAN"; + + public static final String ENABLE_LOG_SYSTEM_METRICS = "ENABLE_LOG_SYSTEM_METRICS"; + /** * the min size of IN expr that would be pruned */ @@ -2481,6 +2634,12 @@ public class ConnectionProperties { */ public static final String ROLLBACK_UNKNOWN_PRIMARY_GROUP_XA_TRX = "ROLLBACK_UNKNOWN_PRIMARY_GROUP_XA_TRX"; public static final String PREFETCH_EXECUTE_POLICY = "PREFETCH_EXECUTE_POLICY"; + + public static final String ENABLE_RANGE_SCAN = "ENABLE_RANGE_SCAN"; + public static final String ENABLE_RANGE_SCAN_FOR_DML = "ENABLE_RANGE_SCAN_FOR_DML"; + public static final String RANGE_SCAN_MODE = "RANGE_SCAN_MODE"; + public static final String RANGE_SCAN_ADAPTIVE_POLICY = "RANGE_SCAN_ADAPTIVE_POLICY"; + public static final String RANGE_SCAN_SERIALIZE_LIMIT = "RANGE_SCAN_SERIALIZE_LIMIT"; public static final String MAX_RECURSIVE_TIME = "MAX_RECURSIVE_COUNT"; public static final String MAX_RECURSIVE_CTE_MEM_BYTES = "MAX_RECURSIVE_CTE_MEM_BYTES"; public static final String ENABLE_REPLICA = "ENABLE_REPLICA"; @@ -2547,6 +2706,10 @@ public class ConnectionProperties { * The count of maximum groups in a scan work. */ public static final String COLUMNAR_WORK_UNIT = "COLUMNAR_WORK_UNIT"; + /** + * To enable the multi-version partition for columnar index partition pruning. + */ + public static final String ENABLE_COLUMNAR_MULTI_VERSION_PARTITION = "ENABLE_COLUMNAR_MULTI_VERSION_PARTITION"; /** * The policy of table scan: IO_PRIORITY, FILTER_PRIORITY, IO_ON_DEMAND. */ @@ -2588,6 +2751,7 @@ public class ConnectionProperties { public static final String ENABLE_DRIVER_OBJECT_POOL = "ENABLE_DRIVER_OBJECT_POOL"; public static final String ENABLE_COLUMNAR_SCAN_SELECTION = "ENABLE_COLUMNAR_SCAN_SELECTION"; public static final String BLOCK_CACHE_MEMORY_SIZE_FACTOR = "BLOCK_CACHE_MEMORY_SIZE_FACTOR"; + public static final String PREHEATED_CACHE_MAX_ENTRIES = "PREHEATED_CACHE_MAX_ENTRIES"; public static final String ENABLE_BLOCK_BUILDER_BATCH_WRITING = "ENABLE_BLOCK_BUILDER_BATCH_WRITING"; public static final String ENABLE_SCAN_RANDOM_SHUFFLE = "ENABLE_SCAN_RANDOM_SHUFFLE"; @@ -2620,9 +2784,19 @@ public class ConnectionProperties { public static final String PHYSICAL_BACKFILL_IMPORT_TABLESPACE_BY_LEADER = "PHYSICAL_BACKFILL_IMPORT_TABLESPACE_BY_LEADER"; + public static final String PHYSICAL_BACKFILL_IMPORT_TABLESPACE_IO_ADVISE = + "PHYSICAL_BACKFILL_IMPORT_TABLESPACE_IO_ADVISE"; + public static final String PHYSICAL_BACKFILL_PIPELINE_SIZE = "PHYSICAL_BACKFILL_PIPELINE_SIZE"; + + public static final String DISCARD_TABLESPACE_USE_GROUP_CONCURRENT_BLOCK = + "DISCARD_TABLESPACE_USE_GROUP_CONCURRENT_BLOCK"; + public static final String PHYSICAL_BACKFILL_SPEED_TEST = "PHYSICAL_BACKFILL_SPEED_TEST"; + public static final String ANALYZE_TABLE_AFTER_IMPORT_TABLESPACE = + "ANALYZE_TABLE_AFTER_IMPORT_TABLESPACE"; + public static final String REBALANCE_MAINTENANCE_ENABLE = "REBALANCE_MAINTENANCE_ENABLE"; public static final String REBALANCE_MAINTENANCE_TIME_START = "REBALANCE_MAINTENANCE_TIME_START"; @@ -2631,6 +2805,16 @@ public class ConnectionProperties { public static final String CANCEL_REBALANCE_JOB_DUE_MAINTENANCE = "CANCEL_REBALANCE_JOB_DUE_MAINTENANCE"; public static final String ENABLE_DEADLOCK_DETECTION_80 = "ENABLE_DEADLOCK_DETECTION_80"; + + public static final String DEADLOCK_DETECTION_80_FETCH_TRX_ROWS = "DEADLOCK_DETECTION_80_FETCH_TRX_ROWS"; + + public static final String DEADLOCK_DETECTION_DATA_LOCK_WAITS_THRESHOLD = + "DEADLOCK_DETECTION_DATA_LOCK_WAITS_THRESHOLD"; + + public static final String MAX_KEEP_DEADLOCK_LOGS = "MAX_KEEP_DEADLOCK_LOGS"; + + public static final String DEADLOCK_DETECTION_SKIP_ROUND = "DEADLOCK_DETECTION_SKIP_ROUND"; + public static final String MOCK_COLUMNAR_INDEX = "MOCK_COLUMNAR_INDEX"; public static final String MCI_FORMAT = "MCI_FORMAT"; public static final String ENABLE_LOGICAL_TABLE_META = "ENABLE_LOGICAL_TABLE_META"; @@ -2709,26 +2893,332 @@ public class ConnectionProperties { public static final String ENABLE_1PC_OPT = "ENABLE_1PC_OPT"; - // In milliseconds. - public static final String MIN_SNAPSHOT_KEEP_TIME = "MIN_SNAPSHOT_KEEP_TIME"; - public static final String FORCE_CCI_VISIBLE = "FORCE_CCI_VISIBLE"; - public static final String ENABLE_ORC_DELETED_SCAN = "ENABLE_ORC_DELETED_SCAN"; + public static final String ENABLE_OSS_DELETED_SCAN = "ENABLE_OSS_DELETED_SCAN"; public static final String ENABLE_ORC_RAW_TYPE_BLOCK = "ENABLE_ORC_RAW_TYPE_BLOCK"; - public static final String FORCE_READ_ORC_FILE = "FORCE_READ_ORC_FILE"; - public static final String READ_CSV_ONLY = "READ_CSV_ONLY"; public static final String READ_ORC_ONLY = "READ_ORC_ONLY"; - public static final String ENABLE_FAST_CCI_CHECKER = "ENABLE_FAST_CCI_CHECKER"; + public static final String READ_SPECIFIED_COLUMNAR_FILES = "READ_SPECIFIED_COLUMNAR_FILES"; + + public static final String CCI_INCREMENTAL_CHECK = "CCI_INCREMENTAL_CHECK"; + + public static final String ENABLE_CCI_FAST_CHECKER = "ENABLE_CCI_FAST_CHECKER"; public static final String ENABLE_FAST_PARSE_ORC_RAW_TYPE = "ENABLE_FAST_PARSE_ORC_RAW_TYPE"; + public static final String ENABLE_ACCURATE_REL_TYPE_TO_DATA_TYPE = "ENABLE_ACCURATE_REL_TYPE_TO_DATA_TYPE"; + + public static final String CHECK_CCI_TASK_CHECKPOINT_LIMIT = "CHECK_CCI_TASK_CHECKPOINT_LIMIT"; + + public static final String SKIP_CHECK_CCI_SCHEDULE_JOB = "SKIP_CHECK_CCI_SCHEDULE_JOB"; + public static final String FORBID_AUTO_COMMIT_TRX = "FORBID_AUTO_COMMIT_TRX"; public static final String FORCE_2PC_DURING_CCI_CHECK = "FORCE_2PC_DURING_CCI_CHECK"; + + public static final String ENABLE_ACCURATE_INFO_SCHEMA_TABLES = "ENABLE_ACCURATE_INFO_SCHEMA_TABLES"; + public static final String ENABLE_FLOATING_TYPE_PRECISION = "ENABLE_FLOATING_TYPE_PRECISION"; + + public static final String ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION = "ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION"; + + /** + * Enable sync point function in CN. + */ + public static final String ENABLE_SYNC_POINT = "ENABLE_SYNC_POINT"; + + /** + * Mark this trx as sync point trx, for inner usage. + */ + public static final String MARK_SYNC_POINT = "MARK_SYNC_POINT"; + + public static final String SYNC_POINT_TASK_INTERVAL = "SYNC_POINT_TASK_INTERVAL"; + + public static final String DISABLE_LEGACY_VARIABLE = "DISABLE_LEGACY_VARIABLE"; + + public static final String SHOW_COLUMNAR_STATUS_USE_SUB_QUERY = "SHOW_COLUMNAR_STATUS_USE_SUB_QUERY"; + + public static final String ENABLE_SHARE_READVIEW_IN_RC = "ENABLE_SHARE_READVIEW_IN_RC"; + + /** + * ================ Param keys for ttl job begin ================ + */ + + /** + * =========================== + * The following Config Params for polardbx-inst-level + * =========================== + */ + + /** + * The global worker count of select task of all ttl-jobs, default is 0, auto decided by dn count + */ + public static final String TTL_GLOBAL_SELECT_WORKER_COUNT = "TTL_GLOBAL_SELECT_WORKER_COUNT"; + + /** + * The global worker count of delete task of all ttl-jobs, default is 0, auto decided by dn count + */ + public static final String TTL_GLOBAL_DELETE_WORKER_COUNT = "TTL_GLOBAL_DELETE_WORKER_COUNT"; + + /** + * The max data length of each one ttl tmp table + */ + public static final String TTL_TMP_TBL_MAX_DATA_LENGTH = "TTL_TMP_TBL_MAX_DATA_LENGTH"; + + /** + * The max percent of (data_free * 100 / data_length) of ttl-table to perform optimize-table operation, + * the default value if 60% , unit: % + */ + public static final String TTL_TBL_MAX_DATA_FREE_PERCENT = "TTL_TBL_MAX_DATA_FREE_PERCENT"; + + /** + * The max wait time for interrupting a running ttl intra-task, unit: ms, default is 10s + * Unit: ms + */ + public static final String TTL_INTRA_TASK_INTERRUPTION_MAX_WAIT_TIME = "TTL_INTRA_TASK_INTERRUPTION_MAX_WAIT_TIME"; + + /** + * The wait time of each round for the manager of intra-tasks + * Unit: ms + */ + public static final String TTL_INTRA_TASK_MONITOR_EACH_ROUTE_WAIT_TIME = + "TTL_INTRA_TASK_MONITOR_EACH_ROUTE_WAIT_TIME"; + + /** + * The max wait time for waiting a ddl-job from pause to running, unit: ms, default value is 30s + */ + public static final String TTL_WAIT_TIME_OF_DDL_JOB_FROM_PAUSED_TO_RUNNING = + "TTL_WAIT_TIME_OF_DDL_JOB_FROM_PAUSED_TO_RUNNING"; + + /** + * The global switch that label if using auto-optimize table in ttl job + */ + public static final String TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB = "TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB"; + + /** + * Label if auto perform the optimize-table operation for the ttl-table after archiving + */ + public static final String TTL_ENABLE_AUTO_EXEC_OPTIMIZE_TABLE_AFTER_ARCHIVING = + "TTL_ENABLE_AUTO_EXEC_OPTIMIZE_TABLE_AFTER_ARCHIVING"; + + /** + * The max parallelism for the scheduled job of all ttl tables + */ + public static final String TTL_SCHEDULED_JOB_MAX_PARALLELISM = "TTL_SCHEDULED_JOB_MAX_PARALLELISM"; + + /** + * A local debug option, use create gsi sql instead of cci sql for create + * columnar arc table of ttl table, just for debug, session level + */ + public static final String TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = "TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL"; + + /** + * A local debug option of ttl20, specify the skip ddl tasks of cci creation of ttl tbl, + * such as : SKIP_DDL_TASKS="WaitColumnarTableCreationTask" + */ + public static final String TTL_DEBUG_CCI_SKIP_DDL_TASKS = "TTL_DEBUG_CCI_SKIP_DDL_TASKS"; + + /** + * The default batch size of dml of ttl-job + */ + public static final String TTL_JOB_DEFAULT_BATCH_SIZE = "TTL_JOB_DEFAULT_BATCH_SIZE"; + + /** + * The interval count for computing minCleanupBound base on lowerBound(normalized minVal of ttl_col), + * that means the delta = ttlMinCleanupBoundIntervalCount * ttlUnit, is the delta interval between + * minCleanupBound and the lowerBound, default is 1 + */ + public static final String TTL_CLEANUP_BOUND_INTERVAL_COUNT = "TTL_CLEANUP_BOUND_INTERVAL_COUNT"; + + /** + * Stop ttl-job scheduling for all ttl tables, used for handling critical situation + */ + public static final String TTL_STOP_ALL_JOB_SCHEDULING = "TTL_STOP_ALL_JOB_SCHEDULING"; + + /** + * label if use archive trans policy for all dml trans of ttl-job + *

+     *      usage:
+     *           set transaction_policy = archive;
+     *           begin;
+     *           ...
+     *           delete from ttl_tbl where ...
+     *           commit;
+     *
+     *  
+ */ + public static final String TTL_USE_ARCHIVE_TRANS_POLICY = "TTL_USE_ARCHIVE_TRANS_POLICY"; + + /** + * The default merge_union_size for the select sql of fetch ttl-col lower bound + */ + public static final String TTL_SELECT_MERGE_UNION_SIZE = "TTL_SELECT_MERGE_UNION_SIZE"; + + /** + * The label if use merge_concurrent for the select sql of fetch ttl-col lower bound + */ + public static final String TTL_SELECT_MERGE_CONCURRENT = "TTL_SELECT_MERGE_CONCURRENT"; + + /** + * The query hint for the select stmt of fetch ttl-col lower bound, + * which use to control the concurrent policy + */ + public static final String TTL_SELECT_STMT_HINT = "TTL_SELECT_STMT_HINT"; + + /** + * The query hint for delete stmt of deleting expired data + */ + public static final String TTL_DELETE_STMT_HINT = "TTL_DELETE_STMT_HINT"; + + /** + * The query hint for insert-select stmt of preparing expired data + */ + public static final String TTL_INSERT_STMT_HINT = "TTL_INSERT_STMT_HINT"; + + /** + * The query hint for optimize table stmt of ttl-table + */ + public static final String TTL_OPTIMIZE_TABLE_STMT_HINT = "TTL_OPTIMIZE_TABLE_STMT_HINT"; + + /** + * The query hint for alter table add parts stmt of cci of ttl-table or arctmp of ttl-table + */ + public static final String TTL_ALTER_ADD_PART_STMT_HINT = "TTL_ALTER_ADD_PART_STMT_HINT"; + + /** + * The default group_parallelism of conn of select stmt, 0 means use the default val of inst_config + */ + public static final String TTL_GROUP_PARALLELISM_ON_DQL_CONN = "TTL_GROUP_PARALLELISM_ON_DQL_CONN"; + + /** + * The default group_parallelism of conn of delete/insert stmt,0 means use the default val of inst_config + */ + public static final String TTL_GROUP_PARALLELISM_ON_DML_CONN = "TTL_GROUP_PARALLELISM_ON_DML_CONN"; + + /** + * Label if auto add a maxvalue into the range parts of cci of art-tbl + */ + public static final String TTL_ADD_MAXVAL_PART_ON_CCI_CREATING = "TTL_ADD_MAXVAL_PART_ON_CCI_CREATING"; + + /** + * The max periods of try waiting to acquire the rate permits, unit: ms + */ + public static final String TTL_MAX_WAIT_ACQUIRE_RATE_PERMITS_PERIODS = "TTL_MAX_WAIT_ACQUIRE_RATE_PERMITS_PERIODS"; + + /** + * The default rowsSpeed limit for each dn, unit: rows/sec + */ + public static final String TTL_CLEANUP_ROWS_SPEED_LIMIT_EACH_DN = "TTL_CLEANUP_ROWS_SPEED_LIMIT_EACH_DN"; + + /** + * Label if need limit the cleanup rows speed for each dn + */ + public static final String TTL_ENABLE_CLEANUP_ROWS_SPEED_LIMIT = "TTL_ENABLE_CLEANUP_ROWS_SPEED_LIMIT"; + + /** + * Label if ignore maintain window in ttl ddl job + */ + public static final String TTL_IGNORE_MAINTAIN_WINDOW_IN_DDL_JOB = "TTL_IGNORE_MAINTAIN_WINDOW_IN_DDL_JOB"; + + /** + * The ratio of global-worker / rw-dn-count, default is 2 + */ + public static final String TTL_GLOBAL_WORKER_DN_RATIO = "TTL_GLOBAL_WORKER_DN_RATIO"; + + /** + * The default allocate part count for pre building of futrue of arc cci + */ + public static final String TTL_DEFAULT_ARC_PRE_ALLOCATE_COUNT = "TTL_DEFAULT_ARC_PRE_ALLOCATE_COUNT"; + + /** + * The default allocate part count for post building of past of arc cci + */ + public static final String TTL_DEFAULT_ARC_POST_ALLOCATE_COUNT = "TTL_DEFAULT_ARC_POST_ALLOCATE_COUNT"; + + /** + * Label if enable auto add partitoins for arc cci + */ + public static final String TTL_ENABLE_AUTO_ADD_PARTS_FOR_ARC_CCI = "TTL_ENABLE_AUTO_ADD_PARTS_FOR_ARC_CCI"; + + /** + * + * =========================== + * The following Config Params for polardbx-session-level + * =========================== + */ + + /** + * The default charset of trans conn of ttl-job when exec sql + */ + public static final String TTL_DEFAULT_CHARSET_ON_CONN = "TTL_DEFAULT_CHARSET_ON_CONN"; + + /** + * The default sql mode of trans conn of ttl-job when exec sql + */ + public static final String TTL_DEFAULT_SQL_MODE_ON_CONN = "TTL_DEFAULT_SQL_MODE_ON_CONN"; + + /** + * The parallelism of alter table ttl_tbl optimize partitions xxx + */ + public static final String TTL_OPTIMIZE_TABLE_PARALLELISM = "TTL_OPTIMIZE_TABLE_PARALLELISM"; + + /** + * The current datetime value of debug, using for testcases + */ + public static final String TTL_DEBUG_CURRENT_DATETIME = "TTL_DEBUG_CURRENT_DATETIME"; + + /** + * label of forbid drop ttl-defined table with archive table cci + */ + public static final String TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = "TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI"; + + /** + * + * =========================== + * The following Config Params for polardbx-stmt-level + * =========================== + */ + + /** + * Label if allowed force drop the cci of the archive table + */ + public static final String TTL_FORCE_DROP_ARCHIVE_CCI = "TTL_FORCE_DROP_ARCHIVE_CCI"; + + /** + * Label if allowed force drop the view of the archive table view of cci + */ + public static final String TTL_FORCE_DROP_ARCHIVE_CCI_VIEW = "TTL_FORCE_DROP_ARCHIVE_CCI_VIEW"; + + /** + * ================ Param keys for ttl job end ================ + */ + + public static final String ENABLE_PARAM_TYPE_CHANGE = "ENABLE_PARAM_TYPE_CHANGE"; + + public static final String COLUMNAR_CLUSTER_MAXIMUM_QPS = "COLUMNAR_CLUSTER_MAXIMUM_QPS"; + + public static final String COLUMNAR_CLUSTER_MAXIMUM_CONCURRENCY = "COLUMNAR_CLUSTER_MAXIMUM_CONCURRENCY"; + + public static final String COLUMNAR_QPS_WINDOW_PERIOD = "COLUMNAR_QPS_WINDOW_PERIOD"; + + /** + * All write trx will start a standard 2PC TSO transaction, even in auto-commit mode. + */ + public static final String ENABLE_EXTERNAL_CONSISTENCY_FOR_WRITE_TRX = "ENABLE_EXTERNAL_CONSISTENCY_FOR_WRITE_TRX"; + + public static final String CCI_INCREMENTAL_CHECK_PARALLELISM = "CCI_INCREMENTAL_CHECK_PARALLELISM"; + public static final String CCI_INCREMENTAL_CHECK_BATCH_SIZE = "CCI_INCREMENTAL_CHECK_BATCH_SIZE"; + public static final String ENABLE_COLUMNAR_DEBUG = "ENABLE_COLUMNAR_DEBUG"; + + public static final String MPP_QUERY_RESULT_MAX_WAIT_IN_MILLIS = "MPP_QUERY_RESULT_MAX_WAIT_IN_MILLIS"; + + public static final String WAIT_FOR_COLUMNAR_COMMIT_MS = "WAIT_FOR_COLUMNAR_COMMIT_MS"; + + public static final String CN_DIV_PRECISION_INCREMENT = "CN_DIV_PRECISION_INCREMENT"; + + public static final String ENABLE_DRDS_TYPE_SYSTEM = "ENABLE_DRDS_TYPE_SYSTEM"; } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/DynamicConfig.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/DynamicConfig.java index 2c170fbd7..d7a5544e6 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/DynamicConfig.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/DynamicConfig.java @@ -22,8 +22,8 @@ import com.alibaba.polardbx.common.TddlConstants; import com.alibaba.polardbx.common.constants.IsolationLevel; import com.alibaba.polardbx.common.statementsummary.StatementSummaryManager; -import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.common.utils.TStringUtil; +import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.config.ConfigDataMode; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -96,6 +96,9 @@ public void loadValue(Logger logger, String key, String value) { case ConnectionProperties.OPTIMIZER_ALERT_LOG_INTERVAL: optimizerAlertLogInterval = parseValue(value, Long.class, 600000L); break; + case ConnectionProperties.ENABLE_HOT_GSI_EVOLUTION: + enableHotGsiEvolution = parseValue(value, Boolean.class, true); + break; case ConnectionProperties.ENABLE_TP_SLOW_ALERT_THRESHOLD: tpSlowAlertThreshold = parseValue(value, Integer.class, 10); break; @@ -123,6 +126,9 @@ public void loadValue(Logger logger, String key, String value) { case ConnectionProperties.ENABLE_FOLLOWER_READ: supportFollowRead = parseValue(value, Boolean.class, false); break; + case ConnectionProperties.ENABLE_SHARE_READVIEW_IN_RC: + enableShareReadviewInRc = parseValue(value, Boolean.class, false); + break; case ConnectionProperties.ENABLE_REMOTE_CONSUME_LOG: enableRemoteConsumeLog = parseValue(value, Boolean.class, false); break; @@ -143,6 +149,17 @@ public void loadValue(Logger logger, String key, String value) { case ConnectionProperties.BLOCK_CACHE_MEMORY_SIZE_FACTOR: blockCacheMemoryFactor = parseValue(value, Float.class, 0.6f); break; + case ConnectionProperties.CN_DIV_PRECISION_INCREMENT: + cnDivPrecisionIncrement = parseValue(value, Integer.class, 4); + break; + + case ConnectionProperties.PREHEATED_CACHE_MAX_ENTRIES: + preheatedCacheMaxEntries = parseValue(value, Long.class, 4096L); + break; + + case ConnectionProperties.MPP_QUERY_RESULT_MAX_WAIT_IN_MILLIS: + mppQueryResultMaxWaitInMillis = parseValue(value, Long.class, 10L); + break; case ConnectionProperties.PURGE_HISTORY_MS: { long tempPurgeHistoryMs = parseValue(value, Long.class, 600 * 1000L); @@ -180,6 +197,24 @@ public void loadValue(Logger logger, String key, String value) { case ConnectionProperties.PLAN_CACHE_EXPIRE_TIME: planCacheExpireTime = parseValue(value, Integer.class, 12 * 3600 * 1000); // 12h break; + case ConnectionProperties.ENABLE_COLUMNAR_PLAN_CACHE: + enableColumnarPlanCache = parseValue(value, Boolean.class, true); + break; + case ConnectionProperties.ENABLE_FLOATING_TYPE_PRECISION: + enableFloatingTypePrecision = parseValue(value, Boolean.class, true); + break; + case ConnectionProperties.DEADLOCK_DETECTION_80_FETCH_TRX_ROWS: + deadlockDetection80FetchTrxRows = parseValue(value, Long.class, 100_000L); + break; + case ConnectionProperties.DEADLOCK_DETECTION_DATA_LOCK_WAITS_THRESHOLD: + deadlockDetectionDataLockWaitsThreshold = parseValue(value, Long.class, 50_000L); + break; + case ConnectionProperties.DEADLOCK_DETECTION_SKIP_ROUND: + deadlockDetectionSkipRound = parseValue(value, Long.class, 10L); + break; + case ConnectionProperties.MAX_KEEP_DEADLOCK_LOGS: + maxKeepDeadlockLogs = parseValue(value, Long.class, 100L); + break; case ConnectionProperties.ENABLE_EXTREME_PERFORMANCE: enableExtremePerformance = parseValue(value, Boolean.class, true); break; @@ -291,6 +326,18 @@ public void loadValue(Logger logger, String key, String value) { case ConnectionProperties.ENABLE_X_PROTO_OPT_FOR_AUTO_SP: xProtoOptForAutoSp = parseValue(value, Boolean.class, false); break; + case ConnectionProperties.CHECK_CCI_TASK_CHECKPOINT_LIMIT: + checkCciCheckpointLimit = parseValue(value, Long.class, 1L); + break; + case ConnectionProperties.SKIP_CHECK_CCI_SCHEDULE_JOB: + skipCheckCciScheduleJob = parseValue(value, Boolean.class, false); + break; + case ConnectionProperties.ENABLE_AUTO_GEN_COLUMNAR_SNAPSHOT: + enableAutoGenColumnarSnapshot = parseValue(value, Boolean.class, false); + break; + case ConnectionProperties.AUTO_GEN_COLUMNAR_SNAPSHOT_PARALLELISM: + autoGenColumnarSnapshotParallelism = parseValue(value, Integer.class, 4); + break; case ConnectionProperties.DATABASE_DEFAULT_SINGLE: databaseDefaultSingle = parseValue(value, Boolean.class, false); break; @@ -349,15 +396,30 @@ public void loadValue(Logger logger, String key, String value) { case ConnectionProperties.INSTANCE_READ_ONLY: instanceReadOnly = parseValue(value, Boolean.class, false); break; - case ConnectionProperties.MIN_SNAPSHOT_KEEP_TIME: - minSnapshotKeepTime = parseValue(value, Integer.class, 5 * 60 * 1000); - break; - case ConnectionProperties.FORBID_AUTO_COMMIT_TRX: - forbidAutoCommitTrx = parseValue(value, Boolean.class, false); - break; case ConnectionProperties.MAPPING_TO_MYSQL_ERROR_CODE: errorCodeMapping = initErrorCodeMapping(value); break; + case ConnectionProperties.ENABLE_ACCURATE_INFO_SCHEMA_TABLES: + enableAccurateInfoSchemaTables = parseValue(value, Boolean.class, false); + break; + case ConnectionProperties.ENABLE_SYNC_POINT: + enableSyncPoint = parseValue(value, Boolean.class, false); + break; + case ConnectionProperties.SYNC_POINT_TASK_INTERVAL: + syncPointTaskInterval = parseValue(value, Integer.class, 5000); + break; + case ConnectionProperties.DISABLE_LEGACY_VARIABLE: + disableLegacyVariable = parseValue(value, Boolean.class, true); + break; + case ConnectionProperties.CCI_INCREMENTAL_CHECK_PARALLELISM: + cciIncrementalCheckParallelism = parseValue(value, Integer.class, 8); + break; + case ConnectionProperties.CCI_INCREMENTAL_CHECK_BATCH_SIZE: + cciIncrementalCheckBatchSize = parseValue(value, Integer.class, 128); + break; + case ConnectionProperties.ENABLE_COLUMNAR_DEBUG: + enableColumnarDebug = parseValue(value, Boolean.class, false); + break; case ConnectionProperties.PRUNING_TIME_WARNING_THRESHOLD: pruningTimeWarningThreshold = parseValue(value, Long.class, 500L); break; @@ -370,9 +432,15 @@ public void loadValue(Logger logger, String key, String value) { case ConnectionProperties.ENABLE_MQ_CACHE_COST_BY_THREAD: enableMQCacheByThread = parseValue(value, Boolean.class, true); break; + case ConnectionProperties.NDV_ALIKE_PRECENTAGE_THRESHOLD: + ndvAlikePercentageThreshold = parseValue(value, Long.class, 10L); + break; case ConnectionProperties.ENABLE_USE_KEY_FOR_ALL_LOCAL_INDEX: enableUseKeyForAllLocalIndex = parseValue(value, Boolean.class, false); break; + case ConnectionProperties.ENABLE_PARAM_TYPE_CHANGE: + enableChangeParamTypeByMeta = parseValue(value, Boolean.class, false); + break; case TddlConstants.BLACK_LIST_CONF: String blockLists = parseValue(value, String.class, ""); List tempBlackList = new ArrayList<>(); @@ -386,7 +454,206 @@ public void loadValue(Logger logger, String key, String value) { } blackListConf = tempBlackList; break; + case ConnectionProperties.ALLOW_COLUMNAR_BIND_MASTER: + columnarBindMaster = parseValue(value, Boolean.class, false); + break; + case ConnectionProperties.SHOW_COLUMNAR_STATUS_USE_SUB_QUERY: + showColumnarStatusUseSubQuery = parseValue(value, Boolean.class, false); + break; + + case ConnectionProperties.OSS_STREAM_BUFFER_SIZE: + ossStreamBufferSize = parseValue(value, Integer.class, 8192); + break; + + case ConnectionProperties.TTL_GLOBAL_SELECT_WORKER_COUNT: { + ttlGlobalSelectWorkerCount = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_GLOBAL_SELECT_WORKER_COUNT.getDefault())); + } + break; + + case ConnectionProperties.TTL_GLOBAL_DELETE_WORKER_COUNT: { + ttlGlobalDeleteWorkerCount = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_GLOBAL_DELETE_WORKER_COUNT.getDefault())); + } + break; + + case ConnectionProperties.TTL_TMP_TBL_MAX_DATA_LENGTH: { + ttlTmpTableMaxDataLength = parseValue(value, Long.class, + Long.valueOf(ConnectionParams.TTL_TMP_TBL_MAX_DATA_LENGTH.getDefault())); + } + break; + + case ConnectionProperties.TTL_TBL_MAX_DATA_FREE_PERCENT: { + ttlTmpTableMaxDataFreePercent = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_TBL_MAX_DATA_FREE_PERCENT.getDefault())); + } + break; + + case ConnectionProperties.TTL_INTRA_TASK_INTERRUPTION_MAX_WAIT_TIME: { + ttlIntraTaskInterruptionMaxWaitTime = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_INTRA_TASK_INTERRUPTION_MAX_WAIT_TIME.getDefault())); + } + break; + + case ConnectionProperties.TTL_INTRA_TASK_MONITOR_EACH_ROUTE_WAIT_TIME: { + ttlIntraTaskMonitorEachRoundWaitTime = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_INTRA_TASK_MONITOR_EACH_ROUTE_WAIT_TIME.getDefault())); + } + break; + + case ConnectionProperties.TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB: { + ttlEnableAutoOptimizeTableInTtlJob = parseValue(value, Boolean.class, + Boolean.valueOf(ConnectionParams.TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB.getDefault())); + } + break; + + case ConnectionProperties.TTL_ENABLE_AUTO_EXEC_OPTIMIZE_TABLE_AFTER_ARCHIVING: { + ttlEnableAutoExecOptimizeTableAfterArchiving = parseValue(value, Boolean.class, + Boolean.valueOf(ConnectionParams.TTL_ENABLE_AUTO_EXEC_OPTIMIZE_TABLE_AFTER_ARCHIVING.getDefault())); + } + break; + + case ConnectionProperties.TTL_SCHEDULED_JOB_MAX_PARALLELISM: { + ttlScheduledJobMaxParallelism = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_SCHEDULED_JOB_MAX_PARALLELISM.getDefault())); + + } + break; + + case ConnectionProperties.TTL_JOB_DEFAULT_BATCH_SIZE: { + ttlJobDefaultBatchSize = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_JOB_DEFAULT_BATCH_SIZE.getDefault())); + } + break; + + case ConnectionProperties.TTL_CLEANUP_BOUND_INTERVAL_COUNT: { + ttlCleanupBoundIntervalCount = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_CLEANUP_BOUND_INTERVAL_COUNT.getDefault())); + } + break; + + case ConnectionProperties.TTL_STOP_ALL_JOB_SCHEDULING: { + ttlStopAllJobScheduling = parseValue(value, Boolean.class, + Boolean.valueOf(ConnectionParams.TTL_STOP_ALL_JOB_SCHEDULING.getDefault())); + } + break; + + case ConnectionProperties.TTL_USE_ARCHIVE_TRANS_POLICY: { + ttlUseArchiveTransPolicy = parseValue(value, Boolean.class, + Boolean.valueOf(ConnectionParams.TTL_USE_ARCHIVE_TRANS_POLICY.getDefault())); + } + break; + + case ConnectionProperties.TTL_SELECT_MERGE_UNION_SIZE: { + ttlSelectMergeUnionSize = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_SELECT_MERGE_UNION_SIZE.getDefault())); + } + break; + + case ConnectionProperties.TTL_SELECT_MERGE_CONCURRENT: { + ttlSelectMergeConcurrent = parseValue(value, Boolean.class, + Boolean.valueOf(ConnectionParams.TTL_SELECT_MERGE_CONCURRENT.getDefault())); + } + break; + case ConnectionProperties.TTL_SELECT_STMT_HINT: { + ttlSelectStmtHint = parseValue(value, String.class, + String.valueOf(ConnectionParams.TTL_SELECT_STMT_HINT.getDefault())); + } + break; + + case ConnectionProperties.TTL_DELETE_STMT_HINT: { + ttlDeleteStmtHint = parseValue(value, String.class, + String.valueOf(ConnectionParams.TTL_DELETE_STMT_HINT.getDefault())); + } + break; + + case ConnectionProperties.TTL_INSERT_STMT_HINT: { + ttlInsertStmtHint = parseValue(value, String.class, + String.valueOf(ConnectionParams.TTL_INSERT_STMT_HINT.getDefault())); + } + break; + + case ConnectionProperties.TTL_OPTIMIZE_TABLE_STMT_HINT: { + ttlOptimizeTableStmtHint = parseValue(value, String.class, + String.valueOf(ConnectionParams.TTL_OPTIMIZE_TABLE_STMT_HINT.getDefault())); + } + break; + + case ConnectionProperties.TTL_ALTER_ADD_PART_STMT_HINT: { + ttlAlterTableAddPartsStmtHint = parseValue(value, String.class, + String.valueOf(ConnectionParams.TTL_ALTER_ADD_PART_STMT_HINT.getDefault())); + } + break; + + case ConnectionProperties.TTL_GROUP_PARALLELISM_ON_DQL_CONN: { + ttlGroupParallelismOnDqlConn = parseValue(value, Long.class, + Long.valueOf(ConnectionParams.TTL_GROUP_PARALLELISM_ON_DQL_CONN.getDefault())); + } + break; + + case ConnectionProperties.TTL_GROUP_PARALLELISM_ON_DML_CONN: { + ttlGroupParallelismOnDmlConn = parseValue(value, Long.class, + Long.valueOf(ConnectionParams.TTL_GROUP_PARALLELISM_ON_DML_CONN.getDefault())); + } + break; + + case ConnectionProperties.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING: { + ttlAddMaxValPartOnCciCreating = parseValue(value, Boolean.class, + Boolean.valueOf(ConnectionParams.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING.getDefault())); + } + break; + + case ConnectionProperties.TTL_MAX_WAIT_ACQUIRE_RATE_PERMITS_PERIODS: { + ttlMaxWaitAcquireRatePermitsPeriods = parseValue(value, Long.class, + Long.valueOf(ConnectionParams.TTL_MAX_WAIT_ACQUIRE_RATE_PERMITS_PERIODS.getDefault())); + } + break; + + case ConnectionProperties.TTL_ENABLE_CLEANUP_ROWS_SPEED_LIMIT: { + ttlEnableCleanupRowsSpeedLimit = parseValue(value, Boolean.class, + Boolean.valueOf(ConnectionParams.TTL_ENABLE_CLEANUP_ROWS_SPEED_LIMIT.getDefault())); + } + break; + + case ConnectionProperties.TTL_CLEANUP_ROWS_SPEED_LIMIT_EACH_DN: { + ttlCleanupRowsSpeedLimitEachDn = parseValue(value, Long.class, + Long.valueOf(ConnectionParams.TTL_CLEANUP_ROWS_SPEED_LIMIT_EACH_DN.getDefault())); + } + break; + + case ConnectionProperties.TTL_IGNORE_MAINTAIN_WINDOW_IN_DDL_JOB: { + ttlIgnoreMaintainWindowInDdlJob = parseValue(value, Boolean.class, + Boolean.valueOf(ConnectionParams.TTL_IGNORE_MAINTAIN_WINDOW_IN_DDL_JOB.getDefault())); + } + break; + + case ConnectionProperties.TTL_GLOBAL_WORKER_DN_RATIO: { + ttlGlobalWorkerDnRatio = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_GLOBAL_WORKER_DN_RATIO.getDefault())); + } + break; + + case ConnectionProperties.TTL_DEFAULT_ARC_PRE_ALLOCATE_COUNT: { + ttlDefaultArcPreAllocateCount = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_DEFAULT_ARC_PRE_ALLOCATE_COUNT.getDefault())); + } + break; + + case ConnectionProperties.TTL_DEFAULT_ARC_POST_ALLOCATE_COUNT: { + ttlDefaultArcPostAllocateCount = parseValue(value, Integer.class, + Integer.valueOf(ConnectionParams.TTL_DEFAULT_ARC_POST_ALLOCATE_COUNT.getDefault())); + } + break; + + case ConnectionProperties.TTL_ENABLE_AUTO_ADD_PARTS_FOR_ARC_CCI: { + ttlEnableAutoAddPartsForArcCci = parseValue(value, Boolean.class, + Boolean.valueOf(ConnectionParams.TTL_ENABLE_AUTO_ADD_PARTS_FOR_ARC_CCI.getDefault())); + } + break; + + case ConnectionProperties.WAIT_FOR_COLUMNAR_COMMIT_MS: + waitForColumnarCommitMS = parseValue(value, Long.class, 60000L); default: FileConfig.getInstance().loadValue(logger, key, value); break; @@ -403,7 +670,7 @@ public long getGeneralDynamicSpeedLimitation() { } private static final long xprotoMaxDnConcurrentDefault = - parseValue(ConnectionParams.XPROTO_MAX_DN_CONCURRENT.getDefault(), Long.class, 500L); + parseValue(ConnectionParams.XPROTO_MAX_DN_CONCURRENT.getDefault(), Long.class, 2000L); private volatile long xprotoMaxDnConcurrent = xprotoMaxDnConcurrentDefault; public long getXprotoMaxDnConcurrent() { @@ -411,7 +678,7 @@ public long getXprotoMaxDnConcurrent() { } private static final long xprotoMaxDnWaitConnectionDefault = - parseValue(ConnectionParams.XPROTO_MAX_DN_WAIT_CONNECTION.getDefault(), Long.class, 100L); + parseValue(ConnectionParams.XPROTO_MAX_DN_WAIT_CONNECTION.getDefault(), Long.class, 2000L); private volatile long xprotoMaxDnWaitConnection = xprotoMaxDnWaitConnectionDefault; public long getXprotoMaxDnWaitConnection() { @@ -472,6 +739,30 @@ public int getXprotoTcpAging() { parseValue(ConnectionParams.BLOCK_CACHE_MEMORY_SIZE_FACTOR.getDefault(), Float.class, 0.6f); private volatile float blockCacheMemoryFactor = blockCacheMemoryFactorDefault; + private static final long preheatedCacheMaxEntriesDefault = + parseValue(ConnectionParams.PREHEATED_CACHE_MAX_ENTRIES.getDefault(), Long.class, 4096L); + private volatile long preheatedCacheMaxEntries = preheatedCacheMaxEntriesDefault; + + private static final long mppQueryResultMaxWaitInMillisDefault = + parseValue(ConnectionParams.MPP_QUERY_RESULT_MAX_WAIT_IN_MILLIS.getDefault(), Long.class, 10L); + private volatile long mppQueryResultMaxWaitInMillis = mppQueryResultMaxWaitInMillisDefault; + + public long getMppQueryResultMaxWaitInMillis() { + return mppQueryResultMaxWaitInMillis; + } + + public long getPreheatedCacheMaxEntries() { + return preheatedCacheMaxEntries; + } + + private static final int cnDivPrecisionIncrementDefault = + parseValue(ConnectionParams.CN_DIV_PRECISION_INCREMENT.getDefault(), Integer.class, 4); + private volatile int cnDivPrecisionIncrement = cnDivPrecisionIncrementDefault; + + public int getCnDivPrecisionIncrement() { + return cnDivPrecisionIncrement; + } + public float getBlockCacheMemoryFactor() { return blockCacheMemoryFactor; } @@ -509,6 +800,12 @@ public long getOptimizerAlertLogInterval() { return optimizerAlertLogInterval; } + private volatile boolean enableHotGsiEvolution = true; + + public boolean enableHotGsiEvolution() { + return enableHotGsiEvolution; + } + private volatile int tpSlowAlertThreshold = 10; public int getTpSlowAlertThreshold() { @@ -581,6 +878,42 @@ public int planCacheExpireTime() { return planCacheExpireTime; } + private volatile boolean enableColumnarPlanCache = true; + + public boolean colPlanCache() { + return enableColumnarPlanCache; + } + + private volatile boolean enableFloatingTypePrecision = true; + + public boolean isEnableFloatingTypePrecision() { + return enableFloatingTypePrecision; + } + + private volatile long deadlockDetection80FetchTrxRows = 100_000L; + + public long getDeadlockDetection80FetchTrxRows() { + return deadlockDetection80FetchTrxRows; + } + + private volatile long deadlockDetectionDataLockWaitsThreshold = 50_000L; + + public long getDeadlockDetectionDataLockWaitsThreshold() { + return deadlockDetectionDataLockWaitsThreshold; + } + + private volatile long deadlockDetectionSkipRound = 10L; + + public long getDeadlockDetectionSkipRound() { + return deadlockDetectionSkipRound; + } + + private volatile long maxKeepDeadlockLogs = 100L; + + public long getMaxKeepDeadlockLogs() { + return maxKeepDeadlockLogs; + } + private static final int maxPartitionColumnCountDefault = parseValue(ConnectionParams.MAX_PARTITION_COLUMN_COUNT.getDefault(), Integer.class, 3); private volatile int maxPartitionColumnCount = maxPartitionColumnCountDefault; @@ -705,6 +1038,12 @@ public boolean enableFollowReadForPolarDBX() { return supportFollowRead; } + private volatile boolean enableShareReadviewInRc = false; + + public boolean isEnableShareReadviewInRc() { + return enableShareReadviewInRc; + } + /** * Slow transaction threshold, unit: microsecond, default 3s. */ @@ -753,6 +1092,30 @@ public boolean enableXProtoOptForAutoSp() { return xProtoOptForAutoSp; } + private volatile long checkCciCheckpointLimit = 1; + + public long getCheckCciCheckpointLimit() { + return checkCciCheckpointLimit; + } + + private volatile boolean skipCheckCciScheduleJob = false; + + public boolean isSkipCheckCciScheduleJob() { + return skipCheckCciScheduleJob; + } + + private volatile boolean enableAutoGenColumnarSnapshot = true; + + public boolean isEnableAutoGenColumnarSnapshot() { + return enableAutoGenColumnarSnapshot; + } + + private volatile int autoGenColumnarSnapshotParallelism = 4; + + public int getAutoGenColumnarSnapshotParallelism() { + return autoGenColumnarSnapshotParallelism; + } + private volatile boolean enableRemoteConsumeLog = false; public boolean enableRemoteConsumeLog() { @@ -809,6 +1172,16 @@ public void setSupportSingleDbMultiTbs(boolean supportSingleDbMultiTbs) { this.supportSingleDbMultiTbs = supportSingleDbMultiTbs; } + private volatile boolean enableChangeParamTypeByMeta = false; + + public boolean isEnableChangeParamTypeByMeta() { + return enableChangeParamTypeByMeta; + } + + public void setEnableChangeParamTypeByMeta(boolean enableChangeParamTypeByMeta) { + this.enableChangeParamTypeByMeta = enableChangeParamTypeByMeta; + } + public boolean isSupportRemoveDdl() { return supportRemoveDdl; } @@ -867,6 +1240,12 @@ public void setColumnarOssDirectory(String columnarOssDirectory) { this.columnarOssDirectory = columnarOssDirectory; } + int ossStreamBufferSize = 8192; + + public int getOssStreamBufferSize() { + return ossStreamBufferSize; + } + /** * Default 60s. */ @@ -918,21 +1297,8 @@ public boolean isInstanceReadOnly() { return instanceReadOnly; } - // 5 min. - private volatile long minSnapshotKeepTime = 5 * 60 * 1000; - - public long getMinSnapshotKeepTime() { - return minSnapshotKeepTime; - } - - private volatile boolean forbidAutoCommitTrx = false; - private volatile Map errorCodeMapping = new HashMap<>(); - public boolean isForbidAutoCommitTrx() { - return forbidAutoCommitTrx; - } - public Map getErrorCodeMapping() { return errorCodeMapping; } @@ -948,6 +1314,12 @@ private Map initErrorCodeMapping(String mapping) { return new HashMap<>(); } + private volatile boolean enableAccurateInfoSchemaTables = false; + + public boolean isEnableAccurateInfoSchemaTables() { + return enableAccurateInfoSchemaTables; + } + private boolean enableUseKeyForAllLocalIndex = Boolean.valueOf(ConnectionParams.ENABLE_USE_KEY_FOR_ALL_LOCAL_INDEX.getDefault()); @@ -955,6 +1327,45 @@ public boolean isEnableUseKeyForAllLocalIndex() { return enableUseKeyForAllLocalIndex; } + private volatile boolean enableSyncPoint = false; + + public boolean isEnableSyncPoint() { + return enableSyncPoint; + } + + /** + * Default 5 * 60 * 1000 ms. + */ + private volatile long syncPointTaskInterval = 5 * 60 * 1000; + + public long getSyncPointTaskInterval() { + return syncPointTaskInterval; + } + + private volatile boolean disableLegacyVariable = true; + + public boolean isDisableLegacyVariable() { + return disableLegacyVariable; + } + + private volatile int cciIncrementalCheckParallelism = 8; + + public int getCciIncrementalCheckParallelism() { + return cciIncrementalCheckParallelism; + } + + private volatile int cciIncrementalCheckBatchSize = 128; + + public int getCciIncrementalCheckBatchSize() { + return cciIncrementalCheckBatchSize; + } + + private volatile boolean enableColumnarDebug = false; + + public boolean isEnableColumnarDebug() { + return enableColumnarDebug; + } + // pruning warning threshold in microsecond private volatile long pruningTimeWarningThreshold = 500; @@ -962,6 +1373,13 @@ public long getPruningTimeWarningThreshold() { return pruningTimeWarningThreshold; } + // ndv alike percentage threshold + private volatile long ndvAlikePercentageThreshold = 10L; + + public long getNdvAlikePercentageThreshold() { + return ndvAlikePercentageThreshold; + } + private volatile boolean enablePruningIn = true; private volatile boolean enablePruningInDml = true; @@ -974,12 +1392,261 @@ public boolean isEnablePruningInDml() { return enablePruningInDml; } + private volatile boolean columnarBindMaster = false; + + public boolean allowColumnarBindMaster() { + return columnarBindMaster; + } + + private volatile boolean existColumnarNodes = false; + + public void existColumnarNodes(boolean enable) { + this.existColumnarNodes = enable; + } + + public boolean existColumnarNodes() { + return existColumnarNodes; + } + private volatile List blackListConf = new ArrayList<>(); public List getBlacklistConf() { return blackListConf; } + private volatile boolean showColumnarStatusUseSubQuery = + Boolean.parseBoolean(ConnectionParams.SHOW_COLUMNAR_STATUS_USE_SUB_QUERY.getDefault()); + + public boolean isShowColumnarStatusUseSubQuery() { + return showColumnarStatusUseSubQuery; + } + + public volatile int ttlGlobalSelectWorkerCount = + Integer.valueOf(ConnectionParams.TTL_GLOBAL_SELECT_WORKER_COUNT.getDefault()); + + public volatile int ttlGlobalDeleteWorkerCount = + Integer.valueOf(ConnectionParams.TTL_GLOBAL_DELETE_WORKER_COUNT.getDefault()); + + public volatile long ttlTmpTableMaxDataLength = + Long.valueOf(ConnectionParams.TTL_TMP_TBL_MAX_DATA_LENGTH.getDefault()); + + public volatile int ttlTmpTableMaxDataFreePercent = + Integer.valueOf(ConnectionParams.TTL_TBL_MAX_DATA_FREE_PERCENT.getDefault()); + ; + + public volatile int ttlIntraTaskInterruptionMaxWaitTime = + Integer.valueOf(ConnectionParams.TTL_INTRA_TASK_INTERRUPTION_MAX_WAIT_TIME.getDefault()); + + public volatile int ttlIntraTaskMonitorEachRoundWaitTime = + Integer.valueOf(ConnectionParams.TTL_INTRA_TASK_MONITOR_EACH_ROUTE_WAIT_TIME.getDefault()); + + public volatile int ttlScheduledJobMaxParallelism = + Integer.valueOf(ConnectionParams.TTL_SCHEDULED_JOB_MAX_PARALLELISM.getDefault()); + ; + + public volatile boolean ttlEnableAutoOptimizeTableInTtlJob = + Boolean.valueOf(ConnectionParams.TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB.getDefault()); + + public volatile boolean ttlEnableAutoExecOptimizeTableAfterArchiving = + Boolean.valueOf(ConnectionParams.TTL_ENABLE_AUTO_EXEC_OPTIMIZE_TABLE_AFTER_ARCHIVING.getDefault()); + ; + public volatile int ttlJobDefaultBatchSize = + Integer.valueOf(ConnectionParams.TTL_JOB_DEFAULT_BATCH_SIZE.getDefault()); + + public volatile int ttlCleanupBoundIntervalCount = + Integer.valueOf(ConnectionParams.TTL_CLEANUP_BOUND_INTERVAL_COUNT.getDefault()); + + public volatile boolean ttlStopAllJobScheduling = + Boolean.valueOf(ConnectionParams.TTL_STOP_ALL_JOB_SCHEDULING.getDefault()); + + public volatile boolean ttlUseArchiveTransPolicy = + Boolean.valueOf(ConnectionParams.TTL_USE_ARCHIVE_TRANS_POLICY.getDefault()); + + public volatile int ttlSelectMergeUnionSize = + Integer.valueOf(ConnectionParams.TTL_SELECT_MERGE_UNION_SIZE.getDefault()); + + public volatile boolean ttlSelectMergeConcurrent = + Boolean.valueOf(ConnectionParams.TTL_SELECT_MERGE_CONCURRENT.getDefault()); + + public volatile String ttlSelectStmtHint = + String.valueOf(ConnectionParams.TTL_SELECT_STMT_HINT.getDefault()); + + public volatile String ttlDeleteStmtHint = + String.valueOf(ConnectionParams.TTL_DELETE_STMT_HINT.getDefault()); + + public volatile String ttlInsertStmtHint = + String.valueOf(ConnectionParams.TTL_INSERT_STMT_HINT.getDefault()); + + public volatile String ttlOptimizeTableStmtHint = + String.valueOf(ConnectionParams.TTL_OPTIMIZE_TABLE_STMT_HINT.getDefault()); + + public volatile String ttlAlterTableAddPartsStmtHint = + String.valueOf(ConnectionParams.TTL_ALTER_ADD_PART_STMT_HINT.getDefault()); + + public volatile Long ttlGroupParallelismOnDqlConn = + Long.valueOf(ConnectionParams.TTL_GROUP_PARALLELISM_ON_DQL_CONN.getDefault()); + + public volatile Long ttlGroupParallelismOnDmlConn = + Long.valueOf(ConnectionParams.TTL_GROUP_PARALLELISM_ON_DML_CONN.getDefault()); + + public volatile Boolean ttlAddMaxValPartOnCciCreating = + Boolean.valueOf(ConnectionParams.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING.getDefault()); + + public volatile Long ttlMaxWaitAcquireRatePermitsPeriods = + Long.valueOf(ConnectionParams.TTL_MAX_WAIT_ACQUIRE_RATE_PERMITS_PERIODS.getDefault()); + + public volatile Boolean ttlEnableCleanupRowsSpeedLimit = + Boolean.valueOf(ConnectionParams.TTL_ENABLE_CLEANUP_ROWS_SPEED_LIMIT.getDefault()); + + public volatile Long ttlCleanupRowsSpeedLimitEachDn = + Long.valueOf(ConnectionParams.TTL_CLEANUP_ROWS_SPEED_LIMIT_EACH_DN.getDefault()); + + public volatile Boolean ttlIgnoreMaintainWindowInDdlJob = + Boolean.valueOf(ConnectionParams.TTL_IGNORE_MAINTAIN_WINDOW_IN_DDL_JOB.getDefault()); + + public volatile int ttlGlobalWorkerDnRatio = + Integer.valueOf(ConnectionParams.TTL_GLOBAL_WORKER_DN_RATIO.getDefault()); + + public volatile int ttlDefaultArcPreAllocateCount = + Integer.valueOf(ConnectionParams.TTL_DEFAULT_ARC_PRE_ALLOCATE_COUNT.getDefault()); + + public volatile int ttlDefaultArcPostAllocateCount = + Integer.valueOf(ConnectionParams.TTL_DEFAULT_ARC_POST_ALLOCATE_COUNT.getDefault()); + + public volatile boolean ttlEnableAutoAddPartsForArcCci = + Boolean.valueOf(ConnectionParams.TTL_ENABLE_AUTO_ADD_PARTS_FOR_ARC_CCI.getDefault()); + + public int getTtlGlobalDeleteWorkerCount() { + return ttlGlobalDeleteWorkerCount; + } + + public long getTtlTmpTableMaxDataLength() { + return ttlTmpTableMaxDataLength; + } + + public int getTtlTmpTableMaxDataFreePercent() { + return ttlTmpTableMaxDataFreePercent; + } + + public int getTtlIntraTaskInterruptionMaxWaitTime() { + return ttlIntraTaskInterruptionMaxWaitTime; + } + + public int getTtlScheduledJobMaxParallelism() { + return ttlScheduledJobMaxParallelism; + } + + public boolean isTtlEnableAutoOptimizeTableInTtlJob() { + return ttlEnableAutoOptimizeTableInTtlJob; + } + + public boolean isTtlEnableAutoExecOptimizeTableAfterArchiving() { + return ttlEnableAutoExecOptimizeTableAfterArchiving; + } + + public int getTtlIntraTaskMonitorEachRoundWaitTime() { + return ttlIntraTaskMonitorEachRoundWaitTime; + } + + public int getTtlJobDefaultBatchSize() { + return ttlJobDefaultBatchSize; + } + + public int getTtlCleanupBoundIntervalCount() { + return ttlCleanupBoundIntervalCount; + } + + public boolean isTtlStopAllJobScheduling() { + return ttlStopAllJobScheduling; + } + + public boolean isTtlUseArchiveTransPolicy() { + return ttlUseArchiveTransPolicy; + } + + public int getTtlSelectMergeUnionSize() { + return ttlSelectMergeUnionSize; + } + + public boolean isTtlSelectMergeConcurrent() { + return ttlSelectMergeConcurrent; + } + + public String getTtlSelectStmtHint() { + return ttlSelectStmtHint; + } + + public String getTtlDeleteStmtHint() { + return ttlDeleteStmtHint; + } + + public String getTtlInsertStmtHint() { + return ttlInsertStmtHint; + } + + public Long getTtlGroupParallelismOnDmlConn() { + return ttlGroupParallelismOnDmlConn; + } + + public Long getTtlGroupParallelismOnDqlConn() { + return ttlGroupParallelismOnDqlConn; + } + + public String getTtlOptimizeTableStmtHint() { + return ttlOptimizeTableStmtHint; + } + + public String getTtlAlterTableAddPartsStmtHint() { + return ttlAlterTableAddPartsStmtHint; + } + + public Boolean getTtlAddMaxValPartOnCciCreating() { + return ttlAddMaxValPartOnCciCreating; + } + + public Long getTtlCleanupRowsSpeedLimitEachDn() { + return ttlCleanupRowsSpeedLimitEachDn; + } + + public Boolean getTtlEnableCleanupRowsSpeedLimit() { + return ttlEnableCleanupRowsSpeedLimit; + } + + public Long getTtlMaxWaitAcquireRatePermitsPeriods() { + return ttlMaxWaitAcquireRatePermitsPeriods; + } + + public Boolean getTtlIgnoreMaintainWindowInDdlJob() { + return ttlIgnoreMaintainWindowInDdlJob; + } + + public int getTtlGlobalSelectWorkerCount() { + return ttlGlobalSelectWorkerCount; + } + + public int getTtlGlobalWorkerDnRatio() { + return ttlGlobalWorkerDnRatio; + } + + public int getTtlDefaultArcPreAllocateCount() { + return ttlDefaultArcPreAllocateCount; + } + + public int getTtlDefaultArcPostAllocateCount() { + return ttlDefaultArcPostAllocateCount; + } + + public boolean getTtlEnableAutoAddPartsForArcCci() { + return ttlEnableAutoAddPartsForArcCci; + } + + private volatile long waitForColumnarCommitMS = + Long.parseLong(ConnectionParams.WAIT_FOR_COLUMNAR_COMMIT_MS.getDefault()); + + public long getWaitForColumnarCommitMS() { + return waitForColumnarCommitMS; + } + public static T parseValue(String value, Class type, T defaultValue) { if (value == null) { return defaultValue; @@ -1003,4 +1670,5 @@ public static T parseValue(String value, Class type, T defaultValue) { } private static final DynamicConfig instance = new DynamicConfig(); + } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/MppConfig.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/MppConfig.java index 27871e17f..7ff6e93f2 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/MppConfig.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/properties/MppConfig.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.stream.Collectors; +import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_MPP_UI; import static com.alibaba.polardbx.common.properties.ConnectionProperties.MPP_ALLOCATOR_SIZE; import static com.alibaba.polardbx.common.properties.ConnectionProperties.MPP_AP_PRIORITY; import static com.alibaba.polardbx.common.properties.ConnectionProperties.MPP_CLUSTER_NAME; @@ -274,19 +275,32 @@ public void loadValue(Logger logger, String key, String value) { case MPP_CLUSTER_NAME: defaultCluster = parseValue(value, String.class, DEFAULT_MPP_CLUSTER_NAME); break; - case MPP_SPILL_PATHS: List spillPathsSplit = ImmutableList.copyOf( Splitter.on(",").trimResults().omitEmptyStrings().split(value)); spillPaths = spillPathsSplit.stream().map(path -> Paths.get(path)).collect(Collectors.toList()); break; + case ENABLE_MPP_UI: + this.enableMppUI = parseValue(value, Boolean.class, DEFAULT_ENABLE_MPP_UI); + break; default: logger.warn("unknown mpp config:" + key + ",value=" + value); } } } + //-------------------------------------------- web UI ---------------------------------------------------- + private static final boolean DEFAULT_ENABLE_MPP_UI = true; + /** + * Requires restart + */ + private boolean enableMppUI = DEFAULT_ENABLE_MPP_UI; + + public boolean isEnableMppUI() { + return enableMppUI; + } + //-------------------------------------------- query thread pool------------------------------------------ private static final int DEFAULT_MPP_QUERY_MANAGER_THREAD_POOL_SIZE = 1; private int queryManagerThreadPoolSize = DEFAULT_MPP_QUERY_MANAGER_THREAD_POOL_SIZE; diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/scheduler/FiredScheduledJobState.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/scheduler/FiredScheduledJobState.java index 5fb445138..14e1c525c 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/scheduler/FiredScheduledJobState.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/scheduler/FiredScheduledJobState.java @@ -18,6 +18,16 @@ public enum FiredScheduledJobState { + /** + *
+     *     state machine:
+     * status of scheduled_job      :    ENABLED
+     * status of fired_scheduled_job:  ->QUEUED(init)   ->RUNNING  ->SUCCESS
+     *                                                  ->FAILED
+     *                                                  ->SKIPED
+     *                                                  ->INTERUPTED (actively exit by task itself)
+     * 
+ */ QUEUED, RUNNING, SUCCESS, diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/trx/ISyncPointExecutor.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/trx/ISyncPointExecutor.java new file mode 100644 index 000000000..044200d53 --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/trx/ISyncPointExecutor.java @@ -0,0 +1,11 @@ +package com.alibaba.polardbx.common.trx; + +/** + * @author yaozhili + */ +public interface ISyncPointExecutor { + /** + * @return true if success + */ + boolean execute(); +} diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/trx/TrxLogTableConstants.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/trx/TrxLogTableConstants.java index f5f24bd09..deb5fd3f1 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/trx/TrxLogTableConstants.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/trx/TrxLogTableConstants.java @@ -107,7 +107,7 @@ public class TrxLogTableConstants { "CREATE TABLE IF NOT EXISTS " + SystemTables.POLARDBX_GLOBAL_TX_LOG_TABLE + " (\n" + " `TXID` BIGINT UNSIGNED NOT NULL,\n" - + " `TRX_SEQ` BIGINT UNSIGNED NOT NULL DEFAULT 18446744073709551615 COMMENT \"DEFAULT INVALID_SEQUENCE_NUMBER\",\n" + + " `TRX_SEQ` BIGINT UNSIGNED NOT NULL DEFAULT 18446744073709551615 COMMENT 'DEFAULT INVALID_SEQUENCE_NUMBER',\n" + " `N_PARTICIPANTS` INT UNSIGNED NOT NULL DEFAULT 0,\n" + " PRIMARY KEY (`TXID`)\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"; @@ -121,7 +121,7 @@ public class TrxLogTableConstants { "CREATE TABLE IF NOT EXISTS " + SystemTables.POLARDBX_GLOBAL_TX_LOG_TABLE_TMP + " (\n" + " `TXID` BIGINT UNSIGNED NOT NULL,\n" - + " `TRX_SEQ` BIGINT UNSIGNED NOT NULL DEFAULT 18446744073709551615 COMMENT \"DEFAULT INVALID_SEQUENCE_NUMBER\",\n" + + " `TRX_SEQ` BIGINT UNSIGNED NOT NULL DEFAULT 18446744073709551615 COMMENT 'DEFAULT INVALID_SEQUENCE_NUMBER',\n" + " `N_PARTICIPANTS` INT UNSIGNED NOT NULL DEFAULT 0,\n" + " PRIMARY KEY (`TXID`)\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"; @@ -145,6 +145,10 @@ public class TrxLogTableConstants { "select table_name from information_schema.tables where table_schema = '%s' and table_name like '%s%%'", SystemTables.POLARDBX_GLOBAL_TX_LOG_TABLE_DB, SystemTables.POLARDBX_GLOBAL_TX_LOG_TABLE_PREFIX); + public static final String QUERY_TABLE_ROWS_TX_TABLE_V2 = String.format( + "select table_rows from information_schema.tables where table_schema = '%s' and table_name = '%s'", + SystemTables.POLARDBX_GLOBAL_TX_LOG_TABLE_DB, SystemTables.POLARDBX_GLOBAL_TX_LOG_TABLE_PREFIX); + public static final String SELECT_MAX_TX_ID_IN_ARCHIVE = "SELECT max(TXID) FROM " + SystemTables.POLARDBX_GLOBAL_TX_LOG_TABLE_ARCHIVE; @@ -195,13 +199,18 @@ public class TrxLogTableConstants { public static final String EXISTS_GLOBAL_TX_TABLE_V2 = "SELECT 1 FROM information_schema.tables WHERE table_schema = '" + SystemTables.POLARDBX_GLOBAL_TX_LOG_TABLE_DB + - "' AND table_name = '" + SystemTables.POLARDBX_GLOBAL_TX_LOG_TABLE_ARCHIVE_TABLE + "'"; + "' AND table_name = '" + SystemTables.POLARDBX_GLOBAL_TX_LOG_TABLE_PREFIX + "'"; /** * 18446744073709551611 is a magic snapshot sequence. Using it you can see prepared trx. */ public static final String RECOVER_TIMESTAMP_SQL = "SET innodb_snapshot_seq = 18446744073709551611"; + /** + * Socket timeout for handling trx log table. + */ + public static final int TRX_LOG_SOCKET_TIMEOUT = 10_000; + public static ByteString APPEND_TRX_DIGEST; public static ByteString APPEND_TRX_WITH_TS_DIGEST; public static ByteString SELECT_BY_ID_DIGEST; diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/Assert.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/Assert.java index 9a9ed1bc3..2cdefb75f 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/Assert.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/Assert.java @@ -49,4 +49,11 @@ public static void fail(String message) { throw new TddlRuntimeException(ErrorCode.ERR_ASSERT_FAIL, message); } + public static void check(boolean expression) { + if (!expression) { + throw new TddlRuntimeException(ErrorCode.ERR_ASSERT_TRUE); + } + } + + } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/ConcurrentHashSet.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/ConcurrentHashSet.java new file mode 100644 index 000000000..54f7e15ef --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/ConcurrentHashSet.java @@ -0,0 +1,77 @@ +package com.alibaba.polardbx.common.utils; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class ConcurrentHashSet extends AbstractSet implements Set { + private final Map _map = new ConcurrentHashMap(); + private transient Set _keys; + + public ConcurrentHashSet() { + this._keys = this._map.keySet(); + } + + public boolean add(E e) { + return this._map.put(e, Boolean.TRUE) == null; + } + + public void clear() { + this._map.clear(); + } + + public boolean contains(Object o) { + return this._map.containsKey(o); + } + + public boolean containsAll(Collection c) { + return this._keys.containsAll(c); + } + + public boolean equals(Object o) { + return o == this || this._keys.equals(o); + } + + public int hashCode() { + return this._keys.hashCode(); + } + + public boolean isEmpty() { + return this._map.isEmpty(); + } + + public Iterator iterator() { + return this._keys.iterator(); + } + + public boolean remove(Object o) { + return this._map.remove(o) != null; + } + + public boolean removeAll(Collection c) { + return this._keys.removeAll(c); + } + + public boolean retainAll(Collection c) { + return this._keys.retainAll(c); + } + + public int size() { + return this._map.size(); + } + + public Object[] toArray() { + return this._keys.toArray(); + } + + public T[] toArray(T[] a) { + return this._keys.toArray(a); + } + + public String toString() { + return this._keys.toString(); + } +} \ No newline at end of file diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/GeneralUtil.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/GeneralUtil.java index 39f122297..007bd4f21 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/GeneralUtil.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/GeneralUtil.java @@ -30,6 +30,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringReader; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; @@ -49,6 +51,20 @@ public class GeneralUtil { private static String followDelayMessage = "The follow exists delay, please use 'show storage' command to check latency"; + public static String PRIMARY = "primary"; + + /** + * is this index primary + * + * @return is primary + */ + public static boolean isPrimary(String indexName) { + if (StringUtils.isEmpty(indexName)) { + return false; + } + return PRIMARY.equals(indexName.trim().toLowerCase()); + } + public static boolean isEmpty(Map map) { return null == map || map.isEmpty(); } @@ -199,6 +215,17 @@ public static RuntimeException mergeException(List exceptions) { return new TddlNestableRuntimeException(first); } + public static boolean isWithinPercentage(long num1, long num2, double percentageThreshold) { + // Calculate the absolute difference between the two numbers + long diff = Math.abs(num1 - num2); + + // Calculate the threshold value based on the larger number + long thresholdValue = (long) (Math.max(num1, num2) * (percentageThreshold / 100.0)); + + // Compare the difference with the threshold value + return diff <= thresholdValue; + } + public static InputStream getInputStream(String fileName) { if (fileName.charAt(0) == '/') { fileName = fileName.substring(1); @@ -482,6 +509,17 @@ public static List prepareParam(List paramLi return r; } + public static String sampleString(float sampleRate) { + String sampleRateStr = (sampleRate + "").toLowerCase(); + if (sampleRateStr.contains("e-")) { + int scale = Integer.parseInt(sampleRateStr.split("e-")[1]); + return new BigDecimal(sampleRate).setScale(scale, RoundingMode.HALF_UP).stripTrailingZeros() + .toPlainString(); + } else { + return sampleRateStr; + } + } + /** * decode statistic trace info, like : * Catalog:tpch_100g,lineitem,l_shipdate,null_1998-09-02 @@ -568,6 +606,41 @@ public static void close(Closeable x) { } } + /** + * Converts a floating-point number to a string, handling small values + * represented in scientific notation by converting them to a fixed-point + * decimal representation. + * + * @param sampleRate The sample rate, which may be represented in scientific notation + * @return The formatted string representation of the sample rate + */ + public static String formatSampleRate(float sampleRate) { + // Convert the float to a string + String sampleRateStr = Float.toString(sampleRate).toLowerCase(); + + // Check if the string represents a small value in scientific notation + // Split the string to extract the exponent part + String[] parts = sampleRateStr.split("e-"); + if (parts.length == 2) { + try { + // Parse the exponent as an integer + int scale = Integer.parseInt(parts[1]); + // Use BigDecimal for precise arithmetic + BigDecimal bigDecimalSampleRate = new BigDecimal(sampleRate); + // Set the scale and round the number + BigDecimal formattedSampleRate = bigDecimalSampleRate.setScale(scale, RoundingMode.HALF_UP); + // Remove trailing zeros + return formattedSampleRate.stripTrailingZeros().toPlainString(); + } catch (NumberFormatException e) { + // Return the original string if parsing fails + return sampleRateStr; + } + } else { + // Return the string directly if it does not represent a small value or the format is incorrect + return sampleRateStr; + } + } + /** * remove the suffix of gsi name */ @@ -575,6 +648,7 @@ public static String removeIdxSuffix(String source) { if (source.contains("_$")) { int targetIndex = source.indexOf("_$"); int secondIndex = source.indexOf(",", targetIndex); + secondIndex = secondIndex == -1 ? source.indexOf("\n", targetIndex) : secondIndex; if (secondIndex != -1) { return source.substring(0, targetIndex) + source.substring(secondIndex); } else { diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/LockUtil.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/LockUtil.java index 1015f54ba..2ca715f6e 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/LockUtil.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/LockUtil.java @@ -19,18 +19,22 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.jdbc.IConnection; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.function.Consumer; -import java.util.function.Function; +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; /** * @author yaozhili */ public class LockUtil { + private static final Logger logger = LoggerFactory.getLogger(LockUtil.class); + /** * Wrapped operations with specified lock_wait_timeout to avoid long MDL-wait. */ @@ -61,8 +65,7 @@ public static void wrapWithLockWaitTimeout(Connection conn, int lockWaitTimeout, } } } else { - throw new TddlRuntimeException(ErrorCode.ERR_TRANS_LOG, - "Get wrong lock_wait_timeout value: " + originLockWaitTimeout); + task.run(); } } @@ -93,8 +96,33 @@ public static void wrapWithInnodbLockWaitTimeout(Connection conn, int lockWaitTi } } } else { - throw new TddlRuntimeException(ErrorCode.ERR_TRANS_LOG, - "Get wrong innodb_lock_wait_timeout value: " + originLockWaitTimeout); + task.run(); + } + } + + /** + * Wrapped operations with specified lock_wait_timeout to avoid long MDL-wait. + */ + public static T wrapWithSocketTimeout(Connection conn, int socketTimeout, Executor socketTimeoutExecutor, + Callable task) throws SQLException { + int originNetworkTimeout = conn.getNetworkTimeout(); + // Only decrease the socket timeout, not increase it. + try { + if (0 == originNetworkTimeout || originNetworkTimeout > socketTimeout) { + conn.setNetworkTimeout(socketTimeoutExecutor, socketTimeout); + try { + return task.call(); + } finally { + conn.setNetworkTimeout(socketTimeoutExecutor, originNetworkTimeout); + } + } else { + return task.call(); + } + } catch (SQLException e) { + throw e; + } catch (Exception e) { + logger.error("wrapWithSocketTimeout error: ", e); + throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, e); } } } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/Pair.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/Pair.java index 4af0d7fae..202f1656b 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/Pair.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/Pair.java @@ -16,20 +16,28 @@ package com.alibaba.polardbx.common.utils; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + public final class Pair { private final K key; private final V value; - public Pair(K key, V value){ + @JsonCreator + public Pair( + @JsonProperty("key") K key, + @JsonProperty("value") V value) { this.key = key; this.value = value; } + @JsonProperty public K getKey() { return key; } + @JsonProperty public V getValue() { return value; } @@ -66,15 +74,23 @@ public int hashCode() { @SuppressWarnings("rawtypes") @Override public boolean equals(Object obj) { - if (this == obj) return true; - if (!(obj instanceof Pair)) return false; + if (this == obj) { + return true; + } + if (!(obj instanceof Pair)) { + return false; + } Pair that = (Pair) obj; return isEquals(this.key, that.key) && isEquals(this.value, that.value); } private boolean isEquals(Object o1, Object o2) { - if (o1 == o2) return true; - if (o1 == null) return o2 == null; + if (o1 == o2) { + return true; + } + if (o1 == null) { + return o2 == null; + } return o1.equals(o2); } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/TStringUtil.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/TStringUtil.java index 5c0d3effb..6abc0fa8f 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/TStringUtil.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/TStringUtil.java @@ -26,11 +26,7 @@ import java.lang.reflect.Method; import java.math.BigDecimal; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class TStringUtil extends StringUtils { @@ -846,4 +842,7 @@ public static String concatTableName(String schema, String table) { return backQuote(schema) + "." + backQuote(table); } + public static String quote(String str) { + return str != null ? "'" + str + "'" : null; + } } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/convertor/CommonAndRowValueConvertor.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/convertor/CommonAndRowValueConvertor.java index e5909d9bb..102f97498 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/convertor/CommonAndRowValueConvertor.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/convertor/CommonAndRowValueConvertor.java @@ -17,7 +17,7 @@ package com.alibaba.polardbx.common.utils.convertor; import com.alibaba.polardbx.common.datatype.RowValue; -import org.apache.curator.shaded.com.google.common.collect.Lists; +import com.google.common.collect.Lists; public class CommonAndRowValueConvertor { diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/encrypt/aes/AesCipher.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/encrypt/aes/AesCipher.java index 8c21c2f48..cc7129bc9 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/encrypt/aes/AesCipher.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/encrypt/aes/AesCipher.java @@ -39,16 +39,19 @@ public class AesCipher { public static BlockCipher getCipher(BlockEncryptionMode encryptionMode) { switch (encryptionMode.mode) { + // Cipher Block Chaining case CBC: - return CBC_BLOCK_CIPHER; + return new CBCBlockCipher(AES_ENGINE); + // Cipher FeedBack case CFB1: - return CFB_1_CIPHER; + return new Cfb1BlockCipher(AES_ENGINE); case CFB8: - return CFB_8_CIPHER; + return new CFBBlockCipher(AES_ENGINE, 8); case CFB128: - return CFB_128_CIPHER; + return new CFBBlockCipher(AES_ENGINE, 128); + // Output FeedBack case OFB: - return OFB_CIPHER; + return new OFBBlockCipher(AES_ENGINE, 128); case ECB: default: } @@ -57,6 +60,6 @@ public static BlockCipher getCipher(BlockEncryptionMode encryptionMode) { } public static EcbBlockCipher getEcbCipher() { - return ECB_CIPHER; + return new EcbBlockCipher(); } } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/logger/LoggerFactory.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/logger/LoggerFactory.java index 27cfe2bcb..8a0332d72 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/logger/LoggerFactory.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/logger/LoggerFactory.java @@ -18,7 +18,6 @@ import com.alibaba.polardbx.common.utils.logger.jcl.JclLoggerAdapter; import com.alibaba.polardbx.common.utils.logger.jdk.JdkLoggerAdapter; -import com.alibaba.polardbx.common.utils.logger.log4j.Log4jLoggerAdapter; import com.alibaba.polardbx.common.utils.logger.slf4j.Slf4jLoggerAdapter; import com.alibaba.polardbx.common.utils.logger.support.FailsafeLogger; @@ -43,8 +42,6 @@ private LoggerFactory() { setLoggerAdapter(new Slf4jLoggerAdapter()); } else if ("jcl".equals(logger)) { setLoggerAdapter(new JclLoggerAdapter()); - } else if ("log4j".equals(logger)) { - setLoggerAdapter(new Log4jLoggerAdapter()); } else if ("jdk".equals(logger)) { setLoggerAdapter(new JdkLoggerAdapter()); } else { @@ -52,13 +49,9 @@ private LoggerFactory() { setLoggerAdapter(new Slf4jLoggerAdapter()); } catch (Throwable e1) { try { - setLoggerAdapter(new Log4jLoggerAdapter()); - } catch (Throwable e2) { - try { - setLoggerAdapter(new JclLoggerAdapter()); - } catch (Throwable e3) { - setLoggerAdapter(new JdkLoggerAdapter()); - } + setLoggerAdapter(new JclLoggerAdapter()); + } catch (Throwable e3) { + setLoggerAdapter(new JdkLoggerAdapter()); } } } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/logger/MDC.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/logger/MDC.java index d7d655908..6e610cb18 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/logger/MDC.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/logger/MDC.java @@ -19,8 +19,6 @@ import com.alibaba.polardbx.common.utils.logger.jcl.JclLoggerAdapter; import com.alibaba.polardbx.common.utils.logger.jcl.JclMDC; import com.alibaba.polardbx.common.utils.logger.jdk.JdkMDC; -import com.alibaba.polardbx.common.utils.logger.log4j.Log4jLoggerAdapter; -import com.alibaba.polardbx.common.utils.logger.log4j.Log4jMDC; import com.alibaba.polardbx.common.utils.logger.slf4j.Slf4jLoggerAdapter; import com.alibaba.polardbx.common.utils.logger.slf4j.Slf4jMDC; @@ -41,8 +39,6 @@ public class MDC { mdcAdapter = new Slf4jMDC(); } else if (logger instanceof JclLoggerAdapter) { mdcAdapter = new JclMDC(); - } else if (logger instanceof Log4jLoggerAdapter) { - mdcAdapter = new Log4jMDC(); } else { mdcAdapter = new JdkMDC(); } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/logger/log4j/Log4jLoggerAdapter.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/logger/log4j/Log4jLoggerAdapter.java deleted file mode 100644 index 39d6d6746..000000000 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/logger/log4j/Log4jLoggerAdapter.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.common.utils.logger.log4j; - -import com.alibaba.polardbx.common.utils.logger.Level; -import com.alibaba.polardbx.common.utils.logger.Logger; -import com.alibaba.polardbx.common.utils.logger.LoggerAdapter; -import org.apache.log4j.Appender; -import org.apache.log4j.FileAppender; -import org.apache.log4j.LogManager; - -import java.io.File; -import java.util.Enumeration; - -public class Log4jLoggerAdapter implements LoggerAdapter { - - private File file; - - @SuppressWarnings("unchecked") - public Log4jLoggerAdapter() { - try { - org.apache.log4j.Logger logger = LogManager.getRootLogger(); - if (logger != null) { - Enumeration appenders = logger.getAllAppenders(); - if (appenders != null) { - while (appenders.hasMoreElements()) { - Appender appender = appenders.nextElement(); - if (appender instanceof FileAppender) { - FileAppender fileAppender = (FileAppender) appender; - String filename = fileAppender.getFile(); - file = new File(filename); - break; - } - } - } - } - } catch (Throwable t) { - } - } - - public Logger getLogger(Class key) { - return new Log4jLogger(LogManager.getLogger(key)); - } - - public Logger getLogger(String key) { - return new Log4jLogger(LogManager.getLogger(key)); - } - - public void setLevel(Level level) { - LogManager.getRootLogger().setLevel(toLog4jLevel(level)); - } - - public Level getLevel() { - return fromLog4jLevel(LogManager.getRootLogger().getLevel()); - } - - public File getFile() { - return file; - } - - private static org.apache.log4j.Level toLog4jLevel(Level level) { - if (level == Level.ALL) { - return org.apache.log4j.Level.ALL; - } - if (level == Level.TRACE) { - return org.apache.log4j.Level.TRACE; - } - if (level == Level.DEBUG) { - return org.apache.log4j.Level.DEBUG; - } - if (level == Level.INFO) { - return org.apache.log4j.Level.INFO; - } - if (level == Level.WARN) { - return org.apache.log4j.Level.WARN; - } - if (level == Level.ERROR) { - return org.apache.log4j.Level.ERROR; - } - - return org.apache.log4j.Level.OFF; - } - - private static Level fromLog4jLevel(org.apache.log4j.Level level) { - if (level == org.apache.log4j.Level.ALL) { - return Level.ALL; - } - if (level == org.apache.log4j.Level.TRACE) { - return Level.TRACE; - } - if (level == org.apache.log4j.Level.DEBUG) { - return Level.DEBUG; - } - if (level == org.apache.log4j.Level.INFO) { - return Level.INFO; - } - if (level == org.apache.log4j.Level.WARN) { - return Level.WARN; - } - if (level == org.apache.log4j.Level.ERROR) { - return Level.ERROR; - } - - return Level.OFF; - } - - public void setFile(File file) { - - } - -} diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/time/core/MysqlDateTime.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/time/core/MysqlDateTime.java index 98bed3784..561b498b6 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/time/core/MysqlDateTime.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/time/core/MysqlDateTime.java @@ -69,7 +69,6 @@ public static MysqlDateTime zeroDateTime() { @Override public MysqlDateTime clone() { MysqlDateTime t = new MysqlDateTime(); - t.sqlType = this.sqlType; t.year = this.year; t.month = this.month; t.day = this.day; diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/time/parser/StringTimeParser.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/time/parser/StringTimeParser.java index c18cfe42f..7074c2e67 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/time/parser/StringTimeParser.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/time/parser/StringTimeParser.java @@ -624,6 +624,7 @@ public static MysqlDateTime extractFormat(byte[] timestampAsBytes, byte[] format } sliceOutput.appendByte(formatAsBytes[i]); } + formatAsBytes = sliceOutput.slice().getBytes(); } MysqlDateTime t = new MysqlDateTime(); diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/timezone/TimeZoneUtils.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/timezone/TimeZoneUtils.java index 7a4a1a953..1680a9667 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/timezone/TimeZoneUtils.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/timezone/TimeZoneUtils.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.CaseInsensitive; import com.alibaba.polardbx.common.utils.time.core.MysqlDateTime; import com.alibaba.polardbx.common.utils.time.parser.StringTimeParser; @@ -30,18 +31,19 @@ import java.util.HashSet; import java.util.Set; import java.util.TimeZone; +import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; public class TimeZoneUtils { - private static final Set availableTimeZones = new HashSet<>(); + private static final Set availableTimeZones = new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); private static final Pattern timeZoneOffsetPattern = Pattern.compile("^([\\+|-])([0-1]?[0-9]):([0|3])0$"); static { for (String id : TimeZone.getAvailableIDs()) { - availableTimeZones.add(id.toUpperCase()); + availableTimeZones.add(id); } } @@ -68,7 +70,8 @@ public static InternalTimeZone convertFromMySqlTZ(String timeZoneStr) { throw new TddlRuntimeException(ErrorCode.ERR_UNKNOWN_TZ, timeZoneId); } } else if (availableTimeZones.contains(timeZoneId)) { - return InternalTimeZone.createTimeZone(timeZoneStr, TimeZone.getTimeZone(timeZoneId)); + ZoneId zoneId = ZoneId.of(timeZoneStr); + return InternalTimeZone.createTimeZone(timeZoneStr, TimeZone.getTimeZone(zoneId)); } else { throw new TddlRuntimeException(ErrorCode.ERR_UNKNOWN_TZ, timeZoneId); } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/timezone/TimestampUtils.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/timezone/TimestampUtils.java index c322b6950..bea5c674f 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/timezone/TimestampUtils.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/timezone/TimestampUtils.java @@ -23,6 +23,10 @@ import com.alibaba.polardbx.common.utils.time.parser.StringTimeParser; import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.HashSet; import java.util.Set; @@ -36,6 +40,7 @@ public class TimestampUtils { public static final String TYPE_NAME_TIMESTAMP = "timestamp"; public static final String PATTERN_TIMESTAMP = "yyyy-MM-dd HH:mm:ss"; public static final String FIXED_GMT_IN_META = "GMT+8:00"; + public static final int BITS_LOGICAL_TIME = 22; public static final Pattern PATTERN_ZERO_VALUE = Pattern.compile("^0000-00-00 00:00:00\\.?0*$"); @@ -71,7 +76,7 @@ public static String convertToGMT8(String timestampString, TimeZone fromTimeZone } public static String convertBetweenTimeZones(String timestampString, TimeZone fromTimeZone, TimeZone toTimeZone, - long precision) { + long precision) { boolean needTimeZoneConversion = needTimeZoneConversion(fromTimeZone) || needTimeZoneConversion(toTimeZone); if (!needTimeZoneConversion || TStringUtil.isBlank(timestampString) || @@ -144,4 +149,15 @@ private static String convertBetweenTimeZones(MysqlDateTime mysqlDateTime, TimeZ return mysqlDateTime.toDatetimeString((int) precision); } + public static long getTsFromTimestampWithTimeZone(String timestamp, TimeZone timeZone) { + String utcTimeStampString = + TimestampUtils.convertBetweenTimeZones(timestamp, timeZone, TimeZone.getTimeZone("UTC"), 0); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime localDateTime = LocalDateTime.parse(utcTimeStampString, formatter); + Instant instant = localDateTime.toInstant(ZoneOffset.UTC); + if (instant.toEpochMilli() < 0) { + throw new IllegalArgumentException("timestamp should greater than 1970-01-01 00:00:01"); + } + return instant.toEpochMilli() << BITS_LOGICAL_TIME; + } } diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/version/Version.java b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/version/Version.java index b2cc35ad4..393a90f89 100644 --- a/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/version/Version.java +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/common/utils/version/Version.java @@ -35,7 +35,7 @@ private Version() { } // TODO get product version from config property - public static final String PRODUCT_VERSION = "2.4.0"; + public static final String PRODUCT_VERSION = "2.5.0"; private static final Logger logger = LoggerFactory.getLogger(Version.class); private static final Package myPackage = VersionAnnotation.class.getPackage(); @@ -55,14 +55,14 @@ public static void checkVersion() { return; } try { - + // 可能有误判,跳过检测 boolean versionCheck = true; if (System.getProperty("tddl.version.check") != null) { versionCheck = Boolean.valueOf(System.getProperty("tddl.version.check")); } - + // 检查下sequence包 Version.checkDuplicate("com/taobao/tddl/client/sequence/impl/GroupSequenceDao.class", true && versionCheck); validVersion("polardbx-executor", @@ -75,15 +75,18 @@ public static void checkVersion() { "com/alibaba/polardbx/sequence/impl/SimpleSequenceDao.class", VERSION, false); - + // 检查下经常性冲突的两个包 Version.checkDuplicate("com/alibaba/druid/pool/DruidDataSource.class", true && versionCheck); validVersion("druid", "com/alibaba/druid/pool/DruidDataSource.class", "1.0.15", true && versionCheck); + Version.checkDuplicate("com/taobao/diamond/client/Diamond.class", true && versionCheck); + validVersion("diamond-client", "com/taobao/diamond/client/Diamond.class", "3.6.8", + true && versionCheck); Version.checkDuplicate("com/google/common/collect/MapMaker.class", false); validVersion("guava", "com/google/common/collect/MapMaker.class", "15.0", false); - + // 检查下mysql driver Version.checkDuplicate("com/mysql/jdbc/Driver.class", true && versionCheck); validVersion("mysql-connector-java", "com/mysql/jdbc/Driver.class", "5.1.26", true && versionCheck); - + // 检查是否存在多logger Version.checkDuplicate("org/slf4j/impl/StaticLoggerBinder.class", false); } finally { versionChecked = true; @@ -95,6 +98,9 @@ public static String getVersion() { return VERSION; } + /** + * Returns the detail version info + */ public static String getBuildVersion() { Package myPackage = VersionAnnotation.class.getPackage(); VersionAnnotation va = myPackage.getAnnotation(VersionAnnotation.class); @@ -112,20 +118,20 @@ public static String getBuildVersion() { public static String getVersion(Class cls, String defaultVersion) { if (va != null) { - + // 如果version不是空字符,那就直接以这个为准 if (StringUtils.isNotEmpty(va.version()) && !defaultVersion.equals(va.version())) { return va.version(); } } try { - + // 首先查找MANIFEST.MF规范中的版本号 String version = cls.getPackage().getImplementationVersion(); if (version == null || version.length() == 0) { version = cls.getPackage().getSpecificationVersion(); } if (version == null || version.length() == 0) { - + // 如果规范中没有版本号,基于jar包名获取版本号 CodeSource codeSource = cls.getProtectionDomain().getCodeSource(); if (codeSource == null) { logger.info("No codeSource for class " + cls.getName() + " when getVersion, use default version " @@ -137,18 +143,21 @@ public static String getVersion(Class cls, String defaultVersion) { } if (checkVersionNecessary(version)) { - + // 返回版本号,如果为空返回缺省版本号 return version == null || version.length() == 0 ? defaultVersion : version; } else { return defaultVersion; } - } catch (Throwable e) { - + } catch (Throwable e) { // 防御性容错 + // 忽略异常,返回缺省版本号 logger.error("return default version, ignore exception " + e.getMessage(), e); return defaultVersion; } } + /** + * 检查下对应class path的版本,是否>minVersion + */ public static boolean validVersion(String name, String path, String minVersion, boolean failOnError) { try { if (minVersion == null) { @@ -185,7 +194,7 @@ public static boolean validVersion(String name, String path, String minVersion, } } catch (TddlRuntimeException e) { throw e; - } catch (Throwable e) { + } catch (Throwable e) { // 防御性容错 logger.error(e.getMessage(), e); } @@ -202,7 +211,7 @@ public static boolean checkDuplicate(Class cls) { public static boolean checkDuplicate(String path, boolean failOnError) { try { - + // 在ClassPath搜文件 Enumeration urls = Version.class.getClassLoader().getResources(path); Set files = new HashSet(); while (urls.hasMoreElements()) { @@ -215,6 +224,7 @@ public static boolean checkDuplicate(String path, boolean failOnError) { } } + // 如果有多个,就表示重复 if (files.size() > 1) { try { throw new TddlRuntimeException(ErrorCode.ERR_DUPLICATED_CLASS, @@ -233,13 +243,16 @@ public static boolean checkDuplicate(String path, boolean failOnError) { } } catch (TddlRuntimeException e) { throw e; - } catch (Throwable e) { + } catch (Throwable e) { // 防御性容错 logger.error(e.getMessage(), e); } return false; } + /** + * 根据jar包的路径,找到对应的版本号 + */ public static String getVersionByPath(String file) { if (file != null && file.length() > 0 && StringUtils.contains(file, ".jar")) { int index = StringUtils.lastIndexOf(file, ".jar"); diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/stats/metric/FeatureStats.java b/polardbx-common/src/main/java/com/alibaba/polardbx/stats/metric/FeatureStats.java new file mode 100644 index 000000000..c2812af5f --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/stats/metric/FeatureStats.java @@ -0,0 +1,103 @@ +package com.alibaba.polardbx.stats.metric; + +import com.alibaba.fastjson.JSON; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; + +import java.util.Collection; + +/** + * @author fangwu + */ +public class FeatureStats { + + protected static final Logger logger = LoggerFactory.getLogger(FeatureStats.class); + + private long[] longStats; + + private long sign; + + // common method + public static String serialize(FeatureStats fs) { + return JSON.toJSONString(fs); + } + + public static FeatureStats deserialize(String jsonStr) { + return JSON.parseObject(jsonStr, FeatureStats.class); + } + + public String log() { + StringBuilder stringBuilder = new StringBuilder(); + for (FeatureStatsItem item : FeatureStatsItem.values()) { + stringBuilder.append(item.name()).append(":").append(longStats[item.ordinal()]).append(","); + } + // remove the last "," + stringBuilder.setLength(stringBuilder.length() - 1); + return stringBuilder.toString(); + } + + public static FeatureStats merge(FeatureStats target, Collection source) { + for (FeatureStats featureStats : source) { + if (target.sign != featureStats.sign) { + // warning log + continue; + } + for (int i = 0; i < target.longStats.length; i++) { + target.longStats[i] += featureStats.longStats[i]; + } + } + return target; + } + + private FeatureStats() { + // build stats + int longStatsSize = FeatureStatsItem.longStatsSize(); + longStats = new long[longStatsSize]; + this.sign = FeatureStatsItem.classVersion(); + } + + public static FeatureStats INSTANCE = new FeatureStats(); + + public static FeatureStats getInstance() { + return INSTANCE; + } + + /** + * build a new instance + */ + public static FeatureStats build() { + return new FeatureStats(); + } + + public static void reset() { + INSTANCE = build(); + } + + public void increment(FeatureStatsItem item) { + longStats[item.ordinal()]++; + } + + public void plus(FeatureStatsItem item, long num) { + longStats[item.ordinal()] += num; + } + + public long getLong(FeatureStatsItem item) { + return longStats[item.ordinal()]; + } + + public long[] getLongStats() { + return longStats; + } + + public long getSign() { + return sign; + } + + public void setLongStats(long[] longStats) { + this.longStats = longStats; + } + + public void setSign(long sign) { + this.sign = sign; + } +} diff --git a/polardbx-common/src/main/java/com/alibaba/polardbx/stats/metric/FeatureStatsItem.java b/polardbx-common/src/main/java/com/alibaba/polardbx/stats/metric/FeatureStatsItem.java new file mode 100644 index 000000000..9bb4401bb --- /dev/null +++ b/polardbx-common/src/main/java/com/alibaba/polardbx/stats/metric/FeatureStatsItem.java @@ -0,0 +1,42 @@ +package com.alibaba.polardbx.stats.metric; + +/** + * @author fangwu + */ +public enum FeatureStatsItem { + NEW_BASELINE_NUM("long"), + FIX_PLAN_NUM("long"), + HOT_EVOLVE_PLAN_NUM("long"), + SAMPLE_TASK_SUCC("long"), + SAMPLE_TASK_FAIL("long"), + HLL_TASK_SUCC("long"), + HLL_TASK_FAIL("long"); + + String type; + static long hash = 0L; + + FeatureStatsItem(String type) { + this.type = type; + } + + public static int longStatsSize() { + int i = 0; + for (FeatureStatsItem item : values()) { + if (item.type.equals("long")) { + i++; + } + } + return i; + } + + public static long classVersion() { + if (hash != 0L) { + return hash; + } + for (FeatureStatsItem item : values()) { + hash += item.name().hashCode(); + hash += item.type.hashCode(); + } + return hash; + } +} \ No newline at end of file diff --git a/polardbx-common/src/main/java/io/airlift/slice/DataSize.java b/polardbx-common/src/main/java/io/airlift/slice/DataSize.java index f5e880997..466722c54 100644 --- a/polardbx-common/src/main/java/io/airlift/slice/DataSize.java +++ b/polardbx-common/src/main/java/io/airlift/slice/DataSize.java @@ -149,6 +149,10 @@ public static DataSize valueOf(String size) throw new IllegalArgumentException("Unknown unit: " + unitString); } + public static long convertToByte(String size){ + return DataSize.valueOf(size).toBytes(); + } + @Override public int compareTo(DataSize o) { diff --git a/polardbx-common/src/main/java/io/airlift/slice/JvmUtils.java b/polardbx-common/src/main/java/io/airlift/slice/JvmUtils.java index 1b49111fd..dab4a42a7 100644 --- a/polardbx-common/src/main/java/io/airlift/slice/JvmUtils.java +++ b/polardbx-common/src/main/java/io/airlift/slice/JvmUtils.java @@ -41,6 +41,7 @@ import java.nio.Buffer; import java.nio.ByteBuffer; +import static java.lang.invoke.MethodType.methodType; import static sun.misc.Unsafe.ARRAY_BOOLEAN_INDEX_SCALE; import static sun.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE; import static sun.misc.Unsafe.ARRAY_DOUBLE_INDEX_SCALE; @@ -49,11 +50,15 @@ import static sun.misc.Unsafe.ARRAY_LONG_INDEX_SCALE; import static sun.misc.Unsafe.ARRAY_SHORT_INDEX_SCALE; -final class JvmUtils { +public final class JvmUtils { static final Unsafe unsafe; static final MethodHandle newByteBuffer; - private static final Field ADDRESS_ACCESSOR; + static final Field ADDRESS_ACCESSOR; + static final MethodHandles.Lookup IMPL_LOOKUP; + + static volatile boolean CONSTRUCTOR_LOOKUP_ERROR; + static volatile MethodHandle CONSTRUCTOR_LOOKUP; static { try { @@ -78,13 +83,26 @@ final class JvmUtils { directByteBufferClass.getDeclaredConstructor(long.class, int.class, Object.class); constructor.setAccessible(true); newByteBuffer = MethodHandles.lookup().unreflectConstructor(constructor) - .asType(MethodType.methodType(ByteBuffer.class, long.class, int.class, Object.class)); + .asType(methodType(ByteBuffer.class, long.class, int.class, Object.class)); ADDRESS_ACCESSOR = Buffer.class.getDeclaredField("address"); ADDRESS_ACCESSOR.setAccessible(true); } catch (Exception e) { throw new RuntimeException(e); } + MethodHandles.Lookup trustedLookup = null; + try { + Class lookupClass = MethodHandles.Lookup.class; + Field implLookup = lookupClass.getDeclaredField("IMPL_LOOKUP"); + long fieldOffset = unsafe.staticFieldOffset(implLookup); + trustedLookup = (MethodHandles.Lookup) unsafe.getObject(lookupClass, fieldOffset); + } catch (Throwable ignored) { + // ignored + } + if (trustedLookup == null) { + trustedLookup = MethodHandles.lookup(); + } + IMPL_LOOKUP = trustedLookup; } private static void assertArrayIndexScale(final String name, int actualIndexScale, int expectedIndexScale) { @@ -102,6 +120,28 @@ public static long getAddress(Buffer buffer) { } } + public static MethodHandles.Lookup trustedLookup(Class objectClass) { + if (!CONSTRUCTOR_LOOKUP_ERROR) { + try { + int TRUSTED = -1; + + MethodHandle constructor = CONSTRUCTOR_LOOKUP; + if (constructor == null) { + constructor = IMPL_LOOKUP.findConstructor( + MethodHandles.Lookup.class, + methodType(void.class, Class.class, int.class) + ); + CONSTRUCTOR_LOOKUP = constructor; + } + return (MethodHandles.Lookup) constructor.invoke(objectClass, TRUSTED); + } catch (Throwable ignored) { + CONSTRUCTOR_LOOKUP_ERROR = true; + } + } + + return IMPL_LOOKUP.in(objectClass); + } + private JvmUtils() { } } diff --git a/polardbx-common/src/main/resources/res/ErrorCode.properties b/polardbx-common/src/main/resources/res/ErrorCode.properties index 88e5d02b5..c2f56c63b 100644 --- a/polardbx-common/src/main/resources/res/ErrorCode.properties +++ b/polardbx-common/src/main/resources/res/ErrorCode.properties @@ -310,6 +310,9 @@ ERR_LOAD_DEL_FILE={0} ERR_LOAD_ORC_FILE={0} ERR_COLUMNAR_SNAPSHOT={0} ERR_COLUMNAR_SCHEMA={0} +ERR_COLUMNAR_DROP_PARTITION={0} +ERR_COLUMNAR_MODIFY_PARTITION_DROP_VALUE={0} +ERR_COLUMNAR_TRUNCATE_PARTITION={0} ERR_SET_AUTO_SAVEPOINT=Set auto savepoint fail ERR_REPARTITION_TABLE_WITH_GSI={0} ERR_REPARTITION_KEY={0} @@ -349,6 +352,8 @@ ERR_CREATE_SELECT_FUNCTION_ALIAS={0} ERR_CREATE_SELECT_UPDATE={0} ERR_CREATE_SELECT_WITH_GSI={0} ERR_CREATE_SELECT_WITH_OSS={0} +ERR_CREATE_TABLE_WITH_TTL={0} + ERR_DUPLICATE_NAME_FK_CONSTRAINT=Duplicate foreign key constraint name ''{0}'' ERR_DROP_FK_CONSTRAINT=Can''t DROP ''{0}''; check that column/key exists ERR_DROP_COLUMN_FK_CONSTRAINT=Cannot drop column ''{0}'' needed in ''{1}''.''{2}'' foreign key constraint ''{3}'' @@ -372,6 +377,15 @@ ERR_DDL_WITH_CCI=Do not support current ddl [{0}] with CCI ERR_UNSUPPORTED_COLUMN_TYPE_WITH_CCI=The {0} in the type of {1} is not supported by CCI ERR_BINARY_PREDICATE={0} + ERR_ENCDB={0} ERR_LBAC={0} ERR_INSTANCE_READ_ONLY_OPTION_NOT_SUPPORT=server is running with the instance-read-only option so it cannot execute this statement + +ERR_TTL={0} +ERR_TTL_INTERRUPTED={0} +ERR_TTL_TABLE_NOT_FOUND={0} +ERR_TTL_COLUMN_NOT_FOUND={0} +ERR_TTL_PARAMS={0} + + diff --git a/polardbx-common/src/test/java/com/alibaba/polardbx/common/constants/ServerVariablesTest.java b/polardbx-common/src/test/java/com/alibaba/polardbx/common/constants/ServerVariablesTest.java new file mode 100644 index 000000000..4adfdca75 --- /dev/null +++ b/polardbx-common/src/test/java/com/alibaba/polardbx/common/constants/ServerVariablesTest.java @@ -0,0 +1,35 @@ +package com.alibaba.polardbx.common.constants; + +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.google.common.collect.ImmutableSet; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Set; + +import static com.alibaba.polardbx.common.constants.ServerVariables.ENABLE_POLARX_SYNC_POINT; + +public class ServerVariablesTest { + @Test + public void testMODIFIABLE_SYNC_POINT_PARAM() { + Set expected = ImmutableSet.of( + ConnectionProperties.ENABLE_SYNC_POINT, + ConnectionProperties.SYNC_POINT_TASK_INTERVAL); + + Set actual = ServerVariables.MODIFIABLE_SYNC_POINT_PARAM; + + Assert.assertEquals(expected, actual); + } + + @Test + public void testVariables() { + Assert.assertTrue(ServerVariables.variables.contains(ENABLE_POLARX_SYNC_POINT)); + Assert.assertTrue(ServerVariables.variables.contains("polarx_sync_point_timeout")); + + Assert.assertTrue(ServerVariables.mysqlGlobalVariables.contains(ENABLE_POLARX_SYNC_POINT)); + Assert.assertTrue(ServerVariables.mysqlGlobalVariables.contains("polarx_sync_point_timeout")); + + Assert.assertTrue(ServerVariables.mysqlDynamicVariables.contains(ENABLE_POLARX_SYNC_POINT)); + Assert.assertTrue(ServerVariables.mysqlDynamicVariables.contains("polarx_sync_point_timeout")); + } +} diff --git a/polardbx-common/src/test/java/com/alibaba/polardbx/common/jdbc/ITransactionPolicyTest.java b/polardbx-common/src/test/java/com/alibaba/polardbx/common/jdbc/ITransactionPolicyTest.java new file mode 100644 index 000000000..a89835878 --- /dev/null +++ b/polardbx-common/src/test/java/com/alibaba/polardbx/common/jdbc/ITransactionPolicyTest.java @@ -0,0 +1,122 @@ +package com.alibaba.polardbx.common.jdbc; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ITransactionPolicyTest { + @Test + public void testXA() { + ITransactionPolicy policy = ITransactionPolicy.of("XA"); + assertEquals(ITransactionPolicy.XA, policy); + + ITransactionPolicy.TransactionClass trxClass = + policy.getTransactionType(false, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.XA, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.AUTO_COMMIT, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, true); + assertEquals(ITransactionPolicy.TransactionClass.XA, trxClass); + } + + @Test + public void testTSO() { + ITransactionPolicy policy = ITransactionPolicy.of("TSO"); + assertEquals(ITransactionPolicy.TSO, policy); + + ITransactionPolicy.TransactionClass trxClass = + policy.getTransactionType(false, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.TSO, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.AUTO_COMMIT, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, true); + assertEquals(ITransactionPolicy.TransactionClass.TSO, trxClass); + + trxClass = + policy.getTransactionType(true, true, true, false); + assertEquals(ITransactionPolicy.TransactionClass.AUTO_COMMIT_SINGLE_SHARD, trxClass); + + trxClass = + policy.getTransactionType(true, true, true, true); + assertEquals(ITransactionPolicy.TransactionClass.AUTO_COMMIT_SINGLE_SHARD, trxClass); + } + + @Test + public void testAllowRead() { + ITransactionPolicy policy = ITransactionPolicy.of("ALLOW_READ"); + assertEquals(ITransactionPolicy.ALLOW_READ_CROSS_DB, policy); + + ITransactionPolicy.TransactionClass trxClass = + policy.getTransactionType(false, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.ALLOW_READ_CROSS_DB, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.AUTO_COMMIT, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, true); + assertEquals(ITransactionPolicy.TransactionClass.ALLOW_READ_CROSS_DB, trxClass); + } + + @Test + public void testFree() { + ITransactionPolicy policy = ITransactionPolicy.of("FREE"); + assertEquals(ITransactionPolicy.FREE, policy); + + ITransactionPolicy.TransactionClass trxClass = + policy.getTransactionType(false, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.COBAR_STYLE, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.AUTO_COMMIT, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, true); + assertEquals(ITransactionPolicy.TransactionClass.COBAR_STYLE, trxClass); + } + + @Test + public void testNoTransaction() { + ITransactionPolicy policy = ITransactionPolicy.of("NO_TRANSACTION"); + assertEquals(ITransactionPolicy.NO_TRANSACTION, policy); + + ITransactionPolicy.TransactionClass trxClass = + policy.getTransactionType(false, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.AUTO_COMMIT, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.AUTO_COMMIT, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, true); + assertEquals(ITransactionPolicy.TransactionClass.TSO, trxClass); + } + + @Test + public void testArchive() { + ITransactionPolicy policy = ITransactionPolicy.of("ARCHIVE"); + assertEquals(ITransactionPolicy.ARCHIVE, policy); + ITransactionPolicy.TransactionClass trxClass = + policy.getTransactionType(false, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.ARCHIVE, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, false); + assertEquals(ITransactionPolicy.TransactionClass.ARCHIVE, trxClass); + + trxClass = + policy.getTransactionType(true, false, false, true); + assertEquals(ITransactionPolicy.TransactionClass.ARCHIVE, trxClass); + } +} diff --git a/polardbx-common/src/test/java/com/alibaba/polardbx/common/oss/filesystem/FSOSSInputStreamTest.java b/polardbx-common/src/test/java/com/alibaba/polardbx/common/oss/filesystem/FSOSSInputStreamTest.java new file mode 100644 index 000000000..721ef5e31 --- /dev/null +++ b/polardbx-common/src/test/java/com/alibaba/polardbx/common/oss/filesystem/FSOSSInputStreamTest.java @@ -0,0 +1,89 @@ +package com.alibaba.polardbx.common.oss.filesystem; + +import com.alibaba.polardbx.common.mock.MockUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.io.IOException; +import java.io.InputStream; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; + +public class FSOSSInputStreamTest { + + private static final String OSS_KEY_PATH = "oss://bucket/path/to/file"; + private static final int BUFFER_SIZE = 8192; + private static final long TEST_SEEK_POS = 2048; + private static final int TEST_READ = 3000; + private static final long TEST_SKIP = 4000; + private static final long FILE_LENGTH = 10000; + private FSOSSInputStream inputStream; + private InputStream innerInputStream; + private OSSFileSystemStore ossFileSystemStore; + + @Before + public void setUp() throws Exception { + this.ossFileSystemStore = Mockito.mock(OSSFileSystemStore.class); + this.innerInputStream = Mockito.mock(InputStream.class); + Mockito.when(ossFileSystemStore.retrieve(anyString(), anyLong(), anyLong())).thenReturn(innerInputStream); + Mockito.when(ossFileSystemStore.getOssFileLength(anyString())).thenReturn(FILE_LENGTH); + Mockito.when(innerInputStream.read(any(), anyInt(), anyInt())).thenReturn(TEST_READ); + Mockito.when(innerInputStream.skip(anyLong())).thenReturn(TEST_SKIP); + this.inputStream = new FSOSSInputStream(ossFileSystemStore, OSS_KEY_PATH, BUFFER_SIZE); + } + + @Test + public void testAll() throws IOException { + testSeek(); + testGetPos(); + testSeekToNewSource(); + testRead1(); + testRead2(); + testRead3(); + testSkip(); + testAvailable(); + testClose(); + } + + public void testSeek() throws IOException { + inputStream.seek(TEST_SEEK_POS); + } + + public void testGetPos() { + Assert.assertEquals(TEST_SEEK_POS, inputStream.getPos()); + } + + public void testSeekToNewSource() { + MockUtils.assertThrows(IOException.class, "seekToNewSource is not supported!", + () -> inputStream.seekToNewSource(TEST_SEEK_POS)); + } + + public void testRead1() throws IOException { + Assert.assertEquals(0, inputStream.read()); + } + + public void testRead2() throws IOException { + Assert.assertEquals(1000, inputStream.read(new byte[1000])); + } + + public void testRead3() throws IOException { + Assert.assertEquals(TEST_READ - 1001, inputStream.read(new byte[TEST_READ], 0, TEST_READ)); + } + + public void testSkip() throws IOException { + Assert.assertEquals(TEST_SKIP, inputStream.skip(TEST_SKIP)); + } + + public void testAvailable() throws IOException { + Assert.assertEquals(FILE_LENGTH - TEST_SEEK_POS - TEST_READ - TEST_SKIP, inputStream.available()); + } + + public void testClose() throws IOException { + inputStream.close(); + } +} \ No newline at end of file diff --git a/polardbx-common/src/test/java/com/alibaba/polardbx/common/properties/ConnectionParamsTest.java b/polardbx-common/src/test/java/com/alibaba/polardbx/common/properties/ConnectionParamsTest.java index 17754fad1..50e523378 100644 --- a/polardbx-common/src/test/java/com/alibaba/polardbx/common/properties/ConnectionParamsTest.java +++ b/polardbx-common/src/test/java/com/alibaba/polardbx/common/properties/ConnectionParamsTest.java @@ -2,6 +2,7 @@ import org.junit.Test; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class ConnectionParamsTest { @@ -24,7 +25,7 @@ public void testENABLE_AUTO_COMMIT_TSO() { assertTrue("ENABLE_AUTO_COMMIT_TSO should be an instance of BooleanConfigParam", ConnectionParams.ENABLE_AUTO_COMMIT_TSO instanceof BooleanConfigParam); - assertTrue("ENABLE_AUTO_COMMIT_TSO default value should be true", + assertFalse("ENABLE_AUTO_COMMIT_TSO default value should be false", Boolean.parseBoolean(ConnectionParams.ENABLE_AUTO_COMMIT_TSO.getDefault())); assertTrue("ENABLE_AUTO_COMMIT_TSO should be editable", diff --git a/polardbx-common/src/test/java/com/alibaba/polardbx/common/properties/DynamicConfigTest.java b/polardbx-common/src/test/java/com/alibaba/polardbx/common/properties/DynamicConfigTest.java index 09535f19b..47f220edb 100644 --- a/polardbx-common/src/test/java/com/alibaba/polardbx/common/properties/DynamicConfigTest.java +++ b/polardbx-common/src/test/java/com/alibaba/polardbx/common/properties/DynamicConfigTest.java @@ -2,7 +2,13 @@ import com.alibaba.polardbx.common.TddlConstants; import com.alibaba.polardbx.common.constants.ServerVariables; +import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -11,6 +17,9 @@ * @author fangwu */ public class DynamicConfigTest { + + final private Logger logger = LoggerFactory.getLogger(DynamicConfigTest.class); + @Test public void testLoadInDegradationNum() { assertTrue(DynamicConfig.getInstance().getInDegradationNum() == 100L); @@ -26,8 +35,89 @@ public void testBlackListConf() { DynamicConfig.getInstance().loadValue(null, TddlConstants.BLACK_LIST_CONF, "x1,y1"); assertTrue(DynamicConfig.getInstance().getBlacklistConf().size() == 2); - assertTrue(ServerVariables.isGlobalBlackList("x1")); - assertTrue(ServerVariables.isGlobalBlackList("y1")); - assertFalse(ServerVariables.isGlobalBlackList("y1,x1")); + assertTrue(ServerVariables.isVariablesBlackList("x1")); + assertTrue(ServerVariables.isVariablesBlackList("y1")); + assertFalse(ServerVariables.isVariablesBlackList("y1,x1")); + } + + @Test + public void testSyncPointConfig() { + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.ENABLE_SYNC_POINT, "true"); + Assert.assertTrue(DynamicConfig.getInstance().isEnableSyncPoint()); + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.ENABLE_SYNC_POINT, "false"); + Assert.assertFalse(DynamicConfig.getInstance().isEnableSyncPoint()); + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.SYNC_POINT_TASK_INTERVAL, "200000"); + Assert.assertEquals(200000, DynamicConfig.getInstance().getSyncPointTaskInterval()); + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.SYNC_POINT_TASK_INTERVAL, "1000000"); + Assert.assertEquals(1000000, DynamicConfig.getInstance().getSyncPointTaskInterval()); + } + + @Test + public void testShowColumnarStatusUseSubQueryConfig() { + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.SHOW_COLUMNAR_STATUS_USE_SUB_QUERY, "true"); + Assert.assertTrue(DynamicConfig.getInstance().isShowColumnarStatusUseSubQuery()); + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.SHOW_COLUMNAR_STATUS_USE_SUB_QUERY, "false"); + Assert.assertFalse(DynamicConfig.getInstance().isShowColumnarStatusUseSubQuery()); + } + + @Test + public void testAllowColumnarBindMaster() { + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.ALLOW_COLUMNAR_BIND_MASTER, "true"); + Assert.assertTrue(DynamicConfig.getInstance().allowColumnarBindMaster()); + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.ALLOW_COLUMNAR_BIND_MASTER, "false"); + Assert.assertFalse(DynamicConfig.getInstance().allowColumnarBindMaster()); + } + + @Test + public void testPreheatedCacheMaxEntries() { + long preheatedCacheMaxEntries = DynamicConfig.getInstance().getPreheatedCacheMaxEntries(); + + Assert.assertTrue(preheatedCacheMaxEntries == 4096L); + + DynamicConfig.getInstance().loadValue(null, ConnectionProperties.PREHEATED_CACHE_MAX_ENTRIES, "16384"); + + preheatedCacheMaxEntries = DynamicConfig.getInstance().getPreheatedCacheMaxEntries(); + + Assert.assertTrue(preheatedCacheMaxEntries == 16384L); + } + + @Test + public void testDeadlockVar() { + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.DEADLOCK_DETECTION_80_FETCH_TRX_ROWS, "10000"); + Assert.assertEquals(10000, DynamicConfig.getInstance().getDeadlockDetection80FetchTrxRows()); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.DEADLOCK_DETECTION_DATA_LOCK_WAITS_THRESHOLD, "30000"); + Assert.assertEquals(30000, DynamicConfig.getInstance().getDeadlockDetectionDataLockWaitsThreshold()); + } + + @Test + public void testShareReadviewInRc() { + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.ENABLE_SHARE_READVIEW_IN_RC, "true"); + Assert.assertTrue(DynamicConfig.getInstance().isEnableShareReadviewInRc()); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.ENABLE_SHARE_READVIEW_IN_RC, "false"); + Assert.assertFalse(DynamicConfig.getInstance().isEnableShareReadviewInRc()); + } + + @Test + public void testExistColumnarNodes() { + assertTrue(!DynamicConfig.getInstance().existColumnarNodes()); + DynamicConfig.getInstance().existColumnarNodes(true); + assertTrue(DynamicConfig.getInstance().existColumnarNodes()); + } + + @Test + public void testMPPQueryMaxWait() { + long mppQueryResultMaxWaitInMillis = DynamicConfig.getInstance().getMppQueryResultMaxWaitInMillis(); + + Assert.assertTrue(mppQueryResultMaxWaitInMillis == 10L); + + DynamicConfig.getInstance().loadValue(null, ConnectionProperties.MPP_QUERY_RESULT_MAX_WAIT_IN_MILLIS, "1000"); + + mppQueryResultMaxWaitInMillis = DynamicConfig.getInstance().getMppQueryResultMaxWaitInMillis(); + + Assert.assertTrue(mppQueryResultMaxWaitInMillis == 1000L); } } diff --git a/polardbx-common/src/test/java/com/alibaba/polardbx/common/properties/MppConfigTest.java b/polardbx-common/src/test/java/com/alibaba/polardbx/common/properties/MppConfigTest.java new file mode 100644 index 000000000..b310c0a7e --- /dev/null +++ b/polardbx-common/src/test/java/com/alibaba/polardbx/common/properties/MppConfigTest.java @@ -0,0 +1,22 @@ +package com.alibaba.polardbx.common.properties; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class MppConfigTest { + + final private Logger logger = LoggerFactory.getLogger(MppConfigTest.class); + + @Test + public void testEnableMppUI() { + assertTrue(MppConfig.getInstance().isEnableMppUI()); + MppConfig.getInstance().loadValue(logger, ConnectionProperties.ENABLE_MPP_UI, "false"); + assertFalse(MppConfig.getInstance().isEnableMppUI()); + MppConfig.getInstance().loadValue(logger, ConnectionProperties.ENABLE_MPP_UI, "true"); + assertTrue(MppConfig.getInstance().isEnableMppUI()); + } +} diff --git a/polardbx-common/src/test/java/com/alibaba/polardbx/common/utils/GeneralUtilTest.java b/polardbx-common/src/test/java/com/alibaba/polardbx/common/utils/GeneralUtilTest.java index e53af02e9..6223d0a6a 100644 --- a/polardbx-common/src/test/java/com/alibaba/polardbx/common/utils/GeneralUtilTest.java +++ b/polardbx-common/src/test/java/com/alibaba/polardbx/common/utils/GeneralUtilTest.java @@ -6,6 +6,14 @@ import java.sql.SQLException; import java.util.Map; +import static com.alibaba.polardbx.common.utils.GeneralUtil.formatSampleRate; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author fangwu + */ public class GeneralUtilTest { @Test @@ -31,4 +39,141 @@ public void testDecode() throws IOException { result.get("catalog:gdcams_tp,mk_run_meter_day_energy,data_time,2023-12-07 00:00:00_2023-12-08 00:00:00\n" + "action:datetimetypecompensation").equals("81892745")); } + + /** + * Checks if isPrimary returns false for an empty/null string. + */ + @Test + public void testIsPrimaryEmptyString() { + assertFalse("An empty string should not be considered as primary", GeneralUtil.isPrimary("")); + assertFalse("An null should not be considered as primary", GeneralUtil.isPrimary(null)); + } + + /** + * Ensures isPrimary returns false with a string containing only whitespaces. + */ + @Test + public void testIsPrimaryWhitespace() { + assertFalse("A string with only whitespace characters should not be considered as primary", + GeneralUtil.isPrimary(" ")); + } + + /** + * Validates isPrimary returns false for a non-primary string. + */ + @Test + public void testIsPrimaryNonPrimaryString() { + assertFalse("A string other than 'primary' should not be considered as primary", + GeneralUtil.isPrimary("secondary")); + } + + /** + * Tests isPrimary returning true for lowercase 'primary'. + */ + @Test + public void testIsPrimaryLowerCasePrimary() { + assertTrue("Lowercase 'primary' should be recognized as primary", + GeneralUtil.isPrimary("primary".toLowerCase())); + } + + /** + * Verifies isPrimary returns true for uppercase 'PRIMARY'. + */ + @Test + public void testIsPrimaryUpperCasePrimary() { + assertTrue("Uppercase 'PRIMARY' should be recognized as primary", GeneralUtil.isPrimary("PRIMARY")); + assertTrue("mix case 'PriMArY' should be recognized as primary", GeneralUtil.isPrimary("PriMArY")); + } + + @Test + public void testSampleStringNormalCase() { + float sampleRate = 0.5f; + String expectedOutput = "0.5"; + assertEquals(expectedOutput, formatSampleRate(sampleRate)); + } + + @Test + public void testSampleStringSampleRateZero() { + float sampleRate = 0f; + String expectedOutput = "0.0"; + assertEquals(expectedOutput, formatSampleRate(sampleRate)); + } + + @Test + public void testSampleStringSampleRateOne() { + float sampleRate = 1f; + String expectedOutput = "1.0"; + assertEquals(expectedOutput, formatSampleRate(sampleRate)); + } + + @Test + public void testSampleStringSampleRateGreaterThanOne() { + float sampleRate = 1.5f; + String expectedOutput = "1.5"; + assertEquals(expectedOutput, formatSampleRate(sampleRate)); + + sampleRate = 0.0002f; + expectedOutput = "0.0002"; + assertEquals(expectedOutput, formatSampleRate(sampleRate)); + + sampleRate = 0.000000002f; + expectedOutput = "0.000000002"; + assertEquals(expectedOutput, formatSampleRate(sampleRate)); + + sampleRate = 2.000000002f; + expectedOutput = "2.0"; + assertEquals(expectedOutput, formatSampleRate(sampleRate)); + + sampleRate = 11.0023450002f; + expectedOutput = "11.002345"; + assertEquals(expectedOutput, formatSampleRate(sampleRate)); + } + + @Test + public void testIsWithinPercentageEqualNumbers() { + // Design: Test when both numbers are equal. + assertEquals(true, GeneralUtil.isWithinPercentage(100, 100, 10)); + } + + @Test + public void testIsWithinPercentageExactMatch() { + // Design: Test when difference equals the threshold. + assertEquals(true, GeneralUtil.isWithinPercentage(100, 110, 10)); + } + + @Test + public void testIsWithinPercentageBelowThreshold() { + // Design: Test when difference is less than the threshold. + assertEquals(true, GeneralUtil.isWithinPercentage(100, 105, 10)); + } + + @Test + public void testIsWithinPercentageAboveThreshold() { + // Design: Test when difference is greater than the threshold. + assertEquals(false, GeneralUtil.isWithinPercentage(100, 115, 10)); + } + + @Test + public void testIsWithinPercentageZeroPercentage() { + // Design: Test with a zero percentage threshold. + assertEquals(true, GeneralUtil.isWithinPercentage(100, 100, 0)); + } + + @Test + public void testIsWithinPercentageNegativePercentage() { + // Design: Test with a negative percentage threshold (invalid input). + assertEquals(false, GeneralUtil.isWithinPercentage(100, 100, -10)); + } + + @Test + public void testIsWithinPercentageDecimalThreshold() { + // Design: Test with a decimal percentage threshold. + assertEquals(true, GeneralUtil.isWithinPercentage(100, 106, 6.1)); + } + + @Test + public void testIsWithinPercentageLargeNumbers() { + // Design: Test with large numbers to ensure correct calculation of threshold. + assertEquals(true, GeneralUtil.isWithinPercentage(1000000, 1000100, 0.1)); + } } diff --git a/polardbx-common/src/test/java/com/alibaba/polardbx/stats/metric/FeatureStatsTest.java b/polardbx-common/src/test/java/com/alibaba/polardbx/stats/metric/FeatureStatsTest.java new file mode 100644 index 000000000..54e9345c3 --- /dev/null +++ b/polardbx-common/src/test/java/com/alibaba/polardbx/stats/metric/FeatureStatsTest.java @@ -0,0 +1,47 @@ +package com.alibaba.polardbx.stats.metric; + +import com.google.common.collect.ImmutableList; +import org.junit.Test; + +import static com.alibaba.polardbx.stats.metric.FeatureStats.deserialize; +import static com.alibaba.polardbx.stats.metric.FeatureStats.serialize; + +/** + * @author fangwu + */ +public class FeatureStatsTest { + @Test + public void testSerialize() { + FeatureStats fs = FeatureStats.getInstance(); + fs.plus(FeatureStatsItem.FIX_PLAN_NUM, 10); + fs.plus(FeatureStatsItem.NEW_BASELINE_NUM, 101); + String jsonStr = serialize(fs); + FeatureStats featureStats = deserialize(jsonStr); + + assert featureStats.getLong(FeatureStatsItem.FIX_PLAN_NUM) == 10; + assert featureStats.getLong(FeatureStatsItem.NEW_BASELINE_NUM) == 101; + System.out.println(fs.log()); + System.out.println(featureStats.log()); + assert fs.log().equalsIgnoreCase(featureStats.log()); + } + + @Test + public void testMerge() { + FeatureStats fs = FeatureStats.build(); + FeatureStats fs1 = FeatureStats.build(); + fs1.plus(FeatureStatsItem.FIX_PLAN_NUM, 10); + fs1.plus(FeatureStatsItem.NEW_BASELINE_NUM, 101); + + FeatureStats fs2 = FeatureStats.build(); + fs2.plus(FeatureStatsItem.FIX_PLAN_NUM, 11); + fs2.plus(FeatureStatsItem.NEW_BASELINE_NUM, 101); + + FeatureStats fs3 = FeatureStats.build(); + fs3.plus(FeatureStatsItem.FIX_PLAN_NUM, 13); + fs3.plus(FeatureStatsItem.NEW_BASELINE_NUM, 102); + + FeatureStats.merge(fs, ImmutableList.of(fs1, fs2, fs3)); + assert fs.getLong(FeatureStatsItem.FIX_PLAN_NUM) == 34; + assert fs.getLong(FeatureStatsItem.NEW_BASELINE_NUM) == 304; + } +} diff --git a/polardbx-executor/pom.xml b/polardbx-executor/pom.xml index c704e309f..fae526ba7 100644 --- a/polardbx-executor/pom.xml +++ b/polardbx-executor/pom.xml @@ -14,11 +14,15 @@ 206 + 3.2.2 1.6.9 3.10.2 + 3.2.2 5.9.0 43.0 + 1.0-SNAPSHOT 4.12 + @@ -48,7 +52,7 @@ ${sigar.version} - ${project.groupId} + com.alibaba.polardbx polardbx-calcite @@ -56,8 +60,8 @@ commons-logging - ${project.groupId} - polardbx-common + com.alibaba.polardbx + polardbx-common commons-codec @@ -122,6 +126,10 @@ test-jar + + com.github.ben-manes.caffeine + caffeine + io.airlift bootstrap @@ -131,10 +139,6 @@ org.slf4j slf4j-jdk14 - - log4j-over-slf4j - org.slf4j - @@ -233,11 +237,10 @@ ${aircompressor.version} - io.airlift.resolver - resolver - ${resolver.version} + com.alibaba.polardbx + airlift-all-shade + ${airlift.shade.version} - javax.validation validation-api @@ -287,42 +290,21 @@ commons-codec commons-codec - - org.apache.hadoop - hadoop-client - ${hadoop-client.version} - - - slf4j-reload4j - org.slf4j - - - - - org.apache.hadoop - hadoop-client - ${hadoop.version} - - com.cronutils cron-utils - - org.apache.arrow - arrow-vector - - - - org.apache.arrow - arrow-memory-netty - - io.dropwizard.metrics metrics-core + + org.apache.httpcomponents + httpcore + 4.4.13 + compile + diff --git a/polardbx-executor/src/main/codegen/data/ConjunctionOperators.tdd b/polardbx-executor/src/main/codegen/data/ConjunctionOperators.tdd index c2b9b5418..4d3531d4b 100644 --- a/polardbx-executor/src/main/codegen/data/ConjunctionOperators.tdd +++ b/polardbx-executor/src/main/codegen/data/ConjunctionOperators.tdd @@ -1,5 +1,4 @@ { "operators": [ - {operandCount: 2}, {operandCount: 3}, {operandCount: 4}, {operandCount: 5}, diff --git a/polardbx-executor/src/main/codegen/data/InColConstOperators.tdd b/polardbx-executor/src/main/codegen/data/InColConstOperators.tdd index 81f6d0738..85a6a6295 100644 --- a/polardbx-executor/src/main/codegen/data/InColConstOperators.tdd +++ b/polardbx-executor/src/main/codegen/data/InColConstOperators.tdd @@ -3,801 +3,601 @@ { operandCount: 1 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 2 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 3 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 4 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 5 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 6 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 7 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 8 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 9 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 10 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 11 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 12 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 13 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 14 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 15 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 16 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 17 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 18 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 19 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 20 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 21 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 22 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 23 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 24 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 25 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 26 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 27 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 28 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 29 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 30 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 31 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 32 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 33 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 34 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 35 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 36 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 37 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 38 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 39 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 40 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 41 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 42 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 43 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 44 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 45 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 46 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 47 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 48 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 49 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 50 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 51 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 52 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 53 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 54 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 55 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 56 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 57 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 58 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 59 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 60 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 61 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 62 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 63 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 64 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 65 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 66 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 67 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 68 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 69 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 70 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 71 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 72 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 73 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 74 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 75 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 76 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 77 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 78 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 79 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 80 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 81 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 82 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 83 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 84 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 85 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 86 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 87 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 88 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 89 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 90 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 91 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 92 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 93 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 94 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 95 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 96 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 97 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 98 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 99 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] }, { operandCount: 100 types: [ - {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"}, - {leftType: "Integer", rightType: "Long", abstractClass: "AbstractInIntegerColLongConstVectorizedExpression"}, - {leftType: "Long", rightType: "Long", abstractClass: "AbstractInLongColLongConstVectorizedExpression"} + {leftType: "Varchar", rightType: "Char", abstractClass: "AbstractInVarcharColCharConstVectorizedExpression"} ] } ] diff --git a/polardbx-executor/src/main/codegen/templates/AndColumnColumn.ftl b/polardbx-executor/src/main/codegen/templates/AndColumnColumn.ftl index 204b5a32d..c8acc73f5 100644 --- a/polardbx-executor/src/main/codegen/templates/AndColumnColumn.ftl +++ b/polardbx-executor/src/main/codegen/templates/AndColumnColumn.ftl @@ -44,8 +44,7 @@ import static com.alibaba.polardbx.executor.vectorized.metadata.ArgumentKind.Var Variable, - }, - priority = ExpressionPriority.SPECIAL) +}) public class ${className} extends AbstractVectorizedExpression { public ${className}( int outputIndex, @@ -73,30 +72,30 @@ public class ${className} extends AbstractVectorizedExpression { - long[] res = (outputVectorSlot.cast(LongBlock.class)).longArray(); - boolean[] outputNulls = outputVectorSlot.nulls(); + long[] res = (outputVectorSlot.cast(LongBlock.class)).longArray(); + boolean[] outputNulls = outputVectorSlot.nulls(); - boolean outputVectorHasNull = false; - if (isSelectionInUse) { - for (int i = 0; i < batchSize; i++) { - int j = sel[i]; + boolean outputVectorHasNull = false; + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; - <#list 1..(operator.operandCount) as c> - boolean null${c} = !input${c}HasNull ? false : nulls${c}[j]; + <#list 1..(operator.operandCount) as c> + boolean null${c} = !input${c}HasNull ? false : nulls${c}[j]; <#list 1..(operator.operandCount) as c> - boolean b${c} = (array${c}[j] != 0); + boolean b${c} = (array${c}[j] != 0); boolean hasNull = null1; <#list 2..(operator.operandCount) as c> - hasNull |= null${c}; + hasNull |= null${c}; boolean anyFalse = (!null1 && !b1); <#list 2..(operator.operandCount) as c> - anyFalse |= (!null${c} && !b${c}); + anyFalse |= (!null${c} && !b${c}); outputNulls[j] = !anyFalse && hasNull; diff --git a/polardbx-executor/src/main/codegen/templates/BooleanTestOperator.ftl b/polardbx-executor/src/main/codegen/templates/BooleanTestOperator.ftl index 0ee883736..9c30976f1 100644 --- a/polardbx-executor/src/main/codegen/templates/BooleanTestOperator.ftl +++ b/polardbx-executor/src/main/codegen/templates/BooleanTestOperator.ftl @@ -5,8 +5,8 @@ <#list cmpOperators.booleanTestOperators.types as type> <#assign className = "${operator.classHeader}${type.inputDataType}ColVectorizedExpression"> - <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/comparison/${className}.java" /> -package com.alibaba.polardbx.executor.vectorized.comparison; + <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/compare/${className}.java" /> +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; diff --git a/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorColumnColumn.ftl b/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorColumnColumn.ftl index 64a5a4594..f198a9ef5 100644 --- a/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorColumnColumn.ftl +++ b/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorColumnColumn.ftl @@ -5,8 +5,8 @@ <#list operator.types as type> <#assign className = "${operator.classHeader}${type.inputDataType1}Col${type.inputDataType2}ColVectorizedExpression"> - <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/comparison/${className}.java" /> -package com.alibaba.polardbx.executor.vectorized.math; + <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/compare/${className}.java" /> +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; diff --git a/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorColumnConst.ftl b/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorColumnConst.ftl index a3f175bdb..cba9841fa 100644 --- a/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorColumnConst.ftl +++ b/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorColumnConst.ftl @@ -5,8 +5,8 @@ <#list operator.types as type> <#assign className = "${operator.classHeader}${type.inputDataType1}Col${type.inputDataType2}ConstVectorizedExpression"> - <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/comparison/${className}.java" /> -package com.alibaba.polardbx.executor.vectorized.math; + <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/compare/${className}.java" /> +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; diff --git a/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorConstColumn.ftl b/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorConstColumn.ftl index 1ad71e64a..90b433962 100644 --- a/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorConstColumn.ftl +++ b/polardbx-executor/src/main/codegen/templates/ComparisonBinaryOperatorConstColumn.ftl @@ -5,8 +5,8 @@ <#list operator.types as type> <#assign className = "${operator.classHeader}${type.inputDataType1}Const${type.inputDataType2}ColVectorizedExpression"> - <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/comparison/${className}.java" /> -package com.alibaba.polardbx.executor.vectorized.math; + <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/compare/${className}.java" /> +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; diff --git a/polardbx-executor/src/main/codegen/templates/DivideOperatorColumnColumn.ftl b/polardbx-executor/src/main/codegen/templates/DivideOperatorColumnColumn.ftl index 4c71f7aaa..cb1a09b0d 100644 --- a/polardbx-executor/src/main/codegen/templates/DivideOperatorColumnColumn.ftl +++ b/polardbx-executor/src/main/codegen/templates/DivideOperatorColumnColumn.ftl @@ -49,7 +49,7 @@ public class ${className} extends AbstractVectorizedExpression { .map(m -> m.get(DIV_PRECISION_INCREMENT)) .map(n -> ((Number) n).intValue()) .map(i -> Math.min(i, MAX_DECIMAL_SCALE)) - .orElse(DEFAULT_DIV_PRECISION_INCREMENT); + .orElse(DecimalTypeBase.getDefaultDivPrecisionIncrement()); RandomAccessBlock outputVectorSlot = chunk.slotIn(outputIndex, outputDataType); RandomAccessBlock leftInputVectorSlot = chunk.slotIn(children[0].getOutputIndex(), children[0].getOutputDataType()); diff --git a/polardbx-executor/src/main/codegen/templates/DivideOperatorColumnConst.ftl b/polardbx-executor/src/main/codegen/templates/DivideOperatorColumnConst.ftl index 015e2ccfe..74e4fae58 100644 --- a/polardbx-executor/src/main/codegen/templates/DivideOperatorColumnConst.ftl +++ b/polardbx-executor/src/main/codegen/templates/DivideOperatorColumnConst.ftl @@ -74,7 +74,7 @@ public class ${className} extends AbstractVectorizedExpression { .map(m -> m.get(DIV_PRECISION_INCREMENT)) .map(n -> ((Number) n).intValue()) .map(i -> Math.min(i, MAX_DECIMAL_SCALE)) - .orElse(DEFAULT_DIV_PRECISION_INCREMENT); + .orElse(DecimalTypeBase.getDefaultDivPrecisionIncrement()); RandomAccessBlock outputVectorSlot = chunk.slotIn(outputIndex, outputDataType); RandomAccessBlock leftInputVectorSlot = diff --git a/polardbx-executor/src/main/codegen/templates/DivideOperatorConstColumn.ftl b/polardbx-executor/src/main/codegen/templates/DivideOperatorConstColumn.ftl index e5d324581..908f4afc9 100644 --- a/polardbx-executor/src/main/codegen/templates/DivideOperatorConstColumn.ftl +++ b/polardbx-executor/src/main/codegen/templates/DivideOperatorConstColumn.ftl @@ -74,7 +74,7 @@ public class ${className} extends AbstractVectorizedExpression { .map(m -> m.get(DIV_PRECISION_INCREMENT)) .map(n -> ((Number) n).intValue()) .map(i -> Math.min(i, MAX_DECIMAL_SCALE)) - .orElse(DEFAULT_DIV_PRECISION_INCREMENT); + .orElse(DecimalTypeBase.getDefaultDivPrecisionIncrement()); RandomAccessBlock outputVectorSlot = chunk.slotIn(outputIndex, outputDataType); RandomAccessBlock rightInputVectorSlot = diff --git a/polardbx-executor/src/main/codegen/templates/FilterBooleanTestOperator.ftl b/polardbx-executor/src/main/codegen/templates/FilterBooleanTestOperator.ftl index ed786233a..8474ed883 100644 --- a/polardbx-executor/src/main/codegen/templates/FilterBooleanTestOperator.ftl +++ b/polardbx-executor/src/main/codegen/templates/FilterBooleanTestOperator.ftl @@ -5,8 +5,8 @@ <#list cmpOperators.booleanTestOperators.types as type> <#assign className = "Filter${operator.classHeader}${type.inputDataType}ColVectorizedExpression"> - <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/comparison/${className}.java" /> -package com.alibaba.polardbx.executor.vectorized.comparison; + <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/compare/${className}.java" /> +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; diff --git a/polardbx-executor/src/main/codegen/templates/FilterNullTestOperator.ftl b/polardbx-executor/src/main/codegen/templates/FilterNullTestOperator.ftl index e34900940..aa846543f 100644 --- a/polardbx-executor/src/main/codegen/templates/FilterNullTestOperator.ftl +++ b/polardbx-executor/src/main/codegen/templates/FilterNullTestOperator.ftl @@ -5,8 +5,8 @@ <#list cmpOperators.nullTestOperators.types as type> <#assign className = "Filter${operator.classHeader}${type.inputDataType}ColVectorizedExpression"> - <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/comparison/${className}.java" /> -package com.alibaba.polardbx.executor.vectorized.comparison; + <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/compare/${className}.java" /> +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; diff --git a/polardbx-executor/src/main/codegen/templates/NullTestOperator.ftl b/polardbx-executor/src/main/codegen/templates/NullTestOperator.ftl index a2f1183da..f2ff5df60 100644 --- a/polardbx-executor/src/main/codegen/templates/NullTestOperator.ftl +++ b/polardbx-executor/src/main/codegen/templates/NullTestOperator.ftl @@ -5,8 +5,8 @@ <#list cmpOperators.nullTestOperators.types as type> <#assign className = "${operator.classHeader}${type.inputDataType}ColVectorizedExpression"> - <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/comparison/${className}.java" /> -package com.alibaba.polardbx.executor.vectorized.comparison; + <@pp.changeOutputFile name="/com/alibaba/polardbx/executor/vectorized/compare/${className}.java" /> +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; diff --git a/polardbx-executor/src/main/codegen/templates/OrColumnColumn.ftl b/polardbx-executor/src/main/codegen/templates/OrColumnColumn.ftl index 9fd67a1ba..5740fa9d9 100644 --- a/polardbx-executor/src/main/codegen/templates/OrColumnColumn.ftl +++ b/polardbx-executor/src/main/codegen/templates/OrColumnColumn.ftl @@ -44,8 +44,7 @@ import static com.alibaba.polardbx.executor.vectorized.metadata.ArgumentKind.Var Variable, - }, - priority = ExpressionPriority.SPECIAL) +}) public class ${className} extends AbstractVectorizedExpression { public ${className}( int outputIndex, @@ -73,30 +72,30 @@ public class ${className} extends AbstractVectorizedExpression { - long[] res = (outputVectorSlot.cast(LongBlock.class)).longArray(); - boolean[] outputNulls = outputVectorSlot.nulls(); + long[] res = (outputVectorSlot.cast(LongBlock.class)).longArray(); + boolean[] outputNulls = outputVectorSlot.nulls(); - boolean outputVectorHasNull = false; - if (isSelectionInUse) { - for (int i = 0; i < batchSize; i++) { - int j = sel[i]; + boolean outputVectorHasNull = false; + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; - <#list 1..(operator.operandCount) as c> - boolean null${c} = !input${c}HasNull ? false : nulls${c}[j]; + <#list 1..(operator.operandCount) as c> + boolean null${c} = !input${c}HasNull ? false : nulls${c}[j]; <#list 1..(operator.operandCount) as c> - boolean b${c} = (array${c}[j] != 0); + boolean b${c} = (array${c}[j] != 0); boolean hasNull = null1; <#list 2..(operator.operandCount) as c> - hasNull |= null${c}; + hasNull |= null${c}; boolean anyTrue = b1 && !null1; <#list 2..(operator.operandCount) as c> - anyTrue |= (b${c} && !null${c}); + anyTrue |= (b${c} && !null${c}); outputNulls[j] = !anyTrue && hasNull; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ExecutorHelper.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ExecutorHelper.java index 628c3fc4f..261f29bcc 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ExecutorHelper.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ExecutorHelper.java @@ -21,11 +21,13 @@ import com.alibaba.polardbx.common.utils.ExecutorMode; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.cursor.impl.AsyncCacheCursor; import com.alibaba.polardbx.executor.mpp.Session; import com.alibaba.polardbx.executor.mpp.client.DriverResultCursor; +import com.alibaba.polardbx.executor.mpp.client.MppResultCursor; import com.alibaba.polardbx.executor.mpp.client.MppRunner; import com.alibaba.polardbx.executor.mpp.client.SmpResultCursor; import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; @@ -33,6 +35,8 @@ import com.alibaba.polardbx.executor.mpp.execution.SqlQueryLocalExecution; import com.alibaba.polardbx.executor.mpp.operator.Driver; import com.alibaba.polardbx.executor.operator.CacheCursor; +import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.gms.node.MPPQueryMonitor; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.BaseQueryOperation; @@ -62,13 +66,13 @@ import org.apache.commons.lang3.StringUtils; import static com.alibaba.polardbx.executor.mpp.operator.LocalExecutionPlanner.isAssignableFrom; -import static com.alibaba.polardbx.executor.utils.ExecUtils.existMppOnlyInstanceNode; import static com.alibaba.polardbx.executor.utils.ExecUtils.genSubQueryTraceId; /** * Main entry-point of local executor */ public class ExecutorHelper { + private static final MPPQueryMonitor MPP_QUERY_MONITOR = MPPQueryMonitor.getInstance(); private static final Logger log = LoggerFactory.getLogger(ExecutorHelper.class); @@ -140,7 +144,26 @@ public static Cursor executeLocal(RelNode plan, ExecutionContext context, boolea public static Cursor executeCluster(RelNode plan, ExecutionContext context) { context.setExecuteMode(ExecutorMode.MPP); initQueryContext(context); - return new MppRunner(plan, context).execute(); + + long maximumQPS = context.getParamManager().getLong(ConnectionParams.COLUMNAR_CLUSTER_MAXIMUM_QPS); + long maximumConcurrency = + context.getParamManager().getLong(ConnectionParams.COLUMNAR_CLUSTER_MAXIMUM_CONCURRENCY); + if (ConfigDataMode.isMasterMode() && (maximumQPS > 0 || maximumConcurrency > 0)) { + long windowPeriod = context.getParamManager().getLong(ConnectionParams.COLUMNAR_QPS_WINDOW_PERIOD); + // statistic when starting MPP query. + MPP_QUERY_MONITOR.recordStartingQuery(); + + Cursor result = MppRunner.create(plan, context).execute(); + + ((MppResultCursor) result).addCloseListenable(() -> { + // statistic after finished MPP query. + MPP_QUERY_MONITOR.recordFinishedQuery(windowPeriod); + }); + + return result; + } else { + return new MppRunner(plan, context).execute(); + } } public static Cursor executeByCursor(RelNode plan, ExecutionContext context, boolean cacheOutput) { @@ -223,11 +246,10 @@ public static void selectExecutorMode(RelNode plan, ExecutionContext context, bo targetMode = WorkloadUtil.isApWorkload(workloadType) ? ExecutorMode.MPP : ExecutorMode.TP_LOCAL; } - boolean existMppInstanceNode = existMppOnlyInstanceNode() || - context.getParamManager().getBoolean(ConnectionParams.ENABLE_MASTER_MPP); + boolean allowMppMode = ExecUtils.allowMppMode(context); - if (existMppInstanceNode && - MppPlanCheckers.supportsMppPlan(plan, plannerContext, input -> enableMpp, + if (allowMppMode && + MppPlanCheckers.supportsMppPlan(plan, plannerContext, context, input -> enableMpp, MppPlanCheckers.BASIC_CHECKERS, MppPlanCheckers.TRANSACTION_CHECKER, MppPlanCheckers.UPDATE_CHECKER, @@ -240,7 +262,7 @@ public static void selectExecutorMode(RelNode plan, ExecutionContext context, bo context.setExecuteMode(targetMode); } else if (executorMode == ExecutorMode.MPP) { PlannerContext plannerContext = PlannerContext.getPlannerContext(plan); - if (MppPlanCheckers.supportsMppPlan(plan, plannerContext, input -> enableMpp, + if (MppPlanCheckers.supportsMppPlan(plan, plannerContext, context, input -> enableMpp, MppPlanCheckers.BASIC_CHECKERS, MppPlanCheckers.TRANSACTION_CHECKER, MppPlanCheckers.UPDATE_CHECKER)) { context.setExecuteMode(ExecutorMode.MPP); } else { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/PlanExecutor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/PlanExecutor.java index 5ca67f50a..05d4f97ab 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/PlanExecutor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/PlanExecutor.java @@ -27,7 +27,6 @@ import com.alibaba.polardbx.executor.mpp.client.MppResultCursor; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.executor.utils.ExplainExecutorUtil; -import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.config.meta.CostModelWeight; import com.alibaba.polardbx.optimizer.context.ExecutionContext; @@ -51,7 +50,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Properties; import java.util.stream.Collectors; public class PlanExecutor extends AbstractLifecycle { @@ -104,14 +102,14 @@ public static ResultCursor execute(ExecutionPlan plan, ExecutionContext context) private static void resetParams(ExecutionPlan plan, ExecutionContext context) { // enable columnar schedule - if (plan.isUseColumnar()) { + if (context.isUseColumnar()) { context.putIntoHintCmds(ConnectionProperties.ENABLE_COLUMNAR_SCHEDULE, true); } // reset connection parameters by plan mode boolean automaticColumnarParams = context.getParamManager().getBoolean(ConnectionParams.ENABLE_AUTOMATIC_COLUMNAR_PARAMS); - if (plan.isUseColumnar() && automaticColumnarParams) { + if (context.isUseColumnar() && automaticColumnarParams) { Map columnarParams = getColumnarParams(context); context.putAllHintCmds(columnarParams); } @@ -172,6 +170,14 @@ static Map getColumnarParams(ExecutionContext context) { columnarParams.put(ConnectionProperties.ENABLE_NEW_RF, true); } + if (ExecUtils.needPutIfAbsent(context, ConnectionProperties.ENABLE_HTAP)) { + columnarParams.put(ConnectionProperties.ENABLE_HTAP, true); + } + + if (ExecUtils.needPutIfAbsent(context, ConnectionProperties.ENABLE_MASTER_MPP)) { + columnarParams.put(ConnectionProperties.ENABLE_MASTER_MPP, true); + } + return columnarParams; } @@ -221,7 +227,8 @@ public void visit(RelNode node, int ordinal, RelNode parent) { .addAll(cacheRelNodes.stream().map(t -> t.getRelatedId()).collect(Collectors.toSet())); } Cursor sc = ExecutorHelper.execute(relNode, ec, true, false); - if (sc instanceof MppResultCursor && executionPlan.isExplain()) { + //explain and show prune trace need the latest TaskInfo + if (sc instanceof MppResultCursor && (executionPlan.isExplain() || ec.isEnableTrace())) { ((MppResultCursor) sc).waitQueryInfo(true); } return wrapResultCursor(sc, executionPlan.getCursorMeta()); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/AbstractAccumulator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/AbstractAccumulator.java index 8e520c655..fdd908d19 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/AbstractAccumulator.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/AbstractAccumulator.java @@ -44,15 +44,15 @@ public final void accumulate(int groupId, Chunk inputChunk, int position) { * accumulate method with no arguments e.g. COUNT(*) */ void accumulate(int groupId) { - throw new AssertionError("not implemented"); + throw new UnsupportedOperationException("not implemented"); } /** - * accumulate method with one arguments e.g. SUM(x) + * accumulate method with one argument e.g. SUM(x) * * @param position value position in block */ void accumulate(int groupId, Block block, int position) { - throw new AssertionError("not implemented"); + throw new UnsupportedOperationException("not implemented"); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/AccumulatorBuilders.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/AccumulatorBuilders.java index 8a4115a42..bf5d00cb2 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/AccumulatorBuilders.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/AccumulatorBuilders.java @@ -17,6 +17,7 @@ package com.alibaba.polardbx.executor.accumulator; import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.core.expression.calc.Aggregator; @@ -36,7 +37,8 @@ public static Accumulator create(Aggregator aggregator, DataType aggValueType, D } } else if (aggregator.getSqlKind() == SqlKind.SUM) { if (clazz == Decimal.class) { - return new DecimalSumAccumulator(capacity, aggValueType); + boolean useFastDecimal = context.getParamManager().getBoolean(ConnectionParams.ENABLE_DECIMAL_FAST_VEC); + return new DecimalSumAccumulator(capacity, aggValueType, useFastDecimal); } else if (clazz == Long.class) { return new LongSumAccumulator(capacity); } else if (clazz == Double.class) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/CheckSumV2Accumulator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/CheckSumV2Accumulator.java index 2377b4d67..002fd63c0 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/CheckSumV2Accumulator.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/CheckSumV2Accumulator.java @@ -23,6 +23,7 @@ import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.chunk.BlockBuilder; import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.DoubleBlock; import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.core.expression.calc.Aggregator; @@ -35,9 +36,6 @@ public class CheckSumV2Accumulator implements Accumulator { private final DataType[] inputTypes; private final NullableCheckSumGroupState groupState; -// -// private final static byte SEPARATOR_TAG = (byte) 255; -// private final static byte NULL_TAG = (byte) 254; public CheckSumV2Accumulator(Aggregator aggregator, DataType[] rowInputType, int capacity) { int[] inputColumnIndexes = aggregator.getInputColumnIndexes(); @@ -69,7 +67,7 @@ public void accumulate(int groupId, Chunk inputChunk, int position) { crc.update(CrcAccumulator.NULL_TAG); } else { // Must keep compatible to columnar writers. - int checksum = inputBlock.checksum(position); + int checksum = inputBlock.checksumV2(position); crc.update(new byte[] { (byte) (checksum >>> 24), (byte) (checksum >>> 16), (byte) (checksum >>> 8), (byte) checksum}); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/DecimalAvgAccumulator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/DecimalAvgAccumulator.java index 6623f49b5..f3df4890b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/DecimalAvgAccumulator.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/DecimalAvgAccumulator.java @@ -19,6 +19,7 @@ import com.alibaba.polardbx.common.datatype.Decimal; import com.alibaba.polardbx.common.datatype.DecimalRoundMod; import com.alibaba.polardbx.common.datatype.DecimalStructure; +import com.alibaba.polardbx.common.datatype.DecimalTypeBase; import com.alibaba.polardbx.common.datatype.FastDecimalUtils; import com.alibaba.polardbx.executor.accumulator.state.NullableDecimalLongGroupState; import com.alibaba.polardbx.executor.chunk.Block; @@ -29,7 +30,6 @@ import java.util.Optional; -import static com.alibaba.polardbx.common.datatype.DecimalTypeBase.DEFAULT_DIV_PRECISION_INCREMENT; import static com.alibaba.polardbx.common.datatype.DecimalTypeBase.DIV_PRECISION_INCREMENT; import static com.alibaba.polardbx.common.datatype.DecimalTypeBase.E_DEC_DIV_ZERO; import static com.alibaba.polardbx.common.datatype.DecimalTypeBase.MAX_DECIMAL_SCALE; @@ -54,7 +54,7 @@ public class DecimalAvgAccumulator extends AbstractAccumulator { .map(m -> m.get(DIV_PRECISION_INCREMENT)) .map(n -> ((Number) n).intValue()) .map(i -> Math.min(i, MAX_DECIMAL_SCALE)) - .orElse(DEFAULT_DIV_PRECISION_INCREMENT); + .orElse(DecimalTypeBase.getDefaultDivPrecisionIncrement()); this.cache = new Decimal(); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/DecimalSumAccumulator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/DecimalSumAccumulator.java index ba99795dd..3b3d37af8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/DecimalSumAccumulator.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/accumulator/DecimalSumAccumulator.java @@ -42,19 +42,23 @@ public class DecimalSumAccumulator extends AbstractAccumulator { private final DataType[] inputTypes; private final DecimalBoxGroupState state; - private Decimal cache; private int scale; /** * low bits, high bits, error code */ private final long[] results = new long[3]; + private final boolean useFastDecimal; public DecimalSumAccumulator(int capacity, DataType inputType) { - this.cache = new Decimal(); + this(capacity, inputType, true); + } + + public DecimalSumAccumulator(int capacity, DataType inputType, boolean useFastDecimal) { this.inputTypes = new DataType[1]; this.inputTypes[0] = inputType; this.scale = inputType.getScale(); + this.useFastDecimal = useFastDecimal; this.state = new DecimalBoxGroupState(capacity, scale); } @@ -378,18 +382,16 @@ private void normalAddDecimal64(int groupId, long decimal64Val) { throw new IllegalStateException("Expected Decimal64 state"); } + Decimal to = new Decimal(); + // avoid reset memory to 0 FastDecimalUtils.add( beforeValue.getDecimalStructure(), value.getDecimalStructure(), - cache.getDecimalStructure(), + to.getDecimalStructure(), false); - // swap variants to avoid allocating memory - Decimal afterValue = cache; - cache = beforeValue; - - state.set(groupId, afterValue); + state.set(groupId, to); } private void normalAddDecimal128(int groupId, long decimal128Low, long decimal128High) { @@ -418,22 +420,20 @@ private void normalAddDecimal128(int groupId, long decimal128Low, long decimal12 throw new IllegalStateException("Expected Decimal state: " + state.getFlag(groupId)); } + Decimal to = new Decimal(); + // avoid reset memory to 0 FastDecimalUtils.add( beforeValue.getDecimalStructure(), value.getDecimalStructure(), - cache.getDecimalStructure(), + to.getDecimalStructure(), false); - // swap variants to avoid allocating memory - Decimal afterValue = cache; - cache = beforeValue; - - state.set(groupId, afterValue); + state.set(groupId, to); } private void accumulateDecimal(int groupId, DecimalBlock decimalBlock, int position) { - boolean isSimple = decimalBlock.isSimple(); + boolean isSimple = decimalBlock.isSimple() && useFastDecimal; if (state.isNormalDecimal(groupId)) { // normalDecimal + ANY -> normalDecimal normalAddDecimal(groupId, decimalBlock, position); @@ -492,18 +492,16 @@ private void normalAddDecimal(int groupId, DecimalBlock decimalBlock, int positi } else { Decimal beforeValue = state.getDecimal(groupId); + Decimal to = new Decimal(); + // avoid reset memory to 0 FastDecimalUtils.add( beforeValue.getDecimalStructure(), decimalStructure, - cache.getDecimalStructure(), + to.getDecimalStructure(), false); - // swap variants to avoid allocating memory - Decimal afterValue = cache; - cache = beforeValue; - - state.set(groupId, afterValue); + state.set(groupId, to); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/archive/reader/ORCReaderWithAggTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/archive/reader/ORCReaderWithAggTask.java index dd51d1130..a1484f714 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/archive/reader/ORCReaderWithAggTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/archive/reader/ORCReaderWithAggTask.java @@ -212,7 +212,7 @@ private BlockBuilder fetchStatistics(SessionProperties sessionProperties, int co FileSystemGroup fileSystemGroup = FileSystemManager.getFileSystemGroup(fileMeta.getEngine()); Preconditions.checkArgument(fileSystemGroup != null); try { - if (!fileSystemGroup.exists(fileMeta.getFileName(), context.getFinalPlan().isUseColumnar())) { + if (!fileSystemGroup.exists(fileMeta.getFileName(), false)) { throw new TddlRuntimeException(ErrorCode.ERR_EXECUTE_ON_OSS, "File " + fileMeta.getFileName() + " doesn't exits"); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/archive/writer/OSSBackFillExtractor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/archive/writer/OSSBackFillExtractor.java index 03d633b03..e0fc0a487 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/archive/writer/OSSBackFillExtractor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/archive/writer/OSSBackFillExtractor.java @@ -30,6 +30,8 @@ import com.alibaba.polardbx.executor.gsi.GsiBackfillManager; import com.alibaba.polardbx.executor.gsi.PhysicalPlanBuilder; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.gms.partition.BackfillExtraFieldJSON; +import com.alibaba.polardbx.gms.topology.DbGroupInfoAccessor; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; @@ -47,6 +49,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import static com.alibaba.polardbx.executor.utils.failpoint.FailPointKey.FP_RANDOM_BACKFILL_EXCEPTION; @@ -224,6 +227,7 @@ public Map> getSourcePhyTables() { @Override protected List splitAndInitUpperBound(final ExecutionContext baseEc, final long ddlJobId, + final long taskId, final String dbIndex, final String phyTable, final List primaryKeysId) { @@ -255,7 +259,7 @@ protected List splitAndInitUpperBound(f final List> upperBound = executePhysicalPlan(baseEc, plan); - return getBackfillObjectRecords(baseEc, ddlJobId, dbIndex, phyTable, primaryKeysId, upperBound, ""); + return getBackfillObjectRecords(baseEc, ddlJobId, taskId, dbIndex, phyTable, primaryKeysId, upperBound, ""); } /** @@ -266,9 +270,10 @@ protected List splitAndInitUpperBound(f */ public Extractor loadBackfillMetaRestart(ExecutionContext ec) { Long backfillId = ec.getBackfillId(); + Long taskId = Optional.ofNullable(ec.getTaskId()).orElse(backfillId); // Init position mark with upper bound - final List initBfoList = initAllUpperBound(ec, backfillId); + final List initBfoList = initAllUpperBound(ec, backfillId, taskId); doRestartWithRetry(5, backfillId, initBfoList); @@ -318,6 +323,9 @@ private void doRestart(Long backfillId, List getColumnNames() { + return columnNames; + } + + public void setColumnNames(List columnNames) { + this.columnNames = columnNames; + } + + List columnNames; + DataSource dataSource = MetaDbDataSource.getInstance().getDataSource(); + Map leftRow; + Map rightRow; + + ConcurrentHashMap> positionMarksMap; + + public static ConcurrentHashMap backfillSampleManagerMap = new ConcurrentHashMap<>(); + + public static BackfillSampleManager loadBackfillSampleManager(String schemaName, String logicalTableName, + Long jobId, Long taskId, + Map leftRow, + Map rightRow) { + synchronized (backfillSampleManagerMap) { + return backfillSampleManagerMap.computeIfAbsent(taskId, + k -> new BackfillSampleManager(schemaName, logicalTableName, jobId, taskId, leftRow, rightRow)); + } + } + + public static BackfillSampleManager loadBackfillSampleManager(Long taskId) { + synchronized (backfillSampleManagerMap) { + return backfillSampleManagerMap.get(taskId); + } + } + + public static Boolean removeBackfillSampleManager(Long taskId) { + synchronized (backfillSampleManagerMap) { + if (backfillSampleManagerMap.contains(taskId)) { + backfillSampleManagerMap.remove(taskId); + return true; + } + return false; + } + } + + public BackfillSampleManager(String schemaName, String logicalTableName, + Long jobId, Long taskId, Map leftRow, + Map rightRow + ) { + this.taskId = taskId; + this.jobId = jobId; + this.schemaName = schemaName; + this.logicalTableName = logicalTableName; +// this.columnNames = columnNames; + this.leftRow = leftRow; + this.rightRow = rightRow; + } + + public Pair>, List> loadSampleRows(long maxPkRangeSize, + long maxSampleRows, long batchRows, + long batchSize) { + Pair>, List> sampleRowsAndBackfillIds = querySampleRows(); + if (sampleRowsAndBackfillIds.getKey().isEmpty()) { + List> sampleRows = + samplePkRangeFromLogicalTable(schemaName, logicalTableName, + columnNames, leftRow, rightRow, maxPkRangeSize, maxSampleRows, batchRows, batchSize); + +// SQLRecorderLogger.ddlLogger.warn( +// MessageFormat.format( +// "[{0}] sample rows from pk range [{1}], result is [{2}]", +// taskId, +// com.alibaba.polardbx.executor.gsi.GsiUtils.rowsToString(Lists.newArrayList(leftRow, rightRow)), +// com.alibaba.polardbx.executor.gsi.GsiUtils.rowsToString(sampleRows))); + List backfillIds = LogicalTableGsiPkRangeBackfillTask.generateBackfillIds(sampleRows.size() - 1); + int affected = insertIgnoreSampleRow(sampleRows, backfillIds); + if (affected <= 0) { + throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_EXECUTE, + "insert GSI backfill sample rows failed! because there are concurrent task running on the same pk range!"); + } + sampleRowsAndBackfillIds = Pair.of(sampleRows, backfillIds); + } + return sampleRowsAndBackfillIds; + } + + public void updatePositionMark(Long backfillId, Reporter reporter, ExecutionContext ec, + List backfillObjects, + long successRowCount, List lastPk, + List beforeLastPk, boolean finished, + Map primaryKeysIdMap) { + positionMarksMap.put(backfillId, + Lists.newArrayList(reporter, ec, backfillObjects, successRowCount, lastPk, beforeLastPk, finished, + primaryKeysIdMap)); + } + + public void flushPositionMark() { +// for(Long backfillId : positionMarksMap.keySet()){ +// List positionMarkOperator = positionMarksMap.get(backfillId); +// Reporter reporter = (Reporter) positionMarkOperator.get(0); +// ExecutionContext ec = (ExecutionContext) positionMarkOperator.get(1); +// List backfillObjects = (List) positionMarkOperator.get(2); +// long successRowCount = (long) positionMarkOperator.get(3); +// List lastPk = (List) positionMarkOperator.get(4); +// List beforeLastPk = (List) positionMarkOperator.get(5); +// boolean finished = (boolean) positionMarkOperator.get(6); +// Map primaryKeysIdMap = (Map) positionMarkOperator.get(7); +// reporter.addPositionMarkBatch(ec, backfillObjects, successRowCount, lastPk, beforeLastPk, finished, primaryKeysIdMap); +// } + // TODO: flush partition mark. + } + + public void storeExecutionTime(Map executionTime) { + String compressedExecutionTime = DdlHelper.compress(JSON.toJSONString(executionTime)); + String lastCompressedExecutionTime = queryStoredExecutionTime(); + if (StringUtils.isEmpty(lastCompressedExecutionTime)) { + updateExecutionTime(compressedExecutionTime); + } else { + updateExecutionTime(lastCompressedExecutionTime + "\n" + compressedExecutionTime); + } + } + + public List> samplePkRangeFromLogicalTable(String schemaName, + String logicalTableName, + List columnNames, + Map leftRow, + Map rightRow, + long maxPkRangeSize, + long maxSampleRows, + long rangeRows, + long rangeSize) { + TableMeta tableMeta = + OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(logicalTableName); + BackfillStats backfillStats = + BackfillStats.createForLogicalBackfillPkRange(schemaName, logicalTableName, tableMeta, + maxSampleRows, leftRow, rightRow, rangeRows, rangeSize); + setColumnNames(backfillStats.primaryKeyColumns.stream().map(o -> o.getName()).collect(Collectors.toList())); + List splitPoints = new ArrayList<>(); + backfillStats.setMaxSampleRows(maxSampleRows); + backfillStats.checkAndSplitLogicalTable(schemaName, logicalTableName, tableMeta, + splitPoints, + true, maxPkRangeSize, maxSampleRows); + List> sampleRows = new ArrayList<>(); + for (BackfillStats.SplitBound splitBound : splitPoints) { + sampleRows.add(splitBound.left); + } + if (splitPoints.size() >= 1) { + sampleRows.add(splitPoints.get(splitPoints.size() - 1).right); + } else { +// Map nullParamsRow = Transformer.buildColumnsParam(null); + sampleRows.add(leftRow); + sampleRows.add(rightRow); + } + return sampleRows; + } + + public interface Orm { + T convert(ResultSet resultSet) throws SQLException; + + Map params(); + } + + public static final class BackfillSampleRecord implements Orm { + public static BackfillSampleRecord ORM = new BackfillSampleRecord(); + + String schemaName; + String logicalTableName; + Long jobId; + Long taskId; + String columns; + String sampleRows; + String extra; + String backfillIds; + + BackfillSampleRecord() { + } + + BackfillSampleRecord(String schemaName, String logicalTableName, Long jobId, Long taskId, String columns, + String sampleRows, + String extra, + String backfillIds) { + this.schemaName = schemaName; + this.logicalTableName = logicalTableName; + this.jobId = jobId; + this.taskId = taskId; + this.columns = columns; + this.sampleRows = sampleRows; + this.extra = extra; + this.backfillIds = backfillIds; + } + + @Override + public BackfillSampleRecord convert(ResultSet resultSet) throws SQLException { + final long jobId = resultSet.getLong("JOB_ID"); + final long taskId = resultSet.getLong("TASK_ID"); + final String tableSchema = resultSet.getString("SCHEMA_NAME"); + final String tableName = resultSet.getString("TABLE_NAME"); + final String columns = resultSet.getString("COLUMNS"); + final String sampleRows = resultSet.getString("SAMPLE_ROWS"); + final String extra = resultSet.getString("EXTRA"); + final String backfillIds = resultSet.getString("BACKFILL_IDS"); + + return new BackfillSampleRecord(tableSchema, + tableName, + jobId, + taskId, + columns, + sampleRows, + extra, + backfillIds); + } + + @Override + public Map params() { + return Collections.emptyMap(); + } + } + + private static final String SAMPLE_ROWS = "sampleRows"; + private static final String ROWS_NUMS = "rowsNums"; + private static final String FULL_COLUMNS = + "`schema_name`, `table_name`, `job_id`, `task_id`, `columns`, `sample_rows`, `gmt_created`, `gmt_modified`, `extra`, `backfill_ids`"; + + private static final String COLUMNS = + "`schema_name`, `table_name`, `job_id`, `task_id`, `columns`, `sample_rows`, `extra`, `backfill_ids`"; + + private static final String EXTRA_COLUMN = + "extra"; + + private static final String SQL_INSERT_IGNORE_BACKFILL_SAMPLE_ROWS = "INSERT IGNORE INTO " + + GmsSystemTables.BACKFILL_SAMPLE_ROWS + "( " + COLUMNS + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; + + private static final String WHERE_PK = " WHERE `schema_name` = ? AND `table_name` = ? AND `task_id` = ?"; + + private static final String UPDATE_BACKFILL_SAMPLE_ROWS = "UPDATE " + + GmsSystemTables.BACKFILL_SAMPLE_ROWS + " set " + EXTRA_COLUMN + " = ? " + WHERE_PK; + + private static final String SQL_QUERY_BACKFILL_SAMPLE_ROWS = "SELECT " + COLUMNS + " FROM " + + GmsSystemTables.BACKFILL_SAMPLE_ROWS + WHERE_PK; + + private static final String SQL_QUERY_EXECUTION_TIME = "SELECT " + EXTRA_COLUMN + " FROM " + + GmsSystemTables.BACKFILL_SAMPLE_ROWS + WHERE_PK; + + public static String toJsonString(List> sampleRows) { + List>> valueContent = new ArrayList<>(); + for (Map row : sampleRows) { + Map> value = toValue(row); + valueContent.add(value); + } + Map storedValueContent = new HashMap<>(); + storedValueContent.put(SAMPLE_ROWS, valueContent); + storedValueContent.put(ROWS_NUMS, valueContent.size()); + return JSON.toJSONString(storedValueContent, SerializerFeature.DisableCircularReferenceDetect); + } + + public static Map> toValue(Map parameterContextMap) { + Map> value = new HashMap<>(); + for (Map.Entry entry : parameterContextMap.entrySet()) { + ParameterContext context = entry.getValue(); + value.put(entry.getKey(), Lists.newArrayList(context.getParameterMethod().name(), + Transformer.serializeParam(context))); + } + return value; + } + + public static Map fromValue(Map> value) { + Map row = new HashMap<>(); + for (Map.Entry> entry : value.entrySet()) { + int index = Integer.parseInt(String.valueOf(entry.getKey())); + ParameterContext context = Transformer.buildParamByType(index, entry.getValue().get(0), + entry.getValue().get(1)); + row.put(index, context); + } + return row; + } + + public static List> fromJsonString(String jsonString) { + List>> valueContent = new ArrayList<>(); + Map storedValueContent = new HashMap<>(); + storedValueContent = JSON.parseObject(jsonString, storedValueContent.getClass()); + valueContent = (List>>) storedValueContent.get(SAMPLE_ROWS); + List> sampleRows = new ArrayList<>(); + for (Map> value : valueContent) { + Map row = fromValue(value); + sampleRows.add(row); + } + return sampleRows; + } + + public BackfillSampleRecord toBackfillSampleRowRecord( + List> backfillSampleRows, String schemaName, String logicalTable, + Collection columns, Long jobId, + Long taskId, List backfillIds) { + String valueContent = toJsonString(backfillSampleRows); + String compressedSampleRows = DdlHelper.compress(valueContent); + String columnString = StringUtils.join(columns, ","); + String backfillIdString = StringUtils.join(backfillIds, ","); + String extra = ""; + BackfillSampleRecord backfillSampleRecord = new BackfillSampleRecord( + schemaName, + logicalTable, + jobId, + taskId, + columnString, + compressedSampleRows, + extra, + backfillIdString + ); + return backfillSampleRecord; + } + + public Pair>, List> fromBackfillSampleRowRecord( + BackfillSampleRecord record) { + + List> backfillSampleRows = new ArrayList<>(); + String valueContent = DdlHelper.decompress(record.sampleRows); + backfillSampleRows = fromJsonString(valueContent); + List backfillIds = + Arrays.stream(record.backfillIds.split(",")).map(Long::valueOf).collect(Collectors.toList()); + return Pair.of(backfillSampleRows, backfillIds); + } + + Pair>, List> querySampleRows() { + Pair>, List> sampleRows = + Pair.of(new ArrayList<>(), new ArrayList<>()); + final List backfillSampleRecords = new ArrayList<>(); + + Map params = new HashMap<>(); + params.put(1, new ParameterContext(ParameterMethod.setString, new Object[] {1, schemaName})); + params.put(2, new ParameterContext(ParameterMethod.setString, new Object[] {2, logicalTableName})); + params.put(3, new ParameterContext(ParameterMethod.setLong, new Object[] {3, taskId})); + + GsiUtils.wrapWithTransaction(dataSource, (conn) -> { + try { + backfillSampleRecords.addAll( + query(SQL_QUERY_BACKFILL_SAMPLE_ROWS, params, conn, BackfillSampleRecord.ORM)); + } catch (SQLException e) { + throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_EXECUTE, + e, + "insert GSI backfill sample rows failed!"); + } + }, (e) -> new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_EXECUTE, e, + "insert GSI backfill sample rows failed!") + ); + if (!backfillSampleRecords.isEmpty()) { + sampleRows = fromBackfillSampleRowRecord(backfillSampleRecords.get(0)); + } + return sampleRows; + } + + String queryStoredExecutionTime() { + Map params = new HashMap<>(); + params.put(1, new ParameterContext(ParameterMethod.setString, new Object[] {1, schemaName})); + params.put(2, new ParameterContext(ParameterMethod.setString, new Object[] {2, logicalTableName})); + params.put(3, new ParameterContext(ParameterMethod.setLong, new Object[] {3, taskId})); + List executionTimes = new ArrayList<>(); + + GsiUtils.wrapWithTransaction(dataSource, (conn) -> { + try { + executionTimes.addAll( + queryExecutionTime(SQL_QUERY_EXECUTION_TIME, params, conn)); + } catch (SQLException e) { + throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_EXECUTE, + e, + " query GSI execution Time failed!"); + } + }, (e) -> new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_EXECUTE, e, + "query GSI execution Time failed!") + ); + if (!executionTimes.isEmpty()) { + return executionTimes.get(0); + } else { + return ""; + } + } + + public int insertIgnoreSampleRow(List> backfillSampleRows, List backfillIds) { + + Map params = new HashMap<>(); + BackfillSampleRecord record = + toBackfillSampleRowRecord(backfillSampleRows, schemaName, logicalTableName, columnNames, jobId, + taskId, backfillIds); + params.put(1, new ParameterContext(ParameterMethod.setString, new Object[] {1, record.schemaName})); + params.put(2, new ParameterContext(ParameterMethod.setString, new Object[] {2, record.logicalTableName})); + params.put(3, new ParameterContext(ParameterMethod.setLong, new Object[] {3, record.jobId})); + params.put(4, new ParameterContext(ParameterMethod.setLong, new Object[] {4, record.taskId})); + params.put(5, new ParameterContext(ParameterMethod.setString, new Object[] {5, record.columns})); + params.put(6, new ParameterContext(ParameterMethod.setString, new Object[] {6, record.sampleRows})); + params.put(7, new ParameterContext(ParameterMethod.setString, new Object[] {7, record.extra})); + params.put(8, new ParameterContext(ParameterMethod.setString, new Object[] {8, record.backfillIds})); + + final int[] affected = {0}; + GsiUtils.wrapWithTransaction(dataSource, (conn) -> { + try { + affected[0] = update(SQL_INSERT_IGNORE_BACKFILL_SAMPLE_ROWS, Lists.newArrayList(params), conn); + } catch (SQLException e) { + throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_EXECUTE, + e, + "insert GSI backfill sample rows failed!"); + } + }, (e) -> new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_EXECUTE, e, + "insert GSI backfill sample rows failed!") + ); + return affected[0]; + } + + protected int update(String sql, List> params, Connection connection) + throws SQLException { + final int batchSize = 512; + final int[] totalAffected = {0}; + for (int i = 0; i < params.size(); i += batchSize) { + try (PreparedStatement ps = connection.prepareStatement(sql)) { + for (int j = 0; j < batchSize && i + j < params.size(); j++) { + Map batch = params.get(i + j); + ParameterMethod.setParameters(ps, batch); + ps.addBatch(); + } + int[] affected = ps.executeBatch(); + Arrays.stream(affected).forEach(o -> totalAffected[0] += o); + } + } + return totalAffected[0]; + } + + private List query(String sql, Map params, Connection connection, + BackfillSampleManager.Orm orm) + throws SQLException { + try (PreparedStatement ps = connection.prepareStatement(sql)) { + ParameterMethod.setParameters(ps, params); + + final ResultSet rs = ps.executeQuery(); + + final List result = new ArrayList<>(); + while (rs.next()) { + result.add(orm.convert(rs)); + } + return result; + } + } + + private List queryExecutionTime(String sql, Map params, Connection connection) + throws SQLException { + try (PreparedStatement ps = connection.prepareStatement(sql)) { + ParameterMethod.setParameters(ps, params); + + final ResultSet rs = ps.executeQuery(); + + final List result = new ArrayList<>(); + while (rs.next()) { + result.add(rs.getString(EXTRA_COLUMN)); + } + return result; + } + } + + public int updateExecutionTime(String executionTime) { + Map params = new HashMap<>(); + params.put(1, new ParameterContext(ParameterMethod.setString, new Object[] {1, executionTime})); + params.put(2, new ParameterContext(ParameterMethod.setString, new Object[] {2, schemaName})); + params.put(3, new ParameterContext(ParameterMethod.setString, new Object[] {3, logicalTableName})); + params.put(4, new ParameterContext(ParameterMethod.setLong, new Object[] {4, taskId})); + + final int[] affected = {0}; + GsiUtils.wrapWithTransaction(dataSource, (conn) -> { + try { + affected[0] = update(UPDATE_BACKFILL_SAMPLE_ROWS, Lists.newArrayList(params), conn); + } catch (SQLException e) { + throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_EXECUTE, + e, + "insert execution time failed!"); + } + }, (e) -> new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_EXECUTE, e, + "insert execution time failed!") + ); + return affected[0]; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/BackfillStats.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/BackfillStats.java new file mode 100644 index 000000000..66df15f1c --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/BackfillStats.java @@ -0,0 +1,352 @@ +package com.alibaba.polardbx.executor.backfill; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlHelper; +import com.alibaba.polardbx.executor.gms.util.StatisticUtils; +import com.alibaba.polardbx.executor.gsi.PhysicalPlanBuilder; +import com.alibaba.polardbx.executor.gsi.utils.Transformer; +import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.rel.PhyTableOpBuildParams; +import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation; +import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperationFactory; +import com.alibaba.polardbx.optimizer.core.row.Row; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.utils.PlannerUtils; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import com.google.common.collect.ImmutableList; +import groovy.lang.IntRange; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.sql.SqlDynamicParam; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlNodeList; +import org.apache.calcite.sql.SqlSelect; +import org.apache.calcite.sql.SqlSelectWithPartition; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static com.alibaba.polardbx.executor.ddl.job.task.backfill.LogicalTableGsiPkRangeBackfillTask.formatPkRows; +import static java.lang.Math.ceil; +import static java.lang.Math.max; +import static java.lang.Math.min; + +public class BackfillStats { + + private long maxSampleRows = 200_000L; + + private float sampleRate = 0.05f; + + public String schemaName; + public String logicalTableName; + + public TableMeta tableMeta; + public PartitionInfo partitionInfo; + + public List primaryKeyColumns; + + public List sampleRows; + public int batchRows; + public long batchSize; + + public long rangeRows; + public long rangeSize; + + Map leftRow; + Map rightRow; + + Boolean totalTable; + + public Boolean checkAndSplitLogicalTable(String schemaName, String logicalTableName, TableMeta tableMeta, + List splitPoints, Boolean enableSample, + long maxPkRangeSize, + long maxSampleRows) { + if (enableSample) { + if (tableMeta.getLocalPartitionDefinitionInfo() != null) { + return false; + } + //tables with primary key absent not support (e.g. ugsi) + if (!tableMeta.isHasPrimaryKey()) { + return false; + } + this.setMaxSampleRows(maxSampleRows); + this.prepareSampleRate(); + if (this.needSampleAndSplit(maxPkRangeSize)) { + this.sampleLogicalTableAndSort(); + splitPoints.addAll(this.generateSplitBound(maxPkRangeSize)); + if (splitPoints.isEmpty()) { + long leastMaxSampleRows = (long) Math.ceil(maxPkRangeSize * 2.0 / this.rangeSize * this.rangeRows); + String errMsg = String.format( + "The sample rows is %d, sample rate is %f," + + "The range size is too large: %d, with the range rows: %d while the sample rows is restricted: %d, " + + "you can raise the BACKFILL_MAX_SAMPLE_ROWS value to %d", this.sampleRows.size(), + this.sampleRate, + this.rangeSize, this.rangeRows, maxSampleRows, leastMaxSampleRows); + SQLRecorderLogger.ddlLogger.info(errMsg); + return true; + } + } + return true; + } else { + return false; + } + } + + public static BackfillStats createForLogicalBackfill(String schemaName, String logicalTableName, + TableMeta tableMeta, long maxSampleRows) { + BackfillStats backfillStats = new BackfillStats(); + backfillStats.schemaName = schemaName; + backfillStats.logicalTableName = logicalTableName; + backfillStats.tableMeta = tableMeta; + backfillStats.maxSampleRows = maxSampleRows; + backfillStats.primaryKeyColumns = + new ArrayList<>((tableMeta.isHasPrimaryKey() ? tableMeta.getPrimaryIndex().getKeyColumns() : + tableMeta.getGsiImplicitPrimaryKey())); + backfillStats.sampleRows = new ArrayList<>(); + backfillStats.totalTable = true; + backfillStats.leftRow = Transformer.buildColumnsParam(null); + backfillStats.rightRow = Transformer.buildColumnsParam(null); + return backfillStats; + } + + public static BackfillStats createForLogicalBackfillPkRange(String schemaName, String logicalTableName, + TableMeta tableMeta, long maxSampleRows, + Map leftRow, + Map rightRow, + long rangeRows, + long rangeSize + ) { + BackfillStats backfillStats = createForLogicalBackfill(schemaName, logicalTableName, tableMeta, maxSampleRows); + backfillStats.leftRow = leftRow; + backfillStats.rightRow = rightRow; + backfillStats.rangeRows = rangeRows; + backfillStats.rangeSize = rangeSize; + backfillStats.totalTable = false; + return backfillStats; + } + + public void setMaxSampleRows(long maxSamples) { + this.maxSampleRows = maxSamples; + } + + public void prepareSampleRate() { + //SINCE NO LOGICAL TABLE NAME WITH quota IS ALLOWED, we march on in this way. + if (totalTable) { + final String COUNT_SQL = + "SELECT `TABLE_ROWS`, `DATA_LENGTH` from `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA` = '%s' AND `TABLE_NAME` = '%s'"; + String sql = String.format(COUNT_SQL, schemaName, logicalTableName); + List> results = + DdlHelper.getServerConfigManager().executeQuerySql(sql, schemaName, null); + if (results.size() > 0) { + rangeRows = Long.parseLong(results.get(0).get("TABLE_ROWS").toString()); + rangeSize = Long.parseLong(results.get(0).get("DATA_LENGTH").toString()); + } else { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + "could not find table rows for table " + logicalTableName); + } + } + float maxSampleRate; + if (rangeRows < maxSampleRows * 2) { + maxSampleRate = 0.5f; + } else { + maxSampleRate = min((float) ((maxSampleRows + 1.0) / rangeRows), 0.5f); + } + this.sampleRate = maxSampleRate; + } + + public Pair> sampleLogicalTableAndSort() { + // scan sampling + double sampleRateUp; + Boolean withLowerBound = GeneralUtil.isNotEmpty(leftRow); + Boolean withUpperBound = GeneralUtil.isNotEmpty(rightRow); + if (totalTable && !withLowerBound && !withUpperBound) { + sampleRateUp = StatisticUtils.scanAnalyze(schemaName, logicalTableName, primaryKeyColumns, sampleRate, + (int) maxSampleRows, + sampleRows, false); + } else { + PhyTableOperation phyTableOperation = + buildPhyTableOperationForSample(schemaName, logicalTableName, primaryKeyColumns, + tableMeta, withLowerBound, withUpperBound); + List params = buildPkParameters(leftRow, rightRow, primaryKeyColumns.size()); + Map parameterContextMap = buildLogicalSelectWithParam(maxSampleRows, + params, sampleRate, + withLowerBound, withUpperBound); + + sampleRateUp = + StatisticUtils.scanAnalyzeOnPkRange(schemaName, logicalTableName, primaryKeyColumns, sampleRate, + (int) maxSampleRows, + sampleRows, phyTableOperation, parameterContextMap); + // scanAnalyzeOnPkRange is much accurate then sampleScan, so we should split based on the returned rows. + if (sampleRows.size() <= 10000) { + String msg = String.format( + "The sample rows is %d, which is too less within the range from (%s) to (%s) of logical table %s" + + " the sample rate is %f, max sample rows is %d", sampleRows.size(), + formatPkRows(leftRow, null), formatPkRows(rightRow, null), logicalTableName, + sampleRate, maxSampleRows); + SQLRecorderLogger.ddlLogger.warn(msg); + } + } + List indexes = new IntRange(0, primaryKeyColumns.size() - 1).stream().collect(Collectors.toList()); + List dataTypes = primaryKeyColumns.stream().map(ColumnMeta::getDataType).collect(Collectors.toList()); + Comparator comparator = ExecUtils.getComparatorForColumns(indexes, dataTypes, true); + sampleRows.sort(comparator); + return Pair.of(sampleRateUp, sampleRows); + } + + public boolean needSampleAndSplit(long maxPkRangeSize) { + return rangeSize >= maxPkRangeSize; + } + + public static class SplitBound { + public Map left; + public Map right; + public long rows; + public long size; + + public SplitBound(Map left, Map right) { + this.left = left; + this.right = right; + } + + public void setRightRow(Map right) { + this.right = right; + } + + public void setRowsAndSize(long rows, float sampleRate, long rowLength) { + this.rows = (long) (rows / sampleRate); + this.size = rowLength * this.rows; + } + } + + public List generateSplitBound(long maxRangeSize) { + float estimatedRangSize = sampleRows.size() / sampleRate * rangeSize / rangeRows; + float ratio = estimatedRangSize / rangeSize; + long splitCount = Math.max((long) Math.ceil((estimatedRangSize + 1.0) / maxRangeSize), 1L); + if (splitCount >= sampleRows.size()) { + String errMsg = String.format( + "The sample rows is %d, sample rate is %f, and the estimated ratio is %f, " + + "The range size is too large: %d, with the range rows: %d while the sample rows is restricted: %d, " + , this.sampleRows.size(), this.sampleRate, ratio, + this.rangeSize, this.rangeRows, maxSampleRows); + SQLRecorderLogger.ddlLogger.warn(errMsg); + return Collections.emptyList(); + } + int splitSize = (int) max(1, -Math.floorDiv(sampleRows.size(), -splitCount)); + List splitBounds = new ArrayList<>(); + int lastRow = 0; + int row = lastRow + splitSize; + Map nullParamsRow = Transformer.buildColumnsParam(null); + splitBounds.add(new SplitBound(leftRow, nullParamsRow)); + long rowLength = rangeSize / rangeRows; + while (row < sampleRows.size() && lastRow < sampleRows.size()) { + Map paramsRow = Transformer.buildColumnsParam(sampleRows.get(row)); + SplitBound splitBound = splitBounds.get(splitBounds.size() - 1); + splitBound.setRightRow(paramsRow); + splitBound.setRowsAndSize(row - lastRow, sampleRate, rowLength); + splitBounds.get(splitBounds.size() - 1).setRightRow(paramsRow); + splitBounds.add(new SplitBound(paramsRow, nullParamsRow)); + lastRow = row; + row = lastRow + splitSize; + } + SplitBound splitBound = splitBounds.get(splitBounds.size() - 1); + splitBound.setRightRow(rightRow); + splitBound.setRowsAndSize(sampleRows.size() - lastRow, sampleRate, rowLength); + batchRows = (int) Math.floor(splitSize / sampleRate); + batchSize = (int) Math.floor((double) rangeSize / rangeRows * batchRows); + return splitBounds; + } + + public static PhyTableOperation buildPhyTableOperationForSample(String schemaName, String logicalTableName, + List primaryKeyColumns, + TableMeta tableMeta, + Boolean withLowerBound, + Boolean withUpperBound) { + final PhysicalPlanBuilder builder = + new PhysicalPlanBuilder(schemaName, new ExecutionContext(schemaName)); + List pkColumns = primaryKeyColumns.stream().map(o -> o.getName()).collect(Collectors.toList()); + + PhyTableOperation phyTableOperation = + builder.buildSelectPlanForSample(tableMeta, pkColumns, pkColumns, true, withLowerBound, withUpperBound); + return phyTableOperation; + } + + public static Map buildLogicalSelectWithParam(long batchSize, + List params, + double sampleRate, boolean withLowerBound, + boolean withUpperBound) { + Map planParams = new HashMap<>(); + + int nextParamIndex = 1; + + // Parameters for where(DNF) + int pkNumber = 0; + if (withLowerBound || withUpperBound) { + pkNumber = params.size() / ((withLowerBound ? 1 : 0) + (withUpperBound ? 1 : 0)); + } + if (withLowerBound) { + for (int i = 0; i < pkNumber; ++i) { + for (int j = 0; j <= i; ++j) { + planParams.put(nextParamIndex, + new ParameterContext(params.get(j).getParameterMethod(), + new Object[] {nextParamIndex, params.get(j).getArgs()[1]})); + nextParamIndex++; + } + } + } + if (withUpperBound) { + final int base = withLowerBound ? pkNumber : 0; + for (int i = 0; i < pkNumber; ++i) { + for (int j = 0; j <= i; ++j) { + planParams.put(nextParamIndex, + new ParameterContext(params.get(base + j).getParameterMethod(), + new Object[] {nextParamIndex, params.get(base + j).getArgs()[1]})); + nextParamIndex++; + } + } + } + + // Parameter for rand sample + planParams.put(nextParamIndex, + new ParameterContext(ParameterMethod.setDouble, new Object[] {nextParamIndex, sampleRate})); + nextParamIndex++; + + // Parameters for limit + planParams.put(nextParamIndex, + new ParameterContext(ParameterMethod.setObject1, new Object[] {nextParamIndex, batchSize})); + + return planParams; + } + + public static List buildPkParameters(Map leftRow, + Map rightRow, int pkNum) { + List pkParams = new ArrayList<>(); + if (!leftRow.isEmpty()) { + for (int i = 0; i < pkNum; i++) { + pkParams.add(leftRow.get(i)); + } + } + if (!rightRow.isEmpty()) { + for (int i = 0; i < pkNum; i++) { + pkParams.add(rightRow.get(i)); + } + } + return pkParams; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Extractor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Extractor.java index 55cad4300..622e1c501 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Extractor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Extractor.java @@ -78,12 +78,12 @@ import java.math.BigDecimal; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; @@ -117,7 +117,7 @@ public class Extractor extends PhyOperationBuilderCommon { protected final String schemaName; protected final String sourceTableName; - private final String targetTableName; + protected final String targetTableName; protected final long batchSize; protected volatile RateLimiter rateLimiter; protected volatile long nowSpeedLimit; @@ -159,6 +159,8 @@ public class Extractor extends PhyOperationBuilderCommon { * */ protected final PhyTableOperation planSelectWithMinAndMax; + + protected PhyTableOperation planSelectWithoutMinAndMax; /** *
      * SELECT IFNULL(MAX(pk0), 0), ... , IFNULL(MAX(pkn), 0)
@@ -239,6 +241,7 @@ protected Extractor(String schemaName, String sourceTableName, String targetTabl
      */
     public Extractor loadBackfillMeta(ExecutionContext ec) {
         Long backfillId = ec.getBackfillId();
+        Long taskId = Optional.ofNullable(ec.getTaskId()).orElse(backfillId);
         throttle.setBackFillId(backfillId);
 
         final String positionMarkHint = ec.getParamManager().getString(ConnectionParams.GSI_BACKFILL_POSITION_MARK);
@@ -246,7 +249,8 @@ public Extractor loadBackfillMeta(ExecutionContext ec) {
         if (TStringUtil.isEmpty(positionMarkHint)) {
             if (!backfillManager.allReadyHasBackfillObject(backfillId, sourceTableName, targetTableName)) {
                 // Init position mark with upper bound
-                final List initBfoList = initAllUpperBound(ec, backfillId);
+                final List initBfoList =
+                    initAllUpperBound(ec, backfillId, taskId);
 
                 // Insert ignore
                 backfillManager.initBackfillMeta(ec, initBfoList);
@@ -259,7 +263,8 @@ public Extractor loadBackfillMeta(ExecutionContext ec) {
 
             // Insert ignore
             backfillManager
-                .initBackfillMeta(ec, backfillId, schemaName, sourceTableName, targetTableName, backfillObjects);
+                .initBackfillMeta(ec, backfillId, taskId, schemaName, sourceTableName, targetTableName,
+                    backfillObjects);
         }
 
         // Load from system table
@@ -276,14 +281,16 @@ public Extractor loadBackfillMeta(ExecutionContext ec) {
      * @param ddlJobId Ddl job id
      * @return BackfillObjectRecord with upper bound initialized, one for each physical table and primary key
      */
-    protected List initAllUpperBound(ExecutionContext ec, long ddlJobId) {
+    protected List initAllUpperBound(ExecutionContext ec, long ddlJobId,
+                                                                              long taskId) {
 
         return getSourcePhyTables().entrySet()
             .stream()
             .flatMap(e -> e.getValue()
                 .stream()
                 .flatMap(
-                    phyTable -> splitAndInitUpperBound(ec, ddlJobId, e.getKey(), phyTable, primaryKeysId).stream()))
+                    phyTable -> splitAndInitUpperBound(ec, ddlJobId, taskId, e.getKey(), phyTable,
+                        primaryKeysId).stream()))
             .collect(Collectors.toList());
     }
 
@@ -337,28 +344,29 @@ private long getTableRowsCount(final String dbIndex, final String phyTable) {
 
     protected List splitAndInitUpperBound(final ExecutionContext baseEc,
                                                                                    final long ddlJobId,
+                                                                                   final long taskId,
                                                                                    final String dbIndex,
                                                                                    final String phyTable,
                                                                                    final List primaryKeysId) {
         if (!baseEc.getParamManager().getBoolean(ConnectionParams.ENABLE_PHYSICAL_TABLE_PARALLEL_BACKFILL)) {
-            return initUpperBound(baseEc, ddlJobId, dbIndex, phyTable, primaryKeysId);
+            return initUpperBound(baseEc, ddlJobId, taskId, dbIndex, phyTable, primaryKeysId);
         }
 
         // local partition table not support yet
         TableMeta tableMeta = baseEc.getSchemaManager(schemaName).getTable(sourceTableName);
         if (tableMeta.getLocalPartitionDefinitionInfo() != null) {
-            return initUpperBound(baseEc, ddlJobId, dbIndex, phyTable, primaryKeysId);
+            return initUpperBound(baseEc, ddlJobId, taskId, dbIndex, phyTable, primaryKeysId);
         }
 
         //tables with primary key absent not support (e.g. ugsi)
         if (!tableMeta.isHasPrimaryKey()) {
-            return initUpperBound(baseEc, ddlJobId, dbIndex, phyTable, primaryKeysId);
+            return initUpperBound(baseEc, ddlJobId, taskId, dbIndex, phyTable, primaryKeysId);
         }
 
         boolean enableInnodbBtreeSampling = OptimizerContext.getContext(schemaName).getParamManager()
             .getBoolean(ConnectionParams.ENABLE_INNODB_BTREE_SAMPLING);
         if (!enableInnodbBtreeSampling) {
-            return initUpperBound(baseEc, ddlJobId, dbIndex, phyTable, primaryKeysId);
+            return initUpperBound(baseEc, ddlJobId, taskId, dbIndex, phyTable, primaryKeysId);
         }
 
         int splitCount =
@@ -366,14 +374,14 @@ protected List splitAndInitUpperBound(f
         long maxPhyTableRowCount =
             baseEc.getParamManager().getLong(ConnectionParams.PHYSICAL_TABLE_START_SPLIT_SIZE);
         long maxSampleSize =
-            baseEc.getParamManager().getLong(ConnectionParams.BACKFILL_MAX_SAMPLE_SIZE);
+            baseEc.getParamManager().getLong(ConnectionParams.BACKFILL_MAX_SAMPLE_ROWS);
         float samplePercentage =
             baseEc.getParamManager().getFloat(ConnectionParams.BACKFILL_MAX_SAMPLE_PERCENTAGE);
 
         long rowCount = getTableRowsCount(dbIndex, phyTable);
         // judge need split
         if (rowCount < maxPhyTableRowCount || splitCount <= 1) {
-            return initUpperBound(baseEc, ddlJobId, dbIndex, phyTable, primaryKeysId);
+            return initUpperBound(baseEc, ddlJobId, taskId, dbIndex, phyTable, primaryKeysId);
         }
 
         float calSamplePercentage = maxSampleSize * 1.0f / rowCount * 100;
@@ -394,7 +402,7 @@ protected List splitAndInitUpperBound(f
         // step must not less than zero
         int step = resultList.size() / splitCount;
         if (step <= 0) {
-            return initUpperBound(baseEc, ddlJobId, dbIndex, phyTable, primaryKeysId);
+            return initUpperBound(baseEc, ddlJobId, taskId, dbIndex, phyTable, primaryKeysId);
         }
 
         int subStep = step / splitCount;
@@ -427,7 +435,7 @@ protected List splitAndInitUpperBound(f
         upperBoundList.remove(upperBoundList.size() - 1);
         upperBoundList.addAll(upperBound);
 
-        return genBackfillObjectRecordByUpperBound(ddlJobId, dbIndex, phyTable, null, upperBoundList,
+        return genBackfillObjectRecordByUpperBound(ddlJobId, taskId, dbIndex, phyTable, null, upperBoundList,
             subUpperBoundList, rowCount / splitCount, 1);
     }
 
@@ -507,7 +515,7 @@ protected List splitPhysicalBatch(final
         int splitCount =
             ec.getParamManager().getInt(ConnectionParams.SLIDE_WINDOW_SPLIT_SIZE);
         long maxSampleSize =
-            ec.getParamManager().getLong(ConnectionParams.BACKFILL_MAX_SAMPLE_SIZE);
+            ec.getParamManager().getLong(ConnectionParams.BACKFILL_MAX_SAMPLE_ROWS);
         float samplePercentage =
             ec.getParamManager().getFloat(ConnectionParams.BACKFILL_MAX_SAMPLE_PERCENTAGE);
 
@@ -583,17 +591,21 @@ protected List splitPhysicalBatch(final
         }
 
         long ddlJobId = backfillObjects.get(0).jobId;
+        long taskId = backfillObjects.get(0).taskId;
+
         // return new backfill object record
 
         int splitLevel = 1;
         if (backfillObjects.get(0).extra.getSplitLevel() != null) {
             splitLevel += Integer.parseInt(backfillObjects.get(0).extra.getSplitLevel());
         }
-        return genBackfillObjectRecordByUpperBound(ddlJobId, dbIndex, phyTable, convertBoundParamMap(lowerBoundParam),
+        return genBackfillObjectRecordByUpperBound(ddlJobId, taskId, dbIndex, phyTable,
+            convertBoundParamMap(lowerBoundParam),
             upperBoundList, subUpperBoundList, rows / splitCount, splitLevel);
     }
 
-    private List genBackfillObjectRecordByUpperBound(final long ddlJobId,
+    private List genBackfillObjectRecordByUpperBound(final long backfillId,
+                                                                                              final long taskId,
                                                                                               final String dbIndex,
                                                                                               final String physicalTableName,
                                                                                               Map lowerBound,
@@ -627,7 +639,8 @@ private List genBackfillObjectRecordByU
                     extra.setApproximateRowCount(String.valueOf(approximateRowCount));
                     extra.setSplitLevel(String.valueOf(splitLevel));
 
-                    return GsiUtils.buildBackfillObjectRecord(ddlJobId,
+                    return GsiUtils.buildBackfillObjectRecord(backfillId,
+                        taskId,
                         schemaName,
                         sourceTableName,
                         targetTableName,
@@ -676,6 +689,7 @@ private List> getUpperBound(final ExecutionContex
      */
     private List initUpperBound(final ExecutionContext baseEc,
                                                                          final long ddlJobId,
+                                                                         final long taskId,
                                                                          final String dbIndex, final String phyTable,
                                                                          final List primaryKeysId) {
         final List> upperBound = getUpperBound(baseEc, dbIndex, phyTable);
@@ -683,14 +697,16 @@ private List initUpperBound(final Execu
         long tableRows = getTableRowsCount(dbIndex, phyTable);
         BackfillExtraFieldJSON extra = new BackfillExtraFieldJSON();
         extra.setApproximateRowCount(String.valueOf(tableRows));
+        extra.setLogical(false);
 
-        return getBackfillObjectRecords(baseEc, ddlJobId, dbIndex, phyTable, primaryKeysId, upperBound,
+        return getBackfillObjectRecords(baseEc, ddlJobId, taskId, dbIndex, phyTable, primaryKeysId, upperBound,
             BackfillExtraFieldJSON.toJson(extra));
     }
 
     @NotNull
     protected List getBackfillObjectRecords(ExecutionContext baseEc,
-                                                                                     long ddlJobId, String dbIndex,
+                                                                                     long ddlJobId, long taskId,
+                                                                                     String dbIndex,
                                                                                      String phyTable,
                                                                                      List primaryKeysId,
                                                                                      final List> upperBound,
@@ -709,6 +725,7 @@ protected List getBackfillObjectRecords
             if (upperBound.isEmpty()) {
                 // Table is empty, no upper bound needed
                 return GsiUtils.buildBackfillObjectRecord(ddlJobId,
+                    taskId,
                     schemaName,
                     sourceTableName,
                     targetTableName,
@@ -719,6 +736,7 @@ protected List getBackfillObjectRecords
             } else {
                 final ParameterContext pc = upperBound.get(0).get(srcIndex.getAndIncrement() + 1);
                 return GsiUtils.buildBackfillObjectRecord(ddlJobId,
+                    taskId,
                     schemaName,
                     sourceTableName,
                     targetTableName,
@@ -753,11 +771,10 @@ public void foreachBatch(ExecutionContext ec,
         List futures = new ArrayList<>(16);
 
         // Re-balance by physicalDb.
-        List> tasks = reporter.getBackfillBean().backfillObjects.values()
-            .stream()
-            .filter(v -> v.get(0).status.is(UNFINISHED))
-            .collect(Collectors.toList());
-        Collections.shuffle(tasks);
+        List> tasks = new ArrayList<>();
+        if (reporter.getBackfillBean().status.is(UNFINISHED)) {
+            tasks.addAll(reporter.getBackfillBean().backfillObjects.values());
+        }
 
         if (!tasks.isEmpty()) {
             SQLRecorderLogger.ddlLogger.warn(
@@ -838,7 +855,8 @@ public void foreachBatch(ExecutionContext ec,
 
         throttle.stop();
 
-        // After all physical table finished
+        // After all pk range finished
+        // TODO(yijin): reporter need rebinding
         reporter.updateBackfillStatus(ec, GsiBackfillManager.BackfillStatus.SUCCESS);
     }
 
@@ -923,7 +941,7 @@ protected void foreachPhyTableBatch(String dbIndex, String phyTable,
                     throttle.feedback(new com.alibaba.polardbx.executor.backfill.Throttle.FeedbackStats(
                         System.currentTimeMillis() - start, start, lastBatch.size()));
                 }
-                DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set((long) throttle.getActualRateLastCycle());
+//                DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set((long) throttle.getActualRateLastCycle());
 
                 if (rateLimiter != null) {
                     // Limit rate.
@@ -957,7 +975,7 @@ protected void foreachPhyTableBatch(String dbIndex, String phyTable,
                 dbIndex, phyTable, successRowCount, ec, rangeBackfillStartTime, lastBatch, backfillObjects);
         } while (!finished);
 
-        DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set(0);
+//        DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set(0);
         reporter.addBackfillCount(successRowCount);
 
         SQLRecorderLogger.ddlLogger.warn(MessageFormat.format("[{0}] Last backfill row for {1}[{2}][{3}]: {4}",
@@ -1244,7 +1262,7 @@ protected PhyTableOperation buildSamplePlanWithParam(String dbIndex, String phyT
         PhyTableOperation phyTableOperation = planSelectSample;
         SqlSelect sqlSelect = (SqlSelect) phyTableOperation.getNativeSqlNode().clone();
         OptimizerHint optimizerHint = new OptimizerHint();
-        optimizerHint.addHint("+sample_percentage(" + calSamplePercentage + ")");
+        optimizerHint.addHint("+sample_percentage(" + GeneralUtil.formatSampleRate(calSamplePercentage) + ")");
         sqlSelect.setOptimizerHint(optimizerHint);
         PhyTableOpBuildParams buildParams = new PhyTableOpBuildParams();
         buildParams.setGroupName(dbIndex);
@@ -1339,7 +1357,7 @@ public static ExtractorInfo buildExtractorInfo(ExecutionContext ec,
                                                    String sourceTableName,
                                                    String targetTableName,
                                                    boolean skipGeneratedColumn) {
-        return buildExtractorInfo(ec, schemaName, sourceTableName, targetTableName, skipGeneratedColumn, false);
+        return buildExtractorInfo(ec, schemaName, sourceTableName, targetTableName, skipGeneratedColumn, false, false);
     }
 
     public static ExtractorInfo buildExtractorInfo(ExecutionContext ec,
@@ -1347,7 +1365,8 @@ public static ExtractorInfo buildExtractorInfo(ExecutionContext ec,
                                                    String sourceTableName,
                                                    String targetTableName,
                                                    boolean skipGeneratedColumn,
-                                                   boolean onlyReadColumns) {
+                                                   boolean onlyReadColumns,
+                                                   boolean omcColumnMapping) {
         final SchemaManager sm = OptimizerContext.getContext(schemaName).getLatestSchemaManager();
         final TableMeta sourceTableMeta = sm.getTable(sourceTableName);
         final TableMeta targetTableMeta = sm.getTable(targetTableName);
@@ -1389,7 +1408,7 @@ public static ExtractorInfo buildExtractorInfo(ExecutionContext ec,
         List targetTableColumnsAfterMapping = new ArrayList<>(targetTableColumns.size());
         for (String columnName : targetTableColumns) {
             ColumnMeta columnMeta = targetTableMeta.getColumn(columnName);
-            if (columnMeta.getMappingName() != null) {
+            if (omcColumnMapping && columnMeta.getMappingName() != null) {
                 if (!columnMeta.getMappingName().isEmpty()) {
                     sourceTableColumnsAfterMapping.add(columnMeta.getMappingName());
                     targetTableColumnsAfterMapping.add(columnName);
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/GsiPartitionExtractor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/GsiPartitionExtractor.java
new file mode 100644
index 000000000..760bcbfef
--- /dev/null
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/GsiPartitionExtractor.java
@@ -0,0 +1,154 @@
+package com.alibaba.polardbx.executor.backfill;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException;
+import com.alibaba.polardbx.common.exception.TddlRuntimeException;
+import com.alibaba.polardbx.common.exception.code.ErrorCode;
+import com.alibaba.polardbx.common.jdbc.ParameterContext;
+import com.alibaba.polardbx.common.jdbc.ParameterMethod;
+import com.alibaba.polardbx.common.properties.ConnectionParams;
+import com.alibaba.polardbx.common.properties.DynamicConfig;
+import com.alibaba.polardbx.common.properties.ParamManager;
+import com.alibaba.polardbx.common.utils.GeneralUtil;
+import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.common.utils.TStringUtil;
+import com.alibaba.polardbx.executor.ExecutorHelper;
+import com.alibaba.polardbx.executor.balancer.stats.StatsUtils;
+import com.alibaba.polardbx.executor.common.ExecutorContext;
+import com.alibaba.polardbx.executor.cursor.Cursor;
+import com.alibaba.polardbx.executor.ddl.newengine.DdlEngineStats;
+import com.alibaba.polardbx.executor.ddl.newengine.cross.CrossEngineValidator;
+import com.alibaba.polardbx.executor.ddl.workqueue.BackFillThreadPool;
+import com.alibaba.polardbx.executor.ddl.workqueue.PriorityFIFOTask;
+import com.alibaba.polardbx.executor.gsi.GsiBackfillManager;
+import com.alibaba.polardbx.executor.gsi.GsiUtils;
+import com.alibaba.polardbx.executor.gsi.PhysicalPlanBuilder;
+import com.alibaba.polardbx.executor.gsi.backfill.GsiExtractor;
+import com.alibaba.polardbx.executor.gsi.utils.Transformer;
+import com.alibaba.polardbx.executor.spi.ITransactionManager;
+import com.alibaba.polardbx.executor.utils.failpoint.FailPoint;
+import com.alibaba.polardbx.gms.partition.BackfillExtraFieldJSON;
+import com.alibaba.polardbx.gms.util.GroupInfoUtil;
+import com.alibaba.polardbx.optimizer.OptimizerContext;
+import com.alibaba.polardbx.optimizer.config.table.ColumnMeta;
+import com.alibaba.polardbx.optimizer.config.table.SchemaManager;
+import com.alibaba.polardbx.optimizer.config.table.TableMeta;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.optimizer.core.rel.PhyOperationBuilderCommon;
+import com.alibaba.polardbx.optimizer.core.rel.PhyTableOpBuildParams;
+import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation;
+import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperationFactory;
+import com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter;
+import com.alibaba.polardbx.optimizer.utils.PlannerUtils;
+import com.alibaba.polardbx.optimizer.utils.RelUtils;
+import com.alibaba.polardbx.statistics.SQLRecorderLogger;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import com.google.common.util.concurrent.RateLimiter;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.sql.OptimizerHint;
+import org.apache.calcite.sql.SqlSelect;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.math.RandomUtils;
+import org.jetbrains.annotations.NotNull;
+
+import java.math.BigDecimal;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import static com.alibaba.polardbx.common.exception.code.ErrorCode.ER_LOCK_DEADLOCK;
+import static com.alibaba.polardbx.common.exception.code.ErrorCode.ER_LOCK_WAIT_TIMEOUT;
+import static com.alibaba.polardbx.executor.gsi.GsiBackfillManager.BackfillStatus.UNFINISHED;
+import static com.alibaba.polardbx.executor.gsi.GsiUtils.RETRY_COUNT;
+import static com.alibaba.polardbx.executor.gsi.GsiUtils.RETRY_WAIT;
+import static com.alibaba.polardbx.executor.gsi.GsiUtils.SQLSTATE_DEADLOCK;
+import static com.alibaba.polardbx.executor.gsi.GsiUtils.SQLSTATE_LOCK_TIMEOUT;
+import static com.alibaba.polardbx.executor.utils.failpoint.FailPointKey.FP_RANDOM_BACKFILL_EXCEPTION;
+import static com.alibaba.polardbx.gms.partition.BackfillExtraFieldJSON.isNotEmpty;
+
+/**
+ * Created by luoyanxin.
+ *
+ * @author luoyanxin
+ */
+public class GsiPartitionExtractor extends GsiExtractor {
+
+    List partitionList;
+
+    protected GsiPartitionExtractor(String schemaName, String sourceTableName, String targetTableName, long batchSize,
+                                    long speedMin, long speedLimit, long parallelism, boolean useBinary,
+                                    List modifyStringColumns,
+                                    PhyTableOperation planSelectWithMax, PhyTableOperation planSelectWithMin,
+                                    PhyTableOperation planSelectWithMinAndMax,
+                                    PhyTableOperation planSelectMaxPk,
+                                    PhyTableOperation planSelectSample,
+                                    List primaryKeysId,
+                                    List partitionList) {
+        super(schemaName, sourceTableName, targetTableName, batchSize, speedMin, speedLimit, parallelism, useBinary,
+            modifyStringColumns, planSelectWithMax, planSelectWithMin, planSelectWithMinAndMax, planSelectMaxPk,
+            planSelectSample
+            , primaryKeysId);
+        this.partitionList = partitionList;
+    }
+
+    public static Extractor create(String schemaName, String sourceTableName, String targetTableName, long batchSize,
+                                   long speedMin, long speedLimit, long parallelism, boolean useBinary,
+                                   List modifyStringColumns, List partitionList, ExecutionContext ec) {
+        ExtractorInfo info = Extractor.buildExtractorInfo(ec, schemaName, sourceTableName, targetTableName, true);
+        final PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, useBinary, modifyStringColumns, ec);
+
+        return new GsiPartitionExtractor(schemaName,
+            sourceTableName,
+            targetTableName,
+            batchSize,
+            speedMin,
+            speedLimit,
+            parallelism,
+            useBinary,
+            modifyStringColumns,
+            builder.buildSelectForBackfill(info.getSourceTableMeta(), info.getTargetTableColumns(),
+                info.getPrimaryKeys(),
+                false, true, SqlSelect.LockMode.SHARED_LOCK),
+            builder.buildSelectForBackfill(info.getSourceTableMeta(), info.getTargetTableColumns(),
+                info.getPrimaryKeys(),
+                true, false,
+                SqlSelect.LockMode.SHARED_LOCK),
+            builder.buildSelectForBackfill(info.getSourceTableMeta(), info.getTargetTableColumns(),
+                info.getPrimaryKeys(),
+                true, true,
+                SqlSelect.LockMode.SHARED_LOCK),
+            builder.buildSelectMaxPkForBackfill(info.getSourceTableMeta(), info.getPrimaryKeys()),
+            builder.buildSqlSelectForSample(info.getSourceTableMeta(), info.getPrimaryKeys()),
+            info.getPrimaryKeysId(),
+            partitionList);
+    }
+
+    @Override
+    public Map> getSourcePhyTables() {
+        return GsiUtils.getPhyTablesForBackFill(schemaName, sourceTableName, partitionList);
+    }
+
+}
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/GsiPkRangeExtractor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/GsiPkRangeExtractor.java
new file mode 100644
index 000000000..65fde999b
--- /dev/null
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/GsiPkRangeExtractor.java
@@ -0,0 +1,609 @@
+package com.alibaba.polardbx.executor.backfill;
+
+import com.alibaba.polardbx.common.exception.TddlRuntimeException;
+import com.alibaba.polardbx.common.exception.code.ErrorCode;
+import com.alibaba.polardbx.common.jdbc.ParameterContext;
+import com.alibaba.polardbx.common.jdbc.ParameterMethod;
+import com.alibaba.polardbx.common.properties.ConnectionParams;
+import com.alibaba.polardbx.common.properties.DynamicConfig;
+import com.alibaba.polardbx.common.utils.GeneralUtil;
+import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.executor.ddl.newengine.DdlEngineStats;
+import com.alibaba.polardbx.executor.ddl.newengine.cross.CrossEngineValidator;
+import com.alibaba.polardbx.executor.ddl.workqueue.BackFillThreadPool;
+import com.alibaba.polardbx.executor.ddl.workqueue.PriorityFIFOTask;
+import com.alibaba.polardbx.executor.gsi.GsiBackfillManager;
+import com.alibaba.polardbx.executor.gsi.GsiUtils;
+import com.alibaba.polardbx.executor.gsi.PhysicalPlanBuilder;
+import com.alibaba.polardbx.executor.gsi.utils.Transformer;
+import com.alibaba.polardbx.executor.utils.failpoint.FailPoint;
+import com.alibaba.polardbx.gms.partition.BackfillExtraFieldJSON;
+import com.alibaba.polardbx.optimizer.OptimizerContext;
+import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager;
+import com.alibaba.polardbx.optimizer.config.table.TableMeta;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.rel.PhyTableOpBuildParams;
+import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation;
+import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperationFactory;
+import com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter;
+import com.alibaba.polardbx.statistics.SQLRecorderLogger;
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.sql.SqlSelect;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.alibaba.polardbx.common.exception.code.ErrorCode.ER_LOCK_DEADLOCK;
+import static com.alibaba.polardbx.common.exception.code.ErrorCode.ER_LOCK_WAIT_TIMEOUT;
+import static com.alibaba.polardbx.executor.gsi.GsiBackfillManager.BackfillStatus.UNFINISHED;
+import static com.alibaba.polardbx.executor.gsi.GsiUtils.SQLSTATE_DEADLOCK;
+import static com.alibaba.polardbx.executor.gsi.GsiUtils.SQLSTATE_LOCK_TIMEOUT;
+import static com.alibaba.polardbx.executor.utils.failpoint.FailPointKey.FP_RANDOM_BACKFILL_EXCEPTION;
+
+/**
+ * Created by luoyanxin.
+ *
+ * @author luoyanxin
+ */
+public class GsiPkRangeExtractor extends Extractor {
+
+    private boolean needBuildSubBoundList = true;
+
+    private Map>> backfillSubBoundList = new HashMap<>();
+
+    static private final Integer maxRandomInterval = 10000;
+
+    protected Pair, Map> pkRange;
+    protected TableMeta targetTableMeta;
+    protected int estimatedBatchSize;
+
+    public static Extractor create(String schemaName, String sourceTableName, String targetTableName, long batchSize,
+                                   long speedMin, long speedLimit, long parallelism, boolean useBinary,
+                                   List modifyStringColumns,
+                                   Pair, Map> pkRange,
+                                   ExecutionContext ec) {
+        Extractor.ExtractorInfo
+            info = Extractor.buildExtractorInfo(ec, schemaName, sourceTableName, targetTableName, true);
+        final PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, useBinary, modifyStringColumns, ec);
+
+        TableMeta targetTableMeta =
+            OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(targetTableName);
+        Boolean lockRead = ec.getParamManager().getBoolean(ConnectionParams.GSI_PK_RANGE_LOCK_READ);
+        SqlSelect.LockMode lockMode = null;
+        if (lockRead) {
+            lockMode = SqlSelect.LockMode.SHARED_LOCK;
+        }
+        return new GsiPkRangeExtractor(schemaName,
+            sourceTableName,
+            targetTableName,
+            batchSize,
+            speedMin,
+            speedLimit,
+            parallelism,
+            useBinary,
+            modifyStringColumns,
+            builder.buildSelectForBackfill(info.getSourceTableMeta(), info.getTargetTableColumns(),
+                info.getPrimaryKeys(),
+                false, false, lockMode, null, true, true),
+            builder.buildSelectForBackfill(info.getSourceTableMeta(), info.getTargetTableColumns(),
+                info.getPrimaryKeys(),
+                false, true, lockMode, null, true, true),
+            builder.buildSelectForBackfill(info.getSourceTableMeta(), info.getTargetTableColumns(),
+                info.getPrimaryKeys(),
+                true, false,
+                lockMode, null, true, true),
+            builder.buildSelectForBackfill(info.getSourceTableMeta(), info.getTargetTableColumns(),
+                info.getPrimaryKeys(),
+                true, true,
+                lockMode, null, true, true),
+            builder.buildSelectMaxPkForBackfill(info.getSourceTableMeta(), info.getPrimaryKeys()),
+            builder.buildSqlSelectForSample(info.getSourceTableMeta(), info.getPrimaryKeys()),
+            info.getPrimaryKeysId(),
+            pkRange,
+            targetTableMeta,
+            (int) ec.getEstimatedBackfillBatchRows());
+    }
+
+    public GsiPkRangeExtractor(String schemaName, String sourceTableName, String targetTableName, long batchSize,
+                               long speedMin, long speedLimit, long parallelism, boolean useBinary,
+                               List modifyStringColumns,
+                               PhyTableOperation planSelectWithoutMinAndMax,
+                               PhyTableOperation planSelectWithMax, PhyTableOperation planSelectWithMin,
+                               PhyTableOperation planSelectWithMinAndMax,
+                               PhyTableOperation planSelectMaxPk,
+                               PhyTableOperation planSelectSample,
+                               List primaryKeysId,
+                               Pair, Map> pkRange,
+                               TableMeta targetTableMeta, int estimatedBatchSize) {
+        super(schemaName, sourceTableName, targetTableName, batchSize, speedMin, speedLimit, parallelism, false,
+            null, planSelectWithMax,
+            planSelectWithMin, planSelectWithMinAndMax, planSelectMaxPk, null, primaryKeysId);
+        this.pkRange = pkRange;
+        this.targetTableMeta = targetTableMeta;
+        this.estimatedBatchSize = estimatedBatchSize;
+        this.planSelectWithoutMinAndMax = planSelectWithoutMinAndMax;
+    }
+
+    @Override
+    protected List initAllUpperBound(ExecutionContext ec, long ddlJobId,
+                                                                              long taskId) {
+        return splitAndInitUpperBound(ec, ddlJobId, taskId, primaryKeysId, pkRange);
+    }
+
+    protected List splitAndInitUpperBound(final ExecutionContext baseEc,
+                                                                                   final long ddlJobId,
+                                                                                   final long taskId,
+                                                                                   final List primaryKeysId,
+                                                                                   final Pair, Map> pkRange) {
+
+        // TODO:(yijin), split and init upper bound by sample result, for example, each range should contains only 16MB sample,
+        // and we need to assign the approximateRowCount
+        // we will optimize this after profile.
+
+        Long approximateRowCount = (long) estimatedBatchSize;
+        // convert pkRange to BackfillObjectBound
+        Map lowerBound = pkRange.getKey() != null ? pkRange.getKey() : new HashMap<>();
+        Map upperBound = pkRange.getValue() != null ? pkRange.getValue() : new HashMap<>();
+
+        return genBackfillObjectRecordByUpperBound(ddlJobId, taskId, lowerBound, upperBound
+            , approximateRowCount, 1);
+    }
+
+    private List genBackfillObjectRecordByUpperBound(final long ddlJobId,
+                                                                                              final long taskId,
+                                                                                              Map lowerBound,
+                                                                                              Map upperBound,
+                                                                                              long approximateRowCount,
+                                                                                              int splitLevel) {
+        List backfillBoundRecords = new ArrayList<>();
+
+        // Convert to BackfillObjectRecord
+        BackfillExtraFieldJSON extra = new BackfillExtraFieldJSON();
+        extra.setApproximateRowCount(String.valueOf(approximateRowCount));
+        extra.setSplitLevel(String.valueOf(splitLevel));
+        extra.setLogical(false);
+        // TODO: split by lastItem
+
+        for (int i = 0; i < primaryKeysId.size(); ++i) {
+            int columnIndex = primaryKeysId.get(i);
+            String paramMethod = null;
+            if (!lowerBound.isEmpty() || !upperBound.isEmpty()) {
+                paramMethod = lowerBound.isEmpty() ? upperBound.get(i).getParameterMethod().toString() :
+                    lowerBound.get(i).getParameterMethod().toString();
+            }
+            backfillBoundRecords.add(GsiUtils.buildBackfillObjectRecord(ddlJobId,
+                taskId,
+                schemaName,
+                sourceTableName,
+                targetTableName,
+                //for logical level record.
+                "",
+                "",
+                columnIndex,
+                paramMethod,
+                Transformer.serializeParam(lowerBound.get(i)),
+                Transformer.serializeParam(upperBound.get(i)),
+                BackfillExtraFieldJSON.toJson(extra)));
+        }
+        return backfillBoundRecords;
+    }
+
+    /**
+     * Lock and read batch from logical table, feed them to consumer
+     *
+     * @param ec base execution context
+     * @param consumer next step
+     */
+    @Override
+    public void foreachBatch(ExecutionContext ec,
+                             BatchConsumer consumer) {
+        // For each physical table there is a backfill object which represents a row in
+        // system table
+
+        // set KILL_CLOSE_STREAM = true
+        ec.getExtraCmds().put(ConnectionParams.KILL_CLOSE_STREAM.toString(), true);
+
+        // interrupted
+        AtomicReference interrupted = new AtomicReference<>(false);
+
+        List futures = new ArrayList<>(16);
+
+        List> tasks = reporter.getBackfillBean().backfillObjects.values()
+            .stream()
+            .filter(v -> v.get(0).status.is(UNFINISHED))
+            .collect(Collectors.toList());
+        Collections.shuffle(tasks);
+
+        if (!tasks.isEmpty()) {
+            SQLRecorderLogger.ddlLogger.warn(
+                MessageFormat.format("[{0}] Backfill job: {1} start with {2} task(s) parallelism {3}.",
+                    ec.getTraceId(), tasks.get(0).get(0).jobId, tasks.size(), parallelism));
+        } else {
+            ec.setEstimatedBackfillBatchRows(-1);
+        }
+
+        AtomicReference excep = new AtomicReference<>(null);
+        if (parallelism <= 0 || parallelism >= BackFillThreadPool.getInstance().getCorePoolSize()) {
+            // Full queued.
+            tasks.forEach(v -> {
+                FutureTask task = new FutureTask<>(
+                    () -> foreachPhyTableBatch(Optional.ofNullable(v.get(0).physicalDb).orElse(""),
+                        Optional.ofNullable(v.get(0).physicalTable).orElse(""), v, ec, consumer,
+                        interrupted), null);
+                futures.add(task);
+                BackFillThreadPool.getInstance()
+                    .executeWithContext(task, PriorityFIFOTask.TaskPriority.GSI_BACKFILL_TASK);
+            });
+        } else {
+
+            // Use a bounded blocking queue to control the parallelism.
+            BlockingQueue blockingQueue = new ArrayBlockingQueue<>((int) parallelism);
+            tasks.forEach(v -> {
+                try {
+                    blockingQueue.put(new Object());
+                } catch (Exception e) {
+                    excep.set(e);
+                }
+                if (null == excep.get()) {
+                    FutureTask task = new FutureTask<>(() -> {
+                        try {
+                            foreachPhyTableBatch(v.get(0).physicalDb, v.get(0).physicalTable, v, ec, consumer,
+                                interrupted);
+                        } finally {
+                            // Poll in finally to prevent dead lock on putting blockingQueue.
+                            blockingQueue.poll();
+                        }
+                        return null;
+                    });
+                    futures.add(task);
+                    BackFillThreadPool.getInstance()
+                        .executeWithContext(task, PriorityFIFOTask.TaskPriority.GSI_BACKFILL_TASK);
+                }
+            });
+        }
+
+        if (excep.get() != null) {
+            // Interrupt all.
+            futures.forEach(f -> {
+                try {
+                    f.cancel(true);
+                } catch (Throwable ignore) {
+                }
+            });
+        }
+
+        for (Future future : futures) {
+            try {
+                future.get();
+            } catch (Exception e) {
+                if (null == excep.get()) {
+                    excep.set(e);
+                }
+
+                // set interrupt
+                interrupted.set(true);
+            }
+        }
+
+        if (excep.get() != null) {
+            if (!excep.get().getMessage().contains("need to be split into smaller batches")) {
+                throttle.stop();
+            } else {
+                SQLRecorderLogger.ddlLogger.warn("all backfill feature task was interrupted by split");
+            }
+            throw GeneralUtil.nestedException(excep.get());
+        }
+
+        throttle.stop();
+
+        // After all physical table finished
+        reporter.updateBackfillStatus(ec, GsiBackfillManager.BackfillStatus.SUCCESS);
+    }
+
+    /**
+     * Lock and read batch from physical table, feed them to consumer
+     *
+     * @param dbIndex physical db key actually useless...
+     * @param phyTable physical table name actually useless...
+     * @param ec base execution context
+     * @param loader next step
+     */
+    @Override
+    protected void foreachPhyTableBatch(String dbIndex, String phyTable,
+                                        List backfillObjects,
+                                        ExecutionContext ec,
+                                        BatchConsumer loader,
+                                        AtomicReference interrupted) {
+        String physicalTableName = TddlSqlToRelConverter.unwrapPhysicalTableName(phyTable);
+
+        // Load upper bound
+        List upperBoundParam =
+            buildUpperBoundParam(backfillObjects.size(), backfillObjects, primaryKeysIdMap);
+        final boolean withUpperBound = GeneralUtil.isNotEmpty(upperBoundParam);
+
+        // Init historical position mark
+        long successRowCount = backfillObjects.get(0).successRowCount;
+        List lastPk = initSelectParam(backfillObjects, primaryKeysIdMap);
+
+        long rangeBackfillStartTime = System.currentTimeMillis();
+
+        BackfillSampleManager backfillSampleManager = BackfillSampleManager.loadBackfillSampleManager(ec.getTaskId());
+        List> lastBatch = null;
+        boolean finished = false;
+        long actualBatchSize = batchSize;
+        IServerConfigManager serverConfigManager = GsiUtils.getServerConfigManager();
+        SQLRecorderLogger.ddlLogger.warn(MessageFormat.format("[{0}] [{1}][{2}] load pk range start with ({3})",
+            ec.getTraceId(),
+            String.valueOf(ec.getTaskId()),
+            String.valueOf(ec.getBackfillId()),
+            GsiUtils.rowToString(lastPk)));
+        do {
+            try {
+                if (rateLimiter != null) {
+                    rateLimiter.acquire((int) actualBatchSize);
+                }
+                long start = System.currentTimeMillis();
+
+                // Dynamic adjust lower bound of rate.
+                final long dynamicRate = DynamicConfig.getInstance().getGeneralDynamicSpeedLimitation();
+                if (dynamicRate > 0) {
+                    throttle.resetMaxRate(dynamicRate);
+                }
+
+                // For next batch, build select plan and parameters
+                final PhyTableOperation selectPlan = buildLogicalSelectWithParam(
+                    schemaName,
+                    sourceTableName,
+                    actualBatchSize,
+                    Stream.concat(lastPk.stream(), upperBoundParam.stream()).collect(Collectors.toList()),
+                    GeneralUtil.isNotEmpty(lastPk),
+                    withUpperBound,
+                    planSelectWithoutMinAndMax,
+                    planSelectWithMax,
+                    planSelectWithMin,
+                    planSelectWithMinAndMax);
+
+                List finalLastPk = lastPk;
+                lastBatch = GsiUtils.retryOnException(
+                    // 1. Lock rows within trx1 (distributed db transaction)
+                    // 2. Fill into index table within trx2 (XA transaction)
+                    // 3. Trx1 commit, if (success) {trx2 commit} else {trx2 rollback}
+                    () -> GsiUtils.wrapWithDistributedTrxForPkExtractor(tm, ec,
+                        serverConfigManager,
+                        (ecAndConn) -> {
+                            try {
+                                return extract(dbIndex, physicalTableName, selectPlan, ecAndConn, loader, finalLastPk,
+                                    upperBoundParam);
+                            } catch (SQLException e) {
+                                throw new RuntimeException(e);
+                            }
+                        }),
+                    e -> (GsiUtils.vendorErrorIs(e, SQLSTATE_DEADLOCK, ER_LOCK_DEADLOCK)
+                        || GsiUtils.vendorErrorIs(e, SQLSTATE_LOCK_TIMEOUT, ER_LOCK_WAIT_TIMEOUT))
+                        || e.getMessage().contains("Loader check error."),
+                    // keep it as before, no need to change.
+                    (e, retryCount) -> deadlockErrConsumer(selectPlan, ec, e, retryCount),
+                    ec);
+
+                // For status recording
+                List beforeLastPk = lastPk;
+
+                // Build parameter for next batch
+                lastPk = buildSelectParam(lastBatch, primaryKeysId);
+
+                finished = lastBatch.size() != actualBatchSize;
+
+                // Update position mark
+                successRowCount += lastBatch.size();
+
+                SQLRecorderLogger.ddlLogger.warn(
+                    MessageFormat.format(
+                        "[{0}] [{1}][{2}] pk range last backfill success count and pks: [{3}], ({4}), finished is [{5}]",
+                        ec.getTraceId(),
+                        String.valueOf(ec.getTaskId()),
+                        String.valueOf(ec.getBackfillId()),
+                        successRowCount,
+                        GsiUtils.rowToString(lastPk), finished));
+//                backfillSampleManager.updatePositionMark(ec.getBackfillId(), reporter, ec, backfillObjects,
+//                    successRowCount, lastPk, beforeLastPk, finished, primaryKeysIdMap);
+//                SQLRecorderLogger.ddlLogger.warn(
+//                    MessageFormat.format(
+//                        "[{0}] [{1}][{2}] pk range last backfill success count and pks: [{3}], ({4}), finished is [{5}]",
+//                        ec.getTraceId(),
+//                        String.valueOf(ec.getTaskId()),
+//                        String.valueOf(ec.getBackfillId()),
+//                        successRowCount,
+//                        GsiUtils.rowsToString(lastBatch), finished));
+                reporter.updatePositionMark(ec, backfillObjects, successRowCount, lastPk, beforeLastPk, finished,
+                    primaryKeysIdMap);
+                ec.getStats().backfillRows.addAndGet(lastBatch.size());
+                DdlEngineStats.METRIC_BACKFILL_ROWS_FINISHED.update(lastBatch.size());
+
+                if (!finished) {
+                    throttle.feedback(new Throttle.FeedbackStats(
+                        System.currentTimeMillis() - start, start, lastBatch.size()));
+                }
+//                DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set((long) throttle.getActualRateLastCycle());
+
+                if (rateLimiter != null) {
+                    // Limit rate.
+                    rateLimiter.setRate(throttle.getNewRate());
+                }
+
+                // Check DDL is ongoing.
+                if (CrossEngineValidator.isJobInterrupted(ec) || Thread.currentThread().isInterrupted()
+                    || interrupted.get()) {
+                    long jobId = ec.getDdlJobId();
+                    throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR,
+                        "The job '" + jobId + "' has been cancelled");
+                }
+                if (actualBatchSize < batchSize) {
+                    actualBatchSize = Math.min(actualBatchSize * 2, batchSize);
+                }
+            } catch (TddlRuntimeException e) {
+                boolean retry = (e.getErrorCode() == ErrorCode.ERR_X_PROTOCOL_BAD_PACKET.getCode() ||
+                    (e.getErrorCode() == 1153 && e.getMessage().toLowerCase().contains("max_allowed_packet")) ||
+                    (e.getSQLState() != null && e.getSQLState().equalsIgnoreCase("S1000") && e.getMessage()
+                        .toLowerCase().contains("max_allowed_packet"))) && actualBatchSize > 1;
+                if (retry) {
+                    actualBatchSize = Math.max(actualBatchSize / 8, 1);
+                } else {
+                    throw e;
+                }
+            }
+
+            // yijin:disable sliding window of split, because we don't need this
+//            checkAndSplitBackfillObject(
+//                dbIndex, phyTable, successRowCount, ec, rangeBackfillStartTime, lastBatch, backfillObjects);
+        } while (!finished);
+
+//        DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set(0);
+        reporter.addBackfillCount(successRowCount);
+
+        SQLRecorderLogger.ddlLogger.warn(
+            MessageFormat.format("[{0}] [{1}][{2}] pk range last backfill success count and rows: [{3}], ({4})",
+                ec.getTraceId(),
+                String.valueOf(ec.getTaskId()),
+                String.valueOf(ec.getBackfillId()),
+                successRowCount,
+                GsiUtils.rowToString(lastBatch.isEmpty() ? null : lastBatch.get(lastBatch.size() - 1))));
+    }
+
+    protected List> extract(String dbIndex, String phyTableName,
+                                                           PhyTableOperation logicalSelectSql,
+                                                           Pair ecAndConn,
+                                                           BatchConsumer next,
+                                                           List lowerBound,
+                                                           List upperBound) throws SQLException {
+
+        Pair extractEcAndConn = (Pair) ecAndConn;
+        ExecutionContext extractEc = extractEcAndConn.getKey();
+        Connection connection = extractEcAndConn.getValue();
+        // Transform
+        final List> result;
+
+        ResultSet resultSet = null;
+        String hint = String.format(" /* trace_id(%s) */ ", extractEc.getTraceId());
+        // TODO(yijin): support hint passed to logical sql.
+//        ParamManager pm = extractEc.getParamManager();
+//        String mergeUnionSize = ConnectionProperties.MERGE_UNION_SIZE;
+//        String hint =
+//            String.format("/*+TDDL:cmd_extra(%s=%d)*/", mergeUnionSize, pm.getInt(ConnectionParams.MERGE_UNION_SIZE));
+        // Extract
+
+        try (PreparedStatement statement = connection.prepareStatement(hint + logicalSelectSql.getNativeSql())) {
+            ParameterMethod.setParameters(statement, logicalSelectSql.getParam());
+            resultSet = statement.executeQuery();
+
+            result =
+                com.alibaba.polardbx.executor.gsi.utils.Transformer.buildBatchParam(targetTableMeta.getAllColumns(),
+                    resultSet, useBinary,
+                    notConvertColumns);
+            SQLRecorderLogger.ddlLogger.warn(
+                MessageFormat.format(
+                    "[{0}] [{1}][{2}] select for update get row count [{3}], pk range is [{4}], [{5}], param is {6}",
+                    extractEc.getTraceId(),
+                    extractEc.getTaskId().toString(),
+                    extractEc.getBackfillId().toString(),
+                    result.size(),
+                    result.isEmpty() ? "" : GsiUtils.rowToString(result.get(0)),
+                    result.isEmpty() ? "" : GsiUtils.rowToString(result.get(result.size() - 1)),
+                    GsiUtils.rowToString(logicalSelectSql.getParam())));
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        } finally {
+            // TODO: finally end.
+        }
+        if (resultSet != null) {
+            resultSet.close();
+        }
+
+        FailPoint.injectRandomExceptionFromHint(FP_RANDOM_BACKFILL_EXCEPTION, extractEc);
+
+        // Load
+        next.consume(result, Pair.of(extractEc, Pair.of(dbIndex, phyTableName)));
+
+        return result;
+    }
+
+    /**
+     * Build plan for physical select.
+     *
+     * @param params pk column value of last batch
+     * @return built plan
+     */
+    public static PhyTableOperation buildLogicalSelectWithParam(String tableSchema, String logicalTableName,
+                                                                long batchSize,
+                                                                List params, boolean withLowerBound,
+                                                                boolean withUpperBound,
+                                                                PhyTableOperation planSelectWithoutMinAndMax,
+                                                                PhyTableOperation planSelectWithMax,
+                                                                PhyTableOperation planSelectWithMin,
+                                                                PhyTableOperation planSelectWithMinAndMax) {
+        Map planParams = new HashMap<>();
+        // Physical table is 1st parameter
+//        planParams.put(1, PlannerUtils.buildParameterContextForTableName(logicalTableName, 1));
+
+        int nextParamIndex = 1;
+
+        // Parameters for where(DNF)
+        int pkNumber = 0;
+        PhyTableOperation targetPhyOp = planSelectWithoutMinAndMax;
+        if (withLowerBound || withUpperBound) {
+            pkNumber = params.size() / ((withLowerBound ? 1 : 0) + (withUpperBound ? 1 : 0));
+            targetPhyOp =
+                !withLowerBound ? planSelectWithMax : (withUpperBound ? planSelectWithMinAndMax : planSelectWithMin);
+        }
+        if (withLowerBound) {
+            for (int i = 0; i < pkNumber; ++i) {
+                for (int j = 0; j <= i; ++j) {
+                    planParams.put(nextParamIndex,
+                        new ParameterContext(params.get(j).getParameterMethod(),
+                            new Object[] {nextParamIndex, params.get(j).getArgs()[1]}));
+                    nextParamIndex++;
+                }
+            }
+        }
+        if (withUpperBound) {
+            final int base = withLowerBound ? pkNumber : 0;
+            for (int i = 0; i < pkNumber; ++i) {
+                for (int j = 0; j <= i; ++j) {
+                    planParams.put(nextParamIndex,
+                        new ParameterContext(params.get(base + j).getParameterMethod(),
+                            new Object[] {nextParamIndex, params.get(base + j).getArgs()[1]}));
+                    nextParamIndex++;
+                }
+            }
+        }
+
+        // Parameters for limit
+        planParams.put(nextParamIndex,
+            new ParameterContext(ParameterMethod.setObject1, new Object[] {nextParamIndex, batchSize}));
+
+        PhyTableOpBuildParams buildParams = new PhyTableOpBuildParams();
+        buildParams.setGroupName(tableSchema);
+        buildParams.setPhyTables(ImmutableList.of(ImmutableList.of(logicalTableName)));
+        buildParams.setDynamicParams(planParams);
+//        select * from t1 where a < 1 and a > 0 order by a for update;
+
+        PhyTableOperation phyTableOperation =
+            PhyTableOperationFactory.getInstance().buildPhyTableOperationByPhyOp(targetPhyOp, buildParams);
+        return phyTableOperation;
+    }
+}
\ No newline at end of file
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Loader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Loader.java
index e853499bb..ea1a42955 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Loader.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Loader.java
@@ -130,6 +130,17 @@ public int fillIntoIndexWithReturning(List> batch
                 // Batch insert
                 result = applyBatchWithReturning(batchParams, insertEc.copy(), baseEcAndIndexPair.getValue().getKey(),
                     baseEcAndIndexPair.getValue().getValue());
+                SQLRecorderLogger.ddlLogger.warn(
+                    MessageFormat.format(
+                        "[{0}] [{1}][{2}] loader with returning insert {3} rows, {4} affected, the range is [{5}], [{6}]",
+                        insertEc.getTraceId(),
+                        insertEc.getTaskId().toString(),
+                        insertEc.getBackfillId().toString(),
+                        batchParams.size(),
+                        result,
+                        batchParams.isEmpty() ? "" : GsiUtils.rowToString(batchParams.get(0)),
+                        batchParams.isEmpty() ? "" :
+                            GsiUtils.rowToString(batchParams.get(batchParams.size() - 1))));
 
                 // Batch insert success, check lock exists
                 return checkBeforeCommit(checker, insertEc, result);
@@ -137,8 +148,10 @@ public int fillIntoIndexWithReturning(List> batch
                 // Batch insert failed
                 SQLRecorderLogger.ddlLogger
                     .warn(MessageFormat.format(
-                        "[{0}] Batch insert(returning) failed first row: {1} cause: {2}, phyTableName: {3}",
+                        "[{0}][{1}][{2}] Batch insert(returning) failed first row: {3} cause: {4}, phyTableName: {5}",
                         baseEcAndIndexPair.getKey().getTraceId(),
+                        baseEcAndIndexPair.getKey().getTaskId().toString(),
+                        baseEcAndIndexPair.getKey().getBackfillId().toString(),
                         GsiUtils.rowToString(batchParams.get(0)),
                         e.getMessage(), baseEcAndIndexPair.getValue().getValue()));
 
@@ -163,14 +176,27 @@ public int fillIntoIndexWithInsert(List> batchPar
                     result = applyBatch(batchParams, insertEc.copy(), baseEcAndIndexPair.getValue().getKey(),
                         baseEcAndIndexPair.getValue().getValue());
 
+                    SQLRecorderLogger.ddlLogger.warn(
+                        MessageFormat.format("[{0}] [{1}][{2}] loader insert {3} rows, the range is [{4}], [{5}]",
+                            insertEc.getTraceId(),
+                            insertEc.getTaskId().toString(),
+                            insertEc.getBackfillId().toString(),
+                            batchParams.size(),
+                            batchParams.isEmpty() ? "" : GsiUtils.rowToString(batchParams.get(0)),
+                            batchParams.isEmpty() ? "" :
+                                GsiUtils.rowToString(batchParams.get(batchParams.size() - 1))));
+
                     // Batch insert success, check lock exists
                     return checkBeforeCommit(checker, insertEc, result);
                 } catch (TddlNestableRuntimeException e) {
                     // Batch insert failed
+                    ExecutionContext ec = baseEcAndIndexPair.getKey();
                     SQLRecorderLogger.ddlLogger
                         .warn(MessageFormat.format(
-                            "[{0}] Batch insert failed first row: {1} cause: {2}, phyTableName: {3}",
-                            baseEcAndIndexPair.getKey().getTraceId(),
+                            "[{0}] [{1}] [{2}] Batch insert failed first row: {3} cause: {4}, phyTableName: {5}",
+                            ec.getTraceId(),
+                            ec.getTaskId().toString(),
+                            ec.getBackfillId().toString(),
                             GsiUtils.rowToString(batchParams.get(0)),
                             e.getMessage(), baseEcAndIndexPair.getValue().getValue()));
 
@@ -257,6 +283,7 @@ private void checkDuplicate(Map baseParam, ExecutionC
             exList.add(new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_BACKFILL_DUPLICATE_ENTRY,
                 String.join("-", pkParams),
                 "PRIMARY"));
+            // TODO(yijin_MPP) add error message here into test case.
         } finally {
             if (null != checkerCursor) {
                 checkerCursor.close(exList);
@@ -271,12 +298,19 @@ private void checkDuplicate(Map baseParam, ExecutionC
     private static Integer checkBeforeCommit(Supplier checker, ExecutionContext insertEc, int result) {
         if (checker.get()) {
             insertEc.getTransaction().commit();
+            SQLRecorderLogger.ddlLogger.warn(
+                String.format(
+                    "[%s] [%s] [%s] Loader success to commit in backfill extractor.",
+                    insertEc.getTraceId(), insertEc.getTaskId(), insertEc.getBackfillId()));
             return result;
         } else {
             insertEc.getTransaction().rollback();
+            String errInfo = String.format(
+                "[%s] [%s] [%s] Loader check error. Fail to commit in backfill extractor. Please retry or recover DDL later.",
+                insertEc.getTraceId(), insertEc.getTaskId(), insertEc.getBackfillId());
+            SQLRecorderLogger.ddlLogger.warn(errInfo);
             // This means extractor's connection fail. Throw a special error.
-            throw new TddlNestableRuntimeException(
-                "Loader check error. Fail to commit in backfill extractor. Please retry or recover DDL later.");
+            throw new TddlNestableRuntimeException(errInfo);
         }
     }
 
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Reporter.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Reporter.java
index 41ec122e8..7b4006cee 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Reporter.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/backfill/Reporter.java
@@ -87,6 +87,13 @@ public void splitBackfillRange(ExecutionContext ec, List backfillObjects,
+                                   long successRowCount, List lastPk,
+                                   List beforeLastPk, boolean finished,
+                                   Map primaryKeysIdMap) {
+
+    }
+
     public void updatePositionMark(ExecutionContext ec, List backfillObjects,
                                    long successRowCount, List lastPk,
                                    List beforeLastPk, boolean finished,
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/BalanceOptions.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/BalanceOptions.java
index f8dd106d1..5e2319687 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/BalanceOptions.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/BalanceOptions.java
@@ -55,7 +55,7 @@ public class BalanceOptions {
     /**
      * Whether generate subjob unit by sizes. (MB)
      */
-    public Long maxTaskUnitSize = 1024 * 32L;
+    public Long maxTaskUnitSize = 1024 * 64L;
 
     /**
      * Whether shuffle data distribution randomly;
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/action/ActionMovePartition.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/action/ActionMovePartition.java
index 46bb97c02..160dd9410 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/action/ActionMovePartition.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/action/ActionMovePartition.java
@@ -31,16 +31,21 @@
 import com.alibaba.polardbx.executor.ddl.job.task.CostEstimableDdlTask;
 import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob;
 import com.alibaba.polardbx.gms.topology.DbTopologyManager;
+import com.alibaba.polardbx.gms.topology.StorageInfoRecord;
+import com.alibaba.polardbx.gms.util.InstIdUtil;
 import com.alibaba.polardbx.optimizer.config.table.ScaleOutPlanUtil;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.google.common.collect.Sets;
 import lombok.Getter;
 import lombok.Setter;
+import org.apache.hadoop.util.StringUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -60,6 +65,9 @@ public class ActionMovePartition implements BalanceAction, Comparable moves) {
+        Map targetStorageMap =
+            DbTopologyManager.getGroupNameToStorageInstIdMap(schema);
+        List subSqls = new ArrayList<>();
+        String sql = String.format(ALTER_TABLEGROUP_PARTITIONS_SUBSQL, TStringUtil.backQuote(tableGroupName));
+        if (moves.get(0).isSubpartition) {
+            sql = String.format(ALTER_TABLEGROUP_SUBPARTITIONS_SUBSQL, TStringUtil.backQuote(tableGroupName));
+        }
+        for (ActionMovePartition move : moves) {
+            if (!targetStorageMap.containsKey(move.toGroup)) {
+                throw new TddlRuntimeException(ErrorCode.ERR_REBALANCE,
+                    "target storage not found: group=" + move.toGroup);
+            }
+            String targetStorage = targetStorageMap.get(move.toGroup);
+            String partitionList =
+                move.partitionNames.stream().map(TStringUtil::backQuote).collect(Collectors.joining(","));
+            String subSql;
+            subSql = String.format(MOVE_PARTITIONS_SUBSQL,
+                partitionList,
+                TStringUtil.quoteString(targetStorage));
+            subSqls.add(subSql);
+        }
+        if (subSqls.size() > 0) {
+            sql = sql + StringUtils.join(", ", subSqls) + ";";
+        } else {
+            throw new TddlRuntimeException(ErrorCode.ERR_REBALANCE,
+                "move action not found in ActionMovePartitions");
+        }
+        return sql;
+    }
+
+    public static ExecutableDdlJob movesToDdlJob(String tableGroupName, List moves,
+                                                 ExecutionContext ec) {
+        long totalRows = 0L;
+        long totalSize = 0L;
+        if (moves.size() <= 0) {
+            throw new TddlRuntimeException(ErrorCode.ERR_REBALANCE,
+                "move action not found in ActionMovePartitions");
+        }
+        ActionMovePartition move = moves.get(0);
+        String schema = move.schema;
+        String sql = getMovesSql(schema, tableGroupName, moves);
+        BalanceStats stats = move.stats;
+        List partitionNames = new ArrayList<>();
+        moves.stream().forEach(o -> partitionNames.addAll(o.partitionNames));
+        try {
+            List partitionStatList =
+                stats.filterPartitionStat(tableGroupName, Sets.newHashSet(partitionNames));
+            for (PartitionStat partitionStat : partitionStatList) {
+                totalRows += partitionStat.getPartitionRows();
+                totalSize += partitionStat.getPartitionDiskSize();
+            }
+        } catch (Exception e) {
+            EventLogger.log(EventType.DDL_WARN, "calculate rebalance rows error. " + e.getMessage());
+        }
+        return ActionUtils.convertToDelegatorJob(move.schema, sql,
+            CostEstimableDdlTask.createCostInfo(totalRows, totalSize, (long) move.getLogicalTableCount()));
+    }
+
     @Override
     public ExecutableDdlJob toDdlJob(ExecutionContext ec) {
         String sql = getSql();
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/action/ActionMovePartitions.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/action/ActionMovePartitions.java
index 78ba57e93..7177b1d4b 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/action/ActionMovePartitions.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/action/ActionMovePartitions.java
@@ -132,9 +132,15 @@ public ExecutableDdlJob toDdlJob(ExecutionContext ec) {
 
         for (Map.Entry> entry : actions.entrySet()) {
             ExecutableDdlJob subJob = new ExecutableDdlJob();
-            for (ActionMovePartition move : entry.getValue()) {
-                ExecutableDdlJob ddlTask = move.toDdlJob(ec);
+            if (ec.getParamManager().getBoolean(ConnectionParams.SCALE_OUT_GENERATE_MULTIPLE_TO_GROUP_JOB)) {
+                ExecutableDdlJob ddlTask = ActionMovePartition.movesToDdlJob(entry.getKey(), entry.getValue(), ec);
                 subJob.appendJob2(ddlTask);
+            } else {
+                for (ActionMovePartition move : entry.getValue()) {
+                    ExecutableDdlJob ddlTask = move.toDdlJob(ec);
+                    subJob.appendJob2(ddlTask);
+                }
+
             }
             Set relatedTableGroup;
             if (!tableGroupTaskInfo.containsKey(entry.getKey())) {
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/policy/PolicyDrainNode.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/policy/PolicyDrainNode.java
index 95f4b4806..0507fd747 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/policy/PolicyDrainNode.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/policy/PolicyDrainNode.java
@@ -699,7 +699,7 @@ public List applyToTenantPartitionDb(ExecutionContext ec, Balance
         List tableGroupNames = validTgSet.stream().collect(Collectors.toList());
         tableGroupNames.sort(Comparator.comparingLong(key -> tgDataSize.get(key)).reversed());
         DataDistInfo dataDistInfo = DataDistInfo.fromSchemaAndInstMap(schemaName, storageInstMap, groupDetailMap);
-        List moves = new ArrayList<>();
+        List moves = new ArrayList<>();
         // 4.3 Compute PgMoveAction inside tg.
         for (int k = 0; k < tableGroupNames.size(); k++) {
 
@@ -752,7 +752,7 @@ public List applyToTenantPartitionDb(ExecutionContext ec, Balance
 
                 for (int i = 0; i < N; i++) {
                     if (targetPlace[i] != originalPlace[i]) {
-                        moves.add(new PolicyDrainNode.MoveInfo(toRebalancePgMap.get(i).getFirstPartition(),
+                        moves.add(new PolicyPartitionBalance.MoveInfo(toRebalancePgMap.get(i).getFirstPartition(),
                             toRebalancePgMap.get(i).getTgName(), groupDetailMap.get(targetPlace[i]),
                             toRebalancePgMap.get(i).getDataRows(), toRebalancePgMap.get(i).getTotalDiskSize()));
                     }
@@ -1059,7 +1059,7 @@ public List applyToPartitionDbDrainStoragePool(ExecutionContext e
         List tableGroupNames = tgDataSize.keySet().stream().collect(Collectors.toList());
         tableGroupNames.sort(Comparator.comparingLong(key -> tgDataSize.get(key)).reversed());
         DataDistInfo dataDistInfo = DataDistInfo.fromSchemaAndInstMap(schemaName, storageInstMap, groupDetailMap);
-        List moves = new ArrayList<>();
+        List moves = new ArrayList<>();
         String dbLocality = LocalityManager.getInstance().getLocalityOfDb(schemaName).getLocality();
         // 3.2 compute move actions here.
         for (int k = 0; k < tableGroupNames.size(); k++) {
@@ -1153,7 +1153,7 @@ public List applyToPartitionDbDrainStoragePool(ExecutionContext e
 
                     for (int i = 0; i < N; i++) {
                         if (targetPlace[i] != originalPlace[i]) {
-                            moves.add(new PolicyDrainNode.MoveInfo(toRebalancePgMap.get(i).getFirstPartition(),
+                            moves.add(new PolicyPartitionBalance.MoveInfo(toRebalancePgMap.get(i).getFirstPartition(),
                                 toRebalancePgMap.get(i).getTgName(), groupDetailMap.get(targetPlace[i]),
                                 toRebalancePgMap.get(i).getDataRows(), toRebalancePgMap.get(i).getTotalDiskSize()));
                         }
@@ -1166,7 +1166,7 @@ public List applyToPartitionDbDrainStoragePool(ExecutionContext e
             // sort by dataSize desc.
 //        int toIndex = Math.min(options.maxActions * 20, moves.size());
 //        moves = moves.subList(0, toIndex);
-//        Map> movesGroupByTg = moves.stream().collect(
+//        Map> movesGroupByTg = moves.stream().collect(
 //            Collectors.groupingBy(o -> o.tgName, Collectors.mapping(o -> o, Collectors.toList()))
 //        );
         }
@@ -1433,7 +1433,7 @@ public List applyToPartitionDbNew(ExecutionContext ec, BalanceOpt
         List tableGroupNames = validTgSet.stream().collect(Collectors.toList());
         tableGroupNames.sort(Comparator.comparingLong(key -> tgDataSize.get(key)).reversed());
         DataDistInfo dataDistInfo = DataDistInfo.fromSchemaAndInstMap(schemaName, storageInstMap, groupDetailMap);
-        List moves = new ArrayList<>();
+        List moves = new ArrayList<>();
         for (int k = 0; k < tableGroupNames.size(); k++) {
 
             String tgName = tableGroupNames.get(k);
@@ -1499,7 +1499,7 @@ public List applyToPartitionDbNew(ExecutionContext ec, BalanceOpt
 
                     for (int i = 0; i < N; i++) {
                         if (targetPlace[i] != originalPlace[i]) {
-                            moves.add(new PolicyDrainNode.MoveInfo(toRebalancePgMap.get(i).getFirstPartition(),
+                            moves.add(new PolicyPartitionBalance.MoveInfo(toRebalancePgMap.get(i).getFirstPartition(),
                                 toRebalancePgMap.get(i).getTgName(), groupDetailMap.get(targetPlace[i]),
                                 toRebalancePgMap.get(i).getDataRows(), toRebalancePgMap.get(i).getTotalDiskSize()));
                         }
@@ -1512,7 +1512,7 @@ public List applyToPartitionDbNew(ExecutionContext ec, BalanceOpt
             // sort by dataSize desc.
 //        int toIndex = Math.min(options.maxActions * 20, moves.size());
 //        moves = moves.subList(0, toIndex);
-//        Map> movesGroupByTg = moves.stream().collect(
+//        Map> movesGroupByTg = moves.stream().collect(
 //            Collectors.groupingBy(o -> o.tgName, Collectors.mapping(o -> o, Collectors.toList()))
 //        );
         }
@@ -1808,7 +1808,7 @@ public List applyToPartitionDb(ExecutionContext ec,
             List tableGroupNames = validTgSet.stream().collect(Collectors.toList());
             tableGroupNames.sort(Comparator.comparingLong(key -> tgDataSize.get(key)).reversed());
             DataDistInfo dataDistInfo = DataDistInfo.fromSchemaAndInstMap(schemaName, storageInstMap, groupDetailMap);
-            List moves = new ArrayList<>();
+            List moves = new ArrayList<>();
             for (int k = 0; k < tableGroupNames.size(); k++) {
 
                 String tgName = tableGroupNames.get(k);
@@ -1865,7 +1865,7 @@ public List applyToPartitionDb(ExecutionContext ec,
 
                     for (int i = 0; i < N; i++) {
                         if (targetPlace[i] != originalPlace[i]) {
-                            moves.add(new PolicyDrainNode.MoveInfo(toRebalancePgMap.get(i).getFirstPartition(),
+                            moves.add(new PolicyPartitionBalance.MoveInfo(toRebalancePgMap.get(i).getFirstPartition(),
                                 toRebalancePgMap.get(i).getTgName(),
                                 groupDetailMap.get(targetPlace[i]),
                                 toRebalancePgMap.get(i).getDataRows(),
@@ -1882,70 +1882,20 @@ public List applyToPartitionDb(ExecutionContext ec,
             moves.sort(Comparator.comparingLong(o -> -o.dataSize));
 //        int toIndex = Math.min(options.maxActions * 20, moves.size());
 //        moves = moves.subList(0, toIndex);
-//        Map> movesGroupByTg = moves.stream().collect(
-//            Collectors.groupingBy(o -> o.tgName, Collectors.mapping(o -> o, Collectors.toList()))
-//        );
+            Map> movesGroupByTg = moves.stream().collect(
+                Collectors.groupingBy(o -> o.tgName, Collectors.mapping(o -> o, Collectors.toList()))
+            );
             long maxTaskUnitSize = ec.getParamManager().getLong(REBALANCE_MAX_UNIT_SIZE);
             if (maxTaskUnitSize < 1024) {
                 maxTaskUnitSize = options.maxTaskUnitSize;
             }
             List moveDataActions = new ArrayList<>();
-            for (int i = 0; i < moves.size(); ) {
-                Long sumMoveSizes = 0L;
-                int j = i;
-                int nextI;
-                for (; j < moves.size() && sumMoveSizes <= maxTaskUnitSize * 1024 * 1024; j++) {
-                    sumMoveSizes += moves.get(j).dataSize;
-                }
-                nextI = j;
-                Map> movePartitionActions =
-                    new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-//            Long finalSumMoveRows = sumMoveSizes;
-                GeneralUtil.emptyIfNull(moves.subList(i, nextI)).stream().collect(
-                    Collectors.groupingBy(o -> o.targetDn,
-                        Collectors.mapping(o -> o.partitionStat, Collectors.toList()))
-                ).forEach((toGroup, partitions) -> {
-                    for (ActionMovePartition act : ActionMovePartition.createMoveToGroups(schemaName, partitions,
-                        toGroup, stats)) {
-//                    if (moveDataActions.size() >= options.maxActions) {
-//                        break;
-//                    }
-                        movePartitionActions.computeIfAbsent(act.getTableGroupName(), o -> new ArrayList<>())
-                            .add(act);
-                    }
-                });
-                if (!movePartitionActions.isEmpty()) {
-                    moveDataActions.add(new ActionMovePartitions(schemaName, movePartitionActions));
-                }
-                i = nextI;
+            for (String tgName : movesGroupByTg.keySet()) {
+                List movesGroup = movesGroupByTg.get(tgName);
+                List movePartitionsList =
+                    PolicyPartitionBalance.shuffleToGroup(schemaName, movesGroup, maxTaskUnitSize, stats);
+                moveDataActions.addAll(movePartitionsList);
             }
-
-//        for (String tgName : movesGroupByTg.keySet()) {
-//            List movesOfTg = movesGroupByTg.get(tgName);
-//            movesOfTg.sort(Comparator.comparingLong(o -> -o.dataSize));
-//            for (int i = 0; i < movesOfTg.size(); ) {
-//                Long sumMoveRows = 0L;
-//                int j = i;
-//                int nextI;
-//                for (; j < movesOfTg.size() && sumMoveRows <= options.maxTaskUnitRows; j++) {
-//                    sumMoveRows += movesOfTg.get(j).tableRows;
-//                }
-//                nextI = j;
-//                GeneralUtil.emptyIfNull(movesOfTg.subList(i, nextI)).stream().collect(
-//                    Collectors.groupingBy(o -> o.targetDn,
-//                        Collectors.mapping(o -> o.partitionStat, Collectors.toList()))
-//                ).forEach((toGroup, partitions) -> {
-//                    for (ActionMovePartition act : ActionMovePartition.createMoveToGroups(schema, partitions,
-//                        toGroup, stats)) {
-//                        if (actions.size() >= options.maxActions) {
-//                            break;
-//                        }
-//                        actions.add(act);
-//                    }
-//                });
-//                i = nextI;
-//            }
-//        }
             String distLogInfo =
                 String.format("[schema %s] estimated data distribution: %s", schemaName,
                     JSON.toJSONString(dataDistInfo));
@@ -2302,22 +2252,4 @@ boolean moveInGroup(String schema, String groupName, long dataSize) {
         }
     }
 
-    public class MoveInfo {
-        PartitionStat partitionStat;
-        String targetDn;
-
-        String tgName;
-        Long tableRows;
-        Long dataSize;
-
-        public MoveInfo(PartitionStat partitionStat, String tgName, String targetDn, Long tableRows,
-                        Long dataSize) {
-            this.partitionStat = partitionStat;
-            this.tgName = tgName;
-            this.targetDn = targetDn;
-            this.tableRows = tableRows;
-            this.dataSize = dataSize;
-        }
-    }
-
 }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/policy/PolicyPartitionBalance.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/policy/PolicyPartitionBalance.java
index 077162822..7cead550a 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/policy/PolicyPartitionBalance.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/policy/PolicyPartitionBalance.java
@@ -75,6 +75,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.PriorityQueue;
+import java.util.Queue;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.stream.Collectors;
@@ -293,7 +295,12 @@ public List applyToTable(ExecutionContext ec,
             "[schema %s, table %s] start to solve move partition problem: M=%d, N=%d, originalPlace=%s, partitionSize=%s",
             schemaName, tableName, M, N, Arrays.toString(originalPlace), Arrays.toString(partitionSize));
         EventLogger.log(EventType.REBALANCE_INFO, logInfo);
-        Solution solution = MixedModel.solveMovePartition(M, N, originalPlace, partitionSize, solveLevel);
+        Solution solution;
+        if (options.shuffleDataDistribution != 0) {
+            solution = MixedModel.solveShufflePartition(M, N, originalPlace, partitionSize);
+        } else {
+            solution = MixedModel.solveMovePartition(M, N, originalPlace, partitionSize, solveLevel);
+        }
         if (solution.withValidSolve) {
             Date endTime = new Date();
             Long costMillis = endTime.getTime() - startTime.getTime();
@@ -784,43 +791,52 @@ public List applyToPartitionDb(ExecutionContext ec,
             }
         }
 
-        moves.sort(Comparator.comparingLong(o -> -o.dataSize));
+        // TODO
+        // 1. we need to shuffle toGroup most possibly.
+        // 2. for subjob on tablegroup, we need to allocate resource for tablegroup.
+//        moves.sort(Comparator.comparingLong(o -> -o.dataSize));
 //        int toIndex = Math.min(options.maxActions * 8, moves.size());
 //        moves = moves.subList(0, toIndex);
-//        Map> movesGroupByTg = moves.stream().collect(
-//            Collectors.groupingBy(o -> o.tgName, Collectors.mapping(o -> o, Collectors.toList()))
-//        );
+        Map> movesGroupByTg = moves.stream().collect(
+            Collectors.groupingBy(o -> o.tgName, Collectors.mapping(o -> o, Collectors.toList()))
+        );
         long maxTaskUnitSize = ec.getParamManager().getLong(REBALANCE_MAX_UNIT_SIZE);
         if (maxTaskUnitSize < 1024) {
             maxTaskUnitSize = options.maxTaskUnitSize;
         }
-        for (int i = 0; i < moves.size(); ) {
-            Long sumMoveSize = 0L;
-            int j = i;
-            int nextI;
-            for (; j < moves.size() && sumMoveSize <= maxTaskUnitSize * 1024 * 1024; j++) {
-                sumMoveSize += moves.get(j).dataSize;
-            }
-            nextI = j;
-            Map> movePartitionActions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-//            Long finalSumMoveRows = sumMoveSize;
-            GeneralUtil.emptyIfNull(moves.subList(i, nextI)).stream().collect(
-                Collectors.groupingBy(o -> o.targetDn,
-                    Collectors.mapping(o -> o.partitionStat, Collectors.toList()))
-            ).forEach((toGroup, partitions) -> {
-                for (ActionMovePartition act : ActionMovePartition.createMoveToGroups(schemaName, partitions,
-                    toGroup, stats)) {
-//                    if (actions.size() >= options.maxActions) {
-//                        break;
-//                    }
-                    movePartitionActions.computeIfAbsent(act.getTableGroupName(), o -> new ArrayList<>()).add(act);
-                }
-            });
-            if (!movePartitionActions.isEmpty()) {
-                actions.add(new ActionMovePartitions(schemaName, movePartitionActions));
-            }
-            i = nextI;
-        }
+        for (String tgName : movesGroupByTg.keySet()) {
+            List movesGroup = movesGroupByTg.get(tgName);
+            List movePartitionsList =
+                PolicyPartitionBalance.shuffleToGroup(schemaName, movesGroup, maxTaskUnitSize, stats);
+            actions.addAll(movePartitionsList);
+        }
+//        for (int i = 0; i < moves.size(); ) {
+//            Long sumMoveSize = 0L;
+//            int j = i;
+//            int nextI;
+//            for (; j < moves.size() && sumMoveSize <= maxTaskUnitSize * 1024 * 1024; j++) {
+//                sumMoveSize += moves.get(j).dataSize;
+//            }
+//            nextI = j;
+//            Map> movePartitionActions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+////            Long finalSumMoveRows = sumMoveSize;
+//            GeneralUtil.emptyIfNull(moves.subList(i, nextI)).stream().collect(
+//                Collectors.groupingBy(o -> o.targetDn,
+//                    Collectors.mapping(o -> o.partitionStat, Collectors.toList()))
+//            ).forEach((toGroup, partitions) -> {
+//                for (ActionMovePartition act : ActionMovePartition.createMoveToGroups(schemaName, partitions,
+//                    toGroup, stats)) {
+////                    if (actions.size() >= options.maxActions) {
+////                        break;
+////                    }
+//                    movePartitionActions.computeIfAbsent(act.getTableGroupName(), o -> new ArrayList<>()).add(act);
+//                }
+//            });
+//            if (!movePartitionActions.isEmpty()) {
+//                actions.add(new ActionMovePartitions(schemaName, movePartitionActions));
+//            }
+//            i = nextI;
+//        }
 
 //        for (String tgName : movesGroupByTg.keySet()) {
 //            List movesOfTg = movesGroupByTg.get(tgName);
@@ -866,7 +882,7 @@ public void solveBenchmarkExample(int times) {
         }
     }
 
-    public class MoveInfo {
+    public static class MoveInfo {
         PartitionStat partitionStat;
         String targetDn;
 
@@ -891,4 +907,46 @@ protected boolean isStorageReady(String storageInst) {
             .orElse(false);
     }
 
-}
+    public static List shuffleToGroup(String schemaName, List moves,
+                                                            long maxTaskUnitSize,
+                                                            BalanceStats stats) {
+        List movePartitionsList = new ArrayList<>();
+        Map> moveInfoMap = new HashMap<>();
+        for (MoveInfo moveInfo : moves) {
+            if (!moveInfoMap.containsKey(moveInfo.targetDn)) {
+                moveInfoMap.put(moveInfo.targetDn,
+                    new PriorityQueue((o1, o2) -> Long.compare(o1.dataSize, o2.dataSize)));
+            }
+            moveInfoMap.get(moveInfo.targetDn).add(moveInfo);
+        }
+        List dns = new ArrayList<>(moveInfoMap.keySet());
+        long splitTaskUnitSize = maxTaskUnitSize * 1024 * 1024 / dns.size();
+        int i = 0;
+        while (i < moves.size()) {
+            List moveInfoList = new ArrayList<>();
+            for (String dn : dns) {
+                long sumMoveSize = 0L;
+                Queue moveInfoQueue = moveInfoMap.get(dn);
+                while (!moveInfoQueue.isEmpty() && sumMoveSize < splitTaskUnitSize) {
+                    MoveInfo moveInfo = moveInfoQueue.poll();
+                    sumMoveSize += moveInfo.dataSize;
+                    moveInfoList.add(moveInfo);
+                    i++;
+                }
+            }
+            Map> movePartitionActions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+            GeneralUtil.emptyIfNull(moveInfoList).stream().collect(
+                Collectors.groupingBy(o -> o.targetDn,
+                    Collectors.mapping(o -> o.partitionStat, Collectors.toList()))
+            ).forEach((toGroup, partitions) -> {
+                for (ActionMovePartition act : ActionMovePartition.createMoveToGroups(schemaName, partitions,
+                    toGroup, stats)) {
+                    movePartitionActions.computeIfAbsent(act.getTableGroupName(), o -> new ArrayList<>()).add(act);
+                }
+            });
+            movePartitionsList.add(new ActionMovePartitions(schemaName, movePartitionActions));
+        }
+        return movePartitionsList;
+    }
+
+}
\ No newline at end of file
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/splitpartition/SplitPartitionStats.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/splitpartition/SplitPartitionStats.java
index def8cb45e..9b7363194 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/splitpartition/SplitPartitionStats.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/splitpartition/SplitPartitionStats.java
@@ -118,7 +118,7 @@ private String constructScanPartitionSamplingSql(String physicalTableName, List<
         float cmdExtraSamplePercentage = sampleRate * 100;
         String hint = "";
         if (withHint) {
-            hint = String.format("/*+sample_percentage(%f)*/ ", cmdExtraSamplePercentage);
+            hint = String.format("/*+sample_percentage(%s)*/ ", GeneralUtil.formatSampleRate(cmdExtraSamplePercentage));
         }
         List columnMetaNames =
             columnMetaList.stream().map(o -> "`" + o.getName() + "`").collect(Collectors.toList());
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/stats/StatsUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/stats/StatsUtils.java
index 40dc0cf29..878a54eda 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/stats/StatsUtils.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/balancer/stats/StatsUtils.java
@@ -1095,21 +1095,24 @@ public static Map>> queryTableGroupStatI
                     Object physicalIndexLength = row.get(6);
                     phyTbStatInfo.put("physicalIndexLength", physicalIndexLength);
 
-                    if (row.size() > 7) {
+                    Object physicalDataFree = row.get(7);
+                    phyTbStatInfo.put("physicalDataFree", physicalDataFree);
+
+                    if (row.size() > 8) {
                         // ROWS_READ
-                        Object physicalRowsRead = row.get(7);
+                        Object physicalRowsRead = row.get(8);
                         phyTbStatInfo.put("physicalRowsRead", physicalRowsRead);
 
                         // ROWS_INSERTED
-                        Object physicalRowsInserted = row.get(8);
+                        Object physicalRowsInserted = row.get(9);
                         phyTbStatInfo.put("physicalRowsInserted", physicalRowsInserted);
 
                         // ROWS_UPDATED
-                        Object physicalRowsUpdated = row.get(9);
+                        Object physicalRowsUpdated = row.get(10);
                         phyTbStatInfo.put("physicalRowsUpdated", physicalRowsUpdated);
 
                         // ROWS_DELETED
-                        Object physicalRowsDeleted = row.get(10);
+                        Object physicalRowsDeleted = row.get(11);
                         phyTbStatInfo.put("physicalRowsDeleted", physicalRowsDeleted);
                     }
 
@@ -1339,6 +1342,7 @@ private static String generateQueryPhyTablesStatsSQL(String logicalSchema, Set create(List types, ExecutionContext
             } else if (clazz == Byte.class) {
                 blockEncodingList.add(new ByteBlockEncoding());
             } else if (clazz == Double.class) {
-                blockEncodingList.add(new DoubleBlockEncoding());
+                blockEncodingList.add(new DoubleBlockEncoding(type.getScale()));
             } else if (clazz == Float.class) {
-                blockEncodingList.add(new FloatBlockEncoding());
+                blockEncodingList.add(new FloatBlockEncoding(type.getScale()));
             } else if (clazz == String.class) {
                 blockEncodingList.add(new StringBlockEncoding());
             } else if (clazz == Timestamp.class) {
@@ -124,7 +124,7 @@ private static List createBlockEncodingForRawOrcType(List= 0 && otherVal < 0) || (val < 0 && otherVal >= 0)) {
+                return false;
+            }
+            int scaleDiffAbs = Math.abs(scaleDiff);
+            if (scaleDiffAbs < DecimalTypeBase.POW_10.length) {
+                long power = DecimalTypeBase.POW_10[scaleDiffAbs];
+                // it does not matter if this overflows
+                if (scaleDiff > 0) {
+                    otherVal *= power;
+                } else {
+                    val *= power;
+                }
+                return val == otherVal;
+            }
+            // rare case for large scaleDiff, just fallback to normal compare
+        } else if (otherBlock.isDecimal128()) {
+            if (getScale() == otherBlock.getScale()) {
                 long thisDecimal64 = getLongInner(realPosition);
                 long thatLow = otherBlock.getDecimal128Low(otherPosition);
                 long thatHigh = otherBlock.getDecimal128High(otherPosition);
@@ -1316,30 +1358,34 @@ private boolean equalsInner(int realPosition, Block other, int otherPosition) {
                     return false;
                 }
                 return thisDecimal64 >= 0 ? (thatHigh == 0) : (thatHigh == -1);
-            } else {
-                Slice memorySegment2 = otherBlock.segmentUncheckedAt(otherPosition);
-                return RawBytesDecimalUtils.equals(getDecimalInner(realPosition).getMemorySegment(), memorySegment2);
             }
         }
-        if (isDecimal128()) {
-            if (otherBlock.isDecimal64()) {
+
+        // fallback to normal decimal compare
+        Slice memorySegment1 = this.segmentUncheckedAtInner(realPosition);
+        Slice memorySegment2 = otherBlock.segmentUncheckedAt(otherPosition);
+        return RawBytesDecimalUtils.equals(memorySegment1, memorySegment2);
+    }
+
+    private boolean decimal128EqualsInner(int realPosition, SegmentedDecimalBlock otherBlock, int otherPosition) {
+        if (otherBlock.isDecimal64()) {
+            if (getScale() == otherBlock.getScale()) {
                 long thisLow = decimal64Values[realPosition];
                 long thisHigh = decimal128HighValues[realPosition];
-                long thatDecimal64 = other.getLong(otherPosition);
+                long thatDecimal64 = otherBlock.getLong(otherPosition);
                 if (thisLow != thatDecimal64) {
                     return false;
                 }
                 return thatDecimal64 >= 0 ? (thisHigh == 0) : (thisHigh == -1);
-            } else if (otherBlock.isDecimal128()) {
+            }
+        } else if (otherBlock.isDecimal128()) {
+            if (getScale() == otherBlock.getScale()) {
                 return decimal64Values[realPosition] == otherBlock.getDecimal128Low(otherPosition) &&
                     decimal128HighValues[realPosition] == otherBlock.getDecimal128High(otherPosition);
-            } else {
-                Slice memorySegment2 = otherBlock.segmentUncheckedAt(otherPosition);
-                return RawBytesDecimalUtils.equals(getDecimalInner(realPosition).getMemorySegment(), memorySegment2);
             }
         }
 
-        // for decimal block, compare by memory segment
+        // fallback to normal decimal compare
         Slice memorySegment1 = this.segmentUncheckedAtInner(realPosition);
         Slice memorySegment2 = otherBlock.segmentUncheckedAt(otherPosition);
         return RawBytesDecimalUtils.equals(memorySegment1, memorySegment2);
@@ -1417,7 +1463,7 @@ private Object getElementAtUncheckedInner(int position) {
     }
 
     /**
-     * considered a low-frequency path in VectorizedExpression
+     * considered as a low-frequency path in VectorizedExpression
      */
     private void setElementAtInner(final int position, Object element) {
         if (element == null) {
@@ -1507,6 +1553,9 @@ private Slice getRegionInner(int position, Slice output) {
     @Override
     public void updateSizeInfo() {
         if (isUnalloc()) {
+            // maybe not allocated yet, or all nulls
+            estimatedSize = INSTANCE_SIZE + sizeOf(isNull);
+            elementUsedBytes = Byte.BYTES * positionCount;
             return;
         }
         if (isDecimal64()) {
@@ -1614,6 +1663,7 @@ public boolean isUnalloc() {
         return state == UNALLOC_STATE;
     }
 
+    @Override
     public int getScale() {
         return dataType.getScale();
     }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DecimalBlockBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DecimalBlockBuilder.java
index 7fd4205f9..e74cf54f5 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DecimalBlockBuilder.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DecimalBlockBuilder.java
@@ -232,6 +232,11 @@ public long getDecimal128High(int position) {
         return decimal128HighList.getLong(position);
     }
 
+    @Override
+    public int getScale() {
+        return scale;
+    }
+
     @Override
     public Object getObject(int position) {
         return isNull(position) ? null : getDecimal(position);
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlock.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlock.java
index 4eb31026b..da0f95fce 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlock.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlock.java
@@ -20,11 +20,15 @@
 import com.alibaba.polardbx.common.utils.hash.IStreamingHasher;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.rpc.result.XResultUtil;
 
 import com.google.common.base.Preconditions;
 import io.airlift.slice.XxHash64;
 import org.openjdk.jol.info.ClassLayout;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
 import static com.alibaba.polardbx.common.utils.memory.SizeOf.sizeOf;
 
 public class DoubleBlock extends AbstractBlock {
@@ -32,28 +36,33 @@ public class DoubleBlock extends AbstractBlock {
     private static final long INSTANCE_SIZE = ClassLayout.parseClass(DoubleBlock.class).instanceSize();
 
     private double[] values;
+    private final int scale;
 
     public DoubleBlock(DataType dataType, int slotLen) {
         super(dataType, slotLen);
         this.values = new double[slotLen];
+        this.scale = null == dataType ? XResultUtil.DECIMAL_NOT_SPECIFIED : dataType.getScale();
         updateSizeInfo();
     }
 
     public DoubleBlock(DataType dataType, double[] values, boolean[] nulls, boolean hasNull, int length) {
         super(dataType, length, nulls, hasNull);
         this.values = values;
+        this.scale = null == dataType ? XResultUtil.DECIMAL_NOT_SPECIFIED : dataType.getScale();
         updateSizeInfo();
     }
 
-    public DoubleBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, double[] values) {
+    public DoubleBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, double[] values, int scale) {
         super(arrayOffset, positionCount, valueIsNull);
         this.values = Preconditions.checkNotNull(values);
+        this.scale = scale;
         updateSizeInfo();
     }
 
     public DoubleBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, double[] values, boolean hasNull) {
         super(DataTypes.DoubleType, positionCount, valueIsNull, hasNull);
         this.values = Preconditions.checkNotNull(values);
+        this.scale = XResultUtil.DECIMAL_NOT_SPECIFIED;
         updateSizeInfo();
     }
 
@@ -61,7 +70,8 @@ public static DoubleBlock from(DoubleBlock other, int selSize, int[] selection)
         return new DoubleBlock(0,
             selSize,
             BlockUtils.copyNullArray(other.isNull, selection, selSize),
-            BlockUtils.copyDoubleArray(other.values, selection, selSize));
+            BlockUtils.copyDoubleArray(other.values, selection, selSize),
+            other.scale);
     }
 
     @Override
@@ -235,4 +245,19 @@ public void updateSizeInfo() {
         estimatedSize = INSTANCE_SIZE + sizeOf(isNull) + sizeOf(values);
         elementUsedBytes = Byte.BYTES * positionCount + Double.BYTES * positionCount;
     }
+
+    @Override
+    public int checksumV2(int position) {
+        if (isNull(position)) {
+            return 0;
+        }
+        double roundVal;
+        if (scale > 0 && scale < XResultUtil.DECIMAL_NOT_SPECIFIED) {
+            BigDecimal bd = new BigDecimal(Double.toString(values[position + arrayOffset]));
+            roundVal = bd.setScale(scale, RoundingMode.HALF_UP).doubleValue();
+        } else {
+            roundVal = values[position + arrayOffset];
+        }
+        return Double.hashCode(roundVal);
+    }
 }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlockBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlockBuilder.java
index f644d3286..4248bc6a8 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlockBuilder.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlockBuilder.java
@@ -16,16 +16,25 @@
 
 package com.alibaba.polardbx.executor.chunk;
 
+import com.alibaba.polardbx.rpc.result.XResultUtil;
 import com.google.common.base.Preconditions;
 import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
 
 public class DoubleBlockBuilder extends AbstractBlockBuilder {
 
     private final DoubleArrayList values;
+    private final int scale;
 
     public DoubleBlockBuilder(int capacity) {
         super(capacity);
         this.values = new DoubleArrayList(capacity);
+        this.scale = XResultUtil.DECIMAL_NOT_SPECIFIED;
+    }
+
+    public DoubleBlockBuilder(int capacity, int scale) {
+        super(capacity);
+        this.values = new DoubleArrayList(capacity);
+        this.scale = scale;
     }
 
     @Override
@@ -63,7 +72,8 @@ public void ensureCapacity(int capacity) {
 
     @Override
     public Block build() {
-        return new DoubleBlock(0, getPositionCount(), mayHaveNull() ? valueIsNull.elements() : null, values.elements());
+        return new DoubleBlock(0, getPositionCount(), mayHaveNull() ? valueIsNull.elements() : null,
+            values.elements(), scale);
     }
 
     @Override
@@ -74,7 +84,7 @@ public void appendNull() {
 
     @Override
     public BlockBuilder newBlockBuilder() {
-        return new DoubleBlockBuilder(getCapacity());
+        return new DoubleBlockBuilder(getCapacity(), scale);
     }
 
     @Override
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlockEncoding.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlockEncoding.java
index d9ee37889..cfbe8baa0 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlockEncoding.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/DoubleBlockEncoding.java
@@ -37,6 +37,15 @@
 
 public class DoubleBlockEncoding implements BlockEncoding {
     private static final String NAME = "DOUBLE";
+    private final int scale;
+
+    public DoubleBlockEncoding(int scale) {
+        this.scale = scale;
+    }
+
+    public int getScale() {
+        return scale;
+    }
 
     @Override
     public String getName() {
@@ -67,6 +76,6 @@ public Block readBlock(SliceInput sliceInput) {
                 values[position] = sliceInput.readDouble();
             }
         }
-        return new DoubleBlock(0, positionCount, valueIsNull, values);
+        return new DoubleBlock(0, positionCount, valueIsNull, values, scale);
     }
 }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/EnumBlock.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/EnumBlock.java
index 9f680990a..737e53f9f 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/EnumBlock.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/EnumBlock.java
@@ -36,7 +36,7 @@ public class EnumBlock extends AbstractCommonBlock {
 
     private static final long INSTANCE_SIZE = ClassLayout.parseClass(EnumBlock.class).instanceSize();
 
-    private final int[] offsets;
+    private int[] offsets;
     private final Map enumValues;
     private char[] data;
 
@@ -63,17 +63,16 @@ public EnumBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, int[
     }
 
     public static EnumBlock from(EnumBlock other, int selSize, int[] selection) {
-        int[] newOffsets = new int[selSize];
-
         if (other.data == null) {
+            int[] newOffsets = new int[selSize];
             return new EnumBlock(0, selSize,
                 BlockUtils.copyNullArray(other.isNull, selection, selSize),
                 newOffsets, null, other.enumValues);
         }
         if (selection == null) {
             return new EnumBlock(0, selSize,
-                BlockUtils.copyNullArray(other.isNull, selection, selSize),
-                newOffsets, Arrays.copyOf(other.data, other.data.length), other.enumValues);
+                Arrays.copyOf(other.isNull, selSize), Arrays.copyOf(other.offsets, selSize),
+                Arrays.copyOf(other.data, other.data.length), other.enumValues);
         } else {
             EnumBlockBuilder enumBlockBuilder =
                 new EnumBlockBuilder(selSize, other.data.length / (other.positionCount + 1) * selSize,
@@ -133,7 +132,7 @@ public int hashCode(int position) {
             return 0;
         }
 
-        return ChunkUtil.hashCode(data, beginOffset(position), endOffset(position), true);
+        return ChunkUtil.hashCodeIgnoreCase(data, beginOffset(position), endOffset(position));
     }
 
     @Override
@@ -215,6 +214,10 @@ public int[] getOffsets() {
         return offsets;
     }
 
+    public void setOffsets(int[] offsets) {
+        this.offsets = offsets;
+    }
+
     public char[] getData() {
         return data;
     }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/EnumBlockBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/EnumBlockBuilder.java
index 63afb761b..0acf88dea 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/EnumBlockBuilder.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/EnumBlockBuilder.java
@@ -118,7 +118,7 @@ public int hashCode(int position) {
         int beginOffset = position > 0 ? offsets.getInt(position - 1) : 0;
         int endOffset = offsets.getInt(position);
 
-        return ChunkUtil.hashCode(data.elements(), beginOffset, endOffset, true);
+        return ChunkUtil.hashCodeIgnoreCase(data.elements(), beginOffset, endOffset);
     }
 
     @Override
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlock.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlock.java
index c4d9c6b05..ab8d94d45 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlock.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlock.java
@@ -20,11 +20,14 @@
 import com.alibaba.polardbx.common.utils.hash.IStreamingHasher;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
-
+import com.alibaba.polardbx.rpc.result.XResultUtil;
 import com.google.common.base.Preconditions;
 import io.airlift.slice.XxHash64;
 import org.openjdk.jol.info.ClassLayout;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
 import static com.alibaba.polardbx.common.utils.memory.SizeOf.sizeOf;
 
 public class FloatBlock extends AbstractBlock {
@@ -33,17 +36,19 @@ public class FloatBlock extends AbstractBlock {
 
     private float[] values;
 
-    private boolean forDeletedOrcScan = false;
+    private final int scale;
 
     public FloatBlock(DataType dataType, int slotLen) {
         super(dataType, slotLen);
         this.values = new float[slotLen];
+        this.scale = null == dataType ? XResultUtil.DECIMAL_NOT_SPECIFIED : dataType.getScale();
         updateSizeInfo();
     }
 
-    public FloatBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, float[] values) {
+    public FloatBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, float[] values, int scale) {
         super(arrayOffset, positionCount, valueIsNull);
         this.values = Preconditions.checkNotNull(values);
+        this.scale = scale;
         updateSizeInfo();
     }
 
@@ -51,18 +56,11 @@ public static FloatBlock from(FloatBlock other, int selSize, int[] selection) {
         FloatBlock block = new FloatBlock(0,
             selSize,
             BlockUtils.copyNullArray(other.isNull, selection, selSize),
-            BlockUtils.copyFloatArray(other.values, selection, selSize));
-        block.forDeletedOrcScan = other.forDeletedOrcScan;
+            BlockUtils.copyFloatArray(other.values, selection, selSize),
+            other.scale);
         return block;
     }
 
-    public FloatBlock(DataType dataType, int slotLen, boolean forDeletedOrcScan) {
-        super(dataType, slotLen);
-        this.values = new float[slotLen];
-        this.forDeletedOrcScan = forDeletedOrcScan;
-        updateSizeInfo();
-    }
-
     @Override
     public float getFloat(int position) {
         checkReadablePosition(position);
@@ -220,5 +218,19 @@ public void updateSizeInfo() {
         elementUsedBytes = Byte.BYTES * positionCount + Float.BYTES * positionCount;
     }
 
+    @Override
+    public int checksumV2(int position) {
+        if (isNull(position)) {
+            return 0;
+        }
+        float roundVal;
+        if (scale > 0 && scale < XResultUtil.DECIMAL_NOT_SPECIFIED) {
+            BigDecimal bd = new BigDecimal(Double.toString(values[position + arrayOffset]));
+            roundVal = bd.setScale(scale, RoundingMode.HALF_UP).floatValue();
+        } else {
+            roundVal = values[position + arrayOffset];
+        }
+        return Float.hashCode(roundVal);
+    }
 }
 
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlockBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlockBuilder.java
index f3c41e506..5624b8690 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlockBuilder.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlockBuilder.java
@@ -16,6 +16,7 @@
 
 package com.alibaba.polardbx.executor.chunk;
 
+import com.alibaba.polardbx.rpc.result.XResultUtil;
 import com.google.common.base.Preconditions;
 import it.unimi.dsi.fastutil.floats.FloatArrayList;
 
@@ -23,9 +24,18 @@ public class FloatBlockBuilder extends AbstractBlockBuilder {
 
     private final FloatArrayList values;
 
+    private final int scale;
+
     public FloatBlockBuilder(int capacity) {
         super(capacity);
         this.values = new FloatArrayList(capacity);
+        this.scale = XResultUtil.DECIMAL_NOT_SPECIFIED;
+    }
+
+    public FloatBlockBuilder(int capacity, int scale) {
+        super(capacity);
+        this.values = new FloatArrayList(capacity);
+        this.scale = scale;
     }
 
     @Override
@@ -63,7 +73,8 @@ public void ensureCapacity(int capacity) {
 
     @Override
     public Block build() {
-        return new FloatBlock(0, getPositionCount(), mayHaveNull() ? valueIsNull.elements() : null, values.elements());
+        return new FloatBlock(0, getPositionCount(), mayHaveNull() ? valueIsNull.elements() : null,
+            values.elements(), scale);
     }
 
     @Override
@@ -74,7 +85,7 @@ public void appendNull() {
 
     @Override
     public BlockBuilder newBlockBuilder() {
-        return new FloatBlockBuilder(getCapacity());
+        return new FloatBlockBuilder(getCapacity(), scale);
     }
 
     @Override
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlockEncoding.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlockEncoding.java
index b843ad11b..302181c9b 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlockEncoding.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/FloatBlockEncoding.java
@@ -38,6 +38,16 @@
 public class FloatBlockEncoding implements BlockEncoding {
     private static final String NAME = "FLOAT";
 
+    private final int scale;
+
+    public FloatBlockEncoding(int scale) {
+        this.scale = scale;
+    }
+
+    public int getScale() {
+        return scale;
+    }
+
     @Override
     public String getName() {
         return NAME;
@@ -67,6 +77,6 @@ public Block readBlock(SliceInput sliceInput) {
                 values[position] = sliceInput.readFloat();
             }
         }
-        return new FloatBlock(0, positionCount, valueIsNull, values);
+        return new FloatBlock(0, positionCount, valueIsNull, values, scale);
     }
 }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/IntegerBlock.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/IntegerBlock.java
index 1b54a1323..9366cdf40 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/IntegerBlock.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/IntegerBlock.java
@@ -447,6 +447,12 @@ public int getInt(int position) {
         return getIntInner(position);
     }
 
+    @Override
+    public long getLong(int position) {
+        position = realPositionOf(position);
+        return values[position + arrayOffset];
+    }
+
     @Override
     public Object getObject(int position) {
         position = realPositionOf(position);
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/SegmentedDecimalBlock.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/SegmentedDecimalBlock.java
index 94d0ed5f1..baf219b53 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/SegmentedDecimalBlock.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/SegmentedDecimalBlock.java
@@ -34,10 +34,14 @@ public interface SegmentedDecimalBlock {
 
     boolean isDecimal128();
 
+    long getLong(int position);
+
     long getDecimal128Low(int position);
 
     long getDecimal128High(int position);
 
+    int getScale();
+
     /**
      * State of decimal block
      */
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/ShortBlock.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/ShortBlock.java
index bac4f2039..20a45580a 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/ShortBlock.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/ShortBlock.java
@@ -75,6 +75,12 @@ public short getShort(int position) {
         return values[position + arrayOffset];
     }
 
+    @Override
+    public long getLong(int position) {
+        checkReadablePosition(position);
+        return values[position + arrayOffset];
+    }
+
     @Override
     public Object getObject(int position) {
         return isNull(position) ? null : getShort(position);
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/SliceBlock.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/SliceBlock.java
index caaed6656..79f29bdb4 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/SliceBlock.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/SliceBlock.java
@@ -17,6 +17,7 @@
 package com.alibaba.polardbx.executor.chunk;
 
 import com.alibaba.polardbx.common.charset.CollationName;
+import com.alibaba.polardbx.common.utils.XxhashUtils;
 import com.alibaba.polardbx.common.utils.hash.IStreamingHasher;
 import com.alibaba.polardbx.executor.operator.scan.BlockDictionary;
 import com.alibaba.polardbx.executor.operator.scan.impl.DictionaryMapping;
@@ -535,7 +536,7 @@ public long hashCodeUnderPairWise(int pos, boolean enableCompatible) {
             // should use collation handler to calculate hashcode under partition wise
             int position = realPositionOf(pos);
             Slice subRegion = getRegionInner(position);
-            return dataType.hashcode(subRegion);
+            return XxhashUtils.finalShuffle(dataType.hashcode(subRegion));
         }
     }
 
@@ -678,11 +679,11 @@ public int equals(int position, Slice that) {
             int beginOffset = beginOffsetInner(position);
             int endOffset = endOffsetInner(position);
 
-            return this.data.compareTo(beginOffset, endOffset - beginOffset, that, 0, that.length()) == 0 ? 1 : 0;
+            return this.data.equals(beginOffset, endOffset - beginOffset, that, 0, that.length()) ? 1 : 0;
         } else {
             Slice value = getDictValue(position);
 
-            return value.compareTo(that) == 0 ? 1 : 0;
+            return value.equals(that) ? 1 : 0;
         }
     }
 
@@ -793,7 +794,7 @@ private long hashCodeUseXxHashInner(int pos) {
 
         if (compatible) {
             Slice subRegion = getRegionInner(pos);
-            return dataType.hashcode(subRegion);
+            return XxhashUtils.finalShuffle(dataType.hashcode(subRegion));
         }
 
         if (dictionary == null) {
@@ -866,7 +867,7 @@ private int hashCodeInner(int position) {
 
         if (compatible) {
             Slice subRegion = getRegionInner(position);
-            return dataType.hashcode(subRegion);
+            return Long.hashCode(XxhashUtils.finalShuffle(dataType.hashcode(subRegion)));
         }
 
         if (dictionary == null) {
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/StringBlock.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/StringBlock.java
index c33789b29..fb03812ec 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/StringBlock.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/StringBlock.java
@@ -40,7 +40,7 @@ public class StringBlock extends AbstractCommonBlock {
 
     private static final long INSTANCE_SIZE = ClassLayout.parseClass(StringBlock.class).instanceSize();
 
-    private final int[] offsets;
+    private int[] offsets;
     private char[] data;
 
     public StringBlock(DataType dataType, int positionCount) {
@@ -72,17 +72,16 @@ public static StringBlock of(String... values) {
     }
 
     public static StringBlock from(StringBlock other, int selSize, int[] selection) {
-        int[] newOffsets = new int[selSize];
-
         if (other.data == null) {
+            int[] newOffsets = new int[selSize];
             return new StringBlock(other.dataType, 0, selSize,
                 BlockUtils.copyNullArray(other.isNull, selection, selSize),
                 newOffsets, null);
         }
         if (selection == null) {
             return new StringBlock(other.dataType, 0, selSize,
-                BlockUtils.copyNullArray(other.isNull, selection, selSize),
-                newOffsets, Arrays.copyOf(other.data, other.data.length));
+                Arrays.copyOf(other.isNull, selSize), Arrays.copyOf(other.offsets, selSize),
+                Arrays.copyOf(other.data, other.data.length));
         } else {
             StringBlockBuilder stringBlockBuilder = new StringBlockBuilder(other.dataType, selSize,
                 other.data.length / (other.positionCount + 1) * selSize);
@@ -158,7 +157,7 @@ public int hashCode(int position) {
             return 0;
         }
 
-        return ChunkUtil.hashCode(data, beginOffset(position), endOffset(position), true);
+        return ChunkUtil.hashCodeIgnoreCase(data, beginOffset(position), endOffset(position));
     }
 
     @Override
@@ -224,6 +223,10 @@ public int[] getOffsets() {
         return offsets;
     }
 
+    public void setOffsets(int[] offsets) {
+        this.offsets = offsets;
+    }
+
     public char[] getData() {
         return data;
     }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/StringBlockBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/StringBlockBuilder.java
index 669e28381..c149329b3 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/StringBlockBuilder.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/chunk/StringBlockBuilder.java
@@ -112,7 +112,7 @@ public int hashCode(int position) {
         int beginOffset = position > 0 ? offsets.getInt(position - 1) : 0;
         int endOffset = offsets.getInt(position);
 
-        return ChunkUtil.hashCode(data.elements(), beginOffset, endOffset, true);
+        return ChunkUtil.hashCodeIgnoreCase(data.elements(), beginOffset, endOffset);
     }
 
     int beginOffset(int position) {
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/ByteCSVReader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/ByteCSVReader.java
index 4db00b483..f256d2066 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/ByteCSVReader.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/ByteCSVReader.java
@@ -18,39 +18,41 @@
 
 package com.alibaba.polardbx.executor.columnar;
 
+import org.apache.hadoop.fs.FSDataInputStream;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
 
 public class ByteCSVReader {
     private final ByteBuffer lengthBuffer = ByteBuffer.allocate(Integer.BYTES);
-    private final InputStream inputStream;
+    private final FSDataInputStream inputStream;
 
     private final String csvFileName;
 
     private long currentPosition;
     private final long fileEndOffset;
 
-    public ByteCSVReader(String csvFileName, InputStream inputStream) throws IOException {
+    public ByteCSVReader(String csvFileName, FSDataInputStream inputStream, long length) throws IOException {
         this.csvFileName = csvFileName;
         this.inputStream = inputStream;
         this.currentPosition = 0;
-        this.fileEndOffset = inputStream.available();
+        this.fileEndOffset = length;
     }
 
-    public boolean isReadable() {
-        return currentPosition < fileEndOffset;
+    public boolean isReadable() throws IOException {
+        return currentPosition < fileEndOffset && inputStream.available() > 0;
     }
 
     public CSVRow nextRow() throws IOException {
         lengthBuffer.clear();
         canReadFileLength(Integer.BYTES);
-        inputStream.read(lengthBuffer.array(), 0, Integer.BYTES);
+        inputStream.readFully(lengthBuffer.array(), 0, Integer.BYTES);
 
         int length = lengthBuffer.getInt();
         byte[] data = new byte[length];
         canReadFileLength(length);
-        inputStream.read(data);
+        inputStream.readFully(data);
 
         currentPosition += (Integer.BYTES + length);
 
@@ -71,7 +73,7 @@ private void canReadFileLength(int needRead) throws IOException {
         }
     }
 
-    public long position() {
+    public long position() throws IOException {
         return currentPosition;
     }
 
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/CsvDataIterator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/CsvDataIterator.java
new file mode 100644
index 000000000..840f6b24f
--- /dev/null
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/CsvDataIterator.java
@@ -0,0 +1,110 @@
+package com.alibaba.polardbx.executor.columnar;
+
+import com.alibaba.polardbx.common.Engine;
+import com.alibaba.polardbx.common.exception.TddlRuntimeException;
+import com.alibaba.polardbx.common.exception.code.ErrorCode;
+import com.alibaba.polardbx.executor.chunk.Chunk;
+import com.alibaba.polardbx.executor.gms.FileVersionStorage;
+import com.alibaba.polardbx.optimizer.config.table.ColumnMeta;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+public class CsvDataIterator implements Iterator {
+    private final CSVFileReader csvFileReader;
+    private final String csvFileName;
+    private final long position;
+    private Chunk nextChunk = null;
+    private boolean endOfData = false;
+
+    public CsvDataIterator(CSVFileReader csvFileReader,
+                           String csvFileName, long position, List columnMetas, Engine engine) {
+        this.csvFileReader = csvFileReader;
+        this.csvFileName = csvFileName;
+        this.position = position;
+        try {
+            this.csvFileReader.open(new ExecutionContext(), columnMetas, FileVersionStorage.CSV_CHUNK_LIMIT, engine,
+                csvFileName, 0, (int) position);
+        } catch (Throwable t) {
+            throw new TddlRuntimeException(ErrorCode.ERR_LOAD_CSV_FILE, t,
+                String.format("Failed to open csv file reader, file name: %s, position: %d",
+                    csvFileName, position));
+        }
+    }
+
+    public CsvDataIterator(CSVFileReader csvFileReader,
+                           String csvFileName, int start, int end,
+                           ExecutionContext context, List columnMetas, Engine engine) {
+        this.csvFileReader = csvFileReader;
+        this.csvFileName = csvFileName;
+        this.position = end;
+        try {
+            this.csvFileReader.open(new ExecutionContext(), columnMetas, FileVersionStorage.CSV_CHUNK_LIMIT, engine,
+                csvFileName, start, end - start);
+        } catch (Throwable t) {
+            String msgPrefix =
+                (csvFileReader instanceof RawOrcTypeCsvReader) ? "[Specified Raw Orc Type]" : "[Specified]";
+            throw new TddlRuntimeException(ErrorCode.ERR_LOAD_CSV_FILE, t,
+                String.format("%s Failed to open csv file reader, file name: %s, start: %d, end: %d",
+                    msgPrefix, csvFileName, start, end));
+        }
+    }
+
+    @Override
+    public boolean hasNext() {
+        if (endOfData) {
+            return false;
+        }
+        if (nextChunk == null) {
+            fetchNextChunk();
+        }
+        return nextChunk != null;
+    }
+
+    @Override
+    public Chunk next() {
+        if (!hasNext()) {
+            throw new NoSuchElementException();
+        }
+        Chunk currentChunk = nextChunk;
+        fetchNextChunk(); // Pre-fetch the next chunk
+        return currentChunk;
+    }
+
+    private void fetchNextChunk() {
+        try {
+            nextChunk = csvFileReader.nextUntilPosition(position);
+            if (nextChunk == null) {
+                endOfData = true;
+                csvFileReader.close(); // Close the reader as there's no more data to read
+            }
+        } catch (Throwable t) {
+            endOfData = true;
+            closeReader();
+            throw new TddlRuntimeException(ErrorCode.ERR_LOAD_CSV_FILE, t,
+                String.format("Failed during reading csv file, file name: %s, position: %d",
+                    csvFileName, position));
+        }
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException("Remove operation is not supported by this iterator");
+    }
+
+    public void closeReader() {
+        try {
+            csvFileReader.close();
+        } catch (Throwable t) {
+            // ignored
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        closeReader(); // Ensure the reader is closed when the iterator is garbage-collected
+        super.finalize();
+    }
+}
\ No newline at end of file
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/RawOrcTypeCsvReader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/RawOrcTypeCsvReader.java
index 78fd7de7c..d463b26f4 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/RawOrcTypeCsvReader.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/RawOrcTypeCsvReader.java
@@ -34,12 +34,11 @@
 import com.alibaba.polardbx.optimizer.core.datatype.EnumType;
 import com.alibaba.polardbx.optimizer.core.datatype.SetType;
 import com.alibaba.polardbx.rpc.result.XResultUtil;
+import org.apache.hadoop.fs.FSDataInputStream;
 import org.apache.orc.impl.TypeUtils;
 import org.jetbrains.annotations.NotNull;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -53,12 +52,13 @@
 public class RawOrcTypeCsvReader implements CSVFileReader {
 
     private int fieldNum;
-    private InputStream inputStream;
+    private FSDataInputStream inputStream;
     private List columnMetas;
     private ByteCSVReader rowReader;
     private ExecutionContext context;
     private int chunkLimit;
     private int offset;
+    private int length;
     public static Charset DEFAULT_CHARSET = CharsetName.defaultCharset().toJavaCharset();
 
     @Override
@@ -67,18 +67,15 @@ public void open(ExecutionContext context, List columnMetas, int chu
         this.chunkLimit = chunkLimit;
         this.context = context;
         this.fieldNum = columnMetas.size();
-        // synchronous reading
-        byte[] buffer;
-        if (offset == 0 && length == EOF) {
-            buffer = FileSystemUtils.readFullyFile(csvFileName, engine, true);
-        } else {
-            buffer = new byte[length];
-            FileSystemUtils.readFile(csvFileName, offset, length, buffer, engine, true);
+
+        this.inputStream = FileSystemUtils.openStreamFileWithBuffer(csvFileName, engine, true);
+        if (offset > 0) {
+            inputStream.seek(offset);
         }
+        this.length = length == EOF ? Integer.MAX_VALUE : length;
 
-        this.inputStream = new ByteArrayInputStream(buffer);
         this.columnMetas = columnMetas;
-        this.rowReader = new ByteCSVReader(csvFileName, inputStream);
+        this.rowReader = new ByteCSVReader(csvFileName, inputStream, this.length);
         this.offset = offset;
     }
 
@@ -89,6 +86,7 @@ public Chunk next() {
 
     @Override
     public Chunk nextUntilPosition(long pos) {
+        long positionBound = Math.min(pos, offset + length);
         List blockBuilders = this.columnMetas
             .stream()
             .map(ColumnMeta::getDataType)
@@ -96,8 +94,8 @@ public Chunk nextUntilPosition(long pos) {
             .collect(Collectors.toList());
 
         int totalRow = 0;
-        while (offset + rowReader.position() < pos && rowReader.isReadable()) {
-            try {
+        try {
+            while (offset + rowReader.position() < positionBound && rowReader.isReadable()) {
                 CSVRow row = rowReader.nextRow();
 
                 // for each row, parse each column and append onto block-builder
@@ -112,10 +110,9 @@ public Chunk nextUntilPosition(long pos) {
                 if (++totalRow >= chunkLimit) {
                     return buildChunk(blockBuilders, totalRow);
                 }
-
-            } catch (IOException e) {
-                throw GeneralUtil.nestedException(e);
             }
+        } catch (IOException e) {
+            throw GeneralUtil.nestedException(e);
         }
 
         // flush the remaining rows
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/SimpleCSVFileReader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/SimpleCSVFileReader.java
index 932b33c75..f2ccf763e 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/SimpleCSVFileReader.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/SimpleCSVFileReader.java
@@ -28,11 +28,10 @@
 import com.alibaba.polardbx.optimizer.config.table.ColumnMeta;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import org.apache.hadoop.fs.FSDataInputStream;
 import org.jetbrains.annotations.NotNull;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -42,13 +41,14 @@
  */
 public class SimpleCSVFileReader implements CSVFileReader {
     private int fieldNum;
-    private InputStream inputStream;
+    private FSDataInputStream inputStream;
     private List columnProviders;
     private List columnMetas;
     private ByteCSVReader rowReader;
     private ExecutionContext context;
     private int chunkLimit;
     private int offset;
+    private int length;
 
     @Override
     public void open(ExecutionContext context,
@@ -61,20 +61,17 @@ public void open(ExecutionContext context,
         this.chunkLimit = chunkLimit;
         this.context = context;
         this.fieldNum = columnMetas.size();
-        // synchronous reading
-        byte[] buffer;
-        if (offset == 0 && length == EOF) {
-            buffer = FileSystemUtils.readFullyFile(csvFileName, engine, true);
-        } else {
-            buffer = new byte[length];
-            FileSystemUtils.readFile(csvFileName, offset, length, buffer, engine, true);
+
+        this.inputStream = FileSystemUtils.openStreamFileWithBuffer(csvFileName, engine, true);
+        if (offset > 0) {
+            inputStream.seek(offset);
         }
+        this.length = length == EOF ? Integer.MAX_VALUE : length;
 
-        this.inputStream = new ByteArrayInputStream(buffer);
         this.columnProviders = columnMetas.stream()
             .map(ColumnProviders::getProvider).collect(Collectors.toList());
         this.columnMetas = columnMetas;
-        this.rowReader = new ByteCSVReader(csvFileName, inputStream);
+        this.rowReader = new ByteCSVReader(csvFileName, inputStream, this.length);
         this.offset = offset;
     }
 
@@ -85,6 +82,7 @@ public Chunk next() {
 
     @Override
     public Chunk nextUntilPosition(long pos) {
+        long positionBound = Math.min(pos, offset + length);
         List blockBuilders = this.columnMetas
             .stream()
             .map(ColumnMeta::getDataType)
@@ -92,8 +90,8 @@ public Chunk nextUntilPosition(long pos) {
             .collect(Collectors.toList());
 
         int totalRow = 0;
-        while (offset + rowReader.position() < pos && rowReader.isReadable()) {
-            try {
+        try {
+            while (offset + rowReader.position() < positionBound && rowReader.isReadable()) {
                 CSVRow row = rowReader.nextRow();
 
                 // for each row, parse each column and append onto block-builder
@@ -111,10 +109,9 @@ public Chunk nextUntilPosition(long pos) {
                 if (++totalRow >= chunkLimit) {
                     return buildChunk(blockBuilders, totalRow);
                 }
-
-            } catch (IOException e) {
-                throw GeneralUtil.nestedException(e);
             }
+        } catch (IOException e) {
+            throw GeneralUtil.nestedException(e);
         }
 
         // flush the remaining rows
@@ -122,7 +119,7 @@ public Chunk nextUntilPosition(long pos) {
     }
 
     @NotNull
-    private Chunk buildChunk(List blockBuilders, int totalRow) {
+    protected Chunk buildChunk(List blockBuilders, int totalRow) {
         return new Chunk(totalRow, blockBuilders.stream()
             .map(BlockBuilder::build).toArray(Block[]::new));
     }
@@ -134,7 +131,7 @@ public void close() throws IOException {
         }
     }
 
-    public long position() {
+    public long position() throws IOException {
         return offset + rowReader.position();
     }
 }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/SimpleDeletionFileReader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/SimpleDeletionFileReader.java
index c5a74068d..3debd3d2c 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/SimpleDeletionFileReader.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/SimpleDeletionFileReader.java
@@ -21,10 +21,10 @@
 import com.alibaba.polardbx.common.utils.logger.Logger;
 import com.alibaba.polardbx.common.utils.logger.LoggerFactory;
 import com.alibaba.polardbx.gms.engine.FileSystemUtils;
+import org.apache.hadoop.fs.FSDataInputStream;
 import org.roaringbitmap.RoaringBitmap;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
 import java.text.MessageFormat;
 
 /**
@@ -33,64 +33,74 @@
  */
 public class SimpleDeletionFileReader implements DeletionFileReader {
     private static final Logger LOGGER = LoggerFactory.getLogger("oss");
-    private ByteBuffer byteBuffer;
     private int offset;
+    private int length;
+    private int pos = 0;
+    private FSDataInputStream inputStream;
 
     @Override
     public void open(Engine engine, String delFileName, int offset, int length) throws IOException {
-        // synchronous reading (it may cause OOM)
-        byte[] buffer;
 
+        // TODO(siyun): turn into streaming read
         if (!FileSystemUtils.fileExists(delFileName, engine, true)) {
-            buffer = new byte[0];
+            this.inputStream = null;
             LOGGER.warn(
                 MessageFormat.format("{0} in Engine:{1} is not exists with offset:{2} and length:{3}", delFileName,
                     engine, offset, length));
-        } else if (offset == 0 && length == EOF) {
-            // read fully
-            buffer = FileSystemUtils.readFullyFile(delFileName, engine, true);
-        } else {
-            // read from offset
-            buffer = new byte[length];
-            FileSystemUtils.readFile(delFileName, offset, length, buffer, engine, true);
         }
-        this.byteBuffer = ByteBuffer.wrap(buffer);
+        this.inputStream = FileSystemUtils.openStreamFileWithBuffer(delFileName, engine, true);
+        if (offset > 0) {
+            inputStream.seek(offset);
+        }
+
         this.offset = offset;
+        this.length = length == EOF ? Integer.MAX_VALUE : length;
     }
 
     @Override
     public DeletionEntry next() {
+        if (inputStream == null) {
+            return null;
+        }
+
         // We suppose that the data in byte buffer is complete serialized bitmap list.
-        if (byteBuffer.hasRemaining()) {
-            final int sizeInBytes = byteBuffer.getInt();
-            final int fileId = byteBuffer.getInt();
-            final long tso = byteBuffer.getLong();
-            RoaringBitmap bitmap = new RoaringBitmap();
-            try {
-                bitmap.deserialize(byteBuffer);
-                byteBuffer.position(byteBuffer.position()
-                    + sizeInBytes - (Integer.BYTES + Long.BYTES));
-            } catch (IOException e) {
-                LOGGER.error(MessageFormat.format(
-                    "current bitmap information: sizeInBytes = {0}, fileId = {1}, tso = {2}, dataLen = {3}",
-                    sizeInBytes, fileId, tso, byteBuffer.remaining()), e);
-                throw GeneralUtil.nestedException(e);
-            }
+        try {
+            if (inputStream.getPos() < offset + length && inputStream.available() > 0) {
+                final int sizeInBytes = inputStream.readInt();
+                final int fileId = inputStream.readInt();
+                final long tso = inputStream.readLong();
+                RoaringBitmap bitmap = new RoaringBitmap();
+                try {
+                    bitmap.deserialize(inputStream);
+                } catch (IOException e) {
+                    LOGGER.error(MessageFormat.format(
+                        "current bitmap information: sizeInBytes = {0}, fileId = {1}, tso = {2}, position = {3}",
+                        sizeInBytes, fileId, tso, inputStream.getPos()), e);
+                    throw GeneralUtil.nestedException(e);
+                }
 
-            return new DeletionEntry(tso, fileId, bitmap);
+                pos = (int) inputStream.getPos();
+                return new DeletionEntry(tso, fileId, bitmap);
+            }
+        } catch (IOException e) {
+            LOGGER.error(MessageFormat.format("current readBytesCount = {0}", pos), e);
         }
         return null;
     }
 
     @Override
     public int position() {
-        return offset + byteBuffer.position();
+        return pos;
     }
 
     @Override
     public void close() {
-        if (byteBuffer != null) {
-            this.byteBuffer.clear();
+        if (inputStream != null) {
+            try {
+                inputStream.close();
+            } catch (Throwable t) {
+                // ignore
+            }
         }
     }
 }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciChecker.java
index 7ff68fd6f..62ce13c10 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciChecker.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciChecker.java
@@ -31,6 +31,7 @@
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.utils.ITransaction;
 import com.alibaba.polardbx.statistics.SQLRecorderLogger;
+import org.jetbrains.annotations.NotNull;
 
 import java.sql.Connection;
 import java.sql.ResultSet;
@@ -45,8 +46,8 @@
 public class CciChecker implements ICciChecker {
     private static final Logger logger = LoggerFactory.getLogger(CciChecker.class);
     private final String schemaName;
-    private final String tableName;
-    private final String indexName;
+    protected final String tableName;
+    protected final String indexName;
     private long primaryHashCode = -1;
     private long columnarHashCode = -1;
     private long primaryCount = -1;
@@ -62,11 +63,11 @@ public class CciChecker implements ICciChecker {
     private static final String CALCULATE_COLUMNAR_HASH =
         "select count(0) as count, check_sum_v2(%s) as pk_checksum, check_sum_v2(*) as checksum "
             + "from %s force index(%s)";
-    private static final String PRIMARY_HINT =
-        "/*+TDDL:WORKLOAD_TYPE=AP ENABLE_MPP=true ENABLE_MASTER_MPP=true "
+    protected static final String PRIMARY_HINT =
+        "/*+TDDL:WORKLOAD_TYPE=AP "
             + "SOCKET_TIMEOUT=259200000 MPP_TASK_MAX_RUN_TIME=259200000 %s */";
-    private static final String COLUMNAR_HINT =
-        "/*+TDDL:WORKLOAD_TYPE=AP ENABLE_MPP=true ENABLE_MASTER_MPP=true ENABLE_COLUMNAR_OPTIMIZER=true "
+    protected static final String COLUMNAR_HINT =
+        "/*+TDDL:WORKLOAD_TYPE=AP ENABLE_COLUMNAR_OPTIMIZER=true "
             + "OPTIMIZER_TYPE='columnar' ENABLE_HTAP=true SOCKET_TIMEOUT=259200000 "
             + "MPP_TASK_MAX_RUN_TIME=259200000 %s */";
 
@@ -78,8 +79,7 @@ public CciChecker(String schemaName, String tableName, String indexName) {
 
     @Override
     public void check(ExecutionContext baseEc, Runnable recoverChangedConfigs) throws Throwable {
-        Pair tso =
-            ColumnarTransactionUtils.getLatestOrcCheckpointTsoFromGms();
+        Pair tso = getCheckTso();
         IInnerConnectionManager manager = ExecutorContext.getContext(schemaName).getInnerConnectionManager();
         logger.warn("Check cci using innodb tso " + tso.getKey() + ", columnar tso " + tso.getValue());
 
@@ -104,20 +104,16 @@ public void check(ExecutionContext baseEc, Runnable recoverChangedConfigs) throw
             }
 
             // Calculate columnar table checksum.
-            try (Connection conn = manager.getConnection(schemaName);
+            try (IInnerConnection conn = manager.getConnection(schemaName);
                 Statement stmt = conn.createStatement()) {
-                if (conn instanceof IInnerConnection) {
-                    ((IInnerConnection) conn).addExecutionContextInjectHook(
-                        // To see non-PUBLIC CCI.
-                        (ec) -> ((ExecutionContext) ec).setCheckingCci(true));
-                }
+                conn.addExecutionContextInjectHook(
+                    // To see non-PUBLIC CCI.
+                    (ec) -> ((ExecutionContext) ec).setCheckingCci(true));
                 long start = System.nanoTime();
                 calColumnarHashCode(stmt, baseEc, tso.getValue());
                 SQLRecorderLogger.ddlLogger.info("[Naive checker] Columnar checksum calculated, costing "
                     + ((System.nanoTime() - start) / 1_000_000) + " ms");
-                if (conn instanceof IInnerConnection) {
-                    ((IInnerConnection) conn).clearExecutionContextInjectHooks();
-                }
+                conn.clearExecutionContextInjectHooks();
 
             } catch (Throwable t) {
                 SQLRecorderLogger.ddlLogger.error(
@@ -131,6 +127,10 @@ public void check(ExecutionContext baseEc, Runnable recoverChangedConfigs) throw
 
     }
 
+    protected Pair getCheckTso() {
+        return ColumnarTransactionUtils.getLatestOrcCheckpointTsoFromGms();
+    }
+
     @Override
     public boolean getCheckReports(Collection reports) {
         boolean success = true;
@@ -164,25 +164,6 @@ public boolean getCheckReports(Collection reports) {
     }
 
     private void calPrimaryHashCode(Statement stmt, ExecutionContext ec, long tso) throws SQLException {
-        // Build hint.
-        StringBuilder sb = new StringBuilder();
-        long parallelism;
-        if ((parallelism = ec.getParamManager().getInt(ConnectionParams.MPP_PARALLELISM)) > 0) {
-            sb.append(" MPP_PARALLELISM=")
-                .append(parallelism)
-                .append(" ");
-        }
-        if ((parallelism = ec.getParamManager().getInt(ConnectionParams.PARALLELISM)) > 0) {
-            sb.append(" PARALLELISM=")
-                .append(parallelism)
-                .append(" ");
-        }
-        sb.append(" SNAPSHOT_TS=")
-            .append(tso)
-            .append(" ");
-        sb.append(" TRANSACTION_POLICY=TSO");
-        String hint = String.format(PRIMARY_HINT, sb);
-
         // Build pk list.
         String pkList = ec
             .getSchemaManager(schemaName)
@@ -191,11 +172,7 @@ private void calPrimaryHashCode(Statement stmt, ExecutionContext ec, long tso) t
             .stream()
             .map(ColumnMeta::getName)
             .collect(Collectors.joining(","));
-
-        String sql = String.format(CALCULATE_PRIMARY_HASH, pkList, tableName);
-
-        // Assert using logical view as table scan.
-        sql = hint + sql;
+        String sql = getPrimarySql(ec, tso, pkList);
         logger.warn("Check CCI primary sql: " + sql);
         primaryCheckSql = sql;
         ResultSet explainRs = stmt.executeQuery("explain " + sql);
@@ -208,7 +185,7 @@ private void calPrimaryHashCode(Statement stmt, ExecutionContext ec, long tso) t
             throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, "Check cci plan does not contain LogicalView");
         }
 
-        ResultSet rs = stmt.executeQuery(hint + sql);
+        ResultSet rs = stmt.executeQuery(sql);
         if (rs.next()) {
             primaryCount = rs.getLong("count");
             primaryPkHashCode = rs.getLong("pk_checksum");
@@ -217,24 +194,6 @@ private void calPrimaryHashCode(Statement stmt, ExecutionContext ec, long tso) t
     }
 
     private void calColumnarHashCode(Statement stmt, ExecutionContext ec, long tso) throws SQLException {
-        // Build hint.
-        StringBuilder sb = new StringBuilder();
-        long parallelism;
-        if ((parallelism = ec.getParamManager().getInt(ConnectionParams.MPP_PARALLELISM)) > 0) {
-            sb.append(" MPP_PARALLELISM=")
-                .append(parallelism)
-                .append(" ");
-        }
-        if ((parallelism = ec.getParamManager().getInt(ConnectionParams.PARALLELISM)) > 0) {
-            sb.append(" PARALLELISM=")
-                .append(parallelism)
-                .append(" ");
-        }
-        sb.append(" SNAPSHOT_TS=")
-            .append(tso)
-            .append(" ");
-        String hint = String.format(COLUMNAR_HINT, sb);
-
         // Build pk list.
         String pkList = ec
             .getSchemaManager(schemaName)
@@ -243,11 +202,7 @@ private void calColumnarHashCode(Statement stmt, ExecutionContext ec, long tso)
             .stream()
             .map(ColumnMeta::getName)
             .collect(Collectors.joining(","));
-
-        String sql = String.format(CALCULATE_COLUMNAR_HASH, pkList, tableName, indexName);
-
-        // Assert using columnar scan.
-        sql = hint + sql;
+        String sql = getColumnarSql(ec, tso, pkList);
         logger.warn("Check CCI columnar sql: " + sql);
         columnarCheckSql = sql;
         ResultSet explainRs = stmt.executeQuery("explain " + sql);
@@ -267,4 +222,33 @@ private void calColumnarHashCode(Statement stmt, ExecutionContext ec, long tso)
             columnarHashCode = rs.getLong("checksum");
         }
     }
+
+    protected String getColumnarSql(ExecutionContext ec, long tso, String pkList) {
+        // Build hint.
+        StringBuilder sb = new StringBuilder();
+        ICciChecker.setBasicHint(ec, sb);
+        sb.append(" SNAPSHOT_TS=")
+            .append(tso)
+            .append(" ");
+        String hint = String.format(COLUMNAR_HINT, sb);
+
+        String sql = String.format(CALCULATE_COLUMNAR_HASH, pkList, tableName, indexName);
+
+        return hint + sql;
+    }
+
+    protected String getPrimarySql(ExecutionContext ec, long tso, String pkList) {
+        // Build hint.
+        StringBuilder sb = new StringBuilder();
+        ICciChecker.setBasicHint(ec, sb);
+        sb.append(" SNAPSHOT_TS=")
+            .append(tso)
+            .append(" ");
+        sb.append(" TRANSACTION_POLICY=TSO");
+        String hint = String.format(PRIMARY_HINT, sb);
+
+        String sql = String.format(CALCULATE_PRIMARY_HASH, pkList, tableName);
+
+        return hint + sql;
+    }
 }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciFastChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciFastChecker.java
index 7ab218f9e..31928e5d4 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciFastChecker.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciFastChecker.java
@@ -21,29 +21,47 @@
 import com.alibaba.polardbx.common.RevisableOrderInvariantHash;
 import com.alibaba.polardbx.common.exception.TddlRuntimeException;
 import com.alibaba.polardbx.common.exception.code.ErrorCode;
-import com.alibaba.polardbx.common.properties.ConnectionParams;
+import com.alibaba.polardbx.common.oss.ColumnarFileType;
+import com.alibaba.polardbx.common.oss.IDeltaReadOption;
 import com.alibaba.polardbx.common.utils.Pair;
 import com.alibaba.polardbx.common.utils.logger.Logger;
 import com.alibaba.polardbx.common.utils.logger.LoggerFactory;
+import com.alibaba.polardbx.common.utils.logger.MDC;
 import com.alibaba.polardbx.common.utils.thread.ServerThreadPool;
 import com.alibaba.polardbx.executor.common.ExecutorContext;
-import com.alibaba.polardbx.executor.gms.ColumnarManager;
 import com.alibaba.polardbx.executor.gms.util.ColumnarTransactionUtils;
+import com.alibaba.polardbx.executor.mpp.split.SpecifiedOssSplit;
 import com.alibaba.polardbx.executor.utils.ExecUtils;
-import com.alibaba.polardbx.gms.metadb.table.FilesRecord;
-import com.alibaba.polardbx.optimizer.config.table.TableMeta;
+import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor;
+import com.alibaba.polardbx.gms.metadb.table.FilesRecordSimplifiedWithChecksum;
+import com.alibaba.polardbx.gms.util.MetaDbUtil;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
-import com.alibaba.polardbx.optimizer.partition.PartSpecBase;
 import com.alibaba.polardbx.optimizer.utils.ITransaction;
 import com.alibaba.polardbx.statistics.SQLRecorderLogger;
+import org.jetbrains.annotations.Nullable;
 
 import java.sql.Connection;
 import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import static com.alibaba.polardbx.gms.topology.SystemDbHelper.DEFAULT_DB_NAME;
 
 /**
  * @author yaozhili
@@ -52,27 +70,42 @@ public class CciFastChecker implements ICciChecker {
     private static final Logger logger = LoggerFactory.getLogger(CciFastChecker.class);
 
     private final String schemaName;
-    private final String tableName;
-    private final String indexName;
-    private long columnarHashCode = -1;
-    private long primaryHashCode = -1;
+    protected final String tableName;
+    protected final String indexName;
+    private long columnarHashCode = -1L;
+    private long primaryHashCode = -1L;
+    private final List errors = new ArrayList<>();
+    private final Lock hashLock = new ReentrantLock();
     /**
      * Record connection id in use.
      * If the checking thread is interrupted, kill these connections.
      */
-    private List connIds = new ArrayList<>();
+    private final Set connections = new ConcurrentSkipListSet<>(
+        (o1, o2) -> {
+            if (o1 == null && o2 == null) {
+                return 0;
+            }
+            if (o1 == null) {
+                return -1;
+            }
+            if (o2 == null) {
+                return 1;
+            }
+            return o1.hashCode() - o2.hashCode();
+        }
+    );
 
     private static final String CALCULATE_PRIMARY_HASH =
         "select check_sum_v2(*) as checksum from %s force index(primary)";
     private static final String CALCULATE_COLUMNAR_HASH =
         "select check_sum_v2(*) as checksum from %s force index(%s)";
 
-    private static final String PRIMARY_HINT =
-        "/*+TDDL:WORKLOAD_TYPE=AP ENABLE_MPP=true ENABLE_MASTER_MPP=true ENABLE_ORC_RAW_TYPE_BLOCK=true "
+    protected static final String PRIMARY_HINT =
+        "/*+TDDL:WORKLOAD_TYPE=AP ENABLE_ORC_RAW_TYPE_BLOCK=true "
             + "SOCKET_TIMEOUT=259200000 MPP_TASK_MAX_RUN_TIME=259200000 %s */";
-    private static final String COLUMNAR_HINT =
-        "/*+TDDL:WORKLOAD_TYPE=AP ENABLE_MPP=true ENABLE_MASTER_MPP=true ENABLE_COLUMNAR_OPTIMIZER=true "
-            + "OPTIMIZER_TYPE='columnar' ENABLE_HTAP=true ENABLE_ORC_RAW_TYPE_BLOCK=true "
+    protected static final String COLUMNAR_HINT =
+        "/*+TDDL:WORKLOAD_TYPE=AP ENABLE_COLUMNAR_OPTIMIZER=true "
+            + "OPTIMIZER_TYPE='columnar' ENABLE_HTAP=true ENABLE_BLOCK_CACHE=false ENABLE_ORC_RAW_TYPE_BLOCK=true "
             + "SOCKET_TIMEOUT=259200000 MPP_TASK_MAX_RUN_TIME=259200000 %s */";
 
     public CciFastChecker(String schemaName, String tableName, String indexName) {
@@ -83,8 +116,7 @@ public CciFastChecker(String schemaName, String tableName, String indexName) {
 
     @Override
     public void check(ExecutionContext baseEc, Runnable recoverChangedConfigs) throws Throwable {
-        Pair tso =
-            ColumnarTransactionUtils.getLatestOrcCheckpointTsoFromGms();
+        Pair tso = getCheckTso();
         logger.warn("Check cci using innodb tso " + tso.getKey() + ", columnar tso " + tso.getValue());
 
         ITransaction trx = ExecUtils.createColumnarTransaction(schemaName, baseEc, tso.getValue());
@@ -96,7 +128,7 @@ public void check(ExecutionContext baseEc, Runnable recoverChangedConfigs) throw
 
             // Calculate primary table checksum.
             long start = System.nanoTime();
-            calculatePrimaryChecksum(baseEc, tso.getKey(), connectionManager, recoverChangedConfigs);
+            calculatePrimaryChecksum(baseEc, tso.getKey(), threadPool, connectionManager, recoverChangedConfigs);
             SQLRecorderLogger.ddlLogger.info("[Fast checker] Primary checksum calculated, costing "
                 + ((System.nanoTime() - start) / 1_000_000) + " ms");
 
@@ -110,222 +142,419 @@ public void check(ExecutionContext baseEc, Runnable recoverChangedConfigs) throw
             logger.info("primary checksum: " + primaryHashCode);
             SQLRecorderLogger.ddlLogger.info("columnar checksum: " + columnarHashCode);
             logger.info("columnar checksum: " + columnarHashCode);
+        } catch (Throwable t) {
+            handleError(t);
+            throw t;
         } finally {
             trx.close();
         }
     }
 
-    private void calculatePrimaryChecksum(ExecutionContext baseEc, long tso,
-                                          IInnerConnectionManager connectionManager,
-                                          Runnable recoverChangedConfigs) {
-        // Calculate primary checksum in this thread.
-        try (Connection conn = connectionManager.getConnection(schemaName);
-            Statement stmt = conn.createStatement()) {
+    protected Pair getCheckTso() {
+        return ColumnarTransactionUtils.getLatestOrcCheckpointTsoFromGms();
+    }
 
-            if (conn instanceof IInnerConnection) {
-                ((IInnerConnection) conn).setTimeZone("+8:00");
-            }
+    protected void calculatePrimaryChecksum(ExecutionContext baseEc, long tso,
+                                            ServerThreadPool threadPool,
+                                            IInnerConnectionManager connectionManager,
+                                            Runnable recoverChangedConfigs)
+        throws SQLException, ExecutionException, InterruptedException {
+        try (IInnerConnection daemonConnection = ICciChecker.startDaemonTransaction(
+            connectionManager, schemaName, tableName)) {
+            // Calculate primary checksum in this thread.
+            try (IInnerConnection conn = connectionManager.getConnection(schemaName);
+                Statement stmt = conn.createStatement()) {
+                connections.add(conn);
+                conn.setTimeZone("+8:00");
+
+                String finalSql = getPrimarySql(baseEc, tso);
+                SQLRecorderLogger.ddlLogger.info("primary checksum sql: " + finalSql);
+                logger.info("primary checksum sql: " + finalSql);
 
-            // Build hint.
-            StringBuilder sb = new StringBuilder();
-            long parallelism;
-            if ((parallelism = baseEc.getParamManager().getInt(ConnectionParams.MPP_PARALLELISM)) > 0) {
-                sb.append(" MPP_PARALLELISM=")
-                    .append(parallelism);
+                executeSqlAndInterruptIfDdlCanceled(threadPool, stmt, finalSql, baseEc, true);
+            } catch (Throwable t) {
+                handleError(t);
+                throw t;
+            } finally {
+                connections.clear();
+                if (null != recoverChangedConfigs) {
+                    recoverChangedConfigs.run();
+                }
             }
-            if ((parallelism = baseEc.getParamManager().getInt(ConnectionParams.PARALLELISM)) > 0) {
-                sb.append(" PARALLELISM=")
-                    .append(parallelism);
+            try {
+                daemonConnection.close();
+            } catch (Throwable t) {
+                // ignore.
             }
-            sb.append(" SNAPSHOT_TS=")
-                .append(tso);
-            sb.append(" TRANSACTION_POLICY=TSO");
-            String hint = String.format(PRIMARY_HINT, sb);
-
-            String sql = String.format(CALCULATE_PRIMARY_HASH, tableName);
+        }
+    }
 
-            // Assert using logical view as table scan.
-            sql = hint + sql;
-            SQLRecorderLogger.ddlLogger.info("primary checksum sql: " + sql);
-            logger.info("primary checksum sql: " + sql);
+    private void executeSqlAndInterruptIfDdlCanceled(ServerThreadPool threadPool, Statement stmt, String finalSql,
+                                                     ExecutionContext baseEc, boolean isPrimary)
+        throws InterruptedException, ExecutionException {
+        Future future = threadPool.submit(null, null, () -> {
+            try {
+                ResultSet rs = stmt.executeQuery(finalSql);
+                if (rs.next()) {
+                    if (isPrimary) {
+                        primaryHashCode = rs.getLong("checksum");
+                    } else {
+                        columnarHashCode = rs.getLong("checksum");
+                    }
+                }
+                return null;
+            } catch (SQLException e) {
+                handleError(e);
+                return e.getMessage();
+            }
+        });
+
+        String error = null;
+        while (true) {
+            try {
+                error = future.get(1, TimeUnit.SECONDS);
+                break;
+            } catch (TimeoutException e) {
+                // ignore.
+            }
 
-            ResultSet rs = stmt.executeQuery(sql);
-            if (rs.next()) {
-                primaryHashCode = rs.getLong("checksum");
+            if (baseEc.getDdlContext().isInterrupted()) {
+                future.cancel(true);
+                if (isPrimary) {
+                    primaryHashCode = -1;
+                } else {
+                    columnarHashCode = -1;
+                }
+                error = String.format("Interrupted when checking columnar index %s.%s", tableName, indexName);
+                break;
             }
-        } catch (Throwable t) {
-            SQLRecorderLogger.ddlLogger.error(
-                String.format("Error occurs when checking columnar index %s.%s", tableName, indexName), t);
+        }
+        if (null != error) {
             throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER,
-                "Fast CCI checker error: " + t.getMessage());
-        } finally {
-            if (null != recoverChangedConfigs) {
-                recoverChangedConfigs.run();
-            }
+                "Fast CCI checker error: " + error);
         }
     }
 
-    private void calculateColumnarChecksum(ExecutionContext baseEc,
-                                           long tso,
-                                           ServerThreadPool threadPool,
-                                           IInnerConnectionManager connectionManager) {
-        // 1. Get all orc files of this CCI.
-        ColumnarManager columnarManager = ColumnarManager.getInstance();
-        TableMeta tableMeta = baseEc.getSchemaManager(schemaName).getTable(indexName);
-        List orcFiles = new ArrayList<>();
-        List csvFiles = new ArrayList<>();
-        tableMeta.getPartitionInfo()
-            .getPartitionBy()
-            .getPartitions()
-            .stream()
-            // Get each partition name.
-            .map(PartSpecBase::getName)
-            // Get files from each partition.
-            .forEach(partitionName -> {
-                Pair, List> orcAndCsv =
-                    columnarManager.findFileNames(tso, schemaName, indexName, partitionName);
-                orcFiles.addAll(orcAndCsv.getKey());
-                csvFiles.addAll(orcAndCsv.getValue());
-            });
-        // RTT 1: get file records.
-        List filesRecords = ExecUtils.getFilesMetaByNames(orcFiles);
-        if (filesRecords.size() != orcFiles.size()) {
-            throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER, "The number of orc files not match");
-        }
-
+    protected void calculateColumnarChecksum(ExecutionContext baseEc,
+                                             long tso,
+                                             ServerThreadPool threadPool,
+                                             IInnerConnectionManager connectionManager) throws SQLException {
+        // 1. Get all orc/csv files of this CCI.
+        long startTime = System.nanoTime();
+        final long tableId = ICciChecker.getTableId(schemaName, indexName);
+        SQLRecorderLogger.ddlLogger.info(
+            "[Fast checker] Get table id cost: " + (System.nanoTime() - startTime) / 1_000_000 + " ms");
+
+        startTime = System.nanoTime();
+        List filesRecords = ICciChecker.getFilesRecords(tso, tableId, schemaName);
+        SQLRecorderLogger.ddlLogger.info(
+            "[Fast checker] Get all files cost: " + (System.nanoTime() - startTime) / 1_000_000 + " ms");
+
+        Map> orcFiles = new HashMap<>();
+        Set deltaFiles = new HashSet<>();
         // 2. Filter out files needed to be process, and by the way calculate cached checksum.
         final RevisableOrderInvariantHash hasher = new RevisableOrderInvariantHash();
-        final List toBeProcessedFiles = new ArrayList<>();
-        for (FilesRecord filesRecord : filesRecords) {
-            hasher.add(filesRecord.checksum).remove(0);
-            if (0 != filesRecord.deletedChecksum) {
-                toBeProcessedFiles.add(filesRecord.fileName);
+        final Map> toBeProcessedOrcFiles = new HashMap<>();
+        for (FilesRecordSimplifiedWithChecksum filesRecord : filesRecords) {
+            String fileName = filesRecord.fileName;
+            String partitionName = filesRecord.partitionName.toLowerCase();
+            ColumnarFileType columnarFileType =
+                ColumnarFileType.of(fileName.substring(fileName.lastIndexOf('.') + 1));
+            switch (columnarFileType) {
+            case ORC:
+                orcFiles.computeIfAbsent(partitionName, k -> new HashSet<>()).add(fileName);
+                hasher.add(filesRecord.checksum).remove(0);
+                if (0 != filesRecord.deletedChecksum) {
+                    toBeProcessedOrcFiles.computeIfAbsent(partitionName, k -> new HashSet<>()).add(fileName);
+                }
+                break;
+            case CSV:
+            case DEL:
+                deltaFiles.add(fileName);
+                break;
+            default:
+                logger.warn("Increment check found unexpected file: " + fileName);
+                break;
             }
         }
-
         SQLRecorderLogger.ddlLogger.info("all orc files checksum: " + hasher.getResult());
         logger.info("all orc files checksum: " + hasher.getResult());
 
-        Future future = null;
-        // 3. RTT 2: Calculate deleted checksum.
-        if (!toBeProcessedFiles.isEmpty()) {
-            future = threadPool.submit(null, null, () -> {
-                try (Connection conn = connectionManager.getConnection(schemaName);
-                    Statement stmt = conn.createStatement()) {
-                    if (conn instanceof IInnerConnection) {
-                        ((IInnerConnection) conn).addExecutionContextInjectHook(
-                            (ec) -> {
-                                ((ExecutionContext) ec).setCheckingCci(true);
-                                ((ExecutionContext) ec).setReadOrcFiles(toBeProcessedFiles);
-                            });
-                    }
-                    StringBuilder sb =
-                        new StringBuilder(
-                            " READ_ORC_ONLY=true ENABLE_ORC_DELETED_SCAN=true ");
-                    long parallelism;
-                    if ((parallelism = baseEc.getParamManager().getInt(ConnectionParams.MPP_PARALLELISM)) > 0) {
-                        sb.append(" MPP_PARALLELISM=")
-                            .append(parallelism);
+        // csv/del file name -> pair(partition name, end pos)
+        startTime = System.nanoTime();
+        Map> tuples = new HashMap<>();
+        try (Connection connection = MetaDbUtil.getConnection()) {
+            ColumnarAppendedFilesAccessor accessor = new ColumnarAppendedFilesAccessor();
+            accessor.setConnection(connection);
+            accessor.queryByFileNamesAndTso(deltaFiles, tso).forEach(record -> {
+                String fileName = record.getFileName();
+                long start = record.getAppendOffset();
+                long end = start + record.getAppendLength();
+                String partName = record.getPartName();
+                tuples.put(fileName, new Pair<>(partName, end));
+            });
+        } catch (Throwable t) {
+            logger.error("calculate columnar checksum failed.", t);
+            throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER, t, "Failed to diff csv files");
+        }
+        SQLRecorderLogger.ddlLogger.info(
+            "[Fast checker] Get all delta files info cost: " + (System.nanoTime() - startTime) / 1_000_000 + " ms");
+
+        Map deltas = new HashMap<>();
+        AtomicBoolean hasCsvFiles = new AtomicBoolean(false);
+        for (Map.Entry> deltaFileEntry : tuples.entrySet()) {
+            String fileName = deltaFileEntry.getKey();
+            String partName = deltaFileEntry.getValue().getKey();
+            long endPos = deltaFileEntry.getValue().getValue();
+            deltas.compute(partName, (k, v) -> {
+                if (v == null) {
+                    v = new SpecifiedOssSplit.DeltaReadWithPositionOption(tso, -1, -1, tableId);
+                }
+                ColumnarFileType columnarFileType =
+                    ColumnarFileType.of(fileName.substring(fileName.lastIndexOf('.') + 1));
+                SpecifiedOssSplit.DeltaReadWithPositionOption delta = (SpecifiedOssSplit.DeltaReadWithPositionOption) v;
+                switch (columnarFileType) {
+                case CSV:
+                    hasCsvFiles.set(true);
+                    if (delta.getCsvFiles() == null) {
+                        delta.setCsvFiles(new ArrayList<>());
+                        delta.setCsvStartPos(new ArrayList<>());
+                        delta.setCsvEndPos(new ArrayList<>());
                     }
-                    if ((parallelism = baseEc.getParamManager().getInt(ConnectionParams.PARALLELISM)) > 0) {
-                        sb.append(" PARALLELISM=")
-                            .append(parallelism);
+                    delta.getCsvFiles().add(fileName);
+                    delta.getCsvStartPos().add(0L);
+                    delta.getCsvEndPos().add(endPos);
+                    break;
+                case DEL:
+                    if (delta.getDelFiles() == null) {
+                        delta.setDelFiles(new ArrayList<>());
+                        delta.setDelBeginPos(new ArrayList<>());
+                        delta.setDelEndPos(new ArrayList<>());
                     }
+                    delta.getDelFiles().add(fileName);
+                    delta.getDelBeginPos().add(0L);
+                    delta.getDelEndPos().add(endPos);
+                    break;
+                default:
+                    logger.warn("Cci fast check found unexpected file: " + fileName);
+                    break;
+                }
+                return v;
+            });
+        }
 
-                    String hint = String.format(COLUMNAR_HINT, sb);
-                    String sql = hint + String.format(CALCULATE_COLUMNAR_HASH, tableName, indexName);
+        CompletableFuture deletedChecksumFuture = null;
+        // 3. RTT 2: Calculate deleted checksum.
+        if (!toBeProcessedOrcFiles.isEmpty()) {
+            deletedChecksumFuture = CompletableFuture.supplyAsync(
+                () -> calDeletedChecksum(baseEc, connectionManager, hasher,
+                    toBeProcessedOrcFiles, deltas), threadPool);
+        }
 
-                    SQLRecorderLogger.ddlLogger.info("columnar deleted checksum sql: " + sql);
-                    logger.info("columnar deleted checksum sql: " + sql);
+        // 4. RTT 2: Calculate csv part in this thread.
+        CompletableFuture csvFuture = null;
+        if (hasCsvFiles.get()) {
+            csvFuture = CompletableFuture.supplyAsync(
+                () -> calCsvChecksum(baseEc, connectionManager, hasher, deltas), threadPool);
+        }
 
-                    ResultSet rs = stmt.executeQuery(sql);
-                    if (rs.next()) {
-                        long deletedChecksum = rs.getLong("checksum");
-                        SQLRecorderLogger.ddlLogger.info("columnar deleted checksum: " + deletedChecksum);
-                        logger.info("columnar deleted checksum: " + deletedChecksum);
-                        hasher.remove(deletedChecksum).add(0);
-                    } else {
-                        return "Not found deleted checksum in result set.";
+        // Combine these two tasks.
+        CompletableFuture completableFuture = null;
+        if (null == deletedChecksumFuture) {
+            if (null != csvFuture) {
+                completableFuture = csvFuture;
+            }
+        } else {
+            if (null == csvFuture) {
+                completableFuture = deletedChecksumFuture;
+            } else {
+                completableFuture = deletedChecksumFuture.thenCombine(csvFuture, (s1, s2) -> {
+                    if (null == s1 && null == s2) {
+                        return null;
                     }
+                    return s1 + "\n" + s2;
+                });
+            }
+        }
 
-                    if (conn instanceof IInnerConnection) {
-                        ((IInnerConnection) conn).clearExecutionContextInjectHooks();
-                    }
+        // If ddl is paused, interrupt tasks.
+        String error = null;
+        if (null != completableFuture) {
+            while (true) {
+                try {
+                    error = completableFuture.get(1, TimeUnit.SECONDS);
+                    break;
+                } catch (TimeoutException e) {
+                    // ignore.
                 } catch (Throwable t) {
-                    SQLRecorderLogger.ddlLogger.error(t);
-                    return "Error occurs, caused by " + t.getMessage();
+                    error = t.getMessage();
+                    break;
                 }
-                return null;
-            });
-        }
 
-        // 4. RTT 2: Calculate csv part in this thread.
-        if (!csvFiles.isEmpty()) {
-            try (Connection conn = connectionManager.getConnection(schemaName);
-                Statement stmt = conn.createStatement()) {
-                if (conn instanceof IInnerConnection) {
-                    ((IInnerConnection) conn).addExecutionContextInjectHook(
-                        (ec) -> ((ExecutionContext) ec).setCheckingCci(true));
-                }
-                StringBuilder sb = new StringBuilder(" READ_CSV_ONLY=true");
-                long parallelism;
-                if ((parallelism = baseEc.getParamManager().getInt(ConnectionParams.MPP_PARALLELISM)) > 0) {
-                    sb.append(" MPP_PARALLELISM=")
-                        .append(parallelism);
-                }
-                if ((parallelism = baseEc.getParamManager().getInt(ConnectionParams.PARALLELISM)) > 0) {
-                    sb.append(" PARALLELISM=")
-                        .append(parallelism);
+                if (baseEc.getDdlContext().isInterrupted()) {
+                    completableFuture.cancel(true);
+                    error = String.format("Interrupted when checking columnar index %s.%s", tableName, indexName);
+                    break;
                 }
-                sb.append(" SNAPSHOT_TS=")
-                    .append(tso)
-                    .append(" ");
+            }
+        }
 
-                String hint = String.format(COLUMNAR_HINT, sb);
-                String sql = hint + String.format(CALCULATE_COLUMNAR_HASH, tableName, indexName);
+        if (null != error) {
+            for (IInnerConnection connection : connections) {
+                connection.close();
+            }
+            columnarHashCode = -1;
+            throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER,
+                "Fast CCI checker error: " + error);
+        } else {
+            columnarHashCode = hasher.getResult();
+        }
 
-                SQLRecorderLogger.ddlLogger.info("columnar csv checksum sql: " + sql);
-                logger.info("columnar csv checksum sql: " + sql);
+        if (-1 != columnarHashCode && -1 != primaryHashCode && columnarHashCode != primaryHashCode) {
+            // Use naive method to check again.
+            calColumnarChecksumInNaiveMethod(orcFiles, deltas, baseEc, tso, threadPool, connectionManager);
+        }
+    }
 
-                ResultSet rs = stmt.executeQuery(sql);
-                if (rs.next()) {
-                    long csvChecksum = rs.getLong("checksum");
-                    SQLRecorderLogger.ddlLogger.info("columnar csv checksum: " + csvChecksum);
-                    logger.info("columnar csv checksum: " + csvChecksum);
-                    hasher.add(csvChecksum).remove(0);
-                } else {
-                    throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER, "not found any csv checksum.");
+    @Nullable
+    private String calCsvChecksum(ExecutionContext baseEc, IInnerConnectionManager connectionManager,
+                                  RevisableOrderInvariantHash hasher, Map deltas) {
+        final Map savedMdcContext = MDC.getCopyOfContextMap();
+        MDC.put(MDC.MDC_KEY_APP, DEFAULT_DB_NAME);
+        try (IInnerConnection conn = connectionManager.getConnection(schemaName);
+            Statement stmt = conn.createStatement()) {
+            connections.add(conn);
+            conn.addExecutionContextInjectHook(
+                e -> {
+                    ((ExecutionContext) e).setCheckingCci(true);
+                    ((ExecutionContext) e).setReadDeltaFiles(deltas);
                 }
+            );
+            String sql = getCsvSql(baseEc);
 
-                if (conn instanceof IInnerConnection) {
-                    ((IInnerConnection) conn).clearExecutionContextInjectHooks();
-                }
-            } catch (Throwable t) {
-                if (null != future) {
-                    future.cancel(true);
+            SQLRecorderLogger.ddlLogger.info("columnar csv checksum sql: " + sql);
+            logger.info("columnar csv checksum sql: " + sql);
+
+            long startTime = System.nanoTime();
+            ResultSet rs = stmt.executeQuery(sql);
+            if (rs.next()) {
+                long csvChecksum = rs.getLong("checksum");
+                SQLRecorderLogger.ddlLogger.info("columnar csv checksum: " + csvChecksum);
+                logger.info("columnar csv checksum: " + csvChecksum);
+                hashLock.lock();
+                try {
+                    hasher.add(csvChecksum).remove(0);
+                } finally {
+                    hashLock.unlock();
                 }
-                SQLRecorderLogger.ddlLogger.error(t);
-                throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER, t.getMessage());
+            } else {
+                throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER, "not found any csv checksum.");
             }
+            SQLRecorderLogger.ddlLogger.info(
+                "Calculate csv checksum cost: " + (System.nanoTime() - startTime) / 1_000_000 + " ms");
+
+            conn.clearExecutionContextInjectHooks();
+            connections.remove(conn);
+            return null;
+        } catch (Throwable t) {
+            handleError(t);
+            return t.getMessage();
+        } finally {
+            MDC.setContextMap(savedMdcContext);
         }
+    }
 
-        try {
-            String error = null == future ? null : future.get();
-            if (null != error) {
-                throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER, error);
+    @Nullable
+    private String calDeletedChecksum(ExecutionContext baseEc,
+                                      IInnerConnectionManager connectionManager,
+                                      RevisableOrderInvariantHash hasher,
+                                      Map> toBeProcessedOrcFiles,
+                                      Map deltas) {
+        final Map savedMdcContext = MDC.getCopyOfContextMap();
+        MDC.put(MDC.MDC_KEY_APP, DEFAULT_DB_NAME);
+        try (IInnerConnection conn = connectionManager.getConnection(schemaName);
+            Statement stmt = conn.createStatement()) {
+            connections.add(conn);
+            conn.addExecutionContextInjectHook(
+                (ec) -> {
+                    ((ExecutionContext) ec).setCheckingCci(true);
+                    ((ExecutionContext) ec).setReadOrcFiles(toBeProcessedOrcFiles);
+                    ((ExecutionContext) ec).setReadDeltaFiles(deltas);
+                });
+            String sql = getDeletedSql(baseEc);
+
+            SQLRecorderLogger.ddlLogger.info("columnar deleted checksum sql: " + sql);
+            logger.info("columnar deleted checksum sql: " + sql);
+
+            long startTime = System.nanoTime();
+            ResultSet rs = stmt.executeQuery(sql);
+            if (rs.next()) {
+                long deletedChecksum = rs.getLong("checksum");
+                SQLRecorderLogger.ddlLogger.info("columnar deleted checksum: " + deletedChecksum);
+                logger.info("columnar deleted checksum: " + deletedChecksum);
+                hashLock.lock();
+                try {
+                    hasher.remove(deletedChecksum).add(0);
+                } finally {
+                    hashLock.unlock();
+                }
+            } else {
+                return "Not found deleted checksum in result set.";
             }
+            SQLRecorderLogger.ddlLogger.info(
+                "Calculate deleted checksum cost: " + (System.nanoTime() - startTime) / 1_000_000 + " ms");
+
+            conn.clearExecutionContextInjectHooks();
+            connections.remove(conn);
+        } catch (Throwable t) {
+            handleError(t);
+            return "Error occurs, caused by " + t.getMessage();
+        } finally {
+            MDC.setContextMap(savedMdcContext);
+        }
+        return null;
+    }
+
+    private void calColumnarChecksumInNaiveMethod(Map> orcFiles,
+                                                  Map deltas,
+                                                  ExecutionContext baseEc, long tso, ServerThreadPool threadPool,
+                                                  IInnerConnectionManager connectionManager) {
+        try (IInnerConnection conn = connectionManager.getConnection(schemaName);
+            Statement stmt = conn.createStatement()) {
+            conn.addExecutionContextInjectHook(
+                (ec) -> {
+                    ((ExecutionContext) ec).setCheckingCci(true);
+                    ((ExecutionContext) ec).setReadOrcFiles(orcFiles);
+                    ((ExecutionContext) ec).setReadDeltaFiles(deltas);
+                });
+            connections.add(conn);
+
+            String finalSql = getColumnarNaiveSql(baseEc);
+            SQLRecorderLogger.ddlLogger.info("columnar naive checksum sql: " + finalSql);
+            logger.info("columnar naive checksum sql: " + finalSql);
+
+            executeSqlAndInterruptIfDdlCanceled(threadPool, stmt, finalSql, baseEc, false);
+            conn.clearExecutionContextInjectHooks();
+            connections.remove(conn);
         } catch (Throwable t) {
-            SQLRecorderLogger.ddlLogger.error(t);
-            future.cancel(true);
-            throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER, t.getMessage());
+            handleError(t);
+            throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER,
+                "Fast CCI checker error: " + t.getMessage());
         }
+    }
 
-        columnarHashCode = hasher.getResult();
+    protected void handleError(Throwable t) {
+        SQLRecorderLogger.ddlLogger.error(String.format(
+            "[Fast CCI Checker] Error occurs when checking columnar index %s.%s", tableName, indexName), t);
+        errors.add(t.getMessage());
     }
 
     @Override
     public boolean getCheckReports(Collection reports) {
         boolean success = true;
+        if (!errors.isEmpty()) {
+            reports.addAll(errors);
+        }
         if (-1 == primaryHashCode || primaryHashCode != columnarHashCode) {
             // Check fail.
             reports.add("Inconsistency detected: primary hash: " + primaryHashCode
@@ -334,4 +563,41 @@ public boolean getCheckReports(Collection reports) {
         }
         return success;
     }
+
+    protected String getPrimarySql(ExecutionContext baseEc, long tso) {
+        StringBuilder sb = new StringBuilder();
+        ICciChecker.setBasicHint(baseEc, sb);
+        sb.append(" SNAPSHOT_TS=")
+            .append(tso);
+        sb.append(" TRANSACTION_POLICY=TSO");
+        String hint = String.format(PRIMARY_HINT, sb);
+        return hint + String.format(CALCULATE_PRIMARY_HASH, tableName);
+    }
+
+    protected String getCsvSql(ExecutionContext baseEc) {
+        StringBuilder sb = new StringBuilder(" READ_CSV_ONLY=true");
+        ICciChecker.setBasicHint(baseEc, sb);
+
+        String hint = String.format(COLUMNAR_HINT, sb);
+        return hint + String.format(CALCULATE_COLUMNAR_HASH, tableName, indexName);
+    }
+
+    protected String getDeletedSql(ExecutionContext baseEc) {
+        StringBuilder sb = new StringBuilder(" READ_ORC_ONLY=true ENABLE_OSS_DELETED_SCAN=true ");
+        ICciChecker.setBasicHint(baseEc, sb);
+
+        String hint = String.format(COLUMNAR_HINT, sb);
+        return hint + String.format(CALCULATE_COLUMNAR_HASH, tableName, indexName);
+    }
+
+    protected String getColumnarNaiveSql(ExecutionContext baseEc) {
+        StringBuilder sb = new StringBuilder(" READ_SPECIFIED_COLUMNAR_FILES=true ");
+        ICciChecker.setBasicHint(baseEc, sb);
+        String hint = String.format(COLUMNAR_HINT, sb);
+        return hint + String.format(CALCULATE_COLUMNAR_HASH, tableName, indexName);
+    }
+
+    public long getColumnarHashCode() {
+        return columnarHashCode;
+    }
 }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciIncrementalChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciIncrementalChecker.java
new file mode 100644
index 000000000..e466d45f8
--- /dev/null
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciIncrementalChecker.java
@@ -0,0 +1,368 @@
+package com.alibaba.polardbx.executor.columnar.checker;
+
+import com.alibaba.polardbx.common.IInnerConnection;
+import com.alibaba.polardbx.common.IInnerConnectionManager;
+import com.alibaba.polardbx.common.exception.TddlRuntimeException;
+import com.alibaba.polardbx.common.exception.code.ErrorCode;
+import com.alibaba.polardbx.common.oss.ColumnarFileType;
+import com.alibaba.polardbx.common.oss.IDeltaReadOption;
+import com.alibaba.polardbx.common.properties.DynamicConfig;
+import com.alibaba.polardbx.common.utils.logger.Logger;
+import com.alibaba.polardbx.common.utils.logger.LoggerFactory;
+import com.alibaba.polardbx.common.utils.logger.MDC;
+import com.alibaba.polardbx.common.utils.thread.ServerThreadPool;
+import com.alibaba.polardbx.executor.common.ExecutorContext;
+import com.alibaba.polardbx.executor.mpp.split.SpecifiedOssSplit;
+import com.alibaba.polardbx.executor.utils.ExecUtils;
+import com.alibaba.polardbx.gms.metadb.table.FilesRecordSimplified;
+import com.alibaba.polardbx.gms.metadb.table.FilesRecordSimplifiedWithChecksum;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.statistics.SQLRecorderLogger;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static com.alibaba.polardbx.gms.topology.SystemDbHelper.DEFAULT_DB_NAME;
+
+/**
+ * @author yaozhili
+ */
+public class CciIncrementalChecker implements ICciChecker {
+    private static final Logger logger = LoggerFactory.getLogger(CciIncrementalChecker.class);
+    private final String schemaName;
+    private final String tableName;
+    private final String indexName;
+    private long finalCount;
+    private final List errors = new ArrayList<>();
+    /**
+     * Record connection id in use.
+     * If the checking thread is interrupted, kill these connections.
+     */
+    private final Set connections = new ConcurrentSkipListSet<>(
+        (o1, o2) -> {
+            if (o1 == null && o2 == null) {
+                return 0;
+            }
+            if (o1 == null) {
+                return -1;
+            }
+            if (o2 == null) {
+                return 1;
+            }
+            return o1.hashCode() - o2.hashCode();
+        }
+    );
+
+    private static final String COLUMNAR_HINT =
+        "/*+TDDL:WORKLOAD_TYPE=AP ENABLE_MPP=true ENABLE_MASTER_MPP=true ENABLE_COLUMNAR_OPTIMIZER=true "
+            + "OPTIMIZER_TYPE='columnar' ENABLE_HTAP=true ENABLE_BLOCK_CACHE=false CCI_INCREMENTAL_CHECK=true "
+            + "SOCKET_TIMEOUT=259200000 MPP_TASK_MAX_RUN_TIME=259200000 %s */";
+
+    public CciIncrementalChecker(String schemaName, String tableName, String indexName) {
+        this.schemaName = schemaName;
+        this.tableName = tableName;
+        this.indexName = indexName;
+    }
+
+    @Override
+    public void check(ExecutionContext ec, long tsoV0, long tsoV1, long innodbTso) throws Throwable {
+        SQLRecorderLogger.ddlLogger.info("[Incremental checker] Check cci increment for " + schemaName + "."
+            + indexName + " " + tsoV0 + " " + tsoV1 + " " + innodbTso);
+        long begin = System.nanoTime();
+        ExecutorContext executorContext = ExecutorContext.getContext(schemaName);
+        IInnerConnectionManager connectionManager = executorContext.getInnerConnectionManager();
+        try (IInnerConnection conn = connectionManager.getConnection(schemaName)) {
+            connections.add(conn);
+
+            ResultSet rs = getIncrementalInsertData(ec, tsoV0, tsoV1, conn);
+            if (null == rs || !rs.next()) {
+                return;
+            }
+
+            AtomicBoolean finish = new AtomicBoolean(false);
+            int parallelism = DynamicConfig.getInstance().getCciIncrementalCheckParallelism();
+            int columnCount = rs.getMetaData().getColumnCount();
+            final List columnNames = new ArrayList<>(columnCount);
+            for (int i = 1; i <= columnCount; i++) {
+                columnNames.add(rs.getMetaData().getColumnName(i));
+            }
+            String concatColumnName = "(" + String.join(",", columnNames) + ")";
+            int batchSize = DynamicConfig.getInstance().getCciIncrementalCheckBatchSize();
+            // Each task like: ((0, 0, 0), (1, 1, 1), (2, 2, 2))
+            ConcurrentLinkedQueue checkInsertValues = new ConcurrentLinkedQueue<>();
+            List> futures = new ArrayList<>(parallelism);
+            ServerThreadPool threadPool = executorContext.getTopologyExecutor().getExecutorService();
+            AtomicLong count = new AtomicLong(0);
+            // Consumers.
+            addConsumers(innodbTso, connectionManager, finish, parallelism, concatColumnName, checkInsertValues,
+                futures,
+                threadPool, count);
+            Throwable exception = null;
+            // Producer.
+            int expectedCount = 0;
+            try {
+                // Already rs.next(), just get the result row.
+                do {
+                    List values = new ArrayList<>(batchSize);
+                    int currentBatchSize = 0;
+                    do {
+                        expectedCount++;
+                        List value = new ArrayList<>(columnCount);
+                        for (int i = 0; i < columnCount; i++) {
+                            value.add("'" + rs.getString(columnNames.get(i)) + "'");
+                        }
+                        values.add("(" + String.join(",", value) + ")");
+                        currentBatchSize++;
+                        if (DynamicConfig.getInstance().isEnableColumnarDebug()) {
+                            logger.info("Incremental check found value: "
+                                + "(" + String.join(",", value) + ")");
+                        }
+                    } while (currentBatchSize < batchSize && rs.next());
+                    checkInsertValues.add("(" + String.join(",", values) + ")");
+                } while (rs.next());
+            } catch (Throwable t) {
+                exception = t;
+            } finally {
+                finish.set(true);
+            }
+
+            checkException(futures, exception);
+
+            // Wait all tasks.
+            exception = waitAllTasks(ec, futures);
+
+            checkException(futures, exception);
+
+            if (expectedCount != count.get()) {
+                this.errors.add("Incremental check failed, expected columnar count: " + expectedCount
+                    + ", actual row-store count: " + count.get());
+            } else {
+                this.finalCount = count.get();
+            }
+        } finally {
+            connections.clear();
+            SQLRecorderLogger.ddlLogger.info(
+                "[Incremental checker] Total cost: " + (System.nanoTime() - begin) / 1_000_000 + " ms");
+        }
+    }
+
+    private Throwable waitAllTasks(ExecutionContext ec, List> futures)
+        throws Throwable {
+        Throwable exception = null;
+        while (true) {
+            boolean done = true;
+            for (Future future : futures) {
+                try {
+                    Throwable t = future.get(1000, java.util.concurrent.TimeUnit.MILLISECONDS);
+                    if (null != t) {
+                        exception = t;
+                        break;
+                    }
+                } catch (TimeoutException timeoutException) {
+                    // Ignore timeout exception, this task is not finished yet.
+                    done = false;
+                } catch (Throwable t) {
+                    exception = t;
+                    break;
+                }
+            }
+
+            // If one task fails, cancel all tasks.
+            checkException(futures, exception);
+
+            if (done) {
+                // All tasks succeed.
+                break;
+            }
+
+            // Check ddl interrupt flag.
+            if (ec.getDdlContext().isInterrupted()) {
+                exception = new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER,
+                    "Incremental check is interrupted.");
+                break;
+            }
+        }
+        return exception;
+    }
+
+    private void addConsumers(long tso, IInnerConnectionManager connectionManager, AtomicBoolean finish,
+                              int parallelism, String concatColumnName, ConcurrentLinkedQueue checkInsertValues,
+                              List> futures, ServerThreadPool threadPool, AtomicLong count) {
+        for (int i = 0; i < parallelism; i++) {
+            futures.add(threadPool.submit(null, null, () -> {
+                final Map savedMdcContext = MDC.getCopyOfContextMap();
+                MDC.put(MDC.MDC_KEY_APP, DEFAULT_DB_NAME);
+                String sql = null;
+                try {
+                    String values = null;
+                    // Must get from work queue first, and then check finish flag.
+                    while (null != (values = checkInsertValues.poll()) || !finish.get()) {
+                        if (null == values) {
+                            Thread.sleep(1000);
+                            continue;
+                        }
+                        sql = "select count(0) from " + tableName + " as of tso " + tso + " where "
+                            + concatColumnName + " in " + values;
+                        try (IInnerConnection conn = connectionManager.getConnection(schemaName);
+                            Statement stmt = conn.createStatement()) {
+                            connections.add(conn);
+                            ResultSet countRs = stmt.executeQuery(sql);
+                            if (countRs.next()) {
+                                count.addAndGet(countRs.getLong(1));
+                            }
+                            connections.remove(conn);
+                        }
+                    }
+                } catch (Throwable t) {
+                    logger.error("Check cci incremental insert data failed. sql: " + sql, t);
+                    return t;
+                } finally {
+                    MDC.setContextMap(savedMdcContext);
+                }
+                return null;
+            }));
+        }
+    }
+
+    private void checkException(List> futures, Throwable exception) throws Throwable {
+        if (null != exception) {
+            futures.forEach(future -> future.cancel(true));
+            // Force close all connections.
+            connections.forEach(conn -> {
+                try {
+                    conn.close();
+                } catch (Throwable e) {
+                    // ignore
+                }
+            });
+            throw exception;
+        }
+    }
+
+    private ResultSet getIncrementalInsertData(ExecutionContext ec, long tsoV0, long tsoV1,
+                                               IInnerConnection conn) throws SQLException {
+        // partition_name -> files in this partition
+        Map> orcFiles;
+        Map deltaFiles;
+        // Get v0 orc files.
+        long startTime = System.nanoTime();
+        final long tableId = ICciChecker.getTableId(schemaName, indexName);
+        SQLRecorderLogger.ddlLogger.info(
+            "[Incremental checker] Get table id cost: " + (System.nanoTime() - startTime) / 1_000_000 + " ms");
+
+        startTime = System.nanoTime();
+        Map> orcFilesV0 = new HashMap<>();
+        List filesRecords = ICciChecker.getFilesRecords(tsoV0, tableId, schemaName);
+        SQLRecorderLogger.ddlLogger.info(
+            "[Incremental checker] Get all files cost: " + (System.nanoTime() - startTime) / 1_000_000 + " ms");
+
+        for (FilesRecordSimplified filesRecord : filesRecords) {
+            String fileName = filesRecord.fileName;
+            String partitionName = filesRecord.partitionName.toLowerCase();
+            ColumnarFileType columnarFileType =
+                ColumnarFileType.of(fileName.substring(fileName.lastIndexOf('.') + 1));
+            if (Objects.requireNonNull(columnarFileType) == ColumnarFileType.ORC) {
+                orcFilesV0.computeIfAbsent(partitionName, k -> new HashSet<>()).add(fileName);
+            }
+        }
+
+        // Get v1 orc/csv/del files.
+        Map> orcFilesV1 = new HashMap<>();
+        Set deltaFilesV1 = new HashSet<>();
+        filesRecords = ICciChecker.getFilesRecords(tsoV1, tableId, schemaName);
+        for (FilesRecordSimplified filesRecord : filesRecords) {
+            String fileName = filesRecord.fileName;
+            String partitionName = filesRecord.partitionName.toLowerCase();
+            ColumnarFileType columnarFileType =
+                ColumnarFileType.of(fileName.substring(fileName.lastIndexOf('.') + 1));
+            switch (columnarFileType) {
+            case ORC:
+                orcFilesV1.computeIfAbsent(partitionName, k -> new HashSet<>()).add(fileName);
+                break;
+            case CSV:
+            case DEL:
+                deltaFilesV1.add(fileName);
+                break;
+            default:
+                logger.warn("Increment check found unexpected file: " + fileName);
+                break;
+            }
+        }
+
+        // Calculate the difference.
+        orcFiles = ExecUtils.diffOrcFiles(orcFilesV0, orcFilesV1);
+        startTime = System.nanoTime();
+        deltaFiles = ExecUtils.diffDeltaFiles(tsoV0, tsoV1, tableId, deltaFilesV1);
+        SQLRecorderLogger.ddlLogger.info(
+            "[Incremental checker] Get all delta files info cost: "
+                + (System.nanoTime() - startTime) / 1_000_000 + " ms");
+
+        // Make sure all partitions in orcFiles has corresponding delta files.
+        for (Map.Entry> entry : orcFiles.entrySet()) {
+            String partitionName = entry.getKey();
+            deltaFiles.putIfAbsent(partitionName,
+                new SpecifiedOssSplit.DeltaReadWithPositionOption(tsoV1, tsoV0, tsoV1, tableId));
+        }
+
+        if (orcFiles.isEmpty() && deltaFiles.isEmpty()) {
+            // v0 and v1 are identical.
+            return null;
+        }
+
+        ResultSet rs = null;
+        try (Statement stmt = conn.createStatement()) {
+            conn.addExecutionContextInjectHook(
+                (e) -> {
+                    ((ExecutionContext) e).setCheckingCci(true);
+                    ((ExecutionContext) e).setReadOrcFiles(orcFiles);
+                    ((ExecutionContext) e).setReadDeltaFiles(deltaFiles);
+                });
+            StringBuilder sb = new StringBuilder();
+            ICciChecker.setBasicHint(ec, sb);
+            sb.append(" SNAPSHOT_TS=")
+                .append(tsoV1)
+                .append(" ");
+
+            String hint = String.format(COLUMNAR_HINT, sb);
+            startTime = System.nanoTime();
+            rs = stmt.executeQuery(hint + " select * from " + tableName + " force index(" + indexName + ") ");
+            SQLRecorderLogger.ddlLogger.info(
+                "[Incremental checker] Get incremental insert data cost: "
+                    + (System.nanoTime() - startTime) / 1_000_000 + " ms");
+            return rs;
+        }
+    }
+
+    @Override
+    public boolean getCheckReports(Collection reports) {
+        if (errors.isEmpty()) {
+            String report = String.format("Incremental check passed for schema %s, table %s, index %s , "
+                + "increment insert count %s ", schemaName, tableName, indexName, finalCount);
+            reports.add(report);
+            SQLRecorderLogger.ddlLogger.info(report);
+            return true;
+        }
+        String report = String.format("Incremental check failed for schema %s, table %s, index %s",
+            schemaName, tableName, indexName);
+        SQLRecorderLogger.ddlLogger.warn(report);
+        reports.add(report);
+        reports.addAll(errors);
+        return false;
+    }
+
+}
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciSnapshotChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciSnapshotChecker.java
new file mode 100644
index 000000000..057e4f21f
--- /dev/null
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciSnapshotChecker.java
@@ -0,0 +1,52 @@
+package com.alibaba.polardbx.executor.columnar.checker;
+
+import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+
+public class CciSnapshotChecker extends CciChecker {
+    private static final String CALCULATE_PRIMARY_HASH =
+        "select count(0) as count, check_sum_v2(%s) as pk_checksum, check_sum_v2(*) as checksum "
+            + "from %s as of tso %s force index(primary)";
+    private static final String CALCULATE_COLUMNAR_HASH =
+        "select count(0) as count, check_sum_v2(%s) as pk_checksum, check_sum_v2(*) as checksum "
+            + "from %s as of tso %s force index(%s)";
+    private final long primaryTso;
+    private final long columnarTso;
+
+    public CciSnapshotChecker(String schemaName, String tableName, String indexName,
+                              long primaryTso, long columnarTso) {
+        super(schemaName, tableName, indexName);
+        this.primaryTso = primaryTso;
+        this.columnarTso = columnarTso;
+    }
+
+    @Override
+    protected Pair getCheckTso() {
+        return new Pair<>(primaryTso, columnarTso);
+    }
+
+    @Override
+    protected String getColumnarSql(ExecutionContext ec, long tso, String pkList) {
+        // Build hint.
+        StringBuilder sb = new StringBuilder();
+        ICciChecker.setBasicHint(ec, sb);
+        String hint = String.format(COLUMNAR_HINT, sb);
+
+        String sql = String.format(CALCULATE_COLUMNAR_HASH, pkList, tableName, tso, indexName);
+
+        return hint + sql;
+    }
+
+    @Override
+    protected String getPrimarySql(ExecutionContext ec, long tso, String pkList) {
+        // Build hint.
+        StringBuilder sb = new StringBuilder();
+        ICciChecker.setBasicHint(ec, sb);
+        sb.append(" TRANSACTION_POLICY=TSO");
+        String hint = String.format(PRIMARY_HINT, sb);
+
+        String sql = String.format(CALCULATE_PRIMARY_HASH, pkList, tableName, tso);
+
+        return hint + sql;
+    }
+}
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciSnapshotFastChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciSnapshotFastChecker.java
new file mode 100644
index 000000000..31271f5f2
--- /dev/null
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/CciSnapshotFastChecker.java
@@ -0,0 +1,41 @@
+package com.alibaba.polardbx.executor.columnar.checker;
+
+import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.common.utils.logger.Logger;
+import com.alibaba.polardbx.common.utils.logger.LoggerFactory;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+
+/**
+ * @author yaozhili
+ */
+public class CciSnapshotFastChecker extends CciFastChecker {
+    private static final Logger logger = LoggerFactory.getLogger(CciSnapshotFastChecker.class);
+
+    private static final String CALCULATE_PRIMARY_HASH =
+        "select check_sum_v2(*) as checksum from %s as of tso %s force index(primary)";
+
+    private final long primaryTso;
+    private final long columnarTso;
+
+    public CciSnapshotFastChecker(String schemaName, String tableName, String indexName,
+                                  long primaryTso, long columnarTso) {
+        super(schemaName, tableName, indexName);
+        this.primaryTso = primaryTso;
+        this.columnarTso = columnarTso;
+    }
+
+    @Override
+    protected Pair getCheckTso() {
+        return new Pair<>(primaryTso, columnarTso);
+    }
+
+    @Override
+    protected String getPrimarySql(ExecutionContext baseEc, long tso) {
+        StringBuilder sb = new StringBuilder();
+        ICciChecker.setBasicHint(baseEc, sb);
+
+        sb.append(" TRANSACTION_POLICY=TSO");
+        String hint = String.format(PRIMARY_HINT, sb);
+        return hint + String.format(CALCULATE_PRIMARY_HASH, tableName, tso);
+    }
+}
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/ICciChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/ICciChecker.java
index 30a780efe..7264c12a3 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/ICciChecker.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/checker/ICciChecker.java
@@ -16,15 +16,44 @@
 
 package com.alibaba.polardbx.executor.columnar.checker;
 
+import com.alibaba.polardbx.common.IInnerConnection;
+import com.alibaba.polardbx.common.IInnerConnectionManager;
+import com.alibaba.polardbx.common.exception.TddlRuntimeException;
+import com.alibaba.polardbx.common.exception.code.ErrorCode;
+import com.alibaba.polardbx.common.jdbc.ITransactionPolicy;
+import com.alibaba.polardbx.common.properties.ConnectionParams;
+import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.executor.gms.DynamicColumnarManager;
+import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor;
+import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord;
+import com.alibaba.polardbx.gms.metadb.table.FilesAccessor;
+import com.alibaba.polardbx.gms.metadb.table.FilesRecordSimplifiedWithChecksum;
+import com.alibaba.polardbx.gms.util.MetaDbUtil;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 /**
  * @author yaozhili
  */
 public interface ICciChecker {
-    void check(ExecutionContext baseEc, Runnable recoverChangedConfigs) throws Throwable;
+    default void check(ExecutionContext baseEc) throws Throwable {
+        check(baseEc, null);
+    }
+
+    default void check(ExecutionContext baseEc, Runnable recoverChangedConfigs) throws Throwable {
+        throw new UnsupportedOperationException();
+    }
+
+    default void check(ExecutionContext baseEc, long tsoV1, long tsoV2, long innodbTso) throws Throwable {
+        throw new UnsupportedOperationException();
+    }
 
     /**
      * @param reports [OUT] check reports returned
@@ -32,4 +61,63 @@ public interface ICciChecker {
      * or false if inconsistency detected (inconsistency details are in reports)
      */
     boolean getCheckReports(Collection reports);
+
+    static long getTableId(String schemaName, String indexName) throws SQLException {
+        return DynamicColumnarManager.getInstance().getTableId(0, schemaName, indexName);
+    }
+
+    static List getFilesRecords(long tso, long tableId, String schemaName)
+        throws SQLException {
+        try (Connection connection = MetaDbUtil.getConnection()) {
+            FilesAccessor filesAccessor = new FilesAccessor();
+            filesAccessor.setConnection(connection);
+            return filesAccessor.querySnapshotWithChecksumByTsoAndTableId(tso, schemaName, String.valueOf(tableId));
+        }
+    }
+
+    static void setBasicHint(ExecutionContext ec, StringBuilder sb) {
+        long parallelism;
+        if ((parallelism = ec.getParamManager().getInt(ConnectionParams.MPP_PARALLELISM)) > 0) {
+            sb.append(" MPP_PARALLELISM=")
+                .append(parallelism)
+                .append(" ");
+        }
+        if ((parallelism = ec.getParamManager().getInt(ConnectionParams.PARALLELISM)) > 0) {
+            sb.append(" PARALLELISM=")
+                .append(parallelism)
+                .append(" ");
+        }
+        boolean enableMpp = ec.getParamManager().getBoolean(ConnectionParams.ENABLE_MPP);
+        if (enableMpp) {
+            sb.append(" ENABLE_MPP=true");
+        }
+        boolean enableMasterMpp = ec.getParamManager().getBoolean(ConnectionParams.ENABLE_MASTER_MPP);
+        if (enableMasterMpp) {
+            sb.append(" ENABLE_MASTER_MPP=true");
+        }
+        sb.append(" ENABLE_ACCURATE_REL_TYPE_TO_DATA_TYPE=true");
+    }
+
+    /**
+     * Don't forget to close it.
+     */
+    static IInnerConnection startDaemonTransaction(IInnerConnectionManager mgr, String schema, String table)
+        throws SQLException {
+        IInnerConnection connection = mgr.getConnection(schema);
+        connection.setTrxPolicy(ITransactionPolicy.TSO);
+        connection.setAutoCommit(false);
+        try (Statement stmt = connection.createStatement()) {
+            ResultSet rs = stmt.executeQuery("show topology from " + table);
+            List> topologies = new ArrayList<>();
+            while (rs.next()) {
+                topologies.add(new Pair<>(rs.getString("GROUP_NAME"), rs.getString("TABLE_NAME")));
+            }
+            // For each group, send a query.
+            for (Pair topology : topologies) {
+                stmt.executeQuery(String.format("/*+TDDL:node(%s)*/ select 1 from %s limit 1", topology.getKey(),
+                    topology.getValue()));
+            }
+        }
+        return connection;
+    }
 }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/ColumnarPruneManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/ColumnarPruneManager.java
index a331f6a67..a0330d5dc 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/ColumnarPruneManager.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/ColumnarPruneManager.java
@@ -81,7 +81,7 @@ public static IndexPruner getIndexPruner(Path targetFile,
                     // init sort key index
                     for (OrcProto.RowIndexEntry rowIndexEntry : rgIndex.getEntryList()) {
                         rgNum++;
-                        builder.appendSortKeyIndex(rowIndexEntry.getStatistics().getIntStatistics());
+                        builder.appendSortKeyIndex(rowIndexEntry.getStatistics());
                     }
                 } else {
                     // error log
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/BaseColumnIndex.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/BaseColumnIndex.java
index e925d3b4c..afd19fd3e 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/BaseColumnIndex.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/BaseColumnIndex.java
@@ -19,6 +19,7 @@
 import com.alibaba.polardbx.common.utils.time.core.MysqlDateTime;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
+import com.google.common.base.Preconditions;
 
 /**
  * @author fangwu
@@ -36,27 +37,26 @@ public long rgNum() {
     }
 
     /**
-     * Use this method to force index handling the same type of data internal.
-     * Index data should be written by same data type, and the datatype could also handle comparison correctly.
-     *
-     * @param value the origin value of column datatype
-     * @return return the same type with index data
-     * @throws IllegalArgumentException if value was not meet the requirements, throw IllegalArgumentException
+     * @param value: input data type
+     * @param dt: column data type
+     * @param clazz: excepted input data type
      */
-    protected Long paramTransform(Object value, DataType dt) {
-        if (value == null || dt == null) {
-            return null;
-        }
+    protected  T paramTransform(Object value, DataType dt, Class clazz) {
+        Preconditions.checkArgument(value != null && dt != null, "value and DataType can't be null here");
         if (DataTypeUtil.isIntType(dt)) {
-            return ((Number) value).longValue();
-        }
-        if (DataTypeUtil.isDateType(dt)) {
+            if (clazz.equals(Long.class) && value instanceof Number) {
+                return clazz.cast(((Number) value).longValue());
+            }
+        } else if (DataTypeUtil.isStringSqlType(dt)) {
+            if (clazz.equals(String.class) && value instanceof String) {
+                return clazz.cast(value);
+            }
+        } else if (DataTypeUtil.isDateType(dt)) {
             MysqlDateTime date = DataTypeUtil.toMySQLDatetime(value, dt.getSqlType());
-            if (date == null) {
-                return null;
+            if (clazz.equals(Long.class) && date != null) {
+                return clazz.cast(date.toPackedLong());
             }
-            return date.toPackedLong();
         }
-        throw new IllegalArgumentException("not supported index value:" + value);
+        return null;
     }
 }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/IndexPruner.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/IndexPruner.java
index baf4219e1..850254c27 100644
--- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/IndexPruner.java
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/IndexPruner.java
@@ -202,14 +202,15 @@ public IndexPruner build() {
             return indexPruner;
         }
 
-        public IndexPrunerBuilder appendSortKeyIndex(OrcProto.IntegerStatistics integerStatistics) {
-            sortKeyIndexBuilder.appendDataEntry(integerStatistics);
+        public IndexPrunerBuilder appendSortKeyIndex(OrcProto.ColumnStatistics columnStatistics) {
+            sortKeyIndexBuilder.appendDataEntry(columnStatistics);
             curRgNum++;
             return this;
         }
 
-        public IndexPrunerBuilder appendSortKeyIndex(long min, long max) {
-            sortKeyIndexBuilder.appendDataEntry(min, max);
+        //only for test
+        public IndexPrunerBuilder appendMockSortKeyIndex(Object min, Object max, DataType dt) {
+            sortKeyIndexBuilder.appendMockDataEntry(min, max, dt);
             curRgNum++;
             return this;
         }
diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/LongSortKeyIndex.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/LongSortKeyIndex.java
new file mode 100644
index 000000000..7bd23a31d
--- /dev/null
+++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/LongSortKeyIndex.java
@@ -0,0 +1,216 @@
+package com.alibaba.polardbx.executor.columnar.pruning.index;
+
+import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.google.common.base.Preconditions;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.roaringbitmap.RoaringBitmap;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Sort Key Index for Columnar pruning, each Sort key index for one orc file.
+ * this index only support number/date datatype, which could being easily transformed&compared
+ * by long value.
+ * 

+ * data the long array contains both min/max value for each row group,so the rg num equals data.length/2. like: + * RG data: rg1(1000, 2000), rg2(2000, 3000), rg3(4000, 5000), rg4(5000, 5001) + * index data: [1000, 2000, 2000, 3000, 4000, 5000, 5000, 5001] + *

+ * Sort key index provided two type pruning interface:pruneEqual/pruneRange + *

+ * pruneEqual will return 0~data_length/2 rgs. + * - if target value was between any min/max values of rg(not included min/max value), return that rg + * - if target value was between any two rgs, return 0 rg. like target value(3500) won't return any rg + * - if target value was contain by multi rgs, return them. like target value(5000) would return rg3 and rg4 + *

+ * pruneEqual is a special case for pruneRange. + *

+ * pruneRange will return rgs that ranges intersected + * + * @author fangwu + */ + +public class LongSortKeyIndex extends SortKeyIndex { + /** + * index data + */ + private long[] data; + + private LongSortKeyIndex(long rgNum, int colId, DataType dt) { + super(rgNum, colId, dt); + } + + public static LongSortKeyIndex build(int colId, long[] data, DataType dt) { + Preconditions.checkArgument(data != null && data.length > 0 && data.length % 2 == 0, "bad sort key index"); + LongSortKeyIndex longSortKeyIndex = new LongSortKeyIndex(data.length / 2, colId, dt); + + longSortKeyIndex.data = data; + return longSortKeyIndex; + } + + /** + * return full rg for null arg. + * + * @param param target value + * @return pruneRange result for the same value + */ + @Override + public void pruneEqual(Object param, RoaringBitmap cur) { + if (param == null) { + return; + } + pruneRange(param, param, cur); + } + + /** + * prune range contains two steps. + * - value transformed to long + * - prune by long range values + */ + @Override + public void pruneRange(Object startObj, Object endObj, RoaringBitmap cur) { + Preconditions.checkArgument(!(startObj == null && endObj == null), "null val"); + Long start; + Long end; + + //startObj/endObj == null means lowerBound/upperBound is unlimited + // paramTransform() == null means type of startObj is unsupported + start = (startObj == null) ? data[0] : paramTransform(startObj, dt, Long.class); + end = (endObj == null) ? data[data.length - 1] : paramTransform(endObj, dt, Long.class); + if (start == null || end == null) { + return; + } + + if (start > end) { + cur.and(new RoaringBitmap()); + return; + } + + if (end < data[0] || + start > data[data.length - 1]) { + cur.and(new RoaringBitmap()); + return; + } + + // get lower bound rg index + Pair sIndex = binarySearchLowerBound(start); + // get upper bound rg index + Pair eIndex = binarySearchUpperBound(end); + int startRgIndex; + int endRgIndex; + + // if lower rg index was not included, plus it was different from upper index, then add 1 to lower rg index + if (!sIndex.getValue() && !Objects.equals(sIndex.getKey(), eIndex.getKey())) { + startRgIndex = sIndex.getKey() + 1; + } else { + startRgIndex = sIndex.getKey(); + } + if (eIndex.getValue()) { + endRgIndex = eIndex.getKey() + 1; + } else { + endRgIndex = eIndex.getKey(); + } + + cur.and(RoaringBitmap.bitmapOfRange(startRgIndex, endRgIndex)); + } + + /** + * binary search target value from data array + * - if data array wasn't contains target value, then check odd or even. + * odd meaning target is inside of one row group. even meaning target isn't + * belong any row group. + * data [1, 10, 50, 100] and target 5 will return (0,true) + * data [1, 10, 50, 100] and target 20 will return (0,false) + * - if data array contains target value, try to find the upper bound value + * for the same target value + * data [1, 10, 50, 100, 100, 100] and target 100 will return (3,true) + * + * @param target target value to be searched + */ + private Pair binarySearchUpperBound(Long target) { + if (target < data[0]) { + return Pair.of(0, false); + } + + int index = Arrays.binarySearch(data, target); + + if (index < 0) { + index = -(index + 1); + } else { + for (int i = index + 1; i < data.length; i++) { + if (data[i] == target) { + index = i; + } else { + break; + } + } + return Pair.of(index / 2, true); + } + if (index % 2 == 0) { + return Pair.of(index / 2, false); + } else { + return Pair.of(index / 2, true); + } + } + + /** + * binary search target value from data array + * - if data array wasn't contains target value, then check odd or even. + * odd meaning target is inside of one row group. even meaning target isn't + * belong any row group. + * data [1, 10, 50, 100] and target 5 will return (0,false) + * data [1, 10, 50, 100] and target 20 will return (0,true) + * - if data array contains target value, try to find the lower bound value + * for the same target value + * data [1, 10, 50, 100, 100, 100] and target 100 will return (3,true) + * + * @param target target value to be searched + */ + private Pair binarySearchLowerBound(Long target) { + if (target > data[data.length - 1]) { + return Pair.of((data.length - 1) / 2, false); + } else if (target < data[0]) { + return Pair.of(0, true); + } + int index = Arrays.binarySearch(data, target); + + if (index < 0) { + index = -index - 1; + } else { + for (int i = index - 1; i > 0; i--) { + if (data[i] == target) { + index = i; + } else { + break; + } + } + return Pair.of(index / 2, true); + } + if (index % 2 == 0) { + return Pair.of((index / 2) - 1, false); + } else { + return Pair.of(index / 2, true); + } + } + + @Override + public boolean checkSupport(int columnId, SqlTypeName type) { + if (type != SqlTypeName.BIGINT && + type != SqlTypeName.INTEGER && + type != SqlTypeName.YEAR && + type != SqlTypeName.DATE && + type != SqlTypeName.DATETIME) { + return false; + } + + // TODO col id might need transform + return columnId == colId; + } + + public long[] getData() { + return data; + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/SortKeyIndex.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/SortKeyIndex.java index fe5e6cb02..dfa2e9369 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/SortKeyIndex.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/SortKeyIndex.java @@ -16,235 +16,36 @@ package com.alibaba.polardbx.executor.columnar.pruning.index; -import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.optimizer.core.datatype.DataType; -import com.google.common.base.Preconditions; -import org.apache.calcite.sql.type.SqlTypeName; import org.roaringbitmap.RoaringBitmap; -import java.util.Arrays; -import java.util.Objects; - -/** - * Sort Key Index for Columnar pruning, each Sort key index for one orc file. - * this index only support number/date datatype, which could being easily transformed&compared - * by long value. - *

- * data the long array contains both min/max value for each row group,so the rg num equals data.length/2. like: - * RG data: rg1(1000, 2000), rg2(2000, 3000), rg3(4000, 5000), rg4(5000, 5001) - * index data: [1000, 2000, 2000, 3000, 4000, 5000, 5000, 5001] - *

- * Sort key index provided two type pruning interface:pruneEqual/pruneRange - *

- * pruneEqual will return 0~data_length/2 rgs. - * - if target value was between any min/max values of rg(not included min/max value), return that rg - * - if target value was between any two rgs, return 0 rg. like target value(3500) won't return any rg - * - if target value was contain by multi rgs, return them. like target value(5000) would return rg3 and rg4 - *

- * pruneEqual is a special case for pruneRange. - *

- * pruneRange will return rgs that ranges intersected - * - * @author fangwu - */ -public class SortKeyIndex extends BaseColumnIndex { - /** - * index data - */ - private long[] data; +public abstract class SortKeyIndex extends BaseColumnIndex { /** * col index in the orc file, start with 0 */ - private final int colId; + protected final int colId; /** * column type */ - private final DataType dt; + protected final DataType dt; - private SortKeyIndex(long rgNum, int colId, DataType dt) { + protected SortKeyIndex(long rgNum, int colId, DataType dt) { super(rgNum); this.colId = colId; this.dt = dt; } - public static SortKeyIndex build(int colId, long[] data, DataType dt) { - Preconditions.checkArgument(data != null && data.length > 0 && data.length % 2 == 0, "bad short key index"); - SortKeyIndex sortKeyIndex = new SortKeyIndex(data.length / 2, colId, dt); - - sortKeyIndex.data = data; - return sortKeyIndex; - } - - /** - * return full rg for null arg. - * - * @param param target value - * @return pruneRange result for the same value - */ - public void pruneEqual(Object param, RoaringBitmap cur) { - if (param == null) { - return; - } - pruneRange(param, param, cur); - } - - /** - * prune range contains two steps. - * - value transformed to long - * - prune by long range values - */ - public void pruneRange(Object startObj, Object endObj, RoaringBitmap cur) { - Preconditions.checkArgument(!(startObj == null && endObj == null), "null val"); - Long start; - Long end; - - try { - start = paramTransform(startObj, dt); - if (start == null) { - start = data[0]; - } - end = paramTransform(endObj, dt); - if (end == null) { - end = data[data.length - 1]; - } - } catch (IllegalArgumentException e) { - return; - } - - if (end < data[0] || - start > data[data.length - 1]) { - cur.and(new RoaringBitmap()); - return; - } - - Preconditions.checkArgument(start <= end, "error range value"); - - // get lower bound rg index - Pair sIndex = binarySearchLowerBound(start); - // get upper bound rg index - Pair eIndex = binarySearchUpperBound(end); - int startRgIndex; - int endRgIndex; - - // if lower rg index was not included, plus it was different from upper index, then add 1 to lower rg index - if (!sIndex.getValue() && !Objects.equals(sIndex.getKey(), eIndex.getKey())) { - startRgIndex = sIndex.getKey() + 1; - } else { - startRgIndex = sIndex.getKey(); - } - if (eIndex.getValue()) { - endRgIndex = eIndex.getKey() + 1; - } else { - endRgIndex = eIndex.getKey(); - } - - cur.and(RoaringBitmap.bitmapOfRange(startRgIndex, endRgIndex)); - } - - /** - * binary search target value from data array - * - if data array wasn't contains target value, then check odd or even. - * odd meaning target is inside of one row group. even meaning target isn't - * belong any row group. - * data [1, 10, 50, 100] and target 5 will return (0,true) - * data [1, 10, 50, 100] and target 20 will return (0,false) - * - if data array contains target value, try to find the upper bound value - * for the same target value - * data [1, 10, 50, 100, 100, 100] and target 100 will return (3,true) - * - * @param target target value to be searched - */ - private Pair binarySearchUpperBound(Long target) { - if (target < data[0]) { - return Pair.of(0, false); - } - - int index = Arrays.binarySearch(data, target); - - if (index < 0) { - index = -(index + 1); - } else { - for (int i = index + 1; i < data.length; i++) { - if (data[i] == target) { - index = i; - } else { - break; - } - } - return Pair.of(index / 2, true); - } - if (index % 2 == 0) { - return Pair.of(index / 2, false); - } else { - return Pair.of(index / 2, true); - } - } + abstract public void pruneEqual(Object param, RoaringBitmap cur); - /** - * binary search target value from data array - * - if data array wasn't contains target value, then check odd or even. - * odd meaning target is inside of one row group. even meaning target isn't - * belong any row group. - * data [1, 10, 50, 100] and target 5 will return (0,false) - * data [1, 10, 50, 100] and target 20 will return (0,true) - * - if data array contains target value, try to find the lower bound value - * for the same target value - * data [1, 10, 50, 100, 100, 100] and target 100 will return (3,true) - * - * @param target target value to be searched - */ - private Pair binarySearchLowerBound(Long target) { - if (target > data[data.length - 1]) { - return Pair.of((data.length - 1) / 2, false); - } else if (target < data[0]) { - return Pair.of(0, true); - } - int index = Arrays.binarySearch(data, target); - - if (index < 0) { - index = -index - 1; - } else { - for (int i = index - 1; i > 0; i--) { - if (data[i] == target) { - index = i; - } else { - break; - } - } - return Pair.of(index / 2, true); - } - if (index % 2 == 0) { - return Pair.of((index / 2) - 1, false); - } else { - return Pair.of(index / 2, true); - } - } - - @Override - public boolean checkSupport(int columnId, SqlTypeName type) { - if (type != SqlTypeName.BIGINT && - type != SqlTypeName.INTEGER && - type != SqlTypeName.YEAR && - type != SqlTypeName.DATE && - type != SqlTypeName.DATETIME) { - return false; - } - - // TODO col id might need transform - return columnId == colId; - } + abstract public void pruneRange(Object startObj, Object endObj, RoaringBitmap cur); @Override public DataType getColumnDataType(int colId) { return dt; } - public long[] getData() { - return data; - } - public int getColId() { return colId; } @@ -252,4 +53,5 @@ public int getColId() { public DataType getDt() { return dt; } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/StringSortKeyIndex.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/StringSortKeyIndex.java new file mode 100644 index 000000000..35423a9d7 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/StringSortKeyIndex.java @@ -0,0 +1,219 @@ +package com.alibaba.polardbx.executor.columnar.pruning.index; + +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.google.common.base.Preconditions; +import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.hadoop.io.WritableComparator; +import org.roaringbitmap.RoaringBitmap; + +import java.util.Objects; + +public class StringSortKeyIndex extends SortKeyIndex { + /** + * index data + */ + private byte[][] data; + + private StringSortKeyIndex(long rgNum, int colId, DataType dt) { + super(rgNum, colId, dt); + } + + //build StringSortKeyIndex base on data + public static StringSortKeyIndex build(int colId, String[] data, DataType dt) { + Preconditions.checkArgument(data != null && data.length > 0 && data.length % 2 == 0, "bad sort key index"); + StringSortKeyIndex stringSortKeyIndex = new StringSortKeyIndex(data.length / 2, colId, dt); + + stringSortKeyIndex.data = new byte[data.length][]; + for (int i = 0; i < data.length; i++) { + stringSortKeyIndex.data[i] = data[i].getBytes(); + } + return stringSortKeyIndex; + } + + @Override + public void pruneEqual(Object param, RoaringBitmap cur) { + if (param == null) { + return; + } + pruneRange(param, param, cur); + } + + @Override + public void pruneRange(Object startObj, Object endObj, RoaringBitmap cur) { + Preconditions.checkArgument(!(startObj == null && endObj == null), "null val"); + byte[] start; + byte[] end; + + //startObj/endObj == null means lowerBound/UpperBound is unlimited + // paramTransform() == null means type of startObj is unsupported + if (startObj == null) { + start = data[0]; + } else { + String stringStart = paramTransform(startObj, dt, String.class); + if (stringStart == null) { + return; + } + start = stringStart.getBytes(); + } + + if (endObj == null) { + end = data[data.length - 1]; + } else { + String stringEnd = paramTransform(endObj, dt, String.class); + if (stringEnd == null) { + return; + } + end = stringEnd.getBytes(); + } + if (bytesCompare(start, end) > 0) { + cur.and(new RoaringBitmap()); + return; + } + if (bytesCompare(end, data[0]) < 0 || + bytesCompare(start, data[data.length - 1]) > 0) { + cur.and(new RoaringBitmap()); + return; + } + + // get lower bound rg index + Pair sIndex = binarySearchLowerBound(start); + // get upper bound rg index + Pair eIndex = binarySearchUpperBound(end); + int startRgIndex; + int endRgIndex; + + // if lower rg index was not included, plus it was different from upper index, then add 1 to lower rg index + if (!sIndex.getValue() && !Objects.equals(sIndex.getKey(), eIndex.getKey())) { + startRgIndex = sIndex.getKey() + 1; + } else { + startRgIndex = sIndex.getKey(); + } + if (eIndex.getValue()) { + endRgIndex = eIndex.getKey() + 1; + } else { + endRgIndex = eIndex.getKey(); + } + + cur.and(RoaringBitmap.bitmapOfRange(startRgIndex, endRgIndex)); + } + + /** + * binary search target value from data array + * - if data array wasn't contains target value, then check odd or even. + * odd meaning target is inside of one row group. even meaning target isn't + * belong any row group. + * data [1, 10, 50, 100] and target 5 will return (0,true) + * data [1, 10, 50, 100] and target 20 will return (0,false) + * - if data array contains target value, try to find the upper bound value + * for the same target value + * data [1, 10, 50, 100, 100, 100] and target 100 will return (3,true) + * + * @param target target value to be searched + */ + private Pair binarySearchUpperBound(byte[] target) { + if (bytesCompare(target, data[0]) < 0) { + return Pair.of(0, false); + } + + int index = binarySearch(data, target); + + if (index < 0) { + index = -(index + 1); + } else { + for (int i = index + 1; i < data.length; i++) { + if (bytesCompare(data[i], target) == 0) { + index = i; + } else { + break; + } + } + return Pair.of(index / 2, true); + } + if (index % 2 == 0) { + return Pair.of(index / 2, false); + } else { + return Pair.of(index / 2, true); + } + } + + /** + * binary search target value from data array + * - if data array wasn't contains target value, then check odd or even. + * odd meaning target is inside of one row group. even meaning target isn't + * belong any row group. + * data [1, 10, 50, 100] and target 5 will return (0,false) + * data [1, 10, 50, 100] and target 20 will return (0,true) + * - if data array contains target value, try to find the lower bound value + * for the same target value + * data [1, 10, 50, 100, 100, 100] and target 100 will return (3,true) + * + * @param target target value to be searched + */ + private Pair binarySearchLowerBound(byte[] target) { + if (bytesCompare(target, data[data.length - 1]) > 0) { + return Pair.of((data.length - 1) / 2, false); + } else if (bytesCompare(target, data[0]) < 0) { + return Pair.of(0, true); + } + int index = binarySearch(data, target); + + if (index < 0) { + index = -index - 1; + } else { + for (int i = index - 1; i > 0; i--) { + if (bytesCompare(data[i], target) == 0) { + index = i; + } else { + break; + } + } + return Pair.of(index / 2, true); + } + if (index % 2 == 0) { + return Pair.of((index / 2) - 1, false); + } else { + return Pair.of(index / 2, true); + } + } + + @Override + public boolean checkSupport(int columnId, SqlTypeName type) { + if (type != SqlTypeName.VARCHAR && + type != SqlTypeName.CHAR) { + return false; + } + + // TODO col id might need transform + return columnId == colId; + } + + public byte[][] getData() { + return data; + } + + private int binarySearch(byte[][] a, byte[] key) { + int low = 0; + int high = a.length - 1; + + while (low <= high) { + int mid = (low + high) >>> 1; + byte[] midVal = a[mid]; + int cmp = bytesCompare(midVal, key); + + if (cmp < 0) { + low = mid + 1; + } else if (cmp > 0) { + high = mid - 1; + } else { + return mid; // key found + } + } + return -(low + 1); // key not found. + } + + private static int bytesCompare(byte[] a, byte[] b) { + return WritableComparator.compareBytes(a, 0, a.length, b, 0, b.length); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/ZoneMapIndex.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/ZoneMapIndex.java index ddf6fc783..249462d46 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/ZoneMapIndex.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/ZoneMapIndex.java @@ -145,12 +145,36 @@ public void pruneNull(int colId, RoaringBitmap cur) { * @param end upper value * @param includeEnd is upper value included */ - public void prune(int colId, Object start, boolean includeStart, Object end, boolean includeEnd, + public void prune(int colId, Object startObj, boolean includeStart, Object endObj, boolean includeEnd, RoaringBitmap cur) { - try { - start = paramTransform(start, dtMap.get(colId)); - end = paramTransform(end, dtMap.get(colId)); - } catch (IllegalArgumentException e) { + //startObj/endObj == null means lowerBound/UpperBound is unlimited + // paramTransform() == null means type of startObj is unsupported + Object start; + if (startObj == null) { + //lower bound is unlimited + start = null; + } else { + start = paramTransform(startObj, dtMap.get(colId), Long.class); + //type is unsupported + if (start == null) { + return; + } + } + + Object end; + if (endObj == null) { + //upper bound is unlimited + end = null; + } else { + end = paramTransform(endObj, dtMap.get(colId), Long.class); + //type is unsupported + if (end == null) { + return; + } + } + DataType dt = dtMap.get(colId); + if (start != null && end != null && dt.compare(start, end) > 0) { + cur.and(new RoaringBitmap()); return; } if (includeStart) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/builder/SortKeyIndexBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/builder/SortKeyIndexBuilder.java index c88310b3b..9dff6f5a6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/builder/SortKeyIndexBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/columnar/pruning/index/builder/SortKeyIndexBuilder.java @@ -16,8 +16,12 @@ package com.alibaba.polardbx.executor.columnar.pruning.index.builder; +import com.alibaba.polardbx.executor.columnar.pruning.index.LongSortKeyIndex; import com.alibaba.polardbx.executor.columnar.pruning.index.SortKeyIndex; +import com.alibaba.polardbx.executor.columnar.pruning.index.StringSortKeyIndex; import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil; +import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import org.apache.orc.OrcProto; @@ -30,33 +34,68 @@ public class SortKeyIndexBuilder { private int colId; private DataType dt; - private List dataEntry = Lists.newArrayList(); + private List longDataEntry = Lists.newArrayList(); + private List stringDataEntry = Lists.newArrayList(); - public void appendDataEntry(OrcProto.IntegerStatistics integerStatistics) { - dataEntry.add(integerStatistics.getMinimum()); - dataEntry.add(integerStatistics.getMaximum()); + public void appendDataEntry(OrcProto.ColumnStatistics columnStatistics) { + if (DataTypeUtil.isStringSqlType(dt)) { + OrcProto.StringStatistics stringStatistics = columnStatistics.getStringStatistics(); + stringDataEntry.add( + stringStatistics.getMinimum().isEmpty() ? stringStatistics.getLowerBound() : + stringStatistics.getMinimum()); + stringDataEntry.add( + stringStatistics.getMaximum().isEmpty() ? stringStatistics.getUpperBound() : + stringStatistics.getMaximum()); + + } else { + OrcProto.IntegerStatistics integerStatistics = columnStatistics.getIntStatistics(); + longDataEntry.add(integerStatistics.getMinimum()); + longDataEntry.add(integerStatistics.getMaximum()); + } } - public void appendDataEntry(long min, long max) { - dataEntry.add(min); - dataEntry.add(max); + //only for test + public void appendMockDataEntry(Object min, Object max, DataType dt) { + if (DataTypeUtil.isStringSqlType(dt)) { + stringDataEntry.add((String) min); + stringDataEntry.add((String) max); + } else { + longDataEntry.add(((Number) min).longValue()); + longDataEntry.add(((Number) max).longValue()); + } } public SortKeyIndex build() { - long[] data = new long[dataEntry.size()]; - Iterator it = dataEntry.iterator(); - int cur = 0; - while (it.hasNext()) { - Long l = it.next(); - data[cur++] = l; + Preconditions.checkArgument(dt != null); + if (DataTypeUtil.isStringSqlType(dt)) { + String[] data = new String[stringDataEntry.size()]; + Iterator it = stringDataEntry.iterator(); + int cur = 0; + while (it.hasNext()) { + String l = it.next(); + data[cur++] = l; + } + return StringSortKeyIndex.build(colId, data, dt); + } else { + long[] data = new long[longDataEntry.size()]; + Iterator it = longDataEntry.iterator(); + int cur = 0; + while (it.hasNext()) { + Long l = it.next(); + data[cur++] = l; + } + return LongSortKeyIndex.build(colId, data, dt); } - return SortKeyIndex.build(colId, data, dt); } public void setDt(DataType dt) { this.dt = dt; } + public DataType getDt() { + return this.dt; + } + public void setColId(int colId) { this.colId = colId; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/CciMetaManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/CciMetaManager.java new file mode 100644 index 000000000..6ba8c0388 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/CciMetaManager.java @@ -0,0 +1,133 @@ +/* + * 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 com.alibaba.polardbx.executor.common; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.model.lifecycle.AbstractLifecycle; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionStatus; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; +import com.alibaba.polardbx.gms.partition.TablePartitionAccessor; +import com.alibaba.polardbx.gms.partition.TablePartitionRecord; +import lombok.Getter; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Getter +public class CciMetaManager extends AbstractLifecycle { + private static final Logger logger = LoggerFactory.getLogger(CciMetaManager.class); + + private static CciMetaManager INSTANCE = new CciMetaManager(); + + private final ColumnarTableEvolutionAccessor columnarTableEvolution = new ColumnarTableEvolutionAccessor(); + private final ColumnarPartitionEvolutionAccessor columnarPartitionEvolution = + new ColumnarPartitionEvolutionAccessor(); + private final TablePartitionAccessor tablePartition = new TablePartitionAccessor(); + + @Override + protected void doInit() { + super.doInit(); + logger.info("init CciMetaManager"); + + if (!ConfigDataMode.isPolarDbX()) { + return; + } + + try { + loadPartitions(); + } catch (Throwable e) { + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, + "init cci meta manager failed"); + } + } + + public static CciMetaManager getInstance() { + if (!INSTANCE.isInited()) { + synchronized (INSTANCE) { + if (!INSTANCE.isInited()) { + INSTANCE.init(); + } + } + } + return INSTANCE; + } + + private void setConnection(Connection metaConn) { + columnarTableEvolution.setConnection(metaConn); + columnarPartitionEvolution.setConnection(metaConn); + tablePartition.setConnection(metaConn); + } + + public synchronized void loadPartitions() { + try (Connection metaConn = MetaDbDataSource.getInstance().getConnection()) { + setConnection(metaConn); + + List evolutionRecords = + getColumnarTableEvolution().queryPartitionEmptyRecords(); + for (ColumnarTableEvolutionRecord evolutionRecord : evolutionRecords) { + String tableScHema = evolutionRecord.tableSchema; + String columnarTableName = evolutionRecord.indexName; + long versionId = evolutionRecord.versionId; + long ddlJobId = evolutionRecord.ddlJobId; + long tableId = evolutionRecord.tableId; + + final List partitionRecords = + getTablePartition().getTablePartitionsByDbNameTbName(tableScHema, columnarTableName, false); + + // Skip if removed table's partition + if (partitionRecords.isEmpty()) { + continue; + } + + // Insert partition evolution records + List partitionEvolutionRecords = + new ArrayList<>(partitionRecords.size()); + for (TablePartitionRecord partitionRecord : partitionRecords) { + partitionEvolutionRecords.add( + new ColumnarPartitionEvolutionRecord(tableId, partitionRecord.partName, + versionId, ddlJobId, partitionRecord, ColumnarPartitionStatus.PUBLIC.getValue())); + } + getColumnarPartitionEvolution().insert(partitionEvolutionRecords); + getColumnarPartitionEvolution().updatePartitionIdAsId(tableId, versionId); + + partitionEvolutionRecords = + getColumnarPartitionEvolution().queryTableIdVersionIdOrderById(tableId, versionId); + final List partitions = + partitionEvolutionRecords.stream().map(r -> r.id).collect(Collectors.toList()); + + getColumnarTableEvolution().updatePartition(tableId, partitions); + } + + } catch (Throwable ex) { + throw GeneralUtil.nestedException(ex); + } + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/ExecutorContext.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/ExecutorContext.java index 2c60cce51..295be557e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/ExecutorContext.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/ExecutorContext.java @@ -17,6 +17,7 @@ package com.alibaba.polardbx.executor.common; import com.alibaba.polardbx.common.IInnerConnectionManager; +import com.alibaba.polardbx.common.trx.ISyncPointExecutor; import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.executor.gms.ColumnarManager; import com.alibaba.polardbx.executor.gsi.GsiManager; @@ -47,8 +48,8 @@ public class ExecutorContext { private StorageInfoManager storageInfoManager = null; private GsiManager gsiManager = null; private NodeStatusManager nodeStatusManager; - private Consumer reloadColumnarManager; private IInnerConnectionManager innerConnectionManager; + private ISyncPointExecutor syncPointExecutor = null; private static Map executorContextMap = new ConcurrentHashMap(); @@ -145,18 +146,16 @@ public void setGsiManager(GsiManager gsiManager) { this.gsiManager = gsiManager; } - public final static Map getExecutorContextMap() { - return executorContextMap; + public ISyncPointExecutor getSyncPointExecutor() { + return syncPointExecutor; } - public void reloadColumnarManager() { - if (null != reloadColumnarManager) { - reloadColumnarManager.accept(ColumnarManager.getInstance()); - } + public void setSyncPointExecutor(ISyncPointExecutor syncPointExecutor) { + this.syncPointExecutor = syncPointExecutor; } - public void setReloadColumnarManager(Consumer reloadColumnarManager) { - this.reloadColumnarManager = reloadColumnarManager; + public final static Map getExecutorContextMap() { + return executorContextMap; } public IInnerConnectionManager getInnerConnectionManager() { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/SequenceManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/SequenceManager.java index f6ce9dad1..0aac2a7c0 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/SequenceManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/SequenceManager.java @@ -173,10 +173,10 @@ public Integer getIncrement(String schemaName, String seqName) { @Override public Sequence getSequence(String schemaName, String seqName) { - if (!ConfigDataMode.isMasterMode()) { - throw new TddlRuntimeException(ErrorCode.ERR_OPERATION_NOT_ALLOWED, - "Sequence operations are not allowed on a Read-Only Instance"); - } +// if (!ConfigDataMode.isMasterMode()) { +// throw new TddlRuntimeException(ErrorCode.ERR_OPERATION_NOT_ALLOWED, +// "Sequence operations are not allowed on a Read-Only Instance"); +// } checkSubManager(); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/StorageInfoManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/StorageInfoManager.java index 67c21f133..1d22242b5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/StorageInfoManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/common/StorageInfoManager.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.executor.common; +import com.alibaba.polardbx.common.MergedStorageInfo; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.jdbc.IDataSource; @@ -34,6 +35,7 @@ import com.alibaba.polardbx.rpc.XConfig; import com.alibaba.polardbx.rpc.compatible.XDataSource; import com.google.common.base.Preconditions; +import lombok.Getter; import org.apache.commons.lang3.StringUtils; import javax.sql.DataSource; @@ -63,27 +65,9 @@ public class StorageInfoManager extends AbstractLifecycle { private final Map storageInfos; private final TopologyHandler topologyHandler; - private volatile boolean supportXA; - private volatile boolean supportTso; - private volatile boolean supportTsoHeartbeat; - private volatile boolean supportPurgeTso; - private volatile boolean supportCtsTransaction; - private volatile boolean supportAsyncCommit; - private volatile boolean supportLizard1PCTransaction; - private volatile boolean supportDeadlockDetection; - private volatile boolean supportMdlDeadlockDetection; - private volatile boolean supportsBloomFilter; - private volatile boolean supportOpenSSL; - private volatile boolean supportSharedReadView; - private volatile boolean supportsReturning; - private volatile boolean supportsBackfillReturning; - private volatile boolean supportsAlterType; - private boolean readOnly; - private boolean lowerCaseTableNames; - private volatile boolean supportHyperLogLog; - private volatile boolean lessMy56Version; - private boolean supportXxHash; - private volatile boolean isMysql80; + + @Getter + private volatile MergedStorageInfo mergedStorageInfo; /** * FastChecker: generate checksum on xdb node @@ -101,31 +85,8 @@ public class StorageInfoManager extends AbstractLifecycle { deadlockLogMap.put(MDL_DEADLOCK, NO_DEADLOCKS_DETECTED); } - /** - * FastChecker: generate checksum on xdb node - * Since: 5.4.13 fix - * Requirement: XDB supports HASHCHECK function - */ - private volatile boolean supportFastChecker = false; - - private volatile boolean supportChangeSet = false; - - private volatile boolean supportXOptForAutoSp = false; - - private volatile boolean supportXRpc = false; - - private volatile boolean supportMarkDistributed = false; - - private volatile boolean supportXOptForPhysicalBackfill = false; - - private volatile boolean support2pcOpt = false; - public StorageInfoManager(TopologyHandler topologyHandler) { storageInfos = new ConcurrentHashMap<>(); - supportXA = false; - supportsBloomFilter = false; - supportsReturning = false; - supportsBackfillReturning = false; Preconditions.checkNotNull(topologyHandler); this.topologyHandler = topologyHandler; @@ -497,15 +458,25 @@ private static boolean checkSupportMarkDistributed(IDataSource dataSource) { } } - private static boolean checkSupport2pcOpt(IDataSource dataSource) { + protected static boolean checkSupportSyncPoint(IDataSource dataSource) { try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("call dbms_xa.find_by_xid('1', '', 1)")) { - return true; + ResultSet rs = stmt.executeQuery("SHOW VARIABLES LIKE 'enable_polarx_sync_point'")) { + return rs.next(); } catch (SQLException ex) { - logger.warn("Get support 2pc opt failed.", ex); - // Not support. - return false; + throw new TddlRuntimeException(ErrorCode.ERR_OTHER, ex, + "Failed to check sync point support: " + ex.getMessage()); + } + } + + protected static boolean checkSupportFlashbackArea(IDataSource dataSource) { + try (Connection conn = dataSource.getConnection(); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SHOW VARIABLES LIKE 'opt_flashback_area'")) { + return rs.next(); + } catch (SQLException ex) { + throw new TddlRuntimeException(ErrorCode.ERR_OTHER, ex, + "Failed to check flashback area support: " + ex.getMessage()); } } @@ -563,7 +534,8 @@ protected void doInit() { boolean tmpSupportMarkDistributed = true; boolean storageInfoEmpty = true; - boolean tmpSupport2pcOpt = true; + boolean tmpSupportSyncPoint = true; + boolean tmpSupportFlashbackArea = true; for (Group group : topologyHandler.getMatrix().getGroups()) { if (group.getType() != GroupType.MYSQL_JDBC || !DbGroupInfoManager.isNormalGroup(group)) { continue; @@ -600,43 +572,75 @@ protected void doInit() { tmpSupportXRpc &= storageInfo.supportXRpc; tmpSupportXOptForPhysicalBackfill &= storageInfo.supportXOptForPhysicalBackfill; tmpSupportMarkDistributed &= storageInfo.supportMarkDistributed; - tmpSupport2pcOpt &= storageInfo.support2pcOpt; } } - this.readOnly = !ConfigDataMode.needInitMasterModeResource() && !ConfigDataMode.isFastMock(); + boolean readOnly = !ConfigDataMode.needInitMasterModeResource() && !ConfigDataMode.isFastMock(); // Do not enable XA transaction in read-only instance - this.supportXA = tmpSupportXA && !readOnly; - this.supportsBloomFilter = tmpSupportsBloomFilter; - this.supportsReturning = tmpSupportsReturning; - this.supportsBackfillReturning = tmpSupportsBackfillReturning; - this.supportsAlterType = tmpSupportsAlterType; - this.supportTso = tmpSupportTso && (metaDbUsesXProtocol() || tmpRDS80); - this.supportTsoHeartbeat = tmpSupportTsoHeartbeat && metaDbUsesXProtocol(); - this.supportPurgeTso = tmpSupportPurgeTso && metaDbUsesXProtocol(); - this.supportCtsTransaction = tmpSupportCtsTransaction; - this.supportAsyncCommit = tmpSupportAsyncCommit; - this.supportLizard1PCTransaction = tmpSupportLizard1PCTransaction; - this.supportSharedReadView = tmpSupportSharedReadView; - this.supportDeadlockDetection = tmpSupportDeadlockDetection; - this.supportMdlDeadlockDetection = tmpSupportMdlDeadlockDetection; - this.supportOpenSSL = tmpSupportOpenSSL; - this.lowerCaseTableNames = tmpLowerCaseTableNames; - this.supportHyperLogLog = tmpSupportHyperLogLog; - this.lessMy56Version = lessMysql56; - this.supportFastChecker = tmpSupportFastChecker; - this.supportXxHash = tmpSupportXxHash; - this.isMysql80 = tmpRDS80; - this.supportChangeSet = tmpSupportChangeSet; - this.supportXOptForAutoSp = tmpSupportXOptForAutoSp && tmpSupportXRpc; - this.supportXRpc = tmpSupportXRpc; - this.supportXOptForPhysicalBackfill = tmpSupportXOptForPhysicalBackfill && tmpSupportXRpc; - this.supportMarkDistributed = tmpSupportMarkDistributed; - this.support2pcOpt = tmpSupport2pcOpt; + boolean supportXA = tmpSupportXA && !readOnly; + boolean supportsBloomFilter = tmpSupportsBloomFilter; + boolean supportsReturning = tmpSupportsReturning; + boolean supportsBackfillReturning = tmpSupportsBackfillReturning; + boolean supportsAlterType = tmpSupportsAlterType; + boolean supportTso = tmpSupportTso && (metaDbUsesXProtocol() || tmpRDS80); + boolean supportPurgeTso = tmpSupportPurgeTso && metaDbUsesXProtocol(); + boolean supportTsoHeartbeat = tmpSupportTsoHeartbeat && metaDbUsesXProtocol(); + boolean supportCtsTransaction = tmpSupportCtsTransaction; + boolean supportAsyncCommit = tmpSupportAsyncCommit; + boolean supportLizard1PCTransaction = tmpSupportLizard1PCTransaction; + boolean supportSharedReadView = tmpSupportSharedReadView; + boolean supportDeadlockDetection = tmpSupportDeadlockDetection; + boolean supportMdlDeadlockDetection = tmpSupportMdlDeadlockDetection; + boolean supportOpenSSL = tmpSupportOpenSSL; + boolean lowerCaseTableNames = tmpLowerCaseTableNames; + boolean supportHyperLogLog = tmpSupportHyperLogLog; + boolean lessMy56Version = lessMysql56; + boolean supportFastChecker = tmpSupportFastChecker; + boolean supportXxHash = tmpSupportXxHash; + boolean isMysql80 = tmpRDS80; + boolean supportChangeSet = tmpSupportChangeSet; + boolean supportXOptForAutoSp = tmpSupportXOptForAutoSp && tmpSupportXRpc; + boolean supportXRpc = tmpSupportXRpc; + boolean supportXOptForPhysicalBackfill = tmpSupportXOptForPhysicalBackfill && tmpSupportXRpc; + boolean supportMarkDistributed = tmpSupportMarkDistributed; + boolean supportSyncPoint = tmpSupportSyncPoint; + boolean supportFlashbackArea = tmpSupportFlashbackArea; + + this.mergedStorageInfo = new MergedStorageInfo( + supportXA, + supportTso, + supportPurgeTso, + supportTsoHeartbeat, + supportCtsTransaction, + supportAsyncCommit, + supportLizard1PCTransaction, + supportDeadlockDetection, + supportMdlDeadlockDetection, + supportsBloomFilter, + supportOpenSSL, + supportSharedReadView, + supportsReturning, + supportsBackfillReturning, + supportsAlterType, + readOnly, + lowerCaseTableNames, + supportHyperLogLog, + lessMy56Version, + supportXxHash, + isMysql80, + supportFastChecker, + supportChangeSet, + supportXOptForAutoSp, + supportXRpc, + supportMarkDistributed, + supportXOptForPhysicalBackfill, + supportSyncPoint, + supportFlashbackArea + ); if (!storageInfoEmpty) { - InstanceVersion.setMYSQL80(this.isMysql80); + InstanceVersion.setMYSQL80(isMysql80); } } @@ -681,10 +685,6 @@ private boolean enableLowerCaseTableNames(StorageInfo storageInfo) { @Override protected void doDestroy() { storageInfos.clear(); - supportXA = false; - supportsBloomFilter = false; - supportsReturning = false; - supportsBackfillReturning = false; } private StorageInfo initStorageInfo(Group group, IDataSource dataSource) { @@ -707,7 +707,7 @@ public boolean supportXA() { init(); } - return supportXA; + return this.mergedStorageInfo.isSupportXA(); } public boolean supportTso() { @@ -715,7 +715,7 @@ public boolean supportTso() { init(); } - return supportTso; + return this.mergedStorageInfo.isSupportTso(); } public boolean supportPurgeTso() { @@ -723,7 +723,7 @@ public boolean supportPurgeTso() { init(); } - return supportPurgeTso; + return this.mergedStorageInfo.isSupportPurgeTso(); } public boolean isLessMy56Version() { @@ -731,7 +731,7 @@ public boolean isLessMy56Version() { init(); } - return lessMy56Version; + return this.mergedStorageInfo.isLessMy56Version(); } public boolean isMysql80() { @@ -739,7 +739,7 @@ public boolean isMysql80() { init(); } - return isMysql80; + return this.mergedStorageInfo.isMysql80(); } public String getDnVersion() { @@ -760,7 +760,7 @@ public boolean supportTsoHeartbeat() { init(); } - return supportTsoHeartbeat; + return this.mergedStorageInfo.isSupportTsoHeartbeat(); } public boolean supportCtsTransaction() { @@ -768,7 +768,7 @@ public boolean supportCtsTransaction() { init(); } - return supportCtsTransaction; + return this.mergedStorageInfo.isSupportCtsTransaction(); } public boolean supportAsyncCommit() { @@ -776,7 +776,7 @@ public boolean supportAsyncCommit() { init(); } - return supportAsyncCommit; + return this.mergedStorageInfo.isSupportAsyncCommit(); } public boolean supportLizard1PCTransaction() { @@ -784,7 +784,7 @@ public boolean supportLizard1PCTransaction() { init(); } - return supportLizard1PCTransaction; + return this.mergedStorageInfo.isSupportLizard1PCTransaction(); } public boolean supportDeadlockDetection() { @@ -792,14 +792,14 @@ public boolean supportDeadlockDetection() { init(); } - return supportDeadlockDetection; + return this.mergedStorageInfo.isSupportDeadlockDetection(); } public boolean supportMdlDeadlockDetection() { if (!isInited()) { init(); } - return supportMdlDeadlockDetection; + return this.mergedStorageInfo.isSupportMdlDeadlockDetection(); } public boolean supportsBloomFilter() { @@ -807,7 +807,7 @@ public boolean supportsBloomFilter() { init(); } - return supportsBloomFilter; + return this.mergedStorageInfo.isSupportsBloomFilter(); } public boolean supportSharedReadView() { @@ -815,7 +815,7 @@ public boolean supportSharedReadView() { init(); } - return supportSharedReadView; + return this.mergedStorageInfo.isSupportSharedReadView(); } public boolean supportOpenSSL() { @@ -823,7 +823,7 @@ public boolean supportOpenSSL() { init(); } - return supportOpenSSL; + return this.mergedStorageInfo.isSupportOpenSSL(); } public boolean supportsHyperLogLog() { @@ -831,7 +831,7 @@ public boolean supportsHyperLogLog() { init(); } - return supportHyperLogLog; + return this.mergedStorageInfo.isSupportHyperLogLog(); } public boolean supportsXxHash() { @@ -839,7 +839,7 @@ public boolean supportsXxHash() { init(); } - return supportXxHash; + return this.mergedStorageInfo.isSupportXxHash(); } public boolean supportsReturning() { @@ -847,7 +847,7 @@ public boolean supportsReturning() { init(); } - return supportsReturning; + return this.mergedStorageInfo.isSupportsReturning(); } public boolean supportsBackfillReturning() { @@ -855,7 +855,7 @@ public boolean supportsBackfillReturning() { init(); } - return supportsBackfillReturning; + return this.mergedStorageInfo.isSupportsBackfillReturning(); } public boolean supportsAlterType() { @@ -863,66 +863,74 @@ public boolean supportsAlterType() { init(); } - return supportsAlterType; + return this.mergedStorageInfo.isSupportsAlterType(); } public boolean isReadOnly() { - return readOnly; + return this.mergedStorageInfo.isReadOnly(); } public boolean isLowerCaseTableNames() { - return lowerCaseTableNames; + return this.mergedStorageInfo.isLowerCaseTableNames(); } public boolean supportFastChecker() { if (!isInited()) { init(); } - return supportFastChecker; + return this.mergedStorageInfo.isSupportFastChecker(); } public boolean supportChangeSet() { if (!isInited()) { init(); } - return supportChangeSet; + return this.mergedStorageInfo.isSupportChangeSet(); } public boolean supportXOptForAutoSp() { if (!isInited()) { init(); } - return supportXOptForAutoSp; + return this.mergedStorageInfo.isSupportXOptForAutoSp(); } public boolean supportXRpc() { if (!isInited()) { init(); } - return supportXRpc; + return this.mergedStorageInfo.isSupportXRpc(); } public boolean isSupportMarkDistributed() { if (!isInited()) { init(); } - return supportMarkDistributed; + return this.mergedStorageInfo.isSupportMarkDistributed(); } public boolean supportXOptForPhysicalBackfill() { if (!isInited()) { init(); } - return supportXOptForPhysicalBackfill; + return this.mergedStorageInfo.isSupportXOptForPhysicalBackfill(); } - public boolean support2pcOpt() { + public boolean isSupportSyncPoint() { if (!isInited()) { init(); } - return support2pcOpt; + return this.mergedStorageInfo.isSupportSyncPoint(); } + public boolean isSupportFlashbackArea() { + if (!isInited()) { + init(); + } + return this.mergedStorageInfo.isSupportFlashbackArea(); + } + + public static class StorageInfo { public final String version; @@ -931,6 +939,7 @@ public static class StorageInfo { public final boolean supportPurgeTso; public final boolean supportCtsTransaction; public final boolean supportAsyncCommit; + public final boolean supportSyncpoint; public final boolean supportLizard1PCTransaction; public final boolean supportsBloomFilter; public final boolean supportsReturning; @@ -951,7 +960,7 @@ public static class StorageInfo { boolean supportXRpc; boolean supportXOptForPhysicalBackfill; boolean supportMarkDistributed; - boolean support2pcOpt; + boolean supportFlashbackArea; public StorageInfo( String version, @@ -980,7 +989,8 @@ public StorageInfo( boolean supportXRpc, boolean supportXOptForPhysicalBackfill, boolean supportMarkDistributed, - boolean support2pcOpt + boolean supportSyncPoint, + boolean supportFlashbackArea ) { this.version = version; this.supportTso = supportTso; @@ -1008,7 +1018,8 @@ public StorageInfo( this.supportXRpc = supportXRpc; this.supportXOptForPhysicalBackfill = supportXOptForPhysicalBackfill && supportXRpc; this.supportMarkDistributed = supportMarkDistributed; - this.support2pcOpt = support2pcOpt; + this.supportSyncpoint = supportSyncPoint; + this.supportFlashbackArea = supportFlashbackArea; } public static StorageInfo create(IDataSource dataSource) { @@ -1041,6 +1052,7 @@ public static StorageInfo create(IDataSource dataSource) { false, false, false, + false, false ); } @@ -1074,7 +1086,8 @@ public static StorageInfo create(IDataSource dataSource) { boolean supportXRpc = checkSupportXRpc(dataSource); boolean supportXoptForPhysicalBackfill = checkSupportXOptForPhysicalBackfill(dataSource); boolean supportMarkDistributed = checkSupportMarkDistributed(dataSource); - boolean support2pcOpt = checkSupport2pcOpt(dataSource); + boolean supportSyncPoint = checkSupportSyncPoint(dataSource); + boolean supportFlashbackArea = checkSupportFlashbackArea(dataSource); return new StorageInfo( version, @@ -1103,7 +1116,8 @@ public static StorageInfo create(IDataSource dataSource) { supportXRpc, supportXoptForPhysicalBackfill, supportMarkDistributed, - support2pcOpt); + supportSyncPoint, + supportFlashbackArea); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/GroupConcurrentUnionCursor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/GroupConcurrentUnionCursor.java index c6f3d332c..559719133 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/GroupConcurrentUnionCursor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/GroupConcurrentUnionCursor.java @@ -18,6 +18,8 @@ import com.alibaba.polardbx.common.ddl.newengine.DdlConstants; import com.alibaba.polardbx.common.exception.TddlException; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.TStringUtil; @@ -28,6 +30,9 @@ import com.alibaba.polardbx.executor.ddl.newengine.cross.GenericPhyObjectRecorder; import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlHelper; import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.executor.utils.failpoint.FailPointKey; +import com.alibaba.polardbx.optimizer.context.DdlContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.BaseQueryOperation; import com.alibaba.polardbx.optimizer.core.rel.PhyDdlTableOperation; @@ -133,7 +138,13 @@ public void doInit() { if (cursors.size() > 0) { currentCursor = cursors.get(currentIndex); } - } else if (executionContext.getParamManager().getBoolean(ConnectionParams.BLOCK_CONCURRENT)) { + } else if (executionContext.getParamManager().getBoolean(ConnectionParams.BLOCK_CONCURRENT) || isDDL) { + FailPoint.injectFromHint(FailPointKey.FP_PHYSICAL_DDL_INTERRUPTED, executionContext, () -> { + DdlContext ddlContext = executionContext.getDdlContext(); + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_INTERRUPTED, String.valueOf(ddlContext.getJobId()), + ddlContext.getSchemaName(), ddlContext.getObjectName()); + }); + List> futures = new ArrayList<>(subNodes.size()); for (RelNode subNode : subNodes) { GenericPhyObjectRecorder phyObjectRecorder = @@ -202,59 +213,17 @@ public void doInit() { } else { completedCursorQueue = new LinkedBlockingQueue<>(subNodes.size()); - if (isDDL) { - for (RelNode subNode : subNodes) { - GenericPhyObjectRecorder phyObjectRecorder = - CrossEngineValidator.getPhyObjectRecorder(subNode, executionContext); - if (!phyObjectRecorder.checkIfDone()) { - FutureCursor cursor = new FutureCursor(ExecutorContext.getContext(schemaName) - .getTopologyExecutor() - .execByExecPlanNodeFuture(subNode, executionContext, completedCursorQueue) - ); - cursors.add(cursor); - - String phyTableKey = genPhyTableKeyForDdl(subNode); - if (TStringUtil.isNotBlank(phyTableKey)) { - phyObjectRecorderMap.put(phyTableKey, phyObjectRecorder); - } - } else { - numObjectsSkipped.incrementAndGet(); - } - } - - if (numObjectsSkipped.get() == totalSize) { - super.doInit(); - return; - } - - } else { - //非DDL语句,走prefetch的逻辑 - prefetchCursor(); - } + //非DDL语句,走prefetch的逻辑 + prefetchCursor(); - GenericPhyObjectRecorder phyObjectRecorder = null; try { long startWaitNano = System.nanoTime(); Future future = completedCursorQueue.take(); currentCursor = future.get(); RuntimeStatHelper.statWaitLockTimecost(targetPlanStatGroup, startWaitNano); - - if (isDDL && currentCursor instanceof MyPhyDdlTableCursor) { - RelNode relNode = ((MyPhyDdlTableCursor) currentCursor).getRelNode(); - String phyTableKey = genPhyTableKeyForDdl(relNode); - if (TStringUtil.isNotBlank(phyTableKey)) { - phyObjectRecorder = phyObjectRecorderMap.get(phyTableKey); - if (phyObjectRecorder != null) { - numObjectsDone.incrementAndGet(); - phyObjectRecorder.recordDone(); - } - } - } } catch (Throwable e) { - if (phyObjectRecorder == null || !phyObjectRecorder.checkIfIgnoreException(e)) { - throw GeneralUtil.nestedException(e); - } + throw GeneralUtil.nestedException(e); } } super.doInit(); @@ -279,48 +248,24 @@ public Row doNext() { && currentIndex >= numObjectsDone.get()) { return null; } - } else if (currentIndex >= (isDDL ? cursors.size() : totalSize)) { + } else if (currentIndex >= totalSize) { // 取尽所有cursor return null; } if (currentCursor == null && completedCursorQueue != null) { - GenericPhyObjectRecorder phyObjectRecorder = null; try { long startWaitLockNano = System.nanoTime(); - Future future; - if (isDDL) { - future = completedCursorQueue.poll(MEDIAN_JOB_IDLE_WAITING_TIME, TimeUnit.MILLISECONDS); - if (future == null) { - // Try again - continue; - } - } else { - future = completedCursorQueue.take(); - } + Future future = completedCursorQueue.take(); currentCursor = future.get(); RuntimeStatHelper.statWaitLockTimecost(targetPlanStatGroup, startWaitLockNano); RuntimeStatHelper.registerCursorStatByParentCursor(executionContext, this, currentCursor); - - if (isDDL && currentCursor instanceof MyPhyDdlTableCursor) { - RelNode relNode = ((MyPhyDdlTableCursor) currentCursor).getRelNode(); - String phyTableKey = genPhyTableKeyForDdl(relNode); - if (TStringUtil.isNotBlank(phyTableKey)) { - phyObjectRecorder = phyObjectRecorderMap.get(phyTableKey); - if (phyObjectRecorder != null) { - numObjectsDone.incrementAndGet(); - phyObjectRecorder.recordDone(); - } - } - } } catch (ExecutionException e) { throw GeneralUtil.nestedException(e.getCause()); } catch (Throwable e) { - if (phyObjectRecorder == null || !phyObjectRecorder.checkIfIgnoreException(e)) { - throw GeneralUtil.nestedException(e); - } + throw GeneralUtil.nestedException(e); } } else if (currentCursor == null) { currentCursor = cursors.get(currentIndex); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/GroupSequentialCursor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/GroupSequentialCursor.java index c79629024..5dd425616 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/GroupSequentialCursor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/GroupSequentialCursor.java @@ -21,33 +21,34 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.properties.ConnectionParams; -import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.cursor.AbstractCursor; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.ddl.newengine.cross.CrossEngineValidator; import com.alibaba.polardbx.executor.ddl.newengine.cross.GenericPhyObjectRecorder; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.executor.utils.failpoint.FailPointKey; import com.alibaba.polardbx.optimizer.context.DdlContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.BaseTableOperation; import com.alibaba.polardbx.optimizer.core.row.Row; -import com.alibaba.polardbx.statistics.RuntimeStatHelper; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; import org.apache.calcite.rel.RelNode; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.FutureTask; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; public class GroupSequentialCursor extends AbstractCursor { + private final static Logger LOG = SQLRecorderLogger.ddlEngineLogger; + protected String schemaName; protected Map> plansByInstance; protected int totalSize = 0; @@ -58,13 +59,9 @@ public class GroupSequentialCursor extends AbstractCursor { protected List cursors = new ArrayList<>(); protected final ReentrantLock cursorLock = new ReentrantLock(); - protected AtomicBoolean started = new AtomicBoolean(false); protected AtomicInteger numObjectsDone = new AtomicInteger(0); protected AtomicInteger numObjectsSkipped = new AtomicInteger(0); - protected BlockingQueue completedCursorQueue; - - protected static final int INTERRUPT_TIMEOUT = 10 * 1000; - protected static final int EMPTY_QUEUE_CHECK_TIMEOUT = 60 * 1000; + protected List>> futures; protected List exceptionsWhenCloseSubCursor = new ArrayList<>(); protected List exceptions; @@ -77,7 +74,7 @@ public GroupSequentialCursor(Map> plansByInstance, Executi for (List plans : this.plansByInstance.values()) { this.totalSize += plans.size(); } - this.completedCursorQueue = new LinkedBlockingQueue<>(this.totalSize); + this.futures = new ArrayList<>(this.plansByInstance.size()); this.executionContext = executionContext; this.exceptions = Collections.synchronizedList(exceptions); @@ -97,31 +94,38 @@ public void doInit() { String traceId = executionContext.getTraceId(); for (List plans : plansByInstance.values()) { // Inter-instance in parallel and intra-instance sequentially - executionContext.getExecutorService().submit(schemaName, traceId, AsyncTask.build(() -> { + FutureTask> futureTask = new FutureTask<>(() -> { // Execute sequentially on the same instance - executeSequentially(plans); - })); + return executeSequentially(plans); + }); + futures.add(futureTask); + executionContext.getExecutorService().submit(schemaName, traceId, AsyncTask.build(futureTask)); } super.doInit(); } - private void executeSequentially(List plans) { + private List executeSequentially(List plans) { int numObjectsCountedOnInstance = 0; int delay = executionContext.getParamManager().getInt(ConnectionParams.EMIT_PHY_TABLE_DDL_DELAY); if (delay > 0) { try { - Thread.sleep(delay * 1000); + Thread.sleep(delay * 1000L); } catch (InterruptedException e) { } } + List retCursors = new ArrayList<>(); for (RelNode plan : plans) { GenericPhyObjectRecorder phyObjectRecorder = CrossEngineValidator.getPhyObjectRecorder(plan, executionContext); - try { - started.set(true); + if (CrossEngineValidator.isJobInterrupted(executionContext)) { + throwException(); + } + + FailPoint.injectFromHint(FailPointKey.FP_PHYSICAL_DDL_INTERRUPTED, executionContext, this::throwException); + try { if (!phyObjectRecorder.checkIfDone()) { Cursor cursor = ExecutorContext.getContext(schemaName) .getTopologyExecutor() @@ -139,7 +143,7 @@ private void executeSequentially(List plans) { cursorLock.unlock(); } - completedCursorQueue.put(cursor); + retCursors.add(cursor); numObjectsDone.incrementAndGet(); numObjectsCountedOnInstance++; } else { @@ -162,68 +166,42 @@ private void executeSequentially(List plans) { // Skip the rest of objects. numObjectsSkipped.addAndGet(plans.size() - numObjectsCountedOnInstance); // Don't continue anymore since the job has been cancelled. - return; + return retCursors; } } - } + return retCursors; } @Override public Row doNext() { init(); - Row ret; - - long cursorStartTime = System.currentTimeMillis(); - long elapsedTimeBeforeStart; - long emptyQueueStartTime = System.currentTimeMillis(); - long emptyQueueDuration; - - while (true) { - if ((numObjectsDone.get() + numObjectsSkipped.get() == totalSize) && currentIndex >= numObjectsDone.get()) { - return null; - } + for (FutureTask> future : futures) { + try { + List cursors = future.get(); - if (numObjectsDone.get() == 0 && numObjectsSkipped.get() == 0 && !started.get()) { - elapsedTimeBeforeStart = System.currentTimeMillis() - cursorStartTime; - if (elapsedTimeBeforeStart >= INTERRUPT_TIMEOUT) { - // The DDL job is very likely to have been interrupted and - // never proceed, so we have to terminate. - throwException(); - } - } + for (Cursor cursor : cursors) { + currentCursor = cursor; - if (currentCursor == null) { - try { - currentCursor = completedCursorQueue.poll(DdlConstants.MEDIAN_WAITING_TIME, TimeUnit.MILLISECONDS); - if (currentCursor == null) { - emptyQueueDuration = System.currentTimeMillis() - emptyQueueStartTime; - if (emptyQueueDuration > EMPTY_QUEUE_CHECK_TIMEOUT && - CrossEngineValidator.isJobInterrupted(executionContext)) { - // The job has been cancelled/interrupted, so we have to terminate this - // to avoid occupying the job scheduler permanently in some scenarios. - throwException(); - } - // Try again - continue; + if (currentCursor != null) { + currentCursor.next(); } - emptyQueueStartTime = System.currentTimeMillis(); - } catch (InterruptedException e) { - throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, "The DDL job has been interrupted"); - } catch (Throwable t) { - throw GeneralUtil.nestedException(t); + + switchCursor(); } - RuntimeStatHelper.registerCursorStatByParentCursor(executionContext, this, currentCursor); + } catch (Throwable e) { + exceptions.add(e); } + } - ret = currentCursor.next(); - if (ret != null) { - return ret; - } + // 打印完成情况 + String errMsg = "GroupSequentialCursor physical DDLs execute info: " + + totalSize + " expected, " + numObjectsDone + " done, " + + numObjectsSkipped + " skipped."; + LOG.info(errMsg); - switchCursor(); - } + return null; } protected void switchCursor() { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/MyPhysicalCursor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/MyPhysicalCursor.java index 94cef2f6b..5e10c906d 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/MyPhysicalCursor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/MyPhysicalCursor.java @@ -17,9 +17,13 @@ package com.alibaba.polardbx.executor.cursor.impl; import com.alibaba.polardbx.executor.cursor.AbstractCursor; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.statis.OperatorStatisticsExt; +import com.alibaba.polardbx.optimizer.utils.QueryConcurrencyPolicy; import org.apache.calcite.rel.RelNode; +import static com.alibaba.polardbx.executor.utils.ExecUtils.getQueryConcurrencyPolicy; + /** * @author chenghui.lch */ @@ -44,4 +48,22 @@ public RelNode getRelNode() { public void setRelNode(RelNode relNode) { this.relNode = relNode; } + + /** + * For multi get, delay the initialization to next method. If + * GROUP_CONCURRENT_BLOCK is set, initialization should call at first. + */ + protected boolean isDelayInit(ExecutionContext executionContext) { + QueryConcurrencyPolicy queryConcurrencyPolicy = getQueryConcurrencyPolicy(executionContext); + + switch (queryConcurrencyPolicy) { + case GROUP_CONCURRENT_BLOCK: + case RELAXED_GROUP_CONCURRENT: + case CONCURRENT: + case FIRST_THEN_CONCURRENT: + return false; + default: + return true; + } + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/OutFileStatisticsCursor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/OutFileStatisticsCursor.java index 66f1090c9..9505ae62d 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/OutFileStatisticsCursor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/cursor/impl/OutFileStatisticsCursor.java @@ -78,6 +78,7 @@ import org.apache.calcite.sql.OutFileParams; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.text.StringEscapeUtils; import org.eclipse.jetty.util.StringUtil; import java.sql.Connection; @@ -225,6 +226,7 @@ public OutFileStatisticsCursor( this.iColumnMeta = new ColumnMeta(null, "sql", null, col); outFileParams.setColumnMeata(Lists.newArrayList(iColumnMeta)); + outFileParams.setFieldEscape(null); SpillMonitor spillMonitor = context.getQuerySpillSpaceMonitor(); this.context = context; singleStreamSpiller = (AsyncFileSingleBufferSpiller) @@ -657,12 +659,13 @@ public void prepareStatistics(Map sources) { param.add("'" + rs.getString("CMSKETCH") + "'"); boolean ignoreColumn = ignoreStringColumn(currentSchema, currentTable, currentColumn); - param.add(ignoreColumn ? "''" : "'" + rs.getString("HISTOGRAM") + "'"); + param.add( + ignoreColumn ? "''" : "'" + StringEscapeUtils.escapeJava(rs.getString("HISTOGRAM")) + "'"); if (ignoreColumn || StringUtils.isEmpty(rs.getString("TOPN"))) { param.add(null); } else { - param.add("'" + rs.getString("TOPN") + "'"); + param.add("'" + StringEscapeUtils.escapeJava(rs.getString("TOPN")) + "'"); } param.add(String.valueOf(rs.getLong("NULL_COUNT"))); param.add(String.valueOf(rs.getFloat("SAMPLE_RATE"))); @@ -751,6 +754,21 @@ public void prepareSessionVariables() { } } + private static String mysqlRealEscapeString(String sql) { + byte[] bytes = sql.getBytes(); + ArrayList bytesAfterProcess = new ArrayList<>(bytes.length); + for (Byte b : bytes) { + if (b == '\"') { + bytesAfterProcess.add((byte) '\\'); + } else if (b == '\\') { + bytesAfterProcess.add((byte) '\\'); + } + bytesAfterProcess.add(b); + } + //return new String(Bytes.toArray(bytesAfterProcess)); + return sql; + } + static class SourceInUsed { Set tables; Set views; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/ImplicitTableGroupUtil.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/ImplicitTableGroupUtil.java index 24aecd95f..ed9799d70 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/ImplicitTableGroupUtil.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/ImplicitTableGroupUtil.java @@ -61,6 +61,7 @@ import lombok.Data; import lombok.Getter; import lombok.Setter; +import org.apache.calcite.sql.SqlIdentifier; import org.apache.commons.lang.StringUtils; import java.util.HashMap; @@ -283,7 +284,7 @@ private static boolean process4AlterItems(String schemaName, String tableName, } } - if (alterTableStatement.getPartition() != null) { + if (alterTableStatement.getPartition() != null || alterTableStatement.isRemovePatiting()) { changed |= process4Repartition(schemaName, tableName, alterTableStatement, forCheck, tgGroups); } @@ -299,6 +300,7 @@ private static boolean isAlterTableWithPartition(SQLAlterTableItem item) { private static boolean process4Repartition(String schemaName, String tableName, SQLAlterTableStatement alterTableStatement, boolean forCheck, Set tgGroups) { + boolean changed = false; TableGroupConfig tableGroupConfig = tableGroupConfigProvider.getTableGroupConfig(schemaName, buildQueryTableName(tableName), true); if (forCheck || tableGroupConfig == null) { @@ -316,10 +318,42 @@ private static boolean process4Repartition(String schemaName, String tableName, tryCheckTgName(alterTableStatement.getTargetImplicitTableGroup(), tableGroupConfig); alterTableStatement.setTargetImplicitTableGroup( new SQLIdentifierExpr(tableGroupConfig.getTableGroupRecord().getTg_name())); - return true; + changed = true; } } - return false; + + if (alterTableStatement.isRemovePatiting()) { + PartitionColumnInfo partitionColumnInfo = + tableGroupConfigProvider.getPartitionColumnInfo(schemaName, tableName); + for (Map.Entry> i : partitionColumnInfo.gsiPartitionColumns.entrySet()) { + TableGroupConfig config = tableGroupConfigProvider.getTableGroupConfig( + schemaName, tableName, buildQueryGsiName(i.getKey()), false); + if (config != null && !config.isManuallyCreated()) { + if (forCheck) { + Pair pair = alterTableStatement.getIndexTableGroupPair().stream() + .filter(p -> StringUtils.equalsIgnoreCase(SQLUtils.normalize(p.getKey().getSimpleName()), + i.getKey())) + .findFirst().orElse(null); + Assert.assertNotNull(pair); + forceCheckTgName(pair.getValue().getSimpleName(), + config.getTableGroupRecord().getTg_name()); + tgGroups.add(pair.getValue().getSimpleName()); + } else { + if (alterTableStatement.getIndexTableGroupPair().stream() + .noneMatch(p -> StringUtils.equalsIgnoreCase(SQLUtils.normalize(p.getKey().getSimpleName()), + i.getKey()))) { + alterTableStatement.addIndexTableGroupPair( + new SQLIdentifierExpr(SqlIdentifier.surroundWithBacktick(i.getKey())), + new SQLIdentifierExpr(config.getTableGroupRecord().tg_name)); + } + changed = true; + } + } + + } + } + + return changed; } private static boolean process4CreateIndex(String schemaName, String tableName, @@ -492,15 +526,18 @@ private static boolean process4ModifyColumn(String schemaName, String tableName, if (config != null && !config.isManuallyCreated()) { if (forCheck) { Pair pair = alterTableStatement.getIndexTableGroupPair().stream() - .filter(p -> StringUtils.equalsIgnoreCase(p.getKey().getSimpleName(), i.getKey())) + .filter(p -> StringUtils.equalsIgnoreCase(SQLUtils.normalize(p.getKey().getSimpleName()), + i.getKey())) .findFirst().orElse(null); Assert.assertNotNull(pair); forceCheckTgName(pair.getValue().getSimpleName(), config.getTableGroupRecord().getTg_name()); tgGroups.add(pair.getValue().getSimpleName()); } else { if (alterTableStatement.getIndexTableGroupPair().stream() - .noneMatch(p -> StringUtils.equalsIgnoreCase(p.getKey().getSimpleName(), i.getKey()))) { - alterTableStatement.addIndexTableGroupPair(new SQLIdentifierExpr(i.getKey()), + .noneMatch(p -> StringUtils.equalsIgnoreCase(SQLUtils.normalize(p.getKey().getSimpleName()), + i.getKey()))) { + alterTableStatement.addIndexTableGroupPair( + new SQLIdentifierExpr(SqlIdentifier.surroundWithBacktick(i.getKey())), new SQLIdentifierExpr(config.getTableGroupRecord().tg_name)); } changed = true; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/AlterPartitionTableOptimizePartitionBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/AlterPartitionTableOptimizePartitionBuilder.java new file mode 100644 index 000000000..c599ec84b --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/AlterPartitionTableOptimizePartitionBuilder.java @@ -0,0 +1,47 @@ +package com.alibaba.polardbx.executor.ddl.job.builder; + +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ReplaceTableNameWithQuestionMarkVisitor; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTablePreparedData; +import com.alibaba.polardbx.optimizer.parse.FastsqlParser; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionInfoUtil; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; +import org.apache.calcite.rel.core.DDL; +import org.apache.calcite.sql.SqlNode; + +import java.util.List; +import java.util.stream.Collectors; + +public class AlterPartitionTableOptimizePartitionBuilder extends AlterTableBuilder { + + public AlterPartitionTableOptimizePartitionBuilder(DDL ddl, AlterTablePreparedData preparedData, + ExecutionContext executionContext) { + super(ddl, preparedData, executionContext); + } + + @Override + public void buildTableRuleAndTopology() { + partitionInfo = OptimizerContext.getContext(preparedData.getSchemaName()).getPartitionInfoManager() + .getPartitionInfo(preparedData.getTableName()); + PartitionInfo tempPartitionInfo = partitionInfo.copy(); + List targetTruncatePartitionSpecs = tempPartitionInfo.getPartitionBy().getPartitions().stream() + .filter(o -> preparedData.getTruncatePartitionNames().contains(o.getName())).collect( + Collectors.toList()); + tempPartitionInfo.getPartitionBy().setPartitions(targetTruncatePartitionSpecs); + tableTopology = PartitionInfoUtil.buildTargetTablesFromPartitionInfo(tempPartitionInfo); + } + + @Override + protected void buildSqlTemplate() { + final SqlNode primaryTableNode = new FastsqlParser() + .parse("truncate table " + preparedData.getTableName(), executionContext) + .get(0); + ReplaceTableNameWithQuestionMarkVisitor visitor = + new ReplaceTableNameWithQuestionMarkVisitor(ddlPreparedData.getSchemaName(), executionContext); + this.sqlTemplate = primaryTableNode.accept(visitor); + this.originSqlTemplate = this.sqlTemplate; + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/CreatePartitionTableBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/CreatePartitionTableBuilder.java index 65a8b500f..2fe77c48a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/CreatePartitionTableBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/CreatePartitionTableBuilder.java @@ -104,19 +104,30 @@ protected PartitionInfo buildPartitionInfo() { } else if (preparedData.isGsi() && !preparedData.isSharding() && preparedData.getPartitioning() == null) { partitionTableType = PartitionTableType.GSI_SINGLE_TABLE; } +// partitionInfo = +// PartitionInfoBuilder.buildPartitionInfoByPartDefAst(preparedData.getSchemaName(), tbName, tableGroupName, +// preparedData.isWithImplicitTableGroup(), joinGroupName, (SqlPartitionBy) preparedData.getPartitioning(), +// preparedData.getPartBoundExprInfo(), +// pkColMetas, allColMetas, partitionTableType, executionContext, localityDesc); +// partitionInfo.setTableType(partitionTableType); + + boolean ttlTemporary = preparedData.isTtlTemporary(); partitionInfo = PartitionInfoBuilder.buildPartitionInfoByPartDefAst(preparedData.getSchemaName(), tbName, tableGroupName, preparedData.isWithImplicitTableGroup(), joinGroupName, (SqlPartitionBy) preparedData.getPartitioning(), preparedData.getPartBoundExprInfo(), - pkColMetas, allColMetas, partitionTableType, executionContext, localityDesc); + pkColMetas, allColMetas, partitionTableType, executionContext, localityDesc, ttlTemporary); partitionInfo.setTableType(partitionTableType); // // Set auto partition flag only on primary table. if (tblType == PartitionTableType.PARTITION_TABLE) { assert relDdl.sqlNode instanceof SqlCreateTable; - partitionInfo.setPartFlags( - ((SqlCreateTable) relDdl.sqlNode).isAutoPartition() ? TablePartitionRecord.FLAG_AUTO_PARTITION : 0); + long partFlag = partitionInfo.getPartFlags(); + if (((SqlCreateTable) relDdl.sqlNode).isAutoPartition()) { + partFlag |= TablePartitionRecord.FLAG_AUTO_PARTITION; + } + partitionInfo.setPartFlags(partFlag); // TODO(moyi) write a builder for autoFlag int autoFlag = ((SqlCreateTable) relDdl.sqlNode).isAutoSplit() ? TablePartitionRecord.PARTITION_AUTO_BALANCE_ENABLE_ALL : 0; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/CreateTableBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/CreateTableBuilder.java index dc5b9af8e..0544d5360 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/CreateTableBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/CreateTableBuilder.java @@ -194,7 +194,7 @@ && checkDatabaseEncryption(preparedData.getSchemaName())) { false, sqlTemplate.getAutoIncrement(), null, - sqlTemplate.getLocalPartition(), + null, null, null, sqlTemplate.getLocalPartitionSuffix() diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/DdlPhyPlanBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/DdlPhyPlanBuilder.java index 7cfac148b..fb3809445 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/DdlPhyPlanBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/DdlPhyPlanBuilder.java @@ -27,6 +27,17 @@ import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.model.Group; import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.druid.sql.SQLUtils; +import com.alibaba.polardbx.druid.sql.ast.SQLExpr; +import com.alibaba.polardbx.druid.sql.ast.SQLStatement; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableAddIndex; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableItem; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLTableElement; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.MySqlKey; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex; +import com.alibaba.polardbx.druid.util.JdbcConstants; import com.alibaba.polardbx.executor.ddl.job.converter.DdlJobDataConverter; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.meta.delegate.TableInfoManagerDelegate; @@ -53,7 +64,9 @@ import org.apache.calcite.sql.SequenceBean; import org.apache.calcite.sql.SqlCreateTable; import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlTable; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.validate.SqlValidatorImpl; import org.apache.commons.collections.CollectionUtils; @@ -71,6 +84,9 @@ */ public abstract class DdlPhyPlanBuilder { + // this sql is only used for build sql for add local index. + private static final String ADD_INDEX_SQL = "ALTER TABLE t1 ADD INDEX k1(c1);"; + protected DDL relDdl; protected DdlPreparedData ddlPreparedData; @@ -90,6 +106,7 @@ public abstract class DdlPhyPlanBuilder { protected PartitionInfo partitionInfo; protected Map>> tableTopology; protected List physicalPlans; + protected List physicalPlansForLocalIndex; protected boolean tableRuleFromMeta = false; @@ -130,9 +147,12 @@ public DdlPhyPlanBuilder build() { * * @return physical plan */ - public PhysicalPlanData genPhysicalPlanData(boolean autoPartition) { + public PhysicalPlanData genPhysicalPlanData(boolean autoPartition, boolean forLocalIndex) { Objects.requireNonNull(tableTopology); Objects.requireNonNull(physicalPlans); + if (forLocalIndex) { + Objects.requireNonNull(physicalPlansForLocalIndex); + } if (!built) { throw new AssertionError("DdlPhyPlanBuilder::build has not been called!"); } @@ -143,11 +163,22 @@ public PhysicalPlanData genPhysicalPlanData(boolean autoPartition) { if (relDdl.sqlNode instanceof SqlCreateTable) { Engine tableEngine = ((SqlCreateTable) relDdl.sqlNode).getEngine(); boolean pushDownFk = ((SqlCreateTable) relDdl.sqlNode).getPushDownForeignKeys(); - return DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, physicalPlans, false, autoPartition, - Engine.isFileStore(tableEngine), pushDownFk, executionContext); + if (forLocalIndex) { + return DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, physicalPlansForLocalIndex, false, + autoPartition, Engine.isFileStore(tableEngine), pushDownFk, executionContext); + } else { + return DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, physicalPlans, false, autoPartition, + Engine.isFileStore(tableEngine), pushDownFk, executionContext); + } } else { - return DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, physicalPlans, false, autoPartition, - executionContext); + if (forLocalIndex) { + return DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, physicalPlansForLocalIndex, false, + autoPartition, + executionContext); + } else { + return DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, physicalPlans, false, autoPartition, + executionContext); + } } } @@ -155,6 +186,10 @@ public PhysicalPlanData genPhysicalPlanData() { return genPhysicalPlanData(false); } + public PhysicalPlanData genPhysicalPlanData(boolean autoPartition) { + return genPhysicalPlanData(autoPartition, false); + } + protected void buildExistingTableRule(String tableName) { this.tableRule = optimizerContext.getRuleManager().getTddlRule().getTable(tableName); if (this.tableRule == null) { @@ -246,6 +281,52 @@ protected void buildPhysicalPlans(String tableName) { this.physicalPlans = physicalPlans; } + protected void buildPhysicalPlansForLocalIndex(String tableName) { +// initParameterIndex(); + + SqlNode newTableName = relDdl.getNewTableName(); + + List physicalPlans = new ArrayList<>(); + List indexes = ((SqlCreateTable) sqlTemplate).getLocalIndexes(); + if (indexes == null || indexes.size() == 0) { + this.physicalPlansForLocalIndex = null; + return; + } + String sql = buildSqlForAddLocalIndex(indexes); + for (Map.Entry>> t : tableTopology.entrySet()) { + String group = t.getKey(); + List> tableNames = t.getValue(); + for (List subTableNames : tableNames) { + // 这里是为每个分表 构建 mysql 物理执行计划 (建物理表) + // 需要替换为 oss 表构建计划 + PhyDdlTableOperation phyDdlTable = + PhyDdlTableOperation.create(ddlPreparedData.getSchemaName(), tableName, executionContext); + phyDdlTable.setDbIndex(group); + phyDdlTable.setLogicalTableName(tableName); + if (newTableName != null) { + phyDdlTable.setRenameLogicalTableName(((SqlIdentifier) newTableName).getLastName()); + } + phyDdlTable.setTableNames(ImmutableList.of(subTableNames)); + phyDdlTable.setKind(SqlKind.ALTER_TABLE); + Pair> sqlAndParam = + buildSqlAndParamForLocalIndex(sql, subTableNames); + phyDdlTable.setBytesSql(sqlAndParam.getKey()); + phyDdlTable.setNativeSqlNode(sqlTemplate); + phyDdlTable.setDbType(DbType.MYSQL); + phyDdlTable.setParam(sqlAndParam.getValue()); + phyDdlTable.setTableRule(tableRule); + phyDdlTable.setPartitioned( + tableRule != null && !PlannerUtils.isSingleTable(tableRule) && !tableRule.isBroadcast()); + phyDdlTable.setPartitionInfo(partitionInfo); + phyDdlTable.setSequence(sequenceBean); + phyDdlTable.setHint(ddlPreparedData.isWithHint()); + phyDdlTable.setSchemaName(ddlPreparedData.getSchemaName()); + physicalPlans.add(phyDdlTable); + } + } + this.physicalPlansForLocalIndex = physicalPlans; + } + protected void initParameterIndex() { if (tableTopology != null) { if (tableTopology.keySet().size() == 0) { @@ -287,6 +368,42 @@ private Pair> buildSqlAndParam(List(BytesSql.getBytesSql(sql), params); } + private Pair> buildSqlAndParamForLocalIndex(String sql, + List tableNames) { + Preconditions.checkArgument(CollectionUtils.isNotEmpty(tableNames)); + Engine engine; + if (this.sqlTemplate instanceof SqlCreateTable + && Engine.isFileStore(engine = ((SqlCreateTable) this.sqlTemplate).getEngine())) { + // for file-store engine, avoid to generate MySQL physical sql with engine info. + } else { + + Map params = buildParams(tableNames); + return new Pair<>(BytesSql.getBytesSql(sql), params); + } + return null; + } + + private String buildSqlForAddLocalIndex(List indexes) { + SQLAlterTableStatement alterStatement = + (SQLAlterTableStatement) SQLUtils.parseStatementsWithDefaultFeatures(ADD_INDEX_SQL, + JdbcConstants.MYSQL).get(0); + SQLAlterTableAddIndex item = (SQLAlterTableAddIndex) alterStatement.getItems().get(0); + List sqlAlterTableAddIndexes = new ArrayList<>(); + for (SQLTableElement index : indexes) { + SQLAlterTableAddIndex sqlAlterTableAddIndex = (SQLAlterTableAddIndex) item.clone(); + if (index instanceof MySqlTableIndex) { + sqlAlterTableAddIndex.setIndexDefinition(((MySqlTableIndex) index).getIndexDefinition()); + } else if (index instanceof MySqlKey) { + sqlAlterTableAddIndex.setIndexDefinition(((MySqlKey) index).getIndexDefinition()); + } + sqlAlterTableAddIndexes.add(sqlAlterTableAddIndex); + } + alterStatement.setItems(sqlAlterTableAddIndexes); + alterStatement.setTableSource(new SQLIdentifierExpr("?", 0)); + String sql = alterStatement.toString(); + return sql; + } + private Map buildParams(List tableNames) { Preconditions.checkArgument(CollectionUtils.isNotEmpty(tableNames)); return PlannerUtils.buildParam(tableNames, this.params, paramIndex); @@ -325,6 +442,10 @@ public List getPhysicalPlans() { return physicalPlans; } + public List getPhysicalPlansForLocalIndex() { + return physicalPlansForLocalIndex; + } + public SqlNode getSqlTemplate() { return sqlTemplate; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/DirectPhysicalSqlPlanBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/DirectPhysicalSqlPlanBuilder.java index 473a81c4a..6299f6fe9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/DirectPhysicalSqlPlanBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/DirectPhysicalSqlPlanBuilder.java @@ -46,7 +46,6 @@ public void buildTableRuleAndTopology() { buildExistingTableRule(tableName); buildChangedTableTopology(schemaName, tableName); } - } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/TruncateTableBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/TruncateTableBuilder.java index 21341ae1c..ca92732f8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/TruncateTableBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/TruncateTableBuilder.java @@ -19,15 +19,12 @@ import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; import com.alibaba.polardbx.optimizer.core.rel.ReplaceTableNameWithQuestionMarkVisitor; -import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalDropTable; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalTruncateTable; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.TruncateTablePreparedData; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.rel.core.DDL; -import org.apache.calcite.rel.ddl.DropTable; import org.apache.calcite.rel.ddl.TruncateTable; import org.apache.calcite.sql.SqlDdlNodes; -import org.apache.calcite.sql.SqlDropTable; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlTruncateTable; import org.apache.calcite.sql.parser.SqlParserPos; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreateGlobalIndexBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreateGlobalIndexBuilder.java index d871e6261..0792ac106 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreateGlobalIndexBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreateGlobalIndexBuilder.java @@ -44,6 +44,7 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex; import com.alibaba.polardbx.druid.util.JdbcConstants; +import com.alibaba.polardbx.executor.ddl.job.builder.AlterTableBuilder; import com.alibaba.polardbx.executor.ddl.job.builder.CreateTableBuilder; import com.alibaba.polardbx.executor.ddl.job.builder.DdlPhyPlanBuilder; import com.alibaba.polardbx.executor.gsi.GsiUtils; @@ -99,10 +100,14 @@ import java.util.TreeSet; import java.util.stream.Collectors; +import static org.apache.calcite.sql.SqlIdentifier.surroundWithBacktick; + public class CreateGlobalIndexBuilder extends DdlPhyPlanBuilder { protected final CreateGlobalIndexPreparedData gsiPreparedData; + protected String alterTableStmt; + protected CreateTableBuilder indexTableBuilder; public CreateGlobalIndexBuilder(@Deprecated DDL ddl, CreateGlobalIndexPreparedData gsiPreparedData, @@ -373,7 +378,7 @@ protected SqlNode buildIndexTableDefinition(final SqlAlterTable sqlAlterTable, f final Set indexShardingColumns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); indexShardingColumns.addAll(indexRule.getShardColumns()); - return createIndexTable(sqlAlterTable, + SqlNode createIndex = createIndexTable(sqlAlterTable, indexColumnMap, coveringMap, astCreateIndexTable, @@ -383,6 +388,7 @@ protected SqlNode buildIndexTableDefinition(final SqlAlterTable sqlAlterTable, f gsiPreparedData.getSchemaName(), gsiPreparedData.getPrimaryTableName(), executionContext); + return createIndex; } protected SqlNode buildIndexTableDefinition(final SqlCreateIndex sqlCreateIndex) { @@ -531,6 +537,11 @@ protected void removeIndexOnGsi(Set fullColumn, SQLIndex key) { for (SQLSelectOrderByItem column : key.getColumns()) { final String columnName = SqlCreateTable.getIndexColumnName(column); + if (columnName == null) { + //函数索引,去除掉 + iterator.remove(); + break; + } if (fullColumn.contains(columnName)) { continue; } @@ -562,6 +573,22 @@ protected void genUniqueIndexForUGSI(MySqlCreateTableStatement indexTableStmt, List pkList) { } + protected List popIndexForGSI(MySqlCreateTableStatement indexTableStmt) { + List tableIndexList = new ArrayList<>(); + tableIndexList.addAll(indexTableStmt.getMysqlIndexes()); + List tableElements = indexTableStmt.getTableElementList(); + tableElements.removeAll(tableIndexList); + List tableKeyList = indexTableStmt.getMysqlKeys(); + for (MySqlKey mySqlKey : tableKeyList) { + if (!(mySqlKey instanceof MySqlPrimaryKey)) { + tableElements.remove(mySqlKey); + tableIndexList.add(mySqlKey); + } + } + indexTableStmt.setTableElementList(tableElements); + return tableIndexList; + } + private boolean ukContainsPartKey(List uk, List partKey) { final Set partKeySet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); final Set ukSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); @@ -654,7 +681,7 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName, final String gsiName = indexTableName.getLastName(); // update index table name - indexTableStmt.setTableName(SqlIdentifier.surroundWithBacktick(gsiName)); + indexTableStmt.setTableName(surroundWithBacktick(gsiName)); final Iterator it = indexTableStmt.getTableElementList().iterator(); final Set sortedCovering = new LinkedHashSet<>(); @@ -670,9 +697,13 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName, String duplicatedIndexName = null; List pkList = new ArrayList<>(); TableMeta primaryTableMeta = ec.getSchemaManager(schemaName).getTableWithNull(primaryTableName); + Boolean buildLocalIndexLater = + unique ? false : ec.getParamManager().getBoolean(ConnectionParams.GSI_BUILD_LOCAL_INDEX_LATER); boolean isColumnar = GsiUtils.isAddCci(relDdl.getSqlNode(), sqlAlterTable); + boolean ugsiWithPk = ec.getParamManager().getBoolean(ConnectionParams.UNIQUE_GSI_WITH_PRIMARY_KEY); + // Generated column can not be sharding key if (primaryTableMeta != null) { for (String col : indexShardingKey) { @@ -735,7 +766,7 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName, "multiple primary key definition"); } pkList.add(new SQLSelectOrderByItem(columnDefinition.getName())); - if (unique) { + if (unique && !ugsiWithPk) { removePkOnGsi(constraintIt); } } else if (constraint instanceof SQLColumnReference) { @@ -777,7 +808,7 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName, "multiple primary key definition"); } pkList.addAll(primaryKey.getColumns()); - if (unique) { + if (unique && !ugsiWithPk) { removePkOnGsi(it); } } else if (tableElement instanceof MySqlKey) { @@ -808,7 +839,8 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName, // remove partitioning will drop all indexes on the other new gsi // convert the local index on new primary table (gsi) if (!indexName.contains(TddlConstants.AUTO_LOCAL_INDEX_PREFIX)) { - key.setName(new SQLIdentifierExpr(TddlConstants.AUTO_LOCAL_INDEX_PREFIX + indexName)); + key.setName(new SQLIdentifierExpr( + surroundWithBacktick(TddlConstants.AUTO_LOCAL_INDEX_PREFIX + indexName))); } continue; } @@ -852,7 +884,8 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName, // remove partitioning will drop all indexes on the other new gsi // convert the local index on new primary table (gsi) if (!indexName.contains(TddlConstants.AUTO_LOCAL_INDEX_PREFIX)) { - tableIndex.setName(new SQLIdentifierExpr(TddlConstants.AUTO_LOCAL_INDEX_PREFIX + indexName)); + tableIndex.setName(new SQLIdentifierExpr( + surroundWithBacktick(TddlConstants.AUTO_LOCAL_INDEX_PREFIX + indexName))); } continue; } @@ -880,10 +913,7 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName, } } - // Generate simple index of pk on unique GSI. - if (unique && !pkList.isEmpty()) { - genSimpleIndexForUGSI(indexTableStmt, pkList); - } + validatePartitionColumnInPkForLocalPartition(pkList); // For alter repartition. Generate simple index of other gsi partition key // 1. when alter table to single or broadcast, because the other gsi tables will be dropped @@ -948,6 +978,11 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName, // add local index, such as auto_shard_key i_ addLocalIndex(indexColumnMap, indexTableStmt, unique, true, options); + + // Generate simple index of pk on unique GSI. + if (unique && !pkList.isEmpty() && !ugsiWithPk) { + genSimpleIndexForUGSI(indexTableStmt, pkList); + } // // if (isRepartition()) { // addLocalIndex(indexColumnMap, indexTableStmt, unique, options); @@ -959,11 +994,15 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName, // addLocalIndex(indexColumnMap, indexTableStmt, unique, options); // } // } + List localIndexList = new ArrayList<>(); + if (buildLocalIndexLater) { + localIndexList = popIndexForGSI(indexTableStmt); + } // Generate unique index of pk on unique GSI. // the unique index will be dropped when backfill finish Map tableMetaMap = ec.getSchemaManager(schemaName).getCache(); - if (unique && !pkList.isEmpty() && tableMetaMap != null && tableMetaMap.containsKey( + if (unique && !pkList.isEmpty() && !ugsiWithPk && tableMetaMap != null && tableMetaMap.containsKey( primaryTableName.toLowerCase())) { genUniqueIndexForUGSI(indexTableStmt, pkList); } @@ -998,6 +1037,7 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName, null); result.setUniqueShardingKey(unique); + result.setLocalIndexes(localIndexList); ReplaceTableNameWithQuestionMarkVisitor visitor = new ReplaceTableNameWithQuestionMarkVisitor(schemaName, ec); return result.accept(visitor); @@ -1029,7 +1069,7 @@ protected SqlNode createClusteredIndexTable(SqlIdentifier indexTableName, final String gsiName = indexTableName.getLastName(); // update index table name - indexTableStmt.setTableName(SqlIdentifier.surroundWithBacktick(gsiName)); + indexTableStmt.setTableName(surroundWithBacktick(gsiName)); final Set sortedCovering = new LinkedHashSet<>(); final Set indexColumns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); indexColumns.addAll(indexColumnMap.keySet()); @@ -1045,6 +1085,8 @@ protected SqlNode createClusteredIndexTable(SqlIdentifier indexTableName, TableMeta primaryTableMeta = ec.getSchemaManager(schemaName).getTableWithNull(primaryTableName); boolean isColumnar = GsiUtils.isAddCci(relDdl.getSqlNode(), sqlAlterTable); + Boolean buildLocalIndexLater = + unique ? false : ec.getParamManager().getBoolean(ConnectionParams.GSI_BUILD_LOCAL_INDEX_LATER); // Generated column can not be sharding key if (primaryTableMeta != null) { @@ -1218,6 +1260,11 @@ protected SqlNode createClusteredIndexTable(SqlIdentifier indexTableName, final List indexShardKey = gsiPreparedData.getShardColumns(); addLocalIndex(indexColumnMap, indexTableStmt, unique, true, options); + List localIndexList = new ArrayList<>(); + if (buildLocalIndexLater) { + localIndexList = popIndexForGSI(indexTableStmt); + } + final SqlNodeList columnList = new SqlNodeList(SqlParserPos.ZERO); final SequenceBean sequenceBean = FastSqlConstructUtils.convertTableElements(columnList, indexTableStmt.getTableElementList(), @@ -1249,6 +1296,7 @@ protected SqlNode createClusteredIndexTable(SqlIdentifier indexTableName, null); result.setUniqueShardingKey(unique); + result.setLocalIndexes(localIndexList); ReplaceTableNameWithQuestionMarkVisitor visitor = new ReplaceTableNameWithQuestionMarkVisitor(schemaName, ec); return result.accept(visitor); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreatePartitionGlobalIndexBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreatePartitionGlobalIndexBuilder.java index b7d25cd31..8d207d023 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreatePartitionGlobalIndexBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreatePartitionGlobalIndexBuilder.java @@ -207,6 +207,7 @@ private void physicalLocationAlignWithPrimaryTable(PartitionInfo primaryPartitio protected void buildPhysicalPlans() { buildSqlTemplate(); buildPhysicalPlans(gsiPreparedData.getIndexTableName()); + buildPhysicalPlansForLocalIndex(gsiPreparedData.getIndexTableName()); } private static List getPrimaryKeyNames(MySqlCreateTableStatement astCreateIndexTable) { @@ -370,6 +371,7 @@ protected SqlNode buildIndexTableDefinition(final SqlCreateIndex sqlCreateIndex) final Set indexShardingColumns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); indexShardingColumns.addAll(indexPartitionInfo.getPartitionColumns()); final boolean isClusteredIndex = sqlCreateIndex.createClusteredIndex(); + final List localIndexList = new ArrayList<>(); if (isClusteredIndex) { return createClusteredIndexTable(indexName, @@ -451,7 +453,8 @@ protected void addLocalIndex(Map indexColumnMap, boolean usePartBy = !partStrategy.isEmpty(); boolean useSubPartBy = false; boolean subPartKeyContainAllPartKeyAsPrefixCols = false; - List partKeyList = allLevelPartKeys.get(0); + List partKeyList = new ArrayList<>(); + partKeyList.addAll(allLevelPartKeys.get(0)); List subPartKeyList = null; boolean addPartColIndexLater = false; if (allLevelPartKeys.size() > 1 && allLevelPartKeys.get(1).size() > 0) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreatePartitionTableWithGsiBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreatePartitionTableWithGsiBuilder.java index 2bedcd153..f506bce26 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreatePartitionTableWithGsiBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/gsi/CreatePartitionTableWithGsiBuilder.java @@ -39,7 +39,6 @@ public class CreatePartitionTableWithGsiBuilder { private final DDL relDdl; private final CreateTableWithGsiPreparedData preparedData; private final ExecutionContext executionContext; - private CreateTableBuilder primaryTableBuilder; private Map>> primaryTableTopology; @@ -80,10 +79,10 @@ public Map> getIndexTablePhysicalPlansMap() { private void buildPrimaryTablePhysicalPlans() { CreateTablePreparedData primaryTablePreparedData = preparedData.getPrimaryTablePreparedData(); final PartitionTableType partitionTableType = getPartitionTableType(primaryTablePreparedData); - primaryTableBuilder = new CreatePartitionTableBuilder(relDdl, primaryTablePreparedData, executionContext, partitionTableType); primaryTableBuilder.build(); + this.primaryTableTopology = primaryTableBuilder.getTableTopology(); this.primaryTablePhysicalPlans = primaryTableBuilder.getPhysicalPlans(); } @@ -137,4 +136,8 @@ private void buildIndexTablePhysicalPlans(String indexTableName, this.indexTablePhysicalPlansMap.put(indexTableName, indexTableBuilder.getPhysicalPlans()); } + public CreateTableBuilder getPrimaryTableBuilder() { + return primaryTableBuilder; + } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupBaseBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupBaseBuilder.java index c63f771c9..114b8ff07 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupBaseBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupBaseBuilder.java @@ -20,6 +20,7 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; import com.alibaba.polardbx.gms.tablegroup.TableGroupAccessor; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; @@ -43,7 +44,6 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; -import java.util.stream.Collectors; public class AlterTableGroupBaseBuilder { @@ -140,6 +140,11 @@ public Map>> getOrderedTargetTablesLoca public AlterTableGroupItemPreparedData createAlterTableGroupItemPreparedData(String tableName, List groupDetailInfoExRecords) { + TableMeta tableMeta = + getExecutionContext().getSchemaManager(getPreparedData().getSchemaName()).getTable(tableName); + if (tableMeta.withCci()) { + TableValidator.validateTableWithCCI(getExecutionContext(), getPreparedData().getTaskType()); + } AlterTableGroupItemPreparedData alterTableGroupItemPreparedData = new AlterTableGroupItemPreparedData(preparedData.getSchemaName(), tableName); @@ -161,7 +166,6 @@ public AlterTableGroupItemPreparedData createAlterTableGroupItemPreparedData(Str alterTableGroupItemPreparedData.setInvisiblePartitionGroups(preparedData.getInvisiblePartitionGroups()); alterTableGroupItemPreparedData.setTaskType(preparedData.getTaskType()); String primaryTableName; - TableMeta tableMeta = executionContext.getSchemaManager(preparedData.getSchemaName()).getTable(tableName); if (tableMeta.isGsi()) { //all the gsi table version change will be behavior by primary table assert @@ -175,6 +179,7 @@ public AlterTableGroupItemPreparedData createAlterTableGroupItemPreparedData(Str .setTableVersion( executionContext.getSchemaManager(preparedData.getSchemaName()).getTable(primaryTableName) .getVersion()); + alterTableGroupItemPreparedData.setColumnarIndex(tableMeta.isColumnar()); return alterTableGroupItemPreparedData; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupDropPartitionBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupDropPartitionBuilder.java index 297617f28..1442ffbea 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupDropPartitionBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupDropPartitionBuilder.java @@ -36,19 +36,16 @@ public AlterTableGroupDropPartitionBuilder(DDL ddl, AlterTableGroupDropPartition public void buildTablesPhysicalPlans() { List allTables = getAllTableNames(); List groupDetailInfoExRecords = preparedData.getTargetGroupDetailInfoExRecords(); - generateNewPhysicalTableNames(allTables); for (String tableName : allTables) { AlterTableGroupItemPreparedData alterTableGroupItemPreparedData = createAlterTableGroupItemPreparedData(tableName, groupDetailInfoExRecords); - AlterTableGroupItemBuilder itemBuilder = - new AlterTableGroupDropPartitionItemBuilder(relDdl, alterTableGroupItemPreparedData, executionContext); - List phyDdlTableOperations = itemBuilder.build().getPhysicalPlans(); - tablesTopologyMap.put(tableName, itemBuilder.getTableTopology()); - sourceTablesTopology.put(tableName, itemBuilder.getSourcePhyTables()); - targetTablesTopology.put(tableName, itemBuilder.getTargetPhyTables()); - newPartitionsPhysicalPlansMap.put(tableName, phyDdlTableOperations); + + tablesTopologyMap.put(tableName, null); + sourceTablesTopology.put(tableName, null); + targetTablesTopology.put(tableName, null); + newPartitionsPhysicalPlansMap.put(tableName, null); tablesPreparedData.put(tableName, alterTableGroupItemPreparedData); - orderedTargetTablesLocations.put(tableName, itemBuilder.getOrderedTargetTableLocations()); + orderedTargetTablesLocations.put(tableName, null); } } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupItemBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupItemBuilder.java index 1d70119d8..d16249652 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupItemBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupItemBuilder.java @@ -68,7 +68,10 @@ public AlterTableGroupItemBuilder(DDL ddl, @Override public AlterTableGroupItemBuilder build() { buildNewTableTopology(preparedData.getSchemaName(), preparedData.getTableName()); - buildPhysicalPlans(); + // not build physical plans for cci + if (!preparedData.isColumnarIndex()) { + buildPhysicalPlans(); + } this.built = true; return this; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupModifyPartitionBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupModifyPartitionBuilder.java index 559e7526f..dd292d611 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupModifyPartitionBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupModifyPartitionBuilder.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.executor.ddl.job.builder.tablegroup; +import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; import com.alibaba.polardbx.gms.topology.GroupDetailInfoExRecord; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.TableMeta; @@ -38,6 +39,11 @@ public AlterTableGroupModifyPartitionBuilder(DDL ddl, AlterTableGroupModifyParti @Override public AlterTableGroupItemPreparedData createAlterTableGroupItemPreparedData(String tableName, List groupDetailInfoExRecords) { + TableMeta tableMeta = + getExecutionContext().getSchemaManager(getPreparedData().getSchemaName()).getTable(tableName); + if (tableMeta.withCci()) { + TableValidator.validateTableWithCCI(getExecutionContext(), getPreparedData().getTaskType()); + } AlterTableGroupItemPreparedData alterTableGroupItemPreparedData = new AlterTableGroupItemPreparedData(preparedData.getSchemaName(), tableName); @@ -55,7 +61,6 @@ public AlterTableGroupItemPreparedData createAlterTableGroupItemPreparedData(Str alterTableGroupItemPreparedData.setInvisiblePartitionGroups(preparedData.getInvisiblePartitionGroups()); alterTableGroupItemPreparedData.setTaskType(preparedData.getTaskType()); String primaryTableName; - TableMeta tableMeta = executionContext.getSchemaManager(preparedData.getSchemaName()).getTable(tableName); if (tableMeta.isGsi()) { //all the gsi table version change will be behavior by primary table assert @@ -69,6 +74,7 @@ public AlterTableGroupItemPreparedData createAlterTableGroupItemPreparedData(Str .setTableVersion( executionContext.getSchemaManager(preparedData.getSchemaName()).getTable(primaryTableName) .getVersion()); + alterTableGroupItemPreparedData.setColumnarIndex(tableMeta.isColumnar()); return alterTableGroupItemPreparedData; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupMovePartitionBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupMovePartitionBuilder.java index 53cdd7355..aa3f60a60 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupMovePartitionBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupMovePartitionBuilder.java @@ -80,17 +80,16 @@ public void buildTablesPhysicalPlans() { assert srcGroupKey != null; - String tarGroupKey = null; for (String phyTbName : srcPhyTbInfo.getValue()) { - if (tarGroupKey == null) { - for (Map.Entry> tarPhyTbInfo : itemBuilder.getTargetPhyTables() - .entrySet()) { - if (tarPhyTbInfo.getValue().contains(phyTbName)) { - tarGroupKey = tarPhyTbInfo.getKey(); - break; - } + String tarGroupKey = null; + for (Map.Entry> tarPhyTbInfo : itemBuilder.getTargetPhyTables() + .entrySet()) { + if (tarPhyTbInfo.getValue().contains(phyTbName)) { + tarGroupKey = tarPhyTbInfo.getKey(); + break; } } + tbPtbGroupMap.get(tableName).put(phyTbName, Pair.of(srcGroupKey, tarGroupKey)); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupOptimizePartitionBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupOptimizePartitionBuilder.java new file mode 100644 index 000000000..6e89946aa --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupOptimizePartitionBuilder.java @@ -0,0 +1,61 @@ +package com.alibaba.polardbx.executor.ddl.job.builder.tablegroup; + +import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupOptimizePartitionItemPreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupOptimizePartitionPreparedData; +import org.apache.calcite.rel.core.DDL; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class AlterTableGroupOptimizePartitionBuilder extends AlterTableGroupBaseBuilder { + + protected AlterTableGroupOptimizePartitionPreparedData preparedData; + protected final Map tableVersions = new HashMap<>(); + protected final Map phyPlanDataMap = new HashMap<>(); + + public AlterTableGroupOptimizePartitionBuilder(DDL ddl, AlterTableGroupOptimizePartitionPreparedData preparedData, + ExecutionContext executionContext) { + super(ddl, preparedData, executionContext); + this.preparedData = preparedData; + } + + @Override + public void buildTablesPhysicalPlans() { + List allTables = getAllTableNames(); + for (String tableName : allTables) { + AlterTableGroupOptimizePartitionItemPreparedData itemPreparedData = buildItemPreparedData(tableName); + AlterTableGroupItemBuilder itemBuilder = + new AlterTableGroupOptimizePartitionItemBuilder(relDdl, itemPreparedData, executionContext).build(); + tablesTopologyMap.put(tableName, itemBuilder.getTableTopology()); + newPartitionsPhysicalPlansMap.put(tableName, itemBuilder.getPhysicalPlans()); + phyPlanDataMap.put(tableName, itemBuilder.genPhysicalPlanData()); + tableVersions.put(tableName, itemPreparedData.getTableVersion()); + } + } + + private AlterTableGroupOptimizePartitionItemPreparedData buildItemPreparedData(String tableName) { + String schemaName = preparedData.getSchemaName(); + + AlterTableGroupOptimizePartitionItemPreparedData itemPreparedData = + new AlterTableGroupOptimizePartitionItemPreparedData(schemaName, tableName); + + itemPreparedData.setSchemaName(schemaName); + itemPreparedData.setTableName(tableName); + itemPreparedData.setTableVersion( + executionContext.getSchemaManager(schemaName).getTable(tableName).getVersion()); + itemPreparedData.setOptimizePartitionNames(preparedData.getOptimizePartitionNames()); + + return itemPreparedData; + } + + public Map getTableVersions() { + return tableVersions; + } + + public Map getPhyPlanDataMap() { + return phyPlanDataMap; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupOptimizePartitionItemBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupOptimizePartitionItemBuilder.java new file mode 100644 index 000000000..87d2d84b2 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableGroupOptimizePartitionItemBuilder.java @@ -0,0 +1,78 @@ +package com.alibaba.polardbx.executor.ddl.job.builder.tablegroup; + +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ReplaceTableNameWithQuestionMarkVisitor; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupOptimizePartitionItemPreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupTruncatePartitionItemPreparedData; +import com.alibaba.polardbx.optimizer.parse.FastsqlParser; +import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionInfoUtil; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; +import org.apache.calcite.rel.core.DDL; +import org.apache.calcite.sql.SqlNode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class AlterTableGroupOptimizePartitionItemBuilder extends AlterTableGroupItemBuilder { + + protected AlterTableGroupOptimizePartitionItemPreparedData preparedData; + + public AlterTableGroupOptimizePartitionItemBuilder(DDL ddl, + AlterTableGroupOptimizePartitionItemPreparedData preparedData, + ExecutionContext executionContext) { + super(ddl, preparedData, executionContext); + this.preparedData = preparedData; + } + + @Override + public void buildNewTableTopology(String schemaName, String tableName) { + partitionInfo = OptimizerContext.getContext(preparedData.getSchemaName()).getPartitionInfoManager() + .getPartitionInfo(preparedData.getTableName()); + + PartitionInfo tempPartitionInfo = partitionInfo.copy(); + + PartitionByDefinition partByDef = tempPartitionInfo.getPartitionBy(); + PartitionByDefinition subPartByDef = partByDef.getSubPartitionBy(); + + Set optimizePartitionNames = preparedData.getOptimizePartitionNames(); + List targetOptimizePartitionSpecs = new ArrayList<>(); + + partByDef.getPartitions().forEach(p -> { + boolean hasSubParts = false; + if (subPartByDef != null && GeneralUtil.isNotEmpty(p.getSubPartitions())) { + List targetTruncateSubPartSpecs = + p.getSubPartitions().stream().filter(sp -> optimizePartitionNames.contains(sp.getName())) + .collect(Collectors.toList()); + p.setSubPartitions(targetTruncateSubPartSpecs); + hasSubParts = true; + } + if (optimizePartitionNames.contains(p.getName()) || hasSubParts) { + targetOptimizePartitionSpecs.add(p); + } + }); + + partByDef.setPartitions(targetOptimizePartitionSpecs); + + partByDef.getPhysicalPartitions().clear(); + + tableTopology = PartitionInfoUtil.buildTargetTablesFromPartitionInfo(tempPartitionInfo); + } + + @Override + protected void buildSqlTemplate() { + final SqlNode optimizeTableNode = + new FastsqlParser().parse("optimize table " + preparedData.getTableName(), executionContext).get(0); + ReplaceTableNameWithQuestionMarkVisitor visitor = + new ReplaceTableNameWithQuestionMarkVisitor(ddlPreparedData.getSchemaName(), executionContext); + this.originSqlTemplate = this.sqlTemplate; + SqlNode tmpSqlTemp = optimizeTableNode.accept(visitor); + this.sqlTemplate = tmpSqlTemp; + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableOptimizePartitionBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableOptimizePartitionBuilder.java new file mode 100644 index 000000000..6455ee039 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/builder/tablegroup/AlterTableOptimizePartitionBuilder.java @@ -0,0 +1,22 @@ +package com.alibaba.polardbx.executor.ddl.job.builder.tablegroup; + +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupOptimizePartitionPreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupTruncatePartitionPreparedData; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.core.DDL; + +import java.util.List; + +public class AlterTableOptimizePartitionBuilder extends AlterTableGroupOptimizePartitionBuilder { + + public AlterTableOptimizePartitionBuilder(DDL ddl, AlterTableGroupOptimizePartitionPreparedData preparedData, + ExecutionContext executionContext) { + super(ddl, preparedData, executionContext); + } + + @Override + public List getAllTableNames() { + return ImmutableList.of(preparedData.getTableName()); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/converter/PhysicalPlanData.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/converter/PhysicalPlanData.java index a44c8292e..f22f6499f 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/converter/PhysicalPlanData.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/converter/PhysicalPlanData.java @@ -17,10 +17,15 @@ package com.alibaba.polardbx.executor.ddl.job.converter; import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.executor.TddlGroupExecutor; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.common.TopologyHandler; +import com.alibaba.polardbx.executor.spi.IGroupExecutor; import com.alibaba.polardbx.gms.locality.LocalityDesc; import com.alibaba.polardbx.gms.metadb.table.TablesExtRecord; import com.alibaba.polardbx.gms.lbac.LBACSecurityEntity; import com.alibaba.polardbx.gms.tablegroup.TableGroupDetailConfig; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTablePreparedData; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.pruning.PhysicalPartitionInfo; @@ -35,6 +40,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; @Data public class PhysicalPlanData { @@ -130,15 +136,105 @@ public List>> partitionParamsList(int count) return Lists.partition(paramsList, count); } - public List>>> partitionTableTopology(int count) { + /** + *

+     *     Convert to data_struct from
+     *          Map{GrpKey,List[[t1_0,t2_0,t3_0],[t1_2,t2_2,t3_2],...]
+     *              grp1->[[t1_1,t2_1,t3_1],[t1_3,t2_2,t3_3],...]
+     *     to
+     *          SubMap1{grpKey, List[log_name_list_with_same_phy_index]}
+     *              grp0->[[t1_0,t2_0,t3_0],...]
+     *              grp1->[[t1_1,t2_1,t3_1],...]
+     *          SubMap2{grpKey, List[log_name_list_with_same_phy_index]}
+     *              grp0->[[t1_2,t2_2,t3_2],...]
+     *              grp1->[[t1_3,t2_2,t3_3],...]
+     *
+     * 
+ */ + public List>>> partitionTableTopology(int parallelism) { + /** + *
+         *     Convert to data_struct from
+         *          Map{GrpKey,List[[t1_0,t2_0,t3_0],[t1_2,t2_2,t3_2],...]
+         *              grp1->[[t1_1,t2_1,t3_1],[t1_3,t2_2,t3_3],...]
+         *     to
+         [{grp0, [t1_0,t2_0,t3_0]}, {grp0,[t1_2,t2_2,t3_2]}, {grp1, [t1_1,t2_1,t3_1]},...]
+         * 
+ */ List>> flatTopology = new ArrayList<>(); for (Map.Entry>> entry : tableTopology.entrySet()) { for (List item : entry.getValue()) { flatTopology.add(Pair.of(entry.getKey(), item)); } } - List>>> partitionedFlatTopology = Lists.partition(flatTopology, count); + /** + *
+         *     Convert to data_struct from
+         *      List< {grpKey, log_name_list_with_same_phy_index} >
+         *          e.g.
+         *              grp0, t1_0,t2_0,t3_0
+         *              grp0, t1_2,t2_2,t3_2
+         *              grp1, t1_3,t2_3,t3_3
+         *              grp1, t1_1,t2_1,t3_1
+         *     to
+         *      List< {grpKey, log_name_list_with_same_phy_index} > order bb zigzag
+         *              grp0, t1_0,t2_0,t3_0
+         *              grp1, t1_1,t2_1,t3_1
+         *              grp0, t1_2,t2_2,t3_2
+         *              grp1, t1_3,t2_3,t3_3
+         *
+         * 
+ */ + List>> zigzaggedFlatTopology = zigzagOrderByDnList(flatTopology); + + /** + *
+         *     Convert to data_struct from
+         *      List< {grpKey, log_name_list_with_same_phy_index} >
+         *          e.g.
+         *              grp0, t1_0,t2_0,t3_0
+         *              grp1, t1_1,t2_1,t3_1
+         *              grp0, t1_2,t2_2,t3_2
+         *              grp1, t1_3,t2_3,t3_3
+         *     to
+         *      SubList1[{grpKey, log_name_list_with_same_phy_index}],
+         *          e.g.
+         *              grp0, t1_0,t2_0,t3_0
+         *              grp1, t1_1,t2_1,t3_1
+         *      SubList2[{grpKey, log_name_list_with_same_phy_index}],s
+         *          e.g.
+         *              grp0, t1_2,t2_2,t3_2
+         *              grp1, t1_3,t2_2,t3_3
+         * 
+ */ + List>>> partitionedFlatTopology = + Lists.partition(zigzaggedFlatTopology, parallelism); + + /** + *
+         *     Convert to data_struct from
+         *      SubList1[{grpKey, log_name_list_with_same_phy_index}],
+         *          e.g.
+         *              [grp0, t1_0,t2_0,t3_0]
+         *              [grp1, t1_1,t2_1,t3_1]
+         *      SubList2[{grpKey, log_name_list_with_same_phy_index}],s
+         *          e.g.
+         *              [grp0, t1_2,t2_2,t3_2]
+         *              [grp1, t1_3,t2_2,t3_3]
+         *
+         *      to
+         *
+         *          SubMap1{grpKey, List[log_name_list_with_same_phy_index]}
+         *              grp0->t1_0,t2_0,t3_0
+         *              grp1->t1_1,t2_1,t3_1
+         *          SubMap2{grpKey, List[log_name_list_with_same_phy_index]}
+         *              grp0->t1_2,t2_2,t3_2
+         *              grp1->t1_3,t2_2,t3_3
+         * 
+ */ List>>> result = new ArrayList<>(); for (List>> itemsInOneMap : partitionedFlatTopology) { Map>> map = new HashMap<>(); @@ -156,6 +252,52 @@ public List>>> partitionTableTopology(int count) { return result; } + protected List>> zigzagOrderByDnList(List>> flatTopology) { + + /** + *
+         *     key: dnId,
+         *     val: idx list of flatTopology, start with zero
+         * 
+ */ + Map> dnIdToListIdxMapping = new TreeMap<>(); + TopologyHandler topologyHandler = ExecutorContext.getContext(this.schemaName).getTopologyHandler(); + + for (int i = 0; i < flatTopology.size(); i++) { + Pair> item = flatTopology.get(i); + String grpKey = item.getKey(); + TddlGroupExecutor grpExecutor = (TddlGroupExecutor) topologyHandler.get(grpKey); + String rwDnId = grpExecutor.getDataSource().getMasterDNId(); + List idxList = dnIdToListIdxMapping.get(rwDnId); + if (idxList == null) { + idxList = new ArrayList<>(); + dnIdToListIdxMapping.put(rwDnId, idxList); + } + idxList.add(i); + } + + List>> newFlatTopology = new ArrayList<>(); + + int curPosiOfDnList = -1; + boolean findAnyItems = false; + while (true) { + ++curPosiOfDnList; + findAnyItems = false; + for (Map.Entry> mapItem : dnIdToListIdxMapping.entrySet()) { + List idxListOfDn = mapItem.getValue(); + if (curPosiOfDnList < idxListOfDn.size()) { + Integer idxVal = idxListOfDn.get(curPosiOfDnList); + newFlatTopology.add(flatTopology.get(idxVal)); + findAnyItems = true; + } + } + if (!findAnyItems) { + break; + } + } + return newFlatTopology; + } + public List explainInfo() { String explainStringTemplate = "%s( tables=\"%s\", shardCount=%d, sql=\"%s\" )"; int shardCount = this.tableTopology.keySet().stream().mapToInt(o -> this.tableTopology.get(o).size()).sum(); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterFileStorageAsOfTimestampJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterFileStorageAsOfTimestampJobFactory.java index b7898e878..ba2040a14 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterFileStorageAsOfTimestampJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterFileStorageAsOfTimestampJobFactory.java @@ -21,6 +21,7 @@ import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.timezone.TimestampUtils; import com.alibaba.polardbx.executor.ddl.job.task.basic.DoNothingTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.oss.DeleteOssFilesTask; @@ -87,7 +88,7 @@ protected ExecutableDdlJob doCreate() { } long ts = - OSSTaskUtils.getTsFromTimestampWithTimeZone(alterFileStoragePreparedData.getTimestamp(), fromTimeZone); + TimestampUtils.getTsFromTimestampWithTimeZone(alterFileStoragePreparedData.getTimestamp(), fromTimeZone); List toDeleteFileRecordList = new ArrayList<>(); List toUpdateFileRecordList = new ArrayList<>(); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterFileStoragePurgeBeforeTimestampJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterFileStoragePurgeBeforeTimestampJobFactory.java index 80f37b994..9a409c7ea 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterFileStoragePurgeBeforeTimestampJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterFileStoragePurgeBeforeTimestampJobFactory.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.timezone.TimestampUtils; import com.alibaba.polardbx.executor.ddl.job.task.basic.DoNothingTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.oss.DeleteOssFilesTask; @@ -96,7 +97,7 @@ protected ExecutableDdlJob doCreate() { } long ts = - OSSTaskUtils.getTsFromTimestampWithTimeZone(alterFileStoragePreparedData.getTimestamp(), fromTimeZone); + TimestampUtils.getTsFromTimestampWithTimeZone(alterFileStoragePreparedData.getTimestamp(), fromTimeZone); // ensure purge do not affect backup int backupOssPeriodInDay = executionContext.getParamManager().getInt(ConnectionParams.BACKUP_OSS_PERIOD); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableAddPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableAddPartitionJobFactory.java index 1313ed31a..8b789e5c8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableAddPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableAddPartitionJobFactory.java @@ -132,7 +132,7 @@ protected ExecutableDdlJob doAddInOriginTableGroup() { )); List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); + taskType, preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableDropPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableDropPartitionJobFactory.java index 470867a93..9c485e617 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableDropPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableDropPartitionJobFactory.java @@ -17,13 +17,20 @@ package com.alibaba.polardbx.executor.ddl.job.factory; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.ddl.job.builder.tablegroup.AlterTableDropPartitionBuilder; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.PauseCurrentJobTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.shared.EmptyTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupAddMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupDisableDropPartitionMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupDropPartitionRefreshMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupValidateTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.CleanupEmptyTableGroupTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.TableGroupSyncTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.TableGroupsSyncTask; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.scaleout.ScaleOutUtils; @@ -46,6 +53,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeSet; /** * @author luoyanxin @@ -102,45 +110,31 @@ protected ExecutableDdlJob doDropInOriginTableGroup() { tablesVersion, true, isBrdTg ? null : alterTableGroupDropPartitionPreparedData.getTargetPhysicalGroups(), false); - Set outdatedPartitionGroupId = new HashSet<>(); - List outdatedPartitionNames = new ArrayList(); - outdatedPartitionNames.addAll(preparedData.getOldPartitionNames()); - outdatedPartitionNames.addAll(preparedData.getNewPartitionNames()); - for (String mergePartitionName : outdatedPartitionNames) { - for (PartitionGroupRecord record : tableGroupConfig.getPartitionGroupRecords()) { - if (record.partition_name.equalsIgnoreCase(mergePartitionName)) { - outdatedPartitionGroupId.add(record.id); - break; - } - } - } - List targetDbList = new ArrayList<>(); - int targetDbCnt = alterTableGroupDropPartitionPreparedData.getTargetGroupDetailInfoExRecords().size(); - List newPartitions = new ArrayList<>(); - for (int i = 0; i < alterTableGroupDropPartitionPreparedData.getNewPartitionNames().size(); i++) { - targetDbList.add(alterTableGroupDropPartitionPreparedData.getTargetGroupDetailInfoExRecords() - .get(i % targetDbCnt).phyDbName); - newPartitions.add(alterTableGroupDropPartitionPreparedData.getNewPartitionNames().get(i)); - } - DdlTask addMetaTask = new AlterTableGroupAddMetaTask(schemaName, + Set oldPartitionNames = new TreeSet<>(String::compareToIgnoreCase); + oldPartitionNames.addAll(preparedData.getOldPartitionNames()); + + DdlTask disableDropPartitionMetaTask = new AlterTableGroupDisableDropPartitionMetaTask(schemaName, tableGroupName, tableGroupConfig.getTableGroupRecord().getId(), + preparedData.getTableName(), + false, alterTableGroupDropPartitionPreparedData.getSourceSql(), - ComplexTaskMetaManager.ComplexTaskStatus.DOING_REORG.getValue(), - taskType.getValue(), - outdatedPartitionGroupId, - targetDbList, - newPartitions); + oldPartitionNames, + preparedData.isOperateOnSubPartition()); + + DdlTask refreshMetaTask = + new AlterTableGroupDropPartitionRefreshMetaTask(schemaName, tableGroupName, tableGroupName, + preparedData.getTableName(), + false, + alterTableGroupDropPartitionPreparedData.getSourceSql(), + oldPartitionNames, + preparedData.isOperateOnSubPartition()); executableDdlJob.addSequentialTasks(Lists.newArrayList( validateTask, - addMetaTask + disableDropPartitionMetaTask )); executableDdlJob.labelAsHead(validateTask); - List bringUpAlterTableGroupTasks = - ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); - final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); boolean stayAtPublic = true; @@ -150,15 +144,26 @@ protected ExecutableDdlJob doDropInOriginTableGroup() { } if (stayAtPublic) { - executableDdlJob.addSequentialTasks(bringUpAlterTableGroupTasks); - constructSubTasks(schemaName, executableDdlJob, addMetaTask, bringUpAlterTableGroupTasks, + constructSubTasks(schemaName, executableDdlJob, disableDropPartitionMetaTask, + ImmutableList.of(refreshMetaTask), null); + + BaseDdlTask tableGroupSyncTask = + new TableGroupSyncTask(preparedData.getSchemaName(), preparedData.getTableGroupName()); + + DdlTask dropUselessTableTask = + ComplexTaskFactory.CreateDropUselessPhyTableTask(schemaName, preparedData.getTableName(), + getTheDeletedPartitionsLocation((AlterTableGroupDropPartitionPreparedData) preparedData, + preparedData.getTableName()), null, executionContext); + + executableDdlJob.addTaskRelationship(executableDdlJob.getTail(), tableGroupSyncTask); + executableDdlJob.addTaskRelationship(tableGroupSyncTask, dropUselessTableTask); } else { PauseCurrentJobTask pauseCurrentJobTask = new PauseCurrentJobTask(schemaName); - constructSubTasks(schemaName, executableDdlJob, addMetaTask, ImmutableList.of(pauseCurrentJobTask), null); + constructSubTasks(schemaName, executableDdlJob, disableDropPartitionMetaTask, + ImmutableList.of(pauseCurrentJobTask), null); } - // TODO(luoyanxin) executableDdlJob.setMaxParallelism(ScaleOutUtils.getTableGroupTaskParallelism(executionContext)); return executableDdlJob; } @@ -189,38 +194,27 @@ protected ExecutableDdlJob doDropAndMoveToExistTableGroup() { executableDdlJob.addTaskRelationship(emptyTask, validateSourceTableGroup); executableDdlJob.addTaskRelationship(emptyTask, validateTargetTableGroup); - Set outdatedPartitionGroupId = new HashSet<>(); + Set oldPartitionNames = new TreeSet<>(String::compareToIgnoreCase); + oldPartitionNames.addAll(preparedData.getOldPartitionNames()); - for (String splitPartitionName : preparedData.getOldPartitionNames()) { - for (PartitionGroupRecord record : tableGroupConfig.getPartitionGroupRecords()) { - if (record.partition_name.equalsIgnoreCase(splitPartitionName)) { - outdatedPartitionGroupId.add(record.id); - break; - } - } - } - List targetDbList = new ArrayList<>(); - List newPartitions = preparedData.getNewPartitionNames(); - for (int i = 0; i < preparedData.getNewPartitionNames().size(); i++) { - targetDbList.add(preparedData.getInvisiblePartitionGroups().get(i).getPhy_db()); - } - DdlTask addMetaTask = new AlterTableGroupAddMetaTask(schemaName, - targetTableGroup, + DdlTask disableDropPartitionMetaTask = new AlterTableGroupDisableDropPartitionMetaTask(schemaName, + sourceTableGroup, tableGroupConfig.getTableGroupRecord().getId(), + preparedData.getTableName(), + false, preparedData.getSourceSql(), - ComplexTaskMetaManager.ComplexTaskStatus.DOING_REORG.getValue(), - taskType.getValue(), - outdatedPartitionGroupId, - targetDbList, - newPartitions); + oldPartitionNames, + preparedData.isOperateOnSubPartition()); - executableDdlJob.addTask(addMetaTask); - executableDdlJob.addTaskRelationship(validateSourceTableGroup, addMetaTask); - executableDdlJob.addTaskRelationship(validateTargetTableGroup, addMetaTask); + DdlTask refreshMetaTask = + new AlterTableGroupDropPartitionRefreshMetaTask(schemaName, sourceTableGroup, targetTableGroup, + preparedData.getTableName(), + false, + preparedData.getSourceSql(), oldPartitionNames, + preparedData.isOperateOnSubPartition()); - List bringUpAlterTableGroupTasks = - ComplexTaskFactory.bringUpAlterTableChangeTopology(schemaName, targetTableGroup, tableName, - taskType, executionContext); + executableDdlJob.addTaskRelationship(validateSourceTableGroup, disableDropPartitionMetaTask); + executableDdlJob.addTaskRelationship(validateTargetTableGroup, disableDropPartitionMetaTask); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); @@ -231,12 +225,30 @@ protected ExecutableDdlJob doDropAndMoveToExistTableGroup() { } if (stayAtPublic) { - executableDdlJob.addSequentialTasks(bringUpAlterTableGroupTasks); - constructSubTasks(schemaName, executableDdlJob, addMetaTask, bringUpAlterTableGroupTasks, + constructSubTasks(schemaName, executableDdlJob, disableDropPartitionMetaTask, + ImmutableList.of(refreshMetaTask), null); + + CleanupEmptyTableGroupTask cleanupEmptyTableGroupTask = new CleanupEmptyTableGroupTask(schemaName, + preparedData.getTableGroupName()); + + List tableGroups = new ArrayList<>(2); + tableGroups.add(preparedData.getTableGroupName()); + tableGroups.add(preparedData.getTargetTableGroup()); + BaseDdlTask tableGroupsSyncTask = + new TableGroupsSyncTask(preparedData.getSchemaName(), tableGroups); + + DdlTask dropUselessTableTask = + ComplexTaskFactory.CreateDropUselessPhyTableTask(schemaName, preparedData.getTableName(), + getTheDeletedPartitionsLocation((AlterTableGroupDropPartitionPreparedData) preparedData, + preparedData.getTableName()), null, executionContext); + executableDdlJob.addTaskRelationship(executableDdlJob.getTail(), cleanupEmptyTableGroupTask); + executableDdlJob.addTaskRelationship(cleanupEmptyTableGroupTask, tableGroupsSyncTask); + executableDdlJob.addTaskRelationship(tableGroupsSyncTask, dropUselessTableTask); } else { PauseCurrentJobTask pauseCurrentJobTask = new PauseCurrentJobTask(schemaName); - constructSubTasks(schemaName, executableDdlJob, addMetaTask, ImmutableList.of(pauseCurrentJobTask), + constructSubTasks(schemaName, executableDdlJob, disableDropPartitionMetaTask, + ImmutableList.of(pauseCurrentJobTask), null); } @@ -270,22 +282,6 @@ public static ExecutableDdlJob create(@Deprecated DDL ddl, AlterTableDropPartitionPreparedData preparedData, ExecutionContext executionContext) { - String schemaName = preparedData.getSchemaName(); - String tableGroupName = preparedData.getTableGroupName(); - - TableGroupConfig tableGroupConfig = OptimizerContext.getContext(schemaName).getTableGroupInfoManager() - .getTableGroupConfigByName(tableGroupName); - - Set outdatedPartitionGroupId = new HashSet<>(); - for (String dropPartitionName : preparedData.getOldPartitionNames()) { - for (PartitionGroupRecord record : tableGroupConfig.getPartitionGroupRecords()) { - if (record.partition_name.equalsIgnoreCase(dropPartitionName)) { - outdatedPartitionGroupId.add(record.id); - break; - } - } - } - AlterTableDropPartitionBuilder alterTableDropPartitionBuilder = new AlterTableDropPartitionBuilder(ddl, preparedData, executionContext); Map>>> tablesTopologyMap = @@ -308,10 +304,7 @@ public static ExecutableDdlJob create(@Deprecated DDL ddl, @Override public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJob, DdlTask tailTask, List bringUpAlterTableGroupTasks, String targetPartitionName) { - - EmptyTask emptyTask = new EmptyTask(schemaName); - - AlterTableGroupSubTaskJobFactory subTaskJobFactory = + AlterTableDropPartitionSubTaskJobFactory subTaskJobFactory = new AlterTableDropPartitionSubTaskJobFactory(ddl, (AlterTableDropPartitionPreparedData) preparedData, tablesPrepareData.get(preparedData.getTableName()), @@ -320,35 +313,31 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ targetTablesTopology.get(preparedData.getTableName()), sourceTablesTopology.get(preparedData.getTableName()), orderedTargetTablesLocations.get(preparedData.getTableName()), - targetPartitionName, + "", false, taskType, executionContext); - ExecutableDdlJob subTask = subTaskJobFactory.create(); - executableDdlJob.combineTasks(subTask); - executableDdlJob.addTaskRelationship(tailTask, subTask.getHead()); + ExecutableDdlJob subDdlJob = subTaskJobFactory.create(); + List subTasks = subDdlJob.getAllTasks(); + + executableDdlJob.getExcludeResources().addAll(subDdlJob.getExcludeResources()); + executableDdlJob.addTaskRelationship(tailTask, subTasks.get(0)); + executableDdlJob.addTaskRelationship(subTasks.get(0), subTasks.get(1)); + executableDdlJob.addTaskRelationship(subTasks.get(1), subTasks.get(2)); if (subTaskJobFactory.getCdcTableGroupDdlMarkTask() != null) { - executableDdlJob.addTask(emptyTask); - executableDdlJob.addTask(subTaskJobFactory.getCdcTableGroupDdlMarkTask()); - executableDdlJob.addTaskRelationship(subTask.getTail(), emptyTask); - executableDdlJob.addTaskRelationship(emptyTask, subTaskJobFactory.getCdcTableGroupDdlMarkTask()); + executableDdlJob.addTaskRelationship(subTasks.get(subTasks.size() - 1), + subTaskJobFactory.getCdcTableGroupDdlMarkTask()); executableDdlJob.addTaskRelationship(subTaskJobFactory.getCdcTableGroupDdlMarkTask(), bringUpAlterTableGroupTasks.get(0)); + + List syncTasks = + subTaskJobFactory.generateSyncTask(schemaName, preparedData.getTableName(), executionContext); + executableDdlJob.addTaskRelationship(bringUpAlterTableGroupTasks.get(0), syncTasks.get(0)); + executableDdlJob.addTaskRelationship(syncTasks.get(0), syncTasks.get(1)); + executableDdlJob.labelAsTail(syncTasks.get(1)); } else { - executableDdlJob.addTaskRelationship(subTask.getTail(), bringUpAlterTableGroupTasks.get(0)); - } - if (bringUpAlterTableGroupTasks.size() > 1 && !(bringUpAlterTableGroupTasks.get( - 0) instanceof PauseCurrentJobTask)) { - DdlTask dropUselessTableTask = ComplexTaskFactory - .CreateDropUselessPhyTableTask(schemaName, preparedData.getTableName(), - getTheDeletedPartitionsLocation(preparedData.getSchemaName(), preparedData.getTableName()), - executionContext); - executableDdlJob.addTask(dropUselessTableTask); - executableDdlJob - .addTaskRelationship(bringUpAlterTableGroupTasks.get(bringUpAlterTableGroupTasks.size() - 1), - dropUselessTableTask); + executableDdlJob.addTaskRelationship(subTasks.get(subTasks.size() - 1), bringUpAlterTableGroupTasks.get(0)); } - executableDdlJob.getExcludeResources().addAll(subTask.getExcludeResources()); } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableDropPartitionSubTaskJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableDropPartitionSubTaskJobFactory.java index c1b0dac95..a1e696da3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableDropPartitionSubTaskJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableDropPartitionSubTaskJobFactory.java @@ -16,30 +16,62 @@ package com.alibaba.polardbx.executor.ddl.job.factory; +import com.alibaba.polardbx.common.TddlConstants; +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.ddl.job.builder.DropPartLocalIndexBuilder; +import com.alibaba.polardbx.executor.ddl.job.converter.DdlJobDataConverter; +import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.DropIndexPhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.TablesSyncTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.UpdateTablesVersionTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcTableGroupDdlMarkTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupAddSubTaskMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupDropPartitionAddSubTaskMetaTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; +import com.alibaba.polardbx.gms.partition.TablePartitionRecord; +import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.DdlContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.PhyDdlTableOperation; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableDropPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupBasePreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupDropPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupItemPreparedData; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionInfoUtil; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; import com.alibaba.polardbx.optimizer.tablegroup.AlterTableGroupSnapShotUtils; +import com.alibaba.polardbx.optimizer.tablegroup.TableGroupInfoManager; import org.apache.calcite.rel.core.DDL; import org.apache.calcite.sql.SqlAlterTable; +import org.apache.calcite.sql.SqlAlterTableGroup; +import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlNode; +import org.apache.commons.lang.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.TimeUnit; + +import static com.alibaba.polardbx.optimizer.tablegroup.AlterTableGroupSnapShotUtils.updatePartitionSpecRelationship; +import static com.alibaba.polardbx.optimizer.tablegroup.AlterTableGroupSnapShotUtils.updateSubPartitionTemplate; public class AlterTableDropPartitionSubTaskJobFactory extends AlterTableGroupSubTaskJobFactory { - final AlterTableDropPartitionPreparedData parentPrepareData; + final AlterTableGroupDropPartitionPreparedData parentPrepareData; public AlterTableDropPartitionSubTaskJobFactory(DDL ddl, - AlterTableDropPartitionPreparedData parentPrepareData, + AlterTableGroupDropPartitionPreparedData parentPrepareData, AlterTableGroupItemPreparedData preparedData, List phyDdlTableOperations, Map>> tableTopology, @@ -57,19 +89,20 @@ public AlterTableDropPartitionSubTaskJobFactory(DDL ddl, } @Override - protected void validate() { - - } - - @Override - protected PartitionInfo generateNewPartitionInfo() { + protected ExecutableDdlJob doCreate() { PartitionInfo curPartitionInfo = OptimizerContext.getContext(preparedData.getSchemaName()).getPartitionInfoManager() .getPartitionInfo(preparedData.getTableName()); + SqlNode sqlNode; + if (ddl.getSqlNode() instanceof SqlAlterTable) { + sqlNode = ((SqlAlterTable) ddl.getSqlNode()).getAlters().get(0); + } else { + sqlNode = ((SqlAlterTableGroup) ddl.getSqlNode()).getAlters().get(0); + } + final TableGroupInfoManager tableGroupInfoManager = + OptimizerContext.getContext(curPartitionInfo.getTableSchema()).getTableGroupInfoManager(); - SqlNode sqlNode = ((SqlAlterTable) ddl.getSqlNode()).getAlters().get(0); - - PartitionInfo newPartInfo = AlterTableGroupSnapShotUtils + PartitionInfo newPartitionInfo = AlterTableGroupSnapShotUtils .getNewPartitionInfo( parentPrepareData, curPartitionInfo, @@ -82,17 +115,96 @@ protected PartitionInfo generateNewPartitionInfo() { preparedData.getInvisiblePartitionGroups(), orderedTargetTableLocations, executionContext); + String targetTableGroupName = null; + if (StringUtils.isNotEmpty(parentPrepareData.getTargetTableGroup())) { + targetTableGroupName = parentPrepareData.getTargetTableGroup(); - if (parentPrepareData.isMoveToExistTableGroup()) { - updateNewPartitionInfoByTargetGroup(parentPrepareData, newPartInfo); + } else if (StringUtils.isNotEmpty(parentPrepareData.getTargetImplicitTableGroupName())) { + targetTableGroupName = parentPrepareData.getTargetImplicitTableGroupName(); } + if (StringUtils.isNotEmpty(targetTableGroupName)) { + TableGroupConfig tableGroupConfig = + tableGroupInfoManager.getTableGroupConfigByName(targetTableGroupName); + if (tableGroupConfig != null) { + newPartitionInfo.setTableGroupId(tableGroupConfig.getTableGroupRecord().id); + } + } + TablePartitionRecord logTableRec = PartitionInfoUtil.prepareRecordForLogicalTable(newPartitionInfo); + logTableRec.partStatus = TablePartitionRecord.PARTITION_STATUS_LOGICAL_TABLE_PUBLIC; + List partRecList = + PartitionInfoUtil.prepareRecordForAllPartitions(newPartitionInfo); + Map> subPartRecInfos = PartitionInfoUtil + .prepareRecordForAllSubpartitions(partRecList, newPartitionInfo, + newPartitionInfo.getPartitionBy().getPartitions()); + + AlterTableGroupDropPartitionAddSubTaskMetaTask addSubTaskMetaTask = + new AlterTableGroupDropPartitionAddSubTaskMetaTask(preparedData.getSchemaName(), + preparedData.getTableName(), + logTableRec, partRecList, subPartRecInfos); + List taskList = new ArrayList<>(); + taskList.add(addSubTaskMetaTask); + final ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); + taskList.addAll(generateSyncTask(preparedData.getSchemaName(), preparedData.getTableName(), executionContext)); + executableDdlJob.addSequentialTasks(taskList); - //checkPartitionCount(newPartInfo); + SqlKind sqlKind = ddl.kind(); + Map> newTopology = newPartitionInfo.getTopology(); - return newPartInfo; + DdlContext dc = executionContext.getDdlContext(); + + DdlTask cdcDdlMarkTask = + new CdcTableGroupDdlMarkTask(preparedData.getTableGroupName(), preparedData.getSchemaName(), + preparedData.getTableName(), sqlKind, newTopology, + dc.getDdlStmt(), + sqlKind == SqlKind.ALTER_TABLEGROUP ? CdcDdlMarkVisibility.Private : CdcDdlMarkVisibility.Protected, + preparedData.isColumnarIndex()); + boolean stayAtPublic = true; + final String finalStatus = + executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); + if (StringUtils.isNotEmpty(finalStatus)) { + stayAtPublic = + StringUtils.equalsIgnoreCase(ComplexTaskMetaManager.ComplexTaskStatus.PUBLIC.name(), finalStatus); + } + if (stayAtPublic) { + cdcTableGroupDdlMarkTask = cdcDdlMarkTask; + } + return executableDdlJob; } - public AlterTableGroupBasePreparedData getParentPrepareData() { - return parentPrepareData; + public List generateSyncTask(String schemaName, + String tableName, + ExecutionContext executionContext) { + + List logicalTableNames = new ArrayList<>(); + // not include GSI tables + Set primaryLogicalTables = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + + // for alter table set tableGroup, only need to care about the table in "alter table" only + String logicalTable = tableName; + TableMeta tableMeta = executionContext.getSchemaManager(schemaName).getTable(logicalTable); + if (tableMeta.isGsi()) { + //all the gsi table version change will be behavior by primary table + assert + tableMeta.getGsiTableMetaBean() != null && tableMeta.getGsiTableMetaBean().gsiMetaBean != null; + logicalTable = tableMeta.getGsiTableMetaBean().gsiMetaBean.tableName; + } + if (!primaryLogicalTables.contains(logicalTable)) { + logicalTableNames.add(logicalTable); + primaryLogicalTables.add(logicalTable); + } + + boolean enablePreemptiveMdl = + executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_PREEMPTIVE_MDL); + Long initWait = executionContext.getParamManager().getLong(ConnectionParams.PREEMPTIVE_MDL_INITWAIT); + Long interval = executionContext.getParamManager().getLong(ConnectionParams.PREEMPTIVE_MDL_INTERVAL); + + List ddlTasks = new ArrayList<>(2); + DdlTask updateTablesVersionTask = new UpdateTablesVersionTask(schemaName, logicalTableNames); + DdlTask tablesSyncTask = + new TablesSyncTask(schemaName, logicalTableNames, enablePreemptiveMdl, initWait, interval, + TimeUnit.MILLISECONDS); + ddlTasks.add(updateTablesVersionTask); + ddlTasks.add(tablesSyncTask); + return ddlTasks; } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableExtractPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableExtractPartitionJobFactory.java index a30a25f5c..30f43011a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableExtractPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableExtractPartitionJobFactory.java @@ -137,7 +137,7 @@ private ExecutableDdlJob splitInOriginTableGroup() { )); List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); + taskType, preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); @@ -329,6 +329,7 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ DdlTask dropUselessTableTask = ComplexTaskFactory .CreateDropUselessPhyTableTask(schemaName, preparedData.getTableName(), sourceTablesTopology.get(preparedData.getTableName()), + targetTablesTopology.get(preparedData.getTableName()), executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupAddPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupAddPartitionJobFactory.java index f120efae6..039a55710 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupAddPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupAddPartitionJobFactory.java @@ -105,7 +105,8 @@ protected ExecutableDdlJob doCreate() { executableDdlJob.addSequentialTasks(Lists.newArrayList(validateTask, addMetaTask)); List bringUpAlterTableGroupTasks = - ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, executionContext); + ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, + preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupBaseJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupBaseJobFactory.java index b9fc08711..dd6e679a2 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupBaseJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupBaseJobFactory.java @@ -47,6 +47,7 @@ import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.PhyDdlTableOperation; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupBasePreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupDropPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupItemPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupMergePartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupReorgPartitionPreparedData; @@ -181,6 +182,7 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ DdlTask dropUselessTableTask = ComplexTaskFactory .CreateDropUselessPhyTableTask(schemaName, entry.getKey(), sourceTablesTopology.get(entry.getKey()), + targetTablesTopology.get(entry.getKey()), executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob.labelAsTail(dropUselessTableTask); @@ -312,47 +314,71 @@ protected void attacheCdcFinalMarkTask(ExecutableDdlJob executableDdlJob) { executableDdlJob.appendTask(cdcAlterTableGroupFinalMarkTask); } - public Map> getTheDeletedPartitionsLocation(String schemaName, String tableName) { + public Map> getTheDeletedPartitionsLocation( + AlterTableGroupDropPartitionPreparedData preparedData, + String tableName) { Map> deletedPhyTables = new HashMap<>(); PartitionInfo partitionInfo = - OptimizerContext.getContext(schemaName).getPartitionInfoManager().getPartitionInfo(tableName); + OptimizerContext.getContext(preparedData.getSchemaName()).getPartitionInfoManager() + .getPartitionInfo(tableName); PartitionByDefinition partByDef = partitionInfo.getPartitionBy(); PartitionByDefinition subPartByDef = partByDef.getSubPartitionBy(); - int num = 0; - List outdatedPartitionNames = new ArrayList(); - - outdatedPartitionNames.addAll(preparedData.getOldPartitionNames()); - outdatedPartitionNames.addAll(preparedData.getNewPartitionNames()); - - for (String oldPartitionName : outdatedPartitionNames) { - for (PartitionSpec partSpec : partByDef.getPartitions()) { - if (subPartByDef != null) { - for (PartitionSpec subPartSpec : partSpec.getSubPartitions()) { - if (subPartSpec.getName().equalsIgnoreCase(oldPartitionName)) { - PartitionLocation location = subPartSpec.getLocation(); - deletedPhyTables.computeIfAbsent(location.getGroupKey(), o -> new HashSet<>()) - .add(location.getPhyTableName()); - num++; - break; + for (String oldPartitionName : preparedData.getOldPartitionNames()) { + if (preparedData.isOperateOnSubPartition()) { + if (subPartByDef.isUseSubPartTemplate()) { + for (PartitionSpec partSpec : partByDef.getPartitions()) { + for (PartitionSpec subPartSpec : partSpec.getSubPartitions()) { + if (subPartSpec.getTemplateName().equalsIgnoreCase(oldPartitionName)) { + PartitionLocation location = subPartSpec.getLocation(); + deletedPhyTables.computeIfAbsent(location.getGroupKey(), o -> new HashSet<>()) + .add(location.getPhyTableName()); + break; + } } } } else { + boolean isFound = false; + for (PartitionSpec partSpec : partByDef.getPartitions()) { + for (PartitionSpec subPartSpec : partSpec.getSubPartitions()) { + if (subPartSpec.getName().equalsIgnoreCase(oldPartitionName)) { + PartitionLocation location = subPartSpec.getLocation(); + deletedPhyTables.computeIfAbsent(location.getGroupKey(), o -> new HashSet<>()).add( + location.getPhyTableName()); + isFound = true; + break; + } + } + if (isFound) { + break; + } + } + } + } else { + for (PartitionSpec partSpec : partByDef.getPartitions()) { if (partSpec.getName().equalsIgnoreCase(oldPartitionName)) { - PartitionLocation location = partSpec.getLocation(); - deletedPhyTables.computeIfAbsent(location.getGroupKey(), o -> new HashSet<>()) - .add(location.getPhyTableName()); - num++; - break; + if (subPartByDef != null) { + if (partSpec.getName().equalsIgnoreCase(oldPartitionName)) { + for (PartitionSpec subPartSpec : partSpec.getSubPartitions()) { + PartitionLocation location = subPartSpec.getLocation(); + deletedPhyTables.computeIfAbsent(location.getGroupKey(), o -> new HashSet<>()) + .add(location.getPhyTableName()); + } + break; + } + } else { + PartitionLocation location = partSpec.getLocation(); + deletedPhyTables.computeIfAbsent(location.getGroupKey(), o -> new HashSet<>()) + .add(location.getPhyTableName()); + break; + } } } } } - assert num == preparedData.getOldPartitionNames().size() + preparedData.getNewPartitionNames().size(); - return deletedPhyTables; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupChangeSetJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupChangeSetJobFactory.java index 5ca81fc57..fe5897358 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupChangeSetJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupChangeSetJobFactory.java @@ -18,13 +18,14 @@ import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.changeset.ChangeSetManager; import com.alibaba.polardbx.executor.ddl.job.converter.DdlJobDataConverter; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.task.backfill.AlterTableGroupBackFillTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.CloneTableDataFileTask; -import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.CreatePhyTableWithRollbackCheckTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.DiscardTableSpaceDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.ImportTableSpaceDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.PhysicalBackfillTask; @@ -39,6 +40,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.ddl.util.ChangeSetUtils; import com.alibaba.polardbx.executor.physicalbackfill.PhysicalBackfillUtils; +import com.alibaba.polardbx.executor.scaleout.ScaleOutUtils; import com.alibaba.polardbx.gms.partition.TablePartitionRecord; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.topology.DbTopologyManager; @@ -54,12 +56,14 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupItemPreparedData; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.PartitionInfoUtil; +import com.mysql.cj.polarx.protobuf.PolarxPhysicalBackfill; import org.apache.calcite.rel.core.DDL; import org.apache.calcite.sql.SqlKind; import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -190,21 +194,17 @@ protected ExecutableDdlJob doCreate() { taskList.add(addMetaTask); //2.2 create partitioned physical table phyDdlTableOperations.forEach(o -> o.setPartitionInfo(newPartitionInfo)); - + List discardTableSpaceTasks = null; if (!tableTopology.isEmpty()) { PhysicalPlanData physicalPlanData = DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, phyDdlTableOperations, executionContext); DdlTask phyDdlTask = - new CreateTablePhyDdlTask(schemaName, physicalPlanData.getLogicalTableName(), physicalPlanData); + new CreatePhyTableWithRollbackCheckTask(schemaName, physicalPlanData.getLogicalTableName(), + physicalPlanData, sourceTableTopology); taskList.add(phyDdlTask); if (usePhysicalBackfill) { - physicalPlanData = - DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, discardTableSpaceOperations, - executionContext); - phyDdlTask = - new DiscardTableSpaceDdlTask(schemaName, physicalPlanData.getLogicalTableName(), - physicalPlanData); - taskList.add(phyDdlTask); + discardTableSpaceTasks = ScaleOutUtils.generateDiscardTableSpaceDdlTask(schemaName, tableTopology, + discardTableSpaceOperations, executionContext); } } @@ -236,12 +236,6 @@ protected ExecutableDdlJob doCreate() { final boolean useApplyOpt = changeSetApplyFinishTask != null && executionContext.getParamManager().getBoolean(CHANGE_SET_APPLY_OPTIMIZATION); - AlterTableGroupMovePartitionsCheckTask changeSetCheckTask = - new AlterTableGroupMovePartitionsCheckTask(schemaName, tableName, sourceTableTopology, targetTableTopology, - useApplyOpt, relatedTables); - AlterTableGroupMovePartitionsCheckTask changeSetCheckTwiceTask = - new AlterTableGroupMovePartitionsCheckTask(schemaName, tableName, sourceTableTopology, targetTableTopology, - false, relatedTables); final ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); @@ -261,8 +255,11 @@ protected ExecutableDdlJob doCreate() { boolean healthyCheck = executionContext.getParamManager().getBoolean(ConnectionParams.PHYSICAL_BACKFILL_STORAGE_HEALTHY_CHECK); + long totalDataSize = 0l; if (usePhysicalBackfill) { + Set sourceStorageInsts = new HashSet<>(); + Set targetStorageInsts = new HashSet<>(); for (Map.Entry> entry : ptbGroupMap.entrySet()) { String phyTb = entry.getKey(); Pair srcTarGroup = entry.getValue(); @@ -288,36 +285,65 @@ protected ExecutableDdlJob doCreate() { .getLong(ConnectionParams.PHYSICAL_BACKFILL_MIN_SUCCESS_BATCH_UPDATE); final long parallelism = executionContext.getParamManager().getLong(ConnectionParams.PHYSICAL_BACKFILL_PARALLELISM); + final long ioAdvise = + executionContext.getParamManager() + .getLong(ConnectionParams.PHYSICAL_BACKFILL_IMPORT_TABLESPACE_IO_ADVISE); List phyPartNames = PhysicalBackfillUtils.getPhysicalPartitionNames(schemaName, srcDbAndGroup.getValue(), srcDbAndGroup.getKey(), phyTb); + + Pair srcDnUserAndPasswd = storageInstAndUserInfos.computeIfAbsent(sourceStorageId, + key -> PhysicalBackfillUtils.getUserPasswd(sourceStorageId)); + Pair userAndPasswd = storageInstAndUserInfos.computeIfAbsent(targetStorageId, + key -> PhysicalBackfillUtils.getUserPasswd(targetStorageId)); + sourceStorageInsts.add(sourceStorageId); + targetStorageInsts.add(targetStorageId); + + boolean hasNoPhyPart = GeneralUtil.isEmpty(phyPartNames); + List temPhyPartNames = new ArrayList<>(); + if (hasNoPhyPart) { + temPhyPartNames.add(""); + } else { + temPhyPartNames.addAll(phyPartNames); + } + PolarxPhysicalBackfill.GetFileInfoOperator fileInfoOperator = + PhysicalBackfillUtils.checkFileExistence(srcDnUserAndPasswd, srcDbAndGroup.getKey(), + phyTb.toLowerCase(), + temPhyPartNames, + true, PhysicalBackfillUtils.getMySQLLeaderIpAndPort(sourceStorageId)); + long dataSize = 0l; + for (PolarxPhysicalBackfill.FileInfo fileInfo : fileInfoOperator.getTableInfo().getFileInfoList()) { + dataSize += fileInfo.getDataSize(); + } + CloneTableDataFileTask cloneTableDataFileTask = new CloneTableDataFileTask(schemaName, tableName, srcDbAndGroup, tarDbAndGroup, phyTb, phyPartNames, sourceStorageId, sourceHostIpAndPort, targetHostsIpAndPort, batchSize, - tableMeta.isEncryption()); + dataSize, tableMeta.isEncryption()); cloneTableDataFileTask.setTaskId(ID_GENERATOR.nextId()); List importTableSpaceTasks = new ArrayList<>(); PhysicalBackfillTask physicalBackfillTask = - new PhysicalBackfillTask(schemaName, cloneTableDataFileTask.getTaskId(), tableName, phyTb, + new PhysicalBackfillTask(schemaName, cloneTableDataFileTask.getTaskId(), tableName, + phyTb.toLowerCase(), phyPartNames, srcTarGroup, - Pair.of(sourceStorageId, targetStorageId), storageInstAndUserInfos, batchSize, parallelism, + Pair.of(sourceStorageId, targetStorageId), + storageInstAndUserInfos, + batchSize, + dataSize, + parallelism, minUpdateBatch, waitLsn, tableMeta.isEncryption()); - storageInstAndUserInfos.computeIfAbsent(sourceStorageId, - key -> PhysicalBackfillUtils.getUserPasswd(sourceStorageId)); - Pair userAndPasswd = storageInstAndUserInfos.computeIfAbsent(targetStorageId, - key -> PhysicalBackfillUtils.getUserPasswd(targetStorageId)); for (Pair hostIpAndPort : targetHostsIpAndPort) { ImportTableSpaceDdlTask importTableSpaceDdlTask = new ImportTableSpaceDdlTask(schemaName, tableName, tarDbAndGroup.getKey(), phyTb, hostIpAndPort, - userAndPasswd); + userAndPasswd, targetStorageId, dataSize, ioAdvise); importTableSpaceTasks.add(importTableSpaceDdlTask); } List tasks = new ArrayList<>(importTableSpaceTasks.size() + 2); @@ -325,6 +351,7 @@ protected ExecutableDdlJob doCreate() { tasks.add(physicalBackfillTask); tasks.addAll(importTableSpaceTasks); physicalyTaskPipeLine.add(tasks); + totalDataSize += dataSize; } Map targetStorageIds = new HashMap<>(); for (GroupDetailInfoExRecord groupDetailInfoExRecord : preparedData.getGroupDetailInfoExRecords()) { @@ -332,6 +359,15 @@ protected ExecutableDdlJob doCreate() { groupDetailInfoExRecord.storageInstId); } + AlterTableGroupMovePartitionsCheckTask changeSetCheckTask = + new AlterTableGroupMovePartitionsCheckTask(schemaName, tableName, sourceTableTopology, + targetTableTopology, + useApplyOpt, relatedTables, sourceStorageInsts, targetStorageInsts, totalDataSize); + AlterTableGroupMovePartitionsCheckTask changeSetCheckTwiceTask = + new AlterTableGroupMovePartitionsCheckTask(schemaName, tableName, sourceTableTopology, + targetTableTopology, + false, relatedTables, sourceStorageInsts, targetStorageInsts, totalDataSize); + movePartitionTasks = ChangeSetUtils.genChangeSetOnlineSchemaChangeTasks( schemaName, tableName, relatedTables, @@ -345,6 +381,15 @@ protected ExecutableDdlJob doCreate() { backfillTaskEdgeNodes, executionContext); } else { + AlterTableGroupMovePartitionsCheckTask changeSetCheckTask = + new AlterTableGroupMovePartitionsCheckTask(schemaName, tableName, sourceTableTopology, + targetTableTopology, + useApplyOpt, relatedTables, null, null, totalDataSize); + AlterTableGroupMovePartitionsCheckTask changeSetCheckTwiceTask = + new AlterTableGroupMovePartitionsCheckTask(schemaName, tableName, sourceTableTopology, + targetTableTopology, + false, relatedTables, null, null, totalDataSize); + AlterTableGroupBackFillTask alterTableGroupBackFillTask = new AlterTableGroupBackFillTask(schemaName, tableName, sourceTableTopology, targetTableTopology, isBroadcast(), @@ -362,9 +407,18 @@ protected ExecutableDdlJob doCreate() { backfillTaskEdgeNodes, executionContext); } + DdlTask CreateTablePhyDdlTask = taskList.get(taskList.size() - 1); taskList.addAll(movePartitionTasks); executableDdlJob.addSequentialTasks(taskList); + if (usePhysicalBackfill) { + executableDdlJob.removeTaskRelationship(CreateTablePhyDdlTask, movePartitionTasks.get(0)); + for (DdlTask discardTask : discardTableSpaceTasks) { + executableDdlJob.addTaskRelationship(CreateTablePhyDdlTask, discardTask); + executableDdlJob.addTaskRelationship(discardTask, movePartitionTasks.get(0)); + } + } + //cdc ddl mark task SqlKind sqlKind = ddl.kind(); DdlContext dc = executionContext.getDdlContext(); @@ -373,7 +427,8 @@ protected ExecutableDdlJob doCreate() { if (stayAtPublic) { cdcTableGroupDdlMarkTask = new CdcTableGroupDdlMarkTask(tableGroupName, schemaName, tableName, sqlKind, newTopology, dc.getDdlStmt(), - sqlKind == SqlKind.ALTER_TABLEGROUP ? CdcDdlMarkVisibility.Private : CdcDdlMarkVisibility.Protected); + sqlKind == SqlKind.ALTER_TABLEGROUP ? CdcDdlMarkVisibility.Private : CdcDdlMarkVisibility.Protected, + false); } if (changeSetApplyExecutorInitTask != null) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupDropPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupDropPartitionJobFactory.java index 02d3f14bb..153ca2cc4 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupDropPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupDropPartitionJobFactory.java @@ -20,10 +20,14 @@ import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.ddl.job.builder.tablegroup.AlterTableGroupDropPartitionBuilder; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.PauseCurrentJobTask; import com.alibaba.polardbx.executor.ddl.job.task.shared.EmptyTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupAddMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupDisableDropPartitionMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupDropPartitionRefreshMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupValidateTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.TableGroupSyncTask; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.scaleout.ScaleOutUtils; @@ -33,6 +37,7 @@ import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.PhyDdlTableOperation; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableDropPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupDropPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupItemPreparedData; import com.google.common.collect.ImmutableList; @@ -45,6 +50,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeSet; /** * @author luoyanxin @@ -88,37 +94,28 @@ protected ExecutableDdlJob doCreate() { tablesVersion, true, isBrdTg ? null : alterTableGroupDropPartitionPreparedData.getTargetPhysicalGroups(), false); - Set outdatedPartitionGroupId = new HashSet<>(); - List outdatedPartitionNames = new ArrayList(); - outdatedPartitionNames.addAll(preparedData.getOldPartitionNames()); - outdatedPartitionNames.addAll(preparedData.getNewPartitionNames()); - for (String mergePartitionName : outdatedPartitionNames) { - for (PartitionGroupRecord record : tableGroupConfig.getPartitionGroupRecords()) { - if (record.partition_name.equalsIgnoreCase(mergePartitionName)) { - outdatedPartitionGroupId.add(record.id); - break; - } - } - } - List targetDbList = new ArrayList<>(); - int targetDbCnt = alterTableGroupDropPartitionPreparedData.getTargetGroupDetailInfoExRecords().size(); - List newPartitions = new ArrayList<>(); - for (int i = 0; i < alterTableGroupDropPartitionPreparedData.getNewPartitionNames().size(); i++) { - targetDbList.add(alterTableGroupDropPartitionPreparedData.getTargetGroupDetailInfoExRecords() - .get(i % targetDbCnt).phyDbName); - newPartitions.add(alterTableGroupDropPartitionPreparedData.getNewPartitionNames().get(i)); - } - DdlTask addMetaTask = - new AlterTableGroupAddMetaTask(schemaName, tableGroupName, tableGroupConfig.getTableGroupRecord().getId(), - alterTableGroupDropPartitionPreparedData.getSourceSql(), - ComplexTaskMetaManager.ComplexTaskStatus.DOING_REORG.getValue(), taskType.getValue(), - outdatedPartitionGroupId, targetDbList, newPartitions); - - executableDdlJob.addSequentialTasks(Lists.newArrayList(validateTask, addMetaTask)); + Set oldPartitionNames = new TreeSet<>(String::compareToIgnoreCase); + oldPartitionNames.addAll(preparedData.getOldPartitionNames()); + + DdlTask disableDropPartitionMetaTask = new AlterTableGroupDisableDropPartitionMetaTask(schemaName, + tableGroupName, + tableGroupConfig.getTableGroupRecord().getId(), + null, true, + alterTableGroupDropPartitionPreparedData.getSourceSql(), + oldPartitionNames, + preparedData.isOperateOnSubPartition()); + + DdlTask refreshMetaTask = + new AlterTableGroupDropPartitionRefreshMetaTask(schemaName, tableGroupName, tableGroupName, + null, true, + alterTableGroupDropPartitionPreparedData.getSourceSql(), oldPartitionNames, + preparedData.isOperateOnSubPartition()); + + executableDdlJob.addSequentialTasks(Lists.newArrayList( + validateTask, + disableDropPartitionMetaTask + )); executableDdlJob.labelAsHead(validateTask); - List bringUpAlterTableGroupTasks = - ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, executionContext); - final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); boolean stayAtPublic = true; @@ -128,11 +125,13 @@ protected ExecutableDdlJob doCreate() { } if (stayAtPublic) { - executableDdlJob.addSequentialTasks(bringUpAlterTableGroupTasks); - constructSubTasks(schemaName, executableDdlJob, addMetaTask, bringUpAlterTableGroupTasks, null); + constructSubTasks(schemaName, executableDdlJob, disableDropPartitionMetaTask, + ImmutableList.of(refreshMetaTask), + null); } else { PauseCurrentJobTask pauseCurrentJobTask = new PauseCurrentJobTask(schemaName); - constructSubTasks(schemaName, executableDdlJob, addMetaTask, ImmutableList.of(pauseCurrentJobTask), null); + constructSubTasks(schemaName, executableDdlJob, disableDropPartitionMetaTask, + ImmutableList.of(pauseCurrentJobTask), null); } // TODO(luoyanxin) @@ -184,40 +183,60 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ List bringUpAlterTableGroupTasks, String targetPartitionName) { EmptyTask emptyTask = new EmptyTask(schemaName); + BaseDdlTask tableGroupSyncTask = null; boolean emptyTaskAdded = false; for (Map.Entry>>> entry : tablesTopologyMap.entrySet()) { - boolean skipBackfill = GeneralUtil.isEmpty(sourceTablesTopology.get(entry.getKey())); - AlterTableGroupSubTaskJobFactory subTaskJobFactory = - new AlterTableGroupSubTaskJobFactory(ddl, preparedData, tablesPrepareData.get(entry.getKey()), - newPartitionsPhysicalPlansMap.get(entry.getKey()), tablesTopologyMap.get(entry.getKey()), - targetTablesTopology.get(entry.getKey()), sourceTablesTopology.get(entry.getKey()), - orderedTargetTablesLocations.get(entry.getKey()), targetPartitionName, skipBackfill, taskType, + AlterTableDropPartitionSubTaskJobFactory subTaskJobFactory = + new AlterTableDropPartitionSubTaskJobFactory(ddl, + (AlterTableGroupDropPartitionPreparedData) preparedData, + tablesPrepareData.get(entry.getKey()), + newPartitionsPhysicalPlansMap.get(entry.getKey()), + tablesTopologyMap.get(entry.getKey()), + targetTablesTopology.get(entry.getKey()), + sourceTablesTopology.get(entry.getKey()), + orderedTargetTablesLocations.get(entry.getKey()), + "", + false, + taskType, executionContext); - ExecutableDdlJob subTask = subTaskJobFactory.create(); - executableDdlJob.combineTasks(subTask); - executableDdlJob.addTaskRelationship(tailTask, subTask.getHead()); - + ExecutableDdlJob subDdlJob = subTaskJobFactory.create(); + List subTasks = subDdlJob.getAllTasks(); + DdlTask dropUselessTableTask = + ComplexTaskFactory.CreateDropUselessPhyTableTask(schemaName, entry.getKey(), + getTheDeletedPartitionsLocation((AlterTableGroupDropPartitionPreparedData) preparedData, + entry.getKey()), + null, executionContext); + executableDdlJob.getExcludeResources().addAll(subDdlJob.getExcludeResources()); + executableDdlJob.addTaskRelationship(tailTask, subTasks.get(0)); + executableDdlJob.addTaskRelationship(subTasks.get(0), subTasks.get(1)); + executableDdlJob.addTaskRelationship(subTasks.get(1), subTasks.get(2)); if (subTaskJobFactory.getCdcTableGroupDdlMarkTask() != null) { + executableDdlJob.addTaskRelationship(subTasks.get(subTasks.size() - 1), + subTaskJobFactory.getCdcTableGroupDdlMarkTask()); + if (!emptyTaskAdded) { + executableDdlJob.addTaskRelationship(subTaskJobFactory.getCdcTableGroupDdlMarkTask(), + bringUpAlterTableGroupTasks.get(0)); + } + + List syncTasks = + subTaskJobFactory.generateSyncTask(schemaName, entry.getKey(), executionContext); + executableDdlJob.addTaskRelationship(bringUpAlterTableGroupTasks.get(0), syncTasks.get(0)); + executableDdlJob.addTaskRelationship(syncTasks.get(0), syncTasks.get(1)); + executableDdlJob.addTaskRelationship(syncTasks.get(1), emptyTask); + if (!emptyTaskAdded) { - executableDdlJob.addTask(emptyTask); - emptyTaskAdded = true; + tableGroupSyncTask = + new TableGroupSyncTask(preparedData.getSchemaName(), preparedData.getTableGroupName()); + executableDdlJob.addTaskRelationship(emptyTask, tableGroupSyncTask); } - executableDdlJob.addTask(subTaskJobFactory.getCdcTableGroupDdlMarkTask()); - executableDdlJob.addTaskRelationship(subTask.getTail(), emptyTask); - executableDdlJob.addTaskRelationship(emptyTask, subTaskJobFactory.getCdcTableGroupDdlMarkTask()); - executableDdlJob.addTaskRelationship(subTaskJobFactory.getCdcTableGroupDdlMarkTask(), bringUpAlterTableGroupTasks.get(0)); + executableDdlJob.addTaskRelationship(tableGroupSyncTask, dropUselessTableTask); + emptyTaskAdded = true; } else { - executableDdlJob.addTaskRelationship(subTask.getTail(), bringUpAlterTableGroupTasks.get(0)); + executableDdlJob.addTaskRelationship(subTasks.get(subTasks.size() - 1), + bringUpAlterTableGroupTasks.get(0)); } - - DdlTask dropUselessTableTask = ComplexTaskFactory.CreateDropUselessPhyTableTask(schemaName, entry.getKey(), - getTheDeletedPartitionsLocation(preparedData.getSchemaName(), entry.getKey()), executionContext); - executableDdlJob.addTask(dropUselessTableTask); executableDdlJob.labelAsTail(dropUselessTableTask); - executableDdlJob.addTaskRelationship( - bringUpAlterTableGroupTasks.get(bringUpAlterTableGroupTasks.size() - 1), dropUselessTableTask); - executableDdlJob.getExcludeResources().addAll(subTask.getExcludeResources()); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupExtractPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupExtractPartitionJobFactory.java index ac655b716..a687382b1 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupExtractPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupExtractPartitionJobFactory.java @@ -112,7 +112,8 @@ protected ExecutableDdlJob doCreate() { executableDdlJob.addSequentialTasks(Lists.newArrayList(validateTask, addMetaTask)); List bringUpAlterTableGroupTasks = - ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, executionContext); + ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, + preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); @@ -188,7 +189,8 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ executableDdlJob.addTaskRelationship(subTask.getTail(), bringUpAlterTableGroupTasks.get(0)); } DdlTask dropUselessTableTask = ComplexTaskFactory.CreateDropUselessPhyTableTask(schemaName, entry.getKey(), - sourceTablesTopology.get(entry.getKey()), executionContext); + sourceTablesTopology.get(entry.getKey()), targetTablesTopology.get(entry.getKey()), + executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob.addTaskRelationship( bringUpAlterTableGroupTasks.get(bringUpAlterTableGroupTasks.size() - 1), dropUselessTableTask); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupMergePartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupMergePartitionJobFactory.java index 8cfdeff20..01fe30df4 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupMergePartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupMergePartitionJobFactory.java @@ -137,7 +137,7 @@ protected ExecutableDdlJob doCreate() { )); List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); + taskType, preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupModifyPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupModifyPartitionJobFactory.java index 1dcbd8bda..d9b8c363d 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupModifyPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupModifyPartitionJobFactory.java @@ -160,7 +160,7 @@ protected ExecutableDdlJob doCreate() { List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); + taskType, preparedData.getDdlVersionId(), executionContext); if (preparedData.isDropVal()) { AlterTableGroupRemoveTempPartitionTask alterTableGroupRemoveTempPartitionTask = @@ -229,7 +229,8 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ DdlTask dropUselessTableTask = ComplexTaskFactory .CreateDropUselessPhyTableTask(schemaName, entry.getKey(), getTheDeletedPartitionsLocation(preparedData.getSchemaName(), entry.getKey(), - subTaskJobFactory.getTempPartitionSpecs()), executionContext); + subTaskJobFactory.getTempPartitionSpecs()), + targetTablesTopology.get(entry.getKey()), executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob .addTaskRelationship(bringUpAlterTableGroupTasks.get(bringUpAlterTableGroupTasks.size() - 1), diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupMovePartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupMovePartitionJobFactory.java index 8ebf0b1dd..d1821ede8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupMovePartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupMovePartitionJobFactory.java @@ -22,9 +22,9 @@ import com.alibaba.polardbx.executor.balancer.Balancer; import com.alibaba.polardbx.executor.balancer.stats.BalanceStats; import com.alibaba.polardbx.executor.balancer.stats.PartitionGroupStat; -import com.alibaba.polardbx.executor.balancer.stats.PartitionStat; import com.alibaba.polardbx.executor.ddl.job.builder.tablegroup.AlterTableGroupMovePartitionBuilder; import com.alibaba.polardbx.executor.ddl.job.task.CostEstimableDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.AnalyzePhyTableTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.DdlBackfillCostRecordTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.ImportTableSpaceDdlNormalTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.PauseCurrentJobTask; @@ -32,7 +32,6 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.SyncLsnTask; import com.alibaba.polardbx.executor.ddl.job.task.changset.ChangeSetApplyExecutorInitTask; import com.alibaba.polardbx.executor.ddl.job.task.changset.ChangeSetApplyFinishTask; -import com.alibaba.polardbx.executor.ddl.job.task.shared.EmptyLogTask; import com.alibaba.polardbx.executor.ddl.job.task.shared.EmptyTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupAddMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupValidateTask; @@ -67,7 +66,6 @@ import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; -import java.util.stream.Collectors; /** * @author luoyanxin @@ -175,7 +173,8 @@ protected ExecutableDdlJob doCreate() { executableDdlJob.labelAsHead(validateTask); List bringUpAlterTableGroupTasks = - ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, executionContext); + ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, + preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); @@ -190,8 +189,19 @@ protected ExecutableDdlJob doCreate() { constructSubTasks(schemaName, executableDdlJob, addMetaTask, bringUpAlterTableGroupTasks, alterTableGroupMovePartitionPreparedData.getTargetPartitionsLocation().keySet().iterator().next()); } else { + List parentTaskList = new ArrayList<>(); + boolean partitionSwitch = + ComplexTaskMetaManager.ComplexTaskStatus.SOURCE_WRITE_ONLY.name().equalsIgnoreCase(finalStatus) + || ComplexTaskMetaManager.ComplexTaskStatus.SOURCE_DELETE_ONLY.name().equalsIgnoreCase(finalStatus); PauseCurrentJobTask pauseCurrentJobTask = new PauseCurrentJobTask(schemaName); - constructSubTasks(schemaName, executableDdlJob, addMetaTask, ImmutableList.of(pauseCurrentJobTask), + if (partitionSwitch) { + executableDdlJob.addSequentialTasks(bringUpAlterTableGroupTasks); + parentTaskList.addAll(bringUpAlterTableGroupTasks); + executableDdlJob.addTaskRelationship( + bringUpAlterTableGroupTasks.get(bringUpAlterTableGroupTasks.size() - 1), pauseCurrentJobTask); + } + parentTaskList.add(pauseCurrentJobTask); + constructSubTasks(schemaName, executableDdlJob, addMetaTask, parentTaskList, alterTableGroupMovePartitionPreparedData.getTargetPartitionsLocation().keySet().iterator().next()); } @@ -242,7 +252,7 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ final boolean useChangeSet = ChangeSetUtils.isChangeSetProcedure(executionContext); - int parallelism = ScaleOutUtils.getTableGroupTaskParallelism(executionContext); + int pipelineSize = ScaleOutUtils.getTaskPipelineSize(executionContext); Queue leavePipeLineQueue = new LinkedList<>(); for (Map.Entry>>> entry : tablesTopologyMap.entrySet()) { @@ -290,15 +300,17 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ DbTopologyManager.getStorageInstIdByGroupName(schemaName, groupName)); } - syncLsnTask = new SyncLsnTask(schemaName, sourceGroupAndStorageIdMap, targetGroupAndStorageIdMap); - executableDdlJob.addTask(syncLsnTask); - syncLsnTaskAdded = true; + if (GeneralUtil.isNotEmpty(subTaskJobFactory.getPhysicalyTaskPipeLine())) { + syncLsnTask = new SyncLsnTask(schemaName, sourceGroupAndStorageIdMap, targetGroupAndStorageIdMap); + executableDdlJob.addTask(syncLsnTask); + syncLsnTaskAdded = true; + } } if (preparedData.isUsePhysicalBackfill()) { for (List pipeLine : GeneralUtil.emptyIfNull(subTaskJobFactory.getPhysicalyTaskPipeLine())) { DdlTask parentLeaveNode; - if (leavePipeLineQueue.size() < parallelism) { + if (leavePipeLineQueue.size() < pipelineSize) { parentLeaveNode = syncLsnTask; } else { parentLeaveNode = leavePipeLineQueue.poll(); @@ -327,9 +339,12 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ executableDdlJob.addTaskRelationship(pipeLine.get(i), importTableSpaceDdlNormalTask); } - executableDdlJob.addTaskRelationship(importTableSpaceDdlNormalTask, + AnalyzePhyTableTask analyzePhyTableTask = new AnalyzePhyTableTask(schemaName, tarGroupKey, + phyTableName); + executableDdlJob.addTaskRelationship(importTableSpaceDdlNormalTask, analyzePhyTableTask); + executableDdlJob.addTaskRelationship(analyzePhyTableTask, subTaskJobFactory.getBackfillTaskEdgeNodes().get(1)); - leavePipeLineQueue.add(importTableSpaceDdlNormalTask); + leavePipeLineQueue.add(analyzePhyTableTask); } } @@ -348,7 +363,8 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ } DdlTask dropUselessTableTask = ComplexTaskFactory.CreateDropUselessPhyTableTask(schemaName, entry.getKey(), - sourceTablesTopology.get(entry.getKey()), executionContext); + sourceTablesTopology.get(entry.getKey()), targetTablesTopology.get(entry.getKey()), + executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob.labelAsTail(dropUselessTableTask); executableDdlJob.addTaskRelationship( diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupOptimizePartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupOptimizePartitionJobFactory.java new file mode 100644 index 000000000..04986b866 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupOptimizePartitionJobFactory.java @@ -0,0 +1,172 @@ +package com.alibaba.polardbx.executor.ddl.job.factory; + +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.executor.ddl.job.builder.tablegroup.AlterTableGroupOptimizePartitionBuilder; +import com.alibaba.polardbx.executor.ddl.job.builder.tablegroup.AlterTableGroupTruncatePartitionBuilder; +import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.ddl.job.task.basic.OptimizeTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.TruncateTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcDdlMarkTask; +import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupValidateTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; +import com.alibaba.polardbx.executor.scaleout.ScaleOutUtils; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.TablesAccessor; +import com.alibaba.polardbx.gms.metadb.table.TablesRecord; +import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupOptimizePartitionPreparedData; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import com.google.common.collect.Lists; +import org.apache.calcite.rel.core.DDL; + +import java.sql.Connection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import static com.alibaba.polardbx.common.cdc.ICdcManager.DEFAULT_DDL_VERSION_ID; + +public class AlterTableGroupOptimizePartitionJobFactory extends DdlJobFactory { + + private final static Logger LOG = SQLRecorderLogger.ddlEngineLogger; + + protected DDL ddl; + protected AlterTableGroupOptimizePartitionPreparedData preparedData; + protected ExecutionContext executionContext; + + public AlterTableGroupOptimizePartitionJobFactory(DDL ddl, + AlterTableGroupOptimizePartitionPreparedData preparedData, + ExecutionContext executionContext) { + this.ddl = ddl; + this.preparedData = preparedData; + this.executionContext = executionContext; + } + + @Override + protected void validate() { + } + + @Override + protected ExecutableDdlJob doCreate() { + String schemaName = preparedData.getSchemaName(); + String tableGroupName = preparedData.getTableGroupName(); + + ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); + + AlterTableGroupOptimizePartitionBuilder builder = getDdlPhyPlanBuilder(); + + TableGroupConfig tableGroupConfig = OptimizerContext.getContext(schemaName).getTableGroupInfoManager() + .getTableGroupConfigByName(tableGroupName); + + Map tableVersions = getTableVersions(tableGroupConfig); + + boolean isBrdTg = tableGroupConfig.getTableGroupRecord().isBroadCastTableGroup(); + DdlTask validateTask = new AlterTableGroupValidateTask(schemaName, tableGroupName, tableVersions, true, + isBrdTg ? null : preparedData.getTargetPhysicalGroups(), false); + + executableDdlJob.labelAsHead(validateTask); + + constructSubTasks(schemaName, executableDdlJob, validateTask, builder); + + executableDdlJob.setMaxParallelism(ScaleOutUtils.getTableGroupTaskParallelism(executionContext)); + return executableDdlJob; + } + + public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJob, DdlTask tailTask, + AlterTableGroupOptimizePartitionBuilder builder) { + for (Map.Entry entry : builder.getTableVersions().entrySet()) { + String tableName = entry.getKey(); + Long tableVersion = entry.getValue(); + + PhysicalPlanData physicalPlanData = builder.getPhyPlanDataMap().get(tableName); + + ExecutableDdlJob subTasks = buildSubTasks(schemaName, tableName, tableVersion, physicalPlanData); + + executableDdlJob.combineTasks(subTasks); + executableDdlJob.addTaskRelationship(tailTask, subTasks.getHead()); + + executableDdlJob.getExcludeResources().addAll(subTasks.getExcludeResources()); + } + } + + private ExecutableDdlJob buildSubTasks(String schemaName, String tableName, + Long tableVersion, PhysicalPlanData physicalPlanData) { + ExecutableDdlJob subTasks = new ExecutableDdlJob(); + + Map tableVersions = new HashMap<>(1); + tableVersions.put(tableName, tableVersion); + ValidateTableVersionTask validateTableVersionTask = new ValidateTableVersionTask(schemaName, tableVersions); + + DdlTask phyDdlTask = new OptimizeTablePhyDdlTask(schemaName, physicalPlanData); +// DdlTask cdcDdlMarkTask = new CdcDdlMarkTask(schemaName, physicalPlanData, false, false, DEFAULT_DDL_VERSION_ID); + + subTasks.addSequentialTasks(Lists.newArrayList( + validateTableVersionTask, + phyDdlTask +// ,cdcDdlMarkTask /* no need to notify cdc */ + )); + + subTasks.labelAsHead(validateTableVersionTask); + + return subTasks; + } + + protected Map getTableVersions(TableGroupConfig tableGroupConfig) { + String schemaName = preparedData.getSchemaName(); + Map tableVersions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + tableGroupConfig.getAllTables().forEach(t -> { + Long tableVersion = executionContext.getSchemaManager(schemaName).getTable(t).getVersion(); + tableVersions.put(t, tableVersion); + }); + + try (Connection conn = MetaDbDataSource.getInstance().getConnection()) { + TablesAccessor tablesAccessor = new TablesAccessor(); + tablesAccessor.setConnection(conn); + for (Map.Entry entry : tableVersions.entrySet()) { + String tableName = entry.getKey(); + Long tableVersion = entry.getValue(); + + TablesRecord tablesRecord = tablesAccessor.query(schemaName, tableName, false); + + LOG.warn(String.format("%s current tableVersion in Ec:%d", tableName, tableVersion)); + + if (tablesRecord != null) { + LOG.warn(String.format("current tablesRecord details in prepare phase: %s", tablesRecord)); + } else { + LOG.warn( + String.format("current tablesRecord details: %s.%s %s", schemaName, tableName, " not exists")); + } + } + } catch (Throwable t) { + throw new TddlNestableRuntimeException(t); + } + + return tableVersions; + } + + protected AlterTableGroupOptimizePartitionBuilder getDdlPhyPlanBuilder() { + return (AlterTableGroupOptimizePartitionBuilder) new AlterTableGroupOptimizePartitionBuilder(ddl, preparedData, + executionContext).build(); + } + + @Override + protected void excludeResources(Set resources) { + resources.add(concatWithDot(preparedData.getSchemaName(), preparedData.getTableGroupName())); + for (String partitionName : preparedData.getOptimizePartitionNames()) { + resources.add(concatWithDot(concatWithDot(preparedData.getSchemaName(), preparedData.getTableGroupName()), + partitionName)); + } + } + + @Override + protected void sharedResources(Set resources) { + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupRenamePartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupRenamePartitionJobFactory.java index a7812b2c5..ffda6fdc6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupRenamePartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupRenamePartitionJobFactory.java @@ -22,17 +22,18 @@ import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupRenamePartitionChangeMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.TableGroupSyncTask; +import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.ddl.newengine.job.TransientDdlJob; -import com.alibaba.polardbx.gms.partition.TablePartRecordInfoContext; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupRenamePartitionPreparedData; import com.google.common.collect.Lists; +import org.apache.calcite.sql.SqlKind; import org.apache.calcite.rel.core.DDL; import java.util.ArrayList; @@ -61,7 +62,13 @@ public AlterTableGroupRenamePartitionJobFactory(DDL ddl, AlterTableGroupRenamePa @Override protected void validate() { - + TableGroupConfig tableGroupConfig = + OptimizerContext.getContext(preparedData.getSchemaName()).getTableGroupInfoManager() + .getTableGroupConfigByName(preparedData.getTableGroupName()); + for (String tableName : tableGroupConfig.getAllTables()) { + TableValidator.validateTableWithCCI(preparedData.getSchemaName(), tableName, executionContext, + SqlKind.RENAME_PARTITION); + } } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupReorgPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupReorgPartitionJobFactory.java index 17d2ecb68..8c7c1218b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupReorgPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupReorgPartitionJobFactory.java @@ -139,7 +139,8 @@ protected ExecutableDdlJob doCreate() { )); List bringUpAlterTableGroupTasks = - ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, executionContext); + ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, + preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSplitPartitionByHotValueJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSplitPartitionByHotValueJobFactory.java index 199d5c53a..0a9431577 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSplitPartitionByHotValueJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSplitPartitionByHotValueJobFactory.java @@ -123,7 +123,7 @@ protected ExecutableDdlJob doCreate() { )); List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); + taskType, preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); @@ -208,6 +208,7 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ } DdlTask dropUselessTableTask = ComplexTaskFactory .CreateDropUselessPhyTableTask(schemaName, entry.getKey(), sourceTablesTopology.get(entry.getKey()), + targetTablesTopology.get(entry.getKey()), executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSplitPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSplitPartitionJobFactory.java index 40dbe5903..bd5e74826 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSplitPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSplitPartitionJobFactory.java @@ -45,12 +45,10 @@ import org.apache.commons.lang.StringUtils; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; -import java.util.stream.Collectors; /** * @author luoyanxin @@ -141,7 +139,7 @@ protected ExecutableDdlJob doCreate() { )); List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); + taskType, preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSubTaskJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSubTaskJobFactory.java index 587a61fbc..8e4e43b61 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSubTaskJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupSubTaskJobFactory.java @@ -29,7 +29,7 @@ import com.alibaba.polardbx.executor.ddl.job.converter.DdlJobDataConverter; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.task.basic.AddLogicalForeignKeyTask; -import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.CreatePhyTableWithRollbackCheckTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.DropIndexPhyDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.DropLogicalForeignKeyTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcTableGroupDdlMarkTask; @@ -64,6 +64,8 @@ import java.util.Optional; import java.util.Set; +import static org.apache.calcite.sql.SqlIdentifier.surroundWithBacktick; + public class AlterTableGroupSubTaskJobFactory extends DdlJobFactory { @Deprecated @@ -149,13 +151,17 @@ protected ExecutableDdlJob doCreate() { //2.1 insert meta to complex_task_outline taskList.add(addMetaTask); //2.2 create partitioned physical table - phyDdlTableOperations.forEach(o -> o.setPartitionInfo(newPartitionInfo)); - if (!tableTopology.isEmpty()) { - PhysicalPlanData physicalPlanData = - DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, phyDdlTableOperations, executionContext); - DdlTask phyDdlTask = - new CreateTablePhyDdlTask(schemaName, physicalPlanData.getLogicalTableName(), physicalPlanData); - taskList.add(phyDdlTask); + if (!preparedData.isColumnarIndex()) { + phyDdlTableOperations.forEach(o -> o.setPartitionInfo(newPartitionInfo)); + if (!tableTopology.isEmpty()) { + PhysicalPlanData physicalPlanData = + DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, phyDdlTableOperations, + executionContext); + DdlTask phyDdlTask = + new CreatePhyTableWithRollbackCheckTask(schemaName, physicalPlanData.getLogicalTableName(), + physicalPlanData, sourceTableTopology); + taskList.add(phyDdlTask); + } } final String finalStatus = @@ -175,18 +181,20 @@ protected ExecutableDdlJob doCreate() { StringUtils.equalsIgnoreCase(ComplexTaskMetaManager.ComplexTaskStatus.WRITE_REORG.name(), finalStatus); DdlTask mayBeTailTask = taskList.get(taskList.size() - 1); + boolean skipBackFill = skipBackfill || tableTopology.isEmpty() || preparedData.isColumnarIndex(); List bringUpNewPartitions = ComplexTaskFactory .addPartitionTasks(schemaName, tableName, sourceTableTopology, targetTableTopology, stayAtCreating, stayAtDeleteOnly, stayAtWriteOnly, stayAtWriteReOrg, - skipBackfill || tableTopology.isEmpty(), executionContext, isBroadcast(), taskType); + skipBackFill, executionContext, isBroadcast(), taskType); //3.2 status: CREATING -> DELETE_ONLY -> WRITE_ONLY -> WRITE_REORG -> READY_TO_PUBLIC taskList.addAll(bringUpNewPartitions); TableMeta tableMeta = OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(tableName); - if (!tableTopology.isEmpty() && tableMeta.isGsi() && !tableMeta.isClustered() + if (!tableTopology.isEmpty() && tableMeta.isGsi() && !tableMeta.isClustered() && !tableMeta.isHasPrimaryKey() && !tableMeta.getGsiTableMetaBean().gsiMetaBean.nonUnique) { - String sql = "drop index " + TddlConstants.UGSI_PK_UNIQUE_INDEX_NAME + " on " + tableName; + String sql = + "drop index " + TddlConstants.UGSI_PK_UNIQUE_INDEX_NAME + " on " + surroundWithBacktick(tableName); DropPartLocalIndexBuilder builder = DropPartLocalIndexBuilder.createBuilder(schemaName, tableName, TddlConstants.UGSI_PK_UNIQUE_INDEX_NAME, @@ -212,7 +220,8 @@ protected ExecutableDdlJob doCreate() { DdlTask cdcDdlMarkTask = new CdcTableGroupDdlMarkTask(tableGroupName, schemaName, tableName, sqlKind, newTopology, dc.getDdlStmt(), - sqlKind == SqlKind.ALTER_TABLEGROUP ? CdcDdlMarkVisibility.Private : CdcDdlMarkVisibility.Protected); + sqlKind == SqlKind.ALTER_TABLEGROUP ? CdcDdlMarkVisibility.Private : CdcDdlMarkVisibility.Protected, + preparedData.isColumnarIndex()); if (stayAtPublic) { cdcTableGroupDdlMarkTask = cdcDdlMarkTask; } @@ -230,7 +239,7 @@ protected ExecutableDdlJob doCreate() { @Override protected void excludeResources(Set resources) { - for (String phyTableName : preparedData.getNewPhyTables()) { + for (String phyTableName : GeneralUtil.emptyIfNull(preparedData.getNewPhyTables())) { resources.add( concatWithDot(concatWithDot(preparedData.getSchemaName(), preparedData.getTableName()), phyTableName)); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupTruncatePartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupTruncatePartitionJobFactory.java index 5f5d626c4..df2dc7d09 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupTruncatePartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableGroupTruncatePartitionJobFactory.java @@ -23,6 +23,7 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.TruncateTablePhyDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcDdlMarkTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; +import com.alibaba.polardbx.executor.ddl.job.task.shared.EmptyTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupValidateTask; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; @@ -33,6 +34,7 @@ import com.alibaba.polardbx.gms.metadb.table.TablesRecord; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupTruncatePartitionPreparedData; import com.alibaba.polardbx.statistics.SQLRecorderLogger; @@ -54,13 +56,16 @@ public class AlterTableGroupTruncatePartitionJobFactory extends DdlJobFactory { protected DDL ddl; protected AlterTableGroupTruncatePartitionPreparedData preparedData; protected ExecutionContext executionContext; + protected final Long versionId; public AlterTableGroupTruncatePartitionJobFactory(DDL ddl, AlterTableGroupTruncatePartitionPreparedData preparedData, - ExecutionContext executionContext) { + ExecutionContext executionContext, + Long versionId) { this.ddl = ddl; this.preparedData = preparedData; this.executionContext = executionContext; + this.versionId = versionId; } @Override @@ -119,8 +124,13 @@ private ExecutableDdlJob buildSubTasks(String schemaName, String tableName, tableVersions.put(tableName, tableVersion); ValidateTableVersionTask validateTableVersionTask = new ValidateTableVersionTask(schemaName, tableVersions); - DdlTask phyDdlTask = new TruncateTablePhyDdlTask(schemaName, physicalPlanData); - DdlTask cdcDdlMarkTask = new CdcDdlMarkTask(schemaName, physicalPlanData, false, false, DEFAULT_DDL_VERSION_ID); + DdlTask phyDdlTask = new EmptyTask(schemaName); + TableMeta tableMeta = + OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTableWithNull(tableName); + if (tableMeta != null && !tableMeta.isColumnar()) { + phyDdlTask = new TruncateTablePhyDdlTask(schemaName, physicalPlanData); + } + DdlTask cdcDdlMarkTask = new CdcDdlMarkTask(schemaName, physicalPlanData, false, false, versionId); subTasks.addSequentialTasks(Lists.newArrayList( validateTableVersionTask, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableJobFactory.java index ab9cc5835..c5abadee5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableJobFactory.java @@ -235,6 +235,17 @@ protected ExecutableDdlJob doCreate() { !prepareData.getAddedForeignKeys().isEmpty() || !prepareData.getDroppedForeignKeys().isEmpty(); boolean isForeignKeyCdcMark = isForeignKeysDdl && !executionContext.getDdlContext().isFkRepartition(); + boolean isRenameCci = false; + String cciTableName = null; + if (prepareData.isColumnar() && !prepareData.getRenamedIndexes().isEmpty()) { + TableMeta cciTableMeta = OptimizerContext.getContext(schemaName).getLatestSchemaManager() + .getTableWithNull(prepareData.getRenamedIndexes().get(0).getValue()); + isRenameCci = cciTableMeta != null && cciTableMeta.isColumnar(); + if (isRenameCci) { + cciTableName = prepareData.getRenamedIndexes().get(0).getValue(); + } + } + Boolean generateTwoPhaseDdlTask = supportTwoPhaseDdl; DdlTask phyDdlTask = new AlterTablePhyDdlTask(schemaName, logicalTableName, physicalPlanData); if (this.repartition) { @@ -261,6 +272,10 @@ protected ExecutableDdlJob doCreate() { } else { if (ignoreMarkCdcDDL()) { cdcDdlMarkTask = null; + } else if (isRenameCci) { + cdcDdlMarkTask = new CdcDdlMarkTask(schemaName, physicalPlanData, false, isForeignKeyCdcMark, + prepareData.getDdlVersionId()); + ((CdcDdlMarkTask) cdcDdlMarkTask).setCci(true); } else { cdcDdlMarkTask = new CdcDdlMarkTask(schemaName, physicalPlanData, false, isForeignKeyCdcMark, prepareData.getDdlVersionId()); @@ -333,9 +348,9 @@ protected ExecutableDdlJob doCreate() { beginAlterColumnDefault, beginAlterColumnDefaultSyncTask, phyDdlTask, + updateMetaTask, cdcDdlMarkTask, - dropESATask, - updateMetaTask + dropESATask ).stream().filter(Objects::nonNull).collect(Collectors.toList()); } else { taskList = Lists.newArrayList( @@ -345,8 +360,8 @@ protected ExecutableDdlJob doCreate() { tableSyncTaskAfterHiding ); taskList.addAll(generateTwoPhaseDdlTask(ddlAlgorithmType, twoPhaseDdlId)); - taskList.add(cdcDdlMarkTask); taskList.add(updateMetaTask); + taskList.add(cdcDdlMarkTask); taskList = taskList.stream().filter(Objects::nonNull).collect(Collectors.toList()); } } else { @@ -362,7 +377,15 @@ protected ExecutableDdlJob doCreate() { alterTableViaDefaultAlgorithm(generateTwoPhaseDdlTask, isModifyColumn); DdlAlgorithmType algorithmType = alterCheckResult.getKey(); Long twoPhaseDdlId = alterCheckResult.getValue(); - if (!generateTwoPhaseDdlTask || algorithmType == DdlAlgorithmType.COPY_ADD_DROP_COLUMN_INDEX + if (isRenameCci) { + taskList = Lists.newArrayList( + validateTask, + updateMetaTask, + cdcDdlMarkTask, + // must sync cci table to reload table group cache + new TableSyncTask(schemaName, cciTableName) + ).stream().filter(Objects::nonNull).collect(Collectors.toList()); + } else if (!generateTwoPhaseDdlTask || algorithmType == DdlAlgorithmType.COPY_ADD_DROP_COLUMN_INDEX || algorithmType == DdlAlgorithmType.UNKNOWN_MODIFY_CHANGE_COLUMN_ALGORITHM || algorithmType == DdlAlgorithmType.UNKNOWN_ALGORITHM) { taskList = Lists.newArrayList( @@ -370,8 +393,8 @@ protected ExecutableDdlJob doCreate() { beginAlterColumnDefault, beginAlterColumnDefaultSyncTask, phyDdlTask, - cdcDdlMarkTask, - updateMetaTask + updateMetaTask, + cdcDdlMarkTask ).stream().filter(Objects::nonNull).collect(Collectors.toList()); } else { taskList = Lists.newArrayList( @@ -381,8 +404,8 @@ protected ExecutableDdlJob doCreate() { ); taskList.addAll(generateTwoPhaseDdlTask(algorithmType, twoPhaseDdlId)); - taskList.add(cdcDdlMarkTask); taskList.add(updateMetaTask); + taskList.add(cdcDdlMarkTask); taskList = taskList.stream().filter(Objects::nonNull).collect(Collectors.toList()); } } @@ -440,13 +463,16 @@ private DropEntitySecurityAttrTask createDropESATask( protected void excludeResources(Set resources) { resources.add(concatWithDot(schemaName, logicalTableName)); + // exclude foreign key tables + excludeFkTables(resources); + } + + @Override + protected void sharedResources(Set resources) { String tgName = FactoryUtils.getTableGroupNameByTableName(schemaName, logicalTableName); if (tgName != null) { resources.add(concatWithDot(schemaName, tgName)); } - - // exclude foreign key tables - excludeFkTables(resources); } protected Boolean checkAlgorithmSpecificationCopy(SQLAlterTableStatement alterTable) { @@ -715,10 +741,6 @@ protected List generateTwoPhaseDdlTask(DdlAlgorithmType algorithmType, return taskList; } - @Override - protected void sharedResources(Set resources) { - } - public void validateExistence(boolean validateExistence) { this.validateExistence = validateExistence; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableMergePartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableMergePartitionJobFactory.java index ecf123048..437f0df63 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableMergePartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableMergePartitionJobFactory.java @@ -19,14 +19,11 @@ import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.ddl.job.builder.tablegroup.AlterTableMergePartitionBuilder; -import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateTableGroupAddMetaTask; -import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateTableGroupValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.PauseCurrentJobTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.shared.EmptyTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupAddMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupValidateTask; -import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.TableGroupsSyncTask; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.ddl.util.ChangeSetUtils; @@ -242,7 +239,7 @@ private ExecutableDdlJob mergeInOriginTableGroup() { )); List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); + taskType, preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); @@ -340,6 +337,7 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ DdlTask dropUselessTableTask = ComplexTaskFactory .CreateDropUselessPhyTableTask(schemaName, preparedData.getTableName(), sourceTablesTopology.get(preparedData.getTableName()), + targetTablesTopology.get(preparedData.getTableName()), executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob.labelAsTail(dropUselessTableTask); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableModifyPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableModifyPartitionJobFactory.java index 51be69f52..62033eb4e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableModifyPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableModifyPartitionJobFactory.java @@ -159,7 +159,7 @@ protected ExecutableDdlJob modifyInOriginTableGroup() { List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); + taskType, preparedData.getDdlVersionId(), executionContext); if (((AlterTableGroupModifyPartitionPreparedData) preparedData).isDropVal()) { AlterTableGroupRemoveTempPartitionTask alterTableGroupRemoveTempPartitionTask = @@ -361,7 +361,8 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ DdlTask dropUselessTableTask = ComplexTaskFactory .CreateDropUselessPhyTableTask(schemaName, preparedData.getTableName(), getTheDeletedPartitionsLocation(preparedData.getSchemaName(), preparedData.getTableName(), - subTaskJobFactory.getTempPartitionSpecs()), executionContext); + subTaskJobFactory.getTempPartitionSpecs()), + targetTablesTopology.get(preparedData.getTableName()), executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob.labelAsTail(dropUselessTableTask); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableMovePartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableMovePartitionJobFactory.java index 2d34988cc..54f951888 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableMovePartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableMovePartitionJobFactory.java @@ -24,6 +24,7 @@ import com.alibaba.polardbx.executor.balancer.stats.PartitionStat; import com.alibaba.polardbx.executor.ddl.job.builder.tablegroup.AlterTableMovePartitionBuilder; import com.alibaba.polardbx.executor.ddl.job.task.CostEstimableDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.AnalyzePhyTableTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.DdlBackfillCostRecordTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.ImportTableSpaceDdlNormalTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.PauseCurrentJobTask; @@ -336,7 +337,8 @@ private ExecutableDdlJob doMoveInOriginTableGroup() { executableDdlJob.labelAsHead(validateTask); List bringUpAlterTableGroupTasks = - ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, executionContext); + ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, + preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); @@ -400,7 +402,8 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ executableDdlJob.addTaskRelationship(tailTask, subTask.getHead()); SyncLsnTask syncLsnTask = null; - int parallelism = ScaleOutUtils.getTableGroupTaskParallelism(executionContext); + int pipelineSize = ScaleOutUtils.getTaskPipelineSize(executionContext); + Queue leavePipeLineQueue = new LinkedList<>(); if (preparedData.isUsePhysicalBackfill()) { @@ -417,13 +420,14 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ DbTopologyManager.getStorageInstIdByGroupName(schemaName, groupName)); } - syncLsnTask = - new SyncLsnTask(schemaName, sourceGroupAndStorageIdMap, targetGroupAndStorageIdMap); - executableDdlJob.addTask(syncLsnTask); + if (GeneralUtil.isNotEmpty(subTaskJobFactory.getPhysicalyTaskPipeLine())) { + syncLsnTask = new SyncLsnTask(schemaName, sourceGroupAndStorageIdMap, targetGroupAndStorageIdMap); + executableDdlJob.addTask(syncLsnTask); + } for (List pipeLine : GeneralUtil.emptyIfNull(subTaskJobFactory.getPhysicalyTaskPipeLine())) { DdlTask parentLeaveNode; - if (leavePipeLineQueue.size() < parallelism) { + if (leavePipeLineQueue.size() < pipelineSize) { parentLeaveNode = syncLsnTask; } else { parentLeaveNode = leavePipeLineQueue.poll(); @@ -455,9 +459,13 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ executableDdlJob.addTaskRelationship(pipeLine.get(i), importTableSpaceDdlNormalTask); } - executableDdlJob.addTaskRelationship(importTableSpaceDdlNormalTask, + + AnalyzePhyTableTask analyzePhyTableTask = new AnalyzePhyTableTask(schemaName, tarGroupKey, + phyTableName); + executableDdlJob.addTaskRelationship(importTableSpaceDdlNormalTask, analyzePhyTableTask); + executableDdlJob.addTaskRelationship(analyzePhyTableTask, subTaskJobFactory.getBackfillTaskEdgeNodes().get(1)); - leavePipeLineQueue.add(importTableSpaceDdlNormalTask); + leavePipeLineQueue.add(analyzePhyTableTask); } } @@ -477,7 +485,8 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ 0) instanceof PauseCurrentJobTask)) { DdlTask dropUselessTableTask = ComplexTaskFactory.CreateDropUselessPhyTableTask(schemaName, preparedData.getTableName(), - sourceTablesTopology.get(preparedData.getTableName()), executionContext); + sourceTablesTopology.get(preparedData.getTableName()), + targetTablesTopology.get(preparedData.getTableName()), executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob.labelAsTail(dropUselessTableTask); executableDdlJob.addTaskRelationship( diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableOptimizePartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableOptimizePartitionJobFactory.java new file mode 100644 index 000000000..3ceebb26c --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableOptimizePartitionJobFactory.java @@ -0,0 +1,23 @@ +package com.alibaba.polardbx.executor.ddl.job.factory; + +import com.alibaba.polardbx.executor.ddl.job.builder.tablegroup.AlterTableGroupOptimizePartitionBuilder; +import com.alibaba.polardbx.executor.ddl.job.builder.tablegroup.AlterTableOptimizePartitionBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupOptimizePartitionPreparedData; +import org.apache.calcite.rel.core.DDL; + +public class AlterTableOptimizePartitionJobFactory extends AlterTableGroupOptimizePartitionJobFactory { + + public AlterTableOptimizePartitionJobFactory(DDL ddl, + AlterTableGroupOptimizePartitionPreparedData preparedData, + ExecutionContext executionContext) { + super(ddl, preparedData, executionContext); + } + + @Override + protected AlterTableGroupOptimizePartitionBuilder getDdlPhyPlanBuilder() { + return (AlterTableGroupOptimizePartitionBuilder) new AlterTableOptimizePartitionBuilder(ddl, preparedData, + executionContext).build(); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableRenamePartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableRenamePartitionJobFactory.java index a5dbf08fd..4e73f070f 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableRenamePartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableRenamePartitionJobFactory.java @@ -29,20 +29,20 @@ import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableRenamePartitionChangeMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.CleanupEmptyTableGroupTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.TableGroupSyncTask; +import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.ddl.newengine.job.TransientDdlJob; -import com.alibaba.polardbx.gms.partition.TablePartRecordInfoContext; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.DdlContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupBasePreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupRenamePartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableRenamePartitionPreparedData; import com.google.common.collect.Lists; import org.apache.calcite.rel.core.DDL; +import org.apache.calcite.sql.SqlKind; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; @@ -66,7 +66,8 @@ public AlterTableRenamePartitionJobFactory(DDL ddl, AlterTableRenamePartitionPre @Override protected void validate() { - + TableValidator.validateTableWithCCI(preparedData.getSchemaName(), preparedData.getTableName(), executionContext, + SqlKind.RENAME_PARTITION); } @Override @@ -293,8 +294,11 @@ private DdlTask buildCdcDdlMarkTask() { placeHolder = false; } + String logicalTable = preparedData.getTableName(); + TableMeta tableMeta = executionContext.getSchemaManager(preparedData.getSchemaName()).getTable(logicalTable); + return new CdcAlterTableRenamePartitionMarkTask(preparedData.getSchemaName(), - preparedData.getTableName(), placeHolder); + preparedData.getTableName(), placeHolder, tableMeta.isColumnar(), preparedData.getDdlVersionId()); } private boolean isFromSetTableGroup(ExecutionContext executionContext) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableReorgPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableReorgPartitionJobFactory.java index 816ec9ed6..95c142f74 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableReorgPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableReorgPartitionJobFactory.java @@ -243,7 +243,8 @@ private ExecutableDdlJob reorgInOriginTableGroup() { )); List bringUpAlterTableGroupTasks = - ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, executionContext); + ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, taskType, + preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); @@ -325,6 +326,7 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ DdlTask dropUselessTableTask = ComplexTaskFactory .CreateDropUselessPhyTableTask(schemaName, preparedData.getTableName(), sourceTablesTopology.get(preparedData.getTableName()), + targetTablesTopology.get(preparedData.getTableName()), executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob.labelAsTail(dropUselessTableTask); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSetTableGroupJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSetTableGroupJobFactory.java index c24daa5b8..5249184fa 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSetTableGroupJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSetTableGroupJobFactory.java @@ -24,7 +24,7 @@ import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; -import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.CreatePhyTableWithRollbackCheckTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.UpdateTablesVersionTask; @@ -190,7 +190,7 @@ protected ExecutableDdlJob doCreate() { boolean isGsi = isGsi(schemaName, preparedData.getPrimaryTableName(), preparedData.getTableName()); CdcAlterTableSetTableGroupMarkTask cdcAlterTableSetTableGroupMarkTask = new CdcAlterTableSetTableGroupMarkTask(schemaName, preparedData.getPrimaryTableName(), - preparedData.getTableName(), isGsi); + preparedData.getTableName(), isGsi, true); executableDdlJob.addSequentialTasks(Lists.newArrayList( validateTask, tableSetTableGroupChangeMetaOnlyTask, @@ -250,7 +250,8 @@ protected ExecutableDdlJob doCreate() { } List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, targetTableGroupName, tableName, - ComplexTaskMetaManager.ComplexTaskType.SET_TABLEGROUP, executionContext); + ComplexTaskMetaManager.ComplexTaskType.SET_TABLEGROUP, preparedData.getDdlVersionId(), + executionContext); executableDdlJob.addSequentialTasks(bringUpAlterTableGroupTasks); @@ -286,7 +287,7 @@ private ExecutableDdlJob repartitionWithTableGroup() { CdcAlterTableSetTableGroupMarkTask cdcAlterTableSetTableGroupMarkTask = new CdcAlterTableSetTableGroupMarkTask(schemaName, preparedData.getPrimaryTableName(), - preparedData.getTableName(), isGsi); + preparedData.getTableName(), isGsi, false); executableDdlJob.appendTask(cdcAlterTableSetTableGroupMarkTask); } @@ -347,7 +348,7 @@ private ExecutableDdlJob alignPartitionNameAndSetTableGroup() { CdcAlterTableSetTableGroupMarkTask cdcAlterTableSetTableGroupMarkTask = new CdcAlterTableSetTableGroupMarkTask(schemaName, preparedData.getPrimaryTableName(), - preparedData.getTableName(), isGsi); + preparedData.getTableName(), isGsi, false); executableDdlJob.appendTask(cdcAlterTableSetTableGroupMarkTask); } @@ -403,7 +404,8 @@ protected void constructSubTasks(String schemaName, PartitionInfo curPartitionIn taskList.add(addMetaTask); //2.2 create partitioned physical table DdlTask phyDdlTask = - new CreateTablePhyDdlTask(schemaName, physicalPlanData.getLogicalTableName(), physicalPlanData); + new CreatePhyTableWithRollbackCheckTask(schemaName, physicalPlanData.getLogicalTableName(), + physicalPlanData, sourceTableTopology); taskList.add(phyDdlTask); final String finalStatus = @@ -447,7 +449,7 @@ protected void constructSubTasks(String schemaName, PartitionInfo curPartitionIn CdcDdlMarkVisibility.Protected; CdcTableGroupDdlMarkTask cdcTableGroupDdlMarkTask = new CdcTableGroupDdlMarkTask(preparedData.getTableGroupName(), schemaName, tableName, sqlKind, newTopology, - dc.getDdlStmt(), cdcDdlMarkVisibility); + dc.getDdlStmt(), cdcDdlMarkVisibility, false); executableDdlJob.addTask(cdcTableGroupDdlMarkTask); executableDdlJob.addTaskRelationship(taskList.get(taskList.size() - 1), cdcTableGroupDdlMarkTask); @@ -455,6 +457,7 @@ protected void constructSubTasks(String schemaName, PartitionInfo curPartitionIn DdlTask dropUselessTableTask = ComplexTaskFactory.CreateDropUselessPhyTableTask(schemaName, tableName, sourceTableTopology, + targetTableTopology, executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob.addTaskRelationship(bringUpAlterTableGroupTasks.get(bringUpAlterTableGroupTasks.size() - 1), diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSplitPartitionByHotValueJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSplitPartitionByHotValueJobFactory.java index 0716a434e..ccee4fcc0 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSplitPartitionByHotValueJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSplitPartitionByHotValueJobFactory.java @@ -136,7 +136,7 @@ private ExecutableDdlJob splitInOriginTableGroup() { )); List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); + taskType, preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); @@ -331,6 +331,7 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ DdlTask dropUselessTableTask = ComplexTaskFactory .CreateDropUselessPhyTableTask(schemaName, preparedData.getTableName(), sourceTablesTopology.get(preparedData.getTableName()), + targetTablesTopology.get(preparedData.getTableName()), executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSplitPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSplitPartitionJobFactory.java index 997222239..a31c257d9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSplitPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableSplitPartitionJobFactory.java @@ -260,7 +260,7 @@ private ExecutableDdlJob splitInOriginTableGroup() { )); List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); + taskType, preparedData.getDdlVersionId(), executionContext); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); @@ -376,6 +376,7 @@ public void constructSubTasks(String schemaName, ExecutableDdlJob executableDdlJ DdlTask dropUselessTableTask = ComplexTaskFactory .CreateDropUselessPhyTableTask(schemaName, preparedData.getTableName(), sourceTablesTopology.get(preparedData.getTableName()), + targetTablesTopology.get(preparedData.getTableName()), executionContext); executableDdlJob.addTask(dropUselessTableTask); executableDdlJob.labelAsTail(dropUselessTableTask); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableTruncatePartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableTruncatePartitionJobFactory.java index 24b56bd4e..36553e5ae 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableTruncatePartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/AlterTableTruncatePartitionJobFactory.java @@ -26,8 +26,9 @@ public class AlterTableTruncatePartitionJobFactory extends AlterTableGroupTrunca public AlterTableTruncatePartitionJobFactory(DDL ddl, AlterTableGroupTruncatePartitionPreparedData preparedData, - ExecutionContext executionContext) { - super(ddl, preparedData, executionContext); + ExecutionContext executionContext, + Long versionId) { + super(ddl, preparedData, executionContext, versionId); } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ComplexTaskFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ComplexTaskFactory.java index 113d6635a..e4e9b0496 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ComplexTaskFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ComplexTaskFactory.java @@ -24,13 +24,15 @@ import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.backfill.AlterTableGroupBackFillTask; import com.alibaba.polardbx.executor.ddl.job.task.backfill.MoveTableBackFillTask; -import com.alibaba.polardbx.executor.ddl.job.task.basic.DropTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.DropTablePhyDdlWithCheckTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.MoveDatabaseCleanupTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.MoveDatabaseSwitchDataSourcesTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TablesSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.UpdateTablesVersionTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcColumnarTableGroupDdlMark; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcMoveDatabaseDdlMarkTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.WaitColumnarTableAlterPartitionTask; import com.alibaba.polardbx.executor.ddl.job.task.shared.EmptyLogTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterComplexTaskUpdateJobStatusTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableChangeTopologyRefreshMetaTask; @@ -41,7 +43,6 @@ import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.CleanupEmptyTableGroupTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.TableGroupSyncTask; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; -import com.alibaba.polardbx.gms.partition.TablePartRecordInfoContext; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; @@ -49,6 +50,8 @@ import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.PhyDdlTableOperation; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableDropPartitionPreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupDropPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.MoveDatabasePreparedData; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import org.apache.calcite.sql.SqlKind; @@ -62,6 +65,8 @@ import java.util.TreeSet; import java.util.concurrent.TimeUnit; +import static com.alibaba.polardbx.common.cdc.ICdcManager.DEFAULT_DDL_VERSION_ID; + public class ComplexTaskFactory { /** * for @@ -186,9 +191,12 @@ public static List bringUpAlterTableGroup(String schemaName, String tableGroupName, String tableName, ComplexTaskMetaManager.ComplexTaskType complexTaskType, + Long versionId, ExecutionContext executionContext) { List logicalTableNames = new ArrayList<>(); + final String finalStatus = + executionContext.getParamManager().getString(ConnectionParams.TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG); // not include GSI tables Set primaryLogicalTables = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); TableGroupConfig tableGroupConfig = OptimizerContext.getContext(schemaName).getTableGroupInfoManager() @@ -255,7 +263,7 @@ public static List bringUpAlterTableGroup(String schemaName, List synTableGroupTasks = new ArrayList<>(); if (complexTaskType == ComplexTaskMetaManager.ComplexTaskType.MOVE_PARTITION) { alterTableGroupRefreshTableGroupMetaTask = - new AlterTableGroupMovePartitionRefreshMetaTask(schemaName, tableGroupName); + new AlterTableGroupMovePartitionRefreshMetaTask(schemaName, tableGroupName, versionId); BaseDdlTask synTableGroup = new TableGroupSyncTask(schemaName, tableGroupName); synTableGroupTasks.add(synTableGroup); @@ -270,7 +278,7 @@ public static List bringUpAlterTableGroup(String schemaName, alterTableGroupRefreshTableGroupMetaTask = new AlterTableSetTableGroupRefreshMetaTask(schemaName, tableGroupName, partitionInfo.getTableGroupId(), - tableName); + tableName, versionId); CleanupEmptyTableGroupTask cleanupEmptyTableGroupTask = new CleanupEmptyTableGroupTask(schemaName, sourceTableGroupConfigInfo.getTableGroupRecord().getTg_name()); @@ -283,24 +291,52 @@ public static List bringUpAlterTableGroup(String schemaName, synTableGroupTasks.add(synSourceTableGroup); } else { alterTableGroupRefreshTableGroupMetaTask = - new AlterTableGroupRefreshMetaBaseTask(schemaName, tableGroupName); + new AlterTableGroupRefreshMetaBaseTask(schemaName, tableGroupName, versionId); BaseDdlTask synTableGroup = new TableGroupSyncTask(schemaName, tableGroupName); synTableGroupTasks.add(synTableGroup); } + List columnarTables = new ArrayList<>(); + boolean hasColumnar = hasColumnarTable(tableGroupConfig, columnarTables, executionContext, schemaName); + AlterTableGroupCleanupTask alterTableGroupCleanupTask = new AlterTableGroupCleanupTask(schemaName); taskList.add(DoingReorgTask); + + if (ComplexTaskMetaManager.ComplexTaskStatus.SOURCE_WRITE_ONLY.name().equalsIgnoreCase(finalStatus)) { + taskList + .add(new TablesSyncTask(schemaName, logicalTableNames, enablePreemptiveMdl, initWait, interval, + TimeUnit.MILLISECONDS, true)); + return taskList; + } taskList .add(new TablesSyncTask(schemaName, logicalTableNames, enablePreemptiveMdl, initWait, interval, TimeUnit.MILLISECONDS)); taskList.add(sourceWriteOnlyTask); + + if (ComplexTaskMetaManager.ComplexTaskStatus.SOURCE_DELETE_ONLY.name().equalsIgnoreCase(finalStatus)) { + taskList + .add(new TablesSyncTask(schemaName, logicalTableNames, enablePreemptiveMdl, initWait, interval, + TimeUnit.MILLISECONDS, true)); + return taskList; + } taskList .add(new TablesSyncTask(schemaName, logicalTableNames, enablePreemptiveMdl, initWait, interval, TimeUnit.MILLISECONDS)); - taskList.add(alterTableGroupRefreshTableGroupMetaTask); + if (hasColumnar) { + // mark after refresh meta + CdcColumnarTableGroupDdlMark cdcColumnarTableGroupDdlMark = + new CdcColumnarTableGroupDdlMark(tableGroupName, schemaName, columnarTables, versionId); + taskList.add(cdcColumnarTableGroupDdlMark); + // wait until alter partition success + boolean skipTask = + executionContext.skipDdlTasks().contains(WaitColumnarTableAlterPartitionTask.class.getSimpleName()); + WaitColumnarTableAlterPartitionTask waitColumnarTableAlterPartitionTask = + new WaitColumnarTableAlterPartitionTask(schemaName, columnarTables, skipTask); + taskList.add(waitColumnarTableAlterPartitionTask); + } taskList.addAll(synTableGroupTasks); DdlTask updateTablesVersionTask = new UpdateTablesVersionTask(schemaName, logicalTableNames); taskList.add(updateTablesVersionTask); @@ -385,7 +421,7 @@ public static List bringUpAlterTableChangeTopology(String schemaName, alterTableRefreshMetaTask = new AlterTableSetTableGroupRefreshMetaTask(schemaName, targetTableGroupName, partitionInfo.getTableGroupId(), - tableName); + tableName, DEFAULT_DDL_VERSION_ID); } else if (complexTaskType == ComplexTaskMetaManager.ComplexTaskType.SPLIT_HOT_VALUE || complexTaskType == ComplexTaskMetaManager.ComplexTaskType.EXTRACT_PARTITION || complexTaskType == ComplexTaskMetaManager.ComplexTaskType.SPLIT_PARTITION || @@ -626,6 +662,7 @@ public static List moveTableTasks(String schemaName, public static DdlTask CreateDropUselessPhyTableTask(String schemaName, String logicalTableName, Map> sourceTables, + Map> targetTables, ExecutionContext executionContext) { PartitionInfo partitionInfo = @@ -650,7 +687,19 @@ public static DdlTask CreateDropUselessPhyTableTask(String schemaName, String lo PhysicalPlanData physicalPlanData = DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, physicalPlans, executionContext); - return new DropTablePhyDdlTask(schemaName, physicalPlanData); + return new DropTablePhyDdlWithCheckTask(schemaName, physicalPlanData, targetTables); } + public static boolean hasColumnarTable(TableGroupConfig tableGroupConfig, List columnarTables, + ExecutionContext executionContext, String schemaName) { + boolean hasColumnar = false; + for (String logicalTable : tableGroupConfig.getAllTables()) { + TableMeta tableMeta = executionContext.getSchemaManager(schemaName).getTable(logicalTable); + if (tableMeta.isColumnar()) { + hasColumnar = true; + columnarTables.add(logicalTable); + } + } + return hasColumnar; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreateIndexJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreateIndexJobFactory.java index 6f5e9b7bf..13f5c70d6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreateIndexJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreateIndexJobFactory.java @@ -36,6 +36,7 @@ import com.google.common.collect.Lists; import org.apache.calcite.rel.core.DDL; import org.apache.calcite.sql.SqlNode; +import org.apache.commons.collections.CollectionUtils; import java.util.ArrayList; import java.util.List; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreatePartitionTableJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreatePartitionTableJobFactory.java index 9b64b5448..e6b200b1e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreatePartitionTableJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreatePartitionTableJobFactory.java @@ -49,14 +49,18 @@ import com.alibaba.polardbx.gms.tablegroup.TableGroupRecord; import com.alibaba.polardbx.gms.util.TableGroupNameUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.CreateTablePreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.LikeTableInfo; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.common.LocalPartitionDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; import com.alibaba.polardbx.optimizer.utils.RelUtils; import com.alibaba.polardbx.statistics.SQLRecorderLogger; import com.google.common.collect.Lists; +import org.apache.calcite.sql.SqlNode; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -243,12 +247,14 @@ protected ExecutableDdlJob doCreate() { LocalPartitionDefinitionInfo localPartitionDefinitionInfo = preparedData.getLocalPartitionDefinitionInfo(); boolean autoCreateTg = executionContext.getParamManager().getBoolean(ConnectionParams.ALLOW_AUTO_CREATE_TABLEGROUP); + TtlDefinitionInfo ttlDefinitionInfo = preparedData.getTtlDefinitionInfo(); CreateTableAddTablesPartitionInfoMetaTask addPartitionInfoTask = new CreateTableAddTablesPartitionInfoMetaTask(schemaName, logicalTableName, physicalPlanData.isTemporary(), - physicalPlanData.getTableGroupConfig(), localPartitionDefinitionInfo, null, null, - joinGroup, false, preparedData.isWithImplicitTableGroup(), autoCreateTg); + physicalPlanData.getTableGroupConfig(), localPartitionDefinitionInfo, ttlDefinitionInfo, null, + preparedData.isWithImplicitTableGroup(), false, null, + joinGroup, false, autoCreateTg); CreateTablePhyDdlTask phyDdlTask = new CreateTablePhyDdlTask(schemaName, logicalTableName, physicalPlanData); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreatePartitionTableWithGsiJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreatePartitionTableWithGsiJobFactory.java index 74cf39135..064f85831 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreatePartitionTableWithGsiJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreatePartitionTableWithGsiJobFactory.java @@ -17,16 +17,24 @@ package com.alibaba.polardbx.executor.ddl.job.factory; import com.alibaba.polardbx.common.ColumnarTableOptions; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.ColumnarOptions; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.executor.ddl.job.builder.gsi.CreatePartitionTableWithGsiBuilder; import com.alibaba.polardbx.executor.ddl.job.converter.DdlJobDataConverter; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.factory.gsi.CreatePartitionGsiJobFactory; import com.alibaba.polardbx.executor.ddl.job.factory.gsi.columnar.CreateColumnarIndexJobFactory; +import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateViewAddMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateViewSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.InsertIntoTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcDdlMarkTask; import com.alibaba.polardbx.executor.ddl.job.task.columnar.CciSchemaEvolutionTask; import com.alibaba.polardbx.executor.ddl.job.task.columnar.WaitColumnarTableCreationTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.GsiStatisticsInfoSyncTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlTaskSqlBuilder; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlExceptionAction; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; @@ -36,11 +44,19 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.wrapper.ExecutableDdlJob4CreatePartitionTable; import com.alibaba.polardbx.executor.ddl.newengine.job.wrapper.ExecutableDdlJob4CreateSelect; import com.alibaba.polardbx.executor.sync.GsiStatisticsSyncAction; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.PhyDdlTableOperation; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.LikeTableInfo; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.CreateGlobalIndexPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.CreateTableWithGsiPreparedData; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlMetaValidationUtil; +import com.alibaba.polardbx.optimizer.view.SystemTableView; +import com.alibaba.polardbx.optimizer.view.ViewManager; import org.apache.calcite.rel.core.DDL; import org.apache.calcite.sql.SqlCreateTable; import org.apache.calcite.sql.SqlIdentifier; @@ -73,6 +89,7 @@ public class CreatePartitionTableWithGsiJobFactory extends DdlJobFactory { Map>> primaryTableTopology; List primaryTablePhysicalPlans; Map> indexTablePhysicalPlansMap; + private CreatePartitionTableWithGsiBuilder createPartitionTableWithGsiBuilder; private final String schemaName; private final String primaryTableName; @@ -97,8 +114,8 @@ public CreatePartitionTableWithGsiJobFactory(@Deprecated DDL ddl, CreatePartitionTableWithGsiBuilder createTableWithGsiBuilder = new CreatePartitionTableWithGsiBuilder(ddl, preparedData, executionContext); - createTableWithGsiBuilder.build(); + this.createPartitionTableWithGsiBuilder = createTableWithGsiBuilder; Map>> primaryTableTopology = createTableWithGsiBuilder.getPrimaryTableTopology(); List primaryTablePhysicalPlans = createTableWithGsiBuilder.getPrimaryTablePhysicalPlans(); @@ -117,6 +134,49 @@ public CreatePartitionTableWithGsiJobFactory(@Deprecated DDL ddl, @Override protected void validate() { + /** + * Check if the archive table name already exists if need creating archive table and its cci + */ + + if (preparedData.getPrimaryTablePreparedData().getTtlDefinitionInfo() != null) { + TtlDefinitionInfo ttlDefinitionInfo = preparedData.getPrimaryTablePreparedData().getTtlDefinitionInfo(); + String ttlTableSchema = ttlDefinitionInfo.getTtlInfoRecord().getTableSchema(); + String ttlTableName = ttlDefinitionInfo.getTtlInfoRecord().getTableName(); + String archiveTableName = ttlDefinitionInfo.getArchiveTableName(); + String archiveTableSchema = ttlDefinitionInfo.getArchiveTableSchema(); + + if (ttlDefinitionInfo.needPerformExpiredDataArchivingByCci()) { + boolean foundTargetCciName = false; + String tarArcCciIdxName = null; + String arcTmpName = ttlDefinitionInfo.getTmpTableName().toLowerCase(); + Set allIndexTableNameSet = preparedData.getIndexTablePreparedDataMap().keySet(); + for (String idxTblName : allIndexTableNameSet) { + if (idxTblName.toLowerCase().startsWith(arcTmpName)) { + foundTargetCciName = true; + tarArcCciIdxName = idxTblName; + break; + } + } + if (foundTargetCciName) { + CreateGlobalIndexPreparedData gsiPrepData = + preparedData.getIndexTablePreparedDataMap().get(tarArcCciIdxName); + if (gsiPrepData != null && gsiPrepData.isColumnarIndex()) { + ViewManager viewManager = OptimizerContext.getContext(archiveTableSchema).getViewManager(); + if (viewManager != null) { + SystemTableView.Row viewInfo = viewManager.select(archiveTableName); + if (viewInfo != null) { +// throw new TddlRuntimeException(ErrorCode.ERR_TTL, String.format( +// "Failed to create table `%s`.`%s` because the specifying archive table '%s'.'%s' of ttl definition already exists", +// ttlTableSchema, ttlTableName, +// archiveTableSchema, archiveTableName)); + } + } + } + } + + } + + } } @Override @@ -146,7 +206,7 @@ protected ExecutableDdlJob doCreate() { } ExecutableDdlJob4CreatePartitionTable createTableJob = (ExecutableDdlJob4CreatePartitionTable) thisParentJob; - ; + createTableJob.removeTaskRelationship( createTableJob.getCreateTableAddTablesMetaTask(), createTableJob.getCdcDdlMarkTask() @@ -201,6 +261,7 @@ protected ExecutableDdlJob doCreate() { indexPreparedData.getDdlVersionId())); // TODO is CreateGsiPreCheckTask necessary ? + } else { // Global secondary index ExecutableDdlJob thisJob = @@ -252,6 +313,48 @@ protected ExecutableDdlJob doCreate() { result.addTaskRelationship(last, createTableJob.getCreateTableShowTableMetaTask()); } + if (preparedData.getPrimaryTablePreparedData().getTtlDefinitionInfo() != null) { + TtlDefinitionInfo ttlDefinitionInfo = preparedData.getPrimaryTablePreparedData().getTtlDefinitionInfo(); + + if (ttlDefinitionInfo.needPerformExpiredDataArchivingByCci()) { + boolean foundTargetIdxName = false; + String arcTmpName = ttlDefinitionInfo.getTmpTableName().toLowerCase(); + Set allIndexTableNameSet = preparedData.getIndexTablePreparedDataMap().keySet(); + for (String idxTblName : allIndexTableNameSet) { + if (idxTblName.toLowerCase().startsWith(arcTmpName)) { + foundTargetIdxName = true; + break; + } + } + if (foundTargetIdxName) { + TableMeta primTblMeta = preparedData.getPrimaryTablePreparedData().getTableMeta(); + String ttlTblSchema = ttlDefinitionInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlDefinitionInfo.getTtlInfoRecord().getTableName(); + String cciName = ttlDefinitionInfo.getTtlInfoRecord().getArcTmpTblName(); + String arcTblName = ttlDefinitionInfo.getArchiveTableName(); + String viewName = arcTblName; + List colMetaList = new ArrayList<>(); + colMetaList.addAll(primTblMeta.getAllColumns()); + String viewDefinition = + TtlTaskSqlBuilder.buildSqlForFullScanArcTbl(ttlTblSchema, ttlTblName, cciName, colMetaList); + CreateViewAddMetaTask createViewAddMetaTask = + new CreateViewAddMetaTask(ttlTblSchema, viewName, false, null, viewDefinition, null, null); + CreateViewSyncTask createViewSyncTask = new CreateViewSyncTask(ttlTblSchema, viewName); + + List tailNodes = + result.getAllZeroOutDegreeVertexes().stream().map(o -> o.getObject()).collect( + Collectors.toList()); + result.addTask(createViewAddMetaTask); + result.addTask(createViewSyncTask); + result.addTaskRelationship(createViewAddMetaTask, createViewSyncTask); + for (int i = 0; i < tailNodes.size(); i++) { + DdlTask tailTask = tailNodes.get(i); + result.addTaskRelationship(tailTask, createViewAddMetaTask); + } + } + } + } + if (selectSql != null) { InsertIntoTask insertIntoTask = new InsertIntoTask(schemaName, primaryTableName, selectSql, null, 0); @@ -265,16 +368,22 @@ protected ExecutableDdlJob doCreate() { insertIntoTask.setExceptionAction(DdlExceptionAction.ROLLBACK); return ans; } + return result; } private Map buildColumnarOptions(SqlIndexDefinition indexDefinition) { - Map options = new HashMap<>(); - if (indexDefinition != null && CollectionUtils.isNotEmpty(indexDefinition.getDictColumns())) { - String columns = indexDefinition.getDictColumns().stream() - .map(sqlIndexColumnName -> SqlIdentifier.surroundWithBacktick(sqlIndexColumnName.getColumnNameStr())) + if (indexDefinition == null) { + return new HashMap<>(); + } + Map options = indexDefinition.getColumnarOptions(); + // Normalize dict columns. + String dictColumnStr = options.get(ColumnarOptions.DICTIONARY_COLUMNS); + if (null != dictColumnStr) { + dictColumnStr = SQLUtils.splitNamesByComma(dictColumnStr.toLowerCase()).stream() + .map(SqlIdentifier::surroundWithBacktick) .collect(Collectors.joining(",")); - options.put(ColumnarTableOptions.DICTIONARY_COLUMNS, columns); + options.put(ColumnarOptions.DICTIONARY_COLUMNS, dictColumnStr); } return options; } @@ -286,9 +395,12 @@ private void updateOriginalDdlSql(CdcDdlMarkTask cdcDdlMarkTask) { // Call SqlCreateTable.unparse(SqlWriter writer, int leftPrec, int rightPrec) will get create table // statement with cci name replaced (suffix added). // For GDN use, we need cci name without suffix + SqlCreateTable.PrepareSqlStringOptions options = new SqlCreateTable.PrepareSqlStringOptions(); + options.setTtlDefinitionAllowed(true); final String normalizedOriginalDdl = this.normalizedOriginalDdl // .toSqlString(MysqlSqlDialect.DEFAULT, false) - .toString(); + .toSqlStringForCdc(options); + cdcDdlMarkTask.setNormalizedOriginalDdl(normalizedOriginalDdl); } catch (Exception ignored) { logger.error( @@ -335,4 +447,8 @@ protected void sharedResources(Set resources) { public void setSelectSql(String selectSql) { this.selectSql = selectSql; } + + public CreatePartitionTableWithGsiBuilder getCreatePartitionTableWithGsiBuilder() { + return createPartitionTableWithGsiBuilder; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreateViewJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreateViewJobFactory.java index 8d53426da..5129650ba 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreateViewJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/CreateViewJobFactory.java @@ -25,6 +25,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; +import com.alibaba.polardbx.executor.ddl.newengine.job.wrapper.ExecutableDdlJob4CreateView; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.dialect.DbType; import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan; @@ -91,9 +92,15 @@ protected ExecutableDdlJob doCreate() { DdlTask cdcMarkTask = new CdcCreateViewMarkTask(schemaName, viewName, isAlter); DdlTask syncTask = new CreateViewSyncTask(schemaName, viewName); - ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); - executableDdlJob.addSequentialTasks(Lists.newArrayList(validateTask, addMetaTask, cdcMarkTask, syncTask)); - return executableDdlJob; + ExecutableDdlJob4CreateView executableDdlJob4CreateView = new ExecutableDdlJob4CreateView(); + executableDdlJob4CreateView.setValidateCreateViewTask((ValidateCreateViewTask) validateTask); + executableDdlJob4CreateView.setCreateViewAddMetaTask((CreateViewAddMetaTask) addMetaTask); + executableDdlJob4CreateView.setCdcCreateViewMarkTask((CdcCreateViewMarkTask) cdcMarkTask); + executableDdlJob4CreateView.setCreateViewSyncTask((CreateViewSyncTask) syncTask); + executableDdlJob4CreateView.addSequentialTasks( + Lists.newArrayList(validateTask, addMetaTask, cdcMarkTask, syncTask)); + + return executableDdlJob4CreateView; } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/DropIndexJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/DropIndexJobFactory.java index 5778287c3..c55afe644 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/DropIndexJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/DropIndexJobFactory.java @@ -36,6 +36,7 @@ import com.google.common.collect.Lists; import org.apache.calcite.rel.core.DDL; import org.apache.calcite.sql.SqlNode; +import org.apache.commons.collections.CollectionUtils; import java.util.ArrayList; import java.util.List; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/DropPartitionTableWithGsiJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/DropPartitionTableWithGsiJobFactory.java index 93245a016..93b3d5c49 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/DropPartitionTableWithGsiJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/DropPartitionTableWithGsiJobFactory.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.executor.ddl.job.factory; +import com.alibaba.polardbx.common.utils.CaseInsensitive; import com.alibaba.polardbx.executor.ddl.job.builder.gsi.DropPartitionTableWithGsiBuilder; import com.alibaba.polardbx.executor.ddl.job.builder.gsi.DropTableWithGsiBuilder; import com.alibaba.polardbx.executor.ddl.job.converter.DdlJobDataConverter; @@ -23,10 +24,12 @@ import com.alibaba.polardbx.executor.ddl.job.factory.gsi.DropPartitionGsiJobFactory; import com.alibaba.polardbx.executor.ddl.job.factory.gsi.columnar.DropColumnarIndexJobFactory; import com.alibaba.polardbx.executor.ddl.job.factory.util.FactoryUtils; +import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.DropPartitionTableWithGsiValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.GsiStatisticsInfoSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlTaskSqlBuilder; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; @@ -35,10 +38,13 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.wrapper.ExecutableDdlJob4DropPartitionTable; import com.alibaba.polardbx.executor.sync.GsiStatisticsSyncAction; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.PhyDdlTableOperation; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.DropGlobalIndexPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.DropTableWithGsiPreparedData; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; import org.apache.calcite.rel.core.DDL; import java.util.ArrayList; @@ -46,6 +52,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeSet; /** * @author guxu @@ -117,12 +124,14 @@ protected ExecutableDdlJob doCreate() { ValidateTableVersionTask validateTableVersionTask = new ValidateTableVersionTask(preparedData.getPrimaryTablePreparedData().getSchemaName(), tableVersions); + boolean foundColumnarIndex = false; Map gsiPreparedDataMap = preparedData.getIndexTablePreparedDataMap(); for (Map.Entry entry : gsiPreparedDataMap.entrySet()) { final DropGlobalIndexPreparedData gsiPreparedData = entry.getValue(); final String indexTableName = gsiPreparedData.getIndexTableName(); if (entry.getValue().isColumnar()) { + foundColumnarIndex = true; // columnar index will be destroyed automatically ExecutableDdlJob4DropColumnarIndex dropCciJob = (ExecutableDdlJob4DropColumnarIndex) DropColumnarIndexJobFactory.create(gsiPreparedData, executionContext, true, false); @@ -191,6 +200,26 @@ protected ExecutableDdlJob doCreate() { result.addTask(tableGroupValidateTask); result.addTaskRelationship(tableGroupValidateTask, validateTableVersionTask); + boolean dropTtlTblWithArcCci = + TtlUtil.checkIfDropTtlTableWithCciArcTblView(this.schemaName, this.primaryTableName, this.executionContext); + if (dropTtlTblWithArcCci) { + TableMeta ttlTblMeta = executionContext.getSchemaManager(this.schemaName).getTable(this.primaryTableName); + TtlDefinitionInfo ttlInfo = ttlTblMeta.getTtlDefinitionInfo(); + if (ttlInfo != null && ttlInfo.needPerformExpiredDataArchivingByCci()) { + String arcTblSchema = ttlInfo.getArchiveTableSchema(); + String arcTblName = ttlInfo.getArchiveTableName(); + String dropViewSqlForArcTbl = + TtlTaskSqlBuilder.buildDropViewSqlFroArcTbl(arcTblSchema, arcTblName, ttlInfo); + SubJobTask dropViewSubJobTask = new SubJobTask(arcTblSchema, dropViewSqlForArcTbl, ""); + dropViewSubJobTask.setParentAcquireResource(true); + Set viewNames = new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + viewNames.add(arcTblName); + result.addExcludeResources(viewNames); + result.addTask(dropViewSubJobTask); + + } + } + // result.setMaxParallelism(gsiPreparedDataMap.size() + 1); return result; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/InsertOverwriteJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/InsertOverwriteJobFactory.java index 174f519b1..43c7de058 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/InsertOverwriteJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/InsertOverwriteJobFactory.java @@ -16,12 +16,12 @@ package com.alibaba.polardbx.executor.ddl.job.factory; -import com.alibaba.polardbx.common.ddl.foreignkey.ForeignKeyData; import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.executor.ddl.job.factory.gsi.TruncateTableWithGsiJobFactory; import com.alibaba.polardbx.executor.ddl.job.factory.util.FactoryUtils; import com.alibaba.polardbx.executor.ddl.job.task.basic.LogicalInsertTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcTruncateTableWithGsiMarkTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.TruncateColumnarTableTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.TruncateCutOverTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.TruncateSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; @@ -109,6 +109,9 @@ protected ExecutableDdlJob doCreate() { result.appendJob2(validateJob); result.appendJob2(createTmpTableJob); result.appendJob2(insertJob); + if (preparedData.isHasColumnarIndex()) { + result.appendTask(new TruncateColumnarTableTask(schemaName, logicalTableName, preparedData.getVersionId())); + } result.appendJob2(cutOverJob); result.appendJob2(dropTmpTableJob); @@ -127,7 +130,7 @@ protected ExecutableDdlJob doCreate() { private ExecutableDdlJob generateCutOverJob() { ExecutableDdlJob cutOverJob = new ExecutableDdlJob(); CdcTruncateTableWithGsiMarkTask cdcTask = - new CdcTruncateTableWithGsiMarkTask(schemaName, logicalTableName, tmpPrimaryTableName); + new CdcTruncateTableWithGsiMarkTask(schemaName, logicalTableName, tmpPrimaryTableName, preparedData.getVersionId()); TruncateCutOverTask cutOverTask = new TruncateCutOverTask(schemaName, logicalTableName, tmpIndexTableMap, tmpPrimaryTableName); TruncateSyncTask syncTask = diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseChangeSetJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseChangeSetJobFactory.java index 5518f8e0c..114f1945d 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseChangeSetJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseChangeSetJobFactory.java @@ -17,13 +17,14 @@ package com.alibaba.polardbx.executor.ddl.job.factory; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.changeset.ChangeSetManager; import com.alibaba.polardbx.executor.ddl.job.converter.DdlJobDataConverter; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.task.backfill.MoveTableBackFillTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.CloneTableDataFileTask; -import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.CreatePhyTableWithRollbackCheckTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.DiscardTableSpaceDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.ImportTableSpaceDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.MoveDatabaseAddMetaTask; @@ -37,6 +38,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.ddl.util.ChangeSetUtils; import com.alibaba.polardbx.executor.physicalbackfill.PhysicalBackfillUtils; +import com.alibaba.polardbx.executor.scaleout.ScaleOutUtils; import com.alibaba.polardbx.gms.topology.DbTopologyManager; import com.alibaba.polardbx.gms.util.GroupInfoUtil; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; @@ -45,6 +47,7 @@ import com.alibaba.polardbx.optimizer.core.rel.PhyDdlTableOperation; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.MoveDatabaseItemPreparedData; import com.google.common.collect.ImmutableList; +import com.mysql.cj.polarx.protobuf.PolarxPhysicalBackfill; import org.apache.calcite.rel.core.DDL; import java.util.ArrayList; @@ -119,17 +122,14 @@ protected ExecutableDdlJob doCreate() { PhysicalPlanData physicalPlanData = DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, phyDdlTableOperations, executionContext); DdlTask phyDdlTask = - new CreateTablePhyDdlTask(schemaName, physicalPlanData.getLogicalTableName(), physicalPlanData); + new CreatePhyTableWithRollbackCheckTask(schemaName, physicalPlanData.getLogicalTableName(), + physicalPlanData, sourceTableTopology); taskList.add(phyDdlTask); MoveTableBackFillTask moveTableBackFillTask = null; + List discardTableSpaceTasks = null; if (usePhysicalBackfill) { - physicalPlanData = - DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, discardTableSpaceOperations, - executionContext); - phyDdlTask = - new DiscardTableSpaceDdlTask(schemaName, physicalPlanData.getLogicalTableName(), - physicalPlanData); - taskList.add(phyDdlTask); + discardTableSpaceTasks = ScaleOutUtils.generateDiscardTableSpaceDdlTask(schemaName, tableTopology, + discardTableSpaceOperations, executionContext); } else { moveTableBackFillTask = new MoveTableBackFillTask(schemaName, tableName, sourceTableTopology, targetTableTopology, @@ -167,12 +167,6 @@ protected ExecutableDdlJob doCreate() { final boolean useApplyOpt = changeSetApplyFinishTask != null && executionContext.getParamManager().getBoolean(CHANGE_SET_APPLY_OPTIMIZATION); - MoveTableCheckTask moveTableCheckTask = - new MoveTableCheckTask(schemaName, tableName, preparedData.getSourceTargetGroupMap(), sourceTableTopology, - targetTableTopology, useApplyOpt, relatedTables); - MoveTableCheckTask moveTableCheckTwiceTask = - new MoveTableCheckTask(schemaName, tableName, preparedData.getSourceTargetGroupMap(), sourceTableTopology, - targetTableTopology, false, relatedTables); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.SCALE_OUT_FINAL_TABLE_STATUS_DEBUG); @@ -187,6 +181,7 @@ protected ExecutableDdlJob doCreate() { boolean healthyCheck = executionContext.getParamManager().getBoolean(ConnectionParams.PHYSICAL_BACKFILL_STORAGE_HEALTHY_CHECK); + long totalDataSize = 0l; if (usePhysicalBackfill) { for (Map.Entry> entry : sourceTableTopology.entrySet()) { String srcGroupName = entry.getKey(); @@ -220,16 +215,43 @@ protected ExecutableDdlJob doCreate() { .getLong(ConnectionParams.PHYSICAL_BACKFILL_MIN_SUCCESS_BATCH_UPDATE); final long parallelism = executionContext.getParamManager().getLong(ConnectionParams.PHYSICAL_BACKFILL_PARALLELISM); + final long ioAdvise = + executionContext.getParamManager() + .getLong(ConnectionParams.PHYSICAL_BACKFILL_IMPORT_TABLESPACE_IO_ADVISE); for (String phyTb : entry.getValue()) { List phyPartNames = PhysicalBackfillUtils.getPhysicalPartitionNames(schemaName, srcDbAndGroup.getValue(), srcDbAndGroup.getKey(), phyTb); + + Pair srcDnUserAndPasswd = storageInstAndUserInfos.computeIfAbsent(sourceStorageId, + key -> PhysicalBackfillUtils.getUserPasswd(sourceStorageId)); + + Pair userAndPasswd = storageInstAndUserInfos.computeIfAbsent(targetStorageId, + key -> PhysicalBackfillUtils.getUserPasswd(targetStorageId)); + + boolean hasNoPhyPart = GeneralUtil.isEmpty(phyPartNames); + List temPhyPartNames = new ArrayList<>(); + if (hasNoPhyPart) { + temPhyPartNames.add(""); + } else { + temPhyPartNames.addAll(phyPartNames); + } + PolarxPhysicalBackfill.GetFileInfoOperator fileInfoOperator = + PhysicalBackfillUtils.checkFileExistence(srcDnUserAndPasswd, srcDbAndGroup.getKey(), + phyTb.toLowerCase(), + temPhyPartNames, + true, PhysicalBackfillUtils.getMySQLLeaderIpAndPort(sourceStorageId)); + long dataSize = 0l; + for (PolarxPhysicalBackfill.FileInfo fileInfo : fileInfoOperator.getTableInfo().getFileInfoList()) { + dataSize += fileInfo.getDataSize(); + } + CloneTableDataFileTask cloneTableDataFileTask = new CloneTableDataFileTask(schemaName, tableName, srcDbAndGroup, tarDbAndGroup, phyTb, phyPartNames, sourceStorageId, sourceHostIpAndPort, targetHostsIpAndPort, batchSize, - tableMeta.isEncryption()); + dataSize, tableMeta.isEncryption()); cloneTableDataFileTask.setTaskId(ID_GENERATOR.nextId()); List importTableSpaceTasks = new ArrayList<>(); @@ -238,22 +260,23 @@ protected ExecutableDdlJob doCreate() { new PhysicalBackfillTask(schemaName, cloneTableDataFileTask.getTaskId(), tableName, phyTb, phyPartNames, srcTarGroup, - Pair.of(sourceStorageId, targetStorageId), storageInstAndUserInfos, batchSize, parallelism, + Pair.of(sourceStorageId, targetStorageId), + storageInstAndUserInfos, + batchSize, + dataSize, + parallelism, minUpdateBatch, waitLsn, tableMeta.isEncryption()); - storageInstAndUserInfos.computeIfAbsent(sourceStorageId, - key -> PhysicalBackfillUtils.getUserPasswd(sourceStorageId)); - - Pair userAndPasswd = storageInstAndUserInfos.computeIfAbsent(targetStorageId, - key -> PhysicalBackfillUtils.getUserPasswd(targetStorageId)); - for (Pair hostIpAndPort : targetHostsIpAndPort) { ImportTableSpaceDdlTask importTableSpaceDdlTask = new ImportTableSpaceDdlTask(schemaName, tableName, tarDbAndGroup.getKey(), phyTb, hostIpAndPort, - userAndPasswd); + userAndPasswd, + targetStorageId, + dataSize, + ioAdvise); importTableSpaceTasks.add(importTableSpaceDdlTask); } List tasks = new ArrayList<>(importTableSpaceTasks.size() + 2); @@ -261,9 +284,18 @@ protected ExecutableDdlJob doCreate() { tasks.add(physicalBackfillTask); tasks.addAll(importTableSpaceTasks); physicalyTaskPipeLine.add(tasks); + totalDataSize += dataSize; } } + MoveTableCheckTask moveTableCheckTask = + new MoveTableCheckTask(schemaName, tableName, preparedData.getSourceTargetGroupMap(), + sourceTableTopology, + targetTableTopology, useApplyOpt, relatedTables, totalDataSize); + MoveTableCheckTask moveTableCheckTwiceTask = + new MoveTableCheckTask(schemaName, tableName, preparedData.getSourceTargetGroupMap(), + sourceTableTopology, + targetTableTopology, false, relatedTables, totalDataSize); moveDatabaseTasks = ChangeSetUtils.genChangeSetOnlineSchemaChangeTasks( schemaName, tableName, relatedTables, @@ -277,6 +309,14 @@ protected ExecutableDdlJob doCreate() { backfillTaskEdgeNodes, executionContext); } else { + MoveTableCheckTask moveTableCheckTask = + new MoveTableCheckTask(schemaName, tableName, preparedData.getSourceTargetGroupMap(), + sourceTableTopology, + targetTableTopology, useApplyOpt, relatedTables, totalDataSize); + MoveTableCheckTask moveTableCheckTwiceTask = + new MoveTableCheckTask(schemaName, tableName, preparedData.getSourceTargetGroupMap(), + sourceTableTopology, + targetTableTopology, false, relatedTables, totalDataSize); moveDatabaseTasks = ChangeSetUtils.genChangeSetOnlineSchemaChangeTasks( schemaName, tableName, relatedTables, @@ -296,6 +336,14 @@ protected ExecutableDdlJob doCreate() { taskList.addAll(moveDatabaseTasks); executableDdlJob.addSequentialTasks(taskList); + if (usePhysicalBackfill) { + executableDdlJob.removeTaskRelationship(phyDdlTask, moveDatabaseTasks.get(0)); + for (DdlTask discardTask : discardTableSpaceTasks) { + executableDdlJob.addTaskRelationship(phyDdlTask, discardTask); + executableDdlJob.addTaskRelationship(discardTask, moveDatabaseTasks.get(0)); + } + } + //todo(ziyang) cdc ddl mark task if (changeSetApplyExecutorInitTask != null) { executableDdlJob.labelAsHead(changeSetApplyExecutorInitTask); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseJobFactory.java index d301c79b6..46be09681 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseJobFactory.java @@ -27,6 +27,7 @@ import com.alibaba.polardbx.executor.ddl.job.builder.MoveDatabaseBuilder; import com.alibaba.polardbx.executor.ddl.job.task.BaseValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.CostEstimableDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.AnalyzePhyTableTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.DdlBackfillCostRecordTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.ImportTableSpaceDdlNormalTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.InitNewStorageInstTask; @@ -140,7 +141,7 @@ public void constructSubTasks(ExecutableDdlJob executableDdlJob, tarGroupAndStorageIds.put(srcTarGroup.getValue(), targetStorageId); } } - int parallelism = ScaleOutUtils.getScaleoutTaskParallelism(executionContext); + int pipelineSize = ScaleOutUtils.getTaskPipelineSize(executionContext); Queue leavePipeLineQueue = new LinkedList<>(); for (Map.Entry>>> entry : tablesTopologyMap.entrySet()) { @@ -186,14 +187,16 @@ public void constructSubTasks(ExecutableDdlJob executableDdlJob, targetGroupAndStorageIdMap.put(preparedData.getSourceTargetGroupMap().get(groupName), preparedData.getGroupAndStorageInstId().get(groupName).getValue()); } - syncLsnTask = - new SyncLsnTask(schemaName, sourceGroupAndStorageIdMap, targetGroupAndStorageIdMap); - executableDdlJob.addTask(syncLsnTask); - syncLsnTaskAdded = true; + if (GeneralUtil.isNotEmpty(subTaskJobFactory.getPhysicalyTaskPipeLine())) { + syncLsnTask = + new SyncLsnTask(schemaName, sourceGroupAndStorageIdMap, targetGroupAndStorageIdMap); + executableDdlJob.addTask(syncLsnTask); + syncLsnTaskAdded = true; + } } for (List pipeLine : GeneralUtil.emptyIfNull(subTaskJobFactory.getPhysicalyTaskPipeLine())) { DdlTask parentLeaveNode; - if (leavePipeLineQueue.size() < parallelism) { + if (leavePipeLineQueue.size() < pipelineSize) { parentLeaveNode = syncLsnTask; } else { parentLeaveNode = leavePipeLineQueue.poll(); @@ -224,9 +227,13 @@ public void constructSubTasks(ExecutableDdlJob executableDdlJob, executableDdlJob.addTaskRelationship(pipeLine.get(i), importTableSpaceDdlNormalTask); } - executableDdlJob.addTaskRelationship(importTableSpaceDdlNormalTask, + + AnalyzePhyTableTask analyzePhyTableTask = new AnalyzePhyTableTask(schemaName, tarGroupKey, + phyTableName); + executableDdlJob.addTaskRelationship(importTableSpaceDdlNormalTask, analyzePhyTableTask); + executableDdlJob.addTaskRelationship(analyzePhyTableTask, subTaskJobFactory.getBackfillTaskEdgeNodes().get(1)); - leavePipeLineQueue.add(importTableSpaceDdlNormalTask); + leavePipeLineQueue.add(analyzePhyTableTask); } } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseSubTaskJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseSubTaskJobFactory.java index 46f7e9abd..7e757b9a6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseSubTaskJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/MoveDatabaseSubTaskJobFactory.java @@ -21,7 +21,7 @@ import com.alibaba.polardbx.executor.ddl.job.converter.DdlJobDataConverter; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.task.basic.AddLogicalForeignKeyTask; -import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.CreatePhyTableWithRollbackCheckTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.DropLogicalForeignKeyTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.MoveDatabaseAddMetaTask; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; @@ -104,7 +104,8 @@ protected ExecutableDdlJob doCreate() { PhysicalPlanData physicalPlanData = DdlJobDataConverter.convertToPhysicalPlanData(tableTopology, phyDdlTableOperations, executionContext); DdlTask phyDdlTask = - new CreateTablePhyDdlTask(schemaName, physicalPlanData.getLogicalTableName(), physicalPlanData); + new CreatePhyTableWithRollbackCheckTask(schemaName, physicalPlanData.getLogicalTableName(), + physicalPlanData, sourceTableTopology); taskList.add(phyDdlTask); final String finalStatus = diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RecycleOssTableJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RecycleOssTableJobFactory.java index 1b5c8962b..9cd8ffd63 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RecycleOssTableJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RecycleOssTableJobFactory.java @@ -23,6 +23,7 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.RenameTableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.RenameTableUpdateMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.RenameTableValidateTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.oss.UnBindingArchiveTableMetaDirectTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; @@ -32,6 +33,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.archive.CheckOSSArchiveUtil; +import com.alibaba.polardbx.optimizer.archive.TtlSourceInfo; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.google.common.collect.Lists; @@ -75,10 +77,19 @@ protected ExecutableDdlJob doCreate() { List tasks = Lists.newArrayList(); tasks.add(validateTask); - Optional> source = CheckOSSArchiveUtil.getTTLSource(schemaName, logicalTableName); +// Optional> source = CheckOSSArchiveUtil.getTTLSource(schemaName, logicalTableName); + Optional source = CheckOSSArchiveUtil.getTtlSourceInfo(schemaName, logicalTableName); source.ifPresent(x -> { - sourceSchemaName = x.getKey(); - sourceTableName = x.getValue(); + + boolean useRowLevelTtl = x.isUseRowLevelTtl(); + if (useRowLevelTtl) { + sourceSchemaName = x.getTtlInfoRecord().getTableSchema(); + sourceTableName = x.getTtlInfoRecord().getTableName(); + } else { + sourceSchemaName = x.getTableLocalPartitionRecord().getTableSchema(); + sourceTableName = x.getTableLocalPartitionRecord().getTableName(); + } + TableMeta tm = OptimizerContext.getContext(sourceSchemaName).getLatestSchemaManager().getTable(sourceTableName); @@ -90,11 +101,23 @@ protected ExecutableDdlJob doCreate() { // unbinding task DdlTask unBindingTask = new UnBindingArchiveTableMetaDirectTask(sourceSchemaName, sourceTableName, + x.isUseRowLevelTtl(), schemaName, logicalTableName); + TableSyncTask tableSyncTask = new TableSyncTask(sourceSchemaName, sourceTableName); + tasks.add(validateTableVersionTask); tasks.add(unBindingTask); tasks.add(tableSyncTask); + + if (useRowLevelTtl) { + String ttlTmpSchema = x.getTtlInfoRecord().getArcTmpTblSchema(); + String ttlTmpTbl = x.getTtlInfoRecord().getArcTmpTblName(); + String dropSql = String.format("DROP TABLE IF EXISTS `%s`.`%s`", ttlTmpSchema, ttlTmpTbl); + SubJobTask dropTtlTmpTblTask = new SubJobTask(ttlTmpSchema, dropSql, ""); + tasks.add(dropTtlTmpTblTask); + } + }); DdlTask addMetaTask = new RenameTableAddMetaTask(schemaName, logicalTableName, newLogicalTableName); DdlTask phyDdlTask = new RenameTablePhyDdlTask(schemaName, physicalPlanData); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RefreshDbTopologyFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RefreshDbTopologyFactory.java index a4d1171ed..3e6b5c111 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RefreshDbTopologyFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RefreshDbTopologyFactory.java @@ -114,7 +114,7 @@ protected ExecutableDdlJob doCreate() { )); List bringUpAlterTableGroupTasks = ComplexTaskFactory.bringUpAlterTableGroup(schemaName, tableGroupName, null, - taskType, executionContext); + taskType, preparedData.getDdlVersionId(), executionContext); executableDdlJob.addSequentialTasks(bringUpAlterTableGroupTasks); constructSubTasks(schemaName, executableDdlJob, addMetaTask, bringUpAlterTableGroupTasks, null); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RenameTableJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RenameTableJobFactory.java index cb75a53a7..d13720fe9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RenameTableJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RenameTableJobFactory.java @@ -29,7 +29,7 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.RenameTableValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcDdlMarkTask; -import com.alibaba.polardbx.executor.ddl.job.task.columnar.RenameColumnarTablesMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.RenameColumnarTableMetaTask; import com.alibaba.polardbx.executor.ddl.job.validator.GsiValidator; import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; @@ -98,9 +98,7 @@ protected ExecutableDdlJob doCreate() { SchemaManager schemaManager = executionContext.getSchemaManager(schemaName); TableMeta tableMeta = schemaManager.getTable(logicalTableName); - boolean withColumnar = - tableMeta.getGsiTableMetaBean() != null && tableMeta.getGsiTableMetaBean().indexMap != null - && tableMeta.getGsiTableMetaBean().indexMap.values().stream().anyMatch(m -> m.columnarIndex); + boolean withColumnar = tableMeta.withColumnar(); List taskList = new ArrayList<>(); taskList.add(validateTask); @@ -113,7 +111,7 @@ protected ExecutableDdlJob doCreate() { if (!Engine.isFileStore(engine) && !isGsi) { if (withColumnar) { DdlTask renameColumnarTask = - new RenameColumnarTablesMetaTask(schemaName, logicalTableName, newLogicalTableName, versionId); + new RenameColumnarTableMetaTask(schemaName, logicalTableName, newLogicalTableName, versionId); taskList.add(renameColumnarTask); } taskList.add(cdcDdlMarkTask); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RenameTablesJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RenameTablesJobFactory.java index c0658f900..90e312826 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RenameTablesJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/RenameTablesJobFactory.java @@ -25,6 +25,7 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.RenameTablesUpdateMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.RenameTablesValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableListDataIdSyncTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.RenameColumnarTablesMetaTask; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; @@ -45,13 +46,17 @@ public class RenameTablesJobFactory extends DdlJobFactory { private final String schemaName; private final RenameTablesPreparedData preparedData; private final ExecutionContext executionContext; + // each tableName has a versionId + private final List versionIds; public RenameTablesJobFactory(String schemaName, RenameTablesPreparedData preparedData, - ExecutionContext executionContext) { + ExecutionContext executionContext, + List versionIds) { this.schemaName = schemaName; this.preparedData = preparedData; this.executionContext = executionContext; + this.versionIds = versionIds; } @Override @@ -75,11 +80,13 @@ protected ExecutableDdlJob doCreate() { List newNames = preparedData.getToTableNames(); DdlTask validateTask = new RenameTablesValidateTask(schemaName, oldNames, newNames); RenameTablesUpdateMetaTask metaTask = new RenameTablesUpdateMetaTask(schemaName, oldNames, newNames); + RenameColumnarTablesMetaTask columnarTask = + new RenameColumnarTablesMetaTask(schemaName, oldNames, newNames, versionIds); RenameTablesCdcSyncTask cdcSyncTask = new RenameTablesCdcSyncTask(schemaName, preparedData.getDistinctNames(), enablePreemptiveMdl, initWait, interval, TimeUnit.MILLISECONDS, oldNames, newNames, preparedData.getCollate(), preparedData.getCdcMetas(), - preparedData.getNewTableTopologies()); + preparedData.getNewTableTopologies(), versionIds); RenameTablesUpdateDataIdTask dataIdTask = new RenameTablesUpdateDataIdTask(schemaName, oldNames, newNames); TableListDataIdSyncTask tableListDataIdSyncTask = new TableListDataIdSyncTask(schemaName, preparedData.getDistinctNames()); @@ -89,6 +96,7 @@ protected ExecutableDdlJob doCreate() { taskList.add(validateTask); taskList.add(tableListDataIdSyncTask0); taskList.add(metaTask); + taskList.add(columnarTask); // lock + cdc + sync + unlock taskList.add(cdcSyncTask); taskList.add(dataIdTask); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/TruncateTableJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/TruncateTableJobFactory.java index eef0f63d2..8e68797c4 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/TruncateTableJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/TruncateTableJobFactory.java @@ -17,9 +17,11 @@ package com.alibaba.polardbx.executor.ddl.job.factory; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.ddl.job.task.basic.ResetSequence4TruncateTableTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TruncateTablePhyDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TruncateTableValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcDdlMarkTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.TruncateColumnarTableTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; @@ -32,20 +34,23 @@ import java.util.Map; import java.util.Set; -import static com.alibaba.polardbx.common.cdc.ICdcManager.DEFAULT_DDL_VERSION_ID; - public class TruncateTableJobFactory extends DdlJobFactory { private final PhysicalPlanData physicalPlanData; private final String schemaName; private final String logicalTableName; private final long tableVersion; + private final long versionId; + private final boolean withCci; - public TruncateTableJobFactory(PhysicalPlanData physicalPlanData, long tableVersion) { + public TruncateTableJobFactory(PhysicalPlanData physicalPlanData, long tableVersion, long versionId, + boolean withCci) { this.physicalPlanData = physicalPlanData; this.schemaName = physicalPlanData.getSchemaName(); this.logicalTableName = physicalPlanData.getLogicalTableName(); this.tableVersion = tableVersion; + this.versionId = versionId; + this.withCci = withCci; } @Override @@ -64,15 +69,29 @@ protected ExecutableDdlJob doCreate() { DdlTask validateTask = new TruncateTableValidateTask(schemaName, logicalTableName, tableGroupConfig); DdlTask phyDdlTask = new TruncateTablePhyDdlTask(schemaName, physicalPlanData); - DdlTask cdcDdlMarkTask = new CdcDdlMarkTask(schemaName, physicalPlanData, false, false, DEFAULT_DDL_VERSION_ID); + DdlTask resetSequenceTask = new ResetSequence4TruncateTableTask(schemaName, logicalTableName); + DdlTask truncateColumnarTableTask = new TruncateColumnarTableTask(schemaName, logicalTableName, versionId); + DdlTask cdcDdlMarkTask = new CdcDdlMarkTask(schemaName, physicalPlanData, false, false, versionId); ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); - executableDdlJob.addSequentialTasks(Lists.newArrayList( - validateTableVersionTask, - validateTask, - phyDdlTask.onExceptionTryRecoveryThenRollback(), - cdcDdlMarkTask - )); + executableDdlJob.addSequentialTasks( + !withCci ? + Lists.newArrayList( + validateTableVersionTask, + validateTask, + resetSequenceTask, + phyDdlTask.onExceptionTryRecoveryThenRollback(), + cdcDdlMarkTask + ) : + Lists.newArrayList( + validateTableVersionTask, + validateTask, + resetSequenceTask, + phyDdlTask.onExceptionTryRecoveryThenRollback(), + truncateColumnarTableTask, + cdcDdlMarkTask + ) + ); return executableDdlJob; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/AlterPartitionCountJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/AlterPartitionCountJobFactory.java index 07cd85566..e5efe4059 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/AlterPartitionCountJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/AlterPartitionCountJobFactory.java @@ -108,7 +108,7 @@ protected ExecutableDdlJob doCreate() { List createGsiJobs = new ArrayList<>(); globalIndexPrepareData.forEach((createGlobalIndexPreparedData, physicalPlanData) -> { CreateGsiJobFactory createGsiJobFactory = - CreateGsiJobFactory.create(createGlobalIndexPreparedData, physicalPlanData, executionContext); + CreateGsiJobFactory.create(createGlobalIndexPreparedData, physicalPlanData, null, executionContext); createGsiJobFactory.stayAtBackFill = true; createGsiJobs.add((ExecutableDdlJob4CreatePartitionGsi) createGsiJobFactory.create()); }); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/CreateGsiJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/CreateGsiJobFactory.java index f502f0857..d77bfe65e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/CreateGsiJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/CreateGsiJobFactory.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.ddl.foreignkey.ForeignKeyData; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.polardbx.executor.ddl.job.builder.DdlPhyPlanBuilder; import com.alibaba.polardbx.executor.ddl.job.builder.gsi.CreateGlobalIndexBuilder; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; @@ -26,6 +27,7 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateTableShowTableMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.factory.GsiTaskFactory; +import com.alibaba.polardbx.executor.ddl.job.task.gsi.AlterGsiAddLocalIndexTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.CreateGsiPhyDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.CreateGsiValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.GsiInsertIndexMetaTask; @@ -34,11 +36,9 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.ddl.newengine.job.wrapper.ExecutableDdlJob4CreateGsi; -import com.alibaba.polardbx.executor.ddl.util.ChangeSetUtils; import com.alibaba.polardbx.gms.metadb.table.IndexStatus; import com.alibaba.polardbx.gms.metadb.table.IndexVisibility; import com.alibaba.polardbx.gms.topology.DbInfoManager; -import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.CreateGlobalIndexPreparedData; @@ -76,6 +76,7 @@ public class CreateGsiJobFactory extends DdlJobFactory { protected final String indexComment; protected final String indexType; protected PhysicalPlanData physicalPlanData; + protected PhysicalPlanData physicalPlanDataForLocalIndex; protected final boolean clusteredIndex; protected final boolean hasTimestampColumnDefault; protected final Map specialDefaultValues; @@ -87,6 +88,8 @@ public class CreateGsiJobFactory extends DdlJobFactory { public boolean mirrorCopy = false; public boolean stayAtBackFill = false; public boolean buildBroadCast = false; + public boolean splitByPkRange = false; + public boolean splitByPartition = false; /** * Foreign key @@ -95,32 +98,38 @@ public class CreateGsiJobFactory extends DdlJobFactory { protected List addedForeignKeys; /** - * for alter table modify sharding key (repartition check) + * for online modify column checker */ - public Map virtualColumnMap = null; + public Map srcVirtualColumnMap = null; + public Map dstVirtualColumnMap = null; + public Map dstColumnNewDefinitions = null; /** * for online modify column (change column name), column map, oldName ----> newName */ - public Map backfillColumnMap = null; + public Map omcColumnMap = null; public List modifyStringColumns = null; public List addNewColumns = null; /** - * for online modify column, oldIndexName ----> newIndexName + * for online modify column, backfillSourceTable ----> newIndex */ - public String oldIndexName; + public String backfillSourceTableName; public SubJobTask rerunTask; private boolean visible; - private boolean repartition; + protected boolean gsiCdcMark = true; + + protected boolean removePartitioning = false; public CreateGsiJobFactory(CreateGlobalIndexPreparedData globalIndexPreparedData, PhysicalPlanData physicalPlanData, + PhysicalPlanData physicalPlanDataForLocalIndex, + Boolean create4CreateTableWithGsi, ExecutionContext executionContext) { this( globalIndexPreparedData.getSchemaName(), @@ -140,22 +149,27 @@ public CreateGsiJobFactory(CreateGlobalIndexPreparedData globalIndexPreparedData globalIndexPreparedData.getIndexTablePreparedData() != null ? globalIndexPreparedData.getIndexTablePreparedData().getSpecialDefaultValueFlags() : new TreeMap<>(String.CASE_INSENSITIVE_ORDER), + executionContext.getParamManager().getBoolean(ConnectionParams.GSI_BACKFILL_BY_PK_RANGE), + executionContext.getParamManager().getBoolean(ConnectionParams.GSI_BACKFILL_BY_PARTITION), physicalPlanData, + physicalPlanDataForLocalIndex, + create4CreateTableWithGsi, globalIndexPreparedData.getAddedForeignKeys(), executionContext ); this.visible = globalIndexPreparedData.isVisible(); - this.repartition = globalIndexPreparedData.isRepartition(); + this.gsiCdcMark = !globalIndexPreparedData.isRepartition(); } public static CreateGsiJobFactory create(CreateGlobalIndexPreparedData preparedData, PhysicalPlanData physicalPlanData, + PhysicalPlanData physicalPlanDataForLocalIndex, ExecutionContext ec) { final String schema = preparedData.getSchemaName(); return DbInfoManager.getInstance().isNewPartitionDb(schema) ? - new CreatePartitionGsiJobFactory(preparedData, physicalPlanData, ec) : - new CreateGsiJobFactory(preparedData, physicalPlanData, ec); + new CreatePartitionGsiJobFactory(preparedData, physicalPlanData, physicalPlanDataForLocalIndex, false, ec) : + new CreateGsiJobFactory(preparedData, physicalPlanData, physicalPlanDataForLocalIndex, false, ec); } protected CreateGsiJobFactory(String schemaName, @@ -170,7 +184,11 @@ protected CreateGsiJobFactory(String schemaName, boolean hasTimestampColumnDefault, Map specialDefaultValues, Map specialDefaultValueFlags, + boolean splitByPkRange, + boolean splitByPartition, PhysicalPlanData physicalPlanData, + PhysicalPlanData physicalPlanDataForLocalIndex, + Boolean create4CreateTableWithGsi, List addedForeignKeys, ExecutionContext executionContext) { this.schemaName = schemaName; @@ -182,12 +200,17 @@ protected CreateGsiJobFactory(String schemaName, this.indexComment = indexComment == null ? "" : indexComment; this.indexType = indexType; this.physicalPlanData = physicalPlanData; + this.physicalPlanDataForLocalIndex = physicalPlanDataForLocalIndex; this.clusteredIndex = clusteredIndex; this.hasTimestampColumnDefault = hasTimestampColumnDefault; this.specialDefaultValues = specialDefaultValues; this.specialDefaultValueFlags = specialDefaultValueFlags; this.executionContext = executionContext; this.addedForeignKeys = addedForeignKeys; + if (!unique && !create4CreateTableWithGsi) { + this.splitByPkRange = splitByPkRange; + } + this.splitByPartition = splitByPartition; } @Override @@ -199,15 +222,15 @@ protected void validate() { @Override protected ExecutableDdlJob doCreate() { CreateGsiValidateTask validateTask = - new CreateGsiValidateTask(schemaName, primaryTableName, indexTableName, null, null); + new CreateGsiValidateTask(schemaName, primaryTableName, indexTableName, null, null, removePartitioning, false); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.GSI_FINAL_STATUS_DEBUG); final boolean stayAtDeleteOnly = StringUtils.equalsIgnoreCase(DELETE_ONLY.name(), finalStatus); final boolean stayAtWriteOnly = StringUtils.equalsIgnoreCase(WRITE_ONLY.name(), finalStatus); - Map columnMapping = backfillColumnMap == null ? null : - backfillColumnMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); + Map columnMapping = omcColumnMap == null ? null : + omcColumnMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); List columns = columnAst2nameStr(this.columns); List coverings = columnAst2nameStr(this.coverings); @@ -217,13 +240,14 @@ protected ExecutableDdlJob doCreate() { bringUpGsi = GsiTaskFactory.addGlobalIndexTasksChangeSet( schemaName, primaryTableName, - oldIndexName, + backfillSourceTableName, indexTableName, stayAtDeleteOnly, stayAtWriteOnly, stayAtBackFill, - virtualColumnMap, - backfillColumnMap, + srcVirtualColumnMap, + dstVirtualColumnMap, + dstColumnNewDefinitions, modifyStringColumns, onlineModifyColumn, mirrorCopy, @@ -236,17 +260,18 @@ protected ExecutableDdlJob doCreate() { bringUpGsi = GsiTaskFactory.addGlobalIndexTasks( schemaName, primaryTableName, - oldIndexName, + backfillSourceTableName, indexTableName, stayAtDeleteOnly, stayAtWriteOnly, stayAtBackFill, - null, - null, + srcVirtualColumnMap, + dstVirtualColumnMap, + dstColumnNewDefinitions, modifyStringColumns, physicalPlanData, tableMeta, - repartition, + gsiCdcMark, onlineModifyColumn, mirrorCopy, executionContext.getOriginSql() @@ -322,6 +347,12 @@ protected ExecutableDdlJob doCreate() { taskList.add(addIndexMetaTask.onExceptionTryRecoveryThenRollback()); //3.2 gsi status: CREATING -> DELETE_ONLY -> WRITE_ONLY -> WRITE_REORG -> PUBLIC taskList.addAll(bringUpGsi); + if (physicalPlanDataForLocalIndex != null) { + AlterGsiAddLocalIndexTask alterGsiPhyTable = + new AlterGsiAddLocalIndexTask(schemaName, primaryTableName, indexTableName, + physicalPlanDataForLocalIndex); + taskList.add(alterGsiPhyTable); + } final ExecutableDdlJob4CreateGsi result = new ExecutableDdlJob4CreateGsi(); result.addSequentialTasks(taskList); @@ -366,7 +397,8 @@ public static ExecutableDdlJob create4CreateTableWithGsi(@Deprecated DDL ddl, DdlPhyPlanBuilder builder = new CreateGlobalIndexBuilder(ddl, globalIndexPreparedData, ec).build(); PhysicalPlanData physicalPlanData = builder.genPhysicalPlanData(autoPartition); ec.getDdlContext().setIgnoreCdcGsiMark(true); - CreateGsiJobFactory gsiJobFactory = new CreateGsiJobFactory(globalIndexPreparedData, physicalPlanData, ec); + CreateGsiJobFactory gsiJobFactory = + new CreateGsiJobFactory(globalIndexPreparedData, physicalPlanData, null, true, ec); gsiJobFactory.needOnlineSchemaChange = false; return gsiJobFactory.create(); } @@ -377,20 +409,32 @@ public static ExecutableDdlJob create(@Deprecated DDL ddl, DdlPhyPlanBuilder builder = new CreateGlobalIndexBuilder(ddl, preparedData, ec).build(); PhysicalPlanData physicalPlanData = builder.genPhysicalPlanData(); - CreateGsiJobFactory gsiJobFactory = CreateGsiJobFactory.create(preparedData, physicalPlanData, ec); + CreateGsiJobFactory gsiJobFactory = CreateGsiJobFactory.create(preparedData, physicalPlanData, null, ec); return gsiJobFactory.create(); } - public void setVirtualColumnMap(Map virtualColumnMap) { - this.virtualColumnMap = virtualColumnMap; + public void setStayAtBackFill(boolean stayAtBackFill) { + this.stayAtBackFill = stayAtBackFill; + } + + public void setSrcVirtualColumnMap(Map srcVirtualColumnMap) { + this.srcVirtualColumnMap = srcVirtualColumnMap; + } + + public void setDstVirtualColumnMap(Map dstVirtualColumnMap) { + this.dstVirtualColumnMap = dstVirtualColumnMap; } - public void setBackfillColumnMap(Map backfillColumnMap) { - this.backfillColumnMap = backfillColumnMap; + public void setDstColumnNewDefinitions(Map dstColumnNewDefinitions) { + this.dstColumnNewDefinitions = dstColumnNewDefinitions; } - public void setOldIndexName(String oldIndexName) { - this.oldIndexName = oldIndexName; + public void setOmcColumnMap(Map omcColumnMap) { + this.omcColumnMap = omcColumnMap; + } + + public void setBackfillSourceTableName(String backfillSourceTableName) { + this.backfillSourceTableName = backfillSourceTableName; } public void setOnlineModifyColumn(boolean onlineModifyColumn) { @@ -412,4 +456,12 @@ public void setModifyStringColumns(List modifyStringColumns) { public void setAddNewColumns(List addNewColumns) { this.addNewColumns = addNewColumns; } + + public void setGsiCdcMark(boolean gsiCdcMark) { + this.gsiCdcMark = gsiCdcMark; + } + + public void setRemovePartitioning(boolean removePartitioning) { + this.removePartitioning = removePartitioning; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/CreatePartitionGsiJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/CreatePartitionGsiJobFactory.java index f79ffb459..e91495209 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/CreatePartitionGsiJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/CreatePartitionGsiJobFactory.java @@ -19,6 +19,8 @@ import com.alibaba.polardbx.common.TddlConstants; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.executor.common.StorageInfoManager; import com.alibaba.polardbx.executor.ddl.job.builder.DdlPhyPlanBuilder; import com.alibaba.polardbx.executor.ddl.job.builder.gsi.CreateGlobalIndexBuilder; import com.alibaba.polardbx.executor.ddl.job.builder.gsi.CreatePartitionGlobalIndexBuilder; @@ -31,6 +33,7 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.factory.GsiTaskFactory; +import com.alibaba.polardbx.executor.ddl.job.task.gsi.AlterGsiAddLocalIndexTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.CreateGsiPhyDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.CreateGsiPreValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.CreateGsiValidateTask; @@ -39,17 +42,24 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.ddl.newengine.job.wrapper.ExecutableDdlJob4CreatePartitionGsi; +import com.alibaba.polardbx.executor.ddl.twophase.DnStats; +import com.alibaba.polardbx.executor.gsi.corrector.GsiChecker; import com.alibaba.polardbx.gms.metadb.table.IndexStatus; import com.alibaba.polardbx.gms.metadb.table.IndexVisibility; +import com.alibaba.polardbx.gms.node.GmsNodeManager; +import com.alibaba.polardbx.gms.node.StorageStatusManager; import com.alibaba.polardbx.gms.partition.TablePartRecordInfoContext; +import com.alibaba.polardbx.gms.sync.SyncScope; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.tablegroup.TableGroupDetailConfig; +import com.alibaba.polardbx.gms.topology.DbTopologyManager; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.CreateGlobalIndexPreparedData; import com.alibaba.polardbx.statistics.SQLRecorderLogger; import com.google.common.collect.Lists; +import io.airlift.slice.DataSize; import org.apache.calcite.rel.core.DDL; import org.apache.commons.lang3.StringUtils; @@ -62,8 +72,10 @@ import java.util.stream.Collectors; import static com.alibaba.polardbx.executor.gsi.GsiUtils.columnAst2nameStr; +import static com.alibaba.polardbx.executor.gsi.GsiUtils.getAvaliableNodeNum; import static com.alibaba.polardbx.gms.metadb.table.IndexStatus.DELETE_ONLY; import static com.alibaba.polardbx.gms.metadb.table.IndexStatus.WRITE_ONLY; +import static io.airlift.slice.DataSize.*; import static org.apache.calcite.sql.SqlIdentifier.surroundWithBacktick; /** @@ -83,6 +95,8 @@ public class CreatePartitionGsiJobFactory extends CreateGsiJobFactory { public CreatePartitionGsiJobFactory(CreateGlobalIndexPreparedData globalIndexPreparedData, PhysicalPlanData physicalPlanData, + PhysicalPlanData physicalPlanDataForLocalIndex, + Boolean create4CreateTableWithGsi, ExecutionContext executionContext) { super( globalIndexPreparedData.getSchemaName(), @@ -102,12 +116,17 @@ public CreatePartitionGsiJobFactory(CreateGlobalIndexPreparedData globalIndexPre globalIndexPreparedData.getIndexTablePreparedData() != null ? globalIndexPreparedData.getIndexTablePreparedData().getSpecialDefaultValueFlags() : new TreeMap<>(String.CASE_INSENSITIVE_ORDER), + executionContext.getParamManager().getBoolean(ConnectionParams.GSI_BACKFILL_BY_PK_RANGE), + executionContext.getParamManager().getBoolean(ConnectionParams.GSI_BACKFILL_BY_PARTITION), physicalPlanData, + physicalPlanDataForLocalIndex, + create4CreateTableWithGsi, globalIndexPreparedData.getAddedForeignKeys(), executionContext ); this.tableGroupAlignWithTargetTable = globalIndexPreparedData.getTableGroupAlignWithTargetTable(); this.globalIndexPreparedData = globalIndexPreparedData; + this.gsiCdcMark = !globalIndexPreparedData.isRepartition(); } @Override @@ -186,55 +205,105 @@ protected ExecutableDdlJob doCreate() { physicalPlanData.getTableGroupConfig()); CreateGsiValidateTask validateTask = new CreateGsiValidateTask(schemaName, primaryTableName, indexTableName, tableGroupIds, - physicalPlanData.getTableGroupConfig()); + physicalPlanData.getTableGroupConfig(), removePartitioning, false); List columns = columnAst2nameStr(this.columns); List coverings = columnAst2nameStr(this.coverings); - Map columnMapping = backfillColumnMap == null ? null : - backfillColumnMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); + Map columnMapping = omcColumnMap == null ? null : + omcColumnMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); final String finalStatus = executionContext.getParamManager().getString(ConnectionParams.GSI_FINAL_STATUS_DEBUG); + Boolean buildLocalIndexLater = + executionContext.getParamManager().getBoolean(ConnectionParams.GSI_BUILD_LOCAL_INDEX_LATER); + int gsiMaxParallelism = executionContext.getParamManager().getInt(ConnectionParams.GSI_JOB_MAX_PARALLELISM); final boolean stayAtDeleteOnly = StringUtils.equalsIgnoreCase(DELETE_ONLY.name(), finalStatus); final boolean stayAtWriteOnly = StringUtils.equalsIgnoreCase(WRITE_ONLY.name(), finalStatus); List bringUpGsi = null; + ExecutableDdlJob bringUpGsiDdlJob = new ExecutableDdlJob(); if (useChangeSet) { // online modify column bringUpGsi = GsiTaskFactory.addGlobalIndexTasksChangeSet( schemaName, primaryTableName, - oldIndexName, + backfillSourceTableName, indexTableName, stayAtDeleteOnly, stayAtWriteOnly, stayAtBackFill, - virtualColumnMap, - backfillColumnMap, + srcVirtualColumnMap, + dstVirtualColumnMap, + dstColumnNewDefinitions, modifyStringColumns, onlineModifyColumn, mirrorCopy, physicalPlanData, globalIndexPreparedData.getIndexPartitionInfo() ); + } else if (needOnlineSchemaChange && (splitByPkRange || splitByPartition)) { + TableMeta tableMeta = executionContext.getSchemaManager(schemaName).getTable(primaryTableName); + ParamManager pm = executionContext.getParamManager(); + boolean enableSample = pm.getBoolean(ConnectionParams.ENABLE_INNODB_BTREE_SAMPLING); + String maxPkRangeSizeStr = pm.getString(ConnectionParams.BACKFILL_MAX_PK_RANGE_SIZE); + String maxTaskPkRangeSizeStr = pm.getString(ConnectionParams.BACKFILL_MAX_TASK_PK_RANGE_SIZE); + long maxPkRangeSize = convertToByte(maxPkRangeSizeStr); + long maxTaskPkRangeSize = convertToByte(maxTaskPkRangeSizeStr); + long maxSampleRows = pm.getLong(ConnectionParams.BACKFILL_MAX_SAMPLE_ROWS); + long maxPkRangeSampleRows = pm.getLong(ConnectionParams.BACKFILL_MAX_SAMPLE_ROWS_FOR_PK_RANGE); + int cpuAcquired = pm.getInt(ConnectionParams.GSI_PK_RANGE_CPU_ACQUIRE); + int maxNodeNum = getAvaliableNodeNum(schemaName, primaryTableName, executionContext); + // if you use pk range, then control the concurrency by cpuAcquired. + gsiMaxParallelism = Math.floorDiv(100, cpuAcquired) * maxNodeNum; + GsiChecker.Params params = GsiChecker.Params.buildFromExecutionContext(executionContext); + bringUpGsiDdlJob = GsiTaskFactory.addGlobalIndexTasks( + schemaName, + primaryTableName, + backfillSourceTableName, + indexTableName, + stayAtDeleteOnly, + stayAtWriteOnly, + stayAtBackFill, + srcVirtualColumnMap, + null, + modifyStringColumns, + physicalPlanData, + physicalPlanDataForLocalIndex, + tableMeta, + gsiCdcMark, + onlineModifyColumn, + mirrorCopy, + executionContext.getOriginSql(), + params, + splitByPkRange, + splitByPartition, + enableSample, + maxTaskPkRangeSize, + maxPkRangeSize, + maxSampleRows, + maxPkRangeSampleRows, + gsiMaxParallelism, + cpuAcquired + ); + physicalPlanDataForLocalIndex = null; } else if (needOnlineSchemaChange) { TableMeta tableMeta = executionContext.getSchemaManager(schemaName).getTable(primaryTableName); - boolean repartition = globalIndexPreparedData.isRepartition(); bringUpGsi = GsiTaskFactory.addGlobalIndexTasks( schemaName, primaryTableName, - oldIndexName, + backfillSourceTableName, indexTableName, stayAtDeleteOnly, stayAtWriteOnly, stayAtBackFill, - virtualColumnMap, - null, + srcVirtualColumnMap, + dstVirtualColumnMap, + dstColumnNewDefinitions, modifyStringColumns, physicalPlanData, tableMeta, - repartition, + gsiCdcMark, onlineModifyColumn, mirrorCopy, executionContext.getOriginSql() @@ -251,8 +320,9 @@ protected ExecutableDdlJob doCreate() { CreateTableAddTablesPartitionInfoMetaTask createTableAddTablesPartitionInfoMetaTask = new CreateTableAddTablesPartitionInfoMetaTask(schemaName, indexTableName, physicalPlanData.isTemporary(), - physicalPlanData.getTableGroupConfig(), null, tableGroupAlignWithTargetTable, primaryTableName, - null, false, globalIndexPreparedData.isWithImplicitTableGroup(), autoCreateTg); + physicalPlanData.getTableGroupConfig(), null, null, tableGroupAlignWithTargetTable, + globalIndexPreparedData.isWithImplicitTableGroup(), false, primaryTableName, + null, false, autoCreateTg); CreateTableAddTablesMetaTask addTablesMetaTask = new CreateTableAddTablesMetaTask( schemaName, @@ -292,6 +362,7 @@ protected ExecutableDdlJob doCreate() { addNewColumns ); addIndexMetaTask = (GsiInsertIndexMetaTask) addIndexMetaTask.onExceptionTryRecoveryThenRollback(); + final ExecutableDdlJob4CreatePartitionGsi result = new ExecutableDdlJob4CreatePartitionGsi(); List taskList = new ArrayList<>(); //1. validate @@ -312,22 +383,38 @@ protected ExecutableDdlJob doCreate() { taskList.add(addIndexMetaTask); // taskList.add(new GsiSyncTask(schemaName, primaryTableName, indexTableName)); //3.2 gsi status: CREATING -> DELETE_ONLY -> WRITE_ONLY -> WRITE_REORG -> PUBLIC - taskList.addAll(bringUpGsi); + result.addSequentialTasks(taskList); + if (splitByPkRange || splitByPartition) { + result.combineTasks(bringUpGsiDdlJob); + result.addTaskRelationship(taskList.get(taskList.size() - 1), bringUpGsiDdlJob.getHead()); + taskList = new ArrayList<>(); + } else { + taskList = new ArrayList<>(); + taskList.addAll(bringUpGsi); + } + if (buildLocalIndexLater && physicalPlanDataForLocalIndex != null) { + AlterGsiAddLocalIndexTask alterGsiPhyTable = + new AlterGsiAddLocalIndexTask(schemaName, primaryTableName, indexTableName, + physicalPlanDataForLocalIndex); + taskList.add(alterGsiPhyTable); + } DdlTask tableSyncTask = new TableSyncTask(schemaName, indexTableName); taskList.add(tableSyncTask); Map tableMetaMap = executionContext.getSchemaManager().getCache(); - if (unique && !clusteredIndex && tableMetaMap != null + boolean ugsiWithPk = + executionContext.getParamManager().getBoolean(ConnectionParams.UNIQUE_GSI_WITH_PRIMARY_KEY); + if (unique && !ugsiWithPk && !clusteredIndex && tableMetaMap != null && tableMetaMap.containsKey(primaryTableName.toLowerCase())) { // only create ugsi (not contains clustered ugsi) // create table with ugsi will not arrive here taskList.add(generateDropLocalIndexJob()); } - final ExecutableDdlJob4CreatePartitionGsi result = new ExecutableDdlJob4CreatePartitionGsi(); - result.addSequentialTasks(taskList); - //todo delete me + for (int i = 0; i < taskList.size(); i++) { + result.appendTask(taskList.get(i)); + } result.labelAsHead(validateTask); result.labelAsTail(tableSyncTask); @@ -338,9 +425,14 @@ protected ExecutableDdlJob doCreate() { result.setCreateTableShowTableMetaTask(showTableMetaTask); result.setGsiInsertIndexMetaTask(addIndexMetaTask); result.setCreateGsiPhyDdlTask(createGsiPhyDdlTask); - result.setLastUpdateGsiStatusTask(bringUpGsi.get(bringUpGsi.size() - 1)); + if (bringUpGsi != null) { + result.setLastUpdateGsiStatusTask(bringUpGsi.get(bringUpGsi.size() - 1)); + } else { + result.setLastUpdateGsiStatusTask(bringUpGsiDdlJob.getTail()); + } result.setLastTask(tableSyncTask); + result.setMaxParallelism(gsiMaxParallelism); return result; } @@ -430,8 +522,13 @@ public static ExecutableDdlJob create(@Deprecated DDL ddl, DdlPhyPlanBuilder builder = CreateGlobalIndexBuilder.create(ddl, globalIndexPreparedData, null, executionContext).build(); PhysicalPlanData physicalPlanData = builder.genPhysicalPlanData(); + PhysicalPlanData physicalPlanDataForLocalIndex = null; + if (builder.getPhysicalPlansForLocalIndex() != null) { + physicalPlanDataForLocalIndex = builder.genPhysicalPlanData(false, true); + } - return CreateGsiJobFactory.create(globalIndexPreparedData, physicalPlanData, executionContext).create(); + return CreateGsiJobFactory.create(globalIndexPreparedData, physicalPlanData, physicalPlanDataForLocalIndex, + executionContext).create(); } public static ExecutableDdlJob create4CreateTableWithGsi(@Deprecated DDL ddl, @@ -447,6 +544,8 @@ public static ExecutableDdlJob create4CreateTableWithGsi(@Deprecated DDL ddl, CreateGsiJobFactory gsiJobFactory = new CreatePartitionGsiJobFactory( globalIndexPreparedData, physicalPlanData, + null, + true, ec ); gsiJobFactory.needOnlineSchemaChange = false; @@ -463,4 +562,6 @@ protected boolean needCreateImplicitTableGroup(List tableGroups) { } return ret; } + + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/DropGsiJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/DropGsiJobFactory.java index 9e814f9d8..f638fbdc6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/DropGsiJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/DropGsiJobFactory.java @@ -27,6 +27,7 @@ import com.alibaba.polardbx.executor.ddl.job.task.gsi.DropGsiTableRemoveMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.GsiDropCleanUpTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateGsiExistenceTask; +import com.alibaba.polardbx.executor.ddl.job.validator.GsiValidator; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; @@ -36,6 +37,7 @@ import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.DropGlobalIndexPreparedData; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; import com.google.common.collect.Lists; import java.util.ArrayList; @@ -85,6 +87,12 @@ protected void validate() { ValidateGsiExistenceTask validateTask = new ValidateGsiExistenceTask(schemaName, primaryTableName, indexTableName, null, null); validateTask.doValidate(schemaName, primaryTableName, indexTableName, executionContext); + + if (TtlConfigUtil.isUseGsiInsteadOfCciForCreateColumnarArcTbl(executionContext)) { + GsiValidator.validateIfDroppingCciOfArcTableOfTtlTable(schemaName, primaryTableName, indexTableName, + executionContext); + } + } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/CreateGsiCheckTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/OmcCheckTask.java similarity index 76% rename from polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/CreateGsiCheckTask.java rename to polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/OmcCheckTask.java index e6a86450e..0820fa4c3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/CreateGsiCheckTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/OmcCheckTask.java @@ -29,23 +29,26 @@ import java.util.Map; -@TaskName(name = "CreateGsiCheckTask") +/** + * @author wumu + */ +@TaskName(name = "OmcCheckTask") @Getter -public class CreateGsiCheckTask extends BaseBackfillTask { +public class OmcCheckTask extends BaseBackfillTask { final private String logicalTableName; final private String indexTableName; - public Map virtualColumns; - public Map backfillColumnMap; + final private Map srcCheckColumnMap; + final private Map dstCheckColumnMap; @JSONCreator - public CreateGsiCheckTask(String schemaName, String logicalTableName, String indexTableName, - Map virtualColumns, Map backfillColumnMap) { + public OmcCheckTask(String schemaName, String logicalTableName, String indexTableName, + Map srcCheckColumnMap, Map dstCheckColumnMap) { super(schemaName); this.logicalTableName = logicalTableName; this.indexTableName = indexTableName; - this.virtualColumns = virtualColumns; - this.backfillColumnMap = backfillColumnMap; - onExceptionTryRecoveryThenRollback(); + this.srcCheckColumnMap = srcCheckColumnMap; + this.dstCheckColumnMap = dstCheckColumnMap; + onExceptionTryRecoveryThenPause(); } @Override @@ -62,7 +65,9 @@ protected void executeImpl(ExecutionContext executionContext) { OptimizerContext.getContext(schemaName).getRuleManager().isBroadCast(indexTableName); CheckGsiTask checkTask = new CheckGsiTask(schemaName, logicalTableName, indexTableName, lockMode, lockMode, params, false, "", - isPrimaryBroadCast, isGsiBroadCast, virtualColumns, backfillColumnMap); + isPrimaryBroadCast, isGsiBroadCast, true); + checkTask.setSrcCheckColumnMap(srcCheckColumnMap); + checkTask.setDstCheckColumnMap(dstCheckColumnMap); checkTask.checkInBackfill(executionContext); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RebuildTableJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RebuildTableJobFactory.java index 35e1cc56f..ba6a96025 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RebuildTableJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RebuildTableJobFactory.java @@ -18,12 +18,15 @@ import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLColumnDefinition; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLNotNullConstraint; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.factory.util.FactoryUtils; import com.alibaba.polardbx.executor.ddl.job.task.basic.AlterColumnDefaultTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.AlterTablePhyDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.ModifyPartitionKeyRemoveTableStatisticTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.RebuildTableChangeMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.RebuildTableCleanFlagTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcModifyPartitionKeyMarkTask; @@ -44,6 +47,7 @@ import com.alibaba.polardbx.gms.util.TableGroupNameUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; +import com.alibaba.polardbx.optimizer.config.table.TableColumnUtils; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.RebuildTablePrepareData; @@ -57,7 +61,6 @@ import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; @@ -75,17 +78,20 @@ public class RebuildTableJobFactory extends DdlJobFactory { private final String schemaName; private final String primaryTableName; + private final String backfillSourceTableName; private final Map tableNameMap; private final Map tableNameMapReverse; - private final Map globalIndexPrepareData; + private final List> globalIndexPrepareData; private final ExecutionContext executionContext; private List alterDefaultColumns; private List changedColumns; private boolean needDropImplicitKey; - private final Map virtualColumnMap; - private final Map columnNewDef; + private final Map srcVirtualColumnMap; + private final Map dstVirtualColumnMap; + private final Map srcColumnNewDef; + private final Map dstColumnNewDef; private final Map backfillColumnMap; private final PhysicalPlanData oldPhysicalPlanData; @@ -93,26 +99,32 @@ public class RebuildTableJobFactory extends DdlJobFactory { private final List modifyStringColumns; private final List addNewColumns; - public RebuildTableJobFactory(String schemaName, String primaryTableName, - Map globalIndexPrepareData, + private long versionId; + + public RebuildTableJobFactory(String schemaName, String primaryTableName, String backfillSourceTableName, + List> globalIndexPrepareData, RebuildTablePrepareData rebuildTablePrepareData, PhysicalPlanData oldPhysicalPlanData, ExecutionContext executionContext) { this.schemaName = schemaName; this.primaryTableName = primaryTableName; + this.backfillSourceTableName = backfillSourceTableName; this.globalIndexPrepareData = globalIndexPrepareData; this.executionContext = executionContext; this.needDropImplicitKey = false; this.alterDefaultColumns = null; this.tableNameMap = rebuildTablePrepareData.getTableNameMap(); this.tableNameMapReverse = rebuildTablePrepareData.getTableNameMapReverse(); - this.virtualColumnMap = rebuildTablePrepareData.getVirtualColumnMap(); - this.columnNewDef = rebuildTablePrepareData.getColumnNewDef(); + this.srcVirtualColumnMap = rebuildTablePrepareData.getSrcVirtualColumnMap(); + this.dstVirtualColumnMap = rebuildTablePrepareData.getDstVirtualColumnMap(); + this.srcColumnNewDef = rebuildTablePrepareData.getSrcColumnNewDef(); + this.dstColumnNewDef = rebuildTablePrepareData.getDstColumnNewDef(); this.backfillColumnMap = rebuildTablePrepareData.getBackfillColumnMap(); this.needRehash = rebuildTablePrepareData.getNeedReHash(); this.modifyStringColumns = rebuildTablePrepareData.getModifyStringColumns(); this.addNewColumns = rebuildTablePrepareData.getAddNewColumns(); this.oldPhysicalPlanData = oldPhysicalPlanData; + this.versionId = rebuildTablePrepareData.getVersionId(); } @Override @@ -134,6 +146,8 @@ protected ExecutableDdlJob doCreate() { final boolean enableBackFillPushDown = executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_BACKFILL_OPT_FOR_OMC); + TableMeta tableMeta = executionContext.getSchemaManager().getTable(primaryTableName); + ExecutableDdlJob ddlJob = new ExecutableDdlJob(); assert !globalIndexPrepareData.isEmpty(); @@ -146,15 +160,14 @@ protected ExecutableDdlJob doCreate() { tableGroupConfigs.addAll(oldTableGroupConfigs); // get new table groups tableGroupConfigs.addAll( - globalIndexPrepareData.values().stream() - .map(PhysicalPlanData::getTableGroupConfig).collect(Collectors.toList()) + globalIndexPrepareData.stream().map(e -> e.getValue().getTableGroupConfig()).collect(Collectors.toList()) ); DdlTask validateTask = new RebuildTableValidateTask(schemaName, primaryTableName, tableNameMap, tableGroupConfigs); // 标记开始 rebuild RebuildTableChangeMetaTask rebuildTableChangeMetaTask = - new RebuildTableChangeMetaTask(schemaName, primaryTableName); + new RebuildTableChangeMetaTask(schemaName, primaryTableName, executionContext.getOriginSql()); TableSyncTask rebuildSyncTask = new TableSyncTask(schemaName, primaryTableName); // for modify default column @@ -166,42 +179,43 @@ protected ExecutableDdlJob doCreate() { beginAlterColumnDefaultSyncTask = new TableSyncTask(schemaName, primaryTableName); } - List checkerTasks = genCheckerTasks(); + List checkerTasks = + genGeneratedColumn4CheckTasks(schemaName, primaryTableName, srcVirtualColumnMap, srcColumnNewDef, + oldPhysicalPlanData); // create gsi List createGsiJobs = new ArrayList<>(); AtomicBoolean hasSubJob = new AtomicBoolean(false); - List> listGlobalIndexPrepareData = new ArrayList<>(); - globalIndexPrepareData.forEach((createGlobalIndexPreparedData, physicalPlanData) -> { - listGlobalIndexPrepareData.add(new Pair<>(createGlobalIndexPreparedData, physicalPlanData)); - }); - Collections.sort(listGlobalIndexPrepareData, - new Comparator>() { - @Override - public int compare(Pair o1, - Pair o2) { - CreateGlobalIndexPreparedData data1 = o1.getKey(); - CreateGlobalIndexPreparedData data2 = o2.getKey(); - - // 检查fieldA是否为空(这里假设fieldA是String类型) - boolean isData1TableGroupAlignWithTargetTableEmpty = - StringUtils.isEmpty(data1.getTableGroupAlignWithTargetTable()); - boolean isData2TableGroupAlignWithTargetTableEmpty = - StringUtils.isEmpty(data2.getTableGroupAlignWithTargetTable()); - - if (isData1TableGroupAlignWithTargetTableEmpty && !isData2TableGroupAlignWithTargetTableEmpty) { - return -1; // data1中的TableGroupAlignWithTargetTable为空,应该排在前面 - } else if (!isData1TableGroupAlignWithTargetTableEmpty - && isData2TableGroupAlignWithTargetTableEmpty) { - return 1; // data2中的TableGroupAlignWithTargetTable为空,data1应该排在后面 - } else { - return 0; // 两者都为空或都不为空,视为相等 - } + globalIndexPrepareData.sort(new Comparator>() { + @Override + public int compare(Pair o1, + Pair o2) { + CreateGlobalIndexPreparedData data1 = o1.getKey(); + CreateGlobalIndexPreparedData data2 = o2.getKey(); + + // 检查fieldA是否为空(这里假设fieldA是String类型) + boolean isData1TableGroupAlignWithTargetTableEmpty = + StringUtils.isEmpty(data1.getTableGroupAlignWithTargetTable()); + boolean isData2TableGroupAlignWithTargetTableEmpty = + StringUtils.isEmpty(data2.getTableGroupAlignWithTargetTable()); + + // 主表对应的目标表永远放在第一位 + if (data1.isOmcRebuildPrimaryTable()) { + return -1; + } + + if (isData1TableGroupAlignWithTargetTableEmpty && !isData2TableGroupAlignWithTargetTableEmpty) { + return -1; // data1中的TableGroupAlignWithTargetTable为空,应该排在前面 + } else if (!isData1TableGroupAlignWithTargetTableEmpty + && isData2TableGroupAlignWithTargetTableEmpty) { + return 1; // data2中的TableGroupAlignWithTargetTable为空,data1应该排在后面 + } else { + return 0; // 两者都为空或都不为空,视为相等 } - }); - for (int i = 0; i < listGlobalIndexPrepareData.size(); i++) { - Pair pair = listGlobalIndexPrepareData.get(i); + } + }); + for (Pair pair : globalIndexPrepareData) { PhysicalPlanData physicalPlanData = pair.getValue(); CreateGlobalIndexPreparedData createGlobalIndexPreparedData = pair.getKey(); if (!hasSubJob.get()) { @@ -221,26 +235,36 @@ public int compare(Pair o1, } CreateGsiJobFactory createGsiJobFactory = - CreateGsiJobFactory.create(createGlobalIndexPreparedData, physicalPlanData, executionContext); - createGsiJobFactory.stayAtBackFill = true; - createGsiJobFactory.setVirtualColumnMap(virtualColumnMap); - createGsiJobFactory.setBackfillColumnMap(backfillColumnMap); - String oldIndexName = tableNameMapReverse.get(createGlobalIndexPreparedData.getIndexTableName()); - createGsiJobFactory.setOldIndexName(oldIndexName); - - boolean mirrorCopy = !needRehash.get(createGlobalIndexPreparedData.getIndexTableName()); - if (enableBackFillPushDown) { - createGsiJobFactory.setMirrorCopy(mirrorCopy); - } - TableMeta gsiTableMeta = executionContext.getSchemaManager(schemaName).getTable(oldIndexName); - if (useChangeSet && ChangeSetUtils.supportUseChangeSet( - ComplexTaskMetaManager.ComplexTaskType.ONLINE_MODIFY_COLUMN, gsiTableMeta)) { - createGsiJobFactory.setUseChangeSet(mirrorCopy); - } - - createGsiJobFactory.setOnlineModifyColumn(true); + CreateGsiJobFactory.create(createGlobalIndexPreparedData, physicalPlanData, null, executionContext); + createGsiJobFactory.setStayAtBackFill(true); createGsiJobFactory.setModifyStringColumns(modifyStringColumns); + createGsiJobFactory.setOmcColumnMap(backfillColumnMap); createGsiJobFactory.setAddNewColumns(addNewColumns); + + if (createGlobalIndexPreparedData.isOmcRebuildPrimaryTable()) { + // 特殊流程,涉及 changeset 优化、insert select backfill 优化、列名映射等流程 + createGsiJobFactory.setOnlineModifyColumn(true); + createGsiJobFactory.setSrcVirtualColumnMap(srcVirtualColumnMap); + createGsiJobFactory.setDstVirtualColumnMap(dstVirtualColumnMap); + createGsiJobFactory.setDstColumnNewDefinitions(dstColumnNewDef); + String oldIndexName = tableNameMapReverse.get(createGlobalIndexPreparedData.getIndexTableName()); + createGsiJobFactory.setBackfillSourceTableName(oldIndexName); + + boolean mirrorCopy = !needRehash.get(createGlobalIndexPreparedData.getIndexTableName()); + if (enableBackFillPushDown) { + createGsiJobFactory.setMirrorCopy(mirrorCopy); + } + TableMeta gsiTableMeta = executionContext.getSchemaManager(schemaName).getTable(oldIndexName); + if (useChangeSet && ChangeSetUtils.supportUseChangeSet( + ComplexTaskMetaManager.ComplexTaskType.ONLINE_MODIFY_COLUMN, gsiTableMeta)) { + createGsiJobFactory.setUseChangeSet(mirrorCopy); + } + } else { + // 普通重建 GSI 流程 + createGsiJobFactory.setOnlineModifyColumn(false); + createGsiJobFactory.setBackfillSourceTableName(backfillSourceTableName); + } + ExecutableDdlJob gsiJob = createGsiJobFactory.create(); SubJobTask subJobTask = createGsiJobFactory.rerunTask; if (createGlobalIndexPreparedData.isNeedToGetTableGroupLock() && !hasSubJob.get()) { @@ -261,25 +285,30 @@ public int compare(Pair o1, createGsiJobs.forEach(ddlJob::appendJob2); return ddlJob; } - TableMeta tableMeta = executionContext.getSchemaManager().getTable(primaryTableName); + TddlRuleManager tddlRuleManager = executionContext.getSchemaManager().getTddlRuleManager(); // cut over RebuildTableCutOverTask cutOverTask = new RebuildTableCutOverTask(schemaName, primaryTableName, tableNameMap, tableMeta.isAutoPartition(), tddlRuleManager.isTableInSingleDb(primaryTableName), - tddlRuleManager.isBroadCast(primaryTableName) + tddlRuleManager.isBroadCast(primaryTableName), + versionId ); ModifyPartitionKeySyncTask modifyPartitionKeySyncTask = new ModifyPartitionKeySyncTask(schemaName, primaryTableName, tableNameMap); + RebuildTableCleanFlagTask rebuildTableCleanFlagTask = + new RebuildTableCleanFlagTask(schemaName, primaryTableName); + TableSyncTask cleanFlagSyncTask = new TableSyncTask(schemaName, primaryTableName); + ModifyPartitionKeyRemoveTableStatisticTask removeTableStatisticTask = new ModifyPartitionKeyRemoveTableStatisticTask(schemaName, primaryTableName, changedColumns); // cdc DdlTask cdcDdlMarkTask = new CdcModifyPartitionKeyMarkTask(schemaName, primaryTableName, tableNameMap.get(primaryTableName), - SqlKind.ALTER_TABLE, tableNameMap); + SqlKind.ALTER_TABLE, tableNameMap, versionId); // drop gsi List dropGsiJobs = new ArrayList<>(); @@ -334,7 +363,9 @@ public int compare(Pair o1, ddlJob.appendTask(cdcDdlMarkTask); ddlJob.addTaskRelationship(cdcDdlMarkTask, cutOverTask); ddlJob.addTaskRelationship(cutOverTask, modifyPartitionKeySyncTask); - ddlJob.addTaskRelationship(modifyPartitionKeySyncTask, removeTableStatisticTask); + ddlJob.addTaskRelationship(modifyPartitionKeySyncTask, rebuildTableCleanFlagTask); + ddlJob.addTaskRelationship(rebuildTableCleanFlagTask, cleanFlagSyncTask); + ddlJob.addTaskRelationship(cleanFlagSyncTask, removeTableStatisticTask); } final boolean skipCleanUp = StringUtils.equalsIgnoreCase( @@ -387,7 +418,35 @@ protected void excludeResources(Set resources) { } } - private List genCheckerTasks() { + public static DdlTask genDropColumn4CheckTasks(String schemaName, String primaryTableName, + Map virtualColumnMap, + PhysicalPlanData physicalPlanData) { + if (MapUtils.isEmpty(virtualColumnMap)) { + return null; + } + + String tableNameWithBacktick = surroundWithBacktick(primaryTableName); + StringBuilder dropSqlFormatter = new StringBuilder(); + dropSqlFormatter.append("ALTER TABLE %s "); + + for (Map.Entry entry : virtualColumnMap.entrySet()) { + String virColName = entry.getValue(); + dropSqlFormatter.append(String.format("DROP COLUMN %s,", surroundWithBacktick(virColName))); + } + + dropSqlFormatter.deleteCharAt(dropSqlFormatter.length() - 1); + + String dropSqlTemplate = String.format(dropSqlFormatter.toString(), "?"); + String dropSql = String.format(dropSqlFormatter.toString(), tableNameWithBacktick); + + return genAlterTablePhyTask(dropSql, "", dropSqlTemplate, "", schemaName, primaryTableName, + "INPLACE", physicalPlanData); + } + + public static List genGeneratedColumn4CheckTasks(String schemaName, String primaryTableName, + Map virtualColumnMap, + Map columnNewDef, + PhysicalPlanData physicalPlanData) { List result = new ArrayList<>(); if (MapUtils.isEmpty(virtualColumnMap) || MapUtils.isEmpty(columnNewDef)) { @@ -396,24 +455,31 @@ private List genCheckerTasks() { String tableNameWithBacktick = surroundWithBacktick(primaryTableName); virtualColumnMap.forEach((colName, virColName) -> { - String addSqlFormatter = - String.format("ALTER TABLE %%s ADD COLUMN `%s` %s GENERATED ALWAYS AS (ALTER_TYPE(`%s`)) VIRTUAL", - virColName, columnNewDef.get(colName), colName); - String dropSqlFormatter = String.format("ALTER TABLE %%s DROP COLUMN `%s`", virColName); + SQLColumnDefinition columnDefinition = columnNewDef.get(colName); + String definition = TableColumnUtils.getDataDefFromColumnDefNoDefault(columnDefinition); + boolean notNull = + columnDefinition.getConstraints().stream().anyMatch(e -> e instanceof SQLNotNullConstraint); + String addSqlFormatter = String.format( + "ALTER TABLE %%s ADD COLUMN %s %s GENERATED ALWAYS AS (ALTER_TYPE(%s)) VIRTUAL %s", + surroundWithBacktick(virColName), definition, surroundWithBacktick(colName), notNull ? "NOT NULL" : ""); + String dropSqlFormatter = String.format("ALTER TABLE %%s DROP COLUMN %s", surroundWithBacktick(virColName)); String addSql = String.format(addSqlFormatter, tableNameWithBacktick); String dropSql = String.format(dropSqlFormatter, tableNameWithBacktick); String addSqlTemplate = String.format(addSqlFormatter, "?"); String dropSqlTemplate = String.format(dropSqlFormatter, "?"); result.add( - genAlterTablePhyTask(addSql, dropSql, addSqlTemplate, dropSqlTemplate, primaryTableName, "INPLACE")); + genAlterTablePhyTask(addSql, dropSql, addSqlTemplate, dropSqlTemplate, schemaName, primaryTableName, + "INPLACE", physicalPlanData)); }); return result; } - private DdlTask genAlterTablePhyTask(String sql, String reverseSql, String sqlTemplate, String reverseSqlTemplate, - String tableName, String algorithm) { + public static DdlTask genAlterTablePhyTask(String sql, String reverseSql, String sqlTemplate, + String reverseSqlTemplate, + String schemaName, String tableName, String algorithm, + PhysicalPlanData physicalPlanData) { sql = sql + ", ALGORITHM=" + algorithm; if (!StringUtils.isEmpty(reverseSql)) { reverseSql = reverseSql + ", ALGORITHM=" + algorithm; @@ -424,7 +490,8 @@ private DdlTask genAlterTablePhyTask(String sql, String reverseSql, String sqlTe reverseSqlTemplate = reverseSqlTemplate + ", ALGORITHM=" + algorithm; } - PhysicalPlanData newPhysicalPlanData = oldPhysicalPlanData.clone(); + PhysicalPlanData newPhysicalPlanData = physicalPlanData.clone(); + newPhysicalPlanData.setKind(SqlKind.ALTER_TABLE); newPhysicalPlanData.setSqlTemplate(sqlTemplate); AlterTablePhyDdlTask task; task = new AlterTablePhyDdlTask(schemaName, tableName, newPhysicalPlanData); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RemovePartitioningJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RemovePartitioningJobFactory.java index 912813c09..72393f69f 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RemovePartitioningJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RemovePartitioningJobFactory.java @@ -17,15 +17,14 @@ package com.alibaba.polardbx.executor.ddl.job.factory.gsi; import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.ddl.newengine.DdlType; +import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.factory.util.FactoryUtils; import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcRepartitionMarkTask; import com.alibaba.polardbx.executor.ddl.job.task.factory.GsiTaskFactory; -import com.alibaba.polardbx.executor.ddl.job.task.gsi.AlterTableRemovePartitioningValidateTask; -import com.alibaba.polardbx.executor.ddl.job.task.gsi.RepartitionCutOverTask; -import com.alibaba.polardbx.executor.ddl.job.task.gsi.RepartitionSyncTask; -import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; +import com.alibaba.polardbx.executor.ddl.job.task.gsi.*; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.TableGroupSyncTask; import com.alibaba.polardbx.executor.ddl.job.validator.GsiValidator; import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; @@ -37,6 +36,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.wrapper.ExecutableDdlJob4DropPartitionGsi; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.context.DdlContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.CreateGlobalIndexPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.DropGlobalIndexPreparedData; @@ -44,15 +44,14 @@ import org.apache.calcite.sql.SqlKind; import org.apache.commons.lang.StringUtils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; +import static com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility.Private; +import static com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility.Protected; +import static com.alibaba.polardbx.common.ddl.newengine.DdlType.*; +import static com.alibaba.polardbx.common.ddl.newengine.DdlType.ALTER_TABLE; + /** * @author wumu */ @@ -107,14 +106,35 @@ protected ExecutableDdlJob doCreate() { // create gsi List createGsiJobs = new ArrayList<>(); - globalIndexPrepareData.forEach((createGlobalIndexPreparedData, physicalPlanData) -> { + for (Map.Entry entry : globalIndexPrepareData.entrySet()) { CreateGsiJobFactory createGsiJobFactory = - CreateGsiJobFactory.create(createGlobalIndexPreparedData, physicalPlanData, executionContext); - if (StringUtils.equalsIgnoreCase(createGlobalIndexPreparedData.getIndexTableName(), indexTableName)) { + CreateGsiJobFactory.create(entry.getKey(), entry.getValue(), null, executionContext); + + if (StringUtils.equalsIgnoreCase(entry.getKey().getIndexTableName(), indexTableName)) { createGsiJobFactory.stayAtBackFill = true; } - createGsiJobs.add((ExecutableDdlJob4CreatePartitionGsi) createGsiJobFactory.create()); - }); + createGsiJobFactory.setGsiCdcMark(false); + createGsiJobFactory.setRemovePartitioning(true); + ExecutableDdlJob createGsiJob = createGsiJobFactory.create(); + if (entry.getKey().getRelatedTableGroupInfo().values().stream().anyMatch(o -> o.booleanValue()) + || entry.getKey().isNeedToGetTableGroupLock()) { + return createGsiJob; + } + createGsiJobs.add((ExecutableDdlJob4CreatePartitionGsi) createGsiJob); + } + Set tgSet = new HashSet<>(); + for (ExecutableDdlJob4CreatePartitionGsi job : createGsiJobs) { + TableGroupConfig tgConfig = job.getCreateGsiValidateTask().getTableGroupConfig(); + if (tgConfig != null && GeneralUtil.isNotEmpty(tgConfig.getPartitionGroupRecords())) { + Long tgId = tgConfig.getPartitionGroupRecords().get(0).tg_id; + if (tgSet.contains(tgId)) { + CreateGsiValidateTask validTask = job.getCreateGsiValidateTask(); + validTask.skipTgChangeCheck(); + } else { + tgSet.add(tgId); + } + } + } RepartitionCutOverTask cutOverTask = new RepartitionCutOverTask(schemaName, primaryTableName, indexTableName, false, false, true, false); @@ -122,7 +142,12 @@ protected ExecutableDdlJob doCreate() { // cdc if (executionContext.getDdlContext().isSubJob()) { - throw new RuntimeException("unexpected parent ddl job"); + DdlContext rootDdlContext = getRootParentDdlContext(executionContext.getDdlContext()); + DdlType rootDdlType = rootDdlContext.getDdlType(); + if (ALTER_TABLE_SET_TABLEGROUP != rootDdlType && ALTER_TABLE != rootDdlType + && ALTER_TABLEGROUP != rootDdlType) { + throw new RuntimeException("unexpected parent ddl job " + rootDdlContext.getDdlType()); + } } DdlTask cdcDdlMarkTask = new CdcRepartitionMarkTask( schemaName, primaryTableName, SqlKind.ALTER_TABLE, CdcDdlMarkVisibility.Protected); @@ -208,4 +233,12 @@ private List genDropGsiColumns() { return tasks; } + + private DdlContext getRootParentDdlContext(DdlContext ddlContext) { + if (ddlContext.getParentDdlContext() != null) { + return getRootParentDdlContext(ddlContext.getParentDdlContext()); + } else { + return ddlContext; + } + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RenameGsiJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RenameGsiJobFactory.java index 6d1158e8f..3279d2c55 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RenameGsiJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RenameGsiJobFactory.java @@ -29,6 +29,7 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.RenameTableValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcDdlMarkTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcGsiDdlMarkTask; import com.alibaba.polardbx.executor.ddl.job.validator.GsiValidator; import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; @@ -48,20 +49,21 @@ import java.util.List; import java.util.Set; +import static com.alibaba.polardbx.common.cdc.ICdcManager.DEFAULT_DDL_VERSION_ID; +import static org.apache.calcite.sql.SqlIdentifier.surroundWithBacktick; + public class RenameGsiJobFactory extends DdlJobFactory { private final String schemaName; private final String gsiName; private final String newGsiName; private final ExecutionContext executionContext; - private final RenameTablePreparedData preparedData; public RenameGsiJobFactory(RenameTablePreparedData preparedData, ExecutionContext executionContext) { this.schemaName = preparedData.getSchemaName(); this.gsiName = preparedData.getTableName(); this.newGsiName = preparedData.getNewTableName(); this.executionContext = executionContext; - this.preparedData = preparedData; } @Override @@ -69,6 +71,7 @@ protected void validate() { GsiValidator.validateGsi(schemaName, gsiName); GsiValidator.validateCreateOnGsi(schemaName, newGsiName, executionContext); GsiValidator.validateAllowRenameOnTable(schemaName, gsiName, executionContext); + } @Override @@ -91,16 +94,24 @@ protected ExecutableDdlJob doCreate() { TableMeta primaryTableMeta = OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(primaryTableName); if (!primaryTableMeta.isAutoPartition()) { - //mark gsi task + // mark gsi task PhysicalPlanData physicalPlanData = new PhysicalPlanData(); physicalPlanData.setKind(SqlKind.RENAME_TABLE); - physicalPlanData.setLogicalTableName(newGsiName); + physicalPlanData.setLogicalTableName(primaryTableName); physicalPlanData.setSchemaName(schemaName); CdcGsiDdlMarkTask cdcDdlMarkTask = new CdcGsiDdlMarkTask(schemaName, physicalPlanData, primaryTableName, executionContext.getOriginSql()); taskList.add(cdcDdlMarkTask); + } else { + // mark local index task + PhysicalPlanData physicalPlanData = new PhysicalPlanData(); + physicalPlanData.setKind(SqlKind.ALTER_TABLE); + physicalPlanData.setLogicalTableName(primaryTableName); + physicalPlanData.setSchemaName(schemaName); + CdcDdlMarkTask cdcDdlMarkTask = + new CdcDdlMarkTask(schemaName, physicalPlanData, false, false, DEFAULT_DDL_VERSION_ID); + taskList.add(cdcDdlMarkTask); } - taskList.add(syncTask); ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); @@ -149,18 +160,23 @@ public static DdlTask createRenameLocalIndex(String schemaName, SqlAlterTable sq SQLAlterTableStatement stmt = (SQLAlterTableStatement) statementList.get(0); for (SQLAlterTableItem item : stmt.getItems()) { - ((SQLAlterTableRenameIndex) item).setName(new SQLIdentifierExpr(preparedData.getOrgIndexName())); - ((SQLAlterTableRenameIndex) item).setTo(new SQLIdentifierExpr(preparedData.getNewIndexName())); + ((SQLAlterTableRenameIndex) item).setName( + new SQLIdentifierExpr(surroundWithBacktick(preparedData.getOrgIndexName()))); + ((SQLAlterTableRenameIndex) item).setTo( + new SQLIdentifierExpr(surroundWithBacktick(preparedData.getNewIndexName()))); } String newRenameIndex = stmt.toString(); for (SQLAlterTableItem item : stmt.getItems()) { - ((SQLAlterTableRenameIndex) item).setName(new SQLIdentifierExpr(preparedData.getNewIndexName())); - ((SQLAlterTableRenameIndex) item).setTo(new SQLIdentifierExpr(preparedData.getOrgIndexName())); + ((SQLAlterTableRenameIndex) item).setName( + new SQLIdentifierExpr(surroundWithBacktick(preparedData.getNewIndexName()))); + ((SQLAlterTableRenameIndex) item).setTo( + new SQLIdentifierExpr(surroundWithBacktick(preparedData.getOrgIndexName()))); } String rollbackRenameIndex = stmt.toString(); SubJobTask ddlTask = new SubJobTask(schemaName, newRenameIndex, rollbackRenameIndex); ddlTask.setParentAcquireResource(true); + ddlTask.setSkipCdcMarkTask(true); return ddlTask; } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RepartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RepartitionJobFactory.java index c1802f84f..38017d1bc 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RepartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/RepartitionJobFactory.java @@ -51,6 +51,7 @@ import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.gms.util.TableGroupNameUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.DdlContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.RepartitionPrepareData; @@ -154,6 +155,11 @@ protected ExecutableDdlJob doCreate() { ); boolean checkSingleTgNotExists = result.getKey(); boolean checkBroadcastTgNotExists = result.getValue(); + boolean rebuildCci = + executionContext.getParamManager().getBoolean(ConnectionParams.REBUILD_CCI_WHEN_REPARTITION); + + TableMeta tableMeta = executionContext.getSchemaManager(schemaName).getTable(primaryTableName); + boolean autoPartition = tableMeta.isAutoPartition(); if (physicalPlanData.getTableGroupConfig() != null) { TableGroupRecord tableGroupRecord = physicalPlanData.getTableGroupConfig().getTableGroupRecord(); @@ -185,7 +191,7 @@ protected ExecutableDdlJob doCreate() { globalIndexPreparedData.setRepartition(true); CreateGsiJobFactory createGsiJobFactory = - CreateGsiJobFactory.create(globalIndexPreparedData, physicalPlanData, executionContext); + CreateGsiJobFactory.create(globalIndexPreparedData, physicalPlanData, null, executionContext); createGsiJobFactory.stayAtBackFill = true; ExecutableDdlJob createGsiJob = createGsiJobFactory.create(); if (globalIndexPreparedData.getRelatedTableGroupInfo().values().stream().anyMatch(o -> o.booleanValue()) @@ -236,17 +242,22 @@ protected ExecutableDdlJob doCreate() { repartitionJob.addTaskRelationship(validateTableVersionTask, validateTask); // 1.gsi add column - for (ExecutableDdlJob4AlterTable gsiAddColumnJob : gsiAddColumnJobs) { - repartitionJob.combineTasks(gsiAddColumnJob); - repartitionJob.addTaskRelationship(validateTask, gsiAddColumnJob.getTableValidateTask()); + if (!autoPartition) { + for (ExecutableDdlJob4AlterTable gsiAddColumnJob : gsiAddColumnJobs) { + repartitionJob.combineTasks(gsiAddColumnJob); + repartitionJob.addTaskRelationship(validateTask, gsiAddColumnJob.getTableValidateTask()); + } + } else { + // 默认主键拆分表,需要删除所有的gsi,无需为 gsi add column + dropGlobalIndexJobs.forEach(repartitionJob::appendJob2); } boolean skipCheck = executionContext.getParamManager().getBoolean(ConnectionParams.REPARTITION_SKIP_CHECK); // only optimize for key partition // do not change topology, only change table meta - if (!skipCheck && changeShardColumnsOnly != null && !changeShardColumnsOnly.isEmpty() && modifyLocality != null - && !modifyLocality) { + if (!skipCheck && changeShardColumnsOnly != null && !changeShardColumnsOnly.isEmpty() + && (modifyLocality == null || !modifyLocality)) { // add local index subJob SubJobTask addIndexSubJobTask = null; if (addLocalIndexSql != null && addLocalIndexSql.getKey() != null && addLocalIndexSql.getValue() != null) { @@ -287,7 +298,7 @@ protected ExecutableDdlJob doCreate() { return repartitionJob; } - if (GeneralUtil.isNotEmpty(dropCciSql)) { + if (rebuildCci && GeneralUtil.isNotEmpty(dropCciSql)) { List dropCciSubJobTasks = new ArrayList<>(); for (Pair sql : dropCciSql) { SubJobTask dropCciSubJobTask = @@ -351,12 +362,14 @@ protected ExecutableDdlJob doCreate() { } // 6. drop gsi tables - dropGlobalIndexJobs.forEach(repartitionJob::appendJob2); + if (!autoPartition) { + dropGlobalIndexJobs.forEach(repartitionJob::appendJob2); + } // create cci // repartitionJob.appendJob2(createCciJob); - if (GeneralUtil.isNotEmpty(addCciSql)) { + if (rebuildCci && GeneralUtil.isNotEmpty(addCciSql)) { List addCciSubJobTasks = new ArrayList<>(); for (Pair sql : addCciSql) { SubJobTask addCciSubJobTask = diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/TruncateTableWithGsiJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/TruncateTableWithGsiJobFactory.java index 9f31f1eb8..fc872faed 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/TruncateTableWithGsiJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/TruncateTableWithGsiJobFactory.java @@ -28,9 +28,11 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.DropTableRemoveMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.DropTableValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.DropTruncateTmpPrimaryTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.ResetSequence4TruncateTableTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TruncateTableValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcTruncateTableWithGsiMarkTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.TruncateColumnarTableTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.TruncateCutOverTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.TruncateSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.TruncateTableWithGsiValidateTask; @@ -128,6 +130,11 @@ protected ExecutableDdlJob doCreate() { result.appendJob2(validateJob); result.appendJob2(createTmpTableJob); + DdlTask resetSequenceTask = new ResetSequence4TruncateTableTask(schemaName, logicalTableName); + result.appendTask(resetSequenceTask); + if (preparedData.isHasColumnarIndex()) { + result.appendTask(new TruncateColumnarTableTask(schemaName, logicalTableName, preparedData.getVersionId())); + } result.appendJob2(cutOverJob); result.appendJob2(dropTmpTableJob); @@ -180,7 +187,7 @@ protected DdlTask generateValidateTruncateTask() { private ExecutableDdlJob generateCutOverJob() { ExecutableDdlJob cutOverJob = new ExecutableDdlJob(); CdcTruncateTableWithGsiMarkTask cdcTask = - new CdcTruncateTableWithGsiMarkTask(schemaName, logicalTableName, tmpPrimaryTableName); + new CdcTruncateTableWithGsiMarkTask(schemaName, logicalTableName, tmpPrimaryTableName, preparedData.getVersionId()); TruncateCutOverTask cutOverTask = new TruncateCutOverTask(schemaName, logicalTableName, tmpIndexTableMap, tmpPrimaryTableName); TruncateSyncTask syncTask = diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/columnar/CreateColumnarIndexJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/columnar/CreateColumnarIndexJobFactory.java index 2559221fc..d8321b1e3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/columnar/CreateColumnarIndexJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/columnar/CreateColumnarIndexJobFactory.java @@ -26,7 +26,14 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateTableShowTableMetaTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcCreateColumnarIndexTask; -import com.alibaba.polardbx.executor.ddl.job.task.columnar.*; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.AddColumnarTablesMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.AddColumnarTablesPartitionInfoMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.CreateCheckCciTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.CreateColumnarIndexValidateTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.CreateMockColumnarIndexTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.InsertColumnarIndexMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.UpdateColumnarConfigTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.WaitColumnarTableCreationTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.CciUpdateIndexStatusTask; import com.alibaba.polardbx.executor.ddl.job.validator.GsiValidator; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlExceptionAction; @@ -57,6 +64,7 @@ import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlPartitionBy; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import java.util.ArrayList; import java.util.Collections; @@ -235,7 +243,7 @@ private void buildPartitionInfo(TableMeta tableMeta) { tableGroupName, preparedData.isWithImplicitTableGroup(), joinGroupName, (SqlPartitionBy) preparedData.getPartitioning(), preparedData.getPartBoundExprInfo(), pkColMetas, allColMetas, PartitionTableType.COLUMNAR_TABLE, - executionContext, new LocalityDesc()); + executionContext, new LocalityDesc(), false); } private void buildCoverings(TableMeta tableMeta) { @@ -333,6 +341,12 @@ protected ExecutableDdlJob doCreate() { primaryTableName, columnarIndexTableName, sqlCreateIndex.getOriginIndexName().getLastName(), + // Some columnar options are defined in CREATE INDEX STATEMENT, + // they are stored in `columnar_table_evolution`. + // Some options may be changed in the future, + // but `columnar_table_evolution` will not be updated. + // So use `columnar_config` to get the latest options, + // and use `columnar_table_evolution` to get the immutable options (like dict columns). sqlCreateIndex.getColumnarOptions(), sqlCreateIndex.toString(true), versionId); @@ -377,6 +391,17 @@ protected ExecutableDdlJob doCreate() { createCheckCciTask.setExceptionAction(DdlExceptionAction.PAUSE); taskList.add(createCheckCciTask); + // 3.1.3 update columnar config if necessary + if (MapUtils.isNotEmpty(sqlCreateIndex.getColumnarOptions())) { + final UpdateColumnarConfigTask updateColumnarConfigTask = new UpdateColumnarConfigTask( + schemaName, + primaryTableName, + columnarIndexTableName, + sqlCreateIndex.getColumnarOptions() + ); + taskList.add(updateColumnarConfigTask); + } + // 3.2 change cci status to PUBLIC final CciUpdateIndexStatusTask updateCciStatusTask = (CciUpdateIndexStatusTask) new CciUpdateIndexStatusTask( schemaName, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/columnar/DropColumnarIndexJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/columnar/DropColumnarIndexJobFactory.java index 5db685680..838a65f37 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/columnar/DropColumnarIndexJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/gsi/columnar/DropColumnarIndexJobFactory.java @@ -27,6 +27,7 @@ import com.alibaba.polardbx.executor.ddl.job.task.gsi.GsiDropCleanUpTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateGsiExistenceTask; import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.TableGroupSyncTask; +import com.alibaba.polardbx.executor.ddl.job.validator.GsiValidator; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; @@ -100,7 +101,8 @@ protected void sharedResources(Set resources) { @Override protected void validate() { - + GsiValidator.validateIfDroppingCciOfArcTableOfTtlTable(schemaName, primaryTableName, indexTableName, + executionContext); } @Override @@ -162,7 +164,6 @@ protected ExecutableDdlJob doCreate() { final DdlTask syncTableGroup = new TableGroupSyncTask( schemaName, indexTgConfig.getTableGroupRecord().getTg_name()); - taskList.add(syncTableGroup); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/ExpireLocalPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/ExpireLocalPartitionJobFactory.java index 1779f045a..4665120dd 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/ExpireLocalPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/ExpireLocalPartitionJobFactory.java @@ -41,6 +41,9 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.oss.FileValidationTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.oss.OSSTaskUtils; import com.alibaba.polardbx.executor.ddl.job.task.basic.oss.UpdateFileCommitTsTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcExpireLocalPartitionMarkTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcExpireLocalPartitionMarkTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcMarkUtil; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; import com.alibaba.polardbx.executor.ddl.job.task.localpartition.LocalPartitionPhyDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.localpartition.LocalPartitionValidateTask; @@ -290,6 +293,9 @@ protected ExecutableDdlJob doCreate() { taskList.add(genPhyDdlTask(schemaName, gsiName, phySql)); }); } + CdcExpireLocalPartitionMarkTask + cdcMarkTask = new CdcExpireLocalPartitionMarkTask(schemaName, primaryTableName); + taskList.add(cdcMarkTask); executableDdlJob.addSequentialTasksAfter(headTask, taskList); return executableDdlJob; } @@ -326,4 +332,4 @@ protected void sharedResources(Set resources) { }); } -} \ No newline at end of file +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/ReorganizeLocalPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/ReorganizeLocalPartitionJobFactory.java index 4a7ec1e9b..fa650a500 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/ReorganizeLocalPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/ReorganizeLocalPartitionJobFactory.java @@ -28,6 +28,7 @@ import com.alibaba.polardbx.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.ddl.job.builder.DirectPhysicalSqlPlanBuilder; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcAllocateLocalPartitionMarkTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; import com.alibaba.polardbx.executor.ddl.job.task.localpartition.LocalPartitionPhyDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.localpartition.LocalPartitionValidateTask; @@ -154,6 +155,9 @@ protected ExecutableDdlJob doCreate() { taskList.add(genPhyDdlTask(schemaName, gsiName, phySql)); }); } + CdcAllocateLocalPartitionMarkTask cdcAllocateLocalPartitionMarkTask = + new CdcAllocateLocalPartitionMarkTask(schemaName, primaryTableName); + taskList.add(cdcAllocateLocalPartitionMarkTask); executableDdlJob.addSequentialTasks(taskList); return executableDdlJob; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/RepartitionLocalPartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/RepartitionLocalPartitionJobFactory.java index f41a9597b..7bc796881 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/RepartitionLocalPartitionJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/localpartition/RepartitionLocalPartitionJobFactory.java @@ -29,6 +29,7 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.AddLocalPartitionTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.RemoveLocalPartitionTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcRepartitionLocalPartitionMarkTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; import com.alibaba.polardbx.executor.ddl.job.task.localpartition.LocalPartitionPhyDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.localpartition.LocalPartitionValidateTask; @@ -184,6 +185,7 @@ protected ExecutableDdlJob doCreate() { definitionInfo.archiveTableName = primaryTableMeta.getLocalPartitionDefinitionInfo().archiveTableName; } taskList.add(new AddLocalPartitionTask(definitionInfo)); + taskList.add(new CdcRepartitionLocalPartitionMarkTask(schemaName, primaryTableName)); taskList.add(new TableSyncTask(schemaName, primaryTableName)); executableDdlJob.addSequentialTasks(taskList); return executableDdlJob; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/oss/CreatePartitionOssTableJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/oss/CreatePartitionOssTableJobFactory.java index 3d0355e9e..764571fdc 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/oss/CreatePartitionOssTableJobFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/oss/CreatePartitionOssTableJobFactory.java @@ -51,6 +51,7 @@ import com.alibaba.polardbx.gms.partition.TableLocalPartitionRecord; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.tablegroup.TableGroupRecord; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; import com.alibaba.polardbx.gms.util.LockUtil; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.CreateTablePreparedData; @@ -103,21 +104,31 @@ protected void validate() { String ttlTableName = preparedData.getLoadTableName(); TableInfoManager tableInfoManager = executionContext.getTableInfoManager(); tableInfoManager.setConnection(conn); - TableLocalPartitionRecord record = + TableLocalPartitionRecord localPartRecord = tableInfoManager.getLocalPartitionRecord(ttlTableSchema, ttlTableName); - - // not a local partition table - if (record == null) { - throw new TddlRuntimeException( - ErrorCode.ERR_INVALID_DDL_PARAMS, - MessageFormat.format("{0}.{1} is not a local partition table.", - ttlTableSchema, ttlTableName)); + TtlInfoRecord ttlInfoRecord = tableInfoManager.getTtlInfoRecord(ttlTableSchema, ttlTableName); + + String oldArchiveTableSchema = null; + String oldArchiveTableName = null; + if (ttlInfoRecord == null) { + // not a local partition table + if (localPartRecord == null) { + throw GeneralUtil.nestedException( + MessageFormat.format("{0}.{1} is not a local partition table.", + ttlTableSchema, ttlTableName)); + } + oldArchiveTableSchema = localPartRecord.getArchiveTableSchema(); + oldArchiveTableName = localPartRecord.getArchiveTableName(); + } else { + /** + * To validate + */ + oldArchiveTableSchema = ttlInfoRecord.getArcTblSchema(); + oldArchiveTableName = ttlInfoRecord.getArcTblName(); } - String oldArchiveTableSchema = record.getArchiveTableSchema(); - String oldArchiveTableName = record.getArchiveTableName(); + // already has archive table but don't allow replace it. - // already has archive table but don't allow to replace it. if (oldArchiveTableSchema != null || oldArchiveTableName != null) { boolean allowReplace = executionContext.getParamManager().getBoolean(ConnectionParams.ALLOW_REPLACE_ARCHIVE_TABLE); @@ -130,6 +141,7 @@ protected void validate() { ttlTableSchema, ttlTableName, oldArchiveTableSchema, oldArchiveTableName)); } } + } catch (Throwable t) { throw new TddlNestableRuntimeException(t); } @@ -193,7 +205,8 @@ protected ExecutableDdlJob doCreate() { // table partition info CreateTableAddTablesPartitionInfoMetaTask addPartitionInfoTask = new CreateTableAddTablesPartitionInfoMetaTask(schemaName, logicalTableName, physicalPlanData.isTemporary(), - physicalPlanData.getTableGroupConfig(), null, null, null, null, true, false, autoCreateTg); + physicalPlanData.getTableGroupConfig(), null, null, + null, false, true, null, null, false, autoCreateTg); taskList.add(addPartitionInfoTask); // mysql physical ddl task @@ -264,9 +277,13 @@ protected ExecutableDdlJob doCreate() { && preparedData.getLoadTableSchema() != null && preparedData.getLoadTableName() != null) { BindingArchiveTableMetaTask bindingArchiveTableMetaTask = new BindingArchiveTableMetaTask( - schemaName, logicalTableName, - preparedData.getLoadTableSchema(), preparedData.getLoadTableName(), // load table as source table - schemaName, logicalTableName, // target table as archive table + schemaName, + logicalTableName, + preparedData.getLoadTableSchema(), + preparedData.getLoadTableName(), // load table as source table + schemaName, + logicalTableName,// target table as archive table + tableEngine.name(), archiveMode ); taskList.add(bindingArchiveTableMetaTask); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/AlterTableModifyTtlJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/AlterTableModifyTtlJobFactory.java new file mode 100644 index 000000000..993ce9031 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/AlterTableModifyTtlJobFactory.java @@ -0,0 +1,208 @@ +package com.alibaba.polardbx.executor.ddl.job.factory.ttl; + +import com.alibaba.polardbx.common.model.Group; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.ddl.job.task.basic.AddTtlInfoTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.AlterTtlInfoTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcAlterTableModifyTtlTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlInfoValidateTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlMetaValidationUtil; +import org.apache.calcite.rel.core.DDL; +import org.apache.calcite.sql.SqlAlterTable; +import org.apache.calcite.sql.SqlAlterTableModifyTtlOptions; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlTimeToLiveExpr; +import org.apache.calcite.sql.SqlTimeToLiveJobExpr; +import org.apache.calcite.sql.dialect.MysqlSqlDialect; +import org.apache.calcite.sql.pretty.SqlPrettyWriter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author chenghui.lch + */ +public class AlterTableModifyTtlJobFactory extends DdlJobFactory { + + private DDL ddl; + private SqlAlterTable sqlAlterTableAst; + private String schemaName; + private String primaryTableName; + private ExecutionContext executionContext; + + private boolean hasTtlInfo = false; + private TtlDefinitionInfo currTtlInfo; + private TtlDefinitionInfo newTtlInfo; + + public AlterTableModifyTtlJobFactory(String schemaName, + String primaryTableName, + DDL ddl, + SqlAlterTable sqlAlterTable, + ExecutionContext executionContext) { + this.schemaName = schemaName; + this.primaryTableName = primaryTableName; + this.ddl = ddl; + this.sqlAlterTableAst = sqlAlterTable; + this.executionContext = executionContext; + } + + @Override + protected void validate() { + + final TableMeta primaryTableMeta = + OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(primaryTableName); + + SqlAlterTableModifyTtlOptions modifyTtlOptions = + (SqlAlterTableModifyTtlOptions) this.sqlAlterTableAst.getAlters().get(0); + String ttlEnableStr = modifyTtlOptions.getTtlEnable(); + SqlNode ttlExpr = modifyTtlOptions.getTtlExpr(); + SqlNode ttlJobExpr = modifyTtlOptions.getTtlJob(); + String archiveTableSchema = modifyTtlOptions.getArchiveTableSchema(); + String archiveTableName = modifyTtlOptions.getArchiveTableName(); + String archiveKind = modifyTtlOptions.getArchiveKind(); + + Integer arcPreAllocate = modifyTtlOptions.getArcPreAllocate(); + Integer arcPostAllocate = modifyTtlOptions.getArcPostAllocate(); + + List pkColMetas = primaryTableMeta.getPrimaryKey().stream().collect(Collectors.toList()); + List pkColNames = new ArrayList<>(); + for (int i = 0; i < pkColMetas.size(); i++) { + ColumnMeta pkCm = pkColMetas.get(i); + pkColNames.add(pkCm.getName()); + } + currTtlInfo = primaryTableMeta.getTtlDefinitionInfo(); + hasTtlInfo = currTtlInfo != null; + + newTtlInfo = null; + if (hasTtlInfo) { + Integer arcPreAllocateVal = currTtlInfo.getTtlInfoRecord().getArcPrePartCnt(); + if (arcPreAllocate != null) { + arcPreAllocateVal = arcPreAllocate; + } + if (arcPreAllocateVal <= 0) { + arcPreAllocateVal = TtlConfigUtil.getPreBuiltPartCntForCreatColumnarIndex(); + } + + Integer arcPostAllocateVal = currTtlInfo.getTtlInfoRecord().getArcPostPartCnt(); + if (arcPostAllocate != null) { + arcPostAllocateVal = arcPostAllocate; + } + if (arcPostAllocateVal <= 0) { + arcPostAllocateVal = TtlConfigUtil.getPostBuiltPartCntForCreateColumnarIndex(); + } + + newTtlInfo = TtlDefinitionInfo.buildModifiedTtlInfo( + currTtlInfo, + schemaName, + primaryTableName, + ttlEnableStr, + (SqlTimeToLiveExpr) ttlExpr, + (SqlTimeToLiveJobExpr) ttlJobExpr, + archiveKind, + archiveTableSchema, + archiveTableName, + arcPreAllocateVal, + arcPostAllocateVal, + pkColNames, + primaryTableMeta, + executionContext + ); + } else { + + Integer arcPreAllocateVal = TtlConfigUtil.getPreBuiltPartCntForCreatColumnarIndex(); + if (arcPreAllocate != null) { + arcPreAllocateVal = arcPreAllocate; + } + + Integer arcPostAllocateVal = TtlConfigUtil.getPostBuiltPartCntForCreateColumnarIndex(); + if (arcPostAllocate != null) { + arcPostAllocateVal = arcPostAllocate; + } + + newTtlInfo = TtlDefinitionInfo.createNewTtlInfo( + schemaName, + primaryTableName, + ttlEnableStr, + (SqlTimeToLiveExpr) ttlExpr, + (SqlTimeToLiveJobExpr) ttlJobExpr, + archiveKind, + archiveTableSchema, + archiveTableName, + arcPreAllocateVal, + arcPostAllocateVal, + pkColNames, + primaryTableMeta, + null, + null, + executionContext + ); + } + + TtlMetaValidationUtil.validateTtlInfoChange(currTtlInfo, newTtlInfo, executionContext); + + } + + @Override + protected ExecutableDdlJob doCreate() { + return buildJobInner(); + } + + protected ExecutableDdlJob buildJobInner() { + + ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); + List taskList = new ArrayList<>(); + + if (!hasTtlInfo) { + AddTtlInfoTask addTtlInfoTask = new AddTtlInfoTask(newTtlInfo); + taskList.add(addTtlInfoTask); + } else { + AlterTtlInfoTask alterTtlInfoTask = new AlterTtlInfoTask(currTtlInfo, newTtlInfo); + taskList.add(alterTtlInfoTask); + } + + TableSyncTask tableSyncTask = new TableSyncTask(schemaName, primaryTableName); + taskList.add(tableSyncTask); + + CdcAlterTableModifyTtlTask cdcModifyTtlTask = new CdcAlterTableModifyTtlTask(schemaName, primaryTableName); + taskList.add(cdcModifyTtlTask); + + executableDdlJob.addSequentialTasks(taskList); + + return executableDdlJob; + } + + @Override + protected void excludeResources(Set resources) { + resources.add(concatWithDot(schemaName, primaryTableName)); + +// Optional> archive = CheckOSSArchiveUtil.getArchive(schemaName, primaryTableName); +// archive.ifPresent(x -> { +// resources.add(concatWithDot(x.getKey(), x.getValue())); +// }); + } + + @Override + protected void sharedResources(Set resources) { +// // add forbid drop read lock if the 'expire' ddl is cross schema +// Optional> archive = CheckOSSArchiveUtil.getArchive(schemaName, primaryTableName); +// archive.ifPresent(x -> { +// if (!x.getKey().equalsIgnoreCase(schemaName)) { +// resources.add(LockUtil.genForbidDropResourceName(x.getKey())); +// } +// }); + } + +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/AlterTableRemoveTtlJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/AlterTableRemoveTtlJobFactory.java new file mode 100644 index 000000000..548f441f8 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/AlterTableRemoveTtlJobFactory.java @@ -0,0 +1,125 @@ +package com.alibaba.polardbx.executor.ddl.job.factory.ttl; + +import com.alibaba.polardbx.executor.ddl.job.task.basic.AddTtlInfoTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.AlterTtlInfoTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.RemoveLocalPartitionTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.RemoveTtlInfoTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcAlterTableModifyTtlTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcAlterTableRemoveTtlTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlMetaValidationUtil; +import org.apache.calcite.rel.core.DDL; +import org.apache.calcite.sql.SqlAlterTable; +import org.apache.calcite.sql.SqlAlterTableModifyTtlOptions; +import org.apache.calcite.sql.SqlAlterTableRemoveTtlOptions; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlTimeToLiveExpr; +import org.apache.calcite.sql.SqlTimeToLiveJobExpr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author chenghui.lch + */ +public class AlterTableRemoveTtlJobFactory extends DdlJobFactory { + + private DDL ddl; + private SqlAlterTable sqlAlterTableAst; + private String schemaName; + private String primaryTableName; + private ExecutionContext executionContext; + + private boolean hasTtlInfo = false; + private TtlDefinitionInfo currTtlInfo; + + public AlterTableRemoveTtlJobFactory(String schemaName, + String primaryTableName, + DDL ddl, + SqlAlterTable sqlAlterTable, + ExecutionContext executionContext) { + this.schemaName = schemaName; + this.primaryTableName = primaryTableName; + this.ddl = ddl; + this.sqlAlterTableAst = sqlAlterTable; + this.executionContext = executionContext; + } + + @Override + protected void validate() { + + final TableMeta primaryTableMeta = + OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(primaryTableName); + + SqlAlterTableRemoveTtlOptions removeTtlOptionsOption = + (SqlAlterTableRemoveTtlOptions) this.sqlAlterTableAst.getAlters().get(0); + assert removeTtlOptionsOption != null; + currTtlInfo = primaryTableMeta.getTtlDefinitionInfo(); + hasTtlInfo = currTtlInfo != null; + if (hasTtlInfo) { + boolean usingArchving = currTtlInfo.needPerformExpiredDataArchiving(); + if (usingArchving) { + String arcTblSchema = currTtlInfo.getArchiveTableSchema(); + String arcTblName = currTtlInfo.getArchiveTableName(); + throw new TtlJobRuntimeException( + String.format( + "Failed to remove ttl because ttl table `%s`.`%s` has bound to the archive table `%s`.%s", + schemaName, primaryTableName, arcTblSchema, arcTblName)); + } + + } + + } + + @Override + protected ExecutableDdlJob doCreate() { + return buildJobInner(); + } + + protected ExecutableDdlJob buildJobInner() { + + ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); + List taskList = new ArrayList<>(); + taskList.add(new RemoveTtlInfoTask(schemaName, primaryTableName)); + taskList.add(new TableSyncTask(schemaName, primaryTableName)); + CdcAlterTableRemoveTtlTask cdcRemoveTtlTask = new CdcAlterTableRemoveTtlTask(schemaName, primaryTableName); + taskList.add(cdcRemoveTtlTask); + executableDdlJob.addSequentialTasks(taskList); + + return executableDdlJob; + } + + @Override + protected void excludeResources(Set resources) { + resources.add(concatWithDot(schemaName, primaryTableName)); + +// Optional> archive = CheckOSSArchiveUtil.getArchive(schemaName, primaryTableName); +// archive.ifPresent(x -> { +// resources.add(concatWithDot(x.getKey(), x.getValue())); +// }); + } + + @Override + protected void sharedResources(Set resources) { +// // add forbid drop read lock if the 'expire' ddl is cross schema +// Optional> archive = CheckOSSArchiveUtil.getArchive(schemaName, primaryTableName); +// archive.ifPresent(x -> { +// if (!x.getKey().equalsIgnoreCase(schemaName)) { +// resources.add(LockUtil.genForbidDropResourceName(x.getKey())); +// } +// }); + } + +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/ArchivePartitionJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/ArchivePartitionJobFactory.java new file mode 100644 index 000000000..c23b652f6 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/ArchivePartitionJobFactory.java @@ -0,0 +1,212 @@ +package com.alibaba.polardbx.executor.ddl.job.factory.ttl; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.oss.OssArchiveCheckTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.oss.OssTableArchivePartitionTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.oss.UpdateFileCommitTsTask; +import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.ArchivePartitionValidateTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.UpdateTtlTmpTablePartStateTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; +import com.alibaba.polardbx.executor.utils.StringUtils; +import com.alibaba.polardbx.gms.partition.TablePartitionRecord; +import com.alibaba.polardbx.gms.ttl.TtlPartArcState; +import com.alibaba.polardbx.gms.util.LockUtil; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.archive.CheckOSSArchiveUtil; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.alibaba.polardbx.executor.ddl.newengine.meta.DdlJobManager.ID_GENERATOR; +import static org.apache.calcite.sql.SqlIdentifier.surroundWithBacktick; + +/** + * @author wumu + */ +public class ArchivePartitionJobFactory extends DdlJobFactory { + + private final String schemaName; + private final String ossTableName; + private final String archiveTmpTableSchema; + private final String archiveTmpTableName; + private final List designatedPartitionNameList; + private final List firstLevelPartitionNameList; + private final ExecutionContext executionContext; + + public ArchivePartitionJobFactory(String schemaName, + String ossTableName, + String archiveTmpTableSchema, + String archiveTmpTableName, + List designatedPartitionNameList, + List firstLevelPartitionNameList, + ExecutionContext executionContext) { + this.schemaName = schemaName; + this.ossTableName = ossTableName; + this.archiveTmpTableSchema = archiveTmpTableSchema; + this.archiveTmpTableName = archiveTmpTableName; + this.designatedPartitionNameList = designatedPartitionNameList; + this.firstLevelPartitionNameList = firstLevelPartitionNameList; + this.executionContext = executionContext; + } + + @Override + protected void validate() { + CheckOSSArchiveUtil.checkColumnConsistency(schemaName, ossTableName, archiveTmpTableSchema, + archiveTmpTableName); + + List partNamesAndSubPartNamesToBeUpdateArcState = new ArrayList<>(); + partNamesAndSubPartNamesToBeUpdateArcState.addAll(firstLevelPartitionNameList); + partNamesAndSubPartNamesToBeUpdateArcState.addAll(designatedPartitionNameList); + CheckOSSArchiveUtil.validateArchivePartitions(archiveTmpTableSchema, archiveTmpTableName, + partNamesAndSubPartNamesToBeUpdateArcState, executionContext); + } + + @Override + protected ExecutableDdlJob doCreate() { + SchemaManager sm = OptimizerContext.getContext(archiveTmpTableSchema).getLatestSchemaManager(); + final TableMeta ossTableMeta = sm.getTable(ossTableName); + + List taskList = new ArrayList<>(); + Map versionMap = new HashMap<>(1); + versionMap.put(ossTableName, ossTableMeta.getVersion()); + ValidateTableVersionTask validateTableVersionTask = new ValidateTableVersionTask(schemaName, versionMap); + taskList.add(validateTableVersionTask); + + List partNamesAndSubPartNamesToBeUpdateArcState = new ArrayList<>(); + partNamesAndSubPartNamesToBeUpdateArcState.addAll(firstLevelPartitionNameList); + partNamesAndSubPartNamesToBeUpdateArcState.addAll(designatedPartitionNameList); + ArchivePartitionValidateTask archivePartitionValidateTask = + new ArchivePartitionValidateTask(schemaName, ossTableName, archiveTmpTableSchema, archiveTmpTableName, + partNamesAndSubPartNamesToBeUpdateArcState); + taskList.add(archivePartitionValidateTask); + + TableMeta arcTmpTblMeta = + OptimizerContext.getContext(archiveTmpTableSchema).getLatestSchemaManager().getTable(archiveTmpTableName); + PartitionInfo arcTmpTblPartInfo = arcTmpTblMeta.getPartitionInfo(); + + List partAndSubPartNamesForReadyState = new ArrayList<>(); + List partAndSubPartNamesForReReadyState = new ArrayList<>(); + + for (int i = 0; i < firstLevelPartitionNameList.size(); i++) { + String firstLevelPartName = firstLevelPartitionNameList.get(i); + PartitionSpec firstLevelPartSpec = + arcTmpTblPartInfo.getPartSpecSearcher().getPartSpecByPartName(firstLevelPartName); + if (firstLevelPartSpec.getArcState() == TtlPartArcState.ARC_STATE_READY.getArcState()) { + partAndSubPartNamesForReadyState.add(firstLevelPartName); + } else if (firstLevelPartSpec.getArcState() == TtlPartArcState.ARC_STATE_REREADY.getArcState()) { + partAndSubPartNamesForReReadyState.add(firstLevelPartName); + } + } + + for (int i = 0; i < designatedPartitionNameList.size(); i++) { + String phyPartName = designatedPartitionNameList.get(i); + PartitionSpec phyPartSpec = arcTmpTblPartInfo.getPartSpecSearcher().getPartSpecByPartName(phyPartName); + if (phyPartSpec != null) { + if (phyPartSpec.getArcState() == TtlPartArcState.ARC_STATE_READY.getArcState()) { + partAndSubPartNamesForReadyState.add(phyPartName); + } else if (phyPartSpec.getArcState() == TtlPartArcState.ARC_STATE_REREADY.getArcState()) { + partAndSubPartNamesForReReadyState.add(phyPartName); + } + } + } + + if (!partAndSubPartNamesForReadyState.isEmpty()) { + UpdateTtlTmpTablePartStateTask updateArchivingTaskForReadyState = + new UpdateTtlTmpTablePartStateTask(archiveTmpTableSchema, archiveTmpTableName, + partAndSubPartNamesForReadyState, + TtlPartArcState.ARC_STATE_READY.getArcState(), TtlPartArcState.ARC_STATE_ARCHIVING.getArcState()); + taskList.add(updateArchivingTaskForReadyState); + } + + if (!partAndSubPartNamesForReReadyState.isEmpty()) { + UpdateTtlTmpTablePartStateTask updateArchivingTaskForReReady = + new UpdateTtlTmpTablePartStateTask(archiveTmpTableSchema, archiveTmpTableName, + partAndSubPartNamesForReReadyState, + TtlPartArcState.ARC_STATE_REREADY.getArcState(), TtlPartArcState.ARC_STATE_ARCHIVING.getArcState()); + taskList.add(updateArchivingTaskForReReady); + } + + TableSyncTask archivingSyncTask = new TableSyncTask(archiveTmpTableSchema, archiveTmpTableName); + taskList.add(archivingSyncTask); + + // build back-fill tasks for all expired partitions + Engine targetTableEngine = ossTableMeta.getEngine(); + List archiveOssTableDataTaskIdList = new ArrayList<>(); + + OssTableArchivePartitionTask ossTableArchivePartitionTask = new OssTableArchivePartitionTask( + schemaName, ossTableName, + archiveTmpTableSchema, archiveTmpTableName, + designatedPartitionNameList, targetTableEngine + ); + ossTableArchivePartitionTask.setTaskId(ID_GENERATOR.nextId()); + taskList.add(ossTableArchivePartitionTask); + archiveOssTableDataTaskIdList.add(ossTableArchivePartitionTask.getTaskId()); + + OssArchiveCheckTask ossArchiveCheckTask = new OssArchiveCheckTask( + schemaName, ossTableName, + archiveTmpTableSchema, archiveTmpTableName, + designatedPartitionNameList, ossTableArchivePartitionTask.getTaskId() + ); + + taskList.add(ossArchiveCheckTask); + + // build timestamp update task + UpdateFileCommitTsTask updateFileCommitTsTask = + new UpdateFileCommitTsTask(targetTableEngine.name(), schemaName, ossTableName, + archiveOssTableDataTaskIdList); + taskList.add(updateFileCommitTsTask); + TableSyncTask tableSyncTask = new TableSyncTask(schemaName, ossTableName); + taskList.add(tableSyncTask); + + SubJobTask subJobTask = buildTruncatePartitionsTask(); + taskList.add(subJobTask); + + UpdateTtlTmpTablePartStateTask updateArchivedTask = + new UpdateTtlTmpTablePartStateTask(archiveTmpTableSchema, archiveTmpTableName, + partNamesAndSubPartNamesToBeUpdateArcState, + TtlPartArcState.ARC_STATE_ARCHIVING.getArcState(), TtlPartArcState.ARC_STATE_ARCHIVED.getArcState()); + TableSyncTask archivedSyncTask = new TableSyncTask(archiveTmpTableSchema, archiveTmpTableName); + taskList.add(updateArchivedTask); + taskList.add(archivedSyncTask); + + ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); + executableDdlJob.addSequentialTasks(taskList); + return executableDdlJob; + } + + @Override + protected void excludeResources(Set resources) { + resources.add(concatWithDot(schemaName, ossTableName)); + + resources.add(concatWithDot(archiveTmpTableSchema, archiveTmpTableName)); + } + + @Override + protected void sharedResources(Set resources) { + // add forbid drop read lock if the 'archive' ddl is cross schema + resources.add(LockUtil.genForbidDropResourceName(archiveTmpTableSchema)); + } + + protected SubJobTask buildTruncatePartitionsTask() { + // alter table truncate partition + String sql = String.format("ALTER TABLE %s.%s TRUNCATE PARTITION %s", + surroundWithBacktick(archiveTmpTableSchema), surroundWithBacktick(archiveTmpTableName), + String.join(",", firstLevelPartitionNameList)); + SubJobTask subJobTask = new SubJobTask(archiveTmpTableSchema, sql, null); + subJobTask.setParentAcquireResource(true); + return subJobTask; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/CleanupExpiredDataJobFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/CleanupExpiredDataJobFactory.java new file mode 100644 index 000000000..6cd37ae49 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/factory/ttl/CleanupExpiredDataJobFactory.java @@ -0,0 +1,163 @@ +package com.alibaba.polardbx.executor.ddl.job.factory.ttl; + +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.common.model.Group; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.CheckAndPerformingOptiTtlTableTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.CheckAndPrepareAddPartsForCciSqlTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.CleanAndPrepareExpiredDataTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.FinishCleaningUpAndLogTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.PrepareCleanupIntervalTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlJobContext; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlJobUtil; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlTaskSqlBuilder; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import org.apache.calcite.rel.core.DDL; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @author chenghui.lch + */ +public class CleanupExpiredDataJobFactory extends DdlJobFactory { + + private DDL ddl; + private String schemaName; + private String primaryTableName; + private ExecutionContext executionContext; + + public CleanupExpiredDataJobFactory(String schemaName, + String primaryTableName, + DDL ddl, + ExecutionContext executionContext) { + this.schemaName = schemaName; + this.primaryTableName = primaryTableName; + this.ddl = ddl; + this.executionContext = executionContext; + } + + @Override + protected void validate() { +// LocalPartitionValidateTask localPartitionValidateTask = +// new LocalPartitionValidateTask(schemaName, primaryTableName); +// localPartitionValidateTask.executeImpl(executionContext); + } + + @Override + protected ExecutableDdlJob doCreate() { + return buildJobInner(); + } + + protected ExecutableDdlJob buildJobInner() { + + IRepository repository = ExecutorContext.getContext(schemaName).getTopologyHandler() + .getRepositoryHolder().get(Group.GroupType.MYSQL_JDBC.toString()); + + final TableMeta primaryTableMeta = + OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(primaryTableName); + + final TtlDefinitionInfo ttlInfo = primaryTableMeta.getTtlDefinitionInfo(); + if (ttlInfo == null) { + throw new TddlNestableRuntimeException(String.format( + "table %s.%s is not a row-level ttl table", schemaName, primaryTableName)); + } + + ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); + + List taskList = new ArrayList<>(); + String tableSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String tableName = ttlInfo.getTtlInfoRecord().getTableName(); + + TtlJobContext jobContext = TtlJobContext.buildFromTtlInfo(ttlInfo); + boolean needPerformArchivingByCci = jobContext.getTtlInfo().needPerformExpiredDataArchivingByCci(); + + PrepareCleanupIntervalTask prepareClearIntervalTask = new PrepareCleanupIntervalTask(tableSchema, tableName); + prepareClearIntervalTask.setJobContext(jobContext); + + CleanAndPrepareExpiredDataTask + clearAndPrepareExpiredDataTask = new CleanAndPrepareExpiredDataTask(tableSchema, tableName); + clearAndPrepareExpiredDataTask.setJobContext(jobContext); + + taskList.add(prepareClearIntervalTask); + taskList.add(clearAndPrepareExpiredDataTask); // perform insert-select + delete + + if (TtlConfigUtil.isEnableAutoControlOptiTblByTtlJob()) { + /** + * control optimize-table ddl-job by ttl job automatically + *
+             *     if opti-table job does not exists, auto submit;
+             *     if opti-table job exists and state is paused, auto continue ddl;
+             *     if opti-table job exists and state is running, auto wait it to finish running;
+             *     if opti-table job exists and state is not running and not paused, just ignore it.
+             * 
+ */ + + // perform a optimize table for ttl table to release data free + CheckAndPerformingOptiTtlTableTask + checkAndPerfOptiTblTask = new CheckAndPerformingOptiTtlTableTask(tableSchema, tableName); + checkAndPerfOptiTblTask.setJobContext(jobContext); + taskList.add(checkAndPerfOptiTblTask); + } + + boolean enableAutoAddPartsForArcCci = TtlConfigUtil.isEnableAutoAddPartsForArcCci(); + if (needPerformArchivingByCci && enableAutoAddPartsForArcCci) { + + /** + * add new range part for cci if need + */ + CheckAndPrepareAddPartsForCciSqlTask prepareAddPartsForCciSqlTask = + new CheckAndPrepareAddPartsForCciSqlTask(tableSchema, tableName); + + String arcTmpTableSchema = ttlInfo.getTtlInfoRecord().getArcTmpTblSchema(); + String ddlStmtForArcCciTmpTbl = + TtlTaskSqlBuilder.buildSubJobTaskNameForAddPartsFroActTmpCciBySpecifySubjobStmt(); + SubJobTask performAddPartSubJobTaskForArcCciTbl = + new SubJobTask(arcTmpTableSchema, ddlStmtForArcCciTmpTbl, ""); + performAddPartSubJobTaskForArcCciTbl.setParentAcquireResource(true); + + taskList.add(prepareAddPartsForCciSqlTask); + taskList.add(performAddPartSubJobTaskForArcCciTbl); + } + + FinishCleaningUpAndLogTask finishCleaningUpAndLogTask = new FinishCleaningUpAndLogTask(tableSchema, tableName); + finishCleaningUpAndLogTask.setJobContext(jobContext); + taskList.add(finishCleaningUpAndLogTask); + + executableDdlJob.addSequentialTasks(taskList); + + return executableDdlJob; + } + + @Override + protected void excludeResources(Set resources) { +// resources.add(concatWithDot(schemaName, primaryTableName)); +// +// Optional> archive = CheckOSSArchiveUtil.getArchive(schemaName, primaryTableName); +// archive.ifPresent(x -> { +// resources.add(concatWithDot(x.getKey(), x.getValue())); +// }); + } + + @Override + protected void sharedResources(Set resources) { +// // add forbid drop read lock if the 'expire' ddl is cross schema +// Optional> archive = CheckOSSArchiveUtil.getArchive(schemaName, primaryTableName); +// archive.ifPresent(x -> { +// if (!x.getKey().equalsIgnoreCase(schemaName)) { +// resources.add(LockUtil.genForbidDropResourceName(x.getKey())); +// } +// }); + } + +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/FileStorageBackFillAccessor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/FileStorageBackFillAccessor.java index cd9229235..725f40c34 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/FileStorageBackFillAccessor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/FileStorageBackFillAccessor.java @@ -47,30 +47,30 @@ public class FileStorageBackFillAccessor extends AbstractAccessor { + FILE_STORAGE_BACKFILL_OBJECTS + " WHERE JOB_ID = ? AND PHYSICAL_DB = ? AND PHYSICAL_TABLE = ?"; private static final String SQL_SELECT_BACKFILL_PROGRESS = - "SELECT ID,JOB_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA,INDEX_NAME,PHYSICAL_DB,PHYSICAL_TABLE,COLUMN_INDEX,PARAMETER_METHOD,`LAST_VALUE`,MAX_VALUE,STATUS,MESSAGE,SUCCESS_ROW_COUNT,START_TIME,END_TIME,EXTRA FROM " + "SELECT ID,JOB_ID,TASK_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA,INDEX_NAME,PHYSICAL_DB,PHYSICAL_TABLE,COLUMN_INDEX,PARAMETER_METHOD,`LAST_VALUE`,MAX_VALUE,STATUS,MESSAGE,SUCCESS_ROW_COUNT,START_TIME,END_TIME,EXTRA FROM " + SYSTABLE_BACKFILL_OBJECTS + " WHERE JOB_ID = ? AND PHYSICAL_DB IS NULL AND PHYSICAL_TABLE IS NULL"; private static final String SQL_SELECT_FILE_BACKFILL_OBJECT = - "SELECT ID,JOB_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA,INDEX_NAME,PHYSICAL_DB,PHYSICAL_TABLE,COLUMN_INDEX,PARAMETER_METHOD,`LAST_VALUE`,MAX_VALUE,STATUS,MESSAGE,SUCCESS_ROW_COUNT,START_TIME,END_TIME,EXTRA FROM " + "SELECT ID,JOB_ID,TASK_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA,INDEX_NAME,PHYSICAL_DB,PHYSICAL_TABLE,COLUMN_INDEX,PARAMETER_METHOD,`LAST_VALUE`,MAX_VALUE,STATUS,MESSAGE,SUCCESS_ROW_COUNT,START_TIME,END_TIME,EXTRA FROM " + FILE_STORAGE_BACKFILL_OBJECTS + " WHERE JOB_ID = ? AND PHYSICAL_DB = ? AND PHYSICAL_TABLE = ?"; private static final String SQL_INSERT_FILE_BACKFILL_OBJECT = "INSERT INTO " + FILE_STORAGE_BACKFILL_OBJECTS - + "(JOB_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA," + + "(JOB_ID,TASK_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA," + "INDEX_NAME,PHYSICAL_DB,PHYSICAL_TABLE,COLUMN_INDEX,PARAMETER_METHOD,`LAST_VALUE`,MAX_VALUE,STATUS,MESSAGE,SUCCESS_ROW_COUNT,START_TIME,END_TIME,EXTRA) " - + "VALUES(? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?, ?, ?)"; + + "VALUES(? , ? , ?, ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?, ?, ?)"; private static final String SQL_INSERT_IGNORE_FILE_BACKFILL_OBJECT = "INSERT IGNORE INTO " + FILE_STORAGE_BACKFILL_OBJECTS - + "(JOB_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA," + + "(JOB_ID,TASK_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA," + "INDEX_NAME,PHYSICAL_DB,PHYSICAL_TABLE,COLUMN_INDEX,PARAMETER_METHOD,`LAST_VALUE`,MAX_VALUE,STATUS,MESSAGE,SUCCESS_ROW_COUNT,START_TIME,END_TIME,EXTRA) " - + "VALUES(? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?, ?, ?)"; + + "VALUES(? , ? , ?, ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?, ?, ?)"; private static final String SQL_REPLACE_BACKFILL_OBJECT = "REPLACE INTO " + SYSTABLE_BACKFILL_OBJECTS - + "(JOB_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA," + + "(JOB_ID,TASK_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA," + "INDEX_NAME,PHYSICAL_DB,PHYSICAL_TABLE,COLUMN_INDEX,PARAMETER_METHOD,`LAST_VALUE`,MAX_VALUE,STATUS,MESSAGE,SUCCESS_ROW_COUNT,START_TIME,END_TIME,EXTRA) " - + "VALUES(? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?, ?, ?)"; + + "VALUES(? , ? , ? , ?, ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?, ?, ?)"; private static final String SQL_UPDATE_FILE_BACKFILL_PROGRESS = "UPDATE " + FILE_STORAGE_BACKFILL_OBJECTS @@ -78,11 +78,11 @@ public class FileStorageBackFillAccessor extends AbstractAccessor { + " WHERE `JOB_ID` = ? AND `PHYSICAL_DB` = ? AND `PHYSICAL_TABLE` = ? AND `COLUMN_INDEX` = ? "; private static final String SQL_SELECT_BACKFILL_OBJECT = - "SELECT ID,JOB_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA,INDEX_NAME,PHYSICAL_DB,PHYSICAL_TABLE,COLUMN_INDEX,PARAMETER_METHOD,`LAST_VALUE`,MAX_VALUE,STATUS,MESSAGE,SUCCESS_ROW_COUNT,START_TIME,END_TIME,EXTRA FROM " + "SELECT ID,JOB_ID,TASK_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA,INDEX_NAME,PHYSICAL_DB,PHYSICAL_TABLE,COLUMN_INDEX,PARAMETER_METHOD,`LAST_VALUE`,MAX_VALUE,STATUS,MESSAGE,SUCCESS_ROW_COUNT,START_TIME,END_TIME,EXTRA FROM " + SYSTABLE_BACKFILL_OBJECTS + " WHERE JOB_ID = ? AND PHYSICAL_DB = ? AND PHYSICAL_TABLE = ?"; private static final String SQL_SELECT_FILE_BACKFILL_OBJECT_BY_ID = - "SELECT ID,JOB_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA,INDEX_NAME,PHYSICAL_DB,PHYSICAL_TABLE,COLUMN_INDEX,PARAMETER_METHOD,`LAST_VALUE`,MAX_VALUE,STATUS,MESSAGE,SUCCESS_ROW_COUNT,START_TIME,END_TIME,EXTRA FROM " + "SELECT ID,JOB_ID,TASK_ID,TABLE_SCHEMA,TABLE_NAME,INDEX_SCHEMA,INDEX_NAME,PHYSICAL_DB,PHYSICAL_TABLE,COLUMN_INDEX,PARAMETER_METHOD,`LAST_VALUE`,MAX_VALUE,STATUS,MESSAGE,SUCCESS_ROW_COUNT,START_TIME,END_TIME,EXTRA FROM " + FILE_STORAGE_BACKFILL_OBJECTS + " WHERE JOB_ID = ? "; private static final String SQL_DELETE_FILE_BACKFILL_OBJECT_BY_ID = "DELETE FROM " diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/TableMetaChanger.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/TableMetaChanger.java index 673eb07dd..f523d348c 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/TableMetaChanger.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/TableMetaChanger.java @@ -56,6 +56,7 @@ import com.alibaba.polardbx.gms.partition.TableLocalPartitionRecord; import com.alibaba.polardbx.gms.scheduler.ScheduledJobsRecord; import com.alibaba.polardbx.gms.tablegroup.TableGroupDetailConfig; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; import com.alibaba.polardbx.optimizer.OptimizerContext; @@ -211,6 +212,7 @@ public static void changeColumnarTableMeta(Connection metaDbConnection, List droppedColumns, List updateColumns, List> changeColumns, + List> renamedIndexes, long versionId, long ddlJobId) { @@ -222,28 +224,19 @@ public static void changeColumnarTableMeta(Connection metaDbConnection, return; } - // ADD COLUMN - if (GeneralUtil.isNotEmpty(addedColumns)) { - tableInfoManager.alterColumnarTableColumns(schemaName, primaryTableName, indexes, versionId, ddlJobId, - DdlType.ALTER_TABLE_ADD_COLUMN, new ArrayList<>()); - } - - // DROP COLUMN - if (GeneralUtil.isNotEmpty(droppedColumns)) { - tableInfoManager.dropColumnarTableColumns(schemaName, primaryTableName, indexes, droppedColumns, - versionId, ddlJobId); - } + boolean isAlterTable = + GeneralUtil.isNotEmpty(addedColumns) || GeneralUtil.isNotEmpty(droppedColumns) || GeneralUtil.isNotEmpty( + updateColumns) || GeneralUtil.isNotEmpty(changeColumns); - // MODIFY COLUMN - if (GeneralUtil.isNotEmpty(updateColumns)) { + if (isAlterTable) { tableInfoManager.alterColumnarTableColumns(schemaName, primaryTableName, indexes, versionId, ddlJobId, - DdlType.ALTER_TABLE_MODIFY_COLUMN, new ArrayList<>()); + DdlType.ALTER_TABLE, changeColumns, droppedColumns); } - // CHANGE COLUMN - if (GeneralUtil.isNotEmpty(changeColumns)) { - tableInfoManager.alterColumnarTableColumns(schemaName, primaryTableName, indexes, versionId, ddlJobId, - DdlType.ALTER_TABLE_CHANGE_COLUMN, changeColumns); + boolean isRenameIndex = GeneralUtil.isNotEmpty(renamedIndexes); + if (isRenameIndex) { + tableInfoManager.renameColumnarTable(schemaName, primaryTableName, indexes, renamedIndexes, versionId, + ddlJobId); } } @@ -302,10 +295,46 @@ public static void removeColumnarTableMeta(Connection metaDbConnection, String s tableInfoManager.removeColumnarTable(schemaName, columnarTableName); } + public static void truncateColumnarTable(Connection metaDbConnection, + String schemaName, + String primaryTableName, + long versionId, + long ddlJobId) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + Set> indexes = tableInfoManager.queryCci(schemaName, primaryTableName); + if (GeneralUtil.isEmpty(indexes)) { + return; + } + tableInfoManager.truncateColumnarTable(schemaName, primaryTableName, indexes, versionId, ddlJobId, + DdlType.TRUNCATE_TABLE); + } + + public static void renameColumnarTablesMeta(Connection metaDbConn, String schemaName, + List oldTableNames, List newTableNames, + List versionIds, long ddlJobId) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConn); + + List> tableRenameMap = new ArrayList<>(); + + for (int i = 0; i < oldTableNames.size(); i++) { + tableRenameMap.add(new Pair<>(oldTableNames.get(i), newTableNames.get(i))); + } + + tableInfoManager.renameColumnarTables(schemaName, tableRenameMap, versionIds, ddlJobId); + } + public static void renameColumnarTableMeta(Connection metaDbConn, String schemaName, String primaryTableName, String newPrimaryTableName, long versionId, long ddlJobId) { TableInfoManager tableInfoManager = new TableInfoManager(); tableInfoManager.setConnection(metaDbConn); + + Set> indexes = tableInfoManager.queryCci(schemaName, primaryTableName); + if (GeneralUtil.isEmpty(indexes)) { + return; + } + tableInfoManager.renameColumnarTable(schemaName, primaryTableName, newPrimaryTableName, versionId, ddlJobId); } @@ -348,12 +377,6 @@ public static void addOssFileMeta(Connection metaDbConn, String tableSchema, Str tableInfoManager.addOssFile(tableSchema, tableName, filesRecord); } - public static void addOssFileWithTso(Connection metaDbConn, String tableSchema, String tableName, - FilesRecord filesRecord) { - TableInfoManager tableInfoManager = new TableInfoManager(); - tableInfoManager.setConnection(metaDbConn); - tableInfoManager.addOssFileWithTso(tableSchema, tableName, filesRecord); - } public static void changeOssFile(Connection metaDbConn, Long primaryKey, Long fileSize) { changeOssFile(metaDbConn, primaryKey, new byte[] {}, fileSize, 0L); @@ -424,14 +447,6 @@ public static void validOssColumnMeta(Connection metaDbConn, Long taskId, String tableInfoManager.validOSSColumnsMeta(taskId, tableSchema, tableName); } - public static void updateArchiveTable(Connection metaDbConnection, - String schemaName, String tableName, - String archiveTableSchema, String archiveTableName) { - TableInfoManager tableInfoManager = new TableInfoManager(); - tableInfoManager.setConnection(metaDbConnection); - tableInfoManager.updateArchiveTable(schemaName, tableName, archiveTableSchema, archiveTableName); - } - public static PhyInfoSchemaContext buildPhyInfoSchemaContext(String schemaName, String logicalTableName, String dbIndex, String phyTableName, SequenceBean sequenceBean, @@ -584,6 +599,7 @@ public static void removeTableMeta(Connection metaDbConnection, String schemaNam if (sequenceRecord != null) { SequenceManagerProxy.getInstance().invalidate(schemaName, sequenceBean.getName()); } + } public static void removeTableMetaWithoutNotify(Connection metaDbConnection, String schemaName, @@ -1043,7 +1059,7 @@ public static void changeTableMeta(Connection metaDbConnection, String schemaNam if (GeneralUtil.isNotEmpty(indexes)) { // columns, indexes changeCciRelatedMeta(metaDbConnection, tableInfoManager, schemaName, logicalTableName, phyInfoSchemaContext, - addedColumns, droppedColumns, changedColumns); + addedColumns, droppedColumns, changedColumns, renamedIndexes); } } @@ -1053,7 +1069,8 @@ public static void changeCciRelatedMeta(Connection metaDbConnection, PhyInfoSchemaContext context, List addedColumns, List droppedColumns, - List> changeColumns) { + List> changeColumns, + List> renamedIndexes) { Set> columnarIndexes = tableInfoManager.queryCci(schemaName, logicalTableName); List indexNames = columnarIndexes.stream().map(Pair::getValue).collect(Collectors.toList()); @@ -1111,7 +1128,18 @@ public static void changeCciRelatedMeta(Connection metaDbConnection, } // CHANGE COLUMNS TABLE - tableInfoManager.changeColumnarIndexTableColumns(indexNames, schemaName, logicalTableName, changeColumns); + tableInfoManager.changeColumnarIndexTableColumns(indexNames, schemaName, logicalTableName); + + // RENAME CCI + if (GeneralUtil.isNotEmpty(renamedIndexes)) { + for (Pair renamedIndex : renamedIndexes) { + String oldIndexName = renamedIndex.getValue(); + String newIndexName = renamedIndex.getKey(); + if (indexNames.stream().anyMatch(indexName -> indexName.equalsIgnoreCase(oldIndexName))) { + tableInfoManager.renameColumnarTable(schemaName, oldIndexName, newIndexName); + } + } + } } public static void changeForeignKeyRefIndex(Connection metaDbConnection, TableInfoManager tableInfoManager, @@ -1701,11 +1729,6 @@ public static void removePartitionInfoMeta(Connection metaDbConn, String schemaN public static void truncateTableWithRecycleBin(String schemaName, String tableName, String binTableName, String tmpTableName, Connection metaDbConn, ExecutionContext executionContext) { - String tableListDataId = MetaDbDataIdBuilder.getTableListDataId(schemaName); - String tableDataId = MetaDbDataIdBuilder.getTableDataId(schemaName, tableName); - String binTableDataId = MetaDbDataIdBuilder.getTableDataId(schemaName, binTableName); - String tmpTableDataId = MetaDbDataIdBuilder.getTableDataId(schemaName, tmpTableName); - TableRule tableRule = OptimizerContext.getContext(schemaName).getRuleManager().getTableRule(tableName); TableRule tmpTableRule = OptimizerContext.getContext(schemaName).getRuleManager().getTableRule(tmpTableName); String tbNamePattern = tableRule.getTbNamePattern(); @@ -1713,33 +1736,27 @@ public static void truncateTableWithRecycleBin(String schemaName, String tableNa // Rename sequence if exists. SequenceBaseRecord sequenceRecord = null; + SequenceBaseRecord sequenceRecordTmp = null; + // for seq rename primary to bin table name SequenceBean sequenceBean = SequenceMetaChanger.renameSequenceIfExists(metaDbConn, schemaName, tableName, binTableName); if (sequenceBean != null) { sequenceRecord = SequenceUtil.convert(sequenceBean, schemaName, executionContext); } + // for seq rename tmp to primary table name + SequenceBean sequenceBeanTmp = + SequenceMetaChanger.renameSequenceIfExists(metaDbConn, schemaName, tmpTableName, tableName); + if (sequenceBeanTmp != null) { + sequenceRecordTmp = SequenceUtil.convert(sequenceBeanTmp, schemaName, executionContext); + } + TableInfoManager tableInfoManager = new TableInfoManager(); tableInfoManager.setConnection(metaDbConn); // Switch the tables. tableInfoManager.renameTable(schemaName, tableName, binTableName, tbNamePattern, sequenceRecord); - tableInfoManager.renameTable(schemaName, tmpTableName, tableName, tmpTbNamePattern, null); - - CONFIG_MANAGER.unregister(tmpTableDataId, metaDbConn); - CONFIG_MANAGER.register(binTableDataId, metaDbConn); - - try { - TableInfoManager.updateTableVersion(schemaName, tableName, metaDbConn); - TableInfoManager.updateTableVersion(schemaName, binTableName, metaDbConn); - } catch (SQLException e) { - throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, e.getMessage()); - } - - CONFIG_MANAGER.notify(tableDataId, metaDbConn); - CONFIG_MANAGER.notify(binTableDataId, metaDbConn); - - CONFIG_MANAGER.notify(tableListDataId, metaDbConn); + tableInfoManager.renameTable(schemaName, tmpTableName, tableName, tmpTbNamePattern, sequenceRecordTmp); } public static void afterTruncatingTableWithRecycleBin(String schemaName, String tableName, String binTableName) { @@ -1833,6 +1850,49 @@ public static void addLocalPartitionMeta(Connection metaDbConnection, tableInfoManager.addLocalPartitionRecord(localPartitionRecord); } + public static void addTtlInfoMeta(Connection metaDbConnection, + TtlInfoRecord ttlInfoRecord) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + tableInfoManager.insertTtlInfoRecord(ttlInfoRecord); + } + + public static void alterTtlInfoMeta(Connection metaDbConnection, + TtlInfoRecord ttlInfoRecord, + String tblSchema, String tblName) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + tableInfoManager.updateTtlInfoRecord(ttlInfoRecord, tblSchema, tblName); + } + + public static void updateArchiveTable(Connection metaDbConnection, + String ttlSchemaName, String ttlTableName, + String archiveTableSchema, String archiveTableName) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + tableInfoManager.updateArchiveTable(ttlSchemaName, ttlTableName, archiveTableSchema, archiveTableName); + } + + public static void renameTtlTableForTtlInfo(Connection metaDbConnection, + String oldTtlSchemaName, String oldTtlTableName, + String newTtlSchemaName, String newTtlTableName) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + tableInfoManager.renameTtlTableForTtlInfo(newTtlSchemaName, newTtlTableName, oldTtlSchemaName, oldTtlTableName); + } + + public static void updateArchiveTableForTtlInfo(Connection metaDbConnection, + Integer arcKind, + String ttlSchemaName, String ttlTableName, + String archiveTableSchema, String archiveTableName, + String arcTmpTblSchemaName, String arcTmpTblName) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + tableInfoManager.updateArchiveTableForTtlInfo(arcKind, archiveTableSchema, archiveTableName, + arcTmpTblSchemaName, arcTmpTblName, ttlSchemaName, + ttlTableName); + } + public static void addScheduledJob(Connection metaDbConnection, ScheduledJobsRecord scheduledJobsRecord) { TableInfoManager tableInfoManager = new TableInfoManager(); @@ -1840,11 +1900,11 @@ public static void addScheduledJob(Connection metaDbConnection, tableInfoManager.addScheduledJob(scheduledJobsRecord); } - public static void replaceScheduledJob(Connection metaDbConnection, - ScheduledJobsRecord scheduledJobsRecord) { + public static void updateScheduledJob(Connection metaDbConnection, + ScheduledJobsRecord scheduledJobsRecord) { TableInfoManager tableInfoManager = new TableInfoManager(); tableInfoManager.setConnection(metaDbConnection); - tableInfoManager.replaceScheduledJob(scheduledJobsRecord); + tableInfoManager.updateScheduledJobsRecordByScheduleId(scheduledJobsRecord); } public static void removeLocalPartitionMeta(Connection metaDbConnection, @@ -1855,6 +1915,14 @@ public static void removeLocalPartitionMeta(Connection metaDbConnection, tableInfoManager.removeLocalPartitionRecord(schemaName, tableName); } + public static void removeTtlInfoMeta(Connection metaDbConnection, + String schemaName, + String tableName) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + tableInfoManager.removeTtlInfoRecord(schemaName, tableName); + } + public static void removeScheduledJobs(Connection metaDbConnection, String schemaName, String tableName) { @@ -1863,6 +1931,14 @@ public static void removeScheduledJobs(Connection metaDbConnection, tableInfoManager.removeScheduledJobRecord(schemaName, tableName); } + public static void removeTtlFiredScheduledJobs(Connection metaDbConnection, + String schemaName, + String tableName) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + tableInfoManager.removeTtlFiredScheduledJobRecords(schemaName, tableName); + } + public static void endAlterColumnDefaultValue(Connection metaDbConn, String schema, String table, String column) { TableInfoManager tableInfoManager = new TableInfoManager(); tableInfoManager.setConnection(metaDbConn); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/misc/RepartitionMetaChanger.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/misc/RepartitionMetaChanger.java index 3ba670001..71cc53daf 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/misc/RepartitionMetaChanger.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/misc/RepartitionMetaChanger.java @@ -18,7 +18,15 @@ import com.alibaba.polardbx.common.ddl.foreignkey.ForeignKeyData; import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.ddl.job.meta.GsiMetaChanger; +import com.alibaba.polardbx.executor.ddl.job.meta.TableMetaChanger; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.CheckCciMetaTask; +import com.alibaba.polardbx.executor.gsi.GsiUtils; import com.alibaba.polardbx.gms.metadb.table.ColumnsRecord; +import com.alibaba.polardbx.gms.metadb.table.IndexStatus; import com.alibaba.polardbx.gms.metadb.table.IndexesRecord; import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; import com.alibaba.polardbx.gms.metadb.table.TablesExtRecord; @@ -30,9 +38,13 @@ import org.apache.commons.lang3.StringUtils; import java.sql.Connection; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; import static com.alibaba.polardbx.optimizer.config.table.GsiMetaManager.TableType.BROADCAST; import static com.alibaba.polardbx.optimizer.config.table.GsiMetaManager.TableType.GSI; @@ -262,7 +274,9 @@ public static void alterTaleModifyColumnCutOver(Connection metaDbConn, Map tableNameMap, boolean autoPartition, boolean single, - boolean broadcast) { + boolean broadcast, + long versionId, + long jobId) { // 1. cut over table_partitions meta and local indexes meta // 2. cut over global indexes meta // 3. cut over columns meta @@ -272,12 +286,12 @@ public static void alterTaleModifyColumnCutOver(Connection metaDbConn, // index table cutOver(metaDbConn, schemaName, tableName, newTableName, false, false, false, true); cutOverIndexes(metaDbConn, schemaName, logicalTableName, tableName, newTableName); - cutOverColumns(metaDbConn, schemaName, tableName, newTableName); + cutOverColumns(metaDbConn, schemaName, tableName, newTableName, versionId, jobId); } else { // primary table cutOver(metaDbConn, schemaName, tableName, newTableName, single, broadcast, autoPartition, false); - cutOverColumns(metaDbConn, schemaName, tableName, newTableName); + cutOverColumns(metaDbConn, schemaName, tableName, newTableName, versionId, jobId); } }); } @@ -338,7 +352,9 @@ public static void cutOverIndexes(Connection metaDbConn, public static void cutOverColumns(Connection metaDbConn, final String schemaName, final String sourceTableName, - final String targetTableName) { + final String targetTableName, + long versionId, + long jobId) { TableInfoManager tableInfoManager = new TableInfoManager(); tableInfoManager.setConnection(metaDbConn); @@ -374,8 +390,74 @@ public static void cutOverColumns(Connection metaDbConn, tableInfoManager.alterModifyColumnCutOver(schemaName, targetTableName, sourceTableName); tableInfoManager.alterModifyColumnCutOver(schemaName, random, targetTableName); + // add evolution record for cci + Set> columnarIndexes = tableInfoManager.queryCci(schemaName, sourceTableName); + if (GeneralUtil.isNotEmpty(columnarIndexes)) { + List indexNames = columnarIndexes.stream().map(Pair::getValue).collect(Collectors.toList()); + List addColumns = + targetTableColumns.stream() + .filter(column -> sourceTableColumns.stream().noneMatch( + srcColumn -> CheckCciMetaTask.equalsColumnRecord(column, srcColumn))) + .collect(Collectors.toList()).stream().map(c -> c.columnName).collect(Collectors.toList()); + List dropColumns = + sourceTableColumns.stream() + .filter(column -> targetTableColumns.stream().noneMatch( + srcColumn -> CheckCciMetaTask.equalsColumnRecord(column, srcColumn))) + .collect(Collectors.toList()).stream().map(c -> c.columnName).collect(Collectors.toList()); + Map isNullable = new HashMap<>(); + for (ColumnsRecord columnsRecord : targetTableColumns) { + isNullable.put(columnsRecord.columnName, columnsRecord.isNullable); + } + // columns, indexes + changeCciRelatedMeta(metaDbConn, tableInfoManager, schemaName, sourceTableName, indexNames, addColumns, + dropColumns, isNullable); + + TableMetaChanger.changeColumnarTableMeta(metaDbConn, schemaName, sourceTableName, addColumns, + dropColumns, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), versionId, jobId); + } + } finally { tableInfoManager.setConnection(null); } } + + public static void changeCciRelatedMeta(Connection metaDbConnection, TableInfoManager tableInfoManager, + String schemaName, + String logicalTableName, List indexNames, List addColumns, + List dropColumns, Map isNullable) { + + for (String indexName : indexNames) { + final GsiMetaManager.GsiIndexMetaBean gsiIndexMetaBean = + ExecutorContext + .getContext(schemaName) + .getGsiManager() + .getGsiMetaManager() + .getIndexMeta(schemaName, logicalTableName, indexName, IndexStatus.ALL); + + final int seqInIndex = + gsiIndexMetaBean.indexColumns.size() + gsiIndexMetaBean.coveringColumns.size() + 1; + + for (String column : dropColumns) { + ExecutorContext + .getContext(schemaName) + .getGsiManager() + .getGsiMetaManager() + .removeColumnMeta(metaDbConnection, schemaName, logicalTableName, indexName, column); + } + + final List indexRecords = + GsiUtils.buildIndexMetaByAddColumns( + addColumns, + schemaName, + logicalTableName, + indexName, + seqInIndex, + IndexStatus.PUBLIC, + isNullable + ); + GsiMetaChanger.addIndexColumnMeta(metaDbConnection, schemaName, logicalTableName, indexRecords); + + tableInfoManager.changeColumnarIndexTableColumns(indexNames, schemaName, logicalTableName); + } + } } \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/misc/TruncateMetaChanger.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/misc/TruncateMetaChanger.java index 32a2c4ae2..0dfa80453 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/misc/TruncateMetaChanger.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/meta/misc/TruncateMetaChanger.java @@ -72,12 +72,10 @@ public static void doCutOver( long newVersion = Math.max(sourceTableExt.version, targetTableExt.version) + 1; - tableInfoManager - .alterTableExtName(schemaName, sourceTableName, random); - tableInfoManager - .alterTableExtName(schemaName, targetTableName, sourceTableName); - tableInfoManager - .alterTableExtName(schemaName, random, targetTableName); + tableInfoManager.alterTableExtNameAndIndexes(schemaName, sourceTableName, random); + tableInfoManager.alterTableExtNameAndIndexes(schemaName, targetTableName, sourceTableName); + tableInfoManager.alterTableExtNameAndIndexes(schemaName, random, targetTableName); + tableInfoManager.updateTablesExtVersion(schemaName, sourceTableName, newVersion); tableInfoManager.updateTablesExtVersion(schemaName, targetTableName, newVersion); } @@ -106,12 +104,10 @@ public static void doNewPartDbCutOver( long newVersion = Math.max(sourceTablePartitions.get(0).metaVersion, targetTablePartitions.get(0).metaVersion) + 1; - tableInfoManager - .alterTablePartitionName(schemaName, sourceTableName, random); - tableInfoManager - .alterTablePartitionName(schemaName, targetTableName, sourceTableName); - tableInfoManager - .alterTablePartitionName(schemaName, random, targetTableName); + tableInfoManager.truncateTableCutOver(schemaName, sourceTableName, random); + tableInfoManager.truncateTableCutOver(schemaName, targetTableName, sourceTableName); + tableInfoManager.truncateTableCutOver(schemaName, random, targetTableName); + tableInfoManager.updateTablePartitionVersion(schemaName, sourceTableName, newVersion); tableInfoManager.updateTablePartitionVersion(schemaName, targetTableName, newVersion); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/BaseCdcTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/BaseCdcTask.java new file mode 100644 index 000000000..2b0498a9d --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/BaseCdcTask.java @@ -0,0 +1,20 @@ +package com.alibaba.polardbx.executor.ddl.job.task; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; + +/** + * @author wumu + */ +public abstract class BaseCdcTask extends BaseDdlTask { + public BaseCdcTask(String schemaName) { + super(schemaName); + } + + @Override + final protected void beforeRollbackTransaction(ExecutionContext executionContext) { + throw new TddlRuntimeException(ErrorCode.ERR_CDC_GENERIC, + "Rollback ddl failed, as the CDC task has already been completed."); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/BasePhyDdlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/BasePhyDdlTask.java index e335f7acc..cb861835d 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/BasePhyDdlTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/BasePhyDdlTask.java @@ -17,7 +17,6 @@ package com.alibaba.polardbx.executor.ddl.job.task; import com.alibaba.polardbx.common.ddl.newengine.DdlConstants; -import com.alibaba.polardbx.common.ddl.newengine.DdlState; import com.alibaba.polardbx.common.ddl.newengine.DdlTaskState; import com.alibaba.polardbx.common.ddl.newengine.DdlType; import com.alibaba.polardbx.common.exception.PhysicalDdlException; @@ -31,7 +30,6 @@ import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlEngineAccessorDelegate; -import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlJobManager; import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlJobManagerUtils; import com.alibaba.polardbx.executor.ddl.newengine.utils.TaskHelper; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; @@ -152,13 +150,24 @@ protected void executePhyDdl(List inputs, ExecutionContext ec) { FailPoint.injectRandomExceptionFromHint(executionContext); FailPoint.injectRandomSuspendFromHint(executionContext); - executeConcurrently(inputs, inputCursors, exceptions, executionContext); + try { + executeConcurrently(inputs, inputCursors, exceptions, executionContext); + } catch (Throwable e) { + exceptions.add(e); + } for (Cursor affectRowCursor : inputCursors) { Row row; - while ((row = affectRowCursor.next()) != null) { - row.getInteger(0); + try { + // 对于 group concurrent 来说,next 中才会调用 init 去真正执行物理 ddl,所以这里也需要异常处理 + // concurrent、sequential、instance concurrent 此处无需异常处理 + while ((row = affectRowCursor.next()) != null) { + row.getInteger(0); + } + } catch (Throwable e) { + exceptions.add(e); } + closeExceptions = affectRowCursor.close(exceptions); } @@ -312,7 +321,7 @@ protected void executeConcurrently(List inputs, List inputCurso } } - private QueryConcurrencyPolicy getConcurrencyPolicy(ExecutionContext executionContext) { + protected QueryConcurrencyPolicy getConcurrencyPolicy(ExecutionContext executionContext) { boolean mergeConcurrent = executionContext.getParamManager().getBoolean(ConnectionParams.MERGE_CONCURRENT); boolean mergeDdlConcurrent = @@ -321,8 +330,10 @@ private QueryConcurrencyPolicy getConcurrencyPolicy(ExecutionContext executionCo boolean sequential = executionContext.getParamManager().getBoolean(ConnectionParams.SEQUENTIAL_CONCURRENT_POLICY); - if (mergeConcurrent && mergeDdlConcurrent) { - return QueryConcurrencyPolicy.CONCURRENT; + boolean overrideDefaultParams = executionContext.isOverrideDdlParams(); + + if ((mergeConcurrent && mergeDdlConcurrent) || overrideDefaultParams) { + return QueryConcurrencyPolicy.DDL_CONCURRENT; } else if (mergeConcurrent) { return QueryConcurrencyPolicy.GROUP_CONCURRENT_BLOCK; } else if (sequential) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/RemoteExecutableDdlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/RemoteExecutableDdlTask.java index 625001f54..43ff55842 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/RemoteExecutableDdlTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/RemoteExecutableDdlTask.java @@ -17,6 +17,9 @@ package com.alibaba.polardbx.executor.ddl.job.task; import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.executor.ddl.newengine.dag.TaskScheduler; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; import com.alibaba.polardbx.gms.node.GmsNodeManager; import com.alibaba.polardbx.gms.node.GmsNodeManager.GmsNode; @@ -24,48 +27,93 @@ import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; +import static com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources.normalizeServerKey; + /** * 几个基础操作: * 1. 发送请求:execute/rollback * 2. 等待结果:轮询/同步等待结果 * 3. 容错:xxxx */ -public interface RemoteExecutableDdlTask { +public interface RemoteExecutableDdlTask extends DdlTask { default Optional chooseServer() { - // choose standby node - List standbyNodeList = GmsNodeManager.getInstance().getStandbyNodes(); - if (enableStandbyNode() && !standbyNodeList.isEmpty()) { - List candidates = standbyNodeList.stream().map(GmsNode::getServerKey).collect(Collectors.toList()); - candidates.add(null); - String chosenNode = candidates.get(RandomUtils.nextInt(0, candidates.size())); + return Optional.empty(); + } - if (chosenNode != null) { - return Optional.of(chosenNode); - } + static Set fetchServerKeyFromGmsNode(List nodeList) { + Set serverKeys = new HashSet<>(); + for (GmsNode node : nodeList) { + serverKeys.add(node.getServerKey()); + } + return serverKeys; + } + + default List chooseCandidate() { + List candidates = new ArrayList<>(); + // we should only choose master node here.(master node = master + standby cn). + List masterNodeList = GmsNodeManager.getInstance().getMasterNodes(); + List standbyNodeList = GmsNodeManager.getInstance().getStandbyNodes(); + Set masterNodeKeySet = fetchServerKeyFromGmsNode(masterNodeList); + Set standbyNodeKeySet = fetchServerKeyFromGmsNode(standbyNodeList); + if (!enableStandbyNode() && !forbidRemoteDdlTask()) { + // non-standby node. + candidates.addAll(masterNodeKeySet); + candidates.removeAll(standbyNodeKeySet); + } else if (enableStandbyNode() && !forbidRemoteDdlTask()) { + // all master node. + candidates.addAll(masterNodeKeySet); } + candidates.add(null); + return candidates; + } + + default DdlEngineResources getDdlEngineResources() { + return new DdlEngineResources(); + } + default String detectServerFromCandidate(Map runningTaskNum) { + List candidates = chooseCandidate(); + DdlEngineResources ddlEngineResources = getDdlEngineResources(); if (forbidRemoteDdlTask()) { - return Optional.empty(); + return null; } - List remoteNodeList = GmsNodeManager.getInstance().getRemoteNodes(); - if (CollectionUtils.isEmpty(remoteNodeList)) { - //no remote node, so choose local node - return Optional.empty(); + List finalCandidates = new ArrayList<>(); + if (ddlEngineResources == null || ddlEngineResources.resources.isEmpty()) { + finalCandidates = candidates; + } else { + for (String candidate : candidates) { + DdlEngineResources ddlEngineResources1 = DdlEngineResources.copyFrom(ddlEngineResources); + ddlEngineResources1.setServerKey(candidate); + if (TaskScheduler.resourceToAllocate.cover(ddlEngineResources1)) { + finalCandidates.add(candidate); + } + } } - List candidates = remoteNodeList.stream().map(GmsNode::getServerKey).collect(Collectors.toList()); - candidates.add(null); - String chosenNode = candidates.get(RandomUtils.nextInt(0, candidates.size())); - if (chosenNode == null) { - //choose local node by random - return Optional.empty(); +// SQLRecorderLogger.ddlEngineLogger.info( +// String.format("remote task %d %s %s candidate server: %s", getTaskId(), getName(), executionInfo(), +// finalCandidates)); + if (finalCandidates == null || finalCandidates.isEmpty()) { + return null; } - //choose remote node by random - return Optional.of(chosenNode); + + finalCandidates.sort(Comparator.comparingInt(o -> runningTaskNum.getOrDefault(normalizeServerKey(o), 0))); + + String result = finalCandidates.get(0); +// SQLRecorderLogger.ddlEngineLogger.info( +// String.format("remote task %d %s %s candidate server: %s, result is: %s", getTaskId(), getName(), +// executionInfo(), +// finalCandidates, result)); + return result; } default boolean forbidRemoteDdlTask() { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/AlterTableGroupBackFillTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/AlterTableGroupBackFillTask.java index e5f72e2a9..74f3de2fa 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/AlterTableGroupBackFillTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/AlterTableGroupBackFillTask.java @@ -82,6 +82,7 @@ protected void executeImpl(ExecutionContext executionContext) { updateTaskStateInNewTxn(DdlTaskState.DIRTY); executionContext = executionContext.copy(); executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); executionContext.setSchemaName(schemaName); FailPoint.injectRandomExceptionFromHint(executionContext); FailPoint.injectRandomSuspendFromHint(executionContext); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/ColumnBackFillTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/ColumnBackFillTask.java index 60acd8604..b64e37f64 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/ColumnBackFillTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/ColumnBackFillTask.java @@ -65,6 +65,7 @@ public ColumnBackFillTask(String schemaName, String tableName, List sour protected void executeImpl(ExecutionContext executionContext) { executionContext = executionContext.copy(); executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); List sourceNodes = new ArrayList<>(); List newTargetColumns; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableBackFillTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableBackFillTask.java index c94b0568e..c430e52a8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableBackFillTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableBackFillTask.java @@ -35,8 +35,8 @@ public class LogicalTableBackFillTask extends BaseBackfillTask implements Remote public String sourceTableName; public String targetTableName; - public Map virtualColumns; - public Map backfillColumnMap; + public Map srcCheckColumnMap; + public Map dstCheckColumnMap; public List modifyStringColumns; public boolean useChangeSet; public boolean modifyColumn; @@ -46,8 +46,8 @@ public class LogicalTableBackFillTask extends BaseBackfillTask implements Remote public LogicalTableBackFillTask(String schemaName, String sourceTableName, String targetTableName, - Map virtualColumns, - Map backfillColumnMap, + Map srcCheckColumnMap, + Map dstCheckColumnMap, List modifyStringColumns, boolean useChangeSet, boolean mirrorCopy, @@ -55,8 +55,8 @@ public LogicalTableBackFillTask(String schemaName, super(schemaName); this.sourceTableName = sourceTableName; this.targetTableName = targetTableName; - this.virtualColumns = virtualColumns; - this.backfillColumnMap = backfillColumnMap; + this.srcCheckColumnMap = srcCheckColumnMap; + this.dstCheckColumnMap = dstCheckColumnMap; this.modifyStringColumns = modifyStringColumns; this.useChangeSet = useChangeSet; this.modifyColumn = modifyColumn; @@ -68,14 +68,15 @@ public LogicalTableBackFillTask(String schemaName, protected void executeImpl(ExecutionContext executionContext) { executionContext = executionContext.copy(); executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); GsiBackfill backFillPlan = GsiBackfill.createGsiBackfill(schemaName, sourceTableName, targetTableName, executionContext); backFillPlan.setUseChangeSet(useChangeSet); - backFillPlan.setModifyColumn(modifyColumn); + backFillPlan.setOnlineModifyColumn(modifyColumn); backFillPlan.setMirrorCopy(mirrorCopy); backFillPlan.setModifyStringColumns(modifyStringColumns); - backFillPlan.setBackfillColumnMap(backfillColumnMap); - backFillPlan.setVirtualColumnMap(virtualColumns); + backFillPlan.setSrcCheckColumnMap(srcCheckColumnMap); + backFillPlan.setDstCheckColumnMap(dstCheckColumnMap); FailPoint.injectRandomExceptionFromHint(executionContext); FailPoint.injectRandomSuspendFromHint(executionContext); ExecutorHelper.execute(backFillPlan, executionContext); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableColumnBackFillTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableColumnBackFillTask.java index 7ab967cf0..eb9ec72b5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableColumnBackFillTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableColumnBackFillTask.java @@ -54,6 +54,7 @@ public LogicalTableColumnBackFillTask(String schemaName, protected void executeImpl(ExecutionContext executionContext) { executionContext = executionContext.copy(); executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); GsiBackfill columnsBackFill = GsiBackfill.createGsiAddColumnsBackfill( schemaName, sourceTableName, ImmutableList.of(targetTableName), Lists.newArrayList(columns), diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableDataMigrationBackfillTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableDataMigrationBackfillTask.java index c07cca703..c71b9fe22 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableDataMigrationBackfillTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableDataMigrationBackfillTask.java @@ -66,6 +66,7 @@ protected void executeImpl(ExecutionContext executionContext) { try { executionContext = executionContext.copy(); executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); executionContext.setSchemaName(schemaName); LogicalTableDataMigrationBackfill logicalTableDataMigrationBackfill = LogicalTableDataMigrationBackfill.createLogicalTableDataMigrationBackfill(srcSchemaName, dstSchemaName, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableGsiPkRangeBackfillTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableGsiPkRangeBackfillTask.java new file mode 100644 index 000000000..6e1762d6d --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTableGsiPkRangeBackfillTask.java @@ -0,0 +1,212 @@ +package com.alibaba.polardbx.executor.ddl.job.task.backfill; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.ExecutorHelper; +import com.alibaba.polardbx.executor.backfill.BackfillSampleManager; +import com.alibaba.polardbx.executor.ddl.job.task.BaseBackfillTask; +import com.alibaba.polardbx.executor.ddl.job.task.RemoteExecutableDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; +import com.alibaba.polardbx.executor.gsi.GsiUtils; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.GsiPkRangeBackfill; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import lombok.Getter; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static com.alibaba.polardbx.executor.backfill.BackfillSampleManager.fromValue; +import static com.alibaba.polardbx.executor.backfill.BackfillSampleManager.loadBackfillSampleManager; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.CN_CPU; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.CN_NETWORK; + +@TaskName(name = "LogicalTableGsiPkRangeBackfillTask") +@Getter +public class LogicalTableGsiPkRangeBackfillTask extends BaseBackfillTask implements RemoteExecutableDdlTask { + + public String sourceTableName; + public String targetTableName; + public Map virtualColumns; + public Map backfillColumnMap; + public List modifyStringColumns; + public List pkColumnIndexes; + public boolean useChangeSet; + public boolean modifyColumn; + public boolean mirrorCopy; + public Map> leftRow; + public Map> rightRow; + public long batchRows; + public long batchSize; + public long maxPkRangeSize; + public long maxSampleRows; + public int totalThreadCount; + public int cpuAcquired; + + @JSONCreator + public LogicalTableGsiPkRangeBackfillTask(String schemaName, + String sourceTableName, + String targetTableName, + Map virtualColumns, + Map backfillColumnMap, + List modifyStringColumns, + List pkColumnList, + boolean useChangeSet, + boolean mirrorCopy, + boolean modifyColumn, + Map> leftRow, + Map> rightRow, + String rankHint, + long batchRows, + long batchSize, + long maxPkRangeSize, + long maxSampleRows, + int threadCount, + int cpuAcquired) { + super(schemaName); + this.sourceTableName = sourceTableName; + this.targetTableName = targetTableName; + this.virtualColumns = virtualColumns; + this.backfillColumnMap = backfillColumnMap; + this.modifyStringColumns = modifyStringColumns; + this.pkColumnIndexes = pkColumnList; + this.useChangeSet = useChangeSet; + this.modifyColumn = modifyColumn; + this.mirrorCopy = mirrorCopy; + this.leftRow = leftRow; + this.rightRow = rightRow; + this.batchRows = batchRows; + this.batchSize = batchSize; + this.maxPkRangeSize = maxPkRangeSize; + this.maxSampleRows = maxSampleRows; + this.totalThreadCount = threadCount; + this.cpuAcquired = cpuAcquired; + setResourceAcquired(buildResourceRequired()); + setRankHint(rankHint); + onExceptionTryRecoveryThenRollback(); + } + + @Override + protected void executeImpl(ExecutionContext executionContext) { + // NOTICE, multiple pk range task would share the executionContext + Map leftRowParam = fromValue(leftRow); + Map rightRowParam = fromValue(rightRow); + BackfillSampleManager backfillSampleManager = + loadBackfillSampleManager(schemaName, sourceTableName, jobId, taskId, leftRowParam, rightRowParam); + Pair>, List> rowsAndBackfillIds = + backfillSampleManager.loadSampleRows(maxPkRangeSize, maxSampleRows, batchRows, + batchSize); + List> rows = rowsAndBackfillIds.getKey(); + List backfillIds = rowsAndBackfillIds.getValue(); + + long start = System.currentTimeMillis(); + Map executionTime = new HashMap<>(); + try { + for (int i = 1; i < rows.size(); i++) { + ExecutionContext copyExecutionContext = executionContext.copy(); + copyExecutionContext.setBackfillId(backfillIds.get(i - 1)); + copyExecutionContext.setEstimatedBackfillBatchRows(batchRows); + copyExecutionContext.setTaskId(taskId); + GsiPkRangeBackfill backFillPlan = + GsiPkRangeBackfill.createGsiPkRangeBackfill(schemaName, sourceTableName, targetTableName, + copyExecutionContext); + backFillPlan.setUseChangeSet(useChangeSet); + backFillPlan.setOnlineModifyColumn(modifyColumn); + backFillPlan.setMirrorCopy(mirrorCopy); + backFillPlan.setModifyStringColumns(modifyStringColumns); + backFillPlan.setDstCheckColumnMap(backfillColumnMap); + backFillPlan.setSrcCheckColumnMap(virtualColumns); + backFillPlan.setPkRange(Pair.of(rows.get(i - 1), rows.get(i))); + backFillPlan.setTotalThreadCount(totalThreadCount); + FailPoint.injectRandomExceptionFromHint(copyExecutionContext); + FailPoint.injectRandomSuspendFromHint(copyExecutionContext); + ExecutorHelper.execute(backFillPlan, copyExecutionContext); + long end = System.currentTimeMillis(); + SQLRecorderLogger.ddlLogger.warn( + MessageFormat.format("[{0}] [{1}][{2}] finish pk range [({3}),({4})] in {5} ms", + executionContext.getTraceId(), + String.valueOf(getTaskId()), + String.valueOf(copyExecutionContext.getBackfillId()), + formatPkRows(rows.get(i - 1), null), + formatPkRows(rows.get(i), null), + end - start + )); + String batchExecutionTime = String.valueOf(end - start); + if (copyExecutionContext.getEstimatedBackfillBatchRows() < 0) { + // mark for idempotent judge + batchExecutionTime = batchExecutionTime + ":i"; + } + executionTime.put(copyExecutionContext.getBackfillId(), batchExecutionTime); + start = end; + + } + } catch (Exception e) { + throw e; + } finally { +// backfillSampleManager.flushPositionMark(); + backfillSampleManager.storeExecutionTime(executionTime); + BackfillSampleManager.removeBackfillSampleManager(taskId); + } + } + + public static List generateBackfillIds(int n) { + List backfillIds = new ArrayList<>(n); + for (int i = 0; i < n; i++) { + backfillIds.add(JOB_ID_GENERATOR.nextId()); + } + return backfillIds; + } + + DdlEngineResources buildResourceRequired() { + DdlEngineResources resourceRequired = new DdlEngineResources(); + String owner = + "LogicalBackfill:" + sourceTableName + ": " + formatPkRows(leftRow) + ", " + formatPkRows(rightRow); + resourceRequired.request(CN_NETWORK, (long) cpuAcquired, owner); + resourceRequired.request(CN_CPU, (long) cpuAcquired, owner); + return resourceRequired; + } + + static public String formatPkRows(Map rows, List indexes) { + String result = " "; + if (!MapUtils.isEmpty(rows)) { + result = StringUtils.join( + rows.keySet().stream().map(index -> rows.get(index).getValue().toString()).collect(Collectors.toList()), + ","); + } + return result; + } + + static public String formatPkRows(Map> rows) { + String result = " "; + if (!MapUtils.isEmpty(rows)) { + result = StringUtils.join( + rows.keySet().stream().map(index -> rows.get(index).get(1)).collect(Collectors.toList()), + ","); + } + return result; + + } + + @Override + public DdlEngineResources getDdlEngineResources() { + return this.resourceAcquired; + } + + @Override + public String remark() { + return "|logical backfill for table:" + sourceTableName + " |pk range:(" + formatPkRows(leftRow) + + ") to (" + formatPkRows(rightRow) + ") |batch rows:(" + batchRows + ")"; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTablePhysicalPartitionBackFillTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTablePhysicalPartitionBackFillTask.java new file mode 100644 index 000000000..b79edfa38 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/LogicalTablePhysicalPartitionBackFillTask.java @@ -0,0 +1,102 @@ +package com.alibaba.polardbx.executor.ddl.job.task.backfill; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.executor.ExecutorHelper; +import com.alibaba.polardbx.executor.ddl.job.task.BaseBackfillTask; +import com.alibaba.polardbx.executor.ddl.job.task.RemoteExecutableDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.GsiPartitionBackfill; +import lombok.Getter; + +import java.util.List; +import java.util.Map; + +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.CN_CPU; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.CN_NETWORK; + +@TaskName(name = "LogicalTablePhysicalPartitionBackFillTask") +@Getter +public class LogicalTablePhysicalPartitionBackFillTask extends BaseBackfillTask implements RemoteExecutableDdlTask { + + public String sourceTableName; + public String targetTableName; + public Map virtualColumns; + public Map backfillColumnMap; + public List modifyStringColumns; + public boolean useChangeSet; + public boolean modifyColumn; + public boolean mirrorCopy; + public List physicalPartitions; + public int cpuAcquired; + + @JSONCreator + public LogicalTablePhysicalPartitionBackFillTask(String schemaName, + String sourceTableName, + String targetTableName, + Map virtualColumns, + Map backfillColumnMap, + List modifyStringColumns, + boolean useChangeSet, + boolean mirrorCopy, + boolean modifyColumn, + List physicalPartitions, + int cpuAcquired) { + super(schemaName); + this.sourceTableName = sourceTableName; + this.targetTableName = targetTableName; + this.virtualColumns = virtualColumns; + this.backfillColumnMap = backfillColumnMap; + this.modifyStringColumns = modifyStringColumns; + this.useChangeSet = useChangeSet; + this.modifyColumn = modifyColumn; + this.mirrorCopy = mirrorCopy; + this.physicalPartitions = physicalPartitions; + this.cpuAcquired = cpuAcquired; + setResourceAcquired(buildResourceRequired()); + onExceptionTryRecoveryThenRollback(); + } + + @Override + protected void executeImpl(ExecutionContext executionContext) { + executionContext = executionContext.copy(); + executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); + GsiPartitionBackfill backFillPlan = + GsiPartitionBackfill.createGsiPartitionBackfill(schemaName, sourceTableName, targetTableName, + executionContext); + backFillPlan.setUseChangeSet(useChangeSet); + backFillPlan.setOnlineModifyColumn(modifyColumn); + backFillPlan.setMirrorCopy(mirrorCopy); + backFillPlan.setModifyStringColumns(modifyStringColumns); + backFillPlan.setSrcCheckColumnMap(backfillColumnMap); + backFillPlan.setDstCheckColumnMap(virtualColumns); + backFillPlan.setPartitionList(physicalPartitions); + FailPoint.injectRandomExceptionFromHint(executionContext); + FailPoint.injectRandomSuspendFromHint(executionContext); + ExecutorHelper.execute(backFillPlan, executionContext); + } + + DdlEngineResources buildResourceRequired() { + DdlEngineResources resourceRequired = new DdlEngineResources(); + String owner = + "LogicalBackfill:" + sourceTableName + ": " + physicalPartitions; + resourceRequired.request(CN_NETWORK, 5L, owner); + resourceRequired.request(CN_CPU, Long.valueOf(cpuAcquired), owner); + return resourceRequired; + } + + @Override + public DdlEngineResources getDdlEngineResources() { + return this.resourceAcquired; + } + + @Override + public String remark() { + return "|logical backfill for table:" + sourceTableName + " |partition:(" + physicalPartitions + + ")"; + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/MoveTableBackFillTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/MoveTableBackFillTask.java index 2241ea21a..19fe359dd 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/MoveTableBackFillTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/backfill/MoveTableBackFillTask.java @@ -81,6 +81,7 @@ protected void executeImpl(ExecutionContext executionContext) { updateTaskStateInNewTxn(DdlTaskState.DIRTY); executionContext = executionContext.copy(); executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); executionContext.setSchemaName(schemaName); FailPoint.injectRandomExceptionFromHint(executionContext); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AddLocalPartitionTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AddLocalPartitionTask.java index f71dc27ad..82f26b8b0 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AddLocalPartitionTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AddLocalPartitionTask.java @@ -41,6 +41,16 @@ public AddLocalPartitionTask(LocalPartitionDefinitionInfo localPartitionDefiniti this.localPartitionDefinitionInfo = localPartitionDefinitionInfo; } + @Override + protected void onExecutionSuccess(ExecutionContext executionContext) { + super.onExecutionSuccess(executionContext); + } + + @Override + protected void onRollbackSuccess(ExecutionContext executionContext) { + super.onRollbackSuccess(executionContext); + } + @Override protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { TableMetaChanger.addLocalPartitionMeta(metaDbConnection, localPartitionDefinitionInfo.convertToRecord()); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AddTtlInfoTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AddTtlInfoTask.java new file mode 100644 index 000000000..21b7ec3a3 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AddTtlInfoTask.java @@ -0,0 +1,69 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.scheduler.SchedulePolicy; +import com.alibaba.polardbx.common.scheduler.SchedulerJobStatus; +import com.alibaba.polardbx.executor.ddl.job.meta.TableMetaChanger; +import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.gms.scheduler.ScheduledJobExecutorType; +import com.alibaba.polardbx.gms.scheduler.ScheduledJobsRecord; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import lombok.Getter; + +import java.sql.Connection; + +@Getter +@TaskName(name = "AddTtlInfoTask") +public class AddTtlInfoTask extends BaseGmsTask { + + private TtlDefinitionInfo ttlDefinitionInfo; + + public AddTtlInfoTask(TtlDefinitionInfo ttlDefinitionInfo) { + super(ttlDefinitionInfo.getTtlInfoRecord().getTableSchema(), + ttlDefinitionInfo.getTtlInfoRecord().getTableName()); + this.ttlDefinitionInfo = ttlDefinitionInfo; + } + + @Override + protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + TableMetaChanger.addTtlInfoMeta(metaDbConnection, ttlDefinitionInfo.getTtlInfoRecord()); + + boolean disableSchedule = !ttlDefinitionInfo.isEnableTtlSchedule(); + + String cronExpr = ttlDefinitionInfo.getTtlInfoRecord().getTtlCron(); + if (cronExpr == null) { + cronExpr = executionContext.getParamManager().getString(ConnectionParams.DEFAULT_TTL_SCHEDULE_CRON_EXPR); + } + + ScheduledJobsRecord scheduledJobsRecord = ScheduledJobsManager.createQuartzCronJob( + schemaName, + null, + logicalTableName, + ScheduledJobExecutorType.TTL_JOB, + cronExpr, + executionContext.getTimeZone().getMySqlTimeZoneName(), + SchedulePolicy.WAIT + ); + String stateVal = disableSchedule ? SchedulerJobStatus.DISABLED.name() : SchedulerJobStatus.ENABLED.name(); + scheduledJobsRecord.setStatus(stateVal); + + try { + TableMetaChanger.addScheduledJob(metaDbConnection, scheduledJobsRecord); + TableInfoManager.updateTableVersion(schemaName, logicalTableName, metaDbConnection); + } catch (Throwable ex) { + throw new TtlJobRuntimeException(ex); + } + + } + + @Override + protected void rollbackImpl(Connection metaDbConnection, ExecutionContext executionContext) { + TableMetaChanger.removeTtlInfoMeta(metaDbConnection, schemaName, logicalTableName); + TableMetaChanger.removeScheduledJobs(metaDbConnection, schemaName, logicalTableName); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTableChangeMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTableChangeMetaTask.java index 1f60ad3ad..74cfa5a72 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTableChangeMetaTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTableChangeMetaTask.java @@ -144,7 +144,7 @@ protected void executeImpl(Connection metaDbConnection, ExecutionContext executi // Change columnar table meta in same transaction // columnar_table_mapping, columnar_table_evolution, columnar_column_evolution TableMetaChanger.changeColumnarTableMeta(metaDbConnection, schemaName, logicalTableName, addedColumns, - droppedColumns, updatedColumns, changedColumns, versionId, jobId); + droppedColumns, updatedColumns, changedColumns, renamedIndexes, versionId, jobId); List alterColumnList = new ArrayList<>(); if (updatedColumns != null) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTableValidateTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTableValidateTask.java index b6f7079e4..1d2c9d075 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTableValidateTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTableValidateTask.java @@ -18,15 +18,11 @@ import com.alibaba.fastjson.annotation.JSONCreator; import com.alibaba.polardbx.common.TddlConstants; -import com.alibaba.polardbx.common.ddl.Attribute; import com.alibaba.polardbx.common.ddl.foreignkey.ForeignKeyData; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; -import com.alibaba.polardbx.common.utils.GeneralUtil; -import com.alibaba.polardbx.common.utils.Pair; -import com.alibaba.polardbx.common.utils.TStringUtil; -import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableItem; import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableRenameColumn; import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableStatement; @@ -34,9 +30,8 @@ import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.ddl.job.validator.GsiValidator; import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; -import com.alibaba.polardbx.gms.metadb.table.ColumnsRecord; -import com.alibaba.polardbx.gms.metadb.table.IndexStatus; import com.alibaba.polardbx.gms.lbac.LBACSecurityManager; +import com.alibaba.polardbx.gms.metadb.table.IndexStatus; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.OptimizerContext; @@ -44,15 +39,12 @@ import com.alibaba.polardbx.optimizer.config.table.GeneratedColumnUtil; import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; import com.alibaba.polardbx.optimizer.config.table.IndexMeta; -import com.alibaba.polardbx.optimizer.config.table.SchemaManager; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTablePreparedData; import com.alibaba.polardbx.optimizer.parse.FastsqlParser; import com.alibaba.polardbx.optimizer.parse.FastsqlUtils; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter; -import com.alibaba.polardbx.optimizer.utils.MetaUtils; import com.alibaba.polardbx.rule.TableRule; import lombok.Getter; import org.apache.calcite.sql.SqlAddColumn; @@ -67,7 +59,6 @@ import org.apache.calcite.sql.SqlAlterTable; import org.apache.calcite.sql.SqlAlterTableDropIndex; import org.apache.calcite.sql.SqlAlterTableRenameIndex; -import org.apache.calcite.sql.SqlBinaryStringLiteral; import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlChangeColumn; import org.apache.calcite.sql.SqlColumnDeclaration; @@ -75,17 +66,12 @@ import org.apache.calcite.sql.SqlDataTypeSpec; import org.apache.calcite.sql.SqlDropColumn; import org.apache.calcite.sql.SqlDropForeignKey; -import org.apache.calcite.sql.SqlDropPrimaryKey; -import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlIndexColumnName; import org.apache.calcite.sql.SqlIndexDefinition; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlModifyColumn; -import org.apache.commons.collections.CollectionUtils; -import java.sql.Types; import java.util.ArrayList; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -203,6 +189,11 @@ public void executeImpl(ExecutionContext executionContext) { tableMeta.getAllIndexes().stream().map(i -> i.getPhysicalIndexName()).collect(Collectors.toList())); indexesBeforeDdl.addAll( tableMeta.getAllIndexes().stream().map(i -> i.getPhysicalIndexName()).collect(Collectors.toList())); + // add cci original name + if (tableMeta.getColumnarIndexPublished() != null) { + indexes.addAll(tableMeta.getColumnarIndexPublished().keySet().stream() + .map(TddlSqlToRelConverter::unwrapGsiName).collect(Collectors.toList())); + } GsiMetaManager.GsiMetaBean gsiMetaBean = OptimizerContext.getContext(schemaName).getLatestSchemaManager().getGsi(tableName, IndexStatus.ALL); @@ -322,12 +313,12 @@ public void executeImpl(ExecutionContext executionContext) { break; case ALTER_RENAME_INDEX: - final SqlAlterTableRenameIndex renameIndex = (SqlAlterTableRenameIndex) alterItem; - if (null != renameIndex.getOriginIndexName() && tableMeta.withCci( - renameIndex.getOriginIndexName().getLastName())) { - throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, "Do not support rename cci " - + renameIndex.getOriginIndexName().getLastName()); - } +// final SqlAlterTableRenameIndex renameIndex = (SqlAlterTableRenameIndex) alterItem; +// if (null != renameIndex.getOriginIndexName() && tableMeta.withCci( +// renameIndex.getOriginIndexName().getLastName())) { +// throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, "Do not support rename cci " +// + renameIndex.getOriginIndexName().getLastName()); +// } checkIndexExists(indexes, ((SqlAlterTableRenameIndex) alterItem).getIndexName().getLastName()); indexes.remove(((SqlAlterTableRenameIndex) alterItem).getIndexName().getLastName()); @@ -469,7 +460,7 @@ private void validateMultipleStatement(TableMeta tableMeta, SqlAlterTable sqlAlt case MODIFY_COLUMN: if (((SqlModifyColumn) alterItem).getAfterColumn() != null) { String afterName = ((SqlModifyColumn) alterItem).getAfterColumn().getLastName(); - if (!newColumns.contains(afterName)) { + if (!containsColumnNameIgnoreCase(newColumns, afterName)) { throw new TddlRuntimeException(ErrorCode.ERR_UNKNOWN_COLUMN, afterName, tableName); } } @@ -478,7 +469,7 @@ private void validateMultipleStatement(TableMeta tableMeta, SqlAlterTable sqlAlt case CHANGE_COLUMN: if (((SqlChangeColumn) alterItem).getAfterColumn() != null) { String afterName = ((SqlChangeColumn) alterItem).getAfterColumn().getLastName(); - if (!newColumns.contains(afterName)) { + if (!containsColumnNameIgnoreCase(newColumns, afterName)) { throw new TddlRuntimeException(ErrorCode.ERR_UNKNOWN_COLUMN, afterName, tableName); } } @@ -489,7 +480,7 @@ private void validateMultipleStatement(TableMeta tableMeta, SqlAlterTable sqlAlt // which would not be adjusted. if (((SqlAddColumn) alterItem).getAfterColumn() != null) { String afterName = ((SqlAddColumn) alterItem).getAfterColumn().getLastName(); - if (!newColumns.contains(afterName)) { + if (!containsColumnNameIgnoreCase(newColumns, afterName)) { throw new TddlRuntimeException(ErrorCode.ERR_UNKNOWN_COLUMN, afterName, tableName); } afterColumns.add(Pair.of(((SqlAddColumn) alterItem).getColName().getLastName(), @@ -504,12 +495,12 @@ private void validateMultipleStatement(TableMeta tableMeta, SqlAlterTable sqlAlt for (Pair afterColumn : afterColumns) { String columnName = afterColumn.getKey(); String afterColumnName = afterColumn.getValue(); - int index = newColumns.indexOf(columnName); + int index = indexOfColumnNameIgnoreCase(newColumns, columnName); if (index == -1) { throw new TddlRuntimeException(ErrorCode.ERR_UNKNOWN_COLUMN, columnName, tableName); } newColumns.remove(index); - index = newColumns.indexOf(afterColumnName); + index = indexOfColumnNameIgnoreCase(newColumns, afterColumnName); if (index == -1) { throw new TddlRuntimeException(ErrorCode.ERR_UNKNOWN_COLUMN, afterColumnName, tableName); } @@ -629,7 +620,7 @@ private void validateMultipleStatement(TableMeta tableMeta, SqlAlterTable sqlAlt } private void validateNewColumns(List newColumns) { - if (newColumns.size() == 1 && newColumns.contains(TddlConstants.IMPLICIT_COL_NAME) + if (newColumns.size() == 1 && containsColumnNameIgnoreCase(newColumns, TddlConstants.IMPLICIT_COL_NAME) || newColumns.isEmpty()) { // no columns without implicit primary key throw new TddlRuntimeException(ErrorCode.ERR_DROP_ALL_COLUMNS); } @@ -642,6 +633,26 @@ private void validateNewColumns(List newColumns) { } } + public static Boolean containsColumnNameIgnoreCase(List columnNames, String toFindColumnName) { + for (String columnName : columnNames) { + if (columnName.equalsIgnoreCase(toFindColumnName)) { + return true; + } + } + return false; + } + + public static int indexOfColumnNameIgnoreCase(List columnNames, String toFindColumnName) { + int index = 0; + for (String columnName : columnNames) { + if (columnName.equalsIgnoreCase(toFindColumnName)) { + return index; + } + index++; + } + return -1; + } + private void validateNewIndexes(List newIndexes) { Set newIndexSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); for (String name : newIndexes) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTtlInfoTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTtlInfoTask.java new file mode 100644 index 000000000..070bd5375 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTtlInfoTask.java @@ -0,0 +1,102 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.scheduler.SchedulerJobStatus; +import com.alibaba.polardbx.executor.ddl.job.meta.TableMetaChanger; +import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlLoggerUtil; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.gms.scheduler.ScheduledJobExecutorType; +import com.alibaba.polardbx.gms.scheduler.ScheduledJobsRecord; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.cronutils.descriptor.CronDescriptor; +import com.cronutils.model.Cron; +import com.cronutils.model.definition.CronDefinitionBuilder; +import com.cronutils.parser.CronParser; +import lombok.Getter; + +import java.sql.Connection; +import java.util.List; +import java.util.Locale; + +import static com.cronutils.model.CronType.QUARTZ; + +@Getter +@TaskName(name = "AlterTtlInfoTask") +public class AlterTtlInfoTask extends BaseGmsTask { + + private TtlDefinitionInfo oldTtlInfo; + private TtlDefinitionInfo newTtlInfo; + + public AlterTtlInfoTask(TtlDefinitionInfo oldTtlInfo, + TtlDefinitionInfo newTtlInfo) { + super(newTtlInfo.getTtlInfoRecord().getTableSchema(), newTtlInfo.getTtlInfoRecord().getTableName()); + this.oldTtlInfo = oldTtlInfo; + this.newTtlInfo = newTtlInfo; + } + + @Override + protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + updateTtlInfoAndSchedule(metaDbConnection, executionContext, newTtlInfo); + } + + @Override + protected void rollbackImpl(Connection metaDbConnection, ExecutionContext executionContext) { + updateTtlInfoAndSchedule(metaDbConnection, executionContext, oldTtlInfo); + } + + protected void updateTtlInfoAndSchedule(Connection metaDbConnection, + ExecutionContext executionContext, + TtlDefinitionInfo newTtlInfo) { + + try { + String oldTtlTblSchema = oldTtlInfo.getTtlInfoRecord().getTableSchema(); + String oldTtlTblName = oldTtlInfo.getTtlInfoRecord().getTableName(); + TableMetaChanger.alterTtlInfoMeta(metaDbConnection, + newTtlInfo.getTtlInfoRecord(), + oldTtlTblSchema, + oldTtlTblName); + boolean enableTtlScheduleOnNewTtlInfo = newTtlInfo.isEnableTtlSchedule(); + String cronExpr = newTtlInfo.getTtlInfoRecord().getTtlCron(); + if (cronExpr == null) { + cronExpr = + executionContext.getParamManager().getString(ConnectionParams.DEFAULT_TTL_SCHEDULE_CRON_EXPR); + } + + List scheduledJobsRecordList = + ScheduledJobsManager.getScheduledJobByTableNameAndExecutorType(schemaName, logicalTableName, + ScheduledJobExecutorType.TTL_JOB.name()); + boolean existScheduledOldJobs = !scheduledJobsRecordList.isEmpty(); + if (existScheduledOldJobs) { + /** + * A ttlInfo must be a scheduled job definition + */ + ScheduledJobsRecord scheduledJobsRecord = scheduledJobsRecordList.get(0); + String stateVal = + !enableTtlScheduleOnNewTtlInfo ? SchedulerJobStatus.DISABLED.name() : + SchedulerJobStatus.ENABLED.name(); + CronParser quartzCronParser = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(QUARTZ)); + Cron cron = quartzCronParser.parse(cronExpr); + cron.validate(); + String cronTimeZoneStr = newTtlInfo.getTtlInfoRecord().getTtlTimezone(); + CronDescriptor descriptor = CronDescriptor.instance(Locale.US); + scheduledJobsRecord.setScheduleComment(descriptor.describe(cron)); + scheduledJobsRecord.setStatus(stateVal); + scheduledJobsRecord.setScheduleExpr(cronExpr); + scheduledJobsRecord.setTimeZone(cronTimeZoneStr); + TableMetaChanger.updateScheduledJob(metaDbConnection, scheduledJobsRecord); + if (!enableTtlScheduleOnNewTtlInfo) { + TableMetaChanger.removeTtlFiredScheduledJobs(metaDbConnection, schemaName, logicalTableName); + } + TableInfoManager.updateTableVersion(schemaName, logicalTableName, metaDbConnection); + } + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.error(ex); + throw new TtlJobRuntimeException(ex); + } + } +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AnalyzePhyTableTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AnalyzePhyTableTask.java new file mode 100644 index 000000000..e87ea9f5d --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AnalyzePhyTableTask.java @@ -0,0 +1,47 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.spi.IDataSourceGetter; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.repo.mysql.spi.DatasourceMySQLImplement; +import com.google.common.collect.ImmutableList; +import lombok.Getter; + +import java.sql.Connection; + +@Getter +@TaskName(name = "AnalyzePhyTableTask") +public class AnalyzePhyTableTask extends AnalyzeTablePhyDdlTask { + + private String schemaName; + private String groupKey; + private String phyTableName; + + public AnalyzePhyTableTask(String schemaName, String groupKey, String phyTableName) { + super(ImmutableList.of(schemaName), ImmutableList.of(phyTableName), null, null); + this.schemaName = schemaName; + this.groupKey = groupKey; + this.phyTableName = phyTableName; + onExceptionTryRecoveryThenPause(); + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + executeImpl(metaDbConnection, executionContext); + } + + @Override + public void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + ParamManager paramManager = OptimizerContext.getContext(schemaName).getParamManager(); + boolean isAnalyzeTableAfterImportTablespace = + paramManager.getBoolean(ConnectionParams.ANALYZE_TABLE_AFTER_IMPORT_TABLESPACE); + if (isAnalyzeTableAfterImportTablespace) { + IDataSourceGetter mysqlDsGetter = new DatasourceMySQLImplement(schemaName); + doAnalyzeOnePhysicalTable(groupKey, phyTableName, mysqlDsGetter); + } + + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AnalyzeTablePhyDdlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AnalyzeTablePhyDdlTask.java index 19cd6ed74..51dda291a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AnalyzeTablePhyDdlTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AnalyzeTablePhyDdlTask.java @@ -96,11 +96,6 @@ public void executeImpl(Connection metaDbConnection, ExecutionContext executionC retUseHll.add(executionContext.getParamManager().getBoolean(ENABLE_HLL) && SchemaMetaUtil .checkSupportHll(schemaName)); - if (OptimizerContext.getContext(schemaName).getRuleManager().getTableRule(table) == null) { - logger.warn( - "no table rule for logicalTableName = " + table + ", analyze this table as the single table!"); - } - forceAnalyzeColumnsDdl(schemaName, table, retMsg, executionContext); // refresh plan cache diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CloneTableDataFileTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CloneTableDataFileTask.java index b5b410fd1..046a5b09b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CloneTableDataFileTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CloneTableDataFileTask.java @@ -26,6 +26,7 @@ import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.ddl.newengine.cross.CrossEngineValidator; +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; import com.alibaba.polardbx.executor.physicalbackfill.PhysicalBackfillManager; import com.alibaba.polardbx.executor.physicalbackfill.PhysicalBackfillReporter; import com.alibaba.polardbx.executor.physicalbackfill.PhysicalBackfillUtils; @@ -37,6 +38,7 @@ import com.alibaba.polardbx.rpc.pool.XConnection; import com.alibaba.polardbx.statistics.SQLRecorderLogger; import com.mysql.cj.polarx.protobuf.PolarxPhysicalBackfill; +import io.airlift.slice.DataSize; import lombok.Getter; import org.apache.commons.lang3.StringUtils; @@ -50,6 +52,8 @@ import java.util.concurrent.atomic.AtomicReference; import static com.alibaba.polardbx.common.TddlConstants.LONG_ENOUGH_TIMEOUT_FOR_DDL_ON_XPROTO_CONN; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_CPU; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_IO; @Getter @TaskName(name = "CloneTableDataFileTask") @@ -64,6 +68,7 @@ public class CloneTableDataFileTask extends BaseDdlTask { final List> targetHostsIpAndPort; final String sourceStorageInstId; final Long batchSize; + final Long dataSize; final boolean encrypted; //don't serialize this parameter private transient Map> storageInstAndUserInfos = new ConcurrentHashMap<>(); @@ -72,7 +77,8 @@ public class CloneTableDataFileTask extends BaseDdlTask { public CloneTableDataFileTask(String schemaName, String logicalTableName, Pair srcDbAndGroup, Pair tarDbAndGroup, String phyTableName, List phyPartNames, String sourceStorageInstId, Pair sourceHostIpAndPort, - List> targetHostsIpAndPort, Long batchSize, Boolean encrypted) { + List> targetHostsIpAndPort, + Long batchSize, long dataSize, Boolean encrypted) { super(schemaName); this.srcDbAndGroup = srcDbAndGroup; this.tarDbAndGroup = tarDbAndGroup; @@ -82,7 +88,11 @@ public CloneTableDataFileTask(String schemaName, String logicalTableName, Pair phyPartNames, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreatePhyTableWithRollbackCheckTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreatePhyTableWithRollbackCheckTask.java new file mode 100644 index 000000000..6c6c69548 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreatePhyTableWithRollbackCheckTask.java @@ -0,0 +1,49 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.executor.ddl.job.builder.DdlPhyPlanBuilder; +import com.alibaba.polardbx.executor.ddl.job.builder.DropPhyTableBuilder; +import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.ddl.job.task.BasePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.scaleout.ScaleOutUtils; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.PhyDdlTableOperation; +import lombok.Getter; +import org.apache.calcite.rel.RelNode; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Getter +@TaskName(name = "CreatePhyTableWithRollbackCheckTask") +public class CreatePhyTableWithRollbackCheckTask extends CreateTablePhyDdlTask { + + Map> sourceTableTopology; + + @JSONCreator + public CreatePhyTableWithRollbackCheckTask(String schemaName, String logicalTableName, + PhysicalPlanData physicalPlanData, + Map> sourceTableTopology) { + super(schemaName, logicalTableName, physicalPlanData); + this.sourceTableTopology = sourceTableTopology; + onExceptionTryRecoveryThenRollback(); + } + + @Override + protected List genRollbackPhysicalPlans(ExecutionContext executionContext) { + for (Map.Entry> entry : sourceTableTopology.entrySet()) { + for (String phyTb : entry.getValue()) { + if (!ScaleOutUtils.checkTableExistence(schemaName, entry.getKey(), phyTb)) { + throw GeneralUtil.nestedException( + "The source table '" + phyTb + "' does not exist in '" + entry.getKey() + + "'; therefore, this DDL operation cannot be rolled back."); + } + } + } + return super.genRollbackPhysicalPlans(executionContext); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreateTableAddTablesPartitionInfoMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreateTableAddTablesPartitionInfoMetaTask.java index f4b50ccc2..3eb977463 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreateTableAddTablesPartitionInfoMetaTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreateTableAddTablesPartitionInfoMetaTask.java @@ -39,6 +39,7 @@ import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.partition.common.LocalPartitionDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; import lombok.Getter; import org.apache.commons.lang.StringUtils; @@ -55,6 +56,8 @@ public class CreateTableAddTablesPartitionInfoMetaTask extends BaseGmsTask { private TableGroupDetailConfig tableGroupConfig; private LocalPartitionDefinitionInfo localPartitionDefinitionInfo; private String tableGroupAlignWithTargetTable; + private TtlDefinitionInfo ttlDefinitionInfo; + private boolean indexAlignWithPrimaryTableGroup; private String primaryTable; private String locality; //specified in create table statement @@ -69,17 +72,21 @@ public CreateTableAddTablesPartitionInfoMetaTask(String schemaName, boolean temporary, TableGroupDetailConfig tableGroupConfig, LocalPartitionDefinitionInfo localPartitionDefinitionInfo, + TtlDefinitionInfo ttlDefinitionInfo, String tableGroupAlignWithTargetTable, + boolean withTableGroupImplicit, + boolean indexAlignWithPrimaryTableGroup, String primaryTable, String joinGroup, boolean oss, - boolean withTableGroupImplicit, boolean autoCreateTg) { super(schemaName, logicalTableName); this.temporary = temporary; this.tableGroupConfig = tableGroupConfig; this.localPartitionDefinitionInfo = localPartitionDefinitionInfo; + this.ttlDefinitionInfo = ttlDefinitionInfo; + this.indexAlignWithPrimaryTableGroup = indexAlignWithPrimaryTableGroup; this.tableGroupAlignWithTargetTable = tableGroupAlignWithTargetTable; this.primaryTable = primaryTable; this.joinGroup = joinGroup; @@ -189,6 +196,9 @@ public void executeImpl(Connection metaDbConnection, ExecutionContext executionC if (localPartitionDefinitionInfo != null) { new AddLocalPartitionTask(localPartitionDefinitionInfo).executeImpl(metaDbConnection, executionContext); } + if (ttlDefinitionInfo != null) { + new AddTtlInfoTask(ttlDefinitionInfo).executeImpl(metaDbConnection, executionContext); + } FailPoint.injectRandomExceptionFromHint(executionContext); FailPoint.injectRandomSuspendFromHint(executionContext); @@ -204,6 +214,9 @@ public void rollbackImpl(Connection metaDbConnection, ExecutionContext execution if (localPartitionDefinitionInfo != null) { new AddLocalPartitionTask(localPartitionDefinitionInfo).rollbackImpl(metaDbConnection, executionContext); } + if (ttlDefinitionInfo != null) { + new AddTtlInfoTask(ttlDefinitionInfo).rollbackImpl(metaDbConnection, executionContext); + } JoinGroupTableDetailAccessor joinGroupTableDetailAccessor = new JoinGroupTableDetailAccessor(); joinGroupTableDetailAccessor.setConnection(metaDbConnection); joinGroupTableDetailAccessor.getJoinGroupDetailBySchemaTableName(schemaName, logicalTableName); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreateTablePhyDdlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreateTablePhyDdlTask.java index 6f84f654e..a0cb55603 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreateTablePhyDdlTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreateTablePhyDdlTask.java @@ -33,7 +33,7 @@ @TaskName(name = "CreateTablePhyDdlTask") public class CreateTablePhyDdlTask extends BasePhyDdlTask { - private String logicalTableName; + protected String logicalTableName; @JSONCreator public CreateTablePhyDdlTask(String schemaName, String logicalTableName, PhysicalPlanData physicalPlanData) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/DiscardTableSpaceDdlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/DiscardTableSpaceDdlTask.java index 79b9a3abe..5c7974822 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/DiscardTableSpaceDdlTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/DiscardTableSpaceDdlTask.java @@ -17,26 +17,98 @@ package com.alibaba.polardbx.executor.ddl.job.task.basic; import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.task.BasePhyDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.utils.QueryConcurrencyPolicy; import lombok.Getter; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.CN_CPU; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.CN_NETWORK; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_CPU; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_IO; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_NETWORK; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_STORAGE; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_SYSTEM_LOCK; + @Getter @TaskName(name = "DiscardTableSpaceDdlTask") public class DiscardTableSpaceDdlTask extends BasePhyDdlTask { private String logicalTableName; + private String storageInst; + @JSONCreator - public DiscardTableSpaceDdlTask(String schemaName, String logicalTableName, PhysicalPlanData physicalPlanData) { + public DiscardTableSpaceDdlTask(String schemaName, String logicalTableName, String storageInst, + PhysicalPlanData physicalPlanData) { super(schemaName, physicalPlanData); this.logicalTableName = logicalTableName; + this.storageInst = storageInst; + setResourceAcquired(buildResourceRequired(storageInst)); onExceptionTryRecoveryThenRollback(); } + DdlEngineResources buildResourceRequired(String storageInst) { + DdlEngineResources resourceRequired = new DdlEngineResources(); + String owner = "DiscardTableSpace:" + logicalTableName + ":" + storageInst; + resourceRequired.request(storageInst + DN_SYSTEM_LOCK, 80L, owner); + return resourceRequired; + } + public void executeImpl(ExecutionContext executionContext) { super.executeImpl(executionContext); } + + @Override + protected QueryConcurrencyPolicy getConcurrencyPolicy(ExecutionContext executionContext) { + boolean useGroupConcurrent = executionContext.getParamManager() + .getBoolean(ConnectionParams.DISCARD_TABLESPACE_USE_GROUP_CONCURRENT_BLOCK); + if (useGroupConcurrent) { + return QueryConcurrencyPolicy.GROUP_CONCURRENT_BLOCK; + } else { + return super.getConcurrencyPolicy(executionContext); + } + } + + @Override + public String remark() { + StringBuilder sb = new StringBuilder(); + sb.append("|discard tablespace detail: "); + sb.append("table_schema ["); + sb.append(schemaName); + sb.append("] "); + sb.append("table ["); + sb.append(logicalTableName); + sb.append("] "); + sb.append("target physical table info ["); + int j = 0; + for (Map.Entry>> entry : physicalPlanData.getTableTopology().entrySet()) { + if (j > 0) { + sb.append(", "); + } + j++; + sb.append("("); + sb.append(entry.getKey()).append(":"); + int i = 0; + for (List tbNames : entry.getValue()) { + if (i > 0) { + sb.append(", "); + } + sb.append(tbNames.get(0)); + i++; + } + sb.append(")"); + } + sb.append("]"); + return sb.toString(); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/DropTablePhyDdlWithCheckTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/DropTablePhyDdlWithCheckTask.java new file mode 100644 index 000000000..b0df1bd7e --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/DropTablePhyDdlWithCheckTask.java @@ -0,0 +1,29 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.ddl.job.task.BasePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; + +import java.util.Map; +import java.util.Set; + +@TaskName(name = "DropTablePhyDdlWithCheckTask") +public class DropTablePhyDdlWithCheckTask extends DropTablePhyDdlTask { + + Map> targetTableTopology; + + @JSONCreator + public DropTablePhyDdlWithCheckTask(String schemaName, PhysicalPlanData physicalPlanData, + Map> targetTableTopology) { + super(schemaName, physicalPlanData); + this.targetTableTopology = targetTableTopology; + } + + @Override + public void executeImpl(ExecutionContext executionContext) { + + super.executeImpl(executionContext); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/ImportTableSpaceDdlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/ImportTableSpaceDdlTask.java index ed89eaf9a..2629485c5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/ImportTableSpaceDdlTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/ImportTableSpaceDdlTask.java @@ -22,16 +22,25 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; -import com.alibaba.polardbx.executor.ddl.job.task.BasePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.RemoteExecutableDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; import com.alibaba.polardbx.executor.physicalbackfill.PhysicalBackfillUtils; +import com.alibaba.polardbx.gms.metadb.misc.ImportTableSpaceInfoStatAccessor; +import com.alibaba.polardbx.gms.metadb.misc.ImportTableSpaceInfoStatRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.config.table.ScaleOutPlanUtil; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.rpc.pool.XConnection; import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import com.google.common.collect.ImmutableList; +import io.airlift.slice.DataSize; import lombok.Getter; import org.apache.commons.lang3.StringUtils; +import java.sql.Connection; import java.sql.SQLException; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -39,26 +48,37 @@ import java.util.regex.Pattern; import static com.alibaba.polardbx.common.TddlConstants.LONG_ENOUGH_TIMEOUT_FOR_DDL_ON_XPROTO_CONN; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_CPU; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_IO; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_SYSTEM_LOCK; @Getter @TaskName(name = "ImportTableSpaceDdlTask") -public class ImportTableSpaceDdlTask extends BaseDdlTask { +public class ImportTableSpaceDdlTask extends BaseDdlTask implements RemoteExecutableDdlTask { private String logicalTableName; private String phyDbName; private String phyTableName; private Pair targetHost;//leader、follower or leaner private Pair userAndPasswd; + private long dataSize; + private long ioAdvise; @JSONCreator public ImportTableSpaceDdlTask(String schemaName, String logicalTableName, String phyDbName, String phyTableName, - Pair targetHost, Pair userAndPasswd) { + Pair targetHost, Pair userAndPasswd, + String targetDnId, + long dataSize, + long ioAdvise) { super(schemaName); this.logicalTableName = logicalTableName; this.phyDbName = phyDbName.toLowerCase(); this.phyTableName = phyTableName.toLowerCase(); this.targetHost = targetHost; this.userAndPasswd = userAndPasswd; + this.dataSize = dataSize; + this.ioAdvise = ioAdvise; + setResourceAcquired(buildResourceRequired(targetDnId, phyDbName + "//" + phyTableName, dataSize)); onExceptionTryRecoveryThenRollback(); } @@ -68,6 +88,24 @@ protected void beforeTransaction(ExecutionContext executionContext) { executeImpl(executionContext); } + DdlEngineResources buildResourceRequired(String targetDnId, String phyDbTableName, long dataSize) { + DdlEngineResources resourceRequired = new DdlEngineResources(); + String owner = "ImportTableSpace:" + phyDbTableName; + long importTableSpaceIo = 40L; + if (ioAdvise >= 10L && ioAdvise <= 100L) { + importTableSpaceIo = ioAdvise; + } + resourceRequired.request(targetDnId + DN_IO, importTableSpaceIo, owner); + resourceRequired.request(targetDnId + DN_CPU, 25L, owner); + resourceRequired.request(targetDnId + DN_SYSTEM_LOCK, 40L, owner); + return resourceRequired; + } + + @Override + public DdlEngineResources getDdlEngineResources() { + return this.resourceAcquired; + } + public void executeImpl(ExecutionContext executionContext) { ///!!!!!!DANGER!!!! // can't change variables via sql bypass CN @@ -88,7 +126,9 @@ public void executeImpl(ExecutionContext executionContext) { SQLRecorderLogger.ddlLogger.info( String.format("begin to execute import tablespace command %s, in host: %s, db:%s", importTableSpace, targetHost, phyDbName)); + long startTime = System.currentTimeMillis(); conn.execQuery(importTableSpace); + addImportTableSpaceStat(startTime); SQLRecorderLogger.ddlLogger.info( String.format("finish execute import tablespace command %s, in host: %s, db:%s", importTableSpace, targetHost, phyDbName)); @@ -135,7 +175,8 @@ protected void beforeRollbackTransaction(ExecutionContext ec) { @Override public String remark() { - return "|alter table " + phyTableName + " import tablespace, phyDb:" + phyDbName + " host:" + targetHost; + return "|alter table " + phyTableName + " import tablespace, phyDb:" + phyDbName + " host:" + targetHost + + " dataSize: " + DataSize.succinctBytes(dataSize); } public List explainInfo() { @@ -144,4 +185,25 @@ public List explainInfo() { command.add(importTableSpace); return command; } + + private void addImportTableSpaceStat(long startTime) { + try (Connection metadb = MetaDbUtil.getConnection()) { + ImportTableSpaceInfoStatRecord infoStatRecord = new ImportTableSpaceInfoStatRecord(); + infoStatRecord.setTaskId(taskId); + infoStatRecord.setTableSchema(schemaName); + infoStatRecord.setTableName(logicalTableName); + infoStatRecord.setPhysicalDb(phyDbName); + infoStatRecord.setPhysicalTable(phyTableName); + infoStatRecord.setDataSize(dataSize); + infoStatRecord.setStartTime(startTime); + infoStatRecord.setEndTime(System.currentTimeMillis()); + ImportTableSpaceInfoStatAccessor importTableSpaceInfoStatAccessor = new ImportTableSpaceInfoStatAccessor(); + importTableSpaceInfoStatAccessor.setConnection(metadb); + importTableSpaceInfoStatAccessor.insert(ImmutableList.of(infoStatRecord)); + metadb.commit(); + } catch (Exception ex) { + SQLRecorderLogger.ddlLogger.info( + String.format("fail to insert into IMPORT_TABLESPACE_INFO_STAT due to %s ", ex.toString())); + } + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/OptimizeTablePhyDdlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/OptimizeTablePhyDdlTask.java index 2804b7b1f..744aec19d 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/OptimizeTablePhyDdlTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/OptimizeTablePhyDdlTask.java @@ -39,12 +39,34 @@ public OptimizeTablePhyDdlTask(String schemaName, PhysicalPlanData physicalPlanD onExceptionTryRollback(); } - public List partition(int physicalTableCount) { + public List partition(int parallelism) { - List>>> topos = this.physicalPlanData.partitionTableTopology(physicalTableCount); + /** + *
+         *     Convert to data_struct from
+         *          Map{GrpKey,List[[t1_0,t2_0,t3_0],[t1_2,t2_2,t3_2],...]
+         *              grp1->[[t1_1,t2_1,t3_1],[t1_3,t2_2,t3_3],...]
+         *     to
+         *          SubMap1{grpKey, List[log_name_list_with_same_phy_index]}
+         *              grp0->[[t1_0,t2_0,t3_0],...]
+         *              grp1->[[t1_1,t2_1,t3_1],...]
+         *          SubMap2{grpKey, List[log_name_list_with_same_phy_index]}
+         *              grp0->[[t1_2,t2_2,t3_2],...]
+         *              grp1->[[t1_3,t2_2,t3_3],...]
+         *     by
+         *      the parallelism
+         *
+         * 
+ */ + List>>> topos = this.physicalPlanData.partitionTableTopology(parallelism); List>> params = - this.physicalPlanData.partitionParamsList(physicalTableCount); + this.physicalPlanData.partitionParamsList(parallelism); + /** + * Split one physicalPlanData into multi physicalPlanData by + * the submap list of topos. + */ List result = new ArrayList<>(); for (int i = 0; i < topos.size(); i++) { PhysicalPlanData p = this.physicalPlanData.clone(); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PauseCurrentJobTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PauseCurrentJobTask.java index 42a3e12fa..6a134ca53 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PauseCurrentJobTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PauseCurrentJobTask.java @@ -32,9 +32,12 @@ import java.sql.Connection; +/** + * set the current running task to pause status for test purpose + * 数据迁移测试专用,其他DDL请勿使用!!!! + */ @Getter @TaskName(name = "PauseCurrentJobTask") -// set the current running task to pause status for test purpose public class PauseCurrentJobTask extends BaseDdlTask { @JSONCreator @@ -63,7 +66,7 @@ public void rollbackImpl(Connection metaDbConnection, ExecutionContext execution @Override protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { executeImpl(metaDbConnection, executionContext); - updateSupportedCommands(false, true, metaDbConnection); + updateSupportedCommands(true, true, metaDbConnection); } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PhysicalBackfillTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PhysicalBackfillTask.java index 8694f436f..5de879f71 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PhysicalBackfillTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PhysicalBackfillTask.java @@ -24,8 +24,10 @@ import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.backfill.BatchConsumer; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.RemoteExecutableDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.ddl.newengine.cross.CrossEngineValidator; +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; import com.alibaba.polardbx.executor.ddl.workqueue.BackFillThreadPool; import com.alibaba.polardbx.executor.ddl.workqueue.PriorityFIFOTask; import com.alibaba.polardbx.executor.physicalbackfill.PhysicalBackfillManager; @@ -41,10 +43,10 @@ import com.alibaba.polardbx.statistics.SQLRecorderLogger; import com.google.common.collect.ImmutableList; import com.mysql.cj.polarx.protobuf.PolarxPhysicalBackfill; +import io.airlift.slice.DataSize; import lombok.Getter; import org.apache.commons.lang3.StringUtils; -import java.sql.SQLException; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -61,6 +63,13 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.CN_CPU; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.CN_NETWORK; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_CPU; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_IO; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_NETWORK; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_STORAGE; + /** * Created by luoyanxin. * @@ -68,12 +77,13 @@ */ @Getter @TaskName(name = "PhysicalBackfillTask") -public class PhysicalBackfillTask extends BaseDdlTask { +public class PhysicalBackfillTask extends BaseDdlTask implements RemoteExecutableDdlTask { private final String schemaName; private final String logicalTableName; private final Long backfillId;// use the taskId of CloneTableDataFileTask private final long batchSize; + private final long dataSize; private final long parallelism; private final long minUpdateBatch; @@ -103,6 +113,7 @@ public PhysicalBackfillTask(String schemaName, Pair sourceTargetDnId, Map> storageInstAndUserInfos, long batchSize, + long dataSize, long parallelism, long minUpdateBatch, boolean waitLsn, @@ -117,6 +128,7 @@ public PhysicalBackfillTask(String schemaName, this.sourceTargetDnId = sourceTargetDnId; this.storageInstAndUserInfos = storageInstAndUserInfos; this.batchSize = batchSize; + this.dataSize = dataSize; this.parallelism = Math.max(parallelism, 1); this.minUpdateBatch = minUpdateBatch; this.waitLsn = waitLsn; @@ -129,9 +141,33 @@ public PhysicalBackfillTask(String schemaName, throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, "missing source-target group mapping entry"); } + this.setResourceAcquired(buildResourceRequired(sourceTargetDnId, dataSize)); backfillManager = new PhysicalBackfillManager(schemaName); } + DdlEngineResources buildResourceRequired(Pair sourceTargetDnId, long dataSize) { + + String sourceDnId = sourceTargetDnId.getKey(); + String targetDnId = sourceTargetDnId.getValue(); + DdlEngineResources resourceRequired = new DdlEngineResources(); + String owner = "PhysicalBackfill:" + logicalTableName + getPhysicalTableName(); + resourceRequired.request(sourceDnId + DN_STORAGE, dataSize, owner); + resourceRequired.request(sourceDnId + DN_NETWORK, 33L, owner); + resourceRequired.request(sourceDnId + DN_CPU, 5L, owner); + resourceRequired.request(targetDnId + DN_STORAGE, dataSize, owner); + resourceRequired.request(targetDnId + DN_NETWORK, 33L, owner); + resourceRequired.request(targetDnId + DN_IO, 5L, owner); + resourceRequired.request(targetDnId + DN_CPU, 5L, owner); + resourceRequired.request(CN_NETWORK, 33L, owner); + resourceRequired.request(CN_CPU, 25L, owner); + return resourceRequired; + } + + @Override + public DdlEngineResources getDdlEngineResources() { + return this.resourceAcquired; + } + @Override protected void beforeTransaction(ExecutionContext executionContext) { updateTaskStateInNewTxn(DdlTaskState.DIRTY); @@ -251,7 +287,7 @@ protected void beforeRollbackTransaction(ExecutionContext ec) { @Override public String remark() { return "|physical backfill for table:" + physicalTableName + " from group:" + sourceTargetGroup.getKey() - + " to " + sourceTargetGroup.getValue(); + + " to " + sourceTargetGroup.getValue() + " dataSize: " + DataSize.succinctBytes(dataSize); } public void doExtract(ExecutionContext ec, BatchConsumer batchConsumer) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RebuildTableChangeMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RebuildTableChangeMetaTask.java index 177a417e3..618d36d4a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RebuildTableChangeMetaTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RebuildTableChangeMetaTask.java @@ -32,29 +32,46 @@ @Getter @TaskName(name = "RebuildTableChangeMetaTask") public class RebuildTableChangeMetaTask extends BaseGmsTask { + protected String sql; - public RebuildTableChangeMetaTask(String schemaName, String logicalTableName) { + public RebuildTableChangeMetaTask(String schemaName, String logicalTableName, String sql) { super(schemaName, logicalTableName); + this.sql = sql; } @Override protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { - EventLogger.log(EventType.DDL_INFO, "Online modify column start"); + EventLogger.log(EventType.DDL_INFO, + "Online modify column start, schema: " + schemaName + ", table: " + logicalTableName + ", sql: \"" + sql + + "\""); TableInfoManager tableInfoManager = new TableInfoManager(); tableInfoManager.setConnection(metaDbConnection); tableInfoManager.updateRebuildingTableFlag(schemaName, logicalTableName, false); + + LOGGER.info( + String.format( + "[rebuild table] start set rebuild table flag for primary table: %s.%s", + schemaName, logicalTableName) + ); } @Override protected void rollbackImpl(Connection metaDbConnection, ExecutionContext executionContext) { - EventLogger.log(EventType.DDL_WARN, "Online modify column rollback"); + EventLogger.log(EventType.DDL_WARN, + "Online modify column rollback" + schemaName + ", table: " + logicalTableName); TableInfoManager tableInfoManager = new TableInfoManager(); tableInfoManager.setConnection(metaDbConnection); tableInfoManager.updateRebuildingTableFlag(schemaName, logicalTableName, true); + + LOGGER.info( + String.format( + "[rebuild table] clean rebuild table flag for primary table: %s.%s by rollback", + schemaName, logicalTableName) + ); } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RebuildTableCleanFlagTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RebuildTableCleanFlagTask.java new file mode 100644 index 000000000..c34fdcb03 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RebuildTableCleanFlagTask.java @@ -0,0 +1,38 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; + +import java.sql.Connection; + +/** + * @author wumu + */ +@Getter +@TaskName(name = "RebuildTableCleanFlagTask") +public class RebuildTableCleanFlagTask extends BaseGmsTask { + public RebuildTableCleanFlagTask(String schemaName, String logicalTableName) { + super(schemaName, logicalTableName); + } + + @Override + protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + tableInfoManager.updateRebuildingTableFlag(schemaName, logicalTableName, true); + LOGGER.info( + String.format( + "[rebuild table] clean rebuild table flag for primary table: %s.%s", + schemaName, logicalTableName) + ); + } + + @Override + public String remark() { + String sb = "clean rebuilding table flag on table " + this.getLogicalTableName(); + return "|" + sb; + } +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RemoveTtlInfoTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RemoveTtlInfoTask.java new file mode 100644 index 000000000..bdaee77e3 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RemoveTtlInfoTask.java @@ -0,0 +1,25 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.polardbx.executor.ddl.job.meta.TableMetaChanger; +import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; + +import java.sql.Connection; + +@Getter +@TaskName(name = "RemoveTtlInfoTask") +public class RemoveTtlInfoTask extends BaseGmsTask { + + public RemoveTtlInfoTask(String schemaName, String logicalTableName) { + super(schemaName, logicalTableName); + } + + @Override + protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + TableMetaChanger.removeTtlInfoMeta(metaDbConnection, schemaName, logicalTableName); + TableMetaChanger.removeScheduledJobs(metaDbConnection, schemaName, logicalTableName); + updateSupportedCommands(true, false, metaDbConnection); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTableUpdateMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTableUpdateMetaTask.java index c2db2fd53..acbe6dadc 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTableUpdateMetaTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTableUpdateMetaTask.java @@ -54,11 +54,14 @@ protected void executeImpl(Connection metaDbConnection, ExecutionContext executi TableMetaChanger .renamePartitionTableMeta(metaDbConnection, schemaName, logicalTableName, newLogicalTableName, needRenamePhyTables, executionContext); + } else { TableMetaChanger .renameTableMeta(metaDbConnection, schemaName, logicalTableName, newLogicalTableName, needRenamePhyTables, executionContext); } + TableMetaChanger.renameTtlTableForTtlInfo(metaDbConnection, schemaName, logicalTableName, schemaName, + newLogicalTableName); CommonMetaChanger.renameFinalOperationsOnSuccess(schemaName, logicalTableName, newLogicalTableName); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTablesCdcSyncTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTablesCdcSyncTask.java index c61192fb4..a6615aa21 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTablesCdcSyncTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTablesCdcSyncTask.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.common.cdc.TablesExtInfo; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcMarkUtil; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.ddl.job.validator.GsiValidator; import com.alibaba.polardbx.executor.sync.LockTablesSyncAction; @@ -53,6 +54,7 @@ public class RenameTablesCdcSyncTask extends TablesSyncTask { private List collates; private List cdcMetas; private List>> newTableTopologies; + private final List versionIds; public RenameTablesCdcSyncTask(String schemaName, List tableNames, @@ -64,7 +66,8 @@ public RenameTablesCdcSyncTask(String schemaName, List newTableNames, List collates, List cdcMetas, - List>> newTableTopologies + List>> newTableTopologies, + List versionIds ) { super(schemaName, tableNames, preemptive, initWait, interval, timeUnit); this.oldTableNames = oldTableNames; @@ -72,6 +75,7 @@ public RenameTablesCdcSyncTask(String schemaName, this.collates = collates; this.cdcMetas = cdcMetas; this.newTableTopologies = newTableTopologies; + this.versionIds = versionIds; } @Override @@ -135,7 +139,7 @@ public void executeImpl(ExecutionContext executionContext) { CdcManagerHelper.getInstance() .notifyDdlNew(schemaName, tableName, "RENAME_TABLE", - ddlSql, ddlContext.getDdlType(), ddlContext.getJobId(), getTaskId(), + getDdlStmt(ddlSql, versionIds.get(i)), ddlContext.getDdlType(), ddlContext.getJobId(), getTaskId(), CdcDdlMarkVisibility.Public, params, true, newTableTopologies.get(i), new Pair<>(collates.get(i), cdcMetas.get(i))); } @@ -186,4 +190,11 @@ public void handleError(ExecutionContext executionContext) { throw GeneralUtil.nestedException(e); } } + + private String getDdlStmt(String ddl, Long versionId) { + if (CdcMarkUtil.isVersionIdInitialized(versionId)) { + return CdcMarkUtil.buildVersionIdHint(versionId) + ddl; + } + return ddl; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTablesUpdateMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTablesUpdateMetaTask.java index 3a94ae1c2..06d5176bd 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTablesUpdateMetaTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/RenameTablesUpdateMetaTask.java @@ -68,6 +68,8 @@ protected void executeImpl(Connection metaDbConnection, ExecutionContext executi .renameTableMeta(metaDbConnection, schemaName, tableName, newTableName, executionContext, false, false); } + TableMetaChanger.renameTtlTableForTtlInfo(metaDbConnection, schemaName, tableName, schemaName, + newTableName); CommonMetaChanger.renameFinalOperationsOnSuccess(schemaName, tableName, newTableName); } } @@ -90,6 +92,8 @@ protected void rollbackImpl(Connection metaDbConnection, ExecutionContext execut TableMetaChanger .renameTableMeta(metaDbConnection, schemaName, tableName, newTableName, true, executionContext); } + TableMetaChanger.renameTtlTableForTtlInfo(metaDbConnection, schemaName, tableName, schemaName, + newTableName); CommonMetaChanger.renameFinalOperationsOnSuccess(schemaName, tableName, newTableName); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/ResetSequence4TruncateTableTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/ResetSequence4TruncateTableTask.java new file mode 100644 index 000000000..e19d30c05 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/ResetSequence4TruncateTableTask.java @@ -0,0 +1,52 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.gms.util.SequenceUtil; +import com.alibaba.polardbx.executor.sync.SequenceSyncAction; +import com.alibaba.polardbx.executor.sync.SyncManagerHelper; +import com.alibaba.polardbx.gms.sync.SyncScope; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; + +import java.sql.Connection; + +import static com.alibaba.polardbx.common.constants.SequenceAttribute.AUTO_SEQ_PREFIX; + +/** + * Created by zhuqiwei. + * + * @author zhuqiwei + */ +@Getter +@TaskName(name = "ResetSequence4TruncateTableTask") +public class ResetSequence4TruncateTableTask extends BaseDdlTask { + final String logicalTableName; + final String schemaName; + + @JSONCreator + public ResetSequence4TruncateTableTask(String schemaName, String logicalTableName) { + super(schemaName); + this.schemaName = schemaName; + this.logicalTableName = logicalTableName; + onExceptionTryRecoveryThenRollback(); + } + + @Override + protected void duringTransaction(Connection metaDbConn, ExecutionContext executionContext) { + final String sequenceName = AUTO_SEQ_PREFIX + logicalTableName; + try { + SequenceUtil.resetSequence4TruncateTable(schemaName, logicalTableName, metaDbConn, executionContext); + SyncManagerHelper.sync(new SequenceSyncAction(schemaName, sequenceName), schemaName, + SyncScope.CURRENT_ONLY); + } catch (Exception e) { + LOGGER.error(String.format( + "error occurs while reset sequence, schemaName:%s, tableNames:%s, sequenceName:%s", schemaName, + logicalTableName, sequenceName), e); + } + LOGGER.info(String.format( + "reset sequence successful, schemaName:%s, tableNames:%s, sequenceName:%s", schemaName, logicalTableName, + sequenceName)); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/SubJobTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/SubJobTask.java index f96f43243..a85706741 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/SubJobTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/SubJobTask.java @@ -67,25 +67,28 @@ @TaskName(name = "SubJobTask") @Getter @Setter -public final class SubJobTask extends BaseDdlTask implements CostEstimableDdlTask { +public class SubJobTask extends BaseDdlTask implements CostEstimableDdlTask { - private String ddlStmt; + protected String ddlStmt; /** * -1: TransientDdlJob * 0: not submitted yet * \d{19}: subJob id */ - private long subJobId; + protected long subJobId; + + protected String rollbackDdlStmt; - private String rollbackDdlStmt; /** * -1: TransientDdlJob * 0: not submitted yet * \d{19}: subJob id */ - private long rollbackSubJobId; + protected long rollbackSubJobId; + + protected boolean parentAcquireResource; - private boolean parentAcquireResource; + protected boolean skipCdcMarkTask; public SubJobTask(String schemaName, String ddlStmt, String rollbackDdlStmt) { this(schemaName, ddlStmt, 0, rollbackDdlStmt, 0); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TableSyncTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TableSyncTask.java index 98a85f079..014d27463 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TableSyncTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TableSyncTask.java @@ -82,7 +82,7 @@ public void executeImpl(ExecutionContext executionContext) { throwExceptions); } else { SyncManagerHelper.sync( - new TableMetaChangePreemptiveSyncAction(schemaName, tableName, initWait, interval, timeUnit), + new TableMetaChangePreemptiveSyncAction(schemaName, tableName, initWait, interval, timeUnit, false), SyncScope.ALL, throwExceptions); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TablesSyncTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TablesSyncTask.java index ae7b9d6bd..b995927ce 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TablesSyncTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TablesSyncTask.java @@ -39,6 +39,7 @@ public class TablesSyncTask extends BaseSyncTask { final Long initWait; final Long interval; final TimeUnit timeUnit; + final boolean forceSyncFailed; public TablesSyncTask(String schemaName, List tableNames) { @@ -48,6 +49,7 @@ public TablesSyncTask(String schemaName, this.initWait = null; this.interval = null; this.timeUnit = null; + this.forceSyncFailed = false; } public TablesSyncTask(String schemaName, @@ -62,16 +64,33 @@ public TablesSyncTask(String schemaName, this.initWait = initWait; this.interval = interval; this.timeUnit = timeUnit; + this.forceSyncFailed = false; + } + + public TablesSyncTask(String schemaName, + List tableNames, + boolean preemptive, + Long initWait, + Long interval, + TimeUnit timeUnit, + boolean forceSyncFailed) { + super(schemaName); + this.tableNames = tableNames; + this.preemptive = preemptive; + this.initWait = initWait; + this.interval = interval; + this.timeUnit = timeUnit; + this.forceSyncFailed = forceSyncFailed; } @Override public void executeImpl(ExecutionContext executionContext) { try { if (!preemptive) { - SyncManagerHelper.sync(new TablesMetaChangeSyncAction(schemaName, tableNames), SyncScope.ALL, true); + SyncManagerHelper.sync(new TablesMetaChangeSyncAction(schemaName, tableNames, forceSyncFailed), SyncScope.ALL, true); } else { SyncManagerHelper.sync( - new TablesMetaChangePreemptiveSyncAction(schemaName, tableNames, initWait, interval, timeUnit), + new TablesMetaChangePreemptiveSyncAction(schemaName, tableNames, initWait, interval, timeUnit, forceSyncFailed), SyncScope.ALL, true); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TruncateTableRecycleBinTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TruncateTableRecycleBinTask.java index a441563fc..f10aece5b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TruncateTableRecycleBinTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TruncateTableRecycleBinTask.java @@ -17,9 +17,12 @@ package com.alibaba.polardbx.executor.ddl.job.task.basic; import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.executor.ddl.job.meta.TableMetaChanger; import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import lombok.Getter; @@ -46,7 +49,40 @@ public void executeImpl(Connection metaDbConnection, ExecutionContext executionC } @Override - protected void onExecutionSuccess(ExecutionContext executionContext) { - TableMetaChanger.afterTruncatingTableWithRecycleBin(schemaName, logicalTableName, binName); + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + executeImpl(metaDbConnection, executionContext); + updateTablesVersion(metaDbConnection); + if (!DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { + updateTablesExtVersion(metaDbConnection); + } + } + + private void updateTablesVersion(Connection metaDbConnection) { + try { + long version = TableInfoManager.getTableVersion4Rename(schemaName, logicalTableName, metaDbConnection); + long version2 = TableInfoManager.getTableVersion4Rename(schemaName, binName, metaDbConnection); + long maxVersion = Math.max(version, version2) + 1; + TableInfoManager.updateTableVersion4Rename(schemaName, logicalTableName, maxVersion, metaDbConnection); + TableInfoManager.updateTableVersion4Rename(schemaName, binName, maxVersion, metaDbConnection); + } catch (Throwable t) { + LOGGER.error(String.format( + "error occurs while update table version, schemaName:%s, tableName:%s", schemaName, logicalTableName)); + throw GeneralUtil.nestedException(t); + } + } + + private void updateTablesExtVersion(Connection metaDbConnection) { + try { + long version = TableInfoManager.getTableExtVersion4Rename(schemaName, logicalTableName, metaDbConnection); + long version2 = TableInfoManager.getTableExtVersion4Rename(schemaName, binName, metaDbConnection); + long maxVersion = Math.max(version, version2) + 1; + TableInfoManager.updateTableExtVersion4Rename(schemaName, logicalTableName, maxVersion, metaDbConnection); + TableInfoManager.updateTableExtVersion4Rename(schemaName, binName, maxVersion, metaDbConnection); + } catch (Throwable t) { + LOGGER.error(String.format( + "error occurs while update tables_ext version, schemaName:%s, tableName:%s", schemaName, + logicalTableName)); + throw GeneralUtil.nestedException(t); + } } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/UpdateTablesVersionTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/UpdateTablesVersionTask.java index 80e8511a4..c0e27296e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/UpdateTablesVersionTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/UpdateTablesVersionTask.java @@ -49,7 +49,7 @@ protected String remark() { @Override protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { - FailPoint.injectExceptionFromHintWithKeyEnable(FP_UPDATE_TABLES_VERSION_ERROR, executionContext); + FailPoint.injectExceptionFromHintWithKeyEnableCheck(FP_UPDATE_TABLES_VERSION_ERROR, executionContext); updateTablesVersion(metaDbConnection); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/ValidateDropViewTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/ValidateDropViewTask.java index 5cc1074d6..001e56213 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/ValidateDropViewTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/ValidateDropViewTask.java @@ -19,13 +19,20 @@ import com.alibaba.fastjson.annotation.JSONCreator; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.executor.ddl.job.task.BaseValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.gms.ttl.TtlInfoAccessor; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.view.SystemTableView; import lombok.Getter; +import java.sql.Connection; + @TaskName(name = "ValidateDropViewTask") @Getter public class ValidateDropViewTask extends BaseValidateTask { @@ -47,6 +54,21 @@ protected void executeImpl(ExecutionContext executionContext) { if (row == null) { throw new TddlRuntimeException(ErrorCode.ERR_VIEW, "Unknown view " + viewName); } + + /** + * Check if the view is created by archive table based on cci of ttl2.0 + */ + try (Connection metaDbConn = MetaDbDataSource.getInstance().getConnection()) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConn); + TtlInfoRecord ttlInfoRec = tableInfoManager.getTtlInfoRecordByArchiveTable(schemaName, viewName); + if (ttlInfoRec != null) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, + String.format("Dropping a view of archive table `%s` is not allowed", viewName)); + } + } catch (Throwable ex) { + throw GeneralUtil.nestedException(ex); + } } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/ArchiveOSSTableDataTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/ArchiveOSSTableDataTask.java index c36d8c641..3c40e0460 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/ArchiveOSSTableDataTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/ArchiveOSSTableDataTask.java @@ -93,6 +93,7 @@ protected void beforeTransaction(ExecutionContext executionContext) { @Override protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); new FileStorageAccessorDelegate() { @Override protected Integer invoke() { @@ -169,6 +170,7 @@ protected void loadTable(ExecutionContext executionContext, boolean supportPause ExecutionContext sourceDbContext = executionContext.copy(); sourceDbContext.setSchemaName(sourceLogicalSchema); sourceDbContext.setBackfillId(getTaskId()); + sourceDbContext.setTaskId(getTaskId()); TableMeta sourceTableMeta = executionContext.getSchemaManager(sourceLogicalSchema).getTable(sourceLogicalTable); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/ArchiveOSSTableDataWithPauseTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/ArchiveOSSTableDataWithPauseTask.java index 03438d4ad..3088ab105 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/ArchiveOSSTableDataWithPauseTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/ArchiveOSSTableDataWithPauseTask.java @@ -62,6 +62,7 @@ protected void onExecutionSuccess(ExecutionContext executionContext) { @Override protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); new FileStorageAccessorDelegate() { @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/BindingArchiveTableMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/BindingArchiveTableMetaTask.java index be1c2a56f..7c85bef37 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/BindingArchiveTableMetaTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/BindingArchiveTableMetaTask.java @@ -22,10 +22,14 @@ import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.executor.ddl.job.meta.TableMetaChanger; import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlTaskSqlBuilder; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; import com.alibaba.polardbx.gms.partition.TableLocalPartitionRecord; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; import lombok.Getter; import java.sql.Connection; @@ -34,25 +38,53 @@ @Getter @TaskName(name = "BindingArchiveTableMetaTask") public class BindingArchiveTableMetaTask extends BaseGmsTask { + + /** + * The schemaName of ttl table (oss archive source) + */ private String sourceTableSchema; + /** + * The tableName of ttl table (oss archive source) + */ private String sourceTableName; + + /** + * The new schemaName of oss table (oss archive table) + */ private String archiveTableSchema; + /** + * The new tableName of oss table (oss archive table) + */ private String archiveTableName; + + private String tableEngine; + private ArchiveMode archiveMode; + /** + * The old schemaName of oss table (oss archive table) bound to ttl table + */ private String oldArchiveTableSchema; + /** + * The old tableName of oss table (oss archive table) bound to ttl table + */ private String oldArchiveTableName; @JSONCreator public BindingArchiveTableMetaTask(String schemaName, String logicalTableName, String sourceTableSchema, String sourceTableName, String archiveTableSchema, String archiveTableName, + String tableEngine, ArchiveMode archiveMode) { super(schemaName, logicalTableName); + this.sourceTableSchema = sourceTableSchema; this.sourceTableName = sourceTableName; + this.archiveTableSchema = archiveTableSchema; this.archiveTableName = archiveTableName; + + this.tableEngine = tableEngine; this.archiveMode = archiveMode; } @@ -64,20 +96,35 @@ protected void executeImpl(Connection metaDbConnection, ExecutionContext executi // check old archive table name TableInfoManager tableInfoManager = new TableInfoManager(); tableInfoManager.setConnection(metaDbConnection); - TableLocalPartitionRecord record = + TableLocalPartitionRecord localPartRecord = tableInfoManager.getLocalPartitionRecord(sourceTableSchema, sourceTableName); + TtlInfoRecord ttlRecord = + tableInfoManager.getTtlInfoRecord(sourceTableSchema, sourceTableName); + + String oldArcTblSchema = null; + String oldArcTblName = null; + + boolean useTtl = ttlRecord != null; + boolean useLocalPart = localPartRecord != null; - // not a local partition table - if (record == null) { - throw GeneralUtil.nestedException( - MessageFormat.format("{0}.{1} is not a local partition table.", - sourceTableSchema, sourceTableName)); + if (!useTtl) { + // not a local partition table + if (!useLocalPart) { + throw GeneralUtil.nestedException( + MessageFormat.format("{0}.{1} is not a local partition table.", + sourceTableSchema, sourceTableName)); + } + oldArcTblSchema = localPartRecord.getArchiveTableSchema(); + oldArcTblName = localPartRecord.getArchiveTableName(); + } else { + oldArcTblSchema = ttlRecord.getArcTblSchema(); + oldArcTblName = ttlRecord.getArcTblName(); } // already has archive table but don't allow replace it. - if (record.getArchiveTableName() != null || record.getArchiveTableSchema() != null) { - this.oldArchiveTableName = record.getArchiveTableName(); - this.oldArchiveTableSchema = record.getArchiveTableSchema(); + if (oldArcTblSchema != null || oldArcTblName != null) { + this.oldArchiveTableName = oldArcTblName; + this.oldArchiveTableSchema = oldArcTblSchema; boolean allowReplace = executionContext.getParamManager().getBoolean(ConnectionParams.ALLOW_REPLACE_ARCHIVE_TABLE); if (!allowReplace) { @@ -87,18 +134,55 @@ protected void executeImpl(Connection metaDbConnection, ExecutionContext executi sourceTableSchema, sourceTableName, oldArchiveTableSchema, oldArchiveTableName)); } } - TableMetaChanger - .updateArchiveTable(metaDbConnection, sourceTableSchema, sourceTableName, archiveTableSchema, - archiveTableName); + + if (!useTtl) { + TableMetaChanger + .updateArchiveTable(metaDbConnection, sourceTableSchema, sourceTableName, archiveTableSchema, + archiveTableName); + } else { + Integer arcKind = TtlDefinitionInfo.getArcKindByEngine(tableEngine); + String arcTmpTblName = TtlUtil.buildArcTmpNameByArcTblName(archiveTableName); + String arcTmpTblSchema = archiveTableSchema; + TableMetaChanger + .updateArchiveTableForTtlInfo(metaDbConnection, arcKind, sourceTableSchema, sourceTableName, + archiveTableSchema, + archiveTableName, arcTmpTblSchema, arcTmpTblName); + } + try { + TableInfoManager.updateTableVersion(sourceTableSchema, sourceTableName, metaDbConnection); + } catch (Throwable ex) { + throw GeneralUtil.nestedException(ex); + } } } @Override public void rollbackImpl(Connection metaDbConnection, ExecutionContext executionContext) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + TtlInfoRecord ttlRecord = + tableInfoManager.getTtlInfoRecord(sourceTableSchema, sourceTableName); + boolean useRowLevelTtl = ttlRecord != null; + if (archiveMode == ArchiveMode.TTL && sourceTableSchema != null && sourceTableName != null && archiveTableSchema != null && archiveTableName != null) { - TableMetaChanger.updateArchiveTable(metaDbConnection, sourceTableSchema, sourceTableName, - oldArchiveTableSchema, oldArchiveTableName); + if (!useRowLevelTtl) { + TableMetaChanger.updateArchiveTable(metaDbConnection, sourceTableSchema, sourceTableName, + oldArchiveTableSchema, oldArchiveTableName); + } else { + Integer arcKind = TtlDefinitionInfo.getArcKindByEngine(""); + String oldArcTmpTblName = TtlUtil.buildArcTmpNameByArcTblName(oldArchiveTableName); + String oldArcTmpTblSchema = oldArchiveTableSchema; + TableMetaChanger.updateArchiveTableForTtlInfo(metaDbConnection, arcKind, sourceTableSchema, + sourceTableName, + oldArchiveTableSchema, oldArchiveTableName, oldArcTmpTblSchema, oldArcTmpTblName); + } + + try { + TableInfoManager.updateTableVersion(sourceTableSchema, sourceTableName, metaDbConnection); + } catch (Throwable ex) { + throw GeneralUtil.nestedException(ex); + } } } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/CreateOssTableGenerateDataTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/CreateOssTableGenerateDataTask.java index 9cbf01a83..e34c2bdfd 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/CreateOssTableGenerateDataTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/CreateOssTableGenerateDataTask.java @@ -181,6 +181,7 @@ protected Map invoke() { ExecutionContext sourceDbContext = executionContext.copy(); sourceDbContext.setSchemaName(sourceLogicalSchema); sourceDbContext.setBackfillId(getTaskId()); + sourceDbContext.setTaskId(getTaskId()); TableMeta sourceTableMeta = executionContext.getSchemaManager(sourceLogicalSchema).getTable(sourceLogicalTable); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/MoveDataToFileStoreTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/MoveDataToFileStoreTask.java index c7f7a1046..09f4afc53 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/MoveDataToFileStoreTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/MoveDataToFileStoreTask.java @@ -84,6 +84,7 @@ public MoveDataToFileStoreTask(String schemaName, String logicalTableName, Strin @Override protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); try (Connection metaDbConn = MetaDbUtil.getConnection()) { try { MetaDbUtil.beginTransaction(metaDbConn); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/MoveDataToInnodbTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/MoveDataToInnodbTask.java index 85a3b20db..03d4d7299 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/MoveDataToInnodbTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/MoveDataToInnodbTask.java @@ -74,6 +74,7 @@ public MoveDataToInnodbTask(String schemaName, String logicalTableName, @Override protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); // don't continue the ddl if it was paused try (Connection metaDbConn = MetaDbUtil.getConnection()) { try { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/OSSTaskUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/OSSTaskUtils.java index a7e5a1ee7..9c55d65c0 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/OSSTaskUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/OSSTaskUtils.java @@ -46,10 +46,6 @@ import com.google.common.collect.ImmutableList; import org.apache.commons.collections.CollectionUtils; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; @@ -59,6 +55,8 @@ import java.util.Optional; import java.util.Set; import java.util.TimeZone; +import java.util.TreeSet; +import java.util.stream.Collectors; import static com.alibaba.polardbx.optimizer.utils.ITimestampOracle.BITS_LOGICAL_TIME; @@ -153,6 +151,14 @@ public static List getFlattenedPartitionInfo(String schem return partitionInfos; } + public static List getFlattenedPartitionInfo(String schema, String table, + List partNames) { + Set partNamesSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + partNamesSet.addAll(partNames); + return getFlattenedPartitionInfo(schema, table).stream().filter(e -> partNamesSet.contains(e.getPartName())) + .collect(Collectors.toList()); + } + public static List getOrderedPartitionInfo(List partitionInfos, int total, int serial) { partitionInfos.sort(Comparator.comparing(PhysicalPartitionInfo::getPartBitSetIdx)); @@ -272,17 +278,4 @@ public static List dropTableTasks(Engine engine, String schemaName, Str tasks.add(tableSyncTask); return tasks; } - - public static long getTsFromTimestampWithTimeZone(String timestamp, TimeZone timeZone) { - String utcTimeStampString = - TimestampUtils.convertBetweenTimeZones(timestamp, timeZone, TimeZone.getTimeZone("UTC"), 0); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - LocalDateTime localDateTime = LocalDateTime.parse(utcTimeStampString, formatter); - Instant instant = localDateTime.toInstant(ZoneOffset.UTC); - if (instant.toEpochMilli() < 0) { - throw new IllegalArgumentException("timestamp should greater than 1970-01-01 00:00:01"); - } - long ts = instant.toEpochMilli() << BITS_LOGICAL_TIME; - return ts; - } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/OssArchiveCheckTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/OssArchiveCheckTask.java new file mode 100644 index 000000000..538eda578 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/OssArchiveCheckTask.java @@ -0,0 +1,164 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic.oss; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.ddl.newengine.DdlTaskState; +import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.archive.writer.OSSBackFillValidator; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.gsi.GsiUtils; +import com.alibaba.polardbx.gms.metadb.misc.DdlEngineTaskAccessor; +import com.alibaba.polardbx.gms.metadb.misc.DdlEngineTaskRecord; +import com.alibaba.polardbx.gms.metadb.table.FilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.FilesRecord; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.memory.QueryMemoryPoolHolder; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.pruning.PhysicalPartitionInfo; +import lombok.Getter; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * @author wumu + */ +@Getter +@TaskName(name = "OssArchiveCheckTask") +public class OssArchiveCheckTask extends BaseDdlTask { + protected final String ossTableName; + protected final String tmpTableSchema; + protected final String tmpTableName; + protected final List partitionNames; + protected final Long archiveTaskId; + + @JSONCreator + public OssArchiveCheckTask(String schemaName, String ossTableName, + String tmpTableSchema, String tmpTableName, + List partitionNames, Long archiveTaskId) { + super(schemaName); + this.ossTableName = ossTableName; + this.tmpTableSchema = tmpTableSchema; + this.tmpTableName = tmpTableName; + this.partitionNames = partitionNames; + this.archiveTaskId = archiveTaskId; + + // Pause if check failed. + onExceptionTryRecoveryThenPause(); + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + executeImpl(metaDbConnection, executionContext); + } + + protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + // 0. check task state and skip this task if allowed. + if (allowSkip(metaDbConnection)) { + return; + } + + // 1. find mapping: - files - physical_table, construct validators. + final String sourceLogicalSchema = tmpTableSchema; + final String sourceLogicalTable = tmpTableName; + TableMeta sourceTableMeta = + executionContext.getSchemaManager(sourceLogicalSchema).getTable(sourceLogicalTable); + final String targetLogicalSchema = schemaName; + final String targetLogicalTable = ossTableName; + + // handle single table. + Pair singleTopology = + OSSTaskUtils.getSingleTopology(sourceLogicalSchema, sourceLogicalTable, sourceTableMeta); + + PartitionInfo sourceTablePartitionInfo = + OSSTaskUtils.getSourcePartitionInfo(executionContext, sourceLogicalSchema, sourceLogicalTable); + final boolean isSingle = sourceTablePartitionInfo.isSingleTable(); + final boolean isBroadcast = sourceTablePartitionInfo.isBroadcastTable(); + + OSSBackFillValidator.ValidatorBound boundVal = findBoundVal(sourceLogicalTable); + + // construct back-fill validators. + FilesAccessor filesAccessor = new FilesAccessor(); + filesAccessor.setConnection(metaDbConnection); + List validatorList = new ArrayList<>(); + for (PhysicalPartitionInfo targetPhysicalPartitionInfo : + getFlattenedPartitionInfo(targetLogicalSchema, targetLogicalTable, partitionNames)) { + final String partName = targetPhysicalPartitionInfo.getPartName(); + Pair sourcePhySchemaAndTable = Optional + .ofNullable(singleTopology) + .orElseGet(() -> OSSTaskUtils.getSourcePhyTable(sourceTablePartitionInfo, partName)); + + String targetPhySchema = targetPhysicalPartitionInfo.getGroupKey(); + String targetPhyTable = targetPhysicalPartitionInfo.getPhyTable(); + String sourcePhySchema = sourcePhySchemaAndTable.getKey(); + String sourcePhyTable = sourcePhySchemaAndTable.getValue(); + + List filesRecords = filesAccessor.queryByPhyTableName( + targetLogicalSchema, targetLogicalTable, targetPhySchema, targetPhyTable, archiveTaskId); + + OSSBackFillValidator validator = new OSSBackFillValidator( + isSingle, isBroadcast, targetLogicalSchema, targetLogicalTable, targetPhySchema, targetPhyTable, + filesRecords, + sourceLogicalSchema, sourceLogicalTable, sourcePhySchema, sourcePhyTable, + partName, boundVal, getTaskId() + ); + validatorList.add(validator); + } + + // 2. invoke all validators + List validationResults = validatorList.stream() + .map(validator -> { + ExecutionContext xaEc = null; + try { + ExecutionContext.CopyOption copyOption = new ExecutionContext.CopyOption() + .setMemoryPoolHolder(new QueryMemoryPoolHolder()) + .setParameters(executionContext.cloneParamsOrNull()); + xaEc = executionContext.copy(copyOption); + xaEc.setTxIsolation(Connection.TRANSACTION_REPEATABLE_READ); + return GsiUtils.wrapWithTransaction( + ExecutorContext.getContext(schemaName).getTransactionManager(), + ITransactionPolicy.XA, + xaEc, + validator::validate); + } finally { + if (xaEc != null) { + xaEc.clearAllMemoryPool(); + } + } + }).collect(Collectors.toList()); + + // 3. pause ddl if check failed. + List failedResults = + validationResults.stream().filter(r -> !r.isCheckSuccess()).collect(Collectors.toList()); + if (!failedResults.isEmpty()) { + throw GeneralUtil.nestedException( + "Data validation failed! Check the source table modification during migration. " + + "Checksum info: " + validationResults.stream().map( + OSSBackFillValidator.ValidationResult::toString).collect(Collectors.toList())); + } + } + + protected List getFlattenedPartitionInfo(String schema, String table, + List partitionNames) { + return OSSTaskUtils.getFlattenedPartitionInfo(schema, table, partitionNames); + } + + protected boolean allowSkip(Connection metaDbConnection) { + DdlEngineTaskAccessor ddlEngineTaskAccessor = new DdlEngineTaskAccessor(); + ddlEngineTaskAccessor.setConnection(metaDbConnection); + DdlEngineTaskRecord ddlEngineTaskRecord = ddlEngineTaskAccessor.query(getJobId(), getTaskId()); + return ddlEngineTaskRecord.state != null + && DdlTaskState.valueOf(ddlEngineTaskRecord.state) == DdlTaskState.SUCCESS; + } + + protected OSSBackFillValidator.ValidatorBound findBoundVal(String sourceLogicalTable) { + return new OSSBackFillValidator.ValidatorBound(sourceLogicalTable, null, null, "MAX_VALUE"); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/OssTableArchivePartitionTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/OssTableArchivePartitionTask.java new file mode 100644 index 000000000..1386023c2 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/OssTableArchivePartitionTask.java @@ -0,0 +1,297 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic.oss; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.ddl.newengine.DdlTaskState; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.archive.writer.OSSBackFillExecutor; +import com.alibaba.polardbx.executor.archive.writer.OSSBackFillTimer; +import com.alibaba.polardbx.executor.archive.writer.OSSBackFillWriterTask; +import com.alibaba.polardbx.executor.ddl.job.meta.CommonMetaChanger; +import com.alibaba.polardbx.executor.ddl.job.meta.FileStorageBackFillAccessor; +import com.alibaba.polardbx.executor.ddl.job.task.BaseBackfillTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.ddl.newengine.meta.FileStorageAccessorDelegate; +import com.alibaba.polardbx.executor.gsi.GsiBackfillManager; +import com.alibaba.polardbx.gms.engine.FileSystemUtils; +import com.alibaba.polardbx.gms.metadb.table.ColumnMetasRecord; +import com.alibaba.polardbx.gms.metadb.table.FilesRecord; +import com.alibaba.polardbx.optimizer.config.table.OrcMetaUtils; +import com.alibaba.polardbx.optimizer.config.table.PolarDBXOrcSchema; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.pruning.PhysicalPartitionInfo; +import lombok.Getter; +import org.apache.hadoop.conf.Configuration; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.sql.Connection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author wumu + */ +@Getter +@TaskName(name = "OssTableArchivePartitionTask") +public class OssTableArchivePartitionTask extends BaseBackfillTask { + protected final String ossTableName; + protected final String tmpTableSchema; + protected final String tmpTableName; + protected final List partitionNames; + + protected final Engine targetTableEngine; + + @JSONCreator + public OssTableArchivePartitionTask(String ossSchemaName, String ossTableName, + String tmpTableSchema, String tmpTableName, + List partitionNames, Engine targetTableEngine) { + super(ossSchemaName); + this.ossTableName = ossTableName; + this.tmpTableSchema = tmpTableSchema; + this.tmpTableName = tmpTableName; + this.partitionNames = partitionNames; + this.targetTableEngine = targetTableEngine; + onExceptionTryRollback(); + } + + @Override + protected void beforeTransaction(ExecutionContext executionContext) { + updateSupportedCommands(true, true, null); + updateTaskStateInNewTxn(DdlTaskState.DIRTY); + executeImpl(executionContext); + } + + @Override + protected void onExecutionSuccess(ExecutionContext executionContext) { + updateSupportedCommands(true, true, null); + } + + @Override + protected void executeImpl(ExecutionContext executionContext) { + executionContext.setBackfillId(getTaskId()); + + new FileStorageAccessorDelegate() { + @Override + protected Integer invoke() { + // rollback unfinished files + List files = filesAccessor.queryUncommitted(getTaskId(), schemaName, ossTableName); + List columnMetas = + columnMetaAccessor.queryUncommitted(getTaskId(), schemaName, ossTableName); + deleteUncommitted(files, columnMetas); + filesAccessor.deleteUncommitted(getTaskId(), schemaName, ossTableName); + columnMetaAccessor.deleteUncommitted(getTaskId(), schemaName, ossTableName); + return 0; + } + }.execute(); + + // do real backfill + loadTable(executionContext); + } + + @Override + protected void duringRollbackTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + new FileStorageAccessorDelegate() { + @Override + protected Integer invoke() { + List files = + filesAccessor.queryByIdAndSchemaAndTable(getTaskId(), schemaName, ossTableName); + List columnMetas = + columnMetaAccessor.queryByIdAndSchemaAndTable(getTaskId(), schemaName, ossTableName); + deleteUncommitted(files, columnMetas); + filesAccessor.delete(getTaskId(), schemaName, ossTableName); + columnMetaAccessor.delete(getTaskId(), schemaName, ossTableName); + return 0; + } + }.execute(); + + // clear back-fill states + // if checkpoint resume is supported, this code block should be removed. + GsiBackfillManager manager = new GsiBackfillManager(schemaName); + manager.deleteByBackfillId(getTaskId()); + + // delete file_storage_backfill_object + FileStorageBackFillAccessor fileStorageBackFillAccessor = new FileStorageBackFillAccessor(); + fileStorageBackFillAccessor.setConnection(metaDbConnection); + fileStorageBackFillAccessor.deleteFileBackfillMeta(getTaskId()); + } + + protected void loadTable(ExecutionContext executionContext) { + Map, OSSBackFillWriterTask> tasks = null; + try { + String sourceLogicalSchema = this.tmpTableSchema; + String sourceLogicalTable = this.tmpTableName; + String targetLogicalSchema = this.schemaName; + String targetLogicalTable = this.ossTableName; + + ExecutionContext sourceDbContext = executionContext.copy(); + sourceDbContext.setSchemaName(sourceLogicalSchema); + sourceDbContext.setBackfillId(getTaskId()); + + TableMeta sourceTableMeta = + executionContext.getSchemaManager(sourceLogicalSchema).getTable(sourceLogicalTable); + if (!sourceTableMeta.isHasPrimaryKey()) { + throw new AssertionError("Table must have primary key"); + } + + TableMeta targetTableMeta = + executionContext.getSchemaManager(targetLogicalSchema).getTable(targetLogicalTable); + // build orc schema + PolarDBXOrcSchema orcSchema = OrcMetaUtils.buildPolarDBXOrcSchema(targetTableMeta); + + // data config + Configuration conf = OrcMetaUtils.getConfiguration(executionContext, orcSchema); + + tasks = buildOssBackFillLoaderTasks( + executionContext, + sourceLogicalSchema, + sourceLogicalTable, + targetLogicalSchema, + targetLogicalTable, + sourceTableMeta, + targetTableMeta, + orcSchema, + conf); + if (GeneralUtil.isEmpty(tasks)) { + return; + } + + Map> sourcePhyTables = OSSTaskUtils.genSourcePhyTables(tasks); + final int parallelism = + executionContext.getParamManager().getInt(ConnectionParams.OSS_BACKFILL_PARALLELISM); + final long indexStride = + executionContext.getParamManager().getLong(ConnectionParams.OSS_ORC_INDEX_STRIDE); + + // do backfill: select source table -> fill target orc file + OSSBackFillExecutor backFillExecutor = new OSSBackFillExecutor(Engine.INNODB, this.targetTableEngine); + backFillExecutor + .backFill2FileStore(sourceLogicalSchema, sourceLogicalTable, targetLogicalTable, sourceDbContext, + sourcePhyTables, + (int) indexStride, + parallelism, tasks, null, true); + + // flush all + tasks.forEach((pair, task) -> task.flush(sourceDbContext)); + + // wait all async task done. + tasks.forEach((pair, task) -> task.waitAsync()); + } catch (Exception e) { + // cancel all tasks + if (tasks != null) { + tasks.forEach((pair, task) -> task.cancelAsync()); + } + // pause ddl if support + OSSBackFillTimer.pauseDDL(executionContext); + throw GeneralUtil.nestedException(e); + } + } + + @NotNull + protected Map, OSSBackFillWriterTask> buildOssBackFillLoaderTasks( + ExecutionContext executionContext, + String sourceLogicalSchema, + String sourceLogicalTable, + String targetLogicalSchema, + String targetLogicalTable, + TableMeta sourceTableMeta, + TableMeta targetTableMeta, + PolarDBXOrcSchema orcSchema, + Configuration conf) { + final long maxRowsPerFile = executionContext.getParamManager().getLong(ConnectionParams.OSS_MAX_ROWS_PER_FILE); + final boolean removeTmpFiles = + executionContext.getParamManager().getBoolean(ConnectionParams.OSS_REMOVE_TMP_FILES); + + Map, OSSBackFillWriterTask> tasks = new HashMap<>(); + + // handle single table. + Pair singleTopology = + OSSTaskUtils.getSingleTopology(sourceLogicalSchema, sourceLogicalTable, sourceTableMeta); + + PartitionInfo sourceTablePartitionInfo = + OSSTaskUtils.getSourcePartitionInfo(executionContext, sourceLogicalSchema, sourceLogicalTable); + + // traverse each physical partition (phy table) + for (PhysicalPartitionInfo physicalPartitionInfo : + getFlattenedPartitionInfo(targetLogicalSchema, targetLogicalTable, partitionNames)) { + + String targetPhySchema = physicalPartitionInfo.getGroupKey(); + String targetPhyTable = physicalPartitionInfo.getPhyTable(); + + String partName = physicalPartitionInfo.getPartName(); + Pair sourcePhySchemaAndTable = Optional + .ofNullable(singleTopology) + .orElseGet(() -> OSSTaskUtils.getSourcePhyTable(sourceTablePartitionInfo, partName)); + String sourcePhySchema = sourcePhySchemaAndTable.getKey(); + String sourcePhyTable = sourcePhySchemaAndTable.getValue(); + + // for each physical table, add orc write task. + OSSBackFillWriterTask task = new OSSBackFillWriterTask( + // for target table + targetLogicalSchema, + targetLogicalTable, + targetPhySchema, + targetPhyTable, + + // for source table + sourcePhySchema, + sourcePhyTable, + sourceTableMeta, + targetTableEngine, + getTaskId(), + + // for orc file + conf, + null, + orcSchema, + targetTableMeta, + maxRowsPerFile, + removeTmpFiles, + executionContext, + true + ); + tasks.put(sourcePhySchemaAndTable, task); + } + return tasks; + } + + protected List getFlattenedPartitionInfo(String schema, String table, + List partitionNames) { + return OSSTaskUtils.getFlattenedPartitionInfo(schema, table, partitionNames); + } + + protected void deleteUncommitted(List files, List columnMetas) { + // delete remote oss files and local tmp files + for (FilesRecord record : files) { + FileSystemUtils.deleteIfExistsFile(record.getFileName(), this.targetTableEngine, false); + File tmpFile = new File(record.getLocalPath()); + if (tmpFile.exists()) { + if (!tmpFile.delete()) { + throw new TddlRuntimeException(ErrorCode.ERR_BACK_FILL_FAIL, + "can't delete file " + record.getLocalPath()); + } + } + } + CommonMetaChanger.clearOSSFileSystemCache( + files.stream().map(FilesRecord::getLocalPath).collect(Collectors.toList()), schemaName); + + // delete column meta and bf files + for (ColumnMetasRecord record : columnMetas) { + FileSystemUtils.deleteIfExistsFile(record.tableFileName, this.targetTableEngine, false); + } + } + + @Override + protected String remark() { + return String.format("|%s.%s.%s", schemaName, ossTableName, partitionNames); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/PurgeOssFileScheduleTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/PurgeOssFileScheduleTask.java index 7aae84f06..167ba6ea9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/PurgeOssFileScheduleTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/PurgeOssFileScheduleTask.java @@ -72,9 +72,9 @@ public synchronized void init(ParamManager paramManager) { List scheduledJobsRecordList = scheduledJobsAccessor.query(DefaultDbSchema.NAME, "purge_oss_file_schedule_task"); if (scheduledJobsRecordList.isEmpty()) { - TableMetaChanger.replaceScheduledJob(metaDbConnection, scheduledJobsRecord); + TableMetaChanger.addScheduledJob(metaDbConnection, scheduledJobsRecord); } else if (!scheduledJobsRecordList.get(0).getScheduleExpr().equalsIgnoreCase(cronExpr)) { - TableMetaChanger.replaceScheduledJob(metaDbConnection, scheduledJobsRecord); + TableMetaChanger.updateScheduledJob(metaDbConnection, scheduledJobsRecord); } } catch (Throwable t) { throw new TddlNestableRuntimeException(t); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/UnBindingArchiveTableMetaDirectTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/UnBindingArchiveTableMetaDirectTask.java index e2953fddb..ae24c9949 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/UnBindingArchiveTableMetaDirectTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/UnBindingArchiveTableMetaDirectTask.java @@ -30,23 +30,32 @@ public class UnBindingArchiveTableMetaDirectTask extends BaseGmsTask { private String archiveSchemaName; private String archiveTableName; + private boolean useRowLevelTtl = false; @JSONCreator public UnBindingArchiveTableMetaDirectTask(String schemaName, String logicalTableName, + boolean useRowLevelTtl, String archiveSchemaName, String archiveTableName) { super(schemaName, logicalTableName); this.archiveSchemaName = archiveSchemaName; this.archiveTableName = archiveTableName; + this.useRowLevelTtl = useRowLevelTtl; } @Override protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { TableInfoManager tableInfoManager = new TableInfoManager(); tableInfoManager.setConnection(metaDbConnection); - tableInfoManager - .unBindingByArchiveTableName(getSchemaName(), archiveTableName); + + if (useRowLevelTtl) { + tableInfoManager + .unBindingByArchiveTableNameForTtlInfo(getSchemaName(), archiveTableName); + } else { + tableInfoManager + .unBindingByArchiveTableName(getSchemaName(), archiveTableName); + } } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/UnBindingArchiveTableMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/UnBindingArchiveTableMetaTask.java index de5bbe18f..0d4568097 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/UnBindingArchiveTableMetaTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/basic/oss/UnBindingArchiveTableMetaTask.java @@ -17,15 +17,20 @@ package com.alibaba.polardbx.executor.ddl.job.task.basic.oss; import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.utils.CaseInsensitive; import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.druid.util.StringUtils; import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlTaskSqlBuilder; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; import com.alibaba.polardbx.executor.sync.TablesMetaChangePreemptiveSyncAction; import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; import com.alibaba.polardbx.gms.partition.TableLocalPartitionRecord; import com.alibaba.polardbx.gms.sync.SyncScope; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import lombok.Getter; @@ -45,6 +50,16 @@ public class UnBindingArchiveTableMetaTask extends BaseGmsTask { private List tables; private Map tableArchive; + /** + *
+     *     key : tblName
+     *     val :
+     * 
+ */ + private Map tableTtlTypeFlags = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + protected final static int TTL_TYPE_FLAG_LOCAL_PARTITION = 0; + protected final static int TTL_TYPE_FLAG_ROW_LEVEL_TTL = 1; + @JSONCreator public UnBindingArchiveTableMetaTask(String schemaName, List tables) { super(schemaName, null); @@ -60,10 +75,24 @@ protected void executeImpl(Connection metaDbConnection, ExecutionContext executi TableInfoManager tableInfoManager = new TableInfoManager(); tableInfoManager.setConnection(metaDbConnection); for (String table : tables) { + + TtlInfoRecord ttlInfoRecord = tableInfoManager.getTtlInfoRecord(getSchemaName(), table); + if (ttlInfoRecord != null) { + if (!StringUtils.isEmpty(ttlInfoRecord.getArcTblName())) { + tableArchive.put(table, ttlInfoRecord.getArcTblSchema() + "." + ttlInfoRecord.getArcTblName()); + tableTtlTypeFlags.put(table, UnBindingArchiveTableMetaTask.TTL_TYPE_FLAG_ROW_LEVEL_TTL); + String ttlTblSchema = getSchemaName(); + String ttlTblName = table; + tableInfoManager + .updateArchiveTableForTtlInfo(null, null, null, null, ttlTblSchema, ttlTblName); + } + } + TableLocalPartitionRecord record = tableInfoManager.getLocalPartitionRecord(getSchemaName(), table); if (record.getArchiveTableName() != null) { tableArchive.put(table, record.getArchiveTableSchema() + "." + record.getArchiveTableName()); + tableTtlTypeFlags.put(table, UnBindingArchiveTableMetaTask.TTL_TYPE_FLAG_LOCAL_PARTITION); tableInfoManager .updateArchiveTable(getSchemaName(), table, null, null); } @@ -76,10 +105,27 @@ public void rollbackImpl(Connection metaDbConnection, ExecutionContext execution TableInfoManager tableInfoManager = new TableInfoManager(); tableInfoManager.setConnection(metaDbConnection); for (Map.Entry entry : tableArchive.entrySet()) { + String tblName = entry.getKey(); String[] tableFull = entry.getValue().split("."); Preconditions.checkArgument(tableFull.length == 2); - tableInfoManager - .updateArchiveTable(getSchemaName(), entry.getKey(), tableFull[0], tableFull[1]); + + Integer flags = tableTtlTypeFlags.get(tblName); + if (flags != null) { + if (flags == UnBindingArchiveTableMetaTask.TTL_TYPE_FLAG_LOCAL_PARTITION) { + tableInfoManager + .updateArchiveTable(getSchemaName(), entry.getKey(), tableFull[0], tableFull[1]); + } else { + String ttlTblSchema = getSchemaName(); + String ttlTblName = entry.getKey(); + String arcTblSchema = tableFull[0]; + String arcTblName = tableFull[1]; + String arcTmpTblName = TtlUtil.buildArcTmpNameByArcTblName(arcTblName); + String arcTmpTblSchema = arcTblSchema; + tableInfoManager + .updateArchiveTableForTtlInfo(arcTblSchema, arcTblName, arcTmpTblSchema, arcTmpTblName, + ttlTblSchema, ttlTblName); + } + } } } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAllocateLocalPartitionMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAllocateLocalPartitionMarkTask.java new file mode 100644 index 000000000..c04ba2a9f --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAllocateLocalPartitionMarkTask.java @@ -0,0 +1,73 @@ +package com.alibaba.polardbx.executor.ddl.job.task.cdc; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.common.cdc.DdlScope; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.executor.utils.failpoint.FailPointKey; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; +import lombok.Setter; +import org.apache.calcite.sql.SqlKind; +import org.apache.commons.lang.StringUtils; + +import java.sql.Connection; +import java.util.Map; + +import static com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcMarkUtil.buildExtendParameter; + +/** + * description: + * author: chengjin.lyf + * create: 2024-08-19 18:52 + **/ +@TaskName(name = "CdcAllocateLocalPartitionMarkTask") +@Getter +@Setter +public class CdcAllocateLocalPartitionMarkTask extends BaseDdlTask { + + private final String tableName; + + @JSONCreator + public CdcAllocateLocalPartitionMarkTask(String schemaName, String tableName) { + super(schemaName); + this.tableName = tableName; + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + updateSupportedCommands(true, false, metaDbConnection); + FailPoint.injectRandomExceptionFromHint(executionContext); + FailPoint.injectRandomSuspendFromHint(executionContext); + DdlContext ddlContext = executionContext.getDdlContext(); + Map param = buildExtendParameter(executionContext); + param.put(ICdcManager.CDC_DDL_SCOPE, DdlScope.Schema); + + Map userDefVariables = executionContext.getUserDefVariables(); + + if (userDefVariables != null) { + String overRideNow = (String) userDefVariables.get(StringUtils.lowerCase(FailPointKey.FP_OVERRIDE_NOW)); + if (StringUtils.isNotBlank(overRideNow)) { + //used by local partition test case + param.put(FailPointKey.FP_OVERRIDE_NOW, overRideNow); + } + } + + CdcManagerHelper.getInstance() + .notifyDdlNew( + schemaName, + tableName, + SqlKind.ALLOCATE_LOCAL_PARTITION.name(), + ddlContext.getDdlStmt(), + ddlContext.getDdlType(), + ddlContext.getJobId(), + getTaskId(), + CdcDdlMarkVisibility.Protected, + param); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableColumnDdlMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableColumnDdlMarkTask.java index 4ad0e5e41..2d85869bd 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableColumnDdlMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableColumnDdlMarkTask.java @@ -20,6 +20,7 @@ import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; import com.alibaba.polardbx.common.cdc.CdcManagerHelper; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.ddl.job.task.BaseCdcTask; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; @@ -42,7 +43,7 @@ @TaskName(name = "CdcAlterTableColumnDdlMarkTask") @Getter @Setter -public class CdcAlterTableColumnDdlMarkTask extends BaseDdlTask { +public class CdcAlterTableColumnDdlMarkTask extends BaseCdcTask { private final PhysicalPlanData physicalPlanData; private final boolean useOMC; private final Long versionId; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableModifyTtlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableModifyTtlTask.java new file mode 100644 index 000000000..b5ca03cda --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableModifyTtlTask.java @@ -0,0 +1,59 @@ +package com.alibaba.polardbx.executor.ddl.job.task.cdc; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.common.cdc.DdlScope; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; +import lombok.Setter; +import org.apache.calcite.sql.SqlKind; + +import java.sql.Connection; +import java.util.Map; + +import static com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcMarkUtil.buildExtendParameter; + +/** + * + */ +@TaskName(name = "CdcAlterTableModifyTtlTask") +@Getter +@Setter +public class CdcAlterTableModifyTtlTask extends BaseDdlTask { + private final String tableName; + + @JSONCreator + public CdcAlterTableModifyTtlTask(String schemaName, String tableName) { + super(schemaName); + this.tableName = tableName; + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + updateSupportedCommands(true, false, metaDbConnection); + FailPoint.injectRandomExceptionFromHint(executionContext); + FailPoint.injectRandomSuspendFromHint(executionContext); + + DdlContext ddlContext = executionContext.getDdlContext(); + Map param = buildExtendParameter(executionContext); + param.put(ICdcManager.CDC_DDL_SCOPE, DdlScope.Instance); + + CdcManagerHelper.getInstance() + .notifyDdlNew( + schemaName, + tableName, + SqlKind.MODIFY_TTL.name(), + ddlContext.getDdlStmt(), + ddlContext.getDdlType(), + ddlContext.getJobId(), + getTaskId(), + CdcDdlMarkVisibility.Protected, + param); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableRemoveTtlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableRemoveTtlTask.java new file mode 100644 index 000000000..a86dba8ee --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableRemoveTtlTask.java @@ -0,0 +1,59 @@ +package com.alibaba.polardbx.executor.ddl.job.task.cdc; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.common.cdc.DdlScope; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; +import lombok.Setter; +import org.apache.calcite.sql.SqlKind; + +import java.sql.Connection; +import java.util.Map; + +import static com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcMarkUtil.buildExtendParameter; + +/** + * + */ +@TaskName(name = "CdcAlterTableRemoveTtlTask") +@Getter +@Setter +public class CdcAlterTableRemoveTtlTask extends BaseDdlTask { + private final String tableName; + + @JSONCreator + public CdcAlterTableRemoveTtlTask(String schemaName, String tableName) { + super(schemaName); + this.tableName = tableName; + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + updateSupportedCommands(true, false, metaDbConnection); + FailPoint.injectRandomExceptionFromHint(executionContext); + FailPoint.injectRandomSuspendFromHint(executionContext); + + DdlContext ddlContext = executionContext.getDdlContext(); + Map param = buildExtendParameter(executionContext); + param.put(ICdcManager.CDC_DDL_SCOPE, DdlScope.Instance); + + CdcManagerHelper.getInstance() + .notifyDdlNew( + schemaName, + tableName, + SqlKind.REMOVE_TTL.name(), + ddlContext.getDdlStmt(), + ddlContext.getDdlType(), + ddlContext.getJobId(), + getTaskId(), + CdcDdlMarkVisibility.Protected, + param); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableRenamePartitionMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableRenamePartitionMarkTask.java index c41654a56..2ea2eddc2 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableRenamePartitionMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableRenamePartitionMarkTask.java @@ -38,6 +38,7 @@ import java.util.List; import java.util.Map; +import static com.alibaba.polardbx.common.cdc.ICdcManager.CDC_IS_CCI; import static com.alibaba.polardbx.common.cdc.ICdcManager.CDC_IS_GSI; import static com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcMarkUtil.buildExtendParameter; @@ -54,12 +55,17 @@ public class CdcAlterTableRenamePartitionMarkTask extends BaseDdlTask { private final String tableName; private final boolean placeHolder; + private boolean isColumnarIndex; + private Long versionId; @JSONCreator - public CdcAlterTableRenamePartitionMarkTask(String schemaName, String tableName, boolean placeHolder) { + public CdcAlterTableRenamePartitionMarkTask(String schemaName, String tableName, boolean placeHolder, + boolean isColumnarIndex, Long versionId) { super(schemaName); this.tableName = tableName; this.placeHolder = placeHolder; + this.isColumnarIndex = isColumnarIndex; + this.versionId = versionId; } @Override @@ -83,7 +89,11 @@ protected void duringTransaction(Connection metaDbConnection, ExecutionContext e SQLAlterTableStatement stmt = (SQLAlterTableStatement) parseResult.get(0); if (stmt.getAlterIndexName() != null) { markTableName = SQLUtils.normalize(stmt.getTableName()); - param.put(CDC_IS_GSI, true); + if (!isColumnarIndex) { + param.put(CDC_IS_GSI, true); + } else { + param.put(CDC_IS_CCI, true); + } } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableRewrittenDdlMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableRewrittenDdlMarkTask.java index ac4ea8e30..39e1441e5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableRewrittenDdlMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableRewrittenDdlMarkTask.java @@ -21,6 +21,7 @@ import com.alibaba.polardbx.common.cdc.CdcManagerHelper; import com.alibaba.polardbx.common.ddl.newengine.DdlType; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.ddl.job.task.BaseCdcTask; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.optimizer.context.DdlContext; @@ -41,7 +42,7 @@ @TaskName(name = "CdcAlterTableRewrittenDdlMarkTask") @Getter @Setter -public class CdcAlterTableRewrittenDdlMarkTask extends BaseDdlTask { +public class CdcAlterTableRewrittenDdlMarkTask extends BaseCdcTask { private PhysicalPlanData physicalPlanData; private String logicalSql; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableSetTableGroupMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableSetTableGroupMarkTask.java index d6fbcf420..d613debb3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableSetTableGroupMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAlterTableSetTableGroupMarkTask.java @@ -24,11 +24,17 @@ import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.druid.sql.ast.SQLStatement; import com.alibaba.polardbx.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableItem; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableSetOption; import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.polardbx.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.polardbx.druid.sql.parser.ByteString; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableSetTableGroupChangeMetaOnlyTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlJobManager; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; import com.alibaba.polardbx.optimizer.context.DdlContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; @@ -56,14 +62,16 @@ public class CdcAlterTableSetTableGroupMarkTask extends BaseDdlTask { private final String primaryTableName; private final String gsiTableName; private final boolean gsi; + private final boolean withImplicitTablegroup; @JSONCreator public CdcAlterTableSetTableGroupMarkTask(String schemaName, String primaryTableName, String gsiTableName, - boolean gsi) { + boolean gsi, boolean withImplicitTablegroup) { super(schemaName); this.primaryTableName = primaryTableName; this.gsiTableName = gsiTableName; this.gsi = gsi; + this.withImplicitTablegroup = withImplicitTablegroup; } @Override @@ -79,6 +87,10 @@ protected void duringTransaction(Connection metaDbConnection, ExecutionContext e ddl = tryRewriteTableName(ddl); } + if (withImplicitTablegroup) { + ddl = tryRewriteTableGroupName(ddl); + } + CdcManagerHelper.getInstance() .notifyDdlNew( schemaName, @@ -107,4 +119,40 @@ private String tryRewriteTableName(String ddl) { } return ddl; } + + private String tryRewriteTableGroupName(String ddl) { + MySqlStatementParser parser = new MySqlStatementParser(ByteString.from(ddl)); + List parseResult = parser.parseStatementList(); + if (!parseResult.isEmpty() && parseResult.get(0) instanceof SQLAlterTableStatement) { + SQLAlterTableStatement alterTableStatement = (SQLAlterTableStatement) parseResult.get(0); + if (alterTableStatement.getItems().size() == 1) { + SQLAlterTableItem sqlAlterTableItem = alterTableStatement.getItems().get(0); + if (sqlAlterTableItem instanceof SQLAlterTableSetOption) { + SQLAlterTableSetOption item = (SQLAlterTableSetOption) sqlAlterTableItem; + if (item.isAlterTableGroup()) { + DdlJobManager jobManager = new DdlJobManager(); + List prevTasks = jobManager.getTasksFromMetaDB(getJobId(), + (new AlterTableSetTableGroupChangeMetaOnlyTask(null, null, null, null, false, false, null, + false)).getName()); + if (prevTasks.size() == 1) { + AlterTableSetTableGroupChangeMetaOnlyTask setTableGroupChangeMetaOnlyTask = + (AlterTableSetTableGroupChangeMetaOnlyTask) prevTasks.get(0); + //get the targetTableGroup from AlterTableSetTableGroupChangeMetaOnlyTask in the some job + String targetTableGroup = setTableGroupChangeMetaOnlyTask.getTargetTableGroup(); + + SQLAssignItem option = item.getOptions().get(0); + String value = SQLUtils.normalizeNoTrim(option.getValue().toString()); + if (!targetTableGroup.equalsIgnoreCase(value)) { + option.setValue(new SQLIdentifierExpr(targetTableGroup)); + item.setImplicit(true); + return SQLUtils.toSQLString(alterTableStatement, DbType.mysql, + new SQLUtils.FormatOption(true, false)); + } + } + } + } + } + } + return ddl; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcColumnarTableGroupDdlMark.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcColumnarTableGroupDdlMark.java new file mode 100644 index 000000000..dd1db8fc9 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcColumnarTableGroupDdlMark.java @@ -0,0 +1,107 @@ +/* + * 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 com.alibaba.polardbx.executor.ddl.job.task.cdc; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.common.ddl.newengine.DdlType; +import com.alibaba.polardbx.druid.DbType; +import com.alibaba.polardbx.druid.sql.SQLUtils; +import com.alibaba.polardbx.druid.sql.ast.SQLStatement; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.apache.calcite.sql.SqlKind; + +import java.sql.Connection; +import java.util.List; +import java.util.Map; + +import static com.alibaba.polardbx.common.cdc.ICdcManager.CDC_IS_CCI; +import static com.alibaba.polardbx.common.cdc.ICdcManager.DDL_ID; +import static com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcMarkUtil.buildExtendParameter; +import static com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcSqlUtils.SQL_PARSE_FEATURES; + +@TaskName(name = "CdcColumnarTableGroupDdlMark") +@Getter +@Setter +@Slf4j +public class CdcColumnarTableGroupDdlMark extends BaseDdlTask { + private String tableGroup; + private List tableNames; + private Long versionId; + + @JSONCreator + public CdcColumnarTableGroupDdlMark(String tableGroup, String schemaName, List tableNames, + Long versionId) { + super(schemaName); + this.tableGroup = tableGroup; + this.tableNames = tableNames; + this.versionId = versionId; + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + updateSupportedCommands(true, false, metaDbConnection); + mark4ColumnarTableGroupChange(executionContext); + } + + public void mark4ColumnarTableGroupChange(ExecutionContext executionContext) { + for (String tableName : tableNames) { + ExecutionContext ecCopy = executionContext.copy(); + Map param = buildExtendParameter(ecCopy); + + DdlContext ddlContext = ecCopy.getDdlContext(); + String ddlStmt = ddlContext.getDdlStmt(); + + String markTableName = tableName; + // alter index ... on table ... , 使用主表的名字进行打标 + List parseResult = SQLUtils.parseStatements(ddlStmt, DbType.mysql, SQL_PARSE_FEATURES); + if (!parseResult.isEmpty() && parseResult.get(0) instanceof SQLAlterTableStatement) { + SQLAlterTableStatement stmt = (SQLAlterTableStatement) parseResult.get(0); + if (stmt.getAlterIndexName() != null) { + markTableName = SQLUtils.normalize(stmt.getTableName()); + param.put(CDC_IS_CCI, true); + } + } + + // set DDL_ID to original ddl + param.put(DDL_ID, versionId); + param.put(ICdcManager.CDC_ORIGINAL_DDL, getDdlStmt(ddlStmt)); + CdcManagerHelper.getInstance() + .notifyDdlNew(schemaName, markTableName, SqlKind.ALTER_TABLE.name(), getDdlStmt(ddlStmt), + DdlType.ALTER_TABLEGROUP, + ddlContext.getJobId(), getTaskId(), CdcDdlMarkVisibility.Protected, param); + } + } + + private String getDdlStmt(String ddl) { + if (CdcMarkUtil.isVersionIdInitialized(versionId)) { + return CdcMarkUtil.buildVersionIdHint(versionId) + ddl; + } + return ddl; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcCreateViewMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcCreateViewMarkTask.java index c785fa7bc..b503e071f 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcCreateViewMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcCreateViewMarkTask.java @@ -64,6 +64,7 @@ protected void duringTransaction(Connection metaDbConnection, ExecutionContext e DdlContext ddlContext = executionContext.getDdlContext(); Map param = buildExtendParameter(executionContext); param.put(ICdcManager.CDC_DDL_SCOPE, DdlScope.Schema); + param.put(ICdcManager.REFRESH_CREATE_SQL_4_PHY_TABLE, false);// view should not refresh create phy sql if (isAlter) { CdcManagerHelper.getInstance() diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcDdlMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcDdlMarkTask.java index 6f2b5d041..e289294ff 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcDdlMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcDdlMarkTask.java @@ -30,7 +30,7 @@ import com.alibaba.polardbx.druid.sql.ast.statement.SQLDropMaterializedViewStatement; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.meta.TableMetaChanger; -import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.BaseCdcTask; import com.alibaba.polardbx.executor.ddl.job.task.columnar.CciSchemaEvolutionTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; @@ -65,13 +65,15 @@ @TaskName(name = "CdcDdlMarkTask") @Getter @Setter -public class CdcDdlMarkTask extends BaseDdlTask { +public class CdcDdlMarkTask extends BaseCdcTask { private final PhysicalPlanData physicalPlanData; private final Long versionId; private boolean useOriginalDDl; private boolean foreignKeys; + private boolean isCci = false; + /** * For statement like CREATE TABLE with CCI, * the original ddl statement will be normalized @@ -112,6 +114,11 @@ protected void duringTransaction(Connection metaDbConnection, ExecutionContext e return; } + if (executionContext.getDdlContext().isSkipSubJobCdcMark()) { + // 跳过子任务 cdc 打标 + return; + } + prepareExtraCmdsKey(executionContext); if (physicalPlanData.getKind() == SqlKind.CREATE_TABLE) { if (executionContext.getDdlContext() != null && @@ -152,6 +159,9 @@ private void prepareExtraCmdsKey(ExecutionContext executionContext) { if (foreignKeys) { executionContext.getExtraCmds().put(ICdcManager.FOREIGN_KEYS_DDL, "true"); } + if (isCci) { + executionContext.getExtraCmds().put(ICdcManager.CDC_IS_CCI, true); + } if (CdcMarkUtil.isVersionIdInitialized(versionId)) { CdcMarkUtil.useDdlVersionId(executionContext, versionId); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcDropColumnarIndexTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcDropColumnarIndexTask.java index 374a93a4c..b52c2313a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcDropColumnarIndexTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcDropColumnarIndexTask.java @@ -26,6 +26,7 @@ import com.alibaba.polardbx.optimizer.context.DdlContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import lombok.Getter; +import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; import java.sql.Connection; @@ -49,8 +50,8 @@ public CdcDropColumnarIndexTask(String schemaName, String logicalTableName, Stri @Override protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { SQLDropIndexStatement stmt = new SQLDropIndexStatement(); - stmt.setTableName(new SQLIdentifierExpr(logicalTableName)); - stmt.setIndexName(new SQLIdentifierExpr(indexName)); + stmt.setTableName(new SQLIdentifierExpr(SqlIdentifier.surroundWithBacktick(logicalTableName))); + stmt.setIndexName(new SQLIdentifierExpr(SqlIdentifier.surroundWithBacktick(indexName))); String markSql = CdcMarkUtil.buildVersionIdHint(versionId) + stmt; CdcMarkUtil.useDdlVersionId(executionContext, versionId); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcExpireLocalPartitionMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcExpireLocalPartitionMarkTask.java new file mode 100644 index 000000000..b90a54e48 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcExpireLocalPartitionMarkTask.java @@ -0,0 +1,74 @@ +package com.alibaba.polardbx.executor.ddl.job.task.cdc; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.common.cdc.DdlScope; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.executor.utils.failpoint.FailPointKey; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; +import lombok.Setter; +import org.apache.calcite.sql.SqlKind; +import org.apache.commons.lang.StringUtils; + +import java.sql.Connection; +import java.util.Map; + +import static com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcMarkUtil.buildExtendParameter; + +/** + * description: + * author: chengjin.lyf + * create: 2024-08-19 18:52 + **/ +@TaskName(name = "CdcExpireLocalPartitionMarkTask") +@Getter +@Setter +public class CdcExpireLocalPartitionMarkTask extends BaseDdlTask { + + private final String tableName; + + @JSONCreator + public CdcExpireLocalPartitionMarkTask(String schemaName, String tableName) { + super(schemaName); + this.tableName = tableName; + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + updateSupportedCommands(true, false, metaDbConnection); + FailPoint.injectRandomExceptionFromHint(executionContext); + FailPoint.injectRandomSuspendFromHint(executionContext); + + DdlContext ddlContext = executionContext.getDdlContext(); + Map param = buildExtendParameter(executionContext); + param.put(ICdcManager.CDC_DDL_SCOPE, DdlScope.Schema); + + Map userDefVariables = executionContext.getUserDefVariables(); + + if (userDefVariables != null) { + String overRideNow = (String) userDefVariables.get(StringUtils.lowerCase(FailPointKey.FP_OVERRIDE_NOW)); + if (StringUtils.isNotBlank(overRideNow)) { + //used by local partition test case + param.put(FailPointKey.FP_OVERRIDE_NOW, overRideNow); + } + } + + CdcManagerHelper.getInstance() + .notifyDdlNew( + schemaName, + tableName, + SqlKind.EXPIRE_LOCAL_PARTITION.name(), + ddlContext.getDdlStmt(), + ddlContext.getDdlType(), + ddlContext.getJobId(), + getTaskId(), + CdcDdlMarkVisibility.Protected, + param); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcGsiDdlMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcGsiDdlMarkTask.java index 275eb428c..a137d5c0c 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcGsiDdlMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcGsiDdlMarkTask.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.common.cdc.ICdcManager; import com.alibaba.polardbx.common.ddl.newengine.DdlType; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.ddl.job.task.BaseCdcTask; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; @@ -41,7 +42,7 @@ @TaskName(name = "CdcGsiDdlMarkTask") @Getter @Setter -public class CdcGsiDdlMarkTask extends BaseDdlTask { +public class CdcGsiDdlMarkTask extends BaseCdcTask { private final PhysicalPlanData physicalPlanData; private String originalDdl; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcInsertOverwriteTasks.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcInsertOverwriteTasks.java index 79fd48988..a208bfce2 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcInsertOverwriteTasks.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcInsertOverwriteTasks.java @@ -21,6 +21,7 @@ import com.alibaba.polardbx.common.cdc.CdcManagerHelper; import com.alibaba.polardbx.common.cdc.ICdcManager; import com.alibaba.polardbx.common.ddl.newengine.DdlType; +import com.alibaba.polardbx.executor.ddl.job.task.BaseCdcTask; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; @@ -48,7 +49,7 @@ public class CdcInsertOverwriteTasks { @TaskName(name = "DropOriginTableMarkTask") @Getter @Setter - public static class DropOriginTableMarkTask extends BaseDdlTask { + public static class DropOriginTableMarkTask extends BaseCdcTask { private final String logicTableName; @JSONCreator diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcLogicalSequenceMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcLogicalSequenceMarkTask.java index b1daf3c5a..5583ae304 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcLogicalSequenceMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcLogicalSequenceMarkTask.java @@ -64,7 +64,7 @@ protected void duringTransaction(Connection metaDbConnection, ExecutionContext e private void mark4LogicalSequence(ExecutionContext executionContext, SqlKind sqlKind, String schemaName, String sequenceName, String ddlSql) { CdcManagerHelper.getInstance() - .notifyDdlNew( + .notifySequenceDdl( schemaName, sequenceName, sqlKind.name(), diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcMarkUtil.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcMarkUtil.java index f5fd6a96e..828955f74 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcMarkUtil.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcMarkUtil.java @@ -145,4 +145,8 @@ public static void useDdlVersionId(ExecutionContext executionContext, Long versi public static boolean isVersionIdInitialized(Long versionId) { return !Objects.equals(versionId, DEFAULT_DDL_VERSION_ID); } + + public static boolean isScheduleJobDdl(String ddlSql) { + return ddlSql.startsWith("/*SCHEDULE_JOB_DDL*/"); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcModifyPartitionKeyMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcModifyPartitionKeyMarkTask.java index 337736d34..f563913b2 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcModifyPartitionKeyMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcModifyPartitionKeyMarkTask.java @@ -20,7 +20,7 @@ import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; import com.alibaba.polardbx.common.cdc.CdcManagerHelper; import com.alibaba.polardbx.common.cdc.ICdcManager; -import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.BaseCdcTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; import com.alibaba.polardbx.optimizer.config.table.TableMeta; @@ -41,20 +41,22 @@ @TaskName(name = "CdcModifyPartitionKeyMarkTask") @Getter @Setter -public class CdcModifyPartitionKeyMarkTask extends BaseDdlTask { +public class CdcModifyPartitionKeyMarkTask extends BaseCdcTask { private String logicalTableName; private String indexName; private SqlKind sqlKind; private Map exchangeNamesMapping; + private long versionId; @JSONCreator public CdcModifyPartitionKeyMarkTask(String schemaName, String logicalTableName, String indexName, - SqlKind sqlKind, Map exchangeNamesMapping) { + SqlKind sqlKind, Map exchangeNamesMapping, long versionId) { super(schemaName); this.logicalTableName = logicalTableName; this.indexName = indexName; this.sqlKind = sqlKind; this.exchangeNamesMapping = exchangeNamesMapping; + this.versionId = versionId; } @Override @@ -76,8 +78,15 @@ private void mark4RepartitionTable(ExecutionContext executionContext) { TableMeta indexTableMeta = executionContext.getSchemaManager().getTable(indexName); CdcManagerHelper.getInstance() - .notifyDdlNew(schemaName, logicalTableName, sqlKind.name(), ddlContext.getDdlStmt(), + .notifyDdlNew(schemaName, logicalTableName, sqlKind.name(), getDdlStmt(ddlContext.getDdlStmt(), versionId), ddlContext.getDdlType(), ddlContext.getJobId(), getTaskId(), CdcDdlMarkVisibility.Public, param, true, indexTableMeta.getLatestTopology()); } + + private String getDdlStmt(String ddl, Long versionId) { + if (CdcMarkUtil.isVersionIdInitialized(versionId)) { + return CdcMarkUtil.buildVersionIdHint(versionId) + ddl; + } + return ddl; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcMoveDatabaseDdlMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcMoveDatabaseDdlMarkTask.java index 7a5830254..dd66621b2 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcMoveDatabaseDdlMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcMoveDatabaseDdlMarkTask.java @@ -20,6 +20,7 @@ import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; import com.alibaba.polardbx.common.cdc.CdcManagerHelper; import com.alibaba.polardbx.common.ddl.newengine.DdlType; +import com.alibaba.polardbx.executor.ddl.job.task.BaseCdcTask; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; @@ -39,7 +40,7 @@ @TaskName(name = "CdcMoveDatabaseDdlMarkTask") @Getter @Setter -public class CdcMoveDatabaseDdlMarkTask extends BaseDdlTask { +public class CdcMoveDatabaseDdlMarkTask extends BaseCdcTask { private SqlKind sqlKind; private String ddlStmt; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcRepartitionLocalPartitionMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcRepartitionLocalPartitionMarkTask.java new file mode 100644 index 000000000..55bc4be90 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcRepartitionLocalPartitionMarkTask.java @@ -0,0 +1,73 @@ +package com.alibaba.polardbx.executor.ddl.job.task.cdc; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.common.cdc.DdlScope; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.executor.utils.failpoint.FailPointKey; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; +import lombok.Setter; +import org.apache.calcite.sql.SqlKind; +import org.apache.commons.lang.StringUtils; + +import java.sql.Connection; +import java.util.Map; + +import static com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcMarkUtil.buildExtendParameter; + +/** + * description: + * author: chengjin.lyf + * create: 2024-08-19 18:52 + **/ +@TaskName(name = "CdcRepartitionLocalPartitionMarkTask") +@Getter +@Setter +public class CdcRepartitionLocalPartitionMarkTask extends BaseDdlTask { + + private final String tableName; + + @JSONCreator + public CdcRepartitionLocalPartitionMarkTask(String schemaName, String tableName) { + super(schemaName); + this.tableName = tableName; + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + updateSupportedCommands(true, false, metaDbConnection); + FailPoint.injectRandomExceptionFromHint(executionContext); + FailPoint.injectRandomSuspendFromHint(executionContext); + DdlContext ddlContext = executionContext.getDdlContext(); + Map param = buildExtendParameter(executionContext); + param.put(ICdcManager.CDC_DDL_SCOPE, DdlScope.Schema); + + Map userDefVariables = executionContext.getUserDefVariables(); + + if (userDefVariables != null) { + String overRideNow = (String) userDefVariables.get(StringUtils.lowerCase(FailPointKey.FP_OVERRIDE_NOW)); + if (StringUtils.isNotBlank(overRideNow)) { + //used by local partition test case + param.put(FailPointKey.FP_OVERRIDE_NOW, overRideNow); + } + } + + CdcManagerHelper.getInstance() + .notifyDdlNew( + schemaName, + tableName, + SqlKind.REPARTITION_LOCAL_PARTITION.name(), + ddlContext.getDdlStmt(), + ddlContext.getDdlType(), + ddlContext.getJobId(), + getTaskId(), + CdcDdlMarkVisibility.Protected, + param); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcRepartitionMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcRepartitionMarkTask.java index bcc093136..f5c25b8e8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcRepartitionMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcRepartitionMarkTask.java @@ -21,6 +21,7 @@ import com.alibaba.polardbx.common.cdc.CdcManagerHelper; import com.alibaba.polardbx.common.cdc.ICdcManager; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.executor.ddl.job.task.BaseCdcTask; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; @@ -43,7 +44,7 @@ @TaskName(name = "CdcRepartitionMarkTask") @Getter @Setter -public class CdcRepartitionMarkTask extends BaseDdlTask { +public class CdcRepartitionMarkTask extends BaseCdcTask { private String logicalTableName; private SqlKind sqlKind; private CdcDdlMarkVisibility CdcDdlMarkVisibility; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTableGroupDdlMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTableGroupDdlMarkTask.java index acd00dd14..46a8924a9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTableGroupDdlMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTableGroupDdlMarkTask.java @@ -27,6 +27,7 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.polardbx.druid.sql.parser.ByteString; import com.alibaba.polardbx.druid.sql.parser.SQLParserUtils; +import com.alibaba.polardbx.executor.ddl.job.task.BaseCdcTask; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.gms.util.TableGroupNameUtil; @@ -54,7 +55,7 @@ @Getter @Setter @Slf4j -public class CdcTableGroupDdlMarkTask extends BaseDdlTask { +public class CdcTableGroupDdlMarkTask extends BaseCdcTask { private String tableGroup; private String tableName; @@ -62,11 +63,12 @@ public class CdcTableGroupDdlMarkTask extends BaseDdlTask { private Map> targetTableTopology; private String ddlStmt; private CdcDdlMarkVisibility cdcDdlMarkVisibility; + private boolean isColumnarIndex; @JSONCreator public CdcTableGroupDdlMarkTask(String tableGroup, String schemaName, String tableName, SqlKind sqlKind, Map> targetTableTopology, String ddlStmt, - CdcDdlMarkVisibility cdcDdlMarkVisibility) { + CdcDdlMarkVisibility cdcDdlMarkVisibility, boolean isColumnarIndex) { super(schemaName); this.tableGroup = tableGroup; this.tableName = tableName; @@ -75,12 +77,15 @@ public CdcTableGroupDdlMarkTask(String tableGroup, String schemaName, String tab this.ddlStmt = ddlStmt; this.cdcDdlMarkVisibility = cdcDdlMarkVisibility; + this.isColumnarIndex = isColumnarIndex; } @Override protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { updateSupportedCommands(true, false, metaDbConnection); - mark4TableGroupChange(executionContext); + if (!isColumnarIndex) { + mark4TableGroupChange(executionContext); + } } private void mark4TableGroupChange(ExecutionContext executionContext) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTruncateTableWithGsiMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTruncateTableWithGsiMarkTask.java index c4a8236d0..4eee86d79 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTruncateTableWithGsiMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTruncateTableWithGsiMarkTask.java @@ -20,7 +20,7 @@ import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; import com.alibaba.polardbx.common.cdc.CdcManagerHelper; import com.alibaba.polardbx.common.cdc.ICdcManager; -import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.BaseCdcTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; import com.alibaba.polardbx.gms.topology.DbInfoManager; @@ -42,17 +42,19 @@ @TaskName(name = "CdcTruncateTableWithGsiMarkTask") @Getter @Setter -public class CdcTruncateTableWithGsiMarkTask extends BaseDdlTask { +public class CdcTruncateTableWithGsiMarkTask extends BaseCdcTask { private String logicalTableName; private String tmpTableName; private String truncateSql; + private final long versionId; @JSONCreator - public CdcTruncateTableWithGsiMarkTask(String schemaName, String logicalTableName, String tmpTableName) { + public CdcTruncateTableWithGsiMarkTask(String schemaName, String logicalTableName, String tmpTableName, long versionId) { super(schemaName); this.logicalTableName = logicalTableName; this.tmpTableName = tmpTableName; this.truncateSql = String.format("truncate table %s", surroundWithBacktick(logicalTableName)); + this.versionId = versionId; } @Override @@ -79,9 +81,20 @@ private void mark4TruncateTableWithGsi(ExecutionContext executionContext) { } else { Map> tmpTableTopology = TruncateUtil.getTmpTableTopology(schemaName, tmpTableName); CdcManagerHelper.getInstance() - .notifyDdlNew(schemaName, logicalTableName, SqlKind.TRUNCATE_TABLE.name(), truncateSql, + .notifyDdlNew(schemaName, logicalTableName, SqlKind.TRUNCATE_TABLE.name(), getDdlStmt(truncateSql), ddlContext.getDdlType(), ddlContext.getJobId(), getTaskId(), CdcDdlMarkVisibility.Public, buildExtendParameter(executionContext), true, tmpTableTopology); } } + + private String getDdlStmt(String ddl) { + if (CdcMarkUtil.isVersionIdInitialized(versionId)) { + return CdcMarkUtil.buildVersionIdHint(versionId) + ddl; + } + return ddl; + } + @Override + protected String remark() { + return String.format("|ddlVersionId: %s", versionId); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTruncateWithRecycleMarkTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTruncateWithRecycleMarkTask.java index b633c2448..7295a3d44 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTruncateWithRecycleMarkTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcTruncateWithRecycleMarkTask.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.common.cdc.ICdcManager; import com.alibaba.polardbx.common.ddl.newengine.DdlType; import com.alibaba.polardbx.executor.ddl.job.meta.TableMetaChanger; +import com.alibaba.polardbx.executor.ddl.job.task.BaseCdcTask; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; @@ -43,7 +44,7 @@ @TaskName(name = "CdcTruncateWithRecycleMarkTask") @Getter @Setter -public class CdcTruncateWithRecycleMarkTask extends BaseDdlTask { +public class CdcTruncateWithRecycleMarkTask extends BaseCdcTask { public static final String CDC_RECYCLE_HINTS = "/* RECYCLEBIN_INTERMEDIATE_DDL=true */"; private final String sourceTableName; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/AlterTableGroupMovePartitionsCheckTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/AlterTableGroupMovePartitionsCheckTask.java index 708da0f79..f39b39fe2 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/AlterTableGroupMovePartitionsCheckTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/AlterTableGroupMovePartitionsCheckTask.java @@ -27,8 +27,10 @@ import com.alibaba.polardbx.executor.corrector.Checker; import com.alibaba.polardbx.executor.corrector.Reporter; import com.alibaba.polardbx.executor.ddl.job.task.BaseBackfillTask; +import com.alibaba.polardbx.executor.ddl.job.task.RemoteExecutableDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlEngineAccessorDelegate; +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; import com.alibaba.polardbx.executor.ddl.util.ChangeSetUtils; import com.alibaba.polardbx.executor.fastchecker.FastChecker; import com.alibaba.polardbx.executor.gsi.CheckerManager; @@ -40,8 +42,10 @@ import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; import com.alibaba.polardbx.gms.sync.SyncScope; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; +import com.alibaba.polardbx.optimizer.config.table.ScaleOutPlanUtil; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import io.airlift.slice.DataSize; import lombok.Getter; import org.apache.calcite.sql.SqlSelect; @@ -51,20 +55,28 @@ import java.util.Set; import java.util.concurrent.TimeUnit; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_CPU; +import static com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils.DN_IO; + @TaskName(name = "AlterTableGroupMovePartitionsCheckTask") @Getter -public class AlterTableGroupMovePartitionsCheckTask extends BaseBackfillTask { +public class AlterTableGroupMovePartitionsCheckTask extends BaseBackfillTask implements RemoteExecutableDdlTask { final private String logicalTableName; final private Map> sourcePhyTableNames; final private Map> targetPhyTableNames; final private Boolean stopDoubleWrite; final private List relatedTables; + final private long dataSize; @JSONCreator public AlterTableGroupMovePartitionsCheckTask(String schemaName, String logicalTableName, Map> sourcePhyTableNames, Map> targetPhyTableNames, - Boolean stopDoubleWrite, List relatedTables + Boolean stopDoubleWrite, + List relatedTables, + Set sourceStorageInsts, + Set targetStorageInsts, + long dataSize ) { super(schemaName); this.logicalTableName = logicalTableName; @@ -72,6 +84,10 @@ public AlterTableGroupMovePartitionsCheckTask(String schemaName, String logicalT this.targetPhyTableNames = targetPhyTableNames; this.stopDoubleWrite = stopDoubleWrite; this.relatedTables = relatedTables; + this.dataSize = dataSize; + if (sourceStorageInsts != null && targetStorageInsts != null) { + setResourceAcquired(buildResourceRequired(sourceStorageInsts, targetStorageInsts, dataSize)); + } onExceptionTryRollback(); } @@ -108,6 +124,26 @@ protected void executeImpl(ExecutionContext executionContext) { } } + @Override + public DdlEngineResources getDdlEngineResources() { + return this.resourceAcquired; + } + + DdlEngineResources buildResourceRequired(Set sourceStorageInsts, Set targetStorageInsts, + Long dataSize) { + String owner = "CheckTask:" + logicalTableName; + DdlEngineResources resourceRequired = new DdlEngineResources(); + for (String storageInst : sourceStorageInsts) { + resourceRequired.request(storageInst + DN_IO, 25L, owner); + resourceRequired.request(storageInst + DN_CPU, 25L, owner); + } + for (String storageInst : targetStorageInsts) { + resourceRequired.request(storageInst + DN_IO, 25L, owner); + resourceRequired.request(storageInst + DN_CPU, 25L, owner); + } + return resourceRequired; + } + @Override protected void onRollbackSuccess(ExecutionContext executionContext) { if (stopDoubleWrite) { @@ -281,4 +317,58 @@ private void checkInCN(ExecutionContext executionContext) { "alter tableGroup checker found error after backfill. Please try to rollback/recover this job"); } } + + @Override + public String remark() { + StringBuilder sb = new StringBuilder(); + sb.append("|checker detail: "); + sb.append("table_schema ["); + sb.append(schemaName); + sb.append("] "); + sb.append("table ["); + sb.append(logicalTableName); + sb.append("] "); + sb.append("source physical table info ["); + int j = 0; + for (Map.Entry> entry : sourcePhyTableNames.entrySet()) { + if (j > 0) { + sb.append(", "); + } + j++; + sb.append("("); + sb.append(entry.getKey()).append(":"); + int i = 0; + for (String tbName : entry.getValue()) { + if (i > 0) { + sb.append(", "); + } + sb.append(tbName); + i++; + } + sb.append(")"); + } + sb.append("], target physical table info ["); + j = 0; + for (Map.Entry> entry : targetPhyTableNames.entrySet()) { + if (j > 0) { + sb.append(", "); + } + j++; + sb.append("("); + sb.append(entry.getKey()).append(":"); + int i = 0; + for (String tbName : entry.getValue()) { + if (i > 0) { + sb.append(", "); + } + sb.append(tbName); + i++; + } + sb.append(")"); + } + sb.append("], size ["); + sb.append(DataSize.succinctBytes(dataSize)); + sb.append("]"); + return sb.toString(); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/ChangeSetCopyBaselineTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/ChangeSetCopyBaselineTask.java index 41c5f14ff..ff8aa56e6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/ChangeSetCopyBaselineTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/ChangeSetCopyBaselineTask.java @@ -55,6 +55,7 @@ public ChangeSetCopyBaselineTask(String schemaName, String logicalTableName, public void executeImpl(ExecutionContext executionContext) { executionContext = executionContext.copy(); executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); executionContext.setSchemaName(schemaName); FailPoint.injectRandomExceptionFromHint(executionContext); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/ChangeSetStartTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/ChangeSetStartTask.java index 566b5edcb..73ff5f3b0 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/ChangeSetStartTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/ChangeSetStartTask.java @@ -54,6 +54,7 @@ public ChangeSetStartTask(String schemaName, String logicalTableName, public void executeImpl(ExecutionContext executionContext) { executionContext = executionContext.copy(); executionContext.setBackfillId(getTaskId()); + executionContext.setTaskId(getTaskId()); executionContext.setSchemaName(schemaName); ChangeSetManager changeSetManager = new ChangeSetManager(schemaName); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/MoveTableCheckTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/MoveTableCheckTask.java index 64a7babde..aa3fd24de 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/MoveTableCheckTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/changset/MoveTableCheckTask.java @@ -27,6 +27,7 @@ import com.alibaba.polardbx.executor.corrector.Checker; import com.alibaba.polardbx.executor.corrector.Reporter; import com.alibaba.polardbx.executor.ddl.job.task.BaseBackfillTask; +import com.alibaba.polardbx.executor.ddl.job.task.RemoteExecutableDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlEngineAccessorDelegate; import com.alibaba.polardbx.executor.ddl.util.ChangeSetUtils; @@ -40,8 +41,10 @@ import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; import com.alibaba.polardbx.gms.sync.SyncScope; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; +import com.alibaba.polardbx.optimizer.config.table.ScaleOutPlanUtil; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import io.airlift.slice.DataSize; import lombok.Getter; import org.apache.calcite.sql.SqlSelect; @@ -53,20 +56,23 @@ @TaskName(name = "MoveTableCheckTask") @Getter -public class MoveTableCheckTask extends BaseBackfillTask { +public class MoveTableCheckTask extends BaseBackfillTask implements RemoteExecutableDdlTask { final private String logicalTableName; final private Map sourceTargetGroup; final private Map> sourcePhyTableNames; final private Map> targetPhyTableNames; final private Boolean optimizeDoubleWrite; final private List relatedTables; + final private long dataSize; @JSONCreator public MoveTableCheckTask(String schemaName, String logicalTableName, Map sourceTargetGroup, Map> sourcePhyTableNames, Map> targetPhyTableNames, - Boolean optimizeDoubleWrite, List relatedTables + Boolean optimizeDoubleWrite, + List relatedTables, + long dataSize ) { super(schemaName); this.logicalTableName = logicalTableName; @@ -75,6 +81,7 @@ public MoveTableCheckTask(String schemaName, String logicalTableName, this.targetPhyTableNames = targetPhyTableNames; this.optimizeDoubleWrite = optimizeDoubleWrite; this.relatedTables = relatedTables; + this.dataSize = dataSize; onExceptionTryRollback(); } @@ -289,7 +296,56 @@ boolean fastCheck(ExecutionContext executionContext) { } @Override - protected String remark() { - return "|tableName: " + logicalTableName; + public String remark() { + StringBuilder sb = new StringBuilder(); + sb.append("|checker detail: "); + sb.append("table_schema ["); + sb.append(schemaName); + sb.append("] "); + sb.append("table ["); + sb.append(logicalTableName); + sb.append("] "); + sb.append("source physical table info ["); + int j = 0; + for (Map.Entry> entry : sourcePhyTableNames.entrySet()) { + if (j > 0) { + sb.append(", "); + } + j++; + sb.append("("); + sb.append(entry.getKey()).append(":"); + int i = 0; + for (String tbName : entry.getValue()) { + if (i > 0) { + sb.append(", "); + } + sb.append(tbName); + i++; + } + sb.append(")"); + } + sb.append("], target physical table info ["); + j = 0; + for (Map.Entry> entry : targetPhyTableNames.entrySet()) { + if (j > 0) { + sb.append(", "); + } + j++; + sb.append("("); + sb.append(entry.getKey()).append(":"); + int i = 0; + for (String tbName : entry.getValue()) { + if (i > 0) { + sb.append(", "); + } + sb.append(tbName); + i++; + } + sb.append(")"); + } + sb.append("], size ["); + sb.append(DataSize.succinctBytes(dataSize)); + sb.append("]"); + return sb.toString(); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciIncrementTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciIncrementTask.java new file mode 100644 index 000000000..a8ce328bc --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciIncrementTask.java @@ -0,0 +1,113 @@ +package com.alibaba.polardbx.executor.ddl.job.task.columnar; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.executor.columnar.checker.CciIncrementalChecker; +import com.alibaba.polardbx.executor.columnar.checker.ICciChecker; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.gsi.CheckerManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.CheckCciPrepareData; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import lombok.Getter; +import org.apache.calcite.sql.SqlCheckColumnarIndex; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + +/** + * @author yaozhili + */ +@Getter +@TaskName(name = "CheckCciIncrementTask") +public class CheckCciIncrementTask extends CheckCciBaseTask { + private final static Logger LOG = LoggerFactory.getLogger(CheckCciIncrementTask.class); + + final List reports = new ArrayList<>(); + long tsoV0; + long tsoV1; + long innodbTso; + + public static CheckCciIncrementTask create(CheckCciPrepareData prepareData) { + return new CheckCciIncrementTask( + prepareData.getSchemaName(), + prepareData.getTableName(), + prepareData.getIndexName(), + prepareData.getExtraCmd(), + prepareData.getTsoList().get(0), + prepareData.getTsoList().get(1), + prepareData.getTsoList().get(2) + ); + } + + @JSONCreator + public CheckCciIncrementTask(String schemaName, + String tableName, + String indexName, + SqlCheckColumnarIndex.CheckCciExtraCmd extraCmd, + long tsoV0, + long tsoV1, + long innodbTso) { + super(schemaName, tableName, indexName, extraCmd); + this.tsoV0 = tsoV0; + this.tsoV1 = tsoV1; + this.innodbTso = innodbTso; + } + + @Override + protected void beforeTransaction(ExecutionContext executionContext) { + // Check. + ICciChecker checker = new CciIncrementalChecker(schemaName, tableName, indexName); + doCheck(executionContext, checker); + } + + protected void doCheck(ExecutionContext executionContext, ICciChecker checker) { + long startTime = System.nanoTime(); + try { + checker.check(executionContext, tsoV0, tsoV1, innodbTso); + } catch (Throwable t) { + reports.add( + createReportRecord( + CheckCciMetaTask.ReportErrorType.SUMMARY, + CheckerManager.CheckerReportStatus.FOUND, + "Error occurs when checking, caused by " + t.getMessage() + )); + SQLRecorderLogger.ddlLogger.error(t); + } + + List checkReports = new ArrayList<>(); + if (!checker.getCheckReports(checkReports)) { + // Inconsistency detected. + for (String error : checkReports) { + reports.add(createReportRecord(CheckCciMetaTask.ReportErrorType.SUMMARY, + CheckerManager.CheckerReportStatus.FOUND, error)); + } + } else if (!checkReports.isEmpty()) { + for (String report : checkReports) { + reports.add(createReportRecord(CheckCciMetaTask.ReportErrorType.SUMMARY, + CheckerManager.CheckerReportStatus.FINISH, report)); + } + } + + reports.add( + createReportRecord( + CheckCciMetaTask.ReportErrorType.SUMMARY, + CheckerManager.CheckerReportStatus.FINISH, + "incremental data of columnar index between " + tsoV0 + " and " + tsoV1 + " checked." + + "Cost " + (System.nanoTime() - startTime) / 1000000 + "ms." + )); + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + // Add reports to metadb.checker_reports + CheckerManager.insertReports(metaDbConnection, reports); + } + + @Override + public String remark() { + return String.format("|CciIncrementCheck(%s.%s)", tableName, indexName); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciMetaTask.java index b96bc4457..e115144d6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciMetaTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciMetaTask.java @@ -32,6 +32,7 @@ import com.alibaba.polardbx.executor.gsi.CheckerManager.CheckerReport; import com.alibaba.polardbx.executor.gsi.CheckerManager.CheckerReportStatus; import com.alibaba.polardbx.gms.metadb.table.ColumnarColumnEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableStatus; @@ -139,8 +140,8 @@ private List checkAndReport(Blackboard blackboard) { // 3. Check columnar index related meta reports.addAll(checkCciTableAndColumnEvolution(blackboard)); - // 4. Check CDC mark - reports.addAll(checkCdcDdlMark(blackboard)); + // 4. Check Create CCI CDC mark + reports.addAll(checkCreateCciCdcDdlMark(blackboard)); // 5. Check CCI partitioning (table partition, table group) reports.addAll(checkCciPartitioning(blackboard)); @@ -341,11 +342,63 @@ private List checkCciPartitioning(Blackboard blackboard) { .report()); } + final List columnarTableMappingRecords = + blackboard.queryColumnarTableMapping(schemaName, tableName, indexName); + + // Check table mapping status + final ColumnarTableMappingRecord columnarTableMapping = columnarTableMappingRecords.get(0); + final long indexTableId = columnarTableMapping.tableId; + final long latestVersionId = columnarTableMapping.latestVersionId; + final List tableEvolutionRecords = + blackboard.queryColumnarTableEvolution(indexTableId, latestVersionId); + + // Check columnar partition evolution records + final List actualColumnarPartitionEvoRecords = + blackboard.queryColumnarPartitionEvolution(tableEvolutionRecords.get(0).partitions); + if (actualColumnarPartitionEvoRecords.isEmpty()) { + reports.add( + createReportRecord( + ReportErrorType.MISSING_COLUMNAR_PARTITION_EVOLUTION_META, + CheckerReportStatus.FOUND, + String.format( + "Missing columnar partition evolution meta of index %s.%s.%s", + schemaName, tableName, indexName))); + return reports; + } + + // Column meta of column store (actual) + // map> + final Map>> colEvoMap = new HashMap<>(); + // map + final Map actualColumnNameFieldIdMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + actualColumnarPartitionEvoRecords.forEach(ccer -> { + actualColumnNameFieldIdMap.put(ccer.partitionRecord.partName, ccer.id); + colEvoMap + .computeIfAbsent(ccer.id, k -> new ArrayList<>()) + .add(Pair.of(ccer.id, ccer.partitionRecord)); + }); + // map + final Map> actualColLatestMap = new HashMap<>(); + colEvoMap.forEach((id, partitionRecordPair) -> + partitionRecordPair + .stream() + .max(Comparator.comparing(Pair::getKey)) + .ifPresent(cr -> actualColLatestMap.put(id, cr))); + // map + final ImmutableConcatMap> actualColumnRecordMap = + new ImmutableConcatMap<>(actualColumnNameFieldIdMap, actualColLatestMap); + + // Check columnar column evolution records (reverseOrder) + reports.addAll(checkPartitionEvolutionRecords(partitionRecords, actualColumnRecordMap)); + + // Check columnar table evolution records + reports.addAll(checkTableEvolutionPartitionRecord(tableEvolutionRecords.get(0), actualColLatestMap)); + return reports; } @NotNull - private List checkCdcDdlMark(Blackboard blackboard) { + private List checkCreateCciCdcDdlMark(Blackboard blackboard) { final List reports = new ArrayList<>(); final List columnarTableMappingRecords = @@ -354,10 +407,10 @@ private List checkCdcDdlMark(Blackboard blackboard) { // Table mapping has been checked in #checkCciTableAndColumnEvolution final ColumnarTableMappingRecord columnarTableMapping = columnarTableMappingRecords.get(0); final long indexTableId = columnarTableMapping.tableId; - final long latestVersionId = columnarTableMapping.latestVersionId; final ColumnarTableEvolutionRecord columnarTableEvolutionRecord = - blackboard.queryColumnarTableEvolution(indexTableId, latestVersionId).get(0); + blackboard.queryColumnarTableEvolution(indexTableId).get(0); + long versionId = columnarTableEvolutionRecord.versionId; final long ddlJobId = columnarTableEvolutionRecord.ddlJobId; final List cdcDdlRecords = CdcManagerHelper.getInstance().queryDdlByJobId(ddlJobId); @@ -408,7 +461,7 @@ private List checkCdcDdlMark(Blackboard blackboard) { // Check CREATE INDEX / CREATE TABLE statement final String ddlSql = ddlExtInfo.getOriginalDdl(); - reports.addAll(checkCreateCciSql(ddlSql, latestVersionId, blackboard)); + reports.addAll(checkCreateCciSql(ddlSql, versionId, blackboard)); return reports; } @@ -727,18 +780,18 @@ private List checkCciTableAndColumnEvolution(Blackboard blackboar // map final Map actualColumnNameFieldIdMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); actualColumnarColumnEvoRecords.forEach(ccer -> { - actualColumnNameFieldIdMap.put(ccer.columnsRecord.columnName, ccer.fieldId); + actualColumnNameFieldIdMap.put(ccer.columnsRecord.columnName, ccer.id); colEvoMap - .computeIfAbsent(ccer.fieldId, k -> new ArrayList<>()) + .computeIfAbsent(ccer.id, k -> new ArrayList<>()) .add(Pair.of(ccer.id, ccer.columnsRecord)); }); // map final Map> actualColLatestMap = new HashMap<>(); - colEvoMap.forEach((fieldId, columnarRecordPair) -> + colEvoMap.forEach((id, columnarRecordPair) -> columnarRecordPair .stream() .max(Comparator.comparing(Pair::getKey)) - .ifPresent(cr -> actualColLatestMap.put(fieldId, cr))); + .ifPresent(cr -> actualColLatestMap.put(id, cr))); // map final ImmutableConcatMap> actualColumnRecordMap = new ImmutableConcatMap<>(actualColumnNameFieldIdMap, actualColLatestMap); @@ -747,7 +800,7 @@ private List checkCciTableAndColumnEvolution(Blackboard blackboar reports.addAll(checkColumnEvolutionRecords(expectedColumnRecords, actualColumnRecordMap)); // Check columnar table evolution records - reports.addAll(checkTableEvolutionRecord(tableEvolutionRecords.get(0), actualColLatestMap)); + reports.addAll(checkTableEvolutionColumnRecord(tableEvolutionRecords.get(0), actualColLatestMap)); return reports; } @@ -792,8 +845,47 @@ private List checkColumnEvolutionRecords(List inde } @NotNull - private List checkTableEvolutionRecord(ColumnarTableEvolutionRecord tableEvolutionRecord, - Map> colLatestMap) { + private List checkPartitionEvolutionRecords(List partitions, + Map> expectedMap) { + return CheckerBuilder + .stringKeyListChecker(partitions, expectedMap, true) + .withReverseOrderCheck() + .withActualKeyGenerator(a -> a.partName) + .withExpectedKeyGenerator(e -> e.getValue().partName) + .withDefValidator((a, e) -> equalsPartitionRecord(a, e.getValue())) + .withOrdValidator((a, e) -> a.partPosition == e.getValue().partPosition) + .withOrphanReporter(msgs -> createReportRecord( + ReportErrorType.ORPHAN_COLUMNAR_PARTITION_EVOLUTION_META, + CheckerReportStatus.FOUND, + String.format( + "Orphan partition evolution meta found for partition: %s", + String.join(",", msgs)))) + .withMissingReporter(msgs -> createReportRecord( + ReportErrorType.MISSING_COLUMNAR_PARTITION_EVOLUTION_META, + CheckerReportStatus.FOUND, + String.format( + "Missing partition evolution meta for partition: %s", + String.join(",", msgs)))) + .withInvalidateDefReporter(msgs -> createReportRecord( + ReportErrorType.UNMATCHED_COLUMNAR_PARTITION_EVOLUTION_DEFINITION, + CheckerReportStatus.FOUND, + String.format( + "Unmatched partition evolution definition found for partition: %s", + String.join(",", msgs)))) + .withInvalidateOrdReporter(msgs -> createReportRecord( + ReportErrorType.UNMATCHED_COLUMNAR_PARTITION_EVOLUTION_ORDER, + CheckerReportStatus.FOUND, + String.format( + "Unmatched partition evolution order found for partition: %s", + String.join(",", msgs)))) + .build() + .check() + .report(); + } + + @NotNull + private List checkTableEvolutionColumnRecord(ColumnarTableEvolutionRecord tableEvolutionRecord, + Map> colLatestMap) { return CheckerBuilder .listChecker(tableEvolutionRecord.columns, colLatestMap) .withActualKeyGenerator(Ord::getValue) @@ -829,6 +921,37 @@ private List checkTableEvolutionRecord(ColumnarTableEvolutionReco .report(); } + @NotNull + private List checkTableEvolutionPartitionRecord(ColumnarTableEvolutionRecord tableEvolutionRecord, + Map> colLatestMap) { + return CheckerBuilder + .listChecker(tableEvolutionRecord.partitions, colLatestMap) + .withActualKeyGenerator(Ord::getValue) + .withExpectedKeyGenerator(Pair::getKey) + .withMissingMsgFromExpectedGenerator( + e -> String.format("%s[%s]", e.getValue().partName, e.getValue().partPosition)) + .withInvalidateOrdMsgGenerator((a, e) -> String.format("%s[%s](%s -> %s)", + e.getValue().partName, + a.getValue(), + e.getValue().partPosition, + a.getKey() + 1)) + .withOrphanReporter(msgs -> createReportRecord( + ReportErrorType.ORPHAN_COLUMNAR_TABLE_EVOLUTION_FIELD_ID, + CheckerReportStatus.FOUND, + String.format( + "Orphan table evolution field id found for partition: %s", + String.join(",", msgs)))) + .withMissingReporter(msgs -> createReportRecord( + ReportErrorType.MISSING_COLUMNAR_TABLE_EVOLUTION_FIELD_ID, + CheckerReportStatus.FOUND, + String.format( + "Missing table evolution field id for partition: %s", + String.join(",", msgs)))) + .build() + .check() + .report(); + } + /** * Check cci exists * & Check cci belongs to primary table @@ -978,7 +1101,7 @@ private List checkCciColumns(Blackboard blackboard) { .report(); } - private boolean equalsColumnRecord(ColumnsRecord left, ColumnsRecord right) { + public static boolean equalsColumnRecord(ColumnsRecord left, ColumnsRecord right) { if (null == left || null == right) { return false; } @@ -994,6 +1117,14 @@ private boolean equalsColumnRecord(ColumnsRecord left, ColumnsRecord right) { && TStringUtil.equals(left.extra, right.extra); } + private boolean equalsPartitionRecord(TablePartitionRecord left, TablePartitionRecord right) { + if (null == left || null == right) { + return false; + } + + return TablePartitionRecord.isPartitionRecordEqual(left, right); + } + private boolean validateIndexRecord(ColumnsRecord primaryColumnDef, IndexesRecord indexColumnDef) { if (null == primaryColumnDef || null == indexColumnDef) { return false; @@ -1036,8 +1167,12 @@ private static class Blackboard { private final Map, List> queryColumnarTableEvolutionCache = new HashMap<>(); + private final Map> queryColumnarTableEvolutionCache1 = + new HashMap<>(); private final Map, List> queryColumnarColumnEvolutionCache = new HashMap<>(); + private final Map, List> + queryColumnarPartitionEvolutionCache = new HashMap<>(); private final Map, List> queryTablePartitionCache = new HashMap<>(); private final Map> queryTableGroupCache = new HashMap<>(); private final Map> queryPartitionGroupCache = new HashMap<>(); @@ -1076,12 +1211,24 @@ public List queryColumnarTableMapping(String schemaN k -> tableInfoManager.queryColumnarTableMapping(k.getLeft(), k.getMiddle(), k.getRight())); } + public List queryColumnarPartitionEvolution(List fieldIdList) { + return queryColumnarPartitionEvolutionCache.computeIfAbsent( + fieldIdList, + tableInfoManager::queryColumnarPartitionEvolution); + } + public List queryColumnarColumnEvolution(List fieldIdList) { return queryColumnarColumnEvolutionCache.computeIfAbsent( fieldIdList, tableInfoManager::queryColumnarColumnEvolution); } + public List queryColumnarTableEvolution(long indexTableId) { + return queryColumnarTableEvolutionCache1.computeIfAbsent( + indexTableId, + p -> tableInfoManager.queryColumnarTableEvolutionFirst(indexTableId)); + } + public List queryColumnarTableEvolution(long indexTableId, long versionId) { return queryColumnarTableEvolutionCache.computeIfAbsent( Pair.of(indexTableId, versionId), @@ -1131,6 +1278,10 @@ public enum ReportErrorType { ORPHAN_COLUMNAR_COLUMN_EVOLUTION_META, UNMATCHED_COLUMNAR_COLUMN_EVOLUTION_DEFINITION, UNMATCHED_COLUMNAR_COLUMN_EVOLUTION_ORDER, + MISSING_COLUMNAR_PARTITION_EVOLUTION_META, + ORPHAN_COLUMNAR_PARTITION_EVOLUTION_META, + UNMATCHED_COLUMNAR_PARTITION_EVOLUTION_DEFINITION, + UNMATCHED_COLUMNAR_PARTITION_EVOLUTION_ORDER, MISSING_COLUMNAR_TABLE_EVOLUTION_FIELD_ID, ORPHAN_COLUMNAR_TABLE_EVOLUTION_FIELD_ID, MISSING_CDC_MARK_CREATE_INDEX, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciSnapshotTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciSnapshotTask.java new file mode 100644 index 000000000..c4c7db13d --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciSnapshotTask.java @@ -0,0 +1,106 @@ +package com.alibaba.polardbx.executor.ddl.job.task.columnar; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.executor.columnar.checker.CciSnapshotChecker; +import com.alibaba.polardbx.executor.columnar.checker.CciSnapshotFastChecker; +import com.alibaba.polardbx.executor.columnar.checker.ICciChecker; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.gsi.CheckerManager; +import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.CheckCciPrepareData; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import lombok.Getter; +import org.apache.calcite.sql.SqlCheckColumnarIndex; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + +@Getter +@TaskName(name = "CheckCciSnapshotTask") +public class CheckCciSnapshotTask extends CheckCciBaseTask { + private final static Logger LOG = LoggerFactory.getLogger(CheckCciTask.class); + + final List reports = new ArrayList<>(); + private final long primaryTso; + private final long columnarTso; + + public static CheckCciSnapshotTask create(CheckCciPrepareData prepareData) { + return new CheckCciSnapshotTask( + prepareData.getSchemaName(), + prepareData.getTableName(), + prepareData.getIndexName(), + prepareData.getExtraCmd(), + prepareData.getTsoList().get(0), + prepareData.getTsoList().get(1) + ); + } + + @JSONCreator + public CheckCciSnapshotTask(String schemaName, + String tableName, + String indexName, + SqlCheckColumnarIndex.CheckCciExtraCmd extraCmd, + long primaryTso, + long columnarTso) { + super(schemaName, tableName, indexName, extraCmd); + this.primaryTso = primaryTso; + this.columnarTso = columnarTso; + } + + @Override + protected void beforeTransaction(ExecutionContext executionContext) { + // Check. + ICciChecker checker; + if (executionContext.isEnableCciFastChecker() && ExecUtils.canUseCciFastChecker(schemaName, indexName)) { + checker = new CciSnapshotFastChecker(schemaName, tableName, indexName, primaryTso, columnarTso); + } else { + checker = new CciSnapshotChecker(schemaName, tableName, indexName, primaryTso, columnarTso); + } + + doCheck(executionContext, checker); + } + + protected void doCheck(ExecutionContext executionContext, ICciChecker checker) { + try { + checker.check(executionContext); + } catch (Throwable t) { + reports.add( + createReportRecord( + CheckCciMetaTask.ReportErrorType.SUMMARY, + CheckerManager.CheckerReportStatus.FOUND, + "Error occurs when checking, caused by " + t.getMessage() + )); + SQLRecorderLogger.ddlLogger.error(t); + } + + List checkReports = new ArrayList<>(); + if (!checker.getCheckReports(checkReports)) { + // Inconsistency detected. + for (String error : checkReports) { + reports.add(createReportRecord(CheckCciMetaTask.ReportErrorType.SUMMARY, + CheckerManager.CheckerReportStatus.FOUND, error)); + } + } + + reports.add( + createReportRecord( + CheckCciMetaTask.ReportErrorType.SUMMARY, + CheckerManager.CheckerReportStatus.FINISH, + "data of columnar index checked")); + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + // Add reports to metadb.checker_reports + CheckerManager.insertReports(metaDbConnection, reports); + } + + @Override + public String remark() { + return String.format("|CciSnapshotCheck(%s.%s)", tableName, indexName); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciTask.java index 8c5ebc703..247b4b4ba 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciTask.java @@ -17,8 +17,6 @@ package com.alibaba.polardbx.executor.ddl.job.task.columnar; import com.alibaba.fastjson.annotation.JSONCreator; -import com.alibaba.polardbx.common.properties.ConnectionProperties; -import com.alibaba.polardbx.common.utils.LoggerUtil; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.columnar.checker.CciChecker; @@ -27,19 +25,13 @@ import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.gsi.CheckerManager; import com.alibaba.polardbx.executor.utils.ExecUtils; -import com.alibaba.polardbx.gms.topology.InstConfigAccessor; -import com.alibaba.polardbx.gms.topology.InstConfigRecord; -import com.alibaba.polardbx.gms.util.InstIdUtil; -import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.CheckCciPrepareData; import com.alibaba.polardbx.statistics.SQLRecorderLogger; -import com.google.common.collect.ImmutableList; import lombok.Getter; import org.apache.calcite.sql.SqlCheckColumnarIndex; import java.sql.Connection; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -76,8 +68,9 @@ public CheckCciTask(String schemaName, @Override protected void beforeTransaction(ExecutionContext executionContext) { // Check. + long startTime = System.nanoTime(); ICciChecker checker; - if (executionContext.isEnableFastCciChecker()) { + if (executionContext.isEnableCciFastChecker() && ExecUtils.canUseCciFastChecker(schemaName, indexName)) { checker = new CciFastChecker(schemaName, tableName, indexName); } else { checker = new CciChecker(schemaName, tableName, indexName); @@ -117,7 +110,9 @@ protected void beforeTransaction(ExecutionContext executionContext) { createReportRecord( CheckCciMetaTask.ReportErrorType.SUMMARY, CheckerManager.CheckerReportStatus.FINISH, - "data of columnar index checked")); + "data of columnar index checked." + + "Cost " + (System.nanoTime() - startTime) / 1000000 + "ms" + )); } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CreateCheckCciTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CreateCheckCciTask.java index a2dc90982..dc76254fb 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CreateCheckCciTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CreateCheckCciTask.java @@ -73,7 +73,7 @@ protected void beforeTransaction(ExecutionContext executionContext) { } ICciChecker checker; - if (executionContext.isEnableFastCciChecker()) { + if (executionContext.isEnableCciFastChecker() && ExecUtils.canUseCciFastChecker(schemaName, indexName)) { checker = new CciFastChecker(schemaName, logicalTableName, indexName); } else { checker = new CciChecker(schemaName, logicalTableName, indexName); @@ -82,12 +82,12 @@ protected void beforeTransaction(ExecutionContext executionContext) { try { long start = System.nanoTime(); checker.check(executionContext, recover); - SQLRecorderLogger.ddlLogger.info((executionContext.isEnableFastCciChecker() ? "Fast " : "") + SQLRecorderLogger.ddlLogger.info((executionContext.isEnableCciFastChecker() ? "Fast " : "") + "Check cci " + schemaName + "." + logicalTableName + "." + indexName + " cost " + (System.nanoTime() - start) / 1_000_000 + " ms."); } catch (Throwable t) { throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, - (executionContext.isEnableFastCciChecker() ? "Fast " : "") + (executionContext.isEnableCciFastChecker() ? "Fast " : "") + "Check cci failed, caused by " + t.getMessage()); } finally { if (null != recover) { @@ -100,7 +100,7 @@ protected void beforeTransaction(ExecutionContext executionContext) { if (!checker.getCheckReports(reports)) { for (String error : reports) { SQLRecorderLogger.ddlLogger.error( - (executionContext.isEnableFastCciChecker() ? "Fast " : "") + (executionContext.isEnableCciFastChecker() ? "Fast " : "") + "Check cci " + logicalTableName + "." + indexName + " error: " + error); } success = false; @@ -110,7 +110,7 @@ protected void beforeTransaction(ExecutionContext executionContext) { return; } - if (executionContext.isEnableFastCciChecker()) { + if (executionContext.isEnableCciFastChecker()) { // Fast checker failed, try naive checker. checker = new CciChecker(schemaName, logicalTableName, indexName); recover = null; @@ -124,7 +124,7 @@ protected void beforeTransaction(ExecutionContext executionContext) { + "." + indexName + " cost " + (System.nanoTime() - start) / 1_000_000 + " ms."); } catch (Throwable t) { throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, - (executionContext.isEnableFastCciChecker() ? "Fast " : "") + (executionContext.isEnableCciFastChecker() ? "Fast " : "") + "Check cci failed, caused by " + t.getMessage()); } finally { if (null != recover) { @@ -135,7 +135,7 @@ protected void beforeTransaction(ExecutionContext executionContext) { if (!checker.getCheckReports(reports)) { for (String error : reports) { SQLRecorderLogger.ddlLogger.error( - (executionContext.isEnableFastCciChecker() ? "Fast " : "") + (executionContext.isEnableCciFastChecker() ? "Fast " : "") + "Check cci " + logicalTableName + "." + indexName + " error: " + error); } success = false; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/RenameColumnarTableMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/RenameColumnarTableMetaTask.java new file mode 100644 index 000000000..ab849bb49 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/RenameColumnarTableMetaTask.java @@ -0,0 +1,43 @@ +package com.alibaba.polardbx.executor.ddl.job.task.columnar; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.executor.ddl.job.meta.TableMetaChanger; +import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; + +import java.sql.Connection; + +@Getter +@TaskName(name = "RenameColumnarTableMetaTask") +public class RenameColumnarTableMetaTask extends BaseGmsTask { + private final String primaryTableName; + private final String newPrimaryTableName; + private final long versionId; + + @JSONCreator + public RenameColumnarTableMetaTask(String schemaName, String primaryTableName, String newPrimaryTableName, + long versionId) { + super(schemaName, primaryTableName); + this.primaryTableName = primaryTableName; + this.newPrimaryTableName = newPrimaryTableName; + this.versionId = versionId; + onExceptionTryRecoveryThenRollback(); + } + + @Override + public void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + FailPoint.injectRandomExceptionFromHint(executionContext); + FailPoint.injectRandomSuspendFromHint(executionContext); + TableMetaChanger.renameColumnarTableMeta(metaDbConnection, schemaName, primaryTableName, newPrimaryTableName, + versionId, jobId); + } + + @Override + public void rollbackImpl(Connection metaDbConnection, ExecutionContext executionContext) { + TableMetaChanger.renameColumnarTableMeta(metaDbConnection, schemaName, newPrimaryTableName, primaryTableName, + versionId, jobId); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/RenameColumnarTablesMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/RenameColumnarTablesMetaTask.java index 6009f4c6b..47d1c3b15 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/RenameColumnarTablesMetaTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/RenameColumnarTablesMetaTask.java @@ -25,35 +25,38 @@ import lombok.Getter; import java.sql.Connection; +import java.util.List; @Getter @TaskName(name = "RenameColumnarTablesMetaTask") public class RenameColumnarTablesMetaTask extends BaseGmsTask { - private final String primaryTableName; - private final String newPrimaryTableName; - private final long versionId; + private final List oldTableNames; + private final List newTableNames; + private final List versionIds; @JSONCreator - public RenameColumnarTablesMetaTask(String schemaName, String primaryTableName, String newPrimaryTableName, - long versionId) { - super(schemaName, primaryTableName); - this.primaryTableName = primaryTableName; - this.newPrimaryTableName = newPrimaryTableName; - this.versionId = versionId; + public RenameColumnarTablesMetaTask(String schemaName, List oldTableNames, List newTableNames, + List versionIds) { + super(schemaName, null); + this.oldTableNames = oldTableNames; + this.newTableNames = newTableNames; + this.versionIds = versionIds; onExceptionTryRecoveryThenRollback(); } @Override - public void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { FailPoint.injectRandomExceptionFromHint(executionContext); FailPoint.injectRandomSuspendFromHint(executionContext); - TableMetaChanger.renameColumnarTableMeta(metaDbConnection, schemaName, primaryTableName, newPrimaryTableName, - versionId, jobId); + + TableMetaChanger.renameColumnarTablesMeta(metaDbConnection, schemaName, oldTableNames, newTableNames, + versionIds, jobId); } @Override public void rollbackImpl(Connection metaDbConnection, ExecutionContext executionContext) { - TableMetaChanger.renameColumnarTableMeta(metaDbConnection, schemaName, newPrimaryTableName, primaryTableName, - versionId, jobId); + TableMetaChanger.renameColumnarTablesMeta(metaDbConnection, schemaName, newTableNames, oldTableNames, + versionIds, jobId); } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/TruncateColumnarTableTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/TruncateColumnarTableTask.java new file mode 100644 index 000000000..fd1d41152 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/TruncateColumnarTableTask.java @@ -0,0 +1,43 @@ +/* + * 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 com.alibaba.polardbx.executor.ddl.job.task.columnar; + +import com.alibaba.polardbx.executor.ddl.job.meta.TableMetaChanger; +import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; +import java.sql.Connection; + +@Getter +@TaskName(name = "TruncateColumnarTableTask") +public class TruncateColumnarTableTask extends BaseGmsTask { + private final long versionId; + + public TruncateColumnarTableTask(String schemaName, String logicalTableName, long versionId) { + super(schemaName, logicalTableName); + this.versionId = versionId; + } + + @Override + protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + TableMetaChanger.truncateColumnarTable(metaDbConnection, schemaName, logicalTableName, versionId + , jobId); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/UpdateColumnarConfigTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/UpdateColumnarConfigTask.java new file mode 100644 index 000000000..a79c41cc7 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/UpdateColumnarConfigTask.java @@ -0,0 +1,143 @@ +package com.alibaba.polardbx.executor.ddl.job.task.columnar; + +import com.alibaba.polardbx.common.ColumnarOptions; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ColumnarConfig; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +@Getter +@TaskName(name = "UpdateColumnarConfigTask") +public class UpdateColumnarConfigTask extends BaseGmsTask { + private final String indexName; + private final Map options; + + public UpdateColumnarConfigTask(String schemaName, String logicalTableName, String indexName, + Map options) { + super(schemaName, logicalTableName); + this.indexName = indexName; + this.options = options; + onExceptionTryRecoveryThenRollback(); + } + + @Override + protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + List configRecords = getColumnarConfigRecords(metaDbConnection); + + // If options contains 'type', update `columnar_table_mapping`. + ColumnarConfigRecord record; + if (null != (record = getRecordWith(configRecords, ColumnarOptions.TYPE))) { + ColumnarTableMappingAccessor tableMappingAccessor = new ColumnarTableMappingAccessor(); + tableMappingAccessor.setConnection(metaDbConnection); + long tableId = record.tableId; + tableMappingAccessor.updateTypeByTableId(record.tableId, record.configValue); + tableMappingAccessor.UpdateExtraByTableId(record.tableId, null); + + Map> records = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + Map globalConfig = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + MetaDbUtil.generateColumnarConfig(schemaName, logicalTableName, records, globalConfig); + + if (null == getRecordWith(configRecords, ColumnarOptions.SNAPSHOT_RETENTION_DAYS)) { + ColumnarConfigRecord tmpRecord = new ColumnarConfigRecord(); + tmpRecord.tableId = tableId; + tmpRecord.configKey = ColumnarOptions.SNAPSHOT_RETENTION_DAYS; + tmpRecord.configValue = ColumnarConfig.getValue(tmpRecord.configKey, null, globalConfig); + String columnarPurgeSaveMs = globalConfig.get(ColumnarOptions.COLUMNAR_PURGE_SAVE_MS); + if (null != columnarPurgeSaveMs) { + long columnarPurgeSaveDays = 1 + Long.parseLong(columnarPurgeSaveMs) / 1000 / 60 / 60 / 24; + if (columnarPurgeSaveDays > Long.parseLong(tmpRecord.configValue)) { + tmpRecord.configValue = Long.toString(columnarPurgeSaveDays); + } + } + configRecords.add(tmpRecord); + } + if (null == getRecordWith(configRecords, ColumnarOptions.AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL)) { + ColumnarConfigRecord tmpRecord = new ColumnarConfigRecord(); + tmpRecord.tableId = tableId; + tmpRecord.configKey = ColumnarOptions.AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL; + tmpRecord.configValue = ColumnarConfig.getValue(tmpRecord.configKey, null, globalConfig); + configRecords.add(tmpRecord); + } + } + + ColumnarConfigAccessor accessor = new ColumnarConfigAccessor(); + accessor.setConnection(metaDbConnection); + accessor.insert(configRecords); + + FailPoint.injectRandomExceptionFromHint(executionContext); + FailPoint.injectRandomSuspendFromHint(executionContext); + } + + @Override + protected void rollbackImpl(Connection metaDbConnection, ExecutionContext executionContext) { + // Find table id. + List configRecords = getColumnarConfigRecords(metaDbConnection); + ColumnarConfigAccessor accessor = new ColumnarConfigAccessor(); + accessor.setConnection(metaDbConnection); + accessor.deleteByTableIdAndKeyValue(configRecords); + + // If options contains 'type', update `columnar_table_mapping`. + ColumnarConfigRecord record; + if (null != (record = getRecordWith(configRecords, ColumnarOptions.TYPE))) { + ColumnarTableMappingAccessor tableMappingAccessor = new ColumnarTableMappingAccessor(); + tableMappingAccessor.setConnection(metaDbConnection); + tableMappingAccessor.updateTypeByTableId(record.tableId, null); + } + } + + @NotNull + private List getColumnarConfigRecords(Connection metaDbConnection) { + // Find table id. + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + + List records = + tableInfoManager.queryColumnarTable(schemaName, logicalTableName, indexName); + if (records.isEmpty()) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + "Columnar table mapping record not found."); + } + long tableId = records.get(0).tableId; + List configRecords = new ArrayList<>(); + for (Map.Entry option : options.entrySet()) { + ColumnarConfigRecord record = new ColumnarConfigRecord(); + record.tableId = tableId; + record.configKey = format(option.getKey()); + record.configValue = format(option.getValue()); + configRecords.add(record); + } + return configRecords; + } + + private ColumnarConfigRecord getRecordWith(List records, String key) { + for (ColumnarConfigRecord record : records) { + if (key.equalsIgnoreCase(record.configKey)) { + return record; + } + } + return null; + } + + protected static String format(String str) { + return str.replaceAll("^[ '\"]*|[ '\"]*$", "").trim(); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/WaitColumnarTableAlterPartitionTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/WaitColumnarTableAlterPartitionTask.java new file mode 100644 index 000000000..001e7bac8 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/WaitColumnarTableAlterPartitionTask.java @@ -0,0 +1,125 @@ +/* + * 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 com.alibaba.polardbx.executor.ddl.job.task.columnar; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import lombok.Getter; +import lombok.SneakyThrows; + +import java.sql.Connection; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +@TaskName(name = "WaitColumnarTableAlterPartitionTask") +@Getter +public class WaitColumnarTableAlterPartitionTask extends BaseDdlTask { + private static final Logger logger = LoggerFactory.getLogger(WaitColumnarTableAlterPartitionTask.class); + public static final String ALTER_PARTITION_SUCCESS_CHECKPOINT_TYPE = "ALTER_PARTITION_SUCCESS"; + + private final List indexNames; + /** + * FOR TEST USE ONLY! + * If set to true, ddl returns succeed right after CN finish writing metadata + */ + private final boolean skipCheck; + + public WaitColumnarTableAlterPartitionTask(String schemaName, List indexNames, boolean skipCheck) { + super(schemaName); + this.indexNames = indexNames; + this.skipCheck = skipCheck; + } + + @Override + @SneakyThrows + protected void beforeTransaction(ExecutionContext executionContext) { + // wait columnar index creation to be finished + long start = System.nanoTime(); + + // Always create new metadb connection to get the latest snapshot + try (Connection conn = Objects.requireNonNull(MetaDbDataSource.getInstance()).getConnection()) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(conn); + + for (String indexName : indexNames) { + while (true) { + List records = + tableInfoManager.queryColumnarTableMapping(schemaName, indexName); + if (records.isEmpty()) { + //找不到该列存索引记录了 + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + "Columnar table mapping record not found."); + } + ColumnarTableMappingRecord record = records.get(0); + + ColumnarTableEvolutionRecord evolutionRecord = + tableInfoManager.queryColumnarTableEvolutionByVersionId(record.latestVersionId); + + List checkpointsRecords = + tableInfoManager.queryColumnarCheckpointsByCommitTs(evolutionRecord.commitTs); + if (GeneralUtil.isNotEmpty(checkpointsRecords) && checkpointsRecords.get(0).getExtra() + .startsWith(ALTER_PARTITION_SUCCESS_CHECKPOINT_TYPE)) { + // ALTER TABLE PARTITION 成功 + break; + } + + if (executionContext.getDdlContext().isInterrupted()) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + "The job '" + executionContext.getDdlContext().getJobId() + "' has been interrupted"); + } + + TimeUnit.MILLISECONDS.sleep(1000); + } + } + } + SQLRecorderLogger.ddlLogger.info("Wait Alter Columnar table partition task ended, cost " + + ((System.nanoTime() - start) / 1_000_000) + " ms."); + if (executionContext.getDdlContext().isInterrupted()) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + "wait alter columnar table partition task is interrupted."); + } + } + + @Override + protected void onExecutionSuccess(ExecutionContext executionContext) { + } + + @Override + protected boolean isSkipExecute() { + return this.skipCheck; + } + + @Override + protected boolean isSkipRollback() { + return this.skipCheck; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/WaitColumnarTableCreationTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/WaitColumnarTableCreationTask.java index ea20adec7..3d12a4cc3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/WaitColumnarTableCreationTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/WaitColumnarTableCreationTask.java @@ -97,11 +97,10 @@ protected void beforeTransaction(ExecutionContext executionContext) { } TimeUnit.MILLISECONDS.sleep(1000); - } finally { - SQLRecorderLogger.ddlLogger.info("Wait Columnar table created task ended, cost " - + ((System.nanoTime() - start) / 1_000_000) + " ms."); } } + SQLRecorderLogger.ddlLogger.info("Wait Columnar table created task ended, cost " + + ((System.nanoTime() - start) / 1_000_000) + " ms."); if (executionContext.getDdlContext().isInterrupted()) { throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, "wait columnar table task is interrupted."); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/factory/GsiTaskFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/factory/GsiTaskFactory.java index 0f7047b54..c65c08e73 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/factory/GsiTaskFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/factory/GsiTaskFactory.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.druid.sql.SQLUtils; @@ -28,43 +29,64 @@ import com.alibaba.polardbx.druid.sql.ast.statement.SQLTableElement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; import com.alibaba.polardbx.druid.util.JdbcConstants; +import com.alibaba.polardbx.executor.backfill.BackfillStats; import com.alibaba.polardbx.executor.changeset.ChangeSetManager; import com.alibaba.polardbx.executor.ddl.job.builder.AlterTableBuilder; import com.alibaba.polardbx.executor.ddl.job.builder.DdlPhyPlanBuilder; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; import com.alibaba.polardbx.executor.ddl.job.factory.AlterTableJobFactory; -import com.alibaba.polardbx.executor.ddl.job.factory.gsi.CreateGsiCheckTask; +import com.alibaba.polardbx.executor.ddl.job.factory.gsi.OmcCheckTask; +import com.alibaba.polardbx.executor.ddl.job.factory.gsi.RebuildTableJobFactory; import com.alibaba.polardbx.executor.ddl.job.task.backfill.LogicalTableBackFillTask; import com.alibaba.polardbx.executor.ddl.job.task.backfill.LogicalTableColumnBackFillTask; +import com.alibaba.polardbx.executor.ddl.job.task.backfill.LogicalTableGsiPkRangeBackfillTask; +import com.alibaba.polardbx.executor.ddl.job.task.backfill.LogicalTablePhysicalPartitionBackFillTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcGsiDdlMarkTask; import com.alibaba.polardbx.executor.ddl.job.task.changset.ChangeSetCatchUpTask; import com.alibaba.polardbx.executor.ddl.job.task.changset.ChangeSetStartTask; +import com.alibaba.polardbx.executor.ddl.job.task.gsi.AlterGsiAddLocalIndexTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.GsiDropColumnCleanUpTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.GsiInsertColumnMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.gsi.GsiPkRangeBackfillLogTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.GsiUpdateIndexColumnStatusTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.GsiUpdateIndexStatusTask; +import com.alibaba.polardbx.executor.ddl.job.task.gsi.SperateCheckGsiTask; +import com.alibaba.polardbx.executor.ddl.job.task.shared.EmptyLogTask; +import com.alibaba.polardbx.executor.ddl.job.task.shared.EmptyTask; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.gsi.GsiUtils; +import com.alibaba.polardbx.executor.gsi.corrector.GsiChecker; +import com.alibaba.polardbx.executor.gsi.utils.Transformer; import com.alibaba.polardbx.gms.metadb.table.ColumnStatus; import com.alibaba.polardbx.gms.metadb.table.IndexStatus; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; -import com.sun.org.apache.xpath.internal.operations.Bool; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; import org.apache.calcite.plan.RelOptCluster; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlSelect; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; +import static com.alibaba.polardbx.executor.backfill.BackfillSampleManager.toValue; import static com.alibaba.polardbx.executor.ddl.util.ChangeSetUtils.genChangeSetCatchUpTasks; +import static org.apache.calcite.sql.SqlIdentifier.surroundWithBacktick; /** * an interesting gsi-relevant task generator @@ -101,22 +123,34 @@ public static List createGlobalIndexTasks(String schemaName, */ public static List addGlobalIndexTasks(String schemaName, String primaryTableName, - String oldIndexName, + String backfillSourceTableName, String indexName, boolean stayAtDeleteOnly, boolean stayAtWriteOnly, boolean stayAtBackFill, - Map virtualColumns, - Map backfillColumnMap, + Map srcVirtualColumns, + Map dstVirtualColumns, + Map dstColumnNewDefinitions, List modifyStringColumns, PhysicalPlanData physicalPlanData, TableMeta tableMeta, - boolean repartition, - boolean modifyColumn, + boolean gsiCdcMark, + boolean onlineModifyColumn, boolean mirrorCopy, String originalDdl) { List taskList = new ArrayList<>(); + if (onlineModifyColumn) { + assert MapUtils.isNotEmpty(dstColumnNewDefinitions); + List checkerTasks = RebuildTableJobFactory.genGeneratedColumn4CheckTasks(schemaName, indexName, + dstVirtualColumns, dstColumnNewDefinitions, physicalPlanData); + if (CollectionUtils.isNotEmpty(checkerTasks)) { + taskList.addAll(checkerTasks); + } + } + + backfillSourceTableName = backfillSourceTableName == null ? primaryTableName : backfillSourceTableName; + DdlTask deleteOnlyTask = new GsiUpdateIndexStatusTask( schemaName, primaryTableName, @@ -160,16 +194,23 @@ public static List addGlobalIndexTasks(String schemaName, if (stayAtWriteOnly) { return taskList; } - String backFillSourceTableName = mirrorCopy ? oldIndexName : primaryTableName; taskList.add( - new LogicalTableBackFillTask(schemaName, backFillSourceTableName, indexName, virtualColumns, - backfillColumnMap, modifyStringColumns, false, mirrorCopy, modifyColumn)); + new LogicalTableBackFillTask(schemaName, backfillSourceTableName, indexName, srcVirtualColumns, + dstVirtualColumns, modifyStringColumns, false, mirrorCopy, onlineModifyColumn)); + if (onlineModifyColumn) { + assert MapUtils.isNotEmpty(dstColumnNewDefinitions); + DdlTask dropCheckColumnTask = RebuildTableJobFactory.genDropColumn4CheckTasks(schemaName, indexName, + dstVirtualColumns, physicalPlanData); + if (dropCheckColumnTask != null) { + taskList.add(dropCheckColumnTask); + } + } if (stayAtBackFill) { return taskList; } taskList.add(writeReOrgTask); taskList.add(new TableSyncTask(schemaName, primaryTableName)); - if (!tableMeta.isAutoPartition() && !repartition) { + if (!tableMeta.isAutoPartition() && gsiCdcMark) { CdcGsiDdlMarkTask cdcDdlMarkTask = new CdcGsiDdlMarkTask(schemaName, physicalPlanData, primaryTableName, originalDdl); taskList.add(cdcDdlMarkTask); @@ -179,36 +220,300 @@ public static List addGlobalIndexTasks(String schemaName, return taskList; } + public static ExecutableDdlJob addGlobalIndexTasks(String schemaName, + String primaryTableName, + String oldIndexName, + String indexName, + boolean stayAtDeleteOnly, + boolean stayAtWriteOnly, + boolean stayAtBackFill, + Map virtualColumns, + Map backfillColumnMap, + List modifyStringColumns, + PhysicalPlanData physicalPlanData, + PhysicalPlanData physicalPlanDataForLocalIndex, + TableMeta tableMeta, + boolean gsiCdcMark, + boolean modifyColumn, + boolean mirrorCopy, + String originalDdl, + GsiChecker.Params params, + Boolean splitByPkRange, + Boolean splitByPartition, + Boolean enableSample, + long maxTaskPkRangeSize, + long maxPkRangeSize, + long maxSampleRows, + long maxPkRangeSampleRows, + int totalThreadCount, + int cpuAcquired) { + ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); + DdlTask deleteOnlyTask = new GsiUpdateIndexStatusTask( + schemaName, + primaryTableName, + indexName, + IndexStatus.CREATING, + IndexStatus.DELETE_ONLY, + true + ).onExceptionTryRecoveryThenRollback(); + DdlTask writeOnlyTask = new GsiUpdateIndexStatusTask( + schemaName, + primaryTableName, + indexName, + IndexStatus.DELETE_ONLY, + IndexStatus.WRITE_ONLY, + true + ).onExceptionTryRecoveryThenRollback(); + DdlTask writeReOrgTask = new GsiUpdateIndexStatusTask( + schemaName, + primaryTableName, + indexName, + IndexStatus.WRITE_ONLY, + IndexStatus.WRITE_REORG, + true + ).onExceptionTryRecoveryThenRollback(); + DdlTask publicTask = new GsiUpdateIndexStatusTask( + schemaName, + primaryTableName, + indexName, + IndexStatus.WRITE_REORG, + IndexStatus.PUBLIC, + true + ).onExceptionTryRecoveryThenRollback(); + + AlterGsiAddLocalIndexTask alterGsiPhyTable = null; + if (physicalPlanDataForLocalIndex != null) { + alterGsiPhyTable = + new AlterGsiAddLocalIndexTask(schemaName, primaryTableName, indexName, physicalPlanDataForLocalIndex + ); + } + + executableDdlJob.appendTask(deleteOnlyTask); + executableDdlJob.labelAsHead(deleteOnlyTask); + TableSyncTask tableSyncTask = new TableSyncTask(schemaName, primaryTableName); + executableDdlJob.appendTask(tableSyncTask); + if (stayAtDeleteOnly) { + if (alterGsiPhyTable != null) { + executableDdlJob.appendTask(alterGsiPhyTable); + executableDdlJob.labelAsTail(alterGsiPhyTable); + } else { + executableDdlJob.labelAsTail(tableSyncTask); + } + return executableDdlJob; + } + executableDdlJob.appendTask(writeOnlyTask); + tableSyncTask = new TableSyncTask(schemaName, primaryTableName); + executableDdlJob.appendTask(tableSyncTask); + if (stayAtWriteOnly) { + if (alterGsiPhyTable != null) { + executableDdlJob.appendTask(alterGsiPhyTable); + executableDdlJob.labelAsTail(alterGsiPhyTable); + } else { + executableDdlJob.labelAsTail(tableSyncTask); + } + return executableDdlJob; + } + String backFillSourceTableName = mirrorCopy ? oldIndexName : primaryTableName; + generateLogicalTableGsiBackfillTask(executableDdlJob, alterGsiPhyTable, schemaName, backFillSourceTableName, + indexName, + virtualColumns, + backfillColumnMap, modifyStringColumns, false, mirrorCopy, + modifyColumn, params, splitByPkRange, splitByPartition, enableSample, maxTaskPkRangeSize, maxPkRangeSize, + maxSampleRows, maxPkRangeSampleRows, tableMeta, totalThreadCount, cpuAcquired); + if (stayAtBackFill) { + // the tail has been tag inside generateLogicalTableGsiBackfillTask + return executableDdlJob; + } + executableDdlJob.appendTask(writeReOrgTask); + executableDdlJob.appendTask(new TableSyncTask(schemaName, primaryTableName)); + if (!tableMeta.isAutoPartition() && gsiCdcMark) { + CdcGsiDdlMarkTask cdcDdlMarkTask = + new CdcGsiDdlMarkTask(schemaName, physicalPlanData, primaryTableName, originalDdl); + executableDdlJob.appendTask(cdcDdlMarkTask); + } + executableDdlJob.appendTask(publicTask); + tableSyncTask = new TableSyncTask(schemaName, primaryTableName); + executableDdlJob.appendTask(tableSyncTask); + executableDdlJob.labelAsTail(tableSyncTask); + return executableDdlJob; + } + + public static Boolean generateLogicalTableGsiBackfillTask(ExecutableDdlJob executableDdlJob, + DdlTask alterGsiPhyTable, + String schemaName, String backfillSourceTableName, + String indexName, + Map virtualColumns, + Map backfillColumnMap, + List modifyStringColumns, + Boolean changeset, Boolean mirrorCopy, + Boolean modifyColumn, + GsiChecker.Params params, + Boolean splitByPkRange, + Boolean splitByPartition, Boolean enableSample, + long maxTaskPkRangeSize, + long maxPkRangeSize, long maxSampleRows, + long maxPkRangeSampleRows, + TableMeta tableMeta, + int totalThreadCount, + int cpuAcquired) { + List splitPoints = new ArrayList<>(); + List pkColumns = tableMeta.getPrimaryKey().stream().map(o -> o.getName()).collect(Collectors.toList()); + Map pkColumnIndexes = new HashMap<>(); + List columnMetas = tableMeta.getAllColumns(); + for (int i = 0; i < columnMetas.size(); i++) { + pkColumnIndexes.put(columnMetas.get(i).getName(), i); + } + List pkColumnIndexList = + pkColumns.stream().map(o -> pkColumnIndexes.get(o)).collect(Collectors.toList()); + DdlTask headTask = new EmptyTask(schemaName); + DdlTask emptyLogTask = new EmptyLogTask(schemaName, "logical backfill finished!"); + String lockMode = SqlSelect.LockMode.UNDEF.toString(); + boolean isPrimaryBroadCast = + OptimizerContext.getContext(schemaName).getRuleManager().isBroadCast(backfillSourceTableName); + boolean isGsiBroadCast = OptimizerContext.getContext(schemaName).getRuleManager().isBroadCast(indexName); + DdlTask checkTask = + new SperateCheckGsiTask(schemaName, backfillSourceTableName, indexName, lockMode, lockMode, params, false, + "", + isPrimaryBroadCast, isGsiBroadCast, virtualColumns, backfillColumnMap); + executableDdlJob.appendTask(headTask); + BackfillStats backfillStats = + BackfillStats.createForLogicalBackfill(schemaName, backfillSourceTableName, tableMeta, maxSampleRows); + if (splitByPkRange && backfillStats.checkAndSplitLogicalTable(schemaName, backfillSourceTableName, tableMeta, + splitPoints, + enableSample, maxTaskPkRangeSize, maxSampleRows)) { + Map leftRow = Transformer.buildColumnsParam(null); + Map rightRow = Transformer.buildColumnsParam(null); + int i = 0; + if (splitPoints.size() <= 0) { + String rankHint = String.format("backfill on %s, %03d", backfillSourceTableName, i); + LogicalTableGsiPkRangeBackfillTask pkRangeBackfillTask = new LogicalTableGsiPkRangeBackfillTask( + schemaName, + backfillSourceTableName, + indexName, + virtualColumns, + backfillColumnMap, + modifyStringColumns, + pkColumnIndexList, + changeset, + mirrorCopy, + modifyColumn, + toValue(leftRow), + toValue(rightRow), + rankHint, + backfillStats.rangeRows, + backfillStats.rangeSize, + maxPkRangeSize, + maxPkRangeSampleRows, + totalThreadCount, + cpuAcquired + ); + executableDdlJob.addTaskRelationship(headTask, pkRangeBackfillTask); + } else { + while (i < splitPoints.size()) { + BackfillStats.SplitBound splitBound = splitPoints.get(i); + String rankHint = String.format("backfill on %s, %03d", backfillSourceTableName, i); + LogicalTableGsiPkRangeBackfillTask pkRangeBackfillTask = new LogicalTableGsiPkRangeBackfillTask( + schemaName, + backfillSourceTableName, + indexName, + virtualColumns, + backfillColumnMap, + modifyStringColumns, + pkColumnIndexList, + changeset, + mirrorCopy, + modifyColumn, + toValue(splitBound.left), + toValue(splitBound.right), + rankHint, + splitBound.rows, + splitBound.size, + maxPkRangeSize, + maxSampleRows, + totalThreadCount, + cpuAcquired + ); + executableDdlJob.addTaskRelationship(headTask, pkRangeBackfillTask); + i++; + } + } + //the tail tag would get overwrite later, we set it here to adapt to 'stayAt' hint. + } else if (splitByPartition) { + int i = 0; + // TODO split task by balance stats + // BalanceStats balanceStats = collectBalanceStatsOfTable(schemaName, backfillSourceTableName); + List partitionSpecs = tableMeta.getPartitionInfo().getPartitionBy().getPhysicalPartitions(); + while (i < partitionSpecs.size()) { + String rankHint = String.format("backfill on %s, %04d", backfillSourceTableName, i); + LogicalTablePhysicalPartitionBackFillTask partitionBackfillTask = + new LogicalTablePhysicalPartitionBackFillTask( + schemaName, + backfillSourceTableName, + indexName, + virtualColumns, + backfillColumnMap, + modifyStringColumns, + changeset, + mirrorCopy, + modifyColumn, + Collections.singletonList(partitionSpecs.get(i).getName()), + cpuAcquired + ); + partitionBackfillTask.setRankHint(rankHint); + executableDdlJob.addTaskRelationship(headTask, partitionBackfillTask); + i++; + } + } else { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + "failed to generate mpp task for logical table " + backfillSourceTableName); + } + executableDdlJob.appendTask(emptyLogTask); + executableDdlJob.addTaskRelationship(emptyLogTask, checkTask); + + Boolean withLocalIndexTask = false; + if (alterGsiPhyTable != null) { + executableDdlJob.addTaskRelationship(checkTask, alterGsiPhyTable); + withLocalIndexTask = true; + } + + GsiPkRangeBackfillLogTask gsiPkRangeBackfillLogTask = new GsiPkRangeBackfillLogTask(schemaName, "fastchecker and local index task finished!"); + executableDdlJob.appendTask(gsiPkRangeBackfillLogTask); + executableDdlJob.labelAsTail(gsiPkRangeBackfillLogTask); + return withLocalIndexTask; + } + public static List addGlobalIndexTasksChangeSet(String schemaName, String primaryTableName, - String oldIndexName, + String backfillSourceTableName, String indexName, boolean stayAtDeleteOnly, boolean stayAtWriteOnly, boolean stayAtBackFill, - Map virtualColumns, - Map backfillColumnMap, + Map srcVirtualColumns, + Map dstVirtualColumns, + Map dstColumnNewDefinitions, List modifyStringColumns, - boolean modifyColumn, + boolean onlineModifyColumn, boolean mirrorCopy, PhysicalPlanData physicalPlanData, PartitionInfo indexPartitionInfo) { List taskList = new ArrayList<>(); // start Long changeSetId = ChangeSetManager.getChangeSetId(); - Map> sourcePhyTableNames = GsiUtils.getPhyTables(schemaName, oldIndexName); + Map> sourcePhyTableNames = GsiUtils.getPhyTables(schemaName, backfillSourceTableName); Map targetTableLocations = - GsiUtils.getPhysicalTableMapping(schemaName, oldIndexName, null, physicalPlanData, indexPartitionInfo); + GsiUtils.getPhysicalTableMapping(schemaName, backfillSourceTableName, null, physicalPlanData, + indexPartitionInfo); ChangeSetStartTask changeSetStartTask = new ChangeSetStartTask( - schemaName, oldIndexName, sourcePhyTableNames, + schemaName, backfillSourceTableName, sourcePhyTableNames, ComplexTaskMetaManager.ComplexTaskType.ONLINE_MODIFY_COLUMN, changeSetId ); Map catchUpTasks = genChangeSetCatchUpTasks( schemaName, - oldIndexName, + backfillSourceTableName, indexName, sourcePhyTableNames, targetTableLocations, @@ -216,8 +521,18 @@ public static List addGlobalIndexTasksChangeSet(String schemaName, changeSetId ); - CreateGsiCheckTask createGsiCheckTask = - new CreateGsiCheckTask(schemaName, primaryTableName, indexName, virtualColumns, backfillColumnMap); + if (onlineModifyColumn) { + assert MapUtils.isNotEmpty(dstColumnNewDefinitions); + List checkerTasks = + RebuildTableJobFactory.genGeneratedColumn4CheckTasks(schemaName, backfillSourceTableName, + dstVirtualColumns, dstColumnNewDefinitions, physicalPlanData); + if (CollectionUtils.isNotEmpty(checkerTasks)) { + taskList.addAll(checkerTasks); + } + } + + OmcCheckTask omcCheckTask = + new OmcCheckTask(schemaName, backfillSourceTableName, indexName, srcVirtualColumns, dstVirtualColumns); DdlTask absentTask = new GsiUpdateIndexStatusTask( schemaName, @@ -269,8 +584,8 @@ public static List addGlobalIndexTasksChangeSet(String schemaName, taskList.add(new TableSyncTask(schemaName, primaryTableName)); // backfill taskList.add( - new LogicalTableBackFillTask(schemaName, oldIndexName, indexName, virtualColumns, backfillColumnMap, - modifyStringColumns, true, mirrorCopy, modifyColumn)); + new LogicalTableBackFillTask(schemaName, backfillSourceTableName, indexName, srcVirtualColumns, + dstVirtualColumns, modifyStringColumns, true, mirrorCopy, onlineModifyColumn)); taskList.add(catchUpTasks.get(ChangeSetManager.ChangeSetCatchUpStatus.ABSENT.toString())); taskList.add(deleteOnlyTask); taskList.add(new TableSyncTask(schemaName, primaryTableName)); @@ -285,7 +600,15 @@ public static List addGlobalIndexTasksChangeSet(String schemaName, if (stayAtWriteOnly) { return taskList; } - taskList.add(createGsiCheckTask); + taskList.add(omcCheckTask); + if (onlineModifyColumn) { + assert MapUtils.isNotEmpty(dstColumnNewDefinitions); + DdlTask dropCheckColumnTask = RebuildTableJobFactory.genDropColumn4CheckTasks(schemaName, indexName, + dstVirtualColumns, physicalPlanData); + if (dropCheckColumnTask != null) { + taskList.add(dropCheckColumnTask); + } + } if (stayAtBackFill) { return taskList; } @@ -439,18 +762,18 @@ private static String genAlterGlobalIndexAddColumnsSql(String primaryTableDefini throw new TddlRuntimeException(ErrorCode.ERR_DUPLICATE_COLUMN, columns.toString()); } - StringBuilder alterGsiTableSql = new StringBuilder("alter table " + indexName + " add column "); - alterGsiTableSql.append(StringUtils.join(columnsDef.toArray(), ", add column ")); - - return alterGsiTableSql.toString(); + return "alter table " + surroundWithBacktick(indexName) + " add column " + + StringUtils.join(columnsDef, ", add column "); } public static String genAlterGlobalIndexDropColumnsSql(String indexName, List columns) { if (indexName == null || columns == null || columns.isEmpty()) { return null; } - String hint = "/*+TDDL:CMD_EXTRA(DDL_ON_GSI=true)*/"; - return hint + "alter table " + indexName + " drop column " + StringUtils.join(columns, ", drop column "); + List columnsWithBacktick = + columns.stream().map(SqlIdentifier::surroundWithBacktick).collect(Collectors.toList()); + return "/*+TDDL:CMD_EXTRA(DDL_ON_GSI=true)*/alter table " + surroundWithBacktick(indexName) + " drop column " + + StringUtils.join(columnsWithBacktick, ", drop column "); } private static String extractCurrentTimestamp(String onUpdate, SQLExpr onUpdateExpr) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/AlterGsiAddLocalIndexTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/AlterGsiAddLocalIndexTask.java new file mode 100644 index 000000000..d480b1908 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/AlterGsiAddLocalIndexTask.java @@ -0,0 +1,83 @@ +package com.alibaba.polardbx.executor.ddl.job.task.gsi; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.polardbx.executor.ExecutorHelper; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.ddl.job.task.basic.AlterTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.spec.AlterTableRollbacker; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.gsi.GsiUtils; +import com.alibaba.polardbx.executor.spi.ITransactionManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.row.Row; +import com.alibaba.polardbx.optimizer.parse.FastsqlUtils; +import com.alibaba.polardbx.optimizer.parse.visitor.DrdsUnparameterizeSqlVisitor; +import com.alibaba.polardbx.optimizer.utils.SqlIdentifierUtil; +import lombok.Getter; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.commons.lang.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@TaskName(name = "AlterGsiAddLocalIndexTask") +public class AlterGsiAddLocalIndexTask extends AlterTablePhyDdlTask { + + private String logicalTableName; + private String indexTableName; + + @JSONCreator + public AlterGsiAddLocalIndexTask(String schemaName, + String logicalTableName, + String indexTableName, + PhysicalPlanData physicalPlanData) { + super(schemaName, indexTableName, physicalPlanData); + this.logicalTableName = logicalTableName; + this.indexTableName = indexTableName; + String sql = substitueQuestionToTableName(physicalPlanData.getSqlTemplate()); + this.setSourceSql(sql); + onExceptionTryRecoveryThenRollback(); + } + + @Override + public void executeImpl(ExecutionContext executionContext) { + ITransactionManager tm = ExecutorContext.getContext(schemaName).getTransactionManager(); + assignDdlConcurrentParams(executionContext); + GsiUtils.wrapWithNoTrx(tm, executionContext, addLocalIndexEc -> { + super.executeImpl(addLocalIndexEc); + return null; + }); + } + + void assignDdlConcurrentParams(ExecutionContext executionContext) { + ParamManager paramManager = executionContext.getParamManager(); + if (paramManager.getBoolean(ConnectionParams.GSI_BACKFILL_OVERRIDE_DDL_PARAMS)) { + executionContext.setOverrideDdlParams(true); + } + } + + @Override + protected List genRollbackPhysicalPlans(ExecutionContext executionContext) { + String sql = substitueQuestionToTableName(physicalPlanData.getSqlTemplate()); + SQLAlterTableStatement alterTableStmt = (SQLAlterTableStatement) FastsqlUtils.parseSql(sql).get(0); + String reversedSql = genReversedAlterTableStmt(alterTableStmt); + return genReversedPhysicalPlans(reversedSql, executionContext); + } + + private String substitueQuestionToTableName(String sql) { + // this is very evil, but there are no better way and it's absolutely right on this scene. + // don't refer to it unless you know what you are doing like me. + return sql.replace("ALTER TABLE ?", "ALTER TABLE " + SqlIdentifier.surroundWithBacktick(logicalTableName)); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/CheckGsiTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/CheckGsiTask.java index 801403838..8a9ab0876 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/CheckGsiTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/CheckGsiTask.java @@ -39,6 +39,7 @@ import com.alibaba.polardbx.executor.gsi.corrector.GsiChecker; import com.alibaba.polardbx.executor.gsi.corrector.GsiReporter; import com.alibaba.polardbx.executor.gsi.fastchecker.GsiFastChecker; +import com.alibaba.polardbx.executor.gsi.fastchecker.OmcFastChecker; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalCheckGsi; @@ -47,6 +48,7 @@ import com.alibaba.polardbx.statistics.SQLRecorderLogger; import com.google.common.collect.ImmutableMap; import lombok.Getter; +import lombok.Setter; import org.apache.calcite.sql.SqlSelect; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -56,7 +58,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.TimeUnit; import static com.alibaba.polardbx.executor.utils.ExecUtils.getQueryConcurrencyPolicy; @@ -67,6 +68,7 @@ * @since 2021/07 */ @Getter +@Setter @TaskName(name = "CheckGsiTask") public class CheckGsiTask extends BaseBackfillTask { @@ -81,8 +83,10 @@ public class CheckGsiTask extends BaseBackfillTask { private final String extraCmd; private final boolean primaryBroadCast; private final boolean gsiBroadCast; - private Map virtualColumnMap; - private Map backfillColumnMap; + + private final boolean onlineModifyColumn; + private Map srcCheckColumnMap; + private Map dstCheckColumnMap; public static CheckGsiTask create(CheckGsiPrepareData prepareData) { return new CheckGsiTask( @@ -103,8 +107,7 @@ public static CheckGsiTask create(CheckGsiPrepareData prepareData) { prepareData.getExtraCmd(), false, false, - null, - null + false ); } @@ -119,8 +122,7 @@ public CheckGsiTask(String schemaName, String extraCmd, boolean primaryBroadCast, boolean gsiBroadCast, - Map virtualColumnMap, - Map backfillColumnMap) { + boolean onlineModifyColumn) { super(schemaName); this.tableName = tableName; this.indexName = indexName; @@ -131,25 +133,20 @@ public CheckGsiTask(String schemaName, this.extraCmd = extraCmd; this.primaryBroadCast = primaryBroadCast; this.gsiBroadCast = gsiBroadCast; - this.virtualColumnMap = virtualColumnMap; - this.backfillColumnMap = backfillColumnMap; + this.onlineModifyColumn = onlineModifyColumn; } @Override protected void executeImpl(ExecutionContext ec) { ec = ec.copy(); ec.setBackfillId(getTaskId()); + ec.setTaskId(getTaskId()); // fast checker if (isUseFastChecker(ec) && fastCheck(ec)) { return; } - if (MapUtils.isNotEmpty(virtualColumnMap) || MapUtils.isNotEmpty(backfillColumnMap)) { - throw GeneralUtil.nestedException( - "Fast checker failed. Please try to rollback/recover this job"); - } - // slow checker Checker checker = buildChecker(ec); checker.setJobId(ec.getDdlJobId()); @@ -222,7 +219,7 @@ public void checkInBackfill(ExecutionContext ec) { return; } - if (MapUtils.isNotEmpty(virtualColumnMap) || MapUtils.isNotEmpty(backfillColumnMap)) { + if (MapUtils.isNotEmpty(srcCheckColumnMap) || MapUtils.isNotEmpty(dstCheckColumnMap)) { throw GeneralUtil.nestedException( "Fast checker failed. Please try to rollback/recover this job"); } @@ -271,8 +268,13 @@ private boolean fastCheck(ExecutionContext ec, Map> srcPhyDb .format("FastChecker for GSI, schema [{0}] logical src table [{1}] logic dst table [{2}] start", schemaName, tableName, indexName)); - FastChecker fastChecker = - GsiFastChecker.create(schemaName, tableName, indexName, virtualColumnMap, backfillColumnMap, ec); + FastChecker fastChecker; + if (onlineModifyColumn) { + fastChecker = + OmcFastChecker.create(schemaName, tableName, indexName, srcCheckColumnMap, dstCheckColumnMap, ec); + } else { + fastChecker = GsiFastChecker.create(schemaName, tableName, indexName, ec); + } if (dstPhyDbAndTables != null) { fastChecker.setDstPhyDbAndTables(dstPhyDbAndTables); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/CreateGsiValidateTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/CreateGsiValidateTask.java index 906d8c054..2a4906fc9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/CreateGsiValidateTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/CreateGsiValidateTask.java @@ -39,15 +39,20 @@ public class CreateGsiValidateTask extends BaseValidateTask { final private String indexName; private List tableGroupIds; private TableGroupConfig tableGroupConfig; + private boolean removePartitioning; + private boolean skipTableGroupChangeCheck; @JSONCreator public CreateGsiValidateTask(String schemaName, String primaryTableName, String indexName, - List tableGroupIds, TableGroupConfig tableGroupConfig) { + List tableGroupIds, TableGroupConfig tableGroupConfig, + boolean removePartitioning, boolean skipTableGroupChangeCheck) { super(schemaName); this.primaryTableName = primaryTableName; this.indexName = indexName; this.tableGroupIds = tableGroupIds; this.tableGroupConfig = TableGroupConfig.copyWithoutTables(tableGroupConfig); + this.removePartitioning = removePartitioning; + this.skipTableGroupChangeCheck = skipTableGroupChangeCheck; if (StringUtils.isEmpty(indexName) || StringUtils.isEmpty(primaryTableName)) { throw new TddlRuntimeException(ErrorCode.ERR_GMS_UNEXPECTED, "validate", "The table name shouldn't be empty"); @@ -72,12 +77,20 @@ public void doValidate(ExecutionContext executionContext) { if (!TableValidator.checkIfTableExists(schemaName, primaryTableName)) { throw new TddlRuntimeException(ErrorCode.ERR_UNKNOWN_TABLE, schemaName, primaryTableName); } - IndexValidator.validateIndexNonExistence(schemaName, primaryTableName, indexName); + if (!removePartitioning) { + IndexValidator.validateIndexNonExistence(schemaName, primaryTableName, indexName); + } GsiValidator.validateGsiSupport(schemaName, executionContext); GsiValidator.validateCreateOnGsi(schemaName, indexName, executionContext); TableValidator.validateTableGroupExistence(schemaName, tableGroupIds, executionContext); - TableValidator.validateTableGroupChange(schemaName, tableGroupConfig); + if (!skipTableGroupChangeCheck) { + TableValidator.validateTableGroupChange(schemaName, tableGroupConfig); + } + } + + public void skipTgChangeCheck() { + skipTableGroupChangeCheck = true; } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/GsiPkRangeBackfillLogTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/GsiPkRangeBackfillLogTask.java new file mode 100644 index 000000000..ae2926e24 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/GsiPkRangeBackfillLogTask.java @@ -0,0 +1,71 @@ +package com.alibaba.polardbx.executor.ddl.job.task.gsi; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.eventlogger.EventLogger; +import com.alibaba.polardbx.common.eventlogger.EventType; +import com.alibaba.polardbx.executor.ddl.job.task.BaseValidateTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import lombok.Getter; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +@Getter +@TaskName(name = "GsiPkRangeBackfillLogTask") +public class GsiPkRangeBackfillLogTask extends BaseValidateTask { + + String msg; + + @JSONCreator + public GsiPkRangeBackfillLogTask(String schemaName, String msg) { + super(schemaName); + this.msg = msg; + } + + @Override + public void executeImpl(ExecutionContext executionContext) { + // log total time. + // log backfill task num, create table stmt, backfill rows, backfill sizes + // and backfill speed. + // log backfill local index num, local index stmt, local index concurrency, local index time. + // log checker concurrency, checker time. + long totalRows = 1L; + long totalSizes = 1L; + long backfillTaskNum = 1L; + String stmt = ""; + long maxTaskPkRangeSize = 0L; + long maxPkRangeSize = 0L; + long concurrency = 0L; + long nodeNum = 0L; + + long localIndexNum = 0L; + long localIndexConcurrency = 0L; + long localIndexTime = 0L; + long checkerConcurreny = 0L; + long checkerTime = 0L; + String logInfo = + String.format("[schema %s] backfill task num %s, concurrency each node %d, total node %s, total rows %s, total sizes %s", schemaName, backfillTaskNum, concurrency, nodeNum, totalRows, totalSizes); + EventLogger.log(EventType.DDL_MPP_INFO, logInfo); + logInfo = + String.format("[schema %s] create gsi stmt: %s, max task pk range size %d, pk range size %d", schemaName, stmt, maxTaskPkRangeSize, maxPkRangeSize); + EventLogger.log(EventType.DDL_MPP_INFO, logInfo); + logInfo = + String.format("[schema %s] local index num %s, total index time %d, concurrency %d", schemaName, localIndexNum, localIndexTime, localIndexConcurrency); + EventLogger.log(EventType.DDL_MPP_INFO, logInfo); +// logInfo = +// String.format("[schema %s] create local index stmt %s, index time %d", stmt, localIndexNum, localIndexTime); +// EventLogger.log(EventType.REBALANCE_INFO, logInfo); + logInfo = + String.format("[schema %s] checker time %d, checker concurrency %d", schemaName, checkerTime, checkerConcurreny); + EventLogger.log(EventType.DDL_MPP_INFO, logInfo); + + Date currentTime = Calendar.getInstance().getTime(); + SQLRecorderLogger.scaleOutTaskLogger.info(String.format("jobId: %s; msg: %s; timestamp: %s; time: %s", + this.getJobId(), msg, currentTime.getTime(), + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(currentTime))); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/RebuildTableCutOverTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/RebuildTableCutOverTask.java index 04ca018b9..835a7de8e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/RebuildTableCutOverTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/RebuildTableCutOverTask.java @@ -42,18 +42,21 @@ public class RebuildTableCutOverTask extends BaseGmsTask { private final boolean autoPartition; private final boolean single; private final boolean broadcast; + private final long versionId; public RebuildTableCutOverTask(final String schemaName, final String logicalTableName, Map tableNameMap, boolean autoPartition, boolean single, - boolean broadcast) { + boolean broadcast, + long versionId) { super(schemaName, logicalTableName); this.tableNameMap = tableNameMap; this.autoPartition = autoPartition; this.single = single; this.broadcast = broadcast; + this.versionId = versionId; onExceptionTryRollback(); } @@ -79,7 +82,9 @@ protected void executeImpl(Connection metaDbConnection, ExecutionContext executi tableNameMap, autoPartition, single, - broadcast + broadcast, + versionId, + jobId ); FailPoint.injectRandomExceptionFromHint(executionContext); FailPoint.injectRandomSuspendFromHint(executionContext); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/SperateCheckGsiTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/SperateCheckGsiTask.java new file mode 100644 index 000000000..0d135da9d --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/gsi/SperateCheckGsiTask.java @@ -0,0 +1,104 @@ +package com.alibaba.polardbx.executor.ddl.job.task.gsi; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.eventlogger.EventLogger; +import com.alibaba.polardbx.common.eventlogger.EventType; +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.executor.corrector.Checker; +import com.alibaba.polardbx.executor.corrector.CheckerCallback; +import com.alibaba.polardbx.executor.corrector.Reporter; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.ddl.job.task.BaseBackfillTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.fastchecker.FastChecker; +import com.alibaba.polardbx.executor.gsi.CheckerManager; +import com.alibaba.polardbx.executor.gsi.GsiUtils; +import com.alibaba.polardbx.executor.gsi.corrector.Corrector; +import com.alibaba.polardbx.executor.gsi.corrector.GsiChecker; +import com.alibaba.polardbx.executor.gsi.corrector.GsiReporter; +import com.alibaba.polardbx.executor.gsi.fastchecker.GsiFastChecker; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalCheckGsi; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.CheckGsiPrepareData; +import com.alibaba.polardbx.optimizer.utils.QueryConcurrencyPolicy; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import com.google.common.collect.ImmutableMap; +import lombok.Getter; +import org.apache.calcite.sql.SqlSelect; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import static com.alibaba.polardbx.executor.utils.ExecUtils.getQueryConcurrencyPolicy; + +/** + * Check consistency of global index + * + * @author moyi + * @since 2021/07 + */ +@Getter +@TaskName(name = "SperateCheckGsiTask") +public class SperateCheckGsiTask extends CheckGsiTask { + public static SperateCheckGsiTask create(CheckGsiPrepareData prepareData) { + return new SperateCheckGsiTask( + prepareData.getSchemaName(), + prepareData.getTableName(), + prepareData.getIndexName(), + prepareData.getLockMode().getKey().name(), + prepareData.getLockMode().getValue().name(), + new GsiChecker.Params( + prepareData.getBatchSize(), + prepareData.getSpeedLimit(), + prepareData.getSpeedMin(), + prepareData.getParallelism(), + prepareData.getEarlyFailNumber(), + prepareData.isUseBinary() + ), + prepareData.isCorrect(), + prepareData.getExtraCmd(), + false, + false, + null, + null + ); + } + + @JSONCreator + public SperateCheckGsiTask(String schemaName, + String tableName, + String indexName, + String primaryTableLockMode, + String indexTableLockMode, + GsiChecker.Params checkParams, + boolean correct, + String extraCmd, + boolean primaryBroadCast, + boolean gsiBroadCast, + Map virtualColumnMap, + Map backfillColumnMap) { + super(schemaName, tableName, + indexName, primaryTableLockMode, + indexTableLockMode, checkParams, + correct, extraCmd, primaryBroadCast, + gsiBroadCast, false); + } + + @Override + protected void executeImpl(ExecutionContext ec) { + checkInBackfill(ec); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupDisableDropPartitionMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupDisableDropPartitionMetaTask.java new file mode 100644 index 000000000..7ef916fc1 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupDisableDropPartitionMetaTask.java @@ -0,0 +1,138 @@ +package com.alibaba.polardbx.executor.ddl.job.task.tablegroup; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.gms.partition.TablePartitionAccessor; +import com.alibaba.polardbx.gms.tablegroup.PartitionGroupRecord; +import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; +import com.google.common.collect.ImmutableList; +import lombok.Getter; + +import java.sql.Connection; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +@Getter +@TaskName(name = "AlterTableGroupDisableDropPartitionMetaTask") +public class AlterTableGroupDisableDropPartitionMetaTask extends BaseDdlTask { + + protected String tableGroupName; + protected Long tableGroupId; + protected String tableName; + protected boolean dropPartitionGroup; + protected String sourceSql; + protected Set oldPartitions; + protected boolean dropSubPartition; + + @JSONCreator + public AlterTableGroupDisableDropPartitionMetaTask(String schemaName, + String tableGroupName, + Long tableGroupId, + String tableName, + boolean dropPartitionGroup, + String sourceSql, + Set oldPartitions, + boolean dropSubPartition) { + super(schemaName); + this.tableGroupName = tableGroupName; + this.tableGroupId = tableGroupId; + this.tableName = tableName; + this.dropPartitionGroup = dropPartitionGroup; + this.sourceSql = sourceSql; + this.oldPartitions = oldPartitions; + this.dropSubPartition = dropSubPartition; + } + + public void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + + disablePartitionsTobeDrop(metaDbConnection, executionContext); + FailPoint.injectRandomExceptionFromHint(executionContext); + FailPoint.injectRandomSuspendFromHint(executionContext); + } + + public void disablePartitionsTobeDrop(Connection metaDbConnection, ExecutionContext executionContext) { + TablePartitionAccessor tbAccessor = new TablePartitionAccessor(); + tbAccessor.setConnection(metaDbConnection); + OptimizerContext oc = + Objects.requireNonNull(OptimizerContext.getContext(schemaName), schemaName + " corrupted"); + TableGroupConfig tableGroupConfig = oc.getTableGroupInfoManager().getTableGroupConfigById(tableGroupId); + List tableNames = dropPartitionGroup ? tableGroupConfig.getTables() : ImmutableList.of(tableName); + if (GeneralUtil.isEmpty(tableNames)) { + throw new TddlRuntimeException(ErrorCode.ERR_TABLEGROUP_META_TOO_OLD, + tableGroupName + " is empty"); + } + String firstTb = tableGroupConfig.getTables().get(0); + TableMeta tableMeta = executionContext.getSchemaManager(schemaName).getTable(firstTb); + PartitionInfo partitionInfo = tableMeta.getPartitionInfo(); + if (partitionInfo == null) { + throw new TddlRuntimeException(ErrorCode.ERR_TABLEGROUP_META_TOO_OLD, + "PartitionInfo is not exists for table:" + firstTb); + } + List partitionGroupRecords = tableGroupConfig.getPartitionGroupRecords(); + for (String partition : oldPartitions) { + if (dropSubPartition) { + if (partitionInfo.getPartitionBy().getSubPartitionBy().isUseSubPartTemplate()) { + for (String tableName : tableNames) { + tbAccessor.disableStatusBySchTempPartL2(schemaName, tableName, partition); + } + } else { + Optional partitionGroupRecordOpt = + partitionGroupRecords.stream().filter(o -> o.partition_name.equalsIgnoreCase(partition)) + .findFirst(); + if (!partitionGroupRecordOpt.isPresent()) { + throw new TddlRuntimeException(ErrorCode.ERR_TABLEGROUP_META_TOO_OLD, + "partition group:" + partition + " is not exists"); + } + if (dropPartitionGroup) { + tbAccessor.disableStatusBySchGidL2(schemaName, partitionGroupRecordOpt.get().id); + } else { + tbAccessor.disableStatusBySchTbGidL2(schemaName, tableName, partitionGroupRecordOpt.get().id); + } + } + } else { + for (String tableName : tableNames) { + tbAccessor.disableStatusBySchPartL1(schemaName, tableName, partition); + } + if (partitionInfo.getPartitionBy().getSubPartitionBy() != null) { + PartitionSpec partitionSpec = partitionInfo.getPartitionBy().getPartitionByPartName(partition); + for (PartitionSpec subPartSpec : partitionSpec.getSubPartitions()) { + Optional partitionGroupRecordOpt = + partitionGroupRecords.stream() + .filter(o -> o.partition_name.equalsIgnoreCase(subPartSpec.getName())) + .findFirst(); + if (!partitionGroupRecordOpt.isPresent()) { + throw new TddlRuntimeException(ErrorCode.ERR_TABLEGROUP_META_TOO_OLD, + "partition group:" + subPartSpec.getName() + " is not exists"); + } + if (dropPartitionGroup) { + tbAccessor.disableStatusBySchGidL2(schemaName, partitionGroupRecordOpt.get().id); + } else { + tbAccessor.disableStatusBySchTbGidL2(schemaName, tableName, + partitionGroupRecordOpt.get().id); + } + } + } + } + } + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + //do not support rollback + updateSupportedCommands(true, false, metaDbConnection); + executeImpl(metaDbConnection, executionContext); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupDropPartitionAddSubTaskMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupDropPartitionAddSubTaskMetaTask.java new file mode 100644 index 000000000..5ede98e7f --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupDropPartitionAddSubTaskMetaTask.java @@ -0,0 +1,80 @@ +package com.alibaba.polardbx.executor.ddl.job.task.tablegroup; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.gms.partition.TablePartitionAccessor; +import com.alibaba.polardbx.gms.partition.TablePartitionRecord; +import com.alibaba.polardbx.gms.tablegroup.ComplexTaskOutlineRecord; +import com.alibaba.polardbx.gms.tablegroup.PartitionGroupRecord; +import com.alibaba.polardbx.gms.tablegroup.TableGroupUtils; +import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; + +import java.sql.Connection; +import java.util.List; +import java.util.Map; + +@Getter +@TaskName(name = "AlterTableGroupDropPartitionAddSubTaskMetaTask") +// here is add meta to partition_partitions_delta table for CDC mark usage only +public class AlterTableGroupDropPartitionAddSubTaskMetaTask extends BaseGmsTask { + + protected String tableName; + protected TablePartitionRecord logTableRec; + protected List partRecList; + protected Map> subPartRecInfos; + + @JSONCreator + public AlterTableGroupDropPartitionAddSubTaskMetaTask(String schemaName, String tableName, + TablePartitionRecord logTableRec, + List partRecList, + Map> subPartRecInfos) { + super(schemaName, tableName); + this.tableName = tableName; + this.logTableRec = logTableRec; + this.partRecList = partRecList; + this.subPartRecInfos = subPartRecInfos; + } + + public void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + TablePartitionAccessor tablePartitionAccessor = new TablePartitionAccessor(); + tablePartitionAccessor.setConnection(metaDbConnection); + + if (GeneralUtil.isNotEmpty(subPartRecInfos)) { + for (Map.Entry> entry : subPartRecInfos.entrySet()) { + if (GeneralUtil.isEmpty(entry.getValue())) { + partRecList.removeIf(o -> o.getPartName().equalsIgnoreCase(entry.getKey())); + subPartRecInfos.remove(entry.getKey()); + } + } + } + tablePartitionAccessor.addNewTablePartitionConfigs(logTableRec, + partRecList, + subPartRecInfos, + true, true); + FailPoint.injectRandomExceptionFromHint(executionContext); + FailPoint.injectRandomSuspendFromHint(executionContext); + } + + public void rollbackImpl(Connection metaDbConnection, ExecutionContext executionContext) { + TablePartitionAccessor tablePartitionAccessor = new TablePartitionAccessor(); + tablePartitionAccessor.setConnection(metaDbConnection); + tablePartitionAccessor + .deleteTablePartitionConfigsForDeltaTable(schemaName, tableName); + } + + @Override + protected void onExecutionSuccess(ExecutionContext executionContext) { + } + + @Override + protected void updateTableVersion(Connection metaDbConnection) { + //do nothing + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupDropPartitionRefreshMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupDropPartitionRefreshMetaTask.java new file mode 100644 index 000000000..4414e3346 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupDropPartitionRefreshMetaTask.java @@ -0,0 +1,316 @@ +package com.alibaba.polardbx.executor.ddl.job.task.tablegroup; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.gms.partition.TablePartRecordInfoContext; +import com.alibaba.polardbx.gms.partition.TablePartitionAccessor; +import com.alibaba.polardbx.gms.partition.TablePartitionConfig; +import com.alibaba.polardbx.gms.partition.TablePartitionRecord; +import com.alibaba.polardbx.gms.partition.TablePartitionSpecConfig; +import com.alibaba.polardbx.gms.tablegroup.PartitionGroupAccessor; +import com.alibaba.polardbx.gms.tablegroup.PartitionGroupRecord; +import com.alibaba.polardbx.gms.tablegroup.TableGroupAccessor; +import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.gms.tablegroup.TableGroupRecord; +import com.alibaba.polardbx.gms.tablegroup.TableGroupUtils; +import com.alibaba.polardbx.gms.topology.DbGroupInfoAccessor; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionInfoUtil; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import com.google.common.collect.ImmutableList; +import lombok.Getter; + +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.TreeMap; +import java.util.stream.Collectors; + +@Getter +@TaskName(name = "AlterTableGroupDropPartitionRefreshMetaTask") +public class AlterTableGroupDropPartitionRefreshMetaTask extends BaseDdlTask { + + protected String tableGroupName; + protected String targetTableGroupName; + protected String tableName; + protected boolean dropPartitionGroup; + protected String sourceSql; + protected Set oldPartitions; + protected boolean dropSubPartition; + + @JSONCreator + public AlterTableGroupDropPartitionRefreshMetaTask(String schemaName, + String tableGroupName, + String targetTableGroupName, + String tableName, + boolean dropPartitionGroup, + String sourceSql, + Set oldPartitions, + boolean dropSubPartition) { + super(schemaName); + this.tableGroupName = tableGroupName; + this.targetTableGroupName = targetTableGroupName; + this.tableName = tableName; + this.dropPartitionGroup = dropPartitionGroup; + this.sourceSql = sourceSql; + this.oldPartitions = oldPartitions; + this.dropSubPartition = dropSubPartition; + } + + public void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + removePartitionsTobeDrop(metaDbConnection, executionContext); + refreshTableGroupMeta(metaDbConnection, executionContext); + FailPoint.injectRandomExceptionFromHint(executionContext); + FailPoint.injectRandomSuspendFromHint(executionContext); + } + + public void removePartitionsTobeDrop(Connection metaDbConnection, ExecutionContext executionContext) { + TablePartitionAccessor tbAccessor = new TablePartitionAccessor(); + PartitionGroupAccessor partitionGroupAccessor = new PartitionGroupAccessor(); + + tbAccessor.setConnection(metaDbConnection); + partitionGroupAccessor.setConnection(metaDbConnection); + + OptimizerContext oc = + Objects.requireNonNull(OptimizerContext.getContext(schemaName), schemaName + " corrupted"); + TableGroupConfig tableGroupConfig = oc.getTableGroupInfoManager().getTableGroupConfigByName(tableGroupName); + if (GeneralUtil.isEmpty(tableGroupConfig.getTables())) { + throw new TddlRuntimeException(ErrorCode.ERR_TABLEGROUP_META_TOO_OLD, + tableGroupName + " is empty"); + } + boolean onlyOneTable = tableGroupConfig.getTables().size() == 1; + List tableNames = dropPartitionGroup ? tableGroupConfig.getTables() : ImmutableList.of(tableName); + String firstTb = tableNames.get(0); + TableMeta tableMeta = executionContext.getSchemaManager(schemaName).getTable(firstTb); + PartitionInfo partitionInfo = tableMeta.getPartitionInfo(); + if (partitionInfo == null) { + throw new TddlRuntimeException(ErrorCode.ERR_TABLEGROUP_META_TOO_OLD, + "PartitionInfo is not exists for table:" + firstTb); + } + + List inValidTablePartitions; + if (partitionInfo.containSubPartitions()) { + inValidTablePartitions = tbAccessor.getInValidTablePartitionsByDbNameTbNameLevel(schemaName, firstTb, + TablePartitionRecord.PARTITION_LEVEL_SUBPARTITION); + } else { + inValidTablePartitions = tbAccessor.getInValidTablePartitionsByDbNameTbNameLevel(schemaName, firstTb, + TablePartitionRecord.PARTITION_LEVEL_PARTITION); + } + + if (GeneralUtil.isEmpty(inValidTablePartitions)) { + throw new TddlRuntimeException(ErrorCode.ERR_TABLEGROUP_META_TOO_OLD, + "invalidTablePartitionRecord is not exists for table:" + firstTb); + } else { + if (onlyOneTable || dropPartitionGroup) { + for (TablePartitionRecord partitionRecord : inValidTablePartitions) { + partitionGroupAccessor.deletePartitionGroupById(partitionRecord.groupId); + } + } + } + + List partitionGroupRecords = tableGroupConfig.getPartitionGroupRecords(); + for (String partition : oldPartitions) { + if (dropSubPartition) { + if (partitionInfo.getPartitionBy().getSubPartitionBy().isUseSubPartTemplate()) { + for (String tableName : tableNames) { + tbAccessor.deletePartitionBySchTempPartL2(schemaName, tableName, partition); + } + } else { + Optional partitionGroupRecordOpt = + partitionGroupRecords.stream().filter(o -> o.partition_name.equalsIgnoreCase(partition)) + .findFirst(); + if (!partitionGroupRecordOpt.isPresent()) { + throw new TddlRuntimeException(ErrorCode.ERR_TABLEGROUP_META_TOO_OLD, + "partition group:" + partition + " is not exists"); + } + if (dropPartitionGroup) { + tbAccessor.deletePartitionBySchGidL2(schemaName, partitionGroupRecordOpt.get().id); + } else { + tbAccessor.deletePartitionBySchTbGidL2(schemaName, tableName, partitionGroupRecordOpt.get().id); + } + } + } else { + for (String tableName : tableNames) { + tbAccessor.deletePartitionBySchPartL1(schemaName, tableName, partition); + } + if (partitionInfo.getPartitionBy().getSubPartitionBy() != null) { + PartitionSpec partitionSpec = partitionInfo.getPartitionBy().getPartitionByPartName(partition); + for (PartitionSpec subPartSpec : partitionSpec.getSubPartitions()) { + Optional partitionGroupRecordOpt = + partitionGroupRecords.stream() + .filter(o -> o.partition_name.equalsIgnoreCase(subPartSpec.getName())) + .findFirst(); + if (!partitionGroupRecordOpt.isPresent()) { + throw new TddlRuntimeException(ErrorCode.ERR_TABLEGROUP_META_TOO_OLD, + "partition group:" + subPartSpec.getName() + " is not exists"); + } + if (dropPartitionGroup) { + tbAccessor.deletePartitionBySchGidL2(schemaName, partitionGroupRecordOpt.get().id); + } else { + tbAccessor.deletePartitionBySchTbGidL2(schemaName, tableName, + partitionGroupRecordOpt.get().id); + } + } + } + } + } + + if (dropSubPartition && !partitionInfo.getPartitionBy().getSubPartitionBy().isUseSubPartTemplate()) { + boolean noLogicalPartDelete = true; + for (String tableName : tableNames) { + tableMeta = executionContext.getSchemaManager(schemaName).getTable(tableName); + partitionInfo = tableMeta.getPartitionInfo(); + + if (partitionInfo.getPartitionBy().getSubPartitionBy() != null) { + for (PartitionSpec partitionSpec : partitionInfo.getPartitionBy().getPartitions()) { + boolean deleteLogicalPart = true; + if (partitionSpec.getSubPartitions().size() <= oldPartitions.size()) { + for (PartitionSpec subPartSpec : partitionSpec.getSubPartitions()) { + if (!oldPartitions.contains(subPartSpec.getName())) { + deleteLogicalPart = false; + break; + } + } + if (deleteLogicalPart) { + noLogicalPartDelete = false; + tbAccessor.deleteTablePartitionsById(partitionSpec.getId()); + } + } + } + } + if (noLogicalPartDelete) { + break; + } + } + } + + } + + public void refreshTableGroupMeta(Connection metaDbConnection, ExecutionContext executionContext) { + + TablePartitionAccessor tablePartitionAccessor = new TablePartitionAccessor(); + PartitionGroupAccessor partitionGroupAccessor = new PartitionGroupAccessor(); + tablePartitionAccessor.setConnection(metaDbConnection); + partitionGroupAccessor.setConnection(metaDbConnection); + TableGroupConfig tableGroupConfig = + OptimizerContext.getContext(schemaName).getTableGroupInfoManager() + .getTableGroupConfigByName(tableGroupName); + + List tableNames = dropPartitionGroup ? tableGroupConfig.getTables() : ImmutableList.of(tableName); + + String firstTb = tableNames.get(0); + TableMeta tableMeta = executionContext.getSchemaManager(schemaName).getTable(firstTb); + PartitionInfo partitionInfo = tableMeta.getPartitionInfo(); + boolean isUpsert = true; + for (String tableName : tableNames) { + if (!StringUtils.isEmpty(targetTableGroupName) && !tableGroupName.equalsIgnoreCase(targetTableGroupName)) { + TableGroupConfig newTableGroupConfig = + OptimizerContext.getContext(schemaName).getTableGroupInfoManager() + .getTableGroupConfigByName(targetTableGroupName); + + long newTableGroupId = newTableGroupConfig.getTableGroupRecord().id; + + List tablePartitionRecords = + tablePartitionAccessor.getValidTablePartitionsByDbNameTbNameLevel(schemaName, tableName, + TablePartitionRecord.PARTITION_LEVEL_LOGICAL_TABLE); + assert tablePartitionRecords.size() == 1; + + // 1.1、update table's groupid + tablePartitionAccessor.updateGroupIdById(newTableGroupId, tablePartitionRecords.get(0).id); + + List phyTablePartitionRecords; + if (partitionInfo.containSubPartitions()) { + phyTablePartitionRecords = + tablePartitionAccessor.getValidTablePartitionsByDbNameTbNameLevel(schemaName, tableName, + TablePartitionRecord.PARTITION_LEVEL_SUBPARTITION); + } else { + phyTablePartitionRecords = + tablePartitionAccessor.getValidTablePartitionsByDbNameTbNameLevel(schemaName, tableName, + TablePartitionRecord.PARTITION_LEVEL_PARTITION); + } + List partitionGroupRecords = newTableGroupConfig.getPartitionGroupRecords(); + + for (PartitionGroupRecord partitionGroupRecord : partitionGroupRecords) { + TablePartitionRecord tablePartitionRecord = + phyTablePartitionRecords.stream() + .filter(tp -> tp.getPartName().equalsIgnoreCase(partitionGroupRecord.getPartition_name())) + .findFirst().orElse(null); + + if (tablePartitionRecord == null) { + throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_MANAGEMENT, + "can't find the partition:" + partitionGroupRecord.getPartition_name()); + } + + // 1.2、update partition's groupid + tablePartitionAccessor.updateGroupIdById(partitionGroupRecord.id, tablePartitionRecord.getId()); + } + } + tablePartitionAccessor.deleteTablePartitionConfigsForDeltaTable(schemaName, tableName); + List logicalTableRecords = + tablePartitionAccessor.getValidTablePartitionsByDbNameTbNameLevel(schemaName, tableName, + TablePartitionRecord.PARTITION_LEVEL_LOGICAL_TABLE); + assert logicalTableRecords.size() == 1; + + List tablePartitionRecords = + tablePartitionAccessor.getValidTablePartitionsByDbNameTbNameLevel(schemaName, tableName, + TablePartitionRecord.PARTITION_LEVEL_PARTITION); + + List tableSubPartitionRecords = + tablePartitionAccessor.getValidTablePartitionsByDbNameTbNameLevel(schemaName, tableName, + TablePartitionRecord.PARTITION_LEVEL_SUBPARTITION); + + Map> subPartRecordInfos = + prepareRecordForAllSubpartitions(partitionInfo, tablePartitionRecords, tableSubPartitionRecords); + + tablePartitionAccessor.addNewTablePartitionConfigs(logicalTableRecords.get(0), + tablePartitionRecords, + subPartRecordInfos, + isUpsert, false); + } + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + executeImpl(metaDbConnection, executionContext); + } + + private Map> prepareRecordForAllSubpartitions( + PartitionInfo partitionInfo, + List parentRecords, + List subPartRecords) { + + Map> subPartRecordInfos = new HashMap<>(); + if (partitionInfo.getPartitionBy().getSubPartitionBy() == null) { + return subPartRecordInfos; + } + + for (int k = 0; k < parentRecords.size(); k++) { + TablePartitionRecord parentRecord = parentRecords.get(k); + Map> subPartMap = subPartRecords.stream() + .collect(Collectors.groupingBy(TablePartitionRecord::getParentId)); + List subPartRecList = subPartMap.get(parentRecord.id); + if (subPartRecList != null) { + subPartRecordInfos.put(parentRecord.getPartName(), subPartRecList); + } + } + return subPartRecordInfos; + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupMovePartitionRefreshMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupMovePartitionRefreshMetaTask.java index 424f09f45..87acc440b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupMovePartitionRefreshMetaTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupMovePartitionRefreshMetaTask.java @@ -23,7 +23,6 @@ import com.alibaba.polardbx.gms.metadb.table.ColumnMetaAccessor; import com.alibaba.polardbx.gms.metadb.table.FilesAccessor; import com.alibaba.polardbx.gms.metadb.table.FilesRecord; -import com.alibaba.polardbx.gms.partition.TablePartRecordInfoContext; import com.alibaba.polardbx.gms.partition.TablePartitionAccessor; import com.alibaba.polardbx.gms.partition.TablePartitionRecord; import com.alibaba.polardbx.gms.tablegroup.PartitionGroupAccessor; @@ -48,8 +47,8 @@ public class AlterTableGroupMovePartitionRefreshMetaTask extends AlterTableGroupRefreshMetaBaseTask { @JSONCreator - public AlterTableGroupMovePartitionRefreshMetaTask(String schemaName, String tableGroupName) { - super(schemaName, tableGroupName); + public AlterTableGroupMovePartitionRefreshMetaTask(String schemaName, String tableGroupName, Long versionId) { + super(schemaName, tableGroupName, versionId); } /** diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupRefreshMetaBaseTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupRefreshMetaBaseTask.java index 4f620bef3..ce99ae9b0 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupRefreshMetaBaseTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupRefreshMetaBaseTask.java @@ -17,12 +17,20 @@ package com.alibaba.polardbx.executor.ddl.job.task.tablegroup; import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.ddl.newengine.DdlType; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionStatus; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; import com.alibaba.polardbx.gms.partition.TablePartRecordInfoContext; import com.alibaba.polardbx.gms.partition.TablePartitionAccessor; @@ -42,6 +50,7 @@ import com.alibaba.polardbx.optimizer.partition.PartitionInfoUtil; import com.alibaba.polardbx.optimizer.partition.PartitionSpec; import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import com.google.common.collect.ImmutableList; import lombok.Getter; import java.sql.Connection; @@ -58,11 +67,13 @@ public class AlterTableGroupRefreshMetaBaseTask extends BaseDdlTask { protected String tableGroupName; + protected Long versionId; @JSONCreator - public AlterTableGroupRefreshMetaBaseTask(String schemaName, String tableGroupName) { + public AlterTableGroupRefreshMetaBaseTask(String schemaName, String tableGroupName, Long versionId) { super(schemaName); this.tableGroupName = tableGroupName; + this.versionId = versionId; } public void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { @@ -103,10 +114,17 @@ public void refreshTableGroupMeta(Connection metaDbConnection) { TablePartitionAccessor tablePartitionAccessor = new TablePartitionAccessor(); PartitionGroupAccessor partitionGroupAccessor = new PartitionGroupAccessor(); DbGroupInfoAccessor dbGroupInfoAccessor = new DbGroupInfoAccessor(); + ColumnarTableMappingAccessor columnarTableMappingAccessor = new ColumnarTableMappingAccessor(); + ColumnarTableEvolutionAccessor columnarTableEvolutionAccessor = new ColumnarTableEvolutionAccessor(); + ColumnarPartitionEvolutionAccessor columnarPartitionEvolutionAccessor = + new ColumnarPartitionEvolutionAccessor(); tablePartitionAccessor.setConnection(metaDbConnection); partitionGroupAccessor.setConnection(metaDbConnection); dbGroupInfoAccessor.setConnection(metaDbConnection); + columnarTableMappingAccessor.setConnection(metaDbConnection); + columnarTableEvolutionAccessor.setConnection(metaDbConnection); + columnarPartitionEvolutionAccessor.setConnection(metaDbConnection); updateTaskStatus(metaDbConnection); @@ -242,6 +260,10 @@ public void refreshTableGroupMeta(Connection metaDbConnection) { tablePartRecordInfoContext.getSubPartitionRecMap(), isUpsert, false); + // 4.5 insert new columnar table partition to columnar evolution + updateColumnarEvolutionSysTables(tableMeta, tableName, tablePartitionAccessor, columnarTableMappingAccessor, + columnarPartitionEvolutionAccessor, columnarTableEvolutionAccessor, versionId, jobId); + // 5、cleanup table_partition_delta //only delete the related records tablePartitionAccessor @@ -292,4 +314,104 @@ protected void updateTableVersion(Connection metaDbConnection, String schemaName } } + public void updateColumnarEvolutionSysTables(TableMeta tableMeta, String tableName, + TablePartitionAccessor tablePartitionAccessor, + ColumnarTableMappingAccessor columnarTableMappingAccessor, + ColumnarPartitionEvolutionAccessor columnarPartitionEvolutionAccessor, + ColumnarTableEvolutionAccessor columnarTableEvolutionAccessor, + long versionId, long jobId) { + if (tableMeta.isColumnar()) { + // Insert column evolution records + List partitionRecords = + tablePartitionAccessor.getTablePartitionsByDbNameTbName(schemaName, tableName, false); + + List records = + columnarTableMappingAccessor.querySchemaIndex(schemaName, tableName); + if (records == null || records.isEmpty()) { + throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, + String.format("Failed to get columnar table mapping for table[%s]", tableName)); + } + + // get columnar table mapping + ColumnarTableMappingRecord record = records.get(0); + // get latest columnar table evolution + ColumnarTableEvolutionRecord columnarTableEvolutionRecord = + columnarTableEvolutionAccessor.queryTableIdLatest(record.tableId).get(0); + + List partitions = columnarTableEvolutionRecord.partitions; + + List columnarPartitionEvolutionRecords = + columnarPartitionEvolutionAccessor.queryIdsWithOrder(columnarTableEvolutionRecord.partitions); + + // find first changed partition(except logic partition) + int pos = getPos(partitionRecords, columnarPartitionEvolutionRecords); + + List partitionEvolutionRecords = new ArrayList<>(); + + // old logic partition +// columnarPartitionEvolutionRecords.get(0).status = ColumnarPartitionStatus.ABSENT.getValue(); +// partitionEvolutionRecords.add(columnarPartitionEvolutionRecords.get(0)); + // new logic partition + partitionEvolutionRecords.add( + new ColumnarPartitionEvolutionRecord(record.tableId, partitionRecords.get(0).partName, + versionId, jobId, partitionRecords.get(0), ColumnarPartitionStatus.PUBLIC.getValue())); + + // other level partitions + for (int i = pos; i < partitionRecords.size(); i++) { + partitionEvolutionRecords.add( + new ColumnarPartitionEvolutionRecord(record.tableId, partitionRecords.get(i).partName, + versionId, jobId, partitionRecords.get(i), ColumnarPartitionStatus.PUBLIC.getValue())); + } +// for (int i = pos; i < columnarPartitionEvolutionRecords.size(); i++) { +// columnarPartitionEvolutionRecords.get(i).status = ColumnarPartitionStatus.ABSENT.getValue(); +// partitionEvolutionRecords.add(columnarPartitionEvolutionRecords.get(i)); +// } + + if (!partitionEvolutionRecords.isEmpty()) { + columnarPartitionEvolutionAccessor.insert(partitionEvolutionRecords); + columnarPartitionEvolutionAccessor.updatePartitionIdAsId(record.tableId, versionId); + } + + partitionEvolutionRecords = + columnarPartitionEvolutionAccessor.queryTableIdAndNotInStatus(record.tableId, versionId, + ColumnarPartitionStatus.ABSENT.getValue()); + + // first partition must be logic partition + partitions = partitions.subList(1, Math.min(pos, partitionRecords.size())); + partitions.add(0, partitionEvolutionRecords.get(0).id); + // other partitions + for (int i = 1; i < partitionEvolutionRecords.size(); i++) { + partitions.add(partitionEvolutionRecords.get(i).id); + } + + ColumnarTableEvolutionRecord latest = + columnarTableEvolutionAccessor.queryTableIdLatest(record.tableId).get(0); + latest.versionId = versionId; + latest.commitTs = Long.MAX_VALUE; + latest.ddlType = DdlType.ALTER_TABLE.name(); + latest.ddlJobId = jobId; + latest.partitions = partitions; + columnarTableEvolutionAccessor.insert(ImmutableList.of(latest)); + columnarTableMappingAccessor.updateVersionId(versionId, record.tableId); + } + } + + private static int getPos(List partitionRecords, + List columnarPartitionEvolutionRecords) { + int pos = -1; + // first is logic partition + for (int i = 1; i < Math.min(columnarPartitionEvolutionRecords.size(), partitionRecords.size()); i++) { + ColumnarPartitionEvolutionRecord evolutionRecord = columnarPartitionEvolutionRecords.get(i); + TablePartitionRecord partitionRecord = partitionRecords.get(i); + if (!TablePartitionRecord.isPartitionRecordEqual(partitionRecord, evolutionRecord.partitionRecord)) { + pos = i; + break; + } + } + // add/drop column last + if (pos == -1) { + pos = columnarPartitionEvolutionRecords.size(); + } + return pos; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupValidateTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupValidateTask.java index c33cc4702..3b6b8b3b1 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupValidateTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableGroupValidateTask.java @@ -25,7 +25,6 @@ import com.alibaba.polardbx.executor.ddl.job.task.BaseValidateTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; import com.alibaba.polardbx.executor.ddl.job.validator.TableGroupValidator; -import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; import com.alibaba.polardbx.gms.metadb.table.TablesAccessor; import com.alibaba.polardbx.gms.metadb.table.TablesRecord; @@ -36,7 +35,6 @@ import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.statistics.SQLRecorderLogger; import lombok.Getter; -import org.apache.calcite.sql.SqlKind; import java.sql.Connection; import java.util.Map; @@ -76,11 +74,6 @@ public void executeImpl(ExecutionContext executionContext) { OptimizerContext.getContext(schemaName).getTableGroupInfoManager() .getTableGroupConfigByName(tableGroupName); - for (String primaryTableName : tableGroupConfig.getAllTables()) { - TableValidator.validateTableWithCCI(schemaName, primaryTableName, executionContext, - SqlKind.ALTER_TABLEGROUP); - } - if (GeneralUtil.isNotEmpty(tablesVersion)) { for (Map.Entry tableVersionInfo : tablesVersion.entrySet()) { Long newTableVersion = diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableSetTableGroupChangeMetaOnlyTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableSetTableGroupChangeMetaOnlyTask.java index 7d2d8e34f..39e839bc1 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableSetTableGroupChangeMetaOnlyTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableSetTableGroupChangeMetaOnlyTask.java @@ -24,7 +24,6 @@ import com.alibaba.polardbx.executor.partitionmanagement.AlterTableGroupUtils; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; -import com.alibaba.polardbx.gms.partition.TablePartRecordInfoContext; import com.alibaba.polardbx.gms.partition.TablePartitionAccessor; import com.alibaba.polardbx.gms.tablegroup.JoinGroupInfoAccessor; import com.alibaba.polardbx.gms.tablegroup.JoinGroupInfoRecord; @@ -249,6 +248,8 @@ private void addNewPartitionGroupFromPartitionInfo(PartitionInfo partitionInfo, } } else if (partitionInfo.getTableType() == PartitionTableType.BROADCAST_TABLE) { tableGroupRecord.tg_type = TableGroupRecord.TG_TYPE_BROADCAST_TBL_TG; + } else if (partitionInfo.getTableType() == PartitionTableType.COLUMNAR_TABLE) { + tableGroupRecord.tg_type = TableGroupRecord.TG_TYPE_COLUMNAR_TBL_TG; } else { tableGroupRecord.tg_type = TableGroupRecord.TG_TYPE_PARTITION_TBL_TG; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableSetTableGroupRefreshMetaTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableSetTableGroupRefreshMetaTask.java index c53633a38..4147a4576 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableSetTableGroupRefreshMetaTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/AlterTableSetTableGroupRefreshMetaTask.java @@ -47,8 +47,8 @@ public class AlterTableSetTableGroupRefreshMetaTask extends AlterTableGroupRefre @JSONCreator public AlterTableSetTableGroupRefreshMetaTask(String schemaName, String tableGroupName, Long sourceTableGroupId, - String tableName) { - super(schemaName, tableGroupName); + String tableName, Long versionId) { + super(schemaName, tableGroupName, versionId); this.tableName = tableName; this.sourceTableGroupId = sourceTableGroupId; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/RefreshTopologyfinalTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/RefreshTopologyfinalTask.java index a06ac8c84..043440455 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/RefreshTopologyfinalTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/RefreshTopologyfinalTask.java @@ -21,6 +21,8 @@ import com.alibaba.polardbx.executor.ddl.job.meta.CommonMetaChanger; import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.ddl.newengine.DdlEngineScheduler; +import com.alibaba.polardbx.executor.ddl.newengine.dag.TaskScheduler; import com.alibaba.polardbx.executor.scaleout.ScaleOutUtils; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; import com.alibaba.polardbx.gms.listener.impl.MetaDbConfigManager; @@ -68,6 +70,7 @@ public void executeImpl(Connection metaDbConnection, ExecutionContext executionC FailPoint.injectRandomSuspendFromHint(executionContext); } } + DdlEngineScheduler.refreshResourceToAllocate(); } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/AbstractTtlJobTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/AbstractTtlJobTask.java new file mode 100644 index 000000000..b25582dc6 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/AbstractTtlJobTask.java @@ -0,0 +1,49 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlJobManager; +import com.alibaba.polardbx.executor.ddl.newengine.serializable.SerializableClassMapper; + +import java.util.List; + +/** + * @author chenghui.lch + */ +public abstract class AbstractTtlJobTask extends BaseDdlTask implements TtlJobTask { + + /** + * The ttl table name + */ + protected String logicalTableName; + + /** + * The whole ttl context of a ttl job + */ + protected TtlJobContext jobContext; + + public AbstractTtlJobTask(String schemaName, String logicalTableName) { + super(schemaName); + this.logicalTableName = logicalTableName; + } + + @Override + public TtlJobContext getJobContext() { + return jobContext; + } + + @Override + public void setJobContext(TtlJobContext jobContext) { + this.jobContext = jobContext; + } + + public String getLogicalTableName() { + return logicalTableName; + } + + public void setLogicalTableName(String logicalTableName) { + this.logicalTableName = logicalTableName; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/ArchivePartitionValidateTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/ArchivePartitionValidateTask.java new file mode 100644 index 000000000..548b25ca5 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/ArchivePartitionValidateTask.java @@ -0,0 +1,38 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.executor.ddl.job.task.BaseValidateTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.optimizer.archive.CheckOSSArchiveUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; + +import java.util.List; + +/** + * @author wumu + */ +@Getter +@TaskName(name = "ArchivePartitionValidateTask") +public class ArchivePartitionValidateTask extends BaseValidateTask { + protected final String ossTableName; + protected final String tmpTableSchema; + protected final String tmpTableName; + protected final List partNames; + + public ArchivePartitionValidateTask(String schemaName, String ossTableName, + String tmpTableSchema, String tmpTableName, + List partNames) { + super(schemaName); + this.ossTableName = ossTableName; + this.tmpTableSchema = tmpTableSchema; + this.tmpTableName = tmpTableName; + this.partNames = partNames; + } + + @Override + protected void executeImpl(ExecutionContext executionContext) { + CheckOSSArchiveUtil.checkColumnConsistency(schemaName, ossTableName, tmpTableSchema, tmpTableName); + + CheckOSSArchiveUtil.validateArchivePartitions(tmpTableSchema, tmpTableName, partNames, executionContext); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CheckAndPerformingOptiTtlTableTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CheckAndPerformingOptiTtlTableTask.java new file mode 100644 index 000000000..d4307b21d --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CheckAndPerformingOptiTtlTableTask.java @@ -0,0 +1,770 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.ddl.newengine.DdlState; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler.TtlScheduledJobStatManager; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.misc.DdlEngineAccessor; +import com.alibaba.polardbx.gms.metadb.misc.DdlEngineRecord; +import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import lombok.Getter; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicLong; + +/** + * @author chenghui.lch + */ +@Getter +@TaskName(name = "CheckAndPerformingOptiTtlTableTask") +public class CheckAndPerformingOptiTtlTableTask extends AbstractTtlJobTask { + + @JSONCreator + public CheckAndPerformingOptiTtlTableTask(String schemaName, + String logicalTableName) { + super(schemaName, logicalTableName); + onExceptionTryRecoveryThenPause(); + } + + @Override + protected void beforeTransaction(ExecutionContext executionContext) { + super.beforeTransaction(executionContext); + fetchTtlJobContextFromPreviousTask(); + try (Connection metaConn = MetaDbDataSource.getInstance().getConnection()) { + executeInner(metaConn, executionContext); + } catch (Throwable ex) { + throw new TtlJobRuntimeException(ex); + } + } + + protected void executeInner(Connection metaDbConnection, ExecutionContext executionContext) { + /** + * Check if arcTmp table contains ready-state partitions + */ + TtlJobUtil.updateJobStage(this.jobContext, "OptimizingTtlTable"); + NotifyOptiTblTaskLogInfo notifyOptiTblTaskLogInfo = new NotifyOptiTblTaskLogInfo(); + TtlDefinitionInfo ttlDefinitionInfo = this.jobContext.getTtlInfo(); + String ttlTblName = ttlDefinitionInfo.getTtlInfoRecord().getTableName(); + String ttlTblSchema = ttlDefinitionInfo.getTtlInfoRecord().getTableSchema(); + + notifyOptiTblTaskLogInfo.jobId = this.jobId; + notifyOptiTblTaskLogInfo.taskId = this.taskId; + notifyOptiTblTaskLogInfo.taskBeginTs = System.nanoTime(); + notifyOptiTblTaskLogInfo.waitOptiTblRunningBeginTs = System.nanoTime(); + notifyOptiTblTaskLogInfo.ttlTblSchema = ttlTblSchema; + notifyOptiTblTaskLogInfo.ttlTblName = ttlTblName; + + notifyOptiTblTaskLogInfo.dataFreePercent = this.jobContext.getDataFreePercentAvgOfTtlTbl().longValue(); + notifyOptiTblTaskLogInfo.dataFreePercentLimit = TtlConfigUtil.getMaxDataFreePercentOfTtlTable(); + + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = TtlScheduledJobStatManager.getInstance() + .getTtlJobStatInfo(ttlTblSchema, ttlTblName); + TtlScheduledJobStatManager.GlobalTtlJobStatInfo globalStatInfo = TtlScheduledJobStatManager.getInstance() + .getGlobalTtlJobStatInfo(); + notifyOptiTblTaskLogInfo.jobStatInfo = jobStatInfo; + notifyOptiTblTaskLogInfo.globalStatInfo = globalStatInfo; + + boolean isInterrupted = executionContext.getDdlContext().isInterrupted(); + notifyOptiTblTaskLogInfo.isInterrupted = isInterrupted; + if (isInterrupted) { + + notifyOptiTblTaskLogInfo.waitOptiTblTaskRunningTimeCost = + System.nanoTime() - notifyOptiTblTaskLogInfo.waitOptiTblRunningBeginTs; + logTaskExecResult(notifyOptiTblTaskLogInfo); + + /** + * Throw an exception , so next continue ddl of curr job can be retried + */ + throw new TtlJobRuntimeException(String.format( + "CheckAndPerformingOptiTtlTableTask[%s.%s] is interrupted", ttlTblSchema, ttlTblName)); + } + + Long[] optiTblDdlStmtJobId = new Long[1]; + String[] optiTblDdlStmt = new String[1]; + Boolean[] optiTblDdlStmtFromTtlJob = new Boolean[1]; + boolean optimizePartitionTaskExecuting = + CheckAndPerformingOptiTtlTableTask.checkIfOptiTblDdlExecuting(metaDbConnection, + optiTblDdlStmtJobId, optiTblDdlStmt, optiTblDdlStmtFromTtlJob, ttlTblSchema, ttlTblName); + notifyOptiTblTaskLogInfo.findOptiTblTaskExecuting = optimizePartitionTaskExecuting; + if (optimizePartitionTaskExecuting) { + notifyOptiTblTaskLogInfo.optiTblDdlStmtJobId = optiTblDdlStmtJobId[0]; + notifyOptiTblTaskLogInfo.optiTblDdlStmt = optiTblDdlStmt[0]; + } + + /** + * Trigger optimize partition ddl + *
+         *
+         *      1. check if opti tbl task is running,
+         *          if it is running,
+         *              ignore
+         *          else
+         *              try to trigger a new optiTbl task by logical ddl by async=true;
+         *              check if the ddl has been submitted successfully
+         *  
+ */ + + /** + * Check if one opti tbl ddl of curr ttl table is running + */ + boolean needWaitAndMonitorOptiTblJob = false; + if (!optimizePartitionTaskExecuting) { + + /** + * No found any opti tbl ddl of curr ttl table is running + */ + boolean needPerformOptiTbl = jobContext.getNeedPerformOptiTable(); + if (needPerformOptiTbl) { + /** + * Submit one opti part cmd here and return + */ + submitOptiTableDdl(executionContext, notifyOptiTblTaskLogInfo); + needWaitAndMonitorOptiTblJob = true; + } + } else { + this.jobContext.setNewOptiTableDdlJobId(optiTblDdlStmtJobId[0]); + /** + * Found one opti tbl ddl of curr ttl table is running + */ + boolean optiTblDdlFromTtlJob = optiTblDdlStmtFromTtlJob[0]; + notifyOptiTblTaskLogInfo.optiTblDdlComeFromTtlJob = optiTblDdlFromTtlJob; + if (optiTblDdlFromTtlJob) { + /** + * If the running opti tbl ddl is from ttl-job + */ + needWaitAndMonitorOptiTblJob = true; + } else { + /** + * If the running opti tbl ddl is NOT from ttl-job, + * then it will be exec by user manly, so ignore to wait and monitor + */ + needWaitAndMonitorOptiTblJob = false; + } + } + + notifyOptiTblTaskLogInfo.needWaitAndMonitorOptiTblJob = needWaitAndMonitorOptiTblJob; + if (needWaitAndMonitorOptiTblJob) { + /** + * wait it complete or pause it if it is out of maintain time interval + */ + waitAndMonitorDdlJob(metaDbConnection, executionContext, + this.jobContext.getNewOptiTableDdlJobId(), notifyOptiTblTaskLogInfo); + } + + notifyOptiTblTaskLogInfo.taskEndTs = System.nanoTime(); + notifyOptiTblTaskLogInfo.isFinished = true; + logTaskExecResult(notifyOptiTblTaskLogInfo); + } + + private void waitAndMonitorDdlJob(Connection metaDbConnection, + ExecutionContext executionContext, + Long jobId, + NotifyOptiTblTaskLogInfo logInfo) { + + /** + * The whole progress of wait and monitor opti-tbl ddl job + *
+         *     The ddl job of opti tbl has the following state need handling:
+         *          (1) the job is running or pending:
+         *                  ttl-job should wait it to be completed
+         *              or  ttl-job pause it if ttl-job is interrupted or out of maintain interval;
+         *
+         *          (2) the job is paused:
+         *                  ttl-job try to recover it if ttl-job is in maintain interval;
+         *
+         *          (3) the job is completed and no found in ddl_engine table:
+         *                  ttl-job ignore and return
+         *          (4) other state:
+         *                  ttl-job ignore and return
+         *
+         * 
+ * + */ + + /** + * Fetch the opti-tbl job by jobid + */ + String ttlSchemaName = this.jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + DdlEngineRecord currentJobRec = null; + while (true) { + + logInfo.waitOptiTblTaskRunningLoopRound++; + + /** + * Label if allowed controlling opti tbl job + */ + boolean enableAutoCtrlOptiTblJob = TtlConfigUtil.isEnableAutoControlOptiTblByTtlJob(); + + try { + currentJobRec = fetchLatestDdlJobRecByJobId(metaDbConnection, jobId); + DdlState currentState = null; + int jobProgress = 0; + if (currentJobRec != null) { + currentState = DdlState.valueOf(currentJobRec.state); + jobProgress = currentJobRec.progress; + logInfo.optiJobProgress = jobProgress; + } + if (currentState == null) { + /** + * No found the opti tbl job by the jobid, + * maybe the job is completed and no found in ddl_engine table, + * so ignore + */ + logInfo.optiTblDdlJobStateBeforeCtrl = ""; + break; + } else { + logInfo.optiTblDdlJobStateBeforeCtrl = currentState.name(); + + if (currentState == DdlState.RUNNING || currentState == DdlState.QUEUED) { + /** + * Wait it to completed, so ignore + */ + } else if (currentState == DdlState.PAUSED) { + /** + * try to recover + */ + recoverOptiTblJob(metaDbConnection, ttlSchemaName, jobId, executionContext, + enableAutoCtrlOptiTblJob, logInfo); + } else { + /** + * Ignore and return + */ + break; + } + } + + boolean currTtlJobOutOfMaintainInterval = !checkIfTtlJobInMaintainTimeWindow(metaDbConnection, jobId); + boolean isInterrupted = executionContext.getDdlContext().isInterrupted(); + logInfo.isInterrupted = isInterrupted; + logInfo.isMaintenancePeriodOver = currTtlJobOutOfMaintainInterval; + + if (isInterrupted || currTtlJobOutOfMaintainInterval) { + pauseOptiTblJob(metaDbConnection, ttlSchemaName, jobId, executionContext, enableAutoCtrlOptiTblJob, + logInfo); + break; + } + + /** + * Wait 5000 ms each round + */ + Thread.sleep(TtlConfigUtil.intraTaskDelegateEachRoundWaitTime); + + } catch (Throwable ex) { + if (ex instanceof TtlJobRuntimeException) { + throw (TtlJobRuntimeException) ex; + } else { + throw new TtlJobRuntimeException(ex); + } + } + + /** + * continue and wait the oss archiving ddl finishing, sleep + */ + try { + logInfo.waitOptiTblTaskRunningTimeCost = System.nanoTime() - logInfo.waitOptiTblRunningBeginTs; + logTaskExecResult(logInfo); + long sleepTimeMills = TtlConfigUtil.intraTaskDelegateEachRoundWaitTime; + Thread.sleep(sleepTimeMills); + } catch (Throwable ex) { + // ignore + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + } + } + + try { + /** + * Fetch the latest progress of optimize table + */ + currentJobRec = fetchLatestDdlJobRecByJobId(metaDbConnection, jobId); + if (currentJobRec != null) { + logInfo.optiJobProgress = currentJobRec.progress; + } else { + logInfo.optiJobProgress = 100; + } + } catch (Throwable ex) { + // ignore + } + } + + protected boolean checkIfTtlJobInMaintainTimeWindow(Connection metaDbConn, Long jobId) { + return TtlJobUtil.checkIfInTtlMaintainWindow(); + } + + protected boolean recoverOptiTblJob(Connection metaDbConn, + String jobSchema, + Long jobId, + ExecutionContext executionContext, + boolean enableAutoCtrlOptiTblJob, + NotifyOptiTblTaskLogInfo logInfo) { + + if (!enableAutoCtrlOptiTblJob) { + return false; + } + + DdlState latestJobState = fetchLatestDdlJobStateByJobId(metaDbConn, jobId); + if (latestJobState == null) { + /** + * Maybe curr ddl job has been completed. + */ + logInfo.noFoundOptiTblJobRec = true; + return true; + } + + if (latestJobState == DdlState.PAUSED) { + + /** + * Send a cmd of continue ddl #job_id to recover the job + */ + int optiTblParallelism = TtlConfigUtil.getOptimizePartitionParallelism(); + String continueDdlSql = TtlTaskSqlBuilder.buildAsyncContinueDdlSql(jobId, optiTblParallelism); + submitDdlJobControlCmd(executionContext, jobSchema, continueDdlSql); + + /** + * Make sure the ddl job has been become the ddl-state of running + */ + logInfo.continueOptiTblSql = continueDdlSql; + waitRecoverDdlDoneByJobId(metaDbConn, jobId, DdlState.RUNNING, executionContext, logInfo); + return true; + } else { + /** + * For other ddl-states,just ignore + */ + return false; + } + } + + protected boolean pauseOptiTblJob(Connection metaDbConn, + String jobSchema, + Long jobId, + ExecutionContext executionContext, + boolean enableAutoCtrlOptiTblJob, + NotifyOptiTblTaskLogInfo logInfo) { + + if (!enableAutoCtrlOptiTblJob) { + return false; + } + + DdlState latestJobState = fetchLatestDdlJobStateByJobId(metaDbConn, jobId); + if (latestJobState == null) { + /** + * Maybe curr ddl job has been complated. + */ + logInfo.noFoundOptiTblJobRec = true; + return true; + } + + if (latestJobState == DdlState.RUNNING || latestJobState == DdlState.QUEUED) { + + /** + * Send a cmd of pause ddl #job_id to pause the job + */ + String pauseDdlSql = TtlTaskSqlBuilder.buildPauseDdlSql(jobId); + long waitPauseDdlBeginTsNano = System.nanoTime(); + submitDdlJobControlCmd(executionContext, jobSchema, pauseDdlSql); + logInfo.pauseOptiTblSql = pauseDdlSql; + logInfo.waitFromRunningToPauseTimeCost = System.nanoTime() - waitPauseDdlBeginTsNano; + return true; + + } else { + /** + * For other ddl-states,just ignore + */ + } + + return false; + } + + protected DdlState fetchLatestDdlJobStateByJobId(Connection metaDbConnection, Long jobId) { + + DdlState ddlState = null; + DdlEngineAccessor ddlEngineAccessor = new DdlEngineAccessor(); + ddlEngineAccessor.setConnection(metaDbConnection); + DdlEngineRecord ddlJobRec = ddlEngineAccessor.query(jobId); + if (ddlJobRec == null) { + /** + * No found the opti tbl job by the jobid, + * maybe the job is completed and no found in ddl_engine table, + * so ignore + */ + } else { + ddlState = DdlState.valueOf(ddlJobRec.state); + } + return ddlState; + } + + protected DdlEngineRecord fetchLatestDdlJobRecByJobId(Connection metaDbConnection, Long jobId) { + DdlEngineAccessor ddlEngineAccessor = new DdlEngineAccessor(); + ddlEngineAccessor.setConnection(metaDbConnection); + DdlEngineRecord ddlJobRec = ddlEngineAccessor.query(jobId); + return ddlJobRec; + } + + protected boolean waitRecoverDdlDoneByJobId(Connection metaDbConnection, + Long jobId, + DdlState taretDdlState, + ExecutionContext ec, + NotifyOptiTblTaskLogInfo logInfo) { + + int waitFinishRecoveringRound = 0; + long waitRecoverBeginTsNano = System.nanoTime(); + long waitRecoverEndTsNano = waitRecoverBeginTsNano; + boolean failedToRecoverDdlJob = false; + while (true) { + boolean isInterrupted = ec.getDdlContext().isInterrupted(); + DdlState latestDdlState = fetchLatestDdlJobStateByJobId(metaDbConnection, jobId); + if (latestDdlState != null) { + if (latestDdlState == taretDdlState) { + break; + } + + if (isInterrupted) { + break; + } + + try { + Thread.sleep(TtlConfigUtil.getIntraTaskDelegateEachRoundWaitTime()); + waitFinishRecoveringRound++; + } catch (Throwable ex) { + // ignore + } finally { + waitRecoverEndTsNano = System.nanoTime(); + } + + long totalWaitTimeNano = waitRecoverEndTsNano - waitRecoverBeginTsNano; + long totalWaitTimeMs = (waitRecoverEndTsNano - waitRecoverBeginTsNano) / 1000000; + if (totalWaitTimeMs > TtlConfigUtil.getMaxWaitTimeForDdlJobFromPauseToRunning()) { + failedToRecoverDdlJob = true; + logInfo.failedToRecoverDdlJob = failedToRecoverDdlJob; + break; + } + + logInfo.waitFromPauseToRunningRound = waitFinishRecoveringRound; + logInfo.waitFromPauseToRunningTimeCost = totalWaitTimeNano; + logTaskExecResult(logInfo); + } else { + logInfo.noFoundOptiTblJobRec = true; + break; + } + } + + logInfo.isInterrupted = true; + logInfo.waitFromPauseToRunningRound = waitFinishRecoveringRound; + logInfo.waitFromPauseToRunningTimeCost = System.nanoTime() - waitRecoverBeginTsNano; + logTaskExecResult(logInfo); + + if (failedToRecoverDdlJob) { + /** + * Throw an exception , so next continue ddl of curr job can be retried + */ + throw new TtlJobRuntimeException( + String.format("Failed to recover optimize table ddlJob[%s] for %s.%s", jobId, logInfo.ttlTblSchema, + logInfo.ttlTblName)); + } + + return true; + } + + public static boolean checkIfOptiTblDdlExecuting(Connection metaDbConnection, + Long[] ddlStmtJobIdOutput, + String[] ddlStmtOutput, + Boolean[] ddlStmtFromTtlJob, + String ttlTableSchema, + String ttlTableName) { + /** + * Trigger archive ddl + *
+         *      1. check if optimize partition task is running,
+         *          if it is running,
+         *              ignore
+         *          else
+         *              try to trigger a new archiving task by logical ddl by async=true;
+         *              check if the ddl has been submitted successfully
+         *  
+ */ + boolean opptimizePartitionTaskRunning = false; + String tblName = ttlTableName; + String tblSchema = ttlTableSchema; + try { + DdlEngineAccessor ddlEngineAccessor = new DdlEngineAccessor(); + ddlEngineAccessor.setConnection(metaDbConnection); + List jobList = ddlEngineAccessor.query(tblSchema, tblName); + List runningOptiPartJobList = new ArrayList<>(); + for (int i = 0; i < jobList.size(); i++) { + DdlEngineRecord ddlEngineRecord = jobList.get(i); + if (ddlEngineRecord.state.equalsIgnoreCase("COMPLETED")) { + continue; + } + if (ddlEngineRecord.ddlStmt.toUpperCase().contains("OPTIMIZE PARTITION")) { + runningOptiPartJobList.add(ddlEngineRecord); + } + if (ddlEngineRecord.ddlStmt.toUpperCase().contains("OPTIMIZE TABLE")) { + runningOptiPartJobList.add(ddlEngineRecord); + } + } + if (!runningOptiPartJobList.isEmpty()) { + Long jobId = runningOptiPartJobList.get(0).getJobId(); + String ddlStmt = runningOptiPartJobList.get(0).ddlStmt; + if (ddlStmtJobIdOutput != null && ddlStmtJobIdOutput.length > 0) { + ddlStmtJobIdOutput[0] = jobId; + } + if (ddlStmtOutput != null && ddlStmtOutput.length > 0) { + ddlStmtOutput[0] = ddlStmt; + if (ddlStmtFromTtlJob != null) { + if (ddlStmt.toLowerCase().contains(TtlTaskSqlBuilder.DDL_FLAG_OF_TTL_JOB)) { + ddlStmtFromTtlJob[0] = true; + } else { + ddlStmtFromTtlJob[0] = false; + } + } + } + opptimizePartitionTaskRunning = true; + } + } catch (Throwable ex) { + throw new TtlJobRuntimeException(ex); + } + + return opptimizePartitionTaskRunning; + } + + protected void submitOptiTableDdl(ExecutionContext executionContext, + NotifyOptiTblTaskLogInfo logInfo) { + + TtlDefinitionInfo ttlDefinitionInfo = this.jobContext.getTtlInfo(); + String ttlTblName = ttlDefinitionInfo.getTtlInfoRecord().getTableName(); + String ttlTblSchema = ttlDefinitionInfo.getTtlInfoRecord().getTableSchema(); + + String ttlTimezoneStr = this.jobContext.getTtlInfo().getTtlInfoRecord().getTtlTimezone(); + String charsetEncoding = TtlConfigUtil.defaultCharsetEncodingOnTransConn; + String sqlModeSetting = TtlConfigUtil.defaultSqlModeOnTransConn; + Map sessionVariables = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + sessionVariables.put("time_zone", ttlTimezoneStr); + sessionVariables.put("names", charsetEncoding); + sessionVariables.put("sql_mode", sqlModeSetting); + + String queryHintOfOptiTbl = TtlConfigUtil.getQueryHintForOptimizeTable(); + String optiTblSql = TtlTaskSqlBuilder.buildAsyncOptimizeTableSql(ttlTblSchema, ttlTblName, queryHintOfOptiTbl); + AtomicLong newSubmitOptiTblJobId = new AtomicLong(0L); + final IServerConfigManager serverConfigManager = TtlJobUtil.getServerConfigManager(); + TtlJobUtil.wrapWithDistributedTrx( + serverConfigManager, + ttlTblSchema, + sessionVariables, + (transConn) -> { + List> rsInfo = TtlJobUtil.execLogicalQueryOnInnerConnection(serverConfigManager, + ttlTblSchema, + transConn, + executionContext, + optiTblSql); + Long jobId = (Long) rsInfo.get(0).get(TtlTaskSqlBuilder.COL_NAME_FOR_DDL_JOB_ID); + newSubmitOptiTblJobId.set(jobId); + return jobId; + } + ); + this.jobContext.setNewOptiTableDdlJobId(newSubmitOptiTblJobId.get()); + logInfo.optiTblDdlStmtJobId = newSubmitOptiTblJobId.get(); + logInfo.newSubmittedOptiTblSql = optiTblSql; + } + + /** + * Submit a cmd of controlling ddl job + */ + protected void submitDdlJobControlCmd(ExecutionContext executionContext, + String jobSchema, + String cmdSql) { + + String ttlTimezoneStr = this.jobContext.getTtlInfo().getTtlInfoRecord().getTtlTimezone(); + String charsetEncoding = TtlConfigUtil.defaultCharsetEncodingOnTransConn; + String sqlModeSetting = TtlConfigUtil.defaultSqlModeOnTransConn; + Map sessionVariables = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + sessionVariables.put("time_zone", ttlTimezoneStr); + sessionVariables.put("names", charsetEncoding); + sessionVariables.put("sql_mode", sqlModeSetting); + final IServerConfigManager serverConfigManager = TtlJobUtil.getServerConfigManager(); + TtlJobUtil.wrapWithDistributedTrx( + serverConfigManager, + jobSchema, + sessionVariables, + (transConn) -> { + int arows = TtlJobUtil.execLogicalDmlOnInnerConnection(serverConfigManager, + jobSchema, + transConn, + executionContext, + cmdSql); + return arows; + } + ); + + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + super.duringTransaction(metaDbConnection, executionContext); + } + + @Override + protected void beforeRollbackTransaction(ExecutionContext executionContext) { + super.beforeRollbackTransaction(executionContext); + } + + @Override + protected void duringRollbackTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + super.duringRollbackTransaction(metaDbConnection, executionContext); + } + + protected void fetchTtlJobContextFromPreviousTask() { + TtlJobContext jobContext = TtlJobUtil.fetchTtlJobContextFromPreviousTaskByTaskName( + getJobId(), + PrepareCleanupIntervalTask.class, + getSchemaName(), + getLogicalTableName() + ); + this.jobContext = jobContext; + } + + protected static class NotifyOptiTblTaskLogInfo { + public NotifyOptiTblTaskLogInfo() { + } + + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo; + TtlScheduledJobStatManager.GlobalTtlJobStatInfo globalStatInfo; + + protected Long jobId; + protected Long taskId; + protected Long taskBeginTs; + protected Long taskEndTs; + + protected String ttlTblSchema; + protected String ttlTblName; + protected long dataFreePercent; + protected long dataFreePercentLimit; + + protected boolean isFinished = false; + protected boolean isInterrupted = false; + protected boolean isMaintenancePeriodOver = false; + + protected boolean enableAutoCtrlOptiTblJob = true; + protected boolean needWaitAndMonitorOptiTblJob = false; + protected long waitOptiTblRunningBeginTs = 0; + protected long waitOptiTblTaskRunningTimeCost = 0; + protected long waitOptiTblTaskRunningLoopRound = 0; + + protected boolean findOptiTblTaskExecuting = false; + protected boolean optiTblDdlComeFromTtlJob = false; + protected long optiTblDdlStmtJobId = 0; + protected String optiTblDdlStmt = ""; + protected String newSubmittedOptiTblSql = ""; + protected String optiTblDdlJobStateBeforeCtrl = ""; + + protected boolean noFoundOptiTblJobRec = false; + protected String continueOptiTblSql = "none"; + protected boolean failedToRecoverDdlJob = false; + protected int waitFromPauseToRunningRound = 0; + protected long waitFromPauseToRunningTimeCost = 0; + + protected String pauseOptiTblSql = "none"; + protected long waitFromRunningToPauseTimeCost = 0; + protected int optiJobProgress = 0; + + } + + protected void logTaskExecResult(NotifyOptiTblTaskLogInfo logInfo) { + + try { + + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = logInfo.jobStatInfo; + TtlScheduledJobStatManager.GlobalTtlJobStatInfo globalStatInfo = logInfo.globalStatInfo; + + jobStatInfo.setOptimizeTableProgress(logInfo.optiJobProgress); + + String logMsg = ""; + String msgPrefix = TtlLoggerUtil.buildTaskLogRowMsgPrefix(jobId, taskId, "NotifyOptiTbl"); + logMsg += String.format("ttlTblSchema: %s, ttlTblName: %s\n", logInfo.ttlTblSchema, logInfo.ttlTblName); + + logMsg += msgPrefix; + logMsg += String.format("isMaintenancePeriodOver: %s\n", logInfo.isMaintenancePeriodOver); + + logMsg += msgPrefix; + logMsg += String.format("dataFreePercent:%s , dataFreePercentLimit: %s\n", logInfo.dataFreePercent, + logInfo.dataFreePercentLimit); + + logMsg += msgPrefix; + logMsg += String.format("enableAutoCtrlOptiTblJob: %s\n", logInfo.enableAutoCtrlOptiTblJob); + + logMsg += msgPrefix; + logMsg += String.format("needWaitAndMonitorOptiTblJob: %s\n", logInfo.needWaitAndMonitorOptiTblJob); + + logMsg += msgPrefix; + logMsg += + String.format("interrupted: %s, loopRound: %s, waitOptiTblTimeCost(ns): %s\n", logInfo.isInterrupted, + logInfo.waitOptiTblTaskRunningLoopRound, logInfo.waitOptiTblTaskRunningTimeCost); + + if (!logInfo.findOptiTblTaskExecuting) { + logMsg += msgPrefix; + logMsg += String.format("newSubmittedOtpiTblStmt: %s\n", logInfo.newSubmittedOptiTblSql); + } else { + logMsg += msgPrefix; + logMsg += String.format("optiTblStmtJobId: %s\n", logInfo.optiTblDdlStmtJobId); + logMsg += msgPrefix; + logMsg += String.format("optiTblStmt: %s\n", logInfo.optiTblDdlStmt); + logMsg += msgPrefix; + logMsg += String.format("optiTblFromTtlJob: %s\n", logInfo.optiTblDdlComeFromTtlJob); + logMsg += msgPrefix; + logMsg += String.format("optiTblStmtJobStateBeforeCtrl: %s\n", logInfo.optiTblDdlJobStateBeforeCtrl); + } + + if (logInfo.needWaitAndMonitorOptiTblJob) { + + logMsg += msgPrefix; + logMsg += String.format("noFoundOptiTblJobRec: %s\n", logInfo.noFoundOptiTblJobRec); + logMsg += msgPrefix; + logMsg += String.format("continueOptiTblSql: %s\n", logInfo.continueOptiTblSql); + logMsg += msgPrefix; + logMsg += String.format("waitFromPauseToRunningRound: %s\n", logInfo.waitFromPauseToRunningRound); + logMsg += msgPrefix; + logMsg += + String.format("waitFromPauseToRunningTimeCost(ns): %s\n", logInfo.waitFromPauseToRunningTimeCost); + logMsg += msgPrefix; + logMsg += String.format("failedToRecoverDdlJob: %s\n", logInfo.failedToRecoverDdlJob); + + logMsg += msgPrefix; + logMsg += String.format("pauseOptiTblSql: %s\n", logInfo.pauseOptiTblSql); + logMsg += msgPrefix; + logMsg += + String.format("waitFromRunningToPauseTimeCost(ns): %s\n", logInfo.waitFromRunningToPauseTimeCost); + + } + + logMsg += msgPrefix; + logMsg += String.format("notifyOptiTblJobFinished: %s\n", logInfo.isFinished); + + if (logInfo.isFinished) { + logMsg += msgPrefix; + long taskTimeCostNano = logInfo.taskEndTs - logInfo.taskBeginTs; + logMsg += String.format("taskTimeCost(ns): %s\n", taskTimeCostNano); + if (logInfo.needWaitAndMonitorOptiTblJob) { + jobStatInfo.getOptimizeSqlCount().incrementAndGet(); + jobStatInfo.getOptimizeSqlTimeCost().addAndGet(taskTimeCostNano / 1000000); // unit: ms + } + jobStatInfo.setCurrJobEndTs(System.currentTimeMillis()); + globalStatInfo.getTotalTtlSuccessJobCount().incrementAndGet(); + } else { + logMsg += msgPrefix; + logMsg += String.format("taskTimeCost(ns): %s\n", System.nanoTime() - logInfo.taskBeginTs); + } + + TtlLoggerUtil.logTaskMsg(this, this.jobContext, logMsg); + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CheckAndPrepareAddPartsForCciSqlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CheckAndPrepareAddPartsForCciSqlTask.java new file mode 100644 index 000000000..0cfab2bec --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CheckAndPrepareAddPartsForCciSqlTask.java @@ -0,0 +1,445 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.ddl.newengine.DdlConstants; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler.TtlScheduledJobStatManager; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; +import com.alibaba.polardbx.optimizer.partition.pruning.PhysicalPartitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlTimeUnit; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.apachecommons.CommonsLog; +import org.apache.commons.lang.StringUtils; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + +/** + * @author chenghui.lch + */ +@CommonsLog +@TaskName(name = "CheckAndPrepareAddPartsForCciSqlTask") +@Getter +@Setter +public class CheckAndPrepareAddPartsForCciSqlTask extends AbstractTtlJobTask { + + @JSONCreator + public CheckAndPrepareAddPartsForCciSqlTask(String schemaName, String logicalTableName) { + super(schemaName, logicalTableName); + onExceptionTryRecoveryThenPause(); + } + + @Override + protected void beforeTransaction(ExecutionContext executionContext) { + super.beforeTransaction(executionContext); + fetchTtlJobContextFromPreviousTask(); + executeInner(executionContext); + } + + protected void executeInner(ExecutionContext executionContext) { + + boolean needPerformArchiving = this.jobContext.getTtlInfo().needPerformExpiredDataArchivingByCci(); + if (!needPerformArchiving) { + return; + } + + AddPartsForCciTaskLogInfo logInfo = new AddPartsForCciTaskLogInfo(); + logInfo.ttlTblSchema = schemaName; + logInfo.ttlTblName = logicalTableName; + logInfo.jobStatInfo = TtlScheduledJobStatManager.getInstance().getTtlJobStatInfo(schemaName, logicalTableName); + logInfo.globalStatInfo = TtlScheduledJobStatManager.getInstance().getGlobalTtlJobStatInfo(); + + String cleanUpLowerBound = this.jobContext.getCleanUpLowerBound(); + String cleanUpUpperBound = this.jobContext.getCleanUpUpperBound(); + + TtlDefinitionInfo ttlDefinitionInfo = this.jobContext.getTtlInfo(); + String ttlTimeZone = ttlDefinitionInfo.getTtlInfoRecord().getTtlTimezone(); + + int prePartCnt = ttlDefinitionInfo.getTtlInfoRecord().getArcPrePartCnt(); + int postPartCnt = ttlDefinitionInfo.getTtlInfoRecord().getArcPostPartCnt(); + + TableMeta cciMeta = getArchiveCciTableMeta(this.schemaName, this.logicalTableName, executionContext); + TableMeta arcCciTableMeta = cciMeta; + + Integer arcPartMode = ttlDefinitionInfo.getTtlInfoRecord().getArcPartMode(); + Integer arcPartInterval = ttlDefinitionInfo.getTtlInfoRecord().getArcPartInterval(); + TtlTimeUnit arcPartUnit = TtlTimeUnit.of(ttlDefinitionInfo.getTtlInfoRecord().getArcPartUnit()); + TtlTimeUnit ttlTimeUnit = TtlTimeUnit.of(this.jobContext.getTtlInfo().getTtlInfoRecord().getTtlUnit()); + Integer ttlInterval = this.jobContext.getTtlInfo().getTtlInfoRecord().getTtlInterval(); + + logInfo.arcTmpTblSchema = this.jobContext.getTtlInfo().getTmpTableSchema(); + logInfo.arcTmpTblName = this.jobContext.getTtlInfo().getTmpTableName(); + logInfo.arcCciFullTblName = cciMeta.getTableName(); + + logInfo.ttlTimeUnit = ttlTimeUnit.getTimeUnitName(); + logInfo.ttlInterval = Long.valueOf(ttlInterval); + logInfo.arcPartTimeUnit = arcPartUnit.getTimeUnitName(); + logInfo.arcPartInterval = Long.valueOf(arcPartInterval); + + String currentDataTime = this.jobContext.getCurrentDateTime(); + logInfo.currentDateTime = currentDataTime; + String formatedCurrentDatetime = this.jobContext.getFormatedCurrentDateTime(); + logInfo.formatedCurrentDateTime = formatedCurrentDatetime; + + /** + * Gen the range bound list by cleanUpLowerBound 、cleanUpUpperBound adn prePartCnt + */ + List outputPartBoundList = new ArrayList<>(); + List outputPartPartList = new ArrayList<>(); + + int finalPreBuildPartCnt = + TtlJobUtil.decidePreBuiltPartCnt(prePartCnt, ttlInterval, ttlTimeUnit, arcPartInterval, arcPartUnit); + logInfo.preAllocateCount = Long.valueOf(finalPreBuildPartCnt); + + TtlJobUtil.genRangeBoundListByInterval(cleanUpLowerBound, + formatedCurrentDatetime, finalPreBuildPartCnt, postPartCnt, ttlTimeZone, arcPartMode, arcPartInterval, + arcPartUnit, + outputPartBoundList, + outputPartPartList); + + /** + * Check and find the-missing-parts-on-ttl-tmp range bounds + */ + List boundListOfMissingPartOnTtlTmp = new ArrayList<>(); + List partNameListOfMissingPartOnTtlTmp = new ArrayList<>(); + String[] maxValPartNameArr = new String[1]; + maxValPartNameArr[0] = null; + findAndExtraMissingPartitionList(executionContext, + outputPartBoundList, + outputPartPartList, + arcCciTableMeta, + ttlTimeZone, + boundListOfMissingPartOnTtlTmp/*Output*/, + partNameListOfMissingPartOnTtlTmp/*Output*/, + maxValPartNameArr/*Output*/); + + if (!boundListOfMissingPartOnTtlTmp.isEmpty()) { + + List allPartBndValsToBeAdded = new ArrayList<>(); + List allPartNamesToBeAdded = new ArrayList<>(); + + /** + * Put the last bound value into the list of allPartBndValsToBeAdded + */ + allPartBndValsToBeAdded.addAll(boundListOfMissingPartOnTtlTmp); + allPartNamesToBeAdded.addAll(partNameListOfMissingPartOnTtlTmp); + + /** + * Build add part sql + */ + String queryHintForAlterTableAddParts = TtlConfigUtil.getQueryHintForAutoAddParts(); + String addPartSqlTemp = + TtlTaskSqlBuilder.buildAddPartitionsSqlTemplate(ttlDefinitionInfo, allPartBndValsToBeAdded, + allPartNamesToBeAdded, maxValPartNameArr[0], queryHintForAlterTableAddParts, executionContext); + String ttlTblSchema = ttlDefinitionInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlDefinitionInfo.getTtlInfoRecord().getTableName(); + String ttlTmpTblSchema = ttlDefinitionInfo.getTmpTableSchema(); + String ttlTmpTblName = ttlDefinitionInfo.getTmpTableName(); + + String addPartsSqlForTtlTmpTbl = + TtlTaskSqlBuilder.buildAddPartitionsByTemplateAndTableName(ttlTblSchema, ttlTblName, ttlTmpTblName, + addPartSqlTemp); + this.jobContext.setNeedAddPartsForArcTmpTbl(true); + this.jobContext.setArcTmpTblAddPartsSql(addPartsSqlForTtlTmpTbl); + this.jobContext.setArcTblAddPartsSql(""); + logInfo.addNewPartsSql = addPartsSqlForTtlTmpTbl; + + } else { + this.jobContext.setNeedAddPartsForArcTmpTbl(false); + } + dynamicNotifyAddPartsSubJobTaskToExecIfNeed(executionContext, logInfo); + logTaskExecResult(logInfo); + } + + private void findAndExtraMissingPartitionList( + ExecutionContext executionContext, + List outputPartBoundList, + List outputPartPartList, + TableMeta arcCciTableMeta, + String ttlTimeZone, + List boundListOfMissingPartOnTtlTmp, + List partNameListOfMissingPartOnTtlTmp, + String[] maxValPartNameArr) { + int outputPartCnt = outputPartBoundList.size(); + + /** + * before checking, should exclude the last bound from the list of outputPartBoundList, + * because the last bound value is upper bound with less than + */ + PartitionInfo arcTmpTblPartInfo = arcCciTableMeta.getPartitionInfo(); + PartitionByDefinition partByOfArcTmpTbl = arcTmpTblPartInfo.getPartitionBy(); + String maxValPartNameVal = null; + for (int i = 0; i < partByOfArcTmpTbl.getPartitions().size(); i++) { + PartitionSpec p = partByOfArcTmpTbl.getPartitions().get(i); + if (p.getBoundSpec().containMaxValues()) { + maxValPartNameVal = p.getName(); + break; + } + } + maxValPartNameArr[0] = maxValPartNameVal; + for (int i = 0; i < outputPartCnt; i++) { + String boundStr = outputPartBoundList.get(i); + String partNameStr = outputPartPartList.get(i); + + String boundStrToCheckIfPartExists = boundStr; + if (i > 0) { + boundStrToCheckIfPartExists = outputPartBoundList.get(i - 1); + } + + /** + * Find the target partName by routing the boundValStr + */ + String targetPartName = + routeFirstPartPartByTtlColValue(executionContext, arcCciTableMeta, ttlTimeZone, + boundStrToCheckIfPartExists); + if (StringUtils.isEmpty(targetPartName)) { + + /** + * Maybe the missing-partition-routing boundStr is the bound value of the last partName which + * has existed in partInfo, + * so here need exclude the last partName + */ + boolean partNameExists = arcTmpTblPartInfo.getPartSpecSearcher().checkIfDuplicated(partNameStr); + if (partNameExists) { + continue; + } + + boundListOfMissingPartOnTtlTmp.add(boundStr); + partNameListOfMissingPartOnTtlTmp.add(partNameStr); + } + } + } + + protected void dynamicNotifyAddPartsSubJobTaskToExecIfNeed(ExecutionContext executionContext, + AddPartsForCciTaskLogInfo logInfo) { + + try (Connection metaDbConnection = MetaDbDataSource.getInstance().getConnection()) { + boolean needAddPart = false; + if (this.jobContext.getNeedAddPartsForArcTmpTbl()) { + needAddPart = true; + } + dynamicNotifyAddPartsSubJobTaskToExecIfNeed(metaDbConnection, needAddPart, logInfo); + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.error(ex); + throw new TtlJobRuntimeException(ex); + } + } + + protected String routeFirstPartPartByTtlColValue(ExecutionContext ec, + TableMeta ttlTmpMeta, + String ttlTimeZone, + String ttlColVal) { + List phyParts = + TtlJobUtil.routeTargetPartsOfTtlTmpTblByTtlColVal(ec, ttlTmpMeta, ttlTimeZone, ttlColVal); + if (phyParts.isEmpty()) { + return null; + } + String partNameRs = phyParts.get(0).getPartName(); + PartitionInfo arcTmpTblPartInfo = ttlTmpMeta.getPartitionInfo(); + PartitionSpec partSpecRs = arcTmpTblPartInfo.getPartSpecSearcher().getPartSpecByPartName(partNameRs); + if (partSpecRs != null && partSpecRs.getBoundSpec().containMaxValues()) { + return null; + } + return partNameRs; + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + super.duringTransaction(metaDbConnection, executionContext); + + } + + @Override + protected void beforeRollbackTransaction(ExecutionContext executionContext) { + super.beforeRollbackTransaction(executionContext); + } + + @Override + protected void duringRollbackTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + super.duringRollbackTransaction(metaDbConnection, executionContext); + } + + protected void fetchTtlJobContextFromPreviousTask() { + TtlJobContext jobContext = TtlJobUtil.fetchTtlJobContextFromPreviousTaskByTaskName( + getJobId(), + PrepareCleanupIntervalTask.class, + getSchemaName(), + this.logicalTableName + ); + this.jobContext = jobContext; + } + + protected void dynamicNotifyAddPartsSubJobTaskToExecIfNeed(Connection metaDbConn, + boolean needAddParts, + AddPartsForCciTaskLogInfo logInfo) { + String oldDdlStmt = ""; + Long newSubJobId = 0L; + String newDdlStmt = ""; + String newRollbackStmt = ""; + + oldDdlStmt = TtlTaskSqlBuilder.buildSubJobTaskNameForAddPartsFroActTmpCciBySpecifySubjobStmt(); + if (needAddParts) { + newDdlStmt = this.jobContext.getArcTmpTblAddPartsSql(); + } else { + newSubJobId = DdlConstants.TRANSIENT_SUB_JOB_ID; + } + + boolean findOptiTblDdlRunning = true; + if (needAddParts) { + /** + * Check if ttl-table running optimize table + */ + String ttlTblSchema = this.jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + String ttlTblName = this.jobContext.getTtlInfo().getTtlInfoRecord().getTableName(); + Long[] ddlStmtJobIdOutput = new Long[1]; + String[] ddlStmtOutput = new String[1]; + Boolean[] ddlStmtFromTtlJob = new Boolean[1]; + try { + findOptiTblDdlRunning = + CheckAndPerformingOptiTtlTableTask.checkIfOptiTblDdlExecuting(metaDbConn, ddlStmtJobIdOutput, + ddlStmtOutput, ddlStmtFromTtlJob, ttlTblSchema, ttlTblName); + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + } + if (findOptiTblDdlRunning) { + /** + * If find the ttl-table is running optimize-table job, + * then ignore the add parts for ttl-table + * + */ + newDdlStmt = ""; + newSubJobId = DdlConstants.TRANSIENT_SUB_JOB_ID; + TtlLoggerUtil.TTL_TASK_LOGGER.warn(String.format( + "found optimize-table job running on ttlTable[%s.%s], so currJob [%s] ignore adding parts for cci", + schemaName, ttlTblSchema, ttlTblName, jobId)); + } + } + + logInfo.needAddNewParts = needAddParts; + logInfo.foundOptiTblDdlRunning = findOptiTblDdlRunning; + logInfo.addNewPartsSql = newDdlStmt; + + /** + * Update jobid and ddl-stmt for the subjob + */ + TtlJobUtil.updateSubJobTaskIdAndStmtByJobIdAndOldStmt(this.jobId, this.schemaName, this.logicalTableName, + oldDdlStmt, + newSubJobId, newDdlStmt, + newRollbackStmt, metaDbConn); + + } + + protected TableMeta getArchiveCciTableMeta(String ttlTblSchema, String ttlTblName, + ExecutionContext executionContext) { + TableMeta ttlTblMeta = executionContext.getSchemaManager(ttlTblSchema).getTable(ttlTblName); + String tblNameOfArcCci = TtlJobUtil.getActualTableNameForArcCci(ttlTblMeta, executionContext); + String arcTblSchema = ttlTblMeta.getTtlDefinitionInfo().getArchiveTableSchema(); + TableMeta cciTblMeta = executionContext.getSchemaManager(arcTblSchema).getTable(tblNameOfArcCci); + return cciTblMeta; + } + + @Override + public TtlJobContext getJobContext() { + return this.jobContext; + } + + @Override + public void setJobContext(TtlJobContext jobContext) { + this.jobContext = jobContext; + } + + protected static class AddPartsForCciTaskLogInfo { + + public AddPartsForCciTaskLogInfo() { + } + + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo; + TtlScheduledJobStatManager.GlobalTtlJobStatInfo globalStatInfo; + + protected Long jobId = 0L; + protected Long taskId = 0L; + protected String ttlTblSchema = ""; + protected String ttlTblName = ""; + protected String arcTmpTblSchema = ""; + protected String arcTmpTblName = ""; + protected String arcCciFullTblName = ""; + + protected String ttlTimeUnit = ""; + protected Long ttlInterval = 0L; + protected String arcPartTimeUnit = ""; + protected Long arcPartInterval = 0L; + protected Long preAllocateCount = 0L; + + protected String currentDateTime = ""; + protected String formatedCurrentDateTime = ""; + protected String currMaxBoundVal = ""; + protected String currMaxBoundPartName = ""; + protected String addNewPartsSql = ""; + + protected boolean needAddNewParts = false; + protected boolean foundOptiTblDdlRunning = false; + protected boolean ignoreAddPartsCurrRound = false; + + } + + protected void logTaskExecResult(CheckAndPrepareAddPartsForCciSqlTask.AddPartsForCciTaskLogInfo logInfo) { + + try { + + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = logInfo.jobStatInfo; + TtlScheduledJobStatManager.GlobalTtlJobStatInfo globalStatInfo = logInfo.globalStatInfo; + + String logMsg = ""; + String msgPrefix = TtlLoggerUtil.buildTaskLogRowMsgPrefix(jobId, taskId, "AddNewPartsForArcTable"); + logMsg += String.format("ttlTblSchema: %s, ttlTblName: %s\n", logInfo.ttlTblSchema, logInfo.ttlTblName); + logMsg += String.format("arcTmpTblSchema: %s, arcTmpTblName: %s\n", logInfo.arcTmpTblSchema, + logInfo.arcTmpTblName); + logMsg += String.format("cciFullTable: %s\n", logInfo.arcCciFullTblName); + + logMsg += msgPrefix; + logMsg += String.format("ttlInterval: %s, ttlTimeUnit: %s\n", logInfo.ttlInterval, logInfo.ttlTimeUnit); + + logMsg += msgPrefix; + logMsg += String.format("arcPartInterval: %s, arcPartTimeUnit: %s\n", logInfo.arcPartInterval, + logInfo.arcPartTimeUnit); + + logMsg += msgPrefix; + logMsg += String.format("preAllocateCount: %s\n", logInfo.preAllocateCount); + + logMsg += msgPrefix; + logMsg += String.format("currentDateTime: %s\n", logInfo.currentDateTime); + logMsg += msgPrefix; + logMsg += String.format("formatedCurrentDateTime: %s\n", logInfo.formatedCurrentDateTime); + logMsg += msgPrefix; + logMsg += String.format("currMaxBoundVal: %s\n", logInfo.currMaxBoundVal); + logMsg += msgPrefix; + logMsg += String.format("addNewPartsSql: %s\n", logInfo.addNewPartsSql); + + logMsg += msgPrefix; + logMsg += String.format("needAddParts: %s\n", logInfo.needAddNewParts); + logMsg += msgPrefix; + logMsg += String.format("foundOptiTblDdlRunning: %s\n", logInfo.foundOptiTblDdlRunning); + logMsg += msgPrefix; + logMsg += String.format("ignoreAddPartsCurrRound: %s\n", logInfo.ignoreAddPartsCurrRound); + + if (logInfo.needAddNewParts && !logInfo.ignoreAddPartsCurrRound) { + jobStatInfo.getAddPartSqlCount().addAndGet(1); + globalStatInfo.getTotalAddPartSqlCount().addAndGet(1); + } + + TtlLoggerUtil.logTaskMsg(this, this.jobContext, logMsg); + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CheckAndPrepareColumnarIndexPartDefTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CheckAndPrepareColumnarIndexPartDefTask.java new file mode 100644 index 000000000..556c70a83 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CheckAndPrepareColumnarIndexPartDefTask.java @@ -0,0 +1,167 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlTimeUnit; +import lombok.Getter; +import lombok.Setter; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + +/** + * @author chenghui.lch + */ +@TaskName(name = "CheckAndPrepareColumnarIndexPartDefTask") +@Getter +@Setter +public class CheckAndPrepareColumnarIndexPartDefTask extends AbstractTtlJobTask { + + protected String arcTblSchema; + protected String arcTblName; + + @JSONCreator + public CheckAndPrepareColumnarIndexPartDefTask(String schemaName, String logicalTableName, + String arcTblSchema, String arcTblName) { + super(schemaName, logicalTableName); + this.arcTblSchema = arcTblSchema; + this.arcTblName = arcTblName; + onExceptionTryRecoveryThenPause(); + + } + + @Override + protected void beforeTransaction(ExecutionContext executionContext) { + super.beforeTransaction(executionContext); + fetchTtlJobContextFromPreviousTask(); + executeInner(executionContext); + } + + protected void executeInner(ExecutionContext executionContext) { + + String cleanUpLowerBound = this.jobContext.getCleanUpLowerBound(); + String cleanUpUpperBound = this.jobContext.getCleanUpUpperBound(); + String formatedCurrentTime = this.jobContext.getFormatedCurrentDateTime(); + + TtlDefinitionInfo ttlDefinitionInfo = this.jobContext.getTtlInfo(); + String ttlTimeZone = ttlDefinitionInfo.getTtlInfoRecord().getTtlTimezone(); + + int preBuiltPartCntForFuture = this.jobContext.getTtlInfo().getTtlInfoRecord().getArcPrePartCnt(); + int postBuiltPartCntForPast = this.jobContext.getTtlInfo().getTtlInfoRecord().getArcPostPartCnt(); + + /** + * Gen the range bound list by cleanUpLowerBound 、cleanUpUpperBound adn prePartCnt + */ + List outputPartBoundList = new ArrayList<>(); + List outputPartPartList = new ArrayList<>(); + + Integer ttlInterval = ttlDefinitionInfo.getTtlInfoRecord().getTtlInterval(); + TtlTimeUnit ttlUnitVal = TtlTimeUnit.of(ttlDefinitionInfo.getTtlInfoRecord().getTtlUnit()); + + Integer arcPartMode = ttlDefinitionInfo.getTtlInfoRecord().getArcPartMode(); + Integer arcPartInterval = ttlDefinitionInfo.getTtlInfoRecord().getArcPartInterval(); + TtlTimeUnit arcPartUnit = TtlTimeUnit.of(ttlDefinitionInfo.getTtlInfoRecord().getArcPartUnit()); + + int finalPreBuildPartCnt = + TtlJobUtil.decidePreBuiltPartCnt(preBuiltPartCntForFuture, ttlInterval, ttlUnitVal, arcPartInterval, + arcPartUnit); + + TtlJobUtil.genRangeBoundListByInterval( + cleanUpLowerBound, + formatedCurrentTime, + finalPreBuildPartCnt, + postBuiltPartCntForPast, + ttlTimeZone, + arcPartMode, + arcPartInterval, + arcPartUnit, + outputPartBoundList, + outputPartPartList); + + List allPartBndValsToBeAdded = new ArrayList<>(); + List allPartNamesToBeAdded = new ArrayList<>(); + + /** + * Put the last bound value into the list of allPartBndValsToBeAdded + */ + allPartBndValsToBeAdded.addAll(outputPartBoundList); + allPartNamesToBeAdded.addAll(outputPartPartList); + +// boolean needAutoAddMaxValPart = TtlConfigUtil.isAutoAddMaxValuePartForCci(); + Boolean needAutoAddMaxValPart = executionContext.getParamManager().getBoolean(ConnectionParams.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING); + if (needAutoAddMaxValPart == null) { + needAutoAddMaxValPart = TtlConfigUtil.isAutoAddMaxValuePartForCci(); + } + if (needAutoAddMaxValPart) { + allPartBndValsToBeAdded.add(TtlTaskSqlBuilder.ARC_TBL_MAXVALUE_BOUND); + allPartNamesToBeAdded.add(TtlTaskSqlBuilder.ARC_TBL_MAXVAL_PART_NAME); + } + + /** + * Build completed partByDef of columnar ci + */ + String createCiSqlForArcTbl = + TtlTaskSqlBuilder.buildCreateColumnarIndexSqlForArcTbl(ttlDefinitionInfo, arcTblSchema, arcTblName, + allPartBndValsToBeAdded, + allPartNamesToBeAdded, executionContext); + this.jobContext.setCreateColumnarIndexSqlForArcTbl(createCiSqlForArcTbl); + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + super.duringTransaction(metaDbConnection, executionContext); + dynamicModifyCreateColumnarIndexSubJobTaskStmt(metaDbConnection); + } + + @Override + protected void beforeRollbackTransaction(ExecutionContext executionContext) { + super.beforeRollbackTransaction(executionContext); + } + + @Override + protected void duringRollbackTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + super.duringRollbackTransaction(metaDbConnection, executionContext); + } + + protected void fetchTtlJobContextFromPreviousTask() { + TtlJobContext jobContext = TtlJobUtil.fetchTtlJobContextFromPreviousTaskByTaskName( + getJobId(), + PrepareCleanupIntervalTask.class, + getSchemaName(), + this.logicalTableName + ); + this.jobContext = jobContext; + } + + protected void dynamicModifyCreateColumnarIndexSubJobTaskStmt(Connection metaDbConn) { + String oldDdlStmt = ""; + Long newSubJobId = 0L; + String newDdlStmt = ""; + String newRollbackStmt = ""; + + oldDdlStmt = TtlTaskSqlBuilder.buildSubJobTaskNameForCreateColumnarIndexBySpecifySubjobStmt(); + newDdlStmt = this.jobContext.getCreateColumnarIndexSqlForArcTbl(); + + /** + * Update jobid and ddl-stmt for the subjob + */ + TtlJobUtil.updateSubJobTaskIdAndStmtByJobIdAndOldStmt(this.jobId, this.schemaName, this.logicalTableName, + oldDdlStmt, + newSubJobId, newDdlStmt, newRollbackStmt, metaDbConn); + } + + @Override + public TtlJobContext getJobContext() { + return this.jobContext; + } + + @Override + public void setJobContext(TtlJobContext jobContext) { + this.jobContext = jobContext; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CleanAndPrepareExpiredDataTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CleanAndPrepareExpiredDataTask.java new file mode 100644 index 000000000..bba7f9169 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/CleanAndPrepareExpiredDataTask.java @@ -0,0 +1,951 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.ddl.newengine.DdlTaskState; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.logger.MDC; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobInterruptedException; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler.TtlScheduledJobStatManager; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlEngineAccessorDelegate; +import com.alibaba.polardbx.executor.ddl.newengine.utils.TaskHelper; +import com.alibaba.polardbx.executor.scheduler.executor.trx.CleanLogTableTask; +import com.alibaba.polardbx.executor.utils.PartitionMetaUtil; +import com.alibaba.polardbx.gms.metadb.misc.DdlEngineTaskRecord; +import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import lombok.Data; +import lombok.Getter; +import org.apache.commons.lang.StringUtils; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import static com.alibaba.polardbx.gms.topology.SystemDbHelper.DEFAULT_DB_NAME; + +/** + * @author chenghui.lch + */ +@Getter +@TaskName(name = "CleanAndPrepareExpiredDataTask") +public class CleanAndPrepareExpiredDataTask extends AbstractTtlJobTask { + + /** + *
+     * The job of ClearAndPrepareExpiredDataTask are the following:
+     * for need archiving:
+     *      delete from ttl_tbl only
+     * for need NOT archiving:
+     *      insert ttl_tmp select * from ttl_tbl
+     *      delete from ttl_tbl;
+     * 
+ */ + + /** + * The set of the phy part that has been finish expired data cleaning + *
+     *      for auto-db part table:
+     *          each item is the global partNum of a partition tbl
+     *      for drds-db part table:
+     *          each item is a global partNum of sharding tbl that is computed by posi of phydb nd posi phytb
+     * 
+ */ + protected volatile Set cleanedPhyPartSet = new HashSet<>(); + + public CleanAndPrepareExpiredDataTask(String schemaName, + String logicalTableName) { + super(schemaName, logicalTableName); + onExceptionTryRecoveryThenPause(); + } + + protected void initCleanedPartMarkSet(ExecutionContext ec) { + + /** + * Try to check if cleanedPartBitSetStr has been init + */ + if (this.cleanedPhyPartSet == null || this.cleanedPhyPartSet.isEmpty()) { + storeCleanedPhyPartSetToTaskRecord(this); + } + } + + public void executeImpl(ExecutionContext executionContext) { + + initCleanedPartMarkSet(executionContext); + TtlJobUtil.updateJobStage(this.jobContext, "DeletingExpiredData"); + CleanupExpiredDataLogInfo logInfo = new CleanupExpiredDataLogInfo(); + logInfo.taskBeginTs = System.currentTimeMillis(); + logInfo.taskBeginTsNano = System.nanoTime(); + logInfo.needPerformArchiving = this.jobContext.getTtlInfo().needPerformExpiredDataArchivingByOssTbl(); + logInfo.arcTmpTblSchema = this.jobContext.getTtlInfo().getTmpTableSchema(); + logInfo.arcTmpTblName = this.jobContext.getTtlInfo().getTmpTableName(); + logInfo.jobId = getJobId(); + logInfo.taskId = getTaskId(); + logInfo.ttlColMinValStr = this.jobContext.getTtlColMinValue(); + logInfo.firstLevelPartNameOfTtlColMinVal = this.jobContext.getPartNameForTtlColMinVal(); + logInfo.cleanupLowerBound = this.jobContext.getCleanUpLowerBound(); + logInfo.firstLevelPartNameOfCleanupLowerBound = this.jobContext.getPartNameForCleanupLowerBound(); + logInfo.previousPartBoundOfTtlColMinVal = this.jobContext.getPreviousPartBoundOfTtlColMinVal(); + + TtlScheduledJobStatManager.TtlJobStatInfo statInfo = + TtlScheduledJobStatManager.getInstance().getTtlJobStatInfo(this.schemaName, this.logicalTableName); + if (statInfo != null) { + logInfo.ttlJobStatInfo = statInfo; + } + + DataCleanupTaskSubmitter dataCleanupTaskSubmitter = + new DataCleanupTaskSubmitter(this, executionContext, jobContext, logInfo); + DataArchivingWorkerTaskMonitor monitor = new DataArchivingWorkerTaskMonitor(this, + executionContext, jobContext, logInfo); + TtlIntraTaskManager taskDelegate = + new TtlIntraTaskManager(this, executionContext, jobContext, dataCleanupTaskSubmitter, monitor); + taskDelegate.submitAndRunIntraTasks(); + } + + public Set getCleanedPhyPartSet() { + return cleanedPhyPartSet; + } + + public void setCleanedPhyPartSet(Set cleanedPhyPartSet) { + this.cleanedPhyPartSet = cleanedPhyPartSet; + } + + protected static class DataCleanupTaskSubmitter implements TtlWorkerTaskSubmitter { + protected DdlTask parentDdlTask; + protected ExecutionContext ec; + protected TtlJobContext ttlJobContext; + protected CleanupExpiredDataLogInfo logInfo; + + public DataCleanupTaskSubmitter(DdlTask parentDdlTask, ExecutionContext ec, + TtlJobContext ttlJobContext, + CleanupExpiredDataLogInfo logInfo) { + this.parentDdlTask = parentDdlTask; + this.ec = ec; + this.ttlJobContext = ttlJobContext; + this.logInfo = logInfo; + } + + @Override + public List> submitWorkerTasks() { + List> result = submitWorkerTasksForDataCleaningAndArchiving(); + TtlJobUtil.getTtlJobStatInfoByJobContext(this.ttlJobContext).getTotalPhyPartCnt().set(result.size()); + return result; + } + + /** + * Submit the insertSelect tasks for all dn of one logical table + */ + protected List> submitWorkerTasksForDataCleaningAndArchiving() { + + /** + *
+             *     foreach part(zigzag concurrent by dn, use delete_thd_pool)
+             *         exec insert select for one part by one trans
+             *         update status for the one part
+             * 
+ */ + + /** + * 1. build phy-part data archiving tasks of one logical tbl; + * 2. submit phy-part data archiving tasks by using zigzag policy to balance dn workloads; + * 3. return the submitted tasks futures + */ + List fullTaskRunners = buildPhyPartDataArchivingTasksForOneLogicalTbl(); + List taskRunners = filerTaskRunnersForFinishedPhyPart(fullTaskRunners); + List zigzagOrderTaskRunners = TtlJobUtil.zigzagSortTasks(taskRunners); + List> taskRunnerFutureInfos = + submitAndExecTaskRunners(zigzagOrderTaskRunners); + return taskRunnerFutureInfos; + } + + protected List buildPhyPartDataArchivingTasksForOneLogicalTbl() { + + TtlDefinitionInfo ttlInfo = ttlJobContext.getTtlInfo(); + + String tblSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String tblName = ttlInfo.getTtlInfoRecord().getTableName(); + TableMeta tblMeta = ec.getSchemaManager(tblSchema).getTable(tblName); + PartitionInfo partInfo = tblMeta.getPartitionInfo(); + + PhyPartSpecIterator phyPartItor = new PhyPartSpecIterator(partInfo); + List taskList = new ArrayList<>(); + while (phyPartItor.hasNext()) { + PartitionMetaUtil.PartitionMetaRecord partMeta = phyPartItor.next(); + DataCleaningUpIntraTask dataArcTask = + new DataCleaningUpIntraTask(parentDdlTask, ec, ttlJobContext, partMeta, logInfo); + taskList.add(dataArcTask); + } + return taskList; + } + + protected List filerTaskRunnersForFinishedPhyPart( + List fullTaskRunners) { + CleanAndPrepareExpiredDataTask task = (CleanAndPrepareExpiredDataTask) parentDdlTask; + Set cleanedPhyPartSet = task.getCleanedPhyPartSet(); + if (cleanedPhyPartSet == null && cleanedPhyPartSet.isEmpty()) { + return fullTaskRunners; + } + List finalRunners = new ArrayList<>(); + for (int i = 0; i < fullTaskRunners.size(); i++) { + TtlIntraTaskRunner runner = fullTaskRunners.get(i); + DataCleaningUpIntraTask intraTask = (DataCleaningUpIntraTask) runner; + PartitionMetaUtil.PartitionMetaRecord partMeta = intraTask.getPhyPartData(); + if (cleanedPhyPartSet.contains(partMeta.getPartNum().intValue())) { + continue; + } + finalRunners.add(runner); + } + return finalRunners; + } + + protected List> submitAndExecTaskRunners( + List taskRunners) { + List> futureInfos = + TtlIntraTaskExecutor.getInstance().submitDeleteTaskRunners(taskRunners); + return futureInfos; + } + } + + /** + *
+     * Execute task for do the followings:
+     *
+     * (1). insert into ttl_tmp select * from ttl_tbl partition(part) by using target interval
+     * (2). delete from ttl_tbl partition(part) by using target interval
+     * 
+ */ + @Data + protected static class DataCleaningUpIntraTask extends TtlIntraTaskRunner { + + protected CleanAndPrepareExpiredDataTask parentDdlTask; + protected ExecutionContext ec; + protected TtlJobContext jobContext; + protected PartitionMetaUtil.PartitionMetaRecord phyPartData; + protected boolean needPerformArchiving = false; + protected volatile boolean stopTask = false; + protected volatile Object transConn; + protected IntraTaskStatInfo currIntraTaskStatInfo = new IntraTaskStatInfo(); + protected CleanupExpiredDataLogInfo logInfo; + + public DataCleaningUpIntraTask( + DdlTask parentDdlTask, + ExecutionContext ec, + TtlJobContext jobContext, + PartitionMetaUtil.PartitionMetaRecord phyPartData, + CleanupExpiredDataLogInfo logInfo + ) { + this.parentDdlTask = (CleanAndPrepareExpiredDataTask) parentDdlTask; + this.ec = ec; + this.jobContext = jobContext; + this.phyPartData = phyPartData; + /** + * Check if a ttl table need do perform oss archiving + */ + this.needPerformArchiving = jobContext.getTtlInfo().needPerformExpiredDataArchivingByOssTbl(); + this.logInfo = logInfo; + } + + @Override + public String getDnId() { + return phyPartData.getRwDnId(); + } + + @Override + public void notifyStopTask() { + this.stopTask = true; + } + + @Override + public void forceStopTask() { + this.stopTask = true; + if (transConn != null) { + IServerConfigManager serverMgr = TtlJobUtil.getServerConfigManager(); + try { + serverMgr.closeTransConnection(transConn); + } catch (Throwable ex) { + // ignore ex + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + } + } + } + + @Override + public void runTask() { + final Map savedMdcContext = MDC.getCopyOfContextMap(); + try { + String schemaName = jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema().toLowerCase(); + MDC.put(MDC.MDC_KEY_APP, schemaName); + runInner(); + } finally { + MDC.setContextMap(savedMdcContext); + } + } + + protected void runInner() { + long totalBeginTs = System.nanoTime(); + String logMsgHeader = TtlLoggerUtil.buildIntraTaskLogMsgHeaderWithPhyPart(this.parentDdlTask, phyPartData); + int batchCnt = this.jobContext.getDmlBatchSize(); + long rowLenAvg = this.jobContext.getRowLengthAvgOfTtlTbl(); + boolean finished = false; + final AtomicLong batchRound = new AtomicLong(0); + + TtlDefinitionInfo ttlInfo = this.jobContext.getTtlInfo(); + String ttlTimezoneStr = ttlInfo.getTtlInfoRecord().getTtlTimezone(); + String charsetEncoding = TtlConfigUtil.getDefaultCharsetEncodingOnTransConn(); + String sqlModeSetting = TtlConfigUtil.getDefaultSqlModeOnTransConn(); + String groupParallelismOfConnStr = String.valueOf(TtlConfigUtil.getDefaultGroupParallelismOnDmlConn()); + Map sessionVariables = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + sessionVariables.put("time_zone", ttlTimezoneStr); + sessionVariables.put("names", charsetEncoding); + sessionVariables.put("sql_mode", sqlModeSetting); + sessionVariables.put("group_parallelism", groupParallelismOfConnStr); + + boolean useArcTrxPolicy = this.jobContext.getUseArcTrans(); + if (useArcTrxPolicy) { + sessionVariables.put("transaction_policy", "archive"); + } + + while (true) { + + /** + * Check if task is interrupt + */ + if (checkTaskInterrupted()) { + doClearWorkForInterruptTask(); + break; + } + + final IServerConfigManager serverConfigManager = TtlJobUtil.getServerConfigManager(); + int dmlBatchSize = this.jobContext.getDmlBatchSize(); + + /** + * Try to acquire the rows speed permits of target dn if need + */ + boolean acquireSucc = tryAcquireRatePermits(dmlBatchSize); + if (!acquireSucc) { + /** + * Failed to acquire rows speed permits of limiter, so ignore and next round + */ + continue; + } + + /** + * Prepare the sql for converging and deleting the expired data, + */ + final String deleteSelectSql = buildDeleteSelectForExpiredDataArchiving(dmlBatchSize); + final AtomicInteger insertRows = new AtomicInteger(0); + final AtomicInteger deleteRows = new AtomicInteger(0); + final AtomicLong insertTcNano = new AtomicLong(0); + final AtomicLong deleteTcNano = new AtomicLong(0); + + /** + * Exec sql to delete and converge the expired data. + */ + final String ttlTblSchemaName = this.jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + TtlJobUtil.wrapWithDistributedTrx( + serverConfigManager, + ttlTblSchemaName, + sessionVariables, + (transConn) -> { + + /** + * Save the reference of transConn on IntraTask to use to do force closing + */ + batchRound.incrementAndGet(); + this.transConn = transConn; + + /** + *
+                         *     exec the sql:
+                         *         delete from ttl_tbl partition(part)
+                         *         where gmt_created <= up_bound
+                         *         limit batch_cnt;
+                         * 
+ */ + long deleteBeginTs = System.nanoTime(); + int deleteArows = TtlJobUtil.execLogicalDmlOnInnerConnection(serverConfigManager, + ttlTblSchemaName, transConn, ec, deleteSelectSql); + deleteRows.set(deleteArows); + long deleteEndTs = System.nanoTime(); + + /** + * Stat the phy sql of intra task + */ + deleteTcNano.set(deleteEndTs - deleteBeginTs); + this.currIntraTaskStatInfo.getTotalDeleteTimeCostNano().addAndGet(deleteTcNano.get()); + this.currIntraTaskStatInfo.getTotalDeleteRows().addAndGet(deleteArows); + this.currIntraTaskStatInfo.getTotalDeleteSqlCount().incrementAndGet(); + + return deleteArows; + } + ); + + if (deleteRows.get() < batchCnt) { + /** + * if deleteRows is less than batchCnt, that means + * current batch is the last batch. + */ + finished = true; + long totalEndTs = System.nanoTime(); + long taskTimeCost = totalEndTs - totalBeginTs; + this.currIntraTaskStatInfo.getTotalExecTimeCostNano().set(taskTimeCost); + logOneIntraTaskExecResult( + logMsgHeader, + this.jobContext.getCleanUpLowerBound(), + batchRound.intValue(), + rowLenAvg, + insertRows, + deleteRows, + insertTcNano, + deleteTcNano, + true, + currIntraTaskStatInfo); + break; + } else { + logOneIntraTaskExecResult( + logMsgHeader, + this.jobContext.getCleanUpLowerBound(), + batchRound.intValue(), + rowLenAvg, + insertRows, + deleteRows, + insertTcNano, + deleteTcNano, + false, + currIntraTaskStatInfo); + } + } + + if (finished) { + /** + * Mark the phypart finishing cleaning persistently + */ + updateCleanStatusForOnePartition(); + } else { + long totalEndTs = System.nanoTime(); + long taskTimeCost = totalEndTs - totalBeginTs; + this.currIntraTaskStatInfo.getTotalExecTimeCostNano().addAndGet(taskTimeCost); + } + } + + protected String buildInsertSelectForExpiredDataArchiving(int dmlBatchSize) { + + TtlDefinitionInfo ttlInfo = this.jobContext.getTtlInfo(); + + String phyPartName = this.phyPartData.getPartName(); + String minBoundToCleanup = this.jobContext.getCleanUpLowerBound(); + String partBoundOfPartOfTtlMinVal = this.jobContext.getPreviousPartBoundOfTtlColMinVal(); + boolean needAddIntervalLowerBound = !StringUtils.isEmpty(partBoundOfPartOfTtlMinVal); + String queryHintForInsert = TtlConfigUtil.getQueryHintForInsertExpiredData(); + String insertSelectSqlTemp = + TtlTaskSqlBuilder.buildInsertSelectTemplate(ttlInfo, needAddIntervalLowerBound, queryHintForInsert); + String insertSelectSql = ""; + if (needAddIntervalLowerBound) { + insertSelectSql = + String.format(insertSelectSqlTemp, phyPartName, minBoundToCleanup, partBoundOfPartOfTtlMinVal, + dmlBatchSize); + } else { + insertSelectSql = String.format(insertSelectSqlTemp, phyPartName, minBoundToCleanup, dmlBatchSize); + } + + return insertSelectSql; + } + + protected String buildDeleteSelectForExpiredDataArchiving(int dmlBatchSize) { + + TtlDefinitionInfo ttlInfo = this.jobContext.getTtlInfo(); + String previousPartBoundOfPartOfTtlMinVal = this.jobContext.getPreviousPartBoundOfTtlColMinVal(); + boolean needAddIntervalLowerBound = !StringUtils.isEmpty(previousPartBoundOfPartOfTtlMinVal); + String phyPartName = this.phyPartData.getPartName(); + String minBoundToCleanup = this.jobContext.getCleanUpLowerBound(); + String forceIndexExpr = this.jobContext.getTtlColForceIndexExpr(); + String queryHintForDelete = TtlConfigUtil.getQueryHintForDeleteExpiredData(); + String deleteSqlTemp = + TtlTaskSqlBuilder.buildDeleteTemplate(ttlInfo, needAddIntervalLowerBound, queryHintForDelete, + forceIndexExpr); + + String deleteSql = ""; + if (needAddIntervalLowerBound) { + deleteSql = + String.format(deleteSqlTemp, phyPartName, minBoundToCleanup, previousPartBoundOfPartOfTtlMinVal, + dmlBatchSize); + } else { + deleteSql = String.format(deleteSqlTemp, phyPartName, minBoundToCleanup, dmlBatchSize); + } + + if (StringUtils.isEmpty(logInfo.deleteSqlTemp)) { + logInfo.deleteSqlTemp = deleteSql; + } + + return deleteSql; + } + + protected boolean checkTaskInterrupted() { + if (Thread.currentThread().isInterrupted() || stopTask || ec.getDdlContext().isInterrupted()) { + return true; + } + return false; + } + + protected boolean tryAcquireRatePermits(int permitsVal) { + boolean enableRowsSpeedLimit = TtlConfigUtil.isEnableTtlCleanupRowsSpeedLimit(); + if (!enableRowsSpeedLimit) { + return true; + } + long waitPeriods = TtlConfigUtil.getMaxWaitAcquireRatePermitsPeriods(); + String rwDnId = this.phyPartData.getRwDnId(); + boolean acquireSucc = false; + try { + long waitPermitsBeginTs = System.nanoTime(); + acquireSucc = + TtlDataCleanupRateLimiter.getInstance() + .tryAcquire(rwDnId, permitsVal, waitPeriods, TimeUnit.MILLISECONDS); + long waitPermitsEndTs = System.nanoTime(); + this.logInfo.ttlJobStatInfo.getWaitPermitsTimeCostNano() + .addAndGet((waitPermitsEndTs - waitPermitsBeginTs)); + this.logInfo.ttlJobStatInfo.getAcquirePermitsCount().incrementAndGet(); + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.warn( + String.format("Failed to acquire rows speeds permits from dn[%s]", rwDnId), ex); + acquireSucc = false; + } + return acquireSucc; + } + + protected void doClearWorkForInterruptTask() { + /** + * Just do nothing + */ + String msg = String.format("ttl job has been interrupted, phypart is %s, table is %s.%s", + phyPartData.getPartName(), phyPartData.getTableSchema(), phyPartData.getTableName()); + + /** + * Throw a exception to notify ddl-engine this task is not finished and restart at next time + */ + throw new TtlJobInterruptedException(msg); + } + + protected void updateCleanStatusForOnePartition() { + + /** + * Update status to label the part has finished archive expired data + */ + markPartFinishExpiredDataCleaning(parentDdlTask, phyPartData); + } + + protected void logOneIntraTaskExecResult( + String logMsgHeader, + String minBoundToBeCleanUp, + int batchRound, + long rowLenAvg, + AtomicInteger insertRowsCurrRound, + AtomicInteger deleteRowsCurrRound, + AtomicLong insertTcNanoCurrRound, + AtomicLong deleteTcNanoCurrRound, + boolean isIntraTaskFinish, + IntraTaskStatInfo oneIntraTaskStatInfo) { + + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = this.logInfo.ttlJobStatInfo; + TtlScheduledJobStatManager.GlobalTtlJobStatInfo globalStatInfo = TtlScheduledJobStatManager.getInstance() + .getGlobalTtlJobStatInfo(); + + long currDeleteRoundTcMs = (deleteTcNanoCurrRound.get()) / (1000 * 1000); + long deleteRowsCurrRoundVal = deleteRowsCurrRound.get(); + long deleteDataLenCurrRoundVal = deleteRowsCurrRoundVal * rowLenAvg; + + globalStatInfo.getTotalDeleteSqlTimeCost().addAndGet(currDeleteRoundTcMs); + globalStatInfo.getTotalDeleteSqlCount().incrementAndGet(); + globalStatInfo.getTotalCleanupRows().addAndGet(deleteRowsCurrRoundVal); + globalStatInfo.getTotalCleanupDataLength().addAndGet(deleteDataLenCurrRoundVal); + + jobStatInfo.getDeleteSqlTimeCost().addAndGet(currDeleteRoundTcMs); + jobStatInfo.getDeleteSqlCount().incrementAndGet(); + jobStatInfo.getCleanupRows().addAndGet(deleteRowsCurrRoundVal); + jobStatInfo.getCleanupDataLength().addAndGet(deleteDataLenCurrRoundVal); + + if (isIntraTaskFinish) { + jobStatInfo.getCleanedPhyPartCnt().incrementAndGet(); + } + + jobStatInfo.calcDeleteSqlAvgRt(); + jobStatInfo.calcDeleteRowsSpeed();//ROWS/S + + /** + *
+             *     cb: cleanup lower bound
+             *     arc: is need perform archving data
+             *     r: the batch roundNum of handling a part tbl for current cleanup lower bound
+             *          e.g  for 1...roundNum
+             *                  delete * from ttl_tbl where ttl_col <= xxx order by ttl_col asc limit batch_size
+             *     tc: timecost of a intra task of DataArchivingIntraTask
+             *     drows: the rows num of deleting sql
+             *     dtAvg: the avg rt of deleting sql
+             *     irows: the rows num of inserting sql
+             *     itAvg: the avg rt of inserting sql
+             * 
+ */ + if (TtlConfigUtil.isEnableCleanupIntraTaskInfoLog()) { + long deleteRowsOfCurrIntraTask = oneIntraTaskStatInfo.getTotalDeleteRows().get(); + long deleteTcNanoOfCurrIntraTask = oneIntraTaskStatInfo.getTotalExecTimeCostNano().get(); + long deleteSqlCntOfCurrIntraTask = oneIntraTaskStatInfo.getTotalDeleteSqlCount().get(); + + long deleteRtMsOfCurrIntraTask = + deleteTcNanoOfCurrIntraTask / (deleteSqlCntOfCurrIntraTask * 1000 * 1000); + long deleteTcMsOfCurrIntraTask = deleteTcNanoOfCurrIntraTask / (1000 * 1000); + + String logMsg = + String.format("[%s] [cb=%s,arc=%s] [r=%d] [tc=%s, drows=%d, drtAvg=%d]", + logMsgHeader, minBoundToBeCleanUp, this.needPerformArchiving, batchRound, + deleteTcMsOfCurrIntraTask, deleteRowsOfCurrIntraTask, + deleteRtMsOfCurrIntraTask); + TtlLoggerUtil.TTL_TASK_LOGGER.info(logMsg); + } + } + } + + /** + * The task monitor for the DataArchivingIntraTask + */ + protected static class DataArchivingWorkerTaskMonitor implements TtlWorkerTaskMonitor { + + protected CleanAndPrepareExpiredDataTask parentDdlTask; + protected ExecutionContext ec; + protected TtlJobContext jobContext; + protected volatile boolean stopTask = false; + protected CleanupExpiredDataLogInfo logInfo; + + public DataArchivingWorkerTaskMonitor( + DdlTask parentDdlTask, + ExecutionContext ec, + TtlJobContext jobContext, + CleanupExpiredDataLogInfo logInfo + ) { + this.parentDdlTask = (CleanAndPrepareExpiredDataTask) parentDdlTask; + this.ec = ec; + this.jobContext = jobContext; + this.logInfo = logInfo; + } + + @Override + public void doMonitoring() { + + String dbName = jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + String tbName = jobContext.getTtlInfo().getTtlInfoRecord().getTableName(); + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = TtlScheduledJobStatManager.getInstance() + .getTtlJobStatInfo(dbName, tbName); + if (jobStatInfo == null) { + return; + } + + /** + * Do some logging + */ + logInfo.waitCleanupTaskRunningLoopRound++; + + logInfo.cleanupRows = jobStatInfo.getCleanupRows().get(); + logInfo.cleanupSpeed = jobStatInfo.calcCleanupSpeed(); + logInfo.cleanupRowsSpeed = jobStatInfo.calcCleanupRowsSpeed(); + logInfo.cleanupTimeCost = jobStatInfo.getCleanupTimeCost().get(); + + logInfo.deleteRows = jobStatInfo.getCleanupRows().get(); + logInfo.deleteSqlCnt = jobStatInfo.getDeleteSqlCount().get(); + logInfo.deleteTimeCost = jobStatInfo.getDeleteSqlTimeCost().get(); + logInfo.deleteAvgRt = jobStatInfo.calcDeleteSqlAvgRt(); + logInfo.deleteRowsSpeed = jobStatInfo.calcDeleteRowsSpeed(); + + logTaskExecResult(parentDdlTask, jobContext, logInfo); + } + + @Override + public boolean checkNeedStop() { + boolean needStop = false; + if (!this.jobContext.getTtlInfo().needPerformExpiredDataArchivingByOssTbl()) { + return needStop; + } +// long arcTmpTblDataLength = TtlJobUtil.fetchArcTmlTableDataLength(ec, this.jobContext, null); +// long arcTmpTblDataLengthLimit = TtlConfigUtil.maxTtlTmpTableDataLength; +// needStop = TtlJobUtil.checkIfArcTmlTableDataLengthExceedLimit(arcTmpTblDataLength); +// if (needStop) { +// Long jobId = this.parentDdlTask.getJobId(); +// Long taskId = this.parentDdlTask.getTaskId(); +// String arcTblSchema = this.jobContext.getTtlInfo().getTmpTableSchema(); +// String arcTblName = this.jobContext.getTtlInfo().getTmpTableName(); +// String logMsg = String.format( +// "DdlTask[%s-%s] arcTmpTable[%s.%s] data length has exceeded, actual is %s, limit is %s, ", +// jobId, taskId, arcTblSchema, arcTblName, arcTmpTblDataLength, arcTmpTblDataLengthLimit); +// TtlLoggerUtil.TTL_TASK_LOGGER.info(logMsg); +// } + + this.logInfo.needStopCleanup = needStop; + this.logInfo.arcTmpTblDataLength = 0; + this.logInfo.arcTmpTblDataLengthLimit = 0; + return needStop; + } + + @Override + public void handleResults(boolean isFinished, + boolean interrupted, + boolean withinMaintainableTimeFrame) { + logInfo.isAllIntraTaskFinished = isFinished; + logInfo.taskEndTs = System.currentTimeMillis(); + logInfo.stopByMaintainTime = !withinMaintainableTimeFrame; + logInfo.isInterrupted = interrupted; + logInfo.isTaskEnd = true; + logTaskExecResult(parentDdlTask, jobContext, logInfo); + } + } + + protected static void markPartFinishExpiredDataCleaning(DdlTask task, + PartitionMetaUtil.PartitionMetaRecord parMetaRec) { + final CleanAndPrepareExpiredDataTask currentTask = (CleanAndPrepareExpiredDataTask) task; + final PartitionMetaUtil.PartitionMetaRecord phyPartMetaRec = parMetaRec; + DdlEngineAccessorDelegate delegate = new DdlEngineAccessorDelegate() { + @Override + protected Integer invoke() { + + synchronized (currentTask) { + /** + * Query Task Record By Using For Update + */ + List taskRecords = + engineTaskAccessor.queryTasksForUpdate(currentTask.getJobId(), currentTask.getName()); + + if (taskRecords.isEmpty()) { + return 0; + } + + DdlEngineTaskRecord currTaskRec = taskRecords.get(0); + + /** + * Convert TaskRecord to TaskObj + */ + CleanAndPrepareExpiredDataTask newTask = + (CleanAndPrepareExpiredDataTask) TaskHelper.fromDdlEngineTaskRecord(currTaskRec); + + /** + * Fetch the newest bitset of phyPart + */ + Set newestCleanedPhyPartSet = newTask.getCleanedPhyPartSet(); + + /** + * Update the bitset to mark current part as finished + */ + TtlJobPhyPartBitSetUtil.markOnePartAsFinished(newestCleanedPhyPartSet, phyPartMetaRec); + + currentTask.setCleanedPhyPartSet(newestCleanedPhyPartSet); + currentTask.setState(DdlTaskState.DIRTY); + + /** + * Convert newTask to taskRecord to store into metadb + */ + DdlEngineTaskRecord taskRecord = TaskHelper.toDdlEngineTaskRecord(newTask); + + /** + * Update Metadb + */ + int updateRs = engineTaskAccessor.updateTask(taskRecord); + return updateRs; + } + } + }; + delegate.execute(); + } + + protected static void storeCleanedPhyPartSetToTaskRecord(DdlTask task) { + final CleanAndPrepareExpiredDataTask currentTask = (CleanAndPrepareExpiredDataTask) task; + DdlEngineAccessorDelegate delegate = new DdlEngineAccessorDelegate() { + @Override + protected Integer invoke() { + + synchronized (currentTask) { + /** + * Convert newTask to taskRecord to store into metadb + */ + currentTask.setState(DdlTaskState.DIRTY); + DdlEngineTaskRecord taskRecord = TaskHelper.toDdlEngineTaskRecord(currentTask); + + /** + * Update ddl_engine_task of Metadb + */ + int updateRs = engineTaskAccessor.updateTask(taskRecord); + + return updateRs; + } + } + }; + delegate.execute(); + } + + @Override + protected void beforeTransaction(ExecutionContext executionContext) { + super.beforeTransaction(executionContext); + fetchTtlJobContextFromPreviousTask(); + executeImpl(executionContext); + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + super.duringTransaction(metaDbConnection, executionContext); + } + + @Override + protected void beforeRollbackTransaction(ExecutionContext executionContext) { + super.beforeRollbackTransaction(executionContext); + } + + @Override + protected void duringRollbackTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + super.duringRollbackTransaction(metaDbConnection, executionContext); + } + + protected void fetchTtlJobContextFromPreviousTask() { +// boolean needPerformArchiving = this.jobContext.getTtlInfo().needPerformExpiredDataArchivingByOssTbl(); + Class previousTaskClass = PrepareCleanupIntervalTask.class; + TtlJobContext jobContext = TtlJobUtil.fetchTtlJobContextFromPreviousTaskByTaskName( + getJobId(), previousTaskClass, + getSchemaName(), getLogicalTableName()); + this.jobContext = jobContext; + } + + public static class CleanupExpiredDataLogInfo { + protected TtlScheduledJobStatManager.TtlJobStatInfo ttlJobStatInfo; + protected Long jobId; + protected Long taskId; + protected Long taskBeginTsNano; + protected Long taskBeginTs; + protected Long taskEndTs; + + protected boolean needPerformArchiving = false; + protected String arcTmpTblSchema = ""; + protected String arcTmpTblName = ""; + + protected String ttlColMinValStr = ""; + protected String firstLevelPartNameOfTtlColMinVal = ""; + protected String cleanupLowerBound = ""; + protected String firstLevelPartNameOfCleanupLowerBound = ""; + protected String previousPartBoundOfTtlColMinVal = ""; + + protected boolean isInterrupted = false; + protected boolean isTaskEnd = false; + protected boolean isAllIntraTaskFinished = false; + protected boolean stopByMaintainTime = false; + + protected boolean needStopCleanup = false; + protected long arcTmpTblDataLength = 0; + protected long arcTmpTblDataLengthLimit = 0; + + protected long waitCleanupTaskRunningLoopRound = 0; + + protected long deleteAvgRt = 0; + protected long deleteRowsSpeed = 0; + protected long deleteSqlCnt = 0; + protected long deleteRows = 0; + protected long deleteTimeCost = 0; + protected String deleteSqlTemp = ""; + + protected long cleanupSpeed = 0; + protected long cleanupRowsSpeed = 0; + protected long cleanupRows = 0; + protected long cleanupTimeCost = 0; + protected long waitPermitsTimeCost = 0; + } + + protected static void logTaskExecResult(DdlTask ddlTask, + TtlJobContext jobContext, + CleanupExpiredDataLogInfo logInfo) { + + try { + + if (logInfo.stopByMaintainTime) { + logInfo.ttlJobStatInfo.setCurrJobStopByMaintainWindow(logInfo.stopByMaintainTime); + logInfo.ttlJobStatInfo.setCurrJobStage("stoppedByMaintainWindow"); + } + + String logMsg = ""; + String msgPrefix = TtlLoggerUtil.buildTaskLogRowMsgPrefix(ddlTask.getJobId(), ddlTask.getTaskId(), + "CleanupExpiredData"); + + logMsg += msgPrefix; + logMsg += String.format("needArc: %s, arcTmpTblSchema: %s, arcTmpTblName: %s\n", + logInfo.needPerformArchiving, + logInfo.arcTmpTblSchema, + logInfo.arcTmpTblName); + + logMsg += msgPrefix; + logMsg += String.format("allTaskFinished: %s, interrupted: %s, loopRound: %s\n", + logInfo.isAllIntraTaskFinished, + logInfo.isInterrupted, + logInfo.waitCleanupTaskRunningLoopRound); + + logMsg += msgPrefix; + logMsg += String.format("stopByMaintainTime: %s, beginTs: %s, totalTimeCost(ms): %s\n", + logInfo.stopByMaintainTime, + logInfo.taskBeginTs, + System.currentTimeMillis() - logInfo.taskBeginTs); + + logMsg += msgPrefix; + logMsg += String.format("needStopCleanup: %s, exceedDelta: %s, arcTmpTblLen: %s, lenLimit: %s, \n", + logInfo.needStopCleanup, + logInfo.arcTmpTblDataLength - logInfo.arcTmpTblDataLengthLimit, + logInfo.arcTmpTblDataLength, + logInfo.arcTmpTblDataLengthLimit); + + logMsg += msgPrefix; + logMsg += String.format("minVal: %s, partOfMinVal: %s\n", + logInfo.ttlColMinValStr, + logInfo.firstLevelPartNameOfTtlColMinVal); + + logMsg += msgPrefix; + logMsg += String.format("lowerBndVal: %s, partOfLowerBndVal: %s\n", + logInfo.cleanupLowerBound, + logInfo.firstLevelPartNameOfCleanupLowerBound); + + logMsg += msgPrefix; + logMsg += String.format("previousPartBndOfMinVal: %s, cleanupInterval: ['%s','%s']\n", + logInfo.previousPartBoundOfTtlColMinVal, + logInfo.previousPartBoundOfTtlColMinVal, + logInfo.cleanupLowerBound); + + logMsg += msgPrefix; + logMsg += String.format("cleanupRowsSpeed(r/s): %s, cleanupSpeed(B/s): %s\n", logInfo.cleanupRowsSpeed, + logInfo.cleanupSpeed); + + logMsg += msgPrefix; + logMsg += + String.format("cleanupRows: %s, cleanupTimeCost: %s, waitPermitsTimeCost: %s\n", logInfo.cleanupRows, + logInfo.cleanupTimeCost, logInfo.waitPermitsTimeCost); + + logMsg += msgPrefix; + logMsg += + String.format("deleteRowsSpeed(r/s): %s, deleteRows: %s\n", + logInfo.deleteRowsSpeed, logInfo.deleteRows); + logMsg += msgPrefix; + logMsg += String.format("deleteAvgRt(ms): %s, deleteSqlCnt: %s, deleteTimeCost(ms): %s\n", + logInfo.deleteAvgRt, logInfo.deleteSqlCnt, logInfo.deleteTimeCost); + logMsg += msgPrefix; + logMsg += String.format("deleteSqlTemp: %s\n", logInfo.deleteSqlTemp); + + logMsg += msgPrefix; + logMsg += String.format("cleanupTaskFinish: %s\n", logInfo.isTaskEnd); + + TtlLoggerUtil.logTaskMsg(ddlTask, jobContext, logMsg); + + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + } + } +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/FinishCleaningUpAndLogTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/FinishCleaningUpAndLogTask.java new file mode 100644 index 000000000..ba9fe223f --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/FinishCleaningUpAndLogTask.java @@ -0,0 +1,42 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.gms.util.TtlEventLogUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; + +/** + * @author chenghui.lch + */ +@Getter +@TaskName(name = "FinishCleaningUpAndLogTask") +public class FinishCleaningUpAndLogTask extends AbstractTtlJobTask { + + @JSONCreator + public FinishCleaningUpAndLogTask(String schemaName, String logicalTableName) { + super(schemaName, logicalTableName); + } + + protected void fetchTtlJobContextFromPreviousTask() { + TtlJobContext jobContext = TtlJobUtil.fetchTtlJobContextFromPreviousTaskByTaskName( + getJobId(), + PrepareCleanupIntervalTask.class, + getSchemaName(), + this.logicalTableName + ); + this.jobContext = jobContext; + } + + @Override + protected void beforeTransaction(ExecutionContext executionContext) { + super.beforeTransaction(executionContext); + fetchTtlJobContextFromPreviousTask(); + executeImpl(executionContext); + } + + protected void executeImpl(ExecutionContext executionContext) { + TtlJobUtil.updateJobStage(this.jobContext, "Finished"); + TtlEventLogUtil.logCleanupExpiredDataEvent(schemaName, logicalTableName); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/IntraTaskStatInfo.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/IntraTaskStatInfo.java new file mode 100644 index 000000000..86e65e700 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/IntraTaskStatInfo.java @@ -0,0 +1,28 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import lombok.Data; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * @author chenghui.lch + */ +@Data +public class IntraTaskStatInfo { + + protected Long jobId; + protected Long taskId; + + protected AtomicLong totalInsertRows = new AtomicLong(0); + protected AtomicLong totalDeleteRows = new AtomicLong(0); + protected AtomicLong totalInsertSqlCount = new AtomicLong(0); + protected AtomicLong totalDeleteSqlCount = new AtomicLong(0); + protected AtomicLong totalInsertTimeCostNano = new AtomicLong(0); + protected AtomicLong totalDeleteTimeCostNano = new AtomicLong(0); + protected AtomicLong totalSelectTimeCostNano = new AtomicLong(0); + protected AtomicLong totalExecTimeCostNano = new AtomicLong(0); + protected AtomicLong totalWaitPermitsTimeCostNano = new AtomicLong(0); + + public IntraTaskStatInfo() { + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/PhyPartSpecIterator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/PhyPartSpecIterator.java new file mode 100644 index 000000000..a061f923a --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/PhyPartSpecIterator.java @@ -0,0 +1,79 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.executor.utils.PartitionMetaUtil; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.LinkedBlockingQueue; + +public class PhyPartSpecIterator implements Iterator { + + protected LinkedBlockingQueue phyPartSpecMetas = new LinkedBlockingQueue<>(); + protected Iterator iterator; + + public PhyPartSpecIterator(PartitionInfo partInfo) { + initIterator(partInfo); + } + + protected void initIterator(PartitionInfo partInfo) { + String tblName = partInfo.getTableName(); + List partitionMetaRecords = + PartitionMetaUtil.handlePartitionsMeta(partInfo, "", tblName); + Map> tmpDnToPhyPartsMappings = + new TreeMap<>(); + int allPhyPartCnt = partitionMetaRecords.size(); + + /** + * Group all the phy-parts by their dnId + */ + for (int i = 0; i < allPhyPartCnt; i++) { + PartitionMetaUtil.PartitionMetaRecord record = partitionMetaRecords.get(i); + String dnId = record.rwDnId; + LinkedBlockingQueue recordList = tmpDnToPhyPartsMappings.get(dnId); + if (recordList == null) { + recordList = new LinkedBlockingQueue<>(); + tmpDnToPhyPartsMappings.put(dnId, recordList); + } + recordList.add(record); + } + + /** + * Reorder all the phy-parts by zigzag their dnId + */ + Set dnIdList = tmpDnToPhyPartsMappings.keySet(); + int currPartIndex = 0; + LinkedBlockingQueue newPhyPartInfos = new LinkedBlockingQueue<>(); + while (currPartIndex < allPhyPartCnt) { + Iterator dnIdItor = dnIdList.iterator(); + while (dnIdItor.hasNext()) { + String tmpDnId = dnIdItor.next(); + LinkedBlockingQueue phyPartInfosOfDn = + tmpDnToPhyPartsMappings.get(tmpDnId); + + if (phyPartInfosOfDn.isEmpty()) { + continue; + } + + PartitionMetaUtil.PartitionMetaRecord phyPart = phyPartInfosOfDn.poll(); + newPhyPartInfos.add(phyPart); + currPartIndex++; + } + } + phyPartSpecMetas = newPhyPartInfos; + } + + @Override + public boolean hasNext() { + return !phyPartSpecMetas.isEmpty(); + } + + @Override + public PartitionMetaUtil.PartitionMetaRecord next() { + PartitionMetaUtil.PartitionMetaRecord phyPart = phyPartSpecMetas.poll(); + return phyPart; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/PrepareCleanupIntervalTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/PrepareCleanupIntervalTask.java new file mode 100644 index 000000000..59070b28b --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/PrepareCleanupIntervalTask.java @@ -0,0 +1,563 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.logger.MDC; +import com.alibaba.polardbx.common.utils.time.core.OriginalTimestamp; +import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler.TtlScheduledJobStatManager; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlTimeUnit; +import lombok.Getter; + +import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; +import java.sql.Connection; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.Future; + +/** + * @author chenghui.lch + */ +@Getter +@TaskName(name = "PrepareCleanupIntervalTask") +public class PrepareCleanupIntervalTask extends AbstractTtlJobTask { + + /** + *
+     * The job of PrepareCleanupIntervalTask are the following:
+     *  1. decide the the time interval of the expired data to be cleared in this job;
+     *  2. check if need do archiving, then make sure that
+     *      the the target time interval of the expired data to be cleared
+     *      are included by range partitions of ttl_tmp table
+     *     or add new range partition for ttl_tmp table if find
+     *     the target time interval of the expired data are NOT included.
+     * 
+ */ + + @JSONCreator + public PrepareCleanupIntervalTask(String schemaName, + String logicalTableName) { + super(schemaName, logicalTableName); + onExceptionTryRecoveryThenPause(); + } + + public void executeImpl(ExecutionContext executionContext) { + resetTtlJobStat(); + TtlJobUtil.updateJobStage(this.jobContext, "SelectingForCleanupBound"); + prepareExpiredCLeanUpBound(executionContext); + } + + protected void resetTtlJobStat() { + String ttlDb = this.jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + String ttlTb = this.jobContext.getTtlInfo().getTtlInfoRecord().getTableName(); + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = + TtlScheduledJobStatManager.getInstance().getTtlJobStatInfo(ttlDb, ttlTb); + if (jobStatInfo != null) { + jobStatInfo.resetFinishedJobStatInfo(); + jobStatInfo.setCurrJobBeginTs(System.currentTimeMillis()); + } + } + + @Override + protected void beforeTransaction(ExecutionContext executionContext) { + super.beforeTransaction(executionContext); + executeImpl(executionContext); + } + + @Override + protected void duringTransaction(Connection metaDbConnection, ExecutionContext executionContext) { + super.duringTransaction(metaDbConnection, executionContext); + } + + protected static class FetchMinCleanUpBoundTaskSubmitter implements TtlWorkerTaskSubmitter { + protected DdlTask parentDdlTask; + protected ExecutionContext ec; + protected TtlJobContext ttlJobContext; + + public FetchMinCleanUpBoundTaskSubmitter(DdlTask parentDdlTask, ExecutionContext ec, + TtlJobContext ttlJobContext) { + this.parentDdlTask = parentDdlTask; + this.ec = ec; + this.ttlJobContext = ttlJobContext; + } + + @Override + public List> submitWorkerTasks() { + List> futureInfos = new ArrayList<>(); + FetchExpiredDataUpperBoundTask task = new FetchExpiredDataUpperBoundTask(parentDdlTask, ec, ttlJobContext); + List runners = new ArrayList<>(); + runners.add(task); + futureInfos = TtlIntraTaskExecutor.getInstance().submitSelectTaskRunners(runners); + return futureInfos; + } + } + + protected static class FetchExpiredDataUpperBoundTask extends TtlIntraTaskRunner { + + protected DdlTask parentDdlTask; + protected TtlJobContext jobContext; + protected ExecutionContext ec; + protected Object transConn; + protected String currentDatetime = null; + protected String formatedCurrentDatetime = null; + protected String expiredUpperBound = null; + protected String expiredLowerBound = null; + protected String ttlColMinValue = null; + protected Boolean ttlColMinValueIsNull = false; + protected Boolean ttlColMinValueIsZero = false; + protected Boolean ttlTblIsEmpty = false; + protected String minBoundToBeCleanUp = null; + protected boolean stopTask = false; + protected IntraTaskStatInfo statInfo = new IntraTaskStatInfo(); + + public FetchExpiredDataUpperBoundTask(DdlTask parentDdlTask, + ExecutionContext ec, + TtlJobContext jobContext) { + this.parentDdlTask = parentDdlTask; + this.jobContext = jobContext; + this.ec = ec; + } + + @Override + public void runTask() { + final Map savedMdcContext = MDC.getCopyOfContextMap(); + try { + String schemaName = jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema().toLowerCase(); + MDC.put(MDC.MDC_KEY_APP, schemaName); + runInner(); + } finally { + MDC.setContextMap(savedMdcContext); + } + } + + protected void runInner() { + + long taskStartTsNano = System.nanoTime(); + String logMsgHeader = TtlLoggerUtil.buildIntraTaskLogMsgHeader(parentDdlTask, jobContext); + + final IServerConfigManager serverConfigManager = TtlJobUtil.getServerConfigManager(); + final String ttlTblSchemaName = this.jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + boolean needPerformArchivingByOssTbl = + this.jobContext.getTtlInfo().needPerformExpiredDataArchivingByOssTbl(); + + TtlDefinitionInfo ttlInfo = this.jobContext.getTtlInfo(); + String ttlTimezoneStr = ttlInfo.getTtlInfoRecord().getTtlTimezone(); + String charsetEncoding = TtlConfigUtil.getDefaultCharsetEncodingOnTransConn(); + String sqlModeSetting = TtlConfigUtil.getDefaultSqlModeOnTransConn(); + String groupParallelismForConnStr = String.valueOf(TtlConfigUtil.getDefaultGroupParallelismOnDqlConn()); + Map sessionVariables = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + sessionVariables.put("time_zone", ttlTimezoneStr); + sessionVariables.put("names", charsetEncoding); + sessionVariables.put("sql_mode", sqlModeSetting); + sessionVariables.put("group_parallelism", groupParallelismForConnStr); + + TtlJobUtil.wrapWithDistributedTrx( + serverConfigManager, + ttlTblSchemaName, + sessionVariables, + (transConn) -> { + + /** + * Save the reference of transConn on IntraTask to use to do force closing + */ + this.transConn = transConn; + + /** + * Select the lower bound value of ttl_col of ttl_tbl + *
+                     * SELECT DATE_FORMAT(ttl_col,formatter) AS expired_lower_bound
+                     *  FROM (SELECT %s as ttl_col
+                     *         FROM [db_name.]ttl_tbl [FORCE INDEX(xxx_ttl_col_idx)]
+                     *         ORDER BY %s ASC
+                     *         LIMIT 1
+                     *       ) as ttl_tbl
+                     * 
+ * + */ + final String selectExpiredLowerBoundSql = buildSelectExpiredLowerBoundSql(); + long selectLowerBoundStartTsNano = System.nanoTime(); + List> lowerBoundResult = + TtlJobUtil.execLogicalQueryOnInnerConnection(serverConfigManager, + ttlTblSchemaName, + transConn, + ec, + selectExpiredLowerBoundSql); + long selectLowerBoundEndTsNano = System.nanoTime(); + this.statInfo.getTotalSelectTimeCostNano() + .addAndGet(selectLowerBoundEndTsNano - selectLowerBoundStartTsNano); + + if (lowerBoundResult == null || lowerBoundResult.isEmpty()) { + this.ttlTblIsEmpty = true; + /** + * ttl_tbl has no data + */ + this.expiredLowerBound = null; + this.ttlColMinValueIsNull = false; + this.ttlColMinValueIsZero = false; + } else { + this.ttlTblIsEmpty = false; + String minValIsNull = fetchStringFromQueryValue(lowerBoundResult, + TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_TTL_COL_MIN_VALUE_IS_NULL); + String minValIsZero = fetchStringFromQueryValue(lowerBoundResult, + TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_TTL_COL_MIN_VALUE_IS_ZERO); + String expiredLowerBoundStr = fetchStringFromQueryValue(lowerBoundResult, + TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_TTL_COL_LOWER_BOUND); + String minValueStr = fetchStringFromQueryValue(lowerBoundResult, + TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_TTL_COL_MIN_VALUE); + + this.ttlColMinValueIsNull = minValIsNull.equalsIgnoreCase("1"); + this.ttlColMinValueIsZero = ttlColMinValueIsNull ? false : minValIsZero.equalsIgnoreCase("1"); + this.expiredLowerBound = expiredLowerBoundStr; + this.ttlColMinValue = minValueStr; + + } + + /** + * Select the round-downed upper bound of expired value of ttl_col + *
+                     * set TIME_ZONE='xxx';
+                     * SELECT DATE_FORMAT( DATE_SUB(NOW(), INTERVAL %s %s), formatter ) expired_upper_bound;
+                     * formatter is like %Y-%m-%d 00:00:00.000000
+                     * 
+ * + */ + final String selectExpiredUpperBoundSql = buildSelectExpiredUpperBoundSql(); + List> upperBoundResult = + TtlJobUtil.execLogicalQueryOnInnerConnection(serverConfigManager, + ttlTblSchemaName, + transConn, + ec, + selectExpiredUpperBoundSql); + + if (upperBoundResult == null || upperBoundResult.isEmpty()) { + /** + * ttl_tbl has no data + */ + this.expiredUpperBound = null; + } else { + String currentDatetime = fetchStringFromQueryValue(upperBoundResult, + TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_TTL_COL_CURRENT_DATETIME); + String formatedCurrentDatetime = fetchStringFromQueryValue(upperBoundResult, + TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_TTL_COL_FORMATED_CURRENT_DATETIME); + String expiredUpperBoundStr = + fetchStringFromQueryValue(upperBoundResult, + TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_TTL_COL_UPPER_BOUND); + this.expiredUpperBound = expiredUpperBoundStr; + this.currentDatetime = currentDatetime; + this.formatedCurrentDatetime = formatedCurrentDatetime; + } + + return 0; + } + ); + + /** + *
+             *     Compute and the Min Bound to Be Cleanup
+             * 
+ */ + minBoundToBeCleanUp = decideExpiredLowerBound(); + this.jobContext.setCurrentDateTime(currentDatetime); + this.jobContext.setFormatedCurrentDateTime(formatedCurrentDatetime); + this.jobContext.setCleanUpUpperBound(expiredUpperBound); + this.jobContext.setCleanUpLowerBound(minBoundToBeCleanUp); + this.jobContext.setTtlColMinValue(ttlColMinValue); + this.jobContext.setTtlColMinValueIsNull(ttlColMinValueIsNull); + this.jobContext.setTtlColMinValueIsZero(ttlColMinValueIsZero); + this.jobContext.setTtlTblIsEmpty(ttlTblIsEmpty); + + long arcTmpTblDataLength = 0; + if (needPerformArchivingByOssTbl) { + // Fetch the arc-tmp tbl data-length + arcTmpTblDataLength = TtlJobUtil.fetchArcTmlTableDataLength(ec, this.jobContext, null); + } + this.jobContext.setArcTmpDataLengthBeforeRunning(arcTmpTblDataLength); + + TtlTblFullDataFreeInfo[] ttlTblFullDfInfoOutput = new TtlTblFullDataFreeInfo[1]; + try { + long maxTtlTblDfPercent = TtlConfigUtil.getMaxDataFreePercentOfTtlTable(); + TtlJobUtil.fetchTtlTableDataFreeStat(this.ec, this.jobContext, ttlTblFullDfInfoOutput); + if (ttlTblFullDfInfoOutput[0] != null) { + TtlTblFullDataFreeInfo ttlTblFullDfInfo = ttlTblFullDfInfoOutput[0]; + BigDecimal primDfPercentDec = ttlTblFullDfInfo.getPrimDataFreeInfo().getDataFreePercent(); + long dfPercentAvg = ttlTblFullDfInfo.getDataFreePercentAvg(); + long rowLenAvg = ttlTblFullDfInfo.getRowDataLengthAvg(); + this.jobContext.setTtlTblPrimDataLength( + ttlTblFullDfInfo.getPrimDataFreeInfo().getDataLength().get()); + this.jobContext.setDataFreeOfTtlTblPrim( + ttlTblFullDfInfo.getPrimDataFreeInfo().getDataFree().get()); + this.jobContext.setDataFreePercentOfTtlTblPrim(primDfPercentDec); + this.jobContext.setDataFreePercentAvgOfTtlTbl(dfPercentAvg); + this.jobContext.setRowLengthAvgOfTtlTbl(rowLenAvg); + + if (TtlConfigUtil.isEnableAutoControlOptiTblByTtlJob()) { + BigDecimal maxTtlTblDfPercentDec = new BigDecimal(maxTtlTblDfPercent); + if (TtlJobUtil.checkNeedPerformOptiTblForTtlTbl(primDfPercentDec, maxTtlTblDfPercentDec)) { + this.jobContext.setNeedPerformOptiTable(true); + } + } + } + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + } + + long taskEndTsNano = System.nanoTime(); + this.statInfo.getTotalExecTimeCostNano().addAndGet(taskEndTsNano - taskStartTsNano); + + logTaskExecResult(logMsgHeader, jobContext, statInfo); + + } + + private String fetchStringFromQueryValue(List> boundResult, String colName) { + String expiredLowerBoundStr = null; + Object expiredLowerBoundObj = boundResult.get(0).get(colName); + if (expiredLowerBoundObj instanceof io.airlift.slice.Slice) { + //expiredLowerBoundStr = ((Slice) expiredLowerBoundObj).toString(); + byte[] valBytes = ((io.airlift.slice.Slice) expiredLowerBoundObj).getBytes(); + try { + expiredLowerBoundStr = new String(valBytes, "utf8"); + } catch (UnsupportedEncodingException e) { + throw new TtlJobRuntimeException(e); + } + } else if (expiredLowerBoundObj instanceof String) { + expiredLowerBoundStr = (String) expiredLowerBoundObj; + } else if (expiredLowerBoundObj instanceof OriginalTimestamp) { + expiredLowerBoundStr = + ((OriginalTimestamp) expiredLowerBoundObj).getMysqlDateTime().toDatetimeString(0); + } else if (expiredLowerBoundObj instanceof Long) { + expiredLowerBoundStr = String.valueOf(expiredLowerBoundObj); + } + + return expiredLowerBoundStr; + } + + protected void logTaskExecResult( + String logMsgHeader, + TtlJobContext jobContext, + IntraTaskStatInfo statInfo) { + + String dbName = jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + String tbName = jobContext.getTtlInfo().getTtlInfoRecord().getTableName(); + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = TtlScheduledJobStatManager.getInstance() + .getTtlJobStatInfo(dbName, tbName); + TtlScheduledJobStatManager.GlobalTtlJobStatInfo globalStatInfo = TtlScheduledJobStatManager.getInstance() + .getGlobalTtlJobStatInfo(); + + long taskTimeCostMills = statInfo.getTotalExecTimeCostNano().get() / 1000000; + long selectTimeCostMills = statInfo.getTotalSelectTimeCostNano().get() / 1000000; + + jobStatInfo.setTtlTblDataFreePercent(jobContext.getDataFreePercentOfTtlTblPrim()); + jobStatInfo.getSelectSqlCount().incrementAndGet(); + jobStatInfo.getSelectSqlTimeCost().addAndGet(selectTimeCostMills); + jobStatInfo.getCleanupTimeCost().addAndGet(taskTimeCostMills); + jobStatInfo.calcSelectSqlAvgRt(); + + globalStatInfo.getTotalSelectSqlCount().incrementAndGet(); + globalStatInfo.getTotalSelectSqlTimeCost().addAndGet(selectTimeCostMills); + globalStatInfo.getTotalCleanupTimeCost().addAndGet(taskTimeCostMills); + + /** + *
+             *     min: ttl col min value
+             *     lb: lower bound to be cleanup
+             *     up: upper bound to be cleanup
+             *     cb: the bound to cleanup in this job
+             *     bz: batch size
+             *     timeCost unit: ms
+             * 
+ */ + String simpleLogMsg = ""; + simpleLogMsg = String.format("[%s] [ts=%s,lb=%s,ub=%s,cb=%s,min=%s,bs=%s] [tc=%d,stc=%d]", + logMsgHeader, currentDatetime, expiredLowerBound, expiredUpperBound, minBoundToBeCleanUp, + ttlColMinValue, jobContext.getDmlBatchSize(), + taskTimeCostMills, selectTimeCostMills); + + jobStatInfo.setCurrTtlColMinVal(String.valueOf(ttlColMinValue)); + jobStatInfo.setCurrCleanupBound(String.valueOf(minBoundToBeCleanUp)); + jobStatInfo.setCurrCleanupUpperBound(String.valueOf(expiredUpperBound)); + jobStatInfo.setCurrDataTimeVal(currentDatetime); + + TtlLoggerUtil.TTL_TASK_LOGGER.info(simpleLogMsg); + + String logMsg = ""; + String msgPrefix = + TtlLoggerUtil.buildTaskLogRowMsgPrefix(parentDdlTask.getJobId(), parentDdlTask.getTaskId(), + "PrepareCleanupBound"); + logMsg += msgPrefix; + + logMsg += String.format("currentDateTime: %s\n", currentDatetime); + + logMsg += msgPrefix; + logMsg += + String.format("expiredLowerBnd: %s, expiredUpperBnd: %s\n", minBoundToBeCleanUp, expiredUpperBound); + + logMsg += msgPrefix; + logMsg += String.format("ttlColMinVal: %s, minBndToBeCleanUp: %s\n", ttlColMinValue, minBoundToBeCleanUp); + + logMsg += msgPrefix; + logMsg += String.format("ttlPrimDataFree: %s, ttlPrimDataLength: %s, ttlPrimRowLengthAvg: %s\n", + this.jobContext.getDataFreeOfTtlTblPrim(), this.jobContext.getTtlTblPrimDataLength(), + this.jobContext.getRowLengthAvgOfTtlTbl()); + + logMsg += msgPrefix; + logMsg += String.format("needPerformOptiTbl: %s, dfPercent: %s, dfPercentAvg: %s\n", + this.jobContext.getNeedPerformOptiTable(), this.jobContext.getDataFreePercentOfTtlTblPrim(), + this.jobContext.getDataFreePercentAvgOfTtlTbl()); + + logMsg += msgPrefix; + logMsg += String.format("dmlBatchSize: %s\n", jobContext.getDmlBatchSize()); + + logMsg += msgPrefix; + logMsg += String.format("selectTimeCost(ms): %s\n", selectTimeCostMills); + + logMsg += msgPrefix; + logMsg += String.format("taskTimeCot(ms): %s\n", taskTimeCostMills); + + TtlLoggerUtil.logTaskMsg(parentDdlTask, this.jobContext, logMsg); + + } + + protected String decideExpiredLowerBound() { + + String lowerBoundStr = this.expiredLowerBound; + String upperBoundStr = this.expiredUpperBound; + String minBoundToBeCleanupStr = upperBoundStr; + + try { + DateTimeFormatter formatter = TtlJobUtil.ISO_DATETIME_FORMATTER; + TtlDefinitionInfo ttlInfo = this.jobContext.getTtlInfo(); + boolean ttlTblIsEmptyVal = this.ttlTblIsEmpty; + boolean ttlColMinValIsNullVal = this.ttlColMinValueIsNull; + boolean ttlColMinValueIsZeroVal = this.ttlColMinValueIsZero; + TtlTimeUnit ttlUnitVal = TtlTimeUnit.of(ttlInfo.getTtlInfoRecord().getTtlUnit()); + + if (StringUtils.isEmpty(lowerBoundStr) || ttlColMinValIsNullVal) { + if (ttlTblIsEmptyVal) { + /** + * ttl_tbl has no data + */ + return minBoundToBeCleanupStr; + } + } + + if (ttlColMinValIsNullVal || ttlColMinValueIsZeroVal) { + lowerBoundStr = TtlTaskSqlBuilder.TTL_COL_MIN_VAL_DEFAULT_LOWER_BOUND; + } + + /** + * Convert upperBoundStr of ISO_LOCAL_DATE_TIME-format to DateTime + */ + LocalDateTime upperBoundDt = LocalDateTime.parse(upperBoundStr, formatter); + + /** + * Convert lowerBoundStr of ISO_LOCAL_DATE_TIME-format to DateTime + */ + LocalDateTime lowerBoundDt = LocalDateTime.parse(lowerBoundStr, formatter); + + int oneUnitStep = TtlConfigUtil.getTtlCleanupBoundIntervalCount(); + LocalDateTime minBoundToBeCleanup = + TtlJobUtil.plusDeltaIntervals(lowerBoundDt, ttlUnitVal, oneUnitStep); + + int cmpRs = minBoundToBeCleanup.compareTo(upperBoundDt); + if (cmpRs >= 0) { + /** + * The minBoundToBeCleanup is NOT less than upperBound, + * use upperBound as the minBound that is to be cleanup + */ + } else { + /** + * The minBoundToBeCleanup is less than upperBound, + */ + minBoundToBeCleanupStr = minBoundToBeCleanup.format(formatter); + } + + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.error(ex); + throw ex; + } + return minBoundToBeCleanupStr; + } + + protected String buildSelectExpiredLowerBoundSql() { + TtlDefinitionInfo ttlInfo = this.jobContext.getTtlInfo(); + boolean useMergeConcurrent = TtlConfigUtil.isUseMergeConcurrentForSelectLowerBound(); + int mergeUnionSize = TtlConfigUtil.getMergeUnionSizeForSelectLowerBound(); + String queryHint = TtlConfigUtil.getQueryHintForSelectLowerBound(); + String forceIndexExpr = this.jobContext.getTtlColForceIndexExpr(); + String selectSql = + TtlTaskSqlBuilder.buildSelectExpiredLowerBoundValueSqlTemplate(ttlInfo, ec, queryHint, forceIndexExpr); + if (!useMergeConcurrent) { + selectSql = + TtlTaskSqlBuilder.buildSelectExpiredLowerBoundValueBySqlTemplateWithoutConcurrent(ttlInfo, ec, + mergeUnionSize, forceIndexExpr); + } + return selectSql; + } + + protected String buildSelectExpiredUpperBoundSql() { + TtlDefinitionInfo ttlInfo = this.jobContext.getTtlInfo(); + String selectSql = TtlTaskSqlBuilder.buildSelectExpiredUpperBoundValueSqlTemplate(ttlInfo, ec); + return selectSql; + } + + @Override + public String getDnId() { + return ""; + } + + @Override + public void notifyStopTask() { + this.stopTask = true; + } + + @Override + public void forceStopTask() { + this.stopTask = true; + if (transConn != null) { + IServerConfigManager serverMgr = TtlJobUtil.getServerConfigManager(); + try { + serverMgr.closeTransConnection(transConn); + } catch (Throwable ex) { + // ignore ex + TtlLoggerUtil.TTL_TASK_LOGGER.info(ex); + } + } + } + } + + protected void prepareExpiredCLeanUpBound(ExecutionContext ec) { + + /** + * Find and build force index expr for ttl col + */ + initForceIndexExprForTtlCol(ec); + + /** + * Fetch min bound of expired data to be cleanup + */ + FetchMinCleanUpBoundTaskSubmitter fetchBoundSubmitter = + new FetchMinCleanUpBoundTaskSubmitter(this, ec, this.jobContext); + TtlIntraTaskManager fetchBoundDelegate = + new TtlIntraTaskManager(this, ec, this.jobContext, fetchBoundSubmitter); + fetchBoundDelegate.submitAndRunIntraTasks(); + } + + protected void initForceIndexExprForTtlCol(ExecutionContext ec) { + String forceIndexExpr = TtlJobUtil.buildForceLocalIndexExprForTtlCol(this.jobContext.getTtlInfo(), ec); + this.jobContext.setTtlColForceIndexExpr(forceIndexExpr); + } + +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlDataCleanupRateLimiter.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlDataCleanupRateLimiter.java new file mode 100644 index 000000000..5a251c0ff --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlDataCleanupRateLimiter.java @@ -0,0 +1,137 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.common.model.lifecycle.AbstractLifecycle; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.gms.ha.impl.StorageHaManager; +import com.alibaba.polardbx.gms.ha.impl.StorageInstHaContext; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.google.common.util.concurrent.RateLimiter; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +/** + * @author chenghui.lch + */ +public class TtlDataCleanupRateLimiter extends AbstractLifecycle { + + private static final Logger logger = LoggerFactory.getLogger(TtlDataCleanupRateLimiter.class); + + /** + * The cleanup rows speed rate limiter for all dn, unit: rows/s + */ + private TtlAutoReloadRowsSpeedRateLimiterSubListener subListener = + new TtlAutoReloadRowsSpeedRateLimiterSubListener(); + private volatile Map allDnRowsSpeedLimiter = new ConcurrentHashMap<>(); + + private static TtlDataCleanupRateLimiter instance = new TtlDataCleanupRateLimiter(); + + public static TtlDataCleanupRateLimiter getInstance() { + return instance; + } + + private TtlDataCleanupRateLimiter() { + initAllRateLimiters(); + StorageHaManager.getInstance().registerStorageInfoSubListener(subListener); + } + + @Override + protected void doInit() { + } + + private void initAllRateLimiters() { + long initialRate = TtlConfigUtil.getCleanupRowsSpeedLimitEachDn(); + List rwDnList = StorageHaManager.getInstance().getMasterStorageList(); + Map newAllDnRowsSpeedLimiter = new ConcurrentHashMap<>(); + for (int i = 0; i < rwDnList.size(); i++) { + String dnId = rwDnList.get(i).getStorageInstId().toLowerCase(); + RateLimiter limiterOfOneDn = RateLimiter.create(initialRate); + newAllDnRowsSpeedLimiter.put(dnId, limiterOfOneDn); + } + this.allDnRowsSpeedLimiter = newAllDnRowsSpeedLimiter; + } + + public boolean tryAcquire(String dbId, int permits, long timeout, TimeUnit unit) { + try { + RateLimiter rateLimiter = this.allDnRowsSpeedLimiter.get(dbId); + if (rateLimiter == null) { + return true; + } + return rateLimiter.tryAcquire(permits, timeout, unit); + } catch (Throwable ex) { + throw new TtlJobRuntimeException(ex); + } + } + + protected class TtlAutoReloadRowsSpeedRateLimiterSubListener + implements StorageHaManager.StorageInfoConfigSubListener { + + @Override + public String getSubListenerName() { + return "TtlAutoReloadRowsSpeedRateLimiterSubListener"; + } + + @Override + public void onHandleConfig(String dataId, long newOpVersion) { + TtlDataCleanupRateLimiter.getInstance().reload(); + } + } + + /** + * Add or remove rows speed limiter by the rw-dn count + */ + public void reload() { + long permitsOfEachDn = TtlConfigUtil.getCleanupRowsSpeedLimitEachDn(); + Set tmpRwDnSetOfLimiters = new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + tmpRwDnSetOfLimiters.addAll(this.allDnRowsSpeedLimiter.keySet()); + + Set tmpRwDnSetOfHaMgr = new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + List dnCtxList = StorageHaManager.getInstance().getMasterStorageList(); + for (int i = 0; i < dnCtxList.size(); i++) { + tmpRwDnSetOfHaMgr.add(dnCtxList.get(i).getStorageInstId()); + } + + /** + * Add new RateLimiter for the new-added rw-dn + */ + for (String dnIdOfHaMgr : tmpRwDnSetOfHaMgr) { + if (this.allDnRowsSpeedLimiter.containsKey(dnIdOfHaMgr)) { + continue; + } + RateLimiter limiterOfOneDn = RateLimiter.create(permitsOfEachDn); + this.allDnRowsSpeedLimiter.put(dnIdOfHaMgr, limiterOfOneDn); + } + + /** + * Remove old RateLimiter for the removed rw-dn + */ + for (String dnIdOfLimiter : tmpRwDnSetOfLimiters) { + if (tmpRwDnSetOfHaMgr.contains(dnIdOfLimiter)) { + continue; + } + this.allDnRowsSpeedLimiter.remove(dnIdOfLimiter); + } + } + + /** + * Dynamic adjust permits of limiter + */ + public void adjustRate(long newPermitsVal) { + try { + for (Map.Entry limiterItem : allDnRowsSpeedLimiter.entrySet()) { + RateLimiter limiter = limiterItem.getValue(); + limiter.setRate(newPermitsVal); + } + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + logger.warn(ex.getMessage(), ex); + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlInfoValidateTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlInfoValidateTask.java new file mode 100644 index 000000000..6712e346f --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlInfoValidateTask.java @@ -0,0 +1,32 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.executor.ddl.job.task.BaseValidateTask; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; + +@Getter +@TaskName(name = "TtlInfoValidateTask") +public class TtlInfoValidateTask extends BaseValidateTask { + + protected String logicalTableName; + + public TtlInfoValidateTask(String schemaName, String logicalTableName) { + super(schemaName); + this.logicalTableName = logicalTableName; + } + + @Override + public void executeImpl(ExecutionContext executionContext) { + final TableMeta primaryTableMeta = + OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(logicalTableName); + + } + + @Override + protected void onExecutionSuccess(ExecutionContext executionContext) { + updateSupportedCommands(true, false, null); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlIntraTaskExecutor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlIntraTaskExecutor.java new file mode 100644 index 000000000..0013872da --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlIntraTaskExecutor.java @@ -0,0 +1,212 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.common.model.lifecycle.AbstractLifecycle; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.thread.NamedThreadFactory; +import com.alibaba.polardbx.gms.ha.impl.StorageHaManager; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @author chenghui.lch + */ +public class TtlIntraTaskExecutor extends AbstractLifecycle { + protected static final Logger logger = LoggerFactory.getLogger(TtlIntraTaskExecutor.class); + + public static final int SELECT_TASK_EXECUTOR_TYPE = 0; + public static final int DELETE_TASK_EXECUTOR_TYPE = 1; + + protected static TtlIntraTaskExecutor instance = new TtlIntraTaskExecutor(); + + /** + * The thread pool for exec the select intra-task of PrepareClearIntervalTask + */ + protected ReentrantLock selectTaskExecutorLock = new ReentrantLock(); + protected int selectTaskQueueSize = 8192 * 128; + protected volatile ThreadPoolExecutor selectTaskExecutor; + + /** + * The thread pool for exec the select intra-task of PrepareClearIntervalTask + */ + protected ReentrantLock deleteTaskExecutorLock = new ReentrantLock(); + protected int deleteTaskQueueSize = 8192 * 128; + protected volatile ThreadPoolExecutor deleteTaskExecutor; + protected TtlIntraTaskExecutorAutoAdjustWorkerSubListener subListener = + new TtlIntraTaskExecutorAutoAdjustWorkerSubListener(); + + protected class TtlIntraTaskExecutorAutoAdjustWorkerSubListener + implements StorageHaManager.StorageInfoConfigSubListener { + + @Override + public String getSubListenerName() { + return "TtlIntraTaskExecutorAutoAdjustWorkerSubListener"; + } + + @Override + public void onHandleConfig(String dataId, long newOpVersion) { + TtlIntraTaskExecutor.getInstance().autoAdjustWorkerCountForChangedRwDnList(); + } + } + + private TtlIntraTaskExecutor() { + } + + protected void iniTtlIntraTaskExecutor() { + + int selectTaskExecutorSize = TtlConfigUtil.getTtlGlobalDeleteWorkerCount(); + selectTaskExecutor = + createWorkerThreadPool("Ttl-SelectTaskExecutor", selectTaskExecutorSize, selectTaskQueueSize); + + int deleteTaskExecutorSize = TtlConfigUtil.getTtlGlobalDeleteWorkerCount(); + deleteTaskExecutor = + createWorkerThreadPool("Ttl-DeleteTaskExecutor", deleteTaskExecutorSize, deleteTaskQueueSize); + + StorageHaManager.getInstance().registerStorageInfoSubListener(subListener); + + } + + protected ThreadPoolExecutor createWorkerThreadPool(String poolName, + int poolSize, + int queueSize) { + int selectTaskExecutorSize = poolSize; + BlockingQueue selectTaskQueue = new LinkedBlockingQueue<>(queueSize); + ThreadPoolExecutor newTaskExecutor = new ThreadPoolExecutor(selectTaskExecutorSize, + selectTaskExecutorSize, + 1800, + TimeUnit.SECONDS, + selectTaskQueue, + new NamedThreadFactory(poolName, true), + new ThreadPoolExecutor.DiscardPolicy()); + return newTaskExecutor; + } + + public static TtlIntraTaskExecutor getInstance() { + if (!instance.isInited()) { + synchronized (instance) { + if (!instance.isInited()) { + instance.init(); + } + } + } + return instance; + } + + @Override + protected void doInit() { + super.doInit(); + iniTtlIntraTaskExecutor(); + } + + public List> submitSelectTaskRunners(List runners) { + this.selectTaskExecutorLock.lock(); + try { + List> futureInfos = new ArrayList<>(); + for (int i = 0; i < runners.size(); i++) { + TtlIntraTaskRunner runner = runners.get(i); + Future future = this.selectTaskExecutor.submit(runner); + Pair futureInfo = new Pair(future, runner); + futureInfos.add(futureInfo); + } + return futureInfos; + } finally { + this.selectTaskExecutorLock.unlock(); + } + } + + public List> submitDeleteTaskRunners(List runners) { + this.deleteTaskExecutorLock.lock(); + try { + List> futureInfos = new ArrayList<>(); + for (int i = 0; i < runners.size(); i++) { + TtlIntraTaskRunner runner = runners.get(i); + Future future = this.deleteTaskExecutor.submit(runner); + Pair futureInfo = new Pair(future, runner); + futureInfos.add(futureInfo); + } + return futureInfos; + } finally { + this.deleteTaskExecutorLock.unlock(); + } + } + + /** + * Auto adjust the task worker count when rw-dn list changed + */ + public static void autoAdjustWorkerCountForChangedRwDnList() { + try { + if (TtlConfigUtil.getTtlGlobalSelectWorkerCount() == 0) { + TtlIntraTaskExecutor.getInstance() + .adjustTaskExecutorWorkerCount(TtlIntraTaskExecutor.SELECT_TASK_EXECUTOR_TYPE, 0); + } + if (TtlConfigUtil.getTtlGlobalDeleteWorkerCount() == 0) { + TtlIntraTaskExecutor.getInstance() + .adjustTaskExecutorWorkerCount(TtlIntraTaskExecutor.DELETE_TASK_EXECUTOR_TYPE, 0); + } + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + logger.warn(ex.getMessage(), ex); + } + } + + public synchronized void adjustTaskExecutorWorkerCount(int taskType, int newMaxWorkerCount) { + try { + int actualWorkerCount = newMaxWorkerCount; + if (actualWorkerCount == 0) { + actualWorkerCount = autoDecideWorkerCount(); + } + if (taskType == SELECT_TASK_EXECUTOR_TYPE) { + if (actualWorkerCount != this.selectTaskExecutor.getMaximumPoolSize()) { + int queueSize = this.selectTaskQueueSize; + ThreadPoolExecutor newExecutor = + createWorkerThreadPool("Ttl-SelectTaskExecutor", actualWorkerCount, queueSize); + ThreadPoolExecutor oldExecutor = this.selectTaskExecutor; + this.selectTaskExecutor = newExecutor; + if (oldExecutor != null) { + oldExecutor.shutdown(); + } + TtlConfigUtil.setTtlGlobalSelectWorkerCount(newMaxWorkerCount); + } + } else { + + if (actualWorkerCount != this.deleteTaskExecutor.getMaximumPoolSize()) { + int queueSize = this.deleteTaskQueueSize; + ThreadPoolExecutor newExecutor = + createWorkerThreadPool("Ttl-DeleteTaskExecutor", actualWorkerCount, queueSize); + ThreadPoolExecutor oldExecutor = this.deleteTaskExecutor; + this.deleteTaskExecutor = newExecutor; + if (oldExecutor != null) { + oldExecutor.shutdown(); + } + TtlConfigUtil.setTtlGlobalDeleteWorkerCount(newMaxWorkerCount); + } + } + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + logger.warn(ex.getMessage(), ex); + } + } + + private static int autoDecideWorkerCount() { + int dnCount = StorageHaManager.getInstance().getMasterStorageList().size(); + int workerDnRatio = TtlConfigUtil.getTtlGlobalWorkerDnRatio(); + int actualWorkerCount = dnCount * workerDnRatio; + if (actualWorkerCount == 0) { + /** + * For invalid worker count + */ + actualWorkerCount = 4; + } + return actualWorkerCount; + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlIntraTaskManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlIntraTaskManager.java new file mode 100644 index 000000000..72fc60359 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlIntraTaskManager.java @@ -0,0 +1,293 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.ddl.job.task.BaseDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobInterruptedException; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +/** + * @author chenghui.lch + */ +public class TtlIntraTaskManager { + + protected BaseDdlTask parentTask; + protected ExecutionContext ec; + protected TtlWorkerTaskSubmitter taskSubmitter; + protected TtlWorkerTaskMonitor taskMonitor; + protected List> taskFutureInfoList = new ArrayList(); + protected TtlJobContext jobContext; + + public TtlIntraTaskManager(BaseDdlTask ddlTask, + ExecutionContext ec, + TtlJobContext jobContext, + TtlWorkerTaskSubmitter taskSubmitter) { + this.parentTask = ddlTask; + this.ec = ec; + this.jobContext = jobContext; + this.taskSubmitter = taskSubmitter; + } + + public TtlIntraTaskManager(BaseDdlTask ddlTask, + ExecutionContext ec, + TtlJobContext jobContext, + TtlWorkerTaskSubmitter taskSubmitter, + TtlWorkerTaskMonitor taskMonitor) { + this.parentTask = ddlTask; + this.ec = ec; + this.jobContext = jobContext; + this.taskSubmitter = taskSubmitter; + this.taskMonitor = taskMonitor; + } + + public void submitAndRunIntraTasks() { + + /** + * submit a real task on thread-pool to exec + */ + taskFutureInfoList = submitWorkerTasks(); + boolean isInterrupted = false; + boolean needAutoExit = false; + boolean allTaskFinished = false; + boolean withinMaintainableTimeFrame = true; + List allUnexpectedExList = new ArrayList<>(); + while (true) { + + long beginTsNano = System.nanoTime(); + + isInterrupted = ec.getDdlContext().isInterrupted(); + if (isInterrupted) { + doTaskInterrupt(allUnexpectedExList); + statTaskTimeCost(beginTsNano); + break; + } + + /** + * Check if it is in the maintainable time frame + */ + withinMaintainableTimeFrame = checkIfWithinMaintainableTime(); + if (!withinMaintainableTimeFrame) { + doTaskInterrupt(allUnexpectedExList); + statTaskTimeCost(beginTsNano); + break; + } + + if (checkIfAllTaskFinished(false, allUnexpectedExList)) { + allTaskFinished = true; + statTaskTimeCost(beginTsNano); + break; + } + + if (!allUnexpectedExList.isEmpty()) { + /** + * Found some unexpected exceptions + */ + statTaskTimeCost(beginTsNano); + break; + } + + try { + if (taskMonitor != null) { + taskMonitor.doMonitoring(); + needAutoExit = taskMonitor.checkNeedStop(); + if (needAutoExit) { + doTaskInterrupt(allUnexpectedExList); + statTaskTimeCost(beginTsNano); + break; + } + } + + // sleep and wait 1s + Thread.sleep(TtlConfigUtil.getIntraTaskDelegateEachRoundWaitTime()); + statTaskTimeCost(beginTsNano); + } catch (Throwable ex) { + // ignore ex + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + } + } + if (taskMonitor != null) { + this.taskMonitor.handleResults(allTaskFinished, isInterrupted, withinMaintainableTimeFrame); + } + handleIntraTaskResults(isInterrupted, needAutoExit, allUnexpectedExList); + + } + + private void statTaskTimeCost(long beginTsNano) { + TtlJobUtil.statTaskTimeCost(this.jobContext, beginTsNano); + } + + protected List> submitWorkerTasks() { + return taskSubmitter.submitWorkerTasks(); + } + + protected boolean checkIfWithinMaintainableTime() { + return TtlJobUtil.checkIfInTtlMaintainWindow(); + } + + /** + * Interrupt task running + */ + protected void doTaskInterrupt(List allUnexpectedExList) { + /** + * Interrupt all intra tasks + */ + for (int i = 0; i < taskFutureInfoList.size(); i++) { + Pair futureInfo = taskFutureInfoList.get(i); + Future future = futureInfo.getKey(); + TtlIntraTaskRunner runner = futureInfo.getValue(); + runner.notifyStopTask(); + future.cancel(true); + } + checkIfAllTaskFinished(true, allUnexpectedExList); + return; + } + + protected boolean checkIfAllTaskFinished(boolean isForInterrupt, + List allUnexpectedExListOutput) { + int finishCnt = 0; + int maxWaitTime = TtlConfigUtil.getIntraTaskInterruptionMaxWaitTime(); + List unexpectedExceptionList = new ArrayList<>(); + for (int i = 0; i < taskFutureInfoList.size(); i++) { + Future future = taskFutureInfoList.get(i).getKey(); + TtlIntraTaskRunner runner = taskFutureInfoList.get(i).getValue(); + Throwable[] unexpectedEx = new Throwable[1]; + boolean[] waitTimeoutFlag = new boolean[1]; + boolean[] completedFlag = new boolean[1]; + checkIfFutureDone(future, maxWaitTime, completedFlag, waitTimeoutFlag, unexpectedEx); + if (completedFlag[0]) { + finishCnt++; + } else { + if (unexpectedEx[0] != null) { + unexpectedExceptionList.add(unexpectedEx[0]); + } + if (isForInterrupt) { + boolean waitTimeout = waitTimeoutFlag[0]; + if (waitTimeout) { + runner.forceStopTask(); + } + } + } + } + + if (!unexpectedExceptionList.isEmpty() && allUnexpectedExListOutput != null) { + allUnexpectedExListOutput.addAll(unexpectedExceptionList); + } + + if (finishCnt == taskFutureInfoList.size()) { + /** + * All subtask has been finished + */ + return true; + } + + return false; + } + + protected void handleIntraTaskResults(boolean isForInterrupted, + boolean needAutoExit, + List foundUnexpectedExList) { + List taskUnexpectedExList = new ArrayList<>(); + if (foundUnexpectedExList != null && !foundUnexpectedExList.isEmpty()) { + taskUnexpectedExList = foundUnexpectedExList; + } else { + for (int i = 0; i < taskFutureInfoList.size(); i++) { + Future future = taskFutureInfoList.get(i).getKey(); + Throwable[] unexpectedEx = new Throwable[1]; + checkIfFutureDone(future, 0, null, null, unexpectedEx); + if (unexpectedEx[0] != null) { + taskUnexpectedExList.add(unexpectedEx[0]); + } + } + } + + if (!taskUnexpectedExList.isEmpty()) { + Throwable ex = taskUnexpectedExList.get(0); + if (isForInterrupted) { + TtlLoggerUtil.TTL_TASK_LOGGER.info(ex); + } else { + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + } + + if (isForInterrupted) { + if (!needAutoExit) { + /** + * actively throw an ex to make curr job from running to paused + */ + throw new TtlJobRuntimeException(ex, + String.format("Ttl job has been interrupted by some unexpected exception, exMsg is ", + ex.getMessage())); + } + } + } else { + if (isForInterrupted) { + if (!needAutoExit) { + /** + * actively throw an ex to make curr job from running to paused + */ + throw new TtlJobRuntimeException(String.format("Ttl job has been interrupted")); + } + } + + } + } + + protected Object checkIfFutureDone(Future future, + int maxWaitTimeMills, + boolean[] taskCompletedFlag, + boolean[] waitTimeoutFlag, + Throwable[] unexpectedExOutput) { + + Object rs = null; + boolean completed = false; + boolean waitTimeout = false; + if (future.isDone()) { + try { + if (maxWaitTimeMills > 0) { + rs = future.get(maxWaitTimeMills, TimeUnit.MILLISECONDS); + } else { + rs = future.get(); + } + completed = true; + } catch (CancellationException e) { + // if the computation was cancelled + } catch (InterruptedException e) { + // if the current thread was interrupted while waiting + // such as waiting rowsSpeed permits to perform cleaning up + } catch (ExecutionException e) { + // if the computation threw an exception + // collection the unexpected ex + if (unexpectedExOutput != null) { + unexpectedExOutput[0] = e; + } + } catch (TimeoutException e) { + // if the wait timed out + waitTimeout = false; + if (waitTimeoutFlag != null) { + waitTimeoutFlag[0] = waitTimeout; + } + } catch (Throwable e) { + // other ex, such as OutOfMemoryException + // // collection the unexpected ex + if (unexpectedExOutput != null) { + unexpectedExOutput[0] = e; + } + } + } else { + completed = false; + } + + if (taskCompletedFlag != null) { + taskCompletedFlag[0] = completed; + } + return rs; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlIntraTaskRunner.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlIntraTaskRunner.java new file mode 100644 index 000000000..af9687bb3 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlIntraTaskRunner.java @@ -0,0 +1,27 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import java.util.concurrent.Callable; + +/** + * The common base of intra task of ttl + */ +public abstract class TtlIntraTaskRunner implements Callable { + + public TtlIntraTaskRunner() { + } + + public abstract void runTask(); + + public abstract String getDnId(); + + public abstract void notifyStopTask(); + + public abstract void forceStopTask(); + + @Override + public Object call() throws Exception { + runTask(); + return true; + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobContext.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobContext.java new file mode 100644 index 000000000..b3e8d8850 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobContext.java @@ -0,0 +1,264 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +/** + * @author chenghui.lch + */ +@Data +public class TtlJobContext { + + /** + * The definition of ttl_info + */ + protected TtlDefinitionInfo ttlInfo; + + /** + * The current datetime, using the timezone of ttl + * and iso formatter: yyyy-MM-dd HH:mm:ss + */ + protected String currentDateTime; + + /** + * The formated currrent datetime + *
+     * For example,
+     *   current time is 2024-06-26 11:04:56
+     *    if the ttlTimeUnit is YEAR, so the formated current datetime str is : 2024-01-01 00:00:00;
+     *   if the ttlTimeUnit is MONTH, so the formated current datetime str is : 2024-06-01 00:00:00;
+     *   if the ttlTimeUnit is DAY, so the formated current datetime str is : 2024-06-26 00:00:00;
+     *   if the ttlTimeUnit is HOUR, so the formated current datetime str is : 2024-06-26 11:00:00;
+     * 
+ */ + protected String formatedCurrentDateTime; + + /** + * The upper bound string of the expired data to be cleanup + *
+     *     For example:
+     *     T1 is the following, and ttl expired interval 3 months:
+     *          id     ttl_col
+     *          1       2023-01-01
+     *          2       2023-05-01
+     *          3       2023-09-01
+     *          4       2023-11-01
+     *     , now assume that current time is 2024-01-01 00:00:00
+     *     then the  cleanUpUpperBound is
+     *          2024-01-01(now_time) - (3 months, ttl expired interval) = 2023-10-01
+     *      so all the data of ttl_col < '2023-10-01' are expired data
+     *      and can be cleanup.
+     * 
+ */ + protected String cleanUpUpperBound; + + /** + * The lowe bound string of the expired data to be cleanup + *
+     *     For example:
+     *     T1 is the following, and ttl expired interval 3 months:
+     *          id     ttl_col
+     *          1       2023-02-03
+     *          2       2023-05-01
+     *          3       2023-09-01
+     *          4       2023-11-01
+     *     , now assume that current time is 2024-01-01 00:00:00
+     *     then the  cleanUpLowerBound is
+     *          2023-02-01( ttl_col min value after normalizing by the unit month ) + (1 month, ttl_unit is month) = 2023-03-01
+     *      so 2023-03-01 is  the lower bound to be clean up.
+     * 
+ */ + protected String cleanUpLowerBound; + + /** + * The min value of ttl col, maybe null or zero + */ + protected String ttlColMinValue; + + /** + * Label if ttl_col_min_val is null value + */ + protected Boolean ttlColMinValueIsNull = false; + + /** + * Label if ttl_col_min_val is zero value + */ + protected Boolean ttlColMinValueIsZero = false; + + /** + * Label if ttl table is empty table + */ + protected Boolean ttlTblIsEmpty = false; + + /** + * The local index of ttl-col + */ + protected String ttlColIndexName; + + /** + * The force index expr for ttl col, default is "" + *
+     *     if found a local index for ttl col,
+     *     the all the delete/select sql will
+     *     use the force index expr,
+     *     such as FORCE INDEX(idx_xxx)
+     * 
+ */ + protected String ttlColForceIndexExpr = ""; + + /** + * The batch size of insert or delete on ttl_tbl + */ + protected int dmlBatchSize = 1024; + + /** + * The part position of the partition that the ttl_col min value located, start with 1 + */ + protected Integer partPositionForTtlColMinVal; + + /** + * The part name of the partition that the ttl_col min value located + */ + protected String partNameForTtlColMinVal; + + /** + * The bound values of the previous partition of the ttl_col min value + */ + protected String previousPartBoundOfTtlColMinVal; + + /** + * The part position of the partition that the cleanup lower bound located, start with 1 + */ + protected Integer partPositionForCleanupLowerBound; + + /** + * The part name of the partition that the cleanup lower bound located + */ + protected String partNameForCleanupLowerBound; + + /** + * The part position of the partition that the cleanup upper bound located, start with 1 + */ + protected Integer partPositionForCleanupUpperBound; + + /** + * The part name of the partition that the cleanup upper bound located + */ + protected String partNameForCleanupUpperBound; + + /** + * Label if need to sync ttl_tmp tbl because its part state of ttl_tmp is changed + */ + protected Boolean needChangeTtlTmpTblState = false; + + /** + * The auto add missing parts sql of ttl-tmp table + */ + protected String arcTmpTblAddPartsSql; + + /** + * The auto add missing parts sql of archived table + */ + protected String arcTblAddPartsSql; + + /** + * Label if need to add missing parts for ttl-tmp table + */ + protected Boolean needAddPartsForArcTmpTbl = false; + + /** + * Label if a archive task of some partition of curr oss table is running + */ + protected Boolean partitionArchivingRunning = false; + + /** + * The table rows of the whole arc-tmp table + */ + protected Long arcTmpTableRows; + + /** + * The data length of the whole arc-tmp table before running + */ + protected Long arcTmpDataLengthBeforeRunning; + + /** + * Label if change the arcState of the parts of arc_tmp tbl + * between ttlColMinValPartPosition and ttlColCleanupUpperBoundPartPosition + */ + protected Boolean needChangeReusingState = false; + + /** + * New submitted the ready-state / reready-state parts to do oss archiving + */ + protected List newSubmittedArcParts = new ArrayList<>(); + + /** + * Label if current arcTmpTable if stop cleaning up the expired data right now + * because its the disk space of arcTmpTbl has exceeded the disk limit and + * wait the parts between ttlColMinValPartPosition and ttlColCleanupUpperBoundPartPosition + * to perform oss archiving firstly to release disk space. + */ + protected Boolean stopCleaningUpExpiredDataNow = false; + + /** + * Label if need perform optimize-table operation for ttl-table on curr cleaning-up job + */ + protected Boolean needPerformOptiTable = false; + + /** + * The JobId for the new Submitted opti table of curr ttl-job + */ + protected Long newOptiTableDdlJobId = 0L; + + /** + * The data free of the primary of ttl-table + */ + protected Long dataFreeOfTtlTblPrim = 0L; + + /** + * The (data length + index length) of the primary of ttl-table + */ + protected Long ttlTblPrimDataLength = 0L; + + /** + * The max allowed percent of data free of ttl-table + */ + protected BigDecimal dataFreePercentOfTtlTblPrim = new BigDecimal(0); + + /** + * The percentAvg of data free of primary table and gsi table of ttl-table + */ + protected Long dataFreePercentAvgOfTtlTbl = 0L; + + /** + * The row lengthAvg of ttl table, unit: byte + */ + protected Long rowLengthAvgOfTtlTbl = 0L; + + /** + * The completed create ci sql of arcTbl + */ + protected String createColumnarIndexSqlForArcTbl; + + /** + * Use archive policy for dml-trans of ttl-jobs + */ + protected Boolean useArcTrans = Boolean.valueOf(ConnectionParams.TTL_USE_ARCHIVE_TRANS_POLICY.getDefault()); + + public TtlJobContext() { + } + + public static TtlJobContext buildFromTtlInfo(TtlDefinitionInfo ttlInfo) { + TtlJobContext ttlJobContext = new TtlJobContext(); + ttlJobContext.setTtlInfo(ttlInfo); + ttlJobContext.setDmlBatchSize(TtlConfigUtil.getTtlJobDefaultBatchSize()); + ttlJobContext.setUseArcTrans(TtlConfigUtil.isUseArchiveTransPolicy()); + return ttlJobContext; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobPhyPartBitSetUtil.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobPhyPartBitSetUtil.java new file mode 100644 index 000000000..2177389a7 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobPhyPartBitSetUtil.java @@ -0,0 +1,80 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.executor.utils.PartitionMetaUtil; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPrunerUtils; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.BitSet; +import java.util.Set; + +/** + * @author chenghui.lch + */ +public class TtlJobPhyPartBitSetUtil { + + public static void markOnePartAsFinished(Set phyParSet, + PartitionMetaUtil.PartitionMetaRecord partMetaRec) { + int nPartPos = partMetaRec.getPartNum().intValue(); + phyParSet.add(nPartPos); + } + + public static BitSet markOnePartAsFinished(BitSet phyPartBitSet, int nPhyPartPos) { + phyPartBitSet.set(nPhyPartPos, true); + return phyPartBitSet; + } + + public static BitSet markOnePartAsUnFinished(BitSet phyPartBitSet, int nPhyPartPos) { + phyPartBitSet.set(nPhyPartPos, false); + return phyPartBitSet; + } + + public static String bitSetToJsonString(BitSet phyPartBitset) { + ObjectMapper mapper = new ObjectMapper(); + String bitsetJson = null; + try { + bitsetJson = mapper.writeValueAsString(phyPartBitset); + } catch (Exception ex) { + throw new TtlJobRuntimeException(ex, ex.getMessage()); + } + return bitsetJson; + } + + public static BitSet jsonStringToBitSet(String bitSetJson) { + ObjectMapper mapper = new ObjectMapper(); + BitSet deserializedBitSet = null; + try { + deserializedBitSet = mapper.readValue(bitSetJson, BitSet.class); + } catch (Exception ex) { + throw new TtlJobRuntimeException(ex, ex.getMessage()); + } + return deserializedBitSet; + } + + public static String createPartMartBitSetStr(PartitionInfo partInfo) { + BitSet newPhyPartBitSet = PartitionPrunerUtils.buildEmptyPhysicalPartitionsBitSet(partInfo); + String bitSetJson = bitSetToJsonString(newPhyPartBitSet); + return bitSetJson; + } + + public static boolean checkIfFinishCleaningExpiredDataForOnePart(String phyPartBitSetStr, + PartitionMetaUtil.PartitionMetaRecord partMetaRec) { + int nPartPos = partMetaRec.getPartNum().intValue(); + BitSet phyPartBitSet = jsonStringToBitSet(phyPartBitSetStr); + boolean checkRs = phyPartBitSet.get(nPartPos); + return checkRs; + } + + public static BitSet markOnePartAsUnFinished(String phyPartBitSetStr, + PartitionMetaUtil.PartitionMetaRecord partMetaRec) { + int nPartPos = partMetaRec.getPartNum().intValue(); + BitSet phyPartBitSet = jsonStringToBitSet(phyPartBitSetStr); + return markOnePartAsUnFinished(phyPartBitSet, nPartPos); + } + + public static int fetchPhyPartBitSetPosition(PartitionMetaUtil.PartitionMetaRecord partMetaRec) { + return partMetaRec.getPartNum().intValue(); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobTask.java new file mode 100644 index 000000000..1cf671da6 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobTask.java @@ -0,0 +1,10 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +/** + * @author chenghui.lch + */ +interface TtlJobTask { + TtlJobContext getJobContext(); + + void setJobContext(TtlJobContext jobContext); +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobUtil.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobUtil.java new file mode 100644 index 000000000..92bc7f5cb --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlJobUtil.java @@ -0,0 +1,899 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.common.exception.NotSupportException; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.common.utils.timezone.InternalTimeZone; +import com.alibaba.polardbx.common.utils.timezone.TimeZoneUtils; +import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.common.TopologyHandler; +import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler.TtlScheduledJobStatManager; +import com.alibaba.polardbx.executor.ddl.newengine.DdlEngineDagExecutor; +import com.alibaba.polardbx.executor.ddl.newengine.DdlEngineDagExecutorMap; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlJobManager; +import com.alibaba.polardbx.executor.ddl.newengine.serializable.SerializableClassMapper; +import com.alibaba.polardbx.executor.ddl.newengine.utils.TaskHelper; +import com.alibaba.polardbx.executor.utils.PartitionMetaUtil; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.metadb.misc.DdlEngineTaskAccessor; +import com.alibaba.polardbx.gms.metadb.misc.DdlEngineTaskRecord; +import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.server.DefaultServerConfigManager; +import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import com.alibaba.polardbx.optimizer.config.table.IndexMeta; +import com.alibaba.polardbx.optimizer.config.table.IndexType; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; +import com.alibaba.polardbx.optimizer.partition.pruning.PartPrunedResult; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruneStep; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruneStepBuilder; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruner; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPrunerUtils; +import com.alibaba.polardbx.optimizer.partition.pruning.PhysicalPartitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlTimeUnit; +import com.alibaba.polardbx.optimizer.utils.OptimizerHelper; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.jetbrains.annotations.NotNull; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.SQLException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Function; + +/** + * @author chenghui.lch + */ +public class TtlJobUtil { + + /** + * The formatter of ISO_LOCAL_DATE_TIME: yyyy-MM-dd HH:mm:ss + */ + public static final DateTimeFormatter ISO_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + public static List zigzagSortTasks(List taskRunners) { + + Map> dn2RunnersMapping = groupTasksByDnId(taskRunners); + + Map> oldDnGrpItorMapping = + new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + for (Map.Entry> taskItem : dn2RunnersMapping.entrySet()) { + String dnId = taskItem.getKey(); + List queue = taskItem.getValue(); + oldDnGrpItorMapping.put(dnId, queue.iterator()); + } + + List zigzagTaskList = new ArrayList<>(); + while (true) { + if (oldDnGrpItorMapping.isEmpty()) { + break; + } + List dnIdSetWithoutNextRunner = new ArrayList<>(); + for (Map.Entry> taskItem : oldDnGrpItorMapping.entrySet()) { + String dnId = taskItem.getKey(); + Iterator queueItor = taskItem.getValue(); + if (queueItor.hasNext()) { + zigzagTaskList.add(queueItor.next()); + } else { + dnIdSetWithoutNextRunner.add(dnId); + } + } + for (int i = 0; i < dnIdSetWithoutNextRunner.size(); i++) { + oldDnGrpItorMapping.remove(dnIdSetWithoutNextRunner.get(i)); + } + } + return zigzagTaskList; + } + + /** + * Key: dnId + * Val: phyPart runners of same dnId + */ + protected static Map> groupTasksByDnId(List taskRunners) { + + Map> dn2RunnersMapping = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + for (int i = 0; i < taskRunners.size(); i++) { + + TtlIntraTaskRunner runner = taskRunners.get(i); + String dnId = runner.getDnId(); + + List runners = dn2RunnersMapping.get(dnId); + if (runners == null) { + runners = new LinkedList<>(); + dn2RunnersMapping.put(dnId, runners); + } + runners.add(runner); + } + + return dn2RunnersMapping; + } + + public static R wrapWithDistributedTrx(IServerConfigManager serverMgr, + String schemaName, + Map sessionVariables, + Function caller) { + + R result = null; + Object transConn = null; + try { + transConn = serverMgr.getTransConnection(schemaName, sessionVariables); + serverMgr.transConnectionBegin(transConn); + result = caller.apply(transConn); + serverMgr.transConnectionCommit(transConn); + } catch (SQLException ex) { + if (transConn != null) { + try { + serverMgr.transConnectionRollback(transConn); + } catch (Throwable err) { + // ignore + } + } + throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, ex); + } finally { + if (null != transConn) { + try { + serverMgr.closeTransConnection(transConn); + } catch (Throwable ex) { + // ignore + } + } + } + return result; + } + + public static IServerConfigManager getServerConfigManager() { + IServerConfigManager serverConfigManager = OptimizerHelper.getServerConfigManager(); + if (serverConfigManager == null) { + serverConfigManager = new DefaultServerConfigManager(null); + } + return serverConfigManager; + } + + public static int execLogicalDmlOnInnerConnection(IServerConfigManager serverMgr, + String schemaName, + Object transConn, + ExecutionContext ec, + String sql) { + /** + * Set timezone & sql_mode + */ +// serverMgr.executeBackgroundDmlByTransConnection(sql, schemaName, null, transConn); + + /** + * Exec dml + */ + int rows = serverMgr.executeBackgroundDmlByTransConnection(sql, schemaName, null, transConn); + return rows; + } + + public static List> execLogicalQueryOnInnerConnection(IServerConfigManager serverMgr, + String schemaName, + Object transConn, + ExecutionContext ec, + String sql) { + + /** + * Exec query + // */ + List> results = + serverMgr.executeBackgroundQueryByTransConnection(sql, schemaName, null, transConn); + return results; + } + + public static TtlJobContext fetchTtlJobContextFromPreviousTaskByTaskName(Long jobId, + Class previousTaskClass, + String schemaName, + String tableName) { + DdlJobManager jobManager = new DdlJobManager(); + String previousTaskName = SerializableClassMapper.getNameByTaskClass(previousTaskClass); + List prevTasks = jobManager.getTasksFromMetaDB(jobId, previousTaskName); + if (prevTasks.isEmpty()) { + throw new TtlJobRuntimeException( + String.format("No found previous task for %s.%s, task name is %s", schemaName, tableName, + previousTaskName)); + } + assert prevTasks.size() == 1; + AbstractTtlJobTask previousTask = (AbstractTtlJobTask) prevTasks.get(0); + TtlJobContext jobContext = previousTask.getJobContext(); + return jobContext; + } + + public static long updateSubJobTaskIdAndStmtByJobIdAndOldStmt(Long jobId, + String schemaName, + String tableName, + String oldDdlStmt, + Long newSubId, + String newDdlStmt, + String newDdlStmtForRollback, + Connection metaDbConn + ) { + DdlJobManager jobManager = new DdlJobManager(); + String subJobTaskName = SubJobTask.getTaskName(); + List allTasks = jobManager.getTasksFromMetaDB(jobId, subJobTaskName); + + if (allTasks.isEmpty()) { + throw new TtlJobRuntimeException( + String.format("No found any posterior task [oldStmt:%s] for job[%s] of [%s.%s]", oldDdlStmt, jobId, + schemaName, tableName)); + } + + List targetSubJobTasks = new ArrayList<>(); + for (int i = 0; i < allTasks.size(); i++) { + DdlTask task = allTasks.get(i); + String taskName = task.getName(); + if (!taskName.equalsIgnoreCase(SubJobTask.getTaskName())) { + continue; + } + SubJobTask subJobTask = (SubJobTask) task; + String ddlStmt = subJobTask.getDdlStmt(); + if (ddlStmt.equalsIgnoreCase(oldDdlStmt)) { + targetSubJobTasks.add(task); + } + } + + if (targetSubJobTasks.size() != 1) { + throw new TtlJobRuntimeException( + String.format("Invalid to find more than one posterior task [oldStmt:%s] for job[%s] of [%s.%s]", + oldDdlStmt, jobId, + schemaName, tableName)); + } + SubJobTask subJobTask = (SubJobTask) targetSubJobTasks.get(0); + Long targetSubJobTaskId = subJobTask.getTaskId(); + + /** + * Update the mem obj of subjob task of current job + */ + DdlEngineDagExecutor ddlEngineDagExecutorOfCurrJob = DdlEngineDagExecutorMap.get(schemaName, jobId); + DdlJob ddlJob = ddlEngineDagExecutorOfCurrJob.getDdlJob(); + DdlTask targetTask = ddlJob.getTaskById(targetSubJobTaskId); + SubJobTask targetSubJobTask = null; + if (targetTask == null) { + throw new TtlJobRuntimeException( + String.format("No found any posterior subtask [oldStmt:%s] for current jobObj[%s] of [%s.%s]", + oldDdlStmt, jobId, + schemaName, tableName)); + } + if (targetTask instanceof SubJobTask) { + targetSubJobTask = (SubJobTask) targetTask; + if (newSubId != null) { + targetSubJobTask.setSubJobId(newSubId); + } + + if (!StringUtils.isEmpty(newDdlStmt)) { + targetSubJobTask.setDdlStmt(newDdlStmt); + } + if (!StringUtils.isEmpty(newDdlStmtForRollback)) { + targetSubJobTask.setRollbackDdlStmt(newDdlStmtForRollback); + } + } + + /** + * Convert newTask to taskRecord to store into metadb + */ + DdlEngineTaskRecord targetSubJobTaskRecord = TaskHelper.toDdlEngineTaskRecord(targetSubJobTask); + + /** + * Update ddl_engine_task of Metadb by MetaDbConn + */ + DdlEngineTaskAccessor taskAccessor = new DdlEngineTaskAccessor(); + taskAccessor.setConnection(metaDbConn); + taskAccessor.updateTask(targetSubJobTaskRecord); + + return targetSubJobTaskId; + } + + public static List routeTargetPartsOfTtlTmpTblByTtlColVal(ExecutionContext ec, + TableMeta arcTmpTableMeta, + String ttlTimezone, + String ttlColValStr) { + PartitionInfo arcTmpTblPartInfo = arcTmpTableMeta.getPartitionInfo(); + InternalTimeZone internalTimeZone = TimeZoneUtils.convertFromMySqlTZ(ttlTimezone); + ec.setTimeZone(internalTimeZone); + List pointValue = new ArrayList<>(); + pointValue.add(ttlColValStr); + List pointValueOpTypes = new ArrayList<>(); + pointValueOpTypes.add(DataTypes.StringType); + ExecutionContext[] newEcOutput = new ExecutionContext[1]; + RelDataTypeFactory type = PartitionPrunerUtils.getTypeFactory(); + RelDataType tbRelRowType = arcTmpTableMeta.getPhysicalRowType(type); + PartitionPruneStep pruneStep = PartitionPruneStepBuilder.genPointSelectPruneStepInfoForTtlRouting(pointValue, + pointValueOpTypes, ec, newEcOutput, arcTmpTblPartInfo, tbRelRowType); + + PartPrunedResult prunedResult = PartitionPruner.doPruningByStepInfo(pruneStep, newEcOutput[0]); + List phyPartList = prunedResult.getPrunedParttions(); + + return phyPartList; + } + + public static String getLastPartBoundValueStrByTtlTmpTblPartInfo(ExecutionContext ec, + TableMeta arcTmpTableMeta, + String ttlTimezone) { + + PartitionInfo partInfo = arcTmpTableMeta.getPartitionInfo(); + int partCnt = partInfo.getPartitionBy().getPartitions().size(); + + return ""; + } + + public static LocalDateTime plusDeltaIntervals(LocalDateTime normalizedDatetime, + TtlTimeUnit intervalUnit, int intervalCount) { + LocalDateTime result = null; + switch (intervalUnit) { + case YEAR: + result = normalizedDatetime.plusYears(intervalCount); + break; + case MONTH: + result = normalizedDatetime.plusMonths(intervalCount); + break; + case DAY: + result = normalizedDatetime.plusDays(intervalCount); + break; + case HOUR: + result = normalizedDatetime.plusHours(intervalCount); + break; + case MINUTE: + result = normalizedDatetime.plusMinutes(intervalCount); + break; + case SECOND: + result = normalizedDatetime.plusSeconds(intervalCount); + break; + } + return result; + } + + public static String getActualTableNameForArcCci(TableMeta ttlTblMeta, + ExecutionContext ec) { + + TtlDefinitionInfo ttlInfo = ttlTblMeta.getTtlDefinitionInfo(); + String arcTmpTblSchema = ttlInfo.getTmpTableSchema(); + String arcTmpTblName = ttlInfo.getTmpTableName(); + + String actualTblNameOfCci = null; + + Map allPublishedIndexes = ttlTblMeta.getColumnarIndexPublished(); + boolean useGsiInsteadOfCci = TtlConfigUtil.isUseGsiInsteadOfCciForCreateColumnarArcTbl(ec); + if (useGsiInsteadOfCci) { + allPublishedIndexes = ttlTblMeta.getGsiPublished(); + } + + for (Map.Entry gsiIdxItem : allPublishedIndexes.entrySet()) { + String gsiTblName = gsiIdxItem.getKey().toLowerCase(); + GsiMetaManager.GsiIndexMetaBean gsiBean = gsiIdxItem.getValue(); + if (!gsiTblName.startsWith(arcTmpTblName)) { + continue; + } + actualTblNameOfCci = gsiBean.indexName; + break; + } + return actualTblNameOfCci; + } + + public static TableMeta getLatestTableMetaBySchemaNameAndTableName(String schemaName, String tableName) { + return OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(tableName); + } + + public static boolean checkIfArcTmlTableDataLengthExceedLimit(long arcTmpTblDataLength) { + if (arcTmpTblDataLength > TtlConfigUtil.maxTtlTmpTableDataLength) { + return true; + } + return false; + } + + public static long fetchArcTmlTableDataLength(ExecutionContext ec, + TtlJobContext jobContext, + List targetPartNames) { + String arcTmpTblSchema = jobContext.getTtlInfo().getTtlInfoRecord().getArcTmpTblSchema(); + String arcTmpTblName = jobContext.getTtlInfo().getTtlInfoRecord().getArcTmpTblName(); + TopologyHandler topologyHandler = ExecutorContext.getContext(arcTmpTblSchema).getTopologyHandler(); + TableMeta ttlTmpTblTableMeta = + TtlJobUtil.getLatestTableMetaBySchemaNameAndTableName(arcTmpTblSchema, arcTmpTblName); + PartitionInfo ttlTmpTblPartInfo = ttlTmpTblTableMeta.getPartitionInfo(); + Long dataLength = + TtlJobUtil.fetchArcTmpTblPartDataLength(ec, topologyHandler, ttlTmpTblPartInfo, targetPartNames); + return dataLength; + } + + protected static Long fetchArcTmpTblPartDataLength( + ExecutionContext ec, + TopologyHandler topology, + PartitionInfo ttlTmpTblPartInfo, + List targetFirstLevelPartNames + ) { + + Long dataLength = 0L; + Map> phyGrpToPhyTbListMapping = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + Map phyGrpToPhyDbMapping = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + final AtomicLong dataLenOfTtlTmpTbl = new AtomicLong(0); + final AtomicLong tableRowsOfTtlTmpTbl = new AtomicLong(0); + List partSpecList = ttlTmpTblPartInfo.getPartitionBy().getPartitions(); + final String ttlTmpTblSchema = ttlTmpTblPartInfo.getTableSchema(); + final String tblTmpTblName = ttlTmpTblPartInfo.getTableName(); + final Set targetFirstLevelPartNameSet = new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + if (targetFirstLevelPartNames != null) { + for (int i = 0; i < targetFirstLevelPartNames.size(); i++) { + String part = targetFirstLevelPartNames.get(i); + if (!targetFirstLevelPartNameSet.contains(part)) { + targetFirstLevelPartNameSet.add(part); + } + } + } + + for (int k = 0; k < partSpecList.size(); k++) { + PartitionSpec partSpec = partSpecList.get(k); + String partName = partSpec.getName(); + if (targetFirstLevelPartNames != null && !targetFirstLevelPartNameSet.isEmpty()) { + if (!targetFirstLevelPartNameSet.contains(partName)) { + continue; + } + } + List subPartSpecs = partSpec.getSubPartitions(); + for (int i = 0; i < subPartSpecs.size(); i++) { + PartitionSpec subPartSpec = subPartSpecs.get(i); + String grpKey = subPartSpec.getLocation().getGroupKey(); + String phyTb = subPartSpec.getLocation().getPhyTableName(); + String phyDb = phyGrpToPhyDbMapping.get(grpKey); + if (phyDb == null) { + phyDb = PartitionMetaUtil.getPhyDbByGroupName(topology, grpKey); + phyGrpToPhyDbMapping.put(grpKey, phyDb); + } + List phyTbList = phyGrpToPhyTbListMapping.get(grpKey); + if (phyTbList == null) { + phyTbList = new ArrayList<>(); + phyGrpToPhyTbListMapping.put(grpKey, phyTbList); + } + phyTbList.add(phyTb); + } + } + + for (Map.Entry> phyGrpToPhyTbListItem : phyGrpToPhyTbListMapping.entrySet()) { + String grpKey = phyGrpToPhyTbListItem.getKey(); + List phyTbList = phyGrpToPhyTbListItem.getValue(); + String phyDb = phyGrpToPhyDbMapping.get(grpKey); + String querySql = TtlTaskSqlBuilder.buildQueryPhyInfoSchemaTablesByGroup(grpKey, phyDb, phyTbList); + + IServerConfigManager serverConfigManager = TtlJobUtil.getServerConfigManager(); + Map sessionVariables = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + TtlJobUtil.wrapWithDistributedTrx( + serverConfigManager, + ttlTmpTblSchema, + sessionVariables, + (transConn) -> { + + List> queryRs = TtlJobUtil.execLogicalQueryOnInnerConnection( + serverConfigManager, + ttlTmpTblSchema, + transConn, + ec, + querySql); + + if (queryRs.isEmpty()) { + throw new TtlJobRuntimeException( + String.format("No found any stats of [%s.%s] from information_schema", ttlTmpTblSchema, + tblTmpTblName)); + } + + BigDecimal dataLen = + (BigDecimal) queryRs.get(0).get(TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_PARTITION_DATA_LENGTH); + dataLenOfTtlTmpTbl.addAndGet(dataLen.longValue()); + + BigDecimal tableRows = + (BigDecimal) queryRs.get(0).get(TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_PARTITION_TABLE_ROWS); + tableRowsOfTtlTmpTbl.addAndGet(tableRows.longValue()); + + return 0; + } + ); + } + dataLength = dataLenOfTtlTmpTbl.get(); + return dataLength; + + } + + /** + * Fetch the stat info of data free for the ttl table and its gsi tables + */ + public static boolean fetchTtlTableDataFreeStat(ExecutionContext ec, + TtlJobContext jobContext, + TtlTblFullDataFreeInfo[] fullDataFreeInfoOutput) { + String ttlTblSchema = jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + String ttlTblName = jobContext.getTtlInfo().getTtlInfoRecord().getTableName(); + + TableMeta ttlTblMeta = ec.getSchemaManager(ttlTblSchema).getTable(ttlTblName); + boolean isTtlOnAutoDb = DbInfoManager.getInstance().isNewPartitionDb(ttlTblSchema); + TopologyHandler topology = ExecutorContext.getContext(ttlTblSchema).getTopologyHandler(); + + if (fullDataFreeInfoOutput == null) { + return true; + } + + TtlTblFullDataFreeInfo fullDataFreeInfo = new TtlTblFullDataFreeInfo(); + fullDataFreeInfoOutput[0] = fullDataFreeInfo; + + Set gsiNameSet = new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + if (ttlTblMeta.withGsi()) { + gsiNameSet = ttlTblMeta.getGsiPublished().keySet(); + } + TtlTblFullDataFreeInfo.OneTblDataFreeInfo primDfInfo = fullDataFreeInfo.getPrimDataFreeInfo(); + Map gsiDfInfoMap = fullDataFreeInfo.getGsiDataFreeInfoMap(); + + /** + * Fetch dataFreeInfo for primary table + */ + if (isTtlOnAutoDb) { + primDfInfo.setTblMeta(ttlTblMeta); + fullDataFreeInfo.setPrimDataFreeInfo(primDfInfo); + PartitionInfo ttlPartInfo = ttlTblMeta.getPartitionInfo(); + fetchDataLengthAndDataFreeForAutoTtlTbl(ec, topology, ttlPartInfo, primDfInfo); + } else { + // Impl for drds ttl-tbl + throw new NotSupportException(); + } + + if (gsiNameSet.isEmpty()) { + return true; + } + + /** + * Fetch dataFreeInfo for gsi tables + */ + if (isTtlOnAutoDb) { + for (String gsiTblName : gsiNameSet) { + String gsiSchemaName = ttlTblSchema; + TtlTblFullDataFreeInfo.OneTblDataFreeInfo gsiTblDfInfo = + new TtlTblFullDataFreeInfo.OneTblDataFreeInfo(); + TableMeta gsiMeta = ec.getSchemaManager(gsiSchemaName).getTable(gsiTblName); + PartitionInfo gsiPartInfo = gsiMeta.getPartitionInfo(); + gsiTblDfInfo.setTblMeta(gsiMeta); + fetchDataLengthAndDataFreeForAutoTtlTbl(ec, topology, gsiPartInfo, gsiTblDfInfo); + gsiDfInfoMap.put(gsiTblName, gsiTblDfInfo); + } + } else { + // Impl for drds ttl-tbl + throw new NotSupportException(); + } + return true; + } + +// protected static Long fetchDataLengthAndDataFreeForDrdsTtlTbl( +// ExecutionContext ec, +// TopologyHandler topology, +// TableRule tableRule, +// TtlTblFullDataFreeInfo.OneTblDataFreeInfo oneTblDataFreeInfoOutput +// ) { +// /** +// * To impl +// */ +// return null; +// } + + protected static void fetchDataLengthAndDataFreeForAutoTtlTbl( + ExecutionContext ec, + TopologyHandler topology, + PartitionInfo ttlTblPartInfo, + TtlTblFullDataFreeInfo.OneTblDataFreeInfo oneTblDataFreeInfoOutput + ) { + Map> phyGrpToPhyTbListMapping = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + Map phyGrpToPhyDbMapping = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + List phyPartSpecList = ttlTblPartInfo.getPartitionBy().getPhysicalPartitions(); + final String ttlTblSchema = ttlTblPartInfo.getTableSchema(); + final String tblTblName = ttlTblPartInfo.getTableName(); + for (int k = 0; k < phyPartSpecList.size(); k++) { + PartitionSpec phyPartSpec = phyPartSpecList.get(k); + String grpKey = phyPartSpec.getLocation().getGroupKey(); + String phyTb = phyPartSpec.getLocation().getPhyTableName(); + String phyDb = phyGrpToPhyDbMapping.get(grpKey); + if (phyDb == null) { + phyDb = PartitionMetaUtil.getPhyDbByGroupName(topology, grpKey); + phyGrpToPhyDbMapping.put(grpKey, phyDb); + } + List phyTbList = phyGrpToPhyTbListMapping.get(grpKey); + if (phyTbList == null) { + phyTbList = new ArrayList<>(); + phyGrpToPhyTbListMapping.put(grpKey, phyTbList); + } + phyTbList.add(phyTb); + } + + TtlJobUtil.queryAndStateDataLengthAndDataFreeByPhyDbsAndPhyTbs( + ec, + phyGrpToPhyTbListMapping, + phyGrpToPhyDbMapping, + ttlTblSchema, + tblTblName, + oneTblDataFreeInfoOutput); + + return; + + } + + /** + * fetch sum(data_length + index_length)and sum(data_free) from information_schema.tables + * for each phy table + * notice: + *
+     *     here does not use logical information_schema.table_detail to fetch these stat, just for:
+     *     (1) to support both autodb ttl-table and drdsdb ttl-table later;
+     *     (2) More efficient
+     * 
+ */ + @NotNull + private static void queryAndStateDataLengthAndDataFreeByPhyDbsAndPhyTbs( + ExecutionContext ec, + Map> phyGrpToPhyTbListMapping, + Map phyGrpToPhyDbMapping, + String ttlTblSchema, + String tblTblName, + TtlTblFullDataFreeInfo.OneTblDataFreeInfo oneTblDataFreeInfoOutput) { + + for (Map.Entry> phyGrpToPhyTbListItem : phyGrpToPhyTbListMapping.entrySet()) { + String grpKey = phyGrpToPhyTbListItem.getKey(); + List phyTbList = phyGrpToPhyTbListItem.getValue(); + String phyDb = phyGrpToPhyDbMapping.get(grpKey); + String querySql = TtlTaskSqlBuilder.buildQueryPhyDataFreeInfoSchemaTablesByGroup(grpKey, phyDb, phyTbList); + + IServerConfigManager serverConfigManager = TtlJobUtil.getServerConfigManager(); + Map sessionVariables = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + TtlJobUtil.wrapWithDistributedTrx( + serverConfigManager, + ttlTblSchema, + sessionVariables, + (transConn) -> { + + List> queryRs = TtlJobUtil.execLogicalQueryOnInnerConnection( + serverConfigManager, + ttlTblSchema, + transConn, + ec, + querySql); + + if (queryRs.isEmpty()) { + throw new TtlJobRuntimeException( + String.format("No found any stats of [%s.%s] from information_schema", ttlTblSchema, + tblTblName)); + } + + if (oneTblDataFreeInfoOutput != null) { + BigDecimal dataLen = + (BigDecimal) queryRs.get(0) + .get(TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_PARTITION_DATA_LENGTH); + oneTblDataFreeInfoOutput.getDataLength().addAndGet(dataLen.longValue()); + + BigDecimal dataFree = + (BigDecimal) queryRs.get(0).get(TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_PARTITION_DATA_FREE); + oneTblDataFreeInfoOutput.getDataFree().addAndGet(dataFree.longValue()); + + BigDecimal tableRows = + (BigDecimal) queryRs.get(0).get(TtlTaskSqlBuilder.COL_NAME_FOR_SELECT_PARTITION_TABLE_ROWS); + oneTblDataFreeInfoOutput.getTableRows().addAndGet(tableRows.longValue()); + + } + + return 0L; + } + ); + } + } + + /** + *
+     *
+     * Generate the bound list as the following, using the interval of deltaIntervalCount and unit of intervalUnit:
+     * 1. generate the bounds list which  is less than lowerBound( x < lowerBound ), the count is postPartCntForPast;
+     * 2. generate the bounds list which is between lowerBound and upperBound ( lowerBound <= x < upperBound );
+     * 3. generate the bounds list which more than upperBound ( x >= upperBound ); the count is prePartCntForPast;
+     *
+     * 
+ *

+ * General the new range bound list + */ + public static void genRangeBoundListByInterval(String lowerBound, + String upperBound, + int prePartCntForFuture, + int postPartCntForPast, + String ttlTimezone, + Integer arcPartMode, + Integer deltaIntervalCount, + TtlTimeUnit intervalUnit, + List outputPartBoundList, + List outputPartNameList) { + + List newRngBoundList = new ArrayList<>(); + List newRngBoundStrList = new ArrayList<>(); + List newRngPartNameList = new ArrayList<>(); + try { + DateTimeFormatter formatter = TtlJobUtil.ISO_DATETIME_FORMATTER; +// LocalDateTime startTime = LocalDateTime.parse(lowerBound, formatter); + LocalDateTime endTime = LocalDateTime.parse(upperBound, formatter); + + /** + * Prepare the part bound list between the cleanup lower bound and the cleanup upper bound + */ + LocalDateTime newPostBound = endTime; + List newPostRngBoundDescList = new ArrayList<>(); + while (true) { + if (newPostRngBoundDescList.size() >= postPartCntForPast) { + break; + } + newPostRngBoundDescList.add(newPostBound); + newPostBound = TtlJobUtil.plusDeltaIntervals(newPostBound, intervalUnit, -1 * deltaIntervalCount); + } + List newPostRngBoundAscList = new ArrayList<>(); + for (int i = newPostRngBoundDescList.size() - 1; i >= 0; --i) { + newPostRngBoundAscList.add(newPostRngBoundDescList.get(i)); + } + newRngBoundList.addAll(newPostRngBoundAscList); + + /** + * Prepare the previous part bound list according to the cleanup upper bound + */ + LocalDateTime newBound = endTime; + for (int i = 0; i < prePartCntForFuture; i++) { + newBound = TtlJobUtil.plusDeltaIntervals(newBound, intervalUnit, deltaIntervalCount); + newRngBoundList.add(newBound); + } + + for (int i = 0; i < newRngBoundList.size(); i++) { + LocalDateTime partBndVal = newRngBoundList.get(i); + String partBndValStr = partBndVal.format(formatter); + newRngBoundStrList.add(partBndValStr); + } + + LocalDateTime lastPartBndVal = null; + for (int i = 0; i < newRngBoundList.size(); i++) { + LocalDateTime partBndVal = newRngBoundList.get(i); + if (i == 0) { + lastPartBndVal = TtlJobUtil.plusDeltaIntervals(partBndVal, intervalUnit, -1 * deltaIntervalCount); + } else { + lastPartBndVal = newRngBoundList.get(i - 1); + } + String partNameStr = buildPartNameByBoundValue(lastPartBndVal, intervalUnit); + newRngPartNameList.add(partNameStr); + } + + } catch (Throwable ex) { + throw new TtlJobRuntimeException(ex); + } + + if (outputPartBoundList != null) { + outputPartBoundList.addAll(newRngBoundStrList); + } + + if (outputPartNameList != null) { + outputPartNameList.addAll(newRngPartNameList); + } + + return; + } + + protected static String buildPartNameByBoundValue(LocalDateTime partBoundVal, TtlTimeUnit ttlUnit) { + String partNameFormatterPattern = TtlTaskSqlBuilder.getPartNameFormatterPatternByTtlUnit(ttlUnit); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(partNameFormatterPattern); + String partName = "p" + partBoundVal.format(formatter); + return partName; + } + + public static boolean checkNeedPerformOptiTblForTtlTbl(BigDecimal primDfPercent, BigDecimal maxTtlTblDfPercent) { + if (primDfPercent.compareTo(maxTtlTblDfPercent) > 0) { + return true; + } + return false; + } + + public static TtlScheduledJobStatManager.TtlJobStatInfo getTtlJobStatInfoByJobContext(TtlJobContext jobContext) { + String dbName = jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + String tbName = jobContext.getTtlInfo().getTtlInfoRecord().getTableName(); + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = + TtlScheduledJobStatManager.getInstance().getTtlJobStatInfo(dbName, tbName); + return jobStatInfo; + } + + public static void updateJobStage(TtlJobContext jobContext, String stageMsg) { + String dbName = jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + String tbName = jobContext.getTtlInfo().getTtlInfoRecord().getTableName(); + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = TtlScheduledJobStatManager.getInstance() + .getTtlJobStatInfo(dbName, tbName); + jobStatInfo.setCurrJobStage(stageMsg); + } + + public static void statTaskTimeCost(TtlJobContext jobContext, long beginTsNano) { + long endTsNano = System.nanoTime(); + long newTcNano = endTsNano - beginTsNano; + + String dbName = jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + String tbName = jobContext.getTtlInfo().getTtlInfoRecord().getTableName(); + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = TtlScheduledJobStatManager.getInstance() + .getTtlJobStatInfo(dbName, tbName); + TtlScheduledJobStatManager.GlobalTtlJobStatInfo globalStatInfo = + TtlScheduledJobStatManager.getInstance().getGlobalTtlJobStatInfo(); + + long tcMs = newTcNano / 1000000; + jobStatInfo.getCleanupTimeCost().addAndGet(tcMs); + globalStatInfo.getTotalCleanupTimeCost().addAndGet(tcMs); + jobStatInfo.calcCleanupSpeed();// unit: bytes/s + jobStatInfo.calcCleanupRowsSpeed();// unit: rows/s + } + + public static boolean checkIfInTtlMaintainWindow() { + if (TtlConfigUtil.isIgnoreMaintainWindowInTtlJob()) { + return true; + } + return InstConfUtil.isInMaintenanceTimeWindow(); + } + + public static int decidePreBuiltPartCnt(int preBuiltPartCntForFuture, + int ttlInterval, + TtlTimeUnit ttlTimeUnit, + int arcPartInterval, + TtlTimeUnit arcTimeUnit + ) { + /** + * The cleanUpUpperBound = normalizedCurrTime - ttlInterval * ttlUnitVal, + * so normalizedCurrTime <= cleanUpUpperBound + ttlInterval * ttlUnitVal. + * + * but the arcTimeUnit maybe is different from tllUnit. + * so here need convert ttlInterval of ttlUnitVal to new_ttlInterval of arcUnit + * + * but here tllUnit and arcUnit are always the same, + * maybe they are different later. + */ +// int finalPreBuildPartCnt = +// preBuiltPartCntForFuture + ttlInterval + 1;// the "+1" is for included curr-time-value bound +// return finalPreBuildPartCnt; + return preBuiltPartCntForFuture + 1; + } + + public static String buildForceLocalIndexExprForTtlCol(TtlDefinitionInfo ttlInfo, + ExecutionContext ec) { + + String forceIndexExpr = ""; + try { + String tblSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String tblName = ttlInfo.getTtlInfoRecord().getTableName(); + String ttlColName = ttlInfo.getTtlInfoRecord().getTtlCol(); + TableMeta tblMeta = ec.getSchemaManager(tblSchema).getTable(tblName); + List idxMetaList = tblMeta.getIndexes(); + String targetIdxName = ""; + for (int i = 0; i < idxMetaList.size(); i++) { + IndexMeta idxMeta = idxMetaList.get(i); + String idxName = idxMeta.getPhysicalIndexName(); + List keyColList = idxMeta.getKeyColumns(); + if (keyColList.get(0).getName().equalsIgnoreCase(ttlColName)) { + targetIdxName = idxName; + break; + } + } + if (!StringUtils.isEmpty(targetIdxName)) { + forceIndexExpr = String.format("FORCE INDEX(%s)", targetIdxName); + } + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.warn(ex); + } + return forceIndexExpr; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlLoggerUtil.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlLoggerUtil.java new file mode 100644 index 000000000..f12ea7fca --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlLoggerUtil.java @@ -0,0 +1,59 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlJobContext; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.utils.PartitionMetaUtil; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; + +public class TtlLoggerUtil { + // TTL 任务日志 + public final static Logger TTL_TASK_LOGGER = SQLRecorderLogger.ttlTaskLogger; + + public static String buildTaskLogRowMsgPrefix(Long jobId, Long taskId, String name) { + String msgPrefix = String.format("TaskInfoLog-%s-%s-%s: ", jobId, taskId, name); + return msgPrefix; + } + + public static void logTaskMsg(DdlTask parentDdlTask, + TtlJobContext jobContext, + String taskExecRsMsg) { + String logHeader = buildIntraTaskLogMsgHeader(parentDdlTask, jobContext); + StringBuilder sb = new StringBuilder(); + sb.append(logHeader); + sb.append(", FullTaskInfoLog=["); + sb.append(taskExecRsMsg); + sb.append("]"); + TTL_TASK_LOGGER.info(sb.toString()); + } + + public static String buildIntraTaskLogMsgHeader(DdlTask parentDdlTask, + TtlJobContext jobContext) { + Long jobId = parentDdlTask.getJobId(); + Long taskId = parentDdlTask.getTaskId(); + String taskName = parentDdlTask.getName(); + String targetTableSchema = jobContext.getTtlInfo().getTtlInfoRecord().getTableSchema(); + String targetTableName = jobContext.getTtlInfo().getTtlInfoRecord().getTableName(); + String fullTblName = String.format("[%s.%s]", targetTableSchema, targetTableName); + String fullIntraTaskName = String.format("%s[%s,%s]-%s", taskName, jobId, taskId, fullTblName); + String logMsgHeader = + String.format("task=%s", fullIntraTaskName); + return logMsgHeader; + } + + public static String buildIntraTaskLogMsgHeaderWithPhyPart(DdlTask parentDdlTask, + PartitionMetaUtil.PartitionMetaRecord phyPartData) { + Long jobId = parentDdlTask.getJobId(); + Long taskId = parentDdlTask.getTaskId(); + String taskName = parentDdlTask.getName(); +// String fullTblName = String.format("[%s.%s]", phyPartData.getTableSchema(), phyPartData.getTableName()); + String phyPartName = String.format("[%s:%s]", phyPartData.getPartNum(), phyPartData.getPartName()); + String fullIntraTaskName = String.format("%s[%s,%s]-%s", taskName, jobId, taskId, phyPartName); + String fulPhyTblName = + String.format("[%s.%s]", phyPartData.getPhyDb(), phyPartData.getPhyTb()); + String logMsgHeader = + String.format("task=%s, phyTb=%s", fullIntraTaskName, fulPhyTblName); + return logMsgHeader; + } + +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlTaskSqlBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlTaskSqlBuilder.java new file mode 100644 index 000000000..43bfe1fbd --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlTaskSqlBuilder.java @@ -0,0 +1,865 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil; +import com.alibaba.polardbx.optimizer.partition.common.LocalPartitionDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlArchiveKind; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlTimeUnit; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; +import com.alibaba.polardbx.optimizer.utils.SqlIdentifierUtil; +import org.apache.commons.lang.StringUtils; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TtlTaskSqlBuilder { + + protected static final String ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_YEAR = "'%Y-01-01 00:00:00'"; + protected static final String ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_MONTH = "'%Y-%m-01 00:00:00'"; + protected static final String ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_DAY = "'%Y-%m-%d 00:00:00'"; + protected static final String ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_HOUR = "'%Y-%m-%d %H:00:00'"; + protected static final String ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_MINUTE = "'%Y-%m-%d %H:%i:00'"; + protected static final String ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_SECOND = "'%Y-%m-%d %H:%i:%s'"; + + public static final DateTimeFormatter ISO_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + protected static final String PART_NAME_FORMAT_ON_UNIT_YEAR = "yyyy"; + protected static final String PART_NAME_FORMAT_ON_UNIT_MONTH = "yyyyMM"; + protected static final String PART_NAME_FORMAT_ON_UNIT_DAY = "yyyyMMdd"; + protected static final String PART_NAME_FORMAT_ON_UNIT_HOUR = "yyyyMMddtHH"; + protected static final String PART_NAME_FORMAT_ON_UNIT_MINUTE = "yyyyMMddtHHmm"; + protected static final String PART_NAME_FORMAT_ON_UNIT_SECOND = "yyyyMMddtHHmmss"; + + protected static final String SUBJOB_STMT_TEMP = "SElECT '%s';"; + + public static final String COL_NAME_FOR_SELECT_TTL_COL_LOWER_BOUND = "expired_lower_bound"; + public static final String COL_NAME_FOR_SELECT_TTL_COL_UPPER_BOUND = "expired_upper_bound"; + public static final String COL_NAME_FOR_SELECT_TTL_COL_MIN_VALUE = "min_value"; + public static final String COL_NAME_FOR_SELECT_TTL_COL_MIN_VALUE_IS_NULL = "is_null"; + public static final String COL_NAME_FOR_SELECT_TTL_COL_MIN_VALUE_IS_ZERO = "is_zero"; + public static final String COL_NAME_FOR_SELECT_TTL_COL_CURRENT_DATETIME = "current_datetime"; + public static final String COL_NAME_FOR_SELECT_TTL_COL_FORMATED_CURRENT_DATETIME = "formated_current_datetime"; + + public static final String COL_NAME_FOR_SELECT_PARTITION_DATA_FREE = "all_data_free"; + public static final String COL_NAME_FOR_SELECT_PARTITION_DATA_LENGTH = "all_data_length"; + public static final String COL_NAME_FOR_SELECT_PARTITION_TABLE_ROWS = "all_table_rows"; + public static final String COL_NAME_FOR_SELECT_UNIX_TIMESTAMP_FOR_BOUND = "bound_ts"; + + public static final String COL_NAME_FOR_DDL_JOB_ID = "job_id"; + public static final String DDL_FLAG_OF_TTL_JOB = "from ttl job"; + + public static final String ARC_TBL_FIRST_PART_NAME = "pstart"; + public static final String ARC_TBL_MAXVAL_PART_NAME = "pmax"; + public static final String ARC_TBL_FIRST_PART_BOUND = "1970-01-02 00:00:00"; + public static final String ARC_TBL_FIRST_PART_BOUND_FOR_TS = + String.format("UNIX_TIMESTAMP('%s')", ARC_TBL_FIRST_PART_BOUND); + public static final String ARC_TBL_MAXVALUE_BOUND = "MAXVALUE"; + + /** + * The default lower bound for null value or zero value of ttl_col_min_val + */ + public static final String TTL_COL_MIN_VAL_DEFAULT_LOWER_BOUND = "1971-01-01 00:00:00"; + + public static final int MAX_TTL_TMP_NAME_PREFIX_LENGTH = 44; + /** + * arc_tmp name format (maxlen 60):arctmp_(7) + %s(ttl_tbl_prefix,max 44) + _%s(hashvalstr, 9) + */ + public static final String ARC_TMP_NAME_TEMPLATE_WITH_HASHCODE = "arctmp_%s_%s"; + public static final String ARC_TMP_NAME_TEMPLATE_WITHOUT_HASHCODE = "arctmp_%s"; + + /** + * the name format of tg name of arc_tmp (maxlen: 63):tg_(3) + arctmp_%s(60) + */ + private static final String ARC_TMP_TG_NAME_TEMPLATEE = "tg_%s"; + + public static final String ALTER_TABLE_CLEANUP_EXPIRED_DATA_TEMPLATE = + "alter /* from ttl scheduled job */ table `%s`.`%s` cleanup expired data;"; + + public static final String ASYNC_ALTER_TABLE_CLEANUP_EXPIRED_DATA_TEMPLATE = + "/*+TDDL:cmd_extra(ENABLE_ASYNC_DDL=true, PURE_ASYNC_DDL_MODE=true)*/ alter /* from ttl scheduled job */ table `%s`.`%s` cleanup expired data;"; + + public static final String ALTER_TABLE_CLEANUP_EXPIRED_DATA_TEMPLATE_KEYWORD = "cleanup expired data"; + + public static final String ALTER_TABLE_MODIFY_TTL_FOR_BIND_ARCHIVE_TABLE = + "alter table `%s`.`%s` modify ttl set archive_type = '%s', archive_table_schema = '%s', archive_table_name = '%s';"; + + public static final String SELECT_TTL_COL_MIN_VAL_AND_LOWER_BOUND_SQL_TEMP_FORMAT = + "SELECT ttl_col AS min_value, DATE_FORMAT(ttl_col,%s) AS expired_lower_bound, ttl_col is null is_null, ttl_col = '0000-00-00 00:00:00.000000' is_zero FROM (SELECT %s as ttl_col FROM %s.%s %s ORDER BY %s ASC LIMIT 1) as ttl_tbl;"; + + public static final String SELECT_TTL_COL_UPPER_BOUND_SQL_TEMP_FORMAT = + "SELECT %s as current_datetime, DATE_FORMAT( %s, %s ) as formated_current_datetime, DATE_FORMAT( DATE_SUB(%s, INTERVAL %s %s), %s ) as expired_upper_bound;"; + + /** + *

+     * SELECT
+     *  DATE_FORMAT(ttl_col,'%Y-%m-%d') as day,
+     *  COUNT(1) rows_cnt
+     * FROM tbl partition(?)
+     * WHERE ttl_col < ?
+     * GROUP BY day
+     * ORDER BY day asc;
+     * 
+ */ + public static String buildSelectForStatTemplate(TableMeta tableMeta) { + LocalPartitionDefinitionInfo ttlDefInfo = tableMeta.getLocalPartitionDefinitionInfo(); + String ttlCol = ttlDefInfo.getColumnName(); + String tblName = tableMeta.getTableName(); + String dateFormatFuncTemp = "%Y-%m-%d"; + String statSqlProjFormat = String.format("DATE_FORMAT(`%s`,'%s') as day", ttlCol, dateFormatFuncTemp); + + String statSqlTemplateFormat = + "SELECT %s FROM `%s` partition(?) WHERE `%s` < '?' GROUP BY day ORDER BY day ASC"; + String statSqlTemplate = String.format(statSqlTemplateFormat, statSqlProjFormat, tblName, ttlCol); + statSqlTemplate = statSqlTemplate.replace("?", "%s"); + return statSqlTemplate; + } + + public static String buildSelectForStatSql(TableMeta tableMeta, String partName, String expireAfterExprStr) { + LocalPartitionDefinitionInfo ttlDefInfo = tableMeta.getLocalPartitionDefinitionInfo(); + String ttlCol = ttlDefInfo.getColumnName(); + String tblName = tableMeta.getTableName(); + String dateFormatFuncTemp = "%Y-%m-%d"; + String statSqlProjFormat = String.format("DATE_FORMAT(`%s`,'%s') as day", ttlCol, dateFormatFuncTemp); + String statSqlTemplateFormat = + "SELECT %s, count(1) rows_cnt FROM `%s` partition(%s) WHERE `%s` <= '%s' GROUP BY day ORDER BY day ASC"; + String statSqlTemplate = + String.format(statSqlTemplateFormat, statSqlProjFormat, tblName, partName, ttlCol, expireAfterExprStr); + + return statSqlTemplate; + } + + /** + *
+     * SELECT {all_columns_of_pk_and_sk}, ttl_col
+     * FROM {physical_primary_table} FORCE INDEX (xxx)
+     * WHERE (ttl_col) <= (?)
+     *      [ AND  (ttl_col) >= (?) ]
+     * ORDER BY ttl_col ASC
+     * 
+ */ + public static String buildSelectForFetchPkAndSkTemplate(TableMeta tableMeta) { + + LocalPartitionDefinitionInfo ttlDefInfo = tableMeta.getLocalPartitionDefinitionInfo(); + String ttlCol = ttlDefInfo.getColumnName(); + Set pkColSet = tableMeta.getPrimaryKeyMap().keySet(); + List selectCols = new ArrayList<>(); + selectCols.addAll(pkColSet); + selectCols.add(ttlCol); + String tblName = tableMeta.getTableName(); + StringBuilder projectPart = new StringBuilder(""); + for (int i = 0; i < selectCols.size(); i++) { + if (i > 0) { + projectPart.append(","); + } + projectPart.append(selectCols.get(i)); + } + String filterPart = String.format(" %s <= ? AND %s >= ? ", ttlCol, ttlCol); + + String selectSqlTemp = + String.format("SELECT %s FROM %s PARTITION(?) WHERE %s ORDER BY %s ASC LIMIT ?,?;", projectPart, tblName, + filterPart, ttlCol); + selectSqlTemp.replace("?", "%s"); + return selectSqlTemp; + } + + /** + * Select the round-downed upper bound of expired value of ttl_col + *
+     * set TIME_ZONE='xxx';
+     * SELECT
+     *      NOW() as current_datetime,
+     *      DATE_FORMAT( NOW(), formatter ) as formated_current_datetime,
+     *      DATE_FORMAT( DATE_SUB(NOW(), INTERVAL %s %s), formatter ) as expired_upper_bound,
+     * ;
+     * formatter is like %Y-%m-%d 00:00:00.000000
+     * 
+ */ + public static String buildSelectExpiredUpperBoundValueSqlTemplate(TtlDefinitionInfo ttlDefInfo, + ExecutionContext ec) { + + String ttlTblSchema = ttlDefInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlDefInfo.getTtlInfoRecord().getTableName(); + String ttlCol = ttlDefInfo.getTtlInfoRecord().getTtlCol(); + String ttlUnit = TtlTimeUnit.of(ttlDefInfo.getTtlInfoRecord().getTtlUnit()).getTimeUnitName(); + Integer ttlInterval = ttlDefInfo.getTtlInfoRecord().getTtlInterval(); + String formatter = fetchRoundDownFormatter(ec, ttlTblSchema, ttlTblName, ttlCol, ttlUnit); + String nowFunExpr = "NOW()"; + String debugCurrDateTime = ec.getParamManager().getString(ConnectionParams.TTL_DEBUG_CURRENT_DATETIME); + if (!StringUtils.isEmpty(debugCurrDateTime)) { + nowFunExpr = String.format("'%s'", debugCurrDateTime); + } + String selectMinTtlColValueSqlTemp = String.format( + TtlTaskSqlBuilder.SELECT_TTL_COL_UPPER_BOUND_SQL_TEMP_FORMAT, + nowFunExpr, nowFunExpr, formatter, nowFunExpr, ttlInterval, ttlUnit, formatter); + return selectMinTtlColValueSqlTemp; + } + + protected static String fetchRoundDownFormatter(ExecutionContext ec, + String ttlTblSchema, + String ttlTblName, + String ttlCol, + String ttlUnit) { + TableMeta tableMeta = ec.getSchemaManager(ttlTblSchema).getTable(ttlTblName); + ColumnMeta ttlCm = tableMeta.getColumn(ttlCol); + DataType dt = ttlCm.getDataType(); + + boolean containTimeInfo = DataTypeUtil.isFractionalTimeType(dt); +// boolean timezoneDependent = DataTypeUtil.isTimezoneDependentType(dt); + boolean isDateType = DataTypeUtil.isDateType(dt); + boolean isIntType = DataTypeUtil.isUnderBigintUnsignedType(dt); + boolean isStrType = DataTypeUtil.isStringSqlType(dt); + + String formatter = ""; + if (isDateType) { + if (containTimeInfo) { + if (ttlUnit.equalsIgnoreCase(TtlInfoRecord.TTL_UNIT_YEAR)) { + formatter = TtlTaskSqlBuilder.ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_YEAR; + } else if (ttlUnit.equalsIgnoreCase(TtlInfoRecord.TTL_UNIT_MONTH)) { + formatter = TtlTaskSqlBuilder.ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_MONTH; + } else if (ttlUnit.equalsIgnoreCase(TtlInfoRecord.TTL_UNIT_DAY)) { + formatter = TtlTaskSqlBuilder.ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_DAY; + } else if (ttlUnit.equalsIgnoreCase(TtlInfoRecord.TTL_UNIT_HOUR)) { + formatter = TtlTaskSqlBuilder.ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_HOUR; + } else if (ttlUnit.equalsIgnoreCase(TtlInfoRecord.TTL_UNIT_MINUTE)) { + formatter = TtlTaskSqlBuilder.ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_MINUTE; + } else { + formatter = TtlTaskSqlBuilder.ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_SECOND; + } + } else { + formatter = TtlTaskSqlBuilder.ROUND_DOWN_DATETIME_FORMAT_ON_UNIT_DAY; + } + } else { + if (isIntType || isStrType) { + throw new TddlRuntimeException(ErrorCode.ERR_NOT_SUPPORT); + } + } + return formatter; + } + + /** + * Select the min value & lower bound value of ttl_col of ttl_tbl + *
+     * SELECT ttl_col AS min_value, DATE_FORMAT(ttl_col,formatter) AS expired_lower_bound
+     *  FROM (SELECT %s as ttl_col
+     *         FROM [db_name.]ttl_tbl [FORCE INDEX(xxx_ttl_col_idx)]
+     *         ORDER BY %s ASC
+     *         LIMIT 1
+     *       ) as ttl_tbl
+     * 
+ */ + public static String buildSelectExpiredLowerBoundValueBySqlTemplateWithoutConcurrent(TtlDefinitionInfo ttlDefInfo, + ExecutionContext ec, + int mergeUnionSize, + String forceIndexExpr) { + String ttlTblSchema = ttlDefInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlDefInfo.getTtlInfoRecord().getTableName(); + String ttlCol = ttlDefInfo.getTtlInfoRecord().getTtlCol(); + String ttlUnit = TtlTimeUnit.of(ttlDefInfo.getTtlInfoRecord().getTtlUnit()).getTimeUnitName(); + String formatter = fetchRoundDownFormatter(ec, ttlTblSchema, ttlTblName, ttlCol, ttlUnit); + String queryHint = + "/*+TDDL:cmd_extra(MERGE_UNION=true, MERGE_UNION_SIZE=%s, MERGE_CONCURRENT=false, PREFETCH_SHARDS=1, SEQUENTIAL_CONCURRENT_POLICY=true)*/"; + String selectExpiredLownerBoundValueSqlTemp = String.format( + queryHint + TtlTaskSqlBuilder.SELECT_TTL_COL_MIN_VAL_AND_LOWER_BOUND_SQL_TEMP_FORMAT, + mergeUnionSize, formatter, ttlCol, ttlTblSchema, ttlTblName, forceIndexExpr, ttlCol); + return selectExpiredLownerBoundValueSqlTemp; + } + + public static String buildSelectExpiredLowerBoundValueSqlTemplate(TtlDefinitionInfo ttlDefInfo, + ExecutionContext ec, + String queryHint, + String forceIndexExpr) { + String ttlTblSchema = ttlDefInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlDefInfo.getTtlInfoRecord().getTableName(); + String ttlCol = ttlDefInfo.getTtlInfoRecord().getTtlCol(); + String ttlUnit = TtlTimeUnit.of(ttlDefInfo.getTtlInfoRecord().getTtlUnit()).getTimeUnitName(); + String formatter = fetchRoundDownFormatter(ec, ttlTblSchema, ttlTblName, ttlCol, ttlUnit); + String queryHintFormatPart = "%s "; + String selectExpiredLownerBoundValueSqlTemp = String.format( + queryHintFormatPart + TtlTaskSqlBuilder.SELECT_TTL_COL_MIN_VAL_AND_LOWER_BOUND_SQL_TEMP_FORMAT, + queryHint, formatter, ttlCol, ttlTblSchema, ttlTblName, forceIndexExpr, ttlCol); + return selectExpiredLownerBoundValueSqlTemp; + } + + public static String buildInsertSelectTemplate(TtlDefinitionInfo ttlDefInfo, + boolean needAddIntervalLowerBound, + String queryHint) { + String ttlTblSchema = ttlDefInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlDefInfo.getTtlInfoRecord().getTableName(); + + String ttlTmpTblSchema = ttlDefInfo.getTtlInfoRecord().getArcTmpTblSchema(); + String ttlTmpTblName = ttlDefInfo.getTtlInfoRecord().getArcTmpTblName(); + + String ttlCol = ttlDefInfo.getTtlInfoRecord().getTtlCol(); + String filterPart = ""; + if (needAddIntervalLowerBound) { + filterPart = String.format(" %s < '?' and %s >= '?' ", ttlCol, ttlCol); + } else { + filterPart = String.format("( %s < '?' or %s is null)", ttlCol, ttlCol); + } + + String pkColsStr = ""; + List pkColumns = ttlDefInfo.getPkColumns(); + for (int i = 0; i < pkColumns.size(); i++) { + String pkCol = pkColumns.get(i).toLowerCase(); + if (!pkColsStr.isEmpty()) { + pkColsStr += ","; + } + pkColsStr += pkCol; + } + + String insertSelectSqlTemp = String.format( + "%s INSERT INTO `%s`.`%s` SELECT * FROM `%s`.`%s` PARTITION(?) WHERE %s ORDER BY %s,%s ASC LIMIT ?;", + queryHint, ttlTmpTblSchema, ttlTmpTblName, ttlTblSchema, ttlTblName, filterPart, ttlCol, pkColsStr); + String finalInsertSelectSqlTemp = insertSelectSqlTemp.replace("?", "%s"); + return finalInsertSelectSqlTemp; + } + + public static String buildDeleteTemplate(TtlDefinitionInfo ttlDefInfo, + boolean needAddIntervalLowerBound, + String queryHint, + String forceIndexExpr) { + String ttlTblSchema = ttlDefInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlDefInfo.getTtlInfoRecord().getTableName(); + + String ttlCol = ttlDefInfo.getTtlInfoRecord().getTtlCol(); + String filterPart = ""; + + if (needAddIntervalLowerBound) { + filterPart = String.format(" %s < '?' and %s >= '?' ", ttlCol, ttlCol); + } else { + filterPart = String.format(" (%s < '?' or %s is null) ", ttlCol, ttlCol); + } + +// String pkColsStr = ""; +// List pkColumns = ttlDefInfo.getPkColumns(); +// for (int i = 0; i < pkColumns.size(); i++) { +// String pkCol = pkColumns.get(i).toLowerCase(); +// if (!pkColsStr.isEmpty()) { +// pkColsStr += ","; +// } +// pkColsStr += pkCol; +// } + + String deleteSqlTemp = + String.format("%s DELETE FROM `%s`.`%s` PARTITION(?) %s WHERE %s ORDER BY %s ASC LIMIT ?;", + queryHint, ttlTblSchema, ttlTblName, forceIndexExpr, filterPart, ttlCol); + String finalDeleteSqlTemp = deleteSqlTemp.replace("?", "%s"); + return finalDeleteSqlTemp; + } + + public static String buildAddPartitionsSqlTemplate(TtlDefinitionInfo ttlInfo, + List newAddRangeBounds, + List newAddRangePartNames, + String maxValPartName, + String queryHint, + ExecutionContext executionContext) { + + String partBoundDefs = ""; + List normalizedNewAddPartBoundList = + normalizedRangePartBoundValueList(ttlInfo, newAddRangeBounds, executionContext); + for (int i = 0; i < normalizedNewAddPartBoundList.size(); i++) { + String bndStr = normalizedNewAddPartBoundList.get(i); + String partNameStr = newAddRangePartNames.get(i); + String escapedPartName = SqlIdentifierUtil.escapeIdentifierString(partNameStr); + String part = String.format("PARTITION %s VALUES LESS THAN (%s)", escapedPartName, bndStr); + if (!partBoundDefs.isEmpty()) { + partBoundDefs += ",\n"; + } + partBoundDefs += part; + } + String addPartSpecSql = ""; + if (StringUtils.isEmpty(maxValPartName)) { + addPartSpecSql = String.format("ADD PARTITION ( \n%s );", + partBoundDefs); + } else { + addPartSpecSql = String.format("SPLIT PARTITION `%s` INTO ( \n%s, PARTITION `%s` VALUES LESS THAN (MAXVALUE) );", + maxValPartName, partBoundDefs, maxValPartName); + } + + String skipDdlTasks = + executionContext.getParamManager().getString(ConnectionParams.TTL_DEBUG_CCI_SKIP_DDL_TASKS); + if (!StringUtils.isEmpty(skipDdlTasks)) { + queryHint = addCciHint(queryHint, String.format("SKIP_DDL_TASKS=\"%s\"", skipDdlTasks)); + } + +// String addPartSqlTemp = queryHint + " ALTER TABLE %s " + addPartSpecSql; + String addPartSqlTemp = queryHint + " ALTER INDEX %s ON TABLE %s " + addPartSpecSql; + return addPartSqlTemp; + } + + public static String addCciHint(String originalString, String... newParams) { + StringBuilder paramBuilder = new StringBuilder(); + for (String param : newParams) { + if (paramBuilder.length() > 0) { + paramBuilder.append(","); + } + paramBuilder.append(param); + } + String newParam = paramBuilder.toString(); + + // 使用正则表达式替换原始字符串 + Pattern pattern = Pattern.compile("/\\*\\+TDDL:cmd_extra\\((.*?)\\)\\*/"); + Matcher matcher = pattern.matcher(originalString); + if (matcher.find()) { + String existingParams = matcher.group(1); + String modifiedString = originalString.replace(matcher.group(), + "/*+TDDL:cmd_extra(" + existingParams + (existingParams.isEmpty() ? "" : ",") + newParam + ")*/"); + return modifiedString; + } else { + return originalString; + } + } + + public static String buildAddPartitionsByTemplateAndTableName(String ttlSchemaName, + String ttlTblName, + String arcCciIndexName, + String addPartSqlTemp) { + + String dbNameStr = SqlIdentifierUtil.escapeIdentifierString(ttlSchemaName); + String tbNameStr = SqlIdentifierUtil.escapeIdentifierString(ttlTblName); + String cciNameStr = SqlIdentifierUtil.escapeIdentifierString(arcCciIndexName); + String dbAndTb = String.format("%s.%s", dbNameStr, tbNameStr); + String addPartsSql = String.format(addPartSqlTemp, cciNameStr, dbAndTb); + return addPartsSql; + } + + public static String buildPartBoundsSqlTemplateForColumnarIndex(TtlDefinitionInfo ttlInfo, + List newAddRangeBounds, + List newAddRangePartNames, + ExecutionContext executionContext) { + + String ttlColName = ttlInfo.getTtlInfoRecord().getTtlCol(); + String partBoundDefs = ""; + + List newTmpAddRangeBounds = new ArrayList<>(); + newTmpAddRangeBounds.add(TtlTaskSqlBuilder.ARC_TBL_FIRST_PART_BOUND); + newTmpAddRangeBounds.addAll(newAddRangeBounds); + + List newTmpAddRangePartNames = new ArrayList<>(); + newTmpAddRangePartNames.add(TtlTaskSqlBuilder.ARC_TBL_FIRST_PART_NAME); + newTmpAddRangePartNames.addAll(newAddRangePartNames); + + List normalizedNewAddPartBoundList = + normalizedRangePartBoundValueList(ttlInfo, newTmpAddRangeBounds, executionContext); + for (int i = 0; i < normalizedNewAddPartBoundList.size(); i++) { + String bndStr = normalizedNewAddPartBoundList.get(i); + String partNameStr = newTmpAddRangePartNames.get(i); + String escapedPartName = SqlIdentifierUtil.escapeIdentifierString(partNameStr); + String part = String.format("PARTITION %s VALUES LESS THAN (%s)", escapedPartName, bndStr); + if (!partBoundDefs.isEmpty()) { + partBoundDefs += ",\n"; + } + partBoundDefs += part; + } + String partByDefStr = buildPartByDef(ttlInfo, ttlColName, executionContext); + String partBySql = String.format("%s ( %s )", partByDefStr, partBoundDefs); + return partBySql; + } + + protected static String buildPartByDef(TtlDefinitionInfo ttlInfo, String ttlColName, + ExecutionContext executionContext) { + boolean useTsOnTtlCol = ttlInfo.useTimestampOnTtlCol(executionContext); + String partByDefStr = ""; + if (useTsOnTtlCol) { + partByDefStr = String.format("PARTITION BY RANGE (UNIX_TIMESTAMP(`%s`))", ttlColName); + } else { + partByDefStr = String.format("PARTITION BY RANGE COLUMNS(`%s`)", ttlColName); + } + return partByDefStr; + } + + protected static List normalizedRangePartBoundValueList(TtlDefinitionInfo ttlInfo, + List rangeBounds, + ExecutionContext executionContext) { + boolean useTsOnTtlCol = ttlInfo.useTimestampOnTtlCol(executionContext); + String ttlTzStr = ttlInfo.getTtlInfoRecord().getTtlTimezone(); + List result = new ArrayList<>(); + for (int i = 0; i < rangeBounds.size(); i++) { + String bndStr = rangeBounds.get(i); + boolean isMaxValBnd = bndStr.toUpperCase().contains(TtlTaskSqlBuilder.ARC_TBL_MAXVALUE_BOUND); + boolean partBndNeedUseFuncExpr = useTsOnTtlCol; + String normalizedPartBndVal = ""; + if (!isMaxValBnd) { + if (!partBndNeedUseFuncExpr) { + normalizedPartBndVal = String.format("'%s'", bndStr); + } else { + normalizedPartBndVal = convertToUnixTimestampLongStr(bndStr, ttlInfo); + } + } else { + normalizedPartBndVal = bndStr; + } + result.add(normalizedPartBndVal); + } + return result; + } + + public static String convertToUnixTimestampLongStr(String bndStr, + TtlDefinitionInfo ttlInfo) { + String timezoneStr = ttlInfo.getTtlInfoRecord().getTtlTimezone(); + ZoneId zoneId = ZoneId.of(timezoneStr); + LocalDateTime localDateTime = LocalDateTime.parse(bndStr, ISO_DATETIME_FORMATTER); + ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId); + Long unixTs = zonedDateTime.toEpochSecond(); + String unixTsStr = String.valueOf(unixTs); + return unixTsStr; + } + + public static String getPartNameFormatterPatternByTtlUnit(TtlTimeUnit ttlUnit) { + String formatter = null; + + switch (ttlUnit) { + case YEAR: + formatter = TtlTaskSqlBuilder.PART_NAME_FORMAT_ON_UNIT_YEAR; + break; + case MONTH: + formatter = TtlTaskSqlBuilder.PART_NAME_FORMAT_ON_UNIT_MONTH; + break; + case DAY: + formatter = TtlTaskSqlBuilder.PART_NAME_FORMAT_ON_UNIT_DAY; + break; + case HOUR: + formatter = TtlTaskSqlBuilder.PART_NAME_FORMAT_ON_UNIT_HOUR; + break; + case MINUTE: + formatter = TtlTaskSqlBuilder.PART_NAME_FORMAT_ON_UNIT_MINUTE; + break; + case SECOND: + formatter = TtlTaskSqlBuilder.PART_NAME_FORMAT_ON_UNIT_SECOND; + break; + } + return formatter; + } + + public static String buildArchivePartitionSql(String tableSchema, + String tableName, + List targetPartNames, + int ossParallelism) { + String sql = ""; + String dbNameStr = SqlIdentifierUtil.escapeIdentifierString(tableSchema); + String tbNameStr = SqlIdentifierUtil.escapeIdentifierString(tableName); + String partNameListStr = ""; + for (int i = 0; i < targetPartNames.size(); i++) { + if (i > 0) { + partNameListStr += ","; + } + partNameListStr += SqlIdentifierUtil.escapeIdentifierString(targetPartNames.get(i)); + } + sql = String.format( + "/*+TDDL:cmd_extra(ENABLE_ASYNC_DDL=true, PURE_ASYNC_DDL_MODE=true, OSS_BACKFILL_PARALLELISM=%d)*/ALTER TABLE %s.%s ARCHIVE PARTITIONS %s", + ossParallelism, dbNameStr, tbNameStr, partNameListStr); + return sql; + } + + public static final String SUBJOB_NAME_FOR_ADD_PARTS_OF_ARC_TMP_TBL = "SUBJOB_NAME_FOR_ADD_PARTS_OF_ARC_TMP_TBL"; + public static final String SUBJOB_NAME_FOR_ADD_PARTS_OF_OSS_TBL = "SUBJOB_NAME_FOR_ADD_PARTS_OF_OSS_TBL"; + public static final String SUBJOB_NAME_FOR_CREATE_CCI_OF_ARC_TMP = "SUBJOB_NAME_FOR_CREATE_CCI_OF_ARC_TMP"; + public static final String SUBJOB_NAME_FOR_ADD_PARTS_FOR_ARC_TMP_CCI = "SUBJOB_NAME_FOR_ADD_PARTS_FOR_ARC_TMP_CCI"; + + /** + * The SubJobTaskName is used by the pervious tasks of the subjobTask to dynamic modify subjobTask sql + */ + public static String buildSubJobTaskNameForAddPartsBySpecifySubjobStmt(boolean isBuildForArcTable) { + String stmt = ""; + if (isBuildForArcTable) { + stmt = String.format(SUBJOB_STMT_TEMP, SUBJOB_NAME_FOR_ADD_PARTS_OF_OSS_TBL); + } else { + stmt = String.format(SUBJOB_STMT_TEMP, SUBJOB_NAME_FOR_ADD_PARTS_OF_ARC_TMP_TBL); + } + return stmt; + } + + public static String buildSubJobTaskNameForCreateColumnarIndexBySpecifySubjobStmt() { + String stmt = ""; + stmt = String.format(SUBJOB_STMT_TEMP, SUBJOB_NAME_FOR_CREATE_CCI_OF_ARC_TMP); + return stmt; + } + + public static String buildSubJobTaskNameForAddPartsFroActTmpCciBySpecifySubjobStmt() { + String stmt = ""; + stmt = String.format(SUBJOB_STMT_TEMP, SUBJOB_NAME_FOR_ADD_PARTS_FOR_ARC_TMP_CCI); + return stmt; + } + + public static final String STATS_PHY_TTL_TMP_TBL_DATA_LENGTH_BY_GROUP = + "/*TDDL: node='%s'*/select sum(table_rows) all_table_rows, sum(data_length + index_length) all_data_length from information_schema.tables where table_schema='%s' and table_name in (%s)"; + + public static String buildQueryPhyInfoSchemaTablesByGroup(String groupKey, + String phyDb, + List phyTbList) { + StringBuilder phyTbListSb = new StringBuilder(""); + for (int i = 0; i < phyTbList.size(); i++) { + if (i > 0) { + phyTbListSb.append(","); + } + phyTbListSb.append("'"); + phyTbListSb.append(phyTbList.get(i)); + phyTbListSb.append("'"); + } + String phyTbListStr = phyTbListSb.toString(); + String querySql = String.format(STATS_PHY_TTL_TMP_TBL_DATA_LENGTH_BY_GROUP, groupKey, phyDb, phyTbListStr); + return querySql; + } + + public static final String STATS_PHY_TTL_TBL_DATA_FREE_BY_GROUP = + "/*TDDL: node='%s'*/select sum(table_rows) all_table_rows, sum(data_length + index_length) all_data_length, sum(data_free) all_data_free from information_schema.tables where table_schema='%s' and table_name in (%s)"; + + public static String buildQueryPhyDataFreeInfoSchemaTablesByGroup(String groupKey, + String phyDb, + List phyTbList) { + StringBuilder phyTbListSb = new StringBuilder(""); + for (int i = 0; i < phyTbList.size(); i++) { + if (i > 0) { + phyTbListSb.append(","); + } + phyTbListSb.append("'"); + phyTbListSb.append(phyTbList.get(i)); + phyTbListSb.append("'"); + } + String phyTbListStr = phyTbListSb.toString(); + String querySql = String.format(STATS_PHY_TTL_TBL_DATA_FREE_BY_GROUP, groupKey, phyDb, phyTbListStr); + return querySql; + } + + public static String buildAsyncOptimizeTableSql(String tableSchema, + String tableName, + String queryHint) { + String sql = ""; + String dbNameStr = SqlIdentifierUtil.escapeIdentifierString(tableSchema); + String tbNameStr = SqlIdentifierUtil.escapeIdentifierString(tableName); + sql = String.format( + "%s OPTIMIZE TABLE /* from ttl job */ %s.%s", + queryHint, dbNameStr, tbNameStr); + return sql; + } + + public static String buildPauseDdlSql(Long jobId) { + String sql = ""; + sql = String.format( + "PAUSE DDL /* from ttl job */ %s", jobId); + return sql; + } + + public static String buildAsyncContinueDdlSql(Long jobId, int optiTblParallelism) { + String sql = ""; + sql = String.format( + "/*+TDDL:cmd_extra(ENABLE_ASYNC_DDL=true, PURE_ASYNC_DDL_MODE=true, RETURN_JOB_ID_ON_ASYNC_DDL_MODE=true, OPTIMIZE_TABLE_PARALLELISM=%s)*/ CONTINUE DDL /* from ttl job */ %s", + optiTblParallelism, jobId); + return sql; + } + + public static String buildContinueDdlSql(Long jobId) { + String sql = ""; + sql = String.format( + "CONTINUE DDL /* from scheduled ttl job */ %s", jobId); + return sql; + } + + public static String buildAsyncContinueDdlSql(Long jobId) { + String sql = ""; + sql = String.format( + "/*+TDDL:cmd_extra(ENABLE_ASYNC_DDL=true, PURE_ASYNC_DDL_MODE=true, RETURN_JOB_ID_ON_ASYNC_DDL_MODE=true)*/ CONTINUE DDL /* from scheduled ttl job */ %s", + jobId); + return sql; + } + + public static String buildCreateColumnarIndexSqlForArcTbl(TtlDefinitionInfo ttlInfo, + String arcTblSchema, + String arcTblName, + List newAddRangeBounds, + List newAddRangePartNames, + ExecutionContext executionContext) { + + if (TtlConfigUtil.isUseGsiInsteadOfCciForCreateColumnarArcTbl(executionContext)) { + return buildCreateNormalGlobalIndexSqlForArcTbl(ttlInfo, arcTblSchema, arcTblName, newAddRangeBounds, + newAddRangePartNames, executionContext); + } + + String sql = ""; + String ciNameOfArcTbl = TtlUtil.buildArcTmpNameByArcTblName(arcTblName); + String ttlTblName = ttlInfo.getTtlInfoRecord().getTableName(); + String ttlColName = ttlInfo.getTtlInfoRecord().getTtlCol(); + String ciPartByStr = + buildPartBoundsSqlTemplateForColumnarIndex(ttlInfo, newAddRangeBounds, newAddRangePartNames, + executionContext); + + String cciHint = ""; + String skipDdlTasks = + executionContext.getParamManager().getString(ConnectionParams.TTL_DEBUG_CCI_SKIP_DDL_TASKS); + if (!StringUtils.isEmpty(skipDdlTasks)) { + cciHint = String.format("/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS=\"%s\")*/", skipDdlTasks); + } + + sql = String.format("%s create clustered columnar index `%s` on `%s`(`%s`) %s;", + cciHint, ciNameOfArcTbl, ttlTblName, ttlColName, ciPartByStr); + return sql; + } + + public static String buildCreateNormalGlobalIndexSqlForArcTbl(TtlDefinitionInfo ttlInfo, + String arcTblSchema, + String arcTblName, + List newAddRangeBounds, + List newAddRangePartNames, + ExecutionContext executionContext) { + String sql = ""; + String ciNameOfArcTbl = TtlUtil.buildArcTmpNameByArcTblName(arcTblName); + String ttlTblName = ttlInfo.getTtlInfoRecord().getTableName(); + String ttlColName = ttlInfo.getTtlInfoRecord().getTtlCol(); + String ciPartByStr = + buildPartBoundsSqlTemplateForColumnarIndex(ttlInfo, newAddRangeBounds, newAddRangePartNames, + executionContext); +// String arcTmpTgName = buildArcTmpTgName(ttlInfo); +// sql = String.format("create clustered index `%s` on `%s`(`%s`) %s tablegroup=%s;", +// ciNameOfArcTbl, ttlTblName, ttlColName, ciPartByStr, arcTmpTgName); + sql = String.format("create clustered index `%s` on `%s`(`%s`) %s;", + ciNameOfArcTbl, ttlTblName, ttlColName, ciPartByStr); + return sql; + } + + public static String buildDropColumnarIndexSqlForArcTbl(TtlDefinitionInfo ttlInfo, String arcTblSchema, + String arcTblName) { + String sql = ""; + String ciNameOfArcTbl = TtlUtil.buildArcTmpNameByArcTblName(arcTblName); + String ttlTblSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlInfo.getTtlInfoRecord().getTableName(); + sql = String.format("alter table `%s`.`%s` drop index `%s`;", + ttlTblSchema, ttlTblName, ciNameOfArcTbl); + return sql; + } + + public static String buildCreateViewSqlForArcTbl(String arcTblSchema, + String arcTblName, + TtlDefinitionInfo ttlInfo) { + String sql = ""; + String viewSchema = arcTblSchema; + String viewName = arcTblName; + String ttlTblSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlInfo.getTtlInfoRecord().getTableName(); + String ciIndexName = TtlUtil.buildArcTmpNameByArcTblName(arcTblName); + sql = String.format("create or replace view `%s`.`%s` as select * from `%s`.`%s` force index (`%s`);", + viewSchema, viewName, ttlTblSchema, ttlTblName, ciIndexName); + return sql; + } + + public static String buildSqlForFullScanArcTbl(String ttlTblSchema, + String ttlTblName, + String cciIndexName, + List columnMetaList + ) { + String sql = ""; + String colListStr = ""; + for (int i = 0; i < columnMetaList.size(); i++) { + if (i > 0) { + colListStr += ","; + } + ColumnMeta cm = columnMetaList.get(i); + String col = cm.getName(); + String fullColName = String.format("`%s`.`%s`", ttlTblName, col); + colListStr += fullColName; + } + sql = String.format("select %s from `%s`.`%s` force index (`%s`);", + colListStr, ttlTblSchema, ttlTblName, cciIndexName); + return sql; + } + + public static String buildDropViewSqlFroArcTbl(String arcTblSchema, + String arcTblName, + TtlDefinitionInfo ttlInfo) { + String sql = ""; + String viewSchema = arcTblSchema; + String viewName = arcTblName; + String ttlTblSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlInfo.getTtlInfoRecord().getTableName(); + String ciIndexName = ttlInfo.getTtlInfoRecord().getArcTmpTblName(); + sql = String.format("drop view if exists `%s`.`%s`;", + viewSchema, viewName, ttlTblSchema, ttlTblName, ciIndexName); + return sql; + } + + public static String buildModifyTtlSqlForBindArcTbl(String ttlTblSchema, + String ttlTblName, + String arcTblSchema, + String arcTblName, + TtlArchiveKind archiveKind + ) { + + String alterModifyTtlSql = + String.format(ALTER_TABLE_MODIFY_TTL_FOR_BIND_ARCHIVE_TABLE, ttlTblSchema, ttlTblName, + archiveKind.getArchiveKindStr(), + arcTblSchema, arcTblName); + return alterModifyTtlSql; + } + +// public static String buildArcTmpTgName(TtlDefinitionInfo ttlInfo) { +// String tgName = ""; +// String arcTmpTblName = ttlInfo.getTtlInfoRecord().getArcTmpTblName(); +// tgName = String.format(ARC_TMP_TG_NAME_TEMPLATEE, arcTmpTblName); +// return tgName; +// } +// +// public static String buildColumnarTgName(TtlDefinitionInfo ttlInfo) { +// String tgName = ""; +//// tgName = TableGroupNameUtil.autoBuildTableGroupName(tableGroupId, tgType); +// return tgName; +// } +// +// public static String buildCreateArcTmpTgSqlForArcTmp(TtlDefinitionInfo ttlInfo) { +// String sql = ""; +// String arcTmpTgName = buildArcTmpTgName(ttlInfo); +// sql = String.format("create tablegroup if not exists `%s`;", arcTmpTgName); +// return sql; +// } +// +// public static String buildDropArcTmpTgSqlForArcTmp(TtlDefinitionInfo ttlInfo) { +// String sql = ""; +// String arcTmpTgName = buildArcTmpTgName(ttlInfo); +// sql = String.format("drop tablegroup if exists `%s`;", arcTmpTgName); +// return sql; +// } +// public static String buildArcTmpNameByArcTblName(String arcTblName) { +// String finalArcTmpName = ""; +// if (StringUtils.isEmpty(arcTblName)) { +// return finalArcTmpName; +// } +// int length = arcTblName.length(); +// String ttlTmpNamePrefixStr = arcTblName; +// String ttlTblNameHashCodeHexStr = ""; +// if (length > TtlUtil.MAX_TTL_TMP_NAME_PREFIX_LENGTH) { +// ttlTmpNamePrefixStr = arcTblName.substring(0, TtlUtil.MAX_TTL_TMP_NAME_PREFIX_LENGTH); +// ttlTblNameHashCodeHexStr = GroupInfoUtil.doMurmur3Hash32(arcTblName); +// finalArcTmpName = +// String.format(ARC_TMP_NAME_TEMPLATE_WITH_HASHCODE, ttlTmpNamePrefixStr, ttlTblNameHashCodeHexStr); +// } else { +// finalArcTmpName = String.format(ARC_TMP_NAME_TEMPLATE_WITHOUT_HASHCODE, ttlTmpNamePrefixStr); +// } +// finalArcTmpName = finalArcTmpName.toLowerCase(); +// return finalArcTmpName; +// } + + public static String buildTtTableCleanupExpiredDataSql(String ttlTblSchema, String ttlTableName) { + String alterTableCleanupExpiredDataSql = + String.format(ALTER_TABLE_CLEANUP_EXPIRED_DATA_TEMPLATE, ttlTblSchema, ttlTableName); + return alterTableCleanupExpiredDataSql; + } + + public static String buildAsyncTtTableCleanupExpiredDataSql(String ttlTblSchema, String ttlTableName) { + String alterTableCleanupExpiredDataSql = + String.format(ASYNC_ALTER_TABLE_CLEANUP_EXPIRED_DATA_TEMPLATE, ttlTblSchema, ttlTableName); + return alterTableCleanupExpiredDataSql; + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlTblFullDataFreeInfo.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlTblFullDataFreeInfo.java new file mode 100644 index 000000000..12aa13803 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlTblFullDataFreeInfo.java @@ -0,0 +1,80 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import lombok.Data; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicLong; + +/** + * @author chenghui.lch + */ +@Data +public class TtlTblFullDataFreeInfo { + + protected OneTblDataFreeInfo primDataFreeInfo = new OneTblDataFreeInfo(); + protected Map gsiDataFreeInfoMap = + new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + + public TtlTblFullDataFreeInfo() { + } + + public long getDataFreePercentAvg() { + long dataLenSum = primDataFreeInfo.getDataLength().get(); + long dataFreeSum = primDataFreeInfo.getDataFree().get(); + for (Map.Entry dfInfoItem : gsiDataFreeInfoMap.entrySet()) { + OneTblDataFreeInfo dfInfo = dfInfoItem.getValue(); + dataLenSum += dfInfo.getDataLength().get(); + dataFreeSum += dfInfo.getDataFree().get(); + } + if (dataFreeSum == 0) { + return 0; + } + long percentAvg = Math.round(dataFreeSum * 100 / dataLenSum); + return percentAvg; + } + + public long getRowDataLengthAvg() { + long dataLenSum = primDataFreeInfo.getDataLength().get(); + for (Map.Entry dfInfoItem : gsiDataFreeInfoMap.entrySet()) { + OneTblDataFreeInfo dfInfo = dfInfoItem.getValue(); + dataLenSum += dfInfo.getDataLength().get(); + } + long tableRows = primDataFreeInfo.getTableRows().get(); + if (tableRows == 0) { + return 0l; + } + long rowLenAvg = Math.round(dataLenSum / tableRows); + return rowLenAvg; + } + + @Data + public static class OneTblDataFreeInfo { + protected TableMeta tblMeta; + protected AtomicLong dataLength = new AtomicLong(0L); + protected AtomicLong dataFree = new AtomicLong(0L); + protected AtomicLong tableRows = new AtomicLong(0L); + + public OneTblDataFreeInfo() { + } + + public BigDecimal getDataFreePercent() { + if (dataLength.get() == 0) { + return new BigDecimal(0); + } + + BigDecimal dataFreeDec = new BigDecimal(dataFree.get()); + BigDecimal dataLengthDec = new BigDecimal(dataLength.get()); + double dfPercentVal = + dataFreeDec.doubleValue() * 100 / (dataLengthDec.doubleValue() + dataFreeDec.doubleValue()); + BigDecimal dfRatioDec = new BigDecimal(dfPercentVal); + dfRatioDec = dfRatioDec.setScale(2, RoundingMode.HALF_UP); + return dfRatioDec; + } + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlWorkerTaskMonitor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlWorkerTaskMonitor.java new file mode 100644 index 000000000..a41f384e5 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlWorkerTaskMonitor.java @@ -0,0 +1,22 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +public interface TtlWorkerTaskMonitor { + + /** + * Do some monitoring for intra tasks + */ + void doMonitoring(); + + /** + * Check need to stop and exit intra task running. + */ + boolean checkNeedStop(); + + /** + * Handle the results of intra-tasks + */ + void handleResults(boolean isFinished, + boolean interrupted, + boolean withinMaintainableTimeFrame); + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlWorkerTaskSubmitter.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlWorkerTaskSubmitter.java new file mode 100644 index 000000000..a1c7f6073 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/TtlWorkerTaskSubmitter.java @@ -0,0 +1,10 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.common.utils.Pair; + +import java.util.List; +import java.util.concurrent.Future; + +public interface TtlWorkerTaskSubmitter { + List> submitWorkerTasks(); +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/UpdateTtlTmpTablePartStateTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/UpdateTtlTmpTablePartStateTask.java new file mode 100644 index 000000000..cbe9e7c60 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/UpdateTtlTmpTablePartStateTask.java @@ -0,0 +1,64 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.executor.ddl.job.task.BaseGmsTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.executor.ddl.job.task.util.TaskName; +import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import lombok.Getter; + +import java.sql.Connection; +import java.util.List; + +/** + * @author wumu + */ +@Getter +@TaskName(name = "UpdateTtlTmpTablePartStateTask") +public class UpdateTtlTmpTablePartStateTask extends BaseGmsTask { + + protected List partNames; + protected Integer beforeTtlState; + protected Integer newTtlState; + + public UpdateTtlTmpTablePartStateTask(String schemaName, String logicalTableName, List partNames, + Integer beforeTtlState, Integer newTtlState) { + super(schemaName, logicalTableName); + this.beforeTtlState = beforeTtlState; + this.newTtlState = newTtlState; + this.partNames = partNames; + } + + @Override + protected void executeImpl(Connection metaDbConnection, ExecutionContext executionContext) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + try { + if (executionContext.getParamManager().getBoolean(ConnectionParams.CHECK_ARCHIVE_PARTITION_READY)) { + tableInfoManager.updateArcStateByFirstLevelPartitionList(schemaName, logicalTableName, partNames, + beforeTtlState, + newTtlState); + } else { + tableInfoManager.updateArcStateByFirstLevelPartitionList(schemaName, logicalTableName, partNames, + newTtlState); + } + } catch (Exception e) { + throw new TtlJobRuntimeException(e); + } + } + + @Override + protected void rollbackImpl(Connection metaDbConnection, ExecutionContext executionContext) { + TableInfoManager tableInfoManager = new TableInfoManager(); + tableInfoManager.setConnection(metaDbConnection); + + try { + tableInfoManager.updateArcStateByFirstLevelPartitionList(schemaName, logicalTableName, partNames, + beforeTtlState); + } catch (Exception e) { + throw new TtlJobRuntimeException(e); + } + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/exception/TtlJobInterruptedException.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/exception/TtlJobInterruptedException.java new file mode 100644 index 000000000..7f18a2e12 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/exception/TtlJobInterruptedException.java @@ -0,0 +1,17 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl.exception; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; + +/** + * @author chenghui.lch + */ +public class TtlJobInterruptedException extends TddlRuntimeException { + public TtlJobInterruptedException(String... params) { + super(ErrorCode.ERR_TTL_INTERRUPTED, params); + } + + public TtlJobInterruptedException(Throwable ex, String... params) { + super(ErrorCode.ERR_TTL_INTERRUPTED, ex, params); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/exception/TtlJobRuntimeException.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/exception/TtlJobRuntimeException.java new file mode 100644 index 000000000..b37f54b96 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/exception/TtlJobRuntimeException.java @@ -0,0 +1,18 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl.exception; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; + +/** + * @author chenghui.lch + */ +public class TtlJobRuntimeException extends TddlRuntimeException { + + public TtlJobRuntimeException(String... params) { + super(ErrorCode.ERR_TTL, params); + } + + public TtlJobRuntimeException(Throwable ex, String... params) { + super(ErrorCode.ERR_TTL, ex, params); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/scheduler/TtlScheduledJobManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/scheduler/TtlScheduledJobManager.java new file mode 100644 index 000000000..0e5894031 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/scheduler/TtlScheduledJobManager.java @@ -0,0 +1,168 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler; + +import com.alibaba.polardbx.common.model.lifecycle.AbstractLifecycle; +import com.alibaba.polardbx.common.scheduler.FiredScheduledJobState; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.exception.TtlJobRuntimeException; +import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.executor.scheduler.executor.TtlArchivedDataScheduledJob; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.scheduler.ExecutableScheduledJob; +import com.alibaba.polardbx.gms.scheduler.FiredScheduledJobsAccessor; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; + +import java.sql.Connection; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.QUEUED; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.RUNNING; + +/** + * @author chenghui.lch + */ +public class TtlScheduledJobManager extends AbstractLifecycle { + protected static final TtlScheduledJobManager instance = new TtlScheduledJobManager(); + protected volatile FiredTtlJobInfo firedTtlJobInfo = null; + + protected static class FiredTtlJobInfo { + protected List queuedTtlJobListOrderByFireTime = new ArrayList<>(); + protected List runningTtlJobListOrderByFireTime = new ArrayList<>(); + protected Set runningJobTableNameSet = new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + + public FiredTtlJobInfo(List latestQueuedJobs, + List latestRunningJobs) { + this.queuedTtlJobListOrderByFireTime = latestQueuedJobs; + this.runningTtlJobListOrderByFireTime = latestRunningJobs; + for (int i = 0; i < runningTtlJobListOrderByFireTime.size(); i++) { + ExecutableScheduledJob job = runningTtlJobListOrderByFireTime.get(i); + String dbName = job.getTableSchema(); + String tbName = job.getTableName(); + String dbAndTb = buildFullTblName(dbName, tbName); + if (!runningJobTableNameSet.contains(dbAndTb)) { + runningJobTableNameSet.add(dbAndTb); + } + } + } + + public List getQueuedTtlJobListOrderByFireTime() { + return queuedTtlJobListOrderByFireTime; + } + + public List getRunningTtlJobListOrderByFireTime() { + return runningTtlJobListOrderByFireTime; + } + + public Set getRunningJobTableNameSet() { + return runningJobTableNameSet; + } + } + + private static String buildFullTblName(String dbName, String tbName) { + return String.format("%s.%s", dbName, tbName).toLowerCase(); + } + + public static TtlScheduledJobManager getInstance() { + if (!instance.isInited()) { + synchronized (instance) { + if (!instance.isInited()) { + instance.init(); + } + } + } + return instance; + } + + protected TtlScheduledJobManager() { + } + + public synchronized void reloadTtlScheduledJobInfos() { + try (Connection conn = MetaDbDataSource.getInstance().getConnection()) { + FiredScheduledJobsAccessor accessor = new FiredScheduledJobsAccessor(); + accessor.setConnection(conn); + List queuedJobs = accessor.getQueuedTtlJobs(); + List runningJobs = accessor.getRunningTtlJobs(); + FiredTtlJobInfo jobInfo = new FiredTtlJobInfo(queuedJobs, runningJobs); + this.firedTtlJobInfo = jobInfo; + } catch (Throwable ex) { + throw new TtlJobRuntimeException(ex); + } + } + + public boolean updateStateCasWithStartTime(long schedulerId, + long fireTime, + FiredScheduledJobState currentState, + FiredScheduledJobState newState, + long startTime) { + + boolean casSuccess = + ScheduledJobsManager.casStateWithStartTime(schedulerId, fireTime, QUEUED, RUNNING, startTime); + return casSuccess; + } + + /** + * Check if current ttl job allowed to running + */ + public synchronized boolean applyForRunning(TtlArchivedDataScheduledJob job) { + + /** + * Fetch the latest queued ttl jobs and running ttl jobs + */ + reloadTtlScheduledJobInfos(); + + FiredTtlJobInfo firedTtlJobInfo = this.firedTtlJobInfo; + List queuedTtlJobListOrderByFireTime = + firedTtlJobInfo.getQueuedTtlJobListOrderByFireTime(); + List runningTtlJobListOrderByFireTime = + firedTtlJobInfo.getRunningTtlJobListOrderByFireTime(); + + if (queuedTtlJobListOrderByFireTime.isEmpty()) { + /** + * No found target fired jobs + */ + return false; + } + + int maxTtlScheduledJobParallelism = TtlConfigUtil.getTtlScheduledJobMaxParallelism(); + if (runningTtlJobListOrderByFireTime.size() >= maxTtlScheduledJobParallelism) { + return false; + } + + boolean findTargetScheduleId = false; + int emptyJobListSize = maxTtlScheduledJobParallelism - runningTtlJobListOrderByFireTime.size(); + int queuedJobListSize = queuedTtlJobListOrderByFireTime.size(); + int queueSize = Math.min(queuedJobListSize, emptyJobListSize); + for (int i = 0; i < queueSize; i++) { + ExecutableScheduledJob nextQueueJob = queuedTtlJobListOrderByFireTime.get(i); + if (nextQueueJob.getScheduleId() == job.getScheduleId()) { + findTargetScheduleId = true; + break; + } + } + if (!findTargetScheduleId) { + return false; + } + + /** + * Update Ttl Schedule Job State + */ + ExecutableScheduledJob jobRec = job.getExecutableScheduledJob(); + long startTime = ZonedDateTime.now().toEpochSecond(); + updateStateCasWithStartTime(jobRec.getScheduleId(), jobRec.getFireTime(), QUEUED, RUNNING, startTime); + return true; + } + + @Override + protected void doInit() { + super.doInit(); + reloadTtlScheduledJobInfos(); + } + + @Override + protected void doDestroy() { + super.doDestroy(); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/scheduler/TtlScheduledJobStatManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/scheduler/TtlScheduledJobStatManager.java new file mode 100644 index 000000000..c136bafdf --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/task/ttl/scheduler/TtlScheduledJobStatManager.java @@ -0,0 +1,724 @@ +package com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler; + +import com.alibaba.polardbx.common.model.lifecycle.AbstractLifecycle; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.thread.ExecutorUtil; +import com.alibaba.polardbx.common.utils.thread.NamedThreadFactory; +import com.alibaba.polardbx.executor.ddl.newengine.DdlEngineStats; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @author chenbhui.lch + */ +public class TtlScheduledJobStatManager extends AbstractLifecycle { + + protected static final TtlScheduledJobStatManager instance = new TtlScheduledJobStatManager(); + static DdlEngineStats.Metric METRIC_TTL_TOTAL_CLEANUP_TIMECOST = + new DdlEngineStats.Metric("TTL_TOTAL_CLEANUP_TIMECOST"); // unit: ms + static DdlEngineStats.Metric METRIC_TTL_TOTAL_CLEANUP_ROWS = new DdlEngineStats.Metric("TTL_TOTAL_CLEANUP_ROWS"); + // unit: bytes + static DdlEngineStats.Metric METRIC_TTL_TOTAL_CLEANUP_ROWS_SPEED = + new DdlEngineStats.Metric("TTL_TOTAL_CLEANUP_ROWS_SPEED");// unit: rows/s + static DdlEngineStats.Metric METRIC_TTL_TOTAL_CLEANUP_DATA_LENGTH = + new DdlEngineStats.Metric("TTL_TOTAL_CLEANUP_DATA_LENGTH"); + static DdlEngineStats.Metric METRIC_TTL_TOTAL_CLEANUP_SPEED = new DdlEngineStats.Metric("TTL_TOTAL_CLEANUP_SPEED"); +// unit: bytes/rows + + static { + METRIC_TTL_TOTAL_CLEANUP_TIMECOST.setValue(getInstance().getGlobalTtlJobStatInfo().getTotalCleanupTimeCost()); + METRIC_TTL_TOTAL_CLEANUP_ROWS.setValue(getInstance().getGlobalTtlJobStatInfo().getTotalCleanupRows()); + METRIC_TTL_TOTAL_CLEANUP_ROWS_SPEED.setValue( + getInstance().getGlobalTtlJobStatInfo().getTotalCleanupRowsSpeed()); + METRIC_TTL_TOTAL_CLEANUP_DATA_LENGTH.setValue( + getInstance().getGlobalTtlJobStatInfo().getTotalCleanupDataLength()); + METRIC_TTL_TOTAL_CLEANUP_SPEED.setValue(getInstance().getGlobalTtlJobStatInfo().getTotalCleanupSpeed()); + } + + protected final GlobalTtlJobStatInfo globalTtlJobStatInfo; + protected volatile Map> allTtlTblJobStatInfo; + protected ReentrantLock mgrLock; + + protected GlobalJobStatCalculationTask globalJobStatCalculationTask = new GlobalJobStatCalculationTask(); + protected final ScheduledThreadPoolExecutor globalTtlJobStatCalcTaskScheduler = + ExecutorUtil.createScheduler(1, + new NamedThreadFactory("Ttl-Global-Stat-Calc-Scheduler", true), + new ThreadPoolExecutor.DiscardPolicy()); + + protected static class GlobalJobStatCalculationTask implements Runnable { + public GlobalJobStatCalculationTask() { + } + + @Override + public void run() { + TtlScheduledJobStatManager.getInstance().getGlobalTtlJobStatInfo().calcJobStatInfos(); + } + } + +// public void reloadTtlJobStatInfos() { +// +// mgrLock.lock(); +// try(Connection metaConn = MetaDbDataSource.getInstance().getConnection()) { +// TableInfoManager tblInfoMgr = new TableInfoManager(); +// tblInfoMgr.setConnection(metaConn); +// List allTtlInfoRecs = tblInfoMgr.getAllTtlInfoRecords(); +// +// Map newTtlTblRecsMap = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); +// for (int i = 0; i < allTtlInfoRecs.size(); i++) { +// TtlInfoRecord rec = allTtlInfoRecs.get(i); +// String fullTblName = buildFUllTtlTblName(rec.getTableSchema(), rec.getTableName()); +// newTtlTblRecsMap.put(fullTblName, rec); +// } +// +// Map currTtlTblJobStatMap = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); +// for (Map.Entry> itemOfOneDb : allTtlTblJobStatInfo.entrySet()) { +// String dbName = itemOfOneDb.getKey(); +// Map allTtlStatInfoOfOneDb = itemOfOneDb.getValue(); +// for (Map.Entry item : allTtlStatInfoOfOneDb.entrySet()) { +// String tblName = item.getKey(); +// TtlJobStatInfo statInfo = item.getValue(); +// String fullTblName = buildFUllTtlTblName(dbName, tblName); +// currTtlTblJobStatMap.put(fullTblName, statInfo); +// } +// } +// +// /** +// * Remove deleted-ttl-table +// */ +// Map> newAllTtlTblJobStatInfo = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); +// for(Map.Entry statInfoItem : currTtlTblJobStatMap.entrySet()) { +// String fullTblName = statInfoItem.getKey(); +// TtlJobStatInfo statInfo = statInfoItem.getValue(); +// if (newTtlTblRecsMap.containsKey(fullTblName)) { +// String dbName = statInfo.getTableSchema(); +// String tbName = statInfo.getTableName(); +// Map statInfoOfOneDb = newAllTtlTblJobStatInfo.get(dbName); +// if (statInfoOfOneDb == null) { +// statInfoOfOneDb = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); +// newAllTtlTblJobStatInfo.put(dbName, statInfoOfOneDb); +// } +// statInfoOfOneDb.put(tbName, statInfo); +// } +// } +// +// /** +// * Add new-created ttl-table +// */ +// for(Map.Entry recItem : newTtlTblRecsMap.entrySet()) { +// String fullTblName = recItem.getKey(); +// TtlInfoRecord rec = recItem.getValue(); +// if (!currTtlTblJobStatMap.containsKey(fullTblName)) { +// String dbName = rec.getTableSchema(); +// String tbName = rec.getTableName(); +// Map statInfoOfOneDb = newAllTtlTblJobStatInfo.get(dbName); +// if (statInfoOfOneDb == null) { +// statInfoOfOneDb = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); +// newAllTtlTblJobStatInfo.put(dbName, statInfoOfOneDb); +// } +// if (!statInfoOfOneDb.containsKey(tbName)) { +// TtlJobStatInfo statInfo = new TtlJobStatInfo(); +// statInfo.setTableSchema(dbName); +// statInfo.setTableName(tbName); +// statInfoOfOneDb.put(tbName, statInfo); +// } +// } +// } +// this.allTtlTblJobStatInfo = newAllTtlTblJobStatInfo; +// } catch (Throwable ex) { +// TtlLoggerUtil.TTL_TASK_LOGGER.error(ex); +// } finally { +// mgrLock.unlock(); +// } +// } +// protected String buildFUllTtlTblName(String tableSchemaName, String tableName) { +// return String.format("`%s`.`%s`", tableSchemaName, tableName).toLowerCase(); +// } + + protected TtlScheduledJobStatManager() { + mgrLock = new ReentrantLock(); + globalTtlJobStatInfo = new GlobalTtlJobStatInfo(); + allTtlTblJobStatInfo = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + } + + protected static long divIgnoreZero(long a, long b) { + if (b == 0) { + return 0; + } + return a / b; + } + + public static TtlScheduledJobStatManager getInstance() { + if (!instance.isInited()) { + synchronized (instance) { + if (!instance.isInited()) { + instance.init(); + } + } + } + return instance; + } + + public static Map buildGlobalTtlMetrics() { + Map ddlStatsForTtl = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + ddlStatsForTtl.put("TTL_TOTAL_CLEANUP_TIMECOST", METRIC_TTL_TOTAL_CLEANUP_TIMECOST); + ddlStatsForTtl.put("TTL_TOTAL_CLEANUP_ROWS", METRIC_TTL_TOTAL_CLEANUP_ROWS); + ddlStatsForTtl.put("TTL_TOTAL_CLEANUP_ROWS_SPEED", METRIC_TTL_TOTAL_CLEANUP_ROWS_SPEED); + ddlStatsForTtl.put("TTL_TOTAL_CLEANUP_DATA_LENGTH", METRIC_TTL_TOTAL_CLEANUP_DATA_LENGTH); + ddlStatsForTtl.put("TTL_TOTAL_CLEANUP_DATA_LENGTH_SPEED", METRIC_TTL_TOTAL_CLEANUP_SPEED); + return ddlStatsForTtl; + } + + public TtlJobStatInfo getTtlJobStatInfo(String schemaName, String tableName) { + Map allTtlJobStatOfOneDb = this.allTtlTblJobStatInfo.get(schemaName); + if (allTtlJobStatOfOneDb == null) { + return null; + } + return allTtlJobStatOfOneDb.get(tableName); + } + + public Map> getAllTtlJobStatInfos() { + return this.allTtlTblJobStatInfo; + } + + public GlobalTtlJobStatInfo getGlobalTtlJobStatInfo() { + return this.globalTtlJobStatInfo; + } + + public void registerTtlTableIfNeed(String schemaName, String tableName) { + mgrLock.lock(); + try { + Map allTtlJobOfOneDb = this.allTtlTblJobStatInfo.get(schemaName); + if (allTtlJobOfOneDb == null) { + allTtlJobOfOneDb = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + this.allTtlTblJobStatInfo.put(schemaName, allTtlJobOfOneDb); + } + if (!allTtlJobOfOneDb.containsKey(tableName)) { + allTtlJobOfOneDb.put(tableName, new TtlJobStatInfo()); + } + } finally { + mgrLock.unlock(); + } + } + + public void unregisterTtlTableIfNeed(String schemaName, String tableName) { + mgrLock.lock(); + try { + Map allTtlJobOfOneDb = this.allTtlTblJobStatInfo.get(schemaName); + if (allTtlJobOfOneDb != null) { + allTtlJobOfOneDb.remove(tableName); + if (allTtlJobOfOneDb.isEmpty()) { + this.allTtlTblJobStatInfo.remove(schemaName); + } + } + } finally { + mgrLock.unlock(); + } + } + + @Override + protected void doInit() { + super.doInit(); + +// globalTtlJobStatCalcTaskScheduler.scheduleWithFixedDelay( +// globalJobStatCalculationTask, +// 1, +// 5, +// TimeUnit.SECONDS +// ); + } + + @Data + public static class GlobalTtlJobStatInfo { + + protected final AtomicLong totalCleanupTimeCost = new AtomicLong(0L); + protected final AtomicLong totalCleanupDataLength = new AtomicLong(0L); + protected final AtomicLong totalCleanupRows = new AtomicLong(0L); + + protected final AtomicLong totalCleanupRowsSpeed = new AtomicLong(0L); + protected final AtomicLong totalCleanupSpeed = new AtomicLong(0L); + + protected AtomicLong totalSelectSqlCount = new AtomicLong(0L); + protected AtomicLong totalSelectSqlTimeCost = new AtomicLong(0L); + + protected AtomicLong totalDeleteSqlCount = new AtomicLong(0L); + protected AtomicLong totalDeleteSqlTimeCost = new AtomicLong(0L); + + protected AtomicLong totalOptimizeSqlCount = new AtomicLong(0L); + protected AtomicLong totalOptimizeSqlTimeCost = new AtomicLong(0L); + + protected AtomicLong totalAddPartSqlCount = new AtomicLong(0L); + protected AtomicLong totalAddPartSqlTimeCost = new AtomicLong(0L); + + protected AtomicLong totalTtlSuccessJobCount = new AtomicLong(0L); + protected AtomicLong totalTtlPausedJobCount = new AtomicLong(0L); + + protected long lastGlobalStatCalcTs = 0L; + protected long lastTotalCleanupDataLength = 0L; + protected long lastTotalCleanupTimeCost = 0L; + protected long lastTotalCleanupRows = 0L; + + public GlobalTtlJobStatInfo() { + } + + public void calcJobStatInfos() { + long currTotalCleanupDataLength = totalCleanupDataLength.get(); + long currTotalCleanupTimeCost = totalCleanupTimeCost.get(); + long currTotalCleanupRows = totalCleanupRows.get(); + long currGlobalStatCalcTs = System.currentTimeMillis(); + + long deltaDataLength = currTotalCleanupDataLength - lastTotalCleanupDataLength; + long deltaRows = currTotalCleanupRows - lastTotalCleanupRows; + long deltaTimeCast = currTotalCleanupTimeCost - lastTotalCleanupTimeCost; + + long rowsSpeed = divIgnoreZero(deltaRows * 1000, deltaTimeCast); + long dataLenSpeed = divIgnoreZero(deltaDataLength * 1000, deltaTimeCast); + this.totalCleanupRowsSpeed.set(rowsSpeed); + this.totalCleanupSpeed.set(dataLenSpeed); + + this.lastTotalCleanupDataLength = currTotalCleanupDataLength; + this.lastTotalCleanupRows = currTotalCleanupRows; + this.lastTotalCleanupTimeCost = currTotalCleanupTimeCost; + this.lastGlobalStatCalcTs = currGlobalStatCalcTs; + } + + public long calcTotalCleanupAvgRowsSpeed() { + long totalCleanupAvgRowsSpeed = + divIgnoreZero(totalCleanupRows.get() * 1000, totalCleanupTimeCost.get());// unit: Byte/s + return totalCleanupAvgRowsSpeed; + } + + public long calcTotalCleanupRowsSpeed() { + long totalCleanupRowsSpeed = 0L; + Map> allTtlJobStatInfos = + TtlScheduledJobStatManager.getInstance().getAllTtlJobStatInfos(); + for (Map.Entry> jobStatInfosOfOneDbItem : allTtlJobStatInfos.entrySet()) { + Map jobStatInfoOfOneDbVal = jobStatInfosOfOneDbItem.getValue(); + for (Map.Entry jobStatInfoItem : jobStatInfoOfOneDbVal.entrySet()) { + TtlJobStatInfo jobStatInfo = jobStatInfoItem.getValue(); + if (jobStatInfo.getCurrJobStage().equalsIgnoreCase("Finished")) { + continue; + } + long cleanupTimeCostVal = jobStatInfo.getCleanupTimeCost().get();//unit:ms + long cleanupRowsVal = jobStatInfo.getCleanupRows().get(); + long cleanupDataLengthVal = jobStatInfo.getCleanupDataLength().get(); + long cleanupSpeed = divIgnoreZero(cleanupDataLengthVal * 1000, cleanupTimeCostVal);// unit: Byte/s + long cleanupRowsSpeed = divIgnoreZero(cleanupRowsVal * 1000, cleanupTimeCostVal);//unit: rows/s + totalCleanupRowsSpeed += cleanupRowsSpeed; + } + } + return totalCleanupRowsSpeed; + } + + public long calcTotalCleanupSpeed() { + long totalCleanupSpeed = 0L; + Map> allTtlJobStatInfos = + TtlScheduledJobStatManager.getInstance().getAllTtlJobStatInfos(); + for (Map.Entry> jobStatInfosOfOneDbItem : allTtlJobStatInfos.entrySet()) { + Map jobStatInfoOfOneDbVal = jobStatInfosOfOneDbItem.getValue(); + for (Map.Entry jobStatInfoItem : jobStatInfoOfOneDbVal.entrySet()) { + TtlJobStatInfo jobStatInfo = jobStatInfoItem.getValue(); + if (jobStatInfo.getCurrJobStage().equalsIgnoreCase("Finished")) { + continue; + } + long cleanupTimeCostVal = jobStatInfo.getCleanupTimeCost().get();//unit:ms + long cleanupRowsVal = jobStatInfo.getCleanupRows().get(); + long cleanupDataLengthVal = jobStatInfo.getCleanupDataLength().get(); + long cleanupSpeed = divIgnoreZero(cleanupDataLengthVal * 1000, cleanupTimeCostVal);// unit: Byte/s + long cleanupRowsSpeed = divIgnoreZero(cleanupRowsVal * 1000, cleanupTimeCostVal);//unit: rows/s + totalCleanupSpeed += cleanupSpeed; + } + } + return totalCleanupSpeed; + } + + public long calcTotalCleanupAvgSpeed() { + long totalCleanupAvgSpeed = + divIgnoreZero(totalCleanupDataLength.get() * 1000, totalCleanupTimeCost.get());// unit: Byte/s + return totalCleanupAvgSpeed; + } + + public long calcTotalSelectSqlAvgRt() { + long totalSelectSqlAvgRt = + divIgnoreZero(totalSelectSqlTimeCost.get(), totalSelectSqlCount.get());//unit: ms/r + return totalSelectSqlAvgRt; + } + + public long calcTotalDeleteSqlAvgRt() { + long totalDeleteSqlAvgRt = + divIgnoreZero(totalDeleteSqlTimeCost.get(), totalDeleteSqlCount.get());//unit: ms/r + return totalDeleteSqlAvgRt; + } + + public long calcTotalOptimizeSqlAvgRt() { + long totalOptimizeSqlAvgRt = + divIgnoreZero(totalOptimizeSqlTimeCost.get(), totalOptimizeSqlCount.get());//unit: ms/r + return totalOptimizeSqlAvgRt; + } + + public long calcTotalAddPartsSqlAvgRt() { + long totalAddPartSqlAvgRt = + divIgnoreZero(totalAddPartSqlTimeCost.get(), totalAddPartSqlCount.get());//unit: ms/r + return totalAddPartSqlAvgRt; + } + + public List> toMetricInfo() { + List> keyValPairList = new ArrayList>(); + + long totalCleanupTimeCostVal = totalCleanupTimeCost.get();// unit: ms + long totalCleanupDataLengthVal = totalCleanupDataLength.get(); + long totalCleanupRowsVal = totalCleanupRows.get(); + + long totalSelectSqlCountVal = totalSelectSqlCount.get(); + long totalSelectSqlTimeCostVal = totalSelectSqlTimeCost.get();// unit: ms + + long totalDeleteSqlCountVal = totalDeleteSqlCount.get(); + long totalDeleteSqlTimeCostVal = totalDeleteSqlTimeCost.get();// unit: ms + + long totalOptimizeSqlCountVal = totalOptimizeSqlCount.get(); + long totalOptimizeSqlTimeCostVal = totalOptimizeSqlTimeCost.get();// unit: ms + + long totalAddPartSqlCountVal = totalAddPartSqlCount.get(); + long totalAddPartSqlTimeCostVal = totalAddPartSqlTimeCost.get();// unit: ms + + long totalTtlSuccessJobCountVal = totalTtlSuccessJobCount.get(); + long totalTtlPausedJobCountVal = totalTtlPausedJobCount.get(); + + long totalCleanupAvgSpeed = calcTotalCleanupAvgSpeed();// unit: Byte/s + long totalCleanupAvgRowsSpeed = calcTotalCleanupAvgRowsSpeed();//unit: rows/s + + long totalSelectSqlAvgRt = calcTotalSelectSqlAvgRt();//unit: ms/r + long totalDeleteSqlAvgRt = calcTotalDeleteSqlAvgRt();//unit: ms/r + + long totalOptimizeSqlAvgRt = calcTotalOptimizeSqlAvgRt();//unit: ms/r + long totalAddPartSqlAvgRt = calcTotalAddPartsSqlAvgRt();//unit: ms/r + + long totalCleanupRowsSpeed = calcTotalCleanupRowsSpeed(); + long totalCleanupSpeed = calcTotalCleanupSpeed(); + + keyValPairList.add(new Pair<>("TTL_TOTAL_CLEANUP_TIMECOST", String.valueOf(totalCleanupTimeCostVal))); + keyValPairList.add(new Pair<>("TTL_TOTAL_CLEANUP_DATA_LENGTH", String.valueOf(totalCleanupDataLengthVal))); + keyValPairList.add(new Pair<>("TTL_TOTAL_CLEANUP_ROWS", String.valueOf(totalCleanupRowsVal))); + + keyValPairList.add(new Pair<>("TTL_TOTAL_SELECT_SQL_COUNT", String.valueOf(totalSelectSqlCountVal))); + keyValPairList.add(new Pair<>("TTL_TOTAL_SELECT_SQL_TIMECOST", String.valueOf(totalSelectSqlTimeCostVal))); + keyValPairList.add(new Pair<>("TTL_TOTAL_DELETE_SQL_COUNT", String.valueOf(totalDeleteSqlCountVal))); + keyValPairList.add(new Pair<>("TTL_TOTAL_DELETE_SQL_TIMECOST", String.valueOf(totalDeleteSqlTimeCostVal))); + keyValPairList.add(new Pair<>("TTL_TOTAL_OPTIMIZE_SQL_COUNT", String.valueOf(totalOptimizeSqlCountVal))); + keyValPairList.add( + new Pair<>("TTL_TOTAL_OPTIMIZE_SQL_TIMECOST", String.valueOf(totalOptimizeSqlTimeCostVal))); + keyValPairList.add(new Pair<>("TTL_TOTAL_ADD_PART_SQL_COUNT", String.valueOf(totalAddPartSqlCountVal))); + keyValPairList.add( + new Pair<>("TTL_TOTAL_ADD_PART_SQL_TIMECOST", String.valueOf(totalAddPartSqlTimeCostVal))); + keyValPairList.add(new Pair<>("TTL_TOTAL_JOB_SUCCESS_COUNT", String.valueOf(totalTtlSuccessJobCountVal))); + keyValPairList.add(new Pair<>("TTL_TOTAL_JOB_PAUSED_COUNT", String.valueOf(totalTtlPausedJobCountVal))); + + keyValPairList.add(new Pair<>("TTL_TOTAL_CLEANUP_NOW_SPEED", String.valueOf(totalCleanupSpeed))); + keyValPairList.add(new Pair<>("TTL_TOTAL_CLEANUP_NOW_ROWS_SPEED", String.valueOf(totalCleanupRowsSpeed))); + + keyValPairList.add(new Pair<>("TTL_TOTAL_CLEANUP_AVG_SPEED", String.valueOf(totalCleanupAvgSpeed))); + keyValPairList.add( + new Pair<>("TTL_TOTAL_CLEANUP_AVG_ROWS_SPEED", String.valueOf(totalCleanupAvgRowsSpeed))); + + keyValPairList.add(new Pair<>("TTL_TOTAL_SELECT_SQL_AVG_RT", String.valueOf(totalSelectSqlAvgRt))); + keyValPairList.add(new Pair<>("TTL_TOTAL_DELETE_SQL_AVG_RT", String.valueOf(totalDeleteSqlAvgRt))); + keyValPairList.add(new Pair<>("TTL_TOTAL_OPTIMIZE_SQL_AVG_RT", String.valueOf(totalOptimizeSqlAvgRt))); + keyValPairList.add(new Pair<>("TTL_TOTAL_ADD_PART_AVG_RT", String.valueOf(totalAddPartSqlAvgRt))); + + return keyValPairList; + } + } + + @Data + public static class TtlJobStatInfo { + + /** + * //=========== metrics by collated from lass ddl job ========= + */ + protected String scheduledId; + protected String tableSchema; + protected String tableName; + + protected boolean lastJobFromScheduler = false; + protected long lastJobBeginTs = 0; + protected long lastJobEndTs = 0; + protected String lastTtlColMinVal = ""; + protected String lastCleanupBound = ""; + protected String lastCleanupUpperBound = ""; + protected long lastJobDataFreePercent = 0L; + protected long lastSelectSqlAvgRt = 0;//unit: ms + protected long lastDeleteSqlAvgRt = 0;//unit: ms + protected long lastOptimizeSqlAvgRt = 0;//unit: ms + protected long lastAddPartsSqlAvgRt = 0;//unit: ms + protected long lastCleanupTimeCost = 0L;//unit: ms + protected long lastCleanupRows = 0L; + protected long lastCleanupDataLength = 0L; + protected long lastCleanupSpeed = 0;// unit: Byte/s + protected long lastCleanupRowsSpeed = 0;//unit: rows/s + protected BigDecimal lastTtlTblDataFreePercent = new BigDecimal(0);// unit: % + protected long lastAcquirePermitsAvgRtNano = 0;// unit: Nano + + /** + * //=========== metrics by collated from each ddl job ========= + */ + protected String currDataTimeVal = ""; + protected String currTtlColMinVal = ""; + protected String currCleanupBound = ""; + protected String currCleanupUpperBound = ""; + protected String currJobStage = ""; + + protected long currJobBeginTs = 0; + protected long currJobEndTs = 0; + protected long currJobBeginDeletingTs = 0; + protected boolean currJobFromScheduler = false; + protected long currJobDataFreePercent = 0; + protected long currJobDnRowsSpeedLimit = 0; + protected boolean currJobStopByMaintainWindow = false; + + protected AtomicLong cleanupTimeCost = new AtomicLong(0L); + protected AtomicLong cleanupRows = new AtomicLong(0L); + protected AtomicLong cleanupDataLength = new AtomicLong(0L); + protected AtomicLong waitPermitsTimeCostNano = new AtomicLong(0L); + protected AtomicLong acquirePermitsCount = new AtomicLong(0L); + + protected AtomicLong selectSqlCount = new AtomicLong(0L); + protected AtomicLong selectSqlTimeCost = new AtomicLong(0L); + + protected AtomicLong deleteSqlCount = new AtomicLong(0L); + protected AtomicLong deleteSqlTimeCost = new AtomicLong(0L); + + protected AtomicLong optimizeSqlCount = new AtomicLong(0L); + protected AtomicLong optimizeSqlTimeCost = new AtomicLong(0L); + + protected AtomicLong addPartSqlCount = new AtomicLong(0L); + protected AtomicLong addPartSqlTimeCost = new AtomicLong(0L);// ns + + protected AtomicLong cleanedPhyPartCnt = new AtomicLong(0L); + protected AtomicLong totalPhyPartCnt = new AtomicLong(0L); + + /** + * //=========== metrics by computed ========= + */ + protected volatile long cleanupSpeed = 0;// unit: Byte/s + protected volatile long cleanupRowsSpeed = 0;//unit: rows/s + protected volatile long selectSqlAvgRt = 0;//unit: ms + protected volatile long deleteSqlAvgRt = 0;//unit: ms + protected volatile long optimizeSqlAvgRt = 0;//unit: ms + protected volatile long addPartSqlAvgRt = 0;//unit: ms + protected volatile long optimizeTableProgress = 0;// unit: % + protected volatile BigDecimal ttlTblDataFreePercent = new BigDecimal(0);// unit: % + + public TtlJobStatInfo() { + } + + public void resetFinishedJobStatInfo() { + /** + * ==== save stat info as last job ==== + */ + lastJobFromScheduler = currJobFromScheduler; + lastJobBeginTs = currJobBeginTs; + lastJobEndTs = currJobEndTs; + lastTtlColMinVal = currTtlColMinVal; + lastCleanupBound = currCleanupBound; + lastCleanupUpperBound = currCleanupUpperBound; + lastSelectSqlAvgRt = selectSqlAvgRt;//unit: ms + lastDeleteSqlAvgRt = deleteSqlAvgRt;//unit: ms + lastOptimizeSqlAvgRt = optimizeSqlAvgRt;//unit: ms + lastAddPartsSqlAvgRt = addPartSqlAvgRt;//unit: ms + lastCleanupTimeCost = cleanupTimeCost.get();//unit: ms + lastCleanupRows = cleanupRows.get(); + lastCleanupDataLength = cleanupDataLength.get(); + lastCleanupSpeed = cleanupSpeed;// unit: Byte/s + lastCleanupRowsSpeed = cleanupRowsSpeed;//unit: rows/s + lastJobDataFreePercent = currJobDataFreePercent;// unit:%s + lastTtlTblDataFreePercent = ttlTblDataFreePercent;// unit:%s + lastAcquirePermitsAvgRtNano = calcAcquirePermitsAvgRtNano(); + + /** + * ==== reset curr stat info ==== + */ + currDataTimeVal = ""; + currTtlColMinVal = ""; + currCleanupBound = ""; + currCleanupUpperBound = ""; + currJobStage = ""; + + currJobBeginTs = 0; + currJobEndTs = 0; + currJobFromScheduler = false; + currJobDataFreePercent = 0; + + cleanupTimeCost = new AtomicLong(0L); + cleanupRows = new AtomicLong(0L); + cleanupDataLength = new AtomicLong(0L); + + selectSqlCount = new AtomicLong(0L); + selectSqlTimeCost = new AtomicLong(0L); + + deleteSqlCount = new AtomicLong(0L); + deleteSqlTimeCost = new AtomicLong(0L); + + optimizeSqlCount = new AtomicLong(0L); + optimizeSqlTimeCost = new AtomicLong(0L); + + addPartSqlCount = new AtomicLong(0L); + addPartSqlTimeCost = new AtomicLong(0L); + + cleanedPhyPartCnt = new AtomicLong(0L); + totalPhyPartCnt = new AtomicLong(0L); + + acquirePermitsCount = new AtomicLong(0); + waitPermitsTimeCostNano = new AtomicLong(0); + + /** + * //=========== metrics by computed ========= + */ + cleanupSpeed = 0;// unit: Byte/s + cleanupRowsSpeed = 0;//unit: rows/s + selectSqlAvgRt = 0;//unit: ms + deleteSqlAvgRt = 0;//unit: ms + optimizeSqlAvgRt = 0;//unit: ms + addPartSqlAvgRt = 0;//unit: ms + } + + public List> toMetricInfo() { + + long cleanupTimeCostVal = cleanupTimeCost.get();//unit:ms + long cleanupRowsVal = cleanupRows.get(); + long cleanupDataLengthVal = cleanupDataLength.get(); + + long cleanedPhyPartCntVal = cleanedPhyPartCnt.get(); + long totalPhyPartCntVal = totalPhyPartCnt.get(); + + boolean currJobEnableRowsSpeedLimit = TtlConfigUtil.isEnableTtlCleanupRowsSpeedLimit(); + long currJobDnRowsSpeedLimitVal = 0; + if (currJobEnableRowsSpeedLimit) { + currJobDnRowsSpeedLimitVal = TtlConfigUtil.getCleanupRowsSpeedLimitEachDn(); + } + long ttlTblDataFreePercentLimit = TtlConfigUtil.getMaxDataFreePercentOfTtlTable(); + + long cleanupSpeed = calcCleanupSpeed();// unit: Byte/s + long cleanupRowsSpeed = calcCleanupRowsSpeed();//unit: rows/s + long selectSqlAvgRt = calcSelectSqlAvgRt();//unit: ms + long deleteSqlAvgRt = calcDeleteSqlAvgRt();//unit: ms + long optimizeSqlAvgRt = calcOptimizeSqlAvgRt();//unit: ms + long addPartSqlAvgRt = calcAddPartSqlAvgRt();//unit: ms + long currJobPercent = calcCurrJobPercent(); + long acquirePermitsAvgRtNano = calcAcquirePermitsAvgRtNano();//unit: nano + + List> keyValPairList = new ArrayList>(); + + keyValPairList.add(new Pair<>("TTL_CURR_TTL_COL_MIN_VAL", String.valueOf(currTtlColMinVal))); + keyValPairList.add(new Pair<>("TTL_CURR_CLEANUP_BOUND", String.valueOf(currCleanupBound))); + keyValPairList.add(new Pair<>("TTL_CURR_CLEANUP_UPPER_BOUND", String.valueOf(currCleanupUpperBound))); + keyValPairList.add(new Pair<>("TTL_CURR_NEW_DATETIME_VAL", String.valueOf(currDataTimeVal))); + keyValPairList.add(new Pair<>("TTL_CURR_JOB_STAGE", String.valueOf(currJobStage))); + keyValPairList.add(new Pair<>("TTL_CURR_JOB_BEGIN_TS", String.valueOf(currJobBeginTs))); + keyValPairList.add(new Pair<>("TTL_CURR_JOB_END_TS", String.valueOf(currJobEndTs))); + keyValPairList.add(new Pair<>("TTL_CURR_JOB_FROM_SCHEDULER", String.valueOf(currJobFromScheduler))); + keyValPairList.add( + new Pair<>("TTL_CURR_JOB_STOP_BY_MAINTAIN_WINDOW", String.valueOf(currJobStopByMaintainWindow))); + + keyValPairList.add(new Pair<>("TTL_CURR_DN_ROWS_SPEED_LIMIT", String.valueOf(currJobDnRowsSpeedLimitVal))); + keyValPairList.add(new Pair<>("TTL_CURR_CLEANED_PHY_PART_COUNT", String.valueOf(cleanedPhyPartCntVal))); + keyValPairList.add(new Pair<>("TTL_CURR_TOTAL_PHY_PART_COUNT", String.valueOf(totalPhyPartCntVal))); + keyValPairList.add(new Pair<>("TTL_CURR_JOB_PERCENT", String.valueOf(currJobPercent))); + keyValPairList.add( + new Pair<>("TTL_ACQUIRE_PERMITS_AVG_RT_NANO", String.valueOf(acquirePermitsAvgRtNano))); + + keyValPairList.add(new Pair<>("TTL_CURR_CLEANUP_TIMECOST", String.valueOf(cleanupTimeCostVal))); + keyValPairList.add(new Pair<>("TTL_CURR_CLEANUP_ROWS", String.valueOf(cleanupRowsVal))); + keyValPairList.add(new Pair<>("TTL_CURR_CLEANUP_ROWS_SPEED", String.valueOf(cleanupRowsSpeed))); + keyValPairList.add(new Pair<>("TTL_CURR_CLEANUP_DATA_LENGTH", String.valueOf(cleanupDataLengthVal))); + keyValPairList.add(new Pair<>("TTL_CURR_CLEANUP_SPEED", String.valueOf(cleanupSpeed))); + keyValPairList.add(new Pair<>("TTL_CURR_SELECT_SQL_AVG_RT", String.valueOf(selectSqlAvgRt))); + keyValPairList.add(new Pair<>("TTL_CURR_DELETE_SQL_AVG_RT", String.valueOf(deleteSqlAvgRt))); + keyValPairList.add(new Pair<>("TTL_CURR_OPTIMIZE_SQL_AVG_RT", String.valueOf(optimizeSqlAvgRt))); + keyValPairList.add(new Pair<>("TTL_CURR_ADD_PART_AVG_RT", String.valueOf(addPartSqlAvgRt))); + keyValPairList.add( + new Pair<>("TTL_CURR_DATA_FREE_PERCENT_LIMIT", String.valueOf(ttlTblDataFreePercentLimit))); + keyValPairList.add(new Pair<>("TTL_CURR_TTL_TBL_DATA_FREE_PERCENT", String.valueOf(ttlTblDataFreePercent))); + keyValPairList.add(new Pair<>("TTL_CURR_OPTIMIZE_TTL_TBL_PROGRESS", String.valueOf(optimizeTableProgress))); + + keyValPairList.add(new Pair<>("TTL_LAST_JOB_FROM_SCHEDULER", String.valueOf(lastJobFromScheduler))); + keyValPairList.add(new Pair<>("TTL_LAST_TTL_COL_MIN_VAL", String.valueOf(lastTtlColMinVal))); + keyValPairList.add(new Pair<>("TTL_LAST_CLEANUP_BOUND", String.valueOf(lastCleanupBound))); + keyValPairList.add(new Pair<>("TTL_LAST_CLEANUP_UPPER_BOUND", String.valueOf(lastCleanupUpperBound))); + keyValPairList.add(new Pair<>("TTL_LAST_JOB_BEGIN_TS", String.valueOf(lastJobBeginTs))); + keyValPairList.add(new Pair<>("TTL_LAST_JOB_END_TS", String.valueOf(lastJobEndTs))); + keyValPairList.add(new Pair<>("TTL_LAST_SELECT_SQL_AVG_RT", String.valueOf(lastSelectSqlAvgRt))); + keyValPairList.add(new Pair<>("TTL_LAST_DELETE_SQL_AVG_RT", String.valueOf(lastDeleteSqlAvgRt))); + keyValPairList.add(new Pair<>("TTL_LAST_OPTIMIZE_SQL_AVG_RT", String.valueOf(lastOptimizeSqlAvgRt))); + keyValPairList.add(new Pair<>("TTL_LAST_ADD_PARTS_SQL_AVG_RT", String.valueOf(lastAddPartsSqlAvgRt))); + keyValPairList.add(new Pair<>("TTL_LAST_CLEANUP_TIMECOST", String.valueOf(lastCleanupTimeCost))); + keyValPairList.add(new Pair<>("TTL_LAST_CLEANUP_ROWS", String.valueOf(lastCleanupRows))); + keyValPairList.add(new Pair<>("TTL_LAST_CLEANUP_ROWS_SPEED", String.valueOf(lastCleanupRowsSpeed))); + keyValPairList.add(new Pair<>("TTL_LAST_CLEANUP_DATA_LENGTH", String.valueOf(lastCleanupDataLength))); + keyValPairList.add(new Pair<>("TTL_LAST_CLEANUP_SPEED", String.valueOf(lastCleanupSpeed))); + keyValPairList.add( + new Pair<>("TTL_LAST_TTL_TBL_DATA_FREE_PERCENT", String.valueOf(lastTtlTblDataFreePercent))); + + return keyValPairList; + } + + public long calcAddPartSqlAvgRt() { + long addPartSqlAvgRtVal = divIgnoreZero(addPartSqlTimeCost.get(), addPartSqlCount.get()); + return addPartSqlAvgRtVal; + } + + public long calcOptimizeSqlAvgRt() { + long optimizeSqlAvgRtVal = divIgnoreZero(optimizeSqlTimeCost.get(), optimizeSqlCount.get()); + this.optimizeSqlAvgRt = optimizeSqlAvgRtVal; + return optimizeSqlAvgRtVal; + } + + public long calcDeleteSqlAvgRt() { + long deleteSqlAvgRtVal = divIgnoreZero(deleteSqlTimeCost.get(), deleteSqlCount.get()); + this.deleteSqlAvgRt = deleteSqlAvgRtVal; + return deleteSqlAvgRtVal; + } + + public long calcSelectSqlAvgRt() { + long selectSqlAvgRtVal = divIgnoreZero(selectSqlTimeCost.get(), selectSqlCount.get()); + this.selectSqlAvgRt = selectSqlAvgRtVal; + return selectSqlAvgRtVal; + } + + public long calcDeleteRowsSpeed() { + long deleteRowSpeedVal = divIgnoreZero(cleanupRows.get() * 1000, deleteSqlTimeCost.get()); + return deleteRowSpeedVal; + } + + public long calcCleanupRowsSpeed() { + long cleanupRowsSpeedVal = divIgnoreZero(cleanupRows.get() * 1000, cleanupTimeCost.get()); + this.cleanupRowsSpeed = cleanupRowsSpeedVal; + return cleanupRowsSpeedVal; + } + + public long calcCleanupSpeed() { + long cleanupSpeedVal = divIgnoreZero(cleanupDataLength.get() * 1000, cleanupTimeCost.get()); + this.cleanupSpeed = cleanupSpeedVal; + return cleanupSpeedVal; + } + + public long calcCurrJobPercent() { + long currJobPercent = divIgnoreZero(cleanedPhyPartCnt.get() * 100, totalPhyPartCnt.get()); + return currJobPercent; + } + + public long calcAcquirePermitsAvgRtNano() { + long currJobPercent = divIgnoreZero(waitPermitsTimeCostNano.get(), acquirePermitsCount.get()); + return currJobPercent; + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/GsiValidator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/GsiValidator.java index b0db16c7a..bfd2db199 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/GsiValidator.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/GsiValidator.java @@ -27,10 +27,14 @@ import com.alibaba.polardbx.gms.metadb.table.IndexStatus; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import com.alibaba.polardbx.optimizer.config.table.GsiUtils; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; import com.alibaba.polardbx.rule.TableRule; import org.apache.commons.lang3.StringUtils; @@ -167,6 +171,18 @@ public static void validateAllowRenameOnTable(String schemaName, } } + if (canRename) { + String gsiName = tableName; + GsiMetaManager.GsiMetaBean gsiMetaBean = + ExecutorContext.getContext(schemaName).getGsiManager().getGsiMetaManager() + .getTableAndIndexMeta(schemaName, tableName, IndexStatus.ALL); + String primaryTblName = gsiMetaBean.getIndexTableRelation().get(tableName); + if (TtlUtil.checkIfArchiveCciOfTtlTable(schemaName, primaryTblName, gsiName, executionContext)) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, + String.format("Renaming columnar index `%s` of archive table is not allowed", tableName)); + } + } + if (!canRename) { throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_MODIFY_GSI_TABLE_WITH_DDL, tableName); @@ -192,4 +208,18 @@ public static void validateAllowTruncateOnTable(String schemaName, } } + public static void validateIfDroppingCciOfArcTableOfTtlTable(String tableSchema, + String tableName, + String indexName, + ExecutionContext ec) { + + if (!TtlUtil.checkIfDropCciOfArcTblView(tableSchema, tableName, indexName, ec)) { + return; + } + + throw new TddlRuntimeException(ErrorCode.ERR_TTL, + String.format("Dropping a columnar index `%s` of archive data of table `%s`.`%s` is not allowed.", + indexName, tableSchema, tableName)); + } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/IndexValidator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/IndexValidator.java index 19e643e7e..c9e42ce30 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/IndexValidator.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/IndexValidator.java @@ -91,6 +91,7 @@ public static void validateIndexNameLength(String indexName) { } public static void validateIndexExistence(String schemaName, String logicalTableName, String indexName) { + indexName = TddlSqlToRelConverter.unwrapGsiName(indexName); if (!checkIfIndexExists(schemaName, logicalTableName, indexName)) { throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, "Index '" + indexName + "' on table '" + logicalTableName + "' doesn't exist"); @@ -98,6 +99,7 @@ public static void validateIndexExistence(String schemaName, String logicalTable } public static void validateIndexNonExistence(String schemaName, String logicalTableName, String indexName) { + indexName = TddlSqlToRelConverter.unwrapGsiName(indexName); if (checkIfIndexExists(schemaName, logicalTableName, indexName)) { throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, "Index '" + indexName + "' on table '" + logicalTableName + "' already exists"); @@ -124,13 +126,25 @@ public static void validateDropPrimaryKey(String indexName) { } } + /** + * 校验索引是否存在,要求 indexName 不能包含gsi的后缀 + * @param schemaName + * @param logicalTableName + * @param indexName + * @return + */ public static boolean checkIfIndexExists(String schemaName, String logicalTableName, String indexName) { - return new TableInfoManagerDelegate(new TableInfoManager()) { - @Override - protected Boolean invoke() { - return tableInfoManager.checkIfIndexExists(schemaName, logicalTableName, indexName); - } - }.execute(); + TableMeta tableMeta = + OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTableWithNull(logicalTableName); + if (tableMeta == null) { + return new TableInfoManagerDelegate(new TableInfoManager()) { + @Override + protected Boolean invoke() { + return tableInfoManager.checkIfIndexExists(schemaName, logicalTableName, indexName); + } + }.execute(); + } + return tableMeta.checkIndexNameExists(indexName); } public static boolean checkIfColumnarIndexExists(String schemaName, String logicalTableName) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/TableValidator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/TableValidator.java index 99f237900..a981e9852 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/TableValidator.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/job/validator/TableValidator.java @@ -43,6 +43,7 @@ import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil; @@ -60,6 +61,7 @@ import com.google.common.base.Preconditions; import org.apache.calcite.sql.SqlAlterSpecification; import org.apache.calcite.sql.SqlAlterTable; +import org.apache.calcite.sql.SqlAlterTableOptimizePartition; import org.apache.calcite.sql.SqlAlterTableTruncatePartition; import org.apache.calcite.sql.SqlColumnDeclaration; import org.apache.calcite.sql.SqlCreateTable; @@ -336,6 +338,15 @@ public static boolean checkTableWithGsi(String schemaName, String logicalTableNa return tableMeta.withGsi(); } + public static void validateTableWithCCI(ExecutionContext executionContext, + ComplexTaskMetaManager.ComplexTaskType taskType) { + boolean forbidDdlWithCci = executionContext.getParamManager().getBoolean(ConnectionParams.FORBID_DDL_WITH_CCI); + // allow move partition on table with cci + if (forbidDdlWithCci && taskType != ComplexTaskMetaManager.ComplexTaskType.MOVE_PARTITION) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_WITH_CCI, taskType.name()); + } + } + public static void validateTableWithCCI(String schemaName, String logicalTableName, ExecutionContext executionContext, SqlKind sqlKind) { TableMeta tableMeta = @@ -523,7 +534,8 @@ public static void validateLocality(String schemaName, LocalityDesc localityDesc } } - public static void validateTruncatePartition(String schemaName, String tableName, SqlAlterTable sqlAlterTable) { + public static void validateTruncatePartition(String schemaName, String tableName, SqlAlterTable sqlAlterTable, + ExecutionContext executionContext) { TableMeta tableMeta = OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(tableName); if (tableMeta == null) { throw new TddlRuntimeException(ErrorCode.ERR_UNKNOWN_TABLE, schemaName, tableName); @@ -537,10 +549,23 @@ public static void validateTruncatePartition(String schemaName, String tableName if (tableMeta.isGsi()) { throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_TRUNCATE_PARTITION, tableName); } + boolean allDropTruncateCciPartition = + executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_DROP_TRUNCATE_CCI_PARTITION); + if (tableMeta.isColumnar() && !allDropTruncateCciPartition) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_TRUNCATE_PARTITION, + "Not support truncate CCI `" + tableName + "` partition."); + } } } } + public static void validateOptimizePartition(String schemaName, String tableName, SqlAlterTable sqlAlterTable) { + TableMeta tableMeta = OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(tableName); + if (tableMeta == null) { + throw new TddlRuntimeException(ErrorCode.ERR_UNKNOWN_TABLE, schemaName, tableName); + } + } + public static void validateCollationImplemented(SqlCreateTable sqlCreateTable) { for (Pair pair : sqlCreateTable.getColDefs()) { SqlColumnDeclaration colDef = pair.getValue(); @@ -577,8 +602,20 @@ public static void validateTableEngine(BaseDdlOperation ddlOperation, ExecutionC // ddl on file storage table if (executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_CHECK_DDL_FILE_STORAGE) && ddlOperation.checkIfFileStorage(executionContext)) { +// if (!ddlOperation.isSupportedByFileStorage() && !ddlOperation.isCciTable(executionContext)) { +// throwEngineNotSupport(ddlOperation.getSchemaName(), ddlOperation.getTableName()); +// } if (!ddlOperation.isSupportedByFileStorage()) { - throwEngineNotSupport(ddlOperation.getSchemaName(), ddlOperation.getTableName()); + if (!ddlOperation.isCciTable(executionContext)) { + throwEngineNotSupport(ddlOperation.getSchemaName(), ddlOperation.getTableName()); + } else { + /** + * Curr table is cci index + */ + if (!ddlOperation.isSupportedByCci(executionContext)) { + throwEngineNotSupport(ddlOperation.getSchemaName(), ddlOperation.getTableName()); + } + } } } // ddl on innodb table binding to file storage table diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineDagExecutor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineDagExecutor.java index 7ec26a7d8..23a774827 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineDagExecutor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineDagExecutor.java @@ -82,10 +82,12 @@ import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.ArrayList; +import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; @@ -133,7 +135,6 @@ public class DdlEngineDagExecutor { private String errorMessage; private final ExecutionContext executionContext; - private final DdlJob ddlJob; private final DdlContext ddlContext; private final DdlJobManager ddlJobManager = new DdlJobManager(); @@ -188,8 +189,8 @@ private DdlEngineDagExecutor(Long jobId, DdlJob ddlJob, DdlContext ddlContext, E this.semaphore = new Semaphore(maxParallelism); } - public static DdlEngineDagExecutor create(Long jobId, ExecutionContext ec) { - Pair pair = new DdlJobManager().restoreJob(jobId); + public static DdlEngineDagExecutor create(Long jobId, Long taskId, ExecutionContext ec) { + Pair pair = new DdlJobManager().restoreJob(jobId, taskId); return new DdlEngineDagExecutor(jobId, pair.getKey(), pair.getValue(), ec); } @@ -360,7 +361,8 @@ private void onRunning() { } if (executingTaskScheduler.hasMoreExecutable()) { // fetch & execute next batch - submitDdlTask(executingTaskScheduler.pollBatch(), true, executingTaskScheduler); + List ddlTasks = executingTaskScheduler.pollBatchByResource(); + submitDdlTask(ddlTasks, true, executingTaskScheduler); continue; } //get some rest @@ -368,6 +370,10 @@ private void onRunning() { } } + public Map> getActiveTaskInfo() { + return taskScheduler.queryActiveTasks(); + } + private void onRollingBack() { if (!allowRollback()) { updateDdlState(DdlState.ROLLBACK_RUNNING, DdlState.PAUSED); @@ -395,7 +401,8 @@ private void onRollingBack() { } if (reveredTaskScheduler.hasMoreExecutable()) { // fetch & execute next batch - submitDdlTask(reveredTaskScheduler.pollBatch(), false, reveredTaskScheduler); + List ddlTasks = reveredTaskScheduler.pollBatchByResource(); + submitDdlTask(ddlTasks, false, reveredTaskScheduler); continue; } //get some rest @@ -432,7 +439,8 @@ private void onRollingBackToReady() { } if (reveredTaskScheduler.hasMoreExecutable()) { // fetch & execute next batch - submitDdlTask(reveredTaskScheduler.pollBatch(), false, reveredTaskScheduler); + List ddlTasks = reveredTaskScheduler.pollBatchByResource(); + submitDdlTask(ddlTasks, false, reveredTaskScheduler); continue; } //get some rest @@ -593,13 +601,24 @@ private void saveDagToTrace() { * @param executeElseRollback true means execute, false means rollback */ private void submitDdlTask(List taskList, boolean executeElseRollback, final TaskScheduler scheduler) { + taskList = taskList.stream().filter(o -> o != null).collect(Collectors.toList()); if (CollectionUtils.isEmpty(taskList)) { return; } for (DdlTask task : taskList) { + String logInfo; try { + logInfo = + String.format("schedule task %d %s for job %d %s, task info %s, semaphore %d", task.getTaskId(), + task.getName(), getJobId(), getDdlStmt(), task.executionInfo(), semaphore.availablePermits()); + LOGGER.info(logInfo); semaphore.acquire(); + logInfo = String.format("now scheduled! schedule task %d %s for job %d %s, task info %s, semaphore %d", + task.getTaskId(), task.getName(), getJobId(), getDdlStmt(), task.executionInfo(), + semaphore.availablePermits()); + task.setScheduled(true); + LOGGER.info(logInfo); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new TddlNestableRuntimeException(e); @@ -654,6 +673,8 @@ && hasFailureOnState(DdlState.ROLLBACK_TO_READY)) { return false; } finally { MDC.remove(MDC_KEY_TASK_ID); + scheduler.releaseResource(task); + task.setScheduled(false); semaphore.release(); } })); @@ -666,6 +687,7 @@ private void statTaskDone(DdlTask task) { DdlEngineStats.METRIC_BACKFILL_TASK_FINISHED.update(1); } DdlEngineStats.METRIC_DDL_TASK_FINISHED.update(1); + DdlEngineStats.taskBeginTime.remove(task); } private void statTaskFail(DdlTask task) { @@ -673,6 +695,11 @@ private void statTaskFail(DdlTask task) { DdlEngineStats.METRIC_BACKFILL_TASK_FAILED.update(1); } DdlEngineStats.METRIC_DDL_TASK_FAILED.update(1); + DdlEngineStats.taskBeginTime.remove(task); + } + + private void statTaskBegin(DdlTask task) { + DdlEngineStats.taskBeginTime.put(task, System.currentTimeMillis()); } /** @@ -686,6 +713,7 @@ private boolean executeTask(DdlTask task) { return false; } LOGGER.info(String.format("start to execute task:[%s], name:[%s]", task.getTaskId(), task.getName())); + statTaskBegin(task); if (task instanceof RemoteExecutableDdlTask) { remoteExecute(task, executionContext); } else { @@ -1297,20 +1325,20 @@ public void executeSingleTask(long taskId) { } public static void remoteExecute(DdlTask remoteTask, ExecutionContext executionContext) { - Optional serverKey = ((RemoteExecutableDdlTask) remoteTask).chooseServer(); - if (!serverKey.isPresent()) { + String serverKey = ((RemoteExecutableDdlTask) remoteTask).getDdlEngineResources().getServerKey(); + if (serverKey == null) { SQLRecorderLogger.ddlEngineLogger.info("choose local server to execute DDL TASK"); remoteTask.execute(executionContext); return; } //remote execute - SQLRecorderLogger.ddlEngineLogger.info("choose remote server to execute DDL TASK: " + serverKey.get()); + SQLRecorderLogger.ddlEngineLogger.info("choose remote server to execute DDL TASK: " + serverKey); try { List> result = GmsSyncManagerHelper.sync(new RemoteDdlTaskSyncAction( remoteTask.getSchemaName(), remoteTask.getJobId(), remoteTask.getTaskId() - ), remoteTask.getSchemaName(), serverKey.get()); + ), remoteTask.getSchemaName(), serverKey); if (!RemoteDdlTaskSyncAction.isRemoteDdlTaskSyncActionSuccess(result)) { throw new TddlNestableRuntimeException(RemoteDdlTaskSyncAction.getMsgFromResult(result)); } @@ -1339,4 +1367,8 @@ private boolean shouldForcePause() { } } + public DdlJob getDdlJob() { + return ddlJob; + } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineDagExecutorMap.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineDagExecutorMap.java index 2a0849c55..6270439ec 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineDagExecutorMap.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineDagExecutorMap.java @@ -29,6 +29,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; import static com.alibaba.polardbx.executor.ddl.newengine.sync.DdlResponse.Response; @@ -36,17 +37,28 @@ public class DdlEngineDagExecutorMap { private static final Logger LOGGER = SQLRecorderLogger.ddlEngineLogger; - private static final Map>> DDL_DAG_EXECUTOR_MAP = + public static final Map>> DDL_DAG_EXECUTOR_MAP = + new ConcurrentHashMap<>(); + + public static final Map>> DDL_DAG_REMOTE_EXECUTOR_MAP = new ConcurrentHashMap<>(); public static void register(String schemaName) { DDL_DAG_EXECUTOR_MAP.put(schemaName.toLowerCase(), new ConcurrentHashMap<>()); } + public static void registerRemote(String schemaName) { + DDL_DAG_REMOTE_EXECUTOR_MAP.put(schemaName.toLowerCase(), new ConcurrentHashMap<>()); + } + public static void deregister(String schemaName) { DDL_DAG_EXECUTOR_MAP.remove(schemaName.toLowerCase()); } + public static void deregisterRemote(String schemaName) { + DDL_DAG_REMOTE_EXECUTOR_MAP.remove(schemaName.toLowerCase()); + } + /** * make sure: * never override ddl job in DDL_DAG_EXECUTOR_MAP @@ -67,7 +79,7 @@ static boolean restore(String schemaName, long jobId, ExecutionContext execution map.put(jobId, Optional.empty()); } try { - DdlEngineDagExecutor dagExecutor = DdlEngineDagExecutor.create(jobId, executionContext); + DdlEngineDagExecutor dagExecutor = DdlEngineDagExecutor.create(jobId, -1L, executionContext); map.put(jobId, Optional.of(dagExecutor)); return true; } catch (Throwable t) { @@ -99,6 +111,21 @@ public static DdlEngineDagExecutor get(String schemaName, long jobId) { } } + public static List getRemoteJobExecutors(String schemaName, long jobId) { + Map> map = DDL_DAG_REMOTE_EXECUTOR_MAP.get(schemaName.toLowerCase()); + if (map == null) { + return null; + } + List ddlEngineDagExecutors = + map.values().stream().filter(o -> o.isPresent() && o.get().getJobId() == jobId).map(o -> o.get()) + .collect(Collectors.toList()); + if (ddlEngineDagExecutors.isEmpty()) { + return null; + } else { + return ddlEngineDagExecutors; + } + } + public static boolean contains(String schemaName, long jobId) { Map> map = DDL_DAG_EXECUTOR_MAP.get(schemaName.toLowerCase()); if (map == null) { @@ -107,6 +134,14 @@ public static boolean contains(String schemaName, long jobId) { return map.containsKey(jobId); } + public static boolean containsRemote(String schemaName, long jobId) { + Map> map = DDL_DAG_REMOTE_EXECUTOR_MAP.get(schemaName.toLowerCase()); + if (map == null) { + return false; + } + return map.containsKey(jobId); + } + public static List getAllDdlJobCaches(String schemaName) { List result = Lists.newArrayList(); Map> dagExecutorMap = DDL_DAG_EXECUTOR_MAP.get(schemaName.toLowerCase()); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineRemoteTaskExecutor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineRemoteTaskExecutor.java index a839482f8..28be6170a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineRemoteTaskExecutor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineRemoteTaskExecutor.java @@ -22,17 +22,20 @@ import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.thread.ExecutorUtil; import com.alibaba.polardbx.common.utils.thread.NamedThreadFactory; +import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlHelper; import com.alibaba.polardbx.gms.lease.impl.LeaseManagerImpl; import com.alibaba.polardbx.gms.metadb.lease.LeaseRecord; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import java.util.Map; import java.util.Optional; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import static com.alibaba.polardbx.common.ddl.newengine.DdlConstants.DDL_LEADER_TTL_IN_MILLIS; +import static com.alibaba.polardbx.executor.ddl.newengine.DdlEngineDagExecutorMap.DDL_DAG_REMOTE_EXECUTOR_MAP; public class DdlEngineRemoteTaskExecutor { @@ -47,41 +50,67 @@ public static void executeRemoteTask(String schemaName, Long jobId, Long taskId, Optional leaseRecordOptional = new LeaseManagerImpl().acquire( schemaName, String.valueOf(taskId), DDL_LEADER_TTL_IN_MILLIS); final DdlEngineDagExecutor dagExecutor; - if (leaseRecordOptional.isPresent()) { - dagExecutor = DdlEngineDagExecutor.create(jobId, executionContext); - dagExecutor.getJobLease().set(leaseRecordOptional.get()); - } else { - final String errMsg = "failed to acquire DDL TASK lease. task_id:" + taskId; - LOGGER.error(errMsg); - throw new TddlNestableRuntimeException(errMsg); - } - //start lease heartbeat - final ScheduledExecutorService jobLeaseSchedulerThread = ExecutorUtil.createScheduler(1, - new NamedThreadFactory("DDL_TASK_LEASE_SCHEDULER"), - new ThreadPoolExecutor.DiscardPolicy()); - + Boolean putIntoGlobalMap = false; try { - jobLeaseSchedulerThread.scheduleAtFixedRate( - AsyncTask.build(() -> { - Optional optional = new LeaseManagerImpl().extend(String.valueOf(taskId)); - if (optional.isPresent()) { - dagExecutor.getJobLease().compareAndSet(dagExecutor.getJobLease().get(), optional.get()); - } else { - //extend job lease failed, so shutdown the scheduler thread - jobLeaseSchedulerThread.shutdown(); + if (leaseRecordOptional.isPresent()) { + if (DdlEngineDagExecutorMap.containsRemote(schemaName, taskId)) { + return; + } + Map> map = + DDL_DAG_REMOTE_EXECUTOR_MAP.get(schemaName.toLowerCase()); + synchronized (DDL_DAG_REMOTE_EXECUTOR_MAP) { + if (map.containsKey(taskId)) { + throw DdlHelper.logAndThrowError(LOGGER, String.format( + "The DDL job is executing. jobId:[%s], taskId:[%s], schemaName:[%s]", jobId, taskId, + schemaName)); } - }), - 0L, - DDL_LEADER_TTL_IN_MILLIS / 2, - TimeUnit.MILLISECONDS - ); + dagExecutor = DdlEngineDagExecutor.create(jobId, taskId, executionContext); + dagExecutor.getJobLease().set(leaseRecordOptional.get()); + map.put(taskId, Optional.of(dagExecutor)); + putIntoGlobalMap = true; + } + } else { + final String errMsg = "failed to acquire DDL TASK lease. task_id:" + taskId; + LOGGER.error(errMsg); + throw new TddlNestableRuntimeException(errMsg); + } + //start lease heartbeat + final ScheduledExecutorService jobLeaseSchedulerThread = ExecutorUtil.createScheduler(1, + new NamedThreadFactory("DDL_TASK_LEASE_SCHEDULER"), + new ThreadPoolExecutor.DiscardPolicy()); + + try { + jobLeaseSchedulerThread.scheduleAtFixedRate( + AsyncTask.build(() -> { + Optional optional = new LeaseManagerImpl().extend(String.valueOf(taskId)); + if (optional.isPresent()) { + dagExecutor.getJobLease().compareAndSet(dagExecutor.getJobLease().get(), optional.get()); + } else { + //extend job lease failed, so we first update the lease inside ddlContext. + //then shutdown the scheduler thread + dagExecutor.getJobLease().compareAndSet(dagExecutor.getJobLease().get(), null); + jobLeaseSchedulerThread.shutdown(); + } + }), + 0L, + DDL_LEADER_TTL_IN_MILLIS / 2, + TimeUnit.MILLISECONDS + ); - //execute task - dagExecutor.executeSingleTask(taskId); - LOGGER.info(String.format("execute/rollback remote DDL TASK success, jobId:%s, taskId:%s", jobId, taskId)); + //execute task + dagExecutor.executeSingleTask(taskId); + LOGGER.info( + String.format("execute/rollback remote DDL TASK success, jobId:%s, taskId:%s", jobId, taskId)); + } finally { + new LeaseManagerImpl().release(String.valueOf(taskId)); + jobLeaseSchedulerThread.shutdown(); + } } finally { - new LeaseManagerImpl().release(String.valueOf(taskId)); - jobLeaseSchedulerThread.shutdown(); + if (putIntoGlobalMap) { + synchronized (DDL_DAG_REMOTE_EXECUTOR_MAP) { + DDL_DAG_REMOTE_EXECUTOR_MAP.get(schemaName.toLowerCase()).remove(taskId); + } + } } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineScheduleStats.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineScheduleStats.java new file mode 100644 index 000000000..e38111255 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineScheduleStats.java @@ -0,0 +1,153 @@ +package com.alibaba.polardbx.executor.ddl.newengine; + +import com.alibaba.polardbx.executor.backfill.Throttle; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Function; + +/** + * Statistics for ddl engine + * + * @author moyi + * @since 2021/11 + */ +public class DdlEngineScheduleStats { + + private final static Map metrics = new HashMap<>(); + + public static Metric METRIC_DDL_JOBS_TOTAL = new Metric("DDL_JOBS_TOTAL"); + public static Metric METRIC_DDL_JOBS_FINISHED = new Metric("DDL_JOBS_FINISHED"); + public static Metric METRIC_DDL_EXECUTION_TIME_MILLIS = new Metric("DDL_EXECUTION_TIME_MILLIS"); + public static Metric METRIC_DDL_TASK_TOTAL = new Metric("DDL_TASK_TOTAL"); + public static Metric METRIC_DDL_TASK_FINISHED = new Metric("DDL_TASK_FINISHED"); + public static Metric METRIC_DDL_TASK_FAILED = new Metric("DDL_TASK_FAILED"); + + public static Metric METRIC_CHECKER_ROWS_FINISHED = new Metric("CHECKER_ROWS_FINISHED"); + public static Metric METRIC_CHECKER_TIME_MILLIS = new Metric("CHECKER_TIME_MILLIS"); + + public static Metric METRIC_FASTCHECKER_TASK_RUNNING = new Metric("FASTCHECKER_TASK_RUNNING"); + public static Metric METRIC_FASTCHECKER_TASK_WAITING = new Metric("FASTCHECKER_TASK_WAITING"); + + public static Metric METRIC_FASTCHECKER_THREAD_POOL_NOW_SIZE = new Metric("FASTCHECKER_THREAD_POOL_NOW_SIZE"); + + public static Metric METRIC_FASTCHECKER_THREAD_POOL_MAX_SIZE = new Metric("FASTCHECKER_THREAD_POOL_MAX_SIZE"); + + public static Metric METRIC_FASTCHECKER_THREAD_POOL_NUM = new Metric("FASTCHECKER_THREAD_POOL_NUM"); + + public static Metric METRIC_BACKFILL_ROWS_FINISHED = new Metric("BACKFILL_ROWS_FINISHED"); + public static Metric METRIC_BACKFILL_ROWS_SPEED = new Metric("BACKFILL_ROWS_SPEED"); + public static Metric METRIC_BACKFILL_TIME_MILLIS = new Metric("BACKFILL_TIME_MILLIS"); + + public static Metric METRIC_BACKFILL_TASK_TOTAL = new Metric("BACKFILL_TASK_TOTAL"); + public static Metric METRIC_BACKFILL_TASK_FINISHED = new Metric("BACKFILL_TASK_FINISHED"); + public static Metric METRIC_BACKFILL_TASK_FAILED = new Metric("BACKFILL_TASK_FAILED"); + + public static Metric METRIC_BACKFILL_PARALLELISM = new Metric("BACKFILL_PARALLELISM"); + public static Metric METRIC_CHANGESET_APPLY_PARALLELISM = new Metric("CHANGESET_APPLY_PARALLELISM"); + public static Metric METRIC_CHANGESET_APPLY_ROWS_SPEED = new Metric("CHANGESET_APPLY_ROWS_SPEED"); + + public static Metric METRIC_TWO_PHASE_DDL_PARALLISM = new Metric("TWO_PHASE_DDL_PARALLISM"); + + public static Metric METRIC_THROTTLE_RATE = + new Metric.DelegatorMetric("THROTTLE_RATE", (x) -> Throttle.getTotalThrottleRate()); + + public static Map getAllMetrics() { + return metrics; + } + + public static void updateMetric(String name, long delta) { + metrics.get(name).getValue().addAndGet(delta); + } + + public static long getMetric(String name) { + return metrics.get(name).getValue().get(); + } + + @Data + public static class Metric { + String name; + AtomicLong value; + + public Metric(String name) { + this.name = name; + this.value = new AtomicLong(); + metrics.put(name, this); + } + + public Metric(String name, long value) { + this.name = name; + this.value = new AtomicLong(value); + } + + public static Metric fromMap(Map map) { + String name = DataTypes.StringType.convertFrom(map.get("METRIC")); + long value = DataTypes.LongType.convertFrom(map.get("VALUE")); + return new Metric(name, value); + } + + public static ArrayResultCursor buildCursor() { + ArrayResultCursor cursor = new ArrayResultCursor("METRICS"); + cursor.addColumn("METRIC", DataTypes.VarcharType); + cursor.addColumn("VALUE", DataTypes.LongType); + cursor.initMeta(); + return cursor; + } + + public static Object[] toRow(Map map) { + return new Object[] {map.get("METRIC"), map.get("VALUE")}; + } + + public Object[] toRow() { + return new Object[] {name, value.get()}; + } + + public void update(long delta) { + this.value.addAndGet(delta); + } + + public void set(long value) { + this.value.set(value); + } + + public Metric merge(Metric rhs) { + assert name.equals(rhs.getName()); + long value = getValue().get() + rhs.getValue().get(); + return new Metric(getName(), value); + } + + /** + * Delegate the metric to the other component + */ + public static class DelegatorMetric extends Metric { + + private Function delegator; + + public DelegatorMetric(String name, Function delegator) { + super(name); + this.delegator = delegator; + } + + @Override + public Object[] toRow() { + return new Object[] {name, delegator.apply(null)}; + } + + @Override + public void update(long delta) { + throw new AssertionError("non-updatable"); + } + + @Override + public void set(long value) { + throw new AssertionError("non-updatable"); + } + + } + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineScheduler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineScheduler.java index 4642ab233..6f8881085 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineScheduler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineScheduler.java @@ -21,7 +21,6 @@ import com.alibaba.polardbx.common.ddl.newengine.DdlState; import com.alibaba.polardbx.common.eventlogger.EventLogger; import com.alibaba.polardbx.common.eventlogger.EventType; -import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.properties.ConnectionProperties; import com.alibaba.polardbx.common.utils.LoggerUtil; import com.alibaba.polardbx.common.utils.TStringUtil; @@ -31,10 +30,11 @@ import com.alibaba.polardbx.common.utils.thread.NamedThreadFactory; import com.alibaba.polardbx.common.utils.thread.ServerThreadPool; import com.alibaba.polardbx.executor.changeset.ChangeSetApplyExecutorMap; -import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlEngineSchedulerManager; +import com.alibaba.polardbx.executor.ddl.newengine.dag.TaskScheduler; import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlJobManager; import com.alibaba.polardbx.executor.ddl.newengine.sync.DdlRequest; import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlHelper; +import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; @@ -44,10 +44,8 @@ import com.alibaba.polardbx.gms.metadb.misc.DdlEngineRecord; import com.alibaba.polardbx.statistics.SQLRecorderLogger; import com.google.common.collect.Sets; -import org.apache.calcite.rel.metadata.BuiltInMetadata; import org.apache.commons.lang3.StringUtils; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -148,6 +146,7 @@ public void register(String schemaName, ServerThreadPool executor) { if (DdlHelper.isRunnable(schemaName)) { String lowerCaseSchemaName = schemaName.toLowerCase(); DdlEngineDagExecutorMap.register(lowerCaseSchemaName); + DdlEngineDagExecutorMap.registerRemote(lowerCaseSchemaName); ChangeSetApplyExecutorMap.register(lowerCaseSchemaName); synchronized (activeSchemaDdlConfig) { activeSchemaDdlConfig.put(lowerCaseSchemaName, @@ -160,6 +159,7 @@ public void deregister(String schemaName) { if (DdlHelper.isRunnable(schemaName)) { String lowerCaseSchemaName = schemaName.toLowerCase(); DdlEngineDagExecutorMap.deregister(lowerCaseSchemaName); + DdlEngineDagExecutorMap.deregisterRemote(lowerCaseSchemaName); ChangeSetApplyExecutorMap.deregister(lowerCaseSchemaName); synchronized (activeSchemaDdlConfig) { activeSchemaDdlConfig.remove(lowerCaseSchemaName); @@ -225,7 +225,7 @@ public synchronized boolean compareAndExecute(long expectVersion, Supplier su } if (System.currentTimeMillis() - startTime >= MORE_WAITING_TIME * 3) { - throw new TimeoutException("wait job transfering to idle time out."); + throw new TimeoutException("wait job transferring to idle time out."); } } } finally { @@ -457,6 +457,7 @@ private class DdlJobScheduler implements Runnable { private volatile boolean scheduleSuspended; + private DdlJobScheduler() { } @@ -468,6 +469,8 @@ public void run() { Thread.currentThread().setName(DDL_SCHEDULER_NAME); + refreshResourceToAllocate(); + while (true) { try { if (!ExecUtils.hasLeadership(null)) { @@ -643,4 +646,10 @@ private boolean offerQueue(BlockingQueue queue, Object object, String message) { public AtomicReference getDdlLeaderLease() { return this.ddlLeaderLease; } + + public static void refreshResourceToAllocate() { + synchronized (TaskScheduler.resourceToAllocate) { + DdlResourceManagerUtils.initializeResources(TaskScheduler.resourceToAllocate); + } + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineStats.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineStats.java index 87e858447..3e763bcef 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineStats.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineStats.java @@ -16,13 +16,19 @@ package com.alibaba.polardbx.executor.ddl.newengine; +import com.alibaba.polardbx.common.utils.CaseInsensitive; import com.alibaba.polardbx.executor.backfill.Throttle; import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler.TtlScheduledJobStatManager; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import lombok.Data; +import org.apache.commons.collections.map.HashedMap; import java.util.HashMap; import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; @@ -36,6 +42,9 @@ public class DdlEngineStats { private final static Map metrics = new HashMap<>(); + public static Long speedStatCycle = 1500L; + + public static Map taskBeginTime = new ConcurrentHashMap<>(); public static Metric METRIC_DDL_JOBS_TOTAL = new Metric("DDL_JOBS_TOTAL"); public static Metric METRIC_DDL_JOBS_FINISHED = new Metric("DDL_JOBS_FINISHED"); public static Metric METRIC_DDL_EXECUTION_TIME_MILLIS = new Metric("DDL_EXECUTION_TIME_MILLIS"); @@ -56,6 +65,12 @@ public class DdlEngineStats { public static Metric METRIC_FASTCHECKER_THREAD_POOL_NUM = new Metric("FASTCHECKER_THREAD_POOL_NUM"); public static Metric METRIC_BACKFILL_ROWS_FINISHED = new Metric("BACKFILL_ROWS_FINISHED"); + + public static Metric METRIC_BACKFILL_ROWS_FINISHED_LAST_CYCLE = + new Metric("BACKFILL_ROWS_FINISHED_LAST_CYCLE", false); + + public static Metric METRIC_BACKFILL_ROWS_FINISHED_LAST_TIMESTAMP = + new Metric("BACKFILL_ROWS_FINISHED_LAST_TIMESTAMP", false); public static Metric METRIC_BACKFILL_ROWS_SPEED = new Metric("BACKFILL_ROWS_SPEED"); public static Metric METRIC_BACKFILL_TIME_MILLIS = new Metric("BACKFILL_TIME_MILLIS"); @@ -73,6 +88,9 @@ public class DdlEngineStats { new Metric.DelegatorMetric("THROTTLE_RATE", (x) -> Throttle.getTotalThrottleRate()); public static Map getAllMetrics() { + Map tmpMetrics = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + tmpMetrics.putAll(metrics); + tmpMetrics.putAll(TtlScheduledJobStatManager.buildGlobalTtlMetrics()); return metrics; } @@ -84,20 +102,61 @@ public static long getMetric(String name) { return metrics.get(name).getValue().get(); } + public static void updateBackfillRowsMetric(long delta) { + long currentTimeMillis = System.currentTimeMillis(); + METRIC_BACKFILL_ROWS_FINISHED.update(delta); + long lastTimeStamp = METRIC_BACKFILL_ROWS_FINISHED_LAST_TIMESTAMP.getValue().get(); + long lastCycle = currentTimeMillis - lastTimeStamp; + if (lastCycle > speedStatCycle) { + updateBackfillSpeedMetric(lastTimeStamp); + } + } + + public static synchronized void updateBackfillSpeedMetric(long lastTimeStamp) { + long timeStamp = METRIC_BACKFILL_ROWS_FINISHED_LAST_TIMESTAMP.getValue().get(); + long currentTimeStamp = System.currentTimeMillis(); + if (timeStamp == lastTimeStamp) { + long backfillRowsFinishedLastCycle = METRIC_BACKFILL_ROWS_FINISHED_LAST_CYCLE.getValue().get(); + long backfillRowsFinished = METRIC_BACKFILL_ROWS_FINISHED.getValue().get(); + long speed = + (backfillRowsFinished - backfillRowsFinishedLastCycle) * 1000 / (currentTimeStamp - lastTimeStamp); + METRIC_BACKFILL_ROWS_FINISHED_LAST_CYCLE.set(backfillRowsFinished); + METRIC_BACKFILL_ROWS_FINISHED_LAST_TIMESTAMP.set(currentTimeStamp); + METRIC_BACKFILL_ROWS_SPEED.set(speed); + } + } + @Data public static class Metric { String name; AtomicLong value; + Boolean show; public Metric(String name) { this.name = name; + this.value = new AtomicLong(0); this.value = new AtomicLong(); + this.show = true; + metrics.put(name, this); + } + + public Metric(String name, Boolean show) { + this.name = name; + this.value = new AtomicLong(); + this.show = show; metrics.put(name, this); } public Metric(String name, long value) { this.name = name; this.value = new AtomicLong(value); + this.show = true; + } + + public Metric(String name, long value, Boolean show) { + this.name = name; + this.value = new AtomicLong(value); + this.show = show; } public static Metric fromMap(Map map) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/dag/DirectedAcyclicGraph.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/dag/DirectedAcyclicGraph.java index 1239a0ca8..341cc53d5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/dag/DirectedAcyclicGraph.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/dag/DirectedAcyclicGraph.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; @@ -333,7 +334,10 @@ public synchronized String toString() { public synchronized String visualize() { StringBuilder dag = new StringBuilder(); dag.append("digraph G {\n"); - for (Vertex v : vertexes) { + List vertexList = + vertexes.stream().sorted(Comparator.comparing(vertex -> vertex.getObject().getRankHint())) + .collect(Collectors.toList()); + for (Vertex v : vertexList) { dag.append(v.object.nodeInfo() + "\n"); } for (Edge e : edges) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/dag/TaskScheduler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/dag/TaskScheduler.java index fb84947a5..54a8a7b87 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/dag/TaskScheduler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/dag/TaskScheduler.java @@ -16,18 +16,28 @@ package com.alibaba.polardbx.executor.ddl.newengine.dag; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.executor.ddl.job.task.RemoteExecutableDdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; +import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlResourceManagerUtils; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import com.google.common.base.Joiner; import com.alibaba.polardbx.common.model.lifecycle.AbstractLifecycle; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; -import com.google.common.base.Joiner; import org.apache.commons.collections.CollectionUtils; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import static com.alibaba.polardbx.executor.ddl.newengine.dag.DirectedAcyclicGraph.Edge; import static com.alibaba.polardbx.executor.ddl.newengine.dag.DirectedAcyclicGraph.Vertex; +import static com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources.normalizeServerKey; /** * use this class to make sure tasks are executed in right dependency order @@ -59,6 +69,17 @@ public class TaskScheduler extends AbstractLifecycle { private final DirectedAcyclicGraph daGraph; private final int count; + public enum ScheduleStatus { + SCHEDULED, + RUNNABLE, + CANDIDATE, + WAITING + } + + public static DdlEngineResources resourceToAllocate = new DdlEngineResources(); + public static Map runningRemoteTaskNums = new ConcurrentHashMap<>(); + private static final Logger LOGGER = SQLRecorderLogger.ddlEngineLogger; + private TaskScheduler(DirectedAcyclicGraph daGraph) { this.count = daGraph.vertexCount(); this.daGraph = daGraph; @@ -151,6 +172,70 @@ public DdlTask poll() { } } + public void releaseResource(DdlTask ddlTask) { + if (ddlTask == null) { + return; + } + synchronized (daGraph) { + DdlEngineResources resourcesAcquired = ddlTask.getResourceAcquired(); + synchronized (resourceToAllocate) { + resourceToAllocate.free(resourcesAcquired); + if (ddlTask instanceof RemoteExecutableDdlTask) { + String serverKey = normalizeServerKey(resourcesAcquired.getServerKey()); + runningRemoteTaskNums.put(serverKey, + runningRemoteTaskNums.getOrDefault(runningRemoteTaskNums.get(serverKey), 1) - 1); + } + } + } + } + + public DdlTask pollByResource() { + synchronized (daGraph) { + // which can be scheduled now. + if (CollectionUtils.isEmpty(zeroInDegreeVertexes)) { + return null; + } + for (Vertex vertex : zeroInDegreeVertexes) { + DdlEngineResources resourcesAcquired = vertex.object.getResourceAcquired(); + + synchronized (resourceToAllocate) { + String logInfo; + if (vertex.object instanceof RemoteExecutableDdlTask) { + String serverKey = + ((RemoteExecutableDdlTask) vertex.object).detectServerFromCandidate(runningRemoteTaskNums); + resourcesAcquired.setServerKey(serverKey); + } + if (resourceToAllocate.cover(resourcesAcquired)) { +// logInfo = +// String.format("ddl engine resource covered {%s} {%s} for task", resourcesAcquired, +// resourceToAllocate); +// LOGGER.info(logInfo); + resourceToAllocate.allocate(resourcesAcquired); + if (vertex.object instanceof RemoteExecutableDdlTask) { + String serverKey = normalizeServerKey(resourcesAcquired.getServerKey()); + runningRemoteTaskNums.put(serverKey, + runningRemoteTaskNums.getOrDefault(serverKey, 0) + 1); + } + vertex.object.setScheduled(false); + executingVertexes.add(vertex); + zeroInDegreeVertexes.remove(vertex); + return vertex.object; + } + Long taskId = vertex.object.getTaskId(); + if (!DdlEngineResources.markNotCoverredBefore(taskId)) { +// logInfo = String.format("ddl engine resource covered not for task {%s}: {%s}", +// vertex.object.executionInfo(), +// DdlEngineResources.digestCoverInfo(resourcesAcquired, resourceToAllocate)); +// LOGGER.info(logInfo); + } + } + } + // we need to upgrade task order everytime we update executing task, not always in this order. + // so we will try to do this soon. + } + return null; + } + public List pollBatch() { synchronized (daGraph) { List result = new ArrayList<>(); @@ -161,6 +246,54 @@ public List pollBatch() { } } + public List pollBatchByResource() { + final int PULL_BATCH_SIZE = 3; + int taskCount = 0; + synchronized (daGraph) { + List result = new ArrayList<>(); + while (hasMoreExecutable() && taskCount <= PULL_BATCH_SIZE) { + DdlTask ddlTask = pollByResource(); + result.add(ddlTask); + taskCount++; + } + return result; + } + } + + public Map> queryActiveTasks() { + // There would be a spot to call so many stream and HashMap.get, however, it's called by hand, we would tolerate + // this performance decrease. + synchronized (daGraph) { + Set runnableTasks = executingVertexes.stream().map(o -> o.object).collect(Collectors.toSet()); + Set candidateTasks = zeroInDegreeVertexes.stream().map(o -> o.object).collect(Collectors.toSet()); + candidateTasks.removeAll(runnableTasks); + Set scheduledTasks = + runnableTasks.stream().filter(o -> o.getScheduled()).collect(Collectors.toSet()); + runnableTasks.removeAll(scheduledTasks); + Map waitingTaskMap = new HashMap<>(); + for (Vertex executingVertex : executingVertexes) { + List outgoingEdges = executingVertex.outgoingEdges; + for (Edge edge : outgoingEdges) { + DdlTask waitingTask = edge.target.object; + if (waitingTaskMap.containsKey(waitingTask)) { + waitingTaskMap.put(waitingTask, waitingTaskMap.get(waitingTask) - 1); + } else { + waitingTaskMap.put(waitingTask, edge.target.inDegree - 1); + } + } + } + Set waitingTasks = + waitingTaskMap.keySet().stream().filter(o -> waitingTaskMap.get(o) == 0).collect( + Collectors.toSet()); + Map> results = new HashMap<>(); + results.put(ScheduleStatus.SCHEDULED, scheduledTasks); + results.put(ScheduleStatus.RUNNABLE, runnableTasks); + results.put(ScheduleStatus.CANDIDATE, candidateTasks); + results.put(ScheduleStatus.WAITING, waitingTasks); + return results; + } + } + public void markAsDone(DdlTask task) { synchronized (daGraph) { Optional vertexOptional = @@ -207,4 +340,5 @@ public void markAsFail(DdlTask task) { } } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/AbstractDdlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/AbstractDdlTask.java index f028c3710..e4cca3d09 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/AbstractDdlTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/AbstractDdlTask.java @@ -23,6 +23,7 @@ import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.ddl.job.task.BaseValidateTask; import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlEngineAccessorDelegate; +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; import com.alibaba.polardbx.executor.ddl.newengine.serializable.SerializableClassMapper; import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlJobManagerUtils; import com.alibaba.polardbx.executor.ddl.newengine.utils.TaskHelper; @@ -36,7 +37,9 @@ import java.sql.Connection; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.function.BooleanSupplier; import static com.alibaba.polardbx.executor.utils.failpoint.FailPointKey.FP_EACH_DDL_TASK_FAIL_ONCE; @@ -61,6 +64,10 @@ public abstract class AbstractDdlTask extends HandlerCommon implements DdlTask { protected transient volatile Long endRollbackTs; private transient volatile int injectTimes = 0; + protected String rankHint = ""; + + protected volatile DdlEngineResources resourceAcquired = new DdlEngineResources(); + protected transient volatile Boolean scheduled = false; public AbstractDdlTask(final String schemaName) { this.schemaName = schemaName; @@ -285,6 +292,26 @@ public void injectOnce(ExecutionContext executionContext) { }); } + @Override + public DdlEngineResources getResourceAcquired() { + return resourceAcquired; + } + + @Override + public void setResourceAcquired(DdlEngineResources resourceAcquired) { + this.resourceAcquired = resourceAcquired; + } + + @Override + public Boolean getScheduled() { + return scheduled; + } + + @Override + public void setScheduled(Boolean scheduled) { + this.scheduled = scheduled; + } + @Override public void setState(DdlTaskState ddlTaskState) { this.state = ddlTaskState; @@ -415,4 +442,14 @@ protected boolean isSkipExecute() { protected boolean isSkipRollback() { return false; } + + @Override + public String getRankHint() { + return rankHint; + } + + @Override + public void setRankHint(String rankHint) { + this.rankHint = rankHint; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/CompressedBlockData.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/CompressedBlockData.java new file mode 100644 index 000000000..35643298c --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/CompressedBlockData.java @@ -0,0 +1,5 @@ +package com.alibaba.polardbx.executor.ddl.newengine.job; + +public class CompressedBlockData { + String blockData; +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/DdlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/DdlTask.java index dff13cba7..14ca12b3b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/DdlTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/DdlTask.java @@ -17,10 +17,12 @@ package com.alibaba.polardbx.executor.ddl.newengine.job; import com.alibaba.polardbx.common.ddl.newengine.DdlTaskState; +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import java.sql.Connection; import java.util.List; +import java.util.Map; public interface DdlTask { @@ -36,6 +38,10 @@ public interface DdlTask { void setRootJobId(Long rootJobId); + String getRankHint(); + + void setRankHint(String rankHint); + /** * Get the task name. * used for Serialize/DeSerialize. @@ -49,6 +55,14 @@ public interface DdlTask { void setSchemaName(String schemaName); + DdlEngineResources getResourceAcquired(); + + void setResourceAcquired(DdlEngineResources resourceAcquired); + + Boolean getScheduled(); + + void setScheduled(Boolean scheduled); + /** * Execute the DDL task. */ diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/ExecutableDdlJobAttachCompressedBlockData.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/ExecutableDdlJobAttachCompressedBlockData.java new file mode 100644 index 000000000..9386925a5 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/ExecutableDdlJobAttachCompressedBlockData.java @@ -0,0 +1,23 @@ +package com.alibaba.polardbx.executor.ddl.newengine.job; + +import com.alibaba.polardbx.executor.ddl.newengine.dag.DirectedAcyclicGraph; + +import java.util.HashMap; +import java.util.Map; + +/** + * ExecutableDdlJob will store in MetaDB, and executed by leader CN + */ +public class ExecutableDdlJobAttachCompressedBlockData extends ExecutableDdlJob { + + private transient final Map extraBlockValueMap = new HashMap<>(); + + public ExecutableDdlJobAttachCompressedBlockData() { + super(); + } + + public ExecutableDdlJobAttachCompressedBlockData(DirectedAcyclicGraph taskGraph) { + super(taskGraph); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/wrapper/ExecutableDdlJob4CreateView.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/wrapper/ExecutableDdlJob4CreateView.java new file mode 100644 index 000000000..13f8a823e --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/job/wrapper/ExecutableDdlJob4CreateView.java @@ -0,0 +1,19 @@ +package com.alibaba.polardbx.executor.ddl.newengine.job.wrapper; + +import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateViewAddMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.CreateViewSyncTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.ValidateCreateViewTask; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcCreateViewMarkTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; +import lombok.Data; + +/** + * @author chenghui.lch + */ +@Data +public class ExecutableDdlJob4CreateView extends ExecutableDdlJob { + private ValidateCreateViewTask validateCreateViewTask; + private CreateViewAddMetaTask createViewAddMetaTask; + private CdcCreateViewMarkTask cdcCreateViewMarkTask; + private CreateViewSyncTask createViewSyncTask; +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlEngineAccessorDelegate.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlEngineAccessorDelegate.java index 40ff1ba26..ff0e5d1fe 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlEngineAccessorDelegate.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlEngineAccessorDelegate.java @@ -20,6 +20,7 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.gms.metadb.delegate.MetaDbAccessorWrapper; +import com.alibaba.polardbx.gms.metadb.misc.BackfillSampleRowsAccessor; import com.alibaba.polardbx.gms.metadb.misc.DdlEngineAccessor; import com.alibaba.polardbx.gms.metadb.misc.DdlEngineTaskAccessor; import com.alibaba.polardbx.gms.util.MetaDbUtil; @@ -34,17 +35,20 @@ public abstract class DdlEngineAccessorDelegate extends MetaDbAccessorWrapper protected final DdlEngineAccessor engineAccessor; protected final DdlEngineTaskAccessor engineTaskAccessor; + protected final BackfillSampleRowsAccessor backfillSampleRowsAccessor; protected Connection connection; public DdlEngineAccessorDelegate() { this.engineAccessor = new DdlEngineAccessor(); this.engineTaskAccessor = new DdlEngineTaskAccessor(); + this.backfillSampleRowsAccessor = new BackfillSampleRowsAccessor(); } @Override protected void open(Connection metaDbConn) { this.engineAccessor.setConnection(metaDbConn); this.engineTaskAccessor.setConnection(metaDbConn); + this.backfillSampleRowsAccessor.setConnection(metaDbConn); this.connection = metaDbConn; } @@ -82,6 +86,7 @@ protected void onException(Connection metaDbConn, Throwable throwable) { protected void close() { this.engineAccessor.setConnection(null); this.engineTaskAccessor.setConnection(null); + this.backfillSampleRowsAccessor.setConnection(null); } public Connection getConnection() { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlEngineSchedulerManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlEngineSchedulerManager.java index 14c1718f2..d22a37246 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlEngineSchedulerManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlEngineSchedulerManager.java @@ -17,6 +17,7 @@ package com.alibaba.polardbx.executor.ddl.newengine.meta; import com.alibaba.polardbx.common.ddl.newengine.DdlState; +import com.alibaba.polardbx.common.ddl.newengine.DdlTaskState; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; @@ -30,6 +31,7 @@ import com.alibaba.polardbx.optimizer.context.DdlContext; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -37,7 +39,7 @@ public class DdlEngineSchedulerManager { protected DdlEngineResourceManager resourceManager = new DdlEngineResourceManager(); - public Pair> fetchJobAndTasks(Long jobId) { + public Pair> fetchJobAndTask(Long jobId) { return new DdlEngineAccessorDelegate>>() { @Override protected Pair> invoke() { @@ -48,6 +50,18 @@ protected Pair> invoke() { }.execute(); } + public Pair> fetchJobAndTask(Long jobId, Long taskId) { + return new DdlEngineAccessorDelegate>>() { + @Override + protected Pair> invoke() { + DdlEngineRecord key = engineAccessor.query(jobId); + DdlEngineTaskRecord task = engineTaskAccessor.query(jobId, taskId); + List value = Collections.singletonList(task); + return Pair.of(key, value); + } + }.execute(); + } + public DdlEngineTaskRecord fetchTaskRecord(long jobId, long taskId) { return new DdlEngineAccessorDelegate() { @Override @@ -75,6 +89,15 @@ protected List invoke() { }.execute(); } + public int querySuccessTaskCount(long jobId) { + return new DdlEngineAccessorDelegate() { + @Override + protected Integer invoke() { + return engineTaskAccessor.querySuccessTaskCount(jobId, DdlTaskState.SUCCESS.name()); + } + }.execute(); + } + public List fetchRecords(List jobIds) { return new DdlEngineAccessorDelegate>() { @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlJobManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlJobManager.java index 3c7411584..9165a2490 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlJobManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/meta/DdlJobManager.java @@ -55,7 +55,6 @@ import com.google.common.base.Function; import com.google.common.base.Preconditions; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.map.HashedMap; import java.sql.Connection; import java.util.ArrayList; @@ -93,6 +92,11 @@ public long storeSubJob(SubJobTask task, DdlJob ddlJob, DdlContext ddlContext, b task.setRollbackSubJobId(jobId); } + if (task.isSkipCdcMarkTask()) { + // subjob 有自己的 ddl context 不用担心被污染 + ddlContext.setSkipSubJobCdcMark(true); + } + DdlEngineRecord jobRecord = buildJobRecord(jobId, ddlJob, ddlContext); List taskRecords = buildTaskRecords(jobId, task.getRootJobId(), ddlJob); @@ -192,12 +196,20 @@ private boolean storeJobImpl(DdlContext ddlContext, DdlJob ddlJob, DdlEngineReco /** * Restore DdlJob & DdlTask from metaDB */ - public Pair restoreJob(long jobId) { + public Pair restoreJob(long jobId, long taskId) { try { - LOGGER.info(String.format("start restoring DDL JOB: [%s]", jobId)); + LOGGER.info(String.format("start restoring DDL JOB: [%d], DDL TASK: [%d]", jobId, taskId)); FailPoint.injectException("FP_RESTORE_DDL_ERROR"); //for now, always rebuild job and task structure from metadata - Pair> jobAndTasks = fetchJobAndTasks(jobId); + Boolean deserializeFullJob; + Pair> jobAndTasks; + if (taskId <= 0L) { + jobAndTasks = fetchJobAndTask(jobId); + deserializeFullJob = true; + } else { + jobAndTasks = fetchJobAndTask(jobId, taskId); + deserializeFullJob = false; + } DdlEngineRecord record = jobAndTasks.getKey(); if (record == null) { throw new TddlRuntimeException(ErrorCode.ERR_GMS_UNEXPECTED, "fetch a DDL job record", @@ -211,7 +223,8 @@ public Pair restoreJob(long jobId) { List taskRecordList = jobAndTasks.getValue(); ExecutableDdlJob ddlJob = - deSerializeTasks(record.taskGraph, TaskHelper.fromDdlEngineTaskRecord(taskRecordList)); + deSerializeTasks(record.taskGraph, TaskHelper.fromDdlEngineTaskRecord(taskRecordList), + deserializeFullJob); ddlJob.setMaxParallelism(record.maxParallelism); @@ -381,10 +394,8 @@ private List buildTaskRecords(Long jobId, Long rootJobId, D return result; } - private ExecutableDdlJob deSerializeTasks(String dagStr, List taskList) { + private ExecutableDdlJob deSerializeTasks(String dagStr, List taskList, Boolean deSerializeFullJob) { DirectedAcyclicGraph taskGraph = DirectedAcyclicGraph.create(); - Map> dag = JSON.parseObject(dagStr, new TypeReference>>() { - }); Map vertexMap = new HashMap<>(taskList.size()); for (DdlTask d : taskList) { if (vertexMap.containsKey(d.getTaskId())) { @@ -395,19 +406,22 @@ private ExecutableDdlJob deSerializeTasks(String dagStr, List taskList) vertexMap.put(d.getTaskId(), vertex); } - for (Map.Entry> entry : dag.entrySet()) { - if (CollectionUtils.isEmpty(entry.getValue())) { - continue; - } + if (deSerializeFullJob) { + Map> dag = JSON.parseObject(dagStr, new TypeReference>>() { + }); + for (Map.Entry> entry : dag.entrySet()) { + if (CollectionUtils.isEmpty(entry.getValue())) { + continue; + } - DirectedAcyclicGraph.Vertex sourceVertex = vertexMap.get(entry.getKey()); + DirectedAcyclicGraph.Vertex sourceVertex = vertexMap.get(entry.getKey()); - for (Long l : entry.getValue()) { - DirectedAcyclicGraph.Vertex targetVertex = vertexMap.get(l); - taskGraph.addEdgeIgnoreCheck(sourceVertex, targetVertex); + for (Long l : entry.getValue()) { + DirectedAcyclicGraph.Vertex targetVertex = vertexMap.get(l); + taskGraph.addEdgeIgnoreCheck(sourceVertex, targetVertex); + } } } - ExecutableDdlJob ddlJob = new ExecutableDdlJob(taskGraph); return ddlJob; } @@ -467,6 +481,7 @@ protected Boolean invoke() { DdlEngineRecord jobRecord = engineAccessor.query(o); validateDdlStateContains(DdlState.valueOf(jobRecord.state), DdlState.FINISHED); int count = engineAccessor.delete(o); + backfillSampleRowsAccessor.deleteByJobId(o); engineTaskAccessor.deleteByJobId(o); if (o == jobId) { @@ -514,6 +529,7 @@ private static void deleteArchive(List archiveDdlEngineRecords) protected Boolean invoke() { engineAccessor.deleteArchive(jobId); engineTaskAccessor.deleteArchiveByJobId(jobId); + backfillSampleRowsAccessor.deleteArchiveByJobId(jobId); return true; } }.execute(); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/resource/DdlEngineResources.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/resource/DdlEngineResources.java new file mode 100644 index 000000000..b8521a8db --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/resource/DdlEngineResources.java @@ -0,0 +1,184 @@ +package com.alibaba.polardbx.executor.ddl.newengine.resource; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.druid.util.StringUtils; +import io.grpc.netty.shaded.io.netty.util.internal.StringUtil; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +public class DdlEngineResources { + + public static DdlEngineResources copyFrom(DdlEngineResources ddlEngineResources) { + return new DdlEngineResources(ddlEngineResources.resources, null, false); + } + + public static Map coverredBefore = new ConcurrentHashMap<>(); + + public static Boolean markNotCoverredBefore(Long taskId) { + if (coverredBefore.containsKey(taskId)) { + return true; + } else { + coverredBefore.put(taskId, true); + return false; + } + } + + public static String extractHost(String resource) { + int index = resource.lastIndexOf(":"); + if (index == -1) { + return resource; + } else if (index == 0) { + return "MASTER_CN"; + } else { + return resource.substring(0, index); + } + } + + public static String extractResourceType(String resource) { + int index = resource.lastIndexOf(":"); + if (index == -1) { + return ""; + } else { + return resource.substring(index + 1, resource.length()); + } + } + + public static String digestCoverInfo(DdlEngineResources resourceAcquired, DdlEngineResources ddlEngineResources) { + Boolean covered = true; + String digestInfoFmt = "required %s[amount=%d], residue %s[amount=%d, waitInfo=%s];"; + List digestInfos = new ArrayList<>(); + for (String resourceName : resourceAcquired.resources.keySet()) { + String fullResourceName = concateServerKeyAndResource(resourceAcquired.getServerKey(), resourceName); + if (ddlEngineResources.resources.containsKey(fullResourceName)) { + if (!ddlEngineResources.resources.get(fullResourceName) + .cover(resourceAcquired.resources.get(resourceName))) { + covered = false; + digestInfos.add( + String.format(digestInfoFmt, fullResourceName, + resourceAcquired.resources.get(resourceName).amount, + fullResourceName, ddlEngineResources.resources.get(resourceName).amount, + ddlEngineResources.resources.get(resourceName).getOwnerMap().toString())); + } + } + } + String digestInfo = StringUtil.join("\n", digestInfos).toString(); + return digestInfo; + + } + + public Map getResources() { + return resources; + } + + public void setResources( + Map resources) { + this.resources = resources; + } + + public Map resources = new ConcurrentHashMap<>(); + + public String getServerKey() { + return serverKey; + } + + public void setServerKey(String serverKey) { + this.serverKey = serverKey; + } + + public String serverKey = null; + + public Boolean getWithRemoteServer() { + return withRemoteServer; + } + + public void setWithRemoteServer(Boolean withRemoteServer) { + this.withRemoteServer = withRemoteServer; + } + + public Boolean withRemoteServer = false; + + public DdlEngineResources() { + } + + @JSONCreator + public DdlEngineResources(Map resources, String serverKey, Boolean withRemoteServer) { + this.resources = resources; + this.serverKey = serverKey; + this.withRemoteServer = withRemoteServer; + } + + public Boolean containsKey(String resourceName) { + return resources.containsKey(resourceName); + } + + public void request(String resourceName, Long amount) { + resources.put(resourceName, new ResourceContainer(amount, null)); + } + + public void request(String resourceName, Long amount, String owner) { + resources.put(resourceName, new ResourceContainer(amount, owner)); + } + + public void preAllocate(String resourceName, Long amount) { + resources.put(resourceName, new ResourceContainer(amount, null)); + } + + public void allocate(DdlEngineResources resourceAcquired) { + for (String resourceName : resourceAcquired.resources.keySet()) { + String fullResourceName = concateServerKeyAndResource(resourceAcquired.getServerKey(), resourceName); + if (resources.containsKey(fullResourceName)) { + resources.get(fullResourceName).allocate(resourceAcquired.resources.get(resourceName)); + } + } + } + + public void free(DdlEngineResources resourceAcquired) { + for (String resourceName : resourceAcquired.resources.keySet()) { + String fullResourceName = concateServerKeyAndResource(resourceAcquired.getServerKey(), resourceName); + if (resources.containsKey(fullResourceName)) { + resources.get(fullResourceName).free(resourceAcquired.resources.get(resourceName)); + } + } + } + + public Boolean cover(DdlEngineResources resourceAcquired) { + Boolean covered = true; + for (String resourceName : resourceAcquired.resources.keySet()) { + String fullResourceName = concateServerKeyAndResource(resourceAcquired.getServerKey(), resourceName); + if (resources.containsKey(fullResourceName)) { + if (!resources.get(fullResourceName).cover(resourceAcquired.resources.get(resourceName))) { + covered = false; + return covered; + } + } + } + return covered; + } + + @Override + public String toString() { + return resources.entrySet().toString(); + } + + public static Boolean isServerResource(String resource) { + return !StringUtils.isEmpty(resource) && resource.startsWith(":CN"); + } + + public static String concateServerKeyAndResource(String serverKey, String resource) { + if (isServerResource(resource) && !StringUtils.isEmpty(serverKey)) { + return serverKey + resource; + } else { + return resource; + } + } + + public static String normalizeServerKey(String serverKey) { + return Optional.ofNullable(serverKey).orElse(""); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/resource/ResourceContainer.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/resource/ResourceContainer.java new file mode 100644 index 000000000..b3b1d761e --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/resource/ResourceContainer.java @@ -0,0 +1,114 @@ +package com.alibaba.polardbx.executor.ddl.newengine.resource; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.polardbx.common.utils.Pair; + +import java.util.HashMap; +import java.util.Map; + +public class ResourceContainer { + public long getAmount() { + return amount; + } + + public void setAmount(long amount) { + this.amount = amount; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public Map> getOwnerMap() { + return ownerMap; + } + + public void setOwnerMap( + Map> ownerMap) { + this.ownerMap = ownerMap; + } + + long amount; + String owner; + // ownerList: owner => (amount, shares) + Map> ownerMap; + + ResourceContainer() { + this.amount = 0; + this.owner = null; + this.ownerMap = new HashMap<>(); + } + + ResourceContainer(Long amount, String owner) { + this.amount = amount; + this.owner = owner; + this.ownerMap = new HashMap<>(); + } + + @JSONCreator + ResourceContainer(Long amount, String owner, Map> ownerMap) { + this.amount = amount; + this.owner = owner; + this.ownerMap = ownerMap; + } + + public Boolean allocate(ResourceContainer ddlEngineResource) { + Boolean allocated = false; + if (ddlEngineResource.owner == null) { + amount -= ddlEngineResource.amount; + allocated = true; + } else if (!ownerMap.containsKey(ddlEngineResource.owner)) { + amount -= ddlEngineResource.amount; + ownerMap.put(ddlEngineResource.owner, Pair.of(ddlEngineResource.amount, 1L)); + allocated = true; + } else { + Pair pair = ownerMap.get(ddlEngineResource.owner); + Pair newPair = Pair.of(ddlEngineResource.amount, pair.getValue() + 1); + amount -= ddlEngineResource.amount - pair.getKey(); + ownerMap.put(ddlEngineResource.owner, newPair); + allocated = true; + } + return allocated; + } + + @Override + public String toString() { + if (ownerMap == null || ownerMap.isEmpty()) { + return String.format("[amount=%d,owner=%s]", amount, owner); + } else { + return String.format("[amount=%d,ownerMap=%s]", amount, ownerMap.toString()); + } + } + + public Boolean cover(ResourceContainer ddlEngineResource) { + Boolean covered = false; + if (ddlEngineResource.owner == null || !ownerMap.containsKey(ddlEngineResource.owner)) { + if (amount >= ddlEngineResource.amount) { + covered = true; + } + } else { + if (amount >= ddlEngineResource.amount - ownerMap.get(ddlEngineResource.owner).getKey()) { + covered = true; + } + } + return covered; + } + + public void free(ResourceContainer ddlEngineResource) { + if (ddlEngineResource.owner == null) { + amount += ddlEngineResource.amount; + } else { + Pair pair = ownerMap.get(ddlEngineResource.owner); + if (pair.getValue() <= 1) { + amount += pair.getKey(); + ownerMap.remove(ddlEngineResource.owner); + } else { + ownerMap.put(ddlEngineResource.owner, Pair.of(pair.getKey(), pair.getValue() - 1)); + } + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/sync/DdlInterruptSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/sync/DdlInterruptSyncAction.java index d21536153..10cd52000 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/sync/DdlInterruptSyncAction.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/sync/DdlInterruptSyncAction.java @@ -23,6 +23,8 @@ import com.alibaba.polardbx.gms.sync.IGmsSyncAction; import org.apache.commons.collections.CollectionUtils; +import java.util.List; + public class DdlInterruptSyncAction implements IGmsSyncAction { private static final Logger logger = LoggerFactory.getLogger(DdlInterruptSyncAction.class); @@ -48,14 +50,26 @@ public Object sync() { if (ddlEngineDagExecutor == null) { logger.warn( String.format("The ddl job %s on schema %s does not exits", jobId, schemaName)); - continue; + } else { + ddlEngineDagExecutor.interrupt(); + logger.warn( + String.format("The ddl job %s on schema %s has been interrupted by DdlInterruptSyncAction", jobId, + schemaName)); + } + List + remoteDdlEngineDagExecutorList = DdlEngineDagExecutorMap.getRemoteJobExecutors(schemaName, jobId); + if (remoteDdlEngineDagExecutorList == null) { + logger.warn( + String.format("The ddl job %s remote executor on schema %s does not exits", jobId, schemaName)); + } else { + remoteDdlEngineDagExecutorList.stream().forEach(o -> o.interrupt()); + logger.warn( + String.format( + "The ddl job %s remote executor on schema %s has been interrupted by DdlInterruptSyncAction", + jobId, + schemaName)); } - ddlEngineDagExecutor.interrupt(); - logger.warn( - String.format("The ddl job %s on schema %s has been interrupted by DdlInterruptSyncAction", jobId, - schemaName)); } - return null; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/utils/DdlHelper.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/utils/DdlHelper.java index 9f89092c3..be61315c3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/utils/DdlHelper.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/utils/DdlHelper.java @@ -126,7 +126,7 @@ public class DdlHelper { - public static final Long COMPRESS_THRESHOLD_SIZE = 1024 * 1024L; + public static final Long COMPRESS_THRESHOLD_SIZE = 128 * 1024L; private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); private static final Set SYSTEM_SCHEMATA = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); @@ -743,6 +743,8 @@ public static boolean getInstConfigAsBoolean(Logger logger, String key, boolean } } + // How to view the compressed content in linux command line: cat 1.txt | base64 --decode | gzip -d | jq . + public static String compress(String data) { try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(bos)) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/utils/DdlResourceManagerUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/utils/DdlResourceManagerUtils.java new file mode 100644 index 000000000..a960dc3bf --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/newengine/utils/DdlResourceManagerUtils.java @@ -0,0 +1,61 @@ +package com.alibaba.polardbx.executor.ddl.newengine.utils; + +import com.alibaba.polardbx.executor.ddl.newengine.resource.DdlEngineResources; +import com.alibaba.polardbx.gms.node.GmsNodeManager; +import com.alibaba.polardbx.optimizer.config.table.ScaleOutPlanUtil; + +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +public class DdlResourceManagerUtils { + public static final String DN_STORAGE = ":DN_STORAGE"; + public static final String DN_NETWORK = ":DN_NETWORK"; + public static final String DN_IO = ":DN_IO"; + public static final String DN_SYSTEM_LOCK = ":DN_SYSTEM_LOCK"; + public static final String DN_CPU = ":DN_CPU"; + public static final String CN_NETWORK = ":CN_NETWORK"; + public static final String CN_CPU = ":CN_CPU"; + + public static void initializeResources(DdlEngineResources resourceToAllocate) { + List readyStorageInsts = ScaleOutPlanUtil.getStorageInstReady(); + for (String storageInst : readyStorageInsts) { + if (!resourceToAllocate.containsKey(storageInst)) { + resourceToAllocate.preAllocate(storageInst, 100L); + resourceToAllocate.preAllocate(storageInst + DN_NETWORK, 100L); + resourceToAllocate.preAllocate(storageInst + DN_IO, 100L); + resourceToAllocate.preAllocate(storageInst + DN_CPU, 100L); + resourceToAllocate.preAllocate(storageInst + DN_SYSTEM_LOCK, 100L); + + } + } + if (!resourceToAllocate.containsKey(CN_CPU)) { + resourceToAllocate.preAllocate(CN_CPU, 100L); + } + if (!resourceToAllocate.containsKey(CN_NETWORK)) { + resourceToAllocate.preAllocate(CN_NETWORK, 100L); + } + List remoteNodeList = GmsNodeManager.getInstance().getRemoteNodes(); + List remoteServers = remoteNodeList.stream().map(GmsNodeManager.GmsNode::getServerKey).collect( + Collectors.toList()); + initializeResourcesForRemoteServer(resourceToAllocate, remoteServers); + } + + public static void initializeResourcesForRemoteServer(DdlEngineResources resourceToAllocate, + List remoteServers) { + if (!resourceToAllocate.getWithRemoteServer()) { + for (String remoteServer : remoteServers) { + if (remoteServer == null) { + continue; + } + if (!resourceToAllocate.containsKey(remoteServer + CN_CPU)) { + resourceToAllocate.preAllocate(remoteServer + CN_CPU, 100L); + } + if (!resourceToAllocate.containsKey(remoteServer + CN_NETWORK)) { + resourceToAllocate.preAllocate(remoteServer + CN_NETWORK, 100L); + } + } + resourceToAllocate.setWithRemoteServer(true); + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/util/ChangeSetUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/util/ChangeSetUtils.java index adfc9f3e0..a9cd49f1b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/util/ChangeSetUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/ddl/util/ChangeSetUtils.java @@ -28,6 +28,7 @@ import com.alibaba.polardbx.executor.ExecutorHelper; import com.alibaba.polardbx.executor.changeset.ChangeSetManager; import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.common.TopologyHandler; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.changset.ChangeSetApplyFinishTask; @@ -59,6 +60,7 @@ import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.datatype.EnumType; +import com.alibaba.polardbx.optimizer.core.datatype.FloatType; import com.alibaba.polardbx.optimizer.core.datatype.TinyIntType; import com.alibaba.polardbx.optimizer.core.datatype.UTinyIntType; import com.alibaba.polardbx.optimizer.core.datatype.YearType; @@ -102,6 +104,7 @@ import static com.alibaba.polardbx.common.properties.ConnectionParams.CHANGE_SET_APPLY_OPTIMIZATION; import static com.alibaba.polardbx.common.properties.ConnectionParams.CHANGE_SET_CHECK_TWICE; +import static com.alibaba.polardbx.executor.columns.ColumnBackfillExecutor.isAllDnUseXDataSource; public class ChangeSetUtils { public final static String SQL_START_CHANGESET = "call polarx.changeset_start(%s, %s);"; @@ -825,6 +828,14 @@ public static boolean supportUseChangeSet(ComplexTaskMetaManager.ComplexTaskType return false; } + final ExecutorContext executorContext = ExecutorContext.getContext(tableMeta.getSchemaName()); + final TopologyHandler topologyHandler = executorContext.getTopologyHandler(); + final boolean allDnUseXDataSource = isAllDnUseXDataSource(topologyHandler); + if (!allDnUseXDataSource && tableMeta.getPrimaryKey().stream() + .anyMatch(columnMeta -> columnMeta.getDataType() instanceof FloatType)) { + return false; + } + return true; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/fastchecker/FastChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/fastchecker/FastChecker.java index f6a6c77ca..e53124f94 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/fastchecker/FastChecker.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/fastchecker/FastChecker.java @@ -16,7 +16,6 @@ package com.alibaba.polardbx.executor.fastchecker; -import com.alibaba.polardbx.common.ddl.newengine.DdlTaskState; import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; @@ -34,25 +33,16 @@ import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.ddl.newengine.cross.CrossEngineValidator; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; -import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlEngineAccessorDelegate; -import com.alibaba.polardbx.executor.ddl.newengine.utils.TaskHelper; import com.alibaba.polardbx.executor.ddl.util.ChangeSetUtils; import com.alibaba.polardbx.executor.ddl.workqueue.FastCheckerThreadPool; -import com.alibaba.polardbx.executor.ddl.workqueue.BackFillThreadPool; -import com.alibaba.polardbx.executor.ddl.workqueue.PriorityFIFOTask; import com.alibaba.polardbx.executor.gsi.CheckerManager; import com.alibaba.polardbx.executor.gsi.GsiUtils; import com.alibaba.polardbx.executor.gsi.PhysicalPlanBuilder; import com.alibaba.polardbx.executor.gsi.utils.Transformer; import com.alibaba.polardbx.executor.spi.ITransactionManager; -import com.alibaba.polardbx.executor.sync.SyncManagerHelper; -import com.alibaba.polardbx.executor.sync.TablesMetaChangePreemptiveSyncAction; import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; -import com.alibaba.polardbx.gms.metadb.misc.DdlEngineTaskRecord; -import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; import com.alibaba.polardbx.gms.topology.GroupDetailInfoAccessor; import com.alibaba.polardbx.gms.topology.ServerInstIdManager; -import com.alibaba.polardbx.gms.sync.SyncScope; import com.alibaba.polardbx.gms.util.GroupInfoUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; @@ -89,7 +79,6 @@ import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -98,11 +87,11 @@ public class FastChecker extends PhyOperationBuilderCommon { private static final Logger logger = LoggerFactory.getLogger(FastChecker.class); - private final String srcSchemaName; + protected final String srcSchemaName; - private final String dstSchemaName; - private final String srcLogicalTableName; - private final String dstLogicalTableName; + protected final String dstSchemaName; + protected final String srcLogicalTableName; + protected final String dstLogicalTableName; private Map> srcPhyDbAndTables; private Map> dstPhyDbAndTables; private final List srcColumns; @@ -127,8 +116,8 @@ public class FastChecker extends PhyOperationBuilderCommon { private final PhyTableOperation planSelectSampleSrc; private final PhyTableOperation planSelectSampleDst; - private volatile AtomicInteger phyTaskSum; - private volatile AtomicInteger phyTaskFinished; + protected volatile AtomicInteger phyTaskSum; + protected volatile AtomicInteger phyTaskFinished; /** * srcColumns and dstColumns must have the same order, @@ -201,7 +190,7 @@ public static FastChecker create(String schemaName, String tableName, final List allColumns = tableMeta.getAllColumns().stream().map(ColumnMeta::getName).collect(Collectors.toList()); final List allColumnsDst = new ArrayList<>(allColumns); - final List srcPks = getorderedPrimaryKeys(tableMeta); + final List srcPks = getOrderedPrimaryKeys(tableMeta); final List dstPks = new ArrayList<>(srcPks); final PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, ec); @@ -225,7 +214,7 @@ public static FastChecker create(String schemaName, String tableName, builder.buildSqlSelectForSample(tableMeta, dstPks)); } - private long getTableRowsCount(final String schema, final String dbIndex, final String phyTable) { + protected long getTableRowsCount(final String schema, final String dbIndex, final String phyTable) { String dbIndexWithoutGroup = GroupInfoUtil.buildPhysicalDbNameFromGroupName(dbIndex); List> phyDb = StatsUtils.queryGroupByPhyDb(schema, dbIndexWithoutGroup, "select database();"); if (GeneralUtil.isEmpty(phyDb) || GeneralUtil.isEmpty(phyDb.get(0))) { @@ -244,7 +233,7 @@ private long getTableRowsCount(final String schema, final String dbIndex, final return Long.parseLong(String.valueOf(result.get(0).get(0))); } - private long getTableAvgRowSize(final String schema, final String dbIndex, final String phyTable) { + protected long getTableAvgRowSize(final String schema, final String dbIndex, final String phyTable) { String dbIndexWithoutGroup = GroupInfoUtil.buildPhysicalDbNameFromGroupName(dbIndex); List> phyDb = StatsUtils.queryGroupByPhyDb(schema, dbIndexWithoutGroup, "select database();"); if (GeneralUtil.isEmpty(phyDb) || GeneralUtil.isEmpty(phyDb.get(0))) { @@ -271,7 +260,7 @@ private PhyTableOperation buildSamplePlanWithParam(String dbIndex, String phyTab PhyTableOperation phyTableOperation = isSrcSchema ? this.planSelectSampleSrc : this.planSelectSampleDst; SqlSelect sqlSelect = (SqlSelect) phyTableOperation.getNativeSqlNode().clone(); OptimizerHint optimizerHint = new OptimizerHint(); - optimizerHint.addHint("+sample_percentage(" + calSamplePercentage + ")"); + optimizerHint.addHint("+sample_percentage(" + GeneralUtil.formatSampleRate(calSamplePercentage) + ")"); sqlSelect.setOptimizerHint(optimizerHint); PhyTableOpBuildParams buildParams = new PhyTableOpBuildParams(); @@ -330,11 +319,11 @@ private PhyTableOperation buildHashcheckPlanWithDnfParam(String dbIndex, String } //for large table, we split table into batch - private List> splitPhyTableIntoBatch(final ExecutionContext baseEc, - final String phyDbName, final String phyTable, - final long tableRowsCount, - final long batchSize, - final boolean isSrcSchema) { + protected List> splitPhyTableIntoBatch(final ExecutionContext baseEc, + final String phyDbName, final String phyTable, + final long tableRowsCount, + final long batchSize, + final boolean isSrcSchema) { boolean enableInnodbBtreeSampling = OptimizerContext.getContext(srcSchemaName).getParamManager() .getBoolean(ConnectionParams.ENABLE_INNODB_BTREE_SAMPLING); @@ -461,13 +450,8 @@ private List> splitPhyTableIntoBatch(final Execut return returnedSampledRowsPc; } - private Long getPhyTableDegistByBatch(String phyDbName, String phyTable, ExecutionContext baseEc, - boolean isSrcTableTask, List> batchBoundList) { - if (batchBoundList.isEmpty()) { - return null; - } - - List hashResults = new ArrayList<>(); + protected List genHashCheckPlans(String phyDbName, String phyTable, boolean isSrcTableTask, + List> batchBoundList) { List hashcheckPlans = new ArrayList<>(); Map firstBound = null, lastBound = null; @@ -512,18 +496,20 @@ private Long getPhyTableDegistByBatch(String phyDbName, String phyTable, Executi } hashcheckPlans.add( buildHashcheckPlanWithDnfParam(phyDbName, phyTable, lastBoundPc, operationLastBound, true, false)); + return hashcheckPlans; + } - //log batch sql -// for (int i = 0; i < hashcheckPlans.size(); i++) { -// SQLRecorderLogger.ddlLogger.info(MessageFormat.format( -// "[{0}] FastChecker {1}[{2}][{3}], batch {4}, phySqlInfo: {5}, param: {6}", -// baseEc.getTraceId(), phyDbName, phyTable, isSrcTableTask ? "src" : "dst", i, -// hashcheckPlans.get(i).getBytesSql(), hashcheckPlans.get(i).getParam())); -// } - - //excute - for (int i = 0; i < hashcheckPlans.size(); i++) { - PhyTableOperation phyPlan = hashcheckPlans.get(i); + private Long getPhyTableDigestByBatch(String phyDbName, String phyTable, ExecutionContext baseEc, + boolean isSrcTableTask, List> batchBoundList) { + if (batchBoundList.isEmpty()) { + return null; + } + + List hashResults = new ArrayList<>(); + List hashCheckPlans = genHashCheckPlans(phyDbName, phyTable, isSrcTableTask, batchBoundList); + + // execute + for (PhyTableOperation phyPlan : hashCheckPlans) { Long batchHashResult = executeHashcheckPlan(phyPlan, baseEc); if (batchHashResult != null) { hashResults.add(batchHashResult); @@ -539,22 +525,15 @@ private Long getPhyTableDegistByBatch(String phyDbName, String phyTable, Executi return null; } - final HashCaculator caculator = new HashCaculator(); + final HashCalculator calculator = new HashCalculator(); for (Long elem : hashResults) { - caculator.caculate(elem); + calculator.calculate(elem); } - return caculator.getHashVal(); + return calculator.getHashVal(); } - private Long getPhyTableDegistByFullScan(String phyDbName, String phyTable, ExecutionContext baseEc, - boolean isSrcTableTask) { - - if (CrossEngineValidator.isJobInterrupted(baseEc) || Thread.currentThread().isInterrupted()) { - long jobId = baseEc.getDdlJobId(); - throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, - "The job '" + jobId + "' has been cancelled"); - } - + protected PhyTableOperation genHashCheckPlan(String phyDbName, String phyTable, ExecutionContext baseEc, + boolean isSrcTableTask) { final Map params = new HashMap<>(1); params.put(1, PlannerUtils.buildParameterContextForTableName(phyTable, 1)); @@ -571,6 +550,20 @@ private Long getPhyTableDegistByFullScan(String phyDbName, String phyTable, Exec "[{0}] FastChecker {1}[{2}][{3}], full scan, phySqlInfo: {4}", baseEc.getTraceId(), phyDbName, phyTable, isSrcTableTask ? "src" : "dst", plan)); + return plan; + } + + private Long getPhyTableDigestByFullScan(String phyDbName, String phyTable, ExecutionContext baseEc, + boolean isSrcTableTask) { + + if (CrossEngineValidator.isJobInterrupted(baseEc) || Thread.currentThread().isInterrupted()) { + long jobId = baseEc.getDdlJobId(); + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + "The job '" + jobId + "' has been cancelled"); + } + + PhyTableOperation plan = genHashCheckPlan(phyDbName, phyTable, baseEc, isSrcTableTask); + return executeHashcheckPlan(plan, baseEc); } @@ -598,7 +591,7 @@ private Long executeHashcheckPlan(PhyTableOperation plan, ExecutionContext ec) { * 1. 含local partition的表将不进行batch check (因为sample结果是乱序的) * 2. 逻辑表为unique gsi的表将不进行batch check (因为其物理表只含主键列,但主键列没有主键属性) */ - private boolean whetherCanSplitIntoBatch(ExecutionContext baseEc, boolean isSrc) { + protected boolean whetherCanSplitIntoBatch(ExecutionContext baseEc, boolean isSrc) { //won't do sample for local partition table TableMeta tableMeta = isSrc ? baseEc.getSchemaManager(srcSchemaName).getTable(srcLogicalTableName) @@ -663,7 +656,7 @@ private Pair hashCheckForSinglePhyTable(String phyDbName, String baseEc.getTraceId(), phyDbName, phyTable, isSrcTableTask ? "src" : "dst", batchBoundList.size() + 1)); - hashResult = getPhyTableDegistByBatch(phyDbName, phyTable, baseEc, isSrcTableTask, batchBoundList); + hashResult = getPhyTableDigestByBatch(phyDbName, phyTable, baseEc, isSrcTableTask, batchBoundList); } else { failedToSplitBatch = true; } @@ -674,7 +667,7 @@ private Pair hashCheckForSinglePhyTable(String phyDbName, String "[{0}] FastChecker start hash phy for {1}[{2}][{3}], and phy table is hashed by full scan", baseEc.getTraceId(), phyDbName, phyTable, isSrcTableTask ? "src" : "dst")); - hashResult = getPhyTableDegistByFullScan(phyDbName, phyTable, baseEc, isSrcTableTask); + hashResult = getPhyTableDigestByFullScan(phyDbName, phyTable, baseEc, isSrcTableTask); } @@ -1020,10 +1013,10 @@ protected boolean parallelCheck(Map> srcDbAndTb, } List srcResult = - result.stream().filter(p -> p != null && p.getKey() != null && p.getValue() == true).map(Pair::getKey) + result.stream().filter(p -> p != null && p.getKey() != null && p.getValue()).map(Pair::getKey) .collect(Collectors.toList()); List dstResult = - result.stream().filter(p -> p != null && p.getKey() != null && p.getValue() == false).map(Pair::getKey) + result.stream().filter(p -> p != null && p.getKey() != null && !p.getValue()).map(Pair::getKey) .collect(Collectors.toList()); return srcTableTaskCount == result.stream().filter(Objects::nonNull).filter(Pair::getValue).count() @@ -1032,11 +1025,11 @@ protected boolean parallelCheck(Map> srcDbAndTb, } private boolean compare(List src, List dst) { - final HashCaculator srcCaculator = new HashCaculator(); - final HashCaculator dstCaculator = new HashCaculator(); - src.forEach(elem -> srcCaculator.caculate(elem)); - dst.forEach(elem -> dstCaculator.caculate(elem)); - return srcCaculator.getHashVal().equals(dstCaculator.getHashVal()); + final HashCalculator srcCalculator = new HashCalculator(); + final HashCalculator dstCalculator = new HashCalculator(); + src.forEach(srcCalculator::calculate); + dst.forEach(dstCalculator::calculate); + return srcCalculator.getHashVal().equals(dstCalculator.getHashVal()); } public void reportCheckOk(ExecutionContext ec) { @@ -1049,7 +1042,7 @@ public void reportCheckOk(ExecutionContext ec) { CheckerManager.CheckerReportStatus.FINISH.getValue(), "--", finishDetails, "Reporter.", null))); } - class HashCaculator { + public class HashCalculator { private final Long p; private final Long q; private final Long r; @@ -1058,7 +1051,7 @@ class HashCaculator { private boolean firstCaculate; //p q r should be same as p q r in DN - public HashCaculator() { + public HashCalculator() { p = 3860031L; q = 2779L; r = 2L; @@ -1066,8 +1059,11 @@ public HashCaculator() { firstCaculate = true; } - public Long caculate(Long elem) { - if (firstCaculate == true) { + public Long calculate(Long elem) { + if (elem == null) { + return hashVal; + } + if (firstCaculate) { hashVal = elem; firstCaculate = false; } else { @@ -1089,20 +1085,19 @@ public void setSrcPhyDbAndTables(Map> srcPhyDbAndTables) { this.srcPhyDbAndTables = srcPhyDbAndTables; } - public static List getorderedPrimaryKeys(TableMeta tableMeta) { - List primaryKeys = ImmutableList + public static List getOrderedPrimaryKeys(TableMeta tableMeta) { + return ImmutableList .copyOf( (tableMeta.isHasPrimaryKey() ? tableMeta.getPrimaryIndex().getKeyColumns() : new ArrayList()) .stream().map(ColumnMeta::getName).collect(Collectors.toList()) ); - return primaryKeys; } /** * map < groupName, storageInstId > */ - private Map queryStorageInstIdByPhyGroup(Set groupName) { + protected Map queryStorageInstIdByPhyGroup(Set groupName) { try (Connection metaDbConn = MetaDbDataSource.getInstance().getConnection()) { GroupDetailInfoAccessor groupDetailInfoAccessor = new GroupDetailInfoAccessor(); groupDetailInfoAccessor.setConnection(metaDbConn); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/ColumnarManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/ColumnarManager.java index 49de01ac8..15e2fd14f 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/ColumnarManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/ColumnarManager.java @@ -18,12 +18,12 @@ import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.chunk.Chunk; -import com.alibaba.polardbx.executor.chunk.IntegerBlock; +import com.alibaba.polardbx.executor.chunk.LongBlock; import com.alibaba.polardbx.optimizer.config.table.FileMeta; -import com.alibaba.polardbx.optimizer.context.ExecutionContext; import org.apache.hadoop.hive.ql.exec.vector.LongColumnVector; import org.roaringbitmap.RoaringBitmap; +import java.util.Iterator; import java.util.List; /** @@ -40,6 +40,13 @@ static ColumnarManager getInstance() { */ void reload(); + /** + * Reload the columnar manager of current CN + * + * @param type reload type: ALL, SCHEMA_ONLY, CACHE_ONLY, SNAPSHOT_ONLY + */ + void reload(ReloadType type); + /** * Get the latest tso at which the columnar snapshot is visible. * @@ -97,11 +104,16 @@ Pair, List> findFileNames(long tso, String logicalSchema, S * @param csvFileName csv file name. * @return Collection of csv cache data (in format of chunk) */ - List csvData(long tso, String csvFileName); + Iterator csvData(long tso, String csvFileName); - default List rawCsvData(long tso, String csvFileName, ExecutionContext context) { - return null; - } + /** + * Get csv data cache of given file name for flashback query + * + * @param csvFileName csv file name. + * @param position end position of the csv file. + * @return Collection of csv cache data (in format of chunk) + */ + Iterator csvData(String csvFileName, long position); /** * Fill the given selection array according to snapshot of tso, file name and position block @@ -114,7 +126,7 @@ default List rawCsvData(long tso, String csvFileName, ExecutionContext co * @return filled size of selection array. */ @Deprecated - int fillSelection(String fileName, long tso, int[] selection, IntegerBlock positionBlock); + int fillSelection(String fileName, long tso, int[] selection, LongBlock positionBlock); @Deprecated int fillSelection(String fileName, long tso, int[] selection, LongColumnVector longColumnVector, int batchSize); @@ -127,4 +139,8 @@ default List rawCsvData(long tso, String csvFileName, ExecutionContext co * @return copy of corresponding delete bitmap */ RoaringBitmap getDeleteBitMapOf(long tso, String fileName); + + public static enum ReloadType { + ALL, SCHEMA_ONLY, CACHE_ONLY, SNAPSHOT_ONLY + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/DynamicColumnarManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/DynamicColumnarManager.java index 258afc83e..95048be49 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/DynamicColumnarManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/DynamicColumnarManager.java @@ -16,20 +16,28 @@ package com.alibaba.polardbx.executor.gms; +import com.alibaba.polardbx.common.Engine; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.model.lifecycle.AbstractLifecycle; import com.alibaba.polardbx.common.oss.ColumnarFileType; import com.alibaba.polardbx.common.oss.OSSFileType; +import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.archive.schemaevolution.ColumnMetaWithTs; import com.alibaba.polardbx.executor.chunk.Chunk; -import com.alibaba.polardbx.executor.chunk.IntegerBlock; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.columnar.CsvDataIterator; +import com.alibaba.polardbx.executor.columnar.SimpleCSVFileReader; import com.alibaba.polardbx.executor.gms.util.ColumnarTransactionUtils; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.engine.FileSystemUtils; import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarFileMappingAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarFileMappingRecord; import com.alibaba.polardbx.gms.metadb.table.FilesAccessor; @@ -37,23 +45,28 @@ import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.config.table.FileMeta; -import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.google.common.base.Preconditions; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; import org.apache.hadoop.hive.ql.exec.vector.LongColumnVector; +import org.apache.htrace.shaded.fasterxml.jackson.databind.util.EmptyIterator; import org.jetbrains.annotations.NotNull; import org.roaringbitmap.RoaringBitmap; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Queue; +import java.util.Set; +import java.util.SortedMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicLong; @@ -99,7 +112,11 @@ public class DynamicColumnarManager extends AbstractLifecycle implements Columna * cache append file last record: {tso, filename} -> {records} */ private LoadingCache, List> appendFileRecordCache; - private final AtomicLong appendFileAccessCounter = new AtomicLong(); + /** + * cache min compaction tso: checkpoint tso -> min compaction tso + */ + private LoadingCache minCompactionTsoCache; + private AtomicLong appendFileAccessCounter = new AtomicLong(); private volatile Long minTso; private volatile Long latestTso; @@ -136,11 +153,17 @@ public FileVersionStorage getVersionStorage() { /** * This method is for unit test ONLY */ - void injectForTest(FileVersionStorage versionStorage, - MultiVersionColumnarSchema multiVersionColumnarSchema) { + public void injectForTest(FileVersionStorage versionStorage, + MultiVersionColumnarSchema multiVersionColumnarSchema, + AtomicLong appendFileAccessCounter, + LoadingCache, List> appendFileRecordCache) { this.versionStorage = versionStorage; - this.versionStorage.open(); + if (versionStorage != null) { + this.versionStorage.open(); + } this.columnarSchema = multiVersionColumnarSchema; + this.appendFileAccessCounter = appendFileAccessCounter; + this.appendFileRecordCache = appendFileRecordCache; } @Override @@ -240,6 +263,25 @@ public List load(@NotNull Pair tsoAnd } }); + this.minCompactionTsoCache = CacheBuilder.newBuilder() + .maximumSize(256) + .build(new CacheLoader() { + @Override + public Long load(@NotNull Long tso) throws SQLException { + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarCheckpointsAccessor accessor = new ColumnarCheckpointsAccessor(); + accessor.setConnection(connection); + + List checkpointsRecords = accessor.queryValidCheckpointByTso(tso); + if (checkpointsRecords != null && !checkpointsRecords.isEmpty()) { + return checkpointsRecords.get(0).minCompactionTso; + } + + return 0L; + } + } + }); + LOGGER.info("Columnar Manager of has been initialized"); } @@ -261,8 +303,7 @@ public void purge(long tso) { snapshotCache.asMap().values().forEach(snapshot -> snapshot.purge(tso)); for (String fileName = nextPurgedFile(); fileName != null; fileName = nextPurgedFile()) { - ColumnarFileType columnarFileType = - ColumnarFileType.of(fileName.substring(fileName.lastIndexOf('.') + 1)); + ColumnarFileType columnarFileType = FileSystemUtils.getFileType(fileName); fileMetaCache.invalidate(fileName); if (columnarFileType.isDeltaFile()) { @@ -335,6 +376,34 @@ public Pair, List> findFileNames(long tso, String logicalSc } } + public Map, List>> findFileNames(long tso, + String logicalSchema, String logicalTable, + SortedMap> partitionResult) { + if (tso == Long.MIN_VALUE) { + return new HashMap<>(); + } + try { + Long tableId = getTableId(tso, logicalSchema, logicalTable); + return snapshotCache.get( + Pair.of(logicalSchema, tableId) + ).generateSnapshot(partitionResult, tso); + } catch (Throwable e) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, e, + String.format("Failed to generate columnar snapshot of tso: %d", tso)); + } + } + + public SortedMap getPartitionInfos(long tso, String logicalSchema, String logicalTable) { + try { + Long tableId = getTableId(tso, logicalSchema, logicalTable); + long schemaTso = snapshotCache.get(Pair.of(logicalSchema, tableId)).getLatestSchemaTso(tso); + return columnarSchema.getPartitionInfos(schemaTso, tableId); + } catch (Throwable e) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, e, + String.format("Failed to generate columnar partition info of tso: %d", tso)); + } + } + public List delFileNames(long tso, String logicalSchema, String logicalTable, String partName) { if (tso == Long.MIN_VALUE) { @@ -354,16 +423,17 @@ public List delFileNames(long tso, String logicalSchema, String logicalT } @Override - public List csvData(long tso, String csvFileName) { + public Iterator csvData(long tso, String csvFileName) { appendFileAccessCounter.getAndIncrement(); try { List appendedFilesRecords = appendFileRecordCache.get(Pair.of(tso, csvFileName)); if (appendedFilesRecords == null || appendedFilesRecords.isEmpty()) { - return new ArrayList<>(); + return new EmptyIterator<>(); } else { Preconditions.checkArgument(appendedFilesRecords.size() == 1); - return versionStorage.csvData(appendedFilesRecords.get(0).checkpointTso, csvFileName); + // TODO(siyun): async IO + return versionStorage.csvData(appendedFilesRecords.get(0).checkpointTso, csvFileName).iterator(); } } catch (Throwable t) { throw new TddlRuntimeException(ErrorCode.ERR_LOAD_CSV_FILE, t, @@ -372,26 +442,17 @@ public List csvData(long tso, String csvFileName) { } @Override - public List rawCsvData(long tso, String csvFileName, ExecutionContext context) { - appendFileAccessCounter.getAndIncrement(); - try { - List appendedFilesRecords = - appendFileRecordCache.get(Pair.of(tso, csvFileName)); - if (appendedFilesRecords == null || appendedFilesRecords.isEmpty()) { - return new ArrayList<>(); - } else { - Preconditions.checkArgument(appendedFilesRecords.size() == 1); - return versionStorage.csvRawOrcTypeData(appendedFilesRecords.get(0).checkpointTso, - csvFileName, context); - } - } catch (Throwable t) { - throw new TddlRuntimeException(ErrorCode.ERR_LOAD_CSV_FILE, t, - String.format("Failed to load csv file, filename: %s, tso: %d", csvFileName, tso)); - } + public Iterator csvData(String csvFileName, long position) { + FileMeta fileMeta = fileMetaOf(csvFileName); + Engine engine = fileMeta.getEngine(); + List columnMetas = fileMeta.getColumnMetas(); + + // Create and return the chunk iterator + return new CsvDataIterator(new SimpleCSVFileReader(), csvFileName, position, columnMetas, engine); } @Override - public int fillSelection(String fileName, long tso, int[] selection, IntegerBlock positionBlock) { + public int fillSelection(String fileName, long tso, int[] selection, LongBlock positionBlock) { return versionStorage.fillSelection(fileName, tso, selection, positionBlock); } @@ -473,8 +534,15 @@ public long latestTso() { if (latestTso != null) { return latestTso; } - - Long gmsLatestTso = ColumnarTransactionUtils.getLatestTsoFromGms(); + int tsoUpdateDelay = InstConfUtil.getInt(ConnectionParams.COLUMNAR_TSO_UPDATE_DELAY); + Long gmsLatestTso; + if (tsoUpdateDelay > 0) { + gmsLatestTso = ColumnarTransactionUtils.getLatestTsoFromGmsWithDelay( + 1000L * tsoUpdateDelay // convert milliseconds to microseconds + ); + } else { + gmsLatestTso = ColumnarTransactionUtils.getLatestTsoFromGms(); + } latestTso = gmsLatestTso != null ? gmsLatestTso : Long.MIN_VALUE; return latestTso; } @@ -491,7 +559,7 @@ public void setLatestTso(long tso) { } } - private Long getTableId(long tso, String logicalSchema, String logicalTable) { + public Long getTableId(long tso, String logicalSchema, String logicalTable) { try { return columnarSchema.getTableId(tso, logicalSchema, logicalTable); } catch (ExecutionException e) { @@ -554,6 +622,14 @@ public Long getMinTso() { return minTso; } + public long getMinCompactionTso(Long tso) { + try { + return minCompactionTsoCache.get(tso); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + /** * approximate number of entries in this cache */ @@ -574,36 +650,47 @@ public long getAppendFileAccessCount() { @Override public void reload() { + reload(ReloadType.ALL); + } + + @Override + public void reload(ReloadType type) { synchronized (minTsoLock) { minTso = null; synchronized (latestTsoLock) { latestTso = null; - try { - snapshotCache.invalidateAll(); - fileMetaCache.invalidateAll(); - fileIdMapping.invalidateAll(); - appendFileRecordCache.invalidateAll(); - filesToBePurged.clear(); - } catch (Throwable t) { - // ignore + if (type == ReloadType.ALL || type == ReloadType.SNAPSHOT_ONLY) { + try { + snapshotCache.invalidateAll(); + fileMetaCache.invalidateAll(); + fileIdMapping.invalidateAll(); + appendFileRecordCache.invalidateAll(); + minCompactionTsoCache.invalidateAll(); + filesToBePurged.clear(); + } catch (Throwable t) { + // ignore + } } - try { - this.columnarSchema = new MultiVersionColumnarSchema(this); - } catch (Throwable t) { - // ignore + if (type == ReloadType.ALL || type == ReloadType.SCHEMA_ONLY) { + try { + this.columnarSchema = new MultiVersionColumnarSchema(this); + } catch (Throwable t) { + // ignore + } } - try { - this.versionStorage = new FileVersionStorage(this); - this.versionStorage.open(); - } catch (Throwable t) { - // ignore + if (type == ReloadType.ALL || type == ReloadType.CACHE_ONLY) { + try { + this.versionStorage = new FileVersionStorage(this); + this.versionStorage.open(); + } catch (Throwable t) { + // ignore + } } } } LOGGER.info("Columnar Manager of has been reloaded"); } - } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/FileVersionStorage.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/FileVersionStorage.java index 1a8355bbb..1d0ef6476 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/FileVersionStorage.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/FileVersionStorage.java @@ -24,6 +24,7 @@ import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.chunk.IntegerBlock; +import com.alibaba.polardbx.executor.chunk.LongBlock; import com.alibaba.polardbx.executor.columnar.DeletionFileReader; import com.alibaba.polardbx.executor.operator.spill.MemorySpillerFactory; import com.alibaba.polardbx.executor.operator.spill.SpillerFactory; @@ -80,6 +81,7 @@ public class FileVersionStorage implements Closeable, Purgeable { /** * Maintain the already loaded tso for each partition + * TODO(siyun): for multi-version partition info, this map is MIXED with different versions, which should be separated for SPLIT PARTITION */ private LoadingCache delDataTsoMap; @@ -187,16 +189,6 @@ public List csvData(long tso, String csvFileName) { } } - /** - * Read data from csv into memory, never cache. - * - * @param tso this tso must be taken from columnar_appended_files - * @return data in raw orc type: long, double, or byte array - */ - public List csvRawOrcTypeData(long tso, String csvFileName, ExecutionContext context) { - return MultiVersionCsvData.loadRawOrcTypeUntilTso(tso, openedIncrementFileCount, csvFileName, context); - } - // Used for old columnar table scan @Deprecated public int fillSelection(String fileName, long tso, int[] selection, LongColumnVector longColumnVector, @@ -229,7 +221,7 @@ public int fillSelection(String fileName, long tso, int[] selection, LongColumnV // Used for old columnar table scan @Deprecated - public int fillSelection(String fileName, long tso, int[] selection, IntegerBlock positionBlock) { + public int fillSelection(String fileName, long tso, int[] selection, LongBlock positionBlock) { try { RoaringBitmap bitmap = delDataMap.get(fileName).buildDeleteBitMap(tso); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/FlashbackDeleteBitmapManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/FlashbackDeleteBitmapManager.java new file mode 100644 index 000000000..ad2a889c5 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/FlashbackDeleteBitmapManager.java @@ -0,0 +1,114 @@ +package com.alibaba.polardbx.executor.gms; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.model.lifecycle.AbstractLifecycle; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.columnar.DeletionFileReader; +import com.alibaba.polardbx.executor.columnar.SimpleDeletionFileReader; +import com.alibaba.polardbx.optimizer.config.table.FileMeta; +import org.roaringbitmap.RoaringBitmap; + +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + +public class FlashbackDeleteBitmapManager extends AbstractLifecycle { + + private final long flashbackTso; + private final String logicalSchema; + private final String logicalTable; + private final String partName; + private final List> delPositions; + + private final Map loadedBitmaps = new HashMap<>(); + + static final Map> MANAGER_MAP = new WeakHashMap<>(); + + public FlashbackDeleteBitmapManager(long flashbackTso, String logicalSchema, String logicalTable, String partName, + List> delPositions) { + this.flashbackTso = flashbackTso; + this.logicalSchema = logicalSchema; + this.logicalTable = logicalTable; + this.partName = partName; + this.delPositions = delPositions; + } + + synchronized public static FlashbackDeleteBitmapManager getInstance(long flashbackTso, String logicalSchema, + String logicalTable, + String partName, + List> delPositions) { + String key = logicalSchema + "." + logicalTable + "." + partName + "." + flashbackTso; + WeakReference ref = MANAGER_MAP.get(key); + FlashbackDeleteBitmapManager manager = ref == null ? null : ref.get(); + if (manager == null) { + manager = + new FlashbackDeleteBitmapManager(flashbackTso, logicalSchema, logicalTable, partName, delPositions); + MANAGER_MAP.entrySet().removeIf(entry -> entry.getValue().get() == null); + + MANAGER_MAP.put(key, new WeakReference<>(manager)); + // init() can not be called here since it is synchronized and would block the loading of delete bitmap + } + return manager; + } + + @Override + protected void doInit() { + if (delPositions == null) { + return; + } + + for (Pair delPosition : delPositions) { + String deleteFileName = delPosition.getKey(); + Long readPos = delPosition.getValue(); + FileMeta deleteFileMeta = ColumnarManager.getInstance().fileMetaOf(deleteFileName); + long tableId = Long.parseLong(deleteFileMeta.getLogicalTableName()); + Engine engine = deleteFileMeta.getEngine(); + + try (SimpleDeletionFileReader fileReader = new SimpleDeletionFileReader()) { + try { + fileReader.open( + engine, + deleteFileName, + 0, + readPos.intValue() + ); + } catch (IOException e) { + throw new TddlRuntimeException(ErrorCode.ERR_LOAD_DEL_FILE, e, + String.format("Failed to open delete bitmap file, filename: %s, offset: %d, length: %d", + deleteFileName, 0, readPos)); + } + + DeletionFileReader.DeletionEntry entry; + while (fileReader.position() < readPos && (entry = fileReader.next()) != null) { + final int fileId = entry.getFileId(); + final RoaringBitmap bitmap = entry.getBitmap(); + ColumnarManager.getInstance().fileNameOf(logicalSchema, tableId, partName, fileId) + .ifPresent(fileName -> loadedBitmaps.compute(fileName, (k, v) -> { + if (v == null) { + return bitmap; + } else { + v.or(bitmap); + return v; + } + })); + } + } + + } + } + + @Override + protected void doDestroy() { + loadedBitmaps.clear(); + } + + public RoaringBitmap getDeleteBitmapOf(String fileName) { + init(); + return loadedBitmaps.getOrDefault(fileName, new RoaringBitmap()); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/GmsTableMetaManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/GmsTableMetaManager.java index f2a868413..1f9f34621 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/GmsTableMetaManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/GmsTableMetaManager.java @@ -38,6 +38,7 @@ import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.common.RecycleBin; import com.alibaba.polardbx.executor.common.StorageInfoManager; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler.TtlScheduledJobStatManager; import com.alibaba.polardbx.executor.mdl.MdlContext; import com.alibaba.polardbx.executor.mdl.MdlDuration; import com.alibaba.polardbx.executor.mdl.MdlKey; @@ -50,6 +51,7 @@ import com.alibaba.polardbx.gms.metadb.foreign.ForeignColsRecord; import com.alibaba.polardbx.gms.metadb.foreign.ForeignRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnStatus; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnsRecord; import com.alibaba.polardbx.gms.metadb.table.IndexStatus; @@ -62,7 +64,6 @@ import com.alibaba.polardbx.gms.partition.TablePartitionRecord; import com.alibaba.polardbx.gms.tablegroup.ComplexTaskOutlineRecord; import com.alibaba.polardbx.gms.topology.DbInfoManager; -import com.alibaba.polardbx.gms.topology.DbInfoRecord; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; @@ -90,6 +91,7 @@ import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; import com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter; import com.alibaba.polardbx.optimizer.tablegroup.TableGroupVersionManager; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; import com.alibaba.polardbx.optimizer.utils.SchemaVersionManager; import com.alibaba.polardbx.rpc.client.XSession; import com.alibaba.polardbx.rpc.compatible.XResultSet; @@ -98,9 +100,9 @@ import com.alibaba.polardbx.rpc.result.XResult; import com.alibaba.polardbx.statistics.SQLRecorderLogger; import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.mysql.cj.polarx.protobuf.PolarxResultset; +import com.google.common.collect.ImmutableList; import lombok.val; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.sql.type.SqlTypeName; @@ -293,6 +295,7 @@ public static Map fetchTableMeta(Connection metaDbConn, != 0); // Load lock flag. locked = (meta.getPartitionInfo().getPartFlags() & TablePartitionRecord.FLAG_LOCK) != 0; + } if (meta.isColumnar()) { @@ -529,14 +532,14 @@ protected TableMeta buildDualTable() { * 2. Allow two concurrent version exists, which is not safe for single-versioned TableRule & PartitionInfoManager */ public void tonewversion(String tableName) { - tonewversionImpl(Arrays.asList(tableName), false, null, null, null, -1, true, false); + tonewversionImpl(Arrays.asList(tableName), false, null, null, null, -1, true, false, false); } public void tonewversion(String tableName, boolean preemptive, Long initWait, Long interval, TimeUnit timeUnit, - boolean allowTwoVersion) { + boolean allowTwoVersion, boolean forceSyncFailed) { tonewversionImpl(Arrays.asList(tableName), preemptive, initWait, interval, timeUnit, -1, allowTwoVersion, - false); + false, forceSyncFailed); } /** @@ -545,17 +548,10 @@ public void tonewversion(String tableName, @Override public void toNewVersionInTrx(List tableNameList, boolean preemptive, long initWait, long interval, TimeUnit timeUnit, - long connId, boolean allowTwoVersion, boolean sameTableGroup) { - tonewversionImpl(tableNameList, preemptive, initWait, interval, timeUnit, connId, allowTwoVersion, - sameTableGroup); - } - - @Override - public void toNewVersionInTrx(List tableNameList, - boolean preemptive, long initWait, long interval, TimeUnit timeUnit, - long connId, boolean allowTwoVersion, boolean sameTableGroup, long trxId) { + long connId, boolean allowTwoVersion, boolean sameTableGroup, + boolean forceSyncFailed) { tonewversionImpl(tableNameList, preemptive, initWait, interval, timeUnit, connId, allowTwoVersion, - sameTableGroup, trxId); + sameTableGroup, forceSyncFailed); } /** @@ -563,19 +559,15 @@ public void toNewVersionInTrx(List tableNameList, * 1. Be preemptive to avoid deadlock within multiple tables */ @Override - public void toNewVersionInTrx(List tableNameList, long connId, boolean allowTwoVersion, long trxId) { + public void toNewVersionInTrx(List tableNameList, long connId, boolean allowTwoVersion, + boolean forceSyncFailed) { ParamManager paramManager = OptimizerContext.getContext(schemaName).getParamManager(); boolean enablePreemptiveMdl = paramManager.getBoolean(ConnectionParams.ENABLE_PREEMPTIVE_MDL); Long initWait = paramManager.getLong(ConnectionParams.TG_PREEMPTIVE_MDL_INITWAIT); Long interval = paramManager.getLong(ConnectionParams.TG_PREEMPTIVE_MDL_INTERVAL); toNewVersionInTrx(tableNameList, enablePreemptiveMdl, initWait, interval, TimeUnit.MILLISECONDS, connId, - allowTwoVersion, tableNameList.size() > 1, trxId); - } - - @Override - public void toNewVersionInTrx(List tableNameList, long connId, boolean allowTwoVersion) { - toNewVersionInTrx(tableNameList, connId, allowTwoVersion, 1L); + allowTwoVersion, tableNameList.size() > 1, forceSyncFailed); } /** @@ -596,7 +588,7 @@ public void toNewVersionForTableGroup(String tableName, boolean allowTwoVersion) return; } - toNewVersionInTrx(Collections.singletonList(tableName), -1, allowTwoVersion); + toNewVersionInTrx(Collections.singletonList(tableName), -1, allowTwoVersion, false); } } @@ -908,6 +900,10 @@ private static List toColumnMetaExt(List columns, List< int idx = 0; for (String cname : columns) { if (!columnMetas.containsKey(cname)) { + if (cname.equalsIgnoreCase("null")) { + //mysql 8.0 函数索引,没有列名,兼容5.7,会插入null + continue; + } throw new RuntimeException("column " + cname + " is not a column of table " + tableName); } final Long subParts = keySubParts.get(idx); @@ -1102,6 +1098,7 @@ private List fetchTableMetas() { if (meta.getPartitionInfo() != null) { meta.setTableGroupDigestList(TableGroupVersionManager.getTableGroupDigestList( meta.getPartitionInfo().getTableGroupId())); + initTtlDefinitionInfo(schemaName, origTableName, tableInfoManager, meta); } // fetch file metas for oss engine. if (meta.getPartitionInfo() != null && Engine.isFileStore(meta.getEngine())) { @@ -1204,6 +1201,13 @@ private static void loadNewestPartitionInfo(Connection conn, logTblMeta.setLocalPartitionDefinitionInfo( LocalPartitionDefinitionInfo.from(tblInfoMgr.getLocalPartitionRecord(schemaName, logicalTableName)) ); + + // init ttl definition info + initTtlDefinitionInfo(schemaName, logicalTableName, tblInfoMgr, logTblMeta); + if (logTblMeta.getTtlDefinitionInfo() != null) { + TtlScheduledJobStatManager.getInstance().registerTtlTableIfNeed(schemaName, logicalTableName); + } + // get the partitionInfo secondly PartitionInfo curPartitionInfo = ruleMgr.getPartitionInfoManager().getPartitionInfo(origTableName); // set the partitionInfo at the last step @@ -1221,7 +1225,8 @@ private static void loadNewestPartitionInfo(Connection conn, curPartitionInfo = PartitionInfoUtil .updatePartitionInfoByOutDatePartitionRecords(conn, curPartitionInfo.getTableGroupId(), curPartitionInfo, tblInfoMgr); - newPartitionInfo = newPartitionInfo.copy(); + // PartitionInfo.copy() won't copy PartitionByDefinitionBase.router + //newPartitionInfo = newPartitionInfo.copy(); logTblMeta.setNewPartitionInfo(curPartitionInfo); logTblMeta.setPartitionInfo(newPartitionInfo); ruleMgr.getPartitionInfoManager().putNewPartitionInfo(logicalTableName, newPartitionInfo); @@ -1235,6 +1240,53 @@ private static void loadNewestPartitionInfo(Connection conn, logParitionInfo(logTblMeta); } + protected static void initTtlDefinitionInfo(String schemaName, + String logicalTableName, + TableInfoManager tblInfoMgr, + TableMeta logTblMeta) { + List pkColMetas = logTblMeta.getPrimaryKey().stream().collect(Collectors.toList()); + List pkColNames = new ArrayList<>(); + for (int i = 0; i < pkColMetas.size(); i++) { + ColumnMeta pkCm = pkColMetas.get(i); + pkColNames.add(pkCm.getName()); + } + + /** + * Check If tableMeta contain ttl_col + */ + + logTblMeta.setTtlDefinitionInfo( + TtlDefinitionInfo.createFrom(tblInfoMgr.getTtlInfoRecord(schemaName, logicalTableName), pkColNames) + ); + + if (logTblMeta.getTtlDefinitionInfo() != null) { + + /** + * Label archive cci of ttl20 + */ + Map cciPublished = logTblMeta.getColumnarIndexPublished(); + Map arcCciPublished = logTblMeta.getArchiveColumnarIndexPublished(); + TtlDefinitionInfo ttlInfo = logTblMeta.getTtlDefinitionInfo(); + if (ttlInfo != null && ttlInfo.needPerformExpiredDataArchivingByCci()) { + if (cciPublished != null && arcCciPublished != null && !cciPublished.isEmpty()) { + String rawCciName = ttlInfo.getTtlInfoRecord().getArcTmpTblName(); + for ( Map.Entry cciItem : cciPublished.entrySet() ) { + String cciItemKey = cciItem.getKey(); + String fullCciName = cciItemKey.toLowerCase(); + GsiMetaManager.GsiIndexMetaBean cciBean = cciItem.getValue(); + if (fullCciName.startsWith(rawCciName)) { + arcCciPublished.putIfAbsent(cciItemKey, cciBean); + } + } + } + } + + TtlScheduledJobStatManager.getInstance() + .registerTtlTableIfNeed(logTblMeta.getSchemaName(), logTblMeta.getTableName()); + } + + } + private static void loadNewestPartitionInfo(Connection metaDbConnect, String schemaName, String logicalTableName, @@ -1272,7 +1324,7 @@ private static void loadNewestPartitionInfo(Connection metaDbConnect, curPartitionInfo = PartitionInfoUtil .updatePartitionInfoByOutDatePartitionRecords(metaDbConnect, curPartitionInfo.getTableGroupId(), curPartitionInfo, tblInfoMgr); - newPartitionInfo = newPartitionInfo.copy(); + //newPartitionInfo = newPartitionInfo.copy(); logTblMeta.setNewPartitionInfo(curPartitionInfo); logTblMeta.setPartitionInfo(newPartitionInfo); ruleMgr.getPartitionInfoManager().putNewPartitionInfo(logicalTableName, newPartitionInfo); @@ -1322,13 +1374,6 @@ protected void loadAndCacheTableMeta(List tableNames, Connection metaDbC } } - private void tonewversionImpl(List tableNameList, - boolean preemptive, Long initWait, Long interval, TimeUnit timeUnit, - long connId, boolean allowTwoVersion, boolean sameTableGroup) { - tonewversionImpl(tableNameList, preemptive, initWait, interval, timeUnit, connId, allowTwoVersion, - sameTableGroup, 1L); - } - /** * Steps: * 1. Check meta version of table, decide whether loading new TableMeta if necessary @@ -1344,7 +1389,8 @@ private void tonewversionImpl(List tableNameList, private void tonewversionImpl(List tableNameList, boolean preemptive, Long initWait, Long interval, TimeUnit timeUnit, - long connId, boolean allowTwoVersion, boolean sameTableGroup, long trxId) { + long connId, boolean allowTwoVersion, boolean sameTableGroup, + boolean forceSyncFailed) { synchronized (OptimizerContext.getContext(schemaName)) { GmsTableMetaManager newSchemaManager; GmsTableMetaManager oldSchemaManager; @@ -1396,7 +1442,7 @@ private void tonewversionImpl(List tableNameList, newSchemaManager.init(); SQLRecorderLogger.ddlMetaLogger.info("allowTwoVersion1:" + String.valueOf(allowTwoVersion)); - if (allowTwoVersion) { + if (allowTwoVersion && !forceSyncFailed) { OptimizerContext.getContext(schemaName).setSchemaManager(newSchemaManager); } SQLRecorderLogger.ddlMetaLogger.info(MessageFormat.format( @@ -1424,7 +1470,7 @@ private void tonewversionImpl(List tableNameList, } return null; - }, trxId); + }); } } } @@ -1466,6 +1512,7 @@ public Map getStaleTables(List tableNameList, Connection c PartitionInfoManager.reload(schemaName, tableName); } } + TtlScheduledJobStatManager.getInstance().unregisterTtlTableIfNeed(schemaName, tableName); staleTables.put(tableName, version); } @@ -1624,6 +1671,21 @@ public GsiMetaManager.GsiMetaBean getGsi(String primaryOrIndexTableName, return gsiMetaManager.getTableAndIndexMeta(primaryOrIndexTableName, statusSet); } + @Override + public boolean cciExists(String columnarTableName, boolean isColumnar) { + if (!isColumnar) { + return false; + } + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + ColumnarTableMappingAccessor accessor = new ColumnarTableMappingAccessor(); + accessor.setConnection(metaDbConn); + List records = accessor.querySchemaIndex(schemaName, columnarTableName); + return !records.isEmpty(); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + @Override public Set guessGsi(String unwrappedName, Predicate filter) { DataSource dataSource = MetaDbDataSource.getInstance().getDataSource(); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSchema.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSchema.java index a41a3083e..8622434df 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSchema.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSchema.java @@ -29,6 +29,7 @@ import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -38,6 +39,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.SortedMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.locks.Lock; import java.util.stream.Collectors; @@ -247,6 +249,25 @@ public ColumnMetaWithTs getInitColumnMeta(long tableId, long fieldId) { } } + @NotNull + public SortedMap getPartitionInfos(long schemaTso, long tableId) { + MultiVersionColumnarTableMeta columnarTableMeta = getColumnarTableMeta(tableId); + + SortedMap partitionInfos = columnarTableMeta.getPartitionInfos(schemaTso); + if (partitionInfos != null) { + return partitionInfos; + } + + Lock writeLock = columnarTableMeta.getLock(); + writeLock.lock(); + try { + columnarTableMeta.loadUntilTso(schemaTso); + return Objects.requireNonNull(columnarTableMeta.getPartitionInfos(schemaTso)); + } finally { + writeLock.unlock(); + } + } + @Override public void purge(long tso) { // TODO(siyun): diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSnapshot.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSnapshot.java index 52896bd9d..d05b39aea 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSnapshot.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSnapshot.java @@ -23,6 +23,7 @@ import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.mpp.split.SplitManagerImpl; +import com.alibaba.polardbx.gms.engine.FileSystemUtils; import com.alibaba.polardbx.gms.metadb.table.FilesAccessor; import com.alibaba.polardbx.gms.metadb.table.FilesRecordSimplified; import com.alibaba.polardbx.gms.util.MetaDbUtil; @@ -32,8 +33,11 @@ import java.sql.SQLException; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.SortedMap; import java.util.concurrent.ConcurrentHashMap; /** @@ -46,21 +50,19 @@ public class MultiVersionColumnarSnapshot implements Purgeable { final private String logicalSchema; final private Long tableId; - /** - * In the range of [minTso, latestTso], all files multi-version info of the partition have been loaded. - */ private final DynamicColumnarManager columnarManager; - private volatile long latestTso = Long.MIN_VALUE; /** - * part_name -> (file_name -> (commit_ts, remove_ts)) + * In the range of [minTso, latestLoadedTso], all snapshots of these versions can be read. */ - private final Map>> allPartsTsoInfo = new ConcurrentHashMap<>(); + private volatile long latestLoadedTso = Long.MIN_VALUE; + + private volatile long latestSchemaTso = Long.MIN_VALUE; /** - * part_name -> latest_tso + * part_name -> (file_name -> (commit_ts, remove_ts, schema_ts)) */ - private final Map latestTsoForEachPart = new ConcurrentHashMap<>(); + private final Map> allPartsTsoInfo = new ConcurrentHashMap<>(); public MultiVersionColumnarSnapshot(DynamicColumnarManager columnarManager, String logicalSchema, Long tableId) { this.columnarManager = columnarManager; @@ -84,6 +86,22 @@ public ColumnarSnapshot() { } } + /** + * The tso info for a columnar file + */ + @Data + public static class ColumnarTsoInfo { + private final Long commitTso; + private final Long removeTso; + private final Long schemaTso; + + public ColumnarTsoInfo(Long commitTso, Long removeTso, Long schemaTso) { + this.commitTso = commitTso; + this.removeTso = removeTso; + this.schemaTso = schemaTso; + } + } + /** * Fetch delta files which satisfy: * lastTso < commitTso <= tso AND minTso < removeTso @@ -104,27 +122,26 @@ public ColumnarSnapshot() { * In this case minTso = 9, lastTso = 7, tso = 11, we should fetch F1, F2, F4 and F5 * After updating the tso info using these filesRecords, we can generate any snapshots in [minTso, tso] */ - private void loadUntilTso(long tso, long minTso) { - List filesRecords = loadDeltaFilesInfoFromGms(latestTso, tso); + private synchronized void loadUntilTso(long tso, long minTso) { + long minCompactionTso = columnarManager.getMinCompactionTso(latestLoadedTso); + + // 0 means there are no hanging compaction + // min compaction tso > checkpoint tso means tso would not go backward, so it can be omitted + long latestFullyLoadedTso = + minCompactionTso == 0 ? latestLoadedTso : Long.min(minCompactionTso - 1, latestLoadedTso); + List filesRecords = loadDeltaFilesInfoFromGms(latestFullyLoadedTso, tso); for (FilesRecordSimplified fileRecord : filesRecords) { String fileName = fileRecord.fileName; String partName = fileRecord.partitionName; Long commitTs = fileRecord.commitTs; Long removeTs = fileRecord.removeTs; + Long schemaTs = fileRecord.schemaTs; - Map> tsoInfo = + Map tsoInfo = allPartsTsoInfo.computeIfAbsent(partName, s -> new ConcurrentHashMap<>()); - long curLatestTso = removeTs != null ? removeTs : commitTs; - - latestTsoForEachPart.compute(partName, (p, latestTsoForThisPart) -> { - if (latestTsoForThisPart == null) { - return curLatestTso; - } else { - return Math.max(latestTsoForThisPart, curLatestTso); - } - }); + latestSchemaTso = Math.max(latestSchemaTso, schemaTs); if (tsoInfo.containsKey(fileName)) { if (removeTs == null) { @@ -135,15 +152,16 @@ private void loadUntilTso(long tso, long minTso) { tsoInfo.remove(fileName); columnarManager.putPurgedFile(fileName); } else { - tsoInfo.put(fileName, Pair.of(commitTs, removeTs)); + tsoInfo.put(fileName, new ColumnarTsoInfo(commitTs, removeTs, schemaTs)); } } else { if (removeTs == null || removeTs > minTso) { - tsoInfo.put(fileName, Pair.of(commitTs, removeTs)); + tsoInfo.put(fileName, new ColumnarTsoInfo(commitTs, removeTs, schemaTs)); } } } - latestTso = latestTsoForEachPart.values().stream().reduce(Long::min).orElse(Long.MIN_VALUE); + + latestLoadedTso = tso; } private List loadDeltaFilesInfoFromGms(long lastTso, long tso) { @@ -164,7 +182,7 @@ public ColumnarSnapshot generateSnapshot(final String partitionName, final long long ioCost = 0L; long totalCost = 0L; long startTime = System.nanoTime(); - long latestTsoBackUp = latestTso; + long latestTsoBackUp = latestLoadedTso; long minTso = columnarManager.getMinTso(); if (tso < minTso) { @@ -172,12 +190,12 @@ public ColumnarSnapshot generateSnapshot(final String partitionName, final long String.format("Snapshot of tso[%d] has been purged!", tso)); } - if (latestTso < tso) { + if (latestLoadedTso < tso) { long startIOTime = System.nanoTime(); synchronized (this) { // In case the tso has not been loaded // Assuming that the tso is reliable - if (latestTso < tso) { + if (latestLoadedTso < tso) { loadUntilTso(tso, minTso); } } @@ -185,15 +203,14 @@ public ColumnarSnapshot generateSnapshot(final String partitionName, final long } ColumnarSnapshot snapshot = new ColumnarSnapshot(); - Map> tsoInfo = + Map tsoInfo = allPartsTsoInfo.computeIfAbsent(partitionName, s -> new ConcurrentHashMap<>()); - tsoInfo.forEach((fileName, commitAndRemoveTs) -> { - Long commitTs = commitAndRemoveTs.getKey(); - Long removeTs = commitAndRemoveTs.getValue(); + tsoInfo.forEach((fileName, fileTsoInfo) -> { + Long commitTs = fileTsoInfo.commitTso; + Long removeTs = fileTsoInfo.removeTso; if (commitTs <= tso && (removeTs == null || removeTs > tso)) { - String suffix = fileName.substring(fileName.lastIndexOf('.') + 1); - ColumnarFileType columnarFileType = ColumnarFileType.of(suffix); + ColumnarFileType columnarFileType = FileSystemUtils.getFileType(fileName); switch (columnarFileType) { case ORC: @@ -226,10 +243,84 @@ public ColumnarSnapshot generateSnapshot(final String partitionName, final long return snapshot; } + public Map, List>> generateSnapshot( + final SortedMap> partitionResult, final long tso) { + long minTso = columnarManager.getMinTso(); + if (tso < minTso) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, + String.format("Snapshot of tso[%d] has been purged!", tso)); + } + + if (latestLoadedTso < tso) { + synchronized (this) { + // In case the tso has not been loaded + // Assuming that the tso is reliable + if (latestLoadedTso < tso) { + loadUntilTso(tso, minTso); + } + } + } + + Map, List>> result = new HashMap<>(); + + allPartsTsoInfo.forEach((partName, snapshot) -> { + snapshot.forEach((fileName, fileTsoInfo) -> { + Long commitTs = fileTsoInfo.commitTso; + Long removeTs = fileTsoInfo.removeTso; + if (commitTs <= tso && (removeTs == null || removeTs > tso)) { + Long schemaTs = fileTsoInfo.schemaTso; + SortedMap> headMap = partitionResult.headMap(schemaTs + 1); + if (!headMap.isEmpty()) { + Set partitionSet = headMap.get(headMap.lastKey()); + if (partitionSet != null && partitionSet.contains(partName)) { + Pair, List> orcAndCsv = result.computeIfAbsent(partName, + s -> Pair.of(new ArrayList<>(), new ArrayList<>())); + ColumnarFileType columnarFileType = FileSystemUtils.getFileType(fileName); + + switch (columnarFileType) { + case ORC: + orcAndCsv.getKey().add(fileName); + break; + case CSV: + orcAndCsv.getValue().add(fileName); + break; + default: + // ignore. + } + } + } + } + }); + }); + + return result; + } + + public long getLatestSchemaTso(final long tso) { + if (latestLoadedTso < tso) { + synchronized (this) { + // In case the tso has not been loaded + // Assuming that the tso is reliable + if (latestLoadedTso < tso) { + loadUntilTso(tso, columnarManager.getMinTso()); + } + } + } + return latestSchemaTso; + } + public synchronized void purge(long tso) { + if (latestLoadedTso < tso) { + synchronized (this) { + if (latestLoadedTso < tso) { + loadUntilTso(tso, tso); + } + } + } + allPartsTsoInfo.forEach((partName, snapshot) -> { snapshot.entrySet().removeIf(entry -> { - Long removeTs = entry.getValue().getValue(); + Long removeTs = entry.getValue().removeTso; if (removeTs != null && removeTs <= tso) { columnarManager.putPurgedFile(entry.getKey()); return true; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarTableMeta.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarTableMeta.java index 7d3479874..7fd8b61cc 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarTableMeta.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarTableMeta.java @@ -23,12 +23,17 @@ import com.alibaba.polardbx.executor.archive.schemaevolution.ColumnMetaWithTs; import com.alibaba.polardbx.gms.metadb.table.ColumnarColumnEvolutionAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarColumnEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnsRecord; +import com.alibaba.polardbx.gms.partition.TablePartitionRecord; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.config.table.Field; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -40,6 +45,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -84,12 +90,20 @@ public class MultiVersionColumnarTableMeta implements Purgeable { // notice that columnar_table_evolution stores id rather than field_id of columnar_column_evolution private final Map> multiVersionColumns = new ConcurrentHashMap<>(); + // version_id -> [partition_id ...] + private final Map> multiVersionPartitions = new ConcurrentHashMap<>(); + // for columnar_column_evoluion: id -> field_id private final Map columnFieldIdMap = new ConcurrentHashMap<>(); - // field -> [column_id for version 1, column_id for version 2, ...] + // field_id -> [column_id for version 1, column_id for version 2, ...] private final Map> multiVersionColumnIds = new ConcurrentHashMap<>(); + // schema_ts -> partition_info + private final SortedMap multiVersionPartitionInfos = new ConcurrentSkipListMap<>(); + + private final Map allPartitions = new ConcurrentHashMap<>(); + private final LoadingCache> columnMetaListByTso; private final LoadingCache> fieldIdMapByTso; @@ -196,6 +210,25 @@ public List getColumnMetaListByTso(long schemaTso) { } } + @Nullable + public PartitionInfo getPartitionInfoByTso(long schemaTso) { + if (versionIdMap.isEmpty() || versionIdMap.lastKey() < schemaTso) { + return null; + } + + Long validSchemaTso = multiVersionPartitionInfos.headMap(schemaTso + 1).lastKey(); + return multiVersionPartitionInfos.get(validSchemaTso); + } + + @Nullable + public SortedMap getPartitionInfos(long schemaTso) { + if (versionIdMap.isEmpty() || versionIdMap.lastKey() < schemaTso) { + return null; + } + + return multiVersionPartitionInfos.headMap(schemaTso + 1); + } + public int @Nullable [] getPrimaryKeyColumns(long schemaTso) { if (versionIdMap.isEmpty() || versionIdMap.lastKey() < schemaTso) { return null; @@ -229,6 +262,7 @@ public void loadUntilTso(long schemaTso) { List tableEvolutionRecordList; List columnEvolutionRecordList; + List partitionEvolutionRecordList; try (Connection connection = MetaDbUtil.getConnection()) { ColumnarTableEvolutionAccessor accessor = new ColumnarTableEvolutionAccessor(); @@ -237,7 +271,6 @@ public void loadUntilTso(long schemaTso) { ColumnarColumnEvolutionAccessor columnAccessor = new ColumnarColumnEvolutionAccessor(); columnAccessor.setConnection(connection); - // TODO(siyun): greater than certain id and order by id columnEvolutionRecordList = columnAccessor.queryTableIdAndVersionIdsOrderById( tableId, tableEvolutionRecordList.stream() @@ -247,6 +280,17 @@ public void loadUntilTso(long schemaTso) { .collect(Collectors.toList()) ); + ColumnarPartitionEvolutionAccessor partitionAccessor = new ColumnarPartitionEvolutionAccessor(); + partitionAccessor.setConnection(connection); + partitionEvolutionRecordList = partitionAccessor.queryTableIdAndVersionIdsOrderById( + tableId, + tableEvolutionRecordList.stream() + // For those versions which have not been loaded + .filter(r -> !multiVersionPartitions.containsKey(r.versionId)) + .map(r -> r.versionId) + .collect(Collectors.toList()) + ); + } catch (SQLException e) { throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, e, String.format("Failed to generate columnar schema of tso: %d", schemaTso)); @@ -254,7 +298,7 @@ public void loadUntilTso(long schemaTso) { for (ColumnarColumnEvolutionRecord columnEvolutionRecord : columnEvolutionRecordList) { Long id = columnEvolutionRecord.id; - Long filedId = columnEvolutionRecord.fieldId; + Long fieldId = columnEvolutionRecord.fieldId; ColumnsRecord columnsRecord = columnEvolutionRecord.columnsRecord; ColumnMeta columnMeta = GmsTableMetaManager.buildColumnMeta( columnsRecord, @@ -266,8 +310,8 @@ public void loadUntilTso(long schemaTso) { primaryKeySet.add(id); } allColumnMetas.put(id, columnMetaWithTs); - columnFieldIdMap.put(id, filedId); - multiVersionColumnIds.compute(filedId, (k, v) -> { + columnFieldIdMap.put(id, fieldId); + multiVersionColumnIds.compute(fieldId, (k, v) -> { if (v == null) { SortedSet newSet = new ConcurrentSkipListSet<>(); newSet.add(id); @@ -279,12 +323,32 @@ public void loadUntilTso(long schemaTso) { }); } + for (ColumnarPartitionEvolutionRecord columnarPartitionRecord : partitionEvolutionRecordList) { + Long id = columnarPartitionRecord.id; + TablePartitionRecord partitionRecord = columnarPartitionRecord.partitionRecord; + allPartitions.put(id, partitionRecord); + } + for (ColumnarTableEvolutionRecord tableRecord : tableEvolutionRecordList) { long commitTs = tableRecord.commitTs; long versionId = tableRecord.versionId; multiVersionColumns.putIfAbsent(versionId, tableRecord.columns); + multiVersionPartitions.putIfAbsent(versionId, tableRecord.partitions); + if (commitTs != Long.MAX_VALUE) { versionIdMap.put(commitTs, versionId); + + List lastPartitions = + latestTso != Long.MIN_VALUE ? multiVersionPartitions.get(versionIdMap.get(latestTso)) : null; + + // If two partition definitions are identical, skip + if (lastPartitions == null || + (lastPartitions != tableRecord.partitions && + !lastPartitions.equals(tableRecord.partitions))) { + multiVersionPartitionInfos.put(commitTs, buildPartitionInfo(commitTs, tableRecord.partitions)); + } + + latestTso = commitTs; } } } @@ -302,4 +366,16 @@ public void purge(long schemaTso) { public Lock getLock() { return lock; } + + private PartitionInfo buildPartitionInfo(long schemaTso, List partitionIds) { + return PartitionInfoManager.generatePartitionInfo( + getColumnMetaListByTso(schemaTso), + partitionIds.stream() + .map(allPartitions::get) + .collect(Collectors.toList()), + null, + false, + false + ); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionCsvData.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionCsvData.java index 3b53988f8..128e17449 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionCsvData.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/MultiVersionCsvData.java @@ -24,6 +24,7 @@ import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.columnar.CSVFileReader; +import com.alibaba.polardbx.executor.columnar.CsvDataIterator; import com.alibaba.polardbx.executor.columnar.RawOrcTypeCsvReader; import com.alibaba.polardbx.executor.columnar.SimpleCSVFileReader; import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; @@ -38,6 +39,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.SortedMap; import java.util.concurrent.ConcurrentSkipListMap; @@ -128,7 +130,7 @@ public void loadUntilTso(long minTso, long tso) { long newEndPosition = record.appendOffset + record.appendLength; List results = new ArrayList<>(); - // It may cause OOM + Chunk result; while ((result = csvFileReader.nextUntilPosition(newEndPosition)) != null) { results.add(result); @@ -153,54 +155,29 @@ public void loadUntilTso(long minTso, long tso) { /** * Never use any cache. */ - public static List loadRawOrcTypeUntilTso(long tso, - AtomicLong openedFileCount, - String csvFileName, - ExecutionContext context) { - // The latest tso which has already been loaded by version chain - long latestTso = Long.MIN_VALUE; - - ColumnarAppendedFilesRecord record; - - try (Connection connection = MetaDbUtil.getConnection()) { - ColumnarAppendedFilesAccessor columnarAppendedFilesAccessor = new ColumnarAppendedFilesAccessor(); - columnarAppendedFilesAccessor.setConnection(connection); - record = columnarAppendedFilesAccessor - .queryLatestByFileNameBetweenTso(csvFileName, latestTso, tso).get(0); - } catch (SQLException e) { - throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, e, - String.format("[RawOrcType]Failed to generate columnar snapshot of tso: %d", tso)); - } - - if (null != record) { - FileMeta fileMeta = ColumnarManager.getInstance().fileMetaOf(csvFileName); - Engine engine = fileMeta.getEngine(); - List columnMetas = fileMeta.getColumnMetas(); + public static Iterator loadRawOrcTypeUntilTso(String csvFileName, + ExecutionContext context, + int start, + int end) { + FileMeta fileMeta = ColumnarManager.getInstance().fileMetaOf(csvFileName); + Engine engine = fileMeta.getEngine(); + List columnMetas = fileMeta.getColumnMetas(); + + return new CsvDataIterator(new RawOrcTypeCsvReader(), csvFileName, start, end, context, columnMetas, engine); + } - long maxReadPosition = record.appendOffset + record.appendLength; - openedFileCount.incrementAndGet(); - try (CSVFileReader csvFileReader = new RawOrcTypeCsvReader()) { - csvFileReader.open(context, columnMetas, FileVersionStorage.CSV_CHUNK_LIMIT, engine, - csvFileName, - 0, - (int) maxReadPosition); - List results = new ArrayList<>(); - // It may cause OOM - Chunk result; - while ((result = csvFileReader.nextUntilPosition(maxReadPosition)) != null) { - results.add(result); - } - return results; - } catch (Throwable t) { - throw new TddlRuntimeException(ErrorCode.ERR_LOAD_CSV_FILE, t, - String.format("[RawOrcType]Failed to load read csv file, " - + "file name: %s, last tso: %d, snapshot tso: %d", - csvFileName, latestTso, tso)); - } finally { - openedFileCount.decrementAndGet(); - } - } - return null; + /** + * Load csv data with specified csv files and specified file positions. + */ + public static Iterator loadSpecifiedCsvFile(String csvFileName, + ExecutionContext context, + int start, + int end) { + FileMeta fileMeta = ColumnarManager.getInstance().fileMetaOf(csvFileName); + Engine engine = fileMeta.getEngine(); + List columnMetas = fileMeta.getColumnMetas(); + + return new CsvDataIterator(new SimpleCSVFileReader(), csvFileName, start, end, context, columnMetas, engine); } public Lock getLock() { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/AlterRepartitionUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/AlterRepartitionUtils.java index 27d1df8d7..d5d4d1d99 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/AlterRepartitionUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/AlterRepartitionUtils.java @@ -494,7 +494,8 @@ public static SqlIndexDefinition genSqlIndexDefinition(List partitionCol null, new LinkedList<>(), withImplicitTableGroup, - true); + true, + null); } public static List getPrimaryKeys(SqlAlterTable sqlAlterTable) { @@ -587,10 +588,10 @@ private static SqlPartitionByHash genPartitioning(List primaryKeys) { public static String genGlobalIndexName(String schema, String indexName, ExecutionContext executionContext) { // Assign new name with suffix. final Random random = new Random(); - final Formatter formatter = new Formatter(); String fullName; do { + Formatter formatter = new Formatter(); final String suffix = "_$" + formatter.format("%04x", random.nextInt(0x10000)); fullName = indexName + suffix; } while (!executionContext.getSchemaManager(schema).getGsi(fullName, IndexStatus.ALL).isEmpty()); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/ColumnarTransactionUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/ColumnarTransactionUtils.java index 7eb286709..85df38531 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/ColumnarTransactionUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/ColumnarTransactionUtils.java @@ -20,14 +20,20 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.oss.ColumnarFileType; import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.gms.ColumnarManager; import com.alibaba.polardbx.executor.sync.RequestColumnarSnapshotSeqSyncAction; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; +import com.alibaba.polardbx.gms.engine.FileSystemUtils; import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableStatus; import com.alibaba.polardbx.gms.metadb.table.FilesAccessor; @@ -52,14 +58,17 @@ import java.util.stream.Collectors; public class ColumnarTransactionUtils { + + private final static Logger LOGGER = LoggerFactory.getLogger("ColumnarTransactionUtils"); + private final static String COLUMNAR_PURGE_LIMIT_TSO = "columnar_purge_limit_tso"; + @NotNull public static Long getMinColumnarSnapshotTime() { IGmsSyncAction action = new RequestColumnarSnapshotSeqSyncAction(); List>> results = SyncManagerHelper.sync(action, SystemDbHelper.DEFAULT_DB_NAME, SyncScope.ALL); - long minSnapshotKeepTime = DynamicConfig.getInstance().getMinSnapshotKeepTime(); - long minSnapshotTime = ColumnarManager.getInstance().latestTso() - (minSnapshotKeepTime << 22); + long minSnapshotTime = ColumnarManager.getInstance().latestTso(); for (List> nodeRows : results) { if (nodeRows == null) { @@ -89,6 +98,18 @@ public static Long getLatestTsoFromGms() { } } + public static Long getLatestTsoFromGmsWithDelay(long delayMicroseconds) { + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarCheckpointsAccessor checkpointsAccessor = new ColumnarCheckpointsAccessor(); + checkpointsAccessor.setConnection(connection); + + return checkpointsAccessor.queryLatestTsoWithDelay(delayMicroseconds); + } catch (SQLException e) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, e, + "Failed to fetch latest columnar tso"); + } + } + /** * @return latest tso of checkpoint that only contains orc files but not csv files, * in format (Innodb tso, Columnar tso) @@ -120,6 +141,35 @@ public static Long getLatestShowColumnarStatusTsoFromGms() { } } + public static int updateColumnarPurgeWatermark(long purgeWatermark) { + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarConfigAccessor configAccessor = new ColumnarConfigAccessor(); + configAccessor.setConnection(connection); + // Only leader CN could reach hear, so we don't need to select for update + List records = configAccessor.queryGlobalByConfigKey(COLUMNAR_PURGE_LIMIT_TSO); + + boolean shouldUpdate = false; + if (GeneralUtil.isEmpty(records)) { + shouldUpdate = true; + } else { + ColumnarConfigRecord configRecord = records.get(0); + + if (configRecord.configValue == null || Long.parseLong(configRecord.configValue) < purgeWatermark) { + shouldUpdate = true; + } + } + + if (shouldUpdate) { + return configAccessor.updateGlobalParamValue(COLUMNAR_PURGE_LIMIT_TSO, Long.toString(purgeWatermark)); + } + + return 0; + } catch (SQLException e) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, e, + "Failed to update purge watermark"); + } + } + public static class ColumnarIndexStatusRow { public long tso; public String tableSchema; @@ -164,14 +214,13 @@ public static List queryColumnarIndexStatus(Long tso, .map(partitionSpecConfig -> partitionSpecConfig.getSpecConfigInfo().partName) .collect(Collectors.toList()); } catch (Exception e) { - //正在创建的表可能rollback了,分区信息找不到,忽略就好 - if (record.status.equalsIgnoreCase(ColumnarTableStatus.CREATING.name())) { - continue; - } else { - throw new TddlRuntimeException(ErrorCode.ERR_GMS_GENERIC, - "fail to fetch partition info by columnar index: " + record.tableSchema + "." + record.tableName - + "(" + record.indexName + "(" + record.tableId + "))", e); - } + //暂时忽略该列存索引表分区获取失败的情况: + //1.正在创建的表可能rollback了,分区信息找不到,忽略就好 + //2.public的表可能删除了,分区信息找不到,也忽略 + LOGGER.warn( + "fail to fetch partition info by columnar index: " + record.tableSchema + "." + record.tableName + + "(" + record.indexName + "(" + record.tableId + "))", e); + continue; } ColumnarIndexStatusRow row = new ColumnarIndexStatusRow(); row.tso = tso; @@ -197,15 +246,24 @@ public static List queryColumnarIndexStatus(Long tso, appendedFilesAccessor.setConnection(metaDbConn); //csv/del文件统计 - List appendedFilesRecords = - appendedFilesAccessor.queryLastValidAppendByTsoAndTableId(tso, schemaName, + boolean useSubQuery = DynamicConfig.getInstance().isShowColumnarStatusUseSubQuery(); + List appendedFilesRecords; + if (useSubQuery) { + //子查询方式 + appendedFilesRecords = + appendedFilesAccessor.queryLastValidAppendByTsoAndTableIdSubQuery(tso, schemaName, + String.valueOf(tableId)); + } else { + //join方式 + appendedFilesRecords = appendedFilesAccessor.queryLastValidAppendByTsoAndTableId(tso, schemaName, String.valueOf(tableId)); + } + //按照tso降序排序的,del文件总删除的行数只需要统计各分区最新文件的最新append记录就行,防止多个del文件 Set haveRecordDelRowPartitions = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); for (ColumnarAppendedFilesRecord appendRecord : appendedFilesRecords) { String fileName = appendRecord.fileName; - String suffix = fileName.substring(fileName.lastIndexOf('.') + 1); - ColumnarFileType columnarFileType = ColumnarFileType.of(suffix); + ColumnarFileType columnarFileType = FileSystemUtils.getFileType(fileName); switch (columnarFileType) { case CSV: row.csvFileNum++; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/SequenceUtil.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/SequenceUtil.java index ff71bc81d..809ae6b63 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/SequenceUtil.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/SequenceUtil.java @@ -20,6 +20,7 @@ import com.alibaba.polardbx.common.constants.SequenceAttribute.Type; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; @@ -27,14 +28,18 @@ import com.alibaba.polardbx.gms.metadb.seq.SequenceBaseRecord; import com.alibaba.polardbx.gms.metadb.seq.SequenceOptRecord; import com.alibaba.polardbx.gms.metadb.seq.SequenceRecord; +import com.alibaba.polardbx.gms.metadb.seq.SequencesAccessor; import com.alibaba.polardbx.gms.metadb.table.TableStatus; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.sequence.SequenceManagerProxy; import com.alibaba.polardbx.sequence.exception.SequenceException; import org.apache.calcite.sql.SequenceBean; +import org.apache.calcite.sql.SqlKind; +import java.sql.Connection; import java.util.function.Supplier; +import static com.alibaba.polardbx.common.constants.SequenceAttribute.AUTO_SEQ_PREFIX; import static com.alibaba.polardbx.common.constants.SequenceAttribute.DEFAULT_INCREMENT_BY; import static com.alibaba.polardbx.common.constants.SequenceAttribute.DEFAULT_INNER_STEP; import static com.alibaba.polardbx.common.constants.SequenceAttribute.DEFAULT_START_WITH; @@ -61,6 +66,29 @@ public static SequenceBaseRecord convert(SequenceBean sequence, String tableSche } } + public static void resetSequence4TruncateTable(String schema, String table, Connection metaDbConn, + ExecutionContext executionContext) { + SequencesAccessor sequencesAccessor = new SequencesAccessor(); + sequencesAccessor.setConnection(metaDbConn); + final String sequenceName = AUTO_SEQ_PREFIX + table; + final SequenceBean sequenceBean = new SequenceBean(); + sequenceBean.setStart(1L); + sequenceBean.setToType(Type.NA); + sequenceBean.setKind(SqlKind.ALTER_SEQUENCE); + sequenceBean.setSchemaName(schema); + sequenceBean.setName(sequenceName); + + long newSeqCacheSize = executionContext.getParamManager().getLong(ConnectionParams.NEW_SEQ_CACHE_SIZE); + newSeqCacheSize = newSeqCacheSize < 1 ? 0 : newSeqCacheSize; + + SequenceBaseRecord record = SequenceUtil.convert(sequenceBean, null, executionContext); + + Type existingType = SequenceManagerProxy.getInstance().checkIfExists(schema, sequenceName); + if (existingType != Type.TIME) { + sequencesAccessor.update(record, newSeqCacheSize); + } + } + public static Pair change(SequenceBean sequence, String tableSchema, ExecutionContext executionContext) { setSchemaName(sequence, tableSchema, executionContext); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/StatisticUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/StatisticUtils.java index b15341981..a88e1e9cf 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/StatisticUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gms/util/StatisticUtils.java @@ -23,6 +23,8 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; import com.alibaba.polardbx.common.jdbc.Parameters; import com.alibaba.polardbx.common.oss.OSSMetaLifeCycle; import com.alibaba.polardbx.common.properties.ConnectionParams; @@ -38,6 +40,7 @@ import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.cursor.ResultCursor; import com.alibaba.polardbx.executor.ddl.newengine.cross.CrossEngineValidator; +import com.alibaba.polardbx.executor.gsi.GsiUtils; import com.alibaba.polardbx.executor.spi.ITransactionManager; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; import com.alibaba.polardbx.executor.sync.UpdateStatisticSyncAction; @@ -55,9 +58,11 @@ import com.alibaba.polardbx.gms.topology.SystemDbHelper; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.config.table.FileMeta; import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; import com.alibaba.polardbx.optimizer.config.table.IndexMeta; import com.alibaba.polardbx.optimizer.config.table.OSSOrcFileMeta; import com.alibaba.polardbx.optimizer.config.table.TableMeta; @@ -67,25 +72,29 @@ import com.alibaba.polardbx.optimizer.config.table.statistic.inf.SystemTableColumnStatistic; import com.alibaba.polardbx.optimizer.config.table.statistic.inf.SystemTableTableStatistic; import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.CursorMeta; import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil; import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan; import com.alibaba.polardbx.optimizer.core.planner.Planner; import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; +import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation; import com.alibaba.polardbx.optimizer.core.row.ArrayRow; import com.alibaba.polardbx.optimizer.core.row.Row; +import com.alibaba.polardbx.optimizer.parse.visitor.DrdsUnparameterizeSqlVisitor; import com.alibaba.polardbx.optimizer.optimizeralert.OptimizerAlertUtil; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager; import com.alibaba.polardbx.optimizer.partition.PartitionSpec; -import com.alibaba.polardbx.optimizer.planmanager.PlanManager; import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; import com.alibaba.polardbx.optimizer.statis.SQLRecorder; import com.alibaba.polardbx.optimizer.utils.ITransaction; import com.alibaba.polardbx.optimizer.view.InformationSchemaTables; import com.alibaba.polardbx.rule.TableRule; import com.alibaba.polardbx.statistics.RuntimeStatHelper; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; import com.alibaba.polardbx.stats.MatrixStatistics; +import com.alibaba.polardbx.stats.metric.FeatureStats; import com.clearspring.analytics.stream.StreamSummary; import com.clearspring.analytics.stream.cardinality.HyperLogLog; import com.clearspring.analytics.stream.membership.BloomFilter; @@ -102,6 +111,7 @@ import org.jetbrains.annotations.NotNull; import java.sql.Connection; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -115,6 +125,7 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Random; import java.util.Set; import java.util.concurrent.ThreadPoolExecutor; @@ -122,6 +133,7 @@ import java.util.stream.Collectors; import static com.alibaba.polardbx.common.properties.ConnectionParams.STATISTIC_VISIT_DN_TIMEOUT; +import static com.alibaba.polardbx.common.utils.GeneralUtil.sampleString; import static com.alibaba.polardbx.common.utils.GeneralUtil.unixTimeStamp; import static com.alibaba.polardbx.gms.module.LogLevel.CRITICAL; import static com.alibaba.polardbx.gms.module.LogLevel.NORMAL; @@ -136,9 +148,11 @@ import static com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils.buildColumnsName; import static com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils.getColumnMetas; import static com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils.packDateTypeToLong; +import static com.alibaba.polardbx.stats.metric.FeatureStatsItem.SAMPLE_TASK_FAIL; +import static com.alibaba.polardbx.stats.metric.FeatureStatsItem.SAMPLE_TASK_SUCC; /** - * @author fangwu + * */ public class StatisticUtils { @@ -167,6 +181,10 @@ public static boolean forceAnalyzeColumnsDdl(String schema, String logicalTableN ExecutionContext ec) { try { long startNanos = System.nanoTime(); + // to lower case + schema = schema.toLowerCase(); + logicalTableName = logicalTableName.toLowerCase(); + // check table if exists if (OptimizerContext.getContext(schema).getLatestSchemaManager() .getTableWithNull(logicalTableName) == null) { @@ -186,7 +204,9 @@ public static boolean forceAnalyzeColumnsDdl(String schema, String logicalTableN schema, logicalTableName, (endNanos - startNanos) / 1_000_000_000D)); startNanos = endNanos; - sketchTableDdl(schema, logicalTableName, true, ec); + + sketchTableDdl(schema, logicalTableName, + !ec.getParamManager().getBoolean(ConnectionParams.ANALYZE_TEST_UPDATE), ec); endNanos = System.nanoTime(); logger.info(String.format("HLL sketch of %s.%s consumed %.2fs", schema, logicalTableName, (endNanos - startNanos) / 1_000_000_000D)); @@ -316,9 +336,11 @@ public static boolean sampleOneTable(String schema, String logicalTableName) { logicalTableName, StatisticManager.getInstance().getCacheLine(schema, logicalTableName)), SyncScope.ALL); - + FeatureStats.getInstance().increment(SAMPLE_TASK_SUCC); } catch (Exception e) { logger.error(e); + OptimizerAlertUtil.statisticErrorAlert(); + FeatureStats.getInstance().increment(SAMPLE_TASK_FAIL); return false; } return true; @@ -419,12 +441,76 @@ private static void updateMetaDbInformationSchemaTables(String schemaName, Strin } } + public static void updateMetaDbInformationSchemaTables(String schemaName, Collection logicalTables) { + ExecutionContext executionContext = new ExecutionContext(schemaName); + executionContext.setTraceId("statistic"); + executionContext.setParams(new Parameters()); + executionContext.setRuntimeStatistics(RuntimeStatHelper.buildRuntimeStat(executionContext)); + SqlConverter sqlConverter = SqlConverter.getInstance(schemaName, executionContext); + RelOptCluster relOptCluster = sqlConverter.createRelOptCluster(); + + InformationSchemaTables informationSchemaTables = + new InformationSchemaTables(relOptCluster, relOptCluster.getPlanner().emptyTraitSet()); + RexBuilder rexBuilder = relOptCluster.getRexBuilder(); + RexNode filterCondition = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, + rexBuilder.makeInputRef(informationSchemaTables, InformationSchemaTables.getTableSchemaIndex()), + rexBuilder.makeLiteral(schemaName)); + List tableNameLiterals = new ArrayList<>(logicalTables.size()); + logicalTables.forEach(table -> tableNameLiterals.add(rexBuilder.makeLiteral(table))); + RexNode inCondition = rexBuilder.makeCall(SqlStdOperatorTable.IN, + rexBuilder.makeInputRef(informationSchemaTables, InformationSchemaTables.getTableNameIndex()), + rexBuilder.makeCall(SqlStdOperatorTable.ROW, tableNameLiterals)); + filterCondition = rexBuilder.makeCall(SqlStdOperatorTable.AND, filterCondition, inCondition); + informationSchemaTables.pushFilter(filterCondition); + + Cursor cursor = ExecutorHelper.execute(informationSchemaTables, executionContext, false, false); + + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + TablesAccessor tablesAccessor = new TablesAccessor(); + tablesAccessor.setConnection(metaDbConn); + Row row; + while ((row = cursor.next()) != null) { + + String tableSchema = row.getString(1); + String tableName = row.getString(2); + Long tableRows = row.getLong(7); + Long avgRowLength = row.getLong(8); + Long dataLength = row.getLong(9); + Long maxDataLength = row.getLong(10); + Long indexLength = row.getLong(11); + Long dataFree = row.getLong(12); + + if (schemaName.equalsIgnoreCase(tableSchema)) { + tablesAccessor.updateStatistic(tableSchema, tableName, tableRows, avgRowLength, dataLength, + maxDataLength, indexLength, dataFree); + } + } + } catch (SQLException e) { + throw new RuntimeException( + "Schema `" + schemaName + "` build meta error."); + } finally { + try { + if (cursor != null) { + cursor.close(new ArrayList<>()); + } + } finally { + executionContext.clearAllMemoryPool(); + } + } + } + public static void sketchTable(String schema, String logicalTableName, boolean needRebuild) { sketchTableDdl(schema, logicalTableName, needRebuild, null); } /** - * hyper loglog process + * Executes the sketch creation or update process for the specified table. + * + * @param schema Database name + * @param logicalTableName Logical table name + * @param needRebuild Whether to force a rebuild of the sketches + * @param ec Execution context + * @throws TddlRuntimeException When the DDL job is interrupted */ public static void sketchTableDdl(String schema, String logicalTableName, boolean needRebuild, ExecutionContext ec) { @@ -436,121 +522,108 @@ public static void sketchTableDdl(String schema, String logicalTableName, boolea int hllParallelism = ec.getParamManager().getInt(ConnectionParams.HLL_PARALLELISM); logger.info(String.format("Sketch table %s.%s with parallelism: %d", schema, logicalTableName, hllParallelism)); ThreadPoolExecutor sketchHllExecutor = null; - if (hllParallelism > 1) { - sketchHllExecutor = ExecutorUtil.createExecutor("SketchHllExecutor", hllParallelism); - } - try { - List columnMetaList = getColumnMetas(false, schema, logicalTableName); + /** + * handle columns inside index + */ + Set colDoneSet = Sets.newHashSet(); + TableMeta tableMeta = OptimizerContext.getContext(schema).getLatestSchemaManager().getTable(logicalTableName); - if (columnMetaList == null || columnMetaList.isEmpty()) { - ModuleLogInfo.getInstance().logRecord(Module.STATISTICS, UNEXPECTED, - new String[] { - "statistic sketch", - "column meta is empty :" + schema + "," + logicalTableName - }, LogLevel.NORMAL); - return; - } + Map> indexColsMap = new HashMap<>(); + getIndexInfoFromLocalIndex(tableMeta, colDoneSet, indexColsMap); + getIndexInfoFromGsi(tableMeta, colDoneSet, indexColsMap); - Map> colMap = PlanManager.getInstance().columnsInvolvedByPlan().get(schema); + try { + if (hllParallelism > 1) { + sketchHllExecutor = ExecutorUtil.createExecutor("SketchHllExecutor", hllParallelism); + } - if (colMap == null) { - colMap = Maps.newHashMap(); + for (Set cols : indexColsMap.values()) { + for (String colsName : cols) { + if (ec != null && CrossEngineValidator.isJobInterrupted(ec)) { + Long jobId = ec.getDdlJobId(); + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + "The job '" + jobId + "' has been cancelled"); + } + if (needRebuild) { + // analyze table would rebuild full ndv sketch info + StatisticManager.getInstance().rebuildShardParts(schema, logicalTableName, colsName, ec, + sketchHllExecutor); + } else { + // schedule job only update ndv sketch info + StatisticManager.getInstance().updateAllShardParts(schema, logicalTableName, colsName, ec, + sketchHllExecutor); + } + } } + } finally { + if (sketchHllExecutor != null) { + sketchHllExecutor.shutdown(); + } + } - Set colSet = colMap.get(logicalTableName); - Set colDoneSet = Sets.newHashSet(); + ModuleLogInfo.getInstance().logInfo(Module.STATISTICS, PROCESS_END, + new String[] { + "statistic sketch table ", + schema + "," + logicalTableName + ",is force:" + needRebuild + ",cols:" + indexColsMap + }); + } - /** - * handle columns needed by plan - */ - for (ColumnMeta columnMeta : columnMetaList) { - if (ec != null && CrossEngineValidator.isJobInterrupted(ec)) { - long jobId = ec.getDdlJobId(); - throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, - "The job '" + jobId + "' has been cancelled"); + protected static void getIndexInfoFromGsi(TableMeta tableMeta, Set colDoneSet, + Map> indexColsMap) { + if (tableMeta == null || tableMeta.getGsiPublished() == null) { + return; + } + for (Map.Entry entry : tableMeta.getGsiPublished().entrySet()) { + List cols = entry.getValue().getIndexColumns(); + String indexName = entry.getKey(); + List colNames = cols.stream().map(bean -> bean.columnName).collect(Collectors.toList()); + for (int i = 0; i < cols.size(); i++) { + if ((!entry.getValue().nonUnique) && i == cols.size() - 1) { + continue; } - - String columnName = columnMeta.getOriginColumnName(); - if (!needRebuild && (colSet == null || !colSet.contains(columnName))) { + String colOrder = buildColumnsName(colNames, i + 1); + if (colDoneSet.contains(colOrder)) { continue; } - - if (needRebuild) { - // analyze table would rebuild full ndv sketch info - StatisticManager.getInstance() - .rebuildShardParts(schema, logicalTableName, columnName, ec, sketchHllExecutor); + if (indexColsMap.containsKey(indexName)) { + indexColsMap.get(indexName).add(colOrder); } else { - // schedule job only update ndv sketch info - StatisticManager.getInstance() - .updateAllShardParts(schema, logicalTableName, columnName, ec, sketchHllExecutor); + Set newSet = Sets.newHashSet(); + newSet.add(colOrder); + indexColsMap.put(indexName, newSet); } - colDoneSet.add(columnName); + colDoneSet.add(colOrder); } + } + } - /** - * handle columns inside index - */ - TableMeta tableMeta = - OptimizerContext.getContext(schema).getLatestSchemaManager().getTable(logicalTableName); - Map>> indexColsMap = GlobalIndexMeta.getTableIndexMap(tableMeta, null); - - for (String tblName : indexColsMap.keySet()) { - if (ec != null && CrossEngineValidator.isJobInterrupted(ec)) { - long jobId = ec.getDdlJobId(); - throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, - "The job '" + jobId + "' has been cancelled"); + protected static void getIndexInfoFromLocalIndex(TableMeta tableMeta, Set colDoneSet, + Map> indexColsMap) { + if (tableMeta == null) { + return; + } + for (IndexMeta localIndex : tableMeta.getAllIndexes()) { + List colList = localIndex.getKeyColumns(); + List colNames = colList.stream().map(ColumnMeta::getName).collect(Collectors.toList()); + String indexName = localIndex.getPhysicalIndexName(); + for (int i = 0; i < colList.size(); i++) { + if (localIndex.isUniqueIndex() && i == colList.size() - 1) { + continue; } - // index key -> columns - Map> indexColumnMap = indexColsMap.get(tblName); - for (List cols : indexColumnMap.values()) { - if (cols != null && cols.size() == 1 && colMap.get(tblName) != null && colMap.get(tblName) - .contains(cols.iterator().next())) { - continue; - } - for (int i = 0; i < cols.size() - 1; i++) { - String colsName = buildColumnsName(cols, i + 1); - if (colDoneSet.contains(colsName)) { - continue; - } - if (needRebuild) { - // analyze table would rebuild full ndv sketch info - StatisticManager.getInstance().rebuildShardParts(schema, logicalTableName, colsName, ec, - sketchHllExecutor); - } else { - // schedule job only update ndv sketch info - StatisticManager.getInstance().updateAllShardParts(schema, tblName, colsName, ec, - sketchHllExecutor); - } - colDoneSet.add(colsName); - } - - String columnsName = buildColumnsName(cols); - if (!colDoneSet.contains(columnsName)) { - if (needRebuild) { - // analyze table would rebuild full ndv sketch info - StatisticManager.getInstance().rebuildShardParts(schema, logicalTableName, columnsName, ec, - sketchHllExecutor); - } else { - // schedule job only update ndv sketch info - StatisticManager.getInstance().updateAllShardParts(schema, tblName, columnsName, ec, - sketchHllExecutor); - } - colDoneSet.add(columnsName); - } + String colOrder = buildColumnsName(colNames, i + 1); + if (colDoneSet.contains(colOrder)) { + continue; } - } - - ModuleLogInfo.getInstance().logRecord(Module.STATISTICS, PROCESS_END, - new String[] { - "statistic sketch table ", - schema + "," + logicalTableName + ",is force:" + needRebuild + ",cols:" + String.join(";", - colDoneSet) - }, LogLevel.NORMAL); - } finally { - if (sketchHllExecutor != null) { - sketchHllExecutor.shutdown(); + if (indexColsMap.containsKey(indexName)) { + indexColsMap.get(indexName).add(colOrder); + } else { + Set newSet = Sets.newHashSet(); + newSet.add(colOrder); + indexColsMap.put(indexName, newSet); + } + colDoneSet.add(colOrder); } } } @@ -620,7 +693,7 @@ public static void sampleTableDdl(String schemaName, String logicalTableName, Ex int maxSampleSize = InstConfUtil.getInt(ConnectionParams.HISTOGRAM_MAX_SAMPLE_SIZE); List rows = new ArrayList<>(); double sampleRateUp = - scanAnalyze(schemaName, logicalTableName, analyzeColumnList, sampleRate, maxSampleSize, rows); + scanAnalyze(schemaName, logicalTableName, analyzeColumnList, sampleRate, maxSampleSize, rows, true); for (int i = 0; i < analyzeColumnList.size(); i++) { if (ec != null && CrossEngineValidator.isJobInterrupted(ec)) { long jobId = ec.getDdlJobId(); @@ -937,7 +1010,7 @@ public static boolean canUseNewTopN(String schemaName, String logicalTableName, return true; } - private static Row purgeRowForHistogram(Row r, int size) { + private static Row purgeRowForHistogram(Row r, int size, Boolean purgeMysqlTime) { Row tmpRow = new ArrayRow(size, r.getParentCursorMeta()); for (int i = 0; i < size; i++) { try { @@ -960,7 +1033,7 @@ private static Row purgeRowForHistogram(Row r, int size) { } } DataType dt = r.getParentCursorMeta().getColumnMeta(i).getDataType(); - if (DataTypeUtil.isMysqlTimeType(dt)) { + if (purgeMysqlTime && DataTypeUtil.isMysqlTimeType(dt)) { byte[] bytes = r.getBytes(i); tmpRow.setObject(i, packDateTypeToLong(dt, bytes)); } else { @@ -974,8 +1047,69 @@ private static Row purgeRowForHistogram(Row r, int size) { return tmpRow; } - private static double scanAnalyze(String schema, String logicalTableName, List columnMetaList, - float sampleRate, int maxSampleSize, List rows) { + public static double scanAnalyzeOnPkRange(String schema, String logicalTableName, List columnMetaList, + float sampleRate, int maxSampleRows, List rows, + PhyTableOperation phyTableOperation, + Map parameterContextMap) { + // scan sampling + try { + StringBuilder hint = new StringBuilder(); + hint.append( + "/*+TDDL:cmd_extra(MERGE_CONCURRENT=true,ENABLE_DIRECT_PLAN=false,ENABLE_COLUMNAR_SCAN_EXEC=false) */ "); + String traceId = ""; + hint.append(String.format(" /* trace_id(%s) */ ", traceId)); + + IServerConfigManager serverConfigManager = GsiUtils.getServerConfigManager(); + ResultSet resultSet = null; + Connection connection = null; + try { + connection = (Connection) serverConfigManager.getTransConnection(schema); + PreparedStatement statement = connection.prepareStatement(hint + phyTableOperation.getNativeSql()); + ParameterMethod.setParameters(statement, parameterContextMap); + resultSet = statement.executeQuery(); + int rowCount = 0; + CursorMeta cursorMeta = CursorMeta.build(columnMetaList); + Random random = new Random(); + while (resultSet.next()) { + Object[] objects = new Object[columnMetaList.size()]; + for (int columnIndex = 1; columnIndex <= columnMetaList.size(); columnIndex++) { + objects[columnIndex - 1] = resultSet.getObject(columnIndex); + } + if (rowCount < maxSampleRows) { + rows.add(new ArrayRow(cursorMeta, objects)); + rowCount++; + } else { + int rowIndex = random.nextInt(maxSampleRows) - 1; + rows.set(rowIndex, new ArrayRow(cursorMeta, objects)); + } + } + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + try { + if (resultSet != null) { + resultSet.close(); + } + + } catch (SQLException exception) { + throw new RuntimeException(exception); + } finally { + if (connection != null) { + connection.close(); + } + } + } + } catch (RuntimeException | SQLException e) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, " scan sample on pk range failed!, and the cause is " + + Optional.ofNullable(e.getMessage()).orElse(" unknown cause")); + } + return (double) rows.size() * sampleRate / maxSampleRows; + } + + // purge is true by default. + // purge is false when scan analyze on pks driven by backfill, because pk is not nullable, and generally not long. + public static double scanAnalyze(String schema, String logicalTableName, List columnMetaList, + float sampleRate, int maxSampleSize, List rows, Boolean purge) { // scan sampling ResultCursor rc = null; ITransaction trx = null; @@ -1006,12 +1140,12 @@ private static double scanAnalyze(String schema, String logicalTableName, List maxSampleSize) { if (rand.nextInt(rowcount) < maxSampleSize) { - rows.set(rand.nextInt(maxSampleSize), purgeRowForHistogram(r, columnMetaList.size())); + rows.set(rand.nextInt(maxSampleSize), purgeRowForHistogram(r, columnMetaList.size(), purge)); } else { // ignore } } else { - rows.add(purgeRowForHistogram(r, columnMetaList.size())); + rows.add(purgeRowForHistogram(r, columnMetaList.size(), purge)); } rowcount++; } @@ -1038,7 +1172,33 @@ protected static String constructScanSamplingSql(String logicalTableName, List columnMetaList, + float sampleRate, Map leftRow, + Map rightRow) { + StringBuilder sql = new StringBuilder(); + + String cmdExtraSamplePercentage = ""; + cmdExtraSamplePercentage = ",sample_percentage=" + sampleString(sampleRate * 100); sql.append( "/*+TDDL:cmd_extra(" + "enable_post_planner=false,enable_index_selection=false,merge_union=false,enable_direct_plan=false" diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/BackfillExecutor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/BackfillExecutor.java index 4322fa9b3..f47eab1cc 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/BackfillExecutor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/BackfillExecutor.java @@ -25,6 +25,8 @@ import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.backfill.BatchConsumer; import com.alibaba.polardbx.executor.backfill.Extractor; +import com.alibaba.polardbx.executor.backfill.GsiPartitionExtractor; +import com.alibaba.polardbx.executor.backfill.GsiPkRangeExtractor; import com.alibaba.polardbx.executor.backfill.Loader; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.gsi.backfill.CdasLoader; @@ -39,6 +41,7 @@ import com.alibaba.polardbx.statistics.SQLRecorderLogger; import org.apache.calcite.rel.RelNode; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -62,7 +65,17 @@ public BackfillExecutor(BiFunction, ExecutionContext, List public int backfill(String schemaName, String primaryTable, String indexName, boolean useBinary, boolean useChangeSet, boolean canUseReturning, List modifyStringColumns, - ExecutionContext baseEc) { + boolean onlineModifyColumn, ExecutionContext baseEc) { + return backfill(schemaName, primaryTable, indexName, useBinary, + useChangeSet, canUseReturning, modifyStringColumns, null, null, + onlineModifyColumn, 1, baseEc); + } + + public int backfill(String schemaName, String primaryTable, String indexName, boolean useBinary, + boolean useChangeSet, boolean canUseReturning, List modifyStringColumns, + Pair, Map> pkRange, + List partitionList, + Boolean onlineModifyColumn, int totalThreadCount, ExecutionContext baseEc) { final long batchSize = baseEc.getParamManager().getLong(ConnectionParams.GSI_BACKFILL_BATCH_SIZE); final long speedLimit = baseEc.getParamManager().getLong(ConnectionParams.GSI_BACKFILL_SPEED_LIMITATION); final long speedMin = baseEc.getParamManager().getLong(ConnectionParams.GSI_BACKFILL_SPEED_MIN); @@ -84,17 +97,34 @@ public int backfill(String schemaName, String primaryTable, String indexName, bo extractor = ChangeSetExecutor .create(schemaName, primaryTable, indexName, batchSize, speedMin, speedLimit, parallelism, - useBinary, modifyStringColumns, sourcePhyTables, baseEc); + useBinary, modifyStringColumns, sourcePhyTables, onlineModifyColumn, baseEc); loader = GsiChangeSetLoader.create(schemaName, primaryTable, indexName, this.executeFunc, baseEc.isUseHint(), baseEc, tableNameMapping); + } else if (pkRange != null) { + long pkRangeSpeedLimit = speedLimit / totalThreadCount; + extractor = + GsiPkRangeExtractor.create(schemaName, primaryTable, indexName, batchSize, speedMin, pkRangeSpeedLimit, + parallelism, + useBinary, modifyStringColumns, pkRange, baseEc); + loader = + GsiLoader.create(schemaName, primaryTable, indexName, this.executeFunc, baseEc.isUseHint(), + canUseReturning, onlineModifyColumn, baseEc); + } else if (partitionList != null) { + extractor = + GsiPartitionExtractor.create(schemaName, primaryTable, indexName, batchSize, speedMin, speedLimit, + parallelism, + useBinary, modifyStringColumns, partitionList, baseEc); + loader = + GsiLoader.create(schemaName, primaryTable, indexName, this.executeFunc, baseEc.isUseHint(), + canUseReturning, onlineModifyColumn, baseEc); } else { extractor = GsiExtractor.create(schemaName, primaryTable, indexName, batchSize, speedMin, speedLimit, parallelism, - useBinary, modifyStringColumns, baseEc); + useBinary, modifyStringColumns, onlineModifyColumn, baseEc); loader = GsiLoader.create(schemaName, primaryTable, indexName, this.executeFunc, baseEc.isUseHint(), - canUseReturning, baseEc); + canUseReturning, onlineModifyColumn, baseEc); } boolean finished; @@ -127,6 +157,14 @@ public void consume(List> batch, if (e.getMessage().contains("need to be split into smaller batches")) { finished = false; } else { + SQLRecorderLogger.ddlLogger.warn( + MessageFormat.format( + "[{0}] [{1}][{2}] execution get exception {3}", + baseEc.getTraceId(), + baseEc.getTaskId().toString(), + baseEc.getBackfillId().toString(), + e) + ); throw e; } } @@ -136,7 +174,7 @@ public void consume(List> batch, } public int mirrorCopyGsiBackfill(String schemaName, String primaryTable, String indexName, boolean useChangeSet, - boolean useBinary, ExecutionContext baseEc) { + boolean useBinary, boolean onlineModifyColumn, ExecutionContext baseEc) { final long batchSize = baseEc.getParamManager().getLong(ConnectionParams.GSI_BACKFILL_BATCH_SIZE); final long speedLimit = baseEc.getParamManager().getLong(ConnectionParams.GSI_BACKFILL_SPEED_LIMITATION); final long speedMin = baseEc.getParamManager().getLong(ConnectionParams.GSI_BACKFILL_SPEED_MIN); @@ -155,7 +193,7 @@ public int mirrorCopyGsiBackfill(String schemaName, String primaryTable, String OmcMirrorCopyExtractor extractor = OmcMirrorCopyExtractor.create(schemaName, primaryTable, indexName, batchSize, speedMin, speedLimit, - parallelism, tableNameMapping, sourcePhyTables, useChangeSet, useBinary, baseEc); + parallelism, tableNameMapping, sourcePhyTables, useChangeSet, useBinary, onlineModifyColumn, baseEc); extractor.loadBackfillMeta(executionContext); final AtomicInteger affectRows = new AtomicInteger(); @@ -199,7 +237,7 @@ public int logicalTableDataMigrationBackFill(String srcSchemaName, String dstSch copiedEc.setSchemaName(dstSchemaName); final Extractor extractor = GsiExtractor.create(srcSchemaName, srcTableName, srcTableName, batchSize, speedMin, speedLimit, parallelism, - useBinary, null, baseEc); + useBinary, null, false, baseEc); final CdasLoader cdasLoader = CdasLoader.create(srcSchemaName, dstSchemaName, srcTableName, dstTableName, this.executeFunc, copiedEc.isUseHint(), copiedEc, false); @@ -285,7 +323,7 @@ public int addColumnsBackfill(String schemaName, String primaryTable, List params = new HashMap<>(); + MetaDbUtil.setParameter(params.size() + 1, params, ParameterMethod.setLong, + System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60)); + + MetaDbUtil.delete(SQL_CLEAN_OUTDATED_IMPORT_TABLESPACE_INFO_STAT_LOG, params, conn); + PhysicalBackfillUtils.destroyDataSources(); } catch (SQLException e) { throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_EXECUTE, e, - "clean outdated backfill log failed!"); + "clean outdated backfill/import_tablespace log failed!"); } }); } catch (Exception e) { @@ -205,22 +215,27 @@ public DataSource getDataSource() { } public void initBackfillMeta(ExecutionContext ec, List initBackfillObjects) { + // insert logicalBfo for physicalBfo + // final BackfillObjectRecord bfo = initBackfillObjects.get(0); final BackfillObjectRecord logicalBfo = bfo.copy(); logicalBfo.setPhysicalDb(null); logicalBfo.setPhysicalTable(null); - logicalBfo.setExtra(""); + logicalBfo.setLastValue("0"); + BackfillExtraFieldJSON extraJson = BackfillExtraFieldJSON.fromJson(bfo.extra); + extraJson.setLogical(true); + logicalBfo.setExtra(BackfillExtraFieldJSON.toJson(extraJson)); initBackfillObjects.add(0, logicalBfo); - insertBackfillMeta(ec, initBackfillObjects, true); } - public void initBackfillMeta(ExecutionContext ec, long backfillId, String schemaName, String tableName, + public void initBackfillMeta(ExecutionContext ec, long backfillId, long taskId, String schemaName, String tableName, String indexName, List positionMarks) { final List backfillObjectRecords = positionMarks.stream() .map(bfo -> new BackfillObjectRecord(-1, backfillId, + taskId, schemaName, tableName, schemaName, @@ -243,12 +258,17 @@ public void initBackfillMeta(ExecutionContext ec, long backfillId, String schema final BackfillObjectRecord logicalBfo = bfo.copy(); logicalBfo.setPhysicalDb(null); logicalBfo.setPhysicalTable(null); + BackfillExtraFieldJSON extraJson = BackfillExtraFieldJSON.fromJson(bfo.extra); + extraJson.setLogical(true); + logicalBfo.setExtra(BackfillExtraFieldJSON.toJson(extraJson)); backfillObjectRecords.add(0, logicalBfo); insertBackfillMeta(ec, backfillObjectRecords, true); } public BackfillBean loadBackfillMeta(long backfillId) { + // TODO(yijin) assume that each reporter only process one logicalBfo + // what if each reporter process multiple logicalBfo List bfoList = queryBackfillObject(backfillId); if (CollectionUtils.isEmpty(bfoList)) { return BackfillBean.EMPTY; @@ -256,7 +276,9 @@ public BackfillBean loadBackfillMeta(long backfillId) { BackfillObjectRecord logicalBfo = null; List physicalBfoList = new ArrayList<>(bfoList.size()); for (BackfillObjectRecord e : bfoList) { - if (TStringUtil.isEmpty(e.getPhysicalDb())) { + // judge whether this is physical backfillObject + // for pk range, it's neccessary to make some mark + if (e.isLogicalBackfillObject()) { logicalBfo = e; } else { physicalBfoList.add(e); @@ -269,6 +291,7 @@ public BackfillBean loadBackfillMeta(long backfillId) { BackfillRecord br = new BackfillRecord( logicalBfo.getId(), logicalBfo.getJobId(), + logicalBfo.getTaskId(), logicalBfo.getTableSchema(), logicalBfo.getTableName(), logicalBfo.getIndexSchema(), @@ -327,6 +350,7 @@ public Integer updateBackfillObject(List backfillObject, Lis return new BackfillObjectRecord(bfo.id, bfo.jobId, + bfo.taskId, bfo.tableSchema, bfo.tableName, bfo.indexSchema, @@ -420,6 +444,7 @@ public void updateLogicalBackfillProcess(String progress, Long backfillId) { BackfillExtraFieldJSON extra = new BackfillExtraFieldJSON(); extra.setProgress(progress); + extra.setLogical(true); String extraStr = BackfillExtraFieldJSON.toJson(extra); Map params = new HashMap<>(); params.put(1, new ParameterContext(ParameterMethod.setString, new Object[] {1, progress})); @@ -475,6 +500,10 @@ public static boolean deleteAll(String schemaName, Connection conn) { private void insertBackfillMeta(ExecutionContext ec, List backfillObjectRecords, boolean insertIgnore) { + // for logical pk range insertion, The backfillId would be different, because it's generated dynamic + // in each task. so we would always load an empty bean. + // to support continiously insertion in task, we need to keep every backfillId as same as before. + // and only sample for backfillId when there is no backfillBeanId. wrapWithTransaction(dataSource, (conn) -> { try { @@ -633,22 +662,22 @@ private static void wrapWithTransaction(DataSource dataSource, Consumer> backfillObjects) { this.id = id; this.jobId = jobId; + this.taskId = taskId; this.tableSchema = tableSchema; this.tableName = tableName; this.indexSchema = indexSchema; @@ -816,6 +853,7 @@ public static BackfillBean create(BackfillRecord bfRecord, List params() { final Map params = new HashMap<>(); params.put(1, new ParameterContext(ParameterMethod.setLong, new Object[] {1, this.jobId})); - params.put(2, new ParameterContext(ParameterMethod.setString, new Object[] {2, this.tableSchema})); - params.put(3, new ParameterContext(ParameterMethod.setString, new Object[] {3, this.tableName})); - params.put(4, new ParameterContext(ParameterMethod.setString, new Object[] {4, this.indexSchema})); - params.put(5, new ParameterContext(ParameterMethod.setString, new Object[] {5, this.indexName})); - params.put(6, new ParameterContext(ParameterMethod.setString, new Object[] {6, this.indexTableName})); - params.put(7, new ParameterContext(ParameterMethod.setLong, new Object[] {7, this.status})); - params.put(8, new ParameterContext(ParameterMethod.setString, new Object[] {8, this.message})); + params.put(2, new ParameterContext(ParameterMethod.setLong, new Object[] {1, this.taskId})); + params.put(3, new ParameterContext(ParameterMethod.setString, new Object[] {2, this.tableSchema})); + params.put(4, new ParameterContext(ParameterMethod.setString, new Object[] {3, this.tableName})); + params.put(5, new ParameterContext(ParameterMethod.setString, new Object[] {4, this.indexSchema})); + params.put(6, new ParameterContext(ParameterMethod.setString, new Object[] {5, this.indexName})); + params.put(7, new ParameterContext(ParameterMethod.setString, new Object[] {6, this.indexTableName})); + params.put(8, new ParameterContext(ParameterMethod.setLong, new Object[] {7, this.status})); + params.put(9, new ParameterContext(ParameterMethod.setString, new Object[] {8, this.message})); // params.put(9, new ParameterContext(ParameterMethod.setString, new // Object[] { // 9, this.startTime })); // params.put(10, new ParameterContext(ParameterMethod.setString, // new Object[] { // 10, this.endTime })); - params.put(9, new ParameterContext(ParameterMethod.setString, new Object[] {9, this.extra})); + params.put(10, new ParameterContext(ParameterMethod.setString, new Object[] {9, this.extra})); return params; } @@ -1247,6 +1303,14 @@ public void setJobId(long jobId) { this.jobId = jobId; } + public long getTaskId() { + return taskId; + } + + public void setTaskId(long taskId) { + this.taskId = taskId; + } + public String getTableSchema() { return tableSchema; } @@ -1413,6 +1477,7 @@ public static class BackfillObjectRecord extends AbstractBackfillBean implements private long id; private long jobId; + private long taskId; private String tableSchema; private String tableName; private String indexSchema; @@ -1433,6 +1498,7 @@ public static class BackfillObjectRecord extends AbstractBackfillBean implements public BackfillObjectRecord() { this.id = -1; this.jobId = -1; + this.taskId = -1; this.tableSchema = null; this.tableName = null; this.indexSchema = null; @@ -1452,13 +1518,15 @@ public BackfillObjectRecord() { } - public BackfillObjectRecord(long id, long jobId, String tableSchema, String tableName, String indexSchema, + public BackfillObjectRecord(long id, long jobId, long taskId, String tableSchema, String tableName, + String indexSchema, String indexName, String physicalDb, String physicalTable, long columnIndex, String parameterMethod, String lastValue, String maxValue, long status, String message, long successRowCount, String startTime, String endTime, String extra) { this.id = id; this.jobId = jobId; + this.taskId = taskId; this.tableSchema = tableSchema; this.tableName = tableName; this.indexSchema = indexSchema; @@ -1481,6 +1549,7 @@ public BackfillObjectRecord copy() { BackfillObjectRecord result = new BackfillObjectRecord(); result.id = this.id; result.jobId = this.jobId; + result.taskId = this.taskId; result.tableSchema = this.tableSchema; result.tableName = this.tableName; result.indexSchema = this.indexSchema; @@ -1504,6 +1573,7 @@ public BackfillObjectRecord copy() { public BackfillObjectRecord convert(ResultSet resultSet) throws SQLException { final long id = resultSet.getLong("ID"); final long jobId = resultSet.getLong("JOB_ID"); + final long taskId = resultSet.getLong("TASK_ID"); final String tableSchema = resultSet.getString("TABLE_SCHEMA"); final String tableName = resultSet.getString("TABLE_NAME"); final String indexSchema = resultSet.getString("INDEX_SCHEMA"); @@ -1523,6 +1593,7 @@ public BackfillObjectRecord convert(ResultSet resultSet) throws SQLException { return new BackfillObjectRecord(id, jobId, + taskId, tableSchema, tableName, indexSchema, @@ -1545,22 +1616,23 @@ public BackfillObjectRecord convert(ResultSet resultSet) throws SQLException { public Map params() { final Map params = new HashMap<>(); params.put(1, new ParameterContext(ParameterMethod.setLong, new Object[] {1, this.jobId})); - params.put(2, new ParameterContext(ParameterMethod.setString, new Object[] {2, this.tableSchema})); - params.put(3, new ParameterContext(ParameterMethod.setString, new Object[] {3, this.tableName})); - params.put(4, new ParameterContext(ParameterMethod.setString, new Object[] {4, this.indexSchema})); - params.put(5, new ParameterContext(ParameterMethod.setString, new Object[] {5, this.indexName})); - params.put(6, new ParameterContext(ParameterMethod.setString, new Object[] {6, this.physicalDb})); - params.put(7, new ParameterContext(ParameterMethod.setString, new Object[] {7, this.physicalTable})); - params.put(8, new ParameterContext(ParameterMethod.setLong, new Object[] {8, this.columnIndex})); - params.put(9, new ParameterContext(ParameterMethod.setString, new Object[] {9, this.parameterMethod})); - params.put(10, new ParameterContext(ParameterMethod.setString, new Object[] {10, this.lastValue})); - params.put(11, new ParameterContext(ParameterMethod.setString, new Object[] {11, this.maxValue})); - params.put(12, new ParameterContext(ParameterMethod.setLong, new Object[] {12, this.status})); - params.put(13, new ParameterContext(ParameterMethod.setString, new Object[] {13, this.message})); - params.put(14, new ParameterContext(ParameterMethod.setLong, new Object[] {14, this.successRowCount})); - params.put(15, new ParameterContext(ParameterMethod.setString, new Object[] {15, this.startTime})); - params.put(16, new ParameterContext(ParameterMethod.setString, new Object[] {16, this.endTime})); - params.put(17, new ParameterContext(ParameterMethod.setString, new Object[] {17, this.extra})); + params.put(2, new ParameterContext(ParameterMethod.setLong, new Object[] {2, this.taskId})); + params.put(3, new ParameterContext(ParameterMethod.setString, new Object[] {3, this.tableSchema})); + params.put(4, new ParameterContext(ParameterMethod.setString, new Object[] {4, this.tableName})); + params.put(5, new ParameterContext(ParameterMethod.setString, new Object[] {5, this.indexSchema})); + params.put(6, new ParameterContext(ParameterMethod.setString, new Object[] {6, this.indexName})); + params.put(7, new ParameterContext(ParameterMethod.setString, new Object[] {7, this.physicalDb})); + params.put(8, new ParameterContext(ParameterMethod.setString, new Object[] {8, this.physicalTable})); + params.put(9, new ParameterContext(ParameterMethod.setLong, new Object[] {9, this.columnIndex})); + params.put(10, new ParameterContext(ParameterMethod.setString, new Object[] {10, this.parameterMethod})); + params.put(11, new ParameterContext(ParameterMethod.setString, new Object[] {11, this.lastValue})); + params.put(12, new ParameterContext(ParameterMethod.setString, new Object[] {12, this.maxValue})); + params.put(13, new ParameterContext(ParameterMethod.setLong, new Object[] {13, this.status})); + params.put(14, new ParameterContext(ParameterMethod.setString, new Object[] {14, this.message})); + params.put(15, new ParameterContext(ParameterMethod.setLong, new Object[] {15, this.successRowCount})); + params.put(16, new ParameterContext(ParameterMethod.setString, new Object[] {16, this.startTime})); + params.put(17, new ParameterContext(ParameterMethod.setString, new Object[] {17, this.endTime})); + params.put(18, new ParameterContext(ParameterMethod.setString, new Object[] {18, this.extra})); return params; } @@ -1570,6 +1642,10 @@ public boolean isWrapperFor(Class iface) { return BackfillObjectRecord.class.isAssignableFrom(iface); } + public boolean isLogicalBackfillObject() { + return StringUtils.isEmpty(physicalDb) && BackfillExtraFieldJSON.fromJson(extra).getLogical(); + } + public long getId() { return id; } @@ -1586,6 +1662,14 @@ public void setJobId(long jobId) { this.jobId = jobId; } + public long getTaskId() { + return taskId; + } + + public void setTaskid(long taskId) { + this.taskId = taskId; + } + public String getTableSchema() { return tableSchema; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/GsiManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/GsiManager.java index 03ec69756..2241e80a3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/GsiManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/GsiManager.java @@ -65,4 +65,16 @@ public GsiMetaManager getGsiMetaManager() { DataSource gsiMgrDs = MetaDbDataSource.getInstance().getDataSource(); return new GsiMetaManager(gsiMgrDs, topologyHandler.getSchemaName()); } + + /** + * Get meta of gsi with specified status from system table + * + * @param tableName primary table name + * @param indexName index table name + * @return gsi meta + */ + public GsiMetaManager.GsiIndexMetaBean getGsiIndexMeta(String schema, String tableName, String indexName, + EnumSet statusSet) { + return getGsiMetaManager().getIndexMeta(schema, tableName, indexName, statusSet); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/GsiUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/GsiUtils.java index 45109a78d..7573544f3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/GsiUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/GsiUtils.java @@ -19,20 +19,35 @@ import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.IConnection; import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; +import com.alibaba.polardbx.common.jdbc.MasterSlave; import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.jdbc.Parameters; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.ParamManager; import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.TStringUtil; +import com.alibaba.polardbx.common.utils.thread.ServerThreadPool; import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.ddl.twophase.DnStats; import com.alibaba.polardbx.executor.gsi.GsiBackfillManager.BackfillObjectRecord; import com.alibaba.polardbx.executor.gsi.GsiBackfillManager.BackfillRecord; import com.alibaba.polardbx.executor.gsi.GsiBackfillManager.BackfillStatus; import com.alibaba.polardbx.executor.spi.ITransactionManager; +import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.gms.metadb.table.IndexStatus; import com.alibaba.polardbx.gms.metadb.table.IndexVisibility; import com.alibaba.polardbx.gms.metadb.table.IndexesRecord; +import com.alibaba.polardbx.gms.node.GmsNodeManager; +import com.alibaba.polardbx.gms.sync.SyncScope; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.group.jdbc.TGroupDataSource; import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.server.DefaultServerConfigManager; +import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager.IndexColumnType; import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager.IndexRecord; @@ -44,6 +59,7 @@ import com.alibaba.polardbx.optimizer.partition.PartitionSpec; import com.alibaba.polardbx.optimizer.partition.common.PartitionLocation; import com.alibaba.polardbx.optimizer.utils.ITransaction; +import com.alibaba.polardbx.optimizer.utils.OptimizerHelper; import com.alibaba.polardbx.optimizer.utils.PlannerUtils; import com.alibaba.polardbx.optimizer.utils.RelUtils; import com.alibaba.polardbx.rule.TableRule; @@ -74,6 +90,10 @@ import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -87,6 +107,9 @@ import java.util.Optional; import java.util.Set; import java.util.TreeSet; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Supplier; @@ -223,12 +246,17 @@ public static Map getPhysicalTableMapping(String schemaName, Str return phyTableMapping; } + public static Map> getPhyTablesForBackFill(String schemaName, String logicalTableName) { + return getPhyTablesForBackFill(schemaName, logicalTableName, null); + } + /** * return group and physical tables for one logical table. * * @return db: [tbs], db and tb are both sorted */ - public static Map> getPhyTablesForBackFill(String schemaName, String logicalTableName) { + public static Map> getPhyTablesForBackFill(String schemaName, String logicalTableName, + List partitionList) { PartitionInfo partitionInfo = OptimizerContext.getContext(schemaName).getPartitionInfoManager().getPartitionInfo(logicalTableName); if (partitionInfo == null) { @@ -247,9 +275,13 @@ public static Map> getPhyTablesForBackFill(String schemaName } } else { Map> phyTables = new HashMap<>(); + Set partitionNames = new HashSet<>(Optional.ofNullable(partitionList).orElse(new ArrayList<>())); for (PartitionSpec spec : partitionInfo.getPartitionBy().getPhysicalPartitions()) { PartitionLocation location = spec.getLocation(); - phyTables.computeIfAbsent(location.getGroupKey(), o -> new HashSet<>()).add(location.getPhyTableName()); + if (partitionNames.isEmpty() || partitionNames.contains(spec.getName())) { + phyTables.computeIfAbsent(location.getGroupKey(), o -> new HashSet<>()) + .add(location.getPhyTableName()); + } if (partitionInfo.isGsiBroadcastOrBroadcast()) { break; } @@ -979,9 +1011,11 @@ public static String getPartitionPolicy(String rule) { return partitionPolicy; } - public static BackfillRecord buildBackfillRecord(long jobId, String schema, String tableName, String indexName) { + public static BackfillRecord buildBackfillRecord(long jobId, long taskId, String schema, String tableName, + String indexName) { return new BackfillRecord(-1, jobId, + taskId, schema, tableName, schema, @@ -994,12 +1028,14 @@ public static BackfillRecord buildBackfillRecord(long jobId, String schema, Stri ""); } - public static BackfillObjectRecord buildBackfillObjectRecord(long jobId, String schema, String tableName, + public static BackfillObjectRecord buildBackfillObjectRecord(long jobId, long taskId, String schema, + String tableName, String indexName, String physicalDb, String physicalTable, long columnIndex, String extra) { return new BackfillObjectRecord(-1, jobId, + taskId, schema, tableName, schema, @@ -1018,13 +1054,15 @@ public static BackfillObjectRecord buildBackfillObjectRecord(long jobId, String extra); } - public static BackfillObjectRecord buildBackfillObjectRecord(long jobId, String schema, String tableName, + public static BackfillObjectRecord buildBackfillObjectRecord(long jobId, long taskId, String schema, + String tableName, String indexName, String physicalDb, String physicalTable, long columnIndex, String paramMethod, String lastValue, String maxValue, String extra) { return new BackfillObjectRecord(-1, jobId, + taskId, schema, tableName, schema, @@ -1053,6 +1091,47 @@ public static R wrapWithDistributedTrx(ITransactionManager tm, ExecutionCont return wrapWithTransaction(tm, tm.getDefaultDistributedTrxPolicy(baseEc), baseEc, call); } + public static IServerConfigManager getServerConfigManager() { + IServerConfigManager serverConfigManager = OptimizerHelper.getServerConfigManager(); + if (serverConfigManager == null) { + serverConfigManager = new DefaultServerConfigManager(null); + } + return serverConfigManager; + } + + public static R wrapWithDistributedTrxForPkExtractor(ITransactionManager tm, ExecutionContext baseEc, + IServerConfigManager serverMgr, + Function, R> caller) { + final ExecutionContext ec = baseEc.copy(); + R result = null; + Object transConn = null; + String schemaName = ec.getSchemaName(); + try { + transConn = serverMgr.getTransConnection(schemaName); + serverMgr.transConnectionBegin(transConn); + result = caller.apply(Pair.of(ec, (Connection) transConn)); + serverMgr.transConnectionCommit(transConn); + } catch (SQLException ex) { + if (transConn != null) { + try { + serverMgr.transConnectionRollback(transConn); + } catch (Throwable err) { + // ignore + } + } + throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, ex); + } finally { + if (null != transConn) { + try { + serverMgr.closeTransConnection(transConn); + } catch (Throwable ex) { + // ignore + } + } + } + return result; + } + public static R wrapWithSingleDbTrx(ITransactionManager tm, ExecutionContext baseEc, Function call) { return wrapWithTransaction(tm, ITransactionPolicy.ALLOW_READ_CROSS_DB, baseEc, call); @@ -1088,8 +1167,12 @@ public static R wrapWithTransaction(ITransactionManager tm, ITransactionPoli ec.setTxId(0L); // Create new transaction - trx = tm.createTransaction(policy.getTransactionType(false, ec.isReadOnly()), ec); + trx = tm.createTransaction(policy.getTransactionType(false, ec.isReadOnly(), false, false), ec); ec.setTransaction(trx); + if (0 == trx.getStartTimeInMs()) { + trx.setStartTimeInMs(ec.getLogicalSqlStartTimeInMs()); + trx.setStartTime(ec.getLogicalSqlStartTime()); + } // Do something within transaction, eg.lock some row return caller.apply(ec); @@ -1112,6 +1195,36 @@ public static String rowToString(Map row) { .collect(Collectors.joining(",")); } + public static String rowToString(List row) { + return GeneralUtil.isEmpty(row) ? "" : row + .stream() + .sorted(Comparator.comparingLong(o -> Long.valueOf(o.getArgs()[0].toString()))) + .map(o -> o.getValue() == null ? "null" : String.valueOf(o.getValue())) + .collect(Collectors.joining(",")); + } + +// public static String rowsToString(List> rows) { +// if (rows.isEmpty()) { +// return ""; +// } else { +// List results = new ArrayList<>(); +// for (Map row : rows) { +// if(row == null){ +// results.add(""); +// continue; +// } +// int size = row.size(); +// List result = new ArrayList<>(); +// for (Integer key: row.keySet()) { +// result.add(row.get(key).getValue().toString()); +// } +// results.add(StringUtils.join(result, "-").toString()); +// } +// return StringUtils.join(results, ", "); +// +// } +// } + public static boolean vendorErrorIs(TddlNestableRuntimeException e, String sqlState, ErrorCode errCode) { return sqlState.equals(e.getSQLState()) && errCode.getCode() == e.getErrorCode(); } @@ -1123,14 +1236,22 @@ public static R retryOnDeadLock(Supplier call, public static R retryOnException(Supplier call, Function errChecker, BiConsumer errConsumer) { + return retryOnException(call, errChecker, errConsumer, null); + } + + public static R retryOnException(Supplier call, Function errChecker, + BiConsumer errConsumer, + ExecutionContext ec) { int retryCount = 0; + String prefix = + (ec == null) ? "" : String.format("[%s][%s][%s] ", ec.getTraceId(), ec.getTaskId(), ec.getBackfillId()); do { try { return call.get(); } catch (TddlNestableRuntimeException e) { if (errChecker.apply(e)) { SQLRecorderLogger.ddlLogger.warn(MessageFormat.format( - "retryOnException()#retry with errorCode:{0}, errorMsg:{1}", + prefix + "retryOnException()#retry with errorCode:{0}, errorMsg:{1}", e.getErrorCode(), e.getMessage() ), e); @@ -1138,7 +1259,7 @@ public static R retryOnException(Supplier call, Function sourceGroupDnMap = + DnStats.buildGroupToDnMap(schemaName, logicalTableName, executionContext); + int dnNodeNum = sourceGroupDnMap.values().stream().collect(Collectors.toSet()).size(); + maxNodeNum = Math.min(cnNodeNum, dnNodeNum); + }else{ + maxNodeNum = cnNodeNum; + } + } + return maxNodeNum; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/IndexExecutor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/IndexExecutor.java index e838fece3..4539a855e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/IndexExecutor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/IndexExecutor.java @@ -16,22 +16,14 @@ package com.alibaba.polardbx.executor.gsi; -import com.alibaba.polardbx.common.exception.TddlRuntimeException; -import com.alibaba.polardbx.common.exception.code.ErrorCode; -import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.row.Row; import org.apache.calcite.rel.RelNode; -import java.util.ArrayList; import java.util.List; import java.util.function.BiFunction; public abstract class IndexExecutor { - - public static final int MAX_UPDATE_NUM_IN_GSI_DEFAULT = 10000; - protected BiFunction, ExecutionContext, List> executeFunc; protected String schemaName; @@ -40,35 +32,4 @@ public IndexExecutor(BiFunction, ExecutionContext, List> e this.executeFunc = executeFunc; this.schemaName = schemaName; } - - protected List> getSelectResults(List selects, ExecutionContext executionContext) { - long selectLimit = executionContext.getParamManager().getLong(ConnectionParams.MAX_UPDATE_NUM_IN_GSI); - - List cursors = executeFunc.apply(selects, executionContext); - List> selectedObjects = new ArrayList<>(); - try { - for (int i = 0; i < cursors.size(); i++) { - Cursor cursor = cursors.get(i); - Row row; - while ((row = cursor.next()) != null && selectedObjects.size() <= selectLimit) { - selectedObjects.add(row.getValues()); - } - cursor.close(new ArrayList<>()); - cursors.set(i, null); - } - } finally { - for (Cursor cursor : cursors) { - if (cursor != null) { - cursor.close(new ArrayList<>()); - } - } - } - - if (selectedObjects.size() > selectLimit) { - throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_UPDATE_NUM_EXCEEDED, - String.valueOf(selectLimit)); - } - - return selectedObjects; - } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/PhysicalPlanBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/PhysicalPlanBuilder.java index 5b270ffd4..b7413bfa5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/PhysicalPlanBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/PhysicalPlanBuilder.java @@ -68,6 +68,7 @@ import org.apache.calcite.sql.SqlDelete; import org.apache.calcite.sql.SqlDmlKeyword; import org.apache.calcite.sql.SqlDynamicParam; +import org.apache.calcite.sql.SqlFunction; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlIndexHint; import org.apache.calcite.sql.SqlInsert; @@ -82,13 +83,13 @@ import org.apache.calcite.sql.SqlUpdate; import org.apache.calcite.sql.fun.SqlBinaryFunction; import org.apache.calcite.sql.fun.SqlHashCheckAggFunction; +import org.apache.calcite.sql.fun.SqlRandFunction; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeFactoryImpl; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.util.Pair; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.MapUtils; import java.text.MessageFormat; import java.util.ArrayList; @@ -243,6 +244,10 @@ protected void buildTargetTable() { targetTableNode = BuildPlanUtils.buildTargetTable(); } + protected void buildTargetTableAsLogicalTableName(String name) { + targetTableNode = new SqlIdentifier(name, SqlParserPos.ZERO); + } + protected void buildTargetTableParams(String tableName) { int tableIndex = PlannerUtils.TABLE_NAME_PARAM_INDEX + 2; currentParams.put(tableIndex, PlannerUtils.buildParameterContextForTableName(tableName, tableIndex)); @@ -1216,6 +1221,14 @@ public List buildSelectForCascadeUnionAll(TableMeta tableMeta, return newPhysicalPlans; } + public PhyTableOperation buildSelectForBackfill(TableMeta tableMeta, List selectKeys, + List primaryKeys, boolean withLowerBound, + boolean withUpperBound, LockMode lockMode, + String physicalPartition) { + return buildSelectForBackfill(tableMeta, selectKeys, primaryKeys, withLowerBound, withUpperBound, lockMode, + physicalPartition, false, true); + } + /** *
      * SELECT {all_columns_exists_in_index_table}
@@ -1238,7 +1251,8 @@ public List buildSelectForCascadeUnionAll(TableMeta tableMeta,
     public PhyTableOperation buildSelectForBackfill(TableMeta tableMeta, List selectKeys,
                                                     List primaryKeys, boolean withLowerBound,
                                                     boolean withUpperBound, LockMode lockMode,
-                                                    String physicalPartition) {
+                                                    String physicalPartition, Boolean useLogicalTableName,
+                                                    Boolean withLimit) {
         initParams(0);
 
         // build select list
@@ -1247,6 +1261,9 @@ public PhyTableOperation buildSelectForBackfill(TableMeta tableMeta, List buildSelectWithInForChecker(TableMeta
         return new Pair<>(sqlSelect, buildSelectPhyTblOpTemplate(sqlSelect, rowType, tableMeta, LockMode.UNDEF, ec));
     }
 
+    /**
+     * 
+     *  SELECT (k0, .., kn)
+     *  FROM TABLE
+     *  WHERE (k0, ..., kn) > (?, ..., ?) AND (k0, ..., kn) <= (?, ..., ?) AND RAND() <= ?
+     *  ORDER BY (k0, ..., kn);
+     * 
+ * + * @param tableMeta Table meta + * @param selectKeys Keys that need to be hash + * @return Query plan + */ + public PhyTableOperation buildSelectPlanForSample(TableMeta tableMeta, List selectKeys, + List conditionKeys, + boolean buildTargetTableAsLogicalTableName, + boolean withLowerBound, + boolean withUpperBound) { + + initParams(0); + + // build select list + SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO); + RelDataType rowType = buildRowTypeForSelect(selectKeys, tableMeta, selectList); + + // build target table + buildTargetTable(); + if (buildTargetTableAsLogicalTableName) { + buildTargetTableAsLogicalTableName(tableMeta.getTableName()); + } + + SqlNode condition = null; + if (withLowerBound) { + //where (k0, ..., kn) > (?, ..., ?) + condition = buildCondition(conditionKeys, SqlStdOperatorTable.GREATER_THAN); + } + if (withUpperBound) { + // where (k0, ..., kn) <= (?, ..., ?) + final SqlNode upperBound = buildCondition(conditionKeys, SqlStdOperatorTable.LESS_THAN_OR_EQUAL); + if (condition == null) { + condition = upperBound; + } else { + condition = PlannerUtils.buildAndTree(ImmutableList.of(condition, upperBound)); + } + } + // where rand() <= ? + final SqlNode sampleNode = buildRandCondition(SqlStdOperatorTable.LESS_THAN_OR_EQUAL); + if (condition == null) { + condition = sampleNode; + } else { + condition = PlannerUtils.buildAndTree(ImmutableList.of(condition, sampleNode)); + } + + // order by primary keys + SqlNodeList orderBy = new SqlNodeList( + conditionKeys.stream().map(key -> new SqlIdentifier(key, SqlParserPos.ZERO)).collect(Collectors.toList()), + SqlParserPos.ZERO); + + // limit ? + SqlNode fetch = new SqlDynamicParam(nextDynamicIndex++, SqlParserPos.ZERO); + SqlNode offset = SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO); + + final SqlSelect sqlSelect = + new SqlSelect(SqlParserPos.ZERO, null, selectList, targetTableNode, condition, null, null, null, orderBy, + offset, fetch); + + // lock mode + sqlSelect.setLockMode(LockMode.UNDEF); + + // create PhyTableOperation + return buildSelectPhyTblOpTemplate(sqlSelect, rowType, tableMeta, LockMode.UNDEF, ec); + } + /** *
      *  SELECT HASHCKECK({all_select_keys})
@@ -1526,17 +1618,20 @@ public PhyTableOperation buildSelectHashCheckForChecker(TableMeta tableMeta, Lis
 
     /**
      * 
-     *  SELECT HASHCKECK({all_select_keys})
+     *  SELECT HASHCKECK({common_keys}), HASHCKECK({origin_keys}), HASHCKECK({check_keys})
      *  FROM ?
      * 
* * @param tableMeta Table meta - * @param selectKeys Keys that need to be hash + * @param commonKeys Keys which not changed + * @param originKeys Keys which changed + * @param checkKeys Keys which are generated columns are used for checking * @return Query plan */ public PhyTableOperation buildSelectHashCheckForGSIChecker(TableMeta tableMeta, - List selectKeys, - Map virtualSelectKeys, + List commonKeys, + List originKeys, + List checkKeys, List conditionKeys, boolean withLowerBound, boolean withUpperBound) { @@ -1545,19 +1640,42 @@ public PhyTableOperation buildSelectHashCheckForGSIChecker(TableMeta tableMeta, // build select list SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO); - RelDataType rowType = buildRowTypeForSelect(selectKeys, tableMeta, selectList); + SqlNodeList originColumnList = new SqlNodeList(SqlParserPos.ZERO); + SqlNodeList checkColumnList = new SqlNodeList(SqlParserPos.ZERO); + for (String colNameStr : commonKeys) { + selectList.add(new SqlIdentifier(colNameStr, SqlParserPos.ZERO)); + } + for (String colNameStr : originKeys) { + originColumnList.add(new SqlIdentifier(colNameStr, SqlParserPos.ZERO)); + } + for (String colNameStr : checkKeys) { + checkColumnList.add(new SqlIdentifier(colNameStr, SqlParserPos.ZERO)); + } - // for modify partition key check - if (MapUtils.isNotEmpty(virtualSelectKeys)) { - for (int i = 0; i < selectList.size(); ++i) { - SqlIdentifier colName = (SqlIdentifier) selectList.get(i); - String colNameStr = colName.getLastName().toLowerCase(); - if (virtualSelectKeys.containsKey(colNameStr)) { - selectList.set(i, new SqlIdentifier(virtualSelectKeys.get(colNameStr), SqlParserPos.ZERO)); - } - } + final SqlNodeList selectListWithFunctionCall = new SqlNodeList(SqlParserPos.ZERO); + + int i = 0; + List columns = new LinkedList<>(); + if (originColumnList.size() > 0 && checkColumnList.size() > 0) { + final SqlNode functionCallNode1 = + new SqlBasicCall(new SqlHashCheckAggFunction(), originColumnList.toArray(), SqlParserPos.ZERO); + final SqlNode functionCallNode2 = + new SqlBasicCall(new SqlHashCheckAggFunction(), checkColumnList.toArray(), SqlParserPos.ZERO); + selectListWithFunctionCall.add(functionCallNode1); + selectListWithFunctionCall.add(functionCallNode2); + columns.add(new RelDataTypeFieldImpl("HASH1", ++i, typeFactory.createSqlType(SqlTypeName.BIGINT))); + columns.add(new RelDataTypeFieldImpl("HASH2", ++i, typeFactory.createSqlType(SqlTypeName.BIGINT))); + } + + if (selectList.size() > 0) { + final SqlNode functionCallNode3 = + new SqlBasicCall(new SqlHashCheckAggFunction(), selectList.toArray(), SqlParserPos.ZERO); + selectListWithFunctionCall.add(functionCallNode3); + columns.add(new RelDataTypeFieldImpl("HASH3", ++i, typeFactory.createSqlType(SqlTypeName.BIGINT))); } + RelDataType rowType = typeFactory.createStructType(columns); + // build target table buildTargetTable(); @@ -1577,11 +1695,6 @@ public PhyTableOperation buildSelectHashCheckForGSIChecker(TableMeta tableMeta, } } - final SqlNode functionCallNode = - new SqlBasicCall(new SqlHashCheckAggFunction(), selectList.toArray(), SqlParserPos.ZERO); - - final SqlNodeList selectListWithFunctionCall = new SqlNodeList(SqlParserPos.ZERO); - selectListWithFunctionCall.add(functionCallNode); final SqlSelect sqlSelect = new SqlSelect(SqlParserPos.ZERO, null, selectListWithFunctionCall, targetTableNode, condition, null, null, null, null, null, null); @@ -1789,6 +1902,16 @@ private PhyTableOperation buildSelectPhyTblOpTemplate(SqlNode sqlNode, RelDataTy return operation; } + // where rand() < 0.2; + private SqlNode buildRandCondition(SqlOperator operator) { + // Infer non-final operator. + SqlNode comp = new SqlBasicCall(operator, new SqlNode[] { + new SqlBasicCall(new SqlRandFunction(), sqlNode.EMPTY_ARRAY, SqlParserPos.ZERO), + new SqlDynamicParam(nextDynamicIndex++, SqlParserPos.ZERO)}, SqlParserPos.ZERO); + return comp; + + } + /** * Build condition with row expression * Caution: Row expression will lead to full table scan in MySQL, so convert to DNF. diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/UpdateDeleteIndexExecutor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/UpdateDeleteIndexExecutor.java deleted file mode 100644 index a7c5c5651..000000000 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/UpdateDeleteIndexExecutor.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.executor.gsi; - -import com.alibaba.polardbx.common.exception.TddlRuntimeException; -import com.alibaba.polardbx.common.exception.code.ErrorCode; -import com.alibaba.polardbx.common.jdbc.ParameterContext; -import com.alibaba.polardbx.executor.cursor.Cursor; -import com.alibaba.polardbx.executor.utils.ExecUtils; -import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; -import com.alibaba.polardbx.optimizer.config.table.TableMeta; -import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation; -import org.apache.calcite.rel.RelNode; -import org.apache.calcite.sql.SqlDynamicParam; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlNodeList; -import org.apache.calcite.sql.SqlUpdate; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.BiFunction; -import java.util.stream.Collectors; - -public class UpdateDeleteIndexExecutor extends IndexExecutor { - - public UpdateDeleteIndexExecutor(BiFunction, ExecutionContext, List> executeFunc, - String schemaName) { - super(executeFunc, schemaName); - } - - /** - * TODO: Gather all sql in the same group, and send them together to MySQL, - * even if they are updating different indexes. - * - * @param basePlan logical SqlUpdate or SqlDelete - * @param physicalPlans physical SqlUpdate or SqlDelete on base table - */ - public int execute(String baseTableName, SqlNode basePlan, List physicalPlans, - ExecutionContext executionContext) { - - TableMeta baseTableMeta = executionContext.getSchemaManager(schemaName).getTable(baseTableName); - List indexMetas = GlobalIndexMeta.getIndex(baseTableName, schemaName, executionContext); - - checkUpdatingShardingKey(basePlan, baseTableMeta, indexMetas); - checkUniqueKeyNull(basePlan, baseTableMeta, executionContext); - - // query the data to be updated or deleted - List selectKeys = GlobalIndexMeta.getPrimaryAndShardingKeys(baseTableMeta, indexMetas, schemaName); - PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, executionContext); - List selects = builder.buildSelect(baseTableMeta, physicalPlans, selectKeys); - - List> results = getSelectResults(selects, executionContext); - if (results.isEmpty()) { - return 0; - } - - PhyTableOperation oneOldPhysicalPlan = (PhyTableOperation) physicalPlans.get(0); - int affectRowsInBase = executeOnTable(basePlan, - baseTableMeta, - executionContext, - results, - selectKeys, - oneOldPhysicalPlan); - - // update index tables - for (TableMeta indexMeta : indexMetas) { - // Don't compare affect rows, because affect rows in index may be - // less than that of the base - executeOnTable(basePlan, indexMeta, executionContext, results, selectKeys, oneOldPhysicalPlan); - } - - return affectRowsInBase; - } - - /** - * Check if sharding keys are to be updated. - */ - private void checkUpdatingShardingKey(SqlNode basePlan, TableMeta baseTableMeta, List indexMetas) { - if (basePlan.getKind() != SqlKind.UPDATE) { - return; - } - - List allTables = new ArrayList<>(indexMetas.size() + 1); - allTables.add(baseTableMeta); - allTables.addAll(indexMetas); - - // column names are already in upper case - Map keyToTable = new HashMap<>(); - for (TableMeta tableMeta : allTables) { - List shardingKeys = GlobalIndexMeta.getShardingKeys(tableMeta, schemaName); - for (String key : shardingKeys) { - keyToTable.putIfAbsent(key, tableMeta.getTableName()); - } - } - - SqlNodeList columnList = ((SqlUpdate) basePlan).getTargetColumnList(); - for (SqlNode column : columnList) { - String columnName = ((SqlIdentifier) column).getLastName().toUpperCase(); - String tableName = keyToTable.get(columnName); - if (tableName != null) { - throw new TddlRuntimeException(ErrorCode.ERR_MODIFY_SHARD_COLUMN, columnName, tableName); - } - } - } - - /** - * Check if unique key is NULL. - */ - private void checkUniqueKeyNull(SqlNode basePlan, TableMeta tableMeta, ExecutionContext executionContext) { - if (basePlan.getKind() != SqlKind.UPDATE) { - return; - } - - List uniqueKeys = - GlobalIndexMeta - .getUniqueKeyColumnList(tableMeta.getTableName(), tableMeta.getSchemaName(), false, executionContext); - if (uniqueKeys.isEmpty()) { - return; - } - - // uniqueKeys are already in upper case - SqlUpdate sqlUpdate = (SqlUpdate) basePlan; - List columnList = sqlUpdate.getTargetColumnList() - .getList() - .stream() - .map(sqlNode -> ((SqlIdentifier) sqlNode).getLastName().toUpperCase()) - .collect(Collectors.toList()); - List uniqueKeyIndexes = uniqueKeys.stream().map(columnList::indexOf).collect(Collectors.toList()); - - SqlNodeList expressionList = sqlUpdate.getSourceExpressionList(); - Map params = executionContext.getParams().getCurrentParameter(); - for (int i = 0; i < uniqueKeyIndexes.size(); i++) { - int index = uniqueKeyIndexes.get(i); - if (index < 0) { - continue; - } - - SqlNode expression = expressionList.get(index); - boolean isNull = false; - if (expression instanceof SqlDynamicParam) { - int dynamicParamIndex = ((SqlDynamicParam) expression).getIndex(); - Object object = params.get(dynamicParamIndex + 1).getValue(); - if (object == null) { - isNull = true; - } - } else if (expression instanceof SqlLiteral) { - Object object = ((SqlLiteral) expression).getValue(); - if (object == null) { - isNull = true; - } - } else { - // what if function? - } - - if (isNull) { - throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_INSERT_UNIQUE_KEY_NULL, - uniqueKeys.get(i)); - } - } - } - - /** - * Execute UPDATE or DELETE on one table. - * - * @param basePlan logical plan, containing all rows - * @param tableMeta base table or index table - * @param selectedResults data that to be updated or deleted - * @param selectKeys columns corresponding to selectedResults - * @param oneOldPhysicalPlan any physical plan, used to create new ones - * @return affected rows - */ - private int executeOnTable(SqlNode basePlan, TableMeta tableMeta, ExecutionContext executionContext, - List> selectedResults, List selectKeys, - PhyTableOperation oneOldPhysicalPlan) { - PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, executionContext); - - List phyTableOperations; - if (basePlan.getKind() == SqlKind.UPDATE) { - if (tableMeta.isGsi() && !GlobalIndexMeta.canWrite(executionContext, tableMeta)) { - if (GlobalIndexMeta.canDelete(executionContext, tableMeta)) { - // Delete only. - phyTableOperations = builder.buildDelete(tableMeta, - selectedResults, - selectKeys, - oneOldPhysicalPlan); - } else { - return 0; // Status which update is not allowed. - } - } else { - phyTableOperations = builder.buildUpdate((SqlUpdate) basePlan, - tableMeta, - selectedResults, - selectKeys, - oneOldPhysicalPlan); - } - } else { - if (tableMeta.isGsi() && !GlobalIndexMeta.canDelete(executionContext, tableMeta)) { - return 0; // Status which deletion is not allowed. - } - - phyTableOperations = builder.buildDelete(tableMeta, - selectedResults, - selectKeys, - oneOldPhysicalPlan); - } - - // If none of the SET columns in the UPDATE are in the index, pass - if (!phyTableOperations.isEmpty()) { - List cursors = executeFunc.apply(phyTableOperations, executionContext); - return ExecUtils.getAffectRowsByCursors(cursors, false); - } else { - return 0; - } - } -} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/GsiExtractor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/GsiExtractor.java index 6e96efcc0..df40e30a9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/GsiExtractor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/GsiExtractor.java @@ -56,8 +56,10 @@ public Map> getSourcePhyTables() { public static Extractor create(String schemaName, String sourceTableName, String targetTableName, long batchSize, long speedMin, long speedLimit, long parallelism, boolean useBinary, - List modifyStringColumns, ExecutionContext ec) { - ExtractorInfo info = Extractor.buildExtractorInfo(ec, schemaName, sourceTableName, targetTableName, true); + List modifyStringColumns, boolean onlineModifyColumn, + ExecutionContext ec) { + ExtractorInfo info = Extractor.buildExtractorInfo(ec, schemaName, sourceTableName, targetTableName, true, false, + onlineModifyColumn); final PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, useBinary, modifyStringColumns, ec); return new GsiExtractor(schemaName, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/GsiLoader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/GsiLoader.java index ab526dd88..fbd42289b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/GsiLoader.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/GsiLoader.java @@ -71,7 +71,8 @@ private GsiLoader(String schemaName, String tableName, SqlInsert insert, SqlInse public static Loader create(String schemaName, String primaryTable, String indexTable, BiFunction, ExecutionContext, List> executeFunc, - boolean useHint, boolean canUseReturning, ExecutionContext ec) { + boolean useHint, boolean canUseReturning, boolean onlineModifyColumn, + ExecutionContext ec) { final OptimizerContext optimizerContext = OptimizerContext.getContext(schemaName); // Construct target table @@ -83,8 +84,8 @@ public static Loader create(String schemaName, String primaryTable, String index final SqlNodeList targetColumnList = new SqlNodeList( indexTableMeta.getAllColumns() .stream() - .filter(columnMeta -> (!columnMeta.isGeneratedColumn() && !(columnMeta.getMappingName() != null - && columnMeta.getMappingName().isEmpty()))) + .filter(columnMeta -> (!columnMeta.isGeneratedColumn() && !(onlineModifyColumn + && columnMeta.getMappingName() != null && columnMeta.getMappingName().isEmpty()))) .map(columnMeta -> new SqlIdentifier(columnMeta.getName(), SqlParserPos.ZERO)) .collect(Collectors.toList()), SqlParserPos.ZERO); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/OmcMirrorCopyExtractor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/OmcMirrorCopyExtractor.java index 68ea8c674..66566c415 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/OmcMirrorCopyExtractor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/backfill/OmcMirrorCopyExtractor.java @@ -110,10 +110,11 @@ public static OmcMirrorCopyExtractor create(String schemaName, String sourceTabl long batchSize, long speedMin, long speedLimit, long parallelism, Map tableNameMapping, Map> sourcePhyTables, - boolean useChangeSet, boolean useBinary, + boolean useChangeSet, boolean useBinary, boolean onlineModifyColumn, ExecutionContext ec) { - Extractor.ExtractorInfo - info = Extractor.buildExtractorInfo(ec, schemaName, sourceTableName, targetTableName, true); + Extractor.ExtractorInfo info = + Extractor.buildExtractorInfo(ec, schemaName, sourceTableName, targetTableName, true, false, + onlineModifyColumn); final PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, useBinary, ec); final TableMeta tableMeta = info.getSourceTableMeta(); @@ -237,7 +238,7 @@ protected void foreachPhyTableBatch(String dbIndex, String phyTable, throttle.feedback(new com.alibaba.polardbx.executor.backfill.Throttle.FeedbackStats( System.currentTimeMillis() - start, start, currentSuccessRowCount.get())); } - DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set((long) throttle.getActualRateLastCycle()); +// DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set((long) throttle.getActualRateLastCycle()); if (rateLimiter != null) { // Limit rate. @@ -271,7 +272,7 @@ protected void foreachPhyTableBatch(String dbIndex, String phyTable, dbIndex, phyTable, successRowCount, ec, rangeBackfillStartTime, lastBatch, backfillObjects); } while (!finished.get()); - DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set(0); +// DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set(0); reporter.addBackfillCount(successRowCount); SQLRecorderLogger.ddlLogger.warn(MessageFormat.format("[{0}] Last backfill row for {1}[{2}][{3}]: {4}", diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/corrector/GsiChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/corrector/GsiChecker.java index b63575615..b8ae96a4f 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/corrector/GsiChecker.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/corrector/GsiChecker.java @@ -103,12 +103,12 @@ public static Checker create(String schemaName, String tableName, String indexNa } final TableMeta baseTableMeta = sm.getTable(tableName); - if (null == baseTableMeta || !baseTableMeta.withGsi() || !indexTableMeta.isGsi() - || !baseTableMeta.getGsiTableMetaBean().indexMap.containsKey(indexName)) { + if (null == baseTableMeta) { throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_CHECKER, "Incorrect GSI relationship."); } - Extractor.ExtractorInfo info = Extractor.buildExtractorInfo(ec, schemaName, tableName, indexName, false, true); + Extractor.ExtractorInfo info = + Extractor.buildExtractorInfo(ec, schemaName, tableName, indexName, false, true, false); final PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, params.isUseBinary(), ec); final Pair selectWithIn = builder diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/fastchecker/GsiFastChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/fastchecker/GsiFastChecker.java index 39a39a50a..1441a3e81 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/fastchecker/GsiFastChecker.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/fastchecker/GsiFastChecker.java @@ -18,7 +18,6 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; -import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.executor.fastchecker.FastChecker; import com.alibaba.polardbx.executor.gsi.GsiUtils; import com.alibaba.polardbx.executor.gsi.PhysicalPlanBuilder; @@ -56,9 +55,7 @@ public GsiFastChecker(String schemaName, String srcLogicalTableName, String dstL planIdleSelectDst, planSelectSampleSrc, planSelectSampleDst); } - public static FastChecker create(String schemaName, String tableName, String indexName, - Map srcColumnMap, Map tarColumnMap, - ExecutionContext ec) { + public static FastChecker create(String schemaName, String tableName, String indexName, ExecutionContext ec) { // Build select plan final SchemaManager sm = ec.getSchemaManager(schemaName); final TableMeta indexTableMeta = sm.getTable(indexName); @@ -71,29 +68,17 @@ public static FastChecker create(String schemaName, String tableName, String ind } final TableMeta baseTableMeta = sm.getTable(tableName); - if (null == baseTableMeta || !baseTableMeta.withGsi() || !indexTableMeta.isGsi() - || !baseTableMeta.getGsiTableMetaBean().indexMap.containsKey(indexName)) { + if (null == baseTableMeta) { throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_CHECKER, "Incorrect GSI relationship."); } - // for rebuild table - final List indexColumns = new ArrayList<>(); - final List baseTableColumns = new ArrayList<>(); - for (ColumnMeta columnMeta : indexTableMeta.getAllColumns()) { - if (columnMeta.getMappingName() != null) { - if (!columnMeta.getMappingName().isEmpty()) { - baseTableColumns.add(columnMeta.getMappingName()); - indexColumns.add(columnMeta.getName()); - } - } else { - baseTableColumns.add(columnMeta.getName()); - indexColumns.add(columnMeta.getName()); - } - } + final List indexColumns = + indexTableMeta.getAllColumns().stream().map(ColumnMeta::getName).collect(Collectors.toList()); + final List baseTableColumns = new ArrayList<>(indexColumns); // 重要:构造planSelectSampleSrc 和 planSelectSampleDst时,传入的主键必须按原本的主键顺序! - final List baseTablePks = FastChecker.getorderedPrimaryKeys(baseTableMeta); - final List indexTablePks = FastChecker.getorderedPrimaryKeys(indexTableMeta); + final List baseTablePks = FastChecker.getOrderedPrimaryKeys(baseTableMeta); + final List indexTablePks = FastChecker.getOrderedPrimaryKeys(indexTableMeta); final Map> srcPhyDbAndTables = GsiUtils.getPhyTables(schemaName, tableName); final Map> dstPhyDbAndTables = GsiUtils.getPhyTables(schemaName, indexName); @@ -102,14 +87,10 @@ public static FastChecker create(String schemaName, String tableName, String ind return new GsiFastChecker(schemaName, tableName, indexName, srcPhyDbAndTables, dstPhyDbAndTables, baseTableColumns, indexColumns, baseTablePks, indexTablePks, - builder.buildSelectHashCheckForGSIChecker(baseTableMeta, baseTableColumns, srcColumnMap, baseTablePks, - false, false), - builder.buildSelectHashCheckForGSIChecker(baseTableMeta, baseTableColumns, srcColumnMap, baseTablePks, - false, true), - builder.buildSelectHashCheckForGSIChecker(baseTableMeta, baseTableColumns, srcColumnMap, baseTablePks, - true, false), - builder.buildSelectHashCheckForGSIChecker(baseTableMeta, baseTableColumns, srcColumnMap, baseTablePks, - true, true), + builder.buildSelectHashCheckForChecker(baseTableMeta, baseTableColumns, baseTablePks, false, false), + builder.buildSelectHashCheckForChecker(baseTableMeta, baseTableColumns, baseTablePks, false, true), + builder.buildSelectHashCheckForChecker(baseTableMeta, baseTableColumns, baseTablePks, true, false), + builder.buildSelectHashCheckForChecker(baseTableMeta, baseTableColumns, baseTablePks, true, true), builder.buildSelectHashCheckForChecker(indexTableMeta, indexColumns, indexTablePks, false, false), builder.buildSelectHashCheckForChecker(indexTableMeta, indexColumns, indexTablePks, false, true), diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/fastchecker/OmcFastChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/fastchecker/OmcFastChecker.java new file mode 100644 index 000000000..4cd7eeab0 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/fastchecker/OmcFastChecker.java @@ -0,0 +1,519 @@ +package com.alibaba.polardbx.executor.gsi.fastchecker; + +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.logger.MDC; +import com.alibaba.polardbx.executor.ExecutorHelper; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.ddl.newengine.cross.CrossEngineValidator; +import com.alibaba.polardbx.executor.ddl.workqueue.FastCheckerThreadPool; +import com.alibaba.polardbx.executor.fastchecker.FastChecker; +import com.alibaba.polardbx.executor.gsi.GsiUtils; +import com.alibaba.polardbx.executor.gsi.PhysicalPlanBuilder; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation; +import com.alibaba.polardbx.optimizer.core.row.Row; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import lombok.Data; +import org.apache.calcite.util.Pair; +import org.apache.commons.collections.MapUtils; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.FutureTask; +import java.util.stream.Collectors; + +import static java.lang.Math.max; + +/** + * @author wumu + */ +public class OmcFastChecker extends FastChecker { + private static final Logger LOGGER = LoggerFactory.getLogger(FastChecker.class); + + public OmcFastChecker(String schemaName, String srcLogicalTableName, String dstLogicalTableName, + Map> srcPhyDbAndTables, Map> dstPhyDbAndTables, + List srcColumns, List dstColumns, List srcPks, List dstPks, + PhyTableOperation planSelectHashCheckSrc, + PhyTableOperation planSelectHashCheckWithUpperBoundSrc, + PhyTableOperation planSelectHashCheckWithLowerBoundSrc, + PhyTableOperation planSelectHashCheckWithLowerUpperBoundSrc, + PhyTableOperation planSelectHashCheckDst, + PhyTableOperation planSelectHashCheckWithUpperBoundDst, + PhyTableOperation planSelectHashCheckWithLowerBoundDst, + PhyTableOperation planSelectHashCheckWithLowerUpperBoundDst, + PhyTableOperation planIdleSelectSrc, PhyTableOperation planIdleSelectDst, + PhyTableOperation planSelectSampleSrc, PhyTableOperation planSelectSampleDst) { + super(schemaName, schemaName, srcLogicalTableName, dstLogicalTableName, srcPhyDbAndTables, + dstPhyDbAndTables, srcColumns, dstColumns, srcPks, dstPks, planSelectHashCheckSrc, + planSelectHashCheckWithUpperBoundSrc, planSelectHashCheckWithLowerBoundSrc, + planSelectHashCheckWithLowerUpperBoundSrc, planSelectHashCheckDst, planSelectHashCheckWithUpperBoundDst, + planSelectHashCheckWithLowerBoundDst, planSelectHashCheckWithLowerUpperBoundDst, planIdleSelectSrc, + planIdleSelectDst, planSelectSampleSrc, planSelectSampleDst); + } + + public static FastChecker create(String schemaName, String tableName, String indexName, + Map srcColumnMap, Map dstColumnMap, + ExecutionContext ec) { + // Build select plan + final SchemaManager sm = ec.getSchemaManager(schemaName); + final TableMeta indexTableMeta = sm.getTable(indexName); + if (null == indexTableMeta || !indexTableMeta.isGsi()) { + throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_CHECKER, "Incorrect GSI table."); + } + + if (null == tableName) { + tableName = indexTableMeta.getGsiTableMetaBean().gsiMetaBean.tableName; + } + final TableMeta baseTableMeta = sm.getTable(tableName); + + if (null == baseTableMeta || !baseTableMeta.withGsi() || !indexTableMeta.isGsi() + || !baseTableMeta.getGsiTableMetaBean().indexMap.containsKey(indexName)) { + throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_CHECKER, "Incorrect GSI relationship."); + } + + // for rebuild table + final List indexColumns = new ArrayList<>(); + final List baseTableColumns = new ArrayList<>(); + + final List commonColumns = new ArrayList<>(); + final List baseTableOriginColumns = new ArrayList<>(); + final List baseTableCheckColumns = new ArrayList<>(); + final List indexOriginColumns = new ArrayList<>(); + final List indexCheckColumns = new ArrayList<>(); + + for (ColumnMeta columnMeta : indexTableMeta.getAllColumns()) { + String baseTableColumnName = null; + if (columnMeta.getMappingName() != null) { + if (!columnMeta.getMappingName().isEmpty()) { + baseTableColumnName = columnMeta.getMappingName().toLowerCase(); + } + } else { + baseTableColumnName = columnMeta.getName().toLowerCase(); + } + + if (baseTableColumnName != null) { + String indexColumnName = columnMeta.getName().toLowerCase(); + baseTableColumns.add(baseTableColumnName); + indexColumns.add(indexColumnName); + + if (MapUtils.isNotEmpty(srcColumnMap) && srcColumnMap.containsKey(baseTableColumnName)) { + baseTableOriginColumns.add(baseTableColumnName); + baseTableCheckColumns.add(srcColumnMap.get(baseTableColumnName)); + + assert (MapUtils.isNotEmpty(dstColumnMap) && dstColumnMap.containsKey(indexColumnName)); + indexOriginColumns.add(indexColumnName); + indexCheckColumns.add(dstColumnMap.get(indexColumnName)); + } else { + commonColumns.add(baseTableColumnName); + } + } + } + + // 重要:构造planSelectSampleSrc 和 planSelectSampleDst时,传入的主键必须按原本的主键顺序! + final List baseTablePks = FastChecker.getOrderedPrimaryKeys(baseTableMeta); + final List indexTablePks = FastChecker.getOrderedPrimaryKeys(indexTableMeta); + + final Map> srcPhyDbAndTables = GsiUtils.getPhyTables(schemaName, tableName); + final Map> dstPhyDbAndTables = GsiUtils.getPhyTables(schemaName, indexName); + + final PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, ec); + + return new OmcFastChecker(schemaName, tableName, indexName, srcPhyDbAndTables, dstPhyDbAndTables, + baseTableColumns, indexColumns, baseTablePks, indexTablePks, + builder.buildSelectHashCheckForGSIChecker(baseTableMeta, commonColumns, baseTableOriginColumns, + baseTableCheckColumns, baseTablePks, false, false), + builder.buildSelectHashCheckForGSIChecker(baseTableMeta, commonColumns, baseTableOriginColumns, + baseTableCheckColumns, baseTablePks, false, true), + builder.buildSelectHashCheckForGSIChecker(baseTableMeta, commonColumns, baseTableOriginColumns, + baseTableCheckColumns, baseTablePks, true, false), + builder.buildSelectHashCheckForGSIChecker(baseTableMeta, commonColumns, baseTableOriginColumns, + baseTableCheckColumns, baseTablePks, true, true), + + builder.buildSelectHashCheckForGSIChecker(indexTableMeta, commonColumns, indexOriginColumns, + indexCheckColumns, indexTablePks, false, false), + builder.buildSelectHashCheckForGSIChecker(indexTableMeta, commonColumns, indexOriginColumns, + indexCheckColumns, indexTablePks, false, true), + builder.buildSelectHashCheckForGSIChecker(indexTableMeta, commonColumns, indexOriginColumns, + indexCheckColumns, indexTablePks, true, false), + builder.buildSelectHashCheckForGSIChecker(indexTableMeta, commonColumns, indexOriginColumns, + indexCheckColumns, indexTablePks, true, true), + + builder.buildIdleSelectForChecker(baseTableMeta, baseTableColumns), + builder.buildIdleSelectForChecker(indexTableMeta, indexColumns), + + builder.buildSqlSelectForSample(baseTableMeta, baseTablePks), + builder.buildSqlSelectForSample(indexTableMeta, indexTablePks)); + } + + @Data + static class HashCheckResult { + public Long commonHash; + public Long originColumnHash; + public Long checkColumnHash; + } + + @Override + protected boolean parallelCheck(Map> srcDbAndTb, + Map> dstDbAndTb, + ExecutionContext baseEc, long batchSize) { + Set allGroups = new TreeSet<>(String::compareToIgnoreCase); + allGroups.addAll(srcDbAndTb.keySet()); + allGroups.addAll(dstDbAndTb.keySet()); + + // + Map mapping = queryStorageInstIdByPhyGroup(allGroups); + + Map>>> allFutureTasksByGroup = + new TreeMap<>(String::compareToIgnoreCase); + + int srcTableTaskCount = 0, dstTableTaskCount = 0; + final Map mdcContext = MDC.getCopyOfContextMap(); + + for (Map.Entry> entry : srcDbAndTb.entrySet()) { + String srcDb = entry.getKey(); + for (String srcTb : entry.getValue()) { + FutureTask> task = new FutureTask<>( + () -> { + MDC.setContextMap(mdcContext); + return hashCheckForSinglePhyTable(srcDb, srcTb, baseEc, true, batchSize); + } + ); + + allFutureTasksByGroup.putIfAbsent(srcDb, new ArrayList<>()); + allFutureTasksByGroup.get(srcDb).add(task); + srcTableTaskCount++; + } + } + + for (Map.Entry> entry : dstDbAndTb.entrySet()) { + String dstDb = entry.getKey(); + for (String dstTb : entry.getValue()) { + FutureTask> task = new FutureTask<>( + () -> { + MDC.setContextMap(mdcContext); + return hashCheckForSinglePhyTable(dstDb, dstTb, baseEc, false, batchSize); + } + ); + + allFutureTasksByGroup.putIfAbsent(dstDb, new ArrayList<>()); + allFutureTasksByGroup.get(dstDb).add(task); + dstTableTaskCount++; + } + } + + LOGGER.info( + MessageFormat.format( + "[{0}] FastChecker try to submit {1} tasks to fastChecker threadPool", + baseEc.getTraceId(), + srcTableTaskCount + dstTableTaskCount + ) + ); + + //update task info + this.phyTaskSum.set(srcTableTaskCount + dstTableTaskCount); + + FastCheckerThreadPool.getInstance().increaseCheckTaskInfo( + baseEc.getDdlJobId(), + this.phyTaskSum.get(), + 0 + ); + + //submit tasks to fastChecker threadPool + FastCheckerThreadPool threadPool = FastCheckerThreadPool.getInstance(); + List> allTasksByStorageInstId = new ArrayList<>(); + for (Map.Entry>>> entry : allFutureTasksByGroup.entrySet()) { + String groupName = entry.getKey(); + if (!mapping.containsKey(groupName)) { + throw new TddlRuntimeException( + ErrorCode.ERR_FAST_CHECKER, + String.format("FastChecker failed to get group-storageInstId mapping, group [%s]", groupName) + ); + } + String storageInstId = mapping.get(groupName); + for (FutureTask> task : entry.getValue()) { + allTasksByStorageInstId.add(Pair.of(storageInstId, task)); + } + } + + threadPool.submitTasks(allTasksByStorageInstId); + + List> result = new ArrayList<>(); + List>> allFutureTasks = allTasksByStorageInstId + .stream() + .map(Pair::getValue) + .map(task -> (FutureTask>) task) + .collect(Collectors.toList()); + + for (FutureTask> futureTask : allFutureTasks) { + try { + result.add(futureTask.get()); + } catch (Exception e) { + for (FutureTask> taskToBeCancel : allFutureTasks) { + try { + taskToBeCancel.cancel(true); + } catch (Exception ignore) { + } + } + if (e.getMessage().toLowerCase().contains("XResult stream fetch result timeout".toLowerCase())) { + throw new TddlNestableRuntimeException("FastChecker fetch phy table digest timeout", e); + } else { + throw new TddlNestableRuntimeException(e); + } + } + } + + List srcResult = + result.stream().filter(p -> p != null && p.getKey() != null && p.getValue()).map(Pair::getKey) + .collect(Collectors.toList()); + List dstResult = + result.stream().filter(p -> p != null && p.getKey() != null && !p.getValue()).map(Pair::getKey) + .collect(Collectors.toList()); + + return srcTableTaskCount == result.stream().filter(Objects::nonNull).filter(Pair::getValue).count() + && dstTableTaskCount == result.stream().filter(Objects::nonNull).filter(x -> !x.getValue()).count() + && compare(srcResult, dstResult); + } + + private Pair hashCheckForSinglePhyTable(String phyDbName, String phyTable, + ExecutionContext baseEc, + boolean isSrcTableTask, long maxBatchRows) { + String schema = isSrcTableTask ? srcSchemaName : dstSchemaName; + long tableRowsCount = getTableRowsCount(schema, phyDbName, phyTable); + + //get phy table's avgRowSize + long tableAvgRowLength = getTableAvgRowSize(schema, phyDbName, phyTable); + long fastCheckerMaxBatchFileSize = + baseEc.getParamManager().getLong(ConnectionParams.FASTCHECKER_BATCH_FILE_SIZE); + + boolean needBatchCheck = false; + if (tableRowsCount * tableAvgRowLength > fastCheckerMaxBatchFileSize || tableRowsCount > maxBatchRows) { + needBatchCheck = true; + } + + long startTime = System.currentTimeMillis(); + /** + * if table size exceed batch size, we will calculate digest by batch. + * otherwise, we will straightly calculate the whole phy table's digest + * */ + + boolean failedToSplitBatch = false; + HashCheckResult hashResult = null; + + if (!whetherCanSplitIntoBatch(baseEc, isSrcTableTask)) { + needBatchCheck = false; + } + + if (needBatchCheck) { + long finalBatchRows = maxBatchRows; + if (tableRowsCount * tableAvgRowLength > fastCheckerMaxBatchFileSize) { + tableAvgRowLength = max(1, tableAvgRowLength); + finalBatchRows = fastCheckerMaxBatchFileSize / tableAvgRowLength; + } + if (finalBatchRows > maxBatchRows) { + finalBatchRows = maxBatchRows; + } + + List> batchBoundList = + splitPhyTableIntoBatch(baseEc, phyDbName, phyTable, tableRowsCount, finalBatchRows, isSrcTableTask); + if (!batchBoundList.isEmpty()) { + SQLRecorderLogger.ddlLogger.info(MessageFormat.format( + "[{0}] FastChecker start hash phy for {1}[{2}][{3}], and phy table is divided into {4} batches", + baseEc.getTraceId(), phyDbName, phyTable, isSrcTableTask ? "src" : "dst", + batchBoundList.size() + 1)); + + hashResult = + getPhyTableHashCheckResByBatch(phyDbName, phyTable, baseEc, isSrcTableTask, batchBoundList); + } else { + failedToSplitBatch = true; + } + } + + if (!needBatchCheck || failedToSplitBatch) { + SQLRecorderLogger.ddlLogger.info(MessageFormat.format( + "[{0}] FastChecker start hash phy for {1}[{2}][{3}], and phy table is hashed by full scan", + baseEc.getTraceId(), phyDbName, phyTable, isSrcTableTask ? "src" : "dst")); + + hashResult = getPhyTableHashCheckResByFullScan(phyDbName, phyTable, baseEc, isSrcTableTask); + } + + SQLRecorderLogger.ddlLogger.info(MessageFormat.format( + "[{0}] FastChecker finish phy hash for {1}[{2}][{3}], time use[{4}], table hash value[{5}]", + baseEc.getTraceId(), phyDbName, phyTable, isSrcTableTask ? "src" : "dst", + (System.currentTimeMillis() - startTime) / 1000.0, hashResult == null ? "null" : hashResult)); + + this.phyTaskFinished.incrementAndGet(); + + FastCheckerThreadPool.getInstance().increaseCheckTaskInfo( + baseEc.getDdlJobId(), + 0, + 1 + ); + + return Pair.of(hashResult, isSrcTableTask); + } + + private HashCheckResult getPhyTableHashCheckResByBatch(String phyDbName, String phyTable, ExecutionContext baseEc, + boolean isSrcTableTask, + List> batchBoundList) { + if (batchBoundList.isEmpty()) { + return null; + } + + List hashResults = new ArrayList<>(); + List hashCheckPlans = genHashCheckPlans(phyDbName, phyTable, isSrcTableTask, batchBoundList); + + // execute + for (PhyTableOperation phyPlan : hashCheckPlans) { + HashCheckResult batchHashResult = executeHashCheckPlan(phyPlan, baseEc); + if (batchHashResult != null) { + hashResults.add(batchHashResult); + } + if (CrossEngineValidator.isJobInterrupted(baseEc) || Thread.currentThread().isInterrupted()) { + long jobId = baseEc.getDdlJobId(); + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + "The job '" + jobId + "' has been cancelled"); + } + } + + if (hashResults.isEmpty()) { + return null; + } + + if (hashResults.size() == 1) { + return hashResults.get(0); + } + + final HashCalculator commonCalculator = new HashCalculator(); + final HashCalculator originColumnCalculator = new HashCalculator(); + final HashCalculator checkColumnCalculator = new HashCalculator(); + for (HashCheckResult hashResult : hashResults) { + commonCalculator.calculate(hashResult.commonHash); + originColumnCalculator.calculate(hashResult.originColumnHash); + checkColumnCalculator.calculate(hashResult.checkColumnHash); + } + + HashCheckResult ret = new HashCheckResult(); + ret.commonHash = commonCalculator.getHashVal(); + ret.originColumnHash = originColumnCalculator.getHashVal(); + ret.checkColumnHash = checkColumnCalculator.getHashVal(); + return ret; + } + + private HashCheckResult getPhyTableHashCheckResByFullScan(String phyDbName, String phyTable, + ExecutionContext baseEc, + boolean isSrcTableTask) { + if (CrossEngineValidator.isJobInterrupted(baseEc) || Thread.currentThread().isInterrupted()) { + long jobId = baseEc.getDdlJobId(); + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + "The job '" + jobId + "' has been cancelled"); + } + + PhyTableOperation plan = genHashCheckPlan(phyDbName, phyTable, baseEc, isSrcTableTask); + + return executeHashCheckPlan(plan, baseEc); + } + + private HashCheckResult executeHashCheckPlan(PhyTableOperation plan, ExecutionContext ec) { + Cursor cursor = null; + HashCheckResult result = null; + try { + cursor = ExecutorHelper.executeByCursor(plan, ec, false); + Row row; + if (cursor != null && (row = cursor.next()) != null) { + result = new HashCheckResult(); + if (row.getColNum() == 1) { + result.commonHash = (Long) row.getObject(0); + } else if (row.getColNum() == 2) { + result.originColumnHash = (Long) row.getObject(0); + result.checkColumnHash = (Long) row.getObject(1); + } else if (row.getColNum() == 3) { + result.originColumnHash = (Long) row.getObject(0); + result.checkColumnHash = (Long) row.getObject(1); + result.commonHash = (Long) row.getObject(2); + } + + while (cursor.next() != null) { + //do nothing + } + } + } finally { + if (cursor != null) { + cursor.close(new ArrayList<>()); + } + } + return result; + } + + private boolean compare(List src, List dst) { + final HashCalculator srcCommonCalculator = new HashCalculator(); + final HashCalculator srcOriginColumnCalculator = new HashCalculator(); + final HashCalculator srcCheckColumnCalculator = new HashCalculator(); + final HashCalculator dstCommonCalculator = new HashCalculator(); + final HashCalculator dstOriginColumnCalculator = new HashCalculator(); + final HashCalculator dstCheckColumnCalculator = new HashCalculator(); + + // 1. check common column hash value + src.forEach(elem -> srcCommonCalculator.calculate(elem.commonHash)); + dst.forEach(elem -> dstCommonCalculator.calculate(elem.commonHash)); + + if (!srcCommonCalculator.getHashVal().equals(dstCommonCalculator.getHashVal())) { + LOGGER.info( + MessageFormat.format( + "FastChecker check common column failed, schemaName: {0}, tableName: {1}, indexName: {2}", + srcSchemaName, + srcLogicalTableName, + dstLogicalTableName + ) + ); + return false; + } + + src.forEach(elem -> srcCheckColumnCalculator.calculate(elem.checkColumnHash)); + dst.forEach(elem -> dstOriginColumnCalculator.calculate(elem.originColumnHash)); + + if (srcCheckColumnCalculator.getHashVal().equals(dstOriginColumnCalculator.getHashVal())) { + return true; + } else { + LOGGER.info( + MessageFormat.format( + "FastChecker check src virtual column failed, schemaName: {0}, tableName: {1}, indexName: {2}", + srcSchemaName, + srcLogicalTableName, + dstLogicalTableName + ) + ); + } + + src.forEach(elem -> srcOriginColumnCalculator.calculate(elem.originColumnHash)); + dst.forEach(elem -> dstCheckColumnCalculator.calculate(elem.checkColumnHash)); + + if (srcOriginColumnCalculator.getHashVal().equals(dstCheckColumnCalculator.getHashVal())) { + return true; + } else { + LOGGER.info( + MessageFormat.format( + "FastChecker check dst virtual column failed, schemaName: {0}, tableName: {1}, indexName: {2}", + srcSchemaName, + srcLogicalTableName, + dstLogicalTableName + ) + ); + return false; + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/utils/Transformer.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/utils/Transformer.java index 40c3b3295..70a9ab01f 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/utils/Transformer.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/gsi/utils/Transformer.java @@ -20,11 +20,15 @@ import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.google.common.base.Preconditions; +import com.google.common.io.BaseEncoding; +import com.mysql.jdbc.StringUtils; +import com.mysql.jdbc.ZeroDate; +import com.mysql.jdbc.ZeroTime; +import com.mysql.jdbc.ZeroTimestamp; +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.jdbc.ParameterMethod; -import com.alibaba.polardbx.common.jdbc.ZeroDate; -import com.alibaba.polardbx.common.jdbc.ZeroTime; -import com.alibaba.polardbx.common.jdbc.ZeroTimestamp; import com.alibaba.polardbx.common.properties.PropUtil; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; @@ -37,15 +41,17 @@ import com.google.common.base.Preconditions; import com.google.common.io.BaseEncoding; import io.airlift.slice.Slice; -import org.apache.commons.lang.StringUtils; import java.math.BigInteger; import java.nio.charset.Charset; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeMap; import java.util.function.BiFunction; /** @@ -179,10 +185,104 @@ public static List> buildBatchParam(Cursor cursor return batchParams; } + public static List> buildBatchParam(List columnMetas, + ResultSet resultSet, boolean useBinary, + Set notConvertColumns) + throws SQLException { + final List> batchParams = new ArrayList<>(); + + int columnSize = columnMetas.size(); + while (resultSet.next()) { + final TreeMap params = new TreeMap<>(); + for (int i = 0; i < columnSize; i++) { + String colName = columnMetas.get(i).getName(); + DataType dataType = columnMetas.get(i).getDataType(); + boolean canConvert = useBinary && (notConvertColumns == null || !notConvertColumns.contains(colName)); + + final ParameterContext parameterContext = + buildColumnParam(resultSet, i + 1, dataType, canConvert); + + params.put(i + 1, parameterContext); + } + batchParams.add(params); + } + return batchParams; + } + + public static ParameterContext buildColumnParam(ResultSet resultSet, int i, DataType columnType, + boolean strToBinary) throws SQLException { + ParameterMethod method = ParameterMethod.setObject1; + Object value = resultSet.getObject(i); + try { + if (value instanceof ZeroDate || value instanceof ZeroTimestamp || value instanceof ZeroTime + || value instanceof Decimal) { + // 针对 0000-00-00 的时间类型 setObject 会失败,setString 没问题 + value = value.toString(); + method = ParameterMethod.setString; + } else if (value instanceof Slice) { + value = ((Slice) value).toStringUtf8(); + method = ParameterMethod.setString; + } else if (value instanceof EnumValue) { + value = ((EnumValue) value).value; + method = ParameterMethod.setString; + } else if (value != null) { + if (DataTypeUtil.anyMatchSemantically(columnType, DataTypes.DateType, DataTypes.TimestampType, + DataTypes.DatetimeType, DataTypes.TimeType, DataTypes.YearType)) { + // 针对 0000-00-00 01:01:01.12 的时间类型或 0000 的year 类型, + // getObject 返回的结果错误,getBytes 后转为 String 没问题 + value = new String(resultSet.getBytes(i)); + method = ParameterMethod.setString; + } else if (DataTypeUtil.anyMatchSemantically(columnType, DataTypes.BitType, DataTypes.BigBitType)) { + // 使用表示范围更大的类型,规避序列化/反序列化上下界时丢失数据 + value = new BigInteger(resultSet.getString(i)); + method = ParameterMethod.setBit; + } else if (DataTypeUtil.anyMatchSemantically(columnType, DataTypes.FloatType, DataTypes.DoubleType)) { + // 使用表示范围更大的类型,规避序列化/反序列化上下界时丢失数据 + value = resultSet.getDouble(i); + method = ParameterMethod.setDouble; + } else if (DataTypeUtil.anyMatchSemantically(columnType, DataTypes.ULongType)) { + // BIGINT(64) UNSIGNED + value = resultSet.getString(i); + method = ParameterMethod.setString; + } else if (DataTypeUtil + .anyMatchSemantically(columnType, DataTypes.BinaryType, DataTypes.BlobType, + DataTypes.BinaryStringType)) { + // 使用 setBytes 标记,序列化时使用16进制字符串 + value = resultSet.getBytes(i); + method = ParameterMethod.setBytes; + } else if (strToBinary && DataTypeUtil.isStringType(columnType)) { + // 字符串类型,直接select binary得到二进制数,直接setBytes,避免字符集转换带来的损失 + value = resultSet.getBytes(i); + method = ParameterMethod.setBytes; + } + } + } catch (TddlNestableRuntimeException e) { + SQLRecorderLogger.ddlLogger.warn("Convert data type failed, use getBytes. message: " + e.getMessage()); + + // 类似 -01:01:01 的时间类型 getObject 会抛异常,getBytes 没问题 + // Ignore exception, use getBytes instead + value = resultSet.getBytes(i); + method = ParameterMethod.setBytes; + } + return new ParameterContext(method, new Object[] {i + 1, value, columnType}); + } + public static ParameterContext buildColumnParam(Row row, int i) { return buildColumnParam(row, i, false); } + public static Map buildColumnsParam(Row row) { + Map params = new TreeMap<>(); + if (row == null || row.getValues().isEmpty()) { + return params; + } + int columnSize = row.getColNum(); + for (int i = 0; i < columnSize; i++) { + params.put(i, buildColumnParam(row, i)); + } + return params; + } + /** * Build column parameter for insert,from the results of select * @@ -268,7 +368,7 @@ public static Map buildColumnParam( for (int i = 0; i < columnMetaList.size(); i++) { String stringVal = null; ColumnMeta meta = columnMetaList.get(i); - if (StringUtils.isEmpty(values.get(i)) && + if (StringUtils.isNullOrEmpty(values.get(i)) && (defaultMode == PropUtil.LOAD_NULL_MODE.DEFAULT_VALUE_MODE || defaultMode == PropUtil.LOAD_NULL_MODE.DEFAULT_VALUE_AND_N_MODE)) { if (meta.getField().getDefault() != null) { @@ -352,6 +452,9 @@ public static ParameterContext buildParamByType(long index, ParameterMethod meth } public static String serializeParam(ParameterContext pc) { + if (pc == null) { + return null; + } final ParameterMethod method = pc.getParameterMethod(); switch (method) { case setBytes: diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/HandlerCommon.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/HandlerCommon.java index e60b1f4f4..6459ce5e6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/HandlerCommon.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/HandlerCommon.java @@ -57,6 +57,8 @@ import com.alibaba.polardbx.executor.utils.GroupKey; import com.alibaba.polardbx.executor.utils.NewGroupKey; import com.alibaba.polardbx.executor.utils.RowSet; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.executor.utils.failpoint.FailPointKey; import com.alibaba.polardbx.gms.topology.SystemDbHelper; import com.alibaba.polardbx.group.config.Weight; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; @@ -64,6 +66,7 @@ import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.DdlContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil; import com.alibaba.polardbx.optimizer.core.rel.BaseQueryOperation; @@ -116,11 +119,13 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Queue; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicLong; import java.util.function.BiPredicate; import java.util.function.Consumer; @@ -265,6 +270,125 @@ private void executeSubNodesBlockConcurrent(ExecutionContext executionContext, L } } + private void executeSubNodesBlockConcurrentAmongShards(ExecutionContext executionContext, List subNodes, + List subCursors, String schemaName) { + if (subNodes != null && subNodes.isEmpty()) { + return; + } + checkExecMemCost(executionContext, subNodes); + Map> groupAndQcs = new HashMap<>(); + List execSubNodes = new ArrayList<>(); + for (RelNode q : subNodes) { + + String groupName = ((BaseQueryOperation) q).getDbIndex(); + Queue qcs = groupAndQcs.get(groupName); + if (qcs == null) { + qcs = new LinkedBlockingQueue<>(); + groupAndQcs.put(groupName, qcs); + execSubNodes.add(q); + } + + qcs.add(q); + } + + Set groupNames = groupAndQcs.keySet(); + + int prefetch = executionContext.getParamManager().getInt(ConnectionParams.PREFETCH_SHARDS); + Boolean overrideDdlParams = executionContext.isOverrideDdlParams(); + if (prefetch < 0) { + if (overrideDdlParams) { + prefetch = 3; + } else { + // By default, #prefetch_shards = 1 + prefetch = 1; + } + } + Map groupAndResidues = new HashMap<>(); + int finalPrefetch = prefetch; + groupNames.forEach(o -> groupAndResidues.put(o, finalPrefetch)); + + Map>> groupAndFutures = new HashMap<>(); + groupNames.forEach(o -> groupAndFutures.put(o, new ArrayList<>())); + + List exceptions = new ArrayList<>(); + + // For DDL only + Map phyObjectRecorderMap = new ConcurrentHashMap<>(); + + FailPoint.injectFromHint(FailPointKey.FP_PHYSICAL_DDL_INTERRUPTED, executionContext, () -> { + DdlContext ddlContext = executionContext.getDdlContext(); + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_INTERRUPTED, String.valueOf(ddlContext.getJobId()), + ddlContext.getSchemaName(), ddlContext.getObjectName()); + }); + + for (int execute = 0; execute < subNodes.size(); ) { + for (String groupName : groupNames) { + int residue = groupAndResidues.get(groupName); + if (residue > 0) { + final RelNode subNode = groupAndQcs.get(groupName).poll(); + if (subNode == null) { + continue; + } + GenericPhyObjectRecorder phyObjectRecorder = + CrossEngineValidator.getPhyObjectRecorder(subNode, executionContext); + if (!phyObjectRecorder.checkIfDone()) { + Future rcfuture = ExecutorContext.getContext(schemaName) + .getTopologyExecutor() + .execByExecPlanNodeFuture(subNode, executionContext, null); + groupAndFutures.get(groupName).add(rcfuture); + if (subNode instanceof PhyDdlTableOperation) { + String phyTableKey = DdlHelper.genPhyTableInfo(subNode, executionContext.getDdlContext()); + if (TStringUtil.isNotBlank(phyTableKey)) { + phyObjectRecorderMap.put(phyTableKey, phyObjectRecorder); + } + } + groupAndResidues.put(groupName, residue - 1); + } else { + // skip + } + + } + } + GenericPhyObjectRecorder phyObjectRecorder = null; + for (String groupName : groupNames) { + final List> futures = groupAndFutures.get(groupName); + List> doneFutures = new ArrayList<>(); + for (Future future : futures) { + if (future.isDone()) { + try { + Cursor cursor = future.get(); + subCursors.add(cursor); + if (cursor instanceof MyPhyDdlTableCursor) { + RelNode subNode = ((MyPhyDdlTableCursor) cursor).getRelNode(); + String phyTableKey = + DdlHelper.genPhyTableInfo(subNode, executionContext.getDdlContext()); + if (TStringUtil.isNotBlank(phyTableKey)) { + phyObjectRecorder = phyObjectRecorderMap.get(phyTableKey); + if (phyObjectRecorder != null) { + phyObjectRecorder.recordDone(); + } + } + } + } catch (Exception e) { + if (phyObjectRecorder == null || !phyObjectRecorder.checkIfIgnoreException(e)) { + exceptions.add(new TddlException(e)); + } + } finally { + doneFutures.add(future); + } + } + } + futures.removeAll(doneFutures); + groupAndResidues.put(groupName, groupAndResidues.get(groupName) + doneFutures.size()); + execute += doneFutures.size(); + } +// Thread.sleep(100); + } + if (!GeneralUtil.isEmpty(exceptions)) { + throw GeneralUtil.mergeException(exceptions); + } + } + private void executeFirstThenBlockConcurrent(ExecutionContext executionContext, List subNodes, List subCursors, String schemaName) { @@ -489,6 +613,10 @@ protected void executeWithConcurrentPolicy(ExecutionContext executionContext, Li // full concurrent executeSubNodesBlockConcurrent(executionContext, inputs, inputCursors, schemaName); break; + case DDL_CONCURRENT: + // full concurrent + executeSubNodesBlockConcurrentAmongShards(executionContext, inputs, inputCursors, schemaName); + break; case RELAXED_GROUP_CONCURRENT: // relaxed group concurrent executeRelaxedGroupConcurrent(executionContext, inputs, inputCursors, schemaName); @@ -503,6 +631,12 @@ protected void executeWithConcurrentPolicy(ExecutionContext executionContext, Li GenericPhyObjectRecorder phyObjectRecorder = CrossEngineValidator.getPhyObjectRecorder(relNode, executionContext); if (!phyObjectRecorder.checkIfDone()) { + FailPoint.injectFromHint(FailPointKey.FP_PHYSICAL_DDL_INTERRUPTED, executionContext, () -> { + DdlContext ddlContext = executionContext.getDdlContext(); + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_INTERRUPTED, + String.valueOf(ddlContext.getJobId()), + ddlContext.getSchemaName(), ddlContext.getObjectName()); + }); try { inputCursors.add(executor.execByExecPlanNode(relNode, executionContext)); phyObjectRecorder.recordDone(); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableArchivePartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableArchivePartitionHandler.java new file mode 100644 index 000000000..a37de18e2 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableArchivePartitionHandler.java @@ -0,0 +1,57 @@ +package com.alibaba.polardbx.executor.handler; + +import com.alibaba.polardbx.common.ddl.newengine.DdlState; +import com.alibaba.polardbx.executor.ddl.job.factory.ttl.ArchivePartitionJobFactory; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; +import com.alibaba.polardbx.executor.handler.ddl.LogicalCommonDdlHandler; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.PolarPrivilegeUtils; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.BaseDdlOperation; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableArchivePartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableArchivePartitionPreparedData; +import com.taobao.tddl.common.privilege.PrivilegePoint; + +import java.util.List; + +/** + * @author wumu + */ +public class LogicalAlterTableArchivePartitionHandler extends LogicalCommonDdlHandler { + + public LogicalAlterTableArchivePartitionHandler(IRepository repo) { + super(repo); + } + + @Override + public DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext executionContext) { + LogicalAlterTableArchivePartition logicalAlterTableArchivePartition = + (LogicalAlterTableArchivePartition) logicalDdlPlan; + + logicalAlterTableArchivePartition.prepare(); + + AlterTableArchivePartitionPreparedData preparedData = logicalAlterTableArchivePartition.getPreparedData(); + + final String schemaName = logicalDdlPlan.getSchemaName(); + final String primaryTableName = logicalDdlPlan.getTableName(); + final String tmpTableSchema = preparedData.getTmpTableSchema(); + final String tmpTableName = preparedData.getTmpTableName(); + final List phyPartitions = preparedData.getPhyPartitionNames(); + final List firstLevelPartNames = preparedData.getFirstLevelPartitionNames(); + + PolarPrivilegeUtils.checkPrivilege(schemaName, primaryTableName, PrivilegePoint.ALTER, executionContext); + PolarPrivilegeUtils.checkPrivilege(tmpTableSchema, tmpTableName, PrivilegePoint.DROP, executionContext); + + executionContext.getDdlContext().setPausedPolicy(DdlState.PAUSED); + + return new ArchivePartitionJobFactory( + schemaName, + primaryTableName, + tmpTableSchema, + tmpTableName, + phyPartitions, + firstLevelPartNames, + executionContext + ).create(); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableCleanupExpiredDataHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableCleanupExpiredDataHandler.java new file mode 100644 index 000000000..c25ba147d --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableCleanupExpiredDataHandler.java @@ -0,0 +1,57 @@ +/* + * Copyright [2013-2021], Alibaba Group Holding Limited + * + * Licensed 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 com.alibaba.polardbx.executor.handler; + +import com.alibaba.polardbx.common.ddl.newengine.DdlState; +import com.alibaba.polardbx.executor.ddl.job.factory.ttl.CleanupExpiredDataJobFactory; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; +import com.alibaba.polardbx.executor.handler.ddl.LogicalCommonDdlHandler; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.PolarPrivilegeUtils; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.BaseDdlOperation; +import com.taobao.tddl.common.privilege.PrivilegePoint; +import org.apache.calcite.sql.SqlAlterTable; +import org.apache.calcite.sql.SqlAlterTableCleanupExpiredData; + +public class LogicalAlterTableCleanupExpiredDataHandler extends LogicalCommonDdlHandler { + + public LogicalAlterTableCleanupExpiredDataHandler(IRepository repo) { + super(repo); + } + + @Override + public DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext executionContext) { + SqlAlterTable sqlAlterTable = (SqlAlterTable) logicalDdlPlan.getNativeSqlNode(); + SqlAlterTableCleanupExpiredData cleanupExpiredData = + (SqlAlterTableCleanupExpiredData) sqlAlterTable.getAlters().get(0); + + final String schemaName = logicalDdlPlan.getSchemaName(); + final String primaryTableName = logicalDdlPlan.getTableName(); + + PolarPrivilegeUtils.checkPrivilege(schemaName, primaryTableName, PrivilegePoint.ALTER, executionContext); + PolarPrivilegeUtils.checkPrivilege(schemaName, primaryTableName, PrivilegePoint.DELETE, executionContext); + + executionContext.getDdlContext().setPausedPolicy(DdlState.PAUSED); + + CleanupExpiredDataJobFactory jobFactory = + new CleanupExpiredDataJobFactory(schemaName, primaryTableName, logicalDdlPlan.relDdl, + executionContext); + return jobFactory.create(); + + } +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableModifyTtlHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableModifyTtlHandler.java new file mode 100644 index 000000000..2e609ccf1 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableModifyTtlHandler.java @@ -0,0 +1,60 @@ +/* + * Copyright [2013-2021], Alibaba Group Holding Limited + * + * Licensed 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 com.alibaba.polardbx.executor.handler; + +import com.alibaba.polardbx.common.ddl.newengine.DdlState; +import com.alibaba.polardbx.executor.ddl.job.factory.ttl.AlterTableModifyTtlJobFactory; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; +import com.alibaba.polardbx.executor.handler.ddl.LogicalCommonDdlHandler; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.PolarPrivilegeUtils; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.BaseDdlOperation; +import com.taobao.tddl.common.privilege.PrivilegePoint; +import org.apache.calcite.sql.SqlAlterTable; + +/** + * @author chenghui.lch + */ +public class LogicalAlterTableModifyTtlHandler extends LogicalCommonDdlHandler { + + public LogicalAlterTableModifyTtlHandler(IRepository repo) { + super(repo); + } + + @Override + public DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext executionContext) { + + final String schemaName = logicalDdlPlan.getSchemaName(); + final String primaryTableName = logicalDdlPlan.getTableName(); + + PolarPrivilegeUtils.checkPrivilege(schemaName, primaryTableName, PrivilegePoint.ALTER, executionContext); + PolarPrivilegeUtils.checkPrivilege(schemaName, primaryTableName, PrivilegePoint.DELETE, executionContext); + + executionContext.getDdlContext().setPausedPolicy(DdlState.PAUSED); + + SqlAlterTable sqlAlterTable = (SqlAlterTable) logicalDdlPlan.getNativeSqlNode(); + + AlterTableModifyTtlJobFactory jobFactory = + new AlterTableModifyTtlJobFactory(schemaName, primaryTableName, + logicalDdlPlan.relDdl, + sqlAlterTable, + executionContext); + return jobFactory.create(); + + } +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableRemoveTtlHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableRemoveTtlHandler.java new file mode 100644 index 000000000..8a899fe96 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalAlterTableRemoveTtlHandler.java @@ -0,0 +1,62 @@ +/* + * Copyright [2013-2021], Alibaba Group Holding Limited + * + * Licensed 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 com.alibaba.polardbx.executor.handler; + +import com.alibaba.polardbx.common.ddl.newengine.DdlState; +import com.alibaba.polardbx.executor.ddl.job.factory.ttl.AlterTableModifyTtlJobFactory; +import com.alibaba.polardbx.executor.ddl.job.factory.ttl.AlterTableRemoveTtlJobFactory; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; +import com.alibaba.polardbx.executor.handler.ddl.LogicalCommonDdlHandler; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.PolarPrivilegeUtils; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.BaseDdlOperation; +import com.taobao.tddl.common.privilege.PrivilegePoint; +import org.apache.calcite.rel.ddl.AlterTable; +import org.apache.calcite.sql.SqlAlterTable; + +/** + * @author chenghui.lch + */ +public class LogicalAlterTableRemoveTtlHandler extends LogicalCommonDdlHandler { + + public LogicalAlterTableRemoveTtlHandler(IRepository repo) { + super(repo); + } + + @Override + public DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext executionContext) { + + final String schemaName = logicalDdlPlan.getSchemaName(); + final String primaryTableName = logicalDdlPlan.getTableName(); + + PolarPrivilegeUtils.checkPrivilege(schemaName, primaryTableName, PrivilegePoint.ALTER, executionContext); + PolarPrivilegeUtils.checkPrivilege(schemaName, primaryTableName, PrivilegePoint.DELETE, executionContext); + + executionContext.getDdlContext().setPausedPolicy(DdlState.PAUSED); + + SqlAlterTable sqlAlterTable = (SqlAlterTable) logicalDdlPlan.getNativeSqlNode(); + + AlterTableRemoveTtlJobFactory jobFactory = + new AlterTableRemoveTtlJobFactory(schemaName, primaryTableName, + logicalDdlPlan.relDdl, + sqlAlterTable, + executionContext); + return jobFactory.create(); + + } +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalFireScheduleHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalFireScheduleHandler.java index 62ab4b3b7..2bd0dc6b8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalFireScheduleHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalFireScheduleHandler.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.executor.cursor.impl.AffectRowCursor; import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; import com.alibaba.polardbx.executor.scheduler.executor.statistic.StatisticHllScheduledJob; +import com.alibaba.polardbx.executor.scheduler.executor.statistic.StatisticInfoSchemaTablesScheduleJob; import com.alibaba.polardbx.executor.scheduler.executor.statistic.StatisticSampleCollectionScheduledJob; import com.alibaba.polardbx.executor.spi.IRepository; import com.alibaba.polardbx.executor.utils.PolarPrivilegeUtils; @@ -69,6 +70,18 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { job.setFromScheduleJob(false); job.execute(); + logger.info(String.format("fire scheduled job:[%s]", scheduleId)); + return new AffectRowCursor(1); + } else if (record.getExecutorType().equalsIgnoreCase("STATISTIC_INFO_SCHEMA_TABLES")) { + ExecutableScheduledJob executableScheduledJob = new ExecutableScheduledJob(); + executableScheduledJob.setScheduleId(record.getScheduleId()); + executableScheduledJob.setFireTime(System.currentTimeMillis()); + executableScheduledJob.setTimeZone("SYSTEM"); + StatisticInfoSchemaTablesScheduleJob job = + new StatisticInfoSchemaTablesScheduleJob(executableScheduledJob); + job.setFromScheduleJob(false); + job.execute(); + logger.info(String.format("fire scheduled job:[%s]", scheduleId)); return new AffectRowCursor(1); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTableHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTableHandler.java index 1b67ec98f..e21425ed3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTableHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTableHandler.java @@ -36,12 +36,16 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.parser.MySqlExprParser; import com.alibaba.polardbx.druid.sql.parser.ByteString; +import com.alibaba.polardbx.druid.sql.dialect.mysql.parser.MySqlExprParser; +import com.alibaba.polardbx.druid.sql.parser.ByteString; +import com.alibaba.polardbx.druid.sql.visitor.VisitorFeature; import com.alibaba.polardbx.druid.util.JdbcConstants; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.spi.IRepository; import com.alibaba.polardbx.gms.metadb.table.ColumnsRecord; import com.alibaba.polardbx.gms.metadb.table.TablesRecord; import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.dal.LogicalShow; import com.alibaba.polardbx.repo.mysql.common.ResultSetHelper; @@ -89,6 +93,10 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { } public static String reorgLogicalColumnOrder(String schemaName, String logicalTableName, String sql) { + if (!ConfigDataMode.isPolarDbX()) { + return sql; + } + // Always show columns in logical column order no matter what the mode. List logicalColumnsInOrder = ResultSetHelper.fetchLogicalColumnsInOrder(schemaName, logicalTableName); @@ -137,7 +145,8 @@ public static String reorgLogicalColumnOrder(String schemaName, String logicalTa } public static MySqlCreateTableStatement fetchShowCreateTableFromMetaDb(String schemaName, String tableName, - ExecutionContext executionContext) { + ExecutionContext executionContext, + TableMeta tableMeta) { final MySqlCreateTableStatement createTableStmt = new MySqlCreateTableStatement(); createTableStmt.setTableName(tableName); // Always show columns in logical column order no matter what the mode. diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTablesForPartitionDatabaseHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTablesForPartitionDatabaseHandler.java index 86d8536f3..6b424176e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTablesForPartitionDatabaseHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTablesForPartitionDatabaseHandler.java @@ -71,6 +71,7 @@ import com.alibaba.polardbx.gms.metadb.table.TablesRecord; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.schema.InformationSchema; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; @@ -89,6 +90,7 @@ import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; import com.alibaba.polardbx.optimizer.sequence.SequenceManagerProxy; import com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; import com.alibaba.polardbx.optimizer.utils.RelUtils; import com.alibaba.polardbx.optimizer.view.InformationSchemaViewManager; import com.alibaba.polardbx.optimizer.view.MysqlSchemaViewManager; @@ -161,15 +163,18 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { String sql; if (executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_LOGICAL_TABLE_META) || - ConfigDataMode.isColumnarMode()) { + ConfigDataMode.isColumnarMode() || tableMeta.isColumnar()) { MySqlCreateTableStatement tableStatement = LogicalShowCreateTableHandler.fetchShowCreateTableFromMetaDb( - schemaName, tableName, executionContext); + schemaName, tableName, executionContext, tableMeta); sql = tableStatement.toString(); } else { sql = fetchShowCreateTableFromPhy(schemaName, tableName, showCreateTable, show, executionContext); sql = LogicalShowCreateTableHandler.reorgLogicalColumnOrder(schemaName, tableName, sql); } + if (tableMeta.getTtlDefinitionInfo() != null) { + sql += tableMeta.getTtlDefinitionInfo().buildShowCreateTableOptions(); + } StringBuilder partitionStr = new StringBuilder(); TddlRuleManager tddlRuleManager = OptimizerContext.getContext(schemaName).getRuleManager(); PartitionInfoManager partitionInfoManager = tddlRuleManager.getPartitionInfoManager(); @@ -342,6 +347,7 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { if (tableOption.getValue() == null || !tableOption.getValue().toString() .equalsIgnoreCase(engine.name())) { tableOption.setValue(new SQLCharExpr(engine.name())); + } } @@ -464,10 +470,11 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { if (!tableMeta.isAutoPartition() || showCreateTable.isFull()) { sql = sql + partitionStr; } + if (tableMeta.getLocalPartitionDefinitionInfo() != null) { sql += "\n" + tableMeta.getLocalPartitionDefinitionInfo().toString(); } - + sql = sql + buildTtlTmpTableInfoIfNeed(schemaName, showCreateTable, partInfo); sql = sql + buildTableGroupInfo(schemaName, showCreateTable, partInfo); sql = tryAttachImplicitTableGroupInfo(executionContext, schemaName, tableName, sql); @@ -496,6 +503,26 @@ private String buildTableGroupInfo(String schemaName, SqlShowCreateTable showCre } } + private String buildTtlTmpTableInfoIfNeed(String schemaName, + SqlShowCreateTable showCreateTable, + PartitionInfo partInfo) { + if (!showCreateTable.isFull()) { + return ""; + } + String arcTableSchema = partInfo.getTableSchema(); + String arcTableName = partInfo.getTableName(); + TtlInfoRecord record = TtlUtil.fetchTtlDefinitionInfoByArcDbAndArcTb(arcTableSchema, arcTableName); + if (record == null) { + return ""; + } + String arcTmpTableName = record.getArcTmpTblName(); + String commentContent = ""; + if (!StringUtils.isEmpty(arcTmpTableName)) { + commentContent = String.format("\n/* arc_tmp = %s */", SqlIdentifier.surroundWithBacktick(arcTmpTableName)); + } + return commentContent; + } + private ArrayResultCursor showCreateView(String schemaName, String tableName, SqlShowCreateTable showCreateTable) { ViewManager viewManager; if (InformationSchema.NAME.equalsIgnoreCase(schemaName)) { @@ -669,15 +696,14 @@ public List buildIndexDefs(String schemaName, indeDef.setColumnar(indexMeta.columnarIndex); if (full && indexMeta.columnarIndex) { // set options - Map options = getColumnarIndexOptions(indexMeta.tableSchema, indexMeta.indexName); - if (options != null) { - indeDef.setDictionaryColumns(options.get(ColumnarTableOptions.DICTIONARY_COLUMNS)); - } TablesAccessor tablesAccessor = new TablesAccessor(); String engine = getColumnarIndexEngine(schemaName, indexMeta.indexName, tablesAccessor); if (engine != null) { indeDef.setEngineName(new SQLIdentifierExpr(engine)); } + + // Other columnar options. + indeDef.getIndexDefinition().addColumnarOption(indexMeta.columnarOptions.get()); } if (!coveringColumns.isEmpty() || full || !meta.isAutoPartition()) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowIndexHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowIndexHandler.java index bd2638908..a2aec87dd 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowIndexHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowIndexHandler.java @@ -16,11 +16,21 @@ package com.alibaba.polardbx.executor.handler; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.gms.metadb.GmsSystemTables; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; import com.alibaba.polardbx.gms.metadb.table.IndexStatus; +import com.alibaba.polardbx.gms.metadb.table.IndexesInfoSchemaRecord; import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.schema.InformationSchema; import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager.GsiIndexColumnMetaBean; @@ -41,11 +51,17 @@ import com.alibaba.polardbx.optimizer.view.SystemTableView; import com.alibaba.polardbx.optimizer.view.ViewManager; import org.apache.calcite.rel.RelNode; +import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlShow; import org.apache.calcite.sql.SqlShowIndex; +import org.apache.commons.lang.StringUtils; +import javax.sql.DataSource; +import java.sql.Connection; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import static com.alibaba.polardbx.common.TddlConstants.AUTO_LOCAL_INDEX_PREFIX; @@ -257,14 +273,77 @@ private Cursor handleForPartitionDatabase(RelNode logicalPlan, ExecutionContext return result; } + private Cursor handleForColumnarMode(RelNode logicalPlan, ExecutionContext ec, String schemaName) { + final BaseDalOperation dal = (BaseDalOperation) logicalPlan; + DataSource dataSource = MetaDbDataSource.getInstance().getDataSource(); + final SqlShowIndex showIndex = (SqlShowIndex) dal.getNativeSqlNode(); + final String tableName = RelUtils.lastStringValue(showIndex.getTableName()); + String sql = "select * from " + SqlIdentifier.surroundWithBacktick(GmsSystemTables.INDEXES) + + "where table_schema = ? and table_name = ? and index_type = ? and column_name != ?"; + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + //ignore columnar index + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, "BTree"); + //ignore primary key of _drds_implicit_id_ + MetaDbUtil.setParameter(4, params, ParameterMethod.setString, "_drds_implicit_id_"); + List indexesInfoSchemaRecords; + try (Connection connection = dataSource.getConnection()) { + indexesInfoSchemaRecords = MetaDbUtil.query(sql, params, IndexesInfoSchemaRecord.class, connection); + } catch (Exception e) { + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, + "fail to access metadb" + e.getMessage()); + } + + ArrayResultCursor result = new ArrayResultCursor("STATISTICS"); + result.addColumn("Table", null, DataTypes.StringType); + result.addColumn("Non_unique", null, DataTypes.IntegerType); + result.addColumn("Key_name", null, DataTypes.StringType); + result.addColumn("Seq_in_index", null, DataTypes.IntegerType); + result.addColumn("Column_name", null, DataTypes.StringType); + result.addColumn("Collation", null, DataTypes.StringType); + result.addColumn("Cardinality", null, DataTypes.LongType); + result.addColumn("Sub_part", null, DataTypes.IntegerType); + result.addColumn("Packed", null, DataTypes.StringType); + result.addColumn("Null", null, DataTypes.StringType); + result.addColumn("Index_type", null, DataTypes.StringType); + result.addColumn("Comment", null, DataTypes.StringType); + result.addColumn("Index_comment", null, DataTypes.StringType); + result.initMeta(); + for (IndexesInfoSchemaRecord record : indexesInfoSchemaRecords) { + String indexName = record.indexName; + if (StringUtils.startsWith(indexName, "_local_")) { + indexName = StringUtils.substring(indexName, "_local_".length()); + } + result.addRow(new Object[] { + record.tableName, + record.nonUnique, + indexName, + record.seqInIndex, + record.columnName, + record.collation, + record.cardinality, + record.subPart, + record.packed, + record.nullable, + record.indexType, + record.comment, + record.indexComment + }); + } + return result; + } + @Override public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { String schemaName = ((BaseDalOperation) logicalPlan).getSchemaName(); if (schemaName == null) { schemaName = executionContext.getSchemaName(); } - - if (DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { + if (ConfigDataMode.isColumnarMode() || executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_LOGICAL_TABLE_META)) { + return handleForColumnarMode(logicalPlan, executionContext, schemaName); + } else if (DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { return handleForPartitionDatabase(logicalPlan, executionContext); } else { return handleForShardingDatabase(logicalPlan, executionContext); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowLocalDeadlocksHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowLocalDeadlocksHandler.java index 2f7af7845..5f382e412 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowLocalDeadlocksHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowLocalDeadlocksHandler.java @@ -37,7 +37,7 @@ */ public class LogicalShowLocalDeadlocksHandler extends HandlerCommon { - private final static String SHOW_ENGINE_INNODB_STATUS = "show engine innodb status"; + public final static String SHOW_ENGINE_INNODB_STATUS = "show engine innodb status"; public LogicalShowLocalDeadlocksHandler(IRepository repo) { super(repo); @@ -54,18 +54,16 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { Set allDnId = ExecUtils.getAllDnStorageId(); // 2. Query each DN for deadlock information, and add it to the result - generateDeadlockLogs(allDnId, executionContext, result); + generateDeadlockLogs(allDnId, result); return result; } /** * @param allDnId is a set of all dn's storage instance id - * @param executionContext is used for privilege check * @param result is updated in this method */ private void generateDeadlockLogs(Set allDnId, - ExecutionContext executionContext, ArrayResultCursor result) { for (String dnId : allDnId) { try (Connection conn = DbTopologyManager.getConnectionForStorage(dnId); @@ -81,7 +79,7 @@ private void generateDeadlockLogs(Set allDnId, // Parse the {status} to get deadlock information, final String deadlockLog = - DeadlockParser.parseLocalDeadlock(status, executionContext); + DeadlockParser.parseLocalDeadlock(status); result.addRow(new Object[] {dnId, deadlockLog}); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowPruneTraceHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowPruneTraceHandler.java index 5784c4484..f046d0004 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowPruneTraceHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalShowPruneTraceHandler.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.statis.ColumnarPruneRecord; +import com.alibaba.polardbx.optimizer.statis.ColumnarTracer; import org.apache.calcite.rel.RelNode; import java.util.Collection; @@ -37,6 +38,7 @@ public LogicalShowPruneTraceHandler(IRepository repo) { @Override public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { ArrayResultCursor result = new ArrayResultCursor("TRACE"); + result.addColumn("INSTANCE_ID", DataTypes.StringType); result.addColumn("TABLE_NAME", DataTypes.StringType); result.addColumn("FILTER", DataTypes.StringType); result.addColumn("INIT_TIME(NS)", DataTypes.StringType); @@ -52,10 +54,12 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { result.initMeta(); Collection ops = null; - if (executionContext.getColumnarTracer() != null) { - ops = executionContext.getColumnarTracer().pruneRecords(); + ColumnarTracer columnarTracer = executionContext.getColumnarTracer(); + if (columnarTracer != null) { + ops = columnarTracer.pruneRecords(); for (ColumnarPruneRecord op : ops) { result.addRow(new Object[] { + columnarTracer.getInstanceId(), op.getTableName(), op.getFilter(), op.initIndexTime, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalSlowSqlCclHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalSlowSqlCclHandler.java index 1948588a4..0508d89d0 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalSlowSqlCclHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalSlowSqlCclHandler.java @@ -283,7 +283,9 @@ public Cursor handleGo(SqlSlowSqlCcl easyCcl, ExecutionContext executionContext) List>> results = SyncManagerHelper.sync( killSyncAction, schema, SyncScope.CURRENT_ONLY); for (List> result : results) { - count += (Integer) result.iterator().next().get(ResultCursor.AFFECT_ROW); + if (CollectionUtils.isNotEmpty(result)) { + count += (Integer) result.iterator().next().get(ResultCursor.AFFECT_ROW); + } } } return new AffectRowCursor(new int[] {count}); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalStartReplicaCheckTableHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalStartReplicaCheckTableHandler.java index dcb9500b1..98ffbfbad 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalStartReplicaCheckTableHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/LogicalStartReplicaCheckTableHandler.java @@ -1,19 +1,3 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.executor.handler; import com.alibaba.fastjson.JSON; @@ -54,14 +38,33 @@ public LogicalStartReplicaCheckTableHandler(IRepository repo) { public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { SqlStartReplicaCheck sqlStartReplicaCheck = (SqlStartReplicaCheck) ((LogicalDal) logicalPlan).getNativeSqlNode(); + Map params = buildParams(sqlStartReplicaCheck); + String daemonEndpoint = CdcTargetUtil.getDaemonMasterTarget(); + String url = String.format(API_PATTERN, daemonEndpoint); + String res; + try { + res = PooledHttpHelper.doPost(url, ContentType.APPLICATION_JSON, JSON.toJSONString(params), 10000); + } catch (Exception e) { + throw new TddlRuntimeException(ErrorCode.ERR_REPLICATION_RESULT, e); + } - String dbName = sqlStartReplicaCheck.getDbName().toString(); + ResultCode httpResult = JSON.parseObject(res, ResultCode.class); + if (httpResult.getCode() != CdcConstants.SUCCESS_CODE) { + throw new TddlRuntimeException(ErrorCode.ERR_REPLICATION_RESULT, httpResult.getMsg()); + } + return new AffectRowCursor(0); + } + + private Map buildParams(SqlStartReplicaCheck sqlStartReplicaCheck) { Map params = new HashMap<>(); + + String dbName = sqlStartReplicaCheck.getDbName().toString(); params.put(RplConstants.RPL_FULL_VALID_DB, dbName); if (sqlStartReplicaCheck.getTableName() != null) { String tbName = sqlStartReplicaCheck.getTableName().toString(); params.put(RplConstants.RPL_FULL_VALID_TB, tbName); } + if (sqlStartReplicaCheck.getChannel() != null) { String channel = sqlStartReplicaCheck.getChannel().toString(); params.put(RplConstants.CHANNEL, channel); @@ -69,19 +72,17 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { params.put(RplConstants.CHANNEL, ""); } - String daemonEndpoint = CdcTargetUtil.getDaemonMasterTarget(); - String url = String.format(API_PATTERN, daemonEndpoint); - String res; - try { - res = PooledHttpHelper.doPost(url, ContentType.APPLICATION_JSON, JSON.toJSONString(params), 10000); - } catch (Exception e) { - throw new TddlRuntimeException(ErrorCode.ERR_REPLICATION_RESULT, e); + if (sqlStartReplicaCheck.getMode() != null) { + String mode = sqlStartReplicaCheck.getMode().toString(); + // 如果mode不是direct或者snapshot,则抛出相关异常 + if (!StringUtils.equalsIgnoreCase(mode, "direct") && !StringUtils.equalsIgnoreCase(mode, "snapshot")) { + throw new TddlRuntimeException(ErrorCode.ERR_CDC_INVALID_PARAMS, "mode must be direct or snapshot"); + } + params.put(RplConstants.RPL_FULL_VALID_MODE, mode); + } else { + params.put(RplConstants.RPL_FULL_VALID_MODE, "snapshot"); } - ResultCode httpResult = JSON.parseObject(res, ResultCode.class); - if (httpResult.getCode() != CdcConstants.SUCCESS_CODE) { - throw new TddlRuntimeException(ErrorCode.ERR_REPLICATION_RESULT, httpResult.getMsg()); - } - return new AffectRowCursor(0); + return params; } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/VirtualViewHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/VirtualViewHandler.java index 8e6bc2974..5c14aadcc 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/VirtualViewHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/VirtualViewHandler.java @@ -27,13 +27,43 @@ import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaCclRuleHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaCclTriggerHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaCheckRoutinesHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaDdlEngineResourceHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaDdlSchedulerHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaCollationsCharsetHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaCollationsHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaColumnarIndexStatusHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaColumnarStatusHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaFunctionCacheCapacityHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaFunctionCacheHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaJavaFunctionsHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaMetricHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaOptimizerAlertHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaParametersHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaPartitionsHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaPartitionsMetaHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaPolardbxTrxHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaPreparedTrxBranchHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaProcedureCacheCapacityHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaProcedureCacheHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaPushedFunctionHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaRebalanceProgressHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaReplicaStatHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaRplSyncPointHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaShowHelpHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaStatementSummaryHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaStatementSummaryHistoryHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaRoutinesHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaCollationsCharsetHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaCollationsHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaColumnStatisticsHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaColumnarIndexStatusHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaColumnarStatusHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaColumnsHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaCreateDatabaseAsBackFillHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaCreateDatabaseHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaDdlEngineResourceHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaDdlPlanHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaDdlSchedulerHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaDnPerfHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaDrdsPhysicalProcessInTrxHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaFileStorageFilesMetaHandler; @@ -58,6 +88,7 @@ import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaLocalPartitionsScheduleHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaLocalityInfoHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaMetadataLockHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaMetricHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaModuleEventHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaModuleHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaMoveDatabaseHandler; @@ -81,6 +112,7 @@ import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaRebalanceProgressHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaReplicaStatHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaRoutinesHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaRplSyncPointHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaSPMHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaScheduleJobsHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaSchemaPrivilegesHandler; @@ -105,6 +137,8 @@ import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaTcpPerfHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaTraceHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaTriggerHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaTtlInfoHandler; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaTtlScheduleHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaUserPrivilegesHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaVariablesHandler; import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaWorkloadHandler; @@ -163,6 +197,7 @@ public VirtualViewHandler(IRepository repo) { subHandler.add(new InformationSchemaColumnarStatusHandler(this)); subHandler.add(new InformationSchemaMetadataLockHandler(this)); subHandler.add(new InformationSchemaModuleHandler(this)); + subHandler.add(new InformationSchemaMetricHandler(this)); subHandler.add(new InformationSchemaModuleEventHandler(this)); subHandler.add(new InformationSchemaUserPrivilegesHandler(this)); subHandler.add(new InformationSchemaTablePrivilegesHandler(this)); @@ -170,8 +205,12 @@ public VirtualViewHandler(IRepository repo) { subHandler.add(new InformationSchemaStorageHandler(this)); subHandler.add(new InformationSchemaStorageStatusHandler(this)); subHandler.add(new InformationSchemaTableGroupHandler(this)); + subHandler.add(new InformationSchemaDdlSchedulerHandler(this)); + subHandler.add(new InformationSchemaDdlEngineResourceHandler(this)); subHandler.add(new InformationSchemaPartitionsMetaHandler(this)); subHandler.add(new InformationSchemaPartitionsHandler(this)); + subHandler.add(new InformationSchemaTtlInfoHandler(this)); + subHandler.add(new InformationSchemaTtlScheduleHandler(this)); subHandler.add(new InformationSchemaLocalPartitionsHandler(this)); subHandler.add(new InformationSchemaLocalPartitionsScheduleHandler(this)); subHandler.add(new InformationSchemaAutoSplitScheduleHandler(this)); @@ -231,6 +270,7 @@ public VirtualViewHandler(IRepository repo) { subHandler.add(new InformationSchemaOptimizerAlertHandler(this)); subHandler.add(new InformationSchemaRebalanceProgressHandler(this)); subHandler.add(new InformationSchemaShowHelpHandler(this)); + subHandler.add(new InformationSchemaRplSyncPointHandler(this)); } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableAddPartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableAddPartitionHandler.java index b5cbfef7b..1e387889d 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableAddPartitionHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableAddPartitionHandler.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.config.table.SchemaManager; import com.alibaba.polardbx.optimizer.config.table.TableMeta; @@ -47,6 +48,7 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e LogicalAlterTableAddPartition logicalAlterTableAddPatition = (LogicalAlterTableAddPartition) logicalDdlPlan; logicalAlterTableAddPatition.preparedData(executionContext); + logicalAlterTableAddPatition.getPreparedData().setDdlVersionId(DdlUtils.generateVersionId(executionContext)); return AlterTableAddPartitionJobFactory .create(logicalAlterTableAddPatition.relDdl, (AlterTableAddPartitionPreparedData) logicalAlterTableAddPatition.getPreparedData(), diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableDropPartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableDropPartitionHandler.java index 741f0c118..04dce7312 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableDropPartitionHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableDropPartitionHandler.java @@ -24,6 +24,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; import com.alibaba.polardbx.executor.partitionmanagement.AlterTableGroupUtils; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.OptimizerContext; @@ -52,6 +53,7 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e LogicalAlterTableDropPartition logicalAlterTableDropPartition = (LogicalAlterTableDropPartition) logicalDdlPlan; logicalAlterTableDropPartition.preparedData(executionContext); + logicalAlterTableDropPartition.getPreparedData().setDdlVersionId(DdlUtils.generateVersionId(executionContext)); return AlterTableDropPartitionJobFactory .create(logicalAlterTableDropPartition.relDdl, (AlterTableDropPartitionPreparedData) logicalAlterTableDropPartition.getPreparedData(), diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableGroupOptimizePartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableGroupOptimizePartitionHandler.java new file mode 100644 index 000000000..51a662a21 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableGroupOptimizePartitionHandler.java @@ -0,0 +1,46 @@ +package com.alibaba.polardbx.executor.handler.ddl; + +import com.alibaba.polardbx.executor.ddl.job.factory.AlterTableGroupOptimizePartitionJobFactory; +import com.alibaba.polardbx.executor.ddl.job.factory.AlterTableGroupTruncatePartitionJobFactory; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; +import com.alibaba.polardbx.executor.partitionmanagement.AlterTableGroupUtils; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.optimizer.archive.CheckOSSArchiveUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.BaseDdlOperation; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupOptimizePartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupTruncatePartition; +import org.apache.calcite.sql.SqlAlterTableGroup; + +public class LogicalAlterTableGroupOptimizePartitionHandler extends LogicalCommonDdlHandler { + + public LogicalAlterTableGroupOptimizePartitionHandler(IRepository repo) { + super(repo); + } + + @Override + protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext executionContext) { + LogicalAlterTableGroupOptimizePartition logicalAlterTableGroupOptimizePartition = + (LogicalAlterTableGroupOptimizePartition) logicalDdlPlan; + + logicalAlterTableGroupOptimizePartition.prepareData(executionContext); + + String dbName = logicalAlterTableGroupOptimizePartition.getPreparedData().getSchemaName(); + String tgName = logicalAlterTableGroupOptimizePartition.getPreparedData().getTableGroupName(); + + CheckOSSArchiveUtil.checkTableGroupWithoutOSS(dbName, tgName); + + return new AlterTableGroupOptimizePartitionJobFactory(logicalAlterTableGroupOptimizePartition.relDdl, + logicalAlterTableGroupOptimizePartition.getPreparedData(), executionContext).create(); + } + + @Override + protected boolean validatePlan(BaseDdlOperation logicalDdlPlan, ExecutionContext executionContext) { + AlterTableGroupUtils.alterTableGroupPreCheck( + (SqlAlterTableGroup) logicalDdlPlan.relDdl.getSqlNode(), + logicalDdlPlan.getSchemaName(), + executionContext); + return super.validatePlan(logicalDdlPlan, executionContext); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableGroupTruncatePartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableGroupTruncatePartitionHandler.java index 7dd455a12..2c25bf382 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableGroupTruncatePartitionHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableGroupTruncatePartitionHandler.java @@ -24,6 +24,7 @@ import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.BaseDdlOperation; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupTruncatePartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupTruncatePartitionPreparedData; import org.apache.calcite.sql.SqlAlterTableGroup; public class LogicalAlterTableGroupTruncatePartitionHandler extends LogicalCommonDdlHandler { @@ -39,13 +40,16 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e logicalAlterTableGroupTruncatePartition.prepareData(executionContext); - String dbName = logicalAlterTableGroupTruncatePartition.getPreparedData().getSchemaName(); - String tgName = logicalAlterTableGroupTruncatePartition.getPreparedData().getTableGroupName(); + AlterTableGroupTruncatePartitionPreparedData preparedData = + logicalAlterTableGroupTruncatePartition.getPreparedData(); + + String dbName = preparedData.getSchemaName(); + String tgName = preparedData.getTableGroupName(); CheckOSSArchiveUtil.checkTableGroupWithoutOSS(dbName, tgName); return new AlterTableGroupTruncatePartitionJobFactory(logicalAlterTableGroupTruncatePartition.relDdl, - logicalAlterTableGroupTruncatePartition.getPreparedData(), executionContext).create(); + preparedData, executionContext, preparedData.getDdlVersionId()).create(); } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableHandler.java index 3340a094f..46dd9b0f1 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableHandler.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.Engine; import com.alibaba.polardbx.common.SQLMode; +import com.alibaba.polardbx.common.ddl.newengine.DdlState; import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; @@ -28,6 +29,7 @@ import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.druid.sql.ast.SQLIndexDefinition; import com.alibaba.polardbx.druid.sql.ast.SQLName; @@ -85,11 +87,13 @@ import com.alibaba.polardbx.executor.ddl.job.factory.oss.AlterTablePurgeBeforeTimeStampJobFactory; import com.alibaba.polardbx.executor.ddl.job.factory.oss.MoveOSSDataJobFactory; import com.alibaba.polardbx.executor.ddl.job.task.basic.AlterColumnDefaultTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TableSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.UpdateTablesVersionTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.GsiStatisticsInfoSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.StatisticSampleTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlTaskSqlBuilder; import com.alibaba.polardbx.executor.ddl.job.validator.ColumnValidator; import com.alibaba.polardbx.executor.ddl.job.validator.ConstraintValidator; import com.alibaba.polardbx.executor.ddl.job.validator.ForeignKeyValidator; @@ -103,9 +107,12 @@ import com.alibaba.polardbx.executor.gms.util.AlterRepartitionUtils; import com.alibaba.polardbx.executor.gsi.GsiUtils; import com.alibaba.polardbx.executor.handler.LogicalAlterTableAllocateLocalPartitionHandler; +import com.alibaba.polardbx.executor.handler.LogicalAlterTableCleanupExpiredDataHandler; import com.alibaba.polardbx.executor.handler.LogicalAlterTableEngineHandler; import com.alibaba.polardbx.executor.handler.LogicalAlterTableExpireLocalPartitionHandler; +import com.alibaba.polardbx.executor.handler.LogicalAlterTableModifyTtlHandler; import com.alibaba.polardbx.executor.handler.LogicalAlterTableRemoveLocalPartitionHandler; +import com.alibaba.polardbx.executor.handler.LogicalAlterTableRemoveTtlHandler; import com.alibaba.polardbx.executor.handler.LogicalAlterTableRepartitionLocalPartitionHandler; import com.alibaba.polardbx.executor.handler.LogicalShowCreateTableHandler; import com.alibaba.polardbx.executor.spi.IRepository; @@ -163,12 +170,13 @@ import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy; import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; import com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; import com.alibaba.polardbx.optimizer.utils.ForeignKeyUtils; import com.alibaba.polardbx.rule.TableRule; import com.alibaba.polardbx.optimizer.utils.ForeignKeyUtils; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.ddl.AlterTable; import org.apache.calcite.rex.RexNode; @@ -194,6 +202,7 @@ import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import java.text.MessageFormat; @@ -204,9 +213,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; -import java.util.Locale; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TreeMap; @@ -247,6 +254,19 @@ protected DdlJob doBuildDdlJob(BaseDdlOperation logicalDdlPlan, .buildDdlJob(logicalDdlPlan, executionContext); } + if (logicalAlterTable.isCleanupExpiredData()) { + return new LogicalAlterTableCleanupExpiredDataHandler(repo) + .buildDdlJob(logicalDdlPlan, executionContext); + } + + if (logicalAlterTable.isModifyTtlOptions()) { + return new LogicalAlterTableModifyTtlHandler(repo).buildDdlJob(logicalDdlPlan, executionContext); + } + + if (logicalAlterTable.isRemoveTtlOptions()) { + return new LogicalAlterTableRemoveTtlHandler(repo).buildDdlJob(logicalDdlPlan, executionContext); + } + if (logicalAlterTable.isRepartitionLocalPartition()) { return new LogicalAlterTableRepartitionLocalPartitionHandler(repo) .buildDdlJob(logicalDdlPlan, executionContext); @@ -272,7 +292,7 @@ protected DdlJob doBuildDdlJob(BaseDdlOperation logicalDdlPlan, if (logicalAlterTable.validateOnlineModify(executionContext, false) || logicalAlterTable.autoConvertToOmc(executionContext)) { - return buildRebuildTableJob(logicalAlterTable, true, executionContext); + return buildRebuildTableJob(logicalAlterTable, true, executionContext, ddlVersionId); } logicalAlterTable = rewriteExpressionIndex(logicalAlterTable, executionContext); @@ -309,7 +329,7 @@ protected DdlJob doBuildDdlJob(BaseDdlOperation logicalDdlPlan, } else { if (logicalAlterTable.getAlterTablePreparedData().isNeedRepartition()) { // for drop primary key, add primary - return buildRebuildTableJob(logicalAlterTable, false, executionContext); + return buildRebuildTableJob(logicalAlterTable, false, executionContext, ddlVersionId); } else { return buildAlterTableJob(logicalAlterTable, executionContext); } @@ -319,7 +339,7 @@ protected DdlJob doBuildDdlJob(BaseDdlOperation logicalDdlPlan, private LogicalAlterTable rewriteExpressionIndex(LogicalAlterTable logicalAlterTable, ExecutionContext executionContext) { // We rewrite expression in executor because in parser we do not know other column names in the table - if (logicalAlterTable.getSqlAlterTable().getOriginalSql() == null) { + if (logicalAlterTable.getSqlAlterTable().getOriginalSql() == null || InstanceVersion.isMYSQL80()) { // Could be alter table after rewrite return logicalAlterTable; } @@ -423,7 +443,8 @@ private LogicalAlterTable rewriteExpressionIndex(LogicalAlterTable logicalAlterT return logicalAlterTable; } - if (!executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_CREATE_EXPRESSION_INDEX)) { + if (!InstanceVersion.isMYSQL80() && !executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_CREATE_EXPRESSION_INDEX)) { throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, "create expression index is not enabled"); } @@ -726,130 +747,12 @@ protected boolean validatePlan(BaseDdlOperation logicalDdlPlan, ExecutionContext ForeignKeyValidator.validateFkConstraints(sqlAlterTable, schemaName, logicalTableName, executionContext); - TableValidator.validateTruncatePartition(logicalDdlPlan.getSchemaName(), logicalTableName, sqlAlterTable); + TableValidator.validateTruncatePartition(logicalDdlPlan.getSchemaName(), logicalTableName, sqlAlterTable, + executionContext); return false; } - private DdlJob buildAlterTableOnlineModifyColumnJob(LogicalAlterTable logicalAlterTable, - ExecutionContext executionContext) { - ExecutorContext executorContext = - ExecutorContext.getContext(logicalAlterTable.getAlterTablePreparedData().getSchemaName()); - if (!executorContext.getStorageInfoManager().supportsAlterType()) { - throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, "DN do not support online modify column"); - } - - AlterTablePreparedData alterTablePreparedData = logicalAlterTable.getAlterTablePreparedData(); - AlterTableWithGsiPreparedData alterTableWithGsiPreparedData = - logicalAlterTable.getAlterTableWithGsiPreparedData(); - - DdlPhyPlanBuilder alterTableBuilder = - AlterTableBuilder.create(logicalAlterTable.relDdl, alterTablePreparedData, executionContext).build(); - PhysicalPlanData physicalPlanData = alterTableBuilder.genPhysicalPlanData(); - - if (!alterTablePreparedData.isNewColumnNullable() && !SQLMode.isStrictMode( - executionContext.getSqlModeFlags())) { - throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, - "Do not support modify/change to not nullable column in non strict mode"); - } - - // Get old column type from show create table, wish we could rename column directly in DN someday - String targetTableName = alterTablePreparedData.getTableName(); - String modifiedColumnName = alterTablePreparedData.getModifyColumnName(); - LogicalShowCreateTableHandler logicalShowCreateTablesHandler = new LogicalShowCreateTableHandler(repo); - - SqlShowCreateTable sqlShowCreateTable = - SqlShowCreateTable.create(SqlParserPos.ZERO, new SqlIdentifier(targetTableName, SqlParserPos.ZERO)); - PlannerContext plannerContext = PlannerContext.fromExecutionContext(executionContext); - ExecutionPlan showCreateTablePlan = Planner.getInstance().getPlan(sqlShowCreateTable, plannerContext); - LogicalShow logicalShowCreateTable = (LogicalShow) showCreateTablePlan.getPlan(); - - Cursor showCreateTableCursor = - logicalShowCreateTablesHandler.handle(logicalShowCreateTable, executionContext); - - String createTableSql = null; - - Row showCreateResult = showCreateTableCursor.next(); - if (showCreateResult != null && showCreateResult.getString(1) != null) { - createTableSql = showCreateResult.getString(1); - } else { - GeneralUtil.nestedException("Get reference table architecture failed."); - } - - SQLCreateTableStatement createTableStmt = - (SQLCreateTableStatement) FastsqlUtils.parseSql(createTableSql).get(0); - - // Do not support if table contains fulltext index on any columns - if (createTableStmt.existFullTextIndex()) { - throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, - "Do not support online modify column on table with fulltext index"); - } - - SQLColumnDefinition colDef = createTableStmt.getColumn(modifiedColumnName); - if (colDef == null) { - for (SQLColumnDefinition columnDefinition : createTableStmt.getColumnDefinitions()) { - String columnName = SQLUtils.normalizeNoTrim(columnDefinition.getColumnName()); - if (columnName.equalsIgnoreCase(modifiedColumnName)) { - colDef = columnDefinition; - break; - } - } - } - - final boolean enableWithGenCol = - executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_OMC_WITH_GEN_COL); - - // Check if table has any generated column - for (SQLColumnDefinition columnDefinition : createTableStmt.getColumnDefinitions()) { - if (columnDefinition.getGeneratedAlawsAs() != null) { - if (!enableWithGenCol) { - // For now, we do not allow OMC on table with generated column, because on mysql we can not add or - // drop column before a generated column using inplace algorithm - throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, - String.format("Can not modify column [%s] on table with generated column [%s].", - alterTablePreparedData.getModifyColumnName(), columnDefinition.getColumnName())); - } - - String expr = columnDefinition.getGeneratedAlawsAs().toString(); - Set refCols = GeneratedColumnUtil.getReferencedColumns(expr); - if (refCols.contains(alterTablePreparedData.getModifyColumnName())) { - throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, - String.format("Can not modify column [%s] referenced by a generated column [%s].", - alterTablePreparedData.getModifyColumnName(), columnDefinition.getColumnName())); - } - } - } - - final boolean forceTypeConversion = - executionContext.getParamManager().getBoolean(ConnectionParams.OMC_FORCE_TYPE_CONVERSION); - if (!forceTypeConversion && TableColumnUtils.isUnsupportedType(colDef.getDataType().getName())) { - throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, - String.format("Converting from %s is not supported", colDef.getDataType().getName())); - } - - alterTablePreparedData.setModifyColumnType(TableColumnUtils.getDataDefFromColumnDef(colDef)); - alterTablePreparedData.setModifyColumnTypeNullable( - TableColumnUtils.getDataDefFromColumnDefWithoutUniqueNullable(colDef)); - - List gsiPhysicalPlanData = - getGsiPhysicalPlanData(logicalAlterTable, executionContext); - - ExecutableDdlJob alterTableJob = - new AlterTableOnlineModifyColumnJobFactory(physicalPlanData, gsiPhysicalPlanData, alterTablePreparedData, - alterTableWithGsiPreparedData, logicalAlterTable, executionContext).create(); - - Map tableVersions = new HashMap<>(); - tableVersions.put(alterTablePreparedData.getTableName(), - alterTablePreparedData.getTableVersion()); - ValidateTableVersionTask validateTableVersionTask = - new ValidateTableVersionTask(alterTablePreparedData.getSchemaName(), tableVersions); - - alterTableJob.addTask(validateTableVersionTask); - alterTableJob.addTaskRelationship(validateTableVersionTask, alterTableJob.getHead()); - - return alterTableJob; - } - private DdlJob buildAlterTableJob(LogicalAlterTable logicalAlterTable, ExecutionContext executionContext) { // Need Refractor, actually we should not let it play in this way. AlterTablePreparedData alterTablePreparedData = logicalAlterTable.getAlterTablePreparedData(); @@ -963,6 +866,9 @@ private DdlJob buildAlterTableJob(LogicalAlterTable logicalAlterTable, Execution logicalAlterTable, executionContext); ddlJob = alterTableAddLogicalForeignKeyJobFactory.create(); } else { + // 物理执行 ddl 的 pausedPolicy 设置为 PAUSED,避免自动调度 + executionContext.getDdlContext().setPausedPolicy(DdlState.PAUSED); + ParamManager paramManager = executionContext.getParamManager(); boolean supportTwoPhaseDdl = paramManager.getBoolean(ConnectionParams.ENABLE_DRDS_MULTI_PHASE_DDL); String finalStatus = paramManager.getString(ConnectionParams.TWO_PHASE_DDL_FINAL_STATUS); @@ -1099,6 +1005,8 @@ private DdlJob buildAlterTableJob(LogicalAlterTable logicalAlterTable, Execution ddlJob.addTask(validateTableVersionTask); ddlJob.addTaskRelationship(validateTableVersionTask, ddlJob.getHead()); + addRefreshArcViewSubJobIfNeed(ddlJob, logicalAlterTable, executionContext); + return ddlJob; } @@ -1138,7 +1046,8 @@ private void validateGenerateColumn(LogicalAlterTable logicalAlterTable, List relatedTableGroupInfo = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - globalIndexesPreparedData.stream().forEach(o -> relatedTableGroupInfo.putAll(o.getRelatedTableGroupInfo())); + globalIndexesPreparedData.forEach(o -> relatedTableGroupInfo.putAll(o.getRelatedTableGroupInfo())); Map indexTablePreparedDataMap = new LinkedHashMap<>(); - Map globalIndexPrepareData = new HashMap<>(); + List> globalIndexPrepareData = new ArrayList<>(); + String targetPrimaryTableName = logicalAlterTable.getSqlAlterTable().getLogicalSecondaryTableName(); for (CreateGlobalIndexPreparedData createGsiPreparedData : globalIndexesPreparedData) { createGsiPreparedData.getRelatedTableGroupInfo().putAll(relatedTableGroupInfo); DdlPhyPlanBuilder builder = CreateGlobalIndexBuilder.create( @@ -1199,13 +1110,18 @@ private DdlJob buildRebuildTableJob(LogicalAlterTable logicalAlterTable, boolean indexTablePreparedDataMap, ec).build(); + if (omc && StringUtils.equalsIgnoreCase(targetPrimaryTableName, + createGsiPreparedData.getIndexTableName())) { + createGsiPreparedData.setOmcRebuildPrimaryTable(true); + } indexTablePreparedDataMap.put(createGsiPreparedData.getIndexTableName(), createGsiPreparedData); - globalIndexPrepareData.put(createGsiPreparedData, builder.genPhysicalPlanData()); + globalIndexPrepareData.add(new Pair<>(createGsiPreparedData, builder.genPhysicalPlanData())); } RebuildTableJobFactory jobFactory = new RebuildTableJobFactory( logicalAlterTable.getSchemaName(), logicalAlterTable.getTableName(), + omc ? targetPrimaryTableName : logicalAlterTable.getTableName(), globalIndexPrepareData, rebuildTablePrepareData, physicalPlanData, @@ -1216,9 +1132,11 @@ private DdlJob buildRebuildTableJob(LogicalAlterTable logicalAlterTable, boolean jobFactory.setChangedColumns(changedColumns); ExecutableDdlJob ddlJob = jobFactory.create(); - Optional opt = globalIndexesPreparedData.stream().filter(o -> o.isNeedToGetTableGroupLock()).findAny(); + Optional opt = globalIndexesPreparedData.stream().filter( + CreateGlobalIndexPreparedData::isNeedToGetTableGroupLock).findAny(); if (opt.isPresent()) { //create tablegroup firstly + addRefreshArcViewSubJobIfNeed(ddlJob, logicalAlterTable, ec); return ddlJob; } Map tableVersions = new HashMap<>(); @@ -1230,6 +1148,8 @@ private DdlJob buildRebuildTableJob(LogicalAlterTable logicalAlterTable, boolean ddlJob.addTask(validateTableVersionTask); ddlJob.addTaskRelationship(validateTableVersionTask, ddlJob.getHead()); + addRefreshArcViewSubJobIfNeed(ddlJob, logicalAlterTable, ec); + return ddlJob; } @@ -1680,8 +1600,10 @@ protected Pair genPrimaryTableInfoAfterModifyColumn(Base ExecutionContext executionContext, List oldPrimaryKeys, RebuildTablePrepareData rebuildTablePrepareData) { - Map virtualColumnMap = rebuildTablePrepareData.getVirtualColumnMap(); - Map columnNewDef = rebuildTablePrepareData.getColumnNewDef(); + Map srcVirtualColumnMap = rebuildTablePrepareData.getSrcVirtualColumnMap(); + Map dstVirtualColumnMap = rebuildTablePrepareData.getDstVirtualColumnMap(); + Map srcColumnNewDef = rebuildTablePrepareData.getSrcColumnNewDef(); + Map dstColumnNewDef = rebuildTablePrepareData.getDstColumnNewDef(); Map backfillColumnMap = rebuildTablePrepareData.getBackfillColumnMap(); List modifyStringColumns = rebuildTablePrepareData.getModifyStringColumns(); List addNewColumns = rebuildTablePrepareData.getAddNewColumns(); @@ -1875,12 +1797,18 @@ protected Pair genPrimaryTableInfoAfterModifyColumn(Base } else if (newColumnDefinitionMap.containsKey(columnName)) { SQLColumnDefinition newColumnDefinition = newColumnDefinitionMap.get(columnName); newTableElementList.add(newColumnDefinition); - if (!autoIncrement) { + if (!autoIncrement && !newColumnDefinition.isAutoIncrement()) { // for checker prepare String colNameStr = columnName.toLowerCase(); - virtualColumnMap.put(colNameStr, GsiUtils.generateRandomGsiName(colNameStr)); - columnNewDef.put(colNameStr, - TableColumnUtils.getDataDefFromColumnDefNoDefault(newColumnDefinition)); + srcVirtualColumnMap.put(colNameStr, GsiUtils.generateRandomGsiName(colNameStr)); + srcColumnNewDef.put(colNameStr, newColumnDefinition); + + String newColNameStr = colNameStr; + if (MapUtils.isNotEmpty(backfillColumnMap) && backfillColumnMap.containsKey(colNameStr)) { + newColNameStr = backfillColumnMap.get(colNameStr); + } + dstVirtualColumnMap.put(newColNameStr, GsiUtils.generateRandomGsiName(newColNameStr)); + dstColumnNewDef.put(newColNameStr, columnDefinition); } if (!newColumnAfter.containsKey(columnName) && !newColumnFirst.containsKey(columnName)) { newColumnDefinitionMap.remove(columnName); @@ -2342,4 +2270,41 @@ public List buildIndexDefinition4AutoForTest(String schemaNa alterTablePreparedData, rebuildTablePrepareData, primaryKeyNotChanged, oldPrimaryKeys, primaryTableInfo, ast); } + + /** + * Check if need add a subjob task of auto refresh the cci view of arc tbl + */ + public void addRefreshArcViewSubJobIfNeed(DdlJob ddlJob, LogicalAlterTable alterTable, ExecutionContext ec) { + if (!alterTable.needRefreshArcTblView(ec)) { + return; + } + + String tableSchema = alterTable.getSchemaName(); + String tableName = alterTable.getTableName(); + TtlDefinitionInfo ttlInfo = TtlUtil.fetchTtlDefinitionInfoByDbAndTb(tableSchema, tableName, ec); + if (ttlInfo == null) { + return; + } + String arcTblSchema = ttlInfo.getArchiveTableSchema(); + String arcTblName = ttlInfo.getArchiveTableName(); + + String createViewSqlForArcTbl = + TtlTaskSqlBuilder.buildCreateViewSqlForArcTbl(arcTblSchema, arcTblName, ttlInfo); + String dropViewSqlForArcTbl = ""; // ignore rollback + SubJobTask freshViewSubJobTask = + new SubJobTask(tableSchema, createViewSqlForArcTbl, dropViewSqlForArcTbl); + freshViewSubJobTask.setParentAcquireResource(true); + + ExecutableDdlJob executableDdlJob = (ExecutableDdlJob) ddlJob; +// DdlTask tailTask = executableDdlJob.getTail(); + List tailNodes = + executableDdlJob.getAllZeroOutDegreeVertexes().stream().map(o -> o.getObject()).collect( + Collectors.toList()); + executableDdlJob.addTask(freshViewSubJobTask); + for (int i = 0; i < tailNodes.size(); i++) { + DdlTask tailTask = tailNodes.get(i); + executableDdlJob.addTaskRelationship(tailTask, freshViewSubJobTask); + } + executableDdlJob.labelAsTail(freshViewSubJobTask); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableMergePartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableMergePartitionHandler.java index 70e4fcddf..e7f44a9a3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableMergePartitionHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableMergePartitionHandler.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; import com.alibaba.polardbx.executor.partitionmanagement.AlterTableGroupUtils; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.OptimizerContext; @@ -52,6 +53,7 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e LogicalAlterTableMergePartition alterTableMergePartition = (LogicalAlterTableMergePartition) logicalDdlPlan; alterTableMergePartition.preparedData(executionContext); + alterTableMergePartition.getPreparedData().setDdlVersionId(DdlUtils.generateVersionId(executionContext)); return AlterTableMergePartitionJobFactory .create(alterTableMergePartition.relDdl, (AlterTableMergePartitionPreparedData) alterTableMergePartition.getPreparedData(), diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableModifyPartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableModifyPartitionHandler.java index 56961a914..f399657b5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableModifyPartitionHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableModifyPartitionHandler.java @@ -18,10 +18,12 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.executor.ddl.job.factory.AlterTableModifyPartitionJobFactory; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; @@ -58,6 +60,8 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e LogicalAlterTableModifyPartition logicalAlterTableModifyPartition = (LogicalAlterTableModifyPartition) logicalDdlPlan; logicalAlterTableModifyPartition.preparedData(executionContext); + logicalAlterTableModifyPartition.getPreparedData() + .setDdlVersionId(DdlUtils.generateVersionId(executionContext)); return AlterTableModifyPartitionJobFactory .create(logicalAlterTableModifyPartition.relDdl, (AlterTableModifyPartitionPreparedData) logicalAlterTableModifyPartition.getPreparedData(), @@ -222,6 +226,16 @@ protected boolean validatePlan(BaseDdlOperation logicalDdlPlan, ExecutionContext throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_MODIFY_PARTITION_DROP_VALUE, String.format("it's not support to drop value for global index[%s]", logicalTableName)); } + boolean allDropTruncateCciPartition = + executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_DROP_TRUNCATE_CCI_PARTITION); + if (tableMeta.withCci() && !allDropTruncateCciPartition) { + throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_MANAGEMENT, + String.format("it's not support to drop value when table[%s] with CCI", logicalTableName)); + } + if (tableMeta.isColumnar() && !allDropTruncateCciPartition) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_MODIFY_PARTITION_DROP_VALUE, + String.format("it's not support to drop value for columnar index[%s]", logicalTableName)); + } } return false; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableOptimizePartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableOptimizePartitionHandler.java new file mode 100644 index 000000000..5fe61d57f --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableOptimizePartitionHandler.java @@ -0,0 +1,82 @@ +package com.alibaba.polardbx.executor.handler.ddl; + +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.executor.ddl.job.factory.AlterTableOptimizePartitionJobFactory; +import com.alibaba.polardbx.executor.ddl.job.factory.AlterTableTruncatePartitionJobFactory; +import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; +import com.alibaba.polardbx.executor.partitionmanagement.AlterTableGroupUtils; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.BaseDdlOperation; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableOptimizePartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableTruncatePartition; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import org.apache.calcite.rel.ddl.AlterTable; +import org.apache.calcite.sql.SqlAlterTable; +import org.apache.calcite.sql.SqlAlterTableOptimizePartition; +import org.apache.calcite.sql.SqlAlterTableTruncatePartition; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.util.Util; + +public class LogicalAlterTableOptimizePartitionHandler extends LogicalCommonDdlHandler { + + public LogicalAlterTableOptimizePartitionHandler(IRepository repo) { + super(repo); + } + + @Override + protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext executionContext) { + LogicalAlterTableOptimizePartition logicalAlterTableOptimizePartition = + (LogicalAlterTableOptimizePartition) logicalDdlPlan; + logicalAlterTableOptimizePartition.prepareData(); + AlterTableOptimizePartitionJobFactory jobFactory = + new AlterTableOptimizePartitionJobFactory(logicalAlterTableOptimizePartition.relDdl, + logicalAlterTableOptimizePartition.getPreparedData(), + executionContext); + DdlJob ddlJob = jobFactory.create(); + return ddlJob; + } + + @Override + protected boolean validatePlan(BaseDdlOperation logicalDdlPlan, ExecutionContext executionContext) { + AlterTable alterTable = (AlterTable) logicalDdlPlan.relDdl; + SqlAlterTable sqlAlterTable = (SqlAlterTable) alterTable.getSqlNode(); + + assert sqlAlterTable.getAlters().size() == 1; + assert sqlAlterTable.getAlters().get(0) instanceof SqlAlterTableTruncatePartition; + + SqlAlterTableOptimizePartition sqlAlterTableOptimizePartition = + (SqlAlterTableOptimizePartition) sqlAlterTable.getAlters().get(0); + + assert sqlAlterTableOptimizePartition.getPartitions().size() >= 1; + + String schemaName = logicalDdlPlan.getSchemaName(); + String logicalTableName = Util.last(((SqlIdentifier) alterTable.getTableName()).names); + + if (!DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { + throw new TddlNestableRuntimeException( + "can't execute the truncate partition command in a non-auto mode database"); + } + + TableValidator.validateOptimizePartition(schemaName, logicalTableName, sqlAlterTable); + + TableValidator.validateTableNotReferenceFk(schemaName, logicalTableName, executionContext); + + PartitionInfo partitionInfo = + OptimizerContext.getContext(schemaName).getPartitionInfoManager().getPartitionInfo(logicalTableName); + + TableGroupConfig tableGroupConfig = + OptimizerContext.getContext(schemaName).getTableGroupInfoManager().getTableGroupConfigById( + partitionInfo.getTableGroupId()); + + AlterTableGroupUtils.alterTableGroupOptimizePartitionCheck(sqlAlterTableOptimizePartition, tableGroupConfig, + executionContext); + + return super.validatePlan(logicalDdlPlan, executionContext); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableRemovePartitioningHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableRemovePartitioningHandler.java index 10c2bb47b..579b2c89c 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableRemovePartitioningHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableRemovePartitioningHandler.java @@ -95,9 +95,12 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e Map globalIndexPrepareData = new HashMap<>(); + Map relatedTableGroupInfo = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + globalIndexPreparedDataList.forEach(o->relatedTableGroupInfo.putAll(o.getRelatedTableGroupInfo())); Map indexTablePreparedDataMap = new TreeMap<>(String::compareToIgnoreCase); for (CreateGlobalIndexPreparedData createGsiPreparedData : globalIndexPreparedDataList) { + createGsiPreparedData.getRelatedTableGroupInfo().putAll(relatedTableGroupInfo); DdlPhyPlanBuilder builder = CreateGlobalIndexBuilder.create( logicalAlterTableRemovePartitioning.relDdl, createGsiPreparedData, @@ -184,6 +187,12 @@ private void initPrimaryTableDefinition(BaseDdlOperation logicalDdlPlan, } String newGsiName = genGlobalIndexName(schema, indexName, executionContext); + SqlIdentifier tableGroupName = null; + boolean withImplicitTableGroup = false; + if(ast.getIndexTableGroupMap().get(indexName) != null) { + tableGroupName = new SqlIdentifier(ast.getIndexTableGroupMap().get(indexName), SqlParserPos.ZERO); + withImplicitTableGroup = true; + } SqlIndexDefinition localIndexGsi = AlterRepartitionUtils.initIndexInfo( newGsiName, indexKeys, @@ -192,8 +201,8 @@ private void initPrimaryTableDefinition(BaseDdlOperation logicalDdlPlan, indexMeta.isUniqueIndex(), primaryTableInfo.getKey(), primaryTableInfo.getValue(), - null, - false + tableGroupName, + withImplicitTableGroup ); // prepare for drop gsi columns diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableRenamePartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableRenamePartitionHandler.java index b5b09a7b7..414944d68 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableRenamePartitionHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableRenamePartitionHandler.java @@ -20,6 +20,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; import com.alibaba.polardbx.executor.partitionmanagement.AlterTableGroupUtils; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; @@ -46,6 +47,8 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e LogicalAlterTableRenamePartition logicalAlterTableRenamePartition = (LogicalAlterTableRenamePartition) logicalDdlPlan; logicalAlterTableRenamePartition.prepareData(executionContext); + logicalAlterTableRenamePartition.getPreparedData() + .setDdlVersionId(DdlUtils.generateVersionId(executionContext)); return AlterTableRenamePartitionJobFactory.create(logicalAlterTableRenamePartition.relDdl, (AlterTableRenamePartitionPreparedData) logicalAlterTableRenamePartition.getPreparedData(), executionContext); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableReorgPartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableReorgPartitionHandler.java index df6199d45..6ab4a0f53 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableReorgPartitionHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableReorgPartitionHandler.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; import com.alibaba.polardbx.executor.partitionmanagement.AlterTableGroupUtils; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.OptimizerContext; @@ -48,6 +49,7 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e (LogicalAlterTableReorgPartition) logicalDdlPlan; logicalAlterTableReorgPartition.prepareData(executionContext); + logicalAlterTableReorgPartition.getPreparedData().setDdlVersionId(DdlUtils.generateVersionId(executionContext)); return AlterTableReorgPartitionJobFactory.create(logicalAlterTableReorgPartition.relDdl, (AlterTableReorgPartitionPreparedData) logicalAlterTableReorgPartition.getPreparedData(), executionContext); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableSplitPartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableSplitPartitionHandler.java index 3c4a1d259..327df7f75 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableSplitPartitionHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableSplitPartitionHandler.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; import com.alibaba.polardbx.executor.partitionmanagement.AlterTableGroupUtils; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.OptimizerContext; @@ -48,6 +49,7 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e LogicalAlterTableSplitPartition alterTableSplitPartition = (LogicalAlterTableSplitPartition) logicalDdlPlan; alterTableSplitPartition.preparedData(executionContext); + alterTableSplitPartition.getPreparedData().setDdlVersionId(DdlUtils.generateVersionId(executionContext)); return AlterTableSplitPartitionJobFactory .create(alterTableSplitPartition.relDdl, (AlterTableSplitPartitionPreparedData) alterTableSplitPartition.getPreparedData(), diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableTruncatePartitionHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableTruncatePartitionHandler.java index 3417b7aae..ec36570a7 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableTruncatePartitionHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalAlterTableTruncatePartitionHandler.java @@ -22,12 +22,14 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; import com.alibaba.polardbx.executor.partitionmanagement.AlterTableGroupUtils; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.BaseDdlOperation; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableTruncatePartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupTruncatePartitionPreparedData; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import org.apache.calcite.rel.ddl.AlterTable; import org.apache.calcite.sql.SqlAlterTable; @@ -48,9 +50,12 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e logicalAlterTableTruncatePartition.prepareData(); + AlterTableGroupTruncatePartitionPreparedData preparedData = + logicalAlterTableTruncatePartition.getPreparedData(); + preparedData.setDdlVersionId(DdlUtils.generateVersionId(executionContext)); + return new AlterTableTruncatePartitionJobFactory(logicalAlterTableTruncatePartition.relDdl, - logicalAlterTableTruncatePartition.getPreparedData(), - executionContext).create(); + preparedData, executionContext, preparedData.getDdlVersionId()).create(); } @Override @@ -74,7 +79,7 @@ protected boolean validatePlan(BaseDdlOperation logicalDdlPlan, ExecutionContext "can't execute the truncate partition command in a non-auto mode database"); } - TableValidator.validateTruncatePartition(schemaName, logicalTableName, sqlAlterTable); + TableValidator.validateTruncatePartition(schemaName, logicalTableName, sqlAlterTable, executionContext); TableValidator.validateTableNotReferenceFk(schemaName, logicalTableName, executionContext); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCheckCciHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCheckCciHandler.java index 510225c96..8cb8415c8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCheckCciHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCheckCciHandler.java @@ -20,7 +20,9 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.CheckCciIncrementTask; import com.alibaba.polardbx.executor.ddl.job.task.columnar.CheckCciMetaTask; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.CheckCciSnapshotTask; import com.alibaba.polardbx.executor.ddl.job.task.columnar.CheckCciStartTask; import com.alibaba.polardbx.executor.ddl.job.task.columnar.CheckCciTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ClearCheckReportTask; @@ -74,6 +76,24 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e job = new ExecutableDdlJob(); job.addSequentialTasks(ImmutableList.of(checkCciMetaTask)); + } else if (prepareData.isIncrement()) { + // CHECK COLUMNAR INDEX INCREMENT tsoV0 tsoV1 + CheckCciStartTask checkCciStartTask = + new CheckCciStartTask(prepareData.getSchemaName(), prepareData.getTableName(), + prepareData.getIndexName()); + CheckCciIncrementTask checkTask = CheckCciIncrementTask.create(prepareData); + + job = new ExecutableDdlJob(); + job.addSequentialTasks(ImmutableList.of(checkCciStartTask, checkTask)); + } else if (prepareData.isSnapshot()) { + // CHECK COLUMNAR INDEX SNAPSHOT tso + CheckCciStartTask checkCciStartTask = + new CheckCciStartTask(prepareData.getSchemaName(), prepareData.getTableName(), + prepareData.getIndexName()); + CheckCciSnapshotTask checkTask = CheckCciSnapshotTask.create(prepareData); + + job = new ExecutableDdlJob(); + job.addSequentialTasks(ImmutableList.of(checkCciStartTask, checkTask)); } final String fullTableName = diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCommonDdlHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCommonDdlHandler.java index 028a9cdf3..9ebc77b05 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCommonDdlHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCommonDdlHandler.java @@ -170,6 +170,18 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { * Some special DDL command could override this method to generate its own result. */ protected Cursor buildResultCursor(BaseDdlOperation baseDdl, DdlJob ddlJob, ExecutionContext ec) { + if (ec.getParamManager().getBoolean(ConnectionParams.RETURN_JOB_ID_ON_ASYNC_DDL_MODE)) { + ArrayResultCursor result = new ArrayResultCursor("Execution Plan"); + result.addColumn("job_id", DataTypes.LongType); + result.initMeta(); + long jobId = 0; + if (ec.getDdlContext() != null) { + jobId = ec.getDdlContext().getJobId(); + } + result.addRow(new Long[] {jobId}); + return result; + } + // Always return 0 rows affected or throw an exception to report error messages. // SHOW DDL RESULT can provide more result details for the DDL execution. return new AffectRowCursor(new int[] {0}); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateDatabaseHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateDatabaseHandler.java index d496545e0..5c3a3ed0b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateDatabaseHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateDatabaseHandler.java @@ -148,18 +148,41 @@ public Cursor handleByGms(RelNode logicalPlan, ExecutionContext executionContext predLocality, dbType, isCreateIfNotExists, socketTimeoutVal, shardDbCountEachStorageInst); - long dbId = DbTopologyManager.createLogicalDb(createDbInfo); + initHookFuncForCreateDbInfo(executionContext, dbName, sqlCreateDatabase, createDbInfo, finalLocalityDesc, lm); + DbTopologyManager.createLogicalDb(createDbInfo); DbEventUtil.logFirstAutoDbCreationEvent(createDbInfo); - CdcManagerHelper.getInstance() - .notifyDdl(dbName, null, sqlCreateDatabase.getKind().name(), executionContext.getOriginSql(), - null, CdcDdlMarkVisibility.Public, buildExtendParameter(executionContext)); - if (!finalLocalityDesc.holdEmptyDnList()) { - lm.setLocalityOfDb(dbId, finalLocalityDesc.toString()); - } return new AffectRowCursor(new int[] {1}); } + private void initHookFuncForCreateDbInfo(ExecutionContext executionContext, + String dbName, + SqlCreateDatabase sqlCreateDatabase, + CreateDbInfo createDbInfo, + LocalityDesc finalLocalityDesc, + LocalityManager lm) { + CreateDbInfo.CreatedDbHookFunc markCdcFunc = new CreateDbInfo.CreatedDbHookFunc() { + @Override + public void handle(Long newAddedDbInfoId) { + CdcManagerHelper.getInstance() + .notifyDdl(dbName, null, sqlCreateDatabase.getKind().name(), executionContext.getOriginSql(), + null, CdcDdlMarkVisibility.Public, buildExtendParameter(executionContext)); + + } + }; + createDbInfo.getCreatedDbHookFuncList().add(markCdcFunc); + + CreateDbInfo.CreatedDbHookFunc refreshLocalityFunc = new CreateDbInfo.CreatedDbHookFunc() { + @Override + public void handle(Long newAddedDbInfoId) { + if (!finalLocalityDesc.holdEmptyDnList()) { + lm.setLocalityOfDb(newAddedDbInfoId, finalLocalityDesc.toString()); + } + } + }; + createDbInfo.getCreatedDbHookFuncList().add(refreshLocalityFunc); + } + @NotNull private DdlCharsetInfo fetchCreateDbCharsetInfo(ExecutionContext executionContext, SqlCreateDatabase sqlCreateDatabase) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateDatabaseLikeAsHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateDatabaseLikeAsHandler.java index 2c6732728..ea5d75c76 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateDatabaseLikeAsHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateDatabaseLikeAsHandler.java @@ -90,6 +90,7 @@ public class LogicalCreateDatabaseLikeAsHandler extends LogicalCommonDdlHandler { private static final Logger logger = LoggerFactory.getLogger(LogicalCreateDatabaseLikeAsHandler.class); final String failedSql = "failed to convert"; + static final String TABLE_TYPE = "base table"; public LogicalCreateDatabaseLikeAsHandler(IRepository repo) { super(repo); @@ -123,7 +124,7 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e maxPhyPartitionNum, maxPartitionColumnNum); tableAndCreateSqlAuto.put(tableName, createAutoModeSql); } catch (Throwable e) { - tableAndCreateSqlAuto.put(tableName, failedSql); + throw new TddlRuntimeException(ErrorCode.ER_AUTO_CONVERT, e, e.getMessage()); } }); tableAndCreateSqlAuto.forEach((tableName, createTableAutoSql) -> { @@ -227,7 +228,8 @@ protected boolean validatePlan(BaseDdlOperation logicalDdlPlan, ExecutionContext } Set allTablesInReferenceDb = new TreeSet<>(String::compareToIgnoreCase); - allTablesInReferenceDb.addAll(getTableNamesFromDatabase(sourceSchemaName, executionContext)); + allTablesInReferenceDb.addAll( + DrdsToAutoTableCreationSqlUtil.getTableNamesFromDatabase(sourceSchemaName, executionContext)); if (!sqlCreateDatabase.getIncludeTables().isEmpty()) { sqlCreateDatabase.getIncludeTables().forEach( includeTable -> { @@ -292,7 +294,8 @@ protected boolean validatePlan(BaseDdlOperation logicalDdlPlan, ExecutionContext } Set allTableInNewDatabase = new TreeSet<>(String::compareToIgnoreCase); - allTableInNewDatabase.addAll(getTableNamesFromDatabase(newDatabaseName, executionContext)); + allTableInNewDatabase.addAll( + DrdsToAutoTableCreationSqlUtil.getTableNamesFromDatabase(newDatabaseName, executionContext)); allNeedConvertTable.forEach( needConvertTb -> { if (!allTableInNewDatabase.contains(needConvertTb)) { @@ -452,7 +455,8 @@ protected Cursor buildResultCursor(BaseDdlOperation baseDdl, DdlJob ddlJob, Exec protected Map getAllCreateTablesSqlSnapshot(String sourceSchemaName, ExecutionContext executionContext) { - List tableInThisSchema = getTableNamesFromDatabase(sourceSchemaName, executionContext); + List tableInThisSchema = + DrdsToAutoTableCreationSqlUtil.getTableNamesFromDatabase(sourceSchemaName, executionContext); Map tableAndCreateSql = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); tableInThisSchema.forEach( @@ -462,38 +466,6 @@ protected Map getAllCreateTablesSqlSnapshot(String sourceSchemaN return tableAndCreateSql; } - protected List getTableNamesFromDatabase(String schemaName, ExecutionContext executionContext) { - SqlShowTables sqlShowTables = - SqlShowTables.create(SqlParserPos.ZERO, false, null, schemaName, null, null, null, null); - ExecutionContext copiedContext = executionContext.copy(); - copiedContext.setSchemaName(schemaName); - PlannerContext plannerContext = PlannerContext.fromExecutionContext(copiedContext); - ExecutionPlan showTablesPlan = Planner.getInstance().getPlan(sqlShowTables, plannerContext); - LogicalShow logicalShowTables = (LogicalShow) showTablesPlan.getPlan(); - - IRepository sourceRepo = ExecutorContext - .getContext(schemaName) - .getTopologyHandler() - .getRepositoryHolder() - .get(Group.GroupType.MYSQL_JDBC.toString()); - LogicalShowTablesMyHandler logicalShowTablesMyHandler = new LogicalShowTablesMyHandler(sourceRepo); - - Cursor showTablesCursor = - logicalShowTablesMyHandler.handle(logicalShowTables, copiedContext); - - List tables = new ArrayList<>(); - Row showTablesResult = null; - while ((showTablesResult = showTablesCursor.next()) != null) { - if (showTablesResult.getColNum() >= 1 && showTablesResult.getString(0) != null) { - tables.add(showTablesResult.getString(0)); - } else { - new TddlRuntimeException(ErrorCode.ERR_INVALID_DDL_PARAMS, - "get tables name in reference database failed."); - } - } - return tables; - } - protected String getCreateTableSql(String schemaName, String tableName, ExecutionContext executionContext) { IRepository sourceTableRepository = ExecutorContext .getContext(schemaName) diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateIndexHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateIndexHandler.java index ae5a98e7c..0cdf457d6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateIndexHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateIndexHandler.java @@ -23,6 +23,7 @@ import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.druid.DbType; import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.druid.sql.ast.SQLIndexDefinition; @@ -90,14 +91,17 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e } boolean globalIndex = logicalCreateIndex.isClustered() || logicalCreateIndex.isGsi(); - boolean expressionIndex = isExpressionIndex(logicalCreateIndex, executionContext); + //mysql 80支持函数索引,直接下推,不用改写成虚拟列+索引 + boolean expressionIndex = + !InstanceVersion.isMYSQL80() && isExpressionIndex(logicalCreateIndex, executionContext); boolean isColumnar = logicalCreateIndex.isColumnar(); final Long versionId = DdlUtils.generateVersionId(executionContext); if (isColumnar) { return buildCreateColumnarIndexJob(logicalCreateIndex, versionId, executionContext); } else if (expressionIndex) { - if (!executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_CREATE_EXPRESSION_INDEX)) { + if (!InstanceVersion.isMYSQL80() && !executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_CREATE_EXPRESSION_INDEX)) { throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, "create expression index is not enabled"); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateTableHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateTableHandler.java index a470f649e..70872d587 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateTableHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalCreateTableHandler.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.ArchiveMode; import com.alibaba.polardbx.common.Engine; + import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; @@ -45,12 +46,19 @@ import com.alibaba.polardbx.executor.ddl.job.factory.ReimportTableJobFactory; import com.alibaba.polardbx.executor.ddl.job.factory.oss.CreatePartitionOssTableJobFactory; import com.alibaba.polardbx.executor.ddl.job.task.basic.InsertIntoTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.CheckAndPrepareColumnarIndexPartDefTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.PrepareCleanupIntervalTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlJobContext; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlTaskSqlBuilder; import com.alibaba.polardbx.executor.ddl.job.validator.ColumnValidator; import com.alibaba.polardbx.executor.ddl.job.validator.ConstraintValidator; import com.alibaba.polardbx.executor.ddl.job.validator.ForeignKeyValidator; import com.alibaba.polardbx.executor.ddl.job.validator.IndexValidator; import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.ddl.newengine.job.TransientDdlJob; import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlHelper; import com.alibaba.polardbx.executor.handler.LogicalShowCreateTableHandler; @@ -72,8 +80,8 @@ import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.config.table.DefaultExprUtil; import com.alibaba.polardbx.optimizer.config.table.GeneratedColumnUtil; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.CursorMeta; import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan; import com.alibaba.polardbx.optimizer.core.planner.Planner; import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; @@ -90,13 +98,17 @@ import com.alibaba.polardbx.optimizer.parse.visitor.FastSqlToCalciteNodeVisitor; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.common.PartitionTableType; -import com.alibaba.polardbx.optimizer.tablegroup.TableGroupInfoManager; -import com.alibaba.polardbx.optimizer.tablegroup.TableGroupUtils; -import io.grpc.netty.shaded.io.netty.util.internal.StringUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlArchiveKind; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlMetaValidationUtil; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.DDL; import org.apache.calcite.rel.ddl.CreateTable; import org.apache.calcite.rel.type.RelDataTypeField; +import com.alibaba.polardbx.optimizer.tablegroup.TableGroupInfoManager; +import com.alibaba.polardbx.optimizer.tablegroup.TableGroupUtils; +import io.grpc.netty.shaded.io.netty.util.internal.StringUtil; import org.apache.calcite.rel.type.RelDataTypeFieldImpl; import org.apache.calcite.rex.RexNode; import org.apache.calcite.sql.SqlCall; @@ -166,7 +178,6 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e if (returnImmediately) { return new TransientDdlJob(); } - } sqlCreateTable = (SqlCreateTable) logicalCreateTable.relDdl.sqlNode; @@ -199,17 +210,41 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e LikeTableInfo likeTableInfo = null; if (sqlCreateTable.getLikeTableName() != null) { - final String sourceCreateTableSql = generateCreateTableSqlForLike(sqlCreateTable, executionContext); + + SqlCreateTable createTableLikeSqlAst = null; + PlannerContext plannerContext = PlannerContext.fromExecutionContext(executionContext); + + Boolean[] needConvertToCreateArcCciArr = new Boolean[1]; + Boolean[] needIgnoreArchiveCciForCreateTableLikeArr = new Boolean[1]; + needConvertToCreateArcCciArr[0] = false; + needIgnoreArchiveCciForCreateTableLikeArr[0] = false; + checkIfAllowedCreatingTableLikeTtlDefinedTable(sqlCreateTable, executionContext, + needConvertToCreateArcCciArr, + needIgnoreArchiveCciForCreateTableLikeArr); + boolean needConvertToCreateArcCci = needConvertToCreateArcCciArr[0]; + boolean needIgnoreArchiveCciForCreateTableLike = needIgnoreArchiveCciForCreateTableLikeArr[0]; + if (needConvertToCreateArcCci) { + return buildCreateColumnarIndexJobForArchiveTable(logicalCreateTable, executionContext, + likeTableInfo); + } + + String sourceCreateTableSql = generateCreateTableSqlForLike(sqlCreateTable, executionContext); MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) FastsqlUtils.parseSql(sourceCreateTableSql).get(0); - stmt.getTableSource().setSimpleName(SqlIdentifier.surroundWithBacktick(logicalCreateTable.getTableName())); + + // remove arc cci of source ttl-table for new created tbl + if (needIgnoreArchiveCciForCreateTableLike) { + stmt.removeArchiveCciInfoForTtlDefinitionOptionIfNeed(); + } + // change table name to new created tbl + stmt.getTableSource() + .setSimpleName(SqlIdentifier.surroundWithBacktick(logicalCreateTable.getTableName())); + + // create table ast of target final String targetCreateTableSql = stmt.toString(); final SqlCreateTable targetTableAst = (SqlCreateTable) new FastsqlParser().parse(targetCreateTableSql, executionContext).get(0); - - PlannerContext plannerContext = PlannerContext.fromExecutionContext(executionContext); - SqlCreateTable createTableLikeSqlAst = (SqlCreateTable) - new FastsqlParser().parse(sourceCreateTableSql, executionContext).get(0); + createTableLikeSqlAst = targetTableAst; createTableLikeSqlAst.setSourceSql(targetTableAst.getSourceSql()); // handle engine @@ -231,9 +266,11 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e createTableLikeSqlAst.setArchiveMode(archiveMode); } - if (!Engine.isFileStore(engine) && archiveMode != null) { - throw GeneralUtil.nestedException( - "cannot create table using ARCHIVE_MODE if the engine of target table is INNODB."); + if (archiveMode != null) { + if (!Engine.isFileStore(engine)) { + throw GeneralUtil.nestedException( + "cannot create table using ARCHIVE_MODE if the engine of target table is INNODB."); + } } List dictColumns; @@ -283,6 +320,7 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e createTableLikeSqlAst.setLoadTableName( ((SqlIdentifier) sqlCreateTable.getLikeTableName()).getComponent(1).getLastName()); } else if (((SqlIdentifier) sqlCreateTable.getLikeTableName()).names.size() == 1) { + createTableLikeSqlAst.setLoadTableSchema(executionContext.getSchemaName()); createTableLikeSqlAst.setLoadTableName( ((SqlIdentifier) sqlCreateTable.getLikeTableName()).getComponent(0).getLastName()); } @@ -713,14 +751,17 @@ protected DdlJob buildCreatePartitionTableJob(LogicalCreateTable logicalCreateTa DdlPhyPlanBuilder createTableBuilder = new CreatePartitionTableBuilder(logicalCreateTable.relDdl, createTablePreparedData, executionContext, partitionTableType).build(); - PhysicalPlanData physicalPlanData = createTableBuilder.genPhysicalPlanData(); + buildTtlInfoIfNeed(logicalCreateTable, executionContext, createTableBuilder.getPartitionInfo(), + createTablePreparedData); + + PhysicalPlanData physicalPlanData = createTableBuilder.genPhysicalPlanData(); Engine tableEngine = ((SqlCreateTable) logicalCreateTable.relDdl.sqlNode).getEngine(); ArchiveMode archiveMode = ((SqlCreateTable) logicalCreateTable.relDdl.sqlNode).getArchiveMode(); List dictColumns = ((SqlCreateTable) logicalCreateTable.relDdl.sqlNode).getDictColumns(); - + CreateTableJobFactory ret = null; if (Engine.isFileStore(tableEngine)) { - CreatePartitionOssTableJobFactory ret = new CreatePartitionOssTableJobFactory( + ret = new CreatePartitionOssTableJobFactory( createTablePreparedData.isAutoPartition(), createTablePreparedData.isTimestampColumnDefault(), createTablePreparedData.getSpecialDefaultValues(), createTablePreparedData.getSpecialDefaultValueFlags(), @@ -733,7 +774,6 @@ protected DdlJob buildCreatePartitionTableJob(LogicalCreateTable logicalCreateTa } PartitionInfo partitionInfo = createTableBuilder.getPartitionInfo(); - if (logicalCreateTable.isReImportTable()) { return new ReimportTableJobFactory(createTablePreparedData.isAutoPartition(), createTablePreparedData.isTimestampColumnDefault(), @@ -743,7 +783,7 @@ protected DdlJob buildCreatePartitionTableJob(LogicalCreateTable logicalCreateTa physicalPlanData, executionContext, createTablePreparedData, partitionInfo).create(); } else { - CreatePartitionTableJobFactory ret = new CreatePartitionTableJobFactory( + ret = new CreatePartitionTableJobFactory( createTablePreparedData.isAutoPartition(), createTablePreparedData.isTimestampColumnDefault(), createTablePreparedData.getSpecialDefaultValues(), createTablePreparedData.getSpecialDefaultValueFlags(), @@ -758,6 +798,18 @@ protected DdlJob buildCreatePartitionTableJob(LogicalCreateTable logicalCreateTa } } + protected static void buildTtlInfoIfNeed(LogicalCreateTable logicalCreateTable, + ExecutionContext executionContext, + PartitionInfo logicalTablePartInfo, + CreateTablePreparedData primTablePreparedData) { + PartitionInfo partInfo = logicalTablePartInfo; + TableMeta tableMeta = primTablePreparedData.getTableMeta(); + TtlDefinitionInfo ttlDefinitionInfo = + TtlUtil.createTtlDefinitionInfoBySqlCreateTable((SqlCreateTable) logicalCreateTable.relDdl.sqlNode, + tableMeta, partInfo, executionContext); + primTablePreparedData.setTtlDefinitionInfo(ttlDefinitionInfo); + } + private DdlJob buildCreateTableWithGsiJob(LogicalCreateTable logicalCreateTable, ExecutionContext executionContext, LikeTableInfo likeTableInfo) { @@ -783,15 +835,23 @@ private DdlJob buildCreatePartitionTableWithGsiJob(LogicalCreateTable logicalCre CreateTableWithGsiPreparedData createTableWithGsiPreparedData = logicalCreateTable.getCreateTableWithGsiPreparedData(); createTableWithGsiPreparedData.getPrimaryTablePreparedData().setLikeTableInfo(likeTableInfo); + CreatePartitionTableWithGsiJobFactory ret = new CreatePartitionTableWithGsiJobFactory( logicalCreateTable.relDdl, createTableWithGsiPreparedData, executionContext ); + if (createTableWithGsiPreparedData.getPrimaryTablePreparedData().getSelectSql() != null) { ret.setSelectSql(createTableWithGsiPreparedData.getPrimaryTablePreparedData().getSelectSql()); } logicalCreateTable.setAffectedRows(ret.getAffectRows()); + + PartitionInfo primTblPartInfo = + ret.getCreatePartitionTableWithGsiBuilder().getPrimaryTableBuilder().getPartitionInfo(); + CreateTablePreparedData primPrepData = createTableWithGsiPreparedData.getPrimaryTablePreparedData(); + buildTtlInfoIfNeed(logicalCreateTable, executionContext, primTblPartInfo, primPrepData); + return ret.create(); } @@ -1078,4 +1138,192 @@ protected void normlizeSubPartitionBy(SqlSubPartitionBy subPartitionBy) { } } } + + protected DdlJob buildCreateColumnarIndexJobForArchiveTable(LogicalCreateTable logicalCreateTable, + ExecutionContext ec, + LikeTableInfo likeTableInfo) { + + SqlCreateTable sqlCreateTable = (SqlCreateTable) logicalCreateTable.relDdl.sqlNode; + SqlIdentifier sourceTableNameAst = (SqlIdentifier) sqlCreateTable.getLikeTableName(); + String sourceTableSchema = + SQLUtils.normalizeNoTrim( + sourceTableNameAst.names.size() > 1 ? sourceTableNameAst.names.get(0) : ec.getSchemaName()); + String sourceTableName = SQLUtils.normalizeNoTrim(sourceTableNameAst.getLastName()); + + String targetTableSchema = logicalCreateTable.getSchemaName(); + String targetTableName = logicalCreateTable.getTableName(); + + TtlDefinitionInfo ttlInfo = TtlUtil.getTtlDefInfoBySchemaAndTable(sourceTableSchema, sourceTableName, ec); + TtlMetaValidationUtil.validateAllowedBoundingArchiveTable(ttlInfo, ec, true, targetTableSchema, + targetTableName); + + String createViewSqlForArcTbl = + TtlTaskSqlBuilder.buildCreateViewSqlForArcTbl(targetTableSchema, targetTableName, ttlInfo); + String dropViewSqlForArcTbl = + TtlTaskSqlBuilder.buildDropViewSqlFroArcTbl(targetTableSchema, targetTableName, ttlInfo); + + List taskList = new ArrayList<>(); + + SubJobTask createViewSubJobTask = + new SubJobTask(targetTableSchema, createViewSqlForArcTbl, dropViewSqlForArcTbl); + createViewSubJobTask.setParentAcquireResource(true); + + String ttlTblSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlInfo.getTtlInfoRecord().getTableName(); + String modifyTtlBindArcTblSql = + TtlTaskSqlBuilder.buildModifyTtlSqlForBindArcTbl(ttlTblSchema, ttlTblName, targetTableSchema, + targetTableName, TtlArchiveKind.COLUMNAR); + String modifyTtlBindArcTblSqlForRollback = + TtlTaskSqlBuilder.buildModifyTtlSqlForBindArcTbl(ttlTblSchema, ttlTblName, "", "", + TtlArchiveKind.UNDEFINED); + SubJobTask modifyTtlForBindArcTblSubTask = + new SubJobTask(sourceTableSchema, modifyTtlBindArcTblSql, modifyTtlBindArcTblSqlForRollback); + modifyTtlForBindArcTblSubTask.setParentAcquireResource(true); + + TtlJobContext jobContext = TtlJobContext.buildFromTtlInfo(ttlInfo); + PrepareCleanupIntervalTask prepareClearIntervalTask = + new PrepareCleanupIntervalTask(sourceTableSchema, sourceTableName); + prepareClearIntervalTask.setJobContext(jobContext); + + CheckAndPrepareColumnarIndexPartDefTask prepareCreateCiSqlTask = + new CheckAndPrepareColumnarIndexPartDefTask(sourceTableSchema, sourceTableName, targetTableSchema, + targetTableName); + String createCiSqlForArcTblSubJobName = + TtlTaskSqlBuilder.buildSubJobTaskNameForCreateColumnarIndexBySpecifySubjobStmt(); + String dropCiSqlForArcTbl = + TtlTaskSqlBuilder.buildDropColumnarIndexSqlForArcTbl(ttlInfo, targetTableSchema, targetTableName); + SubJobTask createCiSubJobTask = + new SubJobTask(sourceTableSchema, createCiSqlForArcTblSubJobName, dropCiSqlForArcTbl); + createCiSubJobTask.setParentAcquireResource(true); + + // taskList.add(); + taskList.add(prepareClearIntervalTask); + taskList.add(prepareCreateCiSqlTask); + taskList.add(createCiSubJobTask);// create cci sql + taskList.add(createViewSubJobTask);// create view sql + taskList.add(modifyTtlForBindArcTblSubTask);// modify ttl setting + + ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); + executableDdlJob.addSequentialTasks(taskList); + executableDdlJob.getExcludeResources().add(sourceTableSchema); + executableDdlJob.getExcludeResources().add(sourceTableName); + executableDdlJob.getExcludeResources().add(targetTableSchema); + executableDdlJob.getExcludeResources().add(targetTableName); + + return executableDdlJob; + } + + // boolean needIgnoreArchiveCciForCreateTableLike = false; +// boolean needConvertToCreateArcCci = false; + protected void checkIfAllowedCreatingTableLikeTtlDefinedTable( + SqlCreateTable sqlCreateTable, + ExecutionContext executionContext, + Boolean[] needConvertToCreateArcCciOutput, + Boolean[] needIgnoreArchiveCciForCreateTableLikeOutput + ) { + boolean createTblLikeTtlDefinedTbl = + TtlUtil.checkIfCreateArcTblLikeRowLevelTtl(sqlCreateTable, executionContext); + boolean useArchiveMode = sqlCreateTable.getArchiveMode() == ArchiveMode.TTL; + boolean specifyColumnarEngine = sqlCreateTable.getEngine() == Engine.COLUMNAR; + + boolean needConvertToCreateArcCci = false; + boolean needIgnoreArchiveCciForCreateTableLike = false; + if (createTblLikeTtlDefinedTbl) { + + if (useArchiveMode && specifyColumnarEngine) { + /** + * case 1: + * Convert + * "create table arc_tbl like ttl_tbl engine='columnar' archive_mode='ttl'" + * to + * "Create Cluster Columnar Index ci on ttl_tbl(ttl_col)" + */ + needConvertToCreateArcCci = true; + } else { + /** + * case 2: + * "create table normal_tbl like ttl_tbl engine='columnar'" + * or + * "create table normal_tbl like ttl_tbl archive_mode='ttl'" + * or + * "create table normal_tbl like ttl_tbl engine='oss' archive_mode='ttl'" (local partition) + * or + * "create table normal_tbl like ttl_tbl ..." + */ + + if (useArchiveMode || specifyColumnarEngine) { + /** + * case 2-1: + * "create table normal_tbl like ttl_tbl engine='columnar'" + * or + * case 2-2: + * "create table normal_tbl like ttl_tbl archive_mode='ttl'" + * case 2-3: + * "create table normal_tbl like ttl_tbl engine='oss' archive_mode='ttl'" (local partition) + */ + throw GeneralUtil.nestedException( + String.format( + "failed to create archive table for a ttl-defined table without specifying both engine=%s and archive_mode='%s'", + Engine.COLUMNAR, ArchiveMode.TTL)); + } else { + /** + * or + * case 2-4: + * "create table normal_tbl like ttl_tbl ..." + */ + boolean allowCreateTblLikeIgnoreTtlDef = executionContext.getParamManager() + .getBoolean(ConnectionParams.ALLOW_CREATE_TABLE_LIKE_IGNORE_ARCHIVE_CCI); + TtlDefinitionInfo ttlInfo = + TtlUtil.fetchTtlInfoFromCreateTableLikeAst(sqlCreateTable, executionContext); + if (ttlInfo.performArchiveByColumnarIndex()) { + if (!allowCreateTblLikeIgnoreTtlDef) { + throw GeneralUtil.nestedException( + "cannot create table like a ttl-defined table, please use the hint /*TDDL:cmd_extra(ALLOW_CREATE_TABLE_LIKE_IGNORE_ARCHIVE_CCI=true)*/ to do table creating"); + } else { + needIgnoreArchiveCciForCreateTableLike = true; + } + } + } + + } + } else { + /** + * case 4: + * "create table normal_tbl like non_ttl_tbl engine='columnar'" + * or + * "create table normal_tbl like non_ttl_tbl archive_mode='ttl'" + * or + * "create table normal_tbl like non_ttl_tbl engine='oss' archive_mode='ttl'" (local partition) + * or + * "create table normal_tbl like non_ttl_tbl ..." + */ + + if (specifyColumnarEngine) { + /** + * case 3-1: + * "create table normal_tbl like non_ttl_tbl engine='columnar' archive_mode='ttl'" + * or + * case 3-2: + * "create table normal_tbl like non_ttl_tbl engine='columnar'" + */ + throw GeneralUtil.nestedException( + String.format( + "failed to create table like with engine='%s' archive_mode='%s' because the source table is not a ttl-defined table", + Engine.COLUMNAR, ArchiveMode.TTL)); + } else { + /** + * Ignore handling + */ + } + } + if (needConvertToCreateArcCciOutput != null && needConvertToCreateArcCciOutput.length > 0) { + needConvertToCreateArcCciOutput[0] = needConvertToCreateArcCci; + } + + if (needIgnoreArchiveCciForCreateTableLikeOutput != null + && needIgnoreArchiveCciForCreateTableLikeOutput.length > 0) { + needIgnoreArchiveCciForCreateTableLikeOutput[0] = needIgnoreArchiveCciForCreateTableLike; + } + } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropDatabaseHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropDatabaseHandler.java index d20768d0d..a4e85e29e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropDatabaseHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropDatabaseHandler.java @@ -19,7 +19,6 @@ import com.alibaba.polardbx.common.TddlConstants; import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; import com.alibaba.polardbx.common.cdc.CdcManagerHelper; -import com.alibaba.polardbx.common.ddl.foreignkey.ForeignKeyData; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.properties.ConnectionParams; @@ -38,6 +37,7 @@ import com.alibaba.polardbx.executor.sync.DropDbRelatedProcedureSyncAction; import com.alibaba.polardbx.executor.sync.GsiStatisticsSyncAction; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.sync.SyncScope; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.gms.topology.DbInfoRecord; @@ -106,6 +106,7 @@ public Cursor handleByGms(RelNode logicalPlan, ExecutionContext executionContext dropDbInfo.setTs(ts); Long socketTimeout = executionContext.getParamManager().getLong(ConnectionParams.SOCKET_TIMEOUT); dropDbInfo.setSocketTimeout(socketTimeout == null ? -1 : socketTimeout); + dropDbInfo.setVersionId(DdlUtils.generateVersionId(executionContext)); DbTopologyManager.dropLogicalDb(dropDbInfo); CdcManagerHelper.getInstance() diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropIndexHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropIndexHandler.java index 6e0e4b8fd..206ca1ef8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropIndexHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropIndexHandler.java @@ -47,6 +47,8 @@ import java.util.Map; import java.util.Set; +import static org.apache.calcite.sql.SqlIdentifier.surroundWithBacktick; + /** * DROP INDEX xxx ON xxx * @@ -157,14 +159,14 @@ public static DdlTask genRenameLocalIndexTask(RenameLocalIndexPreparedData renam if (renameIndexPreparedData != null) { String newRenameIndex = String.format( "/*+TDDL:cmd_extra(DDL_ON_GSI=true)*/alter table %s rename index %s to %s", - renameIndexPreparedData.getTableName(), - renameIndexPreparedData.getOrgIndexName(), - renameIndexPreparedData.getNewIndexName()); + surroundWithBacktick(renameIndexPreparedData.getTableName()), + surroundWithBacktick(renameIndexPreparedData.getOrgIndexName()), + surroundWithBacktick(renameIndexPreparedData.getNewIndexName())); String rollbackRenameIndex = String.format( "/*+TDDL:cmd_extra(DDL_ON_GSI=true)*/alter table %s rename index %s to %s", - renameIndexPreparedData.getTableName(), - renameIndexPreparedData.getNewIndexName(), - renameIndexPreparedData.getOrgIndexName()); + surroundWithBacktick(renameIndexPreparedData.getTableName()), + surroundWithBacktick(renameIndexPreparedData.getNewIndexName()), + surroundWithBacktick(renameIndexPreparedData.getOrgIndexName())); SubJobTask ddlTask = new SubJobTask( renameIndexPreparedData.getSchemaName(), newRenameIndex, rollbackRenameIndex); ddlTask.setParentAcquireResource(true); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropTableHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropTableHandler.java index 730625c05..8c6730ed5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropTableHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropTableHandler.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.CaseInsensitive; import com.alibaba.polardbx.executor.common.RecycleBin; import com.alibaba.polardbx.executor.common.RecycleBinManager; import com.alibaba.polardbx.executor.ddl.job.builder.DdlPhyPlanBuilder; @@ -36,16 +37,20 @@ import com.alibaba.polardbx.executor.ddl.job.factory.PureCdcDdlMark4DropTableJobFactory; import com.alibaba.polardbx.executor.ddl.job.factory.RecycleOssTableJobFactory; import com.alibaba.polardbx.executor.ddl.job.factory.RenameTableJobFactory; +import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcTruncateWithRecycleMarkTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlTaskSqlBuilder; import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlHelper; import com.alibaba.polardbx.executor.spi.IRepository; import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.metadb.limit.LimitValidator; import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.archive.CheckOSSArchiveUtil; import com.alibaba.polardbx.optimizer.config.table.TableMeta; @@ -56,6 +61,9 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.data.DropTablePreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.RenameTablePreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.DropTableWithGsiPreparedData; +import com.alibaba.polardbx.optimizer.ttl.TtlArchiveKind; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; import org.apache.calcite.rel.ddl.RenameTable; import org.apache.calcite.sql.SqlDropTable; import org.apache.calcite.sql.SqlIdentifier; @@ -63,8 +71,12 @@ import org.apache.calcite.sql.SqlRenameTable; import org.apache.calcite.sql.parser.SqlParserPos; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; public class LogicalDropTableHandler extends LogicalCommonDdlHandler { @@ -81,11 +93,21 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e logicalDropTable.setImportTable(true); } + String targetSchemaName = logicalDropTable.getSchemaName(); + String targetTableName = logicalDropTable.getTableName(); + tryForbidDropTableOperationIfNeed(executionContext, targetSchemaName, targetTableName); + boolean checkIfArcTblViewOfTtlTblWithCci = + TtlUtil.checkIfDropArcTblViewOfTtlTableWithCci(targetSchemaName, targetTableName, executionContext); + if (checkIfArcTblViewOfTtlTblWithCci) { + return buildDropArchiveTableViewForTtlTableJob(logicalDropTable, executionContext); + } + if (executionContext.getParamManager().getBoolean(ConnectionParams.PURGE_FILE_STORAGE_TABLE) && logicalDropTable.isPurge()) { LogicalRenameTableHandler.makeTableVisible(logicalDropTable.getSchemaName(), logicalDropTable.getTableName(), executionContext); } + logicalDropTable.prepareData(); if (logicalDropTable.ifExists()) { @@ -108,7 +130,6 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e logicalDropTable.setDdlVersionId(versionId); boolean isNewPartDb = DbInfoManager.getInstance().isNewPartitionDb(logicalDropTable.getSchemaName()); - CheckOSSArchiveUtil.checkWithoutOSS(logicalDropTable.getSchemaName(), logicalDropTable.getTableName()); if (!isNewPartDb) { if (logicalDropTable.isWithGsi()) { @@ -152,6 +173,16 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e } } + private static void tryForbidDropTableOperationIfNeed(ExecutionContext executionContext, String targetSchemaName, String targetTableName) { + boolean allowDropTblOp = + TtlUtil.checkIfAllowedDropTableOperation(targetSchemaName, targetTableName, executionContext); + if (!allowDropTblOp) { + throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, + String.format("Forbid to drop the ttl-defined table `%s`.`%s` with archive cci, please use the hint /*TDDL:cmd_extra(TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI=false)*/ to drop this table", targetSchemaName, + targetTableName)); + } + } + @Override protected boolean validatePlan(BaseDdlOperation logicalDdlPlan, ExecutionContext executionContext) { final SqlDropTable sqlDropTable = (SqlDropTable) logicalDdlPlan.getNativeSqlNode(); @@ -163,14 +194,20 @@ protected boolean validatePlan(BaseDdlOperation logicalDdlPlan, ExecutionContext TableValidator.validateTableName(logicalTableName); final boolean tableExists = TableValidator.checkIfTableExists(schemaName, logicalTableName); + final boolean arcTblViewForTtlTblWithCci = + TtlUtil.checkIfDropArcTblViewOfTtlTableWithCci(schemaName, logicalTableName, executionContext); if (!tableExists && sqlDropTable.isIfExists()) { // do nothing } else if (isImportTable) { //do nothing - } else if (!tableExists) { + } else if (!tableExists && !arcTblViewForTtlTblWithCci) { throw new TddlRuntimeException(ErrorCode.ERR_UNKNOWN_TABLE, schemaName, logicalTableName); } + if (arcTblViewForTtlTblWithCci) { + return false; + } + // can't drop table where referencing by other tables final boolean checkForeignKey = executionContext.foreignKeyChecks(); @@ -339,4 +376,54 @@ private DdlJob buildDropPartitionTableWithGsiJob(LogicalDropTable logicalDropTab ).create(); } + private DdlJob buildDropArchiveTableViewForTtlTableJob(LogicalDropTable logicalDropTable, + ExecutionContext executionContext) { + + String arcTblSchema = logicalDropTable.getSchemaName(); + String arcTblName = logicalDropTable.getTableName(); + TtlInfoRecord ttlInfoRec = TtlUtil.fetchTtlDefinitionInfoByArcDbAndArcTb(arcTblSchema, arcTblName); + String ttlTblSchema = ttlInfoRec.getTableSchema(); + String ttlTblName = ttlInfoRec.getTableName(); + TableMeta ttlTblMeta = executionContext.getSchemaManager(ttlTblSchema).getTable(ttlTblName); + TtlDefinitionInfo ttlInfo = ttlTblMeta.getTtlDefinitionInfo(); + + List taskList = new ArrayList<>(); + String dropCiSqlForArcTbl = + TtlTaskSqlBuilder.buildDropColumnarIndexSqlForArcTbl(ttlInfo, arcTblSchema, arcTblName); + SubJobTask dropCiSubJobTask = new SubJobTask(ttlTblSchema, dropCiSqlForArcTbl, ""); + dropCiSubJobTask.setParentAcquireResource(true); + + String dropViewSqlForArcTbl = TtlTaskSqlBuilder.buildDropViewSqlFroArcTbl(arcTblSchema, arcTblName, ttlInfo); + SubJobTask dropViewSubJobTask = new SubJobTask(arcTblSchema, dropViewSqlForArcTbl, ""); + dropViewSubJobTask.setParentAcquireResource(true); + + String currArcTblSchema = ttlInfo.getArchiveTableSchema(); + String currArcTblName = ttlInfo.getArchiveTableName(); + + String modifyTtlUnbindArcTblSql = + TtlTaskSqlBuilder.buildModifyTtlSqlForBindArcTbl(ttlTblSchema, ttlTblName, "", "", + TtlArchiveKind.UNDEFINED); + String modifyTtlUnbindArcTblSqlForRollback = + TtlTaskSqlBuilder.buildModifyTtlSqlForBindArcTbl(ttlTblSchema, ttlTblName, currArcTblSchema, currArcTblName, + TtlArchiveKind.COLUMNAR); + SubJobTask modifyTtlForUnbindArcTblSubTask = + new SubJobTask(ttlTblSchema, modifyTtlUnbindArcTblSql, modifyTtlUnbindArcTblSqlForRollback); + modifyTtlForUnbindArcTblSubTask.setParentAcquireResource(true); + + taskList.add(modifyTtlForUnbindArcTblSubTask); + taskList.add(dropViewSubJobTask); + taskList.add(dropCiSubJobTask); + + ExecutableDdlJob executableDdlJob = new ExecutableDdlJob(); + executableDdlJob.addSequentialTasks(taskList); + Set resources = new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + resources.add(ttlTblSchema); + resources.add(ttlTblName); + resources.add(arcTblSchema); + resources.add(arcTblName); + + executableDdlJob.addExcludeResources(resources); + + return executableDdlJob; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropViewHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropViewHandler.java index 824a597fa..78bd7bf59 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropViewHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalDropViewHandler.java @@ -39,6 +39,7 @@ public LogicalDropViewHandler(IRepository repo) { @Override protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext executionContext) { + return new DropViewJobFactory((LogicalDropView) logicalDdlPlan).create(); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalInsertOverwriteHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalInsertOverwriteHandler.java index 7a347af42..3e1a91eb9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalInsertOverwriteHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalInsertOverwriteHandler.java @@ -25,6 +25,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; import com.alibaba.polardbx.executor.ddl.newengine.job.wrapper.ExecutableDdlJob4InsertOverwrite; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; import com.alibaba.polardbx.gms.metadb.misc.DdlEngineTaskAccessor; import com.alibaba.polardbx.gms.metadb.misc.DdlEngineTaskRecord; @@ -97,6 +98,9 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e truncateTableWithGsiPreparedData.setTmpIndexTableMap(tmpIndexTableMap); truncateTableWithGsiPreparedData.setLogicalCreateTable(logicalCreateTable); truncateTableWithGsiPreparedData.setTmpTableSuffix(tmpTableSuffix); + if (truncateTableWithGsiPreparedData.isHasColumnarIndex()) { + truncateTableWithGsiPreparedData.setVersionId(DdlUtils.generateVersionId(executionContext)); + } return new InsertOverwriteJobFactory(truncateTableWithGsiPreparedData, executionContext.getOriginSql(), executionContext).create(); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalOptimizeTableHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalOptimizeTableHandler.java index 0f731f44c..64ca8533b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalOptimizeTableHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalOptimizeTableHandler.java @@ -22,11 +22,14 @@ import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; import com.alibaba.polardbx.executor.ddl.job.builder.DirectPhysicalSqlPlanBuilder; import com.alibaba.polardbx.executor.ddl.job.task.basic.OptimizeTablePhyDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlJobUtil; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJobFactory; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.spi.IRepository; import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.rel.ddl.BaseDdlOperation; @@ -45,6 +48,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * OPTIMIZE TABLE @@ -89,6 +93,11 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e @Override protected Cursor buildResultCursor(BaseDdlOperation logicalDdlPlan, DdlJob ddlJob, ExecutionContext ec) { + + if (ec.getDdlContext().isAsyncMode()) { + return super.buildResultCursor(logicalDdlPlan, ddlJob, ec); + } + ArrayResultCursor result = new ArrayResultCursor("OptimizeTable"); result.addColumn("Table", DataTypes.StringType); result.addColumn("Op", DataTypes.StringType); @@ -145,10 +154,26 @@ private List> extractTableList(List tableNameSqlNo String table = ((SqlIdentifier) sqlNode).getLastName(); result.add(Pair.of(schema, table)); - List gsiNames = GlobalIndexMeta.getPublishedIndexNames(table, schema, ec); - if (CollectionUtils.isNotEmpty(gsiNames)) { - for (String gsi : gsiNames) { - result.add(Pair.of(schema, gsi)); +// List gsiNames = GlobalIndexMeta.getPublishedIndexNames(table, schema, ec); +// if (CollectionUtils.isNotEmpty(gsiNames)) { +// for (String gsi : gsiNames) { +// result.add(Pair.of(schema, gsi)); +// } +// } + + /** + * The target table names of optimize table should ignore cci + */ + final TableMeta tableMeta = ec.getSchemaManager(schema).getTable(table); + Map gsiBeans = tableMeta.getGsiPublished(); + if (gsiBeans != null && !gsiBeans.isEmpty()) { + for (String gsiName : gsiBeans.keySet()) { + GsiMetaManager.GsiIndexMetaBean gsiBean = gsiBeans.get(gsiName); + if (gsiBean != null) { + + continue; + } + result.add(Pair.of(schema, gsiName)); } } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalRenameTablesHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalRenameTablesHandler.java index 23b0b9ce8..03730a55a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalRenameTablesHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalRenameTablesHandler.java @@ -24,6 +24,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.job.DdlJob; import com.alibaba.polardbx.executor.ddl.newengine.job.ExecutableDdlJob; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.BaseDdlOperation; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalRenameTables; @@ -33,7 +34,9 @@ import org.apache.calcite.sql.SqlRenameTables; import org.apache.calcite.util.Pair; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; @@ -60,9 +63,13 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e ValidateTableVersionTask validateTableVersionTask = new ValidateTableVersionTask(logicalDdlPlan.getSchemaName(), tableVersions); + List versionIds = new ArrayList<>(); + for (int i = 0; i < renameTablesPreparedData.getFromTableNames().size(); i++) { + versionIds.add(DdlUtils.generateVersionId(executionContext)); + } ExecutableDdlJob result = new RenameTablesJobFactory(logicalDdlPlan.getSchemaName(), renameTablesPreparedData, - executionContext).create(); + executionContext, versionIds).create(); result.addTask(validateTableVersionTask); result.addTaskRelationship(validateTableVersionTask, result.getHead()); return result; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalTruncateTableHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalTruncateTableHandler.java index 4d66e304b..836a820e3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalTruncateTableHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/ddl/LogicalTruncateTableHandler.java @@ -33,6 +33,7 @@ import com.alibaba.polardbx.executor.ddl.job.factory.CreateTableJobFactory; import com.alibaba.polardbx.executor.ddl.job.factory.TruncateTableJobFactory; import com.alibaba.polardbx.executor.ddl.job.factory.gsi.TruncateTableWithGsiJobFactory; +import com.alibaba.polardbx.executor.ddl.job.task.basic.TablesSyncTask; import com.alibaba.polardbx.executor.ddl.job.task.basic.TruncateTableRecycleBinTask; import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcTruncateWithRecycleMarkTask; import com.alibaba.polardbx.executor.ddl.job.task.gsi.ValidateTableVersionTask; @@ -43,6 +44,7 @@ import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlHelper; import com.alibaba.polardbx.executor.handler.LogicalShowCreateTableHandler; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.utils.DdlUtils; import com.alibaba.polardbx.gms.locality.LocalityDesc; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.topology.DbInfoManager; @@ -70,6 +72,7 @@ import com.alibaba.polardbx.optimizer.parse.visitor.ContextParameters; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import org.apache.calcite.rel.ddl.CreateTable; import org.apache.calcite.sql.SqlCreateTable; import org.apache.calcite.sql.SqlIdentifier; @@ -116,7 +119,7 @@ protected DdlJob buildDdlJob(BaseDdlOperation logicalDdlPlan, ExecutionContext e } } } else { - if (logicalTruncateTable.isWithGsi() || logicalTruncateTable.hasColumnarIndex()) { + if (logicalTruncateTable.isWithGsi()) { return buildTruncateTableWithGsiJob(logicalTruncateTable, true, executionContext); } else { return buildTruncatePartitionTableJob(logicalTruncateTable, executionContext); @@ -142,7 +145,8 @@ private DdlJob buildTruncateTableJob(LogicalTruncateTable logicalTruncateTable, .genPhysicalPlanData(); return new TruncateTableJobFactory(physicalPlanData, - logicalTruncateTable.getTruncateTableWithGsiPreparedData().getTableVersion()).create(); + logicalTruncateTable.getTruncateTableWithGsiPreparedData().getTableVersion(), DEFAULT_DDL_VERSION_ID, + false).create(); } private DdlJob handleRecycleBin(LogicalTruncateTable logicalTruncateTable, ExecutionContext executionContext) { @@ -154,14 +158,14 @@ private DdlJob handleRecycleBin(LogicalTruncateTable logicalTruncateTable, Execu String createTableSql = DdlHelper.genCreateTableSql(tableNameNode, executionContext).toLowerCase(); createTableSql = createTableSql.replaceFirst(tableName, tmpBinName); - SqlNode newTableNameNode = new SqlIdentifier(tmpBinName, SqlParserPos.ZERO); createTableSql = CDC_RECYCLE_HINTS + createTableSql; SqlCreateTable sqlCreateTable = (SqlCreateTable) new FastsqlParser().parse(createTableSql).get(0); - CreateTable createTable = - CreateTable.create(logicalTruncateTable.getCluster(), sqlCreateTable, newTableNameNode, null, null); - LogicalCreateTable logicalCreateTable = LogicalCreateTable.create(createTable); + PlannerContext plannerContext = PlannerContext.fromExecutionContext(executionContext); + + ExecutionPlan createTablePlan = Planner.getInstance().getPlan(sqlCreateTable, plannerContext); + LogicalCreateTable logicalCreateTable = (LogicalCreateTable) createTablePlan.getPlan(); Map tableVersions = new HashMap<>(); tableVersions.put(tableName, logicalTruncateTable.getTruncateTableWithGsiPreparedData().getTableVersion()); @@ -182,12 +186,15 @@ private DdlJob handleRecycleBin(LogicalTruncateTable logicalTruncateTable, Execu tableName, binName); CdcTruncateWithRecycleMarkTask cdcTask2 = new CdcTruncateWithRecycleMarkTask(executionContext.getSchemaName(), tmpBinName, tableName); + TablesSyncTask tablesSyncTask = + new TablesSyncTask(executionContext.getSchemaName(), Lists.newArrayList(tableName, binName, tmpBinName)); truncateWithRecycleBinJob.addTask(truncateTableRecycleBinTask); truncateWithRecycleBinJob.addTaskRelationship(tableSyncTask, cdcTask1); truncateWithRecycleBinJob.addTaskRelationship(cdcTask1, cdcTask2); truncateWithRecycleBinJob.addTaskRelationship(cdcTask2, truncateTableRecycleBinTask); - truncateWithRecycleBinJob.labelAsTail(truncateTableRecycleBinTask); + truncateWithRecycleBinJob.addTaskRelationship(truncateTableRecycleBinTask, tablesSyncTask); + truncateWithRecycleBinJob.labelAsTail(tablesSyncTask); recycleBin.add(binName, tableName); @@ -246,6 +253,9 @@ private DdlJob buildTruncateTableWithGsiJob(LogicalTruncateTable logicalTruncate truncateTableWithGsiPreparedData.setTmpIndexTableMap(tmpIndexTableMap); truncateTableWithGsiPreparedData.setLogicalCreateTable(logicalCreateTable); truncateTableWithGsiPreparedData.setTmpTableSuffix(tmpTableSuffix); + if (truncateTableWithGsiPreparedData.isHasColumnarIndex()) { + truncateTableWithGsiPreparedData.setVersionId(DdlUtils.generateVersionId(executionContext)); + } return new TruncateTableWithGsiJobFactory( truncateTableWithGsiPreparedData, @@ -255,6 +265,8 @@ private DdlJob buildTruncateTableWithGsiJob(LogicalTruncateTable logicalTruncate private DdlJob buildTruncatePartitionTableJob(LogicalTruncateTable logicalTruncateTable, ExecutionContext executionContext) { + long versionId = DdlUtils.generateVersionId(executionContext); + TruncateTablePreparedData truncateTablePreparedData = logicalTruncateTable.getTruncateTableWithGsiPreparedData().getPrimaryTablePreparedData(); @@ -264,7 +276,8 @@ private DdlJob buildTruncatePartitionTableJob(LogicalTruncateTable logicalTrunca PhysicalPlanData physicalPlanData = truncateTableBuilder.genPhysicalPlanData(); return new TruncateTableJobFactory(physicalPlanData, - logicalTruncateTable.getTruncateTableWithGsiPreparedData().getTableVersion()).create(); + logicalTruncateTable.getTruncateTableWithGsiPreparedData().getTableVersion(), versionId, + logicalTruncateTable.isWithCci()).create(); } public LogicalCreateTable generateLogicalCreateTmpTable(String schemaName, String targetTableName, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaCollationsHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaCollationsHandler.java index 88fa1b56e..9c0a45327 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaCollationsHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaCollationsHandler.java @@ -32,6 +32,280 @@ public InformationSchemaCollationsHandler(VirtualViewHandler virtualViewHandler) super(virtualViewHandler); } + public static Object[][] COLLATIONS = new Object[][] { + {"armscii8_general_ci", "armscii8", 32, "Yes", "Yes", 1, "PAD SPACE"}, + {"armscii8_bin", "armscii8", 64, "", "Yes", 1, "PAD SPACE"}, + {"ascii_general_ci", "ascii", 11, "Yes", "Yes", 1, "PAD SPACE"}, + {"ascii_bin", "ascii", 65, "", "Yes", 1, "PAD SPACE"}, + {"big5_chinese_ci", "big5", 1, "Yes", "Yes", 1, "PAD SPACE"}, + {"big5_bin", "big5", 84, "", "Yes", 1, "PAD SPACE"}, + {"binary", "binary", 63, "Yes", "Yes", 1, "NO PAD"}, + {"cp1250_general_ci", "cp1250", 26, "Yes", "Yes", 1, "PAD SPACE"}, + {"cp1250_czech_cs", "cp1250", 34, "", "Yes", 2, "PAD SPACE"}, + {"cp1250_croatian_ci", "cp1250", 44, "", "Yes", 1, "PAD SPACE"}, + {"cp1250_bin", "cp1250", 66, "", "Yes", 1, "PAD SPACE"}, + {"cp1250_polish_ci", "cp1250", 99, "", "Yes", 1, "PAD SPACE"}, + {"cp1251_bulgarian_ci", "cp1251", 14, "", "Yes", 1, "PAD SPACE"}, + {"cp1251_ukrainian_ci", "cp1251", 23, "", "Yes", 1, "PAD SPACE"}, + {"cp1251_bin", "cp1251", 50, "", "Yes", 1, "PAD SPACE"}, + {"cp1251_general_ci", "cp1251", 51, "Yes", "Yes", 1, "PAD SPACE"}, + {"cp1251_general_cs", "cp1251", 52, "", "Yes", 1, "PAD SPACE"}, + {"cp1256_general_ci", "cp1256", 57, "Yes", "Yes", 1, "PAD SPACE"}, + {"cp1256_bin", "cp1256", 67, "", "Yes", 1, "PAD SPACE"}, + {"cp1257_lithuanian_ci", "cp1257", 29, "", "Yes", 1, "PAD SPACE"}, + {"cp1257_bin", "cp1257", 58, "", "Yes", 1, "PAD SPACE"}, + {"cp1257_general_ci", "cp1257", 59, "Yes", "Yes", 1, "PAD SPACE"}, + {"cp850_general_ci", "cp850", 4, "Yes", "Yes", 1, "PAD SPACE"}, + {"cp850_bin", "cp850", 80, "", "Yes", 1, "PAD SPACE"}, + {"cp852_general_ci", "cp852", 40, "Yes", "Yes", 1, "PAD SPACE"}, + {"cp852_bin", "cp852", 81, "", "Yes", 1, "PAD SPACE"}, + {"cp866_general_ci", "cp866", 36, "Yes", "Yes", 1, "PAD SPACE"}, + {"cp866_bin", "cp866", 68, "", "Yes", 1, "PAD SPACE"}, + {"cp932_japanese_ci", "cp932", 95, "Yes", "Yes", 1, "PAD SPACE"}, + {"cp932_bin", "cp932", 96, "", "Yes", 1, "PAD SPACE"}, + {"dec8_swedish_ci", "dec8", 3, "Yes", "Yes", 1, "PAD SPACE"}, + {"dec8_bin", "dec8", 69, "", "Yes", 1, "PAD SPACE"}, + {"eucjpms_japanese_ci", "eucjpms", 97, "Yes", "Yes", 1, "PAD SPACE"}, + {"eucjpms_bin", "eucjpms", 98, "", "Yes", 1, "PAD SPACE"}, + {"euckr_korean_ci", "euckr", 19, "Yes", "Yes", 1, "PAD SPACE"}, + {"euckr_bin", "euckr", 85, "", "Yes", 1, "PAD SPACE"}, + {"gb18030_chinese_ci", "gb18030", 248, "Yes", "Yes", 2, "PAD SPACE"}, + {"gb18030_bin", "gb18030", 249, "", "Yes", 1, "PAD SPACE"}, + {"gb18030_unicode_520_ci", "gb18030", 250, "", "Yes", 8, "PAD SPACE"}, + {"gb2312_chinese_ci", "gb2312", 24, "Yes", "Yes", 1, "PAD SPACE"}, + {"gb2312_bin", "gb2312", 86, "", "Yes", 1, "PAD SPACE"}, + {"gbk_chinese_ci", "gbk", 28, "Yes", "Yes", 1, "PAD SPACE"}, + {"gbk_bin", "gbk", 87, "", "Yes", 1, "PAD SPACE"}, + {"geostd8_general_ci", "geostd8", 92, "Yes", "Yes", 1, "PAD SPACE"}, + {"geostd8_bin", "geostd8", 93, "", "Yes", 1, "PAD SPACE"}, + {"greek_general_ci", "greek", 25, "Yes", "Yes", 1, "PAD SPACE"}, + {"greek_bin", "greek", 70, "", "Yes", 1, "PAD SPACE"}, + {"hebrew_general_ci", "hebrew", 16, "Yes", "Yes", 1, "PAD SPACE"}, + {"hebrew_bin", "hebrew", 71, "", "Yes", 1, "PAD SPACE"}, + {"hp8_english_ci", "hp8", 6, "Yes", "Yes", 1, "PAD SPACE"}, + {"hp8_bin", "hp8", 72, "", "Yes", 1, "PAD SPACE"}, + {"keybcs2_general_ci", "keybcs2", 37, "Yes", "Yes", 1, "PAD SPACE"}, + {"keybcs2_bin", "keybcs2", 73, "", "Yes", 1, "PAD SPACE"}, + {"koi8r_general_ci", "koi8r", 7, "Yes", "Yes", 1, "PAD SPACE"}, + {"koi8r_bin", "koi8r", 74, "", "Yes", 1, "PAD SPACE"}, + {"koi8u_general_ci", "koi8u", 22, "Yes", "Yes", 1, "PAD SPACE"}, + {"koi8u_bin", "koi8u", 75, "", "Yes", 1, "PAD SPACE"}, + {"latin1_german1_ci", "latin1", 5, "", "Yes", 1, "PAD SPACE"}, + {"latin1_swedish_ci", "latin1", 8, "Yes", "Yes", 1, "PAD SPACE"}, + {"latin1_danish_ci", "latin1", 15, "", "Yes", 1, "PAD SPACE"}, + {"latin1_german2_ci", "latin1", 31, "", "Yes", 2, "PAD SPACE"}, + {"latin1_bin", "latin1", 47, "", "Yes", 1, "PAD SPACE"}, + {"latin1_general_ci", "latin1", 48, "", "Yes", 1, "PAD SPACE"}, + {"latin1_general_cs", "latin1", 49, "", "Yes", 1, "PAD SPACE"}, + {"latin1_spanish_ci", "latin1", 94, "", "Yes", 1, "PAD SPACE"}, + {"latin2_czech_cs", "latin2", 2, "", "Yes", 4, "PAD SPACE"}, + {"latin2_general_ci", "latin2", 9, "Yes", "Yes", 1, "PAD SPACE"}, + {"latin2_hungarian_ci", "latin2", 21, "", "Yes", 1, "PAD SPACE"}, + {"latin2_croatian_ci", "latin2", 27, "", "Yes", 1, "PAD SPACE"}, + {"latin2_bin", "latin2", 77, "", "Yes", 1, "PAD SPACE"}, + {"latin5_turkish_ci", "latin5", 30, "Yes", "Yes", 1, "PAD SPACE"}, + {"latin5_bin", "latin5", 78, "", "Yes", 1, "PAD SPACE"}, + {"latin7_estonian_cs", "latin7", 20, "", "Yes", 1, "PAD SPACE"}, + {"latin7_general_ci", "latin7", 41, "Yes", "Yes", 1, "PAD SPACE"}, + {"latin7_general_cs", "latin7", 42, "", "Yes", 1, "PAD SPACE"}, + {"latin7_bin", "latin7", 79, "", "Yes", 1, "PAD SPACE"}, + {"macce_general_ci", "macce", 38, "Yes", "Yes", 1, "PAD SPACE"}, + {"macce_bin", "macce", 43, "", "Yes", 1, "PAD SPACE"}, + {"macroman_general_ci", "macroman", 39, "Yes", "Yes", 1, "PAD SPACE"}, + {"macroman_bin", "macroman", 53, "", "Yes", 1, "PAD SPACE"}, + {"sjis_japanese_ci", "sjis", 13, "Yes", "Yes", 1, "PAD SPACE"}, + {"sjis_bin", "sjis", 88, "", "Yes", 1, "PAD SPACE"}, + {"swe7_swedish_ci", "swe7", 10, "Yes", "Yes", 1, "PAD SPACE"}, + {"swe7_bin", "swe7", 82, "", "Yes", 1, "PAD SPACE"}, + {"tis620_thai_ci", "tis620", 18, "Yes", "Yes", 4, "PAD SPACE"}, + {"tis620_bin", "tis620", 89, "", "Yes", 1, "PAD SPACE"}, + {"ucs2_general_ci", "ucs2", 35, "Yes", "Yes", 1, "PAD SPACE"}, + {"ucs2_bin", "ucs2", 90, "", "Yes", 1, "PAD SPACE"}, + {"ucs2_unicode_ci", "ucs2", 128, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_icelandic_ci", "ucs2", 129, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_latvian_ci", "ucs2", 130, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_romanian_ci", "ucs2", 131, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_slovenian_ci", "ucs2", 132, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_polish_ci", "ucs2", 133, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_estonian_ci", "ucs2", 134, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_spanish_ci", "ucs2", 135, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_swedish_ci", "ucs2", 136, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_turkish_ci", "ucs2", 137, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_czech_ci", "ucs2", 138, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_danish_ci", "ucs2", 139, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_lithuanian_ci", "ucs2", 140, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_slovak_ci", "ucs2", 141, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_spanish2_ci", "ucs2", 142, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_roman_ci", "ucs2", 143, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_persian_ci", "ucs2", 144, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_esperanto_ci", "ucs2", 145, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_hungarian_ci", "ucs2", 146, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_sinhala_ci", "ucs2", 147, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_german2_ci", "ucs2", 148, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_croatian_ci", "ucs2", 149, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_unicode_520_ci", "ucs2", 150, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_vietnamese_ci", "ucs2", 151, "", "Yes", 8, "PAD SPACE"}, + {"ucs2_general_mysql500_ci", "ucs2", 159, "", "Yes", 1, "PAD SPACE"}, + {"ujis_japanese_ci", "ujis", 12, "Yes", "Yes", 1, "PAD SPACE"}, + {"ujis_bin", "ujis", 91, "", "Yes", 1, "PAD SPACE"}, + {"utf16_general_ci", "utf16", 54, "Yes", "Yes", 1, "PAD SPACE"}, + {"utf16_bin", "utf16", 55, "", "Yes", 1, "PAD SPACE"}, + {"utf16_unicode_ci", "utf16", 101, "", "Yes", 8, "PAD SPACE"}, + {"utf16_icelandic_ci", "utf16", 102, "", "Yes", 8, "PAD SPACE"}, + {"utf16_latvian_ci", "utf16", 103, "", "Yes", 8, "PAD SPACE"}, + {"utf16_romanian_ci", "utf16", 104, "", "Yes", 8, "PAD SPACE"}, + {"utf16_slovenian_ci", "utf16", 105, "", "Yes", 8, "PAD SPACE"}, + {"utf16_polish_ci", "utf16", 106, "", "Yes", 8, "PAD SPACE"}, + {"utf16_estonian_ci", "utf16", 107, "", "Yes", 8, "PAD SPACE"}, + {"utf16_spanish_ci", "utf16", 108, "", "Yes", 8, "PAD SPACE"}, + {"utf16_swedish_ci", "utf16", 109, "", "Yes", 8, "PAD SPACE"}, + {"utf16_turkish_ci", "utf16", 110, "", "Yes", 8, "PAD SPACE"}, + {"utf16_czech_ci", "utf16", 111, "", "Yes", 8, "PAD SPACE"}, + {"utf16_danish_ci", "utf16", 112, "", "Yes", 8, "PAD SPACE"}, + {"utf16_lithuanian_ci", "utf16", 113, "", "Yes", 8, "PAD SPACE"}, + {"utf16_slovak_ci", "utf16", 114, "", "Yes", 8, "PAD SPACE"}, + {"utf16_spanish2_ci", "utf16", 115, "", "Yes", 8, "PAD SPACE"}, + {"utf16_roman_ci", "utf16", 116, "", "Yes", 8, "PAD SPACE"}, + {"utf16_persian_ci", "utf16", 117, "", "Yes", 8, "PAD SPACE"}, + {"utf16_esperanto_ci", "utf16", 118, "", "Yes", 8, "PAD SPACE"}, + {"utf16_hungarian_ci", "utf16", 119, "", "Yes", 8, "PAD SPACE"}, + {"utf16_sinhala_ci", "utf16", 120, "", "Yes", 8, "PAD SPACE"}, + {"utf16_german2_ci", "utf16", 121, "", "Yes", 8, "PAD SPACE"}, + {"utf16_croatian_ci", "utf16", 122, "", "Yes", 8, "PAD SPACE"}, + {"utf16_unicode_520_ci", "utf16", 123, "", "Yes", 8, "PAD SPACE"}, + {"utf16_vietnamese_ci", "utf16", 124, "", "Yes", 8, "PAD SPACE"}, + {"utf16le_general_ci", "utf16le", 56, "Yes", "Yes", 1, "PAD SPACE"}, + {"utf16le_bin", "utf16le", 62, "", "Yes", 1, "PAD SPACE"}, + {"utf32_general_ci", "utf32", 60, "Yes", "Yes", 1, "PAD SPACE"}, + {"utf32_bin", "utf32", 61, "", "Yes", 1, "PAD SPACE"}, + {"utf32_unicode_ci", "utf32", 160, "", "Yes", 8, "PAD SPACE"}, + {"utf32_icelandic_ci", "utf32", 161, "", "Yes", 8, "PAD SPACE"}, + {"utf32_latvian_ci", "utf32", 162, "", "Yes", 8, "PAD SPACE"}, + {"utf32_romanian_ci", "utf32", 163, "", "Yes", 8, "PAD SPACE"}, + {"utf32_slovenian_ci", "utf32", 164, "", "Yes", 8, "PAD SPACE"}, + {"utf32_polish_ci", "utf32", 165, "", "Yes", 8, "PAD SPACE"}, + {"utf32_estonian_ci", "utf32", 166, "", "Yes", 8, "PAD SPACE"}, + {"utf32_spanish_ci", "utf32", 167, "", "Yes", 8, "PAD SPACE"}, + {"utf32_swedish_ci", "utf32", 168, "", "Yes", 8, "PAD SPACE"}, + {"utf32_turkish_ci", "utf32", 169, "", "Yes", 8, "PAD SPACE"}, + {"utf32_czech_ci", "utf32", 170, "", "Yes", 8, "PAD SPACE"}, + {"utf32_danish_ci", "utf32", 171, "", "Yes", 8, "PAD SPACE"}, + {"utf32_lithuanian_ci", "utf32", 172, "", "Yes", 8, "PAD SPACE"}, + {"utf32_slovak_ci", "utf32", 173, "", "Yes", 8, "PAD SPACE"}, + {"utf32_spanish2_ci", "utf32", 174, "", "Yes", 8, "PAD SPACE"}, + {"utf32_roman_ci", "utf32", 175, "", "Yes", 8, "PAD SPACE"}, + {"utf32_persian_ci", "utf32", 176, "", "Yes", 8, "PAD SPACE"}, + {"utf32_esperanto_ci", "utf32", 177, "", "Yes", 8, "PAD SPACE"}, + {"utf32_hungarian_ci", "utf32", 178, "", "Yes", 8, "PAD SPACE"}, + {"utf32_sinhala_ci", "utf32", 179, "", "Yes", 8, "PAD SPACE"}, + {"utf32_german2_ci", "utf32", 180, "", "Yes", 8, "PAD SPACE"}, + {"utf32_croatian_ci", "utf32", 181, "", "Yes", 8, "PAD SPACE"}, + {"utf32_unicode_520_ci", "utf32", 182, "", "Yes", 8, "PAD SPACE"}, + {"utf32_vietnamese_ci", "utf32", 183, "", "Yes", 8, "PAD SPACE"}, + {"utf8_general_ci", "utf8", 33, "Yes", "Yes", 1, "PAD SPACE"}, + {"utf8_tolower_ci", "utf8", 76, "", "Yes", 1, "PAD SPACE"}, + {"utf8_bin", "utf8", 83, "", "Yes", 1, "PAD SPACE"}, + {"utf8_unicode_ci", "utf8", 192, "", "Yes", 8, "PAD SPACE"}, + {"utf8_icelandic_ci", "utf8", 193, "", "Yes", 8, "PAD SPACE"}, + {"utf8_latvian_ci", "utf8", 194, "", "Yes", 8, "PAD SPACE"}, + {"utf8_romanian_ci", "utf8", 195, "", "Yes", 8, "PAD SPACE"}, + {"utf8_slovenian_ci", "utf8", 196, "", "Yes", 8, "PAD SPACE"}, + {"utf8_polish_ci", "utf8", 197, "", "Yes", 8, "PAD SPACE"}, + {"utf8_estonian_ci", "utf8", 198, "", "Yes", 8, "PAD SPACE"}, + {"utf8_spanish_ci", "utf8", 199, "", "Yes", 8, "PAD SPACE"}, + {"utf8_swedish_ci", "utf8", 200, "", "Yes", 8, "PAD SPACE"}, + {"utf8_turkish_ci", "utf8", 201, "", "Yes", 8, "PAD SPACE"}, + {"utf8_czech_ci", "utf8", 202, "", "Yes", 8, "PAD SPACE"}, + {"utf8_danish_ci", "utf8", 203, "", "Yes", 8, "PAD SPACE"}, + {"utf8_lithuanian_ci", "utf8", 204, "", "Yes", 8, "PAD SPACE"}, + {"utf8_slovak_ci", "utf8", 205, "", "Yes", 8, "PAD SPACE"}, + {"utf8_spanish2_ci", "utf8", 206, "", "Yes", 8, "PAD SPACE"}, + {"utf8_roman_ci", "utf8", 207, "", "Yes", 8, "PAD SPACE"}, + {"utf8_persian_ci", "utf8", 208, "", "Yes", 8, "PAD SPACE"}, + {"utf8_esperanto_ci", "utf8", 209, "", "Yes", 8, "PAD SPACE"}, + {"utf8_hungarian_ci", "utf8", 210, "", "Yes", 8, "PAD SPACE"}, + {"utf8_sinhala_ci", "utf8", 211, "", "Yes", 8, "PAD SPACE"}, + {"utf8_german2_ci", "utf8", 212, "", "Yes", 8, "PAD SPACE"}, + {"utf8_croatian_ci", "utf8", 213, "", "Yes", 8, "PAD SPACE"}, + {"utf8_unicode_520_ci", "utf8", 214, "", "Yes", 8, "PAD SPACE"}, + {"utf8_vietnamese_ci", "utf8", 215, "", "Yes", 8, "PAD SPACE"}, + {"utf8_general_mysql500_ci", "utf8", 223, "", "Yes", 1, "PAD SPACE"}, + {"utf8mb4_general_ci", "utf8mb4", 45, "", "Yes", 1, "PAD SPACE"}, + {"utf8mb4_bin", "utf8mb4", 46, "", "Yes", 1, "PAD SPACE"}, + {"utf8mb4_unicode_ci", "utf8mb4", 224, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_icelandic_ci", "utf8mb4", 225, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_latvian_ci", "utf8mb4", 226, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_romanian_ci", "utf8mb4", 227, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_slovenian_ci", "utf8mb4", 228, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_polish_ci", "utf8mb4", 229, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_estonian_ci", "utf8mb4", 230, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_spanish_ci", "utf8mb4", 231, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_swedish_ci", "utf8mb4", 232, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_turkish_ci", "utf8mb4", 233, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_czech_ci", "utf8mb4", 234, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_danish_ci", "utf8mb4", 235, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_lithuanian_ci", "utf8mb4", 236, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_slovak_ci", "utf8mb4", 237, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_spanish2_ci", "utf8mb4", 238, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_roman_ci", "utf8mb4", 239, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_persian_ci", "utf8mb4", 240, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_esperanto_ci", "utf8mb4", 241, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_hungarian_ci", "utf8mb4", 242, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_sinhala_ci", "utf8mb4", 243, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_german2_ci", "utf8mb4", 244, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_croatian_ci", "utf8mb4", 245, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_unicode_520_ci", "utf8mb4", 246, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_vietnamese_ci", "utf8mb4", 247, "", "Yes", 8, "PAD SPACE"}, + {"utf8mb4_0900_ai_ci", "utf8mb4", 255, "Yes", "Yes", 0, "NO PAD"}, + {"utf8mb4_de_pb_0900_ai_ci", "utf8mb4", 256, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_is_0900_ai_ci", "utf8mb4", 257, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_lv_0900_ai_ci", "utf8mb4", 258, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_ro_0900_ai_ci", "utf8mb4", 259, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_sl_0900_ai_ci", "utf8mb4", 260, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_pl_0900_ai_ci", "utf8mb4", 261, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_et_0900_ai_ci", "utf8mb4", 262, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_es_0900_ai_ci", "utf8mb4", 263, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_sv_0900_ai_ci", "utf8mb4", 264, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_tr_0900_ai_ci", "utf8mb4", 265, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_cs_0900_ai_ci", "utf8mb4", 266, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_da_0900_ai_ci", "utf8mb4", 267, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_lt_0900_ai_ci", "utf8mb4", 268, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_sk_0900_ai_ci", "utf8mb4", 269, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_es_trad_0900_ai_ci", "utf8mb4", 270, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_la_0900_ai_ci", "utf8mb4", 271, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_eo_0900_ai_ci", "utf8mb4", 273, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_hu_0900_ai_ci", "utf8mb4", 274, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_hr_0900_ai_ci", "utf8mb4", 275, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_vi_0900_ai_ci", "utf8mb4", 277, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_0900_as_cs", "utf8mb4", 278, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_de_pb_0900_as_cs", "utf8mb4", 279, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_is_0900_as_cs", "utf8mb4", 280, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_lv_0900_as_cs", "utf8mb4", 281, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_ro_0900_as_cs", "utf8mb4", 282, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_sl_0900_as_cs", "utf8mb4", 283, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_pl_0900_as_cs", "utf8mb4", 284, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_et_0900_as_cs", "utf8mb4", 285, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_es_0900_as_cs", "utf8mb4", 286, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_sv_0900_as_cs", "utf8mb4", 287, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_tr_0900_as_cs", "utf8mb4", 288, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_cs_0900_as_cs", "utf8mb4", 289, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_da_0900_as_cs", "utf8mb4", 290, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_lt_0900_as_cs", "utf8mb4", 291, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_sk_0900_as_cs", "utf8mb4", 292, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_es_trad_0900_as_cs", "utf8mb4", 293, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_la_0900_as_cs", "utf8mb4", 294, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_eo_0900_as_cs", "utf8mb4", 296, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_hu_0900_as_cs", "utf8mb4", 297, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_hr_0900_as_cs", "utf8mb4", 298, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_vi_0900_as_cs", "utf8mb4", 300, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_ja_0900_as_cs", "utf8mb4", 303, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_ja_0900_as_cs_ks", "utf8mb4", 304, "", "Yes", 24, "NO PAD"}, + {"utf8mb4_0900_as_ci", "utf8mb4", 305, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_ru_0900_ai_ci", "utf8mb4", 306, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_ru_0900_as_cs", "utf8mb4", 307, "", "Yes", 0, "NO PAD"}, + {"utf8mb4_zh_0900_as_cs", "utf8mb4", 308, "", "Yes", 0, "NO PAD"}, + }; + @Override public boolean isSupport(VirtualView virtualView) { return virtualView instanceof InformationSchemaCollations; @@ -40,277 +314,9 @@ public boolean isSupport(VirtualView virtualView) { @Override public Cursor handle(VirtualView virtualView, ExecutionContext executionContext, ArrayResultCursor cursor) { InformationSchemaCollations informationSchemaCollations = (InformationSchemaCollations) virtualView; - cursor.addRow(new Object[] {"armscii8_general_ci", "armscii8", 32, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"armscii8_bin", "armscii8", 64, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"ascii_general_ci", "ascii", 11, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"ascii_bin", "ascii", 65, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"big5_chinese_ci", "big5", 1, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"big5_bin", "big5", 84, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"binary", "binary", 63, "Yes", "Yes", 1, "NO PAD"}); - cursor.addRow(new Object[] {"cp1250_general_ci", "cp1250", 26, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1250_czech_cs", "cp1250", 34, "", "Yes", 2, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1250_croatian_ci", "cp1250", 44, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1250_bin", "cp1250", 66, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1250_polish_ci", "cp1250", 99, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1251_bulgarian_ci", "cp1251", 14, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1251_ukrainian_ci", "cp1251", 23, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1251_bin", "cp1251", 50, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1251_general_ci", "cp1251", 51, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1251_general_cs", "cp1251", 52, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1256_general_ci", "cp1256", 57, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1256_bin", "cp1256", 67, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1257_lithuanian_ci", "cp1257", 29, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1257_bin", "cp1257", 58, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp1257_general_ci", "cp1257", 59, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp850_general_ci", "cp850", 4, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp850_bin", "cp850", 80, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp852_general_ci", "cp852", 40, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp852_bin", "cp852", 81, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp866_general_ci", "cp866", 36, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp866_bin", "cp866", 68, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp932_japanese_ci", "cp932", 95, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"cp932_bin", "cp932", 96, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"dec8_swedish_ci", "dec8", 3, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"dec8_bin", "dec8", 69, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"eucjpms_japanese_ci", "eucjpms", 97, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"eucjpms_bin", "eucjpms", 98, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"euckr_korean_ci", "euckr", 19, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"euckr_bin", "euckr", 85, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"gb18030_chinese_ci", "gb18030", 248, "Yes", "Yes", 2, "PAD SPACE"}); - cursor.addRow(new Object[] {"gb18030_bin", "gb18030", 249, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"gb18030_unicode_520_ci", "gb18030", 250, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"gb2312_chinese_ci", "gb2312", 24, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"gb2312_bin", "gb2312", 86, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"gbk_chinese_ci", "gbk", 28, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"gbk_bin", "gbk", 87, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"geostd8_general_ci", "geostd8", 92, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"geostd8_bin", "geostd8", 93, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"greek_general_ci", "greek", 25, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"greek_bin", "greek", 70, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"hebrew_general_ci", "hebrew", 16, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"hebrew_bin", "hebrew", 71, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"hp8_english_ci", "hp8", 6, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"hp8_bin", "hp8", 72, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"keybcs2_general_ci", "keybcs2", 37, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"keybcs2_bin", "keybcs2", 73, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"koi8r_general_ci", "koi8r", 7, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"koi8r_bin", "koi8r", 74, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"koi8u_general_ci", "koi8u", 22, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"koi8u_bin", "koi8u", 75, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin1_german1_ci", "latin1", 5, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin1_swedish_ci", "latin1", 8, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin1_danish_ci", "latin1", 15, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin1_german2_ci", "latin1", 31, "", "Yes", 2, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin1_bin", "latin1", 47, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin1_general_ci", "latin1", 48, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin1_general_cs", "latin1", 49, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin1_spanish_ci", "latin1", 94, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin2_czech_cs", "latin2", 2, "", "Yes", 4, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin2_general_ci", "latin2", 9, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin2_hungarian_ci", "latin2", 21, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin2_croatian_ci", "latin2", 27, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin2_bin", "latin2", 77, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin5_turkish_ci", "latin5", 30, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin5_bin", "latin5", 78, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin7_estonian_cs", "latin7", 20, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin7_general_ci", "latin7", 41, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin7_general_cs", "latin7", 42, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"latin7_bin", "latin7", 79, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"macce_general_ci", "macce", 38, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"macce_bin", "macce", 43, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"macroman_general_ci", "macroman", 39, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"macroman_bin", "macroman", 53, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"sjis_japanese_ci", "sjis", 13, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"sjis_bin", "sjis", 88, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"swe7_swedish_ci", "swe7", 10, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"swe7_bin", "swe7", 82, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"tis620_thai_ci", "tis620", 18, "Yes", "Yes", 4, "PAD SPACE"}); - cursor.addRow(new Object[] {"tis620_bin", "tis620", 89, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_general_ci", "ucs2", 35, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_bin", "ucs2", 90, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_unicode_ci", "ucs2", 128, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_icelandic_ci", "ucs2", 129, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_latvian_ci", "ucs2", 130, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_romanian_ci", "ucs2", 131, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_slovenian_ci", "ucs2", 132, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_polish_ci", "ucs2", 133, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_estonian_ci", "ucs2", 134, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_spanish_ci", "ucs2", 135, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_swedish_ci", "ucs2", 136, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_turkish_ci", "ucs2", 137, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_czech_ci", "ucs2", 138, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_danish_ci", "ucs2", 139, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_lithuanian_ci", "ucs2", 140, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_slovak_ci", "ucs2", 141, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_spanish2_ci", "ucs2", 142, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_roman_ci", "ucs2", 143, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_persian_ci", "ucs2", 144, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_esperanto_ci", "ucs2", 145, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_hungarian_ci", "ucs2", 146, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_sinhala_ci", "ucs2", 147, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_german2_ci", "ucs2", 148, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_croatian_ci", "ucs2", 149, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_unicode_520_ci", "ucs2", 150, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_vietnamese_ci", "ucs2", 151, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"ucs2_general_mysql500_ci", "ucs2", 159, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"ujis_japanese_ci", "ujis", 12, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"ujis_bin", "ujis", 91, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_general_ci", "utf16", 54, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_bin", "utf16", 55, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_unicode_ci", "utf16", 101, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_icelandic_ci", "utf16", 102, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_latvian_ci", "utf16", 103, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_romanian_ci", "utf16", 104, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_slovenian_ci", "utf16", 105, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_polish_ci", "utf16", 106, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_estonian_ci", "utf16", 107, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_spanish_ci", "utf16", 108, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_swedish_ci", "utf16", 109, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_turkish_ci", "utf16", 110, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_czech_ci", "utf16", 111, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_danish_ci", "utf16", 112, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_lithuanian_ci", "utf16", 113, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_slovak_ci", "utf16", 114, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_spanish2_ci", "utf16", 115, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_roman_ci", "utf16", 116, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_persian_ci", "utf16", 117, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_esperanto_ci", "utf16", 118, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_hungarian_ci", "utf16", 119, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_sinhala_ci", "utf16", 120, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_german2_ci", "utf16", 121, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_croatian_ci", "utf16", 122, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_unicode_520_ci", "utf16", 123, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16_vietnamese_ci", "utf16", 124, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16le_general_ci", "utf16le", 56, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf16le_bin", "utf16le", 62, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_general_ci", "utf32", 60, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_bin", "utf32", 61, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_unicode_ci", "utf32", 160, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_icelandic_ci", "utf32", 161, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_latvian_ci", "utf32", 162, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_romanian_ci", "utf32", 163, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_slovenian_ci", "utf32", 164, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_polish_ci", "utf32", 165, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_estonian_ci", "utf32", 166, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_spanish_ci", "utf32", 167, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_swedish_ci", "utf32", 168, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_turkish_ci", "utf32", 169, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_czech_ci", "utf32", 170, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_danish_ci", "utf32", 171, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_lithuanian_ci", "utf32", 172, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_slovak_ci", "utf32", 173, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_spanish2_ci", "utf32", 174, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_roman_ci", "utf32", 175, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_persian_ci", "utf32", 176, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_esperanto_ci", "utf32", 177, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_hungarian_ci", "utf32", 178, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_sinhala_ci", "utf32", 179, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_german2_ci", "utf32", 180, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_croatian_ci", "utf32", 181, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_unicode_520_ci", "utf32", 182, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf32_vietnamese_ci", "utf32", 183, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_general_ci", "utf8", 33, "Yes", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_tolower_ci", "utf8", 76, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_bin", "utf8", 83, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_unicode_ci", "utf8", 192, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_icelandic_ci", "utf8", 193, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_latvian_ci", "utf8", 194, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_romanian_ci", "utf8", 195, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_slovenian_ci", "utf8", 196, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_polish_ci", "utf8", 197, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_estonian_ci", "utf8", 198, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_spanish_ci", "utf8", 199, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_swedish_ci", "utf8", 200, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_turkish_ci", "utf8", 201, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_czech_ci", "utf8", 202, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_danish_ci", "utf8", 203, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_lithuanian_ci", "utf8", 204, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_slovak_ci", "utf8", 205, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_spanish2_ci", "utf8", 206, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_roman_ci", "utf8", 207, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_persian_ci", "utf8", 208, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_esperanto_ci", "utf8", 209, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_hungarian_ci", "utf8", 210, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_sinhala_ci", "utf8", 211, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_german2_ci", "utf8", 212, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_croatian_ci", "utf8", 213, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_unicode_520_ci", "utf8", 214, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_vietnamese_ci", "utf8", 215, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8_general_mysql500_ci", "utf8", 223, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_general_ci", "utf8mb4", 45, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_bin", "utf8mb4", 46, "", "Yes", 1, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_unicode_ci", "utf8mb4", 224, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_icelandic_ci", "utf8mb4", 225, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_latvian_ci", "utf8mb4", 226, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_romanian_ci", "utf8mb4", 227, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_slovenian_ci", "utf8mb4", 228, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_polish_ci", "utf8mb4", 229, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_estonian_ci", "utf8mb4", 230, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_spanish_ci", "utf8mb4", 231, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_swedish_ci", "utf8mb4", 232, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_turkish_ci", "utf8mb4", 233, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_czech_ci", "utf8mb4", 234, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_danish_ci", "utf8mb4", 235, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_lithuanian_ci", "utf8mb4", 236, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_slovak_ci", "utf8mb4", 237, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_spanish2_ci", "utf8mb4", 238, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_roman_ci", "utf8mb4", 239, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_persian_ci", "utf8mb4", 240, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_esperanto_ci", "utf8mb4", 241, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_hungarian_ci", "utf8mb4", 242, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_sinhala_ci", "utf8mb4", 243, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_german2_ci", "utf8mb4", 244, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_croatian_ci", "utf8mb4", 245, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_unicode_520_ci", "utf8mb4", 246, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_vietnamese_ci", "utf8mb4", 247, "", "Yes", 8, "PAD SPACE"}); - cursor.addRow(new Object[] {"utf8mb4_0900_ai_ci", "utf8mb4", 255, "Yes", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_de_pb_0900_ai_ci", "utf8mb4", 256, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_is_0900_ai_ci", "utf8mb4", 257, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_lv_0900_ai_ci", "utf8mb4", 258, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_ro_0900_ai_ci", "utf8mb4", 259, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_sl_0900_ai_ci", "utf8mb4", 260, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_pl_0900_ai_ci", "utf8mb4", 261, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_et_0900_ai_ci", "utf8mb4", 262, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_es_0900_ai_ci", "utf8mb4", 263, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_sv_0900_ai_ci", "utf8mb4", 264, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_tr_0900_ai_ci", "utf8mb4", 265, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_cs_0900_ai_ci", "utf8mb4", 266, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_da_0900_ai_ci", "utf8mb4", 267, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_lt_0900_ai_ci", "utf8mb4", 268, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_sk_0900_ai_ci", "utf8mb4", 269, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_es_trad_0900_ai_ci", "utf8mb4", 270, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_la_0900_ai_ci", "utf8mb4", 271, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_eo_0900_ai_ci", "utf8mb4", 273, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_hu_0900_ai_ci", "utf8mb4", 274, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_hr_0900_ai_ci", "utf8mb4", 275, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_vi_0900_ai_ci", "utf8mb4", 277, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_0900_as_cs", "utf8mb4", 278, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_de_pb_0900_as_cs", "utf8mb4", 279, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_is_0900_as_cs", "utf8mb4", 280, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_lv_0900_as_cs", "utf8mb4", 281, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_ro_0900_as_cs", "utf8mb4", 282, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_sl_0900_as_cs", "utf8mb4", 283, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_pl_0900_as_cs", "utf8mb4", 284, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_et_0900_as_cs", "utf8mb4", 285, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_es_0900_as_cs", "utf8mb4", 286, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_sv_0900_as_cs", "utf8mb4", 287, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_tr_0900_as_cs", "utf8mb4", 288, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_cs_0900_as_cs", "utf8mb4", 289, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_da_0900_as_cs", "utf8mb4", 290, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_lt_0900_as_cs", "utf8mb4", 291, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_sk_0900_as_cs", "utf8mb4", 292, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_es_trad_0900_as_cs", "utf8mb4", 293, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_la_0900_as_cs", "utf8mb4", 294, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_eo_0900_as_cs", "utf8mb4", 296, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_hu_0900_as_cs", "utf8mb4", 297, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_hr_0900_as_cs", "utf8mb4", 298, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_vi_0900_as_cs", "utf8mb4", 300, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_ja_0900_as_cs", "utf8mb4", 303, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_ja_0900_as_cs_ks", "utf8mb4", 304, "", "Yes", 24, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_0900_as_ci", "utf8mb4", 305, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_ru_0900_ai_ci", "utf8mb4", 306, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_ru_0900_as_cs", "utf8mb4", 307, "", "Yes", 0, "NO PAD"}); - cursor.addRow(new Object[] {"utf8mb4_zh_0900_as_cs", "utf8mb4", 308, "", "Yes", 0, "NO PAD"}); + for (Object[] collation : COLLATIONS) { + cursor.addRow(collation); + } return cursor; } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaColumnarIndexStatusHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaColumnarIndexStatusHandler.java index d5901426b..3be80d03a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaColumnarIndexStatusHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaColumnarIndexStatusHandler.java @@ -35,7 +35,6 @@ import com.alibaba.polardbx.optimizer.core.function.calc.scalar.filter.Like; import com.alibaba.polardbx.optimizer.view.InformationSchemaColumnarIndexStatus; import com.alibaba.polardbx.optimizer.view.VirtualView; -import io.airlift.slice.DataSize; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.NotNull; @@ -44,7 +43,6 @@ import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -194,6 +192,7 @@ private Map queryFullStatus(Map queryFullStatus(Map>> metrics = + GmsSyncManagerHelper.sync(new MetricSyncAllAction(), "polardbx", SyncScope.CURRENT_ONLY); + if (metrics == null || metrics.isEmpty()) { + return cursor; + } + for (List> nodeRows : metrics) { + if (nodeRows == null) { + continue; + } + for (Map row : nodeRows) { + final String host = DataTypes.StringType.convertFrom(row.get(MetricSyncAllAction.HOST)); + final String instId = DataTypes.StringType.convertFrom(row.get(MetricSyncAllAction.INST)); + String feat = DataTypes.StringType.convertFrom(row.get(MetricSyncAllAction.METRIC_FEAT_KEY)); + String real = DataTypes.StringType.convertFrom(row.get(MetricSyncAllAction.METRIC_REAL_KEY)); + FeatureStats featureStats = FeatureStats.deserialize(feat); + for (FeatureStatsItem item : FeatureStatsItem.values()) { + cursor.addRow(new Object[] { + host, + instId, + item.name(), + "feat", + featureStats.getLong(item) + }); + } + + for (Map.Entry entry : decodeReal(real).entrySet()) { + cursor.addRow(new Object[] { + host, + instId, + entry.getKey(), + "real", + entry.getValue() + }); + } + + } + } + return cursor; + } + + public static Map decodeReal(String real) { + Map map = Maps.newHashMap(); + QuotedStringTokenizer tokenizer = new QuotedStringTokenizer(real, ","); + + while (tokenizer.hasMoreTokens()) { + String kv = tokenizer.nextToken(); + String[] kvPair = kv.split(":", 2); + map.put(kvPair[0], kvPair[1]); + } + + return map; + } + +} + diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaPartitionsMetaHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaPartitionsMetaHandler.java index 605e56bc2..08b706bc4 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaPartitionsMetaHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaPartitionsMetaHandler.java @@ -169,6 +169,7 @@ public static Cursor handlePartitionsMeta(ArrayResultCursor result, record.partName, record.partPosi, record.partDesc, + record.partArcStateName, record.subPartMethod, record.subPartCol, @@ -178,6 +179,7 @@ public static Cursor handlePartitionsMeta(ArrayResultCursor result, record.subPartTempName, record.subPartPosi, record.subPartDesc, + record.subPartArcStateName, record.pgName, record.phyDbGroup, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaRplSyncPointHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaRplSyncPointHandler.java new file mode 100644 index 000000000..902439a73 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaRplSyncPointHandler.java @@ -0,0 +1,66 @@ +package com.alibaba.polardbx.executor.handler.subhandler; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.handler.VirtualViewHandler; +import com.alibaba.polardbx.gms.metadb.GmsSystemTables; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.view.InformationSchemaRplSyncPoint; +import com.alibaba.polardbx.optimizer.view.VirtualView; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author yudong + * @since 2024/6/18 15:36 + **/ +public class InformationSchemaRplSyncPointHandler extends BaseVirtualViewSubClassHandler { + private static final Logger logger = LoggerFactory.getLogger(InformationSchemaRplSyncPointHandler.class); + + public InformationSchemaRplSyncPointHandler(VirtualViewHandler virtualViewHandler) { + super(virtualViewHandler); + } + + @Override + public boolean isSupport(VirtualView virtualView) { + return virtualView instanceof InformationSchemaRplSyncPoint; + } + + @Override + public Cursor handle(VirtualView virtualView, ExecutionContext executionContext, ArrayResultCursor cursor) { + try { + if (!MetaDbUtil.hasTable(GmsSystemTables.RPL_SYNC_POINT_TABLE)) { + return cursor; + } + } catch (SQLException ex) { + logger.error("get information schema rpl sync point failed!", ex); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_GENERIC, ex); + } + + try (Connection metaDbConn = MetaDbUtil.getConnection(); + PreparedStatement stmt = metaDbConn.prepareStatement( + "SELECT * FROM " + GmsSystemTables.RPL_SYNC_POINT_TABLE); + ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + cursor.addRow(new Object[] { + rs.getLong("ID"), + rs.getString("PRIMARY_TSO"), + rs.getString("SECONDARY_TSO"), + rs.getTimestamp("CREATE_TIME") + }); + } + } catch (SQLException ex) { + logger.error("get information schema rpl sync point failed!", ex); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_GENERIC, ex); + } + return cursor; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaSPMHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaSPMHandler.java index 959977ad3..6c08083fc 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaSPMHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaSPMHandler.java @@ -77,6 +77,7 @@ public Cursor handle(VirtualView virtualView, ExecutionContext executionContext, final String isRebuildAtLoad = DataTypes.StringType.convertFrom(row.get("IS_REBUILD_AT_LOAD")); final String hint = DataTypes.StringType.convertFrom(row.get("HINT")); final String usePostPlanner = DataTypes.StringType.convertFrom(row.get("USE_POST_PLANNER")); + final String hotEvolved = DataTypes.StringType.convertFrom(row.get("HOT_EVOLVED")); cursor.addRow(new Object[] { host, @@ -98,7 +99,8 @@ public Cursor handle(VirtualView virtualView, ExecutionContext executionContext, externalizedPlan, isRebuildAtLoad, hint, - usePostPlanner + usePostPlanner, + hotEvolved }); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTableDetailHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTableDetailHandler.java index 0674c59c6..3c81009cb 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTableDetailHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTableDetailHandler.java @@ -210,6 +210,7 @@ private void queryStats(String tableLike, Long physicalTableRows = DataTypes.LongType.convertFrom(tableStatRow.get("physicalTableRows")); Long physicalDataLength = DataTypes.LongType.convertFrom(tableStatRow.get("physicalDataLength")); Long physicalIndexLength = DataTypes.LongType.convertFrom(tableStatRow.get("physicalIndexLength")); + Long physicalDataFree = DataTypes.LongType.convertFrom(tableStatRow.get("physicalDataFree")); Long physicalRowsRead = 0L; if (tableStatRow.containsKey("physicalRowsRead")) { @@ -242,7 +243,7 @@ private void queryStats(String tableLike, String groupName = pair.getValue(); String phyTblName = record.getLocation().getPhyTableName(); - Object[] row = new Object[21]; + Object[] row = new Object[22]; cursor.addRow(row); int index = 0; @@ -267,6 +268,8 @@ private void queryStats(String tableLike, row[index++] = DataTypes.ULongType.convertFrom(physicalDataLength); // INDEX_LENGTH row[index++] = DataTypes.ULongType.convertFrom(physicalIndexLength); + // DATA_FREE + row[index++] = DataTypes.ULongType.convertFrom(physicalDataFree); // BOUND_VALUE, a complete interval with lower_bnd and upper_bnd for part row[index++] = DataTypes.StringType.convertFrom(boundValue); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTablesHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTablesHandler.java index f0e780c57..49fb2ced2 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTablesHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTablesHandler.java @@ -17,22 +17,28 @@ package com.alibaba.polardbx.executor.handler.subhandler; import com.alibaba.druid.util.JdbcUtils; +import com.alibaba.polardbx.common.constants.SystemTables; import com.alibaba.polardbx.common.jdbc.MasterSlave; import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; import com.alibaba.polardbx.executor.gms.util.StatisticUtils; import com.alibaba.polardbx.executor.handler.VirtualViewHandler; -import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.executor.spi.ITopologyExecutor; +import com.alibaba.polardbx.gms.topology.DbTopologyManager; +import com.alibaba.polardbx.gms.util.GroupInfoUtil; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; import com.alibaba.polardbx.optimizer.config.table.SchemaManager; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticManager; @@ -40,20 +46,28 @@ import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.function.calc.scalar.CanAccessTable; import com.alibaba.polardbx.optimizer.core.function.calc.scalar.filter.Like; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; +import com.alibaba.polardbx.optimizer.partition.common.PartitionLocation; +import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; import com.alibaba.polardbx.optimizer.view.InformationSchemaTables; import com.alibaba.polardbx.optimizer.view.VirtualView; -import org.apache.calcite.rex.RexDynamicParam; -import org.apache.calcite.rex.RexLiteral; -import org.apache.commons.collections.CollectionUtils; +import com.alibaba.polardbx.rule.TableRule; +import com.alibaba.polardbx.rule.TddlRule; import org.apache.commons.lang.StringUtils; import java.math.BigInteger; import java.sql.Connection; import java.sql.ResultSet; +import java.sql.SQLException; import java.sql.Statement; -import java.util.HashSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeMap; import java.util.stream.Collectors; @@ -63,6 +77,9 @@ */ public class InformationSchemaTablesHandler extends BaseVirtualViewSubClassHandler { private static final Logger logger = LoggerFactory.getLogger(InformationSchemaTablesHandler.class); + private static final String QUERY_INFO_SCHEMA_TABLES = "select * from information_schema.tables where " + + " (table_schema, table_name) in (%s)"; + private static final String DISABLE_INFO_SCHEMA_CACHE_80 = "set information_schema_stats_expiry = 0"; public InformationSchemaTablesHandler(VirtualViewHandler virtualViewHandler) { super(virtualViewHandler); @@ -92,6 +109,12 @@ public Cursor handle(VirtualView virtualView, ExecutionContext executionContext, // tableLike String tableLike = virtualView.getLikeString(tableIndex, params); + // Fetch accurate info from each DN. + if (DynamicConfig.getInstance().isEnableAccurateInfoSchemaTables()) { + fetchAccurateInfoSchemaTables(schemaNames, indexTableNames, tableLike, cursor); + return cursor; + } + boolean once = true; for (String schemaName : schemaNames) { SchemaManager schemaManager = OptimizerContext.getContext(schemaName).getLatestSchemaManager(); @@ -213,7 +236,6 @@ public Cursor handle(VirtualView virtualView, ExecutionContext executionContext, avgRowLength = BigInteger.valueOf(dataLength / tableRows); } } - } cursor.addRow(new Object[] { @@ -253,4 +275,304 @@ public Cursor handle(VirtualView virtualView, ExecutionContext executionContext, return cursor; } + + protected static void fetchAccurateInfoSchemaTables(Set schemaNames, Set indexTableNames, + String tableLike, ArrayResultCursor cursor) { + for (String schemaName : schemaNames) { + // logical table -> table statistics + Map tableStatistics = new HashMap<>(); + // gsi table name -> logical table name, all in lower case + Map gsiToLogicalTb = new HashMap<>(); + // dn host:port -> information of physical tables in this dn + Map dnInfos = generateMetadataForSchema(schemaName, indexTableNames, tableLike, + gsiToLogicalTb); + + for (DnInfo dnInfo : dnInfos.values()) { + try (Connection connection = dnInfo.getConnection(); + Statement stmt = connection.createStatement()) { + if (InstanceVersion.isMYSQL80()) { + try { + stmt.execute(DISABLE_INFO_SCHEMA_CACHE_80); + } catch (SQLException e) { + // ignore + } + } + String dbAndTb = dnInfo.phyDbPhyTbToLogicalTb.keySet() + .stream() + .map(o -> "('" + o.getKey() + "', '" + o.getValue() + "')") + .collect(Collectors.joining(",")); + String sql = String.format(QUERY_INFO_SCHEMA_TABLES, dbAndTb); + ResultSet rs = stmt.executeQuery(sql); + while (rs.next()) { + String physicalDb = rs.getString("TABLE_SCHEMA"); + String physicalTb = rs.getString("TABLE_NAME"); + // find logical table + String logicalTable = dnInfo.phyDbPhyTbToLogicalTb.get(new Pair<>(physicalDb, physicalTb)); + if (null == logicalTable) { + logger.warn("Cant find logical table for " + physicalDb + "." + physicalTb + " in " + + dnInfo.dnAddress); + continue; + } + + long version = rs.getLong("VERSION"); + String rowFormat = rs.getString("ROW_FORMAT"); + long tableRows = rs.getLong("TABLE_ROWS"); + long avgRowLength = rs.getLong("AVG_ROW_LENGTH"); + long dataLength = rs.getLong("DATA_LENGTH"); + long maxDataLength = rs.getLong("MAX_DATA_LENGTH"); + long indexLength = rs.getLong("INDEX_LENGTH"); + long dataFree = rs.getLong("DATA_FREE"); + String autoIncrement = rs.getString("AUTO_INCREMENT"); + String createTime = rs.getString("CREATE_TIME"); + String updateTime = rs.getString("UPDATE_TIME"); + String checkTime = rs.getString("CHECK_TIME"); + String tableCollation = rs.getString("TABLE_COLLATION"); + String checksum = rs.getString("CHECKSUM"); + String createOptions = rs.getString("CREATE_OPTIONS"); + String tableComment = rs.getString("TABLE_COMMENT"); + + Statistics stats = tableStatistics.computeIfAbsent(logicalTable, k -> { + Statistics statistics = new Statistics(); + statistics.version = version; + statistics.rowFormat = rowFormat; + statistics.autoIncrement = autoIncrement; + statistics.createTime = createTime; + statistics.updateTime = updateTime; + statistics.checkTime = checkTime; + statistics.tableCollation = tableCollation; + statistics.checksum = checksum; + statistics.createOptions = createOptions; + statistics.tableComment = tableComment; + return statistics; + }); + stats.tableRows += tableRows; + stats.avgRowLength += avgRowLength; + stats.dataLength += dataLength; + stats.maxDataLength += maxDataLength; + stats.indexLength += indexLength; + stats.dataFree += dataFree; + stats.cnt++; + } + } catch (SQLException ex) { + logger.error("error when querying information_schema.tables", ex); + } + } + + // Add index_length of gsi into index_length of primary table + for (Map.Entry gsiAndLogicalTb : gsiToLogicalTb.entrySet()) { + Statistics gsiStat = tableStatistics.get(gsiAndLogicalTb.getKey()); + Statistics primaryStat = tableStatistics.get(gsiAndLogicalTb.getValue()); + if (null != gsiStat && null != primaryStat) { + primaryStat.indexLength += gsiStat.indexLength; + gsiStat.indexLength = 0; + } + } + + for (Map.Entry statistics : tableStatistics.entrySet()) { + if (DynamicConfig.getInstance().isEnableTrxDebugMode()) { + logger.warn("accurate info schema tables: " + statistics.getKey()); + } + String logicalTableName = statistics.getKey(); + if (StatisticUtils.isFileStore(schemaName, logicalTableName)) { + Map statisticMap = + StatisticUtils.getFileStoreStatistic(schemaName, logicalTableName); + statistics.getValue().tableRows = statisticMap.get("TABLE_ROWS"); + statistics.getValue().dataLength = statisticMap.get("DATA_LENGTH"); + statistics.getValue().indexLength = statisticMap.get("INDEX_LENGTH"); + statistics.getValue().dataFree = statisticMap.get("DATA_FREE"); + if (statistics.getValue().tableRows != 0) { + statistics.getValue().avgRowLength + = statistics.getValue().dataLength / statistics.getValue().tableRows; + } + } + cursor.addRow(new Object[] { + "def", + schemaName, + statistics.getKey(), + "BASE TABLE", + "InnoDB", + statistics.getValue().version, + statistics.getValue().rowFormat, + statistics.getValue().tableRows, + statistics.getValue().avgRowLength / statistics.getValue().cnt, + statistics.getValue().dataLength, + statistics.getValue().maxDataLength, + statistics.getValue().indexLength, + statistics.getValue().dataFree, + statistics.getValue().autoIncrement, + statistics.getValue().createTime, + statistics.getValue().updateTime, + statistics.getValue().checkTime, + statistics.getValue().tableCollation, + statistics.getValue().checksum, + statistics.getValue().createOptions, + statistics.getValue().tableComment + }); + } + } + } + + public static Map generateMetadataForSchema(String schemaName, Set indexTableNames, + String tableLike, Map gsiToLogicalTb) { + Map dnInfos = new HashMap<>(); + List logicalTableNameSet = new ArrayList<>(); + ITopologyExecutor executor = ExecutorContext.getContext(schemaName).getTopologyExecutor(); + + // Drds mode. + TddlRuleManager tddlRuleManager = + Objects.requireNonNull(OptimizerContext.getContext(schemaName)).getRuleManager(); + TddlRule tddlRule = tddlRuleManager.getTddlRule(); + Collection tableRules = tddlRule.getTables(); + for (TableRule tableRule : tableRules) { + String logicalTableName = tableRule.getVirtualTbName(); + if (SystemTables.contains(logicalTableName)) { + continue; + } + logicalTableNameSet.add(logicalTableName); + } + + // Auto mode. + PartitionInfoManager partitionInfoManager = + Objects.requireNonNull(OptimizerContext.getContext(schemaName)).getPartitionInfoManager(); + for (PartitionInfo partitionInfo : partitionInfoManager.getPartitionInfos()) { + String logicalTableName = partitionInfo.getTableName(); + if (SystemTables.contains(logicalTableName)) { + continue; + } + logicalTableNameSet.add(logicalTableName); + } + + Like likeFunc = new Like(); + + for (String logicalTableName : logicalTableNameSet) { + if (indexTableNames != null && !indexTableNames.isEmpty()) { + if (!indexTableNames.contains(logicalTableName.toLowerCase())) { + continue; + } + } + + if (tableLike != null) { + if (!likeFunc.like(logicalTableName, tableLike)) { + continue; + } + } + + // Process this logical table + if (partitionInfoManager.isNewPartDbTable(logicalTableName)) { + processAutoTable(dnInfos, executor, partitionInfoManager, logicalTableName); + + // For gsi + TableMeta tableMeta = Objects.requireNonNull(OptimizerContext.getContext(schemaName)) + .getLatestSchemaManager().getTable(logicalTableName); + Map publishedGsi = tableMeta.getGsiPublished(); + if (null != publishedGsi) { + List gsiList = publishedGsi.keySet() + .stream().map(String::toLowerCase).collect(Collectors.toList()); + for (String gsi : gsiList) { + processAutoTable(dnInfos, executor, partitionInfoManager, gsi); + gsiToLogicalTb.put(gsi.toLowerCase(), logicalTableName.toLowerCase()); + } + } + } else { + processDrdsTable(dnInfos, executor, tddlRuleManager, logicalTableName); + + // For gsi + TableMeta tableMeta = Objects.requireNonNull(OptimizerContext.getContext(schemaName)) + .getLatestSchemaManager().getTable(logicalTableName); + Map publishedGsi = tableMeta.getGsiPublished(); + if (null != publishedGsi) { + List gsiList = publishedGsi.keySet() + .stream().map(String::toLowerCase).collect(Collectors.toList()); + for (String gsi : gsiList) { + processDrdsTable(dnInfos, executor, tddlRuleManager, gsi); + gsiToLogicalTb.put(gsi.toLowerCase(), logicalTableName.toLowerCase()); + } + } + } + } + + return dnInfos; + } + + private static void processDrdsTable(Map dnInfos, ITopologyExecutor executor, + TddlRuleManager tddlRuleManager, String tableName) { + TableRule tableRule = tddlRuleManager.getTableRule(tableName); + if (null != tableRule) { + Map> topologys = tableRule.getStaticTopology(); + if (topologys == null || topologys.size() == 0) { + topologys = tableRule.getActualTopology(); + } + + for (Map.Entry> topology : topologys.entrySet()) { + String group = topology.getKey(); + Set tableNames = topology.getValue(); + if (tableNames == null || tableNames.isEmpty()) { + continue; + } + TGroupDataSource dataSource = (TGroupDataSource) executor.getGroupExecutor(group).getDataSource(); + String address = dataSource.getMasterSourceAddress().toLowerCase(); + String phyDb = dataSource.getConfigManager().getDataSource(MasterSlave.MASTER_ONLY) + .getDsConfHandle().getRunTimeConf().getDbName(); + for (String physicalTable : tableNames) { + DnInfo dnInfo = dnInfos.computeIfAbsent(address, k -> new DnInfo(k, dataSource)); + dnInfo.phyDbPhyTbToLogicalTb.put(new Pair<>(phyDb.toLowerCase(), physicalTable.toLowerCase()), + tableName.toLowerCase()); + } + } + } + } + + private static void processAutoTable(Map dnInfos, ITopologyExecutor executor, + PartitionInfoManager partitionInfoManager, String tableName) { + PartitionInfo partitionInfo = partitionInfoManager.getPartitionInfo(tableName); + List partitions = partitionInfo.getPartitionBy().getPhysicalPartitions(); + for (PartitionSpec partition : partitions) { + PartitionLocation location = partition.getLocation(); + String groupName = location.getGroupKey(); + String phyDb = GroupInfoUtil.buildPhysicalDbNameFromGroupName(groupName).toLowerCase(); + String phyTb = location.getPhyTableName().toLowerCase(); + TGroupDataSource dataSource = (TGroupDataSource) executor.getGroupExecutor(groupName).getDataSource(); + String address = dataSource.getMasterSourceAddress().toLowerCase(); + DnInfo dnInfo = dnInfos.computeIfAbsent(address, k -> new DnInfo(k, dataSource)); + dnInfo.phyDbPhyTbToLogicalTb.put(new Pair<>(phyDb, phyTb), tableName.toLowerCase()); + } + } + + private static class DnInfo { + // DN host:port + public String dnAddress; + // (physical_db, physical_tb) -> logical_tb, all in lower case + public Map, String> phyDbPhyTbToLogicalTb = new HashMap<>(); + public TGroupDataSource dataSource; + + public DnInfo(String address, TGroupDataSource dataSource) { + this.dnAddress = address; + this.dataSource = dataSource; + } + + public Connection getConnection() { + String masterDnId = dataSource.getMasterDNId(); + return DbTopologyManager.getConnectionForStorage(masterDnId); + } + } + + private static class Statistics { + public long version; + public String rowFormat; + public long tableRows = 0; + public long avgRowLength = 0; + public long dataLength = 0; + public long maxDataLength = 0; + public long indexLength = 0; + public long dataFree = 0; + public String autoIncrement; + public String createTime; + public String updateTime; + public String checkTime; + public String tableCollation; + public String checksum; + public String createOptions; + public String tableComment; + public long cnt = 0; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTtlInfoHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTtlInfoHandler.java new file mode 100644 index 000000000..cbdb1996b --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTtlInfoHandler.java @@ -0,0 +1,71 @@ +package com.alibaba.polardbx.executor.handler.subhandler; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlLoggerUtil; +import com.alibaba.polardbx.executor.handler.VirtualViewHandler; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.ttl.TtlInfoAccessor; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.ttl.TtlArchiveKind; +import com.alibaba.polardbx.optimizer.view.InformationSchemaTtlInfo; +import com.alibaba.polardbx.optimizer.view.VirtualView; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by guxu. + * + * @author guxu + */ +public class InformationSchemaTtlInfoHandler extends BaseVirtualViewSubClassHandler { + public InformationSchemaTtlInfoHandler(VirtualViewHandler virtualViewHandler) { + super(virtualViewHandler); + } + + @Override + public boolean isSupport(VirtualView virtualView) { + return virtualView instanceof InformationSchemaTtlInfo; + } + + @Override + public Cursor handle(VirtualView virtualView, ExecutionContext executionContext, ArrayResultCursor cursor) { + + List ttlInfoRecs = new ArrayList<>(); + try (Connection metaDbConn = MetaDbDataSource.getInstance().getConnection()) { + TtlInfoAccessor ttlInfoAccessor = new TtlInfoAccessor(); + ttlInfoAccessor.setConnection(metaDbConn); + ttlInfoRecs = ttlInfoAccessor.queryAllTtlInfoList(); + } catch (Throwable ex) { + TtlLoggerUtil.TTL_TASK_LOGGER.error(ex); + throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, ex); + } + + for (int i = 0; i < ttlInfoRecs.size(); i++) { + TtlInfoRecord ttlInfoRec = ttlInfoRecs.get(i); + cursor.addRow(new Object[] { + ttlInfoRec.getTableSchema(), + ttlInfoRec.getTableName(), + ttlInfoRec.getTtlStatus() == TtlInfoRecord.TTL_STATUS_ENABLE_SCHEDULE ? + TtlInfoRecord.TTL_STATUS_ENABLE_SCHEDULE_STR_VAL : + TtlInfoRecord.TTL_STATUS_DISABLE_SCHEDULE_STR_VAL, + ttlInfoRec.getTtlCol(), + ttlInfoRec.getTtlExpr(), + ttlInfoRec.getTtlCron(), + TtlArchiveKind.of(ttlInfoRec.getArcKind()).getArchiveKindStr(), + ttlInfoRec.getArcTblSchema(), + ttlInfoRec.getArcTblName(), + ttlInfoRec.getArcPrePartCnt(), + ttlInfoRec.getArcPostPartCnt() + }); + } + + return cursor; + } +} + diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTtlScheduleHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTtlScheduleHandler.java new file mode 100644 index 000000000..6a82b0940 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTtlScheduleHandler.java @@ -0,0 +1,105 @@ +package com.alibaba.polardbx.executor.handler.subhandler; + +import com.alibaba.polardbx.common.exception.NotSupportException; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler.TtlScheduledJobStatManager; +import com.alibaba.polardbx.executor.handler.VirtualViewHandler; +import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.executor.sync.ISyncAction; +import com.alibaba.polardbx.executor.sync.SyncManagerHelper; +import com.alibaba.polardbx.gms.scheduler.ScheduleDateTimeConverter; +import com.alibaba.polardbx.gms.scheduler.ScheduledJobExecutorType; +import com.alibaba.polardbx.gms.scheduler.ScheduledJobsRecord; +import com.alibaba.polardbx.gms.sync.SyncScope; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.function.calc.scalar.CanAccessTable; +import com.alibaba.polardbx.optimizer.view.InformationSchemaTtlSchedule; +import com.alibaba.polardbx.optimizer.view.VirtualView; + +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by guxu. + * + * @author guxu + */ +public class InformationSchemaTtlScheduleHandler extends BaseVirtualViewSubClassHandler { + + public static final DateTimeFormatter ISO_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + private static Class ttlScheduleViewSyncActionClass; + + static { + // 只有server支持,这里是暂时改法,后续要将这段逻辑解耦 + try { + ttlScheduleViewSyncActionClass = + Class.forName("com.alibaba.polardbx.server.response.TtlScheduleViewSyncAction"); + } catch (ClassNotFoundException e) { + throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, e, e.getMessage()); + } + } + + public InformationSchemaTtlScheduleHandler(VirtualViewHandler virtualViewHandler) { + super(virtualViewHandler); + } + + @Override + public boolean isSupport(VirtualView virtualView) { + return virtualView instanceof InformationSchemaTtlSchedule; + } + + @Override + public Cursor handle(VirtualView virtualView, ExecutionContext executionContext, ArrayResultCursor cursor) { + + InformationSchemaTtlSchedule ttlScheduleView = (InformationSchemaTtlSchedule) virtualView; + + ISyncAction ttlScheduleSyncAction; + if (ttlScheduleViewSyncActionClass == null) { + throw new NotSupportException(); + } + try { + ttlScheduleSyncAction = + (ISyncAction) ttlScheduleViewSyncActionClass.getConstructor().newInstance(); + } catch (Exception e) { + throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, e, e.getMessage()); + } + + List>> resultsOfAllNodes = + SyncManagerHelper.sync(ttlScheduleSyncAction, SyncScope.MASTER_ONLY); + + if (resultsOfAllNodes == null) { + return cursor; + } + + for (int i = 0; i < resultsOfAllNodes.size(); i++) { + List> resultsOfOneNode = resultsOfAllNodes.get(i); + if (resultsOfOneNode == null) { + continue; + } + for (int j = 0; j < resultsOfOneNode.size(); j++) { + Map oneRow = resultsOfOneNode.get(j); + String tableSchema = (String) oneRow.get("TABLE_SCHEMA"); + String tableName = (String) oneRow.get("TABLE_NAME"); + String metricKey = (String) oneRow.get("METRIC_KEY"); + String metricVal = (String) oneRow.get("METRIC_VAL"); + cursor.addRow(new Object[] { + tableSchema, + tableName, + metricKey, + metricVal + }); + } + } + + return cursor; + } +} + diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/VirtualStatisticHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/VirtualStatisticHandler.java index b0f468211..7ba316339 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/VirtualStatisticHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/handler/subhandler/VirtualStatisticHandler.java @@ -124,7 +124,8 @@ public Cursor handle(VirtualView virtualView, ExecutionContext executionContext, for (IndexMeta indexMeta : tableMeta.getIndexes()) { Set cols = indexMeta.getKeyColumns().stream().map(ColumnMeta::getOriginColumnName) .collect(Collectors.toSet()); - if (cols.size() == 1) { + //80 函数索引没有列名 + if (cols.size() <= 1) { continue; } String columnsName = StatisticUtils.buildColumnsName(cols); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/Session.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/Session.java index 23580bd33..f984ec539 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/Session.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/Session.java @@ -24,7 +24,6 @@ import com.alibaba.polardbx.executor.common.StorageInfoManager; import com.alibaba.polardbx.executor.mpp.execution.SessionRepresentation; import com.alibaba.polardbx.executor.mpp.execution.StageId; -import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.executor.utils.GroupingFetchLSN; import com.alibaba.polardbx.gms.topology.SystemDbHelper; import com.alibaba.polardbx.optimizer.context.ExecutionContext; @@ -38,6 +37,7 @@ import java.util.concurrent.ConcurrentHashMap; import static com.alibaba.polardbx.common.jdbc.ITransactionPolicy.TransactionClass.AUTO_COMMIT_SINGLE_SHARD; +import static com.alibaba.polardbx.common.jdbc.ITransactionPolicy.TransactionClass.COLUMNAR_READ_ONLY_TRANSACTION; import static com.alibaba.polardbx.common.jdbc.ITransactionPolicy.TransactionClass.TSO_TRANSACTION; import static com.alibaba.polardbx.util.MoreObjects.toStringHelper; @@ -121,35 +121,43 @@ public boolean isPreferLocal() { } public void generateTsoInfo() throws SQLException { - if (ExecutorContext.getContext( - getSchema()).getStorageInfoManager().supportTso() && - clientContext.getParamManager().getBoolean(ConnectionParams.ENABLE_CONSISTENT_REPLICA_READ) && - !getSchema().equalsIgnoreCase(SystemDbHelper.DEFAULT_META_DB_NAME) && - (ExecUtils.existMppOnlyInstanceNode() || clientContext.getParamManager() - .getBoolean(ConnectionParams.ENABLE_MASTER_MPP)) - ) { - ITransaction iTransaction = clientContext.getTransaction(); - if (iTransaction.getTransactionClass().isA(TSO_TRANSACTION)) { - if (iTransaction.getTransactionClass() == AUTO_COMMIT_SINGLE_SHARD) { - final StorageInfoManager storageInfoManager = - ExecutorContext.getContext(getSchema()).getStorageInfoManager(); - this.lizard1PC = storageInfoManager.supportLizard1PCTransaction(); - this.omitTso = storageInfoManager.supportCtsTransaction() || this.lizard1PC; - } - if (!omitTso) { - long externalTso = clientContext.getSnapshotTs(); - this.tsoTime = externalTso > 0 ? externalTso : - ((IMppTsoTransaction) clientContext.getTransaction()).nextTimestamp(t -> { - }); - } - for (Map.Entry group : groups.entrySet()) { - GroupingFetchLSN.getInstance() - .fetchLSN(ExecutorContext.getContext(group.getValue()).getTopologyExecutor().getTopology(), - group.getKey(), dnLsns, this.tsoTime); + ITransaction iTransaction = clientContext.getTransaction(); + if (iTransaction.getTransactionClass() == COLUMNAR_READ_ONLY_TRANSACTION) { + long externalTso = clientContext.getSnapshotTs(); + this.tsoTime = externalTso > 0 ? externalTso : + ((IMppTsoTransaction) clientContext.getTransaction()).nextTimestamp(t -> { + }); + } else { + if (ExecutorContext.getContext( + getSchema()).getStorageInfoManager().supportTso() && + clientContext.getParamManager().getBoolean(ConnectionParams.ENABLE_CONSISTENT_REPLICA_READ) && + !getSchema().equalsIgnoreCase(SystemDbHelper.DEFAULT_META_DB_NAME) + ) { + + if (iTransaction.getTransactionClass().isA(TSO_TRANSACTION)) { + if (iTransaction.getTransactionClass() == AUTO_COMMIT_SINGLE_SHARD) { + final StorageInfoManager storageInfoManager = + ExecutorContext.getContext(getSchema()).getStorageInfoManager(); + this.lizard1PC = storageInfoManager.supportLizard1PCTransaction(); + this.omitTso = storageInfoManager.supportCtsTransaction() || this.lizard1PC; + } + if (!omitTso) { + long externalTso = clientContext.getSnapshotTs(); + this.tsoTime = externalTso > 0 ? externalTso : + ((IMppTsoTransaction) clientContext.getTransaction()).nextTimestamp(t -> { + }); + } + + for (Map.Entry group : groups.entrySet()) { + GroupingFetchLSN.getInstance() + .fetchLSN(ExecutorContext.getContext(group.getValue()).getTopologyExecutor().getTopology(), + group.getKey(), dnLsns, this.tsoTime); + } } } } + } public SessionRepresentation toSessionRepresentation() { @@ -232,11 +240,11 @@ public SessionRepresentation toSessionRepresentation() { clientContext.getConnection().getLastInsertId(), clientContext.getTimeZone(), tsoTime, - clientContext.getFinalPlan().isUseColumnar(), + clientContext.isUseColumnar(), dnLsns, omitTso, lizard1PC, - clientContext.getColumnarTracer(), + clientContext.getUseColumnarTracer(), clientContext.getWorkloadType(), extraServerVariables); } @@ -273,4 +281,8 @@ public boolean isIgnoreSplitInfo() { public void setIgnoreSplitInfo(boolean ignoreSplitInfo) { this.ignoreSplitInfo = ignoreSplitInfo; } + + public long getTsoTime() { + return tsoTime; + } } \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/Threads.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/Threads.java index f783fd543..5e1d6ea6a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/Threads.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/Threads.java @@ -25,6 +25,18 @@ public class Threads { public static final boolean ENABLE_WISP = System.getProperties().containsKey( "com.alibaba.wisp.transparentWispSwitch"); + public static final boolean ENABLE_CGROUP; + + static { + final String CGROUP_KEY = "com.alibaba.polardbx.cgroup"; + if (System.getProperties().containsKey(CGROUP_KEY)) { + String val = System.getProperties().getProperty(CGROUP_KEY); + ENABLE_CGROUP = Boolean.parseBoolean(val); + } else { + ENABLE_CGROUP = false; + } + } + public static ThreadFactory threadsNamed(String nameFormat) { return new TenantThreadFactory(nameFormat, false); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/client/MppResultCursor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/client/MppResultCursor.java index 08d1c08c6..ad9f51333 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/client/MppResultCursor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/client/MppResultCursor.java @@ -46,6 +46,7 @@ public class MppResultCursor extends AbstractCursor { private int nextPos; private boolean bWaitQueryInfo; private CursorMeta cursorMeta; + private Runnable closeListenable; public MppResultCursor(LocalStatementClient client, ExecutionContext executionContext, CursorMeta cursorMeta) { super(false); @@ -54,6 +55,10 @@ public MppResultCursor(LocalStatementClient client, ExecutionContext executionCo this.cursorMeta = cursorMeta; } + public void addCloseListenable(Runnable closeListenable) { + this.closeListenable = closeListenable; + } + @Override public Row doNext() { if (currentChunk == null || currentChunk.getPositionCount() == nextPos) { @@ -94,6 +99,14 @@ public Row doNext() { @Override public List doClose(List exceptions) { + if (closeListenable != null) { + try { + closeListenable.run(); + } catch (Throwable t) { + // ignore + } + } + if (exceptions == null || exceptions.size() == 0) { if (ec.getRuntimeStatistics() != null && bWaitQueryInfo) { //analyze the sql diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/client/MppRunner.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/client/MppRunner.java index d8cf3adad..85940a352 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/client/MppRunner.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/client/MppRunner.java @@ -44,6 +44,10 @@ public MppRunner(RelNode relNode, ExecutionContext executionContext) { this.executionContext = executionContext; } + public static MppRunner create(RelNode relNode, ExecutionContext executionContext) { + return new MppRunner(relNode, executionContext); + } + public Cursor execute() { if (!ServiceProvider.getInstance().clusterMode()) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/LocalModule.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/LocalModule.java index 1ea8f2e78..13f290310 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/LocalModule.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/LocalModule.java @@ -16,6 +16,8 @@ package com.alibaba.polardbx.executor.mpp.deploy; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.MppConfig; import com.alibaba.polardbx.common.utils.version.Version; import com.alibaba.polardbx.executor.mpp.Threads; import com.alibaba.polardbx.executor.mpp.discover.LocalNodeManager; @@ -53,6 +55,7 @@ import com.alibaba.polardbx.executor.operator.spill.GenericSpillerFactory; import com.alibaba.polardbx.executor.operator.spill.SingleStreamSpillerFactory; import com.alibaba.polardbx.executor.operator.spill.SpillerFactory; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.node.AllNodes; import com.alibaba.polardbx.gms.node.InternalNode; import com.alibaba.polardbx.gms.node.InternalNodeManager; @@ -130,23 +133,25 @@ public void setup(Binder binder) { jaxrsBinder(binder).bind(NodeResource.class); //---------------- web ui ---------------------- - httpServerBinder(binder).bindResource("/ui", "webapp").withWelcomeFile("index.html"); - httpServerBinder(binder).bindResource("/tableau", "webapp/tableau"); - jaxrsBinder(binder).bind(WebUiResource.class); - - //---------------- server web ui ---------------------- - jaxrsBinder(binder).bind(QueryResource.class); - jaxrsBinder(binder).bind(StageResource.class); - jaxrsBinder(binder).bind(ClusterStatsResource.class); - jaxrsBinder(binder).bind(DdlResource.class); - httpClientBinder(binder).bindHttpClient("queryInfo", ForQueryInfo.class); - - //---------------- worker web ui ---------------------- - jaxrsBinder(binder).bind(ThreadResource.class); - jaxrsBinder(binder).bind(WorkerResource.class); - jaxrsBinder(binder).bind(StatusResource.class); - httpClientBinder(binder).bindHttpClient("workerInfo", ForWorkerInfo.class); - //----------------worker web ui ---------------------- + if (MppConfig.getInstance().isEnableMppUI()) { + httpServerBinder(binder).bindResource("/ui", "webapp").withWelcomeFile("index.html"); + httpServerBinder(binder).bindResource("/tableau", "webapp/tableau"); + jaxrsBinder(binder).bind(WebUiResource.class); + + //---------------- server web ui ---------------------- + jaxrsBinder(binder).bind(QueryResource.class); + jaxrsBinder(binder).bind(StageResource.class); + jaxrsBinder(binder).bind(ClusterStatsResource.class); + jaxrsBinder(binder).bind(DdlResource.class); + httpClientBinder(binder).bindHttpClient("queryInfo", ForQueryInfo.class); + + //---------------- worker web ui ---------------------- + jaxrsBinder(binder).bind(ThreadResource.class); + jaxrsBinder(binder).bind(WorkerResource.class); + jaxrsBinder(binder).bind(StatusResource.class); + httpClientBinder(binder).bindHttpClient("workerInfo", ForWorkerInfo.class); + //----------------worker web ui ---------------------- + } // Spiller binder.bind(FileCleaner.class).to(AsyncFileCleaner.class).in(Scopes.SINGLETON); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/LocalServer.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/LocalServer.java index cc402f8f6..adced1e24 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/LocalServer.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/LocalServer.java @@ -100,7 +100,10 @@ public void run() throws TddlRuntimeException { spillerFactory = injector.getInstance(SpillerFactory.class); nodeManager = injector.getInstance(InternalNodeManager.class); - this.manager = new PolarDBXNodeStatusManager(nodeManager, localNode); + if (ConfigDataMode.isPolarDbX()) { + this.manager = new PolarDBXNodeStatusManager(nodeManager, localNode); + this.manager.init(); + } } catch (Throwable t) { log.error("LocalServer start error.", t); throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, t, "LocalServer start error"); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/MainModule.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/MainModule.java index a253a2785..af9864b5b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/MainModule.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/MainModule.java @@ -47,6 +47,7 @@ import com.alibaba.polardbx.executor.operator.spill.GenericSpillerFactory; import com.alibaba.polardbx.executor.operator.spill.SingleStreamSpillerFactory; import com.alibaba.polardbx.executor.operator.spill.SpillerFactory; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.node.AllNodes; import com.alibaba.polardbx.gms.node.InternalNode; import com.alibaba.polardbx.gms.node.InternalNodeManager; @@ -146,9 +147,12 @@ public void setup(Binder binder) { }); //---------------- web ui ---------------------- - httpServerBinder(binder).bindResource("/ui", "webapp").withWelcomeFile("index.html"); - httpServerBinder(binder).bindResource("/tableau", "webapp/tableau"); - jaxrsBinder(binder).bind(WebUiResource.class); + if (MppConfig.getInstance().isEnableMppUI()) { + httpServerBinder(binder).bindResource("/ui", "webapp") + .withWelcomeFile("index.html"); + httpServerBinder(binder).bindResource("/tableau", "webapp/tableau"); + jaxrsBinder(binder).bind(WebUiResource.class); + } // Determine the NodeVersion NodeVersion nodeVersion = new NodeVersion(Version.getVersion()); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/MppServer.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/MppServer.java index 00cb96022..d8a95847e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/MppServer.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/deploy/MppServer.java @@ -68,8 +68,9 @@ public class MppServer extends Server { public MppServer(int id, boolean isMppServer, boolean isMppWorker, String serverHost, int mppHttpPort) { super(id, mppHttpPort); - log.warn("MppServer nodeId=" + id + ",isMppServer=" + isMppServer + ",isMppWorker=" + isMppWorker - + ",serverHost=" + serverHost + ",mppHttpPort=" + mppHttpPort); + log.warn( + "MppServer nodeId=" + id + ",isMppServer=" + isMppServer + ",isMppWorker=" + isMppWorker + ",serverHost=" + + serverHost + ",mppHttpPort=" + mppHttpPort); this.isMppWorker = isMppWorker; this.serverHost = serverHost; this.isMppServer = isMppServer; @@ -131,7 +132,10 @@ public void run() throws TddlRuntimeException { taskExecutor = injector.getInstance(TaskExecutor.class); spillerFactory = injector.getInstance(SpillerFactory.class); - this.manager = new PolarDBXNodeStatusManager(nodeManager, localNode); + if (ConfigDataMode.isPolarDbX()) { + this.manager = new PolarDBXNodeStatusManager(nodeManager, localNode); + this.manager.init(); + } } catch (Throwable t) { log.error("MppServer start error.", t); throw new TddlRuntimeException(ErrorCode.ERR_EXECUTE_MPP, t, "MppServer start error"); @@ -144,6 +148,14 @@ public TaskManager getTaskManager() { return taskManager; } + public synchronized void updateNodeId(int nodeId) { + log.warn("update mppServer nodeId=" + nodeId); + this.nodeId = NODEID_PREFIX + nodeId; + bootstrapProperties.put(BootstrapConfig.CONFIG_KEY_NODE_ID, this.nodeId); + this.localNode.setNodeIdentifier(this.nodeId); + } + + public LocalStatementClient newLocalStatementClient( ExecutionContext executionContext, RelNode node) { if (statementResource == null) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/ClusterNodeManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/ClusterNodeManager.java index c22d911a4..cb9075a24 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/ClusterNodeManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/ClusterNodeManager.java @@ -1,44 +1,22 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.executor.mpp.discover; +import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; -import com.alibaba.polardbx.executor.mpp.deploy.MppServer; +import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; import com.alibaba.polardbx.executor.mpp.metadata.ForNodeManager; -import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.gms.node.AllNodes; import com.alibaba.polardbx.gms.node.InternalNode; import com.alibaba.polardbx.gms.node.InternalNodeManager; import com.alibaba.polardbx.gms.node.Node; import com.alibaba.polardbx.gms.node.NodeServer; -import com.alibaba.polardbx.gms.node.NodeState; import com.alibaba.polardbx.gms.node.NodeStatusManager; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableSet; import io.airlift.http.client.HttpClient; import io.airlift.json.JsonCodec; import javax.inject.Inject; -import java.util.HashSet; -import java.util.List; import java.util.Set; -import java.util.concurrent.ScheduledExecutorService; public class ClusterNodeManager implements InternalNodeManager { @@ -51,112 +29,69 @@ public class ClusterNodeManager implements InternalNodeManager { private HttpClient httpClient; - private ScheduledExecutorService nodeStateUpdateExecutor; - - private MppServer mppServer; - @Inject public ClusterNodeManager(InternalNode currentNode, JsonCodec nodeInfoCodec, JsonCodec allNodeInfoCodec, @ForNodeManager HttpClient httpClient) { this.localNode = currentNode; - this.allNodes = new AllNodes(ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of()); + this.allNodes = new AllNodes( + ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of()); this.nodeInfoCodec = nodeInfoCodec; this.allNodeInfoCodec = allNodeInfoCodec; this.httpClient = httpClient; } - @Override - public Set getNodes(NodeState state, boolean slaveFirst) { - switch (state) { - case ACTIVE: - if (slaveFirst) { - Set otherActiveNodes = getAllNodes().getOtherActiveNodes(); - if (otherActiveNodes != null && !otherActiveNodes.isEmpty()) { - return otherActiveNodes; - } - } - return getAllNodes().getActiveNodes(); - case INACTIVE: - return getAllNodes().getInactiveNodes(); - case SHUTTING_DOWN: - return getAllNodes().getShuttingDownNodes(); - default: - throw new IllegalArgumentException("Unknown node state " + state); - } - } - @Override public Node getCurrentNode() { return localNode; } - @Override - @Deprecated - public Set getCoordinators() { - Set coordinators = new HashSet<>(); - for (Node node : allNodes.getActiveNodes()) { - if (node.isCoordinator()) { - coordinators.add(node); - } - } - return coordinators; - } - @Override public AllNodes getAllNodes() { return allNodes; } - @Override - public void refreshNodes() { - //TODO 向manager主动获取节点信息 - } - @Override public void removeNode(NodeServer nodeServer, String schema) { if (nodeServer != null) { - for (InternalNode node : allNodes.getActiveNodes()) { - if (node.getNodeServer() != null && node.getNodeServer().equals(nodeServer)) { - logger.warn("temp removeNode:" + node); - - allNodes.getActiveNodes().remove(node); - allNodes.getOtherActiveNodes().remove(node); - NodeStatusManager manager = ExecUtils.getStatusManager(schema); - manager.tempInactiveNode(node); - break; - } + markInactiveNode(allNodes.getActiveNodes(), nodeServer); + markInactiveNode(allNodes.getOtherActiveRowNodes(), nodeServer); + markInactiveNode(allNodes.getOtherActiveColumnarNodes(), nodeServer); + } + } + + private void markInactiveNode(Set nodes, NodeServer nodeServer) { + for (InternalNode node : nodes) { + if (node.getNodeServer() != null && node.getNodeServer().equals(nodeServer)) { + nodes.remove(node); + NodeStatusManager manager = ServiceProvider.getInstance().getServer().getStatusManager(); + manager.tempInactiveNode(node); + break; } } } @Override - public synchronized void updateNodes(Set activeNodes, Set otherActiveNodes, - Set inactiveNodes, Set shuttingDownNodes) { + public synchronized void updateNodes(Set currentActiveNodes, Set remoteActiveRowNodes, + Set remoteActiveColumnarNodes, + Set inactiveNodes, + Set shuttingDownNodes) { if (logger.isDebugEnabled()) { logger.debug( - "updateNodes:activeNodes=" + activeNodes + ",otherActiveNodes=" + otherActiveNodes + ",inactiveNodes=" + "updateNodes:activeNodes=" + currentActiveNodes + ",otherActiveNodes=" + remoteActiveRowNodes + + ",remoteActiveColumnarNodes=" + remoteActiveColumnarNodes + ",inactiveNodes=" + inactiveNodes + "," + "shuttingDownNodes=" + shuttingDownNodes); } - allNodes.setActiveNodes(activeNodes, otherActiveNodes); - allNodes.setInactiveNodes(inactiveNodes); - allNodes.setShuttingDownNodes(shuttingDownNodes); - } + allNodes.updateActiveNodes(currentActiveNodes, remoteActiveRowNodes, remoteActiveColumnarNodes, inactiveNodes, + shuttingDownNodes); - @Override - public List getAllWorkers(boolean slaveFirst) { - return allNodes.getAllWorkers(slaveFirst); - } - - @Override - public List getAllCoordinators() { - return allNodes.getAllCoordinators(); - } - - public void setAllNodes(AllNodes allNodes) { - this.allNodes = allNodes; + if (remoteActiveColumnarNodes.isEmpty()) { + DynamicConfig.getInstance().existColumnarNodes(false); + } else { + DynamicConfig.getInstance().existColumnarNodes(true); + } } public InternalNode getLocalNode() { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/DiscoveryManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/DiscoveryManager.java deleted file mode 100644 index ff7c588a0..000000000 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/DiscoveryManager.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.executor.mpp.discover; - -import com.alibaba.polardbx.common.utils.logger.Logger; -import com.alibaba.polardbx.common.utils.logger.LoggerFactory; -import com.alibaba.polardbx.executor.mpp.Threads; -import com.alibaba.polardbx.executor.mpp.deploy.MppServer; -import com.alibaba.polardbx.executor.mpp.deploy.Server; -import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; -import com.alibaba.polardbx.gms.node.AllNodes; -import com.alibaba.polardbx.gms.node.InternalNode; -import com.alibaba.polardbx.gms.node.NodeState; -import com.google.common.net.HttpHeaders; -import com.google.common.net.MediaType; -import io.airlift.http.client.HttpUriBuilder; -import io.airlift.http.client.JsonBodyGenerator; -import io.airlift.http.client.Request; - -import java.net.URI; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import static io.airlift.http.client.HttpUriBuilder.uriBuilderFrom; -import static io.airlift.http.client.JsonBodyGenerator.jsonBodyGenerator; -import static io.airlift.http.client.JsonResponseHandler.createJsonResponseHandler; -import static io.airlift.http.client.Request.Builder.prepareDelete; -import static io.airlift.http.client.Request.Builder.preparePost; -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; - -public class DiscoveryManager { - - private static final Logger logger = LoggerFactory.getLogger(DiscoveryManager.class); - private static DiscoveryManager instance; - private ScheduledExecutorService nodeStateUpdateExecutor; - private Map nodeMap = new ConcurrentHashMap<>(); - private Server server; - - public static DiscoveryManager getInstance() { - if (instance == null) { - synchronized (DiscoveryManager.class) { - if (instance == null) { - instance = new DiscoveryManager(); - } - } - } - return instance; - } - - private DiscoveryManager() { - if (ServiceProvider.getInstance().clusterMode()) { - this.nodeStateUpdateExecutor = newSingleThreadScheduledExecutor( - Threads.threadsNamed("discovery-node-state")); - this.server = ServiceProvider.getInstance().getServer(); - nodeStateUpdateExecutor.scheduleWithFixedDelay(() -> { - if (server != null && server.getLocalNode().isLeader()) { - try { - boolean changed = false; - if (nodeMap.size() > 0) { - //30s未心跳,认为节点不可用 - long timeInactive = System.currentTimeMillis() - 30000L; - for (String nodeId : nodeMap.keySet()) { - NodeDiscoveryStatus status = nodeMap.get(nodeId); - if (status != null && status.nodestate == NodeState.ACTIVE - && status.modifyTime < timeInactive) { - status.nodestate = NodeState.INACTIVE; - changed = true; - logger.warn("inactive node:" + status.node); - } - } - } - if (changed) { - updateNodes(); - } - } catch (Exception e) { - logger.error(e); - } - } - }, 5, 5, TimeUnit.SECONDS); - } - } - - public void updateNodes() { - if (!ServiceProvider.getInstance().clusterMode()) { - return; - } - Set activeNodes = new HashSet<>(); - Set inactiveNodes = new HashSet<>(); - Set shuttingDownNodes = new HashSet<>(); - for (String nodeId : nodeMap.keySet()) { - NodeDiscoveryStatus status = nodeMap.get(nodeId); - switch (status.nodestate) { - case ACTIVE: - if (!status.node.isInBlacklist()) { - activeNodes.add(status.node); - } - break; - case SHUTTING_DOWN: - shuttingDownNodes.add(status.node); - break; - case INACTIVE: - case TEMP_INACTIVE: - inactiveNodes.add(status.node); - break; - default: - break; - } - } - ((MppServer) server).getNodeManager().updateNodes(activeNodes, null, inactiveNodes, shuttingDownNodes); - } - - public boolean notifyNode(InternalNode node) { - NodeDiscoveryStatus dnode = nodeMap.get(node.getNodeIdentifier()); - if (dnode != null && dnode.nodestate == NodeState.ACTIVE) { - dnode.modifyTime = System.currentTimeMillis(); - if (!dnode.node.toString().equals(node.toString())) { - logger.warn("modify node:" + node); - dnode.node = node; - updateNodes(); - return true; - } - } else if (dnode != null && dnode.nodestate == NodeState.TEMP_INACTIVE) { - if (logger.isDebugEnabled()) { - logger.debug("check temp inactive node:" + node); - } - if (System.currentTimeMillis() - dnode.modifyTime > 60000L) { - logger.warn("reactive node:" + node); - nodeMap.put(node.getNodeIdentifier(), new NodeDiscoveryStatus(node)); - updateNodes(); - return true; - } - } else { - logger.warn("input node:" + node); - nodeMap.put(node.getNodeIdentifier(), new NodeDiscoveryStatus(node)); - updateNodes(); - return true; - } - return false; - } - - public boolean removeNode(InternalNode node, String type) { - logger.warn("removeNode:" + node.getNodeIdentifier() + ",type=" + type); - NodeDiscoveryStatus dnode = nodeMap.get(node.getNodeIdentifier()); - if (dnode != null) { - if (type.equalsIgnoreCase("temp") && dnode.nodestate == NodeState.ACTIVE) { - dnode.modifyTime = System.currentTimeMillis(); - dnode.nodestate = NodeState.TEMP_INACTIVE; - updateNodes(); - return true; - } else if (type.equalsIgnoreCase("black")) { - dnode.node.setInBlacklist(true); - updateNodes(); - return true; - } else if (type.equalsIgnoreCase("unblack")) { - dnode.node.setInBlacklist(false); - updateNodes(); - return true; - } - } - return false; - } - - - class NodeDiscoveryStatus { - InternalNode node; - long modifyTime; - NodeState nodestate; - - public NodeDiscoveryStatus(InternalNode node) { - this.node = node; - this.modifyTime = System.currentTimeMillis(); - this.nodestate = NodeState.ACTIVE; - } - } -} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/LocalNodeManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/LocalNodeManager.java index 751eaef42..25c635e54 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/LocalNodeManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/LocalNodeManager.java @@ -23,12 +23,9 @@ import com.alibaba.polardbx.gms.node.InternalNodeManager; import com.alibaba.polardbx.gms.node.Node; import com.alibaba.polardbx.gms.node.NodeServer; -import com.alibaba.polardbx.gms.node.NodeState; import com.google.common.collect.ImmutableSet; import javax.inject.Inject; -import java.util.HashSet; -import java.util.List; import java.util.Set; public class LocalNodeManager implements InternalNodeManager { @@ -42,27 +39,8 @@ public class LocalNodeManager implements InternalNodeManager { public LocalNodeManager(InternalNode currentNode) { this.localNode = currentNode; this.allNodes = - new AllNodes(ImmutableSet.of(localNode), ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of()); - } - - @Override - public Set getNodes(NodeState state, boolean slaveFirst) { - switch (state) { - case ACTIVE: - if (slaveFirst) { - Set otherActiveNodes = getAllNodes().getOtherActiveNodes(); - if (otherActiveNodes != null && !otherActiveNodes.isEmpty()) { - return otherActiveNodes; - } - } - return getAllNodes().getActiveNodes(); - case INACTIVE: - return getAllNodes().getInactiveNodes(); - case SHUTTING_DOWN: - return getAllNodes().getShuttingDownNodes(); - default: - throw new IllegalArgumentException("Unknown node state " + state); - } + new AllNodes(ImmutableSet.of(localNode), ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of(), + ImmutableSet.of()); } @Override @@ -70,51 +48,26 @@ public Node getCurrentNode() { return localNode; } - @Override - public Set getCoordinators() { - Set coordinators = new HashSet<>(); - for (Node node : allNodes.getActiveNodes()) { - if (node.isCoordinator()) { - coordinators.add(node); - } - } - return coordinators; - } - @Override public AllNodes getAllNodes() { return allNodes; } - @Override - public void refreshNodes() { - throw new IllegalStateException(); - } - @Override public void removeNode(NodeServer nodeServer, String schema) { throw new IllegalStateException(); } @Override - public synchronized void updateNodes(Set activeNodes, Set otherActiveNodes, - Set inactiveNodes, Set shuttingDownNodes) { + public synchronized void updateNodes(Set currentActiveNodes, Set remoteActiveRowNodes, + Set remoteActiveColumnarNodes, Set inactiveNodes, + Set shuttingDownNodes) { if (logger.isDebugEnabled()) { - logger.debug("updateNodes:activeNodes=" + activeNodes + ",inactiveNodes=" + inactiveNodes + "," + - "shuttingDownNodes=" + shuttingDownNodes); + logger.debug("updateNodes:activeNodes=" + currentActiveNodes + ",otherActiveNodes=" + remoteActiveRowNodes + + ",remoteActiveColumnarNodes=" + remoteActiveColumnarNodes + ",inactiveNodes=" + inactiveNodes + "," + + "shuttingDownNodes=" + shuttingDownNodes); } - allNodes.setActiveNodes(activeNodes, otherActiveNodes); - allNodes.setInactiveNodes(inactiveNodes); - allNodes.setShuttingDownNodes(shuttingDownNodes); - } - - @Override - public List getAllWorkers(boolean slaveFirst) { - return allNodes.getAllWorkers(slaveFirst); - } - - @Override - public List getAllCoordinators() { - return allNodes.getAllCoordinators(); + allNodes.updateActiveNodes(currentActiveNodes, remoteActiveRowNodes, remoteActiveColumnarNodes, inactiveNodes, + shuttingDownNodes); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/PolarDBXNodeStatusManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/PolarDBXNodeStatusManager.java index ff86f7bf2..c8de274c4 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/PolarDBXNodeStatusManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/PolarDBXNodeStatusManager.java @@ -19,6 +19,7 @@ import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.thread.NamedThreadFactory; import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.executor.utils.ExecUtils; @@ -37,7 +38,6 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.List; -import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -51,7 +51,6 @@ public class PolarDBXNodeStatusManager extends NodeStatusManager { public PolarDBXNodeStatusManager(InternalNodeManager nodeManager, InternalNode localNode) { super(nodeManager, NODE_INFO, localNode); - init(); } @Override @@ -81,18 +80,6 @@ protected void doInit() { ExecUtils.syncNodeStatus(SystemDbHelper.DEFAULT_DB_NAME); } - @Override - protected void updateActiveNodes(String instId, InternalNode node, Set activeNodes, - Set otherActiveNodes, int role) { - if (localNode.getInstId().equalsIgnoreCase(instId)) { - //主实例或者当前节点是只读实例,取这个只读实例相同instId的节点 - activeNodes.add(node); - } else if (ConfigDataMode.isMasterMode() && (role & ROLE_HTAP) == ROLE_HTAP) { - //当前处理是主实例,且获取的节点开启了HTAP节点 - otherActiveNodes.add(node); - } - } - @Override protected void doDestroy(boolean stop) { if (injectFuture != null) { @@ -143,12 +130,23 @@ protected String updateTableMetaSql(int status) { //polarx只读实例,需要处理节点类型的变化 if (gmsNode != null && !ConfigDataMode.isMasterMode()) { boolean changeHtapRole = false; - if (gmsNode.instType == ServerInfoRecord.INST_TYPE_HTAP_SLAVE && !localNode.isHtap()) { - localNode.setHtap(true); - changeHtapRole = true; - } else if (gmsNode.instType != ServerInfoRecord.INST_TYPE_HTAP_SLAVE && localNode.isHtap()) { - localNode.setHtap(false); - changeHtapRole = true; + + if (ConfigDataMode.isRowSlaveMode()) { + if (gmsNode.instType == ServerInfoRecord.INST_TYPE_HTAP_SLAVE && !localNode.isHtap()) { + localNode.setHtap(true); + changeHtapRole = true; + } else if (gmsNode.instType != ServerInfoRecord.INST_TYPE_HTAP_SLAVE && localNode.isHtap()) { + localNode.setHtap(false); + changeHtapRole = true; + } + } else { + if (!localNode.isHtap() && DynamicConfig.getInstance().allowColumnarBindMaster()) { + localNode.setHtap(true); + changeHtapRole = true; + } else if (localNode.isHtap() && !DynamicConfig.getInstance().allowColumnarBindMaster()) { + localNode.setHtap(false); + changeHtapRole = true; + } } if (logger.isDebugEnabled()) { @@ -245,7 +243,7 @@ protected void checkLeader(Connection conn, String leaderId) { private void resetLeaderStatus() { localNode.setLeader(false); - List coordinators = nodeManager.getAllCoordinators(); + List coordinators = nodeManager.getAllNodes().getAllCoordinators(); if (coordinators != null && !coordinators.isEmpty()) { for (Node node : coordinators) { if (node.isLeader() && node.getNodeIdentifier().equalsIgnoreCase(localNode.getNodeIdentifier())) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/RefreshNodeSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/RefreshNodeSyncAction.java index 018b6a96e..db02aca44 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/RefreshNodeSyncAction.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/discover/RefreshNodeSyncAction.java @@ -18,7 +18,7 @@ import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; -import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; import com.alibaba.polardbx.gms.node.NodeStatusManager; import com.alibaba.polardbx.gms.sync.IGmsSyncAction; @@ -41,7 +41,7 @@ public RefreshNodeSyncAction(String schemaName) { @Override public Object sync() { - NodeStatusManager manager = ExecUtils.getStatusManager(schemaName); + NodeStatusManager manager = ServiceProvider.getInstance().getServer().getStatusManager(); if (manager != null) { manager.refreshNode(); logger.info("refreshAllNode end"); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/LocationFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/LocationFactory.java index 09156e567..a22ff49d1 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/LocationFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/LocationFactory.java @@ -39,7 +39,7 @@ public interface LocationFactory { URI createRuntimeFilterLocation(String queryId); - URI createDdlFilterLocktion(String ddlJobId); + URI createDdlFilterLocation(String ddlJobId); URI createStageLocation(StageId stageId); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SessionRepresentation.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SessionRepresentation.java index 509feb54c..f3df2fca0 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SessionRepresentation.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SessionRepresentation.java @@ -73,7 +73,7 @@ public class SessionRepresentation { private WorkloadType workloadType; private boolean omitTso; private boolean lizard1PC; - private ColumnarTracer columnarTracer; + private boolean useColumnarTracer; /** * 暂时只增加polardbx_server_id参数,避免长度增加较多;后续如有需要可以再修改 @@ -109,7 +109,7 @@ public SessionRepresentation( @JsonProperty("dnLsnMap") Map dnLsnMap, @JsonProperty("omitTso") boolean omitTso, @JsonProperty("lizard1PC") boolean lizard1PC, - @JsonProperty("columnarTracer") ColumnarTracer columnarTracer, + @JsonProperty("useColumnarTracer") boolean useColumnarTracer, @JsonProperty("workloadType") WorkloadType workloadType, @JsonProperty("extraServerVariables") Map extraServerVariables) { this.traceId = traceId; @@ -139,7 +139,7 @@ public SessionRepresentation( this.dnLsnMap = dnLsnMap; this.omitTso = omitTso; this.lizard1PC = lizard1PC; - this.columnarTracer = columnarTracer; + this.useColumnarTracer = useColumnarTracer; this.workloadType = workloadType; this.extraServerVariables = extraServerVariables; } @@ -172,7 +172,7 @@ public SessionRepresentation( Map dnLsnMap, boolean omitTso, boolean lizard1PC, - ColumnarTracer columnarTracer, + boolean useColumnarTracer, WorkloadType workloadType, Map extraServerVariables) { this.traceId = traceId; @@ -203,7 +203,7 @@ public SessionRepresentation( this.workloadType = workloadType; this.omitTso = omitTso; this.lizard1PC = lizard1PC; - this.columnarTracer = columnarTracer; + this.useColumnarTracer = useColumnarTracer; this.extraServerVariables = extraServerVariables; } @@ -352,6 +352,11 @@ public Map getExtraServerVariables() { return extraServerVariables; } + @JsonProperty + public boolean getUseColumnarTracer() { + return useColumnarTracer; + } + @Override public String toString() { return MoreObjects.toStringHelper(this) @@ -366,7 +371,7 @@ public String toString() { .toString(); } - public Session toSession(TaskId taskId, QueryContext queryContext, long trxId) { + public Session toSession(TaskId taskId, QueryContext queryContext, long trxId, ColumnarTracer columnarTracer) { ExecutionContext ec = TaskResource.getDrdsContextHandler().makeExecutionContext(schema, hintCmds, txIsolation); ec.setTxId(trxId); if (tsoTimeStamp > 0 || omitTso) { @@ -460,12 +465,4 @@ public Session toSession(TaskId taskId, QueryContext queryContext, long trxId) { return new Session(taskId.getStageId(), ec); } - - public ColumnarTracer getColumnarTracer() { - return columnarTracer; - } - - public void setColumnarTracer(ColumnarTracer columnarTracer) { - this.columnarTracer = columnarTracer; - } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlQueryExecution.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlQueryExecution.java index a049a4d56..247a7853e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlQueryExecution.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlQueryExecution.java @@ -49,11 +49,12 @@ import com.alibaba.polardbx.executor.mpp.planner.StageExecutionPlan; import com.alibaba.polardbx.executor.mpp.planner.SubPlan; import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.gms.node.MppScope; import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; import com.alibaba.polardbx.optimizer.utils.TableTopologyUtil; -import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.google.common.base.Throwables; import com.google.inject.Inject; import io.airlift.units.Duration; @@ -78,7 +79,6 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.atomic.AtomicReference; -import static com.alibaba.polardbx.executor.utils.ExecUtils.existMppOnlyInstanceNode; import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.SECONDS; @@ -147,10 +147,13 @@ public void start() { long distributedPlanningStart = System.currentTimeMillis(); // plan distribution of query Pair subPlan = PlanFragmenter.buildRootFragment(physicalPlan, session); - int polarXParallelism = ExecUtils.getPolarDBXCores( - session.getClientContext().getParamManager(), !existMppOnlyInstanceNode()); int limitNode = session.getClientContext().getParamManager().getInt(ConnectionParams.MPP_NODE_SIZE); + boolean columnarMode = session.getClientContext().getParamManager() + .getBoolean(ConnectionParams.ENABLE_COLUMNAR_SCHEDULE); + MppScope mppScope = ExecUtils.getMppSchedulerScope(!columnarMode); if (limitNode <= 0) { + int polarXParallelism = ExecUtils.getPolarDBXCNCores( + session.getClientContext().getParamManager(), mppScope); limitNode = subPlan.getValue() % polarXParallelism > 0 ? subPlan.getValue() / polarXParallelism + 1 : subPlan.getValue() / polarXParallelism; } @@ -315,6 +318,21 @@ private QueryInfo buildQueryInfo(SqlQueryScheduler scheduler) { } ExecutionContext executionContext = session.getClientContext(); + //fetch ColumnarTrace in TaskInfo when stage is complete + if (executionContext.getColumnarTracer() != null && stageInfo.isPresent() && stageInfo.get().isCompleteInfo()) { + //enumerate all TaskInfo + for (StageInfo stage : StageInfo.getAllStages(stageInfo)) { + for (TaskInfo taskInfo : stage.getTasks()) { + executionContext.getColumnarTracer().mergeColumnarTracer(taskInfo.getColumnarTracer()); + if (logger.isDebugEnabled()) { + logger.debug( + "mergeColumnarTracer node: " + taskInfo.getColumnarTracer().getInstanceId() + " size " + + taskInfo.getColumnarTracer().getPruneRecordMap().size()); + } + } + } + } + if (executionContext.getDriverStatistics() != null && stageInfo.isPresent() && stageInfo.get().isCompleteInfo()) { // Check if this tree-structure StageInfo is completed and collect driver statistics. diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlQueryLocalExecution.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlQueryLocalExecution.java index 6f932a1fc..bfeecfc80 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlQueryLocalExecution.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlQueryLocalExecution.java @@ -24,6 +24,7 @@ import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.mpp.Session; import com.alibaba.polardbx.executor.mpp.execution.buffer.OutputBufferMemoryManager; +import com.alibaba.polardbx.executor.mpp.metadata.NotNull; import com.alibaba.polardbx.executor.mpp.metadata.Split; import com.alibaba.polardbx.executor.mpp.operator.Driver; import com.alibaba.polardbx.executor.mpp.operator.DriverContext; @@ -42,6 +43,7 @@ import com.alibaba.polardbx.optimizer.core.rel.LogicalView; import com.alibaba.polardbx.optimizer.memory.MemoryEstimator; import com.alibaba.polardbx.optimizer.utils.CalciteUtils; +import com.alibaba.polardbx.optimizer.utils.RelUtils; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -145,7 +147,7 @@ public void start() { new LocalExecutionPlanner(context, null, parallelism, parallelism, 1, context.getParamManager().getInt(ConnectionParams.PREFETCH_SHARDS), notificationExecutor, taskContext.isSpillable() ? spillerFactory : null, null, null, false, - -1, -1, ImmutableMap.of(), new SplitManagerImpl()); + -1, -1, ImmutableMap.of(), new SplitManagerImpl(), RelUtils.isSimpleMergeSortPlan(physicalPlan)); returnColumns = CalciteUtils.buildColumnMeta(physicalPlan, "Last"); boolean syncMode = stateMachine.getSession().isLocalResultIsSync(); @@ -298,7 +300,7 @@ private void schedulePartitionedSource(SplitInfo splitInfo, List drivers List> taskLocalSplits = new ArrayList<>(); filterDrivers.stream().forEach(driver -> taskLocalSplits.add(new ArrayList<>())); List splits = splitInfo.getSplits().iterator().next(); - int start = ThreadLocalRandom.current().nextInt(splits.size()); + int start = getRandomStart(splits); for (int i = 0; i < taskLocalSplits.size(); i++) { int index = i + start; for (int j = 0; j < splits.size(); j++) { @@ -331,6 +333,15 @@ private void schedulePartitionedSource(SplitInfo splitInfo, List drivers } } + /** + * Chooses a starting point randomly from the given split list for processing elements. + * + * @param splits The split list, which must not be null. + */ + int getRandomStart(@NotNull List splits) { + return splits.isEmpty() ? 0 : ThreadLocalRandom.current().nextInt(splits.size()); + } + private void enqueueDrivers(List runners, boolean highPriority) { List> finishedFutures = taskExecutor.enqueueSplits(taskHandle, highPriority, runners); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlTask.java index f6085a94f..bd149cf2c 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/SqlTask.java @@ -25,6 +25,7 @@ import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.mpp.OutputBuffers; import com.alibaba.polardbx.executor.mpp.Session; +import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; import com.alibaba.polardbx.executor.mpp.execution.buffer.BufferResult; import com.alibaba.polardbx.executor.mpp.execution.buffer.LazyOutputBuffer; import com.alibaba.polardbx.executor.mpp.execution.buffer.OutputBuffer; @@ -37,9 +38,11 @@ import com.alibaba.polardbx.executor.mpp.planner.PlanFragment; import com.alibaba.polardbx.executor.mpp.util.Failures; import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.gms.node.InternalNodeManager; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.memory.MemoryPool; import com.alibaba.polardbx.optimizer.memory.TaskMemoryPool; +import com.alibaba.polardbx.optimizer.statis.ColumnarTracer; import com.alibaba.polardbx.optimizer.statis.SQLOperation; import com.alibaba.polardbx.optimizer.statis.TaskMemoryStatisticsGroup; import com.alibaba.polardbx.statistics.ExecuteSQLOperation; @@ -108,6 +111,7 @@ public class SqlTask { private Session session; private volatile long trxId = -1; private String schema; + private ColumnarTracer columnarTracer; public SqlTask( String nodeId, @@ -381,6 +385,7 @@ private TaskInfo createInitialTaskInfo(TaskHolder taskHolder) { outputBuffer.getInfo(), ImmutableSet.of(), taskStats, + columnarTracer, needsPlan.get(), taskStatus.getState().isDone(), taskStats.getCompletedPipelineExecs(), @@ -402,6 +407,7 @@ private TaskInfo createInitialTaskInfo(TaskHolder taskHolder) { outputBuffer.getInfo(), ImmutableSet.of(), null, + columnarTracer, needsPlan.get(), taskStatus.getState().isDone(), taskStats.getCompletedPipelineExecs(), @@ -429,6 +435,7 @@ private TaskInfo createTaskInfo(TaskHolder taskHolder) { outputBuffer.getInfo(), noMoreSplits, taskStats, + columnarTracer, needsPlan.get(), taskStatus.getState().isDone(), taskStats.getCompletedPipelineExecs(), @@ -448,6 +455,7 @@ private TaskInfo createTaskInfo(TaskHolder taskHolder) { outputBuffer.getInfo(), noMoreSplits, taskStats, + columnarTracer, needsPlan.get(), taskStatus.getState().isDone(), taskStats.getCompletedPipelineExecs(), @@ -473,6 +481,7 @@ private TaskInfo createTaskInfoWithTaskStats(TaskHolder taskHolder) { outputBuffer.getInfo(), noMoreSplits, taskStats, + columnarTracer, needsPlan.get(), taskStatus.getState().isDone(), taskStats.getCompletedPipelineExecs(), @@ -528,8 +537,13 @@ public TaskInfo updateTask(SessionRepresentation sessionRepresentation, if (session == null) { schema = sessionRepresentation.getSchema(); + if (sessionRepresentation.isUseColumnar()) { + InternalNodeManager manager = ServiceProvider.getInstance().getServer().getNodeManager(); + this.columnarTracer = new ColumnarTracer(manager.getCurrentNode().getHostPort()); + } trxId = TrxIdGenerator.getInstance().nextId(); - session = sessionRepresentation.toSession(taskId, queryContext, trxId); + //set columnarTracer to ExecutionContext + session = sessionRepresentation.toSession(taskId, queryContext, trxId, columnarTracer); queryContext.registerTaskMemoryPool(session.getClientContext().getMemoryPool()); isMPPMetricEnabled = isSQLMetricEnabled( diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/TaskInfo.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/TaskInfo.java index aaa38fed8..6eb3d8374 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/TaskInfo.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/TaskInfo.java @@ -29,14 +29,15 @@ */ package com.alibaba.polardbx.executor.mpp.execution; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.common.collect.ImmutableSet; import com.alibaba.polardbx.executor.mpp.execution.buffer.BufferState; import com.alibaba.polardbx.executor.mpp.execution.buffer.OutputBufferInfo; import com.alibaba.polardbx.executor.mpp.metadata.TaskLocation; import com.alibaba.polardbx.executor.mpp.operator.TaskStats; +import com.alibaba.polardbx.optimizer.statis.ColumnarTracer; import com.alibaba.polardbx.util.MoreObjects; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.collect.ImmutableSet; import org.joda.time.DateTime; import javax.annotation.concurrent.Immutable; @@ -55,6 +56,7 @@ public class TaskInfo { new OutputBufferInfo(BufferState.OPEN, 0), ImmutableSet.of(), null, + null, true, false, getEmptyTaskStats().getCompletedPipelineExecs(), @@ -77,7 +79,7 @@ public static TaskInfo getEmptyTaskInfo() { private final OutputBufferInfo outputBuffers; private final Set noMoreSplits; private final TaskStats taskStats; - + private final ColumnarTracer columnarTracer; private final boolean needsPlan; private final boolean complete; @@ -98,6 +100,7 @@ public TaskInfo(@JsonProperty("taskStatus") TaskStatus taskStatus, @JsonProperty("outputBuffers") OutputBufferInfo outputBuffers, @JsonProperty("noMoreSplits") Set noMoreSplits, @JsonProperty("taskStats") TaskStats taskStats, + @JsonProperty("columnarTracer") ColumnarTracer columnarTracer, @JsonProperty("needsPlan") boolean needsPlan, @JsonProperty("complete") boolean complete, @JsonProperty("completedPipelineExecs") int completedPipelineExecs, @@ -109,12 +112,14 @@ public TaskInfo(@JsonProperty("taskStatus") TaskStatus taskStatus, @JsonProperty("processTimeMillis") long processTimeMillis, @JsonProperty("processWall") long processWall, @JsonProperty("pullDataTimeMillis") long pullDataTimeMillis, - @JsonProperty("deliveryTimeMillis") long deliveryTimeMillis) { + @JsonProperty("deliveryTimeMillis") long deliveryTimeMillis + ) { this.taskStatus = requireNonNull(taskStatus, "taskStatus is null"); this.lastHeartbeat = requireNonNull(lastHeartbeat, "lastHeartbeat is null"); this.outputBuffers = requireNonNull(outputBuffers, "outputBuffers is null"); this.noMoreSplits = requireNonNull(noMoreSplits, "noMoreSplits is null"); this.taskStats = taskStats; + this.columnarTracer = columnarTracer; this.needsPlan = needsPlan; this.complete = complete; @@ -159,6 +164,11 @@ public TaskStats getTaskStats() { return taskStats; } + @JsonProperty + public ColumnarTracer getColumnarTracer() { + return columnarTracer; + } + @JsonProperty public boolean isNeedsPlan() { return needsPlan; @@ -235,6 +245,7 @@ public static TaskInfo createInitialTask( new OutputBufferInfo(BufferState.OPEN, 0), ImmutableSet.of(), null, + null, true, false, taskStats.getCompletedPipelineExecs(), @@ -256,6 +267,7 @@ public TaskInfo withTaskStatus(TaskStatus newTaskStatus) { outputBuffers, noMoreSplits, taskStats, + columnarTracer, needsPlan, complete, completedPipelineExecs, totalPipelineExecs, cumulativeMemory, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/ColumnarNodeSelector.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/ColumnarNodeSelector.java index 5c7d7653f..c1bccfd35 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/ColumnarNodeSelector.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/ColumnarNodeSelector.java @@ -28,6 +28,7 @@ import com.alibaba.polardbx.gms.node.InternalNode; import com.alibaba.polardbx.gms.node.InternalNodeManager; import com.alibaba.polardbx.gms.node.Node; +import com.alibaba.polardbx.optimizer.utils.PartitionUtils; import com.google.common.collect.Multimap; import io.airlift.slice.XxHash64; @@ -187,7 +188,7 @@ private void assignByPartition(List splits, List candidateNodes, OssSplit ossSplit = (OssSplit) (split.getConnectorSplit()); int partNum = ossSplit.getPartIndex(); if (partNum < 0 && forceGenPart) { - partNum = OssSplit.calcPartition(ossSplit.getLogicalSchema(), ossSplit.getLogicalTableName(), + partNum = PartitionUtils.calcPartition(ossSplit.getLogicalSchema(), ossSplit.getLogicalTableName(), ossSplit.getPhysicalSchema(), ossSplit.getPhyTableNameList().get(0)); } int nodeId = partNum % candidateNodes.size(); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/NodeScheduler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/NodeScheduler.java index 03ba9c5a3..25377b564 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/NodeScheduler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/NodeScheduler.java @@ -17,14 +17,15 @@ package com.alibaba.polardbx.executor.mpp.execution.scheduler; import com.alibaba.polardbx.common.properties.ConnectionParams; -import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.executor.mpp.Session; import com.alibaba.polardbx.executor.mpp.execution.NodeTaskMap; +import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.gms.node.InternalNode; import com.alibaba.polardbx.gms.node.InternalNodeManager; -import com.alibaba.polardbx.gms.node.NodeState; +import com.alibaba.polardbx.gms.node.MppScope; import javax.inject.Inject; +import java.util.HashSet; import java.util.Set; public class NodeScheduler { @@ -41,18 +42,18 @@ public NodeScheduler(InternalNodeManager nodeManager, NodeTaskMap nodeTaskMap) { public NodeSelector createNodeSelector(Session session, int limit, boolean randomNode) { int maxSplitsPerNode = session.getClientContext().getParamManager().getInt(ConnectionParams.MPP_SCHEDULE_MAX_SPLITS_PER_NODE); - boolean slaveFirst = - session.getClientContext().getParamManager().getBoolean(ConnectionParams.POLARDBX_SLAVE_INSTANCE_FIRST); boolean enableOSSRoundRobin = session.getClientContext().getParamManager() .getBoolean(ConnectionParams.ENABLE_OSS_FILE_CONCURRENT_SPLIT_ROUND_ROBIN); - Set nodes = nodeManager.getNodes(NodeState.ACTIVE, ConfigDataMode.isMasterMode() && slaveFirst); - boolean columnarMode = session.getClientContext().getParamManager() .getBoolean(ConnectionParams.ENABLE_COLUMNAR_SCHEDULE); + MppScope mppScope = ExecUtils.getMppSchedulerScope(!columnarMode); + + Set nodes = new HashSet<>(nodeManager.getAllNodes().getAllWorkers(mppScope)); + boolean preferLocal = session.getClientContext().getParamManager().getBoolean(ConnectionParams.MPP_PREFER_LOCAL_NODE); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/metadata/HandleResolver.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/metadata/HandleResolver.java index 4175c4212..14c6ee01e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/metadata/HandleResolver.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/metadata/HandleResolver.java @@ -33,6 +33,7 @@ import com.alibaba.polardbx.executor.mpp.split.JdbcSplit; import com.alibaba.polardbx.executor.mpp.split.OssSplit; import com.alibaba.polardbx.executor.mpp.split.RemoteSplit; +import com.alibaba.polardbx.executor.mpp.split.SpecifiedOssSplit; import javax.inject.Inject; import java.util.Map.Entry; @@ -51,6 +52,7 @@ public HandleResolver() { handleResolvers.put("$scan", new MaterializedHandleResolver(JdbcSplit.class)); handleResolvers.put("$remote", new MaterializedHandleResolver(RemoteSplit.class)); handleResolvers.put("$ossScan", new MaterializedHandleResolver(OssSplit.class)); + handleResolvers.put("$specifiedOssScan", new MaterializedHandleResolver(SpecifiedOssSplit.class)); } public String getId(ConnectorSplit split) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/DriverContext.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/DriverContext.java index dfde59bd7..129f2d45e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/DriverContext.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/DriverContext.java @@ -432,6 +432,7 @@ public TaskInfo buildLocalModeTaskInfo(String queryId) { outputBufferInfo, ImmutableSet.of(), taskStats, + null, false, state.isDone(), taskStats.getCompletedPipelineExecs(), diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/LocalExecutionPlanner.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/LocalExecutionPlanner.java index 570cec737..f24d9ed83 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/LocalExecutionPlanner.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/LocalExecutionPlanner.java @@ -21,6 +21,8 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.utils.ExecutorMode; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.mpp.Session; @@ -75,6 +77,7 @@ import com.alibaba.polardbx.executor.mpp.planner.LocalExchange; import com.alibaba.polardbx.executor.mpp.planner.PipelineFragment; import com.alibaba.polardbx.executor.mpp.planner.PlanFragment; +import com.alibaba.polardbx.executor.mpp.planner.RangeScanUtils; import com.alibaba.polardbx.executor.mpp.planner.RemoteSourceNode; import com.alibaba.polardbx.executor.mpp.planner.SimpleFragmentRFManager; import com.alibaba.polardbx.executor.mpp.planner.WrapPipelineFragment; @@ -84,8 +87,10 @@ import com.alibaba.polardbx.executor.operator.util.bloomfilter.BloomFilterExpression; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.executor.vectorized.build.VectorizedExpressionBuilder; +import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.config.meta.CostModelWeight; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.core.join.EquiJoinKey; @@ -119,9 +124,15 @@ import com.alibaba.polardbx.optimizer.core.rel.TopN; import com.alibaba.polardbx.optimizer.core.rel.mpp.ColumnarExchange; import com.alibaba.polardbx.optimizer.core.rel.mpp.MppExchange; +import com.alibaba.polardbx.optimizer.core.rel.util.TargetTableInfo; +import com.alibaba.polardbx.optimizer.core.rel.util.TargetTableInfoOneTable; import com.alibaba.polardbx.optimizer.memory.MemoryPool; import com.alibaba.polardbx.optimizer.memory.MemoryType; +import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition; +import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy; +import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; import com.alibaba.polardbx.optimizer.utils.CalciteUtils; +import com.alibaba.polardbx.optimizer.utils.PartitionUtils; import com.alibaba.polardbx.optimizer.utils.PhyTableOperationUtil; import com.alibaba.polardbx.optimizer.utils.QueryConcurrencyPolicy; import com.alibaba.polardbx.optimizer.utils.RelUtils; @@ -162,15 +173,18 @@ import org.apache.calcite.rex.RexBuilder; import org.apache.calcite.rex.RexCall; import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.util.ImmutableBitSet; +import org.apache.calcite.util.ImmutableIntList; import org.apache.calcite.util.Pair; import java.net.URI; import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -233,6 +247,8 @@ public class LocalExecutionPlanner { private SplitManager splitManager; + private final boolean isSimpleMergeSort; + public LocalExecutionPlanner(ExecutionContext context, ExchangeClientSupplier exchangeClientSupplier, int defaultParallelism, int bkaJoinParallelism, int taskNumber, int prefetch, Executor notificationExecutor, SpillerFactory spillerFactory, @@ -241,6 +257,20 @@ public LocalExecutionPlanner(ExecutionContext context, ExchangeClientSupplier ex boolean enableRuntimeFilter, int localPartitionCount, int totalPartitionCount, Map splitCountMap, SplitManager splitManager) { + this(context, exchangeClientSupplier, defaultParallelism, bkaJoinParallelism, taskNumber, prefetch, + notificationExecutor, spillerFactory, httpClient, runtimeFilterUpdateUri, enableRuntimeFilter, + localPartitionCount, totalPartitionCount, splitCountMap, splitManager, false); + } + + public LocalExecutionPlanner(ExecutionContext context, ExchangeClientSupplier exchangeClientSupplier, + int defaultParallelism, int bkaJoinParallelism, int taskNumber, int prefetch, + Executor notificationExecutor, SpillerFactory spillerFactory, + HttpClient httpClient, + URI runtimeFilterUpdateUri, + boolean enableRuntimeFilter, + int localPartitionCount, int totalPartitionCount, + Map splitCountMap, SplitManager splitManager, + boolean isSimpleMergeSort) { this.exchangeClientSupplier = exchangeClientSupplier; this.totalPartitionCount = totalPartitionCount; this.pagesSerdeFactory = new PagesSerdeFactory(false); @@ -263,6 +293,7 @@ public LocalExecutionPlanner(ExecutionContext context, ExchangeClientSupplier ex this.localPartitionCount = localPartitionCount; this.splitCountMap = splitCountMap; this.splitManager = splitManager; + this.isSimpleMergeSort = isSimpleMergeSort; } public void setForbidMultipleReadConn(boolean forbidMultipleReadConn) { @@ -685,7 +716,7 @@ private ExecutorFactory visitBaseTable(RelNode parent, BaseTableOperation other, SplitInfo splitInfo = splitManager.getSingleSplit(logicalView, context); pipelineFragment.putSource(logicalView.getRelatedId(), splitInfo); return createViewFactory( - parent, logicalView, pipelineFragment, spillerFactory, 1, false); + parent, logicalView, pipelineFragment, spillerFactory, 1, false, null); } private ExecutorFactory visitUnion(RelNode parent, LogicalUnion union, PipelineFragment pipelineFragment) { @@ -957,7 +988,11 @@ private ExecutorFactory visitHashJoin(Join current, PipelineFragment fragment, } } - boolean useRF = context.getParamManager().getBoolean(ConnectionParams.ENABLE_NEW_RF); + // During the stage of configuring columnar parameters for the PlanExecutor, it's impossible to know the actual + // execution mode (MPP or AP_LOCAL). Therefore, when the ENABLE_NEW_RF parameter is actually invoked, + // the execution mode should be checked again. If it's AP_LOCAL mode, the runtime filter should be disabled. + boolean useRF = context.getParamManager().getBoolean(ConnectionParams.ENABLE_NEW_RF) + && context.getExecuteMode() == ExecutorMode.MPP; final boolean useXXHashRFinBuild = context.getParamManager().getBoolean(ConnectionParams.ENABLE_XXHASH_RF_IN_BUILD); final boolean useXXHashRFinFilter = @@ -1632,8 +1667,10 @@ private ExecutorFactory visitView( logicalView.setExpandView(true); } int prefetch = totalPrefetch; + RangeScanMode rangeScanMode = null; if (isCluster) { if (isUnderMergeSort || logicalView.pushedRelNodeIsSort()) { + rangeScanMode = RangeScanUtils.useRangeScan(logicalView, context); holdCollation = true; pipelineFragment.holdSingleTonParallelism(); } @@ -1650,7 +1687,23 @@ private ExecutorFactory visitView( if (logicalView.fromTableOperation() != null) { splitInfo = splitManager.getSingleSplit(logicalView, context); } else { + if (isUnderMergeSort && logicalView.pushedRelNodeIsSort()) { + rangeScanMode = RangeScanUtils.useRangeScan(logicalView, context, isSimpleMergeSort); + } + + int mergeUnionSize = context.getParamManager().getInt(ConnectionParams.MERGE_UNION_SIZE); + + // range scan can not union physical sql + if (rangeScanMode != null) { + context.putIntoHintCmds(ConnectionProperties.MERGE_UNION_SIZE, 1); + } + splitInfo = splitManager.getSplits(logicalView, context, false); + + if (rangeScanMode != null) { + // reset merge union size + context.putIntoHintCmds(ConnectionProperties.MERGE_UNION_SIZE, mergeUnionSize); + } } if (logicalView.pushedRelNodeIsSort()) { @@ -1699,7 +1752,8 @@ private ExecutorFactory visitView( } LogicalViewExecutorFactory logicalViewExecutorFactory = - createViewFactory(parent, logicalView, pipelineFragment, spillerFactory, prefetch, isUnderMergeSort); + createViewFactory(parent, logicalView, pipelineFragment, spillerFactory, prefetch, isUnderMergeSort, + rangeScanMode); boolean isProbeSideOfJoin = parent != null && parent instanceof HashJoin && ((HashJoin) parent).getOuter() == logicalView; @@ -1809,14 +1863,14 @@ private int getParallelismForColumnarScan(boolean isUnderMergeSort, int defaultP private LogicalViewExecutorFactory createViewFactory( RelNode parent, LogicalView logicalView, PipelineFragment pipelineFragment, SpillerFactory spillerFactory, - int prefetch, boolean isUnderMergeSort) { + int prefetch, boolean isUnderMergeSort, RangeScanMode rangeScanMode) { long fetched = Long.MAX_VALUE; long offset = 0; - boolean bSort = false; + boolean bSort = logicalView.pushedRelNodeIsSort(); Map params = context.getParams().getCurrentParameter(); Sort sort = null; - if (logicalView.pushedRelNodeIsSort()) { + if (bSort) { sort = (Sort) logicalView.getOptimizedPushedRelNodeForMetaQuery(); if (isUnderMergeSort) { sort = (Sort) parent; @@ -1829,10 +1883,6 @@ private LogicalViewExecutorFactory createViewFactory( } } - if (sort != null) { - bSort = true; - } - long maxRowCount = ExecUtils.getMaxRowCount(sort, context); int policy = -1; @@ -1851,10 +1901,25 @@ private LogicalViewExecutorFactory createViewFactory( break; } } + + // if number rows to fetch is too large, should not use serialize mode + if (rangeScanMode != null && !rangeScanMode.isNormalMode() && fetched > context.getParamManager() + .getInt(ConnectionParams.RANGE_SCAN_SERIALIZE_LIMIT)) { + rangeScanMode = RangeScanMode.NORMAL; + } + + if (rangeScanMode == RangeScanMode.SERIALIZE) { + prefetch = 1; + } + + if (rangeScanMode != null) { + randomSplits = false; + } + return new LogicalViewExecutorFactory(pipelineFragment, logicalView, prefetch, pipelineFragment.getParallelism(), maxRowCount, bSort, sort, fetched, offset, spillerFactory, bloomFilterExpressionMap, enableRuntimeFilter, - randomSplits); + randomSplits, rangeScanMode); } private ExecutorFactory visitProject(Project project, PipelineFragment pipelineFragment) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/RangeScanMode.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/RangeScanMode.java new file mode 100644 index 000000000..8b0d660ef --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/RangeScanMode.java @@ -0,0 +1,45 @@ +package com.alibaba.polardbx.executor.mpp.operator; + +import com.alibaba.polardbx.druid.util.StringUtils; + +/** + * @author yuehan.wcf + */ + +public enum RangeScanMode { + SERIALIZE, + + NORMAL, + + ADAPTIVE; + + /** + * Retrieves the corresponding RangeScanMode enumeration value based on the input string parameter 'mode'. + * + * @param mode A string parameter representing the scan mode, with possible values being "serialize", "normal", or "adaptive", case-insensitive. + * @return The corresponding RangeScanMode enumeration value. Returns null if the input mode is empty, null, or does not match any enumeration value. + */ + public static RangeScanMode getMode(String mode) { + // Check if the input mode is empty + if (StringUtils.isEmpty(mode)) { + return null; + } + + // Convert mode to lowercase and trim leading/trailing whitespace for uniform comparison + mode = mode.toLowerCase().trim(); + switch (mode) { + case "serialize": + return SERIALIZE; + case "normal": + return NORMAL; + case "adaptive": + return ADAPTIVE; + default: + return null; + } + } + + public boolean isNormalMode() { + return this == NORMAL; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/factory/LogicalViewExecutorFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/factory/LogicalViewExecutorFactory.java index 001bf3f64..5327b2087 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/factory/LogicalViewExecutorFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/factory/LogicalViewExecutorFactory.java @@ -32,21 +32,26 @@ import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.chunk.MutableChunk; import com.alibaba.polardbx.executor.mpp.operator.LocalExecutionPlanner; +import com.alibaba.polardbx.executor.mpp.operator.RangeScanMode; import com.alibaba.polardbx.executor.mpp.planner.FragmentRFItem; import com.alibaba.polardbx.executor.mpp.planner.FragmentRFItemKey; import com.alibaba.polardbx.executor.mpp.planner.FragmentRFManager; import com.alibaba.polardbx.executor.mpp.planner.PipelineFragment; import com.alibaba.polardbx.executor.operator.AbstractOSSTableScanExec; -import com.alibaba.polardbx.executor.operator.ColumnarDeletedScanExec; +import com.alibaba.polardbx.executor.operator.AdaptiveRangeScanClient; import com.alibaba.polardbx.executor.operator.ColumnarScanExec; +import com.alibaba.polardbx.executor.operator.ColumnarSpecifiedScanExec; import com.alibaba.polardbx.executor.operator.DrivingStreamTableScanExec; import com.alibaba.polardbx.executor.operator.DrivingStreamTableScanSortExec; import com.alibaba.polardbx.executor.operator.Executor; import com.alibaba.polardbx.executor.operator.LookupTableScanExec; import com.alibaba.polardbx.executor.operator.MergeSortTableScanClient; import com.alibaba.polardbx.executor.operator.MergeSortWithBufferTableScanClient; +import com.alibaba.polardbx.executor.operator.NormalRangeScanClient; +import com.alibaba.polardbx.executor.operator.RangeScanSortExec; import com.alibaba.polardbx.executor.operator.ResumeTableScanExec; import com.alibaba.polardbx.executor.operator.ResumeTableScanSortExec; +import com.alibaba.polardbx.executor.operator.SerializeRangeScanClient; import com.alibaba.polardbx.executor.operator.TableScanClient; import com.alibaba.polardbx.executor.operator.TableScanExec; import com.alibaba.polardbx.executor.operator.TableScanSortExec; @@ -114,11 +119,13 @@ public class LogicalViewExecutorFactory extends ExecutorFactory { private List dataTypeList; private boolean randomSplits; + private RangeScanMode rangeScanMode; + public LogicalViewExecutorFactory( PipelineFragment fragment, LogicalView logicalView, int totalPrefetch, int parallelism, long maxRowCount, boolean bSort, Sort sort, long fetch, long skip, SpillerFactory spillerFactory, Map bloomFilters, - boolean enableRuntimeFilter, boolean randomSplits) { + boolean enableRuntimeFilter, boolean randomSplits, RangeScanMode rangeScanMode) { this.fragment = fragment; this.logicalView = logicalView; this.totalPrefetch = totalPrefetch; @@ -131,6 +138,7 @@ public LogicalViewExecutorFactory( this.skip = skip; this.spillerFactory = spillerFactory; this.randomSplits = randomSplits; + this.rangeScanMode = rangeScanMode; if (logicalView.getJoin() != null) { Join join = logicalView.getJoin(); @@ -180,13 +188,31 @@ private Executor buildTableScanExec(ExecutionContext context) { boolean useTransactionConnection = ExecUtils.useExplicitTransaction(context); if (bSort) { - long limit = context.getParamManager().getLong(ConnectionParams.MERGE_SORT_BUFFER_SIZE); - if (limit > 0 && logicalView.pushedRelNodeIsSort()) { - this.scanClient = new MergeSortWithBufferTableScanClient( - context, meta, useTransactionConnection, totalPrefetch); + if (rangeScanMode != null) { + if (rangeScanMode == RangeScanMode.SERIALIZE) { + if (totalPrefetch != 1) { + MPP_LOGGER.warn(String.format( + "prefetch under serialize mode should be 1, but was %s, and trace id is %s", + totalPrefetch, context.getTraceId())); + } + this.scanClient = new SerializeRangeScanClient(context, meta, useTransactionConnection); + } else if (rangeScanMode == RangeScanMode.NORMAL) { + this.scanClient = + new NormalRangeScanClient(context, meta, useTransactionConnection, totalPrefetch, + RangeScanMode.NORMAL); + } else { + this.scanClient = + new AdaptiveRangeScanClient(context, meta, useTransactionConnection, totalPrefetch); + } } else { - this.scanClient = new MergeSortTableScanClient( - context, meta, useTransactionConnection, totalPrefetch); + long limit = context.getParamManager().getLong(ConnectionParams.MERGE_SORT_BUFFER_SIZE); + if (limit > 0 && logicalView.pushedRelNodeIsSort()) { + this.scanClient = new MergeSortWithBufferTableScanClient( + context, meta, useTransactionConnection, totalPrefetch); + } else { + this.scanClient = new MergeSortTableScanClient( + context, meta, useTransactionConnection, totalPrefetch); + } } } else if (useTransactionConnection || enablePassiveResume || enableDrivingResume) { int prefetch = calculatePrefetchNum(counter.incrementAndGet(), parallelism); @@ -228,10 +254,14 @@ protected void registerRuntimeStat(Executor scanExec, RelNode relNode, Execution private Executor buildOSSTableScanExec(ExecutionContext context) { OSSTableScan ossTableScan = (OSSTableScan) logicalView; - if (context.isEnableOrcDeletedScan()) { + if (context.isEnableOrcDeletedScan() + || context.isCciIncrementalCheck() + || context.isReadCsvOnly() + || context.isReadOrcOnly() + || context.isReadSpecifiedColumnarFiles()) { // Special path for check cci consistency. // Normal oss read should not get here. - Executor exec = new ColumnarDeletedScanExec(ossTableScan, context, dataTypeList); + Executor exec = new ColumnarSpecifiedScanExec(ossTableScan, context, dataTypeList); registerRuntimeStat(exec, logicalView, context); return exec; } @@ -351,9 +381,15 @@ private TableScanExec buildTableScanExec(TableScanClient scanClient, ExecutionCo } } else { if (bSort) { - return new TableScanSortExec( - logicalView, context, scanClient.incrementSourceExec(), maxRowCount, skip, fetch, - spillerFactory, dataTypeList); + if (rangeScanMode != null) { + return new RangeScanSortExec( + logicalView, context, scanClient.incrementSourceExec(), maxRowCount, skip, fetch, + spillerFactory, dataTypeList); + } else { + return new TableScanSortExec( + logicalView, context, scanClient.incrementSourceExec(), maxRowCount, skip, fetch, + spillerFactory, dataTypeList); + } } else { return new TableScanExec(logicalView, context, scanClient.incrementSourceExec(), maxRowCount, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/factory/OutputExecutorFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/factory/OutputExecutorFactory.java index 133df635a..a55e4e67c 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/factory/OutputExecutorFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/operator/factory/OutputExecutorFactory.java @@ -47,7 +47,7 @@ public OutputExecutorFactory(PlanFragment fragment, OutputBuffer outputBuffer, P public ConsumerExecutor createExecutor(ExecutionContext context, int index) { PartitioningScheme partitioningScheme = fragment.getPartitioningScheme(); List inputType = fragment.getTypes(); - List outputType = SerializeDataType.convertToDataType(fragment.getOutputTypes()); + List outputType = SerializeDataType.convertToDataType(fragment.getOutputTypes(), context); if (partitioningScheme.getShuffleHandle().isSinglePartition() || partitioningScheme.getPartitionMode() .equals(PartitionShuffleHandle.PartitionShuffleMode.BROADCAST) diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/PlanFragmenter.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/PlanFragmenter.java index dbb838795..49144236d 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/PlanFragmenter.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/PlanFragmenter.java @@ -22,10 +22,10 @@ import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; -import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.executor.mpp.Session; import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; import com.alibaba.polardbx.executor.mpp.operator.LocalExecutionPlanner; +import com.alibaba.polardbx.executor.mpp.operator.RangeScanMode; import com.alibaba.polardbx.executor.mpp.split.OssSplit; import com.alibaba.polardbx.executor.mpp.split.SplitInfo; import com.alibaba.polardbx.executor.mpp.split.SplitManager; @@ -33,6 +33,9 @@ import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.executor.utils.OrderByOption; import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.gms.node.MppScope; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; import com.alibaba.polardbx.optimizer.core.rel.BKAJoin; import com.alibaba.polardbx.optimizer.core.rel.BaseTableOperation; import com.alibaba.polardbx.optimizer.core.rel.Limit; @@ -82,7 +85,6 @@ import static com.alibaba.polardbx.executor.mpp.operator.LocalExecutionPlanner.SUPPORT_ONE_SIDE_CACHE_NODES; import static com.alibaba.polardbx.executor.mpp.planner.PartitionHandle.SINGLETON_SOURCE; import static com.alibaba.polardbx.executor.utils.ExecUtils.convertBuildSide; -import static com.alibaba.polardbx.executor.utils.ExecUtils.existMppOnlyInstanceNode; public class PlanFragmenter { @@ -115,10 +117,10 @@ private static class Fragmenter { private int maxConcurrentParallelism = -1; private int currentConcurrentParallelism = 0; - private boolean onlyUseReadInstance; private boolean lowConcurrencyQuery = false; private SplitManager splitManager; + private boolean isColumnar = false; public Fragmenter(Session session, RelNode root) { this.session = session; @@ -127,9 +129,9 @@ public Fragmenter(Session session, RelNode root) { } else { session.getClientContext().getExtraCmds().put(ConnectionProperties.MERGE_UNION, false); } - - this.onlyUseReadInstance = existMppOnlyInstanceNode(); this.splitManager = new SplitManagerImpl(); + this.isColumnar = CBOUtil.isColumnarOptimizer(root); + } public int getMaxConcurrentParallelism() { @@ -350,7 +352,7 @@ private RelNode visitExchange(RelNode parent, Exchange exchange, FragmentPropert shuffleHandle = new PartitionShuffleHandle( PartitionShuffleHandle.PartitionShuffleMode.FIXED, mergeSort); - shuffleHandle.setFullPartCount(exchange.getTraitSet().getDistribution().getShardCnt()); + shuffleHandle.setFullPartCount(exchange.getDistribution().getShardCnt()); } List orderBys = new ArrayList<>(); if (mergeSort) { @@ -457,8 +459,24 @@ private SubPlan generateSubPlan( if (logicalView.fromTableOperation() != null) { splitInfo = splitManager.getSingleSplit(logicalView, session.getClientContext()); } else { - splitInfo = splitManager.getSplits( - logicalView, session.getClientContext(), !lowConcurrencyQuery); + RangeScanMode rangeScanMode = null; + ExecutionContext context = session.getClientContext(); + if (logicalView.pushedRelNodeIsSort()) { + rangeScanMode = RangeScanUtils.useRangeScan(logicalView, context); + } + + int mergeUnionSize = context.getParamManager().getInt(ConnectionParams.MERGE_UNION_SIZE); + + if (rangeScanMode != null) { + context.putIntoHintCmds(ConnectionProperties.MERGE_UNION_SIZE, 1); + } + + splitInfo = splitManager.getSplits(logicalView, context, !lowConcurrencyQuery); + + if (rangeScanMode != null) { + // reset merge union size + context.putIntoHintCmds(ConnectionProperties.MERGE_UNION_SIZE, mergeUnionSize); + } } splitCountMap.put(logicalView.getLogicalTableName(), splitInfo.getSplitCount()); session.getGroups().putAll(splitInfo.getGroups()); @@ -491,7 +509,7 @@ private SubPlan generateSubPlan( bkaJoinParallelism = Math.max(outerParallelism * lookupJoinParallelismFactor, bkaJoinParallelism); bkaJoinParallelism = Math.max(Math.min(bkaJoinParallelism, ExecUtils - .getMppMaxParallelism(session.getClientContext().getParamManager(), !onlyUseReadInstance)), + .getMppMaxParallelism(session.getClientContext().getParamManager(), isColumnar)), ExecUtils.getMppMinParallelism(session.getClientContext().getParamManager())); } } @@ -574,7 +592,7 @@ public int calcParallelism(FragmentProperties properties) { parallelism = (int) (properties.rootRowCnt / paramManager .getInt(ConnectionParams.MPP_QUERY_ROWS_PER_PARTITION)); parallelism = - Math.max(Math.min(parallelism, ExecUtils.getMppMaxParallelism(paramManager, !onlyUseReadInstance)), + Math.max(Math.min(parallelism, ExecUtils.getMppMaxParallelism(paramManager, isColumnar)), ExecUtils.getMppMinParallelism(paramManager)); } else { parallelism = paramManager.getInt(ConnectionParams.MPP_PARALLELISM); @@ -589,7 +607,7 @@ public int calcParallelism(FragmentProperties properties) { parallelism, subPlan.getFragment().getBkaJoinParallelism()); } parallelism = Math.max( - Math.min(parallelism, ExecUtils.getMppMaxParallelism(paramManager, !onlyUseReadInstance)), + Math.min(parallelism, ExecUtils.getMppMaxParallelism(paramManager, isColumnar)), ExecUtils.getMppMinParallelism(paramManager)); } } @@ -606,7 +624,7 @@ public int calcScanParallelism(double io, SplitInfo splitInfo) { int parallelsim = -1; if (paramManager.getBoolean(ConnectionParams.MPP_PARALLELISM_AUTO_ENABLE)) { - int maxParallelism = ExecUtils.getMppMaxParallelism(paramManager, !onlyUseReadInstance); + int maxParallelism = ExecUtils.getMppMaxParallelism(paramManager, isColumnar); int minParallelism = ExecUtils.getMppMinParallelism(paramManager); parallelsim = (int) (io / paramManager .getInt(ConnectionParams.MPP_QUERY_IO_PER_PARTITION)) + 1; @@ -620,12 +638,12 @@ public int calcScanParallelism(double io, SplitInfo splitInfo) { parallelsim = (int) (io / paramManager .getInt(ConnectionParams.MPP_QUERY_IO_PER_PARTITION)) + 1; parallelsim = Math.max( - Math.min(parallelsim, ExecUtils.getMppMaxParallelism(paramManager, !onlyUseReadInstance)), + Math.min(parallelsim, ExecUtils.getMppMaxParallelism(paramManager, isColumnar)), ExecUtils.getMppMinParallelism(paramManager)); } } - int dbParallelism = ExecUtils.getPolarDbCores(paramManager, !onlyUseReadInstance); + int dbParallelism = ExecUtils.getPolarDbCores(paramManager); parallelsim = Math.max(Math.min(Math.min( splitInfo.getSplitCount(), dbParallelism * splitInfo.getInsCount()), parallelsim), 1); @@ -647,14 +665,14 @@ private int calcColumnarScanParallelism(boolean simpleOssScan, SplitInfo splitIn int parallelism = paramManager.getInt(ConnectionParams.MPP_PARALLELISM); if (parallelism < 0) { + MppScope mppScope = ExecUtils.getMppSchedulerScope(!isColumnar); int mppNodeSize = paramManager.getInt(ConnectionParams.MPP_NODE_SIZE); if (mppNodeSize <= 0) { - mppNodeSize = (ServiceProvider.getInstance().getServer()).getNodeManager() - .getAllWorkers(ConfigDataMode.isMasterMode() && paramManager - .getBoolean(ConnectionParams.POLARDBX_SLAVE_INSTANCE_FIRST)).size(); + mppNodeSize = ServiceProvider.getInstance().getServer() + .getNodeManager().getAllNodes().getAllWorkers(mppScope).size(); } // default parallelism is cores of all compute node - parallelism = mppNodeSize * ExecUtils.getPolarDBXCores(paramManager, !onlyUseReadInstance); + parallelism = mppNodeSize * ExecUtils.getPolarDBXCNCores(paramManager, mppScope); } if (simpleOssScan && splitInfo.getSplitCount() > 0) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/PlanUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/PlanUtils.java index c666228a3..93495a8f8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/PlanUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/PlanUtils.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.common.utils.ExecutorMode; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.mpp.Session; +import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; import com.alibaba.polardbx.executor.mpp.execution.buffer.OutputBufferMemoryManager; import com.alibaba.polardbx.executor.mpp.operator.LocalExecutionPlanner; import com.alibaba.polardbx.executor.mpp.operator.factory.LocalBufferExecutorFactory; @@ -30,6 +31,7 @@ import com.alibaba.polardbx.executor.mpp.util.MoreExecutors; import com.alibaba.polardbx.executor.operator.spill.MemorySpillerFactory; import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.gms.node.MppScope; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.memory.MemoryManager; @@ -116,9 +118,13 @@ public static String textPlan(ExecutionContext executionContext, Session session builder.append(formatFragment( executionContext, fragment, session.getClientContext().getParams().getCurrentParameter())); if (executionContext.getParamManager().getBoolean(ConnectionParams.SHOW_PIPELINE_INFO_UNDER_MPP)) { + boolean columnarMode = session.getClientContext().getParamManager() + .getBoolean(ConnectionParams.ENABLE_COLUMNAR_SCHEDULE); int mppNodeSize = executionContext.getParamManager().getInt(ConnectionParams.MPP_NODE_SIZE); if (mppNodeSize <= 0) { - mppNodeSize = ExecUtils.getActiveNodeCount(); + MppScope mppScope = ExecUtils.getMppSchedulerScope(!columnarMode); + mppNodeSize = ServiceProvider.getInstance().getServer() + .getNodeManager().getAllNodes().getAllWorkers(mppScope).size(); } int parallelism = fragment.getPartitioning().getPartitionCount() / mppNodeSize; outputLocalFragment(executionContext, Math.max(1, parallelism), fragment.getRootNode(), builder); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/RangeScanUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/RangeScanUtils.java new file mode 100644 index 000000000..88ffe2334 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/RangeScanUtils.java @@ -0,0 +1,86 @@ +package com.alibaba.polardbx.executor.mpp.planner; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.druid.sql.ast.SqlType; +import com.alibaba.polardbx.executor.mpp.operator.RangeScanMode; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; +import com.alibaba.polardbx.optimizer.core.rel.util.TargetTableInfo; +import com.alibaba.polardbx.optimizer.core.rel.util.TargetTableInfoOneTable; +import com.alibaba.polardbx.optimizer.utils.PartitionUtils; +import org.apache.calcite.rel.core.Sort; + +public class RangeScanUtils { + public static RangeScanMode useRangeScan(LogicalView logicalView, ExecutionContext context) { + return useRangeScan(logicalView, context, false); + } + + /** + * Determines whether to use the range scan mode based on the given logical view, execution context, and flag indicating whether the root node is a merge sort. + * + * @param logicalView The logical view representing the logical structure of tables involved in the query. + * @param context The execution context containing various context information required during query execution. + * @param rootIsMergeSort A flag indicating whether the root node is a merge sort. + * @return The appropriate range scan mode if conditions are met; otherwise, returns null. + */ + public static RangeScanMode useRangeScan(LogicalView logicalView, ExecutionContext context, + boolean rootIsMergeSort) { + if (!context.getParamManager().getBoolean(ConnectionParams.ENABLE_RANGE_SCAN)) { + return null; + } + boolean isDml = SqlType.isDML(context.getSqlType()); + if (isDml && !context.getParamManager().getBoolean(ConnectionParams.ENABLE_RANGE_SCAN_FOR_DML)) { + return null; + } + // Check if the logical view contains multiple tables + if (logicalView.getTableNames().size() != 1) { + return null; + } + // single group no need range scan + if (logicalView.isSingleGroup()) { + return null; + } + // Check if it is a new partitioned table + if (!PartitionUtils.isNewPartShardTable(logicalView)) { + return null; + } + + TargetTableInfo targetTableInfo = logicalView.buildTargetTableInfosForPartitionTb(context); + // contains multi table + if (targetTableInfo.getTargetTableInfoList().size() > 1) { + return null; + } + + TargetTableInfoOneTable tableInfo = targetTableInfo.getTargetTableInfoList().get(0); + if (!PartitionUtils.isTablePartOrdered(tableInfo)) { + return null; + } + if (!PartitionUtils.isOrderKeyMatched(logicalView, tableInfo)) { + return null; + } + return determinRangeScanMode(logicalView, context, rootIsMergeSort); + } + + /** + * Determines the range scan mode based on the given logical view, execution context, and whether the root node is a merge sort. + * + * @param logicalView The logical view representing the query's logical structure. + * @param context The execution context containing parameters and state required for executing the query. + * @param rootIsMergeSort A flag indicating whether the current node is the root merge sort node. + * @return The determined range scan mode. + */ + static RangeScanMode determinRangeScanMode(LogicalView logicalView, ExecutionContext context, + boolean rootIsMergeSort) { + RangeScanMode rangeScanMode = + RangeScanMode.getMode(context.getParamManager().getString(ConnectionParams.RANGE_SCAN_MODE)); + if (rangeScanMode != null) { + return rangeScanMode; + } + if (rootIsMergeSort) { + return RangeScanMode.ADAPTIVE; + } + return RangeScanMode.NORMAL; + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/SerializeDataType.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/SerializeDataType.java index 71e280920..289495057 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/SerializeDataType.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/planner/SerializeDataType.java @@ -19,11 +19,15 @@ import com.alibaba.polardbx.common.charset.CharsetName; import com.alibaba.polardbx.common.charset.CollationName; import com.alibaba.polardbx.common.utils.time.MySQLTimeTypeUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.CharType; import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.datatype.DateTimeType; +import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; +import com.alibaba.polardbx.optimizer.core.datatype.DoubleType; import com.alibaba.polardbx.optimizer.core.datatype.EnumType; +import com.alibaba.polardbx.optimizer.core.datatype.FloatType; import com.alibaba.polardbx.optimizer.core.datatype.TimeType; import com.alibaba.polardbx.optimizer.core.datatype.TimestampType; import com.alibaba.polardbx.optimizer.core.datatype.VarcharType; @@ -158,7 +162,8 @@ public static List convertToSerilizeType(List convertToDataType(List relDataTypeList) { + public static List convertToDataType(List relDataTypeList, + ExecutionContext context) { List dataTypes = new ArrayList<>(); for (int i = 0; i < relDataTypeList.size(); i++) { SerializeDataType serializeDataType = relDataTypeList.get(i); @@ -173,7 +178,8 @@ public static List convertToDataType(List relDataTy serializeDataType.sensitive, enumValues, charsetName, - collationName); + collationName, + context); dataTypes.add(dt); } return dataTypes; @@ -183,8 +189,9 @@ public static List convertToDataType(List relDataTy @Deprecated private static DataType relTypeToTddlType(SqlTypeName typeName, int precision, int scale, boolean hasBooleanType, boolean sensitive, List enumValues, String charset, - String collation) { + String collation, ExecutionContext context) { // TODO FIX ME + boolean accurateType = context.isEnableAccurateRelTypeToDataType(); DataType dataType = null; CharsetName charsetName = Optional.ofNullable(charset) .map(CharsetName::of) @@ -194,7 +201,7 @@ private static DataType relTypeToTddlType(SqlTypeName typeName, int precision, i .orElseGet(CollationName::defaultCollation); switch (typeName) { case DECIMAL: - dataType = DataTypes.DecimalType; + dataType = accurateType ? new DecimalType(precision, scale) : DataTypes.DecimalType; break; case BOOLEAN: if (hasBooleanType) { @@ -219,14 +226,14 @@ private static DataType relTypeToTddlType(SqlTypeName typeName, int precision, i dataType = DataTypes.LongType; break; case FLOAT: - dataType = DataTypes.FloatType; + dataType = accurateType ? new FloatType(scale) : DataTypes.FloatType; break; case DATETIME: dataType = new DateTimeType(MySQLTimeTypeUtil.normalizeScale(scale)); break; case REAL: case DOUBLE: - dataType = DataTypes.DoubleType; + dataType = accurateType ? new DoubleType(scale) : DataTypes.DoubleType; break; case DATE: dataType = DataTypes.DateType; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/server/StatementResource.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/server/StatementResource.java index 555bedb1b..6c400f799 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/server/StatementResource.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/server/StatementResource.java @@ -31,6 +31,7 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.exception.code.ErrorType; +import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; @@ -146,8 +147,12 @@ public LocalResultResponse createQuery(ExecutionContext clientContext, RelNode p UriInfo uriInfo = MockUriInfo.from(uriBuilderFrom(serverUri).replacePath("/v1/statement").build().toString()); + + long mppQueryResultMaxWaitInMillis = DynamicConfig.getInstance().getMppQueryResultMaxWaitInMillis(); + StatementResource - .getQueryResultsLocal(localResultResponse, Optional.empty(), query, uriInfo, new Duration(1, SECONDS)); + .getQueryResultsLocal(localResultResponse, Optional.empty(), query, uriInfo, + new Duration(mppQueryResultMaxWaitInMillis, MILLISECONDS)); } catch (Exception t) { localResultResponse.setException(t); } @@ -190,12 +195,14 @@ public LocalResultResponse getResultLocal(LocalResultRequest request) { String queryId = request.getQueryId(); StatementResource.Query query = queries.get(queryId); if (query != null) { + long mppQueryResultMaxWaitInMillis = DynamicConfig.getInstance().getMppQueryResultMaxWaitInMillis(); + StatementResource.getQueryResultsLocal( queryResult, Optional.of(request.getToken()), query, uriInfo, - new Duration(1, SECONDS) + new Duration(mppQueryResultMaxWaitInMillis, MILLISECONDS) ); } else { throw new Exception("queryId:" + queryId + " not found"); @@ -462,6 +469,7 @@ private synchronized Iterable getData(Duration maxWait) ImmutableList.Builder pages = ImmutableList.builder(); // wait up to max wait for data to arrive; then try to return at least DESIRED_RESULT_BYTES long bytes = 0; + long positionCount = 0; while (bytes < DESIRED_RESULT_BYTES) { SerializedChunk serializedPage; @@ -473,12 +481,13 @@ private synchronized Iterable getData(Duration maxWait) Chunk chunk = serde.deserialize(serializedPage); bytes += chunk.getElementUsedBytes(); + positionCount += chunk.getPositionCount(); pages.add(chunk); // only wait on first call maxWait = afterFristWait; } - if (bytes == 0) { + if (positionCount == 0) { return null; } return (Iterable) pages.build(); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/server/remotetask/HttpLocationFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/server/remotetask/HttpLocationFactory.java index 6ef37b723..b1cb46bb6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/server/remotetask/HttpLocationFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/server/remotetask/HttpLocationFactory.java @@ -67,7 +67,7 @@ public URI createRuntimeFilterLocation(String queryId) { } @Override - public URI createDdlFilterLocktion(String jobId) { + public URI createDdlFilterLocation(String jobId) { requireNonNull(jobId, "jobId is null"); return URI.create(baseUriPath + "/v1/ddl/" + jobId); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/split/OssSplit.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/split/OssSplit.java index 5a17a07e8..5d24f0fbb 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/split/OssSplit.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/split/OssSplit.java @@ -19,6 +19,7 @@ import com.alibaba.polardbx.common.Engine; import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.jdbc.Parameters; +import com.alibaba.polardbx.common.oss.IDeltaReadOption; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; @@ -36,11 +37,10 @@ import com.alibaba.polardbx.executor.archive.reader.TypeComparison; import com.alibaba.polardbx.executor.archive.schemaevolution.ColumnMetaWithTs; import com.alibaba.polardbx.executor.archive.schemaevolution.OrcColumnManager; -import com.alibaba.polardbx.executor.ddl.job.task.basic.oss.OSSTaskUtils; import com.alibaba.polardbx.executor.gms.ColumnarManager; import com.alibaba.polardbx.executor.gms.ColumnarStoreUtils; +import com.alibaba.polardbx.gms.metadb.columnar.FlashbackColumnarManager; import com.alibaba.polardbx.executor.mpp.spi.ConnectorSplit; -import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.config.table.FileMeta; import com.alibaba.polardbx.optimizer.config.table.OSSOrcFileMeta; @@ -53,7 +53,6 @@ import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation; import com.alibaba.polardbx.optimizer.core.rel.PhyTableScanBuilder; -import com.alibaba.polardbx.optimizer.partition.PartSpecBase; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -66,7 +65,6 @@ import org.apache.calcite.rel.logical.LogicalAggregate; import org.apache.calcite.rel.metadata.RelColumnOrigin; import org.apache.calcite.rex.RexBuilder; -import org.apache.calcite.rex.RexDynamicParam; import org.apache.calcite.rex.RexNode; import org.apache.calcite.sql.SqlKind; import org.apache.commons.collections.CollectionUtils; @@ -81,16 +79,16 @@ import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.TimeZone; import java.util.regex.Pattern; import java.util.stream.Collectors; +import static com.alibaba.polardbx.optimizer.utils.PartitionUtils.calcPartition; import static com.alibaba.polardbx.optimizer.utils.ITimestampOracle.BITS_LOGICAL_TIME; import static com.google.common.base.MoreObjects.toStringHelper; @@ -100,7 +98,7 @@ public class OssSplit implements ConnectorSplit { private List readOptions; - private String logicalSchema; + protected String logicalSchema; private String physicalSchema; // all physical tables in a logical table share the parameters @@ -115,12 +113,12 @@ public class OssSplit implements ConnectorSplit { private boolean enableAggPruner; - private String logicalTableName; + protected String logicalTableName; private List phyTableNameList; // all fileMetas share the same version of schema private List> allFileMetas; - private List designatedFile; + protected List designatedFile; private byte[] paramsBytes; private boolean isInit = false; @@ -246,11 +244,37 @@ public static List getTableConcurrencySplit(OSSTableScan ossTableScan, final PartitionInfo partitionInfo = tableMeta.getPartitionInfo(); Map> allCsvFiles = new HashMap<>(); + Map> allCsvPositions = null; + Map>> allDeletePositions = null; List allOrcFiles = new ArrayList<>(); - if (executionContext.isReadOrcOnly()) { - // Special hint, only read specified orc files. - // Normal columnar read should not get here. - allOrcFiles.addAll(executionContext.getReadOrcFiles()); + if (ossTableScan.isFlashbackQuery()) { + allCsvPositions = new HashMap<>(); + FlashbackColumnarManager flashbackManager = + executionContext.getFlashbackColumnarManager(tso, logicalSchema, logicalTable); + Map, List>>> columnarSnapshot = + flashbackManager.getSnapshotInfo(); + allDeletePositions = flashbackManager.getDeletePositions(); + + for (String physicalTable : phyTableList) { + // Find part name from physical schema + physical table + final String partName = partitionInfo.getPartitionNameByPhyLocation(physicalSchema, physicalTable); + Pair, List>> snapshot = columnarSnapshot.get(partName); + if (snapshot == null) { + continue; + } + + List orcFiles = snapshot.getKey(); + List> csvInfos = snapshot.getValue(); + allOrcFiles.addAll(orcFiles); + if (GeneralUtil.isNotEmpty(csvInfos)) { + allCsvFiles.put(physicalTable, csvInfos.stream().map( + Pair::getKey + ).collect(Collectors.toList())); + allCsvPositions.put(physicalTable, csvInfos.stream().map( + Pair::getValue + ).collect(Collectors.toList())); + } + } } else { for (String physicalTable : phyTableList) { // Find part name from physical schema + physical table @@ -274,12 +298,6 @@ public static List getTableConcurrencySplit(OSSTableScan ossTableScan, } } - if (executionContext.isReadCsvOnly()) { - // Special hint, only read csv files, so we clear orc files here. - // Normal columnar read should not get here. - allOrcFiles.clear(); - } - if (allOrcFiles.isEmpty() && allCsvFiles.isEmpty()) { return ImmutableList.of(); } @@ -292,6 +310,8 @@ public static List getTableConcurrencySplit(OSSTableScan ossTableScan, columnarManager.getPhysicalColumnIndexes(tso, null, projectList); deltaReadOption.setAllCsvFiles(allCsvFiles); + deltaReadOption.setAllPositions(allCsvPositions); + deltaReadOption.setAllDelPositions(allDeletePositions); deltaReadOption.setProjectColumnIndexes(correctedProjectList); return ImmutableList.of(new OssSplit(logicalSchema, physicalSchema, params, logicalTable, phyTableList, allOrcFiles, deltaReadOption, @@ -330,75 +350,158 @@ public static List getTableConcurrencySplit(OSSTableScan ossTableScan, } } - public static List getFileConcurrencySplit(OSSTableScan ossTableScan, RelNode relNode, - ExecutionContext executionContext, Long tso) { - Preconditions.checkArgument(relNode instanceof PhyTableOperation); + private static List getFileConcurrencySplitForColumnar(ExecutionContext executionContext, + OSSTableScan ossTableScan, TableMeta tableMeta, + String logicalSchema, String physicalSchema, + String logicalTableName, + List phyTableNameList, + PhyTableScanBuilder phyOperationBuilder, + long tso) { List splits = new ArrayList<>(); + final PartitionInfo partitionInfo = tableMeta.getPartitionInfo(); + final ColumnarManager columnarManager = ColumnarManager.getInstance(); + + // for each physical table + Set targetOrcFiles = null; + for (int i = 0; i < phyTableNameList.size(); i++) { + String phyTable = phyTableNameList.get(i); + + // Find part name from physical schema + physical table + final String partName = partitionInfo.getPartitionNameByPhyLocation(physicalSchema, phyTable); + + // Find csv files from tso + part name + Pair, List> files = + columnarManager.findFileNames(tso, logicalSchema, logicalTableName, partName); + List orcFiles = files.getKey(); + List csvFiles = files.getValue(); + + // get partition number of this split, used for partition wise join + RelPartitionWise partitionWise = ossTableScan.getTraitSet().getPartitionWise(); + boolean needPartition = partitionWise.isRemotePartition() || executionContext.getParamManager() + .getBoolean(ConnectionParams.SCHEDULE_BY_PARTITION); + + int partition = needPartition ? calcPartition(logicalSchema, logicalTableName, + physicalSchema, phyTable) : NO_PARTITION_INFO; + boolean localPairWise = + executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_LOCAL_PARTITION_WISE_JOIN) + && partitionWise.isLocalPartition(); + + // build split for orc files. + if (!orcFiles.isEmpty()) { + // build single physical table list and params, + // and split for each file. + List singlePhyTableNameList = ImmutableList.of(phyTable); - PhyTableOperation phyTableOperation = (PhyTableOperation) relNode; - String logicalSchema = phyTableOperation.getSchemaName(); - String physicalSchema = phyTableOperation.getDbIndex(); + Map params = + phyOperationBuilder.buildSplitParamMap(singlePhyTableNameList); - String logicalTableName = phyTableOperation.getLogicalTableNames().get(0); - List phyTableNameList = phyTableOperation.getTableNames().get(0); + for (String orcFile : orcFiles) { + OssSplit ossSplit = new OssSplit( + logicalSchema, physicalSchema, params, + logicalTableName, singlePhyTableNameList, + ImmutableList.of(orcFile), null, + tso, partition, localPairWise); + splits.add(ossSplit); + } + } - PhyTableScanBuilder phyOperationBuilder = - (PhyTableScanBuilder) phyTableOperation.getPhyOperationBuilder(); + // build split for csv files. + if (!csvFiles.isEmpty()) { + for (String csvFile : csvFiles) { + // build single physical table list and params, + // and split for each file. + List singlePhyTableNameList = ImmutableList.of(phyTable); - TableMeta tableMeta = executionContext.getSchemaManager(logicalSchema).getTable(logicalTableName); + Map params = + phyOperationBuilder.buildSplitParamMap(singlePhyTableNameList); - if (ossTableScan.isColumnarIndex()) { - final PartitionInfo partitionInfo = tableMeta.getPartitionInfo(); - final ColumnarManager columnarManager = ColumnarManager.getInstance(); + // Build delta read option. There is only one physical table and one csv file name. + DeltaReadOption deltaReadOption = new DeltaReadOption(tso); - // for each physical table - Set targetOrcFiles = null; - for (int i = 0; i < phyTableNameList.size(); i++) { - String phyTable = phyTableNameList.get(i); + // correct project column indexes (skip implicit column) + ImmutableList projectList = ossTableScan.getOrcNode().getInProjects(); - // Find part name from physical schema + physical table - final String partName = partitionInfo.getPartitionNameByPhyLocation(physicalSchema, phyTable); + // TODO(siyun): column mapping may defer for different files + List correctedProjectList = + columnarManager.getPhysicalColumnIndexes(tso, null, projectList); - // Find csv files from tso + part name - Pair, List> files = - columnarManager.findFileNames(tso, logicalSchema, logicalTableName, partName); - List orcFiles = files.getKey(); - List csvFiles = files.getValue(); - - if (executionContext.isReadOrcOnly()) { - // Special hint, only read specified files. - // Normal columnar read should not get here. - csvFiles = new ArrayList<>(); - if (null == targetOrcFiles) { - targetOrcFiles = new HashSet<>(executionContext.getReadOrcFiles()); - } - List newOrcFiles = new ArrayList<>(); - for (String orcFile : orcFiles) { - if (targetOrcFiles.contains(orcFile)) { - newOrcFiles.add(orcFile); - } - } - orcFiles = newOrcFiles; - } + deltaReadOption.setAllCsvFiles(Collections.singletonMap(phyTable, ImmutableList.of(csvFile))); + deltaReadOption.setProjectColumnIndexes(correctedProjectList); - if (executionContext.isReadCsvOnly()) { - // Special hint, only read csv files, so we clear orc files here. - orcFiles.clear(); + OssSplit ossSplit = new OssSplit( + logicalSchema, physicalSchema, params, + logicalTableName, singlePhyTableNameList, + null, deltaReadOption, + tso, partition, localPairWise); + splits.add(ossSplit); } + } + } + return splits; + } + + private static List getFileConcurrencySplitForFlashback(ExecutionContext executionContext, + OSSTableScan ossTableScan, TableMeta tableMeta, + String logicalSchema, String physicalSchema, + String logicalTableName, + List phyTableNameList, + PhyTableScanBuilder phyOperationBuilder, + long tso) { + List splits = new ArrayList<>(); + final PartitionInfo partitionInfo = tableMeta.getPartitionInfo(); + FlashbackColumnarManager flashbackColumnarManager = + executionContext.getFlashbackColumnarManager(tso, logicalSchema, logicalTableName); + + Map, List>>> snapshotInfo = + flashbackColumnarManager.getSnapshotInfo(); + Map>> deletePositionMap = flashbackColumnarManager.getDeletePositions(); + + for (int i = 0; i < phyTableNameList.size(); i++) { + String phyTable = phyTableNameList.get(i); + + // Find part name from physical schema + physical table + final String partName = partitionInfo.getPartitionNameByPhyLocation(physicalSchema, phyTable); + Pair, List>> partInfo = snapshotInfo.get(partName); + + if (partInfo == null) { + continue; + } - // get partition number of this split, used for partition wise join - RelPartitionWise partitionWise = ossTableScan.getTraitSet().getPartitionWise(); - boolean needPartition = partitionWise.isRemotePartition() || executionContext.getParamManager() - .getBoolean(ConnectionParams.SCHEDULE_BY_PARTITION); + // get partition number of this split, used for partition wise join + RelPartitionWise partitionWise = ossTableScan.getTraitSet().getPartitionWise(); + boolean needPartition = partitionWise.isRemotePartition() || executionContext.getParamManager() + .getBoolean(ConnectionParams.SCHEDULE_BY_PARTITION); - int partition = needPartition ? - calcPartition(logicalSchema, logicalTableName, physicalSchema, phyTable) : NO_PARTITION_INFO; - boolean localPairWise = - executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_LOCAL_PARTITION_WISE_JOIN) - && partitionWise.isLocalPartition(); + int partition = needPartition ? + calcPartition(logicalSchema, logicalTableName, physicalSchema, phyTable) : NO_PARTITION_INFO; + boolean localPairWise = partitionWise.isLocalPartition() && executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_LOCAL_PARTITION_WISE_JOIN); - // build split for orc files. - if (!orcFiles.isEmpty()) { + List orcFiles = partInfo.getKey(); + if (!orcFiles.isEmpty()) { + List singlePhyTableNameList = ImmutableList.of(phyTable); + + Map params = + phyOperationBuilder.buildSplitParamMap(singlePhyTableNameList); + + DeltaReadOption deltaReadOption = new DeltaReadOption(tso); + deltaReadOption.setAllDelPositions(deletePositionMap); + + for (String orcFile : orcFiles) { + OssSplit ossSplit = new OssSplit( + logicalSchema, physicalSchema, params, + logicalTableName, singlePhyTableNameList, + ImmutableList.of(orcFile), deltaReadOption, + tso, partition, localPairWise); + splits.add(ossSplit); + } + } + + List> csvFileWithPositions = partInfo.getValue(); + if (!csvFileWithPositions.isEmpty()) { + for (Pair fileNameAndPos : csvFileWithPositions) { + String csvFile = fileNameAndPos.getKey(); + Long filePos = fileNameAndPos.getValue(); // build single physical table list and params, // and split for each file. List singlePhyTableNameList = ImmutableList.of(phyTable); @@ -406,91 +509,88 @@ public static List getFileConcurrencySplit(OSSTableScan ossTableScan, Map params = phyOperationBuilder.buildSplitParamMap(singlePhyTableNameList); - for (String orcFile : orcFiles) { - OssSplit ossSplit = new OssSplit( - logicalSchema, physicalSchema, params, - logicalTableName, singlePhyTableNameList, - ImmutableList.of(orcFile), null, - tso, partition, localPairWise); - splits.add(ossSplit); - } - } + // Build delta read option. There is only one physical table and one csv file name. + final DeltaReadOption deltaReadOption = new DeltaReadOption(tso); - // build split for csv files. - if (!csvFiles.isEmpty()) { - for (String csvFile : csvFiles) { - // build single physical table list and params, - // and split for each file. - List singlePhyTableNameList = ImmutableList.of(phyTable); - - Map params = - phyOperationBuilder.buildSplitParamMap(singlePhyTableNameList); - - // Build delta read option. There is only one physical table and one csv file name. - DeltaReadOption deltaReadOption = new DeltaReadOption(tso); - Map> allCsvFiles = new HashMap<>(); - allCsvFiles.put(phyTable, ImmutableList.of(csvFile)); - - // correct project column indexes (skip implicit column) - ImmutableList projectList = ossTableScan.getOrcNode().getInProjects(); - - // TODO(siyun): column mapping may defer for different files - List correctedProjectList = - columnarManager.getPhysicalColumnIndexes(tso, null, projectList); - - deltaReadOption.setAllCsvFiles(allCsvFiles); - deltaReadOption.setProjectColumnIndexes(correctedProjectList); - - OssSplit ossSplit = new OssSplit( - logicalSchema, physicalSchema, params, - logicalTableName, singlePhyTableNameList, - null, deltaReadOption, - tso, partition, localPairWise); - splits.add(ossSplit); - } + deltaReadOption.setAllCsvFiles(Collections.singletonMap(phyTable, ImmutableList.of(csvFile))); + deltaReadOption.setAllPositions(Collections.singletonMap(phyTable, ImmutableList.of(filePos))); + deltaReadOption.setAllDelPositions(deletePositionMap); + + OssSplit ossSplit = new OssSplit( + logicalSchema, physicalSchema, params, + logicalTableName, singlePhyTableNameList, + null, deltaReadOption, + tso, partition, localPairWise); + splits.add(ossSplit); } } - return splits; - } else { - Map> flatFileMetas = tableMeta.getFlatFileMetas(); - // for each physical table - for (int i = 0; i < phyTableNameList.size(); i++) { - String phyTable = phyTableNameList.get(i); - List fileMetas = flatFileMetas.get(phyTable); - if (fileMetas.isEmpty()) { - continue; - } + } + return splits; + } - // build single physical table list and params, - // and split for each file. - List singlePhyTableNameList = ImmutableList.of(phyTable); + private static List getFileConcurrencySplitForColdData(TableMeta tableMeta, + String logicalSchema, String physicalSchema, + String logicalTableName, + List phyTableNameList, + PhyTableScanBuilder phyOperationBuilder) { - Map params = - phyOperationBuilder.buildSplitParamMap(singlePhyTableNameList); + List splits = new ArrayList<>(); + Map> flatFileMetas = tableMeta.getFlatFileMetas(); - for (FileMeta fileMeta : fileMetas) { - OssSplit ossSplit = new OssSplit(logicalSchema, physicalSchema, params, - logicalTableName, singlePhyTableNameList, ImmutableList.of(fileMeta.getFileName()), null, - null, NO_PARTITION_INFO, false); - splits.add(ossSplit); - } + // for each physical table + for (int i = 0; i < phyTableNameList.size(); i++) { + String phyTable = phyTableNameList.get(i); + List fileMetas = flatFileMetas.get(phyTable); + if (fileMetas.isEmpty()) { + continue; + } + + // build single physical table list and params, + // and split for each file. + List singlePhyTableNameList = ImmutableList.of(phyTable); + + Map params = + phyOperationBuilder.buildSplitParamMap(singlePhyTableNameList); + + for (FileMeta fileMeta : fileMetas) { + OssSplit ossSplit = new OssSplit(logicalSchema, physicalSchema, params, + logicalTableName, singlePhyTableNameList, ImmutableList.of(fileMeta.getFileName()), null, + null, NO_PARTITION_INFO, false); + splits.add(ossSplit); } - return splits; } + return splits; } - public static int calcPartition(String logicalSchema, String logicalTableName, String physicalSchema, - String physicalTableName) { - PartitionInfo partInfo = - OptimizerContext.getContext(logicalSchema).getPartitionInfoManager() - .getPartitionInfo(logicalTableName); - int partition = partInfo.getPartitionBy().getPartitions().stream(). - filter( - t -> t.getLocation().getGroupKey().equalsIgnoreCase(physicalSchema) - && t.getLocation().getPhyTableName().equalsIgnoreCase(physicalTableName)) - .findFirst().map(PartSpecBase::getPosition).map(Long::intValue).orElse(-1); - return partition - 1; + public static List getFileConcurrencySplit(OSSTableScan ossTableScan, RelNode relNode, + ExecutionContext executionContext, Long tso) { + Preconditions.checkArgument(relNode instanceof PhyTableOperation); + + PhyTableOperation phyTableOperation = (PhyTableOperation) relNode; + String logicalSchema = phyTableOperation.getSchemaName(); + String physicalSchema = phyTableOperation.getDbIndex(); + + String logicalTableName = phyTableOperation.getLogicalTableNames().get(0); + List phyTableNameList = phyTableOperation.getTableNames().get(0); + + PhyTableScanBuilder phyOperationBuilder = + (PhyTableScanBuilder) phyTableOperation.getPhyOperationBuilder(); + + TableMeta tableMeta = executionContext.getSchemaManager(logicalSchema).getTable(logicalTableName); + + if (ossTableScan.isColumnarIndex()) { + if (ossTableScan.isFlashbackQuery()) { + return getFileConcurrencySplitForFlashback(executionContext, ossTableScan, tableMeta, logicalSchema, + physicalSchema, logicalTableName, phyTableNameList, phyOperationBuilder, tso); + } else { + return getFileConcurrencySplitForColumnar(executionContext, ossTableScan, tableMeta, logicalSchema, + physicalSchema, logicalTableName, phyTableNameList, phyOperationBuilder, tso); + } + } else { + return getFileConcurrencySplitForColdData(tableMeta, logicalSchema, + physicalSchema, logicalTableName, phyTableNameList, phyOperationBuilder); + } } @JsonIgnore @@ -851,19 +951,7 @@ public void init(OSSTableScan ossTableScan, ExecutionContext executionContext, (OSSOrcFileMeta) allFileMetas.get(0).get(0)); } - Long readTs = null; - if (ossTableScan.getFlashback() instanceof RexDynamicParam) { - - String timestampString = executionContext.getParams().getCurrentParameter() - .get(((RexDynamicParam) ossTableScan.getFlashback()).getIndex() + 1).getValue().toString(); - TimeZone fromTimeZone; - if (executionContext.getTimeZone() != null) { - fromTimeZone = executionContext.getTimeZone().getTimeZone(); - } else { - fromTimeZone = TimeZone.getDefault(); - } - readTs = OSSTaskUtils.getTsFromTimestampWithTimeZone(timestampString, fromTimeZone); - } + Long readTs = ossTableScan.getFlashbackQueryTso(executionContext); for (int j = 0; j < allFileMetas.size(); j++) { String phyTable = phyTableNameList.get(j); @@ -1178,7 +1266,7 @@ public String toString() { .toString(); } - public static class DeltaReadOption implements Serializable { + public static class DeltaReadOption implements Serializable, IDeltaReadOption { /** * checkpoint tso for columnar store. */ @@ -1189,6 +1277,13 @@ public static class DeltaReadOption implements Serializable { */ private Map> allCsvFiles; + private Map> allPositions; + + /** + * map: {part name} -> {list } + */ + private Map>> allDelPositions; + private List projectColumnIndexes; public DeltaReadOption(long checkpointTso) { @@ -1199,9 +1294,13 @@ public DeltaReadOption(long checkpointTso) { public DeltaReadOption( @JsonProperty("checkpointTso") long checkpointTso, @JsonProperty("allCsvFiles") Map> allCsvFiles, + @JsonProperty("allPositions") Map> allPositions, + @JsonProperty("allDelPositions") Map>> allDelPositions, @JsonProperty("projectColumnIndexes") List projectColumnIndexes) { this.checkpointTso = checkpointTso; this.allCsvFiles = allCsvFiles; + this.allPositions = allPositions; + this.allDelPositions = allDelPositions; this.projectColumnIndexes = projectColumnIndexes; } @@ -1215,6 +1314,16 @@ public Map> getAllCsvFiles() { return allCsvFiles; } + @JsonProperty + public Map> getAllPositions() { + return allPositions; + } + + @JsonProperty + public Map>> getAllDelPositions() { + return allDelPositions; + } + @JsonProperty public List getProjectColumnIndexes() { return projectColumnIndexes; @@ -1224,8 +1333,59 @@ public void setAllCsvFiles(Map> allCsvFiles) { this.allCsvFiles = allCsvFiles; } + public void setAllPositions(Map> allPositions) { + this.allPositions = allPositions; + } + + public void setAllDelPositions(Map>> allDelPositions) { + // TODO(siyun): optimize the map to reduce the size + this.allDelPositions = allDelPositions; + } + public void setProjectColumnIndexes(List projectColumnIndexes) { this.projectColumnIndexes = projectColumnIndexes; } } + + public List getPrunedOrcFiles(OSSTableScan ossTableScan, ExecutionContext executionContext) { + List fileNames = getDesignatedFile(); + + if (fileNames == null) { + return null; + } + + if (ossTableScan.isColumnarIndex()) { + return fileNames; + } + + Long readTs = ossTableScan.getFlashbackQueryTso(executionContext); + + if (readTs == null) { + return fileNames; + } + + TableMeta tableMeta = executionContext.getSchemaManager(getLogicalSchema()).getTable( + getLogicalTableName()); + Set filterSet = getFilterSet(executionContext); + Map> flatFileMetas = tableMeta.getFlatFileMetas(); + + return getPhyTableNameList().stream() + .map(flatFileMetas::get) + .flatMap(List::stream) + .filter(x -> { + if (filterSet == null || filterSet.contains(x.getFileName())) { + if (readTs < x.getCommitTs()) { + // not committed yet at this ts + return false; + } + // not removed yet at this ts + return x.getRemoveTs() == null || readTs <= x.getRemoveTs(); + } else { + // not designated for this split + return false; + } + }) + .map(FileMeta::getFileName) + .collect(Collectors.toList()); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/split/SpecifiedOssSplit.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/split/SpecifiedOssSplit.java new file mode 100644 index 000000000..9400e8270 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/split/SpecifiedOssSplit.java @@ -0,0 +1,312 @@ +package com.alibaba.polardbx.executor.mpp.split; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.oss.IDeltaReadOption; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; +import com.alibaba.polardbx.executor.archive.schemaevolution.ColumnMetaWithTs; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.Field; +import com.alibaba.polardbx.optimizer.config.table.FileMeta; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; +import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation; +import com.alibaba.polardbx.optimizer.core.rel.PhyTableScanBuilder; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.RelPartitionWise; +import org.apache.calcite.sql.type.SqlTypeName; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.alibaba.polardbx.optimizer.config.table.OrcMetaUtils.TYPE_FACTORY; +import static com.alibaba.polardbx.optimizer.utils.PartitionUtils.calcPartition; + +/** + * This oss split contains specified orc/csv/del files. + * It will also read TSO column. + * + * @author yaozhili + */ +public class SpecifiedOssSplit extends OssSplit { + public SpecifiedOssSplit(String logicalSchema, String physicalSchema, + Map params, + String logicalTableName, List phyTableNameList, + List designatedFile, DeltaReadOption deltaReadOption, Long checkpointTso, + int partIndex, Boolean localPairWise) { + super(logicalSchema, physicalSchema, params, logicalTableName, phyTableNameList, designatedFile, + deltaReadOption, + checkpointTso, partIndex, localPairWise); + } + + @JsonCreator + public SpecifiedOssSplit( + @JsonProperty("logicalSchema") String logicalSchema, + @JsonProperty("physicalSchema") String physicalSchema, + @JsonProperty("paramsBytes") byte[] paramsBytes, + @JsonProperty("logicalTableName") String logicalTableName, + @JsonProperty("phyTableNameList") List phyTableNameList, + @JsonProperty("designatedFile") List designatedFile, + @JsonProperty("deltaReadOption") DeltaReadWithPositionOption deltaReadOption, + @JsonProperty("checkpointTso") Long checkpointTso, + @JsonProperty("partIndex") int partIndex, + @JsonProperty("nodePartCount") int nodePartCount, + @JsonProperty("localPairWise") boolean localPairWise) { + super(logicalSchema, physicalSchema, paramsBytes, logicalTableName, phyTableNameList, designatedFile, + deltaReadOption, checkpointTso, partIndex, nodePartCount, localPairWise); + } + + public static List getSpecifiedSplit(OSSTableScan ossTableScan, RelNode relNode, + ExecutionContext executionContext) { + Preconditions.checkArgument(relNode instanceof PhyTableOperation); + List splits = new ArrayList<>(); + + PhyTableOperation phyTableOperation = (PhyTableOperation) relNode; + String logicalSchema = phyTableOperation.getSchemaName(); + String physicalSchema = phyTableOperation.getDbIndex(); + + String logicalTableName = phyTableOperation.getLogicalTableNames().get(0); + List phyTableNameList = phyTableOperation.getTableNames().get(0); + + TableMeta tableMeta = executionContext.getSchemaManager(logicalSchema).getTable(logicalTableName); + + PhyTableScanBuilder phyOperationBuilder = + (PhyTableScanBuilder) phyTableOperation.getPhyOperationBuilder(); + + final PartitionInfo partitionInfo = tableMeta.getPartitionInfo(); + + Map> specifiedOrcFiles = executionContext.getReadOrcFiles(); + Map specifiedDeltaFiles = executionContext.getReadDeltaFiles(); + + // for each physical table + for (int i = 0; i < phyTableNameList.size(); i++) { + String phyTable = phyTableNameList.get(i); + + // Find part name from physical schema + physical table + final String partName = partitionInfo.getPartitionNameByPhyLocation(physicalSchema, phyTable); + + Set orcFiles = null == specifiedOrcFiles ? null : specifiedOrcFiles.get(partName); + DeltaReadWithPositionOption deltaReadOption = null == specifiedDeltaFiles ? null : + (DeltaReadWithPositionOption) specifiedDeltaFiles.get(partName); + + if (null == orcFiles + && (executionContext.isReadOrcOnly() + || null == deltaReadOption + || null == deltaReadOption.getCsvFiles())) { + // case 1: no orc files but only orc files are considered. + // case 2: no orc files and no delta files. + // case 3: no orc files and no csv files, only delete files mean nothing. + continue; + } + + RelPartitionWise partitionWise = ossTableScan.getTraitSet().getPartitionWise(); + boolean needPartition = partitionWise.isRemotePartition() || executionContext.getParamManager() + .getBoolean(ConnectionParams.SCHEDULE_BY_PARTITION); + + int partition = needPartition ? + calcPartition(logicalSchema, logicalTableName, physicalSchema, phyTable) : NO_PARTITION_INFO; + boolean localPairWise = + executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_LOCAL_PARTITION_WISE_JOIN) + && partitionWise.isLocalPartition(); + + List singlePhyTableNameList = ImmutableList.of(phyTable); + + Map params = + phyOperationBuilder.buildSplitParamMap(singlePhyTableNameList); + + OssSplit ossSplit = new SpecifiedOssSplit( + logicalSchema, physicalSchema, params, + logicalTableName, singlePhyTableNameList, + null == orcFiles ? null : new ArrayList<>(orcFiles), deltaReadOption, + null == deltaReadOption ? 0 : deltaReadOption.getCheckpointTso(), partition, localPairWise); + splits.add(ossSplit); + } + return splits; + } + + public OSSColumnTransformer getColumnTransformer(OSSTableScan ossTableScan, + ExecutionContext executionContext, + String fileName, + boolean addTsoInfo) { + TableMeta tableMeta = executionContext.getSchemaManager(logicalSchema).getTable(logicalTableName); + List timestamps = new ArrayList<>(); + List columnMetas = new ArrayList<>(); + List fileColumnMetas = new ArrayList<>(); + List initColumnMetas = new ArrayList<>(); + List locInOrc = new ArrayList<>(); + + FileMeta fileMeta = ColumnarManager.getInstance().fileMetaOf(fileName); + List inProjects = ossTableScan.getOrcNode().getInProjects(); + List inProjectNames = ossTableScan.getOrcNode().getInputProjectName(); + long tableId = Long.parseLong(fileMeta.getLogicalTableName()); + + Map columnIndexMap = + ColumnarManager.getInstance().getColumnIndex(fileMeta.getSchemaTs(), tableId); + + for (int i = 0; i < inProjects.size(); i++) { + Integer columnIndex = inProjects.get(i); + String columnName = inProjectNames.get(i); + + columnMetas.add(tableMeta.getColumn(columnName)); + + long fieldId = tableMeta.getColumnarFieldId(columnIndex); + Integer actualColumnIndex = columnIndexMap.get(fieldId); + if (actualColumnIndex != null) { + fileColumnMetas.add(fileMeta.getColumnMetas().get(actualColumnIndex)); + locInOrc.add(actualColumnIndex + 1); + timestamps.add(null); + initColumnMetas.add(null); + } else { + ColumnMetaWithTs metaWithTs = ColumnarManager.getInstance().getInitColumnMeta(tableId, fieldId); + fileColumnMetas.add(null); + locInOrc.add(null); + timestamps.add(metaWithTs.getCreate()); + initColumnMetas.add(metaWithTs.getMeta()); + } + } + + // Add TSO column meta to the last column. + if (addTsoInfo) { + ColumnMeta tsoColumnMeta = new ColumnMeta(tableMeta.getTableName(), "tso", null, + new Field(TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT))); + columnMetas.add(tsoColumnMeta); + fileColumnMetas.add(fileMeta.getColumnMetas().get(0)); + locInOrc.add(1); + } + + return new OSSColumnTransformer( + columnMetas, + fileColumnMetas, + initColumnMetas, + timestamps, + locInOrc + ); + } + + public static class DeltaReadWithPositionOption extends DeltaReadOption { + private final long tsoV0; + private final long tsoV1; + private final long tableId; + private List csvFiles; + private List csvStartPos; + private List csvEndPos; + private List delFiles; + private List delBeginPos; + private List delEndPos; + + public DeltaReadWithPositionOption(long checkpointTso, long tsoV0, long tsoV1, long tableId) { + super(checkpointTso); + this.tsoV0 = tsoV0; + this.tsoV1 = tsoV1; + this.tableId = tableId; + } + + @JsonCreator + public DeltaReadWithPositionOption( + @JsonProperty("checkpointTso") long checkpointTso, + @JsonProperty("allCsvFiles") Map> allCsvFiles, + @JsonProperty("allPositions") Map> allPositions, + @JsonProperty("allDelPositions") Map>> allDelPositions, + @JsonProperty("projectColumnIndexes") List projectColumnIndexes, + @JsonProperty("tsoV0") long tsoV0, + @JsonProperty("tsoV1") long tsoV1, + @JsonProperty("tableId") long tableId, + @JsonProperty("csvFiles") List csvFiles, + @JsonProperty("csvStartPos") List startPos, + @JsonProperty("csvEndPos") List endPos, + @JsonProperty("delFiles") List delFiles, + @JsonProperty("delBeginPos") List delBeginPos, + @JsonProperty("delEndPos") List delEndPos) { + super(checkpointTso, allCsvFiles, allPositions, allDelPositions, projectColumnIndexes); + this.tsoV0 = tsoV0; + this.tsoV1 = tsoV1; + this.tableId = tableId; + this.csvFiles = csvFiles; + this.csvStartPos = startPos; + this.csvEndPos = endPos; + this.delFiles = delFiles; + this.delBeginPos = delBeginPos; + this.delEndPos = delEndPos; + } + + @JsonProperty + public List getCsvFiles() { + return csvFiles; + } + + @JsonProperty + public List getCsvStartPos() { + return csvStartPos; + } + + @JsonProperty + public List getCsvEndPos() { + return csvEndPos; + } + + @JsonProperty + public List getDelFiles() { + return delFiles; + } + + @JsonProperty + public List getDelBeginPos() { + return delBeginPos; + } + + @JsonProperty + public List getDelEndPos() { + return delEndPos; + } + + @JsonProperty + public long getTsoV0() { + return tsoV0; + } + + @JsonProperty + public long getTsoV1() { + return tsoV1; + } + + @JsonProperty + public long getTableId() { + return tableId; + } + + public void setCsvFiles(List csvFiles) { + this.csvFiles = csvFiles; + } + + public void setCsvStartPos(List csvStartPos) { + this.csvStartPos = csvStartPos; + } + + public void setCsvEndPos(List csvEndPos) { + this.csvEndPos = csvEndPos; + } + + public void setDelFiles(List delFiles) { + this.delFiles = delFiles; + } + + public void setDelBeginPos(List delBeginPos) { + this.delBeginPos = delBeginPos; + } + + public void setDelEndPos(List delEndPos) { + this.delEndPos = delEndPos; + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/split/SplitManagerImpl.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/split/SplitManagerImpl.java index 73391f9d7..85c0bb7f4 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/split/SplitManagerImpl.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/split/SplitManagerImpl.java @@ -20,6 +20,7 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.jdbc.BytesSql; import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; @@ -29,22 +30,36 @@ import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.common.TopologyHandler; import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.gms.DynamicColumnarManager; import com.alibaba.polardbx.executor.mpp.metadata.Split; import com.alibaba.polardbx.executor.spi.IGroupExecutor; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.executor.utils.SubqueryUtils; +import com.alibaba.polardbx.gms.metadb.columnar.FlashbackColumnarManager; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; import com.alibaba.polardbx.optimizer.core.rel.BaseQueryOperation; import com.alibaba.polardbx.optimizer.core.rel.BaseTableOperation; import com.alibaba.polardbx.optimizer.core.rel.LogicalView; import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation; import com.alibaba.polardbx.optimizer.core.rel.PhyTableScanBuilder; +import com.alibaba.polardbx.optimizer.core.rel.util.DynamicParamInfo; +import com.alibaba.polardbx.optimizer.core.rel.util.IndexedDynamicParamInfo; +import com.alibaba.polardbx.optimizer.partition.PartSpecBase; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.pruning.PartPrunedResult; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruneStep; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruneStepBuilder; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruner; +import com.alibaba.polardbx.optimizer.partition.pruning.PhysicalPartitionInfo; import com.alibaba.polardbx.optimizer.utils.GroupConnId; import com.alibaba.polardbx.optimizer.utils.IColumnarTransaction; import com.alibaba.polardbx.optimizer.utils.ITransaction; +import com.alibaba.polardbx.optimizer.utils.OptimizerUtils; import com.alibaba.polardbx.optimizer.utils.PhyTableOperationUtil; +import com.alibaba.polardbx.optimizer.utils.PlannerUtils; import com.alibaba.polardbx.optimizer.utils.QueryConcurrencyPolicy; import com.alibaba.polardbx.optimizer.utils.RelUtils; import com.alibaba.polardbx.statistics.RuntimeStatistics; @@ -70,6 +85,10 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.SortedMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static com.alibaba.polardbx.group.jdbc.TGroupDataSource.LOCAL_ADDRESS; import static com.alibaba.polardbx.optimizer.utils.QueryConcurrencyPolicy.CONCURRENT; @@ -415,6 +434,141 @@ private SplitInfo logicalViewSplit(LogicalView logicalView, ExecutionContext exe } + public static SplitInfo columnarOssTableScanSplit(OSSTableScan ossTableScan, ExecutionContext executionContext, + long tso) { + DynamicColumnarManager dynamicColumnarManager = (DynamicColumnarManager) ColumnarManager.getInstance(); + String schemaName = StringUtils.isEmpty(ossTableScan.getSchemaName()) + ? executionContext.getSchemaName() : ossTableScan.getSchemaName(); + String tableName = ossTableScan.getLogicalTableName(); + + SortedMap multiVersionPartitionInfo = + dynamicColumnarManager.getPartitionInfos(tso, schemaName, tableName); + + // Empty partition info demonstrates that the snapshot is empty so far + if (multiVersionPartitionInfo.isEmpty()) { + return new SplitInfo(ossTableScan.getRelatedId(), ossTableScan.isExpandView(), FILE_CONCURRENT, + ImmutableList.of(ImmutableList.of()), new HashMap<>(), 1, 0, false); + } + + // TODO(siyun): add cache for columnar pruning result + SortedMap> multiVersionPartitionResult = + OptimizerUtils.pruningInValueForColumnar(ossTableScan, executionContext, multiVersionPartitionInfo); + + // There is no raw-string pruning, regenerate pruned result + if (multiVersionPartitionResult == null) { + multiVersionPartitionResult = new ConcurrentSkipListMap<>(); + final SortedMap> finalResult = multiVersionPartitionResult; + multiVersionPartitionInfo.forEach((lowerBoundTso, partitionInfo) -> { + PartPrunedResult tablePrunedResult = + ossTableScan.getCciPartPrunedResults(executionContext, partitionInfo).get(0); + + finalResult.put( + lowerBoundTso, + tablePrunedResult.getPrunedParttions().stream().map( + PhysicalPartitionInfo::getPartName + ).collect(Collectors.toSet()) + ); + }); + } + + PartitionInfo currentPartitionInfo = multiVersionPartitionInfo.get(multiVersionPartitionInfo.lastKey()); + + // TODO(siyun): optimize codes + SqlNode sqlTemplate = ossTableScan.getSqlTemplate(executionContext); + List dynamicParamList = PlannerUtils.getDynamicParamInfoList(sqlTemplate); + Map params = + executionContext.getParams() == null ? null : executionContext.getParams().getCurrentParameter(); + Map results = new HashMap<>(); + + if (params != null) { + for (DynamicParamInfo dynamicParamInfo : dynamicParamList) { + if (dynamicParamInfo instanceof IndexedDynamicParamInfo) { + int i = ((IndexedDynamicParamInfo) dynamicParamInfo).getParamIndex(); + if (i != PlannerUtils.TABLE_NAME_PARAM_INDEX && i != PlannerUtils.SCALAR_SUBQUERY_PARAM_INDEX + && i != PlannerUtils.APPLY_SUBQUERY_PARAM_INDEX) { + results.put(i, params.get(i + 1)); + } + } else { + throw new IllegalArgumentException("Unsupported dynamic param info: " + dynamicParamInfo); + } + } + } + + List splitList; + if (ossTableScan.isFlashbackQuery()) { + FlashbackColumnarManager flashbackColumnarManager = + new FlashbackColumnarManager(tso, schemaName, tableName); + Map>> deletePositionMap = + flashbackColumnarManager.getDeletePositions(multiVersionPartitionResult); + splitList = flashbackColumnarManager.getSnapshotInfo(multiVersionPartitionResult) + .entrySet().stream().flatMap(entry -> { + String partName = entry.getKey(); + int partition = currentPartitionInfo.getPartitionBy().getPartitions().stream() + .filter(part -> part.getName().equalsIgnoreCase(partName)) + .findFirst().map(PartSpecBase::getPosition).map(Long::intValue).orElse(0); + List orcFileNames = entry.getValue().getKey(); + List> csvFileNamesAndPos = entry.getValue().getValue(); + + return Stream.concat( + orcFileNames.stream().map(fileName -> { + OssSplit.DeltaReadOption deltaReadOption = new OssSplit.DeltaReadOption(tso); + deltaReadOption.setAllDelPositions(deletePositionMap); + return new Split(false, new OssSplit( + schemaName, "", results, tableName, null, + Collections.singletonList(fileName), deltaReadOption, tso, partition, false + )); + }), + csvFileNamesAndPos.stream().map(fileNameAndPos -> { + OssSplit.DeltaReadOption deltaReadOption = new OssSplit.DeltaReadOption(tso); + deltaReadOption.setAllCsvFiles(Collections.singletonMap(partName, + Collections.singletonList(fileNameAndPos.getKey()))); + deltaReadOption.setAllPositions(Collections.singletonMap(partName, + Collections.singletonList(fileNameAndPos.getValue()))); + deltaReadOption.setAllDelPositions(deletePositionMap); + return new Split(false, new OssSplit( + schemaName, "", results, tableName, null, null, deltaReadOption, tso, partition, false + )); + }) + ); + }).collect(Collectors.toList()); + + } else { + splitList = dynamicColumnarManager.findFileNames(tso, schemaName, tableName, multiVersionPartitionResult) + .entrySet().stream().flatMap(entry -> { + String partName = entry.getKey(); + int partition = currentPartitionInfo.getPartitionBy().getPartitions().stream() + .filter(part -> part.getName().equalsIgnoreCase(partName)) + .findFirst().map(PartSpecBase::getPosition).map(Long::intValue).orElse(0); + List orcFileNames = entry.getValue().getKey(); + List csvFileNames = entry.getValue().getValue(); + + return Stream.concat( + orcFileNames.stream() + .map(fileName -> new Split(false, new OssSplit( + schemaName, "", results, tableName, null, + Collections.singletonList(fileName), null, tso, partition, false + ))), + csvFileNames.stream() + .map(fileName -> { + OssSplit.DeltaReadOption deltaReadOption = new OssSplit.DeltaReadOption(tso); + deltaReadOption.setAllCsvFiles( + Collections.singletonMap(partName, Collections.singletonList(fileName))); + return new Split(false, new OssSplit( + schemaName, "", results, tableName, null, null, deltaReadOption, tso, partition, + false + )); + }) + ); + }).collect(Collectors.toList()); + } + + if (splitList.size() > 0) { + executionContext.setHasScanWholeTable(true); + } + return new SplitInfo(ossTableScan.getRelatedId(), ossTableScan.isExpandView(), FILE_CONCURRENT, + ImmutableList.of(splitList), new HashMap<>(), 1, splitList.size(), false); + } + private SplitInfo ossTableScanSplit( OSSTableScan ossTableScan, ExecutionContext executionContext, boolean highConcurrencyQuery) { if (ossTableScan == null) { @@ -424,14 +578,63 @@ private SplitInfo ossTableScanSplit( QueryConcurrencyPolicy concurrencyPolicy = ExecUtils.getQueryConcurrencyPolicy(executionContext, ossTableScan); + // Before allocating splits, a certain tso must be fetched first + Long tso = null; + if (ossTableScan.isColumnarIndex()) { + ITransaction trans = executionContext.getTransaction(); + if (trans instanceof IColumnarTransaction) { + Long flashBackQueryTso = ossTableScan.getFlashbackQueryTso(executionContext); + if (flashBackQueryTso != null) { + tso = flashBackQueryTso; + // flashback query tso may differ among tables, + // so we do not set tso for columnar trans + } else { + IColumnarTransaction columnarTrans = (IColumnarTransaction) trans; + if (!columnarTrans.snapshotSeqIsEmpty()) { + tso = columnarTrans.getSnapshotSeq(); + } else { + tso = ColumnarManager.getInstance().latestTso(); + columnarTrans.setTsoTimestamp(tso); + } + } + } else { + LOGGER.warn("Trying to access columnar index out of IMppReadOnlyTransaction, transaction class is: " + + trans.getTransactionClass().name()); + Long flashBackQueryTso = ossTableScan.getFlashbackQueryTso(executionContext); + if (flashBackQueryTso != null) { + tso = flashBackQueryTso; + } else { + tso = ColumnarManager.getInstance().latestTso(); + } + } + } + List inputs = ExecUtils.getInputs( ossTableScan, executionContext, !ExecUtils.isMppMode(executionContext)); + if (executionContext.isCciIncrementalCheck() + || executionContext.isReadCsvOnly() + || executionContext.isReadOrcOnly() + || executionContext.isReadSpecifiedColumnarFiles()) { + // Splits are already partitioned by partition. + // Normal query should not get here. + return generateSpecifiedSplitInfo(ossTableScan, inputs, executionContext); + } + String schemaName = ossTableScan.getSchemaName(); if (StringUtils.isEmpty(schemaName)) { schemaName = executionContext.getSchemaName(); } + if (ossTableScan.isColumnarIndex() + && CBOUtil.isArchiveCCi(schemaName, ossTableScan.getLogicalTableName()) + // In case multi-version partition info is disrupted or too slow + // SET ENABLE_COLUMNAR_MULTI_VERSION_PARTITION=false to fall back to old logic + && executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_COLUMNAR_MULTI_VERSION_PARTITION)) { + return columnarOssTableScanSplit(ossTableScan, executionContext, tso); + } + if (inputs.size() > 1) { // record full table scan executionContext.setHasScanWholeTable(true); @@ -445,24 +648,6 @@ private SplitInfo ossTableScanSplit( ExecUtils.zigzagInputsByMysqlInst(inputs, schemaName, executionContext); List splitList = new ArrayList<>(); - // Before allocating splits, a certain tso must be fetched first - Long tso = null; - if (ossTableScan.isColumnarIndex()) { - ITransaction trans = executionContext.getTransaction(); - if (trans instanceof IColumnarTransaction) { - IColumnarTransaction columnarTrans = (IColumnarTransaction) trans; - if (!columnarTrans.snapshotSeqIsEmpty()) { - tso = columnarTrans.getSnapshotSeq(); - } else { - tso = ColumnarManager.getInstance().latestTso(); - columnarTrans.setTsoTimestamp(tso); - } - } else { - LOGGER.warn("Trying to access columnar index out of IMppReadOnlyTransaction, transaction class is: " - + trans.getTransactionClass().name()); - tso = ColumnarManager.getInstance().latestTso(); - } - } switch (concurrencyPolicy) { case SEQUENTIAL: @@ -571,4 +756,25 @@ private JdbcSplit parseRelNode(LogicalView logicalView, TopologyHandler topology throw new UnsupportedOperationException("Unknown input " + input); } } + + private SplitInfo generateSpecifiedSplitInfo(OSSTableScan ossTableScan, + List sortInputs, + ExecutionContext ec) { + HashMap shardSet = new HashMap<>(); + List splitList = new ArrayList<>(); + int splitCount = 0; + for (RelNode input : sortInputs) { + List splits = SpecifiedOssSplit.getSpecifiedSplit(ossTableScan, input, ec); + for (OssSplit split : splits) { + shardSet.put(split.getPhysicalSchema(), split.getLogicalSchema()); + splitList.add(new Split(false, split)); + splitCount++; + } + } + return new SplitInfo(ossTableScan.getRelatedId(), ossTableScan.isExpandView(), + FILE_CONCURRENT, + ImmutableList.of(splitList), + shardSet, 1, + splitCount, false); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/web/ClusterStatsResource.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/web/ClusterStatsResource.java index f606472eb..c3dd6a2fc 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/web/ClusterStatsResource.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/web/ClusterStatsResource.java @@ -20,8 +20,8 @@ import com.alibaba.polardbx.executor.mpp.execution.QueryManager; import com.alibaba.polardbx.executor.mpp.execution.QueryState; import com.alibaba.polardbx.gms.node.InternalNodeManager; +import com.alibaba.polardbx.gms.node.MppScope; import com.alibaba.polardbx.gms.node.Node; -import com.alibaba.polardbx.gms.node.NodeState; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -102,7 +102,7 @@ protected static ClusterStats getClusterStatsInternal(List queryIfs, @Produces(MediaType.APPLICATION_JSON) public ClusterStats getClusterStats() { long activeNodes = 0; - for (Node node : nodeManager.getNodes(NodeState.ACTIVE, true)) { + for (Node node : nodeManager.getAllNodes().getAllWorkers(MppScope.ALL)) { if (node.isWorker()) { activeNodes++; } @@ -126,27 +126,16 @@ public static class ClusterStats { @JsonCreator public ClusterStats( - @JsonProperty("totalQueries") - long totalQueries, //总的query数目 - @JsonProperty("runningQueries") - long runningQueries, //运行query数目 - @JsonProperty("blockedQueries") - long blockedQueries, //blocked query数目 - @JsonProperty("queuedQueries") - long queuedQueries, - @JsonProperty("activeWorkers") - long activeWorkers, - @JsonProperty("runningDrivers") - long runningDrivers, - @JsonProperty("reservedMemory") - double reservedMemory, - @JsonProperty("rowInputRate") - double rowInputRate, - @JsonProperty("byteInputRate") - double byteInputRate, - @JsonProperty("cpuTimeRate") - double cpuTimeRate - ) { + @JsonProperty("totalQueries") long totalQueries, //总的query数目 + @JsonProperty("runningQueries") long runningQueries, //运行query数目 + @JsonProperty("blockedQueries") long blockedQueries, //blocked query数目 + @JsonProperty("queuedQueries") long queuedQueries, + @JsonProperty("activeWorkers") long activeWorkers, + @JsonProperty("runningDrivers") long runningDrivers, + @JsonProperty("reservedMemory") double reservedMemory, + @JsonProperty("rowInputRate") double rowInputRate, + @JsonProperty("byteInputRate") double byteInputRate, + @JsonProperty("cpuTimeRate") double cpuTimeRate) { this.totalQueries = totalQueries; this.runningQueries = runningQueries; this.blockedQueries = blockedQueries; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/web/WorkerResource.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/web/WorkerResource.java index 2513a31c5..07eb95273 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/web/WorkerResource.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/mpp/web/WorkerResource.java @@ -18,8 +18,7 @@ import com.alibaba.polardbx.gms.node.InternalNode; import com.alibaba.polardbx.gms.node.InternalNodeManager; -import com.alibaba.polardbx.gms.node.Node; -import com.alibaba.polardbx.gms.node.NodeState; +import com.alibaba.polardbx.gms.node.MppScope; import io.airlift.http.client.HttpClient; import io.airlift.http.client.Request; @@ -30,7 +29,7 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import java.io.InputStream; -import java.util.Set; +import java.util.List; import static io.airlift.http.client.HttpUriBuilder.uriBuilderFrom; import static io.airlift.http.client.Request.Builder.prepareGet; @@ -62,8 +61,8 @@ public Response getThreads(@PathParam("nodeId") String nodeId) { } private Response proxyJsonResponse(String nodeId, String workerPath) { - Set nodes = nodeManager.getNodes(NodeState.ACTIVE, true); - Node node = nodes.stream() + List nodes = nodeManager.getAllNodes().getAllWorkers(MppScope.ALL); + InternalNode node = nodes.stream() .filter(n -> n.getNodeIdentifier().equals(nodeId)) .findFirst() .orElseThrow(() -> new WebApplicationException(NOT_FOUND)); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/AbstractHashJoinExec.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/AbstractHashJoinExec.java index 11fb3fa4e..41cda354d 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/AbstractHashJoinExec.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/AbstractHashJoinExec.java @@ -155,7 +155,7 @@ protected int getBuildChunkConditionIndex() { return Math.min(idx1, idx2); } else { int buildIndex = Math.max(idx1, idx2); - // since this is inner build, build chunk is on the left side + // since this is inner build, build chunk is on the right side return buildIndex - outerInput.getDataTypes().size(); } } @@ -1124,7 +1124,8 @@ public int estimateSize() { } /** - * 仅使用于 semi/anti join 且 long = long and int <> int + * 1. semi/anti join + * 2. long = long and int <> int */ class SemiLongNotEqIntegerProbeOperator implements ProbeOperator { @@ -1276,6 +1277,160 @@ public int estimateSize() { } } + /** + * 1. semi/anti join + * 2. long = long and long <> long + */ + class SemiLongNotEqLongProbeOperator implements ProbeOperator { + + protected final boolean enableVecBuildJoinRow; + protected final boolean isAnti; + // for hash code. + protected final int[] probeKeyHashCode = new int[chunkLimit]; + protected final int[] intermediates = new int[chunkLimit]; + protected final int[] blockHashCodes = new int[chunkLimit]; + protected long[] longValueArray; + protected long[] longValueArray2; + protected int startProbePosition; + protected int conditionProbeColIndex = -1; + // for null values of probe keys. + protected boolean hasNull = false; + protected BitSet nullBitmap = new BitSet(chunkLimit); + + protected SemiLongNotEqLongProbeOperator(boolean enableVecBuildJoinRow) { + if (joinType == JoinRelType.SEMI) { + this.isAnti = false; + } else if (joinType == JoinRelType.ANTI) { + this.isAnti = true; + } else { + throw new UnsupportedOperationException("JoinType not supported: " + joinType); + } + Preconditions.checkArgument(antiJoinOperands == null); + this.enableVecBuildJoinRow = enableVecBuildJoinRow; + + this.longValueArray = new long[chunkLimit]; + this.longValueArray2 = new long[chunkLimit]; + + conditionProbeColIndex = getProbeChunkConditionIndex(); + Preconditions.checkArgument( + conditionProbeColIndex >= 0 && conditionProbeColIndex < outerInput.getDataTypes().size(), + "Illegal Join condition probe index : " + conditionProbeColIndex); + } + + @Override + public void nextRows() { + Preconditions.checkArgument(probeJoinKeyChunk.getBlockCount() == 1 + && probeJoinKeyChunk.getBlock(0).cast(Block.class) instanceof LongBlock); + Preconditions.checkArgument( + probeChunk.getBlock(conditionProbeColIndex).cast(Block.class) instanceof LongBlock, + "Probe condition block should be LongBlock"); + final int positionCount = probeChunk.getPositionCount(); + + // build hash code vector + probeJoinKeyChunk.hashCodeVector(probeKeyHashCode, intermediates, blockHashCodes, positionCount); + + startProbePosition = probePosition; + // copy array from long block + Block keyBlock = probeJoinKeyChunk.getBlock(0).cast(Block.class); + keyBlock.copyToLongArray(startProbePosition, positionCount - startProbePosition, longValueArray, 0); + + // handle nulls + hasNull = keyBlock.mayHaveNull(); + nullBitmap.clear(); + if (hasNull) { + keyBlock.collectNulls(startProbePosition, positionCount - startProbePosition, nullBitmap, 0); + } + + probeChunk.getBlock(conditionProbeColIndex).cast(Block.class) + .copyToLongArray(startProbePosition, positionCount - startProbePosition, longValueArray2, 0); + for (; probePosition < positionCount; probePosition++) { + + // reset matched flag unless it's still during matching + if (!isMatching) { + matched = false; + matchedPosition = matchInit(probeKeyHashCode, probePosition); + } else { + // continue from the last processed match + matchedPosition = matchNext(matchedPosition, probePosition); + isMatching = false; + } + + for (; matchValid(matchedPosition); + matchedPosition = matchNext(matchedPosition, probePosition)) { + if (!matchJoinCondition(probePosition, matchedPosition)) { + continue; + } + + // set matched flag + matched = true; + + // semi join does not care multiple matches + break; + } + + // (!isAnti && matched) || (isAnti && !matched) + if (isAnti ^ matched) { + buildSemiJoinRow(probeChunk, probePosition); + } + + // check buffered data is full + if (currentPosition() >= chunkLimit) { + probePosition++; + return; + } + } + } + + private boolean matchJoinCondition(int probePosition, int matchedPosition) { + // NotEqual + return buildChunks.getLong(0, matchedPosition) != longValueArray2[probePosition - startProbePosition]; + } + + private int matchInit(int[] hashCodes, int position) { + // check null + if (hasNull && nullBitmap.get(position - startProbePosition)) { + return LIST_END; + } + + // find matched positions for each row. + int matchedPosition = hashTable.get(hashCodes[position]); + while (matchedPosition != LIST_END) { + if (buildKeyChunks.getLong(0, matchedPosition) == longValueArray[position - startProbePosition]) { + break; + } + matchedPosition = positionLinks[matchedPosition]; + } + return matchedPosition; + } + + private int matchNext(int current, int position) { + // check null + if (hasNull && nullBitmap.get(position - startProbePosition)) { + return LIST_END; + } + + int matchedPosition = positionLinks[current]; + while (matchedPosition != LIST_END) { + if (buildKeyChunks.getLong(0, matchedPosition) == longValueArray[position - startProbePosition]) { + break; + } + matchedPosition = positionLinks[matchedPosition]; + } + return matchedPosition; + } + + @Override + public void close() { + longValueArray = null; + longValueArray2 = null; + } + + @Override + public int estimateSize() { + return Integer.BYTES * chunkLimit * 4 + Long.BYTES * chunkLimit; + } + } + class ReverseSemiLongProbeOperator implements ProbeOperator { protected final Synchronizer synchronizer; // for hash code. diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/AdaptiveRangeScanClient.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/AdaptiveRangeScanClient.java new file mode 100644 index 000000000..9cdb842a0 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/AdaptiveRangeScanClient.java @@ -0,0 +1,97 @@ +package com.alibaba.polardbx.executor.operator; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.executor.mpp.operator.RangeScanMode; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.CursorMeta; + +/** + * @author yuehan.wcf + */ +public class AdaptiveRangeScanClient extends NormalRangeScanClient { + private final int originPrefetch; + + private final AdaptivePolicy adaptivePolicy; + + public AdaptiveRangeScanClient(ExecutionContext context, CursorMeta meta, + boolean useTransaction, int prefetchNum) { + super(context, meta, useTransaction, 1, RangeScanMode.ADAPTIVE); + this.originPrefetch = prefetchNum; + this.adaptivePolicy = + AdaptivePolicy.getPolicy(context.getParamManager().getString(ConnectionParams.RANGE_SCAN_ADAPTIVE_POLICY)); + } + + /** + * Calculates the next prefetch value. + * This method determines the amount of data to be prefetched based on the current adaptive policy and the existing split index. + * No parameters are accepted. + * + * @return Returns the calculated next prefetch value. The returned value is an integer representing the amount of data to be prefetched. + */ + public int calcNextPrefetch() { + // If using the constant policy, directly return the original prefetch value + if (adaptivePolicy == AdaptivePolicy.CONSTANT) { + return originPrefetch; + } + // Find the next power of two as a potential prefetch value + int nextPrefetch = findNextPowerOfTwo(pushdownSplitIndex.get()); + // Ensure the final prefetch value does not exceed the original prefetch value + return Math.min(nextPrefetch, originPrefetch); + } + + /** + * Finds the next power of two that is greater than or equal to the given number. + * If the input number is less than or equal to 0, returns 1. + * If the number is already a power of two, returns the number itself. + * Otherwise, calculates and returns the next power of two. + * + * @param number The input number. + * @return The next power of two that is greater than or equal to the input number. + */ + private static int findNextPowerOfTwo(int number) { + // If number is less than or equal to 0, the next power of two is 1 + if (number <= 0) { + return 1; + } + // If the number is 2's power, return the number itself. + if ((number & (number - 1)) == 0) { + return number; + } + + // Otherwise, proceed to find the next power of two. + number |= number >> 1; + number |= number >> 2; + number |= number >> 4; + number |= number >> 8; + number |= number >> 16; + return number + 1; + } + + enum AdaptivePolicy { + EXPONENT, + CONSTANT; + + /** + * Retrieves the corresponding adaptive policy based on the provided policy string. + * + * @param policy The policy name, supporting "CONSTANT" and any other value. If "CONSTANT", + * returns the constant policy; otherwise, returns the exponential policy. + * @return The adaptive policy object corresponding to the input. + */ + public static AdaptivePolicy getPolicy(String policy) { + // Returns the exponential policy by default when the policy string is empty. + if (StringUtils.isEmpty(policy)) { + return EXPONENT; + } + // Converts the policy string to uppercase and trims leading/trailing spaces for comparison. + policy = policy.toUpperCase().trim(); + switch (policy) { + case "CONSTANT": + return CONSTANT; + default: + return EXPONENT; + } + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ColumnarDeletedScanExec.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ColumnarDeletedScanExec.java deleted file mode 100644 index e7b19e4b2..000000000 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ColumnarDeletedScanExec.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.executor.operator; - -import com.alibaba.polardbx.common.properties.ConnectionParams; -import com.alibaba.polardbx.executor.gms.ColumnarManager; -import com.alibaba.polardbx.executor.mpp.split.OssSplit; -import com.alibaba.polardbx.executor.operator.scan.impl.DefaultScanPreProcessor; -import com.alibaba.polardbx.executor.operator.scan.impl.DeletedScanPreProcessor; -import com.alibaba.polardbx.optimizer.config.table.TableMeta; -import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.datatype.DataType; -import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileSystem; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -public class ColumnarDeletedScanExec extends ColumnarScanExec { - - public ColumnarDeletedScanExec(OSSTableScan ossTableScan, - ExecutionContext context, - List outputDataTypes) { - super(ossTableScan, context, outputDataTypes); - // TODO: add a validation process to forbid ossTableScan containing filter get here. - } - - @Override - @NotNull - protected DefaultScanPreProcessor getPreProcessor(OssSplit ossSplit, - String logicalSchema, - String logicalTableName, - TableMeta tableMeta, - FileSystem fileSystem, - Configuration configuration, - ColumnarManager columnarManager) { - return new DefaultScanPreProcessor( - configuration, fileSystem, - - // for pruning - logicalSchema, - logicalTableName, - enableIndexPruning, - context.getParamManager().getBoolean(ConnectionParams.ENABLE_OSS_COMPATIBLE), - tableMeta.getAllColumns(), - ossTableScan.getOrcNode().getOriFilters(), - ossSplit.getParams(), - - // for mock - DEFAULT_GROUPS_RATIO, - DEFAULT_DELETION_RATIO, - - // for columnar mode. - columnarManager, - ossSplit.getCheckpointTso(), - tableMeta.getColumnarFieldIdList()); - } -} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ColumnarScanExec.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ColumnarScanExec.java index aa1b39778..7c1cde34b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ColumnarScanExec.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ColumnarScanExec.java @@ -25,7 +25,6 @@ import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.chunk.Chunk; -import com.alibaba.polardbx.executor.ddl.job.task.basic.oss.OSSTaskUtils; import com.alibaba.polardbx.executor.gms.ColumnarManager; import com.alibaba.polardbx.executor.mpp.metadata.Split; import com.alibaba.polardbx.executor.mpp.planner.FragmentRFManager; @@ -41,13 +40,14 @@ import com.alibaba.polardbx.executor.operator.scan.impl.CsvColumnarSplit; import com.alibaba.polardbx.executor.operator.scan.impl.DefaultLazyEvaluator; import com.alibaba.polardbx.executor.operator.scan.impl.DefaultScanPreProcessor; +import com.alibaba.polardbx.executor.operator.scan.impl.FlashbackScanPreProcessor; import com.alibaba.polardbx.executor.operator.scan.impl.MorselColumnarSplit; import com.alibaba.polardbx.executor.operator.scan.impl.SimpleWorkPool; +import com.alibaba.polardbx.executor.operator.scan.impl.SpecifiedDeleteBitmapPreProcessor; import com.alibaba.polardbx.executor.operator.scan.metrics.RuntimeMetrics; import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; import com.alibaba.polardbx.gms.engine.FileSystemManager; import com.alibaba.polardbx.gms.engine.FileSystemUtils; -import com.alibaba.polardbx.optimizer.config.table.FileMeta; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataType; @@ -58,7 +58,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import org.apache.calcite.rex.RexDynamicParam; import org.apache.calcite.rex.RexNode; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; @@ -66,11 +65,11 @@ import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.BitSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.TimeZone; import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -83,7 +82,7 @@ public class ColumnarScanExec extends SourceExec { private static final Logger LOGGER = LoggerFactory.getLogger("oss"); private static final int CPU_CORES = Runtime.getRuntime().availableProcessors(); - private static final ExecutorService IO_EXECUTOR = + protected static final ExecutorService IO_EXECUTOR = Executors.newFixedThreadPool(CPU_CORES * CPU_CORES, new NamedThreadFactory( "columnar-io" )); @@ -92,7 +91,7 @@ public class ColumnarScanExec extends SourceExec { Executors.newFixedThreadPool(CPU_CORES * CPU_CORES, new NamedThreadFactory( "columnar-scan" )); - private static final AtomicLong SNAPSHOT_FILE_ACCESS_COUNT = new AtomicLong(0); + protected static final AtomicLong SNAPSHOT_FILE_ACCESS_COUNT = new AtomicLong(0); public static final double DEFAULT_RATIO = .3D; public static final double DEFAULT_GROUPS_RATIO = 1D; @@ -102,10 +101,10 @@ public class ColumnarScanExec extends SourceExec { private List outputDataTypes; // Shared by all scan operators of one partition in one server node. - private WorkPool workPool; + protected WorkPool workPool; private ExecutorService scanExecutor; - private ScanPreProcessor preProcessor; + protected ScanPreProcessor preProcessor; private ListenableFuture preProcessorFuture; private Supplier> blockedSupplier; @@ -116,7 +115,7 @@ public class ColumnarScanExec extends SourceExec { private volatile boolean lastWorkNotExecutable; private volatile boolean noAvailableWork; private Map> finishedWorks; - private List splitList; + protected List splitList; /** * NOTE: The current IO status does not necessarily come from the current scan work. @@ -140,10 +139,12 @@ public class ColumnarScanExec extends SourceExec { // memory management. private MemoryPool memoryPool; - private MemoryAllocatorCtx memoryAllocator; + protected MemoryAllocatorCtx memoryAllocator; // plan fragment level runtime filter manager. - private volatile FragmentRFManager fragmentRFManager; + protected volatile FragmentRFManager fragmentRFManager; + + protected Set filterSet; public ColumnarScanExec(OSSTableScan ossTableScan, ExecutionContext context, List outputDataTypes) { super(context); @@ -168,59 +169,29 @@ public ColumnarScanExec(OSSTableScan ossTableScan, ExecutionContext context, Lis context.getParamManager().getBoolean(ConnectionParams.ENABLE_COLUMNAR_METRICS); this.enableIndexPruning = context.getParamManager().getBoolean(ConnectionParams.ENABLE_INDEX_PRUNING); - this.enableDebug = LOGGER.isDebugEnabled(); + this.enableDebug = + LOGGER.isDebugEnabled() || context.getParamManager().getBoolean(ConnectionParams.ENABLE_COLUMNAR_DEBUG); this.splitList = new ArrayList<>(); this.memoryPool = MemoryPoolUtils .createOperatorTmpTablePool("ColumnarScanExec@" + System.identityHashCode(this), context.getMemoryPool()); this.memoryAllocator = memoryPool.getMemoryAllocatorCtx(); + + String fileListStr = context.getParamManager().getString(ConnectionParams.FILE_LIST); + if (!"ALL".equalsIgnoreCase(fileListStr)) { + filterSet = Arrays.stream(fileListStr.split(",")) + .map(String::trim) + .collect(Collectors.toSet()); + } } public void setFragmentRFManager(FragmentRFManager fragmentRFManager) { this.fragmentRFManager = fragmentRFManager; } - private List getOrcFiles(OssSplit ossSplit) { - List fileNames = ossSplit.getDesignatedFile(); - - if (fileNames != null && ossTableScan.getFlashback() instanceof RexDynamicParam) { - String timestampString = context.getParams().getCurrentParameter() - .get(((RexDynamicParam) ossTableScan.getFlashback()).getIndex() + 1).getValue().toString(); - TimeZone fromTimeZone; - if (context.getTimeZone() != null) { - fromTimeZone = context.getTimeZone().getTimeZone(); - } else { - fromTimeZone = TimeZone.getDefault(); - } - - long readTs = OSSTaskUtils.getTsFromTimestampWithTimeZone(timestampString, fromTimeZone); - TableMeta tableMeta = context.getSchemaManager(ossSplit.getLogicalSchema()).getTable( - ossSplit.getLogicalTableName()); - Set filterSet = ossSplit.getFilterSet(context); - Map> flatFileMetas = tableMeta.getFlatFileMetas(); - - return ossSplit.getPhyTableNameList().stream() - .map(flatFileMetas::get) - .flatMap(List::stream) - .filter(x -> { - if (filterSet == null || filterSet.contains(x.getFileName())) { - if (readTs < x.getCommitTs()) { - // not committed yet at this ts - return false; - } - // not removed yet at this ts - return x.getRemoveTs() == null || readTs <= x.getRemoveTs(); - } else { - // not designated for this split - return false; - } - }) - .map(FileMeta::getFileName) - .collect(Collectors.toList()); - } else { - return fileNames; - } + protected List getOrcFiles(OssSplit ossSplit) { + return ossSplit.getPrunedOrcFiles(ossTableScan, context); } @Override @@ -311,19 +282,28 @@ public void addSplit(Split split) { final OssSplit.DeltaReadOption deltaReadOption = ossSplit.getDeltaReadOption(); // Build csv split for all csv files in deltaReadOption and fill into work pool. - if (deltaReadOption != null) { + if (deltaReadOption != null && deltaReadOption.getAllCsvFiles() != null) { final Map> allCsvFiles = deltaReadOption.getAllCsvFiles(); + final Map> allPositions = deltaReadOption.getAllPositions(); List finalInputRefsForFilterForCsv = inputRefsForFilter; LazyEvaluator finalEvaluatorForCsv = evaluator; - allCsvFiles.values().stream().flatMap(List::stream).forEach( - csvFile -> { - Path filePath = FileSystemUtils.buildPath(fileSystem, csvFile, isColumnar); + + for (Map.Entry> entry : allCsvFiles.entrySet()) { + List files = entry.getValue(); + List positions = allPositions == null ? null : allPositions.get(entry.getKey()); + for (int i = 0; i < files.size(); i++) { + String fileName = files.get(i); + if (filterSet != null && !filterSet.contains(fileName)) { + continue; + } + Path filePath = FileSystemUtils.buildPath(fileSystem, fileName, isColumnar); preProcessor.addFile(filePath); workPool.addSplit(sequenceId, CsvColumnarSplit.newBuilder() .executionContext(context) .columnarManager(columnarManager) .file(filePath, 0) + .position(positions == null ? null : positions.get(i)) .inputRefs(finalInputRefsForFilterForCsv, inputRefsForProject) .tso(ossSplit.getCheckpointTso()) .prepare(preProcessor) @@ -335,12 +315,15 @@ public void addSplit(Split split) { .build() ); } - ); + } } // Build columnar style split for all orc files in oss-split and fill into work pool. if (orcFileNames != null) { for (String fileName : orcFileNames) { + if (filterSet != null && !filterSet.contains(fileName)) { + continue; + } // The pre-processor shared by all columnar-splits in this table scan. Path filePath = FileSystemUtils.buildPath(fileSystem, fileName, isColumnar); preProcessor.addFile(filePath); @@ -387,27 +370,54 @@ protected DefaultScanPreProcessor getPreProcessor(OssSplit ossSplit, FileSystem fileSystem, Configuration configuration, ColumnarManager columnarManager) { - return new DefaultScanPreProcessor( - configuration, fileSystem, - - // for pruning - logicalSchema, - logicalTableName, - enableIndexPruning, - context.getParamManager().getBoolean(ConnectionParams.ENABLE_OSS_COMPATIBLE), - tableMeta.getAllColumns(), - ossTableScan.getOrcNode().getOriFilters(), - ossSplit.getParams(), - - // for mock - DEFAULT_GROUPS_RATIO, - DEFAULT_DELETION_RATIO, - - // for columnar mode. - columnarManager, - ossSplit.getCheckpointTso(), - tableMeta.getColumnarFieldIdList() - ); + if (ossTableScan.isFlashbackQuery()) { + OssSplit.DeltaReadOption deltaReadOption = ossSplit.getDeltaReadOption(); + + return new FlashbackScanPreProcessor( + configuration, fileSystem, + + // for pruning + logicalSchema, + logicalTableName, + enableIndexPruning, + context.getParamManager().getBoolean(ConnectionParams.ENABLE_OSS_COMPATIBLE), + tableMeta.getAllColumns(), + ossTableScan.getOrcNode().getOriFilters(), + ossSplit.getParams(), + + // for mock + DEFAULT_GROUPS_RATIO, + DEFAULT_DELETION_RATIO, + + // for columnar mode. + columnarManager, + ossSplit.getCheckpointTso(), + tableMeta.getColumnarFieldIdList(), + deltaReadOption == null ? null : deltaReadOption.getAllDelPositions() + ); + } else { + return new DefaultScanPreProcessor( + configuration, fileSystem, + + // for pruning + logicalSchema, + logicalTableName, + enableIndexPruning, + context.getParamManager().getBoolean(ConnectionParams.ENABLE_OSS_COMPATIBLE), + tableMeta.getAllColumns(), + ossTableScan.getOrcNode().getOriFilters(), + ossSplit.getParams(), + + // for mock + DEFAULT_GROUPS_RATIO, + DEFAULT_DELETION_RATIO, + + // for columnar mode. + columnarManager, + ossSplit.getCheckpointTso(), + tableMeta.getColumnarFieldIdList() + ); + } } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ColumnarSpecifiedScanExec.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ColumnarSpecifiedScanExec.java new file mode 100644 index 000000000..d0090e1f9 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ColumnarSpecifiedScanExec.java @@ -0,0 +1,256 @@ +package com.alibaba.polardbx.executor.operator; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.mpp.metadata.Split; +import com.alibaba.polardbx.executor.mpp.split.OssSplit; +import com.alibaba.polardbx.executor.mpp.split.SpecifiedOssSplit; +import com.alibaba.polardbx.executor.operator.scan.BlockCacheManager; +import com.alibaba.polardbx.executor.operator.scan.ColumnarSplit; +import com.alibaba.polardbx.executor.operator.scan.LazyEvaluator; +import com.alibaba.polardbx.executor.operator.scan.impl.DefaultLazyEvaluator; +import com.alibaba.polardbx.executor.operator.scan.impl.DefaultScanPreProcessor; +import com.alibaba.polardbx.executor.operator.scan.impl.SpecifiedCsvColumnarSplit; +import com.alibaba.polardbx.executor.operator.scan.impl.SpecifiedDeleteBitmapPreProcessor; +import com.alibaba.polardbx.executor.operator.scan.impl.SpecifiedOrcColumnarSplit; +import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; +import com.alibaba.polardbx.gms.engine.FileSystemManager; +import com.alibaba.polardbx.gms.engine.FileSystemUtils; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rex.RexNode; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; + +import java.util.BitSet; +import java.util.List; +import java.util.stream.Collectors; + +/** + * This columnar scan exec scans specified orc/csv/del files, + * with specified file position, between specified tso version. + * Do not use any cache. + * + * @author yaozhili + */ +public class ColumnarSpecifiedScanExec extends ColumnarScanExec { + public ColumnarSpecifiedScanExec(OSSTableScan ossTableScan, + ExecutionContext context, + List outputDataTypes) { + super(ossTableScan, context, outputDataTypes); + } + + @Override + public void addSplit(Split split) { + splitList.add(split); + SpecifiedOssSplit ossSplit = (SpecifiedOssSplit) split.getConnectorSplit(); + List orcFileNames = ossSplit.getDesignatedFile(); + final SpecifiedOssSplit.DeltaReadWithPositionOption deltaReadOption = + (SpecifiedOssSplit.DeltaReadWithPositionOption) ossSplit.getDeltaReadOption(); + + // partition info of this split + int partNum = ossSplit.getPartIndex(); + int nodePartCount = ossSplit.getNodePartCount(); + + // base info of table meta. + String logicalSchema = ossSplit.getLogicalSchema(); + String logicalTableName = ossSplit.getLogicalTableName(); + TableMeta tableMeta = context.getSchemaManager(logicalSchema).getTable(logicalTableName); + + // engine and filesystem for files in split. + Engine engine = tableMeta.getEngine(); + FileSystem fileSystem = FileSystemManager.getFileSystemGroup(engine).getMaster(); + + int sequenceId = getSourceId(); + + Configuration configuration = new Configuration(); + + ColumnarManager columnarManager = ColumnarManager.getInstance(); + + // build pre-processor for splits to contain all time-consuming processing + // like pruning, bitmap loading and metadata preheating. + if (preProcessor == null) { + preProcessor = getPreProcessor( + ossSplit, + logicalSchema, + logicalTableName, + tableMeta, + fileSystem, + configuration, + columnarManager + ); + } else if (preProcessor instanceof SpecifiedDeleteBitmapPreProcessor) { + if (null != deltaReadOption && null != deltaReadOption.getDelFiles()) { + ((SpecifiedDeleteBitmapPreProcessor) preProcessor).addDelFiles( + deltaReadOption.getDelFiles(), + deltaReadOption.getDelBeginPos(), + deltaReadOption.getDelEndPos(), + deltaReadOption.getTableId()); + } + } + + // Schema-level cache manager. + BlockCacheManager blockCacheManager = BlockCacheManager.getInstance(); + + // Get the push-down predicate. + // The refs of input-type will be consistent with refs in RexNode. + LazyEvaluator evaluator = null; + List inputRefsForFilter = ImmutableList.of(); + if (!ossTableScan.getOrcNode().getFilters().isEmpty()) { + RexNode rexNode = ossTableScan.getOrcNode().getFilters().get(0); + List> inputTypes = ossTableScan.getOrcNode().getInProjectsDataType(); + + // Build evaluator suitable for columnar scan, with the ratio to decide the evaluation strategy. + evaluator = DefaultLazyEvaluator.builder() + .setRexNode(rexNode) + .setRatio(DEFAULT_RATIO) + .setInputTypes(inputTypes) + .setContext(context) + .build(); + + // Collect input refs for filter (predicate) and project + InputRefTypeChecker inputRefTypeChecker = new InputRefTypeChecker(inputTypes); + rexNode.accept(inputRefTypeChecker); + + // The input-ref-indexes is the list of index of in-projects. + inputRefsForFilter = inputRefTypeChecker.getInputRefIndexes() + .stream() + .map(index -> ossTableScan.getOrcNode().getInProjects().get(index)) + .sorted() + .collect(Collectors.toList()); + } + + // The output projects is the list of index of in-projects. + List inputRefsForProject = ossTableScan.getOrcNode().getOutProjects() + .stream() + .map(index -> ossTableScan.getOrcNode().getInProjects().get(index)) + .sorted() + .collect(Collectors.toList()); + + final int chunkLimit = context.getParamManager().getInt(ConnectionParams.CHUNK_SIZE); + final int morselUnit = context.getParamManager().getInt(ConnectionParams.COLUMNAR_WORK_UNIT); + + boolean generateTsoInfo = context.isCciIncrementalCheck(); + // Build csv split for all csv files in deltaReadOption and fill into work pool. + if (deltaReadOption != null && !context.isReadOrcOnly() && deltaReadOption.getCsvFiles() != null) { + for (int i = 0; i < deltaReadOption.getCsvFiles().size(); i++) { + String fileName = deltaReadOption.getCsvFiles().get(i); + long start = deltaReadOption.getCsvStartPos().get(i); + long end = deltaReadOption.getCsvEndPos().get(i); + Path filePath = FileSystemUtils.buildPath(fileSystem, fileName, true); + ColumnarSplit csvSplit = SpecifiedCsvColumnarSplit.newBuilder() + .executionContext(context) + .columnarManager(columnarManager) + .file(filePath, 0) + .inputRefs(inputRefsForFilter, inputRefsForProject) + .tso(ossSplit.getCheckpointTso()) + .prepare(preProcessor) + .pushDown(evaluator) + .columnTransformer(ossSplit.getColumnTransformer(ossTableScan, context, fileName, generateTsoInfo)) + .partNum(partNum) + .nodePartCount(nodePartCount) + .memoryAllocator(memoryAllocator) + .begin((int) start) + .end((int) end) + .tsoV0(deltaReadOption.getTsoV0()) + .tsoV1(deltaReadOption.getTsoV1()) + .build(); + preProcessor.addFile(filePath); + workPool.addSplit(sequenceId, csvSplit); + } + } + + // Build columnar style split for all orc files in oss-split and fill into work pool. + if (orcFileNames != null && !context.isReadCsvOnly()) { + for (String fileName : orcFileNames) { + // The pre-processor shared by all columnar-splits in this table scan. + Path filePath = FileSystemUtils.buildPath(fileSystem, fileName, true); + preProcessor.addFile(filePath); + + int fileId = 0; + + ColumnarSplit columnarSplit = SpecifiedOrcColumnarSplit.newBuilder() + .executionContext(context) + .ioExecutor(IO_EXECUTOR) + .fileSystem(fileSystem, engine) + .configuration(configuration) + .sequenceId(sequenceId) + .file(filePath, fileId) + .columnTransformer(ossSplit.getColumnTransformer(ossTableScan, context, fileName, generateTsoInfo)) + .inputRefs(inputRefsForFilter, inputRefsForProject) + .cacheManager(blockCacheManager) + .chunkLimit(chunkLimit) + .morselUnit(morselUnit) + .pushDown(evaluator) + .prepare(preProcessor) + .columnarManager(columnarManager) + .isColumnarMode(true) + .tso(ossSplit.getCheckpointTso()) + .partNum(partNum) + .nodePartCount(nodePartCount) + .memoryAllocator(memoryAllocator) + .fragmentRFManager(fragmentRFManager) + .operatorStatistic(statistics) + .tsoV0(deltaReadOption == null ? -1 : deltaReadOption.getTsoV0()) + .tsoV1(deltaReadOption == null ? -1 : deltaReadOption.getTsoV1()) + .build(); + + workPool.addSplit(sequenceId, columnarSplit); + } + SNAPSHOT_FILE_ACCESS_COUNT.getAndAdd(orcFileNames.size()); + } + } + + @Override + protected DefaultScanPreProcessor getPreProcessor(OssSplit ossSplit, + String logicalSchema, + String logicalTableName, + TableMeta tableMeta, + FileSystem fileSystem, + Configuration configuration, + ColumnarManager columnarManager) { + final SpecifiedOssSplit.DeltaReadWithPositionOption deltaReadOption = + (SpecifiedOssSplit.DeltaReadWithPositionOption) ossSplit.getDeltaReadOption(); + List delFiles = null == deltaReadOption ? null : deltaReadOption.getDelFiles(); + List delBeginPos = null == deltaReadOption ? null : deltaReadOption.getDelBeginPos(); + List delEndPos = null == deltaReadOption ? null : deltaReadOption.getDelEndPos(); + long tableId = null == deltaReadOption ? -1 : deltaReadOption.getTableId(); + Engine engine = tableMeta.getEngine(); + return new SpecifiedDeleteBitmapPreProcessor( + configuration, fileSystem, + + // for pruning + logicalSchema, + logicalTableName, + enableIndexPruning, + context.getParamManager().getBoolean(ConnectionParams.ENABLE_OSS_COMPATIBLE), + tableMeta.getAllColumns(), + ossTableScan.getOrcNode().getOriFilters(), + ossSplit.getParams(), + + // for mock + DEFAULT_GROUPS_RATIO, + DEFAULT_DELETION_RATIO, + + // for columnar mode. + columnarManager, + ossSplit.getCheckpointTso(), + tableMeta.getColumnarFieldIdList(), + + // specified delete bitmap + delFiles, + delBeginPos, + delEndPos, + engine, + tableId + ); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/MergeSortWithBufferTableScanClient.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/MergeSortWithBufferTableScanClient.java index b129add33..b6069b7a6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/MergeSortWithBufferTableScanClient.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/MergeSortWithBufferTableScanClient.java @@ -91,7 +91,7 @@ public synchronized void close(SourceExec sourceExec) { } @Override - public SplitResultSet newSplitResultSet(JdbcSplit jdbcSplit) { + public SplitResultSet newSplitResultSet(JdbcSplit jdbcSplit, boolean rangeScan, int splitIndex) { return new BufferSplitResultSet(jdbcSplit, Lists.newArrayList(dataTypeList)); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/NormalRangeScanClient.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/NormalRangeScanClient.java new file mode 100644 index 000000000..68ad24fd7 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/NormalRangeScanClient.java @@ -0,0 +1,69 @@ +package com.alibaba.polardbx.executor.operator; + +import com.alibaba.polardbx.executor.mpp.operator.RangeScanMode; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.CursorMeta; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author yuehan.wcf + */ +public class NormalRangeScanClient extends TableScanClient { + + Map notReadyResultSet = new HashMap<>(); + + AtomicInteger sequence = new AtomicInteger(0); + + public NormalRangeScanClient(ExecutionContext context, CursorMeta meta, + boolean useTransaction, int prefetchNum, RangeScanMode rangeScanMode) { + super(context, meta, useTransaction, prefetchNum, rangeScanMode); + } + + /** + * Adds a split result set to the current object. + * This method checks whether the incoming result set is ready to be added to the ready result sets and, if so, adds it and notifies waiting callers. + * The method is synchronized to handle concurrent access in a multi-threaded environment. + * + * @param splitResultSet The split result set to be added, containing the split index and result data. + */ + @Override + public synchronized void addSplitResultSet(TableScanClient.SplitResultSet splitResultSet) { + boolean resultReady = false; + // Check if the incoming result set is the next expected one; if so, add it to the ready result sets + if (splitResultSet.splitIndex == sequence.get()) { + readyResultSet.add(splitResultSet); + sequence.incrementAndGet(); + resultReady = true; + } else { + // If not the expected result set, place it in the queue of unready result sets awaiting their turn + notReadyResultSet.put(splitResultSet.splitIndex, splitResultSet); + } + // Move all result sets that have reached their sequence from the unready queue to the ready queue + while (notReadyResultSet.containsKey(sequence.get())) { + SplitResultSet result = notReadyResultSet.get(sequence.get()); + readyResultSet.add(result); + notReadyResultSet.remove(sequence.get()); + sequence.incrementAndGet(); + resultReady = true; + } + // If any result sets became ready, notify waiting callers + if (resultReady) { + notifyBlockedCallers(); + } + } + + /** + * Clears the result sets. + * This method resets both the readyResultSet and notReadyResultSet, and initializes the sequence number. + * It is synchronized to ensure safe operations in a multi-threaded environment. + */ + @Override + protected synchronized void clearResultSet() { + readyResultSet.clear(); + notReadyResultSet.clear(); + sequence = new AtomicInteger(0); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/OSSTableScanClient.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/OSSTableScanClient.java index 2234cf84e..4b303cc6b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/OSSTableScanClient.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/OSSTableScanClient.java @@ -33,6 +33,7 @@ import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.chunk.IntegerBlock; +import com.alibaba.polardbx.executor.chunk.LongBlock; import com.alibaba.polardbx.executor.gms.ColumnarManager; import com.alibaba.polardbx.executor.gms.ColumnarStoreUtils; import com.alibaba.polardbx.executor.gms.DynamicColumnarManager; @@ -58,9 +59,11 @@ import org.apache.orc.TypeDescription; import org.apache.orc.UserMetadataUtil; import org.apache.orc.impl.OrcTail; +import org.jetbrains.annotations.VisibleForTesting; import java.io.Closeable; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ArrayBlockingQueue; @@ -148,6 +151,11 @@ public synchronized void executePrefetchThread() { context.getTraceId(), -1, prefetchThread, null, context.getRuntimeStatistics()); } + @VisibleForTesting + public PrefetchThread getPrefetchThread() { + return prefetchThread; + } + public void addSplit(OssSplit split) { this.splits.add(split); } @@ -288,7 +296,7 @@ public void recycle(T element) throws InterruptedException { } } - private class PrefetchThread implements Callable { + class PrefetchThread implements Callable { private volatile boolean isCancelled; PrefetchThread() { @@ -350,38 +358,31 @@ public Object call() { return null; } - private void foreachDeltaFile(String csvFile, long tso, ColumnarManager columnarManager, - List projectColumnIndexes) { - List chunkList = columnarManager.csvData(tso, csvFile); - int chunkIndex = 0; - while (!isCancelled) { + void foreachDeltaFile(String csvFile, long tso, ColumnarManager columnarManager, + List projectColumnIndexes) { + Iterator chunkIterator = columnarManager.csvData(tso, csvFile); + while (!isCancelled && chunkIterator.hasNext()) { try { - if (chunkIndex < chunkList.size()) { - Chunk chunk = chunkList.get(chunkIndex); - - // fill selection array in columnar store mode. - int[] selection = new int[chunk.getPositionCount()]; - IntegerBlock integerBlock = - chunk.getBlock(ColumnarStoreUtils.POSITION_COLUMN_INDEX).cast( - IntegerBlock.class); - int selSize = columnarManager.fillSelection(csvFile, tso, selection, integerBlock); - - // project columns at given index. - Block[] projectBlocks = projectColumnIndexes.stream() - .map(chunk::getBlock).collect(Collectors.toList()).toArray(new Block[0]); - Chunk result = new Chunk(projectBlocks); - - ResultFromOSS resultFromOSS = new ResultFromOSS(result, true); - resultFromOSS.setSelSize(selSize); - resultFromOSS.setSelection(selection); - results.add(resultFromOSS); + Chunk chunk = chunkIterator.next(); - chunkIndex++; - notifyBlockedCallers(); - } else { - // no more chunks - return; - } + // fill selection array in columnar store mode. + int[] selection = new int[chunk.getPositionCount()]; + LongBlock longBlock = + chunk.getBlock(ColumnarStoreUtils.POSITION_COLUMN_INDEX).cast( + LongBlock.class); + int selSize = columnarManager.fillSelection(csvFile, tso, selection, longBlock); + + // project columns at given index. + Block[] projectBlocks = projectColumnIndexes.stream() + .map(chunk::getBlock).collect(Collectors.toList()).toArray(new Block[0]); + Chunk result = new Chunk(projectBlocks); + + ResultFromOSS resultFromOSS = new ResultFromOSS(result, true); + resultFromOSS.setSelSize(selSize); + resultFromOSS.setSelection(selection); + results.add(resultFromOSS); + + notifyBlockedCallers(); } catch (Throwable t) { setException(new TddlRuntimeException(ErrorCode.ERR_EXECUTE_ON_OSS, t, t.getMessage())); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ParallelHashJoinExec.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ParallelHashJoinExec.java index fb6a6e936..963e66971 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ParallelHashJoinExec.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/ParallelHashJoinExec.java @@ -304,27 +304,31 @@ private void buildReverseSemiProbe(Synchronizer synchronizer, boolean isNotNullS } // try matched condition cases - boolean isSemiLongNotEqInteger = joinKeyType == JoinKeyType.LONG; - boolean isSemiIntegerNotEqInteger = joinKeyType == JoinKeyType.INTEGER; + boolean isSemiLongNotEq = joinKeyType == JoinKeyType.LONG; + boolean isSemiIntegerNotEq = joinKeyType == JoinKeyType.INTEGER; int buildChunkConditionIndex = -1; if (!useAntiCondition && isScalarInputRefCondition()) { boolean isNotEq = ((ScalarFunctionExpression) condition).isA(NotEqual.class); - isSemiLongNotEqInteger &= isNotEq; - isSemiIntegerNotEqInteger &= isNotEq; + isSemiLongNotEq &= isNotEq; + isSemiIntegerNotEq &= isNotEq; // since this is outer build (reverse) buildChunkConditionIndex = getBuildChunkConditionIndex(); } else { - isSemiLongNotEqInteger = false; - isSemiIntegerNotEqInteger = false; + isSemiLongNotEq = false; + isSemiIntegerNotEq = false; } - if (useVecJoin && isNotNullSafeJoin && isSemiLongNotEqInteger) { - buildReverseSemiLongNotEqIntProbe(synchronizer, enableVecBuildJoinRow, buildChunkConditionIndex); - return; - } else if (useVecJoin && isNotNullSafeJoin && isSemiIntegerNotEqInteger) { - buildReverseSemiIntNotEqIntProbe(synchronizer, enableVecBuildJoinRow, buildChunkConditionIndex); - return; + if (isSemiLongNotEq || isSemiIntegerNotEq) { + JoinKeyType conditionType = getConditionKeyType((ScalarFunctionExpression) condition); + + if (useVecJoin && isNotNullSafeJoin && isSemiLongNotEq && conditionType == JoinKeyType.INTEGER) { + buildReverseSemiLongNotEqIntProbe(synchronizer, enableVecBuildJoinRow, buildChunkConditionIndex); + return; + } else if (useVecJoin && isNotNullSafeJoin && isSemiIntegerNotEq && conditionType == JoinKeyType.INTEGER) { + buildReverseSemiIntNotEqIntProbe(synchronizer, enableVecBuildJoinRow, buildChunkConditionIndex); + return; + } } // normal cases @@ -659,24 +663,59 @@ private void buildVecSemiAntiProbe(boolean isNotNullSafeJoin, boolean enableVecB return; } + // semi join with condition int buildChunkConditionIndex = -1; - boolean isLongKeyNotEqInteger = joinKeyType == JoinKeyType.LONG; + boolean isLongKeyNotEq = joinKeyType == JoinKeyType.LONG; if (!useAntiCondition && isScalarInputRefCondition()) { - isLongKeyNotEqInteger &= ((ScalarFunctionExpression) condition).isA(NotEqual.class); + isLongKeyNotEq &= ((ScalarFunctionExpression) condition).isA(NotEqual.class); buildChunkConditionIndex = getBuildChunkConditionIndex(); } else { - isLongKeyNotEqInteger = false; + isLongKeyNotEq = false; } - if (joinType == JoinRelType.SEMI && isLongKeyNotEqInteger) { + if (!isLongKeyNotEq || joinType != JoinRelType.SEMI) { + // to be implemented + buildDefaultProbe(); + return; + } + + JoinKeyType conditionKeyType = getConditionKeyType((ScalarFunctionExpression) condition); + + if (conditionKeyType == JoinKeyType.INTEGER) { buildSemiLongNotEqIntProbe(enableVecBuildJoinRow, buildChunkConditionIndex); return; } + if (conditionKeyType == JoinKeyType.LONG) { + buildSemiLongNotEqLongProbe(enableVecBuildJoinRow, buildChunkConditionIndex); + return; + } + // normal cases buildDefaultProbe(); } + protected JoinKeyType getConditionKeyType(ScalarFunctionExpression condition) { + List args = condition.getArgs(); + Preconditions.checkArgument(args.size() == 2, "Join condition arg count should be 2"); + + // get build chunk condition index for TypedHashTable + int idx1 = ((InputRefExpression) args.get(0)).getInputRefIndex(); + int idx2 = ((InputRefExpression) args.get(1)).getInputRefIndex(); + int minIdx = Math.min(idx1, idx2); + int maxIdx = Math.max(idx1, idx2); + + DataType type1 = outerInput.getDataTypes().get(minIdx); + DataType type2 = innerInput.getDataTypes().get(maxIdx - outerInput.getDataTypes().size()); + if (type1 instanceof LongType && type2 instanceof LongType) { + return JoinKeyType.LONG; + } + if (type1 instanceof IntegerType && type2 instanceof IntegerType) { + return JoinKeyType.INTEGER; + } + return JoinKeyType.OTHER; + } + private void buildSemiLongProbe(boolean enableVecBuildJoinRow) { this.probeOperator = new SemiLongProbeOperator(enableVecBuildJoinRow); shared.builderKeyChunks.setTypedHashTable(new TypedListHandle() { @@ -749,6 +788,53 @@ public void consume(Chunk chunk, int sourceIndex) { }); } + private void buildSemiLongNotEqLongProbe(boolean enableVecBuildJoinRow, int buildChunkConditionIndex) { + this.probeOperator = new SemiLongNotEqLongProbeOperator(enableVecBuildJoinRow); + shared.builderChunks.setTypedHashTable(new TypedListHandle() { + private TypedList[] typedLists; + + @Override + public long estimatedSize(int fixedSize) { + return TypedList.LongTypedList.estimatedSizeInBytes(fixedSize); + } + + @Override + public TypedList[] getTypedLists(int fixedSize) { + if (typedLists == null) { + typedLists = new TypedList[] {TypedList.createLong(fixedSize)}; + } + return typedLists; + } + + @Override + public void consume(Chunk chunk, int sourceIndex) { + chunk.getBlock(buildChunkConditionIndex) + .appendTypedHashTable(typedLists[0], sourceIndex, 0, chunk.getPositionCount()); + } + }); + shared.builderKeyChunks.setTypedHashTable(new TypedListHandle() { + private TypedList[] typedLists; + + @Override + public long estimatedSize(int fixedSize) { + return TypedList.LongTypedList.estimatedSizeInBytes(fixedSize); + } + + @Override + public TypedList[] getTypedLists(int fixedSize) { + if (typedLists == null) { + typedLists = new TypedList[] {TypedList.createLong(fixedSize)}; + } + return typedLists; + } + + @Override + public void consume(Chunk chunk, int sourceIndex) { + chunk.getBlock(0).appendTypedHashTable(typedLists[0], sourceIndex, 0, chunk.getPositionCount()); + } + }); + } + @Override public void openConsume() { Preconditions.checkArgument(shared != null, "reopen not supported yet"); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/RangeScanSortExec.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/RangeScanSortExec.java new file mode 100644 index 000000000..5a98d1e87 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/RangeScanSortExec.java @@ -0,0 +1,265 @@ +package com.alibaba.polardbx.executor.operator; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.chunk.BlackHoleBlockBuilder; +import com.alibaba.polardbx.executor.chunk.BlockBuilder; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.mpp.metadata.Split; +import com.alibaba.polardbx.executor.mpp.split.JdbcSplit; +import com.alibaba.polardbx.executor.operator.spill.SpillerFactory; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; +import com.alibaba.polardbx.optimizer.utils.PartitionUtils; +import it.unimi.dsi.fastutil.ints.AbstractIntComparator; +import it.unimi.dsi.fastutil.ints.IntArrays; +import org.apache.calcite.rel.RelCollation; +import org.apache.calcite.rel.RelFieldCollation; +import org.apache.calcite.rel.core.Sort; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static com.alibaba.polardbx.common.exception.code.ErrorCode.ERR_EXECUTE_ON_MYSQL; +import static com.alibaba.polardbx.common.exception.code.ErrorCode.ERR_EXECUTOR; + +public class RangeScanSortExec extends TableScanSortExec { + + public RangeScanSortExec(LogicalView logicalView, ExecutionContext context, TableScanClient scanClient, + long maxRowCount, long skipped, long fetched, SpillerFactory spillerFactory, + List dataTypeList) { + super(logicalView, context, scanClient, maxRowCount, skipped, fetched, spillerFactory, dataTypeList); + } + + @Override + void doOpen() { + checkStatus(); + reorderSplits(); + if (fetched > 0) { + realOpen(); + } + } + + /** + * Reorders splits. This method sorts splits based on the logical table name and schema, + * and then updates the sorted list in the scanClient. + */ + private void reorderSplits() { + List splitList = scanClient.splitList; + String logicalTableName = logicalView.getTableNames().get(0); + String logicalSchema = logicalView.getSchemaName(); + if (!splitList.isEmpty()) { + List partitions = getPhysicalPartitions(splitList, logicalSchema, logicalTableName); + int[] index = sortPartitions(partitions); + List orderedSplits = IntStream.of(index) + .mapToObj(splitList::get).collect(Collectors.toList()); + // Clears the current split list and adds the sorted splits back to the scanClient + scanClient.splitList.clear(); + scanClient.splitList.addAll(orderedSplits); + } + } + + /** + * Checks the scanning status to ensure specific conditions are met. + * This method takes no parameters and returns no value. + * It performs the following checks: + * 1. Ensures there are no more splits to process. + * 2. Confirms that all splits are of type JdbcSplit. + * 3. Verifies that the logical view contains only one table. + * If any check fails, a TddlRuntimeException is thrown. + */ + private void checkStatus() { + // Check if there are no more splits to process + if (!scanClient.noMoreSplit()) { + throw new TddlRuntimeException(ERR_EXECUTE_ON_MYSQL, "RangeScanSortExec input split not ready"); + } + + List splitList = scanClient.splitList; + // Check if all splits are JdbcSplits + boolean allJdbcSplit = splitList.stream().allMatch(split -> split.getConnectorSplit() instanceof JdbcSplit); + if (!allJdbcSplit) { + throw new TddlRuntimeException(ERR_EXECUTOR, "all splits should be jdbc split under range scan mode"); + } + // Check if the logical view contains exactly one table + if (logicalView.getTableNames().size() != 1) { + throw new TddlRuntimeException(ERR_EXECUTOR, + "logical view should contains only one table under range scan mode"); + } + + boolean allSplitHasOnePhyTable = splitList.stream().allMatch(split -> { + JdbcSplit jdbcSplit = (JdbcSplit) split.getConnectorSplit(); + return jdbcSplit.getTableNames().size() == 1 && jdbcSplit.getTableNames().get(0).size() == 1; + }); + if (!allSplitHasOnePhyTable) { + throw new TddlRuntimeException(ERR_EXECUTOR, + "all splits should has one physical table under range scan mode"); + } + } + + /** + * Retrieves physical partition numbers from a list of splits based on the logical schema and table name. + * + * @param splitList A list of split objects. + * @param logicalSchema The logical schema name. + * @param logicalTableName The logical table name. + * @return A list of integer representing the physical partition IDs. + * @throws TddlRuntimeException If no partition information is found in range scan mode. + */ + private static List getPhysicalPartitions(List splitList, String logicalSchema, + String logicalTableName) { + // Convert the splitList to JdbcSplits and extract the physical schema and table names as pairs + List> phySchemaAndPhyTables = + splitList.stream().map(split -> (JdbcSplit) split.getConnectorSplit()) + .map(split -> Pair.of(split.getDbIndex(), split.getTableNames().get(0).get(0))).collect( + Collectors.toList()); + + // Calculate the physical partition numbers using the logical schema, logical table, and extracted pairs, then collect them + List partitions = phySchemaAndPhyTables.stream() + .map(pair -> PartitionUtils.calcPartition(logicalSchema, logicalTableName, pair.getKey(), pair.getValue())) + .collect(Collectors.toList()); + + // Check if any partition was not found, and if so, throw an exception + boolean notFoundPart = partitions.stream().anyMatch(part -> part < 0); + if (notFoundPart) { + throw new TddlRuntimeException(ERR_EXECUTOR, "not found partition info under range scan mode"); + } + return partitions; + } + + /** + * Sorts the given list of partitions. + * + * @param partitions A list of integers representing the partitions to be sorted. + * @return index An array of indices representing the sorted order of the partitions. + */ + private int[] sortPartitions(List partitions) { + int[] index = new int[partitions.size()]; + for (int i = 0; i < index.length; i++) { + index[i] = i; + } + // Obtain sorting information from the logical view + Sort sort = (Sort) logicalView.getOptimizedPushedRelNodeForMetaQuery(); + RelCollation collation = sort.getCollation(); + RelFieldCollation.Direction direction = collation.getFieldCollations().get(0).direction; + // Determine whether the sort order is descending + boolean isDesc = direction.isDescending(); + IntArrays.quickSort(index, new AbstractIntComparator() { + @Override + public int compare(int position1, int position2) { + int part1 = partitions.get(position1); + int part2 = partitions.get(position2); + // Compare according to sort direction + return !isDesc ? part1 - part2 : part2 - part1; + } + }); + return index; + } + + /** + * Fetches a sorted Chunk. + * This method is responsible for retrieving data from the result set and constructing a Chunk to return. If the result set is empty or has been fully iterated, it attempts to fetch a new result set from the scan client. + * If no more data is available, it notifies completion and returns null. + * + * @return Chunk A Chunk containing the fetched data, or null if no data is available. + */ + @Override + protected Chunk fetchSortedChunk() { + // Try to get a data chunk from the current result set. If it's null, attempt to pop a new one from the scan client. + if (consumeResultSet == null) { + consumeResultSet = scanClient.popResultSet(); + // If no result set is available, notify completion and try again. + if (consumeResultSet == null) { + notifyFinish(); + if (consumeResultSet == null) { + return null; + } + } + } + int count = 0; + // Loop until the chunk limit is reached or there is no more data + while (count < chunkLimit && fetched > 0 && !isFinish) { + // If the current result set is exhausted, close it and fetch a new one + if (!consumeResultSet.next()) { + consumeResultSet.close(); + consumeResultSet = scanClient.popResultSet(); + // If no more result sets, notify completion and exit the loop + if (consumeResultSet == null) { + notifyFinish(); + if (consumeResultSet == null) { + break; + } + } + // If the new result set is also empty, continue the loop + if (!consumeResultSet.next()) { + continue; + } + } + try { + // Fill the chunk based on the result set's async mode + if (consumeResultSet.isPureAsyncMode()) { + // Handle skipping a specified number of rows + if (skipped > 0) { + BlockBuilder[] blackHoleBlockBuilders = new BlockBuilder[blockBuilders.length]; + for (int i = 0; i < blockBuilders.length; ++i) { + blackHoleBlockBuilders[i] = new BlackHoleBlockBuilder(); + } + int skip = consumeResultSet.fillChunk(dataTypes, blackHoleBlockBuilders, (int) skipped); + assert skip == blackHoleBlockBuilders[0].getPositionCount(); + skipped -= skip; + // If more rows need to be skipped, continue the loop + if (skipped > 0) { + continue; + } + } + // Fill the chunk up to the limit or until no more data is available + int maxFill = (int) Math.min(chunkLimit - count, fetched); + final int filled = consumeResultSet.fillChunk(dataTypes, blockBuilders, maxFill); + count += filled; + fetched -= filled; + } else { + // Row filling logic for non-pure async mode + if (skipped > 0) { + BlockBuilder[] blackHoleBlockBuilders = new BlockBuilder[blockBuilders.length]; + for (int i = 0; i < blockBuilders.length; ++i) { + blackHoleBlockBuilders[i] = new BlackHoleBlockBuilder(); + } + ResultSetCursorExec.buildOneRow(consumeResultSet.current(), dataTypes, blackHoleBlockBuilders, + context); + skipped -= 1; + // If more rows need to be skipped, continue the loop + if (skipped > 0) { + continue; + } + } + appendRow(consumeResultSet); + count++; + fetched--; + } + // Exit the loop if the fetched data limit is reached + if (fetched <= 0) { + break; + } + } catch (Exception ex) { + TddlRuntimeException exception = + new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, ex, ex.getMessage()); + scanClient.setException(exception); + if (isFinish) { + log.debug(context.getTraceId() + " here occur error, but current scan is closed!", ex); + return null; + } else { + scanClient.throwIfFailed(); + } + } + } + // Return null if no data was fetched; otherwise, build and return the chunk + if (count == 0) { + return null; + } else { + Chunk ret = buildChunkAndReset(); + return ret; + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/SerializeRangeScanClient.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/SerializeRangeScanClient.java new file mode 100644 index 000000000..adbdd5c37 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/SerializeRangeScanClient.java @@ -0,0 +1,16 @@ +package com.alibaba.polardbx.executor.operator; + +import com.alibaba.polardbx.executor.mpp.operator.RangeScanMode; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.CursorMeta; + +/** + * @author yuehan.wcf + */ +public class SerializeRangeScanClient extends TableScanClient { + + public SerializeRangeScanClient(ExecutionContext context, CursorMeta meta, + boolean useTransaction) { + super(context, meta, useTransaction, 1, RangeScanMode.SERIALIZE); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanClient.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanClient.java index 37ef2a91e..7dbcec439 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanClient.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanClient.java @@ -66,6 +66,7 @@ import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; import com.alibaba.polardbx.executor.mpp.metadata.Split; +import com.alibaba.polardbx.executor.mpp.operator.RangeScanMode; import com.alibaba.polardbx.executor.mpp.split.JdbcSplit; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.executor.utils.transaction.PhyOpTrxConnUtils; @@ -150,7 +151,7 @@ public class TableScanClient { protected final boolean useTransaction; protected final boolean enableTaskCpu; protected final CursorMeta meta; - protected final int prefetchNum; + protected volatile int prefetchNum; protected final AtomicInteger noMoreSplitNum = new AtomicInteger(0); protected final AtomicInteger sourceExecNum = new AtomicInteger(0); protected final List splitList = Collections.synchronizedList(new ArrayList<>()); @@ -179,6 +180,8 @@ public class TableScanClient { private boolean killStreaming; private boolean lessMy56Version = false; + private RangeScanMode rangeScanMode; + public TableScanClient(ExecutionContext context, CursorMeta meta, boolean useTransaction, int prefetchNum) { this.context = context; @@ -202,6 +205,12 @@ public TableScanClient(ExecutionContext context, CursorMeta meta, } } + public TableScanClient(ExecutionContext context, CursorMeta meta, + boolean useTransaction, int prefetchNum, RangeScanMode rangeScanMode) { + this(context, meta, useTransaction, prefetchNum); + this.rangeScanMode = rangeScanMode; + } + // Must be called before start public synchronized void initWaitFuture(ListenableFuture> listListenableFuture) { if (this.waitBloomFilterFuture == null) { @@ -279,7 +288,9 @@ public synchronized void executePrefetchThread(boolean force) { if (needFetchNum > 0) { for (int i = 0; i < needFetchNum; i++) { - PrefetchThread thread = new PrefetchThread(splitList.get(pushdownSplitIndex.get())); + int splitIndex = pushdownSplitIndex.get(); + PrefetchThread thread = + new PrefetchThread(splitList.get(splitIndex), rangeScanMode != null, splitIndex); prefetchThreads.add(thread); // Use async X-protocol or original jdbc. if (thread.isPureAsyncMode()) { @@ -387,7 +398,7 @@ public void reset() { cancelAllThreads(true); notifyBlockedCallers(); prefetchThreads.clear(); - readyResultSet.clear(); + clearResultSet(); this.completePrefetchNum.set(0); this.pushdownSplitIndex.set(0); this.completeExecuteNum.set(0); @@ -398,6 +409,14 @@ public void setTargetPlanStatGroup(RuntimeStatistics.OperatorStatisticsGroup tar this.targetPlanStatGroup = targetPlanStatGroup; } + public RangeScanMode getRangeScanMode() { + return rangeScanMode; + } + + public void setPrefetchNum(int prefetchNum) { + this.prefetchNum = prefetchNum; + } + public synchronized void setException(TddlRuntimeException exception) { if (this.exception == null) { this.exception = exception; @@ -436,11 +455,19 @@ public synchronized void close(SourceExec sourceExec) { cancelAllThreads(false); isClosed = true; prefetchThreads.clear(); - readyResultSet.clear(); + clearResultSet(); } notifyBlockedCallers(); } + /** + * Clears the current ResultSet object. + * This method should be synchronized, otherwise the async execute of addSplitResultSet may cause the status incorrect. + */ + synchronized void clearResultSet() { + readyResultSet.clear(); + } + public void cancelAllThreads(boolean ignoreCnt) { if (!prefetchThreads.isEmpty()) { for (PrefetchThread prefetchThread : prefetchThreads) { @@ -450,8 +477,12 @@ public void cancelAllThreads(boolean ignoreCnt) { } - public SplitResultSet newSplitResultSet(JdbcSplit jdbcSplit) { - return new SplitResultSet(jdbcSplit); + public SplitResultSet newSplitResultSet(JdbcSplit jdbcSplit, boolean rangeScan, int splitIndex) { + if (!rangeScan) { + return new SplitResultSet(jdbcSplit); + } else { + return new SplitResultSet(jdbcSplit, splitIndex); + } } public class SplitResultSet { @@ -474,6 +505,8 @@ public class SplitResultSet { protected SettableFuture blockedFuture; protected SettableFuture connectionFuture; + protected int splitIndex; + SplitResultSet(JdbcSplit jdbcSplit) { this.jdbcSplit = jdbcSplit; // Check whether use pure async mode. @@ -483,6 +516,11 @@ public class SplitResultSet { this.pureAsync = isXDatasource && XConnectionManager.getInstance().isEnablePureAsyncMpp(); } + SplitResultSet(JdbcSplit jdbcSplit, int splitIndex) { + this(jdbcSplit); + this.splitIndex = splitIndex; + } + public boolean isPureAsyncMode() { return pureAsync; } @@ -1284,9 +1322,9 @@ public class PrefetchThread implements Callable { AtomicReference timeoutNotify = new AtomicReference<>(null); boolean ignoreCnt; - public PrefetchThread(Split split) { + public PrefetchThread(Split split, boolean rangeScan, int splitIndex) { this.split = (JdbcSplit) split.getConnectorSplit(); - this.resultSet = newSplitResultSet(this.split); + this.resultSet = newSplitResultSet(this.split, rangeScan, splitIndex); } public boolean isPureAsyncMode() { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanExec.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanExec.java index 2570e477f..4abce3c85 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanExec.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanExec.java @@ -30,6 +30,7 @@ import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.mpp.metadata.Split; +import com.alibaba.polardbx.executor.mpp.operator.RangeScanMode; import com.alibaba.polardbx.executor.mpp.split.JdbcSplit; import com.alibaba.polardbx.executor.operator.spill.SpillerFactory; import com.alibaba.polardbx.executor.utils.ExecUtils; @@ -136,11 +137,7 @@ void doOpen() { } if (dataTypes == null) { - List columns = getDataTypes(); - dataTypes = new DataType[columns.size()]; - for (int i = 0; i < columns.size(); i++) { - dataTypes[i] = columns.get(i); - } + createDataTypes(); createBlockBuilders(); } if (scanClient.getSplitNum() != 0) { @@ -159,6 +156,19 @@ void doOpen() { } } + /** + * Creates an array of data types. + * This method first retrieves a list of data types and then constructs a data type array based on the list's size. + * It takes no parameters and returns no value. + */ + void createDataTypes() { + List columns = getDataTypes(); + dataTypes = new DataType[columns.size()]; + for (int i = 0; i < columns.size(); i++) { + dataTypes[i] = columns.get(i); + } + } + @Override Chunk doSourceNextChunk() { long fetchStartNano = System.nanoTime(); @@ -182,6 +192,10 @@ protected void notifyFinish() { isFinish = true; } } else if (scanClient.connectionCount() > 0) { + // under range scan mode, try poll result + if (scanClient.getRangeScanMode() != null) { + consumeResultSet = scanClient.popResultSet(); + } //当前client还有残余连接存在,继续等待吧! } else { consumeResultSet = scanClient.popResultSet(); @@ -191,6 +205,11 @@ protected void notifyFinish() { } } } else { + // update prefetch num under adaptive range scan mode + if (scanClient.getRangeScanMode() == RangeScanMode.ADAPTIVE) { + int nextPrefetch = ((AdaptiveRangeScanClient) scanClient).calcNextPrefetch(); + scanClient.setPrefetchNum(nextPrefetch); + } if (scanClient.connectionCount() > 0) { if (scanClient.beingConnectionCount() > 0) { //存在正在建连的split,这时我们只需要根据prefetch值判断要不要继续下发split diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanSortExec.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanSortExec.java index c736efd2e..a9844be35 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanSortExec.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/TableScanSortExec.java @@ -19,11 +19,15 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.chunk.BlackHoleBlockBuilder; +import com.alibaba.polardbx.executor.chunk.BlockBuilder; import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.chunk.ChunkBuilder; import com.alibaba.polardbx.executor.mpp.metadata.Split; import com.alibaba.polardbx.executor.mpp.operator.WorkProcessor; import com.alibaba.polardbx.executor.mpp.split.JdbcSplit; +import com.alibaba.polardbx.executor.mpp.split.OssSplit; import com.alibaba.polardbx.executor.operator.spill.SpillerFactory; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.executor.utils.OrderByOption; @@ -32,18 +36,23 @@ import com.alibaba.polardbx.optimizer.core.rel.LogicalView; import com.alibaba.polardbx.optimizer.core.row.Row; import com.google.common.collect.Lists; +import it.unimi.dsi.fastutil.ints.AbstractIntComparator; +import it.unimi.dsi.fastutil.ints.IntArrays; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelFieldCollation; import org.apache.calcite.rel.core.Sort; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import static com.alibaba.polardbx.common.exception.code.ErrorCode.ERR_EXECUTE_ON_MYSQL; +import static com.alibaba.polardbx.common.exception.code.ErrorCode.ERR_EXECUTOR; import static com.alibaba.polardbx.executor.mpp.operator.WorkProcessor.mergeSorted; public class TableScanSortExec extends TableScanExec { @@ -80,10 +89,14 @@ void doOpen() { } if (fetched > 0) { - super.doOpen(); + realOpen(); } } + protected void realOpen() { + super.doOpen(); + } + @Override public void addSplit(Split split) { getJdbcByDeletegate(split); @@ -111,6 +124,10 @@ protected Chunk fetchChunk() { return null; } + return fetchSortedChunk(); + } + + protected Chunk fetchSortedChunk() { if (mergeSort) { if (!scanClient.noMorePrefetchSplit()) { return null; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/VectorizedProjectExec.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/VectorizedProjectExec.java index a325a15be..51b319c77 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/VectorizedProjectExec.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/VectorizedProjectExec.java @@ -228,6 +228,7 @@ private void evaluateExpression(int index, Chunk inputChunk) { // compaction by selection array boolean selectionInUse = preAllocatedChunk.isSelectionInUse(); int[] selection = preAllocatedChunk.selection(); + int size = preAllocatedChunk.getPositionCount(); if (selectionInUse && selection != null) { ((RandomAccessBlock) outputBlock).compact(selection); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/lookup/ShardingLookupConditionBuilder.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/lookup/ShardingLookupConditionBuilder.java index 5c07de1ce..f980ea845 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/lookup/ShardingLookupConditionBuilder.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/lookup/ShardingLookupConditionBuilder.java @@ -220,7 +220,7 @@ private Map> buildShardedConditionBySimpleProcessor for (Tuple tuple : joinKeyTuples) { // since p.size() == 1, we can simplify null value condition - Object lookupValue = tuple.get(0); + Object lookupValue = tuple.get(lookupColumnPositions[0]); if (lookupValue == null) { if (isAntiJoin()) { return Collections.emptyMap(); @@ -561,7 +561,7 @@ private Map> buildGeneralShardedCondition( private SqlNode buildCondition(Collection joinKeyTuples) { Iterable lookupKeys = extractLookupKeys(joinKeyTuples); Collection distinctLookupKeys = distinctLookupKeysChunk(lookupKeys); - + // got correct lookup values already if (p.size() == 1) { List flattedValues = distinctLookupKeys.stream() .map(b -> b.get(0)) @@ -577,7 +577,7 @@ private List extractSimpleValues(Iterable chunk) { List values = new ArrayList<>(); // Pick the target values from chunk and convert to row-oriented layout for (Tuple tuple : chunk) { - values.add(tuple.get(0)); + values.add(tuple.get(lookupColumnPositions[0])); } return values; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/ColumnarSplit.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/ColumnarSplit.java index 0efde51b7..8d0f7ba01 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/ColumnarSplit.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/ColumnarSplit.java @@ -24,7 +24,6 @@ import com.alibaba.polardbx.executor.mpp.planner.FragmentRFManager; import com.alibaba.polardbx.executor.mpp.spi.ConnectorSplit; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.memory.MemoryAllocatorCtx; import com.alibaba.polardbx.optimizer.statis.OperatorStatistics; import org.apache.hadoop.conf.Configuration; @@ -107,6 +106,8 @@ interface ColumnarSplitBuilder { ColumnarSplitBuilder tso(Long tso); + ColumnarSplitBuilder position(Long position); + ColumnarSplitBuilder partNum(int partNum); ColumnarSplitBuilder nodePartCount(int nodePartCount); @@ -116,6 +117,22 @@ interface ColumnarSplitBuilder { ColumnarSplitBuilder fragmentRFManager(FragmentRFManager fragmentRFManager); ColumnarSplitBuilder operatorStatistic(OperatorStatistics operatorStatistics); + + default ColumnarSplitBuilder begin(int begin) { + return this; + } + + default ColumnarSplitBuilder end(int end) { + return this; + } + + default ColumnarSplitBuilder tsoV0(long tsoV0) { + return this; + } + + default ColumnarSplitBuilder tsoV1(long tsoV1) { + return this; + } } public enum ColumnarSplitPriority { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/ScanPolicy.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/ScanPolicy.java index 24a5e4add..6d3c118df 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/ScanPolicy.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/ScanPolicy.java @@ -24,9 +24,7 @@ public enum ScanPolicy { FILTER_PRIORITY(2), - MERGE_IO(3), - - DELETED_SCAN(4); + MERGE_IO(3); private final int policyId; @@ -40,8 +38,6 @@ public int getPolicyId() { public static ScanPolicy of(final int policyId) { switch (policyId) { - case 4: - return DELETED_SCAN; case 2: return FILTER_PRIORITY; case 3: diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/AbstractScanWork.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/AbstractScanWork.java index bf5675547..a24fcadbe 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/AbstractScanWork.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/AbstractScanWork.java @@ -16,7 +16,6 @@ package com.alibaba.polardbx.executor.operator.scan.impl; -import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; @@ -394,6 +393,55 @@ protected void mergeIONoCache(List inputRefs, } } + /** + * Not using block cache, do IO and parse for all needed row-groups. + * Read Tso column. + */ + protected void mergeIONoCacheWithTsoColumn(List inputRefs, + boolean[] rowGroupIncluded) { + List columnIds = new ArrayList<>(); + Map rgMatrix = new HashMap<>(); + for (int i = 0; i < inputRefs.size(); i++) { + final Integer columnId = columnTransformer.getLocInOrc(chunkRefMap[inputRefs.get(i)]); + if (columnId == null) { + continue; + } + // No matter whether rows are selected or not, + // We must load the whole column stream at once into memory. + ColumnReader columnReader = rgIterator.getColumnReader(columnId); + if (!columnReader.isOpened()) { + columnIds.add(columnId); + rgMatrix.put(columnId, rowGroupIncluded); + } + } + + // Add TSO column. + ColumnReader tsoColumnReader = rgIterator.getColumnReader(1); + if (!tsoColumnReader.isOpened()) { + columnIds.add(1); + rgMatrix.put(1, rowGroupIncluded); + } + + // Invoke stripe-level IO tasks that has been merged. + StripeLoader stripeLoader = rgIterator.getStripeLoader(); + CompletableFuture> loadFuture = + stripeLoader.load(columnIds, rgMatrix, () -> isIOCanceled.get()); + + for (int i = 0; i < inputRefs.size(); i++) { + final Integer columnId = columnTransformer.getLocInOrc(chunkRefMap[inputRefs.get(i)]); + if (columnId == null) { + continue; + } + ColumnReader columnReader = rgIterator.getColumnReader(columnId); + if (!columnReader.isOpened() && rgMatrix.get(columnId) != null) { + // Open column reader with IO task future. + columnReader.open(loadFuture, false, rgMatrix.get(columnId)); + } + } + // Open TSO column reader. + tsoColumnReader.open(loadFuture, false, rgMatrix.get(1)); + } + protected static boolean[] remove(boolean[] left, boolean[] right) { boolean[] result = new boolean[left.length]; for (int i = 0; i < left.length; i++) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/AsyncStripeLoader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/AsyncStripeLoader.java index 242140446..109ed3863 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/AsyncStripeLoader.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/AsyncStripeLoader.java @@ -55,6 +55,7 @@ import java.text.MessageFormat; import java.util.Arrays; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -232,6 +233,11 @@ public CompletableFuture> load(List columnIds // Column-level parallel data loading is only suitable for columns that size > 2MB in one stripe. // In some cases, we need merge all columns in one IO task. + if (rowGroupBitmaps != null && rowGroupBitmaps.values().stream().allMatch(AsyncStripeLoader::allFalse)) { + // Directly return empty map to avoid opening file. + return CompletableFuture.completedFuture(new HashMap<>()); + } + OrcIndex orcIndex = preheatFileMeta.getOrcIndex( stripeInformation.getStripeId() ); @@ -314,6 +320,12 @@ public CompletableFuture> load(int targetColumnId, boolean[] targetRowGroups, Supplier controller) { Preconditions.checkArgument(isOpened, "The stripe loader has not already been opened"); + + if (allFalse(targetRowGroups)) { + // Directly return empty map to avoid opening file. + return CompletableFuture.completedFuture(new HashMap<>()); + } + // Column-level parallel data loading is only suitable for columns that size > 2MB in one stripe. // In some cases, we need merge all columns in one IO task. @@ -566,4 +578,16 @@ public void close() throws IOException { // nothing should be closed here. } + public static boolean allFalse(boolean[] rowGroupIncluded) { + if (rowGroupIncluded != null) { + for (boolean b : rowGroupIncluded) { + if (b) { + return false; + } + } + return true; + } + return false; + } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/CsvColumnarSplit.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/CsvColumnarSplit.java index e32a596af..980daa181 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/CsvColumnarSplit.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/CsvColumnarSplit.java @@ -44,27 +44,29 @@ import java.util.concurrent.ExecutorService; public class CsvColumnarSplit implements ColumnarSplit { - private final ExecutionContext executionContext; - private final ColumnarManager columnarManager; - private final long tso; - private final Path csvFile; + protected final ExecutionContext executionContext; + protected final ColumnarManager columnarManager; + protected final long tso; + protected final Long position; + protected final Path csvFile; private final int fileId; private final int sequenceId; - private final ScanPreProcessor preProcessor; - private final OSSColumnTransformer columnTransformer; + protected final ScanPreProcessor preProcessor; + protected final OSSColumnTransformer columnTransformer; - private final List inputRefsForFilter; - private final List inputRefsForProject; + protected final List inputRefsForFilter; + protected final List inputRefsForProject; - private CsvScanWork csvScanWork; - private boolean isScanWorkInvoked = false; - private LazyEvaluator lazyEvaluator; + protected CsvScanWork csvScanWork; + protected boolean isScanWorkInvoked = false; + protected LazyEvaluator lazyEvaluator; - private int partNum; + protected int partNum; - private int nodePartCount; + protected int nodePartCount; public CsvColumnarSplit(ExecutionContext executionContext, ColumnarManager columnarManager, long tso, + Long position, Path csvFile, int fileId, int sequenceId, List inputRefsForFilter, List inputRefsForProject, ScanPreProcessor preProcessor, LazyEvaluator lazyEvaluator, @@ -73,6 +75,7 @@ public CsvColumnarSplit(ExecutionContext executionContext, ColumnarManager colum this.executionContext = executionContext; this.columnarManager = columnarManager; this.tso = tso; + this.position = position; this.csvFile = csvFile; this.fileId = fileId; this.sequenceId = sequenceId; @@ -117,7 +120,7 @@ public synchronized ScanWork inputRefsForFilter, List inputRefsForProject, ExecutionContext executionContext, @@ -76,29 +83,35 @@ public CsvScanWork(ColumnarManager columnarManager, long tso, Path csvFile, inputRefsForProject, partNum, nodePartCount, ossColumnTransformer); this.columnarManager = columnarManager; this.tso = tso; + this.position = position; this.csvFile = csvFile; this.useSelection = useSelection; this.enableCompatible = enableCompatible; this.executionContext = executionContext; this.targetTimeZone = TimestampUtils.getTimeZone(executionContext); refList = refSet.stream().sorted().collect(Collectors.toList()); + + this.enableDebug = + LOGGER.isDebugEnabled() || executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_COLUMNAR_DEBUG); } protected void handleNextWork() throws Throwable { - List chunkList; - if (executionContext.isEnableOrcRawTypeBlock()) { - // Special csv scan work for raw orc type. - // Only Long/Double/ByteArray blocks are created. - // Normal query should not get there. - chunkList = columnarManager.rawCsvData(tso, csvFile.getName(), executionContext); + Iterator chunkIterator; + if (position != null) { + // Scan from a specific position, for flashback query + chunkIterator = columnarManager.csvData(csvFile.getName(), position); } else { - chunkList = columnarManager.csvData(tso, csvFile.getName()); + chunkIterator = columnarManager.csvData(tso, csvFile.getName()); } int filterColumns = inputRefsForFilter.size(); boolean skipEvaluation = filterColumns == 0; int totalPositionCnt = 0; - for (Chunk chunk : chunkList) { + int totalChunkCnt = 0; + int actualPositionCnt = 0; + while (chunkIterator.hasNext()) { + Chunk chunk = chunkIterator.next(); if (isCanceled) { break; } @@ -122,22 +135,31 @@ protected void handleNextWork() throws Throwable { // NULL selection means full selection here if (selection == null) { ioStatus.addResult(chunk); + actualPositionCnt += chunk.getPositionCount(); } else if (selection.length > 0) { // rebuild chunk according to project refs. Chunk projectChunk = rebuildProject(chunk, selection, selection.length); ioStatus.addResult(projectChunk); + actualPositionCnt += projectChunk.getPositionCount(); } totalPositionCnt += positionCnt; + totalChunkCnt++; } - logger.debug( - String.format("Csv scan work finished: chunk count: %d, row count: %d, row/chunk: %f", chunkList.size(), - totalPositionCnt, (double) totalPositionCnt / chunkList.size())); + if (enableDebug) { + logger.info( + String.format( + "%s scan work finished: chunk count: %d, scan rows: %d, available rows: %d, row/chunk: %f", + csvFile.getName(), totalChunkCnt, totalPositionCnt, actualPositionCnt, + totalChunkCnt == 0 ? -1 : (double) totalPositionCnt / totalChunkCnt + ) + ); + } ioStatus.finish(); } - private Chunk projectCsvChunk(Chunk chunk) { + protected Chunk projectCsvChunk(Chunk chunk) { Block[] blocks = new Block[refList.size()]; int blockIndex = 0; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DecimalColumnReader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DecimalColumnReader.java index 2393857ad..efdd9a701 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DecimalColumnReader.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DecimalColumnReader.java @@ -429,9 +429,13 @@ private byte[] readDecimalBin(long length) throws IOException { int len = (int) length; byte[] tmp = new byte[len]; byte[] read = new byte[len]; - int num = dataStream.read(read); - if (num < len) { - throw new IOException("Failed to read bytes with length: " + length); + int n = 0; + while (n < len) { + int count = dataStream.read(read, n, len - n); + if (count < 0) { + throw new IOException("Failed to read decimal with length: " + length); + } + n += count; } boolean isUtf8FromLatin1 = MySQLUnicodeUtils.utf8ToLatin1(read, 0, (int) length, tmp); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DefaultLazyEvaluator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DefaultLazyEvaluator.java index 6c93fcaa6..0adc6e6f7 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DefaultLazyEvaluator.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DefaultLazyEvaluator.java @@ -527,7 +527,7 @@ private BitSet handlePartialSelection(int positionCount) { for (int i = 0; i < batchSize; i++) { int j = preSelection[i]; if (longInputArray[j] != 0 && - (nulls == null || !nulls[i])) { + (nulls == null || !nulls[j])) { result.set(j); } } @@ -536,7 +536,7 @@ private BitSet handlePartialSelection(int positionCount) { for (int i = 0; i < batchSize; i++) { int j = preSelection[i]; if (intInputArray[j] != 0 && - (nulls == null || !nulls[i])) { + (nulls == null || !nulls[j])) { result.set(j); } } @@ -627,7 +627,7 @@ private int handlePartialSelection(boolean[] bitmap, int positionCount) { for (int i = 0; i < batchSize; i++) { int j = preSelection[i]; if (longInputArray[j] != 0 && - (nulls == null || !nulls[i])) { + (nulls == null || !nulls[j])) { bitmap[j] = true; selectCount++; } @@ -637,7 +637,7 @@ private int handlePartialSelection(boolean[] bitmap, int positionCount) { for (int i = 0; i < batchSize; i++) { int j = preSelection[i]; if (intInputArray[j] != 0 && - (nulls == null || !nulls[i])) { + (nulls == null || !nulls[j])) { bitmap[j] = true; selectCount++; } @@ -657,22 +657,47 @@ private int handleFullSelection(boolean[] bitmap, int positionCount) { int selectCount = 0; int batchSize = preAllocatedChunk.batchSize(); + boolean selectionInUse = preAllocatedChunk.isSelectionInUse(); if (resultBlock instanceof LongBlock) { long[] longInputArray = ((LongBlock) resultBlock).longArray(); - for (int i = 0; i < batchSize; i++) { - if (longInputArray[i] != 0 && - (nulls == null || !nulls[i])) { - bitmap[i] = true; - selectCount++; + if (selectionInUse) { + int[] sel = preAllocatedChunk.selection(); + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + if (longInputArray[j] != 0 && + (nulls == null || !nulls[j])) { + bitmap[j] = true; + selectCount++; + } + } + } else { + for (int i = 0; i < batchSize; i++) { + if (longInputArray[i] != 0 && + (nulls == null || !nulls[i])) { + bitmap[i] = true; + selectCount++; + } } } } else if (resultBlock instanceof IntegerBlock) { int[] intInputArray = ((IntegerBlock) resultBlock).intArray(); - for (int i = 0; i < batchSize; i++) { - if (intInputArray[i] != 0 && - (nulls == null || !nulls[i])) { - bitmap[i] = true; - selectCount++; + if (selectionInUse) { + int[] sel = preAllocatedChunk.selection(); + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + if (intInputArray[j] != 0 && + (nulls == null || !nulls[j])) { + bitmap[j] = true; + selectCount++; + } + } + } else { + for (int i = 0; i < batchSize; i++) { + if (intInputArray[i] != 0 && + (nulls == null || !nulls[i])) { + bitmap[i] = true; + selectCount++; + } } } } else { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DefaultScanPreProcessor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DefaultScanPreProcessor.java index eb40a20ea..51603d6aa 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DefaultScanPreProcessor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DefaultScanPreProcessor.java @@ -19,10 +19,10 @@ import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.jdbc.Parameters; import com.alibaba.polardbx.common.oss.ColumnarFileType; +import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; -import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; import com.alibaba.polardbx.executor.columnar.pruning.ColumnarPruneManager; import com.alibaba.polardbx.executor.columnar.pruning.data.PruneUtils; import com.alibaba.polardbx.executor.columnar.pruning.index.IndexPruneContext; @@ -71,7 +71,7 @@ public class DefaultScanPreProcessor implements ScanPreProcessor { private static final String PREHEATED_CACHE_NAME = "PREHEATED_CACHE"; - private static final int PREHEATED_CACHE_MAX_ENTRY = 4096; + private static final long PREHEATED_CACHE_MAX_ENTRY = DynamicConfig.getInstance().getPreheatedCacheMaxEntries(); private static final Logger logger = LoggerFactory.getLogger(DefaultScanPreProcessor.class); @@ -160,7 +160,7 @@ public class DefaultScanPreProcessor implements ScanPreProcessor { /** * Mapping from file path to deletion bitmap. */ - private Map deletions; + protected Map deletions; /** * Store the throwable info generated during preparation. @@ -268,7 +268,10 @@ public ListenableFuture prepare(ExecutorService executor, String traceId, Col ColumnarPruneManager.getIndexPruner( filePath, preheat, columns, sortKeys.get(0), columnFieldIdList.stream() - .map(field -> orcIndexesMap.get(field) + 1) + .map(field -> { + Integer orcIndex = orcIndexesMap.get(field); + return orcIndex == null ? null : orcIndex + 1; + }) .collect(Collectors.toList()), enableOssCompatible ); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DeletedScanWork.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DeletedScanWork.java index ca17ab12f..36831ec0f 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DeletedScanWork.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DeletedScanWork.java @@ -36,6 +36,9 @@ import java.util.Map; import java.util.TreeMap; +/** + * This scan work scan return deleted data from orc files. + */ public class DeletedScanWork extends AbstractScanWork { private final boolean activeLoading; @@ -59,7 +62,6 @@ public DeletedScanWork(String workId, @Override protected void handleNextWork() { - // not all row group but those filtered by pruner should be loaded. final boolean[] prunedRowGroupBitmap = rgIterator.rgIncluded(); final int rowGroupCount = prunedRowGroupBitmap.length; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DictionaryJsonColumnReader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DictionaryJsonColumnReader.java index fcdf4149d..2f535f846 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DictionaryJsonColumnReader.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DictionaryJsonColumnReader.java @@ -79,7 +79,7 @@ public void next(RandomAccessBlock randomAccessBlock, int positionCount) throws int dictId = (int) dictIdReader.next(); Slice sliceValue = dictionary.getValue(dictId); sliceOutput.writeBytes(sliceValue); - long length = sliceValue.length(); + long length = sliceValue.toStringUtf8().length(); totalLength += length; offsets[i] = (int) totalLength; nulls[i] = false; @@ -103,7 +103,7 @@ public void next(RandomAccessBlock randomAccessBlock, int positionCount) throws int dictId = (int) dictIdReader.next(); Slice sliceValue = dictionary.getValue(dictId); sliceOutput.writeBytes(sliceValue); - long length = sliceValue.length(); + long length = sliceValue.toStringUtf8().length(); totalLength += length; offsets[i] = (int) totalLength; nulls[i] = false; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectBlobColumnReader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectBlobColumnReader.java index bba6c5cf8..7440db479 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectBlobColumnReader.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectBlobColumnReader.java @@ -454,10 +454,15 @@ public void next(RandomAccessBlock randomAccessBlock, int positionCount) throws } private byte[] readBytes(long length) throws IOException { - byte[] bytes = new byte[(int) length]; - int read = dataStream.read(bytes); - if (read == -1) { - throw new IOException("Failed to read blob with length: " + length); + int len = (int) length; + int n = 0; + byte[] bytes = new byte[len]; + while (n < len) { + int count = dataStream.read(bytes, n, len - n); + if (count < 0) { + throw new IOException("Failed to read blob with length: " + length); + } + n += count; } return bytes; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectEnumColumnReader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectEnumColumnReader.java index 51caec662..78c288c8c 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectEnumColumnReader.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectEnumColumnReader.java @@ -112,6 +112,21 @@ public void next(RandomAccessBlock randomAccessBlock, int positionCount) throws Slice data = sliceOutput.slice(); block.setData(data.toStringUtf8().toCharArray()); + // Replace the offset with string's. + int totalStringLength = 0; + int[] newOffsets = new int[positionCount]; + for (int i = 0; i < positionCount; i++) { + if (!nulls[i]) { + int beginOffset = i > 0 ? offsets[i - 1] : 0; + int endOffset = offsets[i]; + int lengthOfStr = data.slice(beginOffset, endOffset - beginOffset).toStringUtf8().length(); + totalStringLength += lengthOfStr; + newOffsets[i] = totalStringLength; + } + newOffsets[i] = totalStringLength; + } + block.setOffsets(newOffsets); + // metrics if (enableMetrics) { parseTimer.inc(System.nanoTime() - start); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectJsonColumnReader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectJsonColumnReader.java index 0fb5442f7..117c07488 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectJsonColumnReader.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectJsonColumnReader.java @@ -44,17 +44,8 @@ public DirectJsonColumnReader(int columnId, boolean isPrimaryKey, StripeLoader s this.charset = Charset.forName(dataType.getCharsetName().getJavaCharset()); } - private String readJsonString(long length) throws IOException { - byte[] bytes = new byte[(int) length]; - int num = dataStream.read(bytes); - if (num < length) { - throw new IOException("Failed to read string with length: " + length); - } - return new String(bytes, charset); - } - @Override - public void next(RandomAccessBlock randomAccessBlock, int positionCount) throws IOException { + public void next(RandomAccessBlock randomAccessBlock, final int positionCount) throws IOException { Preconditions.checkArgument(isOpened.get()); Preconditions.checkArgument(!openFailed.get()); Preconditions.checkArgument(randomAccessBlock instanceof StringBlock); @@ -121,6 +112,21 @@ public void next(RandomAccessBlock randomAccessBlock, int positionCount) throws Slice data = sliceOutput.slice(); block.setData(data.toStringUtf8().toCharArray()); + // Replace the offset with string's. + int totalStringLength = 0; + int[] newOffsets = new int[positionCount]; + for (int i = 0; i < positionCount; i++) { + if (!nulls[i]) { + int beginOffset = i > 0 ? offsets[i - 1] : 0; + int endOffset = offsets[i]; + int lengthOfStr = data.slice(beginOffset, endOffset - beginOffset).toStringUtf8().length(); + totalStringLength += lengthOfStr; + newOffsets[i] = totalStringLength; + } + newOffsets[i] = totalStringLength; + } + block.setOffsets(newOffsets); + // metrics if (enableMetrics) { parseTimer.inc(System.nanoTime() - start); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectVarcharColumnReader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectVarcharColumnReader.java index 4a9ab6071..d879e0f57 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectVarcharColumnReader.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/DirectVarcharColumnReader.java @@ -461,7 +461,7 @@ public void next(RandomAccessBlock randomAccessBlock, int positionCount) throws } len -= bytesRead; } - Slice data = sliceOutput.slice(); + Slice data = ((DynamicSliceOutput) sliceOutput).copySlice(); block.setData(data); // metrics diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/FlashbackScanPreProcessor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/FlashbackScanPreProcessor.java new file mode 100644 index 000000000..5a69f3bc6 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/FlashbackScanPreProcessor.java @@ -0,0 +1,59 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.gms.FlashbackDeleteBitmapManager; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import org.apache.calcite.rex.RexNode; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.roaringbitmap.RoaringBitmap; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FlashbackScanPreProcessor extends DefaultScanPreProcessor { + + private final Map>> allDelPositions; + /** + * partName -> FlashbackDeleteBitmapManager + */ + private final Map deleteBitmapManagers = new HashMap<>(); + + public FlashbackScanPreProcessor(Configuration configuration, + FileSystem fileSystem, String schemaName, String logicalTableName, + boolean enableIndexPruning, boolean enableOssCompatible, + List columns, + List rexList, + Map params, + double groupsRatio, double deletionRatio, + ColumnarManager columnarManager, Long tso, + List columnFieldIdList, + Map>> allDelPositions) { + super(configuration, fileSystem, schemaName, logicalTableName, enableIndexPruning, enableOssCompatible, columns, + rexList, params, groupsRatio, deletionRatio, columnarManager, tso, columnFieldIdList); + this.allDelPositions = allDelPositions; + } + + @Override + protected RoaringBitmap generateDeletion(Path filePath) { + RoaringBitmap bitmap; + if (tso == null || allDelPositions == null) { + // in archive mode. + bitmap = new RoaringBitmap(); + } else { + // in columnar mode. + FlashbackDeleteBitmapManager deleteBitmapManager = deleteBitmapManagers.computeIfAbsent( + columnarManager.fileMetaOf(filePath.getName()).getPartitionName(), + p -> FlashbackDeleteBitmapManager.getInstance(tso, schemaName, logicalTableName, p, + allDelPositions.get(p)) + ); + bitmap = deleteBitmapManager.getDeleteBitmapOf(filePath.getName()); + } + deletions.put(filePath, bitmap); + return bitmap; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/LogicalRowGroupImpl.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/LogicalRowGroupImpl.java index fbef752a1..fe29d4ea3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/LogicalRowGroupImpl.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/LogicalRowGroupImpl.java @@ -234,6 +234,11 @@ public Chunk nextBatch() { encoding, columnReader, cacheReader, blockCacheManager, context, useBlockCache, enableColumnReaderLock, chunkLimit, loadTimer, memoryCounter, onlyCachePrimaryKey, enableSkipCompression); + } else if (context.isCciIncrementalCheck()) { + loader = new NoCacheBlockLoader(logicalRowGroup, colId, currentPosition, chunkRows, + encoding, columnReader, cacheReader, blockCacheManager, context, useBlockCache, + enableColumnReaderLock, chunkLimit, loadTimer, memoryCounter, + onlyCachePrimaryKey, enableSkipCompression); } else { // build block loader for specify position range. loader = new ReactiveBlockLoader(logicalRowGroup, colId, currentPosition, chunkRows, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/MorselColumnarSplit.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/MorselColumnarSplit.java index 90580d2ac..db1106199 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/MorselColumnarSplit.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/MorselColumnarSplit.java @@ -38,9 +38,7 @@ import com.alibaba.polardbx.executor.operator.scan.metrics.ProfileAccumulatorType; import com.alibaba.polardbx.executor.operator.scan.metrics.ProfileUnit; import com.alibaba.polardbx.executor.operator.scan.metrics.RuntimeMetrics; -import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.memory.MemoryAllocatorCtx; import com.alibaba.polardbx.optimizer.statis.OperatorStatistics; import com.google.common.base.Preconditions; @@ -75,12 +73,12 @@ * A columnar split responsible for morsel-driven scheduling. */ public class MorselColumnarSplit implements ColumnarSplit { - private final ExecutionContext executionContext; + protected final ExecutionContext executionContext; /** * Executor service for IO tasks. */ - private final ExecutorService ioExecutor; + protected final ExecutorService ioExecutor; /** * Engine of filesystem. @@ -90,12 +88,12 @@ public class MorselColumnarSplit implements ColumnarSplit { /** * Filesystem for storing columnar files. */ - private final FileSystem fileSystem; + protected final FileSystem fileSystem; /** * Hadoop-style configuration. */ - private final Configuration configuration; + protected final Configuration configuration; /** * Unique sequence id for Driver-level identification. @@ -110,51 +108,51 @@ public class MorselColumnarSplit implements ColumnarSplit { /** * File path with uri about filesystem. */ - private final Path filePath; + protected final Path filePath; - private final OSSColumnTransformer ossColumnTransformer; + protected final OSSColumnTransformer ossColumnTransformer; /** * The column ids of primary keys in the file. * It may be null. */ - private final int[] primaryKeyColIds; + protected final int[] primaryKeyColIds; /** * Subset of columns in this file. */ - private List inputRefsForFilter; - private List inputRefsForProject; + protected List inputRefsForFilter; + protected List inputRefsForProject; /** * The limit of chunk rows fetched from columnar files. */ - private final int chunkLimit; + protected final int chunkLimit; /** * Global block cache manager. */ - private final BlockCacheManager blockCacheManager; + protected final BlockCacheManager blockCacheManager; /** * The threshold of row-group count in one morsel-unit. */ private final int rgThreshold; - private final LazyEvaluator lazyEvaluator; + protected final LazyEvaluator lazyEvaluator; - private final ScanPreProcessor preProcessor; + protected final ScanPreProcessor preProcessor; /** * Inner iterator to get the next scan work. */ - private ScanWorkIterator scanWorkIterator; + protected ScanWorkIterator scanWorkIterator; - private int partNum; + protected int partNum; - private int nodePartCount; + protected int nodePartCount; - private final MemoryAllocatorCtx memoryAllocatorCtx; + protected final MemoryAllocatorCtx memoryAllocatorCtx; private final FragmentRFManager fragmentRFManager; private final Map rfFilterRefInFileMap; @@ -285,16 +283,16 @@ class ScanWorkIterator implements Iterator> { // start from 0 private int rowGroupIndex; - private ScanRange currentRange; + protected ScanRange currentRange; - private int scanWorkIndex; + protected int scanWorkIndex; /*================== Come from pre-processor ====================*/ /** * Preheated file meta from columnar file. */ - private PreheatFileMeta preheatFileMeta; + protected PreheatFileMeta preheatFileMeta; /** * Selected stripe ids. @@ -304,7 +302,7 @@ class ScanWorkIterator implements Iterator> { /** * The start row id of each stripe. */ - private Map startRowInStripeMap; + protected Map startRowInStripeMap; /** * Filtered row-group bitmaps for each stripe. @@ -314,29 +312,29 @@ class ScanWorkIterator implements Iterator> { /** * File-level deletion bitmap. */ - private final RoaringBitmap deletion; + protected final RoaringBitmap deletion; /*================== Come from parameter collection ====================*/ // parsed from file meta and reused by all scan work. - private SortedMap stripeInformationMap; - private int compressionSize; - private CompressionKind compressionKind; - private TypeDescription fileSchema; - private boolean[] columnIncluded; - private OrcFile.WriterVersion version; - private ReaderEncryption encryption; + protected SortedMap stripeInformationMap; + protected int compressionSize; + protected CompressionKind compressionKind; + protected TypeDescription fileSchema; + protected boolean[] columnIncluded; + protected OrcFile.WriterVersion version; + protected ReaderEncryption encryption; /** * Mapping from stripeId to column-encoding info. */ - private SortedMap encodingMap; - private boolean ignoreNonUtf8BloomFilter; - private long maxBufferSize; - private int indexStride; - private boolean enableDecimal64; - private int maxDiskRangeChunkLimit; - private long maxMergeDistance; + protected SortedMap encodingMap; + protected boolean ignoreNonUtf8BloomFilter; + protected long maxBufferSize; + protected int indexStride; + protected boolean enableDecimal64; + protected int maxDiskRangeChunkLimit; + protected long maxMergeDistance; ScanWorkIterator() throws IOException { // load from pre-processor. @@ -445,7 +443,7 @@ public boolean hasNext() { } // Try to get the next stripe when row-group index is out of bound. - if (++stripeListIndex < stripeIds.size()) { + while (++stripeListIndex < stripeIds.size()) { rowGroupIndex = 0; if (moveRowGroupIndex()) { return true; @@ -533,11 +531,6 @@ public ScanWork next() { memoryAllocatorCtx); ScanPolicy scanPolicy = ScanPolicy.of(scanPolicyId); - if (executionContext.isEnableOrcDeletedScan()) { - // Special path for check cci consistency. - // Normal oss read should not get here. - scanPolicy = ScanPolicy.DELETED_SCAN; - } ScanWork scanWork; switch (scanPolicy) { @@ -578,17 +571,6 @@ public ScanWork next() { enableCancelLoading, ossColumnTransformer); break; - case DELETED_SCAN: - scanWork = new DeletedScanWork( - scanWorkId, - metrics, - enableMetrics, - lazyEvaluator, - rowGroupIterator, deletion, - currentRange, inputRefsForFilter, inputRefsForProject, - partNum, nodePartCount, - activeLoading, ossColumnTransformer); - break; default: throw new UnsupportedOperationException(); } @@ -683,7 +665,7 @@ public int getFileId() { return fileId; } - private static String generateScanWorkId(String traceId, String file, int stripeId, int workIndex) { + protected static String generateScanWorkId(String traceId, String file, int stripeId, int workIndex) { return new StringBuilder() .append("ScanWork$") .append(traceId).append('$') @@ -880,6 +862,11 @@ public ColumnarSplitBuilder tso(Long tso) { return this; } + @Override + public ColumnarSplitBuilder position(Long position) { + return this; + } + @Override public ColumnarSplitBuilder partNum(int partNum) { this.partNum = partNum; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/NoCacheBlockLoader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/NoCacheBlockLoader.java new file mode 100644 index 000000000..b94365a75 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/NoCacheBlockLoader.java @@ -0,0 +1,55 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.executor.chunk.AbstractBlock; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.operator.scan.BlockCacheManager; +import com.alibaba.polardbx.executor.operator.scan.CacheReader; +import com.alibaba.polardbx.executor.operator.scan.ColumnReader; +import com.alibaba.polardbx.executor.operator.scan.LogicalRowGroup; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.codahale.metrics.Counter; +import org.apache.orc.ColumnStatistics; +import org.apache.orc.OrcProto; + +import java.io.IOException; + +/** + * This block loader never uses block cache. + */ +public class NoCacheBlockLoader extends ReactiveBlockLoader { + public NoCacheBlockLoader( + LogicalRowGroup logicalRowGroup, + int columnId, int startPosition, int positionCount, OrcProto.ColumnEncoding encoding, + ColumnReader columnReader, + CacheReader cacheReader, + BlockCacheManager blockCacheManager, + ExecutionContext context, boolean useBlockCache, + boolean enableColumnReaderLock, int chunkLimit, Counter loadTimer, + Counter memoryCounter, boolean onlyCachePrimaryKey, boolean enableSkipCompression) { + super(logicalRowGroup, columnId, startPosition, positionCount, encoding, columnReader, cacheReader, + blockCacheManager, context, useBlockCache, enableColumnReaderLock, chunkLimit, loadTimer, memoryCounter, + onlyCachePrimaryKey, enableSkipCompression); + } + + @Override + public Block load(DataType dataType, int[] selection, int selSize) throws IOException { + // In this case, we need to proactively open column-reader before this method. + if (!columnReader.isOpened()) { + throw GeneralUtil.nestedException("column reader has not already been opened."); + } + + long start = System.nanoTime(); + Block block = parseBlock(dataType, selection, selSize); + block.cast(AbstractBlock.class).updateSizeInfo(); + if (memoryCounter != null) { + memoryCounter.inc(block.estimateSize()); + } + + if (loadTimer != null) { + loadTimer.inc(System.nanoTime() - start); + } + return block; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/OrcRawTypeBlockLoader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/OrcRawTypeBlockLoader.java index 9c348c25f..0932e3192 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/OrcRawTypeBlockLoader.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/OrcRawTypeBlockLoader.java @@ -90,7 +90,8 @@ public Block load(DataType dataType, int[] selection, int selSize) throws IOExce return block; } - private Block parseBlock(DataType dataType, int[] selection, int selSize) throws IOException { + @Override + protected Block parseBlock(DataType dataType, int[] selection, int selSize) throws IOException { Block targetBlock = allocateBlock(dataType); // Start decoding from given position. diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/PreheatFileMeta.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/PreheatFileMeta.java index 1a2a2dc44..1f4ec9d95 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/PreheatFileMeta.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/PreheatFileMeta.java @@ -16,7 +16,7 @@ package com.alibaba.polardbx.executor.operator.scan.impl; -import org.apache.arrow.util.Preconditions; +import com.google.common.base.Preconditions; import org.apache.hadoop.fs.Path; import org.apache.orc.OrcProto; import org.apache.orc.impl.OrcIndex; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/RFLazyEvaluator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/RFLazyEvaluator.java index a7e446d71..6a8967564 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/RFLazyEvaluator.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/RFLazyEvaluator.java @@ -99,7 +99,8 @@ public int eval(Chunk chunk, int startPosition, int positionCount, RoaringBitmap } final int totalPartitionCount = manager.getTotalPartitionCount(); - int selectedCount = chunk.getPositionCount(); + final int initialSelectedCount = chunk.getPositionCount() - (int) cardinality; + int selectedCount = initialSelectedCount; for (int i = 0; i < itemSize; i++) { FragmentRFItem item = items[i]; int filterChannel = item.getSourceFilterChannel(); @@ -143,7 +144,7 @@ public int eval(Chunk chunk, int startPosition, int positionCount, RoaringBitmap } // statistics for filtered rows by runtime filter. - operatorStatistics.addRuntimeFilteredCount(chunk.getPositionCount() - selectedCount); + operatorStatistics.addRuntimeFilteredCount(initialSelectedCount - selectedCount); return selectedCount; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/ReactiveBlockLoader.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/ReactiveBlockLoader.java index 59676dd01..5c5411d31 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/ReactiveBlockLoader.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/ReactiveBlockLoader.java @@ -204,7 +204,7 @@ public Block load(DataType dataType, int[] selection, int selSize) throws IOExce } } - private Block parseBlock(DataType dataType, int[] selection, int selSize) throws IOException { + protected Block parseBlock(DataType dataType, int[] selection, int selSize) throws IOException { boolean compatible = context.isEnableOssCompatible(); Block targetBlock = allocateBlock(dataType, compatible, timeZone); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/RowGroupIteratorImpl.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/RowGroupIteratorImpl.java index d35aae9e9..7e1950123 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/RowGroupIteratorImpl.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/RowGroupIteratorImpl.java @@ -60,7 +60,7 @@ public class RowGroupIteratorImpl implements RowGroupIterator blockCacheManager; - private final OSSColumnTransformer ossColumnTransformer; - private final ExecutionContext context; + protected final boolean[] columnIncluded; + protected final int chunkLimit; + protected final BlockCacheManager blockCacheManager; + protected final OSSColumnTransformer ossColumnTransformer; + protected final ExecutionContext context; private final boolean enableMetrics; private final boolean enableDecimal64; private final int maxDiskRangeChunkLimit; @@ -113,21 +113,21 @@ public class RowGroupIteratorImpl implements RowGroupIterator columnReaders; + protected Map columnReaders; /** * The Mapping from columnId to cache-reader. */ - private Map> cacheReaders; + protected Map> cacheReaders; /** * The current effective group id. */ - private int currentGroupId; + protected int currentGroupId; private int nextGroupId; /** * The fetched row group count must be less than or equal to effectiveGroupCount. @@ -136,7 +136,7 @@ public class RowGroupIteratorImpl implements RowGroupIterator> rowGroupMap; + protected Map> rowGroupMap; public RowGroupIteratorImpl( RuntimeMetrics metrics, @@ -732,7 +732,7 @@ private void generateOrcRawTypeColumnReader(boolean enableMetrics, int colId, Or } } - private int getRowCount(int groupId) { + protected int getRowCount(int groupId) { final long rowsInStripe = stripeInformation.getNumberOfRows(); int groupsInStripe = (int) ((rowsInStripe + indexStride - 1) / indexStride); @@ -743,7 +743,7 @@ private int getRowCount(int groupId) { } } - private int startRowId(int groupId) { + protected int startRowId(int groupId) { return (int) (groupId * indexStride + startRowOfStripe); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SimpleBlockCacheManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SimpleBlockCacheManager.java index d15393efe..3b6c4077c 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SimpleBlockCacheManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SimpleBlockCacheManager.java @@ -109,7 +109,6 @@ public SimpleBlockCacheManager() { .maximumSize(MAXIMUM_IN_FLIGHT_ENTRIES) .removalListener((RemovalListener) (longValue, blockCache, removalCause) -> { // decrement memory size when invalidate block cache. - size.getAndAdd(-(LONG_OBJECT_IN_BYTES + blockCache.memorySize())); }) .expireAfterWrite(IN_FLIGHT_CACHE_TTL_IN_SECOND, TimeUnit.SECONDS) .build(new CacheLoader() { @@ -118,7 +117,6 @@ public BlockCache load(Long key) { // calculate memory size of block cache and cache key BlockCache result = new BlockCache(); - size.getAndAdd(result.memorySize() + LONG_OBJECT_IN_BYTES); return result; } }); @@ -451,7 +449,6 @@ public void putCache(Block block, int chunkLimit, int totalRows, Path path, int // Try to put block into block cache. It will strictly check the alignment and validity of block. boolean completed = inFlight.put(block, totalRows, position, rows, chunkLimit); - size.addAndGet(block.getElementUsedBytes()); // move the block-cache from in-flight cache into valid cache. if (completed) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedCsvColumnarSplit.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedCsvColumnarSplit.java new file mode 100644 index 000000000..5e7c0d791 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedCsvColumnarSplit.java @@ -0,0 +1,299 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.mpp.planner.FragmentRFManager; +import com.alibaba.polardbx.executor.operator.scan.BlockCacheManager; +import com.alibaba.polardbx.executor.operator.scan.ColumnarSplit; +import com.alibaba.polardbx.executor.operator.scan.LazyEvaluator; +import com.alibaba.polardbx.executor.operator.scan.ScanPreProcessor; +import com.alibaba.polardbx.executor.operator.scan.ScanWork; +import com.alibaba.polardbx.executor.operator.scan.metrics.RuntimeMetrics; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.memory.MemoryAllocatorCtx; +import com.alibaba.polardbx.optimizer.statis.OperatorStatistics; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; + +import java.util.BitSet; +import java.util.List; +import java.util.concurrent.ExecutorService; + +/** + * This csv split contain a csv file with specified start and end positions, + * and with specified delete bitmap. + * + * @author yaozhili + */ +public class SpecifiedCsvColumnarSplit extends CsvColumnarSplit { + final private int begin; + final private int end; + + final private long tsoV0; + + final private long tsoV1; + + public SpecifiedCsvColumnarSplit(ExecutionContext executionContext, + ColumnarManager columnarManager, long tso, + Path csvFile, int fileId, int sequenceId, + List inputRefsForFilter, + List inputRefsForProject, + ScanPreProcessor preProcessor, + LazyEvaluator lazyEvaluator, + int partNum, int nodePartCount, + OSSColumnTransformer columnTransformer, + int begin, int end, long tsoV0, long tsoV1) { + super(executionContext, columnarManager, tso, null, csvFile, fileId, sequenceId, inputRefsForFilter, + inputRefsForProject, preProcessor, lazyEvaluator, partNum, nodePartCount, columnTransformer); + this.begin = begin; + this.end = end; + this.tsoV0 = tsoV0; + this.tsoV1 = tsoV1; + } + + @Override + public synchronized ScanWork nextWork() { + if (isScanWorkInvoked) { + return null; + } + + if (!preProcessor.isPrepared()) { + GeneralUtil.nestedException("The pre-processor is not prepared"); + } + String scanWorkId = generateScanWorkId(executionContext.getTraceId(), csvFile.toString(), 0); + boolean enableMetrics = executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_COLUMNAR_METRICS); + boolean useSelection = executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_COLUMNAR_SCAN_SELECTION); + boolean enableCompatible = executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_OSS_COMPATIBLE); + RuntimeMetrics metrics = RuntimeMetrics.create(scanWorkId); + csvScanWork = new SpecifiedCsvScanWork(columnarManager, tso, csvFile, inputRefsForFilter, inputRefsForProject, + executionContext, scanWorkId, metrics, enableMetrics, lazyEvaluator, preProcessor.getDeletion(csvFile), + partNum, nodePartCount, useSelection, enableCompatible, columnTransformer, begin, end, tsoV0, tsoV1); + isScanWorkInvoked = true; + return (ScanWork) csvScanWork; + } + + public static ColumnarSplitBuilder newBuilder() { + return new SpecifiedCsvColumnarSplit.SpecifiedCsvColumnarSplitBuilder(); + } + + static class SpecifiedCsvColumnarSplitBuilder implements ColumnarSplitBuilder { + protected ExecutionContext executionContext; + protected ColumnarManager columnarManager; + protected OSSColumnTransformer columnTransformer; + protected String logicalSchema; + protected String logicalTable; + protected Long tso; + protected Path csvFile; + protected int fileId; + protected int sequenceId; + protected LazyEvaluator lazyEvaluator; + + protected List inputRefsForFilter; + protected List inputRefsForProject; + protected ScanPreProcessor preProcessor; + + protected int partNum; + + protected int nodePartCount; + protected MemoryAllocatorCtx memoryAllocatorCtx; + + protected FragmentRFManager fragmentRFManager; + protected OperatorStatistics operatorStatistics; + + private int begin; + private int end; + + private long tsoV0; + + private long tsoV1; + + @Override + public ColumnarSplit build() { + return new SpecifiedCsvColumnarSplit( + executionContext, + columnarManager, + tso, + csvFile, + fileId, + sequenceId, + inputRefsForFilter, + inputRefsForProject, + preProcessor, + lazyEvaluator, + partNum, + nodePartCount, + columnTransformer, + begin, + end, + tsoV0, + tsoV1); + } + + @Override + public ColumnarSplitBuilder executionContext(ExecutionContext context) { + this.executionContext = context; + return this; + } + + @Override + public ColumnarSplitBuilder columnarManager(ColumnarManager columnarManager) { + this.columnarManager = columnarManager; + return this; + } + + @Override + public ColumnarSplitBuilder isColumnarMode(boolean isColumnarMode) { + // do nothing because the csv split is always in columnar mode. + return this; + } + + @Override + public ColumnarSplitBuilder tso(Long tso) { + this.tso = tso; + return this; + } + + @Override + public ColumnarSplitBuilder position(Long position) { + return this; + } + + @Override + public ColumnarSplitBuilder ioExecutor(ExecutorService ioExecutor) { + return this; + } + + @Override + public ColumnarSplitBuilder fileSystem(FileSystem fileSystem, Engine engine) { + return this; + } + + @Override + public ColumnarSplitBuilder configuration(Configuration configuration) { + return this; + } + + @Override + public ColumnarSplitBuilder sequenceId(int sequenceId) { + this.sequenceId = sequenceId; + return this; + } + + @Override + public ColumnarSplitBuilder file(Path filePath, int fileId) { + this.csvFile = filePath; + this.fileId = fileId; + return this; + } + + @Override + public ColumnarSplitBuilder tableMeta(String logicalSchema, String logicalTable) { + this.logicalSchema = logicalSchema; + this.logicalTable = logicalTable; + return this; + } + + @Override + public ColumnarSplitBuilder columnTransformer(OSSColumnTransformer ossColumnTransformer) { + this.columnTransformer = ossColumnTransformer; + return this; + } + + @Override + public ColumnarSplitBuilder inputRefs(List inputRefsForFilter, List inputRefsForProject) { + this.inputRefsForFilter = inputRefsForFilter; + this.inputRefsForProject = inputRefsForProject; + return this; + } + + @Override + public ColumnarSplitBuilder cacheManager(BlockCacheManager blockCacheManager) { + return this; + } + + @Override + public ColumnarSplitBuilder chunkLimit(int chunkLimit) { + return this; + } + + @Override + public ColumnarSplitBuilder morselUnit(int rgThreshold) { + return this; + } + + @Override + public ColumnarSplitBuilder pushDown(LazyEvaluator lazyEvaluator) { + this.lazyEvaluator = lazyEvaluator; + return this; + } + + @Override + public ColumnarSplitBuilder prepare(ScanPreProcessor scanPreProcessor) { + this.preProcessor = scanPreProcessor; + return this; + } + + @Override + public ColumnarSplitBuilder partNum(int partNum) { + this.partNum = partNum; + return this; + } + + @Override + public ColumnarSplitBuilder nodePartCount(int nodePartCount) { + this.nodePartCount = nodePartCount; + return this; + } + + @Override + public ColumnarSplitBuilder memoryAllocator(MemoryAllocatorCtx memoryAllocatorCtx) { + this.memoryAllocatorCtx = memoryAllocatorCtx; + return this; + } + + @Override + public ColumnarSplitBuilder fragmentRFManager(FragmentRFManager fragmentRFManager) { + this.fragmentRFManager = fragmentRFManager; + return this; + } + + @Override + public ColumnarSplitBuilder operatorStatistic(OperatorStatistics operatorStatistics) { + this.operatorStatistics = operatorStatistics; + return this; + } + + @Override + public ColumnarSplitBuilder begin(int begin) { + this.begin = begin; + return this; + } + + @Override + public ColumnarSplitBuilder end(int end) { + this.end = end; + return this; + } + + @Override + public ColumnarSplitBuilder tsoV0(long tsoV0) { + this.tsoV0 = tsoV0; + return this; + } + + @Override + public ColumnarSplitBuilder tsoV1(long tsoV1) { + this.tsoV1 = tsoV1; + return this; + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedCsvScanWork.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedCsvScanWork.java new file mode 100644 index 000000000..ed618dad2 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedCsvScanWork.java @@ -0,0 +1,151 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.gms.MultiVersionCsvData; +import com.alibaba.polardbx.executor.operator.scan.LazyEvaluator; +import com.alibaba.polardbx.executor.operator.scan.metrics.RuntimeMetrics; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.apache.hadoop.fs.Path; +import org.roaringbitmap.RoaringBitmap; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Iterator; +import java.util.List; + +/** + * This csv scan work scan csv data of specified start and end positions, + * and with specified delete bitmap. + * + * @author wuzhe + */ +public class SpecifiedCsvScanWork extends CsvScanWork { + private static final Logger logger = LoggerFactory.getLogger("COLUMNAR_TRANS"); + + final private int start; + final private int end; + + final private long tsoV0; + + final private long tsoV1; + + public SpecifiedCsvScanWork(ColumnarManager columnarManager, long tso, + Path csvFile, List inputRefsForFilter, + List inputRefsForProject, + ExecutionContext executionContext, String workId, + RuntimeMetrics metrics, + boolean enableMetrics, + LazyEvaluator lazyEvaluator, + RoaringBitmap deletion, int partNum, int nodePartCount, + boolean useSelection, boolean enableCompatible, + OSSColumnTransformer ossColumnTransformer, + int start, int end, long tsoV0, long tsoV1) { + super(columnarManager, tso, null, csvFile, inputRefsForFilter, inputRefsForProject, executionContext, workId, + metrics, + enableMetrics, lazyEvaluator, deletion, partNum, nodePartCount, useSelection, enableCompatible, + ossColumnTransformer); + this.start = start; + this.end = end; + this.tsoV0 = tsoV0; + this.tsoV1 = tsoV1; + } + + @Override + protected void handleNextWork() throws Throwable { + Iterator chunkIterator; + if (executionContext.isEnableOrcRawTypeBlock()) { + // Special csv scan work for raw orc type. + // Only Long/Double/ByteArray blocks are created. + // Normal query should not get there. + chunkIterator = MultiVersionCsvData.loadRawOrcTypeUntilTso(csvFile.getName(), executionContext, start, end); + } else { + chunkIterator = MultiVersionCsvData.loadSpecifiedCsvFile(csvFile.getName(), executionContext, start, end); + } + + int filterColumns = inputRefsForFilter.size(); + + boolean skipEvaluation = filterColumns == 0; + int totalPositionCnt = 0; + int totalChunkCnt = 0; + while (chunkIterator.hasNext()) { + Chunk chunk = chunkIterator.next(); + if (isCanceled) { + break; + } + + Block tsoBlock = chunk.getBlock(0); + int starPos = (int) chunk.getBlock(1).getLong(0); + + chunk = projectCsvChunk(chunk); + int positionCnt = chunk.getPositionCount(); + int[] selection = null; + + if (!skipEvaluation) { + long start = System.nanoTime(); + + selection = selectionOf(lazyEvaluator.eval(chunk, starPos, positionCnt, deletionBitmap)); + + if (enableMetrics) { + evaluationTimer.inc(System.nanoTime() - start); + } + } else { + selection = selectionOf(new int[] {starPos, positionCnt}, deletionBitmap); + } + + if (tsoV0 > 0 && tsoV1 > 0) { + // Filter by specified tso versions. + selection = filterTso(selection, tsoBlock); + } + + // NULL selection means full selection here + if (selection == null) { + ioStatus.addResult(chunk); + } else if (selection.length > 0) { + // rebuild chunk according to project refs. + Chunk projectChunk = rebuildProject(chunk, selection, selection.length); + ioStatus.addResult(projectChunk); + } + totalPositionCnt += positionCnt; + totalChunkCnt++; + } + + logger.debug( + String.format("Specified csv scan work finished: chunk count: %d, row count: %d, row/chunk: %f", + totalChunkCnt, + totalPositionCnt, totalChunkCnt == 0 ? -1 : (double) totalPositionCnt / totalChunkCnt)); + + ioStatus.finish(); + } + + private int[] filterTso(int[] selection, Block tso) { + int[] result = null; + List resultList = new ArrayList<>(); + if (null == selection) { + for (int i = 0; i < tso.getPositionCount(); i++) { + if (!tso.isNull(i) && tso.getLong(i) > tsoV0 && tso.getLong(i) <= tsoV1) { + resultList.add(i); + } + } + if (resultList.size() == tso.getPositionCount()) { + // All selected, return null. + return result; + } + } else { + for (int pos : selection) { + if (!tso.isNull(pos) && tso.getLong(pos) > tsoV0 && tso.getLong(pos) <= tsoV1) { + resultList.add(pos); + } + } + } + result = new int[resultList.size()]; + for (int i = 0; i < resultList.size(); i++) { + result[i] = resultList.get(i); + } + return result; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedDeleteBitmapPreProcessor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedDeleteBitmapPreProcessor.java new file mode 100644 index 000000000..b77088410 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedDeleteBitmapPreProcessor.java @@ -0,0 +1,217 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.oss.ColumnarFileType; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.executor.columnar.DeletionFileReader; +import com.alibaba.polardbx.executor.columnar.SimpleDeletionFileReader; +import com.alibaba.polardbx.executor.columnar.pruning.data.PruneUtils; +import com.alibaba.polardbx.executor.columnar.pruning.predicate.ColumnPredicatePruningInf; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.gms.DynamicColumnarManager; +import com.alibaba.polardbx.gms.engine.FileSystemManager; +import com.alibaba.polardbx.gms.engine.FileSystemUtils; +import com.alibaba.polardbx.gms.metadb.table.ColumnarFileMappingAccessor; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.statis.ColumnarTracer; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; +import org.apache.calcite.rex.RexNode; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.roaringbitmap.RoaringBitmap; + +import java.io.IOException; +import java.sql.Connection; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; + +import static com.alibaba.polardbx.executor.columnar.pruning.data.PruneUtils.transformRexToIndexMergeTree; + +/** + * This scan pre-processor use designate delete bitmap. + * For now, it is used for incremental check only. + * + * @author yaozhili + */ +public class SpecifiedDeleteBitmapPreProcessor extends DefaultScanPreProcessor { + private static final Logger logger = LoggerFactory.getLogger(SpecifiedDeleteBitmapPreProcessor.class); + + private final List delFiles; + private final List delBeginPos; + private final List delEndPos; + private final Engine engine; + private Long tableId = null; + + public SpecifiedDeleteBitmapPreProcessor(Configuration configuration, + FileSystem fileSystem, String schemaName, + String logicalTableName, boolean enableIndexPruning, + boolean enableOssCompatible, + List columns, + List rexList, + Map params, + double groupsRatio, double deletionRatio, + ColumnarManager columnarManager, Long tso, + List columnFieldIdList, + List delFiles, + List delBeginPos, + List delEndPos, + Engine engine, + long tableId) { + super(configuration, fileSystem, schemaName, logicalTableName, enableIndexPruning, enableOssCompatible, columns, + rexList, params, groupsRatio, deletionRatio, columnarManager, tso, columnFieldIdList); + if (null == delFiles) { + Preconditions.checkArgument(delBeginPos == null && delEndPos == null); + this.delFiles = new ArrayList<>(); + this.delBeginPos = new ArrayList<>(); + this.delEndPos = new ArrayList<>(); + } else { + this.delFiles = delFiles; + this.delBeginPos = delBeginPos; + this.delEndPos = delEndPos; + } + Preconditions.checkArgument( + (this.delFiles.size() == this.delBeginPos.size() && this.delBeginPos.size() == this.delEndPos.size()), + "delFiles size not match!"); + this.engine = engine; + this.tableId = tableId; + } + + public void addDelFiles(List delFiles, + List delStartPos, + List delEndPos, + Long tableId) { + this.delFiles.addAll(delFiles); + this.delBeginPos.addAll(delStartPos); + this.delEndPos.addAll(delEndPos); + this.tableId = tableId; + } + + @Override + public ListenableFuture prepare(ExecutorService executor, String traceId, ColumnarTracer tracer) { + SettableFuture future = SettableFuture.create(); + indexPruneContext.setPruneTracer(tracer); + // Is there a more elegant execution mode? + executor.submit( + () -> { + DynamicColumnarManager manager = DynamicColumnarManager.getInstance(); + int stripeNum = 0; + int rgNum = 0; + int pruneRgLeft = 0; + try { + // rex+pc -> distribution segment condition + indexes merge tree + ColumnPredicatePruningInf columnPredicate = + transformRexToIndexMergeTree(rexList, indexPruneContext); + + for (Path filePath : filePaths) { + // only preheat orc file meta + if (filePath.getName().toUpperCase().endsWith(ColumnarFileType.ORC.name())) { + // preheat all meta from orc file. + PreheatFileMeta preheat = PREHEATED_CACHE.get(filePath, () -> preheat(filePath)); + + preheatFileMetaMap.put(filePath, preheat); + + // if pruning is disabled, mark all row-groups as selected. + generateFullMatrix(filePath); + } + } + if (tracer != null && columnPredicate != null) { + tracer.tracePruneResult(logicalTableName, + PruneUtils.display(columnPredicate, columns, indexPruneContext), + filePaths.size(), + stripeNum, rgNum, pruneRgLeft); + } + generateDeletion(); + } catch (Exception e) { + throwable = e; + future.set(null); + return; + } + future.set(null); + } + + ); + + this.future = future; + return future; + } + + protected void generateDeletion() { + if (null == delFiles || delFiles.isEmpty()) { + return; + } + // Generate delete bitmap. + Map fileIdToBitmap = new HashMap<>(); + for (int i = 0; i < delFiles.size(); i++) { + final String fileName = delFiles.get(i); + final long start = delBeginPos.get(i); + final long end = delEndPos.get(i); + if (start == end) { + continue; + } + try (SimpleDeletionFileReader fileReader = new SimpleDeletionFileReader()) { + try { + fileReader.open( + engine, + fileName, + (int) start, + (int) (end - start) + ); + } catch (IOException e) { + throw new TddlRuntimeException(ErrorCode.ERR_LOAD_DEL_FILE, e, + String.format("Failed to open delete bitmap file, filename: %s, offset: %d, length: %d", + fileName, start, end - start)); + } + + DeletionFileReader.DeletionEntry deletionEntry; + while (fileReader.position() < end && null != (deletionEntry = fileReader.next())) { + final int fileId = deletionEntry.getFileId(); + final RoaringBitmap bitmap = deletionEntry.getBitmap(); + fileIdToBitmap.compute(String.valueOf(fileId), (k, v) -> { + if (v == null) { + return bitmap; + } else { + v.or(bitmap); + return v; + } + }); + } + } + } + + if (fileIdToBitmap.isEmpty()) { + return; + } + + // Convert file id to file name. + FileSystem fileSystem = FileSystemManager.getFileSystemGroup(engine).getMaster(); + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarFileMappingAccessor accessor = new ColumnarFileMappingAccessor(); + accessor.setConnection(connection); + accessor.queryByFileIdList(fileIdToBitmap.keySet(), schemaName, tableId).forEach(record -> deletions.put( + // csv/orc file name + FileSystemUtils.buildPath(fileSystem, record.getFileName(), true), + // find bitmap by file id + fileIdToBitmap.get(String.valueOf(record.getColumnarFileId())) + )); + } catch (Throwable t) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER, t, "Failed to diff del-bitmap files"); + } + + if (fileIdToBitmap.size() != deletions.size()) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER, + "Failed to generate specified del-bitmap: Size not match."); + } + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedOrcColumnarSplit.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedOrcColumnarSplit.java new file mode 100644 index 000000000..4226a0279 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedOrcColumnarSplit.java @@ -0,0 +1,445 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.mpp.planner.FragmentRFItem; +import com.alibaba.polardbx.executor.mpp.planner.FragmentRFItemKey; +import com.alibaba.polardbx.executor.mpp.planner.FragmentRFManager; +import com.alibaba.polardbx.executor.operator.scan.BlockCacheManager; +import com.alibaba.polardbx.executor.operator.scan.ColumnReader; +import com.alibaba.polardbx.executor.operator.scan.ColumnarSplit; +import com.alibaba.polardbx.executor.operator.scan.LazyEvaluator; +import com.alibaba.polardbx.executor.operator.scan.LogicalRowGroup; +import com.alibaba.polardbx.executor.operator.scan.RowGroupIterator; +import com.alibaba.polardbx.executor.operator.scan.ScanPreProcessor; +import com.alibaba.polardbx.executor.operator.scan.ScanWork; +import com.alibaba.polardbx.executor.operator.scan.metrics.ProfileAccumulatorType; +import com.alibaba.polardbx.executor.operator.scan.metrics.ProfileUnit; +import com.alibaba.polardbx.executor.operator.scan.metrics.RuntimeMetrics; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.memory.MemoryAllocatorCtx; +import com.alibaba.polardbx.optimizer.statis.OperatorStatistics; +import com.google.common.base.Preconditions; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.orc.ColumnStatistics; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; + +/** + * This split contains an orc file with specified delete bitmap, + * and with specified tso versions. + */ +public class SpecifiedOrcColumnarSplit extends MorselColumnarSplit { + private long tsoV0; + private long tsoV1; + + public SpecifiedOrcColumnarSplit(ExecutionContext executionContext, + ExecutorService ioExecutor, Engine engine, + FileSystem fileSystem, Configuration configuration, + int sequenceId, int fileId, Path filePath, + OSSColumnTransformer ossColumnTransformer, + int[] primaryKeyColIds, List inputRefsForFilter, + List inputRefsForProject, int chunkLimit, + BlockCacheManager blockCacheManager, + int rgThreshold, + LazyEvaluator lazyEvaluator, + ScanPreProcessor preProcessor, int partNum, + int nodePartCount, MemoryAllocatorCtx memoryAllocatorCtx, + FragmentRFManager fragmentRFManager, + Map rfFilterRefInFileMap, + OperatorStatistics operatorStatistics, + long tsoV0, long tsoV1) + throws IOException { + super(executionContext, ioExecutor, engine, fileSystem, configuration, sequenceId, fileId, filePath, + ossColumnTransformer, primaryKeyColIds, inputRefsForFilter, inputRefsForProject, chunkLimit, + blockCacheManager, rgThreshold, lazyEvaluator, preProcessor, partNum, nodePartCount, memoryAllocatorCtx, + fragmentRFManager, rfFilterRefInFileMap, operatorStatistics); + this.tsoV0 = tsoV0; + this.tsoV1 = tsoV1; + } + + @Override + public ScanWork nextWork() { + if (scanWorkIterator == null) { + // The pre-processor must have been done. + if (!preProcessor.isPrepared()) { + GeneralUtil.nestedException("The pre-processor is not prepared"); + } + + try { + scanWorkIterator = new SpecifiedScanWorkIterator(); + } catch (IOException e) { + throw GeneralUtil.nestedException("Fail to initialize scan-work iterator", e); + } + } + + while (scanWorkIterator.hasNext()) { + return (ScanWork) scanWorkIterator.next(); + } + return null; + } + + class SpecifiedScanWorkIterator extends ScanWorkIterator { + + SpecifiedScanWorkIterator() throws IOException { + super(); + } + + @Override + public ScanWork next() { + String scanWorkId = generateScanWorkId( + executionContext.getTraceId(), + filePath.toString(), + currentRange.stripeId, + scanWorkIndex++ + ); + + boolean enableMetrics = executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_COLUMNAR_METRICS); + boolean activeLoading = executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_LAZY_BLOCK_ACTIVE_LOADING); + + RuntimeMetrics metrics = RuntimeMetrics.create(scanWorkId); + + // Add parent metrics node + if (enableMetrics) { + metrics.addDerivedCounter(AsyncStripeLoader.ASYNC_STRIPE_LOADER_MEMORY, + null, ProfileUnit.BYTES, ProfileAccumulatorType.SUM); + metrics.addDerivedCounter(AsyncStripeLoader.ASYNC_STRIPE_LOADER_TIMER, + null, ProfileUnit.NANO_SECOND, ProfileAccumulatorType.SUM); + metrics.addDerivedCounter(AsyncStripeLoader.ASYNC_STRIPE_LOADER_BYTES_RANGE, + null, ProfileUnit.BYTES, ProfileAccumulatorType.SUM); + + metrics.addDerivedCounter(ColumnReader.COLUMN_READER_MEMORY, + null, ProfileUnit.BYTES, ProfileAccumulatorType.SUM); + metrics.addDerivedCounter(ColumnReader.COLUMN_READER_TIMER, + null, ProfileUnit.NANO_SECOND, ProfileAccumulatorType.SUM); + + metrics.addDerivedCounter(LogicalRowGroup.BLOCK_LOAD_TIMER, + null, ProfileUnit.NANO_SECOND, ProfileAccumulatorType.SUM); + metrics.addDerivedCounter(LogicalRowGroup.BLOCK_MEMORY_COUNTER, + null, ProfileUnit.BYTES, ProfileAccumulatorType.SUM); + + metrics.addDerivedCounter(ScanWork.EVALUATION_TIMER, + null, ProfileUnit.NANO_SECOND, ProfileAccumulatorType.SUM); + } + + if (currentRange != null) { + RowGroupIterator rowGroupIterator = new RowGroupIteratorImpl( + metrics, + + // The range of this row-group iterator. + currentRange.stripeId, + currentRange.startRowGroupId, + currentRange.effectiveGroupCount, + currentRange.rowGroupIncluded, + + // primary key col ids. + primaryKeyColIds, + + // parameters for IO task. + ioExecutor, fileSystem, configuration, filePath, + + // for compression + compressionSize, compressionKind, + preheatFileMeta, + + // for stripe-level parser + stripeInformationMap.get(currentRange.stripeId), + startRowInStripeMap.get(currentRange.stripeId), + + fileSchema, version, encryption, + encodingMap.get(currentRange.stripeId), + ignoreNonUtf8BloomFilter, + maxBufferSize, maxDiskRangeChunkLimit, maxMergeDistance, + chunkLimit, blockCacheManager, ossColumnTransformer, + executionContext, columnIncluded, indexStride, enableDecimal64, + memoryAllocatorCtx); + + ScanWork scanWork; + if (executionContext.isEnableOrcDeletedScan()) { + scanWork = new DeletedScanWork( + scanWorkId, + metrics, + enableMetrics, + lazyEvaluator, + rowGroupIterator, deletion, + currentRange, inputRefsForFilter, inputRefsForProject, + partNum, nodePartCount, + activeLoading, ossColumnTransformer); + } else { + scanWork = new SpecifiedOrcScanWork( + scanWorkId, + metrics, + enableMetrics, + lazyEvaluator, + rowGroupIterator, deletion, + currentRange, inputRefsForFilter, inputRefsForProject, + partNum, nodePartCount, + ossColumnTransformer, + tsoV0, tsoV1, executionContext + ); + } + + currentRange = null; + return scanWork; + } + return null; + } + } + + public static ColumnarSplitBuilder newBuilder() { + return new SpecifiedOrcColumnarSplit.SpecifiedOrcColumnarSplitBuilder(); + } + + static class SpecifiedOrcColumnarSplitBuilder implements ColumnarSplitBuilder { + private ExecutionContext executionContext; + private ExecutorService ioExecutor; + private Engine engine; + private FileSystem fileSystem; + private Configuration configuration; + private int sequenceId; + private int fileId; + private Path filePath; + private OSSColumnTransformer ossColumnTransformer; + private String logicalSchema; + private String logicalTable; + private List inputRefsForFilter; + private List inputRefsForProject; + private int chunkLimit; + private BlockCacheManager blockCacheManager; + private int rgThreshold; + private LazyEvaluator lazyEvaluator; + private ScanPreProcessor preProcessor; + private ColumnarManager columnarManager; + private Long tso; + private boolean isColumnarMode; + + private int partNum; + + private int nodePartCount; + private MemoryAllocatorCtx memoryAllocatorCtx; + + private FragmentRFManager fragmentRFManager; + private OperatorStatistics operatorStatistics; + + private long tsoV0; + + private long tsoV1; + + @Override + public ColumnarSplit build() { + try { + // CASE1: when evaluator is null, the input refs for filter must be empty. + // CASE2: when evaluator is entirely a constant expression, the input refs for filter must be empty. + Preconditions.checkArgument((lazyEvaluator == null + || lazyEvaluator.isConstantExpression()) == (inputRefsForFilter.isEmpty()), + "when evaluator is null, the input refs for filter must be empty."); + + Map rfFilterRefInFileMap = new HashMap<>(); + if (fragmentRFManager != null) { + + // For each item, mapping the source ref to file column ref. + for (Map.Entry itemEntry + : fragmentRFManager.getAllItems().entrySet()) { + List rfFilterChannels = new ArrayList<>(); + rfFilterChannels.add(itemEntry.getValue().getSourceRefInFile()); + + rfFilterChannels = isColumnarMode + ? columnarManager.getPhysicalColumnIndexes(tso, filePath.getName(), rfFilterChannels) + : rfFilterChannels; + + rfFilterRefInFileMap.put(itemEntry.getKey(), rfFilterChannels.get(0)); + } + } + + int[] primaryKeyColIds = + isColumnarMode ? columnarManager.getPrimaryKeyColumns(filePath.getName()) : null; + + // To distinguish the columnar mode from archive mode + return new SpecifiedOrcColumnarSplit( + executionContext, ioExecutor, engine, fileSystem, + configuration, sequenceId, fileId, filePath, + ossColumnTransformer, primaryKeyColIds, + + inputRefsForFilter, inputRefsForProject, + + chunkLimit, blockCacheManager, + rgThreshold, lazyEvaluator, + preProcessor, + partNum, nodePartCount, memoryAllocatorCtx, fragmentRFManager, rfFilterRefInFileMap, + operatorStatistics, + + tsoV0, tsoV1); + } catch (IOException e) { + throw GeneralUtil.nestedException("Fail to build columnar split.", e); + } + } + + @Override + public ColumnarSplitBuilder executionContext(ExecutionContext context) { + this.executionContext = context; + return this; + } + + @Override + public ColumnarSplitBuilder ioExecutor(ExecutorService ioExecutor) { + this.ioExecutor = ioExecutor; + return this; + } + + @Override + public ColumnarSplitBuilder fileSystem(FileSystem fileSystem, Engine engine) { + this.fileSystem = fileSystem; + this.engine = engine; + return this; + } + + @Override + public ColumnarSplitBuilder configuration(Configuration configuration) { + this.configuration = configuration; + return this; + } + + @Override + public ColumnarSplitBuilder sequenceId(int sequenceId) { + this.sequenceId = sequenceId; + return this; + } + + @Override + public ColumnarSplitBuilder file(Path filePath, int fileId) { + this.filePath = filePath; + this.fileId = fileId; + return this; + } + + @Override + public ColumnarSplitBuilder tableMeta(String logicalSchema, String logicalTable) { + this.logicalSchema = logicalSchema; + this.logicalTable = logicalTable; + return this; + } + + @Override + public ColumnarSplitBuilder columnTransformer(OSSColumnTransformer ossColumnTransformer) { + this.ossColumnTransformer = ossColumnTransformer; + return this; + } + + @Override + public ColumnarSplitBuilder inputRefs(List inputRefsForFilter, List inputRefsForProject) { + this.inputRefsForFilter = inputRefsForFilter; + this.inputRefsForProject = inputRefsForProject; + return this; + } + + @Override + public ColumnarSplitBuilder cacheManager(BlockCacheManager blockCacheManager) { + this.blockCacheManager = blockCacheManager; + return this; + } + + @Override + public ColumnarSplitBuilder chunkLimit(int chunkLimit) { + this.chunkLimit = chunkLimit; + return this; + } + + @Override + public ColumnarSplitBuilder morselUnit(int rgThreshold) { + this.rgThreshold = rgThreshold; + return this; + } + + @Override + public ColumnarSplitBuilder pushDown(LazyEvaluator lazyEvaluator) { + this.lazyEvaluator = lazyEvaluator; + return this; + } + + @Override + public ColumnarSplitBuilder prepare(ScanPreProcessor scanPreProcessor) { + this.preProcessor = scanPreProcessor; + return this; + } + + @Override + public ColumnarSplitBuilder columnarManager(ColumnarManager columnarManager) { + this.columnarManager = columnarManager; + return this; + } + + @Override + public ColumnarSplitBuilder isColumnarMode(boolean isColumnarMode) { + this.isColumnarMode = isColumnarMode; + return this; + } + + @Override + public ColumnarSplitBuilder tso(Long tso) { + this.tso = tso; + return this; + } + + @Override + public ColumnarSplitBuilder position(Long position) { + return this; + } + + @Override + public ColumnarSplitBuilder partNum(int partNum) { + this.partNum = partNum; + return this; + } + + @Override + public ColumnarSplitBuilder nodePartCount(int nodePartCount) { + this.nodePartCount = nodePartCount; + return this; + } + + @Override + public ColumnarSplitBuilder memoryAllocator(MemoryAllocatorCtx memoryAllocatorCtx) { + this.memoryAllocatorCtx = memoryAllocatorCtx; + return this; + } + + @Override + public ColumnarSplitBuilder fragmentRFManager(FragmentRFManager fragmentRFManager) { + this.fragmentRFManager = fragmentRFManager; + return this; + } + + @Override + public ColumnarSplitBuilder operatorStatistic(OperatorStatistics operatorStatistics) { + this.operatorStatistics = operatorStatistics; + return this; + } + + @Override + public ColumnarSplitBuilder tsoV0(long tsoV0) { + this.tsoV0 = tsoV0; + return this; + } + + @Override + public ColumnarSplitBuilder tsoV1(long tsoV1) { + this.tsoV1 = tsoV1; + return this; + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedOrcScanWork.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedOrcScanWork.java new file mode 100644 index 000000000..148ab1a8b --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedOrcScanWork.java @@ -0,0 +1,263 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.BlockUtils; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.columnar.CommonLazyBlock; +import com.alibaba.polardbx.executor.chunk.columnar.LazyBlock; +import com.alibaba.polardbx.executor.operator.scan.ColumnReader; +import com.alibaba.polardbx.executor.operator.scan.LazyEvaluator; +import com.alibaba.polardbx.executor.operator.scan.LogicalRowGroup; +import com.alibaba.polardbx.executor.operator.scan.RowGroupIterator; +import com.alibaba.polardbx.executor.operator.scan.RowGroupReader; +import com.alibaba.polardbx.executor.operator.scan.metrics.RuntimeMetrics; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.utils.TimestampUtils; +import com.google.common.base.Preconditions; +import org.apache.orc.ColumnStatistics; +import org.roaringbitmap.RoaringBitmap; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; +import java.util.TreeMap; + +/** + * This scan work scan specified orc files with specified delete bitmap. + * It will also filter specified version of rows (filtered by tso). + */ +public class SpecifiedOrcScanWork extends AbstractScanWork { + private final long tsoV0; + private final long tsoV1; + private final boolean useSelection; + private final boolean enableCompatible; + private final TimeZone targetTimeZone; + + public SpecifiedOrcScanWork(String workId, + RuntimeMetrics metrics, + boolean enableMetrics, + LazyEvaluator lazyEvaluator, + RowGroupIterator rgIterator, + RoaringBitmap deletionBitmap, + MorselColumnarSplit.ScanRange scanRange, + List inputRefsForFilter, + List inputRefsForProject, + int partNum, + int nodePartCount, + OSSColumnTransformer ossColumnTransformer, + long tsoV0, + long tsoV1, + ExecutionContext executionContext) { + super(workId, metrics, enableMetrics, lazyEvaluator, rgIterator, deletionBitmap, scanRange, inputRefsForFilter, + inputRefsForProject, partNum, nodePartCount, ossColumnTransformer); + this.tsoV0 = tsoV0; + this.tsoV1 = tsoV1; + this.useSelection = executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_COLUMNAR_SCAN_SELECTION); + this.enableCompatible = executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_OSS_COMPATIBLE); + this.targetTimeZone = TimestampUtils.getTimeZone(executionContext); + } + + @Override + protected void handleNextWork() { + // not all row group but those filtered by pruner should be loaded. + final boolean[] prunedRowGroupBitmap = rgIterator.rgIncluded(); + final int rowGroupCount = prunedRowGroupBitmap.length; + + // Get and lazily evaluate chunks until row group count exceeds the threshold. + // NOTE: the row-group and chunk must be in order. + final Map> chunksWithGroup = new TreeMap<>(); + final List selectedRowGroups = new ArrayList<>(); + + while (!isCanceled && rgIterator.hasNext()) { + rgIterator.next(); + LogicalRowGroup logicalRowGroup = rgIterator.current(); + final int rowGroupId = logicalRowGroup.groupId(); + + // The row group id in iterator must be valid. + Preconditions.checkArgument(prunedRowGroupBitmap[rowGroupId]); + + // A flag for each row group to indicate that at least one block selected in row group. + boolean rgSelected = false; + + Chunk chunk; + RowGroupReader rowGroupReader = logicalRowGroup.getReader(); + while ((chunk = rowGroupReader.nextBatch()) != null) { + int[] batchRange = rowGroupReader.batchRange(); + int[] preSelection = selectionOf(batchRange, deletionBitmap); + if (preSelection != null) { + // rebuild chunk according to project refs. + chunk = rebuildProject(chunk, preSelection, preSelection.length); + } + + chunk.setPartIndex(partNum); + chunk.setPartCount(nodePartCount); + + // no evaluation, just buffer the unloaded chunks. + List chunksInGroup = chunksWithGroup.computeIfAbsent(rowGroupId, any -> new ArrayList<>()); + chunksInGroup.add(chunk); + rgSelected = true; + } + // the chunk in this row group is run out, change to the next. + if (rgSelected) { + selectedRowGroups.add(rowGroupId); + } else { + // if row-group is not selected, remove all chunks of this row-group from buffer. + List chunksInGroup; + if ((chunksInGroup = chunksWithGroup.remove(rowGroupId)) != null) { + chunksInGroup.clear(); + } + } + } + + // There is no more chunk produced by this row group iterator. + rgIterator.noMoreChunks(); + + // no group is selected. + if (selectedRowGroups.isEmpty()) { + ioStatus.finish(); + return; + } + + // We collect all chunks in several row groups here, + // so we can merge the IO range of different row group to improve I/O efficiency. + boolean[] rowGroupIncluded = toRowGroupBitmap(rowGroupCount, selectedRowGroups); + + // collect all row-groups for mering IO tasks. + if (tsoV0 > 0 && tsoV1 > 0) { + mergeIONoCacheWithTsoColumn(inputRefsForProject, rowGroupIncluded); + } else { + mergeIONoCache(inputRefsForProject, rowGroupIncluded); + } + + for (Map.Entry> entry : chunksWithGroup.entrySet()) { + List chunksInGroup = entry.getValue(); + for (Chunk bufferedChunk : chunksInGroup) { + + // The target chunk may be in lazy mode or changed to be in normal mode. + Block[] blocks = new Block[bufferedChunk.getBlockCount()]; + // load project columns + for (int blockIndex = 0; blockIndex < bufferedChunk.getBlockCount(); blockIndex++) { + LazyBlock lazyBlock = (LazyBlock) bufferedChunk.getBlock(blockIndex); + lazyBlock.load(); + + blocks[blockIndex] = lazyBlock.getLoaded(); + } + + Chunk targetChunk = bufferedChunk; + if (tsoV0 > 0 && tsoV1 > 0) { + // Filter data by specified tso versions. + targetChunk = filterByTso(targetChunk, blocks); + } + targetChunk.setPartIndex(partNum); + targetChunk.setPartCount(nodePartCount); + // add result and notify the blocked threads. + ioStatus.addResult(targetChunk); + } + } + + ioStatus.finish(); + + // force columnar reader to close. + forceClose(inputRefsForFilter); + forceClose(inputRefsForProject); + // Close tso column reader if any. + ColumnReader columnReader = rgIterator.getColumnReader(1); + if (columnReader != null) { + columnReader.close(); + } + } + + private Chunk filterByTso(Chunk chunk, Block[] blocks) { + int[] selections = chunk.selection(); + Block tsoBlock = blocks[blocks.length - 1]; + List newSelectionList = new ArrayList<>(); + if (null == selections) { + for (int i = 0; i < chunk.getPositionCount(); i++) { + if (!tsoBlock.isNull(i) && tsoBlock.getLong(i) > tsoV0 && tsoBlock.getLong(i) <= tsoV1) { + newSelectionList.add(i); + } + } + if (newSelectionList.size() == tsoBlock.getPositionCount()) { + // All selected, remove tso block and return. + Block[] newBlocks = new Block[blocks.length - 1]; + System.arraycopy(blocks, 0, newBlocks, 0, blocks.length - 1); + return new Chunk(chunk.getPositionCount(), newBlocks); + } + } else { + for (int pos : selections) { + if (!tsoBlock.isNull(pos) && tsoBlock.getLong(pos) > tsoV0 && tsoBlock.getLong(pos) <= tsoV1) { + newSelectionList.add(pos); + } + } + } + // Build new selection array. + int[] newSelections = new int[newSelectionList.size()]; + for (int i = 0; i < newSelectionList.size(); i++) { + newSelections[i] = newSelectionList.get(i); + } + // Build new chunk. + Block[] newBlocks = new Block[blocks.length - 1]; + if (newSelections.length > 0) { + for (int blockIndex = 0; blockIndex < blocks.length - 1; blockIndex++) { + newBlocks[blockIndex] = + BlockUtils.fillSelection(blocks[blockIndex], newSelections, newSelections.length, + useSelection, enableCompatible, targetTimeZone); + } + } + return new Chunk(newSelections.length, newBlocks); + } + + private void forceClose(List inputRefs) { + for (int i = 0; i < inputRefs.size(); i++) { + final int columnId = inputRefs.get(i) + 1; + ColumnReader columnReader = rgIterator.getColumnReader(columnId); + if (columnReader != null) { + columnReader.close(); + } + } + } + + /** + * Add Tso column in chunk as the last block. + */ + @Override + protected Chunk rebuildProject(Chunk chunk, int[] selection, int selSize) { + Block[] blocks = new Block[inputRefsForProject.size() + 1]; + int blockIndex = 0; + + for (int projectRef : inputRefsForProject) { + // mapping blocks for projection. + int chunkIndex = chunkRefMap[projectRef]; + Block block = chunk.getBlock(chunkIndex); + blocks[blockIndex++] = block; + + // fill with selection. + if (selection != null && chunk.getPositionCount() != selSize) { + Preconditions.checkArgument(block instanceof CommonLazyBlock); + ((CommonLazyBlock) block).setSelection(selection, selSize); + } + } + + if (tsoV0 > 0 && tsoV1 > 0) { + // Last block is tso column. + Block block = chunk.getBlock(blocks.length - 1); + blocks[blockIndex++] = block; + if (selection != null && chunk.getPositionCount() != selSize) { + Preconditions.checkArgument(block instanceof CommonLazyBlock); + ((CommonLazyBlock) block).setSelection(selection, selSize); + } + } + + // NOTE: we must set position count of chunk to selection size. + Chunk projectChunk = new Chunk(selSize, blocks); + projectChunk.setPartIndex(partNum); + projectChunk.setPartCount(nodePartCount); + return projectChunk; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/spill/AsyncFileSingleStreamSpillerFactory.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/spill/AsyncFileSingleStreamSpillerFactory.java index 8a670aca4..7579bb1da 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/spill/AsyncFileSingleStreamSpillerFactory.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/spill/AsyncFileSingleStreamSpillerFactory.java @@ -64,7 +64,6 @@ import static java.nio.file.Files.getFileStore; import static java.nio.file.Files.newDirectoryStream; import static java.util.Objects.requireNonNull; -import static org.apache.hadoop.mapred.FileOutputCommitter.TEMP_DIR_NAME; public class AsyncFileSingleStreamSpillerFactory implements SingleStreamSpillerFactory { @@ -195,7 +194,7 @@ public ReaderThread getReadThread(int idx) { @VisibleForTesting protected static File getTemPath(File base) { - return new File(base, TEMP_DIR_NAME); + return new File(base, "_temporary"); } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/util/AggregateUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/util/AggregateUtils.java index 9e0aa5a25..0e17d6aec 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/util/AggregateUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/util/AggregateUtils.java @@ -36,6 +36,10 @@ import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.GroupConcat; import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.HyperLoglog; import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.InternalFirstValue; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.JsonArrayAgg; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.JsonArrayGlobalAgg; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.JsonObjectAgg; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.JsonObjectGlobalAgg; import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.Lag; import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.LastValue; import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.Lead; @@ -50,6 +54,8 @@ import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.SingleValue; import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.Sum0; import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.SumV2; +import com.alibaba.polardbx.optimizer.core.function.SqlJsonArrayAggFunction; +import com.alibaba.polardbx.optimizer.core.function.SqlJsonObjectAggFunction; import com.alibaba.polardbx.optimizer.memory.MemoryAllocatorCtx; import com.alibaba.polardbx.optimizer.memory.MemoryManager; import org.apache.calcite.rel.core.AggregateCall; @@ -253,6 +259,24 @@ public static List convertAggregators(List aggCallLis } break; } + case JSON_OBJECTAGG: + JsonObjectAgg jsonObjectAgg = + new JsonObjectAgg(call.getArgList().stream().mapToInt(Integer::valueOf).toArray(), filterArg); + aggList.add(jsonObjectAgg); + break; + case JSON_OBJECT_GLOBALAGG: + JsonObjectGlobalAgg jsonObjectGlobalAgg = + new JsonObjectGlobalAgg(index, filterArg); + aggList.add(jsonObjectGlobalAgg); + break; + case JSON_ARRAYAGG: + JsonArrayAgg jsonArrayAgg = new JsonArrayAgg(index, filterArg); + aggList.add(jsonArrayAgg); + break; + case JSON_ARRAY_GLOBALAGG: + JsonArrayGlobalAgg jsonArrayGlobalAgg = new JsonArrayGlobalAgg(index, filterArg); + aggList.add(jsonArrayGlobalAgg); + break; default: throw new UnsupportedOperationException( "Unsupported agg function to convert:" + function.name()); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/util/BatchBlockWriter.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/util/BatchBlockWriter.java index 6a7753bba..b8d7603b1 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/util/BatchBlockWriter.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/operator/util/BatchBlockWriter.java @@ -1312,6 +1312,11 @@ public long getDecimal128High(int position) { } } + @Override + public int getScale() { + return scale; + } + public boolean isNormal() { return state.isNormal(); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/AlterTableGroupUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/AlterTableGroupUtils.java index caba1309c..9085e09b5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/AlterTableGroupUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/AlterTableGroupUtils.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.TStringUtil; @@ -96,6 +97,7 @@ import org.apache.calcite.sql.SqlAlterTableMergePartition; import org.apache.calcite.sql.SqlAlterTableModifyPartitionValues; import org.apache.calcite.sql.SqlAlterTableMovePartition; +import org.apache.calcite.sql.SqlAlterTableOptimizePartition; import org.apache.calcite.sql.SqlAlterTableRenamePartition; import org.apache.calcite.sql.SqlAlterTableReorgPartition; import org.apache.calcite.sql.SqlAlterTableSplitPartition; @@ -208,6 +210,10 @@ public static void alterTableGroupPreCheck(SqlAlterTableGroup sqlAlterTableGroup alterTableGroupTruncatePartitionCheck((SqlAlterTableTruncatePartition) alterSpecifications.get(0), tableGroupConfig, executionContext); + } else if (alterSpecifications.get(0) instanceof SqlAlterTableOptimizePartition) { + alterTableGroupOptimizePartitionCheck((SqlAlterTableOptimizePartition) alterSpecifications.get(0), + tableGroupConfig, executionContext); + } else if (alterSpecifications.get(0) instanceof SqlAlterTableGroupSetPartitionsLocality) { } else if (alterSpecifications.get(0) instanceof SqlAlterTableModifyPartitionValues) { @@ -462,6 +468,9 @@ public static void alterTableGroupSplitPartitionCheck(SqlAlterTableSplitPartitio partSpecAstParams.setSubPartSpec(false); partSpecAstParams.setParentPartSpec(null); partSpecAstParams.setPhySpecCounter(phyPartCounter); + partSpecAstParams.setPartEngine(tableMeta.isColumnar() ? + TablePartitionRecord.PARTITION_ENGINE_COLUMNAR : + TablePartitionRecord.PARTITION_ENGINE_INNODB); PartitionSpec newSpec = PartitionInfoBuilder.buildPartSpecByAstParams(partSpecAstParams); // PartitionSpec newSpec = PartitionInfoBuilder @@ -973,7 +982,7 @@ private static void checkIfNewPartitionsValidForReorg(PartitionInfo partitionInf List newPartSpecs = buildNewPartitionSpecsForCheck(partitionInfo, tableGroupConfig, partRexInfoCtx, newPartDefs, isSubPartition, - isAlterTableGroup, executionContext); + isAlterTableGroup, partitionInfo.isColumnar(), executionContext); if (strategy.isRange()) { PartitionSpec firstNewPartSpec = newPartSpecs.get(0); @@ -1132,7 +1141,8 @@ private static void checkIfNewPartitionsValidForReorg(PartitionInfo partitionInf } List newSubPartSpecs = buildNewPartitionSpecsForCheck(partitionInfo, tableGroupConfig, partRexInfoCtx, - mockDefForNewSubPart, true, isAlterTableGroup, executionContext); + mockDefForNewSubPart, true, isAlterTableGroup, partitionInfo.isColumnar(), + executionContext); newPartSpecs.get(i).getSubPartitions().addAll(newSubPartSpecs); } } @@ -1214,6 +1224,7 @@ private static List buildNewPartitionSpecsForCheck(PartitionInfo List newPartDefs, boolean isSubPartition, boolean isAlterTableGroup, + boolean isColumnarIndex, ExecutionContext executionContext) { String schemaName = tableGroupConfig.getTableGroupRecord().getSchema(); String tableGroupName = tableGroupConfig.getTableGroupRecord().getTg_name(); @@ -1294,6 +1305,9 @@ private static List buildNewPartitionSpecsForCheck(PartitionInfo partSpecAstParams.setSubPartSpec(false); partSpecAstParams.setParentPartSpec(null); partSpecAstParams.setPhySpecCounter(phyPartCounter); + partSpecAstParams.setPartEngine(isColumnarIndex ? + TablePartitionRecord.PARTITION_ENGINE_COLUMNAR : + TablePartitionRecord.PARTITION_ENGINE_INNODB); PartitionSpec newPartSpec = PartitionInfoBuilder.buildPartSpecByAstParams(partSpecAstParams); @@ -1714,9 +1728,28 @@ public static void alterTableGroupDropPartitionCheck(SqlAlterTableDropPartition "Don't allow to drop all the partitions"); } + boolean listOrRangePartition = partByDef.getStrategy().isList() || partByDef.getStrategy().isRange(); + if (sqlAlterTableDropPartition.isSubPartition() && !subPartByDef.isUseSubPartTemplate() + && !listOrRangePartition) { + Map partitionSpecMap = partitionInfo.getPartitionBy().getPartNameToPhyPartMap(); + HashMap> parentPartPositions = new HashMap<>(); + for (String partName : droppingPartNames) { + PartitionSpec subPartSpec = partitionSpecMap.get(partName); + parentPartPositions.computeIfAbsent(subPartSpec.getParentPartPosi(), k -> new ArrayList<>()); + parentPartPositions.get(subPartSpec.getParentPartPosi()).add(partName); + } + for (Map.Entry> entry : parentPartPositions.entrySet()) { + PartitionSpec partitionSpec = partitionInfo.getPartitionBy().getNthPartition(entry.getKey().intValue()); + if (partitionSpec.getSubPartitions().size() == entry.getValue().size()) { + throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_MANAGEMENT, + "Don't allow to drop all the subpartitions for " + partitionSpec.getName()); + } + } + } + for (String tableName : tableGroupConfig.getAllTables()) { TableMeta tbMeta = schemaManager.getTable(tableName); - if (tbMeta.withGsi() && !tbMeta.withCci()) { + if (tbMeta.withGsiExcludingPureCci()) { throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_MANAGEMENT, String.format("it's not support to drop partition/subpartition when table[%s] with GSI", tableName)); @@ -1726,6 +1759,7 @@ public static void alterTableGroupDropPartitionCheck(SqlAlterTableDropPartition String.format("it's not support to drop global index[%s]'s partition/subpartition", tableName)); } + checkAllDropTruncateCciPartition(executionContext, tbMeta, tableName); } } @@ -1758,9 +1792,54 @@ public static void alterTableGroupTruncatePartitionCheck( String.format("it's not support to truncate global index[%s]'s partition/subpartition", tableName)); } + checkAllDropTruncateCciPartition(executionContext, tbMeta, tableName); + } + } + + public static void checkAllDropTruncateCciPartition(ExecutionContext executionContext, TableMeta tbMeta, + String tableName) { + boolean allDropTruncateCciPartition = + executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_DROP_TRUNCATE_CCI_PARTITION); + if (tbMeta.withCci() && !allDropTruncateCciPartition) { + throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_MANAGEMENT, + String.format("it's not support to drop partition/subpartition when table[%s] with CCI", + tableName)); + } + if (tbMeta.isColumnar() && !allDropTruncateCciPartition) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_DROP_PARTITION, + String.format("it's not support to drop columnar index[%s]'s partition/subpartition", + tableName)); } } + public static void alterTableGroupOptimizePartitionCheck( + SqlAlterTableOptimizePartition sqlAlterTableOptimizePartition, TableGroupConfig tableGroupConfig, + ExecutionContext executionContext) { +// String schemaName = tableGroupConfig.getTableGroupRecord().getSchema(); +// final SchemaManager schemaManager = executionContext.getSchemaManager(schemaName); +// String tableInCurrentGroup = tableGroupConfig.getAllTables().get(0); +// PartitionInfo partitionInfo = schemaManager.getTable(tableInCurrentGroup).getPartitionInfo(); +// PartitionByDefinition subPartByDef = partitionInfo.getPartitionBy().getSubPartitionBy(); +// if (subPartByDef == null) { +// // OPTIMIZE SUBPARTITION +// throw new TddlRuntimeException(ErrorCode.ERR_DROP_SUBPARTITION, +// "Don't allow to optimize subpartitions from one-level partitioned table"); +// } +// for (String tableName : tableGroupConfig.getAllTables()) { +// TableMeta tbMeta = schemaManager.getTable(tableName); +// if (tbMeta.withGsi()) { +// throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_MANAGEMENT, +// String.format("it's not support to optimize partition/subpartition when table[%s] with GSI", +// tableName)); +// } +// if (tbMeta.isGsi()) { +// throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_DROP_PARTITION, +// String.format("it's not support to optimize global index[%s]'s partition/subpartition", +// tableName)); +// } +// } + } + private static void alterTableModifyListPartitionValuesCheck(SqlAlterTableGroup sqlAlterTableGroup, TableGroupConfig tableGroupConfig, SqlAlterTableModifyPartitionValues sqlModifyListPartitionValues, @@ -1914,10 +1993,26 @@ private static void alterTableModifyListPartitionValuesCheck(SqlAlterTableGroup throw new TddlRuntimeException(ErrorCode.ERR_GLOBAL_SECONDARY_MODIFY_PARTITION_DROP_VALUE, String.format("it's not support to drop value for global index[%s]", tableName)); } + + checkAllModifyListCciPartition(executionContext, tbMeta, tableName); } } } + public static void checkAllModifyListCciPartition(ExecutionContext executionContext, TableMeta tbMeta, + String tableName) { + boolean allDropTruncateCciPartition = + executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_DROP_TRUNCATE_CCI_PARTITION); + if (tbMeta.withCci() && !allDropTruncateCciPartition) { + throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_MANAGEMENT, + String.format("it's not support to drop value when table[%s] with CCI", tableName)); + } + if (tbMeta.isColumnar() && !allDropTruncateCciPartition) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_MODIFY_PARTITION_DROP_VALUE, + String.format("it's not support to drop value for columnar index[%s]", tableName)); + } + } + public static void alterTableGroupRenamePartitionCheck( SqlAlterTableRenamePartition sqlAlterTableGroupRenamePartition, TableGroupConfig tableGroupConfig, ExecutionContext executionContext) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/BackfillExecutor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/BackfillExecutor.java index 180a9860e..7d3b9baf3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/BackfillExecutor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/BackfillExecutor.java @@ -90,7 +90,7 @@ public int backfill(String schemaName, if (useChangeSet) { extractor = ChangeSetExecutor .create(schemaName, tableName, tableName, batchSize, speedMin, speedLimit, parallelism, useBinary, - null, sourcePhyTables, baseEc); + null, sourcePhyTables, false, baseEc); } else { extractor = AlterTableGroupExtractor .create(schemaName, tableName, tableName, batchSize, speedMin, speedLimit, parallelism, useBinary, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/PartitionUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/PartitionUtils.java index 063109ced..1dc7126cf 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/PartitionUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/PartitionUtils.java @@ -88,7 +88,7 @@ public static SqlNode getSqlTemplate(String schemaName, String logicalTableName, ExecutionContext ec) { TableMeta tableMeta = ec.getSchemaManager(schemaName).getTable(logicalTableName); if (DbInfoManager.getInstance().isNewPartitionDb(schemaName) && tableMeta.isGsi() && !tableMeta.isClustered() - && !tableMeta.getGsiTableMetaBean().gsiMetaBean.nonUnique) { + && !tableMeta.isHasPrimaryKey() && !tableMeta.getGsiTableMetaBean().gsiMetaBean.nonUnique) { final MySqlCreateTableStatement tableStatement = (MySqlCreateTableStatement) SQLUtils.parseStatementsWithDefaultFeatures(primaryTableDefinition, JdbcConstants.MYSQL) diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/fastchecker/AlterTableGroupFastChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/fastchecker/AlterTableGroupFastChecker.java index c732d271a..e63f997ad 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/fastchecker/AlterTableGroupFastChecker.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/fastchecker/AlterTableGroupFastChecker.java @@ -16,7 +16,6 @@ package com.alibaba.polardbx.executor.partitionmanagement.fastchecker; -import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.executor.fastchecker.FastChecker; import com.alibaba.polardbx.executor.gsi.PhysicalPlanBuilder; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; @@ -84,7 +83,7 @@ public static FastChecker create(String schemaName, String tableName, Map baseTablePks = FastChecker.getorderedPrimaryKeys(baseTableMeta); + final List baseTablePks = FastChecker.getOrderedPrimaryKeys(baseTableMeta); final PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, ec); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/fastchecker/LogicalTableDataMigrationFastChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/fastchecker/LogicalTableDataMigrationFastChecker.java index 2f17b0c93..1ade28e9f 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/fastchecker/LogicalTableDataMigrationFastChecker.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionmanagement/fastchecker/LogicalTableDataMigrationFastChecker.java @@ -18,8 +18,6 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; -import com.alibaba.polardbx.common.properties.ConnectionParams; -import com.alibaba.polardbx.executor.ddl.workqueue.BackFillThreadPool; import com.alibaba.polardbx.executor.fastchecker.FastChecker; import com.alibaba.polardbx.executor.gsi.GsiUtils; import com.alibaba.polardbx.executor.gsi.PhysicalPlanBuilder; @@ -90,7 +88,7 @@ public static List create(String logicalSchemaSrc, String logicalSc tableMetaDst.getAllColumns().stream().map(ColumnMeta::getName).collect(Collectors.toList()); // 重要:构造planSelectSampleSrc 和 planSelectSampleDst时,传入的主键必须按原本的主键顺序!!! - final List pks = FastChecker.getorderedPrimaryKeys(tableMetaDst); + final List pks = FastChecker.getOrderedPrimaryKeys(tableMetaDst); final PhysicalPlanBuilder srcBuilder = new PhysicalPlanBuilder(logicalSchemaSrc, ec); final PhysicalPlanBuilder dstBuilder = new PhysicalPlanBuilder(logicalSchemaDst, ec); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionvisualizer/PartitionsStatService.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionvisualizer/PartitionsStatService.java index 83f9e45c8..2b9b83d9a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionvisualizer/PartitionsStatService.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/partitionvisualizer/PartitionsStatService.java @@ -24,11 +24,13 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.TreeMap; import java.util.TreeSet; import java.util.stream.Collectors; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.utils.CaseInsensitive; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; @@ -178,7 +180,7 @@ public List queryPartitionsStat(boolean usePhyTableRowsCache) continue; } List partitionGroupRecords = tableGroupConfig.getPartitionGroupRecords(); - HashMap partitionPyhDbMap = new HashMap<>(); + Map partitionPyhDbMap = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); if (CollectionUtils.isNotEmpty(partitionGroupRecords)) { partitionPyhDbMap.putAll(partitionGroupRecords.stream().collect(Collectors.toMap( PartitionGroupRecord::getPartition_name, PartitionGroupRecord::getPhy_db))); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/physicalbackfill/PhysicalBackfillUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/physicalbackfill/PhysicalBackfillUtils.java index 0a331d9b1..142e6ca0c 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/physicalbackfill/PhysicalBackfillUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/physicalbackfill/PhysicalBackfillUtils.java @@ -757,8 +757,25 @@ public static Map> getSourceTableInfo(Pair> srcFileAndDirs = new HashMap<>(); + for (PolarxPhysicalBackfill.FileInfo fileInfo : getFileInfoOperator.getTableInfo().getFileInfoList()) { + Pair srcFileAndDir = Pair.of(fileInfo.getFileName(), fileInfo.getDirectory()); + srcFileAndDirs.put(fileInfo.getPartitionName(), srcFileAndDir); + } + msg = "already get the source table[" + phyDbName + "." + physicalTableName + ":]'s innodb data file"; + SQLRecorderLogger.ddlLogger.info(msg); + return srcFileAndDirs; + } + + public static PolarxPhysicalBackfill.GetFileInfoOperator checkFileExistence(Pair userInfo, + String phyDbName, + String physicalTableName, + List phyPartNames, + boolean hasNoPhyPart, + Pair sourceIpAndPort) { + PolarxPhysicalBackfill.GetFileInfoOperator getFileInfoOperator = null; boolean success = false; int tryTime = 1; boolean isPartitioned = !hasNoPhyPart; @@ -779,10 +796,6 @@ public static Map> getSourceTableInfo(Pair srcFileAndDir = Pair.of(fileInfo.getFileName(), fileInfo.getDirectory()); - srcFileAndDirs.put(fileInfo.getPartitionName(), srcFileAndDir); - } success = true; } catch (SQLException ex) { @@ -792,9 +805,7 @@ public static Map> getSourceTableInfo(Pair getTempIbdFileInfo(Pair userInfo, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/PLUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/PLUtils.java index b155252b2..885408c0e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/PLUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/PLUtils.java @@ -17,6 +17,7 @@ package com.alibaba.polardbx.executor.pl; import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.druid.sql.ast.SQLName; import com.alibaba.polardbx.druid.sql.ast.SQLStatement; @@ -104,7 +105,7 @@ public static String getPrintString(Object value) { } else { printStr = value.toString(); } - return "\"" + printStr + "\""; + return "'" + TStringUtil.escape(printStr, '\'', '\'') + "'"; } private static MemoryPool createCursorMemoryPool(PlContext procContext, MemoryPool parentMemoryPool) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/ProcedureManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/ProcedureManager.java index 4aff57836..a156846f2 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/ProcedureManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/ProcedureManager.java @@ -24,6 +24,7 @@ import com.alibaba.polardbx.druid.sql.ast.statement.SQLCreateProcedureStatement; import com.alibaba.polardbx.executor.ddl.job.task.basic.pl.PlConstants; import com.alibaba.polardbx.executor.ddl.job.task.basic.pl.accessor.ProcedureAccessor; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; import com.alibaba.polardbx.gms.metadb.pl.procedure.ProcedureDefinitionRecord; import com.alibaba.polardbx.gms.metadb.pl.procedure.ProcedureMetaRecord; import com.alibaba.polardbx.gms.util.MetaDbUtil; @@ -44,7 +45,7 @@ public class ProcedureManager { private static final Logger logger = LoggerFactory.getLogger(ProcedureManager.class); - public static ProcedureManager INSTANCE = new ProcedureManager(); + private volatile static ProcedureManager INSTANCE; /** * schema -> procedure name -> create procedure content @@ -57,11 +58,18 @@ public class ProcedureManager { long usedSpace = 0; public static ProcedureManager getInstance() { + if (INSTANCE == null) { + synchronized (ProcedureManager.class) { + if (INSTANCE == null) { + INSTANCE = new ProcedureManager(); + INSTANCE.initProcedures(); + } + } + } return INSTANCE; } private ProcedureManager() { - initProcedures(); } public synchronized void register(String schema, String procedureName) { @@ -148,6 +156,9 @@ public synchronized void unregisterWholeDb(String schema) { } private synchronized void initProcedures() { + if (MetaDbDataSource.getInstance() == null) { + return; + } try (Connection connection = MetaDbUtil.getConnection()) { ProcedureAccessor accessor = new ProcedureAccessor(); accessor.setConnection(connection); @@ -222,4 +233,8 @@ public synchronized long getUsedSize() { public synchronized long getTotalSize() { return totalSpace; } + + public synchronized long getProcedureSize() { + return procedures.values().stream().mapToLong(Map::size).sum(); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/StoredFunctionManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/StoredFunctionManager.java index b65f530bc..28a2c4198 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/StoredFunctionManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/pl/StoredFunctionManager.java @@ -44,7 +44,7 @@ public class StoredFunctionManager { private static final Logger logger = LoggerFactory.getLogger(StoredFunctionManager.class); - public static StoredFunctionManager INSTANCE = new StoredFunctionManager(); + private static StoredFunctionManager INSTANCE = new StoredFunctionManager(); Map> functions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); @@ -192,4 +192,8 @@ public synchronized long getUsedSize() { public synchronized long getTotalSize() { return totalSpace; } + + public synchronized long getUdfCount() { + return functions.size(); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/planmanagement/BaselineSyncController.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/planmanagement/BaselineSyncController.java index 9c0f80e83..2c46d0bc9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/planmanagement/BaselineSyncController.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/planmanagement/BaselineSyncController.java @@ -17,6 +17,7 @@ package com.alibaba.polardbx.executor.planmanagement; import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.executor.sync.BaselineDeleteSyncAction; import com.alibaba.polardbx.executor.sync.BaselineUpdateSyncAction; import com.alibaba.polardbx.executor.sync.DeleteBaselineSyncAction; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; @@ -45,21 +46,21 @@ public void updateBaselineSync(String schemaName, BaselineInfo baselineInfo) { @Override public void deleteBaseline(String schemaName, BaselineInfo baselineInfo) { - SyncManagerHelper.sync( - new DeleteBaselineSyncAction( + SyncManagerHelper.syncWithDefaultDB( + new BaselineDeleteSyncAction( schemaName, - baselineInfo.getParameterSql()), - schemaName, SyncScope.CURRENT_ONLY); + baselineInfo.getId()), + SyncScope.CURRENT_ONLY); } @Override public void deletePlan(String schemaName, BaselineInfo baselineInfo, PlanInfo planInfo) { - SyncManagerHelper.sync( - new DeleteBaselineSyncAction( + SyncManagerHelper.syncWithDefaultDB( + new BaselineDeleteSyncAction( schemaName, - baselineInfo.getParameterSql(), + baselineInfo.getId(), planInfo.getId()), - schemaName, SyncScope.CURRENT_ONLY); + SyncScope.CURRENT_ONLY); } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/rplchecker/LogicalTableHashCalculator.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/rplchecker/LogicalTableHashCalculator.java index bb02b4787..f8a3e01b7 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/rplchecker/LogicalTableHashCalculator.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/rplchecker/LogicalTableHashCalculator.java @@ -254,7 +254,7 @@ private PhyTableOperation preparePlanSelectHashChecker(String schemaName, String throw new TddlRuntimeException(ErrorCode.ERR_CDC_GENERIC, "failed to get table meta for table:" + schemaName + "." + tableName); } - final List baseTablePks = FastChecker.getorderedPrimaryKeys(baseTableMeta); + final List baseTablePks = FastChecker.getOrderedPrimaryKeys(baseTableMeta); final PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, ec); return builder.buildSelectHashCheckForChecker(baseTableMeta, checkColumnList, baseTablePks, withLowerBound, withUpperBound); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/ScaleOutUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/ScaleOutUtils.java index 9f34d9d3a..b98013053 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/ScaleOutUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/ScaleOutUtils.java @@ -30,15 +30,25 @@ import com.alibaba.polardbx.common.utils.thread.ThreadCpuStatUtil; import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.common.TopologyHandler; +import com.alibaba.polardbx.executor.ddl.job.converter.DdlJobDataConverter; +import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.ddl.job.task.basic.DiscardTableSpaceDdlTask; +import com.alibaba.polardbx.executor.ddl.newengine.job.DdlTask; import com.alibaba.polardbx.executor.ddl.workqueue.BackFillThreadPool; +import com.alibaba.polardbx.executor.gsi.GsiUtils; +import com.alibaba.polardbx.executor.spi.IGroupExecutor; import com.alibaba.polardbx.gms.ha.impl.StorageHaManager; import com.alibaba.polardbx.gms.ha.impl.StorageInstHaContext; import com.alibaba.polardbx.gms.listener.impl.MetaDbConfigManager; import com.alibaba.polardbx.gms.listener.impl.MetaDbDataIdBuilder; import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.node.GmsNodeManager; import com.alibaba.polardbx.gms.topology.DbGroupInfoAccessor; +import com.alibaba.polardbx.gms.topology.DbGroupInfoManager; import com.alibaba.polardbx.gms.topology.DbGroupInfoRecord; +import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.gms.topology.DbTopologyManager; +import com.alibaba.polardbx.gms.util.GroupInfoUtil; import com.alibaba.polardbx.gms.util.InstIdUtil; import com.alibaba.polardbx.gms.util.MetaDbLogUtil; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; @@ -63,6 +73,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import java.text.MessageFormat; import java.time.Instant; import java.util.ArrayList; @@ -70,6 +81,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import java.util.stream.IntStream; public class ScaleOutUtils { @@ -77,6 +89,8 @@ public class ScaleOutUtils { public static final int RETRY_COUNT = 3; public static final long[] RETRY_WAIT = new long[RETRY_COUNT]; + public static int QUERY_TIMEOUT = 600; + static { IntStream.range(0, RETRY_COUNT).forEach(i -> RETRY_WAIT[i] = Math.round(Math.pow(2, i))); } @@ -89,6 +103,9 @@ public class ScaleOutUtils { // 不能和逻辑表的backfill共用一个线程池,防止死锁,因为backfill是其子任务 private static final BackFillThreadPool LOGICAL_TABLE_PARALLEL_INSTANCE_POOL = new BackFillThreadPool(); + private static final String CHECK_TABLE_EXISTENCE = + "SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?"; + private static SqlNode getSqlTemplate(String primaryTableDefinition, ExecutionContext ec) { final SqlCreateTable primaryTableNode = (SqlCreateTable) new FastsqlParser() .parse(primaryTableDefinition) @@ -322,13 +339,47 @@ public static int getScaleoutTaskParallelism(ExecutionContext ec) { return getScaleoutTaskParallelismImpl(ec, ConnectionParams.SCALEOUT_TASK_PARALLELISM); } + public static boolean checkTableExistence(String schemaName, String groupName, String physicalTb) { + IGroupExecutor ge = null; + DbGroupInfoRecord record = DbGroupInfoManager.getInstance().queryGroupInfo(schemaName, groupName); + String physicalDb = record.phyDbName; + try { + ExecutorContext ec = ExecutorContext.getContext(schemaName); + ge = ec.getTopologyExecutor().getGroupExecutor(groupName); + } catch (Throwable e) { + throw GeneralUtil.nestedException( + String.format("query group %s with check table %s.%s existence failed: %s", groupName, physicalTb, + physicalTb, e.getMessage()), e); + } + + try (Connection conn = ge.getDataSource().getConnection(); + PreparedStatement pstmt = conn.prepareStatement(CHECK_TABLE_EXISTENCE)) { + pstmt.setString(1, physicalDb); + pstmt.setString(2, physicalTb); + pstmt.setQueryTimeout(QUERY_TIMEOUT); + + try (ResultSet rs = pstmt.executeQuery()) { + if (rs.next()) { + return true; + } + } + } catch (Throwable e) { + // 注意:这里对异常信息的处理应避免泄露过多细节,特别是在线上环境中 + throw GeneralUtil.nestedException("Error checking table existence for " + physicalDb + "." + physicalTb, e); + } + + return false; + + } + /** - * Min(NumCpuCores, Max(4, NumStorageNodes * 2)) + * Min(NumCpuCores, Max(8, NumStorageNodes * 2)) * NumComputeNodes */ private static int getScaleoutTaskParallelismImpl(ExecutionContext ec, LongConfigParam param) { - final int minParallelism = 4; long parallelism = ec.getParamManager().getLong(param); - if (parallelism > 0) { + int numComputeNode = GsiUtils.getAvaliableNodeNum(null, null, + ec); + if (parallelism > 0 && numComputeNode < 2) { return (int) parallelism; } int numCpuCores = ThreadCpuStatUtil.NUM_CORES; @@ -338,6 +389,42 @@ private static int getScaleoutTaskParallelismImpl(ExecutionContext ec, LongConfi .filter(StorageInstHaContext::isAllReplicaReady) .count(); numStorageNodes = Math.max(1, numStorageNodes); - return Math.min(numCpuCores, Math.max(minParallelism, numStorageNodes * 2)); + final int minParallelism = 10; + final int maxParallelism = 16; + return Math.min(Math.max(numCpuCores, minParallelism), maxParallelism) * Math.max(numComputeNode, numStorageNodes); + } + + public static int getTaskPipelineSize(ExecutionContext ec) { + long pipelineSize = ec.getParamManager().getLong(ConnectionParams.PHYSICAL_BACKFILL_PIPELINE_SIZE); + if (pipelineSize > 0) { + return (int) pipelineSize; + } + return getTableGroupTaskParallelism(ec); + } + + public static List generateDiscardTableSpaceDdlTask(String schemaName, + Map>> tableTopology, + List discardTableSpaceOperations, + ExecutionContext executionContext) { + List tasks = new ArrayList<>(); + Map groupNameToStorageInstMap = DbTopologyManager.getGroupNameToStorageInstIdMap(schemaName); + for (Map.Entry>> entry : tableTopology.entrySet()) { + String groupName = entry.getKey(); + String storageInst = groupNameToStorageInstMap.get(groupName); + List> physicalTbs = entry.getValue(); + Map>> newTableTopology = new HashMap<>(); + newTableTopology.put(groupName, physicalTbs); + List newDiscardTableSpaceOperations = + discardTableSpaceOperations.stream().filter(o -> o.getDbIndex().equalsIgnoreCase(groupName)).collect( + Collectors.toList()); + PhysicalPlanData physicalPlanData = + DdlJobDataConverter.convertToPhysicalPlanData(newTableTopology, newDiscardTableSpaceOperations, + executionContext); + DdlTask phyDdlTask = + new DiscardTableSpaceDdlTask(schemaName, physicalPlanData.getLogicalTableName(), storageInst, + physicalPlanData); + tasks.add(phyDdlTask); + } + return tasks; } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/backfill/BackfillExecutor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/backfill/BackfillExecutor.java index 15a0c17e5..004f3636b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/backfill/BackfillExecutor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/backfill/BackfillExecutor.java @@ -67,7 +67,7 @@ public int backfill(String schemaName, String tableName, ExecutionContext baseEc if (isChangeSet) { extractor = ChangeSetExecutor .create(schemaName, tableName, tableName, batchSize, speedMin, speedLimit, parallelism, useBinary, - null, sourcePhyTables, baseEc); + null, sourcePhyTables, false, baseEc); } else { extractor = MoveTableExtractor .create(schemaName, tableName, batchSize, speedMin, speedLimit, parallelism, useBinary, sourcePhyTables, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/backfill/ChangeSetExecutor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/backfill/ChangeSetExecutor.java index 011604d2c..5d00c2993 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/backfill/ChangeSetExecutor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/backfill/ChangeSetExecutor.java @@ -351,7 +351,7 @@ public void buildBatchParamAndLoad(Cursor cursor, String dbIndex, String phyTabl batchParams.clear(); } while (!finished); - DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set(0); +// DdlEngineStats.METRIC_BACKFILL_ROWS_SPEED.set(0); reporter.addBackfillCount(successRowCount); SQLRecorderLogger.ddlLogger.warn(MessageFormat.format("[{0}] Last backfill row for {1}[{2}][{3}]: {4}", @@ -394,7 +394,7 @@ public void statsAddBackFillRows(ExecutionContext ec, List modifyStringColumns, Map> sourcePhyTables, - ExecutionContext ec) { + boolean onlineModifyColumn, ExecutionContext ec) { final PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, useBinary, modifyStringColumns, ec); - ExtractorInfo info = Extractor.buildExtractorInfo(ec, schemaName, sourceTableName, targetTableName, false); + ExtractorInfo info = + Extractor.buildExtractorInfo(ec, schemaName, sourceTableName, targetTableName, false, false, + onlineModifyColumn); SqlSelect.LockMode lockMode = SqlSelect.LockMode.UNDEF; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/fastchecker/MoveTableFastChecker.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/fastchecker/MoveTableFastChecker.java index 20bb70158..f46699ae1 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/fastchecker/MoveTableFastChecker.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scaleout/fastchecker/MoveTableFastChecker.java @@ -18,8 +18,6 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; -import com.alibaba.polardbx.common.properties.ConnectionParams; -import com.alibaba.polardbx.executor.ddl.workqueue.BackFillThreadPool; import com.alibaba.polardbx.executor.fastchecker.FastChecker; import com.alibaba.polardbx.executor.gsi.PhysicalPlanBuilder; import com.alibaba.polardbx.optimizer.OptimizerContext; @@ -77,7 +75,7 @@ public static FastChecker create(String schemaName, String tableName, tableMeta.getAllColumns().stream().map(ColumnMeta::getName).collect(Collectors.toList()); // 重要:构造planSelectSampleSrc 和 planSelectSampleDst时,传入的主键必须按原本的主键顺序!!! - final List pks = FastChecker.getorderedPrimaryKeys(tableMeta); + final List pks = FastChecker.getOrderedPrimaryKeys(tableMeta); final PhysicalPlanBuilder builder = new PhysicalPlanBuilder(schemaName, ec); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/ScheduledJobsManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/ScheduledJobsManager.java index 9c2743655..4ed99cccc 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/ScheduledJobsManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/ScheduledJobsManager.java @@ -149,6 +149,8 @@ public static ScheduledJobsManager getInstance() { private static final Map executingMap = new ConcurrentHashMap<>(); private ScheduledJobsManager() { + + // ScheduledJobsCleaner: clean scannerThread.scheduleWithFixedDelay( AsyncTask.build( () -> { @@ -161,6 +163,10 @@ private ScheduledJobsManager() { TimeUnit.SECONDS ); + /** + * ScheduledJobsCleaner: + * use to actively clear succ/failed/skiped jobs from fired_scheduled_jobs table of metadb + */ cleanerThread.scheduleWithFixedDelay( AsyncTask.build(new ScheduledJobsCleaner()), 0L, @@ -168,6 +174,11 @@ private ScheduledJobsManager() { TimeUnit.HOURS ); + /** + * ScheduledJobsSafeExitChecker: + * use to actively clear the running-state jobs from fired_scheduled_jobs table of metadb, + * but is not running because of restarting cn + */ safeExitThread.scheduleWithFixedDelay( AsyncTask.build(new ScheduledJobsSafeExitChecker()), 0L, @@ -175,6 +186,10 @@ private ScheduledJobsManager() { TimeUnit.SECONDS ); + /** + * ScheduledJobsAutoInterruptChecker: + * use to actively soft interrupt running jobs if curr time is out of maintain-time window + */ autoInterruptThread.scheduleWithFixedDelay( AsyncTask.build(new ScheduledJobsAutoInterruptChecker()), 0L, @@ -378,6 +393,13 @@ protected Integer invoke() { if (esj == null) { continue; } + + /** + * if a running-state job is not in the map of executingJobs, + * that mean the running-job maybe kill by leader-cn restarting, + * so here need call the esj.safeExit() to notify the running-state + * job to auto exit safely( such as send "pause ddl xxx"). + */ if (esj.needInterrupted().getKey() && esj.safeExit()) { //mark as fail ScheduledJobsManager.updateState(scheduleId, fireTime, INTERRUPTED, @@ -882,4 +904,25 @@ protected List invoke() { } }.execute(); } + + public static List getScheduledJobByTableNameAndExecutorType( + String tableSchema, + String tableName, + String executorType) { + return new ScheduledJobsAccessorDelegate>() { + @Override + protected List invoke() { + return scheduledJobsAccessor.query(tableSchema, tableName, executorType); + } + }.execute(); + } + + public static String queryLatestRemark(long schedulerId) { + return new ScheduledJobsAccessorDelegate() { + @Override + protected String invoke() { + return firedScheduledJobsAccessor.queryLatestRemarkById(schedulerId); + } + }.execute(); + } } \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/CheckCciScheduledJob.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/CheckCciScheduledJob.java new file mode 100644 index 000000000..5476f0d0d --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/CheckCciScheduledJob.java @@ -0,0 +1,243 @@ +package com.alibaba.polardbx.executor.scheduler.executor; + +import com.alibaba.fastjson.JSON; +import com.alibaba.polardbx.common.IInnerConnection; +import com.alibaba.polardbx.common.eventlogger.EventLogger; +import com.alibaba.polardbx.common.eventlogger.EventType; +import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.logger.MDC; +import com.alibaba.polardbx.common.utils.version.InstanceVersion; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.executor.scheduler.executor.trx.CleanLogTableScheduledJob; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; +import com.alibaba.polardbx.gms.module.Module; +import com.alibaba.polardbx.gms.module.ModuleLogInfo; +import com.alibaba.polardbx.gms.scheduler.ExecutableScheduledJob; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import lombok.Data; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.FAILED; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.QUEUED; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.RUNNING; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.SUCCESS; +import static com.alibaba.polardbx.gms.module.LogLevel.CRITICAL; +import static com.alibaba.polardbx.gms.module.LogLevel.WARNING; +import static com.alibaba.polardbx.gms.module.LogPattern.STATE_CHANGE_FAIL; +import static com.alibaba.polardbx.gms.module.LogPattern.UNEXPECTED; +import static com.alibaba.polardbx.gms.scheduler.ScheduledJobExecutorType.CHECK_CCI; +import static com.alibaba.polardbx.gms.topology.SystemDbHelper.DEFAULT_DB_NAME; + +public class CheckCciScheduledJob extends SchedulerExecutor { + private static final Logger logger = LoggerFactory.getLogger(CleanLogTableScheduledJob.class); + + private final ExecutableScheduledJob executableScheduledJob; + + public CheckCciScheduledJob(ExecutableScheduledJob executableScheduledJob) { + this.executableScheduledJob = executableScheduledJob; + } + + @Override + public boolean execute() { + long scheduleId = executableScheduledJob.getScheduleId(); + long fireTime = executableScheduledJob.getFireTime(); + long startTime = ZonedDateTime.now().toEpochSecond(); + + try { + // Mark as RUNNING. + boolean casSuccess = + ScheduledJobsManager.casStateWithStartTime(scheduleId, fireTime, QUEUED, RUNNING, startTime); + if (!casSuccess) { + ModuleLogInfo.getInstance() + .logRecord( + Module.SCHEDULE_JOB, + STATE_CHANGE_FAIL, + new String[] {CHECK_CCI + "," + fireTime, QUEUED.name(), RUNNING.name()}, + WARNING); + return false; + } + + final Map savedMdcContext = MDC.getCopyOfContextMap(); + String remark; + try { + MDC.put(MDC.MDC_KEY_APP, DEFAULT_DB_NAME); + // check cci + remark = doCheckIfNecessary(); + } finally { + MDC.setContextMap(savedMdcContext); + } + + long finishTime = System.currentTimeMillis() / 1000; + return ScheduledJobsManager + .casStateWithFinishTime(scheduleId, fireTime, RUNNING, SUCCESS, finishTime, remark); + } catch (Throwable t) { + logger.error(t); + ModuleLogInfo.getInstance() + .logRecord( + Module.TRX, + UNEXPECTED, + new String[] { + CHECK_CCI + "," + fireTime, + t.getMessage() + }, + CRITICAL, + t + ); + String remark = "Check cci task error: " + t.getMessage(); + ScheduledJobsManager.updateState(scheduleId, fireTime, FAILED, remark, t.getMessage()); + return false; + } + } + + private String doCheckIfNecessary() throws SQLException { + if (!InstanceVersion.isMYSQL80() || DynamicConfig.getInstance().isSkipCheckCciScheduleJob()) { + return null; + } + ExecutorContext executorContext = ExecutorContext.getContext(DEFAULT_DB_NAME); + // Get last task status. + String lastStatusRemark = ScheduledJobsManager.queryLatestRemark(executableScheduledJob.getScheduleId()); + Status lastStatus = null; + try { + lastStatus = JSON.parseObject(lastStatusRemark, Status.class); + } catch (Throwable t) { + logger.error("Parse last status failed: " + lastStatusRemark, t); + } + long lastCheckTso = lastStatus == null ? 0 : lastStatus.lastCheckTso; + long lastFullyCheckTso = lastStatus == null ? 0 : lastStatus.lastFullyCheckTso; + + // Get latest forced checkpoints. + List> columnarAndInnodbTso = new ArrayList<>(); + long checkpointLimit = DynamicConfig.getInstance().getCheckCciCheckpointLimit(); + checkpointLimit = Math.max(1, checkpointLimit); + checkpointLimit = Math.min(100, checkpointLimit); + List> cciList = new ArrayList<>(); + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarCheckpointsAccessor accessor1 = new ColumnarCheckpointsAccessor(); + accessor1.setConnection(connection); + accessor1.queryLatestForcedCheckpoints(lastCheckTso, checkpointLimit).forEach( + record -> columnarAndInnodbTso.add(new Pair<>(record.checkpointTso, record.binlogTso)) + ); + + if (columnarAndInnodbTso.isEmpty()) { + return emptyStatus(executorContext, lastFullyCheckTso, "No checkpoints found. Mark it success."); + } + + // Get all cci. + ColumnarTableMappingAccessor accessor2 = new ColumnarTableMappingAccessor(); + accessor2.setConnection(connection); + accessor2.queryAllSnapshotCci() + .forEach(record -> cciList.add(new Pair<>(record.tableSchema.toLowerCase(), record.indexName))); + + if (cciList.isEmpty()) { + return emptyStatus(executorContext, lastFullyCheckTso, "No cci found. Mark it success."); + } + } + + // Check these cci. + StringBuilder statusStr = new StringBuilder(); + long maxTso = lastFullyCheckTso; + for (Pair tsoPair : columnarAndInnodbTso) { + long columnarTso = tsoPair.getKey(); + long innodbTso = tsoPair.getValue(); + long fullyDiffMs = (columnarTso - lastFullyCheckTso) >> 22; + long diffMs = (columnarTso - lastCheckTso) >> 22; + Collections.shuffle(cciList); + boolean success = true; + boolean skip = false; + for (Pair schemaAndTableIndex : cciList) { + try (IInnerConnection connection = executorContext.getInnerConnectionManager() + .getConnection(schemaAndTableIndex.getKey()); + Statement stmt = connection.createStatement()) { + if ((fullyDiffMs > 24 * 60 * 60 * 1000 || diffMs > 30 * 60 * 1000) + && InstConfUtil.isInMaintenanceTimeWindow()) { + // fully snapshot check + ResultSet rs = stmt.executeQuery("CHECK COLUMNAR INDEX " + schemaAndTableIndex.getValue() + + " SNAPSHOT " + innodbTso + " " + columnarTso); + if (!processDetails(rs, schemaAndTableIndex.getKey(), schemaAndTableIndex.getValue())) { + success = false; + } else { + maxTso = Math.max(maxTso, columnarTso); + } + } else if (diffMs < 30 * 60 * 1000) { + // incremental check + ResultSet rs = stmt.executeQuery("CHECK COLUMNAR INDEX " + schemaAndTableIndex.getValue() + + " INCREMENT " + lastCheckTso + " " + columnarTso + " " + innodbTso); + if (!processDetails(rs, schemaAndTableIndex.getKey(), schemaAndTableIndex.getValue())) { + success = false; + } + } else { + // just skip this check + logger.warn("Skip check cci " + schemaAndTableIndex.getKey() + "." + + schemaAndTableIndex.getValue() + " due to diffMs: " + diffMs); + skip = true; + } + } + } + // Update columnar_checkpoints. + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarCheckpointsAccessor accessor = new ColumnarCheckpointsAccessor(); + accessor.setConnection(connection); + accessor.updateExtraByTso((success ? "success" : "fail") + (skip ? "(some skipped)" : ""), columnarTso); + } + statusStr.append("Check cci ").append(success ? "success" : "fail").append(skip ? "(some skipped);" : ";"); + } + Status newStatus = new Status(); + newStatus.status = statusStr.toString(); + newStatus.lastCheckTso = columnarAndInnodbTso.get(0).getKey(); + newStatus.lastFullyCheckTso = maxTso; + return JSON.toJSONString(newStatus); + } + + private static String emptyStatus(ExecutorContext executorContext, long lastFullyCheckTso, String status) { + Status newStatus = new Status(); + newStatus.status = status; + newStatus.lastCheckTso = executorContext.getTransactionManager().getTimestampOracle().nextTimestamp(); + newStatus.lastFullyCheckTso = 0 == lastFullyCheckTso ? newStatus.lastCheckTso : lastFullyCheckTso; + return JSON.toJSONString(newStatus); + } + + private boolean processDetails(ResultSet rs, String schema, String index) throws SQLException { + StringBuilder errMsg = null; + if (rs.next()) { + String detail = rs.getString("DETAILS"); + if (null == detail || !detail.startsWith("OK")) { + // fail + errMsg = new StringBuilder("Check cci " + schema + "." + index + " failed. Details: " + detail + ";"); + while (rs.next()) { + errMsg.append(rs.getString("DETAILS")).append(";"); + } + } + } else { + // fail + errMsg = new StringBuilder("Check cci " + schema + "." + index + " failed. No results found."); + } + if (null != errMsg) { + logger.error(errMsg.toString()); + EventLogger.log(EventType.COLUMNAR_ERR, errMsg.toString()); + return false; + } + return true; + } + + @Data + private static class Status { + public String status; + public long lastCheckTso; + public long lastFullyCheckTso; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/LocalPartitionScheduledJob.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/LocalPartitionScheduledJob.java index 2dad86578..67896ff91 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/LocalPartitionScheduledJob.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/LocalPartitionScheduledJob.java @@ -51,9 +51,7 @@ import java.time.ZonedDateTime; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; @@ -85,9 +83,11 @@ public class LocalPartitionScheduledJob extends SchedulerExecutor { private static final Logger logger = LoggerFactory.getLogger(LocalPartitionScheduledJob.class); - private static final String ALLOCATE_LOCAL_PARTITION = "ALTER TABLE %s ALLOCATE LOCAL PARTITION"; - private static final String EXPIRE_LOCAL_PARTITION = "ALTER TABLE %s EXPIRE LOCAL PARTITION %s"; - private static final String EXPIRE_LOCAL_PARTITION_PREFIX = "ALTER TABLE %s EXPIRE LOCAL PARTITION"; + private static final String ALLOCATE_LOCAL_PARTITION = + "/*SCHEDULE_JOB_DDL*/ALTER TABLE %s ALLOCATE LOCAL PARTITION"; + private static final String EXPIRE_LOCAL_PARTITION = "/*SCHEDULE_JOB_DDL*/ALTER TABLE %s EXPIRE LOCAL PARTITION %s"; + private static final String EXPIRE_LOCAL_PARTITION_PREFIX = + "/*SCHEDULE_JOB_DDL*/ALTER TABLE %s EXPIRE LOCAL PARTITION"; private final ExecutableScheduledJob executableScheduledJob; @@ -128,6 +128,7 @@ public boolean execute() { Pair needInterruption; + // Fetch all paused ddl-job List pausedDdlJobIdList = getCurrentDdlSqlList(tableSchema, tableName, new DdlState[] {DdlState.PAUSED}); @@ -144,7 +145,9 @@ public boolean execute() { } } + // build new ddl sql list List ddlSqlList = getDdlSqlList(repository, tableSchema, tableName, timeZone); + // exec new ddl sql list for (String ddlSql : ddlSqlList) { needInterruption = needInterrupted(); if (needInterruption.getKey()) { @@ -385,4 +388,4 @@ private String genRemark(List pre, List>> metrics = + GmsSyncManagerHelper.sync(new MetricSyncAction(), "polardbx", SyncScope.CURRENT_ONLY); + FeatureStats fs = FeatureStats.build(); + List mergeList = Lists.newArrayList(); + for (List> metric : metrics) { + for (Map map : metric) { + String json = (String) map.get(MetricSyncAction.JSON_KEY); + mergeList.add(FeatureStats.deserialize(json)); + } + } + FeatureStats.merge(fs, mergeList); + String incrementLog = fs.log(); + + // real-time information + Incremental information + String log = statLog() + incrementLog; + EventLogger.log(EventType.METRICS, log); + ModuleLogInfo.getInstance().logRecord(Module.METRIC, LogPattern.PROCESS_END, + new String[] {"feature metric log", log}, NORMAL); + //mark as SUCCESS + succeedExit(scheduleId, fireTime, remark); + } catch (Throwable t) { + ModuleLogInfo.getInstance() + .logRecord( + Module.STATISTICS, + UNEXPECTED, + new String[] { + LOG_SYSTEM_METRICS + "," + fireTime, + t.getMessage() + }, + CRITICAL, + t); + errorExit(scheduleId, fireTime, t.getMessage()); + return false; + } + return true; + } + + protected boolean markRunning(long scheduleId, long fireTime, long startTime) { + return ScheduledJobsManager.casStateWithStartTime(scheduleId, fireTime, QUEUED, RUNNING, startTime); + } + + protected void errorExit(long scheduleId, long fireTime, String error) { + //mark as fail + ScheduledJobsManager.updateState(scheduleId, fireTime, FAILED, null, error); + // alert + OptimizerAlertUtil.statisticErrorAlert(); + } + + protected boolean succeedExit(long scheduleId, long fireTime, String remark) { + long finishTime = System.currentTimeMillis() / 1000; + //mark as SUCCESS + return ScheduledJobsManager.casStateWithFinishTime(scheduleId, fireTime, RUNNING, SUCCESS, finishTime, remark); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/ScheduleJobStarter.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/ScheduleJobStarter.java index 180ed0213..988b30d11 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/ScheduleJobStarter.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/ScheduleJobStarter.java @@ -44,6 +44,39 @@ public static void launchAll() { initCleanLogTableJob(); initPersistGsiStatisticJob(); initOptimizerAlertJob(); + initStatisticInfoSchemaTablesJob(); + initLogMetricJob(); + initGenerateColumnarSnapshotJob(); + initCheckCciJob(); + } + + private static void initLogMetricJob() { + String tableSchema = VisualConstants.VISUAL_SCHEMA_NAME; + String tableName = VisualConstants.DUAL_TABLE_NAME; + String cronExpr = "0 0 0 * * ?"; + String timeZone = "+08:00"; + ScheduledJobsRecord scheduledJobsRecord = ScheduledJobsManager.createQuartzCronJob( + tableSchema, + null, + tableName, + ScheduledJobExecutorType.LOG_SYSTEM_METRICS, + cronExpr, + timeZone, + SchedulePolicy.SKIP + ); + int count = new ScheduledJobsAccessorDelegate() { + @Override + protected Integer invoke() { + List list = + scheduledJobsAccessor.queryByExecutorType(scheduledJobsRecord.getExecutorType()); + if (list.size() > 0) { + logger.warn("Scheduled Job For LOG_SYSTEM_METRICS Has Exist"); + return 0; + } + return scheduledJobsAccessor.insertIgnoreFail(scheduledJobsRecord); + } + }.execute(); + logger.info(String.format("Init %s Success %s", scheduledJobsRecord.getExecutorType(), count)); } private static void initBaselineSyncJob() { @@ -280,4 +313,93 @@ protected Integer invoke() { }.execute(); logger.info(String.format("Init %s Success %s", scheduledJobsRecord.getExecutorType(), count)); } + + private static void initCheckCciJob() { + // Init new clean job. + String tableSchema = VisualConstants.VISUAL_SCHEMA_NAME; + String tableName = VisualConstants.DUAL_TABLE_NAME; + String cronExpr = "0 0/1 * * * ? "; + String timeZone = "+08:00"; + ScheduledJobsRecord scheduledJobsRecord = ScheduledJobsManager.createQuartzCronJob( + tableSchema, + null, + tableName, + ScheduledJobExecutorType.CHECK_CCI, + cronExpr, + timeZone, + SchedulePolicy.SKIP + ); + int count = new ScheduledJobsAccessorDelegate() { + @Override + protected Integer invoke() { + List list = + scheduledJobsAccessor.queryByExecutorType(scheduledJobsRecord.getExecutorType()); + if (list.size() > 0) { + logger.warn("Scheduled Job For CHECK_CCI Has Exist"); + return 0; + } + return scheduledJobsAccessor.insertIgnoreFail(scheduledJobsRecord); + } + }.execute(); + logger.info(String.format("Init %s Success %s", scheduledJobsRecord.getExecutorType(), count)); + } + + private static void initGenerateColumnarSnapshotJob() { + // Init new clean job. + String tableSchema = VisualConstants.VISUAL_SCHEMA_NAME; + String tableName = VisualConstants.DUAL_TABLE_NAME; + String cronExpr = "0 0/1 * * * ? "; + String timeZone = "+08:00"; + ScheduledJobsRecord scheduledJobsRecord = ScheduledJobsManager.createQuartzCronJob( + tableSchema, + null, + tableName, + ScheduledJobExecutorType.GENERATE_COLUMNAR_SNAPSHOT, + cronExpr, + timeZone, + SchedulePolicy.SKIP + ); + int count = new ScheduledJobsAccessorDelegate() { + @Override + protected Integer invoke() { + List list = + scheduledJobsAccessor.queryByExecutorType(scheduledJobsRecord.getExecutorType()); + if (list.size() > 0) { + logger.warn("Scheduled Job For GENERATE_COLUMNAR_SNAPSHOT Has Exist"); + return 0; + } + return scheduledJobsAccessor.insertIgnoreFail(scheduledJobsRecord); + } + }.execute(); + logger.info(String.format("Init %s Success %s", scheduledJobsRecord.getExecutorType(), count)); + } + + private static void initStatisticInfoSchemaTablesJob() { + String tableSchema = VisualConstants.VISUAL_SCHEMA_NAME; + String tableName = VisualConstants.DUAL_TABLE_NAME; + String cronExpr = "0 15 * * * ?"; + String timeZone = "+08:00"; + ScheduledJobsRecord scheduledJobsRecord = ScheduledJobsManager.createQuartzCronJob( + tableSchema, + null, + tableName, + ScheduledJobExecutorType.STATISTIC_INFO_SCHEMA_TABLES, + cronExpr, + timeZone, + SchedulePolicy.SKIP + ); + int count = new ScheduledJobsAccessorDelegate() { + @Override + protected Integer invoke() { + List list = + scheduledJobsAccessor.queryByExecutorType(scheduledJobsRecord.getExecutorType()); + if (list.size() > 0) { + logger.warn("Scheduled Job For STATISTIC_INFO_SCHEMA_TABLES Has Exist"); + return 0; + } + return scheduledJobsAccessor.insertIgnoreFail(scheduledJobsRecord); + } + }.execute(); + logger.info(String.format("Init %s Success %s", scheduledJobsRecord.getExecutorType(), count)); + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/SchedulerExecutor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/SchedulerExecutor.java index dd0d940a4..a85a30dda 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/SchedulerExecutor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/SchedulerExecutor.java @@ -16,17 +16,18 @@ package com.alibaba.polardbx.executor.scheduler.executor; -import com.alibaba.polardbx.executor.scheduler.executor.statistic.StatisticHllScheduledJob; -import com.alibaba.polardbx.executor.scheduler.executor.trx.CleanLogTableScheduledJob; -import com.alibaba.polardbx.gms.scheduler.ScheduledJobExecutorType; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.timezone.InternalTimeZone; import com.alibaba.polardbx.executor.scheduler.executor.spm.SPMBaseLineSyncScheduledJob; +import com.alibaba.polardbx.executor.scheduler.executor.statistic.StatisticHllScheduledJob; +import com.alibaba.polardbx.executor.scheduler.executor.statistic.StatisticInfoSchemaTablesScheduleJob; import com.alibaba.polardbx.executor.scheduler.executor.statistic.StatisticRowCountCollectionScheduledJob; import com.alibaba.polardbx.executor.scheduler.executor.statistic.StatisticSampleCollectionScheduledJob; import com.alibaba.polardbx.executor.scheduler.executor.trx.CleanLogTableScheduledJob; +import com.alibaba.polardbx.executor.scheduler.executor.trx.GenerateColumnarSnapshotScheduledJob; import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.scheduler.ExecutableScheduledJob; +import com.alibaba.polardbx.gms.scheduler.ScheduledJobExecutorType; import com.alibaba.polardbx.optimizer.config.server.DefaultServerConfigManager; import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager; import com.alibaba.polardbx.optimizer.utils.OptimizerHelper; @@ -34,6 +35,7 @@ import java.util.List; import java.util.Map; +import java.util.Random; public abstract class SchedulerExecutor { @@ -45,6 +47,11 @@ public static SchedulerExecutor createSchedulerExecutor(ExecutableScheduledJob j if (StringUtils.equalsIgnoreCase(job.getExecutorType(), ScheduledJobExecutorType.LOCAL_PARTITION.name())) { return new LocalPartitionScheduledJob(job); } + + if (StringUtils.equalsIgnoreCase(job.getExecutorType(), ScheduledJobExecutorType.TTL_JOB.name())) { + return new TtlArchivedDataScheduledJob(job); + } + if (StringUtils.equalsIgnoreCase(job.getExecutorType(), ScheduledJobExecutorType.PURGE_OSS_FILE.name())) { return new PurgeOssFileScheduledJob(job); } @@ -94,6 +101,26 @@ public static SchedulerExecutor createSchedulerExecutor(ExecutableScheduledJob j ScheduledJobExecutorType.CLEAN_LOG_TABLE_V2.name())) { return new CleanLogTableScheduledJob(job); } + + if (StringUtils.equalsIgnoreCase(job.getExecutorType(), + ScheduledJobExecutorType.CHECK_CCI.name())) { + return new CheckCciScheduledJob(job); + } + + if (StringUtils.equalsIgnoreCase(job.getExecutorType(), + ScheduledJobExecutorType.GENERATE_COLUMNAR_SNAPSHOT.name())) { + return new GenerateColumnarSnapshotScheduledJob(job); + } + + if (StringUtils.equalsIgnoreCase(job.getExecutorType(), + ScheduledJobExecutorType.STATISTIC_INFO_SCHEMA_TABLES.name())) { + return new StatisticInfoSchemaTablesScheduleJob(job); + } + + if (StringUtils.equalsIgnoreCase(job.getExecutorType(), + ScheduledJobExecutorType.LOG_SYSTEM_METRICS.name())) { + return new LogSystemMetricsScheduledJob(job); + } return null; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/TtlArchivedDataScheduledJob.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/TtlArchivedDataScheduledJob.java new file mode 100644 index 000000000..fdd674bb8 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/TtlArchivedDataScheduledJob.java @@ -0,0 +1,514 @@ +package com.alibaba.polardbx.executor.scheduler.executor; + +import com.alibaba.polardbx.common.ddl.newengine.DdlState; +import com.alibaba.polardbx.common.scheduler.FiredScheduledJobState; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.timezone.InternalTimeZone; +import com.alibaba.polardbx.common.utils.timezone.TimeZoneUtils; +import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlTaskSqlBuilder; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler.TtlScheduledJobManager; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlLoggerUtil; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler.TtlScheduledJobStatManager; +import com.alibaba.polardbx.executor.ddl.newengine.meta.DdlEngineSchedulerManager; +import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.gms.metadb.misc.DdlEngineRecord; +import com.alibaba.polardbx.gms.module.Module; +import com.alibaba.polardbx.gms.module.ModuleLogInfo; +import com.alibaba.polardbx.gms.scheduler.ExecutableScheduledJob; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; +import com.alibaba.polardbx.repo.mysql.handler.ddl.newengine.DdlEngineShowJobsHandler; + +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.FAILED; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.RUNNING; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.SUCCESS; +import static com.alibaba.polardbx.gms.module.LogLevel.CRITICAL; +import static com.alibaba.polardbx.gms.module.LogLevel.NORMAL; +import static com.alibaba.polardbx.gms.module.LogPattern.INTERRUPTED; +import static com.alibaba.polardbx.gms.module.LogPattern.PROCESS_END; +import static com.alibaba.polardbx.gms.module.LogPattern.UNEXPECTED; +import static com.alibaba.polardbx.gms.scheduler.ScheduledJobExecutorType.TTL_JOB; + +/** + * TTL Table scheduled job + * + * @author chenghui.lch + */ +public class TtlArchivedDataScheduledJob extends SchedulerExecutor { + private static final Logger logger = LoggerFactory.getLogger(TtlArchivedDataScheduledJob.class); + private final ExecutableScheduledJob executableScheduledJob; + + public TtlArchivedDataScheduledJob(final ExecutableScheduledJob executableScheduledJob) { + this.executableScheduledJob = executableScheduledJob; + } + + public long getScheduleId() { + return this.executableScheduledJob.getScheduleId(); + } + + @Override + public boolean execute() { + final String tableSchema = executableScheduledJob.getTableSchema(); + final String timeZoneStr = executableScheduledJob.getTimeZone(); + final String tableName = executableScheduledJob.getTableName(); + final InternalTimeZone timeZone = TimeZoneUtils.convertFromMySqlTZ(timeZoneStr); + final long scheduleId = executableScheduledJob.getScheduleId(); + final long fireTime = executableScheduledJob.getFireTime(); + final long startTime = ZonedDateTime.now().toEpochSecond(); + + try { + + logTtlScheduledJob(String.format("TtlScheduledJob[%s.%s] start.", tableSchema, tableName), null, false, + false); + + /** + * Stop all ttl-job scheduled + */ + if (TtlConfigUtil.isStopAllTtlTableJobScheduling()) { + /** + * If NOT allowed scheduling, just return directly with QUEUED-STATE + */ + logTtlScheduledJob( + String.format("All ttl jobs is not allowed scheduling, so ignore and queue to exec."), null, false, + false); + return false; + } + + /** + * ask ttl job manager if allowed running curr job + */ + boolean allowedRunningNow = applyForRunning(); + if (!allowedRunningNow) { + /** + * If NOT allowed, just return directly with QUEUED-STATE + */ + logTtlScheduledJob( + String.format("Failed to apply running, so ignore and queue to exec."), null, false, false); + return false; + } + + // Fetch all ddl-job + List allDdlRecList = + getCurrentDdlJobRecList(tableSchema, tableName, + new DdlState[] {DdlState.RUNNING, DdlState.QUEUED, DdlState.PAUSED}); + List allRunningDdlRecList = new ArrayList<>(); + List allPausedDdlRecList = new ArrayList<>(); + for (int i = 0; i < allDdlRecList.size(); i++) { + DdlEngineRecord ddlRec = allDdlRecList.get(i); + DdlState stateVal = DdlState.valueOf(ddlRec.state); + if (stateVal == DdlState.RUNNING || stateVal == DdlState.QUEUED) { + allRunningDdlRecList.add(ddlRec); + } else { + allPausedDdlRecList.add(ddlRec); + } + } + boolean foundRunningDdl = !allRunningDdlRecList.isEmpty(); + boolean foundPausedDdl = !allPausedDdlRecList.isEmpty(); + String remark = ""; + if (!foundRunningDdl) { + if (foundPausedDdl) { + /** + * try to recover ddl job by "continue ddl xxx", and then + * just wait them to finished + */ + + /** + * Just wait them to finished + */ + String ddlJobIdStr = ""; + Long firstJobId = 0L; + for (int i = 0; i < allPausedDdlRecList.size(); i++) { + DdlEngineRecord ddlRec = allPausedDdlRecList.get(i); + if (i > 0) { + ddlJobIdStr += ","; + } else { + firstJobId = ddlRec.jobId; + } + ddlJobIdStr += String.format("[%s:%s]", ddlRec.jobId, ddlRec.ddlStmt); + } + + // If there are paused DDLs, continue them first + List restartedJobIdList = new ArrayList<>(); + for (DdlEngineRecord ddlRec : allPausedDdlRecList) { + Long jobId = ddlRec.getJobId(); + if (!inMaintenanceWindow()) { + continue; + } + if (jobId != null) { + restartedJobIdList.add(jobId); + String msg = String.format("Restart ttl job ddl. table:[%s], jobId:[%d]", tableName, jobId); + logTtlScheduledJob(msg, null, false, true); + String continueDdlSql = TtlTaskSqlBuilder.buildAsyncContinueDdlSql(jobId); + executeBackgroundSql(continueDdlSql, tableSchema, timeZone); + } + } + remark = genRemark(true, false, firstJobId, ddlJobIdStr); + } else { + /** + * try to submit a new ddl stmt, and then + * just wait them to finished + */ + String alterTableCleanupExpiredDataSql = + TtlTaskSqlBuilder.buildAsyncTtTableCleanupExpiredDataSql(tableSchema, tableName); + String msg = String.format("Exec ttl job ddl. table:[%s], sql:[%s]", tableName, + alterTableCleanupExpiredDataSql); + logTtlScheduledJob(msg, null, false, true); + executeBackgroundSql(alterTableCleanupExpiredDataSql, tableSchema, timeZone); + remark = genRemark(false, false, 0L, alterTableCleanupExpiredDataSql); + markTtlJobFromAutoSchedule(tableSchema, tableName); + } + } else { + /** + * Just wait them to finished + */ + String ddlJobIdStr = ""; + Long firstJobId = 0L; + for (int i = 0; i < allRunningDdlRecList.size(); i++) { + DdlEngineRecord ddlRec = allRunningDdlRecList.get(i); + if (i > 0) { + ddlJobIdStr += ","; + } else { + firstJobId = ddlRec.jobId; + } + ddlJobIdStr += String.format("[%s:%s]", ddlRec.jobId, ddlRec.ddlStmt); + } + remark = genRemark(false, true, firstJobId, ddlJobIdStr); + } + + /** + * Update remark for scheduled job + */ + + boolean needInterruptJob = false; + + int waitRound = 0; + while (true) { + List latestRunningDdlRecList = + getCurrentDdlJobRecList(tableSchema, tableName, new DdlState[] {DdlState.RUNNING, DdlState.QUEUED}); + + if (!inMaintenanceWindow()) { + needInterruptJob = true; + break; + } + + if (latestRunningDdlRecList.isEmpty()) { + break; + } + + /** + * Wait result + */ + try { + waitRound++; + if (waitRound % 12 == 0) { + logTtlScheduledJob("Waiting for ddl stmt finish running...", null, false, false); + } + Thread.sleep(5000); + } catch (Throwable ex) { + // ignore + } + } + + if (needInterruptJob) { + /** + * Gen some remark + */ + return interruptionExit(scheduleId, fireTime, "Out of maintenance window"); + } + + //mark as SUCCESS + long finishTime = ZonedDateTime.now().toEpochSecond(); + ModuleLogInfo.getInstance() + .logRecord( + Module.SCHEDULE_JOB, + PROCESS_END, + new String[] { + TTL_JOB + "," + fireTime, + remark + ", consuming " + (finishTime - startTime) + " seconds" + }, + NORMAL + ); + + return succeedExit(scheduleId, fireTime, remark); + + } catch (Throwable t) { + // The schedule job may be interrupted asynchronously. e.g. Pause DDL by other thread, + // throwing an exception which should be caught + ModuleLogInfo.getInstance() + .logRecord( + Module.SCHEDULE_JOB, + UNEXPECTED, + new String[] { + TTL_JOB + "," + fireTime, + t.getMessage() + }, + CRITICAL, + t + ); + String msg = String.format( + "process scheduled ttl job[%s] error, fireTime is [%s], error is %s", scheduleId, fireTime, + t.getMessage()); + logTtlScheduledJob(msg, t, true, false); + errorExit(scheduleId, fireTime, t.getMessage()); + return false; + } + } + + private void markTtlJobFromAutoSchedule(String ttlTblSchema, String ttlTblName) { + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = + TtlScheduledJobStatManager.getInstance().getTtlJobStatInfo(ttlTblSchema, ttlTblName); + if (jobStatInfo != null) { + jobStatInfo.setCurrJobFromScheduler(true); + } + } + + private String fetchDdlJobIdFromRemark(String remarkJson) { + return ""; + } + + @Override + public Pair needInterrupted() { + + boolean withInMaintainWindow = inMaintenanceWindow(); + if (withInMaintainWindow) { + if (executableScheduledJob.getState().equalsIgnoreCase("RUNNING")) { + String tableSchema = executableScheduledJob.getTableSchema(); + String tableName = executableScheduledJob.getTableName(); + Long scheduleId = executableScheduledJob.getScheduleId(); + Long fireTime = executableScheduledJob.getFireTime(); + + Long fireTimeInMap = ScheduledJobsManager.get(scheduleId); + DdlState[] allStates = new DdlState[DdlState.ALL_STATES.size()]; + DdlState.ALL_STATES.toArray(allStates); + + if (fireTimeInMap == null) { + List allDdlRecList = + getCurrentDdlJobRecList(tableSchema, tableName, + new DdlState[] {DdlState.RUNNING, DdlState.QUEUED}); + if (allDdlRecList.isEmpty()) { + return Pair.of(true, "No found in-memory running-state jobs and any running/queued ddl stmt"); + } + } + } + } + + return Pair.of(!withInMaintainWindow, "Out of maintenance window"); + } + + public boolean interrupt() { + return interruptionExit(executableScheduledJob.getScheduleId(), executableScheduledJob.getFireTime(), + "Interrupted by auto interrupter"); + } + + private List getCurrentDdlSqlList(String tableSchema, String tableName, DdlState[] ddlStates) { + String alterTableCleanupExpireDataKeyWord = TtlTaskSqlBuilder.ALTER_TABLE_CLEANUP_EXPIRED_DATA_TEMPLATE_KEYWORD; + List sqlList = new ArrayList<>(); + for (DdlEngineRecord record : DdlEngineShowJobsHandler.inspectDdlJobs(Pair.of(null, tableSchema), + new DdlEngineSchedulerManager())) { + String objName = record.objectName; + if (StringUtils.isEmpty(objName)) { + continue; + } + if (!objName.equalsIgnoreCase(tableName)) { + continue; + } + for (DdlState ddlState : ddlStates) { + if (ddlState.name().equalsIgnoreCase(record.state)) { + if (record.ddlStmt.toLowerCase().contains(alterTableCleanupExpireDataKeyWord)) { + sqlList.add(record.jobId); + } + break; + } + } + } + return sqlList; + } + + private List getCurrentDdlJobRecList(String tableSchema, String tableName, DdlState[] ddlStates) { + String alterTableCleanupExpireDataKeyWord = TtlTaskSqlBuilder.ALTER_TABLE_CLEANUP_EXPIRED_DATA_TEMPLATE_KEYWORD; + List sqlList = new ArrayList<>(); + for (DdlEngineRecord record : DdlEngineShowJobsHandler.inspectDdlJobs(Pair.of(null, tableSchema), + new DdlEngineSchedulerManager())) { + String objName = record.objectName; + if (StringUtils.isEmpty(objName)) { + continue; + } + if (!objName.equalsIgnoreCase(tableName)) { + continue; + } + for (DdlState ddlState : ddlStates) { + if (ddlState.name().equalsIgnoreCase(record.state)) { + if (record.ddlStmt.toLowerCase().contains(alterTableCleanupExpireDataKeyWord)) { + sqlList.add(record); + } + break; + } + } + } + return sqlList; + } + + private String genRemark(boolean findPausedDdl, boolean findRunningDdl, Long jobId, String ddlStmt) { + String remark = ""; + if (findPausedDdl) { + remark = String.format("find pause ddl, ddl_job_id is %s", jobId); + } else { + if (findRunningDdl) { + remark = String.format("find running ddl, ddlStmt is %s", ddlStmt); + } else { + remark = String.format("no find pause ddl, new ddl stmt is %s", ddlStmt); + } + + } + return remark; + } + + protected boolean applyForRunning() { + return TtlScheduledJobManager.getInstance().applyForRunning(this); + } + + /** + * Ttl finish running and exit with Success state + */ + private boolean succeedExit(long scheduleId, long fireTime, String remark) { + long finishTime = ZonedDateTime.now().toEpochSecond(); + boolean updateRs = + ScheduledJobsManager.casStateWithFinishTime(scheduleId, fireTime, RUNNING, SUCCESS, finishTime, remark); + TtlScheduledJobManager.getInstance().reloadTtlScheduledJobInfos(); + logTtlScheduledJob("Job finished successfully", null, false, false); + return updateRs; + } + + /** + * The safeExit method is used to handle those running-job find error and failed to exec, so exit + */ + private void errorExit(long scheduleId, long fireTime, String error) { + ScheduledJobsManager.casState(scheduleId, fireTime, RUNNING, FAILED, null, error); + logTtlScheduledJob(String.format("ttl scheduled job change state from running to failed"), null, true, false); + TtlScheduledJobManager.getInstance().reloadTtlScheduledJobInfos(); + } + + /** + * The safeExit method is used to handle those running-job is killed by cn restarting, + * it can auto paused the ddl-job by using "pause ddl" after cn finish restarting. + */ + @Override + public boolean safeExit() { + return safeExitInner("interrupted by safe exit checker"); + } + + protected boolean safeExitInner(String exitMsg) { + final String tableSchema = executableScheduledJob.getTableSchema(); + final String tableName = executableScheduledJob.getTableName(); + final InternalTimeZone timeZone = TimeZoneUtils.convertFromMySqlTZ(executableScheduledJob.getTimeZone()); + boolean exitSuccess = true; + for (Long jobId : getCurrentDdlSqlList(tableSchema, tableName, + new DdlState[] {DdlState.RUNNING, DdlState.QUEUED})) { + if (jobId != null) { + String pausedDdl = TtlTaskSqlBuilder.buildPauseDdlSql(jobId); + logger.info(pausedDdl); + TtlLoggerUtil.TTL_TASK_LOGGER.info(pausedDdl); + try { + // pause ddl + executeBackgroundSql(pausedDdl, tableSchema, timeZone); + } catch (Throwable t) { + logger.error(t); + TtlLoggerUtil.TTL_TASK_LOGGER.error(t); + exitSuccess = false; + } + } + } + long scheduleId = executableScheduledJob.getScheduleId(); + long fireTime = executableScheduledJob.getFireTime(); + ScheduledJobsManager.updateState(scheduleId, fireTime, FiredScheduledJobState.INTERRUPTED, + exitMsg, ""); + logTtlScheduledJob( + String.format("Ttl scheduled job safe exit and change state from running to interrupted, reason is %s", + exitMsg), null, false, true); + TtlScheduledJobManager.getInstance().reloadTtlScheduledJobInfos(); + return exitSuccess; + } + + /** + * The interruptionExit is + * used to handle running-job is still running out of maintain window, + * and its can be actively interrupt ttl-job by calling safeExit() + */ + private boolean interruptionExit(long scheduleId, long fireTime, String remark) { + if (safeExitInner("interrupted by self-interruption check")) { + ModuleLogInfo.getInstance() + .logRecord( + Module.SCHEDULE_JOB, + INTERRUPTED, + new String[] { + TTL_JOB + "," + scheduleId + "," + fireTime, + remark + }, + NORMAL); + return true; + } + return false; + } + + public ExecutableScheduledJob getExecutableScheduledJob() { + return executableScheduledJob; + } + + protected void logTtlScheduledJob(String msg, + Throwable ex, + boolean isErr, + boolean isWarn) { + + try { + long scheduleId = executableScheduledJob.getScheduleId(); + long fireTime = executableScheduledJob.getFireTime(); + String fireTimeStr = epochSecondsToDataTimeStr(fireTime); + String dbName = executableScheduledJob.getTableSchema(); + String tbName = executableScheduledJob.getTableName(); + + String logPrefix = String.format("[%s.%s][%s,%s,%s]", dbName, tbName, scheduleId, fireTime, fireTimeStr); + + if (!isErr) { + String logMsg = String.format("%s [msg: %s]", logPrefix, msg); + if (isWarn) { + TtlLoggerUtil.TTL_TASK_LOGGER.warn(logMsg); + logger.warn(logMsg); + } else { + TtlLoggerUtil.TTL_TASK_LOGGER.info(logMsg); + logger.info(logMsg); + } + + } else { + String logMsg = String.format("%s [msg: %s] [error: %s]", logPrefix, msg); + if (ex != null) { + TtlLoggerUtil.TTL_TASK_LOGGER.error(logMsg, ex); + logger.error(msg, ex); + } else { + TtlLoggerUtil.TTL_TASK_LOGGER.error(logMsg); + logger.error(msg); + } + } + } catch (Throwable e) { + logger.error(e); + } + + } + + protected String epochSecondsToDataTimeStr(long epochSeconds) { + Instant instant = Instant.ofEpochSecond(epochSeconds); + ZoneId zoneId = TimeZoneUtils.zoneIdOf(executableScheduledJob.getTimeZone()); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(zoneId); + String formattedDate = formatter.format(instant); + return formattedDate; + } + +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/spm/SPMBaseLineSyncScheduledJob.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/spm/SPMBaseLineSyncScheduledJob.java index dad58149c..93edd8f1c 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/spm/SPMBaseLineSyncScheduledJob.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/spm/SPMBaseLineSyncScheduledJob.java @@ -35,6 +35,7 @@ import com.alibaba.polardbx.gms.sync.SyncScope; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.planmanager.BaselineInfo; +import com.alibaba.polardbx.optimizer.planmanager.PlanInfo; import com.alibaba.polardbx.optimizer.planmanager.PlanManager; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -244,10 +245,21 @@ private void mergeSubBaseline(String schema, for (Map.Entry e : tempMap.entrySet()) { String sql = e.getKey(); if (!currentMap.containsKey(sql)) { - final int maxBaselineSize = InstConfUtil.getInt(ConnectionParams.SPM_MAX_BASELINE_SIZE); - if (currentMap.size() < maxBaselineSize && - e.getValue().getAcceptedPlans().size() > 0) { - currentMap.put(sql, e.getValue()); + BaselineInfo baselineInfo = e.getValue(); + boolean fixed = false; + for (PlanInfo planInfo : baselineInfo.getAcceptedPlans().values()) { + if (planInfo.isFixed()) { + fixed = true; + } + } + if (fixed || baselineInfo.isRebuildAtLoad()) { + currentMap.put(sql, baselineInfo); + } else { + final int maxBaselineSize = InstConfUtil.getInt(ConnectionParams.SPM_MAX_BASELINE_SIZE); + if (currentMap.size() < maxBaselineSize && + e.getValue().getAcceptedPlans().size() > 0) { + currentMap.put(sql, e.getValue()); + } } } else { BaselineInfo c = currentMap.get(sql); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/statistic/StatisticInfoSchemaTablesScheduleJob.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/statistic/StatisticInfoSchemaTablesScheduleJob.java new file mode 100644 index 000000000..9a150c0d1 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/statistic/StatisticInfoSchemaTablesScheduleJob.java @@ -0,0 +1,249 @@ +package com.alibaba.polardbx.executor.scheduler.executor.statistic; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.gms.util.StatisticUtils; +import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.executor.scheduler.executor.SchedulerExecutor; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.TablesAccessor; +import com.alibaba.polardbx.gms.module.Module; +import com.alibaba.polardbx.gms.module.ModuleLogInfo; +import com.alibaba.polardbx.gms.scheduler.ExecutableScheduledJob; +import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.gms.topology.SystemDbHelper; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.optimizeralert.OptimizerAlertUtil; +import org.apache.commons.lang.StringUtils; +import org.glassfish.jersey.internal.guava.Sets; + +import java.sql.Connection; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.FAILED; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.QUEUED; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.RUNNING; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.SUCCESS; +import static com.alibaba.polardbx.executor.utils.failpoint.FailPointKey.FP_INJECT_IGNORE_INTERRUPTED_TO_STATISTIC_SCHEDULE_JOB; +import static com.alibaba.polardbx.gms.module.LogLevel.CRITICAL; +import static com.alibaba.polardbx.gms.module.LogLevel.NORMAL; +import static com.alibaba.polardbx.gms.module.LogLevel.WARNING; +import static com.alibaba.polardbx.gms.module.LogPattern.INTERRUPTED; +import static com.alibaba.polardbx.gms.module.LogPattern.NOT_ENABLED; +import static com.alibaba.polardbx.gms.module.LogPattern.PROCESS_END; +import static com.alibaba.polardbx.gms.module.LogPattern.PROCESS_START; +import static com.alibaba.polardbx.gms.module.LogPattern.STATE_CHANGE_FAIL; +import static com.alibaba.polardbx.gms.module.LogPattern.UNEXPECTED; +import static com.alibaba.polardbx.gms.scheduler.ScheduledJobExecutorType.STATISTIC_INFO_SCHEMA_TABLES; + +public class StatisticInfoSchemaTablesScheduleJob extends SchedulerExecutor { + private final ExecutableScheduledJob executableScheduledJob; + private boolean fromScheduleJob = true; + + public StatisticInfoSchemaTablesScheduleJob(final ExecutableScheduledJob executableScheduledJob) { + this.executableScheduledJob = executableScheduledJob; + } + + @Override + public boolean execute() { + long scheduleId = executableScheduledJob.getScheduleId(); + long fireTime = executableScheduledJob.getFireTime(); + long startTime = ZonedDateTime.now().toEpochSecond(); + String remark = ""; + try { + boolean interruptedTest = InstConfUtil.getBool(ConnectionParams.ALERT_STATISTIC_INTERRUPT); + if (interruptedTest) { + throw new TddlRuntimeException(ErrorCode.ERR_STATISTIC_JOB_INTERRUPTED, + "statistic job (info_schema.tables) is interrupted by alert test"); + } + + if (fromScheduleJob) { + //mark as RUNNING + boolean casSuccess = + ScheduledJobsManager.casStateWithStartTime(scheduleId, fireTime, QUEUED, RUNNING, startTime); + if (!casSuccess) { + ModuleLogInfo.getInstance() + .logRecord( + Module.SCHEDULE_JOB, + STATE_CHANGE_FAIL, + new String[] {STATISTIC_INFO_SCHEMA_TABLES + "," + fireTime, QUEUED.name(), RUNNING.name()}, + WARNING); + return false; + } + } + + boolean enableStatisticBackground = + InstConfUtil.getBool(ConnectionParams.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION); + if (fromScheduleJob && !enableStatisticBackground) { + remark = "statistic background collection task (info_schema.tables) disabled."; + ModuleLogInfo.getInstance() + .logRecord( + Module.STATISTICS, + NOT_ENABLED, + new String[] { + ConnectionProperties.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION, + STATISTIC_INFO_SCHEMA_TABLES + "," + fireTime + " exit" + }, + NORMAL); + return succeedExit(scheduleId, fireTime, remark); + } + if (fromScheduleJob && !inMaintenanceWindow()) { + remark = "statistic background collection task (info_schema.tables) not in maintenance window."; + ModuleLogInfo.getInstance() + .logRecord( + Module.STATISTICS, + NOT_ENABLED, + new String[] { + ConnectionProperties.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION, + STATISTIC_INFO_SCHEMA_TABLES + "," + fireTime + " exit" + }, + NORMAL); + return succeedExit(scheduleId, fireTime, remark); + } + + List schemas = DbInfoManager.getInstance().getDbList(); + ModuleLogInfo.getInstance() + .logRecord( + Module.STATISTICS, + PROCESS_START, + new String[] { + STATISTIC_INFO_SCHEMA_TABLES.name(), + "schemas:" + schemas + }, + NORMAL); + + for (String schema : schemas) { + if (StringUtils.isEmpty(schema)) { + continue; + } + if (SystemDbHelper.isDBBuildInExceptCdc(schema)) { + continue; + } + if (!OptimizerContext.getActiveSchemaNames().contains(schema)) { + continue; + } + + // interrupted judge + Pair pair = needInterrupted(); + if (pair.getKey()) { + ModuleLogInfo.getInstance() + .logRecord( + Module.STATISTICS, + INTERRUPTED, + new String[] { + STATISTIC_INFO_SCHEMA_TABLES + "," + fireTime, + pair.getValue() + }, + NORMAL); + return succeedExit(scheduleId, fireTime, "being interrupted"); + } + + Set logicalTableSet = Sets.newHashSet(); + for (TableMeta tableMeta : Objects.requireNonNull(OptimizerContext.getContext(schema)) + .getLatestSchemaManager().getAllUserTables()) { + logicalTableSet.add(tableMeta.getTableName().toLowerCase()); + } + long start = System.currentTimeMillis(); + if (fromScheduleJob) { + // Only consider tables whose last updated time > 1 day. + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + TablesAccessor accessor = new TablesAccessor(); + accessor.setConnection(metaDbConn); + Set longTimeNotUpdatedTables = accessor.getLongTimeNotUpdatedTables(schema); + logicalTableSet.retainAll(longTimeNotUpdatedTables); + } + } + logicalTableSet = logicalTableSet.stream().filter(t -> + Objects.requireNonNull(OptimizerContext.getContext(schema)) + .getLatestSchemaManager().getTableWithNull(t) != null).collect(Collectors.toSet()); + + // Process these tables. + StatisticUtils.updateMetaDbInformationSchemaTables(schema, logicalTableSet); + + long end = System.currentTimeMillis(); + ModuleLogInfo.getInstance() + .logRecord( + Module.STATISTICS, + PROCESS_END, + new String[] { + "auto collect " + STATISTIC_INFO_SCHEMA_TABLES + "," + schema + ",table size " + + logicalTableSet.size(), + " consuming " + (end - start) / 1000.0 + " seconds" + }, + NORMAL); + } + ModuleLogInfo.getInstance() + .logRecord( + Module.STATISTICS, + PROCESS_END, + new String[] { + "auto " + STATISTIC_INFO_SCHEMA_TABLES, + " consuming " + (System.currentTimeMillis() - startTime * 1000) / 1000.0 + " seconds" + }, + NORMAL); + return succeedExit(scheduleId, fireTime, remark); + } catch (Throwable t) { + ModuleLogInfo.getInstance() + .logRecord( + Module.STATISTICS, + UNEXPECTED, + new String[] { + "auto analyze " + STATISTIC_INFO_SCHEMA_TABLES + "," + fireTime, + t.getMessage() + }, + CRITICAL, + t); + errorExit(scheduleId, fireTime, t.getMessage()); + return false; + } + } + + private boolean succeedExit(long scheduleId, long fireTime, String remark) { + if (!fromScheduleJob) { + return true; + } + long finishTime = System.currentTimeMillis() / 1000; + //mark as SUCCESS + return ScheduledJobsManager.casStateWithFinishTime(scheduleId, fireTime, RUNNING, SUCCESS, finishTime, remark); + } + + private void errorExit(long scheduleId, long fireTime, String error) { + if (fromScheduleJob) { + //mark as fail + ScheduledJobsManager.updateState(scheduleId, fireTime, FAILED, null, error); + } + + OptimizerAlertUtil.statisticErrorAlert(); + } + + @Override + public Pair needInterrupted() { + if (!fromScheduleJob) { + return Pair.of(false, "not from schedule job"); + } + if (FailPoint.isKeyEnable(FP_INJECT_IGNORE_INTERRUPTED_TO_STATISTIC_SCHEDULE_JOB)) { + return Pair.of(false, "fail point"); + } + boolean enableStatisticBackground = + InstConfUtil.getBool(ConnectionParams.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION); + if (!enableStatisticBackground) { + return Pair.of(true, "ENABLE_BACKGROUND_STATISTIC_COLLECTION not enabled"); + } + return Pair.of(!inMaintenanceWindow(), "maintenance window"); + } + + public void setFromScheduleJob(boolean fromScheduleJob) { + this.fromScheduleJob = fromScheduleJob; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/statistic/StatisticSampleCollectionScheduledJob.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/statistic/StatisticSampleCollectionScheduledJob.java index 34ae3f554..e9d6838d6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/statistic/StatisticSampleCollectionScheduledJob.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/statistic/StatisticSampleCollectionScheduledJob.java @@ -337,7 +337,7 @@ private boolean testSketchPointCheck() { } private boolean succeedExit(long scheduleId, long fireTime, String remark) { - if (fromScheduleJob) { + if (!fromScheduleJob) { return true; } long finishTime = System.currentTimeMillis() / 1000; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CheckCciSnapshotScheduleJob.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CheckCciSnapshotScheduleJob.java new file mode 100644 index 000000000..b4574c702 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CheckCciSnapshotScheduleJob.java @@ -0,0 +1,4 @@ +package com.alibaba.polardbx.executor.scheduler.executor.trx; + +public class CheckCciSnapshotScheduleJob { +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CleanLogTableScheduledJob.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CleanLogTableScheduledJob.java index afc74cf5e..26edd6e8c 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CleanLogTableScheduledJob.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CleanLogTableScheduledJob.java @@ -62,7 +62,7 @@ public boolean execute() { long fireTime = executableScheduledJob.getFireTime(); long startTime = ZonedDateTime.now().toEpochSecond(); - StringBuilder remark = new StringBuilder(); + StringBuffer remark = new StringBuffer(); try { // Mark as RUNNING. boolean casSuccess = diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CleanLogTableTask.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CleanLogTableTask.java index 33ca52901..8f046cb13 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CleanLogTableTask.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CleanLogTableTask.java @@ -31,12 +31,14 @@ import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.spi.ITopologyExecutor; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.ha.impl.StorageHaManager; import com.alibaba.polardbx.gms.ha.impl.StorageInstHaContext; import com.alibaba.polardbx.gms.metadb.trx.TrxLogStatusAccessor; import com.alibaba.polardbx.gms.metadb.trx.TrxLogStatusRecord; import com.alibaba.polardbx.gms.topology.DbTopologyManager; import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; import java.sql.Connection; import java.sql.ResultSet; @@ -48,6 +50,7 @@ import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Executor; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; @@ -57,11 +60,13 @@ import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.DROP_GLOBAL_TX_TABLE_V2_ARCHIVE; import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.DROP_GLOBAL_TX_TABLE_V2_TMP; import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.FORCE_RENAME_GLOBAL_TX_TABLE_V2; +import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.QUERY_TABLE_ROWS_TX_TABLE_V2; import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.SELECT_MAX_TX_ID_IN_ARCHIVE; import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.SELECT_TABLE_ROWS_V2; import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.SET_DISTRIBUTED_TRX_ID; import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.SHOW_ALL_GLOBAL_TX_TABLE_V2; import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.SWITCH_GLOBAL_TX_TABLE_V2; +import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.TRX_LOG_SOCKET_TIMEOUT; import static com.alibaba.polardbx.common.utils.LockUtil.wrapWithLockWaitTimeout; import static com.alibaba.polardbx.executor.utils.ExecUtils.scanRecoveredTrans; import static com.alibaba.polardbx.executor.utils.failpoint.FailPointKey.FP_TRX_LOG_TB_FAILED_BEFORE_CREATE_TMP; @@ -79,7 +84,7 @@ public class CleanLogTableTask { private static final Logger logger = LoggerFactory.getLogger(CleanLogTableTask.class); - public static long run(boolean force, StringBuilder remark) throws SQLException { + public static long run(boolean force, StringBuffer remark) throws SQLException { Set dnIds = new HashSet<>(); Set addresses = new HashSet<>(); for (StorageInstHaContext ctx : StorageHaManager.getInstance().getMasterStorageList()) { @@ -134,6 +139,13 @@ public static long run(boolean force, StringBuilder remark) throws SQLException return -1; } + // Check if we should clean trx log. + if (!force && !shouldCleanTrxLog(dnIds, lastUpdate, currentTime)) { + updateRemark = false; + remark.append("Too few records, no need to clean. "); + return -1; + } + remark.append("Create tmp table. "); if (FailPoint.isKeyEnable(FP_TRX_LOG_TB_FAILED_BEFORE_CREATE_TMP)) { @@ -222,12 +234,55 @@ public static long run(boolean force, StringBuilder remark) throws SQLException return purged.get(); } + /** + * Clean trx log table if : + * 1. Some trx log table contains more than 100k rows. + * 2. It has been more than 1 day since last clean, and we are in maintenance window. + */ + protected static boolean shouldCleanTrxLog(Set dnIds, long lastUpdate, long currentTime) { + if ((lastUpdate + 24 * 60 * 60 * 1000 < currentTime) && InstConfUtil.isInMaintenanceTimeWindow()) { + return true; + } + ConcurrentLinkedQueue exceptions = new ConcurrentLinkedQueue<>(); + AtomicBoolean shouldClean = new AtomicBoolean(false); + Collection futures = forEachDn(dnIds, (dnId) -> { + try (Connection conn = DbTopologyManager.getConnectionForStorage(dnId); + Statement stmt = conn.createStatement()) { + conn.setNetworkTimeout(TGroupDirectConnection.socketTimeoutExecutor, TRX_LOG_SOCKET_TIMEOUT); + wrapWithLockWaitTimeout(conn, 3, () -> { + try { + ResultSet rs = stmt.executeQuery(QUERY_TABLE_ROWS_TX_TABLE_V2); + while (rs.next()) { + int rows = rs.getInt(1); + if (rows > 100_000) { + shouldClean.set(true); + } + } + } catch (Exception e) { + EventLogger.log(EventType.TRX_LOG_ERR, + "Error during creating tmp table, caused by " + e.getMessage()); + exceptions.offer(e); + } + }); + } catch (Exception e) { + exceptions.offer(e); + } + }); + + AsyncUtils.waitAll(futures); + + exceptions.forEach(logger::error); + + return shouldClean.get(); + } + private static void createTmpTable(Set dnIds) { ConcurrentLinkedQueue exceptions = new ConcurrentLinkedQueue<>(); AtomicBoolean lock = new AtomicBoolean(false); Collection futures = forEachDn(dnIds, (dnId) -> { try (Connection conn = DbTopologyManager.getConnectionForStorage(dnId); Statement stmt = conn.createStatement()) { + conn.setNetworkTimeout(TGroupDirectConnection.socketTimeoutExecutor, TRX_LOG_SOCKET_TIMEOUT); wrapWithLockWaitTimeout(conn, 3, () -> { try { if (FailPoint.isKeyEnable(FP_TRX_LOG_TB_FAILED_DURING_CREATE_TMP) @@ -258,7 +313,7 @@ private static void createTmpTable(Set dnIds) { } } - private static void switchTables(Set dnIds, StringBuilder remark) { + private static void switchTables(Set dnIds, StringBuffer remark) { /* Normal procedure: A -> {A, tmp} -> {B, A} -> A @@ -339,7 +394,7 @@ private static void switchTables(Set dnIds, StringBuilder remark) { } } - private static void dropTable(Set dnIds, StringBuilder remark, AtomicLong purged) { + private static void dropTable(Set dnIds, StringBuffer remark, AtomicLong purged) { // Check support async commit variables. boolean dn57 = ExecutorContext.getContext(CDC_DB_NAME).getStorageInfoManager().supportAsyncCommit(); // Max time 4 * 5 = 20s @@ -488,6 +543,7 @@ private static void execWithLockWaitTimeout(String dnId, Consumer task) { try (Connection conn = DbTopologyManager.getConnectionForStorage(dnId); Statement stmt = conn.createStatement()) { + conn.setNetworkTimeout(TGroupDirectConnection.socketTimeoutExecutor, TRX_LOG_SOCKET_TIMEOUT); wrapWithLockWaitTimeout(conn, 3, () -> task.accept(stmt)); } catch (SQLException e) { exceptions.offer(e); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/GenerateColumnarSnapshotScheduledJob.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/GenerateColumnarSnapshotScheduledJob.java new file mode 100644 index 000000000..ec6500b03 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/scheduler/executor/trx/GenerateColumnarSnapshotScheduledJob.java @@ -0,0 +1,250 @@ +package com.alibaba.polardbx.executor.scheduler.executor.trx; + +import com.alibaba.fastjson.JSON; +import com.alibaba.polardbx.common.ColumnarOptions; +import com.alibaba.polardbx.common.eventlogger.EventLogger; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.logger.MDC; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.executor.scheduler.executor.SchedulerExecutor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingExtra; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.metadb.table.IndexStatus; +import com.alibaba.polardbx.gms.module.Module; +import com.alibaba.polardbx.gms.module.ModuleLogInfo; +import com.alibaba.polardbx.gms.scheduler.ExecutableScheduledJob; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import org.apache.calcite.sql.SqlKind; + +import java.sql.Connection; +import java.sql.SQLException; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicBoolean; + +import static com.alibaba.polardbx.common.columnar.ColumnarUtils.AddCDCMarkEvent; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.FAILED; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.QUEUED; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.RUNNING; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.SUCCESS; +import static com.alibaba.polardbx.gms.module.LogLevel.CRITICAL; +import static com.alibaba.polardbx.gms.module.LogLevel.WARNING; +import static com.alibaba.polardbx.gms.module.LogPattern.STATE_CHANGE_FAIL; +import static com.alibaba.polardbx.gms.module.LogPattern.UNEXPECTED; +import static com.alibaba.polardbx.gms.scheduler.ScheduledJobExecutorType.GENERATE_COLUMNAR_SNAPSHOT; +import static com.alibaba.polardbx.gms.topology.SystemDbHelper.DEFAULT_DB_NAME; + +/** + * @author yaozhili + */ +public class GenerateColumnarSnapshotScheduledJob extends SchedulerExecutor { + private static final Logger logger = LoggerFactory.getLogger(GenerateColumnarSnapshotScheduledJob.class); + + private final ExecutableScheduledJob executableScheduledJob; + + public GenerateColumnarSnapshotScheduledJob(ExecutableScheduledJob executableScheduledJob) { + this.executableScheduledJob = executableScheduledJob; + } + + @Override + public boolean execute() { + long scheduleId = executableScheduledJob.getScheduleId(); + long fireTime = executableScheduledJob.getFireTime(); + long startTime = ZonedDateTime.now().toEpochSecond(); + + StringBuffer remark = new StringBuffer("Begin generate columnar snapshots."); + try { + // Mark as RUNNING. + boolean casSuccess = + ScheduledJobsManager.casStateWithStartTime(scheduleId, fireTime, QUEUED, RUNNING, startTime); + if (!casSuccess) { + ModuleLogInfo.getInstance() + .logRecord( + Module.SCHEDULE_JOB, + STATE_CHANGE_FAIL, + new String[] {GENERATE_COLUMNAR_SNAPSHOT + "," + fireTime, QUEUED.name(), RUNNING.name()}, + WARNING); + return false; + } + + final Map savedMdcContext = MDC.getCopyOfContextMap(); + try { + MDC.put(MDC.MDC_KEY_APP, DEFAULT_DB_NAME); + generateColumnarSnapshots(remark, false); + } finally { + MDC.setContextMap(savedMdcContext); + } + + long finishTime = System.currentTimeMillis() / 1000; + remark.append("End generate columnar snapshots. Cost ").append(finishTime - startTime).append("s."); + return ScheduledJobsManager + .casStateWithFinishTime(scheduleId, fireTime, RUNNING, SUCCESS, finishTime, remark.toString()); + } catch (Throwable t) { + logger.error(t); + ModuleLogInfo.getInstance() + .logRecord( + Module.TRX, + UNEXPECTED, + new String[] { + GENERATE_COLUMNAR_SNAPSHOT + "," + fireTime, + t.getMessage() + }, + CRITICAL, + t + ); + remark.append("Generate columnar snapshots error: ").append(t.getMessage()); + ScheduledJobsManager.updateState(scheduleId, fireTime, FAILED, remark.toString(), t.getMessage()); + return false; + } + } + + public static void generateColumnarSnapshots(StringBuffer remark, boolean force) throws SQLException { + if (!force && !DynamicConfig.getInstance().isEnableAutoGenColumnarSnapshot()) { + remark.append("Not enabled, skip."); + return; + } + List columnarTableMappingRecords; + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarTableMappingAccessor columnarTableMappingAccessor = new ColumnarTableMappingAccessor(); + columnarTableMappingAccessor.setConnection(connection); + columnarTableMappingRecords = columnarTableMappingAccessor.queryAllSnapshotCci(); + } + + if (columnarTableMappingRecords.isEmpty()) { + remark.append("No snapshot cci, skip."); + return; + } + + EventLogger.logCciSnapshot(columnarTableMappingRecords.size()); + + long currentTso = + ExecutorContext.getContext(DEFAULT_DB_NAME).getTransactionManager().getTimestampOracle().nextTimestamp(); + Collections.shuffle(columnarTableMappingRecords); + + AtomicBoolean stop = new AtomicBoolean(false); + ConcurrentLinkedQueue workQueue = new ConcurrentLinkedQueue<>(); + int parallelism = DynamicConfig.getInstance().getAutoGenColumnarSnapshotParallelism(); + List futures = new ArrayList<>(); + try { + // Consumers. + for (int i = 0; i < parallelism; i++) { + futures.add( + ExecutorContext.getContext(DEFAULT_DB_NAME).getTopologyExecutor().getExecutorService() + .submit(null, null, () -> { + final Map savedMdcContext = MDC.getCopyOfContextMap(); + try { + MDC.put(MDC.MDC_KEY_APP, DEFAULT_DB_NAME); + ColumnarTableMappingRecord r; + while (null != (r = workQueue.poll()) || !stop.get()) { + if (null == r) { + Thread.sleep(100); + continue; + } + String sql = String.format("call polardbx.columnar_flush(%s)", r.tableId); + Long tso = AddCDCMarkEvent(sql, SqlKind.PROCEDURE_CALL.name()); + ColumnarTableMappingExtra extra = getColumnarTableMappingExtra(r); + assert extra != null; + extra.setTso(tso); + try { + saveColumnarTableMappingExtra(r, extra); + remark.append("Add ") + .append(r.indexName) + .append(", tso: ") + .append(tso) + .append(". "); + } catch (SQLException e) { + logger.error("Call columnar flush failed.", e); + } + } + } catch (InterruptedException e) { + logger.error(e); + } finally { + MDC.setContextMap(savedMdcContext); + } + })); + } + // Producer. + for (ColumnarTableMappingRecord record : columnarTableMappingRecords) { + long intervalMinute = -1; + try { + GsiMetaManager.GsiIndexMetaBean gsiIndexMetaBean = ExecutorContext.getContext(record.tableSchema) + .getGsiManager() + .getGsiIndexMeta(record.tableSchema, record.tableName, record.indexName, IndexStatus.ALL); + String interval = gsiIndexMetaBean.columnarOptions.get() + .get(ColumnarOptions.AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL); + if (null != interval) { + intervalMinute = Long.parseLong(interval); + } + } catch (Exception e) { + logger.error("Fetch table meta error", e); + continue; + } + + if (intervalMinute < 0) { + continue; + } + + ColumnarTableMappingExtra extra = getColumnarTableMappingExtra(record); + if (extra == null) { + continue; + } + + if (force || (((currentTso - extra.getTso()) >> 22) > intervalMinute * 55 * 1000)) { + // Should generate. + workQueue.add(record); + } + } + } finally { + stop.set(true); + } + + try { + for (Future future : futures) { + future.get(); + } + } catch (Throwable t) { + for (Future future : futures) { + future.cancel(true); + } + } + } + + private static ColumnarTableMappingExtra getColumnarTableMappingExtra(ColumnarTableMappingRecord record) { + ColumnarTableMappingExtra extra; + try { + if (null == record.extra) { + extra = new ColumnarTableMappingExtra(); + extra.setTso(0L); + } else { + extra = JSON.parseObject(record.extra, ColumnarTableMappingExtra.class); + } + } catch (Throwable t) { + logger.error("Parse extra failed: " + record.extra, t); + return null; + } + return extra; + } + + private static void saveColumnarTableMappingExtra(ColumnarTableMappingRecord record, + ColumnarTableMappingExtra extra) throws SQLException { + record.extra = JSON.toJSONString(extra); + // Update meta db. + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + ColumnarTableMappingAccessor columnarTableMappingAccessor = new ColumnarTableMappingAccessor(); + columnarTableMappingAccessor.setConnection(metaDbConn); + columnarTableMappingAccessor.UpdateExtraByTableId(record.tableId, record.extra); + } + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/shadowtable/ShadowTableUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/shadowtable/ShadowTableUtils.java index 0c38c180b..848f80b6c 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/shadowtable/ShadowTableUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/shadowtable/ShadowTableUtils.java @@ -16,27 +16,23 @@ package com.alibaba.polardbx.executor.shadowtable; -import com.alibaba.polardbx.common.IdGenerator; -import com.alibaba.polardbx.common.properties.ConnectionParams; -import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; import com.alibaba.polardbx.druid.util.JdbcConstants; -import com.alibaba.polardbx.executor.common.ExecutorContext; -import com.alibaba.polardbx.executor.ddl.twophase.TwoPhaseDdlData; import com.alibaba.polardbx.executor.ddl.twophase.TwoPhaseDdlUtils; import com.alibaba.polardbx.executor.spi.IGroupExecutor; import com.alibaba.polardbx.executor.utils.StringUtils; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.statistics.SQLRecorderLogger; import org.apache.calcite.sql.SqlIdentifier; + import java.util.List; import java.util.Map; import java.util.concurrent.ThreadLocalRandom; import static com.alibaba.polardbx.druid.sql.SQLUtils.parseStatementsWithDefaultFeatures; -import static com.alibaba.polardbx.executor.ddl.twophase.TwoPhaseDdlUtils.queryGroupBypassConnPool; import static com.alibaba.polardbx.gms.metadb.limit.Limits.MAX_LENGTH_OF_IDENTIFIER_NAME; public class ShadowTableUtils { @@ -111,7 +107,7 @@ public static void initTraceShadowTable(ExecutionContext originEc, String schema String shadowTableName, Long id) { String sql = String.format(TwoPhaseDdlUtils.SQL_INIT_TWO_PHASE_DDL, schemaName, String.valueOf(id), - StringUtils.quote(shadowTableName)); + TStringUtil.quote(shadowTableName)); TwoPhaseDdlUtils.updateGroup(originEc, -1L, schemaName, groupName, sql); sql = String.format(TwoPhaseDdlUtils.SQL_TRACE_TWO_PHASE_DDL, schemaName, String.valueOf(id)); TwoPhaseDdlUtils.updateGroup(originEc, -1L, schemaName, groupName, sql); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/spi/ITransactionManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/spi/ITransactionManager.java index 78dd61df8..0997a5fe3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/spi/ITransactionManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/spi/ITransactionManager.java @@ -64,7 +64,10 @@ default boolean supportAsyncCommit() { long getColumnarMinSnapshotSeq(); - default boolean support2pcOpt() { + void scheduleTimerTask(); + + default boolean supportXaTso() { return false; } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/RealStatsLog.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/RealStatsLog.java new file mode 100644 index 000000000..711949f1d --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/RealStatsLog.java @@ -0,0 +1,25 @@ +package com.alibaba.polardbx.executor.statistic; + +import com.alibaba.polardbx.gms.module.Module; +import com.alibaba.polardbx.gms.module.ModuleLogInfo; + +/** + * @author fangwu + */ +public class RealStatsLog { + /** + * real-time information + */ + public static String statLog() { + StringBuilder sb = new StringBuilder(); + for (RealStatsLogType type : RealStatsLogType.values()) { + try { + sb.append(type.name()).append(":").append(type.getLog()).append(","); + } catch (Exception e) { + ModuleLogInfo.getInstance().logError(Module.METRIC, type.name(), e); + } + } + return sb.toString(); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/RealStatsLogType.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/RealStatsLogType.java new file mode 100644 index 000000000..be1ceb8a6 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/RealStatsLogType.java @@ -0,0 +1,383 @@ +package com.alibaba.polardbx.executor.statistic; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.executor.pl.ProcedureManager; +import com.alibaba.polardbx.executor.pl.StoredFunctionManager; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.gms.topology.SystemDbHelper; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.config.table.statistic.Histogram; +import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticManager; +import com.alibaba.polardbx.optimizer.core.expression.JavaFunctionManager; +import com.alibaba.polardbx.optimizer.core.planner.PlanCache; +import org.glassfish.jersey.internal.guava.Sets; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils.DEFAULT_SAMPLE_SIZE; +import static com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils.buildColumnsName; +import static com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils.isBinaryOrJsonColumn; + +/** + * @author jilong.ljl + */ +public enum RealStatsLogType { + /** + * real-time information + */ + TABLE_NUM { + @Override + public String getLog() { + return "" + tableCount(); + } + }, + COLUMN_NEED_SAMPLE_STATS_SIZE { + @Override + public String getLog() { + return "" + calculateColumnsForSamplingStats(); + } + }, + COLUMN_HAS_FRESH_SAMPLE_STATS_SIZE { + @Override + public String getLog() { + return "" + countFreshSampleStatsColumns(); + } + }, + COLUMN_NEED_HLL_STATS_SIZE { + @Override + public String getLog() { + return "" + calculateColumnsForHyperLoglogStats(); + } + }, + COLUMN_HAS_FRESH_HLL_STATS_SIZE { + @Override + public String getLog() { + return "" + countFreshHyperLogLogStatsColumns(); + } + }, + PLAN_CACHE_SIZE { + @Override + public String getLog() { + return "" + planCacheSize(); + } + }, + STATISTIC_TABLE_NUM { + @Override + public String getLog() { + return "" + tableInStatsCount(); + } + }, + PROCEDURE_NUM { + @Override + public String getLog() { + return "" + procedureCount(); + } + }, + SQL_UDF_NUM { + @Override + public String getLog() { + return "" + sqlUdfCount(); + } + }, + JAVA_UDF_NUM { + @Override + public String getLog() { + return "" + javaUdfCount(); + } + }; + + public abstract String getLog(); + + // util method + + protected static long planCacheSize() { + return PlanCache.getInstance().getCacheKeyCount(); + } + + protected static long procedureCount() { + return ProcedureManager.getInstance().getProcedureSize(); + } + + protected static long sqlUdfCount() { + return StoredFunctionManager.getInstance().getUdfCount(); + } + + protected static long javaUdfCount() { + return JavaFunctionManager.getInstance().getFuncNum(); + } + + public static long countFreshHyperLogLogStatsColumns() { + long columnCount = 0; + + // Retrieve list of databases + List databaseNames = DbInfoManager.getInstance().getDbList(); + + int expiredTime = InstConfUtil.getInt(ConnectionParams.STATISTIC_NDV_SKETCH_EXPIRE_TIME); + long current = System.currentTimeMillis(); + + // Iterate over each database. + for (String dbName : databaseNames) { + OptimizerContext context = OptimizerContext.getContext(dbName); + + // Skip if no context exists for this database. + if (context == null) { + continue; + } + + List tables = context.getLatestSchemaManager().getAllUserTables(); + + // Iterate over each table within the current database. + for (TableMeta tableMeta : tables) { + + String tableName = tableMeta.getTableName(); + StatisticManager.CacheLine c = StatisticManager.getInstance().getCacheLine(dbName, tableName); + + if (c.getRowCount() <= DEFAULT_SAMPLE_SIZE) { + continue; + } + + Map>> indexColsMap = GlobalIndexMeta.getTableIndexMap(tableMeta, null); + Set colDoneSet = Sets.newHashSet(); + for (Map.Entry>> entry : indexColsMap.entrySet()) { + // index key -> columns + Map> indexColumnMap = entry.getValue(); + + for (List cols : indexColumnMap.values()) { + for (int i = 0; i <= cols.size() - 1; i++) { + // Sequentially counting the occurrences of prefix combinations for a prefix index + String colsName = buildColumnsName(cols, i + 1); + colDoneSet.add(colsName); + } + } + } + + for (String cols : colDoneSet) { + long lastUpdate = StatisticManager.getInstance().getSds().ndvModifyTime(dbName, tableName, cols); + if (current - lastUpdate <= expiredTime) { + columnCount++; + } else { + Logger logger = LoggerFactory.getLogger("STATISTICS"); + logger.warn("ndv sketch has expired:" + dbName + "," + tableName + "," + cols); + } + } + } + } + return columnCount; + } + + public static long calculateColumnsForHyperLoglogStats() { + long columnCount = 0; + + // Retrieve list of databases + List databaseNames = DbInfoManager.getInstance().getDbList(); + + // Iterate over each database. + for (String dbName : databaseNames) { + OptimizerContext context = OptimizerContext.getContext(dbName); + + // Skip if no context exists for this database. + if (context == null) { + continue; + } + + List tables = context.getLatestSchemaManager().getAllUserTables(); + + // Iterate over each table within the current database. + for (TableMeta tableMeta : tables) { + String tableName = tableMeta.getTableName(); + StatisticManager.CacheLine c = StatisticManager.getInstance().getCacheLine(dbName, tableName); + + if (c.getRowCount() <= DEFAULT_SAMPLE_SIZE) { + continue; + } + + Map>> indexColsMap = GlobalIndexMeta.getTableIndexMap(tableMeta, null); + Set colDoneSet = Sets.newHashSet(); + for (Map.Entry>> entry : indexColsMap.entrySet()) { + // index key -> columns + Map> indexColumnMap = entry.getValue(); + + for (List cols : indexColumnMap.values()) { + for (int i = 0; i <= cols.size() - 1; i++) { + // Sequentially counting the occurrences of prefix combinations for a prefix index + String colsName = buildColumnsName(cols, i + 1); + colDoneSet.add(colsName); + } + } + } + columnCount += colDoneSet.size(); + } + } + return columnCount; + } + + /** + * Calculates the total number of non-binary and non-JSON type columns across all databases, + * which might require sampling statistics. + * + * @return The total count of columns requiring sampling statistics. + */ + public static long calculateColumnsForSamplingStats() { + long columnCount = 0; + + // Retrieve list of databases + List databaseNames = DbInfoManager.getInstance().getDbList(); + + // Iterate over each database. + for (String dbName : databaseNames) { + OptimizerContext context = OptimizerContext.getContext(dbName); + + // Skip if no context exists for this database. + if (context == null) { + continue; + } + + if (SystemDbHelper.isDBBuildIn(dbName)) { + continue; + } + + List tables = context.getLatestSchemaManager().getAllUserTables(); + + // Iterate over each table within the current database. + for (TableMeta tableMeta : tables) { + Collection columns = tableMeta.getAllColumns(); + + // Iterate over each column within the current table. + for (ColumnMeta columnMeta : columns) { + // Increment counter only if the column is neither binary nor JSON type. + if (!isBinaryOrJsonColumn(columnMeta)) { + columnCount++; + } + } + } + } + // Return the total count of columns needing sampling stats. + return columnCount; + } + + /** + * Counts the total number of columns having fresh sample statistics across all database schemas. + * + * @return Total number of columns with fresh statistics. + */ + public static long countFreshSampleStatsColumns() { + long totalSize = 0L; + List databaseSchemas = DbInfoManager.getInstance().getDbList(); + + for (String schema : databaseSchemas) { + OptimizerContext context = OptimizerContext.getContext(schema); + if (context == null) { + continue; + } + if (SystemDbHelper.isDBBuildIn(schema)) { + continue; + } + + List tables = context.getLatestSchemaManager().getAllUserTables(); + + for (TableMeta tableMeta : tables) { + StatisticManager.CacheLine cacheLine = + StatisticManager.getInstance().getCacheLine(schema, tableMeta.getTableName()); + // Check if cache line exists and hasn't expired. + if (cacheLine != null && !cacheLine.hasExpire()) { + Collection columns = tableMeta.getAllColumns(); + + if (cacheLine.getRowCount() == 0L) { + totalSize += countColumnsWithoutBinaryOrJson(columns); + } else { // Handle cases where row count is greater than zero. + totalSize += countColumnsWithNotExpiredStatistics(cacheLine, columns); + } + } + } + } + + return totalSize; + } + + /** + * Counts columns without binary or JSON types. + * + * @param columns Collection of ColumnMeta objects representing columns. + * @return Count of columns excluding binary or JSON types. + */ + public static long countColumnsWithoutBinaryOrJson(Collection columns) { + long count = 0; + for (ColumnMeta columnMeta : columns) { + if (!isBinaryOrJsonColumn(columnMeta)) { + count++; + } + } + return count; + } + + /** + * Counts columns with statistical information that is not expired. + * + * @param cacheLine Cache line containing statistical information. + * @param columns Collection of ColumnMeta objects representing columns. + * @return Count of columns lacking complete statistical data. + */ + public static long countColumnsWithNotExpiredStatistics(StatisticManager.CacheLine cacheLine, + Collection columns) { + long count = 0; + for (ColumnMeta columnMeta : columns) { + if (!isBinaryOrJsonColumn(columnMeta)) { + if (!hasMissingStatistics(cacheLine, columnMeta.getName())) { + count++; + } + } + } + return count; + } + + /** + * Checks if there are missing statistics for a given column name. + * + * @param cacheLine Cache line containing statistical information. + * @param columnName Name of the column to check. + * @return True if statistics are missing, false otherwise. + */ + public static boolean hasMissingStatistics(StatisticManager.CacheLine cacheLine, String columnName) { + String lowerCaseColName = columnName.toLowerCase(); + boolean isTopnNull = cacheLine.getTopN(lowerCaseColName) == null; + Histogram histogram = + cacheLine.getHistogramMap() == null ? null : cacheLine.getHistogramMap().get(lowerCaseColName); + boolean isHistogramNull = histogram == null || histogram.getBuckets().isEmpty(); + long nullNum = 0L; + if (cacheLine.getNullCountMap().containsKey(lowerCaseColName)) { + nullNum = cacheLine.getNullCountMap().get(lowerCaseColName); + } + return (cacheLine.getRowCount() - nullNum) > 0 && isTopnNull && isHistogramNull; + } + + protected static int tableCount() { + int count = 0; + for (String schema : DbInfoManager.getInstance().getDbList()) { + if (SystemDbHelper.isDBBuildIn(schema)) { + continue; + } + if (!OptimizerContext.getActiveSchemaNames().contains(schema)) { + continue; + } + OptimizerContext optimizerContext = OptimizerContext.getContext(schema); + if (optimizerContext == null) { + continue; + } + count += optimizerContext.getLatestSchemaManager().getAllUserTables().size(); + } + return count; + } + + protected static int tableInStatsCount() { + return StatisticManager.getInstance().getStatisticCache().values().stream().mapToInt(Map::size).sum(); + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/entity/PolarDbXSystemTableColumnStatistic.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/entity/PolarDbXSystemTableColumnStatistic.java index 9dae61e52..78660bb1a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/entity/PolarDbXSystemTableColumnStatistic.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/entity/PolarDbXSystemTableColumnStatistic.java @@ -22,6 +22,10 @@ import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.gms.metadb.GmsSystemTables; +import com.alibaba.polardbx.gms.module.LogLevel; +import com.alibaba.polardbx.gms.module.LogPattern; +import com.alibaba.polardbx.gms.module.Module; +import com.alibaba.polardbx.gms.module.ModuleLogInfo; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.config.table.statistic.Histogram; import com.alibaba.polardbx.optimizer.config.table.statistic.TopN; @@ -337,11 +341,11 @@ private boolean innerBatchReplace(final List row String cmSketchString = Base64.encodeBase64String(CountMinSketch.serialize(new CountMinSketch(1, 1, 1))); pps.setString(k * 10 + 5, cmSketchString); - String histogramString; + String histogramString = ""; if (row.getHistogram() != null) { histogramString = Histogram.serializeToJson(row.getHistogram()); - } else { - histogramString = Histogram.serializeToJson(new Histogram(1, DataTypes.IntegerType, 1)); + histogramString = checkHistogramString(histogramString, row.getSchema(), row.getTableName(), + row.getColumnName()); } pps.setString(k * 10 + 6, histogramString); @@ -376,6 +380,20 @@ private boolean innerBatchReplace(final List row } } + /** + * check if histogram serialize string is valid + */ + public static String checkHistogramString(String histogramString, String schema, String tableName, + String columnName) { + Histogram histogram = Histogram.deserializeFromJson(histogramString); + if (histogram == null) { + ModuleLogInfo.getInstance().logRecord(Module.STATISTICS, LogPattern.CHECK_FAIL, + new String[] {"checkHistogramString", schema + "," + tableName + "," + columnName}, + LogLevel.CRITICAL); + } + return histogramString; + } + private boolean canWrite() { return ConfigDataMode.isMasterMode(); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/entity/PolarDbXSystemTableNDVSketchStatistic.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/entity/PolarDbXSystemTableNDVSketchStatistic.java index 6c362d871..5d7e6e798 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/entity/PolarDbXSystemTableNDVSketchStatistic.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/entity/PolarDbXSystemTableNDVSketchStatistic.java @@ -26,6 +26,7 @@ import com.alibaba.polardbx.optimizer.config.table.statistic.inf.SystemTableNDVSketchStatistic; import com.google.common.collect.Lists; +import javax.sql.DataSource; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -73,11 +74,11 @@ public class PolarDbXSystemTableNDVSketchStatistic implements SystemTableNDVSket + "TABLE_NAME = ? "; private static final String LOAD_ALL_SQL = - "SELECT `SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAMES`, `SHARD_PART`, `DN_CARDINALITY`, `COMPOSITE_CARDINALITY`, `SKETCH_TYPE`, `GMT_MODIFIED`, `GMT_CREATED` FROM " + "SELECT `SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAMES`, `SHARD_PART`, `INDEX_NAME`, `DN_CARDINALITY`, `COMPOSITE_CARDINALITY`, `SKETCH_TYPE`, `GMT_MODIFIED`, `GMT_CREATED` FROM " + TABLE_NAME; private static final String LOAD_BY_TABLE_NAME_SQL = - "SELECT `SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAMES`, `SHARD_PART`, `DN_CARDINALITY`, `COMPOSITE_CARDINALITY`, `SKETCH_TYPE`, `GMT_MODIFIED`, `GMT_CREATED` FROM `" + "SELECT `SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAMES`, `SHARD_PART`, `INDEX_NAME`, `DN_CARDINALITY`, `COMPOSITE_CARDINALITY`, `SKETCH_TYPE`, `GMT_MODIFIED`, `GMT_CREATED` FROM `" + TABLE_NAME + "` WHERE SCHEMA_NAME = ? AND TABLE_NAME = ?"; private static final String LOAD_BY_TABLE_NAME_AND_COLUMN_NAME_SQL = @@ -88,7 +89,8 @@ public class PolarDbXSystemTableNDVSketchStatistic implements SystemTableNDVSket * select table rows sql, need to concat with values */ private static final String REPLACE_SQL = "REPLACE INTO `" + TABLE_NAME + - "` (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAMES`, `SHARD_PART`, `DN_CARDINALITY`, `COMPOSITE_CARDINALITY`, `SKETCH_BYTES`, `SKETCH_TYPE`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; + "` (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAMES`, `SHARD_PART`, `INDEX_NAME`, `DN_CARDINALITY`, `COMPOSITE_CARDINALITY`, `SKETCH_BYTES`, `SKETCH_TYPE`) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; /** * update composite cardinality @@ -206,6 +208,7 @@ public SketchRow[] loadAll() { rs.getString("TABLE_NAME"), rs.getString("COLUMN_NAMES"), rs.getString("SHARD_PART"), + rs.getString("INDEX_NAME"), rs.getLong("DN_CARDINALITY"), rs.getLong("COMPOSITE_CARDINALITY"), rs.getString("SKETCH_TYPE"), @@ -247,6 +250,7 @@ public SketchRow[] loadByTableName(String schemaName, String tableName) { rs.getString("TABLE_NAME"), rs.getString("COLUMN_NAMES"), rs.getString("SHARD_PART"), + rs.getString("INDEX_NAME"), rs.getLong("DN_CARDINALITY"), rs.getLong("COMPOSITE_CARDINALITY"), rs.getString("SKETCH_TYPE"), @@ -281,10 +285,11 @@ public void batchReplace(SketchRow[] sketchRows) { ps.setString(2, sketchRow.getTableName()); ps.setString(3, sketchRow.getColumnNames()); ps.setString(4, sketchRow.getShardPart()); - ps.setLong(5, sketchRow.getDnCardinality()); - ps.setLong(6, sketchRow.getCompositeCardinality()); - ps.setBytes(7, sketchRow.getSketchBytes()); - ps.setString(8, sketchRow.getSketchType()); + ps.setString(5, sketchRow.getIndexName()); + ps.setLong(6, sketchRow.getDnCardinality()); + ps.setLong(7, sketchRow.getCompositeCardinality()); + ps.setBytes(8, sketchRow.getSketchBytes()); + ps.setString(9, sketchRow.getSketchType()); ps.addBatch(); } @@ -329,8 +334,8 @@ public void updateCompositeCardinality(String schemaName, String tableName, Stri } @Override - public void loadByTableNameAndColumnName(String schemaName, String tableName, String columnName, - Map shardParts, int[] registers) { + public boolean loadByTableNameAndColumnName(String schemaName, String tableName, String columnName, + Map shardParts, int[] registers) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; @@ -354,6 +359,9 @@ public void loadByTableNameAndColumnName(String schemaName, String tableName, St if (oneRow == null || oneRow.length == 0) { throw new IllegalArgumentException("sketch bytes not ready yet"); } + if (oneRow.length == 1) { + throw new IllegalArgumentException("sketch bytes from columnar"); + } BitSet bitSet = BitSet.valueOf(oneRow); for (int j = 0; j * 6 < HLL_REGBYTES * 8; j++) {// cal the reciprocal @@ -371,11 +379,55 @@ public void loadByTableNameAndColumnName(String schemaName, String tableName, St } } catch (Exception e) { logger.error("select " + TABLE_NAME + " error", e); + return false; } finally { JdbcUtils.close(rs); JdbcUtils.close(ps); JdbcUtils.close(conn); } + return true; + } + + public boolean deleteByColumn(String schemaName, String tableName, String columns) { + return deleteByColumn(schemaName, tableName, columns, MetaDbDataSource.getInstance().getDataSource()); + } + + /** + * Deletes records based on the specified schema name, table name, and column names. + * + * @param schemaName The schema name to operate on + * @param tableName The table name to operate on + * @param columns The list of column names + */ + public boolean deleteByColumn(String schemaName, String tableName, String columns, DataSource dataSource) { + // Return early if not in master mode + if (!ConfigDataMode.isMasterMode() || dataSource == null) { + return false; + } + + Connection conn = null; + PreparedStatement ps = null; + + try { + conn = dataSource.getConnection(); + ps = conn.prepareStatement(DELETED_BY_TABLENAME_COLUMNS_SQL); + + // Set parameter values (converted to lowercase) + ps.setString(1, schemaName.toLowerCase()); + ps.setString(2, tableName.toLowerCase()); + ps.setString(3, columns.toLowerCase()); + + ps.executeUpdate(); + return true; + } catch (SQLException e) { + // Log error message + logger.error("Delete " + TABLE_NAME + " error, SQL statement: " + DELETED_BY_TABLENAME_COLUMNS_SQL + + ", parameters: " + schemaName + "," + tableName + "," + columns, e); + return false; + } finally { + JdbcUtils.close(ps); + JdbcUtils.close(conn); + } } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/ndv/NDVShardSketch.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/ndv/NDVShardSketch.java index 963d4ce6e..bed8face6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/ndv/NDVShardSketch.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/ndv/NDVShardSketch.java @@ -26,26 +26,32 @@ import com.alibaba.polardbx.common.utils.LoggerUtil; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.druid.util.StringUtils; import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.ddl.newengine.cross.CrossEngineValidator; +import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; import com.alibaba.polardbx.executor.statistic.entity.PolarDbXSystemTableNDVSketchStatistic; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; import com.alibaba.polardbx.executor.sync.UpdateStatisticSyncAction; +import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; import com.alibaba.polardbx.executor.utils.failpoint.FailPointKey; import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.module.LogLevel; import com.alibaba.polardbx.gms.module.Module; import com.alibaba.polardbx.gms.module.ModuleLogInfo; +import com.alibaba.polardbx.gms.node.MppScope; import com.alibaba.polardbx.gms.sync.SyncScope; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import com.alibaba.polardbx.optimizer.config.table.IndexMeta; import com.alibaba.polardbx.optimizer.config.table.TableMeta; -import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticManager; import com.alibaba.polardbx.optimizer.config.table.statistic.inf.SystemTableNDVSketchStatistic; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.exception.TableNotFoundException; +import com.alibaba.polardbx.optimizer.optimizeralert.OptimizerAlertUtil; import com.alibaba.polardbx.optimizer.exception.TableNotFoundException; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -67,6 +73,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_HLL; import static com.alibaba.polardbx.executor.statistic.ndv.HyperLogLogUtil.HLL_REGISTERS; @@ -99,6 +106,7 @@ public class NDVShardSketch { */ private final String shardKey; + private String indexName; /** * one shard for one physical table */ @@ -132,10 +140,11 @@ public class NDVShardSketch { private long cardinality = -1; - public NDVShardSketch(String shardKey, String[] shardParts, long[] dnCardinalityArray, String sketchType, - long[] gmtUpdate, long[] gmtCreated) { + public NDVShardSketch(String shardKey, String[] shardParts, String indexName, long[] dnCardinalityArray, + String sketchType, long[] gmtUpdate, long[] gmtCreated) { this.shardKey = shardKey; this.shardParts = shardParts; + this.indexName = indexName; this.dnCardinalityArray = dnCardinalityArray; this.sketchType = sketchType; this.gmtUpdate = gmtUpdate; @@ -154,58 +163,6 @@ public long getCardinality() { return cardinality; } - /** - * check the validity of the shard parts - * table might change the topology by ddl - */ - public boolean validityCheck() { - String[] shardInfo = shardKey.split(":"); - String schemaName = shardInfo[0]; - String tableName = shardInfo[1]; - Map> topologyTmp; - try { - OptimizerContext op = OptimizerContext.getContext(schemaName); - if (op == null) { - return false; - } - topologyTmp = op.getLatestSchemaManager().getTable(tableName).getLatestTopology(); - } catch (TableNotFoundException tableNotFoundException) { - return false; - } - - Map> topology = Maps.newHashMap(); - - // build new map to avoid concurrency update problem - for (Map.Entry> entry : topologyTmp.entrySet()) { - Set phyTbls = Sets.newHashSet(); - entry.getValue().stream().forEach(s -> phyTbls.add(s.toLowerCase())); - topology.put(entry.getKey().toLowerCase(), phyTbls); - } - - // build topology map using statistic info - Map> topologyStatistic = Maps.newHashMap(); - for (String shardPart : shardParts) { - String[] parts = shardPart.split(":"); - String nodeName = parts[0]; - String phyTableNames = parts[1]; - if (topologyStatistic.containsKey(nodeName)) { - topologyStatistic.get(nodeName).addAll(Arrays.asList(phyTableNames.split(","))); - } else { - topologyStatistic.put(nodeName, Sets.newHashSet(Arrays.asList(phyTableNames.split(",")))); - } - } - - // check if the statistic topology contains full real topology - for (Map.Entry> entry : topology.entrySet()) { - Set physicalTables = topologyStatistic.get(entry.getKey().toLowerCase()); - if (physicalTables == null || !physicalTables.containsAll(entry.getValue())) { - setCardinality(-1); - return false; - } - } - return true; - } - public long lastModifyTime() { if (lastGmtUpdate == -1L) { lastGmtUpdate = Arrays.stream(gmtUpdate).max().getAsLong(); @@ -213,10 +170,25 @@ public long lastModifyTime() { return lastGmtUpdate; } + public long[] getGmtCreated() { + return gmtCreated; + } + + public boolean anyShardExpired() { + int expiredTime = InstConfUtil.getInt(ConnectionParams.STATISTIC_NDV_SKETCH_EXPIRE_TIME); + long current = System.currentTimeMillis(); + for (long updateTime : getGmtCreated()) { + if (current - updateTime > expiredTime) { + return true; + } + } + return false; + } + /** * update all shard parts */ - public boolean updateAllShardParts() throws SQLException { + public boolean updateAllShardParts(ExecutionContext ec) throws Exception { if (!InstConfUtil.getBool(ConnectionParams.ENABLE_HLL)) { // just return ModuleLogInfo.getInstance() @@ -266,7 +238,7 @@ shardKey, shardParts[i], new Date(current).toString(), new Date(gmtUpdate[i]).to long cardinalityTmp = getCurrentCardinality(shardKey, shardParts[i]); cardinalityTime += System.currentTimeMillis() - start; start = System.currentTimeMillis(); - byte[] bytes = getCurrentHll(shardKey, shardParts[i], false, null); + byte[] bytes = getCurrentHll(shardKey, shardParts[i], indexName, false, ec); if (bytes == null) { // null meaning the hll request is stopped by something ModuleLogInfo.getInstance() @@ -283,7 +255,7 @@ shardKey, shardParts[i], new Date(current).toString(), new Date(gmtUpdate[i]).to dnCardinalityArray[i] = cardinalityTmp; gmtUpdate[i] = System.currentTimeMillis(); SystemTableNDVSketchStatistic.SketchRow sketchRow = new SystemTableNDVSketchStatistic.SketchRow - (schemaName, tableName, columnNames, shardParts[i], dnCardinalityArray[i], -1, + (schemaName, tableName, columnNames, shardParts[i], indexName, dnCardinalityArray[i], -1, "HYPER_LOG_LOG"); sketchRow.setSketchBytes(bytes); PolarDbXSystemTableNDVSketchStatistic.getInstance() @@ -306,8 +278,10 @@ shardKey, shardParts[i], new Date(current).toString(), new Date(gmtUpdate[i]).to */ int[] registers = new int[HLL_REGISTERS]; try { - PolarDbXSystemTableNDVSketchStatistic.getInstance() - .loadByTableNameAndColumnName(schemaName, tableName, columnNames, updateBytes, registers); + if (!PolarDbXSystemTableNDVSketchStatistic.getInstance() + .loadByTableNameAndColumnName(schemaName, tableName, columnNames, updateBytes, registers)) { + return false; + } /** * compute new cardinality */ @@ -453,7 +427,7 @@ public static Map> shardPartToTopology(String shardPart) { /** * @param topology map group node name -> set - * @return shardPart physical node:table name,table name;* + * @return shardPart physical node:table name */ public static String[] topologyPartToShard(Map> topology) { int shardNum = topology.entrySet().stream().mapToInt(e -> e.getValue().size()).sum(); @@ -476,7 +450,7 @@ public static String[] topologyPartToShard(Map> topology) { public static NDVShardSketch buildNDVShardSketch(String schemaName, String tableName, String columnName, boolean isForce, ExecutionContext ec, ThreadPoolExecutor sketchHllExecutor) - throws SQLException { + throws Exception { if (!InstConfUtil.getBool(ConnectionParams.ENABLE_HLL)) { // just return ModuleLogInfo.getInstance() @@ -501,11 +475,13 @@ public static NDVShardSketch buildNDVShardSketch(String schemaName, String table ); String shardKey = buildSketchKey(schemaName, tableName, columnName); - // shard parts build - String[] shardPart = buildShardParts(schemaName, tableName); - if (shardPart == null) { + // build shard parts and physical index + Pair rs = buildShardParts(schemaName, tableName, columnName); + if (rs == null) { return null; } + String indexName = rs.getKey(); + String[] shardPart = rs.getValue(); long[] dnCardinalityArray = new long[shardPart.length]; String sketchType = "HYPER_LOG_LOG"; byte[][] sketchArray = new byte[shardPart.length][]; @@ -533,13 +509,22 @@ public static NDVShardSketch buildNDVShardSketch(String schemaName, String table // fill cardinality and sketch bytes for (int i = 0; i < shardPart.length; i++) { if (sketchHllExecutor == null) { - sketchOnePart(shardKey, shardPart, dnCardinalityArray, sketchArray, gmtCreated, gmtUpdate, + sketchOnePart(shardKey, shardPart, indexName, dnCardinalityArray, sketchArray, gmtCreated, + gmtUpdate, cardinalityTime, sketchTime, isForce, ec, i, stopped); } else { final int partIdx = i; Future future = sketchHllExecutor.submit( - () -> sketchOnePart(shardKey, shardPart, dnCardinalityArray, sketchArray, gmtCreated, gmtUpdate, - cardinalityTime, sketchTime, isForce, ec, partIdx, stopped)); + () -> { + try { + sketchOnePart(shardKey, shardPart, indexName, dnCardinalityArray, sketchArray, + gmtCreated, + gmtUpdate, + cardinalityTime, sketchTime, isForce, ec, partIdx, stopped); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); futures.add(future); } } @@ -572,7 +557,7 @@ public static NDVShardSketch buildNDVShardSketch(String schemaName, String table ); NDVShardSketch ndvShardSketch = - new NDVShardSketch(shardKey, shardPart, dnCardinalityArray, sketchType, gmtUpdate, gmtCreated); + new NDVShardSketch(shardKey, shardPart, indexName, dnCardinalityArray, sketchType, gmtUpdate, gmtCreated); ndvShardSketch.setCardinality(cardinality); // persist @@ -594,22 +579,16 @@ private static long sketchByColumnar(String shardKey, String[] shardPart, long[] dnCardinalityArray, byte[][] sketchArray, long[] gmtCreated, long[] gmtUpdate, AtomicLong cardinalityTime, AtomicLong sketchTime, ExecutionContext ec) { - String hint = genColumnarHllHint(ec); - if (StringUtil.isEmpty(hint)) { - return -1; - } String[] shardKeys = shardKey.split(":"); String schemaName = shardKeys[0]; String tableName = shardKeys[1]; String columnsName = shardKeys[2]; - TableMeta tm = OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTableWithNull(tableName); - if (tm == null) { - return -1; - } - // must be a table with columnar indexes - if (GeneralUtil.isEmpty(tm.getColumnarIndexPublished())) { + + String hint = genColumnarHllHint(ec, schemaName, tableName); + if (StringUtil.isEmpty(hint)) { return -1; } + long cardinality = -1; // must visit columnar indexes long start = System.currentTimeMillis(); @@ -639,15 +618,23 @@ private static long sketchByColumnar(String shardKey, String[] shardPart, return cardinality; } - public static String genColumnarHllHint(ExecutionContext ec) { - boolean isNdv = (ec == null) ? - InstConfUtil.getBool(ConnectionParams.ENABLE_NDV_USE_COLUMNAR) : - ec.getParamManager().getBoolean(ConnectionParams.ENABLE_NDV_USE_COLUMNAR); + public static String genColumnarHllHint(ExecutionContext ec, String schemaName, String tableName) { + TableMeta tm = OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTableWithNull(tableName); + if (tm == null) { + return null; + } + // must be a table with columnar indexes + if (GeneralUtil.isEmpty(tm.getColumnarIndexPublished())) { + return null; + } + return genColumnarHllHint(ec); + } + public static String genColumnarHllHint(ExecutionContext ec) { boolean isMppNdv = (ec == null) ? InstConfUtil.getBool(ConnectionParams.ENABLE_MPP_NDV_USE_COLUMNAR) : ec.getParamManager().getBoolean(ConnectionParams.ENABLE_MPP_NDV_USE_COLUMNAR); - if (!(isNdv || isMppNdv)) { + if (!isMppNdv) { return null; } StringBuilder sb = new StringBuilder("/*+TDDL:cmd_extra("); @@ -661,21 +648,34 @@ public static String genColumnarHllHint(ExecutionContext ec) { sb.append(ConnectionProperties.WORKLOAD_TYPE).append("=AP "); sb.append(ConnectionProperties.ENABLE_COLUMNAR_OPTIMIZER).append("=true "); - if (isMppNdv) { - // use master mpp - sb.append(ConnectionProperties.ENABLE_HTAP).append("=true "); - sb.append(ConnectionProperties.ENABLE_MASTER_MPP).append("=true "); + // diable block cache + sb.append(ConnectionProperties.ENABLE_BLOCK_CACHE).append("=false "); + // use master mpp + sb.append(ConnectionProperties.ENABLE_HTAP).append("=true "); + sb.append(ConnectionProperties.ENABLE_MASTER_MPP).append("=true "); + boolean limit = (ec == null) ? + InstConfUtil.getBool(ConnectionParams.MPP_NDV_USE_COLUMNAR_LIMIT) : + ec.getParamManager().getBoolean(ConnectionParams.MPP_NDV_USE_COLUMNAR_LIMIT); + if (limit) { + MppScope mppScope = ExecUtils.getMppSchedulerScope(false); + if (mppScope == MppScope.CURRENT) { + // master node, limit PARALLELISM + int parallelism = ServiceProvider.getInstance().getServer() + .getNodeManager().getAllNodes().getAllWorkers(mppScope).size(); + sb.append(ConnectionProperties.MPP_PARALLELISM).append("=").append(parallelism).append(" "); + sb.append(ConnectionProperties.MPP_NODE_SIZE).append("=").append(parallelism).append(" "); + } } sb.append(")*/"); return sb.toString(); } - private static void sketchOnePart(String shardKey, String[] shardPart, + private static void sketchOnePart(String shardKey, String[] shardPart, String indexName, long[] dnCardinalityArray, byte[][] sketchArray, long[] gmtCreated, long[] gmtUpdate, AtomicLong cardinalityTime, AtomicLong sketchTime, boolean isForce, ExecutionContext ec, - int idx, AtomicBoolean stopped) { + int idx, AtomicBoolean stopped) throws Exception { try { if (stopped.get()) { return; @@ -684,7 +684,7 @@ private static void sketchOnePart(String shardKey, String[] shardPart, dnCardinalityArray[idx] = getCurrentCardinality(shardKey, shardPart[idx]); long mid = System.currentTimeMillis(); cardinalityTime.getAndAdd(mid - start); - sketchArray[idx] = getCurrentHll(shardKey, shardPart[idx], isForce, ec); + sketchArray[idx] = getCurrentHll(shardKey, shardPart[idx], indexName, isForce, ec); sketchTime.getAndAdd(System.currentTimeMillis() - mid); if (sketchArray[idx] == null) { gmtUpdate[idx] = 0L; @@ -706,19 +706,53 @@ private static boolean isSketchDataReady(byte[][] sketchArray) { /** * build shard parts, every phy table is one shard part. */ - public static String[] buildShardParts(String schemaName, String tableName) { + public static Pair buildShardParts(String schemaName, String tableName, String columnNames) { OptimizerContext op = OptimizerContext.getContext(schemaName); if (op == null) { return null; } - // shard parts build + List targetCols = Lists.newArrayList(columnNames.split(",")); + // find index for target columns + TableMeta tableMeta = op.getLatestSchemaManager().getTable(tableName); + if (tableMeta == null) { + return null; + } + + // try main table first + for (IndexMeta indexMeta : tableMeta.getIndexes()) { + List keys = indexMeta.getKeyColumns(); + if (keys.stream().map(ColumnMeta::getName).collect(Collectors.toList()).containsAll(targetCols)) { + Map> topologyMap = getTopology(schemaName, tableName, op); + return Pair.of(indexMeta.getPhysicalIndexName(), topologyPartToShard(topologyMap)); + } + } + // try gsi + for (GsiMetaManager.GsiIndexMetaBean gsiIndexMetaBean : tableMeta.getGsiPublished().values()) { + List keys = gsiIndexMetaBean.indexColumns; + if (keys.stream().map(gsi -> gsi.columnName).collect(Collectors.toList()).containsAll(targetCols)) { + TableMeta gsiMeta = op.getLatestSchemaManager().getTable(gsiIndexMetaBean.indexTableName); + for (IndexMeta indexMeta : gsiMeta.getIndexes()) { + List keysInGsi = indexMeta.getKeyColumns(); + if (keysInGsi.stream().map(ColumnMeta::getName).collect(Collectors.toList()) + .containsAll(targetCols)) { + Map> topologyMap = + getTopology(schemaName, gsiIndexMetaBean.indexTableName, op); + return Pair.of(indexMeta.getPhysicalIndexName(), topologyPartToShard(topologyMap)); + } + } + } + } + return null; + } + + public static Map> getTopology(String schemaName, String tableName, OptimizerContext op) { Map> topologyMap; if (!DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { topologyMap = op.getRuleManager().getTddlRule().getTable(tableName).getActualTopology(); } else { topologyMap = op.getPartitionInfoManager().getPartitionInfo(tableName).getTopology(); } - return topologyPartToShard(topologyMap); + return topologyMap; } /** @@ -727,7 +761,8 @@ public static String[] buildShardParts(String schemaName, String tableName) { * @param shardPart one physical table * @param ifForce true meaning from `analyze table`, false meaning from scheduled work */ - private static byte[] getCurrentHll(String shardKey, String shardPart, boolean ifForce, ExecutionContext ec) { + private static byte[] getCurrentHll(String shardKey, String shardPart, String indexName, boolean ifForce, + ExecutionContext ec) throws Exception { String[] shardKeys = shardKey.split(":"); String schemaName = shardKeys[0]; @@ -766,7 +801,8 @@ private static byte[] getCurrentHll(String shardKey, String shardPart, boolean i } // add time check - if (!ifForce) { + if ((!ifForce) && + (ec == null || !ec.getParamManager().getBoolean(ConnectionParams.ANALYZE_TEST_UPDATE))) { Pair p = needSketchInterrupted(); if (p.getKey()) { // just return @@ -802,12 +838,14 @@ private static byte[] getCurrentHll(String shardKey, String shardPart, boolean i // check if columnsName represent one column or one index String sql; + if (!StringUtils.isEmpty(indexName)) { + physicalTable = physicalTable + " force index(" + indexName + ")"; + } if (!columnsName.contains(",")) { sql = String.format(HYPER_LOG_LOG_SQL, columnsName, physicalTable); } else { sql = String.format(HYPER_LOG_LOG_MUL_COLUMNS_SQL, columnsName, physicalTable); } - ModuleLogInfo.getInstance() .logRecord( Module.STATISTICS, @@ -845,13 +883,8 @@ private static byte[] getCurrentHll(String shardKey, String shardPart, boolean i } hllBytes = rs.getBytes("HLL"); } - } catch (SQLException ex) { - // MySQL Error = 1146 and MySQL SQLState = 42S02 indicate that the target table doesn't exist. - if (ex.getErrorCode() == 1146 && ex.getSQLState().equals("42S02")) { - StatisticManager.getInstance().getSds() - .removeLogicalTableList(schemaName, Lists.newArrayList(shardKeys[1])); - return null; - } + } catch (Exception e) { + handleException(shardKey, shardPart, e, schemaName, shardKeys); } finally { try { if (rs != null) { @@ -900,7 +933,7 @@ public SystemTableNDVSketchStatistic.SketchRow[] serialize(byte[][] sketchBytes, } SystemTableNDVSketchStatistic.SketchRow sketchRow = new SystemTableNDVSketchStatistic.SketchRow(schemaName, tableName, columnNames, - shardParts[i], dnCardinalityArray[i], cardinality, + shardParts[i], indexName, dnCardinalityArray[i], cardinality, sketchType, sketchByte, gmtCreated[i], gmtUpdate[i]); rows.add(sketchRow); } @@ -908,6 +941,17 @@ public SystemTableNDVSketchStatistic.SketchRow[] serialize(byte[][] sketchBytes, return rows.toArray(new SystemTableNDVSketchStatistic.SketchRow[0]); } + public static void handleException(String shardKey, String shardPart, Exception e, String schemaName, + String[] shardKeys) throws Exception { + ModuleLogInfo.getInstance().logRecord( + Module.STATISTICS, + UNEXPECTED, + new String[] {"ndv sketch " + shardKey + "," + shardPart, e.getMessage()}, + LogLevel.CRITICAL, e); + OptimizerAlertUtil.statisticErrorAlert(); + throw e; + } + public String getSketchType() { return sketchType; } @@ -915,4 +959,60 @@ public String getSketchType() { public void setCardinality(long cardinality) { this.cardinality = cardinality; } + + public String getIndexName() { + return indexName; + } + + public void setIndexName(String indexName) { + this.indexName = indexName; + } + + /** + * Determines whether the current shard information is valid. + * + * @return Returns null if the table or schema does not exist; otherwise returns true or false indicating the validity of the shard information. + */ + public static Boolean isValidShardPart(String shardKey, String[] shardParts) { + // Split the shard key to extract the schema name, table name, and column names. + String[] shardInfo = shardKey.split(":"); + if (shardInfo.length != 3) { + return null; + } + String schemaName = shardInfo[0]; + String tableName = shardInfo[1]; + String columnNames = shardInfo[2]; + + // Build the shard parts based on the extracted information. + Pair result = buildShardParts(schemaName, tableName, columnNames); + + // If the result is null, it means that either the table or the schema does not exist. + if (result == null) { + return null; + } + + // Retrieve the array of shard parts from the result. + String[] currentShardParts = result.getValue(); + + // Convert the shard parts arrays into lists for comparison. + Set instanceShardPartsList = Sets.newHashSet(shardParts); + Set builtShardPartsList = Sets.newHashSet(currentShardParts); + + // Check if both lists are equal, which indicates that the shard parts match exactly. + return instanceShardPartsList.equals(builtShardPartsList); + } + + /** + * schemaName:table name:columns name + */ + public String getShardKey() { + return shardKey; + } + + /** + * one shard for one physical table + */ + public String[] getShardParts() { + return shardParts; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/ndv/NDVSketch.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/ndv/NDVSketch.java index 0414a9836..96ef4ef5e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/ndv/NDVSketch.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/statistic/ndv/NDVSketch.java @@ -19,6 +19,7 @@ import com.alibaba.polardbx.druid.util.StringUtils; import com.alibaba.polardbx.executor.gms.util.StatisticUtils; import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.executor.statistic.entity.PolarDbXSystemTableNDVSketchStatistic; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; import com.alibaba.polardbx.executor.sync.UpdateStatisticSyncAction; import com.alibaba.polardbx.gms.scheduler.ScheduledJobExecutorType; @@ -33,7 +34,6 @@ import com.google.common.collect.Maps; import org.glassfish.jersey.internal.guava.Sets; -import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.Set; @@ -47,13 +47,11 @@ * ndv sketch service for one schema */ public class NDVSketch implements NDVSketchService { - /** - * schemaName:table name:columns name -> sketch - */ private Map stringNDVShardSketchMap = Maps.newConcurrentMap(); public void parse(SystemTableNDVSketchStatistic.SketchRow[] sketchRows) { Map> shardParts = Maps.newHashMap(); + Map indexNameMap = Maps.newHashMap(); Map> dnCardinalityArray = Maps.newHashMap(); Map> gmtUpdate = Maps.newHashMap(); Map> gmtCreated = Maps.newHashMap(); @@ -62,7 +60,7 @@ public void parse(SystemTableNDVSketchStatistic.SketchRow[] sketchRows) { Set invalidRows = Sets.newHashSet(); for (SystemTableNDVSketchStatistic.SketchRow sketchRow : sketchRows) { - // schemaName:table name:column name + // schemaName:table name:column name or schemaName:table name:column name String sketchKey = buildSketchKey(sketchRow); if (shardParts.containsKey(sketchKey)) { shardParts.get(sketchKey).add(sketchRow.getShardPart()); @@ -71,6 +69,7 @@ public void parse(SystemTableNDVSketchStatistic.SketchRow[] sketchRows) { tmpList.add(sketchRow.getShardPart()); shardParts.put(sketchKey, tmpList); } + indexNameMap.put(sketchKey, sketchRow.getIndexName()); if (dnCardinalityArray.containsKey(sketchKey)) { dnCardinalityArray.get(sketchKey).add(sketchRow.getDnCardinality()); @@ -105,6 +104,7 @@ public void parse(SystemTableNDVSketchStatistic.SketchRow[] sketchRows) { } NDVShardSketch ndvShardSketch = new NDVShardSketch(sketchKey, shardParts.get(sketchKey).toArray(new String[0]), + indexNameMap.get(sketchKey), dnCardinalityArray.get(sketchKey).stream().mapToLong(e -> e.longValue()).toArray(), "HYPER_LOG_LOG", gmtUpdate.get(sketchKey).stream().mapToLong(e -> e.longValue()).toArray(), gmtCreated.get(sketchKey).stream().mapToLong(e -> e.longValue()).toArray()); @@ -115,22 +115,32 @@ public void parse(SystemTableNDVSketchStatistic.SketchRow[] sketchRows) { @Override public void remove(String schema, String tableName) { - List removeList = Lists.newLinkedList(); + // lower case + if (StringUtils.isEmpty(schema) || StringUtils.isEmpty(tableName)) { + return; + } + schema = schema.toLowerCase(); + tableName = tableName.toLowerCase(); for (String sketchKey : stringNDVShardSketchMap.keySet()) { - if (sketchKey.startsWith(schema + ":" + tableName.toLowerCase() + ":")) { - removeList.add(sketchKey); + if (sketchKey.startsWith(schema + ":" + tableName + ":")) { + String columns = sketchKey.split(":")[2]; + remove(schema, tableName, columns); } } - removeList.forEach(sketchKey -> stringNDVShardSketchMap.remove(sketchKey)); } @Override public void remove(String schema, String tableName, String columns) { - if (StringUtils.isEmpty(tableName) || StringUtils.isEmpty(columns)) { + if (StringUtils.isEmpty(schema) || StringUtils.isEmpty(tableName) || StringUtils.isEmpty(columns)) { return; } + schema = schema.toLowerCase(); + tableName = tableName.toLowerCase(); + columns = columns.toLowerCase(); + String sketchKey = buildSketchKey(schema, tableName, columns); stringNDVShardSketchMap.remove(sketchKey); + PolarDbXSystemTableNDVSketchStatistic.getInstance().deleteByColumn(schema, tableName, columns); } public StatisticResult getCardinality(String schema, String tableName, String columnNames, boolean isNeedTrace) { @@ -209,11 +219,19 @@ public void cleanCache() { @Override public void updateAllShardParts(String schema, String tableName, String columnName, ExecutionContext ec, - ThreadPoolExecutor sketchHllExecutor) throws SQLException { + ThreadPoolExecutor sketchHllExecutor) throws Exception { + if (StringUtils.isEmpty(schema) || StringUtils.isEmpty(tableName) || StringUtils.isEmpty(columnName)) { + return; + } String ndvKey = buildSketchKey(schema, tableName, columnName); - if (!stringNDVShardSketchMap.containsKey(ndvKey)) { - // rebuild sketch - NDVShardSketch ndvShardSketch = + // rebuild sketch if the hll doesn't exist or table topology changed + NDVShardSketch ndvShardSketch = stringNDVShardSketchMap.get(ndvKey); + + if (ndvShardSketch == null || + !NDVShardSketch.isValidShardPart(ndvShardSketch.getShardKey(), ndvShardSketch.getShardParts())) { + // clear&rebuild sketch if topology changed + remove(schema, tableName, columnName); + ndvShardSketch = NDVShardSketch.buildNDVShardSketch(schema, tableName, columnName, false, ec, sketchHllExecutor); if (ndvShardSketch != null) { stringNDVShardSketchMap.put(ndvKey, ndvShardSketch); @@ -221,8 +239,18 @@ public void updateAllShardParts(String schema, String tableName, String columnNa return; } - NDVShardSketch ndvShardSketch = stringNDVShardSketchMap.get(ndvKey); - boolean hasUpdate = ndvShardSketch.updateAllShardParts(); + if (NDVShardSketch.genColumnarHllHint(ec, schema, tableName) != null) { + if (ndvShardSketch.anyShardExpired()) { + ndvShardSketch = + NDVShardSketch.buildNDVShardSketch(schema, tableName, columnName, false, ec, sketchHllExecutor); + if (ndvShardSketch != null) { + stringNDVShardSketchMap.put(ndvKey, ndvShardSketch); + } + } + return; + } + + boolean hasUpdate = ndvShardSketch.updateAllShardParts(ec); if (hasUpdate) { /** sync other nodes */ SyncManagerHelper.syncWithDefaultDB( @@ -236,9 +264,9 @@ public void updateAllShardParts(String schema, String tableName, String columnNa @Override public void reBuildShardParts(String schema, String tableName, String columnName, ExecutionContext ec, - ThreadPoolExecutor sketchHllExecutor) throws SQLException { + ThreadPoolExecutor sketchHllExecutor) throws Exception { // only analyze table would enter here - remove(tableName, columnName); + remove(schema, tableName, columnName); String ndvKey = buildSketchKey(schema, tableName, columnName); NDVShardSketch ndvShardSketch = NDVShardSketch.buildNDVShardSketch(schema, tableName, columnName, true, ec, sketchHllExecutor); @@ -246,4 +274,11 @@ public void reBuildShardParts(String schema, String tableName, String columnName stringNDVShardSketchMap.put(ndvKey, ndvShardSketch); } } + + /** + * schemaName:table name:columns name -> sketch + */ + public Map getStringNDVShardSketchMap() { + return stringNDVShardSketchMap; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/BaselineDeleteHotEvolvedSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/BaselineDeleteHotEvolvedSyncAction.java new file mode 100644 index 000000000..c7baae7df --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/BaselineDeleteHotEvolvedSyncAction.java @@ -0,0 +1,30 @@ +package com.alibaba.polardbx.executor.sync; + +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.gms.util.SyncUtil; +import com.alibaba.polardbx.optimizer.planmanager.PlanManager; + +public class BaselineDeleteHotEvolvedSyncAction implements ISyncAction { + + String schema; + + public BaselineDeleteHotEvolvedSyncAction(String schema) { + this.schema = schema; + } + + @Override + public ResultCursor sync() { + PlanManager.getInstance().deleteBaselineEvolved(schema); + return null; + } + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + +} + diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/BaselineDeleteSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/BaselineDeleteSyncAction.java new file mode 100644 index 000000000..f6b88334e --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/BaselineDeleteSyncAction.java @@ -0,0 +1,69 @@ +package com.alibaba.polardbx.executor.sync; + +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.gms.module.ModuleLogInfo; +import com.alibaba.polardbx.optimizer.planmanager.PlanManager; + +import static com.alibaba.polardbx.gms.module.LogLevel.NORMAL; +import static com.alibaba.polardbx.gms.module.LogPattern.PROCESSING; +import static com.alibaba.polardbx.gms.module.Module.SPM; + +public class BaselineDeleteSyncAction implements ISyncAction { + + private String schemaName; + + private Integer baselineId; + + private Integer planInfoId; + + public BaselineDeleteSyncAction(String schemaName, Integer baselineId) { + this.schemaName = schemaName; + this.baselineId = baselineId; + this.planInfoId = null; + } + + public BaselineDeleteSyncAction(String schemaName, Integer baselineId, int planInfoId) { + this.schemaName = schemaName; + this.baselineId = baselineId; + this.planInfoId = planInfoId; + } + + public String getSchemaName() { + return schemaName; + } + + public void setSchemaName(String schemaName) { + this.schemaName = schemaName; + } + + @Override + public ResultCursor sync() { + if (planInfoId != null && planInfoId != 0) { + ModuleLogInfo.getInstance() + .logRecord(SPM, PROCESSING, new String[] {"delete plan " + planInfoId, baselineId + ""}, NORMAL); + PlanManager.getInstance().deleteBaselinePlan(schemaName, baselineId, planInfoId); + } else { + ModuleLogInfo.getInstance() + .logRecord(SPM, PROCESSING, new String[] {"delete baseline ", baselineId + ""}, NORMAL); + PlanManager.getInstance().deleteBaseline(schemaName, baselineId); + } + return null; + } + + public Integer getPlanInfoId() { + return planInfoId; + } + + public void setPlanInfoId(Integer planInfoId) { + this.planInfoId = planInfoId; + } + + public Integer getBaselineId() { + return baselineId; + } + + public void setBaselineId(Integer baselineId) { + this.baselineId = baselineId; + } +} + diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/DeleteBaselineSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/DeleteBaselineSyncAction.java index 0f37ae7ce..e71e43214 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/DeleteBaselineSyncAction.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/DeleteBaselineSyncAction.java @@ -17,8 +17,15 @@ package com.alibaba.polardbx.executor.sync; import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.gms.module.LogLevel; +import com.alibaba.polardbx.gms.module.LogPattern; +import com.alibaba.polardbx.gms.module.ModuleLogInfo; import com.alibaba.polardbx.optimizer.planmanager.PlanManager; +import static com.alibaba.polardbx.gms.module.LogLevel.NORMAL; +import static com.alibaba.polardbx.gms.module.LogPattern.PROCESSING; +import static com.alibaba.polardbx.gms.module.Module.SPM; + public class DeleteBaselineSyncAction implements ISyncAction { private String schemaName; @@ -49,9 +56,13 @@ public void setSchemaName(String schemaName) { @Override public ResultCursor sync() { - if (planInfoId != null) { + if (planInfoId != null && planInfoId != 0) { + ModuleLogInfo.getInstance() + .logRecord(SPM, PROCESSING, new String[] {"delete plan " + planInfoId, parameterSql}, NORMAL); PlanManager.getInstance().deleteBaseline(schemaName, parameterSql, planInfoId); } else { + ModuleLogInfo.getInstance() + .logRecord(SPM, PROCESSING, new String[] {"delete baseline ", parameterSql}, NORMAL); PlanManager.getInstance().deleteBaseline(schemaName, parameterSql); } return null; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FailPointClearSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FailPointClearSyncAction.java new file mode 100644 index 000000000..d8afd34aa --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FailPointClearSyncAction.java @@ -0,0 +1,15 @@ +package com.alibaba.polardbx.executor.sync; + +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; + +/** + * @author wumu + */ +public class FailPointClearSyncAction implements ISyncAction { + @Override + public ResultCursor sync() { + FailPoint.clear(); + return null; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FailPointDisableSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FailPointDisableSyncAction.java new file mode 100644 index 000000000..4d6af82ed --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FailPointDisableSyncAction.java @@ -0,0 +1,29 @@ +package com.alibaba.polardbx.executor.sync; + +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; + +/** + * @author wumu + */ +public class FailPointDisableSyncAction implements ISyncAction { + private String fpKey; + + public FailPointDisableSyncAction(String fpKey) { + this.fpKey = fpKey; + } + + @Override + public ResultCursor sync() { + FailPoint.disable(fpKey); + return null; + } + + public String getFpKey() { + return fpKey; + } + + public void setFpKey(String fpKey) { + this.fpKey = fpKey; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FailPointEnableSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FailPointEnableSyncAction.java new file mode 100644 index 000000000..a2fc509d4 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FailPointEnableSyncAction.java @@ -0,0 +1,41 @@ +package com.alibaba.polardbx.executor.sync; + +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; + +/** + * @author wumu + */ +public class FailPointEnableSyncAction implements ISyncAction { + + private String fpKey; + + private String value; + + public FailPointEnableSyncAction(String fpKey, String value) { + this.fpKey = fpKey; + this.value = value; + } + + @Override + public ResultCursor sync() { + FailPoint.enable(fpKey, value); + return null; + } + + public String getFpKey() { + return fpKey; + } + + public String getValue() { + return value; + } + + public void setFpKey(String fpKey) { + this.fpKey = fpKey; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FetchSPMSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FetchSPMSyncAction.java index 29beee220..bca13f132 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FetchSPMSyncAction.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/FetchSPMSyncAction.java @@ -98,6 +98,7 @@ public ResultCursor sync() { result.addColumn("IS_REBUILD_AT_LOAD", DataTypes.StringType); result.addColumn("HINT", DataTypes.StringType); result.addColumn("USE_POST_PLANNER", DataTypes.StringType); + result.addColumn("HOT_EVOLVED", DataTypes.StringType); if (baselineMap == null) { return result; @@ -129,7 +130,8 @@ public ResultCursor sync() { "", // plan baselineInfo.isRebuildAtLoad() + "", baselineInfo.getHint(), - baselineInfo.isUsePostPlanner() + "" + baselineInfo.isUsePostPlanner() + "", + String.valueOf(baselineInfo.isHotEvolution()) }); } for (PlanInfo planInfo : baselineInfo.getPlans()) { @@ -163,7 +165,8 @@ public ResultCursor sync() { planExplain, baselineInfo.isRebuildAtLoad() + "", baselineInfo.getHint(), - baselineInfo.isUsePostPlanner() + "" + baselineInfo.isUsePostPlanner() + "", + String.valueOf(baselineInfo.isHotEvolution()) }); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/GlobalAcquireMdlLockInDbSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/GlobalAcquireMdlLockInDbSyncAction.java index e7579679f..40a858a38 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/GlobalAcquireMdlLockInDbSyncAction.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/GlobalAcquireMdlLockInDbSyncAction.java @@ -45,6 +45,8 @@ */ @Getter public class GlobalAcquireMdlLockInDbSyncAction implements ISyncAction { + final static String TABLE_TYPE_COL = "TABLE_TYPE"; + final static String BASE_TABLE_TYPE = "base table"; final private Set schemaNames; public GlobalAcquireMdlLockInDbSyncAction(Set schemaNames) { @@ -91,15 +93,17 @@ protected void acquireAllTablesMdlWriteLockInDb(String schemaName) { } protected Set getAllTablesInDatabase(String schemaName) { - final String queryTablesSql = "show tables"; + final String queryTablesSql = "show full tables"; List> result = DdlHelper.getServerConfigManager().executeQuerySql(queryTablesSql, schemaName, null); Set tables = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); for (Map map : result) { - String tb = (String) map.get(("TABLES_IN_" + SQLUtils.normalize(schemaName)).toUpperCase()); - if (tb != null) { - tables.add(tb); + if (BASE_TABLE_TYPE.equalsIgnoreCase((String) map.get((TABLE_TYPE_COL)))) { + String tb = (String) map.get(("TABLES_IN_" + SQLUtils.normalize(schemaName)).toUpperCase()); + if (tb != null) { + tables.add(tb); + } } } return tables; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/MetricSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/MetricSyncAction.java new file mode 100644 index 000000000..59fb5fcde --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/MetricSyncAction.java @@ -0,0 +1,41 @@ +package com.alibaba.polardbx.executor.sync; + +import com.alibaba.fastjson.JSON; +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.gms.module.LogLevel; +import com.alibaba.polardbx.gms.module.LogPattern; +import com.alibaba.polardbx.gms.module.Module; +import com.alibaba.polardbx.gms.module.ModuleLogInfo; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.stats.metric.FeatureStats; + +/** + * @author fangwu + */ +public class MetricSyncAction implements ISyncAction { + + public static final String JSON_KEY = "JSON_METRIC"; + + public MetricSyncAction() { + } + + @Override + public ResultCursor sync() { + ArrayResultCursor resultCursor = buildResultCursor(); + FeatureStats fs = FeatureStats.getInstance(); + resultCursor.addRow(new Object[] {JSON.toJSONString(fs)}); + + FeatureStats.reset(); + ModuleLogInfo.getInstance().logRecord(Module.METRIC, LogPattern.PROCESS_END, + new String[] {this.getClass().getSimpleName(), ""}, LogLevel.NORMAL); + return resultCursor; + } + + public static ArrayResultCursor buildResultCursor() { + ArrayResultCursor resultCursor = new ArrayResultCursor("METRIC_SYNC_RESULT"); + resultCursor.addColumn(JSON_KEY, DataTypes.VarcharType); + resultCursor.initMeta(); + return resultCursor; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/MetricSyncAllAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/MetricSyncAllAction.java new file mode 100644 index 000000000..ada447689 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/MetricSyncAllAction.java @@ -0,0 +1,56 @@ +package com.alibaba.polardbx.executor.sync; + +import com.alibaba.fastjson.JSON; +import com.alibaba.polardbx.common.TddlNode; +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.statistic.RealStatsLog; +import com.alibaba.polardbx.gms.module.LogLevel; +import com.alibaba.polardbx.gms.module.LogPattern; +import com.alibaba.polardbx.gms.module.Module; +import com.alibaba.polardbx.gms.module.ModuleLogInfo; +import com.alibaba.polardbx.gms.topology.ServerInstIdManager; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.stats.metric.FeatureStats; + +/** + * @author fangwu + */ +public class MetricSyncAllAction implements ISyncAction { + + public static final String INST = "INST"; + public static final String HOST = "HOST"; + public static final String METRIC_FEAT_KEY = "METRIC_FEAT_KEY"; + public static final String METRIC_REAL_KEY = "METRIC_REAL_KEY"; + + public MetricSyncAllAction() { + } + + @Override + public ResultCursor sync() { + ArrayResultCursor resultCursor = buildResultCursor(); + FeatureStats fs = FeatureStats.getInstance(); + String instId = ServerInstIdManager.getInstance().getInstId(); + + resultCursor.addRow(new Object[] { + instId, + TddlNode.getHost() + ":" + TddlNode.getPort(), + JSON.toJSONString(fs), + RealStatsLog.statLog()}); + + ModuleLogInfo.getInstance() + .logInfo(Module.METRIC, LogPattern.PROCESS_END, + new String[] {this.getClass().getSimpleName(), "metric sync all"}); + return resultCursor; + } + + public static ArrayResultCursor buildResultCursor() { + ArrayResultCursor resultCursor = new ArrayResultCursor("METRIC_SYNC_RESULT"); + resultCursor.addColumn(INST, DataTypes.VarcharType); + resultCursor.addColumn(HOST, DataTypes.VarcharType); + resultCursor.addColumn(METRIC_FEAT_KEY, DataTypes.VarcharType); + resultCursor.addColumn(METRIC_REAL_KEY, DataTypes.VarcharType); + resultCursor.initMeta(); + return resultCursor; + } +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/ReloadSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/ReloadSyncAction.java index 64fc89c5c..1acaed8c6 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/ReloadSyncAction.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/ReloadSyncAction.java @@ -19,6 +19,7 @@ import com.alibaba.polardbx.atom.CacheVariables; import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.gms.ColumnarManager; import com.alibaba.polardbx.executor.pl.ProcedureManager; import com.alibaba.polardbx.executor.pl.StoredFunctionManager; import com.alibaba.polardbx.executor.utils.ReloadUtils; @@ -86,9 +87,16 @@ public ResultCursor sync() { break; case COLUMNARMANAGER: - Optional - .ofNullable(ExecutorContext.getContext(schemaName)) - .ifPresent(ExecutorContext::reloadColumnarManager); + ColumnarManager.getInstance().reload(); + break; + case COLUMNARMANAGER_CACHE: + ColumnarManager.getInstance().reload(ColumnarManager.ReloadType.CACHE_ONLY); + break; + case COLUMNARMANAGER_SNAPSHOT: + ColumnarManager.getInstance().reload(ColumnarManager.ReloadType.SNAPSHOT_ONLY); + break; + case COLUMNARMANAGER_SCHEMA: + ColumnarManager.getInstance().reload(ColumnarManager.ReloadType.SCHEMA_ONLY); break; default: break; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/StoragePropertiesSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/StoragePropertiesSyncAction.java index 1300be0eb..1f0f31d3f 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/StoragePropertiesSyncAction.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/StoragePropertiesSyncAction.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.executor.sync; +import com.alibaba.polardbx.common.MergedStorageInfo; import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.executor.common.StorageInfoManager; import com.alibaba.polardbx.executor.cursor.ResultCursor; @@ -41,16 +42,17 @@ public ResultCursor sync() { Optional.ofNullable(ExecutorContext.getContext("polardbx")).ifPresent(context -> { final StorageInfoManager manager = context.getStorageInfoManager(); + final MergedStorageInfo mergedStorageInfo = manager.getMergedStorageInfo(); // Get all boolean member variable of StorageInfoManager. - Class clazz = manager.getClass(); + Class clazz = mergedStorageInfo.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (field.getType().equals(boolean.class)) { field.setAccessible(true); boolean value = false; try { - value = field.getBoolean(manager); + value = field.getBoolean(mergedStorageInfo); } catch (IllegalAccessException e) { // Ignore this value. continue; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TableMetaChangePreemptiveSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TableMetaChangePreemptiveSyncAction.java index ff64b875a..0a59f993a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TableMetaChangePreemptiveSyncAction.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TableMetaChangePreemptiveSyncAction.java @@ -37,6 +37,8 @@ public class TableMetaChangePreemptiveSyncAction implements ISyncAction { private Long interval; private TimeUnit timeUnit; + private Boolean forceSyncFailed; + public TableMetaChangePreemptiveSyncAction() { } @@ -48,13 +50,24 @@ public TableMetaChangePreemptiveSyncAction(String schemaName, String tableName, this.initWait = initWait; this.interval = interval; this.timeUnit = timeUnit; + this.forceSyncFailed = false; + } + + public TableMetaChangePreemptiveSyncAction(String schemaName, String tableName, Long initWait, Long interval, + TimeUnit timeUnit, Boolean forceSyncFailed) { + this.schemaName = schemaName; + this.primaryTableName = tableName; + this.initWait = initWait; + this.interval = interval; + this.timeUnit = timeUnit; + this.forceSyncFailed = forceSyncFailed; } @Override public ResultCursor sync() { SchemaManager oldSchemaManager = OptimizerContext.getContext(schemaName).getLatestSchemaManager(); ((GmsTableMetaManager) oldSchemaManager).tonewversion(primaryTableName, true, initWait, interval, timeUnit, - true); + true, forceSyncFailed); return null; } @@ -101,4 +114,12 @@ public TimeUnit getTimeUnit() { public void setTimeUnit(TimeUnit timeUnit) { this.timeUnit = timeUnit; } + + public Boolean getForceSyncFailed() { + return forceSyncFailed; + } + + public void setForceSyncFailed(Boolean forceSyncFailed) { + this.forceSyncFailed = forceSyncFailed; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TablesMetaChangePreemptiveSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TablesMetaChangePreemptiveSyncAction.java index c1f519bc0..8e63002b8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TablesMetaChangePreemptiveSyncAction.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TablesMetaChangePreemptiveSyncAction.java @@ -37,12 +37,25 @@ public class TablesMetaChangePreemptiveSyncAction implements ISyncAction { private Long connId; private Boolean sameTableGroup; + private Boolean forceSyncFailed; public TablesMetaChangePreemptiveSyncAction() { } @JSONCreator + public TablesMetaChangePreemptiveSyncAction(String schemaName, List logicalTables, Long initWait, + Long interval, TimeUnit timeUnit, Long connId, Boolean sameTableGroup, Boolean forceSyncFailed) { + this.schemaName = schemaName; + this.logicalTables = logicalTables; + this.initWait = initWait; + this.interval = interval; + this.timeUnit = timeUnit; + this.connId = connId; + this.sameTableGroup = sameTableGroup; + this.forceSyncFailed = forceSyncFailed; + } + public TablesMetaChangePreemptiveSyncAction(String schemaName, List logicalTables, Long initWait, Long interval, TimeUnit timeUnit, Long connId, Boolean sameTableGroup) { this.schemaName = schemaName; @@ -52,6 +65,7 @@ public TablesMetaChangePreemptiveSyncAction(String schemaName, List logi this.timeUnit = timeUnit; this.connId = connId; this.sameTableGroup = sameTableGroup; + this.forceSyncFailed = false; } public TablesMetaChangePreemptiveSyncAction(String schemaName, List logicalTables, Long initWait, @@ -63,6 +77,19 @@ public TablesMetaChangePreemptiveSyncAction(String schemaName, List logi this.timeUnit = timeUnit; this.connId = -1L; this.sameTableGroup = true; + this.forceSyncFailed = false; + } + + public TablesMetaChangePreemptiveSyncAction(String schemaName, List logicalTables, Long initWait, + Long interval, TimeUnit timeUnit, boolean forceSyncFailed) { + this.schemaName = schemaName; + this.logicalTables = logicalTables; + this.initWait = initWait; + this.interval = interval; + this.timeUnit = timeUnit; + this.connId = -1L; + this.sameTableGroup = true; + this.forceSyncFailed = forceSyncFailed; } @Override @@ -70,7 +97,7 @@ public ResultCursor sync() { SchemaManager oldSchemaManager = OptimizerContext.getContext(schemaName).getLatestSchemaManager(); // TODO(luoyanxin) optimize single-version schema-change oldSchemaManager.toNewVersionInTrx(logicalTables, true, initWait, interval, timeUnit, connId, true, - sameTableGroup); + sameTableGroup, forceSyncFailed); return null; } @@ -129,4 +156,12 @@ public Boolean getSameTableGroup() { public void setSameTableGroup(Boolean sameTableGroup) { this.sameTableGroup = sameTableGroup; } + + public Boolean getForceSyncFailed() { + return forceSyncFailed; + } + + public void setForceSyncFailed(Boolean forceSyncFailed) { + this.forceSyncFailed = forceSyncFailed; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TablesMetaChangeSyncAction.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TablesMetaChangeSyncAction.java index 2e9955fe7..08d7aaa4e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TablesMetaChangeSyncAction.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/sync/TablesMetaChangeSyncAction.java @@ -35,28 +35,31 @@ public class TablesMetaChangeSyncAction implements ISyncAction { private List logicalTables; private Long connId; + private Boolean forceSyncFailed; public TablesMetaChangeSyncAction() { } - public TablesMetaChangeSyncAction(String schemaName, List logicalTables) { + public TablesMetaChangeSyncAction(String schemaName, List logicalTables, Boolean forceSyncFailed) { this.schemaName = schemaName; this.logicalTables = logicalTables; this.connId = -1L; + this.forceSyncFailed = forceSyncFailed; } @JSONCreator - public TablesMetaChangeSyncAction(String schemaName, List logicalTables, Long connId) { + public TablesMetaChangeSyncAction(String schemaName, List logicalTables, Long connId, Boolean forceSyncFailed) { this.schemaName = schemaName; this.logicalTables = logicalTables; this.connId = connId; + this.forceSyncFailed = forceSyncFailed; } @Override public ResultCursor sync() { SchemaManager oldSchemaManager = OptimizerContext.getContext(schemaName).getLatestSchemaManager(); - oldSchemaManager.toNewVersionInTrx(logicalTables, connId, true); + oldSchemaManager.toNewVersionInTrx(logicalTables, connId, true, forceSyncFailed); return null; } @@ -83,4 +86,12 @@ public Long getConnId() { public void setConnId(Long connId) { this.connId = connId; } + + public Boolean getForceSyncFailed() { + return forceSyncFailed; + } + + public void setForceSyncFailed(Boolean forceSyncFailed) { + this.forceSyncFailed = forceSyncFailed; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/DdlUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/DdlUtils.java index ca3aca5be..5f831cb17 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/DdlUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/DdlUtils.java @@ -1,19 +1,3 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.executor.utils; import com.alibaba.polardbx.common.utils.logger.Logger; @@ -87,5 +71,4 @@ public static long generateVersionId(ExecutionContext ec) { } return timestampOracle.nextTimestamp(); } - } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/DrdsToAutoTableCreationSqlUtil.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/DrdsToAutoTableCreationSqlUtil.java index 9aa592849..052311ffb 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/DrdsToAutoTableCreationSqlUtil.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/DrdsToAutoTableCreationSqlUtil.java @@ -16,6 +16,9 @@ package com.alibaba.polardbx.executor.utils; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.model.Group; import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.druid.sql.ast.SQLDataTypeImpl; import com.alibaba.polardbx.druid.sql.ast.SQLExpr; @@ -45,10 +48,22 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlPartitionByKey; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlSubPartitionByKey; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.spi.IRepository; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.gms.topology.DbInfoRecord; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan; +import com.alibaba.polardbx.optimizer.core.planner.Planner; +import com.alibaba.polardbx.optimizer.core.rel.dal.LogicalShow; +import com.alibaba.polardbx.optimizer.core.row.Row; import com.alibaba.polardbx.optimizer.parse.FastsqlUtils; import com.alibaba.polardbx.optimizer.sharding.utils.DrdsDefaultPartitionNumUtil; +import com.alibaba.polardbx.repo.mysql.handler.LogicalShowTablesMyHandler; +import org.apache.calcite.sql.SqlShowTables; +import org.apache.calcite.sql.parser.SqlParserPos; import java.sql.Types; import java.util.ArrayList; @@ -72,6 +87,7 @@ */ public class DrdsToAutoTableCreationSqlUtil { static final int largestIndexPrefixLengthInBytes = 767; + static final String TABLE_TYPE = "base table"; //ignore the 'locality' option in auto-mode db public static String buildCreateAutoModeDatabaseSql(String drdsSchemaName, String autoSchemaName) { @@ -827,7 +843,7 @@ && validateAutoShardKeyLength(columnsLengthsInBytes, hashKey, pk)) { month.addArgument(col); autoSqlSubPartitionBy.addColumn(month); //build subpartition definition - generateRangeSubPartitionDefInAutoMode((SQLSubPartitionByRange) autoSqlSubPartitionBy, 12, 12); + generateRangeSubPartitionDefInAutoMode((SQLSubPartitionByRange) autoSqlSubPartitionBy, 13, 13); } else if (drdsPartitionBy.getMethodName().equalsIgnoreCase("DD")) { //build dayofmonth(`col`) autoSqlSubPartitionBy = new SQLSubPartitionByRange(); @@ -1267,4 +1283,34 @@ protected static Map tryToCaclColumnsMaxLenInBytes(List getTableNamesFromDatabase(String schemaName, ExecutionContext executionContext) { + SqlShowTables sqlShowTables = + SqlShowTables.create(SqlParserPos.ZERO, true, null, schemaName, null, null, null, null); + ExecutionContext copiedContext = executionContext.copy(); + copiedContext.setSchemaName(schemaName); + PlannerContext plannerContext = PlannerContext.fromExecutionContext(copiedContext); + ExecutionPlan showTablesPlan = Planner.getInstance().getPlan(sqlShowTables, plannerContext); + LogicalShow logicalShowTables = (LogicalShow) showTablesPlan.getPlan(); + + IRepository sourceRepo = ExecutorContext + .getContext(schemaName) + .getTopologyHandler() + .getRepositoryHolder() + .get(Group.GroupType.MYSQL_JDBC.toString()); + LogicalShowTablesMyHandler logicalShowTablesMyHandler = new LogicalShowTablesMyHandler(sourceRepo); + + Cursor showTablesCursor = + logicalShowTablesMyHandler.handle(logicalShowTables, copiedContext); + + List tables = new ArrayList<>(); + Row showTablesResult = null; + while ((showTablesResult = showTablesCursor.next()) != null) { + if (showTablesResult.getColNum() >= 1 && showTablesResult.getString(0) != null + && TABLE_TYPE.equalsIgnoreCase(showTablesResult.getString(1))) { + tables.add(showTablesResult.getString(0)); + } + } + return tables; + } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ExecUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ExecUtils.java index 609aab69f..e807cd241 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ExecUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ExecUtils.java @@ -19,6 +19,7 @@ import com.alibaba.polardbx.common.TddlNode; import com.alibaba.polardbx.common.async.AsyncTask; import com.alibaba.polardbx.common.constants.SequenceAttribute; +import com.alibaba.polardbx.common.constants.TransactionAttribute; import com.alibaba.polardbx.common.exception.NotSupportException; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; @@ -27,8 +28,9 @@ import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; import com.alibaba.polardbx.common.jdbc.MasterSlave; import com.alibaba.polardbx.common.jdbc.ParameterContext; -import com.alibaba.polardbx.common.model.Group; import com.alibaba.polardbx.common.model.RepoInst; +import com.alibaba.polardbx.common.oss.ColumnarFileType; +import com.alibaba.polardbx.common.oss.IDeltaReadOption; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.properties.ConnectionProperties; import com.alibaba.polardbx.common.properties.DynamicConfig; @@ -46,18 +48,17 @@ import com.alibaba.polardbx.druid.sql.ast.SqlType; import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.common.ExecutorContext; -import com.alibaba.polardbx.executor.common.TopologyHandler; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.gms.DynamicColumnarManager; import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; import com.alibaba.polardbx.executor.mpp.discover.RefreshNodeSyncAction; import com.alibaba.polardbx.executor.mpp.execution.QueryInfo; import com.alibaba.polardbx.executor.mpp.execution.StageInfo; import com.alibaba.polardbx.executor.mpp.execution.TaskInfo; +import com.alibaba.polardbx.executor.mpp.split.SpecifiedOssSplit; import com.alibaba.polardbx.executor.operator.util.ConcurrentRawHashTable; -import com.alibaba.polardbx.executor.spi.IGroupExecutor; import com.alibaba.polardbx.executor.spi.ITopologyExecutor; -import com.alibaba.polardbx.executor.sync.CollectVariableSyncAction; import com.alibaba.polardbx.executor.spi.ITransactionManager; import com.alibaba.polardbx.executor.sync.CollectVariableSyncAction; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; @@ -67,13 +68,15 @@ import com.alibaba.polardbx.gms.ha.impl.StorageHaManager; import com.alibaba.polardbx.gms.ha.impl.StorageInstHaContext; import com.alibaba.polardbx.gms.metadb.MetaDbConnectionProxy; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionAccessor; import com.alibaba.polardbx.gms.metadb.table.FilesAccessor; import com.alibaba.polardbx.gms.metadb.table.FilesRecord; import com.alibaba.polardbx.gms.node.GmsNodeManager; import com.alibaba.polardbx.gms.node.InternalNode; import com.alibaba.polardbx.gms.node.InternalNodeManager; +import com.alibaba.polardbx.gms.node.MppScope; import com.alibaba.polardbx.gms.node.Node; -import com.alibaba.polardbx.gms.node.NodeStatusManager; import com.alibaba.polardbx.gms.sync.IGmsSyncAction; import com.alibaba.polardbx.gms.sync.SyncScope; import com.alibaba.polardbx.gms.topology.DbInfoManager; @@ -88,6 +91,7 @@ import com.alibaba.polardbx.gms.util.MetaDbLogUtil; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; +import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; @@ -156,14 +160,12 @@ import org.apache.commons.collections.MapUtils; import org.weakref.jmx.internal.guava.primitives.Bytes; -import javax.sql.DataSource; import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -192,6 +194,7 @@ import java.util.stream.IntStream; import static com.alibaba.polardbx.common.properties.ConnectionParams.MASTER_READ_WEIGHT; +import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.TRX_LOG_SOCKET_TIMEOUT; import static com.alibaba.polardbx.common.utils.thread.ThreadCpuStatUtil.NUM_CORES; import static com.alibaba.polardbx.executor.gsi.utils.Transformer.buildBatchParam; import static com.alibaba.polardbx.executor.utils.failpoint.FailPointKey.FP_INJECT_IGNORE_INTERRUPTED_TO_STATISTIC_SCHEDULE_JOB; @@ -330,18 +333,73 @@ public static long calcRowCount(LogicalView logicalView) { } } - public static int getMppMaxParallelism(ParamManager paramManager, boolean master) { + public static int getMppMaxParallelism(ParamManager paramManager, boolean isColumnar) { int maxParallelism = paramManager.getInt(ConnectionParams.MPP_MAX_PARALLELISM); if (maxParallelism < 1) { - int num = (ServiceProvider.getInstance().getServer()).getNodeManager() - .getAllWorkers(ConfigDataMode.isMasterMode() && paramManager - .getBoolean(ConnectionParams.POLARDBX_SLAVE_INSTANCE_FIRST)).size(); - int cores = getPolarDBXCores(paramManager, master); + MppScope mppScope = ExecUtils.getMppSchedulerScope(!isColumnar); + int num = ServiceProvider.getInstance().getServer() + .getNodeManager().getAllNodes().getAllWorkers(mppScope).size(); + int cores = getPolarDBXCNCores(paramManager, mppScope); maxParallelism = num * cores; } return maxParallelism; } + public static boolean allowMppMode(ExecutionContext context) { + if (!ConfigDataMode.isMasterMode()) { + return true; + } else { + boolean columnarMode = context.getParamManager() + .getBoolean(ConnectionParams.ENABLE_COLUMNAR_SCHEDULE); + if (context.getParamManager().getBoolean(ConnectionParams.ENABLE_MASTER_MPP)) { + return true; + } else if (columnarMode) { + if (ServiceProvider.getInstance().getServer() == null) { + return false; + } + Set columnarNodes = + ServiceProvider.getInstance().getServer().getNodeManager().getAllNodes() + .getOtherActiveColumnarNodes(); + Set rowNodes = + ServiceProvider.getInstance().getServer().getNodeManager().getAllNodes().getOtherActiveRowNodes(); + return columnarNodes.size() > 0 || rowNodes.size() > 0; + } else { + if (ServiceProvider.getInstance().getServer() == null) { + return false; + } + Set rowNodes = + ServiceProvider.getInstance().getServer().getNodeManager().getAllNodes().getOtherActiveRowNodes(); + return rowNodes.size() > 0; + } + } + } + + public static MppScope getMppSchedulerScope(boolean rowPlan) { + if (!ConfigDataMode.isMasterMode()) { + return MppScope.CURRENT; + } else { + Set rowNodes = + ServiceProvider.getInstance().getServer().getNodeManager().getAllNodes().getOtherActiveRowNodes(); + Set columnarNodes = + ServiceProvider.getInstance().getServer().getNodeManager().getAllNodes().getOtherActiveColumnarNodes(); + if (rowPlan) { + if (!rowNodes.isEmpty()) { + return MppScope.SLAVE; + } else { + return MppScope.CURRENT; + } + } else { + if (!columnarNodes.isEmpty()) { + return MppScope.COLUMNAR; + } else if (!rowNodes.isEmpty()) { + return MppScope.SLAVE; + } else { + return MppScope.CURRENT; + } + } + } + } + public static int getMppMinParallelism(ParamManager paramManager) { int minParallelism = paramManager .getInt(ConnectionParams.MPP_MIN_PARALLELISM); @@ -354,35 +412,31 @@ public static int getMppMinParallelism(ParamManager paramManager) { /** * 获取polarX Server节点的cpu核数 */ - public static int getPolarDBXCores(ParamManager paramManager, boolean master) { + public static int getPolarDBXCNCores(ParamManager paramManager, MppScope mppScope) { int polarXParallelism = paramManager.getInt(ConnectionParams.POLARDBX_PARALLELISM); if (polarXParallelism < 1) { - if (master) { - if (ConfigDataMode.isMasterMode()) { - polarXParallelism = NUM_CORES; - } else { - GmsNodeManager gmsNodeManager = GmsNodeManager.getInstance(); - if (gmsNodeManager.getReadOnlyNodes().size() > 0) { - polarXParallelism = - gmsNodeManager.getReadOnlyNodeCpuCore() > 0 ? gmsNodeManager.getReadOnlyNodeCpuCore() : - NUM_CORES; - } else { - polarXParallelism = NUM_CORES; - } + GmsNodeManager gmsNodeManager = GmsNodeManager.getInstance(); + polarXParallelism = NUM_CORES; + switch (mppScope) { + case SLAVE: + int readOnlySize = gmsNodeManager.getReadOnlyNodes().size(); + if (readOnlySize > 0) { + polarXParallelism = + gmsNodeManager.getReadOnlyNodeCpuCore() > 0 ? gmsNodeManager.getReadOnlyNodeCpuCore() : + NUM_CORES; } - } else { - if (!ConfigDataMode.isMasterMode()) { - polarXParallelism = NUM_CORES; - } else { - GmsNodeManager gmsNodeManager = GmsNodeManager.getInstance(); - if (gmsNodeManager.getReadOnlyNodes().size() > 0) { - polarXParallelism = - gmsNodeManager.getReadOnlyNodeCpuCore() > 0 ? gmsNodeManager.getReadOnlyNodeCpuCore() : - NUM_CORES; - } else { - polarXParallelism = NUM_CORES; - } + break; + case COLUMNAR: + int columnarReadOnlySize = gmsNodeManager.getColumnarReadOnlyNodes().size(); + if (columnarReadOnlySize > 0) { + polarXParallelism = + gmsNodeManager.getReadOnlyColumnarCpuCore() > 0 ? gmsNodeManager.getReadOnlyColumnarCpuCore() : + NUM_CORES; } + break; + default: + polarXParallelism = NUM_CORES; + break; } } return polarXParallelism; @@ -391,11 +445,10 @@ public static int getPolarDBXCores(ParamManager paramManager, boolean master) { /** * 获取polarX实例下挂载的mysql的cpu核数 */ - public static int getPolarDbCores(ParamManager paramManager, boolean master) { + public static int getPolarDbCores(ParamManager paramManager) { int dbParallelism = paramManager.getInt(ConnectionParams.DATABASE_PARALLELISM); if (dbParallelism < 1) { - //TODO 现在存储节点和计算节点的CPU核数一致,以后待定 - dbParallelism = getPolarDBXCores(paramManager, master); + dbParallelism = 16; } return dbParallelism; } @@ -588,6 +641,33 @@ public int compare(Row o1, Row o2) { } + public static Comparator getComparatorForColumns(List indexes, List columnMetas, + boolean isAsc) { + Preconditions.checkArgument(columnMetas != null); + Preconditions.checkArgument(indexes != null); + Preconditions.checkArgument(indexes.size() == columnMetas.size()); + return new Comparator() { + + @Override + public int compare(Row o1, Row o2) { + for (int i = 0; i < indexes.size(); i++) { + Object c1 = o1.getObjectForCmp(indexes.get(i)); + Object c2 = o2.getObjectForCmp(indexes.get(i)); + if (c1 == null && c2 == null) { + continue; + } + int n = comp(c1, c2, columnMetas.get(i), isAsc); + if (n == 0) { + continue; + } + return n; + } + return 0; + } + }; + + } + public static int comp(Object c1, Object c2, DataType type, boolean isAsc) { if (type == null) { type = DataTypeUtil.getTypeOfObject(c1); @@ -708,7 +788,10 @@ public static QueryConcurrencyPolicy getQueryConcurrencyPolicy(ExecutionContext } // Force SEQUENTIAL to reduce deadlocks in transactions, unless for SELECT statements - if (executionContext.getTransaction() instanceof IDistributedTransaction + // 5.4.19-0731版本后,新实例,update/delete默认忽略该规则 + if (!executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_DML_GROUP_CONCURRENT_IN_TRANSACTION) + && executionContext.getTransaction() instanceof IDistributedTransaction && executionContext.getSqlType() != SqlType.SELECT && !executionContext.getParamManager().getBoolean( ConnectionParams.GSI_CONCURRENT_WRITE) && logicalView == null) { return QueryConcurrencyPolicy.SEQUENTIAL; @@ -1877,28 +1960,6 @@ public static boolean isTpMode(ExecutionContext context) { return !(context.getExecuteMode() == ExecutorMode.MPP || context.getExecuteMode() == ExecutorMode.AP_LOCAL); } - public static boolean existMppOnlyInstanceNode() { - if (ServiceProvider.getInstance().getServer() == null) { - return false; - } - InternalNodeManager nodeManager = ServiceProvider.getInstance().getServer().getNodeManager(); - Set nodes = null; - if (ConfigDataMode.isMasterMode()) { - nodes = nodeManager.getAllNodes().getOtherActiveNodes(); - } else { - nodes = nodeManager.getAllNodes().getActiveNodes(); - } - return nodes != null && nodes.size() > 0; - } - - public static int getActiveNodeCount() { - if (ServiceProvider.getInstance().getServer() == null) { - return 1; - } - InternalNodeManager nodeManager = ServiceProvider.getInstance().getServer().getNodeManager(); - return Math.max(nodeManager.getAllNodes().getActiveNodes().size(), 1); - } - public static boolean convertBuildSide(Join join) { boolean convertBuildSide = false; if (join instanceof HashJoin) { @@ -1927,7 +1988,7 @@ public static boolean hasLeadership(String schema) { public static String getLeaderKey(String schema) { InternalNodeManager manager = ServiceProvider.getInstance().getServer().getNodeManager(); if (manager != null) { - List coordinators = manager.getAllCoordinators(); + List coordinators = manager.getAllNodes().getAllCoordinators(); if (coordinators != null && !coordinators.isEmpty()) { for (Node node : coordinators) { if (node.isLeader()) { @@ -1939,10 +2000,6 @@ public static String getLeaderKey(String schema) { return null; } - public static NodeStatusManager getStatusManager(String schema) { - return ServiceProvider.getInstance().getServer().getStatusManager(); - } - public static void syncNodeStatus(String schema) { try { IGmsSyncAction action = new RefreshNodeSyncAction(schema); @@ -1998,7 +2055,7 @@ public static long getLsn(IDataSource dataSource, long tso, String hint) throws ResultSet result; try (IConnection masterConn = dataSource.getConnection(MasterSlave.MASTER_ONLY)) { -// if (masterConn.isWrapperFor(XConnection.class)) { +// if (tso > 0 && masterConn.isWrapperFor(XConnection.class)) { // masterConn.unwrap(XConnection.class).execUpdate(tsoSql, null, true); // } @@ -2138,7 +2195,7 @@ public static Pair calculateLogicalAndPhysicalThread(Execution //logicalThreads,physicalThreads <= 0 意味着根据环境自动设置 if (physicalThreads <= 0) { int cnCores = - ExecUtils.getPolarDBXCores(ec.getParamManager(), ConfigDataMode.isMasterMode()); + ExecUtils.getPolarDBXCNCores(ec.getParamManager(), MppScope.CURRENT); if (isSingleTable) { //单表情况,执行物理任务线程等于核数 physicalThreads = Math.max(cnCores, 1); @@ -2230,6 +2287,7 @@ public static void scanRecoveredTrans(Set dnIds, ITopologyExecutor execu futures.add(executor.getExecutorService().submit(null, null, AsyncTask.build(() -> { try (Connection conn = DbTopologyManager.getConnectionForStorage(dnId); Statement stmt = conn.createStatement()) { + conn.setNetworkTimeout(TGroupDirectConnection.socketTimeoutExecutor, TRX_LOG_SOCKET_TIMEOUT); if (conn.isWrapperFor(XConnection.class)) { // Note: XA RECOVER will hold the LOCK_transaction_cache lock, so never block it. conn.unwrap(XConnection.class).setDefaultTokenKb(Integer.MAX_VALUE); @@ -2240,7 +2298,7 @@ public static void scanRecoveredTrans(Set dnIds, ITopologyExecutor execu int gtridLength = rs.getInt(2); byte[] data = rs.getBytes(4); - if (formatId == 1) { + if (TransactionAttribute.FormatId.isUserTransaction((int) formatId)) { byte[] gtridData = Arrays.copyOfRange(data, 0, gtridLength); if (checkGtridPrefix(gtridData)) { int atSymbolIndex = ArrayUtils.indexOf(gtridData, (byte) '@'); @@ -2419,4 +2477,124 @@ public static Runnable forceAllTrx2PC() throws SQLException, InterruptedExceptio } }; } + + public static Map> diffOrcFiles(Map> v0, Map> v1) { + Iterator>> it = v1.entrySet().iterator(); + while (it.hasNext()) { + Entry> entry = it.next(); + String partitionName = entry.getKey(); + Set alreadyInV0 = v0.get(partitionName); + if (null != alreadyInV0) { + entry.getValue().removeAll(alreadyInV0); + } + if (entry.getValue().isEmpty()) { + // this partition is identical between v0 and v1 + it.remove(); + } + } + return v1; + } + + public static Map diffDeltaFiles(long tso0, long tso1, long tableId, + Set deltaFiles) { + Map diff = new HashMap<>(); + + if (deltaFiles.isEmpty()) { + return diff; + } + + final class Tuple { + String partName; + Long startPos; + Long endPos; + } + + // file name -> tuple + Map tuples = new HashMap<>(); + ColumnarAppendedFilesAccessor accessor = new ColumnarAppendedFilesAccessor(); + try (Connection connection = MetaDbUtil.getConnection()) { + accessor.setConnection(connection); + accessor.queryByFileNamesAndTsoRange(deltaFiles, tso0, tso1).forEach(record -> + tuples.compute(record.getFileName(), (k, v) -> { + long start = record.getAppendOffset(); + long end = start + record.getAppendLength(); + String partName = record.getPartName(); + if (null == v) { + v = new Tuple(); + v.partName = partName; + v.startPos = start; + v.endPos = end; + } else if (v.startPos > start) { + // an earlier start position + v.startPos = start; + } else if (v.endPos < end) { + // a later end position + v.endPos = end; + } + + return v; + })); + } catch (Throwable t) { + logger.error("diff delta files failed.", t); + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_INDEX_CHECKER, t, "Failed to diff csv files"); + } + + for (Entry deltaFileEntry : tuples.entrySet()) { + String fileName = deltaFileEntry.getKey(); + Tuple tuple = deltaFileEntry.getValue(); + diff.compute(tuple.partName, (k, v) -> { + if (v == null) { + v = new SpecifiedOssSplit.DeltaReadWithPositionOption(tso1, tso0, tso1, tableId); + } + SpecifiedOssSplit.DeltaReadWithPositionOption delta = (SpecifiedOssSplit.DeltaReadWithPositionOption) v; + ColumnarFileType columnarFileType = + ColumnarFileType.of(fileName.substring(fileName.lastIndexOf('.') + 1)); + switch (columnarFileType) { + case CSV: + if (delta.getCsvFiles() == null) { + delta.setCsvFiles(new ArrayList<>()); + delta.setCsvStartPos(new ArrayList<>()); + delta.setCsvEndPos(new ArrayList<>()); + } + delta.getCsvFiles().add(fileName); + delta.getCsvStartPos().add(tuple.startPos); + delta.getCsvEndPos().add(tuple.endPos); + break; + case DEL: + if (delta.getDelFiles() == null) { + delta.setDelFiles(new ArrayList<>()); + delta.setDelBeginPos(new ArrayList<>()); + delta.setDelEndPos(new ArrayList<>()); + } + delta.getDelFiles().add(fileName); + delta.getDelBeginPos().add(tuple.startPos); + delta.getDelEndPos().add(tuple.endPos); + break; + default: + logger.warn("Increment check found unexpected file: " + fileName); + break; + } + return delta; + }); + } + + return diff; + } + + private static boolean haveCciDoneDdl(String schemaName, String indexName) throws SQLException { + long tableId = DynamicColumnarManager.getInstance().getTableId(0, schemaName, indexName); + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarTableEvolutionAccessor accessor = new ColumnarTableEvolutionAccessor(); + accessor.setConnection(connection); + return accessor.haveDoneDdl(tableId); + } + } + + public static boolean canUseCciFastChecker(String schemaName, String indexName) { + try { + return !haveCciDoneDdl(schemaName, indexName); + } catch (SQLException e) { + return false; + } + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ExplainExecutorUtil.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ExplainExecutorUtil.java index ed3e81067..6a1ed2da0 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ExplainExecutorUtil.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ExplainExecutorUtil.java @@ -32,8 +32,10 @@ import com.alibaba.polardbx.executor.Xprotocol.XRowSet; import com.alibaba.polardbx.executor.cursor.ResultCursor; import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.gms.ColumnarManager; import com.alibaba.polardbx.executor.mpp.Session; import com.alibaba.polardbx.executor.mpp.planner.PlanUtils; +import com.alibaba.polardbx.executor.mpp.split.OssSplit; import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; import com.alibaba.polardbx.executor.vectorized.VectorizedExpressionUtils; import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; @@ -80,6 +82,7 @@ import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruner; import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPrunerUtils; import com.alibaba.polardbx.optimizer.planmanager.BaselineInfo; +import com.alibaba.polardbx.optimizer.planmanager.LogicalViewFinder; import com.alibaba.polardbx.optimizer.planmanager.PlanInfo; import com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil; import com.alibaba.polardbx.optimizer.rule.Partitioner; @@ -143,6 +146,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.atomic.AtomicInteger; @@ -158,6 +162,7 @@ import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isExplainPipeline; import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isExplainSharding; import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isExplainSimple; +import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isExplainSnapshot; import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isExplainStatistics; import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isExplainVec; import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isPhysicalFragment; @@ -218,6 +223,8 @@ public static ResultCursor explain(ExecutionPlan executionPlan, ExecutionContext return ExplainExecutorUtil.handleExplainVec(executionContext, executionPlan, explain.explainMode); } else if (isExplainPipeline(explain)) { return ExplainExecutorUtil.handleExplainPipeline(executionContext, executionPlan); + } else if (isExplainSnapshot(explain)) { + return ExplainExecutorUtil.handleExplainSnapshot(executionContext, executionPlan); } else if (executionPlan.getPlan() instanceof BaseDdlOperation) { return handleDdl(executionContext, executionPlan); } else { @@ -880,6 +887,87 @@ private static ResultCursor handleExplainPipeline(ExecutionContext executionCont return result; } + private static ResultCursor handleExplainSnapshot(ExecutionContext executionContext, ExecutionPlan executionPlan) { + ArrayResultCursor result = new ArrayResultCursor("ColumnarSnapshot"); + result.addColumn("INDEX_NAME", DataTypes.StringType); + result.addColumn("SNAPSHOT_TSO", DataTypes.LongType); + result.addColumn("SNAPSHOT_INFO", DataTypes.StringType); + result.initMeta(); + + final RelNode plan = executionPlan.getPlan(); + final String schemaName = executionContext.getSchemaName(); + final Map params = executionContext.getParams().getCurrentParameter(); + LogicalViewFinder finder = new LogicalViewFinder(); + plan.accept(finder); + + Long tsoFromGms = null; + for (LogicalView lv : finder.getResult()) { + StringBuilder snapshotInfoBuilder = new StringBuilder(); + boolean isFirstElement = true; + if (!(lv instanceof OSSTableScan)) { + continue; + } + + OSSTableScan ossTableScan = (OSSTableScan) lv; + Long tso = ossTableScan.getFlashbackQueryTso(executionContext); + if (ossTableScan.isColumnarIndex()) { + if (tso == null) { + if (tsoFromGms == null) { + tsoFromGms = ColumnarManager.getInstance().latestTso(); + } + tso = tsoFromGms; + } + } + + List inputs = ExecUtils.getInputs(ossTableScan, executionContext, false); + for (RelNode input : inputs) { + List splits = OssSplit.getFileConcurrencySplit(ossTableScan, input, executionContext, tso); + + if (ossTableScan.isColumnarIndex()) { + for (OssSplit split : splits) { + if (!CollectionUtils.isEmpty(split.getDesignatedFile())) { + // ORC files + String fileName = split.getDesignatedFile().get(0); + if (!isFirstElement) { + snapshotInfoBuilder.append(","); + } + snapshotInfoBuilder.append(fileName); + isFirstElement = false; + } else { + // CSV files + Optional> csvFiles = + split.getDeltaReadOption().getAllCsvFiles().values().stream().findFirst(); + if (!csvFiles.isPresent() || csvFiles.get().isEmpty()) { + continue; + } + String fileName = csvFiles.get().get(0); + if (!isFirstElement) { + snapshotInfoBuilder.append(","); + } + snapshotInfoBuilder.append(fileName); + isFirstElement = false; + } + } + } else { + for (OssSplit split : splits) { + List orcFileNames = split.getPrunedOrcFiles(ossTableScan, executionContext); + for (String orcFileName : orcFileNames) { + if (!isFirstElement) { + snapshotInfoBuilder.append(","); + } + snapshotInfoBuilder.append(orcFileName); + isFirstElement = false; + } + } + } + // TODO(siyun): delete bitmap + } + result.addRow(new Object[] {ossTableScan.getTableNames().get(0), tso, snapshotInfoBuilder.toString()}); + } + + return result; + } + private static ResultCursor handleExplain(ExecutionContext executionContext, ExecutionPlan executionPlan, ExplainResult.ExplainMode mode) { SqlExplainLevel explainLevel = SqlExplainLevel.EXPPLAN_ATTRIBUTES; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/PartitionMetaUtil.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/PartitionMetaUtil.java index 22160faa8..f5850f2c5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/PartitionMetaUtil.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/PartitionMetaUtil.java @@ -23,6 +23,7 @@ import com.alibaba.polardbx.executor.common.TopologyHandler; import com.alibaba.polardbx.executor.spi.IGroupExecutor; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.gms.ttl.TtlPartArcState; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition; @@ -30,6 +31,7 @@ import com.alibaba.polardbx.optimizer.partition.PartitionSpec; import com.alibaba.polardbx.optimizer.partition.common.PartitionTableType; import com.alibaba.polardbx.optimizer.tablegroup.TableGroupInfoManager; +import lombok.Getter; import org.apache.commons.lang.StringUtils; import java.util.ArrayList; @@ -41,6 +43,7 @@ */ public class PartitionMetaUtil { + @Getter public static class PartitionMetaRecord { public PartitionMetaRecord() { @@ -62,6 +65,7 @@ public PartitionMetaRecord() { public String partName; public Long partPosi; public String partDesc; + public String partArcStateName; public String subPartMethod; public String subPartCol; @@ -71,6 +75,7 @@ public PartitionMetaRecord() { public String subPartTempName; public Long subPartPosi; public String subPartDesc; + public String subPartArcStateName; public String partComment = ""; @@ -146,6 +151,8 @@ public static List handlePartitionsMeta(PartitionInfo partI String partName = partSpec.getName(); Long partPosi = partSpec.getPosition(); String partDesc = partSpec.getBoundSpec().toString(); + String partArcStateName = + TtlPartArcState.getTtlPartArcStateByArcStateValue(partSpec.getArcState()).getArcStateName(); if (useSubPart) { List subpartSpecs = partSpec.getSubPartitions(); for (int j = 0; j < subpartSpecs.size(); j++) { @@ -155,6 +162,8 @@ public static List handlePartitionsMeta(PartitionInfo partI Long phySpecPosi = subPartSpec.getPhyPartPosition(); String subPartDesc = subPartSpec.getBoundSpec().toString(); String subPartTempName = ""; + String subPartArcStatName = + TtlPartArcState.getTtlPartArcStateByArcStateValue(subPartSpec.getArcState()).getArcStateName(); String pgName = subPartName; String phyDbGroup = subPartSpec.getLocation().getGroupKey(); @@ -184,6 +193,7 @@ public static List handlePartitionsMeta(PartitionInfo partI metaRec.partName = partName; metaRec.partPosi = partPosi; metaRec.partDesc = partDesc; + metaRec.partArcStateName = partArcStateName; metaRec.subPartMethod = subPartMethod; metaRec.subPartCol = subPartCol; @@ -193,6 +203,7 @@ public static List handlePartitionsMeta(PartitionInfo partI metaRec.subPartTempName = subPartTempName; metaRec.subPartPosi = subPartPosi; metaRec.subPartDesc = subPartDesc; + metaRec.subPartArcStateName = subPartArcStatName; metaRec.pgName = pgName; metaRec.phyDbGroup = phyDbGroup; @@ -202,40 +213,6 @@ public static List handlePartitionsMeta(PartitionInfo partI result.add(metaRec); -// result.addRow(new Object[] { -// phySpecPosi, -// -// dbName, -// tblName, -// rawGsiName, -// primaryTbl, -// tblType, -// tgName, -// -// partMethod, -// partCol, -// partColType, -// partExpr, -// partName, -// partPosi, -// partDesc, -// -// subPartMethod, -// subPartCol, -// subPartColType, -// subPartExpr, -// subPartName, -// subPartTempName, -// subPartPosi, -// subPartDesc, -// -// pgName, -// phyDb, -// phyTb, -// rwDnId -// -// }); - } } else { @@ -264,6 +241,7 @@ public static List handlePartitionsMeta(PartitionInfo partI metaRec.partName = partName; metaRec.partPosi = partPosi; metaRec.partDesc = partDesc; + metaRec.partArcStateName = partArcStateName; metaRec.subPartMethod = null; metaRec.subPartCol = null; @@ -273,6 +251,7 @@ public static List handlePartitionsMeta(PartitionInfo partI metaRec.subPartTempName = null; metaRec.subPartPosi = null; metaRec.subPartDesc = null; + metaRec.subPartArcStateName = null; metaRec.pgName = pgName; metaRec.phyDbGroup = phyDbGroup; @@ -301,7 +280,7 @@ protected static String getRwDnByGroupName(TopologyHandler topology, String grpN return groupDs.getMasterDNId(); } - protected static String getPhyDbByGroupName(TopologyHandler topology, String grpName) { + public static String getPhyDbByGroupName(TopologyHandler topology, String grpName) { IGroupExecutor groupExecutor = topology.get(grpName); if (groupExecutor == null) { return null; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ReloadUtils.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ReloadUtils.java index 5a53ba07c..658393db9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ReloadUtils.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/ReloadUtils.java @@ -77,6 +77,7 @@ public static void reloadDataSources(ExecutorContext executorContext, OptimizerC } public enum ReloadType { - USERS, SCHEMA, DATASOURCES, FILESTORAGE, PROCEDURES, FUNCTIONS, JAVA_FUNCTIONS, STATISTICS, COLUMNARMANAGER; + USERS, SCHEMA, DATASOURCES, FILESTORAGE, PROCEDURES, FUNCTIONS, JAVA_FUNCTIONS, STATISTICS, COLUMNARMANAGER, + COLUMNARMANAGER_CACHE, COLUMNARMANAGER_SNAPSHOT, COLUMNARMANAGER_SCHEMA } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/SchemaMetaUtil.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/SchemaMetaUtil.java index bde5b247f..f72189bed 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/SchemaMetaUtil.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/SchemaMetaUtil.java @@ -25,6 +25,7 @@ import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.listener.impl.MetaDbConfigManager; import com.alibaba.polardbx.gms.listener.impl.MetaDbDataIdBuilder; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; import com.alibaba.polardbx.gms.metadb.misc.SchemaInfoCleaner; import com.alibaba.polardbx.gms.metadb.table.BaselineInfoAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableStatus; @@ -34,12 +35,14 @@ import com.alibaba.polardbx.gms.tablegroup.JoinGroupUtils; import com.alibaba.polardbx.gms.tablegroup.TableGroupUtils; import com.alibaba.polardbx.gms.topology.SchemaMetaCleaner; +import com.alibaba.polardbx.gms.ttl.TtlInfoAccessor; import com.alibaba.polardbx.gms.util.MetaDbLogUtil; import com.alibaba.polardbx.optimizer.view.PolarDbXSystemTableView; import java.sql.Connection; import java.util.List; +import static com.alibaba.polardbx.common.cdc.ICdcManager.DEFAULT_DDL_VERSION_ID; import static com.alibaba.polardbx.common.properties.ConnectionParams.ENABLE_HLL; /** @@ -50,17 +53,17 @@ public class SchemaMetaUtil { public static class PolarDbXSchemaMetaCleaner implements SchemaMetaCleaner { @Override - public void clearSchemaMeta(String schemaName, Connection metaDbConn) { - SchemaMetaUtil.cleanupSchemaMeta(schemaName, metaDbConn); + public void clearSchemaMeta(String schemaName, Connection metaDbConn, long versionId) { + SchemaMetaUtil.cleanupSchemaMeta(schemaName, metaDbConn, versionId); } } - public static void cleanupSchemaMeta(String schemaName, Connection metaDbConn) { + public static void cleanupSchemaMeta(String schemaName, Connection metaDbConn, long versionId) { TableInfoManager tableInfoManager = new TableInfoManager(); SchemaInfoCleaner schemaInfoCleaner = new SchemaInfoCleaner(); DdlPlanAccessor ddlPlanAccessor = new DdlPlanAccessor(); - BaselineInfoAccessor baselineInfoAccessor = new BaselineInfoAccessor(false); + TtlInfoAccessor ttlInfoAccessor = new TtlInfoAccessor(); try { assert metaDbConn != null; @@ -68,7 +71,7 @@ public static void cleanupSchemaMeta(String schemaName, Connection metaDbConn) { tableInfoManager.setConnection(metaDbConn); schemaInfoCleaner.setConnection(metaDbConn); ddlPlanAccessor.setConnection(metaDbConn); - baselineInfoAccessor.setConnection(metaDbConn); + ttlInfoAccessor.setConnection(metaDbConn); // If the schema has been dropped, then we have to do some cleanup. String tableListDataId = MetaDbDataIdBuilder.getTableListDataId(schemaName); @@ -83,7 +86,10 @@ public static void cleanupSchemaMeta(String schemaName, Connection metaDbConn) { MetaDbConfigManager.getInstance().unregister(tableDataId, metaDbConn); } - tableInfoManager.updateColumnarTableStatusBySchema(schemaName, ColumnarTableStatus.DROP.name()); + if (versionId != DEFAULT_DDL_VERSION_ID) { + tableInfoManager.updateColumnarTableStatusAndVersionIDBySchema(schemaName, versionId, + ColumnarTableStatus.DROP.name()); + } tableInfoManager.removeAll(schemaName); @@ -95,8 +101,6 @@ public static void cleanupSchemaMeta(String schemaName, Connection metaDbConn) { new PolarDbXSystemTableLogicalTableStatistic().deleteAll(schemaName, metaDbConn); new PolarDbXSystemTableColumnStatistic().deleteAll(schemaName, metaDbConn); - baselineInfoAccessor.deleteBySchema(schemaName); - GsiBackfillManager.deleteAll(schemaName, metaDbConn); CheckerManager.deleteAll(schemaName, metaDbConn); ddlPlanAccessor.deleteAll(schemaName); @@ -109,8 +113,8 @@ public static void cleanupSchemaMeta(String schemaName, Connection metaDbConn) { } finally { tableInfoManager.setConnection(null); schemaInfoCleaner.setConnection(null); - baselineInfoAccessor.setConnection(null); } + deleteBaselineInformation(schemaName, new BaselineInfoAccessor(false)); } public static boolean checkSupportHll(String schemaName) { @@ -130,21 +134,26 @@ public static boolean checkSupportHll(String schemaName) { return executorContext.getStorageInfoManager().supportsHyperLogLog(); } - public static boolean checkSupportHll(String schemaName, boolean useHll) { - if (schemaName == null || schemaName.isEmpty()) { - throw new IllegalArgumentException("checkSupportHll with empty schema name"); - } - if (!useHll) { - return false; - } - - ExecutorContext executorContext = ExecutorContext.getContext(schemaName); - - // should not happen, ExecutorContext should be inited when schema inited - if (executorContext == null) { - return false; + /** + * Deletes baseline information for a specified schema separately, + * due to potential size issues with removing the entire schema in a single transaction. + * + * @param schemaName Name of the schema whose baseline information should be deleted. + */ + public static void deleteBaselineInformation(String schemaName, BaselineInfoAccessor baselineInfoAccessor) { + try (Connection metaDatabaseConnection = MetaDbDataSource.getInstance().getConnection()) { + // Set up a new connection to the meta database specifically + baselineInfoAccessor.setConnection(metaDatabaseConnection); + + // Delete baseline information associated with the specified schema + baselineInfoAccessor.deleteBySchema(schemaName); + } catch (Exception exception) { + MetaDbLogUtil.META_DB_LOG.error("Failed to delete baseline information for schema: " + schemaName, + exception); + } finally { + // Clear the connection reference to ensure proper resource cleanup. + baselineInfoAccessor.setConnection(null); } - return executorContext.getStorageInfoManager().supportsHyperLogLog(); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/failpoint/FailPoint.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/failpoint/FailPoint.java index 382c2cdac..5431d2c5a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/failpoint/FailPoint.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/failpoint/FailPoint.java @@ -70,7 +70,8 @@ public static void inject(String key, Runnable runnable) { } } - public static void inject(String key, ExecutionContext executionContext, Runnable runnable) { + public static void injectFromHintWithEnableKeyCheck(String key, ExecutionContext executionContext, + Runnable runnable) { try { assert !(isKeyEnable(key) && isKeyEnableFromHint(key, executionContext)) @@ -209,12 +210,20 @@ public static void injectExceptionFromHint(String key, ExecutionContext executio }); } - public static void injectExceptionFromHintWithKeyEnable(String key, ExecutionContext executionContext) { - inject(key, executionContext, () -> { + public static void injectExceptionFromHintWithKeyEnableCheck(String key, ExecutionContext executionContext) { + injectFromHintWithEnableKeyCheck(key, executionContext, () -> { throw new RuntimeException("injected failure from " + key); }); } + public static void injectExceptionWithTableName(String tableName, String key, ExecutionContext executionContext) { + injectFromHint(key, executionContext, (k, v) -> { + if (StringUtils.equalsIgnoreCase(tableName, v)) { + throw new RuntimeException("injected failure from " + key); + } + }); + } + public static void throwException() { throw new RuntimeException("injected failure"); } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/failpoint/FailPointKey.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/failpoint/FailPointKey.java index 3d66f9396..ab55a840a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/failpoint/FailPointKey.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/failpoint/FailPointKey.java @@ -86,12 +86,24 @@ public interface FailPointKey { */ String FP_AFTER_PHYSICAL_DDL_PARTIAL_EXCEPTION = "FP_AFTER_PHYSICAL_DDL_PARTIAL_EXCEPTION"; + /** + * set @FP_PHYSICAL_DDL_INTERRUPTED='true'; + * 执行物理DDL期间中断 + */ + String FP_PHYSICAL_DDL_INTERRUPTED = "FP_PHYSICAL_DDL_INTERRUPTED"; + /** * set @FP_NEW_SEQ_EXCEPTION_RIGHT_AFTER_PHY_CREATION='true'; * 创建New Seq的底层Seq后立即失败 */ String FP_NEW_SEQ_EXCEPTION_RIGHT_AFTER_PHY_CREATION = "FP_NEW_SEQ_EXCEPTION_RIGHT_AFTER_PHY_CREATION"; + /** + * set @FP_SPECIFIED_TABLE_DROP_PHY_EXCEPTION='tableName'; + * 指定表执行 DROP TABLE 物理 DDL 异常 + */ + String FP_SPECIFIED_TABLE_DROP_PHY_EXCEPTION = "FP_SPECIFIED_TABLE_DROP_PHY_EXCEPTION"; + /** * set @FP_PHYSICAL_DDL_TIMEOUT='1000'; * 执行物理DDL时超时(毫秒) diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/transaction/DeadlockParser.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/transaction/DeadlockParser.java index 908a2a524..c750ce1c9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/transaction/DeadlockParser.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/transaction/DeadlockParser.java @@ -76,11 +76,9 @@ public class DeadlockParser { * Otherwise, return the deadlock log by parsing the status information. * * @param status the status information get by "show engine innodb status" - * @param executionContext used for privilege check * @return the deadlock log. */ - public static String parseLocalDeadlock(String status, - ExecutionContext executionContext) { + public static String parseLocalDeadlock(String status) { /* 1. Use the following pattern to parse the {status} and get the deadlock log only: @@ -258,7 +256,7 @@ public static Pair parseMdlDeadlock(List schemaNames) { final List>> results = SyncManagerHelper.sync(fetchAllTransSyncAction, schemaName, SyncScope.CURRENT_ONLY); - for (final List> result : results) { - if (result == null) { - continue; - } - for (final Map row : result) { - final Long transId = (Long) row.get("TRANS_ID"); - final String group = (String) row.get("GROUP"); - final Long connId = (Long) row.get("CONN_ID"); - final Long frontendConnId = (Long) row.get("FRONTEND_CONN_ID"); - final Long startTime = (Long) row.get("START_TIME"); - final String sql = (String) row.get("SQL"); - - final GroupConnPair groupConnPair = new GroupConnPair(group, connId); - lookupSet.addNewTransaction(groupConnPair, transId); - lookupSet.updateTransaction(transId, frontendConnId, sql, startTime); - } - } + updateTrxLookupSet(results, lookupSet); } return lookupSet; } + public static void updateTrxLookupSet(List>> results, TrxLookupSet lookupSet) { + for (final List> result : results) { + if (result == null) { + continue; + } + for (final Map row : result) { + final Long transId = (Long) row.get("TRANS_ID"); + final String group = (String) row.get("GROUP"); + final long connId = (Long) row.get("CONN_ID"); + final long frontendConnId = (Long) row.get("FRONTEND_CONN_ID"); + final Long startTime = (Long) row.get("START_TIME"); + final String sql = (String) row.get("SQL"); + Boolean ddl = (Boolean) row.get("DDL"); + if (null == ddl) { + ddl = false; + } + final GroupConnPair entry = new GroupConnPair(group, connId); + lookupSet.addNewTransaction(entry, transId); + lookupSet.updateTransaction(transId, frontendConnId, sql, startTime, ddl); + } + } + } + /** * Find full logical table name (`logical schema`.`logical table`) given physical DB and physical tables * diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/transaction/TrxLookupSet.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/transaction/TrxLookupSet.java index ff237c3c2..ad7435251 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/transaction/TrxLookupSet.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/utils/transaction/TrxLookupSet.java @@ -60,11 +60,13 @@ public TrxLookupSet() { public Transaction updateTransaction(Long transactionId, Long frontendConnId, String sql, - Long startTime) { + Long startTime, + boolean ddl) { final Transaction trx = transactionMap.computeIfAbsent(transactionId, Transaction::new); trx.setFrontendConnId(frontendConnId); trx.setSql(sql); trx.setStartTime(startTime); + trx.setDdl(ddl); return trx; } @@ -151,6 +153,7 @@ public static class Transaction { private Long frontendConnId; private String sql; private Long startTime; + private boolean ddl; /** * group name -> local transaction */ @@ -196,7 +199,7 @@ public Collection getAllLocalTransactions() { } public boolean isDdl() { - return null == frontendConnId; + return null == frontendConnId || ddl; } // ---------- setter methods ---------- @@ -213,6 +216,10 @@ public void setStartTime(Long startTime) { this.startTime = startTime; } + public void setDdl(boolean ddl) { + this.ddl = ddl; + } + @Override public int hashCode() { return transactionId.hashCode(); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/EvaluationContext.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/EvaluationContext.java index a7bd7f3c6..e2021da79 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/EvaluationContext.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/EvaluationContext.java @@ -39,8 +39,4 @@ public ExecutionContext getExecutionContext() { return executionContext; } - public void setExecutionContext(ExecutionContext executionContext) { - this.executionContext = executionContext; - } - } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/ExtractVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/ExtractVectorizedExpression.java index 5b82f1bd8..ce083b5d7 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/ExtractVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/ExtractVectorizedExpression.java @@ -19,7 +19,6 @@ import com.alibaba.polardbx.common.utils.time.MySQLTimeConverter; import com.alibaba.polardbx.common.utils.time.calculator.MySQLIntervalType; import com.alibaba.polardbx.common.utils.time.core.MysqlDateTime; -import com.alibaba.polardbx.common.utils.time.core.OriginalDate; import com.alibaba.polardbx.common.utils.time.core.TimeStorage; import com.alibaba.polardbx.common.utils.time.parser.TimeParserFlags; import com.alibaba.polardbx.executor.chunk.DateBlock; @@ -43,6 +42,7 @@ argumentKinds = {Const, Variable} ) public class ExtractVectorizedExpression extends AbstractVectorizedExpression { + private MySQLIntervalType intervalType; private boolean isConstOperandNull; @@ -60,6 +60,57 @@ public ExtractVectorizedExpression(DataType outputDataType, isConstOperandNull = intervalType == null; } + static long doParseInterval(MysqlDateTime t, int sign, MySQLIntervalType intervalType) { + switch (intervalType) { + case INTERVAL_YEAR: + return t.getYear(); + case INTERVAL_YEAR_MONTH: + return t.getYear() * 100L + t.getMonth(); + case INTERVAL_QUARTER: + return (t.getMonth() + 2) / 3; + case INTERVAL_MONTH: + return t.getMonth(); + case INTERVAL_WEEK: { + long[] weekAndYear = MySQLTimeConverter.datetimeToWeek(t, TimeParserFlags.FLAG_WEEK_FIRST_WEEKDAY); + return weekAndYear[0]; + } + case INTERVAL_DAY: + return t.getDay(); + case INTERVAL_DAY_HOUR: + return (t.getDay() * 100L + t.getHour()) * sign; + case INTERVAL_DAY_MINUTE: + return (t.getDay() * 10000L + t.getHour() * 100L + t.getMinute()) * sign; + case INTERVAL_DAY_SECOND: + return (t.getDay() * 1000000L + (t.getHour() * 10000L + t.getMinute() * 100 + t.getSecond())) * sign; + case INTERVAL_HOUR: + return t.getHour() * sign; + case INTERVAL_HOUR_MINUTE: + return (t.getHour() * 100 + t.getMinute()) * sign; + case INTERVAL_HOUR_SECOND: + return (t.getHour() * 10000 + t.getMinute() * 100 + t.getSecond()) * sign; + case INTERVAL_MINUTE: + return t.getMinute() * sign; + case INTERVAL_MINUTE_SECOND: + return (t.getMinute() * 100 + t.getSecond()) * sign; + case INTERVAL_SECOND: + return t.getSecond() * sign; + case INTERVAL_MICROSECOND: + return t.getSecondPart() / 1000L * sign; + case INTERVAL_DAY_MICROSECOND: + return ((t.getDay() * 1000000L + t.getHour() * 10000L + t.getMinute() * 100 + t.getSecond()) * 1000000L + t + .getSecondPart() / 1000L) * sign; + case INTERVAL_HOUR_MICROSECOND: + return ((t.getHour() * 10000L + t.getMinute() * 100 + t.getSecond()) * 1000000L + t.getSecondPart() / 1000L) + * sign; + case INTERVAL_MINUTE_MICROSECOND: + return (((t.getMinute() * 100 + t.getSecond())) * 1000000L + t.getSecondPart() / 1000L) * sign; + case INTERVAL_SECOND_MICROSECOND: + return (t.getSecond() * 1000000L + t.getSecondPart() / 1000L) * sign; + default: + return 0; + } + } + @Override public void eval(EvaluationContext ctx) { evalChildren(ctx); @@ -79,9 +130,15 @@ public void eval(EvaluationContext ctx) { // when the interval unit is null boolean[] outputNulls = outputVectorSlot.nulls(); if (isConstOperandNull) { - outputVectorSlot.setHasNull(true); - for (int i = 0; i < batchSize; i++) { - outputNulls[i] = true; + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + outputNulls[j] = true; + } + } else { + for (int i = 0; i < batchSize; i++) { + outputNulls[i] = true; + } } return; } @@ -148,17 +205,30 @@ public void eval(EvaluationContext ctx) { // normal processing for datetime value. MysqlDateTime scratchValue = new MysqlDateTime(); - for (int i = 0; i < batchSize; i++) { - int j = isSelectionInUse ? sel[i] : i; + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + + // parse date value + long packedLong = packedLongs[j]; + TimeStorage.readDate(packedLong, scratchValue); - // parse date value - long packedLong = packedLongs[j]; - TimeStorage.readDate(packedLong, scratchValue); + // parse interval by sign and mysql datetime value. + int sign = isDate ? 1 : (scratchValue.isNeg() ? -1 : 1); + long result = doParseInterval(scratchValue, sign, intervalType); + output[j] = result; + } + } else { + for (int i = 0; i < batchSize; i++) { + // parse date value + long packedLong = packedLongs[i]; + TimeStorage.readDate(packedLong, scratchValue); - // parse interval by sign and mysql datetime value. - int sign = isDate ? 1 : (scratchValue.isNeg() ? -1 : 1); - long result = doParseInterval(scratchValue, sign); - output[j] = result; + // parse interval by sign and mysql datetime value. + int sign = isDate ? 1 : (scratchValue.isNeg() ? -1 : 1); + long result = doParseInterval(scratchValue, sign, intervalType); + output[i] = result; + } } } } else if (inputVectorSlot instanceof ReferenceBlock) { @@ -191,61 +261,13 @@ public void eval(EvaluationContext ctx) { } // parse interval by sign and mysql datetime value. - long result = doParseInterval(t, sign); + long result = doParseInterval(t, sign, intervalType); output[j] = result; } } - } - private long doParseInterval(MysqlDateTime t, int sign) { - switch (intervalType) { - case INTERVAL_YEAR: - return t.getYear(); - case INTERVAL_YEAR_MONTH: - return t.getYear() * 100L + t.getMonth(); - case INTERVAL_QUARTER: - return (t.getMonth() + 2) / 3; - case INTERVAL_MONTH: - return t.getMonth(); - case INTERVAL_WEEK: { - long[] weekAndYear = MySQLTimeConverter.datetimeToWeek(t, TimeParserFlags.FLAG_WEEK_FIRST_WEEKDAY); - return weekAndYear[0]; - } - case INTERVAL_DAY: - return t.getDay(); - case INTERVAL_DAY_HOUR: - return (t.getDay() * 100L + t.getHour()) * sign; - case INTERVAL_DAY_MINUTE: - return (t.getDay() * 10000L + t.getHour() * 100L + t.getMinute()) * sign; - case INTERVAL_DAY_SECOND: - return (t.getDay() * 1000000L + (t.getHour() * 10000L + t.getMinute() * 100 + t.getSecond())) * sign; - case INTERVAL_HOUR: - return t.getHour() * sign; - case INTERVAL_HOUR_MINUTE: - return (t.getHour() * 100 + t.getMinute()) * sign; - case INTERVAL_HOUR_SECOND: - return (t.getHour() * 10000 + t.getMinute() * 100 + t.getSecond()) * sign; - case INTERVAL_MINUTE: - return t.getMinute() * sign; - case INTERVAL_MINUTE_SECOND: - return (t.getMinute() * 100 + t.getSecond()) * sign; - case INTERVAL_SECOND: - return t.getSecond() * sign; - case INTERVAL_MICROSECOND: - return t.getSecondPart() / 1000L * sign; - case INTERVAL_DAY_MICROSECOND: - return ((t.getDay() * 1000000L + t.getHour() * 10000L + t.getMinute() * 100 + t.getSecond()) * 1000000L + t - .getSecondPart() / 1000L) * sign; - case INTERVAL_HOUR_MICROSECOND: - return ((t.getHour() * 10000L + t.getMinute() * 100 + t.getSecond()) * 1000000L + t.getSecondPart() / 1000L) - * sign; - case INTERVAL_MINUTE_MICROSECOND: - return (((t.getMinute() * 100 + t.getSecond())) * 1000000L + t.getSecondPart() / 1000L) * sign; - case INTERVAL_SECOND_MICROSECOND: - return (t.getSecond() * 1000000L + t.getSecondPart() / 1000L) * sign; - default: - return 0; - } + public MySQLIntervalType getIntervalType() { + return intervalType; } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/InValuesVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/InValuesVectorizedExpression.java index 194937566..23e22d2f4 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/InValuesVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/InValuesVectorizedExpression.java @@ -16,8 +16,11 @@ package com.alibaba.polardbx.executor.vectorized; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.optimizer.config.table.Field; import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.google.common.base.Preconditions; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; @@ -34,36 +37,76 @@ */ public class InValuesVectorizedExpression extends AbstractVectorizedExpression { + private static final Logger logger = LoggerFactory.getLogger(InValuesVectorizedExpression.class); + private final int operandCount; - private final InValueSet inValueSet; + private InValueSet inValueSet; private boolean hasNull; + private boolean allNull; - public InValuesVectorizedExpression(DataType dataType, List rexLiteralList, int outputIndex) { - super(dataType, outputIndex, new VectorizedExpression[0]); + public InValuesVectorizedExpression(DataType colDataType, DataType inDataType, + List rexLiteralList, int outputIndex, boolean autoTypeConvert) { + super(inDataType, outputIndex, new VectorizedExpression[0]); this.operandCount = rexLiteralList.size() - 1; - this.inValueSet = new InValueSet(dataType, operandCount); + InValueSet inValueSet = null; this.hasNull = false; + this.allNull = true; + + if (autoTypeConvert && shouldBeConverted(inDataType, colDataType)) { + try { + // try converting string into number for better performance + inValueSet = new InValueSet(colDataType, operandCount); + for (int operandIndex = 1; operandIndex <= operandCount; operandIndex++) { + Object value = ((RexLiteral) rexLiteralList.get(operandIndex)).getValue3(); + Object convertedValue = colDataType.convertFrom(value); + if (convertedValue == null) { + this.hasNull = true; + } else { + this.allNull = false; + inValueSet.add(convertedValue); + } + } + this.inValueSet = inValueSet; + return; + } catch (Exception e) { + logger.warn(e.getMessage()); + } + } + inValueSet = new InValueSet(inDataType, operandCount); for (int operandIndex = 1; operandIndex <= operandCount; operandIndex++) { Object value = ((RexLiteral) rexLiteralList.get(operandIndex)).getValue3(); - Object convertedValue = dataType.convertFrom(value); + Object convertedValue = inDataType.convertFrom(value); if (convertedValue == null) { - hasNull = true; + this.hasNull = true; } else { + this.allNull = false; inValueSet.add(convertedValue); } } + + this.inValueSet = inValueSet; + } + + private boolean shouldBeConverted(DataType inDataType, DataType colDataType) { + return DataTypeUtil.anyMatchSemantically(inDataType, DataTypes.CharType, DataTypes.VarcharType) && + DataTypeUtil.anyMatchSemantically(colDataType, DataTypes.IntegerType, DataTypes.LongType); + } + + public static InValuesVectorizedExpression from(List rexLiteralList, int outputIndex) { + return from(rexLiteralList, outputIndex, false); } /** - * @param rexLiteralList start from index1 + * @param rexLiteralList start from index:1 */ - public static InValuesVectorizedExpression from(List rexLiteralList, int outputIndex) { + public static InValuesVectorizedExpression from(List rexLiteralList, int outputIndex, boolean autoTypeConvert) { Preconditions.checkArgument(rexLiteralList.size() > 1, "Illegal in values, list size: " + rexLiteralList.size()); + DataType colDataType = new Field(rexLiteralList.get(0).getType()).getDataType(); RexLiteral rexLiteral = (RexLiteral) rexLiteralList.get(1); Field field = new Field(rexLiteral.getType()); - return new InValuesVectorizedExpression(field.getDataType(), rexLiteralList, outputIndex); + return new InValuesVectorizedExpression(colDataType, field.getDataType(), rexLiteralList, outputIndex, autoTypeConvert); } public int getOperandCount() { @@ -75,7 +118,11 @@ public InValueSet getInValueSet() { } public boolean hasNull() { - return hasNull; + return this.hasNull; + } + + public boolean allNull() { + return this.allNull; } @Override @@ -108,13 +155,13 @@ public InValueSet(DataType dataType, int capacity) { } } - private SetType getSetType(DataType dataType) { - if (dataType == DataTypes.LongType) { - return SetType.LONG; - } + static SetType getSetType(DataType dataType) { if (dataType == DataTypes.IntegerType) { return SetType.INT; } + if (dataType == DataTypes.LongType) { + return SetType.LONG; + } return SetType.OTHERS; } @@ -183,6 +230,10 @@ public boolean contains(Object value) { } } + public DataType getDataType() { + return dataType; + } + enum SetType { INT, LONG, diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/SubStrCharVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/SubStrCharVectorizedExpression.java new file mode 100644 index 000000000..c64ba6a4c --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/SubStrCharVectorizedExpression.java @@ -0,0 +1,21 @@ +package com.alibaba.polardbx.executor.vectorized; + +import com.alibaba.polardbx.executor.vectorized.metadata.ExpressionSignatures; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; + +import static com.alibaba.polardbx.executor.vectorized.metadata.ArgumentKind.Const; +import static com.alibaba.polardbx.executor.vectorized.metadata.ArgumentKind.Variable; + +@ExpressionSignatures( + names = {"SUBSTRING", "SUBSTR"}, + argumentTypes = {"Char", "Long", "Long"}, + argumentKinds = {Variable, Const, Const} +) +public class SubStrCharVectorizedExpression extends SubStrVarcharVectorizedExpression { + + public SubStrCharVectorizedExpression(DataType outputDataType, + int outputIndex, VectorizedExpression[] children) { + super(outputDataType, outputIndex, children); + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/SubStrVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/SubStrVarcharVectorizedExpression.java similarity index 92% rename from polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/SubStrVectorizedExpression.java rename to polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/SubStrVarcharVectorizedExpression.java index 7a1511f64..869f068f0 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/SubStrVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/SubStrVarcharVectorizedExpression.java @@ -30,19 +30,19 @@ import static com.alibaba.polardbx.executor.vectorized.metadata.ArgumentKind.Variable; @ExpressionSignatures( - names = {"SUBSTRING"}, + names = {"SUBSTRING", "SUBSTR"}, argumentTypes = {"Varchar", "Long", "Long"}, argumentKinds = {Variable, Const, Const} ) -public class SubStrVectorizedExpression extends AbstractVectorizedExpression { +public class SubStrVarcharVectorizedExpression extends AbstractVectorizedExpression { private boolean shouldReturnNull; private boolean shouldReturnEmpty; private boolean useNegativeStart; private int startPos; private int subStrLen; - public SubStrVectorizedExpression(DataType outputDataType, - int outputIndex, VectorizedExpression[] children) { + public SubStrVarcharVectorizedExpression(DataType outputDataType, + int outputIndex, VectorizedExpression[] children) { super(outputDataType, outputIndex, children); Object operand1Value = ((LiteralVectorizedExpression) children[1]).getConvertedValue(); @@ -92,9 +92,15 @@ public void eval(EvaluationContext ctx) { if (shouldReturnNull) { boolean[] outputNulls = outputVectorSlot.nulls(); - outputVectorSlot.setHasNull(true); - for (int i = 0; i < batchSize; i++) { - outputNulls[i] = true; + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = selection[i]; + outputNulls[j] = true; + } + } else { + for (int i = 0; i < batchSize; i++) { + outputNulls[i] = true; + } } return; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/build/ExpressionRewriter.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/build/ExpressionRewriter.java index ee5bc7a87..1056b0d97 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/build/ExpressionRewriter.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/build/ExpressionRewriter.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.executor.vectorized.build; +import com.alibaba.polardbx.common.datatype.RowValue; import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.Pair; @@ -29,6 +30,7 @@ import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.expression.calc.DynamicParamExpression; import com.alibaba.polardbx.optimizer.utils.ExprContextProvider; +import com.alibaba.polardbx.optimizer.utils.RexUtils; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import org.apache.calcite.rel.type.RelDataType; @@ -39,9 +41,11 @@ import org.apache.calcite.rex.RexInputRef; import org.apache.calcite.rex.RexLiteral; import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexShuttle; import org.apache.calcite.rex.RexUtil; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.calcite.sql.type.SqlTypeUtil; import java.util.ArrayList; import java.util.Arrays; @@ -54,6 +58,8 @@ import java.util.stream.Stream; import static org.apache.calcite.sql.type.SqlTypeName.BIGINT; +import static org.apache.calcite.sql.type.SqlTypeName.CHAR; +import static org.apache.calcite.sql.type.SqlTypeName.VARCHAR; /** * Rewrite the expression tree to fit the vectorized framework. @@ -67,6 +73,7 @@ public class ExpressionRewriter { private final boolean fallback; private final boolean enableCSE; private ExprContextProvider contextProvider; + private RexConstantFoldShuttle constantFoldShuttle; public ExpressionRewriter(ExecutionContext executionContext) { this.executionContext = executionContext; @@ -75,6 +82,16 @@ public ExpressionRewriter(ExecutionContext executionContext) { this.enableCSE = executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_COMMON_SUB_EXPRESSION_TREE_ELIMINATE); this.contextProvider = new ExprContextProvider(executionContext); + this.constantFoldShuttle = new RexConstantFoldShuttle(REX_BUILDER, executionContext); + } + + public RexCall rewriteConstFold(RexCall call) { + RexNode newNode = call.accept(constantFoldShuttle); + if (newNode instanceof RexCall) { + return (RexCall) newNode; + } + // fail to const fold. + return call; } public RexCall rewrite(RexCall call, boolean isScalar) { @@ -88,7 +105,8 @@ public RexCall rewrite(RexCall call, boolean isScalar) { || call.op == TddlOperatorTable.DATE_SUB || call.op == TddlOperatorTable.SUBDATE) { return rewriteTemporalCalc(call); - } else if (!isScalar && !fallback && call.op == TddlOperatorTable.IN) { + } else if (!isScalar && !fallback && + (call.op == TddlOperatorTable.IN || call.op == TddlOperatorTable.NOT_IN)) { return rewriteIn(call); } else if (enableCSE && call.op == TddlOperatorTable.OR) { return rewriteOr(call); @@ -492,33 +510,6 @@ private RexCall rewriteControlFlowFunction(RexCall rexCall) { return rexCall; } - /** - * rewrite CASE operator to IF operator. - * CASE WHEN cond1 THEN expr1 - * WHEN cond2 THEN expr2 - * ... - * ELSE exprN - * END - * => - * IF = IF1 - * IF1 = (cond1, expr1, IF2) - * IFI = (condI, exprI, IFI+1) - * I < N - */ - private RexNode makeCaseOperator(final RelDataType type, final List exprList, int startIndex) { - RexNode elseNode = startIndex + 2 == exprList.size() - 1 ? - exprList.get(startIndex + 2) : - makeCaseOperator(type, exprList, startIndex + 2); - - List newExprList = ImmutableList.of( - exprList.get(startIndex), - exprList.get(startIndex + 1), - elseNode - ); - RexNode rexNode = REX_BUILDER.makeCall(type, TddlOperatorTable.IF, newExprList); - return rexNode; - } - private Object extractDynamicValue(RexDynamicParam dynamicParam) { // pre-compute the dynamic value when binging expression. DynamicParamExpression dynamicParamExpression = @@ -528,4 +519,76 @@ private Object extractDynamicValue(RexDynamicParam dynamicParam) { return dynamicParamExpression.eval(null, executionContext); } + private static class RexConstantFoldShuttle extends RexShuttle { + RexBuilder rexBuilder; + + ExecutionContext ec; + + RexConstantFoldShuttle(RexBuilder rexBuilder, ExecutionContext ec) { + this.rexBuilder = rexBuilder; + this.ec = ec; + } + + private boolean isTypeAllowed(RelDataType relDataType) { + if (relDataType == null) { + return false; + } + + // Unable to guarantee the correctness of the return value for scalar functions of the time type. + if (SqlTypeUtil.isTime(relDataType)) { + return false; + } + + // Do not accept certain data types, such as Binary, Varbinary, Interval. + return SqlTypeUtil.isNumeric(relDataType) + || SqlTypeUtil.isDatetime(relDataType) + || SqlTypeUtil.isCharTypes(relDataType); + } + + @Override + public RexNode visitCall(final RexCall call) { + if (!isTypeAllowed(call.getType())) { + return call; + } + if (RexUtil.isConstant(call)) { + Object obj = RexUtils.getEvalFuncExec(call, new ExprContextProvider(ec)).eval(null); + if (obj instanceof RowValue) { + return super.visitCall(call); + } + + try { + RelDataType relDataType = call.getType(); + SqlTypeName sqlTypeName = relDataType.getSqlTypeName(); + switch (sqlTypeName) { + case DATE: + case TIMESTAMP: + case DATETIME: + case TIMESTAMP_WITH_LOCAL_TIME_ZONE: + // String constants should be accepted as char type, + // and many vectorized expressions only accept char type constants as well. + case VARCHAR: + case CHAR: + String str = DataTypes.StringType.convertFrom(obj); + if (str == null) { + return rexBuilder.makeCharNullLiteral(); + } + return rexBuilder.makeLiteral(str); + + default: + if (obj == null) { + // sqlTypeName cannot be Char. + return rexBuilder.makeLiteral( + null, relDataType, sqlTypeName + ); + } + return rexBuilder.makeLiteral(obj, relDataType, true); + } + } catch (AssertionError e) { + return super.visitCall(call); + } + } + return super.visitCall(call); + } + } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/build/Rex2VectorizedExpressionVisitor.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/build/Rex2VectorizedExpressionVisitor.java index 6e3f62d83..0587c1b69 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/build/Rex2VectorizedExpressionVisitor.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/build/Rex2VectorizedExpressionVisitor.java @@ -34,6 +34,7 @@ import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; import com.alibaba.polardbx.executor.vectorized.VectorizedExpressionRegistry; import com.alibaba.polardbx.executor.vectorized.compare.FastInVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.compare.FastNotInVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.metadata.ArgumentInfo; import com.alibaba.polardbx.executor.vectorized.metadata.ExpressionConstructor; import com.alibaba.polardbx.executor.vectorized.metadata.ExpressionMode; @@ -118,7 +119,7 @@ public class Rex2VectorizedExpressionVisitor extends RexVisitorImpl expression = createInVecExpr(rewrittenCall); if (expression.isPresent()) { @@ -315,7 +321,7 @@ public VectorizedExpression visitCall(RexCall call) { } } - if (!fallback && !isSpecialFunction(call)) { + if (!fallback && !isSpecialFunction(rewrittenCall)) { Optional expression = createVectorizedExpression(rewrittenCall); if (expression.isPresent()) { return expression.get(); @@ -326,20 +332,33 @@ public VectorizedExpression visitCall(RexCall call) { return createGeneralVectorizedExpression(call); } + /** + * Including IN and NOT_IN + */ private Optional createInVecExpr(RexCall call) { try { - ExpressionConstructor constructor = - ExpressionConstructor.of(FastInVectorizedExpression.class); + ExpressionConstructor constructor; + if (call.op == SqlStdOperatorTable.IN) { + constructor = ExpressionConstructor.of(FastInVectorizedExpression.class); + } else if (call.op == SqlStdOperatorTable.NOT_IN) { + constructor = ExpressionConstructor.of(FastNotInVectorizedExpression.class); + } else { + // should not reach here + return Optional.empty(); + } + int outputIndex = -1; boolean isInFilterMode = isInFilterMode(call); DataType dataType = getOutputDataType(call); + boolean enableInAutoTypeConvert = executionContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_IN_VEC_AUTO_TYPE); VectorizedExpression[] children = new VectorizedExpression[2]; RexNode rexNode = call.operands.get(0); RexNode literalNode1 = call.operands.get(1); children[0] = rexNode.accept(this); outputIndex = addOutput(DataTypeUtil.calciteToDrdsType(literalNode1.getType())); - children[1] = InValuesVectorizedExpression.from(call.operands, outputIndex); + children[1] = InValuesVectorizedExpression.from(call.operands, outputIndex, enableInAutoTypeConvert); if (!isInFilterMode) { outputIndex = addOutput(dataType); @@ -362,32 +381,34 @@ private Optional createInVecExpr(RexCall call) { * check all in values are constants and of same datatype */ private boolean isInConstCall(RexCall call) { - if (call.op != SqlStdOperatorTable.IN) { - return false; - } - - if (call.operands.size() <= MAX_CODEGEN_IN_NUMS + 1) { - // use old code path + if (call.op != SqlStdOperatorTable.IN && + call.op != SqlStdOperatorTable.NOT_IN) { return false; } SqlTypeName typeName = null; - for (int i = 1; i < call.operands.size(); i++) { + for (int i = 0; i < call.operands.size(); i++) { RexNode rexNode = call.operands.get(i); + if (i == 0 && rexNode instanceof RexInputRef) { + // only support one column in (const ...) now + continue; + } if (!(rexNode instanceof RexLiteral)) { return false; } + SqlTypeName currentTypeName = ((RexLiteral) rexNode).getTypeName(); if (typeName == null) { - typeName = ((RexLiteral) rexNode).getTypeName(); + typeName = currentTypeName; } else { - if (typeName != ((RexLiteral) rexNode).getTypeName()) { + // allow NULL values + if (typeName != currentTypeName && currentTypeName != SqlTypeName.NULL) { return false; } } } if (typeName == SqlTypeName.CHAR || typeName == SqlTypeName.VARCHAR) { - // FastInVectorizedExpression does not support collation compare + // does not support collation compare in fast path boolean compatible = executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_OSS_COMPATIBLE); return !compatible; } @@ -396,7 +417,7 @@ private boolean isInConstCall(RexCall call) { @Override public VectorizedExpression visitFieldAccess(RexFieldAccess fieldAccess) { - throw new IllegalArgumentException("Correlated variable not supported in vectorized expression!"); + throw new IllegalArgumentException("Correlated variable is not supported in vectorized expression!"); } @Override diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/AbstractInIntegerColLongConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/AbstractInIntegerColLongConstVectorizedExpression.java deleted file mode 100644 index cc5811f9f..000000000 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/AbstractInIntegerColLongConstVectorizedExpression.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.executor.vectorized.compare; - -import com.alibaba.polardbx.executor.chunk.IntegerBlock; -import com.alibaba.polardbx.executor.chunk.LongBlock; -import com.alibaba.polardbx.executor.chunk.MutableChunk; -import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; -import com.alibaba.polardbx.executor.vectorized.AbstractVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.EvaluationContext; -import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; -import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; - -public abstract class AbstractInIntegerColLongConstVectorizedExpression extends AbstractVectorizedExpression { - protected final boolean[] operandIsNulls; - protected final long[] operands; - - public AbstractInIntegerColLongConstVectorizedExpression( - int outputIndex, - VectorizedExpression[] children) { - super(DataTypes.LongType, outputIndex, children); - - this.operandIsNulls = new boolean[operandCount()]; - this.operands = new long[operandCount()]; - - for (int operandIndex = 1; operandIndex <= operandCount(); operandIndex++) { - Object operand1Value = ((LiteralVectorizedExpression) children[operandIndex]).getConvertedValue(); - if (operand1Value == null) { - operandIsNulls[operandIndex - 1] = true; - operands[operandIndex - 1] = LongBlock.NULL_VALUE; - } else { - operandIsNulls[operandIndex - 1] = false; - operands[operandIndex - 1] = DataTypes.LongType.convertFrom(operand1Value); - } - } - } - - abstract int operandCount(); - - protected boolean anyOperandsNull() { - boolean res = false; - for (int operandIndex = 1; operandIndex <= operandCount(); operandIndex++) { - res |= operandIsNulls[operandIndex - 1]; - if (res) { - return true; - } - } - return false; - } - - protected long anyMatch(int left) { - for (int operandIndex = 1; operandIndex <= operandCount(); operandIndex++) { - if (left == operands[operandIndex - 1]) { - return LongBlock.TRUE_VALUE; - } - } - return LongBlock.FALSE_VALUE; - } - - @Override - public void eval(EvaluationContext ctx) { - children[0].eval(ctx); - MutableChunk chunk = ctx.getPreAllocatedChunk(); - int batchSize = chunk.batchSize(); - boolean isSelectionInUse = chunk.isSelectionInUse(); - int[] sel = chunk.selection(); - - RandomAccessBlock outputVectorSlot = chunk.slotIn(outputIndex, outputDataType); - RandomAccessBlock leftInputVectorSlot = - chunk.slotIn(children[0].getOutputIndex(), children[0].getOutputDataType()); - - long[] output = outputVectorSlot.cast(LongBlock.class).longArray(); - - if (anyOperandsNull()) { - boolean[] outputNulls = outputVectorSlot.nulls(); - outputVectorSlot.setHasNull(true); - for (int i = 0; i < batchSize; i++) { - outputNulls[i] = true; - } - return; - } - - int[] intArray = leftInputVectorSlot.cast(IntegerBlock.class).intArray(); - - if (isSelectionInUse) { - for (int i = 0; i < batchSize; i++) { - int j = sel[i]; - - output[j] = anyMatch(intArray[j]); - } - } else { - for (int i = 0; i < batchSize; i++) { - - output[i] = anyMatch(intArray[i]); - } - } - } -} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/AbstractInLongColLongConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/AbstractInLongColLongConstVectorizedExpression.java deleted file mode 100644 index b07ff0096..000000000 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/AbstractInLongColLongConstVectorizedExpression.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.executor.vectorized.compare; - -import com.alibaba.polardbx.executor.chunk.LongBlock; -import com.alibaba.polardbx.executor.chunk.MutableChunk; -import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; -import com.alibaba.polardbx.executor.vectorized.AbstractVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.EvaluationContext; -import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; -import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; - -public abstract class AbstractInLongColLongConstVectorizedExpression extends AbstractVectorizedExpression { - protected final boolean[] operandIsNulls; - protected final long[] operands; - - public AbstractInLongColLongConstVectorizedExpression( - int outputIndex, - VectorizedExpression[] children) { - super(DataTypes.LongType, outputIndex, children); - - this.operandIsNulls = new boolean[operandCount()]; - this.operands = new long[operandCount()]; - - for (int operandIndex = 1; operandIndex <= operandCount(); operandIndex++) { - Object operand1Value = ((LiteralVectorizedExpression) children[operandIndex]).getConvertedValue(); - if (operand1Value == null) { - operandIsNulls[operandIndex - 1] = true; - operands[operandIndex - 1] = LongBlock.NULL_VALUE; - } else { - operandIsNulls[operandIndex - 1] = false; - operands[operandIndex - 1] = DataTypes.LongType.convertFrom(operand1Value); - } - } - } - - abstract int operandCount(); - - protected boolean anyOperandsNull() { - boolean res = false; - for (int operandIndex = 1; operandIndex <= operandCount(); operandIndex++) { - res |= operandIsNulls[operandIndex - 1]; - if (res) { - return true; - } - } - return false; - } - - protected long anyMatch(long left) { - for (int operandIndex = 1; operandIndex <= operandCount(); operandIndex++) { - if (left == operands[operandIndex - 1]) { - return LongBlock.TRUE_VALUE; - } - } - return LongBlock.FALSE_VALUE; - } - - @Override - public void eval(EvaluationContext ctx) { - children[0].eval(ctx); - MutableChunk chunk = ctx.getPreAllocatedChunk(); - int batchSize = chunk.batchSize(); - boolean isSelectionInUse = chunk.isSelectionInUse(); - int[] sel = chunk.selection(); - - RandomAccessBlock outputVectorSlot = chunk.slotIn(outputIndex, outputDataType); - RandomAccessBlock leftInputVectorSlot = - chunk.slotIn(children[0].getOutputIndex(), children[0].getOutputDataType()); - - long[] output = outputVectorSlot.cast(LongBlock.class).longArray(); - - if (anyOperandsNull()) { - boolean[] outputNulls = outputVectorSlot.nulls(); - outputVectorSlot.setHasNull(true); - for (int i = 0; i < batchSize; i++) { - outputNulls[i] = true; - } - return; - } - - long[] longArray = leftInputVectorSlot.cast(LongBlock.class).longArray(); - - if (isSelectionInUse) { - for (int i = 0; i < batchSize; i++) { - int j = sel[i]; - - output[j] = anyMatch(longArray[j]); - } - } else { - for (int i = 0; i < batchSize; i++) { - - output[i] = anyMatch(longArray[i]); - } - } - } -} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/AbstractInVarcharColCharConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/AbstractInVarcharColCharConstVectorizedExpression.java index 44d08c26c..a59ee9054 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/AbstractInVarcharColCharConstVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/AbstractInVarcharColCharConstVectorizedExpression.java @@ -38,10 +38,8 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; public abstract class AbstractInVarcharColCharConstVectorizedExpression extends AbstractVectorizedExpression { @@ -49,6 +47,7 @@ public abstract class AbstractInVarcharColCharConstVectorizedExpression extends protected final boolean[] operandIsNulls; protected final Slice[] operands; + protected boolean allOperandsNull = true; protected Comparable[] operandSortKeys; protected DictionaryMapping mapping; @@ -72,6 +71,7 @@ public AbstractInVarcharColCharConstVectorizedExpression( operandIsNulls[operandIndex - 1] = true; operands[operandIndex - 1] = null; } else { + allOperandsNull = false; operandIsNulls[operandIndex - 1] = false; Slice operand = sliceType.convertFrom(operand1Value); operands[operandIndex - 1] = operand; @@ -94,17 +94,6 @@ public AbstractInVarcharColCharConstVectorizedExpression( abstract int operandCount(); - protected boolean anyOperandsNull() { - boolean res = false; - for (int operandIndex = 1; operandIndex <= operandCount(); operandIndex++) { - res |= operandIsNulls[operandIndex - 1]; - if (res) { - return true; - } - } - return false; - } - protected long anyMatch(Comparable sortKey) { for (int operandIndex = 1; operandIndex <= operandCount(); operandIndex++) { if (sortKey != null && sortKey.compareTo(operandSortKeys[operandIndex - 1]) == 0) { @@ -145,7 +134,7 @@ public void eval(EvaluationContext ctx) { long[] output = (outputVectorSlot.cast(LongBlock.class)).longArray(); - if (anyOperandsNull()) { + if (allOperandsNull) { boolean[] outputNulls = outputVectorSlot.nulls(); outputVectorSlot.setHasNull(true); Arrays.fill(outputNulls, true); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDateColCharConstCharConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDateColCharConstCharConstVectorizedExpression.java index a7d60bb7e..43abd332e 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDateColCharConstCharConstVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDateColCharConstCharConstVectorizedExpression.java @@ -28,6 +28,7 @@ import com.alibaba.polardbx.executor.vectorized.EvaluationContext; import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpressionUtils; import com.alibaba.polardbx.executor.vectorized.metadata.ExpressionSignatures; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; @@ -90,9 +91,15 @@ public void eval(EvaluationContext ctx) { if (operand1IsNull || operand2IsNull) { boolean[] outputNulls = outputVectorSlot.nulls(); - outputVectorSlot.setHasNull(true); - for (int i = 0; i < batchSize; i++) { - outputNulls[i] = true; + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + outputNulls[j] = true; + } + } else { + for (int i = 0; i < batchSize; i++) { + outputNulls[i] = true; + } } return; } @@ -146,5 +153,6 @@ public void eval(EvaluationContext ctx) { } } } + VectorizedExpressionUtils.mergeNulls(chunk, outputIndex, children[0].getOutputIndex()); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDecimalColDecimalConstDecimalConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDecimalColDecimalConstDecimalConstVectorizedExpression.java index b753d5d50..148fa2fc9 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDecimalColDecimalConstDecimalConstVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDecimalColDecimalConstDecimalConstVectorizedExpression.java @@ -79,6 +79,22 @@ public void eval(EvaluationContext ctx) { RandomAccessBlock leftInputVectorSlot = chunk.slotIn(children[0].getOutputIndex(), children[0].getOutputDataType()); + if (operand1IsNull || operand2IsNull) { + boolean[] outputNulls = outputVectorSlot.nulls(); + outputVectorSlot.setHasNull(true); + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + outputNulls[j] = true; + } + } else { + for (int i = 0; i < batchSize; i++) { + outputNulls[i] = true; + } + } + return; + } + long[] output = (outputVectorSlot.cast(LongBlock.class)).longArray(); DecimalStructure leftDec; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenIntegerColLongConstLongConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenIntegerColLongConstLongConstVectorizedExpression.java index 100bf957c..622c4ec93 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenIntegerColLongConstLongConstVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenIntegerColLongConstLongConstVectorizedExpression.java @@ -24,6 +24,7 @@ import com.alibaba.polardbx.executor.vectorized.EvaluationContext; import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpressionUtils; import com.alibaba.polardbx.executor.vectorized.metadata.ExpressionSignatures; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; @@ -79,8 +80,15 @@ public void eval(EvaluationContext ctx) { if (operand1IsNull || operand2IsNull) { boolean[] outputNulls = outputVectorSlot.nulls(); outputVectorSlot.setHasNull(true); - for (int i = 0; i < batchSize; i++) { - outputNulls[i] = true; + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + outputNulls[j] = true; + } + } else { + for (int i = 0; i < batchSize; i++) { + outputNulls[i] = true; + } } return; } @@ -105,6 +113,6 @@ public void eval(EvaluationContext ctx) { output[i] = b1 && b2 ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; } } - + VectorizedExpressionUtils.mergeNulls(chunk, outputIndex, children[0].getOutputIndex()); } } \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenLongColLongConstLongConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenLongColLongConstLongConstVectorizedExpression.java index 8bdaa5921..1f7fe2347 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenLongColLongConstLongConstVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenLongColLongConstLongConstVectorizedExpression.java @@ -23,6 +23,7 @@ import com.alibaba.polardbx.executor.vectorized.EvaluationContext; import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpressionUtils; import com.alibaba.polardbx.executor.vectorized.metadata.ExpressionSignatures; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; @@ -77,9 +78,15 @@ public void eval(EvaluationContext ctx) { if (operand1IsNull || operand2IsNull) { boolean[] outputNulls = outputVectorSlot.nulls(); - outputVectorSlot.setHasNull(true); - for (int i = 0; i < batchSize; i++) { - outputNulls[i] = true; + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + outputNulls[j] = true; + } + } else { + for (int i = 0; i < batchSize; i++) { + outputNulls[i] = true; + } } return; } @@ -104,6 +111,6 @@ public void eval(EvaluationContext ctx) { output[i] = b1 && b2 ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; } } - + VectorizedExpressionUtils.mergeNulls(chunk, outputIndex, children[0].getOutputIndex()); } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/EQVarcharColCharConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/EQVarcharColCharConstVectorizedExpression.java index 70a1ec4e6..a5d8804b4 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/EQVarcharColCharConstVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/EQVarcharColCharConstVectorizedExpression.java @@ -239,7 +239,7 @@ private void compareWithDict(SliceBlock sliceBlock, RandomAccessBlock outputVect long[] output, int batchSize, boolean isSelectionInUse, int[] sel) { int operandDictIdx; for (operandDictIdx = 0; operandDictIdx < sliceBlock.getDictionary().size(); operandDictIdx++) { - if (operand.compareTo(sliceBlock.getDictionary().getValue(operandDictIdx)) == 0) { + if (operand.equals(sliceBlock.getDictionary().getValue(operandDictIdx))) { break; } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastBetweenDecimalColCharConstCharConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastBetweenDecimalColCharConstCharConstVectorizedExpression.java index 84ea3cf7e..f02adc471 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastBetweenDecimalColCharConstCharConstVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastBetweenDecimalColCharConstCharConstVectorizedExpression.java @@ -66,7 +66,6 @@ public FastBetweenDecimalColCharConstCharConstVectorizedExpression( Object operand2Value = ((LiteralVectorizedExpression) children[2]).getConvertedValue(); this.useCompareWithDecimal64 = false; - // TODO simplify between null and null if (operand1Value == null) { this.operand1 = Decimal.ZERO; this.operand1IsNull = true; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression.java index ce83f2dcd..c52280f57 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression.java @@ -67,7 +67,6 @@ public FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression( Object operand2Value = ((LiteralVectorizedExpression) children[2]).getConvertedValue(); this.useCompareWithDecimal64 = false; - // TODO simplify between null and null if (operand1Value == null) { this.operand1 = Decimal.ZERO; this.operand1IsNull = true; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastGEDecimalColDecimalConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastGEDecimalColDecimalConstVectorizedExpression.java index bd5b68e97..35fae74e8 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastGEDecimalColDecimalConstVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastGEDecimalColDecimalConstVectorizedExpression.java @@ -183,5 +183,3 @@ private boolean checkSameScale(DecimalBlock leftInputVectorSlot) { return leftInputVectorSlot.getScale() == operand1.scale(); } } - - diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastInVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastInVectorizedExpression.java index 59832b022..18c9ab477 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastInVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastInVectorizedExpression.java @@ -24,27 +24,25 @@ import com.alibaba.polardbx.executor.vectorized.EvaluationContext; import com.alibaba.polardbx.executor.vectorized.InValuesVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpressionUtils; import com.alibaba.polardbx.optimizer.core.datatype.DataType; -import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.google.common.base.Preconditions; -import java.util.Set; - public class FastInVectorizedExpression extends AbstractVectorizedExpression { private final InValuesVectorizedExpression.InValueSet inValuesSet; - private final boolean operandsHaveNull; + private final boolean operandsAllNull; public FastInVectorizedExpression(DataType dataType, int outputIndex, VectorizedExpression[] children) { super(dataType, outputIndex, children); Preconditions.checkArgument(children.length == 2, - "Unexpected in vec expression children length: " + children.length); + "Unexpected IN vec expression children length: " + children.length); Preconditions.checkArgument(children[1] instanceof InValuesVectorizedExpression, - "Unexpected in values expression type: " + children[1].getClass().getSimpleName()); + "Unexpected IN values expression type: " + children[1].getClass().getSimpleName()); InValuesVectorizedExpression inExpr = (InValuesVectorizedExpression) children[1]; - this.operandsHaveNull = inExpr.hasNull(); + this.operandsAllNull = inExpr.allNull(); this.inValuesSet = inExpr.getInValueSet(); } @@ -58,15 +56,23 @@ public void eval(EvaluationContext ctx) { RandomAccessBlock outputVectorSlot = chunk.slotIn(outputIndex, outputDataType); long[] output = outputVectorSlot.cast(LongBlock.class).longArray(); - if (operandsHaveNull) { + if (operandsAllNull) { boolean[] outputNulls = outputVectorSlot.nulls(); - outputVectorSlot.setHasNull(true); - for (int i = 0; i < batchSize; i++) { - outputNulls[i] = true; + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + outputNulls[j] = true; + } + } else { + for (int i = 0; i < batchSize; i++) { + outputNulls[i] = true; + } } return; } + VectorizedExpressionUtils.mergeNulls(chunk, outputIndex, children[0].getOutputIndex()); + RandomAccessBlock leftInputVectorSlot = chunk.slotIn(children[0].getOutputIndex(), children[0].getOutputDataType()); if (leftInputVectorSlot.isInstanceOf(LongBlock.class)) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastNotInVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastNotInVectorizedExpression.java new file mode 100644 index 000000000..d42fdf5a0 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/FastNotInVectorizedExpression.java @@ -0,0 +1,121 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.executor.chunk.IntegerBlock; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.vectorized.AbstractVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InValuesVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpressionUtils; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.google.common.base.Preconditions; + +public class FastNotInVectorizedExpression extends AbstractVectorizedExpression { + + private final InValuesVectorizedExpression.InValueSet inValuesSet; + private final boolean operandsHaveNull; + + public FastNotInVectorizedExpression(DataType dataType, + int outputIndex, + VectorizedExpression[] children) { + super(dataType, outputIndex, children); + Preconditions.checkArgument(children.length == 2, + "Unexpected NOT IN vec expression children length: " + children.length); + Preconditions.checkArgument(children[1] instanceof InValuesVectorizedExpression, + "Unexpected NOT IN values expression type: " + children[1].getClass().getSimpleName()); + InValuesVectorizedExpression inExpr = (InValuesVectorizedExpression) children[1]; + this.operandsHaveNull = inExpr.hasNull(); + this.inValuesSet = inExpr.getInValueSet(); + } + + @Override + public void eval(EvaluationContext ctx) { + children[0].eval(ctx); + MutableChunk chunk = ctx.getPreAllocatedChunk(); + int batchSize = chunk.batchSize(); + boolean isSelectionInUse = chunk.isSelectionInUse(); + int[] sel = chunk.selection(); + RandomAccessBlock outputVectorSlot = chunk.slotIn(outputIndex, outputDataType); + + long[] output = outputVectorSlot.cast(LongBlock.class).longArray(); + if (operandsHaveNull) { + boolean[] outputNulls = outputVectorSlot.nulls(); + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + outputNulls[j] = true; + } + } else { + for (int i = 0; i < batchSize; i++) { + outputNulls[i] = true; + } + } + return; + } + + VectorizedExpressionUtils.mergeNulls(chunk, outputIndex, children[0].getOutputIndex()); + + RandomAccessBlock leftInputVectorSlot = + chunk.slotIn(children[0].getOutputIndex(), children[0].getOutputDataType()); + if (leftInputVectorSlot.isInstanceOf(LongBlock.class)) { + evalLongNotIn(output, leftInputVectorSlot.cast(LongBlock.class), batchSize, isSelectionInUse, sel); + return; + } + + if (leftInputVectorSlot.isInstanceOf(IntegerBlock.class)) { + evalIntNotIn(output, leftInputVectorSlot.cast(IntegerBlock.class), batchSize, isSelectionInUse, sel); + return; + } + + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + output[j] = inValuesSet.contains(leftInputVectorSlot.elementAt(j)) ? + LongBlock.FALSE_VALUE : LongBlock.TRUE_VALUE; + } + } else { + for (int i = 0; i < batchSize; i++) { + output[i] = inValuesSet.contains(leftInputVectorSlot.elementAt(i)) ? + LongBlock.FALSE_VALUE : LongBlock.TRUE_VALUE; + } + } + } + + private void evalIntNotIn(long[] output, IntegerBlock leftInputSlot, + int batchSize, boolean isSelectionInUse, + int[] sel) { + int[] intArray = leftInputSlot.intArray(); + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + output[j] = inValuesSet.contains(intArray[j]) ? + LongBlock.FALSE_VALUE : LongBlock.TRUE_VALUE; + } + } else { + for (int i = 0; i < batchSize; i++) { + output[i] = inValuesSet.contains(intArray[i]) ? + LongBlock.FALSE_VALUE : LongBlock.TRUE_VALUE; + } + } + } + + private void evalLongNotIn(long[] output, LongBlock leftInputSlot, + int batchSize, boolean isSelectionInUse, + int[] sel) { + long[] longArray = leftInputSlot.longArray(); + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + output[j] = inValuesSet.contains(longArray[j]) ? + LongBlock.FALSE_VALUE : LongBlock.TRUE_VALUE; + } + } else { + for (int i = 0; i < batchSize; i++) { + output[i] = inValuesSet.contains(longArray[i]) ? + LongBlock.FALSE_VALUE : LongBlock.TRUE_VALUE; + } + } + } +} \ No newline at end of file diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/LikeType.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/LikeType.java new file mode 100644 index 000000000..767badbdc --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/LikeType.java @@ -0,0 +1,8 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +public enum LikeType { + PREFIX, + SUFFIX, + MIDDLE, + OTHERS +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/LikeVarcharColCharConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/LikeVarcharColCharConstVectorizedExpression.java index c05ad0acb..5d4f981f5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/LikeVarcharColCharConstVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/compare/LikeVarcharColCharConstVectorizedExpression.java @@ -24,6 +24,8 @@ import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; import com.alibaba.polardbx.executor.chunk.ReferenceBlock; import com.alibaba.polardbx.executor.chunk.SliceBlock; +import com.alibaba.polardbx.executor.operator.scan.BlockDictionary; +import com.alibaba.polardbx.executor.operator.scan.impl.LocalBlockDictionary; import com.alibaba.polardbx.executor.vectorized.AbstractVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.EvaluationContext; import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; @@ -33,6 +35,7 @@ import com.alibaba.polardbx.optimizer.config.table.charset.CharsetFactory; import com.alibaba.polardbx.optimizer.config.table.charset.CollationHandlers; import com.alibaba.polardbx.optimizer.config.table.collation.CollationHandler; +import com.alibaba.polardbx.optimizer.config.table.collation.Latin1BinCollationHandler; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.datatype.SliceType; import io.airlift.slice.Slice; @@ -44,16 +47,17 @@ @ExpressionSignatures(names = {"LIKE"}, argumentTypes = {"Varchar", "Char"}, argumentKinds = {Variable, Const}) public class LikeVarcharColCharConstVectorizedExpression extends AbstractVectorizedExpression { private final CollationHandler originCollationHandler; - private final CollationHandler latin1CollationHandler = CollationHandlers.COLLATION_HANDLER_LATIN1_BIN; + private final Latin1BinCollationHandler latin1CollationHandler = + (Latin1BinCollationHandler) CollationHandlers.COLLATION_HANDLER_LATIN1_BIN; private final boolean operand1IsNull; private final Slice operand1; /** * works with ENABLE_OSS_COMPATIBLE=false */ private final boolean canUseLatin1Collation; - private boolean isContainsCompare = false; - private byte[] containBytes = null; - private int[] lps = null; + private LikeType likeType = LikeType.OTHERS; + private byte[] compareBytes = null; + private byte[] dictLikeResult = null; public LikeVarcharColCharConstVectorizedExpression( int outputIndex, @@ -74,59 +78,65 @@ public LikeVarcharColCharConstVectorizedExpression( if (sliceType.isLatin1Encoding()) { canUseLatin1Collation = true; - checkIsContainsCompare(operand1); + checkLikeType(operand1); } else { if (isAsciiEncoding(operand1)) { canUseLatin1Collation = true; - checkIsContainsCompare(operand1); + checkLikeType(operand1); } else { canUseLatin1Collation = false; } } } - public static int[] computeLPSArray(byte[] pattern) { - int[] lps = new int[pattern.length]; - int length = 0; - lps[0] = 0; - int i = 1; - - while (i < pattern.length) { - if (pattern[i] == pattern[length]) { - length++; - lps[i] = length; - i++; - } else { - if (length != 0) { - length = lps[length - 1]; - } else { - lps[i] = length; - i++; - } - } - } - return lps; - } - - private void checkIsContainsCompare(Slice operand) { - if (operand == null || operand.length() < 2) { + /** + * 1. only support fast path for latin_bin collation currently + * 2. only support fast poth for middle, prefix and suffix matching + */ + private void checkLikeType(Slice operand) { + if (operand == null) { return; } if (!canUseLatin1Collation) { + // return; } byte[] bytes = operand.getBytes(); - if (bytes[0] == CollationHandler.WILD_MANY && bytes[bytes.length - 1] == CollationHandler.WILD_MANY) { + if (operand.length() >= 2 && bytes[0] == CollationHandler.WILD_MANY + && bytes[bytes.length - 1] == CollationHandler.WILD_MANY) { for (int i = 1; i < bytes.length - 1; i++) { if (bytes[i] == CollationHandler.WILD_MANY || bytes[i] == CollationHandler.WILD_ONE) { // no % _ in the middle return; } } - this.isContainsCompare = true; - this.containBytes = new byte[operand.length() - 2]; - System.arraycopy(bytes, 1, containBytes, 0, operand.length() - 2); - this.lps = computeLPSArray(containBytes); + this.likeType = LikeType.MIDDLE; + this.compareBytes = new byte[operand.length() - 2]; + System.arraycopy(bytes, 1, compareBytes, 0, operand.length() - 2); + return; + } + if (operand.length() >= 1 && bytes[0] == CollationHandler.WILD_MANY) { + for (int i = 1; i < bytes.length; i++) { + if (bytes[i] == CollationHandler.WILD_MANY || bytes[i] == CollationHandler.WILD_ONE) { + // no % _ after the first one + return; + } + } + this.likeType = LikeType.SUFFIX; + this.compareBytes = new byte[operand.length() - 1]; + System.arraycopy(bytes, 1, compareBytes, 0, operand.length() - 1); + return; + } + if (operand.length() >= 1 && bytes[bytes.length - 1] == CollationHandler.WILD_MANY) { + for (int i = 0; i < bytes.length - 1; i++) { + if (bytes[i] == CollationHandler.WILD_MANY || bytes[i] == CollationHandler.WILD_ONE) { + // no % _ before the last one + return; + } + } + this.likeType = LikeType.PREFIX; + this.compareBytes = new byte[operand.length() - 1]; + System.arraycopy(bytes, 0, compareBytes, 0, operand.length() - 1); } } @@ -187,28 +197,14 @@ public void eval(EvaluationContext ctx) { private void doCollationLike(RandomAccessBlock leftInputVectorSlot, boolean isSelectionInUse, int[] sel, int batchSize, long[] output) { - Slice cachedSlice = new Slice(); if (leftInputVectorSlot instanceof SliceBlock) { SliceBlock sliceBlock = leftInputVectorSlot.cast(SliceBlock.class); - - if (isSelectionInUse) { - for (int i = 0; i < batchSize; i++) { - int j = sel[i]; - - Slice slice = sliceBlock.getRegion(j, cachedSlice); - - output[j] = originCollationHandler.wildCompare(slice, operand1) - ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; - } + if (canUseDictCompare(sliceBlock, batchSize)) { + LocalBlockDictionary dictionary = (LocalBlockDictionary) sliceBlock.getDictionary(); + doCollationLikeDict(sliceBlock, dictionary, isSelectionInUse, sel, batchSize, output); } else { - for (int i = 0; i < batchSize; i++) { - - Slice slice = sliceBlock.getRegion(i, cachedSlice); - - output[i] = originCollationHandler.wildCompare(slice, operand1) - ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; - } + doCollationLikeSlice(sliceBlock, isSelectionInUse, sel, batchSize, output); } } else if (leftInputVectorSlot instanceof ReferenceBlock) { if (isSelectionInUse) { @@ -224,7 +220,6 @@ private void doCollationLike(RandomAccessBlock leftInputVectorSlot, boolean isSe } } else { for (int i = 0; i < batchSize; i++) { - Slice lSlice = ((Slice) leftInputVectorSlot.elementAt(i)); if (lSlice == null) { lSlice = Slices.EMPTY_SLICE; @@ -240,61 +235,249 @@ private void doLatin1Like(RandomAccessBlock leftInputVectorSlot, boolean isSelec int[] sel, int batchSize, long[] output) { if (leftInputVectorSlot instanceof SliceBlock) { SliceBlock sliceBlock = leftInputVectorSlot.cast(SliceBlock.class); - doLatin1LikeSlice(sliceBlock, isSelectionInUse, sel, batchSize, output); + boolean useDictCompare = canUseDictCompare(sliceBlock, batchSize); + if (useDictCompare) { + LocalBlockDictionary dictionary = (LocalBlockDictionary) sliceBlock.getDictionary(); + if (compareBytes != null) { + doLatin1SpecificLikeDict(sliceBlock, dictionary, isSelectionInUse, sel, batchSize, output); + } else { + doLatin1LikeDict(sliceBlock, dictionary, isSelectionInUse, sel, batchSize, output); + } + } else { + if (compareBytes != null) { + doLatin1SpecificLikeSlice(sliceBlock, isSelectionInUse, sel, batchSize, output); + } else { + doLatin1LikeSlice(sliceBlock, isSelectionInUse, sel, batchSize, output); + } + } } else if (leftInputVectorSlot instanceof ReferenceBlock) { - doLatin1LikeReference(leftInputVectorSlot, isSelectionInUse, sel, batchSize, output); + if (compareBytes != null) { + doLatin1SpecificLikeReference(leftInputVectorSlot, isSelectionInUse, sel, batchSize, output); + } else { + doLatin1LikeReference(leftInputVectorSlot, isSelectionInUse, sel, batchSize, output); + } } } - private void doLatin1LikeSlice(SliceBlock sliceBlock, boolean isSelectionInUse, int[] sel, int batchSize, - long[] output) { + private void doCollationLikeSlice(SliceBlock sliceBlock, boolean isSelectionInUse, int[] sel, int batchSize, + long[] output) { Slice cachedSlice = new Slice(); if (isSelectionInUse) { - if (isContainsCompare && containBytes != null) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + + Slice slice = sliceBlock.getRegion(j, cachedSlice); + output[j] = originCollationHandler.wildCompare(slice, operand1) + ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + } else { + for (int i = 0; i < batchSize; i++) { + Slice slice = sliceBlock.getRegion(i, cachedSlice); + output[i] = originCollationHandler.wildCompare(slice, operand1) + ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + } + } + + private void doCollationLikeDict(SliceBlock sliceBlock, LocalBlockDictionary dictionary, boolean isSelectionInUse, + int[] sel, int batchSize, long[] output) { + Slice[] dict = dictionary.getDict(); + byte[] dictLikeResult = getDictResultBuffer(dict.length); + for (int i = 0; i < dict.length; i++) { + // may utilize selection to reduce the comparisons + Slice slice = dict[i]; + dictLikeResult[i] = originCollationHandler.wildCompare(slice, operand1) + ? (byte) 1 : 0; + } + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + int dictId = sliceBlock.getDictId(j); + output[j] = dictId == -1 ? 0 : dictLikeResult[dictId]; + } + } else { + for (int i = 0; i < batchSize; i++) { + int dictId = sliceBlock.getDictId(i); + output[i] = dictId == -1 ? 0 : dictLikeResult[dictId]; + } + } + } + + private void doLatin1SpecificLikeSlice(SliceBlock sliceBlock, boolean isSelectionInUse, int[] sel, int batchSize, + long[] output) { + if (likeType == LikeType.OTHERS) { + // should not reach here + doLatin1LikeSlice(sliceBlock, isSelectionInUse, sel, batchSize, output); + return; + } + + Slice cachedSlice = new Slice(); + if (isSelectionInUse) { + switch (likeType) { + case PREFIX: for (int i = 0; i < batchSize; i++) { int j = sel[i]; - Slice slice = sliceBlock.getRegion(j, cachedSlice); - - output[j] = latin1CollationHandler.containsCompare(slice, containBytes, lps) + output[j] = latin1CollationHandler.startsWith(slice, compareBytes) ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; } - } else { + break; + case SUFFIX: for (int i = 0; i < batchSize; i++) { int j = sel[i]; - Slice slice = sliceBlock.getRegion(j, cachedSlice); - - output[j] = latin1CollationHandler.wildCompare(slice, operand1) + output[j] = latin1CollationHandler.endsWith(slice, compareBytes) ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; } + break; + case MIDDLE: + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + Slice slice = sliceBlock.getRegion(j, cachedSlice); + output[j] = latin1CollationHandler.contains(slice, compareBytes) + ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + break; + default: + throw new UnsupportedOperationException("Unsupported like type: " + likeType); } } else { - if (isContainsCompare && containBytes != null) { + switch (likeType) { + case PREFIX: for (int i = 0; i < batchSize; i++) { - Slice slice = sliceBlock.getRegion(i, cachedSlice); - - output[i] = latin1CollationHandler.containsCompare(slice, containBytes, lps) + output[i] = latin1CollationHandler.startsWith(slice, compareBytes) ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; } - } else { + break; + case SUFFIX: for (int i = 0; i < batchSize; i++) { - Slice slice = sliceBlock.getRegion(i, cachedSlice); - - output[i] = latin1CollationHandler.wildCompare(slice, operand1) + output[i] = latin1CollationHandler.endsWith(slice, compareBytes) ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; } + break; + case MIDDLE: + for (int i = 0; i < batchSize; i++) { + Slice slice = sliceBlock.getRegion(i, cachedSlice); + output[i] = latin1CollationHandler.contains(slice, compareBytes) + ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + break; + default: + throw new UnsupportedOperationException("Unsupported like type: " + likeType); } } } - private void doLatin1LikeReference(RandomAccessBlock leftInputVectorSlot, boolean isSelectionInUse, int[] sel, - int batchSize, long[] output) { + /** + * @param dictionary already checked not null and low cardinality, + * should be local dictionary but not global + */ + private void doLatin1SpecificLikeDict(SliceBlock sliceBlock, LocalBlockDictionary dictionary, + boolean isSelectionInUse, int[] sel, + int batchSize, long[] output) { + if (likeType == LikeType.OTHERS) { + // should not reach here + doLatin1LikeDict(sliceBlock, dictionary, isSelectionInUse, sel, batchSize, output); + return; + } + + Slice[] dict = dictionary.getDict(); + byte[] dictLikeResult = getDictResultBuffer(dict.length); + for (int i = 0; i < dict.length; i++) { + // may utilize selection to reduce the comparisons + Slice slice = dict[i]; + switch (likeType) { + case PREFIX: + dictLikeResult[i] = latin1CollationHandler.startsWith(slice, compareBytes) + ? (byte) 1 : 0; + break; + case SUFFIX: + dictLikeResult[i] = latin1CollationHandler.endsWith(slice, compareBytes) + ? (byte) 1 : 0; + break; + case MIDDLE: + dictLikeResult[i] = latin1CollationHandler.contains(slice, compareBytes) + ? (byte) 1 : 0; + break; + default: + throw new UnsupportedOperationException("Unsupported like type: " + likeType); + } + } + + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + int dictId = sliceBlock.getDictId(j); + output[j] = dictId == -1 ? 0 : dictLikeResult[dictId]; + } + } else { + for (int i = 0; i < batchSize; i++) { + int dictId = sliceBlock.getDictId(i); + output[i] = dictId == -1 ? 0 : dictLikeResult[dictId]; + } + } + } + + private void doLatin1LikeDict(SliceBlock sliceBlock, LocalBlockDictionary dictionary, + boolean isSelectionInUse, int[] sel, + int batchSize, long[] output) { + Slice[] dict = dictionary.getDict(); + byte[] dictLikeResult = getDictResultBuffer(dict.length); + for (int i = 0; i < dict.length; i++) { + // may utilize selection to reduce the comparisons + Slice slice = dict[i]; + dictLikeResult[i] = latin1CollationHandler.wildCompare(slice, operand1) + ? (byte) 1 : 0; + } + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + int dictId = sliceBlock.getDictId(j); + output[j] = dictId == -1 ? 0 : dictLikeResult[dictId]; + } + } else { + for (int i = 0; i < batchSize; i++) { + int dictId = sliceBlock.getDictId(i); + output[i] = dictId == -1 ? 0 : dictLikeResult[dictId]; + } + } + } + + private void doLatin1LikeSlice(SliceBlock sliceBlock, boolean isSelectionInUse, int[] sel, int batchSize, + long[] output) { + Slice cachedSlice = new Slice(); + + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + Slice slice = sliceBlock.getRegion(j, cachedSlice); + output[j] = latin1CollationHandler.wildCompare(slice, operand1) + ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + } else { + for (int i = 0; i < batchSize; i++) { + Slice slice = sliceBlock.getRegion(i, cachedSlice); + output[i] = latin1CollationHandler.wildCompare(slice, operand1) + ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + } + } + + private void doLatin1SpecificLikeReference(RandomAccessBlock leftInputVectorSlot, boolean isSelectionInUse, + int[] sel, + int batchSize, long[] output) { + if (likeType == LikeType.OTHERS) { + // should not reach here + doLatin1LikeReference(leftInputVectorSlot, isSelectionInUse, sel, batchSize, output); + return; + } + if (isSelectionInUse) { - if (isContainsCompare && containBytes != null) { + switch (likeType) { + case PREFIX: for (int i = 0; i < batchSize; i++) { int j = sel[i]; @@ -302,10 +485,11 @@ private void doLatin1LikeReference(RandomAccessBlock leftInputVectorSlot, boolea if (lSlice == null) { lSlice = Slices.EMPTY_SLICE; } - output[j] = latin1CollationHandler.containsCompare(lSlice, containBytes, lps) + output[j] = latin1CollationHandler.startsWith(lSlice, compareBytes) ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; } - } else { + break; + case SUFFIX: for (int i = 0; i < batchSize; i++) { int j = sel[i]; @@ -313,32 +497,109 @@ private void doLatin1LikeReference(RandomAccessBlock leftInputVectorSlot, boolea if (lSlice == null) { lSlice = Slices.EMPTY_SLICE; } - output[j] = latin1CollationHandler.wildCompare(lSlice, operand1) + output[j] = latin1CollationHandler.endsWith(lSlice, compareBytes) ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; } + break; + case MIDDLE: + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + + Slice lSlice = ((Slice) leftInputVectorSlot.elementAt(j)); + if (lSlice == null) { + lSlice = Slices.EMPTY_SLICE; + } + output[j] = latin1CollationHandler.contains(lSlice, compareBytes) + ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + break; + default: + throw new UnsupportedOperationException("Unsupported like type: " + likeType); } } else { - if (isContainsCompare && containBytes != null) { + switch (likeType) { + case PREFIX: for (int i = 0; i < batchSize; i++) { - Slice lSlice = ((Slice) leftInputVectorSlot.elementAt(i)); if (lSlice == null) { lSlice = Slices.EMPTY_SLICE; } - output[i] = latin1CollationHandler.containsCompare(lSlice, containBytes, lps) + output[i] = latin1CollationHandler.startsWith(lSlice, compareBytes) ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; } - } else { + break; + case SUFFIX: for (int i = 0; i < batchSize; i++) { - Slice lSlice = ((Slice) leftInputVectorSlot.elementAt(i)); if (lSlice == null) { lSlice = Slices.EMPTY_SLICE; } - output[i] = latin1CollationHandler.wildCompare(lSlice, operand1) + output[i] = latin1CollationHandler.endsWith(lSlice, compareBytes) ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; } + break; + case MIDDLE: + for (int i = 0; i < batchSize; i++) { + Slice lSlice = ((Slice) leftInputVectorSlot.elementAt(i)); + if (lSlice == null) { + lSlice = Slices.EMPTY_SLICE; + } + output[i] = latin1CollationHandler.contains(lSlice, compareBytes) + ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + break; + default: + throw new UnsupportedOperationException("Unsupported like type: " + likeType); } } } + + private void doLatin1LikeReference(RandomAccessBlock leftInputVectorSlot, boolean isSelectionInUse, int[] sel, + int batchSize, long[] output) { + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + + Slice lSlice = ((Slice) leftInputVectorSlot.elementAt(j)); + if (lSlice == null) { + lSlice = Slices.EMPTY_SLICE; + } + output[j] = latin1CollationHandler.wildCompare(lSlice, operand1) + ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + } else { + for (int i = 0; i < batchSize; i++) { + + Slice lSlice = ((Slice) leftInputVectorSlot.elementAt(i)); + if (lSlice == null) { + lSlice = Slices.EMPTY_SLICE; + } + output[i] = latin1CollationHandler.wildCompare(lSlice, operand1) + ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + } + } + + /** + * 1. has dictionary which is local + * 2. the size of dictionary is small + */ + private boolean canUseDictCompare(SliceBlock sliceBlock, int batchSize) { + BlockDictionary dictionary = sliceBlock.getDictionary(); + if (!(dictionary instanceof LocalBlockDictionary)) { + return false; + } + int dictSize = dictionary.size(); + + return dictSize <= (batchSize / 2); + } + + private byte[] getDictResultBuffer(int length) { + if (this.dictLikeResult == null || this.dictLikeResult.length < length) { + this.dictLikeResult = new byte[length]; + return this.dictLikeResult; + } + return this.dictLikeResult; + } + } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/convert/CastLongConstToDecimalVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/convert/CastLongConstToDecimalVectorizedExpression.java index f23617c34..93efe5e09 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/convert/CastLongConstToDecimalVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/convert/CastLongConstToDecimalVectorizedExpression.java @@ -23,8 +23,6 @@ import com.alibaba.polardbx.common.utils.MathUtils; import com.alibaba.polardbx.executor.chunk.DecimalBlock; import com.alibaba.polardbx.executor.chunk.MutableChunk; -import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; -import com.alibaba.polardbx.executor.chunk.ULongBlock; import com.alibaba.polardbx.executor.vectorized.AbstractVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.EvaluationContext; import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; @@ -124,6 +122,7 @@ private void castOperandToNormalDecimal(DecimalBlock outputVectorSlot, int batch int[] sel) { Slice output = (outputVectorSlot.cast(DecimalBlock.class)).getMemorySegments(); DecimalStructure tmpDecimal = new DecimalStructure(); + tmpDecimal.reset(); int precision = outputDataType.getPrecision(); int scale = outputDataType.getScale(); DecimalConverter.rescale(operand1.getDecimalStructure(), tmpDecimal, precision, scale, false); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/logical/FastAndLongColLongColVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/logical/FastAndLongColLongColVectorizedExpression.java new file mode 100644 index 000000000..199fc50c3 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/logical/FastAndLongColLongColVectorizedExpression.java @@ -0,0 +1,224 @@ +package com.alibaba.polardbx.executor.vectorized.logical; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.vectorized.AbstractVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.metadata.ExpressionSignatures; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; + +import static com.alibaba.polardbx.executor.vectorized.metadata.ArgumentKind.Variable; +import static com.alibaba.polardbx.executor.vectorized.metadata.ExpressionPriority.SPECIAL; + +@SuppressWarnings("unused") +@ExpressionSignatures( + names = {"AND"}, + argumentTypes = {"Long", "Long"}, + argumentKinds = {Variable, Variable}, + priority = SPECIAL +) +public class FastAndLongColLongColVectorizedExpression extends AbstractVectorizedExpression { + + private int[] tmpSelectionBuffer = null; + + public FastAndLongColLongColVectorizedExpression(int outputIndex, VectorizedExpression[] children) { + super(DataTypes.LongType, outputIndex, children); + if (children.length != 2) { + throw new IllegalArgumentException("AND expression should have 2 children"); + } + } + + @Override + public void eval(EvaluationContext ctx) { + final boolean enableShortCircuit = + ctx.getExecutionContext().getParamManager().getBoolean(ConnectionParams.ENABLE_AND_FAST_VEC); + + if (!enableShortCircuit) { + doAndEval(ctx); + return; + } + + doAndEvalWithShortCircuit(ctx); + } + + private void doAndEvalWithShortCircuit(EvaluationContext ctx) { + // evaluate left expression first + children[0].eval(ctx); + + MutableChunk chunk = ctx.getPreAllocatedChunk(); + RandomAccessBlock outputVectorSlot = chunk.slotIn(outputIndex, outputDataType); + int batchSize = chunk.batchSize(); + boolean outputVectorHasNull = false; + boolean isSelectionInUse = chunk.isSelectionInUse(); + int[] sel = chunk.selection(); + + long[] res = (outputVectorSlot.cast(LongBlock.class)).longArray(); + boolean[] outputNulls = outputVectorSlot.nulls(); + + RandomAccessBlock inputVec1 = chunk.slotIn(children[0].getOutputIndex(), children[0].getOutputDataType()); + long[] leftResults = (inputVec1.cast(LongBlock.class)).longArray(); + boolean[] nulls1 = inputVec1.nulls(); + boolean input1HasNull = inputVec1.hasNull(); + + // cannot reuse the origin selection inside the chunk + int tmpSelSize = 0; + int[] tmpSel = getSelectionBuffer(leftResults.length); + if (isSelectionInUse) { + // merge selection array + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + // select when left result is true + if (leftResults[j] != LongBlock.FALSE_VALUE) { + tmpSel[tmpSelSize++] = j; + } + } + } else { + for (int i = 0; i < batchSize; i++) { + // select when left result is true + if (leftResults[i] != LongBlock.FALSE_VALUE) { + tmpSel[tmpSelSize++] = i; + } + } + } + chunk.setSelection(tmpSel); + chunk.setSelectionInUse(true); + chunk.setBatchSize(tmpSelSize); + + // pass selection to right expression + children[1].eval(ctx); + + // restore origin selection + chunk.setSelection(sel); + chunk.setSelectionInUse(isSelectionInUse); + chunk.setBatchSize(batchSize); + + RandomAccessBlock inputVec2 = chunk.slotIn(children[1].getOutputIndex(), children[1].getOutputDataType()); + long[] rightResults = (inputVec2.cast(LongBlock.class)).longArray(); + boolean[] nulls2 = inputVec2.nulls(); + boolean input2HasNull = inputVec2.hasNull(); + + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + + boolean null1 = input1HasNull && nulls1[j]; + boolean null2 = input2HasNull && nulls2[j]; + + boolean b1 = (leftResults[j] != 0); + boolean b2 = (rightResults[j] != 0); + + boolean hasNull = null1; + hasNull |= null2; + + boolean anyFalse = (!null1 && !b1); + anyFalse |= (!null2 && !b2); + + outputNulls[j] = !anyFalse && hasNull; + res[j] = !anyFalse && !hasNull ? 1 : 0; + + outputVectorHasNull |= outputNulls[j]; + } + } else { + for (int i = 0; i < batchSize; i++) { + boolean null1 = input1HasNull && nulls1[i]; + boolean null2 = input2HasNull && nulls2[i]; + + boolean b1 = (leftResults[i] != 0); + boolean b2 = (rightResults[i] != 0); + + boolean hasNull = null1; + hasNull |= null2; + + boolean anyFalse = (!null1 && !b1); + anyFalse |= (!null2 && !b2); + + outputNulls[i] = !anyFalse && hasNull; + res[i] = !anyFalse && !hasNull ? 1 : 0; + + outputVectorHasNull |= outputNulls[i]; + } + } + + outputVectorSlot.setHasNull(outputVectorHasNull); + } + + private int[] getSelectionBuffer(int length) { + if (this.tmpSelectionBuffer == null || this.tmpSelectionBuffer.length < length) { + this.tmpSelectionBuffer = new int[length]; + } + return this.tmpSelectionBuffer; + } + + private void doAndEval(EvaluationContext ctx) { + super.evalChildren(ctx); + MutableChunk chunk = ctx.getPreAllocatedChunk(); + int batchSize = chunk.batchSize(); + boolean isSelectionInUse = chunk.isSelectionInUse(); + int[] sel = chunk.selection(); + + RandomAccessBlock outputVectorSlot = chunk.slotIn(outputIndex, outputDataType); + RandomAccessBlock inputVec1 = chunk.slotIn(children[0].getOutputIndex(), children[0].getOutputDataType()); + RandomAccessBlock inputVec2 = chunk.slotIn(children[1].getOutputIndex(), children[1].getOutputDataType()); + + long[] array1 = (inputVec1.cast(LongBlock.class)).longArray(); + boolean[] nulls1 = inputVec1.nulls(); + boolean input1HasNull = inputVec1.hasNull(); + + long[] array2 = (inputVec2.cast(LongBlock.class)).longArray(); + boolean[] nulls2 = inputVec2.nulls(); + boolean input2HasNull = inputVec2.hasNull(); + + long[] res = (outputVectorSlot.cast(LongBlock.class)).longArray(); + boolean[] outputNulls = outputVectorSlot.nulls(); + + boolean outputVectorHasNull = false; + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + + boolean null1 = input1HasNull && nulls1[j]; + boolean null2 = input2HasNull && nulls2[j]; + + boolean b1 = (array1[j] != 0); + boolean b2 = (array2[j] != 0); + + boolean hasNull = null1; + hasNull |= null2; + + boolean anyFalse = (!null1 && !b1); + anyFalse |= (!null2 && !b2); + + outputNulls[j] = !anyFalse && hasNull; + res[j] = !anyFalse && !hasNull ? 1 : 0; + + outputVectorHasNull |= outputNulls[j]; + } + } else { + for (int i = 0; i < batchSize; i++) { + boolean null1 = input1HasNull && nulls1[i]; + boolean null2 = input2HasNull && nulls2[i]; + + boolean b1 = (array1[i] != 0); + boolean b2 = (array2[i] != 0); + + boolean hasNull = null1; + hasNull |= null2; + + boolean anyFalse = (!null1 && !b1); + anyFalse |= (!null2 && !b2); + + outputNulls[i] = !anyFalse && hasNull; + res[i] = !anyFalse && !hasNull ? 1 : 0; + + outputVectorHasNull |= outputNulls[i]; + } + } + + outputVectorSlot.setHasNull(outputVectorHasNull); + } +} + + diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/logical/FastOrLongColLongColVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/logical/FastOrLongColLongColVectorizedExpression.java new file mode 100644 index 000000000..d358420d8 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/logical/FastOrLongColLongColVectorizedExpression.java @@ -0,0 +1,222 @@ +package com.alibaba.polardbx.executor.vectorized.logical; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.vectorized.AbstractVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.metadata.ExpressionSignatures; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; + +import static com.alibaba.polardbx.executor.vectorized.metadata.ArgumentKind.Variable; +import static com.alibaba.polardbx.executor.vectorized.metadata.ExpressionPriority.SPECIAL; + +@SuppressWarnings("unused") +@ExpressionSignatures( + names = {"OR"}, + argumentTypes = {"Long", "Long"}, + argumentKinds = {Variable, Variable}, + priority = SPECIAL +) +public class FastOrLongColLongColVectorizedExpression extends AbstractVectorizedExpression { + + private int[] tmpSelectionBuffer = null; + + public FastOrLongColLongColVectorizedExpression(int outputIndex, VectorizedExpression[] children) { + super(DataTypes.LongType, outputIndex, children); + if (children.length != 2) { + throw new IllegalArgumentException("OR expression should have 2 children"); + } + } + + @Override + public void eval(EvaluationContext ctx) { + final boolean enableShortCircuit = + ctx.getExecutionContext().getParamManager().getBoolean(ConnectionParams.ENABLE_OR_FAST_VEC); + + if (!enableShortCircuit) { + doOrEval(ctx); + return; + } + + doOrEvalWithShortCircuit(ctx); + } + + private void doOrEvalWithShortCircuit(EvaluationContext ctx) { + // evaluate left expression first + children[0].eval(ctx); + + MutableChunk chunk = ctx.getPreAllocatedChunk(); + RandomAccessBlock outputVectorSlot = chunk.slotIn(outputIndex, outputDataType); + int batchSize = chunk.batchSize(); + boolean outputVectorHasNull = false; + boolean isSelectionInUse = chunk.isSelectionInUse(); + int[] sel = chunk.selection(); + + long[] res = (outputVectorSlot.cast(LongBlock.class)).longArray(); + boolean[] outputNulls = outputVectorSlot.nulls(); + + RandomAccessBlock inputVec1 = chunk.slotIn(children[0].getOutputIndex(), children[0].getOutputDataType()); + long[] leftResults = (inputVec1.cast(LongBlock.class)).longArray(); + boolean[] nulls1 = inputVec1.nulls(); + boolean input1HasNull = inputVec1.hasNull(); + + // cannot reuse the origin selection inside the chunk + int tmpSelSize = 0; + int[] tmpSel = getSelectionBuffer(leftResults.length); + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + // select when left result is false + if (leftResults[j] == LongBlock.FALSE_VALUE) { + tmpSel[tmpSelSize++] = j; + } + } + } else { + for (int i = 0; i < batchSize; i++) { + // select when left result is false + if (leftResults[i] == LongBlock.FALSE_VALUE) { + tmpSel[tmpSelSize++] = i; + } + } + } + chunk.setSelection(tmpSel); + chunk.setSelectionInUse(true); + chunk.setBatchSize(tmpSelSize); + + // pass tmp selection to right expression + children[1].eval(ctx); + + // restore origin selection + chunk.setSelection(sel); + chunk.setSelectionInUse(isSelectionInUse); + chunk.setBatchSize(batchSize); + + RandomAccessBlock inputVec2 = chunk.slotIn(children[1].getOutputIndex(), children[1].getOutputDataType()); + long[] rightResults = (inputVec2.cast(LongBlock.class)).longArray(); + boolean[] nulls2 = inputVec2.nulls(); + boolean input2HasNull = inputVec2.hasNull(); + + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + + boolean null1 = input1HasNull && nulls1[j]; + boolean null2 = input2HasNull && nulls2[j]; + + boolean b1 = (leftResults[j] != 0); + boolean b2 = (rightResults[j] != 0); + + boolean hasNull = null1; + hasNull |= null2; + + boolean anyTrue = b1 && !null1; + anyTrue |= (b2 && !null2); + + outputNulls[j] = !anyTrue && hasNull; + res[j] = anyTrue ? 1 : 0; + + outputVectorHasNull |= outputNulls[j]; + } + } else { + for (int i = 0; i < batchSize; i++) { + boolean null1 = input1HasNull && nulls1[i]; + boolean null2 = input2HasNull && nulls2[i]; + + boolean b1 = (leftResults[i] != 0); + boolean b2 = (rightResults[i] != 0); + + boolean hasNull = null1; + hasNull |= null2; + + boolean anyTrue = b1 && !null1; + anyTrue |= (b2 && !null2); + + outputNulls[i] = !anyTrue && hasNull; + res[i] = anyTrue ? 1 : 0; + + outputVectorHasNull |= outputNulls[i]; + } + } + outputVectorSlot.setHasNull(outputVectorHasNull); + } + + private int[] getSelectionBuffer(int length) { + if (this.tmpSelectionBuffer == null || this.tmpSelectionBuffer.length < length) { + this.tmpSelectionBuffer = new int[length]; + } + return this.tmpSelectionBuffer; + } + + private void doOrEval(EvaluationContext ctx) { + super.evalChildren(ctx); + MutableChunk chunk = ctx.getPreAllocatedChunk(); + int batchSize = chunk.batchSize(); + boolean isSelectionInUse = chunk.isSelectionInUse(); + int[] sel = chunk.selection(); + + RandomAccessBlock outputVectorSlot = chunk.slotIn(outputIndex, outputDataType); + RandomAccessBlock inputVec1 = chunk.slotIn(children[0].getOutputIndex(), children[0].getOutputDataType()); + RandomAccessBlock inputVec2 = chunk.slotIn(children[1].getOutputIndex(), children[1].getOutputDataType()); + + long[] array1 = (inputVec1.cast(LongBlock.class)).longArray(); + boolean[] nulls1 = inputVec1.nulls(); + boolean input1HasNull = inputVec1.hasNull(); + + long[] array2 = (inputVec2.cast(LongBlock.class)).longArray(); + boolean[] nulls2 = inputVec2.nulls(); + boolean input2HasNull = inputVec2.hasNull(); + + long[] res = (outputVectorSlot.cast(LongBlock.class)).longArray(); + boolean[] outputNulls = outputVectorSlot.nulls(); + + boolean outputVectorHasNull = false; + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + + boolean null1 = input1HasNull && nulls1[j]; + boolean null2 = input2HasNull && nulls2[j]; + + boolean b1 = (array1[j] != 0); + boolean b2 = (array2[j] != 0); + + boolean hasNull = null1; + hasNull |= null2; + + boolean anyTrue = b1 && !null1; + anyTrue |= (b2 && !null2); + + outputNulls[j] = !anyTrue && hasNull; + res[j] = anyTrue ? 1 : 0; + + outputVectorHasNull |= outputNulls[j]; + } + } else { + for (int i = 0; i < batchSize; i++) { + boolean null1 = input1HasNull && nulls1[i]; + boolean null2 = input2HasNull && nulls2[i]; + + boolean b1 = (array1[i] != 0); + boolean b2 = (array2[i] != 0); + + boolean hasNull = null1; + hasNull |= null2; + + boolean anyTrue = b1 && !null1; + anyTrue |= (b2 && !null2); + + outputNulls[i] = !anyTrue && hasNull; + res[i] = anyTrue ? 1 : 0; + + outputVectorHasNull |= outputNulls[i]; + } + } + + outputVectorSlot.setHasNull(outputVectorHasNull); + } +} + + diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/math/FastBetweenDecimalColLongConstLongConstVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/math/FastBetweenDecimalColLongConstLongConstVectorizedExpression.java index dcfdf5856..32d593602 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/math/FastBetweenDecimalColLongConstLongConstVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/math/FastBetweenDecimalColLongConstLongConstVectorizedExpression.java @@ -17,11 +17,9 @@ package com.alibaba.polardbx.executor.vectorized.math; import com.alibaba.polardbx.common.datatype.Decimal; -import com.alibaba.polardbx.common.datatype.DecimalConverter; import com.alibaba.polardbx.common.datatype.DecimalStructure; import com.alibaba.polardbx.common.datatype.DecimalTypeBase; import com.alibaba.polardbx.common.datatype.FastDecimalUtils; -import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.MathUtils; import com.alibaba.polardbx.executor.chunk.DecimalBlock; import com.alibaba.polardbx.executor.chunk.LongBlock; @@ -36,9 +34,6 @@ import com.alibaba.polardbx.executor.vectorized.metadata.ExpressionSignatures; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; -import java.util.Arrays; - -import static com.alibaba.polardbx.common.datatype.DecimalTypeBase.DECIMAL_MEMORY_SIZE; import static com.alibaba.polardbx.executor.vectorized.metadata.ArgumentKind.Const; import static com.alibaba.polardbx.executor.vectorized.metadata.ArgumentKind.Variable; @@ -77,16 +72,16 @@ public FastBetweenDecimalColLongConstLongConstVectorizedExpression(int outputInd if (left == 0) { operand1WithScale = 0; useOperand1WithScale = true; - return; - } - int scale = children[0].getOutputDataType().getScale(); - if (scale < 0 || scale >= DecimalTypeBase.POW_10.length) { - operand1WithScale = 0; - useOperand1WithScale = false; } else { - long power = DecimalTypeBase.POW_10[scale]; - operand1WithScale = left * power; - useOperand1WithScale = !MathUtils.longMultiplyOverflow(left, power, operand1WithScale); + int scale = children[0].getOutputDataType().getScale(); + if (scale < 0 || scale >= DecimalTypeBase.POW_10.length) { + operand1WithScale = 0; + useOperand1WithScale = false; + } else { + long power = DecimalTypeBase.POW_10[scale]; + operand1WithScale = left * power; + useOperand1WithScale = !MathUtils.longMultiplyOverflow(left, power, operand1WithScale); + } } } @@ -103,16 +98,16 @@ public FastBetweenDecimalColLongConstLongConstVectorizedExpression(int outputInd if (right == 0) { operand2WithScale = 0; useOperand2WithScale = true; - return; - } - int scale = children[0].getOutputDataType().getScale(); - if (scale < 0 || scale >= DecimalTypeBase.POW_10.length) { - operand2WithScale = 0; - useOperand2WithScale = false; } else { - long power = DecimalTypeBase.POW_10[scale]; - operand2WithScale = right * power; - useOperand2WithScale = !MathUtils.longMultiplyOverflow(right, power, operand2WithScale); + int scale = children[0].getOutputDataType().getScale(); + if (scale < 0 || scale >= DecimalTypeBase.POW_10.length) { + operand2WithScale = 0; + useOperand2WithScale = false; + } else { + long power = DecimalTypeBase.POW_10[scale]; + operand2WithScale = right * power; + useOperand2WithScale = !MathUtils.longMultiplyOverflow(right, power, operand2WithScale); + } } } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalColIntegerColVectorizedExpression.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalColIntegerColVectorizedExpression.java index 3c3efe3b3..dcb7effb4 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalColIntegerColVectorizedExpression.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalColIntegerColVectorizedExpression.java @@ -95,7 +95,12 @@ public void eval(EvaluationContext ctx) { } } - doNormalMul(batchSize, isSelectionInUse, sel, leftInputVectorSlot, rightInputVectorSlot, outputVectorSlot); + if (!isRightUnsigned) { + doNormalMul(batchSize, isSelectionInUse, sel, leftInputVectorSlot, rightInputVectorSlot, outputVectorSlot); + } else { + doNormalMulUnsigned(batchSize, isSelectionInUse, sel, leftInputVectorSlot, rightInputVectorSlot, + outputVectorSlot); + } } private boolean checkResultScale(int scale, int outputVectorSlotScale) { @@ -232,13 +237,13 @@ private void mul64To128(int batchSize, long[] leftArray, int[] rightArray, long[ } if (decimal64 == 1) { outputDecimal128Low[i] = multiplier; - outputDecimal128High[i] = multiplier >= 0 ? 0 : 1; + outputDecimal128High[i] = multiplier >= 0 ? 0 : -1; continue; } if (decimal64 == -1) { long negMultiplier = -((long) multiplier); outputDecimal128Low[i] = negMultiplier; - outputDecimal128High[i] = negMultiplier >= 0 ? 0 : 1; + outputDecimal128High[i] = negMultiplier >= 0 ? 0 : -1; continue; } if (multiplier == 1) { @@ -302,13 +307,13 @@ private void mul64To128(int batchSize, int[] sel, long[] leftArray, int[] rightA } if (decimal64 == 1) { outputDecimal128Low[j] = multiplier; - outputDecimal128High[j] = multiplier >= 0 ? 0 : 1; + outputDecimal128High[j] = multiplier >= 0 ? 0 : -1; continue; } if (decimal64 == -1) { long negMultiplier = -((long) multiplier); outputDecimal128Low[j] = negMultiplier; - outputDecimal128High[j] = negMultiplier >= 0 ? 0 : 1; + outputDecimal128High[j] = negMultiplier >= 0 ? 0 : -1; continue; } if (multiplier == 1) { @@ -358,7 +363,7 @@ private void mul64UnsignedTo128(int batchSize, long[] leftArray, int[] rightArra long[] outputDecimal128High) { for (int i = 0; i < batchSize; i++) { long decimal64 = leftArray[i]; - int multiplier = rightArray[i]; + long multiplier = rightArray[i] & 0xFFFFFFFFL; if (decimal64 == 0 || multiplier == 0) { outputDecimal128Low[i] = 0; @@ -367,13 +372,13 @@ private void mul64UnsignedTo128(int batchSize, long[] leftArray, int[] rightArra } if (decimal64 == 1) { outputDecimal128Low[i] = multiplier; - outputDecimal128High[i] = multiplier >= 0 ? 0 : 1; + outputDecimal128High[i] = multiplier >= 0 ? 0 : -1; continue; } if (decimal64 == -1) { long negMultiplier = -((long) multiplier); outputDecimal128Low[i] = negMultiplier; - outputDecimal128High[i] = negMultiplier >= 0 ? 0 : 1; + outputDecimal128High[i] = negMultiplier >= 0 ? 0 : -1; continue; } if (multiplier == 1) { @@ -426,13 +431,13 @@ private void mul64UnsignedTo128(int batchSize, int[] sel, long[] leftArray, int[ } if (decimal64 == 1) { outputDecimal128Low[j] = multiplier; - outputDecimal128High[j] = multiplier >= 0 ? 0 : 1; + outputDecimal128High[j] = multiplier >= 0 ? 0 : -1; continue; } if (decimal64 == -1) { long negMultiplier = -((long) multiplier); outputDecimal128Low[j] = negMultiplier; - outputDecimal128High[j] = negMultiplier >= 0 ? 0 : 1; + outputDecimal128High[j] = negMultiplier >= 0 ? 0 : -1; continue; } if (multiplier == 1) { @@ -610,7 +615,7 @@ private boolean mul128To128(int batchSize, int[] sel, long[] leftDecimal128Low, if (multiplier == 1) { outputDecimal128Low[j] = decimal128Low; outputDecimal128High[j] = decimal128High; - return true; + continue; } if (multiplier == -1) { outputDecimal128Low[j] = ~decimal128Low + 1; @@ -618,7 +623,7 @@ private boolean mul128To128(int batchSize, int[] sel, long[] leftDecimal128Low, if (outputDecimal128Low[j] == 0) { outputDecimal128High[j] += 1; } - return true; + continue; } boolean positive; @@ -807,7 +812,63 @@ private void doNormalMul(int batchSize, boolean isSelectionInUse, int[] sel, Dec leftDec = new DecimalStructure((leftInputVectorSlot).getRegion(j, cachedSlice)); // fetch right decimal value - DecimalConverter.longToDecimal(array2[j], rightDec, isRightUnsigned); + DecimalConverter.longToDecimal(array2[j], rightDec); + + // do operator + FastDecimalUtils.mul(leftDec, rightDec, toValue); + } + } else { + for (int i = 0; i < batchSize; i++) { + int fromIndex = i * DECIMAL_MEMORY_SIZE; + + // wrap memory in specified position + Slice decimalMemorySegment = output.slice(fromIndex, DECIMAL_MEMORY_SIZE); + DecimalStructure toValue = new DecimalStructure(decimalMemorySegment); + + // do reset + rightDec.reset(); + + // fetch left decimal value + leftDec = new DecimalStructure((leftInputVectorSlot).getRegion(i, cachedSlice)); + + // fetch right decimal value + DecimalConverter.longToDecimal(array2[i], rightDec); + + // do operator + FastDecimalUtils.mul(leftDec, rightDec, toValue); + } + } + outputVectorSlot.setFullState(); + } + + private void doNormalMulUnsigned(int batchSize, boolean isSelectionInUse, int[] sel, + DecimalBlock leftInputVectorSlot, + IntegerBlock rightInputVectorSlot, DecimalBlock outputVectorSlot) { + DecimalStructure leftDec; + DecimalStructure rightDec = new DecimalStructure(); + // use cached slice + Slice cachedSlice = leftInputVectorSlot.allocCachedSlice(); + + int[] array2 = rightInputVectorSlot.intArray(); + Slice output = outputVectorSlot.getMemorySegments(); + + if (isSelectionInUse) { + for (int i = 0; i < batchSize; i++) { + int j = sel[i]; + int fromIndex = j * DECIMAL_MEMORY_SIZE; + + // wrap memory in specified position + Slice decimalMemorySegment = output.slice(fromIndex, DECIMAL_MEMORY_SIZE); + DecimalStructure toValue = new DecimalStructure(decimalMemorySegment); + + // do reset + rightDec.reset(); + + // fetch left decimal value + leftDec = new DecimalStructure((leftInputVectorSlot).getRegion(j, cachedSlice)); + + // fetch right decimal value + DecimalConverter.longToDecimal(array2[j] & 0xFFFFFFFFL, rightDec); // do operator FastDecimalUtils.mul(leftDec, rightDec, toValue); @@ -827,7 +888,7 @@ private void doNormalMul(int batchSize, boolean isSelectionInUse, int[] sel, Dec leftDec = new DecimalStructure((leftInputVectorSlot).getRegion(i, cachedSlice)); // fetch right decimal value - DecimalConverter.longToDecimal(array2[i], rightDec, isRightUnsigned); + DecimalConverter.longToDecimal(array2[i] & 0xFFFFFFFFL, rightDec); // do operator FastDecimalUtils.mul(leftDec, rightDec, toValue); diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/metadata/Rex2ArgumentInfo.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/metadata/Rex2ArgumentInfo.java index 068de9dac..3d0643654 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/metadata/Rex2ArgumentInfo.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/executor/vectorized/metadata/Rex2ArgumentInfo.java @@ -58,7 +58,7 @@ private static DataType convertStructDataType(RelDataType relDataType) { .map(t -> (DataType) t) .collect(Collectors.toSet()); - if (dataTypes.size() > 1) { + if (dataTypes.size() != 1) { // struct type return null; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/group/config/OptimizedGroupConfigManager.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/group/config/OptimizedGroupConfigManager.java index ee30cb948..ed32b3a8b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/group/config/OptimizedGroupConfigManager.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/group/config/OptimizedGroupConfigManager.java @@ -411,7 +411,7 @@ protected synchronized void unregisterHaSwitcher() { } } - protected void unbindGroupConfigListener() { + public void unbindGroupConfigListener() { String dbName = groupDataSource.getSchemaName(); String groupName = groupDataSource.getDbGroupKey(); @@ -424,6 +424,8 @@ protected void unbindGroupConfigListener() { } } + + protected synchronized List switchGroupDs(HaSwitchParams haSwitchParams) { String userName = haSwitchParams.userName; @@ -720,39 +722,38 @@ private synchronized void resetByPolarDBXDataSourceWrapper(List slaveDataSources = new ArrayList(); + boolean notAllowFailedSlave = + !ConfigDataMode.isMasterMode() && !SystemDbHelper.isDBBuildIn(groupDataSource.getSchemaName()); - for (DataSourceWrapper dataSourceWrapper : dataSourceWrapperMap.values()) { - if (dataSourceWrapper.hasWriteWeight()) { - masterDataSource = dataSourceWrapper.getWrappedDataSource(); - } else { - slaveDataSources.add(dataSourceWrapper.getWrappedDataSource()); - } + TAtomDataSource masterDataSource = null; + List slaveDataSources = new ArrayList(); + for (DataSourceWrapper dataSourceWrapper : dataSourceWrapperMap.values()) { + if (dataSourceWrapper.hasWriteWeight()) { + masterDataSource = dataSourceWrapper.getWrappedDataSource(); + } else { + slaveDataSources.add(dataSourceWrapper.getWrappedDataSource()); } - if (GeneralUtil.isEmpty(slaveDataSources)) { - /** - * 备库没有任何读权重 - */ + } + + if (GeneralUtil.isEmpty(slaveDataSources)) { + /** + * 备库没有任何读权重 + */ + if (notAllowFailedSlave) { + this.groupDataSourceHolder = new MasterFailedSlaveGroupDataSourceHolder(masterDataSource); + } else { this.groupDataSourceHolder = failedSlave ? new MasterFailedSlaveGroupDataSourceHolder(masterDataSource) : new MasterOnlyGroupDataSourceHolder(masterDataSource); - } else { - this.groupDataSourceHolder = new MasterSlaveGroupDataSourceHolder(masterDataSource, slaveDataSources); } - + } else { + this.groupDataSourceHolder = new MasterSlaveGroupDataSourceHolder(masterDataSource, slaveDataSources); } + } private synchronized void cleanUselessSourceWrapper(Set uselessStorageIds) { @@ -816,7 +817,7 @@ private synchronized void cleanUselessSourceWrapper( } @Override - protected synchronized void doDestroy() { + protected void doDestroy() { // 关闭下层DataSource if (dataSourceWrapperMap != null) { for (DataSourceWrapper dsw : dataSourceWrapperMap.values()) { @@ -841,7 +842,6 @@ protected synchronized void doDestroy() { try { unregisterHaSwitcher(); - unbindGroupConfigListener(); //clean the cache datasource for physical backfill PhysicalBackfillUtils.destroyDataSources(); } catch (Exception e) { @@ -868,6 +868,10 @@ public TAtomDataSource getDataSource(MasterSlave masterSlave) { return this.groupDataSourceHolder.getDataSource(masterSlave); } + public GroupDataSourceHolder getGroupDataSourceHolder() { + return groupDataSourceHolder; + } + protected String getServerInstIdForGroupDataSource() { return null; } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/group/jdbc/TGroupDataSource.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/group/jdbc/TGroupDataSource.java index 8bf8bf02e..9e320000a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/group/jdbc/TGroupDataSource.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/group/jdbc/TGroupDataSource.java @@ -31,9 +31,11 @@ import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.common.utils.version.Version; import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.listener.impl.MetaDbDataIdBuilder; import com.alibaba.polardbx.group.config.OptimizedGroupConfigManager; import com.alibaba.polardbx.group.config.Weight; import com.alibaba.polardbx.rpc.compatible.XDataSource; +import com.google.common.annotations.VisibleForTesting; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; @@ -122,6 +124,11 @@ public void doInit() { configManager.init(); } + @VisibleForTesting + protected void setConfigManager(OptimizedGroupConfigManager configManager) { + this.configManager = configManager; + } + /** * 如果构造的是TAtomDataSource,必须检查dbGroupKey、appName两个属性的值是否合法 */ @@ -327,12 +334,24 @@ public DBType getDbType() { * 销毁数据源,慎用 */ public void destroyDataSource() { + + /** + * Unbound the config listeners of group + */ + if (this.configManager != null) { + configManager.unbindGroupConfigListener(); + } + + /** + * destroy the datasources of group + */ destroy(); } + + @Override protected void doDestroy() { - if (configManager != null) { configManager.destroyDataSource(); } @@ -501,4 +520,15 @@ public String getMasterDNId() { } return masterDNId; } + + @Override + public int hashCode() { + // schema, group name, host:port + int result = 1; + String masterAddr = getMasterSourceAddress(); + result = 31 * result + (schemaName == null ? 0 : schemaName.hashCode()); + result = 31 * result + (dbGroupKey == null ? 0 : dbGroupKey.hashCode()); + result = 31 * result + (masterAddr == null ? 0 : masterAddr.hashCode()); + return result; + } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/group/jdbc/TGroupDirectConnection.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/group/jdbc/TGroupDirectConnection.java index 22174a5a8..211c273f5 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/group/jdbc/TGroupDirectConnection.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/group/jdbc/TGroupDirectConnection.java @@ -145,6 +145,18 @@ public long getId() { } } + @Override + public IConnection enableFlashbackArea(boolean enable) throws SQLException { + if (enable) { + if (this.isWrapperFor(XConnection.class) && this.unwrap(XConnection.class).supportFlashbackArea()) { + this.unwrap(XConnection.class).setLazyFlashbackArea(); + } else { + this.executeLater("SET query_via_flashback_area = 1"); + } + } + return this; + } + @Override public void setEncoding(String encoding) throws SQLException { this.encoding = encoding; diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/group/utils/VariableProxy.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/group/utils/VariableProxy.java index dd2e676fb..e057aee4a 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/group/utils/VariableProxy.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/group/utils/VariableProxy.java @@ -18,17 +18,26 @@ import com.alibaba.druid.util.JdbcUtils; import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.InstanceRole; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; import com.alibaba.polardbx.optimizer.variable.IVariableProxy; +import com.alibaba.polardbx.rpc.XLog; import com.alibaba.polardbx.rpc.client.XClient; import com.alibaba.polardbx.rpc.pool.XConnection; import com.google.common.collect.ImmutableMap; import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashMap; /** * @author dylan @@ -52,6 +61,10 @@ public void resetDataSource(TGroupDataSource dataSource) { @Override public ImmutableMap getSessionVariables() { + if (ConfigDataMode.getInstanceRole() == InstanceRole.COLUMNAR_SLAVE) { + return getSessionVariablesForColumnarRO(); + } + if (!ConfigDataMode.needDNResource()) { return ImmutableMap.builder().build(); } @@ -75,6 +88,49 @@ public ImmutableMap getSessionVariables() { } } + private ImmutableMap getSessionVariablesForColumnarRO() { + // get session variables from GMS. + + try (Connection conn = MetaDbUtil.getConnection()) { + if (conn.isWrapperFor(XConnection.class)) { + // X-protocol Mode. + final XClient client = conn.unwrap(XConnection.class).getSession().getClient(); + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.putAll(client.getSessionVariablesL()); + return builder.build(); + } else { + // JDBC Mode + ImmutableMap.Builder variables = ImmutableMap.builder(); + + String sql = "SHOW SESSION VARIABLES"; + Statement statement = null; + ResultSet resultSet = null; + try { + statement = conn.createStatement(); + resultSet = statement.executeQuery(sql); + + while (resultSet.next()) { + String variableName = resultSet.getString("Variable_name"); + String variableValue = resultSet.getString("Value"); + variables.put(variableName, variableValue); + } + + } finally { + if (resultSet != null) { + resultSet.close(); + } + if (statement != null) { + statement.close(); + } + } + + return variables.build(); + } + } catch (Throwable t) { + throw new TddlNestableRuntimeException(t); + } + } + @Override public ImmutableMap getGlobalVariables() { if (!ConfigDataMode.needDNResource()) { diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/checktable/CheckTableUtil.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/checktable/CheckTableUtil.java index c37ca2bda..815be5dd3 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/checktable/CheckTableUtil.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/checktable/CheckTableUtil.java @@ -23,13 +23,15 @@ import com.mysql.jdbc.MysqlErrorNumbers; import com.alibaba.polardbx.atom.TAtomDataSource; import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; -import com.alibaba.polardbx.group.config.Weight; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.executor.common.ExecutorContext; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; import com.alibaba.polardbx.repo.mysql.spi.MyRepository; +import com.mysql.jdbc.MysqlErrorNumbers; import org.apache.calcite.sql.SqlIdentifier; -import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import java.sql.Connection; @@ -79,7 +81,10 @@ public static Map> getTableIndexColumns(String schemaName, while (rs.next()) { String columnName = rs.getString("COLUMN_NAME"); String tableName = rs.getString("TABLE_NAME"); - tableColumns.add(Pair.of(tableName, columnName)); + if (columnName != null) { + //mysql 8.0 函数索引,列名为null + tableColumns.add(Pair.of(tableName, columnName)); + } } } catch (Exception e) { // 打好相关的日志 diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/CommandHandlerFactoryMyImp.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/CommandHandlerFactoryMyImp.java index a6308e5a0..c4788d29b 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/CommandHandlerFactoryMyImp.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/CommandHandlerFactoryMyImp.java @@ -16,10 +16,10 @@ package com.alibaba.polardbx.repo.mysql.handler; -import com.alibaba.polardbx.druid.support.logging.Log; import com.alibaba.polardbx.executor.handler.HandlerCommon; import com.alibaba.polardbx.executor.handler.LogicalAlterDatabaseHandler; import com.alibaba.polardbx.executor.handler.LogicalAlterInstanceHandler; +import com.alibaba.polardbx.executor.handler.LogicalAlterTableArchivePartitionHandler; import com.alibaba.polardbx.executor.handler.LogicalCancelReplicaCheckTableHandler; import com.alibaba.polardbx.executor.handler.LogicalChangeMasterHandler; import com.alibaba.polardbx.executor.handler.LogicalChangeReplicationFilterHandler; @@ -29,37 +29,22 @@ import com.alibaba.polardbx.executor.handler.LogicalContinueScheduleHandler; import com.alibaba.polardbx.executor.handler.LogicalCreateCclRuleHandler; import com.alibaba.polardbx.executor.handler.LogicalCreateCclTriggerHandler; -import com.alibaba.polardbx.executor.handler.LogicalStartReplicaCheckTableHandler; -import com.alibaba.polardbx.executor.handler.LogicalPauseReplicaCheckTableHandler; -import com.alibaba.polardbx.executor.handler.LogicalReplicaHashcheckHandler; +import com.alibaba.polardbx.executor.handler.LogicalCreateScheduleHandler; import com.alibaba.polardbx.executor.handler.LogicalCreateSecurityEntityHandler; -import com.alibaba.polardbx.executor.handler.LogicalDropSecurityEntityHandler; -import com.alibaba.polardbx.executor.handler.LogicalImportSequenceHandler; -import com.alibaba.polardbx.executor.handler.LogicalResetReplicaCheckTableHandler; -import com.alibaba.polardbx.executor.handler.LogicalShowReplicaCheckDiffHandler; -import com.alibaba.polardbx.executor.handler.LogicalShowReplicaCheckProgressHandler; -import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterStoragePoolHandler; -import com.alibaba.polardbx.executor.handler.ddl.LogicalClearFileStorageHandler; -import com.alibaba.polardbx.executor.handler.ddl.LogicalCreateJavaFunctionHandler; -import com.alibaba.polardbx.executor.handler.LogicalFlushLogsHandler; -import com.alibaba.polardbx.executor.handler.LogicalSetCdcGlobalHandler; -import com.alibaba.polardbx.executor.handler.ddl.LogicalCreateJavaFunctionHandler; import com.alibaba.polardbx.executor.handler.LogicalCreateSecurityLabelComponentHandler; import com.alibaba.polardbx.executor.handler.LogicalCreateSecurityLabelHandler; import com.alibaba.polardbx.executor.handler.LogicalCreateSecurityPolicyHandler; -import com.alibaba.polardbx.executor.handler.LogicalDropSecurityLabelComponentHandler; -import com.alibaba.polardbx.executor.handler.LogicalDropSecurityLabelHandler; -import com.alibaba.polardbx.executor.handler.LogicalDropSecurityPolicyHandler; -import com.alibaba.polardbx.executor.handler.LogicalGrantSecurityLabelHandler; -import com.alibaba.polardbx.executor.handler.LogicalRevokeSecurityLabelHandler; -import com.alibaba.polardbx.executor.handler.LogicalSetCdcGlobalHandler; -import com.alibaba.polardbx.executor.handler.LogicalCreateScheduleHandler; import com.alibaba.polardbx.executor.handler.LogicalDropCclRuleHandler; import com.alibaba.polardbx.executor.handler.LogicalDropCclTriggerHandler; import com.alibaba.polardbx.executor.handler.LogicalDropScheduleHandler; +import com.alibaba.polardbx.executor.handler.LogicalDropSecurityEntityHandler; +import com.alibaba.polardbx.executor.handler.LogicalDropSecurityLabelComponentHandler; +import com.alibaba.polardbx.executor.handler.LogicalDropSecurityLabelHandler; +import com.alibaba.polardbx.executor.handler.LogicalDropSecurityPolicyHandler; import com.alibaba.polardbx.executor.handler.LogicalFireScheduleHandler; import com.alibaba.polardbx.executor.handler.LogicalFlushLogsHandler; import com.alibaba.polardbx.executor.handler.LogicalFlushLogsHandler; +import com.alibaba.polardbx.executor.handler.LogicalGrantSecurityLabelHandler; import com.alibaba.polardbx.executor.handler.LogicalImportSequenceHandler; import com.alibaba.polardbx.executor.handler.LogicalPauseReplicaCheckTableHandler; import com.alibaba.polardbx.executor.handler.LogicalPauseScheduleHandler; @@ -70,6 +55,7 @@ import com.alibaba.polardbx.executor.handler.LogicalResetReplicaCheckTableHandler; import com.alibaba.polardbx.executor.handler.LogicalResetSlaveHandler; import com.alibaba.polardbx.executor.handler.LogicalRestartMasterHandler; +import com.alibaba.polardbx.executor.handler.LogicalRevokeSecurityLabelHandler; import com.alibaba.polardbx.executor.handler.LogicalSetCdcGlobalHandler; import com.alibaba.polardbx.executor.handler.LogicalShowBinaryLogsHandler; import com.alibaba.polardbx.executor.handler.LogicalShowBinaryStreamsHandler; @@ -134,6 +120,7 @@ import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableGroupMergePartitionHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableGroupModifyPartitionProxyHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableGroupMovePartitionHandler; +import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableGroupOptimizePartitionHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableGroupRenamePartitionHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableGroupReorgPartitionHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableGroupSetLocalityHandler; @@ -145,6 +132,7 @@ import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableMergePartitionHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableModifyPartitionProxyHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableMovePartitionHandler; +import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableOptimizePartitionHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTablePartitionCountHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableRemovePartitioningHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableRenamePartitionHandler; @@ -156,6 +144,7 @@ import com.alibaba.polardbx.executor.handler.ddl.LogicalAlterTableTruncatePartitionHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalCheckCciHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalCheckGsiHandler; +import com.alibaba.polardbx.executor.handler.ddl.LogicalClearFileStorageHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalCommonDdlHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalCreateDatabaseHandler; import com.alibaba.polardbx.executor.handler.ddl.LogicalCreateDatabaseLikeAsHandler; @@ -206,6 +195,8 @@ import com.alibaba.polardbx.optimizer.core.rel.EmptyOperation; import com.alibaba.polardbx.optimizer.core.rel.Gather; import com.alibaba.polardbx.optimizer.core.rel.GsiBackfill; +import com.alibaba.polardbx.optimizer.core.rel.GsiPartitionBackfill; +import com.alibaba.polardbx.optimizer.core.rel.GsiPkRangeBackfill; import com.alibaba.polardbx.optimizer.core.rel.LogicalInsert; import com.alibaba.polardbx.optimizer.core.rel.LogicalInsertIgnore; import com.alibaba.polardbx.optimizer.core.rel.LogicalModify; @@ -237,6 +228,7 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterSystemSetConfig; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTable; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableAddPartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableArchivePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableDropPartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableExtractPartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupAddPartition; @@ -246,6 +238,7 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupMergePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupModifyPartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupMovePartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupOptimizePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupRenamePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupReorgPartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupSetLocality; @@ -256,6 +249,7 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableMergePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableModifyPartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableMovePartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableOptimizePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTablePartitionCount; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableRemovePartitioning; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableRenamePartition; @@ -269,8 +263,8 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalChangeConsensusLeader; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalCheckCci; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalCheckGsi; -import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalConvertAllSequences; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalClearFileStorage; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalConvertAllSequences; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalCreateDatabase; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalCreateFileStorage; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalCreateFunction; @@ -318,7 +312,9 @@ import com.alibaba.polardbx.repo.mysql.handler.ddl.newengine.DdlEnginePauseJobsHandler; import com.alibaba.polardbx.repo.mysql.handler.ddl.newengine.DdlEnginePauseRebalanceHandler; import com.alibaba.polardbx.repo.mysql.handler.ddl.newengine.DdlEngineRecoverJobsHandler; +import com.alibaba.polardbx.repo.mysql.handler.ddl.newengine.DdlEngineResumeRebalanceHandler; import com.alibaba.polardbx.repo.mysql.handler.ddl.newengine.DdlEngineRollbackJobsHandler; +import com.alibaba.polardbx.repo.mysql.handler.ddl.newengine.DdlEngineShowDdlEngineStatusHandler; import com.alibaba.polardbx.repo.mysql.handler.ddl.newengine.DdlEngineShowDdlStatsHandler; import com.alibaba.polardbx.repo.mysql.handler.ddl.newengine.DdlEngineShowJobsHandler; import com.alibaba.polardbx.repo.mysql.handler.ddl.newengine.DdlEngineShowRebalanceBackFillHandler; @@ -349,6 +345,7 @@ public CommandHandlerFactoryMyImp(IRepository repo) { LOGICAL_MODIFY_VIEW_HANDLER = new LogicalModifyViewHandler(repo); LOGICAL_MODIFY_HANDLER = new LogicalModifyHandler(repo); SINGLE_TABLE_MODIFY_HANDLER = new MySingleTableModifyHandler(repo); + SINGLE_TABLE_MODIFY_RETURNING_HANDLER = new MySingleTableModifyReturningHandler(repo); LOGICAL_RELOCATE_HANDLER = new LogicalRelocateHandler(repo); LOGICAL_AFFECT_ROW_SUM_HANDLER = new AffectRowSumHandler(); LOGICAL_INSERT_HANDLER = new LogicalInsertHandler(repo); @@ -424,6 +421,7 @@ public CommandHandlerFactoryMyImp(IRepository repo) { LOGICAL_CHECK_TABLE_HANDLER = new LogicalCheckTableHandler(repo); LOGICAL_CHECK_COLUMNAR_PARTITION_HANDLER = new LogicalCheckColumnarPartitionHandler(repo); + LOGICAL_CHECK_COLUMNAR_SNAPSHOT_HANDLER = new LogicalCheckColumnarSnapshotHandler(repo); LOGICAL_KILL_HANDLER = new LogicalKillHandler(repo); LOGICAL_ANALYZE_TABLE_HANDLER = new LogicalAnalyzeTableDdlHandler(repo); @@ -444,6 +442,7 @@ public CommandHandlerFactoryMyImp(IRepository repo) { LOGICAL_IMPORT_SEQUENCE = new LogicalImportSequenceHandler(repo); SHOW_DDL_JOBS_HANDLER = new DdlEngineShowJobsHandler(repo); + SHOW_DDL_ENGINE_HANDLER = new DdlEngineShowDdlEngineStatusHandler(repo); RECOVER_DDL_JOBS_HANDLER = new DdlEngineRecoverJobsHandler(repo); CANCEL_DDL_JOBS_HANDLER = new DdlEngineCancelJobsHandler(repo); ROLLBACK_DDL_JOBS_HANDLER = new DdlEngineRollbackJobsHandler(repo); @@ -454,6 +453,7 @@ public CommandHandlerFactoryMyImp(IRepository repo) { PAUSE_DDL_JOBS_HANDLER = new DdlEnginePauseJobsHandler(repo); PAUSE_REBALANCE_JOBS_HANDLER = new DdlEnginePauseRebalanceHandler(repo); TERMINATE_REBALANCE_JOBS_HANDLER = new DdlEngineTerminateRebalanceHandler(repo); + RESUME_REBALANCE_JOBS_HANDLER = new DdlEngineResumeRebalanceHandler(repo); SKIP_REBALANCE_SUBJOB_HANDLER = new DdlEngineSkipRebalanceSubjobHandler(repo); CONTINUE_DDL_JOBS_HANDLER = new DdlEngineContinueJobsHandler(repo); SHOW_DDL_RESULTS_HANDLER = new DdlEngineShowResultsHandler(repo); @@ -476,6 +476,8 @@ public CommandHandlerFactoryMyImp(IRepository repo) { CONVERT_ALL_SEQUENCES_HANDLER = new ConvertAllSequencesHandler(repo); SAVEPOINT_HANDLER = new SavepointHandler(repo); + GSI_PK_RANGE_BACKFILL_HANDLER = new GsiPkRangeBackfillHandler(repo); + GSI_PARTITION_BACKFILL_HANDLER = new GsiPartitionBackfillHandler(repo); GSI_BACKFILL_HANDLER = new GsiBackfillHandler(repo); LOGICAL_MOVE_DATABASES_HANDLER = new LogicalMoveDatabaseHandler(repo); COLUMN_BACKFILL_HANDLER = new ColumnBackfillHandler(repo); @@ -571,6 +573,7 @@ public CommandHandlerFactoryMyImp(IRepository repo) { LOGICAL_ALTER_TABLEGROUP_ADD_PARTITION_PROXY_HANDLER = new LogicalAlterTableGroupAddPartitionProxyHandler(repo); LOGICAL_ALTER_TABLEGROUP_DROP_PARTITION_HANDLER = new LogicalAlterTableGroupDropPartitionHandler(repo); LOGICAL_ALTER_TABLEGROUP_TRUNCATE_PARTITION_HANDLER = new LogicalAlterTableGroupTruncatePartitionHandler(repo); + LOGICAL_ALTER_TABLEGROUP_OPTIMIZE_PARTITION_HANDLER = new LogicalAlterTableGroupOptimizePartitionHandler(repo); LOGICAL_ALTER_TABLEGROUP_REORGANIZE_PARTITION_HANDLER = new LogicalAlterTableGroupReorgPartitionHandler(repo); LOGICAL_ALTER_TABLEGROUP_MODIFY_PARTITION_PROXY_HANDLER = @@ -603,6 +606,7 @@ public CommandHandlerFactoryMyImp(IRepository repo) { LOGICAL_ALTER_TABLE_ADD_PARTITION_PROXY_HANDLER = new LogicalAlterTableAddPartitionProxyHandler(repo); LOGICAL_ALTER_TABLE_DROP_PARTITION_HANDLER = new LogicalAlterTableDropPartitionHandler(repo); LOGICAL_ALTER_TABLE_TRUNCATE_PARTITION_HANDLER = new LogicalAlterTableTruncatePartitionHandler(repo); + LOGICAL_ALTER_TABLE_OPTIMIZE_PARTITION_HANDLER = new LogicalAlterTableOptimizePartitionHandler(repo); LOGICAL_ALTER_TABLE_REORGANIZE_PARTITION_HANDLER = new LogicalAlterTableReorgPartitionHandler(repo); LOGICAL_ALTER_TABLE_MODIFY_PARTITION_PROXY_HANDLER = new LogicalAlterTableModifyPartitionProxyHandler(repo); LOGICAL_ALTER_TABLE_RENAME_PARTITION_HANDLER = new LogicalAlterTableRenamePartitionHandler(repo); @@ -620,6 +624,8 @@ public CommandHandlerFactoryMyImp(IRepository repo) { LOGICAL_DROP_MATERIALIZED_VIEW = new LogicalDropMaterializedViewHandler(repo); LOGICAL_SHOW_CREATE_TABLEGROUP_HANDLER = new LogicalShowCreateTableGroupHandler(repo); + + LOGICAL_ALTER_TABLE_ARCHIVE_PARTITION_HANDLER = new LogicalAlterTableArchivePartitionHandler(repo); } private final LogicalRecyclebinHandler LOGICAL_RECYCLEBIN_HANDLER; @@ -674,6 +680,7 @@ public CommandHandlerFactoryMyImp(IRepository repo) { private final PlanHandler LOGICAL_MODIFY_HANDLER; private final PlanHandler LOGICAL_RELOCATE_HANDLER; private final PlanHandler SINGLE_TABLE_MODIFY_HANDLER; + private final PlanHandler SINGLE_TABLE_MODIFY_RETURNING_HANDLER; private final PlanHandler BROADCAST_TABLE_MODIFY_HANDLER; private final PlanHandler LOGICAL_SHOW_DATASOURCES_HANDLER; private final PlanHandler LOGICAL_SHOW_TABLES_HANDLER; @@ -723,6 +730,7 @@ public CommandHandlerFactoryMyImp(IRepository repo) { private final PlanHandler LOGICAL_CHECK_TABLE_HANDLER; private final PlanHandler LOGICAL_CHECK_COLUMNAR_PARTITION_HANDLER; + private final PlanHandler LOGICAL_CHECK_COLUMNAR_SNAPSHOT_HANDLER; private final PlanHandler LOGICAL_KILL_HANDLER; private final PlanHandler LOGICAL_ANALYZE_TABLE_HANDLER; @@ -749,6 +757,8 @@ public CommandHandlerFactoryMyImp(IRepository repo) { private final PlanHandler LOGICAL_DROP_JAVA_FUNCTION_HANDLER; private final PlanHandler SHOW_DDL_JOBS_HANDLER; + + private final PlanHandler SHOW_DDL_ENGINE_HANDLER; private final PlanHandler CANCEL_DDL_JOBS_HANDLER; private final PlanHandler ROLLBACK_DDL_JOBS_HANDLER; private final PlanHandler INSPECT_DDL_JOBS_CACHE_HANDLER; @@ -756,6 +766,7 @@ public CommandHandlerFactoryMyImp(IRepository repo) { private final PlanHandler PAUSE_DDL_JOBS_HANDLER; private final PlanHandler PAUSE_REBALANCE_JOBS_HANDLER; private final PlanHandler TERMINATE_REBALANCE_JOBS_HANDLER; + private final PlanHandler RESUME_REBALANCE_JOBS_HANDLER; private final PlanHandler SKIP_REBALANCE_SUBJOB_HANDLER; private final PlanHandler CONTINUE_DDL_JOBS_HANDLER; private final PlanHandler SHOW_DDL_RESULTS_HANDLER; @@ -778,6 +789,8 @@ public CommandHandlerFactoryMyImp(IRepository repo) { private final PlanHandler CONVERT_ALL_SEQUENCES_HANDLER; private final PlanHandler SAVEPOINT_HANDLER; + private final PlanHandler GSI_PK_RANGE_BACKFILL_HANDLER; + private final PlanHandler GSI_PARTITION_BACKFILL_HANDLER; private final PlanHandler GSI_BACKFILL_HANDLER; private final PlanHandler LOGICAL_CHECK_GSI_HANDLER; private final PlanHandler LOGICAL_CHECK_CCI_HANDLER; @@ -870,6 +883,7 @@ public CommandHandlerFactoryMyImp(IRepository repo) { private final PlanHandler LOGICAL_ALTER_TABLEGROUP_ADD_PARTITION_PROXY_HANDLER; private final PlanHandler LOGICAL_ALTER_TABLEGROUP_DROP_PARTITION_HANDLER; private final PlanHandler LOGICAL_ALTER_TABLEGROUP_TRUNCATE_PARTITION_HANDLER; + private final PlanHandler LOGICAL_ALTER_TABLEGROUP_OPTIMIZE_PARTITION_HANDLER; private final PlanHandler LOGICAL_ALTER_TABLEGROUP_REORGANIZE_PARTITION_HANDLER; private final PlanHandler LOGICAL_ALTER_TABLEGROUP_MODIFY_PARTITION_PROXY_HANDLER; private final PlanHandler LOGICAL_ALTER_TABLEGROUP_SPLIT_PARTITION_BY_HOT_AVLUE_HANDLER; @@ -899,10 +913,13 @@ public CommandHandlerFactoryMyImp(IRepository repo) { private final PlanHandler LOGICAL_ALTER_TABLE_ADD_PARTITION_PROXY_HANDLER; private final PlanHandler LOGICAL_ALTER_TABLE_DROP_PARTITION_HANDLER; private final PlanHandler LOGICAL_ALTER_TABLE_TRUNCATE_PARTITION_HANDLER; + private final PlanHandler LOGICAL_ALTER_TABLE_OPTIMIZE_PARTITION_HANDLER; private final PlanHandler LOGICAL_ALTER_TABLE_REORGANIZE_PARTITION_HANDLER; private final PlanHandler LOGICAL_ALTER_TABLE_MODIFY_PARTITION_PROXY_HANDLER; private final PlanHandler LOGICAL_ALTER_TABLE_RENAME_PARTITION_HANDLER; + private final PlanHandler LOGICAL_ALTER_TABLE_ARCHIVE_PARTITION_HANDLER; + private final PlanHandler LOGICAL_CREATE_MATERIALIZED_VIEW; private final PlanHandler LOGICAL_DROP_MATERIALIZED_VIEW; @@ -930,6 +947,8 @@ public PlanHandler getCommandHandler(RelNode logicalPlan, ExecutionContext execu return LOGICAL_SEQUENCE_DDL_HANDLER; } else if (SqlKind.SUPPORT_DDL.contains(kind)) { return SINGLE_TABLE_SCAN_HANDLER; + } else if (SqlKind.DML.contains(kind) && executionContext.useReturning()) { + return SINGLE_TABLE_MODIFY_RETURNING_HANDLER; } else { return SINGLE_TABLE_MODIFY_HANDLER; } @@ -1014,6 +1033,11 @@ public PlanHandler getCommandHandler(RelNode logicalPlan, ExecutionContext execu return LOGICAL_ALTER_SYSTEM_RELOAD_STORAGE_HANDLER; } else if (logicalPlan instanceof LogicalAlterSystemLeader) { return LOGICAL_ALTER_SYSTEM_LEADER_HANDLER; + } else if (logicalPlan instanceof GsiPkRangeBackfill) { + // which must be before, seems GsiPkRangeBackfill is subclass of GsiBackfill + return GSI_PK_RANGE_BACKFILL_HANDLER; + } else if (logicalPlan instanceof GsiPartitionBackfill) { + return GSI_PARTITION_BACKFILL_HANDLER; } else if (logicalPlan instanceof GsiBackfill) { return GSI_BACKFILL_HANDLER; } else if (logicalPlan instanceof ColumnBackFill) { @@ -1092,6 +1116,8 @@ public PlanHandler getCommandHandler(RelNode logicalPlan, ExecutionContext execu } else if (logicalPlan instanceof LogicalAlterTableMovePartition && !(logicalPlan instanceof LogicalAlterTableGroupMovePartition)) { return LOGICAL_ALTER_TABLE_MOVE_PARTITION_HANDLER; + } else if (logicalPlan instanceof LogicalAlterTableArchivePartition) { + return LOGICAL_ALTER_TABLE_ARCHIVE_PARTITION_HANDLER; } else if (logicalPlan instanceof LogicalAlterTableGroupExtractPartition) { return LOGICAL_ALTER_TABLEGROUP_EXTRACT_PARTITION_PROXY_HANDLER; } else if (logicalPlan instanceof LogicalAlterTableExtractPartition @@ -1128,9 +1154,14 @@ public PlanHandler getCommandHandler(RelNode logicalPlan, ExecutionContext execu return LOGICAL_ALTER_TABLE_DROP_PARTITION_HANDLER; } else if (logicalPlan instanceof LogicalAlterTableGroupTruncatePartition) { return LOGICAL_ALTER_TABLEGROUP_TRUNCATE_PARTITION_HANDLER; + } else if (logicalPlan instanceof LogicalAlterTableGroupOptimizePartition) { + return LOGICAL_ALTER_TABLEGROUP_OPTIMIZE_PARTITION_HANDLER; } else if (logicalPlan instanceof LogicalAlterTableTruncatePartition && !(logicalPlan instanceof LogicalAlterTableGroupTruncatePartition)) { return LOGICAL_ALTER_TABLE_TRUNCATE_PARTITION_HANDLER; + } else if (logicalPlan instanceof LogicalAlterTableOptimizePartition + && !(logicalPlan instanceof LogicalAlterTableGroupOptimizePartition)) { + return LOGICAL_ALTER_TABLE_OPTIMIZE_PARTITION_HANDLER; } else if (logicalPlan instanceof LogicalAlterTableGroupReorgPartition) { return LOGICAL_ALTER_TABLEGROUP_REORGANIZE_PARTITION_HANDLER; } else if (logicalPlan instanceof LogicalAlterTableReorgPartition @@ -1250,6 +1281,8 @@ public PlanHandler getCommandHandler(RelNode logicalPlan, ExecutionContext execu return LOGICAL_CHECK_TABLE_HANDLER; case CHECK_COLUMNAR_PARTITION: return LOGICAL_CHECK_COLUMNAR_PARTITION_HANDLER; + case CHECK_COLUMNAR_SNAPSHOT: + return LOGICAL_CHECK_COLUMNAR_SNAPSHOT_HANDLER; case KILL: return LOGICAL_KILL_HANDLER; case ANALYZE_TABLE: @@ -1260,6 +1293,8 @@ public PlanHandler getCommandHandler(RelNode logicalPlan, ExecutionContext execu return LOGICAL_SHOW_INDEX_HANDLER; case SHOW_DDL_JOBS: return SHOW_DDL_JOBS_HANDLER; + case SHOW_DDL_ENGINE: + return SHOW_DDL_ENGINE_HANDLER; case SHOW_DDL_STATUS: return SHOW_DDL_STATS_HANDLER; case SHOW_REBALANCE_BACKFILL: @@ -1280,6 +1315,8 @@ public PlanHandler getCommandHandler(RelNode logicalPlan, ExecutionContext execu return PAUSE_REBALANCE_JOBS_HANDLER; case TERMINATE_REBALANCE_JOB: return TERMINATE_REBALANCE_JOBS_HANDLER; + case RESUME_REBALANCE_JOB: + return RESUME_REBALANCE_JOBS_HANDLER; case ROLLBACK_DDL_JOB: return ROLLBACK_DDL_JOBS_HANDLER; case SKIP_REBALANCE_SUBJOB: diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/GsiBackfillHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/GsiBackfillHandler.java index f9c6abe9c..0c3777a79 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/GsiBackfillHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/GsiBackfillHandler.java @@ -21,6 +21,7 @@ import com.alibaba.polardbx.common.properties.MetricLevel; import com.alibaba.polardbx.common.properties.ParamManager; import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.executor.backfill.Loader; import com.alibaba.polardbx.executor.cursor.Cursor; import com.alibaba.polardbx.executor.cursor.impl.AffectRowCursor; @@ -30,7 +31,6 @@ import com.alibaba.polardbx.executor.handler.HandlerCommon; import com.alibaba.polardbx.executor.spi.IRepository; import com.alibaba.polardbx.optimizer.OptimizerContext; -import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.GsiBackfill; import com.alibaba.polardbx.optimizer.utils.PhyTableOperationUtil; @@ -65,14 +65,19 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { String baseTableName = backfill.getBaseTableName(); List indexNames = backfill.getIndexNames(); List columnsName = backfill.getColumns(); - Map virtualColumnMap = backfill.getVirtualColumnMap(); - Map backfillColumnMap = backfill.getBackfillColumnMap(); + Map srcCheckColumnMap = backfill.getSrcCheckColumnMap(); + Map dstCheckColumnMap = backfill.getDstCheckColumnMap(); List modifyStringColumns = backfill.getModifyStringColumns(); boolean useChangeSet = backfill.isUseChangeSet(); - boolean modifyColumn = backfill.isModifyColumn(); + boolean onlineModifyColumn = backfill.isOnlineModifyColumn(); BackfillExecutor backfillExecutor = new BackfillExecutor((List inputs, ExecutionContext executionContext1) -> { + // backfill batch insert 开启 group concurrent,在有前端流量时,会产生主键冲突,在 RR 下会产生 GAP 锁,容易发生死锁。 + // 关闭改参数,还原为以前的 SEQUENTIAL,减少死锁 + // 后续会将 backfill batch insert 事务改成 XA + RC 避免 gap 锁 + executionContext1.getExtraCmds() + .put(ConnectionProperties.ENABLE_DML_GROUP_CONCURRENT_IN_TRANSACTION, false); QueryConcurrencyPolicy queryConcurrencyPolicy = getQueryConcurrencyPolicy(executionContext1); if (Loader.canUseBackfillReturning(executionContext1, schemaName)) { queryConcurrencyPolicy = QueryConcurrencyPolicy.GROUP_CONCURRENT_BLOCK; @@ -87,7 +92,7 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { boolean canUseReturning = Loader.canUseBackfillReturning(executionContext, schemaName); // online modify column, does not clear sql_mode - if (modifyColumn) { + if (onlineModifyColumn) { executionContext = setChangeSetApplySqlMode(executionContext.copy()); if (!useBinary && !omcForce) { // select + insert, need encoding @@ -119,13 +124,13 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { assert 1 == indexNames.size(); affectRows = backfillExecutor.mirrorCopyGsiBackfill(schemaName, baseTableName, indexNames.get(0), useChangeSet, - useBinary, executionContext); + useBinary, onlineModifyColumn, executionContext); } else { // Normal creating GSI. assert 1 == indexNames.size(); affectRows = backfillExecutor.backfill(schemaName, baseTableName, indexNames.get(0), useBinary, useChangeSet, - canUseReturning, modifyStringColumns, executionContext); + canUseReturning, modifyStringColumns, onlineModifyColumn, executionContext); } // Check GSI immediately after creation by default. @@ -140,28 +145,20 @@ public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { // TODO(moyi) separate check to another task for (String indexName : indexNames) { - baseTableName = getPrimaryTableName(schemaName, baseTableName, backfill.isMirrorCopy(), executionContext); boolean isPrimaryBroadCast = OptimizerContext.getContext(schemaName).getRuleManager().isBroadCast(baseTableName); boolean isGsiBroadCast = OptimizerContext.getContext(schemaName).getRuleManager().isBroadCast(indexName); CheckGsiTask checkTask = new CheckGsiTask(schemaName, baseTableName, indexName, lockMode, lockMode, params, false, "", - isPrimaryBroadCast, isGsiBroadCast, virtualColumnMap, backfillColumnMap); - + isPrimaryBroadCast, isGsiBroadCast, onlineModifyColumn); + if (onlineModifyColumn) { + checkTask.setSrcCheckColumnMap(srcCheckColumnMap); + checkTask.setDstCheckColumnMap(dstCheckColumnMap); + } checkTask.checkInBackfill(executionContext); } return new AffectRowCursor(affectRows); } - - public static String getPrimaryTableName(String schemaName, String baseTableName, boolean mirrorCopy, - ExecutionContext executionContext) { - String primaryTableName = baseTableName; - TableMeta sourceTableMeta = executionContext.getSchemaManager(schemaName).getTable(baseTableName); - if (mirrorCopy && sourceTableMeta.isGsi()) { - primaryTableName = sourceTableMeta.getGsiTableMetaBean().gsiMetaBean.tableName; - } - return primaryTableName; - } } diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/GsiPartitionBackfillHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/GsiPartitionBackfillHandler.java new file mode 100644 index 000000000..211ceed7d --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/GsiPartitionBackfillHandler.java @@ -0,0 +1,154 @@ +package com.alibaba.polardbx.repo.mysql.handler; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.MetricLevel; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.executor.backfill.Loader; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.cursor.impl.AffectRowCursor; +import com.alibaba.polardbx.executor.gsi.BackfillExecutor; +import com.alibaba.polardbx.executor.gsi.corrector.GsiChecker; +import com.alibaba.polardbx.executor.handler.HandlerCommon; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.GsiPartitionBackfill; +import com.alibaba.polardbx.optimizer.core.rel.GsiPkRangeBackfill; +import com.alibaba.polardbx.optimizer.utils.PhyTableOperationUtil; +import com.alibaba.polardbx.optimizer.utils.QueryConcurrencyPolicy; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.sql.SqlSelect; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.alibaba.polardbx.executor.utils.ExecUtils.getQueryConcurrencyPolicy; + +/** + * Process backfill for GSI. GsiPkRangeBackfillHandler extends CalciteHandlerCommon + * because we're going to reuse `executeWithConcurrentPolicy` to execute + * INSERTs. + */ +public class GsiPartitionBackfillHandler extends HandlerCommon { + + private static final Logger LOG = SQLRecorderLogger.ddlLogger; + + public GsiPartitionBackfillHandler(IRepository repo) { + super(repo); + } + + @Override + public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { + GsiPartitionBackfill backfill = (GsiPartitionBackfill) logicalPlan; + String schemaName = backfill.getSchemaName(); + String baseTableName = backfill.getBaseTableName(); + List indexNames = backfill.getIndexNames(); + List columnsName = backfill.getColumns(); + Map virtualColumnMap = backfill.getSrcCheckColumnMap(); + Map backfillColumnMap = backfill.getDstCheckColumnMap(); + List modifyStringColumns = backfill.getModifyStringColumns(); + boolean useChangeSet = backfill.isUseChangeSet(); + boolean modifyColumn = backfill.isOnlineModifyColumn(); + List partitionList = backfill.getPartitionList(); + + BackfillExecutor backfillExecutor = new BackfillExecutor((List inputs, + ExecutionContext executionContext1) -> { + QueryConcurrencyPolicy queryConcurrencyPolicy = getQueryConcurrencyPolicy(executionContext1); + if (Loader.canUseBackfillReturning(executionContext1, schemaName)) { + queryConcurrencyPolicy = QueryConcurrencyPolicy.GROUP_CONCURRENT_BLOCK; + } + List inputCursors = new ArrayList<>(inputs.size()); + executeWithConcurrentPolicy(executionContext1, inputs, queryConcurrencyPolicy, inputCursors, schemaName); + return inputCursors; + }); + + boolean useBinary = executionContext.getParamManager().getBoolean(ConnectionParams.BACKFILL_USING_BINARY); + boolean omcForce = executionContext.getParamManager().getBoolean(ConnectionParams.OMC_FORCE_TYPE_CONVERSION); + boolean canUseReturning = Loader.canUseBackfillReturning(executionContext, schemaName); + + // online modify column, does not clear sql_mode + if (modifyColumn) { + executionContext = setChangeSetApplySqlMode(executionContext.copy()); + if (!useBinary && !omcForce) { + // select + insert, need encoding + upgradeEncoding(executionContext, schemaName, baseTableName); + } + // 暂时不使用 backfill insert ignore returning 优化,因为无法处理 sql_mode 严格模式行为 + canUseReturning = false; + } else { + executionContext = clearSqlMode(executionContext.copy()); + if (!useBinary) { + upgradeEncoding(executionContext, schemaName, baseTableName); + } + } + + executionContext.getExtraCmds().put(ConnectionProperties.MPP_METRIC_LEVEL, MetricLevel.SQL.metricLevel); + + PhyTableOperationUtil.disableIntraGroupParallelism(schemaName, executionContext); + + // Force master first and following will copy this EC. + executionContext.getExtraCmds().put(ConnectionProperties.MASTER, true); + int affectRows; + if (backfill.isAddColumnsBackfill()) { + // Add column on clustered GSI. + assert indexNames.size() > 0; + affectRows = backfillExecutor + .addColumnsBackfill(schemaName, baseTableName, indexNames, columnsName, executionContext); + } else if (backfill.isMirrorCopy()) { + // Normal creating GSI. + assert 1 == indexNames.size(); + affectRows = + backfillExecutor.mirrorCopyGsiBackfill(schemaName, baseTableName, indexNames.get(0), useChangeSet, + useBinary, modifyColumn, executionContext); + } else { + // Normal creating GSI. + assert 1 == indexNames.size(); + affectRows = + backfillExecutor.backfill(schemaName, baseTableName, indexNames.get(0), useBinary, useChangeSet, + canUseReturning, modifyStringColumns, null, partitionList, modifyColumn, 1, executionContext); + } + + // Check GSI immediately after creation by default. + final ParamManager pm = executionContext.getParamManager(); + boolean check = pm.getBoolean(ConnectionParams.GSI_CHECK_AFTER_CREATION) && !useChangeSet; + if (!check) { + return new AffectRowCursor(affectRows); + } + + String lockMode = SqlSelect.LockMode.UNDEF.toString(); + GsiChecker.Params params = GsiChecker.Params.buildFromExecutionContext(executionContext); + + // TODO(yijin-future): we assume that index size is 1, so we only append one check task. + for (String indexName : indexNames) { + baseTableName = getPrimaryTableName(schemaName, baseTableName, backfill.isMirrorCopy(), executionContext); + boolean isPrimaryBroadCast = + OptimizerContext.getContext(schemaName).getRuleManager().isBroadCast(baseTableName); + boolean isGsiBroadCast = OptimizerContext.getContext(schemaName).getRuleManager().isBroadCast(indexName); +// CheckGsiTask checkTask = +// new CheckGsiTask(schemaName, baseTableName, indexName, lockMode, lockMode, params, false, "", +// isPrimaryBroadCast, isGsiBroadCast, virtualColumnMap, backfillColumnMap); +// +// checkTask.checkInBackfill(executionContext); + } + + return new AffectRowCursor(affectRows); + } + + public static String getPrimaryTableName(String schemaName, String baseTableName, boolean mirrorCopy, + ExecutionContext executionContext) { + String primaryTableName = baseTableName; + TableMeta sourceTableMeta = executionContext.getSchemaManager(schemaName).getTable(baseTableName); + if (mirrorCopy && sourceTableMeta.isGsi()) { + primaryTableName = sourceTableMeta.getGsiTableMetaBean().gsiMetaBean.tableName; + } + return primaryTableName; + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/GsiPkRangeBackfillHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/GsiPkRangeBackfillHandler.java new file mode 100644 index 000000000..f29c28239 --- /dev/null +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/GsiPkRangeBackfillHandler.java @@ -0,0 +1,155 @@ +package com.alibaba.polardbx.repo.mysql.handler; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.MetricLevel; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.executor.backfill.Loader; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.cursor.impl.AffectRowCursor; +import com.alibaba.polardbx.executor.ddl.job.task.gsi.CheckGsiTask; +import com.alibaba.polardbx.executor.gsi.BackfillExecutor; +import com.alibaba.polardbx.executor.gsi.corrector.GsiChecker; +import com.alibaba.polardbx.executor.handler.HandlerCommon; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.GsiPkRangeBackfill; +import com.alibaba.polardbx.optimizer.core.row.Row; +import com.alibaba.polardbx.optimizer.utils.PhyTableOperationUtil; +import com.alibaba.polardbx.optimizer.utils.QueryConcurrencyPolicy; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.sql.SqlSelect; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.alibaba.polardbx.executor.utils.ExecUtils.getQueryConcurrencyPolicy; + +/** + * Process backfill for GSI. GsiPkRangeBackfillHandler extends CalciteHandlerCommon + * because we're going to reuse `executeWithConcurrentPolicy` to execute + * INSERTs. + */ +public class GsiPkRangeBackfillHandler extends HandlerCommon { + + private static final Logger LOG = SQLRecorderLogger.ddlLogger; + + public GsiPkRangeBackfillHandler(IRepository repo) { + super(repo); + } + + @Override + public Cursor handle(RelNode logicalPlan, ExecutionContext executionContext) { + GsiPkRangeBackfill backfill = (GsiPkRangeBackfill) logicalPlan; + String schemaName = backfill.getSchemaName(); + String baseTableName = backfill.getBaseTableName(); + List indexNames = backfill.getIndexNames(); + List columnsName = backfill.getColumns(); + int totalThreadCount = backfill.getTotalThreadCount(); + Map virtualColumnMap = backfill.getSrcCheckColumnMap(); + Map backfillColumnMap = backfill.getDstCheckColumnMap(); + List modifyStringColumns = backfill.getModifyStringColumns(); + boolean useChangeSet = backfill.isUseChangeSet(); + boolean modifyColumn = backfill.isOnlineModifyColumn(); + Pair, Map> pkRange = backfill.getPkRange(); + + BackfillExecutor backfillExecutor = new BackfillExecutor((List inputs, + ExecutionContext executionContext1) -> { + QueryConcurrencyPolicy queryConcurrencyPolicy = getQueryConcurrencyPolicy(executionContext1); + if (Loader.canUseBackfillReturning(executionContext1, schemaName)) { + queryConcurrencyPolicy = QueryConcurrencyPolicy.GROUP_CONCURRENT_BLOCK; + } + List inputCursors = new ArrayList<>(inputs.size()); + executeWithConcurrentPolicy(executionContext1, inputs, queryConcurrencyPolicy, inputCursors, schemaName); + return inputCursors; + }); + + boolean useBinary = executionContext.getParamManager().getBoolean(ConnectionParams.BACKFILL_USING_BINARY); + boolean omcForce = executionContext.getParamManager().getBoolean(ConnectionParams.OMC_FORCE_TYPE_CONVERSION); + boolean canUseReturning = Loader.canUseBackfillReturning(executionContext, schemaName); + + // online modify column, does not clear sql_mode + if (modifyColumn) { + executionContext = setChangeSetApplySqlMode(executionContext); + if (!useBinary && !omcForce) { + // select + insert, need encoding + upgradeEncoding(executionContext, schemaName, baseTableName); + } + // 暂时不使用 backfill insert ignore returning 优化,因为无法处理 sql_mode 严格模式行为 + canUseReturning = false; + } else { + executionContext = clearSqlMode(executionContext); + if (!useBinary) { + upgradeEncoding(executionContext, schemaName, baseTableName); + } + } + + executionContext.getExtraCmds().put(ConnectionProperties.MPP_METRIC_LEVEL, MetricLevel.SQL.metricLevel); + + PhyTableOperationUtil.disableIntraGroupParallelism(schemaName, executionContext); + + // Force master first and following will copy this EC. + executionContext.getExtraCmds().put(ConnectionProperties.MASTER, true); + int affectRows; + if (backfill.isAddColumnsBackfill()) { + // Add column on clustered GSI. + assert indexNames.size() > 0; + affectRows = backfillExecutor + .addColumnsBackfill(schemaName, baseTableName, indexNames, columnsName, executionContext); + } else if (backfill.isMirrorCopy()) { + // Normal creating GSI. + assert 1 == indexNames.size(); + affectRows = + backfillExecutor.mirrorCopyGsiBackfill(schemaName, baseTableName, indexNames.get(0), useChangeSet, + useBinary, modifyColumn, executionContext); + } else { + // Normal creating GSI. + assert 1 == indexNames.size(); + affectRows = + backfillExecutor.backfill(schemaName, baseTableName, indexNames.get(0), useBinary, useChangeSet, + canUseReturning, modifyStringColumns, pkRange, null, modifyColumn, totalThreadCount, executionContext); + } + + // Check GSI immediately after creation by default. + final ParamManager pm = executionContext.getParamManager(); + boolean check = pm.getBoolean(ConnectionParams.GSI_CHECK_AFTER_CREATION) && !useChangeSet; + if (!check) { + return new AffectRowCursor(affectRows); + } + + String lockMode = SqlSelect.LockMode.UNDEF.toString(); + GsiChecker.Params params = GsiChecker.Params.buildFromExecutionContext(executionContext); + + for (String indexName : indexNames) { + baseTableName = getPrimaryTableName(schemaName, baseTableName, backfill.isMirrorCopy(), executionContext); + boolean isPrimaryBroadCast = + OptimizerContext.getContext(schemaName).getRuleManager().isBroadCast(baseTableName); + boolean isGsiBroadCast = OptimizerContext.getContext(schemaName).getRuleManager().isBroadCast(indexName); +// CheckGsiTask checkTask = +// new CheckGsiTask(schemaName, baseTableName, indexName, lockMode, lockMode, params, false, "", +// isPrimaryBroadCast, isGsiBroadCast, virtualColumnMap, backfillColumnMap); +// +// checkTask.checkInBackfill(executionContext); + } + + return new AffectRowCursor(affectRows); + } + + public static String getPrimaryTableName(String schemaName, String baseTableName, boolean mirrorCopy, + ExecutionContext executionContext) { + String primaryTableName = baseTableName; + TableMeta sourceTableMeta = executionContext.getSchemaManager(schemaName).getTable(baseTableName); + if (mirrorCopy && sourceTableMeta.isGsi()) { + primaryTableName = sourceTableMeta.getGsiTableMetaBean().gsiMetaBean.tableName; + } + return primaryTableName; + } + +} diff --git a/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/LogicalBaselineHandler.java b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/LogicalBaselineHandler.java index 7a3ac9b3f..fb6533bd7 100644 --- a/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/LogicalBaselineHandler.java +++ b/polardbx-executor/src/main/java/com/alibaba/polardbx/repo/mysql/handler/LogicalBaselineHandler.java @@ -19,34 +19,44 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.executor.PlanExecutor; import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.cursor.ResultCursor; import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; import com.alibaba.polardbx.executor.handler.HandlerCommon; import com.alibaba.polardbx.executor.planmanagement.BaselineSyncController; import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.sync.BaselineDeleteHotEvolvedSyncAction; import com.alibaba.polardbx.executor.sync.BaselineLoadSyncAction; import com.alibaba.polardbx.executor.sync.BaselinePersistSyncAction; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; import com.alibaba.polardbx.gms.sync.SyncScope; +import com.alibaba.polardbx.executor.utils.ExplainExecutorUtil; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan; import com.alibaba.polardbx.optimizer.core.planner.Planner; import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; -import com.alibaba.polardbx.optimizer.core.rel.DirectTableOperation; import com.alibaba.polardbx.optimizer.core.rel.dal.LogicalBaseline; +import com.alibaba.polardbx.optimizer.core.row.Row; import com.alibaba.polardbx.optimizer.hint.util.HintConverter; import com.alibaba.polardbx.optimizer.planmanager.BaselineInfo; import com.alibaba.polardbx.optimizer.planmanager.PlanInfo; import com.alibaba.polardbx.optimizer.planmanager.PlanManager; import com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil; +import com.alibaba.polardbx.optimizer.utils.ExplainResult; import com.alibaba.polardbx.optimizer.utils.RelUtils; import com.alibaba.polardbx.optimizer.workload.WorkloadType; +import com.alibaba.polardbx.stats.metric.FeatureStats; +import com.alibaba.polardbx.stats.metric.FeatureStatsItem; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptSchema; +import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.rel.RelNode; import org.apache.calcite.sql.SqlBaseline; +import org.apache.calcite.sql.SqlExplainFormat; +import org.apache.calcite.sql.SqlExplainLevel; import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.util.trace.CalcitePlanOptimizerTrace; import java.util.ArrayList; import java.util.HashSet; @@ -56,6 +66,7 @@ import java.util.Set; import static com.alibaba.polardbx.common.exception.code.ErrorCode.ERR_BASELINE; +import static com.alibaba.polardbx.stats.metric.FeatureStatsItem.FIX_PLAN_NUM; public class LogicalBaselineHandler extends HandlerCommon { @@ -63,7 +74,7 @@ public LogicalBaselineHandler(IRepository repo) { super(repo); } - enum BASELINE_OPERATION { + public enum BASELINE_OPERATION { LIST("List all baseline infos", "baseline list"), ADD_FIX("Make plan modified by HINT externalized in baseline", "BASELINE (ADD|FIX) SQL @@ -188,51 +196,88 @@ class TaskList extends React.Component { } }); - return ( -
- - - - - - - - - - {/**/} - - - - - - {renderedTasks} -
IDHostStateOutputRowsInputRowsinputBytesElapsedDeliveryProcessDataFinish
- ); + // separate each stage + let stageTaskMap = new Map(); + tasks.forEach(task => { + let taskId = getTaskIdSuffix(task.taskStatus.taskId); + // find stageId, like: 0.0 and 0.1 => 0 + let stageId = taskId.substring(0, taskId.indexOf('.')); + + if (!stageTaskMap.has(stageId)) { + stageTaskMap.set(stageId, []); + } + + stageTaskMap.get(stageId).push(task); + }); + + const stageKeys = Array.from(stageTaskMap.keys()); + stageKeys.sort((a, b) => { + const numA = Number(a); + const numB = Number(b); + return numA - numB; + }); + // console.debug("stages: " + stageKeys); + + var renderedStages = []; + for (const stageId of stageKeys) { + const taskList = stageTaskMap.get(stageId); + if (!taskList) { + continue; + } + const tableId = "stage-" + stageId; + // console.debug("Rendering table:" + tableId); + renderedStages.push( +
+

+ this.openStageDetail(event, Number(stageId))}>{tableId} +

+ + + + + + + + + + + {/**/} + + + + + + {renderTasks(taskList)} +
IDHostStateOutputRowsInputRowsinputBytesElapsedDeliveryProcessDataFinish
+
); + } + + return renderedStages; } } @@ -272,6 +317,14 @@ class SplitList extends React.Component { } } + openStageDetail(event, id: number) { + const queryId = this.props.queryId; + this.setState({ selectedStageId: id }); + const url : string = "/ui/stage.html?" + queryId + "." + id; + event.preventDefault(); + window.open(url, '_blank'); + } + render() { const splits = this.props.splits; @@ -282,7 +335,7 @@ class SplitList extends React.Component { ); } - const renderedSplits = splits.map(split => { + const renderSplits = (splitList) => splitList.map(split => { return ( @@ -310,35 +363,79 @@ class SplitList extends React.Component { ); }); - return ( - - - - {/**/} - - - {/**/} - - - - - {renderedSplits} -
IDStateOutputRowsInputRowsinputBytesElapsedBlockedProcess
- ); + // separate each pipeline + let pipelineSplitMap = new Map(); + splits.forEach(split => { + let driverId = getFullSplitIdSuffix(split.driverId) + let pipelineId = getStagePipelineFromDriverId(driverId); + + if (!pipelineSplitMap.has(pipelineId)) { + pipelineSplitMap.set(pipelineId, []); + } + + pipelineSplitMap.get(pipelineId).push(split); + }); + + const pipelineKeys = Array.from(pipelineSplitMap.keys()); + pipelineKeys.sort((a, b) => { + const parts1 = a.split('.'); + const parts2 = b.split('.'); + const stageId1 = Number(parts1[0]); + const pId1 = Number(parts1[1]); + const stageId2 = Number(parts2[0]); + const pId2 = Number(parts2[1]); + if (stageId1 !== stageId2) { + return stageId1 - stageId2; + } + + return pId1 - pId2; + }); + // console.debug("pipelines: " + pipelineKeys); + + var renderedSplits = []; + for (const pipelineId of pipelineKeys) { + const splitList = pipelineSplitMap.get(pipelineId); + const parts = pipelineId.split('.'); + const stageId = parts[0]; + const pId = parts[1]; + const tableId = "stage-" + stageId + "-pipeline-" + pId; + renderedSplits.push( +
+

+ this.openStageDetail(event, Number(stageId))}>{tableId} +

+ + + + {/**/} + + + {/**/} + + + + + {renderSplits(splitList)} +
IDStateOutputRowsInputRowsinputBytesElapsedBlockedProcess
+
+ ); + } + + return renderedSplits; } } @@ -1107,7 +1204,7 @@ export class QueryDetail extends React.Component { } getSplitsFromStage(stage) { - console.log("getting splits from stage"); + // console.debug("getting splits from stage" + stage); let tasks = this.getTasksFromStage(stage); let splits = [] for (let i = 0; i < tasks.length; i++) { @@ -1167,7 +1264,7 @@ export class QueryDetail extends React.Component {
-

Splits

+

Splits

@@ -1196,7 +1293,7 @@ export class QueryDetail extends React.Component {
- +
@@ -1217,7 +1314,7 @@ export class QueryDetail extends React.Component {
-

Tasks

+

Tasks

@@ -1249,7 +1346,7 @@ export class QueryDetail extends React.Component {
- +
@@ -1265,7 +1362,7 @@ export class QueryDetail extends React.Component {
-

Stages

+

Stages

@@ -1324,7 +1421,7 @@ export class QueryDetail extends React.Component { for (var property in query.session.userDefVariables) { if (query.session.userDefVariables.hasOwnProperty(property)) { properties.push( - - {property + "=" + query.session.userDefVariables[property]}
+ - {property + "=" + query.session.userDefVariables[property]}
); } } @@ -1339,7 +1436,7 @@ export class QueryDetail extends React.Component { for (var property in query.session.serverVariables) { if (query.session.serverVariables.hasOwnProperty(property)) { properties.push( - - {property + "=" + query.session.serverVariables[property]}
+ - {property + "=" + query.session.serverVariables[property]}
); } } @@ -1419,7 +1516,7 @@ export class QueryDetail extends React.Component {
-

Session

+

Session


@@ -1475,7 +1572,7 @@ export class QueryDetail extends React.Component {
-

Execution

+

Execution


@@ -1527,7 +1624,7 @@ export class QueryDetail extends React.Component {
-

Resource Utilization Summary

+

Resource Utilization Summary


@@ -1685,7 +1782,7 @@ export class QueryDetail extends React.Component { {this.renderFailureInfo()}
-

+

Query diff --git a/polardbx-executor/src/main/resources/webapp/src/components/WorkerStatus.jsx b/polardbx-executor/src/main/resources/webapp/src/components/WorkerStatus.jsx index 2d9add126..da5582fdf 100644 --- a/polardbx-executor/src/main/resources/webapp/src/components/WorkerStatus.jsx +++ b/polardbx-executor/src/main/resources/webapp/src/components/WorkerStatus.jsx @@ -54,25 +54,47 @@ export class WorkerStatus extends React.Component { refreshLoop() { clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously const nodeId = getFirstParameter(window.location.search); - $.get('/v1/worker/' + nodeId + '/status', function (serverInfo) { - this.setState({ - serverInfo: serverInfo, - initialized: true, + if (nodeId) { + $.get('/v1/worker/' + nodeId + '/status', function (serverInfo) { + this.setState({ + serverInfo: serverInfo, + initialized: true, - processCpuLoad: addToHistory(serverInfo.processCpuLoad * 100.0, this.state.processCpuLoad), - systemCpuLoad: addToHistory(serverInfo.systemCpuLoad * 100.0, this.state.systemCpuLoad), - heapPercentUsed: addToHistory(serverInfo.heapUsed * 100.0 / serverInfo.heapAvailable, this.state.heapPercentUsed), - nonHeapUsed: addToHistory(serverInfo.nonHeapUsed * 100.0, this.state.nonHeapUsed), - }); + processCpuLoad: addToHistory(serverInfo.processCpuLoad * 100.0, this.state.processCpuLoad), + systemCpuLoad: addToHistory(serverInfo.systemCpuLoad * 100.0, this.state.systemCpuLoad), + heapPercentUsed: addToHistory(serverInfo.heapUsed * 100.0 / serverInfo.heapAvailable, this.state.heapPercentUsed), + nonHeapUsed: addToHistory(serverInfo.nonHeapUsed * 100.0, this.state.nonHeapUsed), + }); - this.resetTimer(); - }.bind(this)) - .error(function () { + this.resetTimer(); + }.bind(this)) + .error(function () { this.setState({ initialized: true, }); this.resetTimer(); - }.bind(this)); + }.bind(this)); + } else { + $.get('/v1/status', function (serverInfo) { + this.setState({ + serverInfo: serverInfo, + initialized: true, + + processCpuLoad: addToHistory(serverInfo.processCpuLoad * 100.0, this.state.processCpuLoad), + systemCpuLoad: addToHistory(serverInfo.systemCpuLoad * 100.0, this.state.systemCpuLoad), + heapPercentUsed: addToHistory(serverInfo.heapUsed * 100.0 / serverInfo.heapAvailable, this.state.heapPercentUsed), + nonHeapUsed: addToHistory(serverInfo.nonHeapUsed * 100.0, this.state.nonHeapUsed), + }); + + this.resetTimer(); + }.bind(this)) + .error(function () { + this.setState({ + initialized: true, + }); + this.resetTimer(); + }.bind(this)); + } } componentDidMount() { diff --git a/polardbx-executor/src/main/resources/webapp/src/components/WorkerThreadList.jsx b/polardbx-executor/src/main/resources/webapp/src/components/WorkerThreadList.jsx index 9e80f1ab3..4c2f9c208 100644 --- a/polardbx-executor/src/main/resources/webapp/src/components/WorkerThreadList.jsx +++ b/polardbx-executor/src/main/resources/webapp/src/components/WorkerThreadList.jsx @@ -43,18 +43,33 @@ export class WorkerThreadList extends React.Component { captureSnapshot() { const nodeId = getFirstParameter(window.location.search); - $.get('/v1/worker/' + nodeId + '/thread', function (threads) { - this.setState({ - threads: WorkerThreadList.processThreads(threads), - snapshotTime: new Date(), - initialized: true, - }); - }.bind(this)) - .error(function () { + if (nodeId) { + $.get('/v1/worker/' + nodeId + '/thread', function (threads) { this.setState({ + threads: WorkerThreadList.processThreads(threads), + snapshotTime: new Date(), initialized: true, }); - }.bind(this)); + }.bind(this)) + .error(function () { + this.setState({ + initialized: true, + }); + }.bind(this)); + } else { + $.get('/v1/thread', function (threads) { + this.setState({ + threads: WorkerThreadList.processThreads(threads), + snapshotTime: new Date(), + initialized: true, + }); + }.bind(this)) + .error(function () { + this.setState({ + initialized: true, + }); + }.bind(this)); + } } componentDidUpdate() { diff --git a/polardbx-executor/src/main/resources/webapp/src/pipeline.jsx b/polardbx-executor/src/main/resources/webapp/src/pipeline.jsx deleted file mode 100644 index 0179120a3..000000000 --- a/polardbx-executor/src/main/resources/webapp/src/pipeline.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from "react"; -import ReactDOM from "react-dom"; -import {PipelinePlan} from "./components/Pipeline"; -import {PageTitle} from "./components/PageTitle"; -import {getFirstParameter} from "./utils"; - -ReactDOM.render( - , - document.getElementById('title') -); - -ReactDOM.render( - , - document.getElementById('live-plan-container') -); diff --git a/polardbx-executor/src/main/resources/webapp/src/utils.js b/polardbx-executor/src/main/resources/webapp/src/utils.js index 73317b065..ac46db573 100644 --- a/polardbx-executor/src/main/resources/webapp/src/utils.js +++ b/polardbx-executor/src/main/resources/webapp/src/utils.js @@ -296,6 +296,14 @@ export function getTaskIdSuffix(taskId: string): string return taskId.slice(taskId.indexOf('.') + 1, taskId.length) } +export function getStagePipelineFromDriverId(driverId: string): string +{ + const parts = driverId.split('.'); + const extracts = [parts[0], parts[2]]; + const resultString = extracts.join('.'); + return resultString +} + export function getFullSplitIdSuffix(driverId: string): string { return driverId.substring(driverId.indexOf('.') + 1) diff --git a/polardbx-executor/src/main/resources/webapp/src/webpack.config.js b/polardbx-executor/src/main/resources/webapp/src/webpack.config.js index 4186bc0a3..0fea9cfb0 100644 --- a/polardbx-executor/src/main/resources/webapp/src/webpack.config.js +++ b/polardbx-executor/src/main/resources/webapp/src/webpack.config.js @@ -3,7 +3,6 @@ module.exports = { 'index': __dirname + '/index.jsx', 'query': __dirname + '/query.jsx', 'plan': __dirname + '/plan.jsx', - 'pipeline': __dirname + '/pipeline.jsx', 'embedded_plan': __dirname + '/embedded_plan.jsx', 'stage': __dirname + '/stage.jsx', 'worker': __dirname + '/worker.jsx', diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/GlobalIndexMetaTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/GlobalIndexMetaTest.java new file mode 100644 index 000000000..25cadecb6 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/GlobalIndexMetaTest.java @@ -0,0 +1,49 @@ +/* + * 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 com.alibaba.polardbx; + +import com.alibaba.polardbx.common.jdbc.Parameters; +import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.LogicalInsert; +import com.alibaba.polardbx.repo.mysql.handler.LogicalInsertHandler; +import org.junit.Test; +import org.mockito.MockedStatic; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class GlobalIndexMetaTest { + @Test + public void isExecuteIndexTest() { + try (MockedStatic globalIndexMeta = mockStatic(GlobalIndexMeta.class)) { + LogicalInsertHandler handler = new LogicalInsertHandler(null); + LogicalInsert logicalInsert = mock(LogicalInsert.class); + ExecutionContext executionContext = mock(ExecutionContext.class); + Parameters parameters = mock(Parameters.class); + when(logicalInsert.hasHint()).thenReturn(false); + when(executionContext.getParams()).thenReturn(parameters); + globalIndexMeta.when(() -> GlobalIndexMeta.hasGsi("schemaName", "tableName", executionContext)) + .thenReturn(true); + handler.isExecuteIndex(logicalInsert, executionContext, "schemaName", "tableName"); + } + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/MPPQueryMonitorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/MPPQueryMonitorTest.java new file mode 100644 index 000000000..a9f19bb3b --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/MPPQueryMonitorTest.java @@ -0,0 +1,79 @@ +package com.alibaba.polardbx.executor; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.mpp.client.LocalStatementClient; +import com.alibaba.polardbx.executor.mpp.client.MppResultCursor; +import com.alibaba.polardbx.executor.mpp.client.MppRunner; +import com.alibaba.polardbx.gms.node.GmsNodeManager; +import com.alibaba.polardbx.gms.node.MPPQueryMonitor; +import com.alibaba.polardbx.gms.sync.SyncScope; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.CursorMeta; +import com.alibaba.polardbx.optimizer.memory.MemoryPool; +import com.alibaba.polardbx.optimizer.spill.QuerySpillSpaceMonitor; +import org.apache.calcite.rel.RelNode; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MPPQueryMonitorTest { + @Test + public void test() { + + try (MockedStatic mockedConfigDataMode = Mockito.mockStatic(ConfigDataMode.class); + MockedStatic mockedGmsNodeManager = Mockito.mockStatic(GmsNodeManager.class); + MockedStatic mockedMppRunner = Mockito.mockStatic(MppRunner.class) + ) { + + mockedConfigDataMode.when(() -> ConfigDataMode.isMasterMode()).thenReturn(true); + GmsNodeManager gmsNodeManager = Mockito.mock(GmsNodeManager.class); + mockedGmsNodeManager.when(() -> GmsNodeManager.getInstance()).thenReturn(gmsNodeManager); + + // three nodes in master cluster. + List nodes = new ArrayList<>(); + nodes.add(Mockito.mock(GmsNodeManager.GmsNode.class)); + nodes.add(Mockito.mock(GmsNodeManager.GmsNode.class)); + nodes.add(Mockito.mock(GmsNodeManager.GmsNode.class)); + Mockito.when(gmsNodeManager.getNodesBySyncScope(Mockito.any(SyncScope.class))).thenReturn(nodes); + + MPPQueryMonitor mppQueryMonitor = MPPQueryMonitor.getInstance(); + + Map extraCmd = new HashMap(); + extraCmd.put(ConnectionParams.COLUMNAR_CLUSTER_MAXIMUM_QPS.getName(), 1000); + extraCmd.put(ConnectionParams.COLUMNAR_CLUSTER_MAXIMUM_CONCURRENCY.getName(), 8); + extraCmd.put(ConnectionParams.COLUMNAR_QPS_WINDOW_PERIOD.getName(), 1000); + ParamManager paramManager = new ParamManager(extraCmd); + ExecutionContext executionContext = new ExecutionContext(); + executionContext.setParamManager(paramManager); + executionContext.setMemoryPool(Mockito.mock(MemoryPool.class)); + executionContext.setQuerySpillSpaceMonitor(Mockito.mock(QuerySpillSpaceMonitor.class)); + + RelNode plan = Mockito.mock(RelNode.class); + MppRunner mppRunner = Mockito.mock(MppRunner.class); + mockedMppRunner.when(() -> MppRunner.create(Mockito.any(), Mockito.any())).thenReturn(mppRunner); + + MppResultCursor mppResultCursor = + new MppResultCursor(Mockito.mock(LocalStatementClient.class), executionContext, Mockito.mock( + CursorMeta.class)); + + Mockito.when(mppRunner.execute()).thenReturn(mppResultCursor); + Cursor cursor = ExecutorHelper.executeCluster(plan, executionContext); + System.out.println(mppQueryMonitor.getQueryConcurrency()); + cursor.close(null); + + System.out.println(mppQueryMonitor.calculateQPS( + executionContext.getParamManager().getLong(ConnectionParams.COLUMNAR_QPS_WINDOW_PERIOD))); + System.out.println(mppQueryMonitor.getQueryConcurrency()); + } + + } + +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/AccumulatorBuildTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/AccumulatorBuildTest.java new file mode 100644 index 000000000..a1cb5030d --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/AccumulatorBuildTest.java @@ -0,0 +1,195 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.AvgV2; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.BitOr; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.BitXor; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CheckSum; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CheckSumMerge; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CheckSumV2; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CheckSumV2Merge; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CountV2; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.FinalHyperLoglog; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.HyperLoglog; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.InternalFirstValue; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.MaxV2; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.MinV2; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.PartialHyperLoglog; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.Sum0; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.SumV2; +import org.junit.Test; + +public class AccumulatorBuildTest { + + @Test + public void testCountAccumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new CountV2(new int[] {0}, false, null, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, 100, getExecutionContext()); + Assert.assertTrue(accumulator instanceof CountAccumulator); + + Accumulator accumulator2 = + AccumulatorBuilders.create(new CountV2(new int[0], false, null, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, 100, getExecutionContext()); + Assert.assertTrue(accumulator2 instanceof CountRowsAccumulator); + } + + @Test + public void testSumAccumulator() { + Accumulator longAccumulator = + AccumulatorBuilders.create(new SumV2(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, 100, + getExecutionContext()); + Assert.assertTrue(longAccumulator instanceof LongSumAccumulator); + + Accumulator decimalAccumulator = + AccumulatorBuilders.create(new SumV2(), DataTypes.DecimalType, new DataType[] {DataTypes.DecimalType}, 100, + getExecutionContext()); + Assert.assertTrue(decimalAccumulator instanceof DecimalSumAccumulator); + + Accumulator doubleAccumulator = + AccumulatorBuilders.create(new SumV2(), DataTypes.DoubleType, new DataType[] {DataTypes.DoubleType}, 100, + getExecutionContext()); + Assert.assertTrue(doubleAccumulator instanceof DoubleSumAccumulator); + } + + @Test + public void testSum0Accumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new Sum0(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, 100, + getExecutionContext()); + Assert.assertTrue(accumulator instanceof LongSum0Accumulator); + } + + @Test + public void testMinMaxAccumulator() { + Accumulator longAccumulator = + AccumulatorBuilders.create(new MinV2(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, 100, + getExecutionContext()); + Assert.assertTrue(longAccumulator instanceof LongMaxMinAccumulator); + Accumulator longAccumulator2 = + AccumulatorBuilders.create(new MaxV2(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, 100, + getExecutionContext()); + Assert.assertTrue(longAccumulator2 instanceof LongMaxMinAccumulator); + + Accumulator decimalAccumulator = + AccumulatorBuilders.create(new MinV2(), DataTypes.DecimalType, new DataType[] {DataTypes.DecimalType}, 100, + getExecutionContext()); + Assert.assertTrue(decimalAccumulator instanceof DecimalMaxMinAccumulator); + Accumulator decimalAccumulator2 = + AccumulatorBuilders.create(new MaxV2(), DataTypes.DecimalType, new DataType[] {DataTypes.DecimalType}, 100, + getExecutionContext()); + Assert.assertTrue(decimalAccumulator2 instanceof DecimalMaxMinAccumulator); + + Accumulator doubleAccumulator = + AccumulatorBuilders.create(new MinV2(), DataTypes.DoubleType, new DataType[] {DataTypes.DoubleType}, 100, + getExecutionContext()); + Assert.assertTrue(doubleAccumulator instanceof DoubleMaxMinAccumulator); + Accumulator doubleAccumulator2 = + AccumulatorBuilders.create(new MaxV2(), DataTypes.DoubleType, new DataType[] {DataTypes.DoubleType}, 100, + getExecutionContext()); + Assert.assertTrue(doubleAccumulator2 instanceof DoubleMaxMinAccumulator); + } + + @Test + public void testAvgAccumulator() { + Accumulator decimalAccumulator = + AccumulatorBuilders.create(new AvgV2(0, false, null, -1), DataTypes.DecimalType, + new DataType[] {DataTypes.DecimalType}, 100, getExecutionContext()); + Assert.assertTrue(decimalAccumulator instanceof DecimalAvgAccumulator); + + Accumulator doubleAccumulator = + AccumulatorBuilders.create(new AvgV2(0, false, null, -1), DataTypes.DoubleType, + new DataType[] {DataTypes.DoubleType}, 100, getExecutionContext()); + Assert.assertTrue(doubleAccumulator instanceof DoubleAvgAccumulator); + } + + @Test + public void testBitOrAccumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new BitOr(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, 100, + getExecutionContext()); + Assert.assertTrue(accumulator instanceof LongBitOrAccumulator); + } + + @Test + public void testBitXorAccumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new BitXor(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, 100, + getExecutionContext()); + Assert.assertTrue(accumulator instanceof LongBitXorAccumulator); + } + + @Test + public void testFirstValueAccumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new InternalFirstValue(0, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, 100, getExecutionContext()); + Assert.assertTrue(accumulator instanceof FirstValueAccumulator); + } + + @Test + public void testHllAccumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new HyperLoglog(new int[] {0}, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, 100, getExecutionContext()); + Assert.assertTrue(accumulator instanceof HyperLogLogAccumulator); + } + + @Test + public void testPartialHllAccumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new PartialHyperLoglog(new int[] {0}, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, 100, getExecutionContext()); + Assert.assertTrue(accumulator instanceof PartialHyperLogLogAccumulator); + } + + @Test + public void testFinalHllAccumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new FinalHyperLoglog(new int[] {0}, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, 100, getExecutionContext()); + Assert.assertTrue(accumulator instanceof FinalHyperLogLogAccumulator); + } + + @Test + public void testCheckSumAccumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new CheckSum(new int[] {0}, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, 100, getExecutionContext()); + Assert.assertTrue(accumulator instanceof CheckSumAccumulator); + } + + @Test + public void testCheckSumMergeAccumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new CheckSumMerge(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, + 100, getExecutionContext()); + Assert.assertTrue(accumulator instanceof CheckSumMergeAccumulator); + } + + @Test + public void testCheckSumV2Accumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new CheckSumV2(new int[] {0}, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, 100, getExecutionContext()); + Assert.assertTrue(accumulator instanceof CheckSumV2Accumulator); + } + + @Test + public void testCheckSumV2MergeAccumulator() { + Accumulator accumulator = + AccumulatorBuilders.create(new CheckSumV2Merge(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, + 100, getExecutionContext()); + Assert.assertTrue(accumulator instanceof CheckSumV2MergeAccumulator); + } + + private ExecutionContext getExecutionContext() { + ExecutionContext executionContext = new ExecutionContext(); + executionContext.setSchemaName("test_accumulator"); + return executionContext; + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/BitOrAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/BitOrAccumulatorTest.java new file mode 100644 index 000000000..75c864dbe --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/BitOrAccumulatorTest.java @@ -0,0 +1,63 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.ByteArrayBlock; +import com.alibaba.polardbx.executor.chunk.ByteArrayBlockBuilder; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.executor.utils.ByteUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.BitOr; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.FinalHyperLoglog; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +public class BitOrAccumulatorTest { + + private static final int COUNT = 1024; + private LongBitOrAccumulator accumulator; + private Random random; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new BitOr(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, COUNT, + new ExecutionContext()); + + this.accumulator = (LongBitOrAccumulator) accumulator; + this.random = new Random(); + } + + @Test + public void testLongBitOr1Group() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + long result = 0; + for (int i = 0; i < COUNT - 1; i++) { + long l = random.nextLong(); + builder.writeLong(l); + result |= l; + } + builder.appendNull(); + LongBlock block = (LongBlock) builder.build(); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, block, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertEquals(result, resultBlock.getLong(0)); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/BitXorAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/BitXorAccumulatorTest.java new file mode 100644 index 000000000..445404887 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/BitXorAccumulatorTest.java @@ -0,0 +1,59 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.BitOr; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.BitXor; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +public class BitXorAccumulatorTest { + + private static final int COUNT = 1024; + private LongBitXorAccumulator accumulator; + private Random random; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new BitXor(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, COUNT, + new ExecutionContext()); + + this.accumulator = (LongBitXorAccumulator) accumulator; + this.random = new Random(); + } + + @Test + public void testLongBitOr1Group() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + long result = 0; + for (int i = 0; i < COUNT - 1; i++) { + long l = random.nextLong(); + builder.writeLong(l); + result ^= l; + } + builder.appendNull(); + LongBlock block = (LongBlock) builder.build(); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, block, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertEquals(result, resultBlock.getLong(0)); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumAccumulatorTest.java new file mode 100644 index 000000000..92e92cf37 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumAccumulatorTest.java @@ -0,0 +1,88 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.common.CrcAccumulator; +import com.alibaba.polardbx.common.OrderInvariantHasher; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CheckSum; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; +import java.util.zip.CRC32; + +public class CheckSumAccumulatorTest { + + private static final int COUNT = 1024; + private CheckSumAccumulator accumulator; + private Random random; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new CheckSum(new int[] {0}, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, + COUNT, new ExecutionContext()); + + this.accumulator = (CheckSumAccumulator) accumulator; + this.random = new Random(); + Assert.assertEquals(1, accumulator.getInputTypes().length); + } + + @Test + public void testCheckSumWith1Block1Group() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + OrderInvariantHasher hash = new OrderInvariantHasher(); + + for (int i = 0; i < COUNT - 1; i++) { + CRC32 crc = new CRC32(); + long l = random.nextLong(); + builder.writeLong(l); + int checksum = Long.hashCode(l); + crc.update(new byte[] { + (byte) (checksum >>> 24), (byte) (checksum >>> 16), (byte) (checksum >>> 8), (byte) checksum}); + crc.update(CrcAccumulator.SEPARATOR_TAG); + + hash.add(crc.getValue()); + } + builder.appendNull(); + CRC32 crc = new CRC32(); + crc.update(CrcAccumulator.NULL_TAG); + crc.update(CrcAccumulator.SEPARATOR_TAG); + hash.add(crc.getValue()); + + LongBlock block = (LongBlock) builder.build(); + Chunk chunk = new Chunk(block); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, chunk, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertEquals(hash.getResult().longValue(), resultBlock.getLong(0)); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } + + @Test + public void testCheckSumWithAllNull() { + accumulator.appendInitValue(); + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertTrue(resultBlock.isNull(0)); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumMergeAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumMergeAccumulatorTest.java new file mode 100644 index 000000000..464dd2ec6 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumMergeAccumulatorTest.java @@ -0,0 +1,75 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.common.OrderInvariantHasher; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CheckSumMerge; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +public class CheckSumMergeAccumulatorTest { + + private static final int COUNT = 1024; + private CheckSumMergeAccumulator accumulator; + private Random random; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new CheckSumMerge(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, + COUNT, new ExecutionContext()); + + this.accumulator = (CheckSumMergeAccumulator) accumulator; + this.random = new Random(); + } + + @Test + public void testCheckSumMerge1Group() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + OrderInvariantHasher hash = new OrderInvariantHasher(); + + for (int i = 0; i < COUNT - 1; i++) { + long l = random.nextLong(); + builder.writeLong(l); + hash.add(l); + } + builder.appendNull(); + // no need to add hasher for null + + LongBlock block = (LongBlock) builder.build(); + Chunk chunk = new Chunk(block); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, chunk, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertEquals(hash.getResult().longValue(), resultBlock.getLong(0)); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } + + @Test + public void testCheckSumMergeWithAllNull() { + accumulator.appendInitValue(); + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertTrue(resultBlock.isNull(0)); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumV2AccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumV2AccumulatorTest.java new file mode 100644 index 000000000..67a783f1d --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumV2AccumulatorTest.java @@ -0,0 +1,88 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.common.CrcAccumulator; +import com.alibaba.polardbx.common.RevisableOrderInvariantHash; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CheckSumV2; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; +import java.util.zip.CRC32; + +public class CheckSumV2AccumulatorTest { + + private static final int COUNT = 1024; + private CheckSumV2Accumulator accumulator; + private Random random; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new CheckSumV2(new int[] {0}, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, + COUNT, new ExecutionContext()); + + this.accumulator = (CheckSumV2Accumulator) accumulator; + this.random = new Random(); + Assert.assertEquals(1, accumulator.getInputTypes().length); + } + + @Test + public void testCheckSumV2With1Block1Group() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + RevisableOrderInvariantHash hash = new RevisableOrderInvariantHash(); + + for (int i = 0; i < COUNT - 1; i++) { + CRC32 crc = new CRC32(); + long l = random.nextLong(); + builder.writeLong(l); + int checksum = Long.hashCode(l); + crc.update(new byte[] { + (byte) (checksum >>> 24), (byte) (checksum >>> 16), (byte) (checksum >>> 8), (byte) checksum}); + crc.update(CrcAccumulator.SEPARATOR_TAG); + + hash.add(crc.getValue()); + } + builder.appendNull(); + CRC32 crc = new CRC32(); + crc.update(CrcAccumulator.NULL_TAG); + crc.update(CrcAccumulator.SEPARATOR_TAG); + hash.add(crc.getValue()); + + LongBlock block = (LongBlock) builder.build(); + Chunk chunk = new Chunk(block); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, chunk, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertEquals(hash.getResult().longValue(), resultBlock.getLong(0)); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } + + @Test + public void testCheckSumV2WithAllNull() { + accumulator.appendInitValue(); + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertTrue(resultBlock.isNull(0)); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumV2MergeAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumV2MergeAccumulatorTest.java new file mode 100644 index 000000000..a2221be6c --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CheckSumV2MergeAccumulatorTest.java @@ -0,0 +1,75 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.common.RevisableOrderInvariantHash; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CheckSumV2Merge; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +public class CheckSumV2MergeAccumulatorTest { + + private static final int COUNT = 1024; + private CheckSumV2MergeAccumulator accumulator; + private Random random; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new CheckSumV2Merge(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, + COUNT, new ExecutionContext()); + + this.accumulator = (CheckSumV2MergeAccumulator) accumulator; + this.random = new Random(); + } + + @Test + public void testCheckSumV2Merge1Group() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + RevisableOrderInvariantHash hash = new RevisableOrderInvariantHash(); + + for (int i = 0; i < COUNT - 1; i++) { + long l = random.nextLong(); + builder.writeLong(l); + hash.add(l).remove(0); + } + builder.appendNull(); + hash.add(0).remove(0); + + LongBlock block = (LongBlock) builder.build(); + Chunk chunk = new Chunk(block); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, chunk, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertEquals(hash.getResult().longValue(), resultBlock.getLong(0)); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } + + @Test + public void testCheckSumV2MergeWithAllNull() { + accumulator.appendInitValue(); + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertTrue(resultBlock.isNull(0)); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CountRowsAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CountRowsAccumulatorTest.java new file mode 100644 index 000000000..3aa66c1b5 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/CountRowsAccumulatorTest.java @@ -0,0 +1,156 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CountV2; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class CountRowsAccumulatorTest { + + private static final int COUNT = 1024; + private CountRowsAccumulator accumulator; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new CountV2(new int[0], false, null, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, COUNT, + new ExecutionContext()); + + this.accumulator = (CountRowsAccumulator) accumulator; + Assert.assertEquals(0, accumulator.getInputTypes().length); + } + + @Test + public void testCountRows2Group() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + for (int i = 0; i < COUNT - 1; i++) { + builder.writeLong(i); + } + builder.appendNull(); + + LongBlock block = (LongBlock) builder.build(); + + accumulator.appendInitValue(); + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + accumulator.writeResultTo(1, resultBuilder); + Block resultBlock = resultBuilder.build(); + + Assert.assertEquals(2, resultBlock.getPositionCount()); + Assert.assertEquals(COUNT, resultBlock.getLong(0)); + Assert.assertEquals(0, resultBlock.getLong(1)); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } + + @Test + public void testCountRows2GroupWithStartEnd() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + for (int i = 0; i < COUNT - 1; i++) { + builder.writeLong(i); + } + builder.appendNull(); + + int offset = COUNT / 2; + + LongBlock block = (LongBlock) builder.build(); + Chunk chunk = new Chunk(block); + accumulator.appendInitValue(); + accumulator.appendInitValue(); + accumulator.accumulate(0, chunk, 0, offset); + accumulator.accumulate(1, chunk, offset, COUNT); + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + accumulator.writeResultTo(1, resultBuilder); + Block resultBlock = resultBuilder.build(); + + Assert.assertEquals(2, resultBlock.getPositionCount()); + Assert.assertEquals(offset, resultBlock.getLong(0)); + Assert.assertEquals(COUNT - offset, resultBlock.getLong(1)); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } + + @Test + public void testCountRowsWithGroupId() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + for (int i = 0; i < COUNT - 1; i++) { + builder.writeLong(i); + } + builder.appendNull(); + + int[] groupIds = new int[COUNT]; + for (int i = 0; i < COUNT; i++) { + groupIds[i] = i % 2; + } + + LongBlock block = (LongBlock) builder.build(); + Chunk chunk = new Chunk(block); + accumulator.appendInitValue(); + accumulator.appendInitValue(); + accumulator.accumulate(groupIds, chunk, COUNT); + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + accumulator.writeResultTo(1, resultBuilder); + Block resultBlock = resultBuilder.build(); + + Assert.assertEquals(2, resultBlock.getPositionCount()); + Assert.assertEquals(COUNT / 2, resultBlock.getLong(0)); + Assert.assertEquals(COUNT / 2, resultBlock.getLong(1)); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } + + @Test + public void testCountRowsWithGroupIdSelection() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + for (int i = 0; i < COUNT - 1; i++) { + builder.writeLong(i); + } + builder.appendNull(); + + int[] group0Selection = new int[COUNT / 2]; + int[] group1Selection = new int[COUNT / 2]; + for (int i = 0; i < COUNT / 2; i++) { + group0Selection[i] = i * 2; + group1Selection[i] = i * 2 + 1; + } + + LongBlock block = (LongBlock) builder.build(); + Chunk chunk = new Chunk(block); + accumulator.appendInitValue(); + accumulator.appendInitValue(); + accumulator.accumulate(0, chunk, group0Selection, COUNT / 2); + accumulator.accumulate(1, chunk, group1Selection, COUNT / 2); + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + accumulator.writeResultTo(1, resultBuilder); + Block resultBlock = resultBuilder.build(); + + Assert.assertEquals(2, resultBlock.getPositionCount()); + Assert.assertEquals(COUNT / 2, resultBlock.getLong(0)); + Assert.assertEquals(COUNT / 2, resultBlock.getLong(1)); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalMaxMinAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalMaxMinAccumulatorTest.java new file mode 100644 index 000000000..c1daa0c2d --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalMaxMinAccumulatorTest.java @@ -0,0 +1,104 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.common.datatype.FastDecimalUtils; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.DecimalBlock; +import com.alibaba.polardbx.executor.chunk.DecimalBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.MaxV2; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.MinV2; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +public class DecimalMaxMinAccumulatorTest { + + private static final int COUNT = 1024; + private DecimalMaxMinAccumulator minAccumulator; + private DecimalMaxMinAccumulator maxAccumulator; + private Random random; + + @Before + public void before() { + Accumulator minAccumulator = + AccumulatorBuilders.create(new MinV2(), DataTypes.DecimalType, new DataType[] {DataTypes.DecimalType}, + COUNT, + new ExecutionContext()); + Accumulator maxAccumulator = + AccumulatorBuilders.create(new MaxV2(), DataTypes.DecimalType, new DataType[] {DataTypes.DecimalType}, + COUNT, + new ExecutionContext()); + + this.minAccumulator = (DecimalMaxMinAccumulator) minAccumulator; + this.maxAccumulator = (DecimalMaxMinAccumulator) maxAccumulator; + this.random = new Random(); + + Assert.assertEquals(1, minAccumulator.getInputTypes().length); + Assert.assertEquals(1, maxAccumulator.getInputTypes().length); + } + + /** + * Group0 has values + * Group1 has no values + */ + @Test + public void testMaxMin2Groups() { + final int scale = 2; + DecimalBlockBuilder builder = new DecimalBlockBuilder(COUNT); + + Decimal decimal = new Decimal(random.nextLong(), scale); + builder.writeDecimal(decimal); + Decimal min = decimal, max = decimal; + for (int i = 0; i < COUNT - 1; i++) { + decimal = new Decimal(random.nextLong(), scale); + builder.writeDecimal(decimal); + int minRes = FastDecimalUtils.compare(decimal.getDecimalStructure(), min.getDecimalStructure()); + if (minRes < 0) { + min = decimal; + } + int maxRes = FastDecimalUtils.compare(decimal.getDecimalStructure(), max.getDecimalStructure()); + if (maxRes > 0) { + max = decimal; + } + } + + DecimalBlock block = (DecimalBlock) builder.build(); + + minAccumulator.appendInitValue(); + minAccumulator.appendInitValue(); + maxAccumulator.appendInitValue(); + maxAccumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + minAccumulator.accumulate(0, block, i); + maxAccumulator.accumulate(0, block, i); + } + + DecimalBlockBuilder minResultBuilder = new DecimalBlockBuilder(COUNT); + DecimalBlockBuilder maxResultBuilder = new DecimalBlockBuilder(COUNT); + minAccumulator.writeResultTo(0, minResultBuilder); + minAccumulator.writeResultTo(1, minResultBuilder); + maxAccumulator.writeResultTo(0, maxResultBuilder); + maxAccumulator.writeResultTo(1, maxResultBuilder); + Block minResultBlock = minResultBuilder.build(); + Assert.assertEquals(2, minResultBlock.getPositionCount()); + Block maxResultBlock = maxResultBuilder.build(); + Assert.assertEquals(2, maxResultBuilder.getPositionCount()); + + Assert.assertEquals(0, FastDecimalUtils.compare(minResultBlock.getDecimal(0).getDecimalStructure(), + min.getDecimalStructure())); + Assert.assertEquals(0, FastDecimalUtils.compare(maxResultBlock.getDecimal(0).getDecimalStructure(), + max.getDecimalStructure())); + + Assert.assertTrue(minResultBlock.isNull(1)); + Assert.assertTrue(maxResultBlock.isNull(1)); + + Assert.assertTrue(minAccumulator.estimateSize() > 0); + Assert.assertTrue(maxAccumulator.estimateSize() > 0); + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DoubleMaxMinAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DoubleMaxMinAccumulatorTest.java new file mode 100644 index 000000000..9dc0a4151 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DoubleMaxMinAccumulatorTest.java @@ -0,0 +1,96 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.DoubleBlock; +import com.alibaba.polardbx.executor.chunk.DoubleBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.MaxV2; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.MinV2; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +public class DoubleMaxMinAccumulatorTest { + + private static final int COUNT = 1024; + private DoubleMaxMinAccumulator minAccumulator; + private DoubleMaxMinAccumulator maxAccumulator; + private Random random; + + @Before + public void before() { + Accumulator minAccumulator = + AccumulatorBuilders.create(new MinV2(), DataTypes.DoubleType, new DataType[] {DataTypes.DoubleType}, + COUNT, + new ExecutionContext()); + Accumulator maxAccumulator = + AccumulatorBuilders.create(new MaxV2(), DataTypes.DoubleType, new DataType[] {DataTypes.DoubleType}, + COUNT, + new ExecutionContext()); + + this.minAccumulator = (DoubleMaxMinAccumulator) minAccumulator; + this.maxAccumulator = (DoubleMaxMinAccumulator) maxAccumulator; + this.random = new Random(); + + Assert.assertEquals(1, minAccumulator.getInputTypes().length); + Assert.assertEquals(1, maxAccumulator.getInputTypes().length); + } + + /** + * Group0 has values + * Group1 has no values + */ + @Test + public void testMaxMin2Groups() { + DoubleBlockBuilder builder = new DoubleBlockBuilder(COUNT); + double d = random.nextDouble(); + builder.writeDouble(d); + double min = d, max = d; + for (int i = 0; i < COUNT - 1; i++) { + d = random.nextDouble(); + builder.writeDouble(d); + if (d < min) { + min = d; + } + if (d > max) { + max = d; + } + } + + DoubleBlock block = (DoubleBlock) builder.build(); + + minAccumulator.appendInitValue(); + minAccumulator.appendInitValue(); + maxAccumulator.appendInitValue(); + maxAccumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + minAccumulator.accumulate(0, block, i); + maxAccumulator.accumulate(0, block, i); + } + + DoubleBlockBuilder minResultBuilder = new DoubleBlockBuilder(COUNT); + DoubleBlockBuilder maxResultBuilder = new DoubleBlockBuilder(COUNT); + minAccumulator.writeResultTo(0, minResultBuilder); + minAccumulator.writeResultTo(1, minResultBuilder); + maxAccumulator.writeResultTo(0, maxResultBuilder); + maxAccumulator.writeResultTo(1, maxResultBuilder); + Block minResultBlock = minResultBuilder.build(); + Assert.assertEquals(2, minResultBlock.getPositionCount()); + Block maxResultBlock = maxResultBuilder.build(); + Assert.assertEquals(2, maxResultBuilder.getPositionCount()); + + Assert.assertEquals(min, minResultBlock.getDouble(0), 1e-10); + Assert.assertEquals(max, maxResultBlock.getDouble(0), 1e-10); + + Assert.assertTrue(minResultBlock.isNull(1)); + Assert.assertTrue(maxResultBlock.isNull(1)); + + Assert.assertTrue(minAccumulator.estimateSize() > 0); + Assert.assertTrue(maxAccumulator.estimateSize() > 0); + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DoubleSumAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DoubleSumAccumulatorTest.java new file mode 100644 index 000000000..4c11d9fe9 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DoubleSumAccumulatorTest.java @@ -0,0 +1,85 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.DoubleBlock; +import com.alibaba.polardbx.executor.chunk.DoubleBlockBuilder; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.SumV2; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +public class DoubleSumAccumulatorTest { + + private static final int COUNT = 1024; + private DoubleSumAccumulator accumulator; + private Random random; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new SumV2(), DataTypes.DoubleType, new DataType[] {DataTypes.DoubleType}, COUNT, + new ExecutionContext()); + + this.accumulator = (DoubleSumAccumulator) accumulator; + Assert.assertEquals(1, accumulator.getInputTypes().length); + + this.random = new Random(); + } + + @Test + public void testDoubleSum1Group() { + DoubleBlockBuilder builder = new DoubleBlockBuilder(COUNT); + double result = 0; + for (int i = 0; i < COUNT; i++) { + double d = random.nextDouble(); + builder.writeDouble(d); + result += d; + } + + DoubleBlock block = (DoubleBlock) builder.build(); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, block, i); + } + + DoubleBlockBuilder resultBuilder = new DoubleBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertEquals(result, resultBlock.getDouble(0), 1e-10); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } + + /** + * regards NULL as NULL rather than 0 + */ + @Test + public void testDoubleSumWithAllNull() { + DoubleBlockBuilder builder = new DoubleBlockBuilder(COUNT); + for (int i = 0; i < COUNT; i++) { + builder.appendNull(); + } + + DoubleBlock block = (DoubleBlock) builder.build(); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, block, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertTrue(resultBlock.isNull(0)); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/FinalHLLAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/FinalHLLAccumulatorTest.java new file mode 100644 index 000000000..de24594ba --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/FinalHLLAccumulatorTest.java @@ -0,0 +1,100 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.ByteArrayBlock; +import com.alibaba.polardbx.executor.chunk.ByteArrayBlockBuilder; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.executor.utils.ByteUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.FinalHyperLoglog; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +public class FinalHLLAccumulatorTest { + + private static final int COUNT = 1024; + private FinalHyperLogLogAccumulator accumulator; + private Random random; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new FinalHyperLoglog(new int[] {0}, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, COUNT, new ExecutionContext()); + + this.accumulator = (FinalHyperLogLogAccumulator) accumulator; + this.random = new Random(); + Assert.assertEquals(1, accumulator.getInputTypes().length); + } + + @Test + public void testFinalHLL1Group() { + ByteArrayBlockBuilder builder = new ByteArrayBlockBuilder(COUNT, 8); + for (int i = 0; i < COUNT - 1; i++) { + builder.writeByteArray(ByteUtil.toByteArray(random.nextLong())); + } + builder.appendNull(); + ByteArrayBlock block = (ByteArrayBlock) builder.build(); + Chunk chunk = new Chunk(block); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, chunk, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertTrue(resultBlock.getLong(0) > 0); + } + + @Test + public void testFinalHLL1NullInput() { + ByteArrayBlockBuilder builder = new ByteArrayBlockBuilder(COUNT, 8); + for (int i = 0; i < COUNT; i++) { + builder.appendNull(); + } + ByteArrayBlock block = (ByteArrayBlock) builder.build(); + Chunk chunk = new Chunk(block); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, chunk, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + } + + @Test + public void testFinalHLLWithIndex() { + ByteArrayBlockBuilder builder = new ByteArrayBlockBuilder(COUNT, 8); + for (int i = 0; i < COUNT - 1; i++) { + builder.writeByteArray(ByteUtil.toByteArray(random.nextLong())); + } + builder.appendNull(); + ByteArrayBlock block = (ByteArrayBlock) builder.build(); + Chunk chunk = new Chunk(block); + + accumulator.appendInitValue(); + accumulator.accumulate(0, chunk, 0, COUNT); + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertTrue(resultBlock.getLong(0) > 0); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/FirstValueAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/FirstValueAccumulatorTest.java new file mode 100644 index 000000000..951187eae --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/FirstValueAccumulatorTest.java @@ -0,0 +1,116 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.InternalFirstValue; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class FirstValueAccumulatorTest { + + private static final int COUNT = 100; + private FirstValueAccumulator accumulator; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new InternalFirstValue(0, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, COUNT, new ExecutionContext()); + this.accumulator = (FirstValueAccumulator) accumulator; + + Assert.assertEquals(1, accumulator.getInputTypes().length); + } + + @Test + public void testFirstValue1Group() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + for (int i = 0; i < COUNT; i++) { + builder.writeLong(i); + } + LongBlock block = (LongBlock) builder.build(); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, block, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertEquals(0, resultBlock.getLong(0)); + } + + @Test + public void testFirstValue2Groups() { + final int offset = 10; + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + for (int i = 0; i < COUNT; i++) { + builder.writeLong(i); + } + LongBlock block = (LongBlock) builder.build(); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, block, i); + accumulator.accumulate(1, block, (i + offset) % COUNT); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + accumulator.writeResultTo(1, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(2, resultBlock.getPositionCount()); + Assert.assertEquals(0, resultBlock.getLong(0)); + Assert.assertEquals(10, resultBlock.getLong(1)); + } + + @Test + public void testFirstValueManyGroups() { + final int groups = 2048; + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + for (int i = 0; i < COUNT; i++) { + builder.writeLong(i); + } + LongBlock block = (LongBlock) builder.build(); + + accumulator.appendInitValue(); + + for (int i = 0; i < block.getPositionCount(); i++) { + for (int j = 0; j < groups; j++) { + accumulator.accumulate(j, block, (i + j) % COUNT); + } + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + for (int i = 0; i < groups; i++) { + accumulator.writeResultTo(i, resultBuilder); + } + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(groups, resultBlock.getPositionCount()); + for (int i = 0; i < groups; i++) { + Assert.assertFalse(resultBuilder.isNull(i)); + Assert.assertEquals("Wrong result at position: " + i, i % COUNT, resultBlock.getLong(i)); + } + + long size = accumulator.estimateSize(); + Assert.assertTrue("Estimate size should be larger than 0", size > 0); + } + + @Test + public void testFirstValueNullInput() { + accumulator.appendInitValue(); + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertTrue(resultBlock.isNull(0)); + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/HLLAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/HLLAccumulatorTest.java new file mode 100644 index 000000000..984f11fb2 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/HLLAccumulatorTest.java @@ -0,0 +1,110 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.ByteArrayBlock; +import com.alibaba.polardbx.executor.chunk.ByteArrayBlockBuilder; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.executor.utils.ByteUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.HyperLoglog; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +public class HLLAccumulatorTest { + + private static final int COUNT = 1024; + private HyperLogLogAccumulator accumulator; + private Random random; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new HyperLoglog(new int[] {0}, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, COUNT, new ExecutionContext()); + + this.accumulator = (HyperLogLogAccumulator) accumulator; + this.random = new Random(); + Assert.assertEquals(1, accumulator.getInputTypes().length); + } + + @Test + public void testHLL1Group() { + ByteArrayBlockBuilder builder = new ByteArrayBlockBuilder(COUNT, 8); + for (int i = 0; i < COUNT - 1; i++) { + builder.writeByteArray(ByteUtil.toByteArray(random.nextLong())); + } + builder.appendNull(); + ByteArrayBlock block = (ByteArrayBlock) builder.build(); + Chunk chunk = new Chunk(block); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, chunk, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertFalse(resultBlock.isNull(0)); + } + + @Test + public void testHLL1NullInput() { + ByteArrayBlockBuilder builder = new ByteArrayBlockBuilder(COUNT, 8); + for (int i = 0; i < COUNT; i++) { + builder.appendNull(); + } + ByteArrayBlock block = (ByteArrayBlock) builder.build(); + Chunk chunk = new Chunk(block); + + accumulator.appendInitValue(); + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, chunk, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + accumulator.writeResultTo(1, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(2, resultBlock.getPositionCount()); + // group 1 has no values + Assert.assertEquals(0, resultBuilder.getLong(1)); + } + + @Test + public void testHLL2Blocks() { + ByteArrayBlockBuilder builder1 = new ByteArrayBlockBuilder(COUNT, 8); + ByteArrayBlockBuilder builder2 = new ByteArrayBlockBuilder(COUNT, 8); + for (int i = 0; i < COUNT - 1; i++) { + builder1.writeByteArray(ByteUtil.toByteArray(random.nextLong())); + builder2.writeByteArray(ByteUtil.toByteArray(random.nextLong())); + } + builder1.appendNull(); + ByteArrayBlock block1 = (ByteArrayBlock) builder1.build(); + ByteArrayBlock block2 = (ByteArrayBlock) builder1.build(); + Chunk chunk = new Chunk(block1, block2); + + accumulator.appendInitValue(); + for (int i = 0; i < chunk.getPositionCount(); i++) { + accumulator.accumulate(0, chunk, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertFalse(resultBlock.isNull(0)); + + Assert.assertTrue(accumulator.estimateSize() > 0); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/IllegalAccumulatorOpTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/IllegalAccumulatorOpTest.java new file mode 100644 index 000000000..2e21f59e8 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/IllegalAccumulatorOpTest.java @@ -0,0 +1,62 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CountV2; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.Sum0; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +/** + * Test illegal operations on certain accumulators + */ +public class IllegalAccumulatorOpTest { + + /** + * Some accumulators need argument, while some don't + */ + @Test + public void testIllegalAccumulateCall() { + Accumulator accumulator = + AccumulatorBuilders.create(new Sum0(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, 100, + new ExecutionContext()); + Assert.assertTrue(accumulator instanceof LongSum0Accumulator); + try { + ((LongSum0Accumulator) accumulator).accumulate(0); + Assert.fail("Expect exception here"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("not implemented")); + } + + Accumulator accumulator2 = + AccumulatorBuilders.create(new CountV2(new int[0], false, null, 0), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, 100, new ExecutionContext()); + Assert.assertTrue(accumulator2 instanceof CountRowsAccumulator); + try { + ((CountRowsAccumulator) accumulator2).accumulate(0, LongBlock.of(1L, 2L, 3L), 0); + Assert.fail("Expect exception here"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("not implemented")); + } + + DecimalAvgAccumulator faultyAccumulator = Mockito.mock(DecimalAvgAccumulator.class); + Mockito.when(faultyAccumulator.getInputTypes()) + .thenReturn(new DataType[] {DataTypes.DecimalType, DataTypes.DecimalType}); + Mockito.doCallRealMethod().when(faultyAccumulator) + .accumulate(Mockito.anyInt(), Mockito.any(Chunk.class), Mockito.anyInt()); + try { + Block block = LongBlock.of(1L, 2L, 3L); + Chunk chunk = new Chunk(block); + faultyAccumulator.accumulate(0, chunk, 0); + Assert.fail("Expect exception here"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage(), e.getMessage().contains("has multiple arguments")); + } + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/LongMaxMinAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/LongMaxMinAccumulatorTest.java new file mode 100644 index 000000000..9e13cf599 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/LongMaxMinAccumulatorTest.java @@ -0,0 +1,97 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.MaxV2; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.MinV2; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +public class LongMaxMinAccumulatorTest { + + private static final int COUNT = 1024; + private LongMaxMinAccumulator minAccumulator; + private LongMaxMinAccumulator maxAccumulator; + private Random random; + + @Before + public void before() { + Accumulator minAccumulator = + AccumulatorBuilders.create(new MinV2(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, + COUNT, + new ExecutionContext()); + Accumulator maxAccumulator = + AccumulatorBuilders.create(new MaxV2(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, + COUNT, + new ExecutionContext()); + + this.minAccumulator = (LongMaxMinAccumulator) minAccumulator; + this.maxAccumulator = (LongMaxMinAccumulator) maxAccumulator; + this.random = new Random(); + + Assert.assertEquals(1, minAccumulator.getInputTypes().length); + Assert.assertEquals(1, maxAccumulator.getInputTypes().length); + } + + /** + * Group0 has values + * Group1 has no values + */ + @Test + public void testMaxMin2Groups() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + long l = random.nextLong(); + builder.writeLong(l); + long min = l, max = l; + for (int i = 0; i < COUNT - 2; i++) { + l = random.nextLong(); + builder.writeLong(l); + if (l < min) { + min = l; + } + if (l > max) { + max = l; + } + } + builder.appendNull(); + + LongBlock block = (LongBlock) builder.build(); + + minAccumulator.appendInitValue(); + minAccumulator.appendInitValue(); + maxAccumulator.appendInitValue(); + maxAccumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + minAccumulator.accumulate(0, block, i); + maxAccumulator.accumulate(0, block, i); + } + + LongBlockBuilder minResultBuilder = new LongBlockBuilder(COUNT); + LongBlockBuilder maxResultBuilder = new LongBlockBuilder(COUNT); + minAccumulator.writeResultTo(0, minResultBuilder); + minAccumulator.writeResultTo(1, minResultBuilder); + maxAccumulator.writeResultTo(0, maxResultBuilder); + maxAccumulator.writeResultTo(1, maxResultBuilder); + Block minResultBlock = minResultBuilder.build(); + Assert.assertEquals(2, minResultBlock.getPositionCount()); + Block maxResultBlock = maxResultBuilder.build(); + Assert.assertEquals(2, maxResultBuilder.getPositionCount()); + + Assert.assertEquals(min, minResultBlock.getLong(0)); + Assert.assertEquals(max, maxResultBlock.getLong(0)); + + Assert.assertTrue(minResultBlock.isNull(1)); + Assert.assertTrue(maxResultBlock.isNull(1)); + + Assert.assertTrue(minAccumulator.estimateSize() > 0); + Assert.assertTrue(maxAccumulator.estimateSize() > 0); + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/LongSum0AccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/LongSum0AccumulatorTest.java new file mode 100644 index 000000000..23a799e85 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/LongSum0AccumulatorTest.java @@ -0,0 +1,80 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.Sum0; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class LongSum0AccumulatorTest { + + private static final int COUNT = 1024; + private LongSum0Accumulator accumulator; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new Sum0(), DataTypes.LongType, new DataType[] {DataTypes.LongType}, COUNT, + new ExecutionContext()); + + this.accumulator = (LongSum0Accumulator) accumulator; + Assert.assertEquals(1, accumulator.getInputTypes().length); + } + + @Test + public void testLongSum1Group() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + // not use random to avoid overflow + long result = 0; + for (int i = 0; i < COUNT - 1; i++) { + builder.writeLong(i); + result += i; + } + builder.appendNull(); + + LongBlock block = (LongBlock) builder.build(); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, block, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertEquals(result, resultBlock.getLong(0)); + + long size = accumulator.estimateSize(); + Assert.assertTrue(size > 0); + } + + /** + * sum0 regards NULL as 0 + */ + @Test + public void testLongSumWithAllNull() { + LongBlockBuilder builder = new LongBlockBuilder(COUNT); + for (int i = 0; i < COUNT; i++) { + builder.appendNull(); + } + + LongBlock block = (LongBlock) builder.build(); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, block, i); + } + + LongBlockBuilder resultBuilder = new LongBlockBuilder(COUNT); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertEquals(0, resultBlock.getLong(0)); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/PartialHLLAccumulatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/PartialHLLAccumulatorTest.java new file mode 100644 index 000000000..731dace3d --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/PartialHLLAccumulatorTest.java @@ -0,0 +1,76 @@ +package com.alibaba.polardbx.executor.accumulator; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.ByteArrayBlock; +import com.alibaba.polardbx.executor.chunk.ByteArrayBlockBuilder; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.utils.ByteUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.PartialHyperLoglog; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +public class PartialHLLAccumulatorTest { + + private static final int COUNT = 1024; + private PartialHyperLogLogAccumulator accumulator; + private Random random; + + @Before + public void before() { + Accumulator accumulator = + AccumulatorBuilders.create(new PartialHyperLoglog(new int[] {0}, -1), DataTypes.LongType, + new DataType[] {DataTypes.LongType}, COUNT, new ExecutionContext()); + + this.accumulator = (PartialHyperLogLogAccumulator) accumulator; + this.random = new Random(); + Assert.assertEquals(1, accumulator.getInputTypes().length); + } + + @Test + public void testPartialHLL1Group() { + ByteArrayBlockBuilder builder = new ByteArrayBlockBuilder(COUNT, 8); + for (int i = 0; i < COUNT - 1; i++) { + builder.writeByteArray(ByteUtil.toByteArray(random.nextLong())); + } + builder.appendNull(); + ByteArrayBlock block = (ByteArrayBlock) builder.build(); + Chunk chunk = new Chunk(block); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, chunk, i); + } + + ByteArrayBlockBuilder resultBuilder = new ByteArrayBlockBuilder(COUNT, 8); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + Assert.assertNotNull(resultBlock.getByteArray(0)); + } + + @Test + public void testPartialHLL1NullInput() { + ByteArrayBlockBuilder builder = new ByteArrayBlockBuilder(COUNT, 8); + for (int i = 0; i < COUNT; i++) { + builder.appendNull(); + } + ByteArrayBlock block = (ByteArrayBlock) builder.build(); + Chunk chunk = new Chunk(block); + + accumulator.appendInitValue(); + for (int i = 0; i < block.getPositionCount(); i++) { + accumulator.accumulate(0, chunk, i); + } + + ByteArrayBlockBuilder resultBuilder = new ByteArrayBlockBuilder(COUNT, 8); + accumulator.writeResultTo(0, resultBuilder); + Block resultBlock = resultBuilder.build(); + Assert.assertEquals(1, resultBlock.getPositionCount()); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/state/GroupStateTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/state/GroupStateTest.java new file mode 100644 index 000000000..4f33c14a7 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/state/GroupStateTest.java @@ -0,0 +1,110 @@ +package com.alibaba.polardbx.executor.accumulator.state; + +import com.alibaba.polardbx.common.datatype.Decimal; +import org.junit.Test; + +import java.util.Random; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class GroupStateTest { + + private final Random random = new Random(); + + @Test + public void testNullableDecimal() { + final Decimal[] values = new Decimal[] { + null, + Decimal.fromString("3.14"), + Decimal.ZERO, + Decimal.fromString("99999999999999999999999999999999999999999999999999999999999999999"), + null + }; + + NullableDecimalGroupState state = new NullableDecimalGroupState(100); + for (int i = 0; i < values.length; i++) { + final Decimal value = values[i]; + state.appendNull(); + if (value != null) { + state.set(i, value); + } + } + + values[2] = Decimal.fromLong(1); + state.set(2, values[2]); + values[3] = Decimal.fromString("7712.025316455696202531645569620253"); + state.set(3, values[3]); + + for (int i = 0; i < values.length; i++) { + if (values[i] != null) { + assertFalse(state.isNull(i)); + assertEquals(values[i], state.get(i)); + } else { + assertTrue(state.isNull(i)); + } + } + } + + @Test + public void testLong() { + final int COUNT = 1000; + long[] values = new long[COUNT]; + for (int i = 0; i < values.length; i++) { + values[i] = random.nextLong(); + } + + LongGroupState state = new LongGroupState(COUNT / 10); + for (int i = 0; i < values.length; i++) { + state.append(values[i]); + } + + for (int i = 0; i < values.length / 2; i += 2) { + long l = random.nextLong(); + state.set(i, l); + values[i] = l; + } + + for (int i = 0; i < values.length; i++) { + assertEquals(values[i], state.get(i)); + } + } + + @Test + public void testNullableDouble() { + final int COUNT = 1000; + Double[] values = new Double[COUNT]; + for (int i = 0; i < values.length; i++) { + if (i % 2 == 0) { + values[i] = null; + } else { + values[i] = random.nextDouble(); + } + } + + NullableDoubleGroupState state = new NullableDoubleGroupState(100); + for (int i = 0; i < values.length; i++) { + if (values[i] != null) { + state.append(values[i]); + } else { + state.appendNull(); + } + } + + for (int i = 0; i < values.length / 2; i += 2) { + double d = random.nextDouble(); + state.set(i, d); + values[i] = d; + } + + for (int i = 0; i < values.length; i++) { + if (values[i] != null) { + assertFalse(state.isNull(i)); + assertEquals(values[i], state.get(i), 1e-10); + } else { + assertTrue(state.isNull(i)); + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalBlockSum2Test.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalBlockSum2Test.java similarity index 99% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalBlockSum2Test.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalBlockSum2Test.java index 2f2d5c3fa..cecfbe2f6 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalBlockSum2Test.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalBlockSum2Test.java @@ -1,4 +1,4 @@ -package com.alibaba.polardbx.executor.accumulator; +package com.alibaba.polardbx.executor.accumulator.sum; import com.alibaba.polardbx.common.datatype.Decimal; import com.alibaba.polardbx.executor.chunk.Block; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalBlockSumTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalBlockSumTest.java similarity index 95% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalBlockSumTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalBlockSumTest.java index 313ab9aaf..e9371518c 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalBlockSumTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalBlockSumTest.java @@ -1,25 +1,17 @@ -package com.alibaba.polardbx.executor.accumulator; +package com.alibaba.polardbx.executor.accumulator.sum; import com.alibaba.polardbx.common.datatype.Decimal; -import com.alibaba.polardbx.common.datatype.FastDecimalUtils; import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.chunk.DecimalBlock; import com.alibaba.polardbx.executor.chunk.DecimalBlockBuilder; -import com.alibaba.polardbx.optimizer.core.datatype.DataType; -import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; -import org.apache.commons.lang3.RandomUtils; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.math.BigDecimal; -import java.math.BigInteger; import java.util.ArrayList; import java.util.List; -import java.util.Random; /** * Do sum inside a DecimalBlock with startIndex and endIndex diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalBoxTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalBoxTest.java similarity index 98% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalBoxTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalBoxTest.java index 31c20061b..088ec6bd0 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalBoxTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalBoxTest.java @@ -1,4 +1,4 @@ -package com.alibaba.polardbx.executor.accumulator; +package com.alibaba.polardbx.executor.accumulator.sum; import com.alibaba.polardbx.common.datatype.Decimal; import com.alibaba.polardbx.common.datatype.DecimalBox; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumAggTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumAggTest.java similarity index 96% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumAggTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumAggTest.java index 39026e844..6be0769da 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumAggTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumAggTest.java @@ -1,6 +1,7 @@ -package com.alibaba.polardbx.executor.accumulator; +package com.alibaba.polardbx.executor.accumulator.sum; import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.executor.accumulator.DecimalSumAccumulator; import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.chunk.DecimalBlock; import com.alibaba.polardbx.executor.chunk.DecimalBlockBuilder; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumRescaleTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumRescaleTest.java similarity index 98% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumRescaleTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumRescaleTest.java index 80d6e1641..588a35970 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumRescaleTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumRescaleTest.java @@ -1,6 +1,7 @@ -package com.alibaba.polardbx.executor.accumulator; +package com.alibaba.polardbx.executor.accumulator.sum; import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.executor.accumulator.DecimalSumAccumulator; import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.chunk.DecimalBlock; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumTest.java similarity index 99% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumTest.java index 47b4c5f1f..fdff8c92f 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumTest.java @@ -1,7 +1,8 @@ -package com.alibaba.polardbx.executor.accumulator; +package com.alibaba.polardbx.executor.accumulator.sum; import com.alibaba.polardbx.common.datatype.Decimal; import com.alibaba.polardbx.common.datatype.FastDecimalUtils; +import com.alibaba.polardbx.executor.accumulator.DecimalSumAccumulator; import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.chunk.DecimalBlock; import com.alibaba.polardbx.executor.chunk.DecimalBlockBuilder; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumV2Test.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumV2Test.java similarity index 99% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumV2Test.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumV2Test.java index 583551b1e..ff32379b7 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumV2Test.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumV2Test.java @@ -1,7 +1,8 @@ -package com.alibaba.polardbx.executor.accumulator; +package com.alibaba.polardbx.executor.accumulator.sum; import com.alibaba.polardbx.common.datatype.Decimal; import com.alibaba.polardbx.common.datatype.FastDecimalUtils; +import com.alibaba.polardbx.executor.accumulator.DecimalSumAccumulator; import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.chunk.DecimalBlock; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumZeroTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumZeroTest.java similarity index 98% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumZeroTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumZeroTest.java index 6898f51e8..b0ad41615 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/DecimalSumZeroTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/accumulator/sum/DecimalSumZeroTest.java @@ -1,4 +1,4 @@ -package com.alibaba.polardbx.executor.accumulator; +package com.alibaba.polardbx.executor.accumulator.sum; import com.alibaba.polardbx.common.datatype.Decimal; import com.alibaba.polardbx.common.datatype.DecimalBox; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/BlackHoleBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/BlackHoleBlockTest.java new file mode 100644 index 000000000..56da3d38e --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/BlackHoleBlockTest.java @@ -0,0 +1,65 @@ +package com.alibaba.polardbx.executor.chunk; + +import com.alibaba.druid.mock.MockClob; +import com.alibaba.polardbx.common.datatype.Decimal; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigInteger; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; + +public class BlackHoleBlockTest extends BaseBlockTest { + @Test + public void testWrite() { + BlackHoleBlockBuilder blockBuilder = new BlackHoleBlockBuilder(); + blockBuilder.writeBoolean(true); + blockBuilder.writeByte((byte) 1); + blockBuilder.writeShort((short) 1); + blockBuilder.writeInt(1); + blockBuilder.writeLong(1); + blockBuilder.writeFloat(1.0f); + blockBuilder.writeDouble(1.0d); + blockBuilder.writeString("1"); + blockBuilder.writeBigInteger(BigInteger.ONE); + blockBuilder.writeDate(new Date(2001, 10, 10)); + blockBuilder.writeDatetimeRawLong(System.currentTimeMillis()); + blockBuilder.writeTime(new Time(10, 1, 1)); + blockBuilder.writeTimestamp(new Timestamp(System.currentTimeMillis())); + blockBuilder.writeBlob(new com.alibaba.polardbx.optimizer.core.datatype.Blob(new byte[] {1})); + blockBuilder.writeClob(new MockClob()); + blockBuilder.writeObject(new Object()); + blockBuilder.writeDecimal(new Decimal(1000, 2)); + blockBuilder.writeByteArray(new byte[] {1}); + blockBuilder.writeByteArray(new byte[] {1, 2}, 1, 1); + blockBuilder.appendNull(); + Assert.assertEquals(20, blockBuilder.positionCount); + + blockBuilder = (BlackHoleBlockBuilder) blockBuilder.newBlockBuilder(); + Assert.assertEquals(0, blockBuilder.getPositionCount()); + blockBuilder.ensureCapacity(10); + blockBuilder = (BlackHoleBlockBuilder) blockBuilder.newBlockBuilder(null, 1024); + } + + @Test + public void testFailMethod() { + BlackHoleBlockBuilder blockBuilder = new BlackHoleBlockBuilder(); + notSupport(() -> blockBuilder.getObject(1)); + notSupport(() -> blockBuilder.isNull(1)); + notSupport(blockBuilder::build); + notSupport(blockBuilder::mayHaveNull); + notSupport(blockBuilder::estimateSize); + notSupport(() -> blockBuilder.hashCodeUseXxhash(1)); + notSupport(() -> blockBuilder.writePositionTo(1, null)); + } + + private void notSupport(Runnable action) { + try { + action.run(); + } catch (UnsupportedOperationException e) { + return; + } + Assert.fail(action + "should not support"); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/BlobBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/BlobBlockTest.java index 0fff8b0d8..b6ca5a6b6 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/BlobBlockTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/BlobBlockTest.java @@ -19,14 +19,11 @@ import com.alibaba.druid.mock.MockBlob; import io.airlift.slice.DynamicSliceOutput; import io.airlift.slice.SliceOutput; +import org.junit.Assert; import org.junit.Test; import java.sql.Blob; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - public class BlobBlockTest extends BaseBlockTest { @Test @@ -73,8 +70,47 @@ public void testBlobEncoding() { Block blobBlockShuffled = encoding.readBlock(output.slice().getInput()); // check - for (int i = 0; i != blobBlock.getPositionCount(); i++) { - assertTrue(blobBlock.equals(i, blobBlockShuffled, i)); + for (int i = 0; i < blobBlock.getPositionCount(); i++) { + Assert.assertTrue(blobBlock.equals(i, blobBlockShuffled, i)); + } + } + + @Test + public void testCopy() { + final Blob[] blobs = new Blob[] { + new com.alibaba.polardbx.optimizer.core.datatype.Blob(new byte[] {0x7E, 0x7F}), + new com.alibaba.polardbx.optimizer.core.datatype.Blob(new byte[] {0x1, 0x2, 0x3}), + new com.alibaba.polardbx.optimizer.core.datatype.Blob(new byte[] {0x4, 0x5, 0x6, 0x7}), + new com.alibaba.polardbx.optimizer.core.datatype.Blob(new byte[] {0x8, 0x9, 0xA, 0xB, 0xC}) + }; + + BlobBlockBuilder blobBlockBuilder = new BlobBlockBuilder(1); + for (Blob blob : blobs) { + blobBlockBuilder.appendNull(); + blobBlockBuilder.writeBlob(blob); + } + BlobBlock blobBlock = (BlobBlock) blobBlockBuilder.build(); + BlobBlock newBlock = BlobBlock.from(blobBlock, blobBlock.getPositionCount(), null); + for (int i = 0; i < blobBlock.getPositionCount(); i++) { + if (blobBlock.isNull(i)) { + Assert.assertTrue(newBlock.isNull(i)); + continue; + } + Assert.assertEquals(blobBlock.getBlob(i), newBlock.getBlob(i)); + Assert.assertEquals(blobBlock.hashCode(i), newBlock.hashCode(i)); + Assert.assertEquals(blobBlock.hashCodeUseXxhash(i), newBlock.hashCodeUseXxhash(i)); + Assert.assertEquals(blobBlock.checksum(i), newBlock.checksum(i)); + } + + int[] sel = new int[] {0, 1, 2, 3, 6, 7}; + BlobBlock newBlock2 = BlobBlock.from(blobBlock, sel.length, sel); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + if (blobBlock.isNull(j)) { + Assert.assertTrue(newBlock2.isNull(i)); + continue; + } + Assert.assertEquals(blobBlock.getBlob(j), newBlock2.getBlob(i)); } } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/BlockEncodingTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/BlockEncodingTest.java new file mode 100644 index 000000000..11cf77b59 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/BlockEncodingTest.java @@ -0,0 +1,410 @@ +package com.alibaba.polardbx.executor.chunk; + +import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; +import com.alibaba.polardbx.optimizer.core.datatype.EnumType; +import com.alibaba.polardbx.optimizer.core.datatype.SliceType; +import com.alibaba.polardbx.rpc.result.XResultUtil; +import com.google.common.collect.Lists; +import io.airlift.slice.BasicSliceInput; +import io.airlift.slice.DynamicSliceOutput; +import io.airlift.slice.SliceInput; +import io.airlift.slice.SliceOutput; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigInteger; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class BlockEncodingTest { + + @Test + public void testEncodingBuilders() { + ExecutionContext context = new ExecutionContext(); + List typeList = Lists.newArrayList(DataTypes.IntegerType, DataTypes.LongType, + DataTypes.ShortType, DataTypes.ByteType, DataTypes.DoubleType, DataTypes.FloatType, + DataTypes.StringType, DataTypes.TimestampType, DataTypes.DateType, DataTypes.TimeType, + new DecimalType(16, 2), DataTypes.BigBitType, DataTypes.BytesType, DataTypes.BlobType, + DataTypes.ClobType, new EnumType(Lists.newArrayList("a", "b", "c")), new SliceType(), + DataTypes.ULongType); + List blockEncodings = BlockEncodingBuilders.create(typeList, context); + Assert.assertEquals(typeList.size(), blockEncodings.size()); + List expectClasses = Lists.newArrayList(IntegerBlockEncoding.class, LongBlockEncoding.class, + ShortBlockEncoding.class, ByteBlockEncoding.class, DoubleBlockEncoding.class, FloatBlockEncoding.class, + StringBlockEncoding.class, TimestampBlockEncoding.class, DateBlockEncoding.class, TimeBlockEncoding.class, + DecimalBlockEncoding.class, BigIntegerBlockEncoding.class, ByteArrayBlockEncoding.class, + BlobBlockEncoding.class, ClobBlockEncoding.class, EnumBlockEncoding.class, SliceBlockEncoding.class, + ULongBlockEncoding.class); + for (int i = 0; i < typeList.size(); i++) { + Assert.assertEquals("Not match at pos: " + i, expectClasses.get(i), blockEncodings.get(i).getClass()); + } + + context.getParamManager().getProps().put("ENABLE_ORC_RAW_TYPE_BLOCK", "true"); + List blockEncodings2 = BlockEncodingBuilders.create(typeList, context); + Assert.assertEquals(typeList.size(), blockEncodings.size()); + List expectClasses2 = Lists.newArrayList(LongBlockEncoding.class, LongBlockEncoding.class, + LongBlockEncoding.class, LongBlockEncoding.class, DoubleBlockEncoding.class, DoubleBlockEncoding.class, + ByteArrayBlockEncoding.class, LongBlockEncoding.class, LongBlockEncoding.class, LongBlockEncoding.class, + LongBlockEncoding.class, LongBlockEncoding.class, ByteArrayBlockEncoding.class, + ByteArrayBlockEncoding.class, + ByteArrayBlockEncoding.class, ByteArrayBlockEncoding.class, ByteArrayBlockEncoding.class, + LongBlockEncoding.class); + for (int i = 0; i < typeList.size(); i++) { + Assert.assertEquals("Not match at pos: " + i, expectClasses2.get(i), blockEncodings2.get(i).getClass()); + } + } + + @Test + public void testNullEncoding() { + final int count = 16; + SliceOutput sliceOutput = new DynamicSliceOutput(128); + NullBlock nullBlock = new NullBlock(count); + NullBlockEncoding encoding = new NullBlockEncoding(); + Assert.assertEquals("NULL", encoding.getName()); + encoding.writeBlock(sliceOutput, nullBlock); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + Block block = encoding.readBlock(sliceInput); + Assert.assertEquals(count, block.getPositionCount()); + } + + @Test + public void testReferenceEncoding() { + final int count = 16; + SliceOutput sliceOutput = new DynamicSliceOutput(128); + ReferenceBlock refBlock = new ObjectBlock(0, count, new boolean[count], new Object[count]); + ReferenceBlockEncoding encoding = new ReferenceBlockEncoding(); + Assert.assertEquals("ReferenceObject", encoding.getName()); + try { + encoding.writeBlock(sliceOutput, refBlock); + Assert.fail("Expect failed"); + } catch (Exception e) { + Assert.assertTrue(e instanceof UnsupportedOperationException); + } + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + try { + Block block = encoding.readBlock(sliceInput); + Assert.fail("Expect failed"); + } catch (Exception e) { + Assert.assertTrue(e instanceof UnsupportedOperationException); + } + } + + @Test + public void testDecimal64Encoding() { + final int count = 16; + final DataType decimalType = new DecimalType(16, 2); + SliceOutput sliceOutput = new DynamicSliceOutput(128); + DecimalBlockBuilder blockBuilder = new DecimalBlockBuilder(count / 2, decimalType); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeLong(i * 200); + } + blockBuilder.appendNull(); + DecimalBlock sourceBlock = (DecimalBlock) blockBuilder.build(); + Assert.assertTrue(sourceBlock.isDecimal64()); + DecimalBlockEncoding encoding = new DecimalBlockEncoding(); + Assert.assertEquals("DECIMAL", encoding.getName()); + encoding.writeBlock(sliceOutput, sourceBlock); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + Block block = encoding.readBlock(sliceInput); + Assert.assertTrue(block instanceof DecimalBlock); + Assert.assertTrue(((DecimalBlock) block).isDecimal64()); + Assert.assertEquals(count, block.getPositionCount()); + for (int i = 0; i < count; i++) { + if (sourceBlock.isNull(i)) { + Assert.assertTrue("Failed at pos: " + i, block.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getLong(i), block.getLong(i)); + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getDecimal(i), block.getDecimal(i)); + } + } + + @Test + public void testDecimal128Encoding() { + final int count = 16; + final DataType decimalType = new DecimalType(30, 4); + SliceOutput sliceOutput = new DynamicSliceOutput(128); + DecimalBlockBuilder blockBuilder = new DecimalBlockBuilder(count / 2, decimalType); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeDecimal128(i * 200, i); + } + blockBuilder.appendNull(); + DecimalBlock sourceBlock = (DecimalBlock) blockBuilder.build(); + Assert.assertTrue(sourceBlock.isDecimal128()); + DecimalBlockEncoding encoding = new DecimalBlockEncoding(); + encoding.writeBlock(sliceOutput, sourceBlock); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + Block block = encoding.readBlock(sliceInput); + Assert.assertTrue(block instanceof DecimalBlock); + Assert.assertTrue(((DecimalBlock) block).isDecimal128()); + Assert.assertEquals(count, block.getPositionCount()); + for (int i = 0; i < count; i++) { + if (sourceBlock.isNull(i)) { + Assert.assertTrue("Failed at pos: " + i, block.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getDecimal128Low(i), + ((DecimalBlock) block).getDecimal128Low(i)); + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getDecimal128High(i), + ((DecimalBlock) block).getDecimal128High(i)); + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getDecimal(i), block.getDecimal(i)); + } + } + + @Test + public void testNormalDecimalEncoding() { + final int count = 16; + final DataType decimalType = new DecimalType(16, 2); + SliceOutput sliceOutput = new DynamicSliceOutput(128); + DecimalBlockBuilder blockBuilder = new DecimalBlockBuilder(count / 2, decimalType); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeDecimal(new Decimal(i * 500L, decimalType.getScale())); + } + blockBuilder.appendNull(); + DecimalBlock sourceBlock = (DecimalBlock) blockBuilder.build(); + Assert.assertTrue(sourceBlock.getState().isNormal()); + DecimalBlockEncoding encoding = new DecimalBlockEncoding(); + encoding.writeBlock(sliceOutput, sourceBlock); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + Block block = encoding.readBlock(sliceInput); + Assert.assertTrue(block instanceof DecimalBlock); + Assert.assertTrue(((DecimalBlock) block).getState().isNormal()); + Assert.assertEquals(count, block.getPositionCount()); + for (int i = 0; i < count; i++) { + if (sourceBlock.isNull(i)) { + Assert.assertTrue("Failed at pos: " + i, block.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getDecimal(i), block.getDecimal(i)); + } + } + + @Test + public void testIllegalDecimalTypeEncoding() { + final byte illegalType = 3; + SliceOutput sliceOutput = new DynamicSliceOutput(128); + sliceOutput.writeInt(16); + sliceOutput.writeByte(illegalType); + DecimalBlockEncoding encoding = new DecimalBlockEncoding(); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + try { + Block block = encoding.readBlock(sliceInput); + Assert.fail("Expect failed"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Unexpected decimal block encoding type: " + illegalType)); + } + } + + @Test + public void testClobEncoding() { + final int count = 16; + SliceOutput sliceOutput = new DynamicSliceOutput(128); + ClobBlock clobBlock = new ClobBlock(0, count, new boolean[count], new Object[count]); + ClobBlockEncoding encoding = new ClobBlockEncoding(); + Assert.assertEquals("CLOB", encoding.getName()); + try { + encoding.writeBlock(sliceOutput, clobBlock); + Assert.fail("Expect failed"); + } catch (Exception e) { + Assert.assertTrue(e instanceof UnsupportedOperationException); + } + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + try { + Block block = encoding.readBlock(sliceInput); + Assert.fail("Expect failed"); + } catch (Exception e) { + Assert.assertTrue(e instanceof UnsupportedOperationException); + } + } + + @Test + public void testBigIntegerEncoding() { + final int count = 16; + SliceOutput sliceOutput = new DynamicSliceOutput(128); + BigIntegerBlockBuilder blockBuilder = new BigIntegerBlockBuilder(count / 2); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeBigInteger(BigInteger.valueOf(i * 100)); + } + blockBuilder.appendNull(); + BigIntegerBlock sourceBlock = (BigIntegerBlock) blockBuilder.build(); + BigIntegerBlockEncoding encoding = new BigIntegerBlockEncoding(); + Assert.assertEquals("BIGINTEGER", encoding.getName()); + encoding.writeBlock(sliceOutput, sourceBlock); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + Block block = encoding.readBlock(sliceInput); + Assert.assertTrue(block instanceof BigIntegerBlock); + Assert.assertEquals(count, block.getPositionCount()); + for (int i = 0; i < count; i++) { + if (sourceBlock.isNull(i)) { + Assert.assertTrue("Failed at pos: " + i, block.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getBigInteger(i), block.getBigInteger(i)); + } + } + + @Test + public void testByteArrayEncoding() { + final int count = 16; + SliceOutput sliceOutput = new DynamicSliceOutput(128); + ByteArrayBlockBuilder blockBuilder = new ByteArrayBlockBuilder(count / 2, 32); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeByteArray(String.valueOf(i * 999).getBytes()); + } + blockBuilder.appendNull(); + ByteArrayBlock sourceBlock = (ByteArrayBlock) blockBuilder.build(); + ByteArrayBlockEncoding encoding = new ByteArrayBlockEncoding(); + Assert.assertEquals("BYTE_ARRAY", encoding.getName()); + encoding.writeBlock(sliceOutput, sourceBlock); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + Block block = encoding.readBlock(sliceInput); + Assert.assertTrue(block instanceof ByteArrayBlock); + Assert.assertEquals(count, block.getPositionCount()); + for (int i = 0; i < count; i++) { + if (sourceBlock.isNull(i)) { + Assert.assertTrue("Failed at pos: " + i, block.isNull(i)); + continue; + } + Assert.assertArrayEquals("Failed at pos: " + i, sourceBlock.getByteArray(i), block.getByteArray(i)); + } + } + + @Test + public void testFloatEncoding() { + final int count = 16; + SliceOutput sliceOutput = new DynamicSliceOutput(128); + FloatBlockBuilder blockBuilder = new FloatBlockBuilder(count / 2); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeFloat(i * 1.1F); + } + blockBuilder.appendNull(); + FloatBlock sourceBlock = (FloatBlock) blockBuilder.build(); + FloatBlockEncoding encoding = new FloatBlockEncoding(XResultUtil.DECIMAL_NOT_SPECIFIED); + Assert.assertEquals("FLOAT", encoding.getName()); + encoding.writeBlock(sliceOutput, sourceBlock); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + Block block = encoding.readBlock(sliceInput); + Assert.assertTrue(block instanceof FloatBlock); + Assert.assertEquals(count, block.getPositionCount()); + for (int i = 0; i < count; i++) { + if (sourceBlock.isNull(i)) { + Assert.assertTrue("Failed at pos: " + i, block.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getFloat(i), block.getFloat(i), 1e-10); + } + } + + @Test + public void testBooleanEncoding() { + final int count = 16; + SliceOutput sliceOutput = new DynamicSliceOutput(128); + BooleanBlockBuilder blockBuilder = new BooleanBlockBuilder(count / 2); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeBoolean(i % 2 == 0); + } + blockBuilder.appendNull(); + BooleanBlock sourceBlock = (BooleanBlock) blockBuilder.build(); + BooleanBlockEncoding encoding = new BooleanBlockEncoding(); + Assert.assertEquals("BOOLEAN", encoding.getName()); + encoding.writeBlock(sliceOutput, sourceBlock); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + Block block = encoding.readBlock(sliceInput); + Assert.assertTrue(block instanceof BooleanBlock); + Assert.assertEquals(count, block.getPositionCount()); + for (int i = 0; i < count; i++) { + if (sourceBlock.isNull(i)) { + Assert.assertTrue("Failed at pos: " + i, block.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getBoolean(i), block.getBoolean(i)); + } + } + + @Test + public void testShortEncoding() { + final int count = 16; + SliceOutput sliceOutput = new DynamicSliceOutput(128); + ShortBlockBuilder blockBuilder = new ShortBlockBuilder(count / 2); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeShort((short) i); + } + blockBuilder.appendNull(); + ShortBlock sourceBlock = (ShortBlock) blockBuilder.build(); + ShortBlockEncoding encoding = new ShortBlockEncoding(); + Assert.assertEquals("SHORT", encoding.getName()); + encoding.writeBlock(sliceOutput, sourceBlock); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + Block block = encoding.readBlock(sliceInput); + Assert.assertTrue(block instanceof ShortBlock); + Assert.assertEquals(count, block.getPositionCount()); + for (int i = 0; i < count; i++) { + if (sourceBlock.isNull(i)) { + Assert.assertTrue("Failed at pos: " + i, block.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getShort(i), block.getShort(i)); + } + } + + @Test + public void testEnumEncoding() { + final Map enumMap = new HashMap<>(); + enumMap.put("a", 1); + enumMap.put("b", 2); + enumMap.put("c", 3); + final int count = 16; + SliceOutput sliceOutput = new DynamicSliceOutput(128); + EnumBlockBuilder blockBuilder = new EnumBlockBuilder(count / 2, 32, enumMap); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf((char) ('a' + i % enumMap.size()))); + } + blockBuilder.appendNull(); + EnumBlock sourceBlock = (EnumBlock) blockBuilder.build(); + EnumBlockEncoding encoding = new EnumBlockEncoding(enumMap); + Assert.assertEquals("ENUM", encoding.getName()); + encoding.writeBlock(sliceOutput, sourceBlock); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + Block block = encoding.readBlock(sliceInput); + Assert.assertTrue(block instanceof EnumBlock); + Assert.assertEquals(count, block.getPositionCount()); + for (int i = 0; i < count; i++) { + if (sourceBlock.isNull(i)) { + Assert.assertTrue("Failed at pos: " + i, block.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getObject(i), block.getObject(i)); + } + } + + @Test + public void testByteEncoding() { + final int count = 16; + SliceOutput sliceOutput = new DynamicSliceOutput(128); + ByteBlockBuilder blockBuilder = new ByteBlockBuilder(count / 2); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeByte((byte) i); + } + blockBuilder.appendNull(); + ByteBlock sourceBlock = (ByteBlock) blockBuilder.build(); + ByteBlockEncoding encoding = new ByteBlockEncoding(); + Assert.assertEquals("BYTE", encoding.getName()); + encoding.writeBlock(sliceOutput, sourceBlock); + SliceInput sliceInput = new BasicSliceInput(sliceOutput.slice()); + Block block = encoding.readBlock(sliceInput); + Assert.assertTrue(block instanceof ByteBlock); + Assert.assertEquals(count, block.getPositionCount()); + for (int i = 0; i < count; i++) { + if (sourceBlock.isNull(i)) { + Assert.assertTrue("Failed at pos: " + i, block.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, sourceBlock.getByte(i), block.getByte(i)); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/DateBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/DateBlockTest.java index bb957949f..2e7cbe16a 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/DateBlockTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/DateBlockTest.java @@ -22,6 +22,7 @@ import io.airlift.slice.DynamicSliceOutput; import io.airlift.slice.Slice; import io.airlift.slice.SliceOutput; +import org.junit.Assert; import org.junit.Test; import java.util.List; @@ -29,20 +30,18 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static com.alibaba.polardbx.common.utils.Assert.assertTrue; public class DateBlockTest extends BaseBlockTest { private final static Random R = new Random(); - private final static int TEST_SIZE = 1 << 20; + private final static int TEST_SIZE = 1 << 10; private final static int TEST_SCALE = 4; @Test public void testDate() { - + ExecutionContext context = new ExecutionContext(); final DateType dataType = new DateType(TEST_SCALE); - DateBlockBuilder dateBlockBuilder = new DateBlockBuilder(TEST_SIZE, dataType, new ExecutionContext()); + DateBlockBuilder dateBlockBuilder = new DateBlockBuilder(TEST_SIZE, dataType, context); // write List values = IntStream.range(0, TEST_SIZE) @@ -69,9 +68,78 @@ public void testDate() { IntStream.range(0, TEST_SIZE) .forEach( i -> { - boolean isEqual = block.equals(i, block1, i); - assertTrue(isEqual); + Assert.assertTrue(block.equals(i, block1, i)); + assertTrue(block.equals(i, dateBlockBuilder, i)); } ); + + DateBlock dateBlock = (DateBlock) block; + DateBlockBuilder builder1 = new DateBlockBuilder(TEST_SIZE / 2, dataType, context); + for (int i = 0; i < TEST_SIZE; i++) { + int r = i % 4; + switch (r) { + case 0: + dateBlock.writePositionTo(i, builder1); + break; + case 1: + if (dateBlock.isNull(i)) { + builder1.appendNull(); + } else { + builder1.writeDate(dateBlock.getDate(i)); + } + break; + case 2: + if (dateBlock.isNull(i)) { + builder1.appendNull(); + } else { + builder1.writeDatetimeRawLong((Long) dateBlock.getObjectForCmp(i)); + } + break; + case 3: + builder1.writeObject(dateBlock.getObject(i)); + break; + } + } + DateBlock newBlock = (DateBlock) builder1.build(); + for (int i = 0; i < TEST_SIZE; i++) { + Assert.assertEquals(dateBlock.hashCode(i), newBlock.hashCode(i)); + Assert.assertEquals(dateBlock.hashCodeUseXxhash(i), newBlock.hashCodeUseXxhash(i)); + if (dateBlock.isNull(i)) { + Assert.assertTrue(newBlock.isNull(i)); + continue; + } + Assert.assertEquals(dateBlock.getDate(i), newBlock.getDate(i)); + Assert.assertEquals(dateBlock.getDate(i), builder1.getDate(i)); + Assert.assertEquals(dateBlock.getObjectForCmp(i), builder1.getPackedLong(i)); + Assert.assertEquals(dateBlock.getObject(i), newBlock.getObject(i)); + Assert.assertEquals(dateBlock.getLong(i), newBlock.getLong(i)); + } + + BlockBuilder builder = builder1.newBlockBuilder(); + Assert.assertTrue(builder instanceof DateBlockBuilder); + + DateBlock newBlock2 = DateBlock.from(dateBlock, TEST_SIZE, null, false); + for (int i = 0; i < TEST_SIZE; i++) { + if (dateBlock.isNull(i)) { + Assert.assertTrue(newBlock2.isNull(i)); + continue; + } + Assert.assertEquals(dateBlock.getDate(i), newBlock2.getDate(i)); + } + + int[] sel = new int[TEST_SIZE / 2]; + for (int i = 0; i < sel.length; i++) { + sel[i] = i * 2; + } + DateBlock newBlock3 = DateBlock.from(dateBlock, TEST_SIZE / 2, sel, true); + for (int i = 0; i < TEST_SIZE / 2; i++) { + int j = sel[i]; + if (dateBlock.isNull(j)) { + Assert.assertTrue(newBlock3.isNull(i)); + continue; + } + Assert.assertEquals(dateBlock.getDate(j), newBlock3.getDate(i)); + } + } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/DecimalBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/DecimalBlockTest.java index 7edc81728..6d97bd341 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/DecimalBlockTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/DecimalBlockTest.java @@ -17,6 +17,7 @@ package com.alibaba.polardbx.executor.chunk; import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.common.datatype.DecimalTypeBase; import com.alibaba.polardbx.common.datatype.FastDecimalUtils; import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; import io.airlift.slice.Slice; @@ -43,7 +44,7 @@ public class DecimalBlockTest extends BaseBlockTest { @Test public void testSizeInBytes() { DecimalBlock block = new DecimalBlock(new DecimalType(), 1024); - Assert.assertEquals("delay memory allocation should be 0", 0, block.getElementUsedBytes()); + Assert.assertEquals("delay memory allocation should contains the nulls array", 1024, block.getElementUsedBytes()); block.setElementAt(0, Decimal.fromString("3.14")); Assert.assertEquals("should allocate memory after setting an element", 41984, block.getElementUsedBytes()); @@ -589,6 +590,111 @@ public void testDecimal128Block() { } } + @Test + public void testDecimalEquals() { + final int count = 2000; + final int scale1 = 2; + final int scale2 = 4; + DecimalType decimal64Type1 = new DecimalType(16, scale1); + DecimalType decimal64Type2 = new DecimalType(17, scale2); + DecimalType decimal128Type1 = new DecimalType(30, scale1); + DecimalType decimal128Type2 = new DecimalType(30, scale2); + final int scaleDiff = scale2 - scale1; + final long power = DecimalTypeBase.POW_10_LONG[scaleDiff]; + + DecimalBlockBuilder decimal64Builder1 = new DecimalBlockBuilder(count, decimal64Type1); + DecimalBlockBuilder decimal64Builder2 = new DecimalBlockBuilder(count, decimal64Type2); + DecimalBlockBuilder decimal128Builder1 = new DecimalBlockBuilder(count, decimal128Type1); + DecimalBlockBuilder decimal128Builder2 = new DecimalBlockBuilder(count, decimal128Type2); + + DecimalBlockBuilder normalBuilder1 = new DecimalBlockBuilder(count); + DecimalBlockBuilder normalBuilder2 = new DecimalBlockBuilder(count); + + long[] decimal64Values = new long[count]; + for (int i = 0; i < count; i++) { + int val = random.nextInt(); + val = (val == 0) ? Integer.MAX_VALUE : val; + decimal64Values[i] = val; + } + decimal64Values[0] = 0; + + for (int i = 0; i < count; i++) { + long high = decimal64Values[i] >= 0 ? 0 : -1; + if (i % 4 == 0) { + // write equals + decimal64Builder1.writeLong(decimal64Values[i]); + decimal64Builder2.writeLong(decimal64Values[i] * power); + decimal128Builder1.writeDecimal128(decimal64Values[i], high); + decimal128Builder2.writeDecimal128(decimal64Values[i] * power, high); + normalBuilder1.writeDecimal(new Decimal(decimal64Values[i], decimal64Type1.getScale())); + normalBuilder2.writeDecimal(new Decimal(decimal64Values[i], decimal64Type1.getScale())); + } else if (i % 4 == 1) { + // write diff sign + decimal64Builder1.writeLong(decimal64Values[i]); + decimal64Builder2.writeLong(decimal64Values[i] * -1); + decimal128Builder1.writeDecimal128(decimal64Values[i] * -1, -1); + decimal128Builder2.writeDecimal128(decimal64Values[i] * -1, -1); + normalBuilder1.writeDecimal(new Decimal(decimal64Values[i], decimal64Type1.getScale())); + normalBuilder2.writeDecimal(new Decimal(-decimal64Values[i], decimal64Type1.getScale())); + } else if (i % 4 == 2) { + // write smaller value + decimal64Builder1.writeLong(decimal64Values[i]); + decimal64Builder2.writeLong(decimal64Values[i] * power - 1); + decimal128Builder1.writeDecimal128(decimal64Values[i] * power - 2, high); + decimal128Builder2.writeDecimal128(decimal64Values[i] * power - 3, high); + normalBuilder1.writeDecimal(new Decimal(decimal64Values[i], decimal64Type1.getScale())); + normalBuilder2.writeDecimal(new Decimal(-decimal64Values[i], decimal64Type1.getScale())); + } else { + // write larger value + decimal64Builder1.writeLong(decimal64Values[i]); + decimal64Builder2.writeLong(decimal64Values[i] * power + 1); + decimal128Builder1.writeDecimal128(decimal64Values[i] * power + 2, high); + decimal128Builder2.writeDecimal128(decimal64Values[i] * power + 3, high); + normalBuilder1.writeDecimal(new Decimal(decimal64Values[i], decimal64Type1.getScale())); + normalBuilder2.writeDecimal(new Decimal(-decimal64Values[i], decimal64Type1.getScale())); + } + } + DecimalBlock decimal64Block1 = (DecimalBlock) decimal64Builder1.build(); + DecimalBlock decimal64Block2 = (DecimalBlock) decimal64Builder2.build(); + DecimalBlock decimal128Block1 = (DecimalBlock) decimal128Builder1.build(); + DecimalBlock decimal128Block2 = (DecimalBlock) decimal128Builder2.build(); + DecimalBlock normalBlock1 = (DecimalBlock) normalBuilder1.build(); + DecimalBlock normalBlock2 = (DecimalBlock) normalBuilder2.build(); + + Assert.assertTrue(decimal64Block1.isDecimal64()); + Assert.assertTrue(decimal64Block2.isDecimal64()); + Assert.assertTrue(decimal128Block1.isDecimal128()); + Assert.assertTrue(decimal128Block2.isDecimal128()); + Assert.assertTrue(normalBlock1.getState().isNormal()); + Assert.assertTrue(normalBlock2.getState().isNormal()); + + for (int i = 0; i < count; i++) { + if (i % 4 == 0) { + Assert.assertTrue("Failed at : " + i, decimal64Block1.equals(i, decimal64Block2, i)); + Assert.assertTrue("Failed at : " + i, decimal64Block2.equals(i, decimal64Block1, i)); + Assert.assertTrue("Failed at : " + i, decimal64Block1.equals(i, decimal128Block1, i)); + Assert.assertTrue("Failed at : " + i, decimal128Block1.equals(i, decimal128Block2, i)); + Assert.assertTrue("Failed at : " + i, decimal128Block1.equals(i, decimal64Block1, i)); + Assert.assertTrue("Failed at : " + i, decimal128Block2.equals(i, decimal128Block1, i)); + Assert.assertTrue("Failed at : " + i, decimal64Block1.equals(i, normalBlock1, i)); + Assert.assertTrue("Failed at : " + i, decimal128Block1.equals(i, normalBlock1, i)); + Assert.assertTrue("Failed at : " + i, normalBlock1.equals(i, decimal64Block1, i)); + Assert.assertTrue("Failed at : " + i, normalBlock1.equals(i, normalBlock2, i)); + } else { + Assert.assertFalse("Failed at : " + i, decimal64Block1.equals(i, decimal64Block2, i)); + Assert.assertFalse("Failed at : " + i, decimal64Block2.equals(i, decimal64Block1, i)); + Assert.assertFalse("Failed at : " + i, decimal64Block1.equals(i, decimal128Block1, i)); + Assert.assertFalse("Failed at : " + i, decimal128Block1.equals(i, decimal128Block2, i)); + Assert.assertFalse("Failed at : " + i, decimal128Block1.equals(i, decimal64Block1, i)); + Assert.assertFalse("Failed at : " + i, decimal128Block2.equals(i, decimal128Block1, i)); + Assert.assertFalse("Failed at : " + i, decimal64Block1.equals(i, normalBlock2, i)); + Assert.assertFalse("Failed at : " + i, decimal128Block1.equals(i, normalBlock1, i)); + Assert.assertFalse("Failed at : " + i, normalBlock2.equals(i, decimal64Block1, i)); + Assert.assertFalse("Failed at : " + i, normalBlock1.equals(i, decimal128Block1, i)); + } + } + } + /** * generate random unsigned decimal128 String */ @@ -668,6 +774,13 @@ public void testCopyDecimal64() { testCopySelected(decimal64Block, normalOutput, selCount); Assert.assertTrue("Actual state: " + normalOutput.getState(), normalOutput.getState().isNormal()); + try { + normalOutput.allocateDecimal64(); + Assert.fail("Should fail since it is in normal state"); + } catch (IllegalStateException e) { + Assert.assertTrue(e.getMessage(), e.getMessage().contains("Should not allocate decimal64")); + } + // test with selection normalOutput = new DecimalBlock(decimalType, count); testCopySelected(decimal64Block, normalOutput, sel, selCount); @@ -729,6 +842,13 @@ public void testCopyDecimal128() { testCopySelected(decimal128Block, normalOutput, selCount); Assert.assertTrue("Actual state: " + normalOutput.getState(), normalOutput.getState().isNormal()); + try { + normalOutput.allocateDecimal128(); + Assert.fail("Should fail since it is in normal state"); + } catch (IllegalStateException e) { + Assert.assertTrue(e.getMessage().contains("Should not allocate decimal128")); + } + // test with selection normalOutput = new DecimalBlock(decimalType, count); testCopySelected(decimal128Block, normalOutput, sel, selCount); diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/DoubleBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/DoubleBlockTest.java new file mode 100644 index 000000000..6b0193c6f --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/DoubleBlockTest.java @@ -0,0 +1,115 @@ +package com.alibaba.polardbx.executor.chunk; + +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class DoubleBlockTest extends BaseBlockTest { + private final int count = 16; + private int[] sel; + + @Before + public void before() { + this.sel = new int[count / 2]; + for (int i = 0; i < count / 2; i++) { + sel[i] = i * 2; + } + } + + @Test + public void test() { + DoubleBlockBuilder blockBuilder = new DoubleBlockBuilder(count); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeDouble(i * 1.23D); + } + blockBuilder.appendNull(); + DoubleBlock fromBlock = (DoubleBlock) blockBuilder.build(); + + DoubleBlock newBlock = DoubleBlock.from(fromBlock, fromBlock.positionCount, null); + int[] hashCodes = fromBlock.hashCodeVector(); + int[] newHashCodes = new int[hashCodes.length]; + newBlock.hashCodeVector(newHashCodes, newHashCodes.length); + for (int i = 0; i < count; i++) { + if (fromBlock.isNull(i)) { + Assert.assertTrue(newBlock.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, fromBlock.getDouble(i), newBlock.getDouble(i), 1e-10); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCode(i), newBlock.hashCode(i)); + Assert.assertEquals("Failed at pos: " + i, hashCodes[i], newBlock.hashCode(i)); + Assert.assertEquals("Failed at pos: " + i, hashCodes[i], newHashCodes[i]); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCodeUseXxhash(i), newBlock.hashCodeUseXxhash(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.checksum(i), newBlock.checksum(i)); + } + DoubleBlock newBlock2 = DoubleBlock.from(fromBlock, sel.length, sel); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + if (fromBlock.isNull(j)) { + Assert.assertTrue(newBlock2.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, fromBlock.getDouble(j), newBlock2.getDouble(i), 1e-10); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCode(j), newBlock2.hashCode(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCodeUseXxhash(j), newBlock2.hashCodeUseXxhash(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.checksum(j), newBlock2.checksum(i)); + } + Assert.assertTrue(newBlock.estimateSize() > 0); + + DoubleBlockBuilder blockBuilder2 = new DoubleBlockBuilder(count); + for (int i = 0; i < count; i++) { + fromBlock.writePositionTo(i, blockBuilder2); + } + DoubleBlock newBlock3 = (DoubleBlock) blockBuilder2.build(); + for (int i = 0; i < count; i++) { + if (fromBlock.isNull(i)) { + Assert.assertTrue(newBlock3.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, fromBlock.getDouble(i), newBlock3.getDouble(i), 1e-10); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCode(i), newBlock3.hashCode(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCodeUseXxhash(i), newBlock3.hashCodeUseXxhash(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.checksum(i), newBlock3.checksum(i)); + } + + DoubleBlock newBlock4 = new DoubleBlock(DataTypes.DoubleType, count); + fromBlock.copySelected(false, null, count, newBlock4); + for (int i = 0; i < count; i++) { + if (fromBlock.isNull(i)) { + Assert.assertTrue(newBlock4.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, fromBlock.getDouble(i), newBlock4.getDouble(i), 1e-10); + } + DoubleBlock newBlock5 = new DoubleBlock(DataTypes.DoubleType, count); + fromBlock.copySelected(true, sel, sel.length, newBlock5); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + if (fromBlock.isNull(j)) { + Assert.assertTrue(newBlock5.isNull(j)); + continue; + } + Assert.assertEquals("Failed at pos: " + j, fromBlock.getDouble(j), newBlock5.getDouble(j), 1e-10); + } + + DoubleBlock newBlock6 = new DoubleBlock(DataTypes.DoubleType, count); + // just compare reference since it is a shallow copy + fromBlock.shallowCopyTo(newBlock6); + Assert.assertSame(fromBlock.doubleArray(), newBlock6.doubleArray()); + + // compact should work + fromBlock.compact(sel); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + if (fromBlock.isNull(i)) { + Assert.assertTrue(newBlock.isNull(j)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, fromBlock.getDouble(i), newBlock3.getDouble(j), 1e-10); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCode(i), newBlock3.hashCode(j)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCodeUseXxhash(i), newBlock3.hashCodeUseXxhash(j)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.checksum(i), newBlock3.checksum(j)); + } + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/EnumBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/EnumBlockTest.java new file mode 100644 index 000000000..d7e94b074 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/EnumBlockTest.java @@ -0,0 +1,70 @@ +package com.alibaba.polardbx.executor.chunk; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class EnumBlockTest extends BaseBlockTest { + private final int count = 16; + private Map enumMap; + private int[] sel; + + @Before + public void before() { + this.enumMap = new HashMap<>(); + this.enumMap.put("a", 1); + this.enumMap.put("b", 2); + this.enumMap.put("c", 3); + this.sel = new int[count / 2]; + for (int i = 0; i < count / 2; i++) { + sel[i] = i * 2; + } + } + + @Test + public void test() { + EnumBlockBuilder blockBuilder = new EnumBlockBuilder(count, 16, enumMap); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf((char) ('a' + i % enumMap.size()))); + } + blockBuilder.appendNull(); + EnumBlock fromBlock = (EnumBlock) blockBuilder.build(); + + EnumBlock newBlock = EnumBlock.from(fromBlock, fromBlock.positionCount, null); + for (int i = 0; i < count; i++) { + Assert.assertEquals("Failed at pos: " + i, fromBlock.getString(i), newBlock.getString(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCode(i), newBlock.hashCode(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCodeUseXxhash(i), newBlock.hashCodeUseXxhash(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.checksum(i), newBlock.checksum(i)); + Assert.assertTrue("Failed at pos: " + i, fromBlock.equals(i, newBlock, i)); + Assert.assertTrue("Failed at pos: " + i, fromBlock.equals(i, blockBuilder, i)); + } + EnumBlock newBlock2 = EnumBlock.from(fromBlock, sel.length, sel); + // should do nothing after compact + fromBlock.compact(sel); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + i, fromBlock.getString(j), newBlock2.getString(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCode(j), newBlock2.hashCode(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCodeUseXxhash(j), newBlock2.hashCodeUseXxhash(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.checksum(j), newBlock2.checksum(i)); + } + Assert.assertTrue(newBlock.estimateSize() > 0); + + EnumBlockBuilder blockBuilder2 = new EnumBlockBuilder(count, 16, enumMap); + for (int i = 0; i < count; i++) { + fromBlock.writePositionTo(i, blockBuilder2); + } + EnumBlock newBlock3 = (EnumBlock) blockBuilder2.build(); + for (int i = 0; i < count; i++) { + Assert.assertEquals("Failed at pos: " + i, fromBlock.getString(i), newBlock3.getString(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCode(i), newBlock3.hashCode(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCodeUseXxhash(i), newBlock3.hashCodeUseXxhash(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.checksum(i), newBlock3.checksum(i)); + } + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/FloatBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/FloatBlockTest.java new file mode 100644 index 000000000..4c6c32622 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/FloatBlockTest.java @@ -0,0 +1,115 @@ +package com.alibaba.polardbx.executor.chunk; + +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class FloatBlockTest extends BaseBlockTest { + private final int count = 16; + private int[] sel; + + @Before + public void before() { + this.sel = new int[count / 2]; + for (int i = 0; i < count / 2; i++) { + sel[i] = i * 2; + } + } + + @Test + public void test() { + FloatBlockBuilder blockBuilder = new FloatBlockBuilder(count); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeFloat(i * 1.23F); + } + blockBuilder.appendNull(); + FloatBlock fromBlock = (FloatBlock) blockBuilder.build(); + + FloatBlock newBlock = FloatBlock.from(fromBlock, fromBlock.positionCount, null); + int[] hashCodes = fromBlock.hashCodeVector(); + int[] newHashCodes = new int[hashCodes.length]; + newBlock.hashCodeVector(newHashCodes, newHashCodes.length); + for (int i = 0; i < count; i++) { + if (fromBlock.isNull(i)) { + Assert.assertTrue(newBlock.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, fromBlock.getFloat(i), newBlock.getFloat(i), 1e-10); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCode(i), newBlock.hashCode(i)); + Assert.assertEquals("Failed at pos: " + i, hashCodes[i], newBlock.hashCode(i)); + Assert.assertEquals("Failed at pos: " + i, hashCodes[i], newHashCodes[i]); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCodeUseXxhash(i), newBlock.hashCodeUseXxhash(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.checksum(i), newBlock.checksum(i)); + } + FloatBlock newBlock2 = FloatBlock.from(fromBlock, sel.length, sel); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + if (fromBlock.isNull(j)) { + Assert.assertTrue(newBlock2.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, fromBlock.getFloat(j), newBlock2.getFloat(i), 1e-10); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCode(j), newBlock2.hashCode(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCodeUseXxhash(j), newBlock2.hashCodeUseXxhash(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.checksum(j), newBlock2.checksum(i)); + } + Assert.assertTrue(newBlock.estimateSize() > 0); + + FloatBlockBuilder blockBuilder2 = new FloatBlockBuilder(count); + for (int i = 0; i < count; i++) { + fromBlock.writePositionTo(i, blockBuilder2); + } + FloatBlock newBlock3 = (FloatBlock) blockBuilder2.build(); + for (int i = 0; i < count; i++) { + if (fromBlock.isNull(i)) { + Assert.assertTrue(newBlock3.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, fromBlock.getFloat(i), newBlock3.getFloat(i), 1e-10); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCode(i), newBlock3.hashCode(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCodeUseXxhash(i), newBlock3.hashCodeUseXxhash(i)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.checksum(i), newBlock3.checksum(i)); + } + + FloatBlock newBlock4 = new FloatBlock(DataTypes.FloatType, count); + fromBlock.copySelected(false, null, count, newBlock4); + for (int i = 0; i < count; i++) { + if (fromBlock.isNull(i)) { + Assert.assertTrue(newBlock4.isNull(i)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, fromBlock.getFloat(i), newBlock4.getFloat(i), 1e-10); + } + FloatBlock newBlock5 = new FloatBlock(DataTypes.FloatType, count); + fromBlock.copySelected(true, sel, sel.length, newBlock5); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + if (fromBlock.isNull(j)) { + Assert.assertTrue(newBlock5.isNull(j)); + continue; + } + Assert.assertEquals("Failed at pos: " + j, fromBlock.getFloat(j), newBlock5.getFloat(j), 1e-10); + } + + FloatBlock newBlock6 = new FloatBlock(DataTypes.FloatType, count); + // just compare reference since it is a shallow copy + fromBlock.shallowCopyTo(newBlock6); + Assert.assertSame(fromBlock.floatArray(), newBlock6.floatArray()); + + // compact should work + fromBlock.compact(sel); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + if (fromBlock.isNull(i)) { + Assert.assertTrue(newBlock.isNull(j)); + continue; + } + Assert.assertEquals("Failed at pos: " + i, fromBlock.getFloat(i), newBlock3.getFloat(j), 1e-10); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCode(i), newBlock3.hashCode(j)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.hashCodeUseXxhash(i), newBlock3.hashCodeUseXxhash(j)); + Assert.assertEquals("Failed at pos: " + i, fromBlock.checksum(i), newBlock3.checksum(j)); + } + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/LongBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/LongBlockTest.java index cff31d455..d9e54ad82 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/LongBlockTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/LongBlockTest.java @@ -83,4 +83,67 @@ public void test() { assertEquals(block.hashCode(i), anotherBuilder.hashCode(i)); } } + + @Test + public void testNotSupportedOperation() { + LongBlock longBlock = LongBlock.of(1L, 2L, 3L, 4L); + expectUnsupportedException(() -> longBlock.getByte(0)); + expectUnsupportedException(() -> longBlock.getShort(0)); + expectUnsupportedException(() -> longBlock.getDouble(0)); + expectUnsupportedException(() -> longBlock.getFloat(0)); + expectUnsupportedException(() -> longBlock.getTimestamp(0)); + expectUnsupportedException(() -> longBlock.getDate(0)); + expectUnsupportedException(() -> longBlock.getTime(0)); + expectUnsupportedException(() -> longBlock.getString(0)); + expectUnsupportedException(() -> longBlock.getDecimal(0)); + expectUnsupportedException(() -> longBlock.getBigInteger(0)); + expectUnsupportedException(() -> longBlock.getBoolean(0)); + expectUnsupportedException(() -> longBlock.getByteArray(0)); + expectUnsupportedException(() -> longBlock.getBlob(0)); + expectUnsupportedException(() -> longBlock.getClob(0)); + } + + @Test + public void testBuilderNotSupportedOperation() { + LongBlockBuilder longBlockBuilder = new LongBlockBuilder(4); + expectUnsupportedException(() -> longBlockBuilder.writeByte((byte) 0)); + expectUnsupportedException(() -> longBlockBuilder.writeShort((short) 0)); + expectUnsupportedException(() -> longBlockBuilder.writeDouble(0D)); + expectUnsupportedException(() -> longBlockBuilder.writeFloat(0F)); + expectUnsupportedException(() -> longBlockBuilder.writeTimestamp(null)); + expectUnsupportedException(() -> longBlockBuilder.writeDate(null)); + expectUnsupportedException(() -> longBlockBuilder.writeTime(null)); + expectUnsupportedException(() -> longBlockBuilder.writeString(null)); + expectUnsupportedException(() -> longBlockBuilder.writeDecimal(null)); + expectUnsupportedException(() -> longBlockBuilder.writeBigInteger(null)); + expectUnsupportedException(() -> longBlockBuilder.writeBoolean(true)); + expectUnsupportedException(() -> longBlockBuilder.writeByteArray(null)); + expectUnsupportedException(() -> longBlockBuilder.writeBlob(null)); + expectUnsupportedException(() -> longBlockBuilder.writeClob(null)); + } + + @Test + public void illegalCastTest() { + LongBlock longBlock = new LongBlock(new LongType(), 1024); + try { + longBlock.cast(ShortBlock.class); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("failed to cast")); + } + } + + private void expectUnsupportedException(FunctionInterface notSupportedFunc) { + try { + notSupportedFunc.execute(); + Assert.fail("Expect not supported"); + } catch (Exception e) { + Assert.assertTrue(e instanceof UnsupportedOperationException); + Assert.assertTrue(e.getMessage().contains(LongBlock.class.getName())); + } + } + + @FunctionalInterface + interface FunctionInterface { + void execute(); + } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/RFReadWriteTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/RFReadWriteTest.java index 1a3a51560..ea510257e 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/RFReadWriteTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/RFReadWriteTest.java @@ -1,6 +1,8 @@ package com.alibaba.polardbx.executor.chunk; +import com.alibaba.polardbx.common.datatype.UInt64; import com.alibaba.polardbx.common.utils.bloomfilter.BlockLongBloomFilter; +import com.alibaba.polardbx.common.utils.bloomfilter.ConcurrentIntBloomFilter; import com.alibaba.polardbx.common.utils.bloomfilter.RFBloomFilter; import org.junit.Assert; import org.junit.Test; @@ -177,4 +179,111 @@ public void testLocalRFConjunctive() { } } } + + @Test + public void testULongBroadcastRF() { + // store 1 ~ 100 + ULongBlockBuilder builder = new ULongBlockBuilder(4); + for (long i = 1; i <= 100; i++) { + builder.writeUInt64(UInt64.fromLong(i)); + } + Block block = builder.build(); + + // global rf + RFBloomFilter bloomFilter = new BlockLongBloomFilter(BLOOM_FILTER_ELEMENT_COUNT); + + // write into runtime filter + block.addLongToBloomFilter(bloomFilter); + + // for rf checking + boolean[] bitmap = new boolean[CHUNK_LIMIT]; + Arrays.fill(bitmap, false); + + // check 0 ~ 999 + builder = new ULongBlockBuilder(4); + for (long i = 0; i < 1000; i++) { + builder.writeUInt64(UInt64.fromLong(i)); + } + block = builder.build(); + + int hitCount = block.mightContainsLong(bloomFilter, bitmap); + Assert.assertEquals(100, hitCount); + for (int i = 0; i < 1000; i++) { + if (i >= 1 && i <= 100) { + Assert.assertTrue(bitmap[i]); + } else { + Assert.assertFalse(bitmap[i]); + } + } + } + + @Test + public void testIntBroadcastRF() { + // store 1 ~ 100 + IntegerBlockBuilder builder = new IntegerBlockBuilder(4); + for (int i = 1; i <= 100; i++) { + builder.writeInt(i); + } + Block block = builder.build(); + + // global rf + RFBloomFilter bloomFilter = new BlockLongBloomFilter(BLOOM_FILTER_ELEMENT_COUNT); + + // write into runtime filter + block.addLongToBloomFilter(bloomFilter); + + // for rf checking + boolean[] bitmap = new boolean[CHUNK_LIMIT]; + Arrays.fill(bitmap, false); + + // check 0 ~ 999 + builder = new IntegerBlockBuilder(4); + for (int i = 0; i < 1000; i++) { + builder.writeInt(i); + } + block = builder.build(); + + int hitCount = block.mightContainsLong(bloomFilter, bitmap); + Assert.assertEquals(100, hitCount); + for (int i = 0; i < 1000; i++) { + if (i >= 1 && i <= 100) { + Assert.assertTrue(bitmap[i]); + } else { + Assert.assertFalse(bitmap[i]); + } + } + } + + @Test + public void testIntBroadcastRF2() { + // store 1 ~ 100 + IntegerBlockBuilder builder = new IntegerBlockBuilder(4); + for (int i = 1; i <= 100; i++) { + builder.writeInt(i); + } + Block block = builder.build(); + + // global rf + RFBloomFilter bloomFilter = ConcurrentIntBloomFilter.create(BLOOM_FILTER_ELEMENT_COUNT); + + // write into runtime filter + block.addIntToBloomFilter(bloomFilter); + + // for rf checking + boolean[] bitmap = new boolean[CHUNK_LIMIT]; + Arrays.fill(bitmap, false); + + // check 0 ~ 999 + builder = new IntegerBlockBuilder(4); + for (int i = 0; i < 1000; i++) { + builder.writeInt(i); + } + block = builder.build(); + + int hitCount = block.mightContainsInt(bloomFilter, bitmap); + Assert.assertTrue("hit count is higher than expected", hitCount < 110); + for (int i = 1; i < 100; i++) { + Assert.assertTrue(bitmap[i]); + } + } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/ShortBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/ShortBlockTest.java index 59cb8405d..3c850adb5 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/ShortBlockTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/ShortBlockTest.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.executor.chunk; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.datatype.ShortType; import org.junit.Assert; import org.junit.Test; @@ -87,5 +88,42 @@ public void test() { assertTrue(block.equals(i, anotherBuilder, i)); assertEquals(block.hashCode(i), anotherBuilder.hashCode(i)); } + + ShortBlock shortBlock = (ShortBlock) block; + ShortBlock newBlock1 = new ShortBlock(DataTypes.ShortType, block.getPositionCount()); + shortBlock.shallowCopyTo(newBlock1); + int[] hashCodes1 = block.hashCodeVector(); + int[] hashCodes2 = new int[hashCodes1.length]; + block.hashCodeVector(hashCodes2, hashCodes2.length); + for (int i = 0; i < newBlock1.positionCount; i++) { + assertEquals(block.hashCodeUseXxhash(i), newBlock1.hashCodeUseXxhash(i)); + assertEquals(block.getObject(i), newBlock1.getObject(i)); + assertEquals(hashCodes1[i], newBlock1.hashCode(i)); + assertEquals(hashCodes2[i], newBlock1.hashCode(i)); + } + + int[] sel = new int[] {1, 2, 3}; + ShortBlock newBlock2 = new ShortBlock(DataTypes.ShortType, block.getPositionCount()); + shortBlock.copySelected(false, null, shortBlock.positionCount, newBlock2); + for (int i = 0; i < newBlock1.positionCount; i++) { + assertEquals(shortBlock.getObject(i), newBlock2.getObject(i)); + } + ShortBlock newBlock3 = new ShortBlock(DataTypes.ShortType, block.getPositionCount()); + shortBlock.copySelected(true, sel, sel.length, newBlock3); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + assertEquals(shortBlock.getObject(j), newBlock3.getObject(j)); + } + IntegerBlock newBlock4 = new IntegerBlock(DataTypes.IntegerType, block.getPositionCount()); + shortBlock.copySelected(true, sel, sel.length, newBlock4); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + assertEquals(shortBlock.getShort(j), newBlock4.getInt(j)); + } + + shortBlock.compact(null); + // compact should work + shortBlock.compact(sel); + Assert.assertEquals(sel.length, shortBlock.positionCount); } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/SliceBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/SliceBlockTest.java index 2108f5715..722493994 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/SliceBlockTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/SliceBlockTest.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.charset.CharsetName; import com.alibaba.polardbx.common.charset.CollationName; +import com.alibaba.polardbx.executor.operator.scan.impl.LocalBlockDictionary; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.SliceType; import com.alibaba.polardbx.optimizer.core.datatype.VarcharType; @@ -87,10 +88,28 @@ public void test() { for (int i = 0; i < CHUNK_SIZE; i++) { Assert.assertTrue(sliceBlock.equals(i, block, i)); + Assert.assertEquals(sliceBlock.checksum(i), block.checksum(i)); + Assert.assertEquals(sliceBlock.hashCode(i), block.hashCode(i)); + Assert.assertEquals(sliceBlock.hashCodeUseXxhash(i), block.hashCodeUseXxhash(i)); } } + @Test + public void testDict() { + final int count = 10; + boolean[] nulls = new boolean[count]; + Slice[] dict = new Slice[] {Slices.utf8Slice("a"), Slices.utf8Slice("b"), Slices.utf8Slice("c")}; + int[] dictIds = new int[] {0, 1, 2, 0, 1, 2, 0, 1, 2, 0}; + LocalBlockDictionary dictionary1 = new LocalBlockDictionary(dict); + SliceBlock sliceBlock1 = new SliceBlock(new SliceType(), 0, count, + nulls, dictionary1, dictIds, false); + + for (int i = 0; i < dictIds.length; i++) { + Assert.assertEquals(1, sliceBlock1.equals(i, dict[dictIds[i]])); + } + } + @Test public void testCopyAllValues() { final boolean compatible = true; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/TimeBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/TimeBlockTest.java index 26b15e0d3..f3b842423 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/TimeBlockTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/TimeBlockTest.java @@ -1,19 +1,3 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.executor.chunk; import com.alibaba.polardbx.common.utils.time.RandomTimeGenerator; @@ -22,6 +6,7 @@ import io.airlift.slice.DynamicSliceOutput; import io.airlift.slice.Slice; import io.airlift.slice.SliceOutput; +import org.junit.Assert; import org.junit.Test; import java.util.List; @@ -69,9 +54,24 @@ public void testTime() { IntStream.range(0, TEST_SIZE) .forEach( i -> { - boolean isEqual = block.equals(i, block1, i); - assertTrue(isEqual); + Assert.assertTrue(block.equals(i, block1, i)); + Assert.assertTrue(block.equals(i, timeBlockBuilder, i)); } ); + + TimeBlock timeBlock = (TimeBlock) block; + TimeBlockBuilder builder = new TimeBlockBuilder(TEST_SIZE / 2, dataType, new ExecutionContext()); + for (int i = 0; i < TEST_SIZE; i++) { + timeBlock.writePositionTo(i, builder); + } + TimeBlock newBlock = (TimeBlock) builder.build(); + for (int i = 0; i < TEST_SIZE; i++) { + Assert.assertEquals(timeBlock.getTime(i), newBlock.getTime(i)); + Assert.assertEquals(timeBlock.getObject(i), newBlock.getObject(i)); + Assert.assertEquals(timeBlock.getPackedLong(i), newBlock.getPackedLong(i)); + Assert.assertEquals(timeBlock.getLong(i), newBlock.getLong(i)); + Assert.assertEquals(timeBlock.hashCode(i), newBlock.hashCode(i)); + Assert.assertEquals(timeBlock.hashCodeUseXxhash(i), newBlock.hashCodeUseXxhash(i)); + } } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/TimestampBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/TimestampBlockTest.java index 327ac475f..f32fbc27c 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/TimestampBlockTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/TimestampBlockTest.java @@ -25,14 +25,19 @@ import org.junit.Assert; import org.junit.Test; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Random; +import java.util.TimeZone; import java.util.stream.Collectors; import java.util.stream.IntStream; public class TimestampBlockTest extends BaseBlockTest { private final static Random R = new Random(); - private final static int TEST_SIZE = 1 << 20; + private final static int TEST_SIZE = 1 << 10; private final static int TEST_SCALE = 4; @Test @@ -67,9 +72,76 @@ public void testTimestamp() { IntStream.range(0, TEST_SIZE) .forEach( i -> { - boolean isEqual = block.equals(i, block1, i); - Assert.assertTrue(isEqual); + Assert.assertTrue(block.equals(i, block1, i)); + Assert.assertTrue(block.equals(i, timestampBlockBuilder, i)); } ); + + TimestampBlock timestampBlock = (TimestampBlock) block; + TimestampBlockBuilder builder = new TimestampBlockBuilder(TEST_SIZE / 2, dataType, new ExecutionContext()); + for (int i = 0; i < TEST_SIZE; i++) { + timestampBlock.writePositionTo(i, builder); + } + TimestampBlock newBlock = (TimestampBlock) builder.build(); + for (int i = 0; i < TEST_SIZE; i++) { + Assert.assertEquals(timestampBlock.getTimestamp(i), newBlock.getTimestamp(i)); + Assert.assertEquals(timestampBlock.getObject(i), newBlock.getObject(i)); + Assert.assertEquals(timestampBlock.getObjectForCmp(i), newBlock.getObjectForCmp(i)); + Assert.assertEquals(timestampBlock.hashCode(i), newBlock.hashCode(i)); + Assert.assertEquals(timestampBlock.hashCodeUseXxhash(i), newBlock.hashCodeUseXxhash(i)); + } + + } + + @Test + public void testFrom() { + final TimestampType dataType = new TimestampType(TEST_SCALE); + + TimestampBlockBuilder builder = new TimestampBlockBuilder(TEST_SIZE / 2, dataType, new ExecutionContext()); + for (int i = 0; i < TEST_SIZE - 1; i++) { + builder.writeString(RandomTimeGenerator.generateStandardTimestamp().substring(0, 19)); + } + builder.appendNull(); + TimestampBlock timestampBlock = (TimestampBlock) builder.build(); + + TimestampBlock newBlock2 = TimestampBlock.from(timestampBlock, TimeZone.getDefault()); + for (int i = 0; i < TEST_SIZE; i++) { + Assert.assertEquals(timestampBlock.getTimestamp(i), newBlock2.getTimestamp(i)); + } + + final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + final String targetZone = "GMT+6"; + final ZoneId targetZoneId = ZoneId.of("GMT+6"); + + TimestampBlock newBlock3 = TimestampBlock.from(timestampBlock, TimeZone.getTimeZone(targetZone)); + for (int i = 0; i < TEST_SIZE; i++) { + if (timestampBlock.isNull(i)) { + Assert.assertTrue(newBlock3.isNull(i)); + continue; + } + String original = timestampBlock.getTimestamp(i).toString(); + LocalDateTime localDateTime = LocalDateTime.parse(original, formatter); + ZonedDateTime originalZoneDateTime = localDateTime.atZone(TimeZone.getDefault().toZoneId()); + ZonedDateTime targetZoneDateTime = originalZoneDateTime.withZoneSameInstant(targetZoneId); + String expectResult = targetZoneDateTime.format(formatter); + Assert.assertEquals(expectResult, newBlock3.getTimestamp(i).toString()); + } + + final String targetZone2 = "GMT+10"; + final ZoneId targetZoneId2 = ZoneId.of("GMT+10"); + TimestampBlock newBlock4 = + TimestampBlock.from(timestampBlock, TEST_SIZE, null, false, TimeZone.getTimeZone(targetZone2)); + for (int i = 0; i < TEST_SIZE; i++) { + if (timestampBlock.isNull(i)) { + Assert.assertTrue(newBlock4.isNull(i)); + continue; + } + String original = timestampBlock.getTimestamp(i).toString(); + LocalDateTime localDateTime = LocalDateTime.parse(original, formatter); + ZonedDateTime originalZoneDateTime = localDateTime.atZone(TimeZone.getDefault().toZoneId()); + ZonedDateTime targetZoneDateTime = originalZoneDateTime.withZoneSameInstant(targetZoneId2); + String expectResult = targetZoneDateTime.format(formatter); + Assert.assertEquals(expectResult, newBlock4.getTimestamp(i).toString()); + } } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/ULongBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/ULongBlockTest.java index 79d4326a4..519ac80c2 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/ULongBlockTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/chunk/ULongBlockTest.java @@ -17,6 +17,7 @@ package com.alibaba.polardbx.executor.chunk; import com.alibaba.polardbx.common.datatype.UInt64; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.datatype.ULongType; import io.airlift.slice.DynamicSliceOutput; import io.airlift.slice.SliceInput; @@ -119,4 +120,57 @@ public void testEncoding() { Assert.assertEquals(block.getObject(i), block1.getObject(i)); } } + + @Test + public void test() { + int count = 100; + ULongBlockBuilder builder1 = new ULongBlockBuilder(count / 2); + for (int i = 0; i < count - 1; i++) { + builder1.writeLong(i); + } + builder1.appendNull(); + ULongBlock ulongBlock = (ULongBlock) builder1.build(); + ULongBlockBuilder builder2 = new ULongBlockBuilder(1); + for (int i = 0; i < count; i++) { + ulongBlock.writePositionTo(i, builder2); + } + ULongBlock newBlock = (ULongBlock) builder2.build(); + Assert.assertSame(DataTypes.ULongType, newBlock.getType()); + int[] hashes = newBlock.hashCodeVector(); + int[] hashes2 = new int[hashes.length]; + newBlock.hashCodeVector(hashes2, hashes2.length); + for (int i = 0; i < count; i++) { + Assert.assertEquals(ulongBlock.getObject(i), newBlock.getObject(i)); + Assert.assertEquals(ulongBlock.getElementAtUnchecked(i), newBlock.getElementAtUnchecked(i)); + Assert.assertEquals(ulongBlock.getLong(i), newBlock.getLong(i)); + Assert.assertEquals(ulongBlock.hashCode(i), newBlock.hashCode(i)); + Assert.assertEquals(ulongBlock.hashCode(i), hashes[i]); + Assert.assertEquals(ulongBlock.hashCode(i), hashes2[i]); + Assert.assertEquals(ulongBlock.hashCodeUseXxhash(i), newBlock.hashCodeUseXxhash(i)); + } + + ULongBlock newBlock2 = new ULongBlock(DataTypes.ULongType, count); + newBlock.shallowCopyTo(newBlock2); + Assert.assertSame(newBlock.longArray(), newBlock2.longArray()); + + int[] sel = new int[] {0, 1, 2, 3, 4, 11, 12, 13, 14}; + ULongBlock newBlock3 = new ULongBlock(DataTypes.ULongType, count); + newBlock.copySelected(false, null, count, newBlock3); + for (int i = 0; i < count; i++) { + Assert.assertEquals(newBlock3.getObject(i), newBlock.getObject(i)); + } + newBlock.copySelected(true, sel, sel.length, newBlock3); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals(newBlock3.getObject(j), newBlock.getObject(j)); + } + LongBlock longBlock = new LongBlock(DataTypes.LongType, count); + newBlock.copySelected(false, null, count, longBlock); + for (int i = 0; i < count; i++) { + Assert.assertEquals(longBlock.getLong(i), newBlock.getLong(i)); + } + // compact should work + newBlock.compact(sel); + Assert.assertEquals(sel.length, newBlock.getPositionCount()); + } } \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/checker/CciFastCheckerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/checker/CciFastCheckerTest.java new file mode 100644 index 000000000..e3b2b3bfd --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/checker/CciFastCheckerTest.java @@ -0,0 +1,174 @@ +package com.alibaba.polardbx.executor.columnar.checker; + +import com.alibaba.polardbx.common.IInnerConnection; +import com.alibaba.polardbx.common.IInnerConnectionManager; +import com.alibaba.polardbx.common.RevisableOrderInvariantHash; +import com.alibaba.polardbx.common.utils.thread.ServerThreadPool; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; +import com.alibaba.polardbx.gms.metadb.table.FilesRecordSimplifiedWithChecksum; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.rpc.compatible.ArrayResultSet; +import com.google.common.util.concurrent.Futures; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.sql.Connection; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class CciFastCheckerTest { + @Test + public void testCalculateColumnarChecksum() throws Throwable { + String schema = "test"; + String table = "test"; + String index = "test"; + long tso = 100L; + long tableId = 100L; + long orcChecksum = 100L; + long deletedChecksum = 200L; + long csvChecksum = 300L; + try (MockedStatic iCciCheckerMockedStatic = mockStatic(ICciChecker.class); + MockedStatic metaDbUtilMockedStatic = mockStatic(MetaDbUtil.class);) { + // mock mock + iCciCheckerMockedStatic.when(() -> ICciChecker.getTableId(schema, index)).thenReturn(tableId); + List records = new ArrayList<>(); + // orc + FilesRecordSimplifiedWithChecksum filesRecordSimplifiedWithChecksum = + new FilesRecordSimplifiedWithChecksum(); + filesRecordSimplifiedWithChecksum.fileName = "test.orc"; + filesRecordSimplifiedWithChecksum.partitionName = "p0"; + filesRecordSimplifiedWithChecksum.commitTs = tso; + filesRecordSimplifiedWithChecksum.checksum = orcChecksum; + filesRecordSimplifiedWithChecksum.deletedChecksum = -1L; + records.add(filesRecordSimplifiedWithChecksum); + // csv + filesRecordSimplifiedWithChecksum = new FilesRecordSimplifiedWithChecksum(); + filesRecordSimplifiedWithChecksum.fileName = "test.csv"; + filesRecordSimplifiedWithChecksum.partitionName = "p0"; + records.add(filesRecordSimplifiedWithChecksum); + // del + filesRecordSimplifiedWithChecksum = new FilesRecordSimplifiedWithChecksum(); + filesRecordSimplifiedWithChecksum.fileName = "test.del"; + filesRecordSimplifiedWithChecksum.partitionName = "p0"; + records.add(filesRecordSimplifiedWithChecksum); + iCciCheckerMockedStatic.when(() -> ICciChecker.getFilesRecords(tso, tableId, schema)).thenReturn(records); + + metaDbUtilMockedStatic.when(MetaDbUtil::getConnection).thenReturn(mock(Connection.class)); + List columnarAppendedFilesRecords = new ArrayList<>(); + ColumnarAppendedFilesRecord columnarAppendedFilesRecord = new ColumnarAppendedFilesRecord(); + columnarAppendedFilesRecord.fileName = "test.csv"; + columnarAppendedFilesRecord.partName = "p0"; + columnarAppendedFilesRecord.appendOffset = 0; + columnarAppendedFilesRecord.appendLength = 100; + columnarAppendedFilesRecords.add(columnarAppendedFilesRecord); + metaDbUtilMockedStatic.when(() -> MetaDbUtil.query(any(), any(), any(), any())) + .thenReturn(columnarAppendedFilesRecords); + + ServerThreadPool serverThreadPool = mock(ServerThreadPool.class); + doAnswer( + invocation -> { + Object[] args = invocation.getArguments(); + ((Runnable) args[0]).run(); + return null; + } + ).when(serverThreadPool).execute(any()); + IInnerConnectionManager innerConnectionManager = mock(IInnerConnectionManager.class); + IInnerConnection innerConnection = mock(IInnerConnection.class); + when(innerConnectionManager.getConnection(schema)).thenReturn(innerConnection); + Statement stmt = mock(Statement.class); + when(innerConnection.createStatement()).thenReturn(stmt); + when(stmt.executeQuery(any())).then( + invocation -> { + Object[] args = invocation.getArguments(); + String sql = args[0].toString(); + if (sql.contains("READ_ORC_ONLY=true ENABLE_OSS_DELETED_SCAN=true")) { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("checksum"); + rs.getRows().add(new Object[] {deletedChecksum}); + return rs; + } else if (sql.contains("READ_CSV_ONLY=true")) { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("checksum"); + rs.getRows().add(new Object[] {csvChecksum}); + return rs; + } + throw new RuntimeException(); + } + ); + + CciFastChecker checker = new CciFastChecker(schema, table, index); + ExecutionContext ec = new ExecutionContext(); + + doNothing().when(innerConnection).addExecutionContextInjectHook(any()); + + DdlContext ddlContext = new DdlContext(); + ec.setDdlContext(ddlContext); + + checker.calculateColumnarChecksum(ec, 100L, serverThreadPool, innerConnectionManager); + + RevisableOrderInvariantHash hash = new RevisableOrderInvariantHash(); + hash.add(orcChecksum).remove(0).remove(deletedChecksum).add(0).add(csvChecksum).remove(0); + Assert.assertEquals(hash.getResult().longValue(), checker.getColumnarHashCode()); + } + } + + @Test + public void testCalculatePrimaryChecksum() throws Throwable { + String schema = "test"; + String table = "test"; + String index = "test"; + long tso = 100L; + + ServerThreadPool serverThreadPool = mock(ServerThreadPool.class); + when(serverThreadPool.submit(any(), any(), any(Callable.class))).then( + invocation -> { + Object[] args = invocation.getArguments(); + return Futures.immediateFuture(((Callable) args[2]).call()); + } + ); + IInnerConnectionManager innerConnectionManager = mock(IInnerConnectionManager.class); + IInnerConnection innerConnection = mock(IInnerConnection.class); + when(innerConnectionManager.getConnection(schema)).thenReturn(innerConnection); + Statement stmt = mock(Statement.class); + when(innerConnection.createStatement()).thenReturn(stmt); + when(stmt.executeQuery(any())).then( + invocation -> { + Object[] args = invocation.getArguments(); + String sql = args[0].toString(); + if (sql.contains("show topology from")) { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("GROUP_NAME"); + rs.getColumnName().add("TABLE_NAME"); + rs.getRows().add(new Object[] {"test_group", "test_table"}); + return rs; + } else if (sql.contains("select check_sum_v2(*) as checksum from")) { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("checksum"); + rs.getRows().add(new Object[] {100}); + return rs; + } + return new ArrayResultSet(); + } + ); + + ExecutionContext ec = new ExecutionContext(); + + DdlContext ddlContext = new DdlContext(); + ec.setDdlContext(ddlContext); + + CciFastChecker checker = new CciFastChecker(schema, table, index); + checker.calculatePrimaryChecksum(ec, tso, serverThreadPool, innerConnectionManager, null); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/checker/CciIncrementalCheckerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/checker/CciIncrementalCheckerTest.java new file mode 100644 index 000000000..03b27bb3a --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/checker/CciIncrementalCheckerTest.java @@ -0,0 +1,195 @@ +package com.alibaba.polardbx.executor.columnar.checker; + +import com.alibaba.polardbx.common.IInnerConnection; +import com.alibaba.polardbx.common.IInnerConnectionManager; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.common.utils.thread.ServerThreadPool; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.spi.ITopologyExecutor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; +import com.alibaba.polardbx.gms.metadb.table.FilesRecordSimplifiedWithChecksum; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.rpc.compatible.ArrayResultSet; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class CciIncrementalCheckerTest { + @Test + public void test() throws Throwable { + String schema = "test"; + String table = "test"; + String index = "test"; + long tsoV0 = 100L; + long tsoV1 = 200L; + + // Mock executor. + ExecutorContext executorContext = new ExecutorContext(); + ExecutorContext.setContext(schema, executorContext); + IInnerConnectionManager innerConnectionManager = mock(IInnerConnectionManager.class); + executorContext.setInnerConnectionManager(innerConnectionManager); + ITopologyExecutor topologyExecutor = mock(ITopologyExecutor.class); + executorContext.setTopologyExecutor(topologyExecutor); + ServerThreadPool serverThreadPool = mock(ServerThreadPool.class); + when(topologyExecutor.getExecutorService()).thenReturn(serverThreadPool); + ExecutorService threadPool = Executors.newFixedThreadPool(1); + when(serverThreadPool.submit(any(), any(), any(Callable.class))).then( + invocation -> { + Object[] args = invocation.getArguments(); + return threadPool.submit((Callable) args[2]); + } + ); + DynamicConfig.getInstance().loadValue(null, ConnectionProperties.CCI_INCREMENTAL_CHECK_PARALLELISM, "1"); + + // Mock result set. + Statement stmt = mock(Statement.class); + IInnerConnection innerConnection = mock(IInnerConnection.class); + when(innerConnectionManager.getConnection(schema)).thenReturn(innerConnection); + when(innerConnection.createStatement()).thenReturn(stmt); + when(stmt.executeQuery(any())).then( + invocation -> { + Object[] args = invocation.getArguments(); + String sql = args[0].toString(); + if (sql.contains("show topology from")) { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("GROUP_NAME"); + rs.getColumnName().add("TABLE_NAME"); + rs.getRows().add(new Object[] {"test_group", "test_table"}); + return rs; + } else if (sql.contains("select * from " + table)) { + MockResultSet rs = new MockResultSet(); + rs.getColumnName().add("id"); + rs.getColumnName().add("a"); + rs.getRows().add(new Object[] {100, 100}); + ResultSetMetaData metaData = mock(ResultSetMetaData.class); + rs.setMetaData(metaData); + when(metaData.getColumnCount()).thenReturn(2); + when(metaData.getColumnName(1)).thenReturn("a"); + when(metaData.getColumnName(2)).thenReturn("id"); + return rs; + } else if (sql.contains("select count(0) from test as of tso 200 where (a,id) in")) { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("count"); + rs.getRows().add(new Object[] {1}); + return rs; + } + return new ArrayResultSet(); + } + ); + + // Mock v0 files. + List v0Records = mockV0Files(); + List v1Records = mockV1Files(); + List v1AppendedFilesRecords = mockV1AppendedFilesRecords(); + + ExecutionContext ec = new ExecutionContext(); + DdlContext ddlContext = new DdlContext(); + ec.setDdlContext(ddlContext); + + try (MockedStatic iCciCheckerMockedStatic = mockStatic(ICciChecker.class); + MockedStatic metaDbUtilMockedStatic = mockStatic(MetaDbUtil.class);) { + iCciCheckerMockedStatic.when(() -> ICciChecker.getTableId(schema, index)).thenReturn(100L); + iCciCheckerMockedStatic.when(() -> ICciChecker.getFilesRecords(tsoV0, 100L, schema)).thenReturn(v0Records); + iCciCheckerMockedStatic.when(() -> ICciChecker.getFilesRecords(tsoV1, 100L, schema)).thenReturn(v1Records); + + metaDbUtilMockedStatic.when(() -> MetaDbUtil.query(any(), any(), any(), any())) + .thenReturn(v1AppendedFilesRecords); + + CciIncrementalChecker checker = new CciIncrementalChecker(schema, table, index); + checker.check(ec, tsoV0, tsoV1, tsoV1); + + List reports = new ArrayList<>(); + checker.getCheckReports(reports); + System.out.println(reports); + Assert.assertTrue(reports.size() == 1 && reports.get(0).contains( + "Incremental check passed for schema test, table test, index test , increment insert count 1")); + } + + threadPool.shutdown(); + } + + private static List mockV0Files() { + List records = new ArrayList<>(); + // orc + FilesRecordSimplifiedWithChecksum filesRecordSimplifiedWithChecksum = + new FilesRecordSimplifiedWithChecksum(); + filesRecordSimplifiedWithChecksum.fileName = "test_v0.orc"; + filesRecordSimplifiedWithChecksum.partitionName = "p0"; + records.add(filesRecordSimplifiedWithChecksum); + return records; + } + + private static List mockV1Files() { + List records = new ArrayList<>(); + // orc + FilesRecordSimplifiedWithChecksum filesRecordSimplifiedWithChecksum = + new FilesRecordSimplifiedWithChecksum(); + filesRecordSimplifiedWithChecksum.fileName = "test_v0.orc"; + filesRecordSimplifiedWithChecksum.partitionName = "p0"; + records.add(filesRecordSimplifiedWithChecksum); + filesRecordSimplifiedWithChecksum = + new FilesRecordSimplifiedWithChecksum(); + filesRecordSimplifiedWithChecksum.fileName = "test_v1.orc"; + filesRecordSimplifiedWithChecksum.partitionName = "p0"; + records.add(filesRecordSimplifiedWithChecksum); + // csv + filesRecordSimplifiedWithChecksum = new FilesRecordSimplifiedWithChecksum(); + filesRecordSimplifiedWithChecksum.fileName = "test.csv"; + filesRecordSimplifiedWithChecksum.partitionName = "p0"; + records.add(filesRecordSimplifiedWithChecksum); + // del + filesRecordSimplifiedWithChecksum = new FilesRecordSimplifiedWithChecksum(); + filesRecordSimplifiedWithChecksum.fileName = "test.del"; + filesRecordSimplifiedWithChecksum.partitionName = "p0"; + records.add(filesRecordSimplifiedWithChecksum); + return records; + } + + private List mockV1AppendedFilesRecords() { + List records = new ArrayList<>(); + ColumnarAppendedFilesRecord record = new ColumnarAppendedFilesRecord(); + record.setFileName("test.csv"); + record.setPartName("p0"); + record.setAppendOffset(0); + record.setAppendLength(100); + records.add(record); + + record = new ColumnarAppendedFilesRecord(); + record.setFileName("test.del"); + record.setPartName("p0"); + record.setAppendOffset(0); + record.setAppendLength(100); + records.add(record); + return records; + } + + private static class MockResultSet extends ArrayResultSet { + ResultSetMetaData metaData; + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return metaData; + } + + public void setMetaData(ResultSetMetaData metaData) { + this.metaData = metaData; + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/checker/CciSnapshotCheckerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/checker/CciSnapshotCheckerTest.java new file mode 100644 index 000000000..5b7f16e2f --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/checker/CciSnapshotCheckerTest.java @@ -0,0 +1,53 @@ +package com.alibaba.polardbx.executor.columnar.checker; + +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.junit.Assert; +import org.junit.Test; + +public class CciSnapshotCheckerTest { + @Test + public void test0() { + ExecutionContext context = new ExecutionContext(); + context.getParamManager().getProps().put("MPP_PARALLELISM", "1024"); + context.getParamManager().getProps().put("PARALLELISM", "1024"); + context.getParamManager().getProps().put("ENABLE_MPP", "true"); + context.getParamManager().getProps().put("ENABLE_MASTER_MPP", "true"); + CciSnapshotChecker checker = new CciSnapshotChecker("test_schema", + "test_table", "test_index", 100L, 200L); + Assert.assertEquals(Long.valueOf(100L), checker.getCheckTso().getKey()); + Assert.assertEquals(Long.valueOf(200L), checker.getCheckTso().getValue()); + String columnarSql = checker.getColumnarSql(context, 100L, "id, a"); + Assert.assertTrue(columnarSql.contains("MPP_PARALLELISM=1024")); + Assert.assertTrue(columnarSql.contains("PARALLELISM=1024")); + Assert.assertTrue(columnarSql.contains("ENABLE_MPP=true")); + Assert.assertTrue(columnarSql.contains("ENABLE_MASTER_MPP=true")); + Assert.assertTrue(columnarSql.contains("check_sum_v2(id, a) as pk_checksum")); + Assert.assertTrue(columnarSql.contains("force index(test_index)")); + String primarySql = checker.getPrimarySql(context, 100L, "id, a"); + Assert.assertTrue(primarySql.contains("MPP_PARALLELISM=1024")); + Assert.assertTrue(primarySql.contains("PARALLELISM=1024")); + Assert.assertTrue(primarySql.contains("ENABLE_MPP=true")); + Assert.assertTrue(primarySql.contains("ENABLE_MASTER_MPP=true")); + Assert.assertTrue(primarySql.contains("check_sum_v2(id, a) as pk_checksum")); + Assert.assertTrue(primarySql.contains("force index(primary)")); + } + + @Test + public void test1() { + ExecutionContext context = new ExecutionContext(); + context.getParamManager().getProps().put("MPP_PARALLELISM", "1024"); + context.getParamManager().getProps().put("PARALLELISM", "1024"); + context.getParamManager().getProps().put("ENABLE_MPP", "true"); + context.getParamManager().getProps().put("ENABLE_MASTER_MPP", "true"); + CciSnapshotFastChecker checker = new CciSnapshotFastChecker("test_schema", + "test_table", "test_index", 100L, 200L); + Assert.assertEquals(Long.valueOf(100L), checker.getCheckTso().getKey()); + Assert.assertEquals(Long.valueOf(200L), checker.getCheckTso().getValue()); + String primarySql = checker.getPrimarySql(context, 100L); + Assert.assertTrue(primarySql.contains("MPP_PARALLELISM=1024")); + Assert.assertTrue(primarySql.contains("PARALLELISM=1024")); + Assert.assertTrue(primarySql.contains("ENABLE_MPP=true")); + Assert.assertTrue(primarySql.contains("ENABLE_MASTER_MPP=true")); + Assert.assertTrue(primarySql.contains("force index(primary)")); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/ColumnarPruneTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/ColumnarPruneTest.java index 36a143edf..c49a0bf07 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/ColumnarPruneTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/ColumnarPruneTest.java @@ -2,6 +2,9 @@ import com.alibaba.polardbx.executor.columnar.pruning.index.IndexPruneContext; import com.alibaba.polardbx.executor.columnar.pruning.index.IndexPruner; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.google.common.collect.Lists; import org.apache.calcite.adapter.java.ReflectiveSchema; import org.apache.calcite.rel.logical.LogicalTableScan; @@ -9,9 +12,11 @@ import org.apache.calcite.rex.RexNode; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.tools.Frameworks; +import org.apache.hadoop.io.WritableComparator; import org.junit.runners.Parameterized; import org.roaringbitmap.RoaringBitmap; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; @@ -52,7 +57,7 @@ public static List prepareCases() { rexBuilder.makeLiteral("35500")); }; - IndexPruner indexPruner = mockPruner(); + IndexPruner indexPruner = mockPruner(DataTypes.LongType); RoaringBitmap target = RoaringBitmap.bitmapOfRange(0, 35); IndexPruneContext ipcTarget = new IndexPruneContext(); List params = Lists.newArrayList(); @@ -62,17 +67,48 @@ public static List prepareCases() { return params; } - public static IndexPruner mockPruner() { + public static IndexPruner mockPruner(DataType dataType) { IndexPruner.IndexPrunerBuilder indexPrunerBuilder = new IndexPruner.IndexPrunerBuilder("mock file", false); - mockSortKeyIndex(indexPrunerBuilder); + mockSortKeyIndex(indexPrunerBuilder, dataType); return indexPrunerBuilder.build(); } - private static void mockSortKeyIndex(IndexPruner.IndexPrunerBuilder indexPrunerBuilder) { + private static void mockSortKeyIndex(IndexPruner.IndexPrunerBuilder indexPrunerBuilder, DataType dt) { Random r = new Random(); - for (int i = 0; i < RG_NUM_FOR_TEST; i++) { - indexPrunerBuilder.appendSortKeyIndex(1000 * i + r.nextInt(500), 1000 * i + 500 + r.nextInt(500)); + indexPrunerBuilder.setSortKeyDataType(dt); + if (DataTypeUtil.isStringSqlType(dt)) { + List strings = new ArrayList<>(RG_NUM_FOR_TEST * 2); + for (int i = 0; i < RG_NUM_FOR_TEST * 2; i++) { + strings.add(generateRandomString(6)); + } + strings.sort((a, b) -> { + byte[] s1 = a.getBytes(); + byte[] s2 = b.getBytes(); + return WritableComparator.compareBytes(s1, 0, s1.length, s2, 0, s2.length); + }); + for (int i = 0; i < RG_NUM_FOR_TEST; i++) { + indexPrunerBuilder.appendMockSortKeyIndex(strings.get(i * 2), strings.get(i * 2 + 1), + DataTypes.StringType); + } + } else { + for (int i = 0; i < RG_NUM_FOR_TEST; i++) { + indexPrunerBuilder.appendMockSortKeyIndex(1000 * i + r.nextInt(500), 1000 * i + 500 + r.nextInt(500), + DataTypes.LongType); + } } + } + public static String generateRandomString(int length) { + String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + Random random = new Random(); + StringBuffer buf = new StringBuffer(); + + for (int i = 0; i < length; i++) { + int num = random.nextInt(62); + buf.append(str.charAt(num)); + } + + return buf.toString(); + } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/PredicatePruningTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/PredicatePruningTest.java index 944a279aa..bbd76814e 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/PredicatePruningTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/PredicatePruningTest.java @@ -7,6 +7,7 @@ import com.alibaba.polardbx.executor.columnar.pruning.predicate.ColumnPredicatePruningInf; import com.alibaba.polardbx.executor.columnar.pruning.predicate.ColumnarPredicatePruningVisitor; import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.google.common.collect.Lists; import org.apache.calcite.adapter.java.JavaTypeFactory; import org.apache.calcite.adapter.java.ReflectiveSchema; @@ -52,13 +53,22 @@ public static List prepareCases() { } List params = Lists.newArrayList(); + // ship_instructions <= string 'abcdefg' + params.add(buildPredicateCase((rexBuilder, scan) -> { + final String d = new String("abcdefg"); + return rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN_OR_EQUAL, + rexBuilder.makeInputRef(scan, 14), + rexBuilder.makeLiteral(d)); + }, mockPruner(DataTypes.VarcharType), -1L, new Parameters(), + "shipInstructions_14 LESS_THAN_OR_EQUAL abcdefg")); + // l_shipdate <= date '1998-09-01' params.add(buildPredicateCase((rexBuilder, scan) -> { final DateString d = new DateString(1998, 9, 1); return rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN_OR_EQUAL, rexBuilder.makeInputRef(scan, 11), rexBuilder.makeDateLiteral(d)); - }, mockPruner(), -1L, new Parameters(), "shipDate_11 LESS_THAN_OR_EQUAL 1998-09-01")); + }, mockPruner(DataTypes.DateType), -1L, new Parameters(), "shipDate_11 LESS_THAN_OR_EQUAL 1998-09-01")); // date '1998-09-01' >= l_shipdate params.add(buildPredicateCase((rexBuilder, scan) -> { @@ -66,7 +76,7 @@ public static List prepareCases() { return rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, rexBuilder.makeDateLiteral(d), rexBuilder.makeInputRef(scan, 11)); - }, mockPruner(), -1L, new Parameters(), "shipDate_11 LESS_THAN_OR_EQUAL 1998-09-01")); + }, mockPruner(DataTypes.DateType), -1L, new Parameters(), "shipDate_11 LESS_THAN_OR_EQUAL 1998-09-01")); // date '1998-09-01' = l_shipdate params.add(buildPredicateCase((rexBuilder, scan) -> { @@ -74,7 +84,7 @@ public static List prepareCases() { return rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeDateLiteral(d), rexBuilder.makeInputRef(scan, 11)); - }, mockPruner(), -1L, new Parameters(), "shipDate_11 EQUALS 1998-09-01")); + }, mockPruner(DataTypes.DateType), -1L, new Parameters(), "shipDate_11 EQUALS 1998-09-01")); // l_shipdate > date '1998-09-01' params.add(buildPredicateCase((rexBuilder, scan) -> { @@ -82,7 +92,7 @@ public static List prepareCases() { return rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN, rexBuilder.makeInputRef(scan, 11), rexBuilder.makeDateLiteral(d)); - }, mockPruner(), -1L, new Parameters(), "shipDate_11 GREATER_THAN 1998-09-01")); + }, mockPruner(DataTypes.DateType), -1L, new Parameters(), "shipDate_11 GREATER_THAN 1998-09-01")); // date '1998-09-01' > l_shipdate params.add(buildPredicateCase((rexBuilder, scan) -> { @@ -90,7 +100,7 @@ public static List prepareCases() { return rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN, rexBuilder.makeDateLiteral(d), rexBuilder.makeInputRef(scan, 11)); - }, mockPruner(), -1L, new Parameters(), "shipDate_11 LESS_THAN 1998-09-01")); + }, mockPruner(DataTypes.DateType), -1L, new Parameters(), "shipDate_11 LESS_THAN 1998-09-01")); return params; } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/TpchColumnarPruneTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/TpchColumnarPruneTest.java index 8218591c9..7b105e619 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/TpchColumnarPruneTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/TpchColumnarPruneTest.java @@ -323,7 +323,7 @@ private static void mockSortKeyIndexForLineitem(IndexPruner.IndexPrunerBuilder i int rgNum = 0; while (it.hasNext()) { Long date = it.next(); - indexPrunerBuilder.appendSortKeyIndex(date, date); + indexPrunerBuilder.appendMockSortKeyIndex(date, date, DataTypes.LongType); rgNum++; } indexPrunerBuilder.setRgNum(rgNum); diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/data/PruneUtilsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/data/PruneUtilsTest.java index 967a3bf94..f4189a060 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/data/PruneUtilsTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/data/PruneUtilsTest.java @@ -4,7 +4,7 @@ import com.alibaba.polardbx.common.utils.Assert; import com.alibaba.polardbx.executor.columnar.pruning.index.BitMapRowGroupIndex; import com.alibaba.polardbx.executor.columnar.pruning.index.IndexPruneContext; -import com.alibaba.polardbx.executor.columnar.pruning.index.SortKeyIndex; +import com.alibaba.polardbx.executor.columnar.pruning.index.LongSortKeyIndex; import com.alibaba.polardbx.executor.columnar.pruning.index.ZoneMapIndex; import com.alibaba.polardbx.executor.columnar.pruning.predicate.ColumnPredicatePruningInf; import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; @@ -146,7 +146,8 @@ public void pruneDateNot() { ColumnPredicatePruningInf columnPredicatePruningInf = PruneUtils.transformRexToIndexMergeTree(rexNodes, ipc); RoaringBitmap bitmap = RoaringBitmap.bitmapOfRange(10, 100); - columnPredicatePruningInf.sortKey(SortKeyIndex.build(0, new long[] {1, 10, 11, 100}, DataTypes.LongType), null, + columnPredicatePruningInf.sortKey(LongSortKeyIndex.build(0, new long[] {1, 10, 11, 100}, DataTypes.LongType), + null, bitmap); columnPredicatePruningInf.zoneMap( ZoneMapIndex.build(1, Maps.newHashMap(), Maps.newHashMap(), Maps.newHashMap()), null, bitmap); diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/SortKeyIndexTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/LongSortKeyIndexTest.java similarity index 50% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/SortKeyIndexTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/LongSortKeyIndexTest.java index 18837990e..843605101 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/SortKeyIndexTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/LongSortKeyIndexTest.java @@ -8,68 +8,67 @@ /** * @author fangwu */ -public class SortKeyIndexTest { +public class LongSortKeyIndexTest { private final long[] data = new long[] {10000, 20000, 40000, 70000, 70000, 70050, 80000, 100000}; - private final SortKeyIndex shortKeyIndex = SortKeyIndex.build(1, data, DataTypes.LongType); + private final LongSortKeyIndex sortKeyIndex = LongSortKeyIndex.build(1, data, DataTypes.LongType); @Test public void testEqual() { - RoaringBitmap rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneEqual(50000L, rs); + RoaringBitmap rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual(50000L, rs); rs.stream().forEachOrdered(System.out::print); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(1)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneEqual(30000L, rs); - + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual(30000L, rs); rs.stream().forEachOrdered(System.out::print); Assert.assertTrue(rs.getCardinality() == 0); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneEqual(70000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual(70000L, rs); rs.stream().forEachOrdered(System.out::print); Assert.assertTrue(rs.getCardinality() == 2 && rs.contains(RoaringBitmap.bitmapOf(1, 2))); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneEqual(70001L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual(70001L, rs); rs.stream().forEachOrdered(System.out::print); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(RoaringBitmap.bitmapOf(2))); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneEqual(79999L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual(79999L, rs); rs.stream().forEachOrdered(System.out::print); Assert.assertTrue(rs.getCardinality() == 0); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneEqual(80000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual(80000L, rs); rs.stream().forEachOrdered(System.out::print); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(RoaringBitmap.bitmapOf(3))); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneEqual(100000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual(100000L, rs); rs.stream().forEachOrdered(System.out::print); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(RoaringBitmap.bitmapOf(3))); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneEqual(100001L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual(100001L, rs); rs.stream().forEachOrdered(System.out::print); Assert.assertTrue(rs.getCardinality() == 0); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneEqual(10000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual(10000L, rs); rs.stream().forEachOrdered(System.out::print); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(RoaringBitmap.bitmapOf(0))); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneEqual(9999L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual(9999L, rs); rs.stream().forEachOrdered(System.out::print); Assert.assertTrue(rs.getCardinality() == 0); @@ -78,111 +77,133 @@ public void testEqual() { @Test public void testRange() { // test start obj less than the lowest value - RoaringBitmap rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-10L, -1L, rs); + RoaringBitmap rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-10L, -1L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 0); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-1L, 10L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-1L, 10L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 0); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-1L, 10000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-1L, 10000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-1L, 10001L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-1L, 10001L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-1L, 20000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-1L, 20000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-1L, 25000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-1L, 25000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-1L, 40000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-1L, 40000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 2 && rs.contains(0) && rs.contains(1)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-1L, 40001L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-1L, 40001L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 2 && rs.contains(0) && rs.contains(1)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-1L, 70000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-1L, 70000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 3 && rs.contains(0) && rs.contains(1) && rs.contains(2)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-1L, 80000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-1L, 80000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue( rs.getCardinality() == 4 && rs.contains(0) && rs.contains(1) && rs.contains(2) && rs.contains(3)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-1L, 100000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-1L, 100000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue( rs.getCardinality() == 4 && rs.contains(0) && rs.contains(1) && rs.contains(2) && rs.contains(3)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(-1L, 100001L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(-1L, 100001L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue( rs.getCardinality() == 4 && rs.contains(0) && rs.contains(1) && rs.contains(2) && rs.contains(3)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(10000L, 10001L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(10000L, 10001L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(10000L, 20000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(10000L, 20000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(10000L, 20010L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(10000L, 20010L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(10000L, 40000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(10000L, 40000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 2 && rs.contains(0) && rs.contains(1)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(10000L, 70000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(10000L, 70000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 3 && rs.contains(0) && rs.contains(1) && rs.contains(2)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(20001L, 70000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(20001L, 70000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 2 && rs.contains(1) && rs.contains(2)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(70000L, 100000L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(70000L, 100000L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 3 && rs.contains(1) && rs.contains(2) && rs.contains(3)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(100000L, 100001L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(100000L, 100001L, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(3)); - rs = RoaringBitmap.bitmapOfRange(0, shortKeyIndex.rgNum()); - shortKeyIndex.pruneRange(100001L, 110001L, rs); + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(100001L, 110001L, rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 0); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(null, 100000L, rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue( + rs.getCardinality() == 4 && rs.contains(0) && rs.contains(1) && rs.contains(2) && rs.contains(3)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(10000L, null, rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue( + rs.getCardinality() == 4 && rs.contains(0) && rs.contains(1) && rs.contains(2) && rs.contains(3)); + + } + + @Test + public void testInvalidRange() { + //start > end + RoaringBitmap rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(20000, 10000, rs); rs.stream().forEachOrdered(System.out::println); Assert.assertTrue(rs.getCardinality() == 0); } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/StringSortKeyIndexTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/StringSortKeyIndexTest.java new file mode 100644 index 000000000..8f4900119 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/StringSortKeyIndexTest.java @@ -0,0 +1,217 @@ +package com.alibaba.polardbx.executor.columnar.pruning.index; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Test; +import org.roaringbitmap.RoaringBitmap; + +public class StringSortKeyIndexTest { + private final String[] data = new String[] {"aaa", "bbb", "ddd", "ggg", "ggg", "jjj", "xxx", "zzz"}; + + private final StringSortKeyIndex sortKeyIndex = StringSortKeyIndex.build(1, data, DataTypes.StringType); + + @Test + public void testEqual() { + RoaringBitmap rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual("eee", rs); + rs.stream().forEachOrdered(System.out::print); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(1)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual("ccc", rs); + rs.stream().forEachOrdered(System.out::print); + Assert.assertTrue(rs.getCardinality() == 0); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual("ggg", rs); + rs.stream().forEachOrdered(System.out::print); + Assert.assertTrue(rs.getCardinality() == 2 && rs.contains(RoaringBitmap.bitmapOf(1, 2))); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual("hhh", rs); + rs.stream().forEachOrdered(System.out::print); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(RoaringBitmap.bitmapOf(2))); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual("www", rs); + rs.stream().forEachOrdered(System.out::print); + Assert.assertTrue(rs.getCardinality() == 0); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual("xxx", rs); + rs.stream().forEachOrdered(System.out::print); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(RoaringBitmap.bitmapOf(3))); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual("zzz", rs); + rs.stream().forEachOrdered(System.out::print); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(RoaringBitmap.bitmapOf(3))); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual("zzza", rs); + rs.stream().forEachOrdered(System.out::print); + Assert.assertTrue(rs.getCardinality() == 0); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual("aaa", rs); + rs.stream().forEachOrdered(System.out::print); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(RoaringBitmap.bitmapOf(0))); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneEqual("aa", rs); + rs.stream().forEachOrdered(System.out::print); + Assert.assertTrue(rs.getCardinality() == 0); + } + + @Test + public void testRange() { + // test start obj less than the lowest value + RoaringBitmap rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("a", "aa", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 0); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("aa", "aa", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 0); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("a", "aaa", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("a", "b", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("a", "bb", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("a", "bbb", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("bbb", "bbb", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("bb", "bbb", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("bb", "ddd", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 2 && rs.contains(0) && rs.contains(1)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("bbb", "eee", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 2 && rs.contains(0) && rs.contains(1)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("bba", "ggg", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 3 && rs.contains(0) && rs.contains(1) && rs.contains(2)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("bba", "xxxa", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue( + rs.getCardinality() == 4 && rs.contains(0) && rs.contains(1) && rs.contains(2) && rs.contains(3)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("bba", "xxx", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue( + rs.getCardinality() == 4 && rs.contains(0) && rs.contains(1) && rs.contains(2) && rs.contains(3)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("bba", "xxxy", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue( + rs.getCardinality() == 4 && rs.contains(0) && rs.contains(1) && rs.contains(2) && rs.contains(3)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("aaa", "bb", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("aaa", "bbb", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("aaa", "bbbd", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(0)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("aaa", "gga", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 2 && rs.contains(0) && rs.contains(1)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("aaa", "ggg", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 3 && rs.contains(0) && rs.contains(1) && rs.contains(2)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("ddd", "ggg", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 2 && rs.contains(1) && rs.contains(2)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("ddd", "xxx", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 3 && rs.contains(1) && rs.contains(2) && rs.contains(3)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("xxx", "zzz", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(3)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("zzza", "zzzb", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 0); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("zzzzzzzz", "zzzzzzzz", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 0); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("bbb", "zzzz", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue( + rs.getCardinality() == 4 && rs.contains(0) && rs.contains(1) && rs.contains(2) && rs.contains(3)); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange(null, "zzz", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == sortKeyIndex.rgNum()); + + rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("zzz", null, rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 1 && rs.contains(3)); + } + + @Test + public void testInvalidRange() { + // test start obj less than the lowest value + RoaringBitmap rs = RoaringBitmap.bitmapOfRange(0, sortKeyIndex.rgNum()); + sortKeyIndex.pruneRange("aa", "a", rs); + rs.stream().forEachOrdered(System.out::println); + Assert.assertTrue(rs.getCardinality() == 0); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/ZoneMapIndexTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/ZoneMapIndexTest.java index 9e5b7ae9c..1f6261485 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/ZoneMapIndexTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/columnar/pruning/index/ZoneMapIndexTest.java @@ -1,5 +1,6 @@ package com.alibaba.polardbx.executor.columnar.pruning.index; +import com.alibaba.polardbx.common.utils.Assert; import com.alibaba.polardbx.executor.columnar.pruning.index.builder.ZoneMapIndexBuilder; import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; @@ -52,4 +53,32 @@ public void testZoneMapGroup() { } + @Test + public void testInvalidZoneMapGroup() { + MetaDbInstConfigManager.setConfigFromMetaDb(false); + ZoneMapIndexBuilder zoneMapIndexBuilder = new ZoneMapIndexBuilder(); + zoneMapIndexBuilder.appendColumn(1, DataTypes.IntegerType); + Random r = new Random(); + for (int i = 0; i < 100000; i++) { + int start = r.nextInt(2000); + zoneMapIndexBuilder.appendIntegerData(1, start).appendIntegerData(1, start + 500); + } + + ZoneMapIndex zoneMapIndexWithGroup = zoneMapIndexBuilder.build(); + MetaDbInstConfigManager.getInstance().getCnVariableConfigMap().put("ZONEMAP_MAX_GROUP_SIZE", "1"); + + long rgNum = zoneMapIndexWithGroup.rgNum(); + + for (int i = 0; i < 100; i++) { + int testStart = r.nextInt(5000); + int range = r.nextInt(500); + RoaringBitmap rsWithGroup = RoaringBitmap.bitmapOfRange(0, rgNum); + zoneMapIndexWithGroup.prune(1, testStart, true, testStart - range, true, rsWithGroup); + Assert.assertTrue(rsWithGroup.getCardinality() >= 0); + } + + MetaDbInstConfigManager.getInstance().getCnVariableConfigMap().remove("ZONEMAP_MAX_GROUP_SIZE"); + + } + } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/CciMetaManagerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/CciMetaManagerTest.java new file mode 100644 index 000000000..da379f381 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/CciMetaManagerTest.java @@ -0,0 +1,117 @@ +/* + * 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 com.alibaba.polardbx.executor.common; + +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; +import com.alibaba.polardbx.gms.partition.TablePartitionAccessor; +import com.alibaba.polardbx.gms.partition.TablePartitionRecord; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class CciMetaManagerTest { + + @Spy + CciMetaManager cciMetaManagerSpy; + + List evolutionRecords = new ArrayList<>(); + List partitionRecords = new ArrayList<>(); + + @Before + public void setUp() { + MockitoAnnotations.openMocks(this); + + ColumnarTableEvolutionRecord record = new ColumnarTableEvolutionRecord(); + record.tableId = 1L; + record.tableName = "test_table"; + record.tableSchema = "test_schema"; + record.indexName = "test_index"; + record.versionId = 100L; + record.ddlJobId = 101L; + record.partitions = new java.util.ArrayList<>(); + evolutionRecords.add(record); + + TablePartitionRecord partitionRecord = new TablePartitionRecord(); + partitionRecords.add(partitionRecord); + + } + + @Test + public void testDoInit() { + ColumnarTableEvolutionAccessor columnarTableEvolutionAccessor = mock(ColumnarTableEvolutionAccessor.class); + ColumnarPartitionEvolutionAccessor columnarPartitionEvolutionAccessor = + mock(ColumnarPartitionEvolutionAccessor.class); + TablePartitionAccessor tablePartition = mock(TablePartitionAccessor.class); + when(columnarTableEvolutionAccessor.queryPartitionEmptyRecords()).thenReturn(evolutionRecords); + when(tablePartition.getTablePartitionsByDbNameTbName(anyString(), anyString(), anyBoolean())).thenReturn( + partitionRecords); + + when(cciMetaManagerSpy.getColumnarTableEvolution()).thenReturn(columnarTableEvolutionAccessor); + when(cciMetaManagerSpy.getColumnarPartitionEvolution()).thenReturn(columnarPartitionEvolutionAccessor); + when(cciMetaManagerSpy.getTablePartition()).thenReturn(tablePartition); + + try (MockedStatic configDataModeMockedStatic = mockStatic(ConfigDataMode.class)) { + configDataModeMockedStatic.when(ConfigDataMode::isPolarDbX).thenReturn(true); + + try (MockedStatic metaDbDataSourceMockedStatic = mockStatic(MetaDbDataSource.class)) { + MetaDbDataSource metaDbDataSourceMock = mock(MetaDbDataSource.class); + Connection connectionMock = mock(Connection.class); + when(metaDbDataSourceMock.getConnection()).thenReturn(connectionMock); + metaDbDataSourceMockedStatic.when(MetaDbDataSource::getInstance).thenReturn(metaDbDataSourceMock); + + cciMetaManagerSpy.init(); + verify(cciMetaManagerSpy, times(1)).doInit(); + verify(cciMetaManagerSpy, times(1)).loadPartitions(); + } + + } + } + + @Test + public void testDoInitNotPolarDBX() { + try (MockedStatic configDataModeMockedStatic = mockStatic(ConfigDataMode.class)) { + configDataModeMockedStatic.when(ConfigDataMode::isPolarDbX).thenReturn(false); + + cciMetaManagerSpy.init(); + verify(cciMetaManagerSpy, times(1)).doInit(); + verify(cciMetaManagerSpy, times(0)).loadPartitions(); // 验证是否没有调用loadPartitions + } + } +} + + + diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/ExecutorContextTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/ExecutorContextTest.java new file mode 100644 index 000000000..9fdb4b356 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/ExecutorContextTest.java @@ -0,0 +1,23 @@ +package com.alibaba.polardbx.executor.common; + +import com.alibaba.polardbx.common.trx.ISyncPointExecutor; +import org.junit.Assert; +import org.junit.Test; + +public class ExecutorContextTest { + @Test + public void syncPointExecutorTest() { + ExecutorContext context = new ExecutorContext(); + ISyncPointExecutor syncPointExecutor = new MockSyncPointExecutor(); + context.setSyncPointExecutor(syncPointExecutor); + Assert.assertEquals(syncPointExecutor, context.getSyncPointExecutor()); + } + + private static class MockSyncPointExecutor implements ISyncPointExecutor { + + @Override + public boolean execute() { + return false; + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/SequenceManagerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/SequenceManagerTest.java new file mode 100644 index 000000000..5a1225d7c --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/SequenceManagerTest.java @@ -0,0 +1,36 @@ +package com.alibaba.polardbx.executor.common; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.sequence.Sequence; +import com.alibaba.polardbx.sequence.impl.NewSequence; +import org.junit.Test; +import org.mockito.Mockito; + +/** + * Created by zhuqiwei. + * + * @author zhuqiwei + */ +public class SequenceManagerTest { + public SequenceLoadFromDBManager subManager = Mockito.mock(SequenceLoadFromDBManager.class); + + @Test + public void testGetSequence() { + Sequence newSequence = Mockito.mock(NewSequence.class); + SequenceManager sequenceManager = new SequenceManager(subManager); + Mockito.when(subManager.isInited()).thenReturn(true); + Mockito.when(subManager.getSequence("schemaName", "seqName")).thenReturn(newSequence); + + Assert.assertTrue(sequenceManager.getSequence("schemaName", "seqName") instanceof NewSequence); + } + + @Test(expected = TddlRuntimeException.class) + public void testGetSequenceException() { + SequenceManager sequenceManager = new SequenceManager(subManager); + Mockito.when(subManager.isInited()).thenReturn(true); + Mockito.when(subManager.getSequence("schemaName", "seqName")).thenReturn(null); + sequenceManager.getSequence("schemaName", "seqName"); + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/StorageInfoManagerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/StorageInfoManagerTest.java new file mode 100644 index 000000000..63f4b6dfe --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/common/StorageInfoManagerTest.java @@ -0,0 +1,202 @@ +package com.alibaba.polardbx.executor.common; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.jdbc.IConnection; +import com.alibaba.polardbx.common.jdbc.IDataSource; +import com.alibaba.polardbx.common.model.Group; +import com.alibaba.polardbx.common.model.Group.GroupType; +import com.alibaba.polardbx.common.model.Matrix; +import com.alibaba.polardbx.executor.spi.IGroupExecutor; +import com.alibaba.polardbx.gms.topology.DbGroupInfoManager; +import com.alibaba.polardbx.group.jdbc.TGroupDataSource; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import java.lang.reflect.Field; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class StorageInfoManagerTest { + @Mock + private IGroupExecutor groupExecutor; + @Mock + private Group group; + @Mock + private IDataSource dataSource; + + @Before + public void setUp() { + MockitoAnnotations.openMocks(this); + // Initialize mocks here if needed + } + + @Test + public void testDoInitWithDefaultValue() throws NoSuchFieldException, IllegalAccessException { + TopologyHandler topologyHandler = new TopologyHandler("test", "test", "test", new ExecutorContext()); + StorageInfoManager storageInfoManager = new StorageInfoManager(topologyHandler); + when(groupExecutor.getDataSource()).thenReturn(dataSource); + when(group.getType()).thenReturn(GroupType.MYSQL_JDBC); + + storageInfoManager.doInit(); + + // modify isInited through reflection + Class parentClass = storageInfoManager.getClass().getSuperclass(); + Field field = parentClass.getDeclaredField("isInited"); + if (field.isAccessible() == false) { + field.setAccessible(true); + } + field.set(storageInfoManager, true); + + // Verify the expected value here + Assert.assertTrue(storageInfoManager.supportXA()); + Assert.assertTrue(storageInfoManager.supportTso()); + Assert.assertTrue(!storageInfoManager.supportPurgeTso()); + Assert.assertTrue(!storageInfoManager.isLessMy56Version()); + Assert.assertTrue(storageInfoManager.isMysql80()); + Assert.assertTrue(!storageInfoManager.supportTsoHeartbeat()); + Assert.assertTrue(storageInfoManager.supportCtsTransaction()); + Assert.assertTrue(storageInfoManager.supportAsyncCommit()); + Assert.assertTrue(storageInfoManager.supportLizard1PCTransaction()); + Assert.assertTrue(storageInfoManager.supportDeadlockDetection()); + Assert.assertTrue(storageInfoManager.supportMdlDeadlockDetection()); + Assert.assertTrue(storageInfoManager.supportsBloomFilter()); + Assert.assertTrue(storageInfoManager.supportSharedReadView()); + Assert.assertTrue(storageInfoManager.supportOpenSSL()); + Assert.assertTrue(storageInfoManager.supportsHyperLogLog()); + Assert.assertTrue(storageInfoManager.supportsXxHash()); + Assert.assertTrue(storageInfoManager.supportsReturning()); + Assert.assertTrue(storageInfoManager.supportsBackfillReturning()); + Assert.assertTrue(storageInfoManager.supportsAlterType()); + Assert.assertTrue(!storageInfoManager.isReadOnly()); + Assert.assertTrue(storageInfoManager.isLowerCaseTableNames()); + Assert.assertTrue(storageInfoManager.supportFastChecker()); + Assert.assertTrue(storageInfoManager.supportChangeSet()); + Assert.assertTrue(storageInfoManager.supportXOptForAutoSp()); + Assert.assertTrue(storageInfoManager.supportXRpc()); + Assert.assertTrue(storageInfoManager.isSupportMarkDistributed()); + Assert.assertTrue(storageInfoManager.supportXOptForPhysicalBackfill()); + } + + @Test + public void testDoInit() { + StorageInfoManager.StorageInfo storageInfo = new StorageInfoManager.StorageInfo( + "5.7", + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + 1, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + true, + true + ); + + Group group = mock(Group.class); + when(group.getType()).thenReturn(Group.GroupType.MYSQL_JDBC); + when(group.getName()).thenReturn("test_group"); + List groups = new ArrayList<>(); + groups.add(group); + + IGroupExecutor groupExecutor = mock(IGroupExecutor.class); + IDataSource dataSource = mock(TGroupDataSource.class); + when(groupExecutor.getDataSource()).thenReturn(dataSource); + Matrix matrix = mock(Matrix.class); + TopologyHandler topologyHandler = mock(TopologyHandler.class); + when(topologyHandler.getMatrix()).thenReturn(matrix); + when(matrix.getGroups()).thenReturn(groups); + when(topologyHandler.get(any())).thenReturn(groupExecutor); + + try (MockedStatic storageInfoMock = + Mockito.mockStatic(StorageInfoManager.StorageInfo.class); + MockedStatic dbGroupInfoManagerMock = + Mockito.mockStatic(DbGroupInfoManager.class)) { + storageInfoMock.when(() -> StorageInfoManager.StorageInfo.create(any())) + .thenReturn(storageInfo); + dbGroupInfoManagerMock.when(() -> DbGroupInfoManager.isNormalGroup(any())) + .thenReturn(true); + + StorageInfoManager storageInfoManager = new StorageInfoManager(topologyHandler); + storageInfoManager.doInit(); + assertTrue(storageInfoManager.isSupportSyncPoint()); + } + } + + @Test + public void checkSupportSyncPointTest() throws SQLException { + IDataSource dataSource = mock(IDataSource.class); + IConnection connection = mock(IConnection.class); + Statement statement = mock(Statement.class); + ResultSet rs = mock(ResultSet.class); + when(dataSource.getConnection()).thenReturn(connection); + when(connection.createStatement()).thenReturn(statement); + when(statement.executeQuery(any())).thenReturn(rs); + when(rs.next()).thenReturn(true); + assertTrue(StorageInfoManager.checkSupportSyncPoint(dataSource)); + + when(rs.next()).thenReturn(false); + assertFalse(StorageInfoManager.checkSupportSyncPoint(dataSource)); + + when(statement.executeQuery(any())).thenThrow(new SQLException("test")); + try { + StorageInfoManager.checkSupportSyncPoint(dataSource); + } catch (TddlRuntimeException e) { + assertTrue(e.getMessage().contains("Failed to check sync point support: test")); + } + } + + @Test + public void checkSupportFlashbackAreaTest() throws SQLException { + IDataSource dataSource = mock(IDataSource.class); + IConnection connection = mock(IConnection.class); + Statement statement = mock(Statement.class); + ResultSet rs = mock(ResultSet.class); + when(dataSource.getConnection()).thenReturn(connection); + when(connection.createStatement()).thenReturn(statement); + when(statement.executeQuery(any())).thenReturn(rs); + when(rs.next()).thenReturn(true); + assertTrue(StorageInfoManager.checkSupportFlashbackArea(dataSource)); + + when(rs.next()).thenReturn(false); + assertFalse(StorageInfoManager.checkSupportFlashbackArea(dataSource)); + + when(statement.executeQuery(any())).thenThrow(new SQLException("test")); + try { + StorageInfoManager.checkSupportFlashbackArea(dataSource); + } catch (TddlRuntimeException e) { + assertTrue(e.getMessage().contains("Failed to check flashback area support: test")); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/ColumnarForbidTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/ColumnarForbidTest.java index 1db89123a..342c71b7a 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/ColumnarForbidTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/ColumnarForbidTest.java @@ -20,13 +20,17 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.executor.ddl.job.builder.tablegroup.AlterTableGroupBaseBuilder; +import com.alibaba.polardbx.executor.ddl.job.builder.tablegroup.AlterTableGroupModifyPartitionBuilder; import com.alibaba.polardbx.executor.ddl.job.task.basic.TruncateTableValidateTask; import com.alibaba.polardbx.executor.ddl.job.validator.TableValidator; import com.alibaba.polardbx.executor.ddl.newengine.job.AbstractDdlTask; import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; import com.alibaba.polardbx.optimizer.config.table.SchemaManager; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupBasePreparedData; import org.apache.calcite.sql.SqlKind; import org.junit.Rule; import org.junit.Test; @@ -110,4 +114,98 @@ public void ForbidTruncateCciTable1() { truncateTableValidateTask.executeImpl(ec); } } + + @Test(expected = TddlRuntimeException.class) + public void validateTableWithCciThrowTest() { + ParamManager paramManager = mock(ParamManager.class); + ExecutionContext executionContext = mock(ExecutionContext.class); + when(executionContext.getParamManager()).thenReturn(paramManager); + when(paramManager.getBoolean(any())).thenReturn(true); + ComplexTaskMetaManager.ComplexTaskType complexTaskType = ComplexTaskMetaManager.ComplexTaskType.ADD_PARTITION; + TableValidator.validateTableWithCCI(executionContext, complexTaskType); + complexTaskType = ComplexTaskMetaManager.ComplexTaskType.DROP_PARTITION; + TableValidator.validateTableWithCCI(executionContext, complexTaskType); + complexTaskType = ComplexTaskMetaManager.ComplexTaskType.SPLIT_PARTITION; + TableValidator.validateTableWithCCI(executionContext, complexTaskType); + } + + @Test + public void validateTableWithCciTest() { + ParamManager paramManager = mock(ParamManager.class); + ExecutionContext executionContext = mock(ExecutionContext.class); + when(executionContext.getParamManager()).thenReturn(paramManager); + when(paramManager.getBoolean(any())).thenReturn(true); + ComplexTaskMetaManager.ComplexTaskType complexTaskType = ComplexTaskMetaManager.ComplexTaskType.MOVE_PARTITION; + TableValidator.validateTableWithCCI(executionContext, complexTaskType); + } + + @Test(expected = TddlRuntimeException.class) + public void validateTableWithCciThrowTest1() { + AlterTableGroupBaseBuilder builder = mock(AlterTableGroupBaseBuilder.class); + AlterTableGroupBasePreparedData preparedData = mock(AlterTableGroupBasePreparedData.class); + ExecutionContext executionContext = mock(ExecutionContext.class); + SchemaManager schemaManager = mock(SchemaManager.class); + TableMeta tableMeta = mock(TableMeta.class); + when(builder.getExecutionContext()).thenReturn(executionContext); + when(builder.getPreparedData()).thenReturn(preparedData); + when(preparedData.getSchemaName()).thenReturn("schema"); + when(executionContext.getSchemaManager(any())).thenReturn(schemaManager); + when(schemaManager.getTable(any())).thenReturn(tableMeta); + when(tableMeta.withCci()).thenReturn(true); + ParamManager paramManager = mock(ParamManager.class); + when(executionContext.getParamManager()).thenReturn(paramManager); + when(paramManager.getBoolean(any())).thenReturn(true); + + doCallRealMethod().when(builder).createAlterTableGroupItemPreparedData(any(), any()); + when(preparedData.getTaskType()).thenReturn(ComplexTaskMetaManager.ComplexTaskType.ADD_PARTITION); + builder.createAlterTableGroupItemPreparedData("tableName", null); + when(preparedData.getTaskType()).thenReturn(ComplexTaskMetaManager.ComplexTaskType.DROP_PARTITION); + builder.createAlterTableGroupItemPreparedData("tableName", null); + when(preparedData.getTaskType()).thenReturn(ComplexTaskMetaManager.ComplexTaskType.SPLIT_PARTITION); + builder.createAlterTableGroupItemPreparedData("tableName", null); + } + + @Test(expected = NullPointerException.class) + public void validateTableWithCciTest1() { + AlterTableGroupBaseBuilder builder = mock(AlterTableGroupBaseBuilder.class); + AlterTableGroupBasePreparedData preparedData = mock(AlterTableGroupBasePreparedData.class); + ExecutionContext executionContext = mock(ExecutionContext.class); + SchemaManager schemaManager = mock(SchemaManager.class); + TableMeta tableMeta = mock(TableMeta.class); + when(builder.getExecutionContext()).thenReturn(executionContext); + when(builder.getPreparedData()).thenReturn(preparedData); + when(preparedData.getSchemaName()).thenReturn("schema"); + when(executionContext.getSchemaManager(any())).thenReturn(schemaManager); + when(schemaManager.getTable(any())).thenReturn(tableMeta); + when(tableMeta.withCci()).thenReturn(true); + ParamManager paramManager = mock(ParamManager.class); + when(executionContext.getParamManager()).thenReturn(paramManager); + when(paramManager.getBoolean(any())).thenReturn(true); + + doCallRealMethod().when(builder).createAlterTableGroupItemPreparedData(any(), any()); + when(preparedData.getTaskType()).thenReturn(ComplexTaskMetaManager.ComplexTaskType.MOVE_PARTITION); + builder.createAlterTableGroupItemPreparedData("tableName", null); + } + + @Test(expected = TddlRuntimeException.class) + public void validateTableWithCciTest2() { + AlterTableGroupModifyPartitionBuilder builder = mock(AlterTableGroupModifyPartitionBuilder.class); + AlterTableGroupBasePreparedData preparedData = mock(AlterTableGroupBasePreparedData.class); + ExecutionContext executionContext = mock(ExecutionContext.class); + SchemaManager schemaManager = mock(SchemaManager.class); + TableMeta tableMeta = mock(TableMeta.class); + when(builder.getExecutionContext()).thenReturn(executionContext); + when(builder.getPreparedData()).thenReturn(preparedData); + when(preparedData.getSchemaName()).thenReturn("schema"); + when(executionContext.getSchemaManager(any())).thenReturn(schemaManager); + when(schemaManager.getTable(any())).thenReturn(tableMeta); + when(tableMeta.withCci()).thenReturn(true); + ParamManager paramManager = mock(ParamManager.class); + when(executionContext.getParamManager()).thenReturn(paramManager); + when(paramManager.getBoolean(any())).thenReturn(true); + + doCallRealMethod().when(builder).createAlterTableGroupItemPreparedData(any(), any()); + when(preparedData.getTaskType()).thenReturn(ComplexTaskMetaManager.ComplexTaskType.REORGANIZE_PARTITION); + builder.createAlterTableGroupItemPreparedData("tableName", null); + } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/ImplicitTableGroupTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/ImplicitTableGroupTest.java index d42bf38b0..cf07cfd5d 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/ImplicitTableGroupTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/ImplicitTableGroupTest.java @@ -98,6 +98,8 @@ private GsiMetaManager.GsiTableMetaBean buildGsiTableMetaBean(String schemaName, buildGsiIndexMetaBean(schemaName, tableName, "gsi_2", Lists.newArrayList("c1", "C2"))); indexMap.put("gsi_3$abc", buildGsiIndexMetaBean(schemaName, tableName, "gsi_3", Lists.newArrayList("c2", "C1"))); + indexMap.put("gs`i_4$abc", + buildGsiIndexMetaBean(schemaName, tableName, "gs`i_4", Lists.newArrayList("c2", "C1"))); GsiMetaManager.GsiTableMetaBean gsiTableMetaBean = new GsiMetaManager.GsiTableMetaBean(null, schemaName, tableName, GsiMetaManager.TableType.SHARDING, null, null, null, @@ -830,9 +832,34 @@ public void testAlterIndex() { public void testAlterTableModifyColumn() { String sql = "alter table t1 modify column c1 bigint not null"; sql = ImplicitTableGroupUtil.tryAttachImplicitTableGroup("xx", "t1", sql); - Assert.assertEquals("ALTER TABLE t1\n" - + "\tMODIFY COLUMN c1 bigint NOT NULL WITH TABLEGROUP=tgi2 IMPLICIT, INDEX gsi_3 WITH TABLEGROUP=tgi2 IMPLICIT, INDEX gsi_2 WITH TABLEGROUP=tgi2 IMPLICIT, INDEX gsi_1 WITH TABLEGROUP=tgi2 IMPLICIT", - sql); + String expectedSql = "ALTER TABLE t1\n" + + "\tMODIFY COLUMN c1 bigint NOT NULL WITH TABLEGROUP=tgi2 IMPLICIT, " + + "INDEX `gsi_3` WITH TABLEGROUP=tgi2 IMPLICIT, " + + "INDEX `gsi_2` WITH TABLEGROUP=tgi2 IMPLICIT, " + + "INDEX `gsi_1` WITH TABLEGROUP=tgi2 IMPLICIT, " + + "INDEX `gs``i_4` WITH TABLEGROUP=tgi2 IMPLICIT"; + + Assert.assertEquals(expectedSql, sql); + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, SQL_PARSE_FEATURES); + List parseResult = parser.parseStatementList(); + Assert.assertEquals(expectedSql, parseResult.get(0).toString()); + } + + @Test + public void testAlterTableRemovePartitioning() { + String sql = "alter table t1 remove partitioning"; + sql = ImplicitTableGroupUtil.tryAttachImplicitTableGroup("xx", "t1", sql); + String expectedSql = "ALTER TABLE t1\n" + + "\tREMOVE PARTITIONING WITH TABLEGROUP=tgi2 IMPLICIT, " + + "INDEX `gsi_3` WITH TABLEGROUP=tgi2 IMPLICIT, " + + "INDEX `gsi_2` WITH TABLEGROUP=tgi2 IMPLICIT, " + + "INDEX `gsi_1` WITH TABLEGROUP=tgi2 IMPLICIT, " + + "INDEX `gs``i_4` WITH TABLEGROUP=tgi2 IMPLICIT"; + Assert.assertEquals(expectedSql, sql); + + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, SQL_PARSE_FEATURES); + List parseResult = parser.parseStatementList(); + Assert.assertEquals(expectedSql, parseResult.get(0).toString()); } private void processImplicitTableGroup4Index(SQLAlterTableStatement alterTableStatement, String tableGroupName) { diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/CdcColumnarTableGroupDdlMarkTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/CdcColumnarTableGroupDdlMarkTest.java new file mode 100644 index 000000000..d0fe46fbb --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/CdcColumnarTableGroupDdlMarkTest.java @@ -0,0 +1,105 @@ +/* + * 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 com.alibaba.polardbx.executor.ddl.job.task; + +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.druid.sql.SQLUtils; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcColumnarTableGroupDdlMark; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcMarkUtil; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@RunWith(MockitoJUnitRunner.class) +public class CdcColumnarTableGroupDdlMarkTest { + + @InjectMocks + private CdcColumnarTableGroupDdlMark cdcColumnarTableGroupDdlMark; + + @Mock + private ExecutionContext executionContext; + + @Mock + private ExecutionContext ecCopy; + + private final DdlContext ddlContext = new DdlContext(); + + @Before + public void setUp() { + cdcColumnarTableGroupDdlMark = + new CdcColumnarTableGroupDdlMark("tg_test", "test_schema", Collections.singletonList("test_table"), 1L); + Mockito.when(executionContext.copy()).thenReturn(ecCopy); + Mockito.when(ecCopy.getDdlContext()).thenReturn(ddlContext); + } + + @Test + public void testMark4ColumnarTableGroupChangeWithAlterTable() { + String alterTableStmt = "alter table `test_table` drop partition `p1`"; + ddlContext.setDdlStmt(alterTableStmt); + + Map extendParams = new HashMap<>(); + extendParams.put(ICdcManager.CDC_IS_CCI, true); + + SQLAlterTableStatement alterTableStatement = new SQLAlterTableStatement(); + List parseResult = Collections.singletonList(alterTableStatement); + try (MockedStatic sqlUtilsMock = Mockito.mockStatic(SQLUtils.class)) { + sqlUtilsMock.when( + () -> SQLUtils.parseStatements(eq(alterTableStmt), any(), any())) + .thenReturn(parseResult); + + try (MockedStatic cdcManagerMock = Mockito.mockStatic(CdcManagerHelper.class)) { + CdcManagerHelper cdcManagerHelper = Mockito.mock(CdcManagerHelper.class); + cdcManagerMock.when(CdcManagerHelper::getInstance).thenReturn(cdcManagerHelper); + + try (MockedStatic cdcMarkUtilMock = Mockito.mockStatic(CdcMarkUtil.class)) { + cdcMarkUtilMock.when(() -> CdcMarkUtil.buildExtendParameter(executionContext)) + .thenReturn(extendParams); + + cdcColumnarTableGroupDdlMark.mark4ColumnarTableGroupChange(executionContext); + + verify(cdcManagerHelper, times(1)).notifyDdlNew(eq("test_schema"), eq("test_table"), + eq("ALTER_TABLE"), + eq(alterTableStmt), eq(com.alibaba.polardbx.common.ddl.newengine.DdlType.ALTER_TABLEGROUP), + any(), + any(), eq(CdcDdlMarkVisibility.Protected), any()); + } + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/TtlTaskSqlBuilderTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/TtlTaskSqlBuilderTest.java new file mode 100644 index 000000000..abaf233b5 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/TtlTaskSqlBuilderTest.java @@ -0,0 +1,37 @@ +/* + * 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 com.alibaba.polardbx.executor.ddl.job.task; + +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlTaskSqlBuilder; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class TtlTaskSqlBuilderTest { + + @Test + public void testAddParamsToTDDL() { + String originalString = "/*+TDDL:cmd_extra(SOCKET_TIMEOUT=1800000)*/"; + String expectedModifiedString = + "/*+TDDL:cmd_extra(SOCKET_TIMEOUT=1800000,SKIP_DDL_TASKS=\"WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask\")*/"; + String modifiedString = TtlTaskSqlBuilder.addCciHint(originalString, + "SKIP_DDL_TASKS=\"WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask\""); + assertEquals(expectedModifiedString, modifiedString); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTableValidateTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTableValidateTaskTest.java new file mode 100644 index 000000000..5d273bd80 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AlterTableValidateTaskTest.java @@ -0,0 +1,29 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.polardbx.common.utils.Assert; +import com.google.common.collect.Lists; +import junit.framework.TestCase; + +import java.util.List; + +public class AlterTableValidateTaskTest extends TestCase { + public void testContainsColumnNameIgnoreCase1() throws Throwable { + List columnNames = Lists.newArrayList("hello", "World"); + Assert.assertTrue(AlterTableValidateTask.containsColumnNameIgnoreCase(columnNames, "HELLO")); + } + + public void testContainsColumnNameIgnoreCase2() throws Throwable { + List columnNames = Lists.newArrayList("hello", "World"); + Assert.assertTrue(!AlterTableValidateTask.containsColumnNameIgnoreCase(columnNames, "HE")); + } + + public void testIndexOfColumnNameIgnoreCase1() throws Throwable { + List columnNames = Lists.newArrayList("hello", "World"); + Assert.assertTrue(AlterTableValidateTask.indexOfColumnNameIgnoreCase(columnNames, "HELLO") == 0); + } + + public void testIndexOfColumnNamesIgnoreCase2() throws Throwable { + List columnNames = Lists.newArrayList("hello", "World"); + Assert.assertTrue(AlterTableValidateTask.indexOfColumnNameIgnoreCase(columnNames, "HE") == -1); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AnalyzePhyTableTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AnalyzePhyTableTaskTest.java new file mode 100644 index 000000000..dc58ec480 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/AnalyzePhyTableTaskTest.java @@ -0,0 +1,39 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.repo.mysql.spi.DatasourceMySQLImplement; +import org.junit.Test; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import static org.mockito.ArgumentMatchers.anyString; + +/** + * Created by luoyanxin. + * + * @author luoyanxin + */ +public class AnalyzePhyTableTaskTest { + @Test + public void testForeachPhysicalFile_success() { + try (MockedStatic mockedOptimizerContext = Mockito.mockStatic(OptimizerContext.class); + MockedConstruction mockedDatasourceMySQLImplement = Mockito.mockConstruction( + DatasourceMySQLImplement.class, (mock, context) -> { + });) { + OptimizerContext optimizerContext = Mockito.mock(OptimizerContext.class); + ParamManager paramManager = Mockito.mock(ParamManager.class); + mockedOptimizerContext.when(() -> OptimizerContext.getContext(anyString())).thenReturn( + optimizerContext); + Mockito.when(optimizerContext.getParamManager()).thenReturn(paramManager); + Mockito.when(paramManager.getBoolean(ConnectionParams.ANALYZE_TABLE_AFTER_IMPORT_TABLESPACE)).thenReturn( + true).thenReturn(false); + AnalyzePhyTableTask analyzePhyTableTask = new AnalyzePhyTableTask("test", "test", "test"); + analyzePhyTableTask.duringTransaction(null, new ExecutionContext()); + analyzePhyTableTask.duringTransaction(null, new ExecutionContext()); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CloneTableDataFileTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CloneTableDataFileTaskTest.java index 95648ee96..3306d4b91 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CloneTableDataFileTaskTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CloneTableDataFileTaskTest.java @@ -148,7 +148,7 @@ public void prepareAndRunCloneTableDataFileTask(boolean inited, boolean encrypte CloneTableDataFileTask task = spy(new CloneTableDataFileTask("schema", "t1", Pair.of("d1_p00000", "d1_p00000_group"), Pair.of("d1_p00001", "d1_p00001_group"), "t1_za6v_00000", ImmutableList.of(""), "dn0", - Pair.of("26.12.155.86", 31159), list, 1000L, + Pair.of("26.12.155.86", 31159), list, 1000L, 0l, encrypted)); task.setTaskId(1L); diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreatePhyTableWithRollbackCheckTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreatePhyTableWithRollbackCheckTaskTest.java new file mode 100644 index 000000000..29b77eee9 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/CreatePhyTableWithRollbackCheckTaskTest.java @@ -0,0 +1,111 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.backfill.BatchConsumer; +import com.alibaba.polardbx.executor.ddl.job.builder.DropPhyTableBuilder; +import com.alibaba.polardbx.executor.ddl.job.converter.PhysicalPlanData; +import com.alibaba.polardbx.executor.physicalbackfill.PhysicalBackfillManager; +import com.alibaba.polardbx.executor.physicalbackfill.PhysicalBackfillUtils; +import com.alibaba.polardbx.executor.scaleout.ScaleOutUtils; +import com.alibaba.polardbx.gms.partition.PhysicalBackfillDetailInfoFieldJSON; +import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.rpc.pool.XConnection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.mysql.cj.polarx.protobuf.PolarxPhysicalBackfill; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.FutureTask; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyLong; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; + +/** + * Created by luoyanxin. + * + * @author luoyanxin + */ +public class CreatePhyTableWithRollbackCheckTaskTest { + + private PhysicalPlanData physicalPlanDataMock; + private ExecutionContext ecMock; + + @Before + public void setUp() { + physicalPlanDataMock = mock(PhysicalPlanData.class); + //Mockito.doNothing().when(consumerMock) + // .consume(any(), any(), any(), any(), any(PolarxPhysicalBackfill.TransferFileDataOperator.class)); + ecMock = mock(ExecutionContext.class); + } + + @After + public void tearDown() { + Mockito.reset(physicalPlanDataMock, ecMock); + } + + @Test + public void testRollback1() throws Exception { + Map> sourceTableTopology = new HashMap<>(); + Set set = new HashSet<>(); + set.add("t1_00000"); + set.add("t1_00002"); + sourceTableTopology.put("g1", set); + CreatePhyTableWithRollbackCheckTask task = spy(new CreatePhyTableWithRollbackCheckTask("s1", "t1", + physicalPlanDataMock, sourceTableTopology)); + + try (MockedStatic mockedScaleOutUtils = Mockito.mockStatic(ScaleOutUtils.class);) { + Mockito.when(ScaleOutUtils.checkTableExistence(anyString(), anyString(), anyString())) + .thenReturn(true).thenReturn(false); + task.genRollbackPhysicalPlans(ecMock); + } catch (TddlNestableRuntimeException e) { + Assert.assertTrue(e.getMessage().contains("this DDL operation cannot be rolled back")); + } + + } + + @Test + public void testRollback2() throws Exception { + Map> sourceTableTopology = new HashMap<>(); + Set set = new HashSet<>(); + set.add("t1_00000"); + set.add("t1_00002"); + sourceTableTopology.put("g1", set); + CreatePhyTableWithRollbackCheckTask task = spy(new CreatePhyTableWithRollbackCheckTask("s1", "t1", + physicalPlanDataMock, sourceTableTopology)); + DropPhyTableBuilder builder = mock(DropPhyTableBuilder.class); + try (MockedStatic mockedScaleOutUtils = Mockito.mockStatic(ScaleOutUtils.class); + MockedStatic mockedDropPhyTableBuilder = Mockito.mockStatic( + DropPhyTableBuilder.class);) { + Mockito.when(ScaleOutUtils.checkTableExistence(anyString(), anyString(), anyString())) + .thenReturn(true).thenReturn(true); + Mockito.when(DropPhyTableBuilder.createBuilder(anyString(), anyString(), anyBoolean(), any(HashMap.class), + any(ExecutionContext.class))) + .thenReturn(builder); + Mockito.when(builder.build()).thenReturn(builder); + task.genRollbackPhysicalPlans(ecMock); + } catch (TddlNestableRuntimeException e) { + Assert.assertTrue(e.getMessage().contains("this DDL operation cannot be rolled back")); + } + + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PhysicalBackfillTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PhysicalBackfillTaskTest.java index 5b73905fd..8cc73aea0 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PhysicalBackfillTaskTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/PhysicalBackfillTaskTest.java @@ -132,7 +132,7 @@ public void prepareAndRunPhysicalBackfillTask(boolean inited, boolean encrypted, PhysicalBackfillTask task = new PhysicalBackfillTask("schema", 123L, "logicalTable", "physicalTable", ImmutableList.of("partition1"), Pair.of("srcGroup", "srcDn"), Pair.of("srcGroup", "tarGroup"), ImmutableMap.of("srcGroup", Pair.of("username", "password"), "tarGroup", - Pair.of("username", "password")), 1000L, 0L, 500L, false, encrypted); + Pair.of("username", "password")), 1000L, 0L, 0L, 500L, false, encrypted); XConnection conn = mock(XConnection.class); mockedPhysicalBackfillUtils.when( diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TruncateTableBuildJobTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TruncateTableBuildJobTest.java new file mode 100644 index 000000000..f7e3da2d4 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/basic/TruncateTableBuildJobTest.java @@ -0,0 +1,121 @@ +package com.alibaba.polardbx.executor.ddl.job.task.basic; + +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.executor.gms.util.SequenceUtil; +import com.alibaba.polardbx.executor.sync.SyncManagerHelper; +import com.alibaba.polardbx.gms.metadb.seq.SequenceRecord; +import com.alibaba.polardbx.gms.sync.IGmsSyncAction; +import com.alibaba.polardbx.gms.sync.SyncScope; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.sequence.SequenceManagerProxy; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.sql.SequenceBean; +import org.junit.Ignore; +import org.junit.Test; + +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.sql.Connection; + +import static com.alibaba.polardbx.common.constants.SequenceAttribute.Type.NEW; +import static com.alibaba.polardbx.common.constants.SequenceAttribute.Type.TIME; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; + +/** + * Created by zhuqiwei. + * + * @author zhuqiwei + */ +public class TruncateTableBuildJobTest { + + @Ignore + public void testResetSequence4TruncateTableTask() { + Connection metaDbConn = Mockito.mock(Connection.class); + ExecutionContext ec = Mockito.mock(ExecutionContext.class); + + try (MockedStatic mockedSequenceUtil = Mockito.mockStatic(SequenceUtil.class); + MockedStatic mockedSyncManagerHelper = Mockito.mockStatic(SyncManagerHelper.class)) { + mockedSequenceUtil.when( + () -> SequenceUtil.resetSequence4TruncateTable(anyString(), anyString(), any(), any())) + .thenAnswer(invocation -> { + return null; + }); + mockedSyncManagerHelper.when(() -> SyncManagerHelper.sync( + any(IGmsSyncAction.class), anyString(), any(SyncScope.class) + ) + ).thenReturn(ImmutableList.of()); + + ResetSequence4TruncateTableTask task = new ResetSequence4TruncateTableTask("testSchema", "testTb"); + task.duringTransaction(metaDbConn, ec); + } catch (Exception e) { + throw new TddlNestableRuntimeException(e); + } + } + + @Ignore + public void testResetSequence4TruncateTableTaskSyncFailed() { + Connection metaDbConn = Mockito.mock(Connection.class); + ExecutionContext ec = Mockito.mock(ExecutionContext.class); + + try (MockedStatic mockedSequenceUtil = Mockito.mockStatic(SequenceUtil.class); + MockedStatic mockedSyncManagerHelper = Mockito.mockStatic(SyncManagerHelper.class)) { + mockedSequenceUtil.when( + () -> SequenceUtil.resetSequence4TruncateTable(anyString(), anyString(), any(), any())) + .thenAnswer(invocation -> { + return null; + }); + mockedSyncManagerHelper.when(() -> SyncManagerHelper.sync( + any(IGmsSyncAction.class), anyString(), any(SyncScope.class) + ) + ).thenThrow(new TddlNestableRuntimeException()); + + ResetSequence4TruncateTableTask task = new ResetSequence4TruncateTableTask("testSchema", "testTb"); + task.duringTransaction(metaDbConn, ec); + } catch (Exception e) { + throw new TddlNestableRuntimeException(e); + } + } + + @Test + public void testResetSequence4TruncateTableUtil() { + Connection metaDbConn = Mockito.mock(Connection.class); + ExecutionContext ec = Mockito.mock(ExecutionContext.class); + ParamManager pm = Mockito.mock(ParamManager.class); + + SequenceManagerProxy proxy = Mockito.mock(SequenceManagerProxy.class); + + Mockito.when(ec.getParamManager()).thenReturn(pm); + Mockito.when(pm.getLong(ConnectionParams.NEW_SEQ_CACHE_SIZE)).thenReturn(0L); + + try (MockedStatic mockedSequenceManagerProxy = Mockito.mockStatic( + SequenceManagerProxy.class)) { + mockedSequenceManagerProxy.when(() -> SequenceManagerProxy.getInstance()).thenReturn(proxy); + Mockito.when(proxy.checkIfExists(anyString(), anyString())).thenReturn(NEW); + + SequenceUtil.resetSequence4TruncateTable("testSchema", "tb", metaDbConn, ec); + + } catch (TddlRuntimeException ignore) { + } + + ParamManager pm2 = Mockito.mock(ParamManager.class); + Mockito.when(pm2.getLong(ConnectionParams.NEW_SEQ_CACHE_SIZE)).thenReturn(100L); + Mockito.when(ec.getParamManager()).thenReturn(pm2); + try (MockedStatic mockedSequenceManagerProxy = Mockito.mockStatic( + SequenceManagerProxy.class)) { + mockedSequenceManagerProxy.when(() -> SequenceManagerProxy.getInstance()).thenReturn(proxy); + Mockito.when(proxy.checkIfExists(anyString(), anyString())).thenReturn(TIME); + + SequenceUtil.resetSequence4TruncateTable("testSchema", "tb", metaDbConn, ec); + + } catch (TddlRuntimeException ignore) { + } + + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAllocateLocalPartitionMarkTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAllocateLocalPartitionMarkTaskTest.java new file mode 100644 index 000000000..16e94b38e --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcAllocateLocalPartitionMarkTaskTest.java @@ -0,0 +1,77 @@ +package com.alibaba.polardbx.executor.ddl.job.task.cdc; + +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.common.ddl.newengine.DdlType; +import com.alibaba.polardbx.druid.sql.SQLUtils; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.apache.calcite.sql.SqlKind; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class CdcAllocateLocalPartitionMarkTaskTest { + + @Test + public void testMark4AllocateLocalPartitionTable() { + + ExecutionContext executionContext = Mockito.mock(ExecutionContext.class); + ExecutionContext ecCopy = Mockito.mock(ExecutionContext.class); + DdlContext ddlContext = new DdlContext(); + + CdcAllocateLocalPartitionMarkTask cdcAllocateLocalPartitionMarkTask = + Mockito.mock(CdcAllocateLocalPartitionMarkTask.class); + + Mockito.doNothing().when( + cdcAllocateLocalPartitionMarkTask).updateSupportedCommands(false, false, null); + Mockito.doCallRealMethod().when(cdcAllocateLocalPartitionMarkTask).duringTransaction(null, executionContext); + Mockito.when(executionContext.copy()).thenReturn(ecCopy); + Mockito.when(ecCopy.getDdlContext()).thenReturn(ddlContext); + Mockito.when(executionContext.getDdlContext()).thenReturn(ddlContext); + String alterTableStmt = + "ALTER TABLE t_single_tb ALLOCATE LOCAL PARTITION"; + ddlContext.setDdlStmt(alterTableStmt); + ddlContext.setDdlType(DdlType.ALTER_TABLE); + + Map extendParams = new HashMap<>(); + extendParams.put(ICdcManager.CDC_IS_CCI, true); + + SQLAlterTableStatement alterTableStatement = new SQLAlterTableStatement(); + List parseResult = Collections.singletonList(alterTableStatement); + try (MockedStatic sqlUtilsMock = Mockito.mockStatic(SQLUtils.class)) { + sqlUtilsMock.when( + () -> SQLUtils.parseStatements(eq(alterTableStmt), any(), any())) + .thenReturn(parseResult); + + try (MockedStatic cdcManagerMock = Mockito.mockStatic(CdcManagerHelper.class)) { + CdcManagerHelper cdcManagerHelper = Mockito.mock(CdcManagerHelper.class); + cdcManagerMock.when(CdcManagerHelper::getInstance).thenReturn(cdcManagerHelper); + + try (MockedStatic cdcMarkUtilMock = Mockito.mockStatic(CdcMarkUtil.class)) { + cdcMarkUtilMock.when(() -> CdcMarkUtil.buildExtendParameter(executionContext)) + .thenReturn(extendParams); + cdcAllocateLocalPartitionMarkTask.duringTransaction(null, executionContext); + + verify(cdcManagerHelper, times(1)).notifyDdlNew(any(), any(), + eq(SqlKind.ALLOCATE_LOCAL_PARTITION.name()), + eq(alterTableStmt), eq(DdlType.ALTER_TABLE), + any(), + any(), eq(CdcDdlMarkVisibility.Protected), any()); + } + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcExpireLocalPartitionMarkTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcExpireLocalPartitionMarkTaskTest.java new file mode 100644 index 000000000..469bc7071 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcExpireLocalPartitionMarkTaskTest.java @@ -0,0 +1,138 @@ +package com.alibaba.polardbx.executor.ddl.job.task.cdc; + +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.common.cdc.DdlScope; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.common.ddl.newengine.DdlType; +import com.alibaba.polardbx.druid.sql.SQLUtils; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.apache.calcite.sql.SqlKind; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class CdcExpireLocalPartitionMarkTaskTest { + + @Test + public void testMark4ExpireLocalPartitionTable() { + + ExecutionContext executionContext = Mockito.mock(ExecutionContext.class); + ExecutionContext ecCopy = Mockito.mock(ExecutionContext.class); + DdlContext ddlContext = new DdlContext(); + + CdcExpireLocalPartitionMarkTask cdcExpireLocalPartitionMarkTask = + Mockito.mock(CdcExpireLocalPartitionMarkTask.class); + + Mockito.doNothing().when( + cdcExpireLocalPartitionMarkTask).updateSupportedCommands(false, false, null); + Mockito.doCallRealMethod().when(cdcExpireLocalPartitionMarkTask).duringTransaction(null, executionContext); + Mockito.when(executionContext.copy()).thenReturn(ecCopy); + Mockito.when(ecCopy.getDdlContext()).thenReturn(ddlContext); + Mockito.when(executionContext.getDdlContext()).thenReturn(ddlContext); + String alterTableStmt = + "ALTER TABLE t_create_ssyi EXPIRE LOCAL PARTITIO"; + ddlContext.setDdlStmt(alterTableStmt); + ddlContext.setDdlType(DdlType.ALTER_TABLE); + + Map extendParams = new HashMap<>(); + extendParams.put(ICdcManager.CDC_IS_CCI, true); + + SQLAlterTableStatement alterTableStatement = new SQLAlterTableStatement(); + List parseResult = Collections.singletonList(alterTableStatement); + try (MockedStatic sqlUtilsMock = Mockito.mockStatic(SQLUtils.class)) { + sqlUtilsMock.when( + () -> SQLUtils.parseStatements(eq(alterTableStmt), any(), any())) + .thenReturn(parseResult); + + try (MockedStatic cdcManagerMock = Mockito.mockStatic(CdcManagerHelper.class)) { + CdcManagerHelper cdcManagerHelper = Mockito.mock(CdcManagerHelper.class); + cdcManagerMock.when(CdcManagerHelper::getInstance).thenReturn(cdcManagerHelper); + + try (MockedStatic cdcMarkUtilMock = Mockito.mockStatic(CdcMarkUtil.class)) { + cdcMarkUtilMock.when(() -> CdcMarkUtil.buildExtendParameter(executionContext)) + .thenReturn(extendParams); + cdcExpireLocalPartitionMarkTask.duringTransaction(null, executionContext); + + verify(cdcManagerHelper, times(1)).notifyDdlNew(any(), any(), + eq(SqlKind.EXPIRE_LOCAL_PARTITION.name()), + eq(alterTableStmt), eq(DdlType.ALTER_TABLE), + any(), + any(), eq(CdcDdlMarkVisibility.Protected), any()); + } + } + } + } + + @Test + public void testMark4ExpireLocalPartitionTableWithFpOverRideNow() { + + ExecutionContext executionContext = Mockito.mock(ExecutionContext.class); + ExecutionContext ecCopy = Mockito.mock(ExecutionContext.class); + DdlContext ddlContext = new DdlContext(); + + CdcExpireLocalPartitionMarkTask cdcExpireLocalPartitionMarkTask = + Mockito.mock(CdcExpireLocalPartitionMarkTask.class); + + Mockito.doNothing().when( + cdcExpireLocalPartitionMarkTask).updateSupportedCommands(false, false, null); + Mockito.doCallRealMethod().when(cdcExpireLocalPartitionMarkTask).duringTransaction(null, executionContext); + Mockito.when(executionContext.copy()).thenReturn(ecCopy); + Mockito.when(ecCopy.getDdlContext()).thenReturn(ddlContext); + Mockito.when(executionContext.getDdlContext()).thenReturn(ddlContext); + + Map userDefineMap = new HashMap<>(); + userDefineMap.put("fp_override_now", "2013-08-21"); + Mockito.when(executionContext.getUserDefVariables()).thenReturn(userDefineMap); + + String alterTableStmt = + "ALTER TABLE t_create_ssyi EXPIRE LOCAL PARTITIO"; + ddlContext.setDdlStmt(alterTableStmt); + ddlContext.setDdlType(DdlType.ALTER_TABLE); + + Map extendParams = new HashMap<>(); + extendParams.put(ICdcManager.CDC_IS_CCI, true); + + Map expectParams = new HashMap<>(); + expectParams.put(ICdcManager.CDC_IS_CCI, true); + expectParams.put("cdc_ddl_scope", DdlScope.Schema); + expectParams.put("FP_OVERRIDE_NOW", "2013-08-21"); + + SQLAlterTableStatement alterTableStatement = new SQLAlterTableStatement(); + List parseResult = Collections.singletonList(alterTableStatement); + try (MockedStatic sqlUtilsMock = Mockito.mockStatic(SQLUtils.class)) { + sqlUtilsMock.when( + () -> SQLUtils.parseStatements(eq(alterTableStmt), any(), any())) + .thenReturn(parseResult); + + try (MockedStatic cdcManagerMock = Mockito.mockStatic(CdcManagerHelper.class)) { + CdcManagerHelper cdcManagerHelper = Mockito.mock(CdcManagerHelper.class); + cdcManagerMock.when(CdcManagerHelper::getInstance).thenReturn(cdcManagerHelper); + + try (MockedStatic cdcMarkUtilMock = Mockito.mockStatic(CdcMarkUtil.class)) { + cdcMarkUtilMock.when(() -> CdcMarkUtil.buildExtendParameter(executionContext)) + .thenReturn(extendParams); + cdcExpireLocalPartitionMarkTask.duringTransaction(null, executionContext); + + verify(cdcManagerHelper, times(1)).notifyDdlNew(any(), any(), + eq(SqlKind.EXPIRE_LOCAL_PARTITION.name()), + eq(alterTableStmt), eq(DdlType.ALTER_TABLE), + any(), + any(), eq(CdcDdlMarkVisibility.Protected), eq(expectParams)); + } + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcMarkUtilTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcMarkUtilTest.java new file mode 100644 index 000000000..51ae5ce30 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcMarkUtilTest.java @@ -0,0 +1,13 @@ +package com.alibaba.polardbx.executor.ddl.job.task.cdc; + +import org.junit.Assert; +import org.junit.Test; + +public class CdcMarkUtilTest { + @Test + public void testScheduleJobDdlRegex() { + Assert.assertFalse(CdcMarkUtil.isScheduleJobDdl("alter table t1 add column c1 int")); + Assert.assertTrue(CdcMarkUtil.isScheduleJobDdl("/*SCHEDULE_JOB_DDL*/alter table t1 add column c1 int")); + + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcRepartitionLocalPartitionMarkTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcRepartitionLocalPartitionMarkTaskTest.java new file mode 100644 index 000000000..7a8bec986 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/cdc/CdcRepartitionLocalPartitionMarkTaskTest.java @@ -0,0 +1,77 @@ +package com.alibaba.polardbx.executor.ddl.job.task.cdc; + +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.common.ddl.newengine.DdlType; +import com.alibaba.polardbx.druid.sql.SQLUtils; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.apache.calcite.sql.SqlKind; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class CdcRepartitionLocalPartitionMarkTaskTest { + + @Test + public void testMark4ExpireLocalPartitionTable() { + + ExecutionContext executionContext = Mockito.mock(ExecutionContext.class); + ExecutionContext ecCopy = Mockito.mock(ExecutionContext.class); + DdlContext ddlContext = new DdlContext(); + + CdcRepartitionLocalPartitionMarkTask cdcRepartitionLocalPartitionMarkTask = + Mockito.mock(CdcRepartitionLocalPartitionMarkTask.class); + + Mockito.doNothing().when( + cdcRepartitionLocalPartitionMarkTask).updateSupportedCommands(false, false, null); + Mockito.doCallRealMethod().when(cdcRepartitionLocalPartitionMarkTask).duringTransaction(null, executionContext); + Mockito.when(executionContext.copy()).thenReturn(ecCopy); + Mockito.when(ecCopy.getDdlContext()).thenReturn(ddlContext); + Mockito.when(executionContext.getDdlContext()).thenReturn(ddlContext); + String alterTableStmt = + "ALTER TABLE t_ttl_single LOCAL PARTITION BY RANGE (gmt_modified) STARTWITH '2023-08-20' INTERVAL 1 MONTH EXPIRE AFTER 1 PRE ALLOCATE 3 PIVOTDATE now()"; + ddlContext.setDdlStmt(alterTableStmt); + ddlContext.setDdlType(DdlType.ALTER_TABLE); + + Map extendParams = new HashMap<>(); + extendParams.put(ICdcManager.CDC_IS_CCI, true); + + SQLAlterTableStatement alterTableStatement = new SQLAlterTableStatement(); + List parseResult = Collections.singletonList(alterTableStatement); + try (MockedStatic sqlUtilsMock = Mockito.mockStatic(SQLUtils.class)) { + sqlUtilsMock.when( + () -> SQLUtils.parseStatements(eq(alterTableStmt), any(), any())) + .thenReturn(parseResult); + + try (MockedStatic cdcManagerMock = Mockito.mockStatic(CdcManagerHelper.class)) { + CdcManagerHelper cdcManagerHelper = Mockito.mock(CdcManagerHelper.class); + cdcManagerMock.when(CdcManagerHelper::getInstance).thenReturn(cdcManagerHelper); + + try (MockedStatic cdcMarkUtilMock = Mockito.mockStatic(CdcMarkUtil.class)) { + cdcMarkUtilMock.when(() -> CdcMarkUtil.buildExtendParameter(executionContext)) + .thenReturn(extendParams); + cdcRepartitionLocalPartitionMarkTask.duringTransaction(null, executionContext); + + verify(cdcManagerHelper, times(1)).notifyDdlNew(any(), any(), + eq(SqlKind.REPARTITION_LOCAL_PARTITION.name()), + eq(alterTableStmt), eq(DdlType.ALTER_TABLE), + any(), + any(), eq(CdcDdlMarkVisibility.Protected), any()); + } + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciIncrementTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciIncrementTaskTest.java new file mode 100644 index 000000000..a22492f8a --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciIncrementTaskTest.java @@ -0,0 +1,97 @@ +package com.alibaba.polardbx.executor.ddl.job.task.columnar; + +import com.alibaba.polardbx.executor.columnar.checker.ICciChecker; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.CheckCciPrepareData; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.sql.SqlCheckColumnarIndex; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collection; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class CheckCciIncrementTaskTest { + @Test + public void testSuccessWithEmptyResults() throws Throwable { + String schema = "test"; + String table = "test"; + String index = "test"; + SqlCheckColumnarIndex.CheckCciExtraCmd extraCmd = SqlCheckColumnarIndex.CheckCciExtraCmd.INCREMENT; + List tsoList = ImmutableList.of(100L, 200L, 200L); + CheckCciPrepareData checkCciPrepareData = new CheckCciPrepareData(schema, table, index, extraCmd, tsoList); + CheckCciIncrementTask task = CheckCciIncrementTask.create(checkCciPrepareData); + Assert.assertEquals(schema, task.getSchemaName()); + Assert.assertEquals(table, task.getTableName()); + Assert.assertEquals(index, task.getIndexName()); + + ExecutionContext ec = new ExecutionContext(); + ICciChecker checker = mock(ICciChecker.class); + when(checker.getCheckReports(any())).thenReturn(true); + + task.setJobId(0L); + task.doCheck(ec, checker); + System.out.println(task.getReports()); + Assert.assertTrue(task.getReports().size() == 1 && task.getReports().get(0).getDetails() + .contains("incremental data of columnar index between 100 and 200 checked")); + } + + @Test + public void testSuccessWithOneResult() throws Throwable { + String schema = "test"; + String table = "test"; + String index = "test"; + SqlCheckColumnarIndex.CheckCciExtraCmd extraCmd = SqlCheckColumnarIndex.CheckCciExtraCmd.INCREMENT; + List tsoList = ImmutableList.of(100L, 200L, 200L); + CheckCciPrepareData checkCciPrepareData = new CheckCciPrepareData(schema, table, index, extraCmd, tsoList); + CheckCciIncrementTask task = CheckCciIncrementTask.create(checkCciPrepareData); + Assert.assertEquals(schema, task.getSchemaName()); + Assert.assertEquals(table, task.getTableName()); + Assert.assertEquals(index, task.getIndexName()); + + ExecutionContext ec = new ExecutionContext(); + ICciChecker checker = mock(ICciChecker.class); + when(checker.getCheckReports(any())).then( + invocation -> { + Collection reports = invocation.getArgument(0); + reports.add("testSuccessWithOneResult"); + return true; + } + ); + + task.setJobId(0L); + task.doCheck(ec, checker); + System.out.println(task.getReports()); + Assert.assertTrue(task.getReports().size() == 2 && task.getReports().get(0).getDetails() + .contains("testSuccessWithOneResult")); + } + + @Test + public void testFailWithException() throws Throwable { + String schema = "test"; + String table = "test"; + String index = "test"; + SqlCheckColumnarIndex.CheckCciExtraCmd extraCmd = SqlCheckColumnarIndex.CheckCciExtraCmd.INCREMENT; + List tsoList = ImmutableList.of(100L, 200L, 200L); + CheckCciPrepareData checkCciPrepareData = new CheckCciPrepareData(schema, table, index, extraCmd, tsoList); + CheckCciIncrementTask task = CheckCciIncrementTask.create(checkCciPrepareData); + Assert.assertEquals(schema, task.getSchemaName()); + Assert.assertEquals(table, task.getTableName()); + Assert.assertEquals(index, task.getIndexName()); + + ExecutionContext ec = new ExecutionContext(); + ICciChecker checker = mock(ICciChecker.class); + doThrow(new RuntimeException("testFailWithException")).when(checker).check(ec, 100L, 200L, 200L); + + task.setJobId(0L); + task.doCheck(ec, checker); + System.out.println(task.getReports()); + Assert.assertTrue(task.getReports().size() == 2 && task.getReports().get(0).getDetails() + .contains("Error occurs when checking, caused by testFailWithException")); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciSnapshotTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciSnapshotTaskTest.java new file mode 100644 index 000000000..94c99103b --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/CheckCciSnapshotTaskTest.java @@ -0,0 +1,73 @@ +package com.alibaba.polardbx.executor.ddl.job.task.columnar; + +import com.alibaba.polardbx.executor.columnar.checker.ICciChecker; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.CheckCciPrepareData; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.sql.SqlCheckColumnarIndex; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collection; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class CheckCciSnapshotTaskTest { + @Test + public void testFailedWithOneResult() throws Throwable { + String schema = "test"; + String table = "test"; + String index = "test"; + SqlCheckColumnarIndex.CheckCciExtraCmd extraCmd = SqlCheckColumnarIndex.CheckCciExtraCmd.SNAPSHOT; + List tsoList = ImmutableList.of(100L, 200L); + CheckCciPrepareData checkCciPrepareData = new CheckCciPrepareData(schema, table, index, extraCmd, tsoList); + CheckCciSnapshotTask task = CheckCciSnapshotTask.create(checkCciPrepareData); + Assert.assertEquals(schema, task.getSchemaName()); + Assert.assertEquals(table, task.getTableName()); + Assert.assertEquals(index, task.getIndexName()); + + ExecutionContext ec = new ExecutionContext(); + ICciChecker checker = mock(ICciChecker.class); + when(checker.getCheckReports(any())).then( + invocation -> { + Collection reports = invocation.getArgument(0); + reports.add("testFailedWithOneResult"); + return false; + } + ); + + task.setJobId(0L); + task.doCheck(ec, checker); + System.out.println(task.getReports()); + Assert.assertTrue(task.getReports().size() == 2 && task.getReports().get(0).getDetails() + .contains("testFailedWithOneResult")); + } + + @Test + public void testFailWithException() throws Throwable { + String schema = "test"; + String table = "test"; + String index = "test"; + SqlCheckColumnarIndex.CheckCciExtraCmd extraCmd = SqlCheckColumnarIndex.CheckCciExtraCmd.SNAPSHOT; + List tsoList = ImmutableList.of(100L, 200L); + CheckCciPrepareData checkCciPrepareData = new CheckCciPrepareData(schema, table, index, extraCmd, tsoList); + CheckCciSnapshotTask task = CheckCciSnapshotTask.create(checkCciPrepareData); + Assert.assertEquals(schema, task.getSchemaName()); + Assert.assertEquals(table, task.getTableName()); + Assert.assertEquals(index, task.getIndexName()); + + ExecutionContext ec = new ExecutionContext(); + ICciChecker checker = mock(ICciChecker.class); + doThrow(new RuntimeException("testFailWithException")).when(checker).check(ec); + + task.setJobId(0L); + task.doCheck(ec, checker); + System.out.println(task.getReports()); + Assert.assertTrue(task.getReports().size() == 2 && task.getReports().get(0).getDetails() + .contains("Error occurs when checking, caused by testFailWithException")); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/RenameTableTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/RenameTableTest.java new file mode 100644 index 000000000..c0c1e2c2c --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/RenameTableTest.java @@ -0,0 +1,90 @@ +/* + * 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 com.alibaba.polardbx.executor.ddl.job.task.columnar; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.sql.Connection; + +@RunWith(MockitoJUnitRunner.class) +public class RenameTableTest { + + @Mock + private Connection metaDbConnection; + @Mock + private ExecutionContext executionContext; + + @InjectMocks + private RenameColumnarTablesMetaTask task1; + + private RenameColumnarTableMetaTask task2; + + private static final String SCHEMA_NAME = "testSchema"; + private static final String OLD_TABLE_NAME = "oldTableName"; + private static final String NEW_TABLE_NAME = "newTableName"; + private static final Long VERSION_ID = 1L; + private static final Long JOB_ID = 1L; + + @Before + public void setUp() { + task1 = new RenameColumnarTablesMetaTask(SCHEMA_NAME, + java.util.Collections.singletonList(OLD_TABLE_NAME), + java.util.Collections.singletonList(NEW_TABLE_NAME), + java.util.Collections.singletonList(VERSION_ID)); + task1.setJobId(JOB_ID); + + task2 = new RenameColumnarTableMetaTask(SCHEMA_NAME, + OLD_TABLE_NAME, + NEW_TABLE_NAME, + VERSION_ID); + task2.setJobId(JOB_ID); + } + + @Test(expected = TddlRuntimeException.class) + public void testRenameTables() throws Exception { + // When: executeImpl method is called. + task1.executeImpl(metaDbConnection, executionContext); + } + + @Test(expected = TddlRuntimeException.class) + public void testRenameTablesRollback() throws Exception { + // When: executeImpl method is called. + task1.rollbackImpl(metaDbConnection, executionContext); + } + + @Test(expected = TddlRuntimeException.class) + public void testRenameTable() throws Exception { + // When: executeImpl method is called. + task2.executeImpl(metaDbConnection, executionContext); + } + + @Test(expected = TddlRuntimeException.class) + public void testRenameTableRollback() throws Exception { + // When: executeImpl method is called. + task2.rollbackImpl(metaDbConnection, executionContext); + } +} + diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/WaitColumnarTableAlterPartitionTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/WaitColumnarTableAlterPartitionTaskTest.java new file mode 100644 index 000000000..e3bc1e2cc --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/columnar/WaitColumnarTableAlterPartitionTaskTest.java @@ -0,0 +1,140 @@ +/* + * 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 com.alibaba.polardbx.executor.ddl.job.task.columnar; + +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.sql.Connection; +import java.util.Collections; + +import static com.alibaba.polardbx.common.utils.Assert.fail; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class WaitColumnarTableAlterPartitionTaskTest { + @Mock + private ExecutionContext executionContext; + + @Mock + private Connection connection; + + @Mock + private DdlContext ddlContext; + + @Mock + MetaDbDataSource metaDbDataSource; + + private MockedStatic mockMetaDbDataSource; + private MockedConstruction mockTableInfoManager; + + private final ColumnarTableMappingRecord mappingRecord = new ColumnarTableMappingRecord(); + private final ColumnarTableEvolutionRecord evolutionRecord = new ColumnarTableEvolutionRecord(); + private final ColumnarCheckpointsRecord checkpointRecord = new ColumnarCheckpointsRecord(); + + @Before + public void setUp() throws Exception { + mockMetaDbDataSource = Mockito.mockStatic(MetaDbDataSource.class); + mockMetaDbDataSource.when(MetaDbDataSource::getInstance).thenReturn(metaDbDataSource); + when(metaDbDataSource.getConnection()).thenReturn(connection); + + mappingRecord.latestVersionId = 1; + evolutionRecord.commitTs = 1000L; + checkpointRecord.extra = WaitColumnarTableAlterPartitionTask.ALTER_PARTITION_SUCCESS_CHECKPOINT_TYPE; + + mockTableInfoManager = Mockito.mockConstruction( + TableInfoManager.class, + (mock, context) -> { + Mockito.when(mock.queryColumnarTableMapping(Mockito.anyString(), Mockito.anyString())).thenAnswer( + invocation -> Collections.singletonList(mappingRecord) + ); + Mockito.when(mock.queryColumnarTableEvolutionByVersionId(Mockito.anyLong())).thenAnswer( + invocation -> evolutionRecord + ); + Mockito.when(mock.queryColumnarCheckpointsByCommitTs(Mockito.anyLong())).thenAnswer( + invocation -> Collections.singletonList(checkpointRecord) + ); + }); + + when(executionContext.getDdlContext()).thenReturn(ddlContext); + when(ddlContext.isInterrupted()).thenReturn(false); + } + + @After + public void tearDown() throws Exception { + if (mockMetaDbDataSource != null) { + mockMetaDbDataSource.close(); + } + + if (mockTableInfoManager != null) { + mockTableInfoManager.close(); + } + } + + @Test + public void testBeforeTransaction_Success() throws Exception { + String schemaName = "testSchema"; + String indexName = "testIndex"; + WaitColumnarTableAlterPartitionTask task = + spy(new WaitColumnarTableAlterPartitionTask(schemaName, Collections.singletonList(indexName), false)); + + task.beforeTransaction(executionContext); + + // 跳出等待循环 + verify(executionContext, times(1)).getDdlContext(); + } + + @Test + public void testBeforeTransaction_Failed() throws Exception { + String schemaName = "testSchema"; + String indexName = "testIndex"; + WaitColumnarTableAlterPartitionTask task = + spy(new WaitColumnarTableAlterPartitionTask(schemaName, Collections.singletonList(indexName), false)); + + checkpointRecord.extra = ""; + when(ddlContext.isInterrupted()).thenReturn(true); + + // 验证抛出异常 + try { + task.beforeTransaction(executionContext); + fail("Expected an exception to be thrown"); // 如果未抛出异常,测试失败 + } catch (Exception e) { + // 验证异常类型和消息 + assertEquals("ERR-CODE: [PXC-4636][ERR_DDL_JOB_ERROR] The job '0' has been interrupted. ", e.getMessage()); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/TableGroupRefreshColumnarTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/TableGroupRefreshColumnarTest.java new file mode 100644 index 000000000..16eb0f23e --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/job/task/tablegroup/TableGroupRefreshColumnarTest.java @@ -0,0 +1,140 @@ +/* + * 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. + */ + +import com.alibaba.polardbx.executor.ddl.job.task.tablegroup.AlterTableGroupRefreshMetaBaseTask; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.partition.TablePartitionAccessor; +import com.alibaba.polardbx.gms.partition.TablePartitionRecord; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class TableGroupRefreshColumnarTest { + + @Mock + private TablePartitionAccessor tablePartitionAccessor; + @Mock + private ColumnarTableMappingAccessor columnarTableMappingAccessor; + @Mock + private ColumnarPartitionEvolutionAccessor columnarPartitionEvolutionAccessor; + @Mock + private ColumnarTableEvolutionAccessor columnarTableEvolutionAccessor; + + @InjectMocks + private AlterTableGroupRefreshMetaBaseTask task; + + private final static String TABLE_GROUP_NAME = "tg_test"; + private final static String SCHEMA_NAME = "db_test"; + private final static String TABLE_NAME = "tb_test"; + private final static long VERSION_ID = 1L; + private final static long JOB_ID = 2L; + + @Before + public void setUp() { + task = new AlterTableGroupRefreshMetaBaseTask(SCHEMA_NAME, TABLE_GROUP_NAME, VERSION_ID); + } + + @Test + public void testUpdateColumnarEvolutionSysTables() { + TableMeta tableMeta = mock(TableMeta.class); + when(tableMeta.isColumnar()).thenReturn(true); + + List evolutionRecords = new ArrayList<>(); + ColumnarPartitionEvolutionRecord record = new ColumnarPartitionEvolutionRecord(); + record.id = 3L; + evolutionRecords.add(record); + + when(columnarPartitionEvolutionAccessor.queryIdsWithOrder(anyList())).thenReturn(evolutionRecords); + + List partitionRecords = new ArrayList<>(); + TablePartitionRecord partitionRecord1 = new TablePartitionRecord(); + TablePartitionRecord partitionRecord2 = new TablePartitionRecord(); + TablePartitionRecord partitionRecordOld1 = new TablePartitionRecord(); + TablePartitionRecord partitionRecordOld2 = new TablePartitionRecord(); + partitionRecord1.partName = ""; + // rename partition name + partitionRecord2.partName = "p10"; + partitionRecords.add(partitionRecord1); + partitionRecords.add(partitionRecord2); + partitionRecordOld1.partName = ""; + partitionRecordOld2.partName = "p1"; + + when(tablePartitionAccessor.getTablePartitionsByDbNameTbName(eq(SCHEMA_NAME), eq(TABLE_NAME), eq(false))) + .thenReturn(partitionRecords); + + List columnarTableMappingRecords = new ArrayList<>(); + ColumnarTableMappingRecord columnarTableMappingRecord = new ColumnarTableMappingRecord(); + columnarTableMappingRecord.tableId = 1L; + columnarTableMappingRecords.add(columnarTableMappingRecord); + + ColumnarTableEvolutionRecord columnarTableEvolutionRecord = new ColumnarTableEvolutionRecord(); + columnarTableEvolutionRecord.partitions = new ArrayList<>(); + columnarTableEvolutionRecord.partitions.add(0L); + columnarTableEvolutionRecord.partitions.add(1L); + + List columnarPartitionEvolutionRecords = new ArrayList<>(); + ColumnarPartitionEvolutionRecord record1 = + new ColumnarPartitionEvolutionRecord(1L, "", 1L, 1L, partitionRecordOld1, 1); + ColumnarPartitionEvolutionRecord record2 = + new ColumnarPartitionEvolutionRecord(1L, "p1", 1L, 1L, partitionRecordOld2, 1); + columnarPartitionEvolutionRecords.add(record1); + columnarPartitionEvolutionRecords.add(record2); + + when(columnarTableMappingAccessor.querySchemaIndex(eq(SCHEMA_NAME), eq(TABLE_NAME))).thenReturn( + columnarTableMappingRecords); + + when(columnarPartitionEvolutionAccessor.queryIdsWithOrder(anyList())).thenReturn( + columnarPartitionEvolutionRecords); + + when(columnarTableEvolutionAccessor.queryTableIdLatest(eq(1L))).thenReturn( + Collections.singletonList(columnarTableEvolutionRecord)); + + when(columnarPartitionEvolutionAccessor.queryTableIdAndNotInStatus(anyLong(), anyLong(), anyLong())).thenReturn( + columnarPartitionEvolutionRecords); + + task.updateColumnarEvolutionSysTables(tableMeta, TABLE_NAME, tablePartitionAccessor, + columnarTableMappingAccessor, columnarPartitionEvolutionAccessor, columnarTableEvolutionAccessor, + VERSION_ID, JOB_ID); + + verify(columnarPartitionEvolutionAccessor, times(1)).insert(anyList()); + verify(columnarTableMappingAccessor, times(1)).updateVersionId(eq(VERSION_ID), anyLong()); + } +} + diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineSchedulerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineSchedulerTest.java new file mode 100644 index 000000000..c48d9e5a6 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/newengine/DdlEngineSchedulerTest.java @@ -0,0 +1,19 @@ +package com.alibaba.polardbx.executor.ddl.newengine; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.TimeoutException; + +public class DdlEngineSchedulerTest { + + @Test + public void testCompareAndExecute() { + try { + DdlEngineScheduler ddlEngineScheduler = DdlEngineScheduler.getInstance(); + ddlEngineScheduler.compareAndExecute(0, () -> null); + Assert.fail("should trigger timeout exception, but not."); + } catch (TimeoutException ignored) { + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/newengine/backfill/BackfillHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/newengine/backfill/BackfillHandlerTest.java deleted file mode 100644 index f9f104fe3..000000000 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/newengine/backfill/BackfillHandlerTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.alibaba.polardbx.executor.ddl.newengine.backfill; - -import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; -import com.alibaba.polardbx.optimizer.config.table.SchemaManager; -import com.alibaba.polardbx.optimizer.config.table.TableMeta; -import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.repo.mysql.handler.GsiBackfillHandler; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -public class BackfillHandlerTest { - - @Test - public void testGetPrimaryTableName() { - ExecutionContext executionContext = Mockito.mock(ExecutionContext.class); - SchemaManager schemaManager = Mockito.mock(SchemaManager.class); - TableMeta tableMeta = Mockito.mock(TableMeta.class); - GsiMetaManager.GsiTableMetaBean gsiTableMetaBean = Mockito.mock(GsiMetaManager.GsiTableMetaBean.class); - GsiMetaManager.GsiIndexMetaBean gsiIndexMetaBean = Mockito.mock(GsiMetaManager.GsiIndexMetaBean.class); - - Mockito.when(executionContext.getSchemaManager(Mockito.anyString())).thenReturn(schemaManager); - Mockito.when(schemaManager.getTable(Mockito.anyString())).thenReturn(tableMeta); - Mockito.when(tableMeta.isGsi()).thenReturn(true); - Mockito.when(tableMeta.getGsiTableMetaBean()).thenReturn(gsiTableMetaBean); - gsiTableMetaBean.gsiMetaBean = gsiIndexMetaBean; - - String tableName = GsiBackfillHandler.getPrimaryTableName("wumu", "gsi", true, executionContext); - Assert.assertNull(tableName); - } -} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/newengine/subjob/SpecialCharacterTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/newengine/subjob/SpecialCharacterTest.java new file mode 100644 index 000000000..475d0e730 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/ddl/newengine/subjob/SpecialCharacterTest.java @@ -0,0 +1,174 @@ +package com.alibaba.polardbx.executor.ddl.newengine.subjob; + +import com.alibaba.polardbx.common.ddl.foreignkey.ForeignKeyData; +import com.alibaba.polardbx.executor.ddl.job.task.basic.SubJobTask; +import com.alibaba.polardbx.executor.ddl.job.task.factory.GsiTaskFactory; +import com.alibaba.polardbx.executor.handler.ddl.LogicalDropIndexHandler; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableRepartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.RenameLocalIndexPreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.RepartitionPrepareData; +import org.apache.calcite.plan.RelOptCluster; +import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.ddl.AlterTableRepartition; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.sql.SqlDdl; +import org.apache.calcite.sql.SqlDialect; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.util.SqlString; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.mockito.Mockito.when; + +public class SpecialCharacterTest { + + @Test + public void testGenAlterGlobalIndexDropColumnsSql() { + String indexName = "idx`Name"; + List columns = new ArrayList<>(); + columns.add("c`olumn"); + columns.add("c o l umn"); + columns.add("abc"); + String sql = GsiTaskFactory.genAlterGlobalIndexDropColumnsSql(indexName, columns); + Assert.assertEquals(sql, + "/*+TDDL:CMD_EXTRA(DDL_ON_GSI=true)*/alter table `idx``Name` drop column `c``olumn`, drop column `c o l umn`, drop column `abc`"); + } + + @Test + public void testGenRenameLocalIndexTask() { + RenameLocalIndexPreparedData preparedData = new RenameLocalIndexPreparedData(); + preparedData.setTableName("t`b"); + preparedData.setOrgIndexName("idx`Name"); + preparedData.setNewIndexName("new`Index"); + SubJobTask subJobTask = (SubJobTask) LogicalDropIndexHandler.genRenameLocalIndexTask(preparedData); + Assert.assertEquals(subJobTask.getDdlStmt(), + "/*+TDDL:cmd_extra(DDL_ON_GSI=true)*/alter table `t``b` rename index `idx``Name` to `new``Index`"); + } + + @Test + public void testGenAddForeignKeySql() { + SqlDdl sqlNode = Mockito.mock(SqlDdl.class); + AlterTableRepartition alterTableRepartition = Mockito.mock(AlterTableRepartition.class); + when(alterTableRepartition.getCluster()).thenReturn(Mockito.mock(RelOptCluster.class)); + when(alterTableRepartition.getTraitSet()).thenReturn(Mockito.mock(RelTraitSet.class)); + when(alterTableRepartition.getSqlNode()).thenReturn(sqlNode); + when(sqlNode.toSqlString(Mockito.any())).thenReturn(new SqlString(Mockito.mock(SqlDialect.class), "123")); + when(alterTableRepartition.getRowType()).thenReturn(Mockito.mock(RelDataType.class)); + + Set foreignKeyDataList = new HashSet<>(); + ForeignKeyData foreignKeyData = new ForeignKeyData(); + foreignKeyData.setSchema("wumu"); + foreignKeyData.setTableName("t`b"); + foreignKeyData.setConstraint("c`onstraint"); + foreignKeyData.setIndexName("idx`Name"); + foreignKeyData.setColumns(new ArrayList<>()); + foreignKeyData.getColumns().add("c`olumn"); + foreignKeyData.setRefColumns(new ArrayList<>()); + foreignKeyData.getRefColumns().add("c`olumn"); + + foreignKeyDataList.add(foreignKeyData); + + List names = new ArrayList<>(); + names.add("wumu"); + names.add("t`b"); + try (MockedStatic optimizerContextMockedStatic = Mockito.mockStatic(OptimizerContext.class)) { + when(OptimizerContext.getContext(Mockito.anyString())).thenReturn(Mockito.mock(OptimizerContext.class)); + when(alterTableRepartition.getTableName()).thenReturn(new SqlIdentifier(names, SqlParserPos.ZERO)); + + LogicalAlterTableRepartition logicalAlterTableRepartition = + new LogicalAlterTableRepartition(alterTableRepartition); + + RepartitionPrepareData prepareData = new RepartitionPrepareData(); + + Class clazz = logicalAlterTableRepartition.getClass(); + Field secretField = clazz.getDeclaredField("repartitionPrepareData"); + secretField.setAccessible(true); + secretField.set(logicalAlterTableRepartition, prepareData); + + logicalAlterTableRepartition.genAddForeignKeySql(foreignKeyDataList); + Assert.assertEquals(prepareData.getAddForeignKeySql().get(0).getValue(), + "ALTER TABLE `wumu`.`t``b` DROP FOREIGN KEY `c``onstraint` /* partition_fk_sub_job */"); + + logicalAlterTableRepartition.genDropForeignKeySql(foreignKeyDataList); + Assert.assertEquals(prepareData.getDropForeignKeySql().get(0).getKey(), + "ALTER TABLE `wumu`.`t``b` DROP FOREIGN KEY `c``onstraint` /* partition_fk_sub_job */"); + + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + @Test + public void testGenChangeLocalIndexSql4OptimizeKey() { + SqlDdl sqlNode = Mockito.mock(SqlDdl.class); + AlterTableRepartition alterTableRepartition = Mockito.mock(AlterTableRepartition.class); + when(alterTableRepartition.getCluster()).thenReturn(Mockito.mock(RelOptCluster.class)); + when(alterTableRepartition.getTraitSet()).thenReturn(Mockito.mock(RelTraitSet.class)); + when(alterTableRepartition.getSqlNode()).thenReturn(sqlNode); + when(sqlNode.toSqlString(Mockito.any())).thenReturn(new SqlString(Mockito.mock(SqlDialect.class), "123")); + when(alterTableRepartition.getRowType()).thenReturn(Mockito.mock(RelDataType.class)); + + List names = new ArrayList<>(); + names.add("wumu"); + names.add("t`b"); + + String tableDef = "CREATE TABLE `t1_swuq_00000` (\n" + + "\t`a` int(11) DEFAULT NULL,\n" + + "\t`b` int(11) DEFAULT NULL,\n" + + "\t`_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT,\n" + + "\tPRIMARY KEY (`_drds_implicit_id_`),\n" + + "\tKEY `auto_shard_key_a` USING BTREE (`a`)\n" + + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4"; + + String tableDef2 = "CREATE TABLE tbl (\n" + + "\t`a` int(11) DEFAULT NULL,\n" + + "\t`b` int(11) DEFAULT NULL,\n" + + "\t`_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT,\n" + + "\tPRIMARY KEY (`_drds_implicit_id_`),\n" + + "\tINDEX `auto_shard_key_a_b` USING BTREE(`a`, `b`)\n" + + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4"; + + try (MockedStatic optimizerContextMockedStatic = Mockito.mockStatic(OptimizerContext.class)) { + when(OptimizerContext.getContext(Mockito.anyString())).thenReturn(Mockito.mock(OptimizerContext.class)); + when(alterTableRepartition.getTableName()).thenReturn(new SqlIdentifier(names, SqlParserPos.ZERO)); + + LogicalAlterTableRepartition logicalAlterTableRepartition = + new LogicalAlterTableRepartition(alterTableRepartition); + + RepartitionPrepareData prepareData = new RepartitionPrepareData(); + + Class clazz = logicalAlterTableRepartition.getClass(); + Field secretField = clazz.getDeclaredField("repartitionPrepareData"); + secretField.setAccessible(true); + secretField.set(logicalAlterTableRepartition, prepareData); + + logicalAlterTableRepartition.genDropIndexSql4OptimizeKey(tableDef); + Assert.assertEquals(prepareData.getDropLocalIndexSql().getKey(), + "alter table `wumu`.`t``b` drop index `auto_shard_key_a`;"); + + List newColumns = new ArrayList<>(); + newColumns.add("a"); + newColumns.add("b"); + + logicalAlterTableRepartition.genChangeLocalIndexSql4OptimizeKey(tableDef2, newColumns); + Assert.assertEquals(prepareData.getAddLocalIndexSql().getKey(), + "alter table `wumu`.`t``b` add index `auto_shard_key_a_b` USING BTREE (a,b);"); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/ColumnarAppendedFilesLoadTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/ColumnarAppendedFilesLoadTest.java index 141f526c2..0cf968a8b 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/ColumnarAppendedFilesLoadTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/ColumnarAppendedFilesLoadTest.java @@ -6,6 +6,7 @@ import org.junit.Test; import org.roaringbitmap.RoaringBitmap; +import java.util.Iterator; import java.util.List; import static com.alibaba.polardbx.executor.gms.FileVersionStorage.CSV_CHUNK_LIMIT; @@ -74,9 +75,48 @@ public void testCsvLoadWithRandomPurge() { public void testCsvDataWithoutCache() { for (MockAppendedFilesStatus status : CSV_STATUSES) { // Check for csv read bypass for columnar checksum - List chunkList = - fileVersionStorage.csvRawOrcTypeData(status.checkpointTso, CSV_FILE_NAME, new ExecutionContext()); - Assert.assertEquals(status.totalRows, chunkList.stream().mapToLong(Chunk::getPositionCount).sum()); + Iterator iterator = + MultiVersionCsvData.loadRawOrcTypeUntilTso(CSV_FILE_NAME, new ExecutionContext(), + 0, (int) (status.appendOffset + status.appendLength)); + long rowCount = 0; + while (iterator.hasNext()) { + Chunk chunk = iterator.next(); + rowCount += chunk.getPositionCount(); + } + Assert.assertEquals(status.totalRows, rowCount); + } + } + + @Test + public void testCsvDataWithoutCache2() { + for (MockAppendedFilesStatus status : CSV_STATUSES) { + // Check for csv read bypass for columnar checksum + Iterator iterator = + MultiVersionCsvData.loadSpecifiedCsvFile(CSV_FILE_NAME, new ExecutionContext(), + 0, (int) (status.appendOffset + status.appendLength)); + long rowCount = 0; + while (iterator.hasNext()) { + Chunk chunk = iterator.next(); + rowCount += chunk.getPositionCount(); + } + Assert.assertEquals(status.totalRows, rowCount); + } + + // For incremental check. + for (int i = 0; i < CSV_STATUSES.length - 1; i++) { + // Check for csv read bypass for columnar checksum + MockAppendedFilesStatus status0 = CSV_STATUSES[i]; + MockAppendedFilesStatus status1 = CSV_STATUSES[i + 1]; + Iterator iterator = + MultiVersionCsvData.loadSpecifiedCsvFile(CSV_FILE_NAME, new ExecutionContext(), + (int) status1.appendOffset, (int) (status1.appendOffset + status1.appendLength)); + + long rowCount = 0; + while (iterator.hasNext()) { + Chunk chunk = iterator.next(); + rowCount += chunk.getPositionCount(); + } + Assert.assertEquals(status1.totalRows - status0.totalRows, rowCount); } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/ColumnarManagerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/ColumnarManagerTest.java index c90f81922..7f164225b 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/ColumnarManagerTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/ColumnarManagerTest.java @@ -1,9 +1,13 @@ package com.alibaba.polardbx.executor.gms; import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.gms.util.ColumnarTransactionUtils; import com.alibaba.polardbx.executor.sync.ColumnarSnapshotUpdateSyncAction; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsRecord; import com.alibaba.polardbx.gms.metadb.table.FilesAccessor; import com.alibaba.polardbx.gms.metadb.table.FilesRecordSimplified; import com.alibaba.polardbx.gms.util.MetaDbUtil; @@ -18,34 +22,43 @@ import org.mockito.junit.MockitoJUnitRunner; import org.mockito.stubbing.Answer; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +import static org.mockito.ArgumentMatchers.anyLong; @RunWith(MockitoJUnitRunner.class) public class ColumnarManagerTest { private static final List MOCK_FILE_STATUSES = new ArrayList<>(Arrays.asList( - new MockFileStatus("1.csv", "p1", 1, 2), - new MockFileStatus("1.orc", "p1", 1, 2), - new MockFileStatus("1.del", "p1", 1, 2), - new MockFileStatus("2.csv", "p1", 2, 4), - new MockFileStatus("2.orc", "p1", 2, 4), - new MockFileStatus("2.del", "p1", 2, 4), - new MockFileStatus("3.csv", "p1", 3, 5), - new MockFileStatus("3.orc", "p1", 3, 5), - new MockFileStatus("3.del", "p1", 3, 5), - new MockFileStatus("4.csv", "p2", 1, 5), - new MockFileStatus("4.orc", "p2", 1, 5), - new MockFileStatus("4.del", "p2", 1, 5) + new MockFileStatus("1.csv", "p1", 1, 2, 1), + new MockFileStatus("1.orc", "p1", 1, 2, 1), + new MockFileStatus("1.del", "p1", 1, 2, 1), + new MockFileStatus("2.csv", "p1", 2, 4, 1), + new MockFileStatus("2.orc", "p1", 2, 4, 1), + new MockFileStatus("2.del", "p1", 2, 4, 1), + new MockFileStatus("3.csv", "p1", 3, 5, 1), + new MockFileStatus("3.orc", "p1", 3, 5, 1), + new MockFileStatus("3.del", "p1", 3, 5, 1), + new MockFileStatus("4.csv", "p2", 1, 5, 1), + new MockFileStatus("4.orc", "p2", 1, 5, 1), + new MockFileStatus("4.del", "p2", 1, 5, 1) )); private static final List MOCK_COMPACTION_STATUSES = Arrays.asList( - new MockFileStatus("5.csv", "p2", 2, 5), - new MockFileStatus("5.orc", "p2", 2, 5), - new MockFileStatus("5.del", "p2", 2, 5) + new MockFileStatus("5.csv", "p2", 2, 5, 1), + new MockFileStatus("5.orc", "p2", 2, 5, 1), + new MockFileStatus("5.del", "p2", 2, 5, 1) ); private MockedStatic mockMetaDbUtil; + private MockedStatic mockInstConfUtil; private MockedConstruction mockFilesAccessorCtor; final Answer> mockDeltaFilesQuery = invocationOnMock -> { @@ -67,6 +80,7 @@ public class ColumnarManagerTest { } filesRecordSimplified.fileName = fileStatus.fileName; filesRecordSimplified.partitionName = fileStatus.partitionName; + filesRecordSimplified.schemaTs = fileStatus.schemaTso; result.add(filesRecordSimplified); } @@ -80,8 +94,11 @@ public void prepareFileVersionStorage() { mockMetaDbUtil = Mockito.mockStatic(MetaDbUtil.class); mockMetaDbUtil.when(MetaDbUtil::getConnection).thenReturn(null); + mockInstConfUtil = Mockito.mockStatic(InstConfUtil.class); + mockInstConfUtil.when(() -> InstConfUtil.getInt(ConnectionParams.COLUMNAR_TSO_UPDATE_DELAY)).thenReturn(0); + mockFilesAccessorCtor = Mockito.mockConstruction(FilesAccessor.class, (mock, context) -> { - Mockito.when(mock.queryColumnarDeltaFilesByTsoAndTableId(Mockito.anyLong(), Mockito.anyLong(), + Mockito.when(mock.queryColumnarDeltaFilesByTsoAndTableId(anyLong(), anyLong(), Mockito.anyString(), Mockito.anyString())) .thenAnswer(mockDeltaFilesQuery); }); @@ -99,6 +116,9 @@ public void reloadColumnarManager() { if (mockFilesAccessorCtor != null) { mockFilesAccessorCtor.close(); } + if (mockInstConfUtil != null) { + mockInstConfUtil.close(); + } } @Test @@ -200,7 +220,7 @@ public void testPurgeWithMultiVersionSchema() { // Initialize columnar manager and set min/latest tso DynamicColumnarManager cm = (DynamicColumnarManager) ColumnarManager.getInstance(); - cm.injectForTest(mockFileVersionStorage, mockMultiVersionColumnarSchema); + cm.injectForTest(mockFileVersionStorage, mockMultiVersionColumnarSchema, new AtomicLong(0L), null); Assert.assertEquals(minTso, cm.getMinTso().longValue()); Assert.assertEquals(initTso, cm.latestTso()); @@ -257,7 +277,22 @@ public void testTsoBackward() { long queryTso1 = 4L; // Prepare mock data try (MockedStatic columnarTransactionUtilsMockedStatic = Mockito.mockStatic( - ColumnarTransactionUtils.class)) { + ColumnarTransactionUtils.class); + MockedConstruction checkpointsAccessorCtor = Mockito.mockConstruction( + ColumnarCheckpointsAccessor.class, (mock, context) -> { + Mockito.when(mock.queryValidCheckpointByTso(anyLong())) + .thenAnswer(invocation -> { + Long tso = invocation.getArgument(0); + ColumnarCheckpointsRecord record = new ColumnarCheckpointsRecord(); + if (3L == tso) { + record.minCompactionTso = 2; + } else { + record.minCompactionTso = 0; + } + return Collections.singletonList(record); + }); + } + )) { columnarTransactionUtilsMockedStatic.when(ColumnarTransactionUtils::getLatestTsoFromGms) .thenReturn(initTso); columnarTransactionUtilsMockedStatic.when(ColumnarTransactionUtils::getMinColumnarSnapshotTime) @@ -269,7 +304,7 @@ public void testTsoBackward() { // Initialize columnar manager and set min/latest tso DynamicColumnarManager cm = (DynamicColumnarManager) ColumnarManager.getInstance(); - cm.injectForTest(mockFileVersionStorage, mockMultiVersionColumnarSchema); + cm.injectForTest(mockFileVersionStorage, mockMultiVersionColumnarSchema, new AtomicLong(0), null); Assert.assertEquals(minTso, cm.getMinTso().longValue()); Assert.assertEquals(initTso, cm.latestTso()); @@ -289,6 +324,10 @@ public void testTsoBackward() { Assert.assertEquals(queryTso1, cm.latestTso()); orcAndCsvFile = cm.findFileNames(initTso, "db1", "t1", "p2"); + Assert.assertEquals(1, orcAndCsvFile.getKey().size()); + Assert.assertEquals(1, orcAndCsvFile.getValue().size()); + + orcAndCsvFile = cm.findFileNames(queryTso1, "db1", "t1", "p2"); Assert.assertEquals(2, orcAndCsvFile.getKey().size()); Assert.assertEquals(2, orcAndCsvFile.getValue().size()); @@ -298,17 +337,37 @@ public void testTsoBackward() { } } + @Test + public void testGetTsoWithDelayMinValue() throws SQLException { + mockInstConfUtil.when(() -> InstConfUtil.getInt(ConnectionParams.COLUMNAR_TSO_UPDATE_DELAY)).thenReturn(1000); + Connection mockConnection = Mockito.mock(Connection.class); + mockMetaDbUtil.when(MetaDbUtil::getConnection).thenReturn(mockConnection); + PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class); + Mockito.when(mockConnection.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement); + ResultSet mockResultSet = Mockito.mock(ResultSet.class); + Mockito.when(mockPreparedStatement.executeQuery()).thenReturn(mockResultSet); + Assert.assertEquals(Long.MIN_VALUE, ColumnarManager.getInstance().latestTso()); + + ColumnarManager.getInstance().reload(); + + Mockito.when(mockResultSet.next()).thenReturn(true); + Mockito.when(mockResultSet.getLong("checkpoint_tso")).thenReturn(1L); + Assert.assertEquals(1L, ColumnarManager.getInstance().latestTso()); + } + static class MockFileStatus { String fileName; String partitionName; long commitTso; long removeTso; + long schemaTso; - MockFileStatus(String fileName, String partitionName, long commitTso, long removeTso) { + MockFileStatus(String fileName, String partitionName, long commitTso, long removeTso, long schemaTso) { this.fileName = fileName; this.partitionName = partitionName; this.commitTso = commitTso; this.removeTso = removeTso; + this.schemaTso = schemaTso; } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/FileVersionStorageTestBase.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/FileVersionStorageTestBase.java index d8851eae3..9452173e2 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/FileVersionStorageTestBase.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/FileVersionStorageTestBase.java @@ -2,9 +2,11 @@ import com.alibaba.polardbx.common.Engine; import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.gms.engine.FileSystemManager; import com.alibaba.polardbx.gms.engine.FileSystemUtils; import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarFileMappingAccessor; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.config.table.Field; @@ -12,6 +14,7 @@ import org.apache.calcite.sql.type.SqlTypeName; import org.apache.commons.io.IOUtils; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Seekable; @@ -47,17 +50,19 @@ public abstract class FileVersionStorageTestBase { protected final static Random R = new Random(); protected final static String CSV_FILE_NAME = "6659a663977d.csv"; protected final static int FIRST_CSV_PART_OVER_1000 = 40; - private final static int CSV_FILE_ID = 10; - private final static String DEL_FILE_NAME = "fb2604e133e6.del"; - protected final static FileMeta FILE_META; - private static FileSystem FILESYSTEM; + protected final static int CSV_FILE_ID = 10; + protected final static String DEL_FILE_NAME = "fb2604e133e6.del"; + public final static FileMeta FILE_META; + protected static FileSystem FILESYSTEM; protected FileVersionStorage fileVersionStorage; - private MockedConstruction mockCafCtor; - private MockedStatic mockCm; - private MockedStatic mockFsUtils; - private MockedStatic mockMetaDbUtil; + protected MockedConstruction mockCafCtor; + protected MockedConstruction mockCfmCtor; + protected MockedStatic mockCm; + protected MockedStatic mockFsUtils; + protected MockedStatic mockMetaDbUtil; + protected MockedStatic mockFsManager; - final Answer mockFileReadAnswer = invocation -> { + protected final Answer mockFileReadAnswer = invocation -> { Object[] args = invocation.getArguments(); String fileName = (String) args[0]; int offset = (Integer) args[1]; @@ -68,6 +73,13 @@ public abstract class FileVersionStorageTestBase { return null; }; + protected final Answer mockOpenFileAnswer = invocation -> { + Object[] args = invocation.getArguments(); + String fileName = (String) args[0]; + + return openMockFile(fileName); + }; + public static final MockAppendedFilesStatus[] CSV_STATUSES = { new MockAppendedFilesStatus(7182618497799684160L, 0, 1775, 25), new MockAppendedFilesStatus(7182618502824460352L, 1775, 1775, 50), @@ -254,6 +266,13 @@ public void prepareFileVersionStorage() { ).thenAnswer( mockFileReadAnswer ); + mockFsUtils.when( + () -> FileSystemUtils.openStreamFileWithBuffer( + anyString(), any(Engine.class), anyBoolean() + ) + ).thenAnswer( + mockOpenFileAnswer + ); mockMetaDbUtil = Mockito.mockStatic(MetaDbUtil.class); mockMetaDbUtil.when(MetaDbUtil::getConnection).thenReturn(null); @@ -366,13 +385,19 @@ public void clearFileVersionStorage() { if (mockCafCtor != null) { mockCafCtor.close(); } + if (mockFsManager != null) { + mockFsManager.close(); + } + if (mockCfmCtor != null) { + mockCfmCtor.close(); + } } - static class MockAppendedFilesStatus { - long checkpointTso; - long appendOffset; - long appendLength; - long totalRows; + public static class MockAppendedFilesStatus { + public long checkpointTso; + public long appendOffset; + public long appendLength; + public long totalRows; public MockAppendedFilesStatus(long checkpointTso, long appendOffset, long appendLength, long totalRows) { this.checkpointTso = checkpointTso; @@ -394,7 +419,7 @@ public ColumnarAppendedFilesRecord toAppendedFilesRecord(String fileName) { } } - private static void readMockFile(String fileName, int offset, int length, byte[] output) { + public static void readMockFile(String fileName, int offset, int length, byte[] output) { try (InputStream in = FILESYSTEM.open(new Path(ClassLoader.getSystemResource(fileName).getPath()))) { ((Seekable) in).seek(offset); IOUtils.read(in, output, 0, length); @@ -402,4 +427,12 @@ private static void readMockFile(String fileName, int offset, int length, byte[] throw GeneralUtil.nestedException(e); } } + + public static FSDataInputStream openMockFile(String fileName) { + try { + return FILESYSTEM.open(new Path(ClassLoader.getSystemResource(fileName).getPath())); + } catch (IOException e) { + throw GeneralUtil.nestedException(e); + } + } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/FlashbackDeleteBitmapManagerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/FlashbackDeleteBitmapManagerTest.java new file mode 100644 index 000000000..215cfd09e --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/FlashbackDeleteBitmapManagerTest.java @@ -0,0 +1,41 @@ +package com.alibaba.polardbx.executor.gms; + +import org.junit.Test; + +import java.util.Collections; + +import static org.junit.Assert.*; + +public class FlashbackDeleteBitmapManagerTest { + + @Test + public void testWeakReferenceGC() { + FlashbackDeleteBitmapManager manager = + FlashbackDeleteBitmapManager.getInstance(1L, "test_schema", "test_table", "p0", Collections.emptyList()); + assertNotNull(manager); + assertEquals(1, FlashbackDeleteBitmapManager.MANAGER_MAP.size()); + + manager = null; + + // before GC + assertEquals(1, FlashbackDeleteBitmapManager.MANAGER_MAP.size()); + + System.gc(); + int i = 60; + int referenceCount = 1; + while (i-- > 0) { + referenceCount = FlashbackDeleteBitmapManager.MANAGER_MAP.size(); + if (referenceCount == 0) { + break; + } + try { + Thread.sleep(100); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // after GC + assertEquals(0, referenceCount); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSchemaTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSchemaTest.java index 1bdfb5113..de0dada4a 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSchemaTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/MultiVersionColumnarSchemaTest.java @@ -3,15 +3,36 @@ import com.alibaba.polardbx.common.exception.NotSupportException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.executor.archive.schemaevolution.ColumnMetaWithTs; +import com.alibaba.polardbx.executor.operator.scan.ScanPreProcessor; +import com.alibaba.polardbx.executor.operator.scan.impl.DefaultScanPreProcessor; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.metadb.table.ColumnarColumnEvolutionAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarColumnEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.tablegroup.PartitionGroupAccessor; +import com.alibaba.polardbx.gms.tablegroup.PartitionGroupRecord; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; +import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.statis.ColumnarTracer; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.ListenableFuture; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexInputRef; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.hadoop.fs.Path; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.MockedConstruction; @@ -20,15 +41,28 @@ import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; +import java.sql.Connection; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.SortedMap; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import static com.alibaba.polardbx.common.properties.ConnectionParams.ZONEMAP_MAX_GROUP_SIZE; +import static com.alibaba.polardbx.executor.gms.FileVersionStorageTestBase.FILESYSTEM; +import static com.alibaba.polardbx.executor.gms.FileVersionStorageTestBase.prepareFileSystem; +import static com.alibaba.polardbx.executor.operator.scan.ScanTestBase.getFileFromClasspath; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class MultiVersionColumnarSchemaTest { private MultiVersionColumnarSchema multiVersionColumnarSchema; @@ -37,6 +71,8 @@ public class MultiVersionColumnarSchemaTest { private MockedConstruction tableEvolutionAccessorMockedConstruction; private MockedConstruction columnEvolutionAccessorMockedConstruction; private MockedConstruction tableMappingAccessorMockedConstruction; + private MockedConstruction partitionEvolutionAccessorMockedConstruction; + private MockedConstruction partitionGroupAccessorMockedConstruction; private static final Long TABLE_ID = 1L; private static final int DDL_ROUND_COUNT = 15; @@ -44,237 +80,263 @@ public class MultiVersionColumnarSchemaTest { private static final ColumnarTableEvolutionRecord[] TABLE_EVOLUTION_RECORDS = { new ColumnarTableEvolutionRecord(7193543211267129408L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", - null, 1724608426958393344L, "CREATE_INDEX", 7193543213288783936L, Arrays.asList(1L, 2L, 3L, 4L)), + null, 1724608426958393344L, "CREATE_INDEX", 7193543213288783936L, Arrays.asList(1L, 2L, 3L, 4L), + Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543479677419648L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608695356104704L, "ALTER_TABLE_ADD_COLUMN", 7193543481715851328L, - Arrays.asList(1L, 2L, 3L, 4L, 5L)), + Arrays.asList(1L, 2L, 3L, 4L, 5L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543486010818688L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608701685309440L, "ALTER_TABLE_ADD_COLUMN", 7193543488070221888L, - Arrays.asList(6L, 7L, 8L, 9L, 10L, 11L)), + Arrays.asList(6L, 7L, 8L, 9L, 10L, 11L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543493531205696L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608709188919296L, "ALTER_TABLE_ADD_COLUMN", 7193543495498334272L, - Arrays.asList(6L, 12L, 13L, 14L, 15L, 16L, 17L)), + Arrays.asList(6L, 12L, 13L, 14L, 15L, 16L, 17L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543500346949760L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608716004663296L, "ALTER_TABLE_DROP_COLUMN", 7193543504839049280L, - Arrays.asList(6L, 12L, 13L, 14L, 15L, 16L)), + Arrays.asList(6L, 12L, 13L, 14L, 15L, 16L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543510081929280L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608725844500480L, "ALTER_TABLE_DROP_COLUMN", 7193543513747751040L, - Arrays.asList(20L, 21L, 22L, 23L, 24L)), + Arrays.asList(20L, 21L, 22L, 23L, 24L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543518810275968L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608734459600896L, "ALTER_TABLE_MODIFY_COLUMN", 7193543520727072896L, - Arrays.asList(20L, 21L, 25L, 26L, 27L)), + Arrays.asList(20L, 21L, 25L, 26L, 27L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543524187373632L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608739840892928L, "ALTER_TABLE_MODIFY_COLUMN", 7193543525730877504L, - Arrays.asList(20L, 21L, 28L, 29L, 30L)), + Arrays.asList(20L, 21L, 28L, 29L, 30L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543530847928512L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608746514030592L, "ALTER_TABLE_MODIFY_COLUMN", 7193543532404015168L, - Arrays.asList(31L, 32L, 33L, 34L, 35L)), + Arrays.asList(31L, 32L, 33L, 34L, 35L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543535960785024L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608751610109952L, "ALTER_TABLE_MODIFY_COLUMN", 7193543537814667328L, - Arrays.asList(36L, 37L, 38L, 39L, 40L)), + Arrays.asList(36L, 37L, 38L, 39L, 40L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543542566813760L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608758224527360L, "ALTER_TABLE_CHANGE_COLUMN", 7193543544571691072L, - Arrays.asList(41L, 42L, 43L, 44L, 45L)), + Arrays.asList(41L, 42L, 43L, 44L, 45L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543547780333632L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608763429658624L, "ALTER_TABLE_CHANGE_COLUMN", 7193543549244145728L, - Arrays.asList(46L, 47L, 48L, 49L, 50L)), + Arrays.asList(46L, 47L, 48L, 49L, 50L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543553971126336L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608769637228544L, "ALTER_TABLE_ADD_COLUMN", 7193543555581739072L, - Arrays.asList(46L, 47L, 48L, 49L, 50L, 51L)), + Arrays.asList(46L, 47L, 48L, 49L, 50L, 51L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543559344029760L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608774997549056L, "ALTER_TABLE_DROP_COLUMN", 7193543563106320448L, - Arrays.asList(46L, 53L, 54L, 55L, 56L)), + Arrays.asList(46L, 53L, 54L, 55L, 56L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543569020289088L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608784665419776L, "ALTER_TABLE_DROP_COLUMN", 7193543573315256384L, - Arrays.asList(46L, 53L, 54L, 55L)), + Arrays.asList(46L, 53L, 54L, 55L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543578759462976L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608794408787968L, "ALTER_TABLE_MODIFY_COLUMN", 7193543580323938560L, - Arrays.asList(46L, 58L, 59L, 60L)), + Arrays.asList(46L, 58L, 59L, 60L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543583968788544L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608799722971136L, "ALTER_TABLE_ADD_COLUMN", 7193543585772339264L, - Arrays.asList(46L, 58L, 59L, 60L, 61L)), + Arrays.asList(46L, 58L, 59L, 60L, 61L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543589274583104L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608804953268224L, "ALTER_TABLE_ADD_COLUMN", 7193543590679675008L, - Arrays.asList(62L, 63L, 64L, 65L, 66L, 67L)), + Arrays.asList(62L, 63L, 64L, 65L, 66L, 67L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543593737322688L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608809399230464L, "ALTER_TABLE_ADD_COLUMN", 7193543595851251776L, - Arrays.asList(62L, 68L, 69L, 70L, 71L, 72L, 73L)), + Arrays.asList(62L, 68L, 69L, 70L, 71L, 72L, 73L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543599181529216L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608814826659840L, "ALTER_TABLE_DROP_COLUMN", 7193543602138513472L, - Arrays.asList(62L, 68L, 69L, 70L, 71L, 72L)), + Arrays.asList(62L, 68L, 69L, 70L, 71L, 72L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543605280047168L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608820925177856L, "ALTER_TABLE_DROP_COLUMN", 7193543608513855552L, - Arrays.asList(76L, 77L, 78L, 79L, 80L)), + Arrays.asList(76L, 77L, 78L, 79L, 80L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543611466645568L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608827115970560L, "ALTER_TABLE_MODIFY_COLUMN", 7193543613047898176L, - Arrays.asList(76L, 77L, 81L, 82L, 83L)), + Arrays.asList(76L, 77L, 81L, 82L, 83L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543616805994560L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608832455319552L, "ALTER_TABLE_MODIFY_COLUMN", 7193543618370470016L, - Arrays.asList(76L, 77L, 84L, 85L, 86L)), + Arrays.asList(76L, 77L, 84L, 85L, 86L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543622447333504L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608838084075520L, "ALTER_TABLE_MODIFY_COLUMN", 7193543624234106944L, - Arrays.asList(87L, 88L, 89L, 90L, 91L)), + Arrays.asList(87L, 88L, 89L, 90L, 91L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543627287560320L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608842928496640L, "ALTER_TABLE_MODIFY_COLUMN", 7193543643221721152L, - Arrays.asList(92L, 93L, 94L, 95L, 96L)), + Arrays.asList(92L, 93L, 94L, 95L, 96L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543645553754176L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608861198884864L, "ALTER_TABLE_CHANGE_COLUMN", 7193543646430363712L, - Arrays.asList(97L, 98L, 99L, 100L, 101L)), + Arrays.asList(97L, 98L, 99L, 100L, 101L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543648217137216L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608863866462208L, "ALTER_TABLE_CHANGE_COLUMN", 7193543649295073344L, - Arrays.asList(102L, 103L, 104L, 105L, 106L)), + Arrays.asList(102L, 103L, 104L, 105L, 106L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543650888908864L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608866550816768L, "ALTER_TABLE_ADD_COLUMN", 7193543651815850048L, - Arrays.asList(102L, 103L, 104L, 105L, 106L, 107L)), + Arrays.asList(102L, 103L, 104L, 105L, 106L, 107L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543653569069120L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608869222588416L, "ALTER_TABLE_DROP_COLUMN", 7193543655351648320L, - Arrays.asList(102L, 109L, 110L, 111L, 112L)), + Arrays.asList(102L, 109L, 110L, 111L, 112L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543656660271168L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608872305401856L, "ALTER_TABLE_DROP_COLUMN", 7193543658417684544L, - Arrays.asList(102L, 109L, 110L, 111L)), + Arrays.asList(102L, 109L, 110L, 111L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543660166709312L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608875816034304L, "ALTER_TABLE_MODIFY_COLUMN", 7193543661244645440L, - Arrays.asList(102L, 114L, 115L, 116L)), + Arrays.asList(102L, 114L, 115L, 116L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543662834286656L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608878487805952L, "ALTER_TABLE_ADD_COLUMN", 7193543663752839232L, - Arrays.asList(102L, 114L, 115L, 116L, 117L)), + Arrays.asList(102L, 114L, 115L, 116L, 117L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543665086627904L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608880744341504L, "ALTER_TABLE_ADD_COLUMN", 7193543666227478592L, - Arrays.asList(118L, 119L, 120L, 121L, 122L, 123L)), + Arrays.asList(118L, 119L, 120L, 121L, 122L, 123L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543667762593856L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608883416113152L, "ALTER_TABLE_ADD_COLUMN", 7193543668916027456L, - Arrays.asList(118L, 124L, 125L, 126L, 127L, 128L, 129L)), + Arrays.asList(118L, 124L, 125L, 126L, 127L, 128L, 129L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543670430171200L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608886079496192L, "ALTER_TABLE_DROP_COLUMN", 7193543672191778880L, - Arrays.asList(118L, 124L, 125L, 126L, 127L, 128L)), + Arrays.asList(118L, 124L, 125L, 126L, 127L, 128L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543673936609344L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608889585934336L, "ALTER_TABLE_DROP_COLUMN", 7193543675698217024L, - Arrays.asList(132L, 133L, 134L, 135L, 136L)), + Arrays.asList(132L, 133L, 134L, 135L, 136L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543677023617088L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608892664553472L, "ALTER_TABLE_MODIFY_COLUMN", 7193543678097358912L, - Arrays.asList(132L, 133L, 137L, 138L, 139L)), + Arrays.asList(132L, 133L, 137L, 138L, 139L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543679687000128L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608895336325120L, "ALTER_TABLE_MODIFY_COLUMN", 7193543680764936256L, - Arrays.asList(132L, 133L, 140L, 141L, 142L)), + Arrays.asList(132L, 133L, 140L, 141L, 142L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543682354577472L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608897995513856L, "ALTER_TABLE_MODIFY_COLUMN", 7193543683424124992L, - Arrays.asList(143L, 144L, 145L, 146L, 147L)), + Arrays.asList(143L, 144L, 145L, 146L, 147L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543685017960512L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608900663091200L, "ALTER_TABLE_MODIFY_COLUMN", 7193543686091702336L, - Arrays.asList(148L, 149L, 150L, 151L, 152L)), + Arrays.asList(148L, 149L, 150L, 151L, 152L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543687677149248L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608903322279936L, "ALTER_TABLE_CHANGE_COLUMN", 7193543688536981568L, - Arrays.asList(153L, 154L, 155L, 156L, 157L)), + Arrays.asList(153L, 154L, 155L, 156L, 157L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543690336337984L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608905989857280L, "ALTER_TABLE_CHANGE_COLUMN", 7193543691418468416L, - Arrays.asList(158L, 159L, 160L, 161L, 162L)), + Arrays.asList(158L, 159L, 160L, 161L, 162L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543693008109632L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608908661628928L, "ALTER_TABLE_ADD_COLUMN", 7193543693922467904L, - Arrays.asList(158L, 159L, 160L, 161L, 162L, 163L)), + Arrays.asList(158L, 159L, 160L, 161L, 162L, 163L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543695675686976L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608911320817664L, "ALTER_TABLE_DROP_COLUMN", 7193543697441488960L, - Arrays.asList(158L, 165L, 166L, 167L, 168L)), + Arrays.asList(158L, 165L, 166L, 167L, 168L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543699177930816L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608914823061504L, "ALTER_TABLE_DROP_COLUMN", 7193543700931149888L, - Arrays.asList(158L, 165L, 166L, 167L)), + Arrays.asList(158L, 165L, 166L, 167L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543702260744256L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608917905874944L, "ALTER_TABLE_MODIFY_COLUMN", 7193543703330291776L, - Arrays.asList(158L, 170L, 171L, 172L)), + Arrays.asList(158L, 170L, 171L, 172L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543704919932992L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608920590229504L, "ALTER_TABLE_ADD_COLUMN", 7193543705846874176L, - Arrays.asList(158L, 170L, 171L, 172L, 173L)), + Arrays.asList(158L, 170L, 171L, 172L, 173L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543707604287552L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608923266195456L, "ALTER_TABLE_ADD_COLUMN", 7193543708736749632L, - Arrays.asList(174L, 175L, 176L, 177L, 178L, 179L)), + Arrays.asList(174L, 175L, 176L, 177L, 178L, 179L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543710284447808L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608925946355712L, "ALTER_TABLE_ADD_COLUMN", 7193543711416909888L, - Arrays.asList(174L, 180L, 181L, 182L, 183L, 184L, 185L)), + Arrays.asList(174L, 180L, 181L, 182L, 183L, 184L, 185L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543712964608064L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608928601350144L, "ALTER_TABLE_DROP_COLUMN", 7193543714709438528L, - Arrays.asList(174L, 180L, 181L, 182L, 183L, 184L)), + Arrays.asList(174L, 180L, 181L, 182L, 183L, 184L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543716454268992L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608932086816768L, "ALTER_TABLE_DROP_COLUMN", 7193543718194905152L, - Arrays.asList(188L, 189L, 190L, 191L, 192L)), + Arrays.asList(188L, 189L, 190L, 191L, 192L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543719939735616L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608935589060608L, "ALTER_TABLE_MODIFY_COLUMN", 7193543721013477440L, - Arrays.asList(188L, 189L, 193L, 194L, 195L)), + Arrays.asList(188L, 189L, 193L, 194L, 195L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543722607312960L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608938248249344L, "ALTER_TABLE_MODIFY_COLUMN", 7193543723681054784L, - Arrays.asList(188L, 189L, 196L, 197L, 198L)), + Arrays.asList(188L, 189L, 196L, 197L, 198L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543725681737792L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608941326868480L, "ALTER_TABLE_MODIFY_COLUMN", 7193543726742896704L, - Arrays.asList(199L, 200L, 201L, 202L, 203L)), + Arrays.asList(199L, 200L, 201L, 202L, 203L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543728336732224L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608943977668608L, "ALTER_TABLE_MODIFY_COLUMN", 7193543729397891136L, - Arrays.asList(204L, 205L, 206L, 207L, 208L)), + Arrays.asList(204L, 205L, 206L, 207L, 208L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543730991726656L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608946645245952L, "ALTER_TABLE_CHANGE_COLUMN", 7193543731859947584L, - Arrays.asList(209L, 210L, 211L, 212L, 213L)), + Arrays.asList(209L, 210L, 211L, 212L, 213L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543733667692608L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608949312823296L, "ALTER_TABLE_CHANGE_COLUMN", 7193543734728851520L, - Arrays.asList(214L, 215L, 216L, 217L, 218L)), + Arrays.asList(214L, 215L, 216L, 217L, 218L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543736326881344L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608951980400640L, "ALTER_TABLE_ADD_COLUMN", 7193543737237045312L, - Arrays.asList(214L, 215L, 216L, 217L, 218L, 219L)), + Arrays.asList(214L, 215L, 216L, 217L, 218L, 219L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543739002847296L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608954647977984L, "ALTER_TABLE_DROP_COLUMN", 7193543740764454976L, - Arrays.asList(214L, 221L, 222L, 223L, 224L)), + Arrays.asList(214L, 221L, 222L, 223L, 224L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543742509285440L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608958154416128L, "ALTER_TABLE_DROP_COLUMN", 7193543744262504512L, - Arrays.asList(214L, 221L, 222L, 223L)), + Arrays.asList(214L, 221L, 222L, 223L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543746003140672L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608961648271360L, "ALTER_TABLE_MODIFY_COLUMN", 7193543747076882496L, - Arrays.asList(214L, 226L, 227L, 228L)), + Arrays.asList(214L, 226L, 227L, 228L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543748666523712L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608964320043008L, "ALTER_TABLE_ADD_COLUMN", 7193543749576687680L, - Arrays.asList(214L, 226L, 227L, 228L, 229L)), + Arrays.asList(214L, 226L, 227L, 228L, 229L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543751338295360L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608966996008960L, "ALTER_TABLE_ADD_COLUMN", 7193543752474951744L, - Arrays.asList(230L, 231L, 232L, 233L, 234L, 235L)), + Arrays.asList(230L, 231L, 232L, 233L, 234L, 235L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543754010067008L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608969671974912L, "ALTER_TABLE_ADD_COLUMN", 7193543755150917696L, - Arrays.asList(230L, 236L, 237L, 238L, 239L, 240L, 241L)), + Arrays.asList(230L, 236L, 237L, 238L, 239L, 240L, 241L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543756694421568L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608972343746560L, "ALTER_TABLE_DROP_COLUMN", 7193543758451834944L, - Arrays.asList(230L, 236L, 237L, 238L, 239L, 240L)), + Arrays.asList(230L, 236L, 237L, 238L, 239L, 240L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543760205054016L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608975837601792L, "ALTER_TABLE_DROP_COLUMN", 7193543761937301568L, - Arrays.asList(244L, 245L, 246L, 247L, 248L)), + Arrays.asList(244L, 245L, 246L, 247L, 248L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543763694714944L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608979339845632L, "ALTER_TABLE_MODIFY_COLUMN", 7193543764764262464L, - Arrays.asList(244L, 245L, 249L, 250L, 251L)), + Arrays.asList(244L, 245L, 249L, 250L, 251L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543766349709376L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608981994840064L, "ALTER_TABLE_MODIFY_COLUMN", 7193543767419256896L, - Arrays.asList(244L, 245L, 252L, 253L, 254L)), + Arrays.asList(244L, 245L, 252L, 253L, 254L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543769013092416L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608984649834496L, "ALTER_TABLE_MODIFY_COLUMN", 7193543770074251328L, - Arrays.asList(255L, 256L, 257L, 258L, 259L)), + Arrays.asList(255L, 256L, 257L, 258L, 259L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543771668086848L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608987329994752L, "ALTER_TABLE_MODIFY_COLUMN", 7193543772758605888L, - Arrays.asList(260L, 261L, 262L, 263L, 264L)), + Arrays.asList(260L, 261L, 262L, 263L, 264L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543774344052800L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608989989183488L, "ALTER_TABLE_CHANGE_COLUMN", 7193543775199690816L, - Arrays.asList(265L, 266L, 267L, 268L, 269L)), + Arrays.asList(265L, 266L, 267L, 268L, 269L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543777003241536L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608992648372224L, "ALTER_TABLE_CHANGE_COLUMN", 7193543778076983360L, - Arrays.asList(270L, 271L, 272L, 273L, 274L)), + Arrays.asList(270L, 271L, 272L, 273L, 274L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543779666624576L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608995336921088L, "ALTER_TABLE_ADD_COLUMN", 7193543780610342976L, - Arrays.asList(270L, 271L, 272L, 273L, 274L, 275L)), + Arrays.asList(270L, 271L, 272L, 273L, 274L, 275L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543781931548736L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724608997580873728L, "ALTER_TABLE_DROP_COLUMN", 7193543783688962112L, - Arrays.asList(270L, 277L, 278L, 279L, 280L)), + Arrays.asList(270L, 277L, 278L, 279L, 280L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543785429598272L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724609001074728960L, "ALTER_TABLE_DROP_COLUMN", 7193543787195400256L, - Arrays.asList(270L, 277L, 278L, 279L)), + Arrays.asList(270L, 277L, 278L, 279L), Arrays.asList(1L, 2L, 3L, 4L)), new ColumnarTableEvolutionRecord(7193543788931842112L, 1L, "transfer", "accounts", "accounts_col_index_$c9a1", null, 1724609004572778496L, "ALTER_TABLE_MODIFY_COLUMN", 7193543789993001024L, - Arrays.asList(270L, 282L, 283L, 284L)), + Arrays.asList(270L, 282L, 283L, 284L), Arrays.asList(1L, 2L, 3L, 4L)), }; private static final ColumnarColumnEvolutionRecord[] COLUMN_EVOLUTION_RECORDS; + private static final ColumnarPartitionEvolutionRecord[] COLUMNAR_PARTITION_EVOLUTION_RECORDS = { + new ColumnarPartitionEvolutionRecord(1L, 1L, "", 7193543211267129408L, 1724608426958393344L, + ColumnarPartitionEvolutionRecord.deserializeFromJson( + "{\"groupId\": 10, \"tblType\": 7, \"autoFlag\": 0, \"parentId\": -1, \"partDesc\": \"\", \"partExpr\": \"\", \"partName\": \"\", \"phyTable\": \"\", \"nextLevel\": 1, \"partFlags\": 0, \"partLevel\": 0, \"tableName\": \"accounts_col_index_$c9a1\", \"partEngine\": \"\", \"partExtras\": \"{\\\"charset\\\":\\\"utf8\\\",\\\"locality\\\":\\\"\\\",\\\"partitionPattern\\\":\\\"accounts_col_index_$c9a1_2zTE\\\",\\\"timeZone\\\":\\\"SYSTEM\\\"}\", \"partMethod\": \"\", \"partStatus\": 1, \"spTempFlag\": -1, \"metaVersion\": 1, \"partComment\": \"\", \"tableSchema\": \"transfer\", \"partPosition\": -1, \"partTempName\": \"\"}"), + 1), + new ColumnarPartitionEvolutionRecord(1L, 2L, "p0", 7193543211267129408L, 1724608426958393344L, + ColumnarPartitionEvolutionRecord.deserializeFromJson( + "{\"groupId\": 29, \"tblType\": 7, \"autoFlag\": 0, \"parentId\": 44, \"partDesc\": \"10000\", \"partExpr\": \"`id`\", \"partName\": \"p0\", \"phyTable\": \"accounts_col_index_$c9a1_2zTE_00000\", \"nextLevel\": -1, \"partFlags\": 0, \"partLevel\": 1, \"tableName\": \"accounts_col_index_$c9a1\", \"partEngine\": \"Columnar\", \"partExtras\": \"{\\\"locality\\\":\\\"\\\"}\", \"partMethod\": \"RANGE\", \"partStatus\": 0, \"spTempFlag\": -1, \"metaVersion\": 1, \"partComment\": \"\", \"tableSchema\": \"transfer\", \"partPosition\": 1, \"partTempName\": \"\"}"), + 1), + new ColumnarPartitionEvolutionRecord(1L, 3L, "p1", 7193543211267129408L, 1724608426958393344L, + ColumnarPartitionEvolutionRecord.deserializeFromJson( + "{\"groupId\": 30, \"tblType\": 7, \"autoFlag\": 0, \"parentId\": 44, \"partDesc\": \"20000\", \"partExpr\": \"`id`\", \"partName\": \"p1\", \"phyTable\": \"accounts_col_index_$c9a1_2zTE_00001\", \"nextLevel\": -1, \"partFlags\": 0, \"partLevel\": 1, \"tableName\": \"accounts_col_index_$c9a1\", \"partEngine\": \"Columnar\", \"partExtras\": \"{\\\"locality\\\":\\\"\\\"}\", \"partMethod\": \"RANGE\", \"partStatus\": 0, \"spTempFlag\": -1, \"metaVersion\": 1, \"partComment\": \"\", \"tableSchema\": \"transfer\", \"partPosition\": 2, \"partTempName\": \"\"}"), + 1), + new ColumnarPartitionEvolutionRecord(1L, 4L, "p2", 7193543211267129408L, 1724608426958393344L, + ColumnarPartitionEvolutionRecord.deserializeFromJson( + "{\"groupId\": 31, \"tblType\": 7, \"autoFlag\": 0, \"parentId\": 44, \"partDesc\": \"30000\", \"partExpr\": \"`id`\", \"partName\": \"p2\", \"phyTable\": \"accounts_col_index_$c9a1_2zTE_00002\", \"nextLevel\": -1, \"partFlags\": 0, \"partLevel\": 1, \"tableName\": \"accounts_col_index_$c9a1\", \"partEngine\": \"Columnar\", \"partExtras\": \"{\\\"locality\\\":\\\"\\\"}\", \"partMethod\": \"RANGE\", \"partStatus\": 0, \"spTempFlag\": -1, \"metaVersion\": 1, \"partComment\": \"\", \"tableSchema\": \"transfer\", \"partPosition\": 3, \"partTempName\": \"\"}"), + 1), + }; + + public static final PartitionGroupRecord[] PARTITION_GROUP_RECORDS = { + new PartitionGroupRecord(), + new PartitionGroupRecord(), + new PartitionGroupRecord(), + }; + static { Yaml yaml = new Yaml(new Constructor((List.class))); List> recordObjectList = @@ -296,29 +358,30 @@ public class MultiVersionColumnarSchemaTest { for (int i = 0; i < COLUMN_EVOLUTION_RECORDS.length; i++) { COLUMN_EVOLUTION_RECORDS[i].id = i + 1; } + + for (int i = 0; i < COLUMNAR_PARTITION_EVOLUTION_RECORDS.length; i++) { + COLUMNAR_PARTITION_EVOLUTION_RECORDS[i].id = i + 1; + } } @Before public void setUp() { mockMetaDbUtil = Mockito.mockStatic(MetaDbUtil.class); - mockMetaDbUtil.when(MetaDbUtil::getConnection).thenReturn(null); + mockMetaDbUtil.when(MetaDbUtil::getConnection).thenReturn(Mockito.mock(Connection.class)); + mockMetaDbUtil.when(() -> MetaDbUtil.queryMetaDbWrapper(Mockito.any(), Mockito.any())).thenCallRealMethod(); multiVersionColumnarSchema = new MultiVersionColumnarSchema(null); tableEvolutionAccessorMockedConstruction = Mockito.mockConstruction( ColumnarTableEvolutionAccessor.class, (mock, context) -> { Mockito.when(mock.queryTableIdAndGreaterThanTso(Mockito.anyLong(), Mockito.anyLong())).thenAnswer( - invocation -> { - return Arrays.asList(TABLE_EVOLUTION_RECORDS); - } + invocation -> Arrays.asList(TABLE_EVOLUTION_RECORDS) ); }); columnEvolutionAccessorMockedConstruction = Mockito.mockConstruction( ColumnarColumnEvolutionAccessor.class, (mock, context) -> { Mockito.when(mock.queryTableIdAndVersionIdsOrderById(Mockito.anyLong(), Mockito.anyList())).thenAnswer( - invocation -> { - return Arrays.asList(COLUMN_EVOLUTION_RECORDS); - } + invocation -> Arrays.asList(COLUMN_EVOLUTION_RECORDS) ); }); tableMappingAccessorMockedConstruction = Mockito.mockConstruction( @@ -328,7 +391,19 @@ public void setUp() { records.add(new ColumnarTableMappingRecord("transfer", "accounts", "accounts_col_index_$c9a1", 7193543788931842112L, "PUBLIC")); records.get(0).tableId = 1L; - Mockito.when(mock.querySchemaIndex(Mockito.anyString(), Mockito.anyString())).thenReturn(records); + Mockito.when(mock.querySchemaIndex(anyString(), anyString())).thenReturn(records); + }); + partitionEvolutionAccessorMockedConstruction = Mockito.mockConstruction( + ColumnarPartitionEvolutionAccessor.class, + (mock, context) -> { + Mockito.when(mock.queryTableIdAndVersionIdsOrderById(Mockito.anyLong(), Mockito.anyList())) + .thenReturn(Arrays.asList(COLUMNAR_PARTITION_EVOLUTION_RECORDS)); + }); + partitionGroupAccessorMockedConstruction = Mockito.mockConstruction( + PartitionGroupAccessor.class, + (mock, context) -> { + Mockito.when(mock.getPartitionGroupsByTableGroupId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(Arrays.asList(PARTITION_GROUP_RECORDS)); }); } @@ -349,6 +424,14 @@ public void tearDown() throws Exception { if (tableMappingAccessorMockedConstruction != null) { tableMappingAccessorMockedConstruction.close(); } + + if (partitionEvolutionAccessorMockedConstruction != null) { + partitionEvolutionAccessorMockedConstruction.close(); + } + + if (partitionGroupAccessorMockedConstruction != null) { + partitionGroupAccessorMockedConstruction.close(); + } } @Test @@ -415,7 +498,6 @@ public void getInitColumnMeta() { ColumnMeta meta = result.getMeta(); ColumnarColumnEvolutionRecord record = COLUMN_EVOLUTION_RECORDS[(int) (fieldId - 1)]; assertEquals(meta.getFullName(), record.columnsRecord.tableName + "." + record.columnName); - System.out.println(meta); } } @@ -424,12 +506,29 @@ public void getPrimaryKeyColumns() { for (ColumnarTableEvolutionRecord record : TABLE_EVOLUTION_RECORDS) { long schemaTs = record.commitTs; int[] result = multiVersionColumnarSchema.getPrimaryKeyColumns(schemaTs, TABLE_ID); - assertEquals(result.length, 1); + assertEquals(1, result.length); List columnMetas = multiVersionColumnarSchema.getColumnMetas(schemaTs, TABLE_ID); assertEquals("id", columnMetas.get(result[0] - 1).getName()); } } + @Test + public void getPartitionInfos() { + long schemaTs = TABLE_EVOLUTION_RECORDS[TABLE_EVOLUTION_RECORDS.length - 1].commitTs; + SortedMap partitionInfos = + multiVersionColumnarSchema.getPartitionInfos(schemaTs, TABLE_ID); + assertEquals(1, partitionInfos.size()); + Map.Entry entry = partitionInfos.entrySet().stream().findFirst().get(); + assertEquals(TABLE_EVOLUTION_RECORDS[0].commitTs, entry.getKey().longValue()); + assertEquals( + "PARTITION BY RANGE(`id`)\n" + + "(PARTITION `p0` VALUES LESS THAN (10000) ENGINE = Columnar,\n" + + " PARTITION `p1` VALUES LESS THAN (20000) ENGINE = Columnar,\n" + + " PARTITION `p2` VALUES LESS THAN (30000) ENGINE = Columnar)", + entry.getValue().getPartitionBy().toString() + ); + } + @Test public void purge() { // TODO(siyun): @@ -443,4 +542,56 @@ public void purge() { } assertTrue(failed); } + + @Test + public void testIndexPruning() throws ExecutionException, InterruptedException { + try (MockedStatic mockedStatic = Mockito.mockStatic(InstConfUtil.class)) { + mockedStatic.when(() -> InstConfUtil.getInt(ZONEMAP_MAX_GROUP_SIZE)).thenReturn(5000); + prepareFileSystem(); + final Map indexMap = + multiVersionColumnarSchema.getColumnIndexMap(TABLE_EVOLUTION_RECORDS[0].commitTs, TABLE_ID); + ColumnarManager columnarManager = Mockito.mock(ColumnarManager.class); + Mockito.when(columnarManager.getSortKeyColumns(anyLong(), anyString(), anyString())).thenReturn( + Collections.singletonList(0)); + Mockito.when(columnarManager.getPhysicalColumnIndexes(anyString())) + .thenReturn(indexMap); + Path orcPath = new Path(getFileFromClasspath("5a91a2f23573.orc")); + RelDataTypeFactory factory = new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); + RexBuilder rexBuilder = new RexBuilder(factory); + RexNode rexNode = rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, + new RexInputRef(0, factory.createSqlType(SqlTypeName.INTEGER)), + rexBuilder.makeIntLiteral(50)); + + List rexNodes = Lists.newArrayList(); + rexNodes.add(rexNode); + for (ColumnarTableEvolutionRecord record : TABLE_EVOLUTION_RECORDS) { + long versionId = record.versionId; + long commitTs = record.commitTs; + List columnMetas = multiVersionColumnarSchema.getColumnMetas(commitTs, TABLE_ID); + ScanPreProcessor preProcessor = new DefaultScanPreProcessor( + FILESYSTEM.getConf(), FILESYSTEM, "transfer", "accounts_col_index_$c9a1", true, true, + columnMetas.subList(2, columnMetas.size()), + rexNodes, null, 0D, 0D, columnarManager, + commitTs, multiVersionColumnarSchema.getColumnFieldIdList(versionId, TABLE_ID) + ); + + preProcessor.addFile(orcPath); + ExecutorService executorService = mock(ExecutorService.class); + when(executorService.submit(any(Runnable.class))).thenAnswer( + invocation -> { + Runnable runnable = invocation.getArgument(0); + runnable.run(); + return null; + } + ); + ListenableFuture future = + preProcessor.prepare(executorService, "traceId", new ColumnarTracer("default")); + future.get(); + Assert.assertTrue(preProcessor.isPrepared()); + SortedMap result = preProcessor.getPruningResult(orcPath); + Assert.assertEquals(1, result.size()); + Assert.assertArrayEquals(new boolean[] {true}, result.get(0)); + } + } + } } \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/util/StatisticUtilsUnitTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/util/StatisticUtilsUnitTest.java index 7f8061dda..f0d9310ab 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/util/StatisticUtilsUnitTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/gms/util/StatisticUtilsUnitTest.java @@ -3,27 +3,206 @@ import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.Assert; import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.ddl.newengine.cross.CrossEngineValidator; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.Field; +import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import com.alibaba.polardbx.optimizer.config.table.IndexMeta; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import static com.alibaba.polardbx.common.properties.ConnectionParams.ENABLE_BACKGROUND_STATISTIC_COLLECTION; import static com.alibaba.polardbx.common.properties.ConnectionParams.ENABLE_HLL; import static com.alibaba.polardbx.common.properties.ConnectionParams.MAINTENANCE_TIME_START; +import static com.alibaba.polardbx.common.utils.Assert.assertTrue; import static com.alibaba.polardbx.executor.gms.util.StatisticUtils.SELECT_TABLE_ROWS_SQL; +import static com.alibaba.polardbx.executor.gms.util.StatisticUtils.getIndexInfoFromGsi; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; /** * @author fangwu */ public class StatisticUtilsUnitTest { + @Test + public void testSketchTableDdlNormal() { + MetaDbInstConfigManager.setConfigFromMetaDb(false); + // 测试用例1:当参数正确时,不抛出异常 + try (MockedStatic optimizerContextMockedStatic = Mockito.mockStatic(OptimizerContext.class); + MockedStatic globalIndexMetaMockedStatic = Mockito.mockStatic(GlobalIndexMeta.class); + ) { + OptimizerContext optimizerContext = mock(OptimizerContext.class); + SchemaManager schemaManager = mock(SchemaManager.class); + optimizerContextMockedStatic.when(() -> OptimizerContext.getContext("test_schema")) + .thenReturn(optimizerContext); + when(optimizerContext.getLatestSchemaManager()).thenReturn(schemaManager); + when(schemaManager.getTable("test_table")).thenReturn(mock(TableMeta.class)); + globalIndexMetaMockedStatic.when(() -> GlobalIndexMeta.getTableIndexMap(any(), any())) + .thenReturn(Maps.newHashMap()); + StatisticUtils.sketchTableDdl("test_schema", "test_table", false, new ExecutionContext()); + } + } + + @Test + public void testSketchTableDdlFileStore() { + // 测试用例2:如果是文件存储表,则直接返回而不执行后续操作 + MetaDbInstConfigManager.setConfigFromMetaDb(false); + try (MockedStatic optimizerContextMockedStatic = Mockito.mockStatic(OptimizerContext.class); + MockedStatic globalIndexMetaMockedStatic = Mockito.mockStatic(GlobalIndexMeta.class); + MockedStatic statisticUtilsMockedStatic = Mockito.mockStatic(StatisticUtils.class);) { + OptimizerContext optimizerContext = mock(OptimizerContext.class); + SchemaManager schemaManager = mock(SchemaManager.class); + optimizerContextMockedStatic.when(() -> OptimizerContext.getContext("test_schema")) + .thenReturn(optimizerContext); + when(optimizerContext.getLatestSchemaManager()).thenReturn(schemaManager); + when(schemaManager.getTable("test_table")).thenReturn(mock(TableMeta.class)); + + globalIndexMetaMockedStatic.when(() -> GlobalIndexMeta.getTableIndexMap(any(), any())) + .thenReturn(Maps.newHashMap()); + + statisticUtilsMockedStatic.when(() -> StatisticUtils.isFileStore(any(), any())) + .thenReturn(true); + statisticUtilsMockedStatic.when( + () -> StatisticUtils.sketchTableDdl(any(), any(), Mockito.anyBoolean(), any())) + .thenCallRealMethod(); + + StatisticUtils.sketchTableDdl("test_schema", "test_table", false, new ExecutionContext()); + } + } + + @Test + public void testSketchTableDdl_JobInterrupted() { + // 测试用例3:如果DDL作业被取消,则抛出TddlRuntimeException + MetaDbInstConfigManager.setConfigFromMetaDb(false); + try (MockedStatic optimizerContextMockedStatic = Mockito.mockStatic(OptimizerContext.class); + MockedStatic globalIndexMetaMockedStatic = Mockito.mockStatic(GlobalIndexMeta.class); + MockedStatic statisticUtilsMockedStatic = Mockito.mockStatic(StatisticUtils.class); + MockedStatic crossEngineValidatorMockedStatic = Mockito.mockStatic( + CrossEngineValidator.class); + ) { + Map>> indexMap = Maps.newHashMap(); + indexMap.put("test_schema", Maps.newHashMap()); + + OptimizerContext optimizerContext = mock(OptimizerContext.class); + SchemaManager schemaManager = mock(SchemaManager.class); + optimizerContextMockedStatic.when(() -> OptimizerContext.getContext("test_schema")) + .thenReturn(optimizerContext); + when(optimizerContext.getLatestSchemaManager()).thenReturn(schemaManager); + + TableMeta tableMeta = mock(TableMeta.class); + when(schemaManager.getTable("test_table")).thenReturn(tableMeta); + IndexMeta uniqueIndex = createIndex(false); + List indexMetas = Lists.newArrayList(); + indexMetas.add(uniqueIndex); + when(tableMeta.getAllIndexes()).thenReturn(indexMetas); + + globalIndexMetaMockedStatic.when(() -> GlobalIndexMeta.getTableIndexMap(any(), any())) + .thenReturn(indexMap); + statisticUtilsMockedStatic.when(() -> StatisticUtils.getIndexInfoFromGsi(any(), any(), any())) + .thenCallRealMethod(); + statisticUtilsMockedStatic.when(() -> StatisticUtils.getIndexInfoFromLocalIndex(any(), any(), any())) + .thenCallRealMethod(); + statisticUtilsMockedStatic.when(() -> StatisticUtils.isFileStore(any(), any())) + .thenReturn(false); + statisticUtilsMockedStatic.when( + () -> StatisticUtils.sketchTableDdl(any(), any(), Mockito.anyBoolean(), any())) + .thenCallRealMethod(); + crossEngineValidatorMockedStatic.when(() -> CrossEngineValidator.isJobInterrupted(any())) + .thenReturn(true); + + StatisticUtils.sketchTableDdl("test_schema", "test_table", false, new ExecutionContext()); + Assert.fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("4636")); + } + } + + @Test + public void testSketchTableDdlRebuild() { + // 测试用例5:当需要强制重建时,调用rebuildShardParts方法 + MetaDbInstConfigManager.setConfigFromMetaDb(false); + try (MockedStatic optimizerContextMockedStatic = Mockito.mockStatic(OptimizerContext.class); + MockedStatic globalIndexMetaMockedStatic = Mockito.mockStatic(GlobalIndexMeta.class); + MockedStatic statisticUtilsMockedStatic = Mockito.mockStatic(StatisticUtils.class); + MockedStatic crossEngineValidatorMockedStatic = Mockito.mockStatic( + CrossEngineValidator.class); + MockedStatic statisticManagerMockedStatic = Mockito.mockStatic(StatisticManager.class); + + ) { + Map>> indexMap = Maps.newHashMap(); + indexMap.put("test_schema", Maps.newHashMap()); + indexMap.get("test_schema").put("test_table", ImmutableList.of("test_col")); + + OptimizerContext optimizerContext = mock(OptimizerContext.class); + SchemaManager schemaManager = mock(SchemaManager.class); + optimizerContextMockedStatic.when(() -> OptimizerContext.getContext("test_schema")) + .thenReturn(optimizerContext); + when(optimizerContext.getLatestSchemaManager()).thenReturn(schemaManager); + TableMeta tableMeta = mock(TableMeta.class); + when(schemaManager.getTable("test_table")).thenReturn(tableMeta); + IndexMeta uniqueIndex = createIndex(false); + List indexMetas = Lists.newArrayList(); + indexMetas.add(uniqueIndex); + when(tableMeta.getAllIndexes()).thenReturn(indexMetas); + + statisticUtilsMockedStatic.when(() -> StatisticUtils.isFileStore(any(), any())) + .thenReturn(false); + statisticUtilsMockedStatic.when( + () -> StatisticUtils.sketchTableDdl(any(), any(), Mockito.anyBoolean(), any())) + .thenCallRealMethod(); + statisticUtilsMockedStatic.when(() -> StatisticUtils.getIndexInfoFromGsi(any(), any(), any())) + .thenCallRealMethod(); + statisticUtilsMockedStatic.when(() -> StatisticUtils.getIndexInfoFromLocalIndex(any(), any(), any())) + .thenCallRealMethod(); + crossEngineValidatorMockedStatic.when(() -> CrossEngineValidator.isJobInterrupted(any())) + .thenReturn(false); + + StatisticManager statisticManager = mock(StatisticManager.class); + statisticManagerMockedStatic.when(() -> StatisticManager.getInstance()).thenReturn(statisticManager); + + ExecutionContext executionContext = new ExecutionContext(); + + StatisticUtils.sketchTableDdl("test_schema", "test_table", true, executionContext); + + verify(statisticManager, times(2)).rebuildShardParts(any(), any(), any(), any(), any()); + verify(statisticManager, times(0)).updateAllShardParts(any(), any(), any(), any(), any()); + + clearInvocations(statisticManager); + + StatisticUtils.sketchTableDdl("test_schema", "test_table", false, executionContext); + + verify(statisticManager, times(0)).rebuildShardParts(any(), any(), any(), any(), any()); + verify(statisticManager, times(2)).updateAllShardParts(any(), any(), any(), any(), any()); + } + } @Test public void testConstructScanSamplingSql() { @@ -43,7 +222,7 @@ public void testConstructScanSamplingSql() { + "select `col1`,`col2` from `testTable`"; // 断言结果是否正确 - Assert.assertTrue(sql.startsWith(expectedSqlStart)); + assertTrue(sql.startsWith(expectedSqlStart)); } @@ -55,7 +234,7 @@ public void testBuildCollectRowCountSql() { "select_base_four_multi_db_multi_tb_Nu9i_06"}; String sql = StatisticUtils.buildCollectRowCountSql(Lists.newArrayList(tbls)); System.out.println(sql); - Assert.assertTrue( + assertTrue( ("SELECT table_schema, table_name, table_rows FROM information_schema.tables " + "WHERE TABLE_NAME IN (" + "'select_base_four_multi_db_multi_tb_Nu9i_00'," @@ -66,9 +245,9 @@ public void testBuildCollectRowCountSql() { .equals(sql)); sql = StatisticUtils.buildCollectRowCountSql(null); - Assert.assertTrue(SELECT_TABLE_ROWS_SQL.equals(sql)); + assertTrue(SELECT_TABLE_ROWS_SQL.equals(sql)); sql = StatisticUtils.buildCollectRowCountSql(Collections.emptyList()); - Assert.assertTrue(SELECT_TABLE_ROWS_SQL.equals(sql)); + assertTrue(SELECT_TABLE_ROWS_SQL.equals(sql)); } /** @@ -82,32 +261,32 @@ public void testNeedSketchInterrupted() { MetaDbInstConfigManager.getInstance().getCnVariableConfigMap() .put("ENABLE_BACKGROUND_STATISTIC_COLLECTION", "false"); - Assert.assertTrue(InstConfUtil.getBool(ENABLE_BACKGROUND_STATISTIC_COLLECTION) == false); + assertTrue(InstConfUtil.getBool(ENABLE_BACKGROUND_STATISTIC_COLLECTION) == false); Pair pair = ExecUtils.needSketchInterrupted(); - Assert.assertTrue(pair.getKey()); + assertTrue(pair.getKey()); - Assert.assertTrue(pair.getValue().equals("ENABLE_BACKGROUND_STATISTIC_COLLECTION not enabled")); + assertTrue(pair.getValue().equals("ENABLE_BACKGROUND_STATISTIC_COLLECTION not enabled")); // revert ENABLE_BACKGROUND_STATISTIC_COLLECTION = true MetaDbInstConfigManager.getInstance().getCnVariableConfigMap() .put("ENABLE_BACKGROUND_STATISTIC_COLLECTION", "true"); - Assert.assertTrue(InstConfUtil.getBool(ENABLE_BACKGROUND_STATISTIC_COLLECTION)); + assertTrue(InstConfUtil.getBool(ENABLE_BACKGROUND_STATISTIC_COLLECTION)); // Test sketch interrupted by ENABLE_HLL=false MetaDbInstConfigManager.getInstance().getCnVariableConfigMap().put("ENABLE_HLL", "false"); - Assert.assertTrue(InstConfUtil.getBool(ENABLE_HLL) == false); + assertTrue(InstConfUtil.getBool(ENABLE_HLL) == false); pair = ExecUtils.needSketchInterrupted(); - Assert.assertTrue(pair.getKey()); + assertTrue(pair.getKey()); - Assert.assertTrue(pair.getValue().equals("ENABLE_HLL not enabled")); + assertTrue(pair.getValue().equals("ENABLE_HLL not enabled")); // revert ENABLE_HLL = true MetaDbInstConfigManager.getInstance().getCnVariableConfigMap().put("ENABLE_HLL", "true"); - Assert.assertTrue(InstConfUtil.getBool(ENABLE_HLL)); + assertTrue(InstConfUtil.getBool(ENABLE_HLL)); } /** @@ -119,53 +298,215 @@ public void testIsInMaintenanceTimeWindow() { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, 1); - Assert.assertTrue(!InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, + assertTrue(!InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, ConnectionParams.MAINTENANCE_TIME_END)); calendar.set(Calendar.HOUR_OF_DAY, 2); - Assert.assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, + assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, ConnectionParams.MAINTENANCE_TIME_END)); calendar.set(Calendar.HOUR_OF_DAY, 3); - Assert.assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, + assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, ConnectionParams.MAINTENANCE_TIME_END)); calendar.set(Calendar.HOUR_OF_DAY, 4); - Assert.assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, + assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, ConnectionParams.MAINTENANCE_TIME_END)); calendar.set(Calendar.HOUR_OF_DAY, 4); calendar.set(Calendar.MINUTE, 40); - Assert.assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, + assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, ConnectionParams.MAINTENANCE_TIME_END)); calendar.set(Calendar.HOUR_OF_DAY, 5); calendar.set(Calendar.MINUTE, 1); - Assert.assertTrue(!InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, + assertTrue(!InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, ConnectionParams.MAINTENANCE_TIME_END)); // mock error config for MAINTENANCE_TIME_START / MAINTENANCE_TIME_END MetaDbInstConfigManager.getInstance().getCnVariableConfigMap().put("MAINTENANCE_TIME_START", "xx"); - Assert.assertTrue(InstConfUtil.getOriginVal(MAINTENANCE_TIME_START).equals("xx")); + assertTrue(InstConfUtil.getOriginVal(MAINTENANCE_TIME_START).equals("xx")); - Assert.assertTrue(!InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, + assertTrue(!InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, ConnectionParams.MAINTENANCE_TIME_END)); MetaDbInstConfigManager.getInstance().getCnVariableConfigMap().remove("MAINTENANCE_TIME_START"); - Assert.assertTrue(InstConfUtil.getOriginVal(MAINTENANCE_TIME_START).equals("02:00")); + assertTrue(InstConfUtil.getOriginVal(MAINTENANCE_TIME_START).equals("02:00")); MetaDbInstConfigManager.getInstance().getCnVariableConfigMap().put("MAINTENANCE_TIME_START", "23:00"); MetaDbInstConfigManager.getInstance().getCnVariableConfigMap().put("MAINTENANCE_TIME_END", "03:00"); calendar.set(Calendar.HOUR_OF_DAY, 1); - Assert.assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, + assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, ConnectionParams.MAINTENANCE_TIME_END)); calendar.set(Calendar.HOUR_OF_DAY, 0); - Assert.assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, + assertTrue(InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, ConnectionParams.MAINTENANCE_TIME_END)); calendar.set(Calendar.HOUR_OF_DAY, 4); - Assert.assertTrue(!InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, + assertTrue(!InstConfUtil.isInMaintenanceTimeWindow(calendar, ConnectionParams.MAINTENANCE_TIME_START, ConnectionParams.MAINTENANCE_TIME_END)); } + + /** + * 空的gsiPublished集合 + */ + @Test + public void testGetIndexInfoFromGsiWithEmptyGsiPublished() { + TableMeta mockTableMeta = mock(TableMeta.class); + + Set colDoneSet = new HashSet<>(); + Map> indexColsMap = new HashMap<>(); + getIndexInfoFromGsi(mockTableMeta, colDoneSet, indexColsMap); + assertTrue(indexColsMap.isEmpty(), "当没有GSI时,索引列映射应该是空的"); + } + + /** + * 包含非唯一索引的gsiPublished集合 + */ + @Test + public void testGetIndexInfoFromGsiWithNonUniqueGsi() { + TableMeta mockTableMeta = mock(TableMeta.class); + Set colDoneSet = new HashSet<>(); + Map> indexColsMap = new HashMap<>(); + + // 假设有一个非唯一的GSI + List columns = Arrays.asList( + new GsiMetaManager.GsiIndexColumnMetaBean(-1, "columnA", "", -1L, null, null, null, false), + new GsiMetaManager.GsiIndexColumnMetaBean(-1, "columnB", "", -1L, null, null, null, false) + ); + GsiMetaManager.GsiIndexMetaBean gsiIndexMetaBean = new GsiMetaManager.GsiIndexMetaBean(null, null, null, true, + null, null, columns, null, null, null, null, null, null, null, -1L, false, false, null); + Map gsiPublished = new HashMap<>(); + gsiPublished.put("index1", gsiIndexMetaBean); + when(mockTableMeta.getGsiPublished()).thenReturn(gsiPublished); + + getIndexInfoFromGsi(mockTableMeta, colDoneSet, indexColsMap); + + assertEquals("应该有两个索引列被加入到集合中", 2, indexColsMap.get("index1").size()); + } + + /** + * 包含唯一索引的gsiPublished集合 + */ + @Test + public void testGetIndexInfoFromGsiWithUniqueGsi() { + TableMeta mockTableMeta = mock(TableMeta.class); + Set colDoneSet = new HashSet<>(); + Map> indexColsMap = new HashMap<>(); + + // 假设有一个非唯一的GSI + List columns = Arrays.asList( + new GsiMetaManager.GsiIndexColumnMetaBean(-1, "columnA", "", -1L, null, null, null, false), + new GsiMetaManager.GsiIndexColumnMetaBean(-1, "columnB", "", -1L, null, null, null, false), + new GsiMetaManager.GsiIndexColumnMetaBean(-1, "columnC", "", -1L, null, null, null, false) + ); + GsiMetaManager.GsiIndexMetaBean gsiIndexMetaBean = new GsiMetaManager.GsiIndexMetaBean(null, null, null, false, + null, null, columns, null, null, null, null, null, null, null, -1L, false, false, null); + Map gsiPublished = new HashMap<>(); + gsiPublished.put("index1", gsiIndexMetaBean); + when(mockTableMeta.getGsiPublished()).thenReturn(gsiPublished); + + getIndexInfoFromGsi(mockTableMeta, colDoneSet, indexColsMap); + + assertEquals("应该有一个索引被加入到集合中", 1, indexColsMap.size()); + assertEquals("应该有两个索引列被加入到集合中", 2, indexColsMap.values().iterator().next().size()); + } + + /** + * 已经存在的索引名称 + */ + @Test + public void testGetIndexInfoFromGsiWithExistingIndexName() { + TableMeta mockTableMeta = mock(TableMeta.class); + Set colDoneSet = new HashSet<>(); + Map> indexColsMap = new HashMap<>(); + + List columns = Arrays.asList( + new GsiMetaManager.GsiIndexColumnMetaBean(-1, "columnA", "", -1L, null, null, null, true), + new GsiMetaManager.GsiIndexColumnMetaBean(-1, "columnB", "", -1L, null, null, null, true) + ); + GsiMetaManager.GsiIndexMetaBean gsiIndexMetaBean = new GsiMetaManager.GsiIndexMetaBean(null, null, null, true, + null, null, columns, null, null, null, null, null, null, null, -1L, false, false, null); + // 假设有两个相同的非唯一GSI + Map gsiPublished = new HashMap<>(); + gsiPublished.put("index1", gsiIndexMetaBean); + gsiPublished.put("index1", gsiIndexMetaBean); // 同样的名字 + when(mockTableMeta.getGsiPublished()).thenReturn(gsiPublished); + + getIndexInfoFromGsi(mockTableMeta, colDoneSet, indexColsMap); + assertEquals("即使存在多个同名索引,也应该只记录一次", 2, indexColsMap.get("index1").size()); + assertEquals("即使存在多个同名索引,也应该只记录一次", 1, indexColsMap.size()); + } + + /** + * 空的tableMeta, 当传入空的tableMeta时,应该没有任何改变。 + */ + @Test + public void testGetIndexInfoFromLocalIndexWithEmptyTableMeta() { + TableMeta mockTableMeta = mock(TableMeta.class); + Set colDoneSet = new HashSet<>(); + Map> indexColsMap = new HashMap<>(); + + when(mockTableMeta.getAllIndexes()).thenReturn(Collections.emptyList()); + + StatisticUtils.getIndexInfoFromLocalIndex(mockTableMeta, colDoneSet, indexColsMap); + + assertEquals(0, indexColsMap.size()); + assertEquals(0, colDoneSet.size()); + } + + /** + * 包含唯一索引的tableMeta + * 唯一索引不应该被处理。 + */ + @Test + public void testGetIndexInfoFromLocalIndexWithUniqueIndex() { + TableMeta mockTableMeta = mock(TableMeta.class); + Set colDoneSet = new HashSet<>(); + Map> indexColsMap = new HashMap<>(); + + IndexMeta uniqueIndex = createIndex(true); // 创建唯一的索引 + List indexMetas = Lists.newArrayList(); + indexMetas.add(uniqueIndex); + when(mockTableMeta.getAllIndexes()).thenReturn(indexMetas); + + StatisticUtils.getIndexInfoFromLocalIndex(mockTableMeta, colDoneSet, indexColsMap); + + assertEquals(1, indexColsMap.size()); + assertEquals(1, colDoneSet.size()); + } + + /** + * 正常情况下的非唯一索引 + * 应当正确填充indexColsMap并更新colDoneSet。 + */ + @Test + public void testGetIndexInfoFromLocalIndexWithNonUniqueIndex() { + TableMeta mockTableMeta = mock(TableMeta.class); + Set colDoneSet = new HashSet<>(); + Map> indexColsMap = new HashMap<>(); + + IndexMeta nonUniqueIndex = createIndex(false); // 创建非唯一的索引 + List indexMetas = Lists.newArrayList(); + indexMetas.add(nonUniqueIndex); + when(mockTableMeta.getAllIndexes()).thenReturn(indexMetas); + + StatisticUtils.getIndexInfoFromLocalIndex(mockTableMeta, colDoneSet, indexColsMap); + + assertEquals(1, indexColsMap.size()); + assertTrue(indexColsMap.containsKey("idx1")); + assertEquals(2, colDoneSet.size()); + assertTrue(colDoneSet.contains("c1")); + assertTrue(colDoneSet.contains("c1,c2")); + } + + private IndexMeta createIndex(boolean isUnique) { + List columns = Arrays.asList( + new ColumnMeta(null, "c1", null, mock(Field.class)), + new ColumnMeta(null, "c2", null, mock(Field.class)) + ); + return new IndexMeta("t1", columns, columns, null, null, false, false, isUnique, "idx1"); + } + } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTablesForPartitionDatabaseHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTablesForPartitionDatabaseHandlerTest.java index 0765fb607..fe4c5d573 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTablesForPartitionDatabaseHandlerTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/LogicalShowCreateTablesForPartitionDatabaseHandlerTest.java @@ -47,7 +47,6 @@ import static com.alibaba.polardbx.common.properties.ConnectionParams.OUTPUT_MYSQL_INDENT; import static com.alibaba.polardbx.common.properties.ConnectionParams.SHOW_HASH_PARTITIONS_BY_RANGE; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.mock; @@ -127,31 +126,5 @@ public void showWithMySqlIndentTest() { } } - @Test - public void testGetColumnarIndexEngineReturnsExternalDisk() { - try (MockedStatic mockedDataSource = mockStatic(MetaDbDataSource.class)) { - MetaDbDataSource mockDataSource = mock(MetaDbDataSource.class); - Connection mockConnection = mock(Connection.class); - TablesAccessor mockAccessor = mock(TablesAccessor.class); - - mockedDataSource.when(MetaDbDataSource::getInstance).thenReturn(mockDataSource); - when(mockDataSource.getConnection()).thenReturn(mockConnection); - - TablesRecord expectedRecord = new TablesRecord(); - expectedRecord.engine = "EXTERNAL_DISK"; - when(mockAccessor.query(anyString(), anyString(), eq(false))).thenReturn(expectedRecord); - - LogicalShowCreateTablesForPartitionDatabaseHandler service = mock( - LogicalShowCreateTablesForPartitionDatabaseHandler.class); - doCallRealMethod().when(service).getColumnarIndexEngine(anyString(), anyString(), any()); - String engine = service.getColumnarIndexEngine("schemaName", "indexName", mockAccessor); - - Assert.assertEquals("EXTERNAL_DISK", engine); - - when(mockAccessor.query(anyString(), anyString(), eq(false))).thenReturn(null); - engine = service.getColumnarIndexEngine("schemaName", "indexName", mockAccessor); - Assert.assertNull(engine); - } - } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/LogicalStartReplicaCheckTableHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/LogicalStartReplicaCheckTableHandlerTest.java new file mode 100644 index 000000000..3c7114a6b --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/LogicalStartReplicaCheckTableHandlerTest.java @@ -0,0 +1,85 @@ +package com.alibaba.polardbx.executor.handler; + +import com.alibaba.polardbx.common.cdc.RplConstants; +import lombok.SneakyThrows; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlStartReplicaCheck; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.junit.Test; +import org.mockito.Mockito; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +/** + * @author yudong + * @since 2024/6/25 14:54 + **/ +public class LogicalStartReplicaCheckTableHandlerTest { + + @SneakyThrows + @SuppressWarnings("unchecked") + @Test + public void testBuildParamsWithAllParametersPresent() { + LogicalStartReplicaCheckTableHandler mockHandler = Mockito.mock(LogicalStartReplicaCheckTableHandler.class); + SqlStartReplicaCheck sqlStartReplicaCheck = Mockito.mock(SqlStartReplicaCheck.class); + when(sqlStartReplicaCheck.getDbName()).thenReturn(new SqlIdentifier("test_db", new SqlParserPos(0, 0))); + when(sqlStartReplicaCheck.getTableName()).thenReturn(new SqlIdentifier("test_table", new SqlParserPos(0, 0))); + when(sqlStartReplicaCheck.getChannel()).thenReturn(new SqlIdentifier("test_channel", new SqlParserPos(0, 0))); + when(sqlStartReplicaCheck.getMode()).thenReturn(new SqlIdentifier("snapshot", new SqlParserPos(0, 0))); + + Method method = + LogicalStartReplicaCheckTableHandler.class.getDeclaredMethod("buildParams", SqlStartReplicaCheck.class); + method.setAccessible(true); + Map result = (Map) method.invoke(mockHandler, sqlStartReplicaCheck); + + assertEquals("test_db", result.get(RplConstants.RPL_FULL_VALID_DB)); + assertEquals("test_table", result.get(RplConstants.RPL_FULL_VALID_TB)); + assertEquals("test_channel", result.get(RplConstants.CHANNEL)); + assertEquals("snapshot", result.get(RplConstants.RPL_FULL_VALID_MODE)); + } + + @SneakyThrows + @SuppressWarnings("unchecked") + @Test + public void testBuildParamsWithoutMode() { + LogicalStartReplicaCheckTableHandler mockHandler = Mockito.mock(LogicalStartReplicaCheckTableHandler.class); + SqlStartReplicaCheck sqlStartReplicaCheck = Mockito.mock(SqlStartReplicaCheck.class); + when(sqlStartReplicaCheck.getDbName()).thenReturn(new SqlIdentifier("test_db", new SqlParserPos(0, 0))); + when(sqlStartReplicaCheck.getTableName()).thenReturn(new SqlIdentifier("test_table", new SqlParserPos(0, 0))); + when(sqlStartReplicaCheck.getChannel()).thenReturn(new SqlIdentifier("test_channel", new SqlParserPos(0, 0))); + when(sqlStartReplicaCheck.getMode()).thenReturn(null); + + Method method = + LogicalStartReplicaCheckTableHandler.class.getDeclaredMethod("buildParams", SqlStartReplicaCheck.class); + method.setAccessible(true); + Map result = (Map) method.invoke(mockHandler, sqlStartReplicaCheck); + + assertEquals("test_db", result.get(RplConstants.RPL_FULL_VALID_DB)); + assertEquals("test_table", result.get(RplConstants.RPL_FULL_VALID_TB)); + assertEquals("test_channel", result.get(RplConstants.CHANNEL)); + assertEquals("snapshot", result.get(RplConstants.RPL_FULL_VALID_MODE)); + } + + @Test(expected = InvocationTargetException.class) + @SneakyThrows + public void testBuildParamsWithFalseMode() { + LogicalStartReplicaCheckTableHandler mockHandler = Mockito.mock(LogicalStartReplicaCheckTableHandler.class); + SqlStartReplicaCheck sqlStartReplicaCheck = Mockito.mock(SqlStartReplicaCheck.class); + when(sqlStartReplicaCheck.getDbName()).thenReturn(new SqlIdentifier("test_db", new SqlParserPos(0, 0))); + when(sqlStartReplicaCheck.getTableName()).thenReturn(new SqlIdentifier("test_table", new SqlParserPos(0, 0))); + when(sqlStartReplicaCheck.getChannel()).thenReturn(new SqlIdentifier("test_channel", new SqlParserPos(0, 0))); + when(sqlStartReplicaCheck.getMode()).thenReturn(new SqlIdentifier("auto", new SqlParserPos(0, 0))); + + Method method = + LogicalStartReplicaCheckTableHandler.class.getDeclaredMethod("buildParams", SqlStartReplicaCheck.class); + + method.setAccessible(true); + method.invoke(mockHandler, sqlStartReplicaCheck); + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaMetricHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaMetricHandlerTest.java new file mode 100644 index 000000000..8858b8b45 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaMetricHandlerTest.java @@ -0,0 +1,79 @@ +package com.alibaba.polardbx.executor.handler.subhandler; + +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.sync.MetricSyncAllAction; +import com.alibaba.polardbx.gms.sync.GmsSyncManagerHelper; +import com.alibaba.polardbx.gms.sync.SyncScope; +import com.alibaba.polardbx.optimizer.core.row.Row; +import com.alibaba.polardbx.stats.metric.FeatureStats; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.util.List; +import java.util.Map; + +import static com.alibaba.polardbx.stats.metric.FeatureStatsItem.NEW_BASELINE_NUM; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; + +/** + * @author fangwu + */ +public class InformationSchemaMetricHandlerTest { + + @Test + public void testBuildEmptyArrayResultCursor() { + try (MockedStatic gmsSyncManagerHelperMockedStatic = mockStatic( + GmsSyncManagerHelper.class)) { + gmsSyncManagerHelperMockedStatic.when(() -> GmsSyncManagerHelper.sync(any(), any(), any(SyncScope.class))) + .thenReturn(null); + + ArrayResultCursor cursor = MetricSyncAllAction.buildResultCursor(); + cursor = InformationSchemaMetricHandler.buildArrayResultCursor(cursor); + + assert cursor.getRows().isEmpty(); + } + } + + @Test + public void testBuildArrayResultCursor() { + List>> metrics = Lists.newArrayList(); + Map map = Maps.newHashMap(); + map.put(MetricSyncAllAction.HOST, "host"); + map.put(MetricSyncAllAction.INST, "instId"); + map.put(MetricSyncAllAction.METRIC_REAL_KEY, "test_key:val1,test_key2:33"); + map.put(MetricSyncAllAction.METRIC_FEAT_KEY, FeatureStats.serialize(FeatureStats.build())); + + metrics.add(Lists.newArrayList(map)); + + try (MockedStatic gmsSyncManagerHelperMockedStatic = mockStatic( + GmsSyncManagerHelper.class)) { + gmsSyncManagerHelperMockedStatic.when(() -> GmsSyncManagerHelper.sync(any(), any(), any(SyncScope.class))) + .thenReturn(metrics); + + ArrayResultCursor cursor = MetricSyncAllAction.buildResultCursor(); + cursor = InformationSchemaMetricHandler.buildArrayResultCursor(cursor); + + boolean hasTestKey = false; + boolean hasTestKey2 = false; + boolean hasNewBaselineNum = false; + for (Row row : cursor.getRows()) { + String key = row.getString(2); + if (key.equalsIgnoreCase(NEW_BASELINE_NUM.name())) { + hasNewBaselineNum = true; + continue; + } else if (key.equalsIgnoreCase("test_key")) { + hasTestKey = true; + continue; + } else if (key.equalsIgnoreCase("test_key2")) { + hasTestKey2 = true; + continue; + } + } + + assert hasNewBaselineNum && hasTestKey2 && hasTestKey; + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaRplSyncPointHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaRplSyncPointHandlerTest.java new file mode 100644 index 000000000..fcd734553 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaRplSyncPointHandlerTest.java @@ -0,0 +1,68 @@ +package com.alibaba.polardbx.executor.handler.subhandler; + +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.row.Row; +import com.alibaba.polardbx.optimizer.view.VirtualView; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertArrayEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +/** + * @author yudong + * @since 2024/6/25 16:25 + **/ +public class InformationSchemaRplSyncPointHandlerTest { + + @Test + public void test() throws SQLException { + List expectedData = Arrays.asList( + new Object[] {1L, "111", "222", new Timestamp(System.currentTimeMillis())}, + new Object[] {2L, "333", "444", new Timestamp(System.currentTimeMillis())} + ); + + Connection mockMetaConn = mock(Connection.class); + PreparedStatement mockStmt = mock(PreparedStatement.class); + ResultSet mockRs = mock(ResultSet.class); + when(mockMetaConn.prepareStatement(anyString())).thenReturn(mockStmt); + when(mockStmt.executeQuery()).thenReturn(mockRs); + when(mockRs.next()).thenReturn(true, true, false); + when(mockRs.getLong("ID")).thenReturn((Long) expectedData.get(0)[0]).thenReturn((Long) expectedData.get(1)[0]); + when(mockRs.getString("PRIMARY_TSO")).thenReturn((String) expectedData.get(0)[1]) + .thenReturn((String) expectedData.get(1)[1]); + when(mockRs.getString("SECONDARY_TSO")).thenReturn((String) expectedData.get(0)[2]) + .thenReturn((String) expectedData.get(1)[2]); + when(mockRs.getTimestamp("CREATE_TIME")).thenReturn((Timestamp) expectedData.get(0)[3]) + .thenReturn((Timestamp) expectedData.get(1)[3]); + + try (MockedStatic metaDbUtilMockedStatic = mockStatic(MetaDbUtil.class)) { + metaDbUtilMockedStatic.when(MetaDbUtil::getConnection).thenReturn(mockMetaConn); + metaDbUtilMockedStatic.when(() -> MetaDbUtil.hasTable(anyString())).thenReturn(true); + InformationSchemaRplSyncPointHandler handler = new InformationSchemaRplSyncPointHandler(null); + VirtualView virtualView = mock(VirtualView.class); + ExecutionContext executionContext = mock(ExecutionContext.class); + ArrayResultCursor cursor = new ArrayResultCursor("test"); + handler.handle(virtualView, executionContext, cursor); + + for (int i = 0; i < expectedData.size(); i++) { + Row row = cursor.getRows().get(i); + assertArrayEquals(expectedData.get(i), row.getValues().toArray()); + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTablesTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTablesTest.java new file mode 100644 index 000000000..fabf110a8 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/handler/subhandler/InformationSchemaTablesTest.java @@ -0,0 +1,519 @@ +package com.alibaba.polardbx.executor.handler.subhandler; + +import com.alibaba.polardbx.atom.TAtomDataSource; +import com.alibaba.polardbx.atom.config.TAtomDsConfDO; +import com.alibaba.polardbx.atom.config.TAtomDsConfHandle; +import com.alibaba.polardbx.common.utils.version.InstanceVersion; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.spi.IGroupExecutor; +import com.alibaba.polardbx.executor.spi.ITopologyExecutor; +import com.alibaba.polardbx.gms.topology.DbTopologyManager; +import com.alibaba.polardbx.group.config.OptimizedGroupConfigManager; +import com.alibaba.polardbx.group.jdbc.TGroupDataSource; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.core.row.Row; +import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; +import com.alibaba.polardbx.optimizer.partition.common.PartitionLocation; +import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; +import com.alibaba.polardbx.rpc.compatible.ArrayResultSet; +import com.alibaba.polardbx.rule.TableRule; +import com.alibaba.polardbx.rule.TddlRule; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import static com.alibaba.polardbx.gms.topology.DbTopologyManager.getConnectionForStorage; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class InformationSchemaTablesTest { + @Before + public void before() { + InstanceVersion.setMYSQL80(true); + } + + @Before + public void after() { + InstanceVersion.setMYSQL80(false); + } + + @Test + public void test() throws SQLException { + try (MockedStatic mockDbTopologyManager = mockStatic(DbTopologyManager.class)) { + // mock mock + // db1: drds mode, contains table tb1, tb1 contains gsi gsi1 + // db2: auto mode, contains table tb2, tb2 contains gsi gsi2 + String db1 = "db1"; + String db1Group1 = "db1_00000_GROUP"; + String db1Group2 = "db1_00001_GROUP"; + String db2 = "db2"; + String db2Group1 = "db2_00000_GROUP"; + String db2Group2 = "db2_00001_GROUP"; + String db2db1 = "db2_00000"; + String db2db2 = "db2_00001"; + String tb1 = "tb1"; + String tb1p1 = "tb1_qwer"; + String tb1p2 = "tb1_rtyu"; + String tb2 = "tb2"; + String tb2p1 = "tb2_uiop"; + String tb2p2 = "tb2_asdf"; + String gsi1 = "gsi1"; + String gsi1p1 = "gsi1_hjkl"; + String gsi1p2 = "gsi1_qwer"; + String gsi2 = "gsi2"; + String gsi2p1 = "gsi2_hjkl"; + String gsi2p2 = "gsi2_qwer"; + + Set schemaNames = ImmutableSet.of(db1, db2); + Set tables = ImmutableSet.of(tb1, tb2); + + // mock db1 + ExecutorContext executorContext1 = new ExecutorContext(); + ITopologyExecutor topologyExecutor1 = mock(ITopologyExecutor.class); + executorContext1.setTopologyExecutor(topologyExecutor1); + ExecutorContext.setContext(db1, executorContext1); + + IGroupExecutor groupExecutor1 = mock(IGroupExecutor.class); + when(topologyExecutor1.getGroupExecutor(db1Group1)).thenReturn(groupExecutor1); + TGroupDataSource dataSource1 = mock(TGroupDataSource.class); + when(groupExecutor1.getDataSource()).thenReturn(dataSource1); + String dataSource1Address = "127.0.0.1:3001"; + when(dataSource1.getMasterSourceAddress()).thenReturn(dataSource1Address); + when(dataSource1.getMasterDNId()).thenReturn(dataSource1Address); + OptimizedGroupConfigManager configManager1 = mock(OptimizedGroupConfigManager.class); + when(dataSource1.getConfigManager()).thenReturn(configManager1); + TAtomDataSource tAtomDataSource1 = mock(TAtomDataSource.class); + when(configManager1.getDataSource(any())).thenReturn(tAtomDataSource1); + TAtomDsConfHandle tAtomDsConfHandle1 = mock(TAtomDsConfHandle.class); + when(tAtomDataSource1.getDsConfHandle()).thenReturn(tAtomDsConfHandle1); + TAtomDsConfDO tAtomDsConfDO1 = mock(TAtomDsConfDO.class); + when(tAtomDsConfHandle1.getRunTimeConf()).thenReturn(tAtomDsConfDO1); + when(tAtomDsConfDO1.getDbName()).thenReturn(db1Group1); + Connection connection1 = mock(Connection.class); + mockDbTopologyManager.when(() -> getConnectionForStorage(dataSource1Address)).thenReturn(connection1); + Statement statement1 = mock(Statement.class); + when(connection1.createStatement()).thenReturn(statement1); + ResultSet rs1 = mock2Results(db1Group1.toLowerCase(), tb1p1.toLowerCase(), db1Group1.toLowerCase(), + gsi1p1.toLowerCase()); + when(statement1.executeQuery(any())).then(invocation -> { + String sql = invocation.getArgument(0); + System.out.println(sql); + Assert.assertTrue(sql.contains("('" + db1Group1.toLowerCase() + "', '" + tb1p1.toLowerCase() + "')")); + Assert.assertTrue(sql.contains("('" + db1Group1.toLowerCase() + "', '" + gsi1p1.toLowerCase() + "'))")); + return rs1; + }); + + IGroupExecutor groupExecutor2 = mock(IGroupExecutor.class); + when(topologyExecutor1.getGroupExecutor(db1Group2)).thenReturn(groupExecutor2); + TGroupDataSource dataSource2 = mock(TGroupDataSource.class); + when(groupExecutor2.getDataSource()).thenReturn(dataSource2); + String dataSource2Address = "127.0.0.1:3002"; + when(dataSource2.getMasterSourceAddress()).thenReturn(dataSource2Address); + when(dataSource2.getMasterDNId()).thenReturn(dataSource2Address); + OptimizedGroupConfigManager configManager2 = mock(OptimizedGroupConfigManager.class); + when(dataSource2.getConfigManager()).thenReturn(configManager2); + TAtomDataSource tAtomDataSource2 = mock(TAtomDataSource.class); + when(configManager2.getDataSource(any())).thenReturn(tAtomDataSource2); + TAtomDsConfHandle tAtomDsConfHandle2 = mock(TAtomDsConfHandle.class); + when(tAtomDataSource2.getDsConfHandle()).thenReturn(tAtomDsConfHandle2); + TAtomDsConfDO tAtomDsConfDO2 = mock(TAtomDsConfDO.class); + when(tAtomDsConfHandle2.getRunTimeConf()).thenReturn(tAtomDsConfDO2); + when(tAtomDsConfDO2.getDbName()).thenReturn(db1Group2); + Connection connection2 = mock(Connection.class); + mockDbTopologyManager.when(() -> getConnectionForStorage(dataSource2Address)).thenReturn(connection2); + Statement statement2 = mock(Statement.class); + when(connection2.createStatement()).thenReturn(statement2); + ResultSet rs2 = mock2Results(db1Group2.toLowerCase(), tb1p2.toLowerCase(), db1Group2.toLowerCase(), + gsi1p2.toLowerCase()); + when(statement2.executeQuery(any())).then(invocation -> { + String sql = invocation.getArgument(0); + System.out.println(sql); + Assert.assertTrue(sql.contains("('" + db1Group2.toLowerCase() + "', '" + tb1p2.toLowerCase() + "')")); + Assert.assertTrue(sql.contains("('" + db1Group2.toLowerCase() + "', '" + gsi1p2.toLowerCase() + "'))")); + return rs2; + }); + + OptimizerContext optimizerContext1 = new OptimizerContext(db1); + OptimizerContext.loadContext(optimizerContext1); + // mock tddl rule manager + TddlRuleManager ruleManager1 = mock(TddlRuleManager.class); + optimizerContext1.setRuleManager(ruleManager1); + TddlRule tddlRule = mock(TddlRule.class); + when(ruleManager1.getTddlRule()).thenReturn(tddlRule); + TableRule tb1TableRule = mock(TableRule.class); + TableRule gsi1TableRule = mock(TableRule.class); + Collection tableRules = ImmutableSet.of(tb1TableRule, gsi1TableRule); + when(tddlRule.getTables()).thenReturn(tableRules); + when(tb1TableRule.getVirtualTbName()).thenReturn(tb1); + when(gsi1TableRule.getVirtualTbName()).thenReturn(gsi1); + when(ruleManager1.getTableRule(tb1)).thenReturn(tb1TableRule); + when(ruleManager1.getTableRule(gsi1)).thenReturn(gsi1TableRule); + Map> tb1Topologys = ImmutableMap.of( + db1Group1, ImmutableSet.of(tb1p1), + db1Group2, ImmutableSet.of(tb1p2) + ); + when(tb1TableRule.getStaticTopology()).thenReturn(tb1Topologys); + Map> gsi1Topologys = ImmutableMap.of( + db1Group1, ImmutableSet.of(gsi1p1), + db1Group2, ImmutableSet.of(gsi1p2) + ); + when(gsi1TableRule.getStaticTopology()).thenReturn(gsi1Topologys); + // mock empty partition manager + PartitionInfoManager partitionInfoManager1 = mock(PartitionInfoManager.class); + optimizerContext1.setPartitionInfoManager(partitionInfoManager1); + when(partitionInfoManager1.getPartitionInfos()).thenReturn(new ArrayList<>()); + // mock schema manager and table meta + SchemaManager schemaManager1 = mock(SchemaManager.class); + optimizerContext1.setSchemaManager(schemaManager1); + TableMeta tb1TableMeta = mock(TableMeta.class); + when(schemaManager1.getTable(tb1)).thenReturn(tb1TableMeta); + GsiMetaManager.GsiIndexMetaBean gsi1IndexMeta = mock(GsiMetaManager.GsiIndexMetaBean.class); + Map tb1Gsi = ImmutableMap.of( + gsi1, gsi1IndexMeta + ); + when(tb1TableMeta.getGsiPublished()).thenReturn(tb1Gsi); + + // mock db2 + ExecutorContext executorContext2 = new ExecutorContext(); + ITopologyExecutor topologyExecutor2 = mock(ITopologyExecutor.class); + ExecutorContext.setContext(db2, executorContext2); + executorContext2.setTopologyExecutor(topologyExecutor2); + + IGroupExecutor groupExecutor3 = mock(IGroupExecutor.class); + when(topologyExecutor2.getGroupExecutor(db2Group1)).thenReturn(groupExecutor3); + TGroupDataSource dataSource3 = mock(TGroupDataSource.class); + when(groupExecutor3.getDataSource()).thenReturn(dataSource3); + String dataSource3Address = "127.0.0.1:3003"; + when(dataSource3.getMasterSourceAddress()).thenReturn(dataSource3Address); + when(dataSource3.getMasterDNId()).thenReturn(dataSource3Address); + Connection connection3 = mock(Connection.class); + mockDbTopologyManager.when(() -> getConnectionForStorage(dataSource3Address)).thenReturn(connection3); + Statement statement3 = mock(Statement.class); + when(connection3.createStatement()).thenReturn(statement3); + ResultSet rs3 = mock2Results(db2db1.toLowerCase(), tb2p1.toLowerCase(), db2db1.toLowerCase(), + gsi2p1.toLowerCase()); + when(statement3.executeQuery(any())).then(invocation -> { + String sql = invocation.getArgument(0); + System.out.println(sql); + Assert.assertTrue(sql.contains("('" + db2db1.toLowerCase() + "', '" + tb2p1.toLowerCase() + "')")); + Assert.assertTrue(sql.contains("('" + db2db1.toLowerCase() + "', '" + gsi2p1.toLowerCase() + "'))")); + return rs3; + }); + + IGroupExecutor groupExecutor4 = mock(IGroupExecutor.class); + when(topologyExecutor2.getGroupExecutor(db2Group2)).thenReturn(groupExecutor4); + TGroupDataSource dataSource4 = mock(TGroupDataSource.class); + when(groupExecutor4.getDataSource()).thenReturn(dataSource4); + String dataSource4Address = "127.0.0.1:3004"; + when(dataSource4.getMasterSourceAddress()).thenReturn(dataSource4Address); + when(dataSource4.getMasterDNId()).thenReturn(dataSource4Address); + Connection connection4 = mock(Connection.class); + mockDbTopologyManager.when(() -> getConnectionForStorage(dataSource4Address)).thenReturn(connection4); + Statement statement4 = mock(Statement.class); + when(connection4.createStatement()).thenReturn(statement4); + ResultSet rs4 = mock2Results(db2db2.toLowerCase(), tb2p2.toLowerCase(), db2db2.toLowerCase(), + gsi2p2.toLowerCase()); + when(statement4.executeQuery(any())).then(invocation -> { + String sql = invocation.getArgument(0); + System.out.println(sql); + Assert.assertTrue(sql.contains("('" + db2db2.toLowerCase() + "', '" + tb2p2.toLowerCase() + "')")); + Assert.assertTrue(sql.contains("('" + db2db2.toLowerCase() + "', '" + gsi2p2.toLowerCase() + "'))")); + return rs4; + }); + + OptimizerContext optimizerContext2 = new OptimizerContext(db2); + OptimizerContext.loadContext(optimizerContext2); + // mock empty tddl rule manager + TddlRuleManager ruleManager2 = mock(TddlRuleManager.class); + optimizerContext2.setRuleManager(ruleManager2); + TddlRule tddlRule2 = mock(TddlRule.class); + when(ruleManager2.getTddlRule()).thenReturn(tddlRule2); + when(tddlRule2.getTables()).thenReturn(new ArrayList<>()); + // mock partition manager + PartitionInfoManager partitionInfoManager2 = mock(PartitionInfoManager.class); + optimizerContext2.setPartitionInfoManager(partitionInfoManager2); + PartitionInfo partitionInfo1 = mock(PartitionInfo.class); + PartitionInfo partitionInfo2 = mock(PartitionInfo.class); + when(partitionInfoManager2.getPartitionInfos()).thenReturn( + ImmutableList.of(partitionInfo1, partitionInfo2)); + when(partitionInfo1.getTableName()).thenReturn(tb2); + when(partitionInfo2.getTableName()).thenReturn(gsi2); + when(partitionInfoManager2.getPartitionInfo(tb2)).thenReturn(partitionInfo1); + when(partitionInfoManager2.getPartitionInfo(gsi2)).thenReturn(partitionInfo2); + PartitionByDefinition partitionByDefinition1 = mock(PartitionByDefinition.class); + when(partitionInfo1.getPartitionBy()).thenReturn(partitionByDefinition1); + PartitionSpec tb2PartitionSpec1 = mock(PartitionSpec.class); + PartitionSpec tb2PartitionSpec2 = mock(PartitionSpec.class); + when(partitionByDefinition1.getPhysicalPartitions()).thenReturn( + ImmutableList.of(tb2PartitionSpec1, tb2PartitionSpec2)); + PartitionLocation tb2Location1 = mock(PartitionLocation.class); + PartitionLocation tb2Location2 = mock(PartitionLocation.class); + when(tb2Location1.getGroupKey()).thenReturn(db2Group1); + when(tb2Location2.getGroupKey()).thenReturn(db2Group2); + when(tb2Location1.getPhyTableName()).thenReturn(tb2p1); + when(tb2Location2.getPhyTableName()).thenReturn(tb2p2); + when(tb2PartitionSpec1.getLocation()).thenReturn(tb2Location1); + when(tb2PartitionSpec2.getLocation()).thenReturn(tb2Location2); + + PartitionByDefinition partitionByDefinition2 = mock(PartitionByDefinition.class); + when(partitionInfo2.getPartitionBy()).thenReturn(partitionByDefinition2); + PartitionSpec gsi2PartitionSpec1 = mock(PartitionSpec.class); + PartitionSpec gsi2PartitionSpec2 = mock(PartitionSpec.class); + when(partitionByDefinition2.getPhysicalPartitions()).thenReturn( + ImmutableList.of(gsi2PartitionSpec1, gsi2PartitionSpec2)); + PartitionLocation gsi2Location1 = mock(PartitionLocation.class); + PartitionLocation gsi2Location2 = mock(PartitionLocation.class); + when(gsi2Location1.getGroupKey()).thenReturn(db2Group1); + when(gsi2Location2.getGroupKey()).thenReturn(db2Group2); + when(gsi2Location1.getPhyTableName()).thenReturn(gsi2p1); + when(gsi2Location2.getPhyTableName()).thenReturn(gsi2p2); + when(gsi2PartitionSpec1.getLocation()).thenReturn(gsi2Location1); + when(gsi2PartitionSpec2.getLocation()).thenReturn(gsi2Location2); + + // mock schema manager and table meta + SchemaManager schemaManager2 = mock(SchemaManager.class); + optimizerContext2.setSchemaManager(schemaManager2); + TableMeta tb2TableMeta = mock(TableMeta.class); + when(schemaManager2.getTable(tb2)).thenReturn(tb2TableMeta); + GsiMetaManager.GsiIndexMetaBean gsi2IndexMeta = mock(GsiMetaManager.GsiIndexMetaBean.class); + Map tb2Gsi = ImmutableMap.of( + gsi2, gsi2IndexMeta + ); + when(tb2TableMeta.getGsiPublished()).thenReturn(tb2Gsi); + when(partitionInfoManager2.isNewPartDbTable(tb2)).thenReturn(true); + + String tableLike = null; + ArrayResultCursor cursor = new ArrayResultCursor("TABLES"); + InformationSchemaTablesHandler.fetchAccurateInfoSchemaTables(schemaNames, tables, tableLike, cursor); + for (Row row : cursor.getRows()) { + String table = (String) row.getObject(2); + String schema = (String) row.getObject(1); + long dataLength = (long) row.getObject(9); + long indexLength = (long) row.getObject(11); + if (table.equals(tb1)) { + Assert.assertEquals(db1, schema); + Assert.assertEquals(200, dataLength); + Assert.assertEquals(400, indexLength); + } else if (table.equals(gsi1)) { + Assert.assertEquals(db1, schema); + Assert.assertEquals(200, dataLength); + Assert.assertEquals(0, indexLength); + } else if (table.equals(tb2)) { + Assert.assertEquals(db2, schema); + Assert.assertEquals(200, dataLength); + Assert.assertEquals(400, indexLength); + } else if (table.equals(gsi2)) { + Assert.assertEquals(db2, schema); + Assert.assertEquals(200, dataLength); + Assert.assertEquals(0, indexLength); + } + } + } + } + + @Test + public void testLike() throws SQLException { + try (MockedStatic mockDbTopologyManager = mockStatic(DbTopologyManager.class)) { + // mock mock + // db1: drds mode, contains table tb1, tb1 contains gsi gsi1 + // db2: auto mode, contains table tb2, tb2 contains gsi gsi2 + String db1 = "db1"; + String db1Group1 = "db1_00000_GROUP"; + String db1Group2 = "db1_00001_GROUP"; + String tb1 = "tb1"; + String tb1p1 = "tb1_qwer"; + String tb1p2 = "tb1_rtyu"; + + Set schemaNames = ImmutableSet.of(db1); + Set tables = ImmutableSet.of(tb1); + + // mock db1 + ExecutorContext executorContext1 = new ExecutorContext(); + ITopologyExecutor topologyExecutor1 = mock(ITopologyExecutor.class); + executorContext1.setTopologyExecutor(topologyExecutor1); + ExecutorContext.setContext(db1, executorContext1); + + IGroupExecutor groupExecutor1 = mock(IGroupExecutor.class); + when(topologyExecutor1.getGroupExecutor(db1Group1)).thenReturn(groupExecutor1); + TGroupDataSource dataSource1 = mock(TGroupDataSource.class); + when(groupExecutor1.getDataSource()).thenReturn(dataSource1); + String dataSource1Address = "127.0.0.1:3001"; + when(dataSource1.getMasterSourceAddress()).thenReturn(dataSource1Address); + when(dataSource1.getMasterDNId()).thenReturn(dataSource1Address); + OptimizedGroupConfigManager configManager1 = mock(OptimizedGroupConfigManager.class); + when(dataSource1.getConfigManager()).thenReturn(configManager1); + TAtomDataSource tAtomDataSource1 = mock(TAtomDataSource.class); + when(configManager1.getDataSource(any())).thenReturn(tAtomDataSource1); + TAtomDsConfHandle tAtomDsConfHandle1 = mock(TAtomDsConfHandle.class); + when(tAtomDataSource1.getDsConfHandle()).thenReturn(tAtomDsConfHandle1); + TAtomDsConfDO tAtomDsConfDO1 = mock(TAtomDsConfDO.class); + when(tAtomDsConfHandle1.getRunTimeConf()).thenReturn(tAtomDsConfDO1); + when(tAtomDsConfDO1.getDbName()).thenReturn(db1Group1); + Connection connection1 = mock(Connection.class); + mockDbTopologyManager.when(() -> getConnectionForStorage(dataSource1Address)).thenReturn(connection1); + Statement statement1 = mock(Statement.class); + when(connection1.createStatement()).thenReturn(statement1); + ResultSet rs1 = mock1Result1(db1Group1.toLowerCase(), tb1p1.toLowerCase()); + when(statement1.executeQuery(any())).then(invocation -> { + String sql = invocation.getArgument(0); + System.out.println(sql); + Assert.assertTrue(sql.contains("('" + db1Group1.toLowerCase() + "', '" + tb1p1.toLowerCase() + "')")); + return rs1; + }); + + IGroupExecutor groupExecutor2 = mock(IGroupExecutor.class); + when(topologyExecutor1.getGroupExecutor(db1Group2)).thenReturn(groupExecutor2); + TGroupDataSource dataSource2 = mock(TGroupDataSource.class); + when(groupExecutor2.getDataSource()).thenReturn(dataSource2); + String dataSource2Address = "127.0.0.1:3002"; + when(dataSource2.getMasterSourceAddress()).thenReturn(dataSource2Address); + when(dataSource2.getMasterDNId()).thenReturn(dataSource2Address); + OptimizedGroupConfigManager configManager2 = mock(OptimizedGroupConfigManager.class); + when(dataSource2.getConfigManager()).thenReturn(configManager2); + TAtomDataSource tAtomDataSource2 = mock(TAtomDataSource.class); + when(configManager2.getDataSource(any())).thenReturn(tAtomDataSource2); + TAtomDsConfHandle tAtomDsConfHandle2 = mock(TAtomDsConfHandle.class); + when(tAtomDataSource2.getDsConfHandle()).thenReturn(tAtomDsConfHandle2); + TAtomDsConfDO tAtomDsConfDO2 = mock(TAtomDsConfDO.class); + when(tAtomDsConfHandle2.getRunTimeConf()).thenReturn(tAtomDsConfDO2); + when(tAtomDsConfDO2.getDbName()).thenReturn(db1Group2); + Connection connection2 = mock(Connection.class); + mockDbTopologyManager.when(() -> getConnectionForStorage(dataSource2Address)).thenReturn(connection2); + Statement statement2 = mock(Statement.class); + when(connection2.createStatement()).thenReturn(statement2); + ResultSet rs2 = mock1Result1(db1Group2.toLowerCase(), tb1p2.toLowerCase()); + when(statement2.executeQuery(any())).then(invocation -> { + String sql = invocation.getArgument(0); + System.out.println(sql); + Assert.assertTrue(sql.contains("('" + db1Group2.toLowerCase() + "', '" + tb1p2.toLowerCase() + "')")); + return rs2; + }); + + OptimizerContext optimizerContext1 = new OptimizerContext(db1); + OptimizerContext.loadContext(optimizerContext1); + // mock tddl rule manager + TddlRuleManager ruleManager1 = mock(TddlRuleManager.class); + optimizerContext1.setRuleManager(ruleManager1); + TddlRule tddlRule = mock(TddlRule.class); + when(ruleManager1.getTddlRule()).thenReturn(tddlRule); + TableRule tb1TableRule = mock(TableRule.class); + Collection tableRules = ImmutableSet.of(tb1TableRule); + when(tddlRule.getTables()).thenReturn(tableRules); + when(tb1TableRule.getVirtualTbName()).thenReturn(tb1); + when(ruleManager1.getTableRule(tb1)).thenReturn(tb1TableRule); + Map> tb1Topologys = ImmutableMap.of( + db1Group1, ImmutableSet.of(tb1p1), + db1Group2, ImmutableSet.of(tb1p2) + ); + when(tb1TableRule.getStaticTopology()).thenReturn(tb1Topologys); + // mock empty partition manager + PartitionInfoManager partitionInfoManager1 = mock(PartitionInfoManager.class); + optimizerContext1.setPartitionInfoManager(partitionInfoManager1); + when(partitionInfoManager1.getPartitionInfos()).thenReturn(new ArrayList<>()); + // mock schema manager and table meta + SchemaManager schemaManager1 = mock(SchemaManager.class); + optimizerContext1.setSchemaManager(schemaManager1); + TableMeta tb1TableMeta = mock(TableMeta.class); + when(schemaManager1.getTable(tb1)).thenReturn(tb1TableMeta); + when(tb1TableMeta.getGsiPublished()).thenReturn(null); + + String tableLike = "%t%"; + ArrayResultCursor cursor = new ArrayResultCursor("TABLES"); + InformationSchemaTablesHandler.fetchAccurateInfoSchemaTables(schemaNames, tables, tableLike, cursor); + for (Row row : cursor.getRows()) { + String table = (String) row.getObject(2); + String schema = (String) row.getObject(1); + long dataLength = (long) row.getObject(9); + long indexLength = (long) row.getObject(11); + if (table.equals(tb1)) { + Assert.assertEquals(db1, schema); + Assert.assertEquals(200, dataLength); + Assert.assertEquals(200, indexLength); + } + } + } + + } + + private ArrayResultSet mock1Result1(String db1, String tb1) { + ArrayResultSet rs = mockColumn(); + rs.getRows().add(mockRow(db1, tb1)); + return rs; + } + + private ArrayResultSet mock2Results(String db1, String tb1, String db2, String tb2) { + ArrayResultSet rs = mockColumn(); + rs.getRows().add(mockRow(db1, tb1)); + rs.getRows().add(mockRow(db2, tb2)); + return rs; + } + + private ArrayResultSet mockColumn() { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("TABLE_SCHEMA"); + rs.getColumnName().add("TABLE_NAME"); + rs.getColumnName().add("VERSION"); + rs.getColumnName().add("ROW_FORMAT"); + rs.getColumnName().add("TABLE_ROWS"); + rs.getColumnName().add("AVG_ROW_LENGTH"); + rs.getColumnName().add("DATA_LENGTH"); + rs.getColumnName().add("MAX_DATA_LENGTH"); + rs.getColumnName().add("INDEX_LENGTH"); + rs.getColumnName().add("DATA_FREE"); + rs.getColumnName().add("AUTO_INCREMENT"); + rs.getColumnName().add("CREATE_TIME"); + rs.getColumnName().add("UPDATE_TIME"); + rs.getColumnName().add("CHECK_TIME"); + rs.getColumnName().add("TABLE_COLLATION"); + rs.getColumnName().add("CHECKSUM"); + rs.getColumnName().add("TABLE_COMMENT"); + rs.getColumnName().add("CREATE_OPTIONS"); + return rs; + } + + private Object[] mockRow(String db, String tb) { + return new Object[] { + db, + tb, + 10L, + "Dynamic", + 100L, + 64L, + 100L, + 0L, + 100L, + 100L, + "0", + "2024-01-01 00:00:00", + "2024-01-01 00:00:00", + "2024-01-01 00:00:00", + "utf8_general_ci", + "", + "", + "" + }; + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/discover/PolarDBXNodeStatusManagerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/discover/PolarDBXNodeStatusManagerTest.java new file mode 100644 index 000000000..edaae5260 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/discover/PolarDBXNodeStatusManagerTest.java @@ -0,0 +1,111 @@ +package com.alibaba.polardbx.executor.mpp.discover; + +import com.alibaba.polardbx.common.utils.InstanceRole; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.node.GmsNodeManager; +import com.alibaba.polardbx.gms.node.InternalNode; +import com.alibaba.polardbx.gms.node.NodeVersion; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +public class PolarDBXNodeStatusManagerTest { + + private Pair masterNodeInfo; + private Pair slaveNodeInfo; + private Pair columnarNodeInfo; + + @Before + public void setUp() throws Exception { + masterNodeInfo = getNodeAndGmsNode("master", false, 1); + slaveNodeInfo = getNodeAndGmsNode("salve", false, 2); + columnarNodeInfo = getNodeAndGmsNode("columnar", true, 4); + } + + private Pair getNodeAndGmsNode(String key, boolean htap, int instType) { + InternalNode node = new InternalNode(key, "cluster1", "inst1", "11.11.11.11", 1234, 12345, + NodeVersion.UNKNOWN, true, true, false, htap); + GmsNodeManager.GmsNode gmsNode = new GmsNodeManager.GmsNode(); + gmsNode.instType = instType; + return Pair.of(node, gmsNode); + } + + @Test + public void testUpdateHeartbeatStatus() { + + String sql = generateUpdateStatusSql(masterNodeInfo, 1, InstanceRole.MASTER); + + Assert.assertTrue(sql.contains("TIMESTAMPDIFF")); + + } + + @Test + public void testUpdateInactiveStatus() { + + String sql = generateUpdateStatusSql(masterNodeInfo, 0, InstanceRole.MASTER); + + Assert.assertTrue(!sql.contains("ROLE") && !sql.contains("TIMESTAMPDIFF")); + + } + + @Test + public void testUpdateSlaveStatus() { + + String sql = generateUpdateStatusSql(slaveNodeInfo, 1, InstanceRole.ROW_SLAVE); + + Assert.assertTrue(sql.contains("ROLE") && !sql.contains("TIMESTAMPDIFF")); + + } + + @Test + public void testUpdateColumnarStatus() { + + String sql = generateUpdateStatusSql(columnarNodeInfo, 1, InstanceRole.COLUMNAR_SLAVE); + + Assert.assertTrue(sql.contains("ROLE") && !sql.contains("TIMESTAMPDIFF")); + + } + + @Test + public void testRole() { + PolarDBXNodeStatusManager polarDBXNodeStatusManager = + spy(new PolarDBXNodeStatusManager(null, masterNodeInfo.getKey())); + + int role = polarDBXNodeStatusManager.getRole(columnarNodeInfo.getKey()); + Assert.assertEquals(39, role); + try (final MockedStatic mockConfigDataMode = mockStatic(ConfigDataMode.class);) { + when(ConfigDataMode.isColumnarMode()).thenReturn(true); + role = polarDBXNodeStatusManager.getRole(columnarNodeInfo.getKey()); + Assert.assertEquals(67, role); + } + } + + private String generateUpdateStatusSql(Pair nodeinfo, int status, + InstanceRole role) { + ClusterNodeManager nodeManager = new ClusterNodeManager(nodeinfo.getKey(), null, null, null); + PolarDBXNodeStatusManager polarDBXNodeStatusManager = + spy(new PolarDBXNodeStatusManager(nodeManager, nodeinfo.getKey())); + + Mockito.doNothing().when(polarDBXNodeStatusManager).init(); + + GmsNodeManager gmsNodeManager = mock(GmsNodeManager.class); + + try (final MockedStatic mockGmsNodeManagerStatic = mockStatic(GmsNodeManager.class); + final MockedStatic mockConfigDataMode = mockStatic(ConfigDataMode.class);) { + when(GmsNodeManager.getInstance()).thenReturn(gmsNodeManager); + when(ConfigDataMode.getInstanceRole()).thenReturn(role); + when(ConfigDataMode.isRowSlaveMode()).thenReturn(role == InstanceRole.ROW_SLAVE); + when(gmsNodeManager.getLocalNode()).thenReturn(nodeinfo.getValue()); + String sql = polarDBXNodeStatusManager.updateTableMetaSql(status); + return sql; + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/execution/SqlQueryLocalExecutionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/execution/SqlQueryLocalExecutionTest.java new file mode 100644 index 000000000..360933f29 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/execution/SqlQueryLocalExecutionTest.java @@ -0,0 +1,44 @@ +package com.alibaba.polardbx.executor.mpp.execution; + +import com.alibaba.polardbx.executor.mpp.metadata.Split; +import org.junit.Test; +import org.junit.Before; +import org.mockito.Mock; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertTrue; + +import org.mockito.MockitoAnnotations; + +public class SqlQueryLocalExecutionTest { + + @Mock + SqlQueryLocalExecution sqlQueryLocalExecution; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testGetRandomStartWithNonEmptyList() { + List splits = new ArrayList<>(); + splits.add(Split.EMPTY_SPLIT); + splits.add(new Split(false, null)); + + int randomStart = sqlQueryLocalExecution.getRandomStart(splits); + assertTrue("Expected randomStart to be within the bounds of the list", + randomStart >= 0 && randomStart < splits.size()); + } + + @Test + public void testGetRandomStartWithEmptyList() { + List splits = Collections.emptyList(); + + int randomStart = sqlQueryLocalExecution.getRandomStart(splits); + assertTrue("Expected randomStart to be 0 for an empty list", randomStart == 0); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/ColumnarNodeSelectorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/ColumnarNodeSelectorTest.java index 958413e3b..ba146d455 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/ColumnarNodeSelectorTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/execution/scheduler/ColumnarNodeSelectorTest.java @@ -1,13 +1,14 @@ package com.alibaba.polardbx.executor.mpp.execution.scheduler; import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.executor.mpp.execution.NodeTaskMap; +import com.alibaba.polardbx.executor.mpp.metadata.Split; import com.alibaba.polardbx.executor.mpp.split.OssSplit; import com.alibaba.polardbx.gms.node.InternalNode; import com.alibaba.polardbx.gms.node.InternalNodeManager; import com.alibaba.polardbx.gms.node.Node; -import com.alibaba.polardbx.executor.mpp.metadata.Split; -import com.alibaba.polardbx.executor.mpp.execution.NodeTaskMap; import com.alibaba.polardbx.gms.node.NodeVersion; +import com.alibaba.polardbx.optimizer.utils.PartitionUtils; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableList; import com.google.common.collect.Multimap; @@ -21,7 +22,8 @@ import java.util.List; import java.util.Set; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class ColumnarNodeSelectorTest { @@ -54,8 +56,8 @@ public void testScheduleOssSplit() { List splits = ImmutableList.of(new Split(true, split)); NodeAssignmentStats assignmentStats = mock(NodeAssignmentStats.class); Multimap assignment = HashMultimap.create(); - try (MockedStatic theMock = Mockito.mockStatic(OssSplit.class)) { - when(OssSplit.calcPartition("test", "test", "test", "test")).thenReturn(1); + try (MockedStatic theMock = Mockito.mockStatic(PartitionUtils.class)) { + when(PartitionUtils.calcPartition("test", "test", "test", "test")).thenReturn(1); Multimap result = nodeSelector.scheduleOssSplit(splits, candidateNodes, assignmentStats, assignment); diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/operator/RFBlockTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/operator/RFBlockTest.java new file mode 100644 index 000000000..899df563d --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/operator/RFBlockTest.java @@ -0,0 +1,289 @@ +package com.alibaba.polardbx.executor.mpp.operator; + +import com.alibaba.polardbx.common.utils.XxhashUtils; +import com.alibaba.polardbx.common.utils.bloomfilter.RFBloomFilter; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.ByteBlock; +import com.alibaba.polardbx.executor.chunk.ByteBlockBuilder; +import com.alibaba.polardbx.executor.chunk.IntegerBlock; +import com.alibaba.polardbx.executor.chunk.IntegerBlockBuilder; +import com.alibaba.polardbx.executor.chunk.ShortBlock; +import com.alibaba.polardbx.executor.chunk.ShortBlockBuilder; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; + +public class RFBlockTest { + static final int CHUNK_LIMIT = 1000; + + @Test + public void testByteBroadcast() { + RFBloomFilter bloomFilter = RFBloomFilter.createBlockLongBloomFilter(CHUNK_LIMIT * 4); + + ByteBlockBuilder byteBlockBuilder = new ByteBlockBuilder(1024); + for (int i = 0; i < CHUNK_LIMIT; i++) { + byteBlockBuilder.writeByte((byte) ((i % 128) * 2)); + } + ByteBlock block = (ByteBlock) byteBlockBuilder.build(); + block.addLongToBloomFilter(bloomFilter); + + byteBlockBuilder = new ByteBlockBuilder(1024); + for (int i = 0; i < CHUNK_LIMIT; i++) { + byteBlockBuilder.writeByte((byte) (i % 128)); + } + block = (ByteBlock) byteBlockBuilder.build(); + + boolean[] bitmap = new boolean[CHUNK_LIMIT]; + Arrays.fill(bitmap, true); + block.mightContainsLong(bloomFilter, bitmap, true); + + for (int i = 0; i < bitmap.length; i++) { + if (i % 2 == 0) { + Assert.assertTrue(bitmap[i]); + } + } + } + + @Test + public void testByteLocal() { + final int partitionCount = 4; + + RFBloomFilter[] bloomFilters = new RFBloomFilter[partitionCount]; + for (int part = 0; part < partitionCount; part++) { + bloomFilters[part] = RFBloomFilter.createBlockLongBloomFilter(CHUNK_LIMIT * 4); + } + + ByteBlockBuilder[] byteBlockBuilders = new ByteBlockBuilder[partitionCount]; + for (int part = 0; part < partitionCount; part++) { + byteBlockBuilders[part] = new ByteBlockBuilder(CHUNK_LIMIT); + } + + // write values into different partition. + for (int i = 0; i < 3 * CHUNK_LIMIT; i++) { + int val = (i % 128) * 2; + int targetPart = getPartition(val, partitionCount); + byteBlockBuilders[targetPart].writeByte((byte) val); + } + ByteBlock[] byteBlocks = new ByteBlock[partitionCount]; + for (int part = 0; part < partitionCount; part++) { + byteBlocks[part] = (ByteBlock) byteBlockBuilders[part].build(); + + // add to rf. + byteBlocks[part].addLongToBloomFilter(bloomFilters[part]); + } + + // build blocks for checking. + for (int part = 0; part < partitionCount; part++) { + byteBlockBuilders[part] = new ByteBlockBuilder(CHUNK_LIMIT); + } + for (int i = 0; i < 3 * CHUNK_LIMIT; i++) { + int val = i % 128; + int targetPart = getPartition(val, partitionCount); + byteBlockBuilders[targetPart].writeByte((byte) val); + } + for (int part = 0; part < partitionCount; part++) { + byteBlocks[part] = (ByteBlock) byteBlockBuilders[part].build(); + } + + // assert + for (int part = 0; part < partitionCount; part++) { + Block block = byteBlocks[part]; + + boolean[] bitmap = new boolean[CHUNK_LIMIT]; + Arrays.fill(bitmap, true); + block.mightContainsLong(bloomFilters[part], bitmap, true); + + System.out.println(Arrays.toString(bitmap)); + + for (int i = 0; i < block.getPositionCount(); i++) { + if (block.getLong(i) % 2 == 0) { + Assert.assertTrue(bitmap[i]); + } + } + } + } + + @Test + public void testShortBroadcast() { + RFBloomFilter bloomFilter = RFBloomFilter.createBlockLongBloomFilter(CHUNK_LIMIT * 4); + + ShortBlockBuilder shortBlockBuilder = new ShortBlockBuilder(1024); + for (int i = 0; i < CHUNK_LIMIT; i++) { + shortBlockBuilder.writeShort((short) ((i % 65536) * 2)); + } + ShortBlock block = (ShortBlock) shortBlockBuilder.build(); + block.addLongToBloomFilter(bloomFilter); + + shortBlockBuilder = new ShortBlockBuilder(1024); + for (int i = 0; i < CHUNK_LIMIT; i++) { + shortBlockBuilder.writeShort((short) (i % 65536)); + } + block = (ShortBlock) shortBlockBuilder.build(); + + boolean[] bitmap = new boolean[CHUNK_LIMIT]; + Arrays.fill(bitmap, true); + block.mightContainsLong(bloomFilter, bitmap, true); + + for (int i = 0; i < bitmap.length; i++) { + if (i % 2 == 0) { + Assert.assertTrue(bitmap[i]); + } + } + } + + @Test + public void testShortLocal() { + final int partitionCount = 4; + + RFBloomFilter[] bloomFilters = new RFBloomFilter[partitionCount]; + for (int part = 0; part < partitionCount; part++) { + bloomFilters[part] = RFBloomFilter.createBlockLongBloomFilter(CHUNK_LIMIT * 4); + } + + ShortBlockBuilder[] shortBlockBuilders = new ShortBlockBuilder[partitionCount]; + for (int part = 0; part < partitionCount; part++) { + shortBlockBuilders[part] = new ShortBlockBuilder(CHUNK_LIMIT); + } + + // write values into different partition. + for (int i = 0; i < 3 * CHUNK_LIMIT; i++) { + int val = (i % 65536) * 2; + int targetPart = getPartition(val, partitionCount); + shortBlockBuilders[targetPart].writeShort((short) val); + } + ShortBlock[] shortBlocks = new ShortBlock[partitionCount]; + for (int part = 0; part < partitionCount; part++) { + shortBlocks[part] = (ShortBlock) shortBlockBuilders[part].build(); + + // add to rf. + shortBlocks[part].addLongToBloomFilter(bloomFilters[part]); + } + + // build blocks for checking. + for (int part = 0; part < partitionCount; part++) { + shortBlockBuilders[part] = new ShortBlockBuilder(CHUNK_LIMIT); + } + for (int i = 0; i < 3 * CHUNK_LIMIT; i++) { + int val = i % 65536; + int targetPart = getPartition(val, partitionCount); + shortBlockBuilders[targetPart].writeShort((short) val); + } + for (int part = 0; part < partitionCount; part++) { + shortBlocks[part] = (ShortBlock) shortBlockBuilders[part].build(); + } + + // assert + for (int part = 0; part < partitionCount; part++) { + Block block = shortBlocks[part]; + + boolean[] bitmap = new boolean[CHUNK_LIMIT]; + Arrays.fill(bitmap, true); + block.mightContainsLong(bloomFilters[part], bitmap, true); + + System.out.println(Arrays.toString(bitmap)); + + for (int i = 0; i < block.getPositionCount(); i++) { + if (block.getLong(i) % 2 == 0) { + Assert.assertTrue(bitmap[i]); + } + } + } + } + + @Test + public void testIntBroadcast() { + RFBloomFilter bloomFilter = RFBloomFilter.createBlockLongBloomFilter(CHUNK_LIMIT * 4); + + IntegerBlockBuilder intBlockBuilder = new IntegerBlockBuilder(1024); + for (int i = 0; i < CHUNK_LIMIT; i++) { + intBlockBuilder.writeInt(i * 2); + } + IntegerBlock block = (IntegerBlock) intBlockBuilder.build(); + block.addLongToBloomFilter(bloomFilter); + + intBlockBuilder = new IntegerBlockBuilder(1024); + for (int i = 0; i < CHUNK_LIMIT; i++) { + intBlockBuilder.writeInt(i); + } + block = (IntegerBlock) intBlockBuilder.build(); + + boolean[] bitmap = new boolean[CHUNK_LIMIT]; + Arrays.fill(bitmap, true); + block.mightContainsLong(bloomFilter, bitmap, true); + + for (int i = 0; i < bitmap.length; i++) { + if (i % 2 == 0) { + Assert.assertTrue(bitmap[i]); + } + } + } + + @Test + public void testIntLocal() { + final int partitionCount = 4; + + RFBloomFilter[] bloomFilters = new RFBloomFilter[partitionCount]; + for (int part = 0; part < partitionCount; part++) { + bloomFilters[part] = RFBloomFilter.createBlockLongBloomFilter(CHUNK_LIMIT * 4); + } + + IntegerBlockBuilder[] intBlockBuilders = new IntegerBlockBuilder[partitionCount]; + for (int part = 0; part < partitionCount; part++) { + intBlockBuilders[part] = new IntegerBlockBuilder(CHUNK_LIMIT); + } + + // write values into different partition. + for (int i = 0; i < 3 * CHUNK_LIMIT; i++) { + int val = i * 2; + int targetPart = getPartition(val, partitionCount); + intBlockBuilders[targetPart].writeInt(val); + } + IntegerBlock[] intBlocks = new IntegerBlock[partitionCount]; + for (int part = 0; part < partitionCount; part++) { + intBlocks[part] = (IntegerBlock) intBlockBuilders[part].build(); + + // add to rf. + intBlocks[part].addLongToBloomFilter(bloomFilters[part]); + } + + // build blocks for checking. + for (int part = 0; part < partitionCount; part++) { + intBlockBuilders[part] = new IntegerBlockBuilder(CHUNK_LIMIT); + } + for (int i = 0; i < 3 * CHUNK_LIMIT; i++) { + int val = i % 65536; + int targetPart = getPartition(val, partitionCount); + intBlockBuilders[targetPart].writeInt(val); + } + for (int part = 0; part < partitionCount; part++) { + intBlocks[part] = (IntegerBlock) intBlockBuilders[part].build(); + } + + // assert + for (int part = 0; part < partitionCount; part++) { + Block block = intBlocks[part]; + + boolean[] bitmap = new boolean[CHUNK_LIMIT]; + Arrays.fill(bitmap, true); + block.mightContainsLong(bloomFilters[part], bitmap, true); + + System.out.println(Arrays.toString(bitmap)); + + for (int i = 0; i < block.getPositionCount(); i++) { + if (block.getLong(i) % 2 == 0) { + Assert.assertTrue(bitmap[i]); + } + } + } + } + + private static int getPartition(long longVal, int partitionCount) { + + // Convert the searchVal from field space to hash space + long hashVal = XxhashUtils.finalShuffle(longVal); + int partition = (int) ((hashVal & Long.MAX_VALUE) % partitionCount); + + return partition; + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/operator/RFLazyEvaluatorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/operator/RFLazyEvaluatorTest.java index 8ed355f3b..f544bc67c 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/operator/RFLazyEvaluatorTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/operator/RFLazyEvaluatorTest.java @@ -8,6 +8,7 @@ import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.chunk.LongBlock; import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.executor.chunk.NullBlock; import com.alibaba.polardbx.executor.mpp.planner.FragmentRFItem; import com.alibaba.polardbx.executor.mpp.planner.FragmentRFItemImpl; import com.alibaba.polardbx.executor.mpp.planner.FragmentRFItemKey; @@ -242,4 +243,38 @@ public void testLocalRF() { } } + + @Test + public void testNoRFWithDeletion() { + OperatorStatistics operatorStatistics = new OperatorStatistics(); + + // Initialize FragmentRFManager + int totalPartitionCount = PARTITION_COUNT; + double defaultFpp = 0.1d; + int rowUpperBound = 100000; + int rowLowerBound = 4096; + double filterRatioThreshold = 0.25d; + int rfSampleCount = 10; + FragmentRFManager manager = new SimpleFragmentRFManager( + totalPartitionCount, 1, defaultFpp, + rowUpperBound, rowLowerBound, + filterRatioThreshold, rfSampleCount + ); + + RFLazyEvaluator evaluator = new RFLazyEvaluator(manager, operatorStatistics, new HashMap<>()); + + // empty + RoaringBitmap deletion = new RoaringBitmap(); + deletion.add(1, 3, 5, 7, 1001, 1005, 1007, 1010, 1099); + boolean[] bitmap = new boolean[CHUNK_LIMIT]; + + // evaluate and check the filter ratio. + Chunk chunk = new Chunk(CHUNK_LIMIT, new NullBlock(CHUNK_LIMIT)); + int selectionCount = evaluator.eval(chunk, 0, CHUNK_LIMIT, deletion, bitmap); + Assert.assertTrue(selectionCount == (CHUNK_LIMIT - 4)); + + chunk = new Chunk(CHUNK_LIMIT, new NullBlock(CHUNK_LIMIT)); + selectionCount = evaluator.eval(chunk, CHUNK_LIMIT, CHUNK_LIMIT, deletion, bitmap); + Assert.assertTrue(selectionCount == (CHUNK_LIMIT - 5)); + } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/operator/RangeScanModeTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/operator/RangeScanModeTest.java new file mode 100644 index 000000000..cc85ec868 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/operator/RangeScanModeTest.java @@ -0,0 +1,44 @@ +package com.alibaba.polardbx.executor.mpp.operator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +public class RangeScanModeTest { + + @Test + public void testGetModeWithSerialize() { + assertEquals(RangeScanMode.SERIALIZE, RangeScanMode.getMode("serialize")); + assertEquals(RangeScanMode.SERIALIZE, RangeScanMode.getMode("Serialize")); + assertEquals(RangeScanMode.SERIALIZE, RangeScanMode.getMode("SERIALIZE")); + } + + @Test + public void testGetModeWithNormal() { + assertEquals(RangeScanMode.NORMAL, RangeScanMode.getMode("normal")); + assertEquals(RangeScanMode.NORMAL, RangeScanMode.getMode("Normal")); + assertEquals(RangeScanMode.NORMAL, RangeScanMode.getMode("NORMAL")); + } + + @Test + public void testGetModeWithAdaptive() { + assertEquals(RangeScanMode.ADAPTIVE, RangeScanMode.getMode("adaptive")); + assertEquals(RangeScanMode.ADAPTIVE, RangeScanMode.getMode("Adaptive")); + assertEquals(RangeScanMode.ADAPTIVE, RangeScanMode.getMode("ADAPTIVE")); + } + + @Test + public void testGetModeWithInvalidMode() { + assertNull(RangeScanMode.getMode("invalid")); + assertNull(RangeScanMode.getMode("")); + assertNull(RangeScanMode.getMode(null)); + } + + @Test + public void testIsNormalMode() { + assertEquals(true, RangeScanMode.NORMAL.isNormalMode()); + assertEquals(false, RangeScanMode.SERIALIZE.isNormalMode()); + assertEquals(false, RangeScanMode.ADAPTIVE.isNormalMode()); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/planner/RangeScanUtilsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/planner/RangeScanUtilsTest.java new file mode 100644 index 000000000..5a0be4715 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/planner/RangeScanUtilsTest.java @@ -0,0 +1,50 @@ +package com.alibaba.polardbx.executor.mpp.planner; + +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.executor.mpp.operator.RangeScanMode; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.Assert.assertEquals; + +public class RangeScanUtilsTest { + + private ExecutionContext context; + @Mock + private LogicalView logicalView; + + @Before + public void setUp() { + context = new ExecutionContext(); + MockitoAnnotations.initMocks(this); + } + + @Test + public void testDetermineRangeScanModeWhenRangeScanModeIsSet() { + context.putIntoHintCmds(ConnectionProperties.RANGE_SCAN_MODE, "SERIALIZE"); + + RangeScanMode result = RangeScanUtils.determinRangeScanMode(logicalView, context, false); + assertEquals(RangeScanMode.SERIALIZE, result); + } + + @Test + public void testDetermineRangeScanModeWhenRootIsMergeSort() { + context.putIntoHintCmds(ConnectionProperties.RANGE_SCAN_MODE, null); + + RangeScanMode result = RangeScanUtils.determinRangeScanMode(logicalView, context, true); + assertEquals(RangeScanMode.ADAPTIVE, result); + } + + @Test + public void testDetermineRangeScanModeWhenRootIsNotMergeSort() { + context.putIntoHintCmds(ConnectionProperties.RANGE_SCAN_MODE, null); + + RangeScanMode result = RangeScanUtils.determinRangeScanMode(logicalView, context, false); + assertEquals(RangeScanMode.NORMAL, result); + } + +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/split/OssSplitTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/split/OssSplitTest.java new file mode 100644 index 000000000..dd255a715 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/split/OssSplitTest.java @@ -0,0 +1,558 @@ +package com.alibaba.polardbx.executor.mpp.split; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.jdbc.Parameters; +import com.alibaba.polardbx.common.jdbc.RawString; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.gms.MultiVersionColumnarSchema; +import com.alibaba.polardbx.executor.gms.util.ColumnarTransactionUtils; +import com.alibaba.polardbx.executor.mpp.metadata.Split; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPartitionEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.metadb.table.FilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.FilesRecordSimplified; +import com.alibaba.polardbx.gms.metadb.table.TableStatus; +import com.alibaba.polardbx.gms.partition.TablePartitionRecord; +import com.alibaba.polardbx.gms.tablegroup.PartitionGroupAccessor; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.Field; +import com.alibaba.polardbx.optimizer.config.table.FileMeta; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; +import com.alibaba.polardbx.optimizer.core.dialect.DbType; +import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; +import com.alibaba.polardbx.optimizer.core.rel.OrcTableScan; +import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation; +import com.alibaba.polardbx.optimizer.core.rel.PhyTableScanBuilder; +import com.alibaba.polardbx.optimizer.core.rel.PushDownOpt; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager; +import com.alibaba.polardbx.optimizer.utils.CalciteUtils; +import com.alibaba.polardbx.optimizer.utils.OptimizerUtils; +import com.alibaba.polardbx.optimizer.utils.PushDownUtils; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import org.apache.calcite.jdbc.JavaTypeFactoryImpl; +import org.apache.calcite.plan.ConventionTraitDef; +import org.apache.calcite.plan.RelOptCluster; +import org.apache.calcite.plan.RelOptTable; +import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.plan.volcano.VolcanoPlanner; +import org.apache.calcite.rel.RelPartitionWise; +import org.apache.calcite.rel.logical.LogicalFilter; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rel.type.RelDataTypeSystem; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexInputRef; +import org.apache.calcite.rex.RexLiteral; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.type.SqlTypeFactoryImpl; +import org.apache.calcite.sql.type.SqlTypeName; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnitRunner; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static com.alibaba.polardbx.executor.gms.MultiVersionColumnarSchemaTest.PARTITION_GROUP_RECORDS; +import static com.alibaba.polardbx.optimizer.config.table.OrcMetaUtils.TYPE_FACTORY; +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class OssSplitTest { + + @Mock + private OSSTableScan ossTableScan; + @Mock + private OrcTableScan orcTableScan; + @Mock + private PhyTableOperation relNode; + @Mock + private PhyTableScanBuilder phyTableScanBuilder; + @Mock + private SchemaManager schemaManager; + @Mock + private TableMeta tableMeta; + @Mock + private PartitionInfo partitionInfo; + @Mock + private RelTraitSet relTraitSet; + @Mock + private RelPartitionWise relPartitionWise; + @Mock + private ParamManager paramManager; + @Mock + private FileMeta fileMeta; + + private SortedMap partitionInfos; + + private MockedStatic mockMetaDbUtil; + private MockedStatic columnarTransactionUtilsMockedStatic; + + private MockedConstruction tableMappingAccessorCtor; + private MockedConstruction filesAccessorCtor; + private MockedConstruction cafAccessorCtor; + private MockedConstruction partitionGroupAccessorMockedConstruction; + private MockedConstruction csMockedConstruction; + + private AutoCloseable autoCloseable; + + private static final List CAF_RECORDS = + ImmutableList.of(buildCafRecord("1.csv", "p0", 100L, 100L), + buildCafRecord("1.del", "p0", 200L, 100L)); + + private static final List FILES_RECORDS = + ImmutableList.of(buildFileRecord("1.orc", "p0", 1L, 3L, 1L), + buildFileRecord("1.csv", "p0", 1L, 3L, 1L), + buildFileRecord("1.del", "p0", 1L, 3L, 1L), + buildFileRecord("WRONG.orc", "p1", 1L, 3L, 1L)); + + private static final List COLUMN_METAS = + ImmutableList.of(new ColumnMeta("1", "id", null, + new Field("1", "id", TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT)))); + + private static final List PARTITION_RECORDS = + ImmutableList.of(ColumnarPartitionEvolutionRecord.deserializeFromJson( + "{\"groupId\": 10, \"tblType\": 7, \"autoFlag\": 0, \"parentId\": -1, \"partDesc\": \"\", \"partExpr\": \"\", \"partName\": \"\", \"phyTable\": \"\", \"nextLevel\": 1, \"partFlags\": 0, \"partLevel\": 0, \"tableName\": \"cci1_$39a1\", \"partEngine\": \"\", \"partExtras\": \"{\\\"charset\\\":\\\"utf8\\\",\\\"locality\\\":\\\"\\\",\\\"partitionPattern\\\":\\\"cci1_$39a1_2zTE\\\",\\\"timeZone\\\":\\\"SYSTEM\\\"}\", \"partMethod\": \"\", \"partStatus\": 1, \"spTempFlag\": -1, \"metaVersion\": 1, \"partComment\": \"\", \"tableSchema\": \"db1\", \"partPosition\": -1, \"partTempName\": \"\"}"), + ColumnarPartitionEvolutionRecord.deserializeFromJson( + "{\"groupId\": 29, \"tblType\": 7, \"autoFlag\": 0, \"parentId\": 44, \"partDesc\": \"10000\", \"partExpr\": \"`id`\", \"partName\": \"p0\", \"phyTable\": \"cci1_$39a1_2zTE_00000\", \"nextLevel\": -1, \"partFlags\": 0, \"partLevel\": 1, \"tableName\": \"cci1_$39a1\", \"partEngine\": \"Columnar\", \"partExtras\": \"{\\\"locality\\\":\\\"\\\"}\", \"partMethod\": \"RANGE\", \"partStatus\": 0, \"spTempFlag\": -1, \"metaVersion\": 1, \"partComment\": \"\", \"tableSchema\": \"db1\", \"partPosition\": 1, \"partTempName\": \"\"}"), + ColumnarPartitionEvolutionRecord.deserializeFromJson( + "{\"groupId\": 30, \"tblType\": 7, \"autoFlag\": 0, \"parentId\": 44, \"partDesc\": \"20000\", \"partExpr\": \"`id`\", \"partName\": \"p1\", \"phyTable\": \"cci1_$39a1_2zTE_00001\", \"nextLevel\": -1, \"partFlags\": 0, \"partLevel\": 1, \"tableName\": \"cci1_$39a1\", \"partEngine\": \"Columnar\", \"partExtras\": \"{\\\"locality\\\":\\\"\\\"}\", \"partMethod\": \"RANGE\", \"partStatus\": 0, \"spTempFlag\": -1, \"metaVersion\": 1, \"partComment\": \"\", \"tableSchema\": \"db1\", \"partPosition\": 2, \"partTempName\": \"\"}")); + + private final ExecutionContext executionContext = new ExecutionContext(); + + @Before + public void setUp() throws Exception { + autoCloseable = MockitoAnnotations.openMocks(this); + when(relNode.getSchemaName()).thenReturn("db1"); + when(relNode.getDbIndex()).thenReturn("db1_0"); + when(relNode.getLogicalTableNames()).thenReturn(ImmutableList.of("t1")); + when(relNode.getTableNames()).thenReturn(ImmutableList.of(ImmutableList.of("t1_0"))); + when(relNode.getPhyOperationBuilder()).thenReturn(phyTableScanBuilder); + executionContext.setSchemaManager("db1", schemaManager); + executionContext.setParamManager(paramManager); + when(schemaManager.getTable(anyString())).thenReturn(tableMeta); + + mockMetaDbUtil = Mockito.mockStatic(MetaDbUtil.class); + mockMetaDbUtil.when(MetaDbUtil::getConnection).thenReturn(Mockito.mock(Connection.class)); + mockMetaDbUtil.when(() -> MetaDbUtil.queryMetaDbWrapper(Mockito.any(), Mockito.any())).thenCallRealMethod(); + + ColumnarTableMappingRecord record = new ColumnarTableMappingRecord("db1", "t1", "cci1_$39a1", 1, "PUBLIC"); + record.tableId = 1; + tableMappingAccessorCtor = Mockito.mockConstruction(ColumnarTableMappingAccessor.class, (mock, context) -> { + when(mock.querySchemaIndex(anyString(), anyString())) + .thenReturn(ImmutableList.of(record)); + }); + + when(tableMeta.getPartitionInfo()).thenReturn(partitionInfo); + when(partitionInfo.getPartitionNameByPhyLocation(anyString(), anyString())).thenReturn("p0"); + + when(ossTableScan.getOrcNode()).thenReturn(orcTableScan); + when(ossTableScan.getTraitSet()).thenReturn(relTraitSet); + when(ossTableScan.getSchemaName()).thenReturn("db1"); + when(ossTableScan.getLogicalTableName()).thenReturn("t1"); + when(ossTableScan.isNewPartDbTbl()).thenReturn(true); + when(relTraitSet.getPartitionWise()).thenReturn(relPartitionWise); + when(relPartitionWise.isRemotePartition()).thenReturn(false); + when(relPartitionWise.isLocalPartition()).thenReturn(false); + when(orcTableScan.getInProjects()).thenReturn(ImmutableList.of()); + + partitionGroupAccessorMockedConstruction = Mockito.mockConstruction( + PartitionGroupAccessor.class, + (mock, context) -> { + Mockito.when(mock.getPartitionGroupsByTableGroupId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(Arrays.asList(PARTITION_GROUP_RECORDS)); + }); + + ColumnarManager.getInstance().reload(); + } + + public void setUpForFlashback() { + when(ossTableScan.isColumnarIndex()).thenReturn(true); + when(ossTableScan.isFlashbackQuery()).thenReturn(true); + + columnarTransactionUtilsMockedStatic = Mockito.mockStatic(ColumnarTransactionUtils.class); + columnarTransactionUtilsMockedStatic.when(ColumnarTransactionUtils::getLatestTsoFromGms).thenReturn(2L); + columnarTransactionUtilsMockedStatic.when(ColumnarTransactionUtils::getMinColumnarSnapshotTime) + .thenReturn(1L); + + filesAccessorCtor = Mockito.mockConstruction(FilesAccessor.class, (mock, context) -> { + when(mock.queryColumnarSnapshotFilesByTsoAndTableId(anyLong(), anyString(), anyString())) + .thenReturn(FILES_RECORDS); + }); + + cafAccessorCtor = Mockito.mockConstruction(ColumnarAppendedFilesAccessor.class, (mock, context) -> { + when(mock.queryLastValidAppendByTsoAndTableId(anyLong(), anyString(), anyString())) + .thenReturn(CAF_RECORDS); + }); + } + + public void setUpForColumnar() { + when(ossTableScan.isColumnarIndex()).thenReturn(true); + when(ossTableScan.isFlashbackQuery()).thenReturn(false); + + columnarTransactionUtilsMockedStatic = Mockito.mockStatic(ColumnarTransactionUtils.class); + columnarTransactionUtilsMockedStatic.when(ColumnarTransactionUtils::getLatestTsoFromGms).thenReturn(2L); + columnarTransactionUtilsMockedStatic.when(ColumnarTransactionUtils::getMinColumnarSnapshotTime) + .thenReturn(1L); + filesAccessorCtor = Mockito.mockConstruction(FilesAccessor.class, (mock, context) -> { + when(mock.queryColumnarDeltaFilesByTsoAndTableId(anyLong(), anyLong(), anyString(), anyString())) + .thenReturn(FILES_RECORDS); + }); + } + + public void setUpForSharding() { + partitionInfos = new ConcurrentSkipListMap<>(); + // TODO(siyun): add more test cases + partitionInfos.put(1L, + PartitionInfoManager.generatePartitionInfo(COLUMN_METAS, PARTITION_RECORDS, null, false, false)); + partitionInfos.put(2L, + PartitionInfoManager.generatePartitionInfo(COLUMN_METAS, PARTITION_RECORDS, null, false, false)); + csMockedConstruction = Mockito.mockConstruction(MultiVersionColumnarSchema.class, (mock, context) -> { + when(mock.getPartitionInfos(anyLong(), anyLong())).thenReturn(partitionInfos); + }); + + ColumnarManager.getInstance().reload(); + + VolcanoPlanner planner = new VolcanoPlanner(new PlannerContext(executionContext)); + planner.addRelTraitDef(ConventionTraitDef.INSTANCE); + final RelDataTypeFactory typeFactory = new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + RelOptCluster cluster = RelOptCluster.create(planner, new RexBuilder(typeFactory)); + + RelOptTable mockTable = mock(RelOptTable.class); + when(mockTable.getQualifiedName()).thenReturn(ImmutableList.of("db1", "t1")); + when(ossTableScan.getTable()).thenReturn(mockTable); + when(ossTableScan.getCluster()).thenReturn(cluster); + when(tableMeta.getStatus()).thenReturn(TableStatus.PUBLIC); + doCallRealMethod().when(tableMeta).getRowType(any()); + when(tableMeta.getAllColumns()).thenReturn(COLUMN_METAS); + when(ossTableScan.getRowType()).thenReturn(CalciteUtils.switchRowType(COLUMN_METAS, typeFactory)); + when(ossTableScan.getTableNames()).thenReturn(ImmutableList.of("t1")); + PushDownOpt pushDownOpt = new PushDownOpt(ossTableScan, DbType.MYSQL, executionContext); + + final JavaTypeFactoryImpl javaTypeFactory = + new JavaTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + final RexBuilder rexBuilder = new RexBuilder(javaTypeFactory); + final RexLiteral i1 = rexBuilder.makeExactLiteral(BigDecimal.ONE); + + final RelDataType intType = javaTypeFactory.createType(int.class); + final RexInputRef x = rexBuilder.makeInputRef(intType, 0); // $0 + + final RexNode xEq1 = + rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN_OR_EQUAL, x, i1); + + LogicalFilter filter = new LogicalFilter(cluster, RelTraitSet.createEmpty(), ossTableScan, xEq1, + ImmutableSet.of()); + PushDownUtils.pushFilter(filter, pushDownOpt.getBuilder()); + + when(ossTableScan.getPushDownOpt()).thenReturn(pushDownOpt); + + doCallRealMethod().when(ossTableScan).getCciPartPrunedResults(any(), any()); + doCallRealMethod().when(ossTableScan).getCciRelShardInfo(any(), any()); + + when(paramManager.getInt(ConnectionParams.PARTITION_PRUNING_STEP_COUNT_LIMIT)).thenReturn(1024); + when(paramManager.getBoolean(ConnectionParams.ENABLE_PARTITION_PRUNING)).thenReturn(true); + } + + public void setUpForRawString() { + Parameters parameters = new Parameters(); + Map params = Maps.newHashMap(); + params.put(1, + new ParameterContext(ParameterMethod.setObject1, new Object[] { + 1, new RawString(IntStream.range(0, 10000).boxed().collect( + Collectors.toList()))})); + parameters.setParams(params); + executionContext.setParams(parameters); + when(paramManager.getInt(ConnectionParams.IN_PRUNE_MAX_TIME)).thenReturn(100000); + when(paramManager.getBoolean(ConnectionParams.ENABLE_PARTITION_PRUNING)).thenReturn(true); + + PartitionInfo tmpPartitionInfo = + PartitionInfoManager.generatePartitionInfo(COLUMN_METAS, PARTITION_RECORDS, null, false, false); + when(tableMeta.getPartitionInfo()).thenReturn(tmpPartitionInfo); + + PushDownOpt pushDownOpt = new PushDownOpt(ossTableScan, DbType.MYSQL, executionContext); + + final JavaTypeFactoryImpl javaTypeFactory = + new JavaTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + final RexBuilder rexBuilder = new RexBuilder(javaTypeFactory); + + final RelDataType intType = javaTypeFactory.createType(int.class); + final RexInputRef x = rexBuilder.makeInputRef(intType, 0); // $0 + + final RexNode xinList = + rexBuilder.makeCall(TddlOperatorTable.IN, x, + rexBuilder.makeCall(SqlStdOperatorTable.ROW, + rexBuilder.makeDynamicParam(intType, 0))); + + LogicalFilter filter = + new LogicalFilter(ossTableScan.getCluster(), RelTraitSet.createEmpty(), ossTableScan, xinList, + ImmutableSet.of()); + PushDownUtils.pushFilter(filter, pushDownOpt.getBuilder()); + + when(ossTableScan.getPushDownOpt()).thenReturn(pushDownOpt); + } + + public void setUpForColdData() { + when(ossTableScan.isColumnarIndex()).thenReturn(false); + + when(fileMeta.getFileName()).thenReturn("1.orc"); + when(fileMeta.getCommitTs()).thenReturn(1L); + Map> flatFileMetas = new HashMap<>(); + flatFileMetas.put("t1_0", ImmutableList.of(fileMeta)); + when(tableMeta.getFlatFileMetas()).thenReturn(flatFileMetas); + + when(paramManager.getString(ConnectionParams.FILE_LIST)).thenReturn("ALL"); + } + + @After + public void clear() throws Exception { + if (autoCloseable != null) { + autoCloseable.close(); + } + + if (columnarTransactionUtilsMockedStatic != null) { + columnarTransactionUtilsMockedStatic.close(); + } + + if (mockMetaDbUtil != null) { + mockMetaDbUtil.close(); + } + + if (tableMappingAccessorCtor != null) { + tableMappingAccessorCtor.close(); + } + + if (filesAccessorCtor != null) { + filesAccessorCtor.close(); + } + + if (cafAccessorCtor != null) { + cafAccessorCtor.close(); + } + + if (partitionGroupAccessorMockedConstruction != null) { + partitionGroupAccessorMockedConstruction.close(); + } + + if (csMockedConstruction != null) { + csMockedConstruction.close(); + } + } + + @Test + public void getTableConcurrencySplitForFlashback() { + setUpForFlashback(); + List splits = OssSplit.getTableConcurrencySplit(ossTableScan, relNode, executionContext, 1L); + assertEquals(1, splits.size()); + OssSplit split = splits.get(0); + assertEquals("1.orc", split.getDesignatedFile().get(0)); + List csvFiles = split.getDeltaReadOption().getAllCsvFiles().get("t1_0"); + List positions = split.getDeltaReadOption().getAllPositions().get("t1_0"); + assertEquals(1, csvFiles.size()); + assertEquals("1.csv", csvFiles.get(0)); + assertEquals(1, positions.size()); + assertEquals(200, positions.get(0).longValue()); + List> delPositions = split.getDeltaReadOption().getAllDelPositions().get("p0"); + assertEquals(1, delPositions.size()); + assertEquals("1.del", delPositions.get(0).getKey()); + assertEquals(300, delPositions.get(0).getValue().longValue()); + } + + @Test + public void getFileConcurrencySplitForFlashback() { + setUpForFlashback(); + List splits = OssSplit.getFileConcurrencySplit(ossTableScan, relNode, executionContext, 1L); + assertEquals(2, splits.size()); + for (OssSplit split : splits) { + if (split.getDesignatedFile() != null && split.getDesignatedFile().size() == 1) { + assertEquals("1.orc", split.getDesignatedFile().get(0)); + } else { + List csvFiles = split.getDeltaReadOption().getAllCsvFiles().get("t1_0"); + List positions = split.getDeltaReadOption().getAllPositions().get("t1_0"); + assertEquals(1, csvFiles.size()); + assertEquals("1.csv", csvFiles.get(0)); + assertEquals(1, positions.size()); + assertEquals(200, positions.get(0).longValue()); + } + List> delPositions = split.getDeltaReadOption().getAllDelPositions().get("p0"); + assertEquals(1, delPositions.size()); + assertEquals("1.del", delPositions.get(0).getKey()); + assertEquals(300, delPositions.get(0).getValue().longValue()); + } + } + + @Test + public void getFileConcurrencySplitForColumnar() { + setUpForColumnar(); + List splits = OssSplit.getFileConcurrencySplit(ossTableScan, relNode, executionContext, 1L); + assertEquals(2, splits.size()); + for (OssSplit split : splits) { + if (split.getDesignatedFile() != null && split.getDesignatedFile().size() == 1) { + assertEquals("1.orc", split.getDesignatedFile().get(0)); + } else { + List csvFiles = split.getDeltaReadOption().getAllCsvFiles().get("t1_0"); + assertEquals(1, csvFiles.size()); + assertEquals("1.csv", csvFiles.get(0)); + } + } + } + + @Test + public void getFileConcurrencySplitForColdData() { + setUpForColdData(); + List splits = OssSplit.getFileConcurrencySplit(ossTableScan, relNode, executionContext, null); + assertEquals(1, splits.size()); + for (OssSplit split : splits) { + assertEquals("1.orc", split.getDesignatedFile().get(0)); + List prunedOrcFiles = split.getPrunedOrcFiles(ossTableScan, executionContext); + assertEquals(0, prunedOrcFiles.size()); + } + } + + @Test + public void getColumnarSplitForFlashbackQuery() { + setUpForFlashback(); + setUpForSharding(); + + SplitInfo splitInfo = SplitManagerImpl.columnarOssTableScanSplit(ossTableScan, executionContext, 1L); + Collection> splits = splitInfo.getSplits(); + assertEquals(1, splits.size()); + List splitList = splits.stream().findFirst().get(); + assertEquals(2, splitList.size()); + for (Split wrapSplit : splitList) { + OssSplit split = (OssSplit) wrapSplit.getConnectorSplit(); + if (split.getDesignatedFile() != null && split.getDesignatedFile().size() == 1) { + assertEquals("1.orc", split.getDesignatedFile().get(0)); + } else { + List csvFiles = split.getDeltaReadOption().getAllCsvFiles().get("p0"); + List positions = split.getDeltaReadOption().getAllPositions().get("p0"); + assertEquals(1, csvFiles.size()); + assertEquals("1.csv", csvFiles.get(0)); + assertEquals(1, positions.size()); + assertEquals(200, positions.get(0).longValue()); + } + List> delPositions = split.getDeltaReadOption().getAllDelPositions().get("p0"); + assertEquals(1, delPositions.size()); + assertEquals("1.del", delPositions.get(0).getKey()); + assertEquals(300, delPositions.get(0).getValue().longValue()); + } + } + + @Test + public void getColumnarSplitForColumnarQuery() { + setUpForColumnar(); + setUpForSharding(); + + SplitInfo splitInfo = SplitManagerImpl.columnarOssTableScanSplit(ossTableScan, executionContext, 1L); + Collection> splits = splitInfo.getSplits(); + assertEquals(1, splits.size()); + List splitList = splits.stream().findFirst().get(); + assertEquals(2, splitList.size()); + for (Split wrapSplit : splitList) { + OssSplit split = (OssSplit) wrapSplit.getConnectorSplit(); + if (split.getDesignatedFile() != null && split.getDesignatedFile().size() == 1) { + assertEquals("1.orc", split.getDesignatedFile().get(0)); + } else { + List csvFiles = split.getDeltaReadOption().getAllCsvFiles().get("p0"); + assertEquals(1, csvFiles.size()); + assertEquals("1.csv", csvFiles.get(0)); + } + } + } + + @Test + public void getColumnarSplitForColumnarQueryWithRawString() { + setUpForColumnar(); + setUpForSharding(); + setUpForRawString(); + + SplitInfo splitInfo = SplitManagerImpl.columnarOssTableScanSplit(ossTableScan, executionContext, 1L); + Collection> splits = splitInfo.getSplits(); + assertEquals(1, splits.size()); + List splitList = splits.stream().findFirst().get(); + assertEquals(2, splitList.size()); + for (Split wrapSplit : splitList) { + OssSplit split = (OssSplit) wrapSplit.getConnectorSplit(); + if (split.getDesignatedFile() != null && split.getDesignatedFile().size() == 1) { + assertEquals("1.orc", split.getDesignatedFile().get(0)); + } else { + List csvFiles = split.getDeltaReadOption().getAllCsvFiles().get("p0"); + assertEquals(1, csvFiles.size()); + assertEquals("1.csv", csvFiles.get(0)); + } + } + } + + @Ignore("Used for perf") + @Test + public void perfMultiVersionPruning() { + setUpForColumnar(); + setUpForSharding(); + setUpForRawString(); + + for (int i = 0; i < 10; i++) { + OptimizerUtils.pruningInValueForColumnar(ossTableScan, executionContext, partitionInfos); + } + long avg = executionContext.getPruningTime() / 10; + System.out.println("avg pruning time(ms):" + avg); + } + + static ColumnarAppendedFilesRecord buildCafRecord(String fileName, String partitionName, long appendOffset, + long appendLength) { + ColumnarAppendedFilesRecord cafRecord = new ColumnarAppendedFilesRecord(); + cafRecord.fileName = fileName; + cafRecord.partName = partitionName; + cafRecord.appendOffset = appendOffset; + cafRecord.appendLength = appendLength; + return cafRecord; + } + + static FilesRecordSimplified buildFileRecord(String fileName, String partitionName, long commitTs, long removeTs, + long schemaTs) { + FilesRecordSimplified fileRecord = new FilesRecordSimplified(); + fileRecord.fileName = fileName; + fileRecord.partitionName = partitionName; + fileRecord.commitTs = commitTs; + fileRecord.removeTs = removeTs; + fileRecord.schemaTs = schemaTs; + return fileRecord; + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/split/SpecifiedOssSplitTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/split/SpecifiedOssSplitTest.java new file mode 100644 index 000000000..889a13f3f --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/mpp/split/SpecifiedOssSplitTest.java @@ -0,0 +1,241 @@ +package com.alibaba.polardbx.executor.mpp.split; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.oss.IDeltaReadOption; +import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; +import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformerUtil; +import com.alibaba.polardbx.executor.archive.reader.TypeComparison; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.FileMeta; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; +import com.alibaba.polardbx.optimizer.core.rel.OrcTableScan; +import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation; +import com.alibaba.polardbx.optimizer.core.rel.PhyTableScanBuilder; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.RelPartitionWise; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class SpecifiedOssSplitTest { + private SpecifiedOssSplit create() { + String logicalSchema = "testlogicalschema"; + String physicalSchema = "testPhysicalSchema"; + Map params = new HashMap<>(); + String logicalTableName = "testLogicalTableName"; + List phyTableNameList = new ArrayList<>(); + List designatedFile = new ArrayList<>(); + OssSplit.DeltaReadOption deltaReadOption = new SpecifiedOssSplit.DeltaReadWithPositionOption( + 100L, 100L, 100L, 100L + ); + Long checkpointTso = 100L; + int partIndex = 0; + Boolean localPairWise = false; + return new SpecifiedOssSplit( + logicalSchema, + physicalSchema, + params, + logicalTableName, + phyTableNameList, + designatedFile, + deltaReadOption, + checkpointTso, + partIndex, + localPairWise + ); + } + + @Test + public void testCreateAndCopy() { + SpecifiedOssSplit specifiedOssSplit = create(); + SpecifiedOssSplit.DeltaReadWithPositionOption deltaReadOption = + (SpecifiedOssSplit.DeltaReadWithPositionOption) specifiedOssSplit.getDeltaReadOption(); + SpecifiedOssSplit.DeltaReadWithPositionOption copyDeltaReadOption = + new SpecifiedOssSplit.DeltaReadWithPositionOption( + deltaReadOption.getCheckpointTso(), + deltaReadOption.getAllCsvFiles(), + deltaReadOption.getAllPositions(), + deltaReadOption.getAllDelPositions(), + deltaReadOption.getProjectColumnIndexes(), + deltaReadOption.getTsoV0(), + deltaReadOption.getTsoV1(), + deltaReadOption.getTableId(), + deltaReadOption.getCsvFiles(), + deltaReadOption.getCsvStartPos(), + deltaReadOption.getCsvEndPos(), + deltaReadOption.getDelFiles(), + deltaReadOption.getDelBeginPos(), + deltaReadOption.getDelEndPos() + ); + Assert.assertEquals(deltaReadOption.getCheckpointTso(), copyDeltaReadOption.getCheckpointTso()); + Assert.assertEquals(deltaReadOption.getAllCsvFiles(), copyDeltaReadOption.getAllCsvFiles()); + Assert.assertEquals(deltaReadOption.getAllPositions(), copyDeltaReadOption.getAllPositions()); + Assert.assertEquals(deltaReadOption.getAllDelPositions(), copyDeltaReadOption.getAllDelPositions()); + Assert.assertEquals(deltaReadOption.getProjectColumnIndexes(), copyDeltaReadOption.getProjectColumnIndexes()); + Assert.assertEquals(deltaReadOption.getTsoV0(), copyDeltaReadOption.getTsoV0()); + Assert.assertEquals(deltaReadOption.getTsoV1(), copyDeltaReadOption.getTsoV1()); + Assert.assertEquals(deltaReadOption.getTableId(), copyDeltaReadOption.getTableId()); + Assert.assertEquals(deltaReadOption.getCsvFiles(), copyDeltaReadOption.getCsvFiles()); + Assert.assertEquals(deltaReadOption.getCsvStartPos(), copyDeltaReadOption.getCsvStartPos()); + Assert.assertEquals(deltaReadOption.getCsvEndPos(), copyDeltaReadOption.getCsvEndPos()); + Assert.assertEquals(deltaReadOption.getDelFiles(), copyDeltaReadOption.getDelFiles()); + Assert.assertEquals(deltaReadOption.getDelBeginPos(), copyDeltaReadOption.getDelBeginPos()); + Assert.assertEquals(deltaReadOption.getDelEndPos(), copyDeltaReadOption.getDelEndPos()); + + copyDeltaReadOption.setDelBeginPos(deltaReadOption.getDelBeginPos()); + copyDeltaReadOption.setDelEndPos(deltaReadOption.getDelEndPos()); + copyDeltaReadOption.setDelFiles(deltaReadOption.getDelFiles()); + copyDeltaReadOption.setCsvStartPos(deltaReadOption.getCsvStartPos()); + copyDeltaReadOption.setCsvEndPos(deltaReadOption.getCsvEndPos()); + copyDeltaReadOption.setCsvFiles(deltaReadOption.getCsvFiles()); + + Assert.assertEquals(deltaReadOption.getCsvFiles(), copyDeltaReadOption.getCsvFiles()); + Assert.assertEquals(deltaReadOption.getCsvStartPos(), copyDeltaReadOption.getCsvStartPos()); + Assert.assertEquals(deltaReadOption.getCsvEndPos(), copyDeltaReadOption.getCsvEndPos()); + Assert.assertEquals(deltaReadOption.getDelFiles(), copyDeltaReadOption.getDelFiles()); + Assert.assertEquals(deltaReadOption.getDelBeginPos(), copyDeltaReadOption.getDelBeginPos()); + Assert.assertEquals(deltaReadOption.getDelEndPos(), copyDeltaReadOption.getDelEndPos()); + + SpecifiedOssSplit copySpecifiedOssSplit = new SpecifiedOssSplit( + specifiedOssSplit.getLogicalSchema(), + specifiedOssSplit.getPhysicalSchema(), + specifiedOssSplit.getParamsBytes(), + specifiedOssSplit.getLogicalTableName(), + specifiedOssSplit.getPhyTableNameList(), + specifiedOssSplit.getDesignatedFile(), + (SpecifiedOssSplit.DeltaReadWithPositionOption) specifiedOssSplit.getDeltaReadOption(), + specifiedOssSplit.getCheckpointTso(), + specifiedOssSplit.getPartIndex(), + specifiedOssSplit.getNodePartCount(), + false + ); + Assert.assertEquals(specifiedOssSplit.getLogicalSchema(), copySpecifiedOssSplit.getLogicalSchema()); + Assert.assertEquals(specifiedOssSplit.getPhysicalSchema(), copySpecifiedOssSplit.getPhysicalSchema()); + Assert.assertEquals(specifiedOssSplit.getParamsBytes(), copySpecifiedOssSplit.getParamsBytes()); + Assert.assertEquals(specifiedOssSplit.getLogicalTableName(), copySpecifiedOssSplit.getLogicalTableName()); + Assert.assertEquals(specifiedOssSplit.getPhyTableNameList(), copySpecifiedOssSplit.getPhyTableNameList()); + Assert.assertEquals(specifiedOssSplit.getDesignatedFile(), copySpecifiedOssSplit.getDesignatedFile()); + Assert.assertEquals(specifiedOssSplit.getDeltaReadOption(), copySpecifiedOssSplit.getDeltaReadOption()); + Assert.assertEquals(specifiedOssSplit.getCheckpointTso(), copySpecifiedOssSplit.getCheckpointTso()); + Assert.assertEquals(specifiedOssSplit.getPartIndex(), copySpecifiedOssSplit.getPartIndex()); + Assert.assertEquals(specifiedOssSplit.getNodePartCount(), copySpecifiedOssSplit.getNodePartCount()); + } + + @Test + public void testGetSpecifiedSplit() { + OSSTableScan ossTableScan = mock(OSSTableScan.class); + PhyTableOperation phyTableOperation = mock(PhyTableOperation.class); + ExecutionContext executionContext = new ExecutionContext(); + + String schema = "testschema"; + String physicalSchema = "testPhysicalSchema"; + String logicalTableName = "logicalCci"; + String phyTableName = "phyCci"; + List phyTableNameList = ImmutableList.of(phyTableName); + TableMeta tableMeta = mock(TableMeta.class); + SchemaManager schemaManager = mock(SchemaManager.class); + PhyTableScanBuilder phyTableScanBuilder = mock(PhyTableScanBuilder.class); + PartitionInfo partitionInfo = mock(PartitionInfo.class); + Map> specifiedOrcFiles = ImmutableMap.of( + "p1", ImmutableSet.of("test1.csv", "test2.csv") + ); + Map readDeltaFiles = ImmutableMap.of( + "p1", new SpecifiedOssSplit.DeltaReadWithPositionOption(100L, 100L, 100L, 100L) + ); + RelTraitSet relTraitSet = mock(RelTraitSet.class); + RelPartitionWise partitionWise = mock(RelPartitionWise.class); + + when(phyTableOperation.getSchemaName()).thenReturn(schema); + when(phyTableOperation.getDbIndex()).thenReturn(physicalSchema); + when(phyTableOperation.getLogicalTableNames()).thenReturn(ImmutableList.of(logicalTableName)); + when(phyTableOperation.getTableNames()).thenReturn(ImmutableList.of(phyTableNameList)); + executionContext.setSchemaManager(schema, schemaManager); + when(schemaManager.getTable(logicalTableName)).thenReturn(tableMeta); + when(phyTableOperation.getPhyOperationBuilder()).thenReturn(phyTableScanBuilder); + when(tableMeta.getPartitionInfo()).thenReturn(partitionInfo); + when(partitionInfo.getPartitionNameByPhyLocation(physicalSchema, phyTableName)).thenReturn("p1"); + executionContext.setReadOrcFiles(specifiedOrcFiles); + executionContext.setReadDeltaFiles(readDeltaFiles); + when(ossTableScan.getTraitSet()).thenReturn(relTraitSet); + when(relTraitSet.getPartitionWise()).thenReturn(partitionWise); + when(partitionWise.isRemotePartition()).thenReturn(false); + + List specifiedOssSplits = + SpecifiedOssSplit.getSpecifiedSplit(ossTableScan, phyTableOperation, executionContext); + Assert.assertEquals(1, specifiedOssSplits.size()); + Assert.assertEquals(physicalSchema, specifiedOssSplits.get(0).getPhysicalSchema()); + Assert.assertEquals(schema, specifiedOssSplits.get(0).getLogicalSchema()); + Assert.assertEquals(logicalTableName, specifiedOssSplits.get(0).getLogicalTableName()); + Assert.assertEquals(phyTableNameList, specifiedOssSplits.get(0).getPhyTableNameList()); + Assert.assertEquals(specifiedOrcFiles.get("p1").toArray(), + specifiedOssSplits.get(0).getDesignatedFile().toArray()); + Assert.assertEquals(readDeltaFiles.get("p1"), specifiedOssSplits.get(0).getDeltaReadOption()); + } + + @Test + public void testGetColumnTransformer() { + OSSTableScan ossTableScan = mock(OSSTableScan.class); + ExecutionContext executionContext = new ExecutionContext(); + String fileName = "test.orc"; + SpecifiedOssSplit specifiedOssSplit = create(); + + String schema = specifiedOssSplit.getLogicalSchema(); + String logicalTable = specifiedOssSplit.getLogicalTableName(); + ColumnarManager columnarManager = mock(ColumnarManager.class); + FileMeta fileMeta = mock(FileMeta.class); + OrcTableScan orcTableScan = mock(OrcTableScan.class); + ImmutableList inProjects = ImmutableList.of(1); + ImmutableList inProjectNames = ImmutableList.of("a"); + SchemaManager schemaManager = mock(SchemaManager.class); + TableMeta tableMeta = mock(TableMeta.class); + ColumnMeta columnMeta = mock(ColumnMeta.class); + Map columnIndexMap = ImmutableMap.of(1L, 0); + List columnMetas = ImmutableList.of(columnMeta); + + executionContext.setSchemaManager(schema, schemaManager); + when(schemaManager.getTable(logicalTable)).thenReturn(tableMeta); + when(columnarManager.fileMetaOf(fileName)).thenReturn(fileMeta); + when(fileMeta.getLogicalTableName()).thenReturn("100"); + when(fileMeta.getSchemaTs()).thenReturn(100L); + when(columnarManager.getColumnIndex(100L, 100)).thenReturn(columnIndexMap); + when(tableMeta.getColumn("a")).thenReturn(columnMeta); + when(tableMeta.getColumnarFieldId(1)).thenReturn(1L); + when(fileMeta.getColumnMetas()).thenReturn(columnMetas); + when(orcTableScan.getInProjects()).thenReturn(inProjects); + when(orcTableScan.getInputProjectName()).thenReturn(inProjectNames); + when(ossTableScan.getOrcNode()).thenReturn(orcTableScan); + when(columnMeta.getName()).thenReturn("a"); + + try (MockedStatic staticColumnarManager = mockStatic(ColumnarManager.class); + MockedStatic staticOssColumnTransformerUtil = mockStatic( + OSSColumnTransformerUtil.class);) { + staticColumnarManager.when(ColumnarManager::getInstance).thenReturn(columnarManager); + staticOssColumnTransformerUtil.when(() -> OSSColumnTransformerUtil.compare(any(), any())).thenReturn( + TypeComparison.IS_EQUAL_YES + ); + OSSColumnTransformer transformer = + specifiedOssSplit.getColumnTransformer(ossTableScan, executionContext, fileName, true); + + System.out.println(transformer); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/AdaptiveRangeScanClientTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/AdaptiveRangeScanClientTest.java new file mode 100644 index 000000000..a2707455a --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/AdaptiveRangeScanClientTest.java @@ -0,0 +1,67 @@ +package com.alibaba.polardbx.executor.operator; + +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class AdaptiveRangeScanClientTest { + + @Test + public void testFindNextPowerOfTwo() throws Exception { + Method method = AdaptiveRangeScanClient.class.getDeclaredMethod("findNextPowerOfTwo", int.class); + method.setAccessible(true); + + // Test cases where input is less than or equal to 0 + assertEquals(1, method.invoke(null, -1)); + assertEquals(1, method.invoke(null, 0)); + + // Test case where input is already a power of two + assertEquals(4, method.invoke(null, 4)); + assertEquals(16, method.invoke(null, 16)); + + // Test cases where input is not a power of two + assertEquals(4, method.invoke(null, 3)); + assertEquals(128, method.invoke(null, 127)); + assertEquals(512, method.invoke(null, 511)); + } + + @Test + public void testGetPolicyWithConstant() { + assertEquals(AdaptiveRangeScanClient.AdaptivePolicy.CONSTANT, + AdaptiveRangeScanClient.AdaptivePolicy.getPolicy("CONSTANT")); + } + + @Test + public void testGetPolicyWithExponential() { + assertEquals(AdaptiveRangeScanClient.AdaptivePolicy.EXPONENT, + AdaptiveRangeScanClient.AdaptivePolicy.getPolicy("EXPONENTIAL")); + } + + @Test + public void testGetPolicyWithEmpty() { + assertEquals(AdaptiveRangeScanClient.AdaptivePolicy.EXPONENT, + AdaptiveRangeScanClient.AdaptivePolicy.getPolicy("")); + } + + @Test + public void testGetPolicyWithNull() { + assertEquals(AdaptiveRangeScanClient.AdaptivePolicy.EXPONENT, + AdaptiveRangeScanClient.AdaptivePolicy.getPolicy(null)); + } + + @Test + public void testGetPolicyWithOtherValue() { + assertEquals(AdaptiveRangeScanClient.AdaptivePolicy.EXPONENT, + AdaptiveRangeScanClient.AdaptivePolicy.getPolicy("SOME_OTHER_POLICY")); + } + + @Test + public void testGetPolicyWithCaseInsensitive() { + assertEquals(AdaptiveRangeScanClient.AdaptivePolicy.CONSTANT, + AdaptiveRangeScanClient.AdaptivePolicy.getPolicy("constant ")); + assertEquals(AdaptiveRangeScanClient.AdaptivePolicy.EXPONENT, + AdaptiveRangeScanClient.AdaptivePolicy.getPolicy(" exponential")); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/HashAggExecTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/HashAggExecTest.java index d70e3c7c8..b84672e4a 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/HashAggExecTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/HashAggExecTest.java @@ -17,9 +17,11 @@ package com.alibaba.polardbx.executor.operator; import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.common.datatype.FastDecimalUtils; import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.chunk.DecimalBlockBuilder; import com.alibaba.polardbx.executor.chunk.DoubleBlock; +import com.alibaba.polardbx.executor.chunk.DoubleBlockBuilder; import com.alibaba.polardbx.executor.chunk.IntegerBlock; import com.alibaba.polardbx.executor.chunk.LongBlock; import com.alibaba.polardbx.optimizer.core.datatype.DataType; @@ -30,7 +32,10 @@ import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.CountV2; import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.SumV2; import org.junit.Ignore; +import com.google.common.collect.Lists; import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; import java.math.BigDecimal; import java.util.ArrayList; @@ -38,6 +43,8 @@ import java.util.Collections; import java.util.List; +import static com.alibaba.polardbx.common.datatype.DecimalTypeBase.E_DEC_DIV_ZERO; + public class HashAggExecTest extends BaseExecTest { private static String TABLE_NAME = "MOCK_HASH_AGG_TABLE"; @@ -90,6 +97,82 @@ public void testHashAggSimpleAvg() { } + @Test + public void testHashAggSimpleAvg2() { + MockExec inputExec = MockExec.builder(DataTypes.IntegerType, DataTypes.IntegerType) + .withChunk(new Chunk( + IntegerBlock.of(0, 1, 2, 3), + IntegerBlock.of(3, 4, 9, 7))) + .withChunk(new Chunk( + IntegerBlock.of(0, 1, 2, 3), + IntegerBlock.of(5, 3, 8, 1))) + .build(); + int[] groups = {0}; + List aggregators = new ArrayList<>(); + aggregators.add(new AvgV2(1, false, context.getMemoryPool().getMemoryAllocatorCtx(), -1)); + List outputColumn = Lists.newArrayList(DataTypes.IntegerType, DataTypes.DoubleType); + + HashAggExec exec = + new HashAggExec(inputExec.getDataTypes(), groups, aggregators, outputColumn, DEFAULT_AGG_HASH_TABLE_SIZE, + context); + SingleExecTest test = new SingleExecTest.Builder(exec, inputExec.getChunks()).build(); + test.exec(); + + DoubleBlockBuilder doubleBlockBuilder = new DoubleBlockBuilder(4); + doubleBlockBuilder.writeDouble(4.0); + doubleBlockBuilder.writeDouble(3.5); + doubleBlockBuilder.writeDouble(8.5); + doubleBlockBuilder.writeDouble(4.0); + + assertExecResultByRow(test.result(), Collections.singletonList(new Chunk( + IntegerBlock.of(0, 1, 2, 3), + doubleBlockBuilder.build() + )), false); + + } + + @Test + public void testDecimalAvgDivBy0() { + // Divided by 0 may be an unreachable state + try (MockedStatic mockedDecUtils = Mockito.mockStatic(FastDecimalUtils.class)) { + mockedDecUtils.when( + () -> FastDecimalUtils.div(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyInt())) + .thenReturn(E_DEC_DIV_ZERO); + MockExec inputExec = MockExec.builder(DataTypes.IntegerType, DataTypes.IntegerType) + .withChunk(new Chunk( + IntegerBlock.of(0, 1, 2, 3), + IntegerBlock.of(1, 2, 3, 4))) + .withChunk(new Chunk( + IntegerBlock.of(0, 1, 2, 3), + IntegerBlock.of(null, null, null, null))) + .build(); + int[] groups = {0}; + List aggregators = new ArrayList<>(); + aggregators.add(new AvgV2(1, false, context.getMemoryPool().getMemoryAllocatorCtx(), -1)); + List outputColumn = new ArrayList<>(); + outputColumn.add(DataTypes.IntegerType); + outputColumn.add(DataTypes.DecimalType); + + HashAggExec exec = + new HashAggExec(inputExec.getDataTypes(), groups, aggregators, outputColumn, + DEFAULT_AGG_HASH_TABLE_SIZE, + context); + SingleExecTest test = new SingleExecTest.Builder(exec, inputExec.getChunks()).build(); + test.exec(); + + DecimalBlockBuilder decimalBlockBuilder = new DecimalBlockBuilder(256); + decimalBlockBuilder.appendNull(); + decimalBlockBuilder.appendNull(); + decimalBlockBuilder.appendNull(); + decimalBlockBuilder.appendNull(); + + assertExecResultByRow(test.result(), Collections.singletonList(new Chunk( + IntegerBlock.of(0, 1, 2, 3), + decimalBlockBuilder.build() + )), false); + } + } + @Test public void testHashAggSimpleCount() { MockExec inputExec = MockExec.builder(DataTypes.IntegerType, DataTypes.IntegerType) diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/HashJoinTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/HashJoinTest.java index 4dba31db1..3910a6442 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/HashJoinTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/HashJoinTest.java @@ -66,7 +66,7 @@ public class HashJoinTest extends BaseExecTest { private static AsyncFileSingleStreamSpillerFactory spillerFactory; - private static Path tempPath = Paths.get("./tmp/" + UUID.randomUUID()); + private static final Path tempPath = Paths.get("./tmp/" + UUID.randomUUID()); @BeforeClass public static void beforeClass() { @@ -235,7 +235,7 @@ public void testInnerJoin_MultiKey() { IntegerBlock.of(1, 1, 2, 2, 3), StringBlock.of("a", "a", "a", "b", "a"), StringBlock.of("E", "A", "B", "F", "C")); - List expects[] = new List[4]; + List[] expects = new List[4]; expects[0] = rowChunksBuilder(outTypes).addChunk(baseExpect). row(8118, 1000, "XX", 1000, "XX", "YY"). @@ -394,7 +394,7 @@ public void testLeftOuterJoin_MultiKey() { IntegerBlock.of(1, 1, null, 2, 2, null, 3, null, null, null, null), StringBlock.of("a", "a", null, "a", "b", null, "a", null, null, null, null), StringBlock.of("E", "A", null, "B", "F", null, "C", null, null, null, null)); - List expects[] = new List[4]; + List[] expects = new List[4]; expects[0] = rowChunksBuilder(outTypes).addChunk(baseExpect). row(8008, null, null, null, null, null). @@ -501,7 +501,7 @@ public void testRightOuterJoin_MultiKey() { IntegerBlock.of(1, 1, 1, 2, 2, null, 3, 3, 4, 4, 4), StringBlock.of("a", "a", "b", "a", "b", "a", "a", "b", "a", "b", null) ); - List expects[] = new List[4]; + List[] expects = new List[4]; expects[0] = rowChunksBuilder(outTypes).addChunk(baseExpect). row(null, null, null, 8008, null, null). @@ -660,6 +660,28 @@ public void testSemiLongJoinVec() { // assertExecResultByRow(test.result(), expects, false); // } + @Test + public void testSemiLongJoinNotEqLongVec() { + enableVecJoin(); + + IExpression condition = ScalarFunctionExpression.getScalarFunctionExp( + ImmutableList.of(new InputRefExpression(1), new InputRefExpression(5)), new NotEqual(), context); + + List expects = Collections.singletonList(new Chunk( + LongBlock.of(1L, 3L, 4L, 7L), + IntegerBlock.of(4, 7, 5, 10), + LongBlock.of(12L, 14L, 15L, 18L))); + + SingleExecTest test = + mockParallelHashJoinExec(EquiJoinMockData.SEMI_LONG_NOT_EQ_LONG_CASE, JoinRelType.SEMI, false, + condition, null, context); + Assert.assertTrue( + ((ParallelHashJoinExec) test.exec).probeOperator instanceof AbstractHashJoinExec.SemiLongNotEqLongProbeOperator); + + test.exec(); + assertExecResultByRow(test.result(), expects, false); + } + @Test public void testReverseSemiJoin() { List expects = Collections.singletonList(new Chunk( @@ -830,7 +852,7 @@ public void testSemiJoin_InnerEmpty() { MockExec innerInput = MockExec.builder(DataTypes.IntegerType).build(); - List joinKeys = Arrays.asList( + List joinKeys = Collections.singletonList( mockEquiJoinKey(1, 0, DataTypes.IntegerType)); Executor exec = @@ -861,7 +883,7 @@ public void testReverseSemiJoin_InnerEmpty() { MockExec innerInput = MockExec.builder(DataTypes.IntegerType).build(); - List joinKeys = Arrays.asList( + List joinKeys = Collections.singletonList( mockEquiJoinKey(1, 0, DataTypes.IntegerType)); Executor exec = @@ -954,7 +976,7 @@ public void testAntiJoin_NotIn() { IntegerBlock.of(2, 3, 6), IntegerBlock.of(9, 7, 8) )); - List antiJoinOperands = Arrays.asList( + List antiJoinOperands = Collections.singletonList( new InputRefExpression(1) ); @@ -1065,10 +1087,10 @@ public void testAntiJoin_NotIn_InnerEmpty() { MockExec innerInput = MockExec.builder(DataTypes.IntegerType).build(); - List joinKeys = Arrays.asList( + List joinKeys = Collections.singletonList( mockEquiJoinKey(1, 0, DataTypes.IntegerType)); - List antiJoinOperands = Arrays.asList( + List antiJoinOperands = Collections.singletonList( new InputRefExpression(1) ); @@ -1112,10 +1134,10 @@ public void testAntiJoin_NotIn_InnerContainsNull() { IntegerBlock.of(3, null, 5, 6))) .build(); - List joinKeys = Arrays.asList( + List joinKeys = Collections.singletonList( mockEquiJoinKey(1, 0, DataTypes.IntegerType)); - List antiJoinOperands = Arrays.asList( + List antiJoinOperands = Collections.singletonList( new InputRefExpression(1) ); diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/OSSTableScanClientTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/OSSTableScanClientTest.java new file mode 100644 index 000000000..ec64f5c9d --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/OSSTableScanClientTest.java @@ -0,0 +1,146 @@ +package com.alibaba.polardbx.executor.operator; + +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.thread.ExecutorUtil; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.gms.FileVersionStorage; +import com.alibaba.polardbx.executor.gms.FileVersionStorageTestBase; +import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; +import com.alibaba.polardbx.executor.operator.scan.CsvScanTestBase; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import org.jetbrains.annotations.NotNull; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +import static com.alibaba.polardbx.executor.gms.FileVersionStorageTestBase.CSV_STATUSES; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class OSSTableScanClientTest extends CsvScanTestBase { + + private OSSTableScan ossTableScan; + private MockedConstruction mockCafCtor; + private MockedStatic mockMetaDbUtil; + + @Before + public void setUp() { + super.setUp(); + ossTableScan = mock(OSSTableScan.class); + ServiceProvider.getInstance().setServerExecutor( + ExecutorUtil.create("ServerExecutor", 1, 500, 1)); + when(columnarManager.csvData(anyLong(), anyString())).thenCallRealMethod(); + doCallRealMethod().when(columnarManager).injectForTest(any(), any(), any(), any()); + columnarManager.injectForTest(new FileVersionStorage(columnarManager), null, new AtomicLong(0), + CacheBuilder.newBuilder() + .build(new CacheLoader, List>() { + @Override + public List load(@NotNull Pair tsoAndFileName) { + ColumnarAppendedFilesRecord caf = new ColumnarAppendedFilesRecord(); + caf.appendLength = 1775L; + caf.appendOffset = 86549L; + caf.checkpointTso = TSO; + caf.fileName = DATA_FILE_NAME; + return Collections.singletonList(caf); + } + })); + + mockCafCtor = Mockito.mockConstruction(ColumnarAppendedFilesAccessor.class, (mock, context) -> { + Mockito.when( + mock.queryLatestByFileNameBetweenTso(anyString(), anyLong(), anyLong()) + ).thenAnswer( + invocationOnMock -> { + Object[] args = invocationOnMock.getArguments(); + String fileName = (String) args[0]; + long lowerTso = (long) args[1]; + long upperTso = (long) args[2]; + List appendedFilesRecords = new ArrayList<>(); + for (int i = CSV_STATUSES.length - 1; i >= 0; i--) { + FileVersionStorageTestBase.MockAppendedFilesStatus appendedFilesStatus = CSV_STATUSES[i]; + if (appendedFilesStatus.checkpointTso > lowerTso + && appendedFilesStatus.checkpointTso <= upperTso) { + appendedFilesRecords.add(appendedFilesStatus.toAppendedFilesRecord(fileName)); + break; + } + } + return appendedFilesRecords; + } + ); + + Mockito.when( + mock.queryByFileNameBetweenTso(anyString(), anyLong(), anyLong()) + ).thenAnswer( + invocationOnMock -> { + Object[] args = invocationOnMock.getArguments(); + String fileName = (String) args[0]; + long lowerTso = (long) args[1]; + long upperTso = (long) args[2]; + List appendedFilesRecords = new ArrayList<>(); + for (FileVersionStorageTestBase.MockAppendedFilesStatus appendedFilesStatus : CSV_STATUSES) { + if (appendedFilesStatus.checkpointTso > lowerTso + && appendedFilesStatus.checkpointTso <= upperTso) { + appendedFilesRecords.add(appendedFilesStatus.toAppendedFilesRecord(fileName)); + } + } + return appendedFilesRecords; + } + ); + }); + + mockMetaDbUtil = Mockito.mockStatic(MetaDbUtil.class); + } + + @After + public void tearDown() { + super.tearDown(); + if (mockCafCtor != null) { + mockCafCtor.close(); + } + + if (mockMetaDbUtil != null) { + mockMetaDbUtil.close(); + } + } + + @Test + public void deltaFileReadTest() { + try (OSSTableScanClient client = new OSSTableScanClient(ossTableScan, new ExecutionContext(), null)) { + client.executePrefetchThread(); + OSSTableScanClient.PrefetchThread prefetchThread = client.getPrefetchThread(); + prefetchThread.foreachDeltaFile(DATA_FILE_NAME, TSO, columnarManager, Collections.singletonList(1)); + + OSSTableScanClient.ResultFromOSS result; + long rowCount = 0; + int chunkCount = 0; + while ((result = client.popResult()) != null) { + if (result.isChunk() && result.isDelta()) { + Chunk chunk = result.getChunk(); + rowCount += chunk.getPositionCount(); + } + chunkCount++; + } + + Assert.assertEquals(CSV_STATUSES.length, chunkCount); + Assert.assertEquals(CSV_STATUSES[CSV_STATUSES.length - 1].totalRows, rowCount); + } + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/RangeScanSortExecTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/RangeScanSortExecTest.java new file mode 100644 index 000000000..0f0c9da49 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/RangeScanSortExecTest.java @@ -0,0 +1,75 @@ +package com.alibaba.polardbx.executor.operator; + +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; +import com.alibaba.polardbx.optimizer.core.row.ArrayRow; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class RangeScanSortExecTest { + + @Mock + private TableScanClient scanClient; + + private ExecutionContext context = new ExecutionContext(); + + @Mock + private TableScanClient.SplitResultSet consumeResultSet; + + private RangeScanSortExec rangeScanSortExec; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + LogicalView logicalView = mock(LogicalView.class); + + when(scanClient.popResultSet()).thenReturn(consumeResultSet); + List dataTypeList = Arrays.asList(DataTypes.IntegerType); + rangeScanSortExec = new RangeScanSortExec(logicalView, context, scanClient, 1, 0, 1, null, dataTypeList); + rangeScanSortExec.createDataTypes(); + rangeScanSortExec.createBlockBuilders(); + } + + @Test + public void testFetchSortedChunkWithData() throws Exception { + // 配置mock以返回数据 + when(consumeResultSet.next()).thenReturn(true, false); // 有1行数据 + when(consumeResultSet.current()).thenReturn(new ArrayRow(new Integer[] {1})); + when(consumeResultSet.fillChunk(any(), any(), anyInt())).thenReturn(1); + + Chunk resultChunk = rangeScanSortExec.fetchSortedChunk(); + + assertNotNull(resultChunk); + assertEquals(1, resultChunk.getPositionCount()); + verify(consumeResultSet, times(0)).fillChunk(any(), any(), anyInt()); + } + + @Test + public void testFetchSortedChunkWithDataAsync() throws Exception { + Class clazz = consumeResultSet.getClass(); + Field field = clazz.getDeclaredField("pureAsync"); + field.setAccessible(true); + field.set(consumeResultSet, true); + when(consumeResultSet.next()).thenReturn(true, false); + when(consumeResultSet.current()).thenReturn(new ArrayRow(new Integer[] {1})); + when(consumeResultSet.fillChunk(any(), any(), anyInt())).thenReturn(1); + when(consumeResultSet.isPureAsyncMode()).thenReturn(true); + Chunk resultChunk = rangeScanSortExec.fetchSortedChunk(); + + assertNotNull(resultChunk); + verify(consumeResultSet, times(1)).fillChunk(any(), any(), anyInt()); + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ArrowBatchTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ArrowBatchTest.java index c73844cfe..834ac0f02 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ArrowBatchTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ArrowBatchTest.java @@ -1,109 +1,109 @@ -package com.alibaba.polardbx.executor.operator.scan; - -import org.apache.arrow.memory.BufferAllocator; -import org.apache.arrow.memory.RootAllocator; -import org.apache.arrow.vector.IntVector; -import org.apache.arrow.vector.VarCharVector; -import org.apache.arrow.vector.VectorSchemaRoot; -import org.apache.arrow.vector.complex.ListVector; -import org.apache.arrow.vector.complex.impl.UnionListWriter; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.apache.arrow.vector.types.pojo.Field; -import org.apache.arrow.vector.types.pojo.FieldType; -import org.apache.arrow.vector.types.pojo.Schema; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import static java.util.Arrays.asList; - -public class ArrowBatchTest { - @Test - public void testField() { - Field name = new Field("name", FieldType.nullable(new ArrowType.Utf8()), null); - System.out.print(name); - - Field age = new Field("age", FieldType.nullable(new ArrowType.Int(32, true)), null); - System.out.print(age); - - FieldType intType = new FieldType(true, new ArrowType.Int(32, true), null); - FieldType listType = new FieldType(true, new ArrowType.List(), null); - Field childField = new Field("intCol", intType, null); - List childFields = new ArrayList<>(); - childFields.add(childField); - Field points = new Field("points", listType, childFields); - - System.out.print(points); - } - - @Test - public void testSchema() { - Field name = new Field("name", FieldType.nullable(new ArrowType.Utf8()), null); - Field document = new Field("document", new FieldType(true, new ArrowType.Utf8(), null), null); - Field age = new Field("age", FieldType.nullable(new ArrowType.Int(32, true)), null); - - FieldType intType = new FieldType(true, new ArrowType.Int(32, true), /*dictionary=*/null); - FieldType listType = new FieldType(true, new ArrowType.List(), /*dictionary=*/null); - - Field childField = new Field("intCol", intType, null); - List childFields = new ArrayList<>(); - childFields.add(childField); - - Field points = new Field("points", listType, childFields); - Schema schemaPerson = new Schema(asList(name, document, age, points)); - - System.out.print(schemaPerson); - } - - @Test - public void testVectorSchemaRoot() { - Field name = new Field("name", FieldType.nullable(new ArrowType.Utf8()), null); - Field age = new Field("age", FieldType.nullable(new ArrowType.Int(32, true)), null); - FieldType intType = new FieldType(true, new ArrowType.Int(32, true), null); - FieldType listType = new FieldType(true, new ArrowType.List(), null); - Field childField = new Field("intCol", intType, null); - List childFields = new ArrayList<>(); - childFields.add(childField); - Field points = new Field("points", listType, childFields); - Schema schema = new Schema(asList(name, age, points)); - try ( - BufferAllocator allocator = new RootAllocator(); - VectorSchemaRoot root = VectorSchemaRoot.create(schema, allocator) - ) { - VarCharVector nameVector = (VarCharVector) root.getVector("name"); - nameVector.allocateNew(3); - nameVector.set(0, "David".getBytes()); - nameVector.set(1, "Gladis".getBytes()); - nameVector.set(2, "Juan".getBytes()); - nameVector.setValueCount(3); - IntVector ageVector = (IntVector) root.getVector("age"); - ageVector.allocateNew(3); - ageVector.set(0, 10); - ageVector.set(1, 20); - ageVector.set(2, 30); - ageVector.setValueCount(3); - ListVector listVector = (ListVector) root.getVector("points"); - UnionListWriter listWriter = listVector.getWriter(); - int[] data = new int[] {4, 8, 12, 10, 20, 30, 5, 10, 15}; - int tmp_index = 0; - for (int i = 0; i < 3; i++) { - listWriter.setPosition(i); - listWriter.startList(); - for (int j = 0; j < 3; j++) { - listWriter.writeInt(data[tmp_index]); - tmp_index = tmp_index + 1; - } - listWriter.setValueCount(2); - listWriter.endList(); - } - listVector.setValueCount(3); - root.setRowCount(3); - - System.out.print(root.contentToTSVString()); - } catch (Exception e) { - e.printStackTrace(); - } - } - -} +//package com.alibaba.polardbx.executor.operator.scan; +// +//import org.apache.arrow.memory.BufferAllocator; +//import org.apache.arrow.memory.RootAllocator; +//import org.apache.arrow.vector.IntVector; +//import org.apache.arrow.vector.VarCharVector; +//import org.apache.arrow.vector.VectorSchemaRoot; +//import org.apache.arrow.vector.complex.ListVector; +//import org.apache.arrow.vector.complex.impl.UnionListWriter; +//import org.apache.arrow.vector.types.pojo.ArrowType; +//import org.apache.arrow.vector.types.pojo.Field; +//import org.apache.arrow.vector.types.pojo.FieldType; +//import org.apache.arrow.vector.types.pojo.Schema; +//import org.junit.Test; +// +//import java.util.ArrayList; +//import java.util.List; +// +//import static java.util.Arrays.asList; +// +//public class ArrowBatchTest { +// @Test +// public void testField() { +// Field name = new Field("name", FieldType.nullable(new ArrowType.Utf8()), null); +// System.out.print(name); +// +// Field age = new Field("age", FieldType.nullable(new ArrowType.Int(32, true)), null); +// System.out.print(age); +// +// FieldType intType = new FieldType(true, new ArrowType.Int(32, true), null); +// FieldType listType = new FieldType(true, new ArrowType.List(), null); +// Field childField = new Field("intCol", intType, null); +// List childFields = new ArrayList<>(); +// childFields.add(childField); +// Field points = new Field("points", listType, childFields); +// +// System.out.print(points); +// } +// +// @Test +// public void testSchema() { +// Field name = new Field("name", FieldType.nullable(new ArrowType.Utf8()), null); +// Field document = new Field("document", new FieldType(true, new ArrowType.Utf8(), null), null); +// Field age = new Field("age", FieldType.nullable(new ArrowType.Int(32, true)), null); +// +// FieldType intType = new FieldType(true, new ArrowType.Int(32, true), /*dictionary=*/null); +// FieldType listType = new FieldType(true, new ArrowType.List(), /*dictionary=*/null); +// +// Field childField = new Field("intCol", intType, null); +// List childFields = new ArrayList<>(); +// childFields.add(childField); +// +// Field points = new Field("points", listType, childFields); +// Schema schemaPerson = new Schema(asList(name, document, age, points)); +// +// System.out.print(schemaPerson); +// } +// +// @Test +// public void testVectorSchemaRoot() { +// Field name = new Field("name", FieldType.nullable(new ArrowType.Utf8()), null); +// Field age = new Field("age", FieldType.nullable(new ArrowType.Int(32, true)), null); +// FieldType intType = new FieldType(true, new ArrowType.Int(32, true), null); +// FieldType listType = new FieldType(true, new ArrowType.List(), null); +// Field childField = new Field("intCol", intType, null); +// List childFields = new ArrayList<>(); +// childFields.add(childField); +// Field points = new Field("points", listType, childFields); +// Schema schema = new Schema(asList(name, age, points)); +// try ( +// BufferAllocator allocator = new RootAllocator(); +// VectorSchemaRoot root = VectorSchemaRoot.create(schema, allocator) +// ) { +// VarCharVector nameVector = (VarCharVector) root.getVector("name"); +// nameVector.allocateNew(3); +// nameVector.set(0, "David".getBytes()); +// nameVector.set(1, "Gladis".getBytes()); +// nameVector.set(2, "Juan".getBytes()); +// nameVector.setValueCount(3); +// IntVector ageVector = (IntVector) root.getVector("age"); +// ageVector.allocateNew(3); +// ageVector.set(0, 10); +// ageVector.set(1, 20); +// ageVector.set(2, 30); +// ageVector.setValueCount(3); +// ListVector listVector = (ListVector) root.getVector("points"); +// UnionListWriter listWriter = listVector.getWriter(); +// int[] data = new int[] {4, 8, 12, 10, 20, 30, 5, 10, 15}; +// int tmp_index = 0; +// for (int i = 0; i < 3; i++) { +// listWriter.setPosition(i); +// listWriter.startList(); +// for (int j = 0; j < 3; j++) { +// listWriter.writeInt(data[tmp_index]); +// tmp_index = tmp_index + 1; +// } +// listWriter.setValueCount(2); +// listWriter.endList(); +// } +// listVector.setValueCount(3); +// root.setRowCount(3); +// +// System.out.print(root.contentToTSVString()); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } +// +//} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ArrowVectorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ArrowVectorTest.java index e8fd41261..6c977c604 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ArrowVectorTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ArrowVectorTest.java @@ -1,88 +1,88 @@ -package com.alibaba.polardbx.executor.operator.scan; - -import org.junit.Test; -import org.apache.arrow.memory.BufferAllocator; -import org.apache.arrow.memory.RootAllocator; -import org.apache.arrow.vector.IntVector; -import org.apache.arrow.vector.VarCharVector; - -import org.apache.arrow.vector.FieldVector; -import org.apache.arrow.vector.dictionary.Dictionary; -import org.apache.arrow.vector.dictionary.DictionaryEncoder; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.apache.arrow.vector.types.pojo.DictionaryEncoding; - -import java.nio.charset.StandardCharsets; - -public class ArrowVectorTest { - @Test - public void test1() { - try ( - BufferAllocator allocator = new RootAllocator(); - IntVector intVector = new IntVector("intVector", allocator) - ) { - intVector.allocateNew(3); - intVector.set(0, 1); - intVector.set(1, 2); - intVector.set(2, 3); - intVector.setValueCount(3); - - System.out.print(intVector); - } - } - - @Test - public void test2() { - try ( - BufferAllocator allocator = new RootAllocator(); - VarCharVector varCharVector = new VarCharVector("varCharVector", allocator); - ) { - varCharVector.allocateNew(3); - varCharVector.set(0, "one".getBytes()); - varCharVector.set(1, "two".getBytes()); - varCharVector.set(2, "three".getBytes()); - varCharVector.setValueCount(3); - - System.out.print(varCharVector); - } - } - - @Test - public void test3() { - try (BufferAllocator root = new RootAllocator(); - VarCharVector countries = new VarCharVector("country-dict", root); - VarCharVector appUserCountriesUnencoded = new VarCharVector("app-use-country-dict", root) - ) { - countries.allocateNew(10); - countries.set(0, "Andorra".getBytes(StandardCharsets.UTF_8)); - countries.set(1, "Cuba".getBytes(StandardCharsets.UTF_8)); - countries.set(2, "Grecia".getBytes(StandardCharsets.UTF_8)); - countries.set(3, "Guinea".getBytes(StandardCharsets.UTF_8)); - countries.set(4, "Islandia".getBytes(StandardCharsets.UTF_8)); - countries.set(5, "Malta".getBytes(StandardCharsets.UTF_8)); - countries.set(6, "Tailandia".getBytes(StandardCharsets.UTF_8)); - countries.set(7, "Uganda".getBytes(StandardCharsets.UTF_8)); - countries.set(8, "Yemen".getBytes(StandardCharsets.UTF_8)); - countries.set(9, "Zambia".getBytes(StandardCharsets.UTF_8)); - countries.setValueCount(10); - - Dictionary countriesDictionary = new Dictionary(countries, - new DictionaryEncoding(/*id=*/1L, /*ordered=*/false, /*indexType=*/new ArrowType.Int(8, true))); - System.out.println("Dictionary: " + countriesDictionary); - - appUserCountriesUnencoded.allocateNew(5); - appUserCountriesUnencoded.set(0, "Andorra".getBytes(StandardCharsets.UTF_8)); - appUserCountriesUnencoded.set(1, "Guinea".getBytes(StandardCharsets.UTF_8)); - appUserCountriesUnencoded.set(2, "Islandia".getBytes(StandardCharsets.UTF_8)); - appUserCountriesUnencoded.set(3, "Malta".getBytes(StandardCharsets.UTF_8)); - appUserCountriesUnencoded.set(4, "Uganda".getBytes(StandardCharsets.UTF_8)); - appUserCountriesUnencoded.setValueCount(5); - System.out.println("Unencoded data: " + appUserCountriesUnencoded); - - try (FieldVector appUserCountriesDictionaryEncoded = (FieldVector) DictionaryEncoder - .encode(appUserCountriesUnencoded, countriesDictionary)) { - System.out.println("Dictionary-encoded data: " + appUserCountriesDictionaryEncoded); - } - } - } -} +//package com.alibaba.polardbx.executor.operator.scan; +// +//import org.junit.Test; +//import org.apache.arrow.memory.BufferAllocator; +//import org.apache.arrow.memory.RootAllocator; +//import org.apache.arrow.vector.IntVector; +//import org.apache.arrow.vector.VarCharVector; +// +//import org.apache.arrow.vector.FieldVector; +//import org.apache.arrow.vector.dictionary.Dictionary; +//import org.apache.arrow.vector.dictionary.DictionaryEncoder; +//import org.apache.arrow.vector.types.pojo.ArrowType; +//import org.apache.arrow.vector.types.pojo.DictionaryEncoding; +// +//import java.nio.charset.StandardCharsets; +// +//public class ArrowVectorTest { +// @Test +// public void test1() { +// try ( +// BufferAllocator allocator = new RootAllocator(); +// IntVector intVector = new IntVector("intVector", allocator) +// ) { +// intVector.allocateNew(3); +// intVector.set(0, 1); +// intVector.set(1, 2); +// intVector.set(2, 3); +// intVector.setValueCount(3); +// +// System.out.print(intVector); +// } +// } +// +// @Test +// public void test2() { +// try ( +// BufferAllocator allocator = new RootAllocator(); +// VarCharVector varCharVector = new VarCharVector("varCharVector", allocator); +// ) { +// varCharVector.allocateNew(3); +// varCharVector.set(0, "one".getBytes()); +// varCharVector.set(1, "two".getBytes()); +// varCharVector.set(2, "three".getBytes()); +// varCharVector.setValueCount(3); +// +// System.out.print(varCharVector); +// } +// } +// +// @Test +// public void test3() { +// try (BufferAllocator root = new RootAllocator(); +// VarCharVector countries = new VarCharVector("country-dict", root); +// VarCharVector appUserCountriesUnencoded = new VarCharVector("app-use-country-dict", root) +// ) { +// countries.allocateNew(10); +// countries.set(0, "Andorra".getBytes(StandardCharsets.UTF_8)); +// countries.set(1, "Cuba".getBytes(StandardCharsets.UTF_8)); +// countries.set(2, "Grecia".getBytes(StandardCharsets.UTF_8)); +// countries.set(3, "Guinea".getBytes(StandardCharsets.UTF_8)); +// countries.set(4, "Islandia".getBytes(StandardCharsets.UTF_8)); +// countries.set(5, "Malta".getBytes(StandardCharsets.UTF_8)); +// countries.set(6, "Tailandia".getBytes(StandardCharsets.UTF_8)); +// countries.set(7, "Uganda".getBytes(StandardCharsets.UTF_8)); +// countries.set(8, "Yemen".getBytes(StandardCharsets.UTF_8)); +// countries.set(9, "Zambia".getBytes(StandardCharsets.UTF_8)); +// countries.setValueCount(10); +// +// Dictionary countriesDictionary = new Dictionary(countries, +// new DictionaryEncoding(/*id=*/1L, /*ordered=*/false, /*indexType=*/new ArrowType.Int(8, true))); +// System.out.println("Dictionary: " + countriesDictionary); +// +// appUserCountriesUnencoded.allocateNew(5); +// appUserCountriesUnencoded.set(0, "Andorra".getBytes(StandardCharsets.UTF_8)); +// appUserCountriesUnencoded.set(1, "Guinea".getBytes(StandardCharsets.UTF_8)); +// appUserCountriesUnencoded.set(2, "Islandia".getBytes(StandardCharsets.UTF_8)); +// appUserCountriesUnencoded.set(3, "Malta".getBytes(StandardCharsets.UTF_8)); +// appUserCountriesUnencoded.set(4, "Uganda".getBytes(StandardCharsets.UTF_8)); +// appUserCountriesUnencoded.setValueCount(5); +// System.out.println("Unencoded data: " + appUserCountriesUnencoded); +// +// try (FieldVector appUserCountriesDictionaryEncoded = (FieldVector) DictionaryEncoder +// .encode(appUserCountriesUnencoded, countriesDictionary)) { +// System.out.println("Dictionary-encoded data: " + appUserCountriesDictionaryEncoded); +// } +// } +// } +//} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/BlockCacheManagerSizeTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/BlockCacheManagerSizeTest.java new file mode 100644 index 000000000..222273b38 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/BlockCacheManagerSizeTest.java @@ -0,0 +1,100 @@ +package com.alibaba.polardbx.executor.operator.scan; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.BlockBuilder; +import com.alibaba.polardbx.executor.chunk.BlockBuilders; +import com.alibaba.polardbx.executor.operator.scan.impl.SimpleBlockCacheManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.apache.hadoop.fs.Path; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; +import java.util.Map; +import java.util.Random; + +public class BlockCacheManagerSizeTest { + private Random random = new Random(); + private ExecutionContext context = new ExecutionContext(); + private BlockCacheManager blockCacheManager; + + @Test + public void sizeTest() { + final int chunkLimit = 1000; + final int rowCountInGroup = 4500; + + synchronized (BlockCacheManager.class) { + blockCacheManager = new SimpleBlockCacheManager(); + blockCacheManager.clear(); + long initialSize = blockCacheManager.getMemorySize(); + + final Path path = new Path("foo"); + Block block = createBlock(chunkLimit); + blockCacheManager.putCache( + block, chunkLimit, rowCountInGroup, + path, 0, 0, 0, + 0, 1000 + ); + Assert.assertEquals(blockCacheManager.getMemorySize(), initialSize); + + block = createBlock(chunkLimit); + blockCacheManager.putCache( + block, chunkLimit, rowCountInGroup, + path, 0, 0, 0, + 1000, 1000 + ); + Assert.assertEquals(blockCacheManager.getMemorySize(), initialSize); + + block = createBlock(chunkLimit); + blockCacheManager.putCache( + block, chunkLimit, rowCountInGroup, + path, 0, 0, 0, + 2000, 1000 + ); + Assert.assertEquals(blockCacheManager.getMemorySize(), initialSize); + + block = createBlock(chunkLimit); + blockCacheManager.putCache( + block, chunkLimit, rowCountInGroup, + path, 0, 0, 0, + 3000, 1000 + ); + Assert.assertEquals(blockCacheManager.getMemorySize(), initialSize); + + block = createBlock(500); + blockCacheManager.putCache( + block, chunkLimit, rowCountInGroup, + path, 0, 0, 0, + 4000, 500 + ); + long lastSize = blockCacheManager.getMemorySize(); + + block = createBlock(1000); + blockCacheManager.putCache( + block, chunkLimit, rowCountInGroup, + path, 0, 1, 0, + 0, 1000 + ); + Assert.assertEquals(blockCacheManager.getMemorySize(), lastSize); + + block = createBlock(1000); + blockCacheManager.putCache( + block, chunkLimit, rowCountInGroup, + path, 0, 1, 0, + 1000, 1000 + ); + Assert.assertEquals(blockCacheManager.getMemorySize(), lastSize); + } + } + + private Block createBlock(int positionCount) { + BlockBuilder blockBuilder = BlockBuilders.create(DataTypes.LongType, context, positionCount); + for (int i = 0; i < positionCount; i++) { + blockBuilder.writeLong(random.nextLong()); + } + return blockBuilder.build(); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/CsvScanTestBase.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/CsvScanTestBase.java new file mode 100644 index 000000000..36e0d86dc --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/CsvScanTestBase.java @@ -0,0 +1,134 @@ +package com.alibaba.polardbx.executor.operator.scan; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.gms.DynamicColumnarManager; +import com.alibaba.polardbx.executor.operator.scan.impl.FlashbackScanPreProcessor; +import com.alibaba.polardbx.gms.engine.FileSystemUtils; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.Field; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.apache.calcite.rex.RexNode; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FSDataInputStream; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.stubbing.Answer; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static com.alibaba.polardbx.executor.gms.FileVersionStorageTestBase.FILE_META; +import static com.alibaba.polardbx.executor.gms.FileVersionStorageTestBase.openMockFile; +import static com.alibaba.polardbx.executor.gms.FileVersionStorageTestBase.prepareFileSystem; +import static com.alibaba.polardbx.executor.gms.FileVersionStorageTestBase.readMockFile; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public abstract class CsvScanTestBase { + + protected final static String DEL_FILE_NAME = "fb2604e133e6.del"; + protected final static String DATA_FILE_NAME = "6659a663977d.csv"; + protected FlashbackScanPreProcessor flashbackScanPreProcessor; + @Mock + protected Configuration configuration; + @Mock + protected FileSystem fileSystem; + + protected static DynamicColumnarManager columnarManager = mock(DynamicColumnarManager.class); + + protected static final String SCHEMA_NAME = ""; + protected static final String LOGICAL_TABLE_NAME = "1"; + private static final String PARTITION_NAME = "p1"; + protected static final Long TSO = 7182618688200114304L; + private static final Long FILE_LENGTH = 4088L; + protected static final int DELETE_COUNT = 1219; + protected static final Path TEST_FILE_PATH = new Path("/" + DEL_FILE_NAME); + protected static final Path DATA_FILE_PATH = new Path("/" + DATA_FILE_NAME); + + protected MockedStatic columnarManagerMockedStatic; + protected MockedStatic mockFsUtils; + + @Before + public void setUp() { + when(columnarManager.fileMetaOf(anyString())).thenReturn(FILE_META); + when(columnarManager.fileNameOf(anyString(), anyLong(), anyString(), anyInt())).thenReturn( + Optional.of(DATA_FILE_NAME)); + Map>> allDelPositions = new HashMap<>(); + allDelPositions.put(PARTITION_NAME, Collections.singletonList(new Pair<>(DEL_FILE_NAME, FILE_LENGTH))); + List columns = + Collections.singletonList(new ColumnMeta("t1", "pk", "pk", new Field(DataTypes.LongType))); + List rexList = Collections.emptyList(); // Mocked or real instance as needed + Map params = new HashMap<>(); + double groupsRatio = 0.5; + double deletionRatio = 0.5; + + flashbackScanPreProcessor = new FlashbackScanPreProcessor(configuration, + fileSystem, SCHEMA_NAME, LOGICAL_TABLE_NAME, true, true, columns, + rexList, params, groupsRatio, deletionRatio, columnarManager, TSO, + Collections.singletonList(1L), allDelPositions); + + columnarManagerMockedStatic = Mockito.mockStatic(ColumnarManager.class); + columnarManagerMockedStatic.when(ColumnarManager::getInstance).thenReturn(columnarManager); + + mockFsUtils = Mockito.mockStatic(FileSystemUtils.class); + mockFsUtils.when(() -> FileSystemUtils.fileExists(anyString(), any(Engine.class), anyBoolean())) + .thenReturn(true); + mockFsUtils.when( + () -> FileSystemUtils.readFile(anyString(), anyInt(), anyInt(), any(byte[].class), any(Engine.class), + anyBoolean()) + ).thenAnswer(mockFileReadAnswer); + mockFsUtils.when( + () -> FileSystemUtils.openStreamFileWithBuffer(anyString(), any(Engine.class), anyBoolean()) + ).thenAnswer(mockOpenFileAnswer); + } + + @BeforeClass + public static void beforeClass() { + prepareFileSystem(); + } + + @After + public void tearDown() { + if (columnarManagerMockedStatic != null) { + columnarManagerMockedStatic.close(); + } + if (mockFsUtils != null) { + mockFsUtils.close(); + } + } + + protected static final Answer mockFileReadAnswer = invocation -> { + Object[] args = invocation.getArguments(); + String fileName = (String) args[0]; + int offset = (Integer) args[1]; + int length = (Integer) args[2]; + byte[] output = (byte[]) args[3]; + + readMockFile(fileName, offset, length, output); + return null; + }; + + protected static final Answer mockOpenFileAnswer = invocation -> { + Object[] args = invocation.getArguments(); + String fileName = (String) args[0]; + + return openMockFile(fileName); + }; +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/DirectBlobColumnReaderTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/DirectBlobColumnReaderTest.java new file mode 100644 index 000000000..ca561d8c1 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/DirectBlobColumnReaderTest.java @@ -0,0 +1,120 @@ +package com.alibaba.polardbx.executor.operator.scan; + +import com.alibaba.polardbx.executor.chunk.BlobBlock; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.google.common.collect.ImmutableList; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hive.ql.exec.vector.BytesColumnVector; +import org.apache.hadoop.hive.ql.exec.vector.ColumnVector; +import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch; +import org.apache.orc.OrcConf; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Executors; + +public class DirectBlobColumnReaderTest extends ColumnTestBase { + + protected static final String TEST_ORC_FILE_NAME = "direct_blob_type.orc"; + private static final int COLUMN_ID = 1; + + @BeforeClass + public static void prepareStaticParams() throws IOException { + IO_EXECUTOR = Executors.newFixedThreadPool(IO_THREADS); + + CONFIGURATION = new Configuration(); + OrcConf.ROW_INDEX_STRIDE.setInt(CONFIGURATION, 1000); + FILE_PATH = new Path(getFileFromClasspath(TEST_ORC_FILE_NAME)); + + FILESYSTEM = FileSystem.get( + FILE_PATH.toUri(), CONFIGURATION + ); + } + + @Test + public void testSingleGroup() throws IOException { + final int columnId = COLUMN_ID + 1; + boolean[] columnIncluded = new boolean[fileSchema.getMaximumId() + 1]; + Arrays.fill(columnIncluded, false); + columnIncluded[0] = true; + columnIncluded[columnId] = true; + doTest(0, columnId, + columnIncluded, + fromRowGroupIds(0, new int[] {0}), + ImmutableList.of( + new ScanTestBase.BlockLocation(0, 0, 100), + new ScanTestBase.BlockLocation(0, 400, 300) + )); + } + + @Test + public void testMultiGroup() throws IOException { + final int columnId = COLUMN_ID + 1; + boolean[] columnIncluded = new boolean[fileSchema.getMaximumId() + 1]; + Arrays.fill(columnIncluded, false); + columnIncluded[0] = true; + columnIncluded[columnId] = true; + doTest(0, columnId, + columnIncluded, + fromRowGroupIds(0, new int[] {0, 1, 2}), + ImmutableList.of( + new ScanTestBase.BlockLocation(0, 0, 1000), + new ScanTestBase.BlockLocation(1, 1000, 700), + new ScanTestBase.BlockLocation(2, 2000, 500) + ) + ); + } + + @Override + protected void check(Block block, VectorizedRowBatch batch, int targetColumnId) { + Assert.assertTrue(block instanceof BlobBlock); + + for (int row = 0; row < batch.size; row++) { + ColumnVector vector = batch.cols[COLUMN_ID]; + + if (vector.isNull[row]) { + // check null + Assert.assertTrue(block.isNull(row)); + } else { + Assert.assertTrue(vector instanceof BytesColumnVector); + BytesColumnVector bytesColumnVector = (BytesColumnVector) vector; + int idx = row; + if (vector.isRepeating) { + idx = 0; + } + + byte[] bytes = new byte[bytesColumnVector.length[idx]]; + System.arraycopy(bytesColumnVector.vector[idx], bytesColumnVector.start[idx], bytes, 0, + bytesColumnVector.length[idx]); + try { + long length = block.getBlob(row).length(); + byte[] blobBytes = block.getBlob(row).getBytes(1, (int) length); + Assert.assertArrayEquals(bytes, blobBytes); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + } + } + + @Override + protected List createInputTypes() { + // int(id) + // blob + return ImmutableList.of(DataTypes.IntegerType, DataTypes.BlobType); + } + + @Override + protected String getOrcFilename() { + return TEST_ORC_FILE_NAME; + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ScanRangeTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ScanRangeTest.java new file mode 100644 index 000000000..2a715decc --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ScanRangeTest.java @@ -0,0 +1,349 @@ +package com.alibaba.polardbx.executor.operator.scan; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.operator.scan.impl.AbstractScanWork; +import com.alibaba.polardbx.executor.operator.scan.impl.MorselColumnarSplit; +import com.alibaba.polardbx.executor.operator.scan.impl.NonBlockedScanPreProcessor; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.util.concurrent.ListenableFuture; +import org.apache.calcite.rex.RexNode; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openjdk.jol.info.GraphLayout; +import org.roaringbitmap.RoaringBitmap; + +import java.io.IOException; +import java.util.BitSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; + +public class ScanRangeTest extends ScanTestBase { + private final static ExecutorService SCAN_WORK_EXECUTOR = Executors.newFixedThreadPool(4); + + public static final int MORSEL_UNIT = 1024; + private static final long ESTIMATED_SIZE_IN_BYTES_BEFORE_CLOSE = 8 * 1024 * 1024; // 8MB + + // need trace_id or other session-level parameters. + private ExecutionContext context; + + // partial cache + private BlockCacheManager blockCacheManager; + + // NOTE: The inputRefs in RexNode must be in consistent with inputRefForFilter. + private RexNode predicate; + private List inputRefsForFilter; + private LazyEvaluator evaluator; + private RoaringBitmap deletionBitmap; + private TreeMap matrix; + + @Before + public void prepare() throws IOException { + context = new ExecutionContext(); + context.setTraceId(TRACE_ID); + + // Cached ranges + final int cachedStripeId = 0; + final int[] columnIds = new int[] {1, 2}; + final int[] cachedGroupIds = new int[] {0, 2}; + blockCacheManager = prepareCache( + cachedStripeId, columnIds, cachedGroupIds + ); + + // ($0 + 10000L) >= 0L + predicate = null; + + // NOTE: The inputRefs in RexNode must be in consistent with inputRefForFilter. + evaluator = null; + inputRefsForFilter = ImmutableList.of(); + deletionBitmap = new RoaringBitmap(); + } + + @Test + public void test1() throws Throwable { + matrix = new TreeMap<>(); + matrix.put(0, fromRowGroupIds(0, new int[] {0, 1, 2, 3, 4, 8, 10, 12, 14, 16, 18, 20, 21, 22})); + matrix.put(1, fromRowGroupIds(1, new int[] {2, 4, 7, 11, 19, 20})); + matrix.put(2, fromRowGroupIds(2, new int[] {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21})); + matrix.put(3, fromRowGroupIds(3, new int[] {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21})); + + doTest( + matrix, + ImmutableList.of(0, 1, 2, 3) + ); + } + + @Test + public void test2() throws Throwable { + matrix = new TreeMap<>(); + matrix.put(0, fromRowGroupIds(0, new int[] {0, 1, 2, 3, 4, 8, 10, 12, 14, 16, 18, 20, 21, 22})); + matrix.put(1, fromRowGroupIds(1, new int[] {})); + matrix.put(2, fromRowGroupIds(2, new int[] {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21})); + matrix.put(3, fromRowGroupIds(3, new int[] {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21})); + + doTest( + matrix, + ImmutableList.of(0, 1, 2, 3) + ); + } + + @Test + public void test3() throws Throwable { + matrix = new TreeMap<>(); + matrix.put(0, fromRowGroupIds(0, new int[] {0, 1, 2, 3, 4, 8, 10, 12, 14, 16, 18, 20, 21, 22})); + matrix.put(1, fromRowGroupIds(1, new int[] {2, 4, 7, 11, 19, 20})); + matrix.put(2, fromRowGroupIds(2, new int[] {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21})); + matrix.put(3, fromRowGroupIds(3, new int[] {})); + + doTest( + matrix, + ImmutableList.of(0, 1, 2, 3) + ); + } + + @Test + public void test4() throws Throwable { + matrix = new TreeMap<>(); + matrix.put(0, fromRowGroupIds(0, new int[] {})); + matrix.put(1, fromRowGroupIds(1, new int[] {2, 4, 7, 11, 19, 20})); + matrix.put(2, fromRowGroupIds(2, new int[] {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21})); + matrix.put(3, fromRowGroupIds(3, new int[] {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21})); + + doTest( + matrix, + ImmutableList.of(0, 1, 2, 3) + ); + } + + @Test + public void test5() throws Throwable { + matrix = new TreeMap<>(); + matrix.put(0, fromRowGroupIds(0, new int[] {})); + matrix.put(1, fromRowGroupIds(1, new int[] {})); + matrix.put(2, fromRowGroupIds(2, new int[] {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21})); + matrix.put(3, fromRowGroupIds(3, new int[] {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21})); + + doTest( + matrix, + ImmutableList.of(0, 1, 2, 3) + ); + } + + @Test + public void test6() throws Throwable { + matrix = new TreeMap<>(); + matrix.put(0, fromRowGroupIds(0, new int[] {})); + matrix.put(1, fromRowGroupIds(1, new int[] {})); + matrix.put(2, fromRowGroupIds(2, new int[] {})); + matrix.put(3, fromRowGroupIds(3, new int[] {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21})); + + doTest( + matrix, + ImmutableList.of(0, 1, 2, 3) + ); + } + + @Test + public void test7() throws Throwable { + matrix = new TreeMap<>(); + matrix.put(0, fromRowGroupIds(0, new int[] {})); + matrix.put(1, fromRowGroupIds(1, new int[] {2, 4, 7, 11, 19, 20})); + matrix.put(2, fromRowGroupIds(2, new int[] {})); + matrix.put(3, fromRowGroupIds(3, new int[] {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21})); + + doTest( + matrix, + ImmutableList.of(0, 1, 2, 3) + ); + } + + @Test + public void test8() throws Throwable { + matrix = new TreeMap<>(); + matrix.put(0, fromRowGroupIds(0, new int[] {})); + matrix.put(1, fromRowGroupIds(1, new int[] {})); + matrix.put(2, fromRowGroupIds(2, new int[] {})); + matrix.put(3, fromRowGroupIds(3, new int[] {2, 4, 7, 11, 19, 20})); + + doTest( + matrix, + ImmutableList.of(0, 1, 2, 3) + ); + } + + public void doTest( + SortedMap rowGroupMatrix, + List inputRefsForProject + ) + throws Throwable { + + long sizeInBytesBeforeClose = ESTIMATED_SIZE_IN_BYTES_BEFORE_CLOSE; + + Map> finishedWorks = new TreeMap<>(); + + context = new ExecutionContext(); + context.setTraceId(TRACE_ID); + + final int morselUnit = MORSEL_UNIT; + + NonBlockedScanPreProcessor preProcessor = new NonBlockedScanPreProcessor( + preheatFileMeta, rowGroupMatrix, deletionBitmap + ); + preProcessor.addFile(FILE_PATH); + + Set refSet = new TreeSet<>(); + refSet.addAll(inputRefsForProject); + refSet.addAll(inputRefsForFilter); + List columnMetas = refSet.stream().map(COLUMN_METAS::get).collect(Collectors.toList()); + List locInOrc = refSet.stream().map(LOC_IN_ORC::get).collect(Collectors.toList()); + + ColumnarSplit split = MorselColumnarSplit.newBuilder() + .executionContext(context) + .ioExecutor(IO_EXECUTOR) + .fileSystem(FILESYSTEM, Engine.LOCAL_DISK) + .configuration(CONFIGURATION) + .sequenceId(SEQUENCE_ID) + .file(FILE_PATH, FILE_ID) + .columnTransformer(new OSSColumnTransformer(columnMetas, columnMetas, null, null, locInOrc)) + .inputRefs(inputRefsForFilter, inputRefsForProject) + .cacheManager(blockCacheManager) + .chunkLimit(DEFAULT_CHUNK_LIMIT) + .morselUnit(morselUnit) + .pushDown(evaluator) + .prepare(preProcessor) + .columnarManager(mockColumnarManager) + .memoryAllocator(memoryAllocatorCtx) + .build(); + + Iterator iterator = new CustomIterator(matrix); + + ScanWork scanWork; + while ((scanWork = split.nextWork()) != null) { + System.out.println(scanWork.getWorkId()); + + MorselColumnarSplit.ScanRange scanRange = + ((AbstractScanWork) scanWork).getScanRange(); + System.out.println("scan range: " + scanRange); + Assert.assertTrue(iterator.hasNext()); + int expectedStripeId = iterator.next(); + Assert.assertEquals(expectedStripeId, scanRange.getStripeId()); + + // get status + IOStatus ioStatus = scanWork.getIOStatus(); + scanWork.invoke(SCAN_WORK_EXECUTOR); + + // Get chunks according to state. + boolean isCompleted = false; + while (!isCompleted) { + ScanState state = ioStatus.state(); + Chunk result; + switch (state) { + case READY: + case BLOCKED: { + result = ioStatus.popResult(); + if (result == null) { + ListenableFuture listenableFuture = ioStatus.isBlocked(); + listenableFuture.get(); + result = ioStatus.popResult(); + } + + // stripe = ... + // rgMatrix = ... + // proj_column = ... + // filter = ... + break; + } + case FINISHED: + + while ((result = ioStatus.popResult()) != null) { + + } + isCompleted = true; + + finishedWorks.put(scanWork.getWorkId(), scanWork); + long sizeInBytesAfterClose = GraphLayout.parseInstance(scanWork).totalSize(); + System.out.println("object size = " + GraphLayout.parseInstance(scanWork).totalSize()); + Assert.assertTrue(sizeInBytesAfterClose * 100 < sizeInBytesBeforeClose); + + break; + case FAILED: + isCompleted = true; + ioStatus.throwIfFailed(); + + break; + case CLOSED: + isCompleted = true; + + finishedWorks.put(scanWork.getWorkId(), scanWork); + break; + } + + } + Preconditions.checkArgument(((AbstractScanWork) scanWork).checkIfAllReadersClosed()); + + } + + Assert.assertTrue(!iterator.hasNext()); + + } + + public class CustomIterator implements Iterator { + private Iterator> iterator; + private Integer nextKey; + + public CustomIterator(TreeMap treeMap) { + this.iterator = treeMap.entrySet().iterator(); + findNext(); + } + + private void findNext() { + nextKey = null; + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + if (!isAllFalse(entry.getValue())) { + nextKey = entry.getKey(); + break; + } + } + } + + private boolean isAllFalse(boolean[] array) { + for (boolean b : array) { + if (b) { + return false; + } + } + return true; + } + + @Override + public boolean hasNext() { + return nextKey != null; + } + + @Override + public Integer next() { + if (nextKey == null) { + throw new java.util.NoSuchElementException(); + } + Integer currentKey = nextKey; + findNext(); // set up the next key + return currentKey; + } + } +} + diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ScanTestBase.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ScanTestBase.java index 6009a154d..7e637116f 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ScanTestBase.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ScanTestBase.java @@ -1,13 +1,12 @@ package com.alibaba.polardbx.executor.operator.scan; import com.alibaba.polardbx.common.utils.Pair; -import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; import com.alibaba.polardbx.executor.archive.schemaevolution.ColumnMetaWithTs; import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.chunk.BlockBuilder; import com.alibaba.polardbx.executor.chunk.BlockBuilders; import com.alibaba.polardbx.executor.chunk.Chunk; -import com.alibaba.polardbx.executor.chunk.IntegerBlock; +import com.alibaba.polardbx.executor.chunk.LongBlock; import com.alibaba.polardbx.executor.gms.ColumnarManager; import com.alibaba.polardbx.executor.operator.scan.impl.AsyncStripeLoader; import com.alibaba.polardbx.executor.operator.scan.impl.PreheatFileMeta; @@ -17,7 +16,6 @@ import com.alibaba.polardbx.optimizer.config.table.Field; import com.alibaba.polardbx.optimizer.config.table.FileMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.datatype.VarcharType; import com.alibaba.polardbx.optimizer.memory.MemoryAllocatorCtx; @@ -50,6 +48,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; @@ -151,7 +150,7 @@ public int compareTo(@NotNull ScanTestBase.BlockLocation that) { protected PreheatFileMeta preheatFileMeta; protected OrcTail orcTail; - protected static String getFileFromClasspath(String name) { + public static String getFileFromClasspath(String name) { URL url = ClassLoader.getSystemResource(name); if (url == null) { throw new IllegalArgumentException("Could not find " + name); @@ -431,6 +430,11 @@ public void reload() { } + @Override + public void reload(ReloadType type) { + + } + @Override public long latestTso() { return 0; @@ -459,12 +463,17 @@ public Pair, List> findFileNames(long tso, String logicalSc } @Override - public List csvData(long tso, String csvFileName) { + public Iterator csvData(long tso, String csvFileName) { + return null; + } + + @Override + public Iterator csvData(String csvFileName, long position) { return null; } @Override - public int fillSelection(String fileName, long tso, int[] selection, IntegerBlock positionBlock) { + public int fillSelection(String fileName, long tso, int[] selection, LongBlock positionBlock) { return 0; } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ScanWorkTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ScanWorkTest.java index 55f1eca61..9db0eab6c 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ScanWorkTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/ScanWorkTest.java @@ -56,7 +56,7 @@ import static org.apache.calcite.sql.type.SqlTypeName.BIGINT; public class ScanWorkTest extends ScanTestBase { - private final static ExecutorService SCAN_WORK_EXECUTOR = Executors.newFixedThreadPool(4); + protected final static ExecutorService SCAN_WORK_EXECUTOR = Executors.newFixedThreadPool(4); private final static RelDataTypeFactory TYPE_FACTORY = new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); @@ -65,16 +65,16 @@ public class ScanWorkTest extends ScanTestBase { public static final double RATIO = .3D; // need trace_id or other session-level parameters. - private ExecutionContext context; + protected ExecutionContext context; // partial cache - private BlockCacheManager blockCacheManager; + protected BlockCacheManager blockCacheManager; // NOTE: The inputRefs in RexNode must be in consistent with inputRefForFilter. private RexNode predicate; - private List inputRefsForFilter; - private LazyEvaluator evaluator; - private RoaringBitmap deletionBitmap; + protected List inputRefsForFilter; + protected LazyEvaluator evaluator; + protected RoaringBitmap deletionBitmap; @Before public void prepare() throws IOException { diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/SimpleBlockCacheManagerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/SimpleBlockCacheManagerTest.java index 8e39b81d8..287c1741f 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/SimpleBlockCacheManagerTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/SimpleBlockCacheManagerTest.java @@ -3,6 +3,7 @@ import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.chunk.BlockBuilder; import com.alibaba.polardbx.executor.chunk.BlockBuilders; +import com.alibaba.polardbx.executor.operator.scan.impl.SimpleBlockCacheManager; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import org.apache.hadoop.fs.Path; @@ -18,62 +19,68 @@ public class SimpleBlockCacheManagerTest { @Test public void testOneRowGroup() { - final int chunkLimit = 1000; - BlockCacheManager blockCacheManager = BlockCacheManager.getInstance(); - // It means 3 blocks in one row-group. - final Path path = new Path("foo"); - final int rowCountInGroup = 2900; - final int stripeId = 0; - final int rowGroupId = 0; - final int columnId = 0; - final boolean rowGroupIncluded[] = new boolean[1]; - rowGroupIncluded[0] = true; + synchronized (BlockCacheManager.class) { + final int chunkLimit = 1000; + BlockCacheManager blockCacheManager = new SimpleBlockCacheManager(); - // write range [0, 1000) - int position = 0; - int positionCount = 1000; - Block block = createBlock(positionCount); - blockCacheManager.putCache( - block, chunkLimit, rowCountInGroup, - path, stripeId, rowGroupId, columnId, - position, positionCount - ); + // It means 3 blocks in one row-group. + final Path path = new Path("foo"); + final int rowCountInGroup = 2900; + final int stripeId = 0; + final int rowGroupId = 0; + final int columnId = 0; + final boolean rowGroupIncluded[] = new boolean[1]; + rowGroupIncluded[0] = true; - // Not visible. - Map> cachedBlocks = - blockCacheManager.getCachedRowGroups(path, stripeId, columnId, rowGroupIncluded); - Assert.assertTrue(cachedBlocks.isEmpty()); + blockCacheManager.clear(); - // write range [1000, 2000) - position += positionCount; - positionCount = 1000; - block = createBlock(positionCount); - blockCacheManager.putCache( - block, chunkLimit, rowCountInGroup, - path, stripeId, rowGroupId, columnId, - position, positionCount - ); + // write range [0, 1000) + int position = 0; + int positionCount = 1000; + Block block = createBlock(positionCount); + blockCacheManager.putCache( + block, chunkLimit, rowCountInGroup, + path, stripeId, rowGroupId, columnId, + position, positionCount + ); - // Not visible. - cachedBlocks = blockCacheManager.getCachedRowGroups(path, stripeId, columnId, rowGroupIncluded); - Assert.assertTrue(cachedBlocks.isEmpty()); + // Not visible. + Map> cachedBlocks = + blockCacheManager.getCachedRowGroups(path, stripeId, columnId, rowGroupIncluded); + Assert.assertTrue(cachedBlocks.isEmpty()); - // write range [2000, 2900) - position += positionCount; - positionCount = 900; - block = createBlock(positionCount); - blockCacheManager.putCache( - block, chunkLimit, rowCountInGroup, - path, stripeId, rowGroupId, columnId, - position, positionCount - ); + // write range [1000, 2000) + position += positionCount; + positionCount = 1000; + block = createBlock(positionCount); + blockCacheManager.putCache( + block, chunkLimit, rowCountInGroup, + path, stripeId, rowGroupId, columnId, + position, positionCount + ); + + // Not visible. + cachedBlocks = blockCacheManager.getCachedRowGroups(path, stripeId, columnId, rowGroupIncluded); + Assert.assertTrue(cachedBlocks.isEmpty()); + + // write range [2000, 2900) + position += positionCount; + positionCount = 900; + block = createBlock(positionCount); + blockCacheManager.putCache( + block, chunkLimit, rowCountInGroup, + path, stripeId, rowGroupId, columnId, + position, positionCount + ); + + // Test seekable + cachedBlocks = blockCacheManager.getCachedRowGroups(path, stripeId, columnId, rowGroupIncluded); + SeekableIterator blockIterator = cachedBlocks.get(rowGroupId); + Block cached = blockIterator.seek(2000 + 1); + Assert.assertTrue(cached.getPositionCount() == 900); + } - // Test seekable - cachedBlocks = blockCacheManager.getCachedRowGroups(path, stripeId, columnId, rowGroupIncluded); - SeekableIterator blockIterator = cachedBlocks.get(rowGroupId); - Block cached = blockIterator.seek(2000 + 1); - Assert.assertTrue(cached.getPositionCount() == 900); } private Block createBlock(int positionCount) { diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/VarcharColumnReaderTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/VarcharColumnReaderTest.java index 91b00b310..5a1af2810 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/VarcharColumnReaderTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/VarcharColumnReaderTest.java @@ -100,6 +100,11 @@ public void doTest(int stripeId, int columnId, columnReader.startAt(location.rowGroupId, location.startPosition); columnReader.next((RandomAccessBlock) block, location.positionCount); + Slice slice = ((SliceBlock) block).getData(); + int bytesSize = ((byte[]) slice.getBase()).length; + int sliceSize = slice.length(); + Assert.assertTrue(bytesSize == sliceSize); + // Check block doValidate(block, columnId, stripeId, orcTail.getStripes(), location); } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/ColumnarStartAtTestBase.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/ColumnarStartAtTestBase.java index 67fa58242..4f5e4f021 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/ColumnarStartAtTestBase.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/ColumnarStartAtTestBase.java @@ -62,7 +62,8 @@ public class ColumnarStartAtTestBase { protected OrcIndex orcIndex; protected AsyncStripeLoader stripeLoader; protected boolean[] rowGroupIncluded; - private boolean[] columnIncluded; + protected boolean[] columnIncluded; + protected OrcProto.ColumnEncoding[] encodings; public ColumnarStartAtTestBase(String orcFileName, int columnId, int stripeId) throws IOException { this.orcFileName = orcFileName; @@ -138,7 +139,7 @@ protected void prepareReading() throws IOException { maxDiskRangeChunkLimit = OrcConf.ORC_MAX_DISK_RANGE_CHUNK_LIMIT.getInt(configuration); maxMergeDistance = OrcConf.MAX_MERGE_DISTANCE.getLong(configuration); - OrcProto.ColumnEncoding[] encodings = StaticStripePlanner.buildEncodings( + encodings = StaticStripePlanner.buildEncodings( encryption, columnIncluded, preheatFileMeta.getStripeFooter(stripeId) ); diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/CsvScanWorkTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/CsvScanWorkTest.java new file mode 100644 index 000000000..ae7995c70 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/CsvScanWorkTest.java @@ -0,0 +1,220 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.operator.scan.ColumnarSplit; +import com.alibaba.polardbx.executor.operator.scan.CsvScanTestBase; +import com.alibaba.polardbx.executor.operator.scan.IOStatus; +import com.alibaba.polardbx.executor.operator.scan.ScanState; +import com.alibaba.polardbx.executor.operator.scan.ScanWork; +import com.alibaba.polardbx.gms.engine.FileSystemUtils; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.ListenableFuture; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static com.alibaba.polardbx.executor.gms.FileVersionStorageTestBase.FILE_META; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; + +public class CsvScanWorkTest extends CsvScanTestBase { + private static ExecutorService SCAN_WORK_EXECUTOR; + + @BeforeClass + public static void setUpExecutor() { + SCAN_WORK_EXECUTOR = new MockExecutorService(); + } + + @Before + public void setUpColumnarManager() { + Mockito.doCallRealMethod().when(columnarManager).csvData(anyString(), anyLong()); + } + + @Test + public void testColumnarScan() { + // TODO(siyun): test normal csv columnar scan + } + + @Test + public void testColumnarFlashbackQuery() throws Throwable { + flashbackScanPreProcessor.addFile(DATA_FILE_PATH); + ListenableFuture preProcessorFuture = flashbackScanPreProcessor.prepare(SCAN_WORK_EXECUTOR, null, null); + preProcessorFuture.get(); + ColumnarSplit split = CsvColumnarSplit.newBuilder() + .executionContext(new ExecutionContext()) + .columnarManager(columnarManager) + .file(DATA_FILE_PATH, 0) + .position(86549L + 1775L) + .inputRefs(new ArrayList<>(), Lists.newArrayList(2, 3, 4, 5)) + .tso(7182618688200114304L) + .prepare(flashbackScanPreProcessor) + .columnTransformer( + new OSSColumnTransformer(FILE_META.getColumnMetas(), FILE_META.getColumnMetas(), null, null, + Lists.newArrayList(1, 2, 3, 4, 5, 6))) + .partNum(0) + .nodePartCount(1) + .build(); + + ScanWork scanWork; + int rowCount = 0; + while ((scanWork = split.nextWork()) != null) { + IOStatus ioStatus = scanWork.getIOStatus(); + scanWork.invoke(SCAN_WORK_EXECUTOR); + boolean isCompleted = false; + while (!isCompleted) { + ScanState state = ioStatus.state(); + Chunk result; + switch (state) { + case READY: + case BLOCKED: { + result = ioStatus.popResult(); + if (result == null) { + ListenableFuture listenableFuture = ioStatus.isBlocked(); + listenableFuture.get(); + result = ioStatus.popResult(); + } + + if (result != null) { + rowCount += result.getPositionCount(); + } + break; + } + case FINISHED: + while ((result = ioStatus.popResult()) != null) { + rowCount += result.getPositionCount(); + } + isCompleted = true; + break; + case FAILED: + isCompleted = true; + ioStatus.throwIfFailed(); + break; + case CLOSED: + isCompleted = true; + break; + } + } + } + Assert.assertEquals(25, rowCount); + } + + static class MockExecutorService implements ExecutorService { + private final ExecutorService executorService = Executors.newFixedThreadPool(4); + + @Override + public void shutdown() { + executorService.shutdown(); + } + + @NotNull + @Override + public List shutdownNow() { + return executorService.shutdownNow(); + } + + @Override + public boolean isShutdown() { + return executorService.isShutdown(); + } + + @Override + public boolean isTerminated() { + return executorService.isTerminated(); + } + + @Override + public boolean awaitTermination(long timeout, @NotNull TimeUnit unit) throws InterruptedException { + return executorService.awaitTermination(timeout, unit); + } + + @NotNull + @Override + public Future submit(@NotNull Callable task) { + return executorService.submit(task); + } + + @NotNull + @Override + public Future submit(@NotNull Runnable task, T result) { + return executorService.submit(task, result); + } + + @NotNull + @Override + public Future submit(@NotNull Runnable task) { + return executorService.submit(() -> { + try (MockedStatic columnarManagerMockedStatic = Mockito.mockStatic( + ColumnarManager.class); + MockedStatic mockFsUtils = Mockito.mockStatic(FileSystemUtils.class)) { + mockFsUtils.when(() -> FileSystemUtils.fileExists(anyString(), any(Engine.class), anyBoolean())) + .thenReturn(true); + mockFsUtils.when( + () -> FileSystemUtils.readFile(anyString(), anyInt(), anyInt(), any(byte[].class), + any(Engine.class), + anyBoolean()) + ).thenAnswer(mockFileReadAnswer); + mockFsUtils.when( + () -> FileSystemUtils.openStreamFileWithBuffer(anyString(), any(Engine.class), anyBoolean()) + ).thenAnswer(mockOpenFileAnswer); + columnarManagerMockedStatic.when(ColumnarManager::getInstance).thenReturn(columnarManager); + beforeClass(); + task.run(); + } + }); + } + + @NotNull + @Override + public List> invokeAll(@NotNull Collection> tasks) + throws InterruptedException { + return executorService.invokeAll(tasks); + } + + @NotNull + @Override + public List> invokeAll(@NotNull Collection> tasks, long timeout, + @NotNull TimeUnit unit) throws InterruptedException { + return executorService.invokeAll(tasks, timeout, unit); + } + + @NotNull + @Override + public T invokeAny(@NotNull Collection> tasks) + throws InterruptedException, ExecutionException { + return executorService.invokeAny(tasks); + } + + @Override + public T invokeAny(@NotNull Collection> tasks, long timeout, @NotNull TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + return executorService.invokeAny(tasks, timeout, unit); + } + + @Override + public void execute(@NotNull Runnable command) { + executorService.execute(command); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/EnumColumnDictionaryNonAsciiTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/EnumColumnDictionaryNonAsciiTest.java new file mode 100644 index 000000000..a44cde456 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/EnumColumnDictionaryNonAsciiTest.java @@ -0,0 +1,105 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.executor.chunk.BlockUtils; +import com.alibaba.polardbx.executor.chunk.EnumBlock; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import org.apache.hadoop.hive.ql.exec.vector.BytesColumnVector; +import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch; +import org.apache.orc.OrcFile; +import org.apache.orc.TypeDescription; +import org.apache.orc.Writer; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class EnumColumnDictionaryNonAsciiTest extends ColumnarStartAtTestBase { + private Map enumValues = new HashMap<>(); + private final String[] enumStrings = {"枚举值1", "枚举值2", "枚举值3", "枚举值4", "枚举值5", "枚举值6",}; + + public EnumColumnDictionaryNonAsciiTest() throws IOException { + super("dictionary_enum_test.orc", 1, 0); + } + + @Before + public void prepare() throws IOException { + prepareWriting(); + prepareReading(); + for (int i = 0; i < enumStrings.length; i++) { + enumValues.put(enumStrings[i], i); + } + } + + private void prepareWriting() throws IOException { + TypeDescription schema = TypeDescription.createStruct() + .addField("f1", TypeDescription.createString()); + + int rowCount = 31500; + + try (Writer writer = OrcFile.createWriter(filePath, + OrcFile.writerOptions(configuration) + .fileSystem(fileSystem) + .overwrite(true) + .rowIndexStride(DEFAULT_INDEX_STRIDE) + .setSchema(schema))) { + + VectorizedRowBatch batch = schema.createRowBatch(1000); + + for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { + + ((BytesColumnVector) batch.cols[0]).setVal(batch.size, + (enumStrings[rowIndex % enumStrings.length]).getBytes()); + + batch.size += 1; + if (batch.size == batch.getMaxSize()) { + writer.addRowBatch(batch); + batch.reset(); + } + } + if (batch.size > 0) { + writer.addRowBatch(batch); + batch.reset(); + } + } + } + + @Test + public void test() throws IOException { + + DictionaryEnumColumnReader directEnumColumnReader = new DictionaryEnumColumnReader( + columnId, false, + stripeLoader, + orcIndex, + null, encodings[columnId], indexStride, false + ); + + directEnumColumnReader.open(true, rowGroupIncluded); + + // Read position 1005, and value should be "枚举1005" + directEnumColumnReader.startAt(0, 1000); + EnumBlock block = new EnumBlock(1000, enumValues); + directEnumColumnReader.next(block, 1000); + RandomAccessBlock result = BlockUtils.fillSelection(block, new int[] {5}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), enumStrings[1005 % enumStrings.length], + result.elementAt(0)); + + // Read position 2010, and value should be "枚举2010" + directEnumColumnReader.startAt(0, 2000); + block = new EnumBlock(1000, enumValues); + directEnumColumnReader.next(block, 1000); + result = BlockUtils.fillSelection(block, new int[] {10}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), enumStrings[2010 % enumStrings.length], + result.elementAt(0)); + + // Read position 7333, and value should be "枚举7333" + directEnumColumnReader.startAt(0, 7000); + block = new EnumBlock(1000, enumValues); + directEnumColumnReader.next(block, 1000); + result = BlockUtils.fillSelection(block, new int[] {333}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), enumStrings[7333 % enumStrings.length], + result.elementAt(0)); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/EnumColumnNonAsciiTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/EnumColumnNonAsciiTest.java new file mode 100644 index 000000000..5fc0a900e --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/EnumColumnNonAsciiTest.java @@ -0,0 +1,101 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.executor.chunk.BlockUtils; +import com.alibaba.polardbx.executor.chunk.EnumBlock; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.optimizer.core.datatype.EnumType; +import org.apache.hadoop.hive.ql.exec.vector.BytesColumnVector; +import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch; +import org.apache.orc.OrcFile; +import org.apache.orc.TypeDescription; +import org.apache.orc.Writer; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +public class EnumColumnNonAsciiTest extends ColumnarStartAtTestBase { + private Map enumValues = new HashMap<>(); + + public EnumColumnNonAsciiTest() throws IOException { + super("direct_enum_test.orc", 1, 0); + } + + @Before + public void prepare() throws IOException { + prepareWriting(); + prepareReading(); + } + + private void prepareWriting() throws IOException { + TypeDescription schema = TypeDescription.createStruct() + .addField("f1", TypeDescription.createString()); + + int rowCount = 31500; + + try (Writer writer = OrcFile.createWriter(filePath, + OrcFile.writerOptions(configuration) + .fileSystem(fileSystem) + .overwrite(true) + .rowIndexStride(DEFAULT_INDEX_STRIDE) + .setSchema(schema))) { + + VectorizedRowBatch batch = schema.createRowBatch(1000); + + for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { + + ((BytesColumnVector) batch.cols[0]).setVal(batch.size, ("枚举" + rowIndex).getBytes()); + + enumValues.put("枚举" + rowIndex, rowIndex); + + batch.size += 1; + if (batch.size == batch.getMaxSize()) { + writer.addRowBatch(batch); + batch.reset(); + } + } + if (batch.size > 0) { + writer.addRowBatch(batch); + batch.reset(); + } + } + } + + @Test + public void test() throws IOException { + + DirectEnumColumnReader directEnumColumnReader = new DirectEnumColumnReader( + columnId, false, + stripeLoader, + orcIndex, + null, indexStride, false, new EnumType(enumValues.keySet().stream().collect(Collectors.toList())) + ); + + directEnumColumnReader.open(true, rowGroupIncluded); + + // Read position 1005, and value should be "枚举1005" + directEnumColumnReader.startAt(0, 1000); + EnumBlock block = new EnumBlock(1000, enumValues); + directEnumColumnReader.next(block, 1000); + RandomAccessBlock result = BlockUtils.fillSelection(block, new int[] {5}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), "枚举1005", result.elementAt(0)); + + // Read position 2010, and value should be "枚举2010" + directEnumColumnReader.startAt(0, 2000); + block = new EnumBlock(1000, enumValues); + directEnumColumnReader.next(block, 1000); + result = BlockUtils.fillSelection(block, new int[] {10}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), "枚举2010", result.elementAt(0)); + + // Read position 7333, and value should be "枚举7333" + directEnumColumnReader.startAt(0, 7000); + block = new EnumBlock(1000, enumValues); + directEnumColumnReader.next(block, 1000); + result = BlockUtils.fillSelection(block, new int[] {333}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), "枚举7333", result.elementAt(0)); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/FlashbackScanPreProcessorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/FlashbackScanPreProcessorTest.java new file mode 100644 index 000000000..bd1bd0aa5 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/FlashbackScanPreProcessorTest.java @@ -0,0 +1,38 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.executor.operator.scan.CsvScanTestBase; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.Field; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Test; +import org.roaringbitmap.RoaringBitmap; + +import java.util.Collections; +import java.util.HashMap; + +import static org.junit.Assert.*; + +public class FlashbackScanPreProcessorTest extends CsvScanTestBase { + + @Test + public void testGenerateDeletionInColumnarMode() { + RoaringBitmap actualBitmap = flashbackScanPreProcessor.generateDeletion(DATA_FILE_PATH); + + assertEquals("Bitmaps should match in columnar mode", DELETE_COUNT, actualBitmap.getCardinality()); + } + + @Test + public void testGenerateDeletionInArchiveMode() { + // Setting conditions to simulate archive mode: tso and allDelPositions are null + flashbackScanPreProcessor = new FlashbackScanPreProcessor(configuration, + fileSystem, SCHEMA_NAME, LOGICAL_TABLE_NAME, true, true, + Collections.singletonList(new ColumnMeta("t1", "pk", "pk", new Field(DataTypes.LongType))), + Collections.emptyList(), new HashMap<>(), 0.5, 0.5, columnarManager, null, + Collections.singletonList(1L), null); + + RoaringBitmap actualBitmap = flashbackScanPreProcessor.generateDeletion(DATA_FILE_PATH); + + // In archive mode, the bitmap should be empty + assertEquals("Bitmap should be empty in archive mode", 0, actualBitmap.getCardinality()); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/JsonColumnDictionaryNonAsciiTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/JsonColumnDictionaryNonAsciiTest.java new file mode 100644 index 000000000..5c5460737 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/JsonColumnDictionaryNonAsciiTest.java @@ -0,0 +1,98 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.executor.chunk.BlockUtils; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.chunk.StringBlock; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.JsonType; +import org.apache.hadoop.hive.ql.exec.vector.BytesColumnVector; +import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch; +import org.apache.orc.OrcFile; +import org.apache.orc.TypeDescription; +import org.apache.orc.Writer; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; + +public class JsonColumnDictionaryNonAsciiTest extends ColumnarStartAtTestBase { + public JsonColumnDictionaryNonAsciiTest() throws IOException { + super("dictionary_json_test.orc", 1, 0); + } + + @Before + public void prepare() throws IOException { + prepareWriting(); + prepareReading(); + } + + private void prepareWriting() throws IOException { + TypeDescription schema = TypeDescription.createStruct() + .addField("f1", TypeDescription.createString()); + + int rowCount = 31500; + + try (Writer writer = OrcFile.createWriter(filePath, + OrcFile.writerOptions(configuration) + .fileSystem(fileSystem) + .overwrite(true) + .rowIndexStride(DEFAULT_INDEX_STRIDE) + .setSchema(schema))) { + + VectorizedRowBatch batch = schema.createRowBatch(1000); + + for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { + + // low cardinality. + ((BytesColumnVector) batch.cols[0]).setVal(batch.size, ("中文" + (rowIndex % 100)).getBytes()); + + batch.size += 1; + if (batch.size == batch.getMaxSize()) { + writer.addRowBatch(batch); + batch.reset(); + } + } + if (batch.size > 0) { + writer.addRowBatch(batch); + batch.reset(); + } + } + + } + + @Test + public void test() throws IOException { + + DataType inputType = new JsonType(); + + DictionaryJsonColumnReader dictionaryJsonColumnReader = new DictionaryJsonColumnReader( + columnId, false, + stripeLoader, + orcIndex, + null, encodings[columnId], indexStride, false); + + dictionaryJsonColumnReader.open(true, rowGroupIncluded); + + // Read position 1005, and value should be "中文1005" + dictionaryJsonColumnReader.startAt(0, 1000); + StringBlock block = new StringBlock(inputType, 1000); + dictionaryJsonColumnReader.next(block, 1000); + RandomAccessBlock result = BlockUtils.fillSelection(block, new int[] {5}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), "中文" + (1005 % 100), result.elementAt(0)); + + // Read position 2010, and value should be "中文2010" + dictionaryJsonColumnReader.startAt(0, 2000); + block = new StringBlock(inputType, 1000); + dictionaryJsonColumnReader.next(block, 1000); + result = BlockUtils.fillSelection(block, new int[] {10}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), "中文" + (2010 % 100), result.elementAt(0)); + + // Read position 7333, and value should be "中文7333" + dictionaryJsonColumnReader.startAt(0, 7000); + block = new StringBlock(inputType, 1000); + dictionaryJsonColumnReader.next(block, 1000); + result = BlockUtils.fillSelection(block, new int[] {333}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), "中文" + (7333 % 100), result.elementAt(0)); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/JsonColumnNonAsciiTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/JsonColumnNonAsciiTest.java new file mode 100644 index 000000000..90737a9de --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/JsonColumnNonAsciiTest.java @@ -0,0 +1,97 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.executor.chunk.BlockUtils; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.chunk.StringBlock; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.JsonType; +import org.apache.hadoop.hive.ql.exec.vector.BytesColumnVector; +import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch; +import org.apache.orc.OrcFile; +import org.apache.orc.TypeDescription; +import org.apache.orc.Writer; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; + +public class JsonColumnNonAsciiTest extends ColumnarStartAtTestBase { + public JsonColumnNonAsciiTest() throws IOException { + super("direct_json_test.orc", 1, 0); + } + + @Before + public void prepare() throws IOException { + prepareWriting(); + prepareReading(); + } + + private void prepareWriting() throws IOException { + TypeDescription schema = TypeDescription.createStruct() + .addField("f1", TypeDescription.createString()); + + int rowCount = 31500; + + try (Writer writer = OrcFile.createWriter(filePath, + OrcFile.writerOptions(configuration) + .fileSystem(fileSystem) + .overwrite(true) + .rowIndexStride(DEFAULT_INDEX_STRIDE) + .setSchema(schema))) { + + VectorizedRowBatch batch = schema.createRowBatch(1000); + + for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { + + ((BytesColumnVector) batch.cols[0]).setVal(batch.size, ("中文" + rowIndex).getBytes()); + + batch.size += 1; + if (batch.size == batch.getMaxSize()) { + writer.addRowBatch(batch); + batch.reset(); + } + } + if (batch.size > 0) { + writer.addRowBatch(batch); + batch.reset(); + } + } + } + + @Test + public void test() throws IOException { + + DataType inputType = new JsonType(); + + DirectJsonColumnReader directJsonColumnReader = new DirectJsonColumnReader( + columnId, false, + stripeLoader, + orcIndex, + null, indexStride, false, new JsonType() + ); + + directJsonColumnReader.open(true, rowGroupIncluded); + + // Read position 1005, and value should be "中文1005" + directJsonColumnReader.startAt(0, 1000); + StringBlock block = new StringBlock(inputType, 1000); + directJsonColumnReader.next(block, 1000); + RandomAccessBlock result = BlockUtils.fillSelection(block, new int[] {5}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), "中文1005", result.elementAt(0)); + + // Read position 2010, and value should be "中文2010" + directJsonColumnReader.startAt(0, 2000); + block = new StringBlock(inputType, 1000); + directJsonColumnReader.next(block, 1000); + result = BlockUtils.fillSelection(block, new int[] {10}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), "中文2010", result.elementAt(0)); + + // Read position 7333, and value should be "中文7333" + directJsonColumnReader.startAt(0, 7000); + block = new StringBlock(inputType, 1000); + directJsonColumnReader.next(block, 1000); + result = BlockUtils.fillSelection(block, new int[] {333}, 1, false, false, null); + Assert.assertEquals("actual = " + result.elementAt(0), "中文7333", result.elementAt(0)); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedCsvColumnarSplitTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedCsvColumnarSplitTest.java new file mode 100644 index 000000000..e44973b9d --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedCsvColumnarSplitTest.java @@ -0,0 +1,349 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.gms.DynamicColumnarManager; +import com.alibaba.polardbx.executor.gms.FileVersionStorage; +import com.alibaba.polardbx.executor.gms.FileVersionStorageTestBase; +import com.alibaba.polardbx.executor.operator.scan.ColumnarSplit; +import com.alibaba.polardbx.executor.operator.scan.IOStatus; +import com.alibaba.polardbx.executor.operator.scan.ScanState; +import com.alibaba.polardbx.executor.operator.scan.ScanWork; +import com.alibaba.polardbx.gms.engine.FileSystemGroup; +import com.alibaba.polardbx.gms.engine.FileSystemManager; +import com.alibaba.polardbx.gms.engine.FileSystemUtils; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarFileMappingAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarFileMappingRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.statis.ColumnarTracer; +import com.google.common.collect.ImmutableList; +import org.apache.hadoop.fs.Path; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class SpecifiedCsvColumnarSplitTest extends FileVersionStorageTestBase { + private final long minTso = 7182618494427463808L; + private final long maxTso = 7182618688200114304L; + private static final AtomicBoolean flag = new AtomicBoolean(false); + + @Test + public void test1() throws Throwable { + ExecutionContext executionContext = new ExecutionContext(); + // Should see nothing. + long tsoV0 = 1024; + long tsoV1 = minTso - 100L; + + long count = getActualRowCount(executionContext, tsoV0, tsoV1); + System.out.println("Total count: " + count); + Assert.assertEquals(count, 0); + } + + @Test + public void test2() throws Throwable { + ExecutionContext executionContext = new ExecutionContext(); + // Should see something. + long tsoV0 = minTso - 1024; + long tsoV1 = maxTso; + + long count = getActualRowCount(executionContext, tsoV0, tsoV1); + System.out.println("Total count: " + count); + Assert.assertTrue(count > 0); + } + + @Test + public void test3() throws Throwable { + ExecutionContext executionContext = new ExecutionContext(); + // Should see nothing. + long tsoV0 = maxTso; + long tsoV1 = maxTso + 1024; + + long count = getActualRowCount(executionContext, tsoV0, tsoV1); + System.out.println("Total count: " + count); + Assert.assertEquals(count, 0); + } + + private static long getActualRowCount(ExecutionContext executionContext, long tsoV0, long tsoV1) throws Throwable { + SpecifiedCsvColumnarSplit.ColumnarSplitBuilder builder = SpecifiedCsvColumnarSplit.newBuilder(); + long delBegin = DEL_STATUS[0].appendOffset; + long delEnd = DEL_STATUS[DEL_STATUS.length - 1].appendOffset + + DEL_STATUS[DEL_STATUS.length - 1].appendLength; + int csvBegin = (int) CSV_STATUSES[0].appendOffset; + int csvEnd = (int) (CSV_STATUSES[CSV_STATUSES.length - 1].appendOffset + + CSV_STATUSES[CSV_STATUSES.length - 1].appendLength); + Path csvfilePath = new Path(ClassLoader.getSystemResource(CSV_FILE_NAME).getPath()); + List columnMetas = FILE_META.getColumnMetas(); + List locInOrc = ImmutableList.of(1, 2, 3, 4, 5, 6); + OSSColumnTransformer ossColumnTransformer = + new OSSColumnTransformer(columnMetas, columnMetas, null, null, locInOrc); + + boolean localFlag = flag.get(); + flag.set(!localFlag); + List delFiles = null; + List delBeginPos = null; + List delEndPos = null; + if (localFlag) { + delFiles = ImmutableList.of(DEL_FILE_NAME); + delBeginPos = ImmutableList.of(delBegin); + delEndPos = ImmutableList.of(delEnd); + } + + SpecifiedDeleteBitmapPreProcessor preProcessor = new SpecifiedDeleteBitmapPreProcessor( + FILESYSTEM.getConf(), + FILESYSTEM, + "db1", + "tb1", + false, + false, + columnMetas, + new ArrayList<>(), + new HashMap<>(), + 0, + 0, + DynamicColumnarManager.getInstance(), + tsoV1, + new ArrayList<>(), + delFiles, + delBeginPos, + delEndPos, + Engine.LOCAL_DISK, + 1 + ); + + if (!localFlag) { + delFiles = ImmutableList.of(DEL_FILE_NAME); + delBeginPos = ImmutableList.of(delBegin); + delEndPos = ImmutableList.of(delEnd); + preProcessor.addDelFiles(delFiles, delBeginPos, delEndPos, 1L); + } + + ExecutorService executorService = mock(ExecutorService.class); + when(executorService.submit(any(Runnable.class))).thenAnswer( + invocation -> { + Runnable runnable = invocation.getArgument(0); + runnable.run(); + return null; + } + ); + preProcessor.prepare(executorService, "traceId", new ColumnarTracer("default")); + + builder.executionContext(executionContext) + .columnarManager(DynamicColumnarManager.getInstance()) + .isColumnarMode(true) + .tso(tsoV1) + .position(null) + .ioExecutor(null) + .fileSystem(FILESYSTEM, Engine.LOCAL_DISK) + .configuration(FILESYSTEM.getConf()) + .sequenceId(1) + .file(csvfilePath, CSV_FILE_ID) + .tableMeta("db1", "tb1") + .columnTransformer(ossColumnTransformer) + .inputRefs(new ArrayList<>(), ImmutableList.of(1)) + .cacheManager(null) + .chunkLimit(1024) + .morselUnit(1) + .pushDown(null) + .prepare(preProcessor) + .partNum(8) + .nodePartCount(8) + .memoryAllocator(null) + .fragmentRFManager(null) + .operatorStatistic(null) + .begin(csvBegin) + .end(csvEnd) + .tsoV0(tsoV0) + .tsoV1(tsoV1); + + ColumnarSplit split = builder.build(); + Assert.assertTrue(split instanceof SpecifiedCsvColumnarSplit); + + ScanWork scanWork; + long count = 0; + while ((scanWork = split.nextWork()) != null) { + Assert.assertTrue(scanWork instanceof SpecifiedCsvScanWork); + ((SpecifiedCsvScanWork) scanWork).handleNextWork(); + IOStatus ioStatus = scanWork.getIOStatus(); + Assert.assertSame(ioStatus.state(), ScanState.FINISHED); + Chunk chunk = ioStatus.popResult(); + if (null != chunk) { + count += chunk.getPositionCount(); + } + } + return count; + } + + @Before + public void prepareFileVersionStorage() { + mockCm = Mockito.mockStatic(DynamicColumnarManager.class); + + DynamicColumnarManager mockDynamicColumnarManager = mock(DynamicColumnarManager.class); + mockCm.when(DynamicColumnarManager::getInstance).thenReturn(mockDynamicColumnarManager); + + Mockito.when(mockDynamicColumnarManager.fileMetaOf(anyString())).thenReturn(FILE_META); + + this.fileVersionStorage = new FileVersionStorage(mockDynamicColumnarManager); + this.fileVersionStorage.open(); + + mockFsUtils = Mockito.mockStatic(FileSystemUtils.class); + mockFsUtils.when( + () -> FileSystemUtils.fileExists(anyString(), any(Engine.class), anyBoolean()) + ).thenReturn( + true + ); + mockFsUtils.when( + () -> FileSystemUtils.readFile( + anyString(), anyInt(), anyInt(), any(byte[].class), any(Engine.class), anyBoolean() + ) + ).thenAnswer( + mockFileReadAnswer + ); + mockFsUtils.when( + () -> FileSystemUtils.openStreamFileWithBuffer( + anyString(), any(Engine.class), anyBoolean() + ) + ).thenAnswer( + mockOpenFileAnswer + ); + mockFsUtils.when( + () -> FileSystemUtils.buildPath(eq(FILESYSTEM), any(), eq(true)) + ).thenReturn(new Path(ClassLoader.getSystemResource(CSV_FILE_NAME).getPath())); + + FileSystemGroup fileSystemGroup = Mockito.mock(FileSystemGroup.class); + mockFsManager = Mockito.mockStatic(FileSystemManager.class); + mockFsManager.when( + () -> FileSystemManager.getFileSystemGroup(any()) + ).thenReturn( + fileSystemGroup + ); + Mockito.when(fileSystemGroup.getMaster()).thenReturn(FILESYSTEM); + + mockMetaDbUtil = Mockito.mockStatic(MetaDbUtil.class); + mockMetaDbUtil.when(MetaDbUtil::getConnection).thenReturn(null); + + mockCafCtor = Mockito.mockConstruction(ColumnarAppendedFilesAccessor.class, (mock, context) -> { + + /** + * Mock method for csv + */ + Mockito.when( + mock.queryLatestByFileNameBetweenTso(anyString(), anyLong(), anyLong()) + ).thenAnswer( + invocationOnMock -> { + Object[] args = invocationOnMock.getArguments(); + String fileName = (String) args[0]; + long lowerTso = (long) args[1]; + long upperTso = (long) args[2]; + List appendedFilesRecords = new ArrayList<>(); + for (int i = CSV_STATUSES.length - 1; i >= 0; i--) { + MockAppendedFilesStatus appendedFilesStatus = CSV_STATUSES[i]; + if (appendedFilesStatus.checkpointTso > lowerTso + && appendedFilesStatus.checkpointTso <= upperTso) { + appendedFilesRecords.add(appendedFilesStatus.toAppendedFilesRecord(fileName)); + break; + } + } + return appendedFilesRecords; + } + ); + + /** + * Mock method for csv + */ + Mockito.when( + mock.queryByFileNameBetweenTso(anyString(), anyLong(), anyLong()) + ).thenAnswer( + invocationOnMock -> { + Object[] args = invocationOnMock.getArguments(); + String fileName = (String) args[0]; + long lowerTso = (long) args[1]; + long upperTso = (long) args[2]; + List appendedFilesRecords = new ArrayList<>(); + for (MockAppendedFilesStatus appendedFilesStatus : CSV_STATUSES) { + if (appendedFilesStatus.checkpointTso > lowerTso + && appendedFilesStatus.checkpointTso <= upperTso) { + appendedFilesRecords.add(appendedFilesStatus.toAppendedFilesRecord(fileName)); + } + } + return appendedFilesRecords; + } + ); + + /** + * Mock method for delete bitmap + */ + Mockito.when( + mock.queryByFileNameAndMaxTso(anyString(), anyLong()) + ).thenAnswer( + invocationOnMock -> { + Object[] args = invocationOnMock.getArguments(); + String fileName = (String) args[0]; + long tso = (long) args[1]; + List appendedFilesRecords = new ArrayList<>(); + for (int i = DEL_STATUS.length - 1; i >= 0; i--) { + MockAppendedFilesStatus appendedFilesStatus = DEL_STATUS[i]; + if (appendedFilesStatus.checkpointTso <= tso) { + appendedFilesRecords.add(appendedFilesStatus.toAppendedFilesRecord(fileName)); + break; + } + } + return appendedFilesRecords; + } + ); + + /** + * Mock method for delete bitmap + */ + Mockito.when( + mock.queryDelByPartitionBetweenTso(anyString(), anyString(), anyString(), anyLong(), anyLong()) + ).thenAnswer( + invocationOnMock -> { + Object[] args = invocationOnMock.getArguments(); + long lowerTso = (long) args[3]; + long upperTso = (long) args[4]; + List appendedFilesRecords = new ArrayList<>(); + for (MockAppendedFilesStatus appendedFilesStatus : DEL_STATUS) { + if (appendedFilesStatus.checkpointTso > lowerTso + && appendedFilesStatus.checkpointTso <= upperTso) { + appendedFilesRecords.add(appendedFilesStatus.toAppendedFilesRecord(DEL_FILE_NAME)); + } + } + return appendedFilesRecords; + } + ); + }); + + ColumnarFileMappingRecord columnarFileMappingRecord = new ColumnarFileMappingRecord(); + columnarFileMappingRecord.setFileName(CSV_FILE_NAME); + columnarFileMappingRecord.setColumnarFileId(CSV_FILE_ID); + mockCfmCtor = Mockito.mockConstruction(ColumnarFileMappingAccessor.class, (mock, context) -> { + Mockito.when( + mock.queryByFileIdList(any(), anyString(), anyLong()) + ).thenReturn( + ImmutableList.of(columnarFileMappingRecord) + ); + }); + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedOrcColumnarSplitTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedOrcColumnarSplitTest.java new file mode 100644 index 000000000..a55e3def9 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/SpecifiedOrcColumnarSplitTest.java @@ -0,0 +1,245 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.executor.archive.reader.OSSColumnTransformer; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.mpp.planner.FragmentRFManager; +import com.alibaba.polardbx.executor.operator.scan.ColumnarSplit; +import com.alibaba.polardbx.executor.operator.scan.IOStatus; +import com.alibaba.polardbx.executor.operator.scan.ScanState; +import com.alibaba.polardbx.executor.operator.scan.ScanWork; +import com.alibaba.polardbx.executor.operator.scan.ScanWorkTest; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.Field; +import com.alibaba.polardbx.optimizer.core.datatype.VarcharType; +import com.alibaba.polardbx.optimizer.statis.OperatorStatistics; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.util.concurrent.ListenableFuture; +import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.orc.TypeDescription; +import org.junit.After; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +import static com.alibaba.polardbx.optimizer.config.table.OrcMetaUtils.TYPE_FACTORY; +import static org.mockito.Mockito.mock; + +public class SpecifiedOrcColumnarSplitTest extends ScanWorkTest { + public static TypeDescription SCHEMA = TypeDescription.createStruct(); + protected TypeDescription backupSchema = null; + protected List backupColumnMeta = null; + protected List backLocInOrc = null; + private long tsoV0 = 100L; + private long tsoV1 = 200L; + + static { + SCHEMA.addField("pk", TypeDescription.createLong()); + SCHEMA.addField("i0", TypeDescription.createLong()); + SCHEMA.addField("order_id", TypeDescription.createString()); + SCHEMA.addField("v0", TypeDescription.createString()); + } + + @Test + @Override + public void test1() { + setTso(); + ColumnarSplit split = getSplit(); + Assert.assertTrue(split instanceof SpecifiedOrcColumnarSplit); + } + + @After + public void after() { + context.getParamManager().getProps().put("CCI_INCREMENTAL_CHECK", "false"); + if (backupColumnMeta != null) { + COLUMN_METAS.clear(); + COLUMN_METAS.addAll(backupColumnMeta); + } + if (backLocInOrc != null) { + LOC_IN_ORC.clear(); + LOC_IN_ORC.addAll(backLocInOrc); + } + if (backupSchema != null) { + SCHEMA = backupSchema; + } + } + + @Test + @Override + public void test2() throws ExecutionException, InterruptedException { + setTso(); + // 100-200: nothing can be seen + tsoV0 = 100L; + tsoV1 = 200L; + context.getParamManager().getProps().put("CCI_INCREMENTAL_CHECK", "true"); + shouldSeenRows(0); + } + + @Test + @Override + public void test3() throws ExecutionException, InterruptedException { + setTso(); + // 100000-100001: should see only one row + tsoV0 = 1000000L; + tsoV1 = 1000001L; + context.getParamManager().getProps().put("CCI_INCREMENTAL_CHECK", "true"); + shouldSeenRows(1); + } + + @Test + @Override + public void test4() throws ExecutionException, InterruptedException { + setTso(); + // 900000-900001: should see nothing + tsoV0 = 9000000L; + tsoV1 = 9000001L; + context.getParamManager().getProps().put("CCI_INCREMENTAL_CHECK", "true"); + shouldSeenRows(0); + } + + @Test + @Override + public void test5() throws ExecutionException, InterruptedException { + setTso(); + // 100000-100001: should see only one row + tsoV0 = 1000000L; + tsoV1 = 1000001L; + context.getParamManager().getProps().put("ENABLE_ORC_RAW_TYPE_BLOCK", "true"); + shouldSeenRows(1); + } + + private void shouldSeenRows(long expected) throws InterruptedException, ExecutionException { + ColumnarSplit split = getSplit(); + ScanWork scanWork; + long actual = 0; + while ((scanWork = split.nextWork()) != null) { + System.out.println(scanWork.getWorkId()); + + MorselColumnarSplit.ScanRange scanRange = + ((AbstractScanWork) scanWork).getScanRange(); + System.out.println("scan range: " + scanRange); + + // get status + IOStatus ioStatus = scanWork.getIOStatus(); + scanWork.invoke(SCAN_WORK_EXECUTOR); + + // Get chunks according to state. + boolean isCompleted = false; + while (!isCompleted) { + ScanState state = ioStatus.state(); + Chunk result; + switch (state) { + case READY: + case BLOCKED: { + result = ioStatus.popResult(); + if (result == null) { + ListenableFuture listenableFuture = ioStatus.isBlocked(); + listenableFuture.get(); + result = ioStatus.popResult(); + actual += null == result ? 0 : result.getPositionCount(); + } + break; + } + case FINISHED: + while ((result = ioStatus.popResult()) != null) { + actual += result.getPositionCount(); + } + isCompleted = true; + break; + case FAILED: + isCompleted = true; + ioStatus.throwIfFailed(); + break; + case CLOSED: + isCompleted = true; + break; + } + + } + Preconditions.checkArgument(((AbstractScanWork) scanWork).checkIfAllReadersClosed()); + } + Assert.assertTrue(expected == actual); + } + + private void setTso() { + backupSchema = SCHEMA; + SCHEMA = TypeDescription.createStruct(); + SCHEMA.addField("tso", TypeDescription.createLong()); + SCHEMA.addField("pos", TypeDescription.createLong()); + SCHEMA.addField("order_id", TypeDescription.createString()); + SCHEMA.addField("v0", TypeDescription.createString()); + + backupColumnMeta = new ArrayList<>(COLUMN_METAS); + COLUMN_METAS.clear(); + COLUMN_METAS.add(new ColumnMeta("t1", "order_id", "order_id", new Field(new VarcharType()))); + COLUMN_METAS.add(new ColumnMeta("t1", "v0", "v0", new Field(new VarcharType()))); + + backLocInOrc = new ArrayList<>(LOC_IN_ORC); + LOC_IN_ORC.clear(); + LOC_IN_ORC.add(3); + LOC_IN_ORC.add(4); + } + + private ColumnarSplit getSplit() { + Engine engine = Engine.LOCAL_DISK; + String schema = "test_schema"; + Set refSet = new TreeSet<>(); + List inputRefsForProject = ImmutableList.of(0); + refSet.addAll(inputRefsForProject); + List columnMetas = refSet.stream().map(COLUMN_METAS::get).collect(Collectors.toList()); + List locInOrc = refSet.stream().map(LOC_IN_ORC::get).collect(Collectors.toList()); + ColumnMeta tsoColumnMeta = new ColumnMeta("t1", "tso", null, + new Field(TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT))); + columnMetas.add(tsoColumnMeta); + locInOrc.add(1); + OSSColumnTransformer ossColumnTransformer = + new OSSColumnTransformer(columnMetas, columnMetas, null, null, locInOrc); + SortedMap matrix = new TreeMap<>(); + matrix.put(0, fromRowGroupIds(0, new int[] {0, 1, 2, 3, 4, 8, 10, 12, 14, 16, 18, 20, 21, 22})); + NonBlockedScanPreProcessor preProcessor = new NonBlockedScanPreProcessor( + preheatFileMeta, matrix, deletionBitmap + ); + preProcessor.addFile(FILE_PATH); + FragmentRFManager fragmentRFManager = mock(FragmentRFManager.class); + ColumnarManager columnarManager = mock(ColumnarManager.class); + OperatorStatistics operatorStatistics = mock(OperatorStatistics.class); + + ColumnarSplit.ColumnarSplitBuilder builder = SpecifiedOrcColumnarSplit.newBuilder(); + builder.executionContext(context); + builder.ioExecutor(IO_EXECUTOR); + builder.fileSystem(FILESYSTEM, engine); + builder.configuration(CONFIGURATION); + builder.sequenceId(1); + builder.file(FILE_PATH, 1); + builder.tableMeta(schema, "test_table"); + builder.columnTransformer(ossColumnTransformer); + builder.inputRefs(inputRefsForFilter, inputRefsForProject); + builder.cacheManager(blockCacheManager); + builder.chunkLimit(DEFAULT_CHUNK_LIMIT); + builder.morselUnit(1024); + builder.pushDown(evaluator); + builder.prepare(preProcessor); + builder.columnarManager(columnarManager); + builder.isColumnarMode(true); + builder.tso(100L); + builder.position(100L); + builder.partNum(8); + builder.nodePartCount(8); + builder.memoryAllocator(memoryAllocatorCtx); + builder.fragmentRFManager(fragmentRFManager); + builder.operatorStatistic(operatorStatistics); + builder.tsoV0(tsoV0); + builder.tsoV1(tsoV1); + return builder.build(); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/StripeLoaderEmptyGroupsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/StripeLoaderEmptyGroupsTest.java new file mode 100644 index 000000000..e7314f5d0 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/scan/impl/StripeLoaderEmptyGroupsTest.java @@ -0,0 +1,98 @@ +package com.alibaba.polardbx.executor.operator.scan.impl; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import org.apache.hadoop.hive.ql.exec.vector.DoubleColumnVector; +import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch; +import org.apache.orc.OrcFile; +import org.apache.orc.TypeDescription; +import org.apache.orc.Writer; +import org.apache.orc.impl.InStream; +import org.apache.orc.impl.StreamName; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +public class StripeLoaderEmptyGroupsTest extends ColumnarStartAtTestBase { + + public StripeLoaderEmptyGroupsTest() throws IOException { + super("StripeLoaderEmptyGroupsTest.orc", 1, 0); + } + + @Before + public void prepare() throws IOException { + prepareWriting(); + prepareReading(); + } + + private void prepareWriting() throws IOException { + TypeDescription schema = TypeDescription.createStruct() + .addField("f1", TypeDescription.createDouble()); + + int rowCount = 31500; + + try (Writer writer = OrcFile.createWriter(filePath, + OrcFile.writerOptions(configuration) + .fileSystem(fileSystem) + .overwrite(true) + .rowIndexStride(DEFAULT_INDEX_STRIDE) + .setSchema(schema))) { + + VectorizedRowBatch batch = schema.createRowBatch(1000); + + for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { + // Populate the rowIdx + ((DoubleColumnVector) batch.cols[0]).vector[batch.size] = rowIndex + 0.5d; + + batch.size += 1; + if (batch.size == batch.getMaxSize()) { + writer.addRowBatch(batch); + batch.reset(); + } + } + if (batch.size > 0) { + writer.addRowBatch(batch); + batch.reset(); + } + } + } + + @Test + public void testColumnReader() throws IOException { + DoubleColumnReader doubleColumnReader = new DoubleColumnReader( + columnId, false, + stripeLoader, + orcIndex, + null, indexStride, false + ); + + Arrays.fill(rowGroupIncluded, false); + doubleColumnReader.open(true, rowGroupIncluded); + + // this columnar reader is not accessible. + } + + @Test + public void testColumnLoading1() throws ExecutionException, InterruptedException { + Arrays.fill(rowGroupIncluded, false); + CompletableFuture> loadFuture = + stripeLoader.load(ImmutableList.of(columnId), ImmutableMap.of(columnId, rowGroupIncluded)); + Map result = loadFuture.get(); + Assert.assertTrue(result.isEmpty()); + } + + @Test + public void testColumnLoading2() throws ExecutionException, InterruptedException { + Arrays.fill(rowGroupIncluded, false); + CompletableFuture> loadFuture = + stripeLoader.load(columnId, rowGroupIncluded); + Map result = loadFuture.get(); + Assert.assertTrue(result.isEmpty()); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/util/EquiJoinMockData.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/util/EquiJoinMockData.java index c7842f551..15294b8fa 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/util/EquiJoinMockData.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/util/EquiJoinMockData.java @@ -55,6 +55,10 @@ public class EquiJoinMockData { ImmutableList.of(DataTypes.LongType, DataTypes.IntegerType, DataTypes.LongType); private static final List LONG_LONG_INT_LONG_TYPES = ImmutableList.of(DataTypes.LongType, DataTypes.LongType, DataTypes.IntegerType, DataTypes.LongType); + private static final List LONG_LONG_LONG_TYPES = + ImmutableList.of(DataTypes.LongType, DataTypes.LongType, DataTypes.LongType); + private static final List LONG_LONG_LONG_LONG_TYPES = + ImmutableList.of(DataTypes.LongType, DataTypes.LongType, DataTypes.LongType, DataTypes.LongType); private static final List ANTI_INT_NOT_EQ_INT_INNER_TYPES = ImmutableList.of(DataTypes.LongType, DataTypes.IntegerType, DataTypes.LongType, DataTypes.IntegerType); private static final List ANTI_INT_NOT_EQ_INT_OUTER_TYPES = @@ -194,6 +198,34 @@ public class EquiJoinMockData { ImmutableList.of(0), ImmutableList.of(0)); + public static EquiJoinMockData SEMI_LONG_NOT_EQ_LONG_CASE = new EquiJoinMockData( + LONG_LONG_LONG_LONG_TYPES, + new RowChunksBuilder(LONG_LONG_LONG_LONG_TYPES) + .addChunk(new Chunk( + LongBlock.of(1L, 2L, 3L, 4L), + LongBlock.of(3L, 4L, 5L, 6L), + LongBlock.of(3L, 4L, 5L, 6L), + LongBlock.of(-1L, -2L, -3L, -4L))) + .addChunk(new Chunk( + LongBlock.of(4L, 5L, 6L, 7L), + LongBlock.of(7L, 8L, 9L, 10L), + LongBlock.of(6L, 7L, 8L, 9L), + LongBlock.of(-1L, -2L, -3L, -4L))) + .build(), + LONG_LONG_LONG_TYPES, + new RowChunksBuilder(LONG_LONG_LONG_TYPES) + .addChunk(new Chunk( + LongBlock.of(0L, 1L, 3L, 3L), + LongBlock.of(3L, 4L, 5L, 7L), + LongBlock.of(11L, 12L, 13L, 14L))) + .addChunk(new Chunk( + LongBlock.of(4L, 5L, 6L, 7L), + LongBlock.of(5L, 7L, 8L, 10L), + LongBlock.of(15L, 16L, 17L, 18L))) + .build(), + ImmutableList.of(0), + ImmutableList.of(0)); + public static EquiJoinMockData SEMI_INT_NOT_EQ_INT_CASE = new EquiJoinMockData( LONG_INT_INT_TYPES, new RowChunksBuilder(LONG_INT_INT_TYPES) @@ -298,9 +330,9 @@ public class EquiJoinMockData { ImmutableList.of(0), ImmutableList.of(1)); - private static List SIMPLE_CASE_INNER_TYPES = + private static final List SIMPLE_CASE_INNER_TYPES = ImmutableList.of(DataTypes.IntegerType, DataTypes.StringType); - private static List SIMPLE_CASE_OUTER_TYPES = + private static final List SIMPLE_CASE_OUTER_TYPES = ImmutableList.of(DataTypes.IntegerType, DataTypes.IntegerType); public static EquiJoinMockData SIMPLE_CASE = new EquiJoinMockData( @@ -327,9 +359,9 @@ public class EquiJoinMockData { ImmutableList.of(0), ImmutableList.of(1)); - private static List SINGLE_JOIN_CASE_INNER_TYPES = + private static final List SINGLE_JOIN_CASE_INNER_TYPES = ImmutableList.of(DataTypes.StringType, DataTypes.IntegerType); - private static List SINGLE_JOIN_CASE_OUTER_TYPES = + private static final List SINGLE_JOIN_CASE_OUTER_TYPES = ImmutableList.of(DataTypes.IntegerType, DataTypes.IntegerType); public static EquiJoinMockData SINGLE_JOIN_CASE = new EquiJoinMockData( @@ -356,9 +388,9 @@ public class EquiJoinMockData { ImmutableList.of(1), ImmutableList.of(1)); - private static List MULTI_KEY_CASE_INNER_TYPES = + private static final List MULTI_KEY_CASE_INNER_TYPES = ImmutableList.of(DataTypes.IntegerType, DataTypes.StringType, DataTypes.StringType); - private static List MULTI_KEY_CASE_OUTER_TYPES = + private static final List MULTI_KEY_CASE_OUTER_TYPES = ImmutableList.of(DataTypes.IntegerType, DataTypes.IntegerType, DataTypes.StringType); public static EquiJoinMockData MULTI_KEY_CASE = new EquiJoinMockData( @@ -401,7 +433,7 @@ public class EquiJoinMockData { final List outerChunks; final List innerKeyIndexes; final List outerKeyIndexes; - boolean keyIsNullSafe[]; + boolean[] keyIsNullSafe; public EquiJoinMockData(List innerTypes, List innerChunks, List outerTypes, List outerChunks, diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/vectorized/GroupByTestBase.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/vectorized/GroupByTestBase.java index 9bf7463e7..d630ed6f0 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/vectorized/GroupByTestBase.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/operator/vectorized/GroupByTestBase.java @@ -458,7 +458,7 @@ protected Map getResults(DataType[] inputDataTypes, int[] groups Decimal result = sum.divide(Decimal.fromLong(count)); Decimal round = new Decimal(); FastDecimalUtils.round(result.getDecimalStructure(), round.getDecimalStructure(), - DecimalTypeBase.DEFAULT_DIV_PRECISION_INCREMENT, DecimalRoundMod.HALF_UP); + DecimalTypeBase.getDefaultDivPrecisionIncrement(), DecimalRoundMod.HALF_UP); ((List) aggResult[1]).set(finalAggIndex, round); }); diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/partitionmanagement/CheckCciPartitionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/partitionmanagement/CheckCciPartitionTest.java new file mode 100644 index 000000000..356cf3238 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/partitionmanagement/CheckCciPartitionTest.java @@ -0,0 +1,94 @@ +/* + * 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 com.alibaba.polardbx.executor.partitionmanagement; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class CheckCciPartitionTest { + @Mock + private ExecutionContext executionContext; + + @Mock + private TableMeta tableMeta; + + @Mock + private ParamManager paramManager; + + private static final String TABLE_NAME = "test_table"; + + @Before + public void setUp() { + when(executionContext.getParamManager()).thenReturn(paramManager); + + } + + @Test + public void testDropNoException() { + when(paramManager.getBoolean(any())).thenReturn(true); + AlterTableGroupUtils.checkAllDropTruncateCciPartition(executionContext, tableMeta, TABLE_NAME); + } + + @Test(expected = TddlRuntimeException.class) + public void testDropException1() { + when(paramManager.getBoolean(any())).thenReturn(false); + when(tableMeta.withCci()).thenReturn(true); + AlterTableGroupUtils.checkAllDropTruncateCciPartition(executionContext, tableMeta, TABLE_NAME); + } + + @Test(expected = TddlRuntimeException.class) + public void testDropException2() { + when(paramManager.getBoolean(any())).thenReturn(false); + when(tableMeta.withCci()).thenReturn(false); + when(tableMeta.isColumnar()).thenReturn(true); + AlterTableGroupUtils.checkAllDropTruncateCciPartition(executionContext, tableMeta, TABLE_NAME); + } + + @Test + public void testModifyNoException() { + when(paramManager.getBoolean(any())).thenReturn(true); + AlterTableGroupUtils.checkAllModifyListCciPartition(executionContext, tableMeta, TABLE_NAME); + } + + @Test(expected = TddlRuntimeException.class) + public void testModifyException1() { + when(paramManager.getBoolean(any())).thenReturn(false); + when(tableMeta.withCci()).thenReturn(true); + AlterTableGroupUtils.checkAllModifyListCciPartition(executionContext, tableMeta, TABLE_NAME); + } + + @Test(expected = TddlRuntimeException.class) + public void testModifyException2() { + when(paramManager.getBoolean(any())).thenReturn(false); + when(tableMeta.withCci()).thenReturn(false); + when(tableMeta.isColumnar()).thenReturn(true); + AlterTableGroupUtils.checkAllModifyListCciPartition(executionContext, tableMeta, TABLE_NAME); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/pl/PLUtilsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/pl/PLUtilsTest.java new file mode 100644 index 000000000..2bf1043af --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/pl/PLUtilsTest.java @@ -0,0 +1,69 @@ +package com.alibaba.polardbx.executor.pl; + +import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.optimizer.core.datatype.Blob; +import com.alibaba.polardbx.optimizer.core.datatype.EnumType; +import com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue; +import io.airlift.slice.Slice; +import io.airlift.slice.Slices; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; + +public class PLUtilsTest { + + @Test + public void testGetPrintStringWithNull() { + Assert.assertNull(PLUtils.getPrintString(null)); + } + + @Test + public void testGetPrintStringWithNumber() { + Assert.assertEquals("123", PLUtils.getPrintString(123)); + } + + @Test + public void testGetPrintStringWithDecimal() { + Decimal decimal = Decimal.fromString("1234567890123456"); + Assert.assertEquals("1234567890123456", PLUtils.getPrintString(decimal)); + } + + @Test + public void testGetPrintStringWithByteArray() { + byte[] bytes = new byte[] {0x1, 0x2, 0x3}; + Assert.assertEquals("0x010203", PLUtils.getPrintString(bytes)); + } + + @Test + public void testGetPrintStringWithBlob() { + Blob blob = new Blob("test".getBytes()); + Assert.assertEquals("0x74657374", PLUtils.getPrintString(blob)); + } + + @Test + public void testGetPrintStringWithSlice() { + Slice slice = Slices.wrappedBuffer("test".getBytes()); + Assert.assertEquals("'test'", PLUtils.getPrintString(slice)); + } + + @Test + public void testGetPrintStringWithEnumValue() { + EnumValue enumValue = new EnumValue(new EnumType(Arrays.asList("TEST_ENUM", "TEST")), "TEST"); + Assert.assertEquals("'TEST'", PLUtils.getPrintString(enumValue)); + } + + @Test + public void testGetPrintStringWithString() { + String stringWithSpecialChar = "it's a test"; + String expected = "'it''s a test'"; + Assert.assertEquals(expected, PLUtils.getPrintString(stringWithSpecialChar)); + } + + @Test + public void testGetPrintStringWithString2() { + String stringWithSpecialChar = "it\"s a test"; + String expected = "'it\"s a test'"; + Assert.assertEquals(expected, PLUtils.getPrintString(stringWithSpecialChar)); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scaleout/ScaleOutUtilsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scaleout/ScaleOutUtilsTest.java new file mode 100644 index 000000000..af7c050a4 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scaleout/ScaleOutUtilsTest.java @@ -0,0 +1,90 @@ +package com.alibaba.polardbx.executor.scaleout; + +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.executor.TddlGroupExecutor; +import com.alibaba.polardbx.executor.TopologyExecutor; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.ddl.job.builder.DropPhyTableBuilder; +import com.alibaba.polardbx.gms.topology.DbGroupInfoManager; +import com.alibaba.polardbx.gms.topology.DbGroupInfoRecord; +import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.group.jdbc.TGroupDataSource; +import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; + +/** + * Created by luoyanxin. + * + * @author luoyanxin + */ +public class ScaleOutUtilsTest { + @Test + public void checkTableExistenceTest() { + try (MockedStatic mockedDropPhyTableBuilder = Mockito.mockStatic( + DropPhyTableBuilder.class); + MockedStatic mockDbGroupInfoManager = Mockito.mockStatic( + DbGroupInfoManager.class); + MockedStatic mockExecutorContext = Mockito.mockStatic( + ExecutorContext.class);) { + + ExecutorContext mockEc = Mockito.mock(ExecutorContext.class); + TopologyExecutor mockTopologyExecutor = Mockito.mock(TopologyExecutor.class); + TddlGroupExecutor mockTddlGroupExecutor = Mockito.mock(TddlGroupExecutor.class); + TGroupDataSource mockTddlGroupDataSource = Mockito.mock(TGroupDataSource.class); + TGroupDirectConnection mockTddlGroupDirectConnection = Mockito.mock(TGroupDirectConnection.class); + PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class); + ResultSet mockRs = Mockito.mock(ResultSet.class); + + DbGroupInfoRecord DbGroupInfoRecord = new DbGroupInfoRecord(); + DbGroupInfoRecord.phyDbName = "ddd"; + DbGroupInfoManager mockDbGroupInfoMan = Mockito.mock(DbGroupInfoManager.class); + mockDbGroupInfoManager.when(() -> DbGroupInfoManager.getInstance()).thenReturn(mockDbGroupInfoMan); + mockExecutorContext.when(() -> ExecutorContext.getContext(anyString())).thenReturn(mockEc) + .thenReturn(mockEc); + + Mockito.when(mockEc.getTopologyExecutor()).thenReturn(mockTopologyExecutor); + Mockito.when(mockTopologyExecutor.getGroupExecutor(anyString())).thenReturn(mockTddlGroupExecutor); + Mockito.when(mockTddlGroupExecutor.getDataSource()).thenReturn(mockTddlGroupDataSource); + Mockito.when(mockTddlGroupDataSource.getConnection()).thenReturn(mockTddlGroupDirectConnection); + Mockito.when(mockTddlGroupDirectConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); + Mockito.when(mockPreparedStatement.executeQuery()).thenReturn(mockRs); + Mockito.when(mockRs.next()).thenReturn(true).thenReturn(false); + Mockito.when(mockDbGroupInfoMan.queryGroupInfo(anyString(), anyString())).thenReturn(DbGroupInfoRecord); + + Assert.assertTrue(ScaleOutUtils.checkTableExistence("test", "test", "test")); + Assert.assertFalse(ScaleOutUtils.checkTableExistence("test", "test", "test")); + + mockExecutorContext.when(() -> ExecutorContext.getContext(anyString())).thenReturn(null).thenReturn(mockEc); + try { + ScaleOutUtils.checkTableExistence("test", "test", "test"); + } catch (TddlNestableRuntimeException e) { + Assert.assertTrue(e.getMessage().contains("existence failed")); + } + + Mockito.when(mockPreparedStatement.executeQuery()).thenReturn(null); + try { + ScaleOutUtils.checkTableExistence("test", "test", "test"); + } catch (TddlNestableRuntimeException e) { + Assert.assertTrue(e.getMessage().contains("Error checking table existence")); + } + } catch (TddlNestableRuntimeException e) { + Assert.assertTrue(e.getMessage().contains("this DDL operation cannot be rolled back")); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scheduler/executor/LogSystemMetricsScheduledJobTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scheduler/executor/LogSystemMetricsScheduledJobTest.java new file mode 100644 index 000000000..dfc8ecbae --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scheduler/executor/LogSystemMetricsScheduledJobTest.java @@ -0,0 +1,148 @@ +package com.alibaba.polardbx.executor.scheduler.executor; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.executor.sync.MetricSyncAction; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.gms.scheduler.ExecutableScheduledJob; +import com.alibaba.polardbx.gms.sync.GmsSyncManagerHelper; +import com.alibaba.polardbx.gms.sync.SyncScope; +import com.google.common.collect.Lists; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.stubbing.Answer; + +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.FAILED; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.QUEUED; +import static com.alibaba.polardbx.common.scheduler.FiredScheduledJobState.RUNNING; +import static com.alibaba.polardbx.common.utils.Assert.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; + +/** + * @author fangwu + */ +public class LogSystemMetricsScheduledJobTest { + private static long scheduleId = 1L; + private static long fireTime = 2L; + private static long startTime = 3L; + + private static LogSystemMetricsScheduledJob job; + private static MockedStatic mockedScheduledJobsManager; + private static MockedStatic mockedScheduleJobStarter; + private static MockedStatic mockedGmsSyncManagerHelper; + private static MockedStatic mockedInst; + private static MockedStatic mockedConfigDataMode; + + @BeforeClass + public static void setUp() { + MetaDbInstConfigManager.setConfigFromMetaDb(false); + Mockito.clearAllCaches(); + + ExecutableScheduledJob executableScheduledJob = new ExecutableScheduledJob(); + executableScheduledJob.setScheduleId(scheduleId); + executableScheduledJob.setFireTime(fireTime); + executableScheduledJob.setStartTime(startTime); + + job = new LogSystemMetricsScheduledJob(executableScheduledJob); + mockedInst = Mockito.mockStatic(InstConfUtil.class); + mockedInst.when(() -> InstConfUtil.getInt(any())).thenReturn(5); + mockedInst.when(() -> InstConfUtil.getLong(any())).thenReturn(5L); + mockedScheduleJobStarter = Mockito.mockStatic(ScheduleJobStarter.class); + mockedScheduleJobStarter.when(ScheduleJobStarter::launchAll).thenAnswer((Answer) invocation -> null); + mockedScheduledJobsManager = Mockito.mockStatic(ScheduledJobsManager.class); + mockedGmsSyncManagerHelper = Mockito.mockStatic(GmsSyncManagerHelper.class); + mockedConfigDataMode = Mockito.mockStatic(ConfigDataMode.class); + mockedConfigDataMode.when(ConfigDataMode::isFastMock).thenReturn(true); + } + + @AfterClass + public static void tearDown() { + mockedScheduledJobsManager.close(); + mockedGmsSyncManagerHelper.close(); + mockedScheduleJobStarter.close(); + mockedConfigDataMode.close(); + mockedInst.close(); + MetaDbInstConfigManager.setConfigFromMetaDb(true); + Mockito.clearAllCaches(); + } + + @Test + public void testMarkRunningWhenQueuedShouldReturnTrue() { + // Arrange + mockedScheduledJobsManager.clearInvocations(); + mockedScheduledJobsManager.when(() -> + ScheduledJobsManager.casStateWithStartTime(eq(scheduleId), eq(fireTime), eq(QUEUED), eq(RUNNING), + anyLong())) + .thenReturn(true); + // Act + boolean result = job.markRunning(scheduleId, fireTime, startTime); + // Assert + assertTrue(result); + mockedScheduledJobsManager.verify(() -> + ScheduledJobsManager.casStateWithStartTime(eq(scheduleId), eq(fireTime), eq(QUEUED), eq(RUNNING), + anyLong())); + } + + @Test + public void testMarkRunningWhenNotQueuedShouldReturnFalse() { + // Arrange + mockedScheduledJobsManager.clearInvocations(); + mockedScheduledJobsManager.when(() -> + ScheduledJobsManager.casStateWithStartTime(eq(scheduleId), eq(fireTime), eq(QUEUED), eq(RUNNING), + anyLong())) + .thenReturn(false); + + // Act + boolean result = job.markRunning(scheduleId, fireTime, startTime); + + // Assert + assertFalse(result); + mockedScheduledJobsManager.verify(() -> + ScheduledJobsManager.casStateWithStartTime(eq(scheduleId), eq(fireTime), eq(QUEUED), eq(RUNNING), + anyLong())); + } + + /** + * check job interrupted when ENABLE_LOG_SYSTEM_METRICS is false + */ + @Test + public void testExecute() { + mockedInst.when(() -> InstConfUtil.getBool(ConnectionParams.ENABLE_LOG_SYSTEM_METRICS)).thenReturn(false); + + Exception targetException = new RuntimeException("test LogSystemMetricsScheduledJobTest execute"); + mockedScheduledJobsManager.when(() -> + ScheduledJobsManager.casStateWithFinishTime(anyLong(), anyLong(), any(), any(), anyLong(), anyString())) + .thenThrow(targetException); + mockedScheduledJobsManager.when(() -> + ScheduledJobsManager.updateState(anyLong(), anyLong(), any(), anyString(), anyString())) + .thenThrow(targetException); + boolean result = job.execute(); + // Assert + assertFalse(result); + mockedScheduledJobsManager.verify(() -> + ScheduledJobsManager.updateState(eq(scheduleId), eq(fireTime), eq(FAILED), any(), any())); + + mockedInst.when(() -> InstConfUtil.getBool(ConnectionParams.ENABLE_LOG_SYSTEM_METRICS)).thenReturn(true); + assert !job.execute(); + mockedScheduledJobsManager.when(() -> + ScheduledJobsManager.casStateWithStartTime(eq(scheduleId), eq(fireTime), eq(QUEUED), eq(RUNNING), + anyLong())) + .thenReturn(true); + mockedGmsSyncManagerHelper.when(() -> + GmsSyncManagerHelper.sync(new MetricSyncAction(), "polardbx", SyncScope.CURRENT_ONLY) + ).thenReturn(Lists.newArrayList()); + mockedScheduledJobsManager.when(() -> + ScheduledJobsManager.casStateWithFinishTime(anyLong(), anyLong(), any(), any(), anyLong(), anyString())) + .thenAnswer((Answer) invocation -> null); + assert job.execute(); + } +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scheduler/executor/statistic/StatisticInfoSchemaTablesScheduleJobTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scheduler/executor/statistic/StatisticInfoSchemaTablesScheduleJobTest.java new file mode 100644 index 000000000..59dda1359 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scheduler/executor/statistic/StatisticInfoSchemaTablesScheduleJobTest.java @@ -0,0 +1,318 @@ +package com.alibaba.polardbx.executor.scheduler.executor.statistic; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.executor.scheduler.executor.ScheduleJobStarter; +import com.alibaba.polardbx.executor.spi.ITopologyExecutor; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.gms.scheduler.ExecutableScheduledJob; +import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.rpc.compatible.ArrayResultSet; +import com.google.common.collect.ImmutableList; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicReference; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class StatisticInfoSchemaTablesScheduleJobTest { + + @Test + public void testExecuteInterruptedTestTrue() { + Properties properties = new Properties(); + properties.setProperty(ConnectionProperties.ALERT_STATISTIC_INTERRUPT, "true"); + try (MockedStatic mockedStaticMetaDbInstConfigManager = + mockStatic(MetaDbInstConfigManager.class)) { + MetaDbInstConfigManager metaDbInstConfigManager = mock(MetaDbInstConfigManager.class); + when(metaDbInstConfigManager.getCnVariableConfigMap()).thenReturn(properties); + mockedStaticMetaDbInstConfigManager.when(MetaDbInstConfigManager::getInstance) + .thenReturn(metaDbInstConfigManager); + try (MockedStatic mockedStaticScheduleJobStarter = + mockStatic(ScheduleJobStarter.class); + MockedStatic mockedStaticScheduledJobsManager = + mockStatic(ScheduledJobsManager.class);) { + ExecutableScheduledJob executableScheduledJob = new ExecutableScheduledJob(); + executableScheduledJob.setScheduleId(1); + executableScheduledJob.setFireTime(System.currentTimeMillis()); + executableScheduledJob.setTimeZone("SYSTEM"); + Assert.assertFalse(new StatisticInfoSchemaTablesScheduleJob(executableScheduledJob).execute()); + } + } + } + + @Test + public void testDisableStatisticBackground() { + Properties properties = new Properties(); + properties.setProperty(ConnectionProperties.ALERT_STATISTIC_INTERRUPT, "false"); + properties.setProperty(ConnectionProperties.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION, "false"); + try (MockedStatic mockedStaticMetaDbInstConfigManager = + mockStatic(MetaDbInstConfigManager.class)) { + MetaDbInstConfigManager metaDbInstConfigManager = mock(MetaDbInstConfigManager.class); + when(metaDbInstConfigManager.getCnVariableConfigMap()).thenReturn(properties); + mockedStaticMetaDbInstConfigManager.when(MetaDbInstConfigManager::getInstance) + .thenReturn(metaDbInstConfigManager); + try (MockedStatic mockedStaticScheduleJobStarter = + mockStatic(ScheduleJobStarter.class); + MockedStatic mockedStaticScheduledJobsManager = + mockStatic(ScheduledJobsManager.class);) { + AtomicReference remark = new AtomicReference<>(); + mockedStaticScheduledJobsManager.when(() -> ScheduledJobsManager.casStateWithFinishTime( + anyLong(), anyLong(), any(), any(), anyLong(), anyString())) + .then(invocation -> { + remark.set(invocation.getArgument(5)); + return true; + }); + + mockedStaticScheduledJobsManager.when(() -> ScheduledJobsManager.casStateWithStartTime( + anyLong(), anyLong(), any(), any(), anyLong())) + .thenReturn(true); + + ExecutableScheduledJob executableScheduledJob = new ExecutableScheduledJob(); + executableScheduledJob.setScheduleId(1); + executableScheduledJob.setFireTime(System.currentTimeMillis()); + executableScheduledJob.setTimeZone("SYSTEM"); + Assert.assertTrue(new StatisticInfoSchemaTablesScheduleJob(executableScheduledJob).execute()); + Assert.assertTrue(remark.get().equalsIgnoreCase( + "statistic background collection task (info_schema.tables) disabled.")); + } + } + } + + @Test + public void testNotInMaintenanceWindow() { + Properties properties = new Properties(); + properties.setProperty(ConnectionProperties.ALERT_STATISTIC_INTERRUPT, "false"); + properties.setProperty(ConnectionProperties.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION, "true"); + try (MockedStatic mockedStaticMetaDbInstConfigManager = + mockStatic(MetaDbInstConfigManager.class)) { + MetaDbInstConfigManager metaDbInstConfigManager = mock(MetaDbInstConfigManager.class); + when(metaDbInstConfigManager.getCnVariableConfigMap()).thenReturn(properties); + mockedStaticMetaDbInstConfigManager.when(MetaDbInstConfigManager::getInstance) + .thenReturn(metaDbInstConfigManager); + try (MockedStatic mockedStaticScheduleJobStarter = + mockStatic(ScheduleJobStarter.class); + MockedStatic mockedStaticScheduledJobsManager = + mockStatic(ScheduledJobsManager.class); + MockedStatic mockedStaticInstConfUtil = + mockStatic(InstConfUtil.class);) { + AtomicReference remark = new AtomicReference<>(); + mockedStaticScheduledJobsManager.when(() -> ScheduledJobsManager.casStateWithFinishTime( + anyLong(), anyLong(), any(), any(), anyLong(), anyString())) + .then(invocation -> { + remark.set(invocation.getArgument(5)); + return true; + }); + + mockedStaticScheduledJobsManager.when(() -> ScheduledJobsManager.casStateWithStartTime( + anyLong(), anyLong(), any(), any(), anyLong())) + .thenReturn(true); + + mockedStaticInstConfUtil.when(InstConfUtil::isInMaintenanceTimeWindow).thenReturn(false); + mockedStaticInstConfUtil.when(() -> InstConfUtil.getBool( + eq(ConnectionParams.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION))) + .thenReturn(true); + ExecutableScheduledJob executableScheduledJob = new ExecutableScheduledJob(); + executableScheduledJob.setScheduleId(1); + executableScheduledJob.setFireTime(System.currentTimeMillis()); + executableScheduledJob.setTimeZone("SYSTEM"); + Assert.assertTrue(new StatisticInfoSchemaTablesScheduleJob(executableScheduledJob).execute()); + Assert.assertTrue(remark.get().equalsIgnoreCase( + "statistic background collection task (info_schema.tables) not in maintenance window.")); + } + } + } + + @Test + public void testCasFail() { + Properties properties = new Properties(); + properties.setProperty(ConnectionProperties.ALERT_STATISTIC_INTERRUPT, "false"); + properties.setProperty(ConnectionProperties.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION, "false"); + try (MockedStatic mockedStaticMetaDbInstConfigManager = + mockStatic(MetaDbInstConfigManager.class)) { + MetaDbInstConfigManager metaDbInstConfigManager = mock(MetaDbInstConfigManager.class); + when(metaDbInstConfigManager.getCnVariableConfigMap()).thenReturn(properties); + mockedStaticMetaDbInstConfigManager.when(MetaDbInstConfigManager::getInstance) + .thenReturn(metaDbInstConfigManager); + try (MockedStatic mockedStaticScheduleJobStarter = + mockStatic(ScheduleJobStarter.class); + MockedStatic mockedStaticScheduledJobsManager = + mockStatic(ScheduledJobsManager.class);) { + mockedStaticScheduledJobsManager.when(() -> ScheduledJobsManager.casStateWithStartTime( + anyLong(), anyLong(), any(), any(), anyLong())) + .thenReturn(false); + + ExecutableScheduledJob executableScheduledJob = new ExecutableScheduledJob(); + executableScheduledJob.setScheduleId(1); + executableScheduledJob.setFireTime(System.currentTimeMillis()); + executableScheduledJob.setTimeZone("SYSTEM"); + Assert.assertFalse(new StatisticInfoSchemaTablesScheduleJob(executableScheduledJob).execute()); + } + } + } + + @Test + public void testEmptySchemas() { + Properties properties = new Properties(); + properties.setProperty(ConnectionProperties.ALERT_STATISTIC_INTERRUPT, "false"); + properties.setProperty(ConnectionProperties.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION, "true"); + try (MockedStatic mockedStaticMetaDbInstConfigManager = + mockStatic(MetaDbInstConfigManager.class)) { + MetaDbInstConfigManager metaDbInstConfigManager = mock(MetaDbInstConfigManager.class); + when(metaDbInstConfigManager.getCnVariableConfigMap()).thenReturn(properties); + mockedStaticMetaDbInstConfigManager.when(MetaDbInstConfigManager::getInstance) + .thenReturn(metaDbInstConfigManager); + try (MockedStatic mockedStaticScheduleJobStarter = + mockStatic(ScheduleJobStarter.class); + MockedStatic mockedStaticScheduledJobsManager = + mockStatic(ScheduledJobsManager.class); + MockedStatic mockedStaticDbInfoManager = + mockStatic(DbInfoManager.class); + MockedStatic mockedStaticInstConfUtil = + mockStatic(InstConfUtil.class);) { + AtomicReference remark = new AtomicReference<>(); + mockedStaticScheduledJobsManager.when(() -> ScheduledJobsManager.casStateWithFinishTime( + anyLong(), anyLong(), any(), any(), anyLong(), anyString())) + .then(invocation -> { + remark.set(invocation.getArgument(5)); + return true; + }); + mockedStaticInstConfUtil.when(InstConfUtil::isInMaintenanceTimeWindow).thenReturn(true); + mockedStaticInstConfUtil.when(() -> InstConfUtil.getBool( + eq(ConnectionParams.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION))) + .thenReturn(true); + + mockedStaticScheduledJobsManager.when(() -> ScheduledJobsManager.casStateWithStartTime( + anyLong(), anyLong(), any(), any(), anyLong())) + .thenReturn(true); + + DbInfoManager dbInfoManager = mock(DbInfoManager.class); + mockedStaticDbInfoManager.when(DbInfoManager::getInstance).thenReturn(dbInfoManager); + when(dbInfoManager.getDbList()).thenReturn(new ArrayList<>()); + + ExecutableScheduledJob executableScheduledJob = new ExecutableScheduledJob(); + executableScheduledJob.setScheduleId(1); + executableScheduledJob.setFireTime(System.currentTimeMillis()); + executableScheduledJob.setTimeZone("SYSTEM"); + Assert.assertTrue(new StatisticInfoSchemaTablesScheduleJob(executableScheduledJob).execute()); + Assert.assertTrue(remark.get().equalsIgnoreCase("")); + } + } + } + + @Test + public void test() throws SQLException { + Properties properties = new Properties(); + properties.setProperty(ConnectionProperties.ALERT_STATISTIC_INTERRUPT, "false"); + properties.setProperty(ConnectionProperties.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION, "true"); + try (MockedStatic mockedStaticMetaDbInstConfigManager = + mockStatic(MetaDbInstConfigManager.class)) { + MetaDbInstConfigManager metaDbInstConfigManager = mock(MetaDbInstConfigManager.class); + when(metaDbInstConfigManager.getCnVariableConfigMap()).thenReturn(properties); + mockedStaticMetaDbInstConfigManager.when(MetaDbInstConfigManager::getInstance) + .thenReturn(metaDbInstConfigManager); + try (MockedStatic mockedStaticScheduleJobStarter = + mockStatic(ScheduleJobStarter.class); + MockedStatic mockedStaticScheduledJobsManager = + mockStatic(ScheduledJobsManager.class); + MockedStatic mockedStaticDbInfoManager = + mockStatic(DbInfoManager.class); + MockedStatic mockedStaticInstConfUtil = + mockStatic(InstConfUtil.class); + MockedStatic mockedStaticMetaDbUtil = + mockStatic(MetaDbUtil.class); + ) { + AtomicReference remark = new AtomicReference<>(); + mockedStaticScheduledJobsManager.when(() -> ScheduledJobsManager.casStateWithFinishTime( + anyLong(), anyLong(), any(), any(), anyLong(), anyString())) + .then(invocation -> { + remark.set(invocation.getArgument(5)); + return true; + }); + mockedStaticInstConfUtil.when(InstConfUtil::isInMaintenanceTimeWindow).thenReturn(true); + mockedStaticInstConfUtil.when(() -> InstConfUtil.getBool( + eq(ConnectionParams.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION))) + .thenReturn(true); + + mockedStaticScheduledJobsManager.when(() -> ScheduledJobsManager.casStateWithStartTime( + anyLong(), anyLong(), any(), any(), anyLong())) + .thenReturn(true); + + DbInfoManager dbInfoManager = mock(DbInfoManager.class); + mockedStaticDbInfoManager.when(DbInfoManager::getInstance).thenReturn(dbInfoManager); + List schemas = new ArrayList<>(); + String db1 = "db1"; + schemas.add(db1); + schemas.add("polardbx"); + schemas.add("notActive"); + when(dbInfoManager.getDbList()).thenReturn(schemas); + + OptimizerContext db1OptimizerContext = new OptimizerContext(db1); + OptimizerContext.loadContext(db1OptimizerContext); + SchemaManager schemaManager = mock(SchemaManager.class); + db1OptimizerContext.setSchemaManager(schemaManager); + TableMeta tableMeta1 = mock(TableMeta.class); + TableMeta tableMeta2 = mock(TableMeta.class); + List tableMetas = ImmutableList.of(tableMeta1, tableMeta2); + when(schemaManager.getAllUserTables()).thenReturn(tableMetas); + // tb1 was long time not updated. + String tb1 = "tb1"; + // tb2 was just updated + String tb2 = "tb2"; + when(tableMeta1.getTableName()).thenReturn(tb1); + when(tableMeta2.getTableName()).thenReturn(tb2); + when(schemaManager.getTable(tb1)).thenReturn(tableMeta1); + when(schemaManager.getTable(tb2)).thenReturn(tableMeta2); + + OptimizerContext polardbxOptimizerContext = new OptimizerContext("polardbx"); + OptimizerContext.loadContext(polardbxOptimizerContext); + + Connection connection = mock(Connection.class); + mockedStaticMetaDbUtil.when(MetaDbUtil::getConnection).thenReturn(connection); + PreparedStatement preparedStatement = mock(PreparedStatement.class); + when(connection.prepareStatement(anyString())).thenReturn(preparedStatement); + + ArrayResultSet arrayResultSet = new ArrayResultSet(); + arrayResultSet.getColumnName().add("table_name"); + arrayResultSet.getRows().add(new Object[] {tb1}); + when(preparedStatement.executeQuery()).thenReturn(arrayResultSet); + + ITopologyExecutor topologyExecutor = mock(ITopologyExecutor.class); + ExecutorContext executorContext = mock(ExecutorContext.class); + when(executorContext.getTopologyExecutor()).thenReturn(topologyExecutor); + ExecutorContext.setContext(db1, executorContext); + Cursor cursor = mock(Cursor.class); + when(topologyExecutor.execByExecPlanNode(any(), any())).thenReturn(cursor); + + ExecutableScheduledJob executableScheduledJob = new ExecutableScheduledJob(); + executableScheduledJob.setScheduleId(1); + executableScheduledJob.setFireTime(System.currentTimeMillis()); + executableScheduledJob.setTimeZone("SYSTEM"); + Assert.assertTrue(new StatisticInfoSchemaTablesScheduleJob(executableScheduledJob).execute()); + Assert.assertTrue(remark.get().equalsIgnoreCase("")); + } + } + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CleanLogTableTaskTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CleanLogTableTaskTest.java new file mode 100644 index 000000000..26169b75a --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/scheduler/executor/trx/CleanLogTableTaskTest.java @@ -0,0 +1,126 @@ +package com.alibaba.polardbx.executor.scheduler.executor.trx; + +import com.alibaba.polardbx.common.utils.thread.ServerThreadPool; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.spi.ITopologyExecutor; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.topology.DbTopologyManager; +import com.alibaba.polardbx.rpc.compatible.ArrayResultSet; +import com.google.common.util.concurrent.Futures; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.HashSet; +import java.util.Set; + +import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.QUERY_TABLE_ROWS_TX_TABLE_V2; +import static com.alibaba.polardbx.gms.topology.SystemDbHelper.DEFAULT_DB_NAME; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class CleanLogTableTaskTest { + @Test + public void test0() throws SQLException { + Set dnIds = new HashSet<>(); + try (MockedStatic instConfUtilMockedStatic = mockStatic(InstConfUtil.class)) { + instConfUtilMockedStatic.when(InstConfUtil::isInMaintenanceTimeWindow).thenReturn(true); + Timestamp t0 = new Timestamp(2024, 1, 1, 0, 0, 0, 0); + Timestamp t1 = new Timestamp(2024, 1, 2, 1, 0, 0, 0); + Assert.assertTrue(CleanLogTableTask.shouldCleanTrxLog(dnIds, t0.getTime(), t1.getTime())); + } + } + + @Test + public void test1() throws SQLException { + try (MockedStatic instConfUtilMockedStatic = mockStatic(InstConfUtil.class); + MockedStatic dbTopologyManagerMockedStatic = mockStatic(DbTopologyManager.class)) { + instConfUtilMockedStatic.when(InstConfUtil::isInMaintenanceTimeWindow).thenReturn(true); + Timestamp t0 = new Timestamp(2024, 1, 1, 0, 0, 0, 0); + Timestamp t1 = new Timestamp(2024, 1, 1, 1, 0, 0, 0); + + ExecutorContext executorContext = new ExecutorContext(); + ExecutorContext.setContext(DEFAULT_DB_NAME, executorContext); + ITopologyExecutor topologyExecutor = mock(ITopologyExecutor.class); + executorContext.setTopologyExecutor(topologyExecutor); + ServerThreadPool serverThreadPool = mock(ServerThreadPool.class); + when(topologyExecutor.getExecutorService()).thenReturn(serverThreadPool); + when(serverThreadPool.submit(Mockito.any(), Mockito.any(), Mockito.any(Runnable.class))).then( + invocation -> { + Runnable runnable = invocation.getArgument(2); + runnable.run(); + return Futures.immediateFuture(null); + }); + + Connection connection = mock(Connection.class); + dbTopologyManagerMockedStatic.when( + () -> DbTopologyManager.getConnectionForStorage(Mockito.any(String.class))) + .thenReturn(connection); + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("count"); + rs.getRows().add(new Object[] {50000}); + Statement stmt = mock(Statement.class); + when(connection.createStatement()).thenReturn(stmt); + when(stmt.executeQuery(Mockito.anyString())).thenReturn(rs); + + Set dnIds = new HashSet<>(); + dnIds.add("test"); + Assert.assertFalse(CleanLogTableTask.shouldCleanTrxLog(dnIds, t0.getTime(), t1.getTime())); + } + } + + @Test + public void test2() throws SQLException { + try (MockedStatic instConfUtilMockedStatic = mockStatic(InstConfUtil.class); + MockedStatic dbTopologyManagerMockedStatic = mockStatic(DbTopologyManager.class)) { + instConfUtilMockedStatic.when(InstConfUtil::isInMaintenanceTimeWindow).thenReturn(true); + Timestamp t0 = new Timestamp(2024, 1, 1, 0, 0, 0, 0); + Timestamp t1 = new Timestamp(2024, 1, 1, 1, 0, 0, 0); + + ExecutorContext executorContext = new ExecutorContext(); + ExecutorContext.setContext(DEFAULT_DB_NAME, executorContext); + ITopologyExecutor topologyExecutor = mock(ITopologyExecutor.class); + executorContext.setTopologyExecutor(topologyExecutor); + ServerThreadPool serverThreadPool = mock(ServerThreadPool.class); + when(topologyExecutor.getExecutorService()).thenReturn(serverThreadPool); + when(serverThreadPool.submit(Mockito.any(), Mockito.any(), Mockito.any(Runnable.class))).then( + invocation -> { + Runnable runnable = invocation.getArgument(2); + runnable.run(); + return Futures.immediateFuture(null); + }); + + Connection connection = mock(Connection.class); + dbTopologyManagerMockedStatic.when( + () -> DbTopologyManager.getConnectionForStorage(Mockito.any(String.class))) + .thenReturn(connection); + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("count"); + rs.getRows().add(new Object[] {100001}); + Statement stmt = mock(Statement.class); + when(connection.createStatement()).thenReturn(stmt); + when(stmt.executeQuery(QUERY_TABLE_ROWS_TX_TABLE_V2)).thenReturn(rs); + ResultSet rs0 = mock(ResultSet.class); + when(stmt.executeQuery(Mockito.anyString())).then( + invocation -> { + String sql = invocation.getArgument(0); + if (sql.equals(QUERY_TABLE_ROWS_TX_TABLE_V2)) { + return rs; + } + return rs0; + } + ); + + Set dnIds = new HashSet<>(); + dnIds.add("test"); + Assert.assertTrue(CleanLogTableTask.shouldCleanTrxLog(dnIds, t0.getTime(), t1.getTime())); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/shuffle/DirectHashRouteCollationTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/shuffle/DirectHashRouteCollationTest.java index 687de9457..efbc5fd8c 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/shuffle/DirectHashRouteCollationTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/shuffle/DirectHashRouteCollationTest.java @@ -22,7 +22,12 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; import java.util.stream.IntStream; public class DirectHashRouteCollationTest { @@ -142,6 +147,26 @@ public void testVarCharLatin1() { checkConsistency(block, searchDatumInfos); } + @Test + public void testVarCharUtf8Mb4() { + ExecutionContext executionContext = new ExecutionContext(); + executionContext.setEnableOssCompatible(Boolean.TRUE); + DataType type = new VarcharType(CharsetName.UTF8MB4, CollationName.UTF8MB4_GENERAL_CI); + SliceBlockBuilder blockBuilder = + new SliceBlockBuilder(type, 1024, executionContext, executionContext.getParamManager().getBoolean( + ConnectionParams.ENABLE_OSS_COMPATIBLE)); + List searchDatumInfos = new ArrayList<>(); + writeBytes(type, new byte[] {'a', 'B', ' '}, searchDatumInfos, blockBuilder, Charset.forName("utf8")); + writeBytes(type, new byte[] {'A', 'B', ' '}, searchDatumInfos, blockBuilder, Charset.forName("utf8")); + writeBytes(type, new byte[] {'A', 'b', ' '}, searchDatumInfos, blockBuilder, Charset.forName("utf8")); + writeBytes(type, new byte[] {'a', 'b', ' '}, searchDatumInfos, blockBuilder, Charset.forName("utf8")); + writeBytes(type, new byte[] {'a', 'b'}, searchDatumInfos, blockBuilder, Charset.forName("utf8")); + writeBytes(type, new byte[] {'a', 'b', ' ', ' '}, searchDatumInfos, blockBuilder, Charset.forName("utf8")); + + Block block = blockBuilder.build(); + checkConsistency(block, searchDatumInfos); + } + private void writeBytes(DataType type, byte[] bytes, List searchDatumInfos, SliceBlockBuilder blockBuilder, Charset charset) { blockBuilder.writeString(new String(bytes, charset)); @@ -166,4 +191,61 @@ public void checkConsistency(Block block, List searchDatumInfos Assert.assertTrue(IntStream.range(0, block.getPositionCount()) .mapToLong(i -> NonConsistencyHasherUtils.calcHashCode(searchDatumInfos.get(i))).distinct().count() == 1); } + + @Test + public void testCharFieldSkew() { + DataType type = new CharType(CharsetName.UTF8MB4, CollationName.UTF8MB4_GENERAL_CI); + testSkew(type); + type = new CharType(CharsetName.UTF8MB4, CollationName.UTF8MB4_BIN); + testSkew(type); + } + + @Test + public void testVarCharFieldSkew() { + DataType type = new VarcharType(CharsetName.UTF8MB4, CollationName.UTF8MB4_GENERAL_CI); + testSkew(type); + type = new VarcharType(CharsetName.UTF8MB4, CollationName.UTF8MB4_BIN); + testSkew(type); + } + + private void testSkew(DataType type) { + List partitionFields = Arrays.asList( + getPartitionField(type, "JPBS21082984490347130065".getBytes()), + getPartitionField(type, "JPBR21073100350927170621".getBytes()), + getPartitionField(type, "JPBS21082984340345560593".getBytes()), + getPartitionField(type, "JPBS22080617230503440904".getBytes()), + getPartitionField(type, "JPBS22071902121219350135".getBytes()), + getPartitionField(type, "JPBS22071018910901310901".getBytes()), + getPartitionField(type, "JPBS22043001810618580367".getBytes()), + getPartitionField(type, "JPBS22072026671000490511".getBytes()), + getPartitionField(type, "JPBS22072090520333570941".getBytes()), + getPartitionField(type, "JPBS22072591990853040266".getBytes()), + getPartitionField(type, "JPBS22072735210846060183".getBytes()), + getPartitionField(type, "JPBS22070126010737400679".getBytes()), + getPartitionField(type, "JPBS22071798090713090622".getBytes()), + getPartitionField(type, "JPBS22072425270837500933".getBytes()), + getPartitionField(type, "JPBS22072169520632570863".getBytes()), + getPartitionField(type, "JPBS22043083710432430348".getBytes()), + getPartitionField(type, "JPBS22042369890646300579".getBytes()), + getPartitionField(type, "JPBS22072724010731420761".getBytes()), + getPartitionField(type, "JPBS22072415891155260120".getBytes()), + getPartitionField(type, "JPBS22072074361242110099".getBytes()) + ); + List partition = partitionFields.stream().map(filed -> filed.xxHashCode()).map(code -> code & 3).collect( + Collectors.toList()); + Assert.assertTrue(partition.stream().distinct().count() == 4); + + Map countMap = partition.stream() + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + Long maxCount = Collections.max(countMap.values()); + Long minCount = Collections.min(countMap.values()); + + Assert.assertTrue(maxCount <= 10 && minCount >= 2, "char filed skew"); + } + + private PartitionField getPartitionField(DataType type, byte[] bytes) { + PartitionField partFiled = PartitionFieldBuilder.createField(type); + partFiled.store(bytes, DataTypes.CharType); + return partFiled; + } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/HllTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/HllTest.java new file mode 100644 index 000000000..d0b83f80a --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/HllTest.java @@ -0,0 +1,23 @@ +package com.alibaba.polardbx.executor.statistics; + +import com.alibaba.polardbx.executor.statistic.ndv.NDVShardSketch; +import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.sun.tools.javac.util.Assert; +import org.junit.Test; + +public class HllTest { + + @Test + public void testAllExpired() { + MetaDbInstConfigManager.setConfigFromMetaDb(false); + long start = 0; + NDVShardSketch ndvShardSketch = + new NDVShardSketch(null, null, null, null, null, null, new long[] {start}); + Assert.check(ndvShardSketch.anyShardExpired()); + + ndvShardSketch = + new NDVShardSketch(null, null, null, null, null, null, new long[] {System.currentTimeMillis()}); + Assert.check(!ndvShardSketch.anyShardExpired()); + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/PolarDbXSystemTableNDVSketchStatisticTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/PolarDbXSystemTableNDVSketchStatisticTest.java new file mode 100644 index 000000000..1a7624d5f --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/PolarDbXSystemTableNDVSketchStatisticTest.java @@ -0,0 +1,184 @@ +package com.alibaba.polardbx.executor.statistics; + +import com.alibaba.polardbx.common.jdbc.IConnection; +import com.alibaba.polardbx.common.jdbc.IDataSource; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.executor.statistic.entity.PolarDbXSystemTableNDVSketchStatistic; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.optimizer.config.table.statistic.inf.SystemTableNDVSketchStatistic; +import org.apache.calcite.avatica.Meta; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.MockitoAnnotations; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * @author fangwu + */ +public class PolarDbXSystemTableNDVSketchStatisticTest { + /** + * Mocked DataSource object to simulate database connection. + */ + @Mock + private IDataSource dataSource; + + /** + * Mocked Connection object for database operations. + */ + @Mock + private IConnection conn; + + /** + * Mocked PreparedStatement object for executing SQL statements in batches. + */ + @Mock + private PreparedStatement ps; + + private PolarDbXSystemTableNDVSketchStatistic polarDbXSystemTableNDVSketchStatistic; + + /** + * Initializes mocked objects before each test case. + */ + @Before + public void setUp() throws SQLException { + MockitoAnnotations.initMocks(this); + when(dataSource.getConnection()).thenReturn(conn); + when(conn.prepareStatement(anyString())).thenReturn(ps); + polarDbXSystemTableNDVSketchStatistic = new PolarDbXSystemTableNDVSketchStatistic(); + + Connection mockedConnection = mock(Connection.class); + PreparedStatement mockedPreparedStatement = mock(PreparedStatement.class); + + when(mockedConnection.prepareStatement(anyString())).thenReturn(mockedPreparedStatement); + } + + /** + * Tests batchReplace method with a normal scenario where data is successfully replaced in PolarDB-X mode. + */ + @Test + public void testBatchReplaceNormalCase() throws SQLException { + setUp(); + + SystemTableNDVSketchStatistic.SketchRow sketchRow1 = mock(SystemTableNDVSketchStatistic.SketchRow.class); + when(sketchRow1.getSchemaName()).thenReturn("schema1"); + // ... set up other mock methods for sketchRow1 ... + + SystemTableNDVSketchStatistic.SketchRow sketchRow2 = mock(SystemTableNDVSketchStatistic.SketchRow.class); + // ... set up other mock methods for sketchRow2 ... + when(sketchRow2.getSchemaName()).thenReturn("schema2"); + + SystemTableNDVSketchStatistic.SketchRow[] sketchRows = + new SystemTableNDVSketchStatistic.SketchRow[] {sketchRow1, sketchRow2}; + + PolarDbXSystemTableNDVSketchStatistic statistic = new PolarDbXSystemTableNDVSketchStatistic(); + + try (MockedStatic metaDbDataSourceMockedStatic = mockStatic(MetaDbDataSource.class)) { + MetaDbDataSource metaDbDataSource = mock(MetaDbDataSource.class); + when(metaDbDataSource.getDataSource()).thenReturn(dataSource); + metaDbDataSourceMockedStatic.when(() -> MetaDbDataSource.getInstance()).thenReturn(metaDbDataSource); + statistic.batchReplace(sketchRows); + + // Verify that the correct number of calls were made to the PreparedStatement's setter methods + // and that executeBatch was called once. + verify(ps, times(2)).setString(eq(1), anyString()); + // Add more verification statements as needed ... + verify(ps).executeBatch(); + } + } + + /** + * 测试用例1 - 正常情况下的删除操作 + * 设计思路:当系统处于master模式时,尝试删除指定schema下表的数据。 + * 输入参数:有效的schema名称、表名称和列名称。 + * 预期结果:成功执行SQL语句并关闭资源。 + */ + @Test + public void testDeleteByColumnNormalCase() throws SQLException { + // 准备 + String schemaName = "test_schema"; + String tableName = "test_table"; + String columns = "column1,column2"; + Connection c = mock(Connection.class); + MetaDbDataSource metaDbDataSourceMock = mock(MetaDbDataSource.class); + DataSource dataSourceMock = mock(DataSource.class); + + doReturn(dataSourceMock).when(metaDbDataSourceMock).getDataSource(); + doReturn(c).when(dataSourceMock).getConnection(); + PreparedStatement preparedStatement = mock(PreparedStatement.class); + doReturn(preparedStatement).when(c).prepareStatement(anyString()); + + try (MockedStatic metaDbDataSourceMockedStatic = mockStatic(MetaDbDataSource.class)) { + metaDbDataSourceMockedStatic.when(MetaDbDataSource::getInstance).thenReturn(metaDbDataSourceMock); + // 执行 + polarDbXSystemTableNDVSketchStatistic.deleteByColumn(schemaName, tableName, columns); + + // 验证 + verify(metaDbDataSourceMock, times(1)).getDataSource(); + verify(c, times(1)).prepareStatement(anyString()); + verify(preparedStatement, times(1)).executeUpdate(); + } + } + + /** + * 测试用例2 - 系统不在master模式的情况 + * 设计思路:当系统不处于master模式时,直接返回而不执行任何操作。 + * 输入参数:任意schema名称、表名称和列名称。 + * 预期结果:没有执行任何数据库操作。 + */ + @Test + public void testDeleteByColumnNotInMasterMode() { + String schemaName = "any_schema"; + String tableName = "any_table"; + String columns = "any_column"; + + try (MockedStatic configDataModeMockedStatic = mockStatic(ConfigDataMode.class)) { + configDataModeMockedStatic.when(ConfigDataMode::isMasterMode).thenReturn(false); + + boolean rs = polarDbXSystemTableNDVSketchStatistic.deleteByColumn(schemaName, tableName, columns, null); + assert !rs; + } + } + + /** + * 测试用例3 - 数据库操作失败的情况 + * 设计思路:模拟数据库操作过程中抛出异常。 + * 输入参数:有效的schema名称、表名称和列名称。 + * 预期结果:记录错误日志并释放资源。 + */ + @Test + public void testDeleteByColumnWithException() throws SQLException { + String schemaName = "test_schema"; + String tableName = "test_table"; + String columns = "column1,column2"; + Connection c = mock(Connection.class); + DataSource metaDbDataSourceMock = mock(DataSource.class); + + doReturn(c).when(metaDbDataSourceMock).getConnection(); + PreparedStatement preparedStatement = mock(PreparedStatement.class); + doReturn(preparedStatement).when(c).prepareStatement(anyString()); + + doThrow(new SQLException()).when(preparedStatement).executeUpdate(); + boolean rs = + polarDbXSystemTableNDVSketchStatistic.deleteByColumn(schemaName, tableName, columns, metaDbDataSourceMock); + + assert !rs; + + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/RealStatsLogTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/RealStatsLogTest.java new file mode 100644 index 000000000..0b92e7f67 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/RealStatsLogTest.java @@ -0,0 +1,644 @@ +package com.alibaba.polardbx.executor.statistics; + +import com.alibaba.polardbx.executor.pl.ProcedureManager; +import com.alibaba.polardbx.executor.pl.StoredFunctionManager; +import com.alibaba.polardbx.executor.statistic.RealStatsLogType; +import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.gms.topology.SystemDbHelper; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.config.table.statistic.Histogram; +import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticDataSource; +import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticManager; +import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils; +import com.alibaba.polardbx.optimizer.config.table.statistic.TopN; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.datatype.IntegerType; +import com.alibaba.polardbx.optimizer.core.expression.JavaFunctionManager; +import com.alibaba.polardbx.optimizer.core.planner.PlanCache; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.alibaba.polardbx.common.utils.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +/** + * @author fangwu + */ +public class RealStatsLogTest { + + @BeforeClass + public static void setUp() { + MetaDbInstConfigManager.setConfigFromMetaDb(false); + } + + @Test + public void testPlanCacheSize() { + PlanCache mockPlanCache = mock(PlanCache.class); + when(mockPlanCache.getCacheKeyCount()).thenReturn(123L); + try (MockedStatic mock = mockStatic(PlanCache.class)) { + mock.when(PlanCache::getInstance).thenReturn(mockPlanCache); + String result = RealStatsLogType.PLAN_CACHE_SIZE.getLog(); + assertEquals("123", result); + } + } + + @Test + public void testTableCount() { + DbInfoManager mockDbInfoManager = mock(DbInfoManager.class); + OptimizerContext mockOptimizerContext = mock(OptimizerContext.class); + + // mock db list + String[] dbList = {"db1", "db2"}; + when(mockDbInfoManager.getDbList()).thenReturn(Arrays.asList(dbList)); + + try (MockedStatic mock = mockStatic(SystemDbHelper.class); + MockedStatic optimizerContextMockedStatic = mockStatic(OptimizerContext.class); + MockedStatic dbInfoManagerMockedStatic = mockStatic(DbInfoManager.class); + ) { + mock.when(() -> SystemDbHelper.isDBBuildIn("db1")).thenReturn(false); + mock.when(() -> SystemDbHelper.isDBBuildIn("db2")).thenReturn(false); + dbInfoManagerMockedStatic.when(DbInfoManager::getInstance).thenReturn(mockDbInfoManager); + + Set set = new HashSet<>(); + set.add("db1"); + optimizerContextMockedStatic.when(OptimizerContext::getActiveSchemaNames).thenReturn(set); + + List tableList = Lists.newArrayList(); + tableList.add(mock(TableMeta.class)); + tableList.add(mock(TableMeta.class)); + tableList.add(mock(TableMeta.class)); + SchemaManager mockSchemaManager = mock(SchemaManager.class); + when(mockSchemaManager.getAllUserTables()).thenReturn(tableList); + when(mockOptimizerContext.getContext("db1")).thenReturn(mockOptimizerContext); + when(mockOptimizerContext.getLatestSchemaManager()).thenReturn(mockSchemaManager); + + String result = RealStatsLogType.TABLE_NUM.getLog(); + + // 验证返回的表数量 + assertEquals("3", result); + } + } + + @Test + public void testTableInStatsCount() { + StatisticManager mockStatisticManager = mock(StatisticManager.class); + Map> mockCache = new HashMap<>(); + Map tbMap1 = Maps.newHashMap(); + tbMap1.put("tb1", mock(StatisticManager.CacheLine.class)); + tbMap1.put("tb2", mock(StatisticManager.CacheLine.class)); + tbMap1.put("tb3", mock(StatisticManager.CacheLine.class)); + + Map tbMap2 = Maps.newHashMap(); + tbMap2.put("tb4", mock(StatisticManager.CacheLine.class)); + tbMap2.put("tb5", mock(StatisticManager.CacheLine.class)); + tbMap2.put("tb6", mock(StatisticManager.CacheLine.class)); + tbMap2.put("tb7", mock(StatisticManager.CacheLine.class)); + + mockCache.put("schema1", tbMap1); + mockCache.put("schema2", tbMap2); + when(mockStatisticManager.getStatisticCache()).thenReturn(mockCache); + + try (MockedStatic managerMockedStatic = mockStatic(StatisticManager.class)) { + managerMockedStatic.when(StatisticManager::getInstance).thenReturn(mockStatisticManager); + String result = RealStatsLogType.STATISTIC_TABLE_NUM.getLog(); + + assertEquals("7", result); + } + } + + @Test + public void testProcedureCount() { + ProcedureManager mockManager = mock(ProcedureManager.class); + when(mockManager.getProcedureSize()).thenReturn(12L); + try (MockedStatic mock = mockStatic(ProcedureManager.class)) { + mock.when(ProcedureManager::getInstance).thenReturn(mockManager); + String result = RealStatsLogType.PROCEDURE_NUM.getLog(); + assertEquals("12", result); + } + } + + @Test + public void testCountFreshHyperLogLogStatsColumns() { + // Mock DbInfoManager + List databaseNames = new ArrayList<>(); + databaseNames.add("db1"); + DbInfoManager dbInfoManager = mock(DbInfoManager.class); + when(dbInfoManager.getDbList()).thenReturn(databaseNames); + + // Mock OptimizerContext and TableMeta + OptimizerContext context = mock(OptimizerContext.class); + TableMeta tableMeta = mock(TableMeta.class); + when(context.getLatestSchemaManager()).thenReturn(mock(SchemaManager.class)); + when(context.getLatestSchemaManager().getAllUserTables()).thenReturn(Arrays.asList(tableMeta)); + + // Mock StatisticManager and CacheLine + StatisticManager.CacheLine cacheLine = mock(StatisticManager.CacheLine.class); + when(cacheLine.getRowCount()).thenReturn(100001L); + StatisticManager statisticManager = mock(StatisticManager.class); + when(statisticManager.getCacheLine("db1", "table1")).thenReturn(cacheLine); + + // Mock GlobalIndexMeta and TableIndexMap + Map>> indexColsMap = new HashMap<>(); + Map> indexColumnMap = new HashMap<>(); + indexColumnMap.put("index1", Arrays.asList("col1", "col2")); + indexColsMap.put("indexKey", indexColumnMap); + when(tableMeta.getTableName()).thenReturn("table1"); + + try (MockedStatic globalIndexMetaMockedStatic = mockStatic(GlobalIndexMeta.class); + MockedStatic dbInfoManagerMockedStatic = mockStatic(DbInfoManager.class); + MockedStatic optimizerContextMockedStatic = mockStatic(OptimizerContext.class); + MockedStatic statisticManagerMockedStatic = mockStatic(StatisticManager.class); + ) { + globalIndexMetaMockedStatic.when(() -> GlobalIndexMeta.getTableIndexMap(tableMeta, null)) + .thenReturn(indexColsMap); + dbInfoManagerMockedStatic.when(DbInfoManager::getInstance).thenReturn(dbInfoManager); + optimizerContextMockedStatic.when(() -> OptimizerContext.getContext("db1")).thenReturn(context); + statisticManagerMockedStatic.when(StatisticManager::getInstance).thenReturn(statisticManager); + + // Mock StatisticManager and Sds ndvModifyTime + StatisticDataSource sds = mock(StatisticDataSource.class); + long currentTime = System.currentTimeMillis(); + long lastUpdate = currentTime - 1000 * 60 * 60 * 24 * 7 / 2; + when(sds.ndvModifyTime("db1", "table1", "col1,col2")).thenReturn(lastUpdate); + when(statisticManager.getSds()).thenReturn(sds); + + long result = RealStatsLogType.countFreshHyperLogLogStatsColumns(); + + assertEquals(1, result); + } + } + + /** + * test return 0 when db list is empty + */ + @Test + public void testCalculateColumnsForHyperLoglogStatsWhenDatabaseListIsEmpty() { + DbInfoManager mockDbInfoManager = mock(DbInfoManager.class); + when(mockDbInfoManager.getDbList()).thenReturn(new ArrayList<>()); + + try (MockedStatic dbInfoManagerMockedStatic = mockStatic(DbInfoManager.class)) { + dbInfoManagerMockedStatic.when(DbInfoManager::getInstance).thenReturn(mockDbInfoManager); + long result = RealStatsLogType.calculateColumnsForHyperLoglogStats(); + assertEquals(0L, result); + } + } + + /** + * test return 0 when there was no table + */ + @Test + public void testCalculateColumnsForHyperLoglogStatsWhenNoTablesExist() { + List databaseNames = new ArrayList<>(); + databaseNames.add("db1"); + DbInfoManager mockDbInfoManager = mock(DbInfoManager.class); + when(mockDbInfoManager.getDbList()).thenReturn(databaseNames); + OptimizerContext mockOptimizerContext = mock(OptimizerContext.class); + SchemaManager mockSchemaManager = mock(SchemaManager.class); + when(mockOptimizerContext.getLatestSchemaManager()).thenReturn(mockSchemaManager); + when(mockSchemaManager.getAllUserTables()).thenReturn(Collections.emptyList()); + + try (MockedStatic dbInfoManagerMockedStatic = mockStatic(DbInfoManager.class); + MockedStatic optimizerContextMockedStatic = mockStatic(OptimizerContext.class)) { + optimizerContextMockedStatic.when(() -> OptimizerContext.getContext("db1")) + .thenReturn(mockOptimizerContext); + dbInfoManagerMockedStatic.when(DbInfoManager::getInstance).thenReturn(mockDbInfoManager); + + long result = RealStatsLogType.calculateColumnsForHyperLoglogStats(); + + assertEquals(0L, result); + } + } + + /** + * test sample size + */ + @Test + public void testCalculateColumnsForHyperLoglogStatsWhenRowCountIsLessThanOrEqualToDefaultSampleSize() { + List databaseNames = new ArrayList<>(); + databaseNames.add("db1"); + DbInfoManager dbInfoManagerMock = mock(DbInfoManager.class); + OptimizerContext optimizerContextMock = mock(OptimizerContext.class); + StatisticManager statisticManagerMock = mock(StatisticManager.class); + TableMeta tableMetaMock = mock(TableMeta.class); + + when(dbInfoManagerMock.getDbList()).thenReturn(databaseNames); + when(statisticManagerMock.getCacheLine("db1", "table1")).thenReturn(new StatisticManager.CacheLine()); + when(tableMetaMock.getTableName()).thenReturn("table1"); + + SchemaManager mockSchemaManager = mock(SchemaManager.class); + when(optimizerContextMock.getLatestSchemaManager()).thenReturn(mockSchemaManager); + when(mockSchemaManager.getAllUserTables()).thenReturn(ImmutableList.of(tableMetaMock)); + + Map>> indexColsMap = new HashMap<>(); + Map> indexColumnMap = new HashMap<>(); + indexColumnMap.put("index1", Arrays.asList("col1", "col2")); + indexColsMap.put("indexKey", indexColumnMap); + + try (MockedStatic dbInfoManagerMockedStatic = mockStatic(DbInfoManager.class); + MockedStatic optimizerContextMockedStatic = mockStatic(OptimizerContext.class); + MockedStatic statisticManagerMockedStatic = mockStatic(StatisticManager.class); + MockedStatic globalIndexMetaMockedStatic = mockStatic(GlobalIndexMeta.class); + ) { + optimizerContextMockedStatic.when(() -> OptimizerContext.getContext("db1")) + .thenReturn(optimizerContextMock); + dbInfoManagerMockedStatic.when(DbInfoManager::getInstance).thenReturn(dbInfoManagerMock); + statisticManagerMockedStatic.when(StatisticManager::getInstance).thenReturn(statisticManagerMock); + globalIndexMetaMockedStatic.when(() -> GlobalIndexMeta.getTableIndexMap(tableMetaMock, null)) + .thenReturn(indexColsMap); + + long result = RealStatsLogType.calculateColumnsForHyperLoglogStats(); + + assertEquals(0L, result); + + StatisticManager.CacheLine cl = new StatisticManager.CacheLine(); + cl.setRowCount(100001L); + + when(statisticManagerMock.getCacheLine("db1", "table1")).thenReturn(cl); + + result = RealStatsLogType.calculateColumnsForHyperLoglogStats(); + + assertEquals(2L, result); + } + } + + /** + * test return 0 while db list is empty + */ + @Test + public void testCalculateColumnsForSamplingStatsWhenNoDatabases() { + // 准备 + List emptyDatabaseNames = new ArrayList<>(); + DbInfoManager dbInfoManagerMock = mock(DbInfoManager.class); + when(dbInfoManagerMock.getDbList()).thenReturn(emptyDatabaseNames); + + // 执行 + long result = RealStatsLogType.calculateColumnsForSamplingStats(); + + // 验证 + assertEquals(0L, result); + } + + /** + * test json type meta columns + */ + @Test + public void testCalculateColumnsForSamplingStatsExcludingBinaryAndJsonTypes() { + // 准备 + List databaseNames = Arrays.asList("db1"); + DbInfoManager dbInfoManagerMock = mock(DbInfoManager.class); + when(dbInfoManagerMock.getDbList()).thenReturn(databaseNames); + + OptimizerContext optimizerContextMock = mock(OptimizerContext.class); + SchemaManager schemaManagerMock = mock(SchemaManager.class); + TableMeta tableMetaMock = mock(TableMeta.class); + ColumnMeta binaryColumnMock = mock(ColumnMeta.class); + ColumnMeta jsonColumnMock = mock(ColumnMeta.class); + + when(optimizerContextMock.getLatestSchemaManager()).thenReturn(schemaManagerMock); + when(schemaManagerMock.getAllUserTables()).thenReturn(Arrays.asList(tableMetaMock)); + when(tableMetaMock.getAllColumns()).thenReturn(Arrays.asList(binaryColumnMock, jsonColumnMock)); + try (MockedStatic statisticUtilsMockedStatic = mockStatic(StatisticUtils.class); + MockedStatic dbInfoManagerMockedStatic = mockStatic(DbInfoManager.class); + MockedStatic optimizerContextMockedStatic = mockStatic(OptimizerContext.class);) { + statisticUtilsMockedStatic.when(() -> StatisticUtils.isBinaryOrJsonColumn(binaryColumnMock)) + .thenReturn(true); + statisticUtilsMockedStatic.when(() -> StatisticUtils.isBinaryOrJsonColumn(jsonColumnMock)).thenReturn(true); + optimizerContextMockedStatic.when(() -> OptimizerContext.getContext("db1")) + .thenReturn(optimizerContextMock); + dbInfoManagerMockedStatic.when(DbInfoManager::getInstance).thenReturn(dbInfoManagerMock); + + long result = RealStatsLogType.calculateColumnsForSamplingStats(); + + assertEquals(0L, result); + + statisticUtilsMockedStatic.when(() -> StatisticUtils.isBinaryOrJsonColumn(jsonColumnMock)) + .thenReturn(false); + + result = RealStatsLogType.calculateColumnsForSamplingStats(); + + assertEquals(1L, result); + } + } + + @Test + public void testCountFreshSampleStatsColumnsWhenDbListIsEmpty() { + List emptyDatabaseSchemas = new ArrayList<>(); + DbInfoManager dbInfoManagerMock = mock(DbInfoManager.class); + when(dbInfoManagerMock.getDbList()).thenReturn(emptyDatabaseSchemas); + + try (MockedStatic dbInfoManagerMockedStatic = mockStatic(DbInfoManager.class);) { + dbInfoManagerMockedStatic.when(DbInfoManager::getInstance).thenReturn(dbInfoManagerMock); + + long result = RealStatsLogType.countFreshSampleStatsColumns(); + + assertEquals(0L, result); + } + + } + + /** + * test return 0 when there is no db or table + */ + @Test + public void testCountFreshSampleStatsColumnsWhenNoTablesInSchema() { + // 准备 + String schema = "test_schema"; + List databaseSchemas = ImmutableList.of(schema); + OptimizerContext context = mock(OptimizerContext.class); + DbInfoManager dbInfoManagerMock = mock(DbInfoManager.class); + + when(dbInfoManagerMock.getDbList()).thenReturn(databaseSchemas); + when(context.getLatestSchemaManager()).thenReturn(mock(SchemaManager.class)); + + try (MockedStatic dbInfoManagerMockedStatic = mockStatic(DbInfoManager.class); + MockedStatic optimizerContextMockedStatic = mockStatic(OptimizerContext.class); + MockedStatic statisticManagerMockedStatic = mockStatic(StatisticManager.class);) { + optimizerContextMockedStatic.when(() -> OptimizerContext.getContext(schema)) + .thenReturn(context); + dbInfoManagerMockedStatic.when(DbInfoManager::getInstance).thenReturn(dbInfoManagerMock); + statisticManagerMockedStatic.when(StatisticManager::getInstance).thenReturn(mock(StatisticManager.class)); + + long result = RealStatsLogType.countFreshSampleStatsColumns(); + + verify(context).getLatestSchemaManager(); + verifyNoInteractions(StatisticManager.getInstance()); + assertEquals(0L, result); + } + } + + @Test + public void testCountFreshSampleStatsColumns() { + // 准备 + String schema = "test_schema"; + List databaseSchemas = ImmutableList.of(schema); + OptimizerContext context = mock(OptimizerContext.class); + DbInfoManager dbInfoManagerMock = mock(DbInfoManager.class); + SchemaManager schemaManager = mock(SchemaManager.class); + + when(dbInfoManagerMock.getDbList()).thenReturn(databaseSchemas); + when(context.getLatestSchemaManager()).thenReturn(schemaManager); + + ColumnMeta columnMeta1 = mock(ColumnMeta.class); + ColumnMeta columnMeta2 = mock(ColumnMeta.class); + + when(columnMeta1.getDataType()).thenReturn(DataTypes.VarcharType); + when(columnMeta2.getDataType()).thenReturn(DataTypes.IntegerType); + + ArrayList allNonBinaryOrJson = new ArrayList<>(Arrays.asList( + columnMeta1, + columnMeta2 + )); + + TableMeta tableMeta = mock(TableMeta.class); + List tableMetas = Lists.newArrayList(); + tableMetas.add(tableMeta); + when(schemaManager.getAllUserTables()).thenReturn(tableMetas); + when(tableMeta.getTableName()).thenReturn("table1"); + when(tableMeta.getAllColumns()).thenReturn(allNonBinaryOrJson); + + StatisticManager.CacheLine cacheLine = mock(StatisticManager.CacheLine.class); + + StatisticManager statisticManager = mock(StatisticManager.class); + when(statisticManager.getCacheLine(schema, "table1")).thenReturn(cacheLine); + when(cacheLine.hasExpire()).thenReturn(false); + + try (MockedStatic dbInfoManagerMockedStatic = mockStatic(DbInfoManager.class); + MockedStatic optimizerContextMockedStatic = mockStatic(OptimizerContext.class); + MockedStatic statisticManagerMockedStatic = mockStatic(StatisticManager.class);) { + optimizerContextMockedStatic.when(() -> OptimizerContext.getContext(schema)) + .thenReturn(context); + dbInfoManagerMockedStatic.when(DbInfoManager::getInstance).thenReturn(dbInfoManagerMock); + statisticManagerMockedStatic.when(StatisticManager::getInstance).thenReturn(statisticManager); + + long result = RealStatsLogType.countFreshSampleStatsColumns(); + + verify(context).getLatestSchemaManager(); + assertEquals(2L, result); + } + } + + @Test + public void testSqlUdfCount() { + StoredFunctionManager mockManager = mock(StoredFunctionManager.class); + when(mockManager.getUdfCount()).thenReturn(0L); + try (MockedStatic mock = mockStatic(StoredFunctionManager.class)) { + mock.when(StoredFunctionManager::getInstance).thenReturn(mockManager); + String result = RealStatsLogType.SQL_UDF_NUM.getLog(); + assertEquals("0", result); + } + } + + public void testCountColumnsWithoutBinaryOrJsonEmptyList() { + ArrayList emptyList = new ArrayList<>(); + long expected = 0; // 期望的结果 + long actual = RealStatsLogType.countColumnsWithoutBinaryOrJson(emptyList); + assertEquals(expected, actual); // 验证实际结果等于预期结果 + } + + @Test + public void testCountColumnsWithoutBinaryOrJsonAllNonBinaryOrJson() { + ColumnMeta columnMeta1 = mock(ColumnMeta.class); + ColumnMeta columnMeta2 = mock(ColumnMeta.class); + + when(columnMeta1.getDataType()).thenReturn(DataTypes.VarcharType); + when(columnMeta2.getDataType()).thenReturn(DataTypes.IntegerType); + + ArrayList allNonBinaryOrJson = new ArrayList<>(Arrays.asList( + columnMeta1, + columnMeta2 + )); + long expected = 2; + long actual = RealStatsLogType.countColumnsWithoutBinaryOrJson(allNonBinaryOrJson); + + assertEquals(expected, actual); + } + + @Test + public void testCountColumnsWithoutBinaryOrJsonMixedTypes() { + ColumnMeta columnMeta1 = mock(ColumnMeta.class); + ColumnMeta columnMeta2 = mock(ColumnMeta.class); + ColumnMeta columnMeta3 = mock(ColumnMeta.class); + + when(columnMeta1.getDataType()).thenReturn(DataTypes.VarcharType); + when(columnMeta2.getDataType()).thenReturn(DataTypes.IntegerType); + when(columnMeta3.getDataType()).thenReturn(DataTypes.BinaryType); + + ArrayList mixedTypes = new ArrayList<>(Arrays.asList( + columnMeta1, + columnMeta2, + columnMeta3 + )); + + long expected = 2; + long actual = RealStatsLogType.countColumnsWithoutBinaryOrJson(mixedTypes); + + assertEquals(expected, actual); + } + + @Test + public void testCountColumnsWithMissingStatisticsEmptyList() { + + StatisticManager.CacheLine cacheLine = mock(StatisticManager.CacheLine.class); + + long result = RealStatsLogType.countColumnsWithNotExpiredStatistics(cacheLine, Lists.newArrayList()); + + assertEquals(0L, result); + } + + @Test + public void testCountColumnsWithMissingStatisticsAllComplete() { + ColumnMeta columnMeta1 = mock(ColumnMeta.class); + ColumnMeta columnMeta2 = mock(ColumnMeta.class); + ColumnMeta columnMeta3 = mock(ColumnMeta.class); + + when(columnMeta1.getDataType()).thenReturn(DataTypes.VarcharType); + when(columnMeta2.getDataType()).thenReturn(DataTypes.IntegerType); + when(columnMeta3.getDataType()).thenReturn(DataTypes.BinaryType); + + ArrayList mixedTypes = new ArrayList<>(Arrays.asList( + columnMeta1, + columnMeta2, + columnMeta3 + )); + + StatisticManager.CacheLine cacheLine = mock(StatisticManager.CacheLine.class); + try ( + MockedStatic realStatsLogTypeMockedStatic = mockStatic(RealStatsLogType.class);) { + realStatsLogTypeMockedStatic.when( + () -> RealStatsLogType.countColumnsWithNotExpiredStatistics(cacheLine, mixedTypes)) + .thenCallRealMethod(); + realStatsLogTypeMockedStatic.when(() -> RealStatsLogType.hasMissingStatistics(any(), anyString())) + .thenReturn(false); + + long result = RealStatsLogType.countColumnsWithNotExpiredStatistics(cacheLine, mixedTypes); + + assertEquals(2L, result); + } + } + + @Test + public void testJavaUdfCount() { + JavaFunctionManager mockManager = mock(JavaFunctionManager.class); + when(mockManager.getFuncNum()).thenReturn(11L); + try (MockedStatic mock = mockStatic(JavaFunctionManager.class)) { + mock.when(JavaFunctionManager::getInstance).thenReturn(mockManager); + String result = RealStatsLogType.JAVA_UDF_NUM.getLog(); + assertEquals("11", result); + } + } + + @Test + public void testCountColumnsWithMissingStatisticsSomeMissing() { + ColumnMeta columnMeta1 = mock(ColumnMeta.class); + ColumnMeta columnMeta2 = mock(ColumnMeta.class); + ColumnMeta columnMeta3 = mock(ColumnMeta.class); + + when(columnMeta1.getDataType()).thenReturn(DataTypes.VarcharType); + when(columnMeta2.getDataType()).thenReturn(DataTypes.IntegerType); + when(columnMeta3.getDataType()).thenReturn(DataTypes.BinaryType); + when(columnMeta1.getName()).thenReturn("c1"); + when(columnMeta2.getName()).thenReturn("c2"); + when(columnMeta3.getName()).thenReturn("c3"); + + ArrayList mixedTypes = new ArrayList<>(Arrays.asList( + columnMeta1, + columnMeta2, + columnMeta3 + )); + + StatisticManager.CacheLine cacheLine = mock(StatisticManager.CacheLine.class); + try ( + MockedStatic realStatsLogTypeMockedStatic = mockStatic(RealStatsLogType.class);) { + realStatsLogTypeMockedStatic.when( + () -> RealStatsLogType.countColumnsWithNotExpiredStatistics(cacheLine, mixedTypes)) + .thenCallRealMethod(); + realStatsLogTypeMockedStatic.when(() -> RealStatsLogType.hasMissingStatistics(cacheLine, "c1")) + .thenReturn(false); + realStatsLogTypeMockedStatic.when(() -> RealStatsLogType.hasMissingStatistics(cacheLine, "c2")) + .thenReturn(true); + realStatsLogTypeMockedStatic.when(() -> RealStatsLogType.hasMissingStatistics(cacheLine, "c3")) + .thenReturn(false); + + long result = RealStatsLogType.countColumnsWithNotExpiredStatistics(cacheLine, mixedTypes); + + assertEquals(1L, result); + } + } + + @Test + public void testHasMissingStatisticsWithValidStats() { + StatisticManager.CacheLine mockCacheLine = mock(StatisticManager.CacheLine.class); + + Map histogramMap = Maps.newHashMap(); + Histogram histogram = new Histogram(7, new IntegerType(), 1); + Integer[] list = new Integer[10]; + list[0] = 1; + list[1] = 1; + list[2] = 1; + histogram.buildFromData(list); + + histogramMap.put("column_name", histogram); + when(mockCacheLine.getTopN("column_name")).thenReturn(new TopN(new IntegerType(), 1)); + when(mockCacheLine.getHistogramMap()).thenReturn(histogramMap); + + boolean result = RealStatsLogType.hasMissingStatistics(mockCacheLine, "Column_Name"); + + assertFalse("当缓存行包含有效的统计信息时,应该返回false", result); + } + + @Test + public void testHasMissingStatisticsTopNIsNull() { + String colName = "column_name"; + Map nullCountMap = Maps.newHashMap(); + nullCountMap.put(colName, 1L); + StatisticManager.CacheLine mockCacheLine = mock(StatisticManager.CacheLine.class); + when(mockCacheLine.getTopN("column_name")).thenReturn(null); + when(mockCacheLine.getRowCount()).thenReturn(2L); + when(mockCacheLine.getNullCountMap()).thenReturn(nullCountMap); + + boolean result = RealStatsLogType.hasMissingStatistics(mockCacheLine, colName); + + assertTrue(result, "当topN统计为空时,应该返回true"); + } + + @Test + public void testHasMissingStatisticsHistogramMapIsNull() { + String colName = "column_name"; + Map nullCountMap = Maps.newHashMap(); + nullCountMap.put(colName, 1L); + StatisticManager.CacheLine mockCacheLine = mock(StatisticManager.CacheLine.class); + when(mockCacheLine.getHistogramMap()).thenReturn(null); + when(mockCacheLine.getRowCount()).thenReturn(2L); + when(mockCacheLine.getNullCountMap()).thenReturn(nullCountMap); + + boolean result = RealStatsLogType.hasMissingStatistics(mockCacheLine, colName); + + assertTrue(result, "当缓存行的直方图映射为null时,应该返回true"); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/SketchByColumnarTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/SketchByColumnarTest.java index 49443f4e8..d8a28d5df 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/SketchByColumnarTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/SketchByColumnarTest.java @@ -3,9 +3,22 @@ import com.alibaba.polardbx.common.properties.BooleanConfigParam; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.executor.mpp.deploy.Server; +import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; import com.alibaba.polardbx.executor.statistic.ndv.NDVShardSketch; +import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.node.AllNodes; +import com.alibaba.polardbx.gms.node.InternalNode; +import com.alibaba.polardbx.gms.node.InternalNodeManager; +import com.alibaba.polardbx.gms.node.MppScope; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.google.common.collect.ImmutableBiMap; +import com.sun.tools.javac.util.List; import org.junit.Test; import org.mockito.MockedStatic; import org.mockito.Mockito; @@ -13,6 +26,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; public class SketchByColumnarTest { @@ -25,23 +39,6 @@ public void testGenColumnarHllHintWithoutEc() { assertThat(NDVShardSketch.genColumnarHllHint(null)).isNull(); } - try (MockedStatic instConfUtilMockedStatic = Mockito.mockStatic(InstConfUtil.class)) { - instConfUtilMockedStatic.when(() -> InstConfUtil.getBool(any(BooleanConfigParam.class))).thenAnswer( - invocation -> { - BooleanConfigParam param = invocation.getArgument(0); - if (param.equals(ConnectionParams.ENABLE_NDV_USE_COLUMNAR)) { - return true; - } - return false; - } - ); - - String hint = NDVShardSketch.genColumnarHllHint(null); - assertThat(hint).isNotEmpty(); - assertThat(hint).contains("ENABLE_DIRECT_PLAN=false"); - assertThat(hint).doesNotContain("ENABLE_HTAP"); - } - try (MockedStatic instConfUtilMockedStatic = Mockito.mockStatic(InstConfUtil.class)) { instConfUtilMockedStatic.when(() -> InstConfUtil.getBool(any(BooleanConfigParam.class))).thenAnswer( invocation -> { @@ -69,21 +66,18 @@ public void testGenColumnarHllHint() { when(pm.getBoolean(any(BooleanConfigParam.class))).thenReturn(false); assertThat(NDVShardSketch.genColumnarHllHint(ec)).isNull(); - // enable ENABLE_NDV_USE_COLUMNAR + String hint; + when(pm.getBoolean(any(BooleanConfigParam.class))).thenAnswer( invocation -> { BooleanConfigParam param = invocation.getArgument(0); - if (param.equals(ConnectionParams.ENABLE_NDV_USE_COLUMNAR)) { + if (param.equals(ConnectionParams.ENABLE_MPP_NDV_USE_COLUMNAR)) { return true; } return false; }); - - String hint; hint = NDVShardSketch.genColumnarHllHint(ec); - assertThat(NDVShardSketch.genColumnarHllHint(ec)).isNotEmpty(); - assertThat(hint).doesNotContain("ENABLE_HTAP"); - assertThat(hint).doesNotContain("ENABLE_MASTER_MPP"); + assertThat(hint).contains("ENABLE_MASTER_MPP=true"); when(pm.getBoolean(any(BooleanConfigParam.class))).thenAnswer( invocation -> { @@ -95,19 +89,106 @@ public void testGenColumnarHllHint() { }); hint = NDVShardSketch.genColumnarHllHint(ec); assertThat(hint).contains("ENABLE_MASTER_MPP=true"); + } + + @Test + public void testGenColumnarHllLimitHint() { + ExecutionContext ec = mock(ExecutionContext.class); + ParamManager pm = mock(ParamManager.class); + Mockito.when(ec.getParamManager()).thenReturn(pm); + + when(pm.getBoolean(any(BooleanConfigParam.class))).thenReturn(false); + assertThat(NDVShardSketch.genColumnarHllHint(ec)).isNull(); when(pm.getBoolean(any(BooleanConfigParam.class))).thenAnswer( invocation -> { BooleanConfigParam param = invocation.getArgument(0); - if (param.equals(ConnectionParams.ENABLE_NDV_USE_COLUMNAR)) { + if (param.equals(ConnectionParams.ENABLE_MPP_NDV_USE_COLUMNAR)) { return true; } - if (param.equals(ConnectionParams.ENABLE_MPP_NDV_USE_COLUMNAR)) { + if (param.equals(ConnectionParams.MPP_NDV_USE_COLUMNAR_LIMIT)) { return true; } return false; }); - hint = NDVShardSketch.genColumnarHllHint(ec); - assertThat(hint).contains("ENABLE_MASTER_MPP=true"); + + try (MockedStatic execUtilsMockedStatic = Mockito.mockStatic(ExecUtils.class); + final MockedStatic mockServiceProvider = mockStatic(ServiceProvider.class)) { + execUtilsMockedStatic.when(() -> ExecUtils.getMppSchedulerScope(any(Boolean.class))).thenAnswer( + invocation -> MppScope.CURRENT + ); + ServiceProvider serviceProvider = mock(ServiceProvider.class); + mockServiceProvider.when(ServiceProvider::getInstance).thenReturn(serviceProvider); + Server server = mock(Server.class); + when(serviceProvider.getServer()).thenReturn(server); + InternalNodeManager nodeManager = mock(InternalNodeManager.class); + when(server.getNodeManager()).thenReturn(nodeManager); + AllNodes allNodes = mock(AllNodes.class); + when(nodeManager.getAllNodes()).thenReturn(allNodes); + when(allNodes.getAllWorkers(any(MppScope.class))).thenAnswer( + invocation -> List.of(mock(InternalNode.class), mock(InternalNode.class)) + ); + + String hint; + hint = NDVShardSketch.genColumnarHllHint(ec); + assertThat(hint).contains("MPP_PARALLELISM=2"); + assertThat(hint).contains("MPP_NODE_SIZE=2"); + + execUtilsMockedStatic.when(() -> ExecUtils.getMppSchedulerScope(any(Boolean.class))).thenAnswer( + invocation -> MppScope.COLUMNAR + ); + when(pm.getBoolean(any(BooleanConfigParam.class))).thenAnswer( + invocation -> { + BooleanConfigParam param = invocation.getArgument(0); + if (param.equals(ConnectionParams.ENABLE_MPP_NDV_USE_COLUMNAR)) { + return true; + } + if (param.equals(ConnectionParams.MPP_NDV_USE_COLUMNAR_LIMIT)) { + return true; + } + return false; + }); + hint = NDVShardSketch.genColumnarHllHint(ec); + assertThat(hint).doesNotContain("MPP_PARALLELISM"); + + when(pm.getBoolean(any(BooleanConfigParam.class))).thenAnswer( + invocation -> { + BooleanConfigParam param = invocation.getArgument(0); + if (param.equals(ConnectionParams.ENABLE_MPP_NDV_USE_COLUMNAR)) { + return true; + } + return false; + }); + hint = NDVShardSketch.genColumnarHllHint(ec); + assertThat(hint).doesNotContain("MPP_PARALLELISM"); + } + } + + @Test + public void testGenColumnarHllMeta() { + try (MockedStatic optimizerContextMockedStatic = Mockito.mockStatic(OptimizerContext.class); + MockedStatic instConfUtilMockedStatic = Mockito.mockStatic(InstConfUtil.class)) { + String hint; + TableMeta tableMeta = mock(TableMeta.class); + SchemaManager schemaManager = mock(SchemaManager.class); + OptimizerContext optimizerContext = mock(OptimizerContext.class); + optimizerContextMockedStatic.when(() -> OptimizerContext.getContext(any())).thenReturn(optimizerContext); + + when(optimizerContext.getLatestSchemaManager()).thenReturn(schemaManager); + when(schemaManager.getTableWithNull(any())).thenReturn(null); + hint = NDVShardSketch.genColumnarHllHint(null, "a", "b"); + assertThat(hint).isNull(); + + when(schemaManager.getTableWithNull(any())).thenReturn(tableMeta); + when(tableMeta.getColumnarIndexPublished()).thenReturn(null); + hint = NDVShardSketch.genColumnarHllHint(null, "a", "b"); + assertThat(hint).isNull(); + + when(tableMeta.getColumnarIndexPublished()).thenReturn(ImmutableBiMap.of("c", + mock(GsiMetaManager.GsiIndexMetaBean.class))); + instConfUtilMockedStatic.when(() -> InstConfUtil.getBool(any())).thenReturn(false); + hint = NDVShardSketch.genColumnarHllHint(null, "a", "b"); + assertThat(hint).isNull(); + } } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/StatisticManagerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/StatisticManagerTest.java index de1024efc..3262dee09 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/StatisticManagerTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/StatisticManagerTest.java @@ -1,7 +1,11 @@ package com.alibaba.polardbx.executor.statistics; +import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.executor.common.BasePlannerTest; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticManager; import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticResult; import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/entity/PolarDbXSystemTableColumnStatisticTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/entity/PolarDbXSystemTableColumnStatisticTest.java new file mode 100644 index 000000000..da3b2e21a --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/entity/PolarDbXSystemTableColumnStatisticTest.java @@ -0,0 +1,56 @@ +package com.alibaba.polardbx.executor.statistics.entity; + +import com.alibaba.polardbx.executor.statistic.entity.PolarDbXSystemTableColumnStatistic; +import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.optimizer.config.table.statistic.Histogram; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import static org.junit.Assert.assertEquals; + +/** + * @author fangwu + */ +public class PolarDbXSystemTableColumnStatisticTest { + + @BeforeClass + public static void setUp() { + MetaDbInstConfigManager.setConfigFromMetaDb(false); + } + + @Test + // 测试用例1: 当传入的直方图字符串可以成功反序列化时,函数应该正常返回空字符串。 + public void testCheckHistogramStringWithValidInput() { + // 准备 + String histogramString = "{\"buckets\":[[\"a\",1],[\"b\",2]]}"; + String schema = "test_schema"; + String tableName = "test_table"; + String columnName = "test_column"; + + // 使用Mockito模拟Histogram类的deserializeFromJson方法,使其返回一个非null对象。 + Histogram mockHistogram = Mockito.mock(Histogram.class); + try (MockedStatic mockedStatic = Mockito.mockStatic(Histogram.class);) { + mockedStatic.when(() -> Histogram.deserializeFromJson(histogramString)).thenReturn(mockHistogram); + + String result = + PolarDbXSystemTableColumnStatistic.checkHistogramString(histogramString, schema, tableName, columnName); + + assertEquals(histogramString, result); + } + } + + @Test + // 测试用例2: 当传入的直方图字符串无法反序列化成Histogram对象时,函数应该记录错误并返回空字符串。 + public void testCheckHistogramStringWithInvalidInput() { + String schema = "test_schema"; + String tableName = "test_table"; + String columnName = "test_column"; + + String result = + PolarDbXSystemTableColumnStatistic.checkHistogramString("", schema, tableName, columnName); + + assertEquals("", result); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/ndv/NDVShardSketchTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/ndv/NDVShardSketchTest.java new file mode 100644 index 000000000..c01758459 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/ndv/NDVShardSketchTest.java @@ -0,0 +1,381 @@ +package com.alibaba.polardbx.executor.statistics.ndv; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.statistic.ndv.NDVShardSketch; +import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.gms.metadb.table.IndexStatus; +import com.alibaba.polardbx.gms.metadb.table.IndexVisibility; +import com.alibaba.polardbx.gms.module.ModuleLogInfo; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import com.alibaba.polardbx.optimizer.config.table.IndexMeta; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticDataSource; +import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticManager; +import com.clearspring.analytics.util.Lists; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import org.jetbrains.annotations.NotNull; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import static com.alibaba.polardbx.common.utils.Assert.assertNotNull; +import static com.alibaba.polardbx.common.utils.Assert.assertTrue; +import static com.alibaba.polardbx.common.utils.Assert.fail; +import static com.alibaba.polardbx.executor.statistic.ndv.NDVShardSketch.handleException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +/** + * @author fangwu + */ +public class NDVShardSketchTest { + @Test + public void testBuildShardPartsValidInput() { + String schemaName = "test_schema"; + String tableName = "test_table"; + String columnNames = "col1,col2"; + OptimizerContext opMock = mock(OptimizerContext.class); + when(opMock.getLatestSchemaManager()).thenReturn(mock(SchemaManager.class)); + + TableMeta tableMeta = mock(TableMeta.class); + IndexMeta indexMeta = mock(IndexMeta.class); + ColumnMeta col1 = mock(ColumnMeta.class); + ColumnMeta col2 = mock(ColumnMeta.class); + when(col1.getName()).thenReturn("col1"); + when(col2.getName()).thenReturn("col2"); + when(tableMeta.getIndexes()).thenReturn(Collections.singletonList(indexMeta)); + when(indexMeta.getPhysicalIndexName()).thenReturn("physical_index"); + when(indexMeta.getKeyColumns()).thenReturn(ImmutableList.of(col1, col2)); + when(opMock.getLatestSchemaManager().getTable(tableName)).thenReturn(tableMeta); + + Map> topology = new HashMap<>(); + topology.put("group1", Collections.singleton("testTable1")); + topology.put("group2", ImmutableSet.of("testTable1", "testTable2")); + + try (MockedStatic optimizerContext = Mockito.mockStatic(OptimizerContext.class); + MockedStatic ndvShardSketch = Mockito.mockStatic(NDVShardSketch.class)) { + ndvShardSketch.when(() -> NDVShardSketch.getTopology(schemaName, tableName, opMock)).thenReturn(topology); + ndvShardSketch.when(() -> NDVShardSketch.buildShardParts(schemaName, tableName, columnNames)) + .thenCallRealMethod(); + ndvShardSketch.when(() -> NDVShardSketch.topologyPartToShard(any())).thenCallRealMethod(); + optimizerContext.when(() -> OptimizerContext.getContext(schemaName)).thenReturn(opMock); + + Pair result = NDVShardSketch.buildShardParts(schemaName, tableName, columnNames); + + assertNotNull(result); + assertEquals("physical_index", result.getKey()); + assertTrue(Arrays.asList(result.getValue()) + .containsAll(ImmutableList.of("group1:testtable1", "group2:testtable1", "group2:testtable2"))); + } + } + + @Test + public void testBuildShardPartsGsiValidInput() { + String schemaName = "test_schema"; + String tableName = "test_table"; + String indexTableName = "index_test_table"; + String columnNames = "col1,col2"; + OptimizerContext opMock = mock(OptimizerContext.class); + when(opMock.getLatestSchemaManager()).thenReturn(mock(SchemaManager.class)); + + final Map gsiMeta = getStringGsiIndexMetaBeanMap(); + TableMeta tableMeta = mock(TableMeta.class); + TableMeta tableMetaGsi = mock(TableMeta.class); + IndexMeta indexMeta = mock(IndexMeta.class); + ColumnMeta col1 = mock(ColumnMeta.class); + ColumnMeta col2 = mock(ColumnMeta.class); + when(col1.getName()).thenReturn("col1"); + when(col2.getName()).thenReturn("col2"); + when(tableMeta.getIndexes()).thenReturn(Collections.emptyList()); + when(tableMeta.getGsiPublished()).thenReturn(gsiMeta); + when(tableMetaGsi.getIndexes()).thenReturn(Collections.singletonList(indexMeta)); + when(indexMeta.getPhysicalIndexName()).thenReturn("physical_index"); + when(indexMeta.getKeyColumns()).thenReturn(ImmutableList.of(col1, col2)); + when(opMock.getLatestSchemaManager().getTable(tableName)).thenReturn(tableMeta); + when(opMock.getLatestSchemaManager().getTable(indexTableName)).thenReturn(tableMetaGsi); + + Map> topology = new HashMap<>(); + topology.put("group1", Collections.singleton("testTable1")); + topology.put("group2", ImmutableSet.of("testTable1", "testTable2")); + + try (MockedStatic optimizerContext = Mockito.mockStatic(OptimizerContext.class); + MockedStatic ndvShardSketch = Mockito.mockStatic(NDVShardSketch.class)) { + ndvShardSketch.when(() -> NDVShardSketch.getTopology(schemaName, indexTableName, opMock)) + .thenReturn(topology); + ndvShardSketch.when(() -> NDVShardSketch.buildShardParts(schemaName, tableName, columnNames)) + .thenCallRealMethod(); + ndvShardSketch.when(() -> NDVShardSketch.topologyPartToShard(any())).thenCallRealMethod(); + optimizerContext.when(() -> OptimizerContext.getContext(schemaName)).thenReturn(opMock); + + Pair result = NDVShardSketch.buildShardParts(schemaName, tableName, columnNames); + + assertNotNull(result); + assertEquals("physical_index", result.getKey()); + assertTrue(Arrays.asList(result.getValue()) + .containsAll(ImmutableList.of("group1:testtable1", "group2:testtable1", "group2:testtable2"))); + } + } + + @Test + public void testHandleExceptionOtherSqlError() { + // test error code that is not 1146 + String shardKey = "shardKey"; + String shardPart = "shardPart"; + SQLException e = mock(SQLException.class); + when(e.getErrorCode()).thenReturn(1000); // 假设这是另一个错误码 + when(e.getSQLState()).thenReturn("42S02"); + try (MockedStatic mockedStatic = mockStatic(StatisticManager.class); + MockedStatic mockedLog = mockStatic(ModuleLogInfo.class);) { + StatisticManager mockManager = mock(StatisticManager.class); + ModuleLogInfo mockModuleLog = mock(ModuleLogInfo.class); + StatisticDataSource mockSource = mock(StatisticDataSource.class); + mockedStatic.when(StatisticManager::getInstance).thenReturn(mockManager); + mockedLog.when(ModuleLogInfo::getInstance).thenReturn(mockModuleLog); + when(mockManager.getSds()).thenReturn(mockSource); + doNothing().when(mockSource).removeLogicalTableList(any(), any()); + doNothing().when(mockModuleLog).logRecord(any(), any(), any(), any(), any(Exception.class)); + + handleException(shardKey, shardPart, e, "schemaName", new String[] {"shardKeys1"}); + fail("Should throw exception"); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Test + public void testHandleExceptionDifferentSqlState() { + // test sql state that is not 42S02 + String shardKey = "shardKey"; + String shardPart = "shardPart"; + SQLException e = mock(SQLException.class); + when(e.getErrorCode()).thenReturn(1146); + when(e.getSQLState()).thenReturn("50000"); + try (MockedStatic mockedStatic = mockStatic(StatisticManager.class); + MockedStatic mockedLog = mockStatic(ModuleLogInfo.class);) { + StatisticManager mockManager = mock(StatisticManager.class); + ModuleLogInfo mockModuleLog = mock(ModuleLogInfo.class); + StatisticDataSource mockSource = mock(StatisticDataSource.class); + mockedStatic.when(StatisticManager::getInstance).thenReturn(mockManager); + mockedLog.when(ModuleLogInfo::getInstance).thenReturn(mockModuleLog); + when(mockManager.getSds()).thenReturn(mockSource); + doNothing().when(mockSource).removeLogicalTableList(any(), any()); + doNothing().when(mockModuleLog).logRecord(any(), any(), any(), any(), any(Exception.class)); + + handleException(shardKey, shardPart, e, "schemaName", new String[] {"shardKeys1"}); + fail("Should throw exception"); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Test + public void testHandleExceptionNonSqlException() throws Exception { + // test exception that is not SQLException + String shardKey = "shardKey"; + String shardPart = "shardPart"; + Exception e = new RuntimeException("Non-SQL exception"); + try (MockedStatic mockedStatic = mockStatic(StatisticManager.class); + MockedStatic mockedLog = mockStatic(ModuleLogInfo.class);) { + StatisticManager mockManager = mock(StatisticManager.class); + ModuleLogInfo mockModuleLog = mock(ModuleLogInfo.class); + StatisticDataSource mockSource = mock(StatisticDataSource.class); + mockedStatic.when(StatisticManager::getInstance).thenReturn(mockManager); + mockedLog.when(ModuleLogInfo::getInstance).thenReturn(mockModuleLog); + when(mockManager.getSds()).thenReturn(mockSource); + doNothing().when(mockSource).removeLogicalTableList(any(), any()); + doNothing().when(mockModuleLog).logRecord(any(), any(), any(), any(), any(Exception.class)); + + handleException(shardKey, shardPart, e, "schemaName", new String[] {"shardKeys1"}); + fail("Should throw exception"); + } catch (Exception ex) { + ex.printStackTrace(); + assertEquals(e, ex); + } + } + + /** + * 测试用例1: 当schema存在时返回true + * 设计思路: + * - 假设shardKey包含有效的schema名称、表名和列名。 + * - mock buildShardParts使其返回预期的结果。 + * - 确保当传入的shardParts与构建出的一致时,返回true。 + */ + @Test + public void testIsValidShardPartSchemaExists() { + // 准备 + String shardKey = "test_schema:test_table:test_column"; + String[] shardParts = {"part1", "part2"}; + String[] shardParts1 = {"part2", "part1"}; + String[] shardParts2 = {"part2", "part1", "part3"}; + + // 模拟 + Pair mockedResult = mock(Pair.class); + when(mockedResult.getValue()).thenReturn(shardParts); + + try (MockedStatic ndvShardSketch = Mockito.mockStatic(NDVShardSketch.class)) { + ndvShardSketch.when(() -> NDVShardSketch.buildShardParts(any(), any(), any())) + .thenReturn(mockedResult); + ndvShardSketch.when(() -> NDVShardSketch.isValidShardPart(anyString(), any())).thenCallRealMethod(); + // 执行 + boolean result = NDVShardSketch.isValidShardPart(shardKey, shardParts).booleanValue(); + + // 验证 + assertTrue(result); + + when(mockedResult.getValue()).thenReturn(shardParts1); + + // 执行 + result = NDVShardSketch.isValidShardPart(shardKey, shardParts).booleanValue(); + + // 验证 + assertTrue(result); + + when(mockedResult.getValue()).thenReturn(shardParts2); + + // 执行 + result = NDVShardSketch.isValidShardPart(shardKey, shardParts).booleanValue(); + + // 验证 + assertFalse(result); + } + } + + /** + * 测试用例2: 当schema不存在时返回null + * 设计思路: + * - 设置shardKey为有效值但让buildShardParts返回null。 + * - 预期isValidShardPart应该返回null。 + */ + @Test + public void testIsValidShardPartSchemaNotExists() { + // 准备 + String shardKey = "nonexistent_schema:test_table:test_column"; + String[] shardParts = {"part1", "part2"}; + + // 执行 + Boolean result = NDVShardSketch.isValidShardPart(shardKey, shardParts); + + // 验证 + assertNull(result); + } + + /** + * 测试用例3: 当shardKey为空时抛出异常 + * 设计思路: + * - 输入一个空字符串作为shardKey。 + * - 预期程序会因为split操作失败而抛出异常。 + */ + @Test + public void testIsValidShardPartWithEmptyShardKey() { + // 准备 + String shardKey = ""; + String[] shardParts = {"part1", "part2"}; + + // 执行并验证 + Assert.assertTrue(NDVShardSketch.isValidShardPart(shardKey, shardParts) == null); + } + + /** + * 测试用例4: 当shardKey缺少部分信息时返回false + * 设计思路: + * - 提供一个缺少一部分信息的shardKey。 + * - 即使buildShardParts正确返回,但由于shardParts不匹配,所以返回false。 + */ + @Test + public void testIsValidShardPartWithIncompleteShardKey() { + // 准备 + String shardKey = "test_schema:test_table:column"; + String[] shardParts = {"part1", "part2"}; + + // 模拟 + Pair mockedResult = mock(Pair.class); + when(mockedResult.getValue()).thenReturn(new String[] {"part1"}); + try (MockedStatic ndvShardSketch = Mockito.mockStatic(NDVShardSketch.class)) { + ndvShardSketch.when(() -> NDVShardSketch.buildShardParts(any(), any(), any())) + .thenReturn(mockedResult); + ndvShardSketch.when(() -> NDVShardSketch.isValidShardPart(anyString(), any())).thenCallRealMethod(); + // 执行 + boolean result = NDVShardSketch.isValidShardPart(shardKey, shardParts).booleanValue(); + + // 验证 + assertFalse(result); + } + } + + @NotNull + private Map getStringGsiIndexMetaBeanMap() { + Map gsiMeta = new HashMap<>(); + GsiMetaManager.GsiIndexMetaBean gsiMeta1 = new GsiMetaManager.GsiIndexMetaBean( + "testIndex", + "testSchema", + "index_test_table", + false, + "index_schema", + "non_Matching_Index", + Lists.newArrayList(), + Lists.newArrayList(), + "indexType", + "", + "", + null, + "index_test_table", + IndexStatus.PUBLIC, + 0, + false, + false, + IndexVisibility.VISIBLE); + + final GsiMetaManager.GsiIndexMetaBean gsiMeta2 = getGsiIndexMetaBean(); + gsiMeta.put("1", gsiMeta1); + gsiMeta.put("2", gsiMeta2); + return gsiMeta; + } + + @NotNull + private GsiMetaManager.GsiIndexMetaBean getGsiIndexMetaBean() { + GsiMetaManager.GsiIndexColumnMetaBean gsiIndexColumnMetaBean1 = + new GsiMetaManager.GsiIndexColumnMetaBean(1, "col1", "", 0, 0L, "", "", false); + GsiMetaManager.GsiIndexColumnMetaBean gsiIndexColumnMetaBean2 = + new GsiMetaManager.GsiIndexColumnMetaBean(1, "col2", "", 0, 0L, "", "", false); + GsiMetaManager.GsiIndexMetaBean gsiMeta2 = new GsiMetaManager.GsiIndexMetaBean( + "testIndex", + "testSchema", + "index_test_table", + false, + "index_schema", + "non_Matching_Index", + ImmutableList.of(gsiIndexColumnMetaBean1, gsiIndexColumnMetaBean2), + Lists.newArrayList(), + "indexType", + "", + "", + null, + "index_test_table", + IndexStatus.PUBLIC, + 0, + false, + false, + IndexVisibility.VISIBLE); + return gsiMeta2; + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/ndv/NDVSketchTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/ndv/NDVSketchTest.java new file mode 100644 index 000000000..71b9f51f9 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/statistics/ndv/NDVSketchTest.java @@ -0,0 +1,188 @@ +package com.alibaba.polardbx.executor.statistics.ndv; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.executor.statistic.entity.PolarDbXSystemTableNDVSketchStatistic; +import com.alibaba.polardbx.executor.statistic.ndv.NDVShardSketch; +import com.alibaba.polardbx.executor.statistic.ndv.NDVSketch; +import com.alibaba.polardbx.optimizer.config.table.statistic.inf.SystemTableNDVSketchStatistic; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ThreadPoolExecutor; + +import static com.alibaba.polardbx.common.utils.Assert.assertTrue; +import static com.alibaba.polardbx.common.utils.Assert.fail; +import static com.alibaba.polardbx.executor.statistic.ndv.HyperLogLogUtil.buildSketchKey; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atMostOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * @author fangwu + */ +public class NDVSketchTest { + @Test + public void testParseWithValidInput() { + SystemTableNDVSketchStatistic.SketchRow[] sketchRows = createMockSketchRows(3); + NDVSketch instanceUnderTest = new NDVSketch(); + + instanceUnderTest.parse(sketchRows); + + assertTrue(instanceUnderTest.getStringNDVShardSketchMap().size() == 3); + } + + private SystemTableNDVSketchStatistic.SketchRow[] createMockSketchRows(int count) { + List rows = new ArrayList<>(); + for (int i = 0; i < count; i++) { + SystemTableNDVSketchStatistic.SketchRow row = mock(SystemTableNDVSketchStatistic.SketchRow.class); + when(row.getSchemaName()).thenReturn("schema" + i); + when(row.getTableName()).thenReturn("table" + i); + when(row.getColumnNames()).thenReturn("column" + i); + when(row.getShardPart()).thenReturn("part" + i); + when(row.getIndexName()).thenReturn("index" + i); + when(row.getDnCardinality()).thenReturn((long) i); + when(row.getGmtUpdate()).thenReturn((long) (i * 1000)); + when(row.getGmtCreate()).thenReturn((long) (i * 100)); + when(row.getCompositeCardinality()).thenReturn((long) (i + 1)); + rows.add(row); + } + return rows.toArray(new SystemTableNDVSketchStatistic.SketchRow[0]); + } + + @Test + public void testParseWithEmptyInput() { + SystemTableNDVSketchStatistic.SketchRow[] emptySketchRows = {}; + NDVSketch instanceUnderTest = new NDVSketch(); + + instanceUnderTest.parse(emptySketchRows); + + assertTrue(instanceUnderTest.getStringNDVShardSketchMap().isEmpty()); + } + + @Test + public void testParseWithDuplicateKeys() { + SystemTableNDVSketchStatistic.SketchRow[] duplicateSketchRows = createMockSketchRowsWithDuplicates(2); + NDVSketch instanceUnderTest = new NDVSketch(); + + instanceUnderTest.parse(duplicateSketchRows); + + assertTrue(instanceUnderTest.getStringNDVShardSketchMap().size() == 1); + } + + @Test + public void testRemove() { + PolarDbXSystemTableNDVSketchStatistic mockedInstance = mock(PolarDbXSystemTableNDVSketchStatistic.class); + try (MockedStatic mockedStatic = mockStatic( + PolarDbXSystemTableNDVSketchStatistic.class)) { + mockedStatic.when(PolarDbXSystemTableNDVSketchStatistic::getInstance).thenReturn(mockedInstance); + NDVSketch ndvSketch = new NDVSketch(); + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + for (int m = 0; m < 5; m++) { + String schema = "schema" + i; + String table = "tbl" + j; + String col = "col" + m; + String sketchKey = buildSketchKey(schema, table, col); + ndvSketch.getStringNDVShardSketchMap().put(sketchKey, Mockito.mock(NDVShardSketch.class)); + } + } + } + ndvSketch.remove("schema2", "tbl5"); + Assert.assertTrue(ndvSketch.getStringNDVShardSketchMap().size() == 495); + verify(mockedInstance, times(5)).deleteByColumn(eq("schema2"), eq("tbl5"), anyString()); + Mockito.clearInvocations(mockedInstance); + + ndvSketch.remove("sChema1", "Tbl5"); + Assert.assertTrue(ndvSketch.getStringNDVShardSketchMap().size() == 490); + verify(mockedInstance, times(5)).deleteByColumn(eq("schema1"), eq("tbl5"), anyString()); + Mockito.clearInvocations(mockedInstance); + + ndvSketch.remove("", "Tbl5"); + Assert.assertTrue(ndvSketch.getStringNDVShardSketchMap().size() == 490); + verify(mockedInstance, times(0)).deleteByColumn(anyString(), anyString(), anyString()); + } + } + + /** + * 测试用例1: 当传入参数为空时,直接返回不执行后续操作。 + * 确认当任意一个参数为空字符串时,方法正常退出。 + */ + @Test + public void testUpdateAllShardPartsWhenParamsAreEmptyShouldReturnWithoutExecuting() throws Exception { + PolarDbXSystemTableNDVSketchStatistic mockedInstance = mock(PolarDbXSystemTableNDVSketchStatistic.class); + NDVSketch sketchUnderTest = new NDVSketch(); + + try (MockedStatic mockedStatic = mockStatic( + PolarDbXSystemTableNDVSketchStatistic.class)) { + mockedStatic.when(PolarDbXSystemTableNDVSketchStatistic::getInstance).thenReturn(mockedInstance); + + sketchUnderTest.updateAllShardParts("", "tableName", "columnName", mock(ExecutionContext.class), + mock(ThreadPoolExecutor.class)); + sketchUnderTest.updateAllShardParts("schema", "", "columnName", mock(ExecutionContext.class), + mock(ThreadPoolExecutor.class)); + sketchUnderTest.updateAllShardParts("schema", "tableName", "", mock(ExecutionContext.class), + mock(ThreadPoolExecutor.class)); + + verify(mockedInstance, times(0)).deleteByColumn(eq("schema"), eq("tablename"), eq("columnname")); + } + } + + /** + * 测试用例2: 当NDVShardSketch有效但部分分区已过期时,应该重新构建。 + * 假设genColumnarHllHint返回非空值。 + */ + @Test + public void testUpdateAllShardPartsWhenNDVShardSketchHasExpiredPartsShouldRebuild() throws Exception { + NDVSketch sketchUnderTest = new NDVSketch(); + + NDVShardSketch expiredSketch = mock(NDVShardSketch.class); + when(expiredSketch.getShardKey()).thenReturn("key"); + when(expiredSketch.getShardParts()).thenReturn(Arrays.asList("part1", "part2").toArray(new String[0])); + sketchUnderTest.getStringNDVShardSketchMap().put("key", expiredSketch); + PolarDbXSystemTableNDVSketchStatistic mockedInstance = mock(PolarDbXSystemTableNDVSketchStatistic.class); + try (MockedStatic mockedStatic = mockStatic(NDVShardSketch.class); + MockedStatic mockedStatic1 = mockStatic( + PolarDbXSystemTableNDVSketchStatistic.class)) { + mockedStatic.when(() -> NDVShardSketch.isValidShardPart(anyString(), any())).thenReturn(true); + mockedStatic.when( + () -> NDVShardSketch.genColumnarHllHint(mock(ExecutionContext.class), "schema", "tableName")) + .thenReturn("hint"); + mockedStatic1.when(PolarDbXSystemTableNDVSketchStatistic::getInstance).thenReturn(mockedInstance); + + when(expiredSketch.anyShardExpired()).thenReturn(true); + sketchUnderTest.updateAllShardParts("schema", "tableName", "columnName", mock(ExecutionContext.class), + mock(ThreadPoolExecutor.class)); + verify(mockedInstance).deleteByColumn(eq("schema"), eq("tablename"), eq("columnname")); + } + } + + private SystemTableNDVSketchStatistic.SketchRow[] createMockSketchRowsWithDuplicates(int count) { + List rows = new ArrayList<>(); + for (int i = 0; i < count; i++) { + SystemTableNDVSketchStatistic.SketchRow row = mock(SystemTableNDVSketchStatistic.SketchRow.class); + when(row.getSchemaName()).thenReturn("schema"); + when(row.getTableName()).thenReturn("table"); + when(row.getColumnNames()).thenReturn("column"); + when(row.getShardPart()).thenReturn("part" + i); + when(row.getIndexName()).thenReturn("index"); + when(row.getDnCardinality()).thenReturn((long) i); + when(row.getGmtUpdate()).thenReturn((long) (i * 1000)); + when(row.getGmtCreate()).thenReturn((long) (i * 100)); + when(row.getCompositeCardinality()).thenReturn((long) (i + 1)); + rows.add(row); + } + return rows.toArray(new SystemTableNDVSketchStatistic.SketchRow[0]); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/sync/GlobalAcquireMdlLockInDbSyncActionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/sync/GlobalAcquireMdlLockInDbSyncActionTest.java new file mode 100644 index 000000000..83bc03ca5 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/sync/GlobalAcquireMdlLockInDbSyncActionTest.java @@ -0,0 +1,62 @@ +package com.alibaba.polardbx.executor.sync; + +import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlHelper; +import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class GlobalAcquireMdlLockInDbSyncActionTest { + + @InjectMocks + private GlobalAcquireMdlLockInDbSyncAction action = + new GlobalAcquireMdlLockInDbSyncAction(ImmutableSet.of("testSchema")); + + @Mock + private SchemaManager schemaManager; + + @Before + public void setUp() { + } + + @Test + public void testGetAllTablesInDatabase() { + String schemaName = "testSchema"; + List> mockResult = ImmutableList.of( + ImmutableMap.of("TABLE_TYPE", "base table", "TABLES_IN_TESTSCHEMA", "tbl1"), + ImmutableMap.of("TABLE_TYPE", "base table", "TABLES_IN_TESTSCHEMA1", "tbl2"), + ImmutableMap.of("TABLE_TYPE", "view", "TABLES_IN_TESTSCHEMA", "view1") + ); + IServerConfigManager iServerConfigManager = mock(IServerConfigManager.class); + try (MockedStatic mockedDdlHelper = Mockito.mockStatic(DdlHelper.class);) { + mockedDdlHelper.when(() -> DdlHelper.getServerConfigManager()).thenReturn(iServerConfigManager); + when(iServerConfigManager.executeQuerySql(anyString(), anyString(), any())).thenReturn(mockResult); + + Set expectedTables = ImmutableSet.of("tbl1"); + Set actualTables = action.getAllTablesInDatabase(schemaName); + + assertEquals(expectedTables, actualTables); + } + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/sync/MetricSyncAllActionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/sync/MetricSyncAllActionTest.java new file mode 100644 index 000000000..88dce10e9 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/sync/MetricSyncAllActionTest.java @@ -0,0 +1,47 @@ +package com.alibaba.polardbx.executor.sync; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.gms.topology.ServerInstIdManager; +import com.alibaba.polardbx.optimizer.core.row.Row; +import org.junit.Test; +import org.mockito.MockedStatic; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +/** + * @author fangwu + */ +public class MetricSyncAllActionTest { + @Test + public void testSync() { + MetaDbInstConfigManager.setConfigFromMetaDb(false); + String testInstId = "test_inst_id"; + try ( + MockedStatic serverInstIdManagerMockedStatic = mockStatic(ServerInstIdManager.class)) { + ServerInstIdManager serverInstIdManager = mock(ServerInstIdManager.class); + serverInstIdManagerMockedStatic.when(ServerInstIdManager::getInstance).thenReturn(serverInstIdManager); + when(serverInstIdManager.getInstId()).thenReturn(testInstId); + + MetricSyncAllAction action = new MetricSyncAllAction(); + ResultCursor resultCursor = action.sync(); + + // assert meta + int count = 0; + assert resultCursor.getCursorMeta().getColumnMeta(count++).getName().equals(MetricSyncAllAction.INST); + assert resultCursor.getCursorMeta().getColumnMeta(count++).getName().equals(MetricSyncAllAction.HOST); + assert resultCursor.getCursorMeta().getColumnMeta(count++).getName() + .equals(MetricSyncAllAction.METRIC_FEAT_KEY); + assert resultCursor.getCursorMeta().getColumnMeta(count++).getName() + .equals(MetricSyncAllAction.METRIC_REAL_KEY); + + // assert data + Row r = resultCursor.next(); + Assert.assertTrue(r.getString(0).equalsIgnoreCase(testInstId)); + } + + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/sync/SyncActionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/sync/SyncActionTest.java new file mode 100644 index 000000000..93f58a9c7 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/sync/SyncActionTest.java @@ -0,0 +1,79 @@ +package com.alibaba.polardbx.executor.sync; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import org.junit.Test; + +public class SyncActionTest { + + @Test + public void testFailPointEnableSyncAction() { + ParserConfig parserConfig = ParserConfig.getGlobalInstance(); + parserConfig.setAutoTypeSupport(true); + ParserConfig.getGlobalInstance() + .addAccept("com.alibaba.polardbx.executor.sync.FailPointEnableSyncAction"); + + String key = "key1"; + FailPointEnableSyncAction action = new FailPointEnableSyncAction(key, "true"); + action.setFpKey(key); + action.setValue("true"); + + // serialize + String data = JSON.toJSONString(action, SerializerFeature.WriteClassName); + + // deserialize + FailPointEnableSyncAction action1 = (FailPointEnableSyncAction) JSON.parse(data); + + action1.sync(); + Assert.assertTrue(FailPoint.isKeyEnable(key)); + + // clear + FailPoint.disable(key); + } + + @Test + public void testFailPointDisableSyncAction() { + ParserConfig parserConfig = ParserConfig.getGlobalInstance(); + parserConfig.setAutoTypeSupport(true); + ParserConfig.getGlobalInstance() + .addAccept("com.alibaba.polardbx.executor.sync.FailPointDisableSyncAction"); + + String key = "key1"; + FailPointDisableSyncAction action = new FailPointDisableSyncAction(key); + action.setFpKey(key); + + // serialize + String data = JSON.toJSONString(action, SerializerFeature.WriteClassName); + + // deserialize + FailPointDisableSyncAction action1 = (FailPointDisableSyncAction) JSON.parse(data); + + FailPoint.enable(key, "true"); + action1.sync(); + Assert.assertTrue(!FailPoint.isKeyEnable(key)); + } + + @Test + public void testFailPointClearSyncAction() { + ParserConfig parserConfig = ParserConfig.getGlobalInstance(); + parserConfig.setAutoTypeSupport(true); + ParserConfig.getGlobalInstance() + .addAccept("com.alibaba.polardbx.executor.sync.FailPointClearSyncAction"); + + String key = "key1"; + FailPointClearSyncAction action = new FailPointClearSyncAction(); + + // serialize + String data = JSON.toJSONString(action, SerializerFeature.WriteClassName); + + // deserialize + FailPointClearSyncAction action1 = (FailPointClearSyncAction) JSON.parse(data); + + FailPoint.enable(key, "true"); + action1.sync(); + Assert.assertTrue(!FailPoint.isKeyEnable(key)); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/test/ParameterContextJSONTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/test/ParameterContextJSONTest.java index 70e759463..b6c87bce4 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/test/ParameterContextJSONTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/test/ParameterContextJSONTest.java @@ -31,7 +31,6 @@ import com.alibaba.polardbx.executor.mpp.split.JdbcSplit; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.statis.ColumnarTracer; import com.alibaba.polardbx.optimizer.utils.ITransaction; import com.alibaba.polardbx.optimizer.workload.WorkloadType; import com.fasterxml.jackson.annotation.JsonInclude; @@ -83,8 +82,6 @@ public static void beforeClass() { @Test public void testSession() throws Exception { - ColumnarTracer columnarTracer = new ColumnarTracer(); - columnarTracer.tracePruneIndex("tbl", "a>10", 10, 10, 10); SessionRepresentation sessionRepresentation = new SessionRepresentation( "traceId", "catalog", @@ -113,7 +110,7 @@ public void testSession() throws Exception { new HashMap<>(), false, false, - columnarTracer, + true, WorkloadType.TP, null); @@ -121,8 +118,7 @@ public void testSession() throws Exception { System.out.println(json); SessionRepresentation target = objectMapper.readValue(json, sessionRepresentation.getClass()); Assert.assertTrue(target.getDnLsnMap() != null); - Assert.assertTrue(target.getColumnarTracer() != null); - Assert.assertTrue(target.getColumnarTracer().pruneRecords().size() > 0); + Assert.assertTrue(target.getUseColumnarTracer()); } @Test diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/ByteUtil.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/ByteUtil.java new file mode 100644 index 000000000..c8e2abe41 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/ByteUtil.java @@ -0,0 +1,14 @@ +package com.alibaba.polardbx.executor.utils; + +public class ByteUtil { + + public static byte[] toByteArray(long value) { + byte[] result = new byte[8]; + for (int i = 7; i >= 0; i--) { + result[i] = (byte) (value & 0xffL); + value >>= 8; + } + return result; + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/CleanSchemaMetaTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/CleanSchemaMetaTest.java new file mode 100644 index 000000000..3089959ac --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/CleanSchemaMetaTest.java @@ -0,0 +1,82 @@ +/* + * 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 com.alibaba.polardbx.executor.utils; + +import com.alibaba.polardbx.gms.listener.impl.MetaDbConfigManager; +import com.alibaba.polardbx.gms.listener.impl.MetaDbDataIdBuilder; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.sql.Connection; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; + +@RunWith(MockitoJUnitRunner.class) +public class CleanSchemaMetaTest { + + @Mock + private Connection metaDbConn; + + @InjectMocks + private SchemaMetaUtil.PolarDbXSchemaMetaCleaner polarDbXSchemaMetaCleaner = + new SchemaMetaUtil.PolarDbXSchemaMetaCleaner(); + + @Before + public void setUp() { + // Setup procedures if necessary + } + + @After + public void tearDown() { + // Cleanup resources or reset mocks +// mockReset(metaDbConn); + } + + @Test + public void testClearSchemaMetaInvokesCleanupSchemaMeta() throws Exception { + // Given + final String schemaName = "test_schema"; + final long versionId = 123L; + + MetaDbConfigManager metaDbConfigManager = Mockito.mock(MetaDbConfigManager.class); + doNothing().when(metaDbConfigManager).unregister(anyString(), any()); + try ( + MockedStatic mockMetaDbDataIdBuilder = Mockito.mockStatic(MetaDbDataIdBuilder.class)) { + try (MockedStatic mockMetaDbConfigManager = Mockito.mockStatic( + MetaDbConfigManager.class)) { + mockMetaDbDataIdBuilder.when(() -> MetaDbDataIdBuilder.getTableListDataId(anyString())) + .thenReturn("table"); + mockMetaDbConfigManager.when(() -> MetaDbConfigManager.getInstance()) + .thenAnswer(invocation -> metaDbConfigManager); + + polarDbXSchemaMetaCleaner.clearSchemaMeta(schemaName, metaDbConn, versionId); + } + } + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/DrdsToAutoTableCreationSqlUtilTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/DrdsToAutoTableCreationSqlUtilTest.java new file mode 100644 index 000000000..5456be1b4 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/DrdsToAutoTableCreationSqlUtilTest.java @@ -0,0 +1,110 @@ +package com.alibaba.polardbx.executor.utils; + +import com.alibaba.polardbx.common.model.Group; +import com.alibaba.polardbx.executor.TopologyExecutor; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.common.TopologyHandler; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.physicalbackfill.PhysicalBackfillManager; +import com.alibaba.polardbx.executor.repo.RepositoryHolder; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.executor.spi.ITopologyExecutor; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.config.table.ScaleOutPlanUtil; +import com.alibaba.polardbx.optimizer.context.AsyncDDLContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan; +import com.alibaba.polardbx.optimizer.core.planner.Planner; +import com.alibaba.polardbx.optimizer.core.rel.dal.LogicalShow; +import com.alibaba.polardbx.repo.mysql.handler.LogicalShowTablesMyHandler; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.sql.SqlShowTables; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class DrdsToAutoTableCreationSqlUtilTest { + + @Mock + private ExecutionContext executionContext; + + @Mock + private LogicalShowTablesMyHandler sourceRepo; + + @InjectMocks + private DrdsToAutoTableCreationSqlUtil util; + + @Before + public void setUp() { + when(executionContext.getSchemaName()).thenReturn("testSchema"); + } + + @Test + public void testGetTableNamesFromDatabase() { + // Prepare mock data + String[] tableData = {"table1", "table2"}; + ArrayResultCursor resultCursor = new ArrayResultCursor("TABLES"); + + resultCursor.addColumn("Tables_in_testschema", DataTypes.StringType, false); + resultCursor.addColumn("Table_type", DataTypes.StringType, false); + resultCursor.addColumn("Auto_partition", DataTypes.StringType, false); + resultCursor.addRow(new Object[] {tableData[0], "BASE TABLE", "YES"}); + resultCursor.addRow(new Object[] {tableData[1], "BASE TABLE", "YES"}); + resultCursor.addRow(new Object[] {"testview", "view", "YES"}); + + AsyncDDLContext asyncDDLContext = mock(AsyncDDLContext.class); + Planner planner = mock(Planner.class); + ExecutionPlan showTablesPlan = mock(ExecutionPlan.class); + LogicalShow logicalShowTables = mock(LogicalShow.class); + ExecutorContext executorContext = mock(ExecutorContext.class); + TopologyHandler topologyHandler = mock(TopologyHandler.class); + RepositoryHolder repositoryHolder = mock(RepositoryHolder.class); + IRepository iRepository = mock(IRepository.class); + + when(executionContext.copy()).thenReturn(executionContext); + when(executionContext.getAsyncDDLContext()).thenReturn(asyncDDLContext); + when(executorContext.getTopologyHandler()).thenReturn(topologyHandler); + when(topologyHandler.getRepositoryHolder()).thenReturn(repositoryHolder); + when(repositoryHolder.get(anyString())).thenReturn(iRepository); + + try (MockedStatic mockedPlanner = Mockito.mockStatic(Planner.class); + MockedStatic mockedExecutorContext = Mockito.mockStatic(ExecutorContext.class); + MockedConstruction mocked = Mockito.mockConstruction( + LogicalShowTablesMyHandler.class, + (mock, context) -> { + Mockito.when(mock.handle(any(RelNode.class), any(ExecutionContext.class))).thenReturn(resultCursor); + });) { + + mockedPlanner.when(() -> Planner.getInstance()).thenReturn(planner); + when(planner.getPlan(any(SqlShowTables.class), any(PlannerContext.class))).thenReturn(showTablesPlan); + when(showTablesPlan.getPlan()).thenReturn(logicalShowTables); + + mockedExecutorContext.when(() -> ExecutorContext.getContext(anyString())).thenReturn(executorContext); + + // Execute method under test + List result = util.getTableNamesFromDatabase("testSchema", executionContext); + + // Assert the result + assertEquals(Arrays.asList(tableData), result); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/ExecutilsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/ExecutilsTest.java new file mode 100644 index 000000000..4131f73c5 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/ExecutilsTest.java @@ -0,0 +1,158 @@ +package com.alibaba.polardbx.executor.utils; + +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.executor.mpp.deploy.Server; +import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; +import com.alibaba.polardbx.gms.node.AllNodes; +import com.alibaba.polardbx.gms.node.GmsNodeManager; +import com.alibaba.polardbx.gms.node.InternalNode; +import com.alibaba.polardbx.gms.node.InternalNodeManager; +import com.alibaba.polardbx.gms.node.MppScope; +import com.alibaba.polardbx.gms.node.NodeVersion; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.google.common.collect.ImmutableSet; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Set; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class ExecutilsTest { + + private AllNodes allNodes; + + @Before + public void setUp() { + InternalNode activeNode = mockNode(); + InternalNode otherActiveRowNode = mockNode(); + InternalNode otherActiveColumnarNode = mockNode(); + InternalNode inactiveNode = mockNode(); + InternalNode shuttingDownNode = mockNode(); + + Set activeNodes = ImmutableSet.of(activeNode); + Set otherActiveRowNodes = ImmutableSet.of(otherActiveRowNode); + Set otherActiveColumnarNodes = ImmutableSet.of(otherActiveColumnarNode); + Set inactiveNodes = ImmutableSet.of(inactiveNode); + Set shuttingDownNodes = ImmutableSet.of(shuttingDownNode); + + allNodes = + new AllNodes(activeNodes, otherActiveRowNodes, otherActiveColumnarNodes, inactiveNodes, shuttingDownNodes); + } + + private InternalNode mockNode() { + InternalNode node = new InternalNode("key", "cluster1", "inst1", "11.11.11.11", 1234, 12345, + NodeVersion.UNKNOWN, true, true, false, true); + return node; + } + + @Test + public void testMppScope() { + + try (final MockedStatic mockConfigDataMode = mockStatic(ConfigDataMode.class); + final MockedStatic mockServiceProvider = mockStatic(ServiceProvider.class); + ) { + ServiceProvider serviceProvider = mock(ServiceProvider.class); + when(ServiceProvider.getInstance()).thenReturn(serviceProvider); + Server server = mock(Server.class); + when(serviceProvider.getServer()).thenReturn(server); + + InternalNodeManager nodeManager = mock(InternalNodeManager.class); + when(server.getNodeManager()).thenReturn(nodeManager); + when(nodeManager.getAllNodes()).thenReturn(allNodes); + when(ConfigDataMode.isMasterMode()).thenReturn(false); + MppScope scope = ExecUtils.getMppSchedulerScope(false); + Assert.assertEquals(scope, MppScope.CURRENT); + + when(ConfigDataMode.isMasterMode()).thenReturn(true); + scope = ExecUtils.getMppSchedulerScope(false); + Assert.assertEquals(scope, MppScope.COLUMNAR); + + when(ConfigDataMode.isMasterMode()).thenReturn(true); + scope = ExecUtils.getMppSchedulerScope(true); + Assert.assertEquals(scope, MppScope.SLAVE); + } + } + + @Test + public void testAllowMppScope() { + + try (final MockedStatic mockConfigDataMode = mockStatic(ConfigDataMode.class); + final MockedStatic mockServiceProvider = mockStatic(ServiceProvider.class); + ) { + ServiceProvider serviceProvider = mock(ServiceProvider.class); + when(ServiceProvider.getInstance()).thenReturn(serviceProvider); + Server server = mock(Server.class); + when(serviceProvider.getServer()).thenReturn(server); + + InternalNodeManager nodeManager = mock(InternalNodeManager.class); + when(server.getNodeManager()).thenReturn(nodeManager); + when(nodeManager.getAllNodes()).thenReturn(allNodes); + when(ConfigDataMode.isMasterMode()).thenReturn(false); + + Assert.assertTrue(ExecUtils.allowMppMode(new ExecutionContext())); + + when(ConfigDataMode.isMasterMode()).thenReturn(true); + ExecutionContext context = new ExecutionContext(); + context.getExtraCmds().put("ENABLE_MASTER_MPP", true); + Assert.assertTrue(ExecUtils.allowMppMode(context)); + context.getExtraCmds().put("ENABLE_MASTER_MPP", false); + Assert.assertTrue(ExecUtils.allowMppMode(context)); + context.getExtraCmds().put("ENABLE_COLUMNAR_SCHEDULE", true); + Assert.assertTrue(ExecUtils.allowMppMode(context)); + + } + } + + @Test + public void testParallelism() { + try (final MockedStatic mockConfigDataMode = mockStatic(ConfigDataMode.class); + final MockedStatic mockServiceProvider = mockStatic(ServiceProvider.class); + ) { + ServiceProvider serviceProvider = mock(ServiceProvider.class); + when(ServiceProvider.getInstance()).thenReturn(serviceProvider); + Server server = mock(Server.class); + when(serviceProvider.getServer()).thenReturn(server); + + InternalNodeManager nodeManager = mock(InternalNodeManager.class); + when(server.getNodeManager()).thenReturn(nodeManager); + when(nodeManager.getAllNodes()).thenReturn(allNodes); + when(ConfigDataMode.isMasterMode()).thenReturn(false); + + HashMap hashMap = new HashMap<>(); + ParamManager paramManager = new ParamManager(hashMap); + hashMap.put("MPP_MAX_PARALLELISM", "1"); + Assert.assertEquals(1, ExecUtils.getMppMaxParallelism(paramManager, false)); + hashMap.put("MPP_MAX_PARALLELISM", "-1"); + hashMap.put("POLARDBX_PARALLELISM", "10"); + Assert.assertEquals(10, ExecUtils.getMppMaxParallelism(paramManager, false)); + } + } + + @Test + public void testCnCores() { + GmsNodeManager gmsNodeManager = mock(GmsNodeManager.class); + + try (final MockedStatic mockGmsNodeManagerStatic = mockStatic(GmsNodeManager.class); + final MockedStatic mockConfigDataMode = mockStatic(ConfigDataMode.class);) { + when(GmsNodeManager.getInstance()).thenReturn(gmsNodeManager); + + HashMap hashMap = new HashMap<>(); + ParamManager paramManager = new ParamManager(hashMap); + when(gmsNodeManager.getReadOnlyNodes()).thenReturn(new ArrayList<>()); + Assert.assertTrue(ExecUtils.getPolarDBXCNCores(paramManager, MppScope.SLAVE) > 0); + + when(gmsNodeManager.getColumnarReadOnlyNodes()).thenReturn(new ArrayList<>()); + Assert.assertTrue(ExecUtils.getPolarDBXCNCores(paramManager, MppScope.COLUMNAR) > 0); + } + + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/TestGroupingFetchLSN.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/GroupingFetchLSNTest.java similarity index 99% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/TestGroupingFetchLSN.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/GroupingFetchLSNTest.java index 7faa15356..b96a5c5f1 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/TestGroupingFetchLSN.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/GroupingFetchLSNTest.java @@ -14,7 +14,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; -public class TestGroupingFetchLSN { +public class GroupingFetchLSNTest { private long heartBeat = 0L; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/SchemaMetaUtilTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/SchemaMetaUtilTest.java new file mode 100644 index 000000000..ca755f462 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/SchemaMetaUtilTest.java @@ -0,0 +1,90 @@ +package com.alibaba.polardbx.executor.utils; + +import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.BaselineInfoAccessor; +import org.apache.calcite.avatica.Meta; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.MockitoAnnotations; + +import java.sql.Connection; + +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * @author fangwu + */ +public class SchemaMetaUtilTest { + @Mock + private Connection mockMetaDatabaseConnection; + + @Mock + private BaselineInfoAccessor mockBaselineInfoAccessor; + + @Before + public void setUp() { + MetaDbInstConfigManager.setConfigFromMetaDb(false); + MockitoAnnotations.openMocks(this); + } + + /* + * Design rationale: + * Simulate successful database connection and 'BaselineInfoAccessor' operation to ensure that when no exceptions are thrown, + * the method calls the 'deleteBySchema' method correctly. + */ + @Test + public void testDeleteBaselineInformationSuccess() { + // Preparation + String schemaName = "test_schema"; + MetaDbDataSource mockMetaDbDataSource = mock(MetaDbDataSource.class); + try (MockedStatic metaDbDataSourceMockedStatic = mockStatic(MetaDbDataSource.class)) { + metaDbDataSourceMockedStatic.when(MetaDbDataSource::getInstance).thenReturn(mockMetaDbDataSource); + when(mockMetaDbDataSource.getConnection()).thenReturn(mockMetaDatabaseConnection); + + doNothing().when(mockBaselineInfoAccessor).deleteBySchema(schemaName); + + // Execution + SchemaMetaUtil.deleteBaselineInformation(schemaName, mockBaselineInfoAccessor); + } + + // Verification + verify(mockBaselineInfoAccessor, times(1)).setConnection(mockMetaDatabaseConnection); + verify(mockBaselineInfoAccessor, times(1)).deleteBySchema(schemaName); + verify(mockBaselineInfoAccessor, times(1)).setConnection(null); + } + + /* + * Design rationale: + * When a database connection or 'BaselineInfoAccessor' operation throws an exception, ensure that the log recording is triggered correctly + * and resources are cleaned up. + */ + @Test + public void testDeleteBaselineInformationFailure() { + // Preparation + String schemaName = "error_schema"; + MetaDbDataSource mockMetaDbDataSource = mock(MetaDbDataSource.class); + + try (MockedStatic metaDbDataSourceMockedStatic = mockStatic(MetaDbDataSource.class)) { + metaDbDataSourceMockedStatic.when(MetaDbDataSource::getInstance).thenReturn(mockMetaDbDataSource); + when(mockMetaDbDataSource.getConnection()).thenThrow(new RuntimeException("Simulated DB error")); + doNothing().when(mockBaselineInfoAccessor).deleteBySchema(schemaName); + + // Execution & Verification + SchemaMetaUtil.deleteBaselineInformation(schemaName, mockBaselineInfoAccessor); + } + + // Verify log recording and resource cleanup + verify(mockBaselineInfoAccessor, never()).deleteBySchema( + schemaName); // Ensure it does not attempt to delete if connection fails + verify(mockBaselineInfoAccessor, times(1)).setConnection(null); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/transaction/TransactionUtilsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/transaction/TransactionUtilsTest.java new file mode 100644 index 000000000..0d8abd016 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/utils/transaction/TransactionUtilsTest.java @@ -0,0 +1,41 @@ +package com.alibaba.polardbx.executor.utils.transaction; + +import com.alibaba.polardbx.common.mock.MockStatus; +import com.google.common.collect.ImmutableList; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TransactionUtilsTest { + @Test + public void testUpdateLookupSet() { + MockStatus.setMock(true); + List>> results = new ArrayList<>(); + Map row0 = new HashMap<>(); + row0.put("TRANS_ID", 100001L); + row0.put("GROUP", "test_group0"); + row0.put("CONN_ID", 1024L); + row0.put("FRONTEND_CONN_ID", 10240L); + row0.put("START_TIME", System.currentTimeMillis()); + row0.put("SQL", "SELECT * FROM TB1 FOR UPDATE"); + row0.put("DDL", true); + Map row1 = new HashMap<>(); + row1.put("TRANS_ID", 100002L); + row1.put("GROUP", "test_group1"); + row1.put("CONN_ID", 1025L); + row1.put("FRONTEND_CONN_ID", 10250L); + row1.put("START_TIME", System.currentTimeMillis()); + row1.put("SQL", "SELECT * FROM TB1 FOR UPDATE"); + results.add(ImmutableList.of(row0, row1)); + results.add(null); + TrxLookupSet lookupSet = new TrxLookupSet(); + TransactionUtils.updateTrxLookupSet(results, lookupSet); + Assert.assertTrue(lookupSet.getTransaction(100001L).isDdl()); + Assert.assertFalse(lookupSet.getTransaction(100002L).isDdl()); + System.out.println(lookupSet); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/BaseVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/BaseVectorizedExpressionTest.java index 58fa2dad1..fd8bcc545 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/BaseVectorizedExpressionTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/BaseVectorizedExpressionTest.java @@ -66,7 +66,7 @@ import java.util.stream.Collectors; public class BaseVectorizedExpressionTest { - protected static final String APP_NAME = "obtest"; + protected static final String APP_NAME = "optest"; private static final String TABLE_DDL = "CREATE TABLE `t_table` (\n" + " `id` int(11) NOT NULL,\n" + " `test_double` DOUBLE DEFAULT NULL,\n" @@ -97,7 +97,7 @@ public class BaseVectorizedExpressionTest { private OptimizerContext optimizerContext; private TableMeta tableMeta; private Map tableData; - private ExecutionContext executionContext; + protected ExecutionContext executionContext; public static Block output(DataType dataType, Object... data) { BlockBuilder builder = BlockBuilders.create(dataType, new ExecutionContext()); diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/BenchmarkExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/BenchmarkExpressionTest.java new file mode 100644 index 000000000..c03481f11 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/BenchmarkExpressionTest.java @@ -0,0 +1,67 @@ +package com.alibaba.polardbx.executor.vectorized; + +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.atomic.AtomicInteger; + +public class BenchmarkExpressionTest extends BaseVectorizedExpressionTest { + + private final long totalCount = 1024L; + private final AtomicInteger counter = new AtomicInteger(0); + private final DataType outputDataType = DataTypes.LongType; + + @Test + public void testBenchmarkExpr() { + BenchmarkVectorizedExpression expr = mockBenchmarkExpr(); + MutableChunk chunk = new MutableChunk(new LongBlock(DataTypes.LongType, 1)); + + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals("Expect benchmark count equals", totalCount, counter.get()); + } + + @Test + public void testBenchmarkExprWithSelection() { + BenchmarkVectorizedExpression expr = mockBenchmarkExpr(); + int[] sel = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + MutableChunk chunk = new MutableChunk(new LongBlock(DataTypes.LongType, sel.length)); + chunk.setBatchSize(sel.length); + chunk.setSelection(sel); + chunk.setSelectionInUse(true); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals("Expect benchmark count equals", totalCount, counter.get()); + } + + private BenchmarkVectorizedExpression mockBenchmarkExpr() { + VectorizedExpression[] children = new VectorizedExpression[2]; + children[0] = new LiteralVectorizedExpression(DataTypes.LongType, totalCount, 0); + children[1] = new VectorizedExpression() { + @Override + public void eval(EvaluationContext ctx) { + counter.incrementAndGet(); + } + + @Override + public VectorizedExpression[] getChildren() { + return new VectorizedExpression[0]; + } + + @Override + public DataType getOutputDataType() { + return DataTypes.LongType; + } + + @Override + public int getOutputIndex() { + return 0; + } + }; + return new BenchmarkVectorizedExpression(outputDataType, 0, children); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/ExtractExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/ExtractExpressionTest.java new file mode 100644 index 000000000..b9f4de690 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/ExtractExpressionTest.java @@ -0,0 +1,310 @@ +package com.alibaba.polardbx.executor.vectorized; + +import com.alibaba.polardbx.common.utils.time.calculator.MySQLIntervalType; +import com.alibaba.polardbx.common.utils.time.core.MysqlDateTime; +import com.alibaba.polardbx.common.utils.time.core.TimeStorage; +import com.alibaba.polardbx.executor.chunk.DateBlock; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.ReferenceBlock; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Assert; +import org.junit.Test; + +import java.util.TimeZone; + +public class ExtractExpressionTest extends BaseVectorizedExpressionTest { + + private final int count = 1024; + private final DataType outputDataType = DataTypes.LongType; + + private final MysqlDateTime dateTime = new MysqlDateTime(2024, 4, 24, 21, 0, + 38, 4121); + + private int[] getSelection() { + int[] selection = new int[count / 2]; + for (int i = 0; i < selection.length; i++) { + selection[i] = i * 2; + } + return selection; + } + + private void setSelection(MutableChunk chunk) { + int[] sel = getSelection(); + chunk.setBatchSize(sel.length); + chunk.setSelection(sel); + chunk.setSelectionInUse(true); + } + + @Test + public void testExtractNull() { + testExtractNull(false); + } + + @Test + public void testExtractNullWithSel() { + testExtractNull(true); + } + + @Test + public void testExtractYear() { + testExtractYear(false); + } + + @Test + public void testExtractYearWithSel() { + testExtractYear(true); + } + + @Test + public void testExtractMonth() { + testExtractMonth(true); + } + + @Test + public void testExtractMonthWithSel() { + testExtractMonth(true); + } + + @Test + public void testExtractDay() { + testExtractDay(false); + } + + @Test + public void testExtractDayWithSel() { + testExtractDay(true); + } + + @Test + public void testExtractHour() { + testExtractHour(false); + } + + @Test + public void testExtractHourWithSel() { + testExtractHour(true); + } + + private void testExtractNull(boolean withSelection) { + ExtractVectorizedExpression expr = mockExtractExpr(null); + Assert.assertNull(expr.getIntervalType()); + ReferenceBlock refBlock = new ReferenceBlock(DataTypes.StringType, count); + DateBlock dateBlock = new DateBlock(count, TimeZone.getDefault()); + LongBlock outputBlock = new LongBlock(DataTypes.LongType, count); + MutableChunk chunk = new MutableChunk(refBlock, dateBlock, outputBlock); + if (withSelection) { + setSelection(chunk); + } + + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + if (withSelection) { + for (int i = 0; i < chunk.batchSize(); i++) { + int j = chunk.selection()[i]; + Assert.assertTrue(outputBlock.isNull(j)); + } + } else { + for (int i = 0; i < count; i++) { + Assert.assertTrue(outputBlock.isNull(i)); + } + } + } + + private void testExtractYear(boolean withSelection) { + ExtractVectorizedExpression expr = mockExtractExpr("Year"); + Assert.assertSame(expr.getIntervalType(), MySQLIntervalType.INTERVAL_YEAR); + ReferenceBlock refBlock = new ReferenceBlock(DataTypes.StringType, count); + DateBlock dateBlock = new DateBlock(count, TimeZone.getDefault()); + LongBlock outputBlock = new LongBlock(DataTypes.LongType, count); + MutableChunk chunk = new MutableChunk(refBlock, dateBlock, outputBlock); + if (withSelection) { + setSelection(chunk); + } + + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals(count, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < chunk.batchSize(); i++) { + int j = chunk.selection()[i]; + Assert.assertEquals(dateTime.getYear(), outputBlock.getLong(j)); + } + } else { + for (int i = 0; i < count; i++) { + Assert.assertEquals(dateTime.getYear(), outputBlock.getLong(i)); + } + } + } + + private void testExtractMonth(boolean withSelection) { + ExtractVectorizedExpression expr = mockExtractExpr("Month"); + Assert.assertSame(expr.getIntervalType(), MySQLIntervalType.INTERVAL_MONTH); + ReferenceBlock refBlock = new ReferenceBlock(DataTypes.StringType, count); + DateBlock dateBlock = new DateBlock(count, TimeZone.getDefault()); + LongBlock outputBlock = new LongBlock(DataTypes.LongType, count); + MutableChunk chunk = new MutableChunk(refBlock, dateBlock, outputBlock); + if (withSelection) { + setSelection(chunk); + } + + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals(count, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < chunk.batchSize(); i++) { + int j = chunk.selection()[i]; + Assert.assertEquals(dateTime.getMonth(), outputBlock.getLong(j)); + } + } else { + for (int i = 0; i < count; i++) { + Assert.assertEquals(dateTime.getMonth(), outputBlock.getLong(i)); + } + } + } + + private void testExtractDay(boolean withSelection) { + ExtractVectorizedExpression expr = mockExtractExpr("Day"); + Assert.assertSame(expr.getIntervalType(), MySQLIntervalType.INTERVAL_DAY); + ReferenceBlock refBlock = new ReferenceBlock(DataTypes.StringType, count); + DateBlock dateBlock = new DateBlock(count, TimeZone.getDefault()); + LongBlock outputBlock = new LongBlock(DataTypes.LongType, count); + MutableChunk chunk = new MutableChunk(refBlock, dateBlock, outputBlock); + if (withSelection) { + setSelection(chunk); + } + + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals(count, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < chunk.batchSize(); i++) { + int j = chunk.selection()[i]; + Assert.assertEquals(dateTime.getDay(), outputBlock.getLong(j)); + } + } else { + for (int i = 0; i < count; i++) { + Assert.assertEquals(dateTime.getDay(), outputBlock.getLong(i)); + } + } + } + + public void testExtractHour(boolean withSelection) { + // No fast path for extracting hour + ExtractVectorizedExpression expr = mockExtractExpr("Hour"); + Assert.assertSame(expr.getIntervalType(), MySQLIntervalType.INTERVAL_HOUR); + ReferenceBlock refBlock = new ReferenceBlock(DataTypes.StringType, count); + DateBlock dateBlock = new DateBlock(count, TimeZone.getDefault()); + LongBlock outputBlock = new LongBlock(DataTypes.LongType, count); + MutableChunk chunk = new MutableChunk(refBlock, dateBlock, outputBlock); + if (withSelection) { + setSelection(chunk); + } + + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals(count, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < chunk.batchSize(); i++) { + int j = chunk.selection()[i]; + Assert.assertEquals(dateTime.getHour(), outputBlock.getLong(j)); + } + } else { + for (int i = 0; i < count; i++) { + Assert.assertEquals(dateTime.getHour(), outputBlock.getLong(i)); + } + } + } + + private ExtractVectorizedExpression mockExtractExpr(String intervalType) { + VectorizedExpression[] children = new VectorizedExpression[2]; + children[0] = new LiteralVectorizedExpression(DataTypes.StringType, intervalType, 0); + children[1] = new VectorizedExpression() { + @Override + public void eval(EvaluationContext ctx) { + MutableChunk chunk = ctx.getPreAllocatedChunk(); + DateBlock outputBlock = (DateBlock) chunk.slotIn(getOutputIndex()); + + long[] longArray = outputBlock.getPacked(); + if (chunk.isSelectionInUse()) { + for (int i = 0; i < chunk.batchSize(); i++) { + int j = chunk.selection()[i]; + longArray[j] = TimeStorage.writeTimestamp(dateTime); + } + } else { + for (int i = 0; i < chunk.batchSize(); i++) { + longArray[i] = TimeStorage.writeTimestamp(dateTime); + } + } + } + + @Override + public VectorizedExpression[] getChildren() { + return new VectorizedExpression[0]; + } + + @Override + public DataType getOutputDataType() { + return DataTypes.DateType; + } + + @Override + public int getOutputIndex() { + return 1; + } + }; + return new ExtractVectorizedExpression(outputDataType, 2, children); + } + + @Test + public void testParseInterval() { + MysqlDateTime dateTime = new MysqlDateTime(2024, 4, 24, 21, 0, + 38, 4121); + + Assert.assertEquals(2024L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_YEAR)); + Assert.assertEquals(4L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_MONTH)); + Assert.assertEquals(24L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_DAY)); + Assert.assertEquals(21L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_HOUR)); + Assert.assertEquals(0L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_MINUTE)); + Assert.assertEquals(38L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_SECOND)); + Assert.assertEquals(2L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_QUARTER)); + Assert.assertEquals(16L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_WEEK)); + Assert.assertEquals(4L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_MICROSECOND)); + Assert.assertEquals(202404L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_YEAR_MONTH)); + Assert.assertEquals(2421L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_DAY_HOUR)); + Assert.assertEquals(242100L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_DAY_MINUTE)); + Assert.assertEquals(24210038L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_DAY_SECOND)); + Assert.assertEquals(2100L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_HOUR_MINUTE)); + Assert.assertEquals(210038L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_HOUR_SECOND)); + Assert.assertEquals(38L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_MINUTE_SECOND)); + Assert.assertEquals(24210038000004L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_DAY_MICROSECOND)); + Assert.assertEquals(210038000004L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_HOUR_MICROSECOND)); + Assert.assertEquals(38000004L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_MINUTE_MICROSECOND)); + Assert.assertEquals(38000004L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_SECOND_MICROSECOND)); + + // INTERVAL_LAST is not implemented + Assert.assertEquals(0L, + ExtractVectorizedExpression.doParseInterval(dateTime, 1, MySQLIntervalType.INTERVAL_LAST)); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/InValuesExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/InValuesExpressionTest.java new file mode 100644 index 000000000..35b8707e7 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/InValuesExpressionTest.java @@ -0,0 +1,52 @@ +package com.alibaba.polardbx.executor.vectorized; + +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Assert; +import org.junit.Test; + +public class InValuesExpressionTest { + + @Test + public void testDiffType() { + InValuesVectorizedExpression.InValueSet longValueSet = + new InValuesVectorizedExpression.InValueSet(DataTypes.LongType, 10); + + longValueSet.add(1L); + longValueSet.add(new Long(2)); + try { + longValueSet.add(3); + Assert.fail("Expect failed with different type"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("cannot be cast")); + } + Assert.assertTrue(longValueSet.contains(1L)); + Assert.assertTrue(longValueSet.contains(new Integer(1))); + Assert.assertTrue(longValueSet.contains("1")); + Assert.assertTrue(longValueSet.contains(2)); + Assert.assertTrue(longValueSet.contains(new Long(2))); + Assert.assertTrue(longValueSet.contains(2L)); + Assert.assertFalse(longValueSet.contains(new Integer(3))); + Assert.assertFalse(longValueSet.contains(new Long(3))); + + InValuesVectorizedExpression.InValueSet intValueSet = + new InValuesVectorizedExpression.InValueSet(DataTypes.IntegerType, 10); + intValueSet.add(-1); + intValueSet.add(new Integer(-2)); + try { + intValueSet.add(3L); + Assert.fail("Expect failed with different type"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("cannot be cast")); + } + Assert.assertTrue(intValueSet.contains(-1)); + Assert.assertTrue(intValueSet.contains(new Integer(-1))); + Assert.assertTrue(intValueSet.contains("-1")); + Assert.assertTrue(intValueSet.contains(-2)); + Assert.assertTrue(intValueSet.contains(new Long(-2))); + Assert.assertTrue(intValueSet.contains(-2L)); + Assert.assertFalse(intValueSet.contains(new Integer(3))); + Assert.assertFalse(intValueSet.contains(new Long(3))); + Assert.assertFalse(intValueSet.contains(Integer.MAX_VALUE + 1L)); + + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/SubStrExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/SubStrExpressionTest.java new file mode 100644 index 000000000..8dddd8734 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/SubStrExpressionTest.java @@ -0,0 +1,352 @@ +package com.alibaba.polardbx.executor.vectorized; + +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.ObjectBlockBuilder; +import com.alibaba.polardbx.executor.chunk.ReferenceBlock; +import com.alibaba.polardbx.executor.chunk.SliceBlock; +import com.alibaba.polardbx.executor.chunk.SliceBlockBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.datatype.SliceType; +import io.airlift.slice.Slice; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(Parameterized.class) +public class SubStrExpressionTest extends BaseVectorizedExpressionTest { + + private final int count = 1024; + /** + * start from index 1 + */ + private final int start = 2; + private final int length = 5; + private final DataType outputDataType = DataTypes.LongType; + private final boolean withSelection; + private final int[] sel; + private List strList = new ArrayList<>(count); + SliceBlockBuilder inputBlockBuilder = new SliceBlockBuilder(new SliceType(), count / 4, + new ExecutionContext(), false); + + public SubStrExpressionTest(boolean withSelection) { + this.withSelection = withSelection; + if (withSelection) { + this.sel = new int[count / 2]; + for (int i = 0; i < this.sel.length; i++) { + this.sel[i] = i * 2 + 1; + } + } else { + this.sel = null; + } + StringBuilder stringBuilder = new StringBuilder(32); + for (int i = 0; i < count; i++) { + if (i % 50 == 0) { + stringBuilder.append(((char) 'a' + i % 26)).append(i); + } + String s = stringBuilder.toString(); + strList.add(s); + inputBlockBuilder.writeString(s); + } + } + + @Parameterized.Parameters(name = "sel={0}") + public static List generateParameters() { + List list = new ArrayList<>(); + list.add(new Object[] {true}); + list.add(new Object[] {false}); + return list; + } + + @Test + public void testSubStrExprSlice() { + SubStrVarcharVectorizedExpression expr = mockBenchmarkExpr(); + SliceBlock inputBlock = (SliceBlock) inputBlockBuilder.build(); + ReferenceBlock outputBlock = new ReferenceBlock(DataTypes.StringType, count); + + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + if (withSelection) { + chunk.setBatchSize(sel.length); + chunk.setSelection(sel); + chunk.setSelectionInUse(true); + } + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals(count, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + String s = strList.get(j); + String subStr; + if (start - 1 + length >= s.length()) { + subStr = s.substring(start - 1); + } else { + subStr = s.substring(start - 1, start - 1 + length); + } + Assert.assertEquals(subStr, ((Slice) outputBlock.getObject(j)).toStringUtf8()); + } + } else { + for (int i = 0; i < count; i++) { + String s = strList.get(i); + String subStr; + if (start - 1 + length >= s.length()) { + subStr = s.substring(start - 1); + } else { + subStr = s.substring(start - 1, start - 1 + length); + } + Assert.assertEquals(subStr, ((Slice) outputBlock.getObject(i)).toStringUtf8()); + } + } + } + + @Test + public void testSubStrExprReference() { + SubStrVarcharVectorizedExpression expr = mockBenchmarkExpr(); + ObjectBlockBuilder refBlockBuilder = new ObjectBlockBuilder(count); + for (int i = 0; i < count; i++) { + refBlockBuilder.writeObject(inputBlockBuilder.getObject(i)); + } + ReferenceBlock inputBlock = (ReferenceBlock) refBlockBuilder.build(); + ReferenceBlock outputBlock = new ReferenceBlock(DataTypes.StringType, count); + + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + if (withSelection) { + chunk.setBatchSize(sel.length); + chunk.setSelection(sel); + chunk.setSelectionInUse(true); + } + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals(count, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + String s = strList.get(j); + String subStr; + if (start - 1 + length >= s.length()) { + subStr = s.substring(start - 1); + } else { + subStr = s.substring(start - 1, start - 1 + length); + } + Assert.assertEquals(subStr, ((Slice) outputBlock.getObject(j)).toStringUtf8()); + } + } else { + for (int i = 0; i < count; i++) { + String s = strList.get(i); + String subStr; + if (start - 1 + length >= s.length()) { + subStr = s.substring(start - 1); + } else { + subStr = s.substring(start - 1, start - 1 + length); + } + Assert.assertEquals(subStr, ((Slice) outputBlock.getObject(i)).toStringUtf8()); + } + } + } + + @Test + public void testSubStrExprWithNullArg() { + SubStrVarcharVectorizedExpression expr = mockBenchmarkExprWithNullArg(); + SliceBlock inputBlock = (SliceBlock) inputBlockBuilder.build(); + ReferenceBlock outputBlock = new ReferenceBlock(DataTypes.StringType, count); + + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + if (withSelection) { + chunk.setBatchSize(sel.length); + chunk.setSelection(sel); + chunk.setSelectionInUse(true); + } + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals(count, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertNull(outputBlock.getObject(j)); + } + } else { + for (int i = 0; i < count; i++) { + Assert.assertNull(outputBlock.getObject(i)); + } + } + } + + /** + * if length is negative, the result is "" rather than NULL + */ + @Test + public void testSubStrExprNegLength() { + SubStrVarcharVectorizedExpression expr = mockBenchmarkExpr(start, -length); + SliceBlock inputBlock = (SliceBlock) inputBlockBuilder.build(); + ReferenceBlock outputBlock = new ReferenceBlock(DataTypes.StringType, count); + + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + if (withSelection) { + chunk.setBatchSize(sel.length); + chunk.setSelection(sel); + chunk.setSelectionInUse(true); + } + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals(count, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals(0, ((Slice) outputBlock.getObject(j)).length()); + } + } else { + for (int i = 0; i < count; i++) { + Assert.assertEquals(0, ((Slice) outputBlock.getObject(i)).length()); + } + } + } + + /** + * if start is negative, the substring result begins from the end + */ + @Test + public void testSubStrExprNegStart() { + SubStrVarcharVectorizedExpression expr = mockBenchmarkExpr(-start, length); + SliceBlock inputBlock = (SliceBlock) inputBlockBuilder.build(); + ReferenceBlock outputBlock = new ReferenceBlock(DataTypes.StringType, count); + + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + if (withSelection) { + chunk.setBatchSize(sel.length); + chunk.setSelection(sel); + chunk.setSelectionInUse(true); + } + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals(count, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + String s = strList.get(j); + int startIndex = s.length() - start + 1; + String subStr; + if (startIndex < 0) { + subStr = ""; + } else { + if (startIndex - 1 + length >= s.length()) { + subStr = s.substring(startIndex - 1); + } else { + subStr = s.substring(startIndex - 1, startIndex - 1 + length); + } + } + Assert.assertEquals(subStr, ((Slice) outputBlock.getObject(j)).toStringUtf8()); + } + } else { + for (int i = 0; i < count; i++) { + String s = strList.get(i); + int startIndex = s.length() - start + 1; + String subStr; + if (startIndex <= 0) { + subStr = ""; + } else { + if (startIndex - 1 + length >= s.length()) { + subStr = s.substring(startIndex - 1); + } else { + subStr = s.substring(startIndex - 1, startIndex - 1 + length); + } + } + Assert.assertEquals(subStr, ((Slice) outputBlock.getObject(i)).toStringUtf8()); + } + } + } + + /** + * if start is zero, the result is "" rather than NULL + */ + @Test + public void testSubStrExprZeroStart() { + SubStrVarcharVectorizedExpression expr = mockBenchmarkExpr(0, length); + SliceBlock inputBlock = (SliceBlock) inputBlockBuilder.build(); + ReferenceBlock outputBlock = new ReferenceBlock(DataTypes.StringType, count); + + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + if (withSelection) { + chunk.setBatchSize(sel.length); + chunk.setSelection(sel); + chunk.setSelectionInUse(true); + } + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + Assert.assertEquals(count, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals(0, ((Slice) outputBlock.getObject(j)).length()); + } + } else { + for (int i = 0; i < count; i++) { + Assert.assertEquals(0, ((Slice) outputBlock.getObject(i)).length()); + } + } + } + + private SubStrVarcharVectorizedExpression mockBenchmarkExpr() { + return mockBenchmarkExpr(start, length); + } + + private SubStrVarcharVectorizedExpression mockBenchmarkExpr(int start, int length) { + VectorizedExpression[] children = new VectorizedExpression[3]; + children[1] = new LiteralVectorizedExpression(DataTypes.LongType, start, 0); + children[2] = new LiteralVectorizedExpression(DataTypes.LongType, length, 0); + children[0] = new VectorizedExpression() { + @Override + public void eval(EvaluationContext ctx) { + + } + + @Override + public VectorizedExpression[] getChildren() { + return new VectorizedExpression[0]; + } + + @Override + public DataType getOutputDataType() { + return DataTypes.StringType; + } + + @Override + public int getOutputIndex() { + return 0; + } + }; + return new SubStrVarcharVectorizedExpression(outputDataType, 1, children); + } + + private SubStrVarcharVectorizedExpression mockBenchmarkExprWithNullArg() { + VectorizedExpression[] children = new VectorizedExpression[3]; + children[1] = new LiteralVectorizedExpression(DataTypes.LongType, null, 0); + children[2] = new LiteralVectorizedExpression(DataTypes.LongType, null, 0); + children[0] = new VectorizedExpression() { + @Override + public void eval(EvaluationContext ctx) { + + } + + @Override + public VectorizedExpression[] getChildren() { + return new VectorizedExpression[0]; + } + + @Override + public DataType getOutputDataType() { + return DataTypes.StringType; + } + + @Override + public int getOutputIndex() { + return 0; + } + }; + return new SubStrVarcharVectorizedExpression(outputDataType, 1, children); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/VectorizedExpressionRegistryTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/VectorizedExpressionRegistryTest.java index 371337f37..132ae0809 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/VectorizedExpressionRegistryTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/VectorizedExpressionRegistryTest.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.executor.vectorized; +import com.alibaba.polardbx.common.utils.Assert; import com.alibaba.polardbx.executor.vectorized.metadata.ArgumentInfo; import com.alibaba.polardbx.executor.vectorized.metadata.ArgumentKind; import com.alibaba.polardbx.executor.vectorized.metadata.ExpressionConstructor; @@ -26,6 +27,7 @@ import java.util.Optional; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class VectorizedExpressionRegistryTest { @@ -42,4 +44,43 @@ public void testGetBuilderConstructor() { TestVectorizedExpression.class, constructor.get().getDeclaringClass()); assertTrue(constructor.get().build(0, new VectorizedExpression[0]) instanceof TestVectorizedExpression); } + + @Test + public void testNotExistSignature() { + ArgumentInfo arg1 = new ArgumentInfo(DataTypes.LongType, ArgumentKind.Const); + ArgumentInfo arg2 = new ArgumentInfo(DataTypes.IntegerType, ArgumentKind.Variable); + ExpressionSignature sig = new ExpressionSignature("expr_test_not_exist", new ArgumentInfo[] {arg1, arg2}); + + Optional> constructor = + VectorizedExpressionRegistry.builderConstructorOf(sig); + assertFalse("Construct of " + sig + " should not exist.", constructor.isPresent()); + try { + constructor.get().build(0, new VectorizedExpression[0]); + Assert.fail("Expect failed when signature does not exist"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("No value")); + } + } + + @Test + public void testNotExistClass() { + try { + ExpressionConstructor.of(FailTestVectorizedExpression.class); + Assert.fail("Expect failed when class construct does not exist"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Failed to get builder constructor")); + Assert.assertTrue(e.getMessage().contains(FailTestVectorizedExpression.class.getName())); + } + } + +} + +class FailTestVectorizedExpression extends AbstractVectorizedExpression { + private FailTestVectorizedExpression() { + super(DataTypes.BlobType, 0, null); + } + + @Override + public void eval(EvaluationContext ctx) { + } } \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/VectorizedUtilsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/VectorizedUtilsTest.java new file mode 100644 index 000000000..3cc2b8bee --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/VectorizedUtilsTest.java @@ -0,0 +1,271 @@ +package com.alibaba.polardbx.executor.vectorized; + +import com.alibaba.polardbx.executor.chunk.BlockBuilder; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.LongBlockBuilder; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(Parameterized.class) +public class VectorizedUtilsTest { + + private final int count = 100; + private final int[] sel; + private final boolean withSelection; + + public VectorizedUtilsTest(boolean withSelection) { + this.withSelection = withSelection; + if (withSelection) { + this.sel = new int[count / 2]; + for (int i = 0; i < this.sel.length; i++) { + this.sel[i] = i * 2 + 1; + } + } else { + this.sel = null; + } + } + + @Parameterized.Parameters(name = "sel={0}") + public static List generateParameters() { + List list = new ArrayList<>(); + list.add(new Object[] {true}); + list.add(new Object[] {false}); + return list; + } + + @Test + public void testPropagateNull() { + RandomAccessBlock leftBlock = buildAllValuesBlock(); + RandomAccessBlock rightBlock = buildAllValuesBlock(); + RandomAccessBlock outputBlock = newOutputBlock(count); + if (!withSelection) { + VectorizedExpressionUtils.propagateNullState(outputBlock, leftBlock, rightBlock, + count, null, false); + for (int i = 0; i < count; i++) { + Assert.assertFalse(((LongBlock) outputBlock).isNull(i)); + } + } else { + VectorizedExpressionUtils.propagateNullState(outputBlock, leftBlock, rightBlock, + sel.length, sel, true); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertFalse(((LongBlock) outputBlock).isNull(j)); + } + } + + // expect all nulls after merge + leftBlock = buildAllValuesBlock(); + rightBlock = buildAllNullBlock(); + outputBlock = newOutputBlock(count); + VectorizedExpressionUtils.propagateNullState(outputBlock, leftBlock, rightBlock, + count, null, false); + if (!withSelection) { + VectorizedExpressionUtils.propagateNullState(outputBlock, leftBlock, rightBlock, + count, null, false); + for (int i = 0; i < count; i++) { + Assert.assertTrue(((LongBlock) outputBlock).isNull(i)); + } + } else { + VectorizedExpressionUtils.propagateNullState(outputBlock, leftBlock, rightBlock, + sel.length, sel, true); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertTrue(((LongBlock) outputBlock).isNull(j)); + } + } + + // expect all nulls after merge + leftBlock = buildAllNullBlock(); + rightBlock = buildAllValuesBlock(); + outputBlock = newOutputBlock(count); + VectorizedExpressionUtils.propagateNullState(outputBlock, leftBlock, rightBlock, + count, null, false); + if (!withSelection) { + VectorizedExpressionUtils.propagateNullState(outputBlock, leftBlock, rightBlock, + count, null, false); + for (int i = 0; i < count; i++) { + Assert.assertTrue(((LongBlock) outputBlock).isNull(i)); + } + } else { + VectorizedExpressionUtils.propagateNullState(outputBlock, leftBlock, rightBlock, + sel.length, sel, true); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertTrue(((LongBlock) outputBlock).isNull(j)); + } + } + + // expect all nulls after merge + leftBlock = buildHalfNullBlock(true); + rightBlock = buildHalfNullBlock(false); + outputBlock = newOutputBlock(count); + VectorizedExpressionUtils.propagateNullState(outputBlock, leftBlock, rightBlock, + count, null, false); + if (!withSelection) { + VectorizedExpressionUtils.propagateNullState(outputBlock, leftBlock, rightBlock, + count, null, false); + for (int i = 0; i < count; i++) { + Assert.assertTrue(((LongBlock) outputBlock).isNull(i)); + } + } else { + VectorizedExpressionUtils.propagateNullState(outputBlock, leftBlock, rightBlock, + sel.length, sel, true); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertTrue(((LongBlock) outputBlock).isNull(j)); + } + } + } + + @Test + public void testHandleLongNull() { + LongBlock longBlock = (LongBlock) buildAllValuesBlock(); + if (!withSelection) { + VectorizedExpressionUtils.handleLongNullValue(longBlock, count, null, false); + for (int i = 0; i < count; i++) { + Assert.assertFalse(longBlock.isNull(i)); + } + } else { + VectorizedExpressionUtils.handleLongNullValue(longBlock, sel.length, sel, true); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertFalse(longBlock.isNull(j)); + } + } + + longBlock = (LongBlock) buildHalfNullBlock(true); + if (!withSelection) { + VectorizedExpressionUtils.handleLongNullValue(longBlock, count, null, false); + for (int i = 0; i < count; i++) { + Assert.assertEquals("Failed at position: " + i, i % 2 == 0, longBlock.isNull(i)); + } + } else { + VectorizedExpressionUtils.handleLongNullValue(longBlock, sel.length, sel, true); + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals(j % 2 == 0, longBlock.isNull(j)); + } + } + } + + @Test + public void testSelectionIntersect() { + int sel2Count = count / 2; + int offset = sel2Count / 2; + int[] sel2 = new int[sel2Count]; + for (int i = 0; i < sel2Count; i++) { + if (i < offset) { + sel2[i] = i * 2; + } else { + // fill the right half with matched select positions + sel2[i] = i * 2 + 1; + } + } + int[] intersection = new int[Math.min(count, sel2Count)]; + + if (!withSelection) { + try { + VectorizedExpressionUtils.intersect(sel, count, sel2, sel2Count, intersection); + Assert.fail("Expect failed with null selection"); + } catch (Exception e) { + Assert.assertTrue(e instanceof IllegalArgumentException); + } + try { + VectorizedExpressionUtils.intersect(sel2, sel2Count, sel, count, intersection); + Assert.fail("Expect failed with null selection"); + } catch (Exception e) { + Assert.assertTrue(e instanceof IllegalArgumentException); + } + return; + } + + int intersectedSize = VectorizedExpressionUtils.intersect(sel, count, sel2, sel2Count, intersection); + Assert.assertEquals(intersectedSize, sel2Count - offset); + for (int i = 0; i < intersectedSize; i++) { + Assert.assertEquals(sel2[i + offset], intersection[i]); + } + } + + @Test + public void testConstantFinder() { + if (withSelection) { + testConstantFinderOverflow(); + } else { + testConstantFinderNotOverflow(); + } + } + + private void testConstantFinderOverflow() { + final int MAX_LEVEL = 1 << 10; + VectorizedExpression[] children = new VectorizedExpression[1]; + VectorizedExpression vectorizedExpression = new AndVectorizedExpression(0, children); + for (int i = 0; i < MAX_LEVEL; i++) { + VectorizedExpression[] subChildren = new VectorizedExpression[1]; + VectorizedExpression expr = new AndVectorizedExpression(0, subChildren); + children[0] = expr; + children = subChildren; + } + children[0] = null; + boolean isConstant = VectorizedExpressionUtils.isConstantExpression(vectorizedExpression); + Assert.assertFalse("Expect false when overflow max level", isConstant); + } + + private void testConstantFinderNotOverflow() { + final int level = 10; + VectorizedExpression[] children = new VectorizedExpression[1]; + VectorizedExpression vectorizedExpression = new AndVectorizedExpression(0, children); + for (int i = 0; i < level; i++) { + VectorizedExpression[] subChildren = new VectorizedExpression[1]; + VectorizedExpression expr = new AndVectorizedExpression(0, subChildren); + children[0] = expr; + children = subChildren; + } + children[0] = new LiteralVectorizedExpression(DataTypes.LongType, 100, 0); + boolean isConstant = VectorizedExpressionUtils.isConstantExpression(vectorizedExpression); + Assert.assertTrue("Should be constant", isConstant); + } + + private RandomAccessBlock newOutputBlock(int count) { + return new LongBlock(DataTypes.LongType, count); + } + + private RandomAccessBlock buildAllNullBlock() { + BlockBuilder builder = new LongBlockBuilder(count); + for (int i = 0; i < count; i++) { + builder.appendNull(); + } + return (RandomAccessBlock) builder.build(); + } + + private RandomAccessBlock buildAllValuesBlock() { + BlockBuilder builder = new LongBlockBuilder(count); + for (int i = 0; i < count; i++) { + builder.writeLong(i); + } + return (RandomAccessBlock) builder.build(); + } + + private RandomAccessBlock buildHalfNullBlock(boolean firstPart) { + BlockBuilder builder = new LongBlockBuilder(count); + if (firstPart) { + for (int i = 0; i < count / 2; i++) { + builder.appendNull(); + builder.writeLong(i); + } + } else { + for (int i = 0; i < count / 2; i++) { + builder.writeLong(i); + builder.appendNull(); + } + } + + return (RandomAccessBlock) builder.build(); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/build/ExpressionConstFoldTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/build/ExpressionConstFoldTest.java new file mode 100644 index 000000000..b1398b33e --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/build/ExpressionConstFoldTest.java @@ -0,0 +1,147 @@ +package com.alibaba.polardbx.executor.vectorized.build; + +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; +import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; +import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.datatype.DateTimeType; +import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexCall; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.type.SqlTypeName; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigDecimal; +import java.util.List; + +public class ExpressionConstFoldTest { + private final static RelDataTypeFactory TYPE_FACTORY = + new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); + private final static RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY); + private ExecutionContext context = new ExecutionContext(); + + @Test + public void test1() { + // 99 + 1 + RexCall needFold = (RexCall) REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), + TddlOperatorTable.PLUS, + ImmutableList.of( + REX_BUILDER.makeBigIntLiteral(99L), + REX_BUILDER.makeBigIntLiteral(1L) + )); + + // int_col = (99 + 1) + RexCall call = (RexCall) REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), + TddlOperatorTable.EQUALS, + ImmutableList.of( + REX_BUILDER.makeInputRef(TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER), 0), + needFold + )); + + doTest(call, ImmutableList.of(DataTypes.IntegerType), + "EQIntegerColLongConstVectorizedExpression", DataTypes.LongType); + } + + @Test + public void test2() { + // 99.0 + 1 + RexCall needFold = (RexCall) REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.DECIMAL), + TddlOperatorTable.PLUS, + ImmutableList.of( + REX_BUILDER.makeExactLiteral(new BigDecimal("99.0")), + REX_BUILDER.makeBigIntLiteral(1L) + )); + + // decimal = (99.0 + 1) + RexCall call = (RexCall) REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), + TddlOperatorTable.EQUALS, + ImmutableList.of( + REX_BUILDER.makeInputRef(TYPE_FACTORY.createSqlType(SqlTypeName.DECIMAL, 15, 2), 0), + needFold + )); + + doTest(call, ImmutableList.of(new DecimalType(15, 2)), + "EQDecimalColDecimalConstVectorizedExpression", DataTypes.LongType); + } + + @Test + public void test3() { + + RexCall needFold = (RexCall) REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.CHAR), + TddlOperatorTable.CONCAT, + ImmutableList.of( + REX_BUILDER.makeLiteral("2011-11-11 11:11:11") + ) + ); + + // datetime_col = concat("2011-11-11 11:11:11") + RexCall call = (RexCall) REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), + TddlOperatorTable.EQUALS, + ImmutableList.of( + REX_BUILDER.makeInputRef(TYPE_FACTORY.createSqlType(SqlTypeName.DATETIME, 6), 0), + needFold + )); + + doTest(call, ImmutableList.of(new DateTimeType(6)), + "EQDatetimeColCharConstVectorizedExpression", DataTypes.LongType); + } + + @Test + public void testNull1() { + // 1 + null + RexCall needFold = (RexCall) REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), + TddlOperatorTable.PLUS, + ImmutableList.of( + REX_BUILDER.makeBigIntLiteral(1L), + REX_BUILDER.makeNullLiteral(TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT)) + ) + ); + + // integer_col < 1 + null + RexCall call = (RexCall) REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), + TddlOperatorTable.LESS_THAN, + ImmutableList.of( + REX_BUILDER.makeInputRef(TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER), 0), + needFold + )); + + doTest(call, ImmutableList.of(DataTypes.IntegerType), + "LTIntegerColLongConstVectorizedExpression", DataTypes.LongType); + } + + private void doTest(RexCall call, List> inputTypes, + String expectedClass, DataType expectedType) { + + RexNode root = VectorizedExpressionBuilder.rewriteRoot(call, true); + + InputRefTypeChecker inputRefTypeChecker = new InputRefTypeChecker(inputTypes); + root = root.accept(inputRefTypeChecker); + + Rex2VectorizedExpressionVisitor converter = + new Rex2VectorizedExpressionVisitor(context, inputTypes.size()); + VectorizedExpression condition = root.accept(converter); + List> filterOutputTypes = converter.getOutputDataTypes(); + + Assert.assertTrue(String.format("expected class = %s, actual class = %s", expectedClass, condition.getClass()), + condition.getClass().toString().contains(expectedClass)); + Assert.assertTrue(String.format("expected type = %s, actual type = %s", expectedType, + filterOutputTypes.get(filterOutputTypes.size() - 1)), + DataTypeUtil.equalsSemantically(expectedType, filterOutputTypes.get(filterOutputTypes.size() - 1))); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/build/ExpressionRewriterTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/build/ExpressionRewriterTest.java new file mode 100644 index 000000000..d275ce7bd --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/build/ExpressionRewriterTest.java @@ -0,0 +1,192 @@ +package com.alibaba.polardbx.executor.vectorized.build; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.jdbc.Parameters; +import com.alibaba.polardbx.common.jdbc.RawString; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rel.type.RelDataTypeSystem; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexCall; +import org.apache.calcite.rex.RexLiteral; +import org.apache.calcite.sql.fun.SqlTrimFunction; +import org.apache.calcite.sql.type.SqlTypeFactoryImpl; +import org.apache.calcite.sql.type.SqlTypeName; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +public class ExpressionRewriterTest { + + private final RelDataTypeFactory typeFactory = new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + private final RexBuilder rexBuilder = new RexBuilder(typeFactory); + private ExpressionRewriter rewriter; + private ExecutionContext context; + + @Before + public void before() { + context = new ExecutionContext(); + context.getParamManager().getProps().put("ENABLE_EXPRESSION_VECTORIZATION", "true"); + context.getParamManager().getProps().put("ENABLE_COMMON_SUB_EXPRESSION_TREE_ELIMINATE", "true"); + this.rewriter = new ExpressionRewriter(context); + } + + @Test + public void testRewriteTrim() { + RelDataType varcharType = typeFactory.createSqlType(SqlTypeName.VARCHAR); + RexCall exprCall = (RexCall) rexBuilder.makeCall(TddlOperatorTable.TRIM, + rexBuilder.makeDynamicParam(varcharType, 0), + rexBuilder.makeDynamicParam(varcharType, 1), + rexBuilder.makeDynamicParam(varcharType, 2)); + RexCall rewrite = rewriter.rewrite(exprCall, false); + Assert.assertTrue(rewrite.op instanceof SqlTrimFunction); + } + + @Test + public void testRewriteDataAdd() { + RelDataType dateType = typeFactory.createSqlType(SqlTypeName.DATE); + RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER); + RexCall exprCall = (RexCall) rexBuilder.makeCall(TddlOperatorTable.DATE_ADD, + rexBuilder.makeDynamicParam(dateType, 0), + rexBuilder.makeDynamicParam(intType, 1)); + RexCall rewrite = rewriter.rewrite(exprCall, false); + // flat the operands tree: + // + // DATE_ADD DATE_ADD + // / \ / | \ + // TIME DAY VALUE => TIME DAY VALUE INTERVAL_DAY + // + Assert.assertEquals(3, rewrite.operands.size()); + } + + @Test + public void testRewriteDataAddInterval() { + RelDataType dateType = typeFactory.createSqlType(SqlTypeName.DATE); + RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER); + RexLiteral timeUnit = rexBuilder.makeLiteral("DAY"); + RexCall intervalCall = (RexCall) rexBuilder.makeCall(TddlOperatorTable.INTERVAL_PRIMARY, + rexBuilder.makeDynamicParam(intType, 1), timeUnit); + RexCall exprCall = (RexCall) rexBuilder.makeCall(TddlOperatorTable.DATE_ADD, + rexBuilder.makeDynamicParam(dateType, 0), + intervalCall); + RexCall rewrite = rewriter.rewrite(exprCall, false); + // flat the operands tree: + // + // DATE_ADD DATE_ADD + // / \ / | \ + // TIME INTERVAL_PRIMARY => TIME VALUE TIME_UNIT + // / \ + // VALUE TIME_UNIT + Assert.assertEquals(3, rewrite.operands.size()); + } + + @Test + public void testRewriteOr() { + Parameters params = new Parameters(); + params.getCurrentParameter().put(1, new ParameterContext(ParameterMethod.setLong, new Object[] {0, 1})); + params.getCurrentParameter().put(2, new ParameterContext(ParameterMethod.setLong, new Object[] {1, 2})); + params.getCurrentParameter().put(3, new ParameterContext(ParameterMethod.setLong, new Object[] {2, 3})); + params.getCurrentParameter().put(4, new ParameterContext(ParameterMethod.setLong, new Object[] {3, 4})); + context.setParams(params); + + RelDataType boolType = typeFactory.createSqlType(SqlTypeName.BOOLEAN); + RexCall rexCall1 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.OR, + rexBuilder.makeDynamicParam(boolType, 0), + rexBuilder.makeDynamicParam(boolType, 1)); + RexCall rewrite1 = rewriter.rewrite(rexCall1, false); + Assert.assertEquals(2, rewrite1.operands.size()); + + RexCall andCall1 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.AND, + rexBuilder.makeDynamicParam(boolType, 0), + rexBuilder.makeDynamicParam(boolType, 1)); + RexCall andCall2 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.AND, + rexBuilder.makeDynamicParam(boolType, 2), + rexBuilder.makeDynamicParam(boolType, 3)); + RexCall rexCall2 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.OR, + andCall1, andCall2); + RexCall rewrite2 = rewriter.rewrite(rexCall2, false); + Assert.assertEquals(2, rewrite2.operands.size()); + } + + @Test + public void testRewriteAnd() { + Parameters params = new Parameters(); + params.getCurrentParameter().put(1, new ParameterContext(ParameterMethod.setLong, new Object[] {0, 1})); + params.getCurrentParameter().put(2, new ParameterContext(ParameterMethod.setLong, new Object[] {1, 2})); + params.getCurrentParameter().put(3, new ParameterContext(ParameterMethod.setLong, new Object[] {2, 3})); + params.getCurrentParameter().put(4, new ParameterContext(ParameterMethod.setLong, new Object[] {3, 4})); + context.setParams(params); + + RelDataType boolType = typeFactory.createSqlType(SqlTypeName.BOOLEAN); + RexCall rexCall1 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.AND, + rexBuilder.makeDynamicParam(boolType, 0), + rexBuilder.makeDynamicParam(boolType, 1)); + RexCall rewrite1 = rewriter.rewrite(rexCall1, false); + Assert.assertEquals(2, rewrite1.operands.size()); + + RexCall orCall1 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.OR, + rexBuilder.makeDynamicParam(boolType, 0), + rexBuilder.makeDynamicParam(boolType, 1)); + RexCall orCall2 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.OR, + rexBuilder.makeDynamicParam(boolType, 2), + rexBuilder.makeDynamicParam(boolType, 3)); + RexCall rexCall2 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.AND, + orCall1, orCall2); + RexCall rewrite2 = rewriter.rewrite(rexCall2, false); + Assert.assertEquals(2, rewrite2.operands.size()); + } + + @Test + public void testRewriteIn() { + RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER); + RexCall inCall1 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.IN, + rexBuilder.makeInputRef(intType, 1), + rexBuilder.makeDynamicParam(intType, 1), + rexBuilder.makeDynamicParam(intType, 2)); + RexCall rewrite1 = rewriter.rewrite(inCall1, false); + Assert.assertEquals(3, rewrite1.operands.size()); + + RexCall row = (RexCall) rexBuilder.makeCall(TddlOperatorTable.ROW, + rexBuilder.makeDynamicParam(intType, 1), + rexBuilder.makeDynamicParam(intType, 2), + rexBuilder.makeDynamicParam(intType, 3)); + RexCall inCall2 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.IN, + rexBuilder.makeDynamicParam(intType, 0), row); + RexCall rewrite2 = rewriter.rewrite(inCall2, false); + Assert.assertEquals(2, rewrite2.operands.size()); + } + + /** + * Raw string decimal in test + */ + @Test + public void testRewriteInDecimal() { + List list = new ArrayList<>(); + list.add(new BigDecimal("125.12")); + list.add(new BigDecimal("521.34")); + list.add(new BigDecimal("999.8")); + RawString rawString = new RawString(list); + context.setParams(new Parameters()); + context.getParams().getCurrentParameter().put(1, new ParameterContext(ParameterMethod.setObject1, new Object[] { + 1, rawString})); + + RelDataType charType = typeFactory.createSqlType(SqlTypeName.CHAR); + RexCall rowCall = (RexCall) rexBuilder.makeCall(TddlOperatorTable.ROW, + rexBuilder.makeDynamicParam(charType, 0)); + RexCall inCall1 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.IN, + rexBuilder.makeInputRef(charType, 1), + rowCall); + RexCall rewrite1 = rewriter.rewrite(inCall1, false); + Assert.assertEquals(4, rewrite1.operands.size()); + for (int i = 0; i < list.size(); i++) { + Assert.assertEquals(list.get(i), ((RexLiteral) rewrite1.operands.get(i + 1)).getValue3()); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/build/Rex2VecExprTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/build/Rex2VecExprTest.java new file mode 100644 index 000000000..286df6722 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/build/Rex2VecExprTest.java @@ -0,0 +1,148 @@ +package com.alibaba.polardbx.executor.vectorized.build; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.jdbc.Parameters; +import com.alibaba.polardbx.executor.vectorized.BuiltInFunctionVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.compare.FastInVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.compare.FastNotInVectorizedExpression; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rel.type.RelDataTypeSystem; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexCall; +import org.apache.calcite.rex.RexDynamicParam; +import org.apache.calcite.rex.RexFieldAccess; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.type.SqlTypeFactoryImpl; +import org.apache.calcite.sql.type.SqlTypeName; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +public class Rex2VecExprTest { + + private final RelDataTypeFactory typeFactory = new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + private final RexBuilder rexBuilder = new RexBuilder(typeFactory); + private ExpressionRewriter rewriter; + private ExecutionContext context; + + @Before + public void before() { + context = new ExecutionContext(); + context.getParamManager().getProps().put("ENABLE_EXPRESSION_VECTORIZATION", "true"); + context.getParamManager().getProps().put("ENABLE_COMMON_SUB_EXPRESSION_TREE_ELIMINATE", "true"); + this.rewriter = new ExpressionRewriter(context); + } + + @Test + public void testVisitIn() { + Rex2VectorizedExpressionVisitor visitor = new Rex2VectorizedExpressionVisitor(context, 3); + RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER); + RexCall inCall1 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.IN, + rexBuilder.makeDynamicParam(intType, 0), + rexBuilder.makeDynamicParam(intType, 1), + rexBuilder.makeDynamicParam(intType, 2)); + VectorizedExpression vectorizedExpression = visitor.visitCall(inCall1); + Assert.assertTrue(vectorizedExpression.getClass().getName(), + vectorizedExpression instanceof BuiltInFunctionVectorizedExpression); + + visitor = new Rex2VectorizedExpressionVisitor(context, 3); + RexCall inCall2 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.IN, + rexBuilder.makeInputRef(intType, 0), + rexBuilder.makeIntLiteral(100), + rexBuilder.makeIntLiteral(200), + rexBuilder.makeIntLiteral(300)); + vectorizedExpression = visitor.visitCall(inCall2); + Assert.assertTrue(vectorizedExpression.getClass().getName(), + vectorizedExpression instanceof FastInVectorizedExpression); + + // all args are of the same types + RexNode[] nodes = new RexNode[1000]; + nodes[0] = rexBuilder.makeInputRef(intType, 0); + for (int i = 1; i < nodes.length; i++) { + nodes[i] = rexBuilder.makeIntLiteral(10 * i); + } + RexCall inCall3 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.IN, nodes); + vectorizedExpression = visitor.visitCall(inCall3); + Assert.assertTrue(vectorizedExpression.getClass().getName(), + vectorizedExpression instanceof FastInVectorizedExpression); + + // diff arg types + nodes[1] = rexBuilder.makeLiteral("0"); + RexCall inCall4 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.IN, nodes); + vectorizedExpression = visitor.visitCall(inCall4); + Assert.assertTrue(vectorizedExpression.getClass().getName(), + vectorizedExpression instanceof BuiltInFunctionVectorizedExpression); + } + + @Test + public void testVisitNotIn() { + Rex2VectorizedExpressionVisitor visitor = new Rex2VectorizedExpressionVisitor(context, 3); + RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER); + RexCall inCall1 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.NOT_IN, + rexBuilder.makeDynamicParam(intType, 0), + rexBuilder.makeDynamicParam(intType, 1), + rexBuilder.makeDynamicParam(intType, 2)); + VectorizedExpression vectorizedExpression = visitor.visitCall(inCall1); + Assert.assertTrue(vectorizedExpression.getClass().getName(), + vectorizedExpression instanceof BuiltInFunctionVectorizedExpression); + + visitor = new Rex2VectorizedExpressionVisitor(context, 3); + RexCall inCall2 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.NOT_IN, + rexBuilder.makeInputRef(intType, 0), + rexBuilder.makeIntLiteral(100), + rexBuilder.makeIntLiteral(200), + rexBuilder.makeIntLiteral(300)); + vectorizedExpression = visitor.visitCall(inCall2); + Assert.assertTrue(vectorizedExpression.getClass().getName(), + vectorizedExpression instanceof FastNotInVectorizedExpression); + + // all args are of the same types + RexNode[] nodes = new RexNode[1000]; + nodes[0] = rexBuilder.makeInputRef(intType, 0); + for (int i = 1; i < nodes.length; i++) { + nodes[i] = rexBuilder.makeIntLiteral(10 * i); + } + RexCall inCall3 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.NOT_IN, nodes); + vectorizedExpression = visitor.visitCall(inCall3); + Assert.assertTrue(vectorizedExpression.getClass().getName(), + vectorizedExpression instanceof FastNotInVectorizedExpression); + + // diff arg types + nodes[1] = rexBuilder.makeLiteral("0"); + RexCall inCall4 = (RexCall) rexBuilder.makeCall(TddlOperatorTable.NOT_IN, nodes); + vectorizedExpression = visitor.visitCall(inCall4); + Assert.assertTrue(vectorizedExpression.getClass().getName(), + vectorizedExpression instanceof BuiltInFunctionVectorizedExpression); + } + + @Test + public void testVisitFieldAccess() { + Rex2VectorizedExpressionVisitor visitor = new Rex2VectorizedExpressionVisitor(context, 2); + try { + VectorizedExpression vectorizedExpression = visitor.visitFieldAccess(Mockito.mock(RexFieldAccess.class)); + Assert.fail("Expect exception"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Correlated variable is not supported")); + } + } + + @Test + public void testVisitDynamicParam() { + Parameters parameters = new Parameters(); + parameters.getCurrentParameter().put(1, new ParameterContext(ParameterMethod.setInt, new Object[] {0, 100})); + context.setParams(parameters); + Rex2VectorizedExpressionVisitor visitor = new Rex2VectorizedExpressionVisitor(context, 2); + RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER); + RexDynamicParam param = new RexDynamicParam(intType, 0); + VectorizedExpression vectorizedExpression = visitor.visitDynamicParam(param); + Assert.assertTrue(vectorizedExpression instanceof LiteralVectorizedExpression); + Assert.assertEquals(100, (int) ((LiteralVectorizedExpression) vectorizedExpression).getValue()); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDateColCharConstVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDateColCharConstVectorizedExpressionTest.java new file mode 100644 index 000000000..8d7876a63 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDateColCharConstVectorizedExpressionTest.java @@ -0,0 +1,222 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.common.utils.time.core.MysqlDateTime; +import com.alibaba.polardbx.common.utils.time.core.OriginalDate; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.DateBlock; +import com.alibaba.polardbx.executor.chunk.DateBlockBuilder; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.ObjectBlockBuilder; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.chunk.ReferenceBlock; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class BetweenDateColCharConstVectorizedExpressionTest { + + private final int count = 10; + private ExecutionContext context; + private List dateList; + + @Before + public void before() { + this.context = new ExecutionContext(); + this.dateList = new ArrayList<>(count); + for (int i = 0; i < count - 1; i++) { + MysqlDateTime date = new MysqlDateTime(); + date.setYear(2024); + date.setMonth(5); + date.setDay(i + 1); + dateList.add(date); + } + dateList.add(null); + } + + @Test + public void testDate() { + DateBlockBuilder dateBlockBuilder = new DateBlockBuilder(count, DataTypes.DateType, context); + for (MysqlDateTime mysqlDateTime : dateList) { + if (mysqlDateTime == null) { + dateBlockBuilder.appendNull(); + } else { + dateBlockBuilder.writeMysqlDatetime(mysqlDateTime); + } + } + DateBlock dateBlock = (DateBlock) dateBlockBuilder.build(); + Chunk inputChunk = new Chunk(dateBlock.getPositionCount(), dateBlock); + + LongBlock expectBlock = LongBlock.of(1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk, expectBlock, "2024-05-01", "2024-05-03", null); + } + + @Test + public void testDateWithSelection() { + int[] sel = new int[] {0, 1, 2, 4, 5, 9}; + DateBlockBuilder dateBlockBuilder = new DateBlockBuilder(count, DataTypes.DateType, context); + for (MysqlDateTime mysqlDateTime : dateList) { + if (mysqlDateTime == null) { + dateBlockBuilder.appendNull(); + } else { + dateBlockBuilder.writeMysqlDatetime(mysqlDateTime); + } + } + DateBlock dateBlock = (DateBlock) dateBlockBuilder.build(); + Chunk inputChunk = new Chunk(dateBlock.getPositionCount(), dateBlock); + + LongBlock expectBlock = LongBlock.of(1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk, expectBlock, "2024-05-01", "2024-05-03", sel); + } + + @Test + public void testRef() { + ObjectBlockBuilder objectBlockBuilder = new ObjectBlockBuilder(count); + for (MysqlDateTime mysqlDateTime : dateList) { + if (mysqlDateTime == null) { + objectBlockBuilder.appendNull(); + } else { + objectBlockBuilder.writeObject(new OriginalDate(mysqlDateTime)); + } + } + ReferenceBlock dateBlock = (ReferenceBlock) objectBlockBuilder.build(); + Chunk inputChunk = new Chunk(dateBlock.getPositionCount(), dateBlock); + + LongBlock expectBlock = LongBlock.of(1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk, expectBlock, "2024-05-01", "2024-05-03", null); + } + + @Test + public void testRefWithSel() { + int[] sel = new int[] {0, 1, 2, 4, 5, 9}; + + ObjectBlockBuilder objectBlockBuilder = new ObjectBlockBuilder(count); + for (MysqlDateTime mysqlDateTime : dateList) { + if (mysqlDateTime == null) { + objectBlockBuilder.appendNull(); + } else { + objectBlockBuilder.writeObject(new OriginalDate(mysqlDateTime)); + } + } + ReferenceBlock dateBlock = (ReferenceBlock) objectBlockBuilder.build(); + Chunk inputChunk = new Chunk(dateBlock.getPositionCount(), dateBlock); + + LongBlock expectBlock = LongBlock.of(1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk, expectBlock, "2024-05-01", "2024-05-03", sel); + } + + @Test + public void testNull() { + DateBlockBuilder dateBlockBuilder = new DateBlockBuilder(count, DataTypes.DateType, context); + for (MysqlDateTime mysqlDateTime : dateList) { + if (mysqlDateTime == null) { + dateBlockBuilder.appendNull(); + } else { + dateBlockBuilder.writeMysqlDatetime(mysqlDateTime); + } + } + DateBlock dateBlock = (DateBlock) dateBlockBuilder.build(); + Chunk inputChunk = new Chunk(dateBlock.getPositionCount(), dateBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null, null); + + doTest(inputChunk, expectBlock, null, "2024-05-03", null); + doTest(inputChunk, expectBlock, "2024-05-01", null, null); + doTest(inputChunk, expectBlock, null, null, null); + } + + @Test + public void testNullWithSel() { + int[] sel = new int[] {0, 1, 2, 4, 5, 9}; + + DateBlockBuilder dateBlockBuilder = new DateBlockBuilder(count, DataTypes.DateType, context); + for (MysqlDateTime mysqlDateTime : dateList) { + if (mysqlDateTime == null) { + dateBlockBuilder.appendNull(); + } else { + dateBlockBuilder.writeMysqlDatetime(mysqlDateTime); + } + } + DateBlock dateBlock = (DateBlock) dateBlockBuilder.build(); + Chunk inputChunk = new Chunk(dateBlock.getPositionCount(), dateBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null, null); + + doTest(inputChunk, expectBlock, null, "2024-05-03", sel); + doTest(inputChunk, expectBlock, "2024-05-01", null, sel); + doTest(inputChunk, expectBlock, null, null, sel); + } + + private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock, String left, String right, int[] sel) { + ExecutionContext context = new ExecutionContext(); + + BetweenDateColCharConstCharConstVectorizedExpression condition = + new BetweenDateColCharConstCharConstVectorizedExpression( + 3, + new VectorizedExpression[] { + new InputRefVectorizedExpression(DataTypes.DateType, 0, 0), + new LiteralVectorizedExpression(DataTypes.CharType, left, 1), + new LiteralVectorizedExpression(DataTypes.CharType, right, 2) + }); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(Collections.singletonList(DataTypes.DateType)) + .addEmptySlots(Arrays.asList(DataTypes.CharType, DataTypes.CharType, DataTypes.LongType)) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputChunk.getBlockCount(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputChunk.getBlockCount(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDecimalColDecimalConstVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDecimalColDecimalConstVectorizedExpressionTest.java new file mode 100644 index 000000000..b2374d62c --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenDecimalColDecimalConstVectorizedExpressionTest.java @@ -0,0 +1,170 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.DecimalBlock; +import com.alibaba.polardbx.executor.chunk.DecimalBlockBuilder; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class BetweenDecimalColDecimalConstVectorizedExpressionTest { + + private final int count = 10; + private final List decValues; + private final List longValues; + private final DataType decimalType = new DecimalType(18, 2); + private final Decimal[] decimals = new Decimal[] { + new Decimal(100, 2), + new Decimal(205, 2), + new Decimal(9999, 2), + null, + new Decimal(20001, 2), + new Decimal(100000, 2), + null, + new Decimal(10000, 2), + new Decimal(-10000, 2) + }; + + public BetweenDecimalColDecimalConstVectorizedExpressionTest() { + this.decValues = new ArrayList<>(count); + this.longValues = new ArrayList<>(count); + for (int i = 0; i < count - 1; i++) { + long val = i * 50; + this.decValues.add(Decimal.fromLong(val)); + this.longValues.add(val); + } + this.decValues.add(null); + this.longValues.add(null); + } + + private DecimalBlock getDecimalBlock(Decimal[] decimals) { + DecimalBlockBuilder blockBuilder = new DecimalBlockBuilder(4, decimalType); + for (int i = 0; i < decimals.length; i++) { + if (decimals[i] != null) { + blockBuilder.writeDecimal(decimals[i]); + } else { + blockBuilder.appendNull(); + } + } + return (DecimalBlock) blockBuilder.build(); + } + + @Test + public void test() { + DecimalBlock decimalBlock = getDecimalBlock(decimals); + Chunk inputChunk = new Chunk(decimalBlock.getPositionCount(), decimalBlock); + + LongBlock expectBlock = LongBlock.of(1L, 1L, 1L, null, 0L, 0L, null, 1L, 0L); + + doTest(inputChunk, expectBlock, new Decimal(100, 2), new Decimal(10000, 2), null); + } + + @Test + public void testWithSelection() { + DecimalBlock decimalBlock = getDecimalBlock(decimals); + Chunk inputChunk = new Chunk(decimalBlock.getPositionCount(), decimalBlock); + + LongBlock expectBlock = LongBlock.of(1L, 1L, 1L, null, 0L, 0L, null, 1L, 0L); + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTest(inputChunk, expectBlock, new Decimal(100, 2), new Decimal(10000, 2), sel); + } + + @Test + public void testNull() { + DecimalBlock decimalBlock = getDecimalBlock(decimals); + Chunk inputChunk = new Chunk(decimalBlock.getPositionCount(), decimalBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null); + + doTest(inputChunk, expectBlock, null, null, null); + doTest(inputChunk, expectBlock, new Decimal(100, 2), null, null); + doTest(inputChunk, expectBlock, null, new Decimal(10000, 2), null); + } + + @Test + public void testNullWithSelection() { + DecimalBlock decimalBlock = getDecimalBlock(decimals); + Chunk inputChunk = new Chunk(decimalBlock.getPositionCount(), decimalBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null); + int[] sel = new int[] {0, 1, 2, 4, 5}; + + doTest(inputChunk, expectBlock, null, null, sel); + doTest(inputChunk, expectBlock, new Decimal(100, 2), null, sel); + doTest(inputChunk, expectBlock, null, new Decimal(10000, 2), sel); + } + + private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock, Decimal left, Decimal right, int[] sel) { + ExecutionContext context = new ExecutionContext(); + + BetweenDecimalColDecimalConstDecimalConstVectorizedExpression condition = + new BetweenDecimalColDecimalConstDecimalConstVectorizedExpression( + 3, + new VectorizedExpression[] { + new InputRefVectorizedExpression(decimalType, 0, 0), + new LiteralVectorizedExpression(decimalType, left, 1), + new LiteralVectorizedExpression(decimalType, right, 2) + }); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(Collections.singletonList(decimalType)) + .addEmptySlots(Arrays.asList(decimalType, decimalType, DataTypes.LongType)) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputChunk.getBlockCount(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputChunk.getBlockCount(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenIntegerColLongConstVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenIntegerColLongConstVectorizedExpressionTest.java new file mode 100644 index 000000000..7fa975a58 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenIntegerColLongConstVectorizedExpressionTest.java @@ -0,0 +1,186 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.IntegerBlock; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; + +public class BetweenIntegerColLongConstVectorizedExpressionTest { + + @Test + public void test() { + + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + + LongBlock expectBlock = LongBlock.of(1L, 1L, 1L, null, 0L, 0L, null, 1L, 0L); + + doTest(inputChunk, expectBlock, 1, 100, null); + } + + @Test + public void testWithSelection() { + + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + + LongBlock expectBlock = LongBlock.of(1L, 1L, 1L, null, 0L, 0L, null, 1L, 0L); + + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTest(inputChunk, expectBlock, 1, 100, sel); + } + + @Test + public void testNull() { + + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null); + + doTestNull(inputChunk, expectBlock, null, null, null); + doTestNull(inputChunk, expectBlock, 1L, null, null); + doTestNull(inputChunk, expectBlock, null, 100L, null); + } + + @Test + public void testNullWithSelection() { + + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null); + + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTestNull(inputChunk, expectBlock, null, null, sel); + doTestNull(inputChunk, expectBlock, 1L, null, sel); + doTestNull(inputChunk, expectBlock, null, 100L, sel); + } + + private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock, long left, long right, int[] sel) { + ExecutionContext context = new ExecutionContext(); + + BetweenIntegerColLongConstLongConstVectorizedExpression condition = + new BetweenIntegerColLongConstLongConstVectorizedExpression( + 3, + new VectorizedExpression[] { + new InputRefVectorizedExpression(DataTypes.IntegerType, 0, 0), + new LiteralVectorizedExpression(DataTypes.LongType, left, 1), + new LiteralVectorizedExpression(DataTypes.LongType, right, 2) + }); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(Collections.singletonList(DataTypes.IntegerType)) + .addEmptySlots(Arrays.asList(DataTypes.LongType, DataTypes.LongType, DataTypes.LongType)) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputChunk.getBlockCount(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputChunk.getBlockCount(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } + + private void doTestNull(Chunk inputChunk, RandomAccessBlock expectBlock, Long left, Long right, int[] sel) { + ExecutionContext context = new ExecutionContext(); + + BetweenIntegerColLongConstLongConstVectorizedExpression condition = + new BetweenIntegerColLongConstLongConstVectorizedExpression( + 3, + new VectorizedExpression[] { + new InputRefVectorizedExpression(DataTypes.IntegerType, 0, 0), + new LiteralVectorizedExpression(DataTypes.LongType, left, 1), + new LiteralVectorizedExpression(DataTypes.LongType, right, 2) + }); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(Collections.singletonList(DataTypes.IntegerType)) + .addEmptySlots(Arrays.asList(DataTypes.LongType, DataTypes.LongType, DataTypes.LongType)) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputChunk.getBlockCount(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputChunk.getBlockCount(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenLongColLongConstVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenLongColLongConstVectorizedExpressionTest.java new file mode 100644 index 000000000..552423b32 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BetweenLongColLongConstVectorizedExpressionTest.java @@ -0,0 +1,128 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; + +public class BetweenLongColLongConstVectorizedExpressionTest { + + @Test + public void test() { + + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + + LongBlock expectBlock = LongBlock.of(1L, 1L, 1L, null, 0L, 0L, null, 1L, 0L); + + doTest(inputChunk, expectBlock, 1L, 100L, null); + } + + @Test + public void testWithSelection() { + + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + + LongBlock expectBlock = LongBlock.of(1L, 1L, 1L, null, 0L, 0L, null, 1L, 0L); + + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTest(inputChunk, expectBlock, 1L, 100L, sel); + } + + @Test + public void testNull() { + + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null); + + doTest(inputChunk, expectBlock, null, null, null); + doTest(inputChunk, expectBlock, 1L, null, null); + doTest(inputChunk, expectBlock, null, 100L, null); + } + + @Test + public void testNullWithSelection() { + + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null); + + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTest(inputChunk, expectBlock, null, null, sel); + doTest(inputChunk, expectBlock, 1L, null, sel); + doTest(inputChunk, expectBlock, null, 100L, sel); + } + + private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock, Long left, Long right, int[] sel) { + ExecutionContext context = new ExecutionContext(); + + BetweenLongColLongConstLongConstVectorizedExpression condition = + new BetweenLongColLongConstLongConstVectorizedExpression( + 3, + new VectorizedExpression[] { + new InputRefVectorizedExpression(DataTypes.LongType, 0, 0), + new LiteralVectorizedExpression(DataTypes.LongType, left, 1), + new LiteralVectorizedExpression(DataTypes.LongType, right, 2) + }); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(Collections.singletonList(DataTypes.LongType)) + .addEmptySlots(Arrays.asList(DataTypes.LongType, DataTypes.LongType, DataTypes.LongType)) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputChunk.getBlockCount(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputChunk.getBlockCount(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/BooleanTestOperatorsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BooleanTestOperatorsTest.java similarity index 98% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/BooleanTestOperatorsTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BooleanTestOperatorsTest.java index 5e3d44501..037be1437 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/BooleanTestOperatorsTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/BooleanTestOperatorsTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.polardbx.executor.vectorized.comparison; +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.vectorized.BaseProjectionTest; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/ComparisonBinaryOperatorsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/ComparisonBinaryOperatorsTest.java similarity index 99% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/ComparisonBinaryOperatorsTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/ComparisonBinaryOperatorsTest.java index a54972f37..e41f8577e 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/ComparisonBinaryOperatorsTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/ComparisonBinaryOperatorsTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.polardbx.executor.vectorized.comparison; +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.executor.chunk.Block; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/EQIntegerColCharConstVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/EQIntegerColCharConstVectorizedExpressionTest.java new file mode 100644 index 000000000..5b9cfd4ea --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/EQIntegerColCharConstVectorizedExpressionTest.java @@ -0,0 +1,215 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.IntegerBlock; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; +import com.alibaba.polardbx.executor.vectorized.build.Rex2VectorizedExpressionVisitor; +import com.alibaba.polardbx.executor.vectorized.build.VectorizedExpressionBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; +import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; +import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.type.SqlTypeName; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class EQIntegerColCharConstVectorizedExpressionTest { + private final static RelDataTypeFactory TYPE_FACTORY = + new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); + private final static RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY); + + @Test + public void test() { + + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + + LongBlock expectBlock = LongBlock.of(0L, 0L, 1L, null, 0L, 0L, null, 1L, 0L); + + doTest(inputChunk, expectBlock, null); + } + + @Test + public void testWithSelection() { + + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + + LongBlock expectBlock = LongBlock.of(0L, 0L, 1L, null, 0L, 0L, null, 1L, 0L); + + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTest(inputChunk, expectBlock, sel); + } + + @Test + public void testNull() { + + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null); + + doTestNull(inputChunk, expectBlock, null); + } + + @Test + public void testNullWithSelection() { + + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null); + + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTestNull(inputChunk, expectBlock, sel); + } + + private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock, int[] sel) { + ExecutionContext context = new ExecutionContext(); + + // rex node is "=(int ref, char const)" + RexNode rexNode = REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), + TddlOperatorTable.EQUALS, + ImmutableList.of( + REX_BUILDER.makeInputRef(TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER), 0), + REX_BUILDER.makeLiteral("100", TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR), true) + )); + + List> inputTypes = ImmutableList.of(DataTypes.IntegerType); + + RexNode root = VectorizedExpressionBuilder.rewriteRoot(rexNode, true); + + InputRefTypeChecker inputRefTypeChecker = new InputRefTypeChecker(inputTypes); + root = root.accept(inputRefTypeChecker); + + Rex2VectorizedExpressionVisitor converter = + new Rex2VectorizedExpressionVisitor(context, inputTypes.size()); + VectorizedExpression condition = root.accept(converter); + + Assert.assertTrue(condition instanceof EQIntegerColCharConstVectorizedExpression); + + // Data types of intermediate results or final results. + List> filterOutputTypes = converter.getOutputDataTypes(); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(inputTypes) + .addEmptySlots(filterOutputTypes) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .addLiteralBitmap(converter.getLiteralBitmap()) + .build(); + + preAllocatedChunk.setSelectionInUse(false); + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputTypes.size(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputTypes.size(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } + + private void doTestNull(Chunk inputChunk, RandomAccessBlock expectBlock, int[] sel) { + ExecutionContext context = new ExecutionContext(); + + EQIntegerColCharConstVectorizedExpression condition = new EQIntegerColCharConstVectorizedExpression( + 2, + new VectorizedExpression[] { + new InputRefVectorizedExpression(DataTypes.IntegerType, 0, 0), + new LiteralVectorizedExpression(DataTypes.VarcharType, null, 1) + }); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(Collections.singletonList(DataTypes.IntegerType)) + .addEmptySlots(Arrays.asList(DataTypes.CharType, DataTypes.LongType)) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .build(); + + preAllocatedChunk.setSelectionInUse(false); + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputChunk.getBlockCount(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputChunk.getBlockCount(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/EQLongColCharConstVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/EQLongColCharConstVectorizedExpressionTest.java new file mode 100644 index 000000000..f43a9478f --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/EQLongColCharConstVectorizedExpressionTest.java @@ -0,0 +1,211 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; +import com.alibaba.polardbx.executor.vectorized.build.Rex2VectorizedExpressionVisitor; +import com.alibaba.polardbx.executor.vectorized.build.VectorizedExpressionBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; +import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; +import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.type.SqlTypeName; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class EQLongColCharConstVectorizedExpressionTest { + private final static RelDataTypeFactory TYPE_FACTORY = + new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); + private final static RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY); + + @Test + public void test() { + + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + + LongBlock expectBlock = LongBlock.of(0L, 0L, 1L, null, 0L, 0L, null, 1L, 0L); + + doTest(inputChunk, expectBlock, "100", null); + } + + @Test + public void testWithSelection() { + + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + + LongBlock expectBlock = LongBlock.of(0L, 0L, 1L, null, 0L, 0L, null, 1L, 0L); + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTest(inputChunk, expectBlock, "100", sel); + } + + @Test + public void testNull() { + + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, 0L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null); + + doTestNull(inputChunk, expectBlock, null); + } + + @Test + public void testWithSelectionNull() { + + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, 0L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null); + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTestNull(inputChunk, expectBlock, sel); + } + + private void doTestNull(Chunk inputChunk, RandomAccessBlock expectBlock, int[] sel) { + ExecutionContext context = new ExecutionContext(); + + EQLongColCharConstVectorizedExpression condition = new EQLongColCharConstVectorizedExpression( + 2, + new VectorizedExpression[] { + new InputRefVectorizedExpression(DataTypes.LongType, 0, 0), + new LiteralVectorizedExpression(DataTypes.VarcharType, null, 1) + }); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(Collections.singletonList(DataTypes.LongType)) + .addEmptySlots(Arrays.asList(DataTypes.CharType, DataTypes.LongType)) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputChunk.getBlockCount(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputChunk.getBlockCount(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } + + private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock, String value, int[] sel) { + ExecutionContext context = new ExecutionContext(); + + // rex node is "=(bigint ref, char const)" + RexNode rexNode = REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), + TddlOperatorTable.EQUALS, + ImmutableList.of( + REX_BUILDER.makeInputRef(TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), 0), + REX_BUILDER.makeLiteral(value, TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR), true) + )); + + List> inputTypes = ImmutableList.of(DataTypes.LongType); + + RexNode root = VectorizedExpressionBuilder.rewriteRoot(rexNode, true); + + InputRefTypeChecker inputRefTypeChecker = new InputRefTypeChecker(inputTypes); + root = root.accept(inputRefTypeChecker); + + Rex2VectorizedExpressionVisitor converter = + new Rex2VectorizedExpressionVisitor(context, inputTypes.size()); + VectorizedExpression condition = root.accept(converter); + + Assert.assertTrue(condition instanceof EQLongColCharConstVectorizedExpression); + condition.getChildren()[1] = new LiteralVectorizedExpression(DataTypes.VarcharType, null, 0); + + // Data types of intermediate results or final results. + List> filterOutputTypes = converter.getOutputDataTypes(); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(inputTypes) + .addEmptySlots(filterOutputTypes) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .addLiteralBitmap(converter.getLiteralBitmap()) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputTypes.size(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputTypes.size(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/EQVarcharColCharConstVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/EQVarcharColCharConstVectorizedExpressionTest.java new file mode 100644 index 000000000..eb313dd42 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/EQVarcharColCharConstVectorizedExpressionTest.java @@ -0,0 +1,340 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.chunk.SliceBlock; +import com.alibaba.polardbx.executor.chunk.SliceBlockBuilder; +import com.alibaba.polardbx.executor.operator.scan.BlockDictionary; +import com.alibaba.polardbx.executor.operator.scan.impl.LocalBlockDictionary; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; +import com.alibaba.polardbx.executor.vectorized.build.Rex2VectorizedExpressionVisitor; +import com.alibaba.polardbx.executor.vectorized.build.VectorizedExpressionBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; +import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; +import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.datatype.SliceType; +import com.google.common.collect.ImmutableList; +import io.airlift.slice.Slice; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.type.SqlTypeName; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@RunWith(Parameterized.class) +public class EQVarcharColCharConstVectorizedExpressionTest { + private final static RelDataTypeFactory TYPE_FACTORY = + new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); + private final static RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY); + private final int count = 10; + private final boolean enableCompatible; + private ExecutionContext context; + + public EQVarcharColCharConstVectorizedExpressionTest(boolean compatible) { + this.enableCompatible = compatible; + } + + @Before + public void before() { + context = new ExecutionContext(); + context.getParamManager().getProps().put("ENABLE_OSS_COMPATIBLE", String.valueOf(enableCompatible)); + } + + @Parameterized.Parameters(name = "compatible={0}") + public static List generateParameters() { + List list = new ArrayList<>(); + list.add(new Object[] {false}); + list.add(new Object[] {true}); + return list; + } + + @Test + public void testSlice() { + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk, expectBlock, "100", null); + } + + @Test + public void testDict() { + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + sliceBlock = getBlockWithDict(sliceBlock); + + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk, expectBlock, "100", null); + } + + @Test + public void testDictWithSelection() { + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + sliceBlock = getBlockWithDict(sliceBlock); + + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, null); + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTest(inputChunk, expectBlock, "100", sel); + } + + @Test + public void testDictNotMatch() { + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + sliceBlock = getBlockWithDict(sliceBlock); + + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk, expectBlock, "999", null); + } + + @Test + public void testDictWithSelectionNotMatch() { + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + sliceBlock = getBlockWithDict(sliceBlock); + + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, null); + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTest(inputChunk, expectBlock, "999", sel); + } + + @Test + public void testSliceWithSelection() { + + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTest(inputChunk, expectBlock, "100", sel); + } + + @Test + public void testNull() { + + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null, null); + + doTestNull(inputChunk, expectBlock, null); + } + + @Test + public void testWithSelectionNull() { + + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null, null); + + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTestNull(inputChunk, expectBlock, sel); + } + + private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock, String value, int[] sel) { + // rex node is "=(varchar ref, char const)" + RexNode rexNode = REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), + TddlOperatorTable.EQUALS, + ImmutableList.of( + REX_BUILDER.makeInputRef(TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR), 0), + REX_BUILDER.makeLiteral(value, TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR), false) + )); + + List> inputTypes = ImmutableList.of(DataTypes.VarcharType); + + RexNode root = VectorizedExpressionBuilder.rewriteRoot(rexNode, true); + + InputRefTypeChecker inputRefTypeChecker = new InputRefTypeChecker(inputTypes); + root = root.accept(inputRefTypeChecker); + + Rex2VectorizedExpressionVisitor converter = + new Rex2VectorizedExpressionVisitor(context, inputTypes.size()); + VectorizedExpression condition = root.accept(converter); + + Assert.assertTrue(condition instanceof EQVarcharColCharConstVectorizedExpression); + + // Data types of intermediate results or final results. + List> filterOutputTypes = converter.getOutputDataTypes(); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(inputTypes) + .addEmptySlots(filterOutputTypes) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .addLiteralBitmap(converter.getLiteralBitmap()) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputTypes.size(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputTypes.size(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } + + private void doTestNull(Chunk inputChunk, RandomAccessBlock expectBlock, int[] sel) { + EQVarcharColCharConstVectorizedExpression condition = new EQVarcharColCharConstVectorizedExpression( + 2, + new VectorizedExpression[] { + new InputRefVectorizedExpression(DataTypes.VarcharType, 0, 0), + new LiteralVectorizedExpression(DataTypes.VarcharType, null, 1) + }); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(Collections.singletonList(DataTypes.VarcharType)) + .addEmptySlots(Arrays.asList(DataTypes.CharType, DataTypes.LongType)) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputChunk.getBlockCount(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputChunk.getBlockCount(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } + + private SliceBlock getBlockWithDict(SliceBlock sliceBlock) { + int count = sliceBlock.getPositionCount(); + Slice[] slices = new Slice[sliceBlock.getPositionCount()]; + int[] dictIds = new int[sliceBlock.getPositionCount()]; + for (int i = 0; i < slices.length; i++) { + slices[i] = sliceBlock.getRegion(i); + dictIds[i] = i; + } + BlockDictionary dictionary = new LocalBlockDictionary(slices); + return new SliceBlock((SliceType) sliceBlock.getType(), 0, count, sliceBlock.nulls(), + dictionary, dictIds, true); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastBetweenDecimalTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastBetweenDecimalTest.java new file mode 100644 index 000000000..8b3e43449 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastBetweenDecimalTest.java @@ -0,0 +1,314 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.common.datatype.FastDecimalUtils; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.DecimalBlock; +import com.alibaba.polardbx.executor.chunk.DecimalBlockBuilder; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Random; + +/** + * 只有当 left 和 right scale 相同时,才能走 decimal64 路径 + */ +@RunWith(Parameterized.class) +public class FastBetweenDecimalTest { + + private static final int COUNT = 1024; + /** + * 虽然 precision 不在 decimal64 范围内 + * 但是否为 decimal64 取决于实际的值 + */ + private static final int PRECISION = 20; + private static final int OUTPUT_INDEX = 1; + private static final int BLOCK_COUNT = 2; + private static final int RANGE = 1000; + private static final Decimal RANGE_DECIMAL = Decimal.fromLong(RANGE); + private final int scale; + private final DecimalType leftDecimalType; + private final DecimalType rightDecimalType; + private final DecimalType inputDecimalType; + + private final Decimal leftDecimal; + private final Decimal rightDecimal; + + private final Random random = new Random(System.currentTimeMillis()); + private final long[] targetResult = new long[COUNT]; + private final int[] sel; + private final boolean withSelection; + + private final ExecutionContext executionContext = new ExecutionContext(); + + public FastBetweenDecimalTest(int scale, boolean withSelection) { + this.scale = scale; + this.leftDecimalType = new DecimalType(PRECISION, scale); + this.rightDecimalType = new DecimalType(PRECISION, scale); + this.inputDecimalType = new DecimalType(PRECISION, scale); + if (scale <= 1) { + long l = genDecimal64NotOverflowLong(); + this.leftDecimal = new Decimal(l, scale); + this.rightDecimal = leftDecimal.add(RANGE_DECIMAL); + } else if (scale <= 2) { + long l = genDecimal64NotOverflowLong(); + this.leftDecimal = null; + this.rightDecimal = new Decimal(l, scale); + } else if (scale <= 5) { + long l = genDecimal64NotOverflowLong(); + this.leftDecimal = new Decimal(-l, scale); + this.rightDecimal = null; + } else { + this.leftDecimal = null; + this.rightDecimal = null; + } + + this.withSelection = withSelection; + if (withSelection) { + final int offset = 10; + this.sel = new int[COUNT / 2]; + for (int i = 0; i < sel.length; i++) { + sel[i] = i + offset; + } + } else { + this.sel = null; + } + } + + @Parameterized.Parameters(name = "scale={0},sel={1}") + public static List generateParameters() { + List list = new ArrayList<>(); + + final int[] scales = {0, 1, 2, 5, 9}; + for (int scale : scales) { + list.add(new Object[] {scale, false}); + list.add(new Object[] {scale, true}); + } + return list; + } + + @Test + public void testBetweenDecimal64() { + final VectorizedExpression[] children = new VectorizedExpression[3]; + children[0] = new InputRefVectorizedExpression(inputDecimalType, 0, 0); + children[1] = new LiteralVectorizedExpression(leftDecimalType, leftDecimal, 1); + children[2] = new LiteralVectorizedExpression(rightDecimalType, rightDecimal, 2); + FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression expr = + new FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression( + OUTPUT_INDEX, children); + + MutableChunk chunk = buildDecimal64Chunk(); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + + LongBlock outputBlock = (LongBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); + DecimalBlock inputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(0)); + + expr.eval(evaluationContext); + + // check result + Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Incorrect between result for: " + inputBlock.getDecimal(j).toString(), + targetResult[j], outputBlock.getLong(j)); + } + } else { + for (int i = 0; i < COUNT; i++) { + Assert.assertEquals("Incorrect between result for: " + inputBlock.getDecimal(i).toString(), + targetResult[i], outputBlock.getLong(i)); + } + } + } + + @Test + public void testBetweenDecimal() { + final VectorizedExpression[] children = new VectorizedExpression[3]; + children[0] = new InputRefVectorizedExpression(inputDecimalType, 0, 0); + children[1] = new LiteralVectorizedExpression(leftDecimalType, leftDecimal, 1); + children[2] = new LiteralVectorizedExpression(rightDecimalType, rightDecimal, 2); + FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression expr = + new FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression( + OUTPUT_INDEX, children); + + MutableChunk chunk = buildDecimalChunk(); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + + LongBlock outputBlock = (LongBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); + DecimalBlock inputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(0)); + + expr.eval(evaluationContext); + + // check result + Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Incorrect between result for: " + inputBlock.getDecimal(j).toString(), + targetResult[j], outputBlock.getLong(j)); + } + } else { + for (int i = 0; i < COUNT; i++) { + Assert.assertEquals("Incorrect between result for: " + inputBlock.getDecimal(i).toString(), + targetResult[i], outputBlock.getLong(i)); + } + } + } + + /** + * between '0.01' and '3.21' + */ + @Test + public void testBetweenDecimal64CharConstCharConst() { + final VectorizedExpression[] children = new VectorizedExpression[3]; + children[0] = new InputRefVectorizedExpression(inputDecimalType, 0, 0); + children[1] = new LiteralVectorizedExpression(DataTypes.CharType, + leftDecimal == null ? null : leftDecimal.toString(), 1); + children[2] = new LiteralVectorizedExpression(DataTypes.CharType, + rightDecimal == null ? null : rightDecimal.toString(), 2); + FastBetweenDecimalColCharConstCharConstVectorizedExpression expr = + new FastBetweenDecimalColCharConstCharConstVectorizedExpression( + OUTPUT_INDEX, children); + + MutableChunk chunk = buildDecimal64Chunk(); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + + LongBlock outputBlock = (LongBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); + DecimalBlock inputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(0)); + + expr.eval(evaluationContext); + + // check result + Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Incorrect between result for: " + inputBlock.getDecimal(j).toString(), + targetResult[j], outputBlock.getLong(j)); + } + } else { + for (int i = 0; i < COUNT; i++) { + Assert.assertEquals("Incorrect between result for: " + inputBlock.getDecimal(i).toString(), + targetResult[i], outputBlock.getLong(i)); + } + } + } + + @Test + public void testBetweenDecimalCharConstCharConst() { + final VectorizedExpression[] children = new VectorizedExpression[3]; + children[0] = new InputRefVectorizedExpression(inputDecimalType, 0, 0); + children[1] = new LiteralVectorizedExpression(DataTypes.CharType, + leftDecimal == null ? null : leftDecimal.toString(), 1); + children[2] = new LiteralVectorizedExpression(DataTypes.CharType, + rightDecimal == null ? null : rightDecimal.toString(), 2); + FastBetweenDecimalColCharConstCharConstVectorizedExpression expr = + new FastBetweenDecimalColCharConstCharConstVectorizedExpression( + OUTPUT_INDEX, children); + + MutableChunk chunk = buildDecimalChunk(); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + + LongBlock outputBlock = (LongBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); + DecimalBlock inputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(0)); + + expr.eval(evaluationContext); + + // check result + Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Incorrect between result for: " + inputBlock.getDecimal(j).toString(), + targetResult[j], outputBlock.getLong(j)); + } + } else { + for (int i = 0; i < COUNT; i++) { + Assert.assertEquals("Incorrect between result for: " + inputBlock.getDecimal(i).toString(), + targetResult[i], outputBlock.getLong(i)); + } + } + } + + private MutableChunk buildDecimal64Chunk() { + Block[] blocks = new Block[BLOCK_COUNT]; + blocks[0] = new DecimalBlock(inputDecimalType, COUNT); + blocks[1] = new LongBlock(DataTypes.LongType, COUNT); + Decimal leftDec = leftDecimal == null ? Decimal.ZERO : leftDecimal; + Decimal rightDec = rightDecimal == null ? Decimal.ZERO : rightDecimal; + DecimalBlockBuilder inputBuilder = new DecimalBlockBuilder(COUNT, inputDecimalType); + for (int i = 0; i < COUNT; i++) { + long left = genDecimal64NotOverflowLong(); + inputBuilder.writeLong(left); + Decimal inputDecimal = new Decimal(left, scale); + boolean between = FastDecimalUtils.compare(inputDecimal.getDecimalStructure(), + leftDec.getDecimalStructure()) >= 0; + between &= FastDecimalUtils.compare(inputDecimal.getDecimalStructure(), + rightDec.getDecimalStructure()) <= 0; + targetResult[i] = between ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + DecimalBlock inputBlock = (DecimalBlock) inputBuilder.build(); + blocks[0] = inputBlock; + Assert.assertTrue(inputBlock.isDecimal64()); + + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setSelectionInUse(true); + chunk.setSelection(sel); + chunk.setBatchSize(sel.length); + } + return chunk; + } + + private MutableChunk buildDecimalChunk() { + Block[] blocks = new Block[BLOCK_COUNT]; + blocks[0] = new DecimalBlock(inputDecimalType, COUNT); + blocks[1] = new LongBlock(DataTypes.LongType, COUNT); + Decimal leftDec = leftDecimal == null ? Decimal.ZERO : leftDecimal; + Decimal rightDec = rightDecimal == null ? Decimal.ZERO : rightDecimal; + DecimalBlockBuilder inputBuilder = new DecimalBlockBuilder(COUNT, inputDecimalType); + for (int i = 0; i < COUNT; i++) { + long left = genDecimal64OverflowLong(); + Decimal inputDecimal = new Decimal(left, scale); + inputBuilder.writeDecimal(inputDecimal); + boolean between = FastDecimalUtils.compare(inputDecimal.getDecimalStructure(), + leftDec.getDecimalStructure()) >= 0; + between &= FastDecimalUtils.compare(inputDecimal.getDecimalStructure(), + rightDec.getDecimalStructure()) <= 0; + targetResult[i] = between ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; + } + DecimalBlock inputBlock = (DecimalBlock) inputBuilder.build(); + blocks[0] = inputBlock; + Assert.assertFalse(inputBlock.isDecimal64()); + + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setSelectionInUse(true); + chunk.setSelection(sel); + chunk.setBatchSize(sel.length); + } + return chunk; + } + + private long genDecimal64NotOverflowLong() { + return random.nextInt(9999999) + 10_000_000; + } + + private long genDecimal64OverflowLong() { + return random.nextInt(9999999) + 9000_000_000L; + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastCompareDecimalTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastCompareDecimalTest.java similarity index 78% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastCompareDecimalTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastCompareDecimalTest.java index da5d07344..1a2d3d617 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastCompareDecimalTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastCompareDecimalTest.java @@ -1,4 +1,4 @@ -package com.alibaba.polardbx.executor.vectorized.math; +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.common.datatype.Decimal; import com.alibaba.polardbx.common.datatype.FastDecimalUtils; @@ -13,14 +13,6 @@ import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.FastGEDecimalColDecimalConstVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.FastGEDecimalColLongConstVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.FastGTDecimalColDecimalConstVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.FastGTDecimalColLongConstVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.FastLEDecimalColDecimalConstVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.FastLEDecimalColLongConstVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.FastLTDecimalColDecimalConstVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.FastLTDecimalColLongConstVectorizedExpression; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; @@ -53,8 +45,10 @@ public class FastCompareDecimalTest { private final Random random = new Random(System.currentTimeMillis()); private final long[] targetResult = new long[COUNT]; private final ExecutionContext executionContext = new ExecutionContext(); + private final boolean withSelection; - public FastCompareDecimalTest(int scale, CompareType compareType, Long specialVal) { + public FastCompareDecimalTest(int scale, CompareType compareType, + Long specialVal, boolean withSelection) { this.scale = scale; this.inputDecimalType = new DecimalType(PRECISION, scale); if (specialVal != null) { @@ -71,25 +65,28 @@ public FastCompareDecimalTest(int scale, CompareType compareType, Long specialVa } this.compareType = compareType; + this.withSelection = withSelection; } - @Parameterized.Parameters(name = "scale={0},compareType={1},specialVal={2}") + @Parameterized.Parameters(name = "scale={0},compareType={1},specialVal={2},sel={3}") public static List generateParameters() { List list = new ArrayList<>(); - int[] scales = {-1, 0, 1, 2, 5, 9}; + int[] scales = {-1, 0, 1, 2, 9}; for (int scale : scales) { for (CompareType type : CompareType.values()) { - list.add(new Object[] {scale, type, null}); + list.add(new Object[] {scale, type, null, false}); + list.add(new Object[] {scale, type, null, true}); } } - scales = new int[] {0, 1, 2, 5, 9}; + scales = new int[] {0, 1, 9}; for (int scale : scales) { for (CompareType type : CompareType.values()) { - list.add(new Object[] {scale, type, new Long(0)}); - list.add(new Object[] {scale, type, new Long(Long.MIN_VALUE)}); - list.add(new Object[] {scale, type, new Long(Long.MAX_VALUE)}); - list.add(new Object[] {scale, type, new Long(Integer.MAX_VALUE)}); + list.add(new Object[] {scale, type, new Long(0), false}); + list.add(new Object[] {scale, type, new Long(0), true}); + list.add(new Object[] {scale, type, new Long(Long.MIN_VALUE), false}); + list.add(new Object[] {scale, type, new Long(Long.MAX_VALUE), false}); + list.add(new Object[] {scale, type, new Long(Integer.MAX_VALUE), false}); } } return list; @@ -182,7 +179,11 @@ public void testDecimal128CompareLong() { public void testDecimal64CompareSameScaleDecimal64() { final VectorizedExpression[] children = new VectorizedExpression[3]; children[0] = new InputRefVectorizedExpression(inputDecimalType, 0, 0); - children[1] = new LiteralVectorizedExpression(inputDecimalType, operandDec, 1); + if (longVal == null) { + children[1] = new LiteralVectorizedExpression(inputDecimalType, null, 1); + } else { + children[1] = new LiteralVectorizedExpression(inputDecimalType, operandDec, 1); + } AbstractVectorizedExpression expr; switch (compareType) { @@ -218,6 +219,53 @@ public void testDecimal64CompareSameScaleDecimal64() { } } + @Test + public void testDecimal128CompareSameScaleDecimal64() { + if (scale == -1) { + return; + } + final VectorizedExpression[] children = new VectorizedExpression[3]; + children[0] = new InputRefVectorizedExpression(inputDecimalType, 0, 0); + if (longVal == null) { + children[1] = new LiteralVectorizedExpression(inputDecimalType, null, 1); + } else { + children[1] = new LiteralVectorizedExpression(inputDecimalType, operandDec, 1); + } + + AbstractVectorizedExpression expr; + switch (compareType) { + case GE: + expr = new FastGEDecimalColDecimalConstVectorizedExpression(OUTPUT_INDEX, children); + break; + case GT: + expr = new FastGTDecimalColDecimalConstVectorizedExpression(OUTPUT_INDEX, children); + break; + case LE: + expr = new FastLEDecimalColDecimalConstVectorizedExpression(OUTPUT_INDEX, children); + break; + case LT: + expr = new FastLTDecimalColDecimalConstVectorizedExpression(OUTPUT_INDEX, children); + break; + default: + throw new UnsupportedOperationException("Unknown compare type: " + compareType); + } + + MutableChunk chunk = buildDecimal128Chunk(); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + + LongBlock outputBlock = (LongBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); + DecimalBlock inputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(0)); + + expr.eval(evaluationContext); + + // check result + Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); + for (int i = 0; i < COUNT; i++) { + Assert.assertEquals("[" + compareType + "] Incorrect result for: " + inputBlock.getDecimal(i).toString(), + targetResult[i], outputBlock.getLong(i)); + } + } + private MutableChunk buildDecimal64Chunk() { Block[] blocks = new Block[BLOCK_COUNT]; blocks[0] = new DecimalBlock(inputDecimalType, COUNT); @@ -264,7 +312,12 @@ private MutableChunk buildDecimal64Chunk() { blocks[0] = inputBlock; Assert.assertTrue(inputBlock.isDecimal64()); - return new MutableChunk(blocks); + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setSelectionInUse(true); + chunk.setSelection(getSelection()); + } + return chunk; } private MutableChunk buildDecimal128Chunk() { @@ -316,7 +369,22 @@ private MutableChunk buildDecimal128Chunk() { blocks[0] = inputBlock; Assert.assertTrue(inputBlock.isDecimal128()); - return new MutableChunk(blocks); + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setSelectionInUse(true); + int[] selection = getSelection(); + chunk.setSelection(selection); + chunk.setBatchSize(selection.length); + } + return chunk; + } + + private int[] getSelection() { + int[] sel = new int[COUNT]; + for (int i = 0; i < COUNT; i++) { + sel[i] = i; + } + return sel; } private long genDecimal64NotOverflowLong() { diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastDecimalBetweenColLongConstLongConstTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastDecimalBetweenColLongConstLongConstTest.java new file mode 100644 index 000000000..4c8e0ddb3 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastDecimalBetweenColLongConstLongConstTest.java @@ -0,0 +1,267 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.DecimalBlock; +import com.alibaba.polardbx.executor.chunk.DecimalBlockBuilder; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.operator.BaseExecTest; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; +import com.alibaba.polardbx.executor.vectorized.build.Rex2VectorizedExpressionVisitor; +import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; +import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; +import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.type.SqlTypeName; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Random; + +/** + * Test for FastBetweenDecimalColLongConstLongConstVectorizedExpression + */ +@RunWith(Parameterized.class) +public class FastDecimalBetweenColLongConstLongConstTest extends BaseExecTest { + private final static RelDataTypeFactory TYPE_FACTORY = + new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); + private final static RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY); + private final DecimalType decimalType = new DecimalType(15, 2); + private final int COUNT = 1000; + private final int[] sel; + private final boolean withSelection; + private final int nullProb = 10; + private final Random random = new Random(); + private final Long betweenLeft; + private final Long betweenRight; + + public FastDecimalBetweenColLongConstLongConstTest(boolean withSelection, Long left, Long right) { + this.withSelection = withSelection; + this.betweenLeft = left; + this.betweenRight = right; + if (withSelection) { + final int offset = 10; + this.sel = new int[COUNT / 2]; + for (int i = 0; i < sel.length; i++) { + sel[i] = i + offset; + } + } else { + this.sel = null; + } + } + + @Parameterized.Parameters(name = "sel={0},left={1},right={2}") + public static List generateParameters() { + List list = new ArrayList<>(); + list.add(new Object[] {false, 0L, 999L}); + list.add(new Object[] {true, null, 999L}); + list.add(new Object[] {true, -999L, 0L}); + list.add(new Object[] {true, -100L, null}); + list.add(new Object[] {true, 0L, null}); + list.add(new Object[] {false, -9999L, 9999L}); + return list; + } + + @Before + public void before() { + Map params = new HashMap(); + params.put(ConnectionParams.CHUNK_SIZE.getName(), COUNT); + params.put(ConnectionParams.ENABLE_EXPRESSION_VECTORIZATION.getName(), true); + context.setParamManager(new ParamManager(params)); + } + + @Test + public void testDecimal64() { + VectorizedExpression expression = buildExpression(); + + MutableChunk preAllocatedChunk = buildDecimal64Chunk(); + DecimalBlock inputBlock = (DecimalBlock) Objects.requireNonNull(preAllocatedChunk.slotIn(0)); + LongBlock outputBlock = (LongBlock) Objects.requireNonNull(preAllocatedChunk.slotIn(3)); + + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + expression.eval(evaluationContext); + + // check actual boolean values with expected values from decimal compare. + Decimal lower; + if (betweenLeft == null) { + lower = Decimal.ZERO; + } else { + lower = Decimal.fromLong(betweenLeft); + } + Decimal upper; + if (betweenRight == null) { + upper = Decimal.ZERO; + } else { + upper = Decimal.fromLong(betweenRight); + } + + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + boolean actual = outputBlock.getLong(j) == 1 && !outputBlock.isNull(j); + boolean expected = (!inputBlock.isNull(j) + && inputBlock.getDecimal(j).compareTo(lower) >= 0 + && inputBlock.getDecimal(j).compareTo(upper) <= 0); + Assert.assertEquals(actual, expected); + } + } else { + for (int i = 0; i < COUNT; i++) { + boolean actual = outputBlock.getLong(i) == 1 && !outputBlock.isNull(i); + boolean expected = (!inputBlock.isNull(i) + && inputBlock.getDecimal(i).compareTo(lower) >= 0 + && inputBlock.getDecimal(i).compareTo(upper) <= 0); + Assert.assertEquals(actual, expected); + } + } + } + + @Test + public void testDecimal() { + VectorizedExpression expression = buildExpression(); + + MutableChunk preAllocatedChunk = buildDecimalChunk(); + DecimalBlock inputBlock = (DecimalBlock) Objects.requireNonNull(preAllocatedChunk.slotIn(0)); + LongBlock outputBlock = (LongBlock) Objects.requireNonNull(preAllocatedChunk.slotIn(3)); + + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + expression.eval(evaluationContext); + + // check actual boolean values with expected values from decimal compare. + Decimal lower; + if (betweenLeft == null) { + lower = Decimal.ZERO; + } else { + lower = Decimal.fromLong(betweenLeft); + } + Decimal upper; + if (betweenRight == null) { + upper = Decimal.ZERO; + } else { + upper = Decimal.fromLong(betweenRight); + } + + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + boolean actual = outputBlock.getLong(j) == 1 && !outputBlock.isNull(j); + boolean expected = (!inputBlock.isNull(j) + && inputBlock.getDecimal(j).compareTo(lower) >= 0 + && inputBlock.getDecimal(j).compareTo(upper) <= 0); + Assert.assertEquals(actual, expected); + } + } else { + for (int i = 0; i < COUNT; i++) { + boolean actual = outputBlock.getLong(i) == 1 && !outputBlock.isNull(i); + boolean expected = (!inputBlock.isNull(i) + && inputBlock.getDecimal(i).compareTo(lower) >= 0 + && inputBlock.getDecimal(i).compareTo(upper) <= 0); + Assert.assertEquals(actual, expected); + } + } + } + + private MutableChunk buildDecimal64Chunk() { + Block[] blocks = new Block[4]; + blocks[0] = new DecimalBlock(decimalType, COUNT); + blocks[1] = new LongBlock(DataTypes.LongType, COUNT); + blocks[2] = new LongBlock(DataTypes.LongType, COUNT); + blocks[3] = new LongBlock(DataTypes.LongType, COUNT); + + DecimalBlockBuilder inputBuilder = new DecimalBlockBuilder(COUNT, decimalType); + for (int i = 0; i < COUNT; i++) { + if (random.nextInt(COUNT) <= nullProb) { + inputBuilder.appendNull(); + } else { + long left = genDecimal64NotOverflowLong(); + inputBuilder.writeLong(left); + } + + } + DecimalBlock inputBlock = (DecimalBlock) inputBuilder.build(); + blocks[0] = inputBlock; + Assert.assertTrue(inputBlock.isDecimal64()); + + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setSelectionInUse(true); + chunk.setSelection(sel); + chunk.setBatchSize(sel.length); + } + return chunk; + } + + private MutableChunk buildDecimalChunk() { + Block[] blocks = new Block[4]; + blocks[0] = new DecimalBlock(decimalType, COUNT); + blocks[1] = new LongBlock(DataTypes.LongType, COUNT); + blocks[2] = new LongBlock(DataTypes.LongType, COUNT); + blocks[3] = new LongBlock(DataTypes.LongType, COUNT); + + DecimalBlockBuilder inputBuilder = new DecimalBlockBuilder(COUNT, decimalType); + for (int i = 0; i < COUNT; i++) { + if (random.nextInt(COUNT) <= nullProb) { + inputBuilder.appendNull(); + } else { + long left = random.nextInt(); + inputBuilder.writeDecimal(new Decimal(left, decimalType.getScale())); + } + + } + DecimalBlock inputBlock = (DecimalBlock) inputBuilder.build(); + blocks[0] = inputBlock; + Assert.assertFalse(inputBlock.isDecimal64()); + + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setSelectionInUse(true); + chunk.setSelection(sel); + chunk.setBatchSize(sel.length); + } + return chunk; + } + + private long genDecimal64NotOverflowLong() { + return random.nextInt(9999999) + 10_000_000; + } + + private VectorizedExpression buildExpression() { + List> inputTypes = ImmutableList.of(decimalType); + + RexNode root = REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), + TddlOperatorTable.BETWEEN, + ImmutableList.of( + REX_BUILDER.makeInputRef( + TYPE_FACTORY.createSqlType(SqlTypeName.DECIMAL, decimalType.getPrecision(), decimalType.getScale()), + 0), + REX_BUILDER.makeBigIntLiteral(betweenLeft), + REX_BUILDER.makeBigIntLiteral(betweenRight) + )); + + InputRefTypeChecker inputRefTypeChecker = new InputRefTypeChecker(inputTypes); + root = root.accept(inputRefTypeChecker); + + Rex2VectorizedExpressionVisitor converter = + new Rex2VectorizedExpressionVisitor(context, inputTypes.size()); + return root.accept(converter); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastInVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastInVectorizedExpressionTest.java new file mode 100644 index 000000000..61cf694d9 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastInVectorizedExpressionTest.java @@ -0,0 +1,327 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.IntegerBlock; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.chunk.SliceBlock; +import com.alibaba.polardbx.executor.chunk.SliceBlockBuilder; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InValuesVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; +import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexInputRef; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.type.SqlTypeName; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class FastInVectorizedExpressionTest { + private final static RelDataTypeFactory TYPE_FACTORY = + new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); + private final static RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY); + + private final RelDataType longRelType = TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT); + private final RelDataType intRelType = TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER); + private final RelDataType varcharRelType = TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR); + private ExecutionContext context; + + @Before + public void setUp() { + this.context = new ExecutionContext(); + } + + @Test + public void testIntInLong() { + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + long[] inValues = {1, 100, 1000}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, null, 0L, 1L, null, 1L, 0L); + + doTest(DataTypes.IntegerType, inputChunk, convertInValues(inValues, intRelType), expectBlock); + } + + @Test + public void testIntInInt() { + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + int[] inValues = {1, 100, 1000}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, null, 0L, 1L, null, 1L, 0L); + + doTest(DataTypes.IntegerType, inputChunk, convertInValues(inValues, intRelType), expectBlock); + } + + @Test + public void testIntInIntWithSelection() { + int[] sel = new int[] {0, 3, 5, 8}; + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + int[] inValues = {1, 100, 1000}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 0L, null, 0L, 1L, null, 0L, 0L); + + doTest(DataTypes.IntegerType, inputChunk, convertInValues(inValues, intRelType), expectBlock, sel); + } + + @Test + public void testLongInLong() { + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + long[] inValues = {1, 100, 1000}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, null, 0L, 1L, null, 1L, 0L); + + doTest(DataTypes.LongType, inputChunk, convertInValues(inValues, longRelType), expectBlock); + } + + @Test + public void testLongInLongWithSelection() { + int[] sel = new int[] {0, 3, 5, 8}; + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock); + long[] inValues = {1, 100, 1000}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 0L, null, 0L, 1L, null, 0L, 0L); + + doTest(DataTypes.LongType, inputChunk, convertInValues(inValues, longRelType), expectBlock, sel); + } + + @Test + public void testIntInString() { + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + String[] inValues = {"1", "100", "1000"}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, null, 0L, 1L, null, 1L, 0L); + + doTest(DataTypes.IntegerType, inputChunk, convertInValues(inValues, intRelType), expectBlock); + } + + @Test + public void testIntInStringWithAutoType() { + context.setParamManager(new ParamManager(new HashMap())); + context.getParamManager().getProps().put(ConnectionProperties.ENABLE_IN_VEC_AUTO_TYPE, "true"); + + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + String[] inValues = {"1", "100", "1000"}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, null, 0L, 1L, null, 1L, 0L); + + doTest(DataTypes.IntegerType, inputChunk, convertInValues(inValues, intRelType), expectBlock); + } + + @Test + public void testLongInString() { + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + String[] inValues = {"1", "100", "1000"}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, null, 0L, 1L, null, 1L, 0L); + + doTest(DataTypes.LongType, inputChunk, convertInValues(inValues, longRelType), expectBlock); + } + + @Test + public void testLongInStringWithAutoType() { + context.setParamManager(new ParamManager(new HashMap())); + context.getParamManager().getProps().put(ConnectionProperties.ENABLE_IN_VEC_AUTO_TYPE, "true"); + + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + String[] inValues = {"1", "100", "1000"}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, null, 0L, 1L, null, 1L, 0L); + + doTest(DataTypes.LongType, inputChunk, convertInValues(inValues, longRelType), expectBlock); + } + + @Test + public void testStringInLong() { + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + + SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, + 10, new ExecutionContext(), false); + for (int i = 0; i < longBlock.getPositionCount(); i++) { + if (longBlock.isNull(i)) { + sliceBlockBuilder.appendNull(); + } else { + sliceBlockBuilder.writeString(Long.toString(longBlock.getLong(i))); + } + } + SliceBlock sliceBlock = (SliceBlock) sliceBlockBuilder.build(); + + Chunk inputChunk = new Chunk(sliceBlock.getPositionCount(), sliceBlock); + long[] inValues = {1, 100, 1000}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, null, 0L, 1L, null, 1L, 0L); + + doTest(DataTypes.VarcharType, inputChunk, convertInValues(inValues, varcharRelType), expectBlock); + } + + @Test + public void testStringInString() { + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + + SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, + 10, new ExecutionContext(), false); + for (int i = 0; i < longBlock.getPositionCount(); i++) { + if (longBlock.isNull(i)) { + sliceBlockBuilder.appendNull(); + } else { + sliceBlockBuilder.writeString(Long.toString(longBlock.getLong(i))); + } + } + SliceBlock sliceBlock = (SliceBlock) sliceBlockBuilder.build(); + + Chunk inputChunk = new Chunk(sliceBlock.getPositionCount(), sliceBlock); + String[] inValues = {"1", "100", "1000"}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, null, 0L, 1L, null, 1L, 0L); + + doTest(DataTypes.VarcharType, inputChunk, convertInValues(inValues, varcharRelType), expectBlock); + } + + @Test + public void testStringInStringWithSelection() { + int[] sel = new int[] {0, 3, 5, 8}; + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + + SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, + 10, new ExecutionContext(), false); + for (int i = 0; i < longBlock.getPositionCount(); i++) { + if (longBlock.isNull(i)) { + sliceBlockBuilder.appendNull(); + } else { + sliceBlockBuilder.writeString(Long.toString(longBlock.getLong(i))); + } + } + SliceBlock sliceBlock = (SliceBlock) sliceBlockBuilder.build(); + + Chunk inputChunk = new Chunk(sliceBlock.getPositionCount(), sliceBlock); + String[] inValues = {"1", "100", "1000"}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 0L, null, 0L, 1L, null, 0L, 0L); + + doTest(DataTypes.VarcharType, inputChunk, convertInValues(inValues, varcharRelType), expectBlock, sel); + } + + /** + * null in (null) is null + */ + @Test + public void testLongInLongWithNull() { + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); + Long[] inValues = {1L, 100L, null}; + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, null, 0L, 0L, null, 1L, 0L); + + doTest(DataTypes.LongType, inputChunk, convertInValues(inValues, longRelType), expectBlock); + } + + private List convertInValues(long[] inValues, RelDataType dataType) { + List rexNodeList = new ArrayList<>(inValues.length + 1); + rexNodeList.add(new RexInputRef(1, dataType)); + for (long inValue : inValues) { + RexNode rexNode = REX_BUILDER.makeLiteral(inValue, + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), false); + rexNodeList.add(rexNode); + } + return rexNodeList; + } + + private List convertInValues(Long[] inValues, RelDataType dataType) { + List rexNodeList = new ArrayList<>(inValues.length + 1); + rexNodeList.add(new RexInputRef(1, dataType)); + for (Long inValue : inValues) { + RexNode rexNode = REX_BUILDER.makeLiteral(inValue, + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), false); + rexNodeList.add(rexNode); + } + return rexNodeList; + } + + private List convertInValues(int[] inValues, RelDataType dataType) { + List rexNodeList = new ArrayList<>(inValues.length + 1); + rexNodeList.add(new RexInputRef(1, dataType)); + for (long inValue : inValues) { + RexNode rexNode = REX_BUILDER.makeLiteral(inValue, + TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER), false); + rexNodeList.add(rexNode); + } + return rexNodeList; + } + + private List convertInValues(String[] inValues, RelDataType dataType) { + List rexNodeList = new ArrayList<>(inValues.length + 1); + rexNodeList.add(new RexInputRef(1, dataType)); + for (String inValue : inValues) { + RexNode rexNode = REX_BUILDER.makeLiteral(inValue, + TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR), false); + rexNodeList.add(rexNode); + } + return rexNodeList; + } + + private void doTest(DataType inputType, Chunk inputChunk, + List rexLiteralList, RandomAccessBlock expectBlock) { + doTest(inputType, inputChunk, rexLiteralList, expectBlock, null); + } + + private void doTest(DataType inputType, Chunk inputChunk, + List rexLiteralList, RandomAccessBlock expectBlock, + int[] sel) { + boolean enableInAutoTypeConvert = context.getParamManager().getBoolean(ConnectionParams.ENABLE_IN_VEC_AUTO_TYPE); + + int outputIndex = 2; + VectorizedExpression inputRef = new InputRefVectorizedExpression(inputType, 0, 0); + VectorizedExpression inValueExpr = InValuesVectorizedExpression.from(rexLiteralList, 2, enableInAutoTypeConvert); + if (enableInAutoTypeConvert) { + Assert.assertSame(((InValuesVectorizedExpression) inValueExpr).getInValueSet().getDataType(), inputType); + } + + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(inputChunk.getPositionCount()) + .addSlot((RandomAccessBlock) inputChunk.getBlock(0)) + .addSlotsByTypes(ImmutableList.of( + DataTypes.LongType, + DataTypes.LongType + )) + .withSelection(sel) + .build(); + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(outputIndex); + + VectorizedExpression inExpr = new FastInVectorizedExpression( + DataTypes.LongType, + outputIndex, + new VectorizedExpression[] { + inputRef, + inValueExpr + } + ); + inExpr.eval(evaluationContext); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + i, + resultBlock.elementAt(j), expectBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, + resultBlock.elementAt(i), expectBlock.elementAt(i)); + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/FastInVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastNotInVectorizedExpressionTest.java similarity index 68% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/FastInVectorizedExpressionTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastNotInVectorizedExpressionTest.java index 9433de7f1..7d95283b6 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/FastInVectorizedExpressionTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/FastNotInVectorizedExpressionTest.java @@ -1,4 +1,4 @@ -package com.alibaba.polardbx.executor.vectorized.comparison; +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.executor.chunk.Chunk; import com.alibaba.polardbx.executor.chunk.IntegerBlock; @@ -11,7 +11,6 @@ import com.alibaba.polardbx.executor.vectorized.InValuesVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.FastInVectorizedExpression; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; @@ -29,63 +28,85 @@ import java.util.ArrayList; import java.util.List; -public class FastInVectorizedExpressionTest { +public class FastNotInVectorizedExpressionTest { private final static RelDataTypeFactory TYPE_FACTORY = new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); private final static RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY); @Test - public void testIntInLong() { + public void testIntNotInLong() { IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); long[] inValues = {1, 100, 1000}; - LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, 0L, 0L, 1L, 0L, 1L, 0L); + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, null, 1L, 0L, null, 0L, 1L); doTest(DataTypes.IntegerType, inputChunk, convertInValues(inValues), expectBlock); } @Test - public void testIntInInt() { + public void testIntNotInInt() { IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); int[] inValues = {1, 100, 1000}; - LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, 0L, 0L, 1L, 0L, 1L, 0L); + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, null, 1L, 0L, null, 0L, 1L); doTest(DataTypes.IntegerType, inputChunk, convertInValues(inValues), expectBlock); } @Test - public void testLongInLong() { + public void testIntNotInIntWithSelection() { + int[] sel = new int[] {0, 3, 5, 8}; + IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); + Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); + int[] inValues = {1, 100, 1000}; + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, null, 1L, 0L, null, 0L, 1L); + + doTest(DataTypes.IntegerType, inputChunk, convertInValues(inValues), expectBlock, sel); + } + + @Test + public void testLongNotInLong() { LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); long[] inValues = {1, 100, 1000}; - LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, 0L, 0L, 1L, 0L, 1L, 0L); + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, null, 1L, 0L, null, 0L, 1L); doTest(DataTypes.LongType, inputChunk, convertInValues(inValues), expectBlock); } @Test - public void testIntInString() { + public void testLongNotInLongWithSelection() { + int[] sel = new int[] {0, 3, 5, 8}; + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + Chunk inputChunk = new Chunk(longBlock); + long[] inValues = {1, 100, 1000}; + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, null, 1L, 0L, null, 0L, 1L); + + doTest(DataTypes.LongType, inputChunk, convertInValues(inValues), expectBlock, sel); + } + + @Test + public void testIntNotInString() { IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); String[] inValues = {"1", "100", "1000"}; - LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, 0L, 0L, 1L, 0L, 1L, 0L); + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, null, 1L, 0L, null, 0L, 1L); doTest(DataTypes.LongType, inputChunk, convertInValues(inValues), expectBlock); } @Test - public void testLongInString() { + public void testLongNotInString() { LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); String[] inValues = {"1", "100", "1000"}; - LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, 0L, 0L, 1L, 0L, 1L, 0L); + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, null, 1L, 0L, null, 0L, 1L); doTest(DataTypes.LongType, inputChunk, convertInValues(inValues), expectBlock); } @Test - public void testStringInLong() { + public void testStringNotInLong() { LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, @@ -101,13 +122,13 @@ public void testStringInLong() { Chunk inputChunk = new Chunk(sliceBlock.getPositionCount(), sliceBlock); long[] inValues = {1, 100, 1000}; - LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, 0L, 0L, 1L, 0L, 1L, 0L); + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, null, 1L, 0L, null, 0L, 1L); doTest(DataTypes.LongType, inputChunk, convertInValues(inValues), expectBlock); } @Test - public void testStringInString() { + public void testStringNotInString() { LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, @@ -123,13 +144,36 @@ public void testStringInString() { Chunk inputChunk = new Chunk(sliceBlock.getPositionCount(), sliceBlock); String[] inValues = {"1", "100", "1000"}; - LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, 0L, 0L, 1L, 0L, 1L, 0L); + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, null, 1L, 0L, null, 0L, 1L); doTest(DataTypes.LongType, inputChunk, convertInValues(inValues), expectBlock); } @Test - public void testLongInLongWithNull() { + public void testStringNotInStringWithSelection() { + int[] sel = new int[] {0, 3, 5, 8}; + LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); + + SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, + 10, new ExecutionContext(), false); + for (int i = 0; i < longBlock.getPositionCount(); i++) { + if (longBlock.isNull(i)) { + sliceBlockBuilder.appendNull(); + } else { + sliceBlockBuilder.writeString(Long.toString(longBlock.getLong(i))); + } + } + SliceBlock sliceBlock = (SliceBlock) sliceBlockBuilder.build(); + + Chunk inputChunk = new Chunk(sliceBlock.getPositionCount(), sliceBlock); + String[] inValues = {"1", "100", "1000"}; + LongBlock expectBlock = LongBlock.of(0L, 1L, 0L, null, 1L, 0L, null, 0L, 1L); + + doTest(DataTypes.LongType, inputChunk, convertInValues(inValues), expectBlock, sel); + } + + @Test + public void testLongNotInLongWithNull() { LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); Long[] inValues = {1L, 100L, null}; @@ -184,6 +228,12 @@ private List convertInValues(String[] inValues) { private void doTest(DataType inputType, Chunk inputChunk, List rexLiteralList, RandomAccessBlock expectBlock) { + doTest(inputType, inputChunk, rexLiteralList, expectBlock, null); + } + + private void doTest(DataType inputType, Chunk inputChunk, + List rexLiteralList, RandomAccessBlock expectBlock, + int[] sel) { ExecutionContext context = new ExecutionContext(); int outputIndex = 2; @@ -196,13 +246,14 @@ private void doTest(DataType inputType, Chunk inputChunk, DataTypes.LongType, DataTypes.LongType )) + .withSelection(sel) .build(); EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); // check resultBlock RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(outputIndex); - VectorizedExpression inExpr = new FastInVectorizedExpression( + VectorizedExpression inExpr = new FastNotInVectorizedExpression( DataTypes.LongType, outputIndex, new VectorizedExpression[] { @@ -212,8 +263,17 @@ private void doTest(DataType inputType, Chunk inputChunk, ); inExpr.eval(evaluationContext); - for (int i = 0; i < inputChunk.getPositionCount(); i++) { - Assert.assertEquals(resultBlock.elementAt(i), expectBlock.elementAt(i)); + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + i, + resultBlock.elementAt(j), expectBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, + resultBlock.elementAt(i), expectBlock.elementAt(i)); + } } } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/GTDateColVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/GTDateColVectorizedExpressionTest.java new file mode 100644 index 000000000..d579c46a3 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/GTDateColVectorizedExpressionTest.java @@ -0,0 +1,225 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.common.utils.time.core.MysqlDateTime; +import com.alibaba.polardbx.common.utils.time.core.OriginalDate; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.DateBlock; +import com.alibaba.polardbx.executor.chunk.DateBlockBuilder; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.ObjectBlockBuilder; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.chunk.ReferenceBlock; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class GTDateColVectorizedExpressionTest { + + private final int count = 10; + private ExecutionContext context; + private List dateList1; + private List dateList2; + + @Before + public void before() { + this.context = new ExecutionContext(); + this.dateList1 = new ArrayList<>(count); + this.dateList2 = new ArrayList<>(count); + for (int i = 0; i < count - 1; i++) { + MysqlDateTime date = new MysqlDateTime(); + date.setYear(2024); + date.setMonth(5); + date.setDay(i + 1); + dateList1.add(date); + } + dateList1.add(null); + dateList2.add(null); + for (int i = 0; i < count - 1; i++) { + MysqlDateTime date = new MysqlDateTime(); + date.setYear(2024); + if (i % 2 == 0) { + date.setMonth(6); + } else { + date.setMonth(4); + } + date.setDay(i + 1); + dateList2.add(date); + } + } + + @Test + public void testDateDate() { + DateBlock dateBlock1 = getDateBlock1(); + DateBlock dateBlock2 = getDateBlock2(); + Chunk inputChunk = new Chunk(dateBlock1.getPositionCount(), dateBlock1, dateBlock2); + + LongBlock expectBlock = LongBlock.of(null, 0L, 1L, 0L, 1L, 0L, 1L, 0L, 1L, null); + + doTest(inputChunk, expectBlock, null); + + int[] sel = new int[] {0, 1, 2, 4, 5, 9}; + doTest(inputChunk, expectBlock, sel); + } + + @Test + public void testDateRef() { + DateBlock dateBlock1 = getDateBlock1(); + ReferenceBlock dateBlock2 = getRefBlock2(); + Chunk inputChunk = new Chunk(dateBlock1.getPositionCount(), dateBlock1, dateBlock2); + + LongBlock expectBlock = LongBlock.of(null, 0L, 1L, 0L, 1L, 0L, 1L, 0L, 1L, null); + + doTest(inputChunk, expectBlock, null); + + int[] sel = new int[] {0, 1, 2, 4, 5, 9}; + doTest(inputChunk, expectBlock, sel); + } + + @Test + public void testRefDate() { + ReferenceBlock dateBlock1 = getRefBlock1(); + DateBlock dateBlock2 = getDateBlock2(); + Chunk inputChunk = new Chunk(dateBlock1.getPositionCount(), dateBlock1, dateBlock2); + + LongBlock expectBlock = LongBlock.of(null, 0L, 1L, 0L, 1L, 0L, 1L, 0L, 1L, null); + + doTest(inputChunk, expectBlock, null); + + int[] sel = new int[] {0, 1, 2, 4, 5, 9}; + doTest(inputChunk, expectBlock, sel); + } + + @Test + public void testRefRef() { + ReferenceBlock dateBlock1 = getRefBlock1(); + ReferenceBlock dateBlock2 = getRefBlock2(); + Chunk inputChunk = new Chunk(dateBlock1.getPositionCount(), dateBlock1, dateBlock2); + + LongBlock expectBlock = LongBlock.of(null, 0L, 1L, 0L, 1L, 0L, 1L, 0L, 1L, null); + + doTest(inputChunk, expectBlock, null); + + int[] sel = new int[] {0, 1, 2, 4, 5, 9}; + doTest(inputChunk, expectBlock, sel); + } + + private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock, int[] sel) { + ExecutionContext context = new ExecutionContext(); + + GTDateColDateColVectorizedExpression condition = + new GTDateColDateColVectorizedExpression( + 3, + new VectorizedExpression[] { + new InputRefVectorizedExpression(DataTypes.DateType, 0, 0), + new InputRefVectorizedExpression(DataTypes.DateType, 1, 1), + }); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(Collections.singletonList(DataTypes.DateType)) + .addEmptySlots(Arrays.asList(DataTypes.CharType, DataTypes.CharType, DataTypes.LongType)) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputChunk.getBlockCount(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputChunk.getBlockCount(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } + + private DateBlock getDateBlock1() { + DateBlockBuilder dateBlockBuilder1 = new DateBlockBuilder(count, DataTypes.DateType, context); + for (int i = 0; i < count; i++) { + MysqlDateTime dateTime = dateList1.get(i); + if (dateTime == null) { + dateBlockBuilder1.appendNull(); + } else { + dateBlockBuilder1.writeMysqlDatetime(dateTime); + } + } + return (DateBlock) dateBlockBuilder1.build(); + } + + private DateBlock getDateBlock2() { + DateBlockBuilder dateBlockBuilder2 = new DateBlockBuilder(count, DataTypes.DateType, context); + for (int i = 0; i < count; i++) { + MysqlDateTime dateTime = dateList2.get(i); + if (dateTime == null) { + dateBlockBuilder2.appendNull(); + } else { + dateBlockBuilder2.writeMysqlDatetime(dateTime); + } + } + return (DateBlock) dateBlockBuilder2.build(); + } + + private ReferenceBlock getRefBlock1() { + ObjectBlockBuilder refBuilder1 = new ObjectBlockBuilder(count); + for (int i = 0; i < count; i++) { + MysqlDateTime dateTime = dateList1.get(i); + if (dateTime == null) { + refBuilder1.appendNull(); + } else { + refBuilder1.writeObject(new OriginalDate(dateTime)); + } + } + return (ReferenceBlock) refBuilder1.build(); + } + + private ReferenceBlock getRefBlock2() { + ObjectBlockBuilder refBuilder2 = new ObjectBlockBuilder(count); + for (int i = 0; i < count; i++) { + MysqlDateTime dateTime = dateList2.get(i); + if (dateTime == null) { + refBuilder2.appendNull(); + } else { + refBuilder2.writeObject(new OriginalDate(dateTime)); + } + } + return (ReferenceBlock) refBuilder2.build(); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/LTDateColVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/LTDateColVectorizedExpressionTest.java new file mode 100644 index 000000000..6d98f5345 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/LTDateColVectorizedExpressionTest.java @@ -0,0 +1,225 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.common.utils.time.core.MysqlDateTime; +import com.alibaba.polardbx.common.utils.time.core.OriginalDate; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.DateBlock; +import com.alibaba.polardbx.executor.chunk.DateBlockBuilder; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.ObjectBlockBuilder; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.chunk.ReferenceBlock; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class LTDateColVectorizedExpressionTest { + + private final int count = 10; + private ExecutionContext context; + private List dateList1; + private List dateList2; + + @Before + public void before() { + this.context = new ExecutionContext(); + this.dateList1 = new ArrayList<>(count); + this.dateList2 = new ArrayList<>(count); + for (int i = 0; i < count - 1; i++) { + MysqlDateTime date = new MysqlDateTime(); + date.setYear(2024); + date.setMonth(5); + date.setDay(i + 1); + dateList1.add(date); + } + dateList1.add(null); + dateList2.add(null); + for (int i = 0; i < count - 1; i++) { + MysqlDateTime date = new MysqlDateTime(); + date.setYear(2024); + if (i % 2 == 0) { + date.setMonth(6); + } else { + date.setMonth(4); + } + date.setDay(i + 1); + dateList2.add(date); + } + } + + @Test + public void testDateDate() { + DateBlock dateBlock1 = getDateBlock1(); + DateBlock dateBlock2 = getDateBlock2(); + Chunk inputChunk = new Chunk(dateBlock1.getPositionCount(), dateBlock1, dateBlock2); + + LongBlock expectBlock = LongBlock.of(null, 1L, 0L, 1L, 0L, 1L, 0L, 1L, 0L, null); + + doTest(inputChunk, expectBlock, null); + + int[] sel = new int[] {0, 1, 2, 4, 5, 9}; + doTest(inputChunk, expectBlock, sel); + } + + @Test + public void testDateRef() { + DateBlock dateBlock1 = getDateBlock1(); + ReferenceBlock dateBlock2 = getRefBlock2(); + Chunk inputChunk = new Chunk(dateBlock1.getPositionCount(), dateBlock1, dateBlock2); + + LongBlock expectBlock = LongBlock.of(null, 1L, 0L, 1L, 0L, 1L, 0L, 1L, 0L, null); + + doTest(inputChunk, expectBlock, null); + + int[] sel = new int[] {0, 1, 2, 4, 5, 9}; + doTest(inputChunk, expectBlock, sel); + } + + @Test + public void testRefDate() { + ReferenceBlock dateBlock1 = getRefBlock1(); + DateBlock dateBlock2 = getDateBlock2(); + Chunk inputChunk = new Chunk(dateBlock1.getPositionCount(), dateBlock1, dateBlock2); + + LongBlock expectBlock = LongBlock.of(null, 1L, 0L, 1L, 0L, 1L, 0L, 1L, 0L, null); + + doTest(inputChunk, expectBlock, null); + + int[] sel = new int[] {0, 1, 2, 4, 5, 9}; + doTest(inputChunk, expectBlock, sel); + } + + @Test + public void testRefRef() { + ReferenceBlock dateBlock1 = getRefBlock1(); + ReferenceBlock dateBlock2 = getRefBlock2(); + Chunk inputChunk = new Chunk(dateBlock1.getPositionCount(), dateBlock1, dateBlock2); + + LongBlock expectBlock = LongBlock.of(null, 1L, 0L, 1L, 0L, 1L, 0L, 1L, 0L, null); + + doTest(inputChunk, expectBlock, null); + + int[] sel = new int[] {0, 1, 2, 4, 5, 9}; + doTest(inputChunk, expectBlock, sel); + } + + private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock, int[] sel) { + ExecutionContext context = new ExecutionContext(); + + LTDateColDateColVectorizedExpression condition = + new LTDateColDateColVectorizedExpression( + 3, + new VectorizedExpression[] { + new InputRefVectorizedExpression(DataTypes.DateType, 0, 0), + new InputRefVectorizedExpression(DataTypes.DateType, 1, 1), + }); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(Collections.singletonList(DataTypes.DateType)) + .addEmptySlots(Arrays.asList(DataTypes.CharType, DataTypes.CharType, DataTypes.LongType)) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputChunk.getBlockCount(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputChunk.getBlockCount(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } + + private DateBlock getDateBlock1() { + DateBlockBuilder dateBlockBuilder1 = new DateBlockBuilder(count, DataTypes.DateType, context); + for (int i = 0; i < count; i++) { + MysqlDateTime dateTime = dateList1.get(i); + if (dateTime == null) { + dateBlockBuilder1.appendNull(); + } else { + dateBlockBuilder1.writeMysqlDatetime(dateTime); + } + } + return (DateBlock) dateBlockBuilder1.build(); + } + + private DateBlock getDateBlock2() { + DateBlockBuilder dateBlockBuilder2 = new DateBlockBuilder(count, DataTypes.DateType, context); + for (int i = 0; i < count; i++) { + MysqlDateTime dateTime = dateList2.get(i); + if (dateTime == null) { + dateBlockBuilder2.appendNull(); + } else { + dateBlockBuilder2.writeMysqlDatetime(dateTime); + } + } + return (DateBlock) dateBlockBuilder2.build(); + } + + private ReferenceBlock getRefBlock1() { + ObjectBlockBuilder refBuilder1 = new ObjectBlockBuilder(count); + for (int i = 0; i < count; i++) { + MysqlDateTime dateTime = dateList1.get(i); + if (dateTime == null) { + refBuilder1.appendNull(); + } else { + refBuilder1.writeObject(new OriginalDate(dateTime)); + } + } + return (ReferenceBlock) refBuilder1.build(); + } + + private ReferenceBlock getRefBlock2() { + ObjectBlockBuilder refBuilder2 = new ObjectBlockBuilder(count); + for (int i = 0; i < count; i++) { + MysqlDateTime dateTime = dateList2.get(i); + if (dateTime == null) { + refBuilder2.appendNull(); + } else { + refBuilder2.writeObject(new OriginalDate(dateTime)); + } + } + return (ReferenceBlock) refBuilder2.build(); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/LikeVarcharColCharConstVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/LikeVarcharColCharConstVectorizedExpressionTest.java index 9dbaca35d..4cc620391 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/LikeVarcharColCharConstVectorizedExpressionTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/LikeVarcharColCharConstVectorizedExpressionTest.java @@ -10,14 +10,17 @@ import com.alibaba.polardbx.executor.chunk.ReferenceBlock; import com.alibaba.polardbx.executor.chunk.SliceBlock; import com.alibaba.polardbx.executor.chunk.SliceBlockBuilder; +import com.alibaba.polardbx.executor.operator.scan.impl.LocalBlockDictionary; import com.alibaba.polardbx.executor.vectorized.EvaluationContext; import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.LikeVarcharColCharConstVectorizedExpression; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.datatype.SliceType; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import io.airlift.slice.Slice; import io.airlift.slice.Slices; import org.junit.Assert; import org.junit.Before; @@ -28,20 +31,81 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.TreeMap; @RunWith(Parameterized.class) public class LikeVarcharColCharConstVectorizedExpressionTest { + private final boolean ossCompatible; private final int count = 10; + /** + * two types of strings arrays with different cardinality + */ private final String[] strs = new String[] { "abc", "aabbcc", "acb", "bacdabc", "zxcvb", "aaabccccdd", "ccbbaacb", "a1b1c1", "a比c", null}; - private ExecutionContext context; + + private final String[] dictStrs = new String[] { + "abc", "aabbcc", "abc", "aabbcc", "abc", + "aabbcc", "ccbbaacb", "abc", "a比c", null}; + private final ExecutionContext context; + private final LocalBlockDictionary dictionary1; + private final int[] dictIds1; + private final LocalBlockDictionary dictionary2; + private final int[] dictIds2; + private final boolean[] nulls; public LikeVarcharColCharConstVectorizedExpressionTest(boolean ossCompatible) { + this.ossCompatible = ossCompatible; this.context = new ExecutionContext(); context.getParamManager().getProps().put("ENABLE_OSS_COMPATIBLE", Boolean.toString(ossCompatible)); + + this.dictIds1 = new int[count]; + this.dictIds2 = new int[count]; + this.nulls = new boolean[count]; + + BiMap map1 = getDictMap(strs); + BiMap map2 = getDictMap(dictStrs); + List slices1 = new ArrayList<>(); + List slices2 = new ArrayList<>(); + for (int i = 0; i < map1.size(); i++) { + slices1.add(Slices.utf8Slice(map1.inverse().get(i))); + } + for (int i = 0; i < map2.size(); i++) { + slices2.add(Slices.utf8Slice(map2.inverse().get(i))); + } + for (int i = 0; i < count; i++) { + if (strs[i] != null) { + dictIds1[i] = map1.get(strs[i]); + nulls[i] = false; + } else { + dictIds1[i] = -1; + nulls[i] = true; + } + if (dictStrs[i] != null) { + dictIds2[i] = map2.get(dictStrs[i]); + nulls[i] = false; + } else { + dictIds2[i] = -1; + nulls[i] = true; + } + } + this.dictionary1 = new LocalBlockDictionary(slices1.toArray(new Slice[0])); + this.dictionary2 = new LocalBlockDictionary(slices2.toArray(new Slice[0])); + } + + private static BiMap getDictMap(String[] strs) { + BiMap dictMap = HashBiMap.create(); + int id = 0; + for (String str : strs) { + if (str != null && !dictMap.containsKey(str)) { + dictMap.put(str, id++); + } + } + return dictMap; } @Parameterized.Parameters(name = "ossCompatible={0}") @@ -76,6 +140,25 @@ public void testSliceWithLatin1Match() { doTest(inputChunk, expectBlock, "%abc%", null); } + @Test + public void testDictWithLatin1Match() { + SliceBlock sliceBlock1 = new SliceBlock(new SliceType(CollationName.LATIN1_BIN), 0, count, + nulls, dictionary1, dictIds1, ossCompatible); + Chunk inputChunk1 = new Chunk(sliceBlock1.getPositionCount(), sliceBlock1); + + LongBlock expectBlock1 = LongBlock.of(1L, 0L, 0L, 1L, 0L, 1L, 0L, 0L, 0L, null); + + doTest(inputChunk1, expectBlock1, "%abc%", null); + + SliceBlock sliceBlock2 = new SliceBlock(new SliceType(CollationName.LATIN1_BIN), 0, count, + nulls, dictionary2, dictIds2, ossCompatible); + Chunk inputChunk2 = new Chunk(sliceBlock2.getPositionCount(), sliceBlock2); + + LongBlock expectBlock2 = LongBlock.of(1L, 0L, 1L, 0L, 1L, 0L, 0L, 1L, 0L, null); + + doTest(inputChunk2, expectBlock2, "%abc%", null); + } + @Test public void testSliceWithLatin1SubStrMatch() { SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(new SliceType(), count, context, true); @@ -131,6 +214,25 @@ public void testSliceWithLatin1SubStrMatch3() { doTest(inputChunk, expectBlock, "%aaa%", sel); } + @Test + public void testDictWithLatin1SubStrMatch3() { + SliceBlock sliceBlock1 = new SliceBlock(new SliceType(CollationName.LATIN1_BIN), 0, count, + nulls, dictionary1, dictIds1, ossCompatible); + Chunk inputChunk1 = new Chunk(sliceBlock1.getPositionCount(), sliceBlock1); + + LongBlock expectBlock1 = LongBlock.of(0L, 1L, 0L, 0L, 0L, 1L, 1L, 0L, 0L, null); + + doTest(inputChunk1, expectBlock1, "%aa%", null); + + SliceBlock sliceBlock2 = new SliceBlock(new SliceType(CollationName.LATIN1_BIN), 0, count, + nulls, dictionary2, dictIds2, ossCompatible); + Chunk inputChunk2 = new Chunk(sliceBlock2.getPositionCount(), sliceBlock2); + + LongBlock expectBlock2 = LongBlock.of(0L, 1L, 0L, 1L, 0L, 1L, 1L, 0L, 0L, null); + + doTest(inputChunk2, expectBlock2, "%aa%", null); + } + @Test public void testSliceWithSubStrMatch() { SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(new SliceType(), count, context, true); @@ -150,7 +252,7 @@ public void testSliceWithSubStrMatch() { } @Test - public void testSliceWitWildcardMatch() { + public void testSliceWithWildcardMatch() { SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(new SliceType(), count, context, true); for (String s : strs) { if (s == null) { @@ -167,6 +269,25 @@ public void testSliceWitWildcardMatch() { doTest(inputChunk, expectBlock, "%a_c%", null); } + @Test + public void testDictWithWildcardMatch() { + SliceBlock sliceBlock1 = new SliceBlock(new SliceType(), 0, count, + nulls, dictionary1, dictIds1, ossCompatible); + Chunk inputChunk1 = new Chunk(sliceBlock1.getPositionCount(), sliceBlock1); + + LongBlock expectBlock1 = LongBlock.of(1L, 0L, 0L, 1L, 0L, 1L, 1L, 0L, 1L, null); + + doTest(inputChunk1, expectBlock1, "%a_c%", null); + + SliceBlock sliceBlock2 = new SliceBlock(new SliceType(), 0, count, + nulls, dictionary2, dictIds2, ossCompatible); + Chunk inputChunk2 = new Chunk(sliceBlock2.getPositionCount(), sliceBlock2); + + LongBlock expectBlock2 = LongBlock.of(1L, 0L, 1L, 0L, 1L, 0L, 1L, 1L, 1L, null); + + doTest(inputChunk2, expectBlock2, "%a_c%", null); + } + @Test public void testSliceWithSuffixMatch() { SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(new SliceType(), count, context, true); @@ -185,6 +306,25 @@ public void testSliceWithSuffixMatch() { doTest(inputChunk, expectBlock, "%abc", null); } + @Test + public void testDictWithSuffixMatch() { + SliceBlock sliceBlock1 = new SliceBlock(new SliceType(), 0, count, + nulls, dictionary1, dictIds1, ossCompatible); + Chunk inputChunk1 = new Chunk(sliceBlock1.getPositionCount(), sliceBlock1); + + LongBlock expectBlock1 = LongBlock.of(1L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk1, expectBlock1, "%abc", null); + + SliceBlock sliceBlock2 = new SliceBlock(new SliceType(), 0, count, + nulls, dictionary2, dictIds2, ossCompatible); + Chunk inputChunk2 = new Chunk(sliceBlock2.getPositionCount(), sliceBlock2); + + LongBlock expectBlock2 = LongBlock.of(1L, 0L, 1L, 0L, 1L, 0L, 0L, 1L, 0L, null); + + doTest(inputChunk2, expectBlock2, "%abc", null); + } + @Test public void testSliceWithSuffixMatchAndSelection() { int[] sel = new int[] {0, 1, 2, 3, 4, 5, 8, 9}; @@ -204,6 +344,102 @@ public void testSliceWithSuffixMatchAndSelection() { doTest(inputChunk, expectBlock, "%abc", sel); } + @Test + public void testDictWithSuffixMatchAndSelection() { + int[] sel = new int[] {0, 1, 2, 3, 4, 5, 8, 9}; + SliceBlock sliceBlock1 = new SliceBlock(new SliceType(), 0, count, + nulls, dictionary1, dictIds1, ossCompatible); + Chunk inputChunk1 = new Chunk(sliceBlock1.getPositionCount(), sliceBlock1); + + LongBlock expectBlock1 = LongBlock.of(1L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk1, expectBlock1, "%abc", null); + + SliceBlock sliceBlock2 = new SliceBlock(new SliceType(), 0, count, + nulls, dictionary2, dictIds2, ossCompatible); + Chunk inputChunk2 = new Chunk(sliceBlock2.getPositionCount(), sliceBlock2); + + LongBlock expectBlock2 = LongBlock.of(1L, 0L, 1L, 0L, 1L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk2, expectBlock2, "%abc", sel); + } + + @Test + public void testSliceWithPrefixMatch() { + SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(new SliceType(), count, context, true); + for (String s : strs) { + if (s == null) { + sliceBlockBuilder.appendNull(); + } else { + sliceBlockBuilder.writeString(s); + } + } + SliceBlock sliceBlock = (SliceBlock) sliceBlockBuilder.build(); + Chunk inputChunk = new Chunk(sliceBlock.getPositionCount(), sliceBlock); + + LongBlock expectBlock = LongBlock.of(1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk, expectBlock, "abc%", null); + } + + @Test + public void testDictWithPrefixMatch() { + SliceBlock sliceBlock1 = new SliceBlock(new SliceType(), 0, count, + nulls, dictionary1, dictIds1, ossCompatible); + Chunk inputChunk1 = new Chunk(sliceBlock1.getPositionCount(), sliceBlock1); + + LongBlock expectBlock1 = LongBlock.of(1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk1, expectBlock1, "abc%", null); + + SliceBlock sliceBlock2 = new SliceBlock(new SliceType(), 0, count, + nulls, dictionary2, dictIds2, ossCompatible); + Chunk inputChunk2 = new Chunk(sliceBlock2.getPositionCount(), sliceBlock2); + + LongBlock expectBlock2 = LongBlock.of(1L, 0L, 1L, 0L, 1L, 0L, 0L, 1L, 0L, null); + + doTest(inputChunk2, expectBlock2, "abc%", null); + } + + @Test + public void testSliceWithPrefixMatchAndSelection() { + int[] sel = new int[] {0, 1, 2, 3, 4, 5, 8, 9}; + SliceBlockBuilder sliceBlockBuilder = new SliceBlockBuilder(new SliceType(), count, context, true); + for (String s : strs) { + if (s == null) { + sliceBlockBuilder.appendNull(); + } else { + sliceBlockBuilder.writeString(s); + } + } + SliceBlock sliceBlock = (SliceBlock) sliceBlockBuilder.build(); + Chunk inputChunk = new Chunk(sliceBlock.getPositionCount(), sliceBlock); + + LongBlock expectBlock = LongBlock.of(1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk, expectBlock, "abc%", sel); + } + + @Test + public void testDictWithPrefixMatchAndSelection() { + int[] sel = new int[] {0, 1, 2, 3, 4, 5, 8, 9}; + SliceBlock sliceBlock1 = new SliceBlock(new SliceType(), 0, count, + nulls, dictionary1, dictIds1, ossCompatible); + Chunk inputChunk1 = new Chunk(sliceBlock1.getPositionCount(), sliceBlock1); + + LongBlock expectBlock1 = LongBlock.of(1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, null); + + doTest(inputChunk1, expectBlock1, "abc%", null); + + SliceBlock sliceBlock2 = new SliceBlock(new SliceType(), 0, count, + nulls, dictionary2, dictIds2, ossCompatible); + Chunk inputChunk2 = new Chunk(sliceBlock2.getPositionCount(), sliceBlock2); + + LongBlock expectBlock2 = LongBlock.of(1L, 0L, 1L, 0L, 1L, 0L, 0L, 1L, 0L, null); + + doTest(inputChunk2, expectBlock2, "abc%", sel); + } + @Test public void testRef() { ObjectBlockBuilder objectBlockBuilder = new ObjectBlockBuilder(count); diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/NEVarcharColCharConstVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/NEVarcharColCharConstVectorizedExpressionTest.java new file mode 100644 index 000000000..ad5dc9952 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/NEVarcharColCharConstVectorizedExpressionTest.java @@ -0,0 +1,255 @@ +package com.alibaba.polardbx.executor.vectorized.compare; + +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; +import com.alibaba.polardbx.executor.chunk.SliceBlock; +import com.alibaba.polardbx.executor.chunk.SliceBlockBuilder; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; +import com.alibaba.polardbx.executor.vectorized.build.Rex2VectorizedExpressionVisitor; +import com.alibaba.polardbx.executor.vectorized.build.VectorizedExpressionBuilder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; +import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; +import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.type.SqlTypeName; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@RunWith(Parameterized.class) +public class NEVarcharColCharConstVectorizedExpressionTest { + private final static RelDataTypeFactory TYPE_FACTORY = + new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); + private final static RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY); + private final int count = 10; + private final boolean enableCompatible; + private ExecutionContext context; + + public NEVarcharColCharConstVectorizedExpressionTest(boolean compatible) { + this.enableCompatible = compatible; + } + + @Before + public void before() { + context = new ExecutionContext(); + context.getParamManager().getProps().put("ENABLE_OSS_COMPATIBLE", String.valueOf(enableCompatible)); + } + + @Parameterized.Parameters(name = "compatible={0}") + public static List generateParameters() { + List list = new ArrayList<>(); + list.add(new Object[] {false}); + list.add(new Object[] {true}); + return list; + } + + @Test + public void testSlice() { + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, null); + + doTest(inputChunk, expectBlock, "100", null); + } + + @Test + public void testSliceWithSelection() { + + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, null); + + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTest(inputChunk, expectBlock, "100", sel); + } + + @Test + public void testNull() { + + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null, null); + + doTestNull(inputChunk, expectBlock, null); + } + + @Test + public void testWithSelectionNull() { + + SliceBlockBuilder blockBuilder = new SliceBlockBuilder(DataTypes.VarcharType, count, context, enableCompatible); + for (int i = 0; i < count - 1; i++) { + blockBuilder.writeString(String.valueOf(i * 100)); + } + blockBuilder.appendNull(); + SliceBlock sliceBlock = (SliceBlock) blockBuilder.build(); + Chunk inputChunk = new Chunk(count, sliceBlock); + + LongBlock expectBlock = LongBlock.of(null, null, null, null, null, null, null, null, null, null); + + int[] sel = new int[] {0, 1, 2, 4, 5}; + doTestNull(inputChunk, expectBlock, sel); + } + + private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock, String value, int[] sel) { + // rex node is "=(varchar ref, char const)" + RexNode rexNode = REX_BUILDER.makeCall( + TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), + TddlOperatorTable.NOT_EQUALS, + ImmutableList.of( + REX_BUILDER.makeInputRef(TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR), 0), + REX_BUILDER.makeLiteral(value, TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR), false) + )); + + List> inputTypes = ImmutableList.of(DataTypes.VarcharType); + + RexNode root = VectorizedExpressionBuilder.rewriteRoot(rexNode, true); + + InputRefTypeChecker inputRefTypeChecker = new InputRefTypeChecker(inputTypes); + root = root.accept(inputRefTypeChecker); + + Rex2VectorizedExpressionVisitor converter = + new Rex2VectorizedExpressionVisitor(context, inputTypes.size()); + VectorizedExpression condition = root.accept(converter); + + Assert.assertTrue(condition instanceof NEVarcharColCharConstVectorizedExpression); + + // Data types of intermediate results or final results. + List> filterOutputTypes = converter.getOutputDataTypes(); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(inputTypes) + .addEmptySlots(filterOutputTypes) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .addLiteralBitmap(converter.getLiteralBitmap()) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputTypes.size(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputTypes.size(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } + + private void doTestNull(Chunk inputChunk, RandomAccessBlock expectBlock, int[] sel) { + NEVarcharColCharConstVectorizedExpression condition = new NEVarcharColCharConstVectorizedExpression( + 2, + new VectorizedExpression[] { + new InputRefVectorizedExpression(DataTypes.VarcharType, 0, 0), + new LiteralVectorizedExpression(DataTypes.VarcharType, null, 1) + }); + + // placeholder for input and output blocks + MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) + .addEmptySlots(Collections.singletonList(DataTypes.VarcharType)) + .addEmptySlots(Arrays.asList(DataTypes.CharType, DataTypes.LongType)) + .addChunkLimit(context.getExecutorChunkLimit()) + .addOutputIndexes(new int[] {condition.getOutputIndex()}) + .build(); + + preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputChunk.getBlockCount(), false); + + // Prepare selection array for evaluation. + if (sel != null) { + preAllocatedChunk.setBatchSize(sel.length); + preAllocatedChunk.setSelection(sel); + preAllocatedChunk.setSelectionInUse(true); + } else { + preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); + preAllocatedChunk.setSelection(null); + preAllocatedChunk.setSelectionInUse(false); + } + + for (int i = 0; i < inputChunk.getBlockCount(); i++) { + Block block = inputChunk.getBlock(i); + preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); + } + + // Do evaluation + EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); + condition.eval(evaluationContext); + + // check resultBlock + RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); + + if (sel != null) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Failed at pos: " + j, expectBlock.elementAt(j), resultBlock.elementAt(j)); + } + } else { + for (int i = 0; i < inputChunk.getPositionCount(); i++) { + Assert.assertEquals("Failed at pos: " + i, expectBlock.elementAt(i), resultBlock.elementAt(i)); + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/NullTestOperatorsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/NullTestOperatorsTest.java similarity index 98% rename from polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/NullTestOperatorsTest.java rename to polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/NullTestOperatorsTest.java index 610d7e31a..a5fc6f938 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/NullTestOperatorsTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/compare/NullTestOperatorsTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.alibaba.polardbx.executor.vectorized.comparison; +package com.alibaba.polardbx.executor.vectorized.compare; import com.alibaba.polardbx.executor.chunk.Block; import com.alibaba.polardbx.executor.vectorized.BaseProjectionTest; diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/EQIntegerColCharConstVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/EQIntegerColCharConstVectorizedExpressionTest.java deleted file mode 100644 index fbf1df67d..000000000 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/EQIntegerColCharConstVectorizedExpressionTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.alibaba.polardbx.executor.vectorized.comparison; - -import com.alibaba.polardbx.executor.chunk.Block; -import com.alibaba.polardbx.executor.chunk.Chunk; -import com.alibaba.polardbx.executor.chunk.IntegerBlock; -import com.alibaba.polardbx.executor.chunk.LongBlock; -import com.alibaba.polardbx.executor.chunk.MutableChunk; -import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; -import com.alibaba.polardbx.executor.vectorized.EvaluationContext; -import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; -import com.alibaba.polardbx.executor.vectorized.build.Rex2VectorizedExpressionVisitor; -import com.alibaba.polardbx.executor.vectorized.build.VectorizedExpressionBuilder; -import com.alibaba.polardbx.executor.vectorized.compare.EQIntegerColCharConstVectorizedExpression; -import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; -import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; -import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; -import com.alibaba.polardbx.optimizer.core.datatype.DataType; -import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; -import com.google.common.collect.ImmutableList; -import org.apache.calcite.rel.type.RelDataTypeFactory; -import org.apache.calcite.rex.RexBuilder; -import org.apache.calcite.rex.RexNode; -import org.apache.calcite.sql.type.SqlTypeName; -import org.junit.Assert; -import org.junit.Test; - -import java.util.List; -import java.util.Objects; - -public class EQIntegerColCharConstVectorizedExpressionTest { - private final static RelDataTypeFactory TYPE_FACTORY = - new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); - private final static RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY); - - @Test - public void test() { - - IntegerBlock integerBlock = IntegerBlock.of(1, 2, 100, null, 200, 1000, null, 100, -1000); - Chunk inputChunk = new Chunk(integerBlock.getPositionCount(), integerBlock); - - LongBlock expectBlock = LongBlock.of(0L, 0L, 1L, null, 0L, 0L, null, 1L, 0L); - - doTest(inputChunk, expectBlock); - } - - private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock) { - ExecutionContext context = new ExecutionContext(); - - // rex node is "=(int ref, char const)" - RexNode rexNode = REX_BUILDER.makeCall( - TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), - TddlOperatorTable.EQUALS, - ImmutableList.of( - REX_BUILDER.makeInputRef(TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER), 0), - REX_BUILDER.makeLiteral("100", TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR), true) - )); - - List> inputTypes = ImmutableList.of(DataTypes.IntegerType); - - RexNode root = VectorizedExpressionBuilder.rewriteRoot(rexNode, true); - - InputRefTypeChecker inputRefTypeChecker = new InputRefTypeChecker(inputTypes); - root = root.accept(inputRefTypeChecker); - - Rex2VectorizedExpressionVisitor converter = - new Rex2VectorizedExpressionVisitor(context, inputTypes.size()); - VectorizedExpression condition = root.accept(converter); - - Assert.assertTrue(condition instanceof EQIntegerColCharConstVectorizedExpression); - - // Data types of intermediate results or final results. - List> filterOutputTypes = converter.getOutputDataTypes(); - - // placeholder for input and output blocks - MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) - .addEmptySlots(inputTypes) - .addEmptySlots(filterOutputTypes) - .addChunkLimit(context.getExecutorChunkLimit()) - .addOutputIndexes(new int[] {condition.getOutputIndex()}) - .addLiteralBitmap(converter.getLiteralBitmap()) - .build(); - - preAllocatedChunk.setSelectionInUse(false); - preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputTypes.size(), false); - - // Prepare selection array for evaluation. - preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); - preAllocatedChunk.setSelection(null); - preAllocatedChunk.setSelectionInUse(false); - - for (int i = 0; i < inputTypes.size(); i++) { - Block block = inputChunk.getBlock(i); - preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); - } - - // Do evaluation - EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); - condition.eval(evaluationContext); - - // check resultBlock - RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); - - for (int i = 0; i < inputChunk.getPositionCount(); i++) { - Assert.assertTrue(Objects.equals( - resultBlock.elementAt(i), expectBlock.elementAt(i) - )); - } - } -} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/EQLongColCharConstVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/EQLongColCharConstVectorizedExpressionTest.java deleted file mode 100644 index 33d7627cf..000000000 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/comparison/EQLongColCharConstVectorizedExpressionTest.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.alibaba.polardbx.executor.vectorized.comparison; - -import com.alibaba.polardbx.executor.chunk.Block; -import com.alibaba.polardbx.executor.chunk.Chunk; -import com.alibaba.polardbx.executor.chunk.LongBlock; -import com.alibaba.polardbx.executor.chunk.MutableChunk; -import com.alibaba.polardbx.executor.chunk.RandomAccessBlock; -import com.alibaba.polardbx.executor.vectorized.EvaluationContext; -import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; -import com.alibaba.polardbx.executor.vectorized.build.Rex2VectorizedExpressionVisitor; -import com.alibaba.polardbx.executor.vectorized.build.VectorizedExpressionBuilder; -import com.alibaba.polardbx.executor.vectorized.compare.EQLongColCharConstVectorizedExpression; -import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; -import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; -import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; -import com.alibaba.polardbx.optimizer.core.datatype.DataType; -import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; -import com.google.common.collect.ImmutableList; -import org.apache.calcite.rel.type.RelDataTypeFactory; -import org.apache.calcite.rex.RexBuilder; -import org.apache.calcite.rex.RexNode; -import org.apache.calcite.sql.type.SqlTypeName; -import org.junit.Assert; -import org.junit.Test; - -import java.util.List; -import java.util.Objects; - -public class EQLongColCharConstVectorizedExpressionTest { - private final static RelDataTypeFactory TYPE_FACTORY = - new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); - private final static RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY); - - @Test - public void test() { - - LongBlock longBlock = LongBlock.of(1L, 2L, 100L, null, 200L, 1000L, null, 100L, -1000L); - Chunk inputChunk = new Chunk(longBlock.getPositionCount(), longBlock); - - LongBlock expectBlock = LongBlock.of(0L, 0L, 1L, null, 0L, 0L, null, 1L, 0L); - - doTest(inputChunk, expectBlock); - } - - private void doTest(Chunk inputChunk, RandomAccessBlock expectBlock) { - ExecutionContext context = new ExecutionContext(); - - // rex node is "=(int ref, char const)" - RexNode rexNode = REX_BUILDER.makeCall( - TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), - TddlOperatorTable.EQUALS, - ImmutableList.of( - REX_BUILDER.makeInputRef(TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), 0), - REX_BUILDER.makeLiteral("100", TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR), true) - )); - - List> inputTypes = ImmutableList.of(DataTypes.LongType); - - RexNode root = VectorizedExpressionBuilder.rewriteRoot(rexNode, true); - - InputRefTypeChecker inputRefTypeChecker = new InputRefTypeChecker(inputTypes); - root = root.accept(inputRefTypeChecker); - - Rex2VectorizedExpressionVisitor converter = - new Rex2VectorizedExpressionVisitor(context, inputTypes.size()); - VectorizedExpression condition = root.accept(converter); - - Assert.assertTrue(condition instanceof EQLongColCharConstVectorizedExpression); - - // Data types of intermediate results or final results. - List> filterOutputTypes = converter.getOutputDataTypes(); - - // placeholder for input and output blocks - MutableChunk preAllocatedChunk = MutableChunk.newBuilder(context.getExecutorChunkLimit()) - .addEmptySlots(inputTypes) - .addEmptySlots(filterOutputTypes) - .addChunkLimit(context.getExecutorChunkLimit()) - .addOutputIndexes(new int[] {condition.getOutputIndex()}) - .addLiteralBitmap(converter.getLiteralBitmap()) - .build(); - - preAllocatedChunk.setSelectionInUse(false); - preAllocatedChunk.reallocate(inputChunk.getPositionCount(), inputTypes.size(), false); - - // Prepare selection array for evaluation. - preAllocatedChunk.setBatchSize(inputChunk.getPositionCount()); - preAllocatedChunk.setSelection(null); - preAllocatedChunk.setSelectionInUse(false); - - for (int i = 0; i < inputTypes.size(); i++) { - Block block = inputChunk.getBlock(i); - preAllocatedChunk.setSlotAt(block.cast(RandomAccessBlock.class), i); - } - - // Do evaluation - EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); - condition.eval(evaluationContext); - - // check resultBlock - RandomAccessBlock resultBlock = preAllocatedChunk.slotIn(condition.getOutputIndex()); - - for (int i = 0; i < inputChunk.getPositionCount(); i++) { - Assert.assertTrue(Objects.equals( - resultBlock.elementAt(i), expectBlock.elementAt(i) - )); - } - } -} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/convert/CastExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/convert/CastExpressionTest.java new file mode 100644 index 000000000..0cd57cec3 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/convert/CastExpressionTest.java @@ -0,0 +1,584 @@ +package com.alibaba.polardbx.executor.vectorized.convert; + +import com.alibaba.polardbx.common.datatype.Decimal; +import com.alibaba.polardbx.common.datatype.DecimalConverter; +import com.alibaba.polardbx.common.datatype.FastDecimalUtils; +import com.alibaba.polardbx.executor.chunk.DecimalBlock; +import com.alibaba.polardbx.executor.chunk.DecimalBlockBuilder; +import com.alibaba.polardbx.executor.chunk.DoubleBlock; +import com.alibaba.polardbx.executor.chunk.DoubleBlockBuilder; +import com.alibaba.polardbx.executor.chunk.FloatBlock; +import com.alibaba.polardbx.executor.chunk.FloatBlockBuilder; +import com.alibaba.polardbx.executor.chunk.LongBlock; +import com.alibaba.polardbx.executor.chunk.MutableChunk; +import com.alibaba.polardbx.executor.chunk.ObjectBlockBuilder; +import com.alibaba.polardbx.executor.chunk.ReferenceBlock; +import com.alibaba.polardbx.executor.chunk.ULongBlock; +import com.alibaba.polardbx.executor.chunk.ULongBlockBuilder; +import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; +import io.airlift.slice.Slices; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +@RunWith(Parameterized.class) +public class CastExpressionTest { + + private final int count = 1024; + private final boolean withSelection; + private final int[] sel; + private final int positionCount; + private final Random random; + private ExecutionContext executionContext; + + public CastExpressionTest(boolean withSelection) { + this.random = new Random(); + this.withSelection = withSelection; + if (withSelection) { + this.sel = new int[count / 2]; + for (int i = 0; i < sel.length; i++) { + this.sel[i] = i * 2; + } + this.positionCount = sel.length; + } else { + this.sel = null; + this.positionCount = count; + } + } + + @Parameterized.Parameters(name = "sel={0}") + public static List generateParameters() { + List list = new ArrayList<>(); + list.add(new Object[] {false}); + list.add(new Object[] {true}); + + return list; + } + + @Before + public void before() { + this.executionContext = new ExecutionContext(); + } + + @Test + public void testLongToDec64() { + final DataType outputType = new DecimalType(16, 2); + final long value = 1234567L; + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new LiteralVectorizedExpression(DataTypes.LongType, value, 0); + CastLongConstToDecimalVectorizedExpression expr = + new CastLongConstToDecimalVectorizedExpression(outputType, 1, children); + LongBlock longBlock = new LongBlock(DataTypes.LongType, count); + DecimalBlock outputBlock = new DecimalBlock(outputType, count); + MutableChunk chunk = new MutableChunk(longBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + Assert.assertTrue(outputBlock.isDecimal64()); + if (!withSelection) { + for (int i = 0; i < positionCount; i++) { + // since scale is 2 + Assert.assertEquals(value * 100, outputBlock.getLong(i)); + } + } else { + for (int i = 0; i < positionCount; i++) { + int j = sel[i]; + // since scale is 2 + Assert.assertEquals(value * 100, outputBlock.getLong(j)); + } + } + } + + /** + * scale is overflow the max power of 10 + */ + @Test + public void testLongToDecOverflow1() { + final DataType outputType = new DecimalType(32, 11); + final long value = 123456789101L; + final Decimal decimal = new Decimal(value, 0); + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new LiteralVectorizedExpression(DataTypes.LongType, value, 0); + CastLongConstToDecimalVectorizedExpression expr = + new CastLongConstToDecimalVectorizedExpression(outputType, 1, children); + LongBlock longBlock = new LongBlock(DataTypes.LongType, count); + DecimalBlock outputBlock = new DecimalBlock(outputType, count); + MutableChunk chunk = new MutableChunk(longBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + Assert.assertFalse(outputBlock.isDecimal64()); + Assert.assertTrue(outputBlock.getState().isNormal()); + + if (!withSelection) { + for (int i = 0; i < positionCount; i++) { + Decimal actual = outputBlock.getDecimal(i); + // since scale is 2 + Assert.assertEquals("Actual output is: " + actual, 0, + FastDecimalUtils.compare(decimal.getDecimalStructure(), + actual.getDecimalStructure())); + } + } else { + for (int i = 0; i < positionCount; i++) { + int j = sel[i]; + Decimal actual = outputBlock.getDecimal(j); + // since scale is 2 + Assert.assertEquals("Actual output is: " + actual, 0, + FastDecimalUtils.compare(decimal.getDecimalStructure(), + actual.getDecimalStructure())); + } + } + } + + @Test + public void testDecimalToDecimal() { + final DecimalType fromDecimalType = new DecimalType(18, 4); + final DecimalType toDecimalType = new DecimalType(18, 2); + DecimalBlockBuilder builder = new DecimalBlockBuilder(count, fromDecimalType); + Decimal[] result = new Decimal[count]; + for (int i = 0; i < count; i++) { + int val = random.nextInt(); + Decimal decimal = new Decimal(val, fromDecimalType.getScale()); + Decimal expectResult = new Decimal(); + DecimalConverter.rescale(decimal.getDecimalStructure(), expectResult.getDecimalStructure(), + toDecimalType.getPrecision(), toDecimalType.getScale(), false); + result[i] = expectResult; + builder.writeDecimal(decimal); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(fromDecimalType, 0, 0); + CastDecimalToDecimalVectorizedExpression expr = + new CastDecimalToDecimalVectorizedExpression(toDecimalType, 1, children); + DecimalBlock inputBlock = (DecimalBlock) builder.build(); + DecimalBlock outputBlock = new DecimalBlock(toDecimalType, count); + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToDecimalResult(outputBlock, result); + } + + @Test + public void testDoubleToDecimal() { + final DecimalType toDecimalType = new DecimalType(18, 2); + DoubleBlockBuilder builder = new DoubleBlockBuilder(count); + Decimal[] result = new Decimal[count]; + for (int i = 0; i < count; i++) { + double val = random.nextDouble(); + Decimal decimalVal = Decimal.fromString(String.valueOf(val)); + Decimal expectResult = new Decimal(); + DecimalConverter.rescale(decimalVal.getDecimalStructure(), expectResult.getDecimalStructure(), + toDecimalType.getPrecision(), toDecimalType.getScale(), false); + result[i] = expectResult; + builder.writeDouble(val); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(DataTypes.DoubleType, 0, 0); + CastDoubleToDecimalVectorizedExpression expr = + new CastDoubleToDecimalVectorizedExpression(toDecimalType, 1, children); + DoubleBlock inputBlock = (DoubleBlock) builder.build(); + DecimalBlock outputBlock = new DecimalBlock(toDecimalType, count); + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToDecimalResult(outputBlock, result); + } + + @Test + public void testFloatToDecimal() { + final DecimalType toDecimalType = new DecimalType(18, 2); + FloatBlockBuilder builder = new FloatBlockBuilder(count); + Decimal[] result = new Decimal[count]; + for (int i = 0; i < count; i++) { + float val = random.nextFloat(); + Decimal decimalVal = Decimal.fromString(String.valueOf(val)); + Decimal expectResult = new Decimal(); + DecimalConverter.rescale(decimalVal.getDecimalStructure(), expectResult.getDecimalStructure(), + toDecimalType.getPrecision(), toDecimalType.getScale(), false); + result[i] = expectResult; + builder.writeFloat(val); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(DataTypes.FloatType, 0, 0); + CastFloatToDecimalVectorizedExpression expr = + new CastFloatToDecimalVectorizedExpression(toDecimalType, 1, children); + FloatBlock inputBlock = (FloatBlock) builder.build(); + DecimalBlock outputBlock = new DecimalBlock(toDecimalType, count); + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToDecimalResult(outputBlock, result); + } + + @Test + public void testULongToDecimal() { + final DecimalType toDecimalType = new DecimalType(32, 2); + ULongBlockBuilder builder = new ULongBlockBuilder(count); + Decimal[] result = new Decimal[count]; + for (int i = 0; i < count; i++) { + long val; + if (i == 0) { + // -1 作为 uint64 是 18446744073709551615 + val = -1; + Decimal expectResult = Decimal.fromString("18446744073709551615.00"); + result[i] = expectResult; + } else { + val = random.nextLong(); + Decimal decimalVal = new Decimal(); + DecimalConverter.unsignedlongToDecimal(val, decimalVal.getDecimalStructure()); + Decimal expectResult = new Decimal(); + DecimalConverter.rescale(decimalVal.getDecimalStructure(), expectResult.getDecimalStructure(), + toDecimalType.getPrecision(), toDecimalType.getScale(), true); + result[i] = expectResult; + } + builder.writeLong(val); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(DataTypes.ULongType, 0, 0); + CastULongToDecimalVectorizedExpression expr = + new CastULongToDecimalVectorizedExpression(toDecimalType, 1, children); + ULongBlock inputBlock = (ULongBlock) builder.build(); + DecimalBlock outputBlock = new DecimalBlock(toDecimalType, count); + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToDecimalResult(outputBlock, result); + } + + @Test + public void testDecimalToLong() { + final DecimalType toDecimalType = new DecimalType(32, 2); + DecimalBlockBuilder builder = new DecimalBlockBuilder(count); + long[] result = new long[count]; + for (int i = 0; i < count; i++) { + double val = random.nextDouble(); + Decimal decimalVal = Decimal.fromString(String.valueOf(val)); + result[i] = Math.round(val); + builder.writeDecimal(decimalVal); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(toDecimalType, 0, 0); + CastDecimalToSignedVectorizedExpression expr = + new CastDecimalToSignedVectorizedExpression(DataTypes.LongType, 1, children); + DecimalBlock inputBlock = (DecimalBlock) builder.build(); + LongBlock outputBlock = new LongBlock(DataTypes.LongType, count); + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToSignedResult(outputBlock, result); + } + + @Test + public void testDecimalToULong() { + final DecimalType decimalType = new DecimalType(32, 2); + DecimalBlockBuilder builder = new DecimalBlockBuilder(count); + long[] result = new long[count]; + for (int i = 0; i < count; i++) { + double val = random.nextDouble(); + Decimal decimalVal = Decimal.fromString(String.valueOf(val)); + result[i] = Math.round(val); + builder.writeDecimal(decimalVal); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(decimalType, 0, 0); + CastDecimalToUnsignedVectorizedExpression expr = + new CastDecimalToUnsignedVectorizedExpression(DataTypes.UIntegerType, 1, children); + DecimalBlock inputBlock = (DecimalBlock) builder.build(); + ULongBlock outputBlock = new ULongBlock(DataTypes.UIntegerType, count); + MutableChunk chunk = new MutableChunk(inputBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToUnsignedResult(outputBlock, result); + } + + @Test + public void testCharToSigned() { + ObjectBlockBuilder builder = new ObjectBlockBuilder(count); + long[] result = new long[count]; + for (int i = 0; i < count; i++) { + long l = random.nextLong(); + result[i] = l; + builder.writeObject(Slices.utf8Slice(Long.toString(l))); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(DataTypes.CharType, 0, 0); + CastCharToSignedVectorizedExpression expr = + new CastCharToSignedVectorizedExpression(DataTypes.LongType, 1, children); + ReferenceBlock refBlock = (ReferenceBlock) builder.build(); + LongBlock outputBlock = new LongBlock(DataTypes.LongType, count); + MutableChunk chunk = new MutableChunk(refBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToSignedResult(outputBlock, result); + } + + @Test + public void testCharToUnsigned() { + ObjectBlockBuilder builder = new ObjectBlockBuilder(count); + long[] result = new long[count]; + for (int i = 0; i < count; i++) { + long l = random.nextLong(); + result[i] = l; + builder.writeObject(Slices.utf8Slice(Long.toString(l))); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(DataTypes.CharType, 0, 0); + CastCharToUnsignedVectorizedExpression expr = + new CastCharToUnsignedVectorizedExpression(DataTypes.UIntegerType, 1, children); + ReferenceBlock refBlock = (ReferenceBlock) builder.build(); + ULongBlock outputBlock = new ULongBlock(DataTypes.UIntegerType, count); + MutableChunk chunk = new MutableChunk(refBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToUnsignedResult(outputBlock, result); + } + + @Test + public void testCharToDouble() { + ObjectBlockBuilder builder = new ObjectBlockBuilder(count); + double[] result = new double[count]; + for (int i = 0; i < count; i++) { + double d = random.nextDouble(); + result[i] = d; + builder.writeObject(Slices.utf8Slice(Double.toString(d))); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(DataTypes.CharType, 0, 0); + CastCharToDoubleVectorizedExpression expr = + new CastCharToDoubleVectorizedExpression(DataTypes.DoubleType, 1, children); + ReferenceBlock refBlock = (ReferenceBlock) builder.build(); + DoubleBlock outputBlock = new DoubleBlock(DataTypes.DoubleType, count); + MutableChunk chunk = new MutableChunk(refBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToDoubleResult(outputBlock, result); + } + + @Test + public void testCharToDecimal() { + final DecimalType decimalType = new DecimalType(18, 2); + ObjectBlockBuilder builder = new ObjectBlockBuilder(count); + Decimal[] result = new Decimal[count]; + for (int i = 0; i < count; i++) { + int val = random.nextInt(); + Decimal decimal = new Decimal(val, decimalType.getScale()); + result[i] = decimal; + builder.writeObject(Slices.utf8Slice(decimal.toString())); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(DataTypes.CharType, 0, 0); + CastCharToDecimalVectorizedExpression expr = + new CastCharToDecimalVectorizedExpression(decimalType, 1, children); + ReferenceBlock refBlock = (ReferenceBlock) builder.build(); + DecimalBlock outputBlock = new DecimalBlock(decimalType, count); + MutableChunk chunk = new MutableChunk(refBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToDecimalResult(outputBlock, result); + } + + @Test + public void testVarcharToSigned() { + ObjectBlockBuilder builder = new ObjectBlockBuilder(count); + long[] result = new long[count]; + for (int i = 0; i < count; i++) { + long l = random.nextLong(); + result[i] = l; + builder.writeObject(Slices.utf8Slice(Long.toString(l))); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(DataTypes.CharType, 0, 0); + CastVarcharToSignedVectorizedExpression expr = + new CastVarcharToSignedVectorizedExpression(DataTypes.LongType, 1, children); + ReferenceBlock refBlock = (ReferenceBlock) builder.build(); + LongBlock outputBlock = new LongBlock(DataTypes.LongType, count); + MutableChunk chunk = new MutableChunk(refBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToSignedResult(outputBlock, result); + } + + @Test + public void testVarcharToUnsigned() { + ObjectBlockBuilder builder = new ObjectBlockBuilder(count); + long[] result = new long[count]; + for (int i = 0; i < count; i++) { + long l = random.nextLong(); + result[i] = l; + builder.writeObject(Slices.utf8Slice(Long.toString(l))); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(DataTypes.CharType, 0, 0); + CastVarcharToUnsignedVectorizedExpression expr = + new CastVarcharToUnsignedVectorizedExpression(DataTypes.UIntegerType, 1, children); + ReferenceBlock refBlock = (ReferenceBlock) builder.build(); + ULongBlock outputBlock = new ULongBlock(DataTypes.UIntegerType, count); + MutableChunk chunk = new MutableChunk(refBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToUnsignedResult(outputBlock, result); + } + + @Test + public void testVarcharToDouble() { + ObjectBlockBuilder builder = new ObjectBlockBuilder(count); + double[] result = new double[count]; + for (int i = 0; i < count; i++) { + double d = random.nextDouble(); + result[i] = d; + builder.writeObject(Slices.utf8Slice(Double.toString(d))); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(DataTypes.CharType, 0, 0); + CastVarcharToDoubleVectorizedExpression expr = + new CastVarcharToDoubleVectorizedExpression(DataTypes.DoubleType, 1, children); + ReferenceBlock refBlock = (ReferenceBlock) builder.build(); + DoubleBlock outputBlock = new DoubleBlock(DataTypes.DoubleType, count); + MutableChunk chunk = new MutableChunk(refBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToDoubleResult(outputBlock, result); + } + + @Test + public void testVarcharToDecimal() { + final DecimalType decimalType = new DecimalType(18, 2); + ObjectBlockBuilder builder = new ObjectBlockBuilder(count); + Decimal[] result = new Decimal[count]; + for (int i = 0; i < count; i++) { + int val = random.nextInt(); + Decimal decimal = new Decimal(val, decimalType.getScale()); + result[i] = decimal; + builder.writeObject(Slices.utf8Slice(decimal.toString())); + } + + VectorizedExpression[] children = new VectorizedExpression[1]; + children[0] = new InputRefVectorizedExpression(DataTypes.CharType, 0, 0); + CastVarcharToDecimalVectorizedExpression expr = + new CastVarcharToDecimalVectorizedExpression(decimalType, 1, children); + ReferenceBlock refBlock = (ReferenceBlock) builder.build(); + DecimalBlock outputBlock = new DecimalBlock(decimalType, count); + MutableChunk chunk = new MutableChunk(refBlock, outputBlock); + setSelection(chunk); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + expr.eval(evaluationContext); + + validateToDecimalResult(outputBlock, result); + } + + private void validateToSignedResult(LongBlock outputBlock, long[] result) { + if (!withSelection) { + for (int i = 0; i < positionCount; i++) { + Assert.assertEquals(result[i], outputBlock.getLong(i)); + } + } else { + for (int i = 0; i < positionCount; i++) { + int j = sel[i]; + Assert.assertEquals(result[j], outputBlock.getLong(j)); + } + } + } + + private void validateToUnsignedResult(ULongBlock outputBlock, long[] result) { + if (!withSelection) { + for (int i = 0; i < positionCount; i++) { + Assert.assertEquals(result[i], outputBlock.getLong(i)); + } + } else { + for (int i = 0; i < positionCount; i++) { + int j = sel[i]; + Assert.assertEquals(result[j], outputBlock.getLong(j)); + } + } + } + + private void validateToDoubleResult(DoubleBlock outputBlock, double[] result) { + if (!withSelection) { + for (int i = 0; i < positionCount; i++) { + Assert.assertEquals(result[i], outputBlock.getDouble(i), 1e-10); + } + } else { + for (int i = 0; i < positionCount; i++) { + int j = sel[i]; + Assert.assertEquals(result[j], outputBlock.getDouble(j), 1e-10); + } + } + } + + private void validateToDecimalResult(DecimalBlock outputBlock, Decimal[] result) { + if (!withSelection) { + for (int i = 0; i < positionCount; i++) { + Assert.assertEquals(result[i].toString(), outputBlock.getDecimal(i).toString()); + } + } else { + for (int i = 0; i < positionCount; i++) { + int j = sel[i]; + Assert.assertEquals(result[j].toString(), outputBlock.getDecimal(j).toString()); + } + } + } + + private void setSelection(MutableChunk chunk) { + if (!withSelection) { + return; + } + chunk.setSelection(sel); + chunk.setBatchSize(sel.length); + chunk.setSelectionInUse(true); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/logical/FastLogicalBinaryOperatorsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/logical/FastLogicalBinaryOperatorsTest.java new file mode 100644 index 000000000..a3f1a7656 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/logical/FastLogicalBinaryOperatorsTest.java @@ -0,0 +1,61 @@ +package com.alibaba.polardbx.executor.vectorized.logical; + +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.chunk.Block; +import com.alibaba.polardbx.executor.vectorized.ColumnInput; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; + +@RunWith(Parameterized.class) +public class FastLogicalBinaryOperatorsTest extends LogicalBinaryOperatorsTest { + private static final Map> FUNCTION_MAP = + new HashMap>() {{ + put("AND", LogicalBinaryOperatorsTest::and); + put("OR", LogicalBinaryOperatorsTest::or); + }}; + + private static final List> COLUMN_PAIRS = loadColumnPairs(); + + public FastLogicalBinaryOperatorsTest(String sql, + List inputs, + Block output, int[] selection) { + super(sql, inputs, output, selection); + } + + /** + * test long type only + */ + protected static List> loadColumnPairs() { + List> columnarPairs = new ArrayList<>(); + columnarPairs.add(new Pair<>("test_bigint", "test_bigint2")); + return columnarPairs; + } + + @Parameterized.Parameters(name = "{0}") + public static List generate() { + List result = new ArrayList<>(COLUMN_PAIRS.size() * COLUMN_PAIRS.size() * FUNCTION_MAP.size()); + + for (String operator : FUNCTION_MAP.keySet()) { + for (Pair columnPair : COLUMN_PAIRS) { + result.addAll(generateColCol(columnPair.getKey(), columnPair.getValue(), operator)); + result.addAll(generateColConst(columnPair.getKey(), columnPair.getValue(), operator)); + } + } + return result; + } + + @Before + public void before() { + this.executionContext.getParamManager().getProps().put(ConnectionProperties.ENABLE_AND_FAST_VEC, "true"); + this.executionContext.getParamManager().getProps().put(ConnectionProperties.ENABLE_OR_FAST_VEC, "true"); + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/logical/LogicalBinaryOperatorsTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/logical/LogicalBinaryOperatorsTest.java index 8be2c348e..985f4143d 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/logical/LogicalBinaryOperatorsTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/logical/LogicalBinaryOperatorsTest.java @@ -81,15 +81,34 @@ public static List generate() { return result; } - private static List generateColCol(String col1Name, String col2Name, String operator) { + protected static List generateColCol(String col1Name, String col2Name, String operator) { + return generateColCol(col1Name, col2Name, operator, true); + } + + protected static List generateColCol(String col1Name, String col2Name, String operator, + boolean withNull) { Random random = getRandom(); - List col1DataList = Lists.newArrayList( - generateColumnInput(random, col1Name, true), - generateColumnInput(random, col1Name, false)); + List col1DataList; + if (withNull) { + col1DataList = Lists.newArrayList( + generateColumnInput(random, col1Name, true), + generateColumnInput(random, col1Name, false)); + } else { + col1DataList = Lists.newArrayList( + generateColumnInput(random, col1Name, false), + generateColumnInput(random, col1Name, false)); + } - List col2DataList = Lists.newArrayList( - generateColumnInput(random, col2Name, true), - generateColumnInput(random, col2Name, false)); + List col2DataList; + if (withNull) { + col2DataList = Lists.newArrayList( + generateColumnInput(random, col2Name, true), + generateColumnInput(random, col2Name, false)); + } else { + col2DataList = Lists.newArrayList( + generateColumnInput(random, col2Name, false), + generateColumnInput(random, col2Name, false)); + } int[] selection = createSelectionArray(SELECTION_LEN, TEST_ROW_COUNT, random); @@ -109,7 +128,7 @@ private static List generateColCol(String col1Name, String col2Name, S return result; } - private static List generateColConst(String col1Name, String col2Name, String operator) { + protected static List generateColConst(String col1Name, String col2Name, String operator) { Random random = getRandom(); DataType dataType1 = dataTypeOfColumn(col1Name); List col1DataList = Lists.newArrayList( @@ -193,7 +212,7 @@ private static Object[] calcColConst(Object[] col1Data, Object col2Data, String return result; } - private static Object and(Object obj1, Object obj2) { + protected static Object and(Object obj1, Object obj2) { Optional b1 = toBigDecimal(obj1) .map(o -> o.compareTo(BigDecimal.ZERO) != 0); @@ -219,7 +238,7 @@ private static Object and(Object obj1, Object obj2) { } } - private static Object or(Object obj1, Object obj2) { + protected static Object or(Object obj1, Object obj2) { Optional b1 = toBigDecimal(obj1) .map(o -> o.compareTo(BigDecimal.ZERO) != 0); diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastAddLongDecimalTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastAddLongDecimalTest.java index a21d2e0bf..881fd2995 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastAddLongDecimalTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastAddLongDecimalTest.java @@ -43,23 +43,37 @@ public class FastAddLongDecimalTest { private final boolean overflow; private final InputState inputState; private final ExecutionContext executionContext = new ExecutionContext(); - private long leftConstVal; + private final boolean withSelection; + private final int[] sel; + private Long leftConstVal; - public FastAddLongDecimalTest(boolean overflow, String inputState) { + public FastAddLongDecimalTest(boolean overflow, String inputState, boolean withSelection) { this.overflow = overflow; this.inputState = InputState.valueOf(inputState); if (this.inputState == InputState.SIMPLE) { executionContext.getParamManager().getProps().put(ENABLE_DECIMAL_FAST_VEC, "true"); } + this.withSelection = withSelection; + if (withSelection) { + this.sel = new int[COUNT / 2]; + final int offset = 10; + for (int i = 0; i < sel.length; i++) { + sel[i] = i + offset; + } + } else { + this.sel = null; + } } - @Parameterized.Parameters(name = "overflow={0},inputState={1}") + @Parameterized.Parameters(name = "overflow={0},inputState={1},sel={2}") public static List generateParameters() { List list = new ArrayList<>(); for (InputState value : InputState.values()) { - list.add(new Object[] {true, value.name()}); - list.add(new Object[] {false, value.name()}); + list.add(new Object[] {true, value.name(), false}); + list.add(new Object[] {true, value.name(), true}); + list.add(new Object[] {false, value.name(), false}); + list.add(new Object[] {false, value.name(), true}); } return list; @@ -89,12 +103,15 @@ public void before() { case FULL: leftConstVal = random.nextLong(); break; + case NULL: + leftConstVal = null; + break; } System.out.println("Left const val: " + leftConstVal); } private boolean isDecimal64() { - return inputState == InputState.DECIMAL_64; + return inputState == InputState.DECIMAL_64 || inputState == InputState.NULL; } private boolean isDecimal128() { @@ -117,6 +134,11 @@ public void testAddLongConstDecimalVar() { leftBlock.isDecimal64(), isDecimal64()); Assert.assertEquals("Expect left block to be decimal128: " + isDecimal64(), leftBlock.isDecimal128(), isDecimal128()); + if (withSelection) { + chunk.setBatchSize(sel.length); + chunk.setSelection(sel); + chunk.setSelectionInUse(true); + } DecimalBlock outputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); @@ -124,7 +146,8 @@ public void testAddLongConstDecimalVar() { expr.eval(evaluationContext); - Assert.assertFalse("Expect to be allocated after evaluation", outputBlock.isUnalloc()); + Assert.assertEquals("Expect to be allocated after evaluation, otherwise it is null", + inputState == InputState.NULL, outputBlock.isUnalloc()); if (!overflow) { switch (inputState) { @@ -176,10 +199,20 @@ public void testAddLongConstDecimalVar() { // check result Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); - for (int i = 0; i < COUNT; i++) { - Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() + " at " + i, - targetResult[i], outputBlock.getDecimal(i)); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(j).toString() + " at " + j, + targetResult[j], outputBlock.isNull(j) ? null : outputBlock.getDecimal(j)); + } + } else { + for (int i = 0; i < COUNT; i++) { + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() + " at " + i, + targetResult[i], outputBlock.isNull(i) ? null : outputBlock.getDecimal(i)); + } } + } private MutableChunk preAllocatedChunk() { @@ -192,6 +225,11 @@ private MutableChunk preAllocatedChunk() { for (int i = 0; i < COUNT; i++) { long l; switch (inputState) { + case NULL: + l = genNotOverflowLong(); + decimal = new Decimal(l, SCALE); + builder.writeLong(l); + break; case DECIMAL_64: if (!overflow || i % 2 == 1) { l = genNotOverflowLong(); @@ -256,16 +294,21 @@ private MutableChunk preAllocatedChunk() { throw new UnsupportedOperationException(); } - Decimal target = new Decimal(); - FastDecimalUtils.add(Decimal.fromLong(leftConstVal).getDecimalStructure(), decimal.getDecimalStructure(), - target.getDecimalStructure()); - targetResult[i] = target; + if (leftConstVal != null) { + Decimal target = new Decimal(); + + FastDecimalUtils.add(Decimal.fromLong(leftConstVal).getDecimalStructure(), + decimal.getDecimalStructure(), + target.getDecimalStructure()); + targetResult[i] = target; + } } DecimalBlock decimalBlock = (DecimalBlock) builder.build(); blocks[0] = decimalBlock; switch (inputState) { case DECIMAL_64: + case NULL: Assert.assertTrue(decimalBlock.isDecimal64()); break; case DECIMAL_128: @@ -298,6 +341,7 @@ enum InputState { DECIMAL_64, DECIMAL_128, SIMPLE, - FULL + FULL, + NULL } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastBetweenDecimalTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastBetweenDecimalTest.java deleted file mode 100644 index 55c37f19b..000000000 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastBetweenDecimalTest.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.alibaba.polardbx.executor.vectorized.math; - -import com.alibaba.polardbx.common.datatype.Decimal; -import com.alibaba.polardbx.common.datatype.FastDecimalUtils; -import com.alibaba.polardbx.executor.chunk.Block; -import com.alibaba.polardbx.executor.chunk.DecimalBlock; -import com.alibaba.polardbx.executor.chunk.DecimalBlockBuilder; -import com.alibaba.polardbx.executor.chunk.LongBlock; -import com.alibaba.polardbx.executor.chunk.MutableChunk; -import com.alibaba.polardbx.executor.vectorized.EvaluationContext; -import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.LiteralVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.FastBetweenDecimalColCharConstCharConstVectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.compare.FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression; -import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; -import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; -import io.airlift.slice.Slice; -import io.airlift.slice.Slices; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Random; - -/** - * 只有当 left 和 right scale 相同时,才能走 decimal64 路径 - */ -@RunWith(Parameterized.class) -public class FastBetweenDecimalTest { - - private static final int COUNT = 1024; - /** - * 虽然 precision 不在 decimal64 范围内 - * 但是否为 decimal64 取决于实际的值 - */ - private static final int PRECISION = 20; - private static final int OUTPUT_INDEX = 1; - private static final int BLOCK_COUNT = 2; - private static final int RANGE = 1000; - private static final Decimal RANGE_DECIMAL = Decimal.fromLong(RANGE); - private final boolean overflow = false; - private final int scale; - private final DecimalType leftDecimalType; - private final DecimalType rightDecimalType; - private final DecimalType inputDecimalType; - - private final Decimal leftDecimal; - private final Decimal rightDecimal; - - private final Random random = new Random(System.currentTimeMillis()); - private final long[] targetResult = new long[COUNT]; - - private final ExecutionContext executionContext = new ExecutionContext(); - - public FastBetweenDecimalTest(int scale) { - this.scale = scale; - this.leftDecimalType = new DecimalType(PRECISION, scale); - this.rightDecimalType = new DecimalType(PRECISION, scale); - this.inputDecimalType = new DecimalType(PRECISION, scale); - long l = genDecimal64NotOverflowLong(); - this.leftDecimal = new Decimal(l, scale); - this.rightDecimal = leftDecimal.add(RANGE_DECIMAL); - } - - @Parameterized.Parameters(name = "scale={0}") - public static List generateParameters() { - List list = new ArrayList<>(); - - final int[] scales = {0, 1, 2, 5, 9}; - for (int scale : scales) { - list.add(new Object[] {scale}); - } - return list; - } - - @Test - public void testBetweenDecimal64() { - final VectorizedExpression[] children = new VectorizedExpression[3]; - children[0] = new InputRefVectorizedExpression(inputDecimalType, 0, 0); - children[1] = new LiteralVectorizedExpression(leftDecimalType, leftDecimal, 1); - children[2] = new LiteralVectorizedExpression(rightDecimalType, rightDecimal, 2); - FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression expr = - new FastBetweenDecimalColDecimalConstDecimalConstVectorizedExpression( - OUTPUT_INDEX, children); - - MutableChunk chunk = buildDecimal64Chunk(); - EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); - - LongBlock outputBlock = (LongBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); - DecimalBlock inputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(0)); - - expr.eval(evaluationContext); - - // check result - Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); - for (int i = 0; i < COUNT; i++) { - Assert.assertEquals("Incorrect between result for: " + inputBlock.getDecimal(i).toString(), - targetResult[i], outputBlock.getLong(i)); - } - } - - /** - * between '0.01' and '3.21' - */ - @Test - public void testBetweenDecimal64CharConstCharConst() { - final VectorizedExpression[] children = new VectorizedExpression[3]; - children[0] = new InputRefVectorizedExpression(inputDecimalType, 0, 0); - children[1] = new LiteralVectorizedExpression(DataTypes.CharType, leftDecimal.toString(), 1); - children[2] = new LiteralVectorizedExpression(DataTypes.CharType, rightDecimal.toString(), 2); - FastBetweenDecimalColCharConstCharConstVectorizedExpression expr = - new FastBetweenDecimalColCharConstCharConstVectorizedExpression( - OUTPUT_INDEX, children); - - MutableChunk chunk = buildDecimal64Chunk(); - EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); - - LongBlock outputBlock = (LongBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); - DecimalBlock inputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(0)); - - expr.eval(evaluationContext); - - // check result - Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); - for (int i = 0; i < COUNT; i++) { - Assert.assertEquals("Incorrect between result for: " + inputBlock.getDecimal(i).toString(), - targetResult[i], outputBlock.getLong(i)); - } - } - - private MutableChunk buildDecimal64Chunk() { - Block[] blocks = new Block[BLOCK_COUNT]; - blocks[0] = new DecimalBlock(inputDecimalType, COUNT); - blocks[1] = new LongBlock(DataTypes.LongType, COUNT); - - DecimalBlockBuilder inputBuilder = new DecimalBlockBuilder(COUNT, inputDecimalType); - for (int i = 0; i < COUNT; i++) { - long left = genDecimal64NotOverflowLong(); - // 穿插正负数 - inputBuilder.writeLong(left); - Decimal inputDecimal = new Decimal(left, scale); - boolean between = FastDecimalUtils.compare(inputDecimal.getDecimalStructure(), - leftDecimal.getDecimalStructure()) >= 0; - between &= FastDecimalUtils.compare(inputDecimal.getDecimalStructure(), - rightDecimal.getDecimalStructure()) <= 0; - targetResult[i] = between ? LongBlock.TRUE_VALUE : LongBlock.FALSE_VALUE; - } - DecimalBlock inputBlock = (DecimalBlock) inputBuilder.build(); - blocks[0] = inputBlock; - Assert.assertTrue(inputBlock.isDecimal64()); - - return new MutableChunk(blocks); - } - - private long genDecimal64NotOverflowLong() { - return random.nextInt(9999999) + 10_000_000; - } - - private long genDecimal64OverflowLong() { - return random.nextInt(9999999) + 9000_000_000L; - } -} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastDecimalBetweenColLongConstLongConstTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastDecimalBetweenColLongConstLongConstTest.java deleted file mode 100644 index 91bddf87f..000000000 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastDecimalBetweenColLongConstLongConstTest.java +++ /dev/null @@ -1,217 +0,0 @@ -package com.alibaba.polardbx.executor.vectorized.math; - -import com.alibaba.polardbx.common.datatype.Decimal; -import com.alibaba.polardbx.common.properties.ConnectionParams; -import com.alibaba.polardbx.common.properties.ParamManager; -import com.alibaba.polardbx.executor.chunk.BlockUtils; -import com.alibaba.polardbx.executor.chunk.Chunk; -import com.alibaba.polardbx.executor.chunk.DecimalBlock; -import com.alibaba.polardbx.executor.chunk.DecimalBlockBuilder; -import com.alibaba.polardbx.executor.chunk.LongBlock; -import com.alibaba.polardbx.executor.chunk.MutableChunk; -import com.alibaba.polardbx.executor.operator.BaseExecTest; -import com.alibaba.polardbx.executor.vectorized.EvaluationContext; -import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; -import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; -import com.alibaba.polardbx.executor.vectorized.build.Rex2VectorizedExpressionVisitor; -import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; -import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; -import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; -import com.alibaba.polardbx.optimizer.core.datatype.DataType; -import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; -import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; -import com.google.common.collect.ImmutableList; -import org.apache.calcite.rel.type.RelDataTypeFactory; -import org.apache.calcite.rex.RexBuilder; -import org.apache.calcite.rex.RexNode; -import org.apache.calcite.sql.type.SqlTypeName; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -public class FastDecimalBetweenColLongConstLongConstTest extends BaseExecTest { - private final static RelDataTypeFactory TYPE_FACTORY = - new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); - private final static RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY); - - private final static Random RANDOM = new Random(); - - @Before - public void before() { - Map connectionMap = new HashMap(); - connectionMap.put(ConnectionParams.CHUNK_SIZE.getName(), 1000); - connectionMap.put(ConnectionParams.ENABLE_EXPRESSION_VECTORIZATION.getName(), true); - context.setParamManager(new ParamManager(connectionMap)); - } - - @Test - public void testDecimal64() { - final DecimalType decimalType = new DecimalType(15, 2); - final int positionCount = context.getExecutorChunkLimit(); - final int nullCount = 20; - final int lowerBound = 0; // 0.00 - final int upperBound = 1000; // 10.00 - final long betweenLeft = 3; // 3.00 - final long betweenRight = 6; // 6.00 - - List> inputTypes = ImmutableList.of(decimalType); - - RexNode root = REX_BUILDER.makeCall( - TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), - TddlOperatorTable.BETWEEN, - ImmutableList.of( - REX_BUILDER.makeInputRef( - TYPE_FACTORY.createSqlType(SqlTypeName.DECIMAL, decimalType.getPrecision(), decimalType.getScale()), - 0), - REX_BUILDER.makeBigIntLiteral(betweenLeft), - REX_BUILDER.makeBigIntLiteral(betweenRight) - )); - - InputRefTypeChecker inputRefTypeChecker = new InputRefTypeChecker(inputTypes); - root = root.accept(inputRefTypeChecker); - - Rex2VectorizedExpressionVisitor converter = - new Rex2VectorizedExpressionVisitor(context, inputTypes.size()); - - VectorizedExpression expression = root.accept(converter); - - MutableChunk preAllocatedChunk = MutableChunk.newBuilder(positionCount) - .addEmptySlots(inputTypes) - .addEmptySlots(converter.getOutputDataTypes()) - .build(); - - // build input decimal block - DecimalBlock inputBlock = - generateDecimal64Block(decimalType, positionCount, nullCount, lowerBound, upperBound); - Chunk inputChunk = new Chunk(positionCount, inputBlock); - - LongBlock outputBlock = (LongBlock) BlockUtils.createBlock(DataTypes.LongType, inputChunk.getPositionCount()); - - preAllocatedChunk.setSelection(null); - preAllocatedChunk.setSelectionInUse(false); - preAllocatedChunk.setSlotAt(inputBlock, 0); - preAllocatedChunk.setSlotAt(outputBlock, expression.getOutputIndex()); - preAllocatedChunk.setBatchSize(positionCount); - - EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); - expression.eval(evaluationContext); - - // check actual boolean values with expected values from decimal compare. - Decimal lower = Decimal.fromLong(betweenLeft); - Decimal upper = Decimal.fromLong(betweenRight); - for (int i = 0; i < inputChunk.getPositionCount(); i++) { - boolean actual = outputBlock.getLong(i) == 1 && !outputBlock.isNull(i); - boolean expected = (!inputBlock.isNull(i) - && inputBlock.getDecimal(i).compareTo(lower) >= 0 - && inputBlock.getDecimal(i).compareTo(upper) <= 0); - Assert.assertTrue(actual == expected); - } - - } - - @Test - public void testDecimal() { - final DecimalType decimalType = new DecimalType(15, 2); - final int positionCount = context.getExecutorChunkLimit(); - final int nullCount = 20; - final int lowerBound = 0; // 0.00 - final int upperBound = 1000; // 10.00 - final long betweenLeft = 3; // 3.00 - final long betweenRight = 6; // 6.00 - - List> inputTypes = ImmutableList.of(decimalType); - - RexNode root = REX_BUILDER.makeCall( - TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT), - TddlOperatorTable.BETWEEN, - ImmutableList.of( - REX_BUILDER.makeInputRef( - TYPE_FACTORY.createSqlType(SqlTypeName.DECIMAL, decimalType.getPrecision(), decimalType.getScale()), - 0), - REX_BUILDER.makeBigIntLiteral(betweenLeft), - REX_BUILDER.makeBigIntLiteral(betweenRight) - )); - - InputRefTypeChecker inputRefTypeChecker = new InputRefTypeChecker(inputTypes); - root = root.accept(inputRefTypeChecker); - - Rex2VectorizedExpressionVisitor converter = - new Rex2VectorizedExpressionVisitor(context, inputTypes.size()); - - VectorizedExpression expression = root.accept(converter); - - MutableChunk preAllocatedChunk = MutableChunk.newBuilder(positionCount) - .addEmptySlots(inputTypes) - .addEmptySlots(converter.getOutputDataTypes()) - .build(); - - // build input decimal block - DecimalBlock inputBlock = - generateDecimalBlock(decimalType, positionCount, nullCount, lowerBound, upperBound); - Chunk inputChunk = new Chunk(positionCount, inputBlock); - - LongBlock outputBlock = (LongBlock) BlockUtils.createBlock(DataTypes.LongType, inputChunk.getPositionCount()); - - preAllocatedChunk.setSelection(null); - preAllocatedChunk.setSelectionInUse(false); - preAllocatedChunk.setSlotAt(inputBlock, 0); - preAllocatedChunk.setSlotAt(outputBlock, expression.getOutputIndex()); - preAllocatedChunk.setBatchSize(positionCount); - - EvaluationContext evaluationContext = new EvaluationContext(preAllocatedChunk, context); - expression.eval(evaluationContext); - - // check actual boolean values with expected values from decimal compare. - Decimal lower = Decimal.fromLong(betweenLeft); - Decimal upper = Decimal.fromLong(betweenRight); - for (int i = 0; i < inputChunk.getPositionCount(); i++) { - boolean actual = outputBlock.getLong(i) == 1 && !outputBlock.isNull(i); - boolean expected = (!inputBlock.isNull(i) - && inputBlock.getDecimal(i).compareTo(lower) >= 0 - && inputBlock.getDecimal(i).compareTo(upper) <= 0); - Assert.assertTrue(actual == expected); - } - - } - - private DecimalBlock generateDecimal64Block(DecimalType decimalType, int positionCount, int nullCount, - int lowerBound, int upperBound) { - DecimalBlock decimalBlock = (DecimalBlock) BlockUtils.createBlock(decimalType, positionCount); - long[] decimal64Values = decimalBlock.allocateDecimal64(); - boolean[] nulls = decimalBlock.nulls(); - - for (int i = 0; i < positionCount; i++) { - int decimalValue = lowerBound + RANDOM.nextInt(upperBound - lowerBound); - decimal64Values[i] = decimalValue; - } - - for (int i = 0; i < positionCount; i++) { - if (RANDOM.nextInt(positionCount) < nullCount) { - nulls[i] = true; - } - } - - return decimalBlock; - } - - private DecimalBlock generateDecimalBlock(DecimalType decimalType, int positionCount, int nullCount, - int lowerBound, int upperBound) { - DecimalBlockBuilder blockBuilder = new DecimalBlockBuilder(positionCount, decimalType); - final int scale = decimalType.getScale(); - for (int i = 0; i < positionCount; i++) { - if (RANDOM.nextInt(positionCount) < nullCount) { - blockBuilder.appendNull(); - } else { - int decimalValue = lowerBound + RANDOM.nextInt(upperBound - lowerBound); - blockBuilder.writeDecimal(new Decimal(decimalValue, scale)); - } - } - return (DecimalBlock) blockBuilder.build(); - } - -} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalIntegerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalIntegerTest.java index b0ef0e44a..18c27c1d2 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalIntegerTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalIntegerTest.java @@ -14,7 +14,6 @@ import com.alibaba.polardbx.executor.vectorized.InputRefVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.datatype.DecimalType; import org.junit.Assert; @@ -42,27 +41,41 @@ public class FastMultiplyDecimalIntegerTest { private final boolean overflow; private final Random random = new Random(System.currentTimeMillis()); private final Decimal[] targetResult = new Decimal[COUNT]; + private final boolean withSelection; + private final int[] sel; private final ExecutionContext executionContext = new ExecutionContext(); - public FastMultiplyDecimalIntegerTest(int leftScale, - boolean overflow) { + public FastMultiplyDecimalIntegerTest(int leftScale, boolean overflow, + boolean withSelection) { if (leftScale > PRECISION) { throw new IllegalArgumentException("Too large scale"); } this.leftDecimalType = new DecimalType(PRECISION, leftScale); this.targetDecimalType = new DecimalType(PRECISION * 2, leftScale); this.overflow = overflow; + this.withSelection = withSelection; + if (withSelection) { + this.sel = new int[COUNT / 2]; + int offset = 10; + for (int i = 0; i < sel.length; i++) { + this.sel[i] = i + offset; + } + } else { + this.sel = null; + } } - @Parameterized.Parameters(name = "leftScale={0},overflow={1}") + @Parameterized.Parameters(name = "leftScale={0},overflow={1},sel={2}") public static List generateParameters() { List list = new ArrayList<>(); - final int[] scales = {0, 1, 2, 5}; + final int[] scales = {0, 2, 5}; for (int leftScale : scales) { - list.add(new Object[] {leftScale, false}); - list.add(new Object[] {leftScale, true}); + list.add(new Object[] {leftScale, false, false}); + list.add(new Object[] {leftScale, true, false}); + list.add(new Object[] {leftScale, false, true}); + list.add(new Object[] {leftScale, true, true}); } return list; } @@ -80,7 +93,7 @@ public void testMultiplyDecimal64() { new FastMultiplyDecimalColIntegerColVectorizedExpression( OUTPUT_INDEX, children); - MutableChunk chunk = buildDecimal64Chunk(); + MutableChunk chunk = buildDecimal64Chunk(false); EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); DecimalBlock outputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); @@ -100,11 +113,40 @@ public void testMultiplyDecimal64() { // check result Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); - for (int i = 0; i < COUNT; i++) { - Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() - + " and " + rightBlock.getInt(i) + " at " + i, - targetResult[i], outputBlock.getDecimal(i)); + validateResult(outputBlock, leftBlock, rightBlock); + } + + @Test + public void testMultiplyDecimal64Unsigned() { + final VectorizedExpression[] children = new VectorizedExpression[2]; + children[0] = new InputRefVectorizedExpression(leftDecimalType, 0, 0); + children[1] = new InputRefVectorizedExpression(DataTypes.UIntegerType, 1, 1); + FastMultiplyDecimalColIntegerColVectorizedExpression expr = + new FastMultiplyDecimalColIntegerColVectorizedExpression( + OUTPUT_INDEX, children); + + MutableChunk chunk = buildDecimal64Chunk(true); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + + DecimalBlock outputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); + DecimalBlock leftBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(0)); + IntegerBlock rightBlock = (IntegerBlock) Objects.requireNonNull(chunk.slotIn(1)); + + Assert.assertTrue("Expect to be unallocated before evaluation", outputBlock.isUnalloc()); + + expr.eval(evaluationContext); + + Assert.assertFalse("Expect to be allocated after evaluation", outputBlock.isUnalloc()); + if (!overflow) { + Assert.assertTrue("Output should be decimal64/128 when not overflowed", + outputBlock.isDecimal64() || outputBlock.isDecimal128()); + } else { + Assert.assertTrue("Output should be decimal128 when overflowed", outputBlock.isDecimal128()); } + + // check result + Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); + validateResult(outputBlock, leftBlock, rightBlock); } @Test @@ -116,7 +158,7 @@ public void testMultiplyDecimal128() { new FastMultiplyDecimalColIntegerColVectorizedExpression( OUTPUT_INDEX, children); - MutableChunk chunk = buildDecimal128Chunk(); + MutableChunk chunk = buildDecimal128Chunk(false); EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); DecimalBlock outputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); @@ -136,11 +178,39 @@ public void testMultiplyDecimal128() { // check result Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); - for (int i = 0; i < COUNT; i++) { - Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() - + " and " + rightBlock.getInt(i) + " at " + i, - targetResult[i], outputBlock.getDecimal(i)); + validateResult(outputBlock, leftBlock, rightBlock); + } + + @Test + public void testMultiplyDecimal128Unsigned() { + final VectorizedExpression[] children = new VectorizedExpression[2]; + children[0] = new InputRefVectorizedExpression(leftDecimalType, 0, 0); + children[1] = new InputRefVectorizedExpression(DataTypes.UIntegerType, 1, 1); + FastMultiplyDecimalColIntegerColVectorizedExpression expr = + new FastMultiplyDecimalColIntegerColVectorizedExpression( + OUTPUT_INDEX, children); + + MutableChunk chunk = buildDecimal128Chunk(true); + EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); + + DecimalBlock outputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); + DecimalBlock leftBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(0)); + IntegerBlock rightBlock = (IntegerBlock) Objects.requireNonNull(chunk.slotIn(1)); + + Assert.assertTrue("Expect to be unallocated before evaluation", outputBlock.isUnalloc()); + + expr.eval(evaluationContext); + + Assert.assertFalse("Expect to be allocated after evaluation", outputBlock.isUnalloc()); + if (!overflow) { + Assert.assertTrue("Output should be decimal128 when not overflowed", outputBlock.isDecimal128()); + } else { + Assert.assertTrue("Output should be full when overflowed", outputBlock.getState().isFull()); } + + // check result + Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); + validateResult(outputBlock, leftBlock, rightBlock); } @Test @@ -174,14 +244,27 @@ public void testMultiplyNormal() { // check result Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); - for (int i = 0; i < COUNT; i++) { - Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() - + " and " + rightBlock.getInt(i) + " at " + i, - targetResult[i], outputBlock.getDecimal(i)); + validateResult(outputBlock, leftBlock, rightBlock); + } + + private void validateResult(DecimalBlock outputBlock, DecimalBlock leftBlock, IntegerBlock rightBlock) { + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(j).toString() + + " and " + rightBlock.getInt(j) + " at selection: " + i, + targetResult[j], outputBlock.getDecimal(j)); + } + } else { + for (int i = 0; i < COUNT; i++) { + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() + + " and " + rightBlock.getInt(i) + " at " + i, + targetResult[i], outputBlock.getDecimal(i)); + } } } - private MutableChunk buildDecimal64Chunk() { + private MutableChunk buildDecimal64Chunk(boolean isUnsigned) { Block[] blocks = new Block[BLOCK_COUNT]; blocks[2] = new DecimalBlock(targetDecimalType, COUNT); @@ -192,29 +275,59 @@ private MutableChunk buildDecimal64Chunk() { for (int i = 0; i < COUNT; i++) { long left; int right; - if (!overflow || i % 2 == 0) { - left = genDecimal64NotOverflowLong(); - // 穿插正负数 - if (i % 3 == 0) { - left = -left; - } + if (i == 0) { + left = 1; + right = 1; + } else if (i == 1) { + left = -1; + right = -1; + } else if (i == 2) { + left = 1; right = genSmallInt(); - if (i % 5 == 0) { - right = -right; - } + } else if (i == 3) { + left = -1; + right = genSmallInt(); + } else if (i == 4) { + left = genDecimal64NotOverflowLong(); + right = -1; + } else if (i == 5) { + left = genDecimal64NotOverflowLong(); + right = 1; } else { - left = genDecimal64OverflowLong(); - right = genLargeInt(); + if (!overflow || i % 2 == 0) { + left = genDecimal64NotOverflowLong(); + // 穿插正负数 + if (i % 3 == 0) { + left = -left; + } + right = genSmallInt(); + if (i % 5 == 0) { + right = -right; + } + } else { + left = genDecimal64OverflowLong(); + right = genLargeInt(); + } } + leftBuilder.writeLong(left); rightBuilder.writeInt(right); - DecimalConverter.longToDecimal(right, rightDecimal.getDecimalStructure(), false); Decimal target = new Decimal(); - FastDecimalUtils.mul( - new Decimal(left, leftDecimalType.getScale()).getDecimalStructure(), - rightDecimal.getDecimalStructure(), - target.getDecimalStructure()); + if (isUnsigned) { + DecimalConverter.longToDecimal(right & 0xFFFFFFFFL, rightDecimal.getDecimalStructure()); + FastDecimalUtils.mul( + new Decimal(left, leftDecimalType.getScale()).getDecimalStructure(), + rightDecimal.getDecimalStructure(), + target.getDecimalStructure()); + } else { + DecimalConverter.longToDecimal(right, rightDecimal.getDecimalStructure(), false); + FastDecimalUtils.mul( + new Decimal(left, leftDecimalType.getScale()).getDecimalStructure(), + rightDecimal.getDecimalStructure(), + target.getDecimalStructure()); + } + targetResult[i] = target; } DecimalBlock leftBlock = (DecimalBlock) leftBuilder.build(); @@ -224,10 +337,16 @@ private MutableChunk buildDecimal64Chunk() { IntegerBlock rightBlock = (IntegerBlock) rightBuilder.build(); blocks[1] = rightBlock; - return new MutableChunk(blocks); + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setBatchSize(sel.length); + chunk.setSelectionInUse(true); + chunk.setSelection(sel); + } + return chunk; } - private MutableChunk buildDecimal128Chunk() { + private MutableChunk buildDecimal128Chunk(boolean isUnsigned) { Block[] blocks = new Block[BLOCK_COUNT]; blocks[2] = new DecimalBlock(targetDecimalType, COUNT); @@ -239,37 +358,72 @@ private MutableChunk buildDecimal128Chunk() { for (int i = 0; i < COUNT; i++) { int right; Decimal decimal; - if (!overflow) { - String decStr = gen128BitUnsignedNumStr(random, 5, false); - if (i % 2 == 0) { - decStr = "-" + decStr; - } - - Decimal writeDec = Decimal.fromString(decStr); + if (i == 0) { + right = 1; + Decimal writeDec = Decimal.fromString("1"); FastDecimalUtils.shift(writeDec.getDecimalStructure(), writeDec.getDecimalStructure(), -scale); writeDec.getDecimalStructure().setFractions(scale); long[] decimal128 = FastDecimalUtils.convertToDecimal128(writeDec); leftBuilder.writeDecimal128(decimal128[0], decimal128[1]); decimal = writeDec; - right = genSmallInt(); - - } else { - DecimalStructure buffer = new DecimalStructure(); - DecimalStructure result = new DecimalStructure(); - // 低 64 位是 unsigned - long[] decimal128 = {-1, Long.MAX_VALUE}; - FastDecimalUtils.setDecimal128WithScale(buffer, result, decimal128[0], decimal128[1], scale); + } else if (i == 1) { + right = -1; + Decimal writeDec = Decimal.fromString("-1"); + FastDecimalUtils.shift(writeDec.getDecimalStructure(), writeDec.getDecimalStructure(), -scale); + writeDec.getDecimalStructure().setFractions(scale); + long[] decimal128 = FastDecimalUtils.convertToDecimal128(writeDec); leftBuilder.writeDecimal128(decimal128[0], decimal128[1]); - decimal = new Decimal(result); - right = genLargeInt(); + decimal = writeDec; + } else if (i == 2) { + right = 0; + Decimal writeDec = Decimal.fromString("0"); + FastDecimalUtils.shift(writeDec.getDecimalStructure(), writeDec.getDecimalStructure(), -scale); + writeDec.getDecimalStructure().setFractions(scale); + long[] decimal128 = FastDecimalUtils.convertToDecimal128(writeDec); + leftBuilder.writeDecimal128(decimal128[0], decimal128[1]); + decimal = writeDec; + } else { + if (!overflow) { + String decStr = gen128BitUnsignedNumStr(random, 5, false); + if (i % 2 == 0) { + decStr = "-" + decStr; + } + + Decimal writeDec = Decimal.fromString(decStr); + FastDecimalUtils.shift(writeDec.getDecimalStructure(), writeDec.getDecimalStructure(), -scale); + writeDec.getDecimalStructure().setFractions(scale); + long[] decimal128 = FastDecimalUtils.convertToDecimal128(writeDec); + leftBuilder.writeDecimal128(decimal128[0], decimal128[1]); + decimal = writeDec; + right = genSmallInt(); + + } else { + DecimalStructure buffer = new DecimalStructure(); + DecimalStructure result = new DecimalStructure(); + // 低 64 位是 unsigned + long[] decimal128 = {-1, Long.MAX_VALUE}; + FastDecimalUtils.setDecimal128WithScale(buffer, result, decimal128[0], decimal128[1], scale); + leftBuilder.writeDecimal128(decimal128[0], decimal128[1]); + decimal = new Decimal(result); + right = genLargeInt(); + } } + rightBuilder.writeInt(right); DecimalConverter.longToDecimal(right, rightDecimal.getDecimalStructure(), false); Decimal target = new Decimal(); - FastDecimalUtils.mul(decimal.getDecimalStructure(), - rightDecimal.getDecimalStructure(), - target.getDecimalStructure()); + if (isUnsigned) { + DecimalConverter.longToDecimal(right & 0xFFFFFFFFL, rightDecimal.getDecimalStructure()); + FastDecimalUtils.mul(decimal.getDecimalStructure(), + rightDecimal.getDecimalStructure(), + target.getDecimalStructure()); + } else { + DecimalConverter.longToDecimal(right, rightDecimal.getDecimalStructure(), false); + FastDecimalUtils.mul(decimal.getDecimalStructure(), + rightDecimal.getDecimalStructure(), + target.getDecimalStructure()); + } targetResult[i] = target; } DecimalBlock leftBlock = (DecimalBlock) leftBuilder.build(); @@ -279,7 +433,13 @@ private MutableChunk buildDecimal128Chunk() { IntegerBlock rightBlock = (IntegerBlock) rightBuilder.build(); blocks[1] = rightBlock; - return new MutableChunk(blocks); + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setBatchSize(sel.length); + chunk.setSelectionInUse(true); + chunk.setSelection(sel); + } + return chunk; } private MutableChunk buildSimpleChunk() { @@ -313,7 +473,13 @@ private MutableChunk buildSimpleChunk() { IntegerBlock rightBlock = (IntegerBlock) rightBuilder.build(); blocks[1] = rightBlock; - return new MutableChunk(blocks); + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setBatchSize(sel.length); + chunk.setSelectionInUse(true); + chunk.setSelection(sel); + } + return chunk; } private long genDecimal64NotOverflowLong() { diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalTest.java index 20ad46af0..4177b7741 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastMultiplyDecimalTest.java @@ -41,25 +41,28 @@ public class FastMultiplyDecimalTest { private final Random random = new Random(System.currentTimeMillis()); private final Decimal[] targetResult = new Decimal[COUNT]; - + private final int[] sel; + private final boolean withSelection; private final ExecutionContext executionContext = new ExecutionContext(); - @Parameterized.Parameters(name = "leftScale={0},rightScale={1},overflow={2}") + @Parameterized.Parameters(name = "leftScale={0},rightScale={1},overflow={2},sel={3}") public static List generateParameters() { List list = new ArrayList<>(); final int[] scales = {0, 1, 2, 5}; for (int leftScale : scales) { for (int rightScale : scales) { - list.add(new Object[] {leftScale, rightScale, false}); - list.add(new Object[] {leftScale, rightScale, true}); + list.add(new Object[] {leftScale, rightScale, false, true}); + list.add(new Object[] {leftScale, rightScale, false, false}); + list.add(new Object[] {leftScale, rightScale, true, true}); + list.add(new Object[] {leftScale, rightScale, true, false}); } } return list; } public FastMultiplyDecimalTest(int leftScale, int rightScale, - boolean overflow) { + boolean overflow, boolean withSelection) { if (leftScale > PRECISION || rightScale > PRECISION) { throw new IllegalArgumentException("Too large scale"); } @@ -67,6 +70,16 @@ public FastMultiplyDecimalTest(int leftScale, int rightScale, this.rightDecimalType = new DecimalType(PRECISION, rightScale); this.targetDecimalType = new DecimalType(PRECISION * 2, leftScale + rightScale); this.overflow = overflow; + this.withSelection = withSelection; + if (withSelection) { + final int offset = 10; + this.sel = new int[COUNT / 2]; + for (int i = 0; i < sel.length; i++) { + sel[i] = i + offset; + } + } else { + this.sel = null; + } } @Before @@ -101,10 +114,19 @@ public void testMultiplyDecimal64() { // check result Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); - for (int i = 0; i < COUNT; i++) { - Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() - + " and " + rightBlock.getDecimal(i).toString() + " at " + i, - targetResult[i], outputBlock.getDecimal(i)); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(j).toString() + + " and " + rightBlock.getDecimal(i).toString() + " at " + i, + targetResult[j], outputBlock.getDecimal(j)); + } + } else { + for (int i = 0; i < COUNT; i++) { + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() + + " and " + rightBlock.getDecimal(i).toString() + " at " + i, + targetResult[i], outputBlock.getDecimal(i)); + } } } @@ -140,8 +162,16 @@ public void testMultiplySimple() { Assert.assertTrue("Output should be simple when not overflowed, but got: " + outputBlock.getState(), outputBlock.getState().isFull()); } else { - Assert.assertTrue("Output should be simple when not overflowed, but got: " + outputBlock.getState(), - outputBlock.isSimple()); + if (withSelection) { + Assert.assertTrue( + "Expect output block to simple when input is simple, got: " + outputBlock.getState(), + outputBlock.getState().isFull()); + } else { + // simple mode does not support selection + Assert.assertTrue("Expect output block to full when input is simple with selection, got: " + + outputBlock.getState(), + outputBlock.isSimple()); + } } } else { // simple 模式可能是full 可能是simple @@ -152,10 +182,19 @@ public void testMultiplySimple() { // check result Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); - for (int i = 0; i < COUNT; i++) { - Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() - + " and " + rightBlock.getDecimal(i).toString() + " at " + i, - targetResult[i], outputBlock.getDecimal(i)); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(j).toString() + + " and " + rightBlock.getDecimal(i).toString() + " at " + i, + targetResult[j], outputBlock.getDecimal(j)); + } + } else { + for (int i = 0; i < COUNT; i++) { + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() + + " and " + rightBlock.getDecimal(i).toString() + " at " + i, + targetResult[i], outputBlock.getDecimal(i)); + } } } @@ -168,20 +207,41 @@ private MutableChunk buildDecimal64Chunk() { for (int i = 0; i < COUNT; i++) { long left; long right; - if (!overflow || i % 2 == 0) { - left = genDecimal64NotOverflowLong(); - // 穿插正负数 - if (i % 3 == 0) { - left = -left; - } + if (i == 0) { + left = 0; right = genDecimal64NotOverflowLong(); - if (i % 5 == 0) { - right = -right; - } + } else if (i == 1) { + left = 1; + right = genDecimal64NotOverflowLong(); + } else if (i == 2) { + left = 1; + right = genDecimal64NotOverflowLong(); + } else if (i == 3) { + left = -1; + right = genDecimal64NotOverflowLong(); + } else if (i == 4) { + left = genDecimal64NotOverflowLong(); + right = -1; + } else if (i == 5) { + left = genDecimal64NotOverflowLong(); + right = 1; } else { - left = genDecimal64OverflowLong(); - right = genDecimal64OverflowLong(); + if (!overflow || i % 2 == 0) { + left = genDecimal64NotOverflowLong(); + // 穿插正负数 + if (i % 3 == 0) { + left = -left; + } + right = genDecimal64NotOverflowLong(); + if (i % 5 == 0) { + right = -right; + } + } else { + left = genDecimal64OverflowLong(); + right = genDecimal64OverflowLong(); + } } + leftBuilder.writeLong(left); rightBuilder.writeLong(right); @@ -200,7 +260,13 @@ private MutableChunk buildDecimal64Chunk() { blocks[1] = rightBlock; Assert.assertTrue(rightBlock.isDecimal64()); - return new MutableChunk(blocks); + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setSelectionInUse(true); + chunk.setSelection(sel); + chunk.setBatchSize(sel.length); + } + return chunk; } private MutableChunk buildSimpleChunk() { @@ -238,7 +304,13 @@ private MutableChunk buildSimpleChunk() { blocks[1] = rightBlock; Assert.assertTrue(rightBlock.isSimple()); - return new MutableChunk(blocks); + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setSelectionInUse(true); + chunk.setSelection(sel); + chunk.setBatchSize(sel.length); + } + return chunk; } private long genDecimal64NotOverflowLong() { diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastSubDecimalDecimalTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastSubDecimalDecimalTest.java index a869273e9..7943dfcd2 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastSubDecimalDecimalTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastSubDecimalDecimalTest.java @@ -35,10 +35,12 @@ public class FastSubDecimalDecimalTest { private final Decimal[] targetResult = new Decimal[COUNT]; private final boolean overflow; private final InputState inputState; + private final int[] sel; + private final boolean withSelection; private final ExecutionContext executionContext = new ExecutionContext(); public FastSubDecimalDecimalTest(boolean overflow, String inputState, - int scale1, int scale2) { + int scale1, int scale2, boolean withSelection) { this.overflow = overflow; this.inputState = InputState.valueOf(inputState); @@ -46,24 +48,35 @@ public FastSubDecimalDecimalTest(boolean overflow, String inputState, this.decimalType2 = new DecimalType(20, scale2); // derive result type this.resultDecimalType = new DecimalType(20, Math.max(scale1, scale2)); + this.withSelection = withSelection; + if (withSelection) { + final int offset = 10; + this.sel = new int[COUNT / 2]; + for (int i = 0; i < sel.length; i++) { + sel[i] = i + offset; + } + } else { + this.sel = null; + } } /** * Mixing different scales */ - @Parameterized.Parameters(name = "overflow={0},inputState={1},scale1={2},scale2={3}") + @Parameterized.Parameters(name = "overflow={0},inputState={1},scale1={2},scale2={3},sel={4}") public static List generateParameters() { List list = new ArrayList<>(); for (InputState value : InputState.values()) { - list.add(new Object[] {true, value.name(), DEFAULT_SCALE, DEFAULT_SCALE}); - list.add(new Object[] {true, value.name(), DEFAULT_SCALE + 1, DEFAULT_SCALE - 1}); - list.add(new Object[] {true, value.name(), DEFAULT_SCALE, DEFAULT_SCALE + 4}); - list.add(new Object[] {true, value.name(), DEFAULT_SCALE, DEFAULT_SCALE + 10}); - list.add(new Object[] {false, value.name(), DEFAULT_SCALE, DEFAULT_SCALE}); - list.add(new Object[] {false, value.name(), DEFAULT_SCALE + 1, DEFAULT_SCALE - 1}); - list.add(new Object[] {false, value.name(), DEFAULT_SCALE, DEFAULT_SCALE + 4}); - list.add(new Object[] {false, value.name(), DEFAULT_SCALE, DEFAULT_SCALE + 10}); + list.add(new Object[] {true, value.name(), DEFAULT_SCALE, DEFAULT_SCALE, false}); + list.add(new Object[] {true, value.name(), DEFAULT_SCALE, DEFAULT_SCALE, true}); + list.add(new Object[] {true, value.name(), DEFAULT_SCALE + 1, DEFAULT_SCALE - 1, true}); + list.add(new Object[] {true, value.name(), DEFAULT_SCALE, DEFAULT_SCALE + 4, false}); + list.add(new Object[] {true, value.name(), DEFAULT_SCALE, DEFAULT_SCALE + 10, true}); + list.add(new Object[] {false, value.name(), DEFAULT_SCALE, DEFAULT_SCALE, false}); + list.add(new Object[] {false, value.name(), DEFAULT_SCALE + 1, DEFAULT_SCALE - 1, true}); + list.add(new Object[] {false, value.name(), DEFAULT_SCALE, DEFAULT_SCALE + 4, false}); + list.add(new Object[] {false, value.name(), DEFAULT_SCALE, DEFAULT_SCALE + 10, true}); } return list; @@ -139,9 +152,17 @@ public void testSubDecimalColDecimalCol() { // check result Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); - for (int i = 0; i < COUNT; i++) { - Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() + " at " + i, - targetResult[i], outputBlock.getDecimal(i)); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(j).toString() + " at pos: " + i, + targetResult[j], outputBlock.getDecimal(j)); + } + } else { + for (int i = 0; i < COUNT; i++) { + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() + " at pos: " + i, + targetResult[i], outputBlock.getDecimal(i)); + } } } @@ -209,7 +230,13 @@ private MutableChunk preAllocatedChunk() { break; } - return new MutableChunk(blocks); + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setSelectionInUse(true); + chunk.setSelection(sel); + chunk.setBatchSize(sel.length); + } + return chunk; } private long genNotOverflowLong() { diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastSubLongDecimalTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastSubLongDecimalTest.java index 60031ca3d..c41bd0caa 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastSubLongDecimalTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/FastSubLongDecimalTest.java @@ -41,23 +41,37 @@ public class FastSubLongDecimalTest { private final boolean overflow; private final InputState inputState; private final ExecutionContext executionContext = new ExecutionContext(); - private long leftConstVal; + private final int[] sel; + private final boolean withSelection; + private Long leftConstVal; - public FastSubLongDecimalTest(boolean overflow, String inputState) { + public FastSubLongDecimalTest(boolean overflow, String inputState, boolean withSelection) { this.overflow = overflow; this.inputState = InputState.valueOf(inputState); if (this.inputState == InputState.SIMPLE) { executionContext.getParamManager().getProps().put(ENABLE_DECIMAL_FAST_VEC, "true"); } + this.withSelection = withSelection; + if (withSelection) { + final int offset = 10; + this.sel = new int[COUNT / 2]; + for (int i = 0; i < sel.length; i++) { + sel[i] = i + offset; + } + } else { + this.sel = null; + } } - @Parameterized.Parameters(name = "overflow={0},inputState={1}") + @Parameterized.Parameters(name = "overflow={0},inputState={1},sel={2}") public static List generateParameters() { List list = new ArrayList<>(); for (InputState value : InputState.values()) { - list.add(new Object[] {true, value.name()}); - list.add(new Object[] {false, value.name()}); + list.add(new Object[] {true, value.name(), false}); + list.add(new Object[] {true, value.name(), true}); + list.add(new Object[] {false, value.name(), true}); + list.add(new Object[] {false, value.name(), false}); } return list; @@ -80,6 +94,9 @@ public void before() { case FULL: leftConstVal = random.nextLong(); break; + case NULL: + leftConstVal = null; + break; } System.out.println("Left const val: " + leftConstVal); } @@ -101,7 +118,7 @@ public void testSubLongConstDecimalVar() { EvaluationContext evaluationContext = new EvaluationContext(chunk, executionContext); DecimalBlock leftBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(0)); Assert.assertEquals("Expect left block to be decimal64: " + isDecimal64(), - leftBlock.isDecimal64(), isDecimal64()); + leftBlock.isDecimal64(), isDecimal64() || inputState == InputState.NULL); DecimalBlock outputBlock = (DecimalBlock) Objects.requireNonNull(chunk.slotIn(OUTPUT_INDEX)); @@ -109,7 +126,11 @@ public void testSubLongConstDecimalVar() { expr.eval(evaluationContext); - Assert.assertFalse("Expect to be allocated after evaluation", outputBlock.isUnalloc()); + if (inputState == InputState.NULL) { + Assert.assertTrue("Expect to be unallocated after evaluation when null", outputBlock.isUnalloc()); + } else { + Assert.assertFalse("Expect to be allocated after evaluation", outputBlock.isUnalloc()); + } if (!overflow) { switch (inputState) { @@ -119,8 +140,17 @@ public void testSubLongConstDecimalVar() { outputBlock.isDecimal64()); break; case SIMPLE: - Assert.assertTrue("Expect output block to simple when input is simple, got: " + outputBlock.getState(), - outputBlock.isSimple()); + if (withSelection) { + Assert.assertTrue( + "Expect output block to simple when input is simple, got: " + outputBlock.getState(), + outputBlock.getState().isFull()); + } else { + // simple mode does not support selection + Assert.assertTrue("Expect output block to full when input is simple with selection, got: " + + outputBlock.getState(), + outputBlock.isSimple()); + } + break; case FULL: Assert.assertTrue("Expect output block to full when input is full got: " + outputBlock.getState(), @@ -150,9 +180,17 @@ public void testSubLongConstDecimalVar() { // check result Assert.assertEquals("Incorrect output block positionCount", COUNT, outputBlock.getPositionCount()); - for (int i = 0; i < COUNT; i++) { - Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() + " at " + i, - targetResult[i], outputBlock.getDecimal(i)); + if (withSelection) { + for (int i = 0; i < sel.length; i++) { + int j = sel[i]; + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(j).toString() + " at pos: " + i, + targetResult[j], outputBlock.getDecimal(j)); + } + } else { + for (int i = 0; i < COUNT; i++) { + Assert.assertEquals("Incorrect value for: " + leftBlock.getDecimal(i).toString() + " at pos: " + i, + targetResult[i], outputBlock.getDecimal(i)); + } } } @@ -165,6 +203,9 @@ private MutableChunk preAllocatedChunk() { for (int i = 0; i < COUNT; i++) { long l; switch (inputState) { + case NULL: + l = genNotOverflowLong(); + break; case DECIMAL_64: if (!overflow || i % 2 == 1) { l = genNotOverflowLong(); @@ -195,22 +236,28 @@ private MutableChunk preAllocatedChunk() { Decimal decimal = new Decimal(l, SCALE); - if (isDecimal64()) { + if (isDecimal64() || inputState == InputState.NULL) { builder.writeLong(l); } else { builder.writeDecimal(decimal); } - Decimal target = new Decimal(); - FastDecimalUtils.sub(Decimal.fromLong(leftConstVal).getDecimalStructure(), decimal.getDecimalStructure(), - target.getDecimalStructure()); - targetResult[i] = target; + if (inputState != InputState.NULL) { + Decimal target = new Decimal(); + FastDecimalUtils.sub(Decimal.fromLong(leftConstVal).getDecimalStructure(), + decimal.getDecimalStructure(), + target.getDecimalStructure()); + targetResult[i] = target; + } else { + targetResult[i] = new Decimal(0, decimalType.getScale()); + } } DecimalBlock decimalBlock = (DecimalBlock) builder.build(); blocks[0] = decimalBlock; switch (inputState) { case DECIMAL_64: + case NULL: Assert.assertTrue(decimalBlock.isDecimal64()); break; case SIMPLE: @@ -221,7 +268,13 @@ private MutableChunk preAllocatedChunk() { break; } - return new MutableChunk(blocks); + MutableChunk chunk = new MutableChunk(blocks); + if (withSelection) { + chunk.setSelectionInUse(true); + chunk.setSelection(sel); + chunk.setBatchSize(sel.length); + } + return chunk; } private long genNotOverflowLong() { @@ -235,6 +288,7 @@ private long genLong() { enum InputState { DECIMAL_64, SIMPLE, - FULL + FULL, + NULL } } diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/SubStrVectorizedExpressionTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/SubStrVectorizedExpressionTest.java index 62da881d7..1937334a9 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/SubStrVectorizedExpressionTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/math/SubStrVectorizedExpressionTest.java @@ -10,12 +10,15 @@ import com.alibaba.polardbx.executor.chunk.SliceBlockBuilder; import com.alibaba.polardbx.executor.operator.BaseExecTest; import com.alibaba.polardbx.executor.vectorized.EvaluationContext; +import com.alibaba.polardbx.executor.vectorized.SubStrCharVectorizedExpression; +import com.alibaba.polardbx.executor.vectorized.SubStrVarcharVectorizedExpression; import com.alibaba.polardbx.executor.vectorized.VectorizedExpression; import com.alibaba.polardbx.executor.vectorized.build.InputRefTypeChecker; import com.alibaba.polardbx.executor.vectorized.build.Rex2VectorizedExpressionVisitor; import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; +import com.alibaba.polardbx.optimizer.core.datatype.CharType; import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.core.datatype.SliceType; import com.google.common.collect.ImmutableList; @@ -53,39 +56,48 @@ public void before() { @Test public void test1() { - doTest(2, 5); + doTest(2, 5, true); + doTest(2, 5, false); } @Test public void test2() { - doTest(-5, 2); + doTest(-5, 2, true); + doTest(-5, 2, false); } @Test public void test3() { - doTest(-3, 4); + doTest(-3, 4, true); + doTest(-3, 4, false); } @Test public void test4() { - doTest(-1, 3); + doTest(-1, 3, true); + doTest(-1, 3, false); } - protected void doTest(int startPos, int subStrLen) { + /** + * @param isVarchar is isVarchar or char + */ + protected void doTest(int startPos, int subStrLen, boolean isVarchar) { final SliceType sliceType = new SliceType(); + final CharType charType = new CharType(); final int positionCount = context.getExecutorChunkLimit(); final int nullCount = 20; final int lowerBound = 0; // 0.00 final int upperBound = 1000; // 10.00 final SqlOperator operator = TddlOperatorTable.SUBSTRING; - List> inputTypes = ImmutableList.of(sliceType); + List> inputTypes = isVarchar ? ImmutableList.of(sliceType) : ImmutableList.of(charType); RexNode root = REX_BUILDER.makeCall( TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR), operator, ImmutableList.of( - REX_BUILDER.makeInputRef(TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR), 0), + REX_BUILDER.makeInputRef(isVarchar ? TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR) + : TYPE_FACTORY.createSqlType(SqlTypeName.CHAR), 0), REX_BUILDER.makeBigIntLiteral(Long.valueOf(startPos)), REX_BUILDER.makeBigIntLiteral(Long.valueOf(subStrLen)) )); @@ -97,6 +109,11 @@ protected void doTest(int startPos, int subStrLen) { new Rex2VectorizedExpressionVisitor(context, inputTypes.size()); VectorizedExpression expression = root.accept(converter); + if (isVarchar) { + Assert.assertEquals(SubStrVarcharVectorizedExpression.class, expression.getClass()); + } else { + Assert.assertEquals(SubStrCharVectorizedExpression.class, expression.getClass()); + } MutableChunk preAllocatedChunk = MutableChunk.newBuilder(positionCount) .addEmptySlots(inputTypes) diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/metadata/Rex2ArgTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/metadata/Rex2ArgTest.java new file mode 100644 index 000000000..d702a9fb1 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/executor/vectorized/metadata/Rex2ArgTest.java @@ -0,0 +1,78 @@ +package com.alibaba.polardbx.executor.vectorized.metadata; + +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import org.apache.calcite.rel.type.DynamicRecordTypeImpl; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rel.type.RelDataTypeFactory; +import org.apache.calcite.rel.type.RelDataTypeFieldImpl; +import org.apache.calcite.rel.type.RelDataTypeSystem; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexCall; +import org.apache.calcite.rex.RexDynamicParam; +import org.apache.calcite.rex.RexInputRef; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexVisitor; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.type.SqlTypeFactoryImpl; +import org.apache.calcite.sql.type.SqlTypeName; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; + +public class Rex2ArgTest { + + @Test + public void testIoArgumentInfo() { + ArgumentInfo argumentInfo = Rex2ArgumentInfo.toArgumentInfo(null); + Assert.assertNull(argumentInfo); + + final RelDataTypeFactory typeFactory = new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + RexBuilder rexBuilder = new RexBuilder(typeFactory); + RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER); + RexCall exprCall = (RexCall) rexBuilder.makeCall(SqlStdOperatorTable.MINUS, + rexBuilder.makeDynamicParam(intType, 0), + rexBuilder.makeDynamicParam(intType, 1)); + argumentInfo = Rex2ArgumentInfo.toArgumentInfo(exprCall); + Assert.assertNotNull(argumentInfo); + Assert.assertTrue(argumentInfo.getType().equalDeeply(DataTypes.LongType)); + Assert.assertSame(argumentInfo.getKind(), ArgumentKind.Variable); + + RexDynamicParam dynamicParam = rexBuilder.makeDynamicParam(intType, 0); + argumentInfo = Rex2ArgumentInfo.toArgumentInfo(dynamicParam); + Assert.assertNotNull(argumentInfo); + Assert.assertSame(argumentInfo.getKind(), ArgumentKind.Const); + + exprCall = Mockito.mock(RexCall.class); + Mockito.when(exprCall.accept(any(RexVisitor.class))).thenCallRealMethod(); + Mockito.when(exprCall.getType()).thenReturn(new DynamicRecordTypeImpl(typeFactory)); + argumentInfo = Rex2ArgumentInfo.toArgumentInfo(exprCall); + Assert.assertNull(argumentInfo); + + DynamicRecordTypeImpl mockType = Mockito.mock(DynamicRecordTypeImpl.class); + RelDataTypeFieldImpl field = new RelDataTypeFieldImpl("f1", 0, typeFactory.createSqlType(SqlTypeName.INTEGER)); + Mockito.when(mockType.getFieldList()).thenReturn(Arrays.asList(field)); + Mockito.when(mockType.isStruct()).thenReturn(true); + Mockito.when(exprCall.getType()).thenReturn(mockType); + argumentInfo = Rex2ArgumentInfo.toArgumentInfo(exprCall); + Assert.assertNotNull(argumentInfo); + Assert.assertSame(argumentInfo.getKind(), ArgumentKind.ConstVargs); + } + + private List convertInValues(RelDataTypeFactory typeFactory, int[] inValues) { + RexBuilder rexBuilder = new RexBuilder(typeFactory); + List rexNodeList = new ArrayList<>(inValues.length + 1); + rexNodeList.add(new RexInputRef(1, typeFactory.createSqlType(SqlTypeName.BIGINT))); + for (long inValue : inValues) { + RexNode rexNode = rexBuilder.makeLiteral(inValue, + typeFactory.createSqlType(SqlTypeName.INTEGER), false); + rexNodeList.add(rexNode); + } + return rexNodeList; + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/group/config/OptimizedGroupConfigManagerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/group/config/OptimizedGroupConfigManagerTest.java new file mode 100644 index 000000000..0d3f26ded --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/group/config/OptimizedGroupConfigManagerTest.java @@ -0,0 +1,87 @@ +package com.alibaba.polardbx.group.config; + +import com.alibaba.polardbx.atom.TAtomDataSource; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.util.GroupInfoUtil; +import com.alibaba.polardbx.group.jdbc.DataSourceWrapper; +import com.alibaba.polardbx.group.jdbc.TGroupDataSource; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.Map; + +import static org.mockito.Mockito.when; + +public class OptimizedGroupConfigManagerTest { + + @Test + public void testPolarDBXSourceHolderInMasterMode() { + TGroupDataSource groupDataSource = Mockito.mock(TGroupDataSource.class); + when(groupDataSource.getSchemaName()).thenReturn("app"); + OptimizedGroupConfigManager configManager = new OptimizedGroupConfigManager(groupDataSource); + + initDataSourceWrapper(1, 0, configManager); + configManager.resetPolarDBXSourceHolder(true); + GroupDataSourceHolder groupDataSourceHolder = configManager.getGroupDataSourceHolder(); + Assert.assertTrue(groupDataSourceHolder instanceof MasterFailedSlaveGroupDataSourceHolder); + + configManager.resetPolarDBXSourceHolder(false); + groupDataSourceHolder = configManager.getGroupDataSourceHolder(); + Assert.assertTrue(groupDataSourceHolder instanceof MasterOnlyGroupDataSourceHolder); + + initDataSourceWrapper(1, 1, configManager); + configManager.resetPolarDBXSourceHolder(true); + groupDataSourceHolder = configManager.getGroupDataSourceHolder(); + Assert.assertTrue(groupDataSourceHolder instanceof MasterSlaveGroupDataSourceHolder); + } + + @Test + public void testPolarDBXSourceHolderInSlaveMode() { + try (MockedStatic configDataMode = Mockito.mockStatic(ConfigDataMode.class)) { + configDataMode.when(() -> ConfigDataMode.isReadOnlyMode()).thenReturn(true); + TGroupDataSource groupDataSource = Mockito.mock(TGroupDataSource.class); + when(groupDataSource.getSchemaName()).thenReturn("app"); + OptimizedGroupConfigManager configManager = new OptimizedGroupConfigManager(groupDataSource); + + initDataSourceWrapper(1, 0, configManager); + configManager.resetPolarDBXSourceHolder(true); + GroupDataSourceHolder groupDataSourceHolder = configManager.getGroupDataSourceHolder(); + Assert.assertTrue(groupDataSourceHolder instanceof MasterFailedSlaveGroupDataSourceHolder); + + configManager.resetPolarDBXSourceHolder(false); + groupDataSourceHolder = configManager.getGroupDataSourceHolder(); + Assert.assertTrue(groupDataSourceHolder instanceof MasterFailedSlaveGroupDataSourceHolder); + + initDataSourceWrapper(1, 1, configManager); + configManager.resetPolarDBXSourceHolder(true); + groupDataSourceHolder = configManager.getGroupDataSourceHolder(); + Assert.assertTrue(groupDataSourceHolder instanceof MasterSlaveGroupDataSourceHolder); + } + + } + + private void initDataSourceWrapper(int masterNum, int slaveNum, OptimizedGroupConfigManager configManager) { + Map dataSourceWrapperMap = configManager.getDataSourceWrapperMap(); + dataSourceWrapperMap.clear(); + for (int i = 0; i < masterNum; i++) { + TAtomDataSource tAtomDataSource = Mockito.mock(TAtomDataSource.class); + when(tAtomDataSource.isFollowerDB()).thenReturn(false); + when(tAtomDataSource.getDnId()).thenReturn("m" + i); + DataSourceWrapper dataSourceWrapper = new DataSourceWrapper( + "m" + i, "a", GroupInfoUtil.buildWeightStr(10, 10), tAtomDataSource, 0); + dataSourceWrapperMap.put("master" + i, dataSourceWrapper); + } + + for (int i = 0; i < slaveNum; i++) { + TAtomDataSource tAtomDataSource = Mockito.mock(TAtomDataSource.class); + when(tAtomDataSource.isFollowerDB()).thenReturn(false); + when(tAtomDataSource.getDnId()).thenReturn("m" + i); + DataSourceWrapper dataSourceWrapper = new DataSourceWrapper( + "s" + i, "a", GroupInfoUtil.buildWeightStr(10, 0), tAtomDataSource, 0); + dataSourceWrapperMap.put("slave" + i, dataSourceWrapper); + } + } + +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/group/jdbc/TGroupDataSourceTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/group/jdbc/TGroupDataSourceTest.java new file mode 100644 index 000000000..a373645f7 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/group/jdbc/TGroupDataSourceTest.java @@ -0,0 +1,59 @@ +package com.alibaba.polardbx.group.jdbc; + +import com.alibaba.polardbx.atom.TAtomDataSource; +import com.alibaba.polardbx.gms.listener.ConfigManager; +import com.alibaba.polardbx.group.config.OptimizedGroupConfigManager; +import com.alibaba.polardbx.group.config.Weight; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class TGroupDataSourceTest { + @Test + public void testHashCode() { + TGroupDataSource tGroupDataSource = new TGroupDataSource("abc", "def", + "gh", "ijk"); + Map dataSourceWrapperMap = new HashMap<>(); + + // Mock the configManager and its behavior + OptimizedGroupConfigManager mockConfigManager = Mockito.mock(OptimizedGroupConfigManager.class); + + // Assume DataSourceWrapper class has a constructor that accepts TAtomDataSource + DataSourceWrapper mockWrapper = Mockito.mock(DataSourceWrapper.class); + + Weight mockWeight = Mockito.mock(Weight.class); + when(mockWrapper.getWeight()).thenReturn(mockWeight); + + TAtomDataSource mockAtomDataSource = mock(TAtomDataSource.class); + when(mockAtomDataSource.getHost()).thenReturn("localhost"); + when(mockAtomDataSource.getPort()).thenReturn("3306"); + + dataSourceWrapperMap.put("data_source_1", mockWrapper); + + when(mockConfigManager.getDataSourceWrapperMap()).thenReturn(dataSourceWrapperMap); + + tGroupDataSource.setConfigManager(mockConfigManager); + Assert.assertEquals(98475778L, tGroupDataSource.hashCode()); + } + + @Test + public void testHashCode2() { + TGroupDataSource tGroupDataSource = new TGroupDataSource(null, null, + "gh", "ijk"); + Map dataSourceWrapperMap = new HashMap<>(); + + OptimizedGroupConfigManager mockConfigManager = Mockito.mock(OptimizedGroupConfigManager.class); + + when(mockConfigManager.getDataSourceWrapperMap()).thenReturn(dataSourceWrapperMap); + + tGroupDataSource.setConfigManager(mockConfigManager); + Assert.assertEquals(29791, tGroupDataSource.hashCode()); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/group/utils/VariableProxyTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/group/utils/VariableProxyTest.java new file mode 100644 index 000000000..914e3553a --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/group/utils/VariableProxyTest.java @@ -0,0 +1,93 @@ +package com.alibaba.polardbx.group.utils; + +import com.alibaba.polardbx.common.utils.InstanceRole; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.rpc.client.XClient; +import com.alibaba.polardbx.rpc.client.XSession; +import com.alibaba.polardbx.rpc.pool.XConnection; +import com.google.common.collect.ImmutableMap; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; + +import static org.mockito.Mockito.when; + +public class VariableProxyTest { + + @Test + public void getSessionVariablesForJDBC() throws Throwable { + try (MockedStatic staticConfigDataMode = Mockito.mockStatic(ConfigDataMode.class); + MockedStatic staticMetaDBUtil = Mockito.mockStatic(MetaDbUtil.class)) { + + VariableProxy proxy = new VariableProxy(null); + + staticConfigDataMode.when(() -> ConfigDataMode.getInstanceRole()).thenReturn(InstanceRole.COLUMNAR_SLAVE); + + // Arrange + Connection mockConnection = Mockito.mock(Connection.class); + Statement mockStatement = Mockito.mock(Statement.class); + ResultSet mockResultSet = Mockito.mock(ResultSet.class); + + when(mockConnection.createStatement()).thenReturn(mockStatement); + when(mockStatement.executeQuery("SHOW SESSION VARIABLES")).thenReturn(mockResultSet); + + when(mockResultSet.next()).thenReturn(true, false); // One record + when(mockResultSet.getString("Variable_name")).thenReturn("max_connections"); + when(mockResultSet.getString("Value")).thenReturn("100"); + + // Add the connection mock + staticMetaDBUtil.when(() -> MetaDbUtil.getConnection()).thenReturn(mockConnection); + + // Act + ImmutableMap result = proxy.getSessionVariables(); + + // Assert + ImmutableMap expected = ImmutableMap.of("max_connections", "100"); + Assert.assertEquals(expected, result); + } + + } + + @Test + public void getSessionVariablesForXProtocol() throws Throwable { + try (MockedStatic staticConfigDataMode = Mockito.mockStatic(ConfigDataMode.class); + MockedStatic staticMetaDBUtil = Mockito.mockStatic(MetaDbUtil.class)) { + + VariableProxy proxy = new VariableProxy(null); + + staticConfigDataMode.when(() -> ConfigDataMode.getInstanceRole()).thenReturn(InstanceRole.COLUMNAR_SLAVE); + + // Arrange + // Arrange for X protocol mode + Connection mockConnection = Mockito.mock(Connection.class); + XConnection mockXConnection = Mockito.mock(XConnection.class); + XClient mockXClient = Mockito.mock(XClient.class); + XSession mockXSession = Mockito.mock(XSession.class); + + when(mockConnection.isWrapperFor(XConnection.class)).thenReturn(true); + when(mockConnection.unwrap(XConnection.class)).thenReturn(mockXConnection); + when(mockXConnection.getSession()).thenReturn(mockXSession); + when(mockXSession.getClient()).thenReturn(mockXClient); + + ImmutableMap expectedMap = ImmutableMap.of("max_connections", "100"); + when(mockXClient.getSessionVariablesL()).thenReturn(expectedMap); + + // Add the connection mock + staticMetaDBUtil.when(() -> MetaDbUtil.getConnection()).thenReturn(mockConnection); + + // Act + ImmutableMap result = proxy.getSessionVariables(); + + // Assert + ImmutableMap expected = ImmutableMap.of("max_connections", "100"); + Assert.assertEquals(expected, result); + } + + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalBaselineHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalBaselineHandlerTest.java new file mode 100644 index 000000000..9cd123540 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalBaselineHandlerTest.java @@ -0,0 +1,261 @@ +package com.alibaba.polardbx.repo.mysql.handler; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.extension.ExtensionLoader; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.sync.SyncManagerHelper; +import com.alibaba.polardbx.executor.utils.ExplainExecutorUtil; +import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan; +import com.alibaba.polardbx.optimizer.core.planner.Planner; +import com.alibaba.polardbx.optimizer.core.row.Row; +import com.alibaba.polardbx.optimizer.planmanager.BaselineInfo; +import com.alibaba.polardbx.optimizer.planmanager.PlanInfo; +import com.alibaba.polardbx.optimizer.planmanager.PlanManager; +import com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.List; +import java.util.Map; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +/** + * @author fangwu + */ +public class LogicalBaselineHandlerTest { + @After + public void cleanup() { + MetaDbInstConfigManager.setConfigFromMetaDb(true); + } + + @BeforeClass + public static void setUp() { + MetaDbInstConfigManager.setConfigFromMetaDb(false); + } + + @Test + public void testBaselineDeletePlan() { + String sql = "select * from t where c1 = 1"; + try ( + MockedStatic extensionLoaderMockedStatic = mockStatic(ExtensionLoader.class); + MockedStatic syncManagerHelperMockedStatic = mockStatic(SyncManagerHelper.class)) { + extensionLoaderMockedStatic.when(() -> ExtensionLoader.load(Mockito.any())).thenReturn(null); + syncManagerHelperMockedStatic.when(() -> SyncManagerHelper.sync(Mockito.any(), Mockito.any())) + .thenReturn(null); + + LogicalBaselineHandler baselineHandler = new LogicalBaselineHandler(null); + PlanManager planManager = Mockito.mock(PlanManager.class); + Map baselineInfoMap = Maps.newHashMap(); + Map> schemaBaselineInfoMap = Maps.newHashMap(); + schemaBaselineInfoMap.put("test_schema", baselineInfoMap); + int targetId = 123; + BaselineInfo baselineInfo = new BaselineInfo(sql, Sets.newHashSet(Pair.of("t", "c1"))); + PlanInfo planInfo = mock(PlanInfo.class); + when(planInfo.getId()).thenReturn(targetId); + baselineInfo.addAcceptedPlan(planInfo); + baselineInfoMap.put(sql, baselineInfo); + Mockito.when(planManager.getBaselineMap()).thenReturn(schemaBaselineInfoMap); + List idList = Lists.newArrayList(); + ExecutionContext ec = new ExecutionContext(); + try { + baselineHandler.baselineLPCVD(idList, ec, "DELETE", planManager); + } catch (Exception e) { + e.printStackTrace(); + assert e.getMessage().equals( + "ERR-CODE: [TDDL-7001][ERR_BASELINE] Baseline error: not support baseline DELETE statement without baselineId "); + } + idList.add(11111111L); + idList.add(11111211L); + idList.add(-11111111L); + idList.add(Long.valueOf(targetId)); + Cursor c = baselineHandler.baselineLPCVD(idList, ec, "DELETE_PLAN", planManager); + + Row r = null; + r = c.next(); + Assert.assertTrue(r.getString(0).equals("11111111")); + Assert.assertTrue(r.getString(1).equals("not found")); + + r = c.next(); + Assert.assertTrue(r.getString(0).equals("11111211")); + Assert.assertTrue(r.getString(1).equals("not found")); + + r = c.next(); + Assert.assertTrue(r.getString(0).equals("-11111111")); + Assert.assertTrue(r.getString(1).equals("not found")); + + r = c.next(); + Assert.assertTrue(r.getString(0).equals("123")); + Assert.assertTrue(r.getString(1).equals("OK")); + } + } + + @Test + public void testBaselineDeleteBaseline() { + String sql = "select * from t where c1 = 1"; + try ( + MockedStatic extensionLoaderMockedStatic = mockStatic(ExtensionLoader.class); + MockedStatic syncManagerHelperMockedStatic = mockStatic(SyncManagerHelper.class)) { + extensionLoaderMockedStatic.when(() -> ExtensionLoader.load(Mockito.any())).thenReturn(null); + syncManagerHelperMockedStatic.when(() -> SyncManagerHelper.sync(Mockito.any(), Mockito.any())) + .thenReturn(null); + + LogicalBaselineHandler baselineHandler = new LogicalBaselineHandler(null); + PlanManager planManager = Mockito.mock(PlanManager.class); + Map baselineInfoMap = Maps.newHashMap(); + Map> schemaBaselineInfoMap = Maps.newHashMap(); + schemaBaselineInfoMap.put("test_schema", baselineInfoMap); + long targetId = sql.hashCode(); + BaselineInfo baselineInfo = new BaselineInfo(sql, Sets.newHashSet(Pair.of("t", "c1"))); + baselineInfoMap.put(sql, baselineInfo); + Mockito.when(planManager.getBaselineMap()).thenReturn(schemaBaselineInfoMap); + List idList = Lists.newArrayList(); + ExecutionContext ec = new ExecutionContext(); + try { + baselineHandler.baselineLPCVD(idList, ec, "DELETE", planManager); + } catch (Exception e) { + e.printStackTrace(); + assert e.getMessage().equals( + "ERR-CODE: [TDDL-7001][ERR_BASELINE] Baseline error: not support baseline DELETE statement without baselineId "); + } + idList.add(11111111L); + idList.add(11111211L); + idList.add(-11111111L); + idList.add(targetId); + Cursor c = baselineHandler.baselineLPCVD(idList, ec, "DELETE", planManager); + + Row r = null; + r = c.next(); + Assert.assertTrue(r.getString(0).equals("11111111")); + Assert.assertTrue(r.getString(1).equals("not found")); + + r = c.next(); + Assert.assertTrue(r.getString(0).equals("11111211")); + Assert.assertTrue(r.getString(1).equals("not found")); + + r = c.next(); + Assert.assertTrue(r.getString(0).equals("-11111111")); + Assert.assertTrue(r.getString(1).equals("not found")); + + r = c.next(); + Assert.assertTrue(r.getString(0).equals("1122414013")); + Assert.assertTrue(r.getString(1).equals("OK")); + } + } + + @Test + public void testBaselineAdd() { + String sql = "select * from t where c1 = 1"; + LogicalBaselineHandler baselineHandler = new LogicalBaselineHandler(null); + ExecutionContext ec = new ExecutionContext("test_schema"); + try { + baselineHandler.baselineAdd(null, sql, ec, false, false, null, null); + Assert.fail(); + } catch (Exception e) { + e.printStackTrace(); + assert e.getMessage().equals( + "ERR-CODE: [TDDL-7001][ERR_BASELINE] Baseline error: not support baseline add statement without hint "); + } + + String hint = "/*TDDL:BASELINE*/"; + Planner planner = Mockito.mock(Planner.class); + ExecutionPlan executionPlan = new ExecutionPlan(null, null, null); + executionPlan.setConstantParams(Maps.newHashMap()); + Mockito.when(planner.plan(Mockito.anyString(), Mockito.eq(ec))).thenReturn(executionPlan); + try { + baselineHandler.baselineAdd(hint, sql, ec, false, false, planner, null); + Assert.fail(); + } catch (Exception e) { + e.printStackTrace(); + assert e.getMessage().equals( + "ERR-CODE: [TDDL-7001][ERR_BASELINE] Baseline error: not support baseline add plan with generated column substitution "); + } + PlanManager planManager = Mockito.mock(PlanManager.class); + Map baselineInfoMap = Maps.newHashMap(); + BaselineInfo baselineInfo = new BaselineInfo(sql, Sets.newHashSet(Pair.of("t", "c1"))); + baselineInfoMap.put(sql, baselineInfo); + Mockito.when(planManager.getBaselineMap(Mockito.anyString())).thenReturn(baselineInfoMap); + executionPlan.setConstantParams(null); + + Cursor cursor = baselineHandler.baselineAdd(hint, sql, ec, false, true, planner, planManager); + Row r = cursor.next(); + String info = r.getString(2); + Assert.assertTrue(info.equals("ExecutionPlan exists")); + cursor.close(null); + + Mockito.when(planManager.getBaselineMap(Mockito.anyString())).thenReturn(Maps.newHashMap()); + Mockito.when(planManager.createBaselineInfo(Mockito.anyString(), Mockito.any(), Mockito.any())) + .thenReturn(baselineInfo); + try ( + MockedStatic extensionLoaderMockedStatic = mockStatic(ExtensionLoader.class); + MockedStatic syncManagerHelperMockedStatic = mockStatic(SyncManagerHelper.class); + MockedStatic planManagerUtil = mockStatic(PlanManagerUtil.class); + MockedStatic explainExecutorUtil = mockStatic(ExplainExecutorUtil.class);) { + extensionLoaderMockedStatic.when(() -> ExtensionLoader.load(Mockito.any())).thenReturn(null); + syncManagerHelperMockedStatic.when(() -> SyncManagerHelper.sync(Mockito.any(), Mockito.any())) + .thenReturn(null); + cursor = baselineHandler.baselineAdd(hint, sql, ec, false, true, planner, planManager); + r = cursor.next(); + info = r.getString(2); + Assert.assertTrue(info.startsWith("HINT BIND :")); + cursor.close(null); + + PlanInfo planInfo = new PlanInfo("", 1, 0.0D, "", "", 0); + planInfo.setFixed(true); + ArrayResultCursor result = new ArrayResultCursor("baseline"); + result.addColumn("PLAN", DataTypes.StringType); + result.addRow(new Object[] {"test plan"}); + planManagerUtil.when(() -> PlanManagerUtil.baselineSupported(Mockito.any())).thenReturn(true); + explainExecutorUtil.when(() -> ExplainExecutorUtil.explain(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(result); + PlanInfo planInfo1 = new PlanInfo("", 1, 0.0D, "", "", 0); + planInfo1.setFixed(true); + Mockito.when(planManager.createPlanInfo(Mockito.anyString(), Mockito.any(), Mockito.any(), Mockito.anyInt(), + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(planInfo1); + Mockito.when(planManager.getBaselineMap(Mockito.anyString())).thenReturn(baselineInfoMap); + baselineInfo.addAcceptedPlan(planInfo); + planInfo.setFixed(true); + + cursor = baselineHandler.baselineAdd(hint, sql, ec, true, false, planner, planManager); + r = cursor.next(); + info = r.getString(2); + Assert.assertTrue(info.equalsIgnoreCase("fixed plan exist")); + cursor.close(null); + cursor = baselineHandler.baselineAdd(hint, sql, ec, false, false, planner, planManager); + r = cursor.next(); + info = r.getString(2); + Assert.assertTrue(info.equalsIgnoreCase("fixed plan exist")); + cursor.close(null); + + planInfo.setFixed(false); + + cursor = baselineHandler.baselineAdd(hint, sql, ec, false, false, planner, planManager); + r = cursor.next(); + info = r.getString(2); + Assert.assertTrue(info.equalsIgnoreCase("ExecutionPlan exists")); + cursor.close(null); + + baselineInfo.getAcceptedPlans().clear(); + + cursor = baselineHandler.baselineAdd(hint, sql, ec, false, false, planner, planManager); + r = cursor.next(); + info = r.getString(2); + Assert.assertTrue(info.equalsIgnoreCase("OK")); + cursor.close(null); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowCreateViewMyHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowCreateViewMyHandlerTest.java new file mode 100644 index 000000000..cf0871313 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowCreateViewMyHandlerTest.java @@ -0,0 +1,52 @@ +package com.alibaba.polardbx.repo.mysql.handler; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.dal.LogicalShow; +import com.alibaba.polardbx.optimizer.view.InformationSchemaViewManager; +import com.alibaba.polardbx.optimizer.view.SystemTableView; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlShowCreateView; +import org.junit.Test; +import org.mockito.MockedStatic; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +public class LogicalShowCreateViewMyHandlerTest { + + @Test + public void testFetchSchemaName() { + LogicalShowCreateViewMyHandler logicalShowCreateViewMyHandler = + spy(new LogicalShowCreateViewMyHandler(mock(IRepository.class))); + + String schemaName = "INFORMATION_SCHEMA"; + String testTableName = "test_table"; + //mock input + LogicalShow logicalPlan = mock(LogicalShow.class); + ExecutionContext executionContext = mock(ExecutionContext.class); + + //mock process + SqlShowCreateView sqlShowCreateView = mock(SqlShowCreateView.class); + when(logicalPlan.getNativeSqlNode()).thenReturn(sqlShowCreateView); + SqlNode tableName = mock(SqlNode.class); + when(tableName.toString()).thenReturn(testTableName); + + when(sqlShowCreateView.getTableName()).thenReturn(tableName); + when(logicalPlan.getSchemaName()).thenReturn(schemaName); + + InformationSchemaViewManager viewManager = mock(InformationSchemaViewManager.class); + SystemTableView.Row row = mock(SystemTableView.Row.class); + when(viewManager.select(any())).thenReturn(row); + + try (MockedStatic mockedStatic = mockStatic(InformationSchemaViewManager.class)) { + mockedStatic.when(InformationSchemaViewManager::getInstance).thenReturn(viewManager); + //call, once the result of handle() not be null, that means we fetch schemaName from logicalShow successfully + Assert.assertTrue(logicalShowCreateViewMyHandler.handle(logicalPlan, executionContext) != null); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowIndexHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowIndexHandlerTest.java new file mode 100644 index 000000000..2efbc276f --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowIndexHandlerTest.java @@ -0,0 +1,75 @@ +package com.alibaba.polardbx.executor.handler; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.IndexesInfoSchemaRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.dal.BaseDalOperation; +import com.alibaba.polardbx.optimizer.utils.RelUtils; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlShowIndex; +import org.junit.Test; +import org.mockito.MockedStatic; + +import javax.sql.DataSource; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +public class LogicalShowIndexHandlerTest { + @Test + public void testShowSingleTableStatusWithColumnarMode() + throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + LogicalShowIndexHandler logicalShowIndexHandler = + spy(new LogicalShowIndexHandler(mock(IRepository.class))); + //input parameter + BaseDalOperation logicalPlan = mock(BaseDalOperation.class); + ExecutionContext ec = mock(ExecutionContext.class); + String schemaName = "test"; + String tableName = "test_table"; + SqlShowIndex sqlShowIndex = mock(SqlShowIndex.class); + when(logicalPlan.getNativeSqlNode()).thenReturn(sqlShowIndex); + SqlNode sqlNode = mock(SqlNode.class); + when(sqlShowIndex.getTableName()).thenReturn(sqlNode); + try (MockedStatic mockedRelUtils = mockStatic(RelUtils.class)) { + mockedRelUtils.when(() -> RelUtils.lastStringValue(any())).thenReturn(tableName); + //mock DataSourcek + DataSource mockDataSource = mock(DataSource.class); + MetaDbDataSource metaDbDataSource = mock(MetaDbDataSource.class); + try (MockedStatic mockedMetaDBDataSource = mockStatic(MetaDbDataSource.class)) { + mockedMetaDBDataSource.when(() -> MetaDbDataSource.getInstance()).thenReturn(metaDbDataSource); + when(metaDbDataSource.getDataSource()).thenReturn(mockDataSource); + //mock Table MetaDB Utils + try (MockedStatic mockedMetaDbUtil = mockStatic(MetaDbUtil.class)) { + List tables = new ArrayList<>(); + tables.add(mock(IndexesInfoSchemaRecord.class)); + tables.add(mock(IndexesInfoSchemaRecord.class)); + mockedMetaDbUtil.when(() -> MetaDbUtil.query(anyString(), any(), any(), any())) + .thenReturn(tables); + //verify + Method method = logicalShowIndexHandler.getClass() + .getDeclaredMethod("handleForColumnarMode", RelNode.class, ExecutionContext.class, + String.class); + method.setAccessible(true); + Cursor result = (Cursor) method.invoke(logicalShowIndexHandler, logicalPlan, ec, schemaName); + Assert.assertTrue( + result instanceof ArrayResultCursor && ((ArrayResultCursor) result).getRows().size() == 2); + } + } + } + } + +} \ No newline at end of file diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowTableStatusHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowTableStatusHandlerTest.java new file mode 100644 index 000000000..af1db861a --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowTableStatusHandlerTest.java @@ -0,0 +1,129 @@ +package com.alibaba.polardbx.repo.mysql.handler; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.spi.IRepository; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.ShowTablesSchemaRecord; +import com.alibaba.polardbx.gms.metadb.table.ViewsInfoRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.dal.LogicalShow; +import com.alibaba.polardbx.repo.mysql.spi.MyRepository; +import org.apache.calcite.sql.SqlShowTableStatus; +import org.junit.Test; +import org.mockito.MockedStatic; + +import javax.sql.DataSource; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +public class LogicalShowTableStatusHandlerTest { + @Test + public void testHandle() throws NoSuchFieldException, IllegalAccessException { + //1. prepare + LogicalShowTableStatusHandler logicalShowTableStatusHandler = + spy(new LogicalShowTableStatusHandler(mock(IRepository.class))); + + //doNothing when call showTables + doNothing().when(logicalShowTableStatusHandler).showTables(any(), any(), any(), any()); + List list = new ArrayList<>(); + list.add(new Object[] {}); + list.add(new Object[] {}); + doReturn(list).when( + logicalShowTableStatusHandler).showSingleTableStatusWithColumnarMode(any()); + + //make 'repo' in HandleCommon be 'MyRepository' + Field field = logicalShowTableStatusHandler.getClass().getSuperclass().getSuperclass().getDeclaredField("repo"); + field.setAccessible(true); + field.set(logicalShowTableStatusHandler, mock(MyRepository.class)); + + //set isColumnarMode = true + try (MockedStatic configDataModeMockedStatic = mockStatic(ConfigDataMode.class)) { + configDataModeMockedStatic.when(() -> ConfigDataMode.isColumnarMode()).thenReturn(true); + //2. input parameter + LogicalShow logicalShow = mock(LogicalShow.class); + ExecutionContext executionContext = mock(ExecutionContext.class); + //mock OptimizerContext.getContext and ExecutorContext.getContext + try (MockedStatic staticOptimizer = mockStatic(OptimizerContext.class)) { + staticOptimizer.when(() -> OptimizerContext.getContext(anyString())) + .thenReturn(mock(OptimizerContext.class)); + try (MockedStatic staticExecution = mockStatic(ExecutorContext.class)) { + staticExecution.when(() -> ExecutorContext.getContext(anyString())) + .thenReturn(mock(ExecutorContext.class)); + when(executionContext.getSchemaName()).thenReturn("test_db"); + ParamManager paramManager = mock(ParamManager.class); + when(paramManager.getBoolean(ConnectionParams.ENABLE_LOGICAL_TABLE_META)).thenReturn(true); + when(executionContext.getParamManager()).thenReturn(paramManager); + + LogicalInfoSchemaContext infoSchemaContext = mock(LogicalInfoSchemaContext.class); + doNothing().when(infoSchemaContext).prepareContextAndRepository(any()); + + //3. handle() utils + SqlShowTableStatus mockNativeSqlNode = mock(SqlShowTableStatus.class); + when(logicalShow.getNativeSqlNode()).thenReturn(mockNativeSqlNode); + + //4. verify + Cursor result = logicalShowTableStatusHandler.handle(logicalShow, executionContext); + Assert.assertTrue( + result instanceof ArrayResultCursor && ((ArrayResultCursor) result).getRows().size() == 2); + } + } + } + } + + @Test + public void testShowSingleTableStatusWithColumnarMode() + throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + LogicalShowTableStatusHandler logicalShowTableStatusHandler = + spy(new LogicalShowTableStatusHandler(mock(IRepository.class))); + //input parameter + String schemaName = "test"; + + //showSingleTableStatusWithColumnMode() utils + //mock DataSource + DataSource mockDataSource = mock(DataSource.class); + MetaDbDataSource metaDbDataSource = mock(MetaDbDataSource.class); + try (MockedStatic mockedMetaDBDataSource = mockStatic(MetaDbDataSource.class)) { + mockedMetaDBDataSource.when(() -> MetaDbDataSource.getInstance()).thenReturn(metaDbDataSource); + when(metaDbDataSource.getDataSource()).thenReturn(mockDataSource); + //mock Table MetaDB Utils + try (MockedStatic mockedMetaDbUtil = mockStatic(MetaDbUtil.class)) { + List tables = new ArrayList<>(); + tables.add(mock(ShowTablesSchemaRecord.class)); + tables.add(mock(ShowTablesSchemaRecord.class)); + mockedMetaDbUtil.when(() -> MetaDbUtil.query(anyString(), any(), any(), any())) + .thenReturn(tables); + //mock View MetaDB Utils + List views = new ArrayList<>(); + views.add(mock(ViewsInfoRecord.class)); + views.add(mock(ViewsInfoRecord.class)); + mockedMetaDbUtil.when(() -> MetaDbUtil.query(anyString(), any(), any())).thenReturn(views); + //verify + Method method = logicalShowTableStatusHandler.getClass() + .getDeclaredMethod("showSingleTableStatusWithColumnarMode", String.class); + method.setAccessible(true); + List result = (List) method.invoke(logicalShowTableStatusHandler, schemaName); + Assert.assertTrue(result.size() == 4); + } + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowVariablesMyHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowVariablesMyHandlerTest.java index cb260b862..595f255cd 100644 --- a/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowVariablesMyHandlerTest.java +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/LogicalShowVariablesMyHandlerTest.java @@ -1,5 +1,7 @@ package com.alibaba.polardbx.repo.mysql.handler; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.common.constants.SequenceAttribute; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.jdbc.BatchInsertPolicy; import com.alibaba.polardbx.common.jdbc.IConnection; @@ -9,8 +11,11 @@ import com.alibaba.polardbx.common.logical.ITPrepareStatement; import com.alibaba.polardbx.common.logical.ITStatement; import com.alibaba.polardbx.common.type.TransactionType; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.spi.ITransactionManager; import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.sequence.SequenceManagerProxy; import com.alibaba.polardbx.optimizer.utils.IConnectionHolder; import com.alibaba.polardbx.optimizer.utils.ITransaction; import com.alibaba.polardbx.optimizer.utils.ITransactionManagerUtil; @@ -23,13 +28,18 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; +import java.lang.reflect.Field; import java.sql.SQLException; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.TreeMap; import java.util.concurrent.atomic.AtomicLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class LogicalShowVariablesMyHandlerTest { private MockedStatic mockMetaDbInstConfigManager; @@ -46,6 +56,12 @@ public void testShowTransactionVariables() { LogicalShowVariablesMyHandler handler = new LogicalShowVariablesMyHandler(repository); TreeMap variables = new TreeMap<>(); + ExecutorContext executorContext = mock(ExecutorContext.class); + ExecutorContext.setContext("polardbx", executorContext); + ITransactionManager transactionManager = mock(ITransactionManager.class); + when(executorContext.getTransactionManager()).thenReturn(transactionManager); + when(transactionManager.supportXaTso()).thenReturn(true); + ExecutionContext executionContext = new ExecutionContext(); ITConnection mockTConnection = new MockTConnection(); executionContext.setConnection(mockTConnection); @@ -60,7 +76,7 @@ public void testShowTransactionVariables() { handler.collectCnVariables(variables, executionContext); for (Map.Entry kv : variables.entrySet()) { if ("enable_auto_commit_tso".equalsIgnoreCase(kv.getKey())) { - Assert.assertEquals(true, kv.getValue()); + Assert.assertEquals(false, kv.getValue()); } if ("enable_auto_savepoint".equalsIgnoreCase(kv.getKey())) { Assert.assertEquals(true, kv.getValue()); @@ -83,6 +99,50 @@ public void testShowTransactionVariables() { } } + @Test + public void showSqlLogBinVariablesTest() throws NoSuchFieldException, IllegalAccessException { + MyRepository repository = new MyRepository(); + LogicalShowVariablesMyHandler handler = new LogicalShowVariablesMyHandler(repository); + TreeMap variables = new TreeMap<>(); + + ExecutorContext executorContext = mock(ExecutorContext.class); + ExecutorContext.setContext("polardbx", executorContext); + ITransactionManager transactionManager = mock(ITransactionManager.class); + when(executorContext.getTransactionManager()).thenReturn(transactionManager); + when(transactionManager.supportXaTso()).thenReturn(true); + ExecutionContext executionContext = new ExecutionContext(); + ITConnection mockTConnection = new MockTConnection(); + executionContext.setConnection(mockTConnection); + Map extraServerVariables = new HashMap<>(); + SequenceManagerProxy proxy = mock(SequenceManagerProxy.class); + when(proxy.areAllSequencesSameType("polardbx", + new SequenceAttribute.Type[] {SequenceAttribute.Type.GROUP, SequenceAttribute.Type.TIME})).thenReturn(true); + Field instaceField = SequenceManagerProxy.class.getDeclaredField("instance"); + instaceField.setAccessible(true); + instaceField.set(null, proxy); + + executionContext.setExtraServerVariables(extraServerVariables); + executionContext.setSchemaName("polardbx"); + // Default value. + handler.updateReturnVariables(variables, executionContext); + for (Map.Entry kv : variables.entrySet()) { + if ("sql_log_bin_x".equalsIgnoreCase(kv.getKey())) { + Assert.assertEquals("ON", kv.getValue()); + } + } + + extraServerVariables.put(ICdcManager.SQL_LOG_BIN, false); + executionContext.setExtraServerVariables(extraServerVariables); + executionContext.setSchemaName("polardbx"); + // Default value. + handler.updateReturnVariables(variables, executionContext); + for (Map.Entry kv : variables.entrySet()) { + if ("sql_log_bin_x".equalsIgnoreCase(kv.getKey())) { + Assert.assertEquals("OFF", kv.getValue()); + } + } + } + private static class MockTransaction implements ITransaction { @Override diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/MyBaseDalHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/MyBaseDalHandlerTest.java new file mode 100644 index 000000000..5119992fd --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/MyBaseDalHandlerTest.java @@ -0,0 +1,190 @@ +package com.alibaba.polardbx.repo.mysql.handler; + +import com.alibaba.polardbx.common.charset.CharsetName; +import com.alibaba.polardbx.common.privilege.MySQLPrivilegesName; +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaCollationsHandler; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.ColumnsInfoSchemaRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.dal.BaseDalOperation; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlShow; +import org.junit.Test; +import org.mockito.MockedStatic; + +import javax.sql.DataSource; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class MyBaseDalHandlerTest { + + @Test + public void testHandleShowCollationInColumnarMode() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + MyBaseDalHandler myBaseDalHandler = mock(MyBaseDalHandler.class); + + String schemaName = "test_schema"; + + BaseDalOperation logicalPlan = mock(BaseDalOperation.class); + ExecutionContext ec = mock(ExecutionContext.class); + when(logicalPlan.getSchemaName()).thenReturn(schemaName); + + //verify + Method method = myBaseDalHandler.getClass() + .getDeclaredMethod("handleShowCollationInColumnarMode", RelNode.class, ExecutionContext.class); + method.setAccessible(true); + Cursor result = (Cursor) method.invoke(myBaseDalHandler, logicalPlan, ec); + Assert.assertTrue(result instanceof ArrayResultCursor + && ((ArrayResultCursor) result).getRows().size() == InformationSchemaCollationsHandler.COLLATIONS.length); + } + + @Test + public void testHandleShowCharacterSetInColumnarMode() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + MyBaseDalHandler myBaseDalHandler = mock(MyBaseDalHandler.class); + + String schemaName = "test_schema"; + + BaseDalOperation logicalPlan = mock(BaseDalOperation.class); + ExecutionContext ec = mock(ExecutionContext.class); + when(logicalPlan.getSchemaName()).thenReturn(schemaName); + + //verify + Method method = myBaseDalHandler.getClass() + .getDeclaredMethod("handleShowCharacterSetInColumnarMode", RelNode.class, ExecutionContext.class); + method.setAccessible(true); + Cursor result = (Cursor) method.invoke(myBaseDalHandler, logicalPlan, ec); + Assert.assertTrue(result instanceof ArrayResultCursor + && ((ArrayResultCursor) result).getRows().size() == CharsetName.values().length); + } + + @Test + public void testHandleShowPrivilegesInColumnarMode() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + MyBaseDalHandler myBaseDalHandler = mock(MyBaseDalHandler.class); + + String schemaName = "test_schema"; + + BaseDalOperation logicalPlan = mock(BaseDalOperation.class); + ExecutionContext ec = mock(ExecutionContext.class); + when(logicalPlan.getSchemaName()).thenReturn(schemaName); + + //verify + Method method = myBaseDalHandler.getClass() + .getDeclaredMethod("handleShowPrivilegesInColumnarMode", RelNode.class, ExecutionContext.class); + method.setAccessible(true); + Cursor result = (Cursor) method.invoke(myBaseDalHandler, logicalPlan, ec); + Assert.assertTrue(result instanceof ArrayResultCursor + && ((ArrayResultCursor) result).getRows().size() == MySQLPrivilegesName.values().length); + } + + @Test + public void testHandleShowColumnInColumnarMode() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + String schemaName = "test_schema"; + String tableName = "test_table"; + MyBaseDalHandler myBaseDalHandler = mock(MyBaseDalHandler.class); + + BaseDalOperation logicalPlan = mock(BaseDalOperation.class); + ExecutionContext ec = mock(ExecutionContext.class); + + //mock extractSchemaTableNameForShowColumns + try (MockedStatic mockedConfigDataMode = mockStatic(ConfigDataMode.class)) { + mockedConfigDataMode.when(() -> ConfigDataMode.isPolarDbX()).thenReturn(true); + when(logicalPlan.getKind()).thenReturn(SqlKind.SHOW); + SqlShow sqlShow = mock(SqlShow.class); + when(logicalPlan.getNativeSqlNode()).thenReturn(sqlShow); + when(logicalPlan.getNativeSql()).thenReturn("SHOW FULL COLUMNS"); + when(logicalPlan.getSchemaName()).thenReturn(schemaName); + SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); + when(sqlShow.getTableName()).thenReturn(sqlIdentifier); + when(sqlIdentifier.getLastName()).thenReturn(tableName); + + //mock DataSourcek + DataSource mockDataSource = mock(DataSource.class); + MetaDbDataSource metaDbDataSource = mock(MetaDbDataSource.class); + try (MockedStatic mockedMetaDBDataSource = mockStatic(MetaDbDataSource.class)) { + mockedMetaDBDataSource.when(() -> MetaDbDataSource.getInstance()).thenReturn(metaDbDataSource); + when(metaDbDataSource.getDataSource()).thenReturn(mockDataSource); + //mock Table MetaDB Utils + try (MockedStatic mockedMetaDbUtil = mockStatic(MetaDbUtil.class)) { + List tables = generateColumnsInfoSchemaRecords(); + mockedMetaDbUtil.when(() -> MetaDbUtil.query(anyString(), any(), any(), any())) + .thenReturn(tables); + //verify + Method method = myBaseDalHandler.getClass() + .getDeclaredMethod("handleShowColumnInColumnarMode", RelNode.class, ExecutionContext.class); + method.setAccessible(true); + Cursor result = (Cursor) method.invoke(myBaseDalHandler, logicalPlan, ec); + Assert.assertTrue( + result instanceof ArrayResultCursor && ((ArrayResultCursor) result).getRows().size() == 2); + } + } + } + } + + List generateColumnsInfoSchemaRecords() { + ColumnsInfoSchemaRecord record1 = new ColumnsInfoSchemaRecord(); + record1.tableSchema = "test_schema1"; + record1.tableName = "test_table1"; + record1.columnName = "test_column1"; + record1.ordinalPosition = 1L; + record1.columnDefault = "DEFAULT_VALUE1"; + record1.isNullable = "NO"; + record1.dataType = "INT"; + record1.characterMaximumLength = 0L; + record1.characterOctetLength = 0L; + record1.numericPrecision = 11L; + record1.numericScale = 0L; + record1.numericScaleNull = false; + record1.datetimePrecision = 0L; + record1.characterSetName = "utf8"; + record1.collationName = "utf8_general_ci"; + record1.columnType = "INT(11)"; + record1.columnKey = ""; + record1.extra = ""; + record1.privileges = "SELECT"; + record1.columnComment = "First Test Column"; + record1.generationExpression = ""; + + ColumnsInfoSchemaRecord record2 = new ColumnsInfoSchemaRecord(); + record2.tableSchema = "test_schema2"; + record2.tableName = "test_table2"; + record2.columnName = "test_column2"; + record2.ordinalPosition = 2L; + record2.columnDefault = null; + record2.isNullable = "YES"; + record2.dataType = "VARCHAR"; + record2.characterMaximumLength = 255L; + record2.characterOctetLength = 765L; + record2.numericPrecision = 0L; + record2.numericScale = 0L; + record2.numericScaleNull = true; + record2.datetimePrecision = 6L; + record2.characterSetName = "latin1"; + record2.collationName = "latin1_swedish_ci"; + record2.columnType = "VARCHAR(255)"; + record2.columnKey = "MUL"; + record2.extra = "on update CURRENT_TIMESTAMP"; + record2.privileges = "SELECT,INSERT,UPDATE"; + record2.columnComment = "Second Test Column"; + record2.generationExpression = "CURRENT_TIMESTAMP()"; + return new ArrayList<>(Arrays.asList(record1, record2)); + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/MySingleTableModifyReturningHandlerTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/MySingleTableModifyReturningHandlerTest.java new file mode 100644 index 000000000..32cbdb2fe --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/handler/MySingleTableModifyReturningHandlerTest.java @@ -0,0 +1,45 @@ +package com.alibaba.polardbx.repo.mysql.handler; + +import com.alibaba.polardbx.common.logical.ITConnection; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.executor.cursor.Cursor; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.BaseTableOperation; +import com.alibaba.polardbx.repo.mysql.spi.MyJdbcHandler; +import com.alibaba.polardbx.repo.mysql.spi.MyRepository; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Field; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class MySingleTableModifyReturningHandlerTest { + @Test + public void testWithReturningSequentialPolicy() throws NoSuchFieldException, IllegalAccessException { + MyRepository repo = new MockMyRepository(); + MySingleTableModifyReturningHandler handler = new MySingleTableModifyReturningHandler(repo); + ExecutionContext executionContext = new ExecutionContext(); + executionContext.setReturning("returning"); + executionContext.getParamManager().getProps().put(ConnectionProperties.SEQUENTIAL_CONCURRENT_POLICY, "true"); + + BaseTableOperation logicalPlan = mock(BaseTableOperation.class); + + long oldLastInsertId = 1L; + ITConnection connection = mock(ITConnection.class); + executionContext.setConnection(connection); + when(connection.getLastInsertId()).thenReturn(oldLastInsertId); + Cursor cursor = handler.handleInner(logicalPlan, executionContext); + Field field = cursor.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredField("inited"); + field.setAccessible(true); + // Should delay init. + Assert.assertFalse((Boolean) field.get(cursor)); + } + + private static class MockMyRepository extends MyRepository { + protected MyJdbcHandler createQueryHandler(ExecutionContext executionContext) { + return mock(MyJdbcHandler.class); + } + } +} diff --git a/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/spi/MyPhyTableModifyReturningCursorTest.java b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/spi/MyPhyTableModifyReturningCursorTest.java new file mode 100644 index 000000000..921d01e75 --- /dev/null +++ b/polardbx-executor/src/test/java/com/alibaba/polardbx/repo/mysql/spi/MyPhyTableModifyReturningCursorTest.java @@ -0,0 +1,73 @@ +package com.alibaba.polardbx.repo.mysql.spi; + +import com.alibaba.polardbx.common.logical.ITConnection; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.optimizer.biv.MockResultSetMetaData; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.BaseTableOperation; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Field; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class MyPhyTableModifyReturningCursorTest { + @Test + public void test() throws SQLException, NoSuchFieldException, IllegalAccessException { + MyRepository repo = mock(MyRepository.class); + MyJdbcHandler handler = mock(MyJdbcHandler.class); + when(handler.executeUpdate(any())).thenReturn(new int[] {1}); + ResultSet rs = mock(ResultSet.class); + when(handler.getResultSet()).thenReturn(rs); + MockResultSetMetaData meta = new MockResultSetMetaData(new ArrayList<>(), new HashMap<>()); + when(rs.getMetaData()).thenReturn(meta); + ExecutionContext ec = new ExecutionContext(); + when(repo.createQueryHandler(ec)).thenReturn(handler); + ITConnection connection = mock(ITConnection.class); + ec.setConnection(connection); + BaseTableOperation logicalPlan = mock(BaseTableOperation.class); + ec.getParamManager().getProps().put(ConnectionProperties.SEQUENTIAL_CONCURRENT_POLICY, "true"); + + MyPhyTableModifyReturningCursor cursor = new MyPhyTableModifyReturningCursor(ec, logicalPlan, repo, + 0, null, null); + + Field field = cursor.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredField("inited"); + field.setAccessible(true); + // Should delay init. + Assert.assertFalse((Boolean) field.get(cursor)); + // Should execute in doInit. + cursor.doInit(); + Assert.assertTrue((Boolean) field.get(cursor)); + } + + @Test + public void test1() throws SQLException, NoSuchFieldException, IllegalAccessException { + MyRepository repo = mock(MyRepository.class); + MyJdbcHandler handler = mock(MyJdbcHandler.class); + when(handler.executeUpdate(any())).thenReturn(new int[] {1}); + ResultSet rs = mock(ResultSet.class); + when(handler.getResultSet()).thenReturn(rs); + MockResultSetMetaData meta = new MockResultSetMetaData(new ArrayList<>(), new HashMap<>()); + when(rs.getMetaData()).thenReturn(meta); + ExecutionContext ec = new ExecutionContext(); + when(repo.createQueryHandler(ec)).thenReturn(handler); + ITConnection connection = mock(ITConnection.class); + ec.setConnection(connection); + BaseTableOperation logicalPlan = mock(BaseTableOperation.class); + ec.getParamManager().getProps().put(ConnectionProperties.SEQUENTIAL_CONCURRENT_POLICY, "false"); + ec.getParamManager().getProps().put(ConnectionProperties.FIRST_THEN_CONCURRENT_POLICY, "true"); + MyPhyTableModifyReturningCursor cursor = new MyPhyTableModifyReturningCursor(ec, logicalPlan, repo, + 0, null, null); + + Field field = cursor.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredField("inited"); + field.setAccessible(true); + Assert.assertTrue((Boolean) field.get(cursor)); + } +} diff --git a/polardbx-executor/src/test/resources/5a91a2f23573.orc b/polardbx-executor/src/test/resources/5a91a2f23573.orc new file mode 100644 index 000000000..c932bd63b Binary files /dev/null and b/polardbx-executor/src/test/resources/5a91a2f23573.orc differ diff --git a/polardbx-executor/src/test/resources/com/alibaba/polardbx/executor/fragmenter/PhysicalPlanTest.phy.yml b/polardbx-executor/src/test/resources/com/alibaba/polardbx/executor/fragmenter/PhysicalPlanTest.phy.yml index 0ef656aca..af4359029 100644 --- a/polardbx-executor/src/test/resources/com/alibaba/polardbx/executor/fragmenter/PhysicalPlanTest.phy.yml +++ b/polardbx-executor/src/test/resources/com/alibaba/polardbx/executor/fragmenter/PhysicalPlanTest.phy.yml @@ -9,11 +9,11 @@ output partitioning: single [] parallelism: 1 hashagg(group="id") remotesource(sourcefragmentids=[0, 1], type=recordtype(integer id)) - + fragment 0 output partitioning: fixed [0] parallelism: 1 logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `id` from `t_shard_id1` as `t_shard_id1`") - + fragment 1 output partitioning: fixed [0] parallelism: 1 logicalview(tables="[0000-0003].t_shard_id2", shardcount=4, sql="select `id` from `t_shard_id2` as `t_shard_id2`") \ No newline at end of file diff --git a/polardbx-executor/src/test/resources/com/alibaba/polardbx/executor/vectorized/comparison/ComparisonBinaryOperatorsTest.yml b/polardbx-executor/src/test/resources/com/alibaba/polardbx/executor/vectorized/compare/ComparisonBinaryOperatorsTest.yml similarity index 100% rename from polardbx-executor/src/test/resources/com/alibaba/polardbx/executor/vectorized/comparison/ComparisonBinaryOperatorsTest.yml rename to polardbx-executor/src/test/resources/com/alibaba/polardbx/executor/vectorized/compare/ComparisonBinaryOperatorsTest.yml diff --git a/polardbx-executor/src/test/resources/direct_blob_type.orc b/polardbx-executor/src/test/resources/direct_blob_type.orc new file mode 100644 index 000000000..256a05b1e Binary files /dev/null and b/polardbx-executor/src/test/resources/direct_blob_type.orc differ diff --git a/polardbx-gms/pom.xml b/polardbx-gms/pom.xml index 0e7e646cf..cd9051ed7 100644 --- a/polardbx-gms/pom.xml +++ b/polardbx-gms/pom.xml @@ -33,7 +33,6 @@ com.alibaba druid - ${druid.version} @@ -41,11 +40,6 @@ mysql-connector-java - - commons-logging - commons-logging-api - - junit junit @@ -75,28 +69,29 @@ org.apache.hadoop - hadoop-client + hadoop-aws ${hadoop.version} + + + org.apache.hadoop + hadoop-azure - commons-logging - commons-logging + org.apache.httpcomponents + httpclient - slf4j-api - org.slf4j + org.eclipse.jetty + jetty-util-ajax - - - org.apache.hadoop - hadoop-aws ${hadoop.version} - org.apache.hadoop - hadoop-azure - ${hadoop.version} + org.eclipse.jetty + jetty-util-ajax + ${jetty.version} + test diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/config/impl/InstConfUtil.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/config/impl/InstConfUtil.java index 9484f9717..5a48b1caf 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/config/impl/InstConfUtil.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/config/impl/InstConfUtil.java @@ -133,7 +133,7 @@ public static int getMinute(String time) { } public static Boolean getBool(BooleanConfigParam c) { - String val = MetaDbInstConfigManager.getInstance().propertiesInfoMap.getProperty(c.getName()); + String val = MetaDbInstConfigManager.getInstance().getCnVariableConfigMap().getProperty(c.getName()); if (val == null) { val = c.getDefault(); } @@ -184,7 +184,7 @@ public static float getFloat(FloatConfigParam c) { public static long getLong(LongConfigParam c) { /* See if it's specified. */ - String val = MetaDbInstConfigManager.getInstance().propertiesInfoMap.getProperty(c.getName()); + String val = MetaDbInstConfigManager.getInstance().getCnVariableConfigMap().getProperty(c.getName()); if (val == null) { val = c.getDefault(); } @@ -206,7 +206,7 @@ public static long getLong(LongConfigParam c) { } public static int getInt(IntConfigParam c) { - String val = MetaDbInstConfigManager.getInstance().propertiesInfoMap.getProperty(c.getName()); + String val = MetaDbInstConfigManager.getInstance().getCnVariableConfigMap().getProperty(c.getName()); if (val == null) { val = c.getDefault(); } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/config/impl/MetaDbInstConfigManager.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/config/impl/MetaDbInstConfigManager.java index 66888dd81..46aae09e7 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/config/impl/MetaDbInstConfigManager.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/config/impl/MetaDbInstConfigManager.java @@ -77,9 +77,9 @@ protected MetaDbInstConfigManager() { @Override protected void doInit() { - SystemDefaultPropertyHelper.initDefaultInstConfig(); Properties newProps = null; if (configFromMetaDb) { + SystemDefaultPropertyHelper.initDefaultInstConfig(); try (Connection conn = MetaDbDataSource.getInstance().getConnection()) { newProps = loadPropertiesFromMetaDbConn(conn); } catch (Throwable ex) { diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/engine/FileSystemUtils.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/engine/FileSystemUtils.java index 8dc73f3e2..0cfa802c4 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/engine/FileSystemUtils.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/engine/FileSystemUtils.java @@ -17,9 +17,13 @@ package com.alibaba.polardbx.gms.engine; import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.oss.ColumnarFileType; import com.alibaba.polardbx.common.oss.filesystem.FileSystemRateLimiter; import com.alibaba.polardbx.common.oss.filesystem.GuavaFileSystemRateLimiter; +import com.alibaba.polardbx.common.oss.filesystem.GuavaFileSystemRateLimiter; +import com.alibaba.polardbx.common.oss.filesystem.FSOSSInputStream; import com.alibaba.polardbx.common.oss.filesystem.OSSFileSystem; +import com.alibaba.polardbx.common.oss.filesystem.OSSFileSystemStore; import com.alibaba.polardbx.common.oss.filesystem.cache.CachingFileSystem; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.properties.ConnectionProperties; @@ -31,9 +35,10 @@ import com.alibaba.polardbx.gms.topology.ServerInstIdManager; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; -import org.apache.hadoop.fs.Seekable; +import org.apache.hadoop.fs.PositionedReadable; import java.io.File; import java.io.IOException; @@ -43,7 +48,6 @@ import java.util.Optional; public class FileSystemUtils { - public static final String DELIMITER = "/"; private static final File LOCAL_DIRECTORY = new File("/tmp/"); @@ -120,6 +124,7 @@ public static boolean fileExists(String fileName, Engine engine, boolean isColum public static byte[] readFullyFile(String fileName, Engine engine, boolean isColumnar) { FileSystem fileSystem = FileSystemManager.getFileSystemGroup(engine).getMaster(); try (InputStream in = fileSystem.open(buildPath(fileSystem, fileName, isColumnar))) { + // TODO(siyun): migrate to use cached file system return IOUtils.toByteArray(in); } catch (IOException e) { throw GeneralUtil.nestedException(e); @@ -133,8 +138,36 @@ public static void readFile(String fileName, int offset, int length, byte[] outp boolean isColumnar) { FileSystem fileSystem = FileSystemManager.getFileSystemGroup(engine).getMaster(); try (InputStream in = fileSystem.open(buildPath(fileSystem, fileName, isColumnar))) { - ((Seekable) in).seek(offset); - IOUtils.read(in, output, 0, length); + ((PositionedReadable) in).readFully(offset, output, 0, length); + } catch (IOException e) { + throw GeneralUtil.nestedException(e); + } + } + + public static FSDataInputStream openStreamFileWithBuffer(String fileName, Engine engine, boolean isColumnar) { + FileSystem fileSystem = FileSystemManager.getFileSystemGroup(engine).getMaster(); + Path filePath = buildPath(fileSystem, fileName, isColumnar); + try { + if (engine == Engine.OSS) { + // This will bypass cache filesystem for OSS + OSSFileSystem ossFileSystem = (OSSFileSystem) ((CachingFileSystem) fileSystem).getDataTier(); + OSSFileSystemStore ossFileSystemStore = ossFileSystem.getStore(); + String ossKeyPath = ossFileSystem.pathToKey(filePath); + return new FSDataInputStream(new FSOSSInputStream(ossFileSystemStore, ossKeyPath, + DynamicConfig.getInstance().getOssStreamBufferSize())); + } else { + return fileSystem.open(filePath); + } + } catch (IOException e) { + throw GeneralUtil.nestedException(e); + } + } + + public static FSDataInputStream openStreamFile(String fileName, Engine engine, boolean isColumnar) { + FileSystem fileSystem = FileSystemManager.getFileSystemGroup(engine).getMaster(); + Path filePath = buildPath(fileSystem, fileName, isColumnar); + try { + return fileSystem.open(filePath); } catch (IOException e) { throw GeneralUtil.nestedException(e); } @@ -168,6 +201,15 @@ private static String getColdDataDirectory() { return ServerInstIdManager.getInstance().getMasterInstId(); } + public static String getSuffix(String fileName) { + return fileName.substring(fileName.lastIndexOf('.') + 1); + } + + public static ColumnarFileType getFileType(String fileName) { + String suffix = getSuffix(fileName); + return ColumnarFileType.of(suffix); + } + public static GuavaFileSystemRateLimiter newRateLimiter() { // fetch rate params Map globalVariables = InstConfUtil.fetchLongConfigs( diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/engine/decorator/impl/ABSFileSystemWrapper.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/engine/decorator/impl/ABSFileSystemWrapper.java index 544f9c9bd..d8603bf71 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/engine/decorator/impl/ABSFileSystemWrapper.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/engine/decorator/impl/ABSFileSystemWrapper.java @@ -24,4 +24,4 @@ public class ABSFileSystemWrapper extends NativeAzureFileSystem implements FileS public Statistics getInnerStatistics() { return statistics; } -} +} \ No newline at end of file diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ha/impl/StorageHaManager.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ha/impl/StorageHaManager.java index 1846a98a3..a0134bd98 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ha/impl/StorageHaManager.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ha/impl/StorageHaManager.java @@ -144,7 +144,7 @@ public class StorageHaManager extends AbstractLifecycle { protected HaSwitcher metaDbHaSwitcher; protected final static int MAX_QUEUE_LEN = 10000; - protected volatile int checkStorageTaskPeriod = 5000; // 5s + protected volatile int checkStorageTaskPeriod = 2000; // 5s protected int refreshStorageInfoOfMetaDbTaskIntervalDelay = checkStorageTaskPeriod * 3; // 15s protected int refreshStorageInfoOfMetaDbTaskInterval = checkStorageTaskPeriod * 12; // 60s @@ -209,8 +209,17 @@ public class StorageHaManager extends AbstractLifecycle { private boolean allowFollowRead; + public interface StorageInfoConfigSubListener extends ConfigListener { + String getSubListenerName(); + } + + protected Map storageInfoSubListenerMap = new ConcurrentHashMap<>(); + protected static class StorageInfoConfigListener implements ConfigListener { + public StorageInfoConfigListener() { + } + @Override public void onHandleConfig(String dataId, long newOpVersion) { String instId = InstIdUtil.getInstIdFromStorageInfoDataId(dataId); @@ -220,7 +229,54 @@ public void onHandleConfig(String dataId, long newOpVersion) { if (ConfigDataMode.isMasterMode()) { StorageHaManager.getInstance().updateGroupConfigVersion(); } + + try { + Map storageInfoSubListenerMap = + StorageHaManager.getInstance().getStorageInfoSubListenerMap(); + for (Map.Entry subListenerItem : storageInfoSubListenerMap.entrySet()) { + String subListenerName = subListenerItem.getKey(); + StorageInfoConfigSubListener subListenerVal = subListenerItem.getValue(); + try { + subListenerVal.onHandleConfig(dataId, newOpVersion); + } catch (Throwable ex) { + logger.warn(String.format("Failed to handle subListener[%s], err is %s", subListenerName, + ex.getMessage()), ex); + } + } + } catch (Throwable ex) { + logger.warn(ex); + } + } + } + + protected Map getStorageInfoSubListenerMap() { + return storageInfoSubListenerMap; + } + + /** + * Register a sub-listener + *
+     * The list of sub-listeners which is called by StorageInfoConfigListener,
+     * sub-listeners is used for those non-gms module to handle the change of rw-dn-list.
+     * the sub-listener should just to refresh some in-memory meta data.
+     * 
+ */ + public void registerStorageInfoSubListener(StorageInfoConfigSubListener subListener) { + if (subListener == null) { + return; + } + String subListenerName = subListener.getSubListenerName(); + storageInfoSubListenerMap.putIfAbsent(subListenerName, subListener); + } + + /** + * Unegister a sub-listener + */ + public void unregisterStorageInfoSubListener(String subListenerName) { + if (StringUtils.isEmpty(subListenerName)) { + return; } + storageInfoSubListenerMap.remove(subListenerName); } public static StorageHaManager getInstance() { diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/locality/LocalityDesc.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/locality/LocalityDesc.java index aead63724..00950bf20 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/locality/LocalityDesc.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/locality/LocalityDesc.java @@ -24,7 +24,6 @@ import com.alibaba.polardbx.gms.topology.GroupDetailInfoRecord; import lombok.Value; import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.yarn.webapp.hamlet2.Hamlet; import java.util.ArrayList; import java.util.Arrays; diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/GmsSystemTables.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/GmsSystemTables.java index f542939c7..f5a7409d1 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/GmsSystemTables.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/GmsSystemTables.java @@ -73,10 +73,13 @@ public class GmsSystemTables { public static final String COLUMNAR_TABLE_MAPPING = "columnar_table_mapping"; public static final String COLUMNAR_TABLE_EVOLUTION = "columnar_table_evolution"; public static final String COLUMNAR_COLUMN_EVOLUTION = "columnar_column_evolution"; + public static final String COLUMNAR_PARTITION_EVOLUTION = "columnar_partition_evolution"; public static final String COLUMNAR_CONFIG = "columnar_config"; public static final String COLUMNAR_LEASE = "columnar_lease"; + public static final String COLUMNAR_DUPLICATES = "columnar_duplicates"; public static final String COLUMNAR_TASK = "columnar_task"; public static final String COLUMNAR_TASK_CONFIG = "columnar_task_config"; + public static final String COLUMNAR_PURGE_HISTORY = "columnar_purge_history"; public static final String FILE_STORAGE_INFO = "file_storage_info"; public static final String STORAGE_POOL_INFO = "storage_pool_info"; @@ -93,6 +96,11 @@ public class GmsSystemTables { public static final String JOIN_GROUP_INFO = "join_group_info"; public static final String JOIN_GROUP_TABLE_DETAIL = "join_group_table_detail"; + /** + * ttl20 + */ + public static final String TTL_INFO = "ttl_info"; + /** * MPP Node Info */ @@ -107,7 +115,11 @@ public class GmsSystemTables { * Global Secondary Index */ public static final String BACKFILL_OBJECTS = "backfill_objects"; + public static final String BACKFILL_SAMPLE_ROWS = "backfill_sample_rows"; + public static final String BACKFILL_SAMPLE_ROWS_ARCHIVE = "backfill_sample_rows_archive"; public static final String PHYSICAL_BACKFILL_OBJECTS = "physical_backfill_objects"; + + public static final String IMPORT_TABLESPACE_INFO_STAT = "import_tablespace_info_stat"; public static final String FILE_STORAGE_BACKFILL_OBJECTS = "file_storage_backfill_objects"; public static final String CHECKER_REPORTS = "checker_reports"; @@ -236,6 +248,8 @@ public class GmsSystemTables { public final static String RPL_FULL_VALID_DIFF_TABLE = "rpl_full_valid_diff"; + public final static String RPL_SYNC_POINT_TABLE = "rpl_sync_point"; + public final static String DDL_PLAN = "ddl_plan"; public final static String LEASE = "lease"; @@ -248,10 +262,16 @@ public class GmsSystemTables { public final static String TRX_LOG_STATUS = "trx_log_status"; + public final static String CHECK_CCI_STATUS = "check_cci_status"; + + public final static String DEADLOCKS = "deadlocks"; + public final static String ENCDB_RULE = "encdb_rule"; public final static String ENCDB_KEY = "encdb_key"; + public final static String CDC_SYNC_POINT_META = "cdc_sync_point_meta"; + static { register(DUAL); register(SCHEMA_CHANGE); @@ -276,8 +296,11 @@ public class GmsSystemTables { register(COLUMNAR_TABLE_MAPPING); register(COLUMNAR_TABLE_EVOLUTION); register(COLUMNAR_COLUMN_EVOLUTION); + register(COLUMNAR_PARTITION_EVOLUTION); register(COLUMNAR_CONFIG); register(COLUMNAR_LEASE); + register(COLUMNAR_DUPLICATES); + register(COLUMNAR_PURGE_HISTORY); register(FILE_STORAGE_INFO); register(STORAGE_POOL_INFO); register(COLUMNS); @@ -293,6 +316,8 @@ public class GmsSystemTables { register(NODE_INFO); register(JAVA_FUNCTIONS); register(BACKFILL_OBJECTS); + register(BACKFILL_SAMPLE_ROWS); + register(BACKFILL_SAMPLE_ROWS_ARCHIVE); register(FILE_STORAGE_BACKFILL_OBJECTS); register(CHANGESET_OBJECT); register(BASELINE_INFO); @@ -365,10 +390,14 @@ public class GmsSystemTables { register(FOREIGN_KEY); register(FOREIGN_KEY_COLS); register(PHYSICAL_BACKFILL_OBJECTS); + register(IMPORT_TABLESPACE_INFO_STAT); register(TRX_LOG_STATUS); + register(DEADLOCKS); register(LOCKING_FUNCTIONS); register(ENCDB_RULE); register(ENCDB_KEY); + register(CDC_SYNC_POINT_META); + register(TTL_INFO); } private static void register(String systemTableName) { diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/cdc/SyncPointMetaAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/cdc/SyncPointMetaAccessor.java new file mode 100644 index 000000000..44aef3dc1 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/cdc/SyncPointMetaAccessor.java @@ -0,0 +1,54 @@ +package com.alibaba.polardbx.gms.metadb.cdc; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.gms.metadb.GmsSystemTables; +import com.alibaba.polardbx.gms.metadb.accessor.AbstractAccessor; +import com.alibaba.polardbx.gms.util.MetaDbUtil; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author yaozhili + */ +public class SyncPointMetaAccessor extends AbstractAccessor { + private static final Logger logger = LoggerFactory.getLogger(SyncPointMetaAccessor.class); + + private final static String INSERT_SQL = + "INSERT INTO " + GmsSystemTables.CDC_SYNC_POINT_META + " (id, participants, tso, valid) values (?, ?, ?, ?)"; + + private final static String DELETE_SQL = + "DELETE FROM " + GmsSystemTables.CDC_SYNC_POINT_META + " where gmt_created < (NOW() - INTERVAL 7 DAY)"; + + public int delete() { + try { + return MetaDbUtil.delete(DELETE_SQL, connection); + } catch (Exception e) { + logger.error("Failed to delete the system table '" + GmsSystemTables.CDC_SYNC_POINT_META + "'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", + GmsSystemTables.CDC_SYNC_POINT_META, + e.getMessage()); + } + } + + public int insert(String uuid, int participants, long tso) { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, uuid); + MetaDbUtil.setParameter(2, params, ParameterMethod.setInt, participants); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, tso); + MetaDbUtil.setParameter(4, params, ParameterMethod.setInt, 1); + try { + return MetaDbUtil.insert(INSERT_SQL, params, connection); + } catch (Exception e) { + logger.error("Failed to insert the system table '" + GmsSystemTables.CDC_SYNC_POINT_META + "'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "insert", + GmsSystemTables.CDC_SYNC_POINT_META, + e.getMessage()); + } + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/cdc/SyncPointMetaRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/cdc/SyncPointMetaRecord.java new file mode 100644 index 000000000..aaf2b8e3e --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/cdc/SyncPointMetaRecord.java @@ -0,0 +1,24 @@ +package com.alibaba.polardbx.gms.metadb.cdc; + +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author yaozhili + */ +public class SyncPointMetaRecord implements SystemTableRecord { + public Integer id; + public Integer participants; + public Long tso; + + @Override + public SyncPointMetaRecord fill(ResultSet rs) throws SQLException { + SyncPointMetaRecord record = new SyncPointMetaRecord(); + record.id = rs.getInt("id"); + record.participants = rs.getInt("participants"); + record.tso = rs.getLong("tso"); + return record; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/columnar/FlashbackColumnarManager.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/columnar/FlashbackColumnarManager.java new file mode 100644 index 000000000..4752f42bf --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/columnar/FlashbackColumnarManager.java @@ -0,0 +1,164 @@ +package com.alibaba.polardbx.gms.metadb.columnar; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.oss.ColumnarFileType; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.metadb.table.FilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.FilesRecordSimplified; +import com.alibaba.polardbx.gms.util.MetaDbUtil; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; + +public class FlashbackColumnarManager { + + private final Map>> deletePositionMap = new HashMap<>(); + private final Map, List>>> snapshotInfo = new HashMap<>(); + private final Map schemaTsoMap = new HashMap<>(); + + public FlashbackColumnarManager(long flashbackTso, String logicalSchema, String logicalTable) { + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarTableMappingAccessor accessor = new ColumnarTableMappingAccessor(); + accessor.setConnection(connection); + + List records = accessor.querySchemaIndex(logicalSchema, logicalTable); + + Long tableId; + if (records != null && !records.isEmpty()) { + ColumnarTableMappingRecord record = records.get(0); + tableId = record.tableId; + } else { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, + String.format("Columnar index not found, schema: %s, table: %s", logicalSchema, logicalTable)); + } + FilesAccessor filesAccessor = new FilesAccessor(); + filesAccessor.setConnection(connection); + + ColumnarAppendedFilesAccessor appendedFilesAccessor = new ColumnarAppendedFilesAccessor(); + appendedFilesAccessor.setConnection(connection); + + List snapshotFiles = filesAccessor + .queryColumnarSnapshotFilesByTsoAndTableId(flashbackTso, logicalSchema, String.valueOf(tableId)); + List appendedFilesRecords = + appendedFilesAccessor.queryLastValidAppendByTsoAndTableId(flashbackTso, logicalSchema, + String.valueOf(tableId)); + + for (FilesRecordSimplified record : snapshotFiles) { + String fileName = record.fileName; + String partName = record.partitionName; + Long schemaTso = record.schemaTs; + String suffix = fileName.substring(fileName.lastIndexOf('.') + 1); + ColumnarFileType columnarFileType = ColumnarFileType.of(suffix); + + if (columnarFileType == ColumnarFileType.ORC) { + snapshotInfo.computeIfAbsent( + partName, + s -> Pair.of(new ArrayList<>(), new ArrayList<>()) + ).getKey().add(fileName); + schemaTsoMap.put(fileName, schemaTso); + } else if (columnarFileType.isDeltaFile()) { + schemaTsoMap.put(fileName, schemaTso); + } + } + + for (ColumnarAppendedFilesRecord record : appendedFilesRecords) { + String fileName = record.fileName; + String partName = record.partName; + long position = record.appendOffset + record.appendLength; + String suffix = fileName.substring(fileName.lastIndexOf('.') + 1); + ColumnarFileType columnarFileType = ColumnarFileType.of(suffix); + + if (columnarFileType == ColumnarFileType.CSV) { + snapshotInfo.computeIfAbsent( + partName, + s -> Pair.of(new ArrayList<>(), new ArrayList<>()) + ).getValue().add(Pair.of(fileName, position)); + } + + if (columnarFileType == ColumnarFileType.DEL) { + deletePositionMap.computeIfAbsent( + partName, + s -> new ArrayList<>() + ).add(Pair.of(fileName, position)); + } + } + } catch (SQLException e) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, + String.format("Failed to generate columnar snapshot, tso: %d, schema: %s, table: %s", + flashbackTso, logicalSchema, logicalTable)); + } + } + + /** + * @return partName -> ([orcFiles](name), [csvFiles](name, pos)) + */ + public Map, List>>> getSnapshotInfo() { + return snapshotInfo; + } + + public Map>> getDeletePositions() { + return deletePositionMap; + } + + public Map, List>>> getSnapshotInfo( + SortedMap> partitionResult) { + Map, List>>> result = new HashMap<>(); + snapshotInfo.forEach((partName, partSnapshot) -> { + for (String orcFileName : partSnapshot.getKey()) { + Long schemaTso = schemaTsoMap.get(orcFileName); + SortedMap> headMap = partitionResult.headMap(schemaTso + 1); + if (!headMap.isEmpty()) { + Set partitionSet = headMap.get(headMap.lastKey()); + if (partitionSet != null && partitionSet.contains(partName)) { + result.computeIfAbsent(partName, + s -> Pair.of(new ArrayList<>(), new ArrayList<>()) + ).getKey().add(orcFileName); + } + } + } + + for (Pair csvNameAndPos : partSnapshot.getValue()) { + Long schemaTso = schemaTsoMap.get(csvNameAndPos.getKey()); + SortedMap> headMap = partitionResult.headMap(schemaTso + 1); + if (!headMap.isEmpty()) { + Set partitionSet = headMap.get(headMap.lastKey()); + if (partitionSet != null && partitionSet.contains(partName)) { + result.computeIfAbsent(partName, + s -> Pair.of(new ArrayList<>(), new ArrayList<>()) + ).getValue().add(csvNameAndPos); + } + } + } + }); + return result; + } + + public Map>> getDeletePositions( + SortedMap> partitionResult) { + Map>> result = new HashMap<>(); + deletePositionMap.forEach((partName, partDeletePositions) -> { + for (Pair deletePosition : partDeletePositions) { + Long schemaTso = schemaTsoMap.get(deletePosition.getKey()); + SortedMap> headMap = partitionResult.headMap(schemaTso + 1); + if (!headMap.isEmpty()) { + Set partitionSet = headMap.get(headMap.lastKey()); + if (partitionSet != null && partitionSet.contains(partName)) { + result.computeIfAbsent(partName, s -> new ArrayList<>()).add(deletePosition); + } + } + } + }); + return result; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/evolution/ColumnEvolutionRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/evolution/ColumnEvolutionRecord.java index c20cb3b63..3373bd3a9 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/evolution/ColumnEvolutionRecord.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/evolution/ColumnEvolutionRecord.java @@ -22,11 +22,11 @@ import com.alibaba.polardbx.common.jdbc.ParameterMethod; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.druid.util.StringUtils; import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnsRecord; import com.alibaba.polardbx.gms.util.FileStorageUtil; import com.alibaba.polardbx.gms.util.MetaDbUtil; -import org.eclipse.jetty.util.StringUtil; import java.sql.ResultSet; import java.sql.SQLException; @@ -120,7 +120,7 @@ public static String serializeToJson(ColumnsRecord columnsRecord) { public static ColumnsRecord deserializeFromJson(String json) { try { - if (StringUtil.isEmpty(json)) { + if (StringUtils.isEmpty(json)) { return null; } ColumnsRecord columnsRecord = new ColumnsRecord(); diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/BackfillSampleRowsAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/BackfillSampleRowsAccessor.java new file mode 100644 index 000000000..c5988e0a4 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/BackfillSampleRowsAccessor.java @@ -0,0 +1,104 @@ +package com.alibaba.polardbx.gms.metadb.misc; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.gms.metadb.GmsSystemTables; +import com.alibaba.polardbx.gms.metadb.accessor.AbstractAccessor; +import com.alibaba.polardbx.gms.util.DdlMetaLogUtil; +import com.alibaba.polardbx.gms.util.MetaDbUtil; + +import java.util.Map; + + +public class BackfillSampleRowsAccessor extends AbstractAccessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(BackfillSampleRowsAccessor.class); + + public static final String BACKFILL_SAMPLE_ROWS_TABLE = wrap(GmsSystemTables.BACKFILL_SAMPLE_ROWS); + + public static final String BACKFILL_SAMPLE_ROWS_ARCHIVE_TABLE = wrap(GmsSystemTables.BACKFILL_SAMPLE_ROWS_ARCHIVE); + + private static final String FROM_TABLE = " from " + BACKFILL_SAMPLE_ROWS_TABLE; + + private static final String WHERE_JOB_ID = " where `job_id` = ?"; + + private static final String WHERE_SCHEMA_NAME = " where `schema_name` = ?"; + + private static final String ARCHIVE_BASE = + "insert into " + BACKFILL_SAMPLE_ROWS_ARCHIVE_TABLE + " select * from " + BACKFILL_SAMPLE_ROWS_TABLE; + + private static final String ARCHIVE_SPECIFIC = ARCHIVE_BASE + WHERE_JOB_ID; + + private static final String DELETE_BASE = "delete" + FROM_TABLE; + + private static final String DELETE_ARCHIVE_BASE = "delete from " + BACKFILL_SAMPLE_ROWS_ARCHIVE_TABLE; + + private static final String DELETE_BY_JOB_ID = DELETE_BASE + WHERE_JOB_ID; + + private static final String DELETE_ARCHIVE_BY_JOB_ID = DELETE_ARCHIVE_BASE + WHERE_JOB_ID; + + private static final String DELETE_ARCHIVE_BY_SCHEMA_NAME = DELETE_ARCHIVE_BASE + WHERE_SCHEMA_NAME; + + private static final String DELETE_BY_SCHEMA_NAME = DELETE_BASE + WHERE_SCHEMA_NAME; + + public int deleteByJobId(long jobId) { + try { + final Map params = + MetaDbUtil.buildParameters(ParameterMethod.setLong, new Long[] {jobId}); + deleteArchiveByJobId(jobId); + archive(jobId); + return MetaDbUtil.delete(DELETE_BY_JOB_ID, params, connection); + } catch (Exception e) { + throw logAndThrow("Failed to delete from " + BACKFILL_SAMPLE_ROWS_TABLE + " for job " + jobId, + "delete from", e); + } + } + + public int deleteArchiveByJobId(long jobId) { + try { + final Map params = + MetaDbUtil.buildParameters(ParameterMethod.setLong, new Long[] {jobId}); + return MetaDbUtil.delete(DELETE_ARCHIVE_BY_JOB_ID, params, connection); + } catch (Exception e) { + throw logAndThrow("Failed to delete from " + BACKFILL_SAMPLE_ROWS_TABLE + " for job " + jobId, + "delete from", e); + } + } + + public int archive(long jobId) { + try { + final Map params = + MetaDbUtil.buildParameters(ParameterMethod.setLong, new Long[] {jobId}); + DdlMetaLogUtil.logSql(ARCHIVE_SPECIFIC, params); + return MetaDbUtil.delete(ARCHIVE_SPECIFIC, params, connection); + } catch (Exception e) { + throw logAndThrow("Failed to copy record from " + BACKFILL_SAMPLE_ROWS_TABLE + " for job " + jobId, + "archive", + e); + } + } + + private TddlRuntimeException logAndThrow(String errMsg, String action, Exception e) { + LOGGER.error(errMsg, e); + return new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, action, + BACKFILL_SAMPLE_ROWS_TABLE, e.getMessage()); + } + + public int deleteAll(String schemaName) { + try { + final Map params = + MetaDbUtil.buildParameters(ParameterMethod.setString, new String[] {schemaName}); + MetaDbUtil.delete(DELETE_ARCHIVE_BY_SCHEMA_NAME, params, connection); + return MetaDbUtil.delete(DELETE_BY_SCHEMA_NAME, params, connection); + } catch (Exception e) { + throw logAndThrow("Failed to delete from " + BACKFILL_SAMPLE_ROWS_TABLE + " for schemaName: " + schemaName, + "delete from", + e); + } + } + +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/DdlEngineTaskAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/DdlEngineTaskAccessor.java index ac07a7cb8..5259704d0 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/DdlEngineTaskAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/DdlEngineTaskAccessor.java @@ -54,6 +54,9 @@ public class DdlEngineTaskAccessor extends AbstractAccessor { private static final String SELECT_FULL = "select `job_id`, `task_id`, `schema_name`, `name`, `state`, `exception_action`, `value`, `extra`, `cost`, `root_job_id`"; + private static final String SELECT_COUNT = + "select count(1) "; + private static final String SELECT_SIMPLE = "select `job_id`, `task_id`, `schema_name`, `name`, `state`, `exception_action`, null as `value`, null as `extra`, `cost`, `root_job_id` "; @@ -70,14 +73,20 @@ public class DdlEngineTaskAccessor extends AbstractAccessor { private static final String WITH_TASK_ID = " and `task_id` = ?"; + private static final String WITH_STATE = " and `state` = ?"; + private static final String WITH_ONGOING_TASK = " and `state` <> 'SUCCESS' and `state` <> 'ROLLBACK_SUCCESS' "; private static final String WITH_TASK_NAME = " and `name` = ?"; private static final String SELECT_BASE = SELECT_FULL + FROM_TABLE; + private static final String SELECT_TASK_COUNT = SELECT_COUNT + FROM_TABLE; + private static final String SELECT_BY_JOB_ID = SELECT_BASE + WHERE_JOB_ID; + private static final String SELECT_SUCCESS_TASK_COUNT_BY_JOB_ID = SELECT_TASK_COUNT + WHERE_JOB_ID + WITH_STATE; + private static final String SELECT_BY_JOB_ID_TASK_ID = SELECT_BASE + WHERE_JOB_ID + WITH_TASK_ID; private static final String SELECT_ONGOING_TASK = @@ -85,6 +94,9 @@ public class DdlEngineTaskAccessor extends AbstractAccessor { private static final String SELECT_BY_JOB_ID_TASK_NAME = SELECT_BASE + WHERE_JOB_ID + WITH_TASK_NAME; + private static final String SELECT_BY_JOB_ID_TASK_NAME_FOR_UPDATE = + SELECT_BASE + WHERE_JOB_ID + WITH_TASK_NAME + " FOR UPDATE"; + private static final String SELECT_TASK_SIMPLE_INFO_BY_ROOT_JOB_ID = SELECT_SIMPLE + FROM_TABLE + " " + WHERE_ROOT_JOB_ID; @@ -124,6 +136,9 @@ public class DdlEngineTaskAccessor extends AbstractAccessor { private static final String UPDATE_EXTRA_FOR_CREATE_DATABASE_AS_LIKE = UPDATE_BASE + "`extra` = ?" + WHERE_JOB_ID + WITH_TASK_ID; + private static final String UPDATE_EXTRA_INFO_BY_JOB_ID_AND_TASK_ID = + UPDATE_BASE + "`extra` = ?" + WHERE_JOB_ID + WITH_TASK_ID; + private static final String DELETE_BASE = "delete" + FROM_TABLE; private static final String DELETE_BY_JOB_ID = DELETE_BASE + WHERE_JOB_ID; @@ -180,6 +195,25 @@ public List query(long jobId) { } } + public Integer querySuccessTaskCount(long jobId, String state) { + try { + final Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, jobId); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, state); + + List> successCount = + MetaDbUtil.executeCount(SELECT_SUCCESS_TASK_COUNT_BY_JOB_ID, params, connection); + + if (!successCount.isEmpty()) { + return Integer.parseInt( + successCount.get(0).values().stream().collect(Collectors.toList()).get(0).toString()); + } + return null; + } catch (Exception e) { + throw logAndThrow("Failed to query from " + DDL_ENGINE_TASK_TABLE, "query from", e); + } + } + public DdlEngineTaskRecord query(long jobId, long taskId) { try { final Map params = new HashMap<>(); @@ -227,6 +261,21 @@ public boolean hasOngoingTask(String schemaName, String taskName) { } } + public List queryTasksForUpdate(long jobId, String name) { + try { + final Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, jobId); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, name); + + List records = + MetaDbUtil.query(SELECT_BY_JOB_ID_TASK_NAME_FOR_UPDATE, params, DdlEngineTaskRecord.class, connection); + + return records; + } catch (Exception e) { + throw logAndThrow("Failed to query from " + DDL_ENGINE_TASK_TABLE, "query from", e); + } + } + public List queryTaskSimpleInfoByJobId(long jobId, boolean archive) { try { final Map params = new HashMap<>(); @@ -339,6 +388,24 @@ public int updatePhyDone(long jobId, long taskId, String phyObjectInfo, boolean } } + public int updateTaskExtraInfo(long jobId, long taskId, String extraInfo) { + try { + final Map params = new HashMap<>(3); + int i = 0; + MetaDbUtil.setParameter(++i, params, ParameterMethod.setString, extraInfo); + MetaDbUtil.setParameter(++i, params, ParameterMethod.setLong, jobId); + MetaDbUtil.setParameter(++i, params, ParameterMethod.setLong, taskId); + return MetaDbUtil.update(UPDATE_EXTRA_INFO_BY_JOB_ID_AND_TASK_ID, params, connection); + } catch (Exception e) { + throw logAndThrow( + "Failed to update " + DDL_ENGINE_TASK_TABLE + " for job " + jobId + " and task " + taskId + + " with updating", + "update done", + e + ); + } + } + public int updateExtraInfoForCreateDbAsLike(long jobId, long taskId, String extraInfo) { try { final Map params = new HashMap<>(3); diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/ImportTableSpaceInfoStatAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/ImportTableSpaceInfoStatAccessor.java new file mode 100644 index 000000000..4a352d68e --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/ImportTableSpaceInfoStatAccessor.java @@ -0,0 +1,52 @@ +package com.alibaba.polardbx.gms.metadb.misc; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.gms.metadb.GmsSystemTables; +import com.alibaba.polardbx.gms.metadb.accessor.AbstractAccessor; +import com.alibaba.polardbx.gms.util.DdlMetaLogUtil; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import org.apache.commons.collections.CollectionUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Created by luoyanxin. + * + * @author luoyanxin + */ +public class ImportTableSpaceInfoStatAccessor extends AbstractAccessor { + private static final Logger LOGGER = LoggerFactory.getLogger(ImportTableSpaceInfoStatAccessor.class); + + public static final String IMPORT_TABLESPACE_INFO_STAT = wrap(GmsSystemTables.IMPORT_TABLESPACE_INFO_STAT); + private static final String INSERT_DATA = "replace into " + IMPORT_TABLESPACE_INFO_STAT + + " (task_id, table_schema, table_name, physical_db, physical_table, data_size, start_time, end_time)" + + " values (?, ?, ?, ?, ?, ?, ?, ?)"; + + public int insert(List recordList) { + try { + if (CollectionUtils.isEmpty(recordList)) { + return 0; + } + List> paramsBatch = + recordList.stream().map(e -> e.buildParams()).collect(Collectors.toList()); + DdlMetaLogUtil.logSql(INSERT_DATA + " record count: " + recordList.size()); + int[] r = MetaDbUtil.insert(INSERT_DATA, paramsBatch, connection); + return Arrays.stream(r).sum(); + } catch (Exception e) { + throw logAndThrow("Failed to insert a new record into " + IMPORT_TABLESPACE_INFO_STAT, "insert into", e); + } + } + + private TddlRuntimeException logAndThrow(String errMsg, String action, Exception e) { + LOGGER.error(errMsg, e); + return new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, action, + IMPORT_TABLESPACE_INFO_STAT, e.getMessage()); + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/ImportTableSpaceInfoStatRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/ImportTableSpaceInfoStatRecord.java new file mode 100644 index 000000000..83c4bfd2e --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/ImportTableSpaceInfoStatRecord.java @@ -0,0 +1,154 @@ +package com.alibaba.polardbx.gms.metadb.misc; + +/** + * Created by luoyanxin. + */ + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * Represents the metadata for a task importing table space information statistics. + */ +public class ImportTableSpaceInfoStatRecord implements SystemTableRecord { + + /** + * Unique identifier for the import task. + */ + private long taskId; + + /** + * Database schema where the table belongs. + */ + private String tableSchema; + + /** + * Name of the table being imported. + */ + private String tableName; + + /** + * Group key representing the physical database. + */ + private String physicalDb; + + /** + * Physical table name in the storage system. + */ + private String physicalTable; + + /** + * Size of the ibd file in bytes. + */ + private long dataSize; + + /** + * Start time of the import task. + */ + private long startTime; + + /** + * End time of the import task, updated on completion or update. + */ + private long endTime; + + public long getTaskId() { + return taskId; + } + + public void setTaskId(long taskId) { + this.taskId = taskId; + } + + public String getTableSchema() { + return tableSchema; + } + + public void setTableSchema(String tableSchema) { + this.tableSchema = tableSchema; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public String getPhysicalDb() { + return physicalDb; + } + + public void setPhysicalDb(String physicalDb) { + this.physicalDb = physicalDb; + } + + public String getPhysicalTable() { + return physicalTable; + } + + public void setPhysicalTable(String physicalTable) { + this.physicalTable = physicalTable; + } + + public long getDataSize() { + return dataSize; + } + + public void setDataSize(long dataSize) { + this.dataSize = dataSize; + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + @Override + public ImportTableSpaceInfoStatRecord fill(ResultSet rs) throws SQLException { + this.taskId = rs.getLong("task_id"); + this.tableSchema = rs.getString("table_schema"); + this.tableName = rs.getString("table_name"); + this.physicalDb = rs.getString("physical_db"); + this.physicalTable = rs.getString("physical_table"); + this.dataSize = rs.getLong("data_size"); + this.startTime = rs.getLong("start_time"); + this.endTime = rs.getLong("end_time"); + return this; + } + + public Map buildParams() { + Map params = new HashMap<>(16); + int index = 0; + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.taskId); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.tableSchema); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.tableName); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.physicalDb); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.physicalTable); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.dataSize); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.startTime); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.endTime); + return params; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/SchemaInfoCleaner.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/SchemaInfoCleaner.java index 874227d53..a865e3db6 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/SchemaInfoCleaner.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/misc/SchemaInfoCleaner.java @@ -29,6 +29,7 @@ public class SchemaInfoCleaner extends AbstractAccessor { private final DdlEngineTaskAccessor ddlEngineTaskAccessor; private final ScheduledJobsAccessor scheduledJobsAccessor; private final FiredScheduledJobsAccessor firedScheduledJobsAccessor; + private final BackfillSampleRowsAccessor backfillSampleRowsAccessor; public SchemaInfoCleaner() { ddlEngineAccessor = new DdlEngineAccessor(); @@ -36,6 +37,7 @@ public SchemaInfoCleaner() { readWriteLockAccessor = new ReadWriteLockAccessor(); scheduledJobsAccessor = new ScheduledJobsAccessor(); firedScheduledJobsAccessor = new FiredScheduledJobsAccessor(); + backfillSampleRowsAccessor = new BackfillSampleRowsAccessor(); } @Override @@ -46,6 +48,7 @@ public void setConnection(Connection connection) { ddlEngineTaskAccessor.setConnection(connection); scheduledJobsAccessor.setConnection(connection); firedScheduledJobsAccessor.setConnection(connection); + backfillSampleRowsAccessor.setConnection(connection); } public void removeAll(String schemaName) { @@ -55,7 +58,9 @@ public void removeAll(String schemaName) { //ddlEngineTaskAccessor.deleteAllArchive(schemaName); readWriteLockAccessor.deleteAll(schemaName); scheduledJobsAccessor.deleteAll(schemaName); + firedScheduledJobsAccessor.deleteAll(schemaName); + backfillSampleRowsAccessor.deleteAll(schemaName); } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/record/RecordConverter.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/record/RecordConverter.java index 16c68be63..fe1bd1955 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/record/RecordConverter.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/record/RecordConverter.java @@ -16,16 +16,18 @@ package com.alibaba.polardbx.gms.metadb.record; +import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.gms.metadb.table.ColumnStatus; import com.alibaba.polardbx.gms.metadb.table.ColumnsAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnsInfoSchemaRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnsRecord; -import com.alibaba.polardbx.gms.metadb.table.IndexesRecord; import com.alibaba.polardbx.gms.metadb.table.IndexStatus; import com.alibaba.polardbx.gms.metadb.table.IndexesInfoSchemaRecord; +import com.alibaba.polardbx.gms.metadb.table.IndexesRecord; import com.alibaba.polardbx.gms.metadb.table.TableStatus; import com.alibaba.polardbx.gms.metadb.table.TablesInfoSchemaRecord; import com.alibaba.polardbx.gms.metadb.table.TablesRecord; +import com.alibaba.polardbx.rpc.result.XResultUtil; import java.util.ArrayList; import java.util.List; @@ -79,6 +81,12 @@ public static List convertColumn(List in record.characterOctetLength = infoSchemaRecord.characterOctetLength; record.numericPrecision = infoSchemaRecord.numericPrecision; record.numericScale = infoSchemaRecord.numericScale; + if (infoSchemaRecord.numericScaleNull && (infoSchemaRecord.dataType.equalsIgnoreCase("float") + || infoSchemaRecord.dataType.equalsIgnoreCase("double"))) { + // 对于 ColumnMeta 中的 float 和 double 数据,存储其精度数据,scale 来自 information_schema columns 中 + // 没有指定精度时,存储为 DECIMAL_NOT_SPECIFIED(31),作为 magic number + record.numericScale = XResultUtil.DECIMAL_NOT_SPECIFIED; + } record.datetimePrecision = infoSchemaRecord.datetimePrecision; record.characterSetName = infoSchemaRecord.characterSetName; record.collationName = infoSchemaRecord.collationName; @@ -112,6 +120,10 @@ public static List convertIndex(List inf record.indexName = infoSchemaRecord.indexName; record.seqInIndex = infoSchemaRecord.seqInIndex; record.columnName = infoSchemaRecord.columnName; + if (InstanceVersion.isMYSQL80() && infoSchemaRecord.columnName == null) { + //mysql 80 函数索引列名为null,这里mock一下 + record.columnName = "null"; + } record.collation = infoSchemaRecord.collation; record.cardinality = infoSchemaRecord.cardinality; record.subPart = infoSchemaRecord.subPart; diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/BaselineInfoAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/BaselineInfoAccessor.java index 9ac235f43..1dc6604fd 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/BaselineInfoAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/BaselineInfoAccessor.java @@ -74,12 +74,11 @@ public class BaselineInfoAccessor extends AbstractAccessor implements AutoClosea + "UNIX_TIMESTAMP(PLAN_INFO.GMT_CREATED) FROM " + BASELINE_INFO_TABLE + " AS BASELINE_INFO LEFT JOIN " + PLAN_INFO_TABLE + " AS PLAN_INFO ON " + "BASELINE_INFO.SCHEMA_NAME = PLAN_INFO.SCHEMA_NAME AND " + + "BASELINE_INFO.INST_ID = PLAN_INFO.INST_ID AND " + "BASELINE_INFO.ID = PLAN_INFO.BASELINE_ID " + "WHERE UNIX_TIMESTAMP(BASELINE_INFO.GMT_MODIFIED) > ? AND " + "(PLAN_INFO.GMT_MODIFIED IS NULL OR UNIX_TIMESTAMP(PLAN_INFO.GMT_MODIFIED) > ?)" - + " AND BASELINE_INFO.INST_ID=? AND" - + " PLAN_INFO.INST_ID=?"; - + + " AND BASELINE_INFO.INST_ID=? "; private static final String MOVE_BASELINE_INFO_TO_SPM_BASELINE = "INSERT INTO " + BASELINE_INFO_TABLE + "(`ID`, `INST_ID`, `SCHEMA_NAME`, `GMT_MODIFIED`, `GMT_CREATED`, `SQL`, `TABLE_SET`, `EXTEND_FIELD`) " @@ -114,8 +113,9 @@ public class BaselineInfoAccessor extends AbstractAccessor implements AutoClosea "DELETE BASELINE_INFO, PLAN_INFO FROM " + BASELINE_INFO_TABLE + " AS BASELINE_INFO LEFT JOIN " + PLAN_INFO_TABLE + " AS PLAN_INFO ON " + "BASELINE_INFO.SCHEMA_NAME = PLAN_INFO.SCHEMA_NAME AND " + + "BASELINE_INFO.INST_ID = PLAN_INFO.INST_ID AND " + "BASELINE_INFO.ID = PLAN_INFO.BASELINE_ID " - + "WHERE BASELINE_INFO.SCHEMA_NAME = ? AND BASELINE_INFO.ID = ? AND BASELINE_INFO.INST_ID=? AND PLAN_INFO.INST_ID=?"; + + "WHERE BASELINE_INFO.SCHEMA_NAME = ? AND BASELINE_INFO.ID = ? AND BASELINE_INFO.INST_ID=?"; private static final String REPLACE_BASELINE = "REPLACE INTO " + BASELINE_INFO_TABLE @@ -157,7 +157,6 @@ public List loadBaselineData(long sinceTime) { MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, sinceTime); MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, sinceTime); MetaDbUtil.setParameter(3, params, ParameterMethod.setString, instId); - MetaDbUtil.setParameter(4, params, ParameterMethod.setString, instId); ModuleLogInfo.getInstance() .logRecord(Module.SPM, LogPattern.PROCESS_END, new String[] {"spm load", "since time:" + sinceTime}, @@ -226,7 +225,6 @@ public void deleteBaseline(String schemaName, int baselineInfoId) { MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); MetaDbUtil.setParameter(2, params, ParameterMethod.setInt, baselineInfoId); MetaDbUtil.setParameter(3, params, ParameterMethod.setString, instId); - MetaDbUtil.setParameter(4, params, ParameterMethod.setString, instId); MetaDbUtil.delete(DELETE_BASELINE, params, connection); ModuleLogInfo.getInstance() diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/CollationRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/CollationRecord.java new file mode 100644 index 000000000..bf9b73444 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/CollationRecord.java @@ -0,0 +1,28 @@ +package com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class CollationRecord implements SystemTableRecord { + public String collationName; + public String characterSetName; + public Long id; + public String isDefault; + public String isCompiled; + public Long sortLen; + public String padAttribute; + + @Override + public CollationRecord fill(ResultSet rs) throws SQLException { + this.collationName = rs.getString("collation_name"); + this.characterSetName = rs.getString("character_set_name"); + this.id = rs.getLong("id"); + this.isDefault = rs.getString("is_default"); + this.isCompiled = rs.getString("is_compiled"); + this.sortLen = rs.getLong("sortlen"); + this.padAttribute = rs.getString("pad_attribute"); + return this; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarAppendedFilesAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarAppendedFilesAccessor.java index d8121366f..91c99429d 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarAppendedFilesAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarAppendedFilesAccessor.java @@ -28,9 +28,12 @@ import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.COLUMNAR_APPENDED_FILES; import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.COLUMNAR_TABLE_MAPPING; @@ -58,12 +61,6 @@ public class ColumnarAppendedFilesAccessor extends AbstractAccessor { + "from " + COLUMNAR_APPENDED_FILES_TABLE + " a join " + COLUMNAR_TABLE_MAPPING_TABLE + " b on a.logical_table=b.table_id "; - /** - * The parameters must be consistent with ColumnarCheckpointsRecord.buildInsertParams() - */ - private static final String QUERY_BY_TSO_AND_SCHEMA = - QUERY_APEENED_FILES_RECORD + "where `checkpoint_tso` = ? and b.`table_schema` = ?"; - /** * The parameters must be consistent with ColumnarCheckpointsRecord.buildInsertParams() */ @@ -115,9 +112,16 @@ public class ColumnarAppendedFilesAccessor extends AbstractAccessor { private static final String DELETE_BY_SCHEMA_AND_TABLE = "delete from " + COLUMNAR_APPENDED_FILES_TABLE + " where `logical_schema` = ? and `logical_table` = ? "; + private static final String DELETE_BY_SCHEMA_AND_TABLE_LIMIT = "delete from " + COLUMNAR_APPENDED_FILES_TABLE + + " where `logical_schema` = ? and `logical_table` = ? limit ? "; + private static final String DELETE_BY_SCHEMA_AND_TABLE_AND_PART = "delete from " + COLUMNAR_APPENDED_FILES_TABLE + " where `logical_schema` = ? and `logical_table` = ? and `part_name` = ?"; + private static final String DELETE_BY_SCHEMA_AND_TABLE_AND_FILE_NAME = + "delete from " + COLUMNAR_APPENDED_FILES_TABLE + + " where `logical_schema` = ? and `logical_table` = ? and `file_name` = ?"; + /** * For PK index log, meta and locks. */ @@ -138,6 +142,9 @@ public class ColumnarAppendedFilesAccessor extends AbstractAccessor { + " where `logical_schema` = ? and `logical_table` = ? and `part_name` = ? and `file_type` = ? and `engine` = ?" + " for update"; + private static final String QUERY_ALL_BY_FILE_TYPE = "select * from " + COLUMNAR_APPENDED_FILES_TABLE + + " where `file_type` = ?"; + private static final String UPDATE_FOR_APPEND = "update " + COLUMNAR_APPENDED_FILES_TABLE + " set `checkpoint_tso` = ?, `file_length` = ?, `append_offset` = ?, `append_length` = ?, `total_rows` = ?" + " where `id` = ?"; @@ -155,6 +162,13 @@ public class ColumnarAppendedFilesAccessor extends AbstractAccessor { private static final String DELETE_BT_TABLE_AND_TYPE = "delete from " + COLUMNAR_APPENDED_FILES_TABLE + " where `logical_schema` = ? and `logical_table` = ? and `file_type` = ? and `engine` = ?"; + private static final String DELETE_BY_TSO_AND_FILE_TYPE = "delete from " + COLUMNAR_APPENDED_FILES_TABLE + + " where `checkpoint_tso` > ? and `file_type` in ('csv', 'del', 'set') "; + + private static final String DELETE_BY_CHECKPOINT_TSO = "delete from " + COLUMNAR_APPENDED_FILES_TABLE + + " where `checkpoint_tso` = ? "; + + //join 方式 private static final String SELECT_CSV_DEL_LAST_APPEND_BY_TSO = "select\n" + " a.* \n" + " from \n" @@ -182,9 +196,92 @@ public class ColumnarAppendedFilesAccessor extends AbstractAccessor { + COLUMNAR_APPENDED_FILES_TABLE + " where\n" + " `checkpoint_tso` <= ? \n" - + " and `logical_schema` = ? \n" - + " and `logical_table` = ? \n" - + " and `file_type` in ('csv', 'del')\n" + + " group by\n" + + " `file_name`\n" + + " ) la, \n" + + COLUMNAR_APPENDED_FILES_TABLE + " a \n" + + " where\n" + + " f.`file_name` = la.`file_name`\n" + + " and f.`file_name` = a.`file_name`\n" + + " and la.`append_tso` = a.`checkpoint_tso`\n" + + " order by a.`checkpoint_tso` desc;"; + + //子查询方式 + private static final String SELECT_CSV_DEL_LAST_APPEND_BY_TSO_SUB_QUERY = "select\n" + + " a.* \n" + + "from\n" + + " (\n" + + " select\n" + + " `file_name`,\n" + + " (\n" + + " select\n" + + " max(`checkpoint_tso`)\n" + + " from \n" + + COLUMNAR_APPENDED_FILES_TABLE + + " where\n" + + " `checkpoint_tso` <= ? \n" + + " and file_name = files.file_name\n" + + " ) as `append_tso`\n" + + " from \n" + + FILES_TABLE + + " where\n" + + " `commit_ts` <= ? \n" + + " and (\n" + + " `remove_ts` is null\n" + + " or `remove_ts` > ? \n" + + " )\n" + + " and `logical_schema_name` = ? \n" + + " and `logical_table_name` = ? \n" + + " and `file_type` = 'TABLE_FILE'\n" + + " and RIGHT(`file_name`, 3) IN ('csv', 'del')\n" + + " ) f,\n" + + COLUMNAR_APPENDED_FILES_TABLE + + " as a where\n" + + " f.`file_name` = a.`file_name`\n" + + " and f.`append_tso` = a.`checkpoint_tso`\n" + + "order by\n" + + " a.`checkpoint_tso` desc;"; + + private static final String QUERY_BY_FILE_NAMES_AND_TSO_RANGE = "select * from " + COLUMNAR_APPENDED_FILES_TABLE + + " where `file_name` in (%s) and `checkpoint_tso` > %s and `checkpoint_tso` <= %s"; + + private static final String QUERY_BY_FILE_NAMES_AND_TSO = "SELECT * FROM " + COLUMNAR_APPENDED_FILES_TABLE + " a" + + " JOIN (" + + " SELECT `file_name`," + + " MAX(`checkpoint_tso`) AS checkpoint_tso" + + " FROM " + COLUMNAR_APPENDED_FILES_TABLE + + " WHERE `file_name` in (%s)" + + " AND `checkpoint_tso` <= %s " + + " GROUP BY `file_name` " + + ") b ON a.file_name = b.file_name " + + " AND a.checkpoint_tso = b.checkpoint_tso"; + + //获取所有追加写文件, + private static final String SELECT_CSV_DEL_SET_LAST_APPEND_BY_START_TSO_AND_END_TSO = "select\n" + + " a.* \n" + + " from \n" + + " (\n" + + " select\n" + + " `file_name`\n" + + " from \n" + + FILES_TABLE + + " where \n" + + " `commit_ts` <= ? \n" + + " and (\n" + + " `remove_ts` is null\n" + + " or `remove_ts` >= ? \n" + + " )\n" + + " and `file_type` = 'TABLE_FILE'\n" + + " and RIGHT(`file_name`, 3) IN ('csv', 'del', 'set')\n" + + " ) f,\n" + + " (\n" + + " select\n" + + " `file_name`,\n" + + " max(`checkpoint_tso`) as `append_tso`\n" + + " from\n" + + COLUMNAR_APPENDED_FILES_TABLE + + " where\n" + + " `checkpoint_tso` <= ? \n" + " group by\n" + " `file_name`\n" + " ) la, \n" @@ -237,26 +334,6 @@ public List queryByTso( } } - /** - * Query all appended files whose tso is equal to given tso with logical schema. - */ - public List queryByTsoAndSchema( - long latestTso, String logicalSchema) { - try { - Map params = new HashMap<>(2); - MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, latestTso); - MetaDbUtil.setParameter(2, params, ParameterMethod.setString, logicalSchema); - - return MetaDbUtil.query(QUERY_BY_TSO_AND_SCHEMA, params, ColumnarAppendedFilesRecord.class, - connection); - } catch (Exception e) { - LOGGER.error("Failed to query the system table " + COLUMNAR_APPENDED_FILES_TABLE, e); - throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", - COLUMNAR_APPENDED_FILES_TABLE, - e.getMessage()); - } - } - /** * Query all appended files whose tso is equal to given tso with logical schema. */ @@ -459,8 +536,6 @@ public List queryLastValidAppendByTsoAndTableId(lon MetaDbUtil.setParameter(3, params, ParameterMethod.setString, schemaName); MetaDbUtil.setParameter(4, params, ParameterMethod.setString, tableId); MetaDbUtil.setParameter(5, params, ParameterMethod.setLong, tso); - MetaDbUtil.setParameter(6, params, ParameterMethod.setString, schemaName); - MetaDbUtil.setParameter(7, params, ParameterMethod.setString, tableId); return MetaDbUtil.query(SELECT_CSV_DEL_LAST_APPEND_BY_TSO, params, ColumnarAppendedFilesRecord.class, connection); @@ -472,6 +547,44 @@ public List queryLastValidAppendByTsoAndTableId(lon } } + public List queryLastValidAppendByTsoAndTableIdSubQuery(long tso, String schemaName, + String tableId) { + try { + Map params = new HashMap<>(8); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, tso); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, tso); + MetaDbUtil.setParameter(4, params, ParameterMethod.setString, schemaName); + MetaDbUtil.setParameter(5, params, ParameterMethod.setString, tableId); + + return MetaDbUtil.query(SELECT_CSV_DEL_LAST_APPEND_BY_TSO_SUB_QUERY, params, + ColumnarAppendedFilesRecord.class, + connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + COLUMNAR_APPENDED_FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + COLUMNAR_APPENDED_FILES_TABLE, + e.getMessage()); + } + } + + public List queryLastValidAppendByStartTsoAndEndTso(long startTso, long endTso) { + try { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, endTso); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, startTso); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, endTso); + + return MetaDbUtil.query(SELECT_CSV_DEL_SET_LAST_APPEND_BY_START_TSO_AND_END_TSO, params, + ColumnarAppendedFilesRecord.class, connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + COLUMNAR_APPENDED_FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + COLUMNAR_APPENDED_FILES_TABLE, + e.getMessage()); + } + } + // lock on id to prevent GAP lock public List lock(long id, boolean shareMode) { try { @@ -507,6 +620,20 @@ public List lockForInit( } } + public List queryFilesByFileType(String fileType) { + try { + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, fileType); + + return MetaDbUtil.query(QUERY_ALL_BY_FILE_TYPE, params, ColumnarAppendedFilesRecord.class, connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + COLUMNAR_APPENDED_FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + COLUMNAR_APPENDED_FILES_TABLE, + e.getMessage()); + } + } + public int updateForAppend( long id, long tso, long fileLength, long appendOffset, long appendLength, long totalRows) { try { @@ -653,6 +780,23 @@ public int delete(String logicalSchema, String logicalTable) { } } + public int deleteLimit(String logicalSchema, String logicalTable, long limit) { + try { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, logicalSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, logicalTable); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, limit); + + DdlMetaLogUtil.logSql(DELETE_BY_SCHEMA_AND_TABLE_LIMIT, params); + return MetaDbUtil.delete(DELETE_BY_SCHEMA_AND_TABLE_LIMIT, params, connection); + } catch (Exception e) { + LOGGER.error("Failed to delete from system table " + COLUMNAR_APPENDED_FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", + COLUMNAR_APPENDED_FILES_TABLE, + e.getMessage()); + } + } + public int delete(String logicalSchema, String logicalTable, String partName) { try { Map params = new HashMap<>(3); @@ -669,4 +813,87 @@ public int delete(String logicalSchema, String logicalTable, String partName) { e.getMessage()); } } + + public int deleteByTableAndFileName(String logicalSchema, String logicalTable, String fileName) { + try { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, logicalSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, logicalTable); + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, fileName); + + DdlMetaLogUtil.logSql(DELETE_BY_SCHEMA_AND_TABLE_AND_FILE_NAME, params); + return MetaDbUtil.delete(DELETE_BY_SCHEMA_AND_TABLE_AND_FILE_NAME, params, connection); + } catch (Exception e) { + LOGGER.error("Failed to delete from system table " + COLUMNAR_APPENDED_FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", + COLUMNAR_APPENDED_FILES_TABLE, + e.getMessage()); + } + } + + public List queryByFileNamesAndTsoRange(Collection files, + long tso0, long tso1) { + try { + if (files.isEmpty()) { + return Collections.emptyList(); + } + String inFileNames = files.stream().map(s -> "'" + s + "'").collect(Collectors.joining(",")); + String sql = String.format(QUERY_BY_FILE_NAMES_AND_TSO_RANGE, inFileNames, tso0, tso1); + DdlMetaLogUtil.logSql(sql); + return MetaDbUtil.query(sql, null, ColumnarAppendedFilesRecord.class, connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + COLUMNAR_APPENDED_FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + COLUMNAR_APPENDED_FILES_TABLE, + e.getMessage()); + } + } + + public List queryByFileNamesAndTso(Collection files, long tso) { + try { + if (files.isEmpty()) { + return Collections.emptyList(); + } + String inFileNames = files.stream().map(s -> "'" + s + "'").collect(Collectors.joining(",")); + String sql = String.format(QUERY_BY_FILE_NAMES_AND_TSO, inFileNames, tso); + DdlMetaLogUtil.logSql(sql); + return MetaDbUtil.query(sql, null, ColumnarAppendedFilesRecord.class, connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + COLUMNAR_APPENDED_FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + COLUMNAR_APPENDED_FILES_TABLE, + e.getMessage()); + } + } + + public int deleteByTso(long tso) { + try { + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + + DdlMetaLogUtil.logSql(DELETE_BY_TSO_AND_FILE_TYPE, params); + return MetaDbUtil.delete(DELETE_BY_TSO_AND_FILE_TYPE, params, connection); + } catch (Exception e) { + LOGGER.error("Failed to delete from system table " + COLUMNAR_APPENDED_FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", + COLUMNAR_APPENDED_FILES_TABLE, + e.getMessage()); + } + } + + public int deleteByEqualTso(long tso) { + try { + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + + DdlMetaLogUtil.logSql(DELETE_BY_CHECKPOINT_TSO, params); + return MetaDbUtil.delete(DELETE_BY_CHECKPOINT_TSO, params, connection); + } catch (Exception e) { + LOGGER.error("Failed to delete from system table " + COLUMNAR_APPENDED_FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", + COLUMNAR_APPENDED_FILES_TABLE, + e.getMessage()); + } + } + } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarCheckpointsAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarCheckpointsAccessor.java index a89414006..40c82b87f 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarCheckpointsAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarCheckpointsAccessor.java @@ -38,115 +38,115 @@ import java.util.Map; import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.COLUMNAR_CHECKPOINTS; -import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.COLUMNAR_TABLE_MAPPING; public class ColumnarCheckpointsAccessor extends AbstractAccessor { private static final Logger LOGGER = LoggerFactory.getLogger("oss"); - private static final String COLUMNAR_CHECKPOINT_TABLE = wrap(COLUMNAR_CHECKPOINTS); - private static final String COLUMNAR_TABLE_MAPPING_TABLE = wrap(COLUMNAR_TABLE_MAPPING); - /** * The parameters must be consistent with ColumnarCheckpointsRecord.buildInsertParams() */ private static final String INSERT_CHECKPOINT_RECORD = "insert into " + COLUMNAR_CHECKPOINT_TABLE - + "(`logical_schema`, `logical_table`, `partition_name`, `checkpoint_tso`, `offset`, `checkpoint_type`, `extra`) " - + "values (?,?,?,?,?,?,?)"; + + "(`logical_schema`, `logical_table`, `partition_name`, `checkpoint_tso`, `offset`, `binlog_tso`, `checkpoint_type`, `min_compaction_tso`, `info`, `extra`) " + + "values (?,?,?,?,?,?,?,?,?,?)"; - private static final String QUERY_BY_TABLE = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where `logical_schema` = ? and `logical_table` = ? "; - - private static final String QUERY_PARTITION_LAST_CHECKPOINTS = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where (id, checkpoint_tso) in " - + "(select max(id), max(checkpoint_tso) from " + COLUMNAR_CHECKPOINT_TABLE + " " - + " where `logical_schema` = ? and `logical_table` = ? and `checkpoint_type` = ? group by partition_name);"; + private static final String ORDER_BY_TSO_DESC_LIMIT_1 = " order by `checkpoint_tso` desc limit 1"; + private static final String WHERE_READABLE_CHECKPOINT_TYPE = + " where `checkpoint_type` in ('STREAM', 'SNAPSHOT_FINISHED', 'COMPACTION', 'DDL', 'HEARTBEAT') "; private static final String QUERY_LAST_CHECKPOINT = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where `checkpoint_type` = ? order by `checkpoint_tso` desc,`update_time` desc limit 1"; + + " where `checkpoint_type` = ?" + ORDER_BY_TSO_DESC_LIMIT_1; private static final String QUERY_LAST_CHECKPOINTS = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where `checkpoint_type` in ( %s ) order by `checkpoint_tso` desc,`update_time` desc limit 1"; + + " where `checkpoint_type` in ( %s )" + ORDER_BY_TSO_DESC_LIMIT_1; private static final String QUERY_LAST_RECORD_BY_TABLE_AND_TSO_AND_TYPE = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where `logical_schema` = ? and `logical_table` = ? and `checkpoint_tso` <= ? and `checkpoint_type` in ( %s ) order by `checkpoint_tso` desc,`update_time` desc limit 1"; + + " where `logical_schema` = ? and `logical_table` = ? and `checkpoint_tso` <= ? and `checkpoint_type` in ( %s )" + + ORDER_BY_TSO_DESC_LIMIT_1; private static final String QUERY_RECORDS_BY_TABLE_AND_TSO_AND_TYPE = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where `logical_schema` = ? and `logical_table` = ? and `checkpoint_tso` <= ? and `checkpoint_type` in ( %s ) order by `checkpoint_tso` desc,`update_time` desc"; + + " where `logical_schema` = ? and `logical_table` = ? and `checkpoint_tso` <= ? and `checkpoint_type` in ( %s ) order by `checkpoint_tso` desc"; + private static final String QUERY_LAST_TSO = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " order by `checkpoint_tso` desc,`update_time` desc limit 1"; + + ORDER_BY_TSO_DESC_LIMIT_1; + + private static final String QUERY_BY_TSO_LATEST = "select * from " + COLUMNAR_CHECKPOINT_TABLE + + " where `checkpoint_tso` = ? order by id desc limit 1"; private static final String QUERY_LAST_CHECKPOINT_BY_TABLE = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where `logical_schema` = ? and `logical_table` = ? and `checkpoint_type` = ? order by `checkpoint_tso` desc,`update_time` desc limit 1"; + + " where `logical_schema` = ? and `logical_table` = ? and `checkpoint_type` = ?" + ORDER_BY_TSO_DESC_LIMIT_1; private static final String QUERY_LAST_CHECKPOINT_BY_PARTITION = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where `logical_schema` = ? and `logical_table` = ? and `partition_name` = ? and `checkpoint_type` = ? order by `checkpoint_tso` desc,`update_time` desc limit 1"; + + " where `logical_schema` = ? and `logical_table` = ? and `partition_name` = ? and `checkpoint_type` = ?" + + ORDER_BY_TSO_DESC_LIMIT_1; - private static final String QUERY_WITH_TABLE_MAPPING = - "select a.`id`, b.`table_schema` as `logical_schema`, b.`index_name` as `logical_table`, a.`partition_name`, a.`checkpoint_tso`, a.`offset`, a.`checkpoint_type`, a.`extra`, a.`create_time`, a.`update_time` from " - + COLUMNAR_CHECKPOINT_TABLE + " a join " + COLUMNAR_TABLE_MAPPING_TABLE - + " b on a.logical_table = b.table_id " - + " where b.`table_schema` = ? and `checkpoint_type` in ('STREAM', 'SNAPSHOT_FINISHED', 'COMPACTION', 'DDL', 'HEARTBEAT')"; + private static final String QUERY_LAST_VALID_TSO_WITH_DELAY = "select `checkpoint_tso` from " + + COLUMNAR_CHECKPOINT_TABLE + WHERE_READABLE_CHECKPOINT_TYPE + + " and `update_time` <= date_sub(now(), interval ? microsecond) " + + ORDER_BY_TSO_DESC_LIMIT_1; - /** - * The parameters must be consistent with ColumnarCheckpointsRecord.buildInsertParams() - */ - private static final String QUERY_BY_LAST_TSO = - QUERY_WITH_TABLE_MAPPING + " and `checkpoint_tso` > ? order by `checkpoint_tso`"; - - private static final String QUERY_BY_LAST_TSO_TOP_1 = QUERY_BY_LAST_TSO + "desc limit 1"; - - private static final String QUERY_BY_SCHEMA_TOP_1 = - QUERY_WITH_TABLE_MAPPING + " order by `checkpoint_tso` desc limit 1"; - - private static final String QUERY_LAST_VALID_TSO = - "select `checkpoint_tso`, `offset` from " + COLUMNAR_CHECKPOINT_TABLE - + " where `checkpoint_type` in ('STREAM', 'SNAPSHOT_FINISHED', 'COMPACTION', 'DDL', 'HEARTBEAT') " - + " order by `checkpoint_tso` desc limit 1"; - - private static final String QUERY_LATEST_ORC_FILE_TSO = - "select `checkpoint_tso`, `offset` from " + COLUMNAR_CHECKPOINT_TABLE - + " where `checkpoint_type` in ('STREAM', 'SNAPSHOT_FINISHED', 'COMPACTION', 'DDL', 'HEARTBEAT') " - + "and logical_schema = ? and logical_table in " - + "(select table_id " - + "from " + COLUMNAR_TABLE_MAPPING_TABLE + " where table_schema = ? and table_name = ? and index_name = ? )" - + "order by `checkpoint_tso` desc limit 1"; + private static final String QUERY_LAST_VALID_TSO = "select `checkpoint_tso`, `offset` from " + + COLUMNAR_CHECKPOINT_TABLE + WHERE_READABLE_CHECKPOINT_TYPE + ORDER_BY_TSO_DESC_LIMIT_1; private static final String QUERY_LAST_TSO_FOR_SHOW_COLUMNAR_STATUS = "select `checkpoint_tso` from " + COLUMNAR_CHECKPOINT_TABLE - + " where `checkpoint_type` in ('STREAM', 'SNAPSHOT_FINISHED', 'COMPACTION', 'DDL', 'HEARTBEAT', 'SNAPSHOT', 'SNAPSHOT_END') order by `checkpoint_tso` desc limit 1"; - - private static final String QUERY_BY_TABLE_LAST_TSO = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where `logical_schema` = ? and logical_table = ? order by `checkpoint_tso` desc limit 1"; - - private static final String QUERY_LAST_DDL_BY_TABLE = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where `logical_schema` = ? and logical_table = ? and `checkpoint_type` in ('DDL')" - + " order by `checkpoint_tso` desc limit 1"; + + " where `checkpoint_type` in ('STREAM', 'SNAPSHOT_FINISHED', 'COMPACTION', 'DDL', 'HEARTBEAT', 'SNAPSHOT', 'SNAPSHOT_END')" + + ORDER_BY_TSO_DESC_LIMIT_1; private static final String DELETE_BY_TSO = "delete from " + COLUMNAR_CHECKPOINT_TABLE + " where `checkpoint_tso` = ? and `logical_schema` = ? "; + private static final String DELETE_BY_CHECKPOINT_TSO = + "delete from " + COLUMNAR_CHECKPOINT_TABLE + " where `checkpoint_tso` > ?"; + private static final String DELETE_BY_SCHEMA = "delete from " + COLUMNAR_CHECKPOINT_TABLE + " where `logical_schema` = ? "; private static final String DELETE_BY_SCHEMA_AND_TABLE = "delete from " + COLUMNAR_CHECKPOINT_TABLE + " where `logical_schema` = ? and logical_table = ? "; + private static final String DELETE_BY_SCHEMA_AND_TABLE_LIMIT = + "delete from " + COLUMNAR_CHECKPOINT_TABLE + " where `logical_schema` = ? and logical_table = ? limit ? "; + private static final String DELETE_BY_SCHEMA_AND_TABLE_AND_PARTITION = "delete from " + COLUMNAR_CHECKPOINT_TABLE + " where `logical_schema` = ? and logical_table = ? and partition_name = ? "; - private static final String QUERY_BY_TSO_AND_TYPE = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where `checkpoint_tso` = ? and `checkpoint_type` = ? "; + private static final String DELETE_BY_TSO_AND_TYPES_LIMIT = + "delete from " + COLUMNAR_CHECKPOINT_TABLE + + " where `checkpoint_tso` < ? and `checkpoint_type` in ( %s ) limit ? "; + + private static final String DELETE_BY_TSO_AND_TYPES_AND_INFO_IS_NULL_LIMIT = + "delete from " + COLUMNAR_CHECKPOINT_TABLE + + " where `checkpoint_tso` < ? and `checkpoint_type` in ( %s ) and info is null limit ? "; private static final String QUERY_BY_TSO_AND_TYPES = "select * from " + COLUMNAR_CHECKPOINT_TABLE - + " where `checkpoint_tso` <= ? and `checkpoint_type` in ( %s ) order by checkpoint_tso desc limit 1"; + + " where `checkpoint_tso` <= ? and `checkpoint_type` in ( %s )" + ORDER_BY_TSO_DESC_LIMIT_1; + + private static final String QUERY_BY_TSO_AND_VALID_TYPE = "select * from " + + COLUMNAR_CHECKPOINT_TABLE + WHERE_READABLE_CHECKPOINT_TYPE + + " and `checkpoint_tso` <= ? " + ORDER_BY_TSO_DESC_LIMIT_1; + + private static final String QUERY_LATEST_UNCHECKED_CHECKPOINTS = + "select * from " + COLUMNAR_CHECKPOINT_TABLE + + " where checkpoint_tso > ? and info = 'force' and extra is null order by checkpoint_tso desc limit ?"; + + private static final String UPDATE_EXTRA_BY_TSO = "update " + COLUMNAR_CHECKPOINT_TABLE + + " set extra = ? where checkpoint_tso = ?"; + + /** + * 根据行存tso获取最接近列存的版本tso, 只获取增量事件的TSO, 有可能binlog_tso会有相同值(ddl多语句;cdc旧版本单机事务),多加一个列存版本排序 + */ + private static final String QUERY_COLUMNAR_TSO_BY_BINLOG_TSO = "select * from " + COLUMNAR_CHECKPOINT_TABLE + + " where `binlog_tso` >= ? and `checkpoint_type` in ('STREAM', 'HEARTBEAT', 'DDL') order by binlog_tso, checkpoint_tso desc limit 1"; - private static final String UPDATE_ON_DUPLICATE_KEY = "insert into " + COLUMNAR_CHECKPOINT_TABLE - + "(`logical_schema`, `logical_table`, `partition_name`, `checkpoint_tso`, `offset`, `checkpoint_type`) " - + "values (?,?,?,?,?,?) ON DUPLICATE KEY UPDATE offset = ?"; + private static final String QUERY_COMPACTION_BY_START_TSO_AND_END_TSO = "select * from " + COLUMNAR_CHECKPOINT_TABLE + + " where checkpoint_tso >= ? and checkpoint_tso < ? and checkpoint_type in ('COMPACTION', 'SNAPSHOT', 'SNAPSHOT_END', 'SNAPSHOT_FINISHED') "; + private static final String DELETE_COMPACTION_BY_TSO = + "delete from " + COLUMNAR_CHECKPOINT_TABLE + + " where `checkpoint_tso` = ? and checkpoint_type in ('COMPACTION', 'SNAPSHOT', 'SNAPSHOT_END', 'SNAPSHOT_FINISHED') "; /** * Insert new checkpoints @@ -167,24 +167,6 @@ public int[] insert(List records) { } } - /** - * Insert new checkpoints - */ - public int updateSnapshotOffset(ColumnarCheckpointsRecord record) { - - Map params = record.buildInsertParams(); - MetaDbUtil.setParameter(params.size() + 1, params, ParameterMethod.setString, record.offset); - try { - DdlMetaLogUtil.logSql(UPDATE_ON_DUPLICATE_KEY, params); - return MetaDbUtil.insert(UPDATE_ON_DUPLICATE_KEY, params, connection); - } catch (SQLException e) { - LOGGER.error("Failed to insert a batch of new records into " + COLUMNAR_CHECKPOINT_TABLE, e); - throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "batch insert into", - COLUMNAR_CHECKPOINT_TABLE, - e.getMessage()); - } - } - public List queryLastByType(CheckPointType checkPointType) { try { Map params = new HashMap<>(1); @@ -280,13 +262,12 @@ public List queryLastTso() { } } - public List queryLastByTable(String schema, String table) { + public List queryByTso(long checkpointTso) { try { - Map params = new HashMap<>(2); - MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schema); - MetaDbUtil.setParameter(2, params, ParameterMethod.setString, table); + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, checkpointTso); - return MetaDbUtil.query(QUERY_BY_TABLE, params, ColumnarCheckpointsRecord.class, + return MetaDbUtil.query(QUERY_BY_TSO_LATEST, params, ColumnarCheckpointsRecord.class, connection); } catch (Exception e) { LOGGER.error("Failed to query the system table " + COLUMNAR_CHECKPOINT_TABLE, e); @@ -314,16 +295,12 @@ public List queryLastByTableAndType(String schema, St } } - public List queryLastByPartitionAndType(String schema, String table, String partition, - CheckPointType checkPointType) { + public List queryColumnarTsoByBinlogTso(long binlogTso) { try { - Map params = new HashMap<>(4); - MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schema); - MetaDbUtil.setParameter(2, params, ParameterMethod.setString, table); - MetaDbUtil.setParameter(3, params, ParameterMethod.setString, partition); - MetaDbUtil.setParameter(4, params, ParameterMethod.setString, checkPointType.name()); + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, binlogTso); - return MetaDbUtil.query(QUERY_LAST_CHECKPOINT_BY_PARTITION, params, ColumnarCheckpointsRecord.class, + return MetaDbUtil.query(QUERY_COLUMNAR_TSO_BY_BINLOG_TSO, params, ColumnarCheckpointsRecord.class, connection); } catch (Exception e) { LOGGER.error("Failed to query the system table " + COLUMNAR_CHECKPOINT_TABLE, e); @@ -333,15 +310,13 @@ public List queryLastByPartitionAndType(String schema } } - public List queryPartitionLastCheckpoints(String schema, String table, - CheckPointType checkPointType) { + public List queryCompactionByStartTsoAndEndTso(long startTso, long endTso) { try { - Map params = new HashMap<>(3); - MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schema); - MetaDbUtil.setParameter(2, params, ParameterMethod.setString, table); - MetaDbUtil.setParameter(3, params, ParameterMethod.setString, checkPointType.name()); + Map params = new HashMap<>(2); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, startTso); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, endTso); - return MetaDbUtil.query(QUERY_PARTITION_LAST_CHECKPOINTS, params, ColumnarCheckpointsRecord.class, + return MetaDbUtil.query(QUERY_COMPACTION_BY_START_TSO_AND_END_TSO, params, ColumnarCheckpointsRecord.class, connection); } catch (Exception e) { LOGGER.error("Failed to query the system table " + COLUMNAR_CHECKPOINT_TABLE, e); @@ -351,12 +326,17 @@ public List queryPartitionLastCheckpoints(String sche } } - public List queryLatestTsoBySchema(String logicalSchema) { + public List queryLastByPartitionAndType(String schema, String table, String partition, + CheckPointType checkPointType) { try { - Map params = new HashMap<>(1); - MetaDbUtil.setParameter(1, params, ParameterMethod.setString, logicalSchema); + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, table); + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, partition); + MetaDbUtil.setParameter(4, params, ParameterMethod.setString, checkPointType.name()); - return MetaDbUtil.query(QUERY_BY_SCHEMA_TOP_1, params, ColumnarCheckpointsRecord.class, connection); + return MetaDbUtil.query(QUERY_LAST_CHECKPOINT_BY_PARTITION, params, ColumnarCheckpointsRecord.class, + connection); } catch (Exception e) { LOGGER.error("Failed to query the system table " + COLUMNAR_CHECKPOINT_TABLE, e); throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", @@ -383,6 +363,25 @@ public Long queryLatestTso() { } } + public Long queryLatestTsoWithDelay(long delayMicroseconds) { + try { + try (PreparedStatement ps = connection.prepareStatement(QUERY_LAST_VALID_TSO_WITH_DELAY)) { + ps.setLong(1, delayMicroseconds); + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return rs.getLong("checkpoint_tso"); + } + } + return null; + } + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + COLUMNAR_CHECKPOINT_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + COLUMNAR_CHECKPOINT_TABLE, + e.getMessage()); + } + } + /** * @return (Innodb tso, Columnar tso) */ @@ -425,16 +424,19 @@ public Long queryLatestTsoByShowColumnarStatus() { } } - public List queryByLastTso(long lastCheckpointTso, String logicalSchema, - boolean queryTheTop) { + public List queryByTsoAndTypes(long checkpointTso, + List checkPointTypes) { + int size = checkPointTypes.size(); + try { - Map params = new HashMap<>(2); - MetaDbUtil.setParameter(1, params, ParameterMethod.setString, logicalSchema); - MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, lastCheckpointTso); + String sql = String.format(QUERY_BY_TSO_AND_TYPES, String.join(",", Collections.nCopies(size, "?"))); + Map params = new HashMap<>(size + 1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, checkpointTso); + for (int i = 1; i <= size; i++) { + MetaDbUtil.setParameter(i + 1, params, ParameterMethod.setString, checkPointTypes.get(i - 1).name()); + } - return MetaDbUtil.query(queryTheTop ? QUERY_BY_LAST_TSO_TOP_1 : QUERY_BY_LAST_TSO, params, - ColumnarCheckpointsRecord.class, - connection); + return MetaDbUtil.query(sql, params, ColumnarCheckpointsRecord.class, connection); } catch (Exception e) { LOGGER.error("Failed to query the system table " + COLUMNAR_CHECKPOINT_TABLE, e); throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", @@ -443,17 +445,25 @@ public List queryByLastTso(long lastCheckpointTso, St } } - public List queryByLastTso(long lastCheckpointTso, String logicalSchema) { - return queryByLastTso(lastCheckpointTso, logicalSchema, false); + public List queryValidCheckpointByTso(long checkpointTso) { + try { + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, checkpointTso); + return MetaDbUtil.query(QUERY_BY_TSO_AND_VALID_TYPE, params, ColumnarCheckpointsRecord.class, connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + COLUMNAR_CHECKPOINT_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + COLUMNAR_CHECKPOINT_TABLE, + e.getMessage()); + } } - public List queryByTableLastTso(String logicalSchema, String logicalTable) { + public List queryLatestForcedCheckpoints(long tso, long limit) { try { Map params = new HashMap<>(2); - MetaDbUtil.setParameter(1, params, ParameterMethod.setString, logicalSchema); - MetaDbUtil.setParameter(2, params, ParameterMethod.setString, logicalTable); - - return MetaDbUtil.query(QUERY_BY_TABLE_LAST_TSO, params, ColumnarCheckpointsRecord.class, + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, limit); + return MetaDbUtil.query(QUERY_LATEST_UNCHECKED_CHECKPOINTS, params, ColumnarCheckpointsRecord.class, connection); } catch (Exception e) { LOGGER.error("Failed to query the system table " + COLUMNAR_CHECKPOINT_TABLE, e); @@ -463,14 +473,12 @@ public List queryByTableLastTso(String logicalSchema, } } - public List queryLastDdlByTable(String logicalSchema, String logicalTable) { + public int updateExtraByTso(String extra, long tso) { try { - Map params = new HashMap<>(3); - MetaDbUtil.setParameter(1, params, ParameterMethod.setString, logicalSchema); - MetaDbUtil.setParameter(2, params, ParameterMethod.setString, logicalTable); - - return MetaDbUtil.query(QUERY_LAST_DDL_BY_TABLE, params, ColumnarCheckpointsRecord.class, - connection); + Map params = new HashMap<>(2); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, extra); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, tso); + return MetaDbUtil.update(UPDATE_EXTRA_BY_TSO, params, connection); } catch (Exception e) { LOGGER.error("Failed to query the system table " + COLUMNAR_CHECKPOINT_TABLE, e); throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", @@ -479,51 +487,44 @@ public List queryLastDdlByTable(String logicalSchema, } } - public List queryByTsoAndType(long checkpointTso, CheckPointType type) { + public int delete(long tso, String logicalSchema) { try { Map params = new HashMap<>(2); - MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, checkpointTso); - MetaDbUtil.setParameter(2, params, ParameterMethod.setString, type.toString()); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, logicalSchema); - return MetaDbUtil.query(QUERY_BY_TSO_AND_TYPE, params, ColumnarCheckpointsRecord.class, - connection); + DdlMetaLogUtil.logSql(DELETE_BY_TSO, params); + return MetaDbUtil.delete(DELETE_BY_TSO, params, connection); } catch (Exception e) { - LOGGER.error("Failed to query the system table " + COLUMNAR_CHECKPOINT_TABLE, e); - throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + LOGGER.error("Failed to delete from system table " + COLUMNAR_CHECKPOINT_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", COLUMNAR_CHECKPOINT_TABLE, e.getMessage()); } } - public List queryByTsoAndTypes(long checkpointTso, - List checkPointTypes) { - int size = checkPointTypes.size(); - + public int deleteByTso(long tso) { try { - String sql = String.format(QUERY_BY_TSO_AND_TYPES, String.join(",", Collections.nCopies(size, "?"))); - Map params = new HashMap<>(size + 1); - MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, checkpointTso); - for (int i = 1; i <= size; i++) { - MetaDbUtil.setParameter(i + 1, params, ParameterMethod.setString, checkPointTypes.get(i - 1).name()); - } + Map params = new HashMap<>(2); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); - return MetaDbUtil.query(sql, params, ColumnarCheckpointsRecord.class, connection); + DdlMetaLogUtil.logSql(DELETE_BY_CHECKPOINT_TSO, params); + return MetaDbUtil.delete(DELETE_BY_CHECKPOINT_TSO, params, connection); } catch (Exception e) { - LOGGER.error("Failed to query the system table " + COLUMNAR_CHECKPOINT_TABLE, e); - throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + LOGGER.error("Failed to delete from system table " + COLUMNAR_CHECKPOINT_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", COLUMNAR_CHECKPOINT_TABLE, e.getMessage()); } } - public int delete(long tso, String logicalSchema) { + public int deleteCompactionByTso(long tso) { try { Map params = new HashMap<>(2); MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); - MetaDbUtil.setParameter(2, params, ParameterMethod.setString, logicalSchema); - DdlMetaLogUtil.logSql(DELETE_BY_TSO, params); - return MetaDbUtil.delete(DELETE_BY_TSO, params, connection); + DdlMetaLogUtil.logSql(DELETE_COMPACTION_BY_TSO, params); + return MetaDbUtil.delete(DELETE_COMPACTION_BY_TSO, params, connection); } catch (Exception e) { LOGGER.error("Failed to delete from system table " + COLUMNAR_CHECKPOINT_TABLE, e); throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", @@ -537,8 +538,8 @@ public int delete(String logicalSchema) { Map params = new HashMap<>(1); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, logicalSchema); - DdlMetaLogUtil.logSql(DELETE_BY_SCHEMA_AND_TABLE, params); - return MetaDbUtil.delete(DELETE_BY_SCHEMA_AND_TABLE, params, connection); + DdlMetaLogUtil.logSql(DELETE_BY_SCHEMA, params); + return MetaDbUtil.delete(DELETE_BY_SCHEMA, params, connection); } catch (Exception e) { LOGGER.error("Failed to delete from system table " + COLUMNAR_CHECKPOINT_TABLE, e); throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", @@ -563,6 +564,23 @@ public int delete(String logicalSchema, String logicalTable) { } } + public int deleteLimit(String logicalSchema, String logicalTable, long limit) { + try { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, logicalSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, logicalTable); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, limit); + + DdlMetaLogUtil.logSql(DELETE_BY_SCHEMA_AND_TABLE_LIMIT, params); + return MetaDbUtil.delete(DELETE_BY_SCHEMA_AND_TABLE_LIMIT, params, connection); + } catch (Exception e) { + LOGGER.error("Failed to delete from system table " + COLUMNAR_CHECKPOINT_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", + COLUMNAR_CHECKPOINT_TABLE, + e.getMessage()); + } + } + public int delete(String logicalSchema, String logicalTable, String partitionName) { try { Map params = new HashMap<>(3); @@ -580,13 +598,81 @@ public int delete(String logicalSchema, String logicalTable, String partitionNam } } + public int deleteLimitByTsoAndTypes(long tso, List checkPointTypes, long limit) { + try { + String sql = String.format(DELETE_BY_TSO_AND_TYPES_LIMIT, + String.join(",", Collections.nCopies(checkPointTypes.size(), "?"))); + Map params = new HashMap<>(4 + checkPointTypes.size()); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + for (int i = 0; i < checkPointTypes.size(); i++) { + MetaDbUtil.setParameter(2 + i, params, ParameterMethod.setString, checkPointTypes.get(i).name()); + } + + MetaDbUtil.setParameter(2 + checkPointTypes.size(), params, ParameterMethod.setLong, limit); + + DdlMetaLogUtil.logSql(sql, params); + return MetaDbUtil.delete(sql, params, connection); + } catch (Exception e) { + LOGGER.error("Failed to delete from system table " + COLUMNAR_CHECKPOINT_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", + COLUMNAR_CHECKPOINT_TABLE, + e.getMessage()); + } + } + + public int deleteLimitByTsoAndTypesAndInfoIsNull(long tso, List checkPointTypes, long limit) { + try { + String sql = String.format(DELETE_BY_TSO_AND_TYPES_AND_INFO_IS_NULL_LIMIT, + String.join(",", Collections.nCopies(checkPointTypes.size(), "?"))); + Map params = new HashMap<>(4 + checkPointTypes.size()); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + for (int i = 0; i < checkPointTypes.size(); i++) { + MetaDbUtil.setParameter(2 + i, params, ParameterMethod.setString, checkPointTypes.get(i).name()); + } + + MetaDbUtil.setParameter(2 + checkPointTypes.size(), params, ParameterMethod.setLong, limit); + + DdlMetaLogUtil.logSql(sql, params); + return MetaDbUtil.delete(sql, params, connection); + } catch (Exception e) { + LOGGER.error("Failed to delete from system table " + COLUMNAR_CHECKPOINT_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", + COLUMNAR_CHECKPOINT_TABLE, + e.getMessage()); + } + } + + /** + * 列存每个版本记录的类型 + */ public enum CheckPointType { + /** + * 增量流,DDL事件 + */ DDL, + /** + * 增量流,包含数据修改,2024年06月后版本,只记录实例级别(多表修改,只会有一行记录) + */ STREAM, + /** + * 全量流,记录每一次全量提交,方便断点续传,表级别 + */ SNAPSHOT, + /** + * 增量流,不包含数据修改,纯心跳提交,或者用户强制提交一次,防止同步延迟过大 + */ HEARTBEAT, + /** + * compaction类型,注:compaction异步分区并行执行,所有穿插到增量流版本中,会出现TSO比当前增量流更小的情况,产生乱序 + */ COMPACTION, + /** + * 全量流,全量数据拉取结束,表级别 + */ SNAPSHOT_END, + /** + * 增全量合并,记录每个分区已经完成了增全量合并,分区级别 + */ SNAPSHOT_FINISHED; public static CheckPointType from(String value) { diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarCheckpointsRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarCheckpointsRecord.java index f62410a57..dbbcc0978 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarCheckpointsRecord.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarCheckpointsRecord.java @@ -38,7 +38,10 @@ public class ColumnarCheckpointsRecord implements SystemTableRecord { public String partitionName; public long checkpointTso; public String offset; + public long binlogTso; public String checkpointType; + public long minCompactionTso; + public String info; public String extra; public String createTime; public String updateTime; @@ -51,7 +54,10 @@ public ColumnarCheckpointsRecord fill(ResultSet rs) throws SQLException { this.partitionName = rs.getString("partition_name"); this.checkpointTso = rs.getLong("checkpoint_tso"); this.offset = rs.getString("offset"); + this.binlogTso = rs.getLong("binlog_tso"); this.checkpointType = rs.getString("checkpoint_type"); + this.minCompactionTso = rs.getLong("min_compaction_tso"); + this.info = rs.getString("info"); this.extra = rs.getString("extra"); this.createTime = rs.getString("create_time"); this.updateTime = rs.getString("update_time"); @@ -59,7 +65,7 @@ public ColumnarCheckpointsRecord fill(ResultSet rs) throws SQLException { } public Map buildInsertParams() { - Map params = new HashMap<>(8); + Map params = new HashMap<>(12); int index = 0; // skip auto increment primary-index MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.logicalSchema); @@ -67,7 +73,10 @@ public Map buildInsertParams() { MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.partitionName); MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.checkpointTso); MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.offset); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.binlogTso); MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.checkpointType); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.minCompactionTso); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.info); MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.extra); // skip automatically updated column: create_time and update_time return params; diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarColumnEvolutionAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarColumnEvolutionAccessor.java index c0e687a5e..092373276 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarColumnEvolutionAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarColumnEvolutionAccessor.java @@ -273,40 +273,41 @@ public void updateColumnRecord(ColumnsRecord columnsRecord, long fieldId) { update(UPDATE_COLUMNS_RECORD, COLUMNAR_COLUMN_EVOLUTION_TABLE, params); } - public void deleteSchema(String schemaName) { + public int deleteSchema(String schemaName) { Map params = new HashMap<>(1); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); try { DdlMetaLogUtil.logSql(DELETE_SCHEMA, params); - MetaDbUtil.delete(DELETE_SCHEMA, params, connection); + return MetaDbUtil.delete(DELETE_SCHEMA, params, connection); } catch (Exception e) { throw GeneralUtil.nestedException(e); } } - public void deleteByTableIdAndStatus(long tableId, long status) { + public int deleteByTableIdAndStatus(long tableId, long status) { Map params = new HashMap<>(2); MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tableId); MetaDbUtil.setParameter(2, params, ParameterMethod.setString, String.valueOf(status)); try { DdlMetaLogUtil.logSql(DELETE_BY_ID_STATUS, params); - MetaDbUtil.delete(DELETE_BY_ID_STATUS, params, connection); + return MetaDbUtil.delete(DELETE_BY_ID_STATUS, params, connection); } catch (Exception e) { throw GeneralUtil.nestedException(e); } } - public void deleteSchemaTableIndex(String schemaName, String tableName, String indexName) { + public int deleteSchemaTableIndex(String schemaName, String tableName, String indexName) { Map params = new HashMap<>(3); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); MetaDbUtil.setParameter(3, params, ParameterMethod.setString, indexName); - delete(DELETE_SCHEMA_TABLE_INDEX, COLUMNAR_COLUMN_EVOLUTION_TABLE, params); + return delete(DELETE_SCHEMA_TABLE_INDEX, COLUMNAR_COLUMN_EVOLUTION_TABLE, params); + } - public void deleteId(long tableId) { + public int deleteId(long tableId) { Map params = new HashMap<>(1); MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tableId); - delete(DELETE_TABLE_ID, COLUMNAR_COLUMN_EVOLUTION_TABLE, params); + return delete(DELETE_TABLE_ID, COLUMNAR_COLUMN_EVOLUTION_TABLE, params); } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarConfigAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarConfigAccessor.java index 34c3cea12..30df8d2e5 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarConfigAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarConfigAccessor.java @@ -35,6 +35,7 @@ import java.util.Map; import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.COLUMNAR_CONFIG; +import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.COLUMNAR_TABLE_MAPPING; public class ColumnarConfigAccessor extends AbstractAccessor { private static final Logger LOGGER = LoggerFactory.getLogger("oss"); @@ -47,15 +48,37 @@ public class ColumnarConfigAccessor extends AbstractAccessor { private static final String QUERY_DATA_BY_TABLE_ID = "select * from " + COLUMNAR_CONFIG_TABLE + " where table_id = ?"; + private static final String QUERY_DATA_BY_CONFIG_KEY = QUERY_DATA + " where config_key = ? and table_id = 0"; + private static final String QUERY_DATA_WITH_TIME = "select * from " + COLUMNAR_CONFIG_TABLE + " where `gmt_modified` > ?"; private static final String INSERT_DATA_ON_DUPLICATE_KEY = "insert into " + COLUMNAR_CONFIG_TABLE + "(table_id, config_key, config_value) values(?,?,?) on duplicate key update config_value=values(config_value)"; + private static final String UPDATE_GLOBAL_CONFIG_VALUE = + "replace into " + COLUMNAR_CONFIG_TABLE + " set table_id = 0, config_key = ?, config_value = ?"; + private static final String DELETE_BY_TABLE_ID = "delete from " + COLUMNAR_CONFIG_TABLE + " where table_id = ?"; + private static final String DELETE_BY_TABLE_ID_AND_KEY = + "delete from " + COLUMNAR_CONFIG_TABLE + " where table_id = ? and config_key = ?"; + + private static final String DELETE_BY_TABLE_ID_KEY_VALUE = + "delete from " + COLUMNAR_CONFIG_TABLE + " where table_id = ? and config_key = ? and config_value = ?"; + + private static final String QUERY_DATA_BY_SCHEMA_TABLE = + "SELECT mapping.index_name index_name, config.table_id table_id, config.config_key config_key, " + + " config.config_value config_value " + + " FROM " + COLUMNAR_CONFIG_TABLE + " config " + + " JOIN " + COLUMNAR_TABLE_MAPPING + " mapping " + + " ON config.table_id = mapping.table_id " + + " WHERE mapping.table_schema = ? AND mapping.table_name = ? " + + " AND mapping.status = '" + ColumnarTableStatus.PUBLIC.name() +"' " + + " UNION SELECT null, table_id, config_key, config_value " + + " FROM " + COLUMNAR_CONFIG_TABLE + " WHERE table_id = 0"; + public ChecksumRecord checksum() { try { final List res = MetaDbUtil.query(GET_CHECKSUM, null, ChecksumRecord.class, connection); @@ -94,6 +117,48 @@ public List query(long tableId) { } } + /** + * Find configs of all columnar indexes corresponding to a logical table. + */ + public List query(String schemaName, String tableName) { + try { + Map params = MetaDbUtil.buildParameters( + ParameterMethod.setString, + new Object[] {schemaName, tableName}); + + return MetaDbUtil.query(QUERY_DATA_BY_SCHEMA_TABLE, params, ColumnarConfigWithIndexNameRecord.class, + connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + + public List queryGlobalByConfigKey(String configKey) { + try { + Map params = MetaDbUtil.buildParameters( + ParameterMethod.setString, + new Object[] {configKey}); + + return MetaDbUtil.query(QUERY_DATA_BY_CONFIG_KEY, params, ColumnarConfigRecord.class, connection); + + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + + public int updateGlobalParamValue(String configKey, String configValue) { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, configKey); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, configValue); + try { + DdlMetaLogUtil.logSql(UPDATE_GLOBAL_CONFIG_VALUE, params); + return MetaDbUtil.update(UPDATE_GLOBAL_CONFIG_VALUE, params, connection); + } catch (Exception e) { + LOGGER.error("Failed to update the system table " + COLUMNAR_CONFIG, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, e.getMessage()); + } + } + public int[] insert(List records) { List> paramsBatch = new ArrayList<>(records.size()); for (ColumnarConfigRecord record : records) { @@ -124,4 +189,52 @@ public int deleteByTableId(long tableId) { e.getMessage()); } } + + public int deleteByTableIdAndKey(long tableId, String configKey) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tableId); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, configKey); + + try { + DdlMetaLogUtil.logSql(DELETE_BY_TABLE_ID_AND_KEY, params); + return MetaDbUtil.delete(DELETE_BY_TABLE_ID_AND_KEY, params, connection); + } catch (SQLException e) { + LOGGER.error("Failed to delete records from " + COLUMNAR_CONFIG_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete from", + COLUMNAR_CONFIG_TABLE, + e.getMessage()); + } + } + + public int[] deleteByTableIdAndKey(List records) { + List> paramsBatch = new ArrayList<>(records.size()); + for (ColumnarConfigRecord record : records) { + paramsBatch.add(record.buildDeleteParams()); + } + try { + DdlMetaLogUtil.logSql(DELETE_BY_TABLE_ID_AND_KEY, paramsBatch); + return MetaDbUtil.delete(DELETE_BY_TABLE_ID_AND_KEY, paramsBatch, connection); + } catch (SQLException e) { + LOGGER.error("Failed to delete records from " + COLUMNAR_CONFIG_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete from", + COLUMNAR_CONFIG_TABLE, + e.getMessage()); + } + } + + public int[] deleteByTableIdAndKeyValue(List records) { + List> paramsBatch = new ArrayList<>(records.size()); + for (ColumnarConfigRecord record : records) { + paramsBatch.add(record.buildInsertParams()); + } + try { + DdlMetaLogUtil.logSql(DELETE_BY_TABLE_ID_KEY_VALUE, paramsBatch); + return MetaDbUtil.delete(DELETE_BY_TABLE_ID_KEY_VALUE, paramsBatch, connection); + } catch (SQLException e) { + LOGGER.error("Failed to delete records from " + COLUMNAR_CONFIG_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete from", + COLUMNAR_CONFIG_TABLE, + e.getMessage()); + } + } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarConfigRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarConfigRecord.java index 1fef27a28..e24c935b9 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarConfigRecord.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarConfigRecord.java @@ -55,4 +55,13 @@ public Map buildInsertParams() { return params; } + + public Map buildDeleteParams() { + Map params = new HashMap<>(2); + int index = 0; + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.tableId); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.configKey); + + return params; + } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarConfigWithIndexNameRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarConfigWithIndexNameRecord.java new file mode 100644 index 000000000..058d7489f --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarConfigWithIndexNameRecord.java @@ -0,0 +1,21 @@ +package com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class ColumnarConfigWithIndexNameRecord implements SystemTableRecord { + public String indexName; + public long tableId; + public String configValue; + public String configKey; + @Override + public ColumnarConfigWithIndexNameRecord fill(ResultSet rs) throws SQLException { + this.indexName = rs.getString(1); + this.tableId = rs.getLong("table_id"); + this.configValue = rs.getString("config_value"); + this.configKey = rs.getString("config_key"); + return this; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarDuplicatesAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarDuplicatesAccessor.java new file mode 100644 index 000000000..591d65d41 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarDuplicatesAccessor.java @@ -0,0 +1,105 @@ +/* + * 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 com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.gms.metadb.accessor.AbstractAccessor; +import com.alibaba.polardbx.gms.util.MetaDbUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.COLUMNAR_DUPLICATES; + +public class ColumnarDuplicatesAccessor extends AbstractAccessor { + private static final String COLUMNAR_DUPLICATES_TABLE = wrap(COLUMNAR_DUPLICATES); + + private static final String INSERT = "insert into " + COLUMNAR_DUPLICATES_TABLE + + " (`engine`, `logical_schema`, `logical_table`, `partition_name`, `long_pk`, `bytes_pk`, `type`," + + " `before_file_id`, `before_pos`, `after_file_id`, `after_pos`, `extra`)" + + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + public void insert(Collection records) { + try { + final List> params = new ArrayList<>(); + for (ColumnarDuplicatesRecord record : records) { + final Map map = new HashMap<>(); + MetaDbUtil.setParameter(1, map, ParameterMethod.setString, record.engine); + MetaDbUtil.setParameter(2, map, ParameterMethod.setString, record.logicalSchema); + MetaDbUtil.setParameter(3, map, ParameterMethod.setString, record.logicalTable); + if (null == record.partitionName) { + MetaDbUtil.setParameter(4, map, ParameterMethod.setNull1, null); + } else { + MetaDbUtil.setParameter(4, map, ParameterMethod.setString, record.partitionName); + } + if (null == record.longPk) { + MetaDbUtil.setParameter(5, map, ParameterMethod.setNull1, null); + } else { + MetaDbUtil.setParameter(5, map, ParameterMethod.setLong, record.longPk); + } + if (null == record.bytesPk) { + MetaDbUtil.setParameter(6, map, ParameterMethod.setNull1, null); + } else { + MetaDbUtil.setParameter(6, map, ParameterMethod.setBytes, record.bytesPk); + } + MetaDbUtil.setParameter(7, map, ParameterMethod.setString, record.type); + if (null == record.beforeFileId) { + MetaDbUtil.setParameter(8, map, ParameterMethod.setNull1, null); + } else { + MetaDbUtil.setParameter(8, map, ParameterMethod.setLong, record.beforeFileId); + } + if (null == record.beforePos) { + MetaDbUtil.setParameter(9, map, ParameterMethod.setNull1, null); + } else { + MetaDbUtil.setParameter(9, map, ParameterMethod.setLong, record.beforePos); + } + if (null == record.afterFileId) { + MetaDbUtil.setParameter(10, map, ParameterMethod.setNull1, null); + } else { + MetaDbUtil.setParameter(10, map, ParameterMethod.setLong, record.afterFileId); + } + if (null == record.afterPos) { + MetaDbUtil.setParameter(11, map, ParameterMethod.setNull1, null); + } else { + MetaDbUtil.setParameter(11, map, ParameterMethod.setLong, record.afterPos); + } + if (null == record.extra) { + MetaDbUtil.setParameter(12, map, ParameterMethod.setNull1, null); + } else { + MetaDbUtil.setParameter(12, map, ParameterMethod.setString, record.extra); + } + params.add(map); + } + + final int[] inserts = MetaDbUtil.executeBatch(INSERT, params, connection); + for (int insert : inserts) { + if (insert != 1) { + throw new RuntimeException("ColumnarDuplicates partly inserts."); + } + } + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarDuplicatesRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarDuplicatesRecord.java new file mode 100644 index 000000000..af10b3922 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarDuplicatesRecord.java @@ -0,0 +1,92 @@ +/* + * 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 com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; +import lombok.Getter; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; + +public class ColumnarDuplicatesRecord implements SystemTableRecord { + @Getter + public enum Type { + DOUBLE_DELETE("double_delete"), + DOUBLE_INSERT("double_insert"); + + private final String name; + + Type(String name) { + this.name = name; + } + } + + public long id; + public String engine; + public String logicalSchema; + public String logicalTable; + public String partitionName; + public Long longPk; + public byte[] bytesPk; + public String type; + public Long beforeFileId; + public Long beforePos; + public Long afterFileId; + public Long afterPos; + public String extra; + + public Timestamp createTime; + public Timestamp updateTime; + + @Override + public ColumnarDuplicatesRecord fill(ResultSet rs) throws SQLException { + this.id = rs.getLong("id"); + this.engine = rs.getString("engine"); + this.logicalSchema = rs.getString("logical_schema"); + this.logicalTable = rs.getString("logical_table"); + this.partitionName = rs.getString("partition_name"); + this.longPk = rs.getLong("long_pk"); + if (rs.wasNull()) { + this.longPk = null; + } + this.bytesPk = rs.getBytes("bytes_pk"); + this.type = rs.getString("type"); + this.beforeFileId = rs.getLong("before_file_id"); + if (rs.wasNull()) { + this.beforeFileId = null; + } + this.beforePos = rs.getLong("before_pos"); + if (rs.wasNull()) { + this.beforePos = null; + } + this.afterFileId = rs.getLong("after_file_id"); + if (rs.wasNull()) { + this.afterFileId = null; + } + this.afterPos = rs.getLong("after_pos"); + if (rs.wasNull()) { + this.afterPos = null; + } + this.extra = rs.getString("extra"); + this.createTime = rs.getTimestamp("gmt_created"); + this.updateTime = rs.getTimestamp("gmt_modified"); + return this; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarFileMappingAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarFileMappingAccessor.java index ca254328a..bdc1c735b 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarFileMappingAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarFileMappingAccessor.java @@ -28,6 +28,7 @@ import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -45,6 +46,9 @@ public class ColumnarFileMappingAccessor extends AbstractAccessor { private static final String QUERY_BY_FILE_ID = "select * from " + COLUMNAR_FILE_MAPPING_TABLE + " where `logical_schema` = ? and `logical_table` = ? and `logical_partition` = ? and `columnar_file_id` = ?"; + private static final String QUERY_BY_FILE_ID_LIST = "select * from " + COLUMNAR_FILE_MAPPING_TABLE + + " where `columnar_file_id` in (%s) and `logical_schema` = '%s' and `logical_table` = %s"; + private static final String QUERY_BY_PARTITION = "select * from " + COLUMNAR_FILE_MAPPING_TABLE + " where `logical_schema` = ? and `logical_table` = ? and `logical_partition` = ?"; @@ -60,6 +64,9 @@ public class ColumnarFileMappingAccessor extends AbstractAccessor { private static final String DELETE_BY_SCHEMA_AND_TABLE = "delete from " + COLUMNAR_FILE_MAPPING_TABLE + " where `logical_schema` = ? and `logical_table` = ? "; + private static final String DELETE_BY_SCHEMA_AND_TABLE_LIMIT = "delete from " + COLUMNAR_FILE_MAPPING_TABLE + + " where `logical_schema` = ? and `logical_table` = ? limit ? "; + private static final String DELETE_BY_SCHEMA_AND_TABLE_AND_PARTITION = "delete from " + COLUMNAR_FILE_MAPPING_TABLE + " where `logical_schema` = ? and `logical_table` = ? and `logical_partition` = ? "; @@ -116,6 +123,21 @@ public List queryByFileId( } } + public List queryByFileIdList(Collection columnarFileIds, + String schema, long table) { + try { + String fileIds = String.join(",", columnarFileIds); + String sql = String.format(QUERY_BY_FILE_ID_LIST, fileIds, schema, table); + DdlMetaLogUtil.logSql(sql); + return MetaDbUtil.query(sql, null, ColumnarFileMappingRecord.class, connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + COLUMNAR_FILE_MAPPING_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + COLUMNAR_FILE_MAPPING_TABLE, + e.getMessage()); + } + } + public int updateLevelByFileId(int level, String logicalSchema, String tableId, String logicalPartition, int columnarFileId) { try { @@ -184,6 +206,23 @@ public int delete(String logicalSchema, String tableId) { } } + public int deleteLimit(String logicalSchema, String tableId, long limit) { + try { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, logicalSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableId); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, limit); + + DdlMetaLogUtil.logSql(DELETE_BY_SCHEMA_AND_TABLE_LIMIT, params); + return MetaDbUtil.delete(DELETE_BY_SCHEMA_AND_TABLE_LIMIT, params, connection); + } catch (Exception e) { + LOGGER.error("Failed to delete from system table " + COLUMNAR_FILE_MAPPING_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "delete", + COLUMNAR_FILE_MAPPING_TABLE, + e.getMessage()); + } + } + public int delete(String logicalSchema, String tableId, String logicalPartition) { try { Map params = new HashMap<>(3); diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarLeaseAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarLeaseAccessor.java index 27b71735f..5c5a206d0 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarLeaseAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarLeaseAccessor.java @@ -40,6 +40,14 @@ public class ColumnarLeaseAccessor extends AbstractAccessor { + " set `owner` = ?, `lease` = ?" + " where `id` = 1 and (`lease` + 500 < ? or `owner` = ?)"; + // 强制抢占租期 + private static final String FORCE_ELECT = "update " + COLUMNAR_LEASE_TABLE + + " set `owner` = ?, `lease` = ?" + + " where `id` = 1"; + + // 取消租期 + private static final String FORCE_CANCEL = "delete from " + COLUMNAR_LEASE_TABLE + "where `id` = 1 and `owner` = ?"; + // 续租,当前的leader续租自己的租期,只允许lease增长 private static final String RENEW = "update " + COLUMNAR_LEASE_TABLE + " set `lease` = ?" @@ -62,6 +70,10 @@ public class ColumnarLeaseAccessor extends AbstractAccessor { private static final String GET_NODES = "select `id`, `owner`, `lease` from " + COLUMNAR_LEASE_TABLE + " where `id` != 1 and `lease` >= ?"; + // 加锁查询上次的leader的lease时间 + private static final String LOCK_LEADER_LEASE = "select `id`, `owner`, `lease` from " + COLUMNAR_LEASE_TABLE + + " where `id` = 1 for update"; + public boolean elect(final String owner, final long nowUTC, final long leaseMs) { try { // try insert first @@ -70,7 +82,7 @@ public boolean elect(final String owner, final long nowUTC, final long leaseMs) MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, nowUTC + leaseMs); try { - final int inserts = MetaDbUtil.update(INIT, params, connection); + final int inserts = MetaDbUtil.insert(INIT, params, connection); if (1 == inserts) { return true; } @@ -89,6 +101,55 @@ public boolean elect(final String owner, final long nowUTC, final long leaseMs) } } + /** + * 返回上一个leader的租约时间, 拆成三步,insert; select for update ; update + */ + public long forceElectInsert(final String owner, final long nowUTC, final long leaseMs) { + try { + // try insert first + final Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, owner); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, nowUTC + leaseMs); + + try { + final int inserts = MetaDbUtil.insert(INIT, params, connection); + if (1 == inserts) { + return 0; + } + } catch (SQLIntegrityConstraintViolationException e) { + // ignore + return -1; + } + return -1; + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + + public List forceElectSelectForUpdate() { + try { + return MetaDbUtil.query(LOCK_LEADER_LEASE, null, ColumnarLeaseRecord.class, connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + + public void forceElectUpdate(final String owner, final long nowUTC, final long leaseMs) { + try { + // try insert first + final Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, owner); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, nowUTC + leaseMs); + + final int updates = MetaDbUtil.update(FORCE_ELECT, params, connection); + if (updates != 1) { + throw new RuntimeException("Failed to force elect"); + } + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + public boolean renew(final String owner, final long nowUTC, final long leaseMs) { try { final Map params = new HashMap<>(3); @@ -127,4 +188,14 @@ public List refresh(final String owner, final long nowUTC, throw GeneralUtil.nestedException(e); } } + + public int delete(String owner) { + try { + final Map params = new HashMap<>(2); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, owner); + return MetaDbUtil.delete(FORCE_CANCEL, params, connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPartitionEvolutionAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPartitionEvolutionAccessor.java new file mode 100644 index 000000000..944cea422 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPartitionEvolutionAccessor.java @@ -0,0 +1,191 @@ +/* + * 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 com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.gms.metadb.GmsSystemTables; +import com.alibaba.polardbx.gms.metadb.accessor.AbstractAccessor; +import com.alibaba.polardbx.gms.util.DdlMetaLogUtil; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import org.apache.commons.collections.CollectionUtils; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ColumnarPartitionEvolutionAccessor extends AbstractAccessor { + private static final Logger LOGGER = LoggerFactory.getLogger("oss"); + + private static final String COLUMNAR_PARTITION_EVOLUTION_TABLE = wrap(GmsSystemTables.COLUMNAR_PARTITION_EVOLUTION); + + private static final String COLUMNAR_TABLE_EVOLUTION_TABLE = wrap(GmsSystemTables.COLUMNAR_TABLE_EVOLUTION); + + private static final String COLUMNAR_TABLE_MAPPING_TABLE = wrap(GmsSystemTables.COLUMNAR_TABLE_MAPPING); + + private static final String INSERT_COLUMNAR_PARTITION_EVOLUTION_RECORDS = + "insert into " + COLUMNAR_PARTITION_EVOLUTION_TABLE + + "(`partition_id`, `table_id`, `partition_name`, `status`, `version_id`, `ddl_job_id`, `partition_record`) values (?, ?, ?, ?, ?, ?, ?)"; + + private static final String SELECT_ALL_COLUMNS = + "select `id`, `partition_id`, `table_id`, `partition_name`, `status`, `version_id`, `ddl_job_id`, `partition_record`, `gmt_created`"; + + private static final String FROM_TABLE = " from " + COLUMNAR_PARTITION_EVOLUTION_TABLE; + + private static final String ORDER_BY_ID = " order by id asc"; + + private static final String WHERE_BY_TABLE_ID = " where `table_id`=?" + ORDER_BY_ID; + + private static final String WHERE_BY_PARTITION_ID = " where `partition_id`=?"; + + private static final String WHERE_BY_VERSION_ID = " where `version_id`=?"; + + private static final String WHERE_BY_TABLE_ID_VERSION_ID = " where `table_id` = ? and `version_id` = ?"; + private static final String WHERE_BY_TABLE_ID_AND_VERSION_IDS = " where `table_id` = ? and `version_id` in (%s)"; + + private static final String AND_PARTITION_ID_ZERO = " and `partition_id` = 0"; + + private static final String SELECT_BY_TABLE_ID_VERSION_ID_ORDER_BY_ID = + SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_TABLE_ID_VERSION_ID + ORDER_BY_ID; + + private static final String SELECT_BY_TABLE_ID_AND_VERSION_IDS_ORDER_BY_ID = + SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_TABLE_ID_AND_VERSION_IDS + ORDER_BY_ID; + + private static final String WHERE_BY_IDS = " where `id` in (%s)"; + + private static final String SELECT_BY_TABLE_ID = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_TABLE_ID + ORDER_BY_ID; + + private static final String SELECT_BY_IDS = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_IDS; + + private static final String WHERE_BY_TABLE_ID_AND_STATUS = " where `table_id`=? and `status` = ?" + ORDER_BY_ID; + + private static final String WHERE_VERSION_ID_NOT_IN_FILED_ID_AND_STATUS = + WHERE_BY_VERSION_ID + " and `table_id`=? and `partition_id` not in ( select `partition_id`" + FROM_TABLE + + WHERE_BY_TABLE_ID_AND_STATUS + ")"; + + private static final String SELECT_BY_TABLE_ID_AND_VERSION_ID_NOT_IN_STATUS = + SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_VERSION_ID_NOT_IN_FILED_ID_AND_STATUS; + + private static final String UPDATE_FIELD_ID_AS_ID_BY_TABLE_ID_VERSION_ID = + "update " + COLUMNAR_PARTITION_EVOLUTION_TABLE + " set `partition_id`=`id`" + WHERE_BY_TABLE_ID_VERSION_ID + + AND_PARTITION_ID_ZERO; + + private static final String DELETE_TABLE_ID = "delete " + FROM_TABLE + WHERE_BY_TABLE_ID; + + public int[] insert(List records) { + List> paramsBatch = new ArrayList<>(records.size()); + for (ColumnarPartitionEvolutionRecord record : records) { + paramsBatch.add(record.buildInsertParams()); + } + try { + DdlMetaLogUtil.logSql(INSERT_COLUMNAR_PARTITION_EVOLUTION_RECORDS, paramsBatch); + return MetaDbUtil.insert(INSERT_COLUMNAR_PARTITION_EVOLUTION_RECORDS, paramsBatch, connection); + } catch (SQLException e) { + LOGGER.error("Failed to insert a batch of new records into " + COLUMNAR_PARTITION_EVOLUTION_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "batch insert into", + COLUMNAR_PARTITION_EVOLUTION_TABLE, + e.getMessage()); + } + } + + public List queryTableIdVersionIdOrderById(Long tableId, Long versionId) { + return query(SELECT_BY_TABLE_ID_VERSION_ID_ORDER_BY_ID, + COLUMNAR_PARTITION_EVOLUTION_TABLE, + ColumnarPartitionEvolutionRecord.class, + tableId, + versionId); + } + + public List queryIds(List ids) { + final Map params = + MetaDbUtil.buildParameters(ParameterMethod.setLong, ids.toArray()); + return query(String.format(SELECT_BY_IDS, concatParams(ids.size())), COLUMNAR_PARTITION_EVOLUTION_TABLE, + ColumnarPartitionEvolutionRecord.class, params); + } + + public List queryTableIdAndNotInStatus(Long tableId, Long versionId, + long status) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, versionId); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, tableId); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, tableId); + MetaDbUtil.setParameter(4, params, ParameterMethod.setString, String.valueOf(status)); + return query(SELECT_BY_TABLE_ID_AND_VERSION_ID_NOT_IN_STATUS, COLUMNAR_PARTITION_EVOLUTION_TABLE, + ColumnarPartitionEvolutionRecord.class, params); + } + + /** + * For columnar use + * + * @return list of ColumnarPartitionEvolutionRecord that keeps the order of partitionIdList + */ + public List queryIdsWithOrder(List ids) { + final List queryResults = queryIds(ids); + + // Reorder columns + Map pos = new HashMap<>(); + for (int i = 0; i < ids.size(); i++) { + pos.put(ids.get(i), i); + } + + ColumnarPartitionEvolutionRecord[] results = new ColumnarPartitionEvolutionRecord[ids.size()]; + for (ColumnarPartitionEvolutionRecord record : queryResults) { + results[pos.get(record.id)] = record; + } + return Arrays.asList(results); + } + + public List queryTableIdAndVersionIdsOrderById(Long tableId, + List versionIds) { + if (CollectionUtils.isEmpty(versionIds)) { + return new ArrayList<>(); + } + + List paramValues = new ArrayList<>(); + paramValues.add(tableId); + paramValues.addAll(versionIds); + + final Map params = + MetaDbUtil.buildParameters(ParameterMethod.setLong, paramValues.toArray()); + return query(String.format(SELECT_BY_TABLE_ID_AND_VERSION_IDS_ORDER_BY_ID, concatParams(versionIds.size())), + COLUMNAR_PARTITION_EVOLUTION_TABLE, + ColumnarPartitionEvolutionRecord.class, + params); + } + + public void updatePartitionIdAsId(long tableId, long versionId) { + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tableId); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, versionId); + update(UPDATE_FIELD_ID_AS_ID_BY_TABLE_ID_VERSION_ID, COLUMNAR_PARTITION_EVOLUTION_TABLE, params); + } + + public int deleteId(long tableId) { + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tableId); + return delete(DELETE_TABLE_ID, COLUMNAR_PARTITION_EVOLUTION_TABLE, params); + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPartitionEvolutionRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPartitionEvolutionRecord.java new file mode 100644 index 000000000..d0cddaddf --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPartitionEvolutionRecord.java @@ -0,0 +1,172 @@ +/* + * 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 com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; +import com.alibaba.polardbx.gms.partition.ExtraFieldJSON; +import com.alibaba.polardbx.gms.partition.TablePartitionRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import lombok.Getter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.Map; + +@Getter +public class ColumnarPartitionEvolutionRecord implements SystemTableRecord { + private static final Logger log = LoggerFactory.getLogger(ColumnarPartitionEvolutionRecord.class); + + public long id; + public long tableId; + public long partitionId; + public String partitionName; + public long versionId; + public long ddlJobId; + public int status; + + public Timestamp create; + public TablePartitionRecord partitionRecord; + + public ColumnarPartitionEvolutionRecord() { + } + + public ColumnarPartitionEvolutionRecord(long tableId, String partitionName, long versionId, long ddlJobId, + TablePartitionRecord partitionRecord, int status) { + this.tableId = tableId; + this.partitionName = partitionName; + this.versionId = versionId; + this.ddlJobId = ddlJobId; + this.partitionRecord = partitionRecord; + this.status = status; + } + + public ColumnarPartitionEvolutionRecord(long tableId, long partitionId, String columnName, long versionId, + long ddlJobId, TablePartitionRecord partitionRecord, int status) { + this.tableId = tableId; + this.partitionId = partitionId; + this.partitionName = columnName; + this.versionId = versionId; + this.ddlJobId = ddlJobId; + this.partitionRecord = partitionRecord; + this.status = status; + } + + public static String serializeToJson(TablePartitionRecord partitionRecord) { + JSONObject tablePartitionJson = new JSONObject(); + + tablePartitionJson.put("id", partitionRecord.id); + tablePartitionJson.put("parentId", partitionRecord.parentId); + tablePartitionJson.put("tableSchema", partitionRecord.tableSchema); + tablePartitionJson.put("tableName", partitionRecord.tableName); + tablePartitionJson.put("spTempFlag", partitionRecord.spTempFlag); + tablePartitionJson.put("groupId", partitionRecord.groupId); + tablePartitionJson.put("metaVersion", partitionRecord.metaVersion); + tablePartitionJson.put("autoFlag", partitionRecord.autoFlag); + tablePartitionJson.put("tblType", partitionRecord.tblType); + tablePartitionJson.put("partName", partitionRecord.partName); + tablePartitionJson.put("partTempName", partitionRecord.partTempName); + tablePartitionJson.put("partLevel", partitionRecord.partLevel); + tablePartitionJson.put("nextLevel", partitionRecord.nextLevel); + tablePartitionJson.put("partStatus", partitionRecord.partStatus); + tablePartitionJson.put("partPosition", partitionRecord.partPosition); + tablePartitionJson.put("partMethod", partitionRecord.partMethod); + tablePartitionJson.put("partExpr", partitionRecord.partExpr); + tablePartitionJson.put("partDesc", partitionRecord.partDesc); + tablePartitionJson.put("partComment", partitionRecord.partComment); + tablePartitionJson.put("partEngine", partitionRecord.partEngine); + tablePartitionJson.put("partExtras", ExtraFieldJSON.toJson(partitionRecord.partExtras)); + tablePartitionJson.put("partFlags", partitionRecord.partFlags); + tablePartitionJson.put("phyTable", partitionRecord.phyTable); + + return tablePartitionJson.toJSONString(); + } + + public static TablePartitionRecord deserializeFromJson(String json) { + TablePartitionRecord partitionRecord = new TablePartitionRecord(); + JSONObject columnRecordJson = JSON.parseObject(json); + + try { + partitionRecord.id = columnRecordJson.getLongValue("id"); + } catch (Exception e) { + // id may be not exists in old version + log.warn( + "Cannot deserialize id from json because old version columnar_partition_evolution record's id not exist, use default value -1"); + partitionRecord.id = -1L; + } + partitionRecord.parentId = columnRecordJson.getLongValue("parentId"); + partitionRecord.tableSchema = columnRecordJson.getString("tableSchema"); + partitionRecord.tableName = columnRecordJson.getString("tableName"); + partitionRecord.spTempFlag = columnRecordJson.getIntValue("spTempFlag"); + partitionRecord.groupId = columnRecordJson.getLongValue("groupId"); + partitionRecord.metaVersion = columnRecordJson.getLongValue("metaVersion"); + partitionRecord.autoFlag = columnRecordJson.getIntValue("autoFlag"); + partitionRecord.tblType = columnRecordJson.getIntValue("tblType"); + partitionRecord.partName = columnRecordJson.getString("partName"); + partitionRecord.partTempName = columnRecordJson.getString("partTempName"); + partitionRecord.partLevel = columnRecordJson.getIntValue("partLevel"); + partitionRecord.nextLevel = columnRecordJson.getIntValue("nextLevel"); + partitionRecord.partStatus = columnRecordJson.getIntValue("partStatus"); + partitionRecord.partPosition = columnRecordJson.getLongValue("partPosition"); + partitionRecord.partMethod = columnRecordJson.getString("partMethod"); + partitionRecord.partExpr = columnRecordJson.getString("partExpr"); + partitionRecord.partDesc = columnRecordJson.getString("partDesc"); + partitionRecord.partComment = columnRecordJson.getString("partComment"); + partitionRecord.partEngine = columnRecordJson.getString("partEngine"); + partitionRecord.partExtras = ExtraFieldJSON.fromJson(columnRecordJson.getString("partExtras")); + partitionRecord.partFlags = columnRecordJson.getLongValue("partFlags"); + partitionRecord.phyTable = columnRecordJson.getString("phyTable"); + + return partitionRecord; + } + + @Override + public ColumnarPartitionEvolutionRecord fill(ResultSet rs) throws SQLException { + this.id = rs.getLong("id"); + this.partitionId = rs.getLong("partition_id"); + this.tableId = rs.getLong("table_id"); + this.partitionName = rs.getString("partition_name"); + this.status = rs.getInt("status"); + this.versionId = rs.getLong("version_id"); + this.ddlJobId = rs.getLong("ddl_job_id"); + this.partitionRecord = deserializeFromJson(rs.getString("partition_record")); + this.create = rs.getTimestamp("gmt_created"); + return this; + } + + public Map buildInsertParams() { + Map params = new HashMap<>(16); + int index = 0; + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.partitionId); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.tableId); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.partitionName); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setInt, this.status); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.versionId); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.ddlJobId); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, serializeToJson(this.partitionRecord)); + return params; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPartitionStatus.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPartitionStatus.java new file mode 100644 index 000000000..d45bd2a49 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPartitionStatus.java @@ -0,0 +1,45 @@ +/* + * 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 com.alibaba.polardbx.gms.metadb.table; + +public enum ColumnarPartitionStatus { + ABSENT(0), + PUBLIC(1); + + private final int value; + + ColumnarPartitionStatus(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } + + public static ColumnarPartitionStatus convert(int value) { + switch (value) { + case 0: + return ABSENT; + case 1: + return PUBLIC; + default: + return null; + } + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPurgeHistoryAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPurgeHistoryAccessor.java new file mode 100644 index 000000000..c8fd3894a --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPurgeHistoryAccessor.java @@ -0,0 +1,116 @@ +/* + * 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 com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.gms.metadb.accessor.AbstractAccessor; +import com.alibaba.polardbx.gms.util.DdlMetaLogUtil; +import com.alibaba.polardbx.gms.util.MetaDbUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.COLUMNAR_PURGE_HISTORY; + +public class ColumnarPurgeHistoryAccessor extends AbstractAccessor { + private static final Logger LOGGER = LoggerFactory.getLogger("oss"); + private static final String COLUMNAR_PURGE_HISTORY_TABLE = wrap(COLUMNAR_PURGE_HISTORY); + + private static final String INSERT = "insert into " + COLUMNAR_PURGE_HISTORY_TABLE + + " (`tso`, `status`, `info`, `extra`)" + + " values (?, ?, ?, ?)"; + + private static final String SELECT_LAST_PURGE = "select * from " + COLUMNAR_PURGE_HISTORY_TABLE + + " order by `tso` desc limit 1"; + + private static final String SELECT_TSO_PURGE_RECORD = "select * from " + COLUMNAR_PURGE_HISTORY_TABLE + + " where `tso` = ? "; + + private static final String UPDATE_STATUS_BY_TSO = "update " + COLUMNAR_PURGE_HISTORY_TABLE + + " set `status` = ? where `tso` = ? "; + + private static final String UPDATE_EXTRA_BY_TSO = "update " + COLUMNAR_PURGE_HISTORY_TABLE + + " set `extra` = ? where `tso` = ? "; + + public int[] insert(Collection records) { + try { + final List> params = new ArrayList<>(); + for (ColumnarPurgeHistoryRecord record : records) { + params.add(record.buildInsertParams()); + } + + DdlMetaLogUtil.logSql(INSERT, params); + return MetaDbUtil.insert(INSERT, params, connection); + + } catch (Exception e) { + LOGGER.error("Failed to insert a batch of new records into " + COLUMNAR_PURGE_HISTORY_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "batch insert into", + COLUMNAR_PURGE_HISTORY_TABLE, + e.getMessage()); + } + } + + public List queryLastPurgeTso() { + try { + return MetaDbUtil.query(SELECT_LAST_PURGE, null, ColumnarPurgeHistoryRecord.class, + connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + COLUMNAR_PURGE_HISTORY_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + COLUMNAR_PURGE_HISTORY_TABLE, e.getMessage()); + } + } + + public List queryPurgeRecordByTso(long tso) { + try { + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + + return MetaDbUtil.query(SELECT_TSO_PURGE_RECORD, params, ColumnarPurgeHistoryRecord.class, + connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + COLUMNAR_PURGE_HISTORY_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + COLUMNAR_PURGE_HISTORY_TABLE, + e.getMessage()); + } + } + + public int updateStatusByTso(ColumnarPurgeHistoryRecord.PurgeStatus status, long tso) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, status.toString()); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, tso); + return update(UPDATE_STATUS_BY_TSO, COLUMNAR_PURGE_HISTORY_TABLE, params); + } + + public int updateStatusByTso(String extra, long tso) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, extra); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, tso); + return update(UPDATE_EXTRA_BY_TSO, COLUMNAR_PURGE_HISTORY_TABLE, params); + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPurgeHistoryRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPurgeHistoryRecord.java new file mode 100644 index 000000000..f5042e7b8 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarPurgeHistoryRecord.java @@ -0,0 +1,101 @@ +/* + * 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 com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.Map; + +public class ColumnarPurgeHistoryRecord implements SystemTableRecord { + + public long id; + public long tso; + public String status; + public String info; + public String extra; + + public Timestamp createTime; + public Timestamp updateTime; + + @Override + public ColumnarPurgeHistoryRecord fill(ResultSet rs) throws SQLException { + this.id = rs.getLong("id"); + this.tso = rs.getLong("tso"); + this.status = rs.getString("status"); + this.info = rs.getString("info"); + this.extra = rs.getString("extra"); + this.createTime = rs.getTimestamp("gmt_created"); + this.updateTime = rs.getTimestamp("gmt_modified"); + return this; + } + + public Map buildInsertParams() { + Map params = new HashMap<>(8); + int index = 0; + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.tso); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.status); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.info); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.extra); + return params; + } + + public enum PurgeStatus { + NONE, + START, + FINISHED, + FAILED; + + public String toString() { + switch (this) { + case NONE: + return "None"; + case START: + return "Start"; + case FINISHED: + return "Finished"; + case FAILED: + return "Failed"; + default: + throw new IllegalArgumentException("Unsupported enum constant: " + this); + } + } + + public static PurgeStatus fromString(String value) { + switch (value.toLowerCase()) { + case "none": + return NONE; + case "start": + return START; + case "finished": + return FINISHED; + case "failed": + return FAILED; + default: + throw new IllegalArgumentException("Invalid string value for PurgeStatus enum: " + value); + } + } + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableEvolutionAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableEvolutionAccessor.java index b0fef2a39..781a2d827 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableEvolutionAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableEvolutionAccessor.java @@ -28,6 +28,8 @@ import com.alibaba.polardbx.gms.util.DdlMetaLogUtil; import com.alibaba.polardbx.gms.util.MetaDbUtil; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; @@ -43,10 +45,10 @@ public class ColumnarTableEvolutionAccessor extends AbstractAccessor { private static final String INSERT_COLUMNAR_TABLE_EVOLUTION_RECORDS = "insert into " + COLUMNAR_TABLE_EVOLUTION_TABLE + - "(`version_id`, `table_id`, `table_schema`, `table_name`, `index_name`, `ddl_job_id`, `ddl_type`, `commit_ts`, `columns`, `options`) values (?, ?, ?, ?, ?, ?, ? ,? ,?, ?)"; + "(`version_id`, `table_id`, `table_schema`, `table_name`, `index_name`, `ddl_job_id`, `ddl_type`, `commit_ts`, `columns`, `partitions`, `options`) values (?, ?, ?, ?, ?, ?, ?, ? ,? ,?, ?)"; private static final String SELECT_ALL_COLUMNS = - "select `version_id`, `table_id`, `table_schema`, `table_name`, `index_name`, `ddl_job_id`, `ddl_type`, `commit_ts`, `columns`, `options`"; + "select `version_id`, `table_id`, `table_schema`, `table_name`, `index_name`, `ddl_job_id`, `ddl_type`, `commit_ts`, `columns`, `partitions`, `options`"; private static final String FROM_TABLE = " from " + COLUMNAR_TABLE_EVOLUTION_TABLE; @@ -74,9 +76,14 @@ public class ColumnarTableEvolutionAccessor extends AbstractAccessor { private static final String ORDER_BY_VERSION_ID_LATEST = " order by `version_id` desc limit 1"; + private static final String ORDER_BY_VERSION_ID_FIRST = " order by `version_id` limit 1"; + private static final String WHERE_BY_VERSION_ID = " where `version_id` = ?"; private static final String WHERE_BY_COMMIT_TS = " where `commit_ts` = ?"; + private static final String WHERE_BY_OVER_COMMIT_TS = " where `commit_ts` > ?"; + + private static final String AND_TABLE_ID = " and `table_id` = ?"; private static final String WHERE_BY_SCHEMA_TABLE_INDEX = " where `table_id` in (select `table_id` from " + COLUMNAR_TABLE_MAPPING_TABLE @@ -98,11 +105,17 @@ public class ColumnarTableEvolutionAccessor extends AbstractAccessor { private static final String UPDATE_DDL_TYPE_BY_VERSION_ID = "update " + COLUMNAR_TABLE_EVOLUTION_TABLE + " set ddl_type=? " + WHERE_BY_VERSION_ID; + private static final String UPDATE_PARTITIONS_BY_TABLE_ID = + "update " + COLUMNAR_TABLE_EVOLUTION_TABLE + " set partitions=? " + WHERE_BY_TABLE_ID; + private static final String WITH_READ_LOCK = " LOCK IN SHARE MODE"; private static final String SELECT_TABLE_ID = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_TABLE_ID_ORDER_BY_COMMIT_TS; + private static final String SELECT_TABLE_ID_FIRST = + SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_TABLE_ID + ORDER_BY_VERSION_ID_FIRST; + private static final String SELECT_TABLE_ID_AND_GT_COMMIT_TS = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_TABLE_ID_AND_GT_COMMIT_TS_ORDER_BY_COMMIT_TS; @@ -113,6 +126,8 @@ public class ColumnarTableEvolutionAccessor extends AbstractAccessor { SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_TABLE_ID_VERSION_ID; private static final String SELECT_COMMIT_TS = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_COMMIT_TS; + private static final String SELECT_COMMIT_TS_TABLE_ID = + SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_COMMIT_TS + AND_TABLE_ID; private static final String SELECT_TABLE_ID_LATEST = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_TABLE_ID_LATEST; private static final String SELECT_SCHEMA_INDEX_LATEST = @@ -123,8 +138,23 @@ public class ColumnarTableEvolutionAccessor extends AbstractAccessor { private static final String SELECT_LATEST_BY_VERSION_ID = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_VERSION_ID; + private static final String SELECT_ALL_BY_OVER_COMMIT_TS = + SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_OVER_COMMIT_TS; + + private static final String WHERE_PARTITION_IS_NULL = " where `partitions` is null"; + + private static final String GROUP_BY_TABLE_ID = " group by table_id"; + + private static final String SELECT_BY_PARTITION_NULL_GROUP_BY_CCI = + SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_PARTITION_IS_NULL + GROUP_BY_TABLE_ID; + private static final String DELETE_TABLE_ID = "delete " + FROM_TABLE + WHERE_BY_TABLE_ID; + private static final String HAVE_DONE_DDL = "SELECT COUNT(0) " + FROM_TABLE + WHERE_BY_TABLE_ID; + + private static final String UPDATE_COMMIT_TS_BY_OVER_COMMIT_TS = + "update " + COLUMNAR_TABLE_EVOLUTION_TABLE + " set commit_ts=" + Long.MAX_VALUE + " " + WHERE_BY_OVER_COMMIT_TS; + public int[] insert(List records) { List> paramsBatch = new ArrayList<>(records.size()); for (ColumnarTableEvolutionRecord record : records) { @@ -145,6 +175,11 @@ public List queryTableId(Long tableId) { return query(SELECT_TABLE_ID, COLUMNAR_TABLE_EVOLUTION_TABLE, ColumnarTableEvolutionRecord.class, tableId); } + public List queryTableIdFirst(Long tableId) { + return query(SELECT_TABLE_ID_FIRST, COLUMNAR_TABLE_EVOLUTION_TABLE, ColumnarTableEvolutionRecord.class, + tableId); + } + public List queryTableIdAndGreaterThanTso(Long tableId, Long commitTs) { return query(SELECT_TABLE_ID_AND_GT_COMMIT_TS, COLUMNAR_TABLE_EVOLUTION_TABLE, ColumnarTableEvolutionRecord.class, tableId, commitTs); @@ -188,6 +223,16 @@ public List queryCommitTs(long commitTs) { commitTs); } + public List queryByOverCommitTs(long commitTs) { + return query(SELECT_ALL_BY_OVER_COMMIT_TS, COLUMNAR_TABLE_EVOLUTION_TABLE, ColumnarTableEvolutionRecord.class, + commitTs); + } + + public List queryCommitTsAndTableId(long commitTs, long tableId) { + return query(SELECT_COMMIT_TS_TABLE_ID, COLUMNAR_TABLE_EVOLUTION_TABLE, ColumnarTableEvolutionRecord.class, + commitTs, tableId); + } + public void deleteSchemaTableIndex(String schemaName, String tableName, String indexName) { Map params = new HashMap<>(3); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); @@ -203,6 +248,12 @@ public void updateCommitTs(long commitTs, long versionId) { update(UPDATE_COMMIT_TS_VERSION_ID, COLUMNAR_TABLE_EVOLUTION_TABLE, params); } + public int updateCommitTs(long commitTs) { + Map params = new HashMap<>(2); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, commitTs); + return update(UPDATE_COMMIT_TS_BY_OVER_COMMIT_TS, COLUMNAR_TABLE_EVOLUTION_TABLE, params); + } + public void updateDdlType(String ddlType, long ddlId) { Map params = new HashMap<>(2); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, ddlType); @@ -224,20 +275,48 @@ public List queryVersionIdWithReadLock(long versio ColumnarTableEvolutionRecord.class, versionId); } - public void deleteSchema(String schemaName) { + public List queryPartitionEmptyRecords() { + return query(SELECT_BY_PARTITION_NULL_GROUP_BY_CCI, COLUMNAR_TABLE_EVOLUTION_TABLE, + ColumnarTableEvolutionRecord.class); + } + + public void updatePartition(long tableId, List partitions) { + Map params = new HashMap<>(2); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, + ColumnarTableEvolutionRecord.serializeToJson(partitions)); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, tableId); + update(UPDATE_PARTITIONS_BY_TABLE_ID, COLUMNAR_TABLE_EVOLUTION_TABLE, params); + } + + public int deleteSchema(String schemaName) { Map params = new HashMap<>(1); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); try { DdlMetaLogUtil.logSql(DELETE_SCHEMA, params); - MetaDbUtil.delete(DELETE_SCHEMA, params, connection); + return MetaDbUtil.delete(DELETE_SCHEMA, params, connection); } catch (Exception e) { throw GeneralUtil.nestedException(e); } } - public void deleteId(long tableId) { + public int deleteId(long tableId) { Map params = new HashMap<>(1); MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tableId); - delete(DELETE_TABLE_ID, COLUMNAR_TABLE_EVOLUTION_TABLE, params); + return delete(DELETE_TABLE_ID, COLUMNAR_TABLE_EVOLUTION_TABLE, params); + } + + public boolean haveDoneDdl(long tableId) { + try (PreparedStatement stmt = connection.prepareStatement(HAVE_DONE_DDL)) { + stmt.setLong(1, tableId); + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + return rs.getInt(1) > 1; + } else { + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, "not found result set"); + } + } + } catch (SQLException e) { + throw GeneralUtil.nestedException(e); + } } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableEvolutionRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableEvolutionRecord.java index 0ac878e39..51042ed73 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableEvolutionRecord.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableEvolutionRecord.java @@ -45,6 +45,7 @@ public class ColumnarTableEvolutionRecord implements SystemTableRecord { public String ddlType; public long commitTs; public List columns; + public List partitions; public Map options; public ColumnarTableEvolutionRecord() { @@ -54,7 +55,8 @@ public ColumnarTableEvolutionRecord(long versionId, long tableId, String tableSc String indexName, Map options, long ddlJobId, - String ddlType, long commitTs, List columns) { + String ddlType, long commitTs, + List columns, List partitions) { this.versionId = versionId; this.tableId = tableId; this.tableSchema = tableSchema; @@ -65,11 +67,12 @@ public ColumnarTableEvolutionRecord(long versionId, long tableId, String tableSc this.ddlType = ddlType; this.commitTs = commitTs; this.columns = columns; + this.partitions = partitions; } - public static String serializeToJson(List columns) { + public static String serializeToJson(List ids) { JSONArray jsonArray = new JSONArray(); - jsonArray.addAll(columns); + jsonArray.addAll(ids); return jsonArray.toJSONString(); } @@ -83,6 +86,9 @@ public static String serializeToJson(Map options) { } public static List deserializeListFromJson(String json) { + if (json == null) { + return new ArrayList<>(); + } List results = new ArrayList<>(); JSONArray jsonArray = JSON.parseArray(json); for (int i = 0; i < jsonArray.size(); i++) { @@ -122,8 +128,11 @@ public ColumnarTableEvolutionRecord fill(ResultSet rs) throws SQLException { this.ddlType = rs.getString("ddl_type"); this.commitTs = rs.getLong("commit_ts"); - String json = rs.getString("columns"); - this.columns = deserializeListFromJson(json); + String columns = rs.getString("columns"); + this.columns = deserializeListFromJson(columns); + + String partitions = rs.getString("partitions"); + this.partitions = deserializeListFromJson(partitions); String options = rs.getString("options"); this.options = deserializeMapFromJson(options); @@ -143,6 +152,7 @@ public Map buildInsertParams() { MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.ddlType); MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.commitTs); MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, serializeToJson(this.columns)); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, serializeToJson(this.partitions)); MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, serializeToJson(this.options)); return params; } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableMappingAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableMappingAccessor.java index 1f95a72b4..287dff4c2 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableMappingAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableMappingAccessor.java @@ -42,9 +42,10 @@ public class ColumnarTableMappingAccessor extends AbstractAccessor { private static final Logger LOGGER = LoggerFactory.getLogger("oss"); private static final String COLUMNAR_TABLE_MAPPING_TABLE = wrap(GmsSystemTables.COLUMNAR_TABLE_MAPPING); + private static final String FILES_TABLE = wrap(GmsSystemTables.FILES); private static final String INSERT_COLUMNAR_TABLE_MAPPING_RECORDS = "insert into " + COLUMNAR_TABLE_MAPPING_TABLE + - "(`table_schema`, `table_name`, `index_name`, `latest_version_id`, `status`, `extra`) values (?, ?, ?, ?, ?, ?)"; + "(`table_schema`, `table_name`, `index_name`, `latest_version_id`, `status`, `extra`, `type`) values (?, ?, ?, ?, ?, ?, ?)"; private static final String FROM_TABLE = " from " + COLUMNAR_TABLE_MAPPING_TABLE; @@ -66,17 +67,26 @@ public class ColumnarTableMappingAccessor extends AbstractAccessor { private static final String WHERE_BY_SCHEMA_TABLE = " where `table_schema` = ? and `table_name` = ?"; + private static final String WHERE_BY_SCHEMA_TABLE_ID = + " where `table_schema` = ? and `table_id` = ?"; + private static final String WHERE_BY_SCHEMA_INDEX = " where `table_schema` = ? and `index_name` = ?"; private static final String WHERE_BY_SCHEMA = " where `table_schema` = ?"; + private static final String WHERE_BY_SCHEMA_TABLE_INDEX_LIKE_AND_STATUS = + " where `table_schema` = ? and `table_name` = ? and `index_name` like ? and status = ? "; + private static final String DELETE_SCHEMA_TABLE_INDEX = "delete " + FROM_TABLE + WHERE_BY_SCHEMA_TABLE_INDEX; private static final String DELETE_SCHEMA = "delete " + FROM_TABLE + WHERE_BY_SCHEMA; private static final String SELECT_ALL_COLUMNS = - "select `table_id`, `table_schema`, `table_name`, `index_name`, `latest_version_id`, `status`, `extra`"; + "select `table_id`, `table_schema`, `table_name`, `index_name`, `latest_version_id`, `status`, `extra`, `type`"; + + private static final String UPDATE_TYPE_BY_ID = + "update " + COLUMNAR_TABLE_MAPPING_TABLE + " set `type` = ? " + WHERE_BY_TABLE_ID; private static final String SELECT_SCHEMA_TABLE_INDEX = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_SCHEMA_TABLE_INDEX; @@ -91,6 +101,8 @@ public class ColumnarTableMappingAccessor extends AbstractAccessor { private static final String SELECT_SCHEMA_TABLE = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_SCHEMA_TABLE; + private static final String SELECT_SCHEMA_TABLE_ID = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_SCHEMA_TABLE_ID; + private static final String SELECT_SCHEMA_TABLE_AND_VERSION_ID = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_BY_SCHEMA_TABLE + AND_VERSION_ID; @@ -100,11 +112,17 @@ public class ColumnarTableMappingAccessor extends AbstractAccessor { private static final String SELECT_ALL = SELECT_ALL_COLUMNS + FROM_TABLE; + private static final String SELECT_ALL_SNAPSHOT_CCI = SELECT_ALL_COLUMNS + FROM_TABLE + " force index(idx_type) " + + "where type = 'snapshot' and status = '" + ColumnarTableStatus.PUBLIC.name() + "'"; + private static final String SELECT_TABLE_BY_STATUS = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_STATUS; private static final String SELECT_TABLE_BY_SCHEMA_AND_STATUS = SELECT_ALL_COLUMNS + FROM_TABLE + WHERE_SCHEMA_AND_STATUS; + private static final String SELECT_TABLE_BY_SCHEMA_TABLE_INDEX_LIKE_AND_STATUS = SELECT_ALL_COLUMNS + FROM_TABLE + + WHERE_BY_SCHEMA_TABLE_INDEX_LIKE_AND_STATUS; + private static final String DELETE_TABLE_ID = "delete " + FROM_TABLE + WHERE_BY_TABLE_ID; private static final String UPDATE_LATEST_VERSION_ID_BY_TABLE_ID = @@ -113,6 +131,9 @@ public class ColumnarTableMappingAccessor extends AbstractAccessor { private static final String UPDATE_TABLE_NAME_LATEST_VERSION_ID_BY_TABLE_ID = "update " + COLUMNAR_TABLE_MAPPING_TABLE + " set table_name = ?, `latest_version_id` = ?" + WHERE_BY_TABLE_ID; + private static final String UPDATE_INDEX_NAME_LATEST_VERSION_ID_BY_TABLE_ID = + "update " + COLUMNAR_TABLE_MAPPING_TABLE + " set index_name = ?, `latest_version_id` = ?" + WHERE_BY_TABLE_ID; + private static final String UPDATE_TABLE_STATUS_BY_TABLE_ID = "update " + COLUMNAR_TABLE_MAPPING_TABLE + " set status = ? " + WHERE_BY_TABLE_ID; @@ -122,6 +143,10 @@ public class ColumnarTableMappingAccessor extends AbstractAccessor { private static final String UPDATE_TABLE_STATUS_AND_VERSION_ID_BY_TABLE_ID = "update " + COLUMNAR_TABLE_MAPPING_TABLE + " set `status` = ?, `latest_version_id` = ? " + WHERE_BY_TABLE_ID; + private static final String UPDATE_TABLE_STATUS_AND_VERSION_ID_BY_SCHEMA = + "update " + COLUMNAR_TABLE_MAPPING_TABLE + + " set `status` = ?, `latest_version_id` = ? " + WHERE_BY_SCHEMA; + private static final String UPDATE_TABLE_STATUS_AND_VERSION_ID_BY_NAME = "update " + COLUMNAR_TABLE_MAPPING_TABLE + " set `status` = ?, `latest_version_id` = ? " + WHERE_BY_SCHEMA_TABLE_INDEX; @@ -129,12 +154,37 @@ public class ColumnarTableMappingAccessor extends AbstractAccessor { private static final String UPDATE_TABLE_STATUS_BY_TABLE_ID_AND_STATUS = "update " + COLUMNAR_TABLE_MAPPING_TABLE + " set status = ? " + WHERE_BY_TABLE_ID_AND_STATUS; + private static final String UPDATE_TABLE_STATUS_AND_VERSION_ID_BY_TABLE_ID_AND_STATUS = + "update " + COLUMNAR_TABLE_MAPPING_TABLE + " set `latest_version_id` = ? , `status` = ? " + + WHERE_BY_TABLE_ID_AND_STATUS; + private static final String UPDATE_TABLE_STATUS_AND_EXTRA_BY_TABLE_ID = "update " + COLUMNAR_TABLE_MAPPING_TABLE + " set `status` = ?, `extra` = ? " + WHERE_BY_TABLE_ID; private static final String UPDATE_EXTRA_BY_TABLE_ID = "update " + COLUMNAR_TABLE_MAPPING_TABLE + " set `extra` = ? " + WHERE_BY_TABLE_ID; + private static final String SELECT_PURGE_TABLE_BY_TSO = + SELECT_ALL_COLUMNS + + FROM_TABLE + + " where `status` = '" + ColumnarTableStatus.PURGE.name() + "' and `latest_version_id` < ? "; + + private static final String SELECT_PURGE_TABLE_WHICH_HAVE_PURGE_FILE_BY_TSO = + "select DISTINCT a.`table_id`, a.`table_schema`, a.`table_name`, a.`index_name`, a.`latest_version_id`, a.`status`, a.`extra`, a.`type` " + + FROM_TABLE + " as a inner join " + + FILES_TABLE + + " as b on a.`table_schema` = b.`logical_schema_name` and a.`table_id` = b.`logical_table_name` " + + " where a.`status` = '" + ColumnarTableStatus.PUBLIC.name() + + "' and b.`remove_ts` is not null and b.`remove_ts` < ? "; + + private static final String SELECT_PURGE_TABLE_WHICH_HAVE_PURGE_FILE_BY_TSO_AND_TYPE = + "select DISTINCT a.`table_id`, a.`table_schema`, a.`table_name`, a.`index_name`, a.`latest_version_id`, a.`status`, a.`extra`, a.`type` " + + FROM_TABLE + " as a inner join " + + FILES_TABLE + + " as b on a.`table_schema` = b.`logical_schema_name` and a.`table_id` = b.`logical_table_name` " + + " where a.`status` = '" + ColumnarTableStatus.PUBLIC.name() + + "' and b.`remove_ts` is not null and b.`remove_ts` < ? and type = ?"; + public int[] insert(List records) { List> paramsBatch = new ArrayList<>(records.size()); for (ColumnarTableMappingRecord record : records) { @@ -197,6 +247,13 @@ public List querySchemaTable(String schemaName, Stri schemaName, tableName); } + public List querySchemaTableId(String schemaName, long tableId) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, tableId); + return query(SELECT_SCHEMA_TABLE_ID, COLUMNAR_TABLE_MAPPING_TABLE, ColumnarTableMappingRecord.class, params); + } + public List querySchemaTableByVersionId(String schemaName, String tableName, Long versionId) { Map params = new HashMap<>(3); @@ -221,6 +278,11 @@ public List queryAll() { Collections.emptyMap()); } + public List queryAllSnapshotCci() { + return query(SELECT_ALL_SNAPSHOT_CCI, COLUMNAR_TABLE_MAPPING_TABLE, ColumnarTableMappingRecord.class, + Collections.emptyMap()); + } + public List queryByStatus(String status) { return query(SELECT_TABLE_BY_STATUS, COLUMNAR_TABLE_MAPPING_TABLE, ColumnarTableMappingRecord.class, status); } @@ -230,29 +292,36 @@ public List queryBySchemaAndStatus(String schemaName schemaName, status); } - public void deleteTableSchemaIndex(String schemaName, String tableName, String indexName) { + public List queryBySchemaTableIndexLike(String schemaName, String tableName, + String indexName, String status) { + return query(SELECT_TABLE_BY_SCHEMA_TABLE_INDEX_LIKE_AND_STATUS, COLUMNAR_TABLE_MAPPING_TABLE, + ColumnarTableMappingRecord.class, + schemaName, tableName, indexName, status); + } + + public int deleteTableSchemaIndex(String schemaName, String tableName, String indexName) { Map params = new HashMap<>(3); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); MetaDbUtil.setParameter(3, params, ParameterMethod.setString, indexName); - delete(DELETE_SCHEMA_TABLE_INDEX, COLUMNAR_TABLE_MAPPING_TABLE, params); + return delete(DELETE_SCHEMA_TABLE_INDEX, COLUMNAR_TABLE_MAPPING_TABLE, params); } - public void deleteSchema(String schemaName) { + public int deleteSchema(String schemaName) { Map params = new HashMap<>(1); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); try { DdlMetaLogUtil.logSql(DELETE_SCHEMA, params); - MetaDbUtil.delete(DELETE_SCHEMA, params, connection); + return MetaDbUtil.delete(DELETE_SCHEMA, params, connection); } catch (Exception e) { throw GeneralUtil.nestedException(e); } } - public void deleteId(long tableId) { + public int deleteId(long tableId) { Map params = new HashMap<>(1); MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tableId); - delete(DELETE_TABLE_ID, COLUMNAR_TABLE_MAPPING_TABLE, params); + return delete(DELETE_TABLE_ID, COLUMNAR_TABLE_MAPPING_TABLE, params); } public void updateVersionId(long versionId, long tableId) { @@ -270,6 +339,14 @@ public void updateTableNameId(String tableName, long versionId, long tableId) { update(UPDATE_TABLE_NAME_LATEST_VERSION_ID_BY_TABLE_ID, COLUMNAR_TABLE_MAPPING_TABLE, params); } + public void updateIndexNameId(String indexName, long versionId, long tableId) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, indexName); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, versionId); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, tableId); + update(UPDATE_INDEX_NAME_LATEST_VERSION_ID_BY_TABLE_ID, COLUMNAR_TABLE_MAPPING_TABLE, params); + } + public int updateStatusAndVersionIdByTableId(long tableId, long newVersionId, String status) { @@ -281,21 +358,33 @@ public int updateStatusAndVersionIdByTableId(long tableId, return update(UPDATE_TABLE_STATUS_AND_VERSION_ID_BY_TABLE_ID, COLUMNAR_TABLE_MAPPING_TABLE, params); } - public void updateStatusByTableIdAndStatus(long tableId, String oldStatus, String newStatus) { + public int updateStatusByTableIdAndStatus(long tableId, String oldStatus, String newStatus) { Map params = new HashMap<>(4); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, newStatus); MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, tableId); MetaDbUtil.setParameter(3, params, ParameterMethod.setString, oldStatus); - update(UPDATE_TABLE_STATUS_BY_TABLE_ID_AND_STATUS, COLUMNAR_TABLE_MAPPING_TABLE, params); + return update(UPDATE_TABLE_STATUS_BY_TABLE_ID_AND_STATUS, COLUMNAR_TABLE_MAPPING_TABLE, params); } - public void updateStatusBySchema(String schemaName, String status) { - Map params = new HashMap<>(2); + public int updateStatusAndLastVersionIdByTableIdAndStatus(long tableId, long lastVersionId, String oldStatus, + String newStatus) { + Map params = new HashMap<>(8); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, lastVersionId); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, newStatus); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, tableId); + MetaDbUtil.setParameter(4, params, ParameterMethod.setString, oldStatus); + + return update(UPDATE_TABLE_STATUS_AND_VERSION_ID_BY_TABLE_ID_AND_STATUS, COLUMNAR_TABLE_MAPPING_TABLE, params); + } + + public void updateStatusAndVersionIdBySchema(String schemaName, long versionId, String status) { + Map params = new HashMap<>(3); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, status); - MetaDbUtil.setParameter(2, params, ParameterMethod.setString, schemaName); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, versionId); + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, schemaName); - update(UPDATE_TABLE_STATUS_BY_SCHEMA, COLUMNAR_TABLE_MAPPING_TABLE, params); + update(UPDATE_TABLE_STATUS_AND_VERSION_ID_BY_SCHEMA, COLUMNAR_TABLE_MAPPING_TABLE, params); } public void updateStatusByName(String schemaName, String tableName, String indexName, String status, @@ -319,6 +408,14 @@ public void updateStatusAndExtraByTableId(long tableId, String status, String ex update(UPDATE_TABLE_STATUS_AND_EXTRA_BY_TABLE_ID, COLUMNAR_TABLE_MAPPING_TABLE, params); } + public void updateTypeByTableId(long tableId, String type) { + Map params = new HashMap<>(2); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, type); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, tableId); + + update(UPDATE_TYPE_BY_ID, COLUMNAR_TABLE_MAPPING_TABLE, params); + } + public void UpdateExtraByTableId(long tableId, String extra) { Map params = new HashMap<>(2); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, extra); @@ -327,4 +424,26 @@ public void UpdateExtraByTableId(long tableId, String extra) { update(UPDATE_EXTRA_BY_TABLE_ID, COLUMNAR_TABLE_MAPPING_TABLE, params); } + public List queryPurgeTablesByTso(long tso) { + Map params = new HashMap<>(2); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + return query(SELECT_PURGE_TABLE_BY_TSO, COLUMNAR_TABLE_MAPPING_TABLE, ColumnarTableMappingRecord.class, + params); + } + + public List queryPurgeTablesWhichHavePurgeFilesByTso(long tso) { + Map params = new HashMap<>(2); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + return query(SELECT_PURGE_TABLE_WHICH_HAVE_PURGE_FILE_BY_TSO, COLUMNAR_TABLE_MAPPING_TABLE, + ColumnarTableMappingRecord.class, params); + } + + public List queryPurgeTablesWhichHavePurgeFilesByTsoAndType(long tso, String type) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, type); + return query(SELECT_PURGE_TABLE_WHICH_HAVE_PURGE_FILE_BY_TSO_AND_TYPE, COLUMNAR_TABLE_MAPPING_TABLE, + ColumnarTableMappingRecord.class, params); + } + } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableMappingExtra.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableMappingExtra.java new file mode 100644 index 000000000..ffe4fec00 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableMappingExtra.java @@ -0,0 +1,9 @@ +package com.alibaba.polardbx.gms.metadb.table; + +import lombok.Data; + +@Data +public class ColumnarTableMappingExtra { + // Latest tso generated automatically. + private Long tso; +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableMappingRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableMappingRecord.java index 6a5f21a6b..ad9a81e7a 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableMappingRecord.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableMappingRecord.java @@ -34,6 +34,7 @@ public class ColumnarTableMappingRecord implements SystemTableRecord { public long latestVersionId; public String status; public String extra; + public String type; public ColumnarTableMappingRecord() { } @@ -56,6 +57,7 @@ public ColumnarTableMappingRecord fill(ResultSet rs) throws SQLException { this.latestVersionId = rs.getLong("latest_version_id"); this.status = rs.getString("status"); this.extra = rs.getString("extra"); + this.type = rs.getString("type"); return this; } @@ -68,6 +70,7 @@ public Map buildInsertParams() { MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.latestVersionId); MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.status); MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.extra); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.type); return params; } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableStatus.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableStatus.java index 482c9ebf2..d31014821 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableStatus.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnarTableStatus.java @@ -41,9 +41,13 @@ public enum ColumnarTableStatus { */ ABSENT, /** - * 待删除 + * cn标记了删除,等待列存同步,列存收到后会将DROP 改为PURGE状态 */ - DROP; + DROP, + /** + * 等待后台线程进行purge,真正删除文件。 + */ + PURGE; public static ColumnarTableStatus from(String value) { switch (value.toLowerCase()) { @@ -61,6 +65,8 @@ public static ColumnarTableStatus from(String value) { return ABSENT; case "drop": return DROP; + case "purge": + return PURGE; default: throw new IllegalArgumentException("Illegal ColumnarTableStatus: " + value); } @@ -76,6 +82,7 @@ public IndexStatus toIndexStatus() { return IndexStatus.PUBLIC; case DROP: case ABSENT: + case PURGE: return IndexStatus.ABSENT; case NONE: case ERROR: diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnsAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnsAccessor.java index e943964fe..512a13b7b 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnsAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnsAccessor.java @@ -76,6 +76,9 @@ public class ColumnsAccessor extends AbstractAccessor { private static final String WHERE_SCHEMA_TABLE_COLUMNS = WHERE_SCHEMA_TABLE + " and `column_name` in (%s)"; + private static final String WHERE_SCHEMA_TABLE_COLUMNS_NOT_IN = + WHERE_SCHEMA_TABLE + " and `column_name` not in (%s)"; + private static final String WHERE_SCHEMA_TABLES_COLUMNS = WHERE_SCHEMA_TABLES + " and `column_name` in (%s)"; private static final String WHERE_SCHEMA_TABLES_COLUMNS_STATUS = WHERE_SCHEMA_TABLES_COLUMNS + " and `status` = ?"; @@ -194,6 +197,8 @@ public static final void copyFromOldToNewColumnRecord(ColumnsRecord oldColumnsRe private static final String DELETE_COLUMNS_SPECIFIED = DELETE_COLUMNS + WHERE_SCHEMA_TABLE_COLUMNS; + private static final String DELETE_COLUMNS_NOT_SPECIFIED = DELETE_COLUMNS + WHERE_SCHEMA_TABLE_COLUMNS_NOT_IN; + private static final String SELECT_MAX_COLUMN_POSITION = "select max(ordinal_position) from " + COLUMNS_TABLE + WHERE_SCHEMA_TABLE; @@ -560,6 +565,11 @@ public int delete(String tableSchema, String tableName, List columnNames return delete(String.format(DELETE_COLUMNS_SPECIFIED, concatParams(columnNames)), COLUMNS_TABLE, params); } + public int deleteNotIn(String tableSchema, String tableName, List columnNames) { + Map params = buildParams(tableSchema, tableName, columnNames); + return delete(String.format(DELETE_COLUMNS_NOT_SPECIFIED, concatParams(columnNames)), COLUMNS_TABLE, params); + } + public long queryMaxColumnPosition(String tableSchema, String tableName) { List records = query(SELECT_MAX_COLUMN_POSITION, COLUMNS_TABLE, MaxValueRecord.class, tableSchema, tableName); diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnsInfoSchemaRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnsInfoSchemaRecord.java index a5b86acc9..8515407b3 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnsInfoSchemaRecord.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ColumnsInfoSchemaRecord.java @@ -40,6 +40,7 @@ public class ColumnsInfoSchemaRecord implements SystemTableRecord { public long characterOctetLength; public long numericPrecision; public long numericScale; + public boolean numericScaleNull; public long datetimePrecision; public String characterSetName; public String collationName; @@ -63,6 +64,8 @@ public ColumnsInfoSchemaRecord fill(ResultSet rs) throws SQLException { this.characterOctetLength = rs.getLong("character_octet_length"); this.numericPrecision = rs.getLong("numeric_precision"); this.numericScale = rs.getLong("numeric_scale"); + // record the null state of scale + this.numericScaleNull = rs.wasNull(); this.datetimePrecision = rs.getLong("datetime_precision"); this.characterSetName = rs.getString("character_set_name"); this.collationName = rs.getString("collation_name"); diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/DBStatusRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/DBStatusRecord.java new file mode 100644 index 000000000..9afc12520 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/DBStatusRecord.java @@ -0,0 +1,19 @@ +package com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; + +import java.sql.ResultSet; +import java.sql.SQLException; + +//compatible with show status +public class DBStatusRecord implements SystemTableRecord { + public String variableName; + public String value; + + @Override + public DBStatusRecord fill(ResultSet rs) throws SQLException { + this.variableName = rs.getString("variable_name"); + this.value = rs.getString("value"); + return this; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/DBVariableRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/DBVariableRecord.java new file mode 100644 index 000000000..0bdce0a01 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/DBVariableRecord.java @@ -0,0 +1,18 @@ +package com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class DBVariableRecord implements SystemTableRecord { + public String variableName; + public String value; + + @Override + public DBVariableRecord fill(ResultSet rs) throws SQLException { + this.variableName = rs.getString("variable_name"); + this.value = rs.getString("value"); + return this; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/EnginesRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/EnginesRecord.java new file mode 100644 index 000000000..6cb8fdd14 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/EnginesRecord.java @@ -0,0 +1,27 @@ +package com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class EnginesRecord implements SystemTableRecord { + + public String engine; + public String support; + public String comment; + public String transcations; + public String XA; + public String savePoints; + + @Override + public EnginesRecord fill(ResultSet rs) throws SQLException { + this.engine = rs.getString("engine"); + this.support = rs.getString("support"); + this.comment = rs.getString("comment"); + this.transcations = rs.getString("transactions"); + this.XA = rs.getString("xa"); + this.savePoints = rs.getString("Savepoints"); + return this; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/FileInfoRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/FileInfoRecord.java new file mode 100644 index 000000000..ccc6cf19f --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/FileInfoRecord.java @@ -0,0 +1,132 @@ +package com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; +import lombok.Data; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * 和FilesRecord类似,但是不包含file_meta列,主要是为了查fileInfo,file_meta列太长了 + */ +@Data +public class FileInfoRecord implements SystemTableRecord { + + public long fileId; + public String fileName; + public String fileType; + public String tablespaceName; + public String tableCatalog; + public String tableSchema; + public String tableName; + public String logfileGroupName; + public long logfileGroupNumber; + public String engine; + public String fulltextKeys; + public long deletedRows; + public long updateCount; + public long freeExtents; + public long totalExtents; + public long extentSize; + public long initialSize; + public long maximumSize; + public long autoextendSize; + public String creationTime; + public String lastUpdateTime; + public String lastAccessTime; + public long recoverTime; + public long transactionCounter; + public long version; + public String rowFormat; + public long tableRows; + public long avgRowLength; + public long dataLength; + public long maxDataLength; + public long indexLength; + public long dataFree; + public String createTime; + public String updateTime; + public String checkTime; + public long checksum; + public Long deletedChecksum; + public String status; + public String extra; + public long taskId; + public long lifeCycle; + public String localPath; + public String logicalSchemaName; + /** + * After supporting DDL, logicalTableName here means table id + */ + public String logicalTableName; + public Long commitTs; + public Long removeTs; + public Long fileHash; + public String localPartitionName; + public String partitionName; + public Long schemaTs; + + @Override + public FileInfoRecord fill(ResultSet rs) throws SQLException { + this.fileId = rs.getLong("file_id"); + this.fileName = rs.getString("file_name"); + this.fileType = rs.getString("file_type"); + this.tablespaceName = rs.getString("tablespace_name"); + this.tableCatalog = rs.getString("table_catalog"); + this.tableSchema = rs.getString("table_schema"); + this.tableName = rs.getString("table_name"); + this.logfileGroupName = rs.getString("logfile_group_name"); + this.logfileGroupNumber = rs.getLong("logfile_group_number"); + this.engine = rs.getString("engine"); + this.fulltextKeys = rs.getString("fulltext_keys"); + this.deletedRows = rs.getLong("deleted_rows"); + this.updateCount = rs.getLong("update_count"); + this.freeExtents = rs.getLong("free_extents"); + this.totalExtents = rs.getLong("total_extents"); + this.extentSize = rs.getLong("extent_size"); + this.initialSize = rs.getLong("initial_size"); + this.maximumSize = rs.getLong("maximum_size"); + this.autoextendSize = rs.getLong("autoextend_size"); + this.creationTime = rs.getString("creation_time"); + this.lastUpdateTime = rs.getString("last_update_time"); + this.lastAccessTime = rs.getString("last_access_time"); + this.recoverTime = rs.getLong("recover_time"); + this.transactionCounter = rs.getLong("transaction_counter"); + this.version = rs.getLong("version"); + this.rowFormat = rs.getString("row_format"); + this.tableRows = rs.getLong("table_rows"); + this.avgRowLength = rs.getLong("avg_row_length"); + this.dataLength = rs.getLong("data_length"); + this.maxDataLength = rs.getLong("max_data_length"); + this.indexLength = rs.getLong("index_length"); + this.dataFree = rs.getLong("data_free"); + this.createTime = rs.getString("create_time"); + this.updateTime = rs.getString("update_time"); + this.checkTime = rs.getString("check_time"); + this.checksum = rs.getLong("checksum"); + this.deletedChecksum = rs.getLong("deleted_checksum"); + this.status = rs.getString("status"); + this.extra = rs.getString("extra"); + this.taskId = rs.getLong("task_id"); + this.lifeCycle = rs.getLong("life_cycle"); + this.localPath = rs.getString("local_path"); + this.logicalSchemaName = rs.getString("logical_schema_name"); + this.logicalTableName = rs.getString("logical_table_name"); + this.commitTs = rs.getLong("commit_ts"); + if (rs.wasNull()) { + this.commitTs = null; + } + this.removeTs = rs.getLong("remove_ts"); + if (rs.wasNull()) { + this.removeTs = null; + } + this.fileHash = rs.getLong("file_hash"); + this.localPartitionName = rs.getString("local_partition_name"); + this.partitionName = rs.getString("partition_name"); + this.schemaTs = rs.getLong("schema_ts"); + if (rs.wasNull()) { + this.schemaTs = null; + } + return this; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/FilesAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/FilesAccessor.java index 16d6e3c17..1896065ea 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/FilesAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/FilesAccessor.java @@ -46,6 +46,9 @@ import java.util.Set; import java.util.stream.Collectors; +import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.COLUMNAR_APPENDED_FILES; +import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.COLUMNAR_FILE_MAPPING; + public class FilesAccessor extends AbstractAccessor { private static final Logger LOGGER = LoggerFactory.getLogger("oss"); @@ -53,6 +56,10 @@ public class FilesAccessor extends AbstractAccessor { private static final String COLUMNAR_TABLE_MAPPING_TABLE = wrap(GmsSystemTables.COLUMNAR_TABLE_MAPPING); + private static final String COLUMNAR_FILE_MAPPING_TABLE = wrap(COLUMNAR_FILE_MAPPING); + + private static final String COLUMNAR_APPENDED_FILES_TABLE = wrap(COLUMNAR_APPENDED_FILES); + public static final String PLACE_HOLDER = "?"; public static final String DELIMITER = ","; @@ -113,6 +120,10 @@ public class FilesAccessor extends AbstractAccessor { private static final String SELECT_SIMPLIFIED_FILES = "select `file_name`, `partition_name`, `commit_ts`, `remove_ts`, `schema_ts` from " + FILES_TABLE; + private static final String SELECT_SIMPLIFIED_FILES_WITH = + "select `file_name`, `partition_name`, `commit_ts`, `remove_ts`, `schema_ts`, `checksum`, `deleted_checksum` from " + + FILES_TABLE; + private static final String SELECT_COLUMNAR_FILES_BY_TSO_AND_TABLE_ID = SELECT_SIMPLIFIED_FILES + " force index (`columnar_ts_idx`)" + " where `commit_ts` > ? and `commit_ts` <= ?" @@ -125,6 +136,21 @@ public class FilesAccessor extends AbstractAccessor { + " and `logical_schema_name` = ? and `logical_table_name` = ?" + " and `file_type` = 'TABLE_FILE'"; + private static final String SELECT_COLUMNAR_SNAPSHOT_FILES_BY_TSO_AND_TABLE_ID = SELECT_SIMPLIFIED_FILES + + " where `commit_ts` <= ?" + + " and (`remove_ts` is null or `remove_ts` > ?) " + + " and `logical_schema_name` = ? " + + " and `logical_table_name` = ? " + + " and `file_type` = 'TABLE_FILE'"; + + private static final String SELECT_COLUMNAR_SNAPSHOT_FILES_WITH_CHECKSUM_BY_TSO_AND_TABLE_ID = + SELECT_SIMPLIFIED_FILES_WITH + + " where `commit_ts` <= ?" + + " and (`remove_ts` is null or `remove_ts` > ?) " + + " and `logical_schema_name` = ? " + + " and `logical_table_name` = ? " + + " and `file_type` = 'TABLE_FILE'"; + private static final String SELECT_COLUMNAR_FILES_BY_FILE_NAME = SELECT_COLUMNAR_FILES + " where a.`file_name` = ?"; @@ -151,6 +177,11 @@ public class FilesAccessor extends AbstractAccessor { + " where `logical_schema_name` = ? and `logical_table_name` = ? and `table_schema` = ? and `table_name` = ? and `local_partition_name` = ?" + "and file_name like '%.orc%'"; + private static final String SELECT_FILES_BY_TABLE_NAME = + "select * from " + FILES_TABLE + + " where `logical_schema_name` = ? and `logical_table_name` = ? and `table_schema` = ? and `table_name` = ? " + + "and file_name like '%.orc%' and task_id = ?"; + private static final String SELECT_FOR_ROLLBACK = "select * from " + FILES_TABLE + " where `task_id` = ? and `logical_schema_name` = ? and `logical_table_name` = ?"; @@ -160,6 +191,11 @@ public class FilesAccessor extends AbstractAccessor { " where `task_id` = ? and `logical_schema_name` = ? and `logical_table_name` = ? " + "and `life_cycle` = " + OSSMetaLifeCycle.CREATING.ordinal(); + private static final String SELECT_COMPACTION_ADD_FILES_BY_TSO = + "select * from " + FILES_TABLE + " where " + + "`commit_ts` = ? " + + " and `logical_schema_name` = ? and `logical_table_name` = ? "; + /** * For PK IDX. */ @@ -167,7 +203,7 @@ public class FilesAccessor extends AbstractAccessor { private static final String SELECT_BY_PARTITION_AND_TYPE_ORDER_BY_TSO_WITH_LIMIT = "select * from " + FILES_TABLE + " where `logical_schema_name` = ? and `logical_table_name` = ? and `partition_name` = ? and `file_type` = ? and `engine` = ?" - + " order by `commit_ts` desc, `version` desc limit ?"; + + " order by `version` desc, `commit_ts` desc limit ?"; private static final String SELECT_BY_ID = "select * from " + FILES_TABLE + " where `file_id` = ?"; @@ -209,6 +245,9 @@ public class FilesAccessor extends AbstractAccessor { private static final String DELETE_FILES_BY_SCHEMA_TABLE = "delete from " + FILES_TABLE + " where `logical_schema_name` = ? and `logical_table_name` = ?"; + private static final String DELETE_FILES_BY_SCHEMA_TABLE_LIMIT = + "delete from " + FILES_TABLE + " where `logical_schema_name` = ? and `logical_table_name` = ? limit ?"; + private static final String DELETE_FILES_BY_SCHEMA = "delete from " + FILES_TABLE + " where `logical_schema_name` = ?"; @@ -236,6 +275,14 @@ public class FilesAccessor extends AbstractAccessor { private static final String VALID_BY_FILE_NAME = "update " + FILES_TABLE + " set `life_cycle`= " + OSSMetaLifeCycle.READY.ordinal() + " where `file_name` = ?"; + private static final String UPDATE_REMOVE_TS_BY_REMOVE_TS = "update " + FILES_TABLE + + " set `remove_ts` = null where `logical_schema_name` = ? and `logical_table_name` = ? and remove_ts = ? "; + + private static final String DELETE_COMPACTION_BY_TABLE_TSO = + "delete a,b from " + FILES_TABLE + " as a join " + COLUMNAR_FILE_MAPPING_TABLE + + " as b on a.file_name = b.file_name and a.logical_schema_name = b.logical_schema and a.logical_table_name = b.logical_table " + + " where a.`logical_schema_name` = ? and a.`logical_table_name` = ? and a.`commit_ts` = ? "; + /** * 统计 */ @@ -274,6 +321,50 @@ public class FilesAccessor extends AbstractAccessor { + " end " + " where `file_id` in (%s)"; + /** + * 不包含file_meta列的select + */ + private static final String SELECT_FILE_INFO = + "select `file_id`,`file_name`,`file_type`, `tablespace_name`,`table_catalog`,`table_schema`,`table_name`,`logfile_group_name`,`logfile_group_number`,`engine`,`fulltext_keys`,`deleted_rows`,`update_count`,`free_extents`,`total_extents`,`extent_size`,`initial_size`,`maximum_size`,`autoextend_size`,`creation_time`,`last_update_time`,`last_access_time`,`recover_time`,`transaction_counter`,`version`,`row_format`,`table_rows`,`avg_row_length`,`data_length`,`max_data_length`,`index_length`,`data_free`,`create_time`,`update_time`,`check_time`,`checksum`,`deleted_checksum`,`status`,`extra`,`task_id`,`life_cycle`,`local_path`, `logical_schema_name`, `logical_table_name`, `local_partition_name`,`commit_ts`,`remove_ts`,`file_hash`,`partition_name`,`local_partition_name`,`schema_ts` from " + + FILES_TABLE; + + private static final String SELECT_FILE_INFO_JOIN_TABLE = + "select `file_id`,`file_name`,`file_type`, `tablespace_name`,`table_catalog`,a.`table_schema`,a.`table_name`,`logfile_group_name`,`logfile_group_number`,`engine`,`fulltext_keys`,`deleted_rows`,`update_count`,`free_extents`,`total_extents`,`extent_size`,`initial_size`,`maximum_size`,`autoextend_size`,`creation_time`,`last_update_time`,`last_access_time`,`recover_time`,`transaction_counter`,`version`,`row_format`,`table_rows`,`avg_row_length`,`data_length`,`max_data_length`,`index_length`,`data_free`,`create_time`,`update_time`,`check_time`,`checksum`,`deleted_checksum`,a.`status`,a.`extra`,`task_id`,`life_cycle`,`local_path`, a.`logical_schema_name`, a.`logical_table_name`, `local_partition_name`,`commit_ts`,`remove_ts`,`file_hash`,`partition_name`,`local_partition_name`,`schema_ts` from " + + FILES_TABLE + " a join " + COLUMNAR_TABLE_MAPPING_TABLE + + " b on a.`logical_table_name` = b.`table_id`"; + ; + + private static final String SELECT_FILE_INFO_BY_LOGICAL_SCHEMA_TABLE = SELECT_FILE_INFO + + " where `logical_schema_name` = ? and `logical_table_name` = ? "; + + private static final String SELECT_FILE_INFO_BY_LOGICAL_SCHEMA_TABLE_TSO = SELECT_FILE_INFO + + " where `logical_schema_name` = ? and `logical_table_name` = ? and `remove_ts` is not null and `remove_ts` < ? "; + + private static final String SELECT_FILE_INFO_BY_START_TSO_AND_END_TSO = SELECT_FILE_INFO_JOIN_TABLE + + " where `commit_ts` <= ? and ( `remove_ts` is null or `remove_ts` >= ? ) and RIGHT(`file_name`, 3) in ('orc', 'sst');"; + + private static final String DELETE_TWO_BY_LOGICAL_SCHEMA_TABLE_TSO = + "delete a,b from " + FILES_TABLE + " as a join " + COLUMNAR_FILE_MAPPING_TABLE + + " as b on a.file_name = b.file_name and a.logical_schema_name = b.logical_schema and a.logical_table_name = b.logical_table " + + " where a.`logical_schema_name` = ? and a.`logical_table_name` = ? and a.`remove_ts` is not null and a.`remove_ts` < ? "; + + private static final String DELETE_ORC_BY_TSO = + "delete a,b from " + FILES_TABLE + " as a join " + COLUMNAR_FILE_MAPPING_TABLE + + " as b on a.file_name = b.file_name and a.logical_schema_name = b.logical_schema and a.logical_table_name = b.logical_table " + + " where a.`commit_ts` > ? and RIGHT(a.`file_name`, 3) = 'orc' "; + + private static final String DELETE_THREE_FILE_META_BY_TSO = + "delete a,b,c from " + FILES_TABLE + " as a join " + COLUMNAR_FILE_MAPPING_TABLE + + " as b on a.file_name = b.file_name join " + COLUMNAR_APPENDED_FILES_TABLE + + " as c on a.file_name = c.file_name" + + " where a.`commit_ts` > ? and RIGHT(a.file_name, 3) in ('csv','del','set') "; + + private static final String UPDATE_COLUMNAR_REMOVE_TS_BY_TSO = + "update " + FILES_TABLE + " as a join " + COLUMNAR_FILE_MAPPING_TABLE + + " as b on a.file_name = b.file_name and a.logical_schema_name = b.logical_schema and a.logical_table_name = b.logical_table " + + " set a.`remove_ts` = null " + + " where a.`remove_ts` > ? "; + public int[] insert(List records, String tableSchema, String tableName) { List> paramsBatch = new ArrayList<>(records.size()); for (FilesRecord record : records) { @@ -393,6 +484,20 @@ public List queryByLogicalSchemaTable(String logicalSchemaName, Str logicalTableName); } + public List queryFileInfoByLogicalSchemaTable(String logicalSchemaName, String logicalTableName) { + return query(SELECT_FILE_INFO_BY_LOGICAL_SCHEMA_TABLE, FILES_TABLE, FileInfoRecord.class, logicalSchemaName, + logicalTableName); + } + + public List queryFileInfoByLogicalSchemaTableTso(String logicalSchemaName, String logicalTableName, + long tso) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, logicalSchemaName); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, logicalTableName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, tso); + return query(SELECT_FILE_INFO_BY_LOGICAL_SCHEMA_TABLE_TSO, FILES_TABLE, FileInfoRecord.class, params); + } + public List queryTableFormatByLogicalSchemaTable(String logicalSchemaName, String logicalTableName) { return query(SELECT_TABLE_FORMAT_FILE_BY_LOGICAL_SCHEMA_TABLE, FILES_TABLE, FilesRecord.class, logicalSchemaName, logicalTableName); @@ -432,6 +537,23 @@ public List queryByLocalPartition(String logicalTableSchema, String } } + public List queryByPhyTableName(String logicalTableSchema, String logicalTableName, + String phyTableSchema, String phyTableName, Long taskId) { + try { + Map params + = MetaDbUtil.buildStringParameters( + new String[] {logicalTableSchema, logicalTableName, phyTableSchema, phyTableName}); + MetaDbUtil.setParameter(5, params, ParameterMethod.setLong, taskId); + + return MetaDbUtil.query(SELECT_FILES_BY_TABLE_NAME, params, FilesRecord.class, connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + FILES_TABLE, + e.getMessage()); + } + } + public List queryByTso(long tso, String logicalSchema, String logicalTable, String partName) { try { Map params = new HashMap<>(8); @@ -478,6 +600,47 @@ public List queryColumnarDeltaFilesByTsoAndTableId(long t } } + public List queryColumnarSnapshotFilesByTsoAndTableId(long tso, String logicalSchema, + String tableId) { + try { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, tso); + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, logicalSchema); + MetaDbUtil.setParameter(4, params, ParameterMethod.setString, tableId); + DdlMetaLogUtil.logSql(SELECT_COLUMNAR_SNAPSHOT_FILES_BY_TSO_AND_TABLE_ID, params); + return MetaDbUtil.query(SELECT_COLUMNAR_SNAPSHOT_FILES_BY_TSO_AND_TABLE_ID, params, + FilesRecordSimplified.class, + connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + FILES_TABLE, + e.getMessage()); + } + } + + public List querySnapshotWithChecksumByTsoAndTableId(long tso, + String logicalSchema, + String tableId) { + try { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, tso); + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, logicalSchema); + MetaDbUtil.setParameter(4, params, ParameterMethod.setString, tableId); + DdlMetaLogUtil.logSql(SELECT_COLUMNAR_SNAPSHOT_FILES_WITH_CHECKSUM_BY_TSO_AND_TABLE_ID, params); + return MetaDbUtil.query(SELECT_COLUMNAR_SNAPSHOT_FILES_WITH_CHECKSUM_BY_TSO_AND_TABLE_ID, params, + FilesRecordSimplifiedWithChecksum.class, + connection); + } catch (Exception e) { + LOGGER.error("Failed to query the system table " + FILES_TABLE, e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + FILES_TABLE, + e.getMessage()); + } + } + /** * Query all files record in schema which are visible in given tso. */ @@ -585,6 +748,20 @@ public List queryByIdAndSchemaAndTable(Long taskId, String logicalS } } + public List queryCompactionFileByTsoAndTable(long commitTso, String logicalSchemaName, + String logicalTableName) { + Map params = new HashMap<>(3); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, commitTso); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, logicalSchemaName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, logicalTableName); + try { + DdlMetaLogUtil.logSql(SELECT_COMPACTION_ADD_FILES_BY_TSO, params); + return MetaDbUtil.query(SELECT_COMPACTION_ADD_FILES_BY_TSO, params, FilesRecord.class, connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + public List queryByPartitionAndTypeOrderByCommitTsDesc( String logicalSchemaName, String logicalTableName, String partitionName, String fileType, String engine, int limit) { @@ -716,6 +893,20 @@ public int deleteByTableAndType( } } + public List queryORCAndSSTFileInfoByTso(long startTso, long endTso) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, endTso); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, startTso); + + try { + DdlMetaLogUtil.logSql(SELECT_FILE_INFO_BY_START_TSO_AND_END_TSO, params); + return MetaDbUtil.query(SELECT_FILE_INFO_BY_START_TSO_AND_END_TSO, params, FileInfoRecord.class, + connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + /** * @return checksums of orc files which contains no deleted data. */ @@ -797,13 +988,26 @@ public void delete(Long taskId, String logicalSchemaName, String logicalTableNam } } - public void delete(String schemaName, String tableName) { + public int delete(String schemaName, String tableName) { Map params = new HashMap<>(2); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); try { DdlMetaLogUtil.logSql(DELETE_FILES_BY_SCHEMA_TABLE, params); - MetaDbUtil.delete(DELETE_FILES_BY_SCHEMA_TABLE, params, connection); + return MetaDbUtil.delete(DELETE_FILES_BY_SCHEMA_TABLE, params, connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + + public int deleteLimit(String schemaName, String tableName, long limit) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, limit); + try { + DdlMetaLogUtil.logSql(DELETE_FILES_BY_SCHEMA_TABLE_LIMIT, params); + return MetaDbUtil.delete(DELETE_FILES_BY_SCHEMA_TABLE_LIMIT, params, connection); } catch (Exception e) { throw GeneralUtil.nestedException(e); } @@ -831,6 +1035,78 @@ public void delete(long fileId) { } } + public int deleteTwoMetaByTableAndTso(String schemaName, String tableName, long tso) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, tso); + try { + DdlMetaLogUtil.logSql(DELETE_TWO_BY_LOGICAL_SCHEMA_TABLE_TSO, params); + return MetaDbUtil.delete(DELETE_TWO_BY_LOGICAL_SCHEMA_TABLE_TSO, params, connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + + public int deleteOrcMetaByCommitTso(long tso) { + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + try { + DdlMetaLogUtil.logSql(DELETE_ORC_BY_TSO, params); + return MetaDbUtil.delete(DELETE_ORC_BY_TSO, params, connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + + public int deleteThreeMetaByCommitTso(long tso) { + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + try { + DdlMetaLogUtil.logSql(DELETE_THREE_FILE_META_BY_TSO, params); + return MetaDbUtil.delete(DELETE_THREE_FILE_META_BY_TSO, params, connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + + public int deleteCompactionFileByCommitTso(String schemaName, String tableName, long tso) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, tso); + try { + DdlMetaLogUtil.logSql(DELETE_COMPACTION_BY_TABLE_TSO, params); + return MetaDbUtil.delete(DELETE_COMPACTION_BY_TABLE_TSO, params, connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + + public int updateRemoveTsByTso(long tso) { + Map params = new HashMap<>(1); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + try { + DdlMetaLogUtil.logSql(UPDATE_COLUMNAR_REMOVE_TS_BY_TSO, params); + return MetaDbUtil.update(UPDATE_COLUMNAR_REMOVE_TS_BY_TSO, params, connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + + public int updateCompactionRemoveTsByTso(String schemaName, String tableName, long tso) { + Map params = new HashMap<>(4); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, schemaName); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + MetaDbUtil.setParameter(1, params, ParameterMethod.setLong, tso); + try { + DdlMetaLogUtil.logSql(UPDATE_REMOVE_TS_BY_REMOVE_TS, params); + return MetaDbUtil.update(UPDATE_REMOVE_TS_BY_REMOVE_TS, params, connection); + } catch (Exception e) { + throw GeneralUtil.nestedException(e); + } + } + public void rename(String schemaName, String tableName, String newTableName) { Map params = new HashMap<>(2); MetaDbUtil.setParameter(1, params, ParameterMethod.setString, newTableName); @@ -838,7 +1114,7 @@ public void rename(String schemaName, String tableName, String newTableName) { MetaDbUtil.setParameter(3, params, ParameterMethod.setString, tableName); try { DdlMetaLogUtil.logSql(RENAME_FILES, params); - MetaDbUtil.delete(RENAME_FILES, params, connection); + MetaDbUtil.update(RENAME_FILES, params, connection); } catch (Exception e) { throw GeneralUtil.nestedException(e); } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/FilesRecordSimplifiedWithChecksum.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/FilesRecordSimplifiedWithChecksum.java new file mode 100644 index 000000000..3901daaf3 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/FilesRecordSimplifiedWithChecksum.java @@ -0,0 +1,17 @@ +package com.alibaba.polardbx.gms.metadb.table; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class FilesRecordSimplifiedWithChecksum extends FilesRecordSimplified { + public Long checksum; + public Long deletedChecksum; + + @Override + public FilesRecordSimplified fill(ResultSet rs) throws SQLException { + super.fill(rs); + this.checksum = rs.getLong("checksum"); + this.deletedChecksum = rs.getLong("deleted_checksum"); + return this; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/IndexesAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/IndexesAccessor.java index f856799a7..cd35ebd33 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/IndexesAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/IndexesAccessor.java @@ -38,7 +38,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; public class IndexesAccessor extends AbstractAccessor { @@ -207,6 +206,10 @@ public class IndexesAccessor extends AbstractAccessor { UPDATE_INDEXES + "`index_name` = ?, `index_table_name` = `index_name`" + WHERE_SCHEMA + " and `index_name` = ?"; + private static final String UPDATE_CCI_TABLE_NAME = + UPDATE_INDEXES + "`index_table_name` = ?" + + WHERE_SCHEMA + " and `index_name` = ?"; + private static final String UPDATE_LOCAL_INDEXES_RENAME = UPDATE_INDEXES + "`table_name` = ?" + WHERE_SCHEMA_TABLE + " and `index_location` = 0"; @@ -605,6 +608,10 @@ public void renameGsiIndexes(String tableSchema, String indexName, String newInd update(UPDATE_INDEXES_TABLE_NAME, INDEXES_TABLE, tableSchema, indexName, newIndexName); } + public void renameCciIndex(String tableSchema, String newIndexName) { + update(UPDATE_CCI_TABLE_NAME, INDEXES_TABLE, tableSchema, newIndexName, newIndexName); + } + public int renameLocalIndexes(String tableSchema, String tableName, String newTableName) { return update(UPDATE_LOCAL_INDEXES_RENAME, INDEXES_TABLE, tableSchema, tableName, newTableName); } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ShowTablesSchemaRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ShowTablesSchemaRecord.java new file mode 100644 index 000000000..a98b225f2 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ShowTablesSchemaRecord.java @@ -0,0 +1,117 @@ +package com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; + +/** + * Data of information_schema.tables, but only for SHOW DAL + */ +public class ShowTablesSchemaRecord implements SystemTableRecord { + + public long id; + public String tableSchema; + public String tableName; + public String tableType; + public String engine; + public long version; + public String rowFormat; + public long tableRows; + public long avgRowLength; + public long dataLength; + public long maxDataLength; + public long indexLength; + public long dataFree; + public long autoIncrement; + public String createTime; + public String updateTime; + public String checkTime; + public String tableCollation; + public long checkSum; + public String createOptions; + public String tableComment; + + @Override + public ShowTablesSchemaRecord fill(ResultSet rs) throws SQLException { + try { + this.id = rs.getLong("id"); + } catch (Exception ignored) { + } + this.tableSchema = rs.getString("table_schema"); + this.tableName = rs.getString("table_name"); + this.tableType = rs.getString("table_type"); + this.engine = rs.getString("engine"); + this.version = rs.getLong("version"); + this.rowFormat = rs.getString("row_format"); + this.tableRows = rs.getLong("table_rows"); + this.avgRowLength = rs.getLong("avg_row_length"); + this.dataLength = rs.getLong("data_length"); + this.maxDataLength = rs.getLong("max_data_length"); + this.indexLength = rs.getLong("index_length"); + this.dataFree = rs.getLong("data_free"); + this.autoIncrement = rs.getLong("auto_increment"); + this.createTime = rs.getString("create_time"); + this.updateTime = rs.getString("update_time"); + this.checkTime = rs.getString("check_time"); + this.tableCollation = rs.getString("table_collation"); + this.checkSum = rs.getLong("checksum"); + this.createOptions = rs.getString("create_options"); + this.tableComment = rs.getString("table_comment"); + return this; + } + + private void setCommonParams(Map params, int index) { + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.tableName); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.tableType); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.engine); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.version); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.rowFormat); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.tableRows); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.avgRowLength); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.dataLength); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.maxDataLength); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.indexLength); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.dataFree); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.autoIncrement); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.createTime); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.updateTime); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.checkTime); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.tableCollation); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setLong, this.checkSum); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.createOptions); + MetaDbUtil.setParameter(++index, params, ParameterMethod.setString, this.tableComment); + } + + @Override + public String toString() { + return "ShowTablesSchemaRecord{" + + "id=" + id + + ", tableSchema='" + tableSchema + '\'' + + ", tableName='" + tableName + '\'' + + ", tableType='" + tableType + '\'' + + ", engine='" + engine + '\'' + + ", version=" + version + + ", rowFormat='" + rowFormat + '\'' + + ", tableRows=" + tableRows + + ", avgRowLength=" + avgRowLength + + ", dataLength=" + dataLength + + ", maxDataLength=" + maxDataLength + + ", indexLength=" + indexLength + + ", dataFree=" + dataFree + + ", autoIncrement=" + autoIncrement + + ", createTime=" + createTime + '\'' + + ", updateTime=" + updateTime + '\'' + + ", checkTime=" + checkTime + '\'' + + ", tableCollation='" + tableCollation + '\'' + + ", checkSum=" + checkSum + + ", createOptions='" + createOptions + '\'' + + ", tableComment='" + tableComment + '\'' + + '}'; + } + +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/TableInfoManager.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/TableInfoManager.java index 0ae06cd80..4364d12e3 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/TableInfoManager.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/TableInfoManager.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.alibaba.polardbx.gms.metadb.table; import com.alibaba.polardbx.common.Engine; @@ -63,6 +62,8 @@ import com.alibaba.polardbx.gms.tablegroup.TableGroupRecord; import com.alibaba.polardbx.gms.tablegroup.TableGroupUtils; import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.gms.ttl.TtlInfoAccessor; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; import com.alibaba.polardbx.gms.util.DdlMetaLogUtil; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.gms.util.TableGroupNameUtil; @@ -93,6 +94,7 @@ import java.util.stream.Collectors; import static com.alibaba.polardbx.gms.tablegroup.TableGroupRecord.TG_TYPE_PARTITION_TBL_TG; +import static java.lang.String.CASE_INSENSITIVE_ORDER; public class TableInfoManager extends AbstractAccessor { @@ -116,12 +118,15 @@ public class TableInfoManager extends AbstractAccessor { private final ColumnEvolutionAccessor columnEvolutionAccessor; private final TableLocalPartitionAccessor localPartitionAccessor; + private final TtlInfoAccessor ttlInfoAccessor; private final ScheduledJobsAccessor scheduledJobsAccessor; private final FiredScheduledJobsAccessor firedScheduledJobsAccessor; private final JoinGroupTableDetailAccessor joinGroupTableDetailAccessor; private final ColumnarTableMappingAccessor columnarTableMappingAccessor; private final ColumnarColumnEvolutionAccessor columnarColumnEvolutionAccessor; private final ColumnarTableEvolutionAccessor columnarTableEvolutionAccessor; + private final ColumnarPartitionEvolutionAccessor columnarPartitionEvolutionAccessor; + private final ColumnarCheckpointsAccessor columnarCheckpointsAccessor; public TableInfoManager() { schemataAccessor = new SchemataAccessor(); @@ -138,12 +143,15 @@ public TableInfoManager() { columnMappingAccessor = new ColumnMappingAccessor(); columnEvolutionAccessor = new ColumnEvolutionAccessor(); localPartitionAccessor = new TableLocalPartitionAccessor(); + ttlInfoAccessor = new TtlInfoAccessor(); scheduledJobsAccessor = new ScheduledJobsAccessor(); firedScheduledJobsAccessor = new FiredScheduledJobsAccessor(); joinGroupTableDetailAccessor = new JoinGroupTableDetailAccessor(); columnarTableMappingAccessor = new ColumnarTableMappingAccessor(); columnarTableEvolutionAccessor = new ColumnarTableEvolutionAccessor(); columnarColumnEvolutionAccessor = new ColumnarColumnEvolutionAccessor(); + columnarPartitionEvolutionAccessor = new ColumnarPartitionEvolutionAccessor(); + columnarCheckpointsAccessor = new ColumnarCheckpointsAccessor(); foreignAccessor = new ForeignAccessor(); foreignColsAccessor = new ForeignColsAccessor(); } @@ -301,12 +309,15 @@ public void setConnection(Connection connection) { columnMappingAccessor.setConnection(connection); columnEvolutionAccessor.setConnection(connection); localPartitionAccessor.setConnection(connection); + ttlInfoAccessor.setConnection(connection); scheduledJobsAccessor.setConnection(connection); firedScheduledJobsAccessor.setConnection(connection); joinGroupTableDetailAccessor.setConnection(connection); columnarTableMappingAccessor.setConnection(connection); columnarTableEvolutionAccessor.setConnection(connection); columnarColumnEvolutionAccessor.setConnection(connection); + columnarPartitionEvolutionAccessor.setConnection(connection); + columnarCheckpointsAccessor.setConnection(connection); foreignAccessor.setConnection(connection); foreignColsAccessor.setConnection(connection); } @@ -433,7 +444,7 @@ public List queryVisibleColumns(String tableSchema, String tableN } public Map> queryVisibleColumns(String tableSchema) { - Map> visibleRecords = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map> visibleRecords = new TreeMap<>(CASE_INSENSITIVE_ORDER); List records = queryColumns(tableSchema); for (ColumnsRecord record : records) { if (record.status != ColumnStatus.ABSENT.getValue()) { @@ -456,7 +467,7 @@ public List queryColumns(String tableSchema, String tableName) { } public Map> queryColumnMappings(String tableSchema) { - Map> visibleRecords = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map> visibleRecords = new TreeMap<>(CASE_INSENSITIVE_ORDER); List records = columnMappingAccessor.querySchema(tableSchema); for (ColumnMappingRecord record : records) { visibleRecords.computeIfAbsent(record.tableName, k -> new ArrayList<>()).add(record); @@ -480,7 +491,7 @@ public List queryVisibleIndexes(String tableSchema, String tableN } public Map> queryVisibleIndexes(String tableSchema) { - Map> visibleRecords = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map> visibleRecords = new TreeMap<>(CASE_INSENSITIVE_ORDER); List records = queryIndexes(tableSchema); for (IndexesRecord record : records) { if (record.indexStatus == IndexStatus.PUBLIC.getValue()) { @@ -499,7 +510,7 @@ public List queryIndexes(String tableSchema, String tableName) { } public Map> queryReferencedForeignKeys(String tableSchema) { - Map> allReferencedFkRecords = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map> allReferencedFkRecords = new TreeMap<>(CASE_INSENSITIVE_ORDER); List records = foreignAccessor.queryReferencedForeignKeys(tableSchema); for (ForeignRecord record : records) { allReferencedFkRecords.computeIfAbsent(record.refTableName, k -> new ArrayList<>()).add(record); @@ -512,7 +523,7 @@ public List queryReferencedForeignKeys(String tableSchema, String } public Map> queryForeignKeys(String tableSchema) { - Map> allFkRecords = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map> allFkRecords = new TreeMap<>(CASE_INSENSITIVE_ORDER); List records = foreignAccessor.queryForeignKeys(tableSchema); for (ForeignRecord record : records) { allFkRecords.computeIfAbsent(record.tableName, k -> new ArrayList<>()).add(record); @@ -660,6 +671,16 @@ public void repartitionCutOver(String tableSchema, String originName, String new indexesAccessor.renameLocalIndexes(tableSchema, originName, newName); } + public int alterTableExtNameAndIndexes(String tableSchema, String originName, String newName) { + indexesAccessor.renameLocalIndexes(tableSchema, originName, newName); + return tablesExtAccessor.alterName(tableSchema, originName, newName); + } + + public void truncateTableCutOver(String tableSchema, String originName, String newName) { + tablePartitionAccessor.rename(tableSchema, originName, newName); + indexesAccessor.renameLocalIndexes(tableSchema, originName, newName); + } + public void alterPartitionCountCutOver(String tableSchema, String originIndexTableName, String newIndexTableName) { indexesAccessor.cutOverGlobalIndex(tableSchema, originIndexTableName, newIndexTableName); } @@ -720,6 +741,7 @@ public ColumnarTableMappingRecord addCreateCciSchemaEvolutionMeta(String schemaN long ddlJobId) { final List columnRecords = columnsAccessor.query(schemaName, columnarTableName); + final List partitionRecords = queryTablePartitions(schemaName, columnarTableName, false); return addCreateCciSchemaEvolutionMeta(schemaName, primaryTableName, @@ -727,7 +749,8 @@ public ColumnarTableMappingRecord addCreateCciSchemaEvolutionMeta(String schemaN options, versionId, ddlJobId, - columnRecords); + columnRecords, + partitionRecords); } public ColumnarTableMappingRecord addCreateCciSchemaEvolutionMeta(String schemaName, @@ -736,7 +759,8 @@ public ColumnarTableMappingRecord addCreateCciSchemaEvolutionMeta(String schemaN Map options, long versionId, long ddlJobId, - List columnsRecords) { + List columnsRecords, + List partitionRecords) { final ColumnarTableMappingRecord tableMappingRecord = addColumnarTableMappingRecord(schemaName, primaryTableName, columnarTableName, @@ -747,6 +771,9 @@ public ColumnarTableMappingRecord addCreateCciSchemaEvolutionMeta(String schemaN // Insert column evolution records addCciColumnEvolutionRecords(columnsRecords, tableId, versionId, ddlJobId); + // Insert partition evolution records + addCciPartitionEvolutionRecords(partitionRecords, tableId, versionId, ddlJobId); + // Insert table evolution record addCreateCciTableEvolutionRecord(tableMappingRecord, options, versionId, ddlJobId, DdlType.CREATE_INDEX); @@ -782,12 +809,26 @@ public void addCciColumnEvolutionRecords(List columnsRecords, lon columnarColumnEvolutionAccessor.updateFieldIdAsId(tableId, versionId); } + public void addCciPartitionEvolutionRecords(List partitionRecords, long tableId, + long versionId, + long ddlJobId) { + // Insert column evolution records + List partitionEvolutionRecords = new ArrayList<>(partitionRecords.size()); + for (TablePartitionRecord partitionRecord : partitionRecords) { + partitionEvolutionRecords.add( + new ColumnarPartitionEvolutionRecord(tableId, partitionRecord.partName, + versionId, ddlJobId, partitionRecord, ColumnarPartitionStatus.PUBLIC.getValue())); + } + columnarPartitionEvolutionAccessor.insert(partitionEvolutionRecords); + columnarPartitionEvolutionAccessor.updatePartitionIdAsId(tableId, versionId); + } + public void addCciTableEvolutionRecord(String schemaName, String primaryTableName, String columnarTableName, Map options, long tableId, long versionId, long ddlJobId, DdlType ddlType, - List columns) { + List columns, List partitions) { final ColumnarTableEvolutionRecord columnarTableEvolutionRecord = new ColumnarTableEvolutionRecord( versionId, tableId, @@ -798,13 +839,15 @@ public void addCciTableEvolutionRecord(String schemaName, String primaryTableNam ddlJobId, ddlType.name(), Long.MAX_VALUE, - columns); + columns, + partitions); columnarTableEvolutionAccessor.insert(ImmutableList.of(columnarTableEvolutionRecord)); } public void addCciTableEvolutionRecord(ColumnarTableMappingRecord tableMappingRecord, long versionId, long ddlJobId, - DdlType ddlType, List columns, Map options) { + DdlType ddlType, List columns, List partitions, + Map options) { addCciTableEvolutionRecord(tableMappingRecord.tableSchema, tableMappingRecord.tableName, tableMappingRecord.indexName, @@ -813,7 +856,8 @@ public void addCciTableEvolutionRecord(ColumnarTableMappingRecord tableMappingRe versionId, ddlJobId, ddlType, - columns); + columns, + partitions); } /** @@ -831,8 +875,11 @@ private void addCreateCciTableEvolutionRecord(ColumnarTableMappingRecord tableMa final List columnEvolutionRecords = columnarColumnEvolutionAccessor.queryTableIdVersionIdOrderById(tableId, versionId); final List columns = columnEvolutionRecords.stream().map(r -> r.id).collect(Collectors.toList()); + final List partitionEvolutionRecords = + columnarPartitionEvolutionAccessor.queryTableIdVersionIdOrderById(tableId, versionId); + final List partitions = partitionEvolutionRecords.stream().map(r -> r.id).collect(Collectors.toList()); - addCciTableEvolutionRecord(tableMappingRecord, versionId, ddlJobId, ddlType, columns, options); + addCciTableEvolutionRecord(tableMappingRecord, versionId, ddlJobId, ddlType, columns, partitions, options); } /** @@ -855,7 +902,7 @@ public ColumnarTableMappingRecord addCciTableEvolutionRecordWithLatestColumns(St queryColumnarTableEvolution(tableId, latestVersionId).get(0); addCciTableEvolutionRecord(tableMappingRecord, versionId, ddlJobId, ddlType, - latestTableEvolution.columns, latestTableEvolution.options); + latestTableEvolution.columns, latestTableEvolution.partitions, latestTableEvolution.options); return tableMappingRecord; } @@ -875,7 +922,7 @@ public ColumnarTableMappingRecord addCciTableEvolutionRecordWithSpecifiedColumns queryColumnarTableEvolution(tableId, fromVersionId).get(0); addCciTableEvolutionRecord(fromTableMappingRecord, versionId, ddlJobId, ddlType, - fromTableEvolution.columns, fromTableEvolution.options); + fromTableEvolution.columns, fromTableEvolution.partitions, fromTableEvolution.options); return fromTableMappingRecord; } @@ -938,109 +985,108 @@ public Set> queryCci(String schemaName, String primaryTableNa Set> indexes = columnarTableMappingRecords.stream() .filter(record -> !record.status.equals(ColumnarTableStatus.DROP.name())) + .filter(record -> !record.status.equals(ColumnarTableStatus.PURGE.name())) .map(record -> new Pair<>(record.tableId, record.indexName)) .collect(Collectors.toSet()); return indexes; } - public void alterColumnarTableColumns(String schemaName, String primaryTableName, Set> indexes, - long versionId, long ddlJobId, DdlType ddlType, - List> changeColumns) { + public List queryColumnarMappingBySchemaTable(String schemaName, + String primaryTableName) { + return columnarTableMappingAccessor.querySchemaTable(schemaName, primaryTableName); + } + + public void renameColumnarTable(String schemaName, String primaryTableName, Set> indexes, + List> renamedIndexes, long versionId, long ddlJobId) { + TreeMap old2NewIndexNameMap = renamedIndexes.stream().collect(Collectors.toMap(Pair::getValue, + Pair::getKey, (before, after) -> after, () -> new TreeMap<>(CASE_INSENSITIVE_ORDER))); + for (Pair index : indexes) { Long tableId = index.getKey(); String indexName = index.getValue(); + if (!old2NewIndexNameMap.containsKey(indexName)) { + continue; + } + String newIndexName = old2NewIndexNameMap.get(indexName); + final ColumnarTableMappingRecord tableMapping = columnarTableMappingAccessor.querySchemaTableIndex(schemaName, primaryTableName, indexName).get(0); - if (tableMapping.status.equals(ColumnarTableStatus.DROP.name())) { + if (tableMapping.status.equals(ColumnarTableStatus.DROP.name()) || + tableMapping.status.equals(ColumnarTableStatus.PURGE.name())) { continue; } long latestVersionId = tableMapping.latestVersionId; - - // Fill primary table column meta into columns system table - List columnsRecords = columnsAccessor.query(schemaName, primaryTableName); - - // Insert column evolution records ColumnarTableEvolutionRecord columnarTableEvolutionRecord = columnarTableEvolutionAccessor.queryByVersionIdLatest(latestVersionId).get(0); - List columns = - reorderColumns(columnarTableEvolutionRecord, columnsRecords, versionId, ddlJobId, - indexName, changeColumns); - columnarTableEvolutionRecord = - new ColumnarTableEvolutionRecord(versionId, tableId, schemaName, primaryTableName, indexName, - columnarTableEvolutionRecord.options, - ddlJobId, ddlType.name(), Long.MAX_VALUE, columns); + new ColumnarTableEvolutionRecord(versionId, tableId, schemaName, primaryTableName, newIndexName, + columnarTableEvolutionRecord.options, ddlJobId, DdlType.ALTER_TABLE.name(), + Long.MAX_VALUE, columnarTableEvolutionRecord.columns, columnarTableEvolutionRecord.partitions); columnarTableEvolutionAccessor.insert(ImmutableList.of(columnarTableEvolutionRecord)); + columnarTableMappingAccessor.updateIndexNameId(newIndexName, latestVersionId, tableId); columnarTableMappingAccessor.updateVersionId(versionId, tableId); } } - public void dropColumnarTableColumns(String schemaName, String primaryTableName, Set> indexes, - List droppedColumns, long versionId, long ddlJobId) { - if (GeneralUtil.isEmpty(droppedColumns)) { - return; - } - + public void alterColumnarTableColumns(String schemaName, String primaryTableName, Set> indexes, + long versionId, long ddlJobId, DdlType ddlType, + List> changeColumns, List droppedColumns) { for (Pair index : indexes) { Long tableId = index.getKey(); String indexName = index.getValue(); final ColumnarTableMappingRecord tableMapping = columnarTableMappingAccessor.querySchemaTableIndex(schemaName, primaryTableName, indexName).get(0); - if (tableMapping.status.equals(ColumnarTableStatus.DROP.name())) { + if (tableMapping.status.equals(ColumnarTableStatus.DROP.name()) || + tableMapping.status.equals(ColumnarTableStatus.PURGE.name())) { continue; } long latestVersionId = tableMapping.latestVersionId; - columnsAccessor.delete(schemaName, indexName, droppedColumns); - List columnarColumnEvolutionRecords = columnarColumnEvolutionAccessor.queryTableIdAndNotInStatus(tableId, ColumnStatus.ABSENT.getValue()); - for (ColumnarColumnEvolutionRecord columnarColumnEvolutionRecord : columnarColumnEvolutionRecords) { - if (droppedColumns.contains(columnarColumnEvolutionRecord.columnName)) { + if (GeneralUtil.isNotEmpty(droppedColumns)) { + for (ColumnarColumnEvolutionRecord columnarColumnEvolutionRecord : columnarColumnEvolutionRecords) { + if (droppedColumns.contains(columnarColumnEvolutionRecord.columnName)) { - columnarColumnEvolutionRecord.columnsRecord.status = ColumnStatus.ABSENT.getValue(); - ColumnarColumnEvolutionRecord columnEvolutionRecord = - new ColumnarColumnEvolutionRecord(tableId, columnarColumnEvolutionRecord.fieldId, - columnarColumnEvolutionRecord.columnName, - versionId, ddlJobId, columnarColumnEvolutionRecord.columnsRecord); - columnarColumnEvolutionAccessor.insert(ImmutableList.of(columnEvolutionRecord)); + columnarColumnEvolutionRecord.columnsRecord.status = ColumnStatus.ABSENT.getValue(); + ColumnarColumnEvolutionRecord columnEvolutionRecord = + new ColumnarColumnEvolutionRecord(tableId, columnarColumnEvolutionRecord.fieldId, + columnarColumnEvolutionRecord.columnName, + versionId, ddlJobId, columnarColumnEvolutionRecord.columnsRecord); + columnarColumnEvolutionAccessor.insert(ImmutableList.of(columnEvolutionRecord)); + } } } + // Fill primary table column meta into columns system table List columnsRecords = columnsAccessor.query(schemaName, primaryTableName); + // Insert column evolution records ColumnarTableEvolutionRecord columnarTableEvolutionRecord = columnarTableEvolutionAccessor.queryByVersionIdLatest(latestVersionId).get(0); List columns = reorderColumns(columnarTableEvolutionRecord, columnsRecords, versionId, ddlJobId, - indexName, new ArrayList<>()); + indexName, changeColumns, droppedColumns); columnarTableEvolutionRecord = new ColumnarTableEvolutionRecord(versionId, tableId, schemaName, primaryTableName, indexName, columnarTableEvolutionRecord.options, - ddlJobId, DdlType.ALTER_TABLE_DROP_COLUMN.name(), Long.MAX_VALUE, columns); + ddlJobId, ddlType.name(), Long.MAX_VALUE, columns, columnarTableEvolutionRecord.partitions); columnarTableEvolutionAccessor.insert(ImmutableList.of(columnarTableEvolutionRecord)); - columnarTableMappingAccessor.updateVersionId(versionId, tableId); } } public void changeColumnarIndexTableColumns(List indexTableNames, String schemaName, - String primaryTableName, List> changeColumns) { - // for alter table change column -> rename column - Map changeColumnsMap = new HashMap<>(); - for (Pair changeColumn : changeColumns) { - // - changeColumnsMap.put(changeColumn.getKey(), changeColumn.getValue()); - } - + String primaryTableName) { for (String indexTableName : indexTableNames) { final ColumnarTableMappingRecord tableMapping = columnarTableMappingAccessor.querySchemaTableIndex(schemaName, primaryTableName, indexTableName).get(0); - if (tableMapping.status.equals(ColumnarTableStatus.DROP.name())) { + if (tableMapping.status.equals(ColumnarTableStatus.DROP.name()) || + tableMapping.status.equals(ColumnarTableStatus.PURGE.name())) { continue; } long latestVersionId = tableMapping.latestVersionId; @@ -1054,6 +1100,10 @@ public void changeColumnarIndexTableColumns(List indexTableNames, String columnarColumnEvolutionAccessor.queryIdsWithOrder(columnarTableEvolutionRecord.columns); final int pos = getPos(columnsRecords, columnarColumnEvolutionRecords); List newRecords = new ArrayList<>(); + List oldColumns = new ArrayList<>(); + for (int i = 0; i < Math.min(pos, columnsRecords.size()); i++) { + oldColumns.add(columnsRecords.get(i).columnName); + } for (int i = pos; i < columnsRecords.size(); i++) { ColumnsRecord record = columnsRecords.get(i); record.tableName = indexTableName; @@ -1061,16 +1111,12 @@ public void changeColumnarIndexTableColumns(List indexTableNames, String } // insert/update index table column records in columns + if (!oldColumns.isEmpty()) { + columnsAccessor.deleteNotIn(schemaName, indexTableName, oldColumns); + } else { + columnsAccessor.delete(schemaName, indexTableName); + } if (!newRecords.isEmpty()) { - List deleteColumns = new ArrayList<>(); - for (ColumnsRecord record : newRecords) { - if (changeColumnsMap.containsKey(record.columnName)) { - deleteColumns.add(changeColumnsMap.get(record.columnName)); - } else { - deleteColumns.add(record.columnName); - } - } - columnsAccessor.delete(schemaName, indexTableName, deleteColumns); columnsAccessor.insert(newRecords, schemaName, indexTableName); } } @@ -1078,7 +1124,8 @@ public void changeColumnarIndexTableColumns(List indexTableNames, String public List reorderColumns(ColumnarTableEvolutionRecord columnarTableEvolutionRecord, List columnsRecords, Long versionId, Long ddlJobId, - String indexTableName, List> changeColumns) { + String indexTableName, List> changeColumns, + List dropColumns) { List columnarColumnEvolutionRecords = columnarColumnEvolutionAccessor.queryIdsWithOrder(columnarTableEvolutionRecord.columns); @@ -1106,7 +1153,8 @@ public List reorderColumns(ColumnarTableEvolutionRecord columnarTableEvolu for (int i = pos; i < columnsRecords.size(); i++) { ColumnsRecord record = columnsRecords.get(i); record.tableName = indexTableName; - if (columnMap.containsKey(record.columnName)) { + if (columnMap.containsKey(record.columnName) && + (dropColumns == null || !dropColumns.contains(record.columnName))) { records.add( new ColumnarColumnEvolutionRecord(tableId, columnMap.get(record.columnName), record.columnName, versionId, ddlJobId, record)); @@ -1185,6 +1233,10 @@ public void changeColumnarIndexColumnMeta(PhyInfoSchemaContext context, } } + public void renameColumnarIndex(String tableSchema, String newIndexName) { + indexesAccessor.renameCciIndex(tableSchema, newIndexName); + } + /** * Query columnar table evolution by tableId */ @@ -1192,6 +1244,20 @@ public List queryColumnarTableEvolutionLatest(Long return columnarTableEvolutionAccessor.queryTableIdLatest(tableId); } + /** + * Query columnar table evolution by versionId + */ + public ColumnarTableEvolutionRecord queryColumnarTableEvolutionByVersionId(long versionId) { + return columnarTableEvolutionAccessor.queryByVersionIdLatest(versionId).get(0); + } + + /** + * Query columnar checkpoints by commit ts + */ + public List queryColumnarCheckpointsByCommitTs(long commitTs) { + return columnarCheckpointsAccessor.queryByTso(commitTs); + } + /** * Query columnar table evolution by ddlJobId */ @@ -1213,6 +1279,13 @@ public List queryColumnarTableEvolution(Long table return columnarTableEvolutionAccessor.queryTableIdVersionId(tableId, versionId); } + /** + * Query first(CREATE_INDEX) columnar table evolution by tableId + */ + public List queryColumnarTableEvolutionFirst(Long tableId) { + return columnarTableEvolutionAccessor.queryTableIdFirst(tableId); + } + /** * Query columnar column evolution by versionId and fieldId list */ @@ -1220,6 +1293,13 @@ public List queryColumnarColumnEvolution(List queryColumnarPartitionEvolution(List ids) { + return columnarPartitionEvolutionAccessor.queryIds(ids); + } + /** * Query columnar table mapping by schema, primary and columnar table name */ @@ -1248,11 +1328,25 @@ public List queryColumnarTableMapping(Long tableId) return columnarTableMappingAccessor.queryTableId(tableId); } + public void renameColumnarTables(String schemaName, List> tableRenameMap, + List versionIds, long ddlJobID) { + for (int i = 0; i < tableRenameMap.size(); i++) { + Long versionId = versionIds.get(i); + String oldName = tableRenameMap.get(i).getKey(); + String newName = tableRenameMap.get(i).getValue(); + renameColumnarTable(schemaName, oldName, newName, versionId, ddlJobID); + } + } + public void renameColumnarTable(String schemaName, String primaryTableName, String newPrimaryTableName, long versionId, long ddlJobID) { List tableMappingRecords = columnarTableMappingAccessor.querySchemaTable(schemaName, primaryTableName); for (ColumnarTableMappingRecord tableMappingRecord : tableMappingRecords) { + if (tableMappingRecord.status.equals(ColumnarTableStatus.DROP.name()) || + tableMappingRecord.status.equals(ColumnarTableStatus.PURGE.name())) { + continue; + } long tableId = tableMappingRecord.tableId; ColumnarTableEvolutionRecord latest = columnarTableEvolutionAccessor.queryTableIdLatest(tableId).get(0); latest.versionId = versionId; @@ -1332,10 +1426,6 @@ public void addOssFile(String tableSchema, String tableName, FilesRecord filesRe filesAccessor.insert(ImmutableList.of(filesRecord), tableSchema, tableName); } - public void addOssFileWithTso(String tableSchema, String tableName, FilesRecord filesRecord) { - filesAccessor.insertWithTso(ImmutableList.of(filesRecord)); - } - public List queryFilesByLogicalSchemaTable(String logicalSchemaName, String logicalTableName) { return filesAccessor.queryByLogicalSchemaTable(logicalSchemaName, logicalTableName); } @@ -1600,7 +1690,20 @@ public void hideTable(String tableSchema, String tableName) { public void updatePartitionBoundDesc(String tableSchema, String tableName, String partitionName, String boundDesc) { tablePartitionAccessor.updatePartBoundDescForOnePartition(tableSchema, tableName, partitionName, boundDesc); + } + + public void updateArcStateByFirstLevelPartitionList(String tableSchema, String tableName, + List partitionNames, + Integer newArcState) throws Exception { + tablePartitionAccessor.setPartitionTtlStateByPartitionNames(tableSchema, tableName, + partitionNames, newArcState, null); + } + public void updateArcStateByFirstLevelPartitionList(String tableSchema, String tableName, + List partitionNames, + Integer beforeArcState, Integer newArcState) throws Exception { + tablePartitionAccessor.setPartitionTtlStateByPartitionNames(tableSchema, tableName, + partitionNames, newArcState, beforeArcState); } private void updateStatus(String tableSchema, String tableName, SequenceBaseRecord sequenceRecord, @@ -1650,12 +1753,58 @@ public void removeColumnarTable(String schemaName, String columnarTableName) { removeTable(schemaName, columnarTableName, null, true); } + public void truncateColumnarTable(String schemaName, String primaryTableName, Set> indexes, + long versionId, long ddlJobId, DdlType ddlType) { + for (Pair index : indexes) { + Long tableId = index.getKey(); + String indexName = index.getValue(); + final ColumnarTableMappingRecord tableMapping = + columnarTableMappingAccessor.querySchemaTableIndex(schemaName, primaryTableName, indexName).get(0); + if (tableMapping.status.equals(ColumnarTableStatus.DROP.name()) || + tableMapping.status.equals(ColumnarTableStatus.PURGE.name())) { + continue; + } + long latestVersionId = tableMapping.latestVersionId; + // Insert column evolution records + ColumnarTableEvolutionRecord columnarTableEvolutionRecord = + columnarTableEvolutionAccessor.queryByVersionIdLatest(latestVersionId).get(0); + columnarTableEvolutionRecord = + new ColumnarTableEvolutionRecord(versionId, tableId, schemaName, primaryTableName, indexName, + columnarTableEvolutionRecord.options, + ddlJobId, ddlType.name(), Long.MAX_VALUE, columnarTableEvolutionRecord.columns, + columnarTableEvolutionRecord.partitions); + + columnarTableEvolutionAccessor.insert(ImmutableList.of(columnarTableEvolutionRecord)); + columnarTableMappingAccessor.updateVersionId(versionId, tableId); + } + } + + public boolean haveColumnarTable(String tableSchema, String tableName) { + //列存索引只会是数字 + if (!StringUtils.isNumeric(tableName)) { + return false; + } + long tableId; + try { + //数字解析失败,返回false,列存索引是正常的long值 + tableId = Long.parseLong(tableName); + } catch (Exception e) { + return false; + } + + return !columnarTableMappingAccessor.querySchemaTableId(tableSchema, tableId).isEmpty(); + } + public void removeTable(String tableSchema, String tableName, SequenceBaseRecord sequenceRecord, boolean withTablesExtOrPartition) { tablesAccessor.delete(tableSchema, tableName); columnsAccessor.delete(tableSchema, tableName); indexesAccessor.delete(tableSchema, tableName); - filesAccessor.delete(tableSchema, tableName); + + //删表时,包含列存的情况不能直接删除files系统表,而oss冷热归档需要删files,特殊判断下 + if (!haveColumnarTable(tableSchema, tableName)) { + filesAccessor.delete(tableSchema, tableName); + } columnMetaAccessor.delete(tableSchema, tableName); foreignAccessor.delete(tableSchema, tableName); foreignColsAccessor.delete(tableSchema, tableName); @@ -1669,6 +1818,7 @@ public void removeTable(String tableSchema, String tableName, SequenceBaseRecord if (withTablesExtOrPartition && DbInfoManager.getInstance().isNewPartitionDb(tableSchema)) { this.deletePartitionInfo(tableSchema, tableName); this.removeLocalPartitionRecord(tableSchema, tableName); + this.removeTtlInfoRecord(tableSchema, tableName); this.removeScheduledJobRecord(tableSchema, tableName); this.joinGroupTableDetailAccessor.deleteJoinGroupTableDetailBySchemaTable(tableSchema, tableName); } @@ -1678,8 +1828,9 @@ public void updateColumnarTableEvolutionDdlType(String ddlType, long ddlId) { columnarTableEvolutionAccessor.updateDdlType(ddlType, ddlId); } - public void updateColumnarTableStatusBySchema(String schema, String status) { - columnarTableMappingAccessor.updateStatusBySchema(schema, status); + public void updateColumnarTableStatusAndVersionIDBySchema(String schema, long versionId, String status) { + columnarTableMappingAccessor. + updateStatusAndVersionIdBySchema(schema, versionId, status); } public void updateColumnarTableStatus(String schema, String tableName, String indexName, String status, @@ -1794,6 +1945,14 @@ public void renamePartitionTable(String tableSchema, String tableName, String ne columnMappingAccessor.rename(tableSchema, tableName, newTableName); } + public void renameColumnarTable(String tableSchema, String tableName, String newTableName) { + tablesAccessor.rename(tableSchema, tableName, newTableName); + tablePartitionAccessor.rename(tableSchema, tableName, newTableName); + columnsAccessor.rename(tableSchema, tableName, newTableName); + indexesAccessor.renameCciIndex(tableSchema, newTableName); + filesAccessor.rename(tableSchema, tableName, newTableName); + } + public void renamePartitionTablePhyTable(String tableSchema, String tableName, String newTableName) { TablePartitionConfig tablePartitionConfig = tablePartitionAccessor.getTablePartitionConfig(tableSchema, tableName, false); @@ -1804,10 +1963,6 @@ public void renamePartitionTablePhyTable(String tableSchema, String tableName, S } } - public void renameIndexes(String tableSchema, String indexName, String newIndexName) { - indexesAccessor.renameGsiIndexes(tableSchema, indexName, newIndexName); - } - public void renameLocalPartitionInfo(String tableSchema, String tableName, String newTableName) { String newScheduleName = "LOCAL_PARTITION:" + tableSchema + "." + newTableName; String oldScheduleName = "LOCAL_PARTITION:" + tableSchema + "." + tableName; @@ -1815,6 +1970,10 @@ public void renameLocalPartitionInfo(String tableSchema, String tableName, Strin localPartitionAccessor.rename(newTableName, tableSchema, tableName); } + public void renameIndexes(String tableSchema, String indexName, String newIndexName) { + indexesAccessor.renameGsiIndexes(tableSchema, indexName, newIndexName); + } + public void setMultiWriteSourceColumn(String tableSchema, String tableName, String columnsName) { columnsAccessor.updateStatus(tableSchema, tableName, ImmutableList.of(columnsName), ColumnStatus.MULTI_WRITE_SOURCE.getValue()); @@ -1927,8 +2086,10 @@ public void updateColumns(PhyInfoSchemaContext context, Map oldColumnsRecords = queryColumns(context.tableSchema, context.tableName); - Map oldColumnRecordMap = - oldColumnsRecords.stream().collect(Collectors.toMap(o -> o.columnName, o -> o)); + TreeMap oldColumnRecordMap = + oldColumnsRecords.stream().collect( + Collectors.toMap(o -> o.columnName, o -> o, (before, after) -> after, + () -> new TreeMap<>(CASE_INSENSITIVE_ORDER))); for (ColumnsRecord columnsRecord : columnsRecords) { String columnName = columnsRecord.columnName; columnsRecord.ordinalPosition = oldColumnRecordMap.get(columnName).ordinalPosition; @@ -1951,10 +2112,10 @@ public void updateColumns(PhyInfoSchemaContext context, Map> columnsJdbcExtInfo, List> columnNamePairs) { // columnNamePairs: new_column_name => old_column_name - Map New2OldColumnNameMap = new HashMap<>(); - Map old2NewColumnNameMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map new2OldColumnNameMap = new TreeMap<>(CASE_INSENSITIVE_ORDER); + Map old2NewColumnNameMap = new TreeMap<>(CASE_INSENSITIVE_ORDER); for (Pair pair : columnNamePairs) { - New2OldColumnNameMap.put(pair.getKey(), pair.getValue()); + new2OldColumnNameMap.put(pair.getKey(), pair.getValue()); old2NewColumnNameMap.put(pair.getValue(), pair.getKey()); } @@ -1970,12 +2131,14 @@ public void changeColumns(PhyInfoSchemaContext context, Map oldColumnsRecords = queryColumns(context.tableSchema, context.tableName); - Map oldColumnRecordMap = - oldColumnsRecords.stream().collect(Collectors.toMap(o -> o.columnName, o -> o)); + TreeMap oldColumnRecordMap = + oldColumnsRecords.stream().collect( + Collectors.toMap(o -> o.columnName, o -> o, (before, after) -> after, + () -> new TreeMap<>(CASE_INSENSITIVE_ORDER))); for (ColumnsRecord columnsRecord : columnsRecords) { String columnName = columnsRecord.columnName; - if (New2OldColumnNameMap.containsKey(columnName)) { - ColumnsRecord oldColumnsRecord = oldColumnRecordMap.get(New2OldColumnNameMap.get(columnName)); + if (new2OldColumnNameMap.containsKey(columnName)) { + ColumnsRecord oldColumnsRecord = oldColumnRecordMap.get(new2OldColumnNameMap.get(columnName)); ColumnsAccessor.copyFromOldToNewColumnRecord(oldColumnsRecord, columnsRecord); } } @@ -1991,7 +2154,7 @@ public void changeColumns(PhyInfoSchemaContext context, Map indexesRecords = @@ -2013,7 +2176,7 @@ public void changeColumns(PhyInfoSchemaContext context, Map indexesRecords = indexesAccessor.queryTableIndexes(tableSchema, tableName); - Map old2NewIndexNameMap = indexNamePairs.stream().collect(Collectors.toMap(Pair::getValue, - Pair::getKey)); + TreeMap old2NewIndexNameMap = indexNamePairs.stream().collect(Collectors.toMap(Pair::getValue, + Pair::getKey, (before, after) -> after, () -> new TreeMap<>(CASE_INSENSITIVE_ORDER))); List indexNames = indexesRecords.stream().map(o -> o.indexName).collect(Collectors.toList()); for (IndexesRecord indexesRecord : indexesRecords) { if (old2NewIndexNameMap.containsKey(indexesRecord.indexName)) { @@ -2659,7 +2822,13 @@ public void removeAll(String schemaName) { sequencesAccessor.deleteAll(schemaName); tablePartitionAccessor.deleteTablePartitionConfigsByDbName(schemaName); localPartitionAccessor.deleteAll(schemaName); - filesAccessor.delete(schemaName); + ttlInfoAccessor.deleteByDbName(schemaName); + + //删库时,包含列存的情况不能直接删除files系统表,而oss冷热归档需要删files,特殊判断下 + List columnarRecords = columnarTableMappingAccessor.querySchema(schemaName); + if (columnarRecords.isEmpty()) { + filesAccessor.delete(schemaName); + } columnMetaAccessor.delete(schemaName); columnEvolutionAccessor.delete(schemaName); columnMappingAccessor.delete(schemaName); @@ -2827,6 +2996,17 @@ public List getLocalPartitionRecordBySchema(String sc return recordList; } + public List getTtlInfoRecordBySchema(String schemaName) { + Preconditions.checkArgument(StringUtils.isNotEmpty(schemaName)); + List recordList = ttlInfoAccessor.queryTtlInfoListByDb(schemaName); + return recordList; + } + + public List getAllTtlInfoRecords() { + List recordList = ttlInfoAccessor.queryAllTtlInfoList(); + return recordList; + } + public List getAllLocalPartitionRecord() { List recordList = localPartitionAccessor.query(); return recordList; @@ -2838,6 +3018,24 @@ public TableLocalPartitionRecord getLocalPartitionRecord(String schemaName, Stri return record; } + public TtlInfoRecord getTtlInfoRecord(String schemaName, String tableName) { + Preconditions.checkArgument(StringUtils.isNotEmpty(schemaName)); + TtlInfoRecord record = ttlInfoAccessor.queryTtlInfoByDbAndTb(schemaName, tableName); + return record; + } + + public TtlInfoRecord getTtlInfoRecordByArchiveTable(String arcSchemaName, String arcTableName) { + Preconditions.checkArgument(StringUtils.isNotEmpty(arcSchemaName)); + TtlInfoRecord record = ttlInfoAccessor.queryTtlInfoByArcDbAndArcTb(arcSchemaName, arcTableName); + return record; + } + + public TtlInfoRecord getTtlInfoRecordByArchiveTmpTable(String arcTmpTblSchema, String arcTmpTblName) { + Preconditions.checkArgument(StringUtils.isNotEmpty(arcTmpTblName)); + TtlInfoRecord record = ttlInfoAccessor.queryTtlInfoByArcTmpDbAndArcTmpTb(arcTmpTblSchema, arcTmpTblName); + return record; + } + public TableLocalPartitionRecord getLocalPartitionRecordByArchiveTable(String archiveSchemaName, String archiveTableName) { Preconditions.checkArgument(StringUtils.isNotEmpty(archiveSchemaName)); @@ -2851,11 +3049,54 @@ public int addLocalPartitionRecord(TableLocalPartitionRecord tableLocalPartition return localPartitionAccessor.insert(tableLocalPartitionRecord); } + public int insertTtlInfoRecord(TtlInfoRecord ttlInfoRecord) { + Preconditions.checkNotNull(ttlInfoRecord); + return ttlInfoAccessor.insertNewTtlInfo(ttlInfoRecord); + } + + public int updateTtlInfoRecord(TtlInfoRecord ttlInfoRecord, + String tblSchema, String tblName) { + Preconditions.checkNotNull(ttlInfoRecord); + return ttlInfoAccessor.updateTtlInfoByDbNameAndTbName(ttlInfoRecord, tblSchema, tblName); + } + public void updateArchiveTable(String schemaName, String tableName, String archiveTableSchema, String archiveTableName) { localPartitionAccessor.updateArchiveTable(schemaName, tableName, archiveTableSchema, archiveTableName); } + public void updateArchiveTableForTtlInfo(String ossTableSchema, + String ossTableName, + String arcTmpTableSchema, + String arcTmpTableName, + String ttlSchemaName, + String ttlTableName) { + ttlInfoAccessor.updateArcTableInfoByByDbAndTb(TtlInfoRecord.ARCHIVE_STATUS_DISABLE_OSS_ARCHIVE, ossTableSchema, + ossTableName, arcTmpTableSchema, arcTmpTableName, ttlSchemaName, ttlTableName); + } + + public void renameTtlTableForTtlInfo(String newTtlTableSchema, + String newTtlTableName, + String ttlSchemaName, + String ttlTableName) { + ttlInfoAccessor.updateTtlTableNameByDbAndTb(newTtlTableSchema, newTtlTableName, ttlSchemaName, ttlTableName); + } + + public void updateArchiveTableForTtlInfo(Integer arcKind, + String ossTableSchema, + String ossTableName, + String arcTmpTableSchema, + String arcTmpTableName, + String ttlSchemaName, + String ttlTableName) { + ttlInfoAccessor.updateArcTableInfoByByDbAndTb(arcKind, ossTableSchema, ossTableName, arcTmpTableSchema, + arcTmpTableName, ttlSchemaName, ttlTableName); + } + + public void unBindingByArchiveTableNameForTtlInfo(String archiveTableSchema, String archiveTableName) { + ttlInfoAccessor.unBindingByArchiveTableName(archiveTableSchema, archiveTableName); + } + public void unBindingByArchiveTableName(String archiveTableSchema, String archiveTableName) { localPartitionAccessor.unBindingByArchiveTableName(archiveTableSchema, archiveTableName); } @@ -2869,9 +3110,9 @@ public int addScheduledJob(ScheduledJobsRecord scheduledJobsRecord) { return scheduledJobsAccessor.insert(scheduledJobsRecord); } - public int replaceScheduledJob(ScheduledJobsRecord scheduledJobsRecord) { + public int updateScheduledJobsRecordByScheduleId(ScheduledJobsRecord scheduledJobsRecord) { Preconditions.checkNotNull(scheduledJobsRecord); - return scheduledJobsAccessor.replace(scheduledJobsRecord); + return scheduledJobsAccessor.updateScheduledJobsRecordByScheduleId(scheduledJobsRecord); } public int removeLocalPartitionRecord(String schemaName, String tableName) { @@ -2880,6 +3121,12 @@ public int removeLocalPartitionRecord(String schemaName, String tableName) { return localPartitionAccessor.delete(schemaName, tableName); } + public int removeTtlInfoRecord(String schemaName, String tableName) { + Preconditions.checkNotNull(schemaName); + Preconditions.checkNotNull(tableName); + return ttlInfoAccessor.deleteTtlInfoByDbAndTb(schemaName, tableName); + } + public int removeScheduledJobRecord(String schemaName, String tableName) { Preconditions.checkNotNull(schemaName); Preconditions.checkNotNull(tableName); @@ -2894,4 +3141,18 @@ public int removeScheduledJobRecord(String schemaName, String tableName) { } return count; } + + public int removeTtlFiredScheduledJobRecords(String schemaName, String tableName) { + Preconditions.checkNotNull(schemaName); + Preconditions.checkNotNull(tableName); + List recordList = scheduledJobsAccessor.query(schemaName, tableName, "TTL_JOB"); + int count = 0; + if (CollectionUtils.isEmpty(recordList)) { + return count; + } + for (ScheduledJobsRecord record : recordList) { + firedScheduledJobsAccessor.deleteQueuedJobsById(record.getScheduleId()); + } + return count; + } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/TablesAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/TablesAccessor.java index 5eeaf6b83..ab479cd18 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/TablesAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/TablesAccessor.java @@ -32,9 +32,12 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; public class TablesAccessor extends AbstractAccessor { @@ -111,7 +114,7 @@ public class TablesAccessor extends AbstractAccessor { private static final String UPDATE_TABLES_STATISTIC = UPDATE_TABLES + "`table_rows` = ?, `avg_row_length` = ?, `data_length` = ?, `max_data_length` = ?, `index_length` = ?, " - + "`data_free` = ?" + + "`data_free` = ?, `update_time` = now()" + WHERE_SCHEMA_TABLE; private static final String UPDATE_TABLES_FLAG = UPDATE_TABLES + "`flag` = ?" + WHERE_SCHEMA_TABLE; @@ -126,6 +129,9 @@ public class TablesAccessor extends AbstractAccessor { public static final String SELECT_VERSION_FOR_UPDATE = "select version from " + TABLES_TABLE + " where table_schema=? and table_name=? for update"; + private static final String QUERY_LONG_TIME_NOT_UPDATED_TABLES = + "select table_name from " + TABLES_TABLE + " where table_schema = ? and update_time < now() - interval 1 day"; + public int insert(TablesRecord record) { try { DdlMetaLogUtil.logSql(INSERT_TABLES, record.buildInsertParams()); @@ -317,4 +323,23 @@ public int delete(String tableSchema) { return delete(DELETE_TABLES_ALL, TABLES_TABLE, tableSchema); } + public Set getLongTimeNotUpdatedTables(String tableSchema) { + Set tables = new HashSet<>(); + try (PreparedStatement ps = connection.prepareStatement(QUERY_LONG_TIME_NOT_UPDATED_TABLES)) { + ps.setString(1, tableSchema); + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + tables.add(rs.getString(1).toLowerCase()); + } + } catch (SQLException e) { + LOGGER.error( + "Failed to query " + TABLES_TABLE + " for update time, schema " + tableSchema, + e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "update", + TABLES_TABLE, + e.getMessage()); + } + return tables; + } + } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ViewsInfoRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ViewsInfoRecord.java new file mode 100644 index 000000000..07446ec84 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/table/ViewsInfoRecord.java @@ -0,0 +1,28 @@ +package com.alibaba.polardbx.gms.metadb.table; + +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class ViewsInfoRecord implements SystemTableRecord { + public long id; + public String catalogName; + public String schemaName; + public String viewName; + public String viewDefinition; + + @Override + public ViewsInfoRecord fill(ResultSet rs) throws SQLException { + try { + this.id = rs.getLong("id"); + } catch (Exception ignored) { + + } + this.catalogName = rs.getString("catalog_name"); + this.schemaName = rs.getString("schema_name"); + this.viewName = rs.getString("view_name"); + this.viewDefinition = rs.getString("view_definition"); + return this; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/trx/DeadlocksAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/trx/DeadlocksAccessor.java new file mode 100644 index 000000000..f272d99ec --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/metadb/trx/DeadlocksAccessor.java @@ -0,0 +1,62 @@ +package com.alibaba.polardbx.gms.metadb.trx; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.gms.metadb.GmsSystemTables; +import com.alibaba.polardbx.gms.metadb.accessor.AbstractAccessor; +import com.alibaba.polardbx.gms.util.MetaDbUtil; + +import java.sql.ResultSet; +import java.sql.Statement; +import java.util.HashMap; +import java.util.Map; + +public class DeadlocksAccessor extends AbstractAccessor { + private static final Logger logger = LoggerFactory.getLogger(TrxLogStatusAccessor.class); + private static final String DEADLOCKS = wrap(GmsSystemTables.DEADLOCKS); + private static final String INSERT_DEADLOCK = "INSERT INTO " + DEADLOCKS + + " (cn_address, type, log) values (?, ?, ?)"; + private static final String QUERY_COUNT = "SELECT COUNT(0) FROM " + DEADLOCKS; + + public int recordDeadlock(String cnAddr, String type, String log) { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, cnAddr); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, type); + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, log); + try { + return MetaDbUtil.insert(INSERT_DEADLOCK, params, connection); + } catch (Exception e) { + logger.error("Failed to insert the system table '" + DEADLOCKS + "'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "insert", + DEADLOCKS, + e.getMessage()); + } + } + + public int rotate() { + long maxKeepLogs = DynamicConfig.getInstance().getMaxKeepDeadlockLogs(); + try (Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery(QUERY_COUNT)) { + long current = 0; + if (rs.next()) { + current = rs.getLong(1); + } + if (current > maxKeepLogs) { + return stmt.executeUpdate( + "DELETE FROM " + DEADLOCKS + " ORDER BY gmt_created LIMIT " + (current - maxKeepLogs)); + } else { + return 0; + } + } catch (Exception e) { + logger.error("Failed to rotate the system table '" + DEADLOCKS + "'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "rotate", + DEADLOCKS, + e.getMessage()); + } + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/LogPattern.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/LogPattern.java index 7b3f1af53..3732fb84f 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/LogPattern.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/LogPattern.java @@ -29,6 +29,7 @@ public enum LogPattern { STATE_CHANGE_FAIL("job: %s, state change fail, from %s to %s"), NOT_ENABLED("%s not enabled, %s"), PROCESS_START("%s started: %s"), + PROCESS_SKIPPED("%s skipped: %s"), PROCESSING("%s processing: %s"), PROCESS_END("%s succeed ended,result: %s"), INTERRUPTED("%s job being interrupted by %s"), diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/Module.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/Module.java index a9810946d..48e1330b7 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/Module.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/Module.java @@ -22,7 +22,7 @@ * @author fangwu */ public enum Module { - SPM, STATISTICS, SCHEDULE_JOB, MODULE_LOG, UNKNOWN, OSS, TRX, OPTIMIZER, COLUMNAR_PRUNE; + SPM, STATISTICS, SCHEDULE_JOB, MODULE_LOG, UNKNOWN, OSS, TRX, OPTIMIZER, COLUMNAR_PRUNE, METRIC; private ModuleInfo moduleInfo; diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/ModuleLogInfo.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/ModuleLogInfo.java index b08e4aa9f..e6d8d9912 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/ModuleLogInfo.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/module/ModuleLogInfo.java @@ -34,11 +34,12 @@ import static com.alibaba.polardbx.common.eventlogger.EventType.MODULE_ERROR; import static com.alibaba.polardbx.common.properties.ConnectionParams.ENABLE_MODULE_LOG; import static com.alibaba.polardbx.common.properties.ConnectionParams.MAX_MODULE_LOG_PARAMS_SIZE; -import static com.alibaba.polardbx.gms.module.LogPattern.START_OVER; -import static com.alibaba.polardbx.gms.module.Module.MODULE_LOG; import static com.alibaba.polardbx.common.utils.logger.LoggerFactory.getLogger; import static com.alibaba.polardbx.gms.module.LogLevel.CRITICAL; +import static com.alibaba.polardbx.gms.module.LogLevel.NORMAL; +import static com.alibaba.polardbx.gms.module.LogPattern.START_OVER; import static com.alibaba.polardbx.gms.module.LogPattern.UNEXPECTED; +import static com.alibaba.polardbx.gms.module.Module.MODULE_LOG; /** * Log event separated by module @@ -72,6 +73,10 @@ public void logRecord(Module m, LogPattern lp, String[] params, LogLevel level) logRecord(m, lp, params, level, Thread.currentThread().getName(), null); } + public void logInfo(Module m, LogPattern lp, String[] params) { + logRecord(m, lp, params, NORMAL, Thread.currentThread().getName(), null); + } + public void logRecord(Module m, LogPattern lp, String[] params, LogLevel level, String traceInfo) { logRecord(m, lp, params, level, traceInfo, null); } @@ -84,6 +89,11 @@ public void logRecord(Module m, LogPattern lp, String[] params, LogLevel level, logRecord(m, lp, params, level, traceInfo, t, false); } + public void logError(Module m, String processInfo, Throwable t) { + logRecord(m, UNEXPECTED, new String[] {processInfo, t.getMessage()}, CRITICAL, Thread.currentThread().getName(), + t); + } + public void logRecord(Module m, LogPattern lp, String[] params, LogLevel level, String traceInfo, Throwable t, boolean needAuditLog) { // enable check diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/AllNodes.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/AllNodes.java index b2db3f573..7372c3fc0 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/AllNodes.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/AllNodes.java @@ -32,41 +32,35 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.collect.ImmutableSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -import static java.util.Objects.requireNonNull; - public class AllNodes { + + protected static final Logger logger = LoggerFactory.getLogger(AllNodes.class); + private Set activeNodes; - private Set otherActiveNodes; + private Set otherActiveRowNodes; + private Set otherActiveColumnarNodes; private Set inactiveNodes; private Set shuttingDownNodes; - private int activeHashcode; - - public static final AllNodes EMPTY = new AllNodes(null, null, null, -1); - - public AllNodes(Set activeNodes, Set otherActiveNodes, Set inactiveNodes, - Set shuttingDownNodes) { - this.activeNodes = new HashSet<>(requireNonNull(activeNodes, "activeNodes is null")); - this.otherActiveNodes = new HashSet<>(requireNonNull(otherActiveNodes, "activeNodes is null")); - this.inactiveNodes = new HashSet<>(requireNonNull(inactiveNodes, "inactiveNodes is null")); - this.shuttingDownNodes = new HashSet<>(requireNonNull(shuttingDownNodes, "shuttingDownNodes is null")); - } + public static final AllNodes EMPTY = + new AllNodes(ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of(), ImmutableSet.of()); @JsonCreator public AllNodes(@JsonProperty("activeNodes") Set activeNodes, + @JsonProperty("otherActiveNodes") Set otherActiveNodes, + @JsonProperty("otherActiveColumnarNodes") Set otherActiveColumnarNodes, @JsonProperty("inactiveNodes") Set inactiveNodes, - @JsonProperty("shuttingDownNodes") Set shuttingDownNodes, - @JsonProperty("activeHashcode") int activeHashcode) { - this.activeNodes = activeNodes; - this.inactiveNodes = inactiveNodes; - this.shuttingDownNodes = shuttingDownNodes; - this.activeHashcode = activeHashcode; + @JsonProperty("shuttingDownNodes") Set shuttingDownNodes) { + updateActiveNodes(activeNodes, otherActiveNodes, otherActiveColumnarNodes, inactiveNodes, shuttingDownNodes); } @JsonProperty @@ -75,8 +69,13 @@ public Set getActiveNodes() { } @JsonIgnore - public Set getOtherActiveNodes() { - return otherActiveNodes; + public Set getOtherActiveRowNodes() { + return otherActiveRowNodes; + } + + @JsonIgnore + public Set getOtherActiveColumnarNodes() { + return otherActiveColumnarNodes; } @JsonProperty @@ -89,56 +88,64 @@ public Set getShuttingDownNodes() { return shuttingDownNodes; } - @JsonProperty - public int getActiveHashcode() { - return activeHashcode; - } - - public void setActiveNodes(Set activeNodes, Set otherActiveNodes) { - this.activeNodes = new HashSet<>(requireNonNull(activeNodes, "activeNodes is null")); - this.otherActiveNodes = otherActiveNodes; - } - - public void setInactiveNodes(Set inactiveNodes) { - this.inactiveNodes = inactiveNodes; - } - - public void setShuttingDownNodes(Set shuttingDownNodes) { - this.shuttingDownNodes = shuttingDownNodes; - } - - public void setActiveHashcode(int activeHashcode) { - this.activeHashcode = activeHashcode; + public void updateActiveNodes(Set activeNodes, Set otherActiveNodes, Set + otherActiveColumnarNodes, Set inactiveNodes, Set shuttingDownNodes) { + this.activeNodes = new HashSet<>(activeNodes); + this.otherActiveRowNodes = new HashSet<>(otherActiveNodes); + this.otherActiveColumnarNodes = new HashSet<>(otherActiveColumnarNodes); + this.inactiveNodes = new HashSet<>(inactiveNodes); + this.shuttingDownNodes = new HashSet<>(shuttingDownNodes); } - public List getAllWorkers(boolean slaveFirst) { - List workers = new ArrayList<>(); - if (slaveFirst && otherActiveNodes != null && !otherActiveNodes.isEmpty()) { - for (Node node : otherActiveNodes) { + public List getAllWorkers(MppScope scope) { + List workers = new ArrayList<>(); + switch (scope) { + case SLAVE: + for (InternalNode node : otherActiveRowNodes) { if (node.isWorker()) { workers.add(node); } } - } else { - for (Node node : activeNodes) { + break; + case COLUMNAR: + for (InternalNode node : otherActiveColumnarNodes) { if (node.isWorker()) { workers.add(node); } } - } - - /* - for (Node node : inactiveNodes) { - if (node.isWorker()) { - workers.add(node); + break; + case CURRENT: + for (InternalNode node : activeNodes) { + if (node.isWorker()) { + workers.add(node); + } } - } - for (Node node : shuttingDownNodes) { - if (node.isWorker()) { - workers.add(node); + break; + case ALL: + for (InternalNode node : otherActiveColumnarNodes) { + if (node.isWorker()) { + workers.add(node); + } + } + for (InternalNode node : otherActiveRowNodes) { + if (node.isWorker()) { + workers.add(node); + } + } + for (InternalNode node : activeNodes) { + if (node.isWorker()) { + workers.add(node); + } } + break; + default: + for (InternalNode node : activeNodes) { + if (node.isWorker()) { + workers.add(node); + } + } + break; } - */ return workers; } @@ -151,4 +158,5 @@ public List getAllCoordinators() { } return coordinators; } + } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/GmsNodeManager.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/GmsNodeManager.java index a4232ee1e..edb97aa68 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/GmsNodeManager.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/GmsNodeManager.java @@ -106,6 +106,7 @@ public class GmsNodeManager extends AbstractLifecycle { private int currentIndex = -1; private int readOnlyNodeCpuCore = -1; + private int readOnlyColumnarCpuCore = -1; private GmsNodeManager() { } @@ -252,8 +253,8 @@ private void reloadDifferentNodes(int localServerPort) { } else if (instType == ServerInfoRecord.INST_TYPE_COLUMNAR_SLAVE) { readOnlyNodes.add(gmsNode); columnarReadOnlyNodes.add(gmsNode); + this.readOnlyColumnarCpuCore = gmsNode.cpuCore; } - if (instId.equalsIgnoreCase(InstIdUtil.getInstId())) { if (TStringUtil.equalsIgnoreCase(gmsNode.host, AddressUtils.getHostIp()) && gmsNode.serverPort == localServerPort) { @@ -573,8 +574,12 @@ private void printGmsNode() { LOGGER.info(nodeInfo.toString()); } - //FIXME estimate public int getReadOnlyNodeCpuCore() { return readOnlyNodeCpuCore; } + + public int getReadOnlyColumnarCpuCore() { + return readOnlyColumnarCpuCore; + } + } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/InternalNode.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/InternalNode.java index 0e396c321..42b2f876c 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/InternalNode.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/InternalNode.java @@ -253,6 +253,7 @@ public String getHostMppPort() { return host + ":" + rpcPort; } + @Override public String getHostPort() { return host + ":" + port; } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/InternalNodeManager.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/InternalNodeManager.java index 6a3ddfd4f..9a9b80c8f 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/InternalNodeManager.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/InternalNodeManager.java @@ -29,33 +29,18 @@ */ package com.alibaba.polardbx.gms.node; -import java.util.List; import java.util.Set; public interface InternalNodeManager { - /** - * @param slaveFirst true - 只读实例的节点优先 - */ - Set getNodes(NodeState state, boolean slaveFirst); - Node getCurrentNode(); - Set getCoordinators(); - AllNodes getAllNodes(); - void refreshNodes(); - - /** - * @param slaveFirst true - 只读实例的节点优先 - */ - List getAllWorkers(boolean slaveFirst); - - List getAllCoordinators(); - void removeNode(NodeServer node, String schema); - void updateNodes(Set activeNodes, Set otherActiveNodes, Set inactiveNodes, + void updateNodes(Set currentActiveNodes, Set remoteActiveRowNodes, + Set remoteActiveColumnarNodes, + Set inactiveNodes, Set shuttingDownNodes); } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/MPPQueryMonitor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/MPPQueryMonitor.java new file mode 100644 index 000000000..736d1113a --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/MPPQueryMonitor.java @@ -0,0 +1,73 @@ +package com.alibaba.polardbx.gms.node; + +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.sync.SyncScope; + +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.StampedLock; + +/** + * Calculate the QPS of queries under MPP mode within the statistical time window. + * Additionally, calculate the concurrency of queries under MPP mode. + */ +public class MPPQueryMonitor { + private static int nodeSize; + + static { + // Get node size of master CN cluster. + if (ConfigDataMode.isMasterMode()) { + List nodes = + GmsNodeManager.getInstance().getNodesBySyncScope(SyncScope.MASTER_ONLY); + nodeSize = nodes.size(); + } else { + nodeSize = 0; + } + } + + private static final MPPQueryMonitor INSTANCE = new MPPQueryMonitor(); + + private AtomicLong currentQueries = new AtomicLong(0L); + private ConcurrentLinkedQueue queryFinishedTimestamp = new ConcurrentLinkedQueue<>(); + private StampedLock stampedLock = new StampedLock(); + + public static MPPQueryMonitor getInstance() { + return INSTANCE; + } + + public void recordStartingQuery() { + currentQueries.getAndIncrement(); + } + + public void recordFinishedQuery(long windowPeriodInMillis) { + long now = System.currentTimeMillis(); + queryFinishedTimestamp.add(now); + currentQueries.decrementAndGet(); + + // Remove timestamps that exceed the statistical period. + long stamp = stampedLock.writeLock(); + try { + while (!queryFinishedTimestamp.isEmpty() + && now - queryFinishedTimestamp.peek() > windowPeriodInMillis) { + queryFinishedTimestamp.poll(); + } + } finally { + stampedLock.unlockWrite(stamp); + } + } + + public double calculateQPS(long windowPeriodInMillis) { + // Calculate the QPS within the statistical period. + double qps = 0; + if (!queryFinishedTimestamp.isEmpty() + && System.currentTimeMillis() - queryFinishedTimestamp.peek() <= windowPeriodInMillis) { + qps = queryFinishedTimestamp.size() / (windowPeriodInMillis / 1000.0); + } + return qps * nodeSize; + } + + public long getQueryConcurrency() { + return currentQueries.get() * nodeSize; + } +} \ No newline at end of file diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/MppScope.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/MppScope.java new file mode 100644 index 000000000..e0908c6cb --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/MppScope.java @@ -0,0 +1,21 @@ +package com.alibaba.polardbx.gms.node; + +public enum MppScope { + + /** + * 当前实例 + */ + CURRENT, + + /** + * 远程行存只读实例 + */ + SLAVE, + + /** + * 远程列存只读实例 + */ + COLUMNAR, + + ALL +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/NodeStatusManager.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/NodeStatusManager.java index 4c4b60429..a08b5cc10 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/NodeStatusManager.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/NodeStatusManager.java @@ -50,11 +50,15 @@ public abstract class NodeStatusManager { public final static int ROLE_MASTER = 4; //是否Leader public final static int ROLE_LEADER = 8; + //加到黑名单中的节点不提供mpp服务 public final static int ROLE_BLACKLIST = 16; + //ROLE_SLAVE: 1 - 只读实例(HTAP使用),主实例 0 - 只读实例节点未加入HTAP链路 public final static int ROLE_HTAP = 32; + public final static int ROLE_COLUMNAR = 64; + protected InternalNode localNode; protected String selectSql; protected String deleteLeaderSql; @@ -103,9 +107,6 @@ public synchronized void destroy(boolean stop) { protected abstract void doDestroy(boolean stop); - protected abstract void updateActiveNodes( - String instId, InternalNode node, Set activeNodes, Set otherActiveNodes, int role); - protected abstract String updateTableMetaSql(int status); protected abstract void checkLeader(Connection conn, String leaderId); @@ -141,10 +142,9 @@ public void tempInactiveNode(InternalNode node) { } } - private String injectNode(ResultSet rs, Set activeNodes, Set otherActiveNodes, - Set inactiveNodes, - Set shuttingDownNodes, - Set htapInstIds) + private String injectNode(ResultSet rs, Set currentActiveNodes, + Set remoteActiveRowNodes, Set remoteActiveColumnarNodes, + Set inactiveNodes, Set shuttingDownNodes) throws SQLException { String leaderId = null; String nodeId = rs.getString("NODEID"); @@ -159,19 +159,14 @@ private String injectNode(ResultSet rs, Set activeNodes, Set ACTIVE_LEASE || status == STATUS_INACTIVE) { @@ -189,7 +184,15 @@ private String injectNode(ResultSet rs, Set activeNodes, Set activeNodes = new HashSet<>(); - Set otherActiveNodes = new HashSet<>(); + try (Statement statement = conn.createStatement(); ResultSet resultSet = statement.executeQuery(selectSql)) { + Set currentActiveNodes = new HashSet<>(); + Set remoteActiveRowNodes = new HashSet<>(); + Set remoteActiveColumnarNodes = new HashSet<>(); Set inactiveNodes = new HashSet<>(); Set shuttingDownNodes = new HashSet<>(); - Set htapInstIds = new HashSet<>(); String leaderId = null; while (resultSet.next()) { - String ret = injectNode( - resultSet, activeNodes, otherActiveNodes, inactiveNodes, shuttingDownNodes, htapInstIds); + String ret = injectNode(resultSet, currentActiveNodes, remoteActiveRowNodes, remoteActiveColumnarNodes, + inactiveNodes, shuttingDownNodes); if (!StringUtils.isEmpty(ret)) { leaderId = ret; } @@ -239,29 +241,18 @@ protected void refreshAllNodeInternal(Connection conn) throws Throwable { if (localNode.isWorker()) { //本节点是worker节点的话,不写0库也有效 - activeNodes.add(localNode); + currentActiveNodes.add(localNode); } //主实例可以选择所有只读实例的worker节点, 只读实例只能选择本只读实例节点 - //otherActiveNodes 存储只读实例的活跃节点 - nodeManager.updateNodes(activeNodes, otherActiveNodes, inactiveNodes, shuttingDownNodes); + //remoteActiveRowNodes 存储只读实例的活跃节点 + nodeManager.updateNodes(currentActiveNodes, remoteActiveRowNodes, remoteActiveColumnarNodes, inactiveNodes, + shuttingDownNodes); } catch (Throwable e) { throw e; } } - /** - * @param role 附加角色,比如给node加上leader角色 - */ - protected String replaceTableMetaSql(Node node, int role) { - return "replace into " + tableName - + " (`CLUSTER`, `INST_ID`, `NODEID`, `VERSION`, `IP`, `PORT`, `RPC_PORT`, `ROLE`, `STATUS`) " - + "values ('" + node.getCluster() + "', '" + node.getInstId() + "', '" + node.getNodeIdentifier() + "', '" - + node.getVersion() + "', '" + node.getHost() - + "', " + node.getPort() + ", " + node.getRpcPort() + ", " + (getRole(node) | role) + ", " + STATUS_ACTIVE - + ")"; - } - protected String insertOrUpdateTableMetaSql(Node node, int role) { return "insert into " + tableName + " (`CLUSTER`, `INST_ID`, `NODEID`, `VERSION`, `IP`, `PORT`, `RPC_PORT`, `ROLE`, `STATUS`) " @@ -278,7 +269,7 @@ protected String insertOrUpdateTableMetaSql(Node node, int role) { " `STATUS` = '" + STATUS_ACTIVE + "'"; } - protected int getRole(Node node) { + public int getRole(Node node) { int role = 0; if (node.isWorker()) { role = role | ROLE_WORKER; @@ -293,7 +284,11 @@ protected int getRole(Node node) { role = role | ROLE_BLACKLIST; } if (node.isHtap()) { - role = role | ROLE_HTAP; + if (ConfigDataMode.isColumnarMode()) { + role = role | ROLE_COLUMNAR; + } else { + role = role | ROLE_HTAP; + } } if (ConfigDataMode.isMasterMode()) { diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/StorageStatusManager.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/StorageStatusManager.java index 94e511027..19173045c 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/StorageStatusManager.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/node/StorageStatusManager.java @@ -237,15 +237,7 @@ private void detection(Supplier connectionSupplier, String instId, S activeSession = 0; delaySecond = Integer.MAX_VALUE; logger.warn("check slave status error for " + storageId, e); - if (salveConn != null) { - try { - salveConn.close(); - salveConn = null; - } catch (Throwable t) { - //ignore - } - } - }finally { + } finally { if (salveConn != null) { try { salveConn.close(); diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/BackfillExtraFieldJSON.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/BackfillExtraFieldJSON.java index aeb19210d..267241516 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/BackfillExtraFieldJSON.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/BackfillExtraFieldJSON.java @@ -23,6 +23,15 @@ public class BackfillExtraFieldJSON { public String approximateRowCount; public String splitLevel; public String testCaseName; + public Boolean logical = false; + + public Boolean getLogical() { + return logical; + } + + public void setLogical(Boolean logical) { + this.logical = logical; + } public BackfillExtraFieldJSON() { } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/ExtraFieldJSON.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/ExtraFieldJSON.java index aef7dbd15..600607dca 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/ExtraFieldJSON.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/ExtraFieldJSON.java @@ -17,7 +17,6 @@ package com.alibaba.polardbx.gms.partition; import com.alibaba.fastjson.JSON; -import lombok.Value; /** * Extensible extra fields for table_partitions @@ -28,10 +27,29 @@ public class ExtraFieldJSON { protected String timeZone; protected String charset; protected String collation; - + /** + * The ttl state of a partition of ttl_tmp (only used by ttl_tmp table) , + * this state is used to label if a part has been finished oss archiving. + *
+     *  arc_state_archived(state=3): means current part has been finish oss archiving;
+     *  arc_state_archiving(state=2): means current part is performing oss archiving;
+     *  arc_state_ready(state=1):  means current part has be ready to do archiving, waiting do archiving;
+     *  arc_state_not_ready(state=0):  means current part is performing oss archiving.
+     *
+     *  (The enum definition is TtlPartArcState)
+     *
+     *  Notice:
+     *  When a part is on the state of ttl_state_ready, it means that
+     *  all the expired data of this part has been inserted, and not more increment。
+     *  So, a ttl_state_ready-state part will REJECT any insert/update/delete operation.
+     *
+     * 
+ */ + protected Integer arcState; + public ExtraFieldJSON() { } - + public static ExtraFieldJSON fromJson(String json) { return JSON.parseObject(json, ExtraFieldJSON.class); } @@ -87,4 +105,12 @@ public String getCollation() { public void setCollation(String collation) { this.collation = collation; } + + public Integer getArcState() { + return arcState; + } + + public void setArcState(Integer arcState) { + this.arcState = arcState; + } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/TablePartitionAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/TablePartitionAccessor.java index 39a360706..65a077d56 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/TablePartitionAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/TablePartitionAccessor.java @@ -67,7 +67,8 @@ public class TablePartitionAccessor extends AbstractAccessor { + " from table_partitions where table_schema=? order by table_name, part_level, part_position asc"; private static final String GET_TABLE_PARTITIONS_BY_DB_TB = - "select " + ALL_COLUMNS + " from table_partitions where table_schema=? and table_name=?"; + "select " + ALL_COLUMNS + + " from table_partitions where table_schema=? and table_name=? order by part_level, part_position asc"; private static final String GET_TABLE_PARTITIONS_BY_DB_TB_PT = "select " + ALL_COLUMNS + " from table_partitions where table_schema=? and table_name=? and part_name = ?"; @@ -83,10 +84,21 @@ public class TablePartitionAccessor extends AbstractAccessor { "select " + ALL_COLUMNS + " from table_partitions where table_schema=? and part_level=? order by parent_id, part_position asc"; + private static final String GET_TABLE_PARTITIONS_BY_DB_TB_PT_LIST = + "select " + ALL_COLUMNS + " from table_partitions where table_schema=? and table_name=? and part_name in (%s)"; + private static final String GET_PUBLIC_TABLE_PARTITIONS_BY_DB_TB_LEVEL = "select " + ALL_COLUMNS + " from table_partitions where table_schema=? and table_name=? and part_level=? and part_status=1 order by parent_id, part_position asc"; + private static final String GET_VALID_TABLE_PARTITIONS_BY_DB_TB_LEVEL = + "select " + ALL_COLUMNS + + " from table_partitions where table_schema=? and table_name=? and part_level=? and part_status>=0 order by parent_id, part_position asc"; + + private static final String GET_INVALID_TABLE_PARTITIONS_BY_DB_TB_LEVEL = + "select " + ALL_COLUMNS + + " from table_partitions where table_schema=? and table_name=? and part_level=? and part_status=-1 order by parent_id, part_position asc"; + private static final String DELETE_TABLE_PARTITIONS_BY_TABLE_NAME = "delete from table_partitions where table_schema=? and table_name=?"; @@ -103,7 +115,7 @@ public class TablePartitionAccessor extends AbstractAccessor { "update table_partitions set meta_version=? where part_level=0 and table_schema=? and table_name=? "; private static final String UPDATE_TABLE_PARTITIONS_PART_FLAG = - "update table_partitions set part_flags = ? where table_schema = ? and table_name = ? "; + "update table_partitions set part_flags = part_flags | ? where table_schema = ? and table_name = ? "; private static final String UPDATE_TABLE_PARTITIONS_SWITCH_NAME_TYPE = "update table_partitions set table_name=? , tbl_type = ? where table_schema=? and table_name=? "; @@ -111,6 +123,9 @@ public class TablePartitionAccessor extends AbstractAccessor { private static final String UPDATE_TABLE_PARTITIONS_LOCALITY_BY_ID = "update table_partitions set part_extras=? where table_schema=? and id=? "; + private static final String UPDATE_TABLE_PARTITIONS_TTL_STATE_BY_ID = + "update table_partitions set part_extras=? where table_schema=? and id=? "; + private static final String DELETE_TABLE_PARTITIONS_BY_TABLE_AND_PARTITION = "delete from table_partitions where (table_schema=? and table_name=? and part_name=?) " + " or parent_id = ?"; @@ -213,6 +228,30 @@ public class TablePartitionAccessor extends AbstractAccessor { "select " + ALL_COLUMNS + " from table_partitions where table_schema=? and group_id=? and part_name=? and part_level=1"; + private static final String DISABLE_STATUS_FOR_PARTITION_BY_SCH_GID_l2 = + "update table_partitions set part_status=-1 where table_schema=? and group_id=? and part_level=2"; + + private static final String DISABLE_STATUS_FOR_PARTITION_BY_SCH_TB_GID_l2 = + "update table_partitions set part_status=-1 where table_schema=? and table_name=? and group_id=? and part_level=2"; + + private static final String DISABLE_STATUS_FOR_PARTITION_BY_SCH_TB_TEMP_PART_l2 = + "update table_partitions set part_status=-1 where table_schema=? and table_name=? and part_temp_name=? and part_level=2"; + + private static final String DISABLE_STATUS_FOR_PARTITION_BY_SCH_TB_PART_l1 = + "update table_partitions set part_status=-1 where table_schema=? and table_name=? and part_name=? and part_level=1"; + + private static final String DELETE_PARTITION_BY_SCH_GID_l2 = + "delete from table_partitions where table_schema=? and group_id=? and part_level=2 and part_status=-1"; + + private static final String DELETE_PARTITION_BY_SCH_TB_GID_l2 = + "delete from table_partitions where table_schema=? and table_name=? and group_id=? and part_level=2 and part_status=-1"; + + private static final String DELETE_PARTITION_BY_SCH_TB_TEMP_PART_l2 = + "delete from table_partitions where table_schema=? and table_name=? and part_temp_name=? and part_level=2 and part_status=-1"; + + private static final String DELETE_PARTITION_BY_SCH_TB_PART_l1 = + "delete from table_partitions where table_schema=? and table_name=? and part_name=? and part_level=1 and part_status=-1"; + public List getTablePartitionsByDbNameTbNameLevel(String dbName, String tbName, int level, boolean from_delta_table) { try { @@ -279,6 +318,52 @@ public List getPublicTablePartitionsByDbNameTbNameLevel(St } } + public List getValidTablePartitionsByDbNameTbNameLevel(String dbName, String tbName, + int level) { + try { + + List records; + Map params = new HashMap<>(); + + assert dbName != null; + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, dbName); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tbName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setInt, level); + records = + MetaDbUtil + .query(GET_VALID_TABLE_PARTITIONS_BY_DB_TB_LEVEL, params, TablePartitionRecord.class, connection); + + return records; + } catch (Exception e) { + logger.error("Failed to query the system table 'table_partitions'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, + e.getMessage()); + } + } + + public List getInValidTablePartitionsByDbNameTbNameLevel(String dbName, String tbName, + int level) { + try { + + List records; + Map params = new HashMap<>(); + + assert dbName != null; + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, dbName); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tbName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setInt, level); + records = + MetaDbUtil + .query(GET_INVALID_TABLE_PARTITIONS_BY_DB_TB_LEVEL, params, TablePartitionRecord.class, connection); + + return records; + } catch (Exception e) { + logger.error("Failed to query the system table 'table_partitions'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, + e.getMessage()); + } + } + public List getTablePartitionsByDbNameGroupId(String dbName, Long groupId) { try { @@ -958,6 +1043,68 @@ public void updateTablePartitionsLocality(List tablePartit MetaDbUtil.update(sql, paramsBatch, this.connection); } + public void setPartitionTtlStateByPartitionNames(String dbName, + String tableName, + List phyPartNames, + Integer newTtlState, + Integer beforeTtlState) throws Exception { + String sqlTemp = GET_TABLE_PARTITIONS_BY_DB_TB_PT_LIST; + + String partNameListStr = ""; + for (int i = 0; i < phyPartNames.size(); i++) { + String partName = phyPartNames.get(i); + if (!partNameListStr.isEmpty()) { + partNameListStr += ","; + } + partNameListStr += "'" + partName + "'"; + } + String sql = String.format(sqlTemp, partNameListStr); + + Map params = new HashMap<>(); + int j = 1; + MetaDbUtil.setParameter(j++, params, ParameterMethod.setString, dbName); + MetaDbUtil.setParameter(j++, params, ParameterMethod.setString, tableName); + + // table_schema + List tablePartitionRecords = + MetaDbUtil.query(sql, params, TablePartitionRecord.class, connection); + + for (TablePartitionRecord tablePartition : tablePartitionRecords) { + if (beforeTtlState != null && !tablePartition.partExtras.arcState.equals(beforeTtlState)) { + String msg = String.format("The table partition %s arcState %s is unexpected, expected is %s.", + tablePartition.getPartName(), tablePartition.partExtras.arcState, beforeTtlState); + logger.error(msg); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_GENERIC, msg); + } + tablePartition.partExtras.setArcState(newTtlState); + } + + updateTablePartitionsTtlState(tablePartitionRecords); + } + + public void updateTablePartitionsTtlState(List tablePartitionRecordList) + throws SQLException { + List> paramsBatch = new ArrayList<>(); + for (int i = 0; i < tablePartitionRecordList.size(); i++) { + TablePartitionRecord tpRecord = tablePartitionRecordList.get(i); + Map params = new HashMap<>(); + int j = 1; + //-----logical table------ + // sp_temp_flag + MetaDbUtil.setParameter(j++, params, ParameterMethod.setString, + ExtraFieldJSON.toJson(tpRecord.partExtras)); + // table_schema + MetaDbUtil.setParameter(j++, params, ParameterMethod.setString, tpRecord.tableSchema); + // table_name + MetaDbUtil.setParameter(j++, params, ParameterMethod.setLong, tpRecord.id); + paramsBatch.add(params); + } + String sql = UPDATE_TABLE_PARTITIONS_TTL_STATE_BY_ID; + + DdlMetaLogUtil.logSql(sql, paramsBatch); + MetaDbUtil.update(sql, paramsBatch, this.connection); + } + public int[] addNewTablePartitions(List tablePartitionsRecordList, boolean isUpsert, boolean toDeltaTable) throws SQLException { @@ -1463,4 +1610,145 @@ public List getFirstLevelPartitionsBySchTgIdName(String sc } } + public void disableStatusBySchGidL2(String tableSchema, Long groupId) { + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, groupId); + + DdlMetaLogUtil.logSql(DISABLE_STATUS_FOR_PARTITION_BY_SCH_GID_l2, params); + + MetaDbUtil.update(DISABLE_STATUS_FOR_PARTITION_BY_SCH_GID_l2, params, connection); + return; + } catch (Exception e) { + logger.error("Failed to query the system table 'table_partitions'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, + e.getMessage()); + } + } + + public void disableStatusBySchTbGidL2(String tableSchema, String tableName, Long groupId) { + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, groupId); + + DdlMetaLogUtil.logSql(DISABLE_STATUS_FOR_PARTITION_BY_SCH_TB_GID_l2, params); + + MetaDbUtil.update(DISABLE_STATUS_FOR_PARTITION_BY_SCH_TB_GID_l2, params, connection); + return; + } catch (Exception e) { + logger.error("Failed to query the system table 'table_partitions'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, + e.getMessage()); + } + } + + public void disableStatusBySchTempPartL2(String tableSchema, String tableName, String tempPartName) { + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, tempPartName); + + DdlMetaLogUtil.logSql(DISABLE_STATUS_FOR_PARTITION_BY_SCH_TB_TEMP_PART_l2, params); + + MetaDbUtil.update(DISABLE_STATUS_FOR_PARTITION_BY_SCH_TB_TEMP_PART_l2, params, connection); + return; + } catch (Exception e) { + logger.error("Failed to query the system table 'table_partitions'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, + e.getMessage()); + } + } + + public void disableStatusBySchPartL1(String tableSchema, String tableName, String partName) { + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, partName); + + DdlMetaLogUtil.logSql(DISABLE_STATUS_FOR_PARTITION_BY_SCH_TB_PART_l1, params); + + MetaDbUtil.update(DISABLE_STATUS_FOR_PARTITION_BY_SCH_TB_PART_l1, params, connection); + return; + } catch (Exception e) { + logger.error("Failed to query the system table 'table_partitions'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, + e.getMessage()); + } + } + + public void deletePartitionBySchGidL2(String tableSchema, Long groupId) { + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setLong, groupId); + + DdlMetaLogUtil.logSql(DELETE_PARTITION_BY_SCH_GID_l2, params); + + MetaDbUtil.update(DELETE_PARTITION_BY_SCH_GID_l2, params, connection); + return; + } catch (Exception e) { + logger.error("Failed to query the system table 'table_partitions'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, + e.getMessage()); + } + } + + public void deletePartitionBySchTbGidL2(String tableSchema, String tableName, Long groupId) { + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setLong, groupId); + + DdlMetaLogUtil.logSql(DELETE_PARTITION_BY_SCH_TB_GID_l2, params); + + MetaDbUtil.update(DELETE_PARTITION_BY_SCH_TB_GID_l2, params, connection); + return; + } catch (Exception e) { + logger.error("Failed to query the system table 'table_partitions'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, + e.getMessage()); + } + } + + public void deletePartitionBySchTempPartL2(String tableSchema, String tableName, String tempPartName) { + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, tempPartName); + + DdlMetaLogUtil.logSql(DELETE_PARTITION_BY_SCH_TB_TEMP_PART_l2, params); + + MetaDbUtil.update(DELETE_PARTITION_BY_SCH_TB_TEMP_PART_l2, params, connection); + return; + } catch (Exception e) { + logger.error("Failed to query the system table 'table_partitions'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, + e.getMessage()); + } + } + + public void deletePartitionBySchPartL1(String tableSchema, String tableName, String partName) { + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + MetaDbUtil.setParameter(3, params, ParameterMethod.setString, partName); + + DdlMetaLogUtil.logSql(DELETE_PARTITION_BY_SCH_TB_PART_l1, params); + + MetaDbUtil.update(DELETE_PARTITION_BY_SCH_TB_PART_l1, params, connection); + return; + } catch (Exception e) { + logger.error("Failed to query the system table 'table_partitions'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, + e.getMessage()); + } + } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/TablePartitionRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/TablePartitionRecord.java index 2ca6c566b..0d3ef6a0c 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/TablePartitionRecord.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/partition/TablePartitionRecord.java @@ -21,6 +21,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.Date; +import java.util.Objects; /** * @author chenghui.lch @@ -42,8 +43,10 @@ public class TablePartitionRecord implements SystemTableRecord { public final static int SUBPARTITION_TEMPLATE_UNUSED = 0; public final static int SUBPARTITION_TEMPLATE_NOT_EXISTED = -1; + public final static int PARTITION_STATUS_PARTITION_OFFLINE = -1; + /** - * Flags for auto-balance + * Flags for auto-balance, use the variable of auto_flag */ public final static int PARTITION_AUTO_BALANCE_DISABLE = 0; public final static int PARTITION_AUTO_BALANCE_ENABLE_ALL = 1; @@ -132,10 +135,11 @@ public class TablePartitionRecord implements SystemTableRecord { public String phyTable; /** - * General flags. + * flags values for part_flags */ public final static long FLAG_LOCK = 0x1; - public final static long FLAG_AUTO_PARTITION = 0x2; + public final static long FLAG_AUTO_PARTITION = 0x2;// label if a part-table is auto-partitioned table + public final static long FLAG_TTL_TEMPORARY_TABLE = 0x4; // label if a part-table is a ttl-tmp table @Override public TablePartitionRecord fill(ResultSet rs) throws SQLException { @@ -372,6 +376,18 @@ public void clearAutoPartition() { this.partFlags &= ~FLAG_AUTO_PARTITION; } + public boolean isTtlTemporary() { + return (this.partFlags & FLAG_TTL_TEMPORARY_TABLE) != 0L; + } + + public void setTtlTemporary() { + this.partFlags |= FLAG_TTL_TEMPORARY_TABLE; + } + + public void clearTtlTemporary() { + this.partFlags &= ~FLAG_TTL_TEMPORARY_TABLE; + } + public String getPhyTable() { return phyTable; } @@ -440,4 +456,28 @@ public String toString() { ", phyTable='" + phyTable + '\'' + '}'; } + + public static boolean isPartitionRecordEqual(TablePartitionRecord record1, TablePartitionRecord record2) { + return Objects.equals(record1.parentId, record2.parentId) && + Objects.equals(record1.tableSchema, record2.tableSchema) && + Objects.equals(record1.tableName, record2.tableName) && + Objects.equals(record1.spTempFlag, record2.spTempFlag) && + Objects.equals(record1.groupId, record2.groupId) && + Objects.equals(record1.metaVersion, record2.metaVersion) && + Objects.equals(record1.autoFlag, record2.autoFlag) && + Objects.equals(record1.tblType, record2.tblType) && + Objects.equals(record1.partName, record2.partName) && + Objects.equals(record1.partTempName, record2.partTempName) && + Objects.equals(record1.partLevel, record2.partLevel) && + Objects.equals(record1.nextLevel, record2.nextLevel) && + Objects.equals(record1.partStatus, record2.partStatus) && + Objects.equals(record1.partPosition, record2.partPosition) && + Objects.equals(record1.partMethod, record2.partMethod) && + Objects.equals(record1.partExpr, record2.partExpr) && + Objects.equals(record1.partDesc, record2.partDesc) && + Objects.equals(record1.partComment, record2.partComment) && + Objects.equals(record1.partEngine, record2.partEngine) && + Objects.equals(record1.partFlags, record2.partFlags) && + Objects.equals(record1.phyTable, record2.phyTable); + } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/FiredScheduledJobsAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/FiredScheduledJobsAccessor.java index a9521a02d..23107e40c 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/FiredScheduledJobsAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/FiredScheduledJobsAccessor.java @@ -24,15 +24,14 @@ import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.gms.metadb.accessor.AbstractAccessor; -import com.alibaba.polardbx.gms.metadb.misc.DdlEngineRecord; -import com.alibaba.polardbx.gms.util.DdlMetaLogUtil; import com.alibaba.polardbx.gms.util.MetaDbUtil; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.time.ZonedDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.FIRED_SCHEDULED_JOBS; import static com.alibaba.polardbx.gms.metadb.GmsSystemTables.SCHEDULED_JOBS; @@ -88,7 +87,7 @@ public class FiredScheduledJobsAccessor extends AbstractAccessor { "LEFT OUTER JOIN " + SCHEDULED_JOBS + " S " + "ON F.`schedule_id`=S.`schedule_id` " + "WHERE F.`fire_time` <= UNIX_TIMESTAMP() " + - "AND F.`state` IN ('QUEUED') "; + "AND F.`state` IN ('QUEUED') ORDER BY fire_time ASC"; private static final String GET_RUNNING_SCHEDULED_JOBS = "SELECT " + @@ -118,6 +117,64 @@ public class FiredScheduledJobsAccessor extends AbstractAccessor { "WHERE F.`fire_time` <= UNIX_TIMESTAMP() " + "AND F.`state` IN ('RUNNING') "; + private static final String GET_QUEUED_TTL_SCHEDULED_JOBS = + "SELECT " + + "S.`schedule_id`, " + + "S.`table_schema`, " + + "S.`table_name`, " + + "S.`table_group_name` as table_group_name, " + + "S.`schedule_name`, " + + "S.`schedule_comment`, " + + "S.`executor_type`, " + + "S.`schedule_context`, " + + "S.`executor_contents`, " + + "S.`status`, " + + "S.`schedule_type`, " + + "S.`schedule_expr`, " + + "S.`time_zone`, " + + "S.`schedule_policy`, " + + "F.`fire_time`, " + + "F.`start_time`, " + + "F.`finish_time`, " + + "F.`state`, " + + "F.`remark`, " + + "F.`result` " + + "FROM " + FIRED_SCHEDULED_JOBS + " F " + + "LEFT OUTER JOIN " + SCHEDULED_JOBS + " S " + + "ON F.`schedule_id`=S.`schedule_id` " + + "WHERE F.`fire_time` <= UNIX_TIMESTAMP() " + + "AND S.executor_type='TTL_JOB' " + + "AND F.`state` IN ('QUEUED') ORDER BY fire_time ASC LIMIT 1000"; + + private static final String GET_RUNNING_TTL_SCHEDULED_JOBS = + "SELECT " + + "S.`schedule_id`, " + + "S.`table_schema`, " + + "S.`table_name`, " + + "S.`table_group_name` as table_group_name, " + + "S.`schedule_name`, " + + "S.`schedule_comment`, " + + "S.`executor_type`, " + + "S.`schedule_context`, " + + "S.`executor_contents`, " + + "S.`status`, " + + "S.`schedule_type`, " + + "S.`schedule_expr`, " + + "S.`time_zone`, " + + "S.`schedule_policy`, " + + "F.`fire_time`, " + + "F.`start_time`, " + + "F.`finish_time`, " + + "F.`state`, " + + "F.`remark`, " + + "F.`result` " + + "FROM " + FIRED_SCHEDULED_JOBS + " F " + + "LEFT OUTER JOIN " + SCHEDULED_JOBS + " S " + + "ON F.`schedule_id`=S.`schedule_id` " + + "WHERE F.`fire_time` <= UNIX_TIMESTAMP() " + + "AND S.executor_type='TTL_JOB' " + + "AND F.`state` IN ('RUNNING') ORDER BY fire_time ASC LIMIT 1000"; + private static final String QUERY_BY_SCHEDULED_ID = "SELECT " + "S.`schedule_id`, " + @@ -156,6 +213,22 @@ public List getQueuedJobs() { } } + public List getQueuedTtlJobs() { + try { + return MetaDbUtil.query(GET_QUEUED_TTL_SCHEDULED_JOBS, ExecutableScheduledJob.class, connection); + } catch (Exception e) { + throw logAndThrow("Failed to query " + FIRED_SCHEDULED_JOBS, "query", e); + } + } + + public List getRunningTtlJobs() { + try { + return MetaDbUtil.query(GET_RUNNING_TTL_SCHEDULED_JOBS, ExecutableScheduledJob.class, connection); + } catch (Exception e) { + throw logAndThrow("Failed to query " + FIRED_SCHEDULED_JOBS, "query", e); + } + } + public List queryByScheduleId(long scheduleId) { try { final Map params = new HashMap<>(1); @@ -228,6 +301,23 @@ public FiredScheduledJobsRecord queryForUpdate(long schedulerId, "AND `schedule_id` = ? " + "AND `fire_time` = ? "; + private static final String QUERY_LATEST_REMARK_BY_ID = "SELECT `remark` FROM " + FIRED_SCHEDULED_JOBS + + " WHERE `schedule_id` = ? AND `remark` is not null order by `fire_time` DESC LIMIT 1"; + + public String queryLatestRemarkById(long scheduleId) { + try (PreparedStatement statement = connection.prepareStatement(QUERY_LATEST_REMARK_BY_ID)) { + statement.setLong(1, scheduleId); + try (ResultSet rs = statement.executeQuery()) { + if (rs.next()) { + return rs.getString(1); + } + } + } catch (Exception e) { + throw logAndThrow("Failed to query from " + FIRED_SCHEDULED_JOBS, "query from", e); + } + return null; + } + public boolean updateState(long schedulerId, long fireTime, FiredScheduledJobState newState, @@ -335,6 +425,9 @@ public int fire(FiredScheduledJobsRecord record) { private static final String DELETE_BY_SCHEDULE_ID = "delete from " + FIRED_SCHEDULED_JOBS + WHERE_SCHEDULE_ID; + private static final String DELETE_QUEUED_JOBS_BY_SCHEDULE_ID = + "delete from " + FIRED_SCHEDULED_JOBS + " where `schedule_id` = ? and `state`='QUEUED'"; + public int deleteById(long scheduleId) { try { final Map params = @@ -346,6 +439,18 @@ public int deleteById(long scheduleId) { } } + public int deleteQueuedJobsById(long scheduleId) { + try { + final Map params = + MetaDbUtil.buildParameters(ParameterMethod.setLong, new Object[] {scheduleId}); + return MetaDbUtil.delete(DELETE_QUEUED_JOBS_BY_SCHEDULE_ID, params, connection); + } catch (Exception e) { + throw logAndThrow( + "Failed to delete queued-state jobs from " + FIRED_SCHEDULED_JOBS + " for schedule_id: " + scheduleId, + "delete from", e); + } + } + public int deleteAll(String schemaName) { try { final Map params = diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/ScheduledJobExecutorType.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/ScheduledJobExecutorType.java index ab314cda9..76c507e20 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/ScheduledJobExecutorType.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/ScheduledJobExecutorType.java @@ -18,6 +18,8 @@ import com.alibaba.polardbx.gms.module.Module; +import static com.alibaba.polardbx.gms.module.Module.METRIC; +import static com.alibaba.polardbx.gms.module.Module.MODULE_LOG; import static com.alibaba.polardbx.gms.module.Module.OPTIMIZER; import static com.alibaba.polardbx.gms.module.Module.OSS; import static com.alibaba.polardbx.gms.module.Module.SPM; @@ -28,6 +30,7 @@ public enum ScheduledJobExecutorType { LOCAL_PARTITION(UNKNOWN), + TTL_JOB(UNKNOWN), REBALANCE(UNKNOWN), PARTITION_VISUALIZER(UNKNOWN), REFRESH_MATERIALIZED_VIEW(UNKNOWN), @@ -37,6 +40,7 @@ public enum ScheduledJobExecutorType { STATISTIC_HLL_SKETCH(STATISTICS), STATISTIC_ROWCOUNT_COLLECTION(STATISTICS), STATISTIC_RELOAD(STATISTICS), + STATISTIC_INFO_SCHEMA_TABLES(STATISTICS), PURGE_OSS_FILE(OSS), OPTIMIZER_ALERT(OPTIMIZER), @@ -44,7 +48,11 @@ public enum ScheduledJobExecutorType { PERSIST_GSI_STATISTICS(UNKNOWN), @Deprecated CLEAN_LOG_TABLE(TRX), - CLEAN_LOG_TABLE_V2(TRX); + CLEAN_LOG_TABLE_V2(TRX), + CHECK_CCI(TRX), + GENERATE_COLUMNAR_SNAPSHOT(TRX), + + LOG_SYSTEM_METRICS(METRIC); ScheduledJobExecutorType(Module module) { m = module; diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/ScheduledJobsAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/ScheduledJobsAccessor.java index b593edc18..a74b69397 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/ScheduledJobsAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/scheduler/ScheduledJobsAccessor.java @@ -59,6 +59,25 @@ public class ScheduledJobsAccessor extends AbstractAccessor { "`schedule_policy`," + "`table_group_name`"; + private static final String COLUMNS_TO_SET = + "`table_schema` = ?," + + "`table_name` = ?," + + "`schedule_name` = ?," + + "`schedule_comment` = ?," + + "`executor_type` = ?," + + "`schedule_context` = ?," + + "`executor_contents` = ?," + + "`status` = ?," + + "`schedule_type` = ?," + + "`schedule_expr` = ?," + + "`time_zone` = ?," + + "`last_fire_time` = ?," + + "`next_fire_time` = ?," + + "`starts` = ?," + + "`ends` = ?," + + "`schedule_policy` = ?," + + "`table_group_name` = ?"; + private static final String ALL_VALUES = "(null,null,null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; private static final String INSERT_TABLE_SCHEDULED_JOBS = @@ -67,6 +86,9 @@ public class ScheduledJobsAccessor extends AbstractAccessor { private static final String REPLACE_TABLE_SCHEDULED_JOBS = "replace into " + SCHEDULED_JOBS + " (" + ALL_COLUMNS + ") VALUES " + ALL_VALUES; + private static final String UPDATE_TABLE_SCHEDULED_JOBS_BY_SCHEDULED_ID = + "update " + SCHEDULED_JOBS + " SET " + COLUMNS_TO_SET + " WHERE schedule_id=?"; + private static final String GET_TABLE_SCHEDULED_JOBS = "select " + ALL_COLUMNS + " from " + SCHEDULED_JOBS; private static final String GET_TABLE_SCHEDULED_JOBS_BY_ID = GET_TABLE_SCHEDULED_JOBS + " where schedule_id=?"; @@ -123,9 +145,50 @@ public int insertIgnoreFail(ScheduledJobsRecord record) { } } - public int replace(ScheduledJobsRecord record) { + public int updateScheduledJobsRecordByScheduleId(ScheduledJobsRecord record) { try { - return MetaDbUtil.insert(REPLACE_TABLE_SCHEDULED_JOBS, record.buildParams(), connection); + +// "`table_schema` = ?," + // varchar,string +// "`table_name` = ?," + // varchar,string +// "`schedule_name` = ?," + // varchar,string +// "`schedule_comment` = ?," + // varchar,string +// "`executor_type` = ?," + // varchar,string +// "`schedule_context` = ?," + // longtext,string +// "`executor_contents` = ?," + // longtext,string +// "`status` = ?," + // longtext,string +// "`schedule_type` = ?," + // varchar,string +// "`schedule_expr` = ?," + // varchar,string +// "`time_zone` = ?," + // varchar,string +// "`last_fire_time` = ?," + // bigint,long +// "`next_fire_time` = ?," + // bigint,long +// "`starts` = ?," + // bigint,long +// "`ends` = ?," + // bigint,long +// "`schedule_policy` = ?," + // varchar,string +// "`table_group_name` = ?"; // varchar,string +// where schedule_id = ? // bigint,long + + final Map params = new HashMap<>(); + int paramIndex = 0; // start with 1 + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getTableSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getTableName()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getScheduleName()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getScheduleComment()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getExecutorType()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getScheduleContext()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getExecutorContents()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getStatus()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getScheduleType()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getScheduleExpr()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getTimeZone()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setLong, record.getLastFireTime()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setLong, record.getNextFireTime()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setLong, record.getStarts()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setLong, record.getEnds()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getSchedulePolicy()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, record.getTableGroupName()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setLong, record.getScheduleId()); + return MetaDbUtil.update(UPDATE_TABLE_SCHEDULED_JOBS_BY_SCHEDULED_ID, params, connection); } catch (Exception e) { throw logAndThrow("Failed to insert into " + SCHEDULED_JOBS, "insert into", e); } @@ -140,7 +203,7 @@ public int rename(String newTableName, String newScheduleName, String schemaName MetaDbUtil.setParameter(4, params, ParameterMethod.setString, oldScheduleName); return MetaDbUtil.update(RENAME_TABLE_BY_TABLE_NAME, params, connection); } catch (Exception e) { - throw logAndThrow("Failed to update " + SCHEDULED_JOBS, "rename", e); + throw logAndThrow("Failed to update " + SCHEDULED_JOBS, "update scheduled job info by scheduled_id", e); } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/sync/GmsSyncDataSource.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/sync/GmsSyncDataSource.java index 3fbb13ad6..e4fea1ea4 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/sync/GmsSyncDataSource.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/sync/GmsSyncDataSource.java @@ -26,7 +26,7 @@ public class GmsSyncDataSource extends AbstractLifecycle { - private static final MessageFormat MYSQL_URL_FORMAT = new MessageFormat("jdbc:mysql://{0}:{1}/{2}"); + private static final MessageFormat MYSQL_URL_FORMAT = new MessageFormat("jdbc:mysql://{0}:{1}/{2}?useSSL=false"); private static final String SYNC_PASSWORD = "none"; private static final String SYNC_DATABASE = "sync"; diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/CreateDbInfo.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/CreateDbInfo.java index ce81a0e04..4c3354259 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/CreateDbInfo.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/CreateDbInfo.java @@ -75,6 +75,15 @@ public class CreateDbInfo { */ protected GroupLocator groupLocator; + protected List createdDbHookFuncList = new ArrayList<>(); + + /** + * The hook function callback to refresh memory only alter finishing creating db + */ + public interface CreatedDbHookFunc { + void handle(Long newAddedDbInfoId); + } + public CreateDbInfo() { } @@ -201,4 +210,13 @@ public Boolean getDefaultSingle() { public void setDefaultSingle(Boolean defaultSingle) { this.defaultSingle = defaultSingle; } + + public List getCreatedDbHookFuncList() { + return createdDbHookFuncList; + } + + public void setCreatedDbHookFuncList( + List createdDbHookFuncList) { + this.createdDbHookFuncList = createdDbHookFuncList; + } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DbGroupInfoManager.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DbGroupInfoManager.java index 8963a8c29..80aa30110 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DbGroupInfoManager.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DbGroupInfoManager.java @@ -59,12 +59,15 @@ public static DbGroupInfoManager getInstance() { @Override protected void doInit() { + if (!ConfigDataMode.isPolarDbX()) { + return; + } for (DbInfoRecord dbInfo : DbInfoManager.getInstance().getDbInfoList()) { reloadGroupsOfDb(dbInfo.dbName); } } - private void reloadGroupsOfDb(String schema) { + public void reloadGroupsOfDb(String schema) { try (Connection conn = MetaDbDataSource.getInstance().getConnection()) { DbGroupInfoAccessor dbGroupInfoAccessor = new DbGroupInfoAccessor(); dbGroupInfoAccessor.setConnection(conn); @@ -126,7 +129,10 @@ public void onDbInfoChange(Map added, Map groupInfoRecordMap) { + cache.put(schema, groupInfoRecordMap); } public void onDbTopologyListener(String dataId) { diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DbTopologyManager.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DbTopologyManager.java index c94b0ff21..74a0e9a7f 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DbTopologyManager.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DbTopologyManager.java @@ -17,7 +17,6 @@ package com.alibaba.polardbx.gms.topology; import com.alibaba.polardbx.common.Engine; -import com.alibaba.polardbx.common.exception.NotSupportException; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.properties.ConnectionProperties; @@ -70,6 +69,7 @@ import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -82,6 +82,9 @@ import java.util.function.Predicate; import java.util.stream.Collectors; +import static com.alibaba.polardbx.common.cdc.ICdcManager.DEFAULT_DDL_VERSION_ID; +import static com.alibaba.polardbx.gms.topology.SystemDbHelper.SYS_SCHEMA_DB_NAME; + /** * @author chenghui.lch */ @@ -291,6 +294,14 @@ public static long createLogicalDb(CreateDbInfo createDbInfo) { // ---- check if logical db exists ---- String dbName = createDbInfo.dbName; + + // check db name + if (Arrays.stream(SYS_SCHEMA_DB_NAME).anyMatch(dbName::equalsIgnoreCase)) { + // throw exception + throw new TddlRuntimeException(ErrorCode.ERR_GMS_GENERIC, + String.format("Can't create database '%s', as it is a keyword", dbName)); + } + boolean createIfNotExist = createDbInfo.isCreateIfNotExists; DbInfoAccessor dbInfoAccessor = new DbInfoAccessor(); dbInfoAccessor.setConnection(metaDbConn); @@ -324,7 +335,7 @@ public static long createLogicalDb(CreateDbInfo createDbInfo) { ts = System.currentTimeMillis() << BITS_LOGICAL_TIME; dropLogicalDbWithConn(dbName, true, metaDbConn, metaDbLockConn, createDbInfo.socketTimeout, ts, - false, false); + false, false, DEFAULT_DDL_VERSION_ID); hasDbConfig = false; } } @@ -369,6 +380,9 @@ public static long createLogicalDb(CreateDbInfo createDbInfo) { // sync other node to reload dbInfo quickly MetaDbConfigManager.getInstance().sync(MetaDbDataIdBuilder.getDbInfoDataId()); + // process the hook func list for new created db(like cdc/locality e.g) + handleHookFuncList(createDbInfo, dbId); + // release meta db lock LockUtil.releaseMetaDbLockByCommit(metaDbLockConn); return dbId; @@ -377,9 +391,18 @@ public static long createLogicalDb(CreateDbInfo createDbInfo) { } } + private static void handleHookFuncList(CreateDbInfo createDbInfo, long dbId) { + List createdDbHookFuncList = createDbInfo.getCreatedDbHookFuncList(); + for (int i = 0; i < createdDbHookFuncList.size(); i++) { + CreateDbInfo.CreatedDbHookFunc hookFunc = createdDbHookFuncList.get(i); + hookFunc.handle(dbId); + } + } + protected static void dropLogicalDbWithConn(String dbName, boolean isDropIfExists, Connection metaDbConn, Connection metaDbLockConn, long socketTimeout, long ts, - boolean allowDropForce, boolean reservePhyDb) throws SQLException { + boolean allowDropForce, boolean reservePhyDb, long versionId) + throws SQLException { // acquire MetaDb Lock by for update, to avoiding concurrent create & drop databases metaDbLockConn.setAutoCommit(false); @@ -468,14 +491,14 @@ protected static void dropLogicalDbWithConn(String dbName, boolean isDropIfExist // ----- cleanup all schema meta infos & configs if (DbTopologyManager.schemaMetaCleaner != null) { - schemaMetaCleaner.clearSchemaMeta(dbName, metaDbConn); + schemaMetaCleaner.clearSchemaMeta(dbName, metaDbConn, versionId); } // clear group_detail_info List allGrpNames = getGroupNamesFromMetaDb(metaDbConn, instId, dbName); // ---- remove topology configs - removeDbTopologyConfig(dbName, metaDbConn); + removeDbTopologyConfig(dbName, metaDbConn, versionId); metaDbConn.commit(); // refresh local group topology of db topology manager of memory @@ -505,7 +528,7 @@ public static void dropLogicalDb(DropDbInfo dropDbInfo) { Connection metaDbLockConn = MetaDbDataSource.getInstance().getConnection()) { dropLogicalDbWithConn(dbName, isDropIfExists, metaDbConn, metaDbLockConn, socketTimeout, dropDbInfo.getTs(), - dropDbInfo.isAllowDropForce(), dropDbInfo.isReservePhyDb()); + dropDbInfo.isAllowDropForce(), dropDbInfo.isReservePhyDb(), dropDbInfo.getVersionId()); // release meta db lock LockUtil.releaseMetaDbLockByCommit(metaDbLockConn); @@ -1130,7 +1153,7 @@ private static String getJdbcConnPropsFromAtomConnPropsForGroup(long socketTimeo * remove all the topology config for db * Notice: this method must call after finishing ddl of drop all phy dbs */ - public static void removeDbTopologyConfig(String dbName, Connection conn) { + public static void removeDbTopologyConfig(String dbName, Connection conn, long versionId) { try { diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DropDbInfo.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DropDbInfo.java index 620953c28..f3ab382d1 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DropDbInfo.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/DropDbInfo.java @@ -38,6 +38,8 @@ public class DropDbInfo { */ private boolean reservePhyDb = false; + private long versionId; + public String getDbName() { return dbName; } @@ -85,4 +87,12 @@ public boolean isReservePhyDb() { public void setReservePhyDb(boolean reservePhyDb) { this.reservePhyDb = reservePhyDb; } + + public long getVersionId() { + return versionId; + } + + public void setVersionId(long versionId) { + this.versionId = versionId; + } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/SchemaMetaCleaner.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/SchemaMetaCleaner.java index 807d8c197..ca7547e64 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/SchemaMetaCleaner.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/SchemaMetaCleaner.java @@ -22,5 +22,5 @@ * @author chenghui.lch */ public interface SchemaMetaCleaner { - void clearSchemaMeta(String schemaName, Connection metaDbConn); + void clearSchemaMeta(String schemaName, Connection metaDbConn, long versionId); } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/ServerInfoAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/ServerInfoAccessor.java index 7b7784cc6..d08193b60 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/ServerInfoAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/ServerInfoAccessor.java @@ -20,6 +20,7 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; @@ -30,6 +31,7 @@ import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.google.common.collect.Maps; +import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -98,6 +100,10 @@ public class ServerInfoAccessor extends AbstractAccessor { "select distinct inst_id from " + SERVER_INFO_TABLE + " where status!=2 and inst_type=" + ServerInfoRecord.INST_TYPE_HTAP_SLAVE; + private static final String SELECT_COLUMNAR_INSTS = + "select distinct inst_id from " + SERVER_INFO_TABLE + " where status!=2 and inst_type=" + + ServerInfoRecord.INST_TYPE_COLUMNAR_SLAVE; + private static final String DELETE_REMOVED_RO_SERVER_INFOS = "delete from `" + SERVER_INFO_TABLE + "` where status=2 and inst_type!=0 and inst_id = ?"; @@ -191,6 +197,29 @@ public Set getAllHTAPReadOnlyInstIdList() { return allHtapInstIdList; } + public synchronized Set loadColumnarInstIdAndUpdate(Connection connection) { + Set allColumnarInstIds = new HashSet<>(); + try { + Set allColumnarInstIdList = new HashSet<>(); + try (PreparedStatement ps = connection.prepareStatement(SELECT_COLUMNAR_INSTS)) { + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + String instId = rs.getString(1); + allColumnarInstIdList.add(instId); + } + } + } catch (Throwable ex) { + MetaDbLogUtil.META_DB_LOG.error(ex); + throw GeneralUtil.nestedException(ex); + } + return allColumnarInstIdList; + } finally { + if (allColumnarInstIds.size() == 0) { + DynamicConfig.getInstance().existColumnarNodes(false); + } + } + } + public List getAllRemovedColumnarReadOnlyInstIdList() { String instId = null; List allRemovedRoInstIdList = new ArrayList<>(); diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/ServerInstIdManager.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/ServerInstIdManager.java index d43a25cab..4483ddc1f 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/ServerInstIdManager.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/ServerInstIdManager.java @@ -70,6 +70,7 @@ protected void doInit() { public void reload() { loadMasterInstId(); loadAllInstIdAndStorageIdSet(); + loadColumnarInstIdAndUpdate(); int instType = loadAllHtapInstIds(); initInstType(instType); //here register the new storageIds listener after load the new learner InstId. @@ -139,6 +140,16 @@ public synchronized int loadAllHtapInstIds() { } } + public synchronized void loadColumnarInstIdAndUpdate() { + ServerInfoAccessor serverInfoAccessor = new ServerInfoAccessor(); + try (Connection connection = MetaDbDataSource.getInstance().getConnection()) { + serverInfoAccessor.loadColumnarInstIdAndUpdate(connection); + } catch (Throwable ex) { + MetaDbLogUtil.META_DB_LOG.error(ex); + throw GeneralUtil.nestedException(ex); + } + } + public List getSlaveStorageInfosByMasterStorageInstId(String masterStorageId) { try (Connection metaDbConn = MetaDbDataSource.getInstance().getConnection()) { StorageInfoAccessor storageInfoAccessor = new StorageInfoAccessor(); @@ -192,5 +203,4 @@ public String getInstId() { public int getInstType() { return instType; } - } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/SystemDbHelper.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/SystemDbHelper.java index b61d9b81b..98b2c3bb1 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/SystemDbHelper.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/SystemDbHelper.java @@ -25,6 +25,8 @@ import javax.sql.DataSource; import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; /** * @author chenghui.lch @@ -56,6 +58,7 @@ public class SystemDbHelper { ""; + public static final String[] SYS_SCHEMA_DB_NAME = {"mysql", "performance_schema", "metadb"}; // Properties for Cdc Db public static final String CDC_DB_NAME = "__cdc__"; @@ -65,6 +68,14 @@ public class SystemDbHelper { {INFO_SCHEMA_DB_NAME, CDC_DB_NAME, DEFAULT_DB_NAME, DEFAULT_META_DB_NAME}; private final static String[] buildInDbExcludeCdc = {INFO_SCHEMA_DB_NAME, DEFAULT_DB_NAME}; + public static List getAllBuildInDbNameList() { + List buildInDbNameList = new ArrayList<>(); + for (int i = 0; i < buildInDb.length; i++) { + buildInDbNameList.add(buildInDb[i]); + } + return buildInDbNameList; + } + public static void checkOrCreateDefaultDb(MetaDbDataSource metaDbDs) { String dbName = DEFAULT_DB_NAME; String phyDbName = DEFAULT_DB_PHY_NAME; diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/VariableConfigAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/VariableConfigAccessor.java index eea52f7ed..b67fe3e73 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/VariableConfigAccessor.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/topology/VariableConfigAccessor.java @@ -67,6 +67,28 @@ public void addVariableConfigs(List variableConfigRecords) } } + public void addVariableConfigs(String instId, Properties properties, boolean notify) { + try (PreparedStatement preparedStatement = this.connection.prepareStatement(INSERT_IGNORE_VARIABLE_CONFIGS)) { + for (String propName : properties.stringPropertyNames()) { + String propVal = properties.getProperty(propName); + preparedStatement.setString(1, instId); + preparedStatement.setString(2, propName); + preparedStatement.setString(3, propVal); + preparedStatement.setString(4, ""); + preparedStatement.addBatch(); + } + preparedStatement.executeBatch(); + } catch (Throwable e) { + logger.error("Failed to query the system table '" + VARIABLE_CONFIG_TABLE + "'", e); + throw new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, "query", + VARIABLE_CONFIG_TABLE, e.getMessage()); + } + + if (notify) { + MetaDbConfigManager.getInstance().notify(MetaDbDataIdBuilder.getVariableConfigDataId(instId), connection); + } + } + private List queryBySql(String sql, Map params) { try { return MetaDbUtil.query(sql, params, VariableConfigRecord.class diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ttl/TtlInfoAccessor.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ttl/TtlInfoAccessor.java new file mode 100644 index 000000000..287596e82 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ttl/TtlInfoAccessor.java @@ -0,0 +1,519 @@ +package com.alibaba.polardbx.gms.ttl; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.gms.metadb.accessor.AbstractAccessor; +import com.alibaba.polardbx.gms.util.DdlMetaLogUtil; +import com.alibaba.polardbx.gms.util.MetaDbUtil; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author chenghui.lch + */ +public class TtlInfoAccessor extends AbstractAccessor { + + private static final Logger logger = LoggerFactory.getLogger(TtlInfoAccessor.class); + + private static final String ALL_COLUMNS = + "`id`,`gmt_created`,`gmt_modified`" + + ",`table_schema`,`table_name`,`ttl_status`,`ttl_expr`,`ttl_filter`,`ttl_interval`,`ttl_unit`,`ttl_col`,`ttl_tz`,`ttl_cron`,`ttl_binlog`" + + ",`arc_kind`,`arc_status`,`arc_tmp_tbl_schema`,`arc_tmp_tbl_name`,`arc_tbl_schema`, `arc_tbl_name`" + + ",`arc_part_mode`,`arc_part_interval`,`arc_part_unit`,`arc_pre_part_cnt`,`arc_post_part_cnt`" + + ",`extra`"; + private static final String ALL_VALUES = "(" + + "null,now(),now()" + + ",?,?,?,?,?,?,?,?,?,?,?" + + ",?,?,?,?,?,?" + + ",?,?,?,?,?" + + ",?" + + ")"; + + private static final String ALL_COLUMNS_SET = "" + + "`gmt_modified`=now()," + + + "`table_schema`=?," + + "`table_name`=?," + + + "`ttl_status`=?," + + "`ttl_expr`=?," + + "`ttl_filter`=?," + + "`ttl_interval`=?," + + "`ttl_unit`=?," + + "`ttl_col`=?," + + "`ttl_tz`=?," + + "`ttl_cron`=?," + + "`ttl_binlog`=?," + + + "`arc_kind`=?," + + "`arc_status`=?," + + "`arc_tmp_tbl_schema`=?," + + "`arc_tmp_tbl_name`=?," + + "`arc_tbl_schema`=?," + + "`arc_tbl_name`=?," + + + "`arc_part_mode`=?," + + "`arc_part_interval`=?," + + "`arc_part_unit`=?," + + "`arc_pre_part_cnt`=?," + + "`arc_post_part_cnt`=?," + + + "`extra`=?"; + + private static final String INSERT_TTL_INFO = + "insert into ttl_info (" + ALL_COLUMNS + ") VALUES " + ALL_VALUES; + + private static final String REPLACE_TTL_INFO = + "replace into ttl_info (" + ALL_COLUMNS + ") VALUES " + ALL_VALUES; + + private static final String DELETE_TTL_INFO_BY_DB_TB = "delete from ttl_info " + + "where table_schema=? and table_name=?"; + + private static final String DELETE_TTL_INFO_BY_DB = "delete from ttl_info " + + "where table_schema=?"; + + private static final String SELECT_TTL_INFO_BY_DB_TB = "select " + + ALL_COLUMNS + + " from ttl_info" + + " where table_schema=? and table_name=?"; + + private static final String SELECT_TTL_INFO_BY_ARC_DB_ARC_TB = "select " + + ALL_COLUMNS + + " from ttl_info" + + " where arc_tbl_schema=? and arc_tbl_name=?"; + + private static final String SELECT_TTL_INFO_BY_ARC_TMP_DB_ARC_TMP_TB = "select " + + ALL_COLUMNS + + " from ttl_info" + + " where arc_tmp_tbl_schema=? and arc_tmp_tbl_name=?"; + + private static final String SELECT_TTL_INFO_BY_DB = "select " + + ALL_COLUMNS + + " from ttl_info" + + " where table_schema=?"; + + private static final String SELECT_ALL_TTL_INFO_LIST = "select " + + ALL_COLUMNS + + " from ttl_info" + + " order by table_schema, table_name"; + + private static final String UPDATE_ARC_TBL_TTL_INFO_BY_DB_TB = + "update ttl_info set arc_kind=?,arc_tbl_schema=?,arc_tbl_name=?,arc_tmp_tbl_schema=?,arc_tmp_tbl_name=? where table_schema=? and table_name=?"; + + private static final String UPDATE_TTL_TBL_NAME_BY_DB_TB = + "update ttl_info set table_schema=?,table_name=? where table_schema=? and table_name=?"; + + private static final String UPDATE_TTL_INFO_BY_ID = "update ttl_info set " + ALL_COLUMNS_SET + " where `id`=?"; + + private static final String UPDATE_TTL_INFO_BY_DB_TB = + "update ttl_info set " + ALL_COLUMNS_SET + " where `table_schema`=? and `table_name`=?"; + + private static final String UNBIND_ARC_TBL_TTL_INFO_BY_ARC_DB_ARC_TB = + "update ttl_info set arc_kind=0,arc_tbl_schema=null,arc_tbl_name=null,arc_tmp_tbl_schema=null,arc_tmp_tbl_name=null where arc_tbl_schema=? and arc_tbl_name=?"; + + public TtlInfoRecord queryTtlInfoByDbAndTb(String tableSchema, String tableName) { + + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + + List ttlInfoRecords = + MetaDbUtil.query(SELECT_TTL_INFO_BY_DB_TB, params, TtlInfoRecord.class, connection); + DdlMetaLogUtil.logSql(SELECT_TTL_INFO_BY_DB_TB, params); + + if (ttlInfoRecords.isEmpty()) { + return null; + } + return ttlInfoRecords.get(0); + } catch (Exception e) { + logAndThrow(e.getMessage(), "query one ttl_info", e); + } + return null; + } + + public TtlInfoRecord queryTtlInfoByArcDbAndArcTb(String arcTableSchema, String arcTableName) { + + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, arcTableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, arcTableName); + + List ttlInfoRecords = + MetaDbUtil.query(SELECT_TTL_INFO_BY_ARC_DB_ARC_TB, params, TtlInfoRecord.class, connection); + DdlMetaLogUtil.logSql(SELECT_TTL_INFO_BY_ARC_DB_ARC_TB, params); + + if (ttlInfoRecords.isEmpty()) { + return null; + } + return ttlInfoRecords.get(0); + } catch (Exception e) { + logAndThrow(e.getMessage(), "query one ttl_info", e); + } + return null; + } + + public TtlInfoRecord queryTtlInfoByArcTmpDbAndArcTmpTb(String arcTmpTableSchema, String arcTmpTableName) { + + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, arcTmpTableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, arcTmpTableName); + + List ttlInfoRecords = + MetaDbUtil.query(SELECT_TTL_INFO_BY_ARC_TMP_DB_ARC_TMP_TB, params, TtlInfoRecord.class, connection); + DdlMetaLogUtil.logSql(SELECT_TTL_INFO_BY_ARC_TMP_DB_ARC_TMP_TB, params); + + if (ttlInfoRecords.isEmpty()) { + return null; + } + return ttlInfoRecords.get(0); + } catch (Exception e) { + logAndThrow(e.getMessage(), "query one ttl_info by arc_tmp_tbl_schema and arc_tmp_tbl", e); + } + return null; + } + + public List queryTtlInfoListByDb(String tableSchema) { + + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + + List ttlInfoRecords = + MetaDbUtil.query(SELECT_TTL_INFO_BY_DB, params, TtlInfoRecord.class, connection); + DdlMetaLogUtil.logSql(SELECT_TTL_INFO_BY_DB, params); + + return ttlInfoRecords; + } catch (Exception e) { + logAndThrow(e.getMessage(), "query ttl_infos by db", e); + } + return null; + } + + public List queryAllTtlInfoList() { + + try { + Map params = new HashMap<>(); + List ttlInfoRecords = + MetaDbUtil.query(SELECT_ALL_TTL_INFO_LIST, params, TtlInfoRecord.class, connection); + DdlMetaLogUtil.logSql(SELECT_ALL_TTL_INFO_LIST, params); + return ttlInfoRecords; + } catch (Exception e) { + logAndThrow(e.getMessage(), "query all ttl_infosb", e); + } + return null; + } + + public int insertNewTtlInfo(TtlInfoRecord ttlInfo) { + int res = -1; + try { + + Map params = new HashMap<>(); + + Integer paramIndex = 0; + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTableSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTableName()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlStatus()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlExpr()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlFilter()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlInterval()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlUnit()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlCol()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlTimezone()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlCron()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlBinlog()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcKind()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcStatus()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTmpTblSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTmpTblName()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTblSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTblName()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartMode()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartInterval()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartUnit()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPrePartCnt()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPostPartCnt()); + + JSONObject extra = new JSONObject(); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, extra.toJSONString()); + + res = MetaDbUtil.insert(INSERT_TTL_INFO, params, connection); + DdlMetaLogUtil.logSql(INSERT_TTL_INFO, params); + } catch (Exception e) { + logAndThrow(e.getMessage(), "add ttl_info", e); + } + + return res; + } + + public int replaceTtlInfo(TtlInfoRecord ttlInfo) { + int res = -1; + try { + + Map params = new HashMap<>(); + + Integer paramIndex = 0; + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTableSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTableName()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlStatus()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlExpr()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlFilter()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlInterval()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlUnit()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlCol()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlTimezone()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlCron()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlBinlog()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcKind()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcStatus()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTmpTblSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTmpTblName()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTblSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTblName()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartMode()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartInterval()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartUnit()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPrePartCnt()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPostPartCnt()); + + JSONObject extra = new JSONObject(); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, extra.toJSONString()); + + res = MetaDbUtil.insert(REPLACE_TTL_INFO, params, connection); + DdlMetaLogUtil.logSql(REPLACE_TTL_INFO, params); + } catch (Exception e) { + logAndThrow(e.getMessage(), "replace ttl_info", e); + } + + return res; + } + + public int updateTtlInfoByDbNameAndTbName(TtlInfoRecord ttlInfo, String ttlTblSchema, String ttlTblName) { + int res = -1; + try { + + Map params = new HashMap<>(); + + Integer paramIndex = 0; + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTableSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTableName()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlStatus()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlExpr()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlFilter()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlInterval()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlUnit()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlCol()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlTimezone()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlCron()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlBinlog()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcKind()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcStatus()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTmpTblSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTmpTblName()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTblSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTblName()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartMode()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartInterval()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartUnit()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPrePartCnt()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPostPartCnt()); + + JSONObject extra = new JSONObject(); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, extra.toJSONString()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlTblSchema); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlTblName); + + res = MetaDbUtil.insert(UPDATE_TTL_INFO_BY_DB_TB, params, connection); + DdlMetaLogUtil.logSql(UPDATE_TTL_INFO_BY_DB_TB, params); + } catch (Exception e) { + logAndThrow(e.getMessage(), "update ttl_info by db.tb", e); + } + + return res; + } + + public int updateTtlInfoById(TtlInfoRecord ttlInfo, Long id) { + int res = -1; + try { + + Map params = new HashMap<>(); + + Integer paramIndex = 0; + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTableSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTableName()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlStatus()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlExpr()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlFilter()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlInterval()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlUnit()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlCol()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlTimezone()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getTtlCron()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getTtlBinlog()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcKind()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcStatus()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTmpTblSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTmpTblName()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTblSchema()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlInfo.getArcTblName()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartMode()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartInterval()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPartUnit()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPrePartCnt()); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, ttlInfo.getArcPostPartCnt()); + + JSONObject extra = new JSONObject(); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, extra.toJSONString()); + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setLong, id); + + res = MetaDbUtil.update(UPDATE_TTL_INFO_BY_ID, params, connection); + DdlMetaLogUtil.logSql(UPDATE_TTL_INFO_BY_ID, params); + } catch (Exception e) { + logAndThrow(e.getMessage(), "update ttl_info by id", e); + } + + return res; + } + + public int deleteTtlInfoByDbAndTb(String tableSchema, String tableName) { + int res = -1; + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, tableName); + + res = MetaDbUtil.delete(DELETE_TTL_INFO_BY_DB_TB, params, connection); + DdlMetaLogUtil.logSql(DELETE_TTL_INFO_BY_DB_TB, params); + return res; + } catch (Exception e) { + logAndThrow(e.getMessage(), "query one ttl_info by tb", e); + } + return res; + } + + public int deleteByDbName(String tableSchema) { + int res = -1; + try { + Map params = new HashMap<>(); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, tableSchema); + + res = MetaDbUtil.delete(DELETE_TTL_INFO_BY_DB, params, connection); + DdlMetaLogUtil.logSql(DELETE_TTL_INFO_BY_DB, params); + return res; + } catch (Exception e) { + logAndThrow(e.getMessage(), "delete ttl_infos by db", e); + } + return res; + } + +// public int updateArcTableInfoByByDbAndTb(String artTblSchema, String arcTblName, +// String arcTmpTblSchema, String arcTmpTblName, +// String ttlTblSchema, String ttlTblName) { +// int res = -1; +// try { +// Map params = new HashMap<>(); +// MetaDbUtil.setParameter(1, params, ParameterMethod.setString, artTblSchema); +// MetaDbUtil.setParameter(2, params, ParameterMethod.setString, arcTblName); +// MetaDbUtil.setParameter(3, params, ParameterMethod.setString, arcTmpTblSchema); +// MetaDbUtil.setParameter(4, params, ParameterMethod.setString, arcTmpTblName); +// MetaDbUtil.setParameter(5, params, ParameterMethod.setString, ttlTblSchema); +// MetaDbUtil.setParameter(6, params, ParameterMethod.setString, ttlTblName); +// +// res = MetaDbUtil.delete(UPDATE_ARC_TBL_TTL_INFO_BY_DB_TB, params, connection); +// DdlMetaLogUtil.logSql(UPDATE_ARC_TBL_TTL_INFO_BY_DB_TB, params); +// return res; +// } catch (Exception e) { +// logAndThrow(e.getMessage(), "update ttl_infos by db and tb", e); +// } +// return res; +// } + + public int updateArcTableInfoByByDbAndTb(Integer arcKind, + String arcTblSchema, String arcTblName, + String arcTmpTblSchema, String arcTmpTblName, + String ttlTblSchema, String ttlTblName) { + int res = -1; + try { + Map params = new HashMap<>(); + Integer paramIndex = 0; + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setInt, arcKind); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, arcTblSchema); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, arcTblName); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, arcTmpTblSchema); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, arcTmpTblName); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlTblSchema); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlTblName); + + res = MetaDbUtil.delete(UPDATE_ARC_TBL_TTL_INFO_BY_DB_TB, params, connection); + DdlMetaLogUtil.logSql(UPDATE_ARC_TBL_TTL_INFO_BY_DB_TB, params); + return res; + } catch (Exception e) { + logAndThrow(e.getMessage(), "update ttl_infos by db and tb", e); + } + return res; + } + + public int updateTtlTableNameByDbAndTb(String newTblSchema, String newTblName, + String ttlTblSchema, String ttlTblName) { + int res = -1; + try { + Map params = new HashMap<>(); + Integer paramIndex = 0; + + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, newTblSchema); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, newTblName); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlTblSchema); + MetaDbUtil.setParameter(++paramIndex, params, ParameterMethod.setString, ttlTblName); + + res = MetaDbUtil.delete(UPDATE_TTL_TBL_NAME_BY_DB_TB, params, connection); + DdlMetaLogUtil.logSql(UPDATE_TTL_TBL_NAME_BY_DB_TB, params); + return res; + } catch (Exception e) { + logAndThrow(e.getMessage(), "update ttl tbl name by db and tb", e); + } + return res; + } + + public void unBindingByArchiveTableName(String archiveTableSchema, String archiveTableName) { + Map params = new HashMap<>(2); + MetaDbUtil.setParameter(1, params, ParameterMethod.setString, archiveTableSchema); + MetaDbUtil.setParameter(2, params, ParameterMethod.setString, archiveTableName); + + try { + DdlMetaLogUtil.logSql(UNBIND_ARC_TBL_TTL_INFO_BY_ARC_DB_ARC_TB, params); + MetaDbUtil.update(UNBIND_ARC_TBL_TTL_INFO_BY_ARC_DB_ARC_TB, params, connection); + } catch (Exception e) { + logAndThrow(e.getMessage(), "unbind ttl_info by arc_db and arc_tb", e); + } + } + + private TddlRuntimeException logAndThrow(String errMsg, String action, Exception e) { + logger.error(errMsg, e); + return new TddlRuntimeException(ErrorCode.ERR_GMS_ACCESS_TO_SYSTEM_TABLE, e, action, + "ttl_info", e.getMessage()); + } + +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ttl/TtlInfoRecord.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ttl/TtlInfoRecord.java new file mode 100644 index 000000000..92fd6ccb2 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ttl/TtlInfoRecord.java @@ -0,0 +1,413 @@ +package com.alibaba.polardbx.gms.ttl; + +import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; +import com.alibaba.polardbx.gms.partition.ExtraFieldJSON; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Date; + +/** + * @author chenghui.lch + */ +public class TtlInfoRecord implements SystemTableRecord { + + public static final String TTL_STATUS_DISABLE_SCHEDULE_STR_VAL = "OFF"; + public static final String TTL_STATUS_ENABLE_SCHEDULE_STR_VAL = "ON"; + + public static final int TTL_STATUS_DISABLE_SCHEDULE = 0; + public static final int TTL_STATUS_ENABLE_SCHEDULE = 1; + public static final int TTL_BINLOG_CLOSE_BINLOG_DURING_CLEANING_DATA = 0; + public static final int TTL_BINLOG_OPEN_BINLOG_DURING_CLEANING_DATA = 1; + + public static final int ARCHIVE_KIND_UNDEF = 0;// ' ARCHIVE_KIND='' ' + public static final int ARCHIVE_KIND_COLUMNAR = 1;// ' ARCHIVE_KIND='COLUMNAR' ' + public static final int ARCHIVE_KIND_PARTITION = 2;// ' ARCHIVE_KIND='PARTITION' ' + public static final int ARCHIVE_KIND_SUBPARTITION = 3;// ' ARCHIVE_KIND='SUBPARTITION' ' + + public static final int ARCHIVE_STATUS_DISABLE_OSS_ARCHIVE = 0; + public static final int ARCHIVE_STATUS_ENABLE_OSS_ARCHIVE = 1; + + public static final String TTL_UNIT_YEAR = "YEAR"; + public static final String TTL_UNIT_MONTH = "MONTH"; + public static final String TTL_UNIT_DAY = "DAY"; + public static final String TTL_UNIT_HOUR = "HOUR"; + public static final String TTL_UNIT_MINUTE = "MINUTE"; + public static final String TTL_UNIT_SECOND = "SECOND"; + + public static final Integer ARC_PART_MODE_NORMAL = 0; + + private Long id; + private Date gmtCreated; + private Date gmtModified; + + private String tableSchema; + private String tableName; + + /** + * 0-disable ttl schedule,1-enable ttl schedule + */ + private Integer ttlStatus; + private String ttlExpr; + private String ttlFilter; + private String ttlCol; + private Integer ttlInterval; + /** + * The time unit code of ttl task + *
+     *     0:year
+     *     1:month
+     *     2:day
+     *     3:hour
+     *     4:minute
+     *     5:second
+     * 
+ */ + private Integer ttlUnit; + private String ttlTimezone; + private String ttlCron; + /** + * 0-disable gen binlog, 1-enable gen binlog + */ + private Integer ttlBinlog; + + /** + *
+     *  0-arc by oss tbl;
+     *  1-arc by columnar index;
+     *  2-arc by time-based range-part;
+     *  3-arc by time-based range-subpart;
+     *  4-arc by self-def-range-part.
+     * 
+ */ + private Integer arcKind; + + /** + * The mode of arc part generation + */ + private Integer arcPartMode = 0; + /** + * The interval of arc part generation + */ + private Integer arcPartInterval = 1; + /** + * The time unit code of arc part generation + *
+     *     0:year
+     *     1:month
+     *     2:day
+     *     3:hour
+     *     4:minute
+     *     5:second
+     * 
+ */ + private Integer arcPartUnit = 1; + /** + * The previous allocated partition counts of ttl-tmp for future + */ + private Integer arcPrePartCnt = 0; + /** + * The post allocated partition counts of ttl-tmp base on ttl-col min value for past + */ + private Integer arcPostPartCnt = 0; + + /** + * 0-enable oss arc schedule, + * 1-disable oss arc schedule + */ + private Integer arcStatus; + private String arcTmpTblSchema; + private String arcTmpTblName; + + private String arcTblSchema; + private String arcTblName; + + private ExtraFieldJSON extra; + + public TtlInfoRecord() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Date getGmtCreated() { + return gmtCreated; + } + + public void setGmtCreated(Date gmtCreated) { + this.gmtCreated = gmtCreated; + } + + public Date getGmtModified() { + return gmtModified; + } + + public void setGmtModified(Date gmtModified) { + this.gmtModified = gmtModified; + } + + public String getTableSchema() { + return tableSchema; + } + + public void setTableSchema(String tableSchema) { + this.tableSchema = tableSchema; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public Integer getTtlStatus() { + return ttlStatus; + } + + public void setTtlStatus(Integer ttlStatus) { + this.ttlStatus = ttlStatus; + } + + public String getTtlExpr() { + return ttlExpr; + } + + public void setTtlExpr(String ttlExpr) { + this.ttlExpr = ttlExpr; + } + + public String getTtlCol() { + return ttlCol; + } + + public void setTtlCol(String ttlCol) { + this.ttlCol = ttlCol; + } + + public Integer getTtlInterval() { + return ttlInterval; + } + + public void setTtlInterval(Integer ttlInterval) { + this.ttlInterval = ttlInterval; + } + + public Integer getTtlUnit() { + return ttlUnit; + } + + public void setTtlUnit(Integer ttlUnit) { + this.ttlUnit = ttlUnit; + } + + public String getTtlTimezone() { + return ttlTimezone; + } + + public void setTtlTimezone(String ttlTimezone) { + this.ttlTimezone = ttlTimezone; + } + + public String getTtlCron() { + return ttlCron; + } + + public void setTtlCron(String ttlCron) { + this.ttlCron = ttlCron; + } + + public Integer getTtlBinlog() { + return ttlBinlog; + } + + public void setTtlBinlog(Integer ttlBinlog) { + this.ttlBinlog = ttlBinlog; + } + + public Integer getArcStatus() { + return arcStatus; + } + + public void setArcStatus(Integer arcStatus) { + this.arcStatus = arcStatus; + } + + public String getArcTmpTblSchema() { + return arcTmpTblSchema; + } + + public void setArcTmpTblSchema(String arcTmpTblSchema) { + this.arcTmpTblSchema = arcTmpTblSchema; + } + + public String getArcTmpTblName() { + return arcTmpTblName; + } + + public void setArcTmpTblName(String arcTmpTblName) { + this.arcTmpTblName = arcTmpTblName; + } + + public Integer getArcPrePartCnt() { + return arcPrePartCnt; + } + + public void setArcPrePartCnt(Integer arcPrePartCnt) { + this.arcPrePartCnt = arcPrePartCnt; + } + + public String getArcTblSchema() { + return arcTblSchema; + } + + public void setArcTblSchema(String arcTblSchema) { + this.arcTblSchema = arcTblSchema; + } + + public String getArcTblName() { + return arcTblName; + } + + public void setArcTblName(String arcTblName) { + this.arcTblName = arcTblName; + } + + public ExtraFieldJSON getExtra() { + return extra; + } + + public void setExtra(ExtraFieldJSON extra) { + this.extra = extra; + } + + public Integer getArcPostPartCnt() { + return arcPostPartCnt; + } + + public void setArcPostPartCnt(Integer arcPostPartCnt) { + this.arcPostPartCnt = arcPostPartCnt; + } + + public Integer getArcKind() { + return arcKind; + } + + public void setArcKind(Integer arcKind) { + this.arcKind = arcKind; + } + + public String getTtlFilter() { + return ttlFilter; + } + + public void setTtlFilter(String ttlFilter) { + this.ttlFilter = ttlFilter; + } + + public Integer getArcPartMode() { + return arcPartMode; + } + + public void setArcPartMode(Integer arcPartMode) { + this.arcPartMode = arcPartMode; + } + + public Integer getArcPartInterval() { + return arcPartInterval; + } + + public void setArcPartInterval(Integer arcPartInterval) { + this.arcPartInterval = arcPartInterval; + } + + public Integer getArcPartUnit() { + return arcPartUnit; + } + + public void setArcPartUnit(Integer arcPartUnit) { + this.arcPartUnit = arcPartUnit; + } + + @Override + public TtlInfoRecord fill(ResultSet rs) throws SQLException { + + this.id = rs.getLong("id"); + this.gmtCreated = rs.getTimestamp("gmt_created"); + this.gmtModified = rs.getTimestamp("gmt_modified"); + + this.tableSchema = rs.getString("table_schema"); + this.tableName = rs.getString("table_name"); + + this.ttlStatus = rs.getInt("ttl_status"); + this.ttlExpr = rs.getString("ttl_expr"); + this.ttlFilter = rs.getString("ttl_filter"); + this.ttlInterval = rs.getInt("ttl_interval"); + this.ttlUnit = rs.getInt("ttl_unit"); + this.ttlCol = rs.getString("ttl_col"); + this.ttlTimezone = rs.getString("ttl_tz"); + this.ttlCron = rs.getString("ttl_cron"); + this.ttlBinlog = rs.getInt("ttl_binlog"); + + this.arcKind = rs.getInt("arc_kind"); + this.arcStatus = rs.getInt("arc_status"); + this.arcTmpTblSchema = rs.getString("arc_tmp_tbl_schema"); + this.arcTmpTblName = rs.getString("arc_tmp_tbl_name"); + this.arcTblSchema = rs.getString("arc_tbl_schema"); + this.arcTblName = rs.getString("arc_tbl_name"); + + this.arcPartMode = rs.getInt("arc_part_mode"); + this.arcPartInterval = rs.getInt("arc_part_interval"); + this.arcPartUnit = rs.getInt("arc_part_unit"); + this.arcPrePartCnt = rs.getInt("arc_pre_part_cnt"); + this.arcPostPartCnt = rs.getInt("arc_post_part_cnt"); + + this.extra = ExtraFieldJSON.fromJson(rs.getString("extra")); + return this; + } + + public TtlInfoRecord copy() { + TtlInfoRecord newRec = new TtlInfoRecord(); + + newRec.setId(null); + newRec.setGmtCreated(this.gmtCreated); + newRec.setGmtModified(this.gmtModified); + + newRec.setTableSchema(this.tableSchema); + newRec.setTableName(this.tableName); + + newRec.setTtlStatus(this.ttlStatus); + newRec.setTtlExpr(this.ttlExpr); + newRec.setTtlFilter(this.ttlFilter); + newRec.setTtlInterval(this.ttlInterval); + newRec.setTtlUnit(this.ttlUnit); + newRec.setTtlCol(this.ttlCol); + newRec.setTtlTimezone(this.ttlTimezone); + newRec.setTtlCron(this.ttlCron); + newRec.setTtlBinlog(this.ttlBinlog); + + newRec.setArcKind(this.arcKind); + newRec.setArcStatus(this.arcStatus); + newRec.setArcTmpTblSchema(this.arcTmpTblSchema); + newRec.setArcTmpTblName(this.arcTmpTblName); + newRec.setArcTblSchema(this.arcTblSchema); + newRec.setArcTblName(this.arcTblName); + + newRec.setArcPartMode(this.arcPartMode); + newRec.setArcPartInterval(this.arcPartInterval); + newRec.setArcPartUnit(this.arcPartUnit); + newRec.setArcPrePartCnt(this.arcPrePartCnt); + newRec.setArcPostPartCnt(this.arcPostPartCnt); + + ExtraFieldJSON newJsonField = ExtraFieldJSON.fromJson(this.extra.toString()); + newRec.setExtra(newJsonField); + + return newRec; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ttl/TtlPartArcState.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ttl/TtlPartArcState.java new file mode 100644 index 000000000..c7d21257e --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/ttl/TtlPartArcState.java @@ -0,0 +1,144 @@ +package com.alibaba.polardbx.gms.ttl; + +import com.alibaba.polardbx.druid.util.StringUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author chenghui.lch + */ +public enum TtlPartArcState { + + /** + * means part data does no change from reusing part and to be redo archiving, + * the part having an archiving file, so not allow splitting part + */ + ARC_STATE_REREADY(6, "REREADY"), + + /** + * means part has been finished archiving at lease once, now is allowed inserting, not allow splitting part + */ + ARC_STATE_REUSING(5, "REUSING"), + + /** + * means part finished archiving, part data is truncated, not allow splitting part + */ + ARC_STATE_ARCHIVED(4, "ARCHIVED"), + + /** + * means part is running archiving, building archiving files, not allow splitting part + */ + ARC_STATE_ARCHIVING(3, "ARCHIVING"), + + /** + * means part data does no change, has no archiving file, allow splitting part + */ + ARC_STATE_READY(2, "READY"), + + /** + * means part has incremental data, allow splitting part + */ + ARC_STATE_USING(1, "USING"), + + /** + * means part must be empty, allow splitting part + */ + ARC_STATE_NO_USE(0, "NO_USE"); + + protected int arcState; + protected String arcStateName; + + TtlPartArcState(int arcState, String arcStateName) { + this.arcState = arcState; + this.arcStateName = arcStateName; + } + + public int getArcState() { + return arcState; + } + + public String getArcStateName() { + return arcStateName; + } + + public static TtlPartArcState getTtlPartArcStateByArcStateValue(int arcState) { + switch (arcState) { + case 0: + return TtlPartArcState.ARC_STATE_NO_USE; + case 1: + return TtlPartArcState.ARC_STATE_USING; + case 2: + return TtlPartArcState.ARC_STATE_READY; + case 3: + return TtlPartArcState.ARC_STATE_ARCHIVING; + case 4: + return TtlPartArcState.ARC_STATE_ARCHIVED; + case 5: + return TtlPartArcState.ARC_STATE_REUSING; + case 6: + return TtlPartArcState.ARC_STATE_REREADY; + default: + return TtlPartArcState.ARC_STATE_NO_USE; + } + } + + public static List toTtlArcStateNames(Collection ttlPartArcStateList) { + List names = new ArrayList<>(); + for (TtlPartArcState state : ttlPartArcStateList) { + names.add(state.getArcStateName()); + } + return names; + } + + public static Set ARC_STATE_SET_FOR_PERFORM_ARCHIVING = new HashSet<>(); + + static { + ARC_STATE_SET_FOR_PERFORM_ARCHIVING.add(TtlPartArcState.ARC_STATE_ARCHIVING); + ARC_STATE_SET_FOR_PERFORM_ARCHIVING.add(TtlPartArcState.ARC_STATE_ARCHIVED); + } + + public static Set ARC_STATE_SET_ALLOWED_TO_CONVERT_TO_USING = new HashSet<>(); + + static { + ARC_STATE_SET_ALLOWED_TO_CONVERT_TO_USING.add(TtlPartArcState.ARC_STATE_ARCHIVED); + ARC_STATE_SET_ALLOWED_TO_CONVERT_TO_USING.add(TtlPartArcState.ARC_STATE_READY); + ARC_STATE_SET_ALLOWED_TO_CONVERT_TO_USING.add(TtlPartArcState.ARC_STATE_REREADY); + } + + public static TtlPartArcState getTtlPartArcStateByArcStateName(String arcStateName) { + + if (StringUtils.isEmpty(arcStateName)) { + return TtlPartArcState.ARC_STATE_NO_USE; + } + + if (TtlPartArcState.ARC_STATE_NO_USE.getArcStateName().equalsIgnoreCase(arcStateName)) { + return TtlPartArcState.ARC_STATE_NO_USE; + } + + if (TtlPartArcState.ARC_STATE_USING.getArcStateName().equalsIgnoreCase(arcStateName)) { + return TtlPartArcState.ARC_STATE_USING; + } + + if (TtlPartArcState.ARC_STATE_READY.getArcStateName().equalsIgnoreCase(arcStateName)) { + return TtlPartArcState.ARC_STATE_READY; + } + + if (TtlPartArcState.ARC_STATE_ARCHIVING.getArcStateName().equalsIgnoreCase(arcStateName)) { + return TtlPartArcState.ARC_STATE_ARCHIVING; + } + + if (TtlPartArcState.ARC_STATE_ARCHIVED.getArcStateName().equalsIgnoreCase(arcStateName)) { + return TtlPartArcState.ARC_STATE_ARCHIVED; + } + + if (TtlPartArcState.ARC_STATE_REUSING.getArcStateName().equalsIgnoreCase(arcStateName)) { + return TtlPartArcState.ARC_STATE_REUSING; + } + + return TtlPartArcState.ARC_STATE_NO_USE; + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/DbNameUtil.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/DbNameUtil.java index bd3c09ecb..7a59b5637 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/DbNameUtil.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/DbNameUtil.java @@ -18,7 +18,11 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.gms.topology.SystemDbHelper; +import java.util.Set; +import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -29,6 +33,15 @@ public class DbNameUtil { private final static int MAX_DB_NAME_LENGTH = 64; + private static Set forbiddenDbNameSet = new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + + static { + forbiddenDbNameSet.add("mysql"); + forbiddenDbNameSet.add("performance_schema"); + forbiddenDbNameSet.addAll(SystemDbHelper.getAllBuildInDbNameList()); + + } + public static boolean validateDbName(String dbName, boolean isKeyWords) { if (dbName.length() > MAX_DB_NAME_LENGTH) { @@ -45,6 +58,11 @@ public static boolean validateDbName(String dbName, boolean isKeyWords) { } } + if (forbiddenDbNameSet.contains(dbName)) { + throw new TddlRuntimeException(ErrorCode.ERR_GMS_GENERIC, + String.format("Failed to create database because the dbName[%s] is forbidden build-in dbname", dbName)); + } + if (isKeyWords) { throw new TddlRuntimeException(ErrorCode.ERR_GMS_GENERIC, String.format("Failed to create database because the string of dbName[%s] is a keyword", dbName)); diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/DdlMetaLogUtil.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/DdlMetaLogUtil.java index 048cd37f2..381c3e368 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/DdlMetaLogUtil.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/DdlMetaLogUtil.java @@ -51,8 +51,11 @@ public class DdlMetaLogUtil { ddlTables.add(GmsSystemTables.COLUMNAR_TABLE_MAPPING); ddlTables.add(GmsSystemTables.COLUMNAR_TABLE_EVOLUTION); ddlTables.add(GmsSystemTables.COLUMNAR_COLUMN_EVOLUTION); + ddlTables.add(GmsSystemTables.COLUMNAR_PARTITION_EVOLUTION); ddlTables.add(GmsSystemTables.COLUMNAR_CONFIG); ddlTables.add(GmsSystemTables.COLUMNAR_LEASE); + ddlTables.add(GmsSystemTables.COLUMNAR_DUPLICATES); + ddlTables.add(GmsSystemTables.COLUMNAR_PURGE_HISTORY); ddlTables.add(GmsSystemTables.COLUMNS); ddlTables.add(GmsSystemTables.INDEXES); ddlTables.add(GmsSystemTables.KEY_COLUMN_USAGE); @@ -60,6 +63,7 @@ public class DdlMetaLogUtil { ddlTables.add(GmsSystemTables.TABLE_CONSTRAINTS); ddlTables.add(GmsSystemTables.REFERENTIAL_CONSTRAINTS); ddlTables.add(GmsSystemTables.BACKFILL_OBJECTS); + ddlTables.add(GmsSystemTables.BACKFILL_SAMPLE_ROWS); ddlTables.add(GmsSystemTables.CHANGESET_OBJECT); ddlTables.add(GmsSystemTables.CHECKER_REPORTS); ddlTables.add(GmsSystemTables.DDL_JOBS); diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/GmsJdbcUtil.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/GmsJdbcUtil.java index 1132502c2..75eeab670 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/GmsJdbcUtil.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/GmsJdbcUtil.java @@ -59,15 +59,16 @@ public class GmsJdbcUtil { public static Map getDefaultConnPropertiesForHaChecker() { Map connPropsMap = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); connPropsMap.putAll(JDBC_DEFAULT_CONN_PROPS_MAP); - connPropsMap.put(JDBC_SOCKET_TIMEOUT, "5000"); + connPropsMap.put(JDBC_SOCKET_TIMEOUT, "2000"); + connPropsMap.put(JDBC_CONNECT_TIMEOUT, "2000"); return connPropsMap; } public static Map getDefaultConnPropertiesForHaCheckerFast() { Map connPropsMap = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); connPropsMap.putAll(JDBC_DEFAULT_CONN_PROPS_MAP); - connPropsMap.put(JDBC_SOCKET_TIMEOUT, "3000"); - connPropsMap.put(JDBC_CONNECT_TIMEOUT, "3000"); + connPropsMap.put(JDBC_SOCKET_TIMEOUT, "2000"); + connPropsMap.put(JDBC_CONNECT_TIMEOUT, "2000"); return connPropsMap; } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/GroupInfoUtil.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/GroupInfoUtil.java index 89a498891..3c4183d45 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/GroupInfoUtil.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/GroupInfoUtil.java @@ -285,9 +285,9 @@ private static byte[] intToBytesByBigEnd(int intVal) { return bytes; } - private static String doMurmur3Hash32(String dbName) { - String dbNameLowerCase = dbName.toLowerCase(); - byte[] rawData = dbNameLowerCase.getBytes(StandardCharsets.UTF_8); + public static String doMurmur3Hash32(String strVal) { + String strLowerCase = strVal.toLowerCase(); + byte[] rawData = strLowerCase.getBytes(StandardCharsets.UTF_8); int hashIntVal = MurmurHashUtils.murmurHash32WithZeroSeed(rawData); byte[] hashValBytes = intToBytesByBigEnd(hashIntVal); String hashCodeHexStr = HexBin.encode(hashValBytes); diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/MetaDbUtil.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/MetaDbUtil.java index 05f63c8c0..8e2fd5692 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/MetaDbUtil.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/MetaDbUtil.java @@ -21,11 +21,14 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.utils.CaseInsensitive; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; import com.alibaba.polardbx.gms.metadb.record.SystemTableRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigWithIndexNameRecord; import com.alibaba.polardbx.gms.topology.InstConfigAccessor; import com.alibaba.polardbx.rpc.pool.XConnection; @@ -470,4 +473,33 @@ public static boolean releaseLock(Connection conn, String lockObj) { return false; } } + + + /** + * Generate columnar config for all columnar indexes of a single logical table. + */ + public static void generateColumnarConfig(String schemaName, String tableName, + Map> records, + Map globalConfig) { + try (Connection connection = MetaDbUtil.getConnection()) { + generateColumnarConfig(connection, schemaName, tableName, records, globalConfig); + } catch (Throwable t) { + MetaDbLogUtil.META_DB_LOG.error("Get columnar config error.", t); + } + } + + public static void generateColumnarConfig(Connection connection, String schemaName, String tableName, + Map> records, + Map globalConfig) { + ColumnarConfigAccessor accessor = new ColumnarConfigAccessor(); + accessor.setConnection(connection); + for (ColumnarConfigWithIndexNameRecord record : accessor.query(schemaName, tableName)) { + if (0 == record.tableId) { + globalConfig.put(record.configKey.toUpperCase(), record.configValue); + continue; + } + records.computeIfAbsent(record.indexName, k -> new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER)) + .put(record.configKey.toUpperCase(), record.configValue); + } + } } diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/PartArcStateUtil.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/PartArcStateUtil.java new file mode 100644 index 000000000..b8f2a6204 --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/PartArcStateUtil.java @@ -0,0 +1,27 @@ +package com.alibaba.polardbx.gms.util; + +import com.alibaba.polardbx.gms.partition.ExtraFieldJSON; +import com.alibaba.polardbx.gms.ttl.TtlPartArcState; + +public class PartArcStateUtil { + + public String getArcStateNameFromExtraJson(ExtraFieldJSON partExtras) { + +// // means part has been finished archiving at lease once, now is allowed inserting, not allow splitting part +// public final static int ARC_STATE_REUSING = 5; +// // means part finished archiving, part data is truncated, not allow splitting part +// public final static int ARC_STATE_ARCHIVED = 4; +// // means part is running archiving, building archiving files, not allow splitting part +// public final static int ARC_STATE_ARCHIVING = 3; +// // means part data does no change, has no archiving file, allow splitting part +// public final static int ARC_STATE_READY = 2; +// // means part has incremental data, allow splitting part +// public final static int ARC_STATE_USING = 1; +// // means part must be empty, allow splitting part +// public final static int ARC_STATE_NO_USE = 0; + + int arcStateVal = partExtras.getArcState(); + TtlPartArcState arcState = TtlPartArcState.getTtlPartArcStateByArcStateValue(arcStateVal); + return arcState.getArcStateName(); + } +} diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/PartColLocalIndexNameUtil.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/PartColLocalIndexNameUtil.java index 81fdbd824..f17a0976d 100644 --- a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/PartColLocalIndexNameUtil.java +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/PartColLocalIndexNameUtil.java @@ -16,8 +16,6 @@ package com.alibaba.polardbx.gms.util; -import com.alibaba.polardbx.common.TddlConstants; - import java.util.Formatter; import java.util.Random; import java.util.Set; @@ -31,9 +29,9 @@ public static String buildRandomName(Set existsNames, String preferName) { // Assign new name with suffix. final Random random = new Random(); - final Formatter formatter = new Formatter(); String fullName; do { + Formatter formatter = new Formatter(); final String suffix = "$" + formatter.format("%04x", random.nextInt(0x10000)); fullName = preferName + suffix; } while (existsNames.contains(fullName)); diff --git a/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/TtlEventLogUtil.java b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/TtlEventLogUtil.java new file mode 100644 index 000000000..1da38e68a --- /dev/null +++ b/polardbx-gms/src/main/java/com/alibaba/polardbx/gms/util/TtlEventLogUtil.java @@ -0,0 +1,78 @@ +package com.alibaba.polardbx.gms.util; + +import com.alibaba.polardbx.common.eventlogger.EventLogger; +import com.alibaba.polardbx.common.eventlogger.EventType; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; + +/** + * @author chenghui.lch + */ +public class TtlEventLogUtil { + + // TTL 任务日志 + private final static Logger TTL_TASK_LOGGER = LoggerFactory.getLogger("ttl_task"); + + public static void logCreateTtlDefinitionEvent(String schemaName, + String ttlTblName) { + try { + String msg = String.format("new ttl-definition of table[`%s`.`%s`] has been created", + schemaName, ttlTblName); + EventLogger.log(EventType.CREATE_TTL_DEFINITION, msg); + + } catch (Throwable ex) { + TTL_TASK_LOGGER.error(ex); + } + } + + public static void logCreateTtlDefinitionWithArchiveTableEvent(String schemaName, + String ttlTblName, + String archiveTable) { + try { + String msg = + String.format("new ttl-definition of table[`%s`.`%s`] with archive table[`%s`.`%s`] has been created", + schemaName, ttlTblName, schemaName, archiveTable); + EventLogger.log(EventType.CREATE_TTL_DEFINITION_WITH_ARCHIVE_TABLE, msg); + + } catch (Throwable ex) { + TTL_TASK_LOGGER.error(ex); + } + } + + public static void logCreateCciArchiveTableEvent(String schemaName, + String ttlTableName, + String archiveTable) { + try { + String msg = + String.format("new cci-based archive table[`%s`.`%s`] of ttl table[`%s`.`%s`] has been created", + schemaName, archiveTable, schemaName, ttlTableName); + EventLogger.log(EventType.CREATE_CCI_ARCHIVE_TABLE, msg); + } catch (Throwable ex) { + TTL_TASK_LOGGER.error(ex); + } + } + + public static void logDropCciArchiveTableEvent(String schemaName, + String ttlTableName, + String archiveTable) { + try { + String msg = + String.format("the cci-based archive table[`%s`.`%s`] of ttl table[`%s`.`%s`] has been dropped", + schemaName, archiveTable, schemaName, ttlTableName); + EventLogger.log(EventType.DROP_CCI_ARCHIVE_TABLE, msg); + } catch (Throwable ex) { + TTL_TASK_LOGGER.error(ex); + } + } + + public static void logCleanupExpiredDataEvent(String schemaName, + String ttlTableName) { + try { + String msg = String.format("the ttl table[`%s`.`%s`] has cleanup the expired data", + schemaName, ttlTableName); + EventLogger.log(EventType.CLEANUP_EXPIRED_DATA, msg); + } catch (Throwable ex) { + TTL_TASK_LOGGER.error(ex); + } + } +} diff --git a/polardbx-gms/src/main/resources/ddl/__index__ b/polardbx-gms/src/main/resources/ddl/__index__ index a1fd0c192..582e03bf2 100644 --- a/polardbx-gms/src/main/resources/ddl/__index__ +++ b/polardbx-gms/src/main/resources/ddl/__index__ @@ -17,4 +17,5 @@ cdc.xml table_group.xml columnar.xml foreign_key.xml -spm.xml \ No newline at end of file +spm.xml +ttl.xml \ No newline at end of file diff --git a/polardbx-gms/src/main/resources/ddl/basic_object_ext.xml b/polardbx-gms/src/main/resources/ddl/basic_object_ext.xml index 6e3a5fbef..ca01caa93 100644 --- a/polardbx-gms/src/main/resources/ddl/basic_object_ext.xml +++ b/polardbx-gms/src/main/resources/ddl/basic_object_ext.xml @@ -123,4 +123,17 @@ ) DEFAULT CHARSET=utf8; ]]> + + + diff --git a/polardbx-gms/src/main/resources/ddl/columnar.xml b/polardbx-gms/src/main/resources/ddl/columnar.xml index d0381cd5c..9808654f9 100644 --- a/polardbx-gms/src/main/resources/ddl/columnar.xml +++ b/polardbx-gms/src/main/resources/ddl/columnar.xml @@ -7,17 +7,38 @@ `logical_schema` varchar(64) not null, `logical_table` varchar(64) default null, `partition_name` varchar(64) default null, - `checkpoint_tso` bigint not null, + `checkpoint_tso` bigint not null COMMENT 'columnar tso version', `offset` json not null, + `binlog_tso` bigint default null COMMENT 'binlog tso', `checkpoint_type` varchar(255) not null, + `min_compaction_tso` bigint default null, + `info` longtext default null, `extra` longtext default null, `create_time` datetime default current_timestamp, `update_time` datetime default current_timestamp on update current_timestamp, unique key `checkpoint_tso_index` (`checkpoint_tso`, `checkpoint_type`, `logical_schema`, `logical_table`, `partition_name`), KEY `checkpoint_tso_table_index` (`checkpoint_tso`, `logical_schema`, `logical_table`), + KEY `binlog_tso_type` (`binlog_tso`, `checkpoint_tso` desc, `checkpoint_type`), + KEY `type_tso_index` (`checkpoint_type`, `logical_schema`, `logical_table`, `partition_name`, `checkpoint_tso`), + KEY `schema_table_binlog_tso` (`logical_schema`, `logical_table`, `binlog_tso`), primary key (`id`) ) charset=utf8 ]]> + + + + + @@ -39,12 +60,12 @@ `total_rows` bigint unsigned default null, `create_time` datetime default current_timestamp, `update_time` datetime default current_timestamp on update current_timestamp, - KEY `checkpoint_tso_index` (`checkpoint_tso`, `logical_schema`), KEY `logical_schema_type_engine_index` (`logical_schema`, `logical_table`, `part_name`, `file_type`, `engine`), - KEY `physical_schema_index` (`physical_schema`, `physical_table`), KEY `file_name_index` (`file_name`), KEY `file_name_tso_index` (`file_name`, `checkpoint_tso`), KEY `type_engine_index` (`file_type`, `engine`), + KEY `schema_table_part_type_tso` (`logical_schema`,`logical_table`,`part_name`,`file_type`,`checkpoint_tso`), + KEY `schema_table_file_name` (`logical_schema`,`logical_table`,`file_name`), primary key (`id`) ) charset=utf8 ]]> @@ -57,6 +78,12 @@ + + @@ -141,10 +168,15 @@ `extra` longtext default null, `gmt_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `gmt_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `type` varchar(64) DEFAULT NULL COMMENT 'CCI type, e.g. SNAPSHOT/ARCHIVE, null means normal CCI', PRIMARY KEY (`table_id`), - UNIQUE KEY (`table_schema`, `table_name`, `index_name`) + UNIQUE KEY (`table_schema`, `table_name`, `index_name`), + KEY idx_type(`type`) ) DEFAULT CHARSET = utf8mb4 ]]> + - - - - - - - - + + com.cronutils + cron-utils + cglib cglib-nodep @@ -97,23 +92,15 @@ junit 4.13.2 - - - - - + - ${project.groupId} + com.alibaba.polardbx polardbx-calcite commons-logging commons-logging - - ${project.groupId} - polardbx-common - @@ -121,34 +108,30 @@ druid ${druid.version} + + mysql + mysql-connector-java + org.slf4j jul-to-slf4j ${jul-to.version} - com.clearspring.analytics stream ${stream.version} - org.yaml snakeyaml ${snakeyaml.version} - - - - - - net.hydromatic foodmart-data-hsqldb - 0.5 + 0.3 test @@ -176,7 +159,7 @@ org.codehaus.janino commons-compiler - 3.1.9 + 3.1.6 org.mockito @@ -184,5 +167,6 @@ ${mockito.verison} test + diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/OptimizerContext.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/OptimizerContext.java index 6f0325050..a01d5183d 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/OptimizerContext.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/OptimizerContext.java @@ -74,6 +74,9 @@ public class OptimizerContext { private ParamManager paramManager; private boolean sqlMock = false; + // Label if OptimizerContext of one db finished init + private volatile boolean finishInit = false; + /** *
      *  KEY: APP_NAME
@@ -122,7 +125,7 @@ public static OptimizerContext getContext(String schemaName) {
         }
         String schemaNameLowerCase = schemaName.toLowerCase();
         OptimizerContext optimizerContext = optimizerContextMap.get(schemaNameLowerCase);
-        if (optimizerContext == null) {
+        if (optimizerContext == null || !optimizerContext.isFinishInit()) {
             IServerConfigManager serverConfigManager = OptimizerHelper.getServerConfigManager();
             if (serverConfigManager != null) {
                 // When running unit test, ServerConfigManager could be null
@@ -247,6 +250,14 @@ public void setParamManager(ParamManager paramManager) {
         this.paramManager = paramManager;
     }
 
+    public boolean isFinishInit() {
+        return finishInit;
+    }
+
+    public void setFinishInit(boolean finishInit) {
+        this.finishInit = finishInit;
+    }
+
     public static SchemaTransactionStatistics getTransStat(String schema) {
         OptimizerContext context = getContext(schema);
         if (DynamicConfig.getInstance().isEnableTransactionStatistics() && null != context) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/PlannerContext.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/PlannerContext.java
index 54d0c2f1d..18dcf4bde 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/PlannerContext.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/PlannerContext.java
@@ -16,9 +16,14 @@
 
 package com.alibaba.polardbx.optimizer;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.polardbx.common.jdbc.Parameters;
 import com.alibaba.polardbx.common.properties.ConnectionParams;
 import com.alibaba.polardbx.common.properties.ParamManager;
+import com.alibaba.polardbx.gms.module.LogLevel;
+import com.alibaba.polardbx.gms.module.LogPattern;
+import com.alibaba.polardbx.gms.module.Module;
+import com.alibaba.polardbx.gms.module.ModuleLogInfo;
 import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticTrace;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.planmanager.BaselineInfo;
@@ -36,6 +41,7 @@
 import org.apache.calcite.rel.logical.LogicalTableScan;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.util.JsonBuilder;
 import org.apache.calcite.util.PlannerContextWithParam;
 import org.apache.calcite.util.trace.CalcitePlanOptimizerTrace;
 
@@ -149,11 +155,28 @@ public class PlannerContext implements Context, PlannerContextWithParam {
     private Map> viewMap = null;
     private Set constantParamIndex = null;
 
+    /**
+     * enable the rule counter in cbo
+     * there is no need to copy the value
+     */
+    private boolean enableRuleCounter = false;
+    /**
+     * record the times of rules called in cbo
+     * there is no need to copy the value
+     */
+    private long ruleCount = 0;
+
+    private boolean hasConstantFold = false;
+
+    private boolean useColumnarPlanCache = false;
+
+    private boolean inExprToLookupJoin = false;
+
     private int columnarMaxShardCnt = 20;
 
     private boolean useColumnar = false;
 
-    private boolean inExprToLookupJoin = false;
+    private boolean localIndexHint = false;
 
     public  T unwrap(Class clazz) {
         return clazz.isInstance(this) ? clazz.cast(this) : null;
@@ -197,6 +220,7 @@ public PlannerContext(ExecutionContext executionContext,
         this.isInSubquery = isInSubquery;
 
         this.addForcePrimary = executionContext.isTsoTransaction() && executionContext.enableForcePrimaryForTso();
+        this.useColumnarPlanCache = executionContext.isColumnarPlanCache();
     }
 
     protected PlannerContext(ExecutionContext executionContext,
@@ -206,8 +230,7 @@ protected PlannerContext(ExecutionContext executionContext,
                              SqlKind sqlkind,
                              boolean isInSubquery,
                              boolean shouldUseHeuOrder,
-                             WorkloadType workloadType,
-                             boolean useColumnar) {
+                             WorkloadType workloadType) {
         this.executionContext = executionContext;
         this.schemaName = executionContext.getSchemaName();
         this.extraCmds = extraCmds;
@@ -219,7 +242,7 @@ protected PlannerContext(ExecutionContext executionContext,
         this.isInSubquery = isInSubquery;
         this.shouldUseHeuOrder = shouldUseHeuOrder;
         this.workloadType = workloadType;
-        this.useColumnar = useColumnar;
+        this.useColumnarPlanCache = executionContext.isColumnarPlanCache();
     }
 
     public PlannerContext copyWithInSubquery() {
@@ -230,8 +253,7 @@ public PlannerContext copyWithInSubquery() {
             sqlKind,
             isInSubquery,
             shouldUseHeuOrder,
-            workloadType,
-            useColumnar);
+            workloadType);
         ret.isInSubquery = true;
         ret.joinCount = joinCount;
         return ret;
@@ -420,6 +442,61 @@ public Object getExecContext() {
         return executionContext;
     }
 
+    /**
+     * Encodes context-specific extended parameters into a JSON string.
+     *
+     * @return A JSON-formatted string representation of the parameters.
+     */
+    public String encodeExtendedParametersToJson() {
+        // Instantiate a builder object for constructing JSON content
+        final JsonBuilder jsonBuilder = new JsonBuilder();
+
+        // Create a map to hold parameters to be encoded
+        Map extendedParams = new HashMap<>();
+
+        // Add parameters to the map
+        extendedParams.put("useColumnar", this.isUseColumnar());
+        extendedParams.put("columnarMaxShardCnt", this.getColumnarMaxShardCnt());
+
+        try {
+            // Convert the map to a JSON string using the JsonBuilder
+            return jsonBuilder.toJsonString(extendedParams);
+        } catch (Exception e) {
+            // Handle any potential exceptions during conversion
+            ModuleLogInfo.getInstance().logRecord(Module.SPM, LogPattern.UNEXPECTED,
+                new String[] {"encoding arguments to JSON", e.getMessage()}, LogLevel.CRITICAL);
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Parses an extension argument string to configure query context settings related to columnar storage.
+     *
+     * @param extend The extension argument string containing configuration information for columnar storage.
+     */
+    public void decodeArguments(String extend) {
+        // If the extension parameter is null or has zero length, simply return without further processing.
+        if (extend == null || extend.isEmpty()) {
+            return;
+        }
+
+        try {
+            // Parse the extension argument string into a Map object.
+            Map extendMap = JSON.parseObject(extend, HashMap.class);
+
+            // Set whether to use columnar storage, defaulting to false.
+            this.useColumnar = (Boolean) extendMap.getOrDefault("useColumnar", false);
+
+            // Set the maximum number of shards for columnar storage, defaulting to 20
+            this.columnarMaxShardCnt = (Integer) extendMap.getOrDefault("columnarMaxShardCnt", 20);
+        } catch (Exception e) {
+            // Handle any potential exceptions during conversion
+            ModuleLogInfo.getInstance().logRecord(Module.SPM, LogPattern.UNEXPECTED,
+                new String[] {"decoding arguments", e.getMessage()}, LogLevel.CRITICAL);
+            throw new RuntimeException(e);
+        }
+    }
+
     public boolean isSkipPostOpt() {
         return isSkipPostOpt;
     }
@@ -613,6 +690,22 @@ public String formatStatisticTrace() {
         return sb.toString();
     }
 
+    public boolean isEnableRuleCounter() {
+        return enableRuleCounter;
+    }
+
+    public void setEnableRuleCounter(boolean enableRuleCounter) {
+        this.enableRuleCounter = enableRuleCounter;
+    }
+
+    public void setRuleCount(long ruleCount) {
+        this.ruleCount = ruleCount;
+    }
+
+    public long getRuleCount() {
+        return ruleCount;
+    }
+
     /**
      * is plan contains recursive cte
      */
@@ -642,6 +735,10 @@ public void setUseColumnar(boolean useColumnar) {
         this.useColumnar = useColumnar;
     }
 
+    public boolean isUseColumnarPlanCache() {
+        return useColumnarPlanCache;
+    }
+
     public Set getConstantParamIndex() {
         return constantParamIndex;
     }
@@ -657,4 +754,20 @@ public boolean isInExprToLookupJoin() {
     public void setInExprToLookupJoin(boolean inExprToLookupJoin) {
         this.inExprToLookupJoin = inExprToLookupJoin;
     }
+
+    public boolean isHasConstantFold() {
+        return hasConstantFold;
+    }
+
+    public void setHasConstantFold(boolean hasConstantFold) {
+        this.hasConstantFold = hasConstantFold;
+    }
+
+    public boolean hasLocalIndexHint() {
+        return localIndexHint;
+    }
+
+    public void setLocalIndexHint(boolean localIndexHint) {
+        this.localIndexHint = localIndexHint;
+    }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/archive/CheckOSSArchiveUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/archive/CheckOSSArchiveUtil.java
index 7cb5de4e7..96cc37739 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/archive/CheckOSSArchiveUtil.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/archive/CheckOSSArchiveUtil.java
@@ -16,8 +16,11 @@
 
 package com.alibaba.polardbx.optimizer.archive;
 
+import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException;
 import com.alibaba.polardbx.common.exception.TddlRuntimeException;
 import com.alibaba.polardbx.common.exception.code.ErrorCode;
+import com.alibaba.polardbx.common.properties.ConnectionParams;
+import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.common.utils.Pair;
 import com.alibaba.polardbx.druid.util.StringUtils;
 import com.alibaba.polardbx.gms.metadb.table.TableInfoManager;
@@ -25,17 +28,28 @@
 import com.alibaba.polardbx.gms.partition.TablePartRecordInfoContext;
 import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig;
 import com.alibaba.polardbx.gms.topology.DbInfoManager;
+import com.alibaba.polardbx.gms.ttl.TtlInfoRecord;
 import com.alibaba.polardbx.gms.util.MetaDbUtil;
 import com.alibaba.polardbx.optimizer.OptimizerContext;
+import com.alibaba.polardbx.optimizer.config.table.ColumnMeta;
 import com.alibaba.polardbx.optimizer.config.table.SchemaManager;
 import com.alibaba.polardbx.optimizer.config.table.TableMeta;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
 import com.alibaba.polardbx.optimizer.exception.TableNotFoundException;
+import com.alibaba.polardbx.optimizer.partition.PartitionInfo;
+import com.alibaba.polardbx.optimizer.partition.PartitionSpec;
 import com.alibaba.polardbx.optimizer.partition.common.LocalPartitionDefinitionInfo;
 import com.alibaba.polardbx.optimizer.tablegroup.TableGroupInfoManager;
+import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo;
 
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.text.MessageFormat;
+import java.util.Comparator;
+import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
  * check whether the ddl should unarchive oss table first
@@ -128,6 +142,12 @@ public static boolean checkWithoutOSS(String schema, String table) {
         if (tableMeta == null) {
             return true;
         }
+
+        TtlDefinitionInfo ttlDefInfo = tableMeta.getTtlDefinitionInfo();
+        if (ttlDefInfo != null && ttlDefInfo.alreadyBoundArchiveTable()) {
+            return false;
+        }
+
         LocalPartitionDefinitionInfo localPartitionDefinitionInfo = tableMeta.getLocalPartitionDefinitionInfo();
         if (localPartitionDefinitionInfo == null) {
             return true;
@@ -197,6 +217,11 @@ public static Optional> getTTLSource(String schemaName, Str
             TableInfoManager tableInfoManager = new TableInfoManager();
             tableInfoManager.setConnection(metaDbConn);
 
+            TtlInfoRecord ttlRec = tableInfoManager.getTtlInfoRecordByArchiveTable(schemaName, tableName);
+            if (ttlRec != null) {
+                return Optional.of(new Pair<>(ttlRec.getTableSchema(), ttlRec.getTableName()));
+            }
+
             TableLocalPartitionRecord record =
                 tableInfoManager.getLocalPartitionRecordByArchiveTable(schemaName, tableName);
             return record != null ?
@@ -206,4 +231,119 @@ public static Optional> getTTLSource(String schemaName, Str
             throw new TddlRuntimeException(ErrorCode.ERR_GMS_GET_CONNECTION, e, e.getMessage());
         }
     }
+
+    public static Optional getTtlSourceInfo(String schemaName, String tableName) {
+        // get ttl source for oss table
+
+        TtlSourceInfo sourceInfo = new TtlSourceInfo();
+        try (Connection metaDbConn = MetaDbUtil.getConnection()) {
+            TableInfoManager tableInfoManager = new TableInfoManager();
+            tableInfoManager.setConnection(metaDbConn);
+
+            TtlInfoRecord ttlRec = tableInfoManager.getTtlInfoRecordByArchiveTable(schemaName, tableName);
+            if (ttlRec != null) {
+                sourceInfo.setTtlInfoRecord(ttlRec);
+                sourceInfo.setUseRowLevelTtl(true);
+                sourceInfo.setTtlTable(true);
+                return Optional.of(sourceInfo);
+            }
+
+            TableLocalPartitionRecord record =
+                tableInfoManager.getLocalPartitionRecordByArchiveTable(schemaName, tableName);
+            if (record != null) {
+                sourceInfo.setTableLocalPartitionRecord(record);
+                sourceInfo.setUseRowLevelTtl(false);
+                sourceInfo.setTtlTable(true);
+                return Optional.of(sourceInfo);
+            } else {
+                return Optional.empty();
+            }
+
+        } catch (SQLException e) {
+            throw new TddlRuntimeException(ErrorCode.ERR_GMS_GET_CONNECTION, e, e.getMessage());
+        }
+    }
+
+    public static void validateArchivePartitions(String schemaName, String tableName, List partNames,
+                                                 ExecutionContext executionContext) {
+        final TableMeta ossTableMeta =
+            OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(tableName);
+
+        if (ossTableMeta == null) {
+            throw new TddlNestableRuntimeException(String.format(
+                "The ttl tmp table %s.%s does not exist.", schemaName, tableName));
+        }
+
+        boolean checkArchivePartitionReady =
+            executionContext.getParamManager().getBoolean(ConnectionParams.CHECK_ARCHIVE_PARTITION_READY);
+
+        PartitionInfo partitionInfo = ossTableMeta.getPartitionInfo();
+        for (String partName : partNames) {
+            PartitionSpec ps = partitionInfo.getPartSpecSearcher().getPartSpecByPartName(partName);
+            if (ps == null) {
+                throw new TddlNestableRuntimeException(String.format(
+                    "The archive partition %s does not exists", partName));
+            }
+
+            if (checkArchivePartitionReady && !ps.isReadyForArchiving()) {
+                throw new TddlNestableRuntimeException(String.format(
+                    "The archive partition %s is not ready for archiving", partName));
+            }
+        }
+    }
+
+    public static void checkColumnConsistency(String ossSchemaName, String ossTableName, String tmpSchemaName,
+                                              String tmpTableName) {
+        final TableMeta ossTableMeta =
+            OptimizerContext.getContext(ossSchemaName).getLatestSchemaManager().getTable(ossTableName);
+        final TableMeta tmpTableMeta =
+            OptimizerContext.getContext(tmpSchemaName).getLatestSchemaManager().getTable(tmpTableName);
+
+        if (ossTableMeta == null) {
+            throw new TddlNestableRuntimeException(String.format(
+                "The oss table %s.%s does not exist.", ossSchemaName, ossTableName));
+        }
+
+        if (tmpTableMeta == null) {
+            throw new TddlNestableRuntimeException(String.format(
+                "The ttl tmp table bound to the oss table %s.%s does not exist.", ossSchemaName, ossTableName));
+        }
+
+        checkColumnConsistency(ossTableMeta, tmpTableMeta);
+    }
+
+    public static void checkColumnConsistency(TableMeta sourceTable, TableMeta targetTable) {
+        // check columns
+        List sortedSourceColumns =
+            sourceTable.getPhysicalColumns().stream().sorted(Comparator.comparing(ColumnMeta::getOriginColumnName))
+                .collect(Collectors.toList());
+
+        List sortedTargetColumns =
+            targetTable.getPhysicalColumns().stream().sorted(Comparator.comparing(ColumnMeta::getOriginColumnName))
+                .collect(Collectors.toList());
+
+        if (sortedSourceColumns.size() != sortedTargetColumns.size()) {
+            throwMetaInconsistentError(sourceTable, targetTable);
+        }
+
+        for (int i = 0; i < sortedSourceColumns.size(); i++) {
+            ColumnMeta c1 = sortedSourceColumns.get(i);
+            ColumnMeta c2 = sortedTargetColumns.get(i);
+            // column name inconsistent
+            if (!c1.getOriginColumnName().equalsIgnoreCase(c2.getOriginColumnName())) {
+                throwMetaInconsistentError(sourceTable, targetTable);
+            }
+            // column type inconsistent
+            if (!DataTypeUtil.equals(c1.getDataType(), c2.getDataType(), true)) {
+                throwMetaInconsistentError(sourceTable, targetTable);
+            }
+        }
+    }
+
+    private static void throwMetaInconsistentError(TableMeta sourceTable, TableMeta targetTable) {
+        throw GeneralUtil.nestedException(MessageFormat.format(
+            "the column metas of source table {0} and target table {1} are not consistent, "
+                + "please create a new archive table for source table {0}", sourceTable.getTableName(),
+            targetTable.getTableName()));
+    }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/archive/TtlSourceInfo.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/archive/TtlSourceInfo.java
new file mode 100644
index 000000000..f0e105486
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/archive/TtlSourceInfo.java
@@ -0,0 +1,49 @@
+package com.alibaba.polardbx.optimizer.archive;
+
+import com.alibaba.polardbx.gms.partition.TableLocalPartitionRecord;
+import com.alibaba.polardbx.gms.ttl.TtlInfoRecord;
+import lombok.Data;
+
+@Data
+public class TtlSourceInfo {
+    protected boolean ttlTable = false;
+    protected boolean useRowLevelTtl = false;
+    protected TableLocalPartitionRecord tableLocalPartitionRecord;
+    protected TtlInfoRecord ttlInfoRecord;
+
+    public TtlSourceInfo() {
+    }
+
+    public boolean isTtlTable() {
+        return ttlTable;
+    }
+
+    public void setTtlTable(boolean ttlTable) {
+        this.ttlTable = ttlTable;
+    }
+
+    public boolean isUseRowLevelTtl() {
+        return useRowLevelTtl;
+    }
+
+    public void setUseRowLevelTtl(boolean useRowLevelTtl) {
+        this.useRowLevelTtl = useRowLevelTtl;
+    }
+
+    public TtlInfoRecord getTtlInfoRecord() {
+        return ttlInfoRecord;
+    }
+
+    public void setTtlInfoRecord(TtlInfoRecord ttlInfoRecord) {
+        this.ttlInfoRecord = ttlInfoRecord;
+    }
+
+    public TableLocalPartitionRecord getTableLocalPartitionRecord() {
+        return tableLocalPartitionRecord;
+    }
+
+    public void setTableLocalPartitionRecord(
+        TableLocalPartitionRecord tableLocalPartitionRecord) {
+        this.tableLocalPartitionRecord = tableLocalPartitionRecord;
+    }
+}
\ No newline at end of file
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/AbstractIOEstimator.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/AbstractIOEstimator.java
index 348683e64..590308efd 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/AbstractIOEstimator.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/AbstractIOEstimator.java
@@ -16,6 +16,9 @@
 
 package com.alibaba.polardbx.optimizer.config.meta;
 
+import com.alibaba.polardbx.optimizer.PlannerContext;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.optimizeralert.OptimizerAlertUtil;
 import org.apache.calcite.plan.RelOptPredicateList;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rex.RexBuilder;
@@ -32,12 +35,15 @@ public class AbstractIOEstimator extends RexVisitorImpl {
     public final RelMetadataQuery metadataQuery;
     private final RexBuilder rexBuilder;
     private final double maxIO;
+    protected final PlannerContext plannerContext;
 
-    public AbstractIOEstimator(RelMetadataQuery metadataQuery, RexBuilder rexBuilder, double maxIO) {
+    public AbstractIOEstimator(RelMetadataQuery metadataQuery, RexBuilder rexBuilder, double maxIO,
+                               PlannerContext plannerContext) {
         super(true);
         this.metadataQuery = metadataQuery;
         this.rexBuilder = rexBuilder;
         this.maxIO = maxIO;
+        this.plannerContext = plannerContext;
     }
 
     public Double normalize(Double io) {
@@ -53,6 +59,20 @@ public Double normalize(Double io) {
     }
 
     public Double evaluate(RexNode predicate) {
+        try {
+            return evaluateInside(predicate);
+        } catch (Throwable e) {
+            OptimizerAlertUtil.selectivityAlert(getExecutionContext(), e);
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public ExecutionContext getExecutionContext() {
+        return plannerContext == null ? null : plannerContext.getExecutionContext();
+    }
+
+    public Double evaluateInside(RexNode predicate) {
         if (predicate == null) {
             return maxIO;
         } else {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdCost.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdCost.java
index d7db86036..7d41be992 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdCost.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdCost.java
@@ -16,46 +16,12 @@
 
 package com.alibaba.polardbx.optimizer.config.meta;
 
-import com.alibaba.polardbx.optimizer.core.rel.HashWindow;
-import com.alibaba.polardbx.optimizer.core.rel.LookupJoin;
-import com.alibaba.polardbx.optimizer.memory.MemoryEstimator;
-import com.google.common.collect.ImmutableList;
 import com.alibaba.polardbx.common.jdbc.ParameterContext;
 import com.alibaba.polardbx.common.properties.ConnectionParams;
 import com.alibaba.polardbx.common.utils.logger.Logger;
 import com.alibaba.polardbx.common.utils.logger.LoggerFactory;
 import com.alibaba.polardbx.optimizer.PlannerContext;
-import com.alibaba.polardbx.optimizer.core.rel.BKAJoin;
-import com.alibaba.polardbx.optimizer.core.rel.HashAgg;
-import com.alibaba.polardbx.optimizer.core.rel.HashGroupJoin;
-import com.alibaba.polardbx.optimizer.core.rel.HashJoin;
-import com.alibaba.polardbx.optimizer.core.rel.Limit;
-import com.alibaba.polardbx.optimizer.core.rel.LogicalIndexScan;
-import com.alibaba.polardbx.optimizer.core.rel.LogicalView;
-import com.alibaba.polardbx.optimizer.core.rel.LookupJoin;
-import com.alibaba.polardbx.optimizer.core.rel.MaterializedSemiJoin;
-import com.alibaba.polardbx.optimizer.core.rel.MemSort;
-import com.alibaba.polardbx.optimizer.core.rel.MergeSort;
-import com.alibaba.polardbx.optimizer.core.rel.MysqlAgg;
-import com.alibaba.polardbx.optimizer.core.rel.MysqlHashJoin;
-import com.alibaba.polardbx.optimizer.core.rel.MysqlIndexNLJoin;
-import com.alibaba.polardbx.optimizer.core.rel.MysqlLimit;
-import com.alibaba.polardbx.optimizer.core.rel.MysqlMaterializedSemiJoin;
-import com.alibaba.polardbx.optimizer.core.rel.MysqlNLJoin;
-import com.alibaba.polardbx.optimizer.core.rel.MysqlSemiHashJoin;
-import com.alibaba.polardbx.optimizer.core.rel.MysqlSemiIndexNLJoin;
-import com.alibaba.polardbx.optimizer.core.rel.MysqlSort;
-import com.alibaba.polardbx.optimizer.core.rel.MysqlTableScan;
-import com.alibaba.polardbx.optimizer.core.rel.MysqlTopN;
-import com.alibaba.polardbx.optimizer.core.rel.NLJoin;
-import com.alibaba.polardbx.optimizer.core.rel.SemiBKAJoin;
-import com.alibaba.polardbx.optimizer.core.rel.SemiHashJoin;
-import com.alibaba.polardbx.optimizer.core.rel.SemiNLJoin;
-import com.alibaba.polardbx.optimizer.core.rel.SemiSortMergeJoin;
-import com.alibaba.polardbx.optimizer.core.rel.SortAgg;
-import com.alibaba.polardbx.optimizer.core.rel.SortMergeJoin;
-import com.alibaba.polardbx.optimizer.core.rel.SortWindow;
-import com.alibaba.polardbx.optimizer.core.rel.TopN;
+import com.alibaba.polardbx.optimizer.core.rel.*;
 import com.alibaba.polardbx.optimizer.index.Index;
 import com.alibaba.polardbx.optimizer.index.IndexUtil;
 import com.alibaba.polardbx.optimizer.memory.MemoryEstimator;
@@ -72,12 +38,7 @@
 import org.apache.calcite.rel.core.Sort;
 import org.apache.calcite.rel.logical.LogicalFilter;
 import org.apache.calcite.rel.logical.LogicalTableLookup;
-import org.apache.calcite.rel.metadata.ChainedRelMetadataProvider;
-import org.apache.calcite.rel.metadata.CyclicMetadataException;
-import org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider;
-import org.apache.calcite.rel.metadata.RelMdPercentageOriginalRows;
-import org.apache.calcite.rel.metadata.RelMetadataProvider;
-import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.rel.metadata.*;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.Util;
@@ -87,6 +48,7 @@
 
 import static com.alibaba.polardbx.optimizer.config.meta.CostModelWeight.LOOKUP_START_UP_NET;
 import static com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil.getRexParam;
+import static com.alibaba.polardbx.optimizer.utils.OptimizerUtils.getParametersMapForOptimizer;
 
 public class DrdsRelMdCost extends RelMdPercentageOriginalRows {
 
@@ -217,7 +179,7 @@ public RelOptCost getCumulativeCost(MysqlLimit rel, RelMetadataQuery mq) {
         RelOptCost inputCost = mq.getCumulativeCost(rel.getInput());
         Double inputRowCount = mq.getRowCount(rel.getInput());
 
-        Map params = PlannerContext.getPlannerContext(rel).getParams().getCurrentParameter();
+        Map params = getParametersMapForOptimizer(rel);
         double skipPlusFetch = 0;
         if (rel.fetch != null) {
             skipPlusFetch += getRexParam(rel.fetch, params);
@@ -262,7 +224,7 @@ private RelOptCost getCumulativeLimitCost(Sort rel, RelMetadataQuery mq) {
         RelOptCost inputCost = mq.getCumulativeCost(rel.getInput());
         Double inputRowCount = mq.getRowCount(rel.getInput());
 
-        Map params = PlannerContext.getPlannerContext(rel).getParams().getCurrentParameter();
+        Map params = getParametersMapForOptimizer(rel);
         double skipPlusFetch = 0;
         if (rel.fetch != null) {
             skipPlusFetch += getRexParam(rel.fetch, params);
@@ -299,7 +261,7 @@ public RelOptCost getCumulativeCost(MysqlTopN rel, RelMetadataQuery mq) {
             return getCumulativeCost((RelNode) rel, mq);
         }
 
-        Map params = PlannerContext.getPlannerContext(rel).getParams().getCurrentParameter();
+        Map params = getParametersMapForOptimizer(rel);
         double skipPlusFetch = 0;
         if (rel.fetch != null) {
             skipPlusFetch += getRexParam(rel.fetch, params);
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdMaxRowCount.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdMaxRowCount.java
index d478ed62e..87bccf4aa 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdMaxRowCount.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdMaxRowCount.java
@@ -36,6 +36,8 @@
 
 import java.util.Map;
 
+import static com.alibaba.polardbx.optimizer.utils.OptimizerUtils.getParametersMapForOptimizer;
+
 public class DrdsRelMdMaxRowCount extends RelMdMaxRowCount {
 
     public static final RelMetadataProvider SOURCE =
@@ -64,12 +66,11 @@ public Double getMaxRowCount(RelSubset rel, RelMetadataQuery mq) {
 
     @Override
     public Double getMaxRowCount(Sort rel, RelMetadataQuery mq) {
-        PlannerContext plannerContext = PlannerContext.getPlannerContext(rel);
         Double rowCount = mq.getMaxRowCount(rel.getInput());
         if (rowCount == null) {
             rowCount = Double.POSITIVE_INFINITY;
         }
-        Map params = plannerContext.getParams().getCurrentParameter();
+        Map params = getParametersMapForOptimizer(rel);
 
         long offset = 0;
         if (rel.offset != null) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdRowCount.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdRowCount.java
index 282efdce9..11a08fe19 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdRowCount.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdRowCount.java
@@ -50,6 +50,8 @@
 import java.util.Map;
 import java.util.Optional;
 
+import static com.alibaba.polardbx.optimizer.utils.OptimizerUtils.getParametersMapForOptimizer;
+
 public class DrdsRelMdRowCount extends RelMdRowCount {
 
     public static final RelMetadataProvider SOURCE =
@@ -76,13 +78,12 @@ public Double getRowCount(XPlanTableScan rel, RelMetadataQuery mq) {
 
     @Override
     public Double getRowCount(Sort rel, RelMetadataQuery mq) {
-        PlannerContext plannerContext = PlannerContext.getPlannerContext(rel);
         Double rowCount = mq.getRowCount(rel.getInput());
         if (rowCount == null) {
             return null;
         }
 
-        Map params = plannerContext.getParams().getCurrentParameter();
+        Map params = getParametersMapForOptimizer(rel);
 
         long offset = 0;
         if (rel.offset != null) {
@@ -172,8 +173,8 @@ public Double getRowCount(DynamicValues rel, RelMetadataQuery mq) {
             if (index < 0) {
                 return super.getRowCount(rel, mq);
             }
-            Parameters parameters = PlannerContext.getPlannerContext(rel).getParams();
-            Object arg = Optional.ofNullable(parameters.getCurrentParameter()).map(params -> params.get(index + 1)).map(
+            Map params = getParametersMapForOptimizer(rel);
+            Object arg = Optional.ofNullable(params).map(map -> map.get(index + 1)).map(
                 ParameterContext::getValue).orElse(null);
             if (arg instanceof RawString) {
                 return (double) ((RawString) arg).size();
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/TableScanIOEstimator.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/TableScanIOEstimator.java
index 68764f4c4..502adab25 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/TableScanIOEstimator.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/meta/TableScanIOEstimator.java
@@ -62,7 +62,7 @@ public class TableScanIOEstimator extends AbstractIOEstimator {
     private final TableScan tableScan;
     private final Double tableRowCount;
     private final TableMeta tableMeta;
-    private final PlannerContext plannerContext;
+
     private final long rowSize;
     private List accessIndexList;
     private Set canUseIndexSet;
@@ -70,10 +70,10 @@ public class TableScanIOEstimator extends AbstractIOEstimator {
     public TableScanIOEstimator(TableScan tableScan, RelMetadataQuery metadataQuery) {
         super(metadataQuery, tableScan.getCluster().getRexBuilder(),
             (Math.ceil((TUPLE_HEADER_SIZE + TableScanIOEstimator.estimateRowSize(tableScan.getRowType()))
-                * tableScan.getTable().getRowCount() / CostModelWeight.SEQ_IO_PAGE_SIZE)));
+                * tableScan.getTable().getRowCount() / CostModelWeight.SEQ_IO_PAGE_SIZE)),
+            PlannerContext.getPlannerContext(tableScan));
         this.tableScan = tableScan;
         this.tableMeta = CBOUtil.getTableMeta(tableScan.getTable());
-        this.plannerContext = PlannerContext.getPlannerContext(tableScan);
         this.tableRowCount = tableMeta.getRowCount(plannerContext);
         this.rowSize = TUPLE_HEADER_SIZE + TableScanIOEstimator.estimateRowSize(tableScan.getRowType());
         this.accessIndexList = new ArrayList<>();
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/schema/TddlCalciteSchema.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/schema/TddlCalciteSchema.java
index 5159c8da4..1dade67c5 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/schema/TddlCalciteSchema.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/schema/TddlCalciteSchema.java
@@ -19,6 +19,7 @@
 import com.alibaba.polardbx.common.exception.TddlRuntimeException;
 import com.alibaba.polardbx.common.exception.code.ErrorCode;
 import com.alibaba.polardbx.gms.metadb.table.TableStatus;
+import com.alibaba.polardbx.gms.topology.DbInfoManager;
 import com.alibaba.polardbx.optimizer.OptimizerContext;
 import com.alibaba.polardbx.optimizer.PlannerContext;
 import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager;
@@ -175,7 +176,14 @@ public ViewProtoDataType(String schemaName, List columnList, String view
         @Override
         public RelDataType apply(RelDataTypeFactory factory) {
             SqlNode ast = new FastsqlParser().parse(viewDefinition).get(0);
-            SqlConverter converter = SqlConverter.getInstance(new ExecutionContext());
+            SqlConverter converter;
+            //if schema is a logical table, e.g. mysql.user, wo don't need to modify the schemaName
+            //however if schema is a physical table, .e.g db.tb1, we set the newest schemaName to ExecutionContext
+            if (DbInfoManager.getInstance().getDbList().contains(this.schemaName)) {
+                converter = SqlConverter.getInstance(this.schemaName, new ExecutionContext(this.schemaName));
+            } else {
+                converter = SqlConverter.getInstance(new ExecutionContext());
+            }
             SqlNode validatedNode = converter.validate(ast);
             RelDataType rowType = converter.toRel(validatedNode).getRowType();
 
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/server/IServerConfigManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/server/IServerConfigManager.java
index e01b60c2f..e0ce41b83 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/server/IServerConfigManager.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/server/IServerConfigManager.java
@@ -26,6 +26,7 @@
 import org.apache.commons.collections.ListUtils;
 
 import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -96,4 +97,43 @@ default List getLoadedSchemas() {
         return Collections.emptyList();
     }
 
+    default Object getTransConnection(String schema) throws SQLException {
+        throw new UnsupportedOperationException("not supported");
+    }
+
+    default Object getTransConnection(String schema, Map sessionVariables) throws SQLException {
+        throw new UnsupportedOperationException("not supported");
+    }
+
+    default void closeTransConnection(Object transConn) throws SQLException {
+        throw new UnsupportedOperationException("not supported");
+    }
+
+    default int executeBackgroundDmlByTransConnection(String sql, String schema, InternalTimeZone timeZone,
+                                                      Object transConn) {
+        throw new UnsupportedOperationException("not supported");
+    }
+
+    default List> executeBackgroundQueryByTransConnection(String sql, String schema,
+                                                                              InternalTimeZone timeZone,
+                                                                              Object transConn) {
+        throw new UnsupportedOperationException("not supported");
+    }
+
+    default void transConnectionBegin(Object transConn) throws SQLException {
+        throw new UnsupportedOperationException("not supported");
+    }
+
+    default void transConnectionCommit(Object transConn) throws SQLException {
+        throw new UnsupportedOperationException("not supported");
+    }
+
+    default void transConnectionRollback(Object transConn) throws SQLException {
+        throw new UnsupportedOperationException("not supported");
+    }
+
+    public static void getColumMetas(ResultSet resultSet) throws SQLException {
+        throw new UnsupportedOperationException("not supported");
+    }
+
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/FileMeta.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/FileMeta.java
index d954f36ef..1c62bcfb8 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/FileMeta.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/FileMeta.java
@@ -20,6 +20,7 @@
 import com.alibaba.polardbx.common.oss.ColumnarFileType;
 import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.common.utils.TreeMaps;
+import com.alibaba.polardbx.gms.engine.FileSystemUtils;
 import com.alibaba.polardbx.gms.metadb.table.FilesRecord;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import org.apache.orc.impl.OrcTail;
@@ -114,8 +115,7 @@ public static FileMeta parseFrom(FilesRecord filesRecord, Function rewriteExprIndex(TableMeta tableMeta,
                 sqlSelectOrderByItem = column.clone();
                 SQLIdentifierExpr id = new SQLIdentifierExpr(newColName);
                 sqlSelectOrderByItem.setExpr(id);
+                //改成列名之后不用括号
+                sqlSelectOrderByItem.setHasParen(false);
             } else {
                 sqlSelectOrderByItem = column.clone();
             }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/GlobalIndexMeta.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/GlobalIndexMeta.java
index c46ef715c..72c263f3a 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/GlobalIndexMeta.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/GlobalIndexMeta.java
@@ -36,6 +36,7 @@
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.sql.validate.SqlValidatorImpl;
 import org.apache.calcite.util.Pair;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -53,9 +54,10 @@
 
 public class GlobalIndexMeta {
 
-    public static boolean hasIndex(String mainTableName, String schemaName, ExecutionContext ec) {
+    public static boolean hasGsi(String mainTableName, String schemaName, ExecutionContext ec) {
         final TableMeta table = ec.getSchemaManager(schemaName).getTable(mainTableName);
-        return table.withGsi();
+        // ignore CCI
+        return table.withGsiExcludingPureCci();
     }
 
     public static int getGsiIndexNum(String mainTableName, String schemaName, ExecutionContext ec) {
@@ -524,11 +526,24 @@ public static IndexType getIndexType(String primaryTable, String index, String s
     public static boolean isEveryUkContainsAllPartitionKey(String table, String schema, boolean includingPrimaryIndex,
                                                            ExecutionContext ec) {
         final TableMeta tableMeta = ec.getSchemaManager(schema).getTable(table);
+        final Map>> tableUkMap =
+            getTableUkMapWithoutImplicitPk(table, schema, includingPrimaryIndex, ec, tableMeta);
+        return isEveryUkContainsAllPartitionKey(tableMeta, tableUkMap, ec);
+    }
+
+    public static @NotNull Map>> getTableUkMapWithoutImplicitPk(String table,
+                                                                                                String schema,
+                                                                                                boolean includingPrimaryIndex,
+                                                                                                ExecutionContext ec,
+                                                                                                TableMeta tableMeta) {
+        if (null == tableMeta) {
+            tableMeta = ec.getSchemaManager(schema).getTable(table);
+        }
         final Map>> tableUkMap = getTableUkMap(tableMeta, includingPrimaryIndex, ec);
         // Skip implicit primary key
         tableUkMap.values().forEach(
             ukMap -> ukMap.entrySet().removeIf(entry -> SqlValidatorImpl.isImplicitKey(entry.getKey())));
-        return isEveryUkContainsAllPartitionKey(tableMeta, tableUkMap, ec);
+        return tableUkMap;
     }
 
     /**
@@ -589,6 +604,37 @@ public static TreeSet getPartitionKeySet(TableMeta primary, ExecutionCon
         return partitionKeySet;
     }
 
+    public static TreeMap> getPartitionKeyMap(String table, String schema,
+                                                                      ExecutionContext ec) {
+        final TableMeta tableMeta = ec.getSchemaManager(schema).getTable(table);
+        return getPartitionKeyMap(tableMeta, ec);
+    }
+
+    public static TreeMap> getPartitionKeyMap(TableMeta primary, ExecutionContext ec) {
+        final List gsiMetaList = getIndex(primary.getTableName(), primary.getSchemaName(), ec);
+
+        // Get all partition key
+        final TreeMap> tablePartitionKeyMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+
+        final TddlRuleManager rm = OptimizerContext.getContext(primary.getSchemaName()).getRuleManager();
+        tablePartitionKeyMap
+            .computeIfAbsent(
+                primary.getTableName(),
+                (k) -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER))
+            .addAll(rm.getSharedColumns(primary.getTableName()));
+
+        for (TableMeta gsiMeta : gsiMetaList) {
+            final String gsiName = gsiMeta.getTableName();
+            final List gsiShardKeyList = rm.getSharedColumns(gsiName);
+            tablePartitionKeyMap
+                .computeIfAbsent(
+                    gsiName,
+                    (k) -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER))
+                .addAll(gsiShardKeyList);
+        }
+        return tablePartitionKeyMap;
+    }
+
     public static Map>> getTableUkMap(String table, String schema,
                                                                       boolean includingPrimaryIndex,
                                                                       ExecutionContext ec) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/GsiMetaManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/GsiMetaManager.java
index 41eab0e3f..e3d5e486b 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/GsiMetaManager.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/GsiMetaManager.java
@@ -16,12 +16,14 @@
 
 package com.alibaba.polardbx.optimizer.config.table;
 
+import com.alibaba.polardbx.common.ColumnarOptions;
 import com.alibaba.polardbx.common.constants.SystemTables;
 import com.alibaba.polardbx.common.exception.TddlRuntimeException;
 import com.alibaba.polardbx.common.exception.code.ErrorCode;
 import com.alibaba.polardbx.common.jdbc.ParameterContext;
 import com.alibaba.polardbx.common.jdbc.ParameterMethod;
 import com.alibaba.polardbx.common.model.lifecycle.AbstractLifecycle;
+import com.alibaba.polardbx.common.properties.ColumnarConfig;
 import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.common.utils.TStringUtil;
 import com.alibaba.polardbx.common.utils.TreeMaps;
@@ -31,12 +33,15 @@
 import com.alibaba.polardbx.gms.listener.impl.MetaDbConfigManager;
 import com.alibaba.polardbx.gms.listener.impl.MetaDbDataIdBuilder;
 import com.alibaba.polardbx.gms.metadb.GmsSystemTables;
+import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigAccessor;
+import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigWithIndexNameRecord;
 import com.alibaba.polardbx.gms.metadb.table.IndexStatus;
 import com.alibaba.polardbx.gms.metadb.table.IndexVisibility;
 import com.alibaba.polardbx.gms.metadb.table.IndexesRecord;
 import com.alibaba.polardbx.gms.metadb.table.TableInfoManager;
 import com.alibaba.polardbx.gms.partition.TablePartitionAccessor;
 import com.alibaba.polardbx.gms.topology.DbInfoManager;
+import com.alibaba.polardbx.gms.util.MetaDbUtil;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.collect.ImmutableList;
@@ -48,6 +53,8 @@
 import org.apache.calcite.linq4j.Ord;
 import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlIndexDefinition.SqlIndexResiding;
+import org.apache.calcite.util.Pair;
+import org.apache.commons.collections.MapUtils;
 
 import javax.sql.DataSource;
 import java.sql.Connection;
@@ -70,6 +77,7 @@
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -1354,6 +1362,12 @@ private static GsiMetaBean mergeIndexTableRecords(List allIndexReco
             result.indexTableRelation = indexTableRelationBuilder.build();
             result.tableMeta = tableMetaBuilder.build();
 
+            try {
+                addColumnarOptions(result);
+            } catch (Throwable t) {
+                logger.error("Add columnar options failed.", t);
+            }
+
             return result;
         }
 
@@ -1388,6 +1402,12 @@ public static GsiMetaBean initTableMeta(GsiMetaManager gsiMetaManager, String sc
                 result.tableMeta = ImmutableMap.of();
             }
 
+            try {
+                addColumnarOptions(result);
+            } catch (Throwable t) {
+                logger.error("Add columnar options failed.", t);
+            }
+
             return result;
         }
 
@@ -1426,9 +1446,61 @@ public static GsiMetaBean initTableMeta(GsiMetaManager gsiMetaManager, String sc
                 result.tableMeta = ImmutableMap.of();
             }
 
+            try {
+                addColumnarOptions(result);
+            } catch (Throwable t) {
+                logger.error("Add columnar options failed.", t);
+            }
+
             return result;
         }
 
+        public static void addColumnarOptions(GsiMetaBean gsiMetaBean) {
+            String schemaName = null;
+            String tableName = null;
+            Map columnarMetaBeans = new HashMap<>();
+            for (GsiTableMetaBean gsiTableMetaBean : gsiMetaBean.tableMeta.values()) {
+                GsiMetaManager.GsiIndexMetaBean indexMetaBean = gsiTableMetaBean.gsiMetaBean;
+                if (null != indexMetaBean && indexMetaBean.indexStatus.isPublished() && indexMetaBean.columnarIndex) {
+                    columnarMetaBeans.put(indexMetaBean.indexName, indexMetaBean);
+                    if (null == schemaName) {
+                        schemaName = indexMetaBean.tableSchema;
+                        tableName = indexMetaBean.tableName;
+                    }
+                }
+            }
+            if (MapUtils.isEmpty(columnarMetaBeans)) {
+                return;
+            }
+
+            // cci name -> config key -> record
+            Map> records = new HashMap<>();
+            Map globalConfig = new HashMap<>();
+            try (Connection connection = MetaDbUtil.getConnection()) {
+                ColumnarConfigAccessor accessor = new ColumnarConfigAccessor();
+                accessor.setConnection(connection);
+                for (ColumnarConfigWithIndexNameRecord record : accessor.query(schemaName, tableName)) {
+                    if (0 == record.tableId) {
+                        globalConfig.put(record.configKey, record.configValue);
+                        continue;
+                    }
+                    records.computeIfAbsent(record.indexName, k -> new HashMap<>())
+                        .put(record.configKey, record.configValue);
+                }
+            } catch (Throwable t) {
+                logger.error("Get columnar config error.", t);
+                return;
+            }
+
+            if (records.isEmpty()) {
+                return;
+            }
+
+            for (Entry gsiIndexMetaBean : columnarMetaBeans.entrySet()) {
+                gsiIndexMetaBean.getValue().updateColumnarOptions(gsiIndexMetaBean.getKey(), records, globalConfig);
+            }
+        }
+
         /**
          * @param tableName main table name
          * @param indexName index table name
@@ -1452,6 +1524,12 @@ public static GsiMetaBean initTableMeta(GsiMetaManager gsiMetaManager, String sc
             result.indexTableRelation = indexTableRelationBuilder.build();
             result.tableMeta = tableMetaBuilder.build();
 
+            try {
+                addColumnarOptions(result);
+            } catch (Throwable t) {
+                logger.error("Add columnar options failed.", t);
+            }
+
             return result;
         }
 
@@ -1793,6 +1871,7 @@ public static class GsiIndexMetaBean extends GsiMeta {
         public final boolean clusteredIndex;
         public final boolean columnarIndex;
         public final IndexVisibility visibility;
+        public AtomicReference> columnarOptions = new AtomicReference<>(new HashMap<>());
 
         public GsiIndexMetaBean(String tableCatalog, String tableSchema, String tableName, boolean nonUnique,
                                 String indexSchema, String indexName, List indexColumns,
@@ -1860,6 +1939,35 @@ public int hashCode() {
             }
             return hashcode;
         }
+
+        public void updateColumnarOptions(String cciName, Map> records,
+                                          Map globalConfig) {
+            Map configMap;
+            Map options = new HashMap<>();
+            if (null != (configMap = records.get(cciName))) {
+                for (Entry option : configMap.entrySet()) {
+                    String optionName = option.getKey();
+                    String optionValue = option.getValue();
+                    if (ColumnarOptions.TYPE.equalsIgnoreCase(optionName)
+                        && ColumnarConfig.SNAPSHOT.equalsIgnoreCase(optionValue)) {
+                        // This cci is a snapshot cci, add columnar snapshot options.
+                        options.put(ColumnarOptions.TYPE, configMap.get(ColumnarOptions.TYPE));
+                        String attribute = ColumnarOptions.SNAPSHOT_RETENTION_DAYS;
+                        options.put(attribute, ColumnarConfig.getValue(attribute, configMap, globalConfig));
+                        attribute = ColumnarOptions.AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL;
+                        options.put(attribute, ColumnarConfig.getValue(attribute, configMap, globalConfig));
+                    } else if ((ColumnarOptions.TYPE.equalsIgnoreCase(optionName)
+                        && ColumnarConfig.DEFAULT.equalsIgnoreCase(optionValue))
+                        || ColumnarOptions.SNAPSHOT_RETENTION_DAYS.equalsIgnoreCase(optionName)
+                        || ColumnarOptions.AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL.equalsIgnoreCase(optionName)) {
+                        // ignore
+                    } else if (null != ColumnarConfig.get(optionName)) {
+                        options.put(optionName, optionValue);
+                    }
+                }
+            }
+            columnarOptions.set(options);
+        }
     }
 
     private static abstract class GsiMeta implements Wrapper {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/IndexMeta.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/IndexMeta.java
index 7fbc7521c..74d55aadb 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/IndexMeta.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/IndexMeta.java
@@ -19,7 +19,6 @@
 import com.alibaba.polardbx.common.utils.GeneralUtil;
 import org.apache.calcite.util.Util;
 import org.apache.commons.lang.StringUtils;
-import org.eclipse.jetty.util.StringUtil;
 
 import java.io.Serializable;
 import java.util.ArrayList;
@@ -39,7 +38,7 @@ public class IndexMeta implements Serializable, Cloneable {
      */
     private final String name;
     /**
-     * 列名字
+     * 列名字,mysql 80 有可能为空list,函数索引没有列名。
      */
     private final List keyColumns; // Keep this for legacy code.
     private final List keyColumnsExt;
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/ScaleOutPlanUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/ScaleOutPlanUtil.java
index b06f3fca0..2eeef460e 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/ScaleOutPlanUtil.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/ScaleOutPlanUtil.java
@@ -221,6 +221,20 @@ public static boolean storageInstIsReady(String storageInstId) {
         }
     }
 
+    public static List getStorageInstReady() {
+        Map storageInstHaCtxCache =
+            StorageHaManager.getInstance().refreshAndGetStorageInstHaContextCache();
+        List storageInstIds = new ArrayList<>();
+        for (String storageInstId : storageInstHaCtxCache.keySet()) {
+            StorageInstHaContext ctx = storageInstHaCtxCache.get(storageInstId);
+            if (ctx == null || !ctx.isAllReplicaReady()) {
+            } else if (ctx.isDNMaster()) {
+                storageInstIds.add(storageInstId);
+            }
+        }
+        return storageInstIds;
+    }
+
     public static DbGroupInfoRecord getDbGroupInfoByGroupName(String groupName) {
         try (Connection metaDbConn = MetaDbDataSource.getInstance().getConnection()) {
             GroupDetailInfoAccessor detailInfoAccessor = new GroupDetailInfoAccessor();
@@ -377,4 +391,5 @@ public static void checkDDLPermission(ExecutionPlan plan, ExecutionContext conte
             }
         }
     }
+
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/SchemaManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/SchemaManager.java
index e2e2bcd49..51c2f8c66 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/SchemaManager.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/SchemaManager.java
@@ -80,6 +80,10 @@ public default TableMeta getTableWithNull(String tableName) {
 
     public GsiMetaBean getGsi(String primaryOrIndexTableName, EnumSet statusSet);
 
+    public default boolean cciExists(String columnarTableName, boolean isColumnar) {
+        return false;
+    }
+
     default Set guessGsi(String unwrappedName, Predicate filter) {
         return Collections.emptySet();
     }
@@ -107,11 +111,13 @@ default TddlRuleManager getTddlRuleManager() {
 
     default void toNewVersionInTrx(List tableNameList,
                                    boolean preemtive, long initWait, long interval, TimeUnit timeUnit,
-                                   long connId, boolean allowTwoVersion, boolean sameTableGroup) {
+                                   long connId, boolean allowTwoVersion, boolean sameTableGroup,
+                                   boolean forceSyncFailed) {
         throw new AssertionError("NOT SUPPORTED");
     }
 
-    default void toNewVersionInTrx(List tableNameList, long connId, boolean allowTwoVersion) {
+    default void toNewVersionInTrx(List tableNameList, long connId, boolean allowTwoVersion,
+                                   boolean forceSyncFailed) {
         throw new AssertionError("NOT SUPPORTED");
     }
 
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/TableColumnUtils.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/TableColumnUtils.java
index fe5491b57..73aaaa1a0 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/TableColumnUtils.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/TableColumnUtils.java
@@ -108,11 +108,6 @@ public static boolean isHiddenColumn(ExecutionContext ec, String schemaName, Str
         return false;
     }
 
-    public static boolean isModifying(RelOptTable primary, ExecutionContext ec) {
-        final Pair schemaTable = RelUtils.getQualifiedTableName(primary);
-        return isModifying(schemaTable.left, schemaTable.right, ec);
-    }
-
     public static boolean isModifying(String schemaName, String tableName, ExecutionContext ec) {
         // In OMC execution, may not be doing column multi-write
         SchemaManager sm;
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/TableMeta.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/TableMeta.java
index ad7c35d13..f38960549 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/TableMeta.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/TableMeta.java
@@ -24,10 +24,12 @@
 import com.alibaba.polardbx.common.utils.TStringUtil;
 import com.alibaba.polardbx.common.utils.version.InstanceVersion;
 import com.alibaba.polardbx.config.ConfigDataMode;
+import com.alibaba.polardbx.druid.sql.SQLUtils;
 import com.alibaba.polardbx.druid.sql.ast.SQLExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLExprUtils;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.parser.MySqlExprParser;
 import com.alibaba.polardbx.gms.metadb.table.ColumnStatus;
+import com.alibaba.polardbx.gms.metadb.table.IndexVisibility;
 import com.alibaba.polardbx.gms.metadb.table.TableStatus;
 import com.alibaba.polardbx.gms.metadb.table.TablesRecord;
 import com.alibaba.polardbx.gms.partition.TablePartitionRecord;
@@ -51,12 +53,14 @@
 import com.alibaba.polardbx.optimizer.rule.TddlRuleManager;
 import com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter;
 import com.alibaba.polardbx.optimizer.tablegroup.TableGroupVersionManager;
+import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo;
 import com.alibaba.polardbx.optimizer.utils.CalciteUtils;
 import com.alibaba.polardbx.optimizer.utils.SchemaVersionManager;
 import com.alibaba.polardbx.rule.TableRule;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.taobao.tddl.common.utils.TddlToStringStyle;
+import lombok.NonNull;
 import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.plan.Context;
 import org.apache.calcite.plan.RelOptCluster;
@@ -184,6 +188,7 @@ public class TableMeta implements Serializable, Cloneable, Table, Wrapper {
     private Map gsiPublished = null;
     private Map columnarIndexPublished = null;
     private Map columnarIndexChecking = null;
+    private Map archiveColumnarIndexPublished = null;
 
     private ComplexTaskOutlineRecord complexTaskOutlineRecord = null;
     private ComplexTaskMetaManager.ComplexTaskTableMetaBean complexTaskTableMetaBean = null;
@@ -207,6 +212,8 @@ public class TableMeta implements Serializable, Cloneable, Table, Wrapper {
 
     private volatile LocalPartitionDefinitionInfo localPartitionDefinitionInfo;
 
+    private volatile TtlDefinitionInfo ttlDefinitionInfo;
+
     private volatile TableFilesMeta tableFilesMeta = null;
 
     private String defaultCharset;
@@ -453,6 +460,74 @@ public List getIndexes() {
         return indexes;
     }
 
+    public boolean checkIndexNameExists(String indexName) {
+        return findLocalIndexByName(indexName) != null || findGlobalSecondaryIndexByName(indexName) != null;
+    }
+
+    /**
+     * Retrieves the local index metadata by its name.
+     *
+     * @param localIndexName the local index name
+     * @return the IndexMeta object if found; otherwise, returns {@code null}
+     */
+    @Nullable
+    public IndexMeta findLocalIndexByName(@NonNull String localIndexName) {
+        // Normalize the input index name without trimming
+        localIndexName = SQLUtils.normalizeNoTrim(localIndexName);
+
+        // Handle primary key
+        if (GeneralUtil.isPrimary(localIndexName)) {
+            return getPrimaryIndex();
+        }
+
+        // Iterate through all indexes to find a non-primary key match
+        for (IndexMeta indexMeta : getAllIndexes()) {
+            if (!indexMeta.isPrimaryKeyIndex() && indexMeta.getPhysicalIndexName().equalsIgnoreCase(localIndexName)) {
+                return indexMeta;
+            }
+        }
+
+        // No matching index found
+        return null;
+    }
+
+    /**
+     * Retrieves the Global Secondary Index (GSI) metadata by its name.
+     *
+     * @param indexName the GSI name (case-insensitive)
+     * @return the GsiIndexMetaBean object if found; otherwise, returns null
+     */
+    public GsiMetaManager.GsiIndexMetaBean findGlobalSecondaryIndexByName(@NonNull String indexName) {
+        // Normalize the input index name
+        String normalizedIndexName = SQLUtils.normalizeNoTrim(indexName);
+
+        if (gsiPublished != null && !gsiPublished.isEmpty()) {
+            for (GsiMetaManager.GsiIndexMetaBean gsiMeta : gsiPublished.values()) {
+                if (gsiMeta.visibility != IndexVisibility.VISIBLE) {
+                    continue;
+                }
+                String gsiIndexName = TddlSqlToRelConverter.unwrapGsiName(gsiMeta.indexName);
+                if (gsiIndexName.equalsIgnoreCase(normalizedIndexName)) {
+                    return gsiMeta;
+                }
+            }
+        }
+
+        if (columnarIndexPublished != null && !columnarIndexPublished.isEmpty()) {
+            for (GsiMetaManager.GsiIndexMetaBean cciMeta : columnarIndexPublished.values()) {
+                if (cciMeta.visibility != IndexVisibility.VISIBLE) {
+                    continue;
+                }
+                String cciName = TddlSqlToRelConverter.unwrapGsiName(cciMeta.indexName);
+                if (cciName.equalsIgnoreCase(normalizedIndexName)) {
+                    return cciMeta;
+                }
+            }
+        }
+
+        return null;
+    }
+
     public Set getLocalIndexNames() {
         Set indexes = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
         indexes.addAll(
@@ -775,6 +850,7 @@ public void setGsiTableMetaBean(GsiMetaManager.GsiTableMetaBean gsiTableMetaBean
             this.gsiPublished = new HashMap<>();
             this.columnarIndexPublished = new HashMap<>();
             this.columnarIndexChecking = new HashMap<>();
+            this.archiveColumnarIndexPublished = new HashMap<>();
             for (Entry indexMetaBeanEntry : gsiTableMetaBean.indexMap.entrySet()) {
                 if (indexMetaBeanEntry.getValue().indexStatus.isWriteReorg()
                     && indexMetaBeanEntry.getValue().columnarIndex) {
@@ -793,6 +869,7 @@ public void setGsiTableMetaBean(GsiMetaManager.GsiTableMetaBean gsiTableMetaBean
         }
     }
 
+    // CCI是GSI的子集,可能包含GSI和CCI
     public boolean withGsi() {
         return null != getGsiTableMetaBean() && getGsiTableMetaBean().tableType != GsiMetaManager.TableType.GSI
             && GeneralUtil.isNotEmpty(getGsiTableMetaBean().indexMap);
@@ -808,6 +885,16 @@ public boolean withCci() {
             .stream().anyMatch(index -> index.columnarIndex);
     }
 
+    // CCI是GSI的子集,当indexMap中都为columnarIndex时,证明表中全部都是CCI
+    public boolean allCci() {
+        return withCci() && getGsiTableMetaBean().indexMap.values()
+            .stream().allMatch(index -> index.columnarIndex);
+    }
+
+    public boolean withGsiExcludingPureCci() {
+        return withGsi() && !allCci();
+    }
+
     public boolean hasCci(String indexName) {
         Set cciNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
         getGsiTableMetaBean().indexMap.forEach((key, value) -> {
@@ -876,6 +963,20 @@ public boolean withColumnar() {
             && GeneralUtil.isNotEmpty(getGsiTableMetaBean().indexMap);
     }
 
+    public boolean isColumnarArchive() {
+        String ttlTable = this.columnarOriginTable();
+        TableMeta ttlTm = OptimizerContext.getContext(this.getSchemaName()).getLatestSchemaManager().getTableWithNull(ttlTable);
+        if (ttlTm == null) {
+            return false;
+        }
+        for (String key : ttlTm.getArchiveColumnarIndexPublished().keySet()) {
+            if (key.equals(this.getTableName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public String columnarOriginTable() {
         if (getGsiTableMetaBean() == null) {
             return null;
@@ -997,6 +1098,18 @@ public String getDefaultCollation() {
         return defaultCollation;
     }
 
+    public TtlDefinitionInfo getTtlDefinitionInfo() {
+        return ttlDefinitionInfo;
+    }
+
+    public void setTtlDefinitionInfo(TtlDefinitionInfo ttlDefinitionInfo) {
+        this.ttlDefinitionInfo = ttlDefinitionInfo;
+    }
+
+    public Map getArchiveColumnarIndexPublished() {
+        return archiveColumnarIndexPublished;
+    }
+
     private class TableMetaInitializerExpressionFactory extends NullInitializerExpressionFactory {
         @Override
         public RexNode newColumnDefaultValue(RelOptTable table, int iColumn, InitializerContext context) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/CollationHandler.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/CollationHandler.java
index e00330f6c..2347aa042 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/CollationHandler.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/CollationHandler.java
@@ -87,13 +87,6 @@ default boolean wildCompare(Slice slice, Slice wildCard) {
         return false;
     }
 
-    /**
-     * match pattern '%xxx%'
-     */
-    default boolean containsCompare(Slice slice, byte[] wildCard, int[] lps) {
-        return false;
-    }
-
     /**
      * Hash code of utf8 string should obey all three criteria in the contract:
      * 1. internal consistency: the value of hashCode() may only change if a property that is in equals() changes
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/Latin1BinCollationHandler.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/Latin1BinCollationHandler.java
index 1bfac8989..dc88923e2 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/Latin1BinCollationHandler.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/Latin1BinCollationHandler.java
@@ -18,13 +18,39 @@
 
 import com.alibaba.polardbx.common.charset.CollationName;
 import com.alibaba.polardbx.common.charset.SortKey;
+import com.alibaba.polardbx.common.utils.logger.Logger;
+import com.alibaba.polardbx.common.utils.logger.LoggerFactory;
 import com.alibaba.polardbx.optimizer.config.table.charset.CharsetHandler;
+import io.airlift.slice.JvmUtils;
 import io.airlift.slice.Slice;
 import io.airlift.slice.SliceInput;
 
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+
+import java.lang.invoke.MethodType;
 import java.nio.ByteBuffer;
 
+import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
+
 public class Latin1BinCollationHandler extends AbstractCollationHandler {
+
+    private static final Logger logger = LoggerFactory.getLogger(Latin1BinCollationHandler.class);
+    private static boolean useNativeMethod = true;
+    private static MethodHandle latin1IndexOfHandle = null;
+
+    static {
+        try {
+            Class clazz = Class.forName("java.lang.StringLatin1");
+            MethodHandles.Lookup lookup = JvmUtils.trustedLookup(String.class);
+            MethodType methodType = MethodType.methodType(int.class, byte[].class, int.class, byte[].class,
+                int.class, int.class);
+            latin1IndexOfHandle = lookup.findStatic(clazz, "indexOf", methodType);
+        } catch (Throwable t) {
+            logger.error(t.getMessage(), t);
+        }
+    }
+
     public Latin1BinCollationHandler(CharsetHandler charsetHandler) {
         super(charsetHandler);
     }
@@ -153,34 +179,109 @@ public boolean wildCompare(Slice slice, Slice wildCard) {
         return doWildCompare(slice, 0, wildCard, 0) == 0;
     }
 
-    @Override
-    public boolean containsCompare(Slice slice, byte[] wildCard, int[] lps) {
+    public boolean contains(Slice slice, byte[] wildCard) {
         if (wildCard == null || wildCard.length == 0) {
             // like '%%' always match
             return true;
         }
-        int length = slice.length();
-        int i = 0;
-        int j = 0;
-
-        while (i < length) {
-            if (wildCard[j] == slice.getByteUnchecked(i)) {
-                i++;
-                j++;
+
+        if (latin1IndexOfHandle != null && useNativeMethod) {
+            Object base = slice.getBase();
+            if (base instanceof byte[]) {
+                try {
+                    int offset = (int) (slice.getAddress() - ARRAY_BYTE_BASE_OFFSET);
+                    // should follow the rules inside the intrinsic method
+                    int result = (int) latin1IndexOfHandle.invokeExact((byte[]) base, slice.length() + offset,
+                        wildCard, wildCard.length, offset);
+                    return result >= 0;
+                } catch (Throwable t) {
+                    // unexpected exception occurs in invocation
+                    // set useNativeMethod to false to avoid repeated errors
+                    logger.error(t.getMessage(), t);
+                    useNativeMethod = false;
+                }
+            }
+        }
+
+        byte first = wildCard[0];
+        int max = slice.length() - wildCard.length;
+        for (int i = 0; i <= max; i++) {
+            if (slice.getByteUnchecked(i) != first) {
+                while (++i <= max && slice.getByteUnchecked(i) != first) {
+                    // move on until first byte matches
+                }
             }
-            if (j == wildCard.length) {
-                return true;
-            } else if (i < length && wildCard[j] != slice.getByteUnchecked(i)) {
-                if (j != 0) {
-                    j = lps[j - 1];
-                } else {
-                    i++;
+            if (i <= max) {
+                int j = i + 1;
+                int end = j + wildCard.length - 1;
+                for (int k = 1; j < end && slice.getByteUnchecked(j) == wildCard[k]; j++, k++) {
+                    // stop when not matching
+                }
+                if (j == end) {
+                    return true;
                 }
             }
         }
+
         return false;
     }
 
+    public boolean startsWith(Slice slice, byte[] wildCard) {
+        int len = slice.length();
+        if (len < wildCard.length) {
+            return false;
+        }
+        if (wildCard.length == 0) {
+            return true;
+        }
+        Object base = slice.getBase();
+        if (base instanceof byte[]) {
+            byte[] bytes = (byte[]) base;
+            int offset = (int) (slice.getAddress() - ARRAY_BYTE_BASE_OFFSET);
+            for (int i = 0; i < wildCard.length; i++) {
+                // be careful with this unchecked behavior
+                if (bytes[i + offset] != wildCard[i]) {
+                    return false;
+                }
+            }
+        } else {
+            for (int i = 0; i < wildCard.length; i++) {
+                if (slice.getByteUnchecked(i) != wildCard[i]) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public boolean endsWith(Slice slice, byte[] wildCard) {
+        int len = slice.length();
+        if (len < wildCard.length) {
+            return false;
+        }
+        if (wildCard.length == 0) {
+            return true;
+        }
+        Object base = slice.getBase();
+        if (base instanceof byte[]) {
+            byte[] bytes = (byte[]) base;
+            int offset = (int) (slice.getAddress() - ARRAY_BYTE_BASE_OFFSET);
+            for (int i = wildCard.length - 1, j = len - 1; i >= 0; i--, j--) {
+                // be careful with this unchecked behavior
+                if (bytes[j + offset] != wildCard[i]) {
+                    return false;
+                }
+            }
+        } else {
+            for (int i = wildCard.length - 1, j = len - 1; i >= 0; i--, j--) {
+                if (slice.getByteUnchecked(j) != wildCard[i]) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     /**
      * @return -1代表不匹配,0代表匹配,1代表继续
      */
@@ -258,7 +359,7 @@ private int doWildCompare(Slice str, int strIdx, Slice wildstr, int wildstrIdx)
                     if (tmp <= 0) {
                         return tmp;
                     }
-                } while (strIdx != strEnd && wildstr.getByte(wildstrIdx) != WILD_MANY);
+                } while (strIdx != strEnd);
 
                 return -1;
             }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/Utf8mb4GeneralCiCollationHandler.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/Utf8mb4GeneralCiCollationHandler.java
index f8ff14c00..ba089ddb8 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/Utf8mb4GeneralCiCollationHandler.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/collation/Utf8mb4GeneralCiCollationHandler.java
@@ -132,23 +132,6 @@ public boolean wildCompare(Slice slice, Slice wildCard) {
         return doWildCompare(slice, wildCard) == 0;
     }
 
-    /**
-     * FIXME high overhead implementation
-     */
-    @Override
-    public boolean containsCompare(Slice slice, byte[] wildCard, int[] lps) {
-        if (wildCard == null || wildCard.length == 0) {
-            // like '%%' always match
-            return true;
-        }
-        byte[] containWildCard = new byte[wildCard.length + 2];
-        containWildCard[0] = WILD_MANY;
-        System.arraycopy(wildCard, 0, containWildCard, 1, wildCard.length);
-        containWildCard[containWildCard.length - 1] = WILD_MANY;
-        Slice wildCardSlice = Slices.wrappedBuffer(containWildCard);
-        return doWildCompare(slice, wildCardSlice) == 0;
-    }
-
     public int doWildCompare(Slice slice, Slice wildCard) {
         int sliceCodePoint, wildCodePoint;
         SliceInput str = slice.getInput();
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/Histogram.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/Histogram.java
index 9a151a3e4..4b14a0043 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/Histogram.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/Histogram.java
@@ -19,9 +19,11 @@
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.alibaba.polardbx.common.utils.LoggerUtil;
 import com.alibaba.polardbx.common.utils.logger.Logger;
 import com.alibaba.polardbx.common.utils.time.core.TimeStorage;
+import com.alibaba.polardbx.druid.util.StringUtils;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
 
@@ -403,8 +405,10 @@ public static String serializeToJson(Histogram histogram) {
                 bucketJson.put("upper", bucket.upper.toString());
                 bucketJson.put("lower", bucket.lower.toString());
             } else {
-                bucketJson.put("upper", bucket.upper);
-                bucketJson.put("lower", bucket.lower);
+                bucketJson.put("upper",
+                    JSON.toJSONString(bucket.upper, SerializerFeature.DisableCircularReferenceDetect));
+                bucketJson.put("lower",
+                    JSON.toJSONString(bucket.lower, SerializerFeature.DisableCircularReferenceDetect));
             }
             bucketsJsonArray.add(bucketJson);
         }
@@ -412,6 +416,9 @@ public static String serializeToJson(Histogram histogram) {
     }
 
     public static Histogram deserializeFromJson(String json) {
+        if (StringUtils.isEmpty(json)) {
+            return null;
+        }
         try {
             JSONObject histogramJson = JSON.parseObject(json);
             String type = histogramJson.getString("type");
@@ -431,6 +438,12 @@ public static Histogram deserializeFromJson(String json) {
                 } else {
                     bucket.lower = bucketJson.get("lower");
                     bucket.upper = bucketJson.get("upper");
+                    try {
+                        validateBucketBounds(bucket);
+                    } catch (IllegalArgumentException e) {
+                        logger.error("validateBucketBounds error ", e);
+                        return null;
+                    }
                 }
                 bucket.count = bucketJson.getIntValue("count");
                 bucket.preSum = bucketJson.getIntValue("preSum");
@@ -444,6 +457,24 @@ public static Histogram deserializeFromJson(String json) {
         }
     }
 
+    /**
+     * Validates histogram bucket boundaries to ensure they are not empty or instances of JSONObject.
+     * Throws an IllegalArgumentException if either lower or upper bounds are invalid.
+     *
+     * @param bucket The Histogram Bucket object whose boundaries need to be validated.
+     */
+    protected static void validateBucketBounds(Bucket bucket) {
+        // Check if the lower bound is null or an instance of JSONObject
+        if (bucket.getLower() == null || bucket.getLower() instanceof JSONObject) {
+            throw new IllegalArgumentException("Invalid lower bound in histogram bucket: " + bucket.getLower());
+        }
+
+        // Check if the upper bound is null or an instance of JSONObject
+        if (bucket.getUpper() == null || bucket.getUpper() instanceof JSONObject) {
+            throw new IllegalArgumentException("Invalid upper bound in histogram bucket: " + bucket.getUpper());
+        }
+    }
+
     /**
      * optimize for reading
      */
@@ -493,6 +524,10 @@ private static Object deserializeTimeObject(DataType datatype, Object obj) {
         }
     }
 
+    public float getSampleRate() {
+        return sampleRate;
+    }
+
     public static class Bucket {
         private Object lower;
         private Object upper;
@@ -519,6 +554,26 @@ public int getPreSum() {
         public int getNdv() {
             return ndv;
         }
+
+        public void setLower(Object lower) {
+            this.lower = lower;
+        }
+
+        public void setUpper(Object upper) {
+            this.upper = upper;
+        }
+
+        public void setCount(int count) {
+            this.count = count;
+        }
+
+        public void setPreSum(int preSum) {
+            this.preSum = preSum;
+        }
+
+        public void setNdv(int ndv) {
+            this.ndv = ndv;
+        }
     }
 
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/MockStatisticDatasource.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/MockStatisticDatasource.java
index 3d1a28205..af31c1d56 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/MockStatisticDatasource.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/MockStatisticDatasource.java
@@ -160,7 +160,11 @@ public Collection loadAllColumnStatistic(long si
                     if (columnList != null) {
                         for (Pair columnInfo : columnList) {
                             Map histMap = (Map) columnInfo.getValue();
-                            if (histMap == null) {
+                            if (histMap == null || histMap.get("valueArr") == null) {
+                                continue;
+                            }
+                            if (histMap.get("valueArr") instanceof List
+                                && ((List) histMap.get("valueArr")).size() == 0) {
                                 continue;
                             }
                             JSONObject topNJson = new JSONObject();
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/MockStatisticManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/MockStatisticManager.java
index ac80151da..4351468b0 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/MockStatisticManager.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/MockStatisticManager.java
@@ -17,17 +17,12 @@
 package com.alibaba.polardbx.optimizer.config.table.statistic;
 
 public class MockStatisticManager extends StatisticManager {
-    public MockStatisticManager(String schemaName,
-                                StatisticDataSource sds) {
+    public MockStatisticManager() {
         super();
     }
-//    public MockStatisticManager(String schemaName,
-//                                SystemTableTableStatistic systemTableTableStatistic,
-//                                SystemTableColumnStatistic systemTableColumnStatistic,
-//                                SystemTableNDVSketchStatistic ndvSketchStatistic,
-//                                NDVSketchService ndvSketch,
-//                                Map connectionProperties) {
-//        super(schemaName, systemTableTableStatistic, systemTableColumnStatistic, ndvSketchStatistic, ndvSketch,
-//            connectionProperties);
-//    }
+
+    @Override
+    protected void doInit() {
+    }
+
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticDataSource.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticDataSource.java
index cfd7406ae..34a35b9ec 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticDataSource.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticDataSource.java
@@ -64,14 +64,14 @@ public interface StatisticDataSource {
      */
     void updateColumnCardinality(String schema, String tableName, String columnName, ExecutionContext ec,
                                  ThreadPoolExecutor sketchHllExecutor)
-        throws SQLException;
+        throws Exception;
 
     /**
      * force rebuilt ndv info by table name and column name from meta source
      */
     void rebuildColumnCardinality(String schema, String tableName, String columnName, ExecutionContext ec,
                                   ThreadPoolExecutor sketchHllExecutor)
-        throws SQLException;
+        throws Exception;
 
     /**
      * get current ndv value from cache
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticDataTableSource.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticDataTableSource.java
index 61a3657a6..766ad3b83 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticDataTableSource.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticDataTableSource.java
@@ -23,7 +23,6 @@
 import com.alibaba.polardbx.optimizer.config.table.statistic.inf.SystemTableTableStatistic;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 
-import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -135,14 +134,14 @@ public void removeNdvLogicalTable(String schema, String logicalTableName) {
     @Override
     public void updateColumnCardinality(String schema, String tableName, String columnName, ExecutionContext ec,
                                         ThreadPoolExecutor sketchHllExecutor)
-        throws SQLException {
+        throws Exception {
         ndvSketch.updateAllShardParts(schema, tableName, columnName, ec, sketchHllExecutor);
     }
 
     @Override
     public void rebuildColumnCardinality(String schema, String tableName, String columnNames, ExecutionContext ec,
                                          ThreadPoolExecutor sketchHllExecutor)
-        throws SQLException {
+        throws Exception {
         ndvSketch.reBuildShardParts(schema, tableName, columnNames, ec, sketchHllExecutor);
     }
 
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticFeedbackSyncAction.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticFeedbackSyncAction.java
new file mode 100644
index 000000000..34f9f5d42
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticFeedbackSyncAction.java
@@ -0,0 +1,44 @@
+package com.alibaba.polardbx.optimizer.config.table.statistic;
+
+import com.alibaba.polardbx.gms.node.LeaderStatusBridge;
+import com.alibaba.polardbx.gms.sync.IGmsSyncAction;
+
+/**
+ * @author jilong.ljl
+ */
+public class StatisticFeedbackSyncAction implements IGmsSyncAction {
+
+    private String schema;
+
+    private String table;
+
+    public StatisticFeedbackSyncAction(String schema, String table) {
+        this.schema = schema;
+        this.table = table;
+    }
+
+    @Override
+    public Object sync() {
+        if (LeaderStatusBridge.getInstance().hasLeadership()) {
+            StatisticManager.getInstance().feedback(schema, table);
+        }
+        return null;
+    }
+
+    public String getSchema() {
+        return schema;
+    }
+
+    public void setSchema(String schema) {
+        this.schema = schema;
+    }
+
+    public String getTable() {
+        return table;
+    }
+
+    public void setTable(String table) {
+        this.table = table;
+    }
+}
+
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticManager.java
index 6c4fe5553..a0b713317 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticManager.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticManager.java
@@ -41,6 +41,8 @@
 import com.alibaba.polardbx.gms.module.ModuleInfo;
 import com.alibaba.polardbx.gms.module.ModuleLogInfo;
 import com.alibaba.polardbx.gms.node.LeaderStatusBridge;
+import com.alibaba.polardbx.gms.sync.GmsSyncManagerHelper;
+import com.alibaba.polardbx.gms.sync.SyncScope;
 import com.alibaba.polardbx.gms.topology.SystemDbHelper;
 import com.alibaba.polardbx.optimizer.OptimizerContext;
 import com.alibaba.polardbx.optimizer.config.table.ColumnMeta;
@@ -63,6 +65,7 @@
 import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPrunerUtils;
 import com.alibaba.polardbx.rule.TableRule;
 import com.alibaba.polardbx.rule.model.TargetDB;
+import com.alibaba.polardbx.stats.metric.FeatureStats;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -71,7 +74,6 @@
 import org.apache.commons.collections.CollectionUtils;
 
 import java.io.IOException;
-import java.sql.SQLException;
 import java.sql.Timestamp;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -93,8 +95,10 @@
 import static com.alibaba.polardbx.common.properties.ConnectionParams.CACHELINE_COMPENSATION_BLACKLIST;
 import static com.alibaba.polardbx.common.properties.ConnectionParams.CACHELINE_INDICATE_UPDATE_TIME;
 import static com.alibaba.polardbx.common.properties.ConnectionParams.ENABLE_CACHELINE_COMPENSATION;
+import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_STATISTIC_FEEDBACK;
 import static com.alibaba.polardbx.common.utils.GeneralUtil.unixTimeStamp;
 import static com.alibaba.polardbx.gms.module.LogPattern.PROCESS_END;
+import static com.alibaba.polardbx.gms.module.LogPattern.PROCESS_SKIPPED;
 import static com.alibaba.polardbx.gms.module.LogPattern.PROCESS_START;
 import static com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils.DATA_MAX_LEN;
 import static com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils.buildSketchKey;
@@ -110,6 +114,8 @@
 import static com.alibaba.polardbx.optimizer.view.VirtualViewType.STATISTICS;
 import static com.alibaba.polardbx.optimizer.view.VirtualViewType.STATISTICS_DATA;
 import static com.alibaba.polardbx.optimizer.view.VirtualViewType.VIRTUAL_STATISTIC;
+import static com.alibaba.polardbx.stats.metric.FeatureStatsItem.HLL_TASK_FAIL;
+import static com.alibaba.polardbx.stats.metric.FeatureStatsItem.HLL_TASK_SUCC;
 
 public class StatisticManager extends AbstractLifecycle implements StatisticService, ModuleInfo {
 
@@ -138,6 +144,10 @@ public static StatisticManager getInstance() {
         return sm;
     }
 
+    public static void setExecutor(ThreadPoolExecutor executor) {
+        StatisticManager.executor = executor;
+    }
+
     @Override
     protected void doInit() {
         // Skip StatisticManager init in mock mode or build in schema
@@ -249,6 +259,9 @@ public CacheLine getCacheLine(String schema, String logicalTableName, boolean by
             logicalTableName = getSourceTableName(schema, logicalTableName);
         }
         String schemaLower = schema.toLowerCase();
+        if (SystemDbHelper.isDBBuildIn(schema)) {
+            return new CacheLine();
+        }
         if (!statisticCache.containsKey(schemaLower)) {
             statisticCache.put(schemaLower, Maps.newConcurrentMap());
         }
@@ -324,11 +337,13 @@ public StatisticResult getRowCount(String schema, String logicalTableName, boole
         return StatisticResult.build(CACHE_LINE).setValue(rowCount, statisticTrace);
     }
 
-    private StatisticResult getCorrectionResult(String catalog, String method, boolean isNeedTrace) {
+    protected StatisticResult getCorrectionResult(String catalog, String method, boolean isNeedTrace) {
         if (correctionsMap.isEmpty()) {
             return null;
         }
-        String val = correctionsMap.get("Catalog:" + catalog + "\nAction:" + method);
+        String key = "Catalog:" + catalog + "\nAction:" + method;
+        key = GeneralUtil.removeIdxSuffix(key);
+        String val = correctionsMap.get(key.toLowerCase());
         if (!StringUtils.isEmpty(val)) {
             try {
                 Long rs = Long.parseLong(val);
@@ -336,7 +351,16 @@ private StatisticResult getCorrectionResult(String catalog, String method, boole
                     StatisticUtils.buildTrace(catalog, method, rs, CORRECTIONS, -1L, "") : null;
                 return StatisticResult.build(CORRECTIONS).setValue(rs, statisticTrace);
             } catch (NumberFormatException nfe) {
-                return null;
+                // try boolean
+                if ("true".equalsIgnoreCase(val) ||
+                    "false".equalsIgnoreCase(val)) {
+                    boolean rs = Boolean.parseBoolean(val);
+                    StatisticTrace statisticTrace = isNeedTrace ?
+                        StatisticUtils.buildTrace(catalog, method, rs, CORRECTIONS, -1L, "") : null;
+                    return StatisticResult.build(CORRECTIONS).setValue(rs, statisticTrace);
+                } else {
+                    return null;
+                }
             }
         }
         return null;
@@ -513,6 +537,61 @@ static protected StatisticResult handleInFrequencyDegradation(StatisticResult ro
         return StatisticResult.build(CACHE_LINE).setValue(frequency, statisticTrace);
     }
 
+    public StatisticResult getFrequencyUpperLimit(String schema, String logicalTableName, String columnName,
+                                                  boolean isNeedTrace) {
+        // try corrections first
+        StatisticResult correctionsSr =
+            getCorrectionResult(
+                schema + "," + logicalTableName + "," + columnName,
+                "getFrequencyUpperLimit", isNeedTrace);
+        if (correctionsSr != null) {
+            return correctionsSr;
+        }
+
+        columnName = columnName.toLowerCase();
+
+        StatisticResult cardinality = getCardinality(schema, logicalTableName, columnName, true, isNeedTrace);
+        if (cardinality.getLongValue() > 0) {
+            CacheLine cacheLine = getCacheLine(schema, logicalTableName);
+            TopN topN = cacheLine.getTopN(columnName);
+            if (topN != null) {
+                long topNCount = topN.getMaxCount();
+                // for a table with 100000k rows, sample 1/1k rows which is 100k rows.
+                // A value appeared more than 10k times is sampled >=5 W.H.P.
+                // A value appeared less than 2k times is sampled <5 W.H.P.
+                if (topNCount >= 5 && cacheLine.getSampleRate() > 0) {
+                    Object statisticValue = topNCount / cacheLine.getSampleRate();
+                    StatisticTrace statisticTrace = isNeedTrace ?
+                        StatisticUtils.buildTrace(
+                            schema + "," + logicalTableName + "," + columnName,
+                            "getFrequencyUpperLimit", statisticValue,
+                            TOP_N, cacheLine.getLastModifyTime(),
+                            "topN count(" + topNCount + ")/sample rate(" + cacheLine.getSampleRate() + ")") : null;
+                    return StatisticResult.build(TOP_N).setValue(statisticValue, statisticTrace);
+                }
+            }
+            StatisticResult sr = getRowCount(schema, logicalTableName, isNeedTrace);
+            Object statisticValue = Math.max(sr.getLongValue() / cardinality.getLongValue(), 1);
+            StatisticTrace statisticTrace = isNeedTrace ?
+                StatisticUtils.buildTrace(
+                    schema + "," + logicalTableName + "," + columnName,
+                    "getFrequency", statisticValue,
+                    CACHE_LINE, cacheLine.getLastModifyTime(),
+                    "max(rowcount(" + sr.getLongValue() + ")/cardinality(" + cardinality.getLongValue() + "), 1)") :
+                null;
+            return StatisticResult.build(CACHE_LINE).setValue(statisticValue, statisticTrace);
+        } else {
+            StatisticTrace statisticTrace = isNeedTrace ?
+                StatisticUtils.buildTrace(
+                    schema + "," + logicalTableName + "," + columnName,
+                    "getFrequency", cardinality.getLongValue(),
+                    NULL, -1L, "").addChild(cardinality.getTrace()) : null;
+
+            // return -1 value
+            return StatisticResult.build(NULL).setValue(-1L, statisticTrace);
+        }
+    }
+
     public StatisticResult getFrequency(String schema, String logicalTableName, String columnName, String value,
                                         boolean isNeedTrace) {
         DataType dataType = dataTypeCheck(schema, logicalTableName, columnName);
@@ -528,6 +607,9 @@ public StatisticResult getFrequency(String schema, String logicalTableName, Stri
     }
 
     public String truncateStringTypeValue(String schema, String logicalTableName, String columnName, String value) {
+        if (StringUtils.isEmpty(value)) {
+            return value;
+        }
         DataType columnRealType = getRealDataType(schema, logicalTableName, columnName);
         return (DataTypeUtil.isStringType(columnRealType) && value.length() > DATA_MAX_LEN) ?
             value.substring(0, DATA_MAX_LEN) : value;
@@ -539,6 +621,10 @@ public String truncateStringTypeValue(String schema, String logicalTableName, St
      */
     public StatisticResult getFrequencyInner(String schema, String logicalTableName, String columnName, String value,
                                              boolean isNeedTrace) {
+        schema = schema.toLowerCase();
+        logicalTableName = logicalTableName.toLowerCase();
+        columnName = columnName.toLowerCase();
+
         logicalTableName = getSourceTableName(schema, logicalTableName);
         // try corrections first
         StatisticResult correctionsSr =
@@ -549,45 +635,48 @@ public StatisticResult getFrequencyInner(String schema, String logicalTableName,
             return correctionsSr;
         }
 
-        columnName = columnName.toLowerCase();
+        // Adaptive Processing : To decide whether to use histogram or topn or rowcount/ndv to calculate frequency
+        // If topn contains this value, then use topn;
+        // If cardinality was from sample process, then should use rowcount/ndv;
+        // If cardinality was from ndv sketch, then we should compare it with sample ndv,
+        // If two numbers are similar below a threshold, then should use histogram, otherwise use rowcount/ndv
+        CacheLine cacheLine = getCacheLine(schema, logicalTableName);
+        TopN topN = cacheLine.getTopN(columnName);
+        if (topN != null) {
+            Long topNCount = topN.rangeCount(value, true, value, true);
+            if (topNCount > 0) {
+                // topn branch
+                Long statisticValue = (long) (topNCount / cacheLine.getSampleRate());
+                StatisticTrace statisticTrace = isNeedTrace ?
+                    StatisticUtils.buildTrace(
+                        schema + "," + logicalTableName + "," + columnName + "," + digestForStatisticTrace(value),
+                        "getFrequency", statisticValue,
+                        TOP_N, cacheLine.getLastModifyTime(),
+                        "topN count(" + topNCount + ")/sample rate(" + cacheLine.getSampleRate() + ")") : null;
+                return StatisticResult.build(TOP_N).setValue(statisticValue, statisticTrace);
+            }
+        }
 
         StatisticResult cardinality = getCardinality(schema, logicalTableName, columnName, true, isNeedTrace);
-        if (cardinality.getLongValue() > 0) {
-            if (cardinality.getLongValue() < 100) {
-                // small enough, use histogram
-                StatisticResult rangeCount =
-                    getRangeCount(schema, logicalTableName, columnName, value, true, value, true, isNeedTrace);
-                if (rangeCount.getLongValue() >= 0) {
-                    if (isNeedTrace) {
-                        StatisticTrace statisticTrace =
-                            StatisticUtils.buildTrace(
-                                schema + "," + logicalTableName + "," + columnName + "," + digestForStatisticTrace(
-                                    value),
-                                "getFrequency", rangeCount.getLongValue(),
-                                NULL, -1L, "ndv small enough to use histogram");
-                        statisticTrace.addChild(cardinality.getTrace());
-                        statisticTrace.addChild(rangeCount.getTrace());
-                        rangeCount.setTrace(statisticTrace);
-                    }
-                    return rangeCount;
-                }
-            }
-            CacheLine cacheLine = getCacheLine(schema, logicalTableName);
-            TopN topN = cacheLine.getTopN(columnName);
-            if (topN != null) {
-                long topNCount = topN.rangeCount(value, true, value, true);
-                if (topNCount != 0 && cacheLine.getSampleRate() > 0) {
-                    Object statisticValue = topNCount / cacheLine.getSampleRate();
-                    StatisticTrace statisticTrace = isNeedTrace ?
-                        StatisticUtils.buildTrace(
-                            schema + "," + logicalTableName + "," + columnName + "," + digestForStatisticTrace(value),
-                            "getFrequency", statisticValue,
-                            TOP_N, cacheLine.getLastModifyTime(),
-                            "topN count(" + topNCount + ")/sample rate(" + cacheLine.getSampleRate() + ")") : null;
-                    return StatisticResult.build(TOP_N).setValue(statisticValue, statisticTrace);
+        if (cardinality.getSource() == HLL_SKETCH) {
+            long hllNdv = cardinality.getLongValue();
+
+            Long sampleNdv = cacheLine.getCardinalityMap().get(columnName);
+            if (sampleNdv != null &&
+                GeneralUtil.isWithinPercentage(hllNdv, sampleNdv,
+                    DynamicConfig.getInstance().getNdvAlikePercentageThreshold())) {
+                StatisticResult statisticResult =
+                    getSingleValFrequencyFromHistogram(schema, logicalTableName, columnName, value,
+                        cacheLine.getHistogramMap(),
+                        isNeedTrace, cacheLine.getLastModifyTime(), cacheLine.getSampleRate());
+                if (statisticResult != null) {
+                    return statisticResult;
                 }
             }
-            StatisticResult sr = getRowCount(schema, logicalTableName, isNeedTrace);
+        }
+
+        StatisticResult sr = getRowCount(schema, logicalTableName, isNeedTrace);
+        if (cardinality != null && sr != null && cardinality.getLongValue() > 0L && sr.getLongValue() != -1L) {
             Object statisticValue = Math.max(sr.getLongValue() / cardinality.getLongValue(), 1);
             StatisticTrace statisticTrace = isNeedTrace ?
                 StatisticUtils.buildTrace(
@@ -596,17 +685,55 @@ public StatisticResult getFrequencyInner(String schema, String logicalTableName,
                     CACHE_LINE, cacheLine.getLastModifyTime(),
                     "max(rowcount(" + sr.getLongValue() + ")/cardinality(" + cardinality.getLongValue() + "), 1)") :
                 null;
+            if (statisticTrace != null) {
+                statisticTrace.addChild(sr.getTrace());
+                statisticTrace.addChild(cardinality.getTrace());
+            }
             return StatisticResult.build(CACHE_LINE).setValue(statisticValue, statisticTrace);
-        } else {
-            StatisticTrace statisticTrace = isNeedTrace ?
-                StatisticUtils.buildTrace(
-                    schema + "," + logicalTableName + "," + columnName + "," + digestForStatisticTrace(value),
-                    "getFrequency", cardinality.getLongValue(),
-                    NULL, -1L, "").addChild(cardinality.getTrace()) : null;
+        }
 
-            // return -1 value
-            return StatisticResult.build(NULL).setValue(-1L, statisticTrace);
+        StatisticTrace statisticTrace = null;
+        if (isNeedTrace) {
+            statisticTrace = StatisticUtils.buildTrace(
+                schema + "," + logicalTableName + "," + columnName + "," + digestForStatisticTrace(value),
+                "getFrequency", cardinality == null ? -1L : cardinality.getLongValue(),
+                NULL, -1L, "");
+            if (cardinality != null) {
+                statisticTrace.addChild(cardinality.getTrace());
+            }
+            if (sr != null) {
+                statisticTrace.addChild(sr.getTrace());
+            }
         }
+
+        // return -1 value
+        return StatisticResult.build(NULL).setValue(-1L, statisticTrace);
+    }
+
+    protected static StatisticResult getSingleValFrequencyFromHistogram(String schema,
+                                                                        String table,
+                                                                        String columnName,
+                                                                        String value,
+                                                                        Map histogramMap,
+                                                                        boolean isNeedTrace,
+                                                                        long lastModifyTime,
+                                                                        float cachelineSampleRate) {
+        // If two numbers are similar below exita threshold, then should use histogram
+        if (histogramMap != null && histogramMap.get(columnName) != null) {
+            Histogram histogram = histogramMap.get(columnName);
+            if (histogram != null) {
+                long rangeCountInHistogram = histogram.rangeCount(value, true, value, true);
+                rangeCountInHistogram = (long) Math.max((rangeCountInHistogram) / cachelineSampleRate, 0);
+                if (rangeCountInHistogram > 0) {
+                    StatisticTrace statisticTrace = isNeedTrace ? StatisticUtils.buildTrace(
+                        schema + "," + table + "," + columnName + "," + digestForStatisticTrace(value),
+                        "getFrequency", rangeCountInHistogram, HISTOGRAM, lastModifyTime,
+                        "histogram count/sample rate(" + cachelineSampleRate + ")") : null;
+                    return StatisticResult.build(HISTOGRAM).setValue(rangeCountInHistogram, statisticTrace);
+                }
+            }
+        }
+        return null;
     }
 
     public DataType getRealDataType(String schemaName, String logicalTableName, String columnName) {
@@ -776,10 +903,13 @@ private long transformDateToUnixTimestamp(Object obj, DataType dataType) {
     private long maxStatisticVal(CacheLine cacheLine, String columnName) {
         Map histogramMap = cacheLine.getHistogramMap();
         TopN topN = cacheLine.getTopN(columnName);
-        if (histogramMap == null || histogramMap.get(columnName) == null || topN == null) {
+        if (histogramMap == null || topN == null) {
             return -1L;
         }
         Histogram histogram = histogramMap.get(columnName);
+        if (histogram == null) {
+            return -1L;
+        }
         List buckets = histogram.getBuckets();
         long dataUpValue = -1L;
         if (buckets.size() != 0) {
@@ -974,24 +1104,10 @@ public void addUpdateRowCount(String schema, String logicalTableName, long affec
         long originRowCount = cacheLine.getOriginRowCount();
         if (shouldCollectUpdate(schema, updateRowCount, originRowCount)) {
             cacheLine.resetUpdateRowCount();
-
-            // TODO move this job to schedule job
-            executor.execute(() -> {
-                if (InstConfUtil.getBool(ConnectionParams.ENABLE_STATISTIC_FEEDBACK)) {
-                    ModuleLogInfo.getInstance().logRecord(Module.STATISTICS, PROCESS_START,
-                        new String[] {
-                            "statistic feedback rowcount:" + schema + "," + logicalTableName,
-                            "old " + originRowCount + ", new " + updateRowCount}, LogLevel.NORMAL);
-                    long start = System.currentTimeMillis();
-                    sds.sampleColumns(schema, logicalTableName);
-                    // column statistic
-                    long end = System.currentTimeMillis();
-                    ModuleLogInfo.getInstance().logRecord(Module.STATISTICS, PROCESS_END,
-                        new String[] {
-                            "statistic feedback rowcount:" + schema + "," + logicalTableName,
-                            "consuming " + (end - start) / 1000.0 + " seconds"}, LogLevel.NORMAL);
-                }
-            });
+            executor.execute(() ->
+                GmsSyncManagerHelper.sync(new StatisticFeedbackSyncAction(schema, logicalTableName),
+                    SystemDbHelper.DEFAULT_DB_NAME,
+                    SyncScope.MASTER_ONLY));
         }
     }
 
@@ -1256,6 +1372,50 @@ Map getCardinalitySketch() {
         return cardinalitySketch;
     }
 
+    public void feedback(String schema, String table) {
+        // check statistic info update time for target table, if it was updated within 1 min, then drop this feedback
+        CacheLine cacheLine = getCacheLine(schema, table);
+        if (cacheLine == null) {
+            ModuleLogInfo.getInstance()
+                .logError(Module.STATISTICS, "FEEDBACK" + schema + ":" + table, new Exception("cacheline is null"));
+            return;
+        }
+        if (cacheLine.getLastModifyTime() > System.currentTimeMillis() / 1000 - 60) {
+            ModuleLogInfo.getInstance()
+                .logInfo(Module.STATISTICS, PROCESS_END, new String[] {"FEEDBACK", schema + ":" + table});
+            return;
+        }
+        cacheLine.resetUpdateRowCount();
+        executor.execute(() -> {
+            feedbackJob(schema, table, cacheLine);
+        });
+    }
+
+    protected void feedbackJob(String schema, String table, CacheLine cacheLine) {
+        // check time again
+        if (cacheLine.getLastModifyTime() > System.currentTimeMillis() / 1000 - 60) {
+            ModuleLogInfo.getInstance()
+                .logInfo(Module.STATISTICS, PROCESS_END, new String[] {"FEEDBACK", schema + ":" + table});
+            return;
+        }
+        if (InstConfUtil.getBool(ConnectionParams.ENABLE_STATISTIC_FEEDBACK)) {
+            long start = System.currentTimeMillis();
+            sds.sampleColumns(schema, table);
+            // column statistic
+            long end = System.currentTimeMillis();
+            ModuleLogInfo.getInstance().logInfo(Module.STATISTICS, PROCESS_END,
+                new String[] {
+                    "statistic feedback " + schema + "," + table,
+                    "consuming " + (end - start) / 1000.0 + " seconds"});
+        } else {
+            ModuleLogInfo.getInstance().logInfo(Module.STATISTICS, PROCESS_SKIPPED,
+                new String[] {
+                    "statistic feedback " + schema + "," + table,
+                    ENABLE_STATISTIC_FEEDBACK + " is false"});
+        }
+
+    }
+
     public enum AutoAnalyzeState {
         RUNNING,
         WAITING
@@ -1267,7 +1427,9 @@ public void updateAllShardParts(String schema, String tableName, String columnNa
             getSds().updateColumnCardinality(schema, tableName, columnName, ec, sketchHllExecutor);
             String key = buildSketchKey(schema, tableName, columnName);
             cardinalitySketch.put(key, getSds().syncCardinality().get(key));
-        } catch (SQLException sqlException) {
+            FeatureStats.getInstance().increment(HLL_TASK_SUCC);
+        } catch (Exception sqlException) {
+            FeatureStats.getInstance().increment(HLL_TASK_FAIL);
             logger.error("error when updateAllShardParts:" + tableName + "," + columnName, sqlException);
         }
     }
@@ -1281,7 +1443,9 @@ public void rebuildShardParts(String schema, String tableName, String columnName
         try {
             getSds().rebuildColumnCardinality(schema, tableName, columnName, ec, sketchHllExecutor);
             cardinalitySketch.putAll(getSds().syncCardinality());
-        } catch (SQLException sqlException) {
+            FeatureStats.getInstance().increment(HLL_TASK_SUCC);
+        } catch (Exception sqlException) {
+            FeatureStats.getInstance().increment(HLL_TASK_FAIL);
             logger.error("error when rebuildShardParts:" + tableName + "," + columnName, sqlException);
         }
     }
@@ -1299,9 +1463,9 @@ public static class CacheLine {
 
         private long originRowCount = 0;
         private AtomicLong updateRowCount = new AtomicLong(0);
-        private Map cardinalityMap;
-        private Map nullCountMap;
-        private Map histogramMap;
+        private Map cardinalityMap = Maps.newHashMap();
+        private Map nullCountMap = Maps.newHashMap();
+        private Map histogramMap = Maps.newHashMap();
         private Map topNMap = Maps.newHashMap();
         private List> skewCols = Lists.newArrayList();
         private float sampleRate = 1;
@@ -1448,7 +1612,9 @@ public void setLastAccessTime(long lastAccessTime) {
 
         public boolean hasExpire() {
             return ((topNMap == null || topNMap.isEmpty()) &&
-                (histogramMap == null || histogramMap.isEmpty())) ||
+                (histogramMap == null || histogramMap.isEmpty()) &&
+                originRowCount > 0)
+                ||
                 (unixTimeStamp() - getLastModifyTime()) >
                     InstConfUtil.getInt(ConnectionParams.STATISTIC_EXPIRE_TIME);
         }
@@ -1521,8 +1687,10 @@ public static CacheLine deserializeFromJson(String json) {
             JSONObject histogramMapJsonObject = cacheLineJson.getJSONObject("histogramMap");
             for (String columnName : histogramMapJsonObject.keySet()) {
                 columnName = columnName.toLowerCase(Locale.ROOT);
-                histogramMap
-                    .put(columnName, Histogram.deserializeFromJson(histogramMapJsonObject.getString(columnName)));
+                Histogram histogram = Histogram.deserializeFromJson(histogramMapJsonObject.getString(columnName));
+                if (histogram != null) {
+                    histogramMap.put(columnName, histogram);
+                }
             }
             cacheLine.setHistogramMap(histogramMap);
 
@@ -1530,7 +1698,10 @@ public static CacheLine deserializeFromJson(String json) {
             JSONObject topNMapJsonObject = cacheLineJson.getJSONObject("topNMap");
             for (String columnName : topNMapJsonObject.keySet()) {
                 columnName = columnName.toLowerCase(Locale.ROOT);
-                topNMap.put(columnName, TopN.deserializeFromJson(topNMapJsonObject.getString(columnName)));
+                TopN topN = TopN.deserializeFromJson(topNMapJsonObject.getString(columnName));
+                if (topN != null) {
+                    topNMap.put(columnName, topN);
+                }
             }
             cacheLine.setTopNMap(topNMap);
             cacheLine.setExtend(cacheLineJson.getString("extend"));
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticUtils.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticUtils.java
index f45aeea42..194c6d008 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticUtils.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticUtils.java
@@ -18,6 +18,7 @@
 
 import com.alibaba.polardbx.common.datatype.RowValue;
 import com.alibaba.polardbx.common.utils.LoggerUtil;
+import com.alibaba.polardbx.common.datatype.RowValue;
 import com.alibaba.polardbx.common.utils.logger.Logger;
 import com.alibaba.polardbx.common.utils.time.core.TimeStorage;
 import com.alibaba.polardbx.optimizer.OptimizerContext;
@@ -231,35 +232,7 @@ public static List getColumnMetas(boolean onlyAnalyzeColumnWithIndex
             return null;
         }
 
-        List analyzeColumnList;
-        if (onlyAnalyzeColumnWithIndex) {
-            Map columnMetaMap = new HashMap<>();
-            for (IndexMeta indexMeta : tableMeta.getIndexes()) {
-                for (ColumnMeta columnMeta : indexMeta.getKeyColumns()) {
-                    if (!isBinaryOrJsonColumn(columnMeta)) {
-                        columnMetaMap.put(columnMeta.getName().toLowerCase(), columnMeta);
-                    }
-                }
-            }
-
-            // gsi
-            Map gsiIndexMetaBeanMap = tableMeta.getGsiPublished();
-            if (gsiIndexMetaBeanMap != null) {
-                for (GsiMetaManager.GsiIndexMetaBean gsiIndexMetaBean : gsiIndexMetaBeanMap.values()) {
-                    for (GsiMetaManager.GsiIndexColumnMetaBean gsiIndexColumnMetaBean : gsiIndexMetaBean.indexColumns) {
-                        ColumnMeta columnMeta = tableMeta.getColumn(gsiIndexColumnMetaBean.columnName);
-                        columnMetaMap.put(columnMeta.getName().toLowerCase(), columnMeta);
-                    }
-
-                }
-            }
-
-            analyzeColumnList = columnMetaMap.entrySet().stream().map(x -> x.getValue()).collect(Collectors.toList());
-        } else {
-            analyzeColumnList =
-                tableMeta.getAllColumns().stream().filter(x -> !isBinaryOrJsonColumn(x)).collect(Collectors.toList());
-        }
-        return analyzeColumnList;
+        return tableMeta.getAllColumns().stream().filter(x -> !isBinaryOrJsonColumn(x)).collect(Collectors.toList());
     }
 
     /**
@@ -277,7 +250,7 @@ public static String buildColumnsName(Collection cols) {
     public static String buildColumnsName(List cols, int index) {
         String[] orderStr = Arrays.copyOf(cols.toArray(new String[0]), index);
         Arrays.sort(orderStr);
-        return String.join(",", orderStr);
+        return String.join(",", orderStr).toLowerCase();
     }
 
     public static String buildSketchKey(String schemaName, String tableName, String columnNames) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/TopN.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/TopN.java
index 021c0186f..ce8fbb475 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/TopN.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/TopN.java
@@ -19,7 +19,10 @@
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.alibaba.polardbx.common.properties.ConnectionParams;
+import com.alibaba.polardbx.common.utils.LoggerUtil;
+import com.alibaba.polardbx.common.utils.logger.Logger;
 import com.alibaba.polardbx.common.utils.time.core.TimeStorage;
 import com.alibaba.polardbx.gms.config.impl.InstConfUtil;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
@@ -37,6 +40,7 @@
 import java.util.stream.Collectors;
 
 public class TopN {
+    private static final Logger logger = LoggerUtil.statisticsLogger;
     /**
      * middle value
      */
@@ -49,6 +53,7 @@ public class TopN {
     private long[] countArr;
     private long[] prefixCountArr;
     private final double sampleRate;
+    private long maxCount;
 
     public TopN(DataType dataType, double sampleRate) {
         this.dataType = dataType;
@@ -56,13 +61,15 @@ public TopN(DataType dataType, double sampleRate) {
         valueMap = Maps.newHashMap();
     }
 
-    public TopN(Object[] valueArr, long[] countArr, long[] prefixCountArr, DataType dataType, double sampleRate) {
+    public TopN(Object[] valueArr, long[] countArr, long[] prefixCountArr, DataType dataType, double sampleRate,
+                long maxCount) {
         assert valueArr.length == countArr.length;
         this.dataType = dataType;
         this.valueArr = valueArr;
         this.countArr = countArr;
         this.prefixCountArr = prefixCountArr;
         this.sampleRate = sampleRate;
+        this.maxCount = maxCount;
         this.build = true;
     }
 
@@ -241,12 +248,13 @@ public boolean buildNew(int maxSize, int minCount, boolean relevantError) {
         valueArr = new Object[loc];
         countArr = new long[loc];
         prefixCountArr = new long[loc];
+        maxCount = 0;
         for (int i = 0; i < loc; i++) {
             valueArr[i] = valueList.get(i);
             countArr[i] = valueMap.get(valueArr[i]);
             prefixCountArr[i] = (i == 0 ? 0 : prefixCountArr[i - 1]) + countArr[i];
+            maxCount = Math.max(maxCount, countArr[i]);
         }
-
         this.build = true;
         valueMap.clear();
         return true;
@@ -315,6 +323,11 @@ public boolean buildDefault(int n, int min) {
         return true;
     }
 
+    public long getMaxCount() {
+        return maxCount;
+    }
+
+    // static method
     public static String serializeToJson(TopN topN) {
         if (topN == null) {
             return null;
@@ -333,7 +346,7 @@ public static String serializeToJson(TopN topN) {
         topNJson.put("sampleRate", topN.sampleRate);
         topNJson.put("valueArr", valueJsonArray);
         topNJson.put("countArr", countJsonArray);
-        return topNJson.toJSONString();
+        return topNJson.toString(SerializerFeature.DisableCircularReferenceDetect);
     }
 
     public static TopN deserializeFromJson(String json) {
@@ -351,16 +364,48 @@ public static TopN deserializeFromJson(String json) {
         JSONArray valueJsonArray = topNJson.getJSONArray("valueArr");
         JSONArray countJsonArray = topNJson.getJSONArray("countArr");
         Object[] valueArr = valueJsonArray.toArray();
+        try {
+            validateTopNValues(valueArr);
+        } catch (IllegalArgumentException e) {
+            logger.error("validateBucketBounds error ", e);
+            return null;
+        }
         Object[] countObjArr = countJsonArray.toArray();
         long[] countArr = new long[countObjArr.length];
         for (int i = 0; i < countObjArr.length; i++) {
             countArr[i] = Long.parseLong(countObjArr[i].toString());
         }
         long[] prefixCountArr = new long[countObjArr.length];
+        long maxCount = 0L;
         for (int i = 0; i < countObjArr.length; i++) {
             prefixCountArr[i] = (i == 0 ? 0 : prefixCountArr[i - 1]) + countArr[i];
+            maxCount = Math.max(maxCount, countArr[i]);
+        }
+        return new TopN(valueArr, countArr, prefixCountArr, datatype, sampleRate, maxCount);
+    }
+
+    /**
+     * Validates the elements within a top N value array to ensure they meet specific criteria.
+     * Throws an IllegalArgumentException if the array is null, empty, contains null elements,
+     * or includes elements of type JSONObject.
+     *
+     * @param values An array containing the values to be validated.
+     */
+    protected static void validateTopNValues(final Object[] values) {
+        // Check if the array is null or empty
+        if (values == null || values.length == 0) {
+            throw new IllegalArgumentException("The values array cannot be null or empty.");
+        }
+
+        // Iterate through the array to check each element
+        for (final Object value : values) {
+            if (value == null) {
+                throw new IllegalArgumentException("The values array should not contain any null elements.");
+            }
+            if (value instanceof JSONObject) {
+                throw new IllegalArgumentException("The values array should not contain elements of type JSONObject.");
+            }
         }
-        return new TopN(valueArr, countArr, prefixCountArr, datatype, sampleRate);
     }
 
     /**
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/inf/NDVSketchService.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/inf/NDVSketchService.java
index c43e00e9c..2c3a100e2 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/inf/NDVSketchService.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/inf/NDVSketchService.java
@@ -31,13 +31,13 @@ public interface NDVSketchService {
      * 重建全部分片的 ndv sketch 信息
      */
     void reBuildShardParts(String schema, String tableName, String columnName, ExecutionContext ec,
-                           ThreadPoolExecutor sketchHllExecutor) throws SQLException;
+                           ThreadPoolExecutor sketchHllExecutor) throws Exception;
 
     /**
      * 更新所有分片的 ndv sketch 信息,如果不存在重建.如果已存在则判断是否需要更新
      */
     void updateAllShardParts(String schema, String tableName, String columnName, ExecutionContext ec,
-                             ThreadPoolExecutor sketchHllExecutor) throws SQLException;
+                             ThreadPoolExecutor sketchHllExecutor) throws Exception;
 
     /**
      * 加载组装 meta db 中的数据
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/inf/SystemTableNDVSketchStatistic.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/inf/SystemTableNDVSketchStatistic.java
index dddcb721b..4aed83b84 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/inf/SystemTableNDVSketchStatistic.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/config/table/statistic/inf/SystemTableNDVSketchStatistic.java
@@ -16,7 +16,6 @@
 
 package com.alibaba.polardbx.optimizer.config.table.statistic.inf;
 
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -34,8 +33,8 @@ public interface SystemTableNDVSketchStatistic {
 
     SketchRow[] loadByTableName(String schemaName, String tableName);
 
-    void loadByTableNameAndColumnName(String schemaName, String tableName, String columnName,
-                                      Map shardParts, int[] registers);
+    boolean loadByTableNameAndColumnName(String schemaName, String tableName, String columnName,
+                                         Map shardParts, int[] registers);
 
     void batchReplace(final SketchRow[] rowList);
 
@@ -53,6 +52,8 @@ class SketchRow {
          */
         private String shardPart;
 
+        private String indexName;
+
         /**
          * the ndv value record from dn, most likely not accurate
          */
@@ -68,30 +69,33 @@ class SketchRow {
 
         private long gmtUpdate;
 
-        public SketchRow(String schemaName, String tableName, String columnNames, String shardPart,
+        public SketchRow(String schemaName, String tableName, String columnNames, String shardPart, String indexName,
                          long dnCardinality, long compositeCardinality, String sketchType) {
             this.schemaName = schemaName;
             this.tableName = tableName;
             this.columnNames = columnNames;
             this.shardPart = shardPart;
+            this.indexName = indexName;
             this.dnCardinality = dnCardinality;
             this.compositeCardinality = compositeCardinality;
             this.sketchType = sketchType;
         }
 
-        public SketchRow(String schemaName, String tableName, String columnNames, String shardPart,
+        public SketchRow(String schemaName, String tableName, String columnNames, String shardPart, String indexName,
                          long dnCardinality, long compositeCardinality, String sketchType, long gmtCreate,
                          long gmtUpdate) {
-            this(schemaName, tableName, columnNames, shardPart, dnCardinality, compositeCardinality, sketchType);
+            this(schemaName, tableName, columnNames, shardPart, indexName, dnCardinality, compositeCardinality,
+                sketchType);
             this.gmtCreate = gmtCreate;
             this.gmtUpdate = gmtUpdate;
         }
 
-        public SketchRow(String schemaName, String tableName, String columnNames, String shardPart,
+        public SketchRow(String schemaName, String tableName, String columnNames, String shardPart, String indexName,
                          long dnCardinality, long compositeCardinality, String sketchType, byte[] sketchBytes,
                          long gmtCreate,
                          long gmtUpdate) {
-            this(schemaName, tableName, columnNames, shardPart, dnCardinality, compositeCardinality, sketchType,
+            this(schemaName, tableName, columnNames, shardPart, indexName, dnCardinality, compositeCardinality,
+                sketchType,
                 gmtCreate, gmtUpdate);
             this.sketchBytes = sketchBytes;
         }
@@ -196,5 +200,13 @@ public long getCompositeCardinality() {
         public void setCompositeCardinality(long compositeCardinality) {
             this.compositeCardinality = compositeCardinality;
         }
+
+        public String getIndexName() {
+            return indexName;
+        }
+
+        public void setIndexName(String indexName) {
+            this.indexName = indexName;
+        }
     }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/context/DdlContext.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/context/DdlContext.java
index b913a8de6..04b25685c 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/context/DdlContext.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/context/DdlContext.java
@@ -60,6 +60,10 @@ public class DdlContext {
     private DdlState pausedPolicy = DdlState.RUNNING;
     private DdlState rollbackPausedPolicy = DdlState.ROLLBACK_RUNNING;
     private String cdcRewriteDdlStmt;
+    /**
+     * subjob 中是否打标,暂时只支持普通的 CdcDdlMarkTask
+     */
+    private boolean skipSubJobCdcMark = false;
 
     private ConcurrentHashMap physicalDdlInjectionFlag = new ConcurrentHashMap<>();
 
@@ -215,6 +219,7 @@ public DdlContext copy() {
         res.setTimeZone(getTimeZone());
         res.setParentDdlContext(getParentDdlContext());
         res.setForeignKeyOriginalSql(getForeignKeyOriginalSql());
+        res.setSkipSubJobCdcMark(isSkipSubJobCdcMark());
 
         return res;
     }
@@ -537,4 +542,12 @@ public void setForeignKeyOriginalSql(String foreignKeyOriginalSql) {
     public String getForeignKeyOriginalSql() {
         return this.foreignKeyOriginalSql;
     }
+
+    public void setSkipSubJobCdcMark(boolean skipSubJobCdcMark) {
+        this.skipSubJobCdcMark = skipSubJobCdcMark;
+    }
+
+    public boolean isSkipSubJobCdcMark() {
+        return skipSubJobCdcMark;
+    }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/context/ExecutionContext.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/context/ExecutionContext.java
index fdb36b81c..ceabbe7e6 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/context/ExecutionContext.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/context/ExecutionContext.java
@@ -18,6 +18,7 @@
 
 import com.alibaba.polardbx.Capabilities;
 import com.alibaba.polardbx.common.DefaultSchema;
+import com.alibaba.polardbx.common.MergedStorageInfo;
 import com.alibaba.polardbx.common.SQLMode;
 import com.alibaba.polardbx.common.charset.CharsetName;
 import com.alibaba.polardbx.common.exception.TddlRuntimeException;
@@ -26,6 +27,7 @@
 import com.alibaba.polardbx.common.jdbc.Parameters;
 import com.alibaba.polardbx.common.jdbc.ShareReadViewPolicy;
 import com.alibaba.polardbx.common.logical.ITConnection;
+import com.alibaba.polardbx.common.oss.IDeltaReadOption;
 import com.alibaba.polardbx.common.privilege.PrivilegeVerifyItem;
 import com.alibaba.polardbx.common.properties.ConnectionParams;
 import com.alibaba.polardbx.common.properties.ConnectionProperties;
@@ -40,6 +42,7 @@
 import com.alibaba.polardbx.common.utils.timezone.InternalTimeZone;
 import com.alibaba.polardbx.druid.sql.ast.SqlType;
 import com.alibaba.polardbx.druid.sql.parser.ByteString;
+import com.alibaba.polardbx.gms.metadb.columnar.FlashbackColumnarManager;
 import com.alibaba.polardbx.gms.metadb.table.TableInfoManager;
 import com.alibaba.polardbx.gms.privilege.AccountType;
 import com.alibaba.polardbx.gms.privilege.PolarPrivManager;
@@ -68,8 +71,11 @@
 import com.alibaba.polardbx.stats.MatrixStatistics;
 import com.alibaba.polardbx.util.ValueHolder;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import lombok.Getter;
+import lombok.Setter;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.CorrelationId;
 import org.apache.calcite.rex.RexDynamicParam;
@@ -94,6 +100,7 @@
 import java.util.TreeMap;
 import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
 
 import static com.alibaba.polardbx.common.jdbc.ITransactionPolicy.TransactionClass.TSO_TRANSACTION;
 
@@ -231,7 +238,7 @@ public class ExecutionContext {
 
     private ExplainResult explain;
     private SqlType sqlType;
-    private BitSet planProperties = new BitSet();
+    private BitSet planProperties = new BitSet(ExecutionPlanProperties.getMaxPropertyValue());
 
     /**
      * 用于sql.log日志,方便sql审计 hasScanWholeTable 是否存在全表扫描 :
@@ -334,6 +341,8 @@ public boolean isEnableTwoPhaseDdl() {
 
     private PrivilegeContext privilegeContext;
 
+    private boolean flashbackArea = false;
+
     private long txId = 0L;
     private long connId;
     private String clientIp;
@@ -367,19 +376,11 @@ public boolean isEnableTwoPhaseDdl() {
     /**
      * For DirectShardingKeyTableOperation
      */
-    private long backfillId;
-    private boolean clientFoundRows = true;
+    private Long backfillId;
+    private Long taskId;
 
-    /**
-     * enable the rule counter in cbo
-     * there is no need to copy the value
-     */
-    private boolean enableRuleCounter = false;
-    /**
-     * record the times of rules called in cbo
-     * there is no need to copy the value
-     */
-    private long ruleCount = 0;
+    private long estimatedBackfillBatchRows;
+    private boolean clientFoundRows = true;
 
     private volatile XplanStat xplanStat = null;
     private volatile Integer blockBuilderCapacity = null;
@@ -387,6 +388,8 @@ public boolean isEnableTwoPhaseDdl() {
     private volatile Boolean enableOssDelayMaterializationOnExchange = null;
 
     private int columnarMaxShard = -1;
+    private boolean useColumnar = false;
+    private boolean columnarPlanCache = false;
 
     private boolean executingPreparedStmt = false;
     private PreparedStmtCache preparedStmtCache = null;
@@ -414,15 +417,38 @@ public boolean isCursorFetchMode() {
 
     private boolean needAutoSavepoint = false;
 
+    private Set ignoredGsiSet = null;
+
     private Map> driverStatistics;
 
     private boolean checkingCci = false;
 
-    private List readOrcFiles = null;
+    private Map> readOrcFiles = null;
+
+    private Map readDeltaFiles = null;
+
+    private Map, FlashbackColumnarManager> fcManager = new HashMap<>();
+
+    @Getter
+    @Setter
+    private Function storageInfoSupplier;
 
     private long pruningTime = 0L;
 
-    private String partitionName;
+    public boolean isOverrideDdlParams() {
+        return overrideDdlParams;
+    }
+
+    public void setOverrideDdlParams(boolean overrideDdlParams) {
+        this.overrideDdlParams = overrideDdlParams;
+    }
+
+    private boolean overrideDdlParams = false;
+
+    /**
+     * Set this flag to true when executing user sql.
+     */
+    private boolean userSql = false;
 
     public ExecutionContext() {
     }
@@ -770,6 +796,14 @@ public void setMemoryPool(MemoryPool memoryPool) {
         memoryPoolHolder.initQueryMemoryPool(memoryPool);
     }
 
+    public boolean isFlashbackArea() {
+        return flashbackArea;
+    }
+
+    public void setFlashbackArea(boolean flashbackArea) {
+        this.flashbackArea = flashbackArea;
+    }
+
     public void renewMemoryPoolHolder() {
         memoryPoolHolder.destroy();
         this.memoryPoolHolder = new QueryMemoryPoolHolder();
@@ -884,6 +918,10 @@ public ColumnarTracer getColumnarTracer() {
         return columnarTracer;
     }
 
+    public boolean getUseColumnarTracer() {
+        return columnarTracer != null;
+    }
+
     public void setColumnarTracer(ColumnarTracer columnarTracer) {
         this.columnarTracer = columnarTracer;
     }
@@ -987,6 +1025,18 @@ public void setSqlType(SqlType sqlType) {
         }
     }
 
+    public void setIgnoredGsi(Set gsiSet) {
+        if (gsiSet == null) {
+            ignoredGsiSet = null;
+            return;
+        }
+        ignoredGsiSet = ImmutableSet.builder().addAll(gsiSet).build();
+    }
+
+    public Set getIgnoredGsi() {
+        return ignoredGsiSet;
+    }
+
     public boolean isModifyBroadcastTable() {
         return getPlanProperties().get(ExecutionPlanProperties.MODIFY_BROADCAST_TABLE);
     }
@@ -1258,7 +1308,9 @@ public ExecutionContext copy(CopyOption option) {
         ec.isOriginSqlPushdownOrRoute = isOriginSqlPushdownOrRoute();
         ec.privilegeContext = getPrivilegeContext();
         ec.txId = getTxId();
+        ec.ignoredGsiSet = getIgnoredGsi();
         ec.clientIp = getClientIp();
+        ec.flashbackArea = isFlashbackArea();
         ec.connId = getConnId();
         ec.rescheduled = isRescheduled();
         ec.testMode = isTestMode();
@@ -1282,6 +1334,7 @@ public ExecutionContext copy(CopyOption option) {
         ec.optimizedWithReturning = isOptimizedWithReturning();
         ec.readOnly = isReadOnly();
         ec.backfillId = getBackfillId();
+        ec.taskId = getTaskId();
         ec.clientFoundRows = isClientFoundRows();
         ec.blockBuilderCapacity = getBlockBuilderCapacity();
         ec.enableOssCompatible = isEnableOssCompatible();
@@ -1293,7 +1346,12 @@ public ExecutionContext copy(CopyOption option) {
         ec.needAutoSavepoint = isNeedAutoSavepoint();
         ec.setColumnarTracer(getColumnarTracer());
         ec.columnarMaxShard = getColumnarMaxShard();
+        ec.useColumnar = isUseColumnar();
+        ec.columnarPlanCache = isColumnarPlanCache();
+        ec.storageInfoSupplier = getStorageInfoSupplier();
         ec.pruningTime = getPruningTime();
+        ec.overrideDdlParams = isOverrideDdlParams();
+        ec.userSql = isUserSql();
         return ec;
     }
 
@@ -1545,6 +1603,10 @@ public void newStatement() {
         this.preparedStmtCache = null;
     }
 
+    public MergedStorageInfo getStorageInfo(String schemaName) {
+        return storageInfoSupplier.apply(schemaName);
+    }
+
     public SchemaManager getSchemaManager(String schemaName) {
         if (schemaName == null) {
             schemaName = DefaultSchema.getSchemaName();
@@ -1782,10 +1844,21 @@ public void clearContextInsideTrans() {
 
         calcitePlanOptimizerTrace = null;
 
+        flashbackArea = false;
+
         // reset use hint flag
         useHint = false;
         xplanStat = null;
         pruningTime = 0L;
+        ignoredGsiSet = null;
+
+        // clear tid
+        sqlTemplateId = null;
+        columnarMaxShard = -1;
+        useColumnar = false;
+        columnarPlanCache = false;
+
+        planProperties = new BitSet();
     }
 
     /**
@@ -1844,7 +1917,6 @@ public void clearContextAfterTrans() {
         privilegeVerifyItems = new ArrayList<>();
         onlyUseTmpTblPool = true;
         internalSystemSql = true;
-        sqlTemplateId = null;
         runtimeStatistics = null;
         usingPhySqlCache = false;
         doingBatchInsertBySpliter = false;
@@ -1894,14 +1966,14 @@ public void clearContextAfterTrans() {
         optimizedWithReturning = false;
         backfillId = 0L;
         clientFoundRows = true;
-        enableRuleCounter = false;
-        ruleCount = 0;
+
         executingPreparedStmt = false;
 
         blockBuilderCapacity = null;
         enableOssCompatible = null;
         enableOssDelayMaterializationOnExchange = null;
-        columnarMaxShard = -1;
+
+        fcManager = null;
     }
 
     public boolean useReturning() {
@@ -1952,14 +2024,30 @@ public void setPreparedStmtCache(PreparedStmtCache preparedStmtCache) {
         this.preparedStmtCache = preparedStmtCache;
     }
 
-    public long getBackfillId() {
+    public Long getBackfillId() {
         return backfillId;
     }
 
-    public void setBackfillId(long backfillId) {
+    public void setBackfillId(Long backfillId) {
         this.backfillId = backfillId;
     }
 
+    public long getEstimatedBackfillBatchRows() {
+        return estimatedBackfillBatchRows;
+    }
+
+    public void setEstimatedBackfillBatchRows(long estimatedBackfillBatchRows) {
+        this.estimatedBackfillBatchRows = estimatedBackfillBatchRows;
+    }
+
+    public Long getTaskId() {
+        return taskId;
+    }
+
+    public void setTaskId(Long taskId) {
+        this.taskId = taskId;
+    }
+
     public boolean isClientFoundRows() {
         return clientFoundRows;
     }
@@ -1989,22 +2077,6 @@ public long getCapabilityFlags() {
             Capabilities.CLIENT_PS_MULTI_RESULTS;
     }
 
-    public boolean isEnableRuleCounter() {
-        return enableRuleCounter;
-    }
-
-    public void setEnableRuleCounter(boolean enableRuleCounter) {
-        this.enableRuleCounter = enableRuleCounter;
-    }
-
-    public void setRuleCount(long ruleCount) {
-        this.ruleCount = ruleCount;
-    }
-
-    public long getRuleCount() {
-        return ruleCount;
-    }
-
     public int getBlockBuilderCapacity() {
         if (blockBuilderCapacity == null) {
             blockBuilderCapacity = paramManager.getInt(ConnectionParams.BLOCK_BUILDER_CAPACITY);
@@ -2040,19 +2112,34 @@ public void setColumnarMaxShard(int columnarMaxShard) {
         this.columnarMaxShard = columnarMaxShard;
     }
 
+    public boolean isUseColumnar() {
+        return useColumnar;
+    }
+
+    public void setUseColumnar(boolean useColumnar) {
+        this.useColumnar = useColumnar;
+    }
+
+    public boolean isColumnarPlanCache() {
+        return columnarPlanCache;
+    }
+
+    public void setColumnarPlanCache(boolean columnarPlanCache) {
+        this.columnarPlanCache = columnarPlanCache;
+    }
+
     /**
-     * copy context for trans
+     * copy context for optimizer
      */
-    public ExecutionContext subContextForParamsPrune() {
+    public ExecutionContext copyContextForOptimizer() {
         ExecutionContext executionContext = new ExecutionContext(schemaName);
-        executionContext.setParamManager(paramManager);
-        executionContext.setExtraCmds(extraCmds);
-        executionContext.setServerVariables(serverVariables);
-        executionContext.setParams(params);
-        executionContext.extraServerVariables = extraServerVariables;
-        executionContext.userDefVariables = userDefVariables;
-        executionContext.serverVariables = serverVariables;
-        executionContext.planProperties = planProperties;
+
+        executionContext.setExtraCmds(deepCopyExtraCmds(this.extraCmds));
+        executionContext.setParams(params.clone());
+        executionContext.setExplain(explain);
+        executionContext.setSqlType(sqlType);
+        executionContext.setAutoCommit(autoCommit);
+        executionContext.setTraceId(traceId);
         return executionContext;
     }
 
@@ -2126,6 +2213,14 @@ public void setCalcitePlanOptimizerTrace(CalcitePlanOptimizerTrace calcitePlanOp
         this.calcitePlanOptimizerTrace = calcitePlanOptimizerTrace;
     }
 
+    public boolean isUserSql() {
+        return userSql;
+    }
+
+    public void setUserSql(boolean userSql) {
+        this.userSql = userSql;
+    }
+
     public boolean isTsoTransaction() {
         return null != transaction && transaction.getTransactionClass().isA(TSO_TRANSACTION);
     }
@@ -2252,7 +2347,7 @@ public void setCheckingCci(boolean checkingCci) {
 
     public boolean isEnableOrcDeletedScan() {
         if (null != this.getParamManager()) {
-            return this.getParamManager().getBoolean(ConnectionParams.ENABLE_ORC_DELETED_SCAN);
+            return this.getParamManager().getBoolean(ConnectionParams.ENABLE_OSS_DELETED_SCAN);
         }
         return false;
     }
@@ -2271,21 +2366,22 @@ public boolean isReadCsvOnly() {
         return false;
     }
 
-    public String getForceReadOrcFile() {
-        if (null != this.getParamManager()) {
-            return this.getParamManager().getString(ConnectionParams.FORCE_READ_ORC_FILE);
-        }
-        return null;
-    }
-
-    public List getReadOrcFiles() {
+    public Map> getReadOrcFiles() {
         return readOrcFiles;
     }
 
-    public void setReadOrcFiles(List readOrcFiles) {
+    public void setReadOrcFiles(Map> readOrcFiles) {
         this.readOrcFiles = readOrcFiles;
     }
 
+    public Map getReadDeltaFiles() {
+        return readDeltaFiles;
+    }
+
+    public void setReadDeltaFiles(Map readDeltaFiles) {
+        this.readDeltaFiles = readDeltaFiles;
+    }
+
     public boolean isReadOrcOnly() {
         if (null != this.getParamManager()) {
             return this.getParamManager().getBoolean(ConnectionParams.READ_ORC_ONLY);
@@ -2293,9 +2389,23 @@ public boolean isReadOrcOnly() {
         return false;
     }
 
-    public boolean isEnableFastCciChecker() {
+    public boolean isReadSpecifiedColumnarFiles() {
+        if (null != this.getParamManager()) {
+            return this.getParamManager().getBoolean(ConnectionParams.READ_SPECIFIED_COLUMNAR_FILES);
+        }
+        return false;
+    }
+
+    public boolean isCciIncrementalCheck() {
+        if (null != this.getParamManager()) {
+            return this.getParamManager().getBoolean(ConnectionParams.CCI_INCREMENTAL_CHECK);
+        }
+        return false;
+    }
+
+    public boolean isEnableCciFastChecker() {
         if (null != this.getParamManager()) {
-            return getParamManager().getBoolean(ConnectionParams.ENABLE_FAST_CCI_CHECKER);
+            return getParamManager().getBoolean(ConnectionParams.ENABLE_CCI_FAST_CHECKER);
         }
         return false;
     }
@@ -2308,6 +2418,14 @@ public boolean isEnableFastParseOrcRawType() {
         return true;
     }
 
+    public boolean isEnableAccurateRelTypeToDataType() {
+        if (null != this.getParamManager()) {
+            return getParamManager().getBoolean(ConnectionParams.ENABLE_ACCURATE_REL_TYPE_TO_DATA_TYPE);
+        }
+        // Default false.
+        return false;
+    }
+
     public boolean isForce2pcDuringCciCheck() {
         if (null != this.getParamManager()) {
             return getParamManager().getBoolean(ConnectionParams.FORCE_2PC_DURING_CCI_CHECK);
@@ -2329,10 +2447,37 @@ public boolean isEnableAutoCommitTso() {
         return false;
     }
 
+    public boolean isMarkSyncPoint() {
+        // default false
+        return null != this.getExtraServerVariables() &&
+            null != this.getExtraServerVariables().get(ConnectionProperties.MARK_SYNC_POINT) &&
+            Boolean.parseBoolean((String) this.getExtraServerVariables().get(ConnectionProperties.MARK_SYNC_POINT));
+    }
+
     public boolean isEnable1PCOpt() {
         if (null != this.getParamManager()) {
             return this.getParamManager().getBoolean(ConnectionParams.ENABLE_1PC_OPT);
         }
         return true;
     }
+
+    public boolean isForbidAutoCommitTrx() {
+        if (null != this.getParamManager()) {
+            return this.getParamManager().getBoolean(ConnectionParams.FORBID_AUTO_COMMIT_TRX);
+        }
+        return false;
+    }
+
+    public boolean isEnableExternalConsistencyForWriteTrx() {
+        if (null != this.getParamManager()) {
+            return this.getParamManager().getBoolean(ConnectionParams.ENABLE_EXTERNAL_CONSISTENCY_FOR_WRITE_TRX);
+        }
+        return false;
+    }
+
+    public FlashbackColumnarManager getFlashbackColumnarManager(Long tso, String logicalSchema, String logicalTable) {
+        List fcKey = Arrays.asList(tso, logicalSchema, logicalTable);
+        return fcManager.computeIfAbsent(fcKey, k -> new FlashbackColumnarManager(tso, logicalSchema, logicalTable));
+    }
+
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/TddlOperatorTable.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/TddlOperatorTable.java
index 6e3d4f09c..48aa6f6e9 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/TddlOperatorTable.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/TddlOperatorTable.java
@@ -32,6 +32,10 @@
 import com.alibaba.polardbx.optimizer.core.function.SqlGroupConcatFunction;
 import com.alibaba.polardbx.optimizer.core.function.SqlIfFunction;
 import com.alibaba.polardbx.optimizer.core.function.SqlIfNullFunction;
+import com.alibaba.polardbx.optimizer.core.function.SqlJsonArrayAggFunction;
+import com.alibaba.polardbx.optimizer.core.function.SqlJsonArrayGlobalAggFunction;
+import com.alibaba.polardbx.optimizer.core.function.SqlJsonObjectAggFunction;
+import com.alibaba.polardbx.optimizer.core.function.SqlJsonObjectGlobalAggFunction;
 import com.alibaba.polardbx.optimizer.core.function.SqlLocateFunction;
 import com.alibaba.polardbx.optimizer.core.function.SqlNumericConvFunction;
 import com.alibaba.polardbx.optimizer.core.function.SqlNumericCrc32Function;
@@ -50,6 +54,7 @@
 import com.alibaba.polardbx.optimizer.core.function.SqlTrimFunction;
 import com.alibaba.polardbx.optimizer.core.function.SqlValuesFunction;
 import com.alibaba.polardbx.optimizer.core.function.SqlWeekYearFunction;
+import com.alibaba.polardbx.optimizer.core.function.calc.scalar.trx.SqlTimeToTsoFunction;
 import com.google.common.collect.ImmutableSet;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.SqlBinaryOperator;
@@ -290,6 +295,7 @@ public static TddlOperatorTable instance() {
         OperandTypes.ANY,
         SqlFunctionCategory.STRING);
     public static SqlFunction CRC32 = new SqlNumericCrc32Function("CRC32");
+    public static SqlFunction TIME_TO_TSO = new SqlTimeToTsoFunction("TIME_TO_TSO");
     public static SqlFunction CURDATE = new SqlFunction("CURDATE",
         SqlKind.OTHER_FUNCTION,
         MySQLStandardTypeInference.DATE_0,
@@ -926,6 +932,20 @@ public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
 
     public static SqlFunction UUID = FunctionWithoutArg.UUID;
     public static SqlFunction UUID_SHORT = FunctionWithoutArg.UUID_SHORT;
+
+    public static SqlFunction UUID_TO_BIN = new SqlFunction("UUID_TO_BIN",
+        SqlKind.OTHER_FUNCTION,
+        ReturnTypes.VARCHAR_BINARY,
+        InferTypes.FIRST_KNOWN,
+        OperandTypes.STRING_OPTIONAL_NUMERIC,
+        SqlFunctionCategory.STRING);
+    public static SqlFunction BIN_TO_UUID = new SqlFunction("BIN_TO_UUID",
+        SqlKind.OTHER_FUNCTION,
+        ReturnTypes.VARCHAR_2000,
+        InferTypes.FIRST_KNOWN,
+        OperandTypes.BINARY_OPTIONAL_NUMERIC,
+        SqlFunctionCategory.STRING);
+
     /**
      * VALIDATE_PASSWORD_STRENGTH VERSION WEEK WEEKDAY WEEKOFYEAR WEIGHT_STRING XOR
      */
@@ -1003,6 +1023,14 @@ public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
 
     public static SqlFunction BIT_XOR = new SqlBitXorFunction();
 
+    public static SqlFunction JSON_OBJECTAGG = new SqlJsonObjectAggFunction();
+
+    public static SqlFunction JSON_OBJECT_GLOBALAGG = new SqlJsonObjectGlobalAggFunction();
+
+    public static SqlFunction JSON_ARRAYAGG = new SqlJsonArrayAggFunction();
+
+    public static SqlFunction JSON_ARRAY_GLOBALAGG = new SqlJsonArrayGlobalAggFunction();
+
     /**
      * Variadic operands functions
      */
@@ -2264,6 +2292,13 @@ public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
         OperandTypes.VARIADIC,
         SqlFunctionCategory.SYSTEM);
 
+    public static SqlFunction JSON_OVERLAPS = new SqlFunction("JSON_OVERLAPS",
+        SqlKind.OTHER_FUNCTION,
+        ReturnTypes.BIGINT_NULLABLE,
+        InferTypes.FIRST_KNOWN,
+        OperandTypes.VARIADIC,
+        SqlFunctionCategory.SYSTEM);
+
     public static SqlFunction JSON_CONTAINS_PATH = new SqlFunction("JSON_CONTAINS_PATH",
         SqlKind.OTHER_FUNCTION,
         ReturnTypes.BIGINT_NULLABLE,
@@ -2390,20 +2425,6 @@ public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
         OperandTypes.ANY,
         SqlFunctionCategory.SYSTEM);
 
-    public static SqlFunction JSON_ARRAYAGG = new SqlFunction("JSON_ARRAYAGG",
-        SqlKind.OTHER_FUNCTION,
-        ReturnTypes.VARCHAR_2000,
-        InferTypes.FIRST_KNOWN,
-        OperandTypes.ANY,
-        SqlFunctionCategory.SYSTEM);
-
-    public static SqlFunction JSON_OBJECTAGG = new SqlFunction("JSON_OBJECTAGG",
-        SqlKind.OTHER_FUNCTION,
-        ReturnTypes.VARCHAR_2000,
-        InferTypes.FIRST_KNOWN,
-        OperandTypes.VARIADIC,
-        SqlFunctionCategory.SYSTEM);
-
     public static SqlFunction USER = new SqlFunction("USER",
         SqlKind.OTHER_FUNCTION,
         ReturnTypes.VARCHAR_2000,
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/Xplan/XPlanTemplate.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/Xplan/XPlanTemplate.java
index b03d8c753..9a5ef597c 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/Xplan/XPlanTemplate.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/Xplan/XPlanTemplate.java
@@ -17,14 +17,15 @@
 package com.alibaba.polardbx.optimizer.core.Xplan;
 
 import com.alibaba.polardbx.common.jdbc.ParameterContext;
+import com.alibaba.polardbx.common.utils.Pair;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.planner.Xplanner.XPlanUtil;
 import com.alibaba.polardbx.rpc.XUtil;
+import com.clearspring.analytics.util.Lists;
 import com.google.protobuf.ByteString;
 import com.googlecode.protobuf.format.JsonFormat;
 import com.mysql.cj.x.protobuf.PolarxExecPlan;
 import org.apache.calcite.sql.SqlIdentifier;
-import org.apache.calcite.sql.type.SqlTypeName;
 
 import java.math.BigDecimal;
 import java.nio.ByteBuffer;
@@ -41,7 +42,7 @@ public class XPlanTemplate implements IXPlan {
 
     private final PolarxExecPlan.AnyPlan template;
     private final ByteString digest;
-    private final List tableNames;
+    private final List> tableNames;
     private final List paramInfos;
 
     private final String indexName;
@@ -57,6 +58,28 @@ public XPlanTemplate(PolarxExecPlan.AnyPlan template, List tableN
             digest = null;
         }
         this.digest = digest;
+        this.tableNames = Lists.newArrayList();
+        for (SqlIdentifier sqlIdentifier : tableNames) {
+            String tableName = sqlIdentifier.getLastName();
+            String schemaName = 2 == sqlIdentifier.names.size() ? sqlIdentifier.names.get(0) : "";
+            this.tableNames.add(new Pair<>(schemaName, tableName));
+        }
+        this.paramInfos = paramInfos;
+        this.indexName = indexName;
+    }
+
+    public XPlanTemplate(String indexName,
+                         PolarxExecPlan.AnyPlan template,
+                         List> tableNames,
+                         List paramInfos) {
+        this.template = template;
+        ByteString digest;
+        try {
+            digest = ByteString.copyFrom(MessageDigest.getInstance("md5").digest(template.toByteArray()));
+        } catch (NoSuchAlgorithmException e) {
+            digest = null;
+        }
+        this.digest = digest;
         this.tableNames = tableNames;
         this.paramInfos = paramInfos;
         this.indexName = indexName;
@@ -66,7 +89,7 @@ public PolarxExecPlan.AnyPlan getTemplate() {
         return template;
     }
 
-    public List getTableNames() {
+    public List> getTableNames() {
         return tableNames;
     }
 
@@ -98,7 +121,7 @@ public PolarxExecPlan.ExecPlan.Builder getXPlan(String dbIndex, List phy
                     return null;
                 }
                 // NOTE: When compare value with BIT type, uint must be used.
-                if (info.getDataType().getSqlTypeName() == SqlTypeName.BIT && val instanceof byte[]) {
+                if (info.isBit() && val instanceof byte[]) {
                     final ByteBuffer buf =
                         ByteBuffer.allocate(Long.BYTES).put((byte[]) val)
                             .order(ByteOrder.LITTLE_ENDIAN);
@@ -145,7 +168,7 @@ public PolarxExecPlan.ExecPlan explain(ExecutionContext ec) {
                         return null;
                     }
                     // NOTE: When compare value with BIT type, uint must be used.
-                    if (info.getDataType().getSqlTypeName() == SqlTypeName.BIT && val instanceof byte[]) {
+                    if (info.isBit() && val instanceof byte[]) {
                         final ByteBuffer buf =
                             ByteBuffer.allocate(Long.BYTES).put((byte[]) val)
                                 .order(ByteOrder.LITTLE_ENDIAN);
@@ -157,13 +180,10 @@ public PolarxExecPlan.ExecPlan explain(ExecutionContext ec) {
                 }
                 break;
             case TableName:
-                builder.addParameters(XUtil.genUtf8StringScalar(tableNames.get(info.getId()).getLastName()));
+                builder.addParameters(XUtil.genUtf8StringScalar(tableNames.get(info.getId()).getValue()));
                 break;
             case SchemaName:
-                builder.addParameters(XUtil.genUtf8StringScalar(
-                    2 == tableNames.get(info.getId()).names.size() ?
-                        tableNames.get(info.getId()).names.get(0) :
-                        ""));
+                builder.addParameters(XUtil.genUtf8StringScalar(tableNames.get(info.getId()).getKey()));
                 break;
             }
         }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeFactoryImpl.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeFactoryImpl.java
index c8c8a3b90..6149322a0 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeFactoryImpl.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeFactoryImpl.java
@@ -16,10 +16,11 @@
 
 package com.alibaba.polardbx.optimizer.core.datatype;
 
-import com.google.common.base.Preconditions;
 import com.alibaba.polardbx.common.charset.CharsetName;
 import com.alibaba.polardbx.common.charset.CollationName;
 import com.alibaba.polardbx.common.utils.time.MySQLTimeTypeUtil;
+import com.alibaba.polardbx.rpc.result.XResultUtil;
+import com.google.common.base.Preconditions;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.SqlCollation;
 import org.apache.calcite.sql.type.EnumSqlType;
@@ -80,10 +81,20 @@ public DataType create(RelDataType relDataType) {
             return DataTypes.ULongType;
         case DECIMAL:
             return new DecimalType(precision, scale);
+        // 注意目前只处理 scale 大于 0 的情况,因为之前没有办法区分0位小数保留和null的情况,
+        // 目前会存储未指定精度并存储为DECIMAL_NOT_SPECIFIED
         case FLOAT:
-            return DataTypes.FloatType;
+            if (scale > 0 && scale < XResultUtil.DECIMAL_NOT_SPECIFIED) {
+                return new FloatType(scale);
+            } else {
+                return DataTypes.FloatType;
+            }
         case DOUBLE:
-            return DataTypes.DoubleType;
+            if (scale > 0 && scale < XResultUtil.DECIMAL_NOT_SPECIFIED) {
+                return new DoubleType(scale);
+            } else {
+                return DataTypes.DoubleType;
+            }
         case DATETIME:
             return new DateTimeType(MySQLTimeTypeUtil.normalizeScale(scale));
         case ENUM:
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeUtil.java
index ac8cd3666..88adf6288 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeUtil.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeUtil.java
@@ -45,6 +45,7 @@
 import com.alibaba.polardbx.optimizer.core.expression.bean.NullValue;
 import com.alibaba.polardbx.optimizer.exception.OptimizerException;
 import com.alibaba.polardbx.optimizer.exception.SqlValidateException;
+import com.alibaba.polardbx.rpc.result.XResultUtil;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import io.airlift.slice.Slice;
@@ -112,6 +113,18 @@ public static  T convert(DataType fromType, DataType toType, Object val
                 return (T) ((Slice) value).getBytes();
             }
             return (T) ((SliceType) fromType).getCharsetHandler().encodeFromUtf8((Slice) value).getBytes();
+        } else if (fromType instanceof BlobType
+            && toType instanceof BytesType
+            && value instanceof Blob) {
+            com.alibaba.polardbx.optimizer.core.datatype.Blob blob =
+                (com.alibaba.polardbx.optimizer.core.datatype.Blob) DataTypes.BlobType.convertFrom(value);
+            return (T) blob.getSlice().getBytes();
+        } else if (fromType instanceof FloatType && fromType.getScale() != XResultUtil.DECIMAL_NOT_SPECIFIED
+            && toType instanceof StringType && value instanceof Float) {
+            return (T) String.format(String.format("%%.%df", fromType.getScale()), value);
+        } else if (fromType instanceof DoubleType && fromType.getScale() != XResultUtil.DECIMAL_NOT_SPECIFIED
+            && toType instanceof StringType && value instanceof Double) {
+            return (T) String.format(String.format("%%.%df", fromType.getScale()), value);
         }
 
         return toType.convertFrom(value);
@@ -691,6 +704,12 @@ public static RelDataType jdbcTypeToRelDataType(int jdbcType, String columnTypeN
         case TIME:
             calciteType = factory.createSqlType(calciteTypeName, precision, scale);
             break;
+        case FLOAT:
+        case DOUBLE:
+            // 由于历史存储的元数据原因,忽略scale=0的情况
+            calciteType = factory.createSqlType(calciteTypeName, RelDataType.PRECISION_NOT_SPECIFIED,
+                scale > 0 ? scale : RelDataType.SCALE_NOT_SPECIFIED);
+            break;
         /*
          * Note: Why CHAR and BINARY was commented here?
          * For CHAR with precision specified, e.g. CHAR(20), `RexBuilder.makeLiteral()` will do right-padding,
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DoubleType.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DoubleType.java
index a683df099..4f50b86a2 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DoubleType.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/DoubleType.java
@@ -17,6 +17,7 @@
 package com.alibaba.polardbx.optimizer.core.datatype;
 
 import com.alibaba.polardbx.common.type.MySQLStandardFieldType;
+import com.alibaba.polardbx.rpc.result.XResultUtil;
 
 import java.math.BigDecimal;
 
@@ -33,6 +34,21 @@ public class DoubleType extends NumberType {
     private static final BigDecimal MIN_VALUE_TO_DECIMAL = new BigDecimal(MIN_VALUE);
     private static final BigDecimal MAX_VALUE_TO_DECIMAL = new BigDecimal(MAX_VALUE);
 
+    private final int scale;
+
+    public DoubleType() {
+        this(XResultUtil.DECIMAL_NOT_SPECIFIED);
+    }
+
+    public DoubleType(int scale) {
+        this.scale = scale;
+    }
+
+    @Override
+    public int getScale() {
+        return scale;
+    }
+
     private final Calculator calculator = new AbstractCalculator() {
 
         @Override
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/FloatType.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/FloatType.java
index acdf48f82..784508409 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/FloatType.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/FloatType.java
@@ -17,6 +17,7 @@
 package com.alibaba.polardbx.optimizer.core.datatype;
 
 import com.alibaba.polardbx.common.type.MySQLStandardFieldType;
+import com.alibaba.polardbx.rpc.result.XResultUtil;
 
 import java.math.BigDecimal;
 
@@ -27,6 +28,21 @@ public class FloatType extends NumberType {
     private static final BigDecimal MIN_VALUE_TO_DECIMAL = new BigDecimal(MIN_VALUE);
     private static final BigDecimal MAX_VALUE_TO_DECIMAL = new BigDecimal(MAX_VALUE);
 
+    private final int scale;
+
+    public FloatType() {
+        this(XResultUtil.DECIMAL_NOT_SPECIFIED);
+    }
+
+    public FloatType(int scale) {
+        this.scale = scale;
+    }
+
+    @Override
+    public int getScale() {
+        return scale;
+    }
+
     private final Calculator calculator = new AbstractCalculator() {
 
         @Override
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/RowType.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/RowType.java
index dae9a89de..829335994 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/RowType.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/datatype/RowType.java
@@ -1,33 +1,21 @@
-/*
- * Copyright [2013-2021], Alibaba Group Holding Limited
- *
- * Licensed 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 com.alibaba.polardbx.optimizer.core.datatype;
 
 import com.alibaba.polardbx.common.datatype.RowValue;
+import com.alibaba.polardbx.common.exception.NotSupportException;
 import com.alibaba.polardbx.common.exception.TddlRuntimeException;
 import com.alibaba.polardbx.common.exception.code.ErrorCode;
 import com.alibaba.polardbx.common.type.MySQLStandardFieldType;
 import com.alibaba.polardbx.optimizer.core.expression.build.Rex2ExprUtil;
+import com.alibaba.polardbx.optimizer.core.row.Row;
 
+import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.util.List;
 
+import static com.alibaba.polardbx.common.type.MySQLStandardFieldType.MYSQL_TYPE_VAR_STRING;
 import static com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil.getTypeOfObject;
 
 public class RowType extends AbstractDataType {
-
     private List dataTypes;
 
     public RowType() {
@@ -36,7 +24,6 @@ public RowType() {
     public RowType(List dataTypes) {
         this.dataTypes = dataTypes;
     }
-
     @Override
     public Class getDataClass() {
         return RowValue.class;
@@ -44,22 +31,35 @@ public Class getDataClass() {
 
     @Override
     public ResultGetter getResultGetter() {
-        throw new UnsupportedOperationException();
+        return new ResultGetter() {
+
+            @Override
+            public Object get(ResultSet rs, int index) throws SQLException {
+                Object val = rs.getString(index);
+                return convertFrom(val);
+            }
+
+            @Override
+            public Object get(Row rs, int index) {
+                Object val = rs.getObject(index);
+                return convertFrom(val);
+            }
+        };
     }
 
     @Override
     public RowValue getMaxValue() {
-        throw new UnsupportedOperationException();
+        return null;
     }
 
     @Override
     public RowValue getMinValue() {
-        throw new UnsupportedOperationException();
+        return null;
     }
 
     @Override
     public Calculator getCalculator() {
-        throw new UnsupportedOperationException();
+        throw new NotSupportException("row类型不支持计算操作");
     }
 
     @Override
@@ -69,12 +69,12 @@ public int getSqlType() {
 
     @Override
     public String getStringSqlType() {
-        return "ROW";
+        return "VARCHAR";
     }
 
     @Override
     public MySQLStandardFieldType fieldType() {
-        throw new UnsupportedOperationException();
+        return MYSQL_TYPE_VAR_STRING;
     }
 
     public Long nullNotSafeEqual(Object o1, Object o2) {
@@ -148,25 +148,34 @@ public int compare(Object o1, Object o2) {
         if (o1 == o2) {
             return 0;
         }
-        if ((o1 instanceof RowValue)
-            && (o2 instanceof RowValue)) {
-
-            List o1s = ((RowValue) o1).getValues();
-            List o2s = ((RowValue) o2).getValues();
-            if (o1s.size() == o2s.size() && o1s.size() == dataTypes.size()) {
-                for (int i = 0; i < o1s.size(); i++) {
-                    int ret = dataTypes.get(i).compare(o1s.get(i), o2s.get(i));
-                    if (ret != 0) {
-                        return ret;
-                    }
-                }
-                return 0;
+
+        RowValue no1 = convertFrom(o1);
+        RowValue no2 = convertFrom(o2);
+        int num1 = no1.getValues().size();
+        int num2 = no2.getValues().size();
+        if (num1 != num2) {
+            throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR,
+                String.format("Operand should contain %s column(s)", num1));
+        }
+        for (int i = 0; i < num1; i++) {
+            Object val1 = no1.getValues().get(i);
+            Object val2 = no2.getValues().get(i);
+            if (val1 == val2) {
+                continue;
+            }
+            if (val1 == null) {
+                return -1;
+            } else if (val2 == null) {
+                return 1;
             } else {
-                throw new UnsupportedOperationException();
+                DataType type = inferCmpType(getTypeOfObject(val1), getTypeOfObject(val2));
+                int ret = type.compare(val1, val2);
+                if (ret != 0) {
+                    return ret;
+                }
             }
-        } else {
-            throw new UnsupportedOperationException();
         }
+        return 0;
     }
 
     private DataType inferCmpType(DataType leftType, DataType rightType) {
@@ -176,6 +185,4 @@ private DataType inferCmpType(DataType leftType, DataType rightType) {
             return Rex2ExprUtil.compareTypeOf(leftType, rightType, true, true);
         }
     }
-
 }
-
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/JavaFunctionManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/JavaFunctionManager.java
index 12f26071e..19da7eabb 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/JavaFunctionManager.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/JavaFunctionManager.java
@@ -36,6 +36,7 @@
 import com.alibaba.polardbx.optimizer.utils.CompileUtils;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
+import com.google.common.io.ByteStreams;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.schema.Function;
 import org.apache.calcite.schema.impl.TypeKnownScalarFunction;
@@ -50,7 +51,7 @@
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.util.ReflectiveSqlOperatorTable;
 import org.apache.calcite.sql.validate.SqlUserDefinedFunction;
-import org.apache.curator.shaded.com.google.common.io.ByteStreams;
+import org.codehaus.commons.compiler.ICompiler;
 import org.codehaus.commons.compiler.ICompiler;
 import org.codehaus.commons.compiler.util.ResourceFinderClassLoader;
 import org.codehaus.commons.compiler.util.resource.MapResourceCreator;
@@ -101,7 +102,7 @@ static class ConstructItem {
 
     private static final Logger logger = LoggerFactory.getLogger(JavaFunctionManager.class);
 
-    public static JavaFunctionManager INSTANCE = new JavaFunctionManager();
+    private static JavaFunctionManager INSTANCE = new JavaFunctionManager();
 
     public static JavaFunctionManager getInstance() {
         return INSTANCE;
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/build/Rex2ExprVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/build/Rex2ExprVisitor.java
index 376fba5e1..9ca679082 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/build/Rex2ExprVisitor.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/build/Rex2ExprVisitor.java
@@ -19,6 +19,7 @@
 import com.alibaba.polardbx.common.charset.CollationName;
 import com.alibaba.polardbx.common.exception.TddlRuntimeException;
 import com.alibaba.polardbx.common.exception.code.ErrorCode;
+import com.alibaba.polardbx.common.properties.ConnectionParams;
 import com.alibaba.polardbx.common.utils.time.calculator.MySQLIntervalType;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.TddlOperatorTable;
@@ -83,15 +84,21 @@ public class Rex2ExprVisitor extends RexVisitorImpl {
     protected List dynamicExpressions = null;
     protected List bloomFilters = null;
     protected ExprContextProvider contextProvider;
+    protected boolean enableDrdsTypeSystem = false;
 
     public Rex2ExprVisitor(ExecutionContext executionContext) {
         super(false);
         this.contextProvider = new ExprContextProvider(executionContext);
+        this.enableDrdsTypeSystem = executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_DRDS_TYPE_SYSTEM);
     }
 
     public Rex2ExprVisitor(ExprContextProvider contextHolder) {
         super(false);
         this.contextProvider = contextHolder;
+        if (contextHolder != null && contextHolder.getContext() != null) {
+            this.enableDrdsTypeSystem = contextHolder.getContext()
+                .getParamManager().getBoolean(ConnectionParams.ENABLE_DRDS_TYPE_SYSTEM);
+        }
     }
 
     public void setDynamicExpressions(List dynamicExpressions) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/Aggregator.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/Aggregator.java
index ebd28f801..9744a3be6 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/Aggregator.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/Aggregator.java
@@ -23,6 +23,10 @@
 import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.DenseRank;
 import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.FirstValue;
 import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.GroupConcat;
+import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.JsonArrayAgg;
+import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.JsonArrayGlobalAgg;
+import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.JsonObjectAgg;
+import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.JsonObjectGlobalAgg;
 import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.Lag;
 import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.LastValue;
 import com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions.NThValue;
@@ -155,6 +159,12 @@ public void aggregate(Row row) {
             return;
         }
 
+        if (this instanceof JsonObjectAgg || this instanceof JsonArrayAgg
+            || this instanceof JsonObjectGlobalAgg || this instanceof JsonArrayGlobalAgg) {
+            aggregateJsonAgg(row);
+            return;
+        }
+
         if (aggTargetIndexes.length == 0) { // e.g. COUNT(*)
             if (isDistinct) {
                 Row arrayRow = FunctionUtils.fromIRowSetToArrayRowSet(row);
@@ -214,6 +224,10 @@ private void aggregateChecksumV2(Row row) {
         conductAgg(row);
     }
 
+    private void aggregateJsonAgg(Row row) {
+        conductAgg(row);
+    }
+
     private void aggregateGroupConcat(Row row) {
         boolean notContainsNull = true;
         if (returnType == null) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/ScalarFunctionExpression.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/ScalarFunctionExpression.java
index 80b510b6f..479535521 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/ScalarFunctionExpression.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/ScalarFunctionExpression.java
@@ -18,11 +18,13 @@
 
 import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
 import com.alibaba.polardbx.optimizer.core.function.calc.AbstractScalarFunction;
 import com.alibaba.polardbx.optimizer.core.function.calc.IScalarFunction;
 import com.alibaba.polardbx.optimizer.core.row.Row;
 import com.alibaba.polardbx.optimizer.utils.ExprContextProvider;
 
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -49,7 +51,10 @@ public Object eval(Row row, ExecutionContext ec) {
             for (int i = 0; i < args.size(); i++) {
                 actualArgs[i] = args.get(i).eval(row, ec);
             }
-            return function.compute(actualArgs, ec);
+//            function.setArgs(Arrays.asList(actualArgs));
+            Object result = function.compute(actualArgs, ec);
+            DataType returnType = function.getReturnType();
+            return returnType.convertFrom(result);
         } else {
             GeneralUtil.nestedException("invoke function of null");
         }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonArrayAgg.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonArrayAgg.java
new file mode 100644
index 000000000..0ac174a03
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonArrayAgg.java
@@ -0,0 +1,85 @@
+package com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.optimizer.core.expression.IFunction;
+import com.alibaba.polardbx.optimizer.core.expression.calc.Aggregator;
+import com.alibaba.polardbx.optimizer.core.row.Row;
+import org.apache.calcite.sql.SqlKind;
+
+/**
+ * @author pangzhaoxing
+ */
+public class JsonArrayAgg extends Aggregator {
+
+    private JSONArray aggResult = new JSONArray();
+
+    public JsonArrayAgg() {
+    }
+
+    public JsonArrayAgg(int targetIndex, int filterArg) {
+        super(new int[] {targetIndex}, false, filterArg);
+        returnType = DataTypes.JsonType;
+    }
+
+    @Override
+    public IFunction.FunctionType getFunctionType() {
+        return IFunction.FunctionType.Aggregate;
+    }
+
+    @Override
+    public DataType getReturnType() {
+        return returnType;
+    }
+
+    @Override
+    public String[] getFunctionNames() {
+        return new String[] {"JSON_ARRAYAGG"};
+    }
+
+    @Override
+    public void clear() {
+
+    }
+
+    @Override
+    public int getScale() {
+        return 0;
+    }
+
+    @Override
+    public int getPrecision() {
+        return 0;
+    }
+
+    @Override
+    public SqlKind getSqlKind() {
+        return SqlKind.JSON_ARRAYAGG;
+    }
+
+    @Override
+    protected void conductAgg(Object value) {
+        assert value instanceof Row;
+
+        Object obj = ((Row) value).getObject(aggTargetIndexes[0]);
+        obj = DataTypeUtil.getTypeOfObject(obj).convertJavaFrom(obj);
+        aggResult.add(obj);
+    }
+
+    @Override
+    public Aggregator getNew() {
+        return new JsonArrayAgg(aggTargetIndexes[0], filterArg);
+    }
+
+    @Override
+    public Object eval(Row row) {
+        if (aggResult.size() == 0) {
+            return null;
+        }
+        return aggResult.toJSONString();
+    }
+
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonArrayGlobalAgg.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonArrayGlobalAgg.java
new file mode 100644
index 000000000..01d19e8c9
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonArrayGlobalAgg.java
@@ -0,0 +1,86 @@
+package com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.optimizer.core.expression.IFunction;
+import com.alibaba.polardbx.optimizer.core.expression.calc.Aggregator;
+import com.alibaba.polardbx.optimizer.core.row.Row;
+import org.apache.calcite.sql.SqlKind;
+
+/**
+ * @author pangzhaoxing
+ */
+public class JsonArrayGlobalAgg extends Aggregator {
+
+    private JSONArray aggResult = new JSONArray();
+
+    public JsonArrayGlobalAgg() {
+    }
+
+    public JsonArrayGlobalAgg(int targetIndex, int filterArg) {
+        super(new int[] {targetIndex}, false, filterArg);
+        returnType = DataTypes.JsonType;
+    }
+
+    @Override
+    public IFunction.FunctionType getFunctionType() {
+        return IFunction.FunctionType.Aggregate;
+    }
+
+    @Override
+    public DataType getReturnType() {
+        return returnType;
+    }
+
+    @Override
+    public String[] getFunctionNames() {
+        return new String[] {"JSON_ARRAY_GLOBALAGG"};
+    }
+
+    @Override
+    public void clear() {
+
+    }
+
+    @Override
+    public int getScale() {
+        return 0;
+    }
+
+    @Override
+    public int getPrecision() {
+        return 0;
+    }
+
+    @Override
+    public SqlKind getSqlKind() {
+        return SqlKind.JSON_ARRAY_GLOBALAGG;
+    }
+
+    @Override
+    protected void conductAgg(Object value) {
+        assert value instanceof Row;
+        if (((Row) value).getObject(aggTargetIndexes[0]) == null) {
+            return;
+        }
+        String json = DataTypes.StringType.convertFrom(((Row) value).getObject(aggTargetIndexes[0]));
+        JSONArray jsonArray = JSON.parseArray(json);
+        aggResult.addAll(jsonArray);
+    }
+
+    @Override
+    public Aggregator getNew() {
+        return new JsonArrayGlobalAgg(aggTargetIndexes[0], filterArg);
+    }
+
+    @Override
+    public Object eval(Row row) {
+        if (aggResult.size() == 0) {
+            return null;
+        }
+        return aggResult.toJSONString();
+    }
+
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonObjectAgg.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonObjectAgg.java
new file mode 100644
index 000000000..f2087b8d6
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonObjectAgg.java
@@ -0,0 +1,90 @@
+package com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.optimizer.core.expression.IFunction;
+import com.alibaba.polardbx.optimizer.core.expression.calc.Aggregator;
+import com.alibaba.polardbx.optimizer.core.row.Row;
+import org.apache.calcite.sql.SqlKind;
+
+/**
+ * @author pangzhaoxing
+ */
+public class JsonObjectAgg extends Aggregator {
+
+    private JSONObject aggResult = new JSONObject();
+
+    public JsonObjectAgg() {
+    }
+
+    public JsonObjectAgg(int[] targetIndexes, int filterArg) {
+        super(targetIndexes, false, filterArg);
+        returnType = DataTypes.JsonType;
+    }
+
+    @Override
+    public IFunction.FunctionType getFunctionType() {
+        return IFunction.FunctionType.Aggregate;
+    }
+
+    @Override
+    public DataType getReturnType() {
+        return returnType;
+    }
+
+    @Override
+    public String[] getFunctionNames() {
+        return new String[] {"JSON_OBJECTAGG"};
+    }
+
+    @Override
+    public void clear() {
+
+    }
+
+    @Override
+    public int getScale() {
+        return 0;
+    }
+
+    @Override
+    public int getPrecision() {
+        return 0;
+    }
+
+    @Override
+    public SqlKind getSqlKind() {
+        return SqlKind.JSON_OBJECTAGG;
+    }
+
+    @Override
+    protected void conductAgg(Object value) {
+        assert value instanceof Row;
+
+        if (((Row) value).getObject(aggTargetIndexes[0]) == null) {
+            throw new TddlNestableRuntimeException("JSON_OBJECTAGG function : key name can not be null");
+        }
+        String k = DataTypes.StringType.convertFrom(((Row) value).getObject(aggTargetIndexes[0]));
+        Object v = ((Row) value).getObject(aggTargetIndexes[1]);
+        v = DataTypeUtil.getTypeOfObject(v).convertJavaFrom(v);
+        aggResult.put(k, v);
+    }
+
+    @Override
+    public Aggregator getNew() {
+        return new JsonObjectAgg(aggTargetIndexes, filterArg);
+    }
+
+    @Override
+    public Object eval(Row row) {
+        if (aggResult.size() == 0) {
+            return null;
+        }
+        return aggResult.toJSONString();
+    }
+
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonObjectGlobalAgg.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonObjectGlobalAgg.java
new file mode 100644
index 000000000..cbd529e49
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonObjectGlobalAgg.java
@@ -0,0 +1,86 @@
+package com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.optimizer.core.expression.IFunction;
+import com.alibaba.polardbx.optimizer.core.expression.calc.Aggregator;
+import com.alibaba.polardbx.optimizer.core.row.Row;
+import org.apache.calcite.sql.SqlKind;
+
+public class JsonObjectGlobalAgg extends Aggregator {
+
+    private JSONObject aggResult = new JSONObject();
+
+    public JsonObjectGlobalAgg() {
+    }
+
+    public JsonObjectGlobalAgg(int targetIndex, int filterArg) {
+        super(new int[] {targetIndex}, false, filterArg);
+        returnType = DataTypes.JsonType;
+    }
+
+    @Override
+    public IFunction.FunctionType getFunctionType() {
+        return IFunction.FunctionType.Aggregate;
+    }
+
+    @Override
+    public DataType getReturnType() {
+        return returnType;
+    }
+
+    @Override
+    public String[] getFunctionNames() {
+        return new String[] {"JSON_OBJECT_GLOBALAGG"};
+    }
+
+    @Override
+    public void clear() {
+
+    }
+
+    @Override
+    public int getScale() {
+        return 0;
+    }
+
+    @Override
+    public int getPrecision() {
+        return 0;
+    }
+
+    @Override
+    public SqlKind getSqlKind() {
+        return SqlKind.JSON_OBJECT_GLOBALAGG;
+    }
+
+    @Override
+    protected void conductAgg(Object value) {
+        assert value instanceof Row;
+
+        if (((Row) value).getObject(aggTargetIndexes[0]) == null) {
+            return;
+        }
+        //input 必须是json字符串
+        String json = DataTypes.StringType.convertFrom(((Row) value).getObject(aggTargetIndexes[0]));
+        JSONObject jsonObj = JSON.parseObject(json);
+        aggResult.putAll(jsonObj);
+    }
+
+    @Override
+    public Aggregator getNew() {
+        return new JsonObjectGlobalAgg(aggTargetIndexes[0], filterArg);
+    }
+
+    @Override
+    public Object eval(Row row) {
+        if (aggResult.size() == 0) {
+            return null;
+        }
+        return aggResult.toJSONString();
+    }
+
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/CharField.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/CharField.java
index c808e8c5a..587ce8e5b 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/CharField.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/CharField.java
@@ -23,12 +23,12 @@
 import com.alibaba.polardbx.common.charset.SortKey;
 import com.alibaba.polardbx.common.type.MySQLStandardFieldType;
 import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.common.utils.XxhashUtils;
 import com.alibaba.polardbx.common.utils.logger.Logger;
 import com.alibaba.polardbx.common.utils.logger.LoggerFactory;
 import com.alibaba.polardbx.common.utils.time.MySQLTimeTypeUtil;
 import com.alibaba.polardbx.common.utils.time.core.MysqlDateTime;
 import com.alibaba.polardbx.common.utils.time.core.OriginalTemporalValue;
-import com.alibaba.polardbx.common.utils.time.core.OriginalTimestamp;
 import com.alibaba.polardbx.common.utils.time.parser.StringNumericParser;
 import com.alibaba.polardbx.common.utils.time.parser.StringTimeParser;
 import com.alibaba.polardbx.optimizer.config.table.charset.CharsetFactory;
@@ -234,6 +234,11 @@ public long xxHashCode() {
         if (isNull()) {
             return NULL_HASH_CODE;
         }
+        long hashCode = calcHashCodeByCollationHandler();
+        return XxhashUtils.finalShuffle(hashCode);
+    }
+
+    long calcHashCodeByCollationHandler() {
         if (isLatin1CharSet() && !isBinaryCollation()) {
             return getCollationHandler().hashcode(convertLatin1ToUtf8(packedBinary, 0, realLength));
         } else {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/DateField.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/DateField.java
index 30378f987..6f5f0776d 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/DateField.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/DateField.java
@@ -136,6 +136,9 @@ protected TypeConversionStatus storeInternal(Object value, DataType resultTyp
                 // store value from chunk executor as mysql datetime.
                 OriginalTemporalValue temporalValue = (OriginalTemporalValue) value;
                 MysqlDateTime mysqlDateTime = temporalValue.getMysqlDateTime();
+                if (mysqlDateTime != null) {
+                    mysqlDateTime = mysqlDateTime.clone();
+                }
                 return storeMysqlDatetime(mysqlDateTime, sessionProperties);
             } else if (value instanceof Timestamp) {
                 // Bad case: Use jdbc-style temporal value (java.sql.Timestamp)
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/DatetimeField.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/DatetimeField.java
index 30a34f69e..b11b27991 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/DatetimeField.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/DatetimeField.java
@@ -135,6 +135,9 @@ protected TypeConversionStatus storeInternal(Object value, DataType resultTyp
                 // store value from chunk executor as mysql datetime.
                 OriginalTemporalValue temporalValue = (OriginalTemporalValue) value;
                 MysqlDateTime mysqlDateTime = temporalValue.getMysqlDateTime();
+                if (mysqlDateTime != null) {
+                    mysqlDateTime = mysqlDateTime.clone();
+                }
                 return storeMysqlDatetime(mysqlDateTime, sessionProperties);
             } else if (value instanceof Timestamp) {
                 // Bad case: Use jdbc-style temporal value (java.sql.Timestamp)
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/TimestampField.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/TimestampField.java
index 47c6b2593..16309ba75 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/TimestampField.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/TimestampField.java
@@ -138,6 +138,9 @@ protected TypeConversionStatus storeInternal(Object value, DataType resultTyp
                 // store value from chunk executor as mysql datetime.
                 OriginalTemporalValue temporalValue = (OriginalTemporalValue) value;
                 MysqlDateTime mysqlDateTime = temporalValue.getMysqlDateTime();
+                if (mysqlDateTime != null) {
+                    mysqlDateTime = mysqlDateTime.clone();
+                }
                 return storeTemporal(mysqlDateTime, sessionProperties, mysqlDateTime.getSqlType());
             } else if (value instanceof Timestamp) {
                 // Bad case: Use jdbc-style temporal value (java.sql.Timestamp)
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/VarcharField.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/VarcharField.java
index 214de36e3..e3df7d82a 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/VarcharField.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/field/VarcharField.java
@@ -17,9 +17,9 @@
 package com.alibaba.polardbx.optimizer.core.field;
 
 import com.alibaba.polardbx.common.charset.CharsetName;
-import com.alibaba.polardbx.common.charset.CollationName;
 import com.alibaba.polardbx.common.charset.SortKey;
 import com.alibaba.polardbx.common.type.MySQLStandardFieldType;
+import com.alibaba.polardbx.common.utils.XxhashUtils;
 import com.alibaba.polardbx.optimizer.config.table.charset.CharsetFactory;
 import com.alibaba.polardbx.optimizer.config.table.charset.CharsetHandler;
 import com.alibaba.polardbx.common.charset.CharsetName;
@@ -27,13 +27,8 @@
 import com.alibaba.polardbx.optimizer.config.table.collation.CollationHandler;
 import com.alibaba.polardbx.common.type.MySQLStandardFieldType;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
-import io.airlift.slice.DynamicSliceOutput;
 import io.airlift.slice.Slice;
-import io.airlift.slice.SliceOutput;
 import io.airlift.slice.Slices;
-import io.airlift.slice.XxHash64;
-
-import static com.alibaba.polardbx.common.charset.MySQLUnicodeUtils.LATIN1_TO_UTF8_BYTES;
 
 /**
  * MySQL varchar(n) data type.
@@ -71,10 +66,7 @@ public void hash(long[] numbers) {
     }
 
     @Override
-    public long xxHashCode() {
-        if (isNull()) {
-            return NULL_HASH_CODE;
-        }
+    long calcHashCodeByCollationHandler() {
         int length = (varLength == UNSET_CHAR_LENGTH) ? 0 : varLength;
         int startPos = startPos();
         if (isLatin1CharSet() && !isBinaryCollation()) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonArrayAggFunction.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonArrayAggFunction.java
new file mode 100644
index 000000000..4c9237a78
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonArrayAggFunction.java
@@ -0,0 +1,29 @@
+package com.alibaba.polardbx.optimizer.core.function;
+
+import org.apache.calcite.sql.SqlAggFunction;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.type.InferTypes;
+import org.apache.calcite.sql.type.OperandTypes;
+import org.apache.calcite.sql.type.ReturnTypes;
+import org.apache.calcite.sql.type.SqlOperandTypeChecker;
+import org.apache.calcite.sql.type.SqlOperandTypeInference;
+import org.apache.calcite.sql.type.SqlReturnTypeInference;
+import org.apache.calcite.sql.type.SqlTypeFamily;
+
+public class SqlJsonArrayAggFunction extends SqlAggFunction {
+
+    public SqlJsonArrayAggFunction() {
+        super("JSON_ARRAYAGG",
+            null,
+            SqlKind.JSON_ARRAYAGG,
+            ReturnTypes.JSON,
+            InferTypes.FIRST_KNOWN,
+            OperandTypes.family(SqlTypeFamily.ANY),
+            SqlFunctionCategory.SYSTEM,
+            false,
+            false);
+    }
+
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonArrayGlobalAggFunction.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonArrayGlobalAggFunction.java
new file mode 100644
index 000000000..93d3d6fb1
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonArrayGlobalAggFunction.java
@@ -0,0 +1,28 @@
+package com.alibaba.polardbx.optimizer.core.function;
+
+import org.apache.calcite.sql.SqlAggFunction;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.type.InferTypes;
+import org.apache.calcite.sql.type.OperandTypes;
+import org.apache.calcite.sql.type.ReturnTypes;
+import org.apache.calcite.sql.type.SqlTypeFamily;
+
+/**
+ * @author pangzhaoxing
+ */
+public class SqlJsonArrayGlobalAggFunction extends SqlAggFunction {
+
+    public SqlJsonArrayGlobalAggFunction() {
+        super("JSON_ARRAY_GLOBALAGG",
+            null,
+            SqlKind.JSON_ARRAY_GLOBALAGG,
+            ReturnTypes.JSON,
+            InferTypes.FIRST_KNOWN,
+            OperandTypes.family(SqlTypeFamily.STRING),
+            SqlFunctionCategory.SYSTEM,
+            false,
+            false);
+    }
+
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonObjectAggFunction.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonObjectAggFunction.java
new file mode 100644
index 000000000..e7e93c35c
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonObjectAggFunction.java
@@ -0,0 +1,32 @@
+package com.alibaba.polardbx.optimizer.core.function;
+
+import org.apache.calcite.sql.SqlAggFunction;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.type.InferTypes;
+import org.apache.calcite.sql.type.OperandTypes;
+import org.apache.calcite.sql.type.ReturnTypes;
+import org.apache.calcite.sql.type.SqlOperandTypeChecker;
+import org.apache.calcite.sql.type.SqlOperandTypeInference;
+import org.apache.calcite.sql.type.SqlReturnTypeInference;
+import org.apache.calcite.sql.type.SqlTypeFamily;
+
+/**
+ * @author pangzhaoxing
+ */
+public class SqlJsonObjectAggFunction extends SqlAggFunction {
+
+    public SqlJsonObjectAggFunction() {
+        super("JSON_OBJECTAGG",
+            null,
+            SqlKind.JSON_OBJECTAGG,
+            ReturnTypes.JSON,
+            InferTypes.FIRST_KNOWN,
+            OperandTypes.family(SqlTypeFamily.STRING, SqlTypeFamily.ANY),
+            SqlFunctionCategory.SYSTEM,
+            false,
+            false);
+    }
+
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonObjectGlobalAggFunction.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonObjectGlobalAggFunction.java
new file mode 100644
index 000000000..15ed1e3b2
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/SqlJsonObjectGlobalAggFunction.java
@@ -0,0 +1,25 @@
+package com.alibaba.polardbx.optimizer.core.function;
+
+import org.apache.calcite.sql.SqlAggFunction;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.type.InferTypes;
+import org.apache.calcite.sql.type.OperandTypes;
+import org.apache.calcite.sql.type.ReturnTypes;
+import org.apache.calcite.sql.type.SqlTypeFamily;
+
+public class SqlJsonObjectGlobalAggFunction extends SqlAggFunction {
+
+    public SqlJsonObjectGlobalAggFunction() {
+        super("JSON_OBJECT_GLOBALAGG",
+            null,
+            SqlKind.JSON_OBJECT_GLOBALAGG,
+            ReturnTypes.JSON,
+            InferTypes.FIRST_KNOWN,
+            OperandTypes.family(SqlTypeFamily.STRING),
+            SqlFunctionCategory.SYSTEM,
+            false,
+            false);
+    }
+
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/datatime/StrToDate.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/datatime/StrToDate.java
index 80e09e137..d610cfc88 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/datatime/StrToDate.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/datatime/StrToDate.java
@@ -39,6 +39,10 @@ public StrToDate(List operandTypes, DataType resultType) {
         super(operandTypes, resultType);
     }
 
+    public StrToDate() {
+        super(null, null);
+    }
+
     private final static long dayMs = 1000 * 60 * 60 * 24;
 
     private int cachedFlags = 0;
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/encryption/AesDecrypt.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/encryption/AesDecrypt.java
index 8f3e88df5..b060b1c91 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/encryption/AesDecrypt.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/encryption/AesDecrypt.java
@@ -24,6 +24,7 @@
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
 import com.alibaba.polardbx.optimizer.core.function.calc.AbstractScalarFunction;
+import com.alibaba.polardbx.optimizer.exception.FunctionException;
 import com.alibaba.polardbx.optimizer.utils.FunctionUtils;
 
 import java.util.List;
@@ -39,6 +40,10 @@ public AesDecrypt(List operandTypes, DataType resultType) {
         super(operandTypes, resultType);
     }
 
+    public AesDecrypt() {
+        super(null, null);
+    }
+
     @Override
     public Object compute(Object[] args, ExecutionContext ec) {
         if (FunctionUtils.isNull(args[0]) || FunctionUtils.isNull(args[1])) {
@@ -50,6 +55,9 @@ public Object compute(Object[] args, ExecutionContext ec) {
 
         byte[] initVector = null;
         if (encryptionMode.isInitVectorRequired()) {
+            if (args.length != 3) {
+                throw FunctionException.invalidParamCount(getFunctionNames()[0]);
+            }
             initVector = FunctionUtils.parseInitVector(args[2], operandTypes.get(2),
                 getFunctionNames()[0]);
         }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/encryption/AesEncrypt.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/encryption/AesEncrypt.java
index 65ee85748..47c1905d8 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/encryption/AesEncrypt.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/encryption/AesEncrypt.java
@@ -1,19 +1,3 @@
-/*
- * Copyright [2013-2021], Alibaba Group Holding Limited
- *
- * Licensed 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 com.alibaba.polardbx.optimizer.core.function.calc.scalar.encryption;
 
 import com.alibaba.polardbx.common.properties.ConnectionProperties;
@@ -24,6 +8,7 @@
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
 import com.alibaba.polardbx.optimizer.core.function.calc.AbstractScalarFunction;
+import com.alibaba.polardbx.optimizer.exception.FunctionException;
 import com.alibaba.polardbx.optimizer.utils.FunctionUtils;
 
 import java.util.List;
@@ -41,6 +26,10 @@ public AesEncrypt(List operandTypes, DataType resultType) {
         super(operandTypes, resultType);
     }
 
+    public AesEncrypt() {
+        super(null, null);
+    }
+
     @Override
     public Object compute(Object[] args, ExecutionContext ec) {
         if (FunctionUtils.isNull(args[0]) || FunctionUtils.isNull(args[1])) {
@@ -52,11 +41,13 @@ public Object compute(Object[] args, ExecutionContext ec) {
 
         byte[] initVector = null;
         if (encryptionMode.isInitVectorRequired()) {
-            initVector = FunctionUtils.parseInitVector(args[2], operandTypes.get(2),
-                getFunctionNames()[0]);
+            if (args.length != 3) {
+                throw FunctionException.invalidParamCount(getFunctionNames()[0]);
+            }
+            initVector = FunctionUtils.parseInitVector(args[2], getOperandType(2), getFunctionNames()[0]);
         }
-        byte[] plainTextBytes = DataTypeUtil.convert(operandTypes.get(0), DataTypes.BytesType, args[0]);
-        byte[] keyBytes = DataTypeUtil.convert(operandTypes.get(1), DataTypes.BytesType, args[1]);
+        byte[] plainTextBytes = DataTypeUtil.convert(getOperandType(0), DataTypes.BytesType, args[0]);
+        byte[] keyBytes = DataTypeUtil.convert(getOperandType(1), DataTypes.BytesType, args[1]);
 
         byte[] crypto = null;
         try {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Equal.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Equal.java
index f6e33d9ae..c9dd4cd6e 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Equal.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Equal.java
@@ -20,9 +20,11 @@
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
 import com.alibaba.polardbx.optimizer.core.datatype.RowType;
+import com.alibaba.polardbx.optimizer.core.datatype.RowType;
 import com.alibaba.polardbx.optimizer.core.function.calc.AbstractCollationScalarFunction;
 import com.alibaba.polardbx.optimizer.utils.FunctionUtils;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList;
 
 import java.util.Arrays;
 import java.util.List;
@@ -44,7 +46,11 @@ public Long compute(Object[] args, ExecutionContext ec) {
         }
 
         DataType type = operandTypes == null ? getEqualType(Arrays.asList(args)) : getCompareType();
-        return type.compare(args[0], args[1]) == 0 ? 1L : 0L;
+
+        if (type instanceof RowType) {
+            return ((RowType) type).nullNotSafeEqual(args[0], args[1]);
+        }
+        return type.compare(args[0], args[1]) == 0 ? 1l : 0l;
     }
 
     @Override
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Greater.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Greater.java
index 9a6a1b024..d52626a4a 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Greater.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Greater.java
@@ -16,9 +16,11 @@
 
 package com.alibaba.polardbx.optimizer.core.function.calc.scalar.filter;
 
+import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
 import com.alibaba.polardbx.optimizer.core.datatype.RowType;
+import com.alibaba.polardbx.optimizer.core.datatype.RowType;
 import com.alibaba.polardbx.optimizer.core.function.calc.AbstractCollationScalarFunction;
 import com.alibaba.polardbx.optimizer.utils.FunctionUtils;
 
@@ -49,7 +51,7 @@ public Object compute(Object[] args, ExecutionContext ec) {
                 return ret;
             }
         } else {
-            return type.compare(args[0], args[1]) > 0 ? 1L : 0L;
+            return type.compare(args[0], args[1]) > 0 ? 1l : 0l;
         }
     }
 
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/GreaterEqual.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/GreaterEqual.java
index 321098603..e2c08dc84 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/GreaterEqual.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/GreaterEqual.java
@@ -18,6 +18,7 @@
 
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.RowType;
 import com.alibaba.polardbx.optimizer.core.function.calc.AbstractCollationScalarFunction;
 import com.alibaba.polardbx.optimizer.core.datatype.RowType;
 import com.alibaba.polardbx.optimizer.utils.FunctionUtils;
@@ -49,6 +50,14 @@ public Object compute(Object[] args, ExecutionContext ec) {
                 return ret;
             }
         }
+        if (type instanceof RowType) {
+            Integer ret = ((RowType) type).nullNotSafeCompare(args[0], args[1], false);
+            if (ret != null) {
+                return ret >= 0 ? 1l : 0l;
+            } else {
+                return ret;
+            }
+        }
         return type.compare(args[0], args[1]) >= 0 ? 1L : 0L;
     }
 
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/In.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/In.java
index 45761a12b..9bcdfa687 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/In.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/In.java
@@ -1,30 +1,12 @@
-/*
- * Copyright [2013-2021], Alibaba Group Holding Limited
- *
- * Licensed 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 com.alibaba.polardbx.optimizer.core.function.calc.scalar.filter;
 
 import com.alibaba.polardbx.common.datatype.RowValue;
 import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
-import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
-import com.alibaba.polardbx.optimizer.core.expression.ISelectable;
-import com.alibaba.polardbx.optimizer.core.function.calc.AbstractCollationScalarFunction;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
 import com.alibaba.polardbx.optimizer.core.datatype.RowType;
+import com.alibaba.polardbx.optimizer.core.function.calc.AbstractCollationScalarFunction;
 import com.alibaba.polardbx.optimizer.utils.FunctionUtils;
 
 import java.util.Arrays;
@@ -107,18 +89,4 @@ public Object compute(Object[] args, ExecutionContext ec) {
     public String[] getFunctionNames() {
         return new String[] {"IN"};
     }
-
-    protected static DataType getArgType(Object arg, int rowValueIdx) {
-        DataType type = null;
-        if (arg instanceof ISelectable) {
-            type = ((ISelectable) arg).getDataType();
-        }
-        if (arg instanceof RowValue) {
-            type = DataTypeUtil.getTypeOfObject(((RowValue) arg).getValues().get(rowValueIdx));
-        }
-        if (type == null) {
-            type = DataTypeUtil.getTypeOfObject(arg);
-        }
-        return type;
-    }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Less.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Less.java
index 8eaaeb6c8..c293e28a0 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Less.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Less.java
@@ -18,6 +18,7 @@
 
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.RowType;
 import com.alibaba.polardbx.optimizer.core.function.calc.AbstractCollationScalarFunction;
 import com.alibaba.polardbx.optimizer.core.datatype.RowType;
 import com.alibaba.polardbx.optimizer.utils.FunctionUtils;
@@ -39,8 +40,18 @@ public Object compute(Object[] args, ExecutionContext ec) {
                 return null;
             }
         }
+
         DataType type = getCompareType();
-        return type.compare(args[0], args[1]) < 0 ? 1L : 0L;
+        if (type instanceof RowType) {
+            Integer ret = ((RowType) type).nullNotSafeCompare(args[0], args[1], false);
+            if (ret != null) {
+                return ret < 0 ? 1l : 0l;
+            } else {
+                return ret;
+            }
+        } else {
+            return type.compare(args[0], args[1]) < 0 ? 1l : 0l;
+        }
     }
 
     @Override
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/LessEqual.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/LessEqual.java
index 393840113..fc8b2775c 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/LessEqual.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/LessEqual.java
@@ -18,6 +18,7 @@
 
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.RowType;
 import com.alibaba.polardbx.optimizer.core.function.calc.AbstractCollationScalarFunction;
 import com.alibaba.polardbx.optimizer.core.datatype.RowType;
 import com.alibaba.polardbx.optimizer.utils.FunctionUtils;
@@ -49,6 +50,14 @@ public Object compute(Object[] args, ExecutionContext ec) {
                 return ret;
             }
         }
+        if (type instanceof RowType) {
+            Integer ret = ((RowType) type).nullNotSafeCompare(args[0], args[1], false);
+            if (ret != null) {
+                return ret <= 0 ? 1l : 0l;
+            } else {
+                return ret;
+            }
+        }
         return type.compare(args[0], args[1]) <= 0 ? 1L : 0L;
     }
 
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/NotEqual.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/NotEqual.java
index e347b7b8f..0b5fd531d 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/NotEqual.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/NotEqual.java
@@ -33,6 +33,10 @@ public NotEqual(List operandTypes, DataType resultType) {
         super(operandTypes, resultType);
     }
 
+    public NotEqual() {
+        super(null, null);
+    }
+
     @Override
     public Object compute(Object[] args, ExecutionContext ec) {
         for (Object arg : args) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/NullSafeEqual.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/NullSafeEqual.java
index f1d86e43e..4d8972b19 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/NullSafeEqual.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/NullSafeEqual.java
@@ -41,8 +41,9 @@ public Object compute(Object[] args, ExecutionContext ec) {
         } else if (isAnull || isBnull) {
             return 0L;
         } else {
+            // Row value compare.
             DataType type = getCompareType();
-            return type.compare(args[0], args[1]) == 0 ? 1L : 0L;
+            return type.compare(args[0], args[1]) == 0 ? 1l : 0l;
         }
     }
 
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Row.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Row.java
index 396daa0cf..e34e55344 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Row.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/filter/Row.java
@@ -19,6 +19,7 @@
 import com.alibaba.polardbx.common.datatype.RowValue;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
 import com.alibaba.polardbx.optimizer.core.datatype.RowType;
 import com.alibaba.polardbx.optimizer.core.function.calc.AbstractCollationScalarFunction;
 
@@ -42,6 +43,11 @@ public Object compute(Object[] args, ExecutionContext ec) {
         return new RowValue(list);
     }
 
+    @Override
+    public DataType getReturnType() {
+        return DataTypes.RowType;
+    }
+
     @Override
     public String[] getFunctionNames() {
         return new String[] {"ROW"};
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/json/JsonOverlaps.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/json/JsonOverlaps.java
new file mode 100644
index 000000000..3e69a72d4
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/json/JsonOverlaps.java
@@ -0,0 +1,133 @@
+package com.alibaba.polardbx.optimizer.core.function.calc.scalar.json;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.optimizer.json.JsonUtil;
+import com.alibaba.polardbx.optimizer.json.exception.JsonParserException;
+import com.alibaba.polardbx.optimizer.utils.FunctionUtils;
+import org.apache.calcite.util.NumberUtil;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * @author liugaoji
+ */
+public class JsonOverlaps extends JsonExtraFunction {
+    public JsonOverlaps(List operandTypes,
+                        DataType resultType) {
+        super(operandTypes, resultType);
+    }
+
+    public JsonOverlaps() {
+        super(null, null);
+    }
+
+    @Override
+    public String[] getFunctionNames() {
+        return new String[] {"JSON_OVERLAPS"};
+    }
+
+    @Override
+    public Object compute(Object[] args, ExecutionContext ec) {
+        if (args.length != 2) {
+            throw JsonParserException.wrongParamCount(getFunctionNames()[0]);
+        }
+        //In MYSQL select json_overlaps('asdasd',NULL) return INVALID but select json_overlaps('asdasd',NULL) return NULL,
+        // it's strange but we need to align with it
+        String stringDoc1 = DataTypeUtil.convert(getOperandType(0), DataTypes.StringType, args[0]);
+        Object jsonDoc1;
+        try {
+            jsonDoc1 = JsonUtil.parse(stringDoc1);
+        } catch (Exception e) {
+            throw JsonParserException.invalidArgInFunc(1, getFunctionNames()[0]);
+        }
+        for (Object arg : args) {
+            if (FunctionUtils.isNull(arg)) {
+                return null;
+            }
+        }
+        String stringDoc2 = DataTypeUtil.convert(getOperandType(1), DataTypes.StringType, args[1]);
+        Object jsonDoc2;
+        try {
+            jsonDoc2 = JsonUtil.parse(stringDoc2);
+        } catch (Exception e) {
+            throw JsonParserException.invalidArgInFunc(2, getFunctionNames()[0]);
+        }
+
+        return checkOverlap(jsonDoc1, jsonDoc2);
+    }
+
+    private boolean checkOverlap(Object target, Object candidate) {
+        if (JsonUtil.isJsonArray(target)) {
+            return arrayOverlaps((JSONArray) target, candidate);
+        }
+        if (JsonUtil.isJsonObject(target)) {
+            return objOverlaps((JSONObject) target, candidate);
+        }
+        //target is a scalar
+        if (JsonUtil.isJsonArray(candidate)) {
+            return arrayOverlaps((JSONArray) candidate, target);
+        }
+        if (JsonUtil.isJsonObject(candidate)) {
+            return objOverlaps((JSONObject) candidate, target);
+        }
+        return scalarEquals(target, candidate);
+    }
+
+    private boolean arrayOverlaps(JSONArray target, Object candidate) {
+        //candidate is a jsonArray
+        if (JsonUtil.isJsonArray(candidate)) {
+            for (Object candElement : (JSONArray) candidate) {
+                if (checkOverlap(target, candElement)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        //candidate is a scalar value
+        for (Object element : target) {
+            if (checkOverlap(element, candidate)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean objOverlaps(JSONObject target, Object candidate) {
+        //candidate must be json object
+        if (JsonUtil.isJsonArray(candidate)) {
+            for (Object canElement : (JSONArray) candidate) {
+                if (checkOverlap(canElement, target)) {
+                    return true;
+                }
+            }
+            return false;
+        } else if (JsonUtil.isJsonObject(candidate)) {
+            if (target.isEmpty() && ((JSONObject) candidate).isEmpty()) {
+                return true;
+            }
+            for (Map.Entry candEntry : ((JSONObject) candidate).entrySet()) {
+                Object targetVal = target.get(candEntry.getKey());
+                if (checkOverlap(targetVal, candEntry.getValue())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return false;
+    }
+
+    private boolean scalarEquals(Object target, Object candidate) {
+        if (target instanceof Number && candidate instanceof Number) {
+            target = NumberUtil.toBigDecimal((Number) target);
+            candidate = NumberUtil.toBigDecimal((Number) candidate);
+        }
+        return Objects.equals(target, candidate);
+    }
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/BinToUuid.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/BinToUuid.java
new file mode 100644
index 000000000..b8c9715de
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/BinToUuid.java
@@ -0,0 +1,82 @@
+/*
+ * 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 com.alibaba.polardbx.optimizer.core.function.calc.scalar.miscellaneous;
+
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.function.calc.AbstractScalarFunction;
+import io.airlift.slice.Slice;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.List;
+import java.util.UUID;
+
+public class BinToUuid extends AbstractScalarFunction {
+    public BinToUuid(List operandTypes,
+                        DataType resultType) {
+        super(operandTypes, resultType);
+    }
+    protected BinToUuid() {
+        super(null, null);
+    }
+    @Override
+    public String[] getFunctionNames() {
+        return new String[] {"BIN_TO_UUID"};
+    }
+
+    @Override
+    public Object compute(Object[] args, ExecutionContext ec) {
+        if (args.length == 0 || args[0] == null) {
+            return null;
+        }
+
+        if (!(args[0] instanceof Slice || args[0] instanceof byte[])) {
+            throw new UnsupportedOperationException(
+                "Incorrect string value: '" + args[0] + "' for function bin_to_uuid");
+        }
+
+        byte[] uuidBytes = args[0] instanceof byte[] ? (byte[]) args[0] : ((Slice) args[0]).getBytes();
+        ByteBuffer byteBuffer = ByteBuffer.wrap(uuidBytes);
+        byteBuffer.order(ByteOrder.BIG_ENDIAN);
+
+        long mostSignificantBits;
+        long leastSignificantBits;
+
+        if (args.length == 1 || (int) args[1] == 0) {
+            mostSignificantBits = byteBuffer.getLong();
+            leastSignificantBits = byteBuffer.getLong();
+        } else {
+            // 如果字节进行了交换,需要还原它们的顺序
+            // We need to swap time-low and time-high back to their original places
+            mostSignificantBits = byteBuffer.getLong();
+
+            long timeLowSwapped = (mostSignificantBits & 0x00000000FFFFFFFFL) << 32;
+            long timeMid = (mostSignificantBits & 0x0000FFFF00000000L) >>> 16;
+            long timeHighSwapped = mostSignificantBits >>> 48;
+
+            mostSignificantBits = timeLowSwapped | timeMid | timeHighSwapped;
+
+            // 继续读取剩余的部分作为 least significant bits
+            leastSignificantBits = byteBuffer.getLong(); // 剩下的8字节作为lsb
+        }
+
+        return new UUID(mostSignificantBits, leastSignificantBits).toString();
+    }
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/string/Uuid.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/Uuid.java
similarity index 99%
rename from polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/string/Uuid.java
rename to polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/Uuid.java
index 6ebfa4b44..bef431461 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/string/Uuid.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/Uuid.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.alibaba.polardbx.optimizer.core.function.calc.scalar.string;
+package com.alibaba.polardbx.optimizer.core.function.calc.scalar.miscellaneous;
 
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/string/UuidShort.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/UuidShort.java
similarity index 98%
rename from polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/string/UuidShort.java
rename to polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/UuidShort.java
index c88e8c033..58f0fa435 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/string/UuidShort.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/UuidShort.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.alibaba.polardbx.optimizer.core.function.calc.scalar.string;
+package com.alibaba.polardbx.optimizer.core.function.calc.scalar.miscellaneous;
 
 import com.alibaba.polardbx.common.TddlNode;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
@@ -77,7 +77,7 @@ public Object compute(Object[] args, ExecutionContext ec) {
     }
 
     private static int getServerId() {
-        int server_id = TddlNode.getNodeIndex();
+        int server_id = TddlNode.getNodeId();
         return server_id % 255;
     }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/UuidToBin.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/UuidToBin.java
new file mode 100644
index 000000000..a0a1a68a5
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/UuidToBin.java
@@ -0,0 +1,88 @@
+/*
+ * 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 com.alibaba.polardbx.optimizer.core.function.calc.scalar.miscellaneous;
+
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.optimizer.core.function.calc.AbstractScalarFunction;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.List;
+import java.util.UUID;
+
+public class UuidToBin extends AbstractScalarFunction {
+
+    public UuidToBin(List operandTypes,
+                        DataType resultType) {
+        super(operandTypes, resultType);
+    }
+
+    protected UuidToBin() {
+        super(null, null);
+    }
+
+    @Override
+    public String[] getFunctionNames() {
+        return new String[] {"UUID_TO_BIN"};
+    }
+
+    @Override
+    public Object compute(Object[] args, ExecutionContext ec) {
+        if (args.length == 0 || args[0] == null) {
+            return null;
+        }
+
+        String uuidStr = DataTypeUtil.convert(getOperandType(0), DataTypes.StringType, args[0]);
+        UUID uuid;
+        try {
+            uuid = UUID.fromString(uuidStr);
+        } catch (Exception e) {
+            throw new UnsupportedOperationException(
+                "Incorrect string value: '" + args[0] + "' for function uuid_to_bin");
+        }
+        ByteBuffer byteBuffer = ByteBuffer.allocate(16);
+        byteBuffer.order(ByteOrder.BIG_ENDIAN);
+
+        if (args.length == 1 || (int) args[1] == 0) {
+            byteBuffer.putLong(uuid.getMostSignificantBits())
+                .putLong(uuid.getLeastSignificantBits());
+        } else {
+            // 需要交换time-low和time-high
+            // 最高有效位 (在标准表示的UUID字符串中是 8-4-4-格式的前两部分)
+            long msb = uuid.getMostSignificantBits();
+
+            // 交换time-low和time-high
+            // time-low 在 long 的高32位
+            // time-high 在 long 的次高16位
+            long timeLow = msb >>> 32;
+            long timeMid = (msb & 0x00000000FFFF0000L) << 16;
+            long timeHigh = (msb & 0x000000000000FFFFL) << 48;
+
+            // 组合交换后的值并放入 ByteBuffer
+            msb = timeHigh | timeMid | timeLow;
+            byteBuffer.putLong(msb)
+                .putLong(uuid.getLeastSignificantBits());
+        }
+
+        return byteBuffer.array();
+    }
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/trx/SqlTimeToTsoFunction.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/trx/SqlTimeToTsoFunction.java
new file mode 100644
index 000000000..d305dd52e
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/trx/SqlTimeToTsoFunction.java
@@ -0,0 +1,21 @@
+package com.alibaba.polardbx.optimizer.core.function.calc.scalar.trx;
+
+import org.apache.calcite.sql.SqlFunction;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.type.InferTypes;
+import org.apache.calcite.sql.type.OperandTypes;
+import org.apache.calcite.sql.type.ReturnTypes;
+
+public class SqlTimeToTsoFunction extends SqlFunction {
+    public SqlTimeToTsoFunction(String funcName) {
+        super(
+            funcName,
+            SqlKind.OTHER_FUNCTION,
+            ReturnTypes.BIGINT_UNSIGNED_NULLABLE,
+            InferTypes.FIRST_KNOWN,
+            OperandTypes.ANY_OR_ANY_ANY,
+            SqlFunctionCategory.NUMERIC
+        );
+    }
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/trx/TimeToTso.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/trx/TimeToTso.java
new file mode 100644
index 000000000..4b89a6be3
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/trx/TimeToTso.java
@@ -0,0 +1,80 @@
+package com.alibaba.polardbx.optimizer.core.function.calc.scalar.trx;
+
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.function.calc.AbstractScalarFunction;
+import com.alibaba.polardbx.optimizer.utils.FunctionUtils;
+import org.apache.commons.collections.MapUtils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+
+public class TimeToTso extends AbstractScalarFunction {
+    public TimeToTso(List operandTypes, DataType resultType) {
+        super(operandTypes, resultType);
+    }
+
+    @Override
+    public Object compute(Object[] args, ExecutionContext ec) {
+        DataType type = getReturnType();
+        if (FunctionUtils.isNull(args[0])) {
+            return null;
+        }
+
+        String sessionTimezone = null;
+        if (args.length > 1 && !FunctionUtils.isNull(args[1])) {
+            sessionTimezone = (String) args[1];
+        }
+
+        if (null == sessionTimezone && null != ec
+            && MapUtils.isNotEmpty(ec.getServerVariables())
+            && null != (sessionTimezone = (String) ec.getServerVariables().get("time_zone"))) {
+            if ("SYSTEM".equalsIgnoreCase(sessionTimezone)) {
+                sessionTimezone = (String) ec.getServerVariables().get("system_time_zone");
+                if ("CST".equalsIgnoreCase(sessionTimezone)) {
+                    sessionTimezone = "GMT+08:00";
+                }
+            }
+        }
+
+        if (null != sessionTimezone) {
+            final String trimmed = sessionTimezone.trim();
+            if (!trimmed.isEmpty() && ('+' == trimmed.charAt(0) || '-' == trimmed.charAt(0))) {
+                // Convert '+08:00' to 'GMT+08:00'
+                sessionTimezone = "GMT" + trimmed;
+            } else if (!sessionTimezone.equals(trimmed)) {
+                sessionTimezone = trimmed;
+            }
+        }
+
+        Date date;
+        try {
+            date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(args[0].toString());
+        } catch (ParseException e) {
+            logger.error("Parse tso failed.", e);
+            return null;
+        }
+
+        if (null != sessionTimezone) {
+            // Convert specified timezone to default timezone.
+            TimeZone sourceTimeZone = TimeZone.getTimeZone(sessionTimezone);
+            TimeZone targetTimeZone = TimeZone.getDefault();
+            long sourceOffset = sourceTimeZone.getRawOffset();
+            long targetOffset = targetTimeZone.getRawOffset();
+            long offset = targetOffset - sourceOffset;
+            date.setTime(date.getTime() + offset);
+        }
+
+        String tso = String.valueOf(date.getTime() << 22);
+
+        return type.convertFrom(tso);
+    }
+
+    @Override
+    public String[] getFunctionNames() {
+        return new String[] {"TIME_TO_TSO"};
+    }
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/ExecutionPlan.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/ExecutionPlan.java
index d579da32e..b372cea10 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/ExecutionPlan.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/ExecutionPlan.java
@@ -157,7 +157,7 @@ public boolean isDirect() {
      */
     private HintConverter.HintCollection hintCollection = null;
 
-    private boolean useColumnar = false;
+    private boolean flashbackArea = false;
 
     /**
      * plan输出的列对应的的origin column name
@@ -259,10 +259,10 @@ public ExecutionPlan copy(RelNode plan) {
         newExecutionPlan.canOptByForcePrimary = this.canOptByForcePrimary;
         newExecutionPlan.constantParams = this.constantParams;
         newExecutionPlan.hintCollection = this.hintCollection;
-        newExecutionPlan.useColumnar = this.useColumnar;
         newExecutionPlan.forbidXplan = this.forbidXplan;
         newExecutionPlan.originColumnNames = this.originColumnNames;
         newExecutionPlan.checkTpSlow = this.checkTpSlow;
+        newExecutionPlan.flashbackArea = this.flashbackArea;
         return newExecutionPlan;
     }
 
@@ -428,14 +428,6 @@ public Map> getReferencedGsiNames() {
         return referencedGsiNames;
     }
 
-    public boolean isUseColumnar() {
-        return useColumnar;
-    }
-
-    public void setUseColumnar(boolean useColumnar) {
-        this.useColumnar = useColumnar;
-    }
-
     public Map getConstantParams() {
         return constantParams;
     }
@@ -462,6 +454,13 @@ public void setOriginColumnNames(List> originColumnNames) {
         this.originColumnNames = originColumnNames;
     }
 
+    public boolean isFlashbackArea() {
+        return flashbackArea;
+    }
+
+    public void setFlashbackArea(boolean flashbackArea) {
+        this.flashbackArea = flashbackArea;
+    }
 }
 
 
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/PlanCache.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/PlanCache.java
index 51e1b18f1..ed803fc28 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/PlanCache.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/PlanCache.java
@@ -23,7 +23,6 @@
 import com.alibaba.polardbx.common.exception.code.ErrorCode;
 import com.alibaba.polardbx.common.jdbc.ParameterContext;
 import com.alibaba.polardbx.common.jdbc.Parameters;
-import com.alibaba.polardbx.common.properties.ConnectionParams;
 import com.alibaba.polardbx.common.properties.DynamicConfig;
 import com.alibaba.polardbx.common.utils.Pair;
 import com.alibaba.polardbx.common.utils.TStringUtil;
@@ -46,15 +45,17 @@
 import com.alibaba.polardbx.optimizer.core.rel.LogicalView;
 import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan;
 import com.alibaba.polardbx.optimizer.exception.OptimizerException;
-import com.alibaba.polardbx.optimizer.optimizeralert.OptimizerAlertUtil;
 import com.alibaba.polardbx.optimizer.parse.FastsqlParser;
 import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized;
 import com.alibaba.polardbx.optimizer.parse.privilege.PrivilegeContext;
 import com.alibaba.polardbx.optimizer.parse.visitor.ContextParameters;
 import com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil;
+import com.alibaba.polardbx.optimizer.planmanager.hotevolution.HotGsiCapture;
+import com.alibaba.polardbx.optimizer.planmanager.hotevolution.HotGsiEvolution;
 import com.alibaba.polardbx.optimizer.statis.XplanStat;
 import com.alibaba.polardbx.optimizer.utils.CalciteUtils;
 import com.alibaba.polardbx.optimizer.utils.ForeignKeyUtils;
+import com.alibaba.polardbx.optimizer.utils.OptimizerUtils;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.collect.Maps;
@@ -64,8 +65,6 @@
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.SqlSelect;
-import org.apache.calcite.sql.SqlWith;
 import org.apache.commons.lang.StringUtils;
 
 import java.util.ArrayList;
@@ -209,11 +208,12 @@ protected Object clone() throws CloneNotSupportedException {
         return super.clone();
     }
 
-    private ExecutionPlan getFromCache(String schema, SqlParameterized sqlParameterized, final List params,
-                                       final ExecutionContext ec,
-                                       boolean testMode) throws ExecutionException {
-        final AtomicBoolean beCached = new AtomicBoolean(true);
-        CacheKey cacheKey = getCacheKey(schema, sqlParameterized, ec, testMode);
+    Callable getCacheLoader(String schema,
+                                           SqlParameterized sqlParameterized,
+                                           final List params,
+                                           final ExecutionContext ec,
+                                           boolean testMode, AtomicBoolean beCached,
+                                           CacheKey cacheKey) {
         final Callable valueLoader = () -> {
             ContextParameters contextParameters = new ContextParameters(testMode);
             SqlNodeList astList = new FastsqlParser()
@@ -272,16 +272,25 @@ private ExecutionPlan getFromCache(String schema, SqlParameterized sqlParameteri
                     executionPlan.setPrivilegeVerifyItems(pc.getPrivilegeVerifyItems());
                     pc.setPrivilegeVerifyItems(null);
                 }
+                HotGsiCapture.capture(
+                    sqlParameterized,
+                    ec,
+                    executionPlan,
+                    HotGsiEvolution.getInstance(),
+                    cacheKey.getTemplateId());
+
+                executionPlan.setFlashbackArea(ec.isFlashbackArea());
 
-                // alert if plan cache is full
-                OptimizerAlertUtil.plancacheAlert(ec);
                 return executionPlan;
             }
         };
+        return valueLoader;
+    }
 
-        ExecutionPlan plan;
+    protected ExecutionPlan getPlanWithLoader(CacheKey cacheKey, Callable valueLoader)
+        throws ExecutionException {
         try {
-            plan = cache.get(cacheKey, valueLoader);
+            return cache.get(cacheKey, valueLoader);
         } catch (UncheckedExecutionException ex) {
             if (ErrorCode.match(ex.getMessage())) {
                 if (ex.getCause() instanceof TddlRuntimeException) {
@@ -294,20 +303,105 @@ private ExecutionPlan getFromCache(String schema, SqlParameterized sqlParameteri
                 throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, ex, ex.getMessage());
             }
         }
+    }
 
-        if (plan.isUseColumnar()) {
-            if (!ec.getParamManager().getBoolean(ConnectionParams.ENABLE_COLUMNAR_PLAN_CACHE)) {
-                return beCached.get() ? null : plan;
-            }
+    ExecutionPlan getFromCache(String schema, SqlParameterized sqlParameterized, final List params,
+                               final ExecutionContext ec,
+                               boolean testMode) throws ExecutionException {
+        final AtomicBoolean beCached = new AtomicBoolean(true);
+        CacheKey cacheKey = getCacheKey(schema, sqlParameterized, ec, testMode);
+        final Callable valueLoader = getCacheLoader(
+            schema, sqlParameterized, params, ec, testMode, beCached, cacheKey);
+
+        if (ec != null) {
+            ec.setColumnarPlanCache(DynamicConfig.getInstance().colPlanCache());
+        }
+        ExecutionPlan plan = getPlanWithLoader(cacheKey, valueLoader);
+        if (plan.getPlan() == null || PlannerContext.getPlannerContext(plan.getPlan()) == null) {
+            return savePlanCachedKey(ec, plan, cacheKey, beCached);
         }
+        PlannerContext pc = PlannerContext.getPlannerContext(plan.getPlan());
 
-        if (beCached.get()) {
-            plan.getHitCount().incrementAndGet();
+        // row plan
+        if (!pc.isUseColumnar()) {
+            return savePlanCachedKey(ec, plan, cacheKey, beCached);
         }
-        plan.setHitCache(beCached.get());
-        savePlanCachedKey(ec, plan, cacheKey);
 
-        return plan;
+        // check whether columnar optimizer closed
+        ExecutionPlan newPlan = checkColumnarDisable(pc, ec, cacheKey, beCached, valueLoader);
+        if (newPlan != null) {
+            return newPlan;
+        }
+
+        // check whether columnar plan cache closed
+        plan = checkColumnarPlanCache(pc, ec, cacheKey, beCached, valueLoader, plan);
+
+        if (plan.getPlan() == null || PlannerContext.getPlannerContext(plan.getPlan()) == null) {
+            return savePlanCachedKey(ec, plan, cacheKey, beCached);
+        }
+        pc = PlannerContext.getPlannerContext(plan.getPlan());
+        if (pc.isUseColumnar() && !pc.isUseColumnarPlanCache()) {
+            return beCached.get() ? null : plan;
+        }
+        return savePlanCachedKey(ec, plan, cacheKey, beCached);
+    }
+
+    /**
+     * generate new plan if cache plan is columnar, while ColumnarOptimizer is disabled
+     *
+     * @param pc PlannerContext of current plan
+     * @param ec context of current query
+     * @param cacheKey cache key of current query
+     * @param beCached cache state of current query
+     * @param valueLoader cache loader
+     * @return plan generated, none otherwise
+     */
+    ExecutionPlan checkColumnarDisable(PlannerContext pc,
+                                       ExecutionContext ec,
+                                       CacheKey cacheKey,
+                                       AtomicBoolean beCached,
+                                       Callable valueLoader) throws ExecutionException {
+        // row plan
+        if (!pc.isUseColumnar()) {
+            return null;
+        }
+        // columnar node
+        if (ConfigDataMode.isColumnarMode()) {
+            return null;
+        }
+        // columnar optimizer disabled
+        if (OptimizerUtils.enableColumnarOptimizer(ec.getParamManager())) {
+            return null;
+        }
+        // invalidate col plan cache if columnar optimizer closed
+        beCached.set(true);
+        invalidateByCacheKey(cacheKey);
+        if (ec != null) {
+            ec.setColumnarPlanCache(DynamicConfig.getInstance().colPlanCache());
+        }
+        // optimize again
+        return savePlanCachedKey(ec, getPlanWithLoader(cacheKey, valueLoader), cacheKey, beCached);
+    }
+
+    ExecutionPlan checkColumnarPlanCache(PlannerContext pc,
+                                         ExecutionContext ec,
+                                         CacheKey cacheKey,
+                                         AtomicBoolean beCached,
+                                         Callable valueLoader,
+                                         ExecutionPlan plan) throws ExecutionException {
+
+        // setting doesn't change
+        if (pc.isUseColumnarPlanCache() == DynamicConfig.getInstance().colPlanCache()) {
+            return plan;
+        }
+        // invalidate col plan cache if setting changed
+        beCached.set(true);
+        invalidateByCacheKey(cacheKey);
+        if (ec != null) {
+            ec.setColumnarPlanCache(DynamicConfig.getInstance().colPlanCache());
+        }
+        // optimize again
+        return getPlanWithLoader(cacheKey, valueLoader);
     }
 
     private boolean ensureValid(CacheKey cacheKey, ExecutionPlan executionPlan) {
@@ -398,6 +492,10 @@ public void invalidateBySchema(String schema) {
         }
     }
 
+    public void invalidateByCacheKey(CacheKey cacheKey) {
+        cache.invalidate(cacheKey);
+    }
+
     /**
      * this implementation of this method will affect sql filter by query.
      */
@@ -590,8 +688,7 @@ private static boolean needBuildFinalPlan(RelNode plan, PlannerContext plannerCo
         return false;
     }
 
-    public void feedBack(ExecutionPlan executionPlan, ExecutionContext ec, Throwable ex) {
-
+    public void xplanFeedBack(ExecutionPlan executionPlan, ExecutionContext ec) {
         CacheKey cacheKey = executionPlan.getCacheKey();
         if (cacheKey == null) {
             return;
@@ -608,6 +705,14 @@ public void feedBack(ExecutionPlan executionPlan, ExecutionContext ec, Throwable
                 }
             }
         }
+    }
+
+    public void feedBack(ExecutionPlan executionPlan, ExecutionContext ec, Throwable ex) {
+        xplanFeedBack(executionPlan, ec);
+        CacheKey cacheKey = executionPlan.getCacheKey();
+        if (cacheKey == null) {
+            return;
+        }
 
         if (ex == null) {
             return;
@@ -619,11 +724,14 @@ public void feedBack(ExecutionPlan executionPlan, ExecutionContext ec, Throwable
         }
     }
 
-    public static void savePlanCachedKey(ExecutionContext ec, ExecutionPlan plan, CacheKey cacheKey) {
-        plan.saveCacheState(plan.getTableSet(), plan.getTableSetHashCode(), cacheKey, plan.getTableMetaSnapshots());
-        if (ec != null) {
-            ec.setSqlTemplateId(cacheKey.getTemplateId());
+    public ExecutionPlan savePlanCachedKey(ExecutionContext ec, ExecutionPlan plan, CacheKey cacheKey,
+                                           AtomicBoolean beCached) {
+        if (beCached.get()) {
+            plan.getHitCount().incrementAndGet();
         }
+        plan.setHitCache(beCached.get());
+        plan.saveCacheState(plan.getTableSet(), plan.getTableSetHashCode(), cacheKey, plan.getTableMetaSnapshots());
+        return plan;
     }
 
     public void putCachePlan(CacheKey cacheKey, ExecutionPlan plan) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Planner.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Planner.java
index 8ef2861be..9f1a0868a 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Planner.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Planner.java
@@ -97,15 +97,17 @@
 import com.alibaba.polardbx.optimizer.core.planner.rule.OptimizePhySqlRule;
 import com.alibaba.polardbx.optimizer.core.planner.rule.OuterJoinAssocRule;
 import com.alibaba.polardbx.optimizer.core.planner.rule.OuterJoinLAsscomRule;
-import com.alibaba.polardbx.optimizer.core.planner.rule.ProjectCorrelateTransposeRule;
+import com.alibaba.polardbx.optimizer.core.planner.rule.PhyPushAggRule;
+import com.alibaba.polardbx.optimizer.core.planner.rule.PhyTwoPhaseAggRule;
 import com.alibaba.polardbx.optimizer.core.planner.rule.ProjectSortTransitiveRule;
-import com.alibaba.polardbx.optimizer.core.planner.rule.PushCorrelateRule;
 import com.alibaba.polardbx.optimizer.core.planner.rule.PushFilterRule;
+import com.alibaba.polardbx.optimizer.core.planner.rule.PushModifyRule;
 import com.alibaba.polardbx.optimizer.core.planner.rule.PushProjectRule;
 import com.alibaba.polardbx.optimizer.core.planner.rule.PushSortRule;
 import com.alibaba.polardbx.optimizer.core.planner.rule.RuleToUse;
 import com.alibaba.polardbx.optimizer.core.planner.rule.SQL_REWRITE_RULE_PHASE;
 import com.alibaba.polardbx.optimizer.core.planner.rule.SemiJoinSemiJoinTransposeRule;
+import com.alibaba.polardbx.optimizer.core.planner.rule.SubQueryToSemiJoinRule;
 import com.alibaba.polardbx.optimizer.core.planner.rule.columnar.COLProjectHashJoinTransposeRule;
 import com.alibaba.polardbx.optimizer.core.planner.rule.implement.LogicalAggToHashAggRule;
 import com.alibaba.polardbx.optimizer.core.planner.rule.implement.LogicalJoinToBKAJoinRule;
@@ -124,6 +126,7 @@
 import com.alibaba.polardbx.optimizer.core.profiler.RuntimeStat;
 import com.alibaba.polardbx.optimizer.core.rel.BaseQueryOperation;
 import com.alibaba.polardbx.optimizer.core.rel.BroadcastTableModify;
+import com.alibaba.polardbx.optimizer.core.rel.BuildFinalPlanVisitor;
 import com.alibaba.polardbx.optimizer.core.rel.CollectorTableVisitor;
 import com.alibaba.polardbx.optimizer.core.rel.CountVisitor;
 import com.alibaba.polardbx.optimizer.core.rel.DirectMultiDBTableOperation;
@@ -137,6 +140,7 @@
 import com.alibaba.polardbx.optimizer.core.rel.LogicalView;
 import com.alibaba.polardbx.optimizer.core.rel.PhyTableOpBuildParams;
 import com.alibaba.polardbx.optimizer.core.rel.RemoveFixedCostVisitor;
+import com.alibaba.polardbx.optimizer.core.rel.RemoveIndexNodeVisitor;
 import com.alibaba.polardbx.optimizer.core.rel.RemoveSchemaNameVisitor;
 import com.alibaba.polardbx.optimizer.core.rel.ReplaceDifferentDBSingleTblWithPhyTblVisitor;
 import com.alibaba.polardbx.optimizer.core.rel.ReplaceSingleTblOrBroadcastTblWithPhyTblVisitor;
@@ -204,10 +208,8 @@
 import org.apache.calcite.rel.logical.LogicalTableScan;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.rules.AggregateProjectMergeRule;
-import org.apache.calcite.rel.rules.ProjectFilterTransposeRule;
 import org.apache.calcite.rel.rules.ProjectMergeRule;
 import org.apache.calcite.rel.rules.ProjectRemoveRule;
-import org.apache.calcite.rel.rules.ProjectWindowTransposeRule;
 import org.apache.calcite.rel.rules.SemiJoinProjectTransposeRule;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexDynamicParam;
@@ -253,6 +255,7 @@
 import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isExplainOptimizer;
 import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isExplainStatistics;
 import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isSuitableForDirectMode;
+import static com.alibaba.polardbx.optimizer.utils.OptimizerUtils.hasDNHint;
 import static com.alibaba.polardbx.optimizer.utils.RelUtils.disableMpp;
 import static com.alibaba.polardbx.optimizer.workload.WorkloadUtil.determineWorkloadType;
 import static org.apache.calcite.sql.SqlKind.DDL;
@@ -371,6 +374,7 @@ private ExecutionPlan plan(ByteString sql, SqlType sqlType,
         }
 
         parameterized.setForPrepare(forPrepare);
+        executionContext.setSqlTemplateId(PlanManagerUtil.generateTemplateId(parameterized.getSql()));
 
         return doPlan(sqlType, parameterized, executionContext, sqlNodeList, forPrepare);
     }
@@ -780,6 +784,7 @@ private ExecutionPlan buildPlanWithHint(SqlNode ast, PlannerContext plannerConte
         }
 
         if (hintCollection.pushdownOriginSql() ||
+            hintCollection.directWithRealTableName() ||
             (StringUtils.isNotEmpty(ec.getPartitionHint()) &&
                 (ast.isA(DML) || ast.isA(QUERY)) &&
                 checkAst(ast) &&
@@ -902,19 +907,10 @@ public ExecutionPlan getPlan(SqlNode ast, PlannerContext plannerContext) {
             }
         }
 
-        // set not pushdown DML condition.
-        plannerContext.getExecutionContext().setModifyShardingColumn(toDrdsRelVisitor.isModifyShardingColumn());
-        plannerContext.getExecutionContext().setModifyGsiTable(toDrdsRelVisitor.isModifyGsiTable());
-        plannerContext.getExecutionContext()
-            .setScaleoutWritableTable(toDrdsRelVisitor.isContainScaleOutWritableTable());
-        plannerContext.getExecutionContext()
-            .setModifyOnlineColumnTable(toDrdsRelVisitor.isContainOnlineModifyColumnTable());
-        plannerContext.getExecutionContext().setModifyBroadcastTable(toDrdsRelVisitor.isModifyBroadcastTable());
-        plannerContext.getExecutionContext().setModifyForeignKey(toDrdsRelVisitor.isModifyForeignKey());
-
         RelMetadataQuery mq = drdsRelNode.getCluster().getMetadataQuery();
         if (Boolean
             .parseBoolean(plannerContext.getParamManager().getProps().get(ConnectionProperties.PREPARE_OPTIMIZE))) {
+            // does not need to optimize plan in prepare mode
             return constructExecutionPlan(mq.getOriginalRowType(drdsRelNode), drdsRelNode, drdsRelNode,
                 ast, validatedNode,
                 converter,
@@ -941,9 +937,26 @@ public ExecutionPlan getPlan(SqlNode ast, PlannerContext plannerContext) {
             if (directMode == ExecutionPlan.DirectMode.TABLE_DIRECT ||
                 directMode == ExecutionPlan.DirectMode.MULTI_DB_TABLE_DIRECT) {
                 optimizedNode = unoptimizedNode;
+                if (OptimizerUtils.enableColumnarOptimizer(plannerContext.getParamManager())
+                    && CollectionUtils.isNotEmpty(toDrdsRelVisitor.getTableNames())
+                    && toDrdsRelVisitor.isAllTableHaveColumnar()) {
+                    try {
+                        optimizedNode = optimize(unoptimizedNode, plannerContext);
+                        // columnar plan
+                        if (plannerContext.isUseColumnar()) {
+                            directMode = ExecutionPlan.DirectMode.NONE;
+                        } else {
+                            optimizedNode = unoptimizedNode;
+                        }
+                    } catch (NotSupportException e) {
+                        if (!e.getMessage().contains(SubQueryToSemiJoinRule.NOT_SUPPORT_SUBQUERY_IN_JOIN)) {
+                            throw e;
+                        }
+                    }
+                }
             } else {
                 optimizedNode = optimize(unoptimizedNode, plannerContext);
-                if (canDirectByShardingKey(optimizedNode)) {
+                if (canDirectByShardingKey(optimizedNode, plannerContext)) {
                     directMode = ExecutionPlan.DirectMode.SHARDING_KEY_DIRECT;
                 } else {
                     directMode = ExecutionPlan.DirectMode.NONE;
@@ -1096,7 +1109,15 @@ private void initConverterAutoPartFlag(PlannerContext plannerContext, boolean en
     /**
      * 是否为分片键点查(主键)
      */
-    private boolean canDirectByShardingKey(RelNode optimizedNode) {
+    private boolean canDirectByShardingKey(RelNode optimizedNode, PlannerContext plannerContext) {
+        if (plannerContext.hasLocalIndexHint()) {
+            return false;
+        }
+
+        if (hasDNHint(plannerContext)) {
+            return false;
+        }
+
         if (!(optimizedNode instanceof LogicalView) || optimizedNode instanceof LogicalModifyView) {
             return false;
         }
@@ -1229,20 +1250,21 @@ public RelNode optimizeByPlanEnumerator(RelNode originInput, RelNode input, Plan
         CountVisitor countVisitor = new CountVisitor();
         input.accept(countVisitor);
 
-        // cbo config, e.g. pass_through
-        configureCBO(volcanoPlanner, countVisitor, paramManager, plannerContext);
-
-        // add rules used by cbo
-        addCBORule(volcanoPlanner, countVisitor, paramManager, plannerContext);
-
-        // optimize
-        RelNode output = optimizeByCBO(input, volcanoPlanner, plannerContext);
-
-        // transform table lookup to bka join
-        output = optimizeByExpandTableLookup(output, plannerContext);
+        ExchangeOptimizerType exchangeOptimizerType = determineWorkload(originInput, input, plannerContext, true);
+        RelNode output = input;
+        if (exchangeOptimizerType != ExchangeOptimizerType.COLUMNAR) {
+            // cbo config, e.g. pass_through
+            configureCBO(volcanoPlanner, countVisitor, paramManager, plannerContext);
+            // add rules used by cbo
+            addCBORule(volcanoPlanner, countVisitor, paramManager, plannerContext);
+            // optimize
+            output = optimizeByCBO(input, volcanoPlanner, plannerContext);
+            // optimize row plan after cbo, e.g. transform tableLookup to bka join
+            output = optimizeRowAfterCBO(output, plannerContext);
+            // determine workload of the query
+            exchangeOptimizerType = determineWorkload(originInput, output, plannerContext, false);
+        }
 
-        // determine workload of the query
-        ExchangeOptimizerType exchangeOptimizerType = determineWorkload(originInput, output, plannerContext);
         switch (exchangeOptimizerType) {
         case MPP:
             output = optimizeByMppPlan(output, plannerContext);
@@ -1329,8 +1351,8 @@ private RelNode optimizeByCBO(RelNode input,
             volcanoPlanner.clear();
             plannerContext.setRestrictCboPushJoin(false);
         }
-        if (plannerContext.getExecutionContext().isEnableRuleCounter()) {
-            plannerContext.getExecutionContext().setRuleCount(volcanoPlanner.getRuleCount());
+        if (plannerContext.isEnableRuleCounter()) {
+            plannerContext.setRuleCount(volcanoPlanner.getRuleCount());
         }
 
         if (plannerContext.getJoinCount() > 0) {
@@ -1348,53 +1370,35 @@ private RelNode optimizeByCBO(RelNode input,
      */
     private ExchangeOptimizerType determineWorkload(RelNode originInput,
                                                     RelNode input,
-                                                    PlannerContext plannerContext) {
+                                                    PlannerContext plannerContext,
+                                                    boolean ignoreRowCBO) {
         // determine TP or AP
-        String workloadType = plannerContext.getParamManager().getString(ConnectionParams.WORKLOAD_TYPE);
-        if (workloadType == null) {
-            plannerContext.setWorkloadType(determineWorkloadType(input, input.getCluster().getMetadataQuery()));
-        } else {
-            try {
-                plannerContext.setWorkloadType(WorkloadType.valueOf(workloadType.toUpperCase()));
-            } catch (Throwable t) {
-                // ignore
+        try {
+            plannerContext.setWorkloadType(WorkloadType.valueOf(
+                plannerContext.getParamManager().getString(ConnectionParams.WORKLOAD_TYPE).toUpperCase()));
+        } catch (Throwable t) {
+            // don't get workload type from cost if row cbo is not invoked yet
+            if (!ignoreRowCBO) {
+                plannerContext.setWorkloadType(determineWorkloadType(input, input.getCluster().getMetadataQuery()));
             }
         }
 
-        //use hint
+        // columnar mode
         if (ConfigDataMode.isColumnarMode()) {
-            if ((!MppPlanCheckers.supportsMppPlan(input, plannerContext, MppPlanCheckers.BASIC_CHECKERS))) {
-                return ExchangeOptimizerType.SMP;
-            } else {
-                if ((MppPlanCheckers.supportsMppPlan(input, plannerContext,
-                    MppPlanCheckers.SAMPLE_HINT_CHECKER,
-                    MppPlanCheckers.ENABLE_COLUMNAR_CHECKER,
-                    MppPlanCheckers.COLUMNAR_TRANSACTION_CHECKER,
-                    MppPlanCheckers.UPDATE_CHECKER) &&
-                    CBOUtil.allTablesHaveColumnar(originInput, plannerContext.getExecutionContext()))) {
-                    return ExchangeOptimizerType.COLUMNAR;
-                }
-                return ExchangeOptimizerType.SMP;
-            }
+            return determineOptimizerTypeForColumnarNode(originInput, input, plannerContext);
         } else {
-            ExchangeOptimizerType specificType = ExchangeOptimizerType.getType(
-                plannerContext.getParamManager().getString(ConnectionParams.OPTIMIZER_TYPE));
-            if (specificType != null) {
-                return specificType;
-            }
-
-            // firstly, smp or columnar_smp
-            if ((WorkloadType.AP != plannerContext.getWorkloadType()) ||
-                (!MppPlanCheckers.supportsMppPlan(input, plannerContext, MppPlanCheckers.BASIC_CHECKERS))) {
-                if (CBOUtil.planWithColumnar(originInput) &&
-                    !MppPlanCheckers.supportsMppPlan(input, plannerContext, MppPlanCheckers.QUERY_CHECKER)) {
-                    throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, "Can't use columnar in SMP planner");
-                }
-                return ExchangeOptimizerType.SMP;
-            }
+            return determineOptimizerTypeForMasterNode(originInput, input, plannerContext);
+        }
+    }
 
-            // secondly, columnar
-            if ((MppPlanCheckers.supportsMppPlan(input, plannerContext,
+    private ExchangeOptimizerType determineOptimizerTypeForColumnarNode(RelNode originInput,
+                                                                        RelNode input,
+                                                                        PlannerContext plannerContext) {
+        if ((!MppPlanCheckers.supportsMppPlan(input, plannerContext, plannerContext.getExecutionContext(),
+            MppPlanCheckers.BASIC_CHECKERS))) {
+            return ExchangeOptimizerType.SMP;
+        } else {
+            if ((MppPlanCheckers.supportsMppPlan(input, plannerContext, plannerContext.getExecutionContext(),
                 MppPlanCheckers.SAMPLE_HINT_CHECKER,
                 MppPlanCheckers.ENABLE_COLUMNAR_CHECKER,
                 MppPlanCheckers.COLUMNAR_TRANSACTION_CHECKER,
@@ -1402,10 +1406,39 @@ private ExchangeOptimizerType determineWorkload(RelNode originInput,
                 CBOUtil.allTablesHaveColumnar(originInput, plannerContext.getExecutionContext()))) {
                 return ExchangeOptimizerType.COLUMNAR;
             }
+            return ExchangeOptimizerType.SMP;
+        }
+    }
+
+    private ExchangeOptimizerType determineOptimizerTypeForMasterNode(RelNode originInput,
+                                                                      RelNode input,
+                                                                      PlannerContext plannerContext) {
+        ExchangeOptimizerType specificType = ExchangeOptimizerType.getType(
+            plannerContext.getParamManager().getString(ConnectionParams.OPTIMIZER_TYPE));
+        if (specificType != null) {
+            return specificType;
+        }
+
+        // firstly, smp or columnar_smp
+        if ((WorkloadType.AP != plannerContext.getWorkloadType()) ||
+            (!MppPlanCheckers.supportsMppPlan(input, plannerContext, plannerContext.getExecutionContext(),
+                MppPlanCheckers.BASIC_CHECKERS))) {
+            return ExchangeOptimizerType.SMP;
+        }
 
-            // finally, mpp
-            return ExchangeOptimizerType.MPP;
+        // secondly, columnar
+        if ((MppPlanCheckers.supportsMppPlan(input, plannerContext, plannerContext.getExecutionContext(),
+            MppPlanCheckers.SAMPLE_HINT_CHECKER,
+            MppPlanCheckers.ENABLE_COLUMNAR_CHECKER,
+            MppPlanCheckers.COLUMNAR_TRANSACTION_CHECKER,
+            MppPlanCheckers.UPDATE_CHECKER,
+            MppPlanCheckers.CORRELATE_CHECKER) &&
+            CBOUtil.allTablesHaveColumnar(originInput, plannerContext.getExecutionContext()))) {
+            return ExchangeOptimizerType.COLUMNAR;
         }
+
+        // finally, mpp
+        return ExchangeOptimizerType.MPP;
     }
 
     private static RelNode getCheapestFractionalPlan(VolcanoPlanner volcanoPlanner) {
@@ -1566,10 +1599,15 @@ private void addCBORule(RelOptPlanner relOptPlanner, CountVisitor countVisitor,
     private RelNode optimizeByColumnarPlan(RelNode input,
                                            ParamManager paramManager,
                                            PlannerContext plannerContext) {
+        try {
+            plannerContext.setWorkloadType(WorkloadType.valueOf(
+                plannerContext.getParamManager().getString(ConnectionParams.WORKLOAD_TYPE).toUpperCase()));
+        } catch (Throwable t) {
+            plannerContext.setWorkloadType(WorkloadType.AP);
+        }
+
         RelNode columnarOutput = optimizeByColumnarRBO(input, paramManager, plannerContext);
-        CBOUtil.ColumnarShardFinder columnarShardFinder = new CBOUtil.ColumnarShardFinder();
-        columnarOutput.accept(columnarShardFinder);
-        plannerContext.setColumnarMaxShardCnt(columnarShardFinder.getMaxShard());
+        CBOUtil.assignColumnarMaxShardCnt(columnarOutput, plannerContext);
 
         // cbo
         plannerContext.getCalcitePlanOptimizerTrace()
@@ -1581,6 +1619,7 @@ private RelNode optimizeByColumnarPlan(RelNode input,
         columnarOutput.accept(countVisitor);
 
         addColumnarCBORule(volcanoPlanner, paramManager, countVisitor);
+        volcanoPlanner.setTopDownOpt(true);
         volcanoPlanner.setStartUpCostOpt(false);
         volcanoPlanner.setEnableColumnar(true);
         volcanoPlanner.setEnableBranchAndBound(
@@ -1588,7 +1627,6 @@ private RelNode optimizeByColumnarPlan(RelNode input,
                 && (!CheckJoinHint.useJoinHint(plannerContext)));
 
         plannerContext.setUseColumnar(true);
-        plannerContext.enableSPM(false);
 
         RelTraitSet newTraitSet = columnarOutput.getTraitSet().simplify().replace(DrdsConvention.INSTANCE);
         RelNode newInput = volcanoPlanner.changeTraits(columnarOutput, newTraitSet);
@@ -1605,12 +1643,6 @@ private RelNode optimizeByColumnarPlan(RelNode input,
             volcanoPlanner.setEnableColumnar(false);
         }
 
-        // Don't use runtime filter in columnar mode if there is no hint for it.
-        if (plannerContext.getExtraCmds() != null
-            && plannerContext.getExtraCmds().containsKey(ConnectionProperties.ENABLE_RUNTIME_FILTER)) {
-            output = optimizeWithRuntimeFilter(output, plannerContext);
-        }
-
         if (plannerContext.getParamManager().getBoolean(
             ConnectionParams.ENABLE_COLUMNAR_AFTER_CBO_PLANNER)) {
             output = optimizeColumnarAfterCBO(output, plannerContext);
@@ -1674,7 +1706,7 @@ private Map configureColumnarRBO(ParamManager paramManager,
         plannerContext.getExtraCmds().put(ConnectionProperties.ENABLE_PUSH_CORRELATE, false);
         plannerContext.getExtraCmds().put(ConnectionProperties.ENABLE_PUSH_AGG, false);
         plannerContext.getExtraCmds().put(ConnectionProperties.ENABLE_PUSH_SORT, false);
-        plannerContext.getExtraCmds().put(ConnectionProperties.ENABLE_EXPAND_DISTINCTAGG, false);
+        plannerContext.getExtraCmds().put(ConnectionProperties.ENABLE_EXPAND_DISTINCTAGG, true);
         plannerContext.getExtraCmds().put(ConnectionProperties.PUSH_CORRELATE_MATERIALIZED_LIMIT, 0);
         plannerContext.setShouldUseHeuOrder(false);
         return valueRecords;
@@ -1751,14 +1783,15 @@ private RelNode optimizeByMppPlan(RelNode input, PlannerContext plannerContext)
     }
 
     private RelNode optimizeWithRuntimeFilter(RelNode input, PlannerContext plannerContext) {
+        plannerContext.getCalcitePlanOptimizerTrace()
+            .ifPresent(x -> x.addSnapshot("MPP RBO AFTER CBO", input, plannerContext));
         boolean enableRuntimeFilter = plannerContext.getParamManager().getBoolean(
             ConnectionParams.ENABLE_RUNTIME_FILTER);
         boolean pushRuntimeFilter = plannerContext.getParamManager().getBoolean(
             ConnectionParams.ENABLE_PUSH_RUNTIME_FILTER_SCAN);
 
-        RelNode output = input;
+        HepProgramBuilder builder = new HepProgramBuilder();
         if (enableRuntimeFilter) {
-            HepProgramBuilder builder = new HepProgramBuilder();
             builder.addGroupBegin();
             builder.addRuleCollection(RuleToUse.RUNTIME_FILTER);
             if (pushRuntimeFilter) {
@@ -1766,41 +1799,32 @@ private RelNode optimizeWithRuntimeFilter(RelNode input, PlannerContext plannerC
                 builder.addRuleInstance(PushBloomFilterRule.LOGICALVIEW);
             }
             builder.addGroupEnd();
-            HepPlanner planner = new HepPlanner(builder.build());
-            planner.stopOptimizerTrace();
-            planner.setRoot(input);
-            output = planner.findBestExp();
         }
 
-        return output;
+        HepPlanner planner = new HepPlanner(builder.build());
+        planner.setRoot(input);
+        return planner.findBestExp();
+
     }
 
     private RelNode optimizeColumnarAfterCBO(RelNode input, PlannerContext plannerContext) {
-        final int inputRefThreshold = plannerContext.getParamManager().getInt(
-            ConnectionParams.PUSH_PROJECT_INPUT_REF_THRESHOLD);
-
-        ImmutableList afterCBORules = ImmutableList.of(
-            // To prune the join keys.
-            JoinConditionPruningRule.INSTANCE,
-
-            // To transpose the project with join/project/agg
-            new COLProjectHashJoinTransposeRule(inputRefThreshold),
-            AggregateProjectMergeRule.INSTANCE,
-            ProjectCorrelateTransposeRule.INSTANCE,
-            ProjectFilterTransposeRule.INSTANCE,
-            ProjectWindowTransposeRule.INSTANCE,
-            ProjectSortTransitiveRule.INSTANCE,
-            PushProjectRule.INSTANCE,
-            PushCorrelateRule.INSTANCE,
-
-            // To merge and remove redundant projects.
-            ProjectMergeRule.INSTANCE,
-            ProjectRemoveRule.INSTANCE
-        );
-
+        plannerContext.getCalcitePlanOptimizerTrace()
+            .ifPresent(x -> x.addSnapshot("Columnar RBO AFTER CBO", input, plannerContext));
         HepProgramBuilder builder = new HepProgramBuilder();
+        builder.addMatchOrder(HepMatchOrder.TOP_DOWN);
         builder.addGroupBegin();
-        builder.addRuleCollection(afterCBORules);
+        builder.addRuleInstance(PhyTwoPhaseAggRule.INSTANCE);
+        builder.addRuleInstance(PhyTwoPhaseAggRule.PROJECT);
+        builder.addGroupEnd();
+
+        builder.addMatchOrder(HepMatchOrder.TOP_DOWN);
+        builder.addGroupBegin();
+        builder.addRuleInstance(AggregateProjectMergeRule.INSTANCE);
+        builder.addRuleInstance(JoinConditionPruningRule.INSTANCE);
+        builder.addRuleInstance(new COLProjectHashJoinTransposeRule(
+            plannerContext.getParamManager().getInt(ConnectionParams.PUSH_PROJECT_INPUT_REF_THRESHOLD)));
+        builder.addRuleInstance(ProjectMergeRule.INSTANCE);
+        builder.addRuleInstance(ProjectRemoveRule.INSTANCE);
         builder.addGroupEnd();
         HepPlanner planner = new HepPlanner(builder.build());
         planner.setRoot(input);
@@ -1850,6 +1874,7 @@ private RelNode optimizeBySmpPlan(RelNode input, PlannerContext plannerContext)
         builder.addGroupEnd();
         builder.addGroupBegin();
         builder.addRuleCollection(RuleToUse.TDDL_SHARDING_RULE);
+        builder.addRuleInstance(PushModifyRule.OPTIMIZE_MODIFY_TOP_N_RULE);
         builder.addGroupEnd();
         HepPlanner hepPlanner = new HepPlanner(builder.build(), plannerContext);
         hepPlanner.setRoot(input);
@@ -1861,7 +1886,7 @@ private RelNode addPartitionWiseTrait(RelNode input, boolean joinKeepPartition)
         return new PartitionWiseAssigner(input, joinKeepPartition).assign();
     }
 
-    private RelNode optimizeByExpandTableLookup(RelNode input, PlannerContext plannerContext) {
+    private RelNode optimizeRowAfterCBO(RelNode input, PlannerContext plannerContext) {
         HepProgramBuilder builder = new HepProgramBuilder();
         // expand table lookup
         builder.addGroupBegin();
@@ -1889,6 +1914,10 @@ private RelNode optimizeByExpandTableLookup(RelNode input, PlannerContext planne
         builder.addRuleInstance(DrdsCorrelateConvertRule.SMP_INSTANCE);
         builder.addRuleInstance(DrdsOutFileConvertRule.INSTANCE);
         builder.addGroupEnd();
+        // push agg
+        builder.addGroupBegin();
+        builder.addRuleInstance(PhyPushAggRule.INSTANCE);
+        builder.addGroupEnd();
         builder.addGroupBegin();
         builder.addRuleInstance(OptimizeLogicalViewRule.INSTANCE);
         builder.addGroupEnd();
@@ -1905,15 +1934,29 @@ private RelNode optimizeByExpandTableLookup(RelNode input, PlannerContext planne
     /**
      * 针对单表和广播表的direct转发
      */
-    private ExecutionPlan.DirectMode shouldDirectByTable(ToDrdsRelVisitor toDrdsRelVisitor, SqlNode sqlNode,
-                                                         PlannerContext plannerContext, RelNode unoptimizedNode) {
-        if (!plannerContext.getParamManager().getBoolean(ConnectionParams.ENABLE_DIRECT_PLAN)) {
+    protected ExecutionPlan.DirectMode shouldDirectByTable(ToDrdsRelVisitor toDrdsRelVisitor, SqlNode sqlNode,
+                                                           PlannerContext plannerContext, RelNode unoptimizedNode) {
+        if (!plannerContext.getParamManager().getBoolean(ConnectionParams.ENABLE_DIRECT_PLAN) ||
+            plannerContext.isUseColumnar()) {
+            return ExecutionPlan.DirectMode.NONE;
+        }
+        if (plannerContext.hasLocalIndexHint()) {
             return ExecutionPlan.DirectMode.NONE;
         }
+
+        if (hasDNHint(plannerContext)) {
+            return ExecutionPlan.DirectMode.NONE;
+        }
+
         final ExecutionStrategy strategy = ExecutionStrategy.fromHint(plannerContext.getExecutionContext());
         if (ExecutionStrategy.LOGICAL == strategy) {
             return ExecutionPlan.DirectMode.NONE;
         }
+
+        if (toDrdsRelVisitor.isExistForceColumnar()) {
+            return ExecutionPlan.DirectMode.NONE;
+        }
+
         if (toDrdsRelVisitor.existsCannotPushDown()) {
             return ExecutionPlan.DirectMode.NONE;
         }
@@ -1964,7 +2007,7 @@ private ExecutionPlan.DirectMode shouldDirectByTable(ToDrdsRelVisitor toDrdsRelV
             return ExecutionPlan.DirectMode.NONE;
         }
 
-        if (RelUtils.existUnPushableLastInsertId(unoptimizedNode)) {
+        if (RelUtils.existUnPushableLastInsertId(unoptimizedNode, toDrdsRelVisitor)) {
             return ExecutionPlan.DirectMode.NONE;
         }
 
@@ -1986,14 +2029,17 @@ private ExecutionPlan.DirectMode shouldDirectByTable(ToDrdsRelVisitor toDrdsRelV
         boolean supportPushOnDifferDB = plannerContext.getParamManager().getBoolean(
             ConnectionParams.SUPPORT_PUSH_AMONG_DIFFERENT_DB);
 
-        if (plannerContext.getExecutionContext().isAutoCommit() &&
-            supportPushOnDifferDB && toDrdsRelVisitor.isDirectInDifferentDB()
+        if (plannerContext.getExecutionContext().isAutoCommit()
+            && supportPushOnDifferDB
+            && !sqlNode.isA(DML)
+            && toDrdsRelVisitor.isDirectInDifferentDB()
             && toDrdsRelVisitor.getSchemaNames().size() > 1
             && !toDrdsRelVisitor.isContainScaleOutWritableTable()
-            && !toDrdsRelVisitor.isContainReplicateWriableTable() &&
-            sqlNode.getKind() != SqlKind.CREATE_MATERIALIZED_VIEW
+            && !toDrdsRelVisitor.isContainReplicateWriableTable()
+            && sqlNode.getKind() != SqlKind.CREATE_MATERIALIZED_VIEW
             && sqlNode.getKind() != SqlKind.REFRESH_MATERIALIZED_VIEW
             && sqlNode.getKind() != SqlKind.DROP_MATERIALIZED_VIEW) {
+            //dml的单表跨库下推没有判断insert表,忽略
             return ExecutionPlan.DirectMode.MULTI_DB_TABLE_DIRECT;
         }
 
@@ -2110,6 +2156,12 @@ private ExecutionPlan constructExecutionPlan(RelDataType originalRowType,
         }
 
         result = new ExecutionPlan(validatedNode, optimizedNode, cursorMeta);
+        if (Boolean
+            .parseBoolean(plannerContext.getParamManager().getProps().get(ConnectionProperties.PREPARE_OPTIMIZE))) {
+            // only need cursorMeta in prepare mode
+            return result;
+        }
+
         result.setDirectShardingKey(directPlanMode == ExecutionPlan.DirectMode.SHARDING_KEY_DIRECT);
         if (direct) {
             // disable tp slow check in direct mode
@@ -2129,8 +2181,9 @@ private ExecutionPlan constructExecutionPlan(RelDataType originalRowType,
 
         // If this plan can be optimized but not yet optimized, set this flag to true.
         result.setCanOptByForcePrimary(plannerContext.isCanOptByForcePrimary() && !plannerContext.isAddForcePrimary());
-        result.setUseColumnar(plannerContext.isUseColumnar());
+        plannerContext.getExecutionContext().setUseColumnar(plannerContext.isUseColumnar());
 
+        plannerContext.setExecutionContext(plannerContext.getExecutionContext().copy());
         return result;
     }
 
@@ -2316,6 +2369,19 @@ private RelNode buildDirectPlan(LogicalView logicalView, RelNode relNode, SqlNod
         CollectorTableVisitor collectorTableVisitor =
             new CollectorTableVisitor(logicalView.getSchemaName(), pc.getExecutionContext());
         List tableName = collectorTableVisitor.getTableNames();
+
+        if (sqlNode.getKind() == SqlKind.DELETE) {
+            /**
+             * non-exist force index delete should not be pushed down
+             */
+            String tableNameForDelete = logicalView.getLogicalTableName();
+            String schemaName = logicalView.getSchemaName();
+            // check force index exist or not
+            final TableMeta tMeta = pc.getExecutionContext().getSchemaManager(schemaName).getTable(tableNameForDelete);
+            RemoveIndexNodeVisitor removeIndexNodeVisitor = new RemoveIndexNodeVisitor(tMeta);
+            sqlNode = sqlNode.accept(removeIndexNodeVisitor);
+        }
+
         sqlNode = sqlNode.accept(collectorTableVisitor);
         List logTableNames = collectorTableVisitor.getTableNames();
         sqlNode = sqlNode.accept(new ReplaceSingleTblOrBroadcastTblWithPhyTblVisitor(logicalView.getSchemaName(),
@@ -2718,9 +2784,8 @@ private ExecutionPlan doPlan(SqlType sqlType, SqlParameterized sqlParameterized,
         }
 
         PlannerContext plannerContext = PlannerContext.getPlannerContext(executionPlan.getPlan());
-        if (plannerContext.isUseColumnar()) {
-            executionContext.setColumnarMaxShard(plannerContext.getColumnarMaxShardCnt());
-        }
+        executionContext.setUseColumnar(plannerContext.isUseColumnar());
+        executionContext.setColumnarMaxShard(plannerContext.getColumnarMaxShardCnt());
 
         plannerContext.setExecutionContext(executionContext);
         executionContext.setFinalPlan(executionPlan);
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/PostPlanner.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/PostPlanner.java
index 74b02f54f..5e38036e9 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/PostPlanner.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/PostPlanner.java
@@ -27,6 +27,7 @@
 import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.common.utils.Pair;
 import com.alibaba.polardbx.common.utils.thread.ThreadCpuStatUtil;
+import com.alibaba.polardbx.gms.config.impl.ConnPoolConfigManager;
 import com.alibaba.polardbx.gms.topology.DbInfoManager;
 import com.alibaba.polardbx.gms.util.GroupInfoUtil;
 import com.alibaba.polardbx.optimizer.config.table.TableColumnUtils;
@@ -46,6 +47,11 @@
 import com.alibaba.polardbx.optimizer.config.table.TableMeta;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.dialect.DbType;
+import com.alibaba.polardbx.optimizer.core.planner.rule.OptimizeModifyReturningRule;
+import com.alibaba.polardbx.optimizer.core.planner.rule.PushModifyRule;
+import com.alibaba.polardbx.optimizer.core.planner.rule.PushProjectRule;
+import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil;
+import com.alibaba.polardbx.optimizer.core.profiler.cpu.CpuStat;
 import com.alibaba.polardbx.optimizer.core.rel.BaseTableOperation;
 import com.alibaba.polardbx.optimizer.core.rel.BroadcastTableModify;
 import com.alibaba.polardbx.optimizer.core.rel.DirectTableOperation;
@@ -55,6 +61,7 @@
 import com.alibaba.polardbx.optimizer.core.rel.LogicalModify;
 import com.alibaba.polardbx.optimizer.core.rel.LogicalModifyView;
 import com.alibaba.polardbx.optimizer.core.rel.LogicalRelocate;
+import com.alibaba.polardbx.optimizer.core.rel.LogicalView;
 import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan;
 import com.alibaba.polardbx.optimizer.core.rel.PhyTableModifyViewBuilder;
 import com.alibaba.polardbx.optimizer.core.rel.PhyTableScanBuilder;
@@ -75,8 +82,10 @@
 import com.alibaba.polardbx.optimizer.utils.ExplainResult;
 import com.alibaba.polardbx.optimizer.utils.ITransaction;
 import com.alibaba.polardbx.optimizer.utils.OptimizerUtils;
+import com.alibaba.polardbx.optimizer.utils.PartitionUtils;
 import com.alibaba.polardbx.optimizer.utils.PlannerUtils;
 import com.alibaba.polardbx.optimizer.utils.RelUtils;
+import com.alibaba.polardbx.optimizer.utils.RelUtils.LogicalModifyViewBuilder;
 import com.alibaba.polardbx.rule.TableRule;
 import com.alibaba.polardbx.rule.model.TargetDB;
 import com.alibaba.polardbx.rule.utils.CalcParamsAttribute;
@@ -98,6 +107,7 @@
 import org.apache.calcite.sql.SqlSelect;
 import org.apache.calcite.sql.SqlUpdate;
 import org.apache.calcite.util.Util;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 import java.util.EnumSet;
@@ -107,9 +117,13 @@
 import java.util.Map;
 import java.util.Random;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.function.BiConsumer;
 
+import static com.alibaba.polardbx.optimizer.core.planner.rule.OptimizeModifyReturningRule.OPTIMIZE_MODIFY_RETURNING_RULES;
 import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isExplainOptimizer;
 import static com.alibaba.polardbx.optimizer.utils.ExplainResult.isExplainSharding;
+import static com.alibaba.polardbx.optimizer.utils.OptimizerUtils.hasDNHint;
 import static com.google.common.util.concurrent.Runnables.doNothing;
 
 /**
@@ -156,7 +170,7 @@ public boolean isSkipPostPlan() {
                 return skipPostPlan;
             }
         }
-        if (direct || shouldSkipPostPlanner) {
+        if (direct || shouldSkipPostPlanner || plannerContext.hasLocalIndexHint() || hasDNHint(plannerContext)) {
             plannerContext.setSkipPostOpt(true);
             return;
         }
@@ -246,12 +260,27 @@ public ExecutionPlan optimize(ExecutionPlan executionPlan, ExecutionContext exec
 
             List schemaNamesOfPlan = new ArrayList();
 
+            // Optimize modify on topN
+            final List modifyTopNOperands = new ArrayList<>();
+            final boolean isModifyTopN =
+                isModifyTopNCanBeOptimizedByReturning(executionPlan, modifyTopNOperands, executionContext);
+
+            final boolean cachePartPrunedResult = isModifyTopN;
+            final Map> partitionResult = new TreeMap<>(String::compareToIgnoreCase);
+            final BiConsumer partitionResultConsumer = cachePartPrunedResult ?
+                (tableName, partResult) -> partitionResult
+                    .computeIfAbsent(tableName, (k) -> new ArrayList<>())
+                    .add(partResult)
+                : null;
+
+            // Build target tables
             Map>> targetTables = getTargetTablesAndSchemas(logTableNames,
                 executionPlan,
                 executionContext,
                 schemaNamesOfPlan,
                 forceAllowFullTableScan,
-                false);
+                false,
+                partitionResultConsumer);
 
             boolean canPushdown = (schemaNamesOfPlan.size() == 1);
             if (ScaleOutPlanUtil.isEnabledScaleOut(executionContext.getParamManager())
@@ -295,13 +324,10 @@ public ExecutionPlan optimize(ExecutionPlan executionPlan, ExecutionContext exec
                 boolean needRelicateWrite = true;
                 boolean isNewPart = DbInfoManager.getInstance().isNewPartitionDb(schemaNamesOfAst);
                 String groupName = targetTables.keySet().iterator().next();
-                boolean needOnlineColumnModify = false;
                 boolean hasGeneratedColumn = false;
                 for (String tableName : logTableNames) {
                     withGsi &=
-                        GlobalIndexMeta.hasIndex(tableName, schemaNamesOfAst, executionContext);
-                    needOnlineColumnModify |=
-                        TableColumnUtils.isModifying(schemaNamesOfAst, tableName, executionContext);
+                        GlobalIndexMeta.hasGsi(tableName, schemaNamesOfAst, executionContext);
                     hasGeneratedColumn |=
                         GeneratedColumnUtil.containLogicalGeneratedColumn(schemaNamesOfAst,
                             tableName,
@@ -324,11 +350,13 @@ public ExecutionPlan optimize(ExecutionPlan executionPlan, ExecutionContext exec
                         }
 
                     }
-                    canPushdown &= !withGsi & !needRelicateWrite & !needOnlineColumnModify
-                        & !hasGeneratedColumn;
+                    canPushdown &= !withGsi & !needRelicateWrite & !hasGeneratedColumn;
                 }
             }
-            canPushdown &= !RelUtils.existUnPushableLastInsertId(plan);
+
+            // handle optimize modify top n by returning
+
+            canPushdown &= !RelUtils.existUnPushableLastInsertId(executionPlan);
             canPushdown &= isAllAtOnePhyTb && !existUnPushableRelNode(plan);
             if (canPushdown) {
                 String schemaNamesOfAst = schemaNamesOfPlan.get(0);
@@ -424,6 +452,19 @@ public ExecutionPlan optimize(ExecutionPlan executionPlan, ExecutionContext exec
                 } // end of switch
 
             } else {
+                // Check pruned partition is ordered by partition key
+                final boolean pushModifyTopN = isModifyTopN
+                    && modifyTopNOperands.size() > 1
+                    && PartitionUtils.checkPrunedPartitionMonotonic(
+                    (LogicalView) modifyTopNOperands.get(2),
+                    partitionResult.values().iterator().next());
+                if (pushModifyTopN) {
+                    if (!isAllAtOnePhyTb) {
+                        executionPlan.getPlanProperties().set(ExecutionPlanProperties.MODIFY_CROSS_DB);
+                    }
+                    return executionPlan.copy(pushdownModifyOnTopN(modifyTopNOperands));
+                }
+
                 /*
                  * Maybe some tables at one group
                  */
@@ -443,6 +484,17 @@ public ExecutionPlan optimize(ExecutionPlan executionPlan, ExecutionContext exec
                         throw new TddlRuntimeException(ErrorCode.ERR_UPDATE_DELETE_NO_PRIMARY_KEY,
                             String.join(",", ((LogicalModify) plan).getTargetTableNames()));
                     } else {
+                        if (isAllAtOnePhyTb) {
+                            final List bindings = new ArrayList<>();
+                            final LogicalModifyViewBuilder lmvBuilder =
+                                isLogicalMultiWriteCanBeOptimizedByReturning(executionPlan, bindings, executionContext);
+
+                            if (lmvBuilder != null) {
+                                final LogicalModify modify = (LogicalModify) bindings.get(0);
+                                modify.getMultiWriteInfo().setLmvBuilder(lmvBuilder);
+                                modify.getMultiWriteInfo().setOptimizeByReturning(true);
+                            }
+                        }
                         executionPlan = executionPlan.copy(executionPlan.getPlan());
                         executionPlan.getPlanProperties()
                             .set(ExecutionPlanProperties.MODIFY_CROSS_DB);
@@ -479,6 +531,144 @@ public ExecutionPlan optimize(ExecutionPlan executionPlan, ExecutionContext exec
         return executionPlan;
     }
 
+    private static LogicalModifyViewBuilder isLogicalMultiWriteCanBeOptimizedByReturning(
+        @NotNull ExecutionPlan executionPlan,
+        @NotNull List bindings,
+        @NotNull ExecutionContext ec) {
+        if (!supportOptimizeMultiWriteByReturning(executionPlan, ec)) {
+            return null;
+        }
+
+        return isPushableLogicalMultiWrite(executionPlan, bindings);
+    }
+
+    /**
+     * Check xrpc is enabled and returning is supported
+     */
+    private static boolean supportOptimizeMultiWriteByReturning(@NotNull ExecutionPlan plan,
+                                                                @NotNull ExecutionContext ec) {
+        if (plan.getSchemaNames().size() != 1) {
+            // do not support cross schema
+            return false;
+        }
+
+        final String schemaName = plan.getSchemaNames().iterator().next();
+
+        // check DML_USE_RETURNING enabled
+        // check OPTIMIZE_DELETE_BY_RETURNING enabled
+        // check returning supported in dn
+        // check xrpc enabled
+        if (!ec.getParamManager().getBoolean(ConnectionParams.DML_USE_RETURNING)
+            || !ec.getParamManager().getBoolean(ConnectionParams.OPTIMIZE_DELETE_BY_RETURNING)
+            || !ec.getStorageInfo(schemaName).isSupportsReturning()
+            || !ConnPoolConfigManager.getInstance().getConnPoolConfig().isStorageDbXprotoEnabled()) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Validate plan is logical multi write and can be pushdown
+     *
+     * @param executionPlan plan
+     * @param bindings for return binding operands, List{LogicalModify,MergeSort,LogicalView}
+     */
+    private static LogicalModifyViewBuilder isPushableLogicalMultiWrite(@NotNull ExecutionPlan executionPlan,
+                                                                        @NotNull List bindings) {
+        final boolean isMultiWriteCanBeOptimizedByReturning = executionPlan.getPlan() instanceof LogicalModify
+            && ((LogicalModify) executionPlan.getPlan()).isMultiWriteCanBeOptimizedByReturning();
+
+        if (!isMultiWriteCanBeOptimizedByReturning) {
+            return null;
+        }
+
+        for (OptimizeModifyReturningRule rule : OPTIMIZE_MODIFY_RETURNING_RULES) {
+            if (RelUtils.matchPlan(executionPlan.getPlan(), rule.getOperand(), bindings, null)) {
+                return rule;
+            }
+        }
+
+        return null;
+    }
+
+    private static LogicalModifyView pushdownModifyOnTopN(List modifyOnTopNOperands) {
+        LogicalModify modify = (LogicalModify) modifyOnTopNOperands.get(0);
+        final LogicalView lv = (LogicalView) modifyOnTopNOperands.get(2);
+        final LogicalModifyView lmv =
+            new LogicalModifyView(lv, modify.getModifyTopNInfo().setOptimizeByReturning(true));
+        lmv.push(modify);
+        RelUtils.changeRowType(lmv, modify.getRowType());
+
+        return lmv;
+    }
+
+    /**
+     * Validation for pushdown logicalModify at runtime in case of xrpc is closed manually
+     *
+     * @return 
+     * true means:
+     *  1. current plan is a modify-on-topN (order by limit)
+     *  2. current plan is possible to be optimized by returning, when partitions to be scanned is monotonic on order by column
+     * 
+ */ + private static boolean isModifyTopNCanBeOptimizedByReturning(@NotNull ExecutionPlan executionPlan, + @NotNull List bindings, + @NotNull ExecutionContext ec) { + if (!supportOptimizeModifyTopNByReturning(executionPlan, ec)) { + return false; + } + + return isModifyTopN(executionPlan, bindings); + } + + /** + * Check xrpc is enabled and returning is supported + */ + private static boolean supportOptimizeModifyTopNByReturning(@NotNull ExecutionPlan plan, + @NotNull ExecutionContext ec) { + if (plan.getSchemaNames().size() != 1) { + // do not support cross schema + return false; + } + + final String schemaName = plan.getSchemaNames().iterator().next(); + + // check DML_USE_RETURNING enabled + // check OPTIMIZE_MODIFY_TOP_N_BY_RETURNING enabled + // check returning supported in dn + // check xrpc enabled + if (!ec.getParamManager().getBoolean(ConnectionParams.DML_USE_RETURNING) + || !ec.getParamManager().getBoolean(ConnectionParams.OPTIMIZE_MODIFY_TOP_N_BY_RETURNING) + || !ec.getStorageInfo(schemaName).isSupportsReturning() + || !ConnPoolConfigManager.getInstance().getConnPoolConfig().isStorageDbXprotoEnabled()) { + return false; + } + return true; + } + + /** + * Validate plan is modify on topN + * + * @param executionPlan plan + * @param bindings for return binding operands, List{LogicalModify,MergeSort,LogicalView} + */ + private static boolean isModifyTopN(@NotNull ExecutionPlan executionPlan, @NotNull List bindings) { + + /* + * Plan for + * update t1 set pad = 11 where id=1 and user_id=1 and create_time<=now() order by create_time desc limit 1; + * looks like: + | LogicalModify(TYPE="UPDATE", SET="t1.pad=?0") | + | MergeSort(sort="create_time DESC", fetch=?4) | + | LogicalView(tables="t1[p16sp202403a,p16sp202403b,p16sp202403c,p16sp202404a]", shardCount=4, sql="SELECT `id`, `user_id`, `pad`, `create_time`, ? FROM `t1` AS `t1` WHERE ((`id` = ?) AND (`user_id` = ?) AND (`create_time` <= ?)) ORDER BY `create_time` DESC LIMIT ? FOR UPDATE") + */ + + // check plan is modify on topN + return executionPlan.getPlan() instanceof LogicalModify + && ((LogicalModify) executionPlan.getPlan()).isModifyTopN() + && RelUtils.matchPlan(executionPlan.getPlan(), PushModifyRule.MERGESORT.getOperand(), bindings, null); + } + /** * Whether is direct broadcast table plan */ @@ -520,7 +710,7 @@ private static boolean isOnlyBroadcast(final ExecutionPlan executionPlan, * 2. Choose a random group if it's the first statement in transaction * 3. Skip single-group if any other groups exist */ - private String getBroadcastTableGroup(ExecutionContext executionContext, String schemaName) { + public static String getBroadcastTableGroup(ExecutionContext executionContext, String schemaName) { ITransaction transaction = executionContext.getTransaction(); List candidateGroups = null; if (transaction != null) { @@ -582,6 +772,9 @@ public static boolean skipPostPlanner(final ExecutionPlan executionPlan, return true; } + if (plan instanceof Gather && ((Gather) plan).getInput() instanceof LogicalView) { + return true; + } // For Pushed DML with subquery, sqlTemplate in LogicalModifyView should be replaced by original ast return plan instanceof LogicalModifyView && !RelUtils.dmlWithDerivedSubquery(plan, ast); } @@ -608,7 +801,8 @@ private Map>> getTargetTablesAndSchemas(List t ExecutionContext executionContext, List schemasToBeReturn, boolean forceAllowFullTableScan, - boolean allowMultiSchema) { + boolean allowMultiSchema, + BiConsumer partPrunedResultBiConsumer) { Map params = executionContext.getParams() == null ? null : @@ -693,6 +887,10 @@ private Map>> getTargetTablesAndSchemas(List t PartPrunedResult prunedResult = PartitionPruner.doPruningByStepInfo(stepInfo, executionContext); + if (null != partPrunedResultBiConsumer) { + partPrunedResultBiConsumer.accept(name, prunedResult); + } + // covert to targetDbList targetDBs.add( PartitionPrunerUtils.buildTargetDbsByPartPrunedResults(prunedResult)); @@ -748,6 +946,11 @@ private Map>> getTargetTablesAndSchemas(List t PartitionPruneStep stepInfo = shardInfo.getPartPruneStepInfo(); PartPrunedResult prunedResult = PartitionPruner.doPruningByStepInfo(stepInfo, executionContext); + + if (null != partPrunedResultBiConsumer) { + partPrunedResultBiConsumer.accept(name, prunedResult); + } + // covert to targetDbList targetDBs.add(PartitionPrunerUtils.buildTargetDbsByPartPrunedResults( prunedResult)); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/SqlConverter.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/SqlConverter.java index c3d4315ea..62ce12214 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/SqlConverter.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/SqlConverter.java @@ -234,7 +234,7 @@ public RelOptCluster createRelOptCluster(PlannerContext plannerContext) { RelOptCostFactory costFactory = DrdsRelOptCostImpl.FACTORY; VolcanoPlanner planner = new VolcanoPlanner(costFactory, plannerContext); if (plannerContext != null && plannerContext.getExecutionContext() != null && - plannerContext.getExecutionContext().isEnableRuleCounter()) { + plannerContext.isEnableRuleCounter()) { planner.setRuleCounter(); } planner.clearRelTraitDefs(); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Xplanner/RelXPlanOptimizer.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Xplanner/RelXPlanOptimizer.java index fe448901d..f171d4d21 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Xplanner/RelXPlanOptimizer.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Xplanner/RelXPlanOptimizer.java @@ -69,6 +69,9 @@ public static boolean canUseXPlan(SqlNode sqlNode) { public static void setXTemplate(BaseQueryOperation operation, RelNode relNode, ExecutionContext ec) { + if (ec.isFlashbackArea()) { + return; + } final RelToXPlanConverter converter = new RelToXPlanConverter(); try { RelNode node = RelXPlanOptimizer.optimize(relNode); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Xplanner/XPlanUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Xplanner/XPlanUtil.java index 1942f356b..c4925cd57 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Xplanner/XPlanUtil.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/Xplanner/XPlanUtil.java @@ -803,13 +803,20 @@ public enum Type { public final Type type; public final int id; - public final RelDataType dataType; + private final boolean isBit; public final boolean nullable; public ScalarParamInfo(Type type, int id, RelDataType dataType, boolean nullable) { this.type = type; this.id = id; - this.dataType = dataType; + this.isBit = dataType == null ? false : dataType.getSqlTypeName() == SqlTypeName.BIT; + this.nullable = nullable; + } + + public ScalarParamInfo(Type type, int id, boolean isBit, boolean nullable) { + this.type = type; + this.id = id; + this.isBit = isBit; this.nullable = nullable; } @@ -821,12 +828,12 @@ public int getId() { return id; } - public RelDataType getDataType() { - return dataType; - } - public boolean isNullable() { return nullable; } + + public boolean isBit() { + return isBit; + } } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/AccessPathRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/AccessPathRule.java index ce226a1a8..d3be83e44 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/AccessPathRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/AccessPathRule.java @@ -20,6 +20,7 @@ import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.TreeMaps; +import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.gms.metadb.table.IndexVisibility; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.PlannerContext; @@ -85,6 +86,8 @@ import java.util.TreeSet; import java.util.stream.Collectors; +import static com.alibaba.polardbx.optimizer.index.IndexUtil.getForceIndex; + public abstract class AccessPathRule extends RelOptRule { public AccessPathRule(RelOptRuleOperand operand, String description) { @@ -188,8 +191,7 @@ public void onMatch(RelOptRuleCall call) { new IndexScanVisitor(primaryTable, indexTable, call.builder()); final LogicalIndexScan logicalIndexScan = new LogicalIndexScan(plan.accept(indexScanVisitor), indexTable, logicalView.getHints(), - lockMode, logicalView.getFlashback()); - + lockMode, logicalView.getFlashback(), logicalView.aggIsPushed()); logicalIndexScan.rebuildPartRoutingPlanInfo(); if (shouldPruneGsi(logicalIndexScan, mq, primaryCanUseIndex, logicalView)) { @@ -393,17 +395,21 @@ public static boolean hasOnlyOneAccessPath(LogicalView logicalView, ExecutionCon } public static List getGsiNameList(LogicalView logicalView, ExecutionContext ec) { + if (logicalView.isFromForceIndex()) { + return null; + } final String schemaName = logicalView.getSchemaName(); List gsiPublishedNameList = null; + String logicalTableName = null; + if (logicalView.getTableNames().size() == 1 && !logicalView.isSingleGroup()) { // do index selection for single logical table only - final String logicalTableName = logicalView.getLogicalTableName(); + logicalTableName = logicalView.getLogicalTableName(); gsiPublishedNameList = GlobalIndexMeta.getPublishedIndexNames(logicalTableName, schemaName, ec); gsiPublishedNameList = filterVisibleIndex(schemaName, logicalTableName, gsiPublishedNameList, ec); } else if (logicalView.getTableNames().size() > 1) { // do index selection for shard logical table with multi broadcast table List tableNames = logicalView.getTableNames(); - String logicalTableName = null; for (String tableName : tableNames) { if (!ec.getSchemaManager(schemaName).getTddlRuleManager().isBroadCast(tableName)) { if (logicalTableName == null) { @@ -421,22 +427,50 @@ public static List getGsiNameList(LogicalView logicalView, ExecutionCont } if (logicalView.getIndexNode() != null) { - gsiPublishedNameList = filterUseIgnoreIndex(schemaName, gsiPublishedNameList, logicalView.getIndexNode()); + gsiPublishedNameList = + filterUseIgnoreIndex(schemaName, logicalTableName, gsiPublishedNameList, logicalView.getIndexNode(), + ec); + } + if (ec.getIgnoredGsi() != null) { + gsiPublishedNameList = + gsiPublishedNameList.stream().filter(x -> !ec.getIgnoredGsi().contains(x)).collect(Collectors.toList()); } return gsiPublishedNameList; } - public static List filterUseIgnoreIndex(String schemaName, List gsiNameList, SqlNode indexNode) { + public static List filterUseIgnoreIndex(String schemaName, String logicalTableName, + List gsiNameList, SqlNode indexNode, ExecutionContext ec) { Set gsiNameSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); if (gsiNameList == null) { return new ArrayList<>(); } - // force index(PRIMARY) - Set gsiForceNameSet = IndexUtil.getForceIndex(indexNode); - if (gsiForceNameSet.size() == 1 && gsiForceNameSet.iterator().next().equalsIgnoreCase("PRIMARY")) { - return new ArrayList<>(); + // force index gsi should be handled&remove in ToDrdsRelVisitor. force index only local index can be stayed + Set forceIndex = getForceIndex(indexNode); + if (forceIndex.size() > 0) { + List forceResult = new ArrayList<>(); + // local index strategy: return all the gsi and primary table that contains this local index + String indexName = forceIndex.iterator().next(); + indexName = SQLUtils.normalizeNoTrim(indexName); + if (GeneralUtil.isPrimary(indexName)) { + return forceResult; + } + TableMeta tableMeta = ec.getSchemaManager(schemaName).getTable(logicalTableName); + + // ignore local index that not in main table + if (tableMeta.findLocalIndexByName(indexName) == null) { + return forceResult; + } + + for (String gsiName : gsiNameList) { + TableMeta gsiTableMeta = ec.getSchemaManager(schemaName).getTable(gsiName); + if (gsiTableMeta != null && gsiTableMeta.findLocalIndexByName(indexName) != null) { + forceResult.add(gsiName); + } + } + + return forceResult; } gsiNameSet.addAll(gsiNameList); @@ -534,7 +568,7 @@ public RelNode visit(TableScan scan) { Set useIndexNames = IndexUtil.getUseIndex(scan.getIndexNode()); Set ignoreIndexNames = IndexUtil.getIgnoreIndex(scan.getIndexNode()); - Set forceIndexNames = IndexUtil.getForceIndex(scan.getIndexNode()); + Set forceIndexNames = getForceIndex(scan.getIndexNode()); Set normalizedUseIndexNames = normalizeIndexNames(useIndexNames, tableName, schemaName, PlannerContext.getPlannerContext(scan).getExecutionContext()); @@ -629,16 +663,61 @@ public RelNode visit(TableScan scan) { return super.visit(scan); } - final LogicalView primary = RelUtils.createLogicalView(scan, lockMode); - final LogicalTableScan indexTableScan = - LogicalTableScan.create(scan.getCluster(), this.indexTable, scan.getHints(), null, scan.getFlashback(), + SqlNode indexNode = scan.getIndexNode(); + Pair forceIndexAndOtherIndex = stripForceIndex(indexNode); + SqlNodeList force = forceIndexAndOtherIndex.getKey(); + SqlNodeList otherIndex = forceIndexAndOtherIndex.getValue(); + + // use empty scan to build primary table + TableScan newScan = + LogicalTableScan.create(scan.getCluster(), primaryTable, scan.getHints(), otherIndex, + scan.getFlashback(), scan.getFlashbackOperator(), + scan.getPartitions()); + + final LogicalView primary = RelUtils.createLogicalView(newScan, lockMode); + + // use index hint to build index table + final LogicalTableScan indexTableScan = + LogicalTableScan.create(scan.getCluster(), this.indexTable, scan.getHints(), force, + scan.getFlashback(), scan.getFlashbackOperator(), null); final LogicalIndexScan index = new LogicalIndexScan(this.indexTable, indexTableScan, lockMode); index.setFlashback(scan.getFlashback()); index.setFlashbackOperator(scan.getFlashbackOperator()); return RelUtils.createTableLookup(primary, index, index.getTable()); } + + /** + * Splits the input index node list into two lists: one containing forced indexes, + * and another containing non-forced ones. + * + * @param indexNode List of index nodes + * @return A pair of lists - the first contains forced indexes, the second has non-forced ones + */ + private Pair stripForceIndex(SqlNode indexNode) { + // Return nulls if the input is not a SqlNodeList instance + if (!(indexNode instanceof SqlNodeList)) { + return Pair.of(null, null); + } + // Initialize lists for forced and non-forced index hints + SqlNodeList forcePart = new SqlNodeList(SqlParserPos.ZERO); + SqlNodeList nonForcedHints = new SqlNodeList(SqlParserPos.ZERO); + + final SqlNodeList indexNodeList = (SqlNodeList) indexNode; + for (SqlNode index : indexNodeList) { + if (index instanceof SqlIndexHint) { + SqlIndexHint indexHint = (SqlIndexHint) index; + if (indexHint.forceIndex()) { + forcePart.add(index); + } else { + nonForcedHints.add(indexHint); + } + } + } + + return Pair.of(forcePart, nonForcedHints); + } } private static class IndexScanVisitor extends RelShuttleImpl { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/AutoForceIndexRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/AutoForceIndexRule.java new file mode 100644 index 000000000..d4a3b9c44 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/AutoForceIndexRule.java @@ -0,0 +1,45 @@ +package com.alibaba.polardbx.optimizer.core.planner.rule; + +import com.alibaba.polardbx.optimizer.core.planner.rule.util.ForceIndexUtil; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.plan.RelOptRule; +import org.apache.calcite.plan.RelOptRuleCall; +import org.apache.calcite.rel.core.TableScan; +import org.apache.calcite.rel.logical.LogicalTableScan; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlIndexHint; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlNodeList; +import org.apache.calcite.sql.parser.SqlParserPos; + +public class AutoForceIndexRule extends RelOptRule { + + String indexName; + + public AutoForceIndexRule(String indexName) { + super(operand(TableScan.class, RelOptRule.none()), + "AutoForceIndexRule"); + this.indexName = indexName; + } + + @Override + public boolean matches(RelOptRuleCall call) { + TableScan scan = call.rel(0); + return !ForceIndexUtil.hasIndexHint(scan); + } + + @Override + public void onMatch(RelOptRuleCall call) { + TableScan scan = call.rel(0); + SqlNode sqlNode = new SqlNodeList(ImmutableList.of( + new SqlIndexHint(SqlLiteral.createCharString("FORCE INDEX", SqlParserPos.ZERO), null, + new SqlNodeList(ImmutableList.of(SqlLiteral.createCharString( + SqlIdentifier.surroundWithBacktick(indexName), SqlParserPos.ZERO)), + SqlParserPos.ZERO), SqlParserPos.ZERO)), SqlParserPos.ZERO); + LogicalTableScan newScan = + LogicalTableScan.create(scan.getCluster(), scan.getTable(), scan.getHints(), + sqlNode, scan.getFlashback(), scan.getFlashbackOperator(), scan.getPartitions()); + call.transformTo(newScan); + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/CBOPushAggRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/CBOPushAggRule.java index 4fe8e7ec1..45b820d82 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/CBOPushAggRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/CBOPushAggRule.java @@ -19,9 +19,8 @@ import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.core.DrdsConvention; -import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; -import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.TwoPhaseAggUtil; import com.alibaba.polardbx.optimizer.core.rel.LogicalView; import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager; @@ -34,29 +33,12 @@ import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.Aggregate; import org.apache.calcite.rel.core.AggregateCall; -import org.apache.calcite.rel.core.GroupConcatAggregateCall; import org.apache.calcite.rel.logical.LogicalAggregate; import org.apache.calcite.rel.logical.LogicalProject; import org.apache.calcite.rel.rules.ProjectRemoveRule; -import org.apache.calcite.rel.type.RelDataType; -import org.apache.calcite.rex.RexBuilder; -import org.apache.calcite.rex.RexCall; -import org.apache.calcite.rex.RexInputRef; import org.apache.calcite.rex.RexNode; -import org.apache.calcite.sql.SqlAggFunction; -import org.apache.calcite.sql.fun.SqlCheckSumMergeFunction; -import org.apache.calcite.sql.fun.SqlCheckSumV2MergeFunction; -import org.apache.calcite.sql.fun.SqlCountAggFunction; -import org.apache.calcite.sql.fun.SqlFinalHyperloglogFunction; -import org.apache.calcite.sql.fun.SqlPartialHyperloglogFunction; -import org.apache.calcite.sql.fun.SqlStdOperatorTable; -import org.apache.calcite.sql.fun.SqlSumAggFunction; -import org.apache.calcite.sql.fun.SqlSumEmptyIsZeroAggFunction; -import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.util.ImmutableBitSet; -import org.apache.calcite.util.ImmutableIntList; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -156,33 +138,11 @@ private RelNode tryPushAgg(LogicalAggregate logicalAggregate, LogicalView logica return newLogicalView; } - boolean enablePushDownDistinct = PlannerContext.getPlannerContext( - logicalAggregate).getParamManager().getBoolean(ConnectionParams.ENABLE_PUSHDOWN_DISTINCT); - boolean enableSplitDistinct = false; - if (enablePushDownDistinct && logicalAggregate.groupSets.size() <= 1 && haveAggWithDistinct( - logicalAggregate.getAggCallList())) { - enableSplitDistinct = canSplitDistinct(shardIndex, logicalAggregate); - } - - TwoPhaseAggComponent twoPhaseAggComponent = null; - if (enableSplitDistinct) { - twoPhaseAggComponent = splitAgg( - logicalAggregate, logicalView instanceof OSSTableScan, true); - } - - if (twoPhaseAggComponent == null) { - if (haveAggWithDistinct(logicalAggregate.getAggCallList())) { - return null; - } - - twoPhaseAggComponent = splitAgg( - logicalAggregate, logicalView instanceof OSSTableScan, false); - } - + TwoPhaseAggUtil.TwoPhaseAggComponent twoPhaseAggComponent = + TwoPhaseAggUtil.splitAggWithDistinct(logicalAggregate, logicalView, shardIndex); if (twoPhaseAggComponent == null) { return null; } - List childExps = twoPhaseAggComponent.getProjectChildExps(); List globalAggCalls = twoPhaseAggComponent.getGlobalAggCalls(); ImmutableBitSet globalAggGroupSet = twoPhaseAggComponent.getGlobalAggGroupSet(); @@ -216,321 +176,17 @@ private RelNode tryPushAgg(LogicalAggregate logicalAggregate, LogicalView logica } } - private boolean fullMatchSharding(LogicalAggregate logicalAggregate, LogicalView logicalView, - List shardColumns, Set shardIndex) { + public static boolean fullMatchSharding(Aggregate aggregate, LogicalView logicalView, + List shardColumns, Set shardIndex) { int matchNum = 0; for (String shardName : shardColumns) { int shardRef = logicalView.getRefByColumnName(logicalView.getShardingTable(), shardName, false, true); - if (shardRef != -1 && logicalAggregate.getGroupSet().asList().contains(shardRef)) { + if (shardRef != -1 && aggregate.getGroupSet().asList().contains(shardRef)) { matchNum++; } shardIndex.add(shardRef); } return matchNum != 0 && matchNum == shardColumns.size(); } - - public static class TwoPhaseAggComponent { - - private List projectChildExps; // Upper Project - private List globalAggCalls; // Global Agg - private ImmutableBitSet globalAggGroupSet; - private List partialAggCalls;// Partial Agg - private ImmutableBitSet partialAggGroupSet; - - public TwoPhaseAggComponent(List projectChildExps, - List globalAggCalls, ImmutableBitSet globalAggGroupSet, - List partialAggCalls, ImmutableBitSet partialAggGroupSet) { - this.projectChildExps = projectChildExps; - this.globalAggCalls = globalAggCalls; - this.globalAggGroupSet = globalAggGroupSet; - this.partialAggCalls = partialAggCalls; - this.partialAggGroupSet = partialAggGroupSet; - } - - public List getProjectChildExps() { - return projectChildExps; - } - - public List getGlobalAggCalls() { - return globalAggCalls; - } - - public List getPartialAggCalls() { - return partialAggCalls; - } - - public ImmutableBitSet getGlobalAggGroupSet() { - return globalAggGroupSet; - } - - public ImmutableBitSet getPartialAggGroupSet() { - return partialAggGroupSet; - } - } - - public static TwoPhaseAggComponent splitAgg(Aggregate agg) { - return splitAgg(agg, true, false); - } - - public static TwoPhaseAggComponent splitAgg(Aggregate agg, boolean canSplitOrcHash, boolean withDistinct) { - TddlTypeFactoryImpl tddlTypeFactory = new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); - List childExps = new ArrayList<>(); - final int aggGroupSetCardinality = agg.getGroupSet().cardinality(); - for (int i = 0; i < aggGroupSetCardinality; i++) { - childExps.add(new RexInputRef(i, agg.getRowType().getFieldList().get(i).getType())); - } - - List globalAggCalls = new ArrayList<>(); - List partialAggCalls = new ArrayList<>(); - - for (int i = 0; i < agg.getAggCallList().size(); i++) { - AggregateCall aggCall = agg.getAggCallList().get(i); - boolean isDistinct = aggCall.isDistinct() && withDistinct; - try { - if (isDistinct) { - buildTwoAggCallsWithDistinct( - aggCall, aggGroupSetCardinality, globalAggCalls, partialAggCalls, childExps); - } else { - buildTwoAggCalls( - aggCall, tddlTypeFactory, aggGroupSetCardinality, globalAggCalls, partialAggCalls, childExps, - canSplitOrcHash, agg.getCluster().getRexBuilder()); - } - } catch (UnsupportedOperationException t) { - // ignore - return null; - } - } - return new TwoPhaseAggComponent(childExps, globalAggCalls, - ImmutableBitSet.range(agg.getGroupSet().cardinality()), - partialAggCalls, agg.getGroupSet()); - } - - private static void buildTwoAggCallsWithDistinct(AggregateCall aggCall, - int aggGroupSetCardinality, - List globalAggCalls, - List partialAggCalls, - List childExps) { - SqlAggFunction function = aggCall.getAggregation(); - switch (function.getKind()) { - case COUNT: - SqlSumEmptyIsZeroAggFunction sumAggFunction = new SqlSumEmptyIsZeroAggFunction(); - - AggregateCall sumAggregateCall = AggregateCall.create(sumAggFunction, - false, - aggCall.isApproximate(), - ImmutableList.of(aggGroupSetCardinality + partialAggCalls.size()), - aggCall.filterArg, - aggCall.getType(), - aggCall.getName()); - - globalAggCalls.add(sumAggregateCall); - - childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); - - partialAggCalls.add(aggCall); - break; - case SUM: - AggregateCall newAggCall = - aggCall.copy( - ImmutableIntList.of(aggGroupSetCardinality + partialAggCalls.size()), -1).withDistinct(false); - globalAggCalls.add(newAggCall); - - childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); - - partialAggCalls.add(aggCall); - break; - default: - throw new UnsupportedOperationException(); - } - - } - - private static void buildTwoAggCalls(AggregateCall aggCall, TddlTypeFactoryImpl tddlTypeFactory, - int aggGroupSetCardinality, - List globalAggCalls, List partialAggCalls, - List childExps, - boolean canSplitOrcHash, RexBuilder rexBuilder) { - - SqlAggFunction function = aggCall.getAggregation(); - switch (function.getKind()) { - case COUNT: - SqlSumEmptyIsZeroAggFunction sumAggFunction = new SqlSumEmptyIsZeroAggFunction(); - - AggregateCall sumAggregateCall = AggregateCall.create(sumAggFunction, - aggCall.isDistinct(), - aggCall.isApproximate(), - ImmutableList.of(aggGroupSetCardinality + partialAggCalls.size()), - aggCall.filterArg, - aggCall.getType(), - aggCall.getName()); - - globalAggCalls.add(sumAggregateCall); - - childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); - - if (aggCall.getArgList().size() > 1) { - //make sure the count with one column, not with multi columns - aggCall = aggCall.copy(ImmutableList.of(aggCall.getArgList().get(0)), aggCall.filterArg); - } - - partialAggCalls.add(aggCall); - break; - case AVG: - SqlSumAggFunction partialSumAggFunc = new SqlSumAggFunction(null); - AggregateCall partialSumAggCall = AggregateCall.create(partialSumAggFunc, - aggCall.isDistinct(), - aggCall.isApproximate(), - aggCall.getArgList(), - aggCall.filterArg, - aggCall.getType(), - "partial_sum"); - - AggregateCall globalSumAggCall = - partialSumAggCall.copy(ImmutableIntList.of(aggGroupSetCardinality + partialAggCalls.size()), - -1, - false, - "global_sum"); - - partialAggCalls.add(partialSumAggCall); - - SqlCountAggFunction pushedCountFunc = new SqlCountAggFunction("COUNT"); - AggregateCall partialCountAggCall = AggregateCall.create(pushedCountFunc, - aggCall.isDistinct(), - aggCall.isApproximate(), - aggCall.getArgList(), - aggCall.filterArg, - tddlTypeFactory.createSqlType(SqlTypeName.BIGINT), - "partial_count"); - - AggregateCall globalCountAggCall = AggregateCall.create(partialSumAggFunc, - partialCountAggCall.isDistinct(), - partialCountAggCall.isApproximate(), - ImmutableIntList.of(aggGroupSetCardinality + partialAggCalls.size()), - partialCountAggCall.filterArg, - partialCountAggCall.getType(), - "global_count"); - - partialAggCalls.add(partialCountAggCall); - - RexInputRef partialSumRef = - new RexInputRef(globalSumAggCall.getArgList().get(0), partialSumAggCall.getType()); - RexInputRef partialCountRef = - new RexInputRef(globalCountAggCall.getArgList().get(0), partialCountAggCall.getType()); - - RexCall divide = (RexCall) rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE, - partialSumRef, - partialCountRef); - - RelDataType relDataType = aggCall.getType(); - if (!divide.getType().getSqlTypeName().equals(relDataType.getSqlTypeName())) { - RexNode castNode = rexBuilder.makeCastForConvertlet(relDataType, divide); - childExps.add(castNode); - } else { - childExps.add(divide); - } - - globalAggCalls.add(globalSumAggCall); - globalAggCalls.add(globalCountAggCall); - break; - case MIN: - case MAX: - case SUM: - case BIT_OR: - case BIT_XOR: - case __FIRST_VALUE: - AggregateCall newAggCall = - aggCall.copy(ImmutableIntList.of(aggGroupSetCardinality + partialAggCalls.size()), -1); - globalAggCalls.add(newAggCall); - - childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); - - partialAggCalls.add(aggCall); - break; - case GROUP_CONCAT: - GroupConcatAggregateCall groupConcatAggregateCall = (GroupConcatAggregateCall) aggCall; - if (groupConcatAggregateCall.getOrderList() != null - && groupConcatAggregateCall.getOrderList().size() != 0) { - throw new UnsupportedOperationException(); - } - GroupConcatAggregateCall newGroupConcatAggregateCall = - groupConcatAggregateCall.copy(ImmutableIntList.of(aggGroupSetCardinality + partialAggCalls.size()), - -1, groupConcatAggregateCall.getOrderList()); - globalAggCalls.add(newGroupConcatAggregateCall); - - childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); - - partialAggCalls.add(aggCall); - break; - case HYPER_LOGLOG: - SqlPartialHyperloglogFunction partialHllFunction = new SqlPartialHyperloglogFunction(); - AggregateCall partialHllAggregateCall = AggregateCall.create(partialHllFunction, - aggCall.isDistinct(), - aggCall.isApproximate(), - aggCall.getArgList(), - aggCall.filterArg, - tddlTypeFactory.createSqlType(SqlTypeName.VARBINARY), - "partial_hll"); - - SqlFinalHyperloglogFunction finalHllFunction = new SqlFinalHyperloglogFunction(); - AggregateCall finalHllAggregateCall = AggregateCall.create(finalHllFunction, - aggCall.isDistinct(), - aggCall.isApproximate(), - ImmutableList.of(aggGroupSetCardinality + partialAggCalls.size()), - aggCall.filterArg, - aggCall.getType(), - "final_hll"); - - globalAggCalls.add(finalHllAggregateCall); - - childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), - tddlTypeFactory.createSqlType(SqlTypeName.VARBINARY))); - - partialAggCalls.add(partialHllAggregateCall); - break; - case CHECK_SUM: - if (!canSplitOrcHash) { - throw new UnsupportedOperationException(); - } - SqlCheckSumMergeFunction crcAggFunction = new SqlCheckSumMergeFunction(); - - AggregateCall crcHashAggregateCall = AggregateCall.create(crcAggFunction, - aggCall.isDistinct(), - aggCall.isApproximate(), - ImmutableList.of(aggGroupSetCardinality + partialAggCalls.size()), - aggCall.filterArg, - aggCall.getType(), - aggCall.getName()); - - globalAggCalls.add(crcHashAggregateCall); - - childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); - - partialAggCalls.add(aggCall); - break; - case CHECK_SUM_V2: - if (!canSplitOrcHash) { - throw new UnsupportedOperationException(); - } - SqlCheckSumV2MergeFunction func = new SqlCheckSumV2MergeFunction(); - - AggregateCall call = AggregateCall.create(func, - aggCall.isDistinct(), - aggCall.isApproximate(), - ImmutableList.of(aggGroupSetCardinality + partialAggCalls.size()), - aggCall.filterArg, - aggCall.getType(), - aggCall.getName()); - - globalAggCalls.add(call); - - childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); - - partialAggCalls.add(aggCall); - break; - default: - throw new UnsupportedOperationException(); - } - } - } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/ConstantFoldRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/ConstantFoldRule.java index a06ada0d8..a0abfb2fc 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/ConstantFoldRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/ConstantFoldRule.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.function.calc.scalar.filter.Row; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; import com.alibaba.polardbx.optimizer.core.rel.PhysicalFilter; import com.alibaba.polardbx.optimizer.utils.ExprContextProvider; import com.alibaba.polardbx.optimizer.utils.RexUtils; @@ -59,13 +60,20 @@ public void onMatch(RelOptRuleCall call) { Filter filter = (Filter) call.rels[0]; RelNode input = filter.getInput(); + ExecutionContext ec = PlannerContext.getPlannerContext(filter).getExecutionContext(); + // don't apply this rule if it will be cached + if (CBOUtil.useColPlanCache(ec)) { + return; + } RexBuilder rb = call.builder().getRexBuilder(); RexConstantFoldShuttle rexConstantFoldShuttle = - new RexConstantFoldShuttle(rb, PlannerContext.getPlannerContext(filter).getExecutionContext()); + new RexConstantFoldShuttle(rb, ec); RexNode condition = filter.getCondition().accept(rexConstantFoldShuttle); if (condition == filter.getCondition()) { return; } + // set constant fold flag to avoid cache this plan + PlannerContext.getPlannerContext(filter).setHasConstantFold(true); if (filter instanceof LogicalFilter) { call.transformTo(LogicalFilter.create(input, condition, diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/JoinAggToJoinAggSemiJoinRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/JoinAggToJoinAggSemiJoinRule.java index 55850c5fc..4b9994db6 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/JoinAggToJoinAggSemiJoinRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/JoinAggToJoinAggSemiJoinRule.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Sets; @@ -25,20 +26,23 @@ import org.apache.calcite.plan.RelOptRuleCall; import org.apache.calcite.plan.RelOptRuleOperand; import org.apache.calcite.plan.RelOptUtil; +import org.apache.calcite.plan.volcano.RelSubset; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.RelShuttleImpl; import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.rel.core.RelFactories; +import org.apache.calcite.rel.core.TableScan; import org.apache.calcite.rel.logical.LogicalAggregate; import org.apache.calcite.rel.logical.LogicalJoin; import org.apache.calcite.rel.logical.LogicalSemiJoin; import org.apache.calcite.rex.RexBuilder; -import org.apache.calcite.rex.RexInputRef; import org.apache.calcite.rex.RexNode; -import org.apache.calcite.rex.RexVisitorImpl; import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.tools.RelBuilderFactory; +import org.apache.calcite.util.Util; import java.util.List; import java.util.Set; @@ -102,9 +106,15 @@ protected LogicalJoin transform(final LogicalJoin join, final LogicalAggregate a return null; } - List groupBy = agg.getGroupSet().toList(); - // build semi join + RelNode copiedRight; + try { + copiedRight = join.getRight().accept(new RelCopied()); + } catch (Util.FoundOne e) { + return null; + } + // build semi join + List groupBy = agg.getGroupSet().toList(); List semiConditions = Lists.newArrayList(); RexBuilder rexBuilder = join.getCluster().getRexBuilder(); @@ -114,7 +124,7 @@ protected LogicalJoin transform(final LogicalJoin join, final LogicalAggregate a RexNode leftRex = rexBuilder.makeInputRef(agg.getInput().getRowType().getFieldList().get(leftKey).getType(), leftKey); RexNode rightRex = - rexBuilder.makeInputRef(join.getRight().getRowType().getFieldList().get(rightKey).getType(), + rexBuilder.makeInputRef(copiedRight.getRowType().getFieldList().get(rightKey).getType(), rightKey + agg.getInput().getRowType().getFieldCount()); semiConditions.add(rexBuilder.makeCall(filterNulls.get(i) ? SqlStdOperatorTable.EQUALS : SqlStdOperatorTable.IS_NOT_DISTINCT_FROM, @@ -122,7 +132,7 @@ protected LogicalJoin transform(final LogicalJoin join, final LogicalAggregate a } relBuilder.push(agg.getInput()); - relBuilder.push(join.getRight()); + relBuilder.push(copiedRight); LogicalSemiJoin semiJoin = (LogicalSemiJoin) relBuilder.logicalSemiJoin(semiConditions, SqlStdOperatorTable.EQUALS, JoinRelType.SEMI, @@ -147,4 +157,22 @@ protected LogicalJoin transform(final LogicalJoin join, final LogicalAggregate a return newJoin; } + static class RelCopied extends RelShuttleImpl { + public RelNode visit(RelNode relNode) { + if (relNode instanceof RelSubset) { + if (((RelSubset) relNode).getOriginal() == null) { + throw Util.FoundOne.NULL; + } + return ((RelSubset) relNode).getOriginal().accept(this); + } + return visitChildren(relNode); + } + + public RelNode visit(TableScan scan) { + if (scan instanceof LogicalView) { + return ((LogicalView) scan).copy(scan.getTraitSet()); + } + throw Util.FoundOne.NULL; + } + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/OptimizeLogicalInsertRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/OptimizeLogicalInsertRule.java index 6ab4ef634..fd8f4425b 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/OptimizeLogicalInsertRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/OptimizeLogicalInsertRule.java @@ -87,6 +87,7 @@ import org.apache.calcite.rex.RexShuttle; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.util.mapping.Mappings; +import org.jetbrains.annotations.NotNull; import java.util.ArrayDeque; import java.util.ArrayList; @@ -717,7 +718,7 @@ private LogicalInsert handleInsertSelect(LogicalInsert insert, ExecutionContext if (!insert.getClass().isAssignableFrom(LogicalInsert.class) || !insert.isSourceSelect()) { return insert; } - final boolean hasIndex = GlobalIndexMeta.hasIndex( + final boolean hasIndex = GlobalIndexMeta.hasGsi( insert.getLogicalTableName(), insert.getSchemaName(), ec); final boolean gsiConcurrentWrite = ec.getParamManager().getBoolean(ConnectionParams.GSI_CONCURRENT_WRITE_OPTIMIZE); @@ -825,9 +826,8 @@ protected Map>> groupUkByTable(LogicalInsertIgnore ins insertIgnore.getTableUkMap() .entrySet() .stream() - .filter( - e -> writableIndexTables.contains(e.getKey().toUpperCase()) || primaryTableName.equalsIgnoreCase( - e.getKey())) + .filter(e -> writableIndexTables.contains(e.getKey().toUpperCase()) + || primaryTableName.equalsIgnoreCase(e.getKey())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); // Map uk to tables, must be exact match for uk @@ -854,21 +854,114 @@ protected Map>> groupUkByTable(LogicalInsertIgnore ins .collect(Collectors.toList())); } - for (Map.Entry> e : ukAllTableMap.entrySet()) { - List tableNames = e.getValue(); - List uniqueKey = uniqueKeys.get(e.getKey()); - boolean isPrimary = uniqueKey.containsAll(primaryKey) && primaryKey.containsAll(uniqueKey); - - // PK must be searched on primary table - String ukTargetTable = isPrimary ? primaryTableName : - getUkTargetTable(schemaName, primaryTableName, uniqueKey, tableNames, executionContext); - tableUkMap.computeIfAbsent(ukTargetTable.toUpperCase(), k -> new ArrayList<>()) - .add(uniqueKeys.get(e.getKey())); + // Best table for all uk is the table contains all uk columns + // and every uk contains all partition columns of this table + final Map>> bestTableUkMap = findBestTableForAllUk(ukAllTableMap, + uniqueKeys, + primaryKey, + schemaName, + primaryTableName, + executionContext); + + if (bestTableUkMap.isEmpty()) { + for (Map.Entry> e : ukAllTableMap.entrySet()) { + List tableNames = e.getValue(); + List uniqueKey = uniqueKeys.get(e.getKey()); + boolean isPrimary = uniqueKey.containsAll(primaryKey) && primaryKey.containsAll(uniqueKey); + + // PK must be searched on primary table + String ukTargetTable = isPrimary ? primaryTableName : + getUkTargetTable(schemaName, primaryTableName, uniqueKey, tableNames, executionContext); + tableUkMap.computeIfAbsent(ukTargetTable.toUpperCase(), k -> new ArrayList<>()) + .add(uniqueKeys.get(e.getKey())); + } + } else { + tableUkMap.putAll(bestTableUkMap); } return tableUkMap; } + /** + * @param ukAllTableMap map[uk index, tables contains this uk] + * @param uniqueKeys map[uk index, columns of this uk] + */ + private static @NotNull Map>> findBestTableForAllUk( + Map> ukAllTableMap, + List> uniqueKeys, + List primaryKey, + String schemaName, + String primaryTableName, + ExecutionContext ec) { + final Map>> bestTableUkMap = new HashMap<>(); + final Set pkSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + pkSet.addAll(primaryKey); + + final SchemaManager sm = ec.getSchemaManager(schemaName); + + final Optional> bestTableCandidates = ukAllTableMap + .entrySet() + .stream() + // skip primary key + .filter(e -> !(uniqueKeys.get(e.getKey()).containsAll(primaryKey) + && pkSet.containsAll(uniqueKeys.get(e.getKey())))) + .map(e -> e.getValue() + .stream() + // exclude unpublished gsi + .filter(tableName -> tableName.equalsIgnoreCase(primaryTableName) + || GlobalIndexMeta.isPublished(ec, sm.getTable(tableName))) + .collect(Collectors.toList())) + // exclude empty table candidates list + .filter(candidates -> !candidates.isEmpty()) + .findFirst(); + + if (bestTableCandidates.isPresent()) { + final TddlRuleManager rm = OptimizerContext.getContext(schemaName).getRuleManager(); + + for (String bestTable : bestTableCandidates.get()) { + boolean bestForAllUk = true; + final List> ukList = new ArrayList<>(); + + for (Map.Entry> e : ukAllTableMap.entrySet()) { + final Set ukTableNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + ukTableNames.addAll(e.getValue()); + final Set ukColumnSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + ukColumnSet.addAll(uniqueKeys.get(e.getKey())); + + final boolean isPrimary = ukColumnSet.containsAll(pkSet) && pkSet.containsAll(ukColumnSet); + + if (isPrimary) { + // PK must be searched on primary table + continue; + } + + if (!ukTableNames.contains(bestTable) + || !ukColumnSet.containsAll(rm.getSharedColumns(bestTable))) { + bestForAllUk = false; + break; + } + + ukList.add(uniqueKeys.get(e.getKey())); + } + + if (bestForAllUk) { + bestTableUkMap.put(bestTable.toUpperCase(), ukList); + + // PK must be searched on primary table + bestTableUkMap.computeIfAbsent( + primaryTableName.toUpperCase(), + k -> new ArrayList<>()) + .add(primaryKey); + break; + } + } + } else { + // PK only and PK must be searched on primary table + bestTableUkMap.computeIfAbsent(primaryTableName.toUpperCase(), k -> new ArrayList<>()).add(primaryKey); + } + return bestTableUkMap; + } + private Map> getLocalIndexName(Map>> tableUkMap, String schemaName, ExecutionContext executionContext) { // Get local index name so that we can use FORCE INDEX later @@ -899,29 +992,44 @@ private String getUkTargetTable(String schemaName, String primaryTableName, List List tableNames, ExecutionContext executionContext) { final TddlRuleManager rm = OptimizerContext.getContext(schemaName).getRuleManager(); final SchemaManager sm = executionContext.getSchemaManager(schemaName); - // All table name in tableNames should be in upper case - Set sharedTableNames = tableNames.stream().filter(tableName -> uniqueKey.containsAll( - rm.getSharedColumns(tableName).stream().map(String::toUpperCase).collect(Collectors.toList()))) - .collect(Collectors.toCollection(HashSet::new)); - Set publicTableNames = tableNames.stream().filter( - tableName -> tableName.equalsIgnoreCase(primaryTableName) || GlobalIndexMeta.isPublished(executionContext, - sm.getTable(tableName))).collect(Collectors.toCollection(HashSet::new)); + final Set ukColumnSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + ukColumnSet.addAll(uniqueKey); + + final Set tablesPartitionedByUk = tableNames + .stream() + .filter(tableName -> ukColumnSet.containsAll(rm.getSharedColumns(tableName))) + .collect(Collectors.toCollection(() -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER))); + final Set primaryTableAndPublicGsiNames = tableNames + .stream() + .filter(tableName -> tableName.equalsIgnoreCase(primaryTableName) + || GlobalIndexMeta.isPublished(executionContext, sm.getTable(tableName))) + .collect(Collectors.toCollection(() -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER))); + + // If primary table is partitioned by uk + if (tablesPartitionedByUk.contains(primaryTableName)) { + return primaryTableName; + } // Try to use table whose sharding key is included in this uk first to avoid full table scan, should // improve small batch performance - for (String tableName : publicTableNames) { - if (sharedTableNames.contains(tableName)) { + for (String tableName : primaryTableAndPublicGsiNames) { + if (tablesPartitionedByUk.contains(tableName)) { return tableName; } } - for (String tableName : publicTableNames) { + // If no table partitioned by uk, check primary table contains uk first + if (primaryTableAndPublicGsiNames.contains(primaryTableName)) { + return primaryTableName; + } + + for (String tableName : primaryTableAndPublicGsiNames) { return tableName; } // Only WRITE_ONLY GSI contains this UK for (String tableName : tableNames) { - if (sharedTableNames.contains(tableName)) { + if (tablesPartitionedByUk.contains(tableName)) { return tableName; } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/OptimizeLogicalModifyRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/OptimizeLogicalModifyRule.java index 37323d2e5..b69051545 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/OptimizeLogicalModifyRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/OptimizeLogicalModifyRule.java @@ -64,7 +64,7 @@ public class OptimizeLogicalModifyRule extends RelOptRule { operand(LogicalModify.class, any())); public OptimizeLogicalModifyRule(RelOptRuleOperand operand) { - super(operand, OptimizeLogicalModifyRule.class.getName()); + super(operand, OptimizeLogicalModifyRule.class.getSimpleName()); } @Override diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/OptimizeModifyReturningRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/OptimizeModifyReturningRule.java new file mode 100644 index 000000000..e0c9da9d3 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/OptimizeModifyReturningRule.java @@ -0,0 +1,236 @@ +/* + * 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 com.alibaba.polardbx.optimizer.core.planner.rule; + +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.core.rel.Gather; +import com.alibaba.polardbx.optimizer.core.rel.LogicalModify; +import com.alibaba.polardbx.optimizer.core.rel.LogicalModify.LogicalMultiWriteInfo; +import com.alibaba.polardbx.optimizer.core.rel.LogicalModifyView; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; +import com.alibaba.polardbx.optimizer.core.rel.MergeSort; +import com.alibaba.polardbx.optimizer.utils.RelUtils; +import com.alibaba.polardbx.optimizer.utils.RelUtils.LogicalModifyViewBuilder; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.plan.RelOptRule; +import org.apache.calcite.plan.RelOptRuleCall; +import org.apache.calcite.plan.RelOptRuleOperand; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.Sort; +import org.apache.calcite.rel.logical.LogicalSort; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +import static com.alibaba.polardbx.optimizer.utils.CheckModifyLimitation.checkModifyGsi; + +public abstract class OptimizeModifyReturningRule extends RelOptRule implements LogicalModifyViewBuilder { + + public static final OptimizeModifyReturningRule MODIFY_VIEW = new OptimizeByReturningModifyViewRule(); + public static final OptimizeModifyReturningRule MODIFY_SORT_VIEW = new OptimizeByReturningSortRule(); + public static final OptimizeModifyReturningRule MODIFY_MERGESORT_VIEW = new OptimizeByReturningMergeSortRule(); + + public static final List OPTIMIZE_MODIFY_RETURNING_RULES = ImmutableList.of( + MODIFY_VIEW, + MODIFY_SORT_VIEW, + MODIFY_MERGESORT_VIEW + ); + + public OptimizeModifyReturningRule(RelOptRuleOperand operand, String description) { + super(operand, "OptimizeModifyReturningRule:" + description); + } + + @Override + public boolean matches(RelOptRuleCall call) { + final LogicalModify modify = call.rel(0); + if (modify.isMultiWriteCanBeOptimizedByReturning()) { + return false; + } + + final PlannerContext context = PlannerContext.getPlannerContext(call); + // TODO support optimize modify on broadcast with returning + final boolean modifyGsi = checkModifyGsi(modify, context.getExecutionContext()); + final boolean singleTableModify = (modify.getPrimaryModifyWriters().size() == 1); + + return modify.isDelete() && singleTableModify && modifyGsi; + } + + private static class OptimizeByReturningModifyViewRule extends OptimizeModifyReturningRule { + + public OptimizeByReturningModifyViewRule() { + super(operand(LogicalModify.class, operand(LogicalView.class, none())), "LogicalModify_LogicalView"); + } + + @Override + public void onMatch(RelOptRuleCall call) { + final LogicalModify modify = call.rel(0); + + final LogicalMultiWriteInfo multiWriteInfo = LogicalMultiWriteInfo + .create(false, false) + .setLmvBuilder(this) + .setOptimizeByReturning(true); + modify.setMultiWriteInfo(multiWriteInfo); + call.transformTo(modify); + } + + @Override + public LogicalModifyView buildForPrimary(List bindings) { + final LogicalModify modify = (LogicalModify) bindings.get(0); + final LogicalView lv = (LogicalView) bindings.get(1); + + LogicalModifyView lmv = new LogicalModifyView(lv); + lmv.push(modify); + RelUtils.changeRowType(lmv, modify.getRowType()); + + return lmv; + } + + @Override + public List bindPlan(LogicalModify modify) { + final List bindings = new ArrayList<>(); + // LogicalModify-LogicalView + if (!RelUtils.matchPlan(modify, getOperand(), bindings, null)) { + bindings.clear(); + // LogicalModify-Gather-LogicalView + if (RelUtils.matchPlan(modify, + operand(LogicalModify.class, + operand(Gather.class, + operand(LogicalView.class, none()))), + bindings, null)) { + // Remove Gather + bindings.set(1, bindings.get(2)); + bindings.remove(2); + } else { + // Miss match + return new ArrayList<>(); + } + } + + return bindings; + } + } + + private static @NotNull LogicalMultiWriteInfo checkAndBuildMultiWriteInfo(Sort sort, LogicalView lv, + LogicalModifyViewBuilder lmvBuilder) { + final LogicalMultiWriteInfo multiWriteInfo = LogicalMultiWriteInfo + .create(sort.offset != null, sort.fetch != null); + + // Following cases can use returning no matter how many partitions left after partition pruning + // 1. DELETE with order but no offset and fetch + // 2. LogicalView is single group (with partition hint or equal condition on partition key) + final boolean singleGroup = lv.isSingleGroup(false); + boolean canUseReturning = !sort.withLimit() || singleGroup; + if (canUseReturning) { + if (singleGroup) { + multiWriteInfo.setLmvBuilder(MODIFY_VIEW); + } else { + multiWriteInfo.setLmvBuilder(lmvBuilder); + } + multiWriteInfo.setOptimizeByReturning(true); + } + return multiWriteInfo; + } + + private static class OptimizeByReturningMergeSortRule extends OptimizeModifyReturningRule { + + public OptimizeByReturningMergeSortRule() { + super(operand(LogicalModify.class, operand(MergeSort.class, operand(LogicalView.class, none()))), + "LogicalModify_MergeSort_LogicalView"); + } + + @Override + public void onMatch(RelOptRuleCall call) { + final LogicalModify modify = call.rel(0); + final MergeSort sort = (MergeSort) call.rels[1]; + final LogicalView lv = (LogicalView) call.rels[2]; + + final LogicalMultiWriteInfo multiWriteInfo = checkAndBuildMultiWriteInfo(sort, lv, this); + + modify.setMultiWriteInfo(multiWriteInfo); + call.transformTo(modify); + } + + @Override + public LogicalModifyView buildForPrimary(List bindings) { + final LogicalModify modify = (LogicalModify) bindings.get(0); + final MergeSort sort = (MergeSort) bindings.get(1); + final LogicalView lv = (LogicalView) bindings.get(2); + + LogicalModifyView lmv = new LogicalModifyView(lv); + lmv.push(modify); + RelUtils.changeRowType(lmv, modify.getRowType()); + + return lmv; + } + + @Override + public List bindPlan(LogicalModify modify) { + final List bindings = new ArrayList<>(); + if (RelUtils.matchPlan(modify, getOperand(), bindings, null)) { + return bindings; + } + // Miss match + return new ArrayList<>(); + } + } + + private static class OptimizeByReturningSortRule extends OptimizeModifyReturningRule { + + public OptimizeByReturningSortRule() { + super(operand(LogicalModify.class, operand(LogicalSort.class, operand(LogicalView.class, none()))), + "LogicalModify_LogicalSort_LogicalView"); + } + + @Override + public void onMatch(RelOptRuleCall call) { + final LogicalModify modify = call.rel(0); + final LogicalSort sort = (LogicalSort) call.rels[1]; + final LogicalView lv = (LogicalView) call.rels[2]; + + final LogicalMultiWriteInfo multiWriteInfo = checkAndBuildMultiWriteInfo(sort, lv, MODIFY_MERGESORT_VIEW); + + modify.setMultiWriteInfo(multiWriteInfo); + call.transformTo(modify); + } + + @Override + public LogicalModifyView buildForPrimary(List bindings) { + final LogicalModify modify = (LogicalModify) bindings.get(0); + final LogicalSort sort = (LogicalSort) bindings.get(1); + final LogicalView lv = (LogicalView) bindings.get(2); + + LogicalModifyView lmv = new LogicalModifyView(lv); + lmv.push(modify); + RelUtils.changeRowType(lmv, modify.getRowType()); + + return lmv; + } + + @Override + public List bindPlan(LogicalModify modify) { + final List bindings = new ArrayList<>(); + if (RelUtils.matchPlan(modify, getOperand(), bindings, null)) { + return bindings; + } + // Miss match + return new ArrayList<>(); + } + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PhyPushAggRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PhyPushAggRule.java new file mode 100644 index 000000000..66f26a346 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PhyPushAggRule.java @@ -0,0 +1,158 @@ +package com.alibaba.polardbx.optimizer.core.planner.rule; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.TwoPhaseAggUtil; +import com.alibaba.polardbx.optimizer.core.rel.HashAgg; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; +import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; +import com.alibaba.polardbx.optimizer.core.rel.PhysicalProject; +import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager; +import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; +import com.alibaba.polardbx.optimizer.utils.RelUtils; +import com.alibaba.polardbx.rule.TableRule; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.plan.RelOptRule; +import org.apache.calcite.plan.RelOptRuleCall; +import org.apache.calcite.plan.RelOptRuleOperand; +import org.apache.calcite.plan.RelOptUtil; +import org.apache.calcite.rel.logical.LogicalAggregate; +import org.apache.calcite.rel.rules.ProjectRemoveRule; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class PhyPushAggRule extends RelOptRule { + + public PhyPushAggRule(RelOptRuleOperand operand) { + super(operand, "PhyPushAggRule"); + } + + public static final PhyPushAggRule INSTANCE = new PhyPushAggRule( + operand(HashAgg.class, + operand(LogicalView.class, null, RelOptUtil.NO_COLLATION_AND_DISTRIBUTION, none()))); + + @Override + public boolean matches(RelOptRuleCall call) { + PlannerContext plannerContext = PlannerContext.getPlannerContext(call); + if (!plannerContext.getParamManager().getBoolean(ConnectionParams.ENABLE_PUSH_AGG)) { + return false; + } + if (!plannerContext.getParamManager().getBoolean(ConnectionParams.PREFER_PUSH_AGG)) { + return false; + } + if (call.rels[1] instanceof OSSTableScan) { + return false; + } + HashAgg hashAgg = (HashAgg) call.rels[0]; + if (hashAgg.getGroupSets().size() > 1) { + return false; + } + if (hashAgg.indicator) { + return false; + } + if (CBOUtil.isCheckSum(hashAgg) || CBOUtil.isGroupSets(hashAgg) || CBOUtil.isSingleValue(hashAgg)) { + return false; + } + if (CBOUtil.containUnpushableAgg(hashAgg)) { + return false; + } + + return super.matches(call); + } + + @Override + public void onMatch(RelOptRuleCall call) { + if (((LogicalView) call.rels[1]).isSingleGroup()) { + onMatchSingle(call); + } else { + onMatchNotSingle(call); + } + } + + protected void onMatchSingle(RelOptRuleCall call) { + HashAgg hashAgg = (HashAgg) call.rels[0]; + LogicalView logicalView = (LogicalView) call.rels[1]; + LogicalAggregate aggregate = + LogicalAggregate.create(logicalView.getPushedRelNode(), hashAgg.getGroupSet(), hashAgg.getGroupSets(), + hashAgg.getAggCallList()); + logicalView.push(aggregate); + RelUtils.changeRowType(logicalView, aggregate.getRowType()); + call.transformTo(logicalView); + } + + protected void onMatchNotSingle(RelOptRuleCall call) { + HashAgg hashAgg = (HashAgg) call.rels[0]; + LogicalView logicalView = (LogicalView) call.rels[1]; + + // try full matching first + TddlRuleManager tddlRuleManager = PlannerContext.getPlannerContext(hashAgg).getExecutionContext() + .getSchemaManager(logicalView.getSchemaName()).getTddlRuleManager(); + TableRule rt = tddlRuleManager.getTableRule(logicalView.getShardingTable()); + PartitionInfoManager partitionInfoManager = tddlRuleManager.getPartitionInfoManager(); + final List shardColumns; + if (rt != null) { + shardColumns = rt.getShardColumns(); + } else if (partitionInfoManager.isNewPartDbTable(logicalView.getShardingTable())) { + shardColumns = + partitionInfoManager.getPartitionInfo(logicalView.getShardingTable()).getPartitionColumns(); + } else { + return; + } + + Set shardIndex = new HashSet<>(); + if (CBOPushAggRule.fullMatchSharding(hashAgg, logicalView, shardColumns, shardIndex)) { + LogicalAggregate aggregate = + LogicalAggregate.create(logicalView.getPushedRelNode(), hashAgg.getGroupSet(), hashAgg.getGroupSets(), + hashAgg.getAggCallList()); + logicalView.push(aggregate); + RelUtils.changeRowType(logicalView, aggregate.getRowType()); + call.transformTo(logicalView); + return; + } + + if (!PlannerContext.getPlannerContext(call).getParamManager().getBoolean(ConnectionParams.ENABLE_PARTIAL_AGG)) { + return; + } + // avoid push agg repeatedly + if (logicalView.aggIsPushed()) { + return; + } + TwoPhaseAggUtil.TwoPhaseAggComponent twoPhaseAggComponent = + TwoPhaseAggUtil.splitAggWithDistinct(hashAgg, logicalView, shardIndex); + if (twoPhaseAggComponent == null) { + return; + } + + LogicalAggregate partialAgg = LogicalAggregate.create( + logicalView.getPushedRelNode(), + twoPhaseAggComponent.getPartialAggGroupSet(), + ImmutableList.of(twoPhaseAggComponent.getPartialAggGroupSet()), + twoPhaseAggComponent.getPartialAggCalls()); + logicalView.push(partialAgg); + RelUtils.changeRowType(logicalView, partialAgg.getRowType()); + + HashAgg globalHashAgg = hashAgg.copy( + hashAgg.getTraitSet(), + logicalView, + hashAgg.indicator, + twoPhaseAggComponent.getGlobalAggGroupSet(), + ImmutableList.of(twoPhaseAggComponent.getGlobalAggGroupSet()), + twoPhaseAggComponent.getGlobalAggCalls()); + + PhysicalProject project = new PhysicalProject( + hashAgg.getCluster(), + globalHashAgg.getTraitSet(), + globalHashAgg, + twoPhaseAggComponent.getProjectChildExps(), + hashAgg.getRowType()); + + if (ProjectRemoveRule.isTrivial(project)) { + call.transformTo(globalHashAgg); + } else { + call.transformTo(project); + } + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PhyTwoPhaseAggRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PhyTwoPhaseAggRule.java new file mode 100644 index 000000000..d1044502b --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PhyTwoPhaseAggRule.java @@ -0,0 +1,220 @@ +package com.alibaba.polardbx.optimizer.core.planner.rule; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.TwoPhaseAggUtil; +import com.alibaba.polardbx.optimizer.core.rel.HashAgg; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; +import com.alibaba.polardbx.optimizer.core.rel.PhysicalProject; +import com.alibaba.polardbx.optimizer.core.rel.mpp.ColumnarExchange; +import com.alibaba.polardbx.optimizer.core.rel.mpp.MppExchange; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Maps; +import org.apache.calcite.plan.RelOptRule; +import org.apache.calcite.plan.RelOptRuleCall; +import org.apache.calcite.plan.RelOptRuleOperand; +import org.apache.calcite.rel.AbstractRelNode; +import org.apache.calcite.rel.RelDistribution; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.AggregateCall; +import org.apache.calcite.rel.core.Exchange; +import org.apache.calcite.rel.rules.ProjectRemoveRule; +import org.apache.calcite.rex.RexInputRef; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.runtime.PredicateImpl; +import org.apache.calcite.util.ImmutableBitSet; +import org.apache.calcite.util.mapping.Mapping; +import org.apache.calcite.util.mapping.Mappings; + +import java.util.List; +import java.util.Map; + +public class PhyTwoPhaseAggRule extends RelOptRule { + public PhyTwoPhaseAggRule(RelOptRuleOperand operand, String description) { + super(operand, "PhyTwoPhaseAggRule:" + description); + } + + private static final Predicate PREDICATE = + new PredicateImpl() { + public boolean test(AbstractRelNode node) { + if (node instanceof LogicalView) { + // don't use two phase agg if agg is pushed + return !((LogicalView) node).aggIsPushed(); + } + if ((node instanceof HashAgg)) { + // don't use two phase agg if two phase agg is used + return !(((HashAgg) node).isPartial()); + } + return true; + } + }; + + public static final PhyTwoPhaseAggRule INSTANCE = new PhyTwoPhaseAggRule( + operand(HashAgg.class, + operand(Exchange.class, operand(AbstractRelNode.class, null, PREDICATE, any()))), "COLUMNAR") { + @Override + public boolean matches(RelOptRuleCall call) { + if (!super.matches(call)) { + return false; + } + final HashAgg hashAgg = (HashAgg) call.rels[0]; + final Exchange exchange = (Exchange) call.rels[1]; + return ((!hashAgg.isPartial()) && (exchange.getTraitSet().getCollation().isTop())); + } + + @Override + public void onMatch(RelOptRuleCall call) { + onMatchInstance(call); + } + }; + + public static final PhyTwoPhaseAggRule PROJECT = new PhyTwoPhaseAggRule( + operand(HashAgg.class, + operand(PhysicalProject.class, operand(Exchange.class, any()))), "COLUMNAR_PROJECT") { + @Override + public boolean matches(RelOptRuleCall call) { + if (!super.matches(call)) { + return false; + } + final HashAgg hashAgg = (HashAgg) call.rels[0]; + final Exchange exchange = (Exchange) call.rels[2]; + return ((!hashAgg.isPartial()) && (exchange.getTraitSet().getCollation().isTop())); + } + + @Override + public void onMatch(RelOptRuleCall call) { + onMatchProject(call); + } + }; + + @Override + public boolean matches(RelOptRuleCall call) { + if (!PlannerContext.getPlannerContext(call).getParamManager() + .getBoolean(ConnectionParams.ENABLE_PARTIAL_AGG)) { + return false; + } + if (!PlannerContext.getPlannerContext(call).getParamManager() + .getBoolean(ConnectionParams.PREFER_PARTIAL_AGG)) { + return false; + } + // forbid agg with filter + return !((HashAgg) call.rels[0]).getAggCallList().stream().anyMatch(AggregateCall::hasFilter); + } + + @Override + public void onMatch(RelOptRuleCall call) { + } + + public void onMatchInstance(RelOptRuleCall call) { + final HashAgg hashAgg = (HashAgg) call.rels[0]; + final Exchange exchange = (Exchange) call.rels[1]; + final RelNode relNode = call.rels[2]; + + TwoPhaseAggUtil.TwoPhaseAggComponent twoPhaseAggComponent = TwoPhaseAggUtil.splitAgg(hashAgg); + if (twoPhaseAggComponent == null) { + return; + } + split(call, hashAgg, exchange, relNode, twoPhaseAggComponent); + + } + + public void onMatchProject(RelOptRuleCall call) { + final HashAgg hashAgg = (HashAgg) call.rels[0]; + final PhysicalProject project = (PhysicalProject) call.rels[1]; + final Exchange exchange = (Exchange) call.rels[2]; + + TwoPhaseAggUtil.TwoPhaseAggComponent twoPhaseAggComponent = TwoPhaseAggUtil.splitAgg(hashAgg); + if (twoPhaseAggComponent == null) { + return; + } + + // make sure distribution columns are preserved in project + Map map = Maps.newHashMap(); + for (int i = 0; i < project.getProjects().size(); i++) { + RexNode node = project.getProjects().get(i); + if (node instanceof RexInputRef) { + map.put(((RexInputRef) node).getIndex(), i); + } + } + final Mapping mapping = (Mapping) Mappings.target( + map::get, + exchange.getRowType().getFieldCount(), + project.getRowType().getFieldCount()); + RelDistribution distribution = exchange.getDistribution().apply(mapping); + if (exchange.getDistribution().getType() != distribution.getType()) { + return; + } + PhysicalProject newProject = project.copy(exchange.getInput().getTraitSet(), exchange.getInput(), + project.getProjects(), project.getRowType()); + Exchange newExchange = createExchange(exchange, newProject, distribution); + if (newExchange == null) { + return; + } + + split(call, hashAgg, newExchange, newProject, twoPhaseAggComponent); + } + + private void split(RelOptRuleCall call, + HashAgg hashAgg, + Exchange exchange, + RelNode bottom, + TwoPhaseAggUtil.TwoPhaseAggComponent twoPhaseAggComponent) { + List childExps = twoPhaseAggComponent.getProjectChildExps(); + List globalAggCalls = twoPhaseAggComponent.getGlobalAggCalls(); + ImmutableBitSet globalAggGroupSet = twoPhaseAggComponent.getGlobalAggGroupSet(); + List partialAggCalls = twoPhaseAggComponent.getPartialAggCalls(); + ImmutableBitSet partialAggGroupSet = twoPhaseAggComponent.getPartialAggGroupSet(); + + // make sure distribution columns are preserved in partial agg + Map map = Maps.newHashMap(); + int inputLoc = -1; + for (int i = 0; i < partialAggGroupSet.cardinality(); i++) { + inputLoc = partialAggGroupSet.nextSetBit(inputLoc + 1); + map.put(inputLoc, i); + } + final Mapping mapping = (Mapping) Mappings.target( + map::get, + bottom.getRowType().getFieldCount(), + partialAggGroupSet.cardinality()); + RelDistribution distribution = exchange.getDistribution().apply(mapping); + if (exchange.getDistribution().getType() != distribution.getType()) { + return; + } + + RelNode partialHashAgg = + HashAgg.createPartial(bottom.getTraitSet(), + bottom, + partialAggGroupSet, + hashAgg.getGroupSets(), + partialAggCalls); + + Exchange newExchange = createExchange(exchange, partialHashAgg, distribution); + if (newExchange == null) { + return; + } + + HashAgg globalHashAgg = hashAgg.copy(hashAgg.getTraitSet(), newExchange, hashAgg.indicator, + globalAggGroupSet, ImmutableList.of(globalAggGroupSet), globalAggCalls); + + PhysicalProject project = new PhysicalProject( + hashAgg.getCluster(), globalHashAgg.getTraitSet(), globalHashAgg, childExps, hashAgg.getRowType()); + + if (ProjectRemoveRule.isTrivial(project)) { + call.transformTo(globalHashAgg); + } else { + call.transformTo(project); + } + } + + Exchange createExchange(Exchange oldExchange, RelNode input, RelDistribution distribution) { + if (oldExchange instanceof MppExchange) { + return MppExchange.create(input, distribution); + } + if (oldExchange instanceof ColumnarExchange) { + return ColumnarExchange.create(input, distribution); + } + return null; + } +} + diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/ProjectFoldRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/ProjectFoldRule.java index 7d8ee5ed6..e5e97e5e2 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/ProjectFoldRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/ProjectFoldRule.java @@ -21,7 +21,7 @@ import com.alibaba.polardbx.common.properties.ParamManager; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.function.calc.scalar.filter.Row; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; import com.alibaba.polardbx.optimizer.utils.ExprContextProvider; import com.alibaba.polardbx.optimizer.utils.RexUtils; import org.apache.calcite.plan.RelOptRule; @@ -58,8 +58,14 @@ public void onMatch(RelOptRuleCall call) { Project project = (Project) call.rels[0]; RelNode input = project.getInput(); RexBuilder rb = call.builder().getRexBuilder(); + + ExecutionContext ec = PlannerContext.getPlannerContext(project).getExecutionContext(); + // don't apply this rule if it will be cached + if (CBOUtil.useColPlanCache(ec)) { + return; + } RexConstantFoldShuttle rexConstantFoldShuttle = - new RexConstantFoldShuttle(rb, PlannerContext.getPlannerContext(project).getExecutionContext()); + new RexConstantFoldShuttle(rb, ec); if (project.getProjects() == null) { return; } @@ -75,6 +81,8 @@ public void onMatch(RelOptRuleCall call) { if (!changed) { return; } + // set constant fold flag to avoid cache this plan + PlannerContext.getPlannerContext(project).setHasConstantFold(true); call.transformTo(project.copy(project.getTraitSet(), input, foldedProjects, project.getRowType())); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushAggRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushAggRule.java index be741ae8c..82bf8b98a 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushAggRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushAggRule.java @@ -22,6 +22,10 @@ import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; +import com.alibaba.polardbx.optimizer.core.function.SqlJsonArrayAggFunction; +import com.alibaba.polardbx.optimizer.core.function.SqlJsonArrayGlobalAggFunction; +import com.alibaba.polardbx.optimizer.core.function.SqlJsonObjectAggFunction; +import com.alibaba.polardbx.optimizer.core.function.SqlJsonObjectGlobalAggFunction; import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; import com.alibaba.polardbx.optimizer.core.rel.LogicalView; import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; @@ -89,31 +93,35 @@ public boolean test(LogicalAggregate agg) { @Override public boolean matches(RelOptRuleCall call) { - PlannerContext plannerContext = PlannerContext.getPlannerContext(call); - return plannerContext.getParamManager().getBoolean(ConnectionParams.ENABLE_PUSH_AGG); - } + LogicalAggregate aggregate = (LogicalAggregate) call.rels[0]; + if (aggregate.getGroupSets().size() > 1) { + return false; + } + LogicalView tableScan = (LogicalView) call.rels[1]; - protected boolean containChecksum(LogicalAggregate agg) { - for (AggregateCall call : agg.getAggCallList()) { - if (call.getAggregation().getKind() == SqlKind.CHECK_SUM) { - return true; - } + if (tableScan instanceof OSSTableScan) { + return false; } - return false; - } - protected boolean containChecksumV2(LogicalAggregate agg) { - for (AggregateCall call : agg.getAggCallList()) { - if (call.getAggregation().getKind() == SqlKind.CHECK_SUM_V2) { - return true; - } + if (CBOUtil.isCheckSum(aggregate) || CBOUtil.isSingleValue(aggregate) || CBOUtil.isGroupSets(aggregate)) { + return false; + } + + if (CBOUtil.containUnpushableAgg(aggregate)) { + return false; + } + + if (!shouldPushAgg(tableScan)) { + return false; } - return false; + + PlannerContext plannerContext = PlannerContext.getPlannerContext(call); + return plannerContext.getParamManager().getBoolean(ConnectionParams.ENABLE_PUSH_AGG); } protected boolean shouldPushAgg(LogicalView logicalView) { - int pushAggInputRowCountThreshold = PlannerContext.getPlannerContext(logicalView).getParamManager() - .getInt(ConnectionParams.PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD); + long pushAggInputRowCountThreshold = PlannerContext.getPlannerContext(logicalView).getParamManager() + .getLong(ConnectionParams.PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD); if (logicalView.getCluster().getMetadataQuery().getRowCount(logicalView) > pushAggInputRowCountThreshold) { return false; } @@ -134,41 +142,6 @@ public static boolean onlyOneAccessPath(LogicalView logicalView) { */ public static class PushAggViewRule extends PushAggRule { - @Override - public boolean matches(RelOptRuleCall call) { - LogicalAggregate aggregate = (LogicalAggregate) call.rels[0]; - if (aggregate.getGroupSets().size() > 1) { - return false; - } - LogicalView tableScan = (LogicalView) call.rels[1]; - - if (tableScan instanceof OSSTableScan) { - return false; - } - - if (containChecksum(aggregate)) { - return false; - } - - if (CBOUtil.containUnpushableAgg(aggregate)) { - return false; - } - - if (containChecksumV2(aggregate)) { - return false; - } - - if (!shouldPushAgg(tableScan)) { - return false; - } - - if (isGroupSets(aggregate)) { - return false; - } - - return super.matches(call); - } - public PushAggViewRule() { super( operand(LogicalAggregate.class, operand(LogicalView.class, null, LogicalView.IS_SINGLE_GROUP, none())), @@ -180,12 +153,6 @@ public PushAggViewRule() { */ @Override public void onMatch(RelOptRuleCall call) { - LogicalAggregate aggregate = (LogicalAggregate) call.rels[0]; - for (AggregateCall aggCall : aggregate.getAggCallList()) { - if (aggCall.getAggregation().getKind() == SqlKind.SINGLE_VALUE) { - return; - } - } pushAggToView(call); } } @@ -212,67 +179,16 @@ public PushAggNotSingleGroupViewRule() { "agg_gather"); } - @Override - public boolean matches(RelOptRuleCall call) { - LogicalAggregate aggregate = (LogicalAggregate) call.rels[0]; - if (aggregate.getGroupSets().size() > 1) { - return false; - } - - LogicalView tableScan = (LogicalView) call.rels[1]; - - if (tableScan instanceof OSSTableScan) { - return false; - } - - if (containChecksum(aggregate)) { - return false; - } - - if (CBOUtil.containUnpushableAgg(aggregate)) { - return false; - } - - if (containChecksumV2(aggregate)) { - return false; - } - - if (!shouldPushAgg(tableScan)) { - return false; - } - - if (isGroupSets(aggregate)) { - return false; - } - - return super.matches(call); - } - @Override public void onMatch(RelOptRuleCall call) { - LogicalAggregate aggregate = (LogicalAggregate) call.rels[0]; - LogicalView lv = (LogicalView) call.rels[1]; - - for (AggregateCall aggCall : aggregate.getAggCallList()) { - if (aggCall.getAggregation().getKind() == SqlKind.SINGLE_VALUE) { - return; - } - } - - pushDownAggregate(call, aggregate, lv); + pushDownAggregate(call); } } - protected void pushDownAggregate(RelOptRuleCall call, LogicalAggregate aggregate, LogicalView tableScan) { - // single_value 不下推 - if (aggregate.getAggCallList() != null) { - for (AggregateCall aggCall : aggregate.getAggCallList()) { - if (aggCall != null && aggCall.getAggregation() != null - && aggCall.getAggregation().getKind() == SqlKind.SINGLE_VALUE) { - return; - } - } - } + protected void pushDownAggregate(RelOptRuleCall call) { + LogicalAggregate aggregate = (LogicalAggregate) call.rels[0]; + LogicalView tableScan = (LogicalView) call.rels[1]; + // 1. check if need push down // 2. init push down context // DSqlTableScan @@ -541,6 +457,20 @@ private boolean buildNewAgg(SqlAggFunction function, PushDownAggCtx ctx, int i, ctx.addPushedAggCalls(i, groupConcatAggregateCall); ctx.addPushedToPartitionAggCalls(i, groupConcatAggregateCall); break; + case JSON_OBJECTAGG: + SqlJsonObjectGlobalAggFunction sqlJsonObjectGlobalAggFunction = new SqlJsonObjectGlobalAggFunction(); + AggregateCall newJsonObjectAggCall = ctx.create(sqlJsonObjectGlobalAggFunction); + ctx.addNewAggCalls(i, newJsonObjectAggCall); + ctx.addPushedAggCalls(i, aggCall); + ctx.addPushedToPartitionAggCalls(i, aggCall); + break; + case JSON_ARRAYAGG: + SqlJsonArrayGlobalAggFunction sqlJsonArrayGlobalAggFunction = new SqlJsonArrayGlobalAggFunction(); + AggregateCall newJsonArrayAggCall = ctx.create(sqlJsonArrayGlobalAggFunction); + ctx.addNewAggCalls(i, newJsonArrayAggCall); + ctx.addPushedAggCalls(i, aggCall); + ctx.addPushedToPartitionAggCalls(i, aggCall); + break; default: throw new UnsupportedOperationException( "Unsupported agg function to push down:" + function.getKind().name()); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushFilterRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushFilterRule.java index d534ae138..8735f1137 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushFilterRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushFilterRule.java @@ -103,8 +103,7 @@ public boolean matches(RelOptRuleCall call) { public void onMatch(RelOptRuleCall call) { Filter filter = call.rel(0); LogicalView logicalView = call.rel(1); - PlannerContext context = call.getPlanner().getContext().unwrap(PlannerContext.class); - if (RelUtils.isNotPushLastInsertId(context, filter)) { + if (RelUtils.existLastInsertId(filter)) { return; } if (logicalView instanceof OSSTableScan diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushJoinRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushJoinRule.java index 33c67a636..e63bd23e9 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushJoinRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushJoinRule.java @@ -132,6 +132,7 @@ protected boolean pushable(RelOptRuleCall call, RelNode rel, LogicalView leftVie final PlannerContext plannerContext = PlannerContext.getPlannerContext(join); final Map extraCmds = plannerContext.getExtraCmds(); boolean enableGroupParallelism = plannerContext.getExecutionContext().getGroupParallelism() > 1; + boolean autoCommit = plannerContext.getExecutionContext().isAutoCommit(); SqlKind sqlKind = plannerContext.getSqlKind(); String pushPolicy = null; @@ -169,7 +170,10 @@ protected boolean pushable(RelOptRuleCall call, RelNode rel, LogicalView leftVie if (!rightPartitionInfo.isBroadcastTable()) { if (leftView.getLockMode() != SqlSelect.LockMode.UNDEF || sqlKind.belongsTo(SqlKind.DML)) { if (enableGroupParallelism) { - return false; + boolean allowPushDown = checkIfAllowPushDownBroTblJoin(leftView, sqlKind, autoCommit); + if (!allowPushDown) { + return false; + } } } } @@ -183,7 +187,11 @@ protected boolean pushable(RelOptRuleCall call, RelNode rel, LogicalView leftVie if (!leftPartitionInfo.isBroadcastTable()) { if (rightView.getLockMode() != SqlSelect.LockMode.UNDEF || sqlKind.belongsTo(SqlKind.DML)) { if (enableGroupParallelism) { - return false; +// return false; + boolean allowPushDown = checkIfAllowPushDownBroTblJoin(rightView, sqlKind, autoCommit); + if (!allowPushDown) { + return false; + } } } } @@ -273,6 +281,21 @@ protected boolean pushable(RelOptRuleCall call, RelNode rel, LogicalView leftVie return findShardColumnMatch(rel, rel, lShardColumnRef, rShardColumnRef); } + private static boolean checkIfAllowPushDownBroTblJoin(LogicalView lv, SqlKind sqlKind, + boolean autoCommit) { + boolean allowPushDown = false; + if (lv.getLockMode() != SqlSelect.LockMode.UNDEF) { + allowPushDown = false; + } else { + if (sqlKind == SqlKind.INSERT || sqlKind == SqlKind.REPLACE) { + if (autoCommit) { + allowPushDown = true; + } + } + } + return allowPushDown; + } + protected void tryPushJoin(RelOptRuleCall call, RelNode rel, LogicalView leftView, LogicalView rightView, RexNode joinCondition) { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushModifyRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushModifyRule.java index 18417c6be..1e29ced92 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushModifyRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushModifyRule.java @@ -23,6 +23,7 @@ import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.planner.rule.util.ExecutionStrategy; import com.alibaba.polardbx.optimizer.core.rel.LogicalModify; @@ -30,26 +31,41 @@ import com.alibaba.polardbx.optimizer.core.rel.LogicalRelocate; import com.alibaba.polardbx.optimizer.core.rel.LogicalView; import com.alibaba.polardbx.optimizer.core.rel.MergeSort; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager; +import com.alibaba.polardbx.optimizer.partition.common.PartKeyLevel; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPrunerUtils; import com.alibaba.polardbx.optimizer.utils.CheckModifyLimitation; import com.alibaba.polardbx.optimizer.utils.OptimizerUtils; +import com.alibaba.polardbx.optimizer.utils.PartitionUtils; import com.alibaba.polardbx.optimizer.utils.RelUtils; import com.alibaba.polardbx.rule.TableRule; import org.apache.calcite.plan.RelOptRule; import org.apache.calcite.plan.RelOptRuleCall; import org.apache.calcite.plan.RelOptRuleOperand; +import org.apache.calcite.plan.RelOptTable; +import org.apache.calcite.rel.core.Sort; import org.apache.calcite.rel.core.TableModify; import org.apache.calcite.rel.logical.LogicalSort; +import org.apache.calcite.rex.RexDynamicParam; +import org.apache.calcite.rex.RexUtil; import org.apache.calcite.sql.SqlDelete; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlUpdate; +import org.apache.calcite.util.Pair; import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import static com.alibaba.polardbx.common.properties.ConnectionParams.DML_FORBID_PUSH_DOWN_UPDATE_WITH_SUBQUERY_IN_SET; +import static com.alibaba.polardbx.common.properties.ConnectionParams.DML_PUSH_MODIFY_WITH_SUBQUERY_CONDITION_OF_TARGET; import static com.alibaba.polardbx.optimizer.utils.CheckModifyLimitation.checkModifyBroadcast; import static com.alibaba.polardbx.optimizer.utils.CheckModifyLimitation.checkModifyFkReferenced; import static com.alibaba.polardbx.optimizer.utils.CheckModifyLimitation.checkModifyFkReferencing; import static com.alibaba.polardbx.optimizer.utils.CheckModifyLimitation.checkModifyGsi; -import static com.alibaba.polardbx.optimizer.utils.CheckModifyLimitation.checkOnlineModifyColumnDdl; /** * @author lingce.ldm 2018-01-30 19:36 @@ -65,6 +81,7 @@ public PushModifyRule(RelOptRuleOperand operand, String description) { public static final PushModifyRule VIEW = new PushModifyViewRule(); public static final PushModifyRule MERGESORT = new PushModifyMergeSortRule(); public static final PushModifyRule SORT_VIEW = new PushModifySortRule(); + public static final PushModifyRule OPTIMIZE_MODIFY_TOP_N_RULE = new OptimizeModifyTopNRule(); @Override public boolean matches(RelOptRuleCall call) { @@ -89,7 +106,6 @@ public boolean matches(RelOptRuleCall call) { || checkModifyFkReferencing(modify, context.getExecutionContext())); if (modifyBroadcastTable || checkModifyGsi(modify, context.getExecutionContext()) || modifyScaleoutTable || - (modify.isUpdate() && checkOnlineModifyColumnDdl(modify, context.getExecutionContext())) || CheckModifyLimitation.checkHasLogicalGeneratedColumns(modify, context.getExecutionContext()) || (ec.getParamManager().getBoolean(ConnectionParams.PRIMARY_KEY_CHECK) && modify.isUpdate()) || (ec.foreignKeyChecks() && (containsUpdateFks || containsDeleteFks)) @@ -124,7 +140,10 @@ public void onMatch(RelOptRuleCall call) { TableModify modify = (TableModify) call.rels[0]; LogicalView lv = (LogicalView) call.rels[1]; - if (forbidPushdownForDelete(modify, lv) || forbidPushDownForDeleteOrUpdate(modify)) { + final PlannerContext context = PlannerContext.getPlannerContext(call); + final ExecutionContext ec = context.getExecutionContext(); + + if (forbidPushdownForDelete(modify, lv) || forbidPushDownForDeleteOrUpdate(modify, lv, ec)) { return; } @@ -139,18 +158,19 @@ public void onMatch(RelOptRuleCall call) { private static class PushModifyMergeSortRule extends PushModifyRule { public PushModifyMergeSortRule() { - super(operand(TableModify.class, operand(MergeSort.class, operand(LogicalView.class, none()))), - "TableModify_MergeSort_LogicalView"); + super(operand(LogicalModify.class, operand(MergeSort.class, operand(LogicalView.class, none()))), + "LogicalModify_MergeSort_LogicalView"); } @Override public void onMatch(RelOptRuleCall call) { - TableModify modify = (TableModify) call.rels[0]; + LogicalModify modify = (LogicalModify) call.rels[0]; MergeSort sort = (MergeSort) call.rels[1]; final LogicalView lv = (LogicalView) call.rels[2]; final PlannerContext context = PlannerContext.getPlannerContext(call); + final ExecutionContext ec = context.getExecutionContext(); - if (forbidPushdownForDelete(modify, lv) || forbidPushDownForDeleteOrUpdate(modify)) { + if (forbidPushdownForDelete(modify, lv) || forbidPushDownForDeleteOrUpdate(modify, lv, ec)) { return; } @@ -190,8 +210,9 @@ public void onMatch(RelOptRuleCall call) { LogicalSort sort = (LogicalSort) call.rels[1]; final LogicalView lv = (LogicalView) call.rels[2]; final PlannerContext context = PlannerContext.getPlannerContext(call); + final ExecutionContext ec = context.getExecutionContext(); - if (forbidPushdownForDelete(modify, lv) || forbidPushDownForDeleteOrUpdate(modify)) { + if (forbidPushdownForDelete(modify, lv) || forbidPushDownForDeleteOrUpdate(modify, lv, ec)) { return; } @@ -218,6 +239,91 @@ public void onMatch(RelOptRuleCall call) { } } + private static class OptimizeModifyTopNRule extends PushModifyRule { + + public OptimizeModifyTopNRule() { + super(operand(LogicalModify.class, operand(Sort.class, operand(LogicalView.class, none()))), + "OptimizeModifyTopNRule"); + } + + @Override + public boolean matches(RelOptRuleCall call) { + final LogicalModify modify = call.rel(0); + if (modify.isModifyTopN()) { + return false; + } + return super.matches(call); + } + + @Override + public void onMatch(RelOptRuleCall call) { + final LogicalModify modify = (LogicalModify) call.rels[0]; + final Sort sort = (Sort) call.rels[1]; + final LogicalView lv = (LogicalView) call.rels[2]; + final PlannerContext context = PlannerContext.getPlannerContext(call); + + // check whether modify top n can be optimized by returning + if (sort.offset == null && sort.fetch != null) { + // MySQL only support specify literal value for fetch clause. + // We replace fetch clause with RexDynamicParam in DrdsParameterizeSqlVisitor. + // So that sort.fetch must be a RexDynamicParam, just double check for sure + final boolean parameterizedFetch = sort.fetch instanceof RexDynamicParam; + final boolean multiTableModify = lv.getTableNames().size() > 1; + final boolean singleGroup = lv.isSingleGroup(true); + final boolean notNewPartitionTable = !PartitionUtils.isNewPartShardTable(lv); + + // 1. MySQL does not support multi table update/delete with limit + // 2. No optimization needed for single group update/delete + // 3. Only support new partition table + boolean isModifyTopN = + !(multiTableModify || singleGroup || notNewPartitionTable) && parameterizedFetch; + + final Pair qn = RelUtils.getQualifiedTableName(modify.getTargetTables().get(0)); + + // 4. At least one partition level is partition by and sorted by order by columns in LogicalView + if (isModifyTopN) { + final PartitionInfo partitionInfo = context + .getExecutionContext() + .getSchemaManager(qn.left) + .getTable(qn.right) + .getPartitionInfo(); + + boolean partitionsSortedBySortKeyInLv = false; + final List partColumnNames = new ArrayList<>(); + if (PartitionPrunerUtils.checkPartitionsSortedByPartitionColumns(partitionInfo, + // check first level partition + PartKeyLevel.PARTITION_KEY, + partColumnNames)) { + partitionsSortedBySortKeyInLv |= PartitionUtils.isOrderKeyMatched(lv, partColumnNames); + } + partColumnNames.clear(); + if (PartitionPrunerUtils.checkPartitionsSortedByPartitionColumns(partitionInfo, + // check second level partition + PartKeyLevel.SUBPARTITION_KEY, + partColumnNames)) { + partitionsSortedBySortKeyInLv |= PartitionUtils.isOrderKeyMatched(lv, partColumnNames); + } + + isModifyTopN &= partitionsSortedBySortKeyInLv; + } + + // mark plan can be pushdown and optimized as modify on top n + if (isModifyTopN) { + final List pkColumnNames = + GlobalIndexMeta.getPrimaryKeys(qn.right, qn.left, context.getExecutionContext()); + + modify.setModifyTopNInfo( + LogicalModify.ModifyTopNInfo.create(pkColumnNames, + sort.getChildExps(), + sort.collation, + (RexDynamicParam) sort.fetch)); + + call.transformTo(modify); + } + } + } + } + /** * if there's a correlated subquery in delete, forbid pushing down to DN */ @@ -255,8 +361,11 @@ private static boolean forbidPushdownForDelete(final TableModify modify, Logical /** * Update / Delete limit m,n 时,由于mysql 不支持 limit m,n; 所以禁止下推 + * Update / Delete WHERE 中包含目标表的子查询 时,由于 mysql 不支持, 禁止下推 */ - private static boolean forbidPushDownForDeleteOrUpdate(final TableModify modify) { + private static boolean forbidPushDownForDeleteOrUpdate(final TableModify modify, + final LogicalView lv, + final ExecutionContext ec) { if (modify instanceof LogicalModify && ((LogicalModify) modify).getOriginalSqlNode() != null) { SqlNode originalNode = ((LogicalModify) modify).getOriginalSqlNode(); if (originalNode instanceof SqlDelete && ((SqlDelete) originalNode).getOffset() != null) { @@ -266,6 +375,25 @@ private static boolean forbidPushDownForDeleteOrUpdate(final TableModify modify) return true; } } + + if (!ec.getParamManager().getBoolean(DML_PUSH_MODIFY_WITH_SUBQUERY_CONDITION_OF_TARGET)) { + final List pushdownTableNames = lv.getTableNames(); + final Map tableCountMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + for (String tn : pushdownTableNames) { + tableCountMap.compute(tn, (k, v) -> v == null ? 1 : v + 1); + } + for (RelOptTable t : modify.getTargetTables()) { + if (tableCountMap.get(RelUtils.getQualifiedTableName(t).right) > 1) { + return true; + } + } + } + + if (ec.getParamManager().getBoolean(DML_FORBID_PUSH_DOWN_UPDATE_WITH_SUBQUERY_IN_SET)) { + return modify.getSourceExpressionList() != null && modify.getSourceExpressionList().stream() + .anyMatch(RexUtil::hasSubQuery); + } + return false; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushProjectRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushProjectRule.java index dee74b6fc..335d758f5 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushProjectRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/PushProjectRule.java @@ -151,7 +151,7 @@ public void onMatch(RelOptRuleCall call) { } // 判断是否有需要特殊处理的Project - if (remainProject(project) || RelUtils.isNotPushLastInsertId(context, project)) { + if (remainProject(project) || RelUtils.existLastInsertId(project)) { // 不下压或者构造新的project下压,保留原先的project // if project has subquery with single table && logicalview only possess single table, diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/RuleToUse.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/RuleToUse.java index a0273e14e..df81702b9 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/RuleToUse.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/RuleToUse.java @@ -27,6 +27,7 @@ import com.alibaba.polardbx.optimizer.core.planner.rule.columnar.COLLogicalWindowToHashWindowRule; import com.alibaba.polardbx.optimizer.core.planner.rule.columnar.COLLogicalWindowToSortWindowRule; import com.alibaba.polardbx.optimizer.core.planner.rule.columnar.COLProjectJoinTransposeRule; +import com.alibaba.polardbx.optimizer.core.planner.rule.columnar.COLSortJoinTransposeRule; import com.alibaba.polardbx.optimizer.core.planner.rule.mpp.MPPMaterializedViewConvertRule; import com.alibaba.polardbx.optimizer.core.planner.rule.mpp.MppBKAJoinConvertRule; import com.alibaba.polardbx.optimizer.core.planner.rule.mpp.MppCorrelateConvertRule; @@ -380,6 +381,9 @@ public class RuleToUse { public static final ImmutableList OPTIMIZE_MODIFY = ImmutableList.of( OptimizeLogicalModifyRule.INSTANCE, + OptimizeModifyReturningRule.MODIFY_VIEW, + OptimizeModifyReturningRule.MODIFY_MERGESORT_VIEW, + OptimizeModifyReturningRule.MODIFY_SORT_VIEW, OptimizeLogicalInsertRule.INSTANCE ); @@ -553,7 +557,7 @@ public class RuleToUse { DrdsAggregateJoinTransposeRule.PROJECT_EXTENDED, new COLProjectJoinTransposeRule(3), // Sort Join Transpose - DrdsSortJoinTransposeRule.INSTANCE, + COLSortJoinTransposeRule.INSTANCE, DrdsSortProjectTransposeRule.INSTANCE, // Convert Sort COLLogicalSortToSortRule.INSTANCE, diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/TddlFilterJoinRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/TddlFilterJoinRule.java index 206134834..7730fa5d4 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/TddlFilterJoinRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/TddlFilterJoinRule.java @@ -31,7 +31,7 @@ import org.apache.calcite.rel.core.Join; import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.rel.core.RelFactories; -import org.apache.calcite.rel.logical.LogicalSemiJoin; +import org.apache.calcite.rel.core.SemiJoin; import org.apache.calcite.rel.metadata.RelMdPredicates; import org.apache.calcite.rel.rules.FilterJoinRule; import org.apache.calcite.rel.type.RelDataType; @@ -86,7 +86,7 @@ protected void perform(RelOptRuleCall call, Filter filter, Join join) { * Simplify join type */ JoinRelType joinType = join.getJoinType(); - if (!origAboveFilters.isEmpty() && joinType != JoinRelType.INNER && !(join instanceof LogicalSemiJoin)) { + if (!origAboveFilters.isEmpty() && joinType != JoinRelType.INNER && !(join instanceof SemiJoin)) { joinType = RelOptUtil.simplifyJoin(join, origAboveFilters, joinType); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/TddlPreBushyJoinShallowPushFilterRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/TddlPreBushyJoinShallowPushFilterRule.java index 1acfb1801..b6246abeb 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/TddlPreBushyJoinShallowPushFilterRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/TddlPreBushyJoinShallowPushFilterRule.java @@ -30,7 +30,7 @@ import org.apache.calcite.rel.core.Join; import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.rel.core.RelFactories; -import org.apache.calcite.rel.logical.LogicalSemiJoin; +import org.apache.calcite.rel.core.SemiJoin; import org.apache.calcite.rel.rules.FilterJoinRule; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rex.RexBuilder; @@ -98,7 +98,7 @@ protected void perform(RelOptRuleCall call, Filter filter, Join join) { * Simplify join type */ JoinRelType joinType = join.getJoinType(); - if (!origAboveFilters.isEmpty() && joinType != JoinRelType.INNER && !(join instanceof LogicalSemiJoin)) { + if (!origAboveFilters.isEmpty() && joinType != JoinRelType.INNER && !(join instanceof SemiJoin)) { joinType = RelOptUtil.simplifyJoin(join, origAboveFilters, joinType); } boolean filterPushed = false; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalAggToHashAggRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalAggToHashAggRule.java index 2ef32e6d0..fffc6d45c 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalAggToHashAggRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalAggToHashAggRule.java @@ -19,9 +19,9 @@ import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.optimizer.PlannerContext; -import com.alibaba.polardbx.optimizer.core.planner.rule.CBOPushAggRule; import com.alibaba.polardbx.optimizer.core.planner.rule.implement.LogicalAggToHashAggRule; import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.TwoPhaseAggUtil; import com.alibaba.polardbx.optimizer.core.rel.HashAgg; import com.google.common.collect.ImmutableList; import org.apache.calcite.plan.RelOptRuleCall; @@ -54,11 +54,8 @@ public COLLogicalAggToHashAggRule(String desc) { @Override protected void createHashAgg(RelOptRuleCall call, LogicalAggregate agg, RelNode newInput) { List> implementationList = new ArrayList<>(); - if (tryConvertToPartialAgg(call, agg, newInput)) { - if (PlannerContext.getPlannerContext(agg).getParamManager().getBoolean(ConnectionParams.PARTIAL_AGG_ONLY)) { - return; - } - } + tryConvertToPartialAgg(call, agg, newInput); + ImmutableBitSet groupIndex = agg.getGroupSet(); if (groupIndex.cardinality() == 0) { implementationList.add(Pair.of(RelDistributions.SINGLETON, RelDistributions.SINGLETON)); @@ -98,7 +95,7 @@ protected boolean tryConvertToPartialAgg(RelOptRuleCall call, LogicalAggregate a } // split to two phase agg - CBOPushAggRule.TwoPhaseAggComponent twoPhaseAggComponent = CBOPushAggRule.splitAgg(agg); + TwoPhaseAggUtil.TwoPhaseAggComponent twoPhaseAggComponent = TwoPhaseAggUtil.splitAgg(agg); if (twoPhaseAggComponent == null) { return false; } @@ -167,16 +164,15 @@ protected boolean checkPartialAggPass(Aggregate hashAgg) { return false; } - // no distinct + // no distinct and filter List aggregateCalls = hashAgg.getAggCallList(); for (AggregateCall aggregateCall : aggregateCalls) { if (aggregateCall.isDistinct() || aggregateCall.filterArg > -1) { return false; } - } - - if (plannerContext.getParamManager().getBoolean(ConnectionParams.PARTIAL_AGG_ONLY)) { - return true; + if (aggregateCall.hasFilter()) { + return false; + } } // cardinality good enough diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalSortToSortRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalSortToSortRule.java index f20f4f08d..21529966c 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalSortToSortRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalSortToSortRule.java @@ -16,17 +16,18 @@ package com.alibaba.polardbx.optimizer.core.planner.rule.columnar; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.core.planner.rule.implement.LogicalSortToSortRule; import com.alibaba.polardbx.optimizer.core.planner.rule.mpp.RuleUtils; import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; import com.alibaba.polardbx.optimizer.core.rel.Limit; import com.alibaba.polardbx.optimizer.core.rel.TopN; import org.apache.calcite.plan.RelOptRuleCall; -import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.RelDistributions; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.logical.LogicalSort; -import org.apache.calcite.rex.RexNode; public class COLLogicalSortToSortRule extends LogicalSortToSortRule { public static final COLLogicalSortToSortRule INSTANCE = new COLLogicalSortToSortRule(false, "INSTANCE"); @@ -38,55 +39,62 @@ private COLLogicalSortToSortRule(boolean isTopNRule, String desc) { this.outConvention = CBOUtil.getColConvention(); } + @Override + public boolean matches(RelOptRuleCall call) { + if (isTopNRule) { + return PlannerContext.getPlannerContext(call).getParamManager().getBoolean(ConnectionParams.ENABLE_TOPN); + } + return true; + } + @Override protected void createSort(RelOptRuleCall call, LogicalSort sort) { - RelTraitSet emptyTrait = call.getPlanner().emptyTraitSet(); if (isTopNRule) { - // convert sort to topN - if (sort.withLimit() && sort.withOrderBy()) { - RelNode input = convert(sort.getInput(), - sort.getInput().getTraitSet().replace(outConvention)); - RexNode fetch = RuleUtils.getPartialFetch(sort); - - TopN partialTopN = TopN.create( - emptyTrait.replace(outConvention).replace(sort.getCollation()), - input, sort.getCollation(), null, fetch); - - RelNode ensureNode = convert(partialTopN, - partialTopN.getTraitSet().replace(RelDistributions.SINGLETON)); - - call.transformTo(TopN.create( - emptyTrait - .replace(outConvention) - .replace(RelDistributions.SINGLETON) - .replace(sort.getCollation()), - ensureNode, sort.getCollation(), sort.offset, sort.fetch)); - return; - } else { - return; - } + convertTopN(call, sort); + } else { + convertLimit(call, sort); } + } + + private void convertTopN(RelOptRuleCall call, LogicalSort sort) { + // convert sort to topN + if (sort.withLimit() && sort.withOrderBy()) { + RelNode input = convert(sort.getInput(), call.getPlanner().emptyTraitSet().replace(outConvention)); + + TopN partialTopN = TopN.create( + input.getTraitSet().replace(sort.getCollation()), + input, sort.getCollation(), null, RuleUtils.getPartialFetch(sort)); + RelNode ensureNode = convert(partialTopN, partialTopN.getTraitSet().replace(RelDistributions.SINGLETON)); + + call.transformTo( + TopN.create(ensureNode.getTraitSet(), ensureNode, sort.getCollation(), sort.offset, sort.fetch)); + } + } + + private void convertLimit(RelOptRuleCall call, LogicalSort sort) { RelNode input = - convert(sort.getInput(), emptyTrait.replace(outConvention)); + convert(sort.getInput(), call.getPlanner().emptyTraitSet().replace(outConvention)); final boolean hasOrdering = sort.withOrderBy(); final boolean hasLimit = sort.withLimit(); if (hasOrdering && !hasLimit) { call.transformTo(convert(input, - emptyTrait - .replace(outConvention) + input.getTraitSet() .replace(RelDistributions.SINGLETON) .replace(sort.getCollation()))); return; } + ParamManager pm = PlannerContext.getPlannerContext(call).getParamManager(); + if (!pm.getBoolean(ConnectionParams.ENABLE_LIMIT)) { + return; + } if (hasOrdering) { Limit limit = Limit.create( - emptyTrait.replace(outConvention).replace(RelDistributions.SINGLETON), + sort.getTraitSet().replace(outConvention).replace(RelDistributions.SINGLETON), convert(input, input.getTraitSet() - .replace(outConvention) .replace(RelDistributions.SINGLETON) .replace(sort.getCollation())), sort.offset, sort.fetch); call.transformTo(limit); @@ -96,7 +104,7 @@ protected void createSort(RelOptRuleCall call, LogicalSort sort) { // now sort has no order // one phase limit Limit limit = Limit.create( - emptyTrait.replace(outConvention).replace(RelDistributions.SINGLETON), + sort.getTraitSet().replace(outConvention).replace(RelDistributions.SINGLETON), convert(input, input.getTraitSet() .replace(outConvention) @@ -104,14 +112,17 @@ protected void createSort(RelOptRuleCall call, LogicalSort sort) { call.transformTo(limit); // tow phase limit + if (!pm.getBoolean(ConnectionParams.ENABLE_PARTIAL_LIMIT)) { + return; + } Limit localLimit = Limit.create( - emptyTrait.replace(outConvention), - convert(input, emptyTrait.replace(outConvention)), - sort.offset, - sort.fetch); + input.getTraitSet(), + input, + null, + RuleUtils.getPartialFetch(sort)); Limit globalLimit = Limit.create( - emptyTrait.replace(outConvention).replace(RelDistributions.SINGLETON), - convert(localLimit, emptyTrait.replace(outConvention).replace(RelDistributions.SINGLETON)), + sort.getTraitSet().replace(outConvention).replace(RelDistributions.SINGLETON), + convert(localLimit, localLimit.getTraitSet().replace(RelDistributions.SINGLETON)), sort.offset, sort.fetch); call.transformTo(globalLimit); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalViewConvertRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalViewConvertRule.java index 908ffca09..5ce3d8a73 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalViewConvertRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalViewConvertRule.java @@ -17,6 +17,7 @@ package com.alibaba.polardbx.optimizer.core.planner.rule.columnar; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.druid.util.StringUtils; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.core.planner.rule.implement.LogicalViewConvertRule; @@ -31,7 +32,6 @@ import org.apache.calcite.rel.RelDistributions; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlNode; -import org.eclipse.jetty.util.StringUtil; import java.util.List; @@ -72,7 +72,7 @@ protected void createLogicalview(RelOptRuleCall call, LogicalView logicalView) { return; } String column = columns.get(0); - if (StringUtil.isEmpty(column)) { + if (StringUtils.isEmpty(column)) { basicOssTableScan(call, logicalView); return; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalWindowToHashWindowRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalWindowToHashWindowRule.java index 5f5602590..99a077e91 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalWindowToHashWindowRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLLogicalWindowToHashWindowRule.java @@ -24,6 +24,7 @@ import com.alibaba.polardbx.optimizer.core.rel.HashWindow; import com.google.common.collect.ImmutableList; import org.apache.calcite.plan.RelOptRuleCall; +import org.apache.calcite.rel.RelCollations; import org.apache.calcite.rel.RelDistribution; import org.apache.calcite.rel.RelDistributions; import org.apache.calcite.rel.RelNode; @@ -70,7 +71,8 @@ public void createHashWindow( } for (Pair implementation : implementationList) { HashWindow newWindow = HashWindow.create( - window.getTraitSet().replace(outConvention).replace(implementation.getKey()), + window.getTraitSet().replace(outConvention).replace(implementation.getKey()) + .replace(RelCollations.EMPTY), convert(newInput, newInput.getTraitSet().replace(implementation.getValue())), window.getConstants(), window.groups, diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLSortJoinTransposeRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLSortJoinTransposeRule.java new file mode 100644 index 000000000..ee4bb84b7 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/columnar/COLSortJoinTransposeRule.java @@ -0,0 +1,99 @@ +package com.alibaba.polardbx.optimizer.core.planner.rule.columnar; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.google.common.base.Predicate; +import org.apache.calcite.plan.RelOptRule; +import org.apache.calcite.plan.RelOptRuleCall; +import org.apache.calcite.plan.RelOptRuleOperand; +import org.apache.calcite.rel.RelCollation; +import org.apache.calcite.rel.RelCollationTraitDef; +import org.apache.calcite.rel.RelCollations; +import org.apache.calcite.rel.RelFieldCollation; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.Join; +import org.apache.calcite.rel.core.JoinRelType; +import org.apache.calcite.rel.core.Sort; +import org.apache.calcite.rel.logical.LogicalJoin; +import org.apache.calcite.rel.logical.LogicalSemiJoin; +import org.apache.calcite.rel.logical.LogicalSort; + +public class COLSortJoinTransposeRule extends RelOptRule { + + public static final COLSortJoinTransposeRule INSTANCE = new COLSortJoinTransposeRule( + operand(LogicalSort.class, null, (Predicate) sort -> sort.withLimit(), + operand(LogicalJoin.class, null, + (Predicate) join -> (join instanceof LogicalJoin || join instanceof LogicalSemiJoin) + && (join.getJoinType() == JoinRelType.LEFT || join.getJoinType() == JoinRelType.RIGHT) + && (join.getTraitSet().simplify().getCollation().isTop() + && join.getTraitSet().simplify().getDistribution().isTop()), any())), + "COLSortJoinTransposeRule" + ); + + public COLSortJoinTransposeRule(RelOptRuleOperand operand, String description) { + super(operand, description); + } + + @Override + public boolean matches(RelOptRuleCall call) { + LogicalSort sort = call.rel(0); + if (sort.getSortOptimizationContext().isSortPushed()) { + return false; + } + return PlannerContext.getPlannerContext(call).getParamManager() + .getBoolean(ConnectionParams.ENABLE_SORT_JOIN_TRANSPOSE); + } + + @Override + public void onMatch(RelOptRuleCall call) { + LogicalSort sort = call.rel(0); + final LogicalJoin join = call.rel(1); + + // We create a new sort operator on the corresponding input + final RelNode newLeftInput; + final RelNode newRightInput; + + final int leftWidth = join.getLeft().getRowType().getFieldList().size(); + if (join.getJoinType() == JoinRelType.LEFT) { + for (RelFieldCollation relFieldCollation : sort.getCollation().getFieldCollations()) { + if (relFieldCollation.getFieldIndex() >= leftWidth) { + return; + } + } + RelCollation collationToPush = sort.getCollation(); + collationToPush = RelCollationTraitDef.INSTANCE.canonize(collationToPush); + + newLeftInput = + sort.copy(sort.getTraitSet().replace(collationToPush), + join.getLeft(), collationToPush, null, CBOUtil.calPushDownFetch(sort)); + newRightInput = join.getRight(); + + } else { + for (RelFieldCollation relFieldCollation : sort.getCollation().getFieldCollations()) { + if (relFieldCollation.getFieldIndex() < leftWidth) { + return; + } + } + RelCollation collationToPush = RelCollations.shift(sort.getCollation(), -leftWidth); + collationToPush = RelCollationTraitDef.INSTANCE.canonize(collationToPush); + newRightInput = + sort.copy(sort.getTraitSet().replace(collationToPush), + join.getRight(), + collationToPush, null, CBOUtil.calPushDownFetch(sort)); + newLeftInput = join.getLeft(); + } + + final RelNode joinCopy = + join.copy(join.getTraitSet(), + join.getCondition(), + newLeftInput, + newRightInput, + join.getJoinType(), + join.isSemiJoinDone()); + + LogicalSort limit = sort.copy(sort.getTraitSet(), joinCopy, sort.getCollation(), sort.offset, sort.fetch); + limit.getSortOptimizationContext().setSortPushed(true); + call.transformTo(limit); + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/mpp/MppHashAggConvertRule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/mpp/MppHashAggConvertRule.java index 2d55c5dac..4f02fe01e 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/mpp/MppHashAggConvertRule.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/mpp/MppHashAggConvertRule.java @@ -20,7 +20,7 @@ import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.core.DrdsConvention; import com.alibaba.polardbx.optimizer.core.MppConvention; -import com.alibaba.polardbx.optimizer.core.planner.rule.CBOPushAggRule; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.TwoPhaseAggUtil; import com.alibaba.polardbx.optimizer.core.rel.HashAgg; import com.google.common.collect.ImmutableList; import org.apache.calcite.plan.Convention; @@ -128,7 +128,7 @@ private RelNode tryConvertToPartialAgg(HashAgg hashAgg, RelNode input) { if (!enablePartialAgg) { return null; } - if (!noDistinct(hashAgg)) { + if (!noDistinctOrFilter(hashAgg)) { return null; } @@ -146,7 +146,7 @@ private RelNode tryConvertToPartialAgg(HashAgg hashAgg, RelNode input) { return null; } - CBOPushAggRule.TwoPhaseAggComponent twoPhaseAggComponent = CBOPushAggRule.splitAgg(hashAgg); + TwoPhaseAggUtil.TwoPhaseAggComponent twoPhaseAggComponent = TwoPhaseAggUtil.splitAgg(hashAgg); if (twoPhaseAggComponent == null) { return null; } @@ -197,12 +197,14 @@ private RelNode tryConvertToPartialAgg(HashAgg hashAgg, RelNode input) { } } - private boolean noDistinct(Aggregate hashAgg) { - List aggregateCalls = hashAgg.getAggCallList(); - for (AggregateCall aggregateCall : aggregateCalls) { + private boolean noDistinctOrFilter(Aggregate hashAgg) { + for (AggregateCall aggregateCall : hashAgg.getAggCallList()) { if (aggregateCall.isDistinct() || aggregateCall.filterArg > -1) { return false; } + if (aggregateCall.hasFilter()) { + return false; + } } return true; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/CBOUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/CBOUtil.java index f4e20925c..d7412f935 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/CBOUtil.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/CBOUtil.java @@ -63,6 +63,7 @@ import com.alibaba.polardbx.optimizer.core.planner.rule.PushFilterRule; import com.alibaba.polardbx.optimizer.core.planner.rule.PushProjectRule; import com.alibaba.polardbx.optimizer.core.planner.rule.mpp.RuleUtils; +import com.alibaba.polardbx.optimizer.core.rel.BaseTableOperation; import com.alibaba.polardbx.optimizer.core.rel.CheckBkaJoinRelVisitor; import com.alibaba.polardbx.optimizer.core.rel.Gather; import com.alibaba.polardbx.optimizer.core.rel.LogicalIndexScan; @@ -70,7 +71,6 @@ import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; import com.alibaba.polardbx.optimizer.index.Index; import com.alibaba.polardbx.optimizer.index.IndexUtil; -import com.alibaba.polardbx.optimizer.index.TableScanFinder; import com.alibaba.polardbx.optimizer.planmanager.LogicalViewWithSubqueryFinder; import com.alibaba.polardbx.optimizer.utils.CalciteUtils; import com.alibaba.polardbx.optimizer.utils.PlannerUtils; @@ -106,6 +106,7 @@ import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttleImpl; import org.apache.calcite.rel.RelVisitor; +import org.apache.calcite.rel.core.Aggregate; import org.apache.calcite.rel.core.AggregateCall; import org.apache.calcite.rel.core.Correlate; import org.apache.calcite.rel.core.Join; @@ -122,6 +123,9 @@ import org.apache.calcite.rel.logical.LogicalTableScan; import org.apache.calcite.rel.metadata.RelColumnOrigin; import org.apache.calcite.rel.metadata.RelMetadataQuery; +import org.apache.calcite.rel.rules.FilterAggregateTransposeRule; +import org.apache.calcite.rel.rules.FilterProjectTransposeRule; +import org.apache.calcite.rel.rules.FilterWindowTransposeRule; import org.apache.calcite.rel.rules.JoinProjectTransposeRule; import org.apache.calcite.rel.rules.JoinToMultiJoinRule; import org.apache.calcite.rel.rules.ProjectFilterTransposeRule; @@ -163,6 +167,7 @@ import java.util.Set; import java.util.stream.Collectors; +import static com.alibaba.polardbx.gms.partition.TablePartitionRecord.PARTITION_TABLE_TYPE_COLUMNAR_TABLE; import static com.alibaba.polardbx.gms.partition.TablePartitionRecord.PARTITION_TABLE_TYPE_GSI_TABLE; public class CBOUtil { @@ -711,12 +716,12 @@ public static long getRexParam(RexNode rex, Map param } } } else { - throw new IllegalArgumentException("Invalid RexNode " + rex); + throw new IllegalStateException("Invalid RexNode " + rex); } } else if (rex instanceof RexLiteral) { rs = DataTypes.ULongType.convertFrom(((RexLiteral) rex).getValue()).longValue(); } else { - throw new IllegalArgumentException("Invalid RexNode " + rex); + throw new IllegalStateException("Invalid RexNode " + rex); } return rs; } @@ -729,6 +734,13 @@ public static TableMeta getTableMeta(RelOptTable relOptTable) { return table instanceof TableMeta ? (TableMeta) table : null; } + public static boolean useColPlanCache(ExecutionContext ec) { + if (ec.isUseHint()) { + return false; + } + return ec.isColumnarPlanCache(); + } + public static DrdsViewTable getDrdsViewTable(RelOptTable relOptTable) { if (!(relOptTable instanceof RelOptTableImpl)) { return null; @@ -780,52 +792,6 @@ public RelNode visit(LogicalSort logicalSort) { } } - public static class ColumnarShardFinder extends RelShuttleImpl { - private int maxShard; - - public ColumnarShardFinder() { - this.maxShard = -1; - } - - public Integer getMaxShard() { - return maxShard; - } - - @Override - public RelNode visit(LogicalFilter filter) { - RexUtil.RexSubqueryListFinder finder = new RexUtil.RexSubqueryListFinder(); - filter.getCondition().accept(finder); - for (RexSubQuery subQuery : finder.getSubQueries()) { - subQuery.rel.accept(this); - } - return visitChild(filter, 0, filter.getInput()); - } - - @Override - public RelNode visit(LogicalProject project) { - RexUtil.RexSubqueryListFinder finder = new RexUtil.RexSubqueryListFinder(); - for (RexNode node : project.getProjects()) { - node.accept(finder); - } - for (RexSubQuery subQuery : finder.getSubQueries()) { - subQuery.rel.accept(this); - } - return visitChild(project, 0, project.getInput()); - } - - @Override - public RelNode visit(TableScan scan) { - if (scan instanceof OSSTableScan) { - TableMeta tm = CBOUtil.getTableMeta(scan.getTable()); - int shard = TableTopologyUtil.isShard(tm) ? - tm.getPartitionInfo().getPartitionBy().getPartitions().size() - : -1; - maxShard = Math.max(shard, maxShard); - } - return scan; - } - } - public static RelNode optimizeByPullProject(RelNode input, PlannerContext plannerContext) { if (!plannerContext.getParamManager().getBoolean(ConnectionParams.ENABLE_COLUMNAR_PULL_UP_PROJECT)) { return input; @@ -855,7 +821,6 @@ public static RelNode optimizeByPullProject(RelNode input, PlannerContext planne builder.addGroupEnd(); HepPlanner hepPlanner = new HepPlanner(builder.build(), plannerContext); - hepPlanner.stopOptimizerTrace(); hepPlanner.setRoot(input); return hepPlanner.findBestExp(); } @@ -1237,6 +1202,23 @@ public static RelNode optimizeByOrcImpl(RelNode rel) { return output; } + public static RelNode optimizeByPushFilterImpl(RelNode rel) { + HepProgramBuilder builder = new HepProgramBuilder(); + + // Push filter to TableScan and generate GetPlan. + builder.addGroupBegin(); + // Just make filter closer to TableScan which helps generating Get in XPlan. + builder.addRuleInstance(FilterAggregateTransposeRule.INSTANCE); + builder.addRuleInstance(FilterWindowTransposeRule.INSTANCE); + builder.addRuleInstance(FilterProjectTransposeRule.INSTANCE); + builder.addRuleInstance(FilterMergeRule.INSTANCE); + builder.addGroupEnd(); + HepPlanner planner = new HepPlanner(builder.build()); + planner.stopOptimizerTrace(); + planner.setRoot(rel); + return planner.findBestExp(); + } + public static RelOptCost getCost(ExecutionContext executionContext) { final RelOptCost zero = DrdsRelOptCostImpl.FACTORY.makeZeroCost(); if (!executionContext.getParamManager().getBoolean(ConnectionParams.RECORD_SQL_COST)) { @@ -1274,17 +1256,7 @@ public static RelOptCost getCost(ExecutionContext executionContext) { return cost; } - public static boolean isGroupSets(LogicalAggregate agg) { - for (AggregateCall aggCall : agg.getAggCallList()) { - SqlKind sqlKind = aggCall.getAggregation().getKind(); - if (sqlKind == SqlKind.GROUP_ID || sqlKind == SqlKind.GROUPING || sqlKind == SqlKind.GROUPING_ID) { - return true; - } - } - return agg.getGroupSets().size() > 1; - } - - public static boolean containUnpushableAgg(LogicalAggregate agg) { + public static boolean containUnpushableAgg(Aggregate agg) { if (agg == null) { return false; } @@ -1298,7 +1270,18 @@ public static boolean containUnpushableAgg(LogicalAggregate agg) { if (call.getAggregation().getKind() == SqlKind.FINAL_HYPER_LOGLOG) { return true; } - + if (call.getAggregation().getKind() == SqlKind.JSON_ARRAY_GLOBALAGG) { + return true; + } + if (call.getAggregation().getKind() == SqlKind.JSON_OBJECT_GLOBALAGG) { + return true; + } + if (call.getAggregation().getKind() == SqlKind.CHECK_SUM_V2) { + return true; + } + if (call.hasFilter()) { + return true; + } if (call.getAggregation().getKind() == SqlKind.COUNT) { if (!call.isDistinct()) { if (call.getArgList().size() > 1) { @@ -1310,26 +1293,43 @@ public static boolean containUnpushableAgg(LogicalAggregate agg) { return false; } - public static boolean isCheckSum(LogicalAggregate agg) { + public static boolean isSingleValue(Aggregate agg) { for (AggregateCall aggCall : agg.getAggCallList()) { - SqlKind sqlKind = aggCall.getAggregation().getKind(); - if (sqlKind == SqlKind.CHECK_SUM) { + if (aggCall.getAggregation().getKind() == SqlKind.SINGLE_VALUE) { return true; } } return false; } - public static boolean isCheckSumV2(LogicalAggregate agg) { + public static boolean isCheckSum(Aggregate agg) { for (AggregateCall aggCall : agg.getAggCallList()) { - SqlKind sqlKind = aggCall.getAggregation().getKind(); - if (sqlKind == SqlKind.CHECK_SUM_V2) { + if (aggCall.getAggregation().getKind() == SqlKind.CHECK_SUM) { return true; } } return false; } + public static boolean isCheckSumV2(Aggregate agg) { + for (AggregateCall aggCall : agg.getAggCallList()) { + if (aggCall.getAggregation().getKind() == SqlKind.CHECK_SUM_V2) { + return true; + } + } + return false; + } + + public static boolean isGroupSets(Aggregate agg) { + for (AggregateCall aggCall : agg.getAggCallList()) { + SqlKind sqlKind = aggCall.getAggregation().getKind(); + if (sqlKind == SqlKind.GROUP_ID || sqlKind == SqlKind.GROUPING || sqlKind == SqlKind.GROUPING_ID) { + return true; + } + } + return agg.getGroupSets().size() > 1; + } + public static boolean isColumnarOptimizer(RelNode node) { return PlannerContext.getPlannerContext(node).isUseColumnar(); } @@ -1607,7 +1607,16 @@ public static boolean isOss(ExecutionContext ec, String table) { public static boolean isOss(String schema, String table) { TableMeta tm = OptimizerContext.getContext(schema).getLatestSchemaManager().getTableWithNull(table); - return tm != null && Engine.isFileStore(tm.getEngine()); + return tm != null && (!tm.isColumnar()) && Engine.isFileStore(tm.getEngine()); + } + + + public static boolean isArchiveCCi(String schema, String table) { + TableMeta tm = OptimizerContext.getContext(schema).getLatestSchemaManager().getTableWithNull(table); + if (tm == null || !tm.isColumnar()) { + return false; + } + return tm.isColumnarArchive(); } /** @@ -1629,6 +1638,33 @@ public static boolean planWithColumnar(RelNode input) { return false; } + /** + * assign ColumnarMaxShardCnt + * + * @param input the root of plan + * @param plannerContext context info + */ + public static void assignColumnarMaxShardCnt(RelNode input, PlannerContext plannerContext) { + LogicalViewWithSubqueryFinder logicalViewWithSubqueryFinder = new LogicalViewWithSubqueryFinder(); + input.accept(logicalViewWithSubqueryFinder); + + int maxShard = -1; + for (LogicalView lv : logicalViewWithSubqueryFinder.getResult()) { + if (lv instanceof OSSTableScan) { + TableMeta tm = CBOUtil.getTableMeta(lv.getTable()); + if (tm.isColumnar() || + (Engine.isFileStore(tm.getEngine()) && plannerContext.getParamManager() + .getBoolean(ConnectionParams.ENABLE_OSS_MOCK_COLUMNAR))) { + int shard = TableTopologyUtil.isShard(tm) ? + tm.getPartitionInfo().getPartitionBy().getPartitions().size() + : -1; + maxShard = Math.max(shard, maxShard); + } + } + } + plannerContext.setColumnarMaxShardCnt(maxShard); + } + /** * check whether there is no scan on row-store * @@ -1636,12 +1672,15 @@ public static boolean planWithColumnar(RelNode input) { * @return false if find a non-columnar logicalView */ public static boolean planAllColumnar(RelNode input) { - TableScanFinder tableScanFinder = new TableScanFinder(); - input.accept(tableScanFinder); - for (Pair pair : tableScanFinder.getResult()) { - TableScan tableScan = pair.getValue(); - if (tableScan instanceof OSSTableScan) { - if (((OSSTableScan) tableScan).isColumnarIndex()) { + if (input instanceof BaseTableOperation) { + return false; + } + LogicalViewWithSubqueryFinder logicalViewWithSubqueryFinder = new LogicalViewWithSubqueryFinder(); + input.accept(logicalViewWithSubqueryFinder); + + for (LogicalView lv : logicalViewWithSubqueryFinder.getResult()) { + if (lv instanceof OSSTableScan) { + if (((OSSTableScan) lv).isColumnarIndex()) { continue; } } @@ -1651,6 +1690,9 @@ public static boolean planAllColumnar(RelNode input) { } public static boolean allTablesHaveColumnar(RelNode input, ExecutionContext context) { + if (input instanceof BaseTableOperation) { + return false; + } // find columnar table, use columnar optimizer LogicalViewWithSubqueryFinder logicalViewFinder = new LogicalViewWithSubqueryFinder(); input.accept(logicalViewFinder); @@ -1664,6 +1706,9 @@ public static boolean allTablesHaveColumnar(RelNode input, ExecutionContext cont String schema = lv.getSchemaName(); String table = lv.getTableNames().get(0); + if (!CBOUtil.hasCci(schema, table, context)) { + return false; + } // OSSTableScan will be generated from force index(columnar) or archive table if (lv instanceof OSSTableScan) { TableMeta tm = context.getSchemaManager(schema).getTableWithNull(table); @@ -1688,7 +1733,8 @@ public static boolean allTablesHaveColumnar(RelNode input, ExecutionContext cont return false; } columnarIndexNameList = - AccessPathRule.filterUseIgnoreIndex(schema, columnarIndexNameList, lv.getIndexNode()); + AccessPathRule.filterUseIgnoreIndex(schema, table, columnarIndexNameList, lv.getIndexNode(), + context); } if (lv.getPartitions() != null) { return false; @@ -1724,6 +1770,54 @@ public static boolean isGsi(String schemaName, String tableName) { return false; } + /** + * check whether table has cci + * + * @param schema given schema name + * @param table given table name + * @param context ExecutionContext + * @return true if 1.the table is archive table while ENABLE_OSS_MOCK_COLUMNAR; 2. the table is cci + * 3. the table has cci + */ + public static boolean hasCci(String schema, String table, ExecutionContext context) { + // oss mock columnar + if (CBOUtil.isOss(schema, table)) { + return context.getParamManager().getBoolean(ConnectionParams.ENABLE_OSS_MOCK_COLUMNAR); + } + + TableMeta tm = context.getSchemaManager(schema).getTableWithNull(table); + if (tm == null) { + return false; + } + if (tm.isColumnar()) { + return true; + } + return CollectionUtils.isNotEmpty(GlobalIndexMeta.getColumnarIndexNames(table, schema, context)); + } + + public static boolean isCci(String schemaName, String tableName, TablePartitionAccessor tablePartitionAccessor, + TablesExtAccessor tablesExtAccessor) { + if (StringUtils.isNotBlank(schemaName) && StringUtils.isNotBlank(tableName)) { + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + if (DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { + tablePartitionAccessor.setConnection(metaDbConn); + List partitionRecords = + tablePartitionAccessor.getTablePartitionsByDbNameTbName(schemaName, tableName, false); + return !partitionRecords.isEmpty() + && partitionRecords.get(0).tblType == PARTITION_TABLE_TYPE_COLUMNAR_TABLE; + } else { + tablesExtAccessor.setConnection(metaDbConn); + TablesExtRecord tablesExtRecord = tablesExtAccessor.query(schemaName, tableName, false); + return tablesExtRecord != null && tablesExtRecord.tableType == GsiMetaManager.TableType.COLUMNAR + .getValue(); + } + } catch (Exception e) { + throw new TddlNestableRuntimeException("check table is cci failed!", e); + } + } + return false; + } + /** * check whether the agg can be pushed down or not * diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/ExecutionStrategy.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/ExecutionStrategy.java index b8884d1c7..f0f35b365 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/ExecutionStrategy.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/ExecutionStrategy.java @@ -40,8 +40,10 @@ import java.util.Collection; import java.util.EnumSet; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.TreeMap; import java.util.TreeSet; import java.util.stream.Collectors; @@ -114,8 +116,6 @@ public static ExecutionStrategyResult determineExecutionStrategy(LogicalInsert i final boolean withGsi = !gsiMetas.isEmpty(); final boolean allGsiPublished = GlobalIndexMeta.isAllGsiPublished(gsiMetas, context); - final boolean onlineModifyColumn = TableColumnUtils.isModifying(primaryTable, ec); - // Unique key detail final List> uniqueKeys = GlobalIndexMeta.getUniqueKeys(targetTable, schema, true, tm -> true, ec); final boolean withoutPkAndUk = uniqueKeys.isEmpty() || uniqueKeys.get(0).isEmpty(); @@ -167,10 +167,17 @@ public static ExecutionStrategyResult determineExecutionStrategy(LogicalInsert i if (insert.isUpsert()) { final List updateCols = buildUpdateColumnList(insert); + final Map>> tableUkMapWithoutImplicitPk = + GlobalIndexMeta.getTableUkMapWithoutImplicitPk(targetTable, schema, true, ec, null); + + final TreeMap> partitionKeyMap = + GlobalIndexMeta.getPartitionKeyMap(targetTable, schema, ec); + // If all sharding columns in update list referencing same column in after value // e.g. insert into t1(a,b,c) values (1,2,3) on duplicate key update a=values(a),b=values(b),c=values(c) - final boolean allUpdatedSkRefValue = checkAllUpdatedSkRefAfterValue(updateCols, partitionKeys, insert) - || checkAllUpdatedSkRefBeforeValue(updateCols, partitionKeys, insert); + final boolean allUpdatedSkRefValue = + checkAllUpdatedSkRefAfterValue(updateCols, partitionKeyMap, tableUkMapWithoutImplicitPk, insert) + || checkAllUpdatedSkRefBeforeValue(updateCols, partitionKeys, insert); final boolean modifyPartitionKey = updateCols.stream().anyMatch(partitionKeys::contains) && !withoutPkAndUk && !allUpdatedSkRefValue; @@ -205,8 +212,6 @@ public static ExecutionStrategyResult determineExecutionStrategy(LogicalInsert i } final boolean doMultiWrite = isBroadcast || withGsi || multiWriteForReplication; - // Do not push down when modify column for now - canPush = canPush && !onlineModifyColumn; canPush = canPush && (!primaryKeyCheck || pushablePrimaryKeyCheck); canPush = canPush && (!foreignKeyChecks || pushableFkCheck); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/ForceIndexUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/ForceIndexUtil.java new file mode 100644 index 000000000..b5fdf6da3 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/ForceIndexUtil.java @@ -0,0 +1,636 @@ +package com.alibaba.polardbx.optimizer.core.planner.rule.util; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.IndexMeta; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.core.join.EquiJoinUtils; +import com.alibaba.polardbx.optimizer.core.join.LookupEquiJoinKey; +import com.alibaba.polardbx.optimizer.core.join.LookupPredicate; +import com.alibaba.polardbx.optimizer.core.join.LookupPredicateBuilder; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; +import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; +import com.alibaba.polardbx.optimizer.index.TableScanFinder; +import com.alibaba.polardbx.optimizer.utils.DrdsRexFolder; +import com.clearspring.analytics.util.Lists; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Maps; +import org.apache.calcite.plan.RelOptUtil; +import org.apache.calcite.rel.RelFieldCollation; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.RelShuttleImpl; +import org.apache.calcite.rel.core.Join; +import org.apache.calcite.rel.core.TableScan; +import org.apache.calcite.rel.logical.LogicalFilter; +import org.apache.calcite.rel.logical.LogicalSort; +import org.apache.calcite.rel.metadata.RelColumnOrigin; +import org.apache.calcite.rel.metadata.RelMetadataQuery; +import org.apache.calcite.rex.RexCall; +import org.apache.calcite.rex.RexInputRef; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexUtil; +import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlNodeList; +import org.apache.calcite.util.Util; +import org.apache.commons.collections.CollectionUtils; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; + +public class ForceIndexUtil { + + public static String genAutoForceIndex(LogicalView logicalView) { + TableScan tableScan = getTableScan(logicalView); + if (tableScan == null) { + return null; + } + TableMeta tm = CBOUtil.getTableMeta(tableScan.getTable()); + + // consider bka join column + ImmutableList bkaColumns = null; + if (logicalView.getJoin() != null) { + Join join = logicalView.getJoin(); + List joinKeys = + EquiJoinUtils.buildLookupEquiJoinKeys(join, join.getOuter(), join.getInner(), + (RexCall) join.getCondition(), join.getJoinType()); + LookupPredicate predicate = + new LookupPredicateBuilder(join, logicalView.getColumnOrigins()).build(joinKeys); + ImmutableList.Builder builder = ImmutableList.builder(); + for (int i = 0; i < predicate.size(); i++) { + builder.add(predicate.getColumn(i).getLastName()); + } + bkaColumns = builder.build(); + } + // collect required columns + RequiredUniqueColumnsCollector requiredUniqueColumnsCollector = new RequiredUniqueColumnsCollector( + tableScan, logicalView.getCluster().getMetadataQuery(), bkaColumns); + RequiredColumnsCollector requiredColumnsCollector = new RequiredColumnsCollector( + tableScan, logicalView.getCluster().getMetadataQuery(), bkaColumns); + logicalView.getPushedRelNode().accept(requiredUniqueColumnsCollector); + logicalView.getPushedRelNode().accept(requiredColumnsCollector); + + // get index to be used in force index + return genAutoForceIndex(requiredUniqueColumnsCollector.build(), requiredColumnsCollector.build(), tm); + } + + private static TableScan getTableScan(LogicalView logicalView) { + final ParamManager paramManager = PlannerContext.getPlannerContext(logicalView).getParamManager(); + if (!paramManager.getBoolean(ConnectionParams.ENABLE_AUTO_FORCE_INDEX)) { + return null; + } + + if (logicalView instanceof OSSTableScan) { + return null; + } + + // should contain only one table + if (logicalView.getTableNames().size() != 1) { + return null; + } + // logicalView should have no index hint + RelNode rel = logicalView.getPushedRelNode(); + TableScanFinder tableScanFinder = new TableScanFinder(); + rel.accept(tableScanFinder); + List> tableScans = tableScanFinder.getResult(); + if (tableScans.size() != 1) { + return null; + } + TableScan tableScan = tableScans.get(0).getValue(); + if (hasIndexHint(tableScan)) { + return null; + } + return tableScan; + } + + public static boolean hasIndexHint(TableScan tableScan) { + if (tableScan == null || tableScan.getIndexNode() == null) { + return false; + } + if (tableScan.getIndexNode() instanceof SqlNodeList) { + SqlNodeList sqlNodeList = (SqlNodeList) tableScan.getIndexNode(); + if (sqlNodeList.size() == 0) { + return false; + } + } + return true; + } + + private static String genAutoForceIndex(RequiredUniqueColumns requiredUniqueColumns, + RequiredColumns requiredColumns, + TableMeta tm) { + if (requiredUniqueColumns != null) { + // check pk first + if (requiredUniqueColumns.checkCoverage(tm.getPrimaryIndex())) { + return "PRIMARY"; + } + // check uk next + for (IndexMeta index : tm.getUniqueIndexes(false)) { + if (requiredUniqueColumns.checkCoverage(index)) { + return index.getPhysicalIndexName(); + } + } + } + + if (requiredColumns == null) { + return null; + } + // check common key last + IndexMeta bestIndex = null; + for (IndexMeta index : tm.getIndexes()) { + if (requiredColumns.checkIndexCoverage(index)) { + // get shortest index + if (bestIndex == null || index.getKeyColumns().size() < bestIndex.getKeyColumns().size()) { + bestIndex = index; + } + } + } + return bestIndex == null ? null : bestIndex.getPhysicalIndexName(); + } + + private static class RequiredUniqueColumnsCollector extends RelShuttleImpl { + // columns list used in 'equal' or 'in' + private final List> equalColumnsList; + private final RelMetadataQuery mq; + private final PlannerContext plannerContext; + + public RequiredUniqueColumnsCollector(TableScan tableScan, RelMetadataQuery mq, List bkaColumns) { + this.mq = mq; + this.plannerContext = PlannerContext.getPlannerContext(tableScan); + this.equalColumnsList = Lists.newArrayList(); + if (CollectionUtils.isNotEmpty(bkaColumns)) { + equalColumnsList.add(bkaColumns); + } + } + + @Override + public RelNode visit(LogicalFilter filter) { + super.visit(filter); + try { + List conjunctions = RelOptUtil.conjunctions(filter.getCondition()); + for (RexNode node : conjunctions) { + if (!RexUtil.containsInputRef(node)) { + continue; + } + if (!(node instanceof RexCall)) { + continue; + } + RexCall call = (RexCall) node; + if (call.getOperands().size() != 2) { + continue; + } + RexNode leftRexNode = call.getOperands().get(0); + RexNode rightRexNode = call.getOperands().get(1); + switch (node.getKind()) { + case IN: + if (!(rightRexNode instanceof RexCall)) { + break; + } + if (leftRexNode instanceof RexInputRef && rightRexNode + .isA(SqlKind.ROW)) { + if (DrdsRexFolder.fold(rightRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ImmutableList.of(leftRexNode)); + break; + } + } + if (leftRexNode.isA(SqlKind.ROW) && leftRexNode instanceof RexCall && rightRexNode.isA( + SqlKind.ROW)) { + boolean leftRef = ((RexCall) leftRexNode).getOperands().stream() + .allMatch(x -> x instanceof RexInputRef); + if (leftRef && DrdsRexFolder.fold(rightRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ((RexCall) leftRexNode).getOperands()); + break; + } + } + break; + case EQUALS: + // xx = xx + if (leftRexNode instanceof RexInputRef && rightRexNode instanceof RexInputRef) { + break; + } + // xx = ? + if (leftRexNode instanceof RexInputRef && + DrdsRexFolder.fold(rightRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ImmutableList.of(leftRexNode)); + break; + } + // ? = xx + if (rightRexNode instanceof RexInputRef && + DrdsRexFolder.fold(leftRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ImmutableList.of(rightRexNode)); + break; + } + //(xx,xx)=(?,?) + if (leftRexNode.isA(SqlKind.ROW) && leftRexNode instanceof RexCall + && rightRexNode.isA(SqlKind.ROW) && rightRexNode instanceof RexCall) { + boolean leftRef = ((RexCall) leftRexNode).getOperands().stream() + .allMatch(x -> x instanceof RexInputRef); + boolean rightRef = ((RexCall) rightRexNode).getOperands().stream() + .allMatch(x -> x instanceof RexInputRef); + // (xx,xx)=(xx,xx) + if (leftRef && rightRef) { + break; + } + if (leftRef && DrdsRexFolder.fold(rightRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ((RexCall) leftRexNode).getOperands()); + break; + } + if (rightRef && DrdsRexFolder.fold(leftRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ((RexCall) rightRexNode).getOperands()); + break; + } + } + break; + default: + break; + } + } + return filter; + } catch (Util.FoundOne find) { + return filter; + } + } + + private void addEqualColumnList(RelNode input, List references) { + ImmutableList.Builder builder = ImmutableList.builder(); + for (RexNode rexNode : references) { + if (!(rexNode instanceof RexInputRef)) { + return; + } + RelColumnOrigin relColumnOrigin = + mq.getColumnOrigin(input, ((RexInputRef) rexNode).getIndex()); + if (relColumnOrigin == null) { + return; + } + builder.add(relColumnOrigin.getColumnName()); + } + equalColumnsList.add(builder.build()); + } + + RequiredUniqueColumns build() { + return new RequiredUniqueColumns(equalColumnsList); + } + } + + private static class RequiredUniqueColumns { + // columns list used in 'equal' or 'in' + private final Map> equalColumnsMap; + private int equalColumnSize; + + public RequiredUniqueColumns(List> equalColumnsList) { + this.equalColumnSize = 0; + this.equalColumnsMap = Maps.newHashMap(); + for (List columns : equalColumnsList) { + this.equalColumnsMap.put(columns.get(0), columns); + this.equalColumnSize += columns.size(); + } + } + + /** + * check whether required equal columns can cover current index + * + * @param index index to be checked, must be unique + * @return true if required columns can cover index + */ + private boolean checkCoverage(IndexMeta index) { + if (index == null) { + return false; + } + if (!index.isUniqueIndex() && !index.isPrimaryKeyIndex()) { + return false; + } + List indexColumns = index.getKeyColumns(); + // all columns of unique key must be covered using equal condition + if (indexColumns.size() > equalColumnSize) { + return false; + } + + int loc = 0; + while (loc < indexColumns.size()) { + List equalColumns = equalColumnsMap.getOrDefault((indexColumns.get(loc).getName()), null); + if (equalColumns == null) { + // can't find equal condition on current index column + return false; + } + loc++; + for (int i = 1; i < equalColumns.size(); i++) { + if (loc == indexColumns.size()) { + return true; + } + if (!equalColumns.get(i).equals(indexColumns.get(loc).getName())) { + return false; + } + loc++; + } + } + return loc == indexColumns.size(); + } + } + + private static class RequiredColumnsCollector extends RelShuttleImpl { + // columns list used in 'equal' or 'in' + private final List> equalColumnsList; + // columns used in order by + private List orderByColumns; + private boolean collectSuccess; + private final RelMetadataQuery mq; + private final PlannerContext plannerContext; + + public RequiredColumnsCollector(TableScan tableScan, RelMetadataQuery mq, List bkaColumns) { + this.mq = mq; + this.plannerContext = PlannerContext.getPlannerContext(tableScan); + equalColumnsList = Lists.newArrayList(); + orderByColumns = null; + collectSuccess = true; + if (CollectionUtils.isNotEmpty(bkaColumns)) { + equalColumnsList.add(bkaColumns); + } + } + + @Override + public RelNode visit(LogicalFilter filter) { + super.visit(filter); + // failed already + if (!collectSuccess) { + return filter; + } + // consider filters before sort + if (orderByColumns != null) { + return filter; + } + try { + + List conjunctions = RelOptUtil.conjunctions(filter.getCondition()); + for (RexNode node : conjunctions) { + if (!RexUtil.containsInputRef(node)) { + continue; + } + // only consider searchable filters + if (!node.getKind().belongsTo(SqlKind.SARGABLE)) { + throw Util.FoundOne.NULL; + } + if (!(node instanceof RexCall)) { + throw Util.FoundOne.NULL; + } + RexCall call = (RexCall) node; + switch (node.getKind()) { + case IN: + if (call.getOperands().size() == 2) { + RexNode leftRexNode = call.getOperands().get(0); + RexNode rightRexNode = call.getOperands().get(1); + if (leftRexNode instanceof RexInputRef && rightRexNode instanceof RexCall && rightRexNode + .isA(SqlKind.ROW)) { + if (DrdsRexFolder.fold(rightRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ImmutableList.of(leftRexNode)); + break; + } + } + if (leftRexNode.isA(SqlKind.ROW) && leftRexNode instanceof RexCall && rightRexNode.isA( + SqlKind.ROW)) { + boolean leftRef = ((RexCall) leftRexNode).getOperands().stream() + .allMatch(x -> x instanceof RexInputRef); + if (leftRef && DrdsRexFolder.fold(rightRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ((RexCall) leftRexNode).getOperands()); + break; + } + } + } + throw Util.FoundOne.NULL; + case EQUALS: + if (call.getOperands().size() == 2) { + RexNode leftRexNode = call.getOperands().get(0); + RexNode rightRexNode = call.getOperands().get(1); + // xx = xx + if (leftRexNode instanceof RexInputRef && rightRexNode instanceof RexInputRef) { + break; + } + // xx = ? + if (leftRexNode instanceof RexInputRef && + DrdsRexFolder.fold(rightRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ImmutableList.of(leftRexNode)); + break; + } + // ? = xx + if (rightRexNode instanceof RexInputRef && + DrdsRexFolder.fold(leftRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ImmutableList.of(rightRexNode)); + break; + } + //(xx,xx)=(?,?) + if (leftRexNode.isA(SqlKind.ROW) && rightRexNode.isA(SqlKind.ROW) + && leftRexNode instanceof RexCall && rightRexNode instanceof RexCall) { + boolean leftRef = ((RexCall) leftRexNode).getOperands().stream() + .allMatch(x -> x instanceof RexInputRef); + boolean rightRef = ((RexCall) rightRexNode).getOperands().stream() + .allMatch(x -> x instanceof RexInputRef); + // (xx,xx)=(xx,xx) + if (leftRef && rightRef) { + break; + } + if (leftRef && DrdsRexFolder.fold(rightRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ((RexCall) leftRexNode).getOperands()); + break; + } + if (rightRef && DrdsRexFolder.fold(leftRexNode, plannerContext) != null) { + addEqualColumnList(filter.getInput(), ((RexCall) rightRexNode).getOperands()); + break; + } + } + } + throw Util.FoundOne.NULL; + case IS_NULL: + RexNode rexNode = call.getOperands().get(0); + if (rexNode instanceof RexInputRef) { + RelColumnOrigin relColumnOrigin = + mq.getColumnOrigin(filter.getInput(), ((RexInputRef) rexNode).getIndex()); + if (relColumnOrigin != null) { + equalColumnsList.add(ImmutableList.of(relColumnOrigin.getColumnName())); + break; + } + } + throw Util.FoundOne.NULL; + case NOT_EQUALS: + case LESS_THAN: + case GREATER_THAN: + case GREATER_THAN_OR_EQUAL: + case LESS_THAN_OR_EQUAL: + // reference input columns + if (call.getOperands().size() == 2) { + RexNode leftRexNode = call.getOperands().get(0); + RexNode rightRexNode = call.getOperands().get(1); + if (RexUtil.containsInputRef(leftRexNode) && RexUtil.containsInputRef(rightRexNode)) { + break; + } + } + throw Util.FoundOne.NULL; + case BETWEEN: + default: + throw Util.FoundOne.NULL; + } + } + return filter; + } catch (Util.FoundOne find) { + collectSuccess = false; + return filter; + } + } + + @Override + public RelNode visit(LogicalSort sort) { + super.visit(sort); + try { + if (orderByColumns != null) { + throw Util.FoundOne.NULL; + } + ImmutableList.Builder builder = ImmutableList.builder(); + for (RelFieldCollation relFieldCollation : sort.getCollation().getFieldCollations()) { + RelColumnOrigin relColumnOrigin = + mq.getColumnOrigin(sort.getInput(), relFieldCollation.getFieldIndex()); + if (relColumnOrigin == null) { + throw Util.FoundOne.NULL; + } + builder.add(relColumnOrigin.getColumnName()); + } + orderByColumns = builder.build(); + } catch (Util.FoundOne find) { + collectSuccess = false; + return sort; + } + return sort; + } + + private void addEqualColumnList(RelNode input, List references) { + // todo: check type equal + ImmutableList.Builder builder = ImmutableList.builder(); + for (RexNode rexNode : references) { + if (!(rexNode instanceof RexInputRef)) { + throw Util.FoundOne.NULL; + } + RelColumnOrigin relColumnOrigin = mq.getColumnOrigin(input, ((RexInputRef) rexNode).getIndex()); + if (relColumnOrigin == null) { + throw Util.FoundOne.NULL; + } + builder.add(relColumnOrigin.getColumnName()); + } + equalColumnsList.add(builder.build()); + } + + RequiredColumns build() { + if (!collectSuccess) { + return null; + } + RequiredColumns requiredColumns = new RequiredColumns(equalColumnsList, orderByColumns); + if (!requiredColumns.build()) { + return null; + } + if (requiredColumns.size() == 0) { + return null; + } + return requiredColumns; + } + } + + private static class RequiredColumns { + // columns list used in 'equal' or 'in' + private final List> equalColumnsList; + // columns used in order by + private final List orderByColumns; + private Map> equalColumnsMap; + private int equalColumnSize; + private int totalColumnSize; + + public RequiredColumns(List> equalColumnsList, List orderByColumns) { + this.equalColumnsList = equalColumnsList; + this.orderByColumns = orderByColumns; + equalColumnSize = 0; + totalColumnSize = 0; + } + + private boolean build() { + equalColumnsMap = Maps.newHashMap(); + for (List columns : equalColumnsList) { + if (equalColumnsMap.put(columns.get(0), columns) != null) { + return false; + } + equalColumnSize += columns.size(); + } + if (CollectionUtils.isNotEmpty(orderByColumns)) { + if (equalColumnsMap.containsKey(orderByColumns.get(0))) { + return false; + } + totalColumnSize = orderByColumns.size(); + } + totalColumnSize += equalColumnSize; + return true; + } + + /** + * get equal-condition-column list containing given column. + * + * @param column given column + * @return column set contains given column + */ + List getEqualColumns(String column) { + return equalColumnsMap.getOrDefault(column, null); + } + + public List getOrderByColumns() { + return orderByColumns; + } + + int size() { + return totalColumnSize; + } + + int equalColumnSize() { + return equalColumnSize; + } + + /** + * check whether current index can cover all required columns + * + * @param index index to be checked + * @return true if index can cover all required columns + */ + private boolean checkIndexCoverage(IndexMeta index) { + List indexColumns = index.getKeyColumns(); + // all required columns must be covered + if (indexColumns.size() < size()) { + return false; + } + + int loc = 0; + // cover equal columns + while (loc < equalColumnSize()) { + List equalColumns = getEqualColumns(indexColumns.get(loc).getName()); + if (equalColumns == null) { + // can't find equal condition on current index column + return false; + } + loc++; + for (int i = 1; i < equalColumns.size(); i++) { + if (!equalColumns.get(i).equals(indexColumns.get(loc).getName())) { + return false; + } + loc++; + } + } + + List orderByColumns = getOrderByColumns(); + if (CollectionUtils.isEmpty(orderByColumns)) { + return true; + } + // cover order by column + for (String orderByColumn : orderByColumns) { + if (!orderByColumn.equals(indexColumns.get(loc).getName())) { + return false; + } + loc++; + } + return true; + } + } +} \ No newline at end of file diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/PartitionWiseAssigner.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/PartitionWiseAssigner.java index 7d83cfe2d..9102be15e 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/PartitionWiseAssigner.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/PartitionWiseAssigner.java @@ -119,9 +119,9 @@ public RelNode visit(RelNode other) { // keep partition info of join result as probe side RelNode probeNode = null; if (other instanceof HashJoin) { - probeNode = ((HashJoin) other).getProbeNode(); + probeNode = ((HashJoin) node).getProbeNode(); } else { - probeNode = ((SemiHashJoin) other).getProbeNode(); + probeNode = ((SemiHashJoin) node).getProbeNode(); } partitionWise.put(node.getId(), partitionWise.getOrDefault(probeNode.getId(), true)); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/TwoPhaseAggUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/TwoPhaseAggUtil.java new file mode 100644 index 000000000..5906b216f --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/planner/rule/util/TwoPhaseAggUtil.java @@ -0,0 +1,369 @@ +package com.alibaba.polardbx.optimizer.core.planner.rule.util; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.core.TddlRelDataTypeSystemImpl; +import com.alibaba.polardbx.optimizer.core.TddlTypeFactoryImpl; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; +import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.rel.core.Aggregate; +import org.apache.calcite.rel.core.AggregateCall; +import org.apache.calcite.rel.core.GroupConcatAggregateCall; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexCall; +import org.apache.calcite.rex.RexInputRef; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.SqlAggFunction; +import org.apache.calcite.sql.fun.SqlCheckSumMergeFunction; +import org.apache.calcite.sql.fun.SqlCheckSumV2MergeFunction; +import org.apache.calcite.sql.fun.SqlCountAggFunction; +import org.apache.calcite.sql.fun.SqlFinalHyperloglogFunction; +import org.apache.calcite.sql.fun.SqlPartialHyperloglogFunction; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.fun.SqlSumAggFunction; +import org.apache.calcite.sql.fun.SqlSumEmptyIsZeroAggFunction; +import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.calcite.util.ImmutableBitSet; +import org.apache.calcite.util.ImmutableIntList; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static com.alibaba.polardbx.optimizer.utils.PlannerUtils.canSplitDistinct; +import static com.alibaba.polardbx.optimizer.utils.PlannerUtils.haveAggWithDistinct; + +public class TwoPhaseAggUtil { + + public static class TwoPhaseAggComponent { + + private List projectChildExps; // Upper Project + private List globalAggCalls; // Global Agg + private ImmutableBitSet globalAggGroupSet; + private List partialAggCalls;// Partial Agg + private ImmutableBitSet partialAggGroupSet; + + public TwoPhaseAggComponent(List projectChildExps, + List globalAggCalls, ImmutableBitSet globalAggGroupSet, + List partialAggCalls, ImmutableBitSet partialAggGroupSet) { + this.projectChildExps = projectChildExps; + this.globalAggCalls = globalAggCalls; + this.globalAggGroupSet = globalAggGroupSet; + this.partialAggCalls = partialAggCalls; + this.partialAggGroupSet = partialAggGroupSet; + } + + public List getProjectChildExps() { + return projectChildExps; + } + + public List getGlobalAggCalls() { + return globalAggCalls; + } + + public List getPartialAggCalls() { + return partialAggCalls; + } + + public ImmutableBitSet getGlobalAggGroupSet() { + return globalAggGroupSet; + } + + public ImmutableBitSet getPartialAggGroupSet() { + return partialAggGroupSet; + } + } + + public static TwoPhaseAggComponent splitAggWithDistinct(Aggregate agg, LogicalView logicalView, + Set shardIndex) { + boolean enablePushDownDistinct = PlannerContext.getPlannerContext( + agg).getParamManager().getBoolean(ConnectionParams.ENABLE_PUSHDOWN_DISTINCT); + boolean enableSplitDistinct = false; + if (enablePushDownDistinct && agg.groupSets.size() <= 1 && haveAggWithDistinct( + agg.getAggCallList())) { + enableSplitDistinct = canSplitDistinct(shardIndex, agg); + } + + TwoPhaseAggComponent twoPhaseAggComponent = null; + if (enableSplitDistinct) { + twoPhaseAggComponent = TwoPhaseAggUtil.splitAgg( + agg, logicalView instanceof OSSTableScan, true); + } + + if (twoPhaseAggComponent == null) { + if (haveAggWithDistinct(agg.getAggCallList())) { + return null; + } + + twoPhaseAggComponent = TwoPhaseAggUtil.splitAgg( + agg, logicalView instanceof OSSTableScan, false); + } + return twoPhaseAggComponent; + } + + public static TwoPhaseAggComponent splitAgg(Aggregate agg) { + return splitAgg(agg, true, false); + } + + public static TwoPhaseAggComponent splitAgg(Aggregate agg, boolean canSplitOrcHash, boolean withDistinct) { + TddlTypeFactoryImpl tddlTypeFactory = new TddlTypeFactoryImpl(TddlRelDataTypeSystemImpl.getInstance()); + List childExps = new ArrayList<>(); + final int aggGroupSetCardinality = agg.getGroupSet().cardinality(); + for (int i = 0; i < aggGroupSetCardinality; i++) { + childExps.add(new RexInputRef(i, agg.getRowType().getFieldList().get(i).getType())); + } + + List globalAggCalls = new ArrayList<>(); + List partialAggCalls = new ArrayList<>(); + + for (int i = 0; i < agg.getAggCallList().size(); i++) { + AggregateCall aggCall = agg.getAggCallList().get(i); + boolean isDistinct = aggCall.isDistinct() && withDistinct; + try { + if (isDistinct) { + buildTwoAggCallsWithDistinct( + aggCall, aggGroupSetCardinality, globalAggCalls, partialAggCalls, childExps); + } else { + buildTwoAggCalls( + aggCall, tddlTypeFactory, aggGroupSetCardinality, globalAggCalls, partialAggCalls, childExps, + canSplitOrcHash, agg.getCluster().getRexBuilder()); + } + } catch (UnsupportedOperationException t) { + // ignore + return null; + } + } + return new TwoPhaseAggComponent(childExps, globalAggCalls, + ImmutableBitSet.range(agg.getGroupSet().cardinality()), + partialAggCalls, agg.getGroupSet()); + } + + private static void buildTwoAggCallsWithDistinct(AggregateCall aggCall, + int aggGroupSetCardinality, + List globalAggCalls, + List partialAggCalls, + List childExps) { + SqlAggFunction function = aggCall.getAggregation(); + switch (function.getKind()) { + case COUNT: + SqlSumEmptyIsZeroAggFunction sumAggFunction = new SqlSumEmptyIsZeroAggFunction(); + + AggregateCall sumAggregateCall = AggregateCall.create(sumAggFunction, + false, + aggCall.isApproximate(), + ImmutableList.of(aggGroupSetCardinality + partialAggCalls.size()), + aggCall.filterArg, + aggCall.getType(), + aggCall.getName()); + + globalAggCalls.add(sumAggregateCall); + + childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); + + partialAggCalls.add(aggCall); + break; + case SUM: + AggregateCall newAggCall = + aggCall.copy( + ImmutableIntList.of(aggGroupSetCardinality + partialAggCalls.size()), -1).withDistinct(false); + globalAggCalls.add(newAggCall); + + childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); + + partialAggCalls.add(aggCall); + break; + default: + throw new UnsupportedOperationException(); + } + + } + + private static void buildTwoAggCalls(AggregateCall aggCall, TddlTypeFactoryImpl tddlTypeFactory, + int aggGroupSetCardinality, + List globalAggCalls, List partialAggCalls, + List childExps, + boolean canSplitOrcHash, RexBuilder rexBuilder) { + + SqlAggFunction function = aggCall.getAggregation(); + switch (function.getKind()) { + case COUNT: + SqlSumEmptyIsZeroAggFunction sumAggFunction = new SqlSumEmptyIsZeroAggFunction(); + + AggregateCall sumAggregateCall = AggregateCall.create(sumAggFunction, + aggCall.isDistinct(), + aggCall.isApproximate(), + ImmutableList.of(aggGroupSetCardinality + partialAggCalls.size()), + aggCall.filterArg, + aggCall.getType(), + aggCall.getName()); + + globalAggCalls.add(sumAggregateCall); + + childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); + + if (aggCall.getArgList().size() > 1) { + //make sure the count with one column, not with multi columns + aggCall = aggCall.copy(ImmutableList.of(aggCall.getArgList().get(0)), aggCall.filterArg); + } + + partialAggCalls.add(aggCall); + break; + case AVG: + SqlSumAggFunction partialSumAggFunc = new SqlSumAggFunction(null); + AggregateCall partialSumAggCall = AggregateCall.create(partialSumAggFunc, + aggCall.isDistinct(), + aggCall.isApproximate(), + aggCall.getArgList(), + aggCall.filterArg, + aggCall.getType(), + "partial_sum"); + + AggregateCall globalSumAggCall = + partialSumAggCall.copy(ImmutableIntList.of(aggGroupSetCardinality + partialAggCalls.size()), + -1, + false, + "global_sum"); + + partialAggCalls.add(partialSumAggCall); + + SqlCountAggFunction pushedCountFunc = new SqlCountAggFunction("COUNT"); + AggregateCall partialCountAggCall = AggregateCall.create(pushedCountFunc, + aggCall.isDistinct(), + aggCall.isApproximate(), + aggCall.getArgList(), + aggCall.filterArg, + tddlTypeFactory.createSqlType(SqlTypeName.BIGINT), + "partial_count"); + + AggregateCall globalCountAggCall = AggregateCall.create(partialSumAggFunc, + partialCountAggCall.isDistinct(), + partialCountAggCall.isApproximate(), + ImmutableIntList.of(aggGroupSetCardinality + partialAggCalls.size()), + partialCountAggCall.filterArg, + partialCountAggCall.getType(), + "global_count"); + + partialAggCalls.add(partialCountAggCall); + + RexInputRef partialSumRef = + new RexInputRef(globalSumAggCall.getArgList().get(0), partialSumAggCall.getType()); + RexInputRef partialCountRef = + new RexInputRef(globalCountAggCall.getArgList().get(0), partialCountAggCall.getType()); + + RexCall divide = (RexCall) rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE, + partialSumRef, + partialCountRef); + + RelDataType relDataType = aggCall.getType(); + if (!divide.getType().getSqlTypeName().equals(relDataType.getSqlTypeName())) { + RexNode castNode = rexBuilder.makeCastForConvertlet(relDataType, divide); + childExps.add(castNode); + } else { + childExps.add(divide); + } + + globalAggCalls.add(globalSumAggCall); + globalAggCalls.add(globalCountAggCall); + break; + case MIN: + case MAX: + case SUM: + case BIT_OR: + case BIT_XOR: + case __FIRST_VALUE: + AggregateCall newAggCall = + aggCall.copy(ImmutableIntList.of(aggGroupSetCardinality + partialAggCalls.size()), -1); + globalAggCalls.add(newAggCall); + + childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); + + partialAggCalls.add(aggCall); + break; + case GROUP_CONCAT: + GroupConcatAggregateCall groupConcatAggregateCall = (GroupConcatAggregateCall) aggCall; + if (groupConcatAggregateCall.getOrderList() != null + && groupConcatAggregateCall.getOrderList().size() != 0) { + throw new UnsupportedOperationException(); + } + GroupConcatAggregateCall newGroupConcatAggregateCall = + groupConcatAggregateCall.copy(ImmutableIntList.of(aggGroupSetCardinality + partialAggCalls.size()), + -1, groupConcatAggregateCall.getOrderList()); + globalAggCalls.add(newGroupConcatAggregateCall); + + childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); + + partialAggCalls.add(aggCall); + break; + case HYPER_LOGLOG: + SqlPartialHyperloglogFunction partialHllFunction = new SqlPartialHyperloglogFunction(); + AggregateCall partialHllAggregateCall = AggregateCall.create(partialHllFunction, + aggCall.isDistinct(), + aggCall.isApproximate(), + aggCall.getArgList(), + aggCall.filterArg, + tddlTypeFactory.createSqlType(SqlTypeName.VARBINARY), + "partial_hll"); + + SqlFinalHyperloglogFunction finalHllFunction = new SqlFinalHyperloglogFunction(); + AggregateCall finalHllAggregateCall = AggregateCall.create(finalHllFunction, + aggCall.isDistinct(), + aggCall.isApproximate(), + ImmutableList.of(aggGroupSetCardinality + partialAggCalls.size()), + aggCall.filterArg, + aggCall.getType(), + "final_hll"); + + globalAggCalls.add(finalHllAggregateCall); + + childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), + tddlTypeFactory.createSqlType(SqlTypeName.VARBINARY))); + + partialAggCalls.add(partialHllAggregateCall); + break; + case CHECK_SUM: + if (!canSplitOrcHash) { + throw new UnsupportedOperationException(); + } + SqlCheckSumMergeFunction crcAggFunction = new SqlCheckSumMergeFunction(); + + AggregateCall crcHashAggregateCall = AggregateCall.create(crcAggFunction, + aggCall.isDistinct(), + aggCall.isApproximate(), + ImmutableList.of(aggGroupSetCardinality + partialAggCalls.size()), + aggCall.filterArg, + aggCall.getType(), + aggCall.getName()); + + globalAggCalls.add(crcHashAggregateCall); + + childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); + + partialAggCalls.add(aggCall); + break; + case CHECK_SUM_V2: + if (!canSplitOrcHash) { + throw new UnsupportedOperationException(); + } + SqlCheckSumV2MergeFunction func = new SqlCheckSumV2MergeFunction(); + + AggregateCall call = AggregateCall.create(func, + aggCall.isDistinct(), + aggCall.isApproximate(), + ImmutableList.of(aggGroupSetCardinality + partialAggCalls.size()), + aggCall.filterArg, + aggCall.getType(), + aggCall.getName()); + + globalAggCalls.add(call); + + childExps.add(new RexInputRef(aggGroupSetCardinality + partialAggCalls.size(), aggCall.getType())); + + partialAggCalls.add(aggCall); + break; + default: + throw new UnsupportedOperationException(); + } + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/BuildFinalPlanVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/BuildFinalPlanVisitor.java index d3a20cc2c..a2ee4dd97 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/BuildFinalPlanVisitor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/BuildFinalPlanVisitor.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.optimizer.core.rel; +import com.alibaba.polardbx.common.Engine; import com.alibaba.polardbx.common.jdbc.BytesSql; import com.alibaba.polardbx.common.model.sqljep.Comparative; import com.alibaba.polardbx.common.properties.ConnectionParams; @@ -27,6 +28,8 @@ import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskPlanUtils; import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import com.alibaba.polardbx.optimizer.config.table.IndexMeta; import com.alibaba.polardbx.optimizer.config.table.SchemaManager; import com.alibaba.polardbx.optimizer.config.table.TableColumnUtils; import com.alibaba.polardbx.optimizer.config.table.TableMeta; @@ -41,6 +44,9 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +import groovy.sql.Sql; +import org.apache.calcite.plan.RelOptSchema; +import org.apache.calcite.rel.AbstractRelNode; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttleImpl; import org.apache.calcite.rel.core.TableScan; @@ -51,6 +57,9 @@ import org.apache.calcite.rex.RexDynamicParam; import org.apache.calcite.rex.RexLiteral; import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.SqlDelete; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlIndexHint; import org.apache.calcite.sql.SqlBasicCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlInsert; @@ -63,6 +72,7 @@ import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeFamily; +import org.jetbrains.annotations.NotNull; import java.security.MessageDigest; import java.util.ArrayList; @@ -131,11 +141,20 @@ private RelNode buildSingleTableScan(OptimizerContext oc, LogicalView lv, TddlRu this.sqlTemplate = this.sqlTemplate.accept(visitor); } - replaceTableNameWithQuestionMark(oc.getSchemaName()); - String tableName = lv.getLogicalTableName(); String schemaName = lv.getSchemaName(); + if (sqlTemplate.getKind() == SqlKind.DELETE) { + /** + * non-exist force index delete should be invalidated + */ + final TableMeta tMeta = this.pc.getExecutionContext().getSchemaManager(schemaName).getTable(tableName); + RemoveIndexNodeVisitor removeIndexNodeVisitor = new RemoveIndexNodeVisitor(tMeta); + this.sqlTemplate = this.sqlTemplate.accept(removeIndexNodeVisitor); + } + + replaceTableNameWithQuestionMark(oc.getSchemaName()); + ShardProcessor processor = null; if (!DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { TableRule tableRule = or.getTableRule(tableName); @@ -244,7 +263,7 @@ private RelNode buildNewPlanForInsert(LogicalInsert logicalInsert, ExecutionCont String tableName = logicalInsert.getLogicalTableName(); String schemaName = logicalInsert.getSchemaName(); final TableMeta table = ec.getSchemaManager(schemaName).getTable(tableName); - if (GlobalIndexMeta.hasIndex(tableName, schemaName, ec)) { + if (GlobalIndexMeta.hasGsi(tableName, schemaName, ec)) { return buildLogicalModify(logicalInsert); } @@ -273,7 +292,6 @@ private RelNode buildNewPlanForInsert(LogicalInsert logicalInsert, ExecutionCont } TableMeta tableMeta = pc.getExecutionContext().getSchemaManager(schemaName).getTable(tableName); - // foreign key? if (ec.foreignKeyChecks() && !GeneralUtil.isEmpty(tableMeta.getForeignKeys())) { return buildLogicalModify(logicalInsert); @@ -343,10 +361,9 @@ private RelNode buildNewPlanForInsert(LogicalInsert logicalInsert, ExecutionCont return buildLogicalModify(logicalInsert); } - boolean isColumnMultiWrite = TableColumnUtils.isModifying(schemaName, tableName, ec); // Insert source must be value here if (!buildPlanForScaleOut && (ComplexTaskPlanUtils.isDeleteOnly(tableMeta) && !logicalInsert.isInsertIgnore() - || !ComplexTaskPlanUtils.canWrite(tableMeta)) && !isColumnMultiWrite) { + || !ComplexTaskPlanUtils.canWrite(tableMeta))) { RelNode singleTableInsert = buildSingleTableInsert(logicalInsert, ec); if (singleTableInsert != null) { return singleTableInsert; @@ -396,7 +413,7 @@ public static boolean canBePushDown(RexNode rexNode, boolean withScaleOut) { private RelNode buildNewPlanForUpdateDelete(LogicalModifyView logicalModifyView, ExecutionContext ec) { String tableName = logicalModifyView.getLogicalTableName(); String schemaName = logicalModifyView.getSchemaName(); - if (GlobalIndexMeta.hasIndex(tableName, schemaName, ec)) { + if (GlobalIndexMeta.hasGsi(tableName, schemaName, ec)) { return buildLogicalModifyViewGsi(logicalModifyView); } @@ -408,8 +425,7 @@ private RelNode buildNewPlanForUpdateDelete(LogicalModifyView logicalModifyView, return logicalModifyView; } - boolean isColumnMultiWrite = TableColumnUtils.isModifying(schemaName, tableName, ec); - if (logicalModifyView.isSingleGroup() && !buildPlanForScaleOut && !isColumnMultiWrite) { + if (logicalModifyView.isSingleGroup() && !buildPlanForScaleOut) { OptimizerContext context = OptimizerContext.getContext(schemaName); TddlRuleManager or = context.getRuleManager(); RelNode tableScan = buildSingleTableScan(context, logicalModifyView, or, true); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ColumnarShardProcessor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ColumnarShardProcessor.java index 851377218..e2704108f 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ColumnarShardProcessor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ColumnarShardProcessor.java @@ -28,7 +28,7 @@ public class ColumnarShardProcessor { /** - * 新版列存分区算法,增加兼容性 + * 列存分区算法。保留该方法,兼容旧版本,该接口只能适配一级分区 * * @param partInfo 分区信息 * @param values 一行数据,可能包含多个列 @@ -36,6 +36,14 @@ public class ColumnarShardProcessor { * @return 分区名称 */ public static String shard(PartitionInfo partInfo, List values, ExecutionContext ec) { + return shard(partInfo, values, null, ec); + } + + /** + * 支持二级分区 + */ + public static String shard(PartitionInfo partInfo, List values, List subPartValues, + ExecutionContext ec) { PartTupleRouter router = new PartTupleRouter(partInfo, ec); router.init(); @@ -45,6 +53,11 @@ public static String shard(PartitionInfo partInfo, List values, Executio */ List> valuesOfAllLevelPartCols = new ArrayList<>(); valuesOfAllLevelPartCols.add(values); + + if (subPartValues != null && !subPartValues.isEmpty()) { + valuesOfAllLevelPartCols.add(subPartValues); + } + PhysicalPartitionInfo phyPartInfo = router.routeTuple(valuesOfAllLevelPartCols); return phyPartInfo.getPartName(); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/GsiBackfill.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/GsiBackfill.java index d06cb2989..1d98f90a0 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/GsiBackfill.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/GsiBackfill.java @@ -16,8 +16,10 @@ package com.alibaba.polardbx.optimizer.core.rel; +import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; +import com.alibaba.polardbx.optimizer.core.row.Row; import com.google.common.collect.ImmutableList; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; @@ -39,11 +41,11 @@ public class GsiBackfill extends AbstractRelNode { private List indexNames; // Add one column and backfill one multi clustered index. private List columns; private boolean useChangeSet = false; - private boolean modifyColumn = false; + private boolean onlineModifyColumn = false; private boolean mirrorCopy = false; private List modifyStringColumns; - private Map virtualColumnMap; - private Map backfillColumnMap; + private Map srcCheckColumnMap; + private Map dstCheckColumnMap; public static GsiBackfill createGsiBackfill(String schemaName, String baseTableName, String indexName, ExecutionContext ec) { @@ -115,23 +117,23 @@ public boolean isAddColumnsBackfill() { } public boolean isModifyPartitionKeyCheck() { - return MapUtils.isNotEmpty(virtualColumnMap); + return MapUtils.isNotEmpty(srcCheckColumnMap); } - public Map getVirtualColumnMap() { - return virtualColumnMap; + public Map getSrcCheckColumnMap() { + return srcCheckColumnMap; } - public void setVirtualColumnMap(Map virtualColumnMap) { - this.virtualColumnMap = virtualColumnMap; + public void setSrcCheckColumnMap(Map srcCheckColumnMap) { + this.srcCheckColumnMap = srcCheckColumnMap; } - public Map getBackfillColumnMap() { - return backfillColumnMap; + public Map getDstCheckColumnMap() { + return dstCheckColumnMap; } - public void setBackfillColumnMap(Map backfillColumnMap) { - this.backfillColumnMap = backfillColumnMap; + public void setDstCheckColumnMap(Map dstCheckColumnMap) { + this.dstCheckColumnMap = dstCheckColumnMap; } public boolean isUseChangeSet() { @@ -158,11 +160,12 @@ public void setModifyStringColumns(List modifyStringColumns) { this.modifyStringColumns = modifyStringColumns; } - public void setModifyColumn(boolean modifyColumn) { - this.modifyColumn = modifyColumn; + public void setOnlineModifyColumn(boolean onlineModifyColumn) { + this.onlineModifyColumn = onlineModifyColumn; } - public boolean isModifyColumn() { - return modifyColumn; + public boolean isOnlineModifyColumn() { + return onlineModifyColumn; } + } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/GsiPartitionBackfill.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/GsiPartitionBackfill.java new file mode 100644 index 000000000..e4868f3bf --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/GsiPartitionBackfill.java @@ -0,0 +1,39 @@ +package com.alibaba.polardbx.optimizer.core.rel; + +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; +import org.apache.calcite.plan.RelOptCluster; +import org.apache.calcite.plan.RelTraitSet; + +import java.util.List; + +/** + * Used to backfill data from base table to index table when a secondary global + * index is created. + */ +public class GsiPartitionBackfill extends GsiBackfill { + + public List getPartitionList() { + return partitionList; + } + + public void setPartitionList(List partitionList) { + this.partitionList = partitionList; + } + + private List partitionList = null; + + public static GsiPartitionBackfill createGsiPartitionBackfill(String schemaName, String baseTableName, + String indexName, + ExecutionContext ec) { + final RelOptCluster cluster = SqlConverter.getInstance(schemaName, ec).createRelOptCluster(null); + RelTraitSet traitSet = RelTraitSet.createEmpty(); + return new GsiPartitionBackfill(cluster, traitSet, schemaName, baseTableName, indexName, null); + } + + public GsiPartitionBackfill(RelOptCluster cluster, RelTraitSet traitSet, String schemaName, String baseTableName, + String indexName, List columns) { + super(cluster, traitSet, schemaName, baseTableName, indexName); + } + +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/GsiPkRangeBackfill.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/GsiPkRangeBackfill.java new file mode 100644 index 000000000..f31575719 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/GsiPkRangeBackfill.java @@ -0,0 +1,55 @@ +package com.alibaba.polardbx.optimizer.core.rel; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; +import com.alibaba.polardbx.optimizer.core.row.Row; +import com.google.common.collect.ImmutableList; +import org.apache.calcite.plan.RelOptCluster; +import org.apache.calcite.plan.RelTraitSet; +import org.apache.calcite.rel.AbstractRelNode; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; + +import java.util.List; +import java.util.Map; + +/** + * Used to backfill data from base table to index table when a secondary global + * index is created. + */ +public class GsiPkRangeBackfill extends GsiBackfill { + + private Pair, Map> pkRange = null; + + public int getTotalThreadCount() { + return totalThreadCount; + } + + public void setTotalThreadCount(int totalThreadCount) { + this.totalThreadCount = totalThreadCount; + } + + public int totalThreadCount = 1; + public static GsiPkRangeBackfill createGsiPkRangeBackfill(String schemaName, String baseTableName, String indexName, + ExecutionContext ec) { + final RelOptCluster cluster = SqlConverter.getInstance(schemaName, ec).createRelOptCluster(null); + RelTraitSet traitSet = RelTraitSet.createEmpty(); + return new GsiPkRangeBackfill(cluster, traitSet, schemaName, baseTableName, indexName, null); + } + + public GsiPkRangeBackfill(RelOptCluster cluster, RelTraitSet traitSet, String schemaName, String baseTableName, + String indexName, List columns) { + super(cluster, traitSet, schemaName, baseTableName, indexName); + } + + public Pair, Map> getPkRange() { + return pkRange; + } + + public void setPkRange( + Pair, Map> pkRange) { + this.pkRange = pkRange; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalIndexScan.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalIndexScan.java index 0fa72c3ca..60086b1b0 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalIndexScan.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalIndexScan.java @@ -36,10 +36,12 @@ public LogicalIndexScan(RelOptTable indexTable, TableScan primaryScan, LockMode this.flashback = primaryScan.getFlashback(); } - public LogicalIndexScan(RelNode rel, RelOptTable table, SqlNodeList hints, LockMode lockMode, RexNode flashback) { + public LogicalIndexScan(RelNode rel, RelOptTable table, SqlNodeList hints, LockMode lockMode, RexNode flashback, + boolean aggIsPushed) { super(rel, table, hints, lockMode, null); this.flashback = flashback; this.pushDownOpt.calculateRowType(); + this.pushDownOpt.setAggIsPushed(aggIsPushed); } public LogicalIndexScan(LogicalView logicalView) { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalInsert.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalInsert.java index 24dc29a9d..3cc7dd291 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalInsert.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalInsert.java @@ -25,8 +25,6 @@ import com.alibaba.polardbx.optimizer.config.table.ComplexTaskPlanUtils; import com.alibaba.polardbx.optimizer.config.table.GeneratedColumnUtil; import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; -import com.alibaba.polardbx.optimizer.config.table.TableColumnMeta; -import com.alibaba.polardbx.optimizer.config.table.TableColumnUtils; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; @@ -66,8 +64,6 @@ import org.apache.calcite.rex.RexNode; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; -import org.apache.calcite.util.Pair; -import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.HashMap; @@ -816,7 +812,7 @@ public boolean needConsistency() { String tableName = getLogicalTableName(); TddlRuleManager or = OptimizerContext.getContext(schemaName).getRuleManager(); return or.isBroadCast(tableName) || GlobalIndexMeta - .hasIndex(tableName, schemaName, PlannerContext.getPlannerContext(this).getExecutionContext()); + .hasGsi(tableName, schemaName, PlannerContext.getPlannerContext(this).getExecutionContext()); } public String getLogicalTableName() { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalModify.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalModify.java index 3f8d5b2e1..4b151c24f 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalModify.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalModify.java @@ -19,22 +19,32 @@ import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.core.dialect.DbType; import com.alibaba.polardbx.optimizer.core.rel.dml.DistinctWriter; +import com.alibaba.polardbx.optimizer.utils.RelUtils.LogicalModifyViewBuilder; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import lombok.Data; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptTable; import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.prepare.Prepare; +import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelWriter; import org.apache.calcite.rel.core.TableModify; import org.apache.calcite.rel.externalize.RelDrdsWriter; import org.apache.calcite.rel.logical.LogicalTableModify; +import org.apache.calcite.rex.RexDynamicParam; import org.apache.calcite.rex.RexNode; import org.apache.calcite.sql.OptimizerHint; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.util.Util; import org.apache.calcite.util.mapping.Mapping; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; @@ -77,6 +87,14 @@ public class LogicalModify extends TableModify { private boolean modifyForeignKey = false; + @Getter + @Setter + protected ModifyTopNInfo modifyTopNInfo = ModifyTopNInfo.EMPTY; + + @Getter + @Setter + protected LogicalMultiWriteInfo multiWriteInfo = LogicalMultiWriteInfo.EMPTY; + public LogicalModify(TableModify modify) { this(modify.getCluster(), modify.getTraitSet(), @@ -98,7 +116,10 @@ public LogicalModify(TableModify modify) { modify instanceof LogicalModify ? ((LogicalModify) modify).getPrimaryModifyWriters() : ImmutableList.of(), modify instanceof LogicalModify ? ((LogicalModify) modify).getGsiModifyWriters() : ImmutableList.of(), modify instanceof LogicalModify ? ((LogicalModify) modify).isWithoutPk() : false, - modify instanceof LogicalModify ? ((LogicalModify) modify).isModifyForeignKey() : false); + modify instanceof LogicalModify ? ((LogicalModify) modify).isModifyForeignKey() : false, + modify instanceof LogicalModify ? ((LogicalModify) modify).getModifyTopNInfo() : ModifyTopNInfo.EMPTY, + modify instanceof LogicalModify ? ((LogicalModify) modify).getMultiWriteInfo() : + LogicalMultiWriteInfo.EMPTY); } public LogicalModify(RelOptCluster cluster, RelTraitSet traitSet, RelOptTable table, @@ -137,7 +158,8 @@ public LogicalModify(RelOptCluster cluster, RelTraitSet traitSet, RelOptTable ta List keywords, SqlNodeList hints, OptimizerHint hintContext, TableInfo tableInfo, List extraTargetTables, List extraTargetColumns, List primaryModifyWriters, List gsiModifyWriters, - boolean withoutPk, boolean modifyForeignKey) { + boolean withoutPk, boolean modifyForeignKey, ModifyTopNInfo modifyTopNInfo, + LogicalMultiWriteInfo multiWriteInfo) { super(cluster, traitSet, table, @@ -165,6 +187,8 @@ public LogicalModify(RelOptCluster cluster, RelTraitSet traitSet, RelOptTable ta this.setColumnTargetMappings = new HashMap<>(); this.setColumnSourceMappings = new HashMap<>(); this.setColumnMetas = new HashMap<>(); + this.modifyTopNInfo = modifyTopNInfo; + this.multiWriteInfo = multiWriteInfo; } public List getTableNames() { @@ -217,6 +241,16 @@ public RelWriter explainTermsForDisplay(RelWriter pw) { .map(t -> String.join(".", t.getQualifiedName())) .collect(Collectors.joining(", "))); } + if (isModifyTopN()) { + pw.item("isModifyTopN", true); + } + if (isMultiWriteCanBeOptimizedByReturning()) { + if (this.multiWriteInfo.isOptimizeByReturning()) { + pw.item("optimizeByReturning", true); + } else { + pw.item("canUseReturning", true); + } + } return pw; } @@ -240,7 +274,9 @@ public final RelNode copy(RelTraitSet traitSet, List inputs) { getPrimaryModifyWriters(), getGsiModifyWriters(), isWithoutPk(), - isModifyForeignKey()); + isModifyForeignKey(), + getModifyTopNInfo(), + getMultiWriteInfo()); logicalModify.originalSqlNode = originalSqlNode; logicalModify.evalRowColumnMetas = evalRowColumnMetas; logicalModify.inputToEvalFieldMappings = inputToEvalFieldMappings; @@ -363,4 +399,71 @@ public void setModifyForeignKey(boolean modifyForeignKey) { public boolean isModifyForeignKey() { return this.modifyForeignKey; } + + public boolean isModifyTopN() { + return null != this.modifyTopNInfo && ModifyTopNInfo.EMPTY != this.modifyTopNInfo; + } + + public boolean isMultiWriteCanBeOptimizedByReturning() { + return null != this.multiWriteInfo + && !LogicalMultiWriteInfo.EMPTY.equals(this.multiWriteInfo); + } + + @Data + @RequiredArgsConstructor + public static class ModifyTopNInfo { + public static ModifyTopNInfo EMPTY = new ModifyTopNInfo(); + + private final ImmutableList pkColumnNames; + private final ImmutableList fieldExps; + private final RelCollation collation; + private final RexDynamicParam fetch; + + @Accessors(chain = true) + private boolean optimizeByReturning = false; + + private ModifyTopNInfo() { + this.pkColumnNames = ImmutableList.of(); + this.fieldExps = ImmutableList.of(); + this.collation = null; + this.fetch = null; + } + + public boolean isDesc() { + return getCollation().getFieldCollations().get(0).direction.isDescending(); + } + + public static ModifyTopNInfo create(@NotNull List pkColumnarNames, + @NotNull List fieldExps, + @NotNull RelCollation collation, + @NotNull RexDynamicParam fetch) { + Preconditions.checkArgument(fieldExps.size() == collation.getFieldCollations().size()); + return new ModifyTopNInfo(ImmutableList.copyOf(pkColumnarNames), ImmutableList.copyOf(fieldExps), collation, + fetch); + } + } + + @Data + @RequiredArgsConstructor + public static class LogicalMultiWriteInfo { + public static LogicalMultiWriteInfo EMPTY = new LogicalMultiWriteInfo(); + + private final boolean withOffset; + private final boolean withFetch; + + @Accessors(chain = true) + private LogicalModifyViewBuilder lmvBuilder = null; + + @Accessors(chain = true) + private boolean optimizeByReturning = false; + + private LogicalMultiWriteInfo() { + this.withOffset = false; + this.withFetch = false; + } + + public static LogicalMultiWriteInfo create(boolean withOffset, boolean withFetch) { + return new LogicalMultiWriteInfo(withOffset, withFetch); + } + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalModifyView.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalModifyView.java index 246d7861c..3264dad31 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalModifyView.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalModifyView.java @@ -20,6 +20,7 @@ import com.alibaba.polardbx.common.jdbc.Parameters; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.utils.OptimizerUtils; +import lombok.Getter; import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.TableModify; @@ -36,14 +37,21 @@ * @author lingce.ldm 2018-01-31 13:48 */ public class LogicalModifyView extends LogicalView { + @Getter + private final LogicalModify.ModifyTopNInfo modifyTopNInfo; public LogicalModifyView(LogicalView logicalView) { + this(logicalView, null); + } + + public LogicalModifyView(LogicalView logicalView, LogicalModify.ModifyTopNInfo modifyTopNInfo) { super(logicalView); this.tableNames = logicalView.getTableNames(); this.pushDownOpt = logicalView.getPushDownOpt().copy(this, logicalView.getPushedRelNode()); this.finishShard = logicalView.getFinishShard(); this.hints = logicalView.getHints(); this.hintContext = logicalView.getHintContext(); + this.modifyTopNInfo = modifyTopNInfo; } @Override @@ -99,11 +107,15 @@ public List getInputWithoutCache(ExecutionContext executionContext) { return getInput(executionContext); } + public List getInput(SqlNode sqlTemplate, ExecutionContext executionContext) { + return getInput(sqlTemplate, false, executionContext); + } + /** * getInput with sqlTemplate. Why not cache sqlTemplate: LogicalModifyView * is put into planCache, so sqlTemplate should be recreated. */ - public List getInput(SqlNode sqlTemplate, ExecutionContext executionContext) { + public List getInput(SqlNode sqlTemplate, boolean noMergeGroupNode, ExecutionContext executionContext) { List> params; if (executionContext.getParams() == null) { params = Collections.singletonList(null); @@ -135,7 +147,7 @@ logTbls, getSchemaName(), pruningMap); relNodes.addAll(phyTableModifyBuilder.build(executionContext)); } - if (relNodes.size() > 1 && relNodes.get(0) instanceof PhyTableOperation) { + if (relNodes.size() > 1 && relNodes.get(0) instanceof PhyTableOperation && !noMergeGroupNode) { return mergeGroupNode(relNodes, executionContext); } else { return relNodes; @@ -151,13 +163,14 @@ public TableModify getTableModify() { return this.pushDownOpt.getTableModify(); } - public boolean hasHint() { - return targetTablesHintCache != null && !targetTablesHintCache.isEmpty(); + public boolean optimizeModifyTopNByReturning() { + return null != modifyTopNInfo && modifyTopNInfo.isOptimizeByReturning(); } @Override public LogicalModifyView copy(RelTraitSet traitSet) { - LogicalModifyView logicalModifyView = new LogicalModifyView(this); + LogicalModifyView logicalModifyView = + new LogicalModifyView(this, this.modifyTopNInfo); logicalModifyView.traitSet = traitSet; logicalModifyView.pushDownOpt = pushDownOpt.copy(this, this.getPushedRelNode()); return logicalModifyView; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalView.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalView.java index 3d931ace0..9fcf7d594 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalView.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/LogicalView.java @@ -26,13 +26,14 @@ import com.alibaba.polardbx.common.model.sqljep.Comparative; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.properties.ConnectionProperties; -import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.partition.TablePartitionRecord; import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.gms.util.GroupInfoUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.config.meta.CostModelWeight; @@ -50,6 +51,7 @@ import com.alibaba.polardbx.optimizer.core.join.LookupPredicate; import com.alibaba.polardbx.optimizer.core.join.LookupPredicateBuilder; import com.alibaba.polardbx.optimizer.core.planner.Planner; +import com.alibaba.polardbx.optimizer.core.planner.PostPlanner; import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; import com.alibaba.polardbx.optimizer.core.planner.Xplanner.RelToXPlanConverter; import com.alibaba.polardbx.optimizer.core.planner.Xplanner.RelXPlanOptimizer; @@ -59,6 +61,8 @@ import com.alibaba.polardbx.optimizer.core.planner.rule.SubQueryToSemiJoinRule; import com.alibaba.polardbx.optimizer.core.planner.rule.TddlFilterJoinRule; import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.ForceIndexUtil; +import com.alibaba.polardbx.optimizer.core.rel.util.TargetTableInfo; import com.alibaba.polardbx.optimizer.index.Index; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager; @@ -70,9 +74,11 @@ import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruner; import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPrunerUtils; import com.alibaba.polardbx.optimizer.partition.pruning.PhysicalPartitionInfo; +import com.alibaba.polardbx.optimizer.planmanager.DRDSRelJson; import com.alibaba.polardbx.optimizer.planmanager.DRDSRelJsonReader; import com.alibaba.polardbx.optimizer.rel.rel2sql.TddlRelToSqlConverter; import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; +import com.alibaba.polardbx.optimizer.selectivity.TableScanSelectivityUpperLimitEstimator; import com.alibaba.polardbx.optimizer.sharding.DataNodeChooser; import com.alibaba.polardbx.optimizer.sharding.result.ExtractionResult; import com.alibaba.polardbx.optimizer.sharding.result.RelShardInfo; @@ -94,6 +100,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; import com.googlecode.protobuf.format.JsonFormat; import com.mysql.cj.x.protobuf.PolarxExecPlan; import org.apache.calcite.linq4j.Ord; @@ -127,6 +134,7 @@ import org.apache.calcite.rel.logical.LogicalJoin; import org.apache.calcite.rel.logical.LogicalProject; import org.apache.calcite.rel.logical.LogicalSemiJoin; +import org.apache.calcite.rel.logical.LogicalTableScan; import org.apache.calcite.rel.metadata.RelColumnOrigin; import org.apache.calcite.rel.metadata.RelMetadataQuery; import org.apache.calcite.rel.rel2sql.RelToSqlConverter; @@ -171,6 +179,7 @@ import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -183,6 +192,7 @@ import java.util.stream.Collectors; import static com.alibaba.polardbx.common.exception.code.ErrorCode.ERR_TABLE_EMPTY_WITH_HINT; +import static com.alibaba.polardbx.common.utils.GeneralUtil.formatSampleRate; /** * @author lingce.ldm 2017-07-07 15:01 @@ -254,6 +264,8 @@ public boolean test(LogicalView logicalView) { private RelOptCost selfCost; private List columnOrigins = Lists.newArrayList(); + private boolean isFromForceIndex = false; + /** * for json serialization */ @@ -269,7 +281,14 @@ public LogicalView(RelInput relInput) { this.newPartDbTbl = checkIfNewPartDbTbl(this.tableNames); this.partitions = extractPartitionsFromStrList(relInput.getStringList("partitions")); this.flashback = relInput.getExpression("flashback"); + this.flashbackOperator = relInput.getSqlOperator("flashbackOperator"); isMGetEnabled = relInput.getBoolean("isMGetEnabled", false); + Map xplanMap = (Map) relInput.get("xplan"); + try { + this.XPlan = DRDSRelJson.fromJsonToXPlan(xplanMap); + } catch (InvalidProtocolBufferException e) { + throw new RuntimeException("PLAN EXTERNALIZE TEST error:" + e.getMessage(), e); + } Map pushDownOptParams = (Map) relInput.get("pushDownOpt"); DRDSRelJsonReader drdsRelJsonReader = new DRDSRelJsonReader(relInput.getCluster(), SqlConverter @@ -283,8 +302,7 @@ public LogicalView(RelInput relInput) { PlannerContext.getPlannerContext(relInput.getCluster()).getExecutionContext()); this.rebuildPartRoutingPlanInfo(); } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException("PLAN EXTERNALIZE TEST error:" + e.getMessage()); + throw new RuntimeException("PLAN EXTERNALIZE TEST error:" + e.getMessage(), e); } buildApply(); rebuildOriginColumnNames(); @@ -470,6 +488,8 @@ public RelWriter explainTerms(RelWriter pw) { .itemIf("isMGetEnabled", isMGetEnabled, isMGetEnabled) .item("partitions", convertPartitionsToStrList()) .item("flashback", flashback) + .itemIf("flashbackOperator", flashbackOperator, flashbackOperator != null) + .itemIf("xplan", XPlan, XPlan != null) ; } @@ -637,6 +657,21 @@ public List getPartPrunedResults(ExecutionContext executionCon return resultList; } + @NotNull + public List getCciPartPrunedResults(ExecutionContext executionContext, + PartitionInfo cciPartInfo) { + List resultList = PartitionPruner.pruneCciPartitions(this, executionContext, cciPartInfo); + filterPrunedResultBySelectedPartitions(resultList); + return resultList; + } + + public TargetTableInfo buildTargetTableInfosForPartitionTb(ExecutionContext executionContext) { + List resultList = PartitionPruner.prunePartitions(this, executionContext); + filterPrunedResultBySelectedPartitions(resultList); + TargetTableInfo targetTableInfo = PartitionPrunerUtils.buildTargetTableInfoByPartPrunedResults(resultList); + return targetTableInfo; + } + private void validateSelectedPartitions(boolean isNewPartDb, PartitionInfo partInfo, boolean isJoin) { if (this.partitions != null) { if (!isNewPartDb) { @@ -688,51 +723,57 @@ private void buildPrunedResultByTargetTablesHintCache(List res protected void filterPrunedResultBySelectedPartitions(List resultList) { if (this.partitions != null) { - for (int i = 0; i < resultList.size(); i++) { - PartitionInfo partInfo = resultList.get(i).getPartInfo(); - if (partInfo.getTableType() == PartitionTableType.PARTITION_TABLE - || partInfo.getTableType() == PartitionTableType.GSI_TABLE - || partInfo.getTableType() == PartitionTableType.COLUMNAR_TABLE) { - SqlNodeList partNamesAst = (SqlNodeList) this.partitions; - Set selectedPartPostSet = new HashSet<>(); - for (SqlNode partNameAst : partNamesAst.getList()) { - String partName = ((SqlIdentifier) partNameAst).getLastName(); - PartitionSpec pSpec = partInfo.getPartSpecSearcher().getPartSpecByPartName(partName); - if (pSpec == null) { - throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, - String.format("Unknown partition '%s' in table '%s'", partName, - partInfo.getTableName())); - } - boolean isPhySpec = !pSpec.isLogical(); - if (isPhySpec) { - selectedPartPostSet.add(pSpec.getPhyPartPosition().intValue()); - } else { - if (pSpec.isSpecTemplate()) { - throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, - String.format("Not allowed to select partition by using subpartition template '%s'", - partName, - partInfo.getTableName())); - } + for (PartPrunedResult partPrunedResult : resultList) { + filterBySelectedPartition(partPrunedResult); + } + } + } - List subPartList = pSpec.getSubPartitions(); - for (int j = 0; j < subPartList.size(); j++) { - PartitionSpec subPart = subPartList.get(j); - selectedPartPostSet.add(subPart.getPhyPartPosition().intValue()); - } - } + public void filterBySelectedPartition(PartPrunedResult partPrunedResult) { + if (this.partitions == null) { + return; + } - } - BitSet partSetSelected = - PartitionPrunerUtils.buildPhyPartsBitSetByPhyPartPostSet(partInfo, selectedPartPostSet); - resultList.get(i).getPartBitSet().and(partSetSelected); - } else if (partInfo.getTableType() == PartitionTableType.BROADCAST_TABLE) { - continue; - } else { + PartitionInfo partInfo = partPrunedResult.getPartInfo(); + if (partInfo.getTableType() == PartitionTableType.PARTITION_TABLE + || partInfo.getTableType() == PartitionTableType.GSI_TABLE + || partInfo.getTableType() == PartitionTableType.COLUMNAR_TABLE) { + SqlNodeList partNamesAst = (SqlNodeList) this.partitions; + Set selectedPartPostSet = new HashSet<>(); + for (SqlNode partNameAst : partNamesAst.getList()) { + String partName = ((SqlIdentifier) partNameAst).getLastName(); + PartitionSpec pSpec = partInfo.getPartSpecSearcher().getPartSpecByPartName(partName); + if (pSpec == null || (pSpec.getStatus() != null + && pSpec.getStatus() == TablePartitionRecord.PARTITION_STATUS_PARTITION_OFFLINE)) { throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, - "PARTITION () clause on non partitioned table"); + String.format("Unknown partition '%s' in table '%s'", partName, + partInfo.getTableName())); } - } + boolean isPhySpec = !pSpec.isLogical(); + if (isPhySpec) { + selectedPartPostSet.add(pSpec.getPhyPartPosition().intValue()); + } else { + if (pSpec.isSpecTemplate()) { + throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, + String.format("Not allowed to select partition by using subpartition template '%s'", + pSpec.getTemplateName())); + } + List subPartList = pSpec.getSubPartitions(); + for (PartitionSpec subPart : subPartList) { + selectedPartPostSet.add(subPart.getPhyPartPosition().intValue()); + } + } + + } + BitSet partSetSelected = + PartitionPrunerUtils.buildPhyPartsBitSetByPhyPartPostSet(partInfo, selectedPartPostSet); + partPrunedResult.getPartBitSet().and(partSetSelected); + } else if (partInfo.getTableType() == PartitionTableType.BROADCAST_TABLE) { + return; + } else { + throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, + "PARTITION () clause on non partitioned table"); } } @@ -742,6 +783,30 @@ protected Map>> buildTargetTablesForShardDbTb(Executio List> targetDBs; if (null == comparativeHintCache) { targetDBs = DataNodeChooser.shard(this, forceAllowFullTableScan, executionContext); + if (executionContext.getParamManager().getBoolean(ConnectionParams.BROADCAST_RANDOM_READ_IN_LOGICALVIEW)) { + if (targetDBs.size() == 1 + && targetDBs.get(0).size() == 1 + && !isJoin() + && OptimizerContext.getContext(getSchemaName()).getRuleManager() + .isBroadCast(getLogicalTableName())) { + + final TargetDB targetDB = targetDBs.get(0).get(0); + + if (GroupInfoUtil.isSingleGroup(targetDB.getDbIndex())) { + final String broadcastTableGroup = + PostPlanner.getBroadcastTableGroup(executionContext, getSchemaName()); + if (!GroupInfoUtil.isSingleGroup(broadcastTableGroup)) { + final TargetDB newTargetDB = new TargetDB(); + newTargetDB.setDbIndex(broadcastTableGroup); + newTargetDB.setTableNames(targetDB.getTableNameMap()); + newTargetDB.setLogTblName(targetDB.getLogTblName()); + final List newTargetDbs = new ArrayList<>(); + newTargetDbs.add(newTargetDB); + targetDBs = Collections.singletonList(newTargetDbs); + } + } + } + } } else { final BitSet evaluatedParamIndex = new BitSet(); this.comparativeHintCache.values().forEach(e -> e.values().forEach( @@ -879,7 +944,14 @@ protected SqlNode buildSqlTemplate(ReplaceCallWithLiteralVisitor replaceCallWith float samplePercentage = PlannerContext.getPlannerContext(this).getParamManager().getFloat(ConnectionParams.SAMPLE_PERCENTAGE); if (samplePercentage >= 0 && samplePercentage <= 100) { - ((SqlSelect) sqlTemplate).getOptimizerHint().addHint("+sample_percentage(" + samplePercentage + ")"); + ((SqlSelect) sqlTemplate).getOptimizerHint() + .addHint("+sample_percentage(" + formatSampleRate(samplePercentage) + ")"); + } + + // Pass through dn hint control by optimizer + String dnHint = ec.getParamManager().getString(ConnectionParams.DN_HINT); + if (ec != null && StringUtils.isNotEmpty(dnHint)) { + ((SqlSelect) sqlTemplate).getOptimizerHint().addHint("+" + dnHint); } // Pass through user hint. @@ -923,23 +995,28 @@ public XPlanTemplate getXPlanDirect() { public XPlanTemplate getXPlan() { // Always generate the XPlan in case of switching connection pool. - if (lockMode != LockMode.UNDEF) { + if (lockMode != LockMode.UNDEF || this.getFlashbackOperator() != null) { return null; // TODO: lock not supported now. } final RelNode pushedRel = getPushedRelNode(); if (XPlanRel != pushedRel) { // Compare the value to check whether the plan changed. - final RelToXPlanConverter converter = new RelToXPlanConverter(); - try { - XPlan = converter.convert(RelXPlanOptimizer.optimize(pushedRel)); - } catch (Exception e) { - Throwable throwable = e; - while (throwable.getCause() != null && throwable.getCause() instanceof InvocationTargetException) { - throwable = ((InvocationTargetException) throwable.getCause()).getTargetException(); + synchronized (this) { + if (XPlanRel != pushedRel) { + final RelToXPlanConverter converter = new RelToXPlanConverter(); + try { + XPlan = converter.convert(RelXPlanOptimizer.optimize(pushedRel)); + } catch (Exception e) { + Throwable throwable = e; + while (throwable.getCause() != null + && throwable.getCause() instanceof InvocationTargetException) { + throwable = ((InvocationTargetException) throwable.getCause()).getTargetException(); + } + logger.info("XPlan converter: " + throwable.getMessage()); + XPlan = null; + } } - logger.info("XPlan converter: " + throwable.getMessage()); - XPlan = null; + XPlanRel = pushedRel; } - XPlanRel = pushedRel; } return XPlan; } @@ -1281,8 +1358,11 @@ public RelWriter explainTermsForDisplay(RelWriter pw) { } ((SqlSelect) nativeSql).setWhere(filter); } + if (PlannerContext.getPlannerContext(this).getExtraCmds().containsKey(ConnectionProperties.DN_HINT)) { + nativeSql = getSqlTemplate(executionContext); + } ReplaceTableNameWithTestTableVisitor replaceTableNameWithTestTableVisitor = - new ReplaceTableNameWithTestTableVisitor(schemaName, false, + new ReplaceTableNameWithTestTableVisitor(schemaName, false, true, PlannerContext.getPlannerContext(this).getExecutionContext()); nativeSql = nativeSql.accept(replaceTableNameWithTestTableVisitor); String sql = TStringUtil.replace(RelUtils.toNativeSql(nativeSql, this.getDbType()), "\n", " "); @@ -1623,6 +1703,8 @@ public int calShardUpperBound() { PlannerContext.getPlannerContext(this).getParamManager() .getBoolean(ConnectionParams.CALCULATE_ACTUAL_SHARD_COUNT_FOR_COST); ExecutionContext executionContext = PlannerContext.getPlannerContext(this).getExecutionContext(); + Parameters params = OptimizerUtils.getParametersForOptimizer(this); + executionContext = executionContext.copy(params); if (calActualShardCount) { try { if (!partitionInfoManager.isNewPartDbTable(logTb)) { @@ -1643,12 +1725,12 @@ public int calShardUpperBound() { calcParams.put(CalcParamsAttribute.COM_DB_TB, m); calcParams.put(CalcParamsAttribute.CONN_TIME_ZONE, executionContext.getTimeZone()); calcParams.put(CalcParamsAttribute.EXECUTION_CONTEXT, executionContext); - Map params = - executionContext.getParams() == null ? null : - executionContext.getParams().getCurrentParameter(); List tdbs = executionContext.getSchemaManager(schemaName).getTddlRuleManager() - .shard(getShardingTable(), false, true, comps, params, calcParams, executionContext); + .shard(getShardingTable(), false, true, comps, + params == null ? null : params.getCurrentParameter(), + calcParams, + executionContext); return tdbs.stream().map(targetDB -> targetDB.getTableNames() == null ? 0 : targetDB.getTableNames().size()).reduce(0, (a, b) -> a + b).intValue(); @@ -1748,6 +1830,11 @@ public boolean isSingleGroup(boolean allowFalseCondition) { } shardColumns = tr.getShardColumns(); } else { + + if (onlySelectOnePhysicalPartition(ec)) { + return true; + } + PartitionInfoManager partitionInfoManager = tddlRuleManager.getPartitionInfoManager(); PartitionInfo partitionInfo = partitionInfoManager.getPartitionInfo(getLogicalTableName()); shardColumns = partitionInfo.getPartitionColumns(); @@ -1782,8 +1869,17 @@ public boolean isSingleGroup(boolean allowFalseCondition) { shardColumns = tr.getShardColumns(); } else { PartitionInfoManager partitionInfoManager = tddlRuleManager.getPartitionInfoManager(); - PartitionInfo partitionInfo = - partitionInfoManager.getPartitionInfo(getLogicalTableName()); + PartitionInfo partitionInfo = partitionInfoManager.getPartitionInfo(name); + + if (partitionInfo == null) { + return false; + } else if (partitionInfo.isSingleTable()) { + hasOne = true; + continue; + } else if (partitionInfo.isBroadcastTable()) { + continue; + } + shardColumns = partitionInfo.getPartitionColumns(); } @@ -1971,6 +2067,16 @@ public void setLockMode(LockMode lockMode) { public void optimizePhySql() { getPushDownOpt().optimizePhySql(); + if(getNativeSqlNode().getKind() == SqlKind.DELETE){ + // since force index in single table delete need to add alias + // may cause error execute on mysql + // so not support delete auto gen force index for delete + return; + } + String index = ForceIndexUtil.genAutoForceIndex(this); + if (index != null) { + getPushDownOpt().autoForceIndex(index); + } tableNames = collectTableNames(); rebuildPartRoutingPlanInfo(); } @@ -2018,7 +2124,6 @@ public boolean isSingleGroup() { public String explainNodeName() { String name = "LogicalView"; return name; - } public List getBloomFilters() { @@ -2057,7 +2162,9 @@ public RelNode clone() { logicalView.setScalarList(scalarList); logicalView.correlateVariableScalar.addAll(correlateVariableScalar); logicalView.flashback = this.flashback; + logicalView.flashbackOperator = this.flashbackOperator; logicalView.columnOrigins = this.getColumnOrigins(); + logicalView.isFromForceIndex = this.isFromForceIndex(); return logicalView; } @@ -2072,7 +2179,9 @@ public LogicalView copy(RelTraitSet traitSet) { newLogicalView.newPartDbTbl = this.newPartDbTbl; newLogicalView.pushDownOpt = pushDownOpt.copy(newLogicalView, this.getPushedRelNode()); newLogicalView.flashback = this.flashback; + newLogicalView.flashbackOperator = this.flashbackOperator; newLogicalView.columnOrigins = this.getColumnOrigins(); + newLogicalView.isFromForceIndex = this.isFromForceIndex(); return newLogicalView; } @@ -2205,6 +2314,14 @@ public List getColumnOrigins() { return columnOrigins; } + public boolean isFromForceIndex() { + return isFromForceIndex; + } + + public void setFromForceIndex(boolean fromForceIndex) { + isFromForceIndex = fromForceIndex; + } + public static class ReplacedTableCondition { private boolean replaced; private RelNode relNode; @@ -2494,10 +2611,7 @@ public RelFieldCollation.Direction collationMatchRangePartition() { } public RelOptCost getSelfCost(RelMetadataQuery mq) { - if (selfCost != null) { - return selfCost; - } - return selfCost = computeSelfCost(getCluster().getPlanner(), mq); + return computeSelfCost(getCluster().getPlanner(), mq); } public synchronized Double getRowCount(RelMetadataQuery mq) { @@ -2548,6 +2662,26 @@ public Map getFunctionalDependency(RelMetadata return mq.getFunctionalDependency(getPushedRelNode(), iOutputColumns); } + public Double getMaxSelectivity() { + final double[] result = {0D}; + new RelVisitor() { + @Override + public void visit(RelNode node, int ordinal, RelNode parent) { + if (node instanceof LogicalFilter) { + if (node.getInput(0) instanceof LogicalTableScan) { + LogicalTableScan tableScan = (LogicalTableScan) ((LogicalFilter) node).getInput(); + TableScanSelectivityUpperLimitEstimator estimator = + new TableScanSelectivityUpperLimitEstimator(tableScan); + result[0] = estimator.evaluate(((LogicalFilter) node).getCondition()).getSelectivity(); + return; + } + } + super.visit(node, ordinal, parent); + } + }.go(CBOUtil.optimizeByPushFilterImpl(getPushedRelNode())); + return result[0]; + } + public boolean useSelectPartitions() { if (this.partitions != null) { SqlNodeList partNamesAst = (SqlNodeList) this.partitions; @@ -2558,6 +2692,27 @@ public boolean useSelectPartitions() { return false; } + public boolean onlySelectOnePhysicalPartition(ExecutionContext ec) { + if (!useSelectPartitions() || isJoin()) { + return false; + } + + try { + List resultList = PartitionPruner.prunePartitions(this, ec); + filterPrunedResultBySelectedPartitions(resultList); + if (!resultList.isEmpty()) { + List prunedResult = resultList.get(0).getPrunedParttions(); + if (prunedResult.size() == 1) { + return true; + } + } + } catch (Throwable ex) { + logger.warn(ex); + } + + return false; + } + public boolean isFromMergeIndex() { return fromMergeIndex; } @@ -2576,4 +2731,8 @@ public boolean unPushDown() { } return false; } + + public boolean hasTargetTableHint() { + return targetTablesHintCache != null && !targetTablesHintCache.isEmpty(); + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/OSSTableScan.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/OSSTableScan.java index 51167ac83..4373327d5 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/OSSTableScan.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/OSSTableScan.java @@ -21,6 +21,7 @@ import com.alibaba.polardbx.common.jdbc.ParameterContext; import com.alibaba.polardbx.common.jdbc.Parameters; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.timezone.TimestampUtils; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.config.meta.CostModelWeight; import com.alibaba.polardbx.optimizer.config.meta.TableScanIOEstimator; @@ -30,6 +31,9 @@ import com.alibaba.polardbx.optimizer.core.planner.Planner; import com.alibaba.polardbx.optimizer.core.planner.rule.OSSMergeIndexRule; import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.sharding.result.RelShardInfo; +import com.alibaba.polardbx.optimizer.utils.RexUtils; import com.alibaba.polardbx.optimizer.utils.TableTopologyUtil; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -61,6 +65,7 @@ import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.SqlSelect; import org.apache.calcite.sql.fun.SqlRuntimeFilterFunction; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -69,6 +74,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TimeZone; public class OSSTableScan extends LogicalView { @@ -688,4 +694,66 @@ public RelWriter explainTerms(RelWriter pw) { .itemIf("ossRuntimeFilter", this.runtimeFilter, this.runtimeFilter != null) .itemIf("partitionWise", this.traitSet.getPartitionWise(), !this.traitSet.getPartitionWise().isTop()); } + + public boolean isFlashbackQuery() { + if (flashbackOperator == null && flashback == null) { + return false; + } + + if (flashback == null) { + throw new RuntimeException("Flashback query timestamp or tso expression should not be empty"); + } + + return true; + } + + public Long getFlashbackQueryTso(ExecutionContext context) { + if (flashbackOperator == null && flashback == null) { + // no flashback expression + return null; + } + + if (flashback == null) { + throw new RuntimeException("Flashback query timestamp or tso expression should not be empty"); + } + + if (flashbackOperator == null || flashbackOperator == SqlStdOperatorTable.AS_OF) { + // as of timestamp + if (!(flashback instanceof RexDynamicParam)) { + throw new RuntimeException("Illegal timestamp expression: " + flashback.toString()); + } + String timestampString = context.getParams().getCurrentParameter() + .get(((RexDynamicParam) flashback).getIndex() + 1).getValue().toString(); + TimeZone fromTimeZone; + if (context.getTimeZone() != null) { + fromTimeZone = context.getTimeZone().getTimeZone(); + } else { + fromTimeZone = TimeZone.getDefault(); + } + return TimestampUtils.getTsFromTimestampWithTimeZone(timestampString, fromTimeZone); + } else if (flashbackOperator == SqlStdOperatorTable.AS_OF_57 + || flashbackOperator == SqlStdOperatorTable.AS_OF_80) { + // as of tso + try { + Object value = + RexUtils.getValueFromRexNode(flashback, context, context.getParams().getCurrentParameter()); + if (value instanceof Long) { + return (Long) value; + } else if (value instanceof Number) { + return ((Number) value).longValue(); + } else { + throw new RuntimeException("Illegal tso param type: " + value.getClass()); + } + } catch (Throwable t) { + throw new RuntimeException("Illegal tso expression: " + flashback.toString(), t); + } + } else { + throw new RuntimeException("Unexpected flashback operator: " + flashbackOperator.getName()); + } + } + + public RelShardInfo getCciRelShardInfo(ExecutionContext ec, PartitionInfo cciPartInfo) { + // TODO: add pruneStepCache + return getPushDownOpt().getCciRelShardInfo(ec, cciPartInfo); + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableInsertSharder.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableInsertSharder.java index 17b42f797..836f53e06 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableInsertSharder.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableInsertSharder.java @@ -75,6 +75,7 @@ public class PhyTableInsertSharder { private Long lastInsertId = null; private Long returnedLastInsertId = null; private boolean usingSequence = true; + private boolean sequenceAlreadyFetched = false; /** * Generated sequence values. Format: [{fieldIndex, seqValue}, ...], each @@ -84,12 +85,18 @@ public class PhyTableInsertSharder { private String schemaName = null; - public PhyTableInsertSharder(LogicalInsert parent, Parameters parameterSettings, boolean autoValueOnZero) { + public PhyTableInsertSharder(LogicalInsert parent, Parameters parameterSettings, boolean autoValueOnZero, + boolean sequenceAlreadyFetched) { this.parent = parent; this.sqlTemplate = (SqlInsert) parent.getSqlTemplate(); this.parameterSettings = parameterSettings; this.autoValueOnZero = autoValueOnZero; this.schemaName = parent.getSchemaName(); + this.sequenceAlreadyFetched = sequenceAlreadyFetched; + } + + public PhyTableInsertSharder(LogicalInsert parent, Parameters parameterSettings, boolean autoValueOnZero) { + this(parent, parameterSettings, autoValueOnZero, false); } public long getLastInsertId() { @@ -249,6 +256,10 @@ public void handleWithSequence(String schemaName, boolean isSingleTable) { usingSequence = seqColumnIndex >= 0; + if (sequenceAlreadyFetched) { + return; + } + // If it's not using sequence, and it's not using batch, which means // there won't be NEXTVAL, skip calculating sequence. if (usingSequence || parameterSettings == null || !parameterSettings.isBatch()) { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableModifyViewBuilder.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableModifyViewBuilder.java index db9fd4fdf..ddbe9c4c3 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableModifyViewBuilder.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableModifyViewBuilder.java @@ -181,6 +181,7 @@ private void buildOnePhyTableOperatorForModify(BytesSql sqlTemplateStr, MemoryAl buildParams.setBatchParameters(null); PhyTableOperation phyTableModify = PhyTableOperationFactory.getInstance().buildPhyTblOpByParams(buildParams); + phyTableModify.setParamIndex(paramIndex); phyTableScans.add(phyTableModify); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOpBuildParams.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOpBuildParams.java index b6726113c..6c30bc734 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOpBuildParams.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOpBuildParams.java @@ -23,6 +23,8 @@ import com.alibaba.polardbx.optimizer.core.dialect.DbType; import com.alibaba.polardbx.optimizer.memory.MemoryAllocatorCtx; import com.google.protobuf.ByteString; +import lombok.Getter; +import lombok.Setter; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.RelNode; @@ -164,6 +166,12 @@ public class PhyTableOpBuildParams { protected BytesSql bytesSql; protected Map dynamicParams; + /** + * Mapping from key of dynamicParams to index in RexDynamicParam + */ + @Getter + @Setter + protected List paramIndexMapping; protected List> batchParameters; public PhyTableOpBuildParams() { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOperation.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOperation.java index 7ac8404be..269b3c4f1 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOperation.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOperation.java @@ -30,6 +30,9 @@ import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.googlecode.protobuf.format.JsonFormat; import com.mysql.cj.x.protobuf.PolarxExecPlan; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.RelNode; @@ -76,6 +79,12 @@ public final class PhyTableOperation extends BaseTableOperation { * instead of going to LogicalViewHandler to its execution. */ protected boolean onlyOnePartitionAfterPruning = false; + /** + * Mapping from index of DynamicParamIndex in {@link #logicalPlan} to index in {@link #param} + */ + @Getter + @Setter + protected List paramIndex = new ArrayList<>(); /** * NOT allowed to use new PhyTableOperation() build PhyTableOp, diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOperationFactory.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOperationFactory.java index 544434f72..2861e7cfa 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOperationFactory.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableOperationFactory.java @@ -87,6 +87,7 @@ public PhyTableOperation buildPhyTblOpTemplate(PhyTableOpBuildParams opTemplateB buildParams.setBytesSql(opTemplateBuildParams.bytesSql); buildParams.setDbType(DbType.MYSQL); buildParams.setDynamicParams(opTemplateBuildParams.dynamicParams); + buildParams.setParamIndexMapping(opTemplateBuildParams.paramIndexMapping); buildParams.setBatchParameters(opTemplateBuildParams.batchParameters); PhyTableOperation operation = buildPhyTblOpByParamsInner(buildParams, false); @@ -131,6 +132,7 @@ private PhyTableOperation buildPhyTableOperationByPhyOpInner(PhyTableOperation t buildParams.setBytesSql(targetPhyOp.getBytesSql()); buildParams.setDbType(targetPhyOp.getDbType()); buildParams.setDynamicParams(targetPhyOp.getParam()); + buildParams.setParamIndexMapping(targetPhyOp.getParamIndex()); buildParams.setBatchParameters(targetPhyOp.getBatchParameters()); if (newBuildParams != null) { @@ -155,6 +157,10 @@ private PhyTableOperation buildPhyTableOperationByPhyOpInner(PhyTableOperation t buildParams.setDynamicParams(newBuildParams.dynamicParams); } + if (newBuildParams.paramIndexMapping != null) { + buildParams.setParamIndexMapping(newBuildParams.paramIndexMapping); + } + if (newBuildParams.bytesSql != null) { buildParams.setBytesSql(newBuildParams.bytesSql); } @@ -199,6 +205,7 @@ private PhyTableOperation buildPhyTblOpByParamsInner(PhyTableOpBuildParams build operation.setBytesSql(buildParams.bytesSql); operation.setDbType(DbType.MYSQL); operation.setParam(buildParams.dynamicParams); + operation.setParamIndex(buildParams.paramIndexMapping); operation.setBatchParameters(buildParams.batchParameters); if (buildParams.nativeSqlNode != null) { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableScanBuilder.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableScanBuilder.java index 12b5b936e..e71d76424 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableScanBuilder.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PhyTableScanBuilder.java @@ -338,11 +338,11 @@ public List build(ExecutionContext executionContext) { if (pushDowned && parent instanceof LogicalView) { //the sqlTemplate shouldn't happen change for push-down plan. bytesSql = RelUtils.toNativeBytesSql(sqlTemplate, dbType); - XPlan = ((LogicalView) parent).getXPlan(); + XPlan = ((LogicalView) parent).getXPlanDirect(); } else if (parent instanceof LogicalView && ((LogicalView) parent).getSqlTemplate(executionContext) == sqlTemplate) { bytesSql = ((LogicalView) parent).getBytesSql(sqlTemplate); - XPlan = ((LogicalView) parent).getXPlan(); + XPlan = ((LogicalView) parent).getXPlanDirect(); } else { bytesSql = RelUtils.toNativeBytesSql(sqlTemplate, dbType); XPlan = null; @@ -385,6 +385,13 @@ public List build(ExecutionContext executionContext) { Boolean enableGrpParallelism = executionContext.getParamManager().getBoolean(ConnectionParams.ENABLE_GROUP_PARALLELISM); + + if (parent instanceof OSSTableScan) { + if (((OSSTableScan) parent).isColumnarIndex()) { + enableGrpParallelism = false; + } + } + if (enableGrpParallelism) { TargetTableInfo targetTableInfo = PhyTableOperationUtil.groupTargetTablesByGroupConnId(schemaName, logTblNames, targetTables, isForUpdate, diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PushDownOpt.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PushDownOpt.java index fc4ac18ad..046b28148 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PushDownOpt.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/PushDownOpt.java @@ -29,6 +29,7 @@ import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.dialect.DbType; +import com.alibaba.polardbx.optimizer.core.planner.rule.AutoForceIndexRule; import com.alibaba.polardbx.optimizer.core.planner.rule.FilterConditionSimplifyRule; import com.alibaba.polardbx.optimizer.core.planner.rule.FilterMergeRule; import com.alibaba.polardbx.optimizer.core.planner.rule.FilterReorderRule; @@ -36,6 +37,7 @@ import com.alibaba.polardbx.optimizer.core.planner.rule.JoinSemiJoinTransposeRule; import com.alibaba.polardbx.optimizer.core.planner.rule.RuleToUse; import com.alibaba.polardbx.optimizer.core.planner.rule.SemiJoinCorrToSubQueryRule; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.pruning.PartPruneStepType; import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruneStep; import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruneStepBuilder; @@ -109,7 +111,6 @@ import java.util.stream.IntStream; import static com.alibaba.polardbx.common.properties.ConnectionParams.MAX_IN_PRUNE_CACHE_SIZE; -import static com.alibaba.polardbx.common.properties.ConnectionParams.MAX_IN_PRUNE_CACHE_TABLE_SIZE; import static com.alibaba.polardbx.optimizer.utils.PlannerUtils.deriveJoinType; import static com.alibaba.polardbx.optimizer.utils.PushDownUtils.pushAgg; import static com.alibaba.polardbx.optimizer.utils.PushDownUtils.pushFilter; @@ -149,6 +150,12 @@ public class PushDownOpt { */ private Map> allPartPruneSteps = Maps.newConcurrentMap(); + /** + * For columnar multi-version partition: + * meta_version -> IN expression key -> PartitionPruneStep + */ + private Map> allColumnarPartPruneSteps = Maps.newConcurrentMap(); + private Set shardRelatedInTypeParamIndexes; public PushDownOpt(LogicalView tableScan, DbType dbType, ExecutionContext ec) { @@ -182,6 +189,7 @@ private PushDownOpt(PushDownOpt pushDownOpt) { this.comparatives = pushDownOpt.comparatives; this.fullComparatives = pushDownOpt.fullComparatives; this.allPartPruneSteps = pushDownOpt.allPartPruneSteps; + this.allColumnarPartPruneSteps = pushDownOpt.allColumnarPartPruneSteps; } public final PushDownOpt copy(LogicalView logicalView, RelNode rel) { @@ -373,6 +381,29 @@ public void optimizePhySql() { this.builder.push(optimizedNode); } + /** + * transform semiJoin and correlate to subquery, optimize the tree for native sql + * + * @return the root of a tree without semiJoin and correlate + */ + public void autoForceIndex(String index) { + HepProgramBuilder builder = new HepProgramBuilder(); + + //pull project + builder.addGroupBegin(); + builder.addRuleInstance(new AutoForceIndexRule(index)); + builder.addGroupEnd(); + + HepPlanner planner = new HepPlanner(builder.build()); + planner.stopOptimizerTrace(); + planner.setRoot(getPushedRelNode()); + RelNode optimizedNode = planner.findBestExp(); + + optimizedNode = optimizedNode.accept(new RelCastRemover()); + this.builder.clear(); + this.builder.push(optimizedNode); + } + /** * return current native sql, may be a middle state */ @@ -481,6 +512,10 @@ public boolean aggIsPushed() { return aggIsPushed; } + public void setAggIsPushed(boolean aggIsPushed) { + this.aggIsPushed = aggIsPushed; + } + public void pushJoin(Join join, LogicalView rightView, List leftFilters, List rightFilters, RelOptCluster cluster) { plainRows = plainRows.updateRefIndexForJoin( @@ -622,13 +657,21 @@ private List buildNewPartPruneSteps(ExecutionContext ec) { } String key = OptimizerUtils.buildInExprKey(ec); // cache prune steps for the key - if (this.allPartPruneSteps.size() < ec.getParamManager().getInt(MAX_IN_PRUNE_CACHE_SIZE) && - allPartPruneSteps.size() < ec.getParamManager().getInt(MAX_IN_PRUNE_CACHE_TABLE_SIZE)) { + if (this.allPartPruneSteps.size() < ec.getParamManager().getInt(MAX_IN_PRUNE_CACHE_SIZE)) { this.allPartPruneSteps.put(key, allPartPruneSteps); } return allPartPruneSteps; } + public PartitionPruneStep buildCciPartPruneSteps(ExecutionContext ec, PartitionInfo cciPartInfo) { + List logTbNameList = tableScan.getTableNames(); + Preconditions.checkArgument(logTbNameList.size() == 1); + PartRoutingPlanInfo partRoutingPlanInfo = buildCciPartRoutingPlanInfo(getPushedRelNode(), ec, cciPartInfo); + + String tbName = logTbNameList.get(0); + return partRoutingPlanInfo.allPartPruningSteps.get(tbName); + } + public RelNode getPushedRelNode() { return builder.peek(); } @@ -684,6 +727,29 @@ public RelShardInfo getRelShardInfo(int tableIndex, ExecutionContext ec) { return relShardInfo; } + public RelShardInfo getCciRelShardInfo(ExecutionContext ec, PartitionInfo cciPartInfo) { + Long metaVersion = cciPartInfo.getMetaVersion(); + Map partPruneStepCache = + allColumnarPartPruneSteps.computeIfAbsent(metaVersion, v -> Maps.newConcurrentMap()); + RelShardInfo relShardInfo = new RelShardInfo(); + String logTbName = this.tableScan.getTableNames().get(0); + relShardInfo.setTableName(logTbName); + relShardInfo.setSchemaName(this.tableScan.getSchemaName()); + relShardInfo.setUsePartTable(true); + + String key = OptimizerUtils.buildInExprKey(ec); + if (partPruneStepCache.containsKey(key)) { + relShardInfo.setPartPruneStepInfo(partPruneStepCache.get(key)); + } else { + relShardInfo.setPartPruneStepInfo(buildCciPartPruneSteps(ec, cciPartInfo)); + if (partPruneStepCache.size() < ec.getParamManager().getInt(MAX_IN_PRUNE_CACHE_SIZE)) { + partPruneStepCache.put(key, relShardInfo.getPartPruneStepInfo()); + } + } + + return relShardInfo; + } + public Map getComparative(int tableIndex) { return Optional.of(comparatives).filter(c -> c.size() > tableIndex).map(c -> c.get(tableIndex)) .orElse(new HashMap<>()); @@ -927,6 +993,17 @@ protected PartRoutingPlanInfo buildPartRoutingPlanInfo(RelNode relPlan, boolean return pruningPlanInfo; } + public PartRoutingPlanInfo buildCciPartRoutingPlanInfo(RelNode relPlan, ExecutionContext ec, + PartitionInfo cciPartitionInfo) { + + PartRoutingPlanInfo pruningPlanInfo = new PartRoutingPlanInfo(); + ExtractionResult er = ConditionExtractor.predicateFrom(relPlan).extract(); + Map allPartPruningSteps = er.allPartPruneSteps(ec, cciPartitionInfo); + pruningPlanInfo.usePartitionTable = true; + pruningPlanInfo.allPartPruningSteps = allPartPruningSteps; + return pruningPlanInfo; + } + protected void updatePartRoutingPlanInfo(PartRoutingPlanInfo newPruningPlanInfo) { if (!newPruningPlanInfo.usePartitionTable) { updateComparative(newPruningPlanInfo.allComps, newPruningPlanInfo.allFullComps, new AtomicInteger()); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/RemoveIndexNodeVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/RemoveIndexNodeVisitor.java new file mode 100644 index 000000000..ad7dc8876 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/RemoveIndexNodeVisitor.java @@ -0,0 +1,78 @@ +package com.alibaba.polardbx.optimizer.core.rel; + +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.optimizer.config.table.IndexMeta; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.utils.PlannerUtils; +import org.apache.calcite.sql.util.SqlShuttle; +import org.apache.calcite.sql.SqlBasicCall; +import org.apache.calcite.sql.SqlCall; +import org.apache.calcite.sql.SqlDataTypeSpec; +import org.apache.calcite.sql.SqlDelete; +import org.apache.calcite.sql.SqlDynamicParam; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlInsert; +import org.apache.calcite.sql.SqlIntervalQualifier; +import org.apache.calcite.sql.SqlJoin; +import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlNodeList; +import org.apache.calcite.sql.SqlReplace; +import org.apache.calcite.sql.SqlSelect; +import org.apache.calcite.sql.SqlUpdate; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.util.SqlShuttle; +import org.apache.commons.lang.StringUtils; + +public class RemoveIndexNodeVisitor extends SqlShuttle { + private final static Logger logger = LoggerFactory.getLogger(PlannerUtils.class); + + private final TableMeta tMeta; + + public RemoveIndexNodeVisitor(TableMeta tMeta) { + this.tMeta = tMeta; + } + + /** + * invalidate not exist force index + * add alias to exist force index + * @param call Call + * @return new SqlDelete + */ + @Override + public SqlNode visit(SqlCall call) { + SqlCall copy = SqlNode.clone(call); + SqlKind kind = copy.getKind(); + if (kind == SqlKind.DELETE) { + SqlDelete delete = (SqlDelete) copy; + SqlIdentifier indexId = delete.getForceIndex(); + + if (indexId != null) { + String tablePart = indexId.names.get(0); + String indexPart = indexId.names.size() > 1 ? indexId.names.get(1) : null; + + if (indexPart == null) { + IndexMeta localIndex = tMeta.findLocalIndexByName(tablePart); + if (localIndex == null) { + // if index not exists, remove sourceSelect.from.indexNode + ((SqlIdentifier) delete.getSourceSelect().getFrom()).indexNode = null; + }else{ + // add alias to sqlDelete + delete.setOperand(7,delete.getSourceSelect().getFrom()); + delete.setWithTableAlias(true); + } + } else { + // 抛出异常报错“table with GSI should not exist here” + throw GeneralUtil.nestedException( + "table with GSI should not exist here"); + } + } + return delete; + } + return super.visit(call); + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceCallWithLiteralVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceCallWithLiteralVisitor.java index c54b02861..6979bd892 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceCallWithLiteralVisitor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceCallWithLiteralVisitor.java @@ -167,7 +167,9 @@ public LogicalModify visit(LogicalModify logicalModify) { logicalModify.getPrimaryModifyWriters(), logicalModify.getGsiModifyWriters(), logicalModify.isWithoutPk(), - logicalModify.isModifyForeignKey()); + logicalModify.isModifyForeignKey(), + logicalModify.getModifyTopNInfo(), + logicalModify.getMultiWriteInfo()); } @Override diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceDifferentDBSingleTblWithPhyTblVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceDifferentDBSingleTblWithPhyTblVisitor.java index 5be52d807..524ce7045 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceDifferentDBSingleTblWithPhyTblVisitor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceDifferentDBSingleTblWithPhyTblVisitor.java @@ -90,7 +90,7 @@ protected SqlNode buildSth(SqlNode sqlNode) { physicalDBName = schemaName; physicalTableName = logicalTableName; } else { - physicalDBName = tableRule.getDbNamePattern(); + physicalDBName = GroupInfoUtil.buildPhysicalDbNameFromGroupName(tableRule.getDbNamePattern()); physicalTableName = tableRule.getTbNamePattern(); } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceSequenceWithLiteralVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceSequenceWithLiteralVisitor.java index 653338077..63e799017 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceSequenceWithLiteralVisitor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceSequenceWithLiteralVisitor.java @@ -646,17 +646,8 @@ private SqlDynamicParam visitOneDynamicParam(SqlDynamicParam dynamicParam) { final Map curParams = parameterSettings.getCurrentParameter(); final int dynamicParamIndex = dynamicParam.getIndex(); - if (dynamicParam instanceof SqlSequenceParam) { - Long nextVal = assignImplicitValue(true); - // use setObject1 instead of oldPc.getParameterMethod, because - // the method is 'setString' when users inserts '0'. - ParameterContext newPc = new ParameterContext(ParameterMethod.setObject1, new Object[] { - dynamicParamIndex + 1, nextVal}); - curParams.put(dynamicParamIndex + 1, newPc); - } - - ParameterContext oldPc = curParams.get(dynamicParamIndex + 1); - Object autoIncValue = oldPc.getValue(); + final ParameterContext oldPc = curParams.get(dynamicParamIndex + 1); + final Object autoIncValue = oldPc.getValue(); final Long newValue = RexUtils.valueOfObject1(autoIncValue); // if NO_AUTO_VALUE_ON_ZERO is set, last_insert_id and returned_last_insert_id won't change. diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTableNameWithSomethingVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTableNameWithSomethingVisitor.java index efbba8ad4..8b8875df2 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTableNameWithSomethingVisitor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTableNameWithSomethingVisitor.java @@ -101,6 +101,8 @@ public abstract class ReplaceTableNameWithSomethingVisitor extends SqlShuttle { protected final ExecutionContext ec; + protected boolean isExplain = false; + protected ReplaceTableNameWithSomethingVisitor(Map correlateFieldInViewMap, String defaultSchemaName, ExecutionContext ec) { this.handleIndexHint = false; @@ -318,6 +320,7 @@ public SqlNode visit(SqlCall call) { } else { throw new UnsupportedOperationException("Unsupported DDL syntax."); } + return ddl; } else if (kind == SqlKind.RENAME_TABLE || kind == SqlKind.ALTER_TABLE_DISCARD_TABLESPACE || kind == SqlKind.ALTER_TABLE_IMPORT_TABLESPACE) { @@ -494,10 +497,42 @@ public SqlNode visit(SqlDataTypeSpec type) { return SqlNode.clone(type); } + /** + * Builds a dynamic parameter for a correlated subquery. + * + * @param isExplain whether in explain mode + * @param dynamicParam the dynamic parameter object + * @param correlateFieldMap the map of correlated fields + * @return the constructed SQL node + */ + public static SqlNode buildDynamicParamForCorrelatedSubquery( + boolean isExplain, + SqlDynamicParam dynamicParam, + Map correlateFieldMap + ) { + + // If in explain mode, return the symbolic representation of the dynamic parameter value + if (isExplain) { + if (dynamicParam.getValue() instanceof RexFieldAccess) { + return SqlLiteral.createSymbol(dynamicParam.getValue().toString(), SqlParserPos.ZERO); + } else { + return dynamicParam; + } + } + + // In non-explain mode, retrieve the corresponding literal from the correlated field map and construct an SQL literal node + RexNode fieldValue = correlateFieldMap.get(dynamicParam.getValue()); + if (fieldValue == null) { + throw new IllegalArgumentException( + "Corresponding item not found in correlated field map: " + dynamicParam.getValue()); + } + return SqlImplementor.buildSqlLiteral((RexLiteral) fieldValue); + } + @Override public SqlNode visit(SqlDynamicParam param) { if (param.getIndex() == -4 && correlateFieldInViewMap != null) { - return SqlImplementor.buildSqlLiteral((RexLiteral) correlateFieldInViewMap.get(param.getValue())); + return buildDynamicParamForCorrelatedSubquery(isExplain, param, correlateFieldInViewMap); } if (param.getIndex() == PlannerUtils.SCALAR_SUBQUERY_PARAM_INDEX && scalarSubqueryExecCtxMap != null) { @@ -572,6 +607,11 @@ public SqlNode buildJoinNode(SqlNode join) { sqlJoin.setRight(buildForIdentifier((SqlIdentifier) right)); } + SqlNode oldCondition = sqlJoin.getCondition(); + if (oldCondition instanceof SqlCall) { + SqlNode newCondition = visit((SqlCall) oldCondition); + sqlJoin.setOperand(5, newCondition); + } return sqlJoin; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTableNameWithTestTableVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTableNameWithTestTableVisitor.java index d7c851e21..31f7f9245 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTableNameWithTestTableVisitor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTableNameWithTestTableVisitor.java @@ -16,9 +16,9 @@ package com.alibaba.polardbx.optimizer.core.rel; +import com.alibaba.polardbx.common.eagleeye.EagleeyeHelper; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.google.common.collect.ImmutableList; -import com.alibaba.polardbx.common.eagleeye.EagleeyeHelper; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlNode; @@ -31,9 +31,11 @@ public class ReplaceTableNameWithTestTableVisitor extends ReplaceTableNameWithSo private final boolean testMode; - public ReplaceTableNameWithTestTableVisitor(String defaultSchemaName, boolean testMode, ExecutionContext ec) { + public ReplaceTableNameWithTestTableVisitor(String defaultSchemaName, boolean testMode, boolean isExplain, + ExecutionContext ec) { super(defaultSchemaName, ec); this.testMode = testMode; + this.isExplain = isExplain; } @Override diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTblWithPhyTblVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTblWithPhyTblVisitor.java index 9e51b05e3..28d091b49 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTblWithPhyTblVisitor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTblWithPhyTblVisitor.java @@ -51,6 +51,8 @@ public class ReplaceTblWithPhyTblVisitor extends ReplaceTableNameWithSomethingVisitor { private String schemaName; + private boolean allBroadcastTbl = true; + private boolean withBroadcastTbl; private boolean withSingleTbl; private boolean withPartitionTbl; private String uniqGroupName; @@ -143,7 +145,7 @@ protected SqlNode buildSth(SqlNode sqlNode) { } else { // should not happen throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_HINT, - "Unsupported to use direct HINT for part table that has multi physical tables in one partition"); + "Unsupported direct HINT for part table :" + pHint); } return sqlNode; @@ -183,6 +185,13 @@ protected SqlNode buildSth(SqlNode sqlNode) { if (tableRule == null) { return sqlNode; } + + this.withSingleTbl |= tddlRuleManager.isTableInSingleDb(logicalTableName); + this.withPartitionTbl |= tddlRuleManager.isShard(logicalTableName); + final boolean currentIsBroadcast = tddlRuleManager.isBroadCast(logicalTableName); + this.withBroadcastTbl |= currentIsBroadcast; + this.allBroadcastTbl &= currentIsBroadcast; + // don't replace table with sharding db and tb if (tableRule.getActualTopology().size() > 1) { for (Map.Entry> dbEntry : tableRule.getActualTopology().entrySet()) { @@ -192,9 +201,6 @@ protected SqlNode buildSth(SqlNode sqlNode) { } } - this.withSingleTbl |= tddlRuleManager.isTableInSingleDb(logicalTableName); - this.withPartitionTbl |= tddlRuleManager.isShard(logicalTableName); - return new SqlIdentifier(tableRule.getTbNamePattern(), SqlParserPos.ZERO); } /** @@ -235,6 +241,14 @@ public boolean shouldChooseSingleGroup() { return false; } + public boolean withBroadcastTable() { + return withBroadcastTbl; + } + + public boolean allBroadcastTable() { + return withBroadcastTbl && allBroadcastTbl; + } + public boolean shouldSkipSingleGroup() { return withPartitionTbl; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ToDrdsRelVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ToDrdsRelVisitor.java index 35ba3b35a..19944c1ea 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ToDrdsRelVisitor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ToDrdsRelVisitor.java @@ -30,14 +30,12 @@ import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.druid.util.StringUtils; -import com.alibaba.polardbx.gms.metadb.table.IndexVisibility; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta; -import com.alibaba.polardbx.optimizer.config.table.GlobalIndexMeta.IndexType; import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; -import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.IndexMeta; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.core.DrdsConvention; import com.alibaba.polardbx.optimizer.core.planner.rule.AccessPathRule; @@ -66,6 +64,7 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterSystemSetConfig; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTable; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableAddPartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableArchivePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableDropPartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableExtractPartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupAddPartition; @@ -75,6 +74,7 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupMergePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupModifyPartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupMovePartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupOptimizePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupRenamePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupReorgPartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableGroupSetLocality; @@ -85,6 +85,7 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableMergePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableModifyPartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableMovePartition; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableOptimizePartition; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTablePartitionCount; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableRemovePartitioning; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalAlterTableRenamePartition; @@ -139,8 +140,6 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalSequenceDdl; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalTruncateTable; import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalUnArchive; -import com.alibaba.polardbx.optimizer.hint.operator.HintCmdIndex; -import com.alibaba.polardbx.optimizer.hint.util.HintConverter; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager; import com.alibaba.polardbx.optimizer.partition.PartitionInfoUtil; @@ -160,6 +159,7 @@ import com.google.common.collect.Lists; import org.apache.calcite.plan.RelOptSchema; import org.apache.calcite.plan.RelOptTable; +import org.apache.calcite.rel.AbstractRelNode; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttleImpl; import org.apache.calcite.rel.core.DDL; @@ -180,6 +180,7 @@ import org.apache.calcite.rel.ddl.AlterStoragePool; import org.apache.calcite.rel.ddl.AlterSystemSetConfig; import org.apache.calcite.rel.ddl.AlterTable; +import org.apache.calcite.rel.ddl.AlterTableArchivePartition; import org.apache.calcite.rel.ddl.AlterTableGroupAddPartition; import org.apache.calcite.rel.ddl.AlterTableGroupAddTable; import org.apache.calcite.rel.ddl.AlterTableGroupDropPartition; @@ -187,6 +188,7 @@ import org.apache.calcite.rel.ddl.AlterTableGroupMergePartition; import org.apache.calcite.rel.ddl.AlterTableGroupModifyPartition; import org.apache.calcite.rel.ddl.AlterTableGroupMovePartition; +import org.apache.calcite.rel.ddl.AlterTableGroupOptimizePartition; import org.apache.calcite.rel.ddl.AlterTableGroupRenamePartition; import org.apache.calcite.rel.ddl.AlterTableGroupReorgPartition; import org.apache.calcite.rel.ddl.AlterTableGroupSetLocality; @@ -247,6 +249,7 @@ import org.apache.calcite.rel.logical.LogicalOutFile; import org.apache.calcite.rel.logical.LogicalProject; import org.apache.calcite.rel.logical.LogicalRecyclebin; +import org.apache.calcite.rel.logical.LogicalTableLookup; import org.apache.calcite.rel.logical.LogicalTableModify; import org.apache.calcite.rel.logical.LogicalTableScan; import org.apache.calcite.rel.metadata.RelMetadataQuery; @@ -265,6 +268,7 @@ import org.apache.calcite.sql.SqlAlterTableModifyPartitionValues; import org.apache.calcite.sql.SqlAlterTableModifySubPartitionValues; import org.apache.calcite.sql.SqlAlterTableMovePartition; +import org.apache.calcite.sql.SqlAlterTableOptimizePartition; import org.apache.calcite.sql.SqlAlterTableRemoveLocalPartition; import org.apache.calcite.sql.SqlAlterTableRenamePartition; import org.apache.calcite.sql.SqlAlterTableReorgPartition; @@ -272,6 +276,8 @@ import org.apache.calcite.sql.SqlAlterTableSplitPartition; import org.apache.calcite.sql.SqlAlterTableSplitPartitionByHotValue; import org.apache.calcite.sql.SqlAlterTableTruncatePartition; +import org.apache.calcite.sql.SqlCall; +import org.apache.calcite.sql.SqlCharStringLiteral; import org.apache.calcite.sql.SqlCheckColumnarIndex; import org.apache.calcite.sql.SqlCheckGlobalIndex; import org.apache.calcite.sql.SqlCreateTable; @@ -293,8 +299,10 @@ import org.apache.calcite.sql.SqlUpdate; import org.apache.calcite.util.Pair; import org.apache.calcite.util.Util; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; @@ -307,6 +315,7 @@ import java.util.stream.Collectors; import static com.alibaba.polardbx.common.exception.code.ErrorCode.ERR_DML_WITH_SUBQUERY; +import static org.apache.calcite.sql.parser.SqlParserPos.ZERO; /** * 对RelNode进行转换,将其底层TableScan转换为 LogicalView @@ -372,6 +381,8 @@ public class ToDrdsRelVisitor extends RelShuttleImpl { private boolean existsGroupingSets; private boolean modifyWithLimitOffset = false; private boolean existsOSSTable; + private boolean existForceColumnar = false; + private boolean allTableHaveColumnar = true; private boolean existsCheckSum = false; private boolean existsUnpushableAgg = false; @@ -381,6 +392,13 @@ public class ToDrdsRelVisitor extends RelShuttleImpl { private boolean existsUnPushedDynamicValues = false; + /** + * insert select 中select包含as of tso时,在RR隔离级别下,下推执行DN会将select变成当前读,快照失效了,这里禁止下推,RC隔离级别没事。 + */ + private boolean insertSelectWithFlashback = false; + + private boolean hasLocalForceIndex = false; + public ToDrdsRelVisitor() { } @@ -417,6 +435,8 @@ public final RelNode visit(TableScan scan) { setShouldRemoveSchemaName(qualifiedName); final String schemaName = qualifiedName.size() == 2 ? qualifiedName.get(0) : null; + final String schemaNameNotNull = + schemaName == null ? this.plannerContext.getExecutionContext().getSchemaName() : schemaName; // Ensure that schema name not null. final RelNode scanOrLookup = buildTableAccess(scan, tableName, @@ -454,32 +474,10 @@ public final RelNode visit(TableScan scan) { existsNonPushDownFunc = true; } } - return scanOrLookup; - } - - private boolean isGsiVisible(String schema, String table, String indexName) { - if (StringUtils.isEmpty(indexName)) { - return true; - } - SchemaManager sm = this.plannerContext.getExecutionContext().getSchemaManager(schema); - if (sm == null) { - return true; - } - TableMeta tableMeta = sm.getTable(table); - if (tableMeta == null) { - return true; - } - final Map gsiPublished = tableMeta.getGsiPublished(); - if (gsiPublished == null) { - return true; - } - - if (gsiPublished.containsKey(indexName) - && gsiPublished.get(indexName).visibility == IndexVisibility.INVISIBLE) { - return false; - } else { - return true; + if (!CBOUtil.hasCci(schemaNameNotNull, tableName, this.plannerContext.getExecutionContext())) { + this.allTableHaveColumnar = false; } + return scanOrLookup; } private RelNode buildTableAccess(TableScan scan, String tableName, String schemaName) { @@ -504,116 +502,346 @@ private RelNode buildTableAccess(TableScan scan, String tableName, String schema } } } - final Engine engine = this.plannerContext.getExecutionContext() - .getSchemaManager(schemaName).getTable(tableName).getEngine(); - return Optional.ofNullable(scan.getIndexNode()) - // FORCE INDEX - .filter(indexNode -> indexNode instanceof SqlNodeList && ((SqlNodeList) indexNode).size() > 0) - // If more than one index specified, choose first one only - .map(indexNode -> (SqlIndexHint) ((SqlNodeList) indexNode).get(0)) - // only support force index - .filter(SqlIndexHint::forceIndex) - .filter(hint -> { - final String indexName = - GlobalIndexMeta.getIndexName(RelUtils.lastStringValue(hint.getIndexList())); - final String unwrapped = GlobalIndexMeta - .getGsiWrappedName(tableName, indexName, schemaName, plannerContext.getExecutionContext()); - return isGsiVisible(schemaName, tableName, StringUtils.isEmpty(unwrapped) ? indexName : unwrapped); - } - ) - // Dealing with force index(`xxx`), `xxx` will decoded as string. - .map(indexNode -> GlobalIndexMeta.getIndexName(RelUtils.lastStringValue(indexNode.getIndexList().get(0)))) - .flatMap(indexName -> { - // check columnar index first - final String columnarIndexNameUnwrapped = GlobalIndexMeta.getColumnarWrappedName(tableName, indexName, - schemaName, plannerContext.getExecutionContext()); - if (columnarIndexNameUnwrapped != null) { - indexName = columnarIndexNameUnwrapped; + final TableMeta tMeta = + this.plannerContext.getExecutionContext().getSchemaManager(schemaName).getTable(tableName); + final Engine engine = tMeta.getEngine(); + + // try index hint first + hasLocalForceIndex = false; + RelNode scanOrLookup = buildForceIndexByIndexHint(catalog, scan, schemaName, tMeta, engine); + if (scanOrLookup != null) { + if (hasLocalForceIndex) { + // meaning index hint is working, we need to forbid the direct plan and post planner + this.plannerContext.setLocalIndexHint(true); + } + return scanOrLookup; + } + + // try force index + scanOrLookup = buildForceIndexByForceIndex(catalog, scan, schemaName, tMeta, engine); + if (scanOrLookup != null) { + return scanOrLookup; + } + + // remove all force index + removeForceIndex(scan); + return RelUtils.createLogicalView(scan, lockMode, engine); + } + + /** + * remove force index hint + */ + protected void removeForceIndex(TableScan scan) { + SqlNode indexNode = scan.getIndexNode(); + if (indexNode instanceof SqlNodeList) { + SqlNodeList sqlNodeList = (SqlNodeList) indexNode; + // use one new list in case of immutable list cannot be modified + SqlNodeList newList = new SqlNodeList(sqlNodeList.getParserPosition()); + boolean needReset = false; + + for (SqlNode node : sqlNodeList.getList()) { + if (isForceIndex(node)) { + needReset = true; + } else { + newList.add(node); } - if (GlobalIndexMeta.getColumnarIndexType(tableName, indexName, - schemaName, plannerContext.getExecutionContext()) == IndexType.PUBLISHED_COLUMNAR) { - final RelOptTable indexTable = catalog.getTableForMember(ImmutableList.of(schemaName, indexName)); - final LogicalTableScan columnarTableScan = - LogicalTableScan.create(scan.getCluster(), indexTable, scan.getHints(), null, - scan.getFlashback(), scan.getFlashbackOperator(), - null); - this.withIndexHint = true; - // remove force index for physical sql + } + if (needReset) { + if (newList.size() == 0) { scan.setIndexNode(null); - return Optional.of(new OSSTableScan(columnarTableScan, lockMode)); + } else { + scan.setIndexNode(newList); } + } + } + } + + private boolean isForceIndex(SqlNode node) { + return node instanceof SqlIndexHint && ((SqlIndexHint) node).forceIndex(); + } + + protected RelNode buildForceIndexByIndexHint(RelOptSchema catalog, TableScan scan, String schemaName, + TableMeta tMeta, + Engine engine) { + // get index hint + SqlCall indexHint = getIndexHint(scan); + if (indexHint == null) { + return null; + } + + List args = indexHint.getOperandList(); + String tablePart = args.get(1).toString(); + String indexPart = null; + if (args.size() > 2) { + indexPart = args.get(2).toString(); + } + if (indexPart == null) { + return buildForceIndex(catalog, scan, schemaName, tMeta, engine, tablePart); + } else { + return buildForceIndex(catalog, scan, schemaName, tMeta, engine, tablePart, indexPart); + } + } - final String unwrapped = GlobalIndexMeta - .getGsiWrappedName(tableName, indexName, schemaName, plannerContext.getExecutionContext()); - if (unwrapped != null) { - indexName = unwrapped; + private SqlCall getIndexHint(TableScan scan) { + SqlNodeList sqlNodes = scan.getHints(); + if (sqlNodes == null) { + return null; + } + for (SqlNode node : sqlNodes) { + if (node instanceof SqlCall) { + SqlCall call = (SqlCall) node; + if (call.getOperator().getName().equalsIgnoreCase("index")) { + if (call.getOperandList().size() < 2) { + // throw new IllegalArgumentException("wrong args num in index hint"); + return null; + } + return call; } - final IndexType indexType = GlobalIndexMeta - .getIndexType(tableName, indexName, schemaName, plannerContext.getExecutionContext()); - - switch (indexType) { - case PUBLISHED_GSI: - break; - case UNPUBLISHED_GSI: - // Gsi whose table not finished creating - case NONE: - // Gsi is removed but sql not updated or - scan.setIndexNode(null); - case LOCAL: - default: - return Optional.empty(); + } + } + return null; + } + + /** + * Constructs a RelNode with the specified forced index applied. + * + * @param catalog Catalog object + * @param scan Initial TableScan node + * @param schemaName Schema name + * @param tMeta Table metadata + * @param engine Execution engine + * @return RelNode with the enforced index + */ + protected RelNode buildForceIndexByForceIndex(RelOptSchema catalog, TableScan scan, String schemaName, + TableMeta tMeta, Engine engine) { + SqlIdentifier indexId = getForceIndex(scan); + if (indexId != null) { + this.withIndexHint = true; + String tablePart = indexId.names.get(0); + String indexPart = indexId.names.size() > 1 ? indexId.names.get(1) : null; + + if (indexPart == null) { + return buildForceIndex(catalog, scan, schemaName, tMeta, engine, tablePart); + } else { + return buildForceIndex(catalog, scan, schemaName, tMeta, engine, tablePart, indexPart); + } + } + return null; + } + + /** + * Builds a RelNode with the specified forced index applied. support gsi and main table local index + *

+ * if indexName is primary or a local index in main table, return a logical view for main table with the same index node + * if indexName is a gsi, return one gsi lookup node + * otherwise, return null + * + * @param catalog Catalog object + * @param scan Initial TableScan node + * @param schemaName Schema name + * @param tMeta Table metadata + * @param engine Execution engine + * @param indexName logical table index, might be a gsi or primary or local index + * @return RelNode with the enforced index + */ + AbstractRelNode buildForceIndex(RelOptSchema catalog, TableScan scan, String schemaName, TableMeta tMeta, + Engine engine, @NotNull String indexName) { + GsiMetaManager.GsiIndexMetaBean gsi = tMeta.findGlobalSecondaryIndexByName(indexName); + if (gsi == null) { + System.out.println("test"); + // force index table.local_index + IndexMeta localIndex = tMeta.findLocalIndexByName(indexName); + if (localIndex != null) { + hasLocalForceIndex = true; + scan.setIndexNode(buildForceIndex(localIndex.getPhysicalIndexName())); + return RelUtils.createLogicalView(scan, lockMode, engine); + } else { + return null; + } + } else { + if (gsi.columnarIndex) { + // forbid force CCI with delete + return this.sqlKind == SqlKind.DELETE && !this.getPlannerContext().getParamManager() + .getBoolean(ConnectionParams.ENABLE_DELETE_FORCE_CC_INDEX) ? null : + buildOSSTableScan(catalog, scan, schemaName, engine, gsi); + } else { + return buildLogicalTableLookup(catalog, scan, schemaName, engine, gsi, null); + } + } + } + + /** + * Builds a RelNode with the specified forced index applied. support gsi and its local index + *

+ * if gsiPart was PRIMARY, return main table logicalview with index node of lsi/primary identified by lsiPart. + * if gsiPart was a gsi, return gsi lookup node and the index scan node got the index node of lsi/primary identified by lsiPart. + *

+ * if any index(gsiPart or lsiPart) was not found, return null + * + * @param catalog Catalog object + * @param scan Initial TableScan node + * @param schemaName Schema name + * @param tMeta Table metadata + * @param engine Execution engine + * @param gsiPart gsi or primary + * @param lsiPart physical table index, might be a primary or local index + * @return RelNode with the enforced index + */ + private AbstractRelNode buildForceIndex(RelOptSchema catalog, TableScan scan, String schemaName, TableMeta tMeta, + Engine engine, @NotNull String gsiPart, + @NotNull String lsiPart) { + // try gsi.local + GsiMetaManager.GsiIndexMetaBean gsi = tMeta.findGlobalSecondaryIndexByName(gsiPart); + if (gsi != null) { + TableMeta gsiMeta = this.getPlannerContext().getExecutionContext().getSchemaManager(schemaName) + .getTable(gsi.indexTableName); + IndexMeta gsiLocalIndex = gsiMeta.findLocalIndexByName(lsiPart); + if (gsiLocalIndex == null) { + // error gsi local index doesn't exist + return null; + } else { + if (gsi.columnarIndex) { + // CCI should not reach here since CCI must not have local index + return null; + } else { + hasLocalForceIndex = true; + return buildLogicalTableLookup(catalog, scan, schemaName, engine, gsi, lsiPart); } + } + } - // remove force index for physical sql - scan.setIndexNode(null); - final LogicalView primary = RelUtils.createLogicalView(scan, lockMode, engine); - final RelOptTable indexTable = catalog.getTableForMember(ImmutableList.of(schemaName, indexName)); - - final LogicalTableScan indexTableScan = - LogicalTableScan.create(scan.getCluster(), indexTable, scan.getHints(), null, scan.getFlashback(), - scan.getFlashbackOperator(), null); - final LogicalIndexScan index = new LogicalIndexScan(indexTable, indexTableScan, this.lockMode); - this.withIndexHint = true; - - return Optional.of((RelNode) RelUtils.createTableLookup(primary, index, index.getTable())); - }) - // INDEX HINT - .orElseGet(() -> Optional.ofNullable(scan.getHints()) - .map(hints -> HintConverter - .convertCmd(hints, new ArrayList<>(), false, plannerContext.getExecutionContext()).cmdHintResult) - .flatMap(cmdHints -> cmdHints.stream() - .filter(hint -> hint instanceof HintCmdIndex) - .map(hint -> (HintCmdIndex) hint) - .filter(hint -> TStringUtil.equalsIgnoreCase(tableName, hint.tableNameLast())) - .filter(hint -> { - final String unwrapped = GlobalIndexMeta.getGsiWrappedName(hint.tableNameLast(), - hint.indexNameLast(), schemaName, plannerContext.getExecutionContext()); - return GlobalIndexMeta.isPublishedPrimaryAndIndex(hint.tableNameLast(), - null == unwrapped ? hint.indexNameLast() : unwrapped, - schemaName, plannerContext.getExecutionContext()); - }) - // If more than one index specified, choose first one only - .findFirst() - .map(hint -> { - final String unwrapped = GlobalIndexMeta.getGsiWrappedName(hint.tableNameLast(), - hint.indexNameLast(), schemaName, plannerContext.getExecutionContext()); - final List indexTableNames; - if (null == unwrapped) { - indexTableNames = hint.indexName.names; - } else { - indexTableNames = ImmutableList.of(schemaName, unwrapped); - } - final LogicalView primary = RelUtils.createLogicalView(scan, lockMode, engine); - final RelOptTable indexTable = catalog.getTableForMember(indexTableNames); - final LogicalTableScan indexTableScan = - LogicalTableScan.create(scan.getCluster(), indexTable, scan.getHints(), null, - scan.getFlashback(), scan.getFlashbackOperator(), null); - final LogicalIndexScan index = new LogicalIndexScan(indexTable, indexTableScan, this.lockMode); - this.withIndexHint = true; + // try primary.local index + if (GeneralUtil.isPrimary(gsiPart)) { + // try primary.local + IndexMeta primaryLocalIndex = tMeta.findLocalIndexByName(lsiPart); + if (primaryLocalIndex != null) { + hasLocalForceIndex = true; + scan.setIndexNode(buildForceIndex(primaryLocalIndex.getPhysicalIndexName())); + } else { + // local index were not found any match for tblPath + return null; + } + hasLocalForceIndex = true; + // force index(primary) equals force index(primary.primary) + LogicalView lv = RelUtils.createLogicalView(scan, lockMode, engine); + lv.setFromForceIndex(true); + return lv; + } + return null; + } + + /** + * Builds a LogicalTableLookup based on the provided components. + * + * @param catalog Catalog object + * @param scan Original table scan + * @param schemaName Schema name + * @param engine Execution engine + * @param gsi Global Secondary Index metadata + * @param localIndexPath Local index path (if any) + * @return A new LogicalTableLookup instance + */ + @NotNull + protected LogicalTableLookup buildLogicalTableLookup(RelOptSchema catalog, TableScan scan, String schemaName, + Engine engine, GsiMetaManager.GsiIndexMetaBean gsi, + String localIndexPath) { + // Create a logical view from the original table scan, and remove its index node + scan.setIndexNode(null); + LogicalView primary = RelUtils.createLogicalView(scan, lockMode, engine); + + // Obtain the index table and create a corresponding table scan + RelOptTable indexTable = catalog.getTableForMember(ImmutableList.of(schemaName, gsi.indexName)); + LogicalTableScan indexTableScan = LogicalTableScan.create(scan.getCluster(), + indexTable, + scan.getHints(), + StringUtils.isEmpty(localIndexPath) ? null : buildForceIndex(localIndexPath), + scan.getFlashback(), + scan.getFlashbackOperator(), + null); + + // Create index lookup scan node + final LogicalIndexScan index = new LogicalIndexScan(indexTable, indexTableScan, this.lockMode); + this.withIndexHint = true; + return RelUtils.createTableLookup(primary, index, index.getTable()); + } + + @NotNull + OSSTableScan buildOSSTableScan(RelOptSchema catalog, TableScan scan, String schemaName, Engine engine, + GsiMetaManager.GsiIndexMetaBean gsi) { + final RelOptTable indexTable = catalog.getTableForMember(ImmutableList.of(schemaName, gsi.indexName)); + final LogicalTableScan columnarTableScan = LogicalTableScan.create( + scan.getCluster(), + indexTable, + scan.getHints(), + null, + scan.getFlashback(), + scan.getFlashbackOperator(), + null + ); + this.withIndexHint = true; + this.existForceColumnar = true; + scan.setIndexNode(null); + return new OSSTableScan(columnarTableScan, this.lockMode); + } - return (RelNode) RelUtils.createTableLookup(primary, index, index.getTable()); - })) - .orElse(RelUtils.createLogicalView(scan, lockMode, engine))); + /** + * Constructs a SQL node list containing a force index hint for the specified local index path. + * + * @param localIndexPath The path of the local index to be forced in the query + * @return A SQL node list with the force index hint + */ + @NotNull + private SqlNodeList buildForceIndex(@NotNull String localIndexPath) { + return new SqlNodeList( + Collections.singletonList( + new SqlIndexHint( + SqlCharStringLiteral.createCharString("FORCE INDEX", ZERO), + null, + SqlNodeList.of(new SqlIdentifier(localIndexPath, ZERO)), + ZERO) + ), + ZERO + ); + } + + /** + * get force index info, or return null if not exists + * + * @param scan Original table scan + * @return force index info, null if there is no force index in table scan + */ + protected SqlIdentifier getForceIndex(TableScan scan) { + if (!(scan.getIndexNode() instanceof SqlNodeList)) { + return null; + } + + SqlNodeList indexNodes = (SqlNodeList) scan.getIndexNode(); + if (indexNodes == null || indexNodes.size() == 0) { + return null; + } + + // get first force index hint + SqlIndexHint sqlIndexHint = null; + for (SqlNode node : indexNodes) { + if (node instanceof SqlIndexHint && ((SqlIndexHint) node).forceIndex()) { + sqlIndexHint = (SqlIndexHint) node; + break; + } + } + + if (sqlIndexHint == null) { + return null; + } + + SqlNodeList indexList = sqlIndexHint.getIndexList(); + + if (indexList != null && + indexList.size() > 0 && + indexList.get(0) instanceof SqlIdentifier) { + return (SqlIdentifier) indexList.get(0); + } + + return null; } @Override @@ -687,6 +915,8 @@ public final RelNode visit(LogicalProject project) { this.existsWindow |= replaceTableScanInFilterSubQueryFinder.isExistsWindow(); this.existsNonPushDownFunc |= replaceTableScanInFilterSubQueryFinder.isExistsNonPushDownFunc(); this.existsOSSTable |= replaceTableScanInFilterSubQueryFinder.existsOSSTable(); + this.existForceColumnar |= replaceTableScanInFilterSubQueryFinder.isExistForceColumnar(); + this.allTableHaveColumnar &= replaceTableScanInFilterSubQueryFinder.isAllTableHaveColumnar(); return LogicalProject.create(logicalProject.getInput(0), rexNodeList, logicalProject.getRowType(), @@ -756,6 +986,8 @@ public RelNode visit(LogicalFilter filter) { this.containComplexExpression |= replaceTableScanInFilterSubQueryFinder.isContainComplexExpression(); this.existsNonPushDownFunc |= replaceTableScanInFilterSubQueryFinder.isExistsNonPushDownFunc(); this.existsOSSTable |= replaceTableScanInFilterSubQueryFinder.existsOSSTable(); + this.existForceColumnar |= replaceTableScanInFilterSubQueryFinder.isExistForceColumnar(); + this.allTableHaveColumnar &= replaceTableScanInFilterSubQueryFinder.isAllTableHaveColumnar(); this.existsWindow |= replaceTableScanInFilterSubQueryFinder.isExistsWindow(); return filter.copy(logicalFilter.getTraitSet(), logicalFilter.getInput(0), rexNode).setHints(filter.getHints()); } @@ -763,7 +995,7 @@ public RelNode visit(LogicalFilter filter) { @Override public final RelNode visit(RelNode other) { if ((other instanceof LogicalTableModify)) { - + this.allTableHaveColumnar = false; LogicalTableModify modify = (LogicalTableModify) super.visit(other); setShouldRemoveSchemaName(modify.getTable().getQualifiedName()); TableModify.Operation operation = modify.getOperation(); @@ -814,6 +1046,13 @@ public final RelNode visit(RelNode other) { logicalInsert.setModifyForeignKey(true); } + if (logicalInsert.isSourceSelect() && !this.plannerContext.getExecutionContext().getParamManager() + .getBoolean(ConnectionParams.ENABLE_INSERT_SELECT_WITH_FLASHBACK_PUSH_DOWN)) { + if (RelUtils.containFlashback(logicalInsert.getInput())) { + insertSelectWithFlashback = true; + } + } + } else { // UPDATE / DELETE // Currently we do not allow create GSI on broadcast or single table targetTableProperties = new HashMap<>(); @@ -1141,6 +1380,8 @@ private RelNode convertToLogicalDdlPlan(DDL ddl) { return LogicalAlterTableDropPartition.create(ddl); } else if (sqlAlterTable.getAlters().get(0) instanceof SqlAlterTableTruncatePartition) { return LogicalAlterTableTruncatePartition.create(ddl); + } else if (sqlAlterTable.getAlters().get(0) instanceof SqlAlterTableOptimizePartition) { + return LogicalAlterTableOptimizePartition.create(ddl); } else if (sqlAlterTable.getAlters().get(0) instanceof SqlAlterTableReorgPartition) { return LogicalAlterTableReorgPartition.create(ddl); } else if (sqlAlterTable.getAlters().get(0) instanceof SqlAlterTableModifyPartitionValues) { @@ -1229,6 +1470,9 @@ private RelNode convertToLogicalDdlPlan(DDL ddl) { } else if (ddl instanceof AlterTableGroupTruncatePartition) { return LogicalAlterTableGroupTruncatePartition.create(ddl); + } else if (ddl instanceof AlterTableGroupOptimizePartition) { + return LogicalAlterTableGroupOptimizePartition.create(ddl); + } else if (ddl instanceof AlterTableGroupReorgPartition) { return LogicalAlterTableGroupReorgPartition.create(ddl); @@ -1247,6 +1491,9 @@ private RelNode convertToLogicalDdlPlan(DDL ddl) { } else if (ddl instanceof AlterTableRepartition) { return LogicalAlterTableRepartition.create((AlterTableRepartition) ddl); + } else if (ddl instanceof AlterTableArchivePartition) { + return LogicalAlterTableArchivePartition.create((AlterTableArchivePartition) ddl); + } else if (ddl instanceof AlterTableGroupSplitPartitionByHotValue) { return LogicalAlterTableGroupSplitPartitionByHotValue.create(ddl); @@ -1605,6 +1852,10 @@ public boolean isModifyForeignKey() { return modifyForeignKey; } + public PlannerContext getPlannerContext() { + return plannerContext; + } + public static class ReplaceTableScanInFilterSubQueryFinder extends RexShuttle { private final PlannerContext plannerContext; @@ -1625,6 +1876,8 @@ public static class ReplaceTableScanInFilterSubQueryFinder extends RexShuttle { private LockMode lockMode = LockMode.UNDEF; private List schemaNames; private boolean existsOSSTable; + private boolean existForceColumnar = false; + private boolean allTableHaveColumnar = true; private boolean existsWindow = false; private Long allTableSingleTgId = null; @@ -1673,6 +1926,8 @@ public RexNode visitSubQuery(RexSubQuery subQuery) { this.allTableBroadcast = visitor.allTableBroadcast; this.allTableSingleNoBroadcast = visitor.allTableSingleNoBroadcast; this.existsOSSTable = visitor.existsOSSTable; + this.existForceColumnar |= visitor.existForceColumnar; + this.allTableHaveColumnar &= visitor.allTableHaveColumnar; this.allTableSingleTgId = visitor.allTableSingleTgId; this.existsNonPushDownFunc |= visitor.existsNonPushDownFunc; this.existsWindow |= visitor.existsWindow; @@ -1715,6 +1970,14 @@ public boolean existsOSSTable() { return existsOSSTable; } + public boolean isExistForceColumnar() { + return existForceColumnar; + } + + public boolean isAllTableHaveColumnar() { + return allTableHaveColumnar; + } + public boolean isAllTableBroadcast() { return allTableBroadcast; } @@ -1798,7 +2061,7 @@ public boolean existsCannotPushDown() { existsIntersect || existsMinus || existsCheckSum || existsUnpushableAgg || existsNonPushDownFunc || (modifyBroadcastTable && containUncertainValue) || existsCheckSumV2 || - existsUnPushedDynamicValues; + existsUnPushedDynamicValues || insertSelectWithFlashback; } public boolean isContainOnlineModifyColumnTable() { @@ -1820,6 +2083,15 @@ public boolean isModifyWithLimitOffset() { public boolean existsOSSTable() { return existsOSSTable; } + + public boolean isExistForceColumnar() { + return existForceColumnar; + } + + public boolean isAllTableHaveColumnar() { + return allTableHaveColumnar; + } + public boolean isExistsCheckSum() { return existsCheckSum; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/BaseDdlOperation.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/BaseDdlOperation.java index 12afc0fc1..19d967b19 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/BaseDdlOperation.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/BaseDdlOperation.java @@ -28,13 +28,13 @@ import com.alibaba.polardbx.druid.util.StringUtils; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.archive.CheckOSSArchiveUtil; import com.alibaba.polardbx.optimizer.config.table.SchemaManager; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.CursorMeta; import com.alibaba.polardbx.optimizer.core.dialect.DbType; import com.alibaba.polardbx.optimizer.core.rel.BaseQueryOperation; -import com.alibaba.polardbx.optimizer.archive.CheckOSSArchiveUtil; import com.alibaba.polardbx.optimizer.exception.TableNotFoundException; import com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter; import com.alibaba.polardbx.optimizer.tablegroup.AlterTablePartitionHelper; @@ -48,9 +48,7 @@ import org.apache.calcite.rel.ddl.AlterTable; import org.apache.calcite.rel.externalize.RelDrdsWriter; import org.apache.calcite.rel.type.RelDataType; -import org.apache.calcite.sql.SqlCreateIndex; import org.apache.calcite.sql.SqlDdl; -import org.apache.calcite.sql.SqlDropIndex; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlNode; @@ -373,6 +371,13 @@ protected RelDataType deriveRowType() { return relDdl.getRowType(); } + /** + * Check if ddl operation is allowed to perform on cci table, default is false + */ + public boolean isSupportedByCci(ExecutionContext ec) { + return false; + } + /** * Check if ddl operation involves file storage. * 1. ddl on a file storage table, and the table is bound to an innodb table, reject the ddl @@ -412,6 +417,21 @@ public boolean checkIfFileStorage(ExecutionContext executionContext) { return Engine.isFileStore(tableMeta.getEngine()); } + /** + * Check if ddl operation on cci table + * + * @return true if ddl on cci table + */ + public boolean isCciTable(ExecutionContext executionContext) { + String schemaName = getSchemaName(); + String logicalTableName = getTableName(); + TableMeta tableMeta = executionContext.getSchemaManager(schemaName).getTableWithNull(logicalTableName); + if (tableMeta == null) { + return false; + } + return tableMeta.isColumnar(); + } + /** * Check if ddl operation on innodb binding to file storage * diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTable.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTable.java index e4da32289..0a27caf84 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTable.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTable.java @@ -20,8 +20,10 @@ import com.alibaba.polardbx.common.TddlConstants; import com.alibaba.polardbx.common.charset.CharsetName; import com.alibaba.polardbx.common.charset.CollationName; +import com.alibaba.polardbx.common.constants.SequenceAttribute; import com.alibaba.polardbx.common.ddl.Attribute; import com.alibaba.polardbx.common.ddl.foreignkey.ForeignKeyData; +import com.alibaba.polardbx.common.exception.NotSupportException; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.properties.ConnectionParams; @@ -69,8 +71,10 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.RenameGlobalIndexPreparedData; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.common.LocalPartitionDefinitionInfo; +import com.alibaba.polardbx.optimizer.sequence.SequenceManagerProxy; import com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter; import com.alibaba.polardbx.optimizer.tablegroup.TableGroupInfoManager; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; import com.alibaba.polardbx.optimizer.utils.ForeignKeyUtils; import com.alibaba.polardbx.optimizer.utils.MetaUtils; import com.alibaba.polardbx.optimizer.utils.PlannerUtils; @@ -93,9 +97,11 @@ import org.apache.calcite.sql.SqlAlterTableDropFile; import org.apache.calcite.sql.SqlAlterTableDropIndex; import org.apache.calcite.sql.SqlAlterTableExchangePartition; +import org.apache.calcite.sql.SqlAlterTableModifyTtlOptions; import org.apache.calcite.sql.SqlAlterTablePartitionKey; import org.apache.calcite.sql.SqlAlterTablePurgeBeforeTimeStamp; import org.apache.calcite.sql.SqlAlterTableRemoveLocalPartition; +import org.apache.calcite.sql.SqlAlterTableRemoveTtlOptions; import org.apache.calcite.sql.SqlAlterTableRenameIndex; import org.apache.calcite.sql.SqlAlterTableRepartitionLocalPartition; import org.apache.calcite.sql.SqlBinaryStringLiteral; @@ -142,6 +148,7 @@ import static com.alibaba.polardbx.common.TddlConstants.AUTO_LOCAL_INDEX_PREFIX; import static com.alibaba.polardbx.common.TddlConstants.IMPLICIT_COL_NAME; +import static com.alibaba.polardbx.common.constants.SequenceAttribute.AUTO_SEQ_PREFIX; import static com.alibaba.polardbx.common.ddl.newengine.DdlConstants.EMPTY_CONTENT; import static com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter.unwrapGsiName; import static com.alibaba.polardbx.optimizer.utils.ForeignKeyUtils.PARTITION_FK_SUB_JOB; @@ -215,6 +222,36 @@ public boolean isExpireLocalPartition() { return sqlAlterTable != null && sqlAlterTable.isExpireLocalPartition(); } + public boolean isCleanupExpiredData() { + return sqlAlterTable != null && sqlAlterTable.isCleanupExpiredData(); + } + + public boolean isModifyTtlOptions() { + if (sqlAlterTable != null) { + List sqlAlterSpecifications = sqlAlterTable.getAlters(); + if (!sqlAlterSpecifications.isEmpty() && sqlAlterSpecifications.size() == 1) { + SqlAlterSpecification alterSpec = sqlAlterSpecifications.get(0); + if (alterSpec instanceof SqlAlterTableModifyTtlOptions) { + return true; + } + } + } + return false; + } + + public boolean isRemoveTtlOptions() { + if (sqlAlterTable != null) { + List sqlAlterSpecifications = sqlAlterTable.getAlters(); + if (!sqlAlterSpecifications.isEmpty() && sqlAlterSpecifications.size() == 1) { + SqlAlterSpecification alterSpec = sqlAlterSpecifications.get(0); + if (alterSpec instanceof SqlAlterTableRemoveTtlOptions) { + return true; + } + } + } + return false; + } + public boolean isDropFile() { return sqlAlterTable != null && sqlAlterTable.isDropFile(); } @@ -352,6 +389,7 @@ public boolean isSupportedByBindFileStorage() { if (skipCheckForFileStorage()) { return true; } + if (CheckOSSArchiveUtil.withoutOldFileStorage(schemaName, tableName)) { if (supportedCommonByFileStorage()) { return true; @@ -374,7 +412,25 @@ public boolean supportedCommonByFileStorage() { || isDropFile() || isAllocateLocalPartition() || isExpireLocalPartition(); } + /** + * Check if ddl od ttl-tbl/local-part-tbl should be skipped by the archive-table + */ private boolean skipCheckForFileStorage() { + + /** + * Comh here, that means the schemaName.tableName + * must be a ttl-table with binding archive table + */ + if (!sqlAlterTable.getAlters().isEmpty()) { + SqlAlterSpecification alterModifyTtlDefAst = sqlAlterTable.getAlters().get(0); + if (alterModifyTtlDefAst instanceof SqlAlterTableModifyTtlOptions) { + if (sqlAlterTable.getAlters().size() > 1) { + throw new NotSupportException("Not support multi alter on modify ttl definition"); + } + return true; + } + } + return isRepartitionLocalPartition(); } @@ -1792,10 +1848,10 @@ private AlterTablePreparedData prepareAlterTableData(String schemaName, String t droppedForeignKeys.add(dropForeignKey.getIndexName().getLastName()); } else if (alterItem instanceof SqlAddIndex) { SqlAddIndex addIndex = (SqlAddIndex) alterItem; - String firstColumnName = addIndex.getIndexDef().getColumns().get(0).getColumnNameStr(); if (addIndex.getIndexName() != null) { addedIndexes.add(addIndex.getIndexName().getLastName()); } else { + String firstColumnName = addIndex.getIndexDef().getColumns().get(0).getColumnNameStr(); // If user doesn't specify an index name, we use the first column name as reference. addedIndexesWithoutNames.add(firstColumnName); } @@ -2235,6 +2291,13 @@ private AlterTablePreparedData prepareAlterTableData(String schemaName, String t return preparedData; } + public static boolean hasSequence(String schemaName, String sourceTableName) { + String seqName = AUTO_SEQ_PREFIX + sourceTableName; + SequenceAttribute.Type existingSeqType = + SequenceManagerProxy.getInstance().checkIfExists(schemaName, seqName); + return existingSeqType != SequenceAttribute.Type.NA; + } + public boolean validateOnlineModify(ExecutionContext ec, boolean forceOmc) { final ParamManager paramManager = ec.getParamManager(); if (!(paramManager.getBoolean(ConnectionParams.FORCE_USING_OMC) || forceOmc)) { @@ -2313,6 +2376,12 @@ public boolean validateOnlineModify(ExecutionContext ec, boolean forceOmc) { "Do not support insert after the same column"); } } + + if (modifyColumn.getColDef().isAutoIncrement() && !hasSequence(schemaName, tableName)) { + throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, String.format( + "Missing sequence for auto increment column. Please try to execute this command first: \"CREATE SEQUENCE `AUTO_SEQ_%s`\"", + tableName)); + } } else if (alterType == SqlKind.CHANGE_COLUMN) { SqlChangeColumn changeColumn = (SqlChangeColumn) alterItem; columnName = changeColumn.getOldName().getLastName(); @@ -2350,6 +2419,12 @@ public boolean validateOnlineModify(ExecutionContext ec, boolean forceOmc) { } } + if (changeColumn.getColDef().isAutoIncrement() && !hasSequence(schemaName, tableName)) { + throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, String.format( + "Missing sequence for auto increment column. Please try to execute this command first: \"CREATE SEQUENCE `AUTO_SEQ_%s`\"", + tableName)); + } + String newColumnName = changeColumn.getNewName().getLastName(); if (newColumnName.equalsIgnoreCase(columnName)) { // Rewrite to modify @@ -2385,6 +2460,11 @@ public boolean validateOnlineModify(ExecutionContext ec, boolean forceOmc) { throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, "Do not support add the column with generated expr when using online modify column"); } + if (sqlAddColumn.getColDef().isAutoIncrement() && !hasSequence(schemaName, tableName)) { + throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, String.format( + "Missing sequence for auto increment column. Please try to execute this command first: \"CREATE SEQUENCE `AUTO_SEQ_%s`\"", + tableName)); + } continue; } else if (alterType == SqlKind.DROP_COLUMN) { SqlDropColumn sqlDropColumn = (SqlDropColumn) alterItem; @@ -2900,10 +2980,10 @@ public void validateColumnar() { } // forbid multiple statements for now - if (getSqlAlterTable().getAlters().size() > 1) { - throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, - "Do not support multiple ALTER TABLE statements on table with clustered columnar index"); - } +// if (getSqlAlterTable().getAlters().size() > 1) { +// throw new TddlRuntimeException(ErrorCode.ERR_OPTIMIZER, +// "Do not support multiple ALTER TABLE statements on table with clustered columnar index"); +// } for (SqlAlterSpecification alterItem : getSqlAlterTable().getAlters()) { SqlKind alterType = alterItem.getKind(); @@ -3382,4 +3462,9 @@ public enum AlterColumnSpecification { AlterColumnComment, // May set to null and this flag is not set. Just push down this alter. AlterColumnOrder // Should alter order in metaDB first. } + + public boolean needRefreshArcTblView(ExecutionContext ec) { + boolean needFreshView = TtlUtil.checkIfNeedRefreshViewForArcTbl(this.alterTablePreparedData, ec); + return needFreshView; + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableAddPartition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableAddPartition.java index 05b5560b4..4c41cb9db 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableAddPartition.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableAddPartition.java @@ -18,15 +18,15 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; -import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; -import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.gms.tablegroup.PartitionGroupRecord; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.gms.topology.GroupDetailInfoExRecord; import com.alibaba.polardbx.gms.util.GroupInfoUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableAddPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupAddPartitionPreparedData; @@ -61,6 +61,20 @@ public LogicalAlterTableAddPartition(DDL ddl, boolean notIncludeGsiName) { assert notIncludeGsiName; } + @Override + public boolean isSupportedByCci(ExecutionContext ec) { + String schemaName = this.schemaName; + String tblName = Util.last(((SqlIdentifier) relDdl.getTableName()).names); + + if (DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { + TableMeta tblMeta = ec.getSchemaManager(schemaName).getTable(tblName); + if (tblMeta.isColumnar()) { + return true; + } + } + return false; + } + @Override public boolean isSupportedByFileStorage() { return false; @@ -158,4 +172,10 @@ public static LogicalAlterTableAddPartition create(DDL ddl) { return new LogicalAlterTableAddPartition(ddl); } + public void setDdlVersionId(Long ddlVersionId) { + if (null != getPreparedData()) { + getPreparedData().setDdlVersionId(ddlVersionId); + } + } + } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableArchivePartition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableArchivePartition.java new file mode 100644 index 000000000..1d1967215 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableArchivePartition.java @@ -0,0 +1,163 @@ +package com.alibaba.polardbx.optimizer.core.rel.ddl; + +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.archive.CheckOSSArchiveUtil; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableArchivePartitionPreparedData; +import com.alibaba.polardbx.optimizer.partition.PartSpecSearcher; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; +import com.alibaba.polardbx.optimizer.partition.common.PartKeyLevel; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import org.apache.calcite.rel.ddl.AlterTableArchivePartition; +import org.apache.calcite.sql.SqlAlterTableArchivePartition; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.TreeSet; + +/** + * @author wumu + */ +public class LogicalAlterTableArchivePartition extends LogicalTableOperation { + private SqlAlterTableArchivePartition sqlAlterTableArchivePartition; + + protected AlterTableArchivePartitionPreparedData preparedData; + + public LogicalAlterTableArchivePartition(AlterTableArchivePartition archivePartition) { + super(archivePartition); + this.sqlAlterTableArchivePartition = (SqlAlterTableArchivePartition) relDdl.sqlNode; + } + + @Override + public boolean isSupportedByFileStorage() { + return true; + } + + @Override + public boolean isSupportedByBindFileStorage() { + return true; + } + + public static LogicalAlterTableArchivePartition create(AlterTableArchivePartition archivePartition) { + return new LogicalAlterTableArchivePartition(archivePartition); + } + + public void prepare() { + SqlAlterTableArchivePartition alterTableArchivePartition = + (SqlAlterTableArchivePartition) this.getNativeSqlNode(); + + preparedData = new AlterTableArchivePartitionPreparedData(); + + Optional> primaryTable = CheckOSSArchiveUtil.getTTLSource(schemaName, tableName); + TableMeta primaryTableMeta = null; + + if (primaryTable.isPresent()) { + String primaryTableSchema = GeneralUtil.coalesce(primaryTable.get().getKey(), schemaName); + String primaryTableName = primaryTable.get().getValue(); + + primaryTableMeta = + OptimizerContext.getContext(primaryTableSchema).getLatestSchemaManager().getTable(primaryTableName); + if (primaryTableMeta == null) { + throw new TddlNestableRuntimeException(String.format( + "The ttl table bound to the oss table %s.%s does not exist.", schemaName, tableName)); + } + + TtlDefinitionInfo ttlDefinitionInfo = primaryTableMeta.getTtlDefinitionInfo(); + if (ttlDefinitionInfo == null) { + throw new TddlNestableRuntimeException(String.format( + "The ttl table bound to the oss table %s.%s does not exist.", schemaName, tableName)); + } + + final String archiveTmpTableName = ttlDefinitionInfo.getTmpTableName(); + final String archiveTmpTableSchema = + GeneralUtil.coalesce(ttlDefinitionInfo.getTmpTableSchema(), schemaName); + + preparedData.setPrimaryTableSchema(primaryTableSchema); + preparedData.setPrimaryTableName(primaryTableName); + preparedData.setTmpTableSchema(archiveTmpTableSchema); + preparedData.setTmpTableName(archiveTmpTableName); + } else { + throw new TddlNestableRuntimeException(String.format( + "The ttl table bound to the oss table %s.%s does not exist.", schemaName, tableName)); + } + + boolean isSubpartition = alterTableArchivePartition.isSubPartitionsArchive(); + if (isSubpartition) { + throw new TddlNestableRuntimeException(String.format( + "Subpartition is not support on this operation")); + } + + TtlDefinitionInfo ttlDefinitionInfo = primaryTableMeta.getTtlDefinitionInfo(); + String archiveTmpTableName = ttlDefinitionInfo.getTmpTableName(); + String archiveTmpTableSchema = ttlDefinitionInfo.getTmpTableSchema(); + TableMeta arcTmpTableMeta = + OptimizerContext.getContext(archiveTmpTableSchema).getLatestSchemaManager().getTable(archiveTmpTableName); + PartitionInfo arcTmpTablePartInfo = arcTmpTableMeta.getPartitionInfo(); + Set partitionNames = alterTableArchivePartition.getTargetPartitions(); + PartSpecSearcher partSpecSearcher = arcTmpTablePartInfo.getPartSpecSearcher(); + for (String partName : partitionNames) { + PartitionSpec spec = partSpecSearcher.getPartSpecByPartName(partName); + if (spec.getPartLevel() == PartKeyLevel.SUBPARTITION_KEY) { + throw new TddlNestableRuntimeException(String.format( + "the subpartition `%s` is not allowed on this operation", partName)); + } + } + + List realPartitionNames = new ArrayList<>(); + if (isSubpartition) { + realPartitionNames.addAll(partitionNames); + } else { + realPartitionNames.addAll(getArchivePartNamesByFirstPartNames(partitionNames)); + } + preparedData.setPhyPartitionNames(realPartitionNames); + List firstPartNames = new ArrayList<>(); + firstPartNames.addAll(partitionNames); + preparedData.setFirstLevelPartitionNames(firstPartNames); + + } + + public AlterTableArchivePartitionPreparedData getPreparedData() { + return preparedData; + } + + public SqlAlterTableArchivePartition getSqlAlterTableArchivePartition() { + return sqlAlterTableArchivePartition; + } + + private List getArchivePartNamesByFirstPartNames(Set partNames) { + final TableMeta ossTableMeta = + OptimizerContext.getContext(schemaName).getLatestSchemaManager().getTable(tableName); + + if (ossTableMeta == null) { + throw new TddlNestableRuntimeException(String.format( + "The oss table %s.%s does not exist.", schemaName, tableName)); + } + + PartitionInfo partitionInfo = ossTableMeta.getPartitionInfo(); + + Set rs = new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + for (String partName : partNames) { + PartitionSpec ps = partitionInfo.getPartSpecSearcher().getPartSpecByPartName(partName); + if (ps == null) { + throw new TddlNestableRuntimeException(String.format( + "The archive partition %s does not exists", partName)); + } + List subParts = ps.getSubPartitions(); + if (subParts != null) { + for (PartitionSpec subPart : subParts) { + rs.add(subPart.getName()); + } + } else { + rs.add(partName); + } + } + return new ArrayList<>(rs); + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableDropPartition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableDropPartition.java index a62408802..b6d342dce 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableDropPartition.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableDropPartition.java @@ -19,14 +19,15 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.Pair; -import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.gms.tablegroup.PartitionGroupRecord; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.gms.topology.GroupDetailInfoExRecord; import com.alibaba.polardbx.gms.util.GroupInfoUtil; import com.alibaba.polardbx.gms.util.PartitionNameUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableDropPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupDropPartitionPreparedData; @@ -64,6 +65,20 @@ public LogicalAlterTableDropPartition(DDL ddl, boolean notIncludeGsiName) { assert notIncludeGsiName; } + @Override + public boolean isSupportedByCci(ExecutionContext ec) { + String schemaName = this.schemaName; + String tblName = Util.last(((SqlIdentifier) relDdl.getTableName()).names); + + if (DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { + TableMeta tblMeta = ec.getSchemaManager(schemaName).getTable(tblName); + if (tblMeta.isColumnar()) { + return true; + } + } + return false; + } + @Override public boolean isSupportedByFileStorage() { return false; @@ -102,34 +117,21 @@ public void preparedData(ExecutionContext ec) { preparedData.setWithHint(targetTablesHintCache != null); preparedData.setTargetGroupDetailInfoExRecords(targetGroupDetailInfoExRecords); - List oldPartitionNames = - getDroppingPartitionNames(sqlAlterTableDropPartition, partitionInfo, preparedData); + List oldPartitionNames = new ArrayList<>(); + for (SqlNode sqlNode : sqlAlterTableDropPartition.getPartitionNames()) { + final String origName = ((SqlIdentifier) sqlNode).getLastName().toLowerCase(); + oldPartitionNames.add(origName); + } preparedData.setOldPartitionNames(oldPartitionNames); - preparedData.prepareInvisiblePartitionGroup(sqlAlterTableDropPartition.isSubPartition()); - - List newPartitionGroups = preparedData.getInvisiblePartitionGroups(); - - List newPartitionNames = - preparedData.getInvisiblePartitionGroups().stream().map(o -> o.getPartition_name()) - .collect(Collectors.toList()); - - preparedData.setNewPartitionNames(newPartitionNames); + preparedData.setOperateOnSubPartition(sqlAlterTableDropPartition.isSubPartition()); preparedData.setTaskType(ComplexTaskMetaManager.ComplexTaskType.DROP_PARTITION); preparedData.setSourceSql(((SqlAlterTable) alterTable.getSqlNode()).getSourceSql()); preparedData.setTableName(logicalTableName); preparedData.setTargetImplicitTableGroupName(sqlAlterTable.getTargetImplicitTableGroupName()); if (preparedData.needFindCandidateTableGroup()) { - Map> mockOrderedTargetTableLocations = - new TreeMap<>(String::compareToIgnoreCase); - for (int i = 0; i < newPartitionNames.size(); i++) { - String mockTableName = ""; - mockOrderedTargetTableLocations.put(newPartitionGroups.get(i).partition_name, new Pair<>(mockTableName, - GroupInfoUtil.buildGroupNameFromPhysicalDb(newPartitionGroups.get(i).partition_name))); - } - PartitionInfo newPartInfo = AlterTableGroupSnapShotUtils .getNewPartitionInfo( preparedData, @@ -141,7 +143,7 @@ public void preparedData(ExecutionContext ec) { preparedData.getTableGroupName(), null, preparedData.getInvisiblePartitionGroups(), - mockOrderedTargetTableLocations, + null, ec); int flag = PartitionInfoUtil.COMPARE_EXISTS_PART_LOCATION; @@ -291,4 +293,10 @@ public static LogicalAlterTableDropPartition create(DDL ddl) { return new LogicalAlterTableDropPartition(ddl); } + public void setDdlVersionId(Long ddlVersionId) { + if (null != getPreparedData()) { + getPreparedData().setDdlVersionId(ddlVersionId); + } + } + } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableGroupDropPartition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableGroupDropPartition.java index 666e07f02..4a5783295 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableGroupDropPartition.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableGroupDropPartition.java @@ -35,7 +35,10 @@ import org.apache.calcite.rel.ddl.AlterTableGroupDropPartition; import org.apache.calcite.sql.SqlAlterTableDropPartition; import org.apache.calcite.sql.SqlAlterTableGroup; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlNode; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -69,18 +72,15 @@ public void preparedData(ExecutionContext ec) { preparedData.setWithHint(targetTablesHintCache != null); preparedData.setTargetGroupDetailInfoExRecords(targetGroupDetailInfoExRecords); - List oldPartitionNames = - getDroppingPartitionNames(sqlAlterTableDropPartition, partitionInfo, preparedData); + List oldPartitionNames = new ArrayList<>(); + for (SqlNode sqlNode : sqlAlterTableDropPartition.getPartitionNames()) { + final String origName = ((SqlIdentifier) sqlNode).getLastName().toLowerCase(); + oldPartitionNames.add(origName); + } preparedData.setOldPartitionNames(oldPartitionNames); - preparedData.prepareInvisiblePartitionGroup(sqlAlterTableDropPartition.isSubPartition()); - - List newPartitionNames = - preparedData.getInvisiblePartitionGroups().stream().map(o -> o.getPartition_name()) - .collect(Collectors.toList()); - - preparedData.setNewPartitionNames(newPartitionNames); + preparedData.setOperateOnSubPartition(sqlAlterTableDropPartition.isSubPartition()); preparedData.setTaskType(ComplexTaskMetaManager.ComplexTaskType.DROP_PARTITION); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableGroupOptimizePartition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableGroupOptimizePartition.java new file mode 100644 index 000000000..1f0d0e840 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableGroupOptimizePartition.java @@ -0,0 +1,70 @@ +package com.alibaba.polardbx.optimizer.core.rel.ddl; + +import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.gms.topology.GroupDetailInfoExRecord; +import com.alibaba.polardbx.gms.util.TableGroupNameUtil; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupOptimizePartitionPreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupTruncatePartitionPreparedData; +import com.alibaba.polardbx.optimizer.locality.LocalityInfoUtils; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.tablegroup.AlterTablePartitionHelper; +import org.apache.calcite.rel.core.DDL; +import org.apache.calcite.rel.ddl.AlterTableGroupOptimizePartition; +import org.apache.calcite.rel.ddl.AlterTableGroupTruncatePartition; +import org.apache.calcite.sql.SqlAlterTableGroup; +import org.apache.calcite.sql.SqlAlterTableOptimizePartition; +import org.apache.calcite.sql.SqlAlterTableTruncatePartition; + +import java.util.List; +import java.util.Set; + +public class LogicalAlterTableGroupOptimizePartition extends LogicalAlterTableOptimizePartition { + + public LogicalAlterTableGroupOptimizePartition(DDL ddl) { + super(ddl, true); + } + + public void prepareData(ExecutionContext executionContext) { + AlterTableGroupOptimizePartition alterTableGroupOptimizePartition = (AlterTableGroupOptimizePartition) relDdl; + SqlAlterTableGroup sqlAlterTableGroup = (SqlAlterTableGroup) alterTableGroupOptimizePartition.getAst(); + + SqlAlterTableOptimizePartition sqlAlterTableOptimizePartition = + (SqlAlterTableOptimizePartition) sqlAlterTableGroup.getAlters().get(0); + + String tableGroupName = alterTableGroupOptimizePartition.getTableGroupName(); + + TableGroupConfig tableGroupConfig = + OptimizerContext.getContext(null).getTableGroupInfoManager().getTableGroupConfigByName(tableGroupName); + String firstTableInGroup = tableGroupConfig.getAllTables().get(0); + PartitionInfo partitionInfo = + executionContext.getSchemaManager().getTable(firstTableInGroup).getPartitionInfo(); + + List targetGroupDetailInfoExRecords = + LocalityInfoUtils.getAllowedGroupInfoOfTableGroup(schemaName, tableGroupName); + + Set actualPartitionNames = + getOptimizingPartitionNames(sqlAlterTableOptimizePartition, partitionInfo, tableGroupConfig); + + preparedData = new AlterTableGroupOptimizePartitionPreparedData(); + preparedData.setSchemaName(schemaName); + preparedData.setTableGroupName(tableGroupName); + preparedData.setWithHint(targetTablesHintCache != null); + preparedData.setTargetGroupDetailInfoExRecords(targetGroupDetailInfoExRecords); + preparedData.setOptimizePartitionNames(actualPartitionNames); + } + + public static LogicalAlterTableGroupOptimizePartition create(DDL ddl) { + return new LogicalAlterTableGroupOptimizePartition(AlterTablePartitionHelper.fixAlterTableGroupDdlIfNeed(ddl)); + } + + @Override + public boolean checkIfFileStorage(ExecutionContext executionContext) { + final AlterTableGroupTruncatePartition alterTableGroupTruncatePartition = + (AlterTableGroupTruncatePartition) relDdl; + final String tableGroupName = alterTableGroupTruncatePartition.getTableGroupName(); + + return TableGroupNameUtil.isFileStorageTg(tableGroupName); + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableMergePartition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableMergePartition.java index 49839bf74..92f2b34b4 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableMergePartition.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableMergePartition.java @@ -19,17 +19,18 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.Pair; -import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.gms.locality.LocalityDesc; import com.alibaba.polardbx.gms.tablegroup.PartitionGroupRecord; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.tablegroup.TableGroupLocation; import com.alibaba.polardbx.gms.tablegroup.TableGroupRecord; +import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.gms.topology.GroupDetailInfoExRecord; import com.alibaba.polardbx.gms.util.GroupInfoUtil; import com.alibaba.polardbx.gms.util.PartitionNameUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupMergePartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableMergePartitionPreparedData; @@ -50,7 +51,6 @@ import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -72,6 +72,20 @@ public LogicalAlterTableMergePartition(DDL ddl, boolean notIncludeGsiName) { assert notIncludeGsiName; } + @Override + public boolean isSupportedByCci(ExecutionContext ec) { + String schemaName = this.schemaName; + String tblName = Util.last(((SqlIdentifier) relDdl.getTableName()).names); + + if (DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { + TableMeta tblMeta = ec.getSchemaManager(schemaName).getTable(tblName); + if (tblMeta.isColumnar()) { + return true; + } + } + return false; + } + @Override public boolean isSupportedByFileStorage() { return false; @@ -256,4 +270,9 @@ public static LogicalAlterTableMergePartition create(DDL ddl) { return new LogicalAlterTableMergePartition(ddl); } + public void setDdlVersionId(Long ddlVersionId) { + if (null != getPreparedData()) { + getPreparedData().setDdlVersionId(ddlVersionId); + } + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableModifyPartition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableModifyPartition.java index 2dbcbb04e..9ce7c57e8 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableModifyPartition.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableModifyPartition.java @@ -19,17 +19,16 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.CaseInsensitive; -import com.alibaba.polardbx.common.exception.TddlRuntimeException; -import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.Pair; -import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.gms.tablegroup.PartitionGroupRecord; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.gms.topology.GroupDetailInfoExRecord; import com.alibaba.polardbx.gms.util.GroupInfoUtil; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupModifyPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableModifyPartitionPreparedData; @@ -42,7 +41,6 @@ import org.apache.calcite.rel.ddl.AlterTable; import org.apache.calcite.sql.SqlAlterTable; import org.apache.calcite.sql.SqlAlterTableModifyPartitionValues; -import org.apache.calcite.sql.SqlAlterTableMovePartition; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlPartition; import org.apache.calcite.sql.SqlSubPartition; @@ -70,6 +68,20 @@ public LogicalAlterTableModifyPartition(DDL ddl, boolean notIncludeGsiName) { assert notIncludeGsiName; } + @Override + public boolean isSupportedByCci(ExecutionContext ec) { + String schemaName = this.schemaName; + String tblName = Util.last(((SqlIdentifier) relDdl.getTableName()).names); + + if (DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { + TableMeta tblMeta = ec.getSchemaManager(schemaName).getTable(tblName); + if (tblMeta.isColumnar()) { + return true; + } + } + return false; + } + @Override public boolean isSupportedByFileStorage() { return false; @@ -263,4 +275,9 @@ public static LogicalAlterTableModifyPartition create(DDL ddl) { return new LogicalAlterTableModifyPartition(ddl); } + public void setDdlVersionId(Long ddlVersionId) { + if (null != getPreparedData()) { + getPreparedData().setDdlVersionId(ddlVersionId); + } + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableOptimizePartition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableOptimizePartition.java new file mode 100644 index 000000000..da4d50493 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableOptimizePartition.java @@ -0,0 +1,127 @@ +package com.alibaba.polardbx.optimizer.core.rel.ddl; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.gms.tablegroup.PartitionGroupRecord; +import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.gms.topology.GroupDetailInfoExRecord; +import com.alibaba.polardbx.gms.util.GroupInfoUtil; +import com.alibaba.polardbx.gms.util.PartitionNameUtil; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableDropPartitionPreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupDropPartitionPreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupOptimizePartitionPreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupTruncatePartitionPreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableOptimizePartitionPreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableTruncatePartitionPreparedData; +import com.alibaba.polardbx.optimizer.locality.LocalityInfoUtils; +import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionInfoUtil; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; +import com.alibaba.polardbx.optimizer.tablegroup.AlterTableGroupSnapShotUtils; +import org.apache.calcite.rel.core.DDL; +import org.apache.calcite.rel.ddl.AlterTable; +import org.apache.calcite.sql.SqlAlterTable; +import org.apache.calcite.sql.SqlAlterTableDropPartition; +import org.apache.calcite.sql.SqlAlterTableOptimizePartition; +import org.apache.calcite.sql.SqlAlterTableTruncatePartition; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.util.Util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.stream.Collectors; + +/** + * @author chenghui.lch + */ +public class LogicalAlterTableOptimizePartition extends BaseDdlOperation { + + protected AlterTableGroupOptimizePartitionPreparedData preparedData; + + public LogicalAlterTableOptimizePartition(DDL ddl) { + super(ddl, ((SqlAlterTable) (ddl.getSqlNode())).getObjectNames()); + } + + public LogicalAlterTableOptimizePartition(DDL ddl, boolean notIncludeGsiName) { + super(ddl); + assert notIncludeGsiName; + } + + public void prepareData() { + AlterTable alterTable = (AlterTable) relDdl; + SqlAlterTable sqlAlterTable = (SqlAlterTable) alterTable.getSqlNode(); + + SqlAlterTableOptimizePartition sqlAlterTableOptimizePartition = + (SqlAlterTableOptimizePartition) sqlAlterTable.getAlters().get(0); + + String logicalTableName = Util.last(((SqlIdentifier) alterTable.getTableName()).names); + + OptimizerContext optimizerContext = OptimizerContext.getContext(schemaName); + + TableMeta tableMeta = optimizerContext.getLatestSchemaManager().getTable(logicalTableName); + + PartitionInfo partitionInfo = optimizerContext.getPartitionInfoManager().getPartitionInfo(logicalTableName); + + TableGroupConfig tableGroupConfig = + optimizerContext.getTableGroupInfoManager().getTableGroupConfigById(partitionInfo.getTableGroupId()); + + String tableGroupName = tableGroupConfig.getTableGroupRecord().getTg_name(); + + Set actualPartitionNames = + getOptimizingPartitionNames(sqlAlterTableOptimizePartition, partitionInfo, tableGroupConfig); + + preparedData = new AlterTableOptimizePartitionPreparedData(); + preparedData.setSchemaName(schemaName); + preparedData.setTableName(logicalTableName); + preparedData.setTableVersion(tableMeta.getVersion()); + preparedData.setTableGroupName(tableGroupName); + preparedData.setWithHint(targetTablesHintCache != null); + preparedData.setSourceSql(((SqlAlterTable) alterTable.getSqlNode()).getSourceSql()); + preparedData.setOptimizePartitionNames(actualPartitionNames); + } + + @Override + public boolean isSupportedByFileStorage() { + return false; + } + + @Override + public boolean isSupportedByBindFileStorage() { + return true; + } + + protected Set getOptimizingPartitionNames(SqlAlterTableOptimizePartition sqlAlterTableOptimizePartition, + PartitionInfo partitionInfo, + TableGroupConfig tableGroupConfig) { + Set partitionNames = sqlAlterTableOptimizePartition.getPartitions().stream() + .map(sqlNode -> ((SqlIdentifier) sqlNode).getLastName().toLowerCase()).collect(Collectors.toSet()); + + String allPartitions = partitionNames.stream().filter(p -> p.equalsIgnoreCase("ALL")).findFirst().orElse(null); + if (allPartitions != null) { + return PartitionInfoUtil.getAllPartitionGroupNames(tableGroupConfig); + } + + return PartitionInfoUtil.checkAndExpandPartitions(partitionInfo, tableGroupConfig, partitionNames, + sqlAlterTableOptimizePartition.isSubPartition()); + } + + public AlterTableGroupOptimizePartitionPreparedData getPreparedData() { + return preparedData; + } + + public static LogicalAlterTableOptimizePartition create(DDL ddl) { + return new LogicalAlterTableOptimizePartition(ddl); + } + +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableRemovePartitioning.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableRemovePartitioning.java index 444214657..7dc26ebd9 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableRemovePartitioning.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableRemovePartitioning.java @@ -38,25 +38,27 @@ public LogicalAlterTableRemovePartitioning(AlterTableRemovePartitioning alterTab } public static LogicalAlterTableRemovePartitioning create( - AlterTableRemovePartitioning alterTableRemovePartitioning) { + AlterTableRemovePartitioning alterTableRemovePartitioning) { return new LogicalAlterTableRemovePartitioning(alterTableRemovePartitioning); } @Override public boolean isSupportedByBindFileStorage() { throw new TddlRuntimeException(ErrorCode.ERR_UNARCHIVE_FIRST, - "unarchive table " + schemaName + "." + tableName); + "unarchive table " + schemaName + "." + tableName); } public void prepareData() { createGlobalIndexesPreparedData = new ArrayList<>(); final List sqlAddIndexes = - sqlAlterTableRemovePartitioning.getAlters().stream().map(e -> (SqlAddIndex) e).collect(Collectors.toList()); + sqlAlterTableRemovePartitioning.getAlters().stream().map(e -> (SqlAddIndex) e).collect(Collectors.toList()); for (SqlAddIndex sqlAddIndex : sqlAddIndexes) { final String indexName = sqlAddIndex.getIndexName().getLastName(); - createGlobalIndexesPreparedData.add(prepareCreateGsiData(indexName, sqlAddIndex)); + CreateGlobalIndexPreparedData preparedGsiData = prepareCreateGsiData(indexName, sqlAddIndex); + preparedGsiData.setWithImplicitTableGroup(preparedGsiData.getTableGroupName() != null); + createGlobalIndexesPreparedData.add(preparedGsiData); } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableReorgPartition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableReorgPartition.java index f4494e427..cc62362a0 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableReorgPartition.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableReorgPartition.java @@ -292,4 +292,9 @@ public static LogicalAlterTableReorgPartition create(DDL ddl) { return new LogicalAlterTableReorgPartition(ddl); } + public void setDdlVersionId(Long ddlVersionId) { + if (null != getPreparedData()) { + getPreparedData().setDdlVersionId(ddlVersionId); + } + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableRepartition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableRepartition.java index a8bbe72da..de463818a 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableRepartition.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableRepartition.java @@ -54,13 +54,7 @@ import org.apache.calcite.rel.ddl.AlterTableRemovePartitioning; import org.apache.calcite.rel.ddl.AlterTableRepartition; import org.apache.calcite.rex.RexNode; -import org.apache.calcite.sql.SqlAddIndex; -import org.apache.calcite.sql.SqlAddUniqueIndex; -import org.apache.calcite.sql.SqlAlterTableRepartition; -import org.apache.calcite.sql.SqlCreateTable; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlIndexDefinition; -import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.*; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.commons.lang.StringUtils; @@ -71,11 +65,15 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.stream.Collectors; +import static org.apache.calcite.sql.SqlCreateTable.getIndexColumnName; +import static org.apache.calcite.sql.SqlIdentifier.surroundWithBacktick; + /** * @author wumu */ @@ -181,16 +179,21 @@ public CreateGlobalIndexPreparedData prepareCreateGsiData(String indexTableName, localPartitionDefinitionInfo.setTableName(indexTableName); } SqlNode tableGroup = null; - if (this.relDdl != null && this.relDdl.sqlNode != null - && this.relDdl.sqlNode instanceof SqlAlterTableRepartition) { - if (((SqlAlterTableRepartition) this.relDdl.sqlNode).isAlignToTableGroup()) { - tableGroup = ((SqlAlterTableRepartition) this.relDdl.sqlNode).getTableGroupName(); - } else { - String implicitTableGroupName = - ((SqlAlterTableRepartition) this.relDdl.sqlNode).getTargetImplicitTableGroupName(); - if (StringUtils.isNotEmpty(implicitTableGroupName)) { - tableGroup = new SqlIdentifier(implicitTableGroupName, SqlParserPos.ZERO); + boolean removePartitioning = false; + if (this.relDdl != null && this.relDdl.sqlNode != null) { + if (this.relDdl.sqlNode instanceof SqlAlterTableRepartition) { + if (((SqlAlterTableRepartition) this.relDdl.sqlNode).isAlignToTableGroup()) { + tableGroup = ((SqlAlterTableRepartition) this.relDdl.sqlNode).getTableGroupName(); + } else { + String implicitTableGroupName = + ((SqlAlterTableRepartition) this.relDdl.sqlNode).getTargetImplicitTableGroupName(); + if (StringUtils.isNotEmpty(implicitTableGroupName)) { + tableGroup = new SqlIdentifier(implicitTableGroupName, SqlParserPos.ZERO); + } } + } else if (this.relDdl.sqlNode instanceof SqlAlterTableRemovePartitioning) { + tableGroup = indexDef.getTableGroupName(); + removePartitioning = true; } } CreateGlobalIndexPreparedData preparedData = @@ -216,7 +219,7 @@ public CreateGlobalIndexPreparedData prepareCreateGsiData(String indexTableName, null, // add index engine locality, partBoundExprInfo, - sqlAlterTableRepartition != null ? sqlAlterTableRepartition.getSourceSql() : null + removePartitioning ? ((SqlAlterTableRemovePartitioning) this.relDdl.sqlNode).getSourceSql() : (sqlAlterTableRepartition != null ? sqlAlterTableRepartition.getSourceSql() : null) ); if (preparedData.isWithImplicitTableGroup()) { TableGroupInfoManager tableGroupInfoManager = @@ -226,10 +229,8 @@ public CreateGlobalIndexPreparedData prepareCreateGsiData(String indexTableName, assert tableGroupName != null; if (tableGroupInfoManager.getTableGroupConfigByName(tableGroupName) == null) { preparedData.getRelatedTableGroupInfo().put(tableGroupName, true); - preparedData.getRelatedTableGroupInfo().put(tableGroupName, true); } else { preparedData.getRelatedTableGroupInfo().put(tableGroupName, false); - preparedData.getRelatedTableGroupInfo().put(tableGroupName, false); } } if (isNewPartDb) { @@ -322,10 +323,10 @@ public void prepareLocalIndexData() { } for (GsiMetaManager.GsiIndexColumnMetaBean indexColumn : indexDetail.indexColumns) { - localIndex.add(SqlIdentifier.surroundWithBacktick(indexColumn.columnName)); + localIndex.add(surroundWithBacktick(indexColumn.columnName)); } - gsiInfo.put(SqlIdentifier.surroundWithBacktick(TddlSqlToRelConverter.unwrapGsiName(indexName)), + gsiInfo.put(surroundWithBacktick(TddlSqlToRelConverter.unwrapGsiName(indexName)), new Pair<>(localIndex, indexDetail.nonUnique)); } } @@ -440,7 +441,8 @@ private void prepareData4OptimizeKey(String gsiTableDef, String primaryDef, Part private List genNewShardColumns4OptimizeKey(PartitionInfo primaryPartitionInfo, PartitionInfo targetPartitionInfo) { // only partition table - if (primaryPartitionInfo.isPartitionedTable() && targetPartitionInfo.isPartitionedGsiTable()) { + if (primaryPartitionInfo.isPartitionedTable() && + (targetPartitionInfo.isPartitionedGsiTable() || targetPartitionInfo.isPartitionedColumnarTable())) { PartitionByDefinition targetPartitionBy = targetPartitionInfo.getPartitionBy(); PartitionByDefinition primaryPartitionBy = primaryPartitionInfo.getPartitionBy(); List> allLevelActualPartCols = primaryPartitionInfo.getAllLevelActualPartCols(); @@ -479,7 +481,7 @@ private List genNewShardColumns4OptimizeKey(PartitionInfo primaryPartiti /** * 生成用于改变local index的sql语句 */ - private void genChangeLocalIndexSql4OptimizeKey(String gsiTableDefinition, List newShardColumns) { + public void genChangeLocalIndexSql4OptimizeKey(String gsiTableDefinition, List newShardColumns) { String sql; String rollbackSql; @@ -523,8 +525,8 @@ private void genChangeLocalIndexSql4OptimizeKey(String gsiTableDefinition, List< if (indexingColumns.size() == newShardColumns.size()) { int i = 0; for (SQLSelectOrderByItem item : indexingColumns) { - String colName = SqlCreateTable.getIndexColumnName(item); - if (!colName.equalsIgnoreCase(newShardColumns.get(i))) { + String colName = getIndexColumnName(item); + if (colName == null || !colName.equalsIgnoreCase(newShardColumns.get(i))) { break; } i++; @@ -532,10 +534,12 @@ private void genChangeLocalIndexSql4OptimizeKey(String gsiTableDefinition, List< // 如果跟自动生成的index name 相同,说明需要添加 if (i == indexingColumns.size() && StringUtils.equalsIgnoreCase(indexName, autoIndexName)) { - sql = String.format("alter table `%s`.`%s` add index `%s` USING BTREE (%s);", - schemaName, tableName, autoIndexName, StringUtils.join(newShardColumns, ",")); - rollbackSql = - String.format("alter table `%s`.`%s` drop index `%s`;", schemaName, tableName, autoIndexName); + sql = String.format("alter table %s.%s add index %s USING BTREE (%s);", + surroundWithBacktick(schemaName), surroundWithBacktick(tableName), + surroundWithBacktick(autoIndexName), StringUtils.join(newShardColumns, ",")); + rollbackSql = String.format("alter table %s.%s drop index %s;", + surroundWithBacktick(schemaName), surroundWithBacktick(tableName), + surroundWithBacktick(autoIndexName)); repartitionPrepareData.setAddLocalIndexSql(new Pair<>(sql, rollbackSql)); } } @@ -545,7 +549,7 @@ private void genChangeLocalIndexSql4OptimizeKey(String gsiTableDefinition, List< /** * drop 由shard key自动生成的local index */ - private void genDropIndexSql4OptimizeKey(String primaryTableDefinition) { + public void genDropIndexSql4OptimizeKey(String primaryTableDefinition) { String sql; String rollbackSql; @@ -561,7 +565,13 @@ private void genDropIndexSql4OptimizeKey(String primaryTableDefinition) { final MySqlTableIndex tableIndex = (MySqlTableIndex) sqlTableElement; indexName = ((SQLIdentifierExpr) tableIndex.getName()).normalizedName(); - indexColumns = tableIndex.getColumns().stream().map(SqlCreateTable::getIndexColumnName) + if (tableIndex.getColumns().stream().anyMatch(c -> getIndexColumnName(c) == null)) { + //函数索引,忽略 + continue; + } + + indexColumns = tableIndex.getColumns().stream() + .map(e -> surroundWithBacktick(Objects.requireNonNull(getIndexColumnName(e)))) .collect(Collectors.toList()); } else if (sqlTableElement instanceof MySqlPrimaryKey) { // do nothing @@ -569,14 +579,23 @@ private void genDropIndexSql4OptimizeKey(String primaryTableDefinition) { final MySqlKey key = (MySqlKey) sqlTableElement; indexName = ((SQLIdentifierExpr) key.getName()).normalizedName(); - indexColumns = key.getColumns().stream().map(SqlCreateTable::getIndexColumnName) + if (key.getColumns().stream().anyMatch(c -> getIndexColumnName(c) == null)) { + //函数索引,忽略 + continue; + } + + indexColumns = key.getColumns().stream() + .map(e -> surroundWithBacktick(Objects.requireNonNull(getIndexColumnName(e)))) .collect(Collectors.toList()); } if (indexName != null && indexName.contains(TddlConstants.AUTO_SHARD_KEY_PREFIX)) { - sql = String.format("alter table `%s`.`%s` drop index `%s`;", schemaName, tableName, indexName); - rollbackSql = String.format("alter table `%s`.`%s` add index %s USING BTREE (%s);", - schemaName, tableName, indexName, StringUtils.join(indexColumns, ",")); + sql = String.format("alter table %s.%s drop index %s;", + surroundWithBacktick(schemaName), surroundWithBacktick(tableName), + surroundWithBacktick(indexName)); + rollbackSql = String.format("alter table %s.%s add index %s USING BTREE (%s);", + surroundWithBacktick(schemaName), surroundWithBacktick(tableName), surroundWithBacktick(indexName), + StringUtils.join(indexColumns, ",")); repartitionPrepareData.setDropLocalIndexSql(new Pair<>(sql, rollbackSql)); } @@ -621,26 +640,28 @@ public void prepareForeignKeyData(TableMeta tableMeta, SqlAlterTableRepartition genDropForeignKeySql(removeFks); } - private void genAddForeignKeySql(Set foreignKeys) { + public void genAddForeignKeySql(Set foreignKeys) { String sql; String rollbackSql; for (ForeignKeyData data : foreignKeys) { - sql = String.format("ALTER TABLE `%s`.`%s` ADD ", - data.schema, data.tableName) + data.toString() + PARTITION_FK_SUB_JOB; - rollbackSql = String.format("ALTER TABLE `%s`.`%s` DROP FOREIGN KEY `%s`", - data.schema, data.tableName, data.constraint) + PARTITION_FK_SUB_JOB; + sql = String.format("ALTER TABLE %s.%s ADD ", + surroundWithBacktick(data.schema), surroundWithBacktick(data.tableName)) + data + PARTITION_FK_SUB_JOB; + rollbackSql = String.format("ALTER TABLE %s.%s DROP FOREIGN KEY %s", + surroundWithBacktick(data.schema), surroundWithBacktick(data.tableName), + surroundWithBacktick(data.constraint)) + PARTITION_FK_SUB_JOB; repartitionPrepareData.getAddForeignKeySql().add(new Pair<>(sql, rollbackSql)); } } - private void genDropForeignKeySql(Set foreignKeys) { + public void genDropForeignKeySql(Set foreignKeys) { String sql; String rollbackSql; for (ForeignKeyData data : foreignKeys) { - sql = String.format("ALTER TABLE `%s`.`%s` DROP FOREIGN KEY `%s`", - data.schema, data.tableName, data.constraint) + PARTITION_FK_SUB_JOB; - rollbackSql = String.format("ALTER TABLE `%s`.`%s` ADD ", - data.schema, data.tableName) + data.toString() + PARTITION_FK_SUB_JOB; + sql = String.format("ALTER TABLE %s.%s DROP FOREIGN KEY %s", + surroundWithBacktick(data.schema), surroundWithBacktick(data.tableName), + surroundWithBacktick(data.constraint)) + PARTITION_FK_SUB_JOB; + rollbackSql = String.format("ALTER TABLE %s.%s ADD ", + surroundWithBacktick(data.schema), surroundWithBacktick(data.tableName)) + data + PARTITION_FK_SUB_JOB; repartitionPrepareData.getDropForeignKeySql().add(new Pair<>(sql, rollbackSql)); Set tables = repartitionPrepareData.getForeignKeyChildTable() .computeIfAbsent(data.schema, x -> new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER)); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableSetTableGroup.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableSetTableGroup.java index 7035a4c46..e6a08f806 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableSetTableGroup.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableSetTableGroup.java @@ -19,6 +19,7 @@ import com.alibaba.polardbx.common.Engine; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.druid.util.StringUtils; import com.alibaba.polardbx.gms.tablegroup.JoinGroupInfoRecord; import com.alibaba.polardbx.gms.tablegroup.JoinGroupUtils; import com.alibaba.polardbx.gms.tablegroup.JoinGroupInfoRecord; @@ -45,6 +46,28 @@ public LogicalAlterTableSetTableGroup(DDL ddl) { super(ddl, ((AlterTableSetTableGroup) ddl).getObjectNames()); } + @Override + public boolean isSupportedByCci(ExecutionContext ec) { + boolean isNewPart = DbInfoManager.getInstance().isNewPartitionDb(schemaName); + if (!isNewPart) { + throw new TddlRuntimeException(ErrorCode.ERR_GMS_GENERIC, + "not support tablegroup in non-partitioning database"); + } + // not allow change columnar tablegroup to others + AlterTableSetTableGroup alterTableSetTableGroup = (AlterTableSetTableGroup) relDdl; + String tableGroupName = alterTableSetTableGroup.getTableGroupName(); + if (StringUtils.isEmpty(tableGroupName)) { + return true; + } + + if (!TableGroupNameUtil.isColumnarTg(tableGroupName)) { + throw new TddlRuntimeException(ErrorCode.ERR_NOT_SUPPORT, + "DDL of " + schemaName + "." + tableName + " involves file storage."); + } + + return true; + } + @Override public boolean isSupportedByFileStorage() { return false; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableSplitPartition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableSplitPartition.java index 5bce52e4d..175685cd0 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableSplitPartition.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalAlterTableSplitPartition.java @@ -20,12 +20,11 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; -import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.gms.tablegroup.PartitionGroupRecord; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; -import com.alibaba.polardbx.gms.tablegroup.TableGroupLocation; import com.alibaba.polardbx.gms.tablegroup.TableGroupRecord; +import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.gms.topology.GroupDetailInfoExRecord; import com.alibaba.polardbx.gms.util.GroupInfoUtil; import com.alibaba.polardbx.gms.util.PartitionNameUtil; @@ -34,12 +33,11 @@ import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.function.calc.scalar.filter.In; import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupSplitPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableSplitPartitionPreparedData; -import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition; import com.alibaba.polardbx.optimizer.locality.LocalityInfoUtils; +import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.PartitionInfoUtil; import com.alibaba.polardbx.optimizer.partition.PartitionSpec; @@ -86,6 +84,20 @@ public LogicalAlterTableSplitPartition(DDL ddl, boolean notIncludeGsiName) { assert notIncludeGsiName; } + @Override + public boolean isSupportedByCci(ExecutionContext ec) { + String schemaName = this.schemaName; + String tblName = Util.last(((SqlIdentifier) relDdl.getTableName()).names); + + if (DbInfoManager.getInstance().isNewPartitionDb(schemaName)) { + TableMeta tblMeta = ec.getSchemaManager(schemaName).getTable(tblName); + if (tblMeta.isColumnar()) { + return true; + } + } + return false; + } + @Override public boolean isSupportedByFileStorage() { return false; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCheckCci.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCheckCci.java index 2d2d09ace..dc22ca2af 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCheckCci.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCheckCci.java @@ -90,7 +90,8 @@ public CheckCciPrepareData prepareData(ExecutionContext ec) { schemaName, tableName, indexName, - extraCmd + extraCmd, + sqlNode.getExtras() ); return this.prepareData; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCreateIndex.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCreateIndex.java index 2aaa06645..e7d095226 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCreateIndex.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCreateIndex.java @@ -33,8 +33,8 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.CreateIndexWithGsiPreparedData; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager; -import com.alibaba.polardbx.optimizer.tablegroup.TableGroupInfoManager; import com.alibaba.polardbx.optimizer.partition.common.LocalPartitionDefinitionInfo; +import com.alibaba.polardbx.optimizer.tablegroup.TableGroupInfoManager; import com.alibaba.polardbx.optimizer.utils.RelUtils; import com.alibaba.polardbx.rule.TableRule; import org.apache.calcite.rel.ddl.CreateIndex; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCreateTable.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCreateTable.java index 6538519c0..77739163b 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCreateTable.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalCreateTable.java @@ -25,14 +25,14 @@ import com.alibaba.polardbx.druid.sql.ast.SQLPartitionByRange; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; import com.alibaba.polardbx.druid.util.StringUtils; -import com.alibaba.polardbx.gms.locality.LocalityDesc; -import com.alibaba.polardbx.gms.metadb.table.ColumnsRecord; -import com.alibaba.polardbx.gms.topology.DbInfoManager; -import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.gms.lbac.LBACSecurityEntity; import com.alibaba.polardbx.gms.lbac.LBACSecurityManager; import com.alibaba.polardbx.gms.lbac.PolarSecurityLabelColumn; +import com.alibaba.polardbx.gms.locality.LocalityDesc; +import com.alibaba.polardbx.gms.metadb.table.ColumnsRecord; +import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.lbac.LBACException; +import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.config.table.DefaultExprUtil; import com.alibaba.polardbx.optimizer.config.table.GeneratedColumnUtil; @@ -47,6 +47,8 @@ import com.alibaba.polardbx.optimizer.parse.TableMetaParser; import com.alibaba.polardbx.optimizer.partition.common.LocalPartitionDefinitionInfo; import com.alibaba.polardbx.optimizer.tablegroup.TableGroupInfoManager; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlUtil; import com.alibaba.polardbx.optimizer.utils.DdlCharsetInfo; import com.alibaba.polardbx.optimizer.utils.DdlCharsetInfoUtil; import com.alibaba.polardbx.optimizer.utils.RelUtils; @@ -381,12 +383,12 @@ private CreateTablePreparedData preparePrimaryData(ExecutionContext executionCon defaultCharset, defaultCollation, true); if (defaultCharset == null && defaultCollation == null && createTbCharInfo.finalCharset != null) { - builder.append(" CHARSET `").append(createTbCharInfo.finalCharset.toLowerCase()).append("`"); + builder.append(" CHARSET ").append(createTbCharInfo.finalCharset.toLowerCase()); sqlCreateTable.setDefaultCharset(createTbCharInfo.finalCharset.toLowerCase()); } if (defaultCollation == null && createTbCharInfo.finalCollate != null) { - builder.append(" COLLATE `").append(createTbCharInfo.finalCollate.toLowerCase()).append("`"); + builder.append(" COLLATE ").append(createTbCharInfo.finalCollate.toLowerCase()); sqlCreateTable.setDefaultCollation(createTbCharInfo.finalCollate.toLowerCase()); } @@ -405,11 +407,18 @@ private CreateTablePreparedData preparePrimaryData(ExecutionContext executionCon tableMeta.getTableName(), (SqlPartitionByRange) sqlCreateTable.getLocalPartition() ); + + TtlDefinitionInfo ttlDefinitionInfo = null; + SqlNode ttlDefinitionExpr = null; if (localPartitionDefinitionInfo != null) { SQLPartitionByRange sqlPartitionByRange = LocalPartitionDefinitionInfo.generateLocalPartitionStmtForCreate( localPartitionDefinitionInfo, localPartitionDefinitionInfo.evalPivotDate(executionContext)); sqlCreateTable.setLocalPartitionSuffix(sqlPartitionByRange); + } else { + if (sqlCreateTable.getTtlDefinition() != null) { + ttlDefinitionExpr = sqlCreateTable.getTtlDefinition(); + } } CreateTablePreparedData res = prepareCreateTableData(tableMeta, @@ -422,6 +431,8 @@ private CreateTablePreparedData preparePrimaryData(ExecutionContext executionCon sqlCreateTable.getTbpartitions(), sqlCreateTable.getSqlPartition(), localPartitionDefinitionInfo, + ttlDefinitionInfo, + ttlDefinitionExpr, sqlCreateTable.getTableGroupName(), sqlCreateTable.isWithImplicitTableGroup(), sqlCreateTable.getJoinGroupName(), @@ -543,17 +554,39 @@ private CreateTablePreparedData preparePrimaryData(ExecutionContext executionCon LocalityDesc desc = LocalityDesc.parse(sqlCreateTable.getLocality()); res.setLocality(desc); - if (sqlCreateTable.getLoadTableName() != null) { - res.setLoadTableName(sqlCreateTable.getLoadTableName()); - if (sqlCreateTable.getLoadTableSchema() != null) { - res.setLoadTableSchema(sqlCreateTable.getLoadTableSchema()); - } else { - res.setLoadTableSchema(schemaName); + /** + * Check if the loading-source table of archive Table is using + * local-partition or row-level-ttl + */ + boolean archiveFromRowLevelTtlTbl = false; + + if (sqlCreateTable.getArchiveMode() == ArchiveMode.TTL) { + String srcTblSchema = sqlCreateTable.getLoadTableSchema(); + if (srcTblSchema == null) { + srcTblSchema = schemaName; } + String srcTblName = sqlCreateTable.getLoadTableName(); + archiveFromRowLevelTtlTbl = TtlUtil.checkIfUsingRowLevelTtl(srcTblSchema, srcTblName, executionContext); } - if (sqlCreateTable.getArchiveMode() == ArchiveMode.TTL) { - res.setArchiveTableName(sqlCreateTable.getLoadTableName()); + if (!archiveFromRowLevelTtlTbl) { + /** + * Archive from local-partition table + */ + if (sqlCreateTable.getLoadTableName() != null) { + res.setLoadTableName(sqlCreateTable.getLoadTableName()); + if (sqlCreateTable.getLoadTableSchema() != null) { + res.setLoadTableSchema(sqlCreateTable.getLoadTableSchema()); + } else { + res.setLoadTableSchema(schemaName); + } + } + + if (sqlCreateTable.getArchiveMode() == ArchiveMode.TTL) { + res.setArchiveTmpTableName(sqlCreateTable.getLoadTableName()); + } + } else { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, "Not support create oss table like a ttl-defined table"); } if (res.isWithImplicitTableGroup()) { @@ -626,6 +659,12 @@ private void prepareCreateTableLikeData() { Engine engine; if ((engine = this.sqlCreateTable.getEngine()) != null) { createTableAst.setEngine(engine); + + createTableAst.setTtlEnable(null); + createTableAst.setTtlExpr(null); + createTableAst.setTtlJob(null); + createTableAst.setTtlDefinition(null); + } ArchiveMode archiveMode; @@ -740,4 +779,5 @@ public void setDdlVersionId(Long ddlVersionId) { getCreateTableWithGsiPreparedData().setDdlVersionId(ddlVersionId); } } + } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalDropDatabase.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalDropDatabase.java index bee7f836a..e18cdf50a 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalDropDatabase.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalDropDatabase.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.optimizer.core.rel.ddl; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; import org.apache.calcite.rel.ddl.DropDatabase; /** diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalTableOperation.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalTableOperation.java index 5f6babecc..078d7ae35 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalTableOperation.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalTableOperation.java @@ -29,6 +29,7 @@ import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.CreateGlobalIndexPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.DropGlobalIndexPreparedData; import com.alibaba.polardbx.optimizer.partition.common.LocalPartitionDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; import org.apache.calcite.rel.core.DDL; import org.apache.calcite.rex.RexNode; import org.apache.calcite.sql.SqlColumnDeclaration; @@ -64,6 +65,8 @@ protected CreateTablePreparedData prepareCreateTableData(TableMeta tableMeta, SqlNode tbPartitions, SqlNode partitionings, LocalPartitionDefinitionInfo localPartitionDefinitionInfo, + TtlDefinitionInfo ttlDefinitionInfo, + SqlNode ttlDefinitionExpr, SqlNode tableGroupName, boolean withImplicitTableGroup, SqlNode joinGroupName, @@ -90,6 +93,8 @@ protected CreateTablePreparedData prepareCreateTableData(TableMeta tableMeta, preparedData.setTbPartitions(tbPartitions); preparedData.setPartitioning(partitionings); preparedData.setLocalPartitionDefinitionInfo(localPartitionDefinitionInfo); + preparedData.setTtlDefinitionInfo(ttlDefinitionInfo); + preparedData.setTtlDefinitionExpr(ttlDefinitionExpr); preparedData.setTableGroupName(tableGroupName); preparedData.setWithImplicitTableGroup(withImplicitTableGroup); preparedData.setJoinGroupName(joinGroupName); @@ -102,33 +107,6 @@ protected CreateTablePreparedData prepareCreateTableData(TableMeta tableMeta, return preparedData; } - protected CreateGlobalIndexPreparedData prepareCreateGlobalIndexData(String primaryTableName, - String primaryTableDefinition, - String indexTableName, - TableMeta tableMeta, - boolean isShadow, - boolean autoPartition, - boolean isBroadcast, - SqlNode dbPartitionBy, - SqlNode dbPartitions, - SqlNode tbPartitionBy, - SqlNode tbPartitions, - SqlNode partitionings, - LocalPartitionDefinitionInfo localPartitionDefinitionInfo, - boolean isUnique, - boolean clusteredIndex, - boolean columnarIndex, - SqlNode tableGroupName, - boolean withImplicitTableGroup, - Map partBoundExprInfo, - String sourceSql) { - return prepareCreateGlobalIndexData(primaryTableName, primaryTableDefinition, indexTableName, tableMeta, - isShadow, autoPartition, isBroadcast, dbPartitionBy, dbPartitions, - tbPartitionBy, tbPartitions, partitionings, localPartitionDefinitionInfo, - isUnique, clusteredIndex, columnarIndex, tableGroupName, withImplicitTableGroup, null, "", - partBoundExprInfo, sourceSql); - } - protected CreateGlobalIndexPreparedData prepareCreateGlobalIndexData(String primaryTableName, String primaryTableDefinition, String indexTableName, @@ -162,9 +140,16 @@ protected CreateGlobalIndexPreparedData prepareCreateGlobalIndexData(String prim CreateTablePreparedData indexTablePreparedData = prepareCreateTableData(primaryTableMeta, isShadow, autoPartition, isBroadcast, dbPartitionBy, dbPartitions, tbPartitionBy, - tbPartitions, partitionings, localPartitionDefinitionInfo, tableGroupName, withImplicitTableGroup, + tbPartitions, partitionings, localPartitionDefinitionInfo, null, null, tableGroupName, + withImplicitTableGroup, null, locality, partBoundExprInfo, sourceSql, null, null); +// CreateTablePreparedData indexTablePreparedData = +// prepareCreateTableData(primaryTableMeta, isShadow, autoPartition, +// isBroadcast, dbPartitionBy, dbPartitions, tbPartitionBy, +// tbPartitions, partitionings, localPartitionDefinitionInfo, null, false, tableGroupName, +// null, locality, partBoundExprInfo, sourceSql, null, null); + // Add all columns in primary table whose default value is binary, so binaryColumnDefaultValues may include // columns that do not exist in GSI Map specialDefaultValues = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalTruncateTable.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalTruncateTable.java index 6277f6d8b..e45df9f6f 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalTruncateTable.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalTruncateTable.java @@ -18,7 +18,6 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; -import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.gms.metadb.table.IndexStatus; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.OptimizerContext; @@ -55,6 +54,10 @@ public boolean isWithGsi() { return truncateTableWithGsiPreparedData != null && truncateTableWithGsiPreparedData.hasGsi(); } + public boolean isWithCci() { + return truncateTableWithGsiPreparedData != null && truncateTableWithGsiPreparedData.isHasColumnarIndex(); + } + public TruncateTableWithGsiPreparedData getTruncateTableWithGsiPreparedData() { return truncateTableWithGsiPreparedData; } @@ -84,8 +87,7 @@ public void prepareData(ExecutionContext ec) { truncateTableWithGsiPreparedData.setSchemaName(schemaName); truncateTableWithGsiPreparedData.setTableName(tableName); truncateTableWithGsiPreparedData.setTableVersion(tableMeta.getVersion()); - truncateTableWithGsiPreparedData.setHasColumnarIndex( - GeneralUtil.isNotEmpty(tableMeta.getColumnarIndexPublished())); + truncateTableWithGsiPreparedData.setHasColumnarIndex(tableMeta.withCci()); final GsiMetaBean gsiMetaBean = sm.getGsi(tableName, IndexStatus.ALL); if (gsiMetaBean.withGsi(tableName)) { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalUnArchive.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalUnArchive.java index 75ab380eb..e4c07ffec 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalUnArchive.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/LogicalUnArchive.java @@ -151,6 +151,7 @@ private Map retainUsefulTables(Map tables, Connectio if (record == null) { continue; } + // without archive table if (StringUtils.isEmpty(record.getArchiveTableName()) || StringUtils.isEmpty( record.getArchiveTableName())) { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableArchivePartitionPreparedData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableArchivePartitionPreparedData.java new file mode 100644 index 000000000..9691c3a16 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableArchivePartitionPreparedData.java @@ -0,0 +1,26 @@ +package com.alibaba.polardbx.optimizer.core.rel.ddl.data; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * @author wumu + */ +@Getter +@Setter +public class AlterTableArchivePartitionPreparedData { + String primaryTableSchema; + + String primaryTableName; + + String tmpTableSchema; + + String tmpTableName; + + List phyPartitionNames; + + List firstLevelPartitionNames; + +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupAddPartitionPreparedData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupAddPartitionPreparedData.java index 7a3233655..09cd70854 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupAddPartitionPreparedData.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupAddPartitionPreparedData.java @@ -22,7 +22,6 @@ import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; import com.alibaba.polardbx.gms.util.PartitionNameUtil; import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition; -import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.PartitionInfoUtil; import com.alibaba.polardbx.optimizer.partition.PartitionSpec; import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupBasePreparedData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupBasePreparedData.java index 4fccb1f4c..98c4f141d 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupBasePreparedData.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupBasePreparedData.java @@ -556,4 +556,5 @@ public boolean needFindCandidateTableGroup() { return TStringUtil.isEmpty(this.getTargetImplicitTableGroupName()) || (implicitTableGroupConfig != null && !implicitTableGroupConfig.isEmpty()); } + } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupItemPreparedData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupItemPreparedData.java index c4f5e2b64..07385a602 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupItemPreparedData.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupItemPreparedData.java @@ -44,6 +44,7 @@ public AlterTableGroupItemPreparedData(String schemaName, String tableName) { */ private List invisiblePartitionGroups; private boolean operateOnSubPartition; + private boolean columnarIndex; public String getTableGroupName() { return tableGroupName; @@ -133,4 +134,12 @@ public boolean isOperateOnSubPartition() { public void setOperateOnSubPartition(boolean operateOnSubPartition) { this.operateOnSubPartition = operateOnSubPartition; } + + public boolean isColumnarIndex() { + return this.columnarIndex; + } + + public void setColumnarIndex(final boolean columnarIndex) { + this.columnarIndex = columnarIndex; + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupOptimizePartitionItemPreparedData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupOptimizePartitionItemPreparedData.java new file mode 100644 index 000000000..bf656eea2 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupOptimizePartitionItemPreparedData.java @@ -0,0 +1,20 @@ +package com.alibaba.polardbx.optimizer.core.rel.ddl.data; + +import java.util.Set; + +public class AlterTableGroupOptimizePartitionItemPreparedData extends AlterTableGroupItemPreparedData { + + private Set optimizePartitionNames; + + public AlterTableGroupOptimizePartitionItemPreparedData(String schemaName, String tableName) { + super(schemaName, tableName); + } + + public Set getOptimizePartitionNames() { + return optimizePartitionNames; + } + + public void setOptimizePartitionNames(Set optimizePartitionNames) { + this.optimizePartitionNames = optimizePartitionNames; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupOptimizePartitionPreparedData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupOptimizePartitionPreparedData.java new file mode 100644 index 000000000..d47d5cfc8 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableGroupOptimizePartitionPreparedData.java @@ -0,0 +1,33 @@ +package com.alibaba.polardbx.optimizer.core.rel.ddl.data; + +import java.util.Set; + +/** + * @author chenghui.lch + */ +public class AlterTableGroupOptimizePartitionPreparedData extends AlterTableGroupBasePreparedData { + + private Set optimizePartitionNames; + + protected boolean isSubPartition = false; + + public AlterTableGroupOptimizePartitionPreparedData() { + } + + public Set getOptimizePartitionNames() { + return optimizePartitionNames; + } + + public void setOptimizePartitionNames(Set optimizePartitionNames) { + this.optimizePartitionNames = optimizePartitionNames; + } + + public boolean isSubPartition() { + return isSubPartition; + } + + public void setSubPartition(boolean subPartition) { + isSubPartition = subPartition; + } + +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableOptimizePartitionPreparedData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableOptimizePartitionPreparedData.java new file mode 100644 index 000000000..4458b5150 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/AlterTableOptimizePartitionPreparedData.java @@ -0,0 +1,7 @@ +package com.alibaba.polardbx.optimizer.core.rel.ddl.data; + +/** + * @author chenghui.lch + */ +public class AlterTableOptimizePartitionPreparedData extends AlterTableGroupOptimizePartitionPreparedData { +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/CheckCciPrepareData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/CheckCciPrepareData.java index 86c6a6297..4366612b5 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/CheckCciPrepareData.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/CheckCciPrepareData.java @@ -20,17 +20,21 @@ import org.apache.calcite.sql.SqlCheckColumnarIndex.CheckCciExtraCmd; import java.util.EnumSet; +import java.util.List; @Getter public class CheckCciPrepareData extends DdlPreparedData { String indexName; CheckCciExtraCmd extraCmd; + List tsoList; - public CheckCciPrepareData(String schemaName, String tableName, String indexName, CheckCciExtraCmd extraCmd) { + public CheckCciPrepareData(String schemaName, String tableName, String indexName, CheckCciExtraCmd extraCmd, + List tsoList) { super(schemaName, tableName); this.indexName = indexName; this.extraCmd = extraCmd; + this.tsoList = tsoList; } /** @@ -50,6 +54,14 @@ public boolean isShow() { return this.extraCmd == CheckCciExtraCmd.SHOW; } + public boolean isIncrement() { + return this.extraCmd == CheckCciExtraCmd.INCREMENT; + } + + public boolean isSnapshot() { + return this.extraCmd == CheckCciExtraCmd.SNAPSHOT; + } + public boolean isCheck() { return EnumSet .of(CheckCciExtraCmd.DEFAULT, CheckCciExtraCmd.CHECK, CheckCciExtraCmd.LOCK) @@ -64,6 +76,9 @@ public boolean isMeta() { } public boolean isNeedReport(boolean asyncDdlMode) { - return isShow() || isMeta() || (!asyncDdlMode && isCheck()); + return isShow() || isMeta() + || (!asyncDdlMode && isCheck()) + || (!asyncDdlMode && isIncrement()) + || (!asyncDdlMode && isSnapshot()); } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/CreateTablePreparedData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/CreateTablePreparedData.java index a7a64e401..7ce20d4ef 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/CreateTablePreparedData.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/CreateTablePreparedData.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.optimizer.config.table.TableMeta; import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.common.LocalPartitionDefinitionInfo; +import com.alibaba.polardbx.optimizer.ttl.TtlDefinitionInfo; import com.alibaba.polardbx.rule.TableRule; import lombok.Data; import org.apache.calcite.rex.RexNode; @@ -73,6 +74,9 @@ public class CreateTablePreparedData extends DdlPreparedData { private PartitionInfo partitionInfo; private LocalPartitionDefinitionInfo localPartitionDefinitionInfo; + private SqlNode ttlDefinitionExpr; + private TtlDefinitionInfo ttlDefinitionInfo; + private String selectSql; /** @@ -80,11 +84,49 @@ public class CreateTablePreparedData extends DdlPreparedData { */ private LocalityDesc locality; + /** + * The schemaName of ttl table + */ private String loadTableSchema; + /** + * The tableName of ttl table + */ private String loadTableName; + /** + * The schemaName of ttl-tmp table + */ + private String archiveTmpTableSchema; + + /** + * The tableName of ttl-tmp table + */ + private String archiveTmpTableName; + + /** + * The schemaName of oss table + */ + private String archiveTableSchema; + + /** + * The tableName of oss table + */ private String archiveTableName; + /** + * The real source schemaName of oss table, the schemaName of ttl table + */ + private String archiveActualSourceTableSchema; + /** + * The real source tableName of oss table, the tableName of ttl table + */ + private String archiveActualSourceTableName; + + /** + * Label if curr table is a ttl-tmp table + */ + private boolean ttlTemporary; + /** * if Create gsi table */ diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/RebuildTablePrepareData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/RebuildTablePrepareData.java index 8dd7542b3..95e30b949 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/RebuildTablePrepareData.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/RebuildTablePrepareData.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.optimizer.core.rel.ddl.data; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLColumnDefinition; import lombok.Data; import java.util.ArrayList; @@ -42,12 +43,19 @@ public class RebuildTablePrepareData { /** * for checker */ - Map virtualColumnMap = new HashMap<>(); + Map srcVirtualColumnMap = new HashMap<>(); /** * for checker */ - Map columnNewDef = new HashMap<>(); + Map srcColumnNewDef = new HashMap<>(); + + Map dstColumnNewDef = new HashMap<>(); + + /** + * for checker + */ + Map dstVirtualColumnMap = new HashMap<>(); /** * for backfill when change column name @@ -73,4 +81,9 @@ public class RebuildTablePrepareData { * for alter table drop column */ List dropColumns = new ArrayList<>(); + + /** + * for cci + */ + long versionId; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/gsi/CreateGlobalIndexPreparedData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/gsi/CreateGlobalIndexPreparedData.java index 43010893e..c160b1cb1 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/gsi/CreateGlobalIndexPreparedData.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/gsi/CreateGlobalIndexPreparedData.java @@ -86,6 +86,9 @@ public class CreateGlobalIndexPreparedData extends DdlPreparedData { private boolean repartition; + // for omc + private boolean omcRebuildPrimaryTable; + public CreateGlobalIndexPreparedData() { } @@ -411,6 +414,14 @@ public void setRepartition(boolean repartition) { this.repartition = repartition; } + public boolean isOmcRebuildPrimaryTable() { + return omcRebuildPrimaryTable; + } + + public void setOmcRebuildPrimaryTable(boolean omcRebuildPrimaryTable) { + this.omcRebuildPrimaryTable = omcRebuildPrimaryTable; + } + public boolean isCreateTableWithIndex() { return createTableWithIndex; } @@ -476,7 +487,8 @@ public static SqlIndexDefinition createIndex2IndexDefinition(SqlCreateIndex sqlC sqlCreateIndex.getEngineName(), sqlCreateIndex.getDictColumns(), sqlCreateIndex.isWithImplicitTableGroup(), - sqlCreateIndex.isVisible() + sqlCreateIndex.isVisible(), + sqlCreateIndex.getColumnarOptions() ); } @@ -517,7 +529,8 @@ public static SqlCreateIndex indexDefinition2CreateIndex(SqlIndexDefinition sqlI sqlIndexDefinition.isWithImplicitTableGroup(), sqlIndexDefinition.getEngineName(), sqlIndexDefinition.getDictColumns(), - sqlIndexDefinition.isVisible() + sqlIndexDefinition.isVisible(), + sqlIndexDefinition.getColumnarOptions() ); } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/gsi/TruncateTableWithGsiPreparedData.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/gsi/TruncateTableWithGsiPreparedData.java index 6489969a2..eb608afa0 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/gsi/TruncateTableWithGsiPreparedData.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/ddl/data/gsi/TruncateTableWithGsiPreparedData.java @@ -23,6 +23,8 @@ import java.util.LinkedHashMap; import java.util.Map; +import static com.alibaba.polardbx.common.cdc.ICdcManager.DEFAULT_DDL_VERSION_ID; + public class TruncateTableWithGsiPreparedData extends DdlPreparedData { protected TruncateTablePreparedData primaryTablePreparedData; @@ -33,6 +35,7 @@ public class TruncateTableWithGsiPreparedData extends DdlPreparedData { protected Map tmpIndexTableMap; protected boolean hasColumnarIndex; + protected long versionId = DEFAULT_DDL_VERSION_ID; public TruncateTablePreparedData getPrimaryTablePreparedData() { return primaryTablePreparedData; @@ -99,4 +102,11 @@ public boolean isHasColumnarIndex() { public void setHasColumnarIndex(boolean hasColumnarIndex) { this.hasColumnarIndex = hasColumnarIndex; } + + public long getVersionId() { + return versionId; + } + public void setVersionId(long versionId) { + this.versionId = versionId; + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/dml/WriterFactory.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/dml/WriterFactory.java index 9cad10e94..9cd4d226f 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/dml/WriterFactory.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/dml/WriterFactory.java @@ -508,7 +508,7 @@ private static DistinctWriter createBroadcastOrSingleUpdateWriter(TableModify pa targetColumns.add(new SqlIdentifier(ImmutableList.of(c), SqlParserPos.ZERO)); sourceExpressions.add(new SqlDynamicParam(index + 2, SqlParserPos.ZERO)); sourceExpressionList.add(rexBuilder.makeDynamicParam( - getUpdateColumnType(parent, updateColumnListLocal.get(index), updateSourceMapping.get(index)), index)); + getUpdateColumnType(parent, updateColumnList.get(index), updateSourceMapping.get(index)), index)); }); /** diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/dml/writer/UpsertRelocateWriter.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/dml/writer/UpsertRelocateWriter.java index 9554c0e72..7428f732d 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/dml/writer/UpsertRelocateWriter.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/dml/writer/UpsertRelocateWriter.java @@ -98,12 +98,9 @@ public ClassifyResult classify(BiPredicate, Map + * key : grpKey + * val: + * List[List] : the same position of (sub)part for multi tables with join + * the i-th element of List: the one phy table name of the multi tables with join on the same position + * + */ + protected Map>> targetTables = null; + + /** + *

+     *   List[i]: the target table info for the i-th logical table name
+     * 
+ */ + protected List targetTableInfoList; + + public TargetTableInfo() { + } + + public List getTargetTableInfoList() { + return targetTableInfoList; + } + + public void setTargetTableInfoList( + List targetTableInfoList) { + this.targetTableInfoList = targetTableInfoList; + } + + public Map>> getTargetTables() { + return targetTables; + } + + public void setTargetTables(Map>> targetTables) { + this.targetTables = targetTables; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/util/TargetTableInfoOneTable.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/util/TargetTableInfoOneTable.java new file mode 100644 index 000000000..14abd2902 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/core/rel/util/TargetTableInfoOneTable.java @@ -0,0 +1,116 @@ +package com.alibaba.polardbx.optimizer.core.rel.util; + +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author chenghui.lch + */ +public class TargetTableInfoOneTable { + + protected PartitionInfo partInfo; + + /** + * The pruned partition count of first-level partition + */ + protected int prunedFirstLevelPartCount = 0; + /** + * Label if all the first-level partitions are sorted, + * all the partitions sorted with asc order + */ + protected boolean allPartSorted = false; + + /** + * The part cols of first-level partitions + */ + protected List partColList = new ArrayList<>(); + /** + * Label if using subpart + */ + protected boolean useSubPart = false; + /** + * Label if all the second-level subpartitions are sorted, + * only for the case of prunedFirstLevelPartCount=1, + * all the subpartitions sorted with asc order + */ + protected boolean allSubPartSorted = false; + + /** + * The subpart cols of first-level partitions + */ + protected List subpartColList = new ArrayList<>(); + + /** + * Label if all the pruned 1st-level partition contain only one subpartition + */ + protected boolean allPrunedPartContainOnlyOneSubPart = false; + + public TargetTableInfoOneTable() { + } + + public int getPrunedFirstLevelPartCount() { + return prunedFirstLevelPartCount; + } + + public void setPrunedFirstLevelPartCount(int prunedFirstLevelPartCount) { + this.prunedFirstLevelPartCount = prunedFirstLevelPartCount; + } + + public boolean isAllPartSorted() { + return allPartSorted; + } + + public void setAllPartSorted(boolean allPartSorted) { + this.allPartSorted = allPartSorted; + } + + public List getPartColList() { + return partColList; + } + + public void setPartColList(List partColList) { + this.partColList = partColList; + } + + public List getSubpartColList() { + return subpartColList; + } + + public void setSubpartColList(List subpartColList) { + this.subpartColList = subpartColList; + } + + public PartitionInfo getPartInfo() { + return partInfo; + } + + public void setPartInfo(PartitionInfo partInfo) { + this.partInfo = partInfo; + } + + public boolean isUseSubPart() { + return useSubPart; + } + + public void setUseSubPart(boolean useSubPart) { + this.useSubPart = useSubPart; + } + + public boolean isAllSubPartSorted() { + return allSubPartSorted; + } + + public void setAllSubPartSorted(boolean allSubPartSorted) { + this.allSubPartSorted = allSubPartSorted; + } + + public boolean isAllPrunedPartContainOnlyOneSubPart() { + return allPrunedPartContainOnlyOneSubPart; + } + + public void setAllPrunedPartContainOnlyOneSubPart(boolean allPrunedPartContainOnlyOneSubPart) { + this.allPrunedPartContainOnlyOneSubPart = allPrunedPartContainOnlyOneSubPart; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/exception/FunctionException.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/exception/FunctionException.java index 148500d9f..5e9ac1bfa 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/exception/FunctionException.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/exception/FunctionException.java @@ -23,16 +23,19 @@ public class FunctionException extends TddlRuntimeException { private static final long serialVersionUID = 7119345874409878404L; - public FunctionException(String... params){ + public FunctionException(String... params) { super(ErrorCode.ERR_FUNCTION, params); } - public FunctionException(Throwable cause, String... params){ + public FunctionException(Throwable cause, String... params) { super(ErrorCode.ERR_FUNCTION, cause, params); } - public FunctionException(Throwable cause){ - super(ErrorCode.ERR_FUNCTION, cause, new String[] { cause.getMessage() }); + public FunctionException(Throwable cause) { + super(ErrorCode.ERR_FUNCTION, cause, new String[] {cause.getMessage()}); } + public static FunctionException invalidParamCount(String functionName) { + return new FunctionException(String.format("Incorrect parameter count in the call to '%s'", functionName)); + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/HintPlanner.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/HintPlanner.java index ae64ad81d..fbae213f4 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/HintPlanner.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/HintPlanner.java @@ -255,9 +255,6 @@ public static HintPlanner getInstance(String schemaName, ExecutionContext ec) { catalog = RelUtils.buildCatalogReader(schemaName, ec); VolcanoPlanner planner = new VolcanoPlanner(DrdsRelOptCostImpl.FACTORY, Contexts.EMPTY_CONTEXT); - if (ec.isEnableRuleCounter()) { - planner.setRuleCounter(); - } planner.clearRelTraitDefs(); planner.addRelTraitDef(ConventionTraitDef.INSTANCE); planner.addRelTraitDef(RelCollationTraitDef.INSTANCE); @@ -405,6 +402,11 @@ public HintCollection collectAndPreExecute(SqlNode ast, CmdBean cmdBean, boolean public ExecutionPlan direct(SqlNode ast, CmdBean cmdBean, HintCollection hintCollection, Map param, String schemaName, ExecutionContext ec) { // init group + boolean isNewPartDb = DbInfoManager.getInstance().isNewPartitionDb(schemaName); + + if (isNewPartDb) { + return directPartDb(ast, cmdBean, hintCollection, param, schemaName, ec); + } List finalGroups; boolean hasDirectHint = false; if (cmdBean.jsonHint()) { @@ -442,7 +444,6 @@ public ExecutionPlan direct(SqlNode ast, CmdBean cmdBean, HintCollection hintCol boolean useGrpParallelism = ec.getGroupParallelism() > 1; boolean shouldUseGrpConnId = false; boolean usingAutoCommit = ec.isAutoCommit(); - boolean isNewPartDb = DbInfoManager.getInstance().isNewPartitionDb(schemaName); List results = new ArrayList<>(); PhyQueryOperationBuilder phyQueryBuilder = new PhyQueryOperationBuilder(); List logTbls = new ArrayList<>(); @@ -622,6 +623,37 @@ public ExecutionPlan direct(SqlNode ast, CmdBean cmdBean, HintCollection hintCol } } } + + boolean copyModifyNode0ToSingle = + ec.getParamManager().getBoolean(ConnectionParams.COPY_MODIFY_NODE0_TO_SINGLE); + + // Fix for early 1.0 user who is using node hint to modify broadcast table + if (visitor.allBroadcastTable() + && sqlKind != null && sqlKind.belongsTo(SqlKind.DML) + && copyModifyNode0ToSingle) { + final List groups = OptimizerContext.getContext(schemaName).getMatrix().getGroups(); + final String zeroGroupName = groups.get(0).getName(); + boolean withZeroGroup = false; + boolean withSingleGroup = false; + for (String group : finalGroups) { + if (GroupInfoUtil.isSingleGroup(group)) { + withSingleGroup = true; + } + + if (TStringUtil.equalsIgnoreCase(group, zeroGroupName)) { + withZeroGroup = true; + } + } + + if (withZeroGroup && !withSingleGroup) { + for (Group group : groups) { + if (GroupInfoUtil.isSingleGroup(group.getName())) { + finalGroups.add(group.getName()); + } + } + } + } + for (String group : finalGroups) { checkGroupPrivileges(group, ec); PhyQueryOperation phyQueryOperation = phyQueryBuilder.buildPhyQueryOperation( @@ -649,6 +681,244 @@ public ExecutionPlan direct(SqlNode ast, CmdBean cmdBean, HintCollection hintCol return result; } + /** + * partition db support partition hint or direct hint + * like set partition_hint=p1; + * or /*+TDDL({'type':'direct','dbid':'p1'})*\/ + * or /*TDDL:NODE p1 *\/ + */ + private ExecutionPlan directPartDb(SqlNode originAst, CmdBean cmdBean, HintCollection hintCollection, + Map param, String schemaName, ExecutionContext ec) { + List partNameList; + if (cmdBean.jsonHint()) { + // JSON HINT + RouteCondition rc = + SimpleHintParser.convertHint2RouteCondition(schemaName, SimpleHintParser.TDDL_HINT_PREFIX + + cmdBean.getJson() + + SimpleHintParser.TDDL_HINT_END, + param); + cmdBean.getExtraCmd().putAll(rc.getExtraCmds()); + + if (rc instanceof DirectlyRouteCondition) { + hintCollection.routeCount++; + final DirectlyRouteCondition drc = (DirectlyRouteCondition) rc; + partNameList = HintUtil.splitAndTrim(drc.getDbId(), ","); + } else { + throw new TddlRuntimeException(ErrorCode.ERR_NOT_SUPPORT, "unsupport HINT type " + + rc.getClass().getName() + + " for direct plan!"); + } + } else { + // NODE + partNameList = cmdBean.getGroups(); + } + + if (partNameList == null || partNameList.isEmpty()) { + partNameList = Lists.newArrayList(ec.getPartitionHint()); + } + + List results = new ArrayList<>(); + List tableModified = null; + BitSet planProperties = null; + final List dynamicParamIndex = PlannerUtils.getDynamicParamIndex(originAst); + + for (String partName : partNameList) { + List finalGroups = Lists.newArrayList(); + final SqlConverter converter = SqlConverter.getInstance(schemaName, ec); + final RelOptCluster cluster = converter.createRelOptCluster(null); + + boolean useGrpParallelism = ec.getGroupParallelism() > 1; + boolean shouldUseGrpConnId = false; + boolean usingAutoCommit = ec.isAutoCommit(); + PhyQueryOperationBuilder phyQueryBuilder = new PhyQueryOperationBuilder(); + List logTbls = new ArrayList<>(); + List> phyTbls = new ArrayList<>(); + + if (StringUtils.isNotEmpty(ec.getPartitionHint())) { + ec.setOriginSqlPushdownOrRoute(true); + } + + boolean pushdownHintOnGsi = false; + if (cmdBean.getExtraCmd().containsKey(ConnectionProperties.PUSHDOWN_HINT_ON_GSI)) { + pushdownHintOnGsi = + Boolean.valueOf(cmdBean.getExtraCmd().get(ConnectionProperties.PUSHDOWN_HINT_ON_GSI).toString()); + } + + boolean pushdownDmlOnBroadcast = false; + if (cmdBean.getExtraCmd().containsKey(ConnectionProperties.PUSHDOWN_HINT_ON_BROADCAST)) { + pushdownDmlOnBroadcast = + Boolean.valueOf( + cmdBean.getExtraCmd().get(ConnectionProperties.PUSHDOWN_HINT_ON_BROADCAST).toString()); + } + + boolean hasDirectHint = false; + if (!partName.toLowerCase().contains("group") && + !MetaDbDataSource.DEFAULT_META_DB_GROUP_NAME.equalsIgnoreCase(partName)) { + ec.setPartitionHint(partName); + } else { + finalGroups.add(partName); + hasDirectHint = true; + } + + // replace table name + ReplaceTblWithPhyTblVisitor visitor = new ReplaceTblWithPhyTblVisitor(schemaName, ec, hasDirectHint); + SqlNode ast = originAst.accept(visitor); + if (visitor.getUniqGroupName() != null) { + finalGroups.add(visitor.getUniqGroupName()); + } else { + if (finalGroups.size() == 0) { + throw new TddlRuntimeException(ErrorCode.ERR_NOT_SUPPORT, + "Unsupported to use direct HINT for part table that has multi physical tables in one partition"); + } + } + + final ExecutionPlanPropertiesVisitor logicalPlanPropertiesVisitor = new ExecutionPlanPropertiesVisitor(); + ast.accept(logicalPlanPropertiesVisitor); + if (planProperties == null) { + planProperties = logicalPlanPropertiesVisitor.appendPlanProperties(null, null, ec); + } + + SqlSelect.LockMode lockMode = logicalPlanPropertiesVisitor.getLockMode(); + List allPhyTableNames = new ArrayList<>(); + final List modifiedPhyTableNames = logicalPlanPropertiesVisitor.getModifiedTableNames(); + SqlKind sqlKind = logicalPlanPropertiesVisitor.getSqlKind(); + if (sqlKind == null) { + sqlKind = ast.getKind(); + } + + /** + *
+             *     key: logTbName
+             *     val: map {
+             *          key: grp
+             *          val: list of phy
+             *     }
+             *
+             * 
+ */ + Map>> logTbPhyTbListMapping = + new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + if (sqlKind != null && sqlKind.belongsTo(SqlKind.DML)) { + // if request with partition hint and dml with one broadcast table, refuse to do direct plan + if (StringUtils.isNotEmpty(ec.getPartitionHint())) { + for (String tb : visitor.getTableNames()) { + if (ec.getSchemaManager(schemaName).getTddlRuleManager().isBroadCast(tb)) { + throw new TddlRuntimeException(ErrorCode.ERR_MODIFY_BROADCAST_TABLE_BY_HINT_NOT_ALLOWED, + String.format("Not allowed to modify broadcast table[%s] by partition hint", tb)); + } + TableMeta tbMeta = ec.getSchemaManager(schemaName).getTable(String.valueOf(tb)); + if (tbMeta.isGsi() || tbMeta.withGsi()) { + throw new TddlRuntimeException( + ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_MODIFY_GSI_TABLE_DIRECTLY, + tb); + } + } + } + + if ((!pushdownHintOnGsi) || (!pushdownDmlOnBroadcast)) { + tableModified = + checkModifyGsiOrBroadcastDirectly(schemaName, modifiedPhyTableNames, ec, pushdownHintOnGsi, + pushdownDmlOnBroadcast); + } else { + tableModified = getModifiedTable(schemaName, modifiedPhyTableNames, ec); + } + allPhyTableNames = modifiedPhyTableNames; + } else if (sqlKind != null && sqlKind.belongsTo(SqlKind.QUERY)) { + Set> tableSet = PlanManagerUtil.getTableSetFromAst(ast); + allPhyTableNames.addAll(tableSet.stream().map(dbTb -> dbTb.getValue()).collect(Collectors.toList())); + } + + if (!usingAutoCommit && ( + (lockMode != SqlSelect.LockMode.UNDEF && sqlKind.belongsTo(SqlKind.QUERY)) || sqlKind.belongsTo( + SqlKind.DML))) { + buildLogTblPhyTblsMapping(schemaName, finalGroups, allPhyTableNames, ec, logTbPhyTbListMapping); + if (logTbPhyTbListMapping.size() > 1) { + // Not allowed access multi logical table by direct hint + throw new TddlRuntimeException(ErrorCode.ERR_NOT_SUPPORT, + "Unsupported to use direct HINT for modifying physical tables[%s] which is belong to more than one logical table[%s]", + String.join("", allPhyTableNames), String.join(",", logTbPhyTbListMapping.keySet())); + } else if (logTbPhyTbListMapping.isEmpty()) { + throw new TddlRuntimeException(ErrorCode.ERR_NOT_SUPPORT, + "Unsupported to use direct HINT for accessing physical tables[%s] which is not belong to any logical tables", + String.join("", allPhyTableNames)); + } + String logTb = logTbPhyTbListMapping.keySet().iterator().next(); + Map> grpToPhyTbls = logTbPhyTbListMapping.get(logTb); + if (grpToPhyTbls.size() > 1 && useGrpParallelism) { + throw new TddlRuntimeException(ErrorCode.ERR_NOT_SUPPORT, + String.format( + "Not allowed to use direct HINT to access more than one groups[%s] of db[%s] with auto mode in transaction, please use partition selection syntax instead.", + String.join(",", grpToPhyTbls.keySet()), schemaName) + ); + } + String grpName = grpToPhyTbls.keySet().iterator().next(); + List phyTblsOfOneGrp = grpToPhyTbls.get(grpName); + if (phyTblsOfOneGrp.size() > 1 && useGrpParallelism) { + throw new TddlRuntimeException(ErrorCode.ERR_NOT_SUPPORT, + String.format( + "Not allowed to use direct HINT to access more than one physical tables[%s] of table[%s] of db[%s] with auto mode in transaction, please use partition selection syntax instead.", + String.join(",", phyTblsOfOneGrp), logTb, schemaName) + ); + } + if (useGrpParallelism) { + PhyTableOperationUtil.enableIntraGroupParallelism(schemaName, ec); + shouldUseGrpConnId = true; + } + } + + if (shouldUseGrpConnId) { + String logTb = logTbPhyTbListMapping.keySet().iterator().next(); + Map> grpToPhyTbls = logTbPhyTbListMapping.get(logTb); + String grpName = grpToPhyTbls.keySet().iterator().next(); + List phyTblsOfOneGrp = grpToPhyTbls.get(grpName); + logTbls.add(logTb); + phyTbls.add(phyTblsOfOneGrp); + for (String group : finalGroups) { + checkGroupPrivileges(group, ec); + PhyQueryOperation phyQueryOperation = phyQueryBuilder.buildPhyQueryOperation( + cluster, RelTraitSet.createEmpty(), + schemaName, + logTbls, + phyTbls, + ast, + ast.getKind(), + lockMode, + group, + null, + true, + param, + dynamicParamIndex, + ec); + results.add(phyQueryOperation); + } // end of for + } else { + for (String group : finalGroups) { + checkGroupPrivileges(group, ec); + PhyQueryOperation phyQueryOperation = phyQueryBuilder.buildPhyQueryOperation( + cluster, RelTraitSet.createEmpty(), + schemaName, + logTbls, + phyTbls, + ast, + ast.getKind(), + lockMode, + group, + null, + false, + param, + dynamicParamIndex, + ec); + results.add(phyQueryOperation); + } // end of for + } + } + final ExecutionPlan result = new ExecutionPlan(originAst, wrapWithViewUnion(results), null, planProperties); + result.setModifiedTables(tableModified); + // disable tp slow check in hint direct mode + result.disableCheckTpSlow(); + return result; + } + private void checkGroupPrivileges(String group, ExecutionContext ec) { if (StringUtils.equalsIgnoreCase(group, MetaDbDataSource.DEFAULT_META_DB_GROUP_NAME)) { PolarPrivUtil diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintArgKey.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintArgKey.java index 37b5bab18..bad502bd1 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintArgKey.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintArgKey.java @@ -70,7 +70,7 @@ public class HintArgKey { public static final List QUERY_BLOCK_NAME_HINT = ImmutableList.of(HintArgKey.of("name", 0)); public static final List MERGE_UNION_SIZE_HINT = ImmutableList.of(HintArgKey.of("merge_union_size", 0)); public static final List INDEX_HINT = ImmutableList.of(HintArgKey.of("table", 0), - HintArgKey.of("index", 1)); + HintArgKey.of("index", 1), HintArgKey.of("local_index", 2)); public static final List INVENTORY_HINT = ImmutableList.of(HintArgKey.of("commit_on_success", 0), HintArgKey.of("rollback_on_fail", 1), HintArgKey.of("target_affect_row", 2), HintArgKey.of("row number", 3)); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdCoronaDbJson.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdCoronaDbJson.java index 5d004be8d..9aa32ba38 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdCoronaDbJson.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdCoronaDbJson.java @@ -95,6 +95,11 @@ public boolean isDirect() { && TStringUtil.isBlank(realtabs); } + public boolean isDirectWithRealTableName() { + return null != type && TStringUtil.equalsIgnoreCase(type, SimpleHintParser.TYPE_DIRECT) + && !TStringUtil.isBlank(realtabs); + } + public boolean isUseRouteCondition() { return null != type && !type.isEmpty(); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdIndex.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdIndex.java index 5a9743f71..7af597adf 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdIndex.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdIndex.java @@ -26,6 +26,7 @@ import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.parser.SqlParserPos; +import org.jetbrains.annotations.NotNull; /** * @author chenmo.cm @@ -33,40 +34,14 @@ public class HintCmdIndex extends BaseHintOperator implements HintCmdOperator { public final SqlIdentifier tableName; public final SqlIdentifier indexName; + private final SqlIdentifier localIndexName; public HintCmdIndex(SqlBasicCall hint, ExecutionContext ec) { super(hint, ec); - - final AtomicReference tmpTableName = new AtomicReference<>(null); - final AtomicReference tmpIndexName = new AtomicReference<>(null); - - getArgKeys().forEach(argKey -> { - final SqlNode value = this.argMap.get(argKey); - - if (null == value) { - return; - } - - switch (argKey.ordinal) { - case 0: - tmpTableName.set(Optional.of(value) - .filter(v -> v instanceof SqlIdentifier) - .map(v -> (SqlIdentifier) v) - .orElseGet(() -> new SqlIdentifier(RelUtils.stringValue(value), SqlParserPos.ZERO))); - break; - case 1: - tmpIndexName.set(Optional.of(value) - .filter(v -> v instanceof SqlIdentifier) - .map(v -> (SqlIdentifier) v) - .orElseGet(() -> new SqlIdentifier(RelUtils.stringValue(value), SqlParserPos.ZERO))); - break; - default: - break; - } // end of switch - }); - - this.tableName = tmpTableName.get(); - this.indexName = tmpIndexName.get(); + // init tableName + tableName = (SqlIdentifier) this.argMap.get(new HintArgKey("table", 0)); + indexName = (SqlIdentifier) this.argMap.get(new HintArgKey("index", 1)); + localIndexName = (SqlIdentifier) this.argMap.get(new HintArgKey("local_index", 2)); } @Override @@ -86,4 +61,8 @@ public String tableNameLast() { public String indexNameLast() { return Optional.ofNullable(indexName).map(SqlIdentifier::getLastName).orElse(null); } + + public SqlIdentifier getLocalIndexName() { + return localIndexName; + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdNode.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdNode.java index 4ca170d41..ddfade3ea 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdNode.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/operator/HintCmdNode.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Map; +import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.hint.util.HintUtil; import com.alibaba.polardbx.optimizer.utils.RelUtils; @@ -70,7 +71,6 @@ public HintCmdNode(SqlBasicCall hint, ExecutionContext ec) { public CmdBean handle(CmdBean current) { if (this.groups.size() > 0) { final List result = convertGroupIndex(current.getSchemaName(), this.groups, current); - current.setGroups(result); } return current; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/util/HintConverter.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/util/HintConverter.java index fc08330c2..1fa75af59 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/util/HintConverter.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/hint/util/HintConverter.java @@ -84,6 +84,8 @@ public static class HintCollection { private int directCount = 0; + private boolean directWithRealTableName = false; + private boolean hasPlanHint = false; public int routeCount = 0; @@ -104,6 +106,10 @@ public boolean route() { return nodeCount + scanCount + routeCount > 0; } + public boolean routeWithoutScan() { + return nodeCount + routeCount > 0 && scanCount == 0; + } + public boolean usePostPlanner() { return (cmdOnly() && !route()) || (inventoryHint != null && inventoryHint.getHints().size() > 0); } @@ -135,6 +141,10 @@ public boolean pushdownSqlOrRoute() { return directOnly() || nodeOnly() || route(); } + public boolean pushdownSqlOrRouteWithoutScan() { + return directOnly() || nodeOnly() || routeWithoutScan(); + } + public boolean hasPlanHint() { return hasPlanHint; } @@ -149,6 +159,10 @@ public void addHintOperator(HintAddOperator addOperator) { addCount++; } + public boolean directWithRealTableName() { + return directWithRealTableName; + } + public void pushdownHintOperator(HintPushdownOperator pushdownOperator) { pushdownHintResult.add(pushdownOperator); pushdownCount++; @@ -172,6 +186,9 @@ public void cmdHintOperator(HintCmdOperator cmdOperator) { } else if (((HintCmdCoronaDbJson) cmdOperator).isUseRouteCondition()) { routeCount++; } + if (((HintCmdCoronaDbJson) cmdOperator).isDirectWithRealTableName()) { + directWithRealTableName = true; + } break; case CMD_PLAN: hasPlanHint = true; @@ -190,6 +207,7 @@ public void merge(HintCollection other) { this.jsonCount += other.jsonCount; this.directCount += other.directCount; this.routeCount += other.routeCount; + this.directWithRealTableName = directWithRealTableName || other.directWithRealTableName; this.hasPlanHint = hasPlanHint || other.hasPlanHint; this.pushHintResult.addAll(other.pushHintResult); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/json/JsonContainProcessor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/json/JsonContainProcessor.java index f89cb5d88..1a0c482d4 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/json/JsonContainProcessor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/json/JsonContainProcessor.java @@ -42,12 +42,13 @@ public static boolean contains(Object target, Object candidate) { private static boolean arrayContains(JSONArray target, Object candidate) { if (JsonUtil.isJsonArray(candidate)) { + //fix: target should contain all candElement for (Object candElement : (JSONArray) candidate) { - if (contains(target, candElement)) { - return true; + if (!contains(target, candElement)) { + return false; } } - return false; + return true; } for (Object element : target) { if (contains(element, candidate)) { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/metadata/InfoSchemaCommon.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/metadata/InfoSchemaCommon.java index 07ec23419..2a8ffe3d1 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/metadata/InfoSchemaCommon.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/metadata/InfoSchemaCommon.java @@ -25,47 +25,47 @@ public class InfoSchemaCommon { - public static final String INFO_SCHEMA_QUERY_TITLE = "INFORMATION_SCHEMA_QUERY"; + public static final String INFO_SCHEMA_QUERY_TITLE = "INFORMATION_SCHEMA_QUERY"; - public static final String INFO_SCHEMA_TABLES = "TABLES"; - public static final String INFO_SCHEMA_COLUMNS = "COLUMNS"; - public static final String INFO_SCHEMA_STATISTICS = "STATISTICS"; - public static final String INFO_SCHEMA_SCHEMATA = "SCHEMATA"; + public static final String INFO_SCHEMA_TABLES = "TABLES"; + public static final String INFO_SCHEMA_COLUMNS = "COLUMNS"; + public static final String INFO_SCHEMA_STATISTICS = "STATISTICS"; + public static final String INFO_SCHEMA_SCHEMATA = "SCHEMATA"; - public static final String COLUMN_TABLE_SCHEMA = "TABLE_SCHEMA"; - public static final String COLUMN_TABLE_NAME = "TABLE_NAME"; - public static final String COLUMN_TABLE_TYPE = "TABLE_TYPE"; - public static final String COLUMN_COLUMN_NAME = "COLUMN_NAME"; - public static final String COLUMN_INDEX_SCHEMA = "INDEX_SCHEMA"; - public static final String COLUMN_INDEX_NAME = "INDEX_NAME"; - public static final String COLUMN_SCHEMA_NAME = "SCHEMA_NAME"; + public static final String COLUMN_TABLE_SCHEMA = "TABLE_SCHEMA"; + public static final String COLUMN_TABLE_NAME = "TABLE_NAME"; + public static final String COLUMN_TABLE_TYPE = "TABLE_TYPE"; + public static final String COLUMN_COLUMN_NAME = "COLUMN_NAME"; + public static final String COLUMN_INDEX_SCHEMA = "INDEX_SCHEMA"; + public static final String COLUMN_INDEX_NAME = "INDEX_NAME"; + public static final String COLUMN_SCHEMA_NAME = "SCHEMA_NAME"; - public static final int OFFSET_COLUMN_TABLE_SCHEMA = -3; - public static final int OFFSET_COLUMN_TABLE_NAME = -2; - public static final int OFFSET_COLUMN_TABLE_TYPE = -1; - public static final int OFFSET_COLUMN_COLUMN_NAME = -1; - public static final int OFFSET_COLUMN_INDEX_NAME = -1; - public static final int OFFSET_COLUMN_SCHEMA_NAME = -1; + public static final int OFFSET_COLUMN_TABLE_SCHEMA = -3; + public static final int OFFSET_COLUMN_TABLE_NAME = -2; + public static final int OFFSET_COLUMN_TABLE_TYPE = -1; + public static final int OFFSET_COLUMN_COLUMN_NAME = -1; + public static final int OFFSET_COLUMN_INDEX_NAME = -1; + public static final int OFFSET_COLUMN_SCHEMA_NAME = -1; - public static final String KEYWORD_SECONDARY_INDEX = "._"; + public static final String KEYWORD_SECONDARY_INDEX = "._"; - public static final String DEFAULT_TABLE_TYPE = "BASE TABLE"; + public static final String DEFAULT_TABLE_TYPE = "BASE TABLE"; + public static final String TABLE_TYPE_VIEW = "VIEW"; + public static final int LIMIT_DEFAULT_OFFSET = 0; + public static final int LIMIT_NO_OFFSET_SPECIFIED = -1; + public static final int LIMIT_NO_ROW_COUNT_SPECIFIED = -1; - public static final int LIMIT_DEFAULT_OFFSET = 0; - public static final int LIMIT_NO_OFFSET_SPECIFIED = -1; - public static final int LIMIT_NO_ROW_COUNT_SPECIFIED = -1; + public static final Set MYSQL_SYS_SCHEMAS = new HashSet<>(); + public static final Set SUPPORTED_TABLE_TYPES = new HashSet<>(); - public static final Set MYSQL_SYS_SCHEMAS = new HashSet<>(); - public static final Set SUPPORTED_TABLE_TYPES = new HashSet<>(); + public static final Set TABLES_STAT_NAMES = new HashSet<>(); + public static final Set TABLES_STAT_INDEXES = new HashSet<>(); - public static final Set TABLES_STAT_NAMES = new HashSet<>(); - public static final Set TABLES_STAT_INDEXES = new HashSet<>(); + public static final Map TABLES_SPECIAL_COLUMNS = new HashMap<>(); + public static final Map TABLES_COLUMN_MAPPING = new HashMap<>(); + public static final Map TABLES_COLUMN_MAPPING_REVERSED = new HashMap<>(); - public static final Map TABLES_SPECIAL_COLUMNS = new HashMap<>(); - public static final Map TABLES_COLUMN_MAPPING = new HashMap<>(); - public static final Map TABLES_COLUMN_MAPPING_REVERSED = new HashMap<>(); - - public static final Set COLUMN_ALIAS_MAPPING = new HashSet<>(); + public static final Set COLUMN_ALIAS_MAPPING = new HashSet<>(); static { MYSQL_SYS_SCHEMAS.add("PERFORMANCE_SCHEMA"); @@ -96,10 +96,10 @@ public class InfoSchemaCommon { } if (TABLES_SPECIAL_COLUMNS.keySet().contains(columnName)) { - TABLES_COLUMN_MAPPING.put(TABLES_SPECIAL_COLUMNS.get(columnName), new Object[] { columnName, i }); + TABLES_COLUMN_MAPPING.put(TABLES_SPECIAL_COLUMNS.get(columnName), new Object[] {columnName, i}); TABLES_COLUMN_MAPPING_REVERSED.put(columnName, TABLES_SPECIAL_COLUMNS.get(columnName)); } else { - TABLES_COLUMN_MAPPING.put(columnName.toUpperCase(), new Object[] { columnName, i }); + TABLES_COLUMN_MAPPING.put(columnName.toUpperCase(), new Object[] {columnName, i}); TABLES_COLUMN_MAPPING_REVERSED.put(columnName, columnName.toUpperCase()); } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLogger.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLogger.java index 5e116d015..94dfd6149 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLogger.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLogger.java @@ -30,9 +30,10 @@ public interface OptimizerAlertLogger { * log the alert when it's not too frequent * * @param ec ExecutionContext of the query + * @param object extra info to print * @return return if log success */ - boolean logDetail(ExecutionContext ec); + boolean logDetail(ExecutionContext ec, Object object); /** * collect alert count since last schedule job diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerBaseImpl.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerBaseImpl.java index 7c3f5bdf9..8331d5a91 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerBaseImpl.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerBaseImpl.java @@ -58,7 +58,7 @@ public void inc() { } @Override - public boolean logDetail(ExecutionContext ec) { + public boolean logDetail(ExecutionContext ec, Object object) { if (lock.tryLock()) { try { long lastTime = lastAccessTime.get(); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerPlanCacheImpl.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerPlanCacheImpl.java deleted file mode 100644 index 5c1a24d5c..000000000 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerPlanCacheImpl.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.optimizer.optimizeralert; - -import com.alibaba.polardbx.common.properties.ConnectionParams; -import com.alibaba.polardbx.common.properties.DynamicConfig; -import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.optimizer.core.planner.PlanCache; - -public class OptimizerAlertLoggerPlanCacheImpl extends OptimizerAlertLoggerBaseImpl { - public OptimizerAlertLoggerPlanCacheImpl() { - super(); - this.optimizerAlertType = OptimizerAlertType.PLAN_CACHE_FULL; - } - - @Override - public void inc() { - // do nothing - } - - @Override - public boolean logDetail(ExecutionContext ec) { - if (lock.tryLock()) { - try { - long lastTime = lastAccessTime.get(); - long currentTime = System.currentTimeMillis(); - if (currentTime >= lastTime + DynamicConfig.getInstance().getOptimizerAlertLogInterval()) { - lastAccessTime.set(currentTime); - // ec == null can only happen in test - if (ec != null - && (!ec.getParamManager().getBoolean(ConnectionParams.ENABLE_ALERT_TEST)) - && (PlanCache.getInstance().getCacheKeyCountForSelect() - <= PlanCache.getInstance().getCurrentCapacity() * 0.75)) { - return false; - } - // add here - totalCount.increment(); - logger.info(String.format("%s: current cache size { %d }", optimizerAlertType.name(), - PlanCache.getInstance().getCache().size())); - return true; - } - } finally { - lock.unlock(); - } - } - return false; - } -} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerSelectivityImpl.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerSelectivityImpl.java new file mode 100644 index 000000000..e66b9c4fc --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerSelectivityImpl.java @@ -0,0 +1,7 @@ +package com.alibaba.polardbx.optimizer.optimizeralert; + +public class OptimizerAlertLoggerSelectivityImpl extends OptimizerAlertLoggerStackBaseImpl { + public OptimizerAlertLoggerSelectivityImpl() { + this.optimizerAlertType = OptimizerAlertType.SELECTIVITY_ERR; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerSpmImpl.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerSpmImpl.java new file mode 100644 index 000000000..ef1772e6b --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerSpmImpl.java @@ -0,0 +1,7 @@ +package com.alibaba.polardbx.optimizer.optimizeralert; + +public class OptimizerAlertLoggerSpmImpl extends OptimizerAlertLoggerStackBaseImpl { + public OptimizerAlertLoggerSpmImpl() { + this.optimizerAlertType = OptimizerAlertType.SPM_ERR; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStackBaseImpl.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStackBaseImpl.java new file mode 100644 index 000000000..b6b78af8e --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStackBaseImpl.java @@ -0,0 +1,46 @@ +package com.alibaba.polardbx.optimizer.optimizeralert; + +import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; + +import java.io.PrintWriter; +import java.io.StringWriter; + +public class OptimizerAlertLoggerStackBaseImpl extends OptimizerAlertLoggerBaseImpl { + public OptimizerAlertLoggerStackBaseImpl() { + super(); + } + + @Override + public boolean logDetail(ExecutionContext ec, Object object) { + if (lock.tryLock()) { + try { + long lastTime = lastAccessTime.get(); + long currentTime = System.currentTimeMillis(); + if (currentTime >= lastTime + DynamicConfig.getInstance().getOptimizerAlertLogInterval()) { + lastAccessTime.set(currentTime); + if (ec == null) { + logger.info(optimizerAlertType.name()); + } else { + String stack = ""; + if (object instanceof Throwable) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + ((Throwable) object).printStackTrace(pw); + stack = sw.toString(); + } + logger.info(String.format("alert_type{ %s }: schema{ %s } trace_id { %s } stack %s", + optimizerAlertType.name(), + ec.getSchemaName(), + ec.getTraceId(), + stack)); + } + return true; + } + } finally { + lock.unlock(); + } + } + return false; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticImpl.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticImpl.java index 0418c5b32..cecd2b926 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticImpl.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticImpl.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.optimizer.optimizeralert; +import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.optimizer.context.ExecutionContext; public class OptimizerAlertLoggerStatisticImpl extends OptimizerAlertLoggerBaseImpl { @@ -25,8 +26,26 @@ public OptimizerAlertLoggerStatisticImpl() { } @Override - public boolean logDetail(ExecutionContext ec) { - // do nothing + public boolean logDetail(ExecutionContext ec, Object object) { + if (ec == null) { + return false; + } + if (lock.tryLock()) { + try { + long lastTime = lastAccessTime.get(); + long currentTime = System.currentTimeMillis(); + if (currentTime >= lastTime + DynamicConfig.getInstance().getOptimizerAlertLogInterval()) { + lastAccessTime.set(currentTime); + logger.info(String.format("alert_type{ %s }: schema{ %s } trace_id { %s }", + optimizerAlertType.name(), + ec.getSchemaName(), + ec.getTraceId())); + return true; + } + } finally { + lock.unlock(); + } + } return false; } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticInconsistentImpl.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticInconsistentImpl.java index 5e924ca53..cb014212a 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticInconsistentImpl.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticInconsistentImpl.java @@ -25,7 +25,7 @@ public OptimizerAlertLoggerStatisticInconsistentImpl() { } @Override - public boolean logDetail(ExecutionContext ec) { + public boolean logDetail(ExecutionContext ec, Object object) { // do nothing return false; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticJobInterruptImpl.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticJobInterruptImpl.java index 2f7ace016..c22a06dcd 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticJobInterruptImpl.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticJobInterruptImpl.java @@ -25,7 +25,7 @@ public OptimizerAlertLoggerStatisticJobInterruptImpl() { } @Override - public boolean logDetail(ExecutionContext ec) { + public boolean logDetail(ExecutionContext ec, Object object) { // do nothing return false; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerXplanImpl.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerXplanImpl.java deleted file mode 100644 index 4cc8de8f5..000000000 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerXplanImpl.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.optimizer.optimizeralert; - -public class OptimizerAlertLoggerXplanImpl extends OptimizerAlertLoggerBaseImpl { - public OptimizerAlertLoggerXplanImpl() { - super(); - this.optimizerAlertType = OptimizerAlertType.XPLAN_SLOW; - } -} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertManager.java index 258d60eba..dd406e791 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertManager.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertManager.java @@ -59,9 +59,22 @@ protected void doDestroy() { * core entry to log alert * * @param optimizerAlertType type of alerts + * @param ec Context need to print log * @return true if logTrace if printed */ public boolean log(OptimizerAlertType optimizerAlertType, ExecutionContext ec) { + return log(optimizerAlertType, ec, null); + } + + /** + * core entry to log alert + * + * @param optimizerAlertType type of alerts + * @param ec Context need to print log + * @param extra extra info to print log + * @return true if logTrace if printed + */ + public boolean log(OptimizerAlertType optimizerAlertType, ExecutionContext ec, Object extra) { if (!DynamicConfig.getInstance().optimizerAlert()) { return false; } @@ -74,7 +87,7 @@ public boolean log(OptimizerAlertType optimizerAlertType, ExecutionContext ec) { if (!DynamicConfig.getInstance().optimizerAlertLog()) { return false; } - return logger.logDetail(ec); + return logger.logDetail(ec, extra); } synchronized public List> collectByScheduleJob() { @@ -101,15 +114,15 @@ private static Map createLogger() { optimizerAlertLoggers = ImmutableMap.builder(); optimizerAlertLoggers.put(OptimizerAlertType.BKA_TOO_MUCH, new OptimizerAlertLoggerBKAImpl()); - optimizerAlertLoggers.put(OptimizerAlertType.XPLAN_SLOW, new OptimizerAlertLoggerXplanImpl()); - optimizerAlertLoggers.put(OptimizerAlertType.PLAN_CACHE_FULL, new OptimizerAlertLoggerPlanCacheImpl()); optimizerAlertLoggers.put(OptimizerAlertType.TP_SLOW, new OptimizerAlertLoggerTpImpl()); + optimizerAlertLoggers.put(OptimizerAlertType.SELECTIVITY_ERR, new OptimizerAlertLoggerSelectivityImpl()); + optimizerAlertLoggers.put(OptimizerAlertType.SPM_ERR, new OptimizerAlertLoggerSpmImpl()); optimizerAlertLoggers.put(OptimizerAlertType.STATISTIC_MISS, new OptimizerAlertLoggerStatisticImpl()); optimizerAlertLoggers.put(OptimizerAlertType.PRUNING_SLOW, new OptimizerAlertLoggerPruningSlowImpl()); optimizerAlertLoggers.put(OptimizerAlertType.STATISTIC_JOB_INTERRUPT, new OptimizerAlertLoggerStatisticJobInterruptImpl()); - optimizerAlertLoggers.put(OptimizerAlertType.STATISTIC_INCONSISTENT, - new OptimizerAlertLoggerStatisticInconsistentImpl()); +// optimizerAlertLoggers.put(OptimizerAlertType.STATISTIC_INCONSISTENT, +// new OptimizerAlertLoggerStatisticInconsistentImpl()); return optimizerAlertLoggers.build(); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertType.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertType.java index afcc49afd..27dee8086 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertType.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertType.java @@ -17,14 +17,13 @@ package com.alibaba.polardbx.optimizer.optimizeralert; public enum OptimizerAlertType { - BKA_TOO_MUCH, - XPLAN_SLOW, - TP_SLOW, - PLAN_CACHE_FULL, + SELECTIVITY_ERR, + + SPM_ERR, STATISTIC_MISS, diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertUtil.java index a24d57c4c..4fa8f5e80 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertUtil.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertUtil.java @@ -72,27 +72,23 @@ public static void tpAlert(ExecutionContext ec, double executeTimeMs) { } } - public static void xplanAlert(ExecutionContext ec, double executeTimeMs, long lastAffectedRows) { + public static void selectivityAlert(ExecutionContext ec, Throwable throwable) { if (!DynamicConfig.getInstance().optimizerAlert()) { return; } try { - if (xplanShouldAlert(ec, executeTimeMs, lastAffectedRows)) { - OptimizerAlertManager.getInstance().log(OptimizerAlertType.XPLAN_SLOW, ec); - } + OptimizerAlertManager.getInstance().log(OptimizerAlertType.SELECTIVITY_ERR, ec, throwable); } catch (Exception e) { // ignore } } - public static void plancacheAlert(ExecutionContext ec) { + public static void spmAlert(ExecutionContext ec, Throwable throwable) { if (!DynamicConfig.getInstance().optimizerAlert()) { return; } try { - if (planCacheShouldAlert(ec)) { - OptimizerAlertManager.getInstance().log(OptimizerAlertType.PLAN_CACHE_FULL, ec); - } + OptimizerAlertManager.getInstance().log(OptimizerAlertType.SPM_ERR, ec, throwable); } catch (Exception e) { // ignore } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/SqlParameterizeUtils.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/SqlParameterizeUtils.java index d22128f26..3a05f65d6 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/SqlParameterizeUtils.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/SqlParameterizeUtils.java @@ -37,6 +37,7 @@ import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized; import com.alibaba.polardbx.optimizer.parse.visitor.DrdsParameterizeSqlVisitor; import com.alibaba.polardbx.optimizer.parse.visitor.ParamCountVisitor; +import org.apache.calcite.sql.SqlBaseline; import java.util.ArrayList; import java.util.List; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/TableMetaParser.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/TableMetaParser.java index b8cef7068..33e4299b5 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/TableMetaParser.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/TableMetaParser.java @@ -202,7 +202,8 @@ public static TableMeta parse(String tableName, SqlCreateTable sqlCreateTable) { null, null, false, - true), true, true); + true, + null), true, true); } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/visitor/DrdsParameterizeSqlVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/visitor/DrdsParameterizeSqlVisitor.java index 1cef9947c..ad69affbb 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/visitor/DrdsParameterizeSqlVisitor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/visitor/DrdsParameterizeSqlVisitor.java @@ -19,6 +19,7 @@ import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.druid.sql.ast.SQLExpr; +import com.alibaba.polardbx.druid.sql.ast.SQLObject; import com.alibaba.polardbx.druid.sql.ast.SQLOver; import com.alibaba.polardbx.druid.sql.ast.expr.SQLAllColumnExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLCharExpr; @@ -41,9 +42,12 @@ import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.TStringUtil; +import com.alibaba.polardbx.druid.sql.visitor.VisitorFeature; +import com.alibaba.polardbx.druid.util.Pair; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.function.calc.scalar.LastInsertId; import com.alibaba.polardbx.optimizer.core.function.calc.scalar.datatime.Now; +import com.alibaba.polardbx.optimizer.parse.SqlParameterizeUtils; import com.alibaba.polardbx.optimizer.parse.bean.PreparedParamRef; import org.apache.calcite.sql.SqlCollation; import org.apache.calcite.util.NlsString; @@ -276,7 +280,7 @@ public boolean visit(SQLVariantRefExpr x) { return false; } - private void visitPreparedParam(SQLVariantRefExpr x) { + protected void visitPreparedParam(SQLVariantRefExpr x) { if (parameters != null) { parameters.add(new PreparedParamRef(x.getIndex())); } @@ -332,7 +336,9 @@ public boolean visit(SQLSelectItem x) { } else if (expr instanceof SQLIdentifierExpr) { aliasNew = ((SQLIdentifierExpr) expr).getName(); } else { - aliasNew = quoteString(SQLUtils.toMySqlString(expr)); + SQLUtils.FormatOption option = new SQLUtils.FormatOption(SqlParameterizeUtils.parameterizeFeatures); + option.setUppCase(isUppCase()); + aliasNew = quoteString(SQLUtils.toMySqlString(expr, option)); } this.print0(aliasNew); } @@ -556,4 +562,9 @@ public boolean visit(SQLOver x) { this.parameterized = parameterized; return visit; } + + @Override + public void postVisit(SQLObject x) { + // do nothing + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/visitor/DrdsUnparameterizeSqlVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/visitor/DrdsUnparameterizeSqlVisitor.java new file mode 100644 index 000000000..e11a2b17d --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/visitor/DrdsUnparameterizeSqlVisitor.java @@ -0,0 +1,69 @@ +package com.alibaba.polardbx.optimizer.parse.visitor; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.druid.sql.ast.SQLStatement; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.polardbx.druid.sql.parser.SQLStatementParser; +import com.alibaba.polardbx.druid.util.JdbcConstants; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.google.common.io.BaseEncoding; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import static com.alibaba.polardbx.druid.sql.parser.SQLParserUtils.createSQLStatementParser; + +public class DrdsUnparameterizeSqlVisitor extends DrdsParameterizeSqlVisitor { + private List parameterContextList; + + private int parameterIndex = 0; + + // WARNING!!! + // DON'T CALL THIS VISITOR, BECAUSE IT'S DESIGNED FOR ONLY ONE OCCASION, WHICH IS UNLIKELY YOURS. + public DrdsUnparameterizeSqlVisitor(Appendable appender, boolean parameterized, ExecutionContext executionContext, + List parameterContextList) { + super(appender, parameterized, executionContext); + this.parameterContextList = parameterContextList; + this.parameterIndex = 0; + } + + @Override + protected void visitPreparedParam(SQLVariantRefExpr x) { + ParameterContext parameterContext = parameterContextList.get(parameterIndex++); + ParameterMethod method = parameterContext.getParameterMethod(); + Object value = parameterContext.getValue(); + switch (method) { + case setInt: + print(Integer.valueOf(value.toString())); + break; + case setLong: + print(Long.valueOf(value.toString())); + break; + case setDouble: + print(Double.valueOf(value.toString())); + break; + case setBytes: + print(BaseEncoding.base16().decode(value.toString()).toString()); + break; + default: + print(value.toString()); + break; + } + } + + public static String unparameterizeSql(String sql, List params) { + SQLStatementParser statementParser = createSQLStatementParser(sql, JdbcConstants.MYSQL); + SQLStatement sqlStatment = statementParser.parseStatement(); + StringBuilder out = new StringBuilder(); + DrdsUnparameterizeSqlVisitor drdsUnparameterizeSqlVisitor = new DrdsUnparameterizeSqlVisitor( + out, + false, + new ExecutionContext(), + params + ); + sqlStatment.accept(drdsUnparameterizeSqlVisitor); + return out.toString(); + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/visitor/FastSqlToCalciteNodeVisitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/visitor/FastSqlToCalciteNodeVisitor.java index 1fe39010c..f149179b3 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/visitor/FastSqlToCalciteNodeVisitor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/parse/visitor/FastSqlToCalciteNodeVisitor.java @@ -104,13 +104,18 @@ import com.alibaba.polardbx.druid.sql.ast.expr.SQLSequenceExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLSomeExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLTextLiteralExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveDefinitionExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveJobExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLUnaryOperator; import com.alibaba.polardbx.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableAllocateLocalPartition; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableCleanupExpiredData; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableExpireLocalPartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableGroupSetLocality; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableGroupSetPartitionsLocality; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsArchivePartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsExtractHotKey; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsInspectIndexStatement; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsMergePartition; @@ -152,6 +157,7 @@ import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableItem; import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableModifyPartitionValues; import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableModifySubPartitionValues; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableOptimizePartition; import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTablePartitionCount; import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableRenameIndex; import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableReorgPartition; @@ -269,8 +275,10 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterStoragePoolStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableAsOfTimeStamp; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableBroadcast; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableModifyTtlOptions; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTablePartition; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTablePurgeBeforeTimeStamp; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableRemoveTtlOptions; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableSingle; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsBaselineStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCancelDDLJob; @@ -279,6 +287,7 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsChangeRuleVersionStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarPartition; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarSnapshot; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckGlobalIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclRulesStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclTriggersStatement; @@ -319,6 +328,8 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRemoveDDLJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRevokeSecurityLabelStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRollbackDDLJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowDdlEngineStatus; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsTerminateRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclRuleStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclTriggerStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowChangeSet; @@ -343,6 +354,7 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsSkipRebalanceSubjob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsSlowSqlCclStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsTerminateRebalanceJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsResumeRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsUnArchiveStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySql8ShowGrantsStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlAlterDatabaseSetOption; @@ -474,6 +486,7 @@ import com.alibaba.polardbx.optimizer.parse.FastSqlParserException.ExceptionType; import com.alibaba.polardbx.optimizer.parse.FastsqlParser; import com.alibaba.polardbx.optimizer.parse.FastsqlUtils; +import com.alibaba.polardbx.optimizer.parse.SqlParameterizeUtils; import com.alibaba.polardbx.optimizer.parse.TDDLSqlFunction; import com.alibaba.polardbx.optimizer.parse.TypeUtils; import com.alibaba.polardbx.optimizer.parse.bean.FieldMetaData; @@ -529,6 +542,9 @@ import org.apache.calcite.sql.SqlAlterTableAddPartition; import org.apache.calcite.sql.SqlAlterTableAllocateLocalPartition; import org.apache.calcite.sql.SqlAlterTableAlterIndex; +import org.apache.calcite.sql.SqlAlterTableArchivePartition; +import org.apache.calcite.sql.SqlAlterTableCleanupExpiredData; +import org.apache.calcite.sql.SqlAlterTableDropFile; import org.apache.calcite.sql.SqlAlterTableDropIndex; import org.apache.calcite.sql.SqlAlterTableDropPartition; import org.apache.calcite.sql.SqlAlterTableExchangePartition; @@ -547,11 +563,14 @@ import org.apache.calcite.sql.SqlAlterTableMergePartition; import org.apache.calcite.sql.SqlAlterTableModifyPartitionValues; import org.apache.calcite.sql.SqlAlterTableModifySubPartitionValues; +import org.apache.calcite.sql.SqlAlterTableModifyTtlOptions; import org.apache.calcite.sql.SqlAlterTableMovePartition; +import org.apache.calcite.sql.SqlAlterTableOptimizePartition; import org.apache.calcite.sql.SqlAlterTablePartitionCount; import org.apache.calcite.sql.SqlAlterTablePartitionKey; import org.apache.calcite.sql.SqlAlterTableRemoveLocalPartition; import org.apache.calcite.sql.SqlAlterTableRemovePartitioning; +import org.apache.calcite.sql.SqlAlterTableRemoveTtlOptions; import org.apache.calcite.sql.SqlAlterTableRenameIndex; import org.apache.calcite.sql.SqlAlterTableRenamePartition; import org.apache.calcite.sql.SqlAlterTableReorgPartition; @@ -576,6 +595,7 @@ import org.apache.calcite.sql.SqlCharStringLiteral; import org.apache.calcite.sql.SqlCheckColumnarIndex; import org.apache.calcite.sql.SqlCheckColumnarPartition; +import org.apache.calcite.sql.SqlCheckColumnarSnapshot; import org.apache.calcite.sql.SqlCheckGlobalIndex; import org.apache.calcite.sql.SqlCheckTable; import org.apache.calcite.sql.SqlClearCclRules; @@ -711,8 +731,13 @@ import org.apache.calcite.sql.SqlResetReplicaCheck; import org.apache.calcite.sql.SqlResetSlave; import org.apache.calcite.sql.SqlRestartMaster; +import org.apache.calcite.sql.SqlResumeRebalanceJob; import org.apache.calcite.sql.SqlRevokeSecurityLabel; import org.apache.calcite.sql.SqlRollbackDdlJob; +import org.apache.calcite.sql.SqlShowDdlEngine; +import org.apache.calcite.sql.SqlShowProfiles; +import org.apache.calcite.sql.SqlSubPartitionByCoHash; +import org.apache.calcite.sql.SqlTerminateRebalanceJob; import org.apache.calcite.sql.SqlShowProfiles; import org.apache.calcite.sql.SqlTerminateRebalanceJob; import org.apache.calcite.sql.SqlSavepoint; @@ -810,6 +835,9 @@ import org.apache.calcite.sql.SqlTableOptions.PackKeys; import org.apache.calcite.sql.SqlTableOptions.RowFormat; import org.apache.calcite.sql.SqlTerminateRebalanceJob; +import org.apache.calcite.sql.SqlTimeToLiveDefinitionExpr; +import org.apache.calcite.sql.SqlTimeToLiveExpr; +import org.apache.calcite.sql.SqlTimeToLiveJobExpr; import org.apache.calcite.sql.SqlTruncateTable; import org.apache.calcite.sql.SqlUnArchive; import org.apache.calcite.sql.SqlUnlockTable; @@ -876,6 +904,7 @@ * @since 6.0.0 */ public class FastSqlToCalciteNodeVisitor extends CalciteVisitor implements MySqlASTVisitor { + private static final BigInteger MAX_UNSIGNED_INT64 = new BigInteger(Long.toUnsignedString(0xffffffffffffffffL)); private static final BigInteger MIN_SIGNED_INT64 = new BigInteger(Long.toString(-0x7fffffffffffffffL - 1)); @@ -1478,6 +1507,11 @@ private List getDeleteTargetTables(final SQLTableSource x, List targetPartitions = new TreeSet<>(String::compareToIgnoreCase); + + for (SQLName sqlPartition : drdsArchivePartition.getPartitions()) { + SqlNode sqlPartNode = convertToSqlNode(sqlPartition); + String partName = Util.last(((SqlIdentifier) (sqlPartNode)).names).toLowerCase(); + targetPartitions.add(partName); + } + + this.sqlNode = + new SqlAlterTableArchivePartition(tableIdentifier, x.toString(), targetPartitions, + drdsArchivePartition.isSubPartitionsArchive()); + + return false; + } + if (x.getAlignToTableGroup() != null) { String targetTableGroup = SQLUtils.normalizeNoTrim(x.getAlignToTableGroup().getTablegroup().toString()); final SqlIdentifier targetTableGroupIdentifier = new SqlIdentifier(targetTableGroup, SqlParserPos.ZERO); @@ -3059,6 +3138,15 @@ public boolean visit(SQLAlterTableStatement x) { String targetImplicitTableGroup = SQLUtils.normalizeNoTrim(x.getTargetImplicitTableGroup().toString()); sqlAlterTableRemovePartitioning.setTargetImplicitTableGroupName(targetImplicitTableGroup); } + Map indexTgMap = sqlAlterTableRemovePartitioning.getIndexTableGroupMap(); + for (int i = 0; i < x.getIndexTableGroupPair().size(); i++) { + String indexName = SQLUtils.normalizeNoTrim(x.getIndexTableGroupPair().get(i).getKey().toString()); + String tgName = SQLUtils.normalizeNoTrim(x.getIndexTableGroupPair().get(i).getValue().toString()); + if (indexTgMap.containsKey(indexName)) { + throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_MANAGEMENT, "duplicate index name!"); + } + indexTgMap.put(indexName, tgName); + } this.sqlNode = sqlAlterTableRemovePartitioning; return false; } @@ -3066,6 +3154,7 @@ public boolean visit(SQLAlterTableStatement x) { List logicalReferencedTables = new ArrayList<>(); boolean gsiExists = false; + boolean cciExists = false; SequenceBean sequenceBean = null; Map> columnOpts = new HashMap<>(); SqlTableOptions tableOptions = null; @@ -3269,6 +3358,9 @@ public boolean visit(SQLAlterTableStatement x) { if (addIndex.isGlobal() || addIndex.isClustered()) { gsiExists = true; } + if (addIndex.isColumnar()) { + cciExists = true; + } } else if (sqlAlterTableItem instanceof SQLAlterTableDropIndex || sqlAlterTableItem instanceof SQLAlterTableDropKey) { final SqlAlterTableDropIndex sqlDropIndex = (SqlAlterTableDropIndex) alterItem; @@ -3279,6 +3371,9 @@ public boolean visit(SQLAlterTableStatement x) { if (gsiMeta.isGsi(indexName.getLastName())) { gsiExists = true; } + if (gsiMeta.isColumnar(indexName.getLastName())) { + cciExists = true; + } } else if (sqlAlterTableItem instanceof SQLAlterTableRenameIndex) { final SqlAlterTableRenameIndex sqlRenameIndex = (SqlAlterTableRenameIndex) alterItem; final SqlIdentifier indexName = sqlRenameIndex.getIndexName(); @@ -3288,6 +3383,9 @@ public boolean visit(SQLAlterTableStatement x) { if (gsiMeta.isGsi(indexName.getLastName())) { gsiExists = true; } + if (gsiMeta.isColumnar(indexName.getLastName())) { + cciExists = true; + } } else if (sqlAlterTableItem instanceof MySqlAlterTableAlterFullTextIndex) { final SqlAlterTableAlterIndex sqlAlterTableAlterIndex = (SqlAlterTableAlterIndex) alterItem; final SqlIdentifier indexName = sqlAlterTableAlterIndex.getIndexName(); @@ -3296,6 +3394,9 @@ public boolean visit(SQLAlterTableStatement x) { if (gsiMeta.isGsi(indexName.getLastName())) { gsiExists = true; } + if (gsiMeta.isColumnar(indexName.getLastName())) { + cciExists = true; + } } else if (sqlAlterTableItem instanceof SQLAlterTableAddExtPartition || sqlAlterTableItem instanceof SQLAlterTableDropExtPartition) { @@ -3540,6 +3641,11 @@ public boolean visit(SQLAlterTableStatement x) { } } + if (cciExists && (!columnOpts.isEmpty() || alters.size() > 1)) { + throw new FastSqlParserException(FastSqlParserException.ExceptionType.NOT_SUPPORT, + "Do not support mix ADD CLUSTERED COLUMNAR INDEX with other ALTER statements"); + } + if (gsiExists && (!columnOpts.isEmpty() || alters.size() > 1)) { throw new FastSqlParserException(FastSqlParserException.ExceptionType.NOT_SUPPORT, "Do not support mix ADD GLOBAL INDEX with other ALTER statements"); @@ -4036,7 +4142,8 @@ public boolean visit(SQLAlterTableAddIndex x) { engineName, dictColumns, x.getIndexDefinition().isWithImplicitTablegroup(), - x.getIndexDefinition().isVisible()); + x.getIndexDefinition().isVisible(), + x.getIndexDefinition().getColumnarOptions()); } else if (x.isClustered()) { indexDef = SqlIndexDefinition.clusteredIndex(SqlParserPos.ZERO, false, @@ -4548,7 +4655,8 @@ public SequenceBean convertTableElements(SqlIdentifier tableName, List 0) { List partNameList = new ArrayList<>(); @@ -5576,6 +5683,13 @@ public boolean visit(SQLExprTableSource x) { } partitions = new SqlNodeList(partNameList, SqlParserPos.ZERO); } + if (tableNameIdentifier instanceof SqlIdentifier) { + ((SqlIdentifier) tableNameIdentifier).partitions = partitions; + if (!x.getHints().isEmpty()) { + ((SqlIdentifier) tableNameIdentifier).indexNode = + FastSqlConstructUtils.constructForceIndex(x, context, ec); + } + } if (ec != null && SystemDbHelper.isDBBuildIn(x.getSchema())) { ec.setVisitDBBuildIn(true); @@ -5590,16 +5704,16 @@ public boolean visit(SQLExprTableSource x) { SqlTypeName.TIMESTAMP, SqlParserPos.ZERO); } - SqlNode sqlNodeHint = FastSqlConstructUtils.constructForceIndex(x, context, ec); - ((SqlIdentifier) tableNameIdentifier).indexNode = sqlNodeHint; - ((SqlIdentifier) tableNameIdentifier).partitions = partitions; - SqlOperator asOfOperator = null; if (x.isFlashbackWithTso()) { //as of tso: 8.0 使用 as of gcn; 5.7 使用 as of tso - asOfOperator = - InstanceVersion.isMYSQL80() ? SqlStdOperatorTable.AS_OF_80 : SqlStdOperatorTable.AS_OF_57; + if (InstanceVersion.isMYSQL80()) { + asOfOperator = SqlStdOperatorTable.AS_OF_80; + ec.setFlashbackArea(true); + } else { + asOfOperator = SqlStdOperatorTable.AS_OF_57; + } } else { //as of timestamp: 8.0 转成 as of gcn; 5.7 使用 as of timestamp asOfOperator = InstanceVersion.isMYSQL80() ? SqlStdOperatorTable.AS_OF_80 : SqlStdOperatorTable.AS_OF; @@ -7997,6 +8111,13 @@ public boolean visit(DrdsShowDDLJobs x) { return false; } + @Override + public boolean visit(DrdsShowDdlEngineStatus x) { + this.sqlNode = new SqlShowDdlEngine(SqlParserPos.ZERO, ImmutableList.of(SqlSpecialIdentifier.DDL, + SqlSpecialIdentifier.STATUS), false); + return false; + } + @Override public boolean visit(DrdsShowDDLResults x) { SqlShowDdlResults showDdlResults = new SqlShowDdlResults(SqlParserPos.ZERO, @@ -8097,6 +8218,16 @@ public boolean visit(DrdsTerminateRebalanceJob x) { return false; } + @Override + public boolean visit(DrdsResumeRebalanceJob x) { + SqlResumeRebalanceJob rollbackRebalanceJob = new SqlResumeRebalanceJob(SqlParserPos.ZERO, x.isAllJobs()); + if (!x.isAllJobs()) { + rollbackRebalanceJob.setJobIds(x.getJobIds()); + } + this.sqlNode = rollbackRebalanceJob; + return false; + } + @Override public boolean visit(DrdsCancelRebalanceJob x) { SqlTerminateRebalanceJob rollbackRebalanceJob = new SqlTerminateRebalanceJob(SqlParserPos.ZERO, x.isAllJobs()); @@ -8177,14 +8308,15 @@ public boolean visit(DrdsBaselineStatement x) { visitor.config(VisitorFeature.OutputParameterizedQuesUnMergeOr, true); visitor.config(VisitorFeature.OutputParameterizedQuesUnMergeAnd, true); visitor.setOutputParameters(outParameters); + visitor.setParameterizedMergeInList(true); x.getSelect().accept(visitor); SqlBaseline baseline = new SqlBaseline(SqlParserPos.ZERO, x.getOperation(), x.getBaselineIds(), - (SqlSelect) convertToSqlNode(x.getSelect()), null); + convertToSqlNode(x.getSelect())); - baseline.setParameterizedSql(builder.toString()); + baseline.setParameterizedSql(SqlParameterizeUtils.parameterize(x.getTargetSql()).getSql()); List headHints = x.getHeadHintsDirect(); if (headHints != null && headHints.size() == 1) { String hint = headHints.get(0).toString(); @@ -8201,13 +8333,14 @@ public boolean visit(DrdsBaselineStatement x) { visitor.config(VisitorFeature.OutputParameterizedQuesUnMergeOr, true); visitor.config(VisitorFeature.OutputParameterizedQuesUnMergeAnd, true); visitor.setOutputParameters(outParameters); + visitor.setParameterizedMergeInList(true); x.getSubStatement().accept(visitor); SqlBaseline baseline = new SqlBaseline(SqlParserPos.ZERO, x.getOperation(), x.getBaselineIds(), - null, convertToSqlNode(x.getSubStatement())); + convertToSqlNode(x.getSubStatement())); - baseline.setParameterizedSql(builder.toString()); + baseline.setParameterizedSql(SqlParameterizeUtils.parameterize(x.getTargetSql()).getSql()); List headHints = x.getHeadHintsDirect(); if (headHints != null && headHints.size() == 1) { String hint = headHints.get(0).toString(); @@ -8219,7 +8352,7 @@ public boolean visit(DrdsBaselineStatement x) { this.sqlNode = new SqlBaseline(SqlParserPos.ZERO, x.getOperation(), x.getBaselineIds(), - (SqlSelect) convertToSqlNode(x.getSelect()), null); + convertToSqlNode(x.getSelect())); } return false; } @@ -8350,7 +8483,8 @@ public boolean visit(DrdsCheckColumnarIndex x) { this.sqlNode = new SqlCheckColumnarIndex(SqlParserPos.ZERO, (SqlIdentifier) convertToSqlNode(x.getIndexName()), (SqlIdentifier) convertToSqlNode(x.getTableName()), - x.getExtraCmd()); + x.getExtraCmd(), + x.getExtras()); return false; } @@ -8361,6 +8495,13 @@ public boolean visit(DrdsCheckColumnarPartition x) { return false; } + @Override + public boolean visit(DrdsCheckColumnarSnapshot x) { + this.sqlNode = new SqlCheckColumnarSnapshot(SqlParserPos.ZERO, + convertToSqlNode(x.getTableName())); + return false; + } + @Override public boolean visit(MySqlUserName x) { this.sqlNode = new SqlUserName(x.getSimpleName(), x.getUserName(), x.getHost(), SqlParserPos.ZERO); @@ -9425,12 +9566,17 @@ public boolean visit(MySqlIndexHintImpl x) { SqlNodeList list = new SqlNodeList(SqlParserPos.ZERO); for (int i = 0; i < indexList.size(); i++) { SQLName sqlName = indexList.get(i); - String simpleName = sqlName.getSimpleName(); - if (context.isTestMode() && !simpleName.equalsIgnoreCase("PRIMARY")) { - simpleName = EagleeyeHelper.rebuildTableName(simpleName, true); + if (sqlName instanceof SQLPropertyExpr) { + String owner = ((SQLPropertyExpr) sqlName).getOwnerName(); + String name = ((SQLPropertyExpr) sqlName).getName(); + list.add(new SqlIdentifier(ImmutableList.of(owner, name), SqlParserPos.ZERO)); + } else { + String simpleName = sqlName.getSimpleName(); + if (context.isTestMode() && !simpleName.equalsIgnoreCase("PRIMARY")) { + simpleName = EagleeyeHelper.rebuildTableName(simpleName, true); + } + list.add(new SqlIdentifier(simpleName, SqlParserPos.ZERO)); } - SqlCharStringLiteral charString = SqlCharStringLiteral.createCharString(simpleName, SqlParserPos.ZERO); - list.add(charString); } String indexValue = IndexType.FORCE.getIndex(); if (x instanceof MySqlUseIndexHint) { @@ -9828,6 +9974,23 @@ public boolean visit(DrdsAlterTableExpireLocalPartition x) { return false; } + @Override + public void endVisit(DrdsAlterTableCleanupExpiredData x) { + + } + + @Override + public boolean visit(DrdsAlterTableCleanupExpiredData x) { + + List sqlNodes = new ArrayList<>(); + + SqlAlterTableCleanupExpiredData result = + new SqlAlterTableCleanupExpiredData(SqlParserPos.ZERO, sqlNodes); + + sqlNode = result; + return false; + } + @Override public boolean visit(SQLPartitionByList x) { SqlPartitionByList sqlPartitionByList = new SqlPartitionByList(SqlParserPos.ZERO); @@ -10147,6 +10310,21 @@ public boolean visit(SQLAlterTableReorgPartition x) { return false; } + @Override + public boolean visit(SQLAlterTableOptimizePartition x) { + assert x.getPartitions().size() >= 1; + List sqlNodes = new ArrayList<>(); + for (SQLObject sqlObject : x.getPartitions()) { + SqlNode partition = convertToSqlNode(sqlObject); + sqlNodes.add(partition); + } + + SqlAlterTableOptimizePartition sqlOptimizePartition = + new SqlAlterTableOptimizePartition(SqlParserPos.ZERO, sqlNodes, x.isSubPartition()); + sqlNode = sqlOptimizePartition; + return false; + } + @Override public boolean visit(DrdsCreateCclRuleStatement x) { SqlIdentifier ruleName = @@ -10821,6 +10999,85 @@ public boolean visit(SQLAlterTableModifySubPartitionValues x) { return false; } + @Override + public boolean visit(@NotNull DrdsAlterTableRemoveTtlOptions x) { + sqlNode = new SqlAlterTableRemoveTtlOptions(SqlParserPos.ZERO); + return false; + } + + @Override + public boolean visit(@NotNull DrdsAlterTableModifyTtlOptions x) { + SqlNode ttlEnableAst = convertToSqlNode(x.getTtlEnable()); + String ttlEnableStr = null; + if (ttlEnableAst != null) { + if (ttlEnableAst instanceof SqlCharStringLiteral) { + ttlEnableStr = SQLUtils.normalize(((SqlCharStringLiteral) ttlEnableAst).toValue()); + } + } + + SqlNode ttlExprAst = convertToSqlNode(x.getTtlExpr()); + SqlNode ttlJobAst = convertToSqlNode(x.getTtlJob()); + + String archiveTableSchemaStr = null; + SqlNode archiveTableSchemaAst = convertToSqlNode(x.getArchiveTableSchema()); + if (archiveTableSchemaAst != null) { + if (archiveTableSchemaAst instanceof SqlCharStringLiteral) { + archiveTableSchemaStr = SQLUtils.normalize(((SqlCharStringLiteral) archiveTableSchemaAst).toValue()); + } else { + + } + } + + String archiveTableNameStr = null; + SqlNode archiveTableNameAst = convertToSqlNode(x.getArchiveTableName()); + if (archiveTableNameAst != null) { + if (archiveTableNameAst instanceof SqlCharStringLiteral) { + archiveTableNameStr = SQLUtils.normalize(((SqlCharStringLiteral) archiveTableNameAst).toValue()); + } else { + + } + } + + String archiveKindStr = null; + SqlNode archiveKindAst = convertToSqlNode(x.getArchiveKind()); + if (archiveKindAst != null) { + if (archiveKindAst instanceof SqlCharStringLiteral) { + archiveKindStr = SQLUtils.normalize(((SqlCharStringLiteral) archiveKindAst).toValue()); + } else { + + } + } + + Integer arcPreAllocate = null; + SqlNode arcPreAllocateAst = convertToSqlNode(x.getArcPreAllocate()); + if (arcPreAllocateAst != null) { + if (arcPreAllocateAst instanceof SqlNumericLiteral) { + arcPreAllocate = Integer.valueOf(((SqlNumericLiteral) arcPreAllocateAst).intValue(true)); + } + } + + Integer arcPostAllocate = null; + SqlNode arcPostAllocateAst = convertToSqlNode(x.getArcPostAllocate()); + if (arcPostAllocateAst != null) { + if (arcPostAllocateAst instanceof SqlNumericLiteral) { + arcPostAllocate = Integer.valueOf(((SqlNumericLiteral) arcPostAllocateAst).intValue(true)); + } + } + + SqlAlterTableModifyTtlOptions sqlModifyTtlOptions = new SqlAlterTableModifyTtlOptions(SqlParserPos.ZERO); + sqlModifyTtlOptions.setTtlEnable(ttlEnableStr); + sqlModifyTtlOptions.setTtlExpr(ttlExprAst); + sqlModifyTtlOptions.setTtlJob(ttlJobAst); + sqlModifyTtlOptions.setArchiveTableSchema(archiveTableSchemaStr); + sqlModifyTtlOptions.setArchiveTableName(archiveTableNameStr); + sqlModifyTtlOptions.setArchiveKind(archiveKindStr); + sqlModifyTtlOptions.setArcPreAllocate(arcPreAllocate); + sqlModifyTtlOptions.setArcPostAllocate(arcPostAllocate); + + sqlNode = sqlModifyTtlOptions; + return false; + } + @Override public boolean visit(SQLCreateTableGroupStatement x) { List headHints = x.getHeadHintsDirect(); @@ -11486,6 +11743,9 @@ public boolean visit(SQLStartReplicaCheckTableStatement x) { if (x.getTableName() != null) { sqlNode.setTableName(convertToSqlNode(x.getTableName())); } + if (x.getMode() != null) { + sqlNode.setMode(convertToSqlNode(x.getMode())); + } this.sqlNode = sqlNode; return false; } @@ -11614,6 +11874,132 @@ public boolean visit(MySqlAlterInstanceStatement x) { return false; } + @Override + public void endVisit(SQLTimeToLiveDefinitionExpr x) { + + } + + @Override + public boolean visit(SQLTimeToLiveDefinitionExpr x) { + + SqlTimeToLiveDefinitionExpr sqlTimeToLiveDefinitionExpr = new SqlTimeToLiveDefinitionExpr(); + + SQLExpr ttlEnableExpr = x.getTtlEnableExpr(); + SQLExpr ttlExpr = x.getTtlExpr(); + SQLExpr ttlJobExpr = x.getTtlJobExpr(); + SQLExpr ttlFilterExpr = x.getTtlFilterExpr(); + SQLExpr archiveTypeExpr = x.getArchiveTypeExpr(); + SQLExpr archiveTableSchemaExpr = x.getArchiveTableSchemaExpr(); + SQLExpr archiveTableNameExpr = x.getArchiveTableNameExpr(); + SQLExpr archiveTablePreAllocateExpr = x.getArchiveTablePreAllocateExpr(); + SQLExpr archiveTablePostAllocateExpr = x.getArchiveTablePostAllocateExpr(); + + if (ttlEnableExpr != null) { + SqlNode ttlEnableAst = convertToSqlNode(ttlEnableExpr); + sqlTimeToLiveDefinitionExpr.setTtlEnableExpr(ttlEnableAst); + } + + if (ttlExpr != null) { + SqlNode ttlExprAst = convertToSqlNode(ttlExpr); + sqlTimeToLiveDefinitionExpr.setTtlExpr(ttlExprAst); + } + + if (ttlJobExpr != null) { + SqlNode ttlJobAst = convertToSqlNode(ttlJobExpr); + sqlTimeToLiveDefinitionExpr.setTtlJobExpr(ttlJobAst); + } + + if (ttlFilterExpr != null) { + SqlNode ttlFilterAst = convertToSqlNode(ttlFilterExpr); + sqlTimeToLiveDefinitionExpr.setTtlFilterExpr(ttlFilterAst); + } + + if (archiveTypeExpr != null) { + SqlNode archiveTypeAst = convertToSqlNode(archiveTypeExpr); + sqlTimeToLiveDefinitionExpr.setArchiveTypeExpr(archiveTypeAst); + } + + if (archiveTableSchemaExpr != null) { + SqlNode archiveTableSchemaAst = convertToSqlNode(archiveTableSchemaExpr); + sqlTimeToLiveDefinitionExpr.setArchiveTableSchemaExpr(archiveTableSchemaAst); + } + + if (archiveTableNameExpr != null) { + SqlNode archiveTableNameAst = convertToSqlNode(archiveTableNameExpr); + sqlTimeToLiveDefinitionExpr.setArchiveTableNameExpr(archiveTableNameAst); + } + + if (archiveTablePreAllocateExpr != null) { + SqlNode archiveTablePreAllocateAst = convertToSqlNode(archiveTablePreAllocateExpr); + sqlTimeToLiveDefinitionExpr.setArchiveTablePreAllocateExpr(archiveTablePreAllocateAst); + } + + if (archiveTablePostAllocateExpr != null) { + SqlNode archiveTablePostAllocateAst = convertToSqlNode(archiveTablePostAllocateExpr); + sqlTimeToLiveDefinitionExpr.setArchiveTablePostAllocateExpr(archiveTablePostAllocateAst); + } + + this.sqlNode = sqlTimeToLiveDefinitionExpr; + return false; + } + + @Override + public boolean visit(SQLTimeToLiveExpr x) { + SqlTimeToLiveExpr timeToLiveExpr = new SqlTimeToLiveExpr(); + + SQLExpr column = x.getColumn(); + if (column != null) { + timeToLiveExpr.setColumn(convertToSqlNode(column)); + } + + SQLExpr expireAfter = x.getExpireAfter(); + if (expireAfter != null) { + timeToLiveExpr.setExpireAfter(convertToSqlNode(expireAfter)); + } + + SQLExpr unit = x.getUnit(); + if (unit != null) { + timeToLiveExpr.setUnit(convertToSqlNode(unit)); + } + + SQLExpr timezone = x.getTimezone(); + if (timezone != null) { + timeToLiveExpr.setTimezone(convertToSqlNode(timezone)); + } + + this.sqlNode = timeToLiveExpr; + + return false; + } + + @Override + public void endVisit(SQLTimeToLiveExpr x) { + } + + @Override + public boolean visit(SQLTimeToLiveJobExpr x) { + + SqlTimeToLiveJobExpr timeToLiveJobExpr = new SqlTimeToLiveJobExpr(); + + SQLExpr cron = x.getCron(); + if (cron != null) { + timeToLiveJobExpr.setCron(convertToSqlNode(cron)); + } + + SQLExpr timezone = x.getTimezone(); + if (timezone != null) { + timeToLiveJobExpr.setTimezone(convertToSqlNode(timezone)); + } + this.sqlNode = timeToLiveJobExpr; + + return false; + } + + @Override + public void endVisit(SQLTimeToLiveJobExpr x) { + + } + private String getDefaultSchema() { return DefaultSchema.getSchemaName(); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartSpecBase.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartSpecBase.java index da240e2f3..a1c8076c0 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartSpecBase.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartSpecBase.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.gms.partition.ExtraFieldJSON; import com.alibaba.polardbx.gms.partition.TablePartitionRecord; +import com.alibaba.polardbx.gms.ttl.TtlPartArcState; import com.alibaba.polardbx.optimizer.partition.boundspec.PartitionBoundSpec; import com.alibaba.polardbx.optimizer.partition.common.PartitionLocation; import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy; @@ -211,6 +212,12 @@ public abstract class PartSpecBase { */ protected boolean useSpecTemplate = false; + /** + * Label if current partSpec (including its subparts if exists) + * of ttl-tmp table has been ready for oss data archiving, default is no_use + */ + protected Integer arcState = TtlPartArcState.ARC_STATE_NO_USE.getArcState(); + public PartitionStrategy getStrategy() { return strategy; } @@ -411,4 +418,12 @@ public Long getParentPartPosi() { public void setParentPartPosi(Long parentPartPosi) { this.parentPartPosi = parentPartPosi; } + + public int getArcState() { + return arcState; + } + + public void setArcState(Integer arcState) { + this.arcState = arcState; + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartSpecSearcher.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartSpecSearcher.java index 9271ca828..517fa6e3e 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartSpecSearcher.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartSpecSearcher.java @@ -20,7 +20,6 @@ import com.alibaba.polardbx.optimizer.partition.common.PartitionLocation; import com.alibaba.polardbx.optimizer.partition.common.PartitionTableType; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -52,6 +51,13 @@ public class PartSpecSearcher { * subpartSpec Temp */ protected Map subPartTempNameToSpecMap; + + /** + * key: phyPartName of subpart-table + * val: first-level partSpec + */ + protected Map phyPartNameToFirstLevelPartSpecMap; + protected PartitionTableType tableType; protected int phyPartCount; /** @@ -73,8 +79,10 @@ private PartSpecSearcher(PartitionTableType tableType, PartitionByDefinition par this.partNameToSpecMap = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); this.subPartTempNameToSpecMap = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); this.subPartSpecDefDigestMap = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + this.phyPartNameToFirstLevelPartSpecMap = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); partByDef.refreshPhysicalPartitionsCache(); List phySpecList = partByDef.getPhysicalPartitions(); + boolean useSubPartBy = partByDef.getSubPartitionBy() != null; this.phyPartCount = phySpecList.size(); for (int i = 0; i < phySpecList.size(); i++) { PartitionSpec p = phySpecList.get(i); @@ -109,6 +117,18 @@ private PartSpecSearcher(PartitionTableType tableType, PartitionByDefinition par this.subPartTempNameToSpecMap.put(subPartSpecTemps.get(i).getName(), subPartSpecTemps.get(i)); } } + + for (int i = 0; i < pSpecList.size(); i++) { + PartitionSpec p = pSpecList.get(i); + List spList = p.getSubPartitions(); + if (spList != null) { + for (int j = 0; j < spList.size(); j++) { + this.phyPartNameToFirstLevelPartSpecMap.put(spList.get(j).getName(), p); + } + } + } + } else { + this.phyPartNameToFirstLevelPartSpecMap.putAll(this.partNameToSpecMap); } } @@ -165,4 +185,7 @@ public boolean checkIfDuplicated(String newPartName) { return false; } + public Map getPhyPartNameToFirstLevelPartSpecMap() { + return phyPartNameToFirstLevelPartSpecMap; + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionByDefinition.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionByDefinition.java index 86503ed62..51582490f 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionByDefinition.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionByDefinition.java @@ -22,7 +22,9 @@ import com.alibaba.polardbx.common.utils.CaseInsensitive; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.time.calculator.MySQLIntervalType; +import com.alibaba.polardbx.gms.partition.ExtraFieldJSON; import com.alibaba.polardbx.gms.tablegroup.TableGroupConfig; +import com.alibaba.polardbx.gms.ttl.TtlPartArcState; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.partition.boundspec.PartitionBoundSpec; @@ -1839,6 +1841,26 @@ public boolean canPerformPruning(List actualUsedPartCols) { } } + /** + * Fetch all the first level partitions name which arc_state + * is from arc_state_ready (without oss files) or arc_state_reready (with oss files) + */ + public List getAllReadyArchivingPartitions() { + List results = new ArrayList<>(); + for (int i = 0; i < this.partitions.size(); i++) { + PartitionSpec partSpec = this.partitions.get(i); + ExtraFieldJSON extras = partSpec.extras; + if (extras != null) { + Integer arcState = partSpec.extras.getArcState(); + if (arcState != null && (arcState == TtlPartArcState.ARC_STATE_READY.getArcState() + || arcState == TtlPartArcState.ARC_STATE_REREADY.getArcState())) { + results.add(partSpec); + } + } + } + return results; + } + public PartKeyLevel getPhysicalPartLevel() { if (this.subPartitionBy != null) { return PartKeyLevel.SUBPARTITION_KEY; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfo.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfo.java index 801d8e68d..c7d6aefdd 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfo.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfo.java @@ -20,6 +20,8 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.utils.CaseInsensitive; import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.druid.util.StringUtils; import com.alibaba.polardbx.gms.partition.TablePartitionRecord; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; @@ -31,7 +33,6 @@ import com.alibaba.polardbx.optimizer.partition.common.PartitionTableType; import com.alibaba.polardbx.optimizer.partition.pruning.PhysicalPartitionInfo; import com.google.common.collect.Lists; -import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.HashMap; @@ -51,6 +52,9 @@ */ public class PartitionInfo { + private static final Logger logger = LoggerFactory.getLogger(PartitionInfo.class); + private static final Long MOCK_TABLE_VERSION = -2l; + /** * the id of logical table in table_partitions of metadb *
@@ -112,7 +116,7 @@ public class PartitionInfo {
     /**
      * The general partition flags
      */
-    protected Long partFlags;
+    protected Long partFlags = new Long(0L);
 
     /**
      * the locality Info
@@ -190,11 +194,12 @@ public boolean isPartitionedGsiTable() {
         return this.tableType == PartitionTableType.GSI_TABLE;
     }
 
-    public boolean isPartitionedTableOrGsiTable() {
-        return this.tableType == PartitionTableType.PARTITION_TABLE || this.tableType == PartitionTableType.GSI_TABLE;
+    public boolean isPartitionedTableOrGsiCciTable() {
+        return this.tableType == PartitionTableType.PARTITION_TABLE || this.tableType == PartitionTableType.GSI_TABLE
+            || this.tableType == PartitionTableType.COLUMNAR_TABLE;
     }
 
-    public boolean isColumnarTable() {
+    public boolean isPartitionedColumnarTable() {
         return this.tableType == PartitionTableType.COLUMNAR_TABLE;
     }
 
@@ -311,6 +316,10 @@ public void setAutoFlag(Integer autoFlag) {
         this.autoFlag = autoFlag;
     }
 
+    public boolean isTtlTemporary() {
+        return (this.partFlags & TablePartitionRecord.FLAG_TTL_TEMPORARY_TABLE) != 0;
+    }
+
     public Long getPartFlags() {
         return partFlags;
     }
@@ -400,9 +409,17 @@ public Map> getPhysicalPartitionTopology(Lis
                         if (ignoreInvalid && location != null && !location.isValidLocation()) {
                             continue;
                         }
+                        try {
+                            logger.error("Found invalid location info of " + this.getTableName() + " " + this.getDigest(
+                                MOCK_TABLE_VERSION));
+                        } catch (Exception e) {
+                            //pass
+                        }
                         throw GeneralUtil
                             .nestedException(new TddlRuntimeException(ErrorCode.ERR_EXECUTOR,
-                                "Found invalid location info of " + this.getTableName()));
+                                "Found invalid location info of " + this.getTableName() + "." + subPartName + (
+                                    (location == null) ?
+                                        "location is null" : "")));
                     }
 
                 }
@@ -440,9 +457,16 @@ public Map> getPhysicalPartitionTopology(Lis
                     if (ignoreInvalid && location != null && !location.isValidLocation()) {
                         continue;
                     }
+                    try {
+                        logger.error("Found invalid location info of " + this.getTableName() + " " + this.getDigest(
+                            MOCK_TABLE_VERSION));
+                    } catch (Exception e) {
+                        //pass
+                    }
                     throw GeneralUtil
                         .nestedException(new TddlRuntimeException(ErrorCode.ERR_EXECUTOR,
-                            "Found invalid location info of " + this.getTableName()));
+                            "Found invalid location info of " + this.getTableName() + "." + name + ((location == null) ?
+                                "location is null" : "")));
                 }
             }
         }
@@ -509,7 +533,8 @@ public String showCreateTablePartitionDefInfo(boolean showHashByRange, String te
 
     public Integer getAllPartLevelCount() {
         if (this.tableType != PartitionTableType.PARTITION_TABLE
-            && this.tableType != PartitionTableType.GSI_TABLE) {
+            && this.tableType != PartitionTableType.GSI_TABLE
+            && this.tableType != PartitionTableType.COLUMNAR_TABLE) {
             return 0;
         } else {
             return this.partitionBy.getAllPartLevelCount();
@@ -652,6 +677,7 @@ public void setStatus(Integer status) {
         this.status = status;
     }
 
+    //PartitionInfo.copy() won't copy PartitionByDefinitionBase.router
     public PartitionInfo copy() {
         PartitionInfo newPartInfo = new PartitionInfo();
         newPartInfo.setTableSchema(this.tableSchema);
@@ -730,7 +756,8 @@ public List> getAllLevelActualPartColMetas() {
     public List> getAllLevelActualPartCols() {
         PartitionTableType tableType = this.tableType;
         List> result = new ArrayList<>();
-        if (tableType != PartitionTableType.PARTITION_TABLE && tableType != PartitionTableType.GSI_TABLE) {
+        if (tableType != PartitionTableType.PARTITION_TABLE && tableType != PartitionTableType.GSI_TABLE
+            && tableType != PartitionTableType.COLUMNAR_TABLE) {
             result.add(Lists.newArrayList());
             result.add(Lists.newArrayList());
             return result;
@@ -742,7 +769,8 @@ public List> getAllLevelActualPartCols() {
     public List> getAllLevelFullPartCols() {
         PartitionTableType tableType = this.tableType;
         List> result = new ArrayList<>();
-        if (tableType != PartitionTableType.PARTITION_TABLE && tableType != PartitionTableType.GSI_TABLE) {
+        if (tableType != PartitionTableType.PARTITION_TABLE && tableType != PartitionTableType.GSI_TABLE
+            && tableType != PartitionTableType.COLUMNAR_TABLE) {
             result.add(Lists.newArrayList());
             result.add(Lists.newArrayList());
             return result;
@@ -995,6 +1023,9 @@ public String getDigest(Long tableVersion) {
         sb.append("tableVersion:");
         sb.append(tableVersion);
         sb.append(",");
+        sb.append("locality:");
+        sb.append(this.getLocality());
+        sb.append(",");
         sb.append(showCreateTablePartitionDefInfo(true));
         for (PartitionSpec partitionSpec : partitionBy.getPartitions()) {
             sb.append(partitionSpec.getDigest());
@@ -1007,7 +1038,7 @@ public String getDigest(Long tableVersion) {
 
     public boolean canPerformPruning(List actualUsedCols, PartKeyLevel level) {
         if (level == PartKeyLevel.PARTITION_KEY && (this.tableType == PartitionTableType.PARTITION_TABLE
-            || this.tableType == PartitionTableType.GSI_TABLE)) {
+            || this.tableType == PartitionTableType.GSI_TABLE || this.tableType == PartitionTableType.COLUMNAR_TABLE)) {
             return this.partitionBy.canPerformPruning(actualUsedCols);
         } else {
             return false;
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoBuilder.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoBuilder.java
index 10ff5fb0d..90bd52b13 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoBuilder.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoBuilder.java
@@ -109,11 +109,9 @@
 import org.apache.calcite.sql.SqlSubPartitionByList;
 import org.apache.calcite.sql.SqlSubPartitionByRange;
 import org.apache.calcite.sql.SqlSubPartitionByUdfHash;
-import org.apache.calcite.sql.dialect.MysqlSqlDialect;
 import org.apache.calcite.sql.fun.SqlSubstringFunction;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.calcite.sql.util.SqlString;
 import org.apache.commons.lang.StringUtils;
 
 import java.util.ArrayList;
@@ -139,7 +137,8 @@
 public class PartitionInfoBuilder {
 
     public static void prepareOrderNumForPartitions(PartitionTableType tblType, List partitions) {
-        if (tblType != PartitionTableType.PARTITION_TABLE && tblType != PartitionTableType.GSI_TABLE) {
+//        if (tblType != PartitionTableType.PARTITION_TABLE && tblType != PartitionTableType.GSI_TABLE) {
+        if (!tblType.isA(PartitionTableType.PARTITIONED_TABLE)) {
             for (int i = 0; i < partitions.size(); i++) {
                 partitions.get(i).setIntraGroupConnKey(null);
             }
@@ -211,7 +210,8 @@ public static PartitionInfo buildPartitionInfoByPartDefAst(String schemaName,
                                                                PartitionTableType tblType,
                                                                ExecutionContext ec) {
         return buildPartitionInfoByPartDefAst(schemaName, tableName, tableGroupName, withImplicitTableGroup,
-            joinGroupName, sqlPartitionBy, boundExprInfo, pkColMetas, allColMetas, tblType, ec, new LocalityDesc());
+            joinGroupName, sqlPartitionBy, boundExprInfo, pkColMetas, allColMetas, tblType, ec, new LocalityDesc(),
+            false);
     }
 
 //    public static PartitionInfo buildPartitionInfoByMetaDbConfigBackup(TablePartitionConfig tbPartConf,
@@ -292,7 +292,8 @@ public static PartitionInfo buildPartitionInfoByPartDefAst(String schemaName,
                                                                List allColMetas,
                                                                PartitionTableType tblType,
                                                                ExecutionContext ec,
-                                                               LocalityDesc locality) {
+                                                               LocalityDesc locality,
+                                                               boolean ttlTemporary) {
         BuildPartInfoFromAstParams buildParams = new BuildPartInfoFromAstParams();
         buildParams.setSchemaName(schemaName);
         buildParams.setTableName(tableName);
@@ -306,6 +307,7 @@ public static PartitionInfo buildPartitionInfoByPartDefAst(String schemaName,
         buildParams.setEc(ec);
         buildParams.setLocality(locality);
         buildParams.setWithImplicitTableGroup(withImplicitTableGroup);
+        buildParams.setTtlTemporary(ttlTemporary);
         PartitionInfo partitionInfo = buildPartInfoByAstParams(buildParams);
         return partitionInfo;
     }
@@ -675,7 +677,8 @@ public static PartitionInfo buildNewPartitionInfoByAddingPartition(ExecutionCont
                                                                        SqlAlterTableAddPartition addPartition,
                                                                        Map> partBoundExprInfoByLevel,
                                                                        List invisiblePartitionGroupRecords,
-                                                                       Map> physicalTableAndGroupPairs) {
+                                                                       Map> physicalTableAndGroupPairs,
+                                                                       boolean isColumnarIndex) {
         assert physicalTableAndGroupPairs.size() == invisiblePartitionGroupRecords.size();
         assert addPartition.getPartitions().size() == invisiblePartitionGroupRecords.size();
 
@@ -721,7 +724,7 @@ public static PartitionInfo buildNewPartitionInfoByAddingPartition(ExecutionCont
             if (!isAddSubPartitions) {
                 newPartitionSpec =
                     buildPartSpec(newSqlPartition, partByDef, newActualPartColCnts, partBoundExprInfoByLevel,
-                        phyPartCounter, partPosCounter, context);
+                        phyPartCounter, partPosCounter, isColumnarIndex, context);
             }
 
             if (subPartByDef != null) {
@@ -742,7 +745,7 @@ public static PartitionInfo buildNewPartitionInfoByAddingPartition(ExecutionCont
                                 buildAllSubPartSpec(newSqlPartition.getSubPartitions(), subPartByDef,
                                     partSpecWithNewSubParts, newActualPartColCnts,
                                     partBoundExprInfoByLevel, invisiblePartitionGroupRecordMap,
-                                    physicalTableAndGroupPairs, context);
+                                    physicalTableAndGroupPairs, isColumnarIndex, context);
 
                             if (!isNewSubPartSpecAdded) {
                                 PartitionInfoUtil.validateAddSubPartitions(partitionInfo, existingSubPartSpecs,
@@ -815,7 +818,7 @@ public static PartitionInfo buildNewPartitionInfoByAddingPartition(ExecutionCont
                                     buildAllSubPartSpec(newSqlPartition.getSubPartitions(), subPartByDef,
                                         partSpecWithNewSubParts, newActualPartColCnts,
                                         partBoundExprInfoByLevel, invisiblePartitionGroupRecordMap,
-                                        physicalTableAndGroupPairs, context);
+                                        physicalTableAndGroupPairs, isColumnarIndex, context);
 
                                 newSubPartitionSpecs.addAll(newSubPartSpecs);
                                 newPartitionSpecs.add(partSpecWithNewSubParts);
@@ -838,7 +841,7 @@ public static PartitionInfo buildNewPartitionInfoByAddingPartition(ExecutionCont
                                 buildAllSubPartSpec(newSqlPartition.getSubPartitions(), subPartByDef,
                                     newPartitionSpec, newActualPartColCnts,
                                     partBoundExprInfoByLevel, invisiblePartitionGroupRecordMap,
-                                    physicalTableAndGroupPairs, context);
+                                    physicalTableAndGroupPairs, isColumnarIndex, context);
                             newSubPartitionSpecs.addAll(newSubPartSpecs);
                         }
                     }
@@ -886,6 +889,7 @@ public static List buildAllSubPartSpec(List newSubPartit
                                                           Map> partBoundExprInfoByLevel,
                                                           Map invisiblePartitionGroupRecordMap,
                                                           Map> physicalTableAndGroupPairs,
+                                                          boolean isColumnarIndex,
                                                           ExecutionContext context) {
         List newSubPartitionSpecs = new ArrayList<>();
 
@@ -924,6 +928,7 @@ public static List buildAllSubPartSpec(List newSubPartit
                     parentPartitionSpec,
                     phySubPartCounter,
                     subPartPosCounter,
+                    isColumnarIndex,
                     context
                 );
             } else if (subStrategy == PartitionStrategy.RANGE || subStrategy == PartitionStrategy.RANGE_COLUMNS
@@ -936,6 +941,7 @@ public static List buildAllSubPartSpec(List newSubPartit
                     parentPartitionSpec,
                     phySubPartCounter,
                     subPartPosCounter,
+                    isColumnarIndex,
                     context
                 );
             } else {
@@ -971,22 +977,14 @@ public static List buildAllSubPartSpec(List newSubPartit
     public static PartitionInfo buildNewPartitionInfoByDroppingPartition(PartitionInfo partitionInfo,
                                                                          SqlAlterTableDropPartition dropPartition,
                                                                          List oldPartitionNameList,
-                                                                         List newPartitionNameList,
-                                                                         List invisiblePartitionGroupRecords,
-                                                                         Map> physicalTableAndGroupPairs,
                                                                          ExecutionContext context) {
         Set origDroppedPartNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
         Set oldPartitionNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
-        Set newPartitionNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
 
         origDroppedPartNames.addAll(
             dropPartition.getPartitionNames().stream().map(o -> ((SqlIdentifier) o).getLastName())
                 .collect(Collectors.toList()));
         oldPartitionNames.addAll(oldPartitionNameList);
-        newPartitionNames.addAll(newPartitionNameList);
-
-        assert !GeneralUtil.isNotEmpty(invisiblePartitionGroupRecords)
-            || physicalTableAndGroupPairs.size() == invisiblePartitionGroupRecords.size();
 
         PartitionInfo newPartInfo = partitionInfo.copy();
 
@@ -1009,13 +1007,6 @@ public static PartitionInfo buildNewPartitionInfoByDroppingPartition(PartitionIn
                         continue;
                     }
 
-                    if (newPartitionNames.contains(subPartName)) {
-                        Pair phyTableAndGroup = physicalTableAndGroupPairs.get(subPartName);
-                        subSpec.getLocation().setVisiable(false);
-                        subSpec.getLocation().setPhyTableName(phyTableAndGroup.getKey());
-                        subSpec.getLocation().setGroupKey(phyTableAndGroup.getValue());
-                    }
-
                     newSubPartSpecList.add(subSpec);
                 }
 
@@ -1051,13 +1042,6 @@ public static PartitionInfo buildNewPartitionInfoByDroppingPartition(PartitionIn
                     continue;
                 }
 
-                if (newPartitionNames.contains(partName)) {
-                    Pair phyTableAndGroup = physicalTableAndGroupPairs.get(partName);
-                    spec.getLocation().setVisiable(false);
-                    spec.getLocation().setPhyTableName(phyTableAndGroup.getKey());
-                    spec.getLocation().setGroupKey(phyTableAndGroup.getValue());
-                }
-
                 newPartSpecList.add(spec);
             }
         }
@@ -1673,6 +1657,7 @@ public static PartitionSpec buildPartSpec(SqlPartition newSqlPartition,
                                               Map> partBoundExprInfoByLevel,
                                               AtomicInteger phyPartCounter,
                                               AtomicInteger partPosCounter,
+                                              boolean isColumnarIndex,
                                               ExecutionContext context) {
         List partColMetaList = partByDef.getPartitionFieldList();
         SearchDatumComparator comparator = partByDef.getPruningSpaceComparator();
@@ -1698,6 +1683,9 @@ public static PartitionSpec buildPartSpec(SqlPartition newSqlPartition,
         partSpecAstParams.setSubPartSpec(false);
         partSpecAstParams.setParentPartSpec(null);
         partSpecAstParams.setPhySpecCounter(phyPartCounter);
+        partSpecAstParams.setPartEngine(isColumnarIndex ?
+            TablePartitionRecord.PARTITION_ENGINE_COLUMNAR :
+            TablePartitionRecord.PARTITION_ENGINE_INNODB);
 
         return buildPartSpecByAstParamInner(partSpecAstParams);
     }
@@ -1713,6 +1701,7 @@ public static PartitionSpec buildSubPartSpecForKey(SqlSubPartition newSubPartiti
                                                        PartitionSpec parentPartitionSpec,
                                                        AtomicInteger phySubPartCounter,
                                                        AtomicInteger subPartPosCounter,
+                                                       boolean isColumnarIndex,
                                                        ExecutionContext context) {
         List subPartColMetaList = subPartByDef.getPartitionFieldList();
         SearchDatumComparator comparator = subPartByDef.getPruningSpaceComparator();
@@ -1739,6 +1728,9 @@ public static PartitionSpec buildSubPartSpecForKey(SqlSubPartition newSubPartiti
         partSpecAstParams.setSubPartSpec(true);
         partSpecAstParams.setParentPartSpec(parentPartitionSpec);
         partSpecAstParams.setPhySpecCounter(phySubPartCounter);
+        partSpecAstParams.setPartEngine(isColumnarIndex ?
+            TablePartitionRecord.PARTITION_ENGINE_COLUMNAR :
+            TablePartitionRecord.PARTITION_ENGINE_INNODB);
 
         return buildPartSpecByAstParamInner(partSpecAstParams);
     }
@@ -1750,6 +1742,7 @@ public static PartitionSpec buildSubPartSpecForRangeOrList(SqlSubPartition newSu
                                                                PartitionSpec parentPartitionSpec,
                                                                AtomicInteger phySubPartCounter,
                                                                AtomicInteger subPartPosCounter,
+                                                               boolean isColumnarIndex,
                                                                ExecutionContext context) {
         List subPartColMetaList = subPartByDef.getPartitionFieldList();
         SearchDatumComparator comparator = subPartByDef.getPruningSpaceComparator();
@@ -1774,6 +1767,10 @@ public static PartitionSpec buildSubPartSpecForRangeOrList(SqlSubPartition newSu
         partSpecAstParams.setSubPartSpec(true);
         partSpecAstParams.setParentPartSpec(parentPartitionSpec);
         partSpecAstParams.setPhySpecCounter(phySubPartCounter);
+        partSpecAstParams.setPartEngine(isColumnarIndex ?
+            TablePartitionRecord.PARTITION_ENGINE_COLUMNAR :
+            TablePartitionRecord.PARTITION_ENGINE_INNODB);
+
         return buildPartSpecByAstParamInner(partSpecAstParams);
     }
 
@@ -2083,6 +2080,7 @@ public static PartitionByDefinition buildCompletePartByDefByAstParams(BuildPartB
                 subPartByAstParam.setParentPartSpecs(partByDef.getPartitions());
                 subPartByAstParam.setParentPartSpecAstList(sqlPartitionBy.getPartitions());
                 subPartByAstParam.setContainNextLevelPartSpec(false);
+                subPartByAstParam.setTtlTemporary(buildParams.isTtlTemporary());
                 PartitionByDefinition subPartByDef = buildPartByDefByAstParams(subPartByAstParam);
                 partByDef.setSubPartitionBy(subPartByDef);
             }
@@ -2232,6 +2230,8 @@ public static PartitionByDefinition buildPartByDefByAstParams(BuildPartByDefFrom
         List partExprTypeList = new ArrayList<>();
         int allPhyGroupCnt = HintUtil.allGroup(schemaName).size();
 
+        boolean ttlTemporary = buildParams.isTtlTemporary();
+
         if (tblType.isA(PartitionTableType.PARTITIONED_TABLE)) {
 
             columns = partByAstColumns;
@@ -2410,6 +2410,7 @@ public static PartitionByDefinition buildPartByDefByAstParams(BuildPartByDefFrom
         buildAllPartSpecsAstParams.setUseSubPartTemplate(useSubPartTemplate);
         buildAllPartSpecsAstParams.setContainNextLevelPartSpec(containNextLevelPartSpec);
         buildAllPartSpecsAstParams.setPhyPartCounter(phyPartCounter);
+        buildAllPartSpecsAstParams.setTtlTemporary(ttlTemporary);
         partSpecList = buildAllPartBySpecList(buildAllPartSpecsAstParams);
         partitionByDef.setPartitions(partSpecList);
         /**
@@ -2495,6 +2496,7 @@ public static PartitionByDefinition buildPartByDefByAstParams(BuildPartByDefFrom
                     buildAllSubPartSpecsAstParams.setContainNextLevelPartSpec(false);
                     buildAllSubPartSpecsAstParams.setParentPartSpec(parentPartSpec);
                     buildAllSubPartSpecsAstParams.setPhyPartCounter(phyPartCounter);
+                    buildAllSubPartSpecsAstParams.setTtlTemporary(ttlTemporary);
                     List subPartSpecList = buildAllPartBySpecList(buildAllSubPartSpecsAstParams);
                     parentPartSpec.setSubPartitions(subPartSpecList);
 
@@ -2640,12 +2642,15 @@ public static PartitionInfo buildPartInfoByAstParams(BuildPartInfoFromAstParams
         ExecutionContext ec = buildParams.getEc();
         LocalityDesc tblLocality = buildParams.getLocality();
         TableGroupConfig tableGroupConfig = null;
+        boolean ttlTemporary = buildParams.isTtlTemporary();
         if (tblLocality.isEmpty() && !StringUtils.isEmpty(tableGroupName)) {
             TableGroupInfoManager tableGroupInfoManager =
                 OptimizerContext.getContext(schemaName).getTableGroupInfoManager();
             tableGroupConfig = tableGroupInfoManager.getTableGroupConfigByName(tableGroupName);
             if (!(buildParams.isWithImplicitTableGroup() && tableGroupConfig == null)) {
-                tblLocality = tableGroupConfig.getLocalityDesc();
+                if (tableGroupConfig != null) {
+                    tblLocality = tableGroupConfig.getLocalityDesc();
+                }
             }
         }
 
@@ -2655,6 +2660,11 @@ public static PartitionInfo buildPartInfoByAstParams(BuildPartInfoFromAstParams
         PartitionStrategy partStrategy = buildPartByStrategy(schemaName, sqlPartitionBy, tblType);
         boolean containNextLevelPartSpec = sqlPartitionBy != null && sqlPartitionBy.getSubPartitionBy() != null;
 
+        long partFlags = 0L;
+        if (ttlTemporary) {
+            partFlags |= TablePartitionRecord.FLAG_TTL_TEMPORARY_TABLE;
+        }
+
         /**
          * Build PartitionBy for partition
          */
@@ -2674,6 +2684,7 @@ public static PartitionInfo buildPartInfoByAstParams(BuildPartInfoFromAstParams
         partByAstParam.setEc(ec);
         partByAstParam.setBuildSubPartBy(false);
         partByAstParam.setContainNextLevelPartSpec(containNextLevelPartSpec);
+        partByAstParam.setTtlTemporary(ttlTemporary);
         PartitionByDefinition partByDef = buildCompletePartByDefByAstParams(partByAstParam, sqlPartitionBy);
         PartitionByDefinition subPartByDef = partByDef.getSubPartitionBy();
         partitionInfo.setPartitionBy(partByDef);
@@ -2689,7 +2700,7 @@ public static PartitionInfo buildPartInfoByAstParams(BuildPartInfoFromAstParams
         partitionInfo.setTableName(tbName);
         partitionInfo.setTableSchema(tbSchema);
         partitionInfo.setAutoFlag(TablePartitionRecord.PARTITION_AUTO_BALANCE_DISABLE);
-        partitionInfo.setPartFlags(0L);
+        partitionInfo.setPartFlags(partFlags);
         partitionInfo.setTableType(tblType);
         partitionInfo.setRandomTableNamePatternEnabled(ec.isRandomPhyTableEnabled());
         partitionInfo.setSessionVars(saveSessionVars(ec));
@@ -2841,7 +2852,7 @@ protected static PartitionByDefinition buildPartByDefByMetaDbParams(BuildPartByD
                 ColumnMeta cm = null;
                 for (int j = 0; j < allColumnMetas.size(); j++) {
                     ColumnMeta colMeta = allColumnMetas.get(j);
-                    if (colMeta.getOriginColumnName().equalsIgnoreCase(partColName)) {
+                    if (partColName.equalsIgnoreCase(colMeta.getOriginColumnName())) {
                         cm = colMeta;
                         break;
                     }
@@ -3004,9 +3015,16 @@ private static List buildAllPartSpecsByMetaParams(BuildAllPartSpe
                         partitionGroupRecord.getId());
             partitionSpec.setLocation(location);
 
-            if (extras != null && TStringUtil.isNotEmpty(extras.getLocality())) {
-                LocalityDesc locality = LocalityDesc.parse(extras.getLocality());
-                partitionSpec.setLocality(locality.toString());
+            if (extras != null) {
+
+                if (TStringUtil.isNotEmpty(extras.getLocality())) {
+                    LocalityDesc locality = LocalityDesc.parse(extras.getLocality());
+                    partitionSpec.setLocality(locality.toString());
+                }
+
+                if (extras.getArcState() != null) {
+                    partitionSpec.setArcState(extras.getArcState());
+                }
             }
 
             if (!buildSubPartBy) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoManager.java
index f5b6021c6..2d1ff4ba9 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoManager.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoManager.java
@@ -41,8 +41,10 @@
 import com.alibaba.polardbx.optimizer.partition.pruning.PhysicalPartitionInfo;
 import com.alibaba.polardbx.optimizer.partition.util.TableMetaFetcher;
 import com.alibaba.polardbx.optimizer.rule.TddlRuleManager;
+import lombok.Setter;
 import lombok.val;
 import org.apache.commons.lang.StringUtils;
+import org.jetbrains.annotations.Nullable;
 
 import java.sql.Connection;
 import java.util.HashMap;
@@ -98,6 +100,7 @@ public class PartitionInfoManager extends AbstractLifecycle {
      */
     protected boolean isMock = false;
 
+    @Setter
     /**
      * The default phy db for broadcast tbl
      */
@@ -547,52 +550,15 @@ private synchronized void loadPartInfo(TableMeta tableMeta, List tablePartitionRecordsFromDelta,
                                                boolean fromDeltaTable) {
             try {
-
-                TablePartitionConfig tbPartConf = null;
-
-                // Fetch logical config
-                TablePartitionRecord logTbRec = fromDeltaTable ? tablePartitionRecordsFromDelta.stream()
-                    .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_LOGICAL_TABLE).findFirst().get() :
-                    tablePartitionRecords.stream()
-                        .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_LOGICAL_TABLE).findFirst()
-                        .get();
-
-                // Fetch partition configs
-                List partitionRecList = fromDeltaTable ? tablePartitionRecordsFromDelta.stream()
-                    .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_PARTITION)
-                    .collect(Collectors.toList()) :
-                    tablePartitionRecords.stream()
-                        .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_PARTITION)
-                        .collect(Collectors.toList());
-
-                // Fetch subpartition configs
-                List subPartitionRecList =
-                    fromDeltaTable ? tablePartitionRecordsFromDelta.stream()
-                        .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_SUBPARTITION)
-                        .collect(Collectors.toList()) :
-                        tablePartitionRecords.stream()
-                            .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_SUBPARTITION)
-                            .collect(Collectors.toList());
-
-                TablePartRecordInfoContext confCtx = new TablePartRecordInfoContext();
-                confCtx.setLogTbRec(logTbRec);
-                confCtx.setPartitionRecList(partitionRecList);
-                confCtx.setSubPartitionRecList(subPartitionRecList);
-                tbPartConf = TablePartitionAccessor.buildPartitionConfByPartitionRecords(confCtx);
-
-                if (tbPartConf.getTableConfig().partStatus
-                    != TablePartitionRecord.PARTITION_STATUS_LOGICAL_TABLE_PUBLIC && !includeNonPublic) {
+                PartitionInfo partInfo =
+                    generatePartitionInfo(tableMeta.getPhysicalColumns(), tablePartitionRecords,
+                        tablePartitionRecordsFromDelta,
+                        fromDeltaTable, includeNonPublic);
+                if (partInfo == null) {
                     return;
                 }
-                List allColumnMetas = tableMeta.getPhysicalColumns();
-                Map partitionGroupRecordsMap =
-                    TableGroupUtils.getPartitionGroupsMapByGroupId(tbPartConf.getTableConfig().getGroupId());
-                PartitionInfo partInfo =
-                    PartitionInfoBuilder.buildPartitionInfoByMetaDbConfig(tbPartConf, allColumnMetas,
-                        partitionGroupRecordsMap);
                 this.partInfo = partInfo;
                 this.tableGroupId = partInfo.getTableGroupId();
-                return;
             } catch (Throwable ex) {
                 String msg =
                     String.format("Failed to load partitionInfo[%s.%s] from metadb", manager.schemaName, tbName);
@@ -603,6 +569,53 @@ private synchronized void loadPartInfo(TableMeta tableMeta, List allColumnMetas,
+                                                      List tablePartitionRecords,
+                                                      List tablePartitionRecordsFromDelta,
+                                                      boolean fromDeltaTable, boolean includeNonPublic) {
+        TablePartitionConfig tbPartConf = null;
+
+        // Fetch logical config
+        TablePartitionRecord logTbRec = fromDeltaTable ? tablePartitionRecordsFromDelta.stream()
+            .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_LOGICAL_TABLE).findFirst().get() :
+            tablePartitionRecords.stream()
+                .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_LOGICAL_TABLE).findFirst()
+                .get();
+
+        // Fetch partition configs
+        List partitionRecList = fromDeltaTable ? tablePartitionRecordsFromDelta.stream()
+            .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_PARTITION)
+            .collect(Collectors.toList()) :
+            tablePartitionRecords.stream()
+                .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_PARTITION)
+                .collect(Collectors.toList());
+
+        // Fetch subpartition configs
+        List subPartitionRecList =
+            fromDeltaTable ? tablePartitionRecordsFromDelta.stream()
+                .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_SUBPARTITION)
+                .collect(Collectors.toList()) :
+                tablePartitionRecords.stream()
+                    .filter(o -> o.partLevel == TablePartitionRecord.PARTITION_LEVEL_SUBPARTITION)
+                    .collect(Collectors.toList());
+
+        TablePartRecordInfoContext confCtx = new TablePartRecordInfoContext();
+        confCtx.setLogTbRec(logTbRec);
+        confCtx.setPartitionRecList(partitionRecList);
+        confCtx.setSubPartitionRecList(subPartitionRecList);
+        tbPartConf = TablePartitionAccessor.buildPartitionConfByPartitionRecords(confCtx);
+
+        if (tbPartConf.getTableConfig().partStatus
+            != TablePartitionRecord.PARTITION_STATUS_LOGICAL_TABLE_PUBLIC && !includeNonPublic) {
+            return null;
+        }
+        Map partitionGroupRecordsMap =
+            TableGroupUtils.getPartitionGroupsMapByGroupId(tbPartConf.getTableConfig().getGroupId());
+        return PartitionInfoBuilder.buildPartitionInfoByMetaDbConfig(tbPartConf, allColumnMetas,
+            partitionGroupRecordsMap);
+    }
+
     public String getAppName() {
         return appName;
     }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoUtil.java
index f67d10f38..4e65819c3 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoUtil.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoUtil.java
@@ -27,6 +27,8 @@
 import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.common.utils.Pair;
 import com.alibaba.polardbx.common.utils.TStringUtil;
+import com.alibaba.polardbx.common.utils.logger.Logger;
+import com.alibaba.polardbx.common.utils.logger.LoggerFactory;
 import com.alibaba.polardbx.config.ConfigDataMode;
 import com.alibaba.polardbx.druid.sql.ast.SQLExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLIdentifierExpr;
@@ -48,6 +50,7 @@
 import com.alibaba.polardbx.gms.topology.DbGroupInfoManager;
 import com.alibaba.polardbx.gms.topology.DbInfoManager;
 import com.alibaba.polardbx.gms.topology.GroupDetailInfoExRecord;
+import com.alibaba.polardbx.gms.ttl.TtlPartArcState;
 import com.alibaba.polardbx.gms.util.GroupInfoUtil;
 import com.alibaba.polardbx.gms.util.PartitionNameUtil;
 import com.alibaba.polardbx.optimizer.OptimizerContext;
@@ -95,7 +98,6 @@
 import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlCreateTable;
-import org.apache.calcite.sql.SqlDialect;
 import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlLiteral;
@@ -106,19 +108,18 @@
 import org.apache.calcite.sql.SqlPartitionValueItem;
 import org.apache.calcite.sql.SqlSubPartition;
 import org.apache.calcite.sql.SqlUnresolvedFunction;
-import org.apache.calcite.sql.dialect.MysqlSqlDialect;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.fun.SqlSubstringFunction;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.sql.util.SqlShuttle;
-import org.apache.calcite.sql.util.SqlString;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.jetbrains.annotations.NotNull;
 
 import java.sql.Connection;
 import java.sql.Types;
+import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
@@ -155,6 +156,7 @@ public class PartitionInfoUtil {
     public static final int IGNORE_PARTNAME_LOCALITY = 1;
     public static final int COMPARE_NEW_PART_LOCATION = 2;
     public static final int COMPARE_EXISTS_PART_LOCATION = 4;
+    public final static Logger DDL_LOGGER = LoggerFactory.getLogger("ddl");
 
     protected static class PartitionColumnFinder extends SqlShuttle {
 
@@ -341,6 +343,7 @@ public static TablePartitionRecord prepareRecordForOnePartition(PartitionInfo pa
 
         ExtraFieldJSON partExtras = new ExtraFieldJSON();
         partExtras.setLocality(partitionSpec.getLocality() == null ? "" : partitionSpec.getLocality());
+        partExtras.setArcState(partitionSpec.getArcState());
         record.partExtras = partExtras;
 
         record.partFlags = 0L;
@@ -2185,6 +2188,10 @@ public static TableGroupConfig getTheBestTableGroupInfo(PartitionInfo partitionI
                     if ((flag & IGNORE_PARTNAME_LOCALITY) == IGNORE_PARTNAME_LOCALITY && withImplicitTableGroup) {
                         partitionInfo.setPartitionBy(originalPartitionBy.copy());
                     }
+                    DDL_LOGGER.error(MessageFormat.format("partitionInfo[{0}]:{1}",
+                        partitionInfo.getTableName(), partitionInfo.getDigest(0L)));
+                    DDL_LOGGER.error(MessageFormat.format("partitionInfo[{0}]:{1}",
+                        comparePartitionInfo.getTableName(), comparePartitionInfo.getDigest(0L)));
                     throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_INVALID_PARAMS, String.format(
                         "Failed to create partition table because the partition definition of the table mismatch the table group[%s]",
                         tableGroupName));
@@ -2554,7 +2561,7 @@ public static PartitionInfo updatePartitionInfoByOutDatePartitionRecords(Connect
                                                                              TableInfoManager tableInfoManager) {
         List outdatedPartitionRecords =
             TableGroupUtils.getOutDatePartitionGroupsByTgId(conn, tgIdInMetadb);
-        partitionInfo = partitionInfo.copy();
+        //partitionInfo = partitionInfo.copy();
         for (PartitionGroupRecord partitionGroupRecord : outdatedPartitionRecords) {
             if (partitionInfo.getPartitionBy().getSubPartitionBy() != null) {
                 boolean found = false;
@@ -2834,7 +2841,7 @@ public static boolean actualPartColsEquals(PartitionInfo tb1, PartitionInfo tb2)
     public static List fetchAllLevelMaxActualPartColsFromPartInfos(PartitionInfo partInfo1,
                                                                             PartitionInfo partInfo2) {
         List allLevelMaxActualPartCols = new ArrayList<>();
-        if (!(partInfo1.isPartitionedTableOrGsiTable() && partInfo2.isPartitionedTableOrGsiTable())) {
+        if (!(partInfo1.isPartitionedTableOrGsiCciTable() && partInfo2.isPartitionedTableOrGsiCciTable())) {
             return allLevelMaxActualPartCols;
         }
         List actualPartColInfoOfPartInfo1 = partInfo1.getAllLevelActualPartColCounts();
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionSpec.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionSpec.java
index f3d762b1a..596769d4b 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionSpec.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/PartitionSpec.java
@@ -18,9 +18,8 @@
 
 import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.common.utils.TStringUtil;
-import com.alibaba.polardbx.gms.locality.LocalityDesc;
-import com.alibaba.polardbx.gms.partition.ExtraFieldJSON;
 import com.alibaba.polardbx.gms.partition.TablePartitionRecord;
+import com.alibaba.polardbx.gms.ttl.TtlPartArcState;
 import com.alibaba.polardbx.optimizer.locality.LocalityInfoUtils;
 import com.alibaba.polardbx.optimizer.partition.boundspec.PartitionBoundSpec;
 import com.alibaba.polardbx.optimizer.partition.common.PartKeyLevel;
@@ -59,6 +58,16 @@ public PartitionSpec() {
         this.isDefaultPartition = false;
     }
 
+    public boolean isReadyForArchiving() {
+        if (this.extras.getArcState() != null) {
+            if (this.extras.getArcState() == TtlPartArcState.ARC_STATE_READY.getArcState()
+                || this.extras.getArcState() == TtlPartArcState.ARC_STATE_REREADY.getArcState()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public PartitionSpec copy() {
 
         PartitionSpec spec = new PartitionSpec();
@@ -83,6 +92,7 @@ public PartitionSpec copy() {
         spec.setSpecTemplate(this.isSpecTemplate);
         spec.setTemplateName(this.templateName);
         spec.setIntraGroupConnKey(this.intraGroupConnKey);
+        spec.setArcState(this.arcState);
 
         if (this.location != null) {
             spec.setLocation(this.location.copy());
@@ -536,7 +546,9 @@ public String getDigest() {
         sb.append(normalizePartSpec(normalSpecParams));
         sb.append(",");
         if (!isLogical) {
-            sb.append(this.getLocation().getDigest());
+            if (this.getLocation() != null) {
+                sb.append(this.getLocation().getDigest());
+            }
         }
         sb.append("]");
         return sb.toString();
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildAllPartSpecsFromAstParams.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildAllPartSpecsFromAstParams.java
index 89af5f26f..0fd64e617 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildAllPartSpecsFromAstParams.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildAllPartSpecsFromAstParams.java
@@ -50,6 +50,7 @@ public class BuildAllPartSpecsFromAstParams {
     protected boolean containNextLevelPartSpec;
     protected PartitionSpec parentPartSpec;
     protected AtomicInteger phyPartCounter;
+    protected boolean ttlTemporary = false;
 
     public BuildAllPartSpecsFromAstParams() {
     }
@@ -191,4 +192,12 @@ public AtomicInteger getPhyPartCounter() {
     public void setPhyPartCounter(AtomicInteger phyPartCounter) {
         this.phyPartCounter = phyPartCounter;
     }
+
+    public boolean isTtlTemporary() {
+        return ttlTemporary;
+    }
+
+    public void setTtlTemporary(boolean ttlTemporary) {
+        this.ttlTemporary = ttlTemporary;
+    }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildPartByDefFromAstParams.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildPartByDefFromAstParams.java
index 5f2c894f9..4041f56d3 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildPartByDefFromAstParams.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildPartByDefFromAstParams.java
@@ -51,6 +51,8 @@ public class BuildPartByDefFromAstParams {
     protected List parentPartSpecAstList;
     protected boolean containNextLevelPartSpec;
 
+    protected boolean ttlTemporary = false;
+
     public BuildPartByDefFromAstParams() {
     }
 
@@ -217,4 +219,16 @@ public boolean isContainNextLevelPartSpec() {
     public void setContainNextLevelPartSpec(boolean containNextLevelPartSpec) {
         this.containNextLevelPartSpec = containNextLevelPartSpec;
     }
+
+    public boolean isTtlTemporary() {
+        return ttlTemporary;
+    }
+
+    public void setTtlTemporary(boolean ttlTemporary) {
+        this.ttlTemporary = ttlTemporary;
+    }
+
+    public void setBuildSubpartBy(boolean buildSubpartBy) {
+        this.buildSubpartBy = buildSubpartBy;
+    }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildPartInfoFromAstParams.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildPartInfoFromAstParams.java
index 3f3e6a91c..b68e652f6 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildPartInfoFromAstParams.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/BuildPartInfoFromAstParams.java
@@ -42,6 +42,7 @@ public class BuildPartInfoFromAstParams {
     protected PartitionTableType tblType;
     protected ExecutionContext ec;
     protected LocalityDesc locality;
+    protected boolean ttlTemporary = false;
 
     public BuildPartInfoFromAstParams() {
     }
@@ -141,4 +142,12 @@ public LocalityDesc getLocality() {
     public void setLocality(LocalityDesc locality) {
         this.locality = locality;
     }
+
+    public boolean isTtlTemporary() {
+        return ttlTemporary;
+    }
+
+    public void setTtlTemporary(boolean ttlTemporary) {
+        this.ttlTemporary = ttlTemporary;
+    }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/PartKeyLevel.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/PartKeyLevel.java
index c7b6254a2..058739bc2 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/PartKeyLevel.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/PartKeyLevel.java
@@ -23,10 +23,36 @@
  * @author chenghui.lch
  */
 public enum PartKeyLevel {
+    /**
+     * No use, maybe use for single-table or bro-table
+     */
     LOGICAL_TBL_KEY(0),
+
+    /**
+     * Mean that current pruning bitset result
+     * are only for a part bitset of one 1level-part
+     * table or of a one 2-level-part table
+     */
     PARTITION_KEY(1),
+
+    /**
+     * Mean that current pruning bitset result
+     * are only for a subpart bitset of one part
+     * of a non-template subpart table
+     */
     SUBPARTITION_KEY(2),
+
+    /**
+     * Mean that current pruning bitset result
+     * has no found part_key and full scan
+     */
     NO_PARTITION_KEY(-1),
+
+    /**
+     * Only used by SubPartTable Pruning,
+     * means current pruning bitset result
+     * are including all subpart bitsets of all part
+     */
     BOTH_PART_SUBPART_KEY(-2);
 
     private int levelIntVal;
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/PartitionStrategy.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/PartitionStrategy.java
index 0409936de..564bae634 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/PartitionStrategy.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/common/PartitionStrategy.java
@@ -16,6 +16,9 @@
 
 package com.alibaba.polardbx.optimizer.partition.common;
 
+import java.util.HashSet;
+import java.util.Set;
+
 /**
  * @author chenghui.lch
  */
@@ -30,6 +33,13 @@ public enum PartitionStrategy {
     CO_HASH("CO_HASH", "CO_HASH"),
     UDF_HASH("UDF_HASH", "UDF_HASH");
 
+    private static Set partitionStrategyWithOrder = new HashSet<>();
+
+    static {
+        partitionStrategyWithOrder.add(RANGE);
+        partitionStrategyWithOrder.add(RANGE_COLUMNS);
+    }
+
     private String strategyStr;
     private String strategyExplainName;
 
@@ -96,4 +106,9 @@ public boolean isUdfHashed() {
     public boolean isCoHashed() {
         return this.equals(CO_HASH);
     }
+
+    public boolean isStrategyWithOrder() {
+        return PartitionStrategy.partitionStrategyWithOrder.contains(this);
+    }
+
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/datatype/function/Monotonicity.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/datatype/function/Monotonicity.java
index 4a87dde70..acd023fb2 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/datatype/function/Monotonicity.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/datatype/function/Monotonicity.java
@@ -16,6 +16,8 @@
 
 package com.alibaba.polardbx.optimizer.partition.datatype.function;
 
+import java.util.Set;
+
 /**
  * Represent the monotonicity info of the partition function.
  */
@@ -32,12 +34,15 @@ public enum Monotonicity {
      * But only for valid/real x and y
      */
     MONOTONIC_INCREASING_NOT_NULL,
+
     /**
      * F() is unary and (x < y) => (F(x) <  F(y))
      */
     MONOTONIC_STRICT_INCREASING,
+
     /**
      * But only for valid/real x and y
      */
-    MONOTONIC_STRICT_INCREASING_NOT_NULL
+    MONOTONIC_STRICT_INCREASING_NOT_NULL;
+
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/datatype/iterator/DecimalInIterator.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/datatype/iterator/DecimalInIterator.java
index 8599088c9..b43392691 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/datatype/iterator/DecimalInIterator.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/datatype/iterator/DecimalInIterator.java
@@ -27,9 +27,7 @@
 import com.alibaba.polardbx.optimizer.partition.datatype.PartitionField;
 import com.google.common.base.Preconditions;
 
-import javax.servlet.http.Part;
 import java.math.BigDecimal;
-import java.math.BigInteger;
 
 import static com.alibaba.polardbx.optimizer.core.field.AbstractNumericField.INT_64_MAX;
 
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartEnumRouteFunction.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartEnumRouteFunction.java
index 3f2538e0c..1d0b3b800 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartEnumRouteFunction.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartEnumRouteFunction.java
@@ -21,6 +21,7 @@
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition;
 import com.alibaba.polardbx.optimizer.partition.PartitionInfo;
 import com.alibaba.polardbx.optimizer.partition.common.PartKeyLevel;
 import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy;
@@ -52,13 +53,15 @@ public class PartEnumRouteFunction extends PartRouteFunction {
     public PartEnumRouteFunction(PartitionInfo partInfo,
                                  StepIntervalInfo rangeIntervalInfo,
                                  boolean inclMin,
-                                 boolean inclMax) {
+                                 boolean inclMax,
+                                 PartKeyLevel partKeyLevel) {
         this.partInfo = partInfo;
         this.rangeIntervalInfo = rangeIntervalInfo;
-        this.matchLevel = PartKeyLevel.PARTITION_KEY;
+        this.matchLevel = partKeyLevel;
         this.inclMin = inclMin;
         this.inclMax = inclMax;
-        this.partIntFunc = partInfo.getPartitionBy().getPartIntFunc();
+        this.partIntFunc = partKeyLevel == PartKeyLevel.SUBPARTITION_KEY ?
+            partInfo.getPartitionBy().getSubPartitionBy().getPartIntFunc() : partInfo.getPartitionBy().getPartIntFunc();
         this.containPartIntFunc = partIntFunc != null;
     }
 
@@ -66,7 +69,7 @@ public PartEnumRouteFunction(PartitionInfo partInfo,
     public PartRouteFunction copy() {
         PartEnumRouteFunction routeFunction =
             new PartEnumRouteFunction(this.partInfo, this.rangeIntervalInfo.copy(), this.inclMin,
-                this.inclMax);
+                this.inclMax, this.matchLevel);
         return routeFunction;
     }
 
@@ -83,15 +86,20 @@ public PartPrunedResult routePartitions(ExecutionContext context, PartPruneStepP
         PartitionRouter router = getRouterByPartInfo(this.matchLevel, parentPartPosi, this.partInfo);
         BitSet allPartBitSet = PartitionPrunerUtils.buildEmptyPartitionsBitSetByPartRouter(router);
         try {
-            DataType fldDataType = partInfo.getPartitionBy().getQuerySpaceComparator().getDatumDrdsDataTypes()[0];
-            int partitionCount = partInfo.getPartitionBy().getPartitions().size();
+            PartitionByDefinition partBy = partInfo.getPartitionBy();
+            if (this.matchLevel == PartKeyLevel.SUBPARTITION_KEY) {
+                partBy = partInfo.getPartitionBy().getSubPartitionBy();
+            }
+
+            DataType fldDataType = partBy.getQuerySpaceComparator().getDatumDrdsDataTypes()[0];
+            int partitionCount = partBy.getPartitions().size();
             PartitionFieldIterator iterator =
-                PartitionFieldIterators.getIterator(fldDataType, partInfo.getPartitionBy().getIntervalType(),
+                PartitionFieldIterators.getIterator(fldDataType, partBy.getIntervalType(),
                     partIntFunc);
             iterator.range(min.getSingletonValue().getValue(), max.getSingletonValue().getValue(), inclMin, inclMax);
 
-            boolean isListOrListCol = partInfo.getPartitionBy().getStrategy() == PartitionStrategy.LIST
-                || partInfo.getPartitionBy().getStrategy() == PartitionStrategy.LIST_COLUMNS;
+            boolean isListOrListCol = partBy.getStrategy() == PartitionStrategy.LIST
+                || partBy.getStrategy() == PartitionStrategy.LIST_COLUMNS;
             while (iterator.hasNext()) {
                 PartitionField partPruningFld = null;
                 Object evalObj = iterator.next();
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartPrunedResult.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartPrunedResult.java
index 65d699f8d..402961964 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartPrunedResult.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartPrunedResult.java
@@ -184,16 +184,11 @@ private List getPrunedPartInfosFromBitSet() {
         List prunedPartInfos = new ArrayList<>();
 
         PartKeyLevel phyPartKeyLevel = partInfo.getPartitionBy().getPhysicalPartLevel();
-        List partitions = partInfo.getPartitionBy().getPhysicalPartitions();
-
-        int partCnt = partitions.size();
-
-//        boolean hasSubPart = partInfo.containSubPartitions();
-//        if (hasSubPart) {
-//            throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_MANAGEMENT,
-//                "Not supported partitioning with subpartitions");
-//        }
+        List phyPartitions = partInfo.getPartitionBy().getPhysicalPartitions();
+        List firstLevelParts = partInfo.getPartitionBy().getPartitions();
+        boolean useSubPartBy = phyPartKeyLevel == PartKeyLevel.SUBPARTITION_KEY;
 
+        int partCnt = phyPartitions.size();
         BitSet phyPartBitSet = getPhysicalPartBitSet();
         for (int i = phyPartBitSet.nextSetBit(0); i >= 0; i = phyPartBitSet.nextSetBit(i + 1)) {
             if (i >= partCnt) {
@@ -201,36 +196,32 @@ private List getPrunedPartInfosFromBitSet() {
                     "Find pruned partition error");
             }
             // operate on index i here
-            PartitionSpec ps = partitions.get(i);
+            PartitionSpec ps = phyPartitions.get(i);
+            PartitionSpec parentPs = null;
+            String parentPartName = null;
+            if (useSubPartBy) {
+                Integer parentPartPosi = ps.getParentPartPosi().intValue() - 1;
+                parentPs = firstLevelParts.get(parentPartPosi);
+                parentPartName = parentPs.getName();
+            }
             PhysicalPartitionInfo prunedPartInfo = new PhysicalPartitionInfo();
             prunedPartInfo.setPartLevel(phyPartKeyLevel);
             prunedPartInfo.setPartName(ps.getName());
+            if (phyPartKeyLevel == PartKeyLevel.SUBPARTITION_KEY) {
+                Long parentPartPosi = ps.getParentPartPosi();
+                PartitionSpec parentPartSpec = partInfo.getPartitionBy().getNthPartition(parentPartPosi.intValue());
+                prunedPartInfo.setParentPartName(parentPartSpec.getName());
+            } else {
+                prunedPartInfo.setParentPartName(null);
+            }
             prunedPartInfo.setPartId(ps.getId());
             prunedPartInfo.setPartBitSetIdx(i);
             prunedPartInfo.setGroupKey(ps.getLocation().getGroupKey());
             prunedPartInfo.setPhyTable(ps.getLocation().getPhyTableName());
+            prunedPartInfo.setParentPartName(parentPartName);
             prunedPartInfos.add(prunedPartInfo);
         }
 
-//        if (!hasSubPart) {
-//            for (int i = 0; i < partCnt; i++) {
-//                PartitionSpec ps = partitions.get(i);
-//                if (partBitSet.get(i)) {
-//                    PhysicalPartitionInfo prunedPartInfo = new PhysicalPartitionInfo();
-//                    prunedPartInfo.setPartLevel(PartKeyLevel.PARTITION_KEY);
-//                    prunedPartInfo.setPartName(ps.getName());
-//                    prunedPartInfo.setPartId(ps.getId());
-//                    prunedPartInfo.setPartBitSetIdx(i);
-//                    prunedPartInfo.setGroupKey(ps.getLocation().getGroupKey());
-//                    prunedPartInfo.setPhyTable(ps.getLocation().getPhyTableName());
-//                    prunedPartInfos.add(prunedPartInfo);
-//                }
-//            }
-//
-//        } else {
-//            throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_MANAGEMENT,
-//                "Not supported partitioning with subpartitions");
-//        }
         return prunedPartInfos;
     }
 
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartRouteFunction.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartRouteFunction.java
index def638849..32fa0fe2d 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartRouteFunction.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartRouteFunction.java
@@ -21,7 +21,6 @@
 import com.alibaba.polardbx.optimizer.partition.common.PartKeyLevel;
 import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy;
 
-import java.util.BitSet;
 import java.util.List;
 
 /**
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPruneStepBuilder.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPruneStepBuilder.java
index e3da16026..98a3f48d9 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPruneStepBuilder.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPruneStepBuilder.java
@@ -23,8 +23,6 @@
 import com.alibaba.polardbx.common.utils.logger.Logger;
 import com.alibaba.polardbx.common.utils.logger.LoggerFactory;
 import com.alibaba.polardbx.common.utils.time.calculator.MySQLIntervalType;
-import com.alibaba.polardbx.gms.topology.DbInfoManager;
-import com.alibaba.polardbx.optimizer.OptimizerContext;
 import com.alibaba.polardbx.optimizer.config.table.ColumnMeta;
 import com.alibaba.polardbx.optimizer.config.table.TableMeta;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
@@ -35,7 +33,6 @@
 import com.alibaba.polardbx.optimizer.core.field.TypeConversionStatus;
 import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition;
 import com.alibaba.polardbx.optimizer.partition.PartitionInfo;
-import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager;
 import com.alibaba.polardbx.optimizer.partition.common.PartKeyLevel;
 import com.alibaba.polardbx.optimizer.partition.common.PartitionTableType;
 import com.alibaba.polardbx.optimizer.partition.datatype.PartitionField;
@@ -62,15 +59,15 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
-import static com.alibaba.polardbx.common.utils.time.calculator.MySQLIntervalType.*;
+import static com.alibaba.polardbx.common.utils.time.calculator.MySQLIntervalType.INTERVAL_DAY;
+import static com.alibaba.polardbx.common.utils.time.calculator.MySQLIntervalType.INTERVAL_MONTH;
+import static com.alibaba.polardbx.common.utils.time.calculator.MySQLIntervalType.INTERVAL_WEEK;
+import static com.alibaba.polardbx.common.utils.time.calculator.MySQLIntervalType.INTERVAL_YEAR;
 
 /**
  * @author chenghui.lch
  */
 public class PartitionPruneStepBuilder {
-
-    private static final Logger log = LoggerFactory.getLogger(PartitionPruneStepBuilder.class);
-
     protected static final long DEFAULT_MAX_ENUMERABLE_INTERVAL_LENGTH = 32;
     protected static final long DEFAULT_MAX_IN_SUBQUERY_PRUNING_SIZE = 8192L;
 
@@ -80,13 +77,9 @@ public class PartitionPruneStepBuilder {
     public static PartitionPruneStep genFullScanAllPhyPartsStepInfoByDbNameAndTbName(String dbName,
                                                                                      String logTbName,
                                                                                      ExecutionContext executionContext) {
-        PartitionInfoManager partitionInfoManager =
-            executionContext.getSchemaManager(dbName).getTddlRuleManager().getPartitionInfoManager();
-        PartitionInfo partInfo = partitionInfoManager.getPartitionInfo(logTbName);
-        if (partInfo == null) {
-            log.warn(String.format("db-%s logTbName %s %s", dbName, logTbName,
-                partitionInfoManager.getPartInfoCtxCache().size()));
-        }
+        TableMeta tableMeta = executionContext.getSchemaManager(dbName).getTable(logTbName);
+        PartitionInfo partInfo = tableMeta.getPartitionInfo();
+
         return genFullScanPruneStepInfoInner(partInfo, partInfo.getPartitionBy().getPhysicalPartLevel(), true);
     }
 
@@ -100,9 +93,9 @@ public static PartitionPruneStep genFullScanAllPhyPartsStepInfoByDbNameAndTbName
      * fullScanSubPartsCrossAllParts=false:  scan subpartitions of just one partition
      * fullScanSubPartsCrossAllParts=true:  scan subpartitions of just all partitions
      */
-    protected static PartitionPruneStep genFullScanPruneStepInfoInner(PartitionInfo partInfo,
-                                                                      PartKeyLevel partLevel,
-                                                                      boolean fullScanSubPartsCrossAllParts) {
+    public static PartitionPruneStep genFullScanPruneStepInfoInner(PartitionInfo partInfo,
+                                                                   PartKeyLevel partLevel,
+                                                                   boolean fullScanSubPartsCrossAllParts) {
         BuildStepOpParams buildParams = new BuildStepOpParams();
         buildParams.setCurrFullContext(null);
         buildParams.setPartInfo(partInfo);
@@ -166,22 +159,38 @@ protected static PartitionPruneStep genFirstPartScanOnlyPruneStepInfoInner(Parti
         return finalStep;
     }
 
-    public static PartitionPruneStep generatePointSelectPruneStepInfo(List pointValue,
-                                                                      List pointValueOpTypes,
-                                                                      ExecutionContext ec,
-                                                                      ExecutionContext[] newEcOutput,
-                                                                      PartitionInfo partInfo,
-                                                                      RelDataType tbRelRowType) {
+    /**
+     *
+     */
+    public static PartitionPruneStep genPointSelectPruneStepInfoForTtlRouting(List pointValue,
+                                                                              List pointValueOpTypes,
+                                                                              ExecutionContext ec,
+                                                                              ExecutionContext[] newEcOutput,
+                                                                              PartitionInfo partInfo,
+                                                                              RelDataType tbRelRowType) {
         RexBuilder rexBuilder = PartitionPrunerUtils.getRexBuilder();
 
         List partColFldList = partInfo.getPartitionBy().getPartitionFieldList();
-        List partColRexInputList = new ArrayList<>();
+
+        /**
+         * map.key: colName
+         * map.val: the col index of table column definition order
+         */
         final Map indexColRefMap = tbRelRowType.getFieldList()
             .stream()
-            .collect(Collectors.toMap(RelDataTypeField::getName,
-                RelDataTypeField::getIndex,
-                (x, y) -> y,
-                TreeMaps::caseInsensitiveMap));
+            .collect(
+                Collectors.toMap(
+                    RelDataTypeField::getName,
+                    RelDataTypeField::getIndex,
+                    (x, y) -> y,
+                    TreeMaps::caseInsensitiveMap
+                )
+            );
+
+        /**
+         * Gen all the InputRef of tbRelRowType for part Cols by using the mapping of indexColRefMap
+         */
+        List partColRexInputList = new ArrayList<>();
         partColFldList.stream().forEach(
             fld -> {
                 if (indexColRefMap.containsKey(fld.getName())) {
@@ -1130,9 +1139,9 @@ private static PartitionPruneStep buildPartPruneStepByStepRangeIntervalInfo(Part
 
             Boolean isBoundInclude[] = new Boolean[2];
             if (checkCanEnumRange(partInfo, pruningCtx, rangeInfo, isBoundInclude)) {
-                PartKeyLevel keyLevel = PartKeyLevel.PARTITION_KEY;
+                PartKeyLevel keyLevel = rangeInfo.getPartLevel();
                 PartEnumRouteFunction routeFunc =
-                    new PartEnumRouteFunction(partInfo, rangeInfo, isBoundInclude[0], isBoundInclude[1]);
+                    new PartEnumRouteFunction(partInfo, rangeInfo, isBoundInclude[0], isBoundInclude[1], keyLevel);
 
                 BuildStepOpParams buildParams = new BuildStepOpParams();
                 buildParams.setCurrFullContext(null);
@@ -1247,7 +1256,7 @@ protected static boolean checkCanEnumRange(PartitionInfo partInfo,
             /**
              * All the part int func is time func
              */
-            MySQLIntervalType intervalType = partInfo.getPartitionBy().getIntervalType();
+            MySQLIntervalType intervalType = partBy.getIntervalType();
             if (intervalType != null) {
                 if (!inclMin && (intervalType == INTERVAL_YEAR || intervalType == INTERVAL_MONTH
                     || intervalType == INTERVAL_WEEK || intervalType == INTERVAL_DAY)) {
@@ -1269,8 +1278,8 @@ protected static boolean checkCanEnumRange(PartitionInfo partInfo,
 
         PartitionFieldIterator iterator = PartitionFieldIterators
             .getIterator(minPartitionField.dataType(),
-                partInfo.getPartitionBy().getIntervalType(),
-                partInfo.getPartitionBy().getPartIntFunc()
+                partBy.getIntervalType(),
+                partBy.getPartIntFunc()
             );
 
         boolean isValidRange = iterator.range(minPartitionField, maxPartitionField, inclMin, inclMax);
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPruner.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPruner.java
index 7466d914a..418e34879 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPruner.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPruner.java
@@ -17,13 +17,18 @@
 package com.alibaba.polardbx.optimizer.partition.pruning;
 
 import com.alibaba.polardbx.common.exception.NotSupportException;
+import com.alibaba.polardbx.common.exception.TddlRuntimeException;
+import com.alibaba.polardbx.common.exception.code.ErrorCode;
 import com.alibaba.polardbx.common.properties.ConnectionParams;
 import com.alibaba.polardbx.common.utils.GeneralUtil;
+import com.alibaba.polardbx.gms.partition.TablePartitionRecord;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.rel.LogicalInsert;
 import com.alibaba.polardbx.optimizer.core.rel.LogicalView;
+import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan;
 import com.alibaba.polardbx.optimizer.partition.PartitionInfo;
 import com.alibaba.polardbx.optimizer.partition.PartitionInfoManager;
+import com.alibaba.polardbx.optimizer.partition.PartitionSpec;
 import com.alibaba.polardbx.optimizer.sharding.result.RelShardInfo;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.type.RelDataType;
@@ -32,6 +37,7 @@
 
 import java.util.ArrayList;
 import java.util.BitSet;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -72,16 +78,6 @@ public static PartitionTupleRouteInfo generatePartitionTupleRoutingInfo(String s
                                                                             RelDataType tupleValRowType,
                                                                             List> tupleValAst,
                                                                             ExecutionContext ec) {
-
-//        GenPartTupleRouteInfoParams genParams = new GenPartTupleRouteInfoParams();
-//        genParams.setSchemaName(schemaName);
-//        genParams.setLogTbName(logTbName);
-//        genParams.setSpecificPartInfo(specificPartInfo);
-//        genParams.setValueRowType(valueRowType);
-//        genParams.setAstValues(astValues);
-//        genParams.setEc(ec);
-//        return PartitionTupleRouteInfoBuilder.genParTupleRoutingInfo(genParams);
-
         return PartitionTupleRouteInfoBuilder
             .genPartTupleRoutingInfo(schemaName, logTbName, specificPartInfo, tupleValRowType, tupleValAst, ec);
     }
@@ -100,17 +96,36 @@ public static PartPrunedResult doPruningByStepInfo(PartitionPruneStep stepInfo,
                 PartitionPruneStepBuilder.genFullScanPruneStepInfoInner(partInfo,
                     partInfo.getPartitionBy().getPhysicalPartLevel(), true);
             pruningCtx.setRootStep(fullScanStep);
-
             PartPrunedResult prunedResult = fullScanStep.prunePartitions(context, pruningCtx, null);
             PartitionPrunerUtils.logStepExplainInfo(context, prunedResult.getPartInfo(), pruningCtx);
             return prunedResult;
         }
         pruningCtx.setRootStep(stepInfo);
         PartPrunedResult prunedResult = stepInfo.prunePartitions(context, pruningCtx, null);
+        invalidParitionFilter(stepInfo.getPartitionInfo(), prunedResult);
         PartitionPrunerUtils.logStepExplainInfo(context, prunedResult.getPartInfo(), pruningCtx);
         return prunedResult;
     }
 
+    public static void invalidParitionFilter(PartitionInfo partitionInfo, PartPrunedResult prunedResult) {
+        if (!prunedResult.getPartBitSet().isEmpty()) {
+            List phyPartSpecs = partitionInfo.getPartitionBy().getPhysicalPartitions();
+            int partCnt = phyPartSpecs.size();
+            for (int i = prunedResult.getPartBitSet().nextSetBit(0); i >= 0;
+                 i = prunedResult.getPartBitSet().nextSetBit(i + 1)) {
+                if (i >= partCnt) {
+                    throw new TddlRuntimeException(ErrorCode.ERR_PARTITION_MANAGEMENT,
+                        "Find pruned partition error");
+                }
+                PartitionSpec phySpec = phyPartSpecs.get(i);
+                if (phySpec.getStatus() != null
+                    && phySpec.getStatus() == TablePartitionRecord.PARTITION_STATUS_PARTITION_OFFLINE) {
+                    prunedResult.getPartBitSet().clear(i);
+                }
+            }
+        }
+    }
+
     /**
      * Methods for pruning by tupleRouteInfo ( for insert / replace )
      */
@@ -124,6 +139,7 @@ public static PartPrunedResult doPruningByTupleRouteInfo(PartitionTupleRouteInfo
         pruningCtx.setEnableConstExprEvalCache(false);
         PartPrunedResult rs = tupleRouteInfo.routeTuple(tupleIndex, context, pruningCtx);
         pruningCtx.setRootTuple(tupleRouteInfo);
+        invalidParitionFilter(tupleRouteInfo.getPartInfo(), rs);
         PartitionPrunerUtils.logStepExplainInfo(context, rs.getPartInfo(), pruningCtx);
         return rs;
     }
@@ -246,4 +262,23 @@ public static List prunePartitions(RelNode relPlan, ExecutionC
             throw GeneralUtil.nestedException(new NotSupportException("Not support to non logical view"));
         }
     }
+
+    public static List pruneCciPartitions(RelNode relPlan, ExecutionContext context,
+                                                            PartitionInfo cciPartInfo) {
+        if (!(relPlan instanceof OSSTableScan)) {
+            throw GeneralUtil.nestedException(new NotSupportException("Not support to non OSS table scan"));
+        }
+        OSSTableScan ossTableScan = (OSSTableScan) relPlan;
+        boolean useSelectPartitions = ossTableScan.useSelectPartitions();
+        PartPrunedResult tbPrunedResult;
+        if (!useSelectPartitions) {
+            RelShardInfo relShardInfo = ossTableScan.getCciRelShardInfo(context, cciPartInfo);
+            tbPrunedResult = PartitionPruner.doPruningByStepInfo(relShardInfo.getPartPruneStepInfo(), context);
+        } else {
+            PartitionPruneStep fullScanStep = PartitionPruneStepBuilder.genFullScanPruneStepInfoInner(cciPartInfo,
+                cciPartInfo.getPartitionBy().getPartLevel(), true);
+            tbPrunedResult = PartitionPruner.doPruningByStepInfo(fullScanStep, context);
+        }
+        return Collections.singletonList(tbPrunedResult);
+    }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPrunerUtils.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPrunerUtils.java
index 6daae3469..be5e26e9d 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPrunerUtils.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionPrunerUtils.java
@@ -20,6 +20,7 @@
 import com.alibaba.polardbx.common.exception.code.ErrorCode;
 import com.alibaba.polardbx.common.jdbc.ParameterContext;
 import com.alibaba.polardbx.common.jdbc.RawString;
+import com.alibaba.polardbx.common.utils.CaseInsensitive;
 import com.alibaba.polardbx.common.utils.logger.Logger;
 import com.alibaba.polardbx.common.utils.logger.LoggerFactory;
 import com.alibaba.polardbx.druid.util.StringUtils;
@@ -36,15 +37,19 @@
 import com.alibaba.polardbx.optimizer.core.field.FieldCheckLevel;
 import com.alibaba.polardbx.optimizer.core.field.SessionProperties;
 import com.alibaba.polardbx.optimizer.core.field.TypeConversionStatus;
+import com.alibaba.polardbx.optimizer.core.rel.util.TargetTableInfo;
+import com.alibaba.polardbx.optimizer.core.rel.util.TargetTableInfoOneTable;
+import com.alibaba.polardbx.optimizer.partition.PartitionByDefinition;
+import com.alibaba.polardbx.optimizer.partition.PartitionInfo;
+import com.alibaba.polardbx.optimizer.partition.PartitionSpec;
 import com.alibaba.polardbx.optimizer.partition.boundspec.PartitionBoundSpec;
 import com.alibaba.polardbx.optimizer.partition.boundspec.PartitionBoundVal;
 import com.alibaba.polardbx.optimizer.partition.boundspec.PartitionBoundValueKind;
-import com.alibaba.polardbx.optimizer.partition.PartitionInfo;
-import com.alibaba.polardbx.optimizer.partition.PartitionSpec;
 import com.alibaba.polardbx.optimizer.partition.common.PartKeyLevel;
 import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy;
 import com.alibaba.polardbx.optimizer.partition.datatype.PartitionField;
 import com.alibaba.polardbx.optimizer.partition.datatype.PartitionFieldBuilder;
+import com.alibaba.polardbx.optimizer.partition.datatype.function.Monotonicity;
 import com.alibaba.polardbx.optimizer.partition.datatype.function.PartitionFunctionBuilder;
 import com.alibaba.polardbx.optimizer.partition.datatype.function.PartitionIntFunction;
 import com.alibaba.polardbx.optimizer.partition.exception.InvalidTypeConversionException;
@@ -65,6 +70,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
 
 /**
  * @author chenghui.lch
@@ -216,6 +223,237 @@ public static Map>> buildTargetTablesByPartPrunedResul
         return phyGrpInfoMap;
     }
 
+    /**
+     * Convert the list of PartPrunedResult to TargetDB
+     */
+    public static TargetTableInfo buildTargetTableInfoByPartPrunedResults(List results) {
+
+        TargetTableInfo targetTableInfo = new TargetTableInfo();
+
+        /**
+         * key: grpKey
+         * val:
+         *      List of phyTblList to be join that has different partition idx
+         *          List of phyTbl of the same partition idx of each logTbl
+         */
+        Map>> phyGrpInfoMap = new HashMap<>();
+        List targetTableInfoOneTableList = new ArrayList<>();
+        targetTableInfo.setTargetTables(phyGrpInfoMap);
+        targetTableInfo.setTargetTableInfoList(targetTableInfoOneTableList);
+
+        /**
+         * key: grpKey
+         * val:
+         *     partIdxPhyTbListMap:
+         *          key: partIdx
+         *          val: phyTbList that has same phy idx
+         */
+        Map>> allPhyInfos = new HashMap<>();
+
+        List>> broadcastTopologyList = new ArrayList<>();
+
+        /**
+         * key: partName
+         * Val: List of subPartNames
+         */
+        Map> part2SubPartListMapping = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER);
+
+        for (int i = 0; i < results.size(); i++) {
+            PartPrunedResult result = results.get(i);
+            PartitionInfo partInfo = result.getPartInfo();
+            if (result.getPrunedParttions().isEmpty()) {
+                TargetTableInfoOneTable targetTableInfoOneTable = new TargetTableInfoOneTable();
+                targetTableInfoOneTable.setPartInfo(partInfo);
+                targetTableInfoOneTableList.add(targetTableInfoOneTable);
+                targetTableInfoOneTable.setUseSubPart(partInfo.getPartitionBy().getSubPartitionBy() != null);
+                targetTableInfoOneTable.setAllPartSorted(false);
+                targetTableInfoOneTable.setAllSubPartSorted(false);
+                targetTableInfoOneTable.setAllPrunedPartContainOnlyOneSubPart(false);
+                return targetTableInfo;
+            }
+        }
+
+        for (int i = 0; i < results.size(); i++) {
+            PartPrunedResult result = results.get(i);
+            PartitionInfo partInfo = result.getPartInfo();
+
+            Set parentPartNameSet = new TreeSet<>(CaseInsensitive.CASE_INSENSITIVE_ORDER);
+            TargetTableInfoOneTable targetTableInfoOneTable = new TargetTableInfoOneTable();
+            targetTableInfoOneTable.setPartInfo(partInfo);
+            targetTableInfoOneTableList.add(targetTableInfoOneTable);
+
+            if (partInfo.isBroadcastTable()) {
+                broadcastTopologyList.add(result.getPartInfo().getTopology());
+                continue;
+            }
+            List prunedParts = result.getPrunedParttions();
+            PartKeyLevel phyPartLevel = null;
+            for (int j = 0; j < prunedParts.size(); j++) {
+                PhysicalPartitionInfo prunedPart = prunedParts.get(j);
+                String partName = prunedPart.getPartName();
+                if (phyPartLevel == null) {
+                    phyPartLevel = prunedPart.getPartLevel();
+                }
+
+                String grpKey = prunedPart.getGroupKey();
+                String phyTb = prunedPart.getPhyTable();
+                int partBitSetIdx = prunedPart.getPartBitSetIdx();
+
+                String parentPartName = prunedPart.getParentPartName();
+                if (!StringUtils.isEmpty(parentPartName)) {
+                    /**
+                     * When parentPartName is NOT empty, the prunedPart must be a subpart
+                     */
+                    if (!parentPartNameSet.contains(parentPartName)) {
+                        parentPartNameSet.add(parentPartName);
+                    }
+
+                    List subPartNames = part2SubPartListMapping.get(parentPartName);
+                    if (subPartNames == null) {
+                        subPartNames = new ArrayList<>();
+                        part2SubPartListMapping.put(parentPartName, subPartNames);
+                    }
+                    subPartNames.add(partName);
+                }
+
+                // Get phyInfos of one Group
+                Map> phyInfosOfOneGrp = allPhyInfos.get(grpKey);
+                if (phyInfosOfOneGrp == null) {
+                    phyInfosOfOneGrp = new HashMap<>();
+                    allPhyInfos.put(grpKey, phyInfosOfOneGrp);
+                }
+
+                // Get phyInfos that is the same partIdx
+                List phyTbListHasSameIdx = phyInfosOfOneGrp.get(partBitSetIdx);
+                if (phyTbListHasSameIdx == null) {
+                    phyTbListHasSameIdx = new ArrayList<>();
+                    phyInfosOfOneGrp.put(partBitSetIdx, phyTbListHasSameIdx);
+                }
+                for (int k = 0; k < broadcastTopologyList.size(); k++) {
+                    String phyTable = broadcastTopologyList.get(k).get(grpKey).iterator().next();
+                    phyTbListHasSameIdx.add(phyTable);
+                }
+                phyTbListHasSameIdx.add(phyTb);
+            }
+            broadcastTopologyList = new ArrayList<>();
+
+            targetTableInfoOneTable.setPrunedFirstLevelPartCount(parentPartNameSet.size());
+            if (phyPartLevel == PartKeyLevel.SUBPARTITION_KEY) {
+                targetTableInfoOneTable.setUseSubPart(true);
+                if (targetTableInfoOneTable.getPrunedFirstLevelPartCount() == 1) {
+                    if (checkPartitionsSortedByPartitionColumns(partInfo, PartKeyLevel.SUBPARTITION_KEY, null)) {
+                        targetTableInfoOneTable.setAllPartSorted(false);
+                        targetTableInfoOneTable.setPartColList(new ArrayList<>());
+                        targetTableInfoOneTable.setAllSubPartSorted(true);
+                        targetTableInfoOneTable.setSubpartColList(
+                            partInfo.getPartitionBy().getSubPartitionBy().getPartitionColumnNameList());
+                    }
+                } else if (targetTableInfoOneTable.getPrunedFirstLevelPartCount() > 1) {
+                    if (checkPartitionsSortedByPartitionColumns(partInfo, PartKeyLevel.PARTITION_KEY, null)) {
+                        targetTableInfoOneTable.setAllPartSorted(true);
+                        targetTableInfoOneTable.setPartColList(partInfo.getPartitionBy().getPartitionColumnNameList());
+                        targetTableInfoOneTable.setAllSubPartSorted(false);
+                        targetTableInfoOneTable.setSubpartColList(new ArrayList<>());
+
+                        if (partInfo.getPartitionBy().getSubPartitionBy() != null) {
+                            // use subpart
+                            boolean allPartContainOnlyOneSubPart = true;
+                            for (Map.Entry> part2SubPartListItem : part2SubPartListMapping.entrySet()) {
+                                List subPartNames = part2SubPartListItem.getValue();
+                                if (subPartNames != null && subPartNames.size() > 1) {
+                                    allPartContainOnlyOneSubPart = false;
+                                    break;
+                                }
+                            }
+                            targetTableInfoOneTable.setAllPrunedPartContainOnlyOneSubPart(allPartContainOnlyOneSubPart);
+                        } else {
+                            // no use subpart
+                            targetTableInfoOneTable.setAllPrunedPartContainOnlyOneSubPart(false);
+                        }
+                    }
+                }
+            } else if (phyPartLevel == PartKeyLevel.PARTITION_KEY) {
+                if (checkPartitionsSortedByPartitionColumns(partInfo, PartKeyLevel.PARTITION_KEY, null)) {
+                    targetTableInfoOneTable.setAllPartSorted(true);
+                    targetTableInfoOneTable.setPartColList(partInfo.getPartitionBy().getPartitionColumnNameList());
+                }
+                targetTableInfoOneTable.setAllSubPartSorted(false);
+                targetTableInfoOneTable.setSubpartColList(new ArrayList<>());
+            }
+        }
+
+        if (!broadcastTopologyList.isEmpty()) {
+            if (allPhyInfos.isEmpty()) {
+                // only broadcast
+                List phyInfosOfSameIdx = new ArrayList<>();
+                List> phyInfosOfOneGrp = new ArrayList<>();
+                phyInfosOfOneGrp.add(phyInfosOfSameIdx);
+                // TODO: broadcast table random access each group
+                String groupKey = broadcastTopologyList.get(0).keySet().stream().findFirst().get();
+                for (int i = 0; i < broadcastTopologyList.size(); i++) {
+                    String phyTable = broadcastTopologyList.get(i).get(groupKey).iterator().next();
+                    phyInfosOfSameIdx.add(phyTable);
+                }
+                phyGrpInfoMap.put(groupKey, phyInfosOfOneGrp);
+                return targetTableInfo;
+            }
+        }
+        // not only broadcast
+        for (Map.Entry>> phyInfosOfOneGrpItem : allPhyInfos.entrySet()) {
+            String grpKey = phyInfosOfOneGrpItem.getKey();
+            Map> phyInfosOfOneGrpMap = phyInfosOfOneGrpItem.getValue();
+            List> phyInfosOfOneGrp = new ArrayList<>();
+            for (Map.Entry> phyInfosOfSameIdxItem : phyInfosOfOneGrpMap.entrySet()) {
+                List phyInfosOfSameIdx = phyInfosOfSameIdxItem.getValue();
+                for (int i = 0; i < broadcastTopologyList.size(); i++) {
+                    String phyTable = broadcastTopologyList.get(i).get(grpKey).iterator().next();
+                    phyInfosOfSameIdx.add(phyTable);
+                }
+                phyInfosOfOneGrp.add(phyInfosOfSameIdx);
+            }
+            phyGrpInfoMap.put(grpKey, phyInfosOfOneGrp);
+        }
+
+        return targetTableInfo;
+    }
+
+    /**
+     * Check if a partitions of partLevel are sorted on partCols
+     * Notice:
+     * if partKeyLevel == PartKeyLevel.SUBPARTITION_KEY,
+     * return true means the subpartitions are sorted within only one partition
+     */
+    public static boolean checkPartitionsSortedByPartitionColumns(PartitionInfo partInfo,
+                                                                  PartKeyLevel partKeyLevel,
+                                                                  List partColsOutput) {
+        PartitionByDefinition partBy = partInfo.getPartitionBy();
+        if (partKeyLevel == PartKeyLevel.SUBPARTITION_KEY) {
+            if (partBy.getSubPartitionBy() == null) {
+                return false;
+            }
+            partBy = partInfo.getPartitionBy().getSubPartitionBy();
+        }
+        PartitionStrategy strategy = partBy.getStrategy();
+        if (!strategy.isStrategyWithOrder()) {
+            return false;
+        }
+
+        if (strategy == PartitionStrategy.RANGE) {
+            PartitionIntFunction partFn = partBy.getPartIntFunc();
+            if (partFn != null) {
+                DataType partColDataType = partBy.getPartitionColumnTypeList().get(0);
+                if (partFn.getMonotonicity(partColDataType) == Monotonicity.NON_MONOTONIC) {
+                    return false;
+                }
+            }
+        }
+        if (partColsOutput != null) {
+            partColsOutput.addAll(partBy.getPartitionColumnNameList());
+        }
+        return true;
+
+    }
+
 //    /*======= Methods for get PartitionIntFunction ========*/
 //    public static PartitionIntFunction getPartitionIntFunction(SqlOperator sqlOperator,
 //                                                               PartKeyLevel partLevel,
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionTupleRoutingContext.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionTupleRoutingContext.java
index 4a5df7d8e..853b1c025 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionTupleRoutingContext.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/pruning/PartitionTupleRoutingContext.java
@@ -85,10 +85,11 @@ protected static class FullPartColMetaInfo {
          * Each entry of list is :
          * key : 0: partition columns,  1: subpartitions columns
          * val : the index of col in (sub)partition columns list of original partition definition
-         *
+         * Notice: if a subpart col already exists in partBy, its index mapping item of the pair of
+         * fullColMetaToPartColMetaMapping will be ignore.
          * 
          *      e.g
-         *          the full part cols: A,C,D,E
+         *          the full part cols: A,C,D,E  (all part cols including both partBy and subpartBy)
          *          the part cols:      A,C,D
          *          the subPartCols:    D,E,C
          *          the mapping:   {0, 0}, {0,1}, {0,2}, {1,1}
@@ -203,6 +204,23 @@ public Parameters createPartColValueParameters(List targetRowValues,
         return allParams;
     }
 
+    /**
+     * Compute the col index mapping
+     * from
+     * partCol meta definition order
+     * to
+     * the col meta definition order of insert values,
+     * and output the result into outputPartColIdxList and outputPartColRelRowTypeList
+     *
+     * 
+     *  outputPartColIdxList: the index mapping of a col on the col meta definition order of insert values
+     *  e.g.
+     *      insert values col order: insert into t1 (b, c, a) ....
+     *      insert values col index:                 0  1  2
+     *      part col definition order : a,  b
+     *      the outputPartColIdxList:   2,  0
+     * 
+ */ protected void computePartColIndexMappings(List fullPartColMetas, List targetTupleRowColMetas, List outputPartColIdxList, @@ -250,6 +268,9 @@ protected FullPartColMetaInfo buildFullPartColMetaInfo(PartitionByDefinition par fullPartColMetaInfo.setFullPartColRelRowType(partColRelRowType); fullPartColMetaInfo.setFullPartColIndexMappings(outputFullPartColIdxList); + /** + * Construct the partColName to partCol definition index for both partBy and subpartBy + */ Map partColIdxMap = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); Map subPartColIdxMap = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); List partCols = partBy.getPartitionColumnNameList(); @@ -262,6 +283,10 @@ protected FullPartColMetaInfo buildFullPartColMetaInfo(PartitionByDefinition par subPartColIdxMap.put(subPartCols.get(i), i); } } + + /** + * C + */ List> fullColIndexMapping = new ArrayList<>(); for (int i = 0; i < fullPartColMetas.size(); i++) { ColumnMeta cm = fullPartColMetas.get(i); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/util/PartTupleRouter.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/util/PartTupleRouter.java index cc7dfb2d7..8131a62cd 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/util/PartTupleRouter.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/partition/util/PartTupleRouter.java @@ -36,6 +36,21 @@ import java.util.List; /** + * A Full Tuple Partition Router + * for the internal usage of routing, + * such as Split hot value. + * + *
+ *     Notice:
+ *          PartTupleRouter is non-thread-safe,
+ *          so route tuple one by one.
+ *     e.g:
+ *     PartTupleRouter router = new PartTupleRouter(...);
+ *      for each tuple of tupleList
+ *            part = router.routeTuple(tuple)
+ *
+ * 
+ * * @author chenghui.lch */ public class PartTupleRouter extends AbstractLifecycle { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/BaselineInfo.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/BaselineInfo.java index a66859b42..1a5541905 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/BaselineInfo.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/BaselineInfo.java @@ -22,13 +22,13 @@ import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.metadb.table.BaselineInfoRecord; -import com.alibaba.polardbx.gms.util.InstIdUtil; import com.alibaba.polardbx.optimizer.planmanager.parametric.Point; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.apache.calcite.rel.RelNode; import org.apache.calcite.util.JsonBuilder; +import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.Collection; @@ -46,7 +46,6 @@ import static com.alibaba.polardbx.common.properties.ConnectionParams.SPM_MAX_ACCEPTED_PLAN_SIZE_PER_BASELINE; import static com.alibaba.polardbx.common.properties.ConnectionParams.SPM_OLD_PLAN_CHOOSE_COUNT_LEVEL; -import static com.alibaba.polardbx.common.utils.GeneralUtil.printlnToStringBuilder; import static com.alibaba.polardbx.common.utils.GeneralUtil.unixTimeStamp; import static com.alibaba.polardbx.optimizer.planmanager.PlanInfo.INVAILD_HASH_CODE; @@ -55,6 +54,7 @@ public class BaselineInfo { public static final String EXTEND_HINT = "HINT"; public static final String EXTEND_USE_POST_PLANNER = "USE_POST_PLANNER"; public static final String EXTEND_REBUILD_AT_LOAD = "REBUILD_AT_LOAD"; + public static final String EXTEND_HOT_EVOLVED = "HOT_EVOLVED"; private int id; private String parameterSql; // unique key @@ -75,6 +75,9 @@ public class BaselineInfo { private boolean dirty = false; + // whether the baseline used to evolve hot gsi + private volatile boolean hotEvolution = false; + private String extend; // --- params from extend --- @@ -108,9 +111,9 @@ public Set> getTableSet() { return tableSet; } - public void addAcceptedPlan(PlanInfo planInfo) { + public PlanInfo addAcceptedPlan(PlanInfo planInfo) { planInfo.setAccepted(true); - acceptedPlans.put(planInfo.getId(), planInfo); + return acceptedPlans.put(planInfo.getId(), planInfo); } public void addUnacceptedPlan(PlanInfo planInfo) { @@ -146,6 +149,21 @@ public void setDirty(boolean dirty) { this.dirty = dirty; } + public boolean isHotEvolution() { + return hotEvolution; + } + + public void setHotEvolution(boolean hotEvolution) { + this.hotEvolution = hotEvolution; + } + + public boolean canHotEvolution() { + return (!hotEvolution) + && (!rebuildAtLoad) + && (!dirty) + && (getFixPlans().isEmpty()); + } + public void addEvolutionFailPlan(int planInfoId) { evolutionFailPlanHashSet.add(planInfoId); } @@ -205,19 +223,6 @@ public static String serializeToJson(BaselineInfo baselineInfo, boolean simpleMo return baselineInfoJson.toJSONString(); } - /** - * base info , just for log - */ - public static String serializeBaseInfoToJson(BaselineInfo baselineInfo) { - JSONObject baselineInfoJson = new JSONObject(); - baselineInfoJson.put("id", baselineInfo.getId()); - baselineInfoJson.put("parameterSql", baselineInfo.getParameterSql()); - baselineInfoJson.put("tableSet", serializeTableSet(baselineInfo.getTableSet())); - baselineInfoJson.put("extend", baselineInfo.encodeExtend()); - - return baselineInfoJson.toJSONString(); - } - public static BaselineInfo deserializeFromJson(String json) { JSONObject baselineInfoJson = JSON.parseObject(json); BaselineInfo baselineInfo = new BaselineInfo(); @@ -242,7 +247,6 @@ public static BaselineInfo deserializeFromJson(String json) { baselineInfo.unacceptedPlans = unacceptedPlans; baselineInfo.extend = baselineInfoJson.getString("extend"); baselineInfo.decodeExtend(); - return baselineInfo; } @@ -347,6 +351,9 @@ public void merge(String schema, BaselineInfo t) { if (!parameterSql.equals(t.parameterSql)) { return; } + if (t.isHotEvolution()) { + this.hotEvolution = true; + } // only merge acceptedPlans int maxAcceptedPlans = InstConfUtil.getInt(SPM_MAX_ACCEPTED_PLAN_SIZE_PER_BASELINE); @@ -472,19 +479,27 @@ private void decodeExtend() { extendMap .getOrDefault(EXTEND_REBUILD_AT_LOAD, false) .toString()); + hotEvolution = Boolean.parseBoolean( + extendMap + .getOrDefault(EXTEND_HOT_EVOLVED, false) + .toString()); } public String encodeExtend() { - if (hint == null || "".equals(hint)) { + Map extendMap = Maps.newHashMap(); + if (!StringUtils.isEmpty(hint)) { + extendMap.put(EXTEND_POINT_SET, PlanManagerUtil.pointsTolist(pointSet)); + extendMap.put(EXTEND_HINT, hint); + extendMap.put(EXTEND_USE_POST_PLANNER, usePostPlanner); + extendMap.put(EXTEND_REBUILD_AT_LOAD, rebuildAtLoad); + } + if (hotEvolution) { + extendMap.put(EXTEND_HOT_EVOLVED, hotEvolution); + } + if (extendMap.isEmpty()) { return ""; } final JsonBuilder jsonBuilder = new JsonBuilder(); - - Map extendMap = Maps.newHashMap(); - extendMap.put(EXTEND_POINT_SET, PlanManagerUtil.pointsTolist(pointSet)); - extendMap.put(EXTEND_HINT, hint); - extendMap.put(EXTEND_USE_POST_PLANNER, usePostPlanner); - extendMap.put(EXTEND_REBUILD_AT_LOAD, rebuildAtLoad); return jsonBuilder.toJsonString(extendMap); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/BaselineManageable.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/BaselineManageable.java index 29c041c9a..f0555f022 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/BaselineManageable.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/BaselineManageable.java @@ -20,7 +20,6 @@ import org.apache.calcite.rel.RelNode; import org.apache.calcite.sql.SqlNode; -import javax.sql.DataSource; import java.util.List; import java.util.Map; @@ -34,11 +33,19 @@ PlanInfo createPlanInfo(String schema, String planJsonString, RelNode plan, int String origin, SqlNode ast, ExecutionContext executionContext); + BaselineInfo addBaselineInfo(String schema, String parameterSql, BaselineInfo baselineInfo); + void updateBaseline(Map> bMap); void deleteBaseline(String schema, String parameterSql); + void deleteBaseline(String schema, Integer baselineId); + void deleteBaseline(String schema, String parameterSql, int planInfoId); + void deleteBaselineEvolved(String schema); + + void deleteBaselinePlan(String schema, Integer baselineId, Integer planInfoId); + boolean checkBaselineHashCodeValid(BaselineInfo baselineInfo, PlanInfo planInfo); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJson.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJson.java index 7c8567e79..12ef4db09 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJson.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJson.java @@ -16,15 +16,20 @@ package com.alibaba.polardbx.optimizer.planmanager; import com.alibaba.polardbx.common.datatype.Decimal; -import com.google.common.collect.ImmutableList; import com.alibaba.polardbx.common.model.sqljep.Comparative; import com.alibaba.polardbx.common.model.sqljep.ComparativeAND; import com.alibaba.polardbx.common.model.sqljep.ComparativeOR; import com.alibaba.polardbx.common.model.sqljep.ExtComparative; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.core.TddlOperatorTable; +import com.alibaba.polardbx.optimizer.core.Xplan.XPlanTemplate; import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; +import com.alibaba.polardbx.optimizer.core.planner.Xplanner.XPlanUtil; import com.alibaba.polardbx.optimizer.core.rel.PushDownOpt; +import com.clearspring.analytics.util.Lists; +import com.google.common.collect.ImmutableList; +import com.google.protobuf.InvalidProtocolBufferException; +import com.mysql.cj.x.protobuf.PolarxExecPlan; import org.apache.calcite.avatica.AvaticaUtils; import org.apache.calcite.avatica.util.ByteString; import org.apache.calcite.avatica.util.TimeUnit; @@ -84,6 +89,9 @@ import java.util.Properties; import java.util.Set; +import static com.alibaba.polardbx.druid.sql.parser.CharTypes.bytesToHex; +import static com.alibaba.polardbx.druid.sql.parser.CharTypes.hexToBytes; + /** * Utilities for converting {@link RelNode} * into JSON format. @@ -101,7 +109,20 @@ public RelDistribution toDistribution(Map map) { List keys = (List) map.get("keys"); RelDistribution.Type type = RelDistribution.Type.valueOf(map.get("type").toString()); Integer shardCnt = (Integer) map.get("shardcnt"); - return new RelDistributions.RelDistributionImpl(type, ImmutableIntList.copyOf(keys), shardCnt); + switch (type) { + case SINGLETON: + return RelDistributions.SINGLETON; + case RANDOM_DISTRIBUTED: + return RelDistributions.RANDOM_DISTRIBUTED; + case ROUND_ROBIN_DISTRIBUTED: + return RelDistributions.ROUND_ROBIN_DISTRIBUTED; + case BROADCAST_DISTRIBUTED: + return RelDistributions.BROADCAST_DISTRIBUTED; + case ANY: + return RelDistributions.ANY; + default: + return new RelDistributions.RelDistributionImpl(type, ImmutableIntList.copyOf(keys), shardCnt); + } } public RelPartitionWise toPartitionWise(Map map) { @@ -188,12 +209,88 @@ protected Object toJson(Object value) { return toJson((RexWindowBound) value); } else if (value instanceof SqlKind) { return toJson((SqlKind) value); + } else if (value instanceof XPlanTemplate) { + return toJson((XPlanTemplate) value); + } else if (value instanceof XPlanUtil.ScalarParamInfo) { + return toJson((XPlanUtil.ScalarParamInfo) value); } else { throw new UnsupportedOperationException("type not serializable: " + value + " (type " + value.getClass().getCanonicalName() + ")"); } } + public static XPlanTemplate fromJsonToXPlan(Map map) throws InvalidProtocolBufferException { + if (map == null || map.isEmpty()) { + return null; + } + String template = (String) map.get("template"); + PolarxExecPlan.AnyPlan plan = PolarxExecPlan.AnyPlan.parseFrom(hexToBytes(template)); + List> tableNameList = Lists.newArrayList(); + List schemaNames = (List) map.get("schemaNames"); + List tableNames = (List) map.get("tableNames"); + for (int i = 0; i < schemaNames.size(); i++) { + tableNameList.add(new com.alibaba.polardbx.common.utils.Pair<>(schemaNames.get(i), tableNames.get(i))); + } + String indexName = (String) map.get("indexName"); + + List params = (List) map.get("paramInfo"); + + List paramInfoList = new ArrayList<>(); + for (Map param : params) { + XPlanUtil.ScalarParamInfo paramInfo = fromJson(param); + paramInfoList.add(paramInfo); + } + return new XPlanTemplate(indexName, plan, tableNameList, paramInfoList); + } + + private Object toJson(XPlanTemplate node) { + final Map map = jsonBuilder.map(); + List> tableNames = node.getTableNames(); + + List schemaList = new ArrayList<>(); + List tableList = new ArrayList<>(); + + for (com.alibaba.polardbx.common.utils.Pair tableName : tableNames) { + schemaList.add(tableName.getKey()); + tableList.add(tableName.getValue()); + } + + map.put("template", bytesToHex(node.getTemplate().toByteArray())); + map.put("schemaNames", schemaList); + map.put("tableNames", tableList); + map.put("indexName", node.getIndexName()); + + List paramInfos = node.getParamInfos(); + List list = jsonBuilder.list(); + for (XPlanUtil.ScalarParamInfo paramInfo : paramInfos) { + list.add(toJson(paramInfo)); + } + map.put("paramInfo", list); + return map; + } + + private static XPlanUtil.ScalarParamInfo fromJson(Map map) { + if (map == null || map.isEmpty()) { + return null; + } + String typeName = (String) map.get("type"); + XPlanUtil.ScalarParamInfo.Type type = XPlanUtil.ScalarParamInfo.Type.valueOf(typeName); + Integer id = (Integer) map.get("id"); + Boolean isBit = (Boolean) map.get("isBit"); + Boolean isNullAble = (Boolean) map.get("isNullAble"); + XPlanUtil.ScalarParamInfo paramInfo = new XPlanUtil.ScalarParamInfo(type, id, isBit, isNullAble); + return paramInfo; + } + + private Object toJson(XPlanUtil.ScalarParamInfo paramInfo) { + final Map map = jsonBuilder.map(); + map.put("type", paramInfo.getType().name()); + map.put("id", paramInfo.getId()); + map.put("isBit", paramInfo.isBit()); + map.put("isNullAble", paramInfo.isNullable()); + return map; + } + protected Object toJson(SqlKind value) { return value.name(); } @@ -276,6 +373,7 @@ private Object toJson(Pair node) { private Map toJson(RelNode node, String key) { final DRDSRelJsonWriter writer = new DRDSRelJsonWriter(this.supportMpp); + writer.setPlannerContext(PlannerContext.getPlannerContext(node)); node.explain(writer); return writer.asMap(key); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJsonReader.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJsonReader.java index 899b5f5fb..97c05ebd5 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJsonReader.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJsonReader.java @@ -18,6 +18,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.alibaba.polardbx.optimizer.PlannerContext; import com.fasterxml.jackson.core.type.TypeReference; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -91,6 +92,8 @@ public class DRDSRelJsonReader { private boolean supportMpp; + public static final String ARGS_KEY = "args"; + public DRDSRelJsonReader(RelOptCluster cluster, RelOptSchema relOptSchema, Schema schema, boolean supportMpp) { this.cluster = cluster; @@ -106,6 +109,10 @@ public RelNode read(String s) throws IOException { o = JSON.parseObject(s, TYPE_REF.getType()); @SuppressWarnings("unchecked") final List> rels = (List) o.get("rels"); readRels(rels); + String args = (String) o.get(ARGS_KEY); + if (args != null && lastRel != null) { + PlannerContext.getPlannerContext(lastRel).decodeArguments(args); + } return lastRel; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJsonWriter.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJsonWriter.java index 4c74613e6..2c3e53eb6 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJsonWriter.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJsonWriter.java @@ -25,6 +25,8 @@ import java.util.List; import java.util.Map; +import static com.alibaba.polardbx.optimizer.planmanager.DRDSRelJsonReader.ARGS_KEY; + /** * Callback for a relational expression to dump itself as JSON. */ @@ -80,6 +82,19 @@ protected void explain_(RelNode rel, List> values) { previousId = id; } + @Override + public String asString() { + final Map map = jsonBuilder.map(); + map.put("rels", relList); + if (plannerContext != null) { + map.put(ARGS_KEY, plannerContext.encodeExtendedParametersToJson()); + } + return jsonBuilder.toJsonString(map); + } + + public void setPlannerContext(PlannerContext plannerContext) { + this.plannerContext = plannerContext; + } } // End RelJsonWriter.java diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanInfo.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanInfo.java index f4d0ec903..2168c8658 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanInfo.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanInfo.java @@ -27,6 +27,8 @@ import com.alibaba.polardbx.gms.module.Module; import com.alibaba.polardbx.gms.module.ModuleLogInfo; import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.optimizeralert.OptimizerAlertUtil; import com.google.common.collect.Maps; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptCost; @@ -255,8 +257,9 @@ public boolean inited() { return plan != null; } - synchronized RelOptCost getCumulativeCost(RelOptCluster cluster, RelOptSchema relOptSchema, Parameters parameters) { + RelOptCost getCumulativeCost(RelOptCluster cluster, RelOptSchema relOptSchema, ExecutionContext ec) { RelNode plan = getPlan(cluster, relOptSchema); + Parameters parameters = ec.getParams(); if (DynamicConfig.getInstance().isEnableMQCacheByThread()) { try { RelMetadataQuery.THREAD_PARAMETERS.set(parameters); @@ -265,14 +268,17 @@ synchronized RelOptCost getCumulativeCost(RelOptCluster cluster, RelOptSchema re ModuleLogInfo.getInstance() .logRecord(Module.SPM, LogPattern.UNEXPECTED, new String[] {"spm get plan cost", t.getMessage()}, LogLevel.CRITICAL); + OptimizerAlertUtil.spmAlert(ec, t); throw new TddlRuntimeException(ErrorCode.ERR_PLAN_COST, t.getMessage()); } finally { RelMetadataQuery.THREAD_PARAMETERS.remove(); cluster.getMetadataQuery().clearThreadCache(); } } else { - PlannerContext.getPlannerContext(plan).setParams(parameters); - return cluster.getMetadataQuery().getCumulativeCost(plan); + synchronized (this) { + PlannerContext.getPlannerContext(plan).setParams(parameters); + return cluster.getMetadataQuery().getCumulativeCost(plan); + } } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanManager.java index ef58ce7eb..abae5659f 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanManager.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanManager.java @@ -37,8 +37,8 @@ import com.alibaba.polardbx.gms.module.ModuleInfo; import com.alibaba.polardbx.gms.module.ModuleLogInfo; import com.alibaba.polardbx.gms.node.LeaderStatusBridge; +import com.alibaba.polardbx.gms.node.MPPQueryMonitor; import com.alibaba.polardbx.gms.topology.ServerInstIdManager; -import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.gms.util.SyncUtil; import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.config.meta.CostModelWeight; @@ -49,11 +49,15 @@ import com.alibaba.polardbx.optimizer.core.planner.Planner; import com.alibaba.polardbx.optimizer.core.planner.PostPlanner; import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.alibaba.polardbx.optimizer.parse.SqlParameterizeUtils; import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized; import com.alibaba.polardbx.optimizer.planmanager.parametric.BaseParametricQueryAdvisor; import com.alibaba.polardbx.optimizer.planmanager.parametric.Point; +import com.alibaba.polardbx.optimizer.utils.OptimizerUtils; import com.alibaba.polardbx.optimizer.workload.WorkloadType; import com.alibaba.polardbx.optimizer.workload.WorkloadUtil; +import com.alibaba.polardbx.stats.metric.FeatureStats; import com.google.common.cache.CacheStats; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -95,6 +99,8 @@ import static com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil.mergeColumns; import static com.alibaba.polardbx.optimizer.view.VirtualViewType.PLAN_CACHE_CAPACITY; import static com.alibaba.polardbx.optimizer.view.VirtualViewType.SPM; +import static com.alibaba.polardbx.stats.metric.FeatureStatsItem.HOT_EVOLVE_PLAN_NUM; +import static com.alibaba.polardbx.stats.metric.FeatureStatsItem.NEW_BASELINE_NUM; import static org.apache.calcite.util.Litmus.IGNORE; public class PlanManager extends AbstractLifecycle implements BaselineManageable, PlanManageable, ModuleInfo { @@ -203,6 +209,7 @@ public ExecutionPlan choosePlan(SqlParameterized sqlParameterized, ExecutionCont executionPlan.setExplain(executionContext.getExplain() != null); if (!PlanManagerUtil.useSPM(schemaName, executionPlan, sqlParameterized.getSql(), executionContext) + || (executionContext.isUseColumnar() && !executionContext.isColumnarPlanCache()) || executionContext.isTestMode()) { return executionPlan; } @@ -252,6 +259,7 @@ private RelNode doChoosePlan(RelNode plan, SqlNode ast, SqlParameterized sqlPara baselineMap.put(schema, Maps.newConcurrentMap()); } BaselineInfo baselineInfo = baselineMap.get(schema).get(parameterizedSql); + SqlConverter sqlConverter = SqlConverter.getInstance(schema, executionContext); RelOptCluster cluster = sqlConverter.createRelOptCluster(); RelOptSchema relOptSchema = sqlConverter.getCatalog(); @@ -259,7 +267,6 @@ private RelNode doChoosePlan(RelNode plan, SqlNode ast, SqlParameterized sqlPara PlannerContext.getPlannerContext(cluster).setExplain(isExplain); PlannerContext.getPlannerContext(cluster).setSqlKind(PlannerContext.getPlannerContext(plan).getSqlKind()); PlannerContext.getPlannerContext(cluster).setAutoCommit(executionContext.isAutoCommit()); - PlannerContext.getPlannerContext(cluster).setExecutionContext(executionContext); PlannerContext.getPlannerContext(cluster).setExtraCmds(PlannerContext.getPlannerContext(plan).getExtraCmds()); PlannerContext.getPlannerContext(cluster) .setSkipPostOpt(PlannerContext.getPlannerContext(plan).isSkipPostOpt()); @@ -289,6 +296,30 @@ private RelNode doChoosePlan(RelNode plan, SqlNode ast, SqlParameterized sqlPara executionContext.setPlanSource(result.source); } + if (result.plan != null && ConfigDataMode.isMasterMode() && CBOUtil.planAllColumnar(result.plan)) { + // columnar query limiter. + long maximumQPS = executionContext.getParamManager().getLong(ConnectionParams.COLUMNAR_CLUSTER_MAXIMUM_QPS); + long maximumConcurrency = + executionContext.getParamManager().getLong(ConnectionParams.COLUMNAR_CLUSTER_MAXIMUM_CONCURRENCY); + + if (maximumQPS > 0 || maximumConcurrency > 0) { + // check concurrency of MPP query + long concurrency = MPPQueryMonitor.getInstance().getQueryConcurrency(); + if (maximumConcurrency > 0 && concurrency > maximumConcurrency) { + // use logicview. + return plan; + } + + long windowPeriod = + executionContext.getParamManager().getLong(ConnectionParams.COLUMNAR_QPS_WINDOW_PERIOD); + double qps = MPPQueryMonitor.getInstance().calculateQPS(windowPeriod); + if (maximumQPS > 0 && qps > maximumQPS) { + // use logicview. + return plan; + } + } + } + if (result.plan == null) { logger.warn("result plan is null"); return plan; @@ -309,7 +340,6 @@ private RelNode doChoosePlan(RelNode plan, SqlNode ast, SqlParameterized sqlPara } } PlannerContext.getPlannerContext(result.plan).setPlanInfo(result.planInfo); - PlannerContext.getPlannerContext(result.plan).setExecutionContext(executionContext); PlannerContext.getPlannerContext(result.plan).setBaselineInfo(result.baselineInfo); return result.plan; } @@ -395,12 +425,13 @@ public void feedBack(ExecutionPlan executionPlan, Throwable ex, // move stmt into spm from plan cache BaselineInfo baselineInfo = createBaselineInfo(parameterizedSql, executionPlan.getAst(), executionContext); - baselineSchemaMap.put(parameterizedSql, baselineInfo); + baselineInfo = addBaselineInfo(schema, parameterizedSql, baselineInfo); String planJsonString = PlanManagerUtil.relNodeToJson(plan); PlanInfo planInfo = createPlanInfo(schema, planJsonString, plan, baselineInfo.getId(), executionContext.getTraceId(), PlanManagerUtil.getPlanOrigin(plan), executionPlan.getAst(), executionContext); baselineInfo.addAcceptedPlan(planInfo); + baselineSchemaMap.put(parameterizedSql, baselineInfo); } // pqo feedback @@ -705,7 +736,7 @@ public Result(BaselineInfo baselineInfo, PlanInfo planInfo, RelNode plan, PLAN_S } } - private boolean baselineSizeCheck(String schema) { + public boolean baselineSizeCheck(String schema) { if (StringUtils.isEmpty(schema)) { return false; } @@ -738,6 +769,7 @@ private Result capturePlan(String schema, int tablesVersion = PlanManagerUtil.computeTablesVersion(schemaTables, schema, PlannerContext.getPlannerContext(plan).getExecutionContext()); if (tablesVersion != ERROR_TABLES_HASH_CODE) { + FeatureStats.getInstance().increment(NEW_BASELINE_NUM); BaselineInfo baselineInfo = new BaselineInfo(parameterizedSql.getSql(), schemaTables); PlanInfo resultPlanInfo = new PlanInfo(planJsonString, baselineInfo.getId(), simpleCostValue(plan), traceId, PlanManagerUtil.getPlanOrigin(plan), tablesVersion); @@ -799,7 +831,10 @@ private Result selectPlan(BaselineInfo baselineInfo, */ Collection fixPlans = baselineInfo.getFixPlans(); if (fixPlans != null && !fixPlans.isEmpty()) { - PlanInfo fixPlan = findMinCostPlan(cluster, relOptSchema, fixPlans, ec, null, cHashCode); + PlanInfo fixPlan = findMinCostPlan(cluster, relOptSchema, fixPlans, ec, null, cHashCode, false); + if (fixPlan == null) { + return buildNewPlan(cluster, relOptSchema, baselineInfo, sqlParameterized, ec, cHashCode); + } PLAN_SOURCE planSource = SPM_FIX; if (fixPlan.getTablesHashCode() != cHashCode && !StringUtils.isEmpty(fixPlan.getFixHint())) { @@ -853,7 +888,7 @@ private Result selectPlan(BaselineInfo baselineInfo, !isExplain && enableEvo) { // use unaccepted plan first if enableEvo PlanInfo unacceptedPlan = - findMinCostPlan(cluster, relOptSchema, unacceptedPlans.values(), ec, null, cHashCode); + findMinCostPlan(cluster, relOptSchema, unacceptedPlans.values(), ec, null, cHashCode, false); if (unacceptedPlan != null) { return new Result(baselineInfo, unacceptedPlan, unacceptedPlan.getPlan(cluster, relOptSchema), PLAN_SOURCE.SPM_UNACCEPTED); @@ -861,7 +896,8 @@ private Result selectPlan(BaselineInfo baselineInfo, } // find best plan from baseline accepted plans - resultPlanInfo = findMinCostPlan(cluster, relOptSchema, acceptedPlans.values(), ec, null, cHashCode); + resultPlanInfo = findMinCostPlan(cluster, relOptSchema, acceptedPlans.values(), ec, null, cHashCode, + baselineInfo.isHotEvolution()); if (resultPlanInfo != null) { // min cost plan return new Result(baselineInfo, resultPlanInfo, resultPlanInfo.getPlan(cluster, relOptSchema), @@ -885,10 +921,11 @@ private PLAN_SOURCE tryUpdatePlan(PlanInfo planInfo, RelOptSchema relOptSchema, int currentHashCode, ExecutionContext executionContext) { RelNode oldPlan = planInfo.getPlan(cluster, relOptSchema); + ExecutionContext executionContextCopy = executionContext.copy(); + executionContextCopy.setUseHint(true); ExecutionPlan newPlan = Planner.getInstance() - .plan(planInfo.getFixHint() + " " + sqlParameterized.getSql(), executionContext.copy()); - + .plan(planInfo.getFixHint() + " " + sqlParameterized.getSql(), executionContextCopy); PlanManagerUtil.jsonToRelNode(planInfo.getPlanJsonString(), cluster, relOptSchema); // if row type changed(select * xxx), meaning plan should be rebuilt RelDataType oldRowType = oldPlan.getRowType(); @@ -1028,16 +1065,43 @@ public static boolean isRecentlyExecuted(PlanInfo planInfo) { return System.currentTimeMillis() - planInfo.getLastExecuteTime() * 1000 <= recentTimePeriod; } - public PlanInfo findMinCostPlan(RelOptCluster cluster, RelOptSchema - relOptSchema, Collection plans, + /** + * check whether the plan can be chosen + * + * @param node root of plan + * @param ec executionContext + * @param planInfo plan info of current plan + * @return false if it's a columnar plan and can't be chosen + */ + public boolean canChooseColumnarPlan(RelNode node, ExecutionContext ec, PlanInfo planInfo) { + // not columnar plan + if (!PlannerContext.getPlannerContext(node).isUseColumnar()) { + return true; + } + // not auto commit, columnar plan can't be chosen + if (!ec.isAutoCommit()) { + return false; + } + // fixed plan can be chosen + if (planInfo.isFixed()) { + return true; + } + return OptimizerUtils.enableColumnarOptimizer(ec.getParamManager()); + } + + public PlanInfo findMinCostPlan(RelOptCluster cluster, RelOptSchema relOptSchema, Collection plans, ExecutionContext executionContext, Collection toBeRemovedPlan, - int tablesHashCode) { + int tablesHashCode, boolean hotEvolution) { String schema = executionContext.getSchemaName(); if (plans.size() == 0) { return null; } else if (plans.size() == 1) { PlanInfo planInfo = plans.iterator().next(); if (planInfo != null && (planInfo.isFixed() || planInfo.getTablesHashCode() == tablesHashCode)) { + RelNode rel = planInfo.getPlan(cluster, relOptSchema); + if (!canChooseColumnarPlan(rel, executionContext, planInfo)) { + return null; + } return planInfo; } else { return null; @@ -1050,7 +1114,10 @@ public PlanInfo findMinCostPlan(RelOptCluster cluster, RelOptSchema continue; } try { - planInfo.getPlan(cluster, relOptSchema); + RelNode rel = planInfo.getPlan(cluster, relOptSchema); + if (!canChooseColumnarPlan(rel, executionContext, planInfo)) { + continue; + } } catch (Throwable e) { logger.error("Plan Management Error", e); LoggerUtil.logSpmError(schema, "plan build error:" + planInfo.getPlanJsonString(), e); @@ -1061,11 +1128,14 @@ public PlanInfo findMinCostPlan(RelOptCluster cluster, RelOptSchema } if (bestCost == null) { // delay calculating acceptedPlanInfo cost - bestCost = planInfo.getCumulativeCost(cluster, relOptSchema, executionContext.getParams()); + bestCost = planInfo.getCumulativeCost(cluster, relOptSchema, executionContext); basePlan = planInfo; continue; } - RelOptCost cost = planInfo.getCumulativeCost(cluster, relOptSchema, executionContext.getParams()); + RelOptCost cost = planInfo.getCumulativeCost(cluster, relOptSchema, executionContext); + if (hotEvolution) { + FeatureStats.getInstance().increment(HOT_EVOLVE_PLAN_NUM); + } if (cost.isLt(bestCost)) { bestCost = cost; basePlan = planInfo; @@ -1103,13 +1173,10 @@ public void doEvolution(String schema, BaselineInfo baselineInfo, PlanInfo planI } return; } - - if (baselineInfoMap != null && - baselineInfoMap.get(baselineInfo.getParameterSql()) == null) { - /* capture plan should add to baselineMap when execute successfully */ - baselineInfoMap.put(baselineInfo.getParameterSql(), baselineInfo); + baselineInfo = addBaselineInfo(schema, baselineInfo.getParameterSql(), baselineInfo); + if (baselineInfo == null) { + return; } - /* try to build new plan if Estimate time diffed too much (1 second) */ @@ -1147,6 +1214,29 @@ try to build new plan if Estimate time diffed too much (1 second) } } + /** + * add baselineInfo to baselineMap + * + * @param schema schema of sql + * @param parameterSql parameterized sql + * @param baselineInfo baselineInfo to be added + * @return baselineInfo of parameterized sql in baselineMap + */ + @Override + public BaselineInfo addBaselineInfo(String schema, String parameterSql, BaselineInfo baselineInfo) { + if (StringUtils.isEmpty(schema)) { + throw GeneralUtil.nestedException("empty schema name"); + } + schema = schema.toLowerCase(Locale.ROOT); + if (!baselineSizeCheck(schema)) { + return null; + } + Map baselineInfoMap = + baselineMap.computeIfAbsent(schema, k -> Maps.newConcurrentMap()); + baselineInfoMap.putIfAbsent(parameterSql, baselineInfo); + return baselineInfoMap.get(parameterSql); + } + private boolean isRepeatableSql(String schema, SqlParameterized parameterizedSql, ExecutionContext ec) { PlanCache.CacheKey cacheKey = PlanCache.getCacheKey(schema, parameterizedSql, ec, false); return PlanCache.getInstance().getCache().getIfPresent(cacheKey) != null; @@ -1280,7 +1370,7 @@ private synchronized void loadBaseLineInfoAndPlanInfo() { continue; } } else { - if (baselineSize > maxSize) { + if (!baselineInfoRecord.fixed && baselineSize > maxSize) { continue; } // sql -> baseline @@ -1295,25 +1385,42 @@ private synchronized void loadBaseLineInfoAndPlanInfo() { continue; } - PlanInfo planInfo = - new PlanInfo(baselineInfoRecord.getId(), - baselineInfoRecord.getPlan(), - baselineInfoRecord.getCreateTime(), - baselineInfoRecord.getLastExecuteTime(), - baselineInfoRecord.getChooseCount(), - baselineInfoRecord.getCost(), - baselineInfoRecord.getEstimateExecutionTime(), - true, - baselineInfoRecord.isFixed(), - baselineInfoRecord.getTraceId(), - baselineInfoRecord.getOrigin(), - baselineInfoRecord.getPlanExtend(), - baselineInfoRecord.getTablesHashCode()); - planSize++; - if (baselineInfoRecord.isFixed()) { - fixPlanSize++; + if (StringUtils.isEmpty(baselineInfoRecord.getPlan())) { + baselineMapTmp.get(baselineInfoRecord.getSchemaName()).remove(baselineInfoRecord.getSql()); + } + + try { + PlanInfo planInfo = + new PlanInfo(baselineInfo.getId(), + baselineInfoRecord.getPlan(), + baselineInfoRecord.getCreateTime(), + baselineInfoRecord.getLastExecuteTime(), + baselineInfoRecord.getChooseCount(), + baselineInfoRecord.getCost(), + baselineInfoRecord.getEstimateExecutionTime(), + true, + baselineInfoRecord.isFixed(), + baselineInfoRecord.getTraceId(), + baselineInfoRecord.getOrigin(), + baselineInfoRecord.getPlanExtend(), + baselineInfoRecord.getTablesHashCode()); + planSize++; + if (baselineInfoRecord.isFixed()) { + fixPlanSize++; + } + baselineInfo.addAcceptedPlan(planInfo); + } catch (Throwable e) { + ModuleLogInfo.getInstance() + .logRecord( + Module.SPM, + UNEXPECTED, + new String[] { + "baseline plan deserialize failed:" + baselineInfoRecord.getSql(), + e.getMessage()}, + CRITICAL, + e + ); } - baselineInfo.addAcceptedPlan(planInfo); } baselineMap = baselineMapTmp; @@ -1401,6 +1508,111 @@ public void deleteBaseline(String schema, String parameterSql) { } } + /** + * only callback by baselineSyncController + */ + @Override + public void deleteBaseline(String schema, Integer baselineId) { + if (StringUtils.isEmpty(schema) || baselineId == null) { + return; + } + deleteBaseline(schema, baselineId, baselineMap); + } + + public static void deleteBaseline(String schema, Integer baselineId, + Map> baselineMap) { + schema = schema.toLowerCase(); + Map bMap = baselineMap.get(schema); + + if (bMap == null) { + return; + } + + String key = null; + for (Map.Entry entry : bMap.entrySet()) { + if (entry.getValue().getId() == baselineId) { + key = entry.getKey(); + break; + } + } + if (key == null) { + return; + } + + bMap.remove(key); + if (SyncUtil.isNodeWithSmallestId()) { + try (BaselineInfoAccessor baselineInfoAccessor = new BaselineInfoAccessor(true)) { + baselineInfoAccessor.deleteBaseline(schema, baselineId); + } catch (Exception e) { + ModuleLogInfo.getInstance() + .logRecord( + Module.SPM, + UNEXPECTED, + new String[] {"BASELINE DELETE", e.getMessage()}, + CRITICAL, + e); + } + } + } + + /** + * only callback by baselineSyncController + */ + @Override + public void deleteBaselinePlan(String schema, Integer baselineId, Integer planInfoId) { + if (StringUtils.isEmpty(schema) || baselineId == null || planInfoId == null) { + return; + } + + deleteBaselinePlan(schema, baselineId, planInfoId, baselineMap); + } + + public static void deleteBaselinePlan(String schema, Integer baselineId, int planInfoId, + Map> baselineMap) { + schema = schema.toLowerCase(); + Map map = baselineMap.get(schema); + if (map == null) { + return; + } + BaselineInfo baselineInfo = null; + String key = null; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue().getId() == baselineId) { + key = entry.getKey(); + baselineInfo = entry.getValue(); + break; + } + } + if (baselineInfo == null) { + return; + } + baselineInfo.removeAcceptedPlan(planInfoId); + baselineInfo.removeUnacceptedPlan(planInfoId); + boolean needRemoveBaseline = false; + if (baselineInfo.getAcceptedPlans().isEmpty()) { + map.remove(key); + needRemoveBaseline = true; + } + + if (SyncUtil.isNodeWithSmallestId()) { + try (BaselineInfoAccessor baselineInfoAccessor = new BaselineInfoAccessor(true)) { + if (needRemoveBaseline) { + baselineInfoAccessor.deleteBaseline(schema, baselineId); + } else { + baselineInfoAccessor.deletePlan(schema, baselineId, planInfoId); + } + } catch (Exception e) { + ModuleLogInfo.getInstance() + .logRecord( + Module.SPM, + UNEXPECTED, + new String[] {"BASELINE DELETE:" + schema + "," + baselineId, e.getMessage()}, + CRITICAL, + e); + } + } + } + /** * only callback by baselineSyncController */ @@ -1422,7 +1634,12 @@ public void deleteBaseline(String schema, String parameterSql, int planInfoId) { if (SyncUtil.isNodeWithSmallestId()) { try (BaselineInfoAccessor baselineInfoAccessor = new BaselineInfoAccessor(true)) { - baselineInfoAccessor.deletePlan(schema, baselineInfo.getId(), planInfoId); + if (baselineInfo.getAcceptedPlans().isEmpty()) { + baselineMap.get(schema).remove(parameterSql); + baselineInfoAccessor.deleteBaseline(schema, baselineInfo.getId()); + } else { + baselineInfoAccessor.deletePlan(schema, baselineInfo.getId(), planInfoId); + } } catch (Exception e) { ModuleLogInfo.getInstance() .logRecord( @@ -1434,9 +1651,37 @@ public void deleteBaseline(String schema, String parameterSql, int planInfoId) { } } - if (baselineInfo.getAcceptedPlans().isEmpty()) { - baselineMap.get(schema).remove(parameterSql); + } + + @Override + public void deleteBaselineEvolved(String schema) { + if (StringUtils.isEmpty(schema)) { + return; } + schema = schema.toLowerCase(Locale.ROOT); + if (baselineMap.get(schema) == null) { + return; + } + + if (SyncUtil.isNodeWithSmallestId()) { + try (BaselineInfoAccessor baselineInfoAccessor = new BaselineInfoAccessor(true)) { + for (BaselineInfo baselineInfo : baselineMap.get(schema).values()) { + if (baselineInfo.isHotEvolution()) { + baselineInfoAccessor.deleteBaseline(schema, baselineInfo.getId()); + } + } + } catch (Exception e) { + ModuleLogInfo.getInstance() + .logRecord( + Module.SPM, + UNEXPECTED, + new String[] {"BASELINE DELETE_EVOLVED:" + schema, e.getMessage()}, + CRITICAL, + e); + } + } + + baselineMap.get(schema).entrySet().removeIf(entry -> entry.getValue().isHotEvolution()); } public enum PLAN_SOURCE { diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanManagerUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanManagerUtil.java index 81e25bb04..9d2b5114a 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanManagerUtil.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/PlanManagerUtil.java @@ -16,11 +16,15 @@ package com.alibaba.polardbx.optimizer.planmanager; +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.jdbc.RawString; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.properties.ConnectionProperties; import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.properties.ParamManager; import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.config.ConfigDataMode; @@ -41,7 +45,6 @@ import com.alibaba.polardbx.optimizer.core.rel.BaseQueryOperation; import com.alibaba.polardbx.optimizer.core.rel.BaseTableOperation; import com.alibaba.polardbx.optimizer.core.rel.CollectTableNameVisitor; -import com.alibaba.polardbx.optimizer.core.rel.DirectTableOperation; import com.alibaba.polardbx.optimizer.core.rel.LogicalView; import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized; import com.alibaba.polardbx.optimizer.planmanager.feedback.PhyFeedBack; @@ -66,6 +69,7 @@ import org.apache.calcite.rex.RexBuilder; import org.apache.calcite.rex.RexCall; import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexUtil; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlNode; @@ -82,14 +86,13 @@ import java.io.IOException; import java.math.BigDecimal; import java.util.Collection; -import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.TreeMap; -import java.util.TreeSet; +import java.util.stream.Collectors; import java.util.zip.Deflater; import java.util.zip.Inflater; @@ -125,11 +128,13 @@ public static String relNodeToJson(RelNode plan) { } public static String relNodeToJson(RelNode plan, boolean supportMpp) { + if (plan == null) { + return null; + } DRDSRelJsonWriter drdsRelJsonWriter = new DRDSRelJsonWriter(supportMpp); + drdsRelJsonWriter.setPlannerContext(PlannerContext.getPlannerContext(plan)); plan.explain(drdsRelJsonWriter); - String serialPlan = drdsRelJsonWriter.asString(); - - return serialPlan; + return drdsRelJsonWriter.asString(); } public static RelNode jsonToRelNode(String json, RelOptCluster cluster, RelOptSchema relOptSchema) { @@ -781,15 +786,110 @@ public static boolean baselineSupported(RelNode plan) { if (plan == null) { return false; } - // don't support any possible xplan - LogicalViewFinder logicalViewFinder = new LogicalViewFinder(); - plan.accept(logicalViewFinder); - if (logicalViewFinder.getResult().size() == 1) { - LogicalView lv = logicalViewFinder.getResult().get(0); - if (lv != null && lv.getXPlanDirect() != null) { - return false; - } + PlannerContext context = PlannerContext.getPlannerContext(plan); + if (context.isHasConstantFold()) { + return false; } return true; } + + /** + * Changes parameter types based on table metadata. + * + * @param executionContext The execution context. + * @param plan The execution plan. + */ + public static void changeParameterTypeByTableMetadata(ExecutionContext executionContext, ExecutionPlan plan) { + if (!DynamicConfig.getInstance().isEnableChangeParamTypeByMeta()) { + return; + } + + try { + Map> parameterIndices = Maps.newHashMap(); + + // Retrieve the mapping between table scans and expressions from the execution plan. + // warning: this might be return null/throw runtime exception + Map tableExpressionMap = getRexNodeTableMap(plan.getPlan()); + + if (tableExpressionMap == null || tableExpressionMap.isEmpty()) { + return; + } + + for (Map.Entry entry : tableExpressionMap.entrySet()) { + RexUtil.EqualAndInExprFinder finder = new RexUtil.EqualAndInExprFinder(entry.getKey()); + entry.getValue().accept(finder); + processParameterTypeConversion(finder.getMap(), executionContext); + } + } catch (Throwable throwable) { + logger.warn("Failed to change parameter type by metadata:", throwable); + } + } + + protected static void processParameterTypeConversion(Map> parameterIndices, + ExecutionContext executionContext) { + if (parameterIndices.isEmpty()) { + return; + } + + convertIntToCharParameters(parameterIndices.get("int2char"), executionContext); + convertCharToIntParameters(parameterIndices.get("char2int"), executionContext); + } + + protected static void convertIntToCharParameters(Set intToCharIndices, + ExecutionContext executionContext) { + if (intToCharIndices != null) { + for (Integer index : intToCharIndices) { + ParameterContext parameterContext = executionContext.getParams().getCurrentParameter().get(index + 1); + Object value = parameterContext.getValue(); + + if (value instanceof Number) { + parameterContext.setValue(value.toString()); + parameterContext.setParameterMethod(ParameterMethod.setString); + } else if (value instanceof RawString) { + RawString rawString = (RawString) value; + List originalList = rawString.getObjList(); + List convertedList = originalList.stream() + .map(Object::toString) + .collect(Collectors.toList()); + parameterContext.setValue(new RawString(convertedList)); + } + } + } + } + + /** + * Generates a template ID based on the provided parameter SQL statement. + * + * @param parameterSql The SQL statement with parameters. + * @return A generated template ID as a fixed-length hexadecimal string. + */ + public static String generateTemplateId(String parameterSql) { + // Calculate the hash code of the parameter SQL + int hashCode = parameterSql.hashCode(); + + // Convert the integer hash code to a fixed-length hexadecimal string as the template ID + return TStringUtil.int2FixedLenHexStr(hashCode); + } + + protected static void convertCharToIntParameters(Set charToIntIndices, + ExecutionContext executionContext) { + if (charToIntIndices != null) { + for (Integer index : charToIntIndices) { + ParameterContext parameterContext = executionContext.getParams().getCurrentParameter().get(index + 1); + Object value = parameterContext.getValue(); + + if (value instanceof String) { + parameterContext.setValue(Long.parseLong((String) value)); + parameterContext.setParameterMethod(ParameterMethod.setLong); + } else if (value instanceof RawString) { + RawString rawString = (RawString) value; + List originalList = rawString.getObjList(); + List convertedList = originalList.stream() + .map(obj -> Long.parseLong((String) obj)) + .collect(Collectors.toList()); + parameterContext.setValue(new RawString(convertedList)); + } + } + } + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/GsiEvolutionInfo.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/GsiEvolutionInfo.java new file mode 100644 index 000000000..f659fb0ca --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/GsiEvolutionInfo.java @@ -0,0 +1,45 @@ +package com.alibaba.polardbx.optimizer.planmanager.hotevolution; + +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan; +import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized; + +/** + * all information needed to evolve the plan with hot gsi + */ +public class GsiEvolutionInfo { + private final SqlParameterized sqlParameterized; + private final ExecutionContext executionContext; + private final ExecutionPlan executionPlan; + private final String indexName; + private String templateId; + + public GsiEvolutionInfo(SqlParameterized sqlParameterized, ExecutionContext executionContext, + ExecutionPlan executionPlan, String indexName, String templateId) { + this.sqlParameterized = sqlParameterized; + this.executionContext = executionContext.copyContextForOptimizer(); + this.executionPlan = executionPlan; + this.indexName = indexName; + this.templateId = templateId; + } + + public SqlParameterized getSqlParameterized() { + return sqlParameterized; + } + + public ExecutionContext getExecutionContext() { + return executionContext; + } + + public ExecutionPlan getExecutionPlan() { + return executionPlan; + } + + public String getIndexName() { + return indexName; + } + + public String getTemplateId() { + return templateId; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/HotGsiCapture.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/HotGsiCapture.java new file mode 100644 index 000000000..03a303629 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/HotGsiCapture.java @@ -0,0 +1,199 @@ +package com.alibaba.polardbx.optimizer.planmanager.hotevolution; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.common.utils.LoggerUtil; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.gms.topology.SystemDbHelper; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticManager; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan; +import com.alibaba.polardbx.optimizer.core.planner.PlanCache; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.alibaba.polardbx.optimizer.core.rel.LogicalIndexScan; +import com.alibaba.polardbx.optimizer.optimizeralert.OptimizerAlertManager; +import com.alibaba.polardbx.optimizer.optimizeralert.OptimizerAlertType; +import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized; +import com.alibaba.polardbx.optimizer.planmanager.BaselineInfo; +import com.alibaba.polardbx.optimizer.planmanager.PlanManager; +import com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil; +import com.alibaba.polardbx.optimizer.utils.ExecutionPlanProperties; +import com.alibaba.polardbx.optimizer.utils.OptimizerUtils; +import org.apache.calcite.rel.RelNode; +import org.apache.commons.lang.StringUtils; + +import java.util.Locale; + +import static org.apache.calcite.sql.SqlKind.QUERY; + +/** + * try to capture plan with hot gsi + */ +public class HotGsiCapture { + + /** + * entry point capture plan with hot gsi + * + * @param sqlParameterized origin sql + * @param ec context of the sql + * @param executionPlan current plan to check + * @param hotGsiEvolution hot gsi evolution + */ + public static boolean capture( + SqlParameterized sqlParameterized, + ExecutionContext ec, + ExecutionPlan executionPlan, + HotGsiEvolution hotGsiEvolution, + String templateId) { + String schema = ec.getSchemaName(); + + try { + // pre-test + if (!preTest(sqlParameterized, ec, executionPlan)) { + return false; + } + + // capture hot gsi + String index = candidateHotGsi(ec, executionPlan.getPlan()); + + if (!StringUtils.isEmpty(index)) { + // submit to evolution + boolean offer = hotGsiEvolution.submitEvolutionTask( + new GsiEvolutionInfo(sqlParameterized, ec, executionPlan, index, templateId)); + if (!offer) { + LoggerUtil.logSpm(schema, + String.format( + "HGE: schema [%s] traceid [%s] tid [%s] fails to capture due to queue full[%d]", + ec.getSchemaName(), + ec.getTraceId(), + templateId, + hotGsiEvolution.getQueueSize())); + return false; + } + LoggerUtil.logSpm(schema, + String.format("HGE: schema [%s] traceid [%s] tid [%s] is submitted to evolution", + ec.getSchemaName(), + ec.getTraceId(), + templateId)); + return true; + } + LoggerUtil.logSpm(schema, + String.format( + "HGE: schema [%s] traceid [%s] tid [%s] fails to capture due to can't find any hot gsi", + ec.getSchemaName(), + ec.getTraceId(), + templateId)); + } catch (Throwable e) { + LoggerUtil.logSpm(schema, e.getMessage()); + } + return false; + } + + /** + * check whether the plan matches specific pattern and contains hot gsi + * + * @param ec context + * @param plan the plan to be checked + * @return gsi name if the plan contains hot gsi, null if not found + */ + public static String candidateHotGsi(ExecutionContext ec, RelNode plan) { + // check if the plan matches specific pattern + Pair getHotGsiPattern = HotGsiPattern.findPattern(plan); + if (!getHotGsiPattern.getKey()) { + return null; + } + LogicalIndexScan indexScan = getHotGsiPattern.getValue(); + String indexName = indexScan.getTableNames().get(0); + // don't evolute if statistics missed + if (StatisticManager.expired(ec.getSchemaName(), indexName)) { + OptimizerAlertManager.getInstance().log(OptimizerAlertType.STATISTIC_MISS, ec); + return null; + } + + // calculate max selectivity + double rowCount = CBOUtil.getTableMeta(indexScan.getTable()).getRowCount(null) * + indexScan.getMaxSelectivity(); + if (rowCount > ec.getParamManager().getLong(ConnectionParams.HOT_GSI_EVOLUTION_THRESHOLD)) { + return indexName; + } + return null; + } + + /** + * pre-test the plan, prevent call candidateHotGsi if preTest fails + * + * @param sqlParameterized origin sql + * @param ec context of the sql + * @param executionPlan current plan to check + * @return true if pre-test passed + */ + private static boolean preTest( + SqlParameterized sqlParameterized, + ExecutionContext ec, + ExecutionPlan executionPlan) { + // should enable hot evolution + if (!DynamicConfig.getInstance().enableHotGsiEvolution()) { + return false; + } + // should enable index selection + if (!ec.getParamManager().getBoolean(ConnectionParams.ENABLE_INDEX_SELECTION)) { + return false; + } + String schema = ec.getSchemaName(); + if (StringUtils.isEmpty(schema)) { + return false; + } + schema = schema.toLowerCase(Locale.ROOT); + // don't evolve built-in-database + if (SystemDbHelper.isDBBuildIn(schema)) { + return false; + } + // should use spm + if (!PlanManagerUtil.useSpm(sqlParameterized, ec)) { + return false; + } + + // don't evolve if the sql is too long + if (sqlParameterized.getSql().length() > + ec.getParamManager().getInt(ConnectionParams.SPM_MAX_BASELINE_INFO_SQL_LENGTH)) { + return false; + } + // only consider query + if (!executionPlan.getAst().isA(QUERY)) { + return false; + } + + // don't evolve if plan cache is full + if (PlanCache.getInstance().getCache().size() >= PlanCache.getInstance().getCurrentCapacity() - 20) { + return false; + } + + // don't evolve if spm is full + if (!PlanManager.getInstance().baselineSizeCheck(schema)) { + return false; + } + + // don't evolve sql with index hint + if (executionPlan.checkProperty(ExecutionPlanProperties.WITH_INDEX_HINT)) { + return false; + } + // don't evolve if the baseline can't evolve + BaselineInfo baselineInfo = + PlanManager.getInstance().getBaselineMap(schema).get(sqlParameterized.getSql()); + if (baselineInfo != null && (!baselineInfo.canHotEvolution())) { + return false; + } + + // don't evolve sql with join + if (PlannerContext.getPlannerContext(executionPlan.getPlan()).getJoinCount() > 0) { + return false; + } + // don't evolve sql with subquery + if (OptimizerUtils.hasSubquery(executionPlan.getPlan())) { + return false; + } + + return true; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/HotGsiEvolution.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/HotGsiEvolution.java new file mode 100644 index 000000000..473cbc069 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/HotGsiEvolution.java @@ -0,0 +1,226 @@ +package com.alibaba.polardbx.optimizer.planmanager.hotevolution; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.LoggerUtil; +import com.alibaba.polardbx.common.utils.thread.ExecutorUtil; +import com.alibaba.polardbx.common.utils.thread.NamedThreadFactory; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan; +import com.alibaba.polardbx.optimizer.core.planner.PlanCache; +import com.alibaba.polardbx.optimizer.core.planner.Planner; +import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized; +import com.alibaba.polardbx.optimizer.planmanager.BaselineInfo; +import com.alibaba.polardbx.optimizer.planmanager.PlanInfo; +import com.alibaba.polardbx.optimizer.planmanager.PlanManager; +import com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil; +import com.alibaba.polardbx.stats.metric.FeatureStats; +import com.google.common.collect.Sets; +import org.apache.calcite.rel.RelNode; +import org.apache.commons.lang.StringUtils; + +import java.util.Locale; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import static com.alibaba.polardbx.stats.metric.FeatureStatsItem.HOT_EVOLVE_PLAN_NUM; + +public class HotGsiEvolution implements Runnable { + // schedule thread to evolve plan every 1s + private final ScheduledThreadPoolExecutor hotEvoluteThread = + ExecutorUtil.createScheduler(1, + new NamedThreadFactory("Hot-Gsi-Evolve-Thread", true), + new ThreadPoolExecutor.DiscardPolicy()); + + private final static int QUEUE_CAPACITY = 100; + private final static long INIT_DELAY = 5L; + private final static HotGsiEvolution INSTANCE = new HotGsiEvolution(QUEUE_CAPACITY, INIT_DELAY); + + public static HotGsiEvolution getInstance() { + return INSTANCE; + } + + private final BlockingQueue evolutionQueue; + + public HotGsiEvolution(int capacity, long delay) { + this.evolutionQueue = new LinkedBlockingQueue<>(capacity); + this.hotEvoluteThread.scheduleWithFixedDelay( + this, + delay, + 1, + TimeUnit.SECONDS + ); + } + + public HotGsiEvolution(int size) { + this.evolutionQueue = new LinkedBlockingQueue<>(size); + } + + public boolean submitEvolutionTask(GsiEvolutionInfo info) { + return evolutionQueue.offer(info); + } + + public int getQueueSize() { + return evolutionQueue.size(); + } + + @Override + public void run() { + GsiEvolutionInfo info; + while ((info = evolutionQueue.poll()) != null) { + evolution(info); + } + } + + /** + * entry point to evolve plan + * + * @param info info of plan to evolved + */ + public static void evolution(GsiEvolutionInfo info) { + try { + SqlParameterized sqlParameterized = info.getSqlParameterized(); + if (sqlParameterized == null) { + return; + } + // check ENABLE_HOT_GSI_EVOLUTION again in case it is disabled between capture and evolution + if (!DynamicConfig.getInstance().enableHotGsiEvolution()) { + return; + } + + ExecutionContext executionContext = info.getExecutionContext(); + ExecutionPlan executionPlan = info.getExecutionPlan(); + PlanManager planManager = PlanManager.getInstance(); + String schema = executionContext.getSchemaName(); + schema = schema.toLowerCase(Locale.ROOT); + String parameterizedSql = sqlParameterized.getSql(); + + // plan cache is full + if (PlanCache.getInstance().getCache().size() >= PlanCache.getInstance().getCurrentCapacity() - 20) { + LoggerUtil.logSpm(schema, + String.format("HGE: schema [%s] tid [%s] fails to evolute due to plan cache full", schema, + info.getTemplateId())); + return; + } + + // get the baseline info of current sql + BaselineInfo baselineInfo = planManager.getBaselineMap(schema).get(parameterizedSql); + if (baselineInfo == null) { + baselineInfo = planManager.addBaselineInfo(schema, parameterizedSql, + planManager.createBaselineInfo(parameterizedSql, executionPlan.getAst(), executionContext)); + } + // baseline is full + if (baselineInfo == null) { + LoggerUtil.logSpm(schema, + String.format("HGE: schema [%s] tid [%s] fails to evolute due to spm full", schema, + info.getTemplateId())); + return; + } + // don't evolve if the sql is evolved already + if (!baselineInfo.canHotEvolution()) { + LoggerUtil.logSpm(schema, + String.format("HGE: schema [%s] tid [%s] bid [%s] fails to evolute due to baseline evolved", + schema, info.getTemplateId(), baselineInfo.getId())); + return; + } + // add origin plan and plan without gsi + if (!addPlanDefaultAndWithoutGsi(sqlParameterized, executionContext, executionPlan, baselineInfo, info)) { + return; + } + Set ignoredGsi = Sets.newTreeSet(String::compareToIgnoreCase); + ignoredGsi.add(info.getIndexName()); + do { + executionContext = executionContext.copyContextForOptimizer(); + executionContext.setIgnoredGsi(ignoredGsi); + executionPlan = Planner.getInstance().doBuildPlan(sqlParameterized, executionContext); + String indexName = HotGsiCapture.candidateHotGsi(executionContext, executionPlan.getPlan()); + // can't find hot gsi + if (StringUtils.isEmpty(indexName)) { + return; + } + ignoredGsi.add(indexName); + } while (addNewPlanInfo(executionContext, executionPlan, baselineInfo, info)); + } catch (Throwable t) { + LoggerUtil.logSpm(info.getExecutionContext().getSchemaName(), t.getMessage()); + } + } + + /** + * gen plan without index selection, mark the baseline as HotEvolution and add it to baseline + * + * @param sqlParameterized origin sql + * @param executionContext original execution context + * @param executionPlan original execution plan + * @param baselineInfo baseline info of the sql + * @return true if plan without gsi is added + */ + private static boolean addPlanDefaultAndWithoutGsi( + SqlParameterized sqlParameterized, + ExecutionContext executionContext, + ExecutionPlan executionPlan, + BaselineInfo baselineInfo, + GsiEvolutionInfo info) { + // build plan without index_selection + ExecutionContext newExecutionContext = executionContext.copyContextForOptimizer(); + newExecutionContext.getExtraCmds().put(ConnectionProperties.ENABLE_INDEX_SELECTION, false); + ExecutionPlan newExecutionPlan = Planner.getInstance().doBuildPlan(sqlParameterized, newExecutionContext); + // HotGsiPattern shouldn't find gsi here, except that force index(gsi) is used or select gsi table directly + // in which case, we don't evolve + if (HotGsiPattern.findPattern(newExecutionPlan.getPlan()).getKey()) { + return false; + } + addNewPlanInfo(executionContext, executionPlan, baselineInfo, info); + + baselineInfo.setHotEvolution(true); + FeatureStats.getInstance().increment(HOT_EVOLVE_PLAN_NUM); + return addNewPlanInfo(newExecutionContext, newExecutionPlan, baselineInfo, info); + } + + /** + * @return true if new plan is added + */ + private static boolean addNewPlanInfo(ExecutionContext executionContext, + ExecutionPlan executionPlan, + BaselineInfo baselineInfo, + GsiEvolutionInfo info) { + PlanManager planManager = PlanManager.getInstance(); + + // don't add if there are too many accepted plans + if (baselineInfo.getAcceptedPlans().size() >= executionContext.getParamManager() + .getInt(ConnectionParams.SPM_MAX_ACCEPTED_PLAN_SIZE_PER_BASELINE)) { + LoggerUtil.logSpm(executionContext.getSchemaName(), + String.format("HGE: schema [%s] traceid [%s] tid [%s] fails to evolve due to baseline plan full", + executionContext.getSchemaName(), executionContext.getTraceId(), info.getTemplateId())); + return false; + } + if (!PlanManagerUtil.baselineSupported(executionPlan.getPlan())) { + LoggerUtil.logSpm(executionContext.getSchemaName(), + String.format("HGE: schema [%s] traceid [%s] tid [%s] fails to evolve due to plan not supported", + executionContext.getSchemaName(), executionContext.getTraceId(), info.getTemplateId())); + return false; + } + RelNode plan = executionPlan.getPlan(); + String planJsonString = PlanManagerUtil.relNodeToJson(plan); + PlanInfo planInfo = + planManager.createPlanInfo( + executionContext.getSchemaName(), planJsonString, plan, baselineInfo.getId(), + executionContext.getTraceId(), + PlanManagerUtil.getPlanOrigin(plan), executionPlan.getAst(), executionContext); + // set LastExecuteTime to avoid bing removed directly + planInfo.setLastExecuteTime(GeneralUtil.unixTimeStamp()); + if (baselineInfo.addAcceptedPlan(planInfo) == null) { + LoggerUtil.logSpm(executionContext.getSchemaName(), + String.format("HGE: generate spm baseline_id[%s] plan_id[%s] for trace_id [%s] tid[%s]", + baselineInfo.getId(), planInfo.getId(), executionContext.getTraceId(), info.getTemplateId())); + return true; + } + return false; + } + +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/HotGsiPattern.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/HotGsiPattern.java new file mode 100644 index 000000000..5d643b424 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/planmanager/hotevolution/HotGsiPattern.java @@ -0,0 +1,112 @@ +package com.alibaba.polardbx.optimizer.planmanager.hotevolution; + +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.alibaba.polardbx.optimizer.core.rel.BKAJoin; +import com.alibaba.polardbx.optimizer.core.rel.Gather; +import com.alibaba.polardbx.optimizer.core.rel.LogicalIndexScan; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; +import com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter; +import org.apache.calcite.rel.BiRel; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.RelVisitor; +import org.apache.calcite.rel.core.Join; +import org.apache.calcite.rel.core.Sort; +import org.apache.calcite.rel.core.TableModify; +import org.apache.calcite.rel.core.Window; +import org.apache.calcite.sql.SqlSelect; +import org.apache.commons.collections.CollectionUtils; + +/** + * check whether the plan follows the following pattern + */ +public class HotGsiPattern extends RelVisitor { + /** + * true only if one lookup join in the table + */ + private boolean canEvolute; + private LogicalIndexScan targetIndexScan; + + public HotGsiPattern() { + this.canEvolute = false; + this.targetIndexScan = null; + } + + @Override + public void visit(RelNode node, int ordinal, RelNode parent) { + /** + * (any node expect BiRel,window or tableModify) + * | + * BKA join + * / \ + * (Gather/sort) (GATHER) + * / \ + * IndexScan LV + */ + if (!(node instanceof BiRel + || node instanceof Window + || node instanceof TableModify)) { + super.visit(node, ordinal, parent); + } + + if (node instanceof BKAJoin) { + RelNode outer = ((Join) node).getOuter(); + RelNode inner = ((Join) node).getInner(); + while (outer instanceof Gather || outer instanceof Sort) { + outer = outer.getInput(0); + } + while (inner instanceof Gather) { + inner = inner.getInput(0); + } + if (outer instanceof LogicalIndexScan && inner instanceof LogicalView) { + LogicalIndexScan indexScan = (LogicalIndexScan) outer; + LogicalView logicalView = (LogicalView) inner; + SqlSelect.LockMode lockMode = indexScan.getLockMode(); + // don't evaluate if lock mode is set + if (!(lockMode == null || lockMode == SqlSelect.LockMode.UNDEF)) { + return; + } + // don't evaluate if has subquery + if (CollectionUtils.isNotEmpty(indexScan.getCorrelateVariableScalar()) + || CollectionUtils.isNotEmpty(logicalView.getCorrelateVariableScalar())) { + return; + } + // outer side must be gsi of inner side + if ((indexScan.getTableNames().size() == 1 && logicalView.getTableNames().size() == 1)) { + TableMeta tm = CBOUtil.getTableMeta(logicalView.getTable()); + if (tm.withGsi(TddlSqlToRelConverter.unwrapGsiName(indexScan.getLogicalTableName()))) { + setEvolute(indexScan); + } + } + } + } + } + + private void setEvolute(LogicalIndexScan indexScan) { + canEvolute = true; + targetIndexScan = indexScan; + } + + boolean canEvolute() { + return canEvolute; + } + + private LogicalIndexScan getTargetIndexScan() { + return targetIndexScan; + } + + /** + * check whether the plan follows the hot gsi pattern + * + * @param rel the root of the plan + * @return Pair + * canEvolute is true if the plan follows the hot gsi pattern, false otherwise + * targetIndexScan is the gsi to be checked, NULL if not found + */ + public static Pair findPattern(RelNode rel) { + HotGsiPattern hotGsiPattern = new HotGsiPattern(); + hotGsiPattern.go(rel); + return Pair.of(hotGsiPattern.canEvolute(), hotGsiPattern.getTargetIndexScan()); + } +} \ No newline at end of file diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/rule/TddlRuleManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/rule/TddlRuleManager.java index c46c4914f..4429c47a6 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/rule/TddlRuleManager.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/rule/TddlRuleManager.java @@ -176,11 +176,6 @@ public TargetDB shardAny(String logicTable) { TargetDB target = new TargetDB(); target.setDbIndex(group); target.addOneTable(tableNames.iterator().next()); -// if (ConfigDataMode.isFastMock()) { -// for (String tableName : target.getTableNames()) { -// MockDataManager.phyTableToLogicalTableName.put(tableName, logicTable); -// } -// } return target; } } @@ -601,6 +596,9 @@ public boolean containExtPartitions(String logicalTable) { return false; } + // !!!!ATTENTION PLEASE!!!! + // if need to get the partitionInfo of latest version, use this interface, + // otherwise PLEASE get it from ExecutionContext, usage: executionContext.getSchemaManager(dbName).getTable(logTbName).getPartitionInfo() public PartitionInfoManager getPartitionInfoManager() { return partitionInfoManager; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/selectivity/AbstractSelectivityEstimator.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/selectivity/AbstractSelectivityEstimator.java index 47a511174..2810b1cc6 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/selectivity/AbstractSelectivityEstimator.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/selectivity/AbstractSelectivityEstimator.java @@ -16,6 +16,9 @@ package com.alibaba.polardbx.optimizer.selectivity; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.optimizeralert.OptimizerAlertUtil; import org.apache.calcite.plan.RelOptPredicateList; import org.apache.calcite.rel.metadata.RelMdUtil; import org.apache.calcite.rel.metadata.RelMetadataQuery; @@ -29,11 +32,14 @@ public abstract class AbstractSelectivityEstimator extends RexVisitorImpl conju } int idx = likeString.indexOf("%"); - if (idx == 0) { + if (idx == -1) { + leftValue = likeString; + rightValue = likeString; + } else if (idx == 0) { continue; } else { leftValue = likeString.substring(0, idx); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/selectivity/TableScanSelectivityUpperLimitEstimator.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/selectivity/TableScanSelectivityUpperLimitEstimator.java new file mode 100644 index 000000000..41f733d80 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/selectivity/TableScanSelectivityUpperLimitEstimator.java @@ -0,0 +1,546 @@ +package com.alibaba.polardbx.optimizer.selectivity; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.RawString; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.config.meta.DrdsRelMdSelectivity; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.IndexMeta; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticManager; +import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticResult; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.alibaba.polardbx.optimizer.utils.DrdsRexFolder; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.apache.calcite.plan.RelOptPredicateList; +import org.apache.calcite.plan.RelOptUtil; +import org.apache.calcite.rel.core.TableScan; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexCall; +import org.apache.calcite.rex.RexDynamicParam; +import org.apache.calcite.rex.RexInputRef; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexSimplify; +import org.apache.calcite.rex.RexUtil; +import org.apache.calcite.rex.RexVisitorImpl; +import org.apache.calcite.sql.SqlKind; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * estimate the upper bound of Selectivity for any possible parameter + */ +public class TableScanSelectivityUpperLimitEstimator extends RexVisitorImpl { + private final double tableRowCount; + private final TableMeta tableMeta; + private final PlannerContext plannerContext; + private final RexBuilder rexBuilder; + + public static int DEFAULT_IN_VALUES = 50; + + private static final Set FREE_OP = ImmutableSet.builder() + .add(SqlKind.LESS_THAN_OR_EQUAL) + .add(SqlKind.LESS_THAN) + .add(SqlKind.GREATER_THAN) + .add(SqlKind.GREATER_THAN_OR_EQUAL) + .add(SqlKind.NOT_EQUALS) + .add(SqlKind.NOT_IN) + .add(SqlKind.BETWEEN) + .add(SqlKind.NOT_BETWEEN) + .add(SqlKind.LIKE) + .add(SqlKind.IS_DISTINCT_FROM) + .build(); + + private static final Set BOUND_OP = ImmutableSet.builder() + .add(SqlKind.EQUALS) + .add(SqlKind.IN) + .add(SqlKind.IS_NOT_DISTINCT_FROM) + .add(SqlKind.IS_NULL) + .add(SqlKind.IS_NOT_NULL) + .build(); + + private static final Set EQ_OP = ImmutableSet.builder() + .add(SqlKind.EQUALS) + .add(SqlKind.IS_NOT_DISTINCT_FROM) + .build(); + + private static final Set COMPOSITE_OP = ImmutableSet.builder() + .add(SqlKind.AND) + .add(SqlKind.OR) + .add(SqlKind.NOT) + .build(); + + public TableScanSelectivityUpperLimitEstimator(TableScan tableScan) { + super(true); + this.tableMeta = CBOUtil.getTableMeta(tableScan.getTable()); + this.tableRowCount = tableMeta.getRowCount(null); + this.plannerContext = PlannerContext.getPlannerContext(tableScan); + this.rexBuilder = tableScan.getCluster().getRexBuilder(); + } + + public UpperSelectivity evaluate(RexNode predicate) { + try { + if (predicate == null) { + return UpperSelectivity.createBound(1D); + } else { + RexNode simplifiedPredicate = + new RexSimplify(rexBuilder, RelOptPredicateList.EMPTY, true, RexUtil.EXECUTOR).simplify(predicate); + if (simplifiedPredicate.isAlwaysTrue()) { + return UpperSelectivity.createBound(1D); + } else if (simplifiedPredicate.isAlwaysFalse()) { + return UpperSelectivity.createBound(0D); + } else { + UpperSelectivity value = simplifiedPredicate.accept(this); + if (value == null) { + return UpperSelectivity.UNKNOWN; + } + return value; + } + } + } catch (Throwable e) { + return UpperSelectivity.UNKNOWN; + } + } + + @Override + public UpperSelectivity visitCall(RexCall call) { + switch (call.getKind()) { + case OR: + return orSelectivity(call); + case AND: + return andSelectivity(call); + case NOT: + return notSelectivity(call); + default: + return defaultSelectivity(call); + } + } + + private UpperSelectivity orSelectivity(RexNode predicate) { + List disjunctions = RelOptUtil.disjunctions(predicate); + List upperBound = Lists.newArrayList(); + for (RexNode rexNode : disjunctions) { + if (rexNode instanceof RexCall) { + RexCall rexCall = (RexCall) rexNode; + if (rexCall.getKind().belongsTo(COMPOSITE_OP)) { + upperBound.add(evaluate(rexCall)); + } else { + upperBound.add(defaultSelectivity(rexCall)); + } + } + } + return UpperSelectivity.or(upperBound); + } + + private UpperSelectivity andSelectivity(RexNode predicate) { + List conjunctions = RelOptUtil.conjunctions(predicate); + Map selectivityMap = Maps.newHashMap(); + List upperBound = Lists.newArrayList(); + Set eqColumns = Sets.newHashSet(); + for (RexNode rexNode : conjunctions) { + if (rexNode instanceof RexCall) { + RexCall rexCall = (RexCall) rexNode; + if (rexCall.getKind().belongsTo(COMPOSITE_OP)) { + upperBound.add(evaluate(rexCall)); + } else { + UpperSelectivity result = defaultSelectivity(rexCall); + if (result.getIdx() < 0) { + upperBound.add(result); + } else { + if (rexCall.getKind().belongsTo(EQ_OP)) { + eqColumns.add(result.getIdx()); + } + UpperSelectivity oldResult = selectivityMap.get(result.getIdx()); + if (oldResult == null || oldResult.getSelectivity() > result.getSelectivity()) { + selectivityMap.put(result.getIdx(), result); + } + } + } + } + } + // composite pk or uk + if (pkukEqualPredicate(eqColumns)) { + return UpperSelectivity.createBound(1 / tableRowCount); + } + + // add smallest Selectivity for each column + upperBound.addAll(selectivityMap.values()); + return UpperSelectivity.and(upperBound); + } + + private UpperSelectivity notSelectivity(RexCall predicate) { + return UpperSelectivity.not(evaluate(predicate.getOperands().get(0))); + } + + /** + * @param predicate the predicate tested + * @return Selectivity upper bound of predicate + */ + private UpperSelectivity defaultSelectivity(RexCall predicate) { + if (predicate == null || tableMeta == null) { + return UpperSelectivity.UNKNOWN; + } + + if (predicate.isAlwaysTrue()) { + return UpperSelectivity.createBound(1D); + } + + if (predicate.isAlwaysFalse()) { + return UpperSelectivity.createBound(0D); + } + + if (FREE_OP.contains(predicate.getKind())) { + switch (predicate.getKind()) { + case LESS_THAN_OR_EQUAL: + case LESS_THAN: + case GREATER_THAN: + case GREATER_THAN_OR_EQUAL: + case NOT_EQUALS: + case IS_DISTINCT_FROM: + return freeVarOpOneConstOrOneConstOpOp(predicate); + case NOT_IN: + return freeVarNotIn(predicate); + case BETWEEN: + case NOT_BETWEEN: + return freeVarOpTwoConst(predicate); + case LIKE: + return freeVarOpOneConst(predicate); + default: + return UpperSelectivity.UNKNOWN; + } + } + + if (BOUND_OP.contains(predicate.getKind())) { + switch (predicate.getKind()) { + case EQUALS: + case IS_NOT_DISTINCT_FROM: + return boundVarEqOneConstOrOneConstEqOp(predicate); + case IS_NULL: + return boundVarNull(predicate); + case IS_NOT_NULL: + return boundVarNotNull(predicate); + case IN: + return boundVarIn(predicate); + default: + return UpperSelectivity.UNKNOWN; + } + } + + return UpperSelectivity.UNKNOWN; + } + + /** + * check whether the predicate is 'a op ?' or '? op a' + * + * @param pred the predicate tested + */ + private UpperSelectivity freeVarOpOneConstOrOneConstOpOp(RexCall pred) { + if (pred.getOperands().size() != 2) { + return UpperSelectivity.UNKNOWN; + } + RexNode leftRexNode = pred.getOperands().get(0); + RexNode rightRexNode = pred.getOperands().get(1); + int inputRef = -1; + Object value = null; + + if (leftRexNode instanceof RexInputRef && !(rightRexNode instanceof RexInputRef)) { + inputRef = ((RexInputRef) leftRexNode).getIndex(); + value = DrdsRexFolder.fold(rightRexNode, plannerContext); + } else if (rightRexNode instanceof RexInputRef && !(leftRexNode instanceof RexInputRef)) { + inputRef = ((RexInputRef) rightRexNode).getIndex(); + value = DrdsRexFolder.fold(leftRexNode, plannerContext); + } + ColumnMeta columnMeta = findColumnMeta(tableMeta, inputRef); + if (columnMeta != null && value != null) { + return UpperSelectivity.FREE; + } + return UpperSelectivity.UNKNOWN; + } + + /** + * check whether the predicate is 'a not in (?)' + * + * @param pred the predicate tested + */ + private UpperSelectivity freeVarNotIn(RexCall pred) { + if (pred.getOperands().size() != 2) { + return UpperSelectivity.UNKNOWN; + } + RexNode leftRexNode = pred.getOperands().get(0); + RexNode rightRexNode = pred.getOperands().get(1); + if (leftRexNode instanceof RexInputRef && rightRexNode instanceof RexCall && rightRexNode + .isA(SqlKind.ROW)) { + int leftIndex = ((RexInputRef) leftRexNode).getIndex(); + ColumnMeta columnMeta = findColumnMeta(tableMeta, leftIndex); + if (columnMeta != null) { + for (RexNode rexNode : ((RexCall) rightRexNode).operands) { + if (DrdsRexFolder.fold(rexNode, plannerContext) == null) { + return UpperSelectivity.UNKNOWN; + } + } + return UpperSelectivity.FREE; + } + } + return UpperSelectivity.UNKNOWN; + } + + /** + * check whether the predicate is 'a op ?,?' + * + * @param pred the predicate tested + */ + private UpperSelectivity freeVarOpTwoConst(RexCall pred) { + if (pred.getOperands().size() != 3) { + return UpperSelectivity.UNKNOWN; + } + RexNode leftRexNode = pred.getOperands().get(0); + RexNode midRexNode = pred.getOperands().get(1); + RexNode rightRexNode = pred.getOperands().get(2); + if (leftRexNode instanceof RexInputRef + && !(midRexNode instanceof RexInputRef) + && !(rightRexNode instanceof RexCall)) { + int leftIndex = ((RexInputRef) leftRexNode).getIndex(); + ColumnMeta columnMeta = findColumnMeta(tableMeta, leftIndex); + if (columnMeta != null) { + if (DrdsRexFolder.fold(midRexNode, plannerContext) != null + && DrdsRexFolder.fold(rightRexNode, plannerContext) != null) { + return UpperSelectivity.FREE; + } + } + } + return UpperSelectivity.UNKNOWN; + } + + /** + * check whether the predicate is 'a op ?' + * + * @param pred the predicate tested + */ + private UpperSelectivity freeVarOpOneConst(RexCall pred) { + if (pred.getOperands().size() != 2) { + return UpperSelectivity.UNKNOWN; + } + RexNode leftRexNode = pred.getOperands().get(0); + RexNode rightRexNode = pred.getOperands().get(1); + if (leftRexNode instanceof RexInputRef && !(rightRexNode instanceof RexInputRef)) { + int inputRef = ((RexInputRef) leftRexNode).getIndex(); + ColumnMeta columnMeta = findColumnMeta(tableMeta, inputRef); + if (columnMeta != null) { + if (DrdsRexFolder.fold(rightRexNode, plannerContext) != null) { + return UpperSelectivity.FREE; + } + } + } + return UpperSelectivity.UNKNOWN; + } + + /** + * check whether the predicate is 'a eq ?' or '? eq a' + * + * @param pred the predicate tested + */ + private UpperSelectivity boundVarEqOneConstOrOneConstEqOp(RexCall pred) { + if (pred.getOperands().size() != 2) { + return UpperSelectivity.UNKNOWN; + } + RexNode leftRexNode = pred.getOperands().get(0); + RexNode rightRexNode = pred.getOperands().get(1); + int inputRef = -1; + Object value = null; + + if (leftRexNode instanceof RexInputRef && !(rightRexNode instanceof RexInputRef)) { + inputRef = ((RexInputRef) leftRexNode).getIndex(); + value = DrdsRexFolder.fold(rightRexNode, plannerContext); + } else if (rightRexNode instanceof RexInputRef && !(leftRexNode instanceof RexInputRef)) { + inputRef = ((RexInputRef) rightRexNode).getIndex(); + value = DrdsRexFolder.fold(leftRexNode, plannerContext); + } + ColumnMeta columnMeta = findColumnMeta(tableMeta, inputRef); + if (columnMeta != null && value != null) { + // pk or uk + if (pkukEqualPredicate(Sets.newHashSet(inputRef))) { + return UpperSelectivity.createBound(1 / tableRowCount, inputRef); + } + StatisticResult statisticResult = + StatisticManager.getInstance().getFrequencyUpperLimit(tableMeta.getSchemaName(), + tableMeta.getTableName(), columnMeta.getName(), false); + long count = statisticResult.getLongValue(); + if (count >= 0) { + return UpperSelectivity.createBound(count / tableRowCount, inputRef); + } + } + return UpperSelectivity.UNKNOWN; + } + + /** + * check whether the predicate is 'a is null' + * + * @param pred the predicate tested + */ + private UpperSelectivity boundVarNull(RexCall pred) { + if (pred.getOperands().size() != 1) { + return UpperSelectivity.UNKNOWN; + } + RexNode leftRexNode = pred.getOperands().get(0); + if (leftRexNode instanceof RexInputRef) { + int inputRef = ((RexInputRef) leftRexNode).getIndex(); + ColumnMeta columnMeta = findColumnMeta(tableMeta, inputRef); + if (columnMeta != null) { + StatisticResult statisticResult = + StatisticManager.getInstance().getNullCount(tableMeta.getSchemaName(), + tableMeta.getTableName(), columnMeta.getName(), false); + long count = statisticResult.getLongValue(); + if (count >= 0) { + return UpperSelectivity.createBound(count / tableRowCount, inputRef); + } + } + } + return UpperSelectivity.UNKNOWN; + } + + /** + * check whether the predicate is 'a is not null' + * + * @param pred the predicate tested + */ + private UpperSelectivity boundVarNotNull(RexCall pred) { + if (pred.getOperands().size() != 1) { + return UpperSelectivity.UNKNOWN; + } + RexNode leftRexNode = pred.getOperands().get(0); + if (leftRexNode instanceof RexInputRef) { + int inputRef = ((RexInputRef) leftRexNode).getIndex(); + ColumnMeta columnMeta = findColumnMeta(tableMeta, inputRef); + if (columnMeta != null) { + StatisticResult statisticResult = + StatisticManager.getInstance().getNullCount(tableMeta.getSchemaName(), + tableMeta.getTableName(), columnMeta.getName(), false); + long count = statisticResult.getLongValue(); + if (count >= 0) { + return UpperSelectivity.createBound(1 - (count / tableRowCount), inputRef); + } + } + } + return UpperSelectivity.UNKNOWN; + } + + /** + * check whether the predicate is 'a in (?)' + * + * @param pred the predicate tested + */ + private UpperSelectivity boundVarIn(RexCall pred) { + if (pred.getOperands().size() != 2) { + return UpperSelectivity.UNKNOWN; + } + RexNode leftRexNode = pred.getOperands().get(0); + RexNode rightRexNode = pred.getOperands().get(1); + if (leftRexNode instanceof RexInputRef && rightRexNode instanceof RexCall && rightRexNode + .isA(SqlKind.ROW)) { + int leftIndex = ((RexInputRef) leftRexNode).getIndex(); + ColumnMeta columnMeta = findColumnMeta(tableMeta, leftIndex); + if (columnMeta == null) { + return UpperSelectivity.UNKNOWN; + } + // non-constant + if (DrdsRexFolder.fold(rightRexNode, plannerContext) == null) { + return UpperSelectivity.UNKNOWN; + } + + long inSize = -1; + // to judge between Rawstring and none-Rawstring + RexCall inValues = ((RexCall) rightRexNode); + if (inValues.getOperands().size() != 1) { + // in (?,?), can't be RawString + // pk or uk + if (pkukEqualPredicate(Sets.newHashSet(leftIndex))) { + inSize = inValues.getOperands().size(); + } else { + StatisticResult statisticResult = + StatisticManager.getInstance().getFrequencyUpperLimit(tableMeta.getSchemaName(), + tableMeta.getTableName(), columnMeta.getName(), plannerContext.isNeedStatisticTrace()); + long count = statisticResult.getLongValue(); + if (count >= 0) { + inSize = count * inValues.getOperands().size(); + } + } + } else { + // pk or uk + if (pkukEqualPredicate(Sets.newHashSet(leftIndex))) { + inSize = DEFAULT_IN_VALUES; + } else { + // in (?) or in (RAW(?)) + StatisticResult statisticResult = + StatisticManager.getInstance().getFrequencyUpperLimit(tableMeta.getSchemaName(), + tableMeta.getTableName(), columnMeta.getName(), plannerContext.isNeedStatisticTrace()); + long count = statisticResult.getLongValue(); + if (count >= 0) { + inSize = count; + if (inValues.getOperands().get(0) instanceof RexDynamicParam) { + int index = ((RexDynamicParam) inValues.getOperands().get(0)).getIndex(); + // valid index + if (index >= 0) { + ParameterContext parameterContext = + plannerContext.getParams().getCurrentParameter().get(index + 1); + if (parameterContext.getValue() instanceof RawString) { + inSize *= DEFAULT_IN_VALUES; + } + } + } + } + } + } + if (inSize >= 0) { + return UpperSelectivity.createBound(inSize / tableRowCount, leftIndex); + } + + } + + return UpperSelectivity.UNKNOWN; + } + + private boolean pkukEqualPredicate(Set columnIndexes) { + // try pk + if (tableMeta.isHasPrimaryKey()) { + if (indexAppearEqualPredicate(tableMeta.getPrimaryIndex(), columnIndexes)) { + return true; + } + } + + // try uk + for (IndexMeta indexMeta : tableMeta.getSecondaryIndexes()) { + if (indexMeta.isUniqueIndex()) { + if (indexAppearEqualPredicate(indexMeta, columnIndexes)) { + return true; + } + } + } + return false; + } + + /** + * @param indexMeta index meta data + * @param columnIndexes columns in predicate + * @return true if indexMeta in EqualPredicate, otherwise false + */ + private boolean indexAppearEqualPredicate(IndexMeta indexMeta, Set columnIndexes) { + for (ColumnMeta columnMeta : indexMeta.getKeyColumns()) { + if (!columnIndexes.contains(DrdsRelMdSelectivity.getColumnIndex(tableMeta, columnMeta))) { + return false; + } + } + return true; + } + + private ColumnMeta findColumnMeta(TableMeta tableMeta, int index) { + if (index < 0 || index > tableMeta.getAllColumns().size()) { + return null; + } + return tableMeta.getAllColumns().get(index); + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/selectivity/UpperSelectivity.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/selectivity/UpperSelectivity.java new file mode 100644 index 000000000..63b56eaa9 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/selectivity/UpperSelectivity.java @@ -0,0 +1,127 @@ +package com.alibaba.polardbx.optimizer.selectivity; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import org.apache.commons.collections.CollectionUtils; + +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +public class UpperSelectivity { + + private enum SelectivityKind { + FREE, BOUND, UNKNOWN + } + + final SelectivityKind kind; + final double selectivity; + final int idx; + + private UpperSelectivity(SelectivityKind kind, double selectivity) { + this.kind = kind; + this.selectivity = selectivity; + this.idx = -1; + } + + private UpperSelectivity(SelectivityKind kind, double selectivity, int idx) { + this.kind = kind; + this.selectivity = selectivity; + this.idx = idx; + } + + public double getSelectivity() { + return selectivity; + } + + public int getIdx() { + return idx; + } + + public static final UpperSelectivity FREE = new UpperSelectivity(SelectivityKind.FREE, 1D); + + public static final UpperSelectivity UNKNOWN = new UpperSelectivity(SelectivityKind.UNKNOWN, 0D); + + public static UpperSelectivity createBound(double selectivity) { + if (selectivity < 0) { + selectivity = 0D; + } + if (selectivity > 1) { + selectivity = 1D; + } + return new UpperSelectivity(SelectivityKind.BOUND, selectivity); + } + + public static UpperSelectivity createBound(double selectivity, int idx) { + if (selectivity < 0) { + selectivity = 0D; + } + if (selectivity > 1) { + selectivity = 1D; + } + return new UpperSelectivity(SelectivityKind.BOUND, selectivity, idx); + } + + public static UpperSelectivity not(UpperSelectivity pred) { + if (pred == UNKNOWN) { + return pred; + } + if (pred == FREE) { + return pred; + } + return FREE; + } + + public static UpperSelectivity or(Collection disconj) { + if (CollectionUtils.isEmpty(disconj)) { + return createBound(1D); + } + Map> map = classifyKind(disconj); + if (!CollectionUtils.isEmpty(map.get(SelectivityKind.FREE))) { + return FREE; + } + if (!CollectionUtils.isEmpty(map.get(SelectivityKind.BOUND))) { + double max = 0D; + for (UpperSelectivity sel : map.get(SelectivityKind.BOUND)) { + max += sel.selectivity; + } + return createBound(max); + } + return UNKNOWN; + } + + public static UpperSelectivity and(Collection conj) { + if (CollectionUtils.isEmpty(conj)) { + return createBound(1D); + } + Map> map = classifyKind(conj); + + if (!CollectionUtils.isEmpty(map.get(SelectivityKind.BOUND))) { + List upperSelectivities = map.get(SelectivityKind.BOUND); + upperSelectivities.sort(Comparator.comparingDouble(x -> x.selectivity)); + double result = 1; + for (int i = 0; i < Math.min(upperSelectivities.size(), 4); i++) { + result *= Math.pow(upperSelectivities.get(i).selectivity, 1D / Math.pow(2, i)); + } + return createBound(result); + } + if (CollectionUtils.isEmpty(map.get(SelectivityKind.FREE))) { + return UNKNOWN; + } + return FREE; + } + + public static Map> classifyKind(Collection conj) { + Map> map = + ImmutableMap.>builder() + .put(SelectivityKind.FREE, Lists.newArrayList()) + .put(SelectivityKind.BOUND, Lists.newArrayList()) + .put(SelectivityKind.UNKNOWN, Lists.newArrayList()) + .build(); + for (UpperSelectivity sel : conj) { + map.get(sel.kind).add(sel); + } + return map; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/label/JoinLabel.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/label/JoinLabel.java index 4cb3ee707..e33b3e281 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/label/JoinLabel.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/label/JoinLabel.java @@ -16,24 +16,32 @@ package com.alibaba.polardbx.optimizer.sharding.label; +import com.alibaba.polardbx.optimizer.core.rel.HashGroupJoin; +import com.alibaba.polardbx.optimizer.sharding.LabelShuttle; import com.alibaba.polardbx.optimizer.sharding.utils.ExtractorContext; +import com.alibaba.polardbx.optimizer.sharding.utils.PredicateUtil; import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; -import com.alibaba.polardbx.optimizer.core.rel.HashGroupJoin; -import com.alibaba.polardbx.optimizer.sharding.LabelShuttle; import org.apache.calcite.linq4j.Ord; +import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.AggregateCall; +import org.apache.calcite.rel.core.Filter; import org.apache.calcite.rel.core.Join; +import org.apache.calcite.rel.core.JoinRelType; +import org.apache.calcite.rel.core.SemiJoin; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.rel.type.RelDataTypeField; +import org.apache.calcite.rex.RexNode; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.mapping.Mapping; import javax.annotation.Nonnull; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -206,4 +214,46 @@ public PredicateNode getValuePredicates() { public void setValuePredicates(PredicateNode valuePredicates) { this.valuePredicates = valuePredicates; } + + @Override + public Label filter(RexNode predicate, Filter filter, + ExtractorContext context) { + + final Join join = this.getRel(); + + final List joinFilters = RelOptUtil.conjunctions(join.getCondition()); + final List originFilters = RelOptUtil.conjunctions(predicate); + final List aboveFilters = RelOptUtil.conjunctions(predicate); + final ImmutableList origAboveFilters = ImmutableList.copyOf(aboveFilters); + + JoinRelType joinType = join.getJoinType(); + if (!origAboveFilters.isEmpty() && joinType != JoinRelType.INNER && !(join instanceof SemiJoin)) { + joinType = RelOptUtil.simplifyJoin(join, origAboveFilters, joinType); + } + + final List leftFilters = new ArrayList<>(); + final List rightFilters = new ArrayList<>(); + final List pushFilters = new ArrayList<>(); + // Try to push down above filters. These are typically where clause + // filters. They can be pushed down if they are not on the NULL + // generating side. + if (RelOptUtil.classifyFilters(join, + aboveFilters, + joinType, + true, + !joinType.generatesNullsOnLeft(), + !joinType.generatesNullsOnRight(), + joinFilters, + leftFilters, + rightFilters)) { + for (RexNode rexNode : originFilters) { + if (!aboveFilters.contains(rexNode)) { + pushFilters.add(rexNode); + } + } + final Map deduplicatedFilters = PredicateUtil.deduplicate(pushFilters, context); + this.predicates.add(new PredicateNode(this.clone(), null, deduplicatedFilters, context)); + } + return this; + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/result/ExtractionResult.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/result/ExtractionResult.java index e19c6cd8e..026b55c63 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/result/ExtractionResult.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/result/ExtractionResult.java @@ -67,7 +67,11 @@ public ExtractionResult(ConditionExtractor extractor) { } public Map allPartPruneSteps(ExecutionContext ec) { - return allPartPruneSteps(ec, (t) -> conditionOf(t).intersect()); + return allPartPruneSteps(ec, (t) -> conditionOf(t).intersect(), null); + } + + public Map allPartPruneSteps(ExecutionContext ec, PartitionInfo cciPartInfo) { + return allPartPruneSteps(ec, (t) -> conditionOf(t).intersect(), cciPartInfo); } public Map allPartPruneStepsWithScalarFunctionReplaced(AtomicInteger maxParamIndex, @@ -76,7 +80,8 @@ public Map allPartPruneStepsWithScalarFunctionReplac ec, (t) -> conditionOf(t) .intersect() - .convertScalarFunction2RexCallParam(maxParamIndex, ec)); + .convertScalarFunction2RexCallParam(maxParamIndex, ec), + null); } /** @@ -87,7 +92,8 @@ public Map allPartPruneStepsWithScalarFunctionReplac * */ public Map allPartPruneSteps(ExecutionContext ec, - Function conditionBuilder) { + Function conditionBuilder, + PartitionInfo cciPartInfo) { Map allTblPruneStepInfo = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); for (RelOptTable t : getLogicalTables()) { @@ -100,13 +106,13 @@ public Map allPartPruneSteps(ExecutionContext ec, final String tableName = Util.last(qualifiedName); if (condRs instanceof NormalConditionResult) { NormalConditionResult normalCondRs = (NormalConditionResult) condRs; - PartitionPruneStep stepInfo = normalCondRs.toPartPruneStep(ec); + PartitionPruneStep stepInfo = normalCondRs.toPartPruneStep(ec, cciPartInfo); if (stepInfo != null) { allTblPruneStepInfo.put(tableName, stepInfo); } } else if (condRs instanceof EmptyConditionResult) { - PartitionInfo partInfo = - ec.getSchemaManager(schema).getTable(tableName).getPartitionInfo(); + PartitionInfo partInfo = cciPartInfo == null ? + ec.getSchemaManager(schema).getTable(tableName).getPartitionInfo() : cciPartInfo; allTblPruneStepInfo .put(tableName, PartitionPruner.generatePartitionPrueStepInfo(partInfo, null, null, ec)); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/result/NormalConditionResult.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/result/NormalConditionResult.java index 2cff9b99a..6bca9e2ef 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/result/NormalConditionResult.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/result/NormalConditionResult.java @@ -78,6 +78,10 @@ public List toRexNodes() { } public PartitionPruneStep toPartPruneStep(ExecutionContext ec) { + return toPartPruneStep(ec, null); + } + + public PartitionPruneStep toPartPruneStep(ExecutionContext ec, PartitionInfo cciPartInfo) { PartitionPruneStep pruneStepInfo = null; if (null == label || GeneralUtil.isEmpty(predicates)) { @@ -93,8 +97,8 @@ public PartitionPruneStep toPartPruneStep(ExecutionContext ec) { final List sorted = PredicateUtil.sortPredicates(predicates); final RexNode comparison = RexUtil.composeConjunction(builder, sorted, true); if (null != comparison) { - PartitionInfo partInfo = - ec.getSchemaManager(schema).getTable(tableName).getPartitionInfo(); + PartitionInfo partInfo = cciPartInfo == null ? + ec.getSchemaManager(schema).getTable(tableName).getPartitionInfo() : cciPartInfo; if (partInfo == null) { return null; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/utils/PredicateUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/utils/PredicateUtil.java index 3571d088d..6111f6e70 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/utils/PredicateUtil.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sharding/utils/PredicateUtil.java @@ -378,7 +378,7 @@ public static Map convertEqualityGroupToRex(List groups */ public static void mergePushdownPredicates(JoinLabel joinLabel, List leftPreds, List rightPreds) { final Join join = joinLabel.getRel(); - final JoinRelType joinType = join.getJoinType(); + JoinRelType joinType = join.getJoinType(); // Predicates belongs or push down to this label final Map top = Optional.ofNullable(joinLabel.getPushdown()) @@ -391,8 +391,18 @@ public static void mergePushdownPredicates(JoinLabel joinLabel, List le // Check null accept predicates final List topPredicates = pushThroughJoin(top.values(), join, new ArrayList<>()); + if (!topPredicates.isEmpty() && joinType != JoinRelType.INNER && !(join instanceof SemiJoin)) { + ImmutableList topPredicatesList = ImmutableList.copyOf(topPredicates); + joinType = RelOptUtil.simplifyJoin(join, topPredicatesList, joinType); + } + // Split top predicates to left and right - RelOptUtil.classifyFilters(join, topPredicates, joinType, false, true, true, null, leftPreds, rightPreds); + RelOptUtil.classifyFilters( + join, topPredicates, joinType, + false, + true, + true, + null, leftPreds, rightPreds); // Predicates pulled up from input labels if (null != leftPreds) { @@ -421,7 +431,7 @@ public static void mergePushdownPredicates(JoinLabel joinLabel, List le */ public static void mergePullUpPredicates(JoinLabel joinLabel, List leftPreds, List rightPreds) { final Join join = joinLabel.getRel(); - final JoinRelType joinType = join.getJoinType(); + JoinRelType joinType = join.getJoinType(); // Predicates belongs to this label final Map topPredicates = pushDown(joinLabel.getPredicates()); @@ -431,6 +441,11 @@ public static void mergePullUpPredicates(JoinLabel joinLabel, List left topPredicates.putAll(joinLabel.getValuePredicates().getDigests()); } + if (!topPredicates.isEmpty() && joinType != JoinRelType.INNER && !(join instanceof SemiJoin)) { + ImmutableList topPredicatesList = ImmutableList.copyOf(topPredicates.values()); + joinType = RelOptUtil.simplifyJoin(join, topPredicatesList, joinType); + } + // Split predicates to left and right RelOptUtil.classifyFilters(join, new ArrayList<>(topPredicates.values()), diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/spill/SpillSpaceManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/spill/SpillSpaceManager.java index 1cf463418..c46898b85 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/spill/SpillSpaceManager.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/spill/SpillSpaceManager.java @@ -39,7 +39,7 @@ public static final SpillSpaceMonitor getInstance() { private static final SpillSpaceMonitor INSTANCE = new SpillSpaceManager(); - private SpillSpaceManager() { + protected SpillSpaceManager() { this.isSpillManager = true; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/spill/SpillSpaceMonitor.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/spill/SpillSpaceMonitor.java index e17427d06..acce58553 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/spill/SpillSpaceMonitor.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/spill/SpillSpaceMonitor.java @@ -46,7 +46,7 @@ public synchronized void updateBytes(long bytes) { } currentBytes += bytes; } else { - currentBytes -= bytes; + currentBytes += bytes; } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sql/sql2rel/TddlSqlToRelConverter.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sql/sql2rel/TddlSqlToRelConverter.java index a6645cfbb..2f51316c9 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sql/sql2rel/TddlSqlToRelConverter.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/sql/sql2rel/TddlSqlToRelConverter.java @@ -77,6 +77,7 @@ import org.apache.calcite.rel.core.Sort; import org.apache.calcite.rel.core.TableModify; import org.apache.calcite.rel.core.TableModify.TableInfo; +import org.apache.calcite.rel.logical.LogicalAggregate; import org.apache.calcite.rel.logical.LogicalProject; import org.apache.calcite.rel.logical.LogicalTableScan; import org.apache.calcite.rel.metadata.RelColumnOrigin; @@ -88,6 +89,7 @@ import org.apache.calcite.rex.RexLiteral; import org.apache.calcite.rex.RexNode; import org.apache.calcite.rex.RexPermuteInputsShuttle; +import org.apache.calcite.runtime.CalciteContextException; import org.apache.calcite.sql.SqlAddForeignKey; import org.apache.calcite.sql.SqlAddFullTextIndex; import org.apache.calcite.sql.SqlAddIndex; @@ -993,6 +995,12 @@ public ReplaceDefaultShuttle(List targetFields, List t this.ec = ec; } + @Override + public RelNode visit(LogicalAggregate aggregate) { + //agg无需替换default值,agg.getChildExps返回的列不一定对齐列表达式 + return aggregate; + } + @Override public RelNode visit(LogicalProject project) { LogicalProject visited; @@ -1261,13 +1269,15 @@ private String assignGsiName(SqlNode queryName, Set existsNames, String existsNames.add(preferName); // Assign new name with suffix. final Random random = new Random(); - final Formatter formatter = new Formatter(); String fullName; + SchemaManager schemaManager = + plannerContext.getExecutionContext().getSchemaManager(plannerContext.getSchemaName()); do { + Formatter formatter = new Formatter(); final String suffix = "_$" + formatter.format("%04x", random.nextInt(0x10000)); fullName = preferName + suffix; - } while (!plannerContext.getExecutionContext().getSchemaManager(plannerContext.getSchemaName()) - .getGsi(fullName, IndexStatus.ALL).isEmpty()); + } while (!schemaManager.getGsi(fullName, IndexStatus.ALL).isEmpty() || + schemaManager.cciExists(fullName, isColumnar)); return fullName; } @@ -1945,7 +1955,11 @@ protected SqlAlterTable checkAndRewriteGsiName(SqlAlterTable query) { } if (query.getAlters().size() != 1) { - throw new NotSupportException("Multi alter specifications when create GSI"); + if (query.createCci()) { + throw new NotSupportException("Multi alter specifications when create CCI"); + } else { + throw new NotSupportException("Multi alter specifications when create GSI"); + } } if (query.getAlters().size() > 0 && query.getTableOptions() != null) { @@ -1966,7 +1980,11 @@ protected SqlAlterTable checkAndRewriteGsiName(SqlAlterTable query) { if (wrapped != null) { // Drop GSI. if (query.getAlters().size() != 1) { - throw new NotSupportException("Multi alter specifications when drop GSI"); + if (tableMeta.hasCci(indexName)) { + throw new NotSupportException("Multi alter specifications when drop CCI"); + } else { + throw new NotSupportException("Multi alter specifications when drop GSI"); + } } check = true; } @@ -1983,7 +2001,11 @@ protected SqlAlterTable checkAndRewriteGsiName(SqlAlterTable query) { final String wrapped = getWrappedIndexName(tableMeta, indexName); if (wrapped != null) { if (query.getAlters().size() != 1) { - throw new NotSupportException("Multi alter specifications when rename GSI"); + if (tableMeta.hasCci(indexName)) { + throw new NotSupportException("Multi alter specifications when rename CCI"); + } else { + throw new NotSupportException("Multi alter specifications when rename GSI"); + } } check = true; } @@ -2396,14 +2418,12 @@ protected RelNode transformUpdateSourceRel(RelNode old, TableInfo tableInfo, Lis final boolean modifyPartitionKey = CheckModifyLimitation.checkModifyShardingColumnWithGsi(targetTables, targetColumns, this.plannerContext.getExecutionContext()); - final boolean modifyColumn = CheckModifyLimitation.checkOnlineModifyColumnDdl(targetTables, - this.plannerContext.getExecutionContext()); final boolean hasGeneratedColumn = CheckModifyLimitation.checkHasLogicalGeneratedColumns(targetTables, this.plannerContext.getExecutionContext()); final ExecutionStrategy hintEx = getExecutionStrategy(); - if (!modifyPartitionKey && !modifyBroadcast && !modifyGsi && !scaleOutIsRunning && !modifyColumn + if (!modifyPartitionKey && !modifyBroadcast && !modifyGsi && !scaleOutIsRunning && hintEx != ExecutionStrategy.LOGICAL && !hasGeneratedColumn) { outTargetColumns.addAll(targetColumns); outTargetTables.addAll(targetTableIndexes); @@ -2740,5 +2760,24 @@ public void addDefaultExpr(boolean withGsi, boolean isBroadcast, boolean withSca } } } + + protected void checkSubqueryInSetClause(SqlUpdate call) { + final ExecutionContext ec = plannerContext.getExecutionContext(); + + final boolean forbidModifyWithSubqueryInSet = + ec.getParamManager().getBoolean(ConnectionParams.DML_FORBID_UPDATE_WITH_SUBQUERY_IN_SET); + + if (call.getSourceExpressionList() != null) { + for (SqlNode node : call.getSourceExpressionList()) { + if (node instanceof SqlSelect) { // Don't allow sub-query in update set clause. + if (forbidModifyWithSubqueryInSet) { + final CalciteContextException ex = + validator.newValidationError(node, RESOURCE.updateNotSupport(node.toString())); + throw new TddlRuntimeException(ErrorCode.ERR_VALIDATE, ex, ex.getMessage()); + } + } + } + } + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/statis/ColumnarPruneRecord.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/statis/ColumnarPruneRecord.java index 23a56071f..b173ecac4 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/statis/ColumnarPruneRecord.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/statis/ColumnarPruneRecord.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -27,8 +26,8 @@ * @author fangwu */ public class ColumnarPruneRecord { - private String tableName; - private String filter; + public String tableName; + public String filter; public AtomicLong initIndexTime = new AtomicLong(); public AtomicLong indexPruneTime = new AtomicLong(); public AtomicInteger fileNum = new AtomicInteger(); @@ -47,22 +46,6 @@ public ColumnarPruneRecord( this.filter = filter; } - public String getTableName() { - return tableName; - } - - public void setTableName(String tableName) { - this.tableName = tableName; - } - - public String getFilter() { - return filter; - } - - public void setFilter(String filter) { - this.filter = filter; - } - @JsonCreator public ColumnarPruneRecord(@JsonProperty("tableName") String tableName, @JsonProperty("filter") String filter, @@ -89,4 +72,135 @@ public ColumnarPruneRecord(@JsonProperty("tableName") String tableName, this.bitMapPruneNum = bitMapPruneNum; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ColumnarPruneRecord)) { + return false; + } + ColumnarPruneRecord that = (ColumnarPruneRecord) o; + return this.tableName.equals(that.tableName) && + this.filter.equals(that.filter) && + this.initIndexTime.get() == that.initIndexTime.get() && + this.indexPruneTime.get() == that.indexPruneTime.get() && + this.fileNum.get() == that.fileNum.get() && + this.stripeNum.get() == that.stripeNum.get() && + this.rgNum.get() == that.rgNum.get() && + this.rgLeftNum.get() == that.rgLeftNum.get() && + this.sortKeyPruneNum.get() == that.sortKeyPruneNum.get() && + this.zoneMapPruneNum.get() == that.zoneMapPruneNum.get() && + this.bitMapPruneNum.get() == that.bitMapPruneNum.get(); + } + + @JsonProperty + public String getTableName() { + return tableName; + } + + @JsonProperty + public void setTableName(String tableName) { + this.tableName = tableName; + } + + @JsonProperty + public String getFilter() { + return filter; + } + + @JsonProperty + public void setFilter(String filter) { + this.filter = filter; + } + + @JsonProperty + public AtomicLong getInitIndexTime() { + return initIndexTime; + } + + @JsonProperty + public void setInitIndexTime(AtomicLong initIndexTime) { + this.initIndexTime = initIndexTime; + } + + @JsonProperty + public AtomicLong getIndexPruneTime() { + return indexPruneTime; + } + + @JsonProperty + public void setIndexPruneTime(AtomicLong indexPruneTime) { + this.indexPruneTime = indexPruneTime; + } + + @JsonProperty + public AtomicInteger getFileNum() { + return fileNum; + } + + @JsonProperty + public void setFileNum(AtomicInteger fileNum) { + this.fileNum = fileNum; + } + + @JsonProperty + public AtomicInteger getStripeNum() { + return stripeNum; + } + + @JsonProperty + public void setStripeNum(AtomicInteger stripeNum) { + this.stripeNum = stripeNum; + } + + @JsonProperty + public AtomicInteger getRgNum() { + return rgNum; + } + + @JsonProperty + public void setRgNum(AtomicInteger rgNum) { + this.rgNum = rgNum; + } + + @JsonProperty + public AtomicInteger getRgLeftNum() { + return rgLeftNum; + } + + @JsonProperty + public void setRgLeftNum(AtomicInteger rgLeftNum) { + this.rgLeftNum = rgLeftNum; + } + + @JsonProperty + public AtomicInteger getSortKeyPruneNum() { + return sortKeyPruneNum; + } + + @JsonProperty + public void setSortKeyPruneNum(AtomicInteger sortKeyPruneNum) { + this.sortKeyPruneNum = sortKeyPruneNum; + } + + @JsonProperty + public AtomicInteger getZoneMapPruneNum() { + return zoneMapPruneNum; + } + + @JsonProperty + public void setZoneMapPruneNum(AtomicInteger zoneMapPruneNum) { + this.zoneMapPruneNum = zoneMapPruneNum; + } + + @JsonProperty + public AtomicInteger getBitMapPruneNum() { + return bitMapPruneNum; + } + + @JsonProperty + public void setBitMapPruneNum(AtomicInteger bitMapPruneNum) { + this.bitMapPruneNum = bitMapPruneNum; + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/statis/ColumnarTracer.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/statis/ColumnarTracer.java index 4a6d67384..c1d6942d5 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/statis/ColumnarTracer.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/statis/ColumnarTracer.java @@ -18,29 +18,40 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.common.collect.Maps; import java.util.Collection; -import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * @author fangwu */ public class ColumnarTracer { - private Map pruneRecordMap = Maps.newConcurrentMap(); + /** + * note: we need to specify the map type here, because Map pruneRecordMap = + * Maps.newConcurrentMap(); will be incorrectly parsed to LinkedHashMap in jackson + */ + private ConcurrentHashMap pruneRecordMap = new ConcurrentHashMap<>(); + private String instanceId = "default"; + //only for test public ColumnarTracer() { + } + public ColumnarTracer(String instanceId) { + this.instanceId = instanceId; } @JsonCreator - public ColumnarTracer(@JsonProperty("pruneRecordMap") Map pruneRecordMap) { + public ColumnarTracer( + @JsonProperty("pruneRecordMap") ConcurrentHashMap pruneRecordMap, + @JsonProperty("instanceId") String instanceId) { + this.instanceId = instanceId; this.pruneRecordMap = pruneRecordMap; } public void tracePruneInit(String table, String filter, long initTime) { - pruneRecordMap.compute(table + "_" + filter, + pruneRecordMap.compute(getTracerKey(table, filter), (s, columnarPruneRecord) -> { if (columnarPruneRecord == null) { columnarPruneRecord = new ColumnarPruneRecord(table, filter); @@ -52,7 +63,7 @@ public void tracePruneInit(String table, String filter, long initTime) { } public void tracePruneTime(String table, String filter, long pruneTime) { - pruneRecordMap.compute(table + "_" + filter, + pruneRecordMap.compute(getTracerKey(table, filter), (s, columnarPruneRecord) -> { if (columnarPruneRecord == null) { columnarPruneRecord = new ColumnarPruneRecord(table, filter); @@ -64,7 +75,7 @@ public void tracePruneTime(String table, String filter, long pruneTime) { } public void tracePruneResult(String table, String filter, int fileNum, int stripeNum, int rgNum, int rgLeftNum) { - pruneRecordMap.compute(table + "_" + filter, + pruneRecordMap.compute(getTracerKey(table, filter), (s, columnarPruneRecord) -> { if (columnarPruneRecord == null) { columnarPruneRecord = new ColumnarPruneRecord(table, filter); @@ -79,7 +90,7 @@ public void tracePruneResult(String table, String filter, int fileNum, int strip public void tracePruneIndex(String table, String filter, int sortKeyPruneNum, int zoneMapPruneNum, int bitMapPruneNum) { - pruneRecordMap.compute(table + "_" + filter, + pruneRecordMap.compute(getTracerKey(table, filter), (s, columnarPruneRecord) -> { if (columnarPruneRecord == null) { columnarPruneRecord = new ColumnarPruneRecord(table, filter); @@ -91,18 +102,59 @@ public void tracePruneIndex(String table, String filter, int sortKeyPruneNum, in }); } + //merge slave instance ColumnarTracer to master instance + public void mergeColumnarTracer(ColumnarTracer right) { + if (right == null || right.getPruneRecordMap() == null) { + return; + } + + right.getPruneRecordMap().forEach((key, rightRecord) -> { + pruneRecordMap.merge(key, rightRecord, (leftRecord, newRecord) -> { + if (leftRecord == null) { + return newRecord; + } + + leftRecord.initIndexTime.addAndGet(newRecord.initIndexTime.get()); + leftRecord.indexPruneTime.addAndGet(newRecord.indexPruneTime.get()); + leftRecord.fileNum.addAndGet(newRecord.fileNum.get()); + leftRecord.stripeNum.addAndGet(newRecord.stripeNum.get()); + leftRecord.rgNum.addAndGet(newRecord.rgNum.get()); + leftRecord.rgLeftNum.addAndGet(newRecord.rgLeftNum.get()); + leftRecord.sortKeyPruneNum.addAndGet(newRecord.sortKeyPruneNum.get()); + leftRecord.zoneMapPruneNum.addAndGet(newRecord.zoneMapPruneNum.get()); + leftRecord.bitMapPruneNum.addAndGet(newRecord.bitMapPruneNum.get()); + + return leftRecord; + }); + }); + } + + public String getTracerKey(String tableName, String filter) { + return instanceId + "_" + tableName + "_" + filter; + } + public Collection pruneRecords() { return this.pruneRecordMap.values(); } @JsonProperty - public Map getPruneRecordMap() { + public ConcurrentHashMap getPruneRecordMap() { return pruneRecordMap; } @JsonProperty public void setPruneRecordMap( - Map pruneRecordMap) { + ConcurrentHashMap pruneRecordMap) { this.pruneRecordMap = pruneRecordMap; } + + @JsonProperty + public String getInstanceId() { + return instanceId; + } + + @JsonProperty + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/AlterTableGroupSnapShotUtils.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/AlterTableGroupSnapShotUtils.java index e651b9b3f..06f1aa158 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/AlterTableGroupSnapShotUtils.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/AlterTableGroupSnapShotUtils.java @@ -35,8 +35,10 @@ import com.alibaba.polardbx.optimizer.core.datatype.DataType; import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableDropPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupAddPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupBasePreparedData; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupDropPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupExtractPartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupMergePartitionPreparedData; import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTableGroupModifyPartitionPreparedData; @@ -73,13 +75,11 @@ import org.apache.calcite.sql.SqlAlterTableAddPartition; import org.apache.calcite.sql.SqlAlterTableDropPartition; import org.apache.calcite.sql.SqlAlterTableExtractPartition; -import org.apache.calcite.sql.SqlAlterTableGroup; -import org.apache.calcite.sql.SqlAlterTableGroupMergePartition; -import org.apache.calcite.sql.SqlAlterTableGroupMovePartition; import org.apache.calcite.sql.SqlAlterTableGroupSplitPartition; import org.apache.calcite.sql.SqlAlterTableMergePartition; import org.apache.calcite.sql.SqlAlterTableModifyPartitionValues; import org.apache.calcite.sql.SqlAlterTableMovePartition; +import org.apache.calcite.sql.SqlAlterTableOptimizePartition; import org.apache.calcite.sql.SqlAlterTableRenamePartition; import org.apache.calcite.sql.SqlAlterTableReorgPartition; import org.apache.calcite.sql.SqlAlterTableSetTableGroup; @@ -111,8 +111,6 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; -import static com.alibaba.polardbx.gms.partition.TablePartitionRecord.PARTITION_LEVEL_PARTITION; - /** * Created by luoyanxin. * @@ -343,6 +341,9 @@ private static PartitionSpec generateNewPartitionSpec(PartitionInfo curPartition partSpecAstParams.setPhySpecCounter(phyPartCounter); partSpecAstParams.setAutoBuildPart(isAutoSubPart); partSpecAstParams.setPartBoundValBuilder(boundValBuilder); + partSpecAstParams.setPartEngine(curPartitionInfo.isColumnar() ? + TablePartitionRecord.PARTITION_ENGINE_COLUMNAR : + TablePartitionRecord.PARTITION_ENGINE_INNODB); PartitionSpec subPartSpec = PartitionInfoBuilder.buildPartSpecByAstParams(partSpecAstParams); subPartSpec.setLocation(new PartitionLocation()); @@ -644,6 +645,9 @@ private static void generateNewPartitionsForSplitWithPartitionSpec( partSpecAstParams.setPartComment(sqlPartition.getComment()); partSpecAstParams.setPartLocality(sqlPartition.getLocality()); partSpecAstParams.setPartBndValuesAst(sqlPartition.getValues()); + partSpecAstParams.setPartEngine(curPartitionInfo.isColumnar() ? + TablePartitionRecord.PARTITION_ENGINE_COLUMNAR : + TablePartitionRecord.PARTITION_ENGINE_INNODB); partSpecAstParams.setLogical(false); @@ -1288,6 +1292,7 @@ private static PartitionInfo getNewPartitionInfoForReorgType( physicalPartIndex, isReorgSubPartition, isAlterTableGroup, + curPartitionInfo.isColumnar(), executionContext ); } else { @@ -1312,6 +1317,7 @@ private static PartitionInfo getNewPartitionInfoForReorgType( physicalPartIndex, isReorgSubPartition, isAlterTableGroup, + curPartitionInfo.isColumnar(), executionContext ); } else { @@ -1341,6 +1347,7 @@ private static void genNewPartSpecsForReorg(PartitionInfo curPartitionInfo, AtomicLong physicalPartIndex, boolean isReorgSubPartition, boolean isAlterTableGroup, + boolean isColumnarIndex, ExecutionContext executionContext) { PartitionByDefinition partByDef = curPartitionInfo.getPartitionBy(); PartitionByDefinition subPartByDef = partByDef.getSubPartitionBy(); @@ -1403,6 +1410,9 @@ private static void genNewPartSpecsForReorg(PartitionInfo curPartitionInfo, partSpecAstParams.setPartComment(sqlPartition.getComment()); partSpecAstParams.setPartLocality(sqlPartition.getLocality()); partSpecAstParams.setPartBndValuesAst(sqlPartition.getValues()); + partSpecAstParams.setPartEngine(isColumnarIndex ? + TablePartitionRecord.PARTITION_ENGINE_COLUMNAR : + TablePartitionRecord.PARTITION_ENGINE_INNODB); partSpecAstParams.setLogical(false); @@ -1653,6 +1663,7 @@ private static PartitionInfo getNewPartitionInfoForAddPartition(PartitionInfo cu SqlAlterTableAddPartition addPartition, Map> physicalTableAndGroupPairs, Map> partBoundExprInfoByLevel, + boolean isColumnarIndex, ExecutionContext executionContext) { PartitionInfo newPartitionInfo = PartitionInfoBuilder.buildNewPartitionInfoByAddingPartition( executionContext, @@ -1661,7 +1672,8 @@ private static PartitionInfo getNewPartitionInfoForAddPartition(PartitionInfo cu addPartition, partBoundExprInfoByLevel, unVisiablePartitionGroupRecords, - physicalTableAndGroupPairs + physicalTableAndGroupPairs, + isColumnarIndex ); updatePartitionSpecRelationship(newPartitionInfo); @@ -1669,20 +1681,15 @@ private static PartitionInfo getNewPartitionInfoForAddPartition(PartitionInfo cu return newPartitionInfo; } + @Deprecated private static PartitionInfo getNewPartitionInfoForDropPartition(PartitionInfo curPartitionInfo, SqlAlterTableDropPartition dropPartition, List oldPartitionNames, - List newPartitionNames, - List invisiblePartitionGroupRecords, - Map> physicalTableAndGroupPairs, ExecutionContext context) { PartitionInfo newPartitionInfo = PartitionInfoBuilder.buildNewPartitionInfoByDroppingPartition( curPartitionInfo, dropPartition, oldPartitionNames, - newPartitionNames, - invisiblePartitionGroupRecords, - physicalTableAndGroupPairs, context ); @@ -2177,19 +2184,13 @@ public static PartitionInfo getNewPartitionInfo( addPartition, physicalTableAndGroupPairs, addPartitionPreparedData.getPartBoundExprInfoByLevel(), + curPartitionInfo.isColumnar(), executionContext ); } else if (sqlNode instanceof SqlAlterTableDropPartition) { - SqlAlterTableDropPartition dropPartition = (SqlAlterTableDropPartition) sqlNode; - newPartInfo = getNewPartitionInfoForDropPartition( - curPartitionInfo, - dropPartition, - oldPartitionNames, - newPartitionNames, - invisiblePartitionGroupRecords, - physicalTableAndGroupPairs, - executionContext - ); + newPartInfo = + generateNewPartitionInfoForDropPartition((AlterTableGroupDropPartitionPreparedData) parentPreparedData, + curPartitionInfo.getTableName()); } else if (sqlNode instanceof SqlAlterTableModifyPartitionValues) { AlterTableGroupModifyPartitionPreparedData modifyPartitionPreparedData = (AlterTableGroupModifyPartitionPreparedData) parentPreparedData; @@ -2234,6 +2235,56 @@ public static PartitionInfo getNewPartitionInfo( return newPartInfo; } + public static PartitionInfo generateNewPartitionInfoForDropPartition( + AlterTableGroupDropPartitionPreparedData parentPrepareData, + String tableName) { + PartitionInfo curPartitionInfo = + OptimizerContext.getContext(parentPrepareData.getSchemaName()).getPartitionInfoManager() + .getPartitionInfo(tableName); + List newPartitions = new ArrayList<>(); + if (parentPrepareData.isOperateOnSubPartition()) { + boolean isTempPart = curPartitionInfo.getPartitionBy().getSubPartitionBy().isUseSubPartTemplate(); + for (PartitionSpec partitionSpec : curPartitionInfo.getPartitionBy().getPartitions()) { + PartitionSpec newPartSpec = partitionSpec.copy(); + newPartitions.add(newPartSpec); + newPartSpec.getSubPartitions().clear(); + for (PartitionSpec subPartSpec : partitionSpec.getSubPartitions()) { + boolean del = false; + for (String oldPart : parentPrepareData.getOldPartitionNames()) { + if (isTempPart && subPartSpec.getTemplateName().equalsIgnoreCase(oldPart) + || !isTempPart && subPartSpec.getName().equalsIgnoreCase(oldPart)) { + del = true; + break; + } + } + if (!del) { + newPartSpec.getSubPartitions().add(subPartSpec.copy()); + } + } + } + } else { + for (PartitionSpec partitionSpec : curPartitionInfo.getPartitionBy().getPartitions()) { + boolean del = false; + for (String oldPart : parentPrepareData.getOldPartitionNames()) { + if (partitionSpec.getName().equalsIgnoreCase(oldPart)) { + del = true; + break; + } + } + if (!del) { + newPartitions.add(partitionSpec.copy()); + } + } + } + + PartitionInfo newPartitionInfo = curPartitionInfo.copy(); + newPartitionInfo.getPartitionBy().setPartitions(newPartitions); + updateSubPartitionTemplate(newPartitionInfo); + updatePartitionSpecRelationship(newPartitionInfo); + newPartitionInfo.getPartitionBy().getPhysicalPartitions().clear(); + return newPartitionInfo; + } + public static void updateTemplateSubPartitions(PartitionInfo newPartitionInfo) { PartitionByDefinition subPartitionByDefinition = newPartitionInfo.getPartitionBy().getSubPartitionBy(); boolean hasSubPartition = subPartitionByDefinition != null; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/AlterTablePartitionHelper.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/AlterTablePartitionHelper.java index 1fbfb9fdf..82690383e 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/AlterTablePartitionHelper.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/AlterTablePartitionHelper.java @@ -73,7 +73,7 @@ public static SqlNode fetchGsiFullTableNameAstForAlterIndexPartition(DDL alterTb if (tblMetaOfTblOfIdx != null) { SqlIdentifier alterIndexNameAst = (SqlIdentifier) alterIndexNameNode; TableMeta gsiFullTblMeta = - getGisTableMetaByPrimaryTblMetaAndIndexName(alterIndexNameAst, tblAstOfAlterIdx, + getGsiTableMetaByPrimaryTblMetaAndIndexName(alterIndexNameAst, tblAstOfAlterIdx, tblMetaOfTblOfIdx); if (gsiFullTblMeta != null) { String gsiDbName = gsiFullTblMeta.getSchemaName(); @@ -124,7 +124,7 @@ public static String fetchTableGroupNameByTableName(DDL alterTgDdl) { List fullTblNamesIdOfIndex = tblIdOfIndex.names; TableMeta tblMetaOfIndex = getTableMetaByFullTblName(fullTblNamesIdOfIndex); TableMeta gsiFullTblMeta = - getGisTableMetaByPrimaryTblMetaAndIndexName(tblId, tblIdOfIndex, tblMetaOfIndex); + getGsiTableMetaByPrimaryTblMetaAndIndexName(tblId, tblIdOfIndex, tblMetaOfIndex); targetTblMeta = gsiFullTblMeta; } else { List fullTblNames = tblId.names; @@ -143,31 +143,38 @@ public static String fetchTableGroupNameByTableName(DDL alterTgDdl) { return targetTgName; } - private static TableMeta getGisTableMetaByPrimaryTblMetaAndIndexName(SqlIdentifier idxNameAst, + private static TableMeta getGsiTableMetaByPrimaryTblMetaAndIndexName(SqlIdentifier idxNameAst, SqlIdentifier tblNameAstOfIndex, TableMeta tblMetaOfIndex) { String dbNameOfTblOfIndex = tblMetaOfIndex.getSchemaName(); String idxName = SQLUtils.normalizeNoTrim(idxNameAst.getLastName()); - String gsiFullTblName = null; + String fullTblName = null; Map gsiPublished = tblMetaOfIndex.getGsiPublished(); + Map cciPublished = tblMetaOfIndex.getColumnarIndexPublished(); if (gsiPublished != null) { String idxNameLowerCase = idxName.toLowerCase(); // all gsi tbl name format is idxname + "_$xxxx"; int targetLength = idxNameLowerCase.length() + 6; for (String gsiName : gsiPublished.keySet()) { if (gsiName.toLowerCase().startsWith(idxNameLowerCase) && gsiName.length() == targetLength) { - gsiFullTblName = gsiName; + fullTblName = gsiName; + break; + } + } + for (String cciName : cciPublished.keySet()) { + if (cciName.toLowerCase().startsWith(idxNameLowerCase) && cciName.length() == targetLength) { + fullTblName = cciName; break; } } } - if (gsiFullTblName == null) { + if (fullTblName == null) { throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, String.format("Not found the index [%s] of table [%s]", idxName, tblNameAstOfIndex.toString())); } - TableMeta gsiFullTblMeta = - OptimizerContext.getContext(dbNameOfTblOfIndex).getLatestSchemaManager().getTable(gsiFullTblName); - return gsiFullTblMeta; + TableMeta fullTblMeta = + OptimizerContext.getContext(dbNameOfTblOfIndex).getLatestSchemaManager().getTable(fullTblName); + return fullTblMeta; } @NotNull diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/TableGroupInfoManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/TableGroupInfoManager.java index 90f8f10d9..21a318916 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/TableGroupInfoManager.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/tablegroup/TableGroupInfoManager.java @@ -51,6 +51,7 @@ import java.util.Map; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; /** * Manage the tablegroup and partition group @@ -400,7 +401,7 @@ public void putMockEntry(PartitionInfo partitionInfo) { return; } for (PartitionGroupRecord partitionGroupRecord : partitionGroupRecords) { - TablePartitionRecord tablePartitionRecord = partRecList.stream() + TablePartitionRecord tablePartitionRecord = allPhyPartRecInfos.stream() .filter(o -> o.partName.equalsIgnoreCase(partitionGroupRecord.partition_name)).findFirst() .orElse(null); assert tablePartitionRecord != null; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlArchiveKind.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlArchiveKind.java new file mode 100644 index 000000000..c524b41d0 --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlArchiveKind.java @@ -0,0 +1,69 @@ +package com.alibaba.polardbx.optimizer.ttl; + +import com.alibaba.polardbx.druid.util.StringUtils; + +/** + * @author chenhui.lch + */ +public enum TtlArchiveKind { + + UNDEFINED(0, ""), + COLUMNAR(1, "COLUMNAR"), + PARTITION(2, "PARTITION"), + SUBPARTITION(3, "SUBPARTITION"); + private int archiveKindCode; + private String archiveKindStr; + + TtlArchiveKind(int code, String name) { + this.archiveKindCode = code; + this.archiveKindStr = name; + } + + public static TtlArchiveKind of(Integer archiveKindCode) { + switch (archiveKindCode) { + case 0: + return TtlArchiveKind.UNDEFINED; + case 1: + return TtlArchiveKind.COLUMNAR; + case 2: + return TtlArchiveKind.PARTITION; + case 3: + return TtlArchiveKind.SUBPARTITION; + case 4: + return TtlArchiveKind.UNDEFINED; + } + return TtlArchiveKind.UNDEFINED; + } + + public static TtlArchiveKind of(String archiveKindStr) { + + if (StringUtils.isEmpty(archiveKindStr)) { + return TtlArchiveKind.UNDEFINED; + } + + if (TtlArchiveKind.UNDEFINED.getArchiveKindStr().equalsIgnoreCase(archiveKindStr)) { + return TtlArchiveKind.UNDEFINED; + } else if (TtlArchiveKind.COLUMNAR.getArchiveKindStr().equalsIgnoreCase(archiveKindStr)) { + return TtlArchiveKind.COLUMNAR; + } else if (TtlArchiveKind.PARTITION.getArchiveKindStr().equalsIgnoreCase(archiveKindStr)) { + return TtlArchiveKind.PARTITION; + } else if (TtlArchiveKind.SUBPARTITION.getArchiveKindStr().equalsIgnoreCase(archiveKindStr)) { + return TtlArchiveKind.SUBPARTITION; + } else { + return TtlArchiveKind.UNDEFINED; + } + } + + public int getArchiveKindCode() { + return archiveKindCode; + } + + public void setArchiveKindCode(int archiveKindCode) { + this.archiveKindCode = archiveKindCode; + } + + public String getArchiveKindStr() { + return archiveKindStr; + } + +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlConfigUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlConfigUtil.java new file mode 100644 index 000000000..88b8c436e --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlConfigUtil.java @@ -0,0 +1,586 @@ +package com.alibaba.polardbx.optimizer.ttl; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; + +public class TtlConfigUtil { + + /** + * =========================== + * Config Params for polardbx-inst-level + * =========================== + */ + + /** + * The max wait time for interrupting a running ttl intra-task, unit: ms, default is 5s + * Unit: ms + */ + public static volatile int intraTaskInterruptionMaxWaitTime = + Integer.valueOf(ConnectionParams.TTL_INTRA_TASK_INTERRUPTION_MAX_WAIT_TIME.getDefault()); + + /** + * The wait time of each round for the delegate of intra-tasks + * Unit: ms, default 1s + */ + public static volatile int intraTaskDelegateEachRoundWaitTime = + Integer.valueOf(ConnectionParams.TTL_INTRA_TASK_MONITOR_EACH_ROUTE_WAIT_TIME.getDefault()); + + /** + * The max wait time for waiting a ddl-job from pause to running, unit: ms, default value is 30s + */ + public static volatile int maxWaitTimeForDdlJobFromPauseToRunning = 30000; + + /** + * The max data length of one partition of ttl-tmp table, default value is 1G + */ + public static volatile long maxTtlTmpTableDataLength = 128 * 1024 * 1024;// for test ,use 128MB + + /** + * Label if print the log for each intra-task of ClearAndPrepareExpiredDataTask + */ + public static volatile boolean enableCleanupIntraTaskInfoLog = false; + + /** + * The max percent of (data_free * 100 / data_length) of ttl-table to perform optimize-table operation, + * the default value if 60% , unit: % + */ + public static volatile long maxDataFreePercentOfTtlTable = + Long.valueOf(ConnectionParams.TTL_TBL_MAX_DATA_FREE_PERCENT.getDefault()); + + /** + * Label if auto perform the optimize-table operation for the ttl-table after data archiving + */ + public static volatile boolean enablePerformAutoOptiTtlTableAfterArchiving = true; + + /** + * Label if need control optimize-table ddl-job by ttl job automatically + *
+     *     if TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB=true, then:
+     *     if opti-table job does not exists, auto submit;
+     *     if opti-table  job exists and state is paused, auto continue ddl;
+     *     if opti-table  job exists and state is running, auto wait it finished;
+     * 
+ */ + public static volatile boolean enableAutoControlOptiTblByTtlJob = + Boolean.valueOf(ConnectionParams.TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB.getDefault()); + ; + + /** + * The interval of each add part of arc tbl + */ + public static volatile int intervalOfPreBuildPartOfArcTbl = 1; + + /** + * The pre-built part count of range base + * on current_datetime() for creating columnar index + */ + public static volatile int preBuiltPartCntForCreatColumnarIndex = + Integer.valueOf(ConnectionParams.TTL_DEFAULT_ARC_PRE_ALLOCATE_COUNT.getDefault()); + ; + + /** + * The post-built part count of range base + * on current_datetime() for creating columnar index + */ + public static volatile int postBuiltPartCntForCreateColumnarIndex = + Integer.valueOf(ConnectionParams.TTL_DEFAULT_ARC_POST_ALLOCATE_COUNT.getDefault()); + + /** + * Label if auto add partition for arc cci + */ + public static volatile boolean enableAutoAddPartsForArcCci = true; + + /** + * The max parallelism of the scheduled ttl job of tables, + * that means the at most tables of maxTtlScheduledJobParallelism are allowed to + * perform archive data at the same time + */ + public static volatile int ttlScheduledJobMaxParallelism = 2; + + /** + * The max thread count of threadpool of select sql of ttl job + */ + public static volatile int ttlGlobalSelectWorkerCount = + Integer.valueOf(ConnectionParams.TTL_GLOBAL_SELECT_WORKER_COUNT.getDefault()); + + /** + * The max thread count of threadpool of delete sql of ttl job + */ + public static volatile int ttlGlobalDeleteWorkerCount = + Integer.valueOf(ConnectionParams.TTL_GLOBAL_SELECT_WORKER_COUNT.getDefault()); + + /** + * The default batch size of delete/insert of ttl job + */ + public static int ttlJobDefaultBatchSize = + Integer.valueOf(ConnectionParams.TTL_JOB_DEFAULT_BATCH_SIZE.getDefault()); + + /** + * The interval count for computing minCleanupBound base on lowerBound(normalized minVal of ttl_col), + * that means the delta = ttlMinCleanupBoundIntervalCount * ttlUnit, is the delta interval between + * minCleanupBound and the lowerBound, default is 1 + */ + public static int ttlCleanupBoundIntervalCount = + Integer.valueOf(ConnectionParams.TTL_CLEANUP_BOUND_INTERVAL_COUNT.getDefault()); + + /** + * Stop ttl-job scheduling for all ttl tables, used for handling critical situation + */ + public static boolean stopAllTtlTableJobScheduling = + Boolean.valueOf(ConnectionParams.TTL_STOP_ALL_JOB_SCHEDULING.getDefault()); + + /** + * Label if use archive trans policy for all trans of ttl-job + */ + public static boolean useArchiveTransPolicy = true; + + /** + * The default merge_union_size for the select sql of fetch ttl-col lower bound + */ + public static int mergeUnionSizeForSelectLowerBound = 2; + + /** + * Use merge group concurrent for the select sql of fetch ttl-col lower bound + */ + public static boolean useMergeConcurrentForSelectLowerBound = true; + + /** + * The query hint for the select stmt of fetch ttl-col lower bound, + * which use to control the concurrent policy + */ + public static String queryHintForSelectLowerBound = + "/*+TDDL:cmd_extra(GROUP_CONCURRENT_BLOCK=true,PREFETCH_EXECUTE_POLICY=1,MERGE_UNION_SIZE=2,SOCKET_TIMEOUT=1800000)*/"; + + /** + * The query hint for delete stmt of deleting expired data, format is /TDDL: cmd_extra(k1=v1,k2=v2,...)/ + */ + public static String queryHintForDeleteExpiredData = "/*+TDDL:cmd_extra(SOCKET_TIMEOUT=1800000)*/"; + + /** + * The query hint for insert-select stmt of preparing expired data, format is /TDDL: cmd_extra(k1=v1,k2=v2,...)/ + */ + public static String queryHintForInsertExpiredData = "/*+TDDL:cmd_extra(SOCKET_TIMEOUT=1800000)*/"; + + /** + * The query hint for optimize-table stmt for ttl-tbl,format is /TDDL: cmd_extra(k1=v1,k2=v2,...)/ + */ + public static String queryHintForOptimizeTable = + "/*+TDDL:cmd_extra(ENABLE_ASYNC_DDL=true, PURE_ASYNC_DDL_MODE=true, RETURN_JOB_ID_ON_ASYNC_DDL_MODE=true, OPTIMIZE_TABLE_PARALLELISM=4, SOCKET_TIMEOUT=1800000)*/"; + + /** + * The query hint for the select stmt of fetch ttl-col lower bound, + * which use to control the concurrent policy + */ + public static String queryHintForAutoAddParts = "/*+TDDL:cmd_extra(SOCKET_TIMEOUT=1800000)*/"; + + /** + * The default group_parallelism of conn of select stmt, 0 means use the default val of inst_config + */ + public static Long defaultGroupParallelismOnDqlConn = 1L; + + /** + * The default group_parallelism of conn of delete/insert stmt,0 means use the default val of inst_config + */ + public static Long defaultGroupParallelismOnDmlConn = 0L; + + /** + * Label if need auto add maxvalue partition for cci of arctmp + */ + public static boolean autoAddMaxValuePartForCci = + Boolean.valueOf(ConnectionParams.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING.getDefault()); + ; + + /** + * The max periods of try waiting to acquire the rate permits, unit: ms + */ + public static long maxWaitAcquireRatePermitsPeriods = + Long.valueOf(ConnectionParams.TTL_MAX_WAIT_ACQUIRE_RATE_PERMITS_PERIODS.getDefault()); + + /** + * Label if need limit the cleanup rows speed for each dn + */ + public static boolean enableTtlCleanupRowsSpeedLimit = + Boolean.valueOf(ConnectionParams.TTL_ENABLE_CLEANUP_ROWS_SPEED_LIMIT.getDefault()); + + /** + * The default rowsSpeed limit for each dn, unit: rows/sec + */ + public static long cleanupRowsSpeedLimitEachDn = + Long.valueOf(ConnectionParams.TTL_CLEANUP_ROWS_SPEED_LIMIT_EACH_DN.getDefault()); + + /** + * Label if ignore maintain window in ttl job + */ + public static boolean ignoreMaintainWindowInTtlJob = + Boolean.valueOf(ConnectionParams.TTL_IGNORE_MAINTAIN_WINDOW_IN_DDL_JOB.getDefault()); + + /** + * The ratio of global-delete-worker / rw-dn-count, default is 2 + */ + public static int ttlGlobalWorkerDnRatio = + Integer.valueOf(ConnectionParams.TTL_GLOBAL_WORKER_DN_RATIO.getDefault()); + + /** + * =========================== + * Config Params for polardbx-session-level + * =========================== + */ + + /** + * The max part count in one archive ddl cmd when data length is less than limit + */ + public static int maxPartCountOneArchivedCmd = 1; + + /** + * The max subbpart count of ttl-tmp tbl and arc-tbl + */ + public static int ttlTmpTblDefaultSubPartHashCount = 8; + + /** + * The max part count in one archive ddl cmd when data length is more than limit + */ + public static int maxPartCountOneArchivedCmdWhenDataLengthExceedLimit = 3; + + /** + * The default charset of trans conn of ttl-job when exec sql + */ + public static String defaultCharsetEncodingOnTransConn = "utf8mb4"; + + /** + * The default sql mode of trans conn of ttl-job when exec sql + */ + public static String defaultSqlModeOnTransConn = ""; + + /** + * The parallelism of alter table ttl_tbl optimize partitions xxx + */ + public static int optimizePartitionParallelism = 4; + + public static int getIntraTaskInterruptionMaxWaitTime() { + return intraTaskInterruptionMaxWaitTime; + } + + public static void setIntraTaskInterruptionMaxWaitTime(int intraTaskInterruptionMaxWaitTime) { + TtlConfigUtil.intraTaskInterruptionMaxWaitTime = intraTaskInterruptionMaxWaitTime; + } + + public static int getIntraTaskDelegateEachRoundWaitTime() { + return intraTaskDelegateEachRoundWaitTime; + } + + public static void setIntraTaskDelegateEachRoundWaitTime(int intraTaskDelegateEachRoundWaitTime) { + TtlConfigUtil.intraTaskDelegateEachRoundWaitTime = intraTaskDelegateEachRoundWaitTime; + } + + public static int getMaxWaitTimeForDdlJobFromPauseToRunning() { + return maxWaitTimeForDdlJobFromPauseToRunning; + } + + public static void setMaxWaitTimeForDdlJobFromPauseToRunning(int maxWaitTimeForDdlJobFromPauseToRunning) { + TtlConfigUtil.maxWaitTimeForDdlJobFromPauseToRunning = maxWaitTimeForDdlJobFromPauseToRunning; + } + + public static long getMaxTtlTmpTableDataLength() { + return maxTtlTmpTableDataLength; + } + + public static void setMaxTtlTmpTableDataLength(long maxTtlTmpTableDataLength) { + TtlConfigUtil.maxTtlTmpTableDataLength = maxTtlTmpTableDataLength; + } + + public static boolean isEnableCleanupIntraTaskInfoLog() { + return enableCleanupIntraTaskInfoLog; + } + + public static void setEnableCleanupIntraTaskInfoLog(boolean enableCleanupIntraTaskInfoLog) { + TtlConfigUtil.enableCleanupIntraTaskInfoLog = enableCleanupIntraTaskInfoLog; + } + + public static boolean isEnableAutoControlOptiTblByTtlJob() { + return enableAutoControlOptiTblByTtlJob; + } + + public static void setEnableAutoControlOptiTblByTtlJob(boolean enableAutoControlOptiTblByTtlJob) { + TtlConfigUtil.enableAutoControlOptiTblByTtlJob = enableAutoControlOptiTblByTtlJob; + } + + public static boolean isEnablePerformAutoOptiTtlTableAfterArchiving() { + return enablePerformAutoOptiTtlTableAfterArchiving; + } + + public static void setEnablePerformAutoOptiTtlTableAfterArchiving( + boolean enablePerformAutoOptiTtlTableAfterArchiving) { + TtlConfigUtil.enablePerformAutoOptiTtlTableAfterArchiving = enablePerformAutoOptiTtlTableAfterArchiving; + } + + public static long getMaxDataFreePercentOfTtlTable() { + return maxDataFreePercentOfTtlTable; + } + + public static void setMaxDataFreePercentOfTtlTable(long maxDataFreePercentOfTtlTable) { + TtlConfigUtil.maxDataFreePercentOfTtlTable = maxDataFreePercentOfTtlTable; + } + + public static int getIntervalOfPreBuildPartOfArcTbl() { + return intervalOfPreBuildPartOfArcTbl; + } + + public static void setIntervalOfPreBuildPartOfArcTbl(int intervalOfPreBuildPartOfArcTbl) { + TtlConfigUtil.intervalOfPreBuildPartOfArcTbl = intervalOfPreBuildPartOfArcTbl; + } + + public static int getPreBuiltPartCntForCreatColumnarIndex() { + return preBuiltPartCntForCreatColumnarIndex; + } + + public static void setPreBuiltPartCntForCreatColumnarIndex(int preBuiltPartCntForCreatColumnarIndex) { + TtlConfigUtil.preBuiltPartCntForCreatColumnarIndex = preBuiltPartCntForCreatColumnarIndex; + } + + public static int getPostBuiltPartCntForCreateColumnarIndex() { + return postBuiltPartCntForCreateColumnarIndex; + } + + public static void setPostBuiltPartCntForCreateColumnarIndex(int postBuiltPartCntForCreateColumnarIndex) { + TtlConfigUtil.postBuiltPartCntForCreateColumnarIndex = postBuiltPartCntForCreateColumnarIndex; + } + + public static int getTtlScheduledJobMaxParallelism() { + return ttlScheduledJobMaxParallelism; + } + + public static void setTtlScheduledJobMaxParallelism(int ttlScheduledJobMaxParallelism) { + TtlConfigUtil.ttlScheduledJobMaxParallelism = ttlScheduledJobMaxParallelism; + } + + public static int getTtlGlobalSelectWorkerCount() { + return ttlGlobalSelectWorkerCount; + } + + public static void setTtlGlobalSelectWorkerCount(int ttlGlobalSelectWorkerCount) { + TtlConfigUtil.ttlGlobalSelectWorkerCount = ttlGlobalSelectWorkerCount; + } + + public static int getTtlGlobalDeleteWorkerCount() { + return ttlGlobalDeleteWorkerCount; + } + + public static void setTtlGlobalDeleteWorkerCount(int ttlGlobalDeleteWorkerCount) { + TtlConfigUtil.ttlGlobalDeleteWorkerCount = ttlGlobalDeleteWorkerCount; + } + + public static int getMaxPartCountOneArchivedCmd() { + return maxPartCountOneArchivedCmd; + } + + public static void setMaxPartCountOneArchivedCmd(int maxPartCountOneArchivedCmd) { + TtlConfigUtil.maxPartCountOneArchivedCmd = maxPartCountOneArchivedCmd; + } + + public static int getTtlTmpTblDefaultSubPartHashCount() { + return ttlTmpTblDefaultSubPartHashCount; + } + + public static void setTtlTmpTblDefaultSubPartHashCount(int ttlTmpTblDefaultSubPartHashCount) { + TtlConfigUtil.ttlTmpTblDefaultSubPartHashCount = ttlTmpTblDefaultSubPartHashCount; + } + + public static int getMaxPartCountOneArchivedCmdWhenDataLengthExceedLimit() { + return maxPartCountOneArchivedCmdWhenDataLengthExceedLimit; + } + + public static void setMaxPartCountOneArchivedCmdWhenDataLengthExceedLimit( + int maxPartCountOneArchivedCmdWhenDataLengthExceedLimit) { + TtlConfigUtil.maxPartCountOneArchivedCmdWhenDataLengthExceedLimit = + maxPartCountOneArchivedCmdWhenDataLengthExceedLimit; + } + + public static String getDefaultCharsetEncodingOnTransConn() { + return defaultCharsetEncodingOnTransConn; + } + + public static void setDefaultCharsetEncodingOnTransConn(String defaultCharsetEncodingOnTransConn) { + TtlConfigUtil.defaultCharsetEncodingOnTransConn = defaultCharsetEncodingOnTransConn; + } + + public static String getDefaultSqlModeOnTransConn() { + return defaultSqlModeOnTransConn; + } + + public static void setDefaultSqlModeOnTransConn(String defaultSqlModeOnTransConn) { + TtlConfigUtil.defaultSqlModeOnTransConn = defaultSqlModeOnTransConn; + } + + public static int getOptimizePartitionParallelism() { + return optimizePartitionParallelism; + } + + public static void setOptimizePartitionParallelism(int optimizePartitionParallelism) { + TtlConfigUtil.optimizePartitionParallelism = optimizePartitionParallelism; + } + + public static int getMergeUnionSizeForSelectLowerBound() { + return mergeUnionSizeForSelectLowerBound; + } + + public static void setMergeUnionSizeForSelectLowerBound(int mergeUnionSizeForSelectLowerBound) { + TtlConfigUtil.mergeUnionSizeForSelectLowerBound = mergeUnionSizeForSelectLowerBound; + } + + public static boolean isUseGsiInsteadOfCciForCreateColumnarArcTbl(ExecutionContext ec) { + boolean useGsiAsCci = ec.getParamManager().getBoolean(ConnectionParams.TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL); + return useGsiAsCci; + } + + public static int getTtlJobDefaultBatchSize() { + return ttlJobDefaultBatchSize; + } + + public static void setTtlJobDefaultBatchSize(int ttlJobDefaultBatchSize) { + TtlConfigUtil.ttlJobDefaultBatchSize = ttlJobDefaultBatchSize; + } + + public static int getTtlCleanupBoundIntervalCount() { + return ttlCleanupBoundIntervalCount; + } + + public static void setTtlCleanupBoundIntervalCount(int ttlCleanupBoundIntervalCount) { + TtlConfigUtil.ttlCleanupBoundIntervalCount = ttlCleanupBoundIntervalCount; + } + + public static boolean isStopAllTtlTableJobScheduling() { + return stopAllTtlTableJobScheduling; + } + + public static void setStopAllTtlTableJobScheduling(boolean stopAllTtlTableJobScheduling) { + TtlConfigUtil.stopAllTtlTableJobScheduling = stopAllTtlTableJobScheduling; + } + + public static boolean isUseArchiveTransPolicy() { + return useArchiveTransPolicy; + } + + public static void setUseArchiveTransPolicy(boolean useArchiveTransPolicy) { + TtlConfigUtil.useArchiveTransPolicy = useArchiveTransPolicy; + } + + public static boolean isUseMergeConcurrentForSelectLowerBound() { + return useMergeConcurrentForSelectLowerBound; + } + + public static void setUseMergeConcurrentForSelectLowerBound(boolean useMergeConcurrentForSelectLowerBound) { + TtlConfigUtil.useMergeConcurrentForSelectLowerBound = useMergeConcurrentForSelectLowerBound; + } + + public static String getQueryHintForSelectLowerBound() { + return queryHintForSelectLowerBound; + } + + public static void setQueryHintForSelectLowerBound(String queryHintForSelectLowerBound) { + TtlConfigUtil.queryHintForSelectLowerBound = queryHintForSelectLowerBound; + } + + public static String getQueryHintForDeleteExpiredData() { + return queryHintForDeleteExpiredData; + } + + public static void setQueryHintForDeleteExpiredData(String queryHintForDeleteExpiredData) { + TtlConfigUtil.queryHintForDeleteExpiredData = queryHintForDeleteExpiredData; + } + + public static String getQueryHintForInsertExpiredData() { + return queryHintForInsertExpiredData; + } + + public static void setQueryHintForInsertExpiredData(String queryHintForInsertExpiredData) { + TtlConfigUtil.queryHintForInsertExpiredData = queryHintForInsertExpiredData; + } + + public static Long getDefaultGroupParallelismOnDqlConn() { + return defaultGroupParallelismOnDqlConn; + } + + public static void setDefaultGroupParallelismOnDqlConn(Long defaultGroupParallelismOnDqlConn) { + TtlConfigUtil.defaultGroupParallelismOnDqlConn = defaultGroupParallelismOnDqlConn; + } + + public static Long getDefaultGroupParallelismOnDmlConn() { + return defaultGroupParallelismOnDmlConn; + } + + public static void setDefaultGroupParallelismOnDmlConn(Long defaultGroupParallelismOnDmlConn) { + TtlConfigUtil.defaultGroupParallelismOnDmlConn = defaultGroupParallelismOnDmlConn; + } + + public static String getQueryHintForOptimizeTable() { + return queryHintForOptimizeTable; + } + + public static boolean isAutoAddMaxValuePartForCci() { + return autoAddMaxValuePartForCci; + } + + public static void setAutoAddMaxValuePartForCci(boolean autoAddMaxValuePartForCci) { + TtlConfigUtil.autoAddMaxValuePartForCci = autoAddMaxValuePartForCci; + } + + public static void setQueryHintForOptimizeTable(String queryHintForOptimizeTable) { + TtlConfigUtil.queryHintForOptimizeTable = queryHintForOptimizeTable; + } + + public static String getQueryHintForAutoAddParts() { + return queryHintForAutoAddParts; + } + + public static void setQueryHintForAutoAddParts(String queryHintForAutoAddParts) { + TtlConfigUtil.queryHintForAutoAddParts = queryHintForAutoAddParts; + } + + public static long getMaxWaitAcquireRatePermitsPeriods() { + return maxWaitAcquireRatePermitsPeriods; + } + + public static void setMaxWaitAcquireRatePermitsPeriods(long maxWaitAcquireRatePermitsPeriods) { + TtlConfigUtil.maxWaitAcquireRatePermitsPeriods = maxWaitAcquireRatePermitsPeriods; + } + + public static boolean isEnableTtlCleanupRowsSpeedLimit() { + return enableTtlCleanupRowsSpeedLimit; + } + + public static void setEnableTtlCleanupRowsSpeedLimit(boolean enableTtlCleanupRowsSpeedLimit) { + TtlConfigUtil.enableTtlCleanupRowsSpeedLimit = enableTtlCleanupRowsSpeedLimit; + } + + public static long getCleanupRowsSpeedLimitEachDn() { + return cleanupRowsSpeedLimitEachDn; + } + + public static void setCleanupRowsSpeedLimitEachDn(long cleanupRowsSpeedLimitEachDn) { + TtlConfigUtil.cleanupRowsSpeedLimitEachDn = cleanupRowsSpeedLimitEachDn; + } + + public static boolean isIgnoreMaintainWindowInTtlJob() { + return ignoreMaintainWindowInTtlJob; + } + + public static void setIgnoreMaintainWindowInTtlJob(boolean ignoreMaintainWindowInTtlJob) { + TtlConfigUtil.ignoreMaintainWindowInTtlJob = ignoreMaintainWindowInTtlJob; + } + + public static int getTtlGlobalWorkerDnRatio() { + return ttlGlobalWorkerDnRatio; + } + + public static void setTtlGlobalWorkerDnRatio(int ttlGlobalWorkerDnRatio) { + TtlConfigUtil.ttlGlobalWorkerDnRatio = ttlGlobalWorkerDnRatio; + } + + public static boolean isEnableAutoAddPartsForArcCci() { + return enableAutoAddPartsForArcCci; + } + + public static void setEnableAutoAddPartsForArcCci(boolean enableAutoAddPartsForArcCci) { + TtlConfigUtil.enableAutoAddPartsForArcCci = enableAutoAddPartsForArcCci; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlDefinitionInfo.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlDefinitionInfo.java new file mode 100644 index 000000000..3ecf0aede --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlDefinitionInfo.java @@ -0,0 +1,513 @@ +package com.alibaba.polardbx.optimizer.ttl; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.time.calculator.MySQLIntervalType; +import com.alibaba.polardbx.druid.sql.SQLUtils; +import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.gms.partition.ExtraFieldJSON; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; +import com.alibaba.polardbx.gms.util.TtlEventLogUtil; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import lombok.Data; +import org.apache.calcite.sql.SqlCharStringLiteral; +import org.apache.calcite.sql.SqlCreateTable; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlNumericLiteral; +import org.apache.calcite.sql.SqlTimeToLiveExpr; +import org.apache.calcite.sql.SqlTimeToLiveJobExpr; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author chenghui.lch + */ +@Data +public class TtlDefinitionInfo { + + /** + * The ttl definition + */ + protected TtlInfoRecord ttlInfoRecord = new TtlInfoRecord(); + + /** + * The pk columns of ttl table + */ + protected List pkColumns = new ArrayList<>(); + + public TtlDefinitionInfo() { + } + + public boolean isEnableTtlSchedule() { + return ttlInfoRecord.getTtlStatus() == TtlInfoRecord.TTL_STATUS_ENABLE_SCHEDULE; + } + + public boolean isTtlBinlogOpen() { + return ttlInfoRecord.getTtlBinlog() == TtlInfoRecord.TTL_BINLOG_OPEN_BINLOG_DURING_CLEANING_DATA; + } + + public boolean isEnableArchivedTableSchedule() { + return ttlInfoRecord.getArcStatus() == TtlInfoRecord.ARCHIVE_STATUS_ENABLE_OSS_ARCHIVE; + } + + public boolean performArchiveByColumnarIndex() { + return ttlInfoRecord.getArcKind() == TtlInfoRecord.ARCHIVE_KIND_COLUMNAR; + } + + public boolean needPerformExpiredDataArchivingByOssTbl() { + if (performArchiveByColumnarIndex()) { + return false; + } + return !StringUtils.isEmpty(ttlInfoRecord.getArcTblName()); + } + + public boolean needPerformExpiredDataArchivingByCci() { + if (!performArchiveByColumnarIndex()) { + return false; + } + return !StringUtils.isEmpty(ttlInfoRecord.getArcTblName()); + } + + public boolean needPerformExpiredDataArchiving() { + return !StringUtils.isEmpty(ttlInfoRecord.getArcTblName()); + } + + public MySQLIntervalType getIntervalType() { + return MySQLIntervalType.of(TtlTimeUnit.of(ttlInfoRecord.getTtlUnit()).getTimeUnitName()); + } + + public boolean useTimestampOnTtlCol(ExecutionContext ec) { + return TtlUtil.useTimestampOnTtlCol(this, ec); + } + + /** + * Create TtlDefInfo from metadb + */ + public static TtlDefinitionInfo createFrom(TtlInfoRecord ttlInfoRecord, + List pkColumns) { + if (ttlInfoRecord == null) { + return null; + } + TtlDefinitionInfo ttlDefinitionInfo = new TtlDefinitionInfo(); + ttlDefinitionInfo.setTtlInfoRecord(ttlInfoRecord); + ttlDefinitionInfo.setPkColumns(pkColumns); + return ttlDefinitionInfo; + } + + public static Integer getArcKindByEngine(String tableEngine) { + if (StringUtils.isEmpty(tableEngine)) { + return TtlInfoRecord.ARCHIVE_KIND_UNDEF; + } + if (tableEngine.equalsIgnoreCase(Engine.COLUMNAR.name())) { + return TtlInfoRecord.ARCHIVE_KIND_COLUMNAR; + } else { + return TtlInfoRecord.ARCHIVE_KIND_UNDEF; + } + } + + public static TtlDefinitionInfo createNewTtlInfo( + String tableSchema, + String tableName, + String ttlEnable, + SqlTimeToLiveExpr ttlExpr, + SqlTimeToLiveJobExpr ttlJob, + String archiveKind, + String archiveTableSchema, + String archiveTableName, + Integer arcPreAllocateCount, + Integer arcPostAllocateCount, + List pkColumns, + TableMeta ttlTableMeta, + PartitionInfo newCreatedTblPartInfo, + SqlCreateTable sqlCreateTableAst, + ExecutionContext ec) { + + if (ttlExpr == null) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, + String.format( + "Failed to create new ttl definition for table `%s`.`%s` because the ttl_expr is not defined", + tableSchema, tableName)); + } + + String ttlExprStrVal = ttlExpr.toString(); + + SqlIdentifier columnNode = (SqlIdentifier) ttlExpr.getColumn(); + String columnName = SQLUtils.normalize(columnNode.getLastName()).trim(); + + SqlNumericLiteral expireAfterNode = (SqlNumericLiteral) ttlExpr.getExpireAfter(); + Integer expireAfter = ((Long) expireAfterNode.getValue()).intValue(); + + SqlIdentifier unitNode = (SqlIdentifier) ttlExpr.getUnit(); + String expireAfterUnit = SQLUtils.normalize(unitNode.getLastName()); + + SqlNode timezone = ttlExpr.getTimezone(); + String ttlExprTimezoneVal = null; + if (timezone != null) { + SqlCharStringLiteral timezoneNode = (SqlCharStringLiteral) timezone; + String ttlExprTimezoneValTmp = timezoneNode.toString(); + ttlExprTimezoneVal = SQLUtils.normalize(ttlExprTimezoneValTmp); + } + + String cronVal = ConnectionParams.DEFAULT_TTL_SCHEDULE_CRON_EXPR.getDefault(); + if (ttlJob != null) { + SqlNode cronNode = ttlJob.getCron(); + cronVal = SQLUtils.normalize((cronNode).toString()); + } + + int ttlStatusVal = TtlInfoRecord.TTL_STATUS_DISABLE_SCHEDULE; + if (!StringUtils.isEmpty(ttlEnable)) { + if (ttlEnable.equalsIgnoreCase(TtlInfoRecord.TTL_STATUS_DISABLE_SCHEDULE_STR_VAL)) { + ttlStatusVal = TtlInfoRecord.TTL_STATUS_DISABLE_SCHEDULE; + } + } + + int arcKind = TtlInfoRecord.ARCHIVE_KIND_UNDEF; + if (archiveKind != null) { + arcKind = TtlArchiveKind.of(archiveKind).getArchiveKindCode(); + } + + String archiveTableNameVal = null; + if (!StringUtils.isEmpty(archiveTableName)) { + /** + * arcTblName has NOT been specified + */ + archiveTableNameVal = archiveTableName; + } + + String archiveTableSchemaVal = null; + if (!StringUtils.isEmpty(archiveTableSchema)) { + archiveTableSchemaVal = archiveTableSchema; + } else { + if (!StringUtils.isEmpty(archiveTableNameVal)) { + /** + * arcTblName has been specified, but arcTblSchema has NOT been specified, + * so arcTblSchema use the ttlSchema as default value + */ + archiveTableSchemaVal = tableSchema; + } + } + + String arcTmpTblSchema = null; + if (!StringUtils.isEmpty(archiveTableSchemaVal)) { + arcTmpTblSchema = archiveTableSchemaVal; + } + + String arcTmpTblName = null; + if (!StringUtils.isEmpty(archiveTableNameVal)) { + arcTmpTblName = TtlUtil.buildArcTmpNameByArcTblName(archiveTableNameVal); + } + + int arcStatus = TtlInfoRecord.ARCHIVE_STATUS_DISABLE_OSS_ARCHIVE; + + TtlDefinitionInfo newTtlInfoToBeReturn = null; + newTtlInfoToBeReturn = new TtlDefinitionInfo(); + TtlInfoRecord ttlDefRec = new TtlInfoRecord(); + ttlDefRec.setTableSchema(tableSchema); + ttlDefRec.setTableName(tableName); + + ttlDefRec.setTtlStatus(ttlStatusVal); + ttlDefRec.setTtlExpr(ttlExprStrVal); + ttlDefRec.setTtlFilter(""); + ttlDefRec.setTtlCol(columnName); + ttlDefRec.setTtlInterval(expireAfter); + ttlDefRec.setTtlUnit(TtlTimeUnit.of(expireAfterUnit).getTimeUnitCode()); + ttlDefRec.setTtlTimezone(ttlExprTimezoneVal); + ttlDefRec.setTtlCron(cronVal); + ttlDefRec.setTtlBinlog(TtlInfoRecord.TTL_BINLOG_CLOSE_BINLOG_DURING_CLEANING_DATA); + + ttlDefRec.setArcKind(arcKind); + ttlDefRec.setArcStatus(arcStatus); + ttlDefRec.setArcTmpTblSchema(arcTmpTblSchema); + ttlDefRec.setArcTmpTblName(arcTmpTblName); + ttlDefRec.setArcTblSchema(archiveTableSchemaVal); + ttlDefRec.setArcTblName(archiveTableNameVal); + + ttlDefRec.setArcPartMode(TtlInfoRecord.ARC_PART_MODE_NORMAL); + ttlDefRec.setArcPartUnit(ttlDefRec.getTtlUnit()); + ttlDefRec.setArcPartInterval(TtlConfigUtil.getIntervalOfPreBuildPartOfArcTbl()); + ttlDefRec.setArcPrePartCnt(arcPreAllocateCount); + ttlDefRec.setArcPostPartCnt(arcPostAllocateCount); + + ExtraFieldJSON extraJsonFld = new ExtraFieldJSON(); + ttlDefRec.setExtra(extraJsonFld); + + newTtlInfoToBeReturn.setTtlInfoRecord(ttlDefRec); + newTtlInfoToBeReturn.setPkColumns(pkColumns); + + TtlMetaValidationUtil.validateTtlDefinition(newTtlInfoToBeReturn, ttlTableMeta, newCreatedTblPartInfo, sqlCreateTableAst, ec); + logEventForCreateTtlInfo(newCreatedTblPartInfo != null, ttlDefRec); + + return newTtlInfoToBeReturn; + } + + public static TtlDefinitionInfo buildModifiedTtlInfo(TtlDefinitionInfo oldTtlInfo, + String tableSchema, + String tableName, + String ttlEnable, + SqlTimeToLiveExpr ttlExpr, + SqlTimeToLiveJobExpr ttlJob, + String archiveKind, + String archiveTableSchema, + String archiveTableName, + Integer arcPreAllocateCount, + Integer arcPostAllocateCount, + List pkColumns, + TableMeta ttlTableMeta, + ExecutionContext ec) { + TtlDefinitionInfo newTtlInfoToBeReturn = null; + newTtlInfoToBeReturn = oldTtlInfo.copy(); + + newTtlInfoToBeReturn.getTtlInfoRecord().setTableSchema(tableSchema); + newTtlInfoToBeReturn.getTtlInfoRecord().setTableName(tableName); + newTtlInfoToBeReturn.setPkColumns(pkColumns); + + if (ttlEnable != null) { + int ttlStatusVal = TtlInfoRecord.TTL_STATUS_ENABLE_SCHEDULE; + if (ttlEnable.equalsIgnoreCase(TtlInfoRecord.TTL_STATUS_DISABLE_SCHEDULE_STR_VAL)) { + ttlStatusVal = TtlInfoRecord.TTL_STATUS_DISABLE_SCHEDULE; + } + newTtlInfoToBeReturn.getTtlInfoRecord().setTtlStatus(ttlStatusVal); + } + + if (ttlExpr != null) { + String ttlExprStrVal = ttlExpr.toString(); + SqlIdentifier columnNode = (SqlIdentifier) ttlExpr.getColumn(); + + String ttlCol = SQLUtils.normalize(columnNode.getLastName()).trim(); + + SqlNumericLiteral expireAfterNode = (SqlNumericLiteral) ttlExpr.getExpireAfter(); + Integer expireAfter = ((Long) expireAfterNode.getValue()).intValue(); + + SqlIdentifier unitNode = (SqlIdentifier) ttlExpr.getUnit(); + String expireAfterUnit = SQLUtils.normalize(unitNode.getLastName()); + + newTtlInfoToBeReturn.getTtlInfoRecord().setTtlCol(ttlCol); + newTtlInfoToBeReturn.getTtlInfoRecord().setTtlExpr(ttlExprStrVal); + newTtlInfoToBeReturn.getTtlInfoRecord().setTtlInterval(expireAfter); + + int newTimeUnitCode = TtlTimeUnit.of(expireAfterUnit).getTimeUnitCode(); + newTtlInfoToBeReturn.getTtlInfoRecord().setTtlUnit(newTimeUnitCode); + newTtlInfoToBeReturn.getTtlInfoRecord().setArcPartUnit(newTimeUnitCode); + + SqlNode timezone = ttlExpr.getTimezone(); + String ttlExprTimezoneVal = null; + if (timezone != null) { + SqlCharStringLiteral timezoneNode = (SqlCharStringLiteral) timezone; + String ttlExprTimezoneValTmp = timezoneNode.toString(); + ttlExprTimezoneVal = SQLUtils.normalize(ttlExprTimezoneValTmp); + newTtlInfoToBeReturn.getTtlInfoRecord().setTtlTimezone(ttlExprTimezoneVal); + } + } + + if (ttlJob != null) { + SqlNode cronNode = ttlJob.getCron(); + String cronVal = SQLUtils.normalize(((SqlCharStringLiteral) cronNode).toString()); + +// SqlNode cronTimezone = ttlJob.getTimezone(); +// String cronTimezoneVal = null; +// if (cronTimezone != null) { +// SqlCharStringLiteral cronTimezoneNode = (SqlCharStringLiteral) cronTimezone; +// cronTimezoneVal = cronTimezoneNode.toString(); +// } + newTtlInfoToBeReturn.getTtlInfoRecord().setTtlCron(cronVal); + } + + if (archiveTableName != null) { + if (StringUtils.isEmpty(archiveTableName)) { + /** + * arcTblName has been specified as an empty str, means unbinding arcTableName + */ + newTtlInfoToBeReturn.getTtlInfoRecord().setArcTblName(null); + newTtlInfoToBeReturn.getTtlInfoRecord().setArcTmpTblName(null); + } else { + /** + * arcTblName has been specified as an non-empty str, means binding arcTableName + */ + String arcTmpTblName = TtlUtil.buildArcTmpNameByArcTblName(archiveTableName); + newTtlInfoToBeReturn.getTtlInfoRecord().setArcTblName(archiveTableName); + newTtlInfoToBeReturn.getTtlInfoRecord().setArcTmpTblName(arcTmpTblName); + } + } + + if (archiveTableSchema != null) { + String arcTblNameToBeReturn = newTtlInfoToBeReturn.getTtlInfoRecord().getArcTblName(); + if (StringUtils.isEmpty(arcTblNameToBeReturn)) { + /** + * arcTblName has NOT been specified, arcTblSchema must be null; + */ + newTtlInfoToBeReturn.getTtlInfoRecord().setArcTblSchema(null); + newTtlInfoToBeReturn.getTtlInfoRecord().setArcTmpTblSchema(null); + } else { + /** + * arcTblName has been specified + */ + if (StringUtils.isEmpty(archiveTableSchema)) { + /** + * arcTblName has been specified, but arcTblSchema has NOT been specified, + * so arcTblSchema use the ttlSchema as default value + */ + newTtlInfoToBeReturn.getTtlInfoRecord().setArcTblSchema(tableSchema); + newTtlInfoToBeReturn.getTtlInfoRecord().setArcTmpTblSchema(tableSchema); + } else { + newTtlInfoToBeReturn.getTtlInfoRecord().setArcTblSchema(archiveTableSchema); + newTtlInfoToBeReturn.getTtlInfoRecord().setArcTmpTblSchema(archiveTableSchema); + } + } + } + + if (archiveKind != null) { + newTtlInfoToBeReturn.getTtlInfoRecord().setArcKind(TtlArchiveKind.of(archiveKind).getArchiveKindCode()); + } + + if (arcPreAllocateCount != null) { + newTtlInfoToBeReturn.getTtlInfoRecord().setArcPrePartCnt(arcPreAllocateCount); + } + + if (arcPostAllocateCount != null) { + newTtlInfoToBeReturn.getTtlInfoRecord().setArcPostPartCnt(arcPostAllocateCount); + } + + TtlMetaValidationUtil.validateTtlDefinition(newTtlInfoToBeReturn, ttlTableMeta, null, null, ec); + logEventForModifyTtlInfo(oldTtlInfo, newTtlInfoToBeReturn); + + return newTtlInfoToBeReturn; + } + + private static void logEventForCreateTtlInfo(boolean isFromCreateTbl, TtlInfoRecord ttlDefRec) { + if (StringUtils.isEmpty(ttlDefRec.getArcTblName())) { + TtlEventLogUtil.logCreateTtlDefinitionEvent(ttlDefRec.getTableSchema(), ttlDefRec.getTableName()); + } else { + if (isFromCreateTbl) { + TtlEventLogUtil.logCreateCciArchiveTableEvent(ttlDefRec.getTableSchema(), ttlDefRec.getTableName(), + ttlDefRec.getArcTblName()); + } else { + TtlEventLogUtil.logCreateTtlDefinitionWithArchiveTableEvent(ttlDefRec.getTableSchema(), + ttlDefRec.getTableName(), ttlDefRec.getArcTblName()); + } + } + } + + private static void logEventForModifyTtlInfo(TtlDefinitionInfo oldTtlInfo, TtlDefinitionInfo newTtlInfoToBeReturn) { + if (!StringUtils.isEmpty(newTtlInfoToBeReturn.getTtlInfoRecord().getArcTblName())) { + if (StringUtils.isEmpty(oldTtlInfo.getTtlInfoRecord().getArcTblName())) { + /** + * ArcTblName change from null to non-null + */ + TtlEventLogUtil.logCreateCciArchiveTableEvent(newTtlInfoToBeReturn.getTtlInfoRecord().getTableSchema(), + newTtlInfoToBeReturn.getTtlInfoRecord().getTableName(), + newTtlInfoToBeReturn.getTtlInfoRecord().getArcTblName()); + } + } else { + if (!StringUtils.isEmpty(oldTtlInfo.getTtlInfoRecord().getArcTblName())) { + /** + * ArcTblName change from non-null to null + */ + TtlEventLogUtil.logDropCciArchiveTableEvent(newTtlInfoToBeReturn.getTtlInfoRecord().getTableSchema(), + newTtlInfoToBeReturn.getTtlInfoRecord().getTableName(), + oldTtlInfo.getTtlInfoRecord().getArcTblName()); + } + } + } + + public String buildShowCreateTableOptions() { +// +// TTL_ENABLE = 'ON' +// TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +// TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00' + /** + *
+         * TTL =
+         * TTL_DEFINITION (
+         *  TTL_ENABLE='ON',
+         *  TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00',
+         *  TTL_JOB = CRON '* * * * * *' TIMEZONE '+00:00',
+         *  ...
+         *  )
+         * 
+ */ + String options = ""; + if (ttlInfoRecord != null) { + options += String.format("\nTTL = TTL_DEFINITION ("); + options += String.format("TTL_ENABLE = '%s', ", + ttlInfoRecord.getTtlStatus() == TtlInfoRecord.TTL_STATUS_ENABLE_SCHEDULE ? "ON" : "OFF"); + options += String.format("TTL_EXPR = %s, ", ttlInfoRecord.getTtlExpr()); + options += String.format("TTL_JOB = CRON '%s' TIMEZONE '%s', ", ttlInfoRecord.getTtlCron(), + ttlInfoRecord.getTtlTimezone()); + options += String.format("ARCHIVE_TYPE = '%s', ", + TtlArchiveKind.of(ttlInfoRecord.getArcKind()).getArchiveKindStr()); + String ttlTblSchema = ttlInfoRecord.getTableSchema(); + String arcTblSchema = ttlInfoRecord.getArcTblSchema(); + String archTblName = ttlInfoRecord.getArcTblName(); + if (!StringUtils.isEmpty(archTblName) && !arcTblSchema.equalsIgnoreCase(ttlTblSchema)) { + options += String.format("ARCHIVE_TABLE_SCHEMA = '%s', ", + ttlInfoRecord.getArcTblSchema() == null ? "" : ttlInfoRecord.getArcTblSchema()); + } + options += String.format("ARCHIVE_TABLE_NAME = '%s', ", + ttlInfoRecord.getArcTblName() == null ? "" : ttlInfoRecord.getArcTblName()); + options += String.format("ARCHIVE_TABLE_PRE_ALLOCATE = %s, ", ttlInfoRecord.getArcPrePartCnt()); + options += String.format("ARCHIVE_TABLE_POST_ALLOCATE = %s", ttlInfoRecord.getArcPostPartCnt()); + + options += String.format(")"); + } + return options; + } + + public boolean alreadyBoundArchiveTable() { + boolean res = false; + if (!StringUtils.isEmpty(this.getTtlInfoRecord().getArcTblSchema()) + || !StringUtils.isEmpty(this.getTtlInfoRecord().getArcTblName())) { + return false; + } + return res; + } + + public TtlDefinitionInfo copy() { + TtlInfoRecord newTtlRec = this.ttlInfoRecord.copy(); + List newPkColumns = new ArrayList<>(); + newPkColumns.addAll(this.pkColumns); + + TtlDefinitionInfo newTtlInfo = new TtlDefinitionInfo(); + newTtlInfo.setTtlInfoRecord(newTtlRec); + newTtlInfo.setPkColumns(newPkColumns); + + return newTtlInfo; + } + + public String getTmpTableName() { + return ttlInfoRecord.getArcTmpTblName(); + } + + public String getTmpTableSchema() { + return ttlInfoRecord.getArcTmpTblSchema(); + } + + public String getArchiveTableName() { + return ttlInfoRecord.getArcTblName(); + } + + public String getArchiveTableSchema() { + return ttlInfoRecord.getArcTblSchema(); + } + + public TtlInfoRecord getTtlInfoRecord() { + return ttlInfoRecord; + } + + public void setTtlInfoRecord(TtlInfoRecord ttlInfoRecord) { + this.ttlInfoRecord = ttlInfoRecord; + } + + public List getPkColumns() { + return pkColumns; + } + + public void setPkColumns(List pkColumns) { + this.pkColumns = pkColumns; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlMetaValidationUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlMetaValidationUtil.java new file mode 100644 index 000000000..206c52ada --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlMetaValidationUtil.java @@ -0,0 +1,594 @@ +package com.alibaba.polardbx.optimizer.ttl; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.timezone.InternalTimeZone; +import com.alibaba.polardbx.common.utils.timezone.TimeZoneUtils; +import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.optimizer.exception.TableNotFoundException; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.sql.sql2rel.TddlSqlToRelConverter; +import com.alibaba.polardbx.optimizer.view.SystemTableView; +import com.alibaba.polardbx.optimizer.view.ViewManager; +import com.cronutils.model.Cron; +import com.cronutils.model.CronType; +import com.cronutils.model.definition.CronDefinitionBuilder; +import com.cronutils.parser.CronParser; +import org.apache.calcite.sql.SqlCreateTable; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +/** + * @author chenghui.lch + */ +public class TtlMetaValidationUtil { + + private static final Logger logger = LoggerFactory.getLogger(TtlMetaValidationUtil.class); + + protected static Set supportedTtlUnit = new HashSet<>(); + + static { + supportedTtlUnit.add(TtlTimeUnit.DAY); + supportedTtlUnit.add(TtlTimeUnit.MONTH); + supportedTtlUnit.add(TtlTimeUnit.YEAR); + } + + public static void validateTtlInfoChange(TtlDefinitionInfo oldTtlInfo, + TtlDefinitionInfo newTtlInfo, + ExecutionContext ec) { + TtlMetaValidationUtil.validateTtlColChange(oldTtlInfo, newTtlInfo, ec); + TtlMetaValidationUtil.validateArcTblChange(oldTtlInfo, newTtlInfo, ec); + TtlMetaValidationUtil.validateArcKindChange(oldTtlInfo, newTtlInfo, ec); + } + + protected static void validateTtlColChange(TtlDefinitionInfo oldTtlInfo, + TtlDefinitionInfo newTtlInfo, + ExecutionContext ec) { + try { + if (oldTtlInfo == null) { + return; + } + + String oldTtlCol = oldTtlInfo.getTtlInfoRecord().getTtlCol(); + boolean useArchiveOfOldTtlInfo = oldTtlInfo.needPerformExpiredDataArchiving(); + + String newTtlCol = newTtlInfo.getTtlInfoRecord().getTtlCol(); + if (useArchiveOfOldTtlInfo) { + String arcTblName = oldTtlInfo.getTtlInfoRecord().getArcTblName(); + if (!newTtlCol.equalsIgnoreCase(oldTtlCol)) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, + String.format( + "Forbid to change ttl column from `%s` to `%s` because archived table `%s` is using", + oldTtlCol, + newTtlCol, arcTblName)); + } + } + } catch (Throwable ex) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, ex.getMessage(), ex); + } + } + + protected static void validateArcTblChange(TtlDefinitionInfo oldTtlInfo, + TtlDefinitionInfo newTtlInfo, + ExecutionContext ec) { + + if (oldTtlInfo == null) { + + return; + } + + String oldArcTblSchema = oldTtlInfo.getTtlInfoRecord().getArcTblSchema(); + String oldArcTblName = oldTtlInfo.getTtlInfoRecord().getArcTblName(); + + String newArcTblSchema = newTtlInfo.getTtlInfoRecord().getArcTblSchema(); + String newArcTblName = newTtlInfo.getTtlInfoRecord().getArcTblName(); + + if (StringUtils.isEmpty(oldArcTblName) && StringUtils.isEmpty(oldArcTblSchema)) { + // no archive table + return; + } + + if (StringUtils.isEmpty(newArcTblName) && StringUtils.isEmpty(newArcTblSchema)) { + // unbind archive table + return; + } + + if (!StringUtils.isEmpty(newArcTblName) && !oldArcTblName.equalsIgnoreCase(newArcTblName) || + !StringUtils.isEmpty(newArcTblSchema) && !oldArcTblSchema.equalsIgnoreCase(newArcTblSchema)) { + // found archive table changed + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, + String.format("Failed to modify ttl definition because archive table `%s`.`%s` is using", + oldArcTblSchema, oldArcTblName)); + } + } + + protected static void validateArcKindChange(TtlDefinitionInfo oldTtlInfo, + TtlDefinitionInfo newTtlInfo, + ExecutionContext ec) { + + if (oldTtlInfo == null) { + return; + } + + TtlArchiveKind oldArcKind = TtlArchiveKind.of(oldTtlInfo.getTtlInfoRecord().getArcKind()); + TtlArchiveKind newArcKind = TtlArchiveKind.of(newTtlInfo.getTtlInfoRecord().getArcKind()); + + String newArcTblSchema = newTtlInfo.getArchiveTableSchema(); + String newArcTblName = newTtlInfo.getArchiveTableName(); + if (newArcKind == TtlArchiveKind.UNDEFINED) { + // no archive table + + if (!StringUtils.isEmpty(newArcTblName) || !StringUtils.isEmpty(newArcTblSchema)) { + // found empty archive table name + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, + String.format( + "Failed to modify ttl definition because archive table must be empty when the arcKind is undefined")); + } + + if (oldArcKind == TtlArchiveKind.UNDEFINED) { + /** + * arcKind from undefined to undefined, + * that means ttl-tbl bind no archive table, + * so ignore + */ + return; + } else { + + /** + * arcKind from defined to undefined, + * that means ttl-tbl unbind archive table, so ignore + */ + } + } else { + if (StringUtils.isEmpty(newArcTblSchema) || StringUtils.isEmpty(newArcTblName)) { + // found archive table changed + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, + String.format( + "Failed to modify ttl definition because archive table must be not empty when the arcKind is %s", + newArcKind.getArchiveKindStr())); + } + + if (oldArcKind == TtlArchiveKind.UNDEFINED) { + /** + * arcKind from undefined to defined, + * that means ttl-tbl bind new archive table, so ignore + */ + return; + } else { + + /** + * arcKind from old defined to new defined, + * that means ttl-tbl want to bind new archive table instead of + * old archive table, + * so need check if arcKind is different, + * it is not allowed to be different. + */ + if (oldArcKind != newArcKind) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, + String.format("Failed to modify ttl definition because the archive table %s.%s is using", + oldTtlInfo.getTtlInfoRecord().getTableSchema(), + oldTtlInfo.getTtlInfoRecord().getTableName())); + } + } + } + + } + + /** + * Validate if the definition of ttl-col is valid + */ + public static void validateTtlColDefinition(TtlDefinitionInfo ttlInfo, + TableMeta ttlTableMeta, + ExecutionContext ec) { + + try { + + String ttlTblSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlInfo.getTtlInfoRecord().getTableName(); + String ttlColName = ttlInfo.getTtlInfoRecord().getTtlCol(); + + TableMeta tblMeta = ttlTableMeta; + if (tblMeta == null) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_TABLE_NOT_FOUND, + String.format("Failed to create ttl definition because `%s`.`%s` does not exist", ttlTblSchema, + ttlTblName)); + } + + ColumnMeta ttlCm = tblMeta.getColumn(ttlColName); + if (ttlCm == null) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_COLUMN_NOT_FOUND, + String.format("Failed to create ttl definition because the column `%s` of `%s`.`%s` does not exist", + ttlColName, ttlTblSchema, ttlTblName)); + } + + DataType ttlColDt = ttlCm.getDataType(); + if (!DataTypeUtil.isMysqlTimeType(ttlColDt) || DataTypeUtil.anyMatchSemantically(DataTypes.TimeType)) { + String sqlTypeName = ttlColDt.getStringSqlType(); + throw new TddlRuntimeException(ErrorCode.ERR_TTL_COLUMN_NOT_FOUND, String.format( + "Failed to create ttl definition because the datatype `%s` of the column `%s` on `%s`.`%s` is not supported", + sqlTypeName, ttlColName, ttlTblSchema, ttlTblName)); + } + + } catch (Throwable ex) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, ex.getMessage(), ex); + } + } + + public static void validateTtlExpiredInterval(TtlDefinitionInfo ttlInfo, ExecutionContext ec) { + + try { + Integer ttlInterval = ttlInfo.getTtlInfoRecord().getTtlInterval(); + if (ttlInterval <= 0) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create ttl definition because the ttl interval value must be more than 0")); + } + + Integer ttlUnitCode = ttlInfo.getTtlInfoRecord().getTtlUnit(); + TtlTimeUnit ttlUnit = TtlTimeUnit.of(ttlUnitCode); + if (!TtlMetaValidationUtil.supportedTtlUnit.contains(ttlUnit)) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create ttl definition because the ttl time unit `%s` is not supported yet", + ttlUnit.getTimeUnitName())); + } + + } catch (Throwable ex) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, ex.getMessage(), ex); + } + + } + + public static void validateTimeZoneExpr(String tzExpr, ExecutionContext ec) { + try { + if (StringUtils.isEmpty(tzExpr)) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create ttl definition because the ttl timezone `%s` is invalid", tzExpr)); + } + InternalTimeZone internalTz = TimeZoneUtils.convertFromMySqlTZ(tzExpr); + if (internalTz == null) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create ttl definition because the ttl timezone `%s` is invalid", tzExpr)); + } + } catch (Throwable ex) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, ex.getMessage(), ex); + } + } + + public static void validateArchiveTableInfo(TtlDefinitionInfo ttlInfo, + TableMeta ttlTableMeta, + ExecutionContext ec) { + String ttlTblSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlInfo.getTtlInfoRecord().getTableName(); + String arcTblSchema = ttlInfo.getTtlInfoRecord().getArcTblSchema(); + String arcTblName = ttlInfo.getTtlInfoRecord().getArcTblSchema(); + + if (StringUtils.isEmpty(arcTblName) && StringUtils.isEmpty(arcTblSchema)) { + /** + * ok, ignore + */ + } else if (StringUtils.isEmpty(arcTblName) && !StringUtils.isEmpty(arcTblSchema)) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create ttl definition because the params of the archive table schema `%s` is invalid", + arcTblSchema)); + } else if (!StringUtils.isEmpty(arcTblName) && StringUtils.isEmpty(arcTblSchema)) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create ttl definition because the params of the archive table name `%s` is invalid", + arcTblName)); + } else { + if (!ttlTblSchema.equalsIgnoreCase(arcTblSchema)) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create ttl definition because the archive table schema `%s` is not the same as ttl table schema `%s`", + arcTblSchema, ttlTblSchema)); + } + } + + } + + protected static String getFirstColumnarName(boolean isValidateForNewCreateTable, + TableMeta primTableMeta, + SqlCreateTable newCreateTableAst) { + + String firstCciNameStr = null; + if (!isValidateForNewCreateTable) { + Map cciBeanInfo = primTableMeta.getColumnarIndexPublished(); + + if (cciBeanInfo == null || cciBeanInfo.isEmpty()) { + return firstCciNameStr; + } + + Collection cciBeans = cciBeanInfo.values(); + if (cciBeans == null || cciBeans.isEmpty()) { + return firstCciNameStr; + } + + Iterator cciItor = cciBeans.iterator(); + if (cciItor != null && cciItor.hasNext()) { + GsiMetaManager.GsiIndexMetaBean cciInfo = cciItor.next(); + firstCciNameStr = TddlSqlToRelConverter.unwrapGsiName(cciInfo.indexName); + } + } else { + firstCciNameStr = TtlUtil.getFirstColumnarIndexName(newCreateTableAst); + } + return firstCciNameStr; + } + + public static void validateArchiveCciInfo(TtlDefinitionInfo ttlInfo, + TableMeta tableMeta, + PartitionInfo newCreatedTblPartInfo, + SqlCreateTable sqlCreateTableAst, + ExecutionContext ec) { + + boolean validateForNewCreateTable = newCreatedTblPartInfo != null; + String arcTblSchema = ttlInfo.getTtlInfoRecord().getArcTblSchema(); + String arcTblName = ttlInfo.getTtlInfoRecord().getArcTblName(); + + String arcCciTblSchema = ttlInfo.getTtlInfoRecord().getArcTmpTblSchema(); + String arcCciTblName = ttlInfo.getTtlInfoRecord().getArcTmpTblName(); + + if (StringUtils.isEmpty(arcTblSchema) || StringUtils.isEmpty(arcTblName)) { + return; + } + + if (!StringUtils.equalsIgnoreCase(arcTblSchema, arcCciTblSchema)) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create ttl definition because the archive table schema `%s` is not the same as the actual archive cci schema `%s`", + arcTblSchema, arcCciTblSchema)); + } + + String realCciName = getFirstColumnarName(validateForNewCreateTable, tableMeta, sqlCreateTableAst); + String tmpCciName = TtlUtil.buildArcTmpNameByArcTblName(arcTblName); + + if (StringUtils.isEmpty(realCciName) && !StringUtils.isEmpty(tmpCciName)) { + + /** + * If the prim Tbl has no any cci, then auto ignore the arc cci bound + *
+             *     Notice !!!
+             *     If code come in here ,that means some wrong has gone on current polardbx-inst cluster
+             *     or its replica polardbx-inst cluster,
+             *     here just to handle for producing invalid meta data of ttl20
+             * 
+ */ + + /** + * Auto reset the arcName & arcTmpName of ttlInfo + */ + ttlInfo.getTtlInfoRecord().setArcTmpTblSchema(null); + ttlInfo.getTtlInfoRecord().setArcTmpTblName(null); + + ttlInfo.getTtlInfoRecord().setArcTblSchema(null); + ttlInfo.getTtlInfoRecord().setArcTblName(null); + + ttlInfo.getTtlInfoRecord().setArcKind(TtlInfoRecord.ARCHIVE_KIND_UNDEF); + + try { + String ttlSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String ttlTbl = ttlInfo.getTtlInfoRecord().getTableName(); + String logMsg = String.format( + "The table `%s`.`%s` has no found any cci, so ignore bounding cci as the archive table `%s`.`%s`", + ttlSchema, ttlTbl, arcTblSchema, arcTblName); + logger.warn(logMsg); + } catch (Throwable e) { + // ignore + } + + return; + } + + if (!StringUtils.equalsIgnoreCase(realCciName, tmpCciName)) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create ttl definition because the real archive cci name `%s` is not the same as the auto-gen cci name `%s`", + realCciName, tmpCciName)); + } + + } + + public static void validateTtlJobExpr(TtlDefinitionInfo ttlInfo, + TableMeta ttlTableMeta, + ExecutionContext ec) { + TtlMetaValidationUtil.validateTtlColDefinition(ttlInfo, ttlTableMeta, ec); + TtlMetaValidationUtil.validateTtlExpiredInterval(ttlInfo, ec); + TtlMetaValidationUtil.validateTimeZoneExpr(ttlInfo.getTtlInfoRecord().getTtlTimezone(), ec); + } + + public static void validateTtlCornExpr(TtlDefinitionInfo ttlInfo, ExecutionContext ec) { + + String ttlCronExpr = ""; + try { + ttlCronExpr = ttlInfo.getTtlInfoRecord().getTtlCron(); + CronParser quartzCronParser = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ)); + Cron cron = quartzCronParser.parse(ttlCronExpr); + assert cron != null; + } catch (Throwable ex) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create ttl definition because the ttl cron expression `%s` is invalid", ttlCronExpr), ex); + } + } + + public static void validateTtlDefinition(TtlDefinitionInfo ttlInfo, + TableMeta ttlTableMeta, + PartitionInfo newCreatedTblPartInfo, + SqlCreateTable sqlCreateTableAst, + ExecutionContext ec) { + TtlMetaValidationUtil.validateAllowedCreatingNewTtlInfo(ttlInfo, ttlTableMeta, newCreatedTblPartInfo, ec); + TtlMetaValidationUtil.validateArchiveTableInfo(ttlInfo, ttlTableMeta, ec); + TtlMetaValidationUtil.validateArchiveCciInfo(ttlInfo, ttlTableMeta, newCreatedTblPartInfo, sqlCreateTableAst, + ec); + TtlMetaValidationUtil.validateAllowedBoundingArchiveTable(ttlInfo, ec, false, ttlInfo.getArchiveTableSchema(), + ttlInfo.getArchiveTableName()); + TtlMetaValidationUtil.validateTtlJobExpr(ttlInfo, ttlTableMeta, ec); + TtlMetaValidationUtil.validateTtlCornExpr(ttlInfo, ec); + } + + public static void validateAllowedBoundingArchiveTable(TtlDefinitionInfo ttlInfo, + ExecutionContext ec, + boolean validateForCreateNewArcTable, + String newTarArcTblSchema, + String newTarArcTblName) { + try { + if (ttlInfo == null) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create table because the source table is not a ttl-defined table")); + } + + String ttlTblSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlInfo.getTtlInfoRecord().getTableName(); + + String arcTblSchema = ttlInfo.getTtlInfoRecord().getArcTblSchema(); + String arcTblName = ttlInfo.getTtlInfoRecord().getArcTblName(); + + String cciName = TtlUtil.buildArcTmpNameByArcTblName(newTarArcTblName); + + if (!StringUtils.isEmpty(arcTblSchema) || !StringUtils.isEmpty(arcTblName)) { + if (validateForCreateNewArcTable) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create archive table because the source table `%s`.`%s` has bound the archive table `%s`.`%s`", + ttlTblSchema, ttlTblName, arcTblSchema, arcTblName)); + } + } + if (StringUtils.isEmpty(newTarArcTblSchema) || StringUtils.isEmpty(newTarArcTblName)) { + return; + } + + ViewManager viewMgr = OptimizerContext.getContext(newTarArcTblSchema).getViewManager(); + if (viewMgr != null) { + SystemTableView.Row viewInfo = viewMgr.select(newTarArcTblName); + if (viewInfo != null) { + String viewDefLowerCase = viewInfo.getViewDefinition().toLowerCase(); + boolean containTtlName = viewDefLowerCase.contains(ttlTblName.toLowerCase()); + boolean containCciName = viewDefLowerCase.contains(cciName.toLowerCase()); + + if (!(containTtlName && containCciName)) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create archive table because the archive table view `%s`.`%s` already exists", + newTarArcTblSchema, newTarArcTblName)); + } + } + } + + SchemaManager schemaManager = ec.getSchemaManager(newTarArcTblSchema); + if (schemaManager != null) { + TableMeta tableMeta = null; + try { + tableMeta = schemaManager.getTable(newTarArcTblName); + } catch (TableNotFoundException exception) { + tableMeta = null; + } + if (tableMeta != null) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL_PARAMS, String.format( + "Failed to create archive table because the archive table name `%s`.`%s` already exists", + newTarArcTblSchema, newTarArcTblName)); + } + } + + } catch (Throwable ex) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, ex.getMessage(), ex); + } + } + + public static void validateAllowedCreatingNewTtlInfo(TtlDefinitionInfo newTtlInfo, + TableMeta ttlTableMeta, + PartitionInfo newCreatedTblPartInfo, + ExecutionContext ec) { + + boolean buildTtlInfoForCreateNewTable = newCreatedTblPartInfo != null; + try { + + String ttlTblSchema = newTtlInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = newTtlInfo.getTtlInfoRecord().getTableName(); + + if (!DbInfoManager.getInstance().isNewPartitionDb(ttlTblSchema)) { + // error + throw new TddlRuntimeException(ErrorCode.ERR_TTL, String.format( + "Failed to create ttl definition because the drds-mode table `%s`.`%s` is not allowed", + ttlTblSchema, ttlTblName)); + } + + boolean isSingleTbl = false; + boolean isBroadcastTbl = false; + boolean isLocalPartTbl = false; + boolean isOssTbl = false; + boolean isGsi = false; + boolean isCci = false; + + if (buildTtlInfoForCreateNewTable) { + isSingleTbl = newCreatedTblPartInfo.isSingleTable(); + isBroadcastTbl = newCreatedTblPartInfo.isBroadcastTable(); + isGsi = newCreatedTblPartInfo.isGsi(); + isCci = newCreatedTblPartInfo.isColumnar(); + + } else { + if (ttlTableMeta != null && ttlTableMeta.getPartitionInfo() != null) { + isSingleTbl = ttlTableMeta.getPartitionInfo().isSingleTable(); + isBroadcastTbl = ttlTableMeta.getPartitionInfo().isBroadcastTable(); + isLocalPartTbl = ttlTableMeta.getLocalPartitionDefinitionInfo() != null; + isGsi = ttlTableMeta.isGsi(); + isCci = ttlTableMeta.isColumnar(); + } + } + isOssTbl = Engine.isFileStore(ttlTableMeta.getEngine()); + + if (isSingleTbl) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, String.format( + "Failed to create ttl definition because the broadcast/single table `%s`.`%s` is not allowed", + ttlTblSchema, ttlTblName)); + } + + if (isBroadcastTbl) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, String.format( + "Failed to create ttl definition because the broadcast/single table `%s`.`%s` is not allowed", + ttlTblSchema, ttlTblName)); + } + + if (isGsi) { + //err + throw new TddlRuntimeException(ErrorCode.ERR_TTL, String.format( + "Failed to create ttl definition because the global index table `%s`.`%s` is not allowed", + ttlTblSchema, ttlTblName)); + } + + if (isCci) { + // err + throw new TddlRuntimeException(ErrorCode.ERR_TTL, String.format( + "Failed to create ttl definition because the columnar index table `%s`.`%s` is not allowed", + ttlTblSchema, ttlTblName)); + } + + if (isLocalPartTbl) { + // err + throw new TddlRuntimeException(ErrorCode.ERR_TTL, String.format( + "Failed to create ttl definition because the local-partition table `%s`.`%s` is not allowed", + ttlTblSchema, ttlTblName)); + } + + if (isOssTbl) { + // err + throw new TddlRuntimeException(ErrorCode.ERR_TTL, String.format( + "Failed to create ttl definition because the oss table `%s`.`%s` is not allowed", + ttlTblSchema, ttlTblName)); + } + } catch (Throwable ex) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, ex.getMessage(), ex); + } + + } + +} + diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlTimeUnit.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlTimeUnit.java new file mode 100644 index 000000000..da6eeb73c --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlTimeUnit.java @@ -0,0 +1,93 @@ +package com.alibaba.polardbx.optimizer.ttl; + +import com.alibaba.polardbx.druid.util.StringUtils; + +/** + * @author chenhui.lch + */ +public enum TtlTimeUnit { + + YEAR(0, "YEAR"), + MONTH(1, "MONTH"), + DAY(2, "DAY"), + HOUR(3, "HOUR"), + MINUTE(4, "MINUTE"), + SECOND(5, "SECOND"); + private int timeUnitCode; + private String timeUnitName; + + TtlTimeUnit(int code, String name) { + this.timeUnitCode = code; + this.timeUnitName = name; + } + + public int getTimeUnitCode() { + return timeUnitCode; + } + + public String getTimeUnitName() { + return timeUnitName; + } + +// public static int convertInterval( +// Integer srcTimeUnitInterval, +// Integer srcTimeUnitCode, +// Integer tarTimeUnitCode +// ) { +// switch (srcTimeUnitCode) { +// case 0: +// return TtlTimeUnit.YEAR; +// case 1: +// return TtlTimeUnit.MONTH; +// case 2: +// return TtlTimeUnit.DAY; +// case 3: +// return TtlTimeUnit.HOUR; +// case 4: +// return TtlTimeUnit.MINUTE; +// case 5: +// return TtlTimeUnit.SECOND; +// } +// } + + public static TtlTimeUnit of(Integer timeUnitCode) { + switch (timeUnitCode) { + case 0: + return TtlTimeUnit.YEAR; + case 1: + return TtlTimeUnit.MONTH; + case 2: + return TtlTimeUnit.DAY; + case 3: + return TtlTimeUnit.HOUR; + case 4: + return TtlTimeUnit.MINUTE; + case 5: + return TtlTimeUnit.SECOND; + } + return null; + } + + public static TtlTimeUnit of(String timeUnitName) { + + if (StringUtils.isEmpty(timeUnitName)) { + return null; + } + + if (TtlTimeUnit.YEAR.getTimeUnitName().equalsIgnoreCase(timeUnitName)) { + return TtlTimeUnit.YEAR; + } else if (TtlTimeUnit.MONTH.getTimeUnitName().equalsIgnoreCase(timeUnitName)) { + return TtlTimeUnit.MONTH; + } else if (TtlTimeUnit.DAY.getTimeUnitName().equalsIgnoreCase(timeUnitName)) { + return TtlTimeUnit.DAY; + } else if (TtlTimeUnit.HOUR.getTimeUnitName().equalsIgnoreCase(timeUnitName)) { + return TtlTimeUnit.HOUR; + } else if (TtlTimeUnit.MINUTE.getTimeUnitName().equalsIgnoreCase(timeUnitName)) { + return TtlTimeUnit.MINUTE; + } else if (TtlTimeUnit.SECOND.getTimeUnitName().equalsIgnoreCase(timeUnitName)) { + return TtlTimeUnit.SECOND; + } else { + return null; + } + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlUtil.java new file mode 100644 index 000000000..a67f65b7e --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/ttl/TtlUtil.java @@ -0,0 +1,580 @@ +package com.alibaba.polardbx.optimizer.ttl; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.druid.sql.SQLUtils; +import com.alibaba.polardbx.druid.sql.ast.SQLPartition; +import com.alibaba.polardbx.druid.sql.ast.SQLPartitionBy; +import com.alibaba.polardbx.druid.sql.ast.SQLPartitionByRange; +import com.alibaba.polardbx.druid.sql.ast.SQLPartitionValue; +import com.alibaba.polardbx.druid.sql.ast.SQLSubPartitionByHash; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLIntegerExpr; +import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.gms.topology.DbInfoManager; +import com.alibaba.polardbx.gms.ttl.TtlInfoRecord; +import com.alibaba.polardbx.gms.util.GroupInfoUtil; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager; +import com.alibaba.polardbx.optimizer.config.table.SchemaManager; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.datatype.DataType; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil; +import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalDropTable; +import com.alibaba.polardbx.optimizer.core.rel.ddl.data.AlterTablePreparedData; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.common.PartitionTableType; +import com.alibaba.polardbx.optimizer.view.SystemTableView; +import com.alibaba.polardbx.optimizer.view.ViewManager; +import org.apache.calcite.sql.SqlCharStringLiteral; +import org.apache.calcite.sql.SqlCreateTable; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlIndexDefinition; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlTimeToLiveDefinitionExpr; +import org.apache.calcite.sql.SqlTimeToLiveExpr; +import org.apache.calcite.sql.SqlTimeToLiveJobExpr; +import org.apache.calcite.util.Pair; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.stream.Collectors; + +/** + * @author chenghui.lch + */ +public class TtlUtil { + + public static final int MAX_TTL_TMP_NAME_PREFIX_LENGTH = 38; + + /** + * arc_tmp name format (maxlen 60):arctmp_(7) + %s(arc_tbl_prefix,max 38) + _%s(hashvalstr, 9) + */ + public static final String ARC_TMP_NAME_TEMPLATE_WITH_HASHCODE = "arctmp_%s_%s"; + public static final String ARC_TMP_NAME_TEMPLATE_WITHOUT_HASHCODE = "arctmp_%s"; + + public static boolean checkIfCreateArcTblLikeRowLevelTtl(SqlCreateTable sqlCreateTable, + ExecutionContext ec) { + SqlIdentifier sourceTableNameAst = (SqlIdentifier) sqlCreateTable.getLikeTableName(); + String sourceTableSchema = + SQLUtils.normalizeNoTrim( + sourceTableNameAst.names.size() > 1 ? sourceTableNameAst.names.get(0) : ec.getSchemaName()); + String sourceTableName = SQLUtils.normalizeNoTrim(sourceTableNameAst.getLastName()); + if (checkIfUsingRowLevelTtl(sourceTableSchema, sourceTableName, ec)) { + return true; + } + return false; + } + + public static TtlDefinitionInfo fetchTtlInfoFromCreateTableLikeAst(SqlCreateTable sqlCreateTable, + ExecutionContext ec) { + if (!checkIfCreateArcTblLikeRowLevelTtl(sqlCreateTable, ec)) { + return null; + } + SqlIdentifier sourceTableNameAst = (SqlIdentifier) sqlCreateTable.getLikeTableName(); + String sourceTableSchema = + SQLUtils.normalizeNoTrim( + sourceTableNameAst.names.size() > 1 ? sourceTableNameAst.names.get(0) : ec.getSchemaName()); + String sourceTableName = SQLUtils.normalizeNoTrim(sourceTableNameAst.getLastName()); + TtlDefinitionInfo ttlDefinitionInfo = getTtlDefInfoBySchemaAndTable(sourceTableSchema, sourceTableName, ec); + return ttlDefinitionInfo; + } + + /** + * Check if using row-level ttl + */ + public static boolean checkIfUsingRowLevelTtl(String tableSchema, + String tableName, + ExecutionContext ec) { + if (StringUtils.isEmpty(tableSchema) || StringUtils.isEmpty(tableName)) { + return false; + } + TtlDefinitionInfo ttlDefinitionInfo = getTtlDefInfoBySchemaAndTable(tableSchema, tableName, ec); + return ttlDefinitionInfo != null; + } + + /** + * Check the + */ + public static boolean checkIfArchiveCciOfTtlTable(String ttlSchema, + String ttlTblName, + String fullCciName, + ExecutionContext ec) { + if (StringUtils.isEmpty(ttlSchema) || StringUtils.isEmpty(fullCciName)) { + return false; + } + + TableMeta ttlTblMeta = ec.getSchemaManager(ttlSchema).getTableWithNull(ttlTblName); + if (ttlTblMeta == null) { + return false; + } + TtlDefinitionInfo ttlInfo = ttlTblMeta.getTtlDefinitionInfo(); + if (ttlInfo == null) { + return false; + } + if (ttlInfo.needPerformExpiredDataArchivingByCci()) { + String arcCciName = ttlInfo.getTtlInfoRecord().getArcTmpTblName(); + Map tmpGsiName2Bean = + new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + tmpGsiName2Bean.putAll(ttlTblMeta.getColumnarIndexPublished()); + + if (TtlConfigUtil.isUseGsiInsteadOfCciForCreateColumnarArcTbl(ec)) { + tmpGsiName2Bean.putAll(ttlTblMeta.getGsiPublished()); + } + boolean foundArcCci = false; + if (tmpGsiName2Bean.containsKey(fullCciName) && fullCciName.toLowerCase() + .startsWith(arcCciName.toLowerCase())) { + foundArcCci = true; + } + return foundArcCci; + } + + return false; + } + + public static TtlDefinitionInfo getTtlDefInfoBySchemaAndTable( + String tableSchema, String tableName, ExecutionContext ec) { + + SchemaManager sm = ec.getSchemaManager(tableSchema); + if (sm == null) { + return null; + } + + TableMeta tableMeta = sm.getTableWithNull(tableName); + if (tableMeta == null) { + return null; + } + TtlDefinitionInfo ttlDefinitionInfo = tableMeta.getTtlDefinitionInfo(); + return ttlDefinitionInfo; + } + + public static TtlInfoRecord fetchTtlDefinitionInfoByArcDbAndArcTb(String arcTableSchema, + String arcTableName) { + try (Connection metaDbConn = MetaDbDataSource.getInstance().getConnection()) { + TableInfoManager mgr = new TableInfoManager(); + mgr.setConnection(metaDbConn); + TtlInfoRecord record = mgr.getTtlInfoRecordByArchiveTable(arcTableSchema, arcTableName); + return record; + } catch (Throwable ex) { + throw new TddlRuntimeException(ErrorCode.ERR_TTL, ex); + } + } + + public static TtlDefinitionInfo fetchTtlDefinitionInfoByDbAndTb(String tableSchema, + String tableName, + ExecutionContext ec) { + TableMeta tableMeta = ec.getSchemaManager(tableSchema).getTable(tableName); + TtlDefinitionInfo ttlDefinitionInfo = tableMeta.getTtlDefinitionInfo(); + return ttlDefinitionInfo; + } + + public static SQLPartitionBy buildNewSqlPartByAstForOssTable(ColumnMeta ttlTblTimeColMeta, + List ttlTblPkColMetas, + int defaultSubHashPartCnt, + String minRangeValue, + ExecutionContext ec) { + + /** + * Build 2nd-level part by key + */ + // Generate the partitioning clause. + final SQLSubPartitionByHash sqlSubPartitionByHash = new SQLSubPartitionByHash(); + SQLIntegerExpr intExpr = new SQLIntegerExpr(defaultSubHashPartCnt); + int maxPartColCnt = ec.getParamManager().getInt(ConnectionParams.MAX_PARTITION_COLUMN_COUNT); + List subPartKeys = new ArrayList<>(); + for (int i = 0; i < ttlTblPkColMetas.size(); i++) { + ColumnMeta pkCol = ttlTblPkColMetas.get(i); + SQLIdentifierExpr idAst = new SQLIdentifierExpr(pkCol.getName()); + subPartKeys.add(idAst); + if (i >= maxPartColCnt) { + break; + } + } + sqlSubPartitionByHash.getColumns().addAll(subPartKeys); + sqlSubPartitionByHash.setKey(true); + sqlSubPartitionByHash.setSubPartitionsCount(intExpr); + + /** + * Build 1st-level part by range + */ + List partKeys = new ArrayList<>(); + SQLIdentifierExpr ttlColAst = new SQLIdentifierExpr(ttlTblTimeColMeta.getName()); + partKeys.add(ttlColAst); + List rangePartKeys = partKeys; + + SQLCharExpr valExpr = new SQLCharExpr(minRangeValue); + SQLPartitionValue p1SpecVal = new SQLPartitionValue(SQLPartitionValue.Operator.LessThan); + p1SpecVal.addItem(valExpr); + SQLPartition p1PartSpec = new SQLPartition(); + p1PartSpec.setName(new SQLIdentifierExpr("pstart")); + p1PartSpec.setValues(p1SpecVal); + + SQLPartitionByRange sqlPartitionByRange = new SQLPartitionByRange(); + sqlPartitionByRange.setColumns(true); + sqlPartitionByRange.getColumns().addAll(rangePartKeys); + sqlPartitionByRange.getPartitions().add(p1PartSpec); + + /** + * Set the subpartBy for partBy + */ + sqlPartitionByRange.setSubPartitionBy(sqlSubPartitionByHash); + + return sqlPartitionByRange; + } + + public static String buildArcTmpNameByArcTblName(String arcTblName) { + String finalArcTmpName = ""; + if (StringUtils.isEmpty(arcTblName)) { + return finalArcTmpName; + } + int length = arcTblName.length(); + String ttlTmpNamePrefixStr = arcTblName; + String ttlTblNameHashCodeHexStr = ""; + if (length > TtlUtil.MAX_TTL_TMP_NAME_PREFIX_LENGTH) { + ttlTmpNamePrefixStr = arcTblName.substring(0, TtlUtil.MAX_TTL_TMP_NAME_PREFIX_LENGTH); + ttlTblNameHashCodeHexStr = GroupInfoUtil.doMurmur3Hash32(arcTblName); + finalArcTmpName = + String.format(ARC_TMP_NAME_TEMPLATE_WITH_HASHCODE, ttlTmpNamePrefixStr, ttlTblNameHashCodeHexStr); + } else { + finalArcTmpName = String.format(ARC_TMP_NAME_TEMPLATE_WITHOUT_HASHCODE, ttlTmpNamePrefixStr); + } + finalArcTmpName = finalArcTmpName.toLowerCase(); + return finalArcTmpName; + } + + public static boolean checkIfDropTtlTableWithCciArcTblView(String ttlTableSchema, + String ttlTableName, + ExecutionContext executionContext) { + + TableMeta ttlTblMeta = executionContext.getSchemaManager(ttlTableSchema).getTableWithNull(ttlTableName); + if (ttlTblMeta == null) { + return false; + } + TtlDefinitionInfo ttlInfo = ttlTblMeta.getTtlDefinitionInfo(); + if (ttlInfo == null) { + return false; + } + if (!ttlInfo.needPerformExpiredDataArchivingByCci()) { + return false; + } + return true; + } + + public static boolean checkIfDropCciOfArcTblView(String ttlTableSchema, + String ttlTableName, + String cciIndexName, + ExecutionContext executionContext) { + + TableMeta ttlTblMeta = executionContext.getSchemaManager(ttlTableSchema).getTableWithNull(ttlTableName); + if (ttlTblMeta == null) { + return false; + } + TtlDefinitionInfo ttlInfo = ttlTblMeta.getTtlDefinitionInfo(); + if (ttlInfo == null) { + return false; + } + if (!ttlInfo.needPerformExpiredDataArchivingByCci()) { + return false; + } + + if (!cciIndexName.toLowerCase().startsWith(ttlInfo.getTmpTableName().toLowerCase())) { + return false; + } + return true; + } + + public static boolean checkIfAllowedDropTableOperation(String targetTableSchema, + String targetTableName, + ExecutionContext executionContext) { + + /** + * Check if tarDb is autodb, + * if false, ignore check and retrun false; + */ + if (!DbInfoManager.getInstance().isNewPartitionDb(targetTableSchema)) { + return true; + } + + boolean enableUseGsiInsteadOfCci = + executionContext.getParamManager().getBoolean(ConnectionParams.TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL); + boolean forbidDropTableWithArcCci = + executionContext.getParamManager().getBoolean(ConnectionParams.TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI); + + /** + * Check if tarDb.tarTb a view + */ + ViewManager viewManager = OptimizerContext.getContext(targetTableSchema).getViewManager(); + if (viewManager != null) { + SystemTableView.Row view = viewManager.select(targetTableName); + + /** + * Check if view is a archive table view of ttl-table forcing cci + */ + + if (view != null) { + boolean dropViewForArcCci = + checkIfDropArcTblViewOfTtlTableWithCci(targetTableSchema, targetTableName, executionContext); + if (dropViewForArcCci) { + if (forbidDropTableWithArcCci) { + return false; + } else { + /** + * the tarDb.tarTb is view, and allowed drop arc_view of cci, so can return direclty + */ + return true; + } + } + } + } + + TableMeta targetTableMeta = + executionContext.getSchemaManager(targetTableSchema).getTableWithNull(targetTableName); + if (targetTableMeta != null) { + + PartitionInfo targetPartInfo = targetTableMeta.getPartitionInfo(); + + /** + * Check if tarDb.tarTb has ttl-definition + */ + TtlDefinitionInfo ttlInfo = targetTableMeta.getTtlDefinitionInfo(); + if (ttlInfo == null) { + /** + * tarDb.tarTb is NOT ttl-definition table + */ + + PartitionTableType tableType = targetPartInfo.getTableType(); + boolean isCciTbl = tableType == PartitionTableType.COLUMNAR_TABLE; + boolean isGsiTbl = tableType.isGsiTableType(); + boolean needCheckIfForbidDropOperation = isCciTbl; + if (enableUseGsiInsteadOfCci) { + needCheckIfForbidDropOperation |= isGsiTbl; + } + if (needCheckIfForbidDropOperation && forbidDropTableWithArcCci) { + /** + * IF the tarDb.tarTb is the cci/gsi of a ttl-definition table, + * now allow droping + */ + return false; + } + } else { + /** + * Now the tarDb.tarTb is ttl-definition table + */ + + /** + * Check if the ttl-definition table contain the archive table cci + */ + if (ttlInfo.performArchiveByColumnarIndex() && forbidDropTableWithArcCci) { + return false; + } + } + return true; + } + return true; + } + + public static boolean checkIfDropArcTblViewOfTtlTableWithCci(String arcTableSchema, + String arcTableName, + ExecutionContext executionContext) { + + final String schemaName = arcTableSchema; + final String logicalTableName = arcTableName; + + boolean dropArcTblViewAndCiForTtlTbl = false; + ViewManager viewManager = OptimizerContext.getContext(schemaName).getViewManager(); + if (viewManager == null) { + /** + * "viewManager == null" should NOT come here + */ + return dropArcTblViewAndCiForTtlTbl; + } + SystemTableView.Row viewInfo = viewManager.select(logicalTableName); + if (viewInfo != null) { + + /** + * The logicalTableName is a View !!! + * Check if it is a archive table view of ttl table with columnar index + */ + + TtlInfoRecord ttlInfoRec = TtlUtil.fetchTtlDefinitionInfoByArcDbAndArcTb(schemaName, logicalTableName); + if (ttlInfoRec != null) { + /** + * Current db.tb is actually a arc table view of ttl-table + */ + String ttlTblSchema = ttlInfoRec.getTableSchema(); + String ttlTblName = ttlInfoRec.getTableName(); + TableMeta ttlTblTm = executionContext.getSchemaManager(ttlTblSchema).getTableWithNull(ttlTblName); + if (ttlTblTm != null) { + TtlDefinitionInfo ttlInfo = ttlTblTm.getTtlDefinitionInfo(); + if (ttlInfo.performArchiveByColumnarIndex()) { + String ciNameOfArcTbl = ttlInfo.getTmpTableName(); + boolean useGsiForCci = + TtlConfigUtil.isUseGsiInsteadOfCciForCreateColumnarArcTbl(executionContext); + if (useGsiForCci) { + boolean withGsi = ttlTblTm.withGsi(); + if (withGsi) { + dropArcTblViewAndCiForTtlTbl = ttlTblTm.withGsi(ciNameOfArcTbl); + } + } else { + boolean withCci = ttlTblTm.withCci(); + if (withCci) { + dropArcTblViewAndCiForTtlTbl = ttlTblTm.withCci(ciNameOfArcTbl); + } + } + } + } + + } + } + return dropArcTblViewAndCiForTtlTbl; + } + + public static boolean useTimestampOnTtlCol(TtlDefinitionInfo ttlInfo, ExecutionContext ec) { + boolean result = false; + String ttlTblSchema = ttlInfo.getTtlInfoRecord().getTableSchema(); + String ttlTblName = ttlInfo.getTtlInfoRecord().getTableName(); + String ttlColName = ttlInfo.getTtlInfoRecord().getTtlCol(); + TableMeta tblMeta = ec.getSchemaManager(ttlTblSchema).getTable(ttlTblName); + ColumnMeta ttlCm = tblMeta.getColumn(ttlColName); + DataType ds = ttlCm.getDataType(); + result = DataTypeUtil.isTimezoneDependentType(ds); + return result; + } + + public static boolean checkIfNeedRefreshViewForArcTbl(AlterTablePreparedData preparedData, + ExecutionContext ec) { + String tableSchema = preparedData.getSchemaName(); + String tableName = preparedData.getTableName(); + + TtlDefinitionInfo ttlDefinitionInfo = fetchTtlDefinitionInfoByDbAndTb(tableSchema, tableName, ec); + if (ttlDefinitionInfo == null) { + return false; + } + + if (!ttlDefinitionInfo.needPerformExpiredDataArchivingByCci()) { + return false; + } + + boolean needFreshView = preparedData.hasColumnModify(); + return needFreshView; + } + + private static String getValueFromLiteral(SqlNode charExprAst) { + String val = SQLUtils.normalize(((SqlCharStringLiteral) charExprAst).toValue()); + return val; + } + + protected static String getFirstColumnarIndexName(SqlCreateTable sqlCreateTable) { + + List> cciIdxInfos = sqlCreateTable.getColumnarKeys(); + if (cciIdxInfos == null || cciIdxInfos.isEmpty()) { + return null; + } + SqlIndexDefinition cciDef = cciIdxInfos.get(0).getValue(); + SqlIdentifier cciRawName = cciDef.getOriginIndexName(); + String cciRawNameStr = cciRawName.getLastName(); + return cciRawNameStr; + } + + public static TtlDefinitionInfo createTtlDefinitionInfoBySqlCreateTable(SqlCreateTable sqlCreateTable, + TableMeta tableMeta, + PartitionInfo newCreateTblPartInfo, + ExecutionContext executionContext + ) { + boolean foundTtlDefinition = false; + + SqlNode ttlDefinitionExprNode = sqlCreateTable.getTtlDefinition(); + if (ttlDefinitionExprNode != null && ttlDefinitionExprNode instanceof SqlTimeToLiveDefinitionExpr) { + foundTtlDefinition = true; + } + + SqlTimeToLiveDefinitionExpr ttlDefinitionExprAst = (SqlTimeToLiveDefinitionExpr) ttlDefinitionExprNode; + + if (foundTtlDefinition) { + if (sqlCreateTable.getLocalPartition() != null) { + throw new TddlRuntimeException(ErrorCode.ERR_CREATE_TABLE_WITH_TTL, + "create table with ttl definition is not allowed using local partition"); + } + } + + if (!foundTtlDefinition) { + return null; + } + + String schemaName = tableMeta.getSchemaName(); + String tableName = tableMeta.getTableName(); + TtlDefinitionInfo ttlDefinitionInfo = null; + SqlNode ttlEnableExpr = ttlDefinitionExprAst.getTtlEnableExpr(); + SqlNode ttlExprNode = ttlDefinitionExprAst.getTtlExpr(); + SqlNode ttlJobNode = ttlDefinitionExprAst.getTtlJobExpr(); +// SqlNode ttlFilterExpr = ttlDefinitionExprAst.getTtlFilterExpr(); + SqlNode archiveTypeExpr = ttlDefinitionExprAst.getArchiveTypeExpr(); + SqlNode archiveTableSchemaExpr = ttlDefinitionExprAst.getArchiveTableSchemaExpr(); + SqlNode archiveTableNameExpr = ttlDefinitionExprAst.getArchiveTableNameExpr(); + SqlNode archiveTablePreAllocateExpr = ttlDefinitionExprAst.getArchiveTablePreAllocateExpr(); + SqlNode archiveTablePostAllocateExpr = ttlDefinitionExprAst.getArchiveTablePostAllocateExpr(); + + String ttlEnable = TtlInfoRecord.TTL_STATUS_DISABLE_SCHEDULE_STR_VAL; + if (ttlEnableExpr != null) { + ttlEnable = ttlEnableExpr.toString(); + } + + SqlTimeToLiveExpr ttlExpr = (SqlTimeToLiveExpr) ttlExprNode; + SqlTimeToLiveJobExpr ttlJob = null; + if (ttlJobNode != null) { + ttlJob = (SqlTimeToLiveJobExpr) ttlJobNode; + } + + List pkColMetas = tableMeta.getPrimaryKey().stream().collect(Collectors.toList()); + List pkColNames = new ArrayList<>(); + for (int i = 0; i < pkColMetas.size(); i++) { + ColumnMeta pkCm = pkColMetas.get(i); + pkColNames.add(pkCm.getName()); + } + + String archiveTypeVal = null; + if (archiveTypeExpr != null) { + archiveTypeVal = getValueFromLiteral(archiveTypeExpr); + } + + String archiveTableSchemaVal = null; + if (archiveTableSchemaExpr != null) { + archiveTableSchemaVal = getValueFromLiteral(archiveTableSchemaExpr); + } + + String archiveTableNameVal = null; + if (archiveTableNameExpr != null) { + archiveTableNameVal = getValueFromLiteral(archiveTableNameExpr); + } + + Integer arcPreAllocateVal = TtlConfigUtil.getPreBuiltPartCntForCreatColumnarIndex(); + if (archiveTablePreAllocateExpr != null) { + arcPreAllocateVal = Integer.valueOf(archiveTablePostAllocateExpr.toString()); + } + + Integer arcPostAllocateVal = TtlConfigUtil.getPostBuiltPartCntForCreateColumnarIndex(); + if (archiveTablePostAllocateExpr != null) { + arcPostAllocateVal = Integer.valueOf(archiveTablePostAllocateExpr.toString()); + } + + ttlDefinitionInfo = TtlDefinitionInfo.createNewTtlInfo(schemaName, tableName, + ttlEnable, ttlExpr, ttlJob, archiveTypeVal, archiveTableSchemaVal, archiveTableNameVal, arcPreAllocateVal, + arcPostAllocateVal, pkColNames, tableMeta, + newCreateTblPartInfo, + sqlCreateTable, + executionContext); + + return ttlDefinitionInfo; + } + +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/BuildPlanUtils.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/BuildPlanUtils.java index a5189b3f5..581baff6a 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/BuildPlanUtils.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/BuildPlanUtils.java @@ -82,6 +82,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -1078,39 +1080,103 @@ public static List buildUpdateColumnList(SqlNodeList duplicateKeyUpdateL return result; } - public static boolean checkAllUpdatedSkRefAfterValue(List updateColumnList, Set partitionKeys, + public static boolean checkAllUpdatedSkRefAfterValue(List updateColumnList, + TreeMap> tablePartitionKeyMap, + Map>> tableUkMapWithoutImplicitPk, LogicalInsert logicalInsert) { if (logicalInsert.isSourceSelect()) { return false; } - int refCnt = 0; + final TreeMap> updatedWithAfterValueTableColumnMap = + new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + for (int i = 0; i < updateColumnList.size(); i++) { - String columnName = updateColumnList.get(i); - if (partitionKeys.contains(updateColumnList.get(i))) { - refCnt++; - try { - RexCall rexCall = - (RexCall) ((RexCall) logicalInsert.getDuplicateKeyUpdateList().get(i)).getOperands().get(1); - SqlOperator op = rexCall.getOperator(); - if (!"VALUES".equalsIgnoreCase(op.getName())) { - return false; - } - RexNode operand = rexCall.getOperands().get(0); - RexInputRef inputRef = (RexInputRef) operand; - String refColumnName = logicalInsert.getInsertRowType().getFieldNames().get(inputRef.getIndex()); - if (!refColumnName.equalsIgnoreCase(columnName)) { + final String columnName = updateColumnList.get(i); + for (Map.Entry> entry : tablePartitionKeyMap.entrySet()) { + final String tableName = entry.getKey(); + final TreeSet partitionKeySet = entry.getValue(); + final TreeSet updatedWithAfterValueColumnSet = updatedWithAfterValueTableColumnMap + .computeIfAbsent(tableName, (k) -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER)); + if (partitionKeySet.contains(columnName)) { + try { + final RexNode rexNode = + ((RexCall) logicalInsert.getDuplicateKeyUpdateList().get(i)).getOperands().get(1); + + RexInputRef inputRef = null; + if (rexNode instanceof RexInputRef) { + // update with before value + // all uk contains this column, so that before and after value must be same + inputRef = (RexInputRef) rexNode; + final Map> ukColumnSet = tableUkMapWithoutImplicitPk.get(tableName); + // check uk with target column name + if (ukColumnSet.values().stream().anyMatch(ukColumn -> !ukColumn.contains(columnName))) { + return false; + } + } else { + RexCall rexCall = + (RexCall) ((RexCall) logicalInsert.getDuplicateKeyUpdateList().get(i)).getOperands() + .get(1); + SqlOperator op = rexCall.getOperator(); + if (!"VALUES".equalsIgnoreCase(op.getName())) { + return false; + } + RexNode operand = rexCall.getOperands().get(0); + inputRef = (RexInputRef) operand; + } + + // check source column equals target column + String refColumnName = + logicalInsert.getInsertRowType().getFieldNames().get(inputRef.getIndex()); + if (!refColumnName.equalsIgnoreCase(columnName)) { + return false; + } + } catch (Throwable e) { + // If it's not values(col), just return false return false; } - } catch (Throwable e) { - // If it's not values(col), just return false + + updatedWithAfterValueColumnSet.add(columnName); + } + } + } + + /* + * Check for situation like below: + * + * CREATE TABLE `t1_upsert` ( + * `ID` varchar(32) NOT NULL , + * `XX_DATE` date NOT NULL, + * PRIMARY KEY (`ID`), + * ) dbpartition by UNI_HASH(`id`) tbpartition by DD(`xx_date`) tbpartitions 31 + * + * explain insert into t1_upsert(id, xx_date) + * values (1, "2024-01-27 00:00:00.0") + * on duplicate key update xx_date=values(xx_date); + * + * We should push down the UPSERT + */ + for (Map.Entry> entry : tablePartitionKeyMap.entrySet()) { + final String tableName = entry.getKey(); + final TreeSet partitionKeySet = entry.getValue(); + final TreeSet updatedWithAfterValueColumnSet = updatedWithAfterValueTableColumnMap + .computeIfAbsent(tableName, (k) -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER)); + final Map> ukColumnSet = tableUkMapWithoutImplicitPk.get(tableName); + for (String sk : partitionKeySet) { + // If uk conflict happens, means the after value of uk column is duplicated with the before value + // So that, the partition result does not change. The UPSERT can pushdown. + final boolean updatedWithAfterValue = updatedWithAfterValueColumnSet.contains(sk) + || ukColumnSet.values().stream().allMatch(ukColumn -> ukColumn.contains(sk)); + + // Otherwise, UPSERT can not pushdown + if (!updatedWithAfterValue) { return false; } } } // Need to make sure all partition key ref to after value - return refCnt == partitionKeys.size(); + return true; } public static boolean checkAllUpdatedSkRefBeforeValue(List updateColumnList, Set partitionKeys, diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/CheckModifyLimitation.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/CheckModifyLimitation.java index eed4819e6..75e5fbd97 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/CheckModifyLimitation.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/CheckModifyLimitation.java @@ -553,20 +553,6 @@ public static boolean checkGsiHasAutoUpdateColumns(List targetTables, ExecutionContext ec) { - for (RelOptTable targetTable : targetTables) { - if (TableColumnUtils.isModifying(targetTable, ec)) { - return true; - } - } - return false; - } - - public static boolean checkOnlineModifyColumnDdl(TableModify tableModify, ExecutionContext ec) { - final List targetTables = tableModify.getTargetTables(); - return checkOnlineModifyColumnDdl(targetTables, ec); - } - public static boolean checkModifyPk(TableModify tableModify, ExecutionContext ec) { if (!tableModify.isUpdate()) { return false; diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/DrdsRexFolder.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/DrdsRexFolder.java index 8e441d690..971bf8fd6 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/DrdsRexFolder.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/DrdsRexFolder.java @@ -23,11 +23,12 @@ import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.expression.build.Rex2ExprVisitor; import com.alibaba.polardbx.optimizer.core.expression.calc.IExpression; -import org.apache.calcite.rel.metadata.RelMetadataQuery; import org.apache.calcite.rex.RexFieldAccess; import org.apache.calcite.rex.RexInputRef; import org.apache.calcite.rex.RexNode; +import static com.alibaba.polardbx.optimizer.utils.OptimizerUtils.getParametersForOptimizer; + /** * DrdsRexFolder folds constant in RexNode including RexDynamicParams * @@ -38,10 +39,7 @@ public abstract class DrdsRexFolder { private static final Logger logger = LoggerFactory.getLogger(DrdsRexFolder.class); public static Object fold(RexNode rex, PlannerContext plannerContext) { - Parameters parameters = RelMetadataQuery.THREAD_PARAMETERS.get(); - if (parameters == null) { - parameters = plannerContext.getParams(); - } + Parameters parameters = getParametersForOptimizer(plannerContext); ExecutionContext context = new ExecutionContext(); context.setParams(parameters); return fold(rex, context); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ExecutionPlanProperties.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ExecutionPlanProperties.java index 29c4519c7..cf1489b2d 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ExecutionPlanProperties.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ExecutionPlanProperties.java @@ -18,6 +18,7 @@ import org.apache.calcite.util.BitSets; +import java.lang.reflect.Field; import java.util.BitSet; /** @@ -72,4 +73,33 @@ public final class ExecutionPlanProperties { public static final BitSet DDL_STATEMENT = BitSets .of(DDL); + + public static final BitSet DML_STATEMENT = BitSets + .of(DML); + + private static Integer cachedMaxPropertyValue = null; + + public static int getMaxPropertyValue() { + if (cachedMaxPropertyValue != null) { + // cache + return cachedMaxPropertyValue; + } + try { + Field[] fields = ExecutionPlanProperties.class.getFields(); // 获取所有公共字段 + + int maxPropertyValue = Integer.MIN_VALUE; + for (Field field : fields) { + if (field.getType() == int.class && (field.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0 + && (field.getModifiers() & java.lang.reflect.Modifier.FINAL) != 0) { + int value = field.getInt(null); // 获取字段的值 + maxPropertyValue = Math.max(maxPropertyValue, value); // 计算最大值 + } + } + int result = maxPropertyValue + 1; + cachedMaxPropertyValue = result; + return result; + } catch (Exception e) { + throw new RuntimeException(e); + } + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ExplainResult.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ExplainResult.java index 379d3e901..39d95f5cf 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ExplainResult.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ExplainResult.java @@ -87,7 +87,9 @@ public static enum ExplainMode { // show statistic detail COST_TRACE, // show pipeline level stats - PIPELINE; + PIPELINE, + // show columnar snapshot + SNAPSHOT; public boolean isLogic() { return this == LOGIC || isSimple(); @@ -157,6 +159,10 @@ public boolean isPipeline() { return this == PIPELINE; } + public boolean isSnapshot() { + return this == SNAPSHOT; + } + public boolean isA(EnumSet enumSet) { return null != enumSet && enumSet.contains(this); } @@ -214,6 +220,10 @@ public static boolean isExplainPipeline(ExplainResult er) { return er != null && er.explainMode.isPipeline(); } + public static boolean isExplainSnapshot(ExplainResult er) { + return er != null && er.explainMode.isSnapshot(); + } + public static boolean isExplainVec(ExplainResult er) { return er == null ? false : er.explainMode.isVec(); } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ITransaction.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ITransaction.java index dab25517a..668eebea8 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ITransaction.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/ITransaction.java @@ -21,7 +21,6 @@ import com.alibaba.polardbx.common.jdbc.IDataSource; import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; import com.alibaba.polardbx.common.type.TransactionType; -import com.alibaba.polardbx.net.AbstractConnection; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.stats.CurrentTransactionStatistics; import com.alibaba.polardbx.stats.TransactionStatistics; @@ -188,4 +187,8 @@ default boolean isRwTransaction() { long getIdleROTimeout(); long getIdleRWTimeout(); + + default void clearFlashbackArea() { + + } } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/KeyWordsUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/KeyWordsUtil.java index 144d90fdc..0ac1f4525 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/KeyWordsUtil.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/KeyWordsUtil.java @@ -32,9 +32,6 @@ public class KeyWordsUtil { static { invalidKeyWords.addAll(MySQLKeywords.DEFAULT_KEYWORDS.getKeywords().keySet()); - invalidKeyWords.add(SystemDbHelper.DEFAULT_DB_NAME); - invalidKeyWords.add(SystemDbHelper.CDC_DB_NAME); -// invalidKeyWords.add(SystemDbHelper.COLUMNAR_DB_NAME); for (Token token : Token.values()) { if (!invalidKeyWords.contains(token.name())) { invalidKeyWords.add(token.name()); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/OptimizerUtils.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/OptimizerUtils.java index c0b31625c..e3a8164ba 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/OptimizerUtils.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/OptimizerUtils.java @@ -26,11 +26,14 @@ import com.alibaba.polardbx.common.model.sqljep.ComparativeOR; import com.alibaba.polardbx.common.model.sqljep.DynamicComparative; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.common.properties.ParamManager; import com.alibaba.polardbx.common.utils.ExecutorMode; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.druid.sql.ast.SqlType; +import com.alibaba.polardbx.optimizer.PlannerContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.planner.Planner; import com.alibaba.polardbx.optimizer.core.rel.LogicalView; @@ -39,18 +42,26 @@ import com.alibaba.polardbx.optimizer.optimizeralert.OptimizerAlertManager; import com.alibaba.polardbx.optimizer.optimizeralert.OptimizerAlertType; import com.alibaba.polardbx.optimizer.parse.bean.PreparedParamRef; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; import com.alibaba.polardbx.optimizer.partition.pruning.PartPrunedResult; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruneStep; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruneStepBuilder; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPruner; import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPrunerUtils; +import com.alibaba.polardbx.optimizer.partition.pruning.PhysicalPartitionInfo; import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; import com.alibaba.polardbx.rule.TableRule; +import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelVisitor; import org.apache.calcite.rel.logical.LogicalFilter; import org.apache.calcite.rel.logical.LogicalProject; import org.apache.calcite.rel.logical.LogicalSemiJoin; +import org.apache.calcite.rel.metadata.RelMetadataQuery; import org.apache.calcite.rex.RexDynamicParam; import org.apache.calcite.rex.RexNode; import org.apache.calcite.rex.RexUtil; @@ -73,6 +84,9 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.SortedMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.stream.Collectors; import static com.alibaba.polardbx.common.jdbc.ITransactionPolicy.TransactionClass.EXPLICIT_TRANSACTION; import static com.alibaba.polardbx.common.jdbc.ITransactionPolicy.TransactionClass.SUPPORT_SHARE_READVIEW_TRANSACTION; @@ -92,6 +106,29 @@ public static Date parseDate(String str, String[] parsePatterns) throws ParseExc } } + public static boolean hasDNHint(PlannerContext plannerContext) { + return plannerContext.getExtraCmds() != null && + plannerContext.getExtraCmds().containsKey(ConnectionProperties.DN_HINT); + } + + public static Map getParametersMapForOptimizer(RelNode rel) { + Parameters parameters = getParametersForOptimizer(rel); + Map params = parameters.getCurrentParameter(); + return params; + } + + public static Parameters getParametersForOptimizer(RelNode rel) { + return getParametersForOptimizer(PlannerContext.getPlannerContext(rel)); + } + + public static Parameters getParametersForOptimizer(PlannerContext context) { + Parameters parameters = RelMetadataQuery.THREAD_PARAMETERS.get(); + if (parameters == null) { + parameters = context.getParams(); + } + return parameters; + } + public static String buildInExprKey(Map currentParameter) { StringBuilder key = new StringBuilder(); for (int i = 1; i <= currentParameter.size(); i++) { @@ -396,6 +433,9 @@ boolean run(RelNode node) { public static Map>, Parameters> pruningInValue(LogicalView lv, ExecutionContext context) { + if (lv.hasTargetTableHint()) { + return null; + } if (!DynamicConfig.getInstance().isEnablePruningIn()) { return null; } @@ -462,6 +502,79 @@ public static Map>, Parameters> pruningInValue(Logical return null; } + public static SortedMap> pruningInValueForColumnar(LogicalView lv, + ExecutionContext context, + SortedMap multiVersionPartitionInfo) { + if (!DynamicConfig.getInstance().isEnablePruningIn()) { + return null; + } + Set shardIndexes = lv.getPushDownOpt().getShardRelatedInTypeParamIndexes(); + if (shardIndexes != null) { + // TODO(siyun): refactor duplicated codes + Pair[] rawStrings = findAllRawStrings(shardIndexes, context); + int maxPruneTime = + context.getParamManager().getInt(ConnectionParams.IN_PRUNE_MAX_TIME) / multiVersionPartitionInfo.size(); + Parameters requestParams = context.getParams(); + if (requestParams == null || rawStrings.length == 0) { + return null; + } + + // final result + SortedMap> allPruningResults = new ConcurrentSkipListMap<>(); + + // start pruning + long startTime = System.currentTimeMillis(); + + if (lv.isNewPartDbTbl()) { + // pruning + for (Map.Entry partitionInfoEntry : multiVersionPartitionInfo.entrySet()) { + PruningRawStringStep iterator = OptimizerUtils.iterateRawStrings(rawStrings, maxPruneTime); + if (iterator == null) { + return null; + } + Pair[] pruningPairArr = iterator.getTargetPair(); + + // reuse parameter and execution context for pruning + Parameters parameters = copy(requestParams, pruningPairArr, false); + Long tso = partitionInfoEntry.getKey(); + PartitionInfo partitionInfo = partitionInfoEntry.getValue(); + + Pair, Parameters>, List> pair = + pruningPartTable(lv, iterator, parameters, context, partitionInfo); + + if (pair == null) { + // meaning full scan + // TODO(siyun): optimize: for full scan, return null and deal it with all partitions + PartitionPruneStep fullScanStep = PartitionPruneStepBuilder.genFullScanPruneStepInfoInner( + partitionInfo, + partitionInfo.getPartitionBy().getPartLevel(), true + ); + PartPrunedResult tablePrunedResult = + PartitionPruner.doPruningByStepInfo(fullScanStep, context); + lv.filterBySelectedPartition(tablePrunedResult); + + allPruningResults.put(tso, tablePrunedResult.getPrunedParttions().stream().map( + PhysicalPartitionInfo::getPartName + ).collect(Collectors.toSet())); + } else { + // merge + allPruningResults.put(tso, mergePartTablePruningResultIntoPartNames(pair)); + } + } + } else { + throw new RuntimeException("CCI must be a new partition table"); + } + long endTime = System.currentTimeMillis(); + long pruningTime = endTime - startTime; + if (pruningTime > DynamicConfig.getInstance().getPruningTimeWarningThreshold()) { + OptimizerAlertManager.getInstance().log(OptimizerAlertType.PRUNING_SLOW, context); + } + context.addPruningTime(pruningTime); + return allPruningResults; + } + return null; + } + /** * pruning and merge result in a same iterator, this might be really slow */ @@ -554,6 +667,26 @@ private static Map simplePruning(LogicalView lv, ExecutionConte return bitSetMap; } + private static Set mergePartTablePruningResultIntoPartNames( + Pair, Parameters>, List> pair) { + Set partNames = Sets.newHashSet(); + Map, Parameters> pruningMapForPartTable = pair.getKey(); + List partPrunedResultsCache = pair.getValue(); + + // For CCI, each table scan has only one table + Preconditions.checkArgument(partPrunedResultsCache.size() == 1); + + for (Map.Entry, Parameters> entry : pruningMapForPartTable.entrySet()) { + // transform bitset to PartPrunedResult + PartPrunedResult partPrunedResultTmp = partPrunedResultsCache.get(0).copy(); + partPrunedResultTmp.setPartBitSet(entry.getKey().get(0)); + for (PhysicalPartitionInfo physicalPartitionInfo : partPrunedResultTmp.getPrunedParttions()) { + partNames.add(physicalPartitionInfo.getPartName()); + } + } + return partNames; + } + /** * merge pruning result for part table */ @@ -615,6 +748,14 @@ private static Pair, Parameters>, List> pruni PruningRawStringStep iterator, Parameters parameters, ExecutionContext context) { + return pruningPartTable(lv, iterator, parameters, context, null); + } + + public static Pair, Parameters>, List> pruningPartTable(LogicalView lv, + PruningRawStringStep iterator, + Parameters parameters, + ExecutionContext context, + PartitionInfo cciPartInfo) { boolean checked = false; List partPrunedResultsCache = null; ExecutionContext contextForInPruning = new ExecutionContext(context.getSchemaName()); @@ -630,7 +771,9 @@ private static Pair, Parameters>, List> pruni iterator.next(); // pruning part table - List partPrunedResults = lv.getPartPrunedResults(contextForInPruning); + List partPrunedResults = cciPartInfo == null ? + lv.getPartPrunedResults(contextForInPruning) : + lv.getCciPartPrunedResults(contextForInPruning, cciPartInfo); // transform PartPrunedResult to bitset list List physicalPartBitSet = Lists.newArrayList(); @@ -724,18 +867,23 @@ private static Parameters copy(Parameters parameters, Pair p : pruningPairArr) { - PruneRawString pruneRawString = p.getValue(); - ParameterContext pc = newParams.getCurrentParameter().get(p.getKey()); - ParameterContext newContext = new ParameterContext(); - newContext.setParameterMethod(pc.getParameterMethod()); - newContext.setArgs(new Object[] {p.getKey(), clonePruning ? pruneRawString.clone() : pruneRawString}); - newParams.getCurrentParameter().put(p.getKey(), newContext); + if (pruningPairArr != null) { + for (Pair p : pruningPairArr) { + PruneRawString pruneRawString = p.getValue(); + ParameterContext pc = newParams.getCurrentParameter().get(p.getKey()); + ParameterContext newContext = new ParameterContext(); + newContext.setParameterMethod(pc.getParameterMethod()); + newContext.setArgs(new Object[] {p.getKey(), clonePruning ? pruneRawString.clone() : pruneRawString}); + newParams.getCurrentParameter().put(p.getKey(), newContext); + } } return newParams; } public static PruningRawStringStep iterateRawStrings(Pair[] rawStrings, int maxPruneTime) { + if (rawStrings.length == 0) { + return null; + } if (rawStrings.length == 1) { Integer rawStringIndex = rawStrings[0].getKey(); RawString rawString = rawStrings[0].getValue(); @@ -941,6 +1089,14 @@ public static boolean useExplicitTransaction(ExecutionContext context) { return ret && ConfigDataMode.isMasterMode() && !isMppMode(context); } + public static boolean enableColumnarOptimizer(ParamManager paramManager) { + if (paramManager.getBoolean(ConnectionParams.ENABLE_COLUMNAR_OPTIMIZER)) { + return true; + } + return (paramManager.getBoolean(ConnectionParams.ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR) + && DynamicConfig.getInstance().existColumnarNodes()); + } + private static boolean isMppMode(ExecutionContext context) { return context.getExecuteMode() == ExecutorMode.MPP; } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/PartitionUtils.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/PartitionUtils.java new file mode 100644 index 000000000..68606aaaa --- /dev/null +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/PartitionUtils.java @@ -0,0 +1,193 @@ +package com.alibaba.polardbx.optimizer.utils; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.config.table.TableMeta; +import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil; +import com.alibaba.polardbx.optimizer.core.rel.LogicalView; +import com.alibaba.polardbx.optimizer.core.rel.util.TargetTableInfo; +import com.alibaba.polardbx.optimizer.core.rel.util.TargetTableInfoOneTable; +import com.alibaba.polardbx.optimizer.partition.PartSpecBase; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.optimizer.partition.PartitionSpec; +import com.alibaba.polardbx.optimizer.partition.pruning.PartPrunedResult; +import com.alibaba.polardbx.optimizer.partition.pruning.PartitionPrunerUtils; +import com.alibaba.polardbx.optimizer.rule.TddlRuleManager; +import org.apache.calcite.linq4j.Ord; +import org.apache.calcite.rel.RelFieldCollation; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.Sort; +import org.apache.calcite.util.ImmutableIntList; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import static com.alibaba.polardbx.common.exception.code.ErrorCode.ERR_EXECUTOR; + +public class PartitionUtils { + /** + * Determines whether the given logical view corresponds to a new partitioned table. + * + * @param logicalView The logical view object used to retrieve the logical table name and underlying physical table information. + * @return boolean Returns true if the table is both a new partitioned table and has been sharded; otherwise, returns false. + */ + public static boolean isNewPartShardTable(LogicalView logicalView) { + String tableName = logicalView.getLogicalTableName(); + TableMeta tm = CBOUtil.getTableMeta(logicalView.getTable()); + TddlRuleManager manger = OptimizerContext.getContext(tm.getSchemaName()).getRuleManager(); + if (!manger.getPartitionInfoManager().isNewPartDbTable(tableName) || !manger.isShard(tableName)) { + return false; + } + return true; + } + + /** + * Checks whether the partitions of a table are ordered as required. + * + * @param tableInfo An object containing partition usage and sorting status information for the table. + * @return boolean Returns true if the table's partitions are orderly; otherwise, returns false. + */ + public static boolean isTablePartOrdered(TargetTableInfoOneTable tableInfo) { + boolean useSubPart = tableInfo.isUseSubPart(); + if (!useSubPart) { + // If sub-partitions are not used, check if all partitions are sorted + if (tableInfo.isAllPartSorted()) { + return true; + } + } else { + // sub-partitions are used + // Check if every partition has only one subpartition after pruning + // Check if all partitions are sorted + if (tableInfo.isAllPrunedPartContainOnlyOneSubPart() + && tableInfo.isAllPartSorted()) { + return true; + } + // Check if the count of first-level partitions is 1 + // Check if all sub-partitions are sorted + if (tableInfo.getPrunedFirstLevelPartCount() == 1 + && tableInfo.isAllSubPartSorted()) { + return true; + } + } + return false; + } + + public static boolean isOrderKeyMatched(LogicalView logicalView, TargetTableInfoOneTable tableInfo) { + List partitionColumns = + tableInfo.isUseSubPart() ? tableInfo.getSubpartColList() : tableInfo.getPartColList(); + return isOrderKeyMatched(logicalView, partitionColumns); + } + + /** + * Checks whether the ordering keys in the logical view match the given partition columns. + * + * @param logicalView The LogicalView object containing the structure and optimized query information for the table to be checked. + * @param partitionColumns A list of partition column names to be verified against the ordering keys. + * @return Returns true if the ordering keys match the partition columns; otherwise, returns false. + */ + public static boolean isOrderKeyMatched(LogicalView logicalView, List partitionColumns) { + List partColumnRefs = new ArrayList<>(); + for (String partitionColumn : partitionColumns) { + partColumnRefs.add( + logicalView.getRefByColumnName(logicalView.getTableNames().get(0), partitionColumn, false, false)); + } + // part column not found in the logical view + if (partColumnRefs.stream().anyMatch(ref -> ref < 0)) { + return false; + } + RelNode pushedRelNode = logicalView.getOptimizedPushedRelNodeForMetaQuery(); + // pushed relNode is not sort, just return false + if (!(pushedRelNode instanceof Sort)) { + return false; + } + ImmutableIntList orderKeys = ((Sort) pushedRelNode).collation.getKeys(); + // The partition key should be a prefix of the sort key + if (partitionColumns.size() > orderKeys.size()) { + return false; + } + for (int i = 0; i < partColumnRefs.size(); ++i) { + if (!partColumnRefs.get(i).equals(orderKeys.get(i))) { + return false; + } + } + // ordered direction should be equal, otherwise split cannot be order + List collations = + ((Sort) pushedRelNode).collation.getFieldCollations().subList(0, partColumnRefs.size()); + long directionCount = collations.stream().map(col -> col.direction).distinct().count(); + if (directionCount > 1) { + return false; + } + return true; + } + + /** + * Calculates the partition number of the given logical table under the specified physical schema and physical table name. + * + * @param logicalSchema Name of the logical schema. + * @param logicalTableName Name of the logical table. + * @param physicalSchema Name of the physical schema. + * @param physicalTableName Name of the physical table. + * @return Partition number. Returns -1 if the corresponding partition is not found. + */ + public static int calcPartition(String logicalSchema, String logicalTableName, String physicalSchema, + String physicalTableName) { + // Retrieves the partition information for the specified logical table + PartitionInfo partInfo = + OptimizerContext.getContext(logicalSchema).getPartitionInfoManager().getPartitionInfo(logicalTableName); + + // Obtains the list of partition specifications + List partitionSpecs = partInfo.getPartitionBy().getPhysicalPartitions(); + + // Streams through partition specifications to find a match where the physical schema and physical table name equal the input parameters + int partition = partitionSpecs.stream().filter( + t -> t.getLocation().getGroupKey().equalsIgnoreCase(physicalSchema) + && t.getLocation().getPhyTableName().equalsIgnoreCase(physicalTableName)) + .findFirst().map(PartSpecBase::getPosition).map(Long::intValue).orElse(-1); + + // Adjusts and returns the found partition number, subtracting 1 to start counting from 0 + return partition - 1; + } + + public static boolean checkPrunedPartitionMonotonic(@NotNull LogicalView logicalView, + @NotNull List partitionResult) { + final TargetTableInfo targetTableInfo = + PartitionPrunerUtils.buildTargetTableInfoByPartPrunedResults(partitionResult); + + final TargetTableInfoOneTable tableInfo = targetTableInfo.getTargetTableInfoList().get(0); + if (!isTablePartOrdered(tableInfo)) { + return false; + } + if (!isOrderKeyMatched(logicalView, tableInfo)) { + return false; + } + + return true; + } + + @NotNull + public static List sortByPartitionOrder(String logicalSchemaName, String logicalTableName, + List> phySchemaAndPhyTables, boolean isDesc) { + final PartitionInfo partInfo = OptimizerContext + .getContext(logicalSchemaName) + .getPartitionInfoManager() + .getPartitionInfo(logicalTableName); + + //noinspection unchecked + final List partitions = Ord.zip(phySchemaAndPhyTables) + .stream() + .map(ord -> Pair.of( + partInfo.getPartSpecSearcher().getPartSpec(ord.e.getKey(), ord.e.getValue()).getPhyPartPosition(), + ord.i)) + .sorted((p1, p2) -> (int) (!isDesc ? p1.getKey() - p2.getKey() : p2.getKey() - p1.getKey())) + .map(Pair::getValue) + .collect(Collectors.toList()); + boolean notFoundPart = partitions.stream().anyMatch(part -> part < 0); + if (notFoundPart) { + throw new TddlRuntimeException(ERR_EXECUTOR, "not found partition info"); + } + return partitions; + } +} diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/PhyTableOperationUtil.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/PhyTableOperationUtil.java index b29f04c15..2ab69e2a3 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/PhyTableOperationUtil.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/PhyTableOperationUtil.java @@ -48,6 +48,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.IntStream; import static com.alibaba.polardbx.common.jdbc.ITransactionPolicy.TransactionClass.ALLOW_GROUP_PARALLELISM_WITHOUT_SHARE_READVIEW_TRANSACTION; import static com.alibaba.polardbx.common.jdbc.ITransactionPolicy.TransactionClass.SUPPORT_PARALLEL_GET_CONNECTION_TRANSACTION; @@ -404,13 +406,15 @@ private static Long tryFetchIntraGroupConnKeyFromPartSpec(String grpIdx, PartitionInfo partInfo) { PartSpecSearcher specSearcher = partInfo.getPartSpecSearcher(); Long connKey = specSearcher.getPartIntraGroupConnKey(grpIdx, phyTb); + + if (connKey == null || connKey == PartSpecSearcher.FOUND_NON_PARTITIONED_TBL) { + return null; + } if (connKey == PartSpecSearcher.NO_FOUND_PART_SPEC) { throw new TddlRuntimeException(ErrorCode.ERR_TRANS_FETCH_INTRA_GROUP_CONN_ID_FAIL, "invalid group or physical table names"); } - if (connKey == PartSpecSearcher.FOUND_NON_PARTITIONED_TBL) { - return null; - } + return connKey; } @@ -518,5 +522,25 @@ public static List buildGroConnSetFromGroups(ExecutionContext ec, List paramIndex = phyPlan.getParamIndex(); + + assert paramIndex.size() == phyPlan.getParam().size(); + final int physicalParamIndex = IntStream + .range(0, phyPlan.getParam().size()) + .filter(i -> paramIndex.get(i) == parameterizedParamIndex) + .map(i -> i + 1) + .findFirst() + .getAsInt(); + return physicalParamIndex; + } + //public static int calc } diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/PlannerUtils.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/PlannerUtils.java index ecbb5b743..55db3021e 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/PlannerUtils.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/PlannerUtils.java @@ -57,6 +57,7 @@ import com.google.common.collect.Sets; import org.apache.calcite.plan.RelOptRuleCall; import org.apache.calcite.plan.RelOptUtil; +import org.apache.calcite.rel.core.Aggregate; import org.apache.calcite.rel.core.AggregateCall; import org.apache.calcite.rel.core.GroupConcatAggregateCall; import org.apache.calcite.rel.core.Project; @@ -404,8 +405,8 @@ public static boolean allTableSingle(List tableName, String schemaName, // Check if all tables are single table or broadcast table PartitionInfo partInfo = tddlRuleManager.getPartitionInfoManager().getPartitionInfo(table); if (partInfo != null) { - if (!partInfo.isSingleTable() || !partInfo.isBroadcastTable()) { - // For partitioned/gsi table, check if only has only one partitions + if (!partInfo.isSingleTable() && !partInfo.isBroadcastTable()) { + // For partitioned/gsi table, check if it has only one partitions if (!partInfo.isSinglePartition()) { return false; } @@ -510,6 +511,16 @@ public static ParameterContext changeParameterContextIndex(ParameterContext oldP return pc; } + public static ParameterContext changeParameterContextValue(ParameterContext oldPc, Object value) { + ParameterContext pc = new ParameterContext(); + pc.setParameterMethod(oldPc.getParameterMethod()); + Object[] args = oldPc.getArgs(); + Object[] newArgs = Arrays.copyOf(args, args.length); + newArgs[1] = value; + pc.setArgs(newArgs); + return pc; + } + /** * 获取 SqlNode 中 SqlDynamicParam 节点对应的 index 值 */ @@ -797,7 +808,7 @@ public static boolean shouldNotPushDistinctAgg(LogicalAggregate agg, List shardIndex, LogicalAggregate aggregate) { + public static boolean canSplitDistinct(Set shardIndex, Aggregate aggregate) { boolean enableSplitDistinct = true; for (int i = 0; i < aggregate.getAggCallList().size(); ++i) { AggregateCall aggregateCall = aggregate.getAggCallList().get(i); diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/QueryConcurrencyPolicy.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/QueryConcurrencyPolicy.java index 0ae147a66..514db5c17 100644 --- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/QueryConcurrencyPolicy.java +++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/QueryConcurrencyPolicy.java @@ -32,6 +32,11 @@ public enum QueryConcurrencyPolicy { */ CONCURRENT, + /** + * DDL分表级并发 + */ + DDL_CONCURRENT, + /** * 宽松的库间并发,适用于Auto数据库的分片的读写 *
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/RelUtils.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/RelUtils.java
index 7328c3ea7..58e75e763 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/RelUtils.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/RelUtils.java
@@ -27,6 +27,7 @@
 import com.alibaba.polardbx.common.model.sqljep.Comparative;
 import com.alibaba.polardbx.common.model.sqljep.ComparativeAND;
 import com.alibaba.polardbx.common.model.sqljep.ComparativeOR;
+import com.alibaba.polardbx.common.properties.ConnectionParams;
 import com.alibaba.polardbx.common.properties.ConnectionProperties;
 import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.common.utils.TStringUtil;
@@ -66,6 +67,7 @@
 import com.alibaba.polardbx.optimizer.core.rel.PhyQueryOperation;
 import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation;
 import com.alibaba.polardbx.optimizer.core.rel.SingleTableOperation;
+import com.alibaba.polardbx.optimizer.core.rel.ToDrdsRelVisitor;
 import com.alibaba.polardbx.optimizer.core.rel.dal.BaseDalOperation;
 import com.alibaba.polardbx.optimizer.core.rel.dal.LogicalShow;
 import com.alibaba.polardbx.optimizer.parse.custruct.FastSqlConstructUtils;
@@ -87,6 +89,7 @@
 import org.apache.calcite.linq4j.Ord;
 import org.apache.calcite.plan.Convention;
 import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptRuleOperand;
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.hep.HepRelVertex;
@@ -136,6 +139,7 @@
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexShuttle;
 import org.apache.calcite.rex.RexSubQuery;
+import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlCharStringLiteral;
@@ -180,6 +184,7 @@
 import java.util.TreeMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Function;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -826,6 +831,74 @@ public static void forbidDMLAllTableSql(SqlNode sqlNode) {
         }
     }
 
+    /**
+     * Check plan matches specified structure and return binding operands
+     *
+     * @param plan plan to be tested
+     * @param operand plan structure
+     * @param bindings for return binding operands
+     * @param checker more check after plan structure matched
+     */
+    public static boolean matchPlan(RelNode plan,
+                                    RelOptRuleOperand operand,
+                                    List bindings,
+                                    Predicate checker) {
+        boolean planStructureMatched = matchOperands(plan, operand, bindings);
+        return planStructureMatched && (null == checker || checker.test(plan));
+    }
+
+    /**
+     * Match plan structure
+     *
+     * @param rel plan to be tested
+     * @param operand plan structure
+     * @param bindings for return binding operands
+     */
+    private static boolean matchOperands(RelNode rel, RelOptRuleOperand operand, List bindings) {
+        if (!operand.matches(rel)) {
+            return false;
+        }
+        bindings.add(rel);
+
+        final List childRels = rel.getInputs();
+
+        switch (operand.childPolicy) {
+        case ANY:
+            return true;
+        case UNORDERED:
+            // For each operand, at least one child must match. If
+            // matchAnyChildren, usually there's just one operand.
+            for (RelOptRuleOperand childOperand : operand.getChildOperands()) {
+                boolean match = false;
+                for (RelNode childRel : childRels) {
+                    match =
+                        matchOperands(childRel, childOperand, bindings);
+                    if (match) {
+                        break;
+                    }
+                }
+                if (!match) {
+                    return false;
+                }
+            }
+            return true;
+        default:
+            int n = operand.getChildOperands().size();
+            if (childRels.size() < n) {
+                return false;
+            }
+            for (Pair pair
+                : Pair.zip(childRels, operand.getChildOperands())) {
+                boolean match =
+                    matchOperands(pair.left, pair.right, bindings);
+                if (!match) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
     static class CacheFinder extends RelVisitor {
 
         List cacheNodes = Lists.newArrayList();
@@ -878,6 +951,48 @@ public static List findCacheNodes(RelNode node) {
         return new CacheFinder().findCacheNodes(node);
     }
 
+    public static boolean findCorrelate(RelNode node) {
+        if (PlannerContext.getPlannerContext(node).getParamManager()
+            .getBoolean(ConnectionParams.ENABLE_COLUMNAR_CORRELATE)) {
+            return false;
+        }
+        try {
+            new RelVisitor() {
+                public void visit(RelNode node, int ordinal, RelNode parent) {
+                    if (node instanceof Correlate) {
+                        throw Util.FoundOne.NULL;
+                    }
+                    if (node instanceof LogicalView) {
+                        if (!((LogicalView) node).getScalarList().isEmpty()) {
+                            throw Util.FoundOne.NULL;
+                        }
+                        visit(((LogicalView) node).getPushedRelNode(), 0, node);
+                        return;
+                    }
+
+                    if (node instanceof Join) {
+                        if (RexUtil.hasSubQuery(((Join) node).getCondition())) {
+                            throw Util.FoundOne.NULL;
+                        }
+                    } else if (node instanceof LogicalProject) {
+                        if (!RelOptUtil.notSubquery(((LogicalProject) node))) {
+                            throw Util.FoundOne.NULL;
+                        }
+                    } else if (node instanceof LogicalFilter) {
+                        if (RexUtil.hasSubQuery(((LogicalFilter) node).getCondition())) {
+                            throw Util.FoundOne.NULL;
+                        }
+                    }
+                    super.visit(node, ordinal, parent);
+
+                }
+            }.go(node);
+            return false;
+        } catch (Util.FoundOne e) {
+            return true;
+        }
+    }
+
     /**
      * Are all tables are single and in the group specified by singleDbIndex
      */
@@ -1360,7 +1475,7 @@ public boolean hasGsi() {
             if (!needCheckGsi) {
                 return false;
             } else {
-                return GlobalIndexMeta.hasIndex(tableName, schemaName, ec);
+                return GlobalIndexMeta.hasGsi(tableName, schemaName, ec);
             }
 
         }
@@ -1690,20 +1805,59 @@ public static boolean isSimpleMergeSortPlan(RelNode plan) {
         return (plan instanceof MergeSort && ((MergeSort) plan).getInput() instanceof LogicalView);
     }
 
-    public static boolean existUnPushableLastInsertId(RelNode node) {
+    // select 中 last_insert_id 不可下推
+    // 不可下推的 DML 中,last_insert_id 不可下推 (带有GSI,Scale-out,拆分键变更(DDL),修改分区键,广播表)
+    public static boolean existUnPushableLastInsertId(ExecutionPlan plan) {
+        final boolean isModifyShardingColumn =
+            plan.getPlanProperties().get(ExecutionPlanProperties.MODIFY_SHARDING_COLUMN);
+        final boolean modifyGsiTable = plan.getPlanProperties().get(ExecutionPlanProperties.MODIFY_GSI_TABLE);
+        final boolean modifyScaleOutTable =
+            plan.getPlanProperties().get(ExecutionPlanProperties.SCALE_OUT_WRITABLE_TABLE);
+        final boolean modifyOnlineColumnTable =
+            plan.getPlanProperties().get(ExecutionPlanProperties.MODIFY_ONLINE_COLUMN_TABLE);
+        final boolean modifyBroadcastTable =
+            plan.getPlanProperties().get(ExecutionPlanProperties.MODIFY_BROADCAST_TABLE);
+
+        return existUnPushableLastInsertId(plan.getPlan(), isModifyShardingColumn, modifyGsiTable, modifyScaleOutTable,
+            modifyOnlineColumnTable, modifyBroadcastTable);
+
+    }
+
+    public static boolean existUnPushableLastInsertId(RelNode relNode, ToDrdsRelVisitor visitor) {
+        return existUnPushableLastInsertId(relNode, visitor.isModifyShardingColumn(),
+            visitor.isModifyShardingColumn(),
+            visitor.isContainScaleOutWritableTable(),
+            visitor.isContainOnlineModifyColumnTable(), visitor.isModifyBroadcastTable());
+    }
+
+    public static boolean existUnPushableLastInsertId(RelNode relNode,
+                                                      boolean isModifyShardingColumn,
+                                                      boolean modifyGsiTable,
+                                                      boolean modifyScaleOutTable,
+                                                      boolean modifyOnlineColumnTable,
+                                                      boolean modifyBroadcastTable) {
+        PlannerContext context = PlannerContext.getPlannerContext(relNode);
+        /**
+         * Non push down dml rule by
+         * {@link PushModifyRule#matches}.
+         */
+        return existLastInsertId(relNode) &&
+            (isModifyShardingColumn ||
+                modifyGsiTable ||
+                modifyScaleOutTable ||
+                modifyBroadcastTable ||
+                (context.getSqlKind() == SqlKind.UPDATE && modifyOnlineColumnTable) ||
+                context.getSqlKind() == SqlKind.SELECT
+            );
+    }
+
+    public static boolean existLastInsertId(RelNode node) {
         class CheckUnPushableRelVisitor extends RelVisitor {
             private boolean exists = false;
-            private final PlannerContext context = PlannerContext.getPlannerContext(node);
 
             @Override
             public void visit(RelNode relNode, int ordinal, RelNode parent) {
-
-                if (relNode instanceof Project) {
-                    exists = isNotPushLastInsertId(context, (Project) relNode) || exists;
-                } else if (relNode instanceof Filter) {
-                    exists = isNotPushLastInsertId(context, (Filter) relNode) || exists;
-                }
-
+                exists = isLastInsertId(relNode) || exists;
                 super.visit(relNode, ordinal, parent);
             }
 
@@ -1717,22 +1871,15 @@ public boolean exists() {
         return checkUnPushableRelVisitor.exists();
     }
 
-    // select 中 last_insert_id 不可下推
-    // 不可下推的 DML 中,last_insert_id 不可下推 (带有GSI,Scale-out,拆分键变更(DDL),修改分区键,广播表)
-    public static boolean isNotPushLastInsertId(PlannerContext context, Project project) {
-        return isNotPushLastInertIdExps(context, project.getChildExps());
-    }
-
-    public static boolean isNotPushLastInsertId(PlannerContext context, Filter filter) {
-        return isNotPushLastInertIdExps(context, filter.getChildExps());
-    }
-
-    private static boolean isNotPushLastInertIdExps(PlannerContext context, List childExps) {
-        final boolean isModifyShardingColumn = context.getExecutionContext().isModifyShardingColumn();
-        final boolean modifyGsiTable = context.getExecutionContext().isModifyGsiTable();
-        final boolean modifyScaleoutTable = context.getExecutionContext().isScaleoutWritableTable();
-        final boolean modifyOnlineColumnTable = context.getExecutionContext().isModifyOnlineColumnTable();
-        final boolean modifyBroadcastTable = context.getExecutionContext().isModifyBroadcastTable();
+    private static boolean isLastInsertId(RelNode relNode) {
+        List childExps;
+        if (relNode instanceof Project) {
+            childExps = ((Project) relNode).getChildExps();
+        } else if (relNode instanceof Filter) {
+            childExps = ((Filter) relNode).getChildExps();
+        } else {
+            return false;
+        }
 
         boolean operands = false;
         boolean isLastInsertId = false;
@@ -1742,19 +1889,8 @@ private static boolean isNotPushLastInertIdExps(PlannerContext context, List bindPlan(LogicalModify modify);
+
+        LogicalModifyView buildForPrimary(List bindings);
+    }
+
+    public static class FlashbackVisitor extends RelShuttleImpl {
+        private boolean containFlashback = false;
+
+        @Override
+        public RelNode visit(TableScan scan) {
+            if (containFlashback) {
+                return scan;
+            }
+            if (scan.getFlashback() != null) {
+                containFlashback = true;
+                return scan;
+            }
+            return super.visit(scan);
+        }
+
+        public boolean isContainFlashback() {
+            return containFlashback;
+        }
+    }
+
+    /**
+     * 查询是否包含flashback
+     */
+    public static boolean containFlashback(RelNode relNode) {
+        FlashbackVisitor visitor = new FlashbackVisitor();
+        relNode.accept(visitor);
+        return visitor.isContainFlashback();
+    }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/RexUtils.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/RexUtils.java
index d3a4619ea..c8a09af56 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/RexUtils.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/RexUtils.java
@@ -275,27 +275,7 @@ public static void updateParam(LogicalInsert insert, ExecutionContext ec, boolea
         TableMeta tableMeta = ec.getSchemaManager(schemaName).getTable(tableName);
 
         // Handle default expr
-        if (tableMeta.hasDefaultExprColumn() && InstanceVersion.isMYSQL80()) {
-            final Function evalFunc = getEvalFunc(ec);
-            for (int i = 0; i < insert.getDefaultExprColRexNodes().size(); i++) {
-                ColumnMeta columnMeta = insert.getDefaultExprColMetas().get(i);
-                RexNode rexNode = insert.getDefaultExprColRexNodes().get(i);
-                Object value = evalFunc.apply(rexNode);
-                if (value instanceof Slice) {
-                    if (isBinaryReturnType(rexNode)) {
-                        value = ((Slice) value).getBytes();
-                    } else {
-                        value = ((Slice) value).toString(CharsetName.DEFAULT_STORAGE_CHARSET_IN_CHUNK);
-                    }
-                } else if (value instanceof ByteString) {
-                    value = ((ByteString) value).getBytes();
-                }
-                if (!columnMeta.isNullable() && value == null) {
-                    throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR,
-                        String.format("Column `%s` cannot be null", columnMeta.getName()));
-                }
-            }
-        }
+        handleDefaultExpr(tableMeta, insert, ec);
 
         // Handle generated column
         if (tableMeta.hasLogicalGeneratedColumn()) {
@@ -434,6 +414,36 @@ public static void updateParam(LogicalInsert insert, ExecutionContext ec, boolea
         }
     }
 
+    public static void handleDefaultExpr(TableMeta tableMeta, LogicalInsert insert, ExecutionContext ec) {
+        if (tableMeta.hasDefaultExprColumn() && InstanceVersion.isMYSQL80()) {
+            final Function evalFunc = getEvalFunc(ec);
+            for (int i = 0; i < insert.getDefaultExprColRexNodes().size(); i++) {
+                ColumnMeta columnMeta = insert.getDefaultExprColMetas().get(i);
+                RexNode rexNode = insert.getDefaultExprColRexNodes().get(i);
+                try {
+                    Object value = evalFunc.apply(rexNode);
+
+                    if (value instanceof Slice) {
+                        if (isBinaryReturnType(rexNode)) {
+                            value = ((Slice) value).getBytes();
+                        } else {
+                            value = ((Slice) value).toString(CharsetName.DEFAULT_STORAGE_CHARSET_IN_CHUNK);
+                        }
+                    } else if (value instanceof ByteString) {
+                        value = ((ByteString) value).getBytes();
+                    }
+                    if (!columnMeta.isNullable() && value == null) {
+                        throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR,
+                            String.format("Column `%s` cannot be null", columnMeta.getName()));
+                    }
+                } catch (UnsupportedOperationException e) {
+                    throw new TddlRuntimeException(ErrorCode.ERR_FUNCTION_NOT_FOUND,
+                        "No match found for function signature " + ((RexCall) rexNode).getOperands().get(0).toString());
+                }
+            }
+        }
+    }
+
     public static Object convertValue(Object value, DataType dataType, boolean strict, ColumnMeta columnMeta,
                                       ExecutionContext ec) {
         if (value == null) {
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/mppchecker/MppPlanCheckerInput.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/mppchecker/MppPlanCheckerInput.java
index 24e6242f5..579570b94 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/mppchecker/MppPlanCheckerInput.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/mppchecker/MppPlanCheckerInput.java
@@ -17,15 +17,18 @@
 package com.alibaba.polardbx.optimizer.utils.mppchecker;
 
 import com.alibaba.polardbx.optimizer.PlannerContext;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import org.apache.calcite.rel.RelNode;
 
 public class MppPlanCheckerInput {
     private final RelNode originalPlan;
     private final PlannerContext plannerContext;
+    private final ExecutionContext executionContext;
 
-    public MppPlanCheckerInput(RelNode originalPlan, PlannerContext plannerContext) {
+    public MppPlanCheckerInput(RelNode originalPlan, PlannerContext plannerContext, ExecutionContext executionContext) {
         this.originalPlan = originalPlan;
         this.plannerContext = plannerContext;
+        this.executionContext = executionContext;
     }
 
     public RelNode getOriginalPlan() {
@@ -35,4 +38,8 @@ public RelNode getOriginalPlan() {
     public PlannerContext getPlannerContext() {
         return plannerContext;
     }
+
+    public ExecutionContext getExecutionContext() {
+        return executionContext;
+    }
 }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/mppchecker/MppPlanCheckers.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/mppchecker/MppPlanCheckers.java
index 3f696aaad..a8fa92b03 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/mppchecker/MppPlanCheckers.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/utils/mppchecker/MppPlanCheckers.java
@@ -22,6 +22,7 @@
 import com.alibaba.polardbx.optimizer.PlannerContext;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.utils.ExplainResult;
+import com.alibaba.polardbx.optimizer.utils.OptimizerUtils;
 import com.alibaba.polardbx.optimizer.utils.RelUtils;
 import com.google.common.collect.Lists;
 import org.apache.calcite.rel.RelNode;
@@ -34,27 +35,27 @@
 import static com.alibaba.polardbx.common.jdbc.ITransactionPolicy.TransactionClass.EXPLICIT_TRANSACTION;
 
 public class MppPlanCheckers {
-    public static final MppPlanChecker MPP_ENABLED_CHECKER = input -> input.getPlannerContext()
+    public static final MppPlanChecker MPP_ENABLED_CHECKER = input -> input.getExecutionContext()
         .getParamManager()
         .getBoolean(ConnectionParams.ENABLE_MPP);
 
     public static final MppPlanChecker TRANSACTION_CHECKER =
-        input -> Optional.ofNullable(input.getPlannerContext().getExecutionContext())
+        input -> Optional.ofNullable(input.getExecutionContext())
             .map(MppPlanCheckers::mppSupportTransaction)
             .orElse(true);
 
     public static final MppPlanChecker COLUMNAR_TRANSACTION_CHECKER =
-        input -> Optional.ofNullable(input.getPlannerContext().getExecutionContext())
+        input -> Optional.ofNullable(input.getExecutionContext())
             .map(MppPlanCheckers::columnarSupportTransaction)
             .orElse(true);
 
     public static final MppPlanChecker UPDATE_CHECKER =
-        input -> Optional.of(input.getPlannerContext().getExecutionContext())
+        input -> Optional.of(input.getExecutionContext())
             .map(c -> c.getSqlType() != SqlType.SELECT_FOR_UPDATE)
             .orElse(true);
 
     public static final MppPlanChecker INTERNAL_SYSTEM_SQL_CHECKER =
-        input -> Optional.ofNullable(input.getPlannerContext().getExecutionContext())
+        input -> Optional.ofNullable(input.getExecutionContext())
             .map(c -> !c.isInternalSystemSql())
             .orElse(true);
 
@@ -66,16 +67,13 @@ public class MppPlanCheckers {
 
     public static final MppPlanChecker CTE_CHECKER = input -> !input.getPlannerContext().isHasRecursiveCte();
 
-    public static final MppPlanChecker SIMPLE_QUERY_PLAN_CHECKER =
-        input -> !RelUtils.isSimpleQueryPlan(input.getOriginalPlan());
-
     public static final MppPlanChecker EXPLAIN_EXECUTE_CHECKER =
-        input -> Optional.ofNullable(input.getPlannerContext().getExecutionContext())
+        input -> Optional.ofNullable(input.getExecutionContext())
             .map(c -> !ExplainResult.isExplainExecute(c.getExplain()))
             .orElse(true);
 
     public static final MppPlanChecker EXPLAIN_STATISTICS_CHECKER =
-        input -> Optional.ofNullable(input.getPlannerContext().getExecutionContext())
+        input -> Optional.ofNullable(input.getExecutionContext())
             .map(c -> !ExplainResult.isExplainStatistics(c.getExplain()))
             .orElse(true);
 
@@ -88,9 +86,11 @@ public class MppPlanCheckers {
             && input.getPlannerContext().getParamManager()
             .getFloat(ConnectionParams.SAMPLE_PERCENTAGE) <= 100F);
 
-    public static final MppPlanChecker ENABLE_COLUMNAR_CHECKER = input -> input.getPlannerContext()
-        .getParamManager()
-        .getBoolean(ConnectionParams.ENABLE_COLUMNAR_OPTIMIZER);
+    public static final MppPlanChecker ENABLE_COLUMNAR_CHECKER = input ->
+        (OptimizerUtils.enableColumnarOptimizer(input.getExecutionContext().getParamManager()));
+
+    public static final MppPlanChecker CORRELATE_CHECKER = input ->
+        (!RelUtils.findCorrelate(input.getOriginalPlan()));
 
     public static final MppPlanChecker BASIC_CHECKERS =
         input -> Lists.newArrayList(MPP_ENABLED_CHECKER, SUBQUERY_CHECKER, QUERY_CHECKER, INTERNAL_SYSTEM_SQL_CHECKER,
@@ -98,8 +98,9 @@ public class MppPlanCheckers {
             .stream()
             .allMatch(c -> c.supportsMpp(input));
 
-    public static boolean supportsMppPlan(RelNode plan, PlannerContext context, MppPlanChecker... checkers) {
-        MppPlanCheckerInput input = new MppPlanCheckerInput(plan, context);
+    public static boolean supportsMppPlan(RelNode plan, PlannerContext context, ExecutionContext ec,
+                                          MppPlanChecker... checkers) {
+        MppPlanCheckerInput input = new MppPlanCheckerInput(plan, context, ec);
 
         return Arrays.stream(checkers)
             .allMatch(c -> c.supportsMpp(input));
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaDdlEngineResources.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaDdlEngineResources.java
new file mode 100644
index 000000000..0ec5fbcb9
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaDdlEngineResources.java
@@ -0,0 +1,49 @@
+package com.alibaba.polardbx.optimizer.view;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
+import org.apache.calcite.sql.type.SqlTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by chenghui.lch
+ *
+ * @author chenghui.lch
+ */
+public class InformationSchemaDdlEngineResources extends VirtualView {
+
+    protected InformationSchemaDdlEngineResources(RelOptCluster cluster,
+                                                  RelTraitSet traitSet) {
+        super(cluster, traitSet, VirtualViewType.DDL_ENGINE_RESOURCE);
+    }
+
+    public InformationSchemaDdlEngineResources(RelInput input) {
+        super(input);
+    }
+
+    @Override
+    protected RelDataType deriveRowType() {
+        final RelDataTypeFactory typeFactory = getCluster().getTypeFactory();
+        List columns = new ArrayList<>();
+
+        int columnIndex = 0;
+        columns.add(new RelDataTypeFieldImpl("HOST", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("RESOURCE_TYPE", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("TOTAL_AMOUNT", columnIndex++, typeFactory.createSqlType(SqlTypeName.BIGINT)));
+        columns.add(
+            new RelDataTypeFieldImpl("RESIDUE", columnIndex++, typeFactory.createSqlType(SqlTypeName.BIGINT)));
+        columns.add(
+            new RelDataTypeFieldImpl("ACTIVE_TASK", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("DETAIL", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        return typeFactory.createStructType(columns);
+    }
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaDdlScheduler.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaDdlScheduler.java
new file mode 100644
index 000000000..c1a5ff46c
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaDdlScheduler.java
@@ -0,0 +1,55 @@
+package com.alibaba.polardbx.optimizer.view;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
+import org.apache.calcite.sql.type.SqlTypeName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by chenghui.lch
+ *
+ * @author chenghui.lch
+ */
+public class InformationSchemaDdlScheduler extends VirtualView {
+
+    protected InformationSchemaDdlScheduler(RelOptCluster cluster,
+                                            RelTraitSet traitSet) {
+        super(cluster, traitSet, VirtualViewType.DDL_SCHEDULER);
+    }
+
+    public InformationSchemaDdlScheduler(RelInput input) {
+        super(input);
+    }
+
+    @Override
+    protected RelDataType deriveRowType() {
+        final RelDataTypeFactory typeFactory = getCluster().getTypeFactory();
+        List columns = new ArrayList<>();
+
+        int columnIndex = 0;
+        columns.add(new RelDataTypeFieldImpl("JOB_ID", columnIndex++, typeFactory.createSqlType(SqlTypeName.BIGINT)));
+        columns.add(new RelDataTypeFieldImpl("TASK_ID", columnIndex++, typeFactory.createSqlType(SqlTypeName.BIGINT)));
+        columns.add(
+            new RelDataTypeFieldImpl("TASK_STATE", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("TASK_NAME", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("TASK_INFO", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("EXECUTION_TIME", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("NODE_IP", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("RESOURCES", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("EXTRAS", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("DDL_STMT", columnIndex++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        return typeFactory.createStructType(columns);
+    }
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaDeadlocks.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaDeadlocks.java
new file mode 100644
index 000000000..051891d83
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaDeadlocks.java
@@ -0,0 +1,34 @@
+package com.alibaba.polardbx.optimizer.view;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
+import org.apache.calcite.sql.type.SqlTypeName;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class InformationSchemaDeadlocks extends VirtualView {
+    public InformationSchemaDeadlocks(RelOptCluster cluster, RelTraitSet traitSet) {
+        super(cluster, traitSet, VirtualViewType.DEADLOCKS);
+    }
+
+    public InformationSchemaDeadlocks(RelInput relInput) {
+        super(relInput);
+    }
+
+    @Override
+    protected RelDataType deriveRowType() {
+        final RelDataTypeFactory typeFactory = getCluster().getTypeFactory();
+        List columns = new LinkedList<>();
+        columns.add(new RelDataTypeFieldImpl("ID", 0, typeFactory.createSqlType(SqlTypeName.BIGINT)));
+        columns.add(new RelDataTypeFieldImpl("TYPE", 1, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("GMT_CREATED", 2, typeFactory.createSqlType(SqlTypeName.TIMESTAMP)));
+        columns.add(new RelDataTypeFieldImpl("LOG", 3, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        return typeFactory.createStructType(columns);
+    }
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaMetric.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaMetric.java
new file mode 100644
index 000000000..2713dde35
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaMetric.java
@@ -0,0 +1,40 @@
+package com.alibaba.polardbx.optimizer.view;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
+import org.apache.calcite.sql.type.SqlTypeName;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author fangwu
+ */
+public class InformationSchemaMetric extends VirtualView {
+
+    public InformationSchemaMetric(RelOptCluster cluster, RelTraitSet traitSet) {
+        super(cluster, traitSet, VirtualViewType.METRIC);
+    }
+
+    public InformationSchemaMetric(RelInput relInput) {
+        super(relInput);
+    }
+
+    @Override
+    protected RelDataType deriveRowType() {
+        final RelDataTypeFactory typeFactory = getCluster().getTypeFactory();
+        List columns = new LinkedList<>();
+        int index = 0;
+        columns.add(new RelDataTypeFieldImpl("INST", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("HOST", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("NAME", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("TYPE", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("VALUE", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        return typeFactory.createStructType(columns);
+    }
+}
+
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaPartitionsMeta.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaPartitionsMeta.java
index c15ebd525..db6cf9d99 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaPartitionsMeta.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaPartitionsMeta.java
@@ -46,39 +46,48 @@ protected RelDataType deriveRowType() {
         final RelDataTypeFactory typeFactory = getCluster().getTypeFactory();
         List columns = new LinkedList<>();
 
-        columns.add(new RelDataTypeFieldImpl("PART_NUM", 0, typeFactory.createSqlType(SqlTypeName.BIGINT)));
+        int colIdx = -1;
+        columns.add(new RelDataTypeFieldImpl("PART_NUM", ++colIdx, typeFactory.createSqlType(SqlTypeName.BIGINT)));
 
-        columns.add(new RelDataTypeFieldImpl("TABLE_SCHEMA", 1, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("TABLE_NAME", 2, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("INDEX_NAME", 3, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("PRIM_TABLE", 4, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("TABLE_TYPE", 5, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("TG_NAME", 6, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("TABLE_SCHEMA", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("TABLE_NAME", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("INDEX_NAME", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("PRIM_TABLE", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("TABLE_TYPE", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("TG_NAME", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
 
-        columns.add(new RelDataTypeFieldImpl("PART_METHOD", 7, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("PART_COL", 8, typeFactory.createSqlType(SqlTypeName.BIGINT)));
-        columns.add(new RelDataTypeFieldImpl("PART_COL_TYPE", 9, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("PART_EXPR", 10, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        //columns.add(new RelDataTypeFieldImpl("PART_BOUND_TYPE", 8, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("PART_NAME", 11, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("PART_POSI", 12, typeFactory.createSqlType(SqlTypeName.BIGINT)));
-        columns.add(new RelDataTypeFieldImpl("PART_DESC", 13, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("PART_METHOD", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("PART_COL", ++colIdx, typeFactory.createSqlType(SqlTypeName.BIGINT)));
+        columns.add(
+            new RelDataTypeFieldImpl("PART_COL_TYPE", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("PART_EXPR", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        //columns.add(new RelDataTypeFieldImpl("PART_BOUND_TYPE", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("PART_NAME", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("PART_POSI", ++colIdx, typeFactory.createSqlType(SqlTypeName.BIGINT)));
+        columns.add(new RelDataTypeFieldImpl("PART_DESC", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("PART_ARC_STATE", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
 
-        columns.add(new RelDataTypeFieldImpl("SUBPART_METHOD", 14, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("SUBPART_COL", 15, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("SUBPART_COL_TYPE", 16, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("SUBPART_EXPR", 17, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        //columns.add(new RelDataTypeFieldImpl("SUBPART_BOUND_TYPE", 8, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("SUBPART_NAME", 18, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("SUBPART_TEMP_NAME", 19, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("SUBPART_POSI", 20, typeFactory.createSqlType(SqlTypeName.BIGINT)));
-        columns.add(new RelDataTypeFieldImpl("SUBPART_DESC", 21, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("SUBPART_METHOD", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("SUBPART_COL", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("SUBPART_COL_TYPE", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("SUBPART_EXPR", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        //columns.add(new RelDataTypeFieldImpl("SUBPART_BOUND_TYPE", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("SUBPART_NAME", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("SUBPART_TEMP_NAME", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("SUBPART_POSI", ++colIdx, typeFactory.createSqlType(SqlTypeName.BIGINT)));
+        columns.add(new RelDataTypeFieldImpl("SUBPART_DESC", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("SUBPART_ARC_STATE", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
 
-        columns.add(new RelDataTypeFieldImpl("PG_NAME", 22, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("PHY_GROUP", 23, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("PHY_DB", 24, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("PHY_TB", 25, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
-        columns.add(new RelDataTypeFieldImpl("RW_DN", 26, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("PG_NAME", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("PHY_GROUP", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("PHY_DB", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("PHY_TB", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("RW_DN", ++colIdx, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
 
         return typeFactory.createStructType(columns);
     }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaRplSyncPoint.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaRplSyncPoint.java
new file mode 100644
index 000000000..ec0491788
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaRplSyncPoint.java
@@ -0,0 +1,40 @@
+package com.alibaba.polardbx.optimizer.view;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
+import org.apache.calcite.sql.type.SqlTypeName;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author yudong
+ * @since 2024/6/18 15:40
+ **/
+public class InformationSchemaRplSyncPoint extends VirtualView {
+
+    protected InformationSchemaRplSyncPoint(RelOptCluster cluster, RelTraitSet traitSet) {
+        super(cluster, traitSet, VirtualViewType.RPL_SYNC_POINT);
+    }
+
+    public InformationSchemaRplSyncPoint(RelInput relInput) {
+        super(relInput);
+    }
+
+    @Override
+    protected RelDataType deriveRowType() {
+        final RelDataTypeFactory typeFactory = getCluster().getTypeFactory();
+        List columns = new LinkedList<>();
+
+        columns.add(new RelDataTypeFieldImpl("ID", 0, typeFactory.createSqlType(SqlTypeName.BIGINT)));
+        columns.add(new RelDataTypeFieldImpl("PRIMARY_TSO", 1, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("SECONDARY_TSO", 2, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("CREATE_TIME", 3, typeFactory.createSqlType(SqlTypeName.TIMESTAMP)));
+
+        return typeFactory.createStructType(columns);
+    }
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaSPM.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaSPM.java
index c9ffc536a..f6b7a66ec 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaSPM.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaSPM.java
@@ -73,6 +73,8 @@ protected RelDataType deriveRowType() {
         columns.add(new RelDataTypeFieldImpl("HINT", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
         columns.add(
             new RelDataTypeFieldImpl("USE_POST_PLANNER", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("HOT_EVOLVED", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
 
         return typeFactory.createStructType(columns);
     }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaTableDetail.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaTableDetail.java
index dc6a3efc0..04e011cf6 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaTableDetail.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaTableDetail.java
@@ -71,6 +71,8 @@ protected RelDataType deriveRowType() {
             new RelDataTypeFieldImpl("DATA_LENGTH", i++, typeFactory.createSqlType(SqlTypeName.BIGINT_UNSIGNED)));
         columns.add(
             new RelDataTypeFieldImpl("INDEX_LENGTH", i++, typeFactory.createSqlType(SqlTypeName.BIGINT_UNSIGNED)));
+        columns.add(
+            new RelDataTypeFieldImpl("DATA_FREE", i++, typeFactory.createSqlType(SqlTypeName.BIGINT_UNSIGNED)));
         columns.add(new RelDataTypeFieldImpl("BOUND_VALUE", i++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
         columns.add(new RelDataTypeFieldImpl("SUB_BOUND_VALUE", i++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
         columns.add(new RelDataTypeFieldImpl("PERCENT", i++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaTtlInfo.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaTtlInfo.java
new file mode 100644
index 000000000..f9da524d5
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaTtlInfo.java
@@ -0,0 +1,87 @@
+package com.alibaba.polardbx.optimizer.view;
+
+import com.google.common.collect.Lists;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
+import org.apache.calcite.sql.type.SqlTypeName;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class InformationSchemaTtlInfo extends VirtualView {
+
+    public InformationSchemaTtlInfo(RelOptCluster cluster, RelTraitSet traitSet) {
+        super(cluster, traitSet, VirtualViewType.TTL_INFO);
+    }
+
+    public InformationSchemaTtlInfo(RelInput relInput) {
+        super(relInput);
+    }
+
+    @Override
+    protected RelDataType deriveRowType() {
+        final RelDataTypeFactory typeFactory = getCluster().getTypeFactory();
+        List columns = new LinkedList<>();
+        int index = 0;
+        columns.add(new RelDataTypeFieldImpl("TABLE_SCHEMA", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("TABLE_NAME", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(
+            new RelDataTypeFieldImpl("TTL_ENABLE",
+                index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        columns.add(new RelDataTypeFieldImpl("TTL_COL", index++,
+            typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        columns.add(new RelDataTypeFieldImpl("TTL_EXPR", index++,
+            typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        columns.add(new RelDataTypeFieldImpl("TTL_CRON", index++,
+            typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        columns.add(new RelDataTypeFieldImpl("ARCHIVE_TYPE", index++,
+            typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        columns.add(new RelDataTypeFieldImpl("ARCHIVE_TABLE_SCHEMA", index++,
+            typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        columns.add(new RelDataTypeFieldImpl("ARCHIVE_TABLE_NAME", index++,
+            typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        columns.add(new RelDataTypeFieldImpl("ARCHIVE_TABLE_PRE_ALLOCATE", index++,
+            typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        columns.add(new RelDataTypeFieldImpl("ARCHIVE_TABLE_POST_ALLOCATE", index++,
+            typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        return typeFactory.createStructType(columns);
+    }
+
+    @Override
+    boolean indexableColumn(int i) {
+        // TABLE_SCHEMA && TABLE_NAME
+        return i == getTableSchemaIndex() || i == getTableNameIndex();
+    }
+
+    private static final List INDEXABLE_COLUMNS;
+
+    static {
+        INDEXABLE_COLUMNS = Lists.newArrayList(getTableSchemaIndex(), getTableNameIndex());
+    }
+
+    @Override
+    List indexableColumnList() {
+        return INDEXABLE_COLUMNS;
+    }
+
+    static public int getTableSchemaIndex() {
+        return 0;
+    }
+
+    static public int getTableNameIndex() {
+        return 1;
+    }
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaTtlSchedule.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaTtlSchedule.java
new file mode 100644
index 000000000..47559f0cf
--- /dev/null
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaTtlSchedule.java
@@ -0,0 +1,37 @@
+package com.alibaba.polardbx.optimizer.view;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelInput;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
+import org.apache.calcite.sql.type.SqlTypeName;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class InformationSchemaTtlSchedule extends VirtualView {
+
+    public InformationSchemaTtlSchedule(RelOptCluster cluster, RelTraitSet traitSet) {
+        super(cluster, traitSet, VirtualViewType.TTL_SCHEDULE);
+    }
+
+    public InformationSchemaTtlSchedule(RelInput relInput) {
+        super(relInput);
+    }
+
+    @Override
+    protected RelDataType deriveRowType() {
+        final RelDataTypeFactory typeFactory = getCluster().getTypeFactory();
+        List columns = new LinkedList<>();
+        int index = 0;
+
+        columns.add(new RelDataTypeFieldImpl("TABLE_SCHEMA", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("TABLE_NAME", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("METRIC_KEY", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+        columns.add(new RelDataTypeFieldImpl("METRIC_VAL", index++, typeFactory.createSqlType(SqlTypeName.VARCHAR)));
+
+        return typeFactory.createStructType(columns);
+    }
+}
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaViewManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaViewManager.java
index d8f8577ea..7aae6be2a 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaViewManager.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/InformationSchemaViewManager.java
@@ -24,7 +24,10 @@
 import com.alibaba.polardbx.gms.metadb.GmsSystemTables;
 import com.alibaba.polardbx.optimizer.config.schema.InformationSchema;
 import com.alibaba.polardbx.optimizer.config.schema.MetaDbSchema;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
 import com.alibaba.polardbx.optimizer.planmanager.PlanManager;
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.sql.type.SqlTypeName;
 
 import java.util.Arrays;
 import java.util.List;
@@ -125,6 +128,37 @@ private void definePolarXView() {
 
         defineCaseSensitiveView(InstConfUtil.getBool(ConnectionParams.ENABLE_LOWER_CASE_TABLE_NAMES));
 
+        defineView("COLUMNAR_SNAPSHOTS",
+            new String[] {
+                "SCHEMA_NAME",
+                "TABLE_NAME",
+                "INDEX_NAME",
+                "TSO"
+            },
+            String.format("select "
+                + "mapping.table_schema as schema_name, "
+                + "mapping.table_name as table_name, "
+                + "mapping.index_name as index_name, "
+                + "checkpoints.binlog_tso as tso "
+                + "from "
+                + "%s.columnar_table_mapping mapping, %s.columnar_checkpoints checkpoints "
+                + "where "
+                + "mapping.table_id = checkpoints.logical_table "
+                + "and mapping.table_schema = checkpoints.logical_schema "
+                + "and checkpoints.info = 'force' "
+                + "and mapping.status = 'PUBLIC' "
+                + "and mapping.type = 'snapshot' "
+                + "union all "
+                + "select "
+                + "'polardbx', '__global__', '__global__', checkpoints.binlog_tso as tso "
+                + "from "
+                + "%s.columnar_checkpoints checkpoints "
+                + "where "
+                + "checkpoints.info = 'force' "
+                + "and logical_schema = 'polardbx' "
+                + "and logical_table is NULL",
+                MetaDbSchema.NAME, MetaDbSchema.NAME, MetaDbSchema.NAME));
+
         defineView("CHARACTER_SETS", null, String.format("select * from %s.CHARACTER_SETS", MetaDbSchema.NAME));
 
         defineVirtualView(VirtualViewType.COLLATION_CHARACTER_SET_APPLICABILITY, new String[] {
@@ -164,6 +198,14 @@ private void definePolarXView() {
             "WORKLOAD"
         });
 
+        defineVirtualView(VirtualViewType.METRIC, new String[] {
+            "INST",
+            "HOST",
+            "NAME",
+            "TYPE",
+            "VALUE"
+        });
+
         defineVirtualView(VirtualViewType.MODULE_EVENT, new String[] {
             "MODULE_NAME",
             "HOST",
@@ -406,6 +448,14 @@ private void definePolarXView() {
                 + "on C.TABLE_SCHEMA = S.SCHEMA_NAME and C.TABLE_NAME = S.TABLE_NAME "
                 + "and C.COLUMN_NAME = S.COLUMN_NAME");
 
+        defineView("DEADLOCKS", new String[] {
+                "ID",
+                "TYPE",
+                "GMT_CREATED",
+                "LOG"
+            },
+            "select ID, TYPE, GMT_CREATED, LOG from " + MetaDbSchema.NAME + "." + GmsSystemTables.DEADLOCKS);
+
         defineView("FILES", new String[] {
                 "FILE_ID",
                 "FILE_NAME",
@@ -504,6 +554,28 @@ private void definePolarXView() {
             "WORKER_IP",
             "UPDATE_TIME"
         });
+
+        defineVirtualView(VirtualViewType.DDL_SCHEDULER, new String[] {
+            "JOB_ID",
+            "TASK_ID",
+            "TASK_NAME",
+            "TASK_INFO",
+            "TASK_STATE",
+            "EXECUTION_TIME",
+            "NODE_IP",
+            "RESOURCES",
+            "EXTRA",
+            "DDL_STMT",
+        });
+
+        defineVirtualView(VirtualViewType.DDL_ENGINE_RESOURCE, new String[] {
+            "HOST",
+            "RESOURCE_TYPE",
+            "TOTAL_AMOUNT",
+            "RESIDUE",
+            "ACTIVE_TASK",
+            "DETAIL",
+        });
     }
 
     public synchronized void defineCaseSensitiveView(boolean currentEnableLower) {
@@ -575,7 +647,10 @@ public synchronized void defineCaseSensitiveView(boolean currentEnableLower) {
                         + "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, ENGINE, VERSION, ROW_FORMAT, "
                         + "TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, "
                         + "AUTO_INCREMENT, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, CHECKSUM, "
-                        + "CREATE_OPTIONS, TABLE_COMMENT, 'NO' as AUTO_PARTITION from information_schema.information_schema_tables"
+                        + "CREATE_OPTIONS, TABLE_COMMENT, 'NO' as AUTO_PARTITION from information_schema.information_schema_tables "
+                        + "UNION ALL "
+                        + "select catalog_name, LOWER(schema_name), LOWER(view_name), 'VIEW' as table_type, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'VIEW' as table_comment, 'NO' as auto_partition "
+                        + "from %s.views"
                     :
                     "select T.TABLE_CATALOG, T.TABLE_SCHEMA, T.TABLE_NAME, T.TABLE_TYPE, T.ENGINE, T.VERSION, T.ROW_FORMAT, "
                         + "T.TABLE_ROWS, T.AVG_ROW_LENGTH, T.DATA_LENGTH, T.MAX_DATA_LENGTH, T.INDEX_LENGTH, T.DATA_FREE, "
@@ -597,8 +672,11 @@ public synchronized void defineCaseSensitiveView(boolean currentEnableLower) {
                         + "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, ENGINE, VERSION, ROW_FORMAT, "
                         + "TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, "
                         + "AUTO_INCREMENT, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, CHECKSUM, "
-                        + "CREATE_OPTIONS, TABLE_COMMENT, 'NO' as AUTO_PARTITION from information_schema.information_schema_tables"
-                , MetaDbSchema.NAME, MetaDbSchema.NAME, MetaDbSchema.NAME, MetaDbSchema.NAME)
+                        + "CREATE_OPTIONS, TABLE_COMMENT, 'NO' as AUTO_PARTITION from information_schema.information_schema_tables "
+                        + "UNION ALL "
+                        + "select catalog_name, schema_name, view_name, 'VIEW' as table_type, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'VIEW' as table_comment, 'NO' as auto_partition "
+                        + "from %s.views"
+                , MetaDbSchema.NAME, MetaDbSchema.NAME, MetaDbSchema.NAME, MetaDbSchema.NAME, MetaDbSchema.NAME)
         );
 
         defineView("COLUMNS", new String[] {
@@ -1712,6 +1790,38 @@ private void defineCommonView() {
             "TABLES"
         });
 
+        defineVirtualView(VirtualViewType.TTL_INFO, new String[] {
+            "TABLE_SCHEMA",
+            "TABLE_NAME",
+            "TTL_ENABLE",
+            "TTL_COL",
+            "TTL_EXPR",
+            "TTL_CRON",
+            "ARCHIVE_TYPE",
+            "ARCHIVE_TABLE_SCHEMA",
+            "ARCHIVE_TABLE_NAME",
+            "ARCHIVE_TABLE_PRE_ALLOCATE",
+            "ARCHIVE_TABLE_POST_ALLOCATE"
+        });
+
+//        defineVirtualView(VirtualViewType.TTL_SCHEDULE, new String[] {
+//            "SCHEDULE_ID",
+//            "TABLE_SCHEMA",
+//            "TABLE_NAME",
+//            "STATUS",
+//            "SCHEDULE_EXPR",
+//            "SCHEDULE_COMMENT",
+//            "TIME_ZONE",
+//            "LAST_FIRE_TIME",
+//            "NEXT_FIRE_TIME"
+//        });
+        defineVirtualView(VirtualViewType.TTL_SCHEDULE, new String[] {
+            "TABLE_SCHEMA",
+            "TABLE_NAME",
+            "METRIC_KEY",
+            "METRIC_VAL"
+        });
+
         defineVirtualView(VirtualViewType.LOCAL_PARTITIONS, new String[] {
             "TABLE_SCHEMA",
             "TABLE_NAME",
@@ -1785,6 +1895,7 @@ private void defineCommonView() {
             "TABLE_ROWS",
             "DATA_LENGTH",
             "INDEX_LENGTH",
+            "DATA_FREE",
             "BOUND_VALUE",
             "SUB_BOUND_VALUE",
             "PERCENT",
@@ -1843,6 +1954,7 @@ private void defineCommonView() {
             "PART_NAME",
             "PART_POSI",
             "PART_DESC",
+            "PART_ARC_STATE",
 
             "SUBPART_METHOD",
             "SUBPART_COL",
@@ -1853,6 +1965,7 @@ private void defineCommonView() {
             "SUBPART_TEMP_NAME",
             "SUBPART_POSI",
             "SUBPART_DESC",
+            "SUBPART_ARC_STATE",
 
             "PG_NAME",
             "PHY_GROUP",
@@ -2464,6 +2577,13 @@ private void defineCommonView() {
             defineVirtualView(VirtualViewType.SHOW_HELP, new String[] {
                 "STATEMENT",
             });
+
+            defineVirtualView(VirtualViewType.RPL_SYNC_POINT, new String[] {
+                "ID",
+                "PRIMARY_TSO",
+                "SECONDARY_TSO",
+                "CREATE_TIME"
+            });
         }
 }
 
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/MysqlSchemaViewManager.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/MysqlSchemaViewManager.java
index 8f189e580..95dae536c 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/MysqlSchemaViewManager.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/MysqlSchemaViewManager.java
@@ -103,12 +103,14 @@ private void definePolarXView() {
                 "password_last_changed",
                 "password_lifetime",
                 "account_locked",
+                //navicat need to fetch password column
+                "password"
             },
             "select host, user_name, select_priv, insert_priv, update_priv, delete_priv, create_priv, drop_priv, NULL, NULL, NULL, NULL, grant_priv, NULL, index_priv, alter_priv,"
                 +
                 " NULL, NULL, NULL, NULL, NULL, NULL, NULL, create_view_priv, show_view_priv, NULL, NULL, create_user_priv, NULL, NULL, NULL, "
                 +
-                " NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL from "
+                " NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, password from "
                 + MetaDbSchema.NAME + ".user_priv");
 
         defineView("tables_priv", new String[] {
@@ -152,6 +154,21 @@ private void definePolarXView() {
                 +
                 "index_priv, alter_priv, NULL, NULL, create_view_priv, NULL, NULL, NULL, NULL, NULL, NULL from "
                 + MetaDbSchema.NAME + ".db_priv");
+
+        //DataGrip use this view to judge whether connection if keep alive
+        defineView("procs_priv", new String[] {
+                "Host",
+                "Db",
+                "User",
+                "Routine_name",
+                "Routine_type",
+                "Grantor",
+                "Proc_priv",
+                "Timestamp",
+            },
+            "select NULL, routine_schema, NULL, routine_name, routine_type, NULL, NULL, created from "
+                + MetaDbSchema.NAME
+                + ".routines");
     }
 
     @Override
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/VirtualView.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/VirtualView.java
index 33ca4a470..367a51418 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/VirtualView.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/VirtualView.java
@@ -113,6 +113,8 @@ public static VirtualView create(RelOptCluster cluster, RelTraitSet traitSet, Vi
             return new InformationSchemaModuleEvent(cluster, traitSet);
         case MODULE:
             return new InformationSchemaModule(cluster, traitSet);
+        case METRIC:
+            return new InformationSchemaMetric(cluster, traitSet);
         case VIRTUAL_STATISTIC:
             return new VirtualStatistic(cluster, traitSet);
         case INFORMATION_SCHEMA_TABLES:
@@ -179,6 +181,10 @@ public static VirtualView create(RelOptCluster cluster, RelTraitSet traitSet, Vi
             return new InformationSchemaPartitions(cluster, traitSet);
         case PARTITIONS_META:
             return new InformationSchemaPartitionsMeta(cluster, traitSet);
+        case TTL_INFO:
+            return new InformationSchemaTtlInfo(cluster, traitSet);
+        case TTL_SCHEDULE:
+            return new InformationSchemaTtlSchedule(cluster, traitSet);
         case LOCAL_PARTITIONS:
             return new InformationSchemaLocalPartitions(cluster, traitSet);
         case LOCAL_PARTITIONS_SCHEDULE:
@@ -295,7 +301,6 @@ public static VirtualView create(RelOptCluster cluster, RelTraitSet traitSet, Vi
             return new InformationSchemaTableGroup(cluster, traitSet);
         case FULL_TABLE_GROUP:
             return new InformationSchemaFullTableGroup(cluster, traitSet);
-
         case TABLE_DETAIL:
             return new InformationSchemaTableDetail(cluster, traitSet);
         case LOCALITY_INFO:
@@ -366,6 +371,8 @@ public static VirtualView create(RelOptCluster cluster, RelTraitSet traitSet, Vi
             return new InformationSchemaTableJoinClosure(cluster, traitSet);
         case POLARDBX_TRX:
             return new InformationSchemaPolardbxTrx(cluster, traitSet);
+        case DEADLOCKS:
+            return new InformationSchemaDeadlocks(cluster, traitSet);
         case STORAGE_PROPERTIES:
             return new InformationSchemaStorageProperties(cluster, traitSet);
         case PREPARED_TRX_BRANCH:
@@ -374,6 +381,12 @@ public static VirtualView create(RelOptCluster cluster, RelTraitSet traitSet, Vi
             return new InformationSchemaReplicaStat(cluster, traitSet);
         case SHOW_HELP:
             return new InformationSchemaShowHelp(cluster, traitSet);
+        case RPL_SYNC_POINT:
+            return new InformationSchemaRplSyncPoint(cluster, traitSet);
+        case DDL_SCHEDULER:
+            return new InformationSchemaDdlScheduler(cluster, traitSet);
+        case DDL_ENGINE_RESOURCE:
+            return new InformationSchemaDdlEngineResources(cluster, traitSet);
         default:
             throw new AssertionError();
         }
diff --git a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/VirtualViewType.java b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/VirtualViewType.java
index ae5e8cc33..be4e5bde9 100644
--- a/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/VirtualViewType.java
+++ b/polardbx-optimizer/src/main/java/com/alibaba/polardbx/optimizer/view/VirtualViewType.java
@@ -79,6 +79,10 @@ public enum VirtualViewType {
 
     PARTITIONS_META,
 
+    TTL_INFO,
+
+    TTL_SCHEDULE,
+
     LOCAL_PARTITIONS,
 
     LOCAL_PARTITIONS_SCHEDULE,
@@ -224,6 +228,7 @@ public enum VirtualViewType {
     STATISTICS,
     STATISTICS_DATA,
     COLUMN_STATISTICS,
+    METRIC,
 
     /**
      * module view
@@ -281,6 +286,8 @@ public enum VirtualViewType {
 
     POLARDBX_TRX,
 
+    DEADLOCKS,
+
     OPTIMIZER_ALERT,
 
     STORAGE_PROPERTIES,
@@ -291,6 +298,11 @@ public enum VirtualViewType {
 
     REBALANCE_PROGRESS,
 
-    SHOW_HELP
+    SHOW_HELP,
+
+    RPL_SYNC_POINT,
+
+    DDL_SCHEDULER,
 
+    DDL_ENGINE_RESOURCE
 }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/metadb/InfoSchemaCommonTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/metadb/InfoSchemaCommonTest.java
new file mode 100644
index 000000000..3a097426c
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/metadb/InfoSchemaCommonTest.java
@@ -0,0 +1,38 @@
+package com.alibaba.polardbx.metadb;
+
+import com.alibaba.polardbx.common.utils.Assert;
+import com.alibaba.polardbx.optimizer.core.function.calc.scalar.filter.In;
+import com.alibaba.polardbx.optimizer.metadata.InfoSchemaCommon;
+import org.apache.calcite.sql.SqlShowTableStatus;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class InfoSchemaCommonTest {
+    public static final Set TABLES_STAT_NAMES = new HashSet<>();
+
+    @Before
+    public void prepare() {
+        TABLES_STAT_NAMES.add("Rows");
+        TABLES_STAT_NAMES.add("Avg_row_length");
+        TABLES_STAT_NAMES.add("Data_length");
+        TABLES_STAT_NAMES.add("Max_data_length");
+        TABLES_STAT_NAMES.add("Index_length");
+        TABLES_STAT_NAMES.add("Auto_increment");
+    }
+
+    @Test
+    public void infoSchemaCommonTest() {
+        InfoSchemaCommon infoSchemaCommon = new InfoSchemaCommon();
+        long num = 0;
+        for (int i = 0; i < SqlShowTableStatus.NUM_OF_COLUMNS; i++) {
+            String columnName = SqlShowTableStatus.COLUMN_NAMES.get(i);
+            if (TABLES_STAT_NAMES.contains(columnName)) {
+                num++;
+            }
+        }
+        Assert.assertTrue(infoSchemaCommon.TABLES_STAT_INDEXES.size() == num);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/BaseRuleTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/BaseRuleTest.java
index d440e7350..a83a3fab1 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/BaseRuleTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/BaseRuleTest.java
@@ -35,6 +35,13 @@ public class BaseRuleTest extends BasePlannerTest {
             + "  actionDate varchar(30)\n"
             + "  ) dbpartition by hash(userId) tbpartition by HASH(actionDate) tbpartitions 7;";
 
+    public static String stuDDL =
+        "CREATE TABLE stu(\n" + "  id int, \n"
+            + "  name varchar(30), \n"
+            + "  operation tinyint(1), \n"
+            + "  actionDate varchar(30),\n"
+            + "  primary(id)\n"
+            + "  ) dbpartition by hash(id) tbpartition by HASH(actionDate) tbpartitions 7;";
     protected RelOptCluster relOptCluster;
     protected RelOptSchema schema;
 
@@ -55,6 +62,7 @@ public void init() {
         }
         try {
             buildTable(SCHEMA_NAME, empDDL);
+            buildTable(SCHEMA_NAME, stuDDL);
         } catch (SQLSyntaxErrorException e) {
             e.printStackTrace();
         }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/ColumnarForbidTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/ColumnarForbidTest.java
index 31f5754f6..8c3112725 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/ColumnarForbidTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/ColumnarForbidTest.java
@@ -32,6 +32,7 @@
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlModifyColumn;
 import org.apache.calcite.sql.validate.SqlValidatorImpl;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -53,6 +54,7 @@ public class ColumnarForbidTest {
     @Rule
     public ExpectedException thrown = ExpectedException.none();
 
+    @Ignore
     @Test
     public void ForbidAlterCciTableWithMultiStatement() {
         try (MockedStatic staticOptimizerContext = mockStatic(OptimizerContext.class)) {
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/PlannerContextTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/PlannerContextTest.java
new file mode 100644
index 000000000..d1f31bbf6
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/PlannerContextTest.java
@@ -0,0 +1,38 @@
+package com.alibaba.polardbx.optimizer;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author fangwu
+ */
+public class PlannerContextTest {
+
+    /**
+     * Test Case 1: Encoding extended parameters to JSON under normal conditions.
+     * Design Idea:
+     * - Create a PlannerContext instance and set its internal state (such as isUseColumnar and getColumnarMaxShardCnt)
+     * - Invoke the encodeExtendedParametersToJson method
+     * - Verify that the toJsonString method of the mocked JsonBuilder object was correctly invoked
+     * - Ensure the returned value is the expected JSON string
+     */
+    @Test
+    public void testEncodeExtendedParametersToJsonNormalCase() {
+        // Preparation
+        PlannerContext plannerContext = new PlannerContext();
+        plannerContext.setUseColumnar(true);
+        plannerContext.setColumnarMaxShardCnt(10);
+
+        // Execution
+        String result = plannerContext.encodeExtendedParametersToJson();
+
+        // Verification
+        assertTrue(result.contains("columnarMaxShardCnt") && result.contains("useColumnar"));
+
+        PlannerContext plannerContext1 = new PlannerContext();
+        plannerContext1.decodeArguments(result);
+
+        assertTrue(plannerContext1.isUseColumnar() && plannerContext1.getColumnarMaxShardCnt() == 10);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/CacheLineTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/CacheLineTest.java
index 07b9407bb..ea9da1f77 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/CacheLineTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/CacheLineTest.java
@@ -53,7 +53,7 @@ public void testExpire2() {
         MetaDbInstConfigManager.setConfigFromMetaDb(false);
         StatisticManager.CacheLine c =
             new StatisticManager.CacheLine(1, unixTimeStamp(), unixTimeStamp());
-        assert c.getHistogramMap() == null;
+        assert c.getHistogramMap().isEmpty();
         assert c.getTopNColumns().size() == 0;
         Assert.assertTrue(c.hasExpire());
     }
@@ -70,7 +70,7 @@ public void testAbnormalByEmptyHistogram() {
         topN.buildDefault(3, 1);
         c.setTopN("test_col", topN);
         c.setLastModifyTime(System.currentTimeMillis() / 1000);
-        assert c.getHistogramMap() == null;
+        assert c.getHistogramMap().isEmpty();
         assert c.getTopNColumns().size() > 0;
         Assert.assertTrue(!c.hasExpire());
     }
@@ -104,7 +104,7 @@ public void testAbnormalByEmptyTopNAndEmptyHistogram() {
         MetaDbInstConfigManager.setConfigFromMetaDb(false);
         StatisticManager.CacheLine c = new StatisticManager.CacheLine(1, unixTimeStamp(), unixTimeStamp());
         c.setLastModifyTime(System.currentTimeMillis());
-        assert c.getHistogramMap() == null;
+        assert c.getHistogramMap().isEmpty();
         assert c.getTopNColumns().size() == 0;
         Assert.assertTrue(c.hasExpire());
     }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/meta/SelectivityTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/meta/SelectivityTest.java
new file mode 100644
index 000000000..24e3d62f1
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/meta/SelectivityTest.java
@@ -0,0 +1,65 @@
+package com.alibaba.polardbx.optimizer.config.meta;
+
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan;
+import com.alibaba.polardbx.optimizer.utils.PlannerUtils;
+import com.alibaba.polardbx.planner.common.PlanTestCommon;
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Correlate;
+import org.apache.calcite.rel.core.Filter;
+import org.apache.calcite.rel.metadata.BuiltInMetadata;
+import org.apache.calcite.rel.metadata.Metadata;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.rex.RexNode;
+import org.junit.Test;
+import org.junit.runners.Parameterized;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * @author fangwu
+ */
+public class SelectivityTest extends PlanTestCommon {
+
+    public SelectivityTest(String caseName, String targetEnvFile) {
+        super(caseName, targetEnvFile);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return ImmutableList.of(
+            new Object[] {"DrdsRelMdCostTest", "/com/alibaba/polardbx/optimizer/config/meta/DrdsRelMdCostTest"});
+    }
+
+    @Override
+    protected void initBasePlannerTestEnv() {
+        this.useNewPartDb = true;
+    }
+
+    @Test
+    public void testCorrelate() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        String testSql =
+            "select * from (select * from key_tbl union all (select * from key_tbl)) b where name='c' or bid in(select bid from hash_tbl )";
+        ExecutionContext executionContext = new ExecutionContext(appName);
+        ExecutionPlan plan = getExecutionPlan(testSql, executionContext);
+        RelNode relNode = plan.getPlan();
+
+        RelMetadataQuery mq = PlannerUtils.newMetadataQuery();
+
+        Method m = BuiltInMetadata.Selectivity.class.getMethod("getSelectivity", RexNode.class);
+
+        Filter filter = (Filter) relNode.getInput(0);
+        Correlate correlate = (Correlate) filter.getInput(0);
+
+        Metadata metadata = correlate.metadata(BuiltInMetadata.Selectivity.class, mq);
+        m.invoke(metadata, filter.getCondition());
+    }
+
+    @Test
+    public void testSql() {
+
+    }
+}
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/meta/TableScanSelectivityEstimatorTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/meta/TableScanSelectivityEstimatorTest.java
new file mode 100644
index 000000000..9697c65aa
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/meta/TableScanSelectivityEstimatorTest.java
@@ -0,0 +1,29 @@
+package com.alibaba.polardbx.optimizer.config.meta;
+
+import com.alibaba.polardbx.common.jdbc.ParameterContext;
+import com.alibaba.polardbx.planner.common.ParameterizedTestCommon;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.sql.SqlExplainLevel;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+import java.util.Map;
+
+public class TableScanSelectivityEstimatorTest extends ParameterizedTestCommon {
+    public TableScanSelectivityEstimatorTest(String caseName, int sqlIndex, String sql, String expectedPlan,
+                                             String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(TableScanSelectivityEstimatorTest.class);
+    }
+
+    public String removeSubqueryHashCode(String planStr, RelNode plan, Map param,
+                                         SqlExplainLevel sqlExplainLevel) {
+        RelMetadataQuery mq = plan.getCluster().getMetadataQuery();
+        return String.valueOf(mq.getRowCount(plan).longValue());
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/GlobalIndexMetaTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/GlobalIndexMetaTest.java
new file mode 100644
index 000000000..7bd5aa463
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/GlobalIndexMetaTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.alibaba.polardbx.optimizer.config.table;
+
+import com.alibaba.polardbx.gms.metadb.table.IndexStatus;
+import com.alibaba.polardbx.gms.metadb.table.IndexVisibility;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GlobalIndexMetaTest {
+    @Test
+    public void hasGsiTest() {
+        String mainTableName = "test_table";
+        String schemaName = "test_schema";
+        ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+        SchemaManager schemaManager = Mockito.mock(SchemaManager.class);
+        TableMeta tableMeta = Mockito.mock(TableMeta.class);
+        Mockito.when(ec.getSchemaManager(schemaName)).thenReturn(schemaManager);
+        Mockito.when(schemaManager.getTable(mainTableName)).thenReturn(tableMeta);
+
+        boolean hasGsi;
+        Mockito.when(tableMeta.withGsiExcludingPureCci()).thenReturn(true);
+        hasGsi = GlobalIndexMeta.hasGsi(mainTableName, schemaName, ec);
+        Assert.assertTrue(hasGsi);
+    }
+
+    @Test
+    public void allCciTest() {
+        String tableName = "test_table";
+        String indexName1 = "test_index_1";
+        String indexName2 = "test_index_2";
+        String schemaName = "test_schema";
+
+        Map indexMap1 = new HashMap<>();
+        Map indexMap3 = new HashMap<>();
+        // cci
+        GsiMetaManager.GsiIndexMetaBean indexMetaBean1 =
+            new GsiMetaManager.GsiIndexMetaBean(null, schemaName, tableName, true, schemaName, indexName1,
+                Collections.emptyList(), null, null, null, null, null, null,
+                IndexStatus.PUBLIC, 1, true, true, IndexVisibility.VISIBLE);
+        // gsi
+        GsiMetaManager.GsiIndexMetaBean indexMetaBean2 =
+            new GsiMetaManager.GsiIndexMetaBean(null, schemaName, tableName, true, schemaName, indexName2,
+                Collections.emptyList(), null, null, null, null, null, null,
+                IndexStatus.PUBLIC, 1, true, false, IndexVisibility.VISIBLE);
+
+        // gsi & cci
+        indexMap1.put(indexName1, indexMetaBean1);
+        indexMap1.put(indexName2, indexMetaBean2);
+
+        // all cci
+        indexMap3.put(indexName1, indexMetaBean1);
+
+        GsiMetaManager.GsiTableMetaBean tableMetaBean1 = new GsiMetaManager.GsiTableMetaBean(null,
+            schemaName, tableName, GsiMetaManager.TableType.SHARDING, null, null, null,
+            null, null, null, indexMap1, null, null);
+        GsiMetaManager.GsiTableMetaBean tableMetaBean3 = new GsiMetaManager.GsiTableMetaBean(null,
+            schemaName, tableName, GsiMetaManager.TableType.SHARDING, null, null, null,
+            null, null, null, indexMap3, null, null);
+
+        TableMeta tableMeta = Mockito.mock(TableMeta.class);
+        Mockito.when(tableMeta.withCci()).thenReturn(true);
+
+        Mockito.when(tableMeta.getGsiTableMetaBean()).thenReturn(tableMetaBean1);
+        Mockito.doCallRealMethod().when(tableMeta).allCci();
+        boolean allCci = tableMeta.allCci();
+        Assert.assertFalse(allCci);
+
+        Mockito.when(tableMeta.getGsiTableMetaBean()).thenReturn(tableMetaBean3);
+        Mockito.doCallRealMethod().when(tableMeta).allCci();
+        allCci = tableMeta.allCci();
+        Assert.assertTrue(allCci);
+    }
+
+    @Test
+    public void withGsiExcludingPureCciTest() {
+        boolean hasGsi;
+        TableMeta tableMeta = Mockito.mock(TableMeta.class);
+        Mockito.doCallRealMethod().when(tableMeta).withGsiExcludingPureCci();
+
+        Mockito.when(tableMeta.withGsi()).thenReturn(true);
+        Mockito.when(tableMeta.allCci()).thenReturn(false);
+        hasGsi = tableMeta.withGsiExcludingPureCci();
+        Assert.assertTrue(hasGsi);
+
+        Mockito.when(tableMeta.withGsi()).thenReturn(true);
+        Mockito.when(tableMeta.allCci()).thenReturn(true);
+        hasGsi = tableMeta.withGsiExcludingPureCci();
+        Assert.assertFalse(hasGsi);
+
+        Mockito.when(tableMeta.withGsi()).thenReturn(false);
+        Mockito.when(tableMeta.allCci()).thenReturn(false);
+        tableMeta.withGsiExcludingPureCci();
+        Assert.assertFalse(hasGsi);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/TableMetaTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/TableMetaTest.java
new file mode 100644
index 000000000..780d77983
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/TableMetaTest.java
@@ -0,0 +1,272 @@
+package com.alibaba.polardbx.optimizer.config.table;
+
+import com.alibaba.polardbx.gms.metadb.table.IndexStatus;
+import com.alibaba.polardbx.gms.metadb.table.IndexVisibility;
+import com.alibaba.polardbx.gms.metadb.table.TableStatus;
+import com.clearspring.analytics.util.Lists;
+import com.google.common.collect.ImmutableList;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author fangwu
+ */
+public class TableMetaTest {
+    /**
+     * Tests that findGlobalSecondaryIndexByName returns null when GSI is empty.
+     */
+    @Test
+    public void testFindGlobalSecondaryIndexByNameWithEmptyGsi() {
+        TableMeta tableMeta = mock(TableMeta.class);
+
+        when(tableMeta.findGlobalSecondaryIndexByName("indexName")).thenCallRealMethod();
+
+        assertNull(tableMeta.findGlobalSecondaryIndexByName("indexName"));
+    }
+
+    /**
+     * Tests that findGlobalSecondaryIndexByName returns null when there's no matching index.
+     */
+    @Test
+    public void testFindGlobalSecondaryIndexByNameWithNonMatchingIndex()
+        throws NoSuchFieldException, IllegalAccessException {
+        TableMeta tableMeta = createMockTableMeta();
+
+        assertNull(tableMeta.findGlobalSecondaryIndexByName("nonExistingIndex"));
+    }
+
+    /**
+     * Tests that findGlobalSecondaryIndexByName returns the correct GsiIndexMetaBean when a match exists.
+     */
+    @Test
+    public void testFindGlobalSecondaryIndexByNameWithMatchingIndex()
+        throws NoSuchFieldException, IllegalAccessException {
+        TableMeta tableMeta = createMockTableMeta();
+        Field field = TableMeta.class.getDeclaredField("gsiPublished");
+        field.setAccessible(true);
+        GsiMetaManager.GsiIndexMetaBean expectedGsiMeta =
+            ((Map) field.get(tableMeta)).get("MATCHING_INDEX");
+
+        assertEquals(expectedGsiMeta, tableMeta.findGlobalSecondaryIndexByName("MATCHING_INDEX"));
+    }
+
+    /**
+     * Tests that findGlobalSecondaryIndexByName with index name with space
+     */
+    @Test
+    public void testFindGlobalSecondaryIndexByNameWithMatchingIndexNameWithSpace()
+        throws NoSuchFieldException, IllegalAccessException {
+        TableMeta tableMeta = createMockTableMeta();
+        Field field = TableMeta.class.getDeclaredField("gsiPublished");
+        field.setAccessible(true);
+        GsiMetaManager.GsiIndexMetaBean expectedGsiMeta =
+            ((Map) field.get(tableMeta)).get("MATCHING INDEX ");
+
+        assertEquals(expectedGsiMeta, tableMeta.findGlobalSecondaryIndexByName("MATCHING INDEX "));
+        assertNotEquals(expectedGsiMeta, tableMeta.findGlobalSecondaryIndexByName("MATCHING INDEX"));
+    }
+
+    /**
+     * Tests that findGlobalSecondaryIndexByName with index name of cci
+     */
+    @Test
+    public void testFindCCIByName()
+        throws NoSuchFieldException, IllegalAccessException {
+        TableMeta tableMeta = createMockTableMeta();
+        Field field = TableMeta.class.getDeclaredField("columnarIndexPublished");
+        field.setAccessible(true);
+        GsiMetaManager.GsiIndexMetaBean cciMeta =
+            ((Map) field.get(tableMeta)).get("CCI");
+        assertEquals(cciMeta, tableMeta.findGlobalSecondaryIndexByName("CCI"));
+        assertNotEquals(cciMeta, tableMeta.findGlobalSecondaryIndexByName("MATCHING_INDEX"));
+    }
+
+    /**
+     * Input is an empty string, expecting null as a result.
+     */
+    @Test
+    public void testFindLocalIndexByNameWithEmptyString() {
+        TableMeta tableMeta = mock(TableMeta.class);
+        List allIndexes = new ArrayList<>();
+
+        when(tableMeta.getAllIndexes()).thenReturn(allIndexes);
+
+        assertNull(tableMeta.findLocalIndexByName(""));
+    }
+
+    /**
+     * Input is the name of a primary key index, expecting the primary key index.
+     */
+    @Test
+    public void testFindLocalIndexByNameWithPrimaryKeyIndexName() {
+        TableMeta tableMeta = mock(TableMeta.class);
+        IndexMeta primaryKeyIndex = mock(IndexMeta.class);
+
+        when(primaryKeyIndex.isPrimaryKeyIndex()).thenReturn(true);
+        when(tableMeta.getPrimaryIndex()).thenReturn(primaryKeyIndex);
+        when(tableMeta.getAllIndexes()).thenReturn(ImmutableList.of(primaryKeyIndex));
+        when(tableMeta.findLocalIndexByName("PRIMARY")).thenCallRealMethod();
+
+        assertEquals(primaryKeyIndex, tableMeta.findLocalIndexByName("PRIMARY"));
+    }
+
+    /**
+     * Input matches a non-primary key index, expecting that index.
+     */
+    @Test
+    public void testFindLocalIndexByNameWithMatchingNonPrimaryKeyIndex() {
+        TableMeta tableMeta = mock(TableMeta.class);
+        List allIndexes = new ArrayList<>();
+        IndexMeta nonPrimaryKeyIndex = mock(IndexMeta.class);
+        allIndexes.add(nonPrimaryKeyIndex);
+
+        when(nonPrimaryKeyIndex.isPrimaryKeyIndex()).thenReturn(false);
+        when(nonPrimaryKeyIndex.getPhysicalIndexName()).thenReturn("matching_index");
+        when(tableMeta.getAllIndexes()).thenReturn(allIndexes);
+        when(tableMeta.findLocalIndexByName("matching_index")).thenCallRealMethod();
+
+        assertEquals(nonPrimaryKeyIndex, tableMeta.findLocalIndexByName("matching_index"));
+    }
+
+    /**
+     * Input is a non-existing index name, expecting null as a result.
+     */
+    @Test
+    public void testFindLocalIndexByNameWithNonExistingIndexName() {
+        TableMeta tableMeta = mock(TableMeta.class);
+        List allIndexes = new ArrayList<>();
+
+        when(tableMeta.getAllIndexes()).thenReturn(allIndexes);
+        when(tableMeta.findLocalIndexByName("non_existent")).thenCallRealMethod();
+
+        assertNull(tableMeta.findLocalIndexByName("non_existent"));
+    }
+
+    /**
+     * Helper method to create a mocked TableMeta instance with sample GSI data.
+     *
+     * @return Mocked TableMeta instance
+     */
+    private TableMeta createMockTableMeta() throws NoSuchFieldException, IllegalAccessException {
+        Map gsiPublished = new HashMap<>();
+        Map columnarIndexPublished = new HashMap<>();
+        GsiMetaManager.GsiIndexMetaBean gsiMeta1 =
+            new GsiMetaManager.GsiIndexMetaBean(
+                "testIndex",
+                "testSchema",
+                "testTable",
+                false,
+                "index_schema",
+                "matching_Index",
+                Lists.newArrayList(),
+                Lists.newArrayList(),
+                "indexType",
+                "",
+                "",
+                null,
+                "indexTableName",
+                IndexStatus.PUBLIC,
+                0,
+                false,
+                false,
+                IndexVisibility.VISIBLE);
+        gsiPublished.put("MATCHING_INDEX", gsiMeta1);
+
+        GsiMetaManager.GsiIndexMetaBean cciMeta =
+            new GsiMetaManager.GsiIndexMetaBean(
+                "testIndex",
+                "testSchema",
+                "testTable",
+                false,
+                "index_schema",
+                "cci",
+                Lists.newArrayList(),
+                Lists.newArrayList(),
+                "indexType",
+                "",
+                "",
+                null,
+                "indexTableName",
+                IndexStatus.PUBLIC,
+                0,
+                true,
+                true,
+                IndexVisibility.VISIBLE);
+        columnarIndexPublished.put("CCI", cciMeta);
+
+        GsiMetaManager.GsiIndexMetaBean gsiMeta2 = new GsiMetaManager.GsiIndexMetaBean(
+            "testIndex",
+            "testSchema",
+            "testTable",
+            false,
+            "index_schema",
+            "non_Matching_Index",
+            Lists.newArrayList(),
+            Lists.newArrayList(),
+            "indexType",
+            "",
+            "",
+            null,
+            "indexTableName",
+            IndexStatus.PUBLIC,
+            0,
+            false,
+            false,
+            IndexVisibility.VISIBLE);
+        gsiPublished.put("NON_MATCHING_INDEX", gsiMeta2);
+
+        GsiMetaManager.GsiIndexMetaBean gsiMeta3 =
+            new GsiMetaManager.GsiIndexMetaBean(
+                "testIndex",
+                "testSchema",
+                "testTable",
+                false,
+                "index_schema",
+                "matching Index ",
+                Lists.newArrayList(),
+                Lists.newArrayList(),
+                "indexType",
+                "",
+                "",
+                null,
+                "indexTableName",
+                IndexStatus.PUBLIC,
+                0,
+                false,
+                false,
+                IndexVisibility.VISIBLE);
+        gsiPublished.put("MATCHING INDEX ", gsiMeta3);
+
+        TableMeta tableMeta = new TableMeta(
+            "testSchema",
+            "testTable",
+            Lists.newArrayList(),
+            null,
+            Lists.newArrayList(),
+            true,
+            TableStatus.PUBLIC,
+            0L,
+            0);
+
+        Field field = TableMeta.class.getDeclaredField("gsiPublished");
+        field.setAccessible(true);
+        field.set(tableMeta, gsiPublished);
+
+        field = TableMeta.class.getDeclaredField("columnarIndexPublished");
+        field.setAccessible(true);
+        field.set(tableMeta, columnarIndexPublished);
+
+        return tableMeta;
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/collation/CharsetFactoryTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/collation/CharsetFactoryTest.java
index 883a438d8..782398d04 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/collation/CharsetFactoryTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/collation/CharsetFactoryTest.java
@@ -20,8 +20,12 @@
 import com.alibaba.polardbx.optimizer.config.table.charset.CharsetFactory;
 import org.junit.Assert;
 import org.junit.Ignore;
+import org.junit.Assert;
 import org.junit.Test;
 
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
 public class CharsetFactoryTest {
     @Test
     @Ignore
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/collation/WildCardTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/collation/WildCardTest.java
index 4d85f4ec7..0edc26bbc 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/collation/WildCardTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/collation/WildCardTest.java
@@ -24,6 +24,14 @@
 import org.junit.Test;
 
 public class WildCardTest {
+
+    enum LikeType {
+        PREFIX,
+        SUFFIX,
+        MIDDLE,
+        OTHERS
+    }
+
     private static final CollationHandler COLLATION_HANDLER =
         CharsetFactory.DEFAULT_CHARSET_HANDLER.getCollationHandler();
     private static final Slice CHECK_STR =
@@ -31,6 +39,7 @@ public class WildCardTest {
 
             "CAAAACCACTATGAGATATCATCTCACACCAGTTAGAATGGCAATCATTAAAAAGTCAGGAAACAACAGGTGCTGGAGAGGATGCGGAGAAATAGGAACAC");
     private static final String[] MATCHED = {
+        // MIDDLE_MATCHED
         "%CAAAACCACTATGAGATATCATCTCACACCAGTTA%",
         "%AAAACCACTATGAGATATCATCTCACACCAGTTAG%",
         "%AAAACCACTATGAGATATCATCTCACACCAGTTAG%",
@@ -75,41 +84,72 @@ public class WildCardTest {
         "%GAATGGCAATCATTAAAAAGTCAGGAAACAACAGG%",
         "%AATGGCAATCATTAAAAAGTCAGGAAACAACAGGT%",
         "%ATGGCAATCATTAAAAAGTCAGGAAACAACAGGTG%",
-        "%TGGCAATCATTAAAAAGTCAGGAAACAACAGGTGC%",
-        "%GCAATCATTAAAAAGTCAGGAAACAACAGGTGCTG%",
-        "%CAATCATTAAAAAGTCAGGAAACAACAGGTGCTGG%",
-        "%AATCATTAAAAAGTCAGGAAACAACAGGTGCTGGA%",
-        "%ATCATTAAAAAGTCAGGAAACAACAGGTGCTGGAG%",
-        "%TCATTAAAAAGTCAGGAAACAACAGGTGCTGGAGA%",
-        "%CATTAAAAAGTCAGGAAACAACAGGTGCTGGAGAG%",
-        "%ATTAAAAAGTCAGGAAACAACAGGTGCTGGAGAGG%",
-        "%TTAAAAAGTCAGGAAACAACAGGTGCTGGAGAGGA%",
-        "%TAAAAAGTCAGGAAACAACAGGTGCTGGAGAGGAT%",
-        "%AAAAAGTCAGGAAACAACAGGTGCTGGAGAGGATG%",
-        "%AAAAGTCAGGAAACAACAGGTGCTGGAGAGGATGC%",
-        "%AAAGTCAGGAAACAACAGGTGCTGGAGAGGATGCG%",
-        "%AAGTCAGGAAACAACAGGTGCTGGAGAGGATGCGG%",
-        "%AGTCAGGAAACAACAGGTGCTGGAGAGGATGCGGA%",
-        "%GTCAGGAAACAACAGGTGCTGGAGAGGATGCGGAG%",
-        "%TCAGGAAACAACAGGTGCTGGAGAGGATGCGGAGA%",
-        "%CAGGAAACAACAGGTGCTGGAGAGGATGCGGAGAA%",
-        "%AGGAAACAACAGGTGCTGGAGAGGATGCGGAGAAA%",
-        "%GGAAACAACAGGTGCTGGAGAGGATGCGGAGAAAT%",
-        "%GAAACAACAGGTGCTGGAGAGGATGCGGAGAAATA%",
-        "%AAACAACAGGTGCTGGAGAGGATGCGGAGAAATAG%",
-        "%AACAACAGGTGCTGGAGAGGATGCGGAGAAATAGG%",
-        "%ACAACAGGTGCTGGAGAGGATGCGGAGAAATAGGA%",
-        "%CAACAGGTGCTGGAGAGGATGCGGAGAAATAGGAA%",
-        "%AACAGGTGCTGGAGAGGATGCGGAGAAATAGGAAC%",
-        "%ACAGGTGCTGGAGAGGATGCGGAGAAATAGGAACA%",
-        "%CAGGTGCTGGAGAGGATGCGGAGAAATAGGAACAC%",
+        "%TGGCAATCATTAAAAAGTCAGGAAACAACAGGTG%",
+        "%GCAATCATTAAAAAGTCAGGAAACAACAGGTGC%",
+        "%CAATCATTAAAAAGTCAGGAAACAACAGGTG%",
+        "%AATCATTAAAAAGTCAGGAAACAACAGGTG%",
+        "%ATCATTAAAAAGTCAGGAAACAACAGGTG%",
+        "%TCATTAAAAAGTCAGGAAACAACAGGTG%",
+        "%CATTAAAAAGTCAGGAAACAACAGGTG%",
+        "%ATTAAAAAGTCAGGAAACAACAGGTG%",
+        "%TTAAAAAGTCAGGAAACAACAGGTG%",
+        "%TAAAAAGTCAGGAAACAACAGGTG%",
+        "%AAAAAGTCAGGAAACAACAGGTG%",
+        "%AAAAGTCAGGAAACAACAGGTG%",
+        "%AAAGTCAGGAAACAACAGGTG%",
+        "%AAGTCAGGAAACAACAGGTG%",
+        "%AGTCAGGAAACAACAGGTG%",
+        "%GTCAGGAAACAACAGGTGC%",
+        "%TCAGGAAACAACAGGTGC%",
+        "%CAGGAAACAACAGGTGC%",
+        "%AGGAAACAACAGGTGC%",
+        "%GGAAACAACAGGTGC%",
+        "%GAAACAACAGG%",
+        "%AAACAACAG%",
+        "%AACAACAGG%",
+        "%ACAACA%",
+        "%CAACA%",
+        "%AAC%",
+        "%AC%",
+        "%C%",
+
+        // PREFIX_MATCHED
+        "CA%",
+        "CAA%",
+        "CAAA%",
+        "CAAAA%",
+        "CAAAAC%",
+        "CAAAACC%",
+        "CAAAACCA%",
+        "CAAAACCAC%",
+        "CAAAACCACT%",
+        "CAAAACCACTA%",
+
+        // SUFFIX_MATCHED
+        "%C",
+        "%AC",
+        "%CAC",
+        "%ACAC",
+        "%AACAC",
+        "%GAACAC",
+        "%GGAACAC",
+        "%AGGAACAC",
+        "%TAGGAACAC",
+        "%ATAGGAACAC",
+
+        // others
         "%",
+        "%%",
+        "%%%",
         "_%_",
         "%_%",
+        "%__%",
+        "%__%_%",
         "%CAGGTG%GAACA_%",
     };
 
     private static final String[] UNMATCHED = {
+        // MIDDLE_UNMATCHED
         "%ATTGACCACACTCTACTATAGAGTATCACCAAAAC%",
         "%GATTGACCACACTCTACTATAGAGTATCACCAAAA%",
         "%AGATTGACCACACTCTACTATAGAGTATCACCAAA%",
@@ -176,7 +216,37 @@ public class WildCardTest {
         "%AAGGATAAAGAGGCGTAGGAGAGGTCGTGGACAAC%",
         "%CAAGGATAAAGAGGCGTAGGAGAGGTCGTGGACAA%",
         "%ACAAGGATAAAGAGGCGTAGGAGAGGTCGTGGACA%",
-        "%CACAAGGATAAAGAGGCGTAGGAGAGGTCGTGGAC%"
+        "%CACAAGGATAAAGAGGCGTAGGAGAGGTCGTGGAC%",
+
+        // PREFIX_UNMATCHED
+        "CT%",
+        "CCA%",
+        "CGAA%",
+        "CACAA%",
+        "CATAAC%",
+        "CATAACC%",
+        "CACAACCA%",
+        "CAGAACCAC%",
+        "CACAACCACT%",
+        "CAATACCACTA%",
+
+        // SUFFIX_UNMATCHED
+        "%G",
+        "%AG",
+        "%CAG",
+        "%ACGC",
+        "%AGCAC",
+        "%GCACAC",
+        "%GCAACAC",
+        "%ACGAACAC",
+        "%TTGGAACAC",
+        "%AGAGGAACAC",
+
+        // others
+        "_",
+        "__",
+        "___",
+        "%CAG_G%GAACA_%",
     };
 
     @Test
@@ -210,70 +280,93 @@ public void testLatin1Bin() {
 
     @Test
     public void testLatin1BinContains() {
-        CollationHandler collationHandler = CollationHandlers.COLLATION_HANDLER_LATIN1_BIN;
+        Latin1BinCollationHandler collationHandler =
+            (Latin1BinCollationHandler) CollationHandlers.COLLATION_HANDLER_LATIN1_BIN;
+        String pattern;
         for (String matched : MATCHED) {
-            if (isContains(matched)) {
-                String pattern = matched.substring(1, matched.length() - 1);
-                int[] lps = computeLPSArray(Slices.utf8Slice(pattern).getBytes());
+            switch (getLikeType(matched)) {
+            case PREFIX:
+                pattern = matched.substring(0, matched.length() - 1);
+                Assert.assertTrue(String.format("select \'%s\' like \'%s\';", CHECK_STR, matched),
+                    collationHandler.startsWith(CHECK_STR, pattern.getBytes()));
+                break;
+            case SUFFIX:
+                pattern = matched.substring(1);
                 Assert.assertTrue(String.format("select \'%s\' like \'%s\';", CHECK_STR, matched),
-                    collationHandler.containsCompare(CHECK_STR, pattern.getBytes(), lps));
-            } else {
+                    collationHandler.endsWith(CHECK_STR, pattern.getBytes()));
+                break;
+            case MIDDLE:
+                pattern = matched.substring(1, matched.length() - 1);
+                Assert.assertTrue(String.format("select \'%s\' like \'%s\';", CHECK_STR, matched),
+                    collationHandler.contains(CHECK_STR, pattern.getBytes()));
+                break;
+            case OTHERS:
                 Assert.assertTrue(String.format("select \'%s\' like \'%s\';", CHECK_STR, matched),
                     collationHandler.wildCompare(CHECK_STR, Slices.utf8Slice(matched)));
+                break;
             }
         }
 
         for (String unmatched : UNMATCHED) {
-            if (isContains(unmatched)) {
-                String pattern = unmatched.substring(1, unmatched.length() - 1);
-                int[] lps = computeLPSArray(Slices.utf8Slice(pattern).getBytes());
+            switch (getLikeType(unmatched)) {
+            case PREFIX:
+                pattern = unmatched.substring(0, unmatched.length() - 1);
+                Assert.assertFalse(String.format("select \'%s\' like \'%s\';", CHECK_STR, unmatched),
+                    collationHandler.startsWith(CHECK_STR, pattern.getBytes()));
+                break;
+            case SUFFIX:
+                pattern = unmatched.substring(1);
+                Assert.assertFalse(String.format("select \'%s\' like \'%s\';", CHECK_STR, unmatched),
+                    collationHandler.endsWith(CHECK_STR, pattern.getBytes()));
+                break;
+            case MIDDLE:
+                pattern = unmatched.substring(1, unmatched.length() - 1);
                 Assert.assertFalse(String.format("select \'%s\' like \'%s\';", CHECK_STR, unmatched),
-                    collationHandler.containsCompare(CHECK_STR, pattern.getBytes(), lps));
-            } else {
+                    collationHandler.contains(CHECK_STR, pattern.getBytes()));
+                break;
+            case OTHERS:
                 Assert.assertFalse(String.format("select \'%s\' like \'%s\';", CHECK_STR, unmatched),
                     collationHandler.wildCompare(CHECK_STR, Slices.utf8Slice(unmatched)));
+                break;
             }
         }
     }
 
-    public static int[] computeLPSArray(byte[] pattern) {
-        int[] lps = new int[pattern.length];
-        int length = 0;
-        lps[0] = 0;
-        int i = 1;
-
-        while (i < pattern.length) {
-            if (pattern[i] == pattern[length]) {
-                length++;
-                lps[i] = length;
-                i++;
-            } else {
-                if (length != 0) {
-                    length = lps[length - 1];
-                } else {
-                    lps[i] = length;
-                    i++;
+    private LikeType getLikeType(String pattern) {
+        if (pattern == null) {
+            return LikeType.OTHERS;
+        }
+        byte[] bytes = pattern.getBytes();
+        if (bytes.length >= 2 && bytes[0] == CollationHandler.WILD_MANY
+            && bytes[bytes.length - 1] == CollationHandler.WILD_MANY) {
+            for (int i = 1; i < bytes.length - 1; i++) {
+                if (bytes[i] == CollationHandler.WILD_MANY || bytes[i] == CollationHandler.WILD_ONE) {
+                    // no % _ in the middle
+                    return LikeType.OTHERS;
                 }
             }
+            return LikeType.MIDDLE;
         }
-        return lps;
-    }
 
-    private boolean isContains(String pattern) {
-        if (pattern == null || pattern.length() < 2) {
-            return false;
+        if (bytes.length >= 1 && bytes[0] == CollationHandler.WILD_MANY) {
+            for (int i = 1; i < bytes.length; i++) {
+                if (bytes[i] == CollationHandler.WILD_MANY || bytes[i] == CollationHandler.WILD_ONE) {
+                    // no % _ after the first one
+                    return LikeType.OTHERS;
+                }
+            }
+            return LikeType.SUFFIX;
         }
-        byte[] bytes = pattern.getBytes();
-        if (bytes[0] == CollationHandler.WILD_MANY && bytes[bytes.length - 1] == CollationHandler.WILD_MANY) {
-            for (int i = 1; i < bytes.length - 1; i++) {
+        if (bytes.length >= 1 && bytes[bytes.length - 1] == CollationHandler.WILD_MANY) {
+            for (int i = 0; i < bytes.length - 1; i++) {
                 if (bytes[i] == CollationHandler.WILD_MANY || bytes[i] == CollationHandler.WILD_ONE) {
-                    // no % _ in the middle
-                    return false;
+                    // no % _ before the last one
+                    return LikeType.OTHERS;
                 }
             }
-            return true;
+            return LikeType.PREFIX;
         }
-        return false;
+        return LikeType.OTHERS;
     }
 
     /**
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/HistogramTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/statistic/HistogramTest.java
similarity index 90%
rename from polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/HistogramTest.java
rename to polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/statistic/HistogramTest.java
index b0e433e41..f666c9da6 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/HistogramTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/statistic/HistogramTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.alibaba.polardbx.optimizer.config;
+package com.alibaba.polardbx.optimizer.config.table.statistic;
 
+import com.alibaba.fastjson.JSONObject;
 import com.alibaba.polardbx.common.utils.time.core.TimeStorage;
 import com.alibaba.polardbx.optimizer.config.table.statistic.Histogram;
-import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
@@ -27,13 +27,13 @@
 import org.junit.Test;
 
 import java.lang.reflect.Method;
-import java.sql.Timestamp;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Random;
-import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.IntStream;
 
+import static com.alibaba.polardbx.common.utils.Assert.assertTrue;
+import static com.alibaba.polardbx.common.utils.Assert.fail;
 import static java.util.Calendar.DATE;
 
 /**
@@ -184,6 +184,87 @@ public void testFindBucketDateType() throws Exception {
 
     }
 
+    @Test
+    public void testHistogram() {
+        String histogram =
+            "{\"buckets\":[{\"ndv\":1,\"upper\":{},\"lower\":{\"$ref\":\"$.buckets[0].upper\"},\"count\":1,\"preSum\":0},{\"ndv\":1,\"upper\":{},\"lower\":{\"$ref\":\"$.buckets[1].upper\"},\"count\":2,\"preSum\":1},\n"
+                + "{\"ndv\":1,\"upper\":{},\"lower\":{\"$ref\":\"$.buckets[2].upper\"},\"count\":1,\"preSum\":3}],\"maxBucketSize\":4,\"type\":\"unsigned_int\",\"sampleRate\":1.0}";
+        Assert.assertTrue(Histogram.deserializeFromJson(histogram) == null);
+    }
+
+    @Test
+    public void testValidBounds() {
+        Histogram.Bucket validBucket = new Histogram.Bucket();
+        validBucket.setLower(1);
+        validBucket.setUpper(10);
+
+        try {
+            Histogram.validateBucketBounds(validBucket);
+        } catch (Exception e) {
+            fail("Should not throw exception");
+        }
+    }
+
+    @Test
+    public void testNullLowerBound() {
+        Histogram.Bucket bucketWithNullLower = new Histogram.Bucket();
+        bucketWithNullLower.setLower(null);
+        bucketWithNullLower.setUpper(10);
+
+        try {
+            Histogram.validateBucketBounds(bucketWithNullLower);
+        } catch (IllegalArgumentException t) {
+            assertTrue(t.getMessage().contains("Invalid lower bound in histogram bucket"));
+            return;
+        }
+        fail();
+    }
+
+    @Test
+    public void testNullUpperBound() {
+        Histogram.Bucket bucketWithNullUpper = new Histogram.Bucket();
+        bucketWithNullUpper.setLower(1);
+        bucketWithNullUpper.setUpper(null);
+
+        try {
+            Histogram.validateBucketBounds(bucketWithNullUpper);
+        } catch (IllegalArgumentException t) {
+            assertTrue(t.getMessage().contains("Invalid upper bound in histogram bucket"));
+            return;
+        }
+        fail();
+    }
+
+    @Test
+    public void testLowerBoundIsJSONObject() {
+        Histogram.Bucket bucketWithJSONObjectLower = new Histogram.Bucket();
+        bucketWithJSONObjectLower.setLower(new JSONObject());
+        bucketWithJSONObjectLower.setUpper(10);
+
+        try {
+            Histogram.validateBucketBounds(bucketWithJSONObjectLower);
+        } catch (IllegalArgumentException t) {
+            assertTrue(t.getMessage().contains("Invalid lower bound in histogram bucket"));
+            return;
+        }
+        fail();
+    }
+
+    @Test
+    public void testUpperBoundIsJSONObject() {
+        Histogram.Bucket bucketWithJSONObjectUpper = new Histogram.Bucket();
+        bucketWithJSONObjectUpper.setLower(1);
+        bucketWithJSONObjectUpper.setUpper(new JSONObject());
+
+        try {
+            Histogram.validateBucketBounds(bucketWithJSONObjectUpper);
+        } catch (IllegalArgumentException t) {
+            assertTrue(t.getMessage().contains("Invalid upper bound in histogram bucket"));
+            return;
+        }
+        fail();
+    }
+
     @Test
     public void testManualReading() {
         IntegerType it = new IntegerType();
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticManagerTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticManagerTest.java
index ea232e782..8b162aa38 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticManagerTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/statistic/StatisticManagerTest.java
@@ -1,8 +1,13 @@
 package com.alibaba.polardbx.optimizer.config.table.statistic;
 
+import com.alibaba.polardbx.common.properties.ConnectionParams;
 import com.alibaba.polardbx.common.properties.ConnectionProperties;
 import com.alibaba.polardbx.common.properties.DynamicConfig;
+import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.config.ConfigDataMode;
+import com.alibaba.polardbx.gms.config.impl.InstConfUtil;
+import com.alibaba.polardbx.gms.module.Module;
+import com.alibaba.polardbx.gms.module.ModuleLogInfo;
 import com.alibaba.polardbx.optimizer.config.table.statistic.inf.StatisticResultSource;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
 import com.clearspring.analytics.util.Lists;
@@ -13,14 +18,35 @@
 
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ThreadPoolExecutor;
 
+import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_STATISTIC_FEEDBACK;
+import static com.alibaba.polardbx.gms.module.LogPattern.PROCESS_END;
+import static com.alibaba.polardbx.gms.module.LogPattern.PROCESS_SKIPPED;
 import static com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils.buildSketchKey;
+import static com.alibaba.polardbx.optimizer.config.table.statistic.StatisticUtils.digestForStatisticTrace;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyDouble;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
 
 /**
  * @author fangwu
  */
 public class StatisticManagerTest {
+
     @Test
     public void testHandleInFrequencyDegradation() {
         StatisticResult rowCount = StatisticResult.build().setValue(0L, null);
@@ -145,4 +171,261 @@ public void testEnableHll() {
             DynamicConfig.getInstance().loadValue(null, ConnectionProperties.ENABLE_HLL, "true");
         }
     }
+
+    @Test
+    public void testGetFrequencyInnerWithCorrection() {
+        String schema = "testSchema";
+        String logicalTableName = "testTable";
+        String columnName = "testColumn";
+        String value = "testValue";
+        boolean isNeedTrace = true;
+        StatisticManager statisticManager = mock(StatisticManager.class);
+
+        when(statisticManager.getCorrectionResult(anyString(), anyString(), eq(isNeedTrace)))
+            .thenReturn(new StatisticResult().setSource(StatisticResultSource.CORRECTIONS).setValue(10L, null));
+        when(statisticManager.getFrequencyInner(schema, logicalTableName, columnName, value,
+            isNeedTrace)).thenCallRealMethod();
+
+        StatisticResult result =
+            statisticManager.getFrequencyInner(schema, logicalTableName, columnName, value, isNeedTrace);
+
+        assertEquals(10, result.getLongValue());
+        assertEquals(StatisticResultSource.CORRECTIONS, result.getSource());
+        verify(statisticManager).getCorrectionResult(
+            eq(schema.toLowerCase() + "," + logicalTableName.toLowerCase() + "," + columnName.toLowerCase() + ","
+                + digestForStatisticTrace(value)),
+            eq("getFrequency"), eq(isNeedTrace));
+    }
+
+    @Test
+    public void testGetFrequencyInnerWithTopN() {
+        String schema = "testSchema";
+        String logicalTableName = "testTable";
+        String columnName = "testColumn";
+        String value = "testValue";
+        boolean isNeedTrace = true;
+        StatisticManager statisticManager = mock(StatisticManager.class);
+        StatisticManager.CacheLine cacheLine = mock(StatisticManager.CacheLine.class);
+        TopN topN = mock(TopN.class);
+
+        when(cacheLine.getTopN(columnName.toLowerCase())).thenReturn(topN);
+        when(topN.rangeCount(value, true, value, true)).thenReturn(10L);
+        when(cacheLine.getSampleRate()).thenReturn(0.5F);
+        when(statisticManager.getCacheLine(schema.toLowerCase(), logicalTableName.toLowerCase())).thenReturn(cacheLine);
+        when(statisticManager.getFrequencyInner(schema, logicalTableName, columnName, value,
+            isNeedTrace)).thenCallRealMethod();
+
+        StatisticResult result =
+            statisticManager.getFrequencyInner(schema, logicalTableName, columnName, value, isNeedTrace);
+
+        assertEquals(20L, result.getLongValue());
+        assertEquals(StatisticResultSource.TOP_N, result.getSource());
+        verify(statisticManager).getCacheLine(eq(schema.toLowerCase()), eq(logicalTableName.toLowerCase()));
+        verify(cacheLine).getTopN(columnName.toLowerCase());
+        verify(cacheLine, times(2)).getSampleRate();
+    }
+
+    @Test
+    public void testGetFrequencyInnerWithSampleNdvHllSketchAlike() {
+        String schema = "testSchema";
+        String logicalTableName = "testTable";
+        String columnName = "testColumn";
+        String value = "testValue";
+        boolean isNeedTrace = true;
+        StatisticManager statisticManager = mock(StatisticManager.class);
+        StatisticManager.CacheLine cacheLine = mock(StatisticManager.CacheLine.class);
+        Map ndvMap = new HashMap<>();
+        ndvMap.put(columnName.toLowerCase(), 100L);
+
+        try (MockedStatic generalUtilMockedStatic = Mockito.mockStatic(GeneralUtil.class)) {
+            generalUtilMockedStatic.when(() -> GeneralUtil.isWithinPercentage(anyLong(), anyLong(), anyDouble()))
+                .thenReturn(true);
+            Map map = new HashMap<>();
+            when(cacheLine.getCardinalityMap()).thenReturn(ndvMap);
+            when(cacheLine.getHistogramMap()).thenReturn(map);
+            when(cacheLine.getSampleRate()).thenReturn(1.0f);
+            when(statisticManager.getCacheLine(any(), anyString())).thenReturn(cacheLine);
+            when(statisticManager.getCardinality(schema.toLowerCase(), logicalTableName.toLowerCase(),
+                columnName.toLowerCase(), true,
+                isNeedTrace)).thenReturn(
+                new StatisticResult().setValue(11, mock(StatisticTrace.class))
+                    .setSource(StatisticResultSource.HLL_SKETCH));
+            when(statisticManager.getFrequencyInner(schema, logicalTableName, columnName, value,
+                isNeedTrace)).thenCallRealMethod();
+
+            Histogram histogram = mock(Histogram.class);
+            when(histogram.rangeCount(any(), anyBoolean(), anyString(), anyBoolean())).thenReturn(13L);
+            map.put(columnName.toLowerCase(), histogram);
+
+            StatisticResult result =
+                statisticManager.getFrequencyInner(schema, logicalTableName, columnName, value, isNeedTrace);
+
+            assertEquals(13L, result.getLongValue());
+            assertEquals(StatisticResultSource.HISTOGRAM, result.getSource());
+            verify(statisticManager).getCacheLine(eq(schema.toLowerCase()), eq(logicalTableName.toLowerCase()));
+        }
+    }
+
+    @Test
+    public void testGetFrequencyInnerWithSampleNdvHllSketchDislike() {
+        String schema = "testSchema";
+        String logicalTableName = "testTable";
+        String columnName = "testColumn";
+        String value = "testValue";
+        boolean isNeedTrace = true;
+        StatisticManager statisticManager = mock(StatisticManager.class);
+        StatisticManager.CacheLine cacheLine = mock(StatisticManager.CacheLine.class);
+        Map ndvMap = new HashMap<>();
+        ndvMap.put(columnName.toLowerCase(), 100L);
+
+        when(cacheLine.getCardinalityMap()).thenReturn(ndvMap);
+        when(statisticManager.getCacheLine(schema.toLowerCase(), logicalTableName.toLowerCase())).thenReturn(cacheLine);
+        when(statisticManager.getCardinality(schema.toLowerCase(), logicalTableName.toLowerCase(),
+            columnName.toLowerCase(), true,
+            isNeedTrace)).thenReturn(
+            new StatisticResult().setValue(11, mock(StatisticTrace.class)).setSource(StatisticResultSource.HLL_SKETCH));
+        when(statisticManager.getRowCount(eq(schema.toLowerCase()), eq(logicalTableName.toLowerCase()),
+            eq(isNeedTrace))).thenReturn(
+            new StatisticResult().setValue(100000, mock(StatisticTrace.class))
+                .setSource(StatisticResultSource.CACHE_LINE));
+        when(statisticManager.getFrequencyInner(schema, logicalTableName, columnName, value,
+            isNeedTrace)).thenCallRealMethod();
+
+        try (MockedStatic generalUtilMockedStatic = Mockito.mockStatic(GeneralUtil.class)) {
+            generalUtilMockedStatic.when(() -> GeneralUtil.isWithinPercentage(anyLong(), anyLong(), anyDouble()))
+                .thenReturn(false);
+
+            StatisticResult result =
+                statisticManager.getFrequencyInner(schema, logicalTableName, columnName, value, isNeedTrace);
+
+            assertEquals(9090L, result.getLongValue());
+            assertEquals(StatisticResultSource.CACHE_LINE, result.getSource());
+            verify(statisticManager).getCacheLine(eq(schema.toLowerCase()), eq(logicalTableName.toLowerCase()));
+        }
+    }
+
+    @Test
+    public void testFeedback() {
+        StatisticManager statisticManager = mock(StatisticManager.class);
+        ModuleLogInfo moduleLogInfo = mock(ModuleLogInfo.class);
+
+        String schema = "schema";
+        String tbl = "tbl";
+        try (MockedStatic moduleLogInfoMockedStatic = Mockito.mockStatic(ModuleLogInfo.class);
+            MockedStatic instConfUtilMockedStatic = Mockito.mockStatic(InstConfUtil.class)) {
+            moduleLogInfoMockedStatic.when(() -> ModuleLogInfo.getInstance()).thenReturn(moduleLogInfo);
+            Mockito.doCallRealMethod().when(statisticManager).feedback(anyString(), anyString());
+            // 1 branch, cache line is null
+            when(statisticManager.getCacheLine(anyString(), anyString())).thenReturn(null);
+
+            statisticManager.feedback(schema, tbl);
+
+            verify(moduleLogInfo).logError(any(), anyString(), any());
+            clearInvocations(moduleLogInfo);
+
+            // 2 branch, feedback quit by time check
+            StatisticManager.CacheLine cacheLine = new StatisticManager.CacheLine();
+            cacheLine.setLastModifyTime(GeneralUtil.unixTimeStamp());
+            when(statisticManager.getCacheLine(anyString(), anyString())).thenReturn(cacheLine);
+
+            statisticManager.feedback(schema, tbl);
+
+            verify(moduleLogInfo).logInfo(Module.STATISTICS, PROCESS_END,
+                new String[] {"FEEDBACK", schema + ":" + tbl});
+            clearInvocations(moduleLogInfo);
+
+            // 3 branch, feedback job submit its job
+            cacheLine.setLastModifyTime(GeneralUtil.unixTimeStamp() - 100);
+            cacheLine.setRowCount(1001L);
+            Assert.assertTrue(cacheLine.addUpdateRowCount(5L) == 1006L);
+            StatisticManager.setExecutor(mock(ThreadPoolExecutor.class));
+
+            statisticManager.feedback(schema, tbl);
+
+            Assert.assertTrue(cacheLine.addUpdateRowCount(0L) == 1001L);
+        }
+    }
+
+    @Test
+    public void testFeedbackJob() {
+        ModuleLogInfo moduleLogInfo = mock(ModuleLogInfo.class);
+        try (MockedStatic moduleLogInfoMockedStatic = Mockito.mockStatic(ModuleLogInfo.class);
+            MockedStatic instConfUtilMockedStatic = Mockito.mockStatic(InstConfUtil.class)) {
+            moduleLogInfoMockedStatic.when(() -> ModuleLogInfo.getInstance()).thenReturn(moduleLogInfo);
+            StatisticManager statisticManager = new MockStatisticManager();
+
+            // 1 branch, feedback job quit by time check
+            StatisticManager.CacheLine cacheLine = new StatisticManager.CacheLine();
+            cacheLine.setLastModifyTime(GeneralUtil.unixTimeStamp());
+
+            statisticManager.feedbackJob("schema", "table", cacheLine);
+
+            verify(moduleLogInfo, times(1)).logInfo(Module.STATISTICS, PROCESS_END,
+                new String[] {"FEEDBACK", "schema:table"});
+            clearInvocations(moduleLogInfo);
+
+            // 2 branch, feedback job quit by ENABLE_STATISTIC_FEEDBACK is false
+            instConfUtilMockedStatic.when(() -> InstConfUtil.getBool(ConnectionParams.ENABLE_STATISTIC_FEEDBACK))
+                .thenReturn(false);
+
+            cacheLine.setLastModifyTime(GeneralUtil.unixTimeStamp() - 100);
+
+            statisticManager.feedbackJob("schema", "table", cacheLine);
+
+            verify(moduleLogInfo, times(1)).logInfo(Module.STATISTICS, PROCESS_SKIPPED,
+                new String[] {
+                    "statistic feedback schema,table",
+                    ENABLE_STATISTIC_FEEDBACK + " is false"});
+            clearInvocations(moduleLogInfo);
+
+            // 3 branch, feedback job finished its job
+            instConfUtilMockedStatic.when(() -> InstConfUtil.getBool(ConnectionParams.ENABLE_STATISTIC_FEEDBACK))
+                .thenReturn(true);
+
+            cacheLine.setLastModifyTime(GeneralUtil.unixTimeStamp() - 100);
+
+            statisticManager.sds = mock(StatisticDataSource.class);
+
+            statisticManager.feedbackJob("schema", "table", cacheLine);
+
+            verify(moduleLogInfo, times(1)).logInfo(eq(Module.STATISTICS), eq(PROCESS_END), any());
+            clearInvocations(moduleLogInfo);
+        }
+    }
+
+    @Test
+    public void testGetSingleValFrequencyFromHistogramWithValidHistogram() {
+        String serialize =
+            "{\"buckets\":[{\"ndv\":1200,\"upper\":-9,\"lower\":-999,\"count\":1200,\"preSum\":0},"
+                + "{\"ndv\":1200,\"upper\":100,\"lower\":10,\"count\":120001,\"preSum\":1200},"
+                + "{\"ndv\":1200,\"upper\":299,\"lower\":150,\"count\":1200,\"preSum\":121201}],"
+                + "\"maxBucketSize\":64,\"type\":\"Int\",\"sampleRate\":0.0098707926}";
+
+        Histogram histogram = Histogram.deserializeFromJson(serialize);
+        Map histogramMap = new HashMap<>();
+        histogramMap.put("columnName", histogram);
+
+        StatisticResult result =
+            StatisticManager.getSingleValFrequencyFromHistogram("schema", "table", "columnName", "9", histogramMap,
+                false, System.currentTimeMillis(), 1.0f);
+
+        assertNull(result);
+
+        result =
+            StatisticManager.getSingleValFrequencyFromHistogram("schema", "table", "columnName", "55", histogramMap,
+                false, System.currentTimeMillis(), 1.0f);
+
+        assertEquals(10130L, result.getValue());
+    }
+
+    @Test
+    public void testGetSingleValFrequencyFromHistogramWithEmptyHistogram() {
+        Map emptyHistogramMap = new HashMap<>();
+
+        StatisticResult result =
+            StatisticManager.getSingleValFrequencyFromHistogram("schema", "table", "columnName", "value",
+                emptyHistogramMap, false, System.currentTimeMillis(), 1.0f);
+
+        assertNull(result);
+    }
 }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/statistic/TopNTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/statistic/TopNTest.java
index 2510e9900..b9f1dc940 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/statistic/TopNTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/config/table/statistic/TopNTest.java
@@ -1,5 +1,6 @@
 package com.alibaba.polardbx.optimizer.config.table.statistic;
 
+import com.alibaba.fastjson.JSONObject;
 import com.alibaba.polardbx.common.utils.Assert;
 import com.alibaba.polardbx.optimizer.core.datatype.DataType;
 import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
@@ -7,7 +8,12 @@
 import org.junit.Test;
 
 import java.sql.Date;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Random;
+import java.util.function.Consumer;
+
+import static com.alibaba.polardbx.optimizer.config.table.statistic.TopN.validateTopNValues;
 
 /**
  * test topn of statistic module
@@ -135,6 +141,72 @@ public void testTopNRangeCount() {
         }
     }
 
+    @Test
+    public void testValidateTopNValuesValidInput() {
+        /**
+         * Test Case #1: Valid Input - Ensure the method can handle an array that is non-empty and does not contain null or JSONObject elements.
+         */
+        Object[] validValues = {1, "string", true};
+        assertDoesNotThrow(t -> validateTopNValues(t), validValues);
+    }
+
+    private  void assertDoesNotThrow(Consumer c, T t) {
+        try {
+            c.accept(t);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    public void testValidateTopNValuesEmptyArray() {
+        /**
+         * Test Case #2: Empty Array - When an empty array is passed, an IllegalArgumentException should be thrown.
+         */
+        Object[] emptyArray = {};
+        assertThrows(IllegalArgumentException.class, t -> validateTopNValues(t), emptyArray);
+    }
+
+    private  void assertThrows(Class exceptionClass, Consumer c, T t) {
+        try {
+            c.accept(t);
+            throw new RuntimeException("Expected exception was not thrown.");
+        } catch (Exception e) {
+            e.printStackTrace();
+            if (!e.getClass().equals(exceptionClass)) {
+                throw new RuntimeException("Expected exception was not thrown.");
+            }
+        }
+    }
+
+    @Test
+    public void testValidateTopNValuesNullArray() {
+        /**
+         * Test Case #3: Null Array - When a null array is passed, an IllegalArgumentException should be thrown.
+         */
+        Object[] objs = null;
+        assertThrows(IllegalArgumentException.class, t -> validateTopNValues(t), objs);
+    }
+
+    @Test
+    public void testValidateTopNValuesArrayContainsNull() {
+        /**
+         * Test Case #4: Array Contains Null Element - When the array contains a null element, an IllegalArgumentException should be thrown.
+         */
+        Object[] arrayWithNull = {"a", null, "b"};
+        assertThrows(IllegalArgumentException.class, t -> validateTopNValues(t), arrayWithNull);
+    }
+
+    @Test
+    public void testValidateTopNValuesArrayContainsJSONObject() {
+        /**
+         * Test Case #5: Array Contains JSONObject - When the array contains an element of type JSONObject, an IllegalArgumentException should be thrown.
+         */
+        JSONObject jsonObject = new JSONObject();
+        Object[] arrayWithJSONObject = {"a", jsonObject, "b"};
+        assertThrows(IllegalArgumentException.class, t -> validateTopNValues(t), arrayWithJSONObject);
+    }
+
     public void checkRangeCount(TopN topN, Object lower, Object upper, DataType dataType, Object[] values,
                                 int[] counts) {
         boolean[][] inclusive = new boolean[][] {
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/context/ExecutionContextTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/context/ExecutionContextTest.java
index 17470a0f4..355992295 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/context/ExecutionContextTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/context/ExecutionContextTest.java
@@ -45,4 +45,33 @@ public void isEnableXaTsoTest() {
         Assert.assertFalse(ec.isEnableXaTso());
         Assert.assertFalse(ec.isEnableAutoCommitTso());
     }
+
+    @Test
+    public void isMarkSyncPointTest() {
+        ExecutionContext ec = new ExecutionContext();
+        ec.setExtraServerVariables(new HashMap<>());
+        ec.getExtraServerVariables().put(ConnectionProperties.MARK_SYNC_POINT, "true");
+        Assert.assertTrue(ec.isMarkSyncPoint());
+
+        ec.getExtraServerVariables().put(ConnectionProperties.MARK_SYNC_POINT, "false");
+        Assert.assertFalse(ec.isMarkSyncPoint());
+
+        ec.getExtraServerVariables().put(ConnectionProperties.MARK_SYNC_POINT, null);
+        Assert.assertFalse(ec.isMarkSyncPoint());
+
+        ec.getExtraServerVariables().remove(ConnectionProperties.MARK_SYNC_POINT);
+        Assert.assertFalse(ec.isMarkSyncPoint());
+
+        ec.setExtraServerVariables(null);
+        Assert.assertFalse(ec.isMarkSyncPoint());
+    }
+
+    @Test
+    public void flashbackAreaTest() {
+        ExecutionContext ec = new ExecutionContext();
+        ec.setFlashbackArea(true);
+        Assert.assertTrue(ec.isFlashbackArea());
+        ec.clearContextInsideTrans();
+        Assert.assertFalse(ec.isFlashbackArea());
+    }
 }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/TddlOperatorTableTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/TddlOperatorTableTest.java
new file mode 100644
index 000000000..04b07b52b
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/TddlOperatorTableTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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 com.alibaba.polardbx.optimizer.core;
+
+import org.apache.calcite.sql.SqlFunction;
+import org.apache.calcite.sql.SqlKind;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TddlOperatorTableTest {
+
+    @Test
+    public void testUUidBinFunc() {
+        TddlOperatorTable tddlOperatorTable = TddlOperatorTable.instance();
+        final SqlFunction uuidToBin = tddlOperatorTable.UUID_TO_BIN;
+        final SqlFunction binToUuid = tddlOperatorTable.BIN_TO_UUID;
+        Assert.assertEquals(uuidToBin.kind, SqlKind.OTHER_FUNCTION);
+        Assert.assertEquals(binToUuid.kind, SqlKind.OTHER_FUNCTION);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeTest.java
index 165af92ad..dee0a2971 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeTest.java
@@ -24,7 +24,6 @@
 import com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue;
 import com.alibaba.polardbx.rpc.result.XResultUtil;
 import io.airlift.slice.Slice;
-import org.apache.hadoop.yarn.webapp.hamlet2.Hamlet;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeUtilTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeUtilTest.java
index 1b0a34428..15cb0f440 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeUtilTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/datatype/DataTypeUtilTest.java
@@ -69,34 +69,34 @@ public void testJdbcTypeToRelDataType() {
             new TypeCase(8, "DOUBLE", 22, 0, 22, true, "DOUBLE"),
             new TypeCase(3, "DECIMAL", 10, 0, 11, true, "DECIMAL(10, 0)"),
             new TypeCase(8, "DOUBLE", 22, 0, 22, true, "DOUBLE"),
-            new TypeCase(7, "FLOAT", 7, 3, 7, true, "FLOAT"),
-            new TypeCase(8, "DOUBLE", 7, 3, 7, true, "DOUBLE"),
+            new TypeCase(7, "FLOAT", 7, 3, 7, true, "FLOAT(3)"),
+            new TypeCase(8, "DOUBLE", 7, 3, 7, true, "DOUBLE(3)"),
             new TypeCase(3, "DECIMAL", 7, 3, 9, true, "DECIMAL(7, 3)"),
-            new TypeCase(8, "DOUBLE", 7, 3, 7, true, "DOUBLE"),
+            new TypeCase(8, "DOUBLE", 7, 3, 7, true, "DOUBLE(3)"),
             new TypeCase(7, "FLOAT UNSIGNED", 12, 0, 12, true, "FLOAT"),
             new TypeCase(8, "DOUBLE UNSIGNED", 22, 0, 22, true, "DOUBLE"),
             new TypeCase(3, "DECIMAL UNSIGNED", 10, 0, 10, true, "DECIMAL(10, 0)"),
             new TypeCase(8, "DOUBLE UNSIGNED", 22, 0, 22, true, "DOUBLE"),
-            new TypeCase(7, "FLOAT UNSIGNED", 7, 3, 7, true, "FLOAT"),
-            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE"),
+            new TypeCase(7, "FLOAT UNSIGNED", 7, 3, 7, true, "FLOAT(3)"),
+            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE(3)"),
             new TypeCase(3, "DECIMAL UNSIGNED", 7, 3, 8, true, "DECIMAL(7, 3)"),
-            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE"),
+            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE(3)"),
             new TypeCase(7, "FLOAT UNSIGNED", 12, 0, 12, true, "FLOAT"),
             new TypeCase(8, "DOUBLE UNSIGNED", 22, 0, 22, true, "DOUBLE"),
             new TypeCase(3, "DECIMAL UNSIGNED", 10, 0, 10, true, "DECIMAL(10, 0)"),
             new TypeCase(8, "DOUBLE UNSIGNED", 22, 0, 22, true, "DOUBLE"),
-            new TypeCase(7, "FLOAT UNSIGNED", 7, 3, 7, true, "FLOAT"),
-            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE"),
+            new TypeCase(7, "FLOAT UNSIGNED", 7, 3, 7, true, "FLOAT(3)"),
+            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE(3)"),
             new TypeCase(3, "DECIMAL UNSIGNED", 7, 3, 8, true, "DECIMAL(7, 3)"),
-            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE"),
+            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE(3)"),
             new TypeCase(7, "FLOAT UNSIGNED", 12, 0, 12, true, "FLOAT"),
             new TypeCase(8, "DOUBLE UNSIGNED", 22, 0, 22, true, "DOUBLE"),
             new TypeCase(3, "DECIMAL UNSIGNED", 10, 0, 10, true, "DECIMAL(10, 0)"),
             new TypeCase(8, "DOUBLE UNSIGNED", 22, 0, 22, true, "DOUBLE"),
-            new TypeCase(7, "FLOAT UNSIGNED", 7, 3, 7, true, "FLOAT"),
-            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE"),
+            new TypeCase(7, "FLOAT UNSIGNED", 7, 3, 7, true, "FLOAT(3)"),
+            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE(3)"),
             new TypeCase(3, "DECIMAL UNSIGNED", 7, 3, 8, true, "DECIMAL(7, 3)"),
-            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE"),
+            new TypeCase(8, "DOUBLE UNSIGNED", 7, 3, 7, true, "DOUBLE(3)"),
             new TypeCase(1, "CHAR", 10, 0, 0, true, "CHAR(10)"),
             new TypeCase(12, "VARCHAR", 1020, 0, 0, true, "VARCHAR(1020)"),
             new TypeCase(-2, "BINARY", 255, 0, 0, true, "BINARY(255)"),
@@ -125,6 +125,20 @@ public void testJdbcTypeToRelDataType() {
             RelDataType dataType =
                 DataTypeUtil.jdbcTypeToRelDataType(t.jdbcType, t.typeName, t.precision, t.scale, t.length, t.nullable);
             Assert.assertEquals(t.expectedTypeString, dataType.toString());
+            if ((dataType.toString().contains("FLOAT") || dataType.toString().contains("DOUBLE")) && t.scale != 0) {
+                Assert.assertEquals(t.scale, dataType.getScale());
+            }
+            DataType dt = DataTypeFactory.INSTANCE.create(dataType);
+            if ((dataType.toString().contains("FLOAT") || dataType.toString().contains("DOUBLE")) && t.scale != 0) {
+                Assert.assertEquals(t.scale, dt.getScale());
+                if (dataType.toString().contains("FLOAT")) {
+                    Assert.assertEquals(1.12f, Float.parseFloat(DataTypeUtil.convert(dt, DataTypes.StringType, 1.12f)),
+                        1e-6);
+                } else {
+                    Assert.assertEquals(1.12d,
+                        Double.parseDouble(DataTypeUtil.convert(dt, DataTypes.StringType, 1.12d)), 1e-6);
+                }
+            }
         }
     }
 
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonArrayAggTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonArrayAggTest.java
new file mode 100644
index 000000000..a99bec780
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonArrayAggTest.java
@@ -0,0 +1,100 @@
+package com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.polardbx.common.utils.Assert;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.optimizer.core.expression.IFunction;
+import com.alibaba.polardbx.optimizer.core.row.ArrayRow;
+import junit.framework.TestCase;
+import org.apache.calcite.sql.SqlKind;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class JsonArrayAggTest {
+
+    @Test
+    public void partitionAggTest1() {
+        JsonArrayAgg jsonArrayAgg = new JsonArrayAgg(0, -1);
+        Assert.assertTrue(IFunction.FunctionType.Aggregate.equals(jsonArrayAgg.getFunctionType()));
+        Assert.assertTrue(DataTypes.JsonType.equals(jsonArrayAgg.getReturnType()));
+        Assert.assertTrue("JSON_ARRAYAGG".equalsIgnoreCase(jsonArrayAgg.getFunctionNames()[0]));
+        Assert.assertTrue(SqlKind.JSON_ARRAYAGG.equals(jsonArrayAgg.getSqlKind()));
+    }
+
+    @Test
+    public void globalAggTest1() {
+        JsonArrayGlobalAgg jsonArrayGlobalAgg = new JsonArrayGlobalAgg(0, -1);
+        Assert.assertTrue(IFunction.FunctionType.Aggregate.equals(jsonArrayGlobalAgg.getFunctionType()));
+        Assert.assertTrue(DataTypes.JsonType.equals(jsonArrayGlobalAgg.getReturnType()));
+        Assert.assertTrue("JSON_ARRAY_GLOBALAGG".equalsIgnoreCase(jsonArrayGlobalAgg.getFunctionNames()[0]));
+        Assert.assertTrue(SqlKind.JSON_ARRAY_GLOBALAGG.equals(jsonArrayGlobalAgg.getSqlKind()));
+    }
+
+    @Test
+    public void partitionAggTest2() {
+        JsonArrayAgg jsonArrayAgg = new JsonArrayAgg(0, -1);
+
+        //没有元素时,返回null
+        Assert.assertTrue(jsonArrayAgg.eval(null) == null);
+
+        List allValues = new ArrayList<>();
+        for (int i = 0; i < 100; i++) {
+            int value = i % 33;
+            allValues.add(value);
+            ArrayRow arrayRow = new ArrayRow(new Object[] {value});
+            jsonArrayAgg.conductAgg(arrayRow);
+        }
+
+        String json = (String) jsonArrayAgg.eval(null);
+        JSONArray jsonArray = JSON.parseArray(json);
+
+        Object[] arr1 = jsonArray.toArray();
+        Object[] arr2 = allValues.toArray();
+        Arrays.sort(arr1);
+        Arrays.sort(arr2);
+        Assert.assertTrue(Arrays.equals(arr1, arr2));
+
+    }
+
+    @Test
+    public void globalAggTest2() {
+        JsonArrayGlobalAgg jsonArrayGlobalAgg = new JsonArrayGlobalAgg(0, -1);
+
+        //没有元素时,返回null
+        Assert.assertTrue(jsonArrayGlobalAgg.eval(null) == null);
+
+        List allValues = new ArrayList<>();
+        JSONArray input = new JSONArray();
+        for (int i = 0; i < 100; i++) {
+            int value = i % 33;
+            allValues.add(value);
+            input.add(value);
+            if (i % 6 == 0) {
+                ArrayRow arrayRow = new ArrayRow(new Object[] {input.toJSONString()});
+                jsonArrayGlobalAgg.conductAgg(arrayRow);
+                input = new JSONArray();
+            }
+
+        }
+        ArrayRow arrayRow = new ArrayRow(new Object[] {input.toJSONString()});
+        jsonArrayGlobalAgg.conductAgg(arrayRow);
+
+        String json = (String) jsonArrayGlobalAgg.eval(null);
+        JSONArray jsonArray = JSON.parseArray(json);
+
+        Object[] arr1 = jsonArray.toArray();
+        Object[] arr2 = allValues.toArray();
+        Arrays.sort(arr1);
+        Arrays.sort(arr2);
+        Assert.assertTrue(Arrays.equals(arr1, arr2));
+    }
+}
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonObjectAggTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonObjectAggTest.java
new file mode 100644
index 000000000..1c8dc24de
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/expression/calc/aggfunctions/JsonObjectAggTest.java
@@ -0,0 +1,96 @@
+package com.alibaba.polardbx.optimizer.core.expression.calc.aggfunctions;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.polardbx.common.utils.Assert;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.optimizer.core.expression.IFunction;
+import com.alibaba.polardbx.optimizer.core.function.calc.scalar.filter.In;
+import com.alibaba.polardbx.optimizer.core.row.ArrayRow;
+import junit.framework.TestCase;
+import org.apache.calcite.sql.SqlKind;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class JsonObjectAggTest {
+
+    @Test
+    public void partitionAggTest1() {
+        JsonObjectAgg jsonObjectAgg = new JsonObjectAgg(new int[] {0, 1}, -1);
+        Assert.assertTrue(IFunction.FunctionType.Aggregate.equals(jsonObjectAgg.getFunctionType()));
+        Assert.assertTrue(DataTypes.JsonType.equals(jsonObjectAgg.getReturnType()));
+        Assert.assertTrue("JSON_OBJECTAGG".equalsIgnoreCase(jsonObjectAgg.getFunctionNames()[0]));
+        Assert.assertTrue(SqlKind.JSON_OBJECTAGG.equals(jsonObjectAgg.getSqlKind()));
+    }
+
+    @Test
+    public void globalAggTest1() {
+        JsonObjectGlobalAgg jsonObjectGlobalAgg = new JsonObjectGlobalAgg(0, -1);
+        Assert.assertTrue(IFunction.FunctionType.Aggregate.equals(jsonObjectGlobalAgg.getFunctionType()));
+        Assert.assertTrue(DataTypes.JsonType.equals(jsonObjectGlobalAgg.getReturnType()));
+        Assert.assertTrue("JSON_OBJECT_GLOBALAGG".equalsIgnoreCase(jsonObjectGlobalAgg.getFunctionNames()[0]));
+        Assert.assertTrue(SqlKind.JSON_OBJECT_GLOBALAGG.equals(jsonObjectGlobalAgg.getSqlKind()));
+    }
+
+    @Test
+    public void partitionAggTest2() {
+        JsonObjectAgg jsonObjectAgg = new JsonObjectAgg(new int[] {0, 1}, -1);
+
+        //没有元素时,返回null
+        Assert.assertTrue(jsonObjectAgg.eval(null) == null);
+
+        Map> allValues = new HashMap<>();
+        for (int i = 0; i < 100; i++) {
+            String key = String.valueOf(i % 10);
+            int value = i;
+            allValues.putIfAbsent(key, new HashSet<>());
+            allValues.get(key).add(value);
+
+            ArrayRow arrayRow = new ArrayRow(new Object[] {key, value});
+            jsonObjectAgg.conductAgg(arrayRow);
+        }
+
+        String json = (String) jsonObjectAgg.eval(null);
+        JSONObject jsonObject = JSON.parseObject(json);
+        for (Map.Entry entry : jsonObject.entrySet()) {
+            Assert.assertTrue(allValues.get(entry.getKey()).contains((int) entry.getValue()));
+        }
+
+    }
+
+    @Test
+    public void globalAggTest2() {
+        JsonObjectGlobalAgg jsonObjectGlobalAgg = new JsonObjectGlobalAgg(0, -1);
+
+        //没有元素时,返回null
+        Assert.assertTrue(jsonObjectGlobalAgg.eval(null) == null);
+
+        Map> allValues = new HashMap<>();
+        JSONObject input = new JSONObject();
+        for (int i = 0; i < 100; i++) {
+            String key = String.valueOf(i % 10);
+            int value = i;
+            allValues.putIfAbsent(key, new HashSet<>());
+            allValues.get(key).add(value);
+            input.put(key, value);
+            if (i % 6 == 0) {
+                ArrayRow row = new ArrayRow(new Object[] {input.toJSONString()});
+                jsonObjectGlobalAgg.conductAgg(row);
+                input = new JSONObject();
+            }
+        }
+        ArrayRow row = new ArrayRow(new Object[] {input.toJSONString()});
+        jsonObjectGlobalAgg.conductAgg(row);
+
+        String json = (String) jsonObjectGlobalAgg.eval(null);
+        JSONObject jsonObject = JSON.parseObject(json);
+        for (Map.Entry entry : jsonObject.entrySet()) {
+            Assert.assertTrue(allValues.get(entry.getKey()).contains((int) entry.getValue()));
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/field/OriginalTimestampValueFieldTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/field/OriginalTimestampValueFieldTest.java
new file mode 100644
index 000000000..33d0c452d
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/field/OriginalTimestampValueFieldTest.java
@@ -0,0 +1,99 @@
+package com.alibaba.polardbx.optimizer.core.field;
+
+import com.alibaba.polardbx.common.type.MySQLStandardFieldType;
+import com.alibaba.polardbx.common.utils.time.core.MysqlDateTime;
+import com.alibaba.polardbx.common.utils.time.core.OriginalTimestamp;
+import com.alibaba.polardbx.common.utils.time.parser.StringTimeParser;
+import com.alibaba.polardbx.common.utils.time.parser.TimeParserFlags;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.DateTimeType;
+import com.alibaba.polardbx.optimizer.core.datatype.DateType;
+import com.alibaba.polardbx.optimizer.core.datatype.TimestampType;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.sql.Types;
+
+import static com.alibaba.polardbx.common.type.MySQLStandardFieldType.MYSQL_TYPE_DATETIME2;
+import static com.alibaba.polardbx.common.type.MySQLStandardFieldType.MYSQL_TYPE_NEWDATE;
+import static com.alibaba.polardbx.common.type.MySQLStandardFieldType.MYSQL_TYPE_TIMESTAMP2;
+
+public class OriginalTimestampValueFieldTest {
+
+    @Test
+    public void testDatetime() {
+        final String timeStr = "2024-06-13 16:36:55.545131";
+        doTest(MYSQL_TYPE_DATETIME2, 6, timeStr, "2024-06-13 16:36:55.545131");
+        doTest(MYSQL_TYPE_DATETIME2, 5, timeStr, "2024-06-13 16:36:55.54513");
+        doTest(MYSQL_TYPE_DATETIME2, 4, timeStr, "2024-06-13 16:36:55.5451");
+        doTest(MYSQL_TYPE_DATETIME2, 3, timeStr, "2024-06-13 16:36:55.545");
+        doTest(MYSQL_TYPE_DATETIME2, 2, timeStr, "2024-06-13 16:36:55.55");
+        doTest(MYSQL_TYPE_DATETIME2, 1, timeStr, "2024-06-13 16:36:55.5");
+        doTest(MYSQL_TYPE_DATETIME2, 0, timeStr, "2024-06-13 16:36:56");
+    }
+
+    @Test
+    public void testDate() {
+        final String dateStr = "2024-06-13 23:59:59.875239";
+        doTest(MYSQL_TYPE_NEWDATE, 6, dateStr, "2024-06-14 00:00:00");
+    }
+
+    @Test
+    public void testTimestamp() {
+        final String timeStr = "2024-06-13 16:36:55.545131";
+        doTest(MYSQL_TYPE_TIMESTAMP2, 6, timeStr, "2024-06-13 16:36:55.545131");
+        doTest(MYSQL_TYPE_TIMESTAMP2, 5, timeStr, "2024-06-13 16:36:55.54513");
+        doTest(MYSQL_TYPE_TIMESTAMP2, 4, timeStr, "2024-06-13 16:36:55.5451");
+        doTest(MYSQL_TYPE_TIMESTAMP2, 3, timeStr, "2024-06-13 16:36:55.545");
+        doTest(MYSQL_TYPE_TIMESTAMP2, 2, timeStr, "2024-06-13 16:36:55.55");
+        doTest(MYSQL_TYPE_TIMESTAMP2, 1, timeStr, "2024-06-13 16:36:55.5");
+        doTest(MYSQL_TYPE_TIMESTAMP2, 0, timeStr, "2024-06-13 16:36:56");
+    }
+
+    private void doTest(MySQLStandardFieldType standardFieldType, int scale, String timeStr, String resultStr) {
+        DataType dataType;
+        StorageField storageField;
+        int sqlType;
+        switch (standardFieldType) {
+        case MYSQL_TYPE_DATE:
+        case MYSQL_TYPE_NEWDATE:
+            dataType = new DateType();
+            storageField = new DateField(dataType);
+            sqlType = Types.DATE;
+            break;
+        case MYSQL_TYPE_DATETIME:
+        case MYSQL_TYPE_DATETIME2:
+            dataType = new DateTimeType(scale);
+            storageField = new DatetimeField(dataType);
+            sqlType = Types.TIMESTAMP;
+            break;
+        case MYSQL_TYPE_TIMESTAMP:
+        case MYSQL_TYPE_TIMESTAMP2:
+            dataType = new TimestampType(scale);
+            storageField = new TimestampField(dataType);
+            sqlType = Types.TIMESTAMP;
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+
+        // 2024-06-13 16:36:55.545131
+        MysqlDateTime mysqlDateTime = StringTimeParser.parseString(
+            timeStr.getBytes(), sqlType,
+            TimeParserFlags.FLAG_TIME_FUZZY_DATE | TimeParserFlags.FLAG_TIME_NO_DATE_FRAC_WARN);
+
+        OriginalTimestamp originalTimestamp = new OriginalTimestamp(mysqlDateTime);
+
+        TypeConversionStatus typeConversionStatus = storageField.store(originalTimestamp, dataType);
+
+        System.out.println(typeConversionStatus);
+        System.out.println(originalTimestamp);
+        System.out.println(storageField.datetimeValue());
+
+        Assert.assertTrue(typeConversionStatus == TypeConversionStatus.TYPE_OK);
+
+        Assert.assertTrue(originalTimestamp.toString().equals(timeStr));
+
+        Assert.assertTrue(storageField.datetimeValue().toString().equals(resultStr));
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/datatime/StrToDateTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/datatime/StrToDateTest.java
new file mode 100644
index 000000000..50de75bc3
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/datatime/StrToDateTest.java
@@ -0,0 +1,63 @@
+package com.alibaba.polardbx.optimizer.core.function.calc.scalar.datatime;
+
+import com.alibaba.polardbx.common.utils.time.core.MysqlDateTime;
+import com.alibaba.polardbx.common.utils.time.core.OriginalTimestamp;
+import com.alibaba.polardbx.optimizer.config.table.Field;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.datatype.DataType;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypes;
+import com.alibaba.polardbx.optimizer.core.datatype.DateTimeType;
+import org.apache.commons.lang3.tuple.ImmutableTriple;
+import org.apache.commons.lang3.tuple.Triple;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class StrToDateTest {
+
+    List> list;
+    StrToDate strToDate;
+    ExecutionContext ec;
+
+    @Before
+    public void prepare() throws IOException {
+        list = new ArrayList<>(
+            Arrays.asList(
+                new ImmutableTriple<>(
+                    "2020-08-01 00:00:00",
+                    "%Y-%m-%d %T",
+                    new OriginalTimestamp(new MysqlDateTime(2020, 8, 1, 0, 0, 0, 0))
+                ),
+                new ImmutableTriple<>(
+                    "Monday 7th November 2022 13:45:30",
+                    "%W %D %M %Y %T",
+                    new OriginalTimestamp(new MysqlDateTime(2022, 11, 7, 13, 45, 30, 0))
+                ),
+                new ImmutableTriple<>(
+                    "01:02:03 PM",
+                    "%r",
+                    new OriginalTimestamp(new MysqlDateTime(0, 0, 0, 13, 2, 3, 0))
+                )
+            )
+        );
+    }
+
+    @Test
+    public void test() {
+        for (Triple triple : list) {
+            strToDate = new StrToDate(Arrays.asList(DataTypes.StringType, DataTypes.StringType), new DateTimeType());
+            strToDate.setResultField(new Field(new DateTimeType()));
+            ec = new ExecutionContext();
+            OriginalTimestamp result =
+                (OriginalTimestamp) strToDate.compute(new Object[] {triple.getLeft(), triple.getMiddle()}, ec);
+            assertEquals(triple.getRight(), result);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/encryption/AesTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/encryption/AesTest.java
new file mode 100644
index 000000000..afc053344
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/encryption/AesTest.java
@@ -0,0 +1,86 @@
+package com.alibaba.polardbx.optimizer.core.function.calc.scalar.encryption;
+
+import com.alibaba.polardbx.common.properties.ConnectionProperties;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class AesTest {
+
+    @Test
+    public void testAesEncryptAndDecrypt() {
+        AesEncrypt encrypt = new AesEncrypt();
+        ExecutionContext context = new ExecutionContext();
+        context.setExtraServerVariables(new HashMap<>());
+        String text = "hello";
+        String key = "goodbye";
+        Object[] args1 = new Object[] {
+            text, key
+        };
+        Object encResult = encrypt.compute(args1, context);
+
+        AesDecrypt decrypt = new AesDecrypt();
+        Object[] args2 = new Object[] {
+            encResult, key
+        };
+        Object decResult = decrypt.compute(args2, context);
+        Assert.assertEquals(text, decResult);
+    }
+
+    @Test
+    public void testConcurrent() {
+        final int threadCount = 5;
+        final int testCount = 10;
+        AtomicReference exceptionRef = new AtomicReference<>();
+        for (int i = 0; i < threadCount; i++) {
+            new Thread(() -> {
+                AesEncrypt encrypt = new AesEncrypt();
+                AesDecrypt decrypt = new AesDecrypt();
+
+                ExecutionContext context = new ExecutionContext();
+                context.setExtraServerVariables(new HashMap<>());
+                String text = "hello";
+                String key = "goodbye";
+                for (int j = 0; j < testCount; j++) {
+                    Object[] args1 = new Object[] {
+                        text, key
+                    };
+                    Object encResult = encrypt.compute(args1, context);
+
+                    Object[] args2 = new Object[] {
+                        encResult, key
+                    };
+                    Object decResult = decrypt.compute(args2, context);
+                    if (!Objects.equals(text, decResult)) {
+                        exceptionRef.set(new RuntimeException("Decryption failed"));
+                        break;
+                    }
+                }
+            }).start();
+        }
+        Assert.assertNull(exceptionRef.get());
+    }
+
+    @Test
+    public void testIncorrectParamCount() {
+        AesEncrypt encrypt = new AesEncrypt();
+        ExecutionContext context = new ExecutionContext();
+        context.setExtraServerVariables(new HashMap<>());
+        context.getExtraServerVariables().put(ConnectionProperties.BLOCK_ENCRYPTION_MODE, "aes-128-cfb8");
+        String text = "hello";
+        String key = "goodbye";
+        Object[] args1 = new Object[] {
+            text, key
+        };
+        try {
+            Object encResult = encrypt.compute(args1, context);
+            Assert.fail("Expect failed");
+        } catch (Exception e) {
+            Assert.assertTrue(e.getMessage().contains("Incorrect parameter count in the call"));
+        }
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/UuidBinTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/UuidBinTest.java
new file mode 100644
index 000000000..102cd1614
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/function/calc/scalar/miscellaneous/UuidBinTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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 com.alibaba.polardbx.optimizer.core.function.calc.scalar.miscellaneous;
+
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import io.airlift.slice.Slice;
+import io.airlift.slice.Slices;
+import org.junit.Test;
+
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class UuidBinTest {
+
+    @Test
+    public void testBinToUuid() {
+        UUID uuid = UUID.randomUUID();
+        BinToUuid function = new BinToUuid();
+        UuidToBin function1 = new UuidToBin();
+
+        byte[] uuidBytes1 = (byte[]) function1.compute(new Object[] {uuid}, new ExecutionContext());
+        byte[] uuidBytes2 = (byte[]) function1.compute(new Object[] {uuid, 1}, new ExecutionContext());
+        Slice slice1 = Slices.wrappedBuffer(uuidBytes1);
+        Slice slice2 = Slices.wrappedBuffer(uuidBytes2);
+
+        Object result = function.compute(new Object[] {slice1}, new ExecutionContext());
+        assertEquals(uuid.toString(), result);
+
+        Object result1 = function.compute(new Object[] {slice1, 0}, new ExecutionContext());
+        assertEquals(uuid.toString(), result1);
+
+        Object result2 = function.compute(new Object[] {slice2, 1}, new ExecutionContext());
+        assertEquals(uuid.toString(), result2);
+    }
+
+    @Test
+    public void testBinToUuidWithNullArgument() {
+        BinToUuid function = new BinToUuid();
+        Object result = function.compute(new Object[] {null}, new ExecutionContext());
+        assertNull(result);
+    }
+
+    @Test
+    public void testUuidToBinWithNullArgument() {
+        UuidToBin function = new UuidToBin();
+        Object result = function.compute(new Object[] {null}, new ExecutionContext());
+        assertNull(result);
+    }
+
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/planner/IsCciTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/planner/IsCciTest.java
new file mode 100644
index 000000000..95cd77347
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/planner/IsCciTest.java
@@ -0,0 +1,121 @@
+package com.alibaba.polardbx.optimizer.core.planner;
+
+import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException;
+import com.alibaba.polardbx.gms.metadb.table.TablesExtAccessor;
+import com.alibaba.polardbx.gms.metadb.table.TablesExtRecord;
+import com.alibaba.polardbx.gms.partition.TablePartitionAccessor;
+import com.alibaba.polardbx.gms.partition.TablePartitionRecord;
+import com.alibaba.polardbx.gms.topology.DbInfoManager;
+import com.alibaba.polardbx.gms.util.MetaDbUtil;
+import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager;
+import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.MockedStatic;
+
+import java.sql.Connection;
+import java.util.Collections;
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+
+public class IsCciTest {
+
+    private MockedStatic metaDbUtilMockedStatic;
+
+    private TablePartitionAccessor tablePartitionAccessorMock;
+
+    private TablesExtAccessor tablesExtAccessorMock;
+
+    @Before
+    public void setUp() {
+        metaDbUtilMockedStatic = mockStatic(MetaDbUtil.class);
+        tablePartitionAccessorMock = mock(TablePartitionAccessor.class);
+        tablesExtAccessorMock = mock(TablesExtAccessor.class);
+    }
+
+    @After
+    public void tearDown() {
+        metaDbUtilMockedStatic.close();
+    }
+
+    @Test
+    public void testIsCciWithNewPartitionDb() throws Exception {
+        try (MockedStatic dbInfoManagerMockedStatic = mockStatic(DbInfoManager.class)) {
+            DbInfoManager dbInfoManagerMock = mock(DbInfoManager.class);
+            dbInfoManagerMockedStatic.when(DbInfoManager::getInstance).thenReturn(dbInfoManagerMock);
+            when(dbInfoManagerMock.isNewPartitionDb(anyString())).thenReturn(true);
+
+            Connection connectionMock = mock(Connection.class);
+            metaDbUtilMockedStatic.when(MetaDbUtil::getConnection).thenReturn(connectionMock);
+
+            List tablePartitionRecordsMock =
+                Collections.singletonList(new TablePartitionRecord());
+            when(tablePartitionAccessorMock.getTablePartitionsByDbNameTbName(anyString(), anyString(), eq(false)))
+                .thenReturn(tablePartitionRecordsMock);
+            tablePartitionRecordsMock.get(0).tblType = 7;
+
+            boolean result =
+                CBOUtil.isCci("schemaName", "tableName", tablePartitionAccessorMock, tablesExtAccessorMock);
+
+            Assert.assertTrue(result);
+        }
+    }
+
+    @Test
+    public void testIsCciWithOldPartitionDb() throws Exception {
+        try (MockedStatic dbInfoManagerMockedStatic = mockStatic(DbInfoManager.class)) {
+            DbInfoManager dbInfoManagerMock = mock(DbInfoManager.class);
+            dbInfoManagerMockedStatic.when(DbInfoManager::getInstance).thenReturn(dbInfoManagerMock);
+            when(dbInfoManagerMock.isNewPartitionDb(anyString())).thenReturn(false);
+
+            Connection connectionMock = mock(Connection.class);
+            metaDbUtilMockedStatic.when(MetaDbUtil::getConnection).thenReturn(connectionMock);
+
+            TablesExtRecord tablesExtRecordsMock = new TablesExtRecord();
+            when(tablesExtAccessorMock.query(anyString(), anyString(), eq(false)))
+                .thenReturn(tablesExtRecordsMock);
+            tablesExtRecordsMock.tableType = GsiMetaManager.TableType.COLUMNAR.getValue();
+
+            boolean result =
+                CBOUtil.isCci("schemaName", "tableName", tablePartitionAccessorMock, tablesExtAccessorMock);
+
+            Assert.assertTrue(result);
+        }
+    }
+
+    @Test
+    public void testIsCciWhenExceptionThrown() {
+        metaDbUtilMockedStatic.when(() -> MetaDbUtil.getConnection())
+            .thenThrow(new TddlNestableRuntimeException("Failed to get connection"));
+        try {
+            CBOUtil.isCci("schemaName", "tableName", tablePartitionAccessorMock, tablesExtAccessorMock);
+            Assert.fail("Expected TddlNestableRuntimeException to be thrown");
+        } catch (TddlNestableRuntimeException e) {
+            Assert.assertEquals("check table is cci failed!", e.getMessage());
+        } catch (Exception e) {
+            Assert.fail("Unexpected exception type: " + e.getClass().getSimpleName());
+        }
+    }
+
+    @Test
+    public void testIsCciWithBlankSchemaName() {
+        Assert.assertFalse(CBOUtil.isCci("", "tableName", tablePartitionAccessorMock, tablesExtAccessorMock));
+    }
+
+    @Test
+    public void testIsCciWithBlankTableName() {
+        Assert.assertFalse(CBOUtil.isCci("schemaName", "", tablePartitionAccessorMock, tablesExtAccessorMock));
+    }
+
+    @Test
+    public void testIsCciWithBothBlank() {
+        Assert.assertFalse(CBOUtil.isCci("", "", tablePartitionAccessorMock, tablesExtAccessorMock));
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/planner/PlanCacheTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/planner/PlanCacheTest.java
index 769295d6e..31f1a9fec 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/planner/PlanCacheTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/planner/PlanCacheTest.java
@@ -16,20 +16,42 @@
 
 package com.alibaba.polardbx.optimizer.core.planner;
 
+import com.alibaba.polardbx.common.properties.BooleanConfigParam;
+import com.alibaba.polardbx.common.properties.ConnectionParams;
 import com.alibaba.polardbx.common.utils.Assert;
 import com.alibaba.polardbx.common.properties.ConnectionProperties;
 import com.alibaba.polardbx.common.properties.DynamicConfig;
+import com.alibaba.polardbx.common.properties.ParamManager;
 import com.alibaba.polardbx.druid.sql.parser.ByteString;
+import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager;
+import com.alibaba.polardbx.optimizer.PlannerContext;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.parse.SqlParameterizeUtils;
 import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized;
 import com.alibaba.polardbx.planner.common.PlanTestCommon;
+import com.clearspring.analytics.util.Lists;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
+import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Values;
+import org.apache.calcite.rel.logical.LogicalValues;
 import org.junit.Test;
 import org.junit.runners.Parameterized;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.stubbing.Answer;
 
+import java.lang.reflect.Field;
 import java.util.List;
+import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.mockStatic;
 
 public class PlanCacheTest extends PlanTestCommon {
 //    private static String schemaName = "tddl";
@@ -130,4 +152,253 @@ public void testInSqlBound2() throws ExecutionException {
             Assert.fail("plan cache in sql size over limit:" + planCache.getCache().size());
         }
     }
+
+    @Test
+    public void testColumnarCacheSwitch() throws Exception {
+        boolean[] values = new boolean[] {true, false};
+        for (boolean cacheColumnar : values) {
+            for (boolean cacheColumnarPlanCache : values) {
+                for (boolean useColumnar : values) {
+                    for (boolean useColumnarPlanCache : values) {
+                        columnarPlanCacheSwitch(cacheColumnar, cacheColumnarPlanCache, useColumnar,
+                            useColumnarPlanCache);
+                    }
+                }
+            }
+        }
+    }
+
+    void columnarPlanCacheSwitch(boolean cacheColumnar, boolean cacheColumnarPlanCache, boolean useColumnar,
+                                 boolean useColumnarPlanCache) throws Exception {
+        MetaDbInstConfigManager.setConfigFromMetaDb(false);
+        boolean config = DynamicConfig.getInstance().colPlanCache();
+        ExecutionContext executionContext = new ExecutionContext("test");
+        LogicalValues va0 = Mockito.mock(LogicalValues.class);
+        LogicalValues va1 = Mockito.mock(LogicalValues.class);
+        try (MockedStatic plannerContextMockedStatic = mockStatic(PlannerContext.class)) {
+            DynamicConfig.getInstance()
+                .loadValue(null, ConnectionProperties.ENABLE_COLUMNAR_PLAN_CACHE, String.valueOf(useColumnarPlanCache));
+            PlanCache planCache = Mockito.mock(PlanCache.class);
+            Mockito.doNothing().when(planCache).invalidateByCacheKey(any());
+
+            SqlParameterized sqlParameterized = new SqlParameterized("", Lists.newArrayList());
+            Field tablesField = sqlParameterized.getClass().getDeclaredField("tables");
+            tablesField.setAccessible(true);
+            tablesField.set(sqlParameterized, Sets.newHashSet());
+
+            plannerContextMockedStatic.when(() -> PlannerContext.getPlannerContext(va0)).thenAnswer(
+                invocation -> {
+                    PlannerContext pc = Mockito.mock(PlannerContext.class);
+                    Mockito.when(pc.isUseColumnar()).thenReturn(cacheColumnar);
+                    Mockito.when(pc.isUseColumnarPlanCache())
+                        .thenReturn(cacheColumnarPlanCache);
+                    return pc;
+                });
+
+            plannerContextMockedStatic.when(() -> PlannerContext.getPlannerContext(va1)).thenAnswer(
+                invocation -> {
+                    PlannerContext pc = Mockito.mock(PlannerContext.class);
+                    Mockito.when(pc.isUseColumnar()).thenReturn(useColumnar);
+                    Mockito.when(pc.isUseColumnarPlanCache())
+                        .thenReturn(executionContext.isColumnarPlanCache());
+                    return pc;
+                });
+
+            Mockito.when(planCache.getCacheLoader(any(), any(), any(), any(), anyBoolean(), any(), any())).thenAnswer(
+                (Answer>) invocation -> () -> {
+                    ExecutionPlan plan = Mockito.mock(ExecutionPlan.class);
+                    Mockito.when(plan.getPlan()).thenReturn(va1);
+                    return plan;
+                }
+            );
+
+            AtomicInteger count = new AtomicInteger(0);
+            Mockito.when(planCache.getPlanWithLoader(any(), any())).thenAnswer(
+                (Answer) invocation -> {
+                    count.getAndIncrement();
+                    if (count.get() == 1) {
+                        ExecutionPlan plan = Mockito.mock(ExecutionPlan.class);
+                        Mockito.when(plan.getPlan()).thenReturn(va0);
+                        return plan;
+                    }
+                    Object[] args = invocation.getArguments();
+                    Callable loader = (Callable) args[1];
+                    return loader.call();
+                });
+
+            Mockito.when(planCache.savePlanCachedKey(any(), any(), any(), any())).thenAnswer(
+                (Answer) invocation -> (ExecutionPlan) invocation.getArguments()[1]);
+
+            Mockito.when(planCache.checkColumnarDisable(any(), any(), any(), any(), any())).thenReturn(null);
+            doCallRealMethod().when(planCache).checkColumnarPlanCache(any(), any(), any(), any(), any(), any());
+            doCallRealMethod().when(planCache).getFromCache(any(), any(), any(), any(), anyBoolean());
+            ExecutionPlan plan = planCache.getFromCache("test", sqlParameterized, null, executionContext, false);
+
+            // row plan cached
+            if (!cacheColumnar) {
+                // plan must be row
+                Assert.check(!PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnar());
+                Assert.check(count.get() == 1);
+                return;
+            }
+
+            // cacheColumnar == true
+            if (cacheColumnarPlanCache == useColumnarPlanCache) {
+                Assert.check(count.get() == 1);
+            }
+
+            if (cacheColumnarPlanCache && useColumnar && useColumnarPlanCache) {
+                Assert.check(PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnar());
+                Assert.check(PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnarPlanCache());
+                Assert.check(count.get() == 1);
+            }
+            if (cacheColumnarPlanCache && useColumnar && !useColumnarPlanCache) {
+                Assert.check(plan == null);
+                Assert.check(count.get() == 2);
+            }
+            if (cacheColumnarPlanCache && !useColumnar && useColumnarPlanCache) {
+                Assert.check(PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnar());
+                Assert.check(PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnarPlanCache());
+                Assert.check(count.get() == 1);
+            }
+            if (cacheColumnarPlanCache && !useColumnar && !useColumnarPlanCache) {
+                Assert.check(!PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnar());
+                Assert.check(!PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnarPlanCache());
+                Assert.check(count.get() == 2);
+            }
+            if (!cacheColumnarPlanCache && useColumnar && useColumnarPlanCache) {
+                Assert.check(PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnar());
+                Assert.check(PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnarPlanCache());
+                Assert.check(count.get() == 2);
+            }
+            if (!cacheColumnarPlanCache && useColumnar && !useColumnarPlanCache) {
+                Assert.check(plan == null);
+                Assert.check(count.get() == 1);
+            }
+            if (!cacheColumnarPlanCache && !useColumnar && useColumnarPlanCache) {
+                Assert.check(!PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnar());
+                Assert.check(PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnarPlanCache());
+                Assert.check(count.get() == 2);
+            }
+            if (!cacheColumnarPlanCache && !useColumnar && !useColumnarPlanCache) {
+                Assert.check(plan == null);
+                Assert.check(count.get() == 1);
+            }
+        } finally {
+            DynamicConfig.getInstance()
+                .loadValue(null, ConnectionProperties.ENABLE_COLUMNAR_PLAN_CACHE, String.valueOf(config));
+        }
+    }
+
+    @Test
+    public void testColumnarSwitch() throws Exception {
+        boolean[] values = new boolean[] {true, false};
+        for (boolean cacheColumnar : values) {
+            for (boolean enableColumnar : values) {
+                columnarSwitch(cacheColumnar, enableColumnar);
+            }
+        }
+    }
+
+    void columnarSwitch(boolean cacheColumnar, boolean enableColumnar) throws Exception {
+        MetaDbInstConfigManager.setConfigFromMetaDb(false);
+        ExecutionContext executionContext = new ExecutionContext("test");
+        LogicalValues va0 = Mockito.mock(LogicalValues.class);
+        LogicalValues va1 = Mockito.mock(LogicalValues.class);
+        try (MockedStatic plannerContextMockedStatic = mockStatic(PlannerContext.class)) {
+            DynamicConfig.getInstance().existColumnarNodes(true);
+
+            ParamManager pm = Mockito.mock(ParamManager.class);
+            executionContext.setParamManager(pm);
+            Mockito.when(pm.getBoolean(any())).thenAnswer(
+                invocation -> {
+                    BooleanConfigParam param = invocation.getArgument(0);
+                    if (param == ConnectionParams.ENABLE_COLUMNAR_OPTIMIZER) {
+                        return enableColumnar;
+                    }
+                    if (param == ConnectionParams.ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR) {
+                        return enableColumnar;
+                    }
+                    return false;
+                }
+            );
+            PlanCache planCache = Mockito.mock(PlanCache.class);
+            Mockito.doNothing().when(planCache).invalidateByCacheKey(any());
+
+            SqlParameterized sqlParameterized = new SqlParameterized("", Lists.newArrayList());
+            Field tablesField = sqlParameterized.getClass().getDeclaredField("tables");
+            tablesField.setAccessible(true);
+            tablesField.set(sqlParameterized, Sets.newHashSet());
+
+            plannerContextMockedStatic.when(() -> PlannerContext.getPlannerContext(va0)).thenAnswer(
+                invocation -> {
+                    PlannerContext pc = Mockito.mock(PlannerContext.class);
+                    Mockito.when(pc.isUseColumnar()).thenReturn(cacheColumnar);
+                    Mockito.when(pc.isUseColumnarPlanCache()).thenReturn(true);
+                    return pc;
+                });
+
+            plannerContextMockedStatic.when(() -> PlannerContext.getPlannerContext(va1)).thenAnswer(
+                invocation -> {
+                    PlannerContext pc = Mockito.mock(PlannerContext.class);
+                    Mockito.when(pc.isUseColumnar()).thenReturn(enableColumnar);
+                    Mockito.when(pc.isUseColumnarPlanCache()).thenReturn(true);
+                    return pc;
+                });
+
+            Mockito.when(planCache.getCacheLoader(any(), any(), any(), any(), anyBoolean(), any(), any())).thenAnswer(
+                (Answer>) invocation -> () -> {
+                    ExecutionPlan plan = Mockito.mock(ExecutionPlan.class);
+                    Mockito.when(plan.getPlan()).thenReturn(va1);
+                    return plan;
+                }
+            );
+
+            AtomicInteger count = new AtomicInteger(0);
+            Mockito.when(planCache.getPlanWithLoader(any(), any())).thenAnswer(
+                (Answer) invocation -> {
+                    count.getAndIncrement();
+                    if (count.get() == 1) {
+                        ExecutionPlan plan = Mockito.mock(ExecutionPlan.class);
+                        Mockito.when(plan.getPlan()).thenReturn(va0);
+                        return plan;
+                    }
+                    Object[] args = invocation.getArguments();
+                    Callable loader = (Callable) args[1];
+                    return loader.call();
+                });
+
+            Mockito.when(planCache.savePlanCachedKey(any(), any(), any(), any())).thenAnswer(
+                (Answer) invocation -> (ExecutionPlan) invocation.getArguments()[1]);
+
+            Mockito.when(planCache.checkColumnarPlanCache(any(), any(), any(), any(), any(), any())).thenAnswer(
+                invocation -> invocation.getArgument(5));
+
+            doCallRealMethod().when(planCache).checkColumnarDisable(any(), any(), any(), any(), any());
+            doCallRealMethod().when(planCache).getFromCache(any(), any(), any(), any(), anyBoolean());
+            ExecutionPlan plan = planCache.getFromCache("test", sqlParameterized, null, executionContext, false);
+
+            // row plan cached
+            if (!cacheColumnar) {
+                // plan must be row
+                Assert.check(!PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnar());
+                Assert.check(count.get() == 1);
+                return;
+            }
+
+            // cacheColumnar == true
+            if (enableColumnar) {
+                Assert.check(PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnar());
+                Assert.check(count.get() == 1);
+            }
+
+            if (!enableColumnar) {
+                Assert.check(!PlannerContext.getPlannerContext(plan.getPlan()).isUseColumnar());
+                Assert.check(count.get() == 2);
+            }
+        } finally {
+            DynamicConfig.getInstance().existColumnarNodes(false);
+        }
+    }
+
 }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/planner/PlannerTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/planner/PlannerTest.java
new file mode 100644
index 000000000..2bb52f27c
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/planner/PlannerTest.java
@@ -0,0 +1,40 @@
+package com.alibaba.polardbx.optimizer.core.planner;
+
+import com.alibaba.polardbx.common.properties.ConnectionProperties;
+import com.alibaba.polardbx.optimizer.PlannerContext;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author fangwu
+ */
+public class PlannerTest {
+
+    @Test
+    public void testEnableDirectPlanFalse() {
+        PlannerContext pc = new PlannerContext();
+        pc.getParamManager().getProps().put(ConnectionProperties.ENABLE_DIRECT_PLAN, "false");
+        ExecutionPlan.DirectMode mode = new Planner().shouldDirectByTable(null, null, pc, null);
+
+        assertEquals(ExecutionPlan.DirectMode.NONE, mode);
+    }
+
+    @Test
+    public void testDnHint() {
+        PlannerContext pc = new PlannerContext();
+        pc.getParamManager().getProps().put(ConnectionProperties.DN_HINT, "test hint");
+        ExecutionPlan.DirectMode mode = new Planner().shouldDirectByTable(null, null, pc, null);
+
+        assertEquals(ExecutionPlan.DirectMode.NONE, mode);
+    }
+
+    @Test
+    public void testForceIndexHint() {
+        PlannerContext pc = new PlannerContext();
+        pc.setLocalIndexHint(true);
+        ExecutionPlan.DirectMode mode = new Planner().shouldDirectByTable(null, null, pc, null);
+
+        assertEquals(ExecutionPlan.DirectMode.NONE, mode);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/OSSTableScanTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/OSSTableScanTest.java
new file mode 100644
index 000000000..946d0379c
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/OSSTableScanTest.java
@@ -0,0 +1,385 @@
+package com.alibaba.polardbx.optimizer.core.rel;
+
+import com.alibaba.polardbx.common.exception.code.ErrorCode;
+import com.alibaba.polardbx.common.jdbc.IConnection;
+import com.alibaba.polardbx.common.jdbc.IDataSource;
+import com.alibaba.polardbx.common.jdbc.ITransactionPolicy;
+import com.alibaba.polardbx.common.jdbc.ParameterContext;
+import com.alibaba.polardbx.common.jdbc.Parameters;
+import com.alibaba.polardbx.common.type.TransactionType;
+import com.alibaba.polardbx.common.utils.Assert;
+import com.alibaba.polardbx.druid.sql.parser.ByteString;
+import com.alibaba.polardbx.optimizer.PlannerContext;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan;
+import com.alibaba.polardbx.optimizer.core.planner.Planner;
+import com.alibaba.polardbx.optimizer.parse.FastsqlParser;
+import com.alibaba.polardbx.optimizer.parse.SqlParameterizeUtils;
+import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized;
+import com.alibaba.polardbx.optimizer.utils.IConnectionHolder;
+import com.alibaba.polardbx.optimizer.utils.ITimestampOracle;
+import com.alibaba.polardbx.optimizer.utils.ITransaction;
+import com.alibaba.polardbx.optimizer.utils.ITransactionManagerUtil;
+import com.alibaba.polardbx.optimizer.utils.InventoryMode;
+import com.alibaba.polardbx.optimizer.utils.OptimizerUtils;
+import com.alibaba.polardbx.planner.common.BasePlannerTest;
+import com.alibaba.polardbx.stats.TransactionStatistics;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlNode;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.sql.SQLException;
+import java.sql.SQLSyntaxErrorException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.junit.Assert.*;
+
+public class OSSTableScanTest extends BasePlannerTest {
+
+    private static final String schemaName = "test_oss_columnar_flashback";
+    private static final long MOCK_TSO = 7147436271206400000L;
+
+    public OSSTableScanTest() {
+        super(schemaName);
+    }
+
+    @Override
+    protected void initBasePlannerTestEnv() {
+        this.useNewPartDb = true;
+    }
+
+    @Before
+    public void prepareSchemaAndOssTable() throws SQLSyntaxErrorException {
+        prepareSchemaByDdl();
+        String createOssTableSql = "create table t1(id int, name varchar(10)) partition by hash(id) engine=oss";
+        buildTable(appName, createOssTableSql);
+    }
+
+    @Test
+    public void getFlashbackQueryTso() {
+        runFlashbackQueryAndCompareTso("select * from t1 as of tso 100 + tso_timestamp()", 100 + MOCK_TSO);
+    }
+
+    @Test
+    public void getFlashbackQueryTimestamp() {
+        runFlashbackQueryAndCompareTso("select * from t1 as of timestamp '2024-01-01 12:00:00'", MOCK_TSO);
+    }
+
+    @Test
+    public void getFlashbackQueryTsoForAbnormalValue() {
+        runFlashbackQueryAndCompareTso("select * from t1 as of tso 0", 0);
+        boolean exceptionCaught = false;
+        try {
+            runFlashbackQueryAndCompareTso("select * from t1 as of tso 'invalid_expression'", 0);
+        } catch (Throwable t) {
+            exceptionCaught = true;
+            assertTrue(t.getMessage().equalsIgnoreCase("Illegal tso expression: ?0"));
+        }
+        assertTrue(exceptionCaught);
+    }
+
+    private void runFlashbackQueryAndCompareTso(String sql, long expectedTso) {
+        ITransaction trx = new MockFlashbackTransaction();
+        ExecutionContext executionContext = new ExecutionContext(appName);
+        executionContext.setTransaction(trx);
+
+        Map currentParameter = new HashMap<>();
+        SqlParameterized sqlParameterized = SqlParameterizeUtils.parameterize(
+            ByteString.from(sql), currentParameter, executionContext, false);
+        Map param = OptimizerUtils.buildParam(sqlParameterized.getParameters());
+        executionContext.setParams(new Parameters(param, false));
+
+        SqlNode ast = new FastsqlParser().parse(
+            sqlParameterized.getSql(), sqlParameterized.getParameters(), executionContext).get(0);
+        ExecutionPlan plan = Planner.getInstance().getPlan(ast, PlannerContext.fromExecutionContext(executionContext));
+        Assert.assertTrue(plan.getPlan() instanceof Gather);
+        Gather gather = (Gather) plan.getPlan();
+        Assert.assertTrue(gather.getInput(0) instanceof OSSTableScan);
+        OSSTableScan ossTableScan = (OSSTableScan) gather.getInput(0);
+        RexNode flashback = ossTableScan.getFlashback();
+        assertNotNull(flashback);
+        Long tso = ossTableScan.getFlashbackQueryTso(executionContext);
+        assertEquals(tso.longValue(), expectedTso);
+    }
+
+    @Override
+    protected String getPlan(String testSql) {
+        return null;
+    }
+
+    private static class MockFlashbackTransaction implements ITransaction {
+
+        @Override
+        public long getId() {
+            return 0;
+        }
+
+        @Override
+        public void commit() {
+
+        }
+
+        @Override
+        public void rollback() {
+
+        }
+
+        @Override
+        public ExecutionContext getExecutionContext() {
+            return null;
+        }
+
+        @Override
+        public void setExecutionContext(ExecutionContext executionContext) {
+
+        }
+
+        @Override
+        public IConnectionHolder getConnectionHolder() {
+            return null;
+        }
+
+        @Override
+        public void tryClose(IConnection conn, String groupName) throws SQLException {
+
+        }
+
+        @Override
+        public void tryClose() throws SQLException {
+
+        }
+
+        @Override
+        public IConnection getConnection(String schemaName, String group, IDataSource ds, RW rw) throws SQLException {
+            return null;
+        }
+
+        @Override
+        public IConnection getConnection(String schemaName, String group, IDataSource ds, RW rw, ExecutionContext ec)
+            throws SQLException {
+            return null;
+        }
+
+        @Override
+        public IConnection getConnection(String schemaName, String group, Long grpConnId, IDataSource ds, RW rw,
+                                         ExecutionContext ec) throws SQLException {
+            return null;
+        }
+
+        @Override
+        public boolean isClosed() {
+            return false;
+        }
+
+        @Override
+        public void close() {
+
+        }
+
+        @Override
+        public void updateStatisticsWhenStatementFinished(AtomicLong rowCount) {
+
+        }
+
+        @Override
+        public void setMdlWaitTime(long mdlWaitTime) {
+
+        }
+
+        @Override
+        public void setStartTimeInMs(long startTime) {
+
+        }
+
+        @Override
+        public void setStartTime(long startTime) {
+
+        }
+
+        @Override
+        public void setSqlStartTime(long sqlStartTime) {
+
+        }
+
+        @Override
+        public void setSqlFinishTime(long t) {
+
+        }
+
+        @Override
+        public void kill() throws SQLException {
+
+        }
+
+        @Override
+        public void savepoint(String savepoint) {
+
+        }
+
+        @Override
+        public void rollbackTo(String savepoint) {
+
+        }
+
+        @Override
+        public void release(String savepoint) {
+
+        }
+
+        @Override
+        public void clearTrxContext() {
+
+        }
+
+        @Override
+        public void setCrucialError(ErrorCode errorCode, String cause) {
+
+        }
+
+        @Override
+        public ErrorCode getCrucialError() {
+            return null;
+        }
+
+        @Override
+        public void checkCanContinue() {
+
+        }
+
+        @Override
+        public boolean isDistributed() {
+            return false;
+        }
+
+        @Override
+        public boolean isStrongConsistent() {
+            return false;
+        }
+
+        @Override
+        public State getState() {
+            return null;
+        }
+
+        @Override
+        public ITransactionPolicy.TransactionClass getTransactionClass() {
+            return ITransactionPolicy.TransactionClass.TSO;
+        }
+
+        @Override
+        public long getStartTimeInMs() {
+            return 0;
+        }
+
+        @Override
+        public boolean isBegun() {
+            return false;
+        }
+
+        @Override
+        public void setInventoryMode(InventoryMode inventoryMode) {
+
+        }
+
+        @Override
+        public ITransactionManagerUtil getTransactionManagerUtil() {
+            return new MockTransactionManagerUtil();
+        }
+
+        @Override
+        public boolean handleStatementError(Throwable t) {
+            return false;
+        }
+
+        @Override
+        public void releaseAutoSavepoint() {
+
+        }
+
+        @Override
+        public boolean isUnderCommitting() {
+            return false;
+        }
+
+        @Override
+        public boolean isAsyncCommit() {
+            return false;
+        }
+
+        @Override
+        public TransactionStatistics getStat() {
+            return null;
+        }
+
+        @Override
+        public TransactionType getType() {
+            return null;
+        }
+
+        @Override
+        public void setLastActiveTime() {
+
+        }
+
+        @Override
+        public long getLastActiveTime() {
+            return 0;
+        }
+
+        @Override
+        public void resetLastActiveTime() {
+
+        }
+
+        @Override
+        public long getIdleTimeout() {
+            return 0;
+        }
+
+        @Override
+        public long getIdleROTimeout() {
+            return 0;
+        }
+
+        @Override
+        public long getIdleRWTimeout() {
+            return 0;
+        }
+    }
+
+    private static class MockTransactionManagerUtil implements ITransactionManagerUtil {
+
+        @Override
+        public ITimestampOracle getTimestampOracle() {
+            return new ITimestampOracle() {
+                @Override
+                public void setTimeout(long timeout) {
+
+                }
+
+                @Override
+                public long nextTimestamp() {
+                    return MOCK_TSO;
+                }
+
+                @Override
+                public void init() {
+
+                }
+
+                @Override
+                public void destroy() {
+
+                }
+
+                @Override
+                public boolean isInited() {
+                    return false;
+                }
+            };
+        }
+    }
+}
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTableNameWithSomethingVisitorTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTableNameWithSomethingVisitorTest.java
new file mode 100644
index 000000000..85272bbe8
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/ReplaceTableNameWithSomethingVisitorTest.java
@@ -0,0 +1,118 @@
+package com.alibaba.polardbx.optimizer.core.rel;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.calcite.rex.RexFieldAccess;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlDynamicParam;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static com.alibaba.polardbx.common.utils.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author fangwu
+ */
+
+public class ReplaceTableNameWithSomethingVisitorTest {
+
+    /**
+     * 测试用例1 - 当处于explain模式时且动态参数值为字段访问类型
+     * 设计思路:模拟一个RexFieldAccess类型的动态参数,在解释模式下返回其符号表示形式。
+     */
+    @Test
+    public void testBuildDynamicParamForCorrelatedSubqueryInExplainModeWithFieldAccess() {
+        // 准备
+        boolean isExplain = true;
+        RexFieldAccess fieldAccess = mock(RexFieldAccess.class);
+        when(fieldAccess.toString()).thenReturn("some_field");
+        SqlDynamicParam dynamicParam = new SqlDynamicParam(0, SqlParserPos.ZERO, fieldAccess);
+
+        // 执行
+        SqlNode result =
+            ReplaceTableNameWithSomethingVisitor.buildDynamicParamForCorrelatedSubquery(isExplain, dynamicParam,
+                null);
+
+        // 验证
+        assert (result instanceof SqlLiteral);
+        assertEquals(SqlLiteral.createSymbol("some_field", SqlParserPos.ZERO), result);
+    }
+
+    /**
+     * 测试用例2 - 当处于explain模式时但动态参数不是字段访问类型
+     * 设计思路:模拟一个非RexFieldAccess类型的动态参数,在解释模式下直接返回动态参数对象。
+     */
+    @Test
+    public void testBuildDynamicParamForCorrelatedSubqueryInExplainModeWithoutFieldAccess() {
+        // 准备
+        boolean isExplain = true;
+        RexNode fieldValue = mock(RexNode.class);
+        SqlDynamicParam dynamicParam = new SqlDynamicParam(0, SqlParserPos.ZERO, fieldValue);
+
+        // 执行
+        SqlNode result =
+            ReplaceTableNameWithSomethingVisitor.buildDynamicParamForCorrelatedSubquery(isExplain, dynamicParam,
+                null);
+
+        // 验证
+        assert (result instanceof SqlDynamicParam);
+        assertEquals(dynamicParam, result);
+    }
+
+    /**
+     * 测试用例3 - 当不在explain模式时且相关字段映射中有对应的值
+     * 设计思路:模拟一个非解释模式下的情况,其中相关字段映射包含对应值,检查是否正确构建SQL字面量节点。
+     */
+    @Test
+    public void testBuildDynamicParamForCorrelatedSubqueryNotInExplainModeWithCorrelation() {
+        // 准备
+        boolean isExplain = false;
+        RexLiteral fieldValue = mock(RexLiteral.class);
+        when(fieldValue.getTypeName()).thenReturn(SqlTypeName.VARCHAR);
+        when(fieldValue.getValue2()).thenReturn("test literal");
+        SqlDynamicParam dynamicParam = new SqlDynamicParam(-4, SqlParserPos.ZERO, fieldValue);
+        RexFieldAccess access = mock(RexFieldAccess.class);
+        Map correlateFieldMap = ImmutableMap.of(access, fieldValue);
+        dynamicParam.setValue(access);
+
+        // 执行
+        SqlNode result =
+            ReplaceTableNameWithSomethingVisitor.buildDynamicParamForCorrelatedSubquery(isExplain, dynamicParam,
+                correlateFieldMap);
+
+        // 验证
+        assert (result instanceof SqlLiteral);
+        assert result.toString().equalsIgnoreCase("'test literal'");
+    }
+
+    /**
+     * 测试用例4 - 当不在explain模式时但在相关字段映射中找不到对应值
+     * 设计思路:模拟一个非explain模式下的情况,其中相关字段映射不包含对应值,预期抛出IllegalArgumentException异常。
+     */
+    @Test
+    public void testBuildDynamicParamForCorrelatedSubqueryNotInExplainModeWithoutCorrelation() {
+        // 准备
+        boolean isExplain = false;
+        RexLiteral fieldValue = mock(RexLiteral.class);
+        SqlDynamicParam dynamicParam = new SqlDynamicParam(0, SqlParserPos.ZERO, fieldValue);
+        Map correlateFieldMap = ImmutableMap.of();
+
+        // 执行并验证
+        try {
+            ReplaceTableNameWithSomethingVisitor.buildDynamicParamForCorrelatedSubquery(isExplain, dynamicParam,
+                correlateFieldMap);
+            fail("Expected an IllegalArgumentException to be thrown.");
+        } catch (IllegalArgumentException e) {
+            assertEquals("Corresponding item not found in correlated field map: " + fieldValue, e.getMessage());
+        }
+    }
+}
+
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/ToDrdsRelVisitorTests.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/ToDrdsRelVisitorTests.java
new file mode 100644
index 000000000..75023bbb8
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/ToDrdsRelVisitorTests.java
@@ -0,0 +1,449 @@
+package com.alibaba.polardbx.optimizer.core.rel;
+
+import com.alibaba.polardbx.common.Engine;
+import com.alibaba.polardbx.gms.metadb.table.IndexStatus;
+import com.alibaba.polardbx.gms.metadb.table.IndexVisibility;
+import com.alibaba.polardbx.optimizer.PlannerContext;
+import com.alibaba.polardbx.optimizer.config.table.GsiMetaManager;
+import com.alibaba.polardbx.optimizer.config.table.IndexMeta;
+import com.alibaba.polardbx.optimizer.config.table.SchemaManager;
+import com.alibaba.polardbx.optimizer.config.table.TableMeta;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.utils.RelUtils;
+import com.clearspring.analytics.util.Lists;
+import org.apache.calcite.plan.RelOptSchema;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.logical.LogicalTableLookup;
+import org.apache.calcite.rel.logical.LogicalTableScan;
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlIndexHint;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.SqlSpecialOperator;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockedConstruction;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static com.alibaba.polardbx.common.utils.Assert.assertNotNull;
+import static org.apache.calcite.sql.parser.SqlParserPos.ZERO;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class ToDrdsRelVisitorTests {
+    private static final String schemaName = "testSchema";
+
+    /**
+     * Tests that null is returned when the index node of the scan is not an instance of SqlNodeList
+     */
+    @Test
+    public void testGetForceIndexWithNonSqlNodeListNode() {
+        TableScan mockTableScan = mock(TableScan.class);
+
+        when(mockTableScan.getIndexNode()).thenReturn(mock(SqlNode.class));
+
+        assertNull(new ToDrdsRelVisitor().getForceIndex(mockTableScan));
+    }
+
+    /**
+     * Tests that null is returned when the index node's list is empty
+     */
+    @Test
+    public void testGetForceIndexWithEmptySqlNodeList() {
+        TableScan mockTableScan = mock(TableScan.class);
+        SqlNodeList mockSqlNodeList = mock(SqlNodeList.class);
+
+        when(mockTableScan.getIndexNode()).thenReturn(mockSqlNodeList);
+        when(mockSqlNodeList.getList()).thenReturn(Collections.emptyList());
+
+        assertNull(new ToDrdsRelVisitor().getForceIndex(mockTableScan));
+    }
+
+    /**
+     * Tests that null is returned when the first element in the index node's list is not a SqlIndexHint
+     */
+    @Test
+    public void testGetForceIndexWithoutSqlIndexHint() {
+        TableScan mockTableScan = mock(TableScan.class);
+        SqlNodeList mockSqlNodeList = mock(SqlNodeList.class);
+
+        when(mockTableScan.getIndexNode()).thenReturn(mockSqlNodeList);
+        when(mockSqlNodeList.getList()).thenReturn(Collections.singletonList(mock(SqlNode.class)));
+
+        assertNull(new ToDrdsRelVisitor().getForceIndex(mockTableScan));
+    }
+
+    /**
+     * Tests that null is returned when the SqlIndexHint is null
+     */
+    @Test
+    public void testGetForceIndexWithNullSqlIndexHint() {
+        TableScan mockTableScan = mock(TableScan.class);
+        SqlNodeList mockSqlNodeList = mock(SqlNodeList.class);
+
+        when(mockTableScan.getIndexNode()).thenReturn(mockSqlNodeList);
+        when(mockSqlNodeList.getList()).thenReturn(null);
+
+        assertNull(new ToDrdsRelVisitor().getForceIndex(mockTableScan));
+    }
+
+    /**
+     * Tests that null is returned when the SqlIndexHint has a null index list
+     */
+    @Test
+    public void testGetForceIndexWithNullIndexListInSqlIndexHint() {
+        TableScan mockTableScan = mock(TableScan.class);
+        SqlNodeList mockSqlNodeList = mock(SqlNodeList.class);
+        SqlIndexHint mockSqlIndexHint = mock(SqlIndexHint.class);
+
+        when(mockTableScan.getIndexNode()).thenReturn(mockSqlNodeList);
+        when(mockSqlNodeList.getList()).thenReturn(Collections.singletonList(mockSqlIndexHint));
+        when(mockSqlIndexHint.getIndexList()).thenReturn(null);
+
+        assertNull(new ToDrdsRelVisitor().getForceIndex(mockTableScan));
+    }
+
+    // test no force index
+    @Test
+    public void testBuildForceIndexWithoutForceIndex() {
+        Engine engine = mock(Engine.class);
+        RelOptSchema catalog = mock(RelOptSchema.class);
+        TableMeta tMeta = mock(TableMeta.class);
+        LogicalTableScan scan = mock(LogicalTableScan.class);
+        ToDrdsRelVisitor visitor = mock(ToDrdsRelVisitor.class);
+
+        when(scan.getIndexNode()).thenReturn(null);
+
+        RelNode result = visitor.buildForceIndexByForceIndex(catalog, scan, schemaName, tMeta, engine);
+
+        assertNull(result);
+    }
+
+    // test force index cci
+    @Test
+    public void testBuildForceIndexWithCci() {
+        try (MockedStatic scanMockedStatic = mockStatic(LogicalTableScan.class);
+            MockedConstruction mockedConstruction = mockConstruction(OSSTableScan.class);
+            MockedStatic plannerContextMockedStatic = mockStatic(PlannerContext.class)) {
+            scanMockedStatic.when(() -> LogicalTableScan.create(any(), any(), any(), any(), any(), any(), any()))
+                .thenReturn(mock(LogicalTableScan.class));
+            plannerContextMockedStatic.when(() -> PlannerContext.getPlannerContext(any(RelNode.class)))
+                .thenReturn(mock(PlannerContext.class));
+            Engine engine = mock(Engine.class);
+            RelOptSchema catalog = mock(RelOptSchema.class);
+            LogicalTableScan scan = mock(LogicalTableScan.class);
+            TableMeta tMeta = mock(TableMeta.class);
+            GsiMetaManager.GsiIndexMetaBean cciMeta =
+                new GsiMetaManager.GsiIndexMetaBean(
+                    "testIndex",
+                    "testSchema",
+                    "testTable",
+                    false,
+                    "index_schema",
+                    "cci",
+                    Lists.newArrayList(),
+                    Lists.newArrayList(),
+                    "indexType",
+                    "",
+                    "",
+                    null,
+                    "indexTableName",
+                    IndexStatus.PUBLIC,
+                    0,
+                    true,
+                    true,
+                    IndexVisibility.VISIBLE);
+            ToDrdsRelVisitor visitor = mock(ToDrdsRelVisitor.class);
+
+            when(scan.getIndexNode()).thenReturn(null);
+            when(tMeta.findGlobalSecondaryIndexByName("cci")).thenReturn(cciMeta);
+            when(visitor.getForceIndex(Mockito.any())).thenReturn(
+                new SqlIdentifier(Collections.singletonList("cci"), ZERO));
+            when(visitor.buildForceIndexByForceIndex(catalog, scan, schemaName, tMeta, engine)).thenCallRealMethod();
+            when(
+                visitor.buildForceIndex(Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.any(), Mockito.any(),
+                    Mockito.anyString()))
+                .thenCallRealMethod();
+            when(visitor.buildOSSTableScan(Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.any(),
+                Mockito.any()))
+                .thenCallRealMethod();
+
+            RelNode result = visitor.buildForceIndexByForceIndex(catalog, scan, schemaName, tMeta, engine);
+
+            assertTrue(result instanceof OSSTableScan);
+        }
+    }
+
+    // test force index with two names, gis exists and local index exists
+    @Test
+    public void testBuildForceIndexWithTwoNamesGsiLocalIndexExists() {
+        Engine engine = mock(Engine.class);
+        RelOptSchema catalog = mock(RelOptSchema.class);
+        LogicalTableScan scan = mock(LogicalTableScan.class);
+        TableMeta tMeta = mock(TableMeta.class);
+        GsiMetaManager.GsiIndexMetaBean gsi = mock(GsiMetaManager.GsiIndexMetaBean.class);
+        TableMeta gsiMeta = mock(TableMeta.class);
+        ToDrdsRelVisitor visitor = mock(ToDrdsRelVisitor.class);
+        LogicalTableLookup target = mock(LogicalTableLookup.class);
+        PlannerContext plannerContext = mock(PlannerContext.class);
+        ExecutionContext executionContext = mock(ExecutionContext.class);
+        SchemaManager schemaManager = mock(SchemaManager.class);
+
+        when(scan.getIndexNode()).thenReturn(null);
+        when(tMeta.findGlobalSecondaryIndexByName("tablePart")).thenReturn(gsi);
+        when(visitor.getForceIndex(scan)).thenReturn(new SqlIdentifier(Arrays.asList("tablePart", "indexPart"), ZERO));
+        when(visitor.buildForceIndexByForceIndex(catalog, scan, schemaName, tMeta, engine)).thenCallRealMethod();
+        when(visitor.getPlannerContext()).thenReturn(plannerContext);
+        when(plannerContext.getExecutionContext()).thenReturn(executionContext);
+        when(executionContext.getSchemaManager(schemaName)).thenReturn(schemaManager);
+        when(schemaManager.getTable(gsi.indexTableName)).thenReturn(gsiMeta);
+        when(tMeta.findLocalIndexByName("tablePart")).thenReturn(null);
+        when(gsiMeta.findLocalIndexByName("indexPart")).thenReturn(mock(IndexMeta.class));
+        when(visitor.buildLogicalTableLookup(catalog, scan, schemaName, engine, gsi, "indexPart")).thenReturn(target);
+
+        RelNode result = visitor.buildForceIndexByForceIndex(catalog, scan, schemaName, tMeta, engine);
+
+        assertEquals(target, result);
+    }
+
+    // test gsi not exists
+    @Test
+    public void testBuildForceIndexWithErrorTablePartNotExist() {
+        Engine engine = mock(Engine.class);
+        RelOptSchema catalog = mock(RelOptSchema.class);
+        LogicalTableScan scan = mock(LogicalTableScan.class);
+        TableMeta tMeta = mock(TableMeta.class);
+        TableMeta gsiMeta = mock(TableMeta.class);
+        ToDrdsRelVisitor visitor = mock(ToDrdsRelVisitor.class);
+        PlannerContext plannerContext = mock(PlannerContext.class);
+        ExecutionContext executionContext = mock(ExecutionContext.class);
+        SchemaManager schemaManager = mock(SchemaManager.class);
+
+        when(scan.getIndexNode()).thenReturn(null);
+        when(tMeta.findGlobalSecondaryIndexByName("tablePart")).thenReturn(null);
+        when(visitor.getForceIndex(scan)).thenReturn(new SqlIdentifier(Arrays.asList("tablePart", "indexPart"), ZERO));
+        when(visitor.buildForceIndexByForceIndex(catalog, scan, schemaName, tMeta, engine)).thenCallRealMethod();
+        when(visitor.getPlannerContext()).thenReturn(plannerContext);
+        when(plannerContext.getExecutionContext()).thenReturn(executionContext);
+        when(executionContext.getSchemaManager(schemaName)).thenReturn(schemaManager);
+        when(tMeta.findLocalIndexByName("tablePart")).thenReturn(null);
+        when(gsiMeta.findLocalIndexByName("indexPart")).thenReturn(null);
+
+        assertNull(visitor.buildForceIndexByForceIndex(catalog, scan, schemaName, tMeta, engine));
+    }
+
+    // gsi local index doesn't exist
+    @Test
+    public void testBuildForceIndexWithErrorIndexPartNotExist() {
+        Engine engine = mock(Engine.class);
+        RelOptSchema catalog = mock(RelOptSchema.class);
+        LogicalTableScan scan = mock(LogicalTableScan.class);
+        TableMeta tMeta = mock(TableMeta.class);
+        GsiMetaManager.GsiIndexMetaBean gsi = mock(GsiMetaManager.GsiIndexMetaBean.class);
+        TableMeta gsiMeta = mock(TableMeta.class);
+        ToDrdsRelVisitor visitor = mock(ToDrdsRelVisitor.class);
+        PlannerContext plannerContext = mock(PlannerContext.class);
+        ExecutionContext executionContext = mock(ExecutionContext.class);
+        SchemaManager schemaManager = mock(SchemaManager.class);
+
+        when(scan.getIndexNode()).thenReturn(null);
+        when(tMeta.findGlobalSecondaryIndexByName("tablePart")).thenReturn(gsi);
+        when(visitor.getForceIndex(scan)).thenReturn(new SqlIdentifier(Arrays.asList("tablePart", "indexPart"), ZERO));
+        when(visitor.buildForceIndexByForceIndex(catalog, scan, schemaName, tMeta, engine)).thenCallRealMethod();
+        when(visitor.getPlannerContext()).thenReturn(plannerContext);
+        when(plannerContext.getExecutionContext()).thenReturn(executionContext);
+        when(executionContext.getSchemaManager(schemaName)).thenReturn(schemaManager);
+        when(schemaManager.getTable(gsi.indexTableName)).thenReturn(gsiMeta);
+        when(tMeta.findLocalIndexByName("tablePart")).thenReturn(null);
+        when(gsiMeta.findLocalIndexByName("indexPart")).thenReturn(null);
+
+        assertNull(visitor.buildForceIndexByForceIndex(catalog, scan, schemaName, tMeta, engine));
+    }
+
+    // test force index with invalid argument count
+    @Test
+    public void testBuildForceIndexWithErrorInvalidArgumentCount() {
+        Engine engine = mock(Engine.class);
+        RelOptSchema catalog = mock(RelOptSchema.class);
+        TableMeta tMeta = mock(TableMeta.class);
+        LogicalTableScan scan = mock(LogicalTableScan.class);
+        ToDrdsRelVisitor visitor = mock(ToDrdsRelVisitor.class);
+
+        SqlIdentifier invalidIndexId = new SqlIdentifier(Arrays.asList("tablePart", "indexPart", "extraPart"), ZERO);
+        doReturn(invalidIndexId).when(visitor).getForceIndex(scan);
+
+        assertNull(visitor.buildForceIndexByForceIndex(catalog, scan, schemaName, tMeta, engine));
+    }
+
+    /**
+     * 测试没有索引提示时返回null
+     */
+    @Test
+    public void testBuildForceIndexByIndexHintWithoutHint() {
+        Engine engine = mock(Engine.class);
+        RelOptSchema catalog = mock(RelOptSchema.class);
+        TableMeta tMeta = mock(TableMeta.class);
+        LogicalTableScan scan = mock(LogicalTableScan.class);
+
+        when(scan.getHints()).thenReturn(null);
+
+        assertNull(new ToDrdsRelVisitor().buildForceIndexByIndexHint(catalog, scan, schemaName, tMeta, engine));
+    }
+
+    /**
+     * 测试获取到完整索引提示,包括表和索引部分
+     */
+    @Test
+    public void testBuildForceIndexByIndexHintWithFullHintAndIndexPart() {
+        Engine engine = mock(Engine.class);
+        RelOptSchema catalog = mock(RelOptSchema.class);
+        TableMeta tMeta = mock(TableMeta.class);
+        LogicalTableScan scan = mock(LogicalTableScan.class);
+        SqlCall indexHintMock = mock(SqlCall.class);
+        SqlNode tableNode = mock(SqlNode.class);
+        SqlNode indexNode = mock(SqlNode.class);
+
+        when(tMeta.getTableName()).thenReturn("tableName_test");
+        when(tableNode.toString()).thenReturn("tableName");
+        when(indexNode.toString()).thenReturn("indexName");
+        when(indexHintMock.getOperandList()).thenReturn(Arrays.asList(mock(SqlNode.class), tableNode, indexNode));
+        when(indexHintMock.getOperator()).thenReturn(new SqlSpecialOperator("index", SqlKind.INDEX_OPTION));
+        when(scan.getHints()).thenReturn(SqlNodeList.of(indexHintMock));
+
+        assertNull(new ToDrdsRelVisitor().buildForceIndexByIndexHint(catalog, scan, schemaName, tMeta, engine));
+    }
+
+    @Test
+    /**
+     * setIndexNode shouldn't be triggered when there is no index node in scan
+     */
+    public void testRemoveForceIndexWithoutIndexNode() {
+        TableScan tableScan = mock(TableScan.class);
+        when(tableScan.getIndexNode()).thenReturn(null);
+
+        ToDrdsRelVisitor visitor = new ToDrdsRelVisitor();
+        visitor.removeForceIndex(tableScan);
+
+        verify(tableScan, never()).setIndexNode(any(SqlNodeList.class));
+    }
+
+    @Test
+    /**
+     * setIndexNode shouldn't be triggered when index node in scan is not one SqlNodeList
+     */
+    public void testRemoveForceIndexWithNonListNode() {
+        TableScan tableScan = mock(TableScan.class);
+        SqlNode indexNode = mock(SqlNode.class);
+        when(tableScan.getIndexNode()).thenReturn(indexNode);
+
+        ToDrdsRelVisitor visitor = new ToDrdsRelVisitor();
+        visitor.removeForceIndex(tableScan);
+
+        verify(tableScan, never()).setIndexNode(any(SqlNodeList.class));
+    }
+
+    @Test
+    /**
+     * setIndexNode shouldn't be triggered when index node in scan is an empty SqlNodeList
+     */
+    public void testRemoveForceIndexWithEmptyListNode() {
+        TableScan tableScan = mock(TableScan.class);
+        SqlNodeList nodeList = new SqlNodeList(ZERO);
+        when(tableScan.getIndexNode()).thenReturn(nodeList);
+
+        ToDrdsRelVisitor visitor = new ToDrdsRelVisitor();
+        visitor.removeForceIndex(tableScan);
+
+        verify(tableScan, never()).setIndexNode(any(SqlNodeList.class));
+    }
+
+    @Test
+    /**
+     * setIndexNode shouldn't be triggered when index node in scan had no force index node
+     */
+    public void testRemoveForceIndexWithOneNonForceNode() {
+        TableScan tableScan = mock(TableScan.class);
+        SqlNodeList nodeList = new SqlNodeList(ZERO);
+        SqlNode nonForceNode = mock(SqlNode.class);
+        nodeList.add(nonForceNode);
+        when(tableScan.getIndexNode()).thenReturn(nodeList);
+
+        ToDrdsRelVisitor visitor = new ToDrdsRelVisitor();
+        visitor.removeForceIndex(tableScan);
+
+        verify(tableScan, never()).setIndexNode(any(SqlNodeList.class));
+    }
+
+    @Test
+    /**
+     * setIndexNode should be triggered when index node in scan had a force index node
+     */
+    public void testRemoveForceIndexWithOneForceNode() {
+        TableScan tableScan = mock(TableScan.class);
+        SqlNodeList nodeList = new SqlNodeList(ZERO);
+        SqlNode forceNode = buildForceIndexForTest();
+        nodeList.add(forceNode);
+        when(tableScan.getIndexNode()).thenReturn(nodeList);
+
+        ToDrdsRelVisitor visitor = new ToDrdsRelVisitor();
+        visitor.removeForceIndex(tableScan);
+
+        ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(SqlNode.class);
+        verify(tableScan, times(1)).setIndexNode(argumentCaptor.capture());
+        SqlNode indexNode = argumentCaptor.getValue();
+        assertTrue(indexNode == null);
+    }
+
+    @Test
+    /**
+     * setIndexNode should be triggered when index node in scan had force/non-force index nodes
+     */
+    public void testRemoveForceIndexWithMixedNodes() {
+        TableScan tableScan = mock(TableScan.class);
+        SqlNodeList nodeList = new SqlNodeList(ZERO);
+        SqlNode forceNode1 = buildForceIndexForTest();
+        SqlNode forceNode2 = buildForceIndexForTest();
+        SqlNode nonForceNode1 = mock(SqlNode.class);
+        SqlNode nonForceNode2 = mock(SqlNode.class);
+        nodeList.add(forceNode1);
+        nodeList.add(nonForceNode1);
+        nodeList.add(forceNode2);
+        nodeList.add(nonForceNode2);
+        when(tableScan.getIndexNode()).thenReturn(nodeList);
+
+        ToDrdsRelVisitor visitor = new ToDrdsRelVisitor();
+        visitor.removeForceIndex(tableScan);
+
+        ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(SqlNode.class);
+        verify(tableScan, times(1)).setIndexNode(argumentCaptor.capture());
+        SqlNode indexNode = argumentCaptor.getValue();
+        assertTrue(indexNode instanceof SqlNodeList &&
+            ((SqlNodeList) indexNode).getList().contains(nonForceNode1) &&
+            ((SqlNodeList) indexNode).getList().contains(nonForceNode2) &&
+            !((SqlNodeList) indexNode).getList().contains(forceNode1) &&
+            !((SqlNodeList) indexNode).getList().contains(forceNode2)
+        );
+    }
+
+    private SqlNode buildForceIndexForTest() {
+        return new SqlIndexHint(SqlLiteral.createCharString("FORCE INDEX", ZERO), null, new SqlNodeList(ZERO), ZERO);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/util/TargetTableInfoOneTableTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/util/TargetTableInfoOneTableTest.java
new file mode 100644
index 000000000..5a931de0e
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/util/TargetTableInfoOneTableTest.java
@@ -0,0 +1,231 @@
+package com.alibaba.polardbx.optimizer.core.rel.util;
+
+import com.alibaba.polardbx.optimizer.partition.PartitionInfo;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class TargetTableInfoOneTableTest {
+
+    private TargetTableInfoOneTable targetTableInfoOneTable;
+
+    @Before
+    public void setUp() {
+        targetTableInfoOneTable = new TargetTableInfoOneTable();
+    }
+
+    @Test
+    public void testGetPrunedFirstLevelPartCount() {
+        // Given
+        int expectedCount = 3;
+
+        // When
+        targetTableInfoOneTable.setPrunedFirstLevelPartCount(expectedCount);
+
+        // Then
+        assertEquals(expectedCount, targetTableInfoOneTable.getPrunedFirstLevelPartCount());
+    }
+
+    @Test
+    public void testSetPrunedFirstLevelPartCount() {
+        // Given
+        int expectedCount = 5;
+
+        // When
+        targetTableInfoOneTable.setPrunedFirstLevelPartCount(expectedCount);
+
+        // Then
+        assertEquals(expectedCount, targetTableInfoOneTable.getPrunedFirstLevelPartCount());
+    }
+
+    @Test
+    public void testIsAllPartSorted() {
+        // Given
+
+        // When
+        targetTableInfoOneTable.setAllPartSorted(true);
+
+        // Then
+        assertTrue(targetTableInfoOneTable.isAllPartSorted());
+    }
+
+    @Test
+    public void testSetAllPartSorted() {
+        // Given
+
+        // When
+        targetTableInfoOneTable.setAllPartSorted(false);
+
+        // Then
+        assertFalse(targetTableInfoOneTable.isAllPartSorted());
+    }
+
+    @Test
+    public void testGetPartColList() {
+        // Given
+        List expectedPartColList = new ArrayList<>();
+        expectedPartColList.add("col1");
+        expectedPartColList.add("col2");
+
+        // When
+        targetTableInfoOneTable.setPartColList(expectedPartColList);
+
+        // Then
+        assertEquals(expectedPartColList, targetTableInfoOneTable.getPartColList());
+    }
+
+    @Test
+    public void testSetPartColList() {
+        // Given
+        List expectedPartColList = new ArrayList<>();
+        expectedPartColList.add("col1");
+        expectedPartColList.add("col2");
+
+        // When
+        targetTableInfoOneTable.setPartColList(expectedPartColList);
+
+        // Then
+        assertEquals(expectedPartColList, targetTableInfoOneTable.getPartColList());
+    }
+
+    @Test
+    public void testGetSubpartColList() {
+        // Given
+        List expectedSubpartColList = new ArrayList<>();
+        expectedSubpartColList.add("sub_col1");
+        expectedSubpartColList.add("sub_col2");
+
+        // When
+        targetTableInfoOneTable.setSubpartColList(expectedSubpartColList);
+
+        // Then
+        assertEquals(expectedSubpartColList, targetTableInfoOneTable.getSubpartColList());
+    }
+
+    @Test
+    public void testSetSubpartColList() {
+        // Given
+        List expectedSubpartColList = new ArrayList<>();
+        expectedSubpartColList.add("sub_col1");
+        expectedSubpartColList.add("sub_col2");
+
+        // When
+        targetTableInfoOneTable.setSubpartColList(expectedSubpartColList);
+
+        // Then
+        assertEquals(expectedSubpartColList, targetTableInfoOneTable.getSubpartColList());
+    }
+
+    @Test
+    public void testGetPartInfo() {
+        // Given
+        PartitionInfo expectedPartInfo = new PartitionInfo() {
+        };
+
+        // When
+        targetTableInfoOneTable.setPartInfo(expectedPartInfo);
+
+        // Then
+        assertEquals(expectedPartInfo, targetTableInfoOneTable.getPartInfo());
+    }
+
+    @Test
+    public void testSetPartInfo() {
+        // Given
+        PartitionInfo expectedPartInfo = new PartitionInfo() {
+        };
+
+        // When
+        targetTableInfoOneTable.setPartInfo(expectedPartInfo);
+
+        // Then
+        assertEquals(expectedPartInfo, targetTableInfoOneTable.getPartInfo());
+    }
+
+    @Test
+    public void testIsUseSubPart() {
+        // Given
+
+        // When
+        targetTableInfoOneTable.setUseSubPart(true);
+
+        // Then
+        assertTrue(targetTableInfoOneTable.isUseSubPart());
+    }
+
+    @Test
+    public void testSetUseSubPart() {
+        // Given
+
+        // When
+        targetTableInfoOneTable.setUseSubPart(false);
+
+        // Then
+        assertFalse(targetTableInfoOneTable.isUseSubPart());
+    }
+
+    @Test
+    public void testIsAllSubPartSorted() {
+        // Given
+
+        // When
+        targetTableInfoOneTable.setAllSubPartSorted(true);
+
+        // Then
+        assertTrue(targetTableInfoOneTable.isAllSubPartSorted());
+    }
+
+    @Test
+    public void testSetAllSubPartSorted() {
+        // Given
+
+        // When
+        targetTableInfoOneTable.setAllSubPartSorted(false);
+
+        // Then
+        assertFalse(targetTableInfoOneTable.isAllSubPartSorted());
+    }
+
+    @Test
+    public void testIsAllPrunedPartContainOnlyOneSubPart() {
+        // Given
+
+        // When
+        targetTableInfoOneTable.setAllPrunedPartContainOnlyOneSubPart(true);
+
+        // Then
+        assertTrue(targetTableInfoOneTable.isAllPrunedPartContainOnlyOneSubPart());
+    }
+
+    @Test
+    public void testSetAllPrunedPartContainOnlyOneSubPart() {
+        // Given
+
+        // When
+        targetTableInfoOneTable.setAllPrunedPartContainOnlyOneSubPart(false);
+
+        // Then
+        assertFalse(targetTableInfoOneTable.isAllPrunedPartContainOnlyOneSubPart());
+    }
+
+    @Test
+    public void testDefaultValues() {
+        // Then
+        assertNull(targetTableInfoOneTable.getPartInfo());
+        assertFalse(targetTableInfoOneTable.isAllPartSorted());
+        assertFalse(targetTableInfoOneTable.isUseSubPart());
+        assertFalse(targetTableInfoOneTable.isAllSubPartSorted());
+        assertFalse(targetTableInfoOneTable.isAllPrunedPartContainOnlyOneSubPart());
+        assertNotNull(targetTableInfoOneTable.getPartColList());
+        assertNotNull(targetTableInfoOneTable.getSubpartColList());
+        assertEquals(0, targetTableInfoOneTable.getPrunedFirstLevelPartCount());
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/util/TargetTableInfoTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/util/TargetTableInfoTest.java
new file mode 100644
index 000000000..073575aed
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/core/rel/util/TargetTableInfoTest.java
@@ -0,0 +1,70 @@
+package com.alibaba.polardbx.optimizer.core.rel.util;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class TargetTableInfoTest {
+
+    private TargetTableInfo targetTableInfo;
+
+    @Before
+    public void setUp() {
+        targetTableInfo = new TargetTableInfo();
+    }
+
+    @Test
+    public void testGetTargetTableInfoList() {
+        List expectedList = new ArrayList<>();
+        expectedList.add(new TargetTableInfoOneTable());
+
+        targetTableInfo.setTargetTableInfoList(expectedList);
+        List actualList = targetTableInfo.getTargetTableInfoList();
+
+        assertNotNull(actualList);
+        assertEquals(expectedList, actualList);
+    }
+
+    @Test
+    public void testSetTargetTableInfoList() {
+        List expectedList = new ArrayList<>();
+        expectedList.add(new TargetTableInfoOneTable());
+
+        targetTableInfo.setTargetTableInfoList(expectedList);
+
+        List actualList = targetTableInfo.getTargetTableInfoList();
+        assertNotNull(actualList);
+        assertEquals(expectedList, actualList);
+    }
+
+    @Test
+    public void testGetTargetTables() {
+        Map>> expectedMap = new HashMap<>();
+        expectedMap.put("table1", new ArrayList<>());
+
+        targetTableInfo.setTargetTables(expectedMap);
+        Map>> actualMap = targetTableInfo.getTargetTables();
+
+        assertNotNull(actualMap);
+        assertEquals(expectedMap, actualMap);
+    }
+
+    @Test
+    public void testSetTargetTables() {
+        Map>> expectedMap = new HashMap<>();
+        expectedMap.put("table1", new ArrayList<>());
+
+        targetTableInfo.setTargetTables(expectedMap);
+
+        Map>> actualMap = targetTableInfo.getTargetTables();
+        assertNotNull(actualMap);
+        assertEquals(expectedMap, actualMap);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/datastruct/IntegerSegmentArrayListTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/datastruct/IntegerSegmentArrayListTest.java
deleted file mode 100644
index 59d52c5f5..000000000
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/datastruct/IntegerSegmentArrayListTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright [2013-2021], Alibaba Group Holding Limited
- *
- * Licensed 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 com.alibaba.polardbx.optimizer.datastruct;
-
-import it.unimi.dsi.fastutil.ints.IntArrayList;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class IntegerSegmentArrayListTest {
-
-    @Test
-    public void test() {
-        IntegerSegmentArrayList a = new IntegerSegmentArrayList(1);
-        IntArrayList gt = new IntArrayList();
-
-        for (int i = 0; i < 10000; i++) {
-            a.add(i);
-            gt.add(i);
-        }
-        for (int i = 0; i < 10000; i += 2) {
-            a.set(i, i * 3);
-            gt.set(i, i * 3);
-        }
-        for (int i = 0; i < 10000; i++) {
-            a.add(i * 0x9e3779b9);
-            gt.add(i * 0x9e3779b9);
-        }
-
-        assertEquals(gt.size(), a.size());
-        for (int i = 0; i < a.size(); i++) {
-            assertEquals(gt.getInt(i), a.get(i));
-        }
-    }
-}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiCaptureTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiCaptureTest.java
new file mode 100644
index 000000000..25d70a80b
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiCaptureTest.java
@@ -0,0 +1,51 @@
+package com.alibaba.polardbx.optimizer.hotgsi;
+
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan;
+import com.alibaba.polardbx.optimizer.core.planner.PlanCache;
+import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized;
+import com.alibaba.polardbx.optimizer.planmanager.hotevolution.HotGsiCapture;
+import com.alibaba.polardbx.optimizer.planmanager.hotevolution.HotGsiEvolution;
+import com.alibaba.polardbx.optimizer.utils.OptimizerUtils;
+import com.alibaba.polardbx.optimizer.utils.RelUtils;
+import com.alibaba.polardbx.optimizer.utils.RexUtils;
+import com.alibaba.polardbx.planner.common.HotGsiTestCommon;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+/**
+ * test HotGsiCapture
+ */
+public class HotGsiCaptureTest extends HotGsiTestCommon {
+    public HotGsiCaptureTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(HotGsiCaptureTest.class);
+    }
+
+    @Override
+    protected String validator(SqlParameterized sqlParameterized, ExecutionPlan executionPlan,
+                               ExecutionContext executionContext) {
+        PlanCache.CacheKey cacheKey =
+            PlanCache.getCacheKey(executionContext.getSchemaName(), sqlParameterized, executionContext, false);
+        boolean evolute = HotGsiCapture.capture(
+            sqlParameterized,
+            executionContext,
+            executionPlan,
+            HotGsiEvolution.getInstance(),
+            cacheKey.getTemplateId());
+
+        String planStr = RelUtils
+            .toString(executionPlan.getPlan(), OptimizerUtils.buildParam(sqlParameterized.getParameters()),
+                RexUtils.getEvalFunc(executionContext), executionContext);
+
+        String code = removeSubqueryHashCode(planStr, executionPlan.getPlan(),
+            executionContext.getParams() == null ? null : executionContext.getParams().getCurrentParameter(),
+            executionContext.getSqlExplainLevel());
+        return evolute + "\n" + code;
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionDisableEvolutionTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionDisableEvolutionTest.java
new file mode 100644
index 000000000..ed3a9db18
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionDisableEvolutionTest.java
@@ -0,0 +1,55 @@
+package com.alibaba.polardbx.optimizer.hotgsi;
+
+import com.alibaba.polardbx.common.properties.ConnectionProperties;
+import com.alibaba.polardbx.common.properties.DynamicConfig;
+import com.alibaba.polardbx.common.utils.Assert;
+import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan;
+import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized;
+import com.alibaba.polardbx.optimizer.planmanager.PlanManager;
+import com.alibaba.polardbx.optimizer.utils.OptimizerUtils;
+import com.alibaba.polardbx.optimizer.utils.RelUtils;
+import com.alibaba.polardbx.optimizer.utils.RexUtils;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+/**
+ * test ENABLE_HOT_GSI_EVOLUTION of HotGsiEvolution
+ */
+public class HotGsiEvolutionDisableEvolutionTest extends HotGsiEvolutionTest {
+    public HotGsiEvolutionDisableEvolutionTest(String caseName, int sqlIndex, String sql,
+                                               String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(HotGsiEvolutionDisableEvolutionTest.class);
+    }
+
+    protected String validator(SqlParameterized sqlParameterized, ExecutionPlan executionPlan,
+                               ExecutionContext executionContext) {
+        MetaDbInstConfigManager.setConfigFromMetaDb(false);
+        DynamicConfig.getInstance()
+            .loadValue(null, ConnectionProperties.ENABLE_HOT_GSI_EVOLUTION, String.valueOf(false));
+        PlanManager.getInstance().getBaselineMap().clear();
+        invokeEvolve(sqlParameterized, executionPlan, executionContext);
+        Assert.assertTrue(PlanManager.getInstance().getBaselineMap(appName).isEmpty());
+
+        DynamicConfig.getInstance()
+            .loadValue(null, ConnectionProperties.ENABLE_HOT_GSI_EVOLUTION, String.valueOf(true));
+        PlanManager.getInstance().getBaselineMap().clear();
+        invokeEvolve(sqlParameterized, executionPlan, executionContext);
+        Assert.assertTrue(PlanManager.getInstance().getBaselineMap(appName).size() == 1);
+        String planStr = RelUtils
+            .toString(executionPlan.getPlan(), OptimizerUtils.buildParam(sqlParameterized.getParameters()),
+                RexUtils.getEvalFunc(executionContext), executionContext);
+
+        String code = removeSubqueryHashCode(planStr, executionPlan.getPlan(),
+            executionContext.getParams() == null ? null : executionContext.getParams().getCurrentParameter(),
+            executionContext.getSqlExplainLevel());
+        return code;
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionQueueTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionQueueTest.java
new file mode 100644
index 000000000..b865f6748
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionQueueTest.java
@@ -0,0 +1,98 @@
+package com.alibaba.polardbx.optimizer.hotgsi;
+
+import com.alibaba.polardbx.common.utils.Assert;
+import com.alibaba.polardbx.optimizer.planmanager.hotevolution.GsiEvolutionInfo;
+import com.alibaba.polardbx.optimizer.planmanager.hotevolution.HotGsiEvolution;
+import com.clearspring.analytics.util.Lists;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * test parallel queue of HotGsiEvolution
+ */
+public class HotGsiEvolutionQueueTest {
+    @Test
+    public void testQueue() {
+        ExecutorService producer = null;
+        try {
+            producer = Executors.newFixedThreadPool(5);
+            int totalSize = 10;
+            HotGsiEvolution hotGsiEvolution = new HotGsiEvolution(totalSize);
+            GsiEvolutionInfo mock = Mockito.mock(GsiEvolutionInfo.class);
+            int threadSize = 5;
+            int size = totalSize / threadSize;
+
+            // add task parallel
+            List> futures = Lists.newArrayList();
+            for (int i = 0; i < threadSize; i++) {
+                futures.add(producer.submit(() -> {
+                    for (int g = 0; g < size; g++) {
+                        if (!hotGsiEvolution.submitEvolutionTask(mock)) {
+                            return false;
+                        }
+                    }
+                    return true;
+                }));
+            }
+            for (Future future : futures) {
+                // all threads should return true
+                Assert.assertTrue(future.get(5L, TimeUnit.SECONDS));
+            }
+            // queue should be full
+            Assert.assertTrue(hotGsiEvolution.getQueueSize() == totalSize);
+
+            // add tasks parallel when it is full
+            futures.clear();
+            for (int i = 0; i < threadSize; i++) {
+                futures.add(producer.submit(() -> hotGsiEvolution.submitEvolutionTask(mock)));
+            }
+            for (Future future : futures) {
+                // all threads should return false
+                Assert.assertTrue(!future.get(5L, TimeUnit.SECONDS));
+            }
+
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (producer != null) {
+                producer.shutdownNow();
+            }
+        }
+    }
+
+    @Test
+    public void testQueueRun() {
+        HotGsiEvolution hotGsiEvolution = new HotGsiEvolution(100, 0L);
+        GsiEvolutionInfo mock = Mockito.mock(GsiEvolutionInfo.class);
+        Mockito.when(mock.getSqlParameterized()).thenReturn(null);
+        try {
+            Class clazz = HotGsiEvolution.class;
+            Field field = clazz.getDeclaredField("QUEUE_CAPACITY");
+            field.setAccessible(true);
+            int capacity = (Integer) field.get(null);
+            for (int i = 0; i < 300; i++) {
+                hotGsiEvolution.submitEvolutionTask(mock);
+            }
+            Assert.assertTrue(hotGsiEvolution.getQueueSize() == capacity);
+
+            // sleep to wait for HotGsiEvolution thread starts
+            Thread.sleep(5000L);
+            Assert.assertTrue(hotGsiEvolution.getQueueSize() == 0);
+
+            for (int i = 0; i < 30; i++) {
+                hotGsiEvolution.submitEvolutionTask(mock);
+            }
+            Thread.sleep(3000L);
+            Assert.assertTrue(hotGsiEvolution.getQueueSize() == 0);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionTest.java
new file mode 100644
index 000000000..95fb84800
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionTest.java
@@ -0,0 +1,95 @@
+package com.alibaba.polardbx.optimizer.hotgsi;
+
+import com.alibaba.polardbx.common.utils.Assert;
+import com.alibaba.polardbx.common.utils.TStringUtil;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan;
+import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized;
+import com.alibaba.polardbx.optimizer.planmanager.BaselineInfo;
+import com.alibaba.polardbx.optimizer.planmanager.PlanManager;
+import com.alibaba.polardbx.optimizer.planmanager.hotevolution.GsiEvolutionInfo;
+import com.alibaba.polardbx.optimizer.planmanager.hotevolution.HotGsiCapture;
+import com.alibaba.polardbx.optimizer.planmanager.hotevolution.HotGsiEvolution;
+import com.alibaba.polardbx.optimizer.utils.OptimizerUtils;
+import com.alibaba.polardbx.optimizer.utils.RelUtils;
+import com.alibaba.polardbx.optimizer.utils.RexUtils;
+import com.alibaba.polardbx.planner.common.HotGsiTestCommon;
+import com.clearspring.analytics.util.Lists;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * test entry point of HotGsiEvolution
+ */
+public class HotGsiEvolutionTest extends HotGsiTestCommon {
+    public HotGsiEvolutionTest(String caseName, int sqlIndex, String sql,
+                               String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(HotGsiEvolutionTest.class);
+    }
+
+    void invokeEvolve(SqlParameterized sqlParameterized, ExecutionPlan executionPlan,
+                      ExecutionContext executionContext) {
+        ExecutorService producer = null;
+        try {
+            producer = Executors.newFixedThreadPool(5);
+            int threadSize = 5;
+
+            // add task parallel
+            List> futures = Lists.newArrayList();
+            for (int i = 0; i < threadSize; i++) {
+                ExecutionPlan finalExecutionPlan = executionPlan;
+                futures.add(
+                    producer.submit(() -> {
+                        GsiEvolutionInfo info = new GsiEvolutionInfo(sqlParameterized, executionContext,
+                            finalExecutionPlan,
+                            HotGsiCapture.candidateHotGsi(executionContext, executionPlan.getPlan()),
+                            TStringUtil.int2FixedLenHexStr(sqlParameterized.getSql().hashCode()));
+                        HotGsiEvolution.evolution(info);
+                        return true;
+                    }));
+            }
+            for (Future future : futures) {
+                // all threads should return true
+                Assert.assertTrue(future.get(5L, TimeUnit.SECONDS));
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (producer != null) {
+                producer.shutdownNow();
+            }
+        }
+    }
+
+    protected String validator(SqlParameterized sqlParameterized, ExecutionPlan executionPlan,
+                               ExecutionContext executionContext) {
+        PlanManager.getInstance().getBaselineMap().clear();
+
+        invokeEvolve(sqlParameterized, executionPlan, executionContext);
+        Assert.assertTrue(PlanManager.getInstance().getBaselineMap(appName).size() == 1);
+        BaselineInfo baselineInfo = PlanManager.getInstance().getBaselineMap(appName).get(sqlParameterized.getSql());
+        Assert.assertTrue(baselineInfo != null);
+        Assert.assertTrue(baselineInfo.isHotEvolution());
+        Assert.assertTrue(baselineInfo.getAcceptedPlans().size() == baselineInfo.getPlans().size());
+
+        String planStr = RelUtils
+            .toString(executionPlan.getPlan(), OptimizerUtils.buildParam(sqlParameterized.getParameters()),
+                RexUtils.getEvalFunc(executionContext), executionContext);
+
+        String code = removeSubqueryHashCode(planStr, executionPlan.getPlan(),
+            executionContext.getParams() == null ? null : executionContext.getParams().getCurrentParameter(),
+            executionContext.getSqlExplainLevel());
+
+        return baselineInfo.getAcceptedPlans().size() + "\n" + code;
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiPatternTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiPatternTest.java
new file mode 100644
index 000000000..d8f3d90dc
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiPatternTest.java
@@ -0,0 +1,47 @@
+package com.alibaba.polardbx.optimizer.hotgsi;
+
+import com.alibaba.polardbx.optimizer.PlannerContext;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan;
+import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized;
+import com.alibaba.polardbx.optimizer.planmanager.hotevolution.HotGsiPattern;
+import com.alibaba.polardbx.optimizer.utils.OptimizerUtils;
+import com.alibaba.polardbx.optimizer.utils.RelUtils;
+import com.alibaba.polardbx.optimizer.utils.RexUtils;
+import com.alibaba.polardbx.planner.common.HotGsiTestCommon;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+/**
+ * check whether the plan fits HotGsiPattern
+ */
+public class HotGsiPatternTest extends HotGsiTestCommon {
+    public HotGsiPatternTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(HotGsiPatternTest.class);
+    }
+
+    protected String validator(SqlParameterized sqlParameterized, ExecutionPlan executionPlan,
+                               ExecutionContext executionContext) {
+
+        boolean evolute = HotGsiPattern.findPattern(executionPlan.getPlan()).getKey();
+
+        if (PlannerContext.getPlannerContext(executionPlan.getPlan()).getJoinCount() > 0) {
+            evolute = false;
+        }
+        String planStr = RelUtils
+            .toString(executionPlan.getPlan(), OptimizerUtils.buildParam(sqlParameterized.getParameters()),
+                RexUtils.getEvalFunc(executionContext), executionContext);
+
+        String code = removeSubqueryHashCode(planStr, executionPlan.getPlan(),
+            executionContext.getParams() == null ? null : executionContext.getParams().getCurrentParameter(),
+            executionContext.getSqlExplainLevel());
+
+        return evolute + "\n" + code;
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiSelectivityUpperLimitEstimatorTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiSelectivityUpperLimitEstimatorTest.java
new file mode 100644
index 000000000..8c098228f
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/hotgsi/HotGsiSelectivityUpperLimitEstimatorTest.java
@@ -0,0 +1,40 @@
+package com.alibaba.polardbx.optimizer.hotgsi;
+
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan;
+import com.alibaba.polardbx.optimizer.core.planner.rule.util.CBOUtil;
+import com.alibaba.polardbx.optimizer.core.rel.LogicalView;
+import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized;
+import com.alibaba.polardbx.optimizer.planmanager.LogicalViewFinder;
+import com.alibaba.polardbx.planner.common.HotGsiTestCommon;
+import org.apache.calcite.rel.RelNode;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+public class HotGsiSelectivityUpperLimitEstimatorTest extends HotGsiTestCommon {
+    public HotGsiSelectivityUpperLimitEstimatorTest(String caseName, int sqlIndex, String sql, String expectedPlan,
+                                                    String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(HotGsiSelectivityUpperLimitEstimatorTest.class);
+    }
+
+    @Override
+    protected String validator(SqlParameterized sqlParameterized, ExecutionPlan executionPlan,
+                               ExecutionContext executionContext) {
+        RelNode node = executionPlan.getPlan();
+
+        LogicalViewFinder finder = new LogicalViewFinder();
+        node.accept(finder);
+        LogicalView lv = finder.getResult().get(0);
+        lv.getPushDownOpt().optimize();
+        double result = lv.getMaxSelectivity() *
+            CBOUtil.getTableMeta(lv.getTable()).getRowCount(null);
+
+        return String.format("%.0f", result);
+    }
+}
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerSelectivityImplTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerSelectivityImplTest.java
new file mode 100644
index 000000000..510b1af1b
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerSelectivityImplTest.java
@@ -0,0 +1,62 @@
+package com.alibaba.polardbx.optimizer.optimizeralert;
+
+import com.alibaba.polardbx.common.properties.ConnectionProperties;
+import com.alibaba.polardbx.common.properties.DynamicConfig;
+import com.alibaba.polardbx.common.utils.Assert;
+import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager;
+import com.alibaba.polardbx.optimizer.config.meta.TableScanIOEstimator;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.selectivity.TableScanSelectivityEstimator;
+import org.junit.Test;
+import org.mockito.stubbing.Answer;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class OptimizerAlertLoggerSelectivityImplTest {
+    @Test
+    public void testEstimator() {
+        long interval = 1000L;
+        MetaDbInstConfigManager.setConfigFromMetaDb(false);
+        DynamicConfig.getInstance()
+            .loadValue(null, ConnectionProperties.OPTIMIZER_ALERT_LOG_INTERVAL, String.valueOf(interval));
+        OptimizerAlertManager.getInstance();
+
+        long beforeCount = OptimizerAlertManager.getInstance().collectByView()
+            .stream().filter(x -> x.getKey().equals(OptimizerAlertType.SELECTIVITY_ERR)).mapToLong(Pair::getValue)
+            .sum();
+
+        ExecutionContext ec = new ExecutionContext("tmp");
+        ec.setTraceId("test");
+
+        TableScanSelectivityEstimator mockEstimator = mock(TableScanSelectivityEstimator.class);
+        when(mockEstimator.getExecutionContext()).thenReturn(ec);
+        when(mockEstimator.evaluateInside(any())).thenAnswer(
+            (Answer) invocation -> {
+                throw new RuntimeException();
+            });
+        doCallRealMethod().when(mockEstimator).evaluate(any());
+        mockEstimator.evaluate(null);
+
+        long afterCount = OptimizerAlertManager.getInstance().collectByView()
+            .stream().filter(x -> x.getKey().equals(OptimizerAlertType.SELECTIVITY_ERR)).mapToLong(Pair::getValue)
+            .sum();
+        Assert.assertTrue(beforeCount < afterCount, String.format("before %d, after %d", beforeCount, afterCount));
+        TableScanIOEstimator mockIOEstimator = mock(TableScanIOEstimator.class);
+        when(mockIOEstimator.getExecutionContext()).thenReturn(null);
+        when(mockIOEstimator.evaluateInside(any())).thenAnswer(
+            (Answer) invocation -> {
+                throw new RuntimeException();
+            });
+        doCallRealMethod().when(mockEstimator).evaluate(any());
+        mockEstimator.evaluate(null);
+        long lastCount = OptimizerAlertManager.getInstance().collectByView()
+            .stream().filter(x -> x.getKey().equals(OptimizerAlertType.SELECTIVITY_ERR)).mapToLong(Pair::getValue)
+            .sum();
+        Assert.assertTrue(afterCount < lastCount, String.format("before %d, after %d", afterCount, lastCount));
+    }
+
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticImplTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticImplTest.java
index 222de3518..1736385a8 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticImplTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertLoggerStatisticImplTest.java
@@ -52,7 +52,7 @@ public void testStatisticAlertTest() {
         OptimizerAlertUtil.statisticsAlert(DEFAULT_META_DB_NAME, testTbl, null);
         Assert.assertTrue(0L == getStatisticAlertNum());
 
-        OptimizerContext oc = BasePlannerTest.initOptiContext(testSchema, 4, true);
+        OptimizerContext oc = BasePlannerTest.initOptiContext(testSchema, 4, true, false);
         OptimizerContext.setContext(oc);
 
         // test rowcount == 0
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertManagerTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertManagerTest.java
index 4d8c28dfd..db4acef59 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertManagerTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/optimizeralert/OptimizerAlertManagerTest.java
@@ -92,68 +92,6 @@ public void testMultiBasicLog() {
         checkLogCount(typeMap);
     }
 
-    @Test
-    public void testMultiLimitedLog() {
-        long interval = 1000L;
-        MetaDbInstConfigManager.setConfigFromMetaDb(false);
-        DynamicConfig.getInstance()
-            .loadValue(null, ConnectionProperties.OPTIMIZER_ALERT_LOG_INTERVAL, String.valueOf(interval));
-        OptimizerAlertManager.getInstance();
-
-        long sleep = 10;
-        final ExecutorService threadPool = new ThreadPoolExecutor(threadNum, threadNum, 0L,
-            TimeUnit.MILLISECONDS, new SynchronousQueue<>());
-
-        Map typeMap = Maps.newTreeMap();
-        for (OptimizerAlertType type : OptimizerAlertType.values()) {
-            typeMap.put(type, 0L);
-        }
-        initLogCount(typeMap);
-
-        List> tasks = Lists.newArrayList();
-
-        long startTime = System.currentTimeMillis();
-        for (int i = 0; i < threadNum; i++) {
-            tasks.add(threadPool.submit(() -> {
-                long cnt = 0L;
-                try {
-                    for (int j = 0; j < logNum; j++) {
-                        if (OptimizerAlertManager.getInstance().log(OptimizerAlertType.PLAN_CACHE_FULL, null)) {
-                            cnt++;
-                        }
-                        Thread.sleep(sleep);
-                    }
-                } catch (InterruptedException e) {
-                    throw new RuntimeException(e);
-                }
-                return cnt;
-            }));
-        }
-
-        long stackNum = 0L;
-        for (Future future : tasks) {
-            try {
-                stackNum += future.get(20, TimeUnit.SECONDS);
-            } catch (Throwable e) {
-                e.printStackTrace();
-                Assert.fail("Get future failed.");
-            }
-        }
-
-        // check stack count
-        long endTime = System.currentTimeMillis();
-        double period = endTime - startTime;
-        // at least 5 seconds
-        Assert.assertTrue(period > (logNum * sleep) / 1000D);
-        // at most 1 stack per interval
-        Assert.assertTrue(stackNum <= (period / interval) + 1);
-        // at least 1 stack per 2 intervals
-        Assert.assertTrue(stackNum >= period / interval / 2);
-
-        typeMap.put(OptimizerAlertType.PLAN_CACHE_FULL, typeMap.get(OptimizerAlertType.PLAN_CACHE_FULL) + stackNum);
-        checkLogCount(typeMap);
-    }
-
     @Test
     public void testLogAndScheduleCollect() throws InterruptedException {
         long interval = 1000L;
@@ -167,7 +105,7 @@ public void testLogAndScheduleCollect() throws InterruptedException {
 
         long sleep = 10;
         List logTypes =
-            Lists.newArrayList(OptimizerAlertType.BKA_TOO_MUCH, OptimizerAlertType.XPLAN_SLOW);
+            Lists.newArrayList(OptimizerAlertType.BKA_TOO_MUCH, OptimizerAlertType.TP_SLOW);
         Map typeMap = Maps.newTreeMap();
         for (OptimizerAlertType type : OptimizerAlertType.values()) {
             typeMap.put(type, 0L);
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/parse/visitor/DrdsParameterizeSqlVisitorTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/parse/visitor/DrdsParameterizeSqlVisitorTest.java
new file mode 100644
index 000000000..198eb7dd1
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/parse/visitor/DrdsParameterizeSqlVisitorTest.java
@@ -0,0 +1,80 @@
+package com.alibaba.polardbx.optimizer.parse.visitor;
+
+import com.alibaba.polardbx.common.utils.Assert;
+import com.alibaba.polardbx.druid.sql.ast.SQLStatement;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsBaselineStatement;
+import com.alibaba.polardbx.druid.sql.parser.ByteString;
+import com.alibaba.polardbx.optimizer.parse.SqlParameterizeUtils;
+import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized;
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+
+import static com.alibaba.polardbx.common.utils.Assert.assertTrue;
+
+/**
+ * @author fangwu
+ */
+public class DrdsParameterizeSqlVisitorTest {
+
+    @Test
+    public void testPostSqlWithoutSemicolon() {
+        String sql = "select * from t where a = 1;";
+        String target = "SELECT *\n"
+            + "FROM t\n"
+            + "WHERE a = ?";
+        SqlParameterized parameterize = SqlParameterizeUtils.parameterize(sql);
+        System.out.println(parameterize.getSql());
+        assertTrue(parameterize.getSql().equals(target));
+    }
+
+    @Test
+    public void testAggSql() {
+        String sql =
+            "SELECT count( 1 ) FROM ( SELECT sum( amount ) AS amount, sum( usedAmount ) AS usedAmount FROM t) a";
+        String target = "SELECT count(1) AS 'count(1)'\n"
+            + "FROM (\n"
+            + "\tSELECT sum(amount) AS amount, sum(usedAmount) AS usedAmount\n"
+            + "\tFROM t\n"
+            + ") a";
+        SqlParameterized parameterize = SqlParameterizeUtils.parameterize(sql);
+        System.out.println(parameterize.getSql());
+        assertTrue(parameterize.getSql().equals(target));
+    }
+
+    @Test
+    public void testBaselineFixAggSql() {
+        String sql =
+            "Baseline fix sql /*TDDL:a()*/ SELECT count( 1 ) FROM ( SELECT sum( amount ) AS amount, sum( usedAmount ) AS usedAmount FROM t) a";
+        String target = "SELECT count(1) AS 'count(1)'\n"
+            + "FROM (\n"
+            + "\tSELECT sum(amount) AS amount, sum(usedAmount) AS usedAmount\n"
+            + "\tFROM t\n"
+            + ") a";
+        SqlParameterized parameterize = SqlParameterizeUtils.parameterize(sql);
+        Assert.assertTrue(parameterize.getAst() instanceof DrdsBaselineStatement);
+        String targetSql = ((DrdsBaselineStatement) parameterize.getAst()).getTargetSql();
+        String targetSqlParameterize = SqlParameterizeUtils.parameterize(targetSql).getSql();
+        System.out.println(target);
+        System.out.println(targetSqlParameterize);
+        assertTrue(target.equals(targetSqlParameterize));
+    }
+
+    @Test
+    public void testBaselineBindHintAggSql() {
+        String sql =
+            "Baseline hint bind /*TDDL:a()*/ SELECT count( 1 ) FROM ( SELECT sum( amount ) AS amount, sum( usedAmount ) AS usedAmount FROM t) a";
+        String target = "SELECT count(1) AS 'count(1)'\n"
+            + "FROM (\n"
+            + "\tSELECT sum(amount) AS amount, sum(usedAmount) AS usedAmount\n"
+            + "\tFROM t\n"
+            + ") a";
+        SqlParameterized parameterize = SqlParameterizeUtils.parameterize(sql);
+        Assert.assertTrue(parameterize.getAst() instanceof DrdsBaselineStatement);
+        String targetSql = ((DrdsBaselineStatement) parameterize.getAst()).getTargetSql();
+        String targetSqlParameterize = SqlParameterizeUtils.parameterize(targetSql).getSql();
+        System.out.println(target);
+        System.out.println(targetSqlParameterize);
+        assertTrue(target.equals(targetSqlParameterize));
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoBuilderTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoBuilderTest.java
new file mode 100644
index 000000000..9405e5b3f
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/partition/PartitionInfoBuilderTest.java
@@ -0,0 +1,124 @@
+package com.alibaba.polardbx.optimizer.partition;
+
+import com.alibaba.polardbx.optimizer.config.table.ColumnMeta;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.partition.boundspec.PartBoundValBuilder;
+import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy;
+import com.alibaba.polardbx.optimizer.partition.datatype.function.PartitionIntFunction;
+import com.alibaba.polardbx.optimizer.partition.pruning.SearchDatumComparator;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlPartition;
+import org.apache.calcite.sql.SqlSubPartition;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class PartitionInfoBuilderTest {
+
+    @Mock
+    private SqlPartition newPartition;
+
+    @Mock
+    private SqlSubPartition newSubPartition;
+
+    @Mock
+    private PartitionByDefinition subPartByDef;
+
+    @Mock
+    private Map> partBoundExprInfoByLevel;
+
+    @Mock
+    private PartBoundValBuilder partBoundValBuilder;
+
+    @Mock
+    private PartitionSpec parentPartitionSpec;
+
+    private AtomicInteger phySubPartCounter = new AtomicInteger(0);
+
+    private AtomicInteger subPartPosCounter = new AtomicInteger(0);
+
+    private boolean isColumnarIndex = true;
+
+    private ExecutionContext context;
+
+    @Before
+    public void setUp() {
+        context = new ExecutionContext();
+        // Setup common mock behaviors here if any
+    }
+
+    @Test
+    public void testBuildSubPartSpecForKey() {
+        // Setup specific to this test
+        try (MockedStatic mockStatic = Mockito.mockStatic(PartitionInfoBuilder.class)) {
+            PartitionSpec spec = new PartitionSpec();
+            when(PartitionInfoBuilder.buildPartSpecByAstParamInner(any())).thenReturn(spec);
+
+            List partitionFiles = new ArrayList<>();
+            SearchDatumComparator searchDatumComparator = mock(SearchDatumComparator.class);
+            PartitionIntFunction partIntFunc = mock(PartitionIntFunction.class);
+            when(newSubPartition.getName()).thenReturn(new SqlIdentifier("p0", SqlParserPos.ZERO));
+            when(subPartByDef.getPartitionFieldList()).thenReturn(partitionFiles);
+            when(subPartByDef.getPruningSpaceComparator()).thenReturn(searchDatumComparator);
+            when(subPartByDef.getPartIntFunc()).thenReturn(partIntFunc);
+            when(subPartByDef.getStrategy()).thenReturn(PartitionStrategy.valueOf("LIST"));
+
+            mockStatic.when(
+                () -> PartitionInfoBuilder.buildSubPartSpecForKey(
+                    newSubPartition,
+                    subPartByDef,
+                    partBoundExprInfoByLevel,
+                    partBoundValBuilder,
+                    parentPartitionSpec,
+                    phySubPartCounter,
+                    subPartPosCounter,
+                    isColumnarIndex,
+                    context)).thenCallRealMethod();
+            PartitionInfoBuilder.buildSubPartSpecForKey(
+                newSubPartition,
+                subPartByDef,
+                partBoundExprInfoByLevel,
+                partBoundValBuilder,
+                parentPartitionSpec,
+                phySubPartCounter,
+                subPartPosCounter,
+                isColumnarIndex,
+                context);
+
+            mockStatic.when(
+                () -> PartitionInfoBuilder.buildSubPartSpecForRangeOrList(
+                    newSubPartition, subPartByDef, null,
+                    partBoundExprInfoByLevel, parentPartitionSpec, phySubPartCounter, subPartPosCounter,
+                    isColumnarIndex,
+                    context)).thenCallRealMethod();
+            PartitionInfoBuilder.buildSubPartSpecForRangeOrList(newSubPartition, subPartByDef, null,
+                partBoundExprInfoByLevel, parentPartitionSpec, phySubPartCounter, subPartPosCounter, isColumnarIndex,
+                context);
+
+            mockStatic.when(
+                () -> PartitionInfoBuilder.buildPartSpec(
+                    newPartition, subPartByDef, null, partBoundExprInfoByLevel,
+                    phySubPartCounter, subPartPosCounter, isColumnarIndex, context)).thenCallRealMethod();
+            PartitionInfoBuilder.buildPartSpec(newPartition, subPartByDef, null, partBoundExprInfoByLevel,
+                phySubPartCounter, subPartPosCounter, isColumnarIndex, context);
+        }
+    }
+
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJsonTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJsonTest.java
new file mode 100644
index 000000000..ca1498b7a
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/DRDSRelJsonTest.java
@@ -0,0 +1,249 @@
+package com.alibaba.polardbx.optimizer.planmanager;
+
+import com.alibaba.polardbx.common.jdbc.Parameters;
+import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.druid.util.HexBin;
+import com.alibaba.polardbx.optimizer.BaseRuleTest;
+import com.alibaba.polardbx.optimizer.PlannerContext;
+import com.alibaba.polardbx.optimizer.core.Xplan.XPlanTemplate;
+import com.alibaba.polardbx.optimizer.core.datatype.DataTypeUtil;
+import com.alibaba.polardbx.optimizer.core.planner.Xplanner.XPlanUtil;
+import com.alibaba.polardbx.optimizer.core.rel.LogicalView;
+import com.alibaba.polardbx.rpc.XUtil;
+import com.alibaba.polardbx.rpc.pool.XConnectionManager;
+import com.clearspring.analytics.util.Lists;
+import com.google.common.collect.ImmutableList;
+import com.mysql.cj.x.protobuf.PolarxExecPlan;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.logical.LogicalFilter;
+import org.apache.calcite.rel.logical.LogicalTableScan;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.util.JsonBuilder;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import static com.alibaba.polardbx.common.utils.Assert.assertTrue;
+import static com.alibaba.polardbx.druid.sql.parser.CharTypes.bytesToHex;
+import static com.alibaba.polardbx.druid.sql.parser.CharTypes.hexToBytes;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author fangwu
+ */
+public class DRDSRelJsonTest extends BaseRuleTest {
+
+    @Test
+    public void testXPlanInLogicalView() {
+        String expect = "{\n"
+            + "  \"rels\": [\n"
+            + "    {\n"
+            + "      \"id\": \"0\",\n"
+            + "      \"relOp\": \"LogicalView\",\n"
+            + "      \"table\": [\n"
+            + "        \"optest\",\n"
+            + "        \"stu\"\n"
+            + "      ],\n"
+            + "      \"tableNames\": [\n"
+            + "        \"stu\"\n"
+            + "      ],\n"
+            + "      \"pushDownOpt\": {\n"
+            + "        \"pushrels\": [\n"
+            + "          {\n"
+            + "            \"id\": \"0\",\n"
+            + "            \"relOp\": \"LogicalTableScan\",\n"
+            + "            \"table\": [\n"
+            + "              \"optest\",\n"
+            + "              \"stu\"\n"
+            + "            ],\n"
+            + "            \"flashback\": null,\n"
+            + "            \"inputs\": []\n"
+            + "          },\n"
+            + "          {\n"
+            + "            \"id\": \"1\",\n"
+            + "            \"relOp\": \"LogicalFilter\",\n"
+            + "            \"condition\": {\n"
+            + "              \"op\": \"SqlBinaryOperator=\",\n"
+            + "              \"operands\": [\n"
+            + "                {\n"
+            + "                  \"input\": 2,\n"
+            + "                  \"name\": \"$2\",\n"
+            + "                  \"type\": {\n"
+            + "                    \"type\": \"TINYINT\",\n"
+            + "                    \"nullable\": true,\n"
+            + "                    \"precision\": 1\n"
+            + "                  }\n"
+            + "                },\n"
+            + "                {\n"
+            + "                  \"input\": 0,\n"
+            + "                  \"name\": \"$0\",\n"
+            + "                  \"type\": {\n"
+            + "                    \"type\": \"INTEGER\",\n"
+            + "                    \"nullable\": true\n"
+            + "                  }\n"
+            + "                }\n"
+            + "              ],\n"
+            + "              \"type\": {\n"
+            + "                \"type\": \"BIGINT\",\n"
+            + "                \"nullable\": true\n"
+            + "              }\n"
+            + "            }\n"
+            + "          }\n"
+            + "        ]\n"
+            + "      },\n"
+            + "      \"schemaName\": \"optest\",\n"
+            + "      \"partitions\": [],\n"
+            + "      \"flashback\": null,\n"
+            + "      \"xplan\": {\n"
+            + "        \"template\": \"080532710A59080322550A1208021A0E0A0C1204080950001A0408095001120A08084A060A026964102D120C08084A080A046E616D65102D121108084A0D0A096F7065726174696F6E102D121208084A0E0A0A616374696F6E44617465102D1214080532100A023D3D120408095002120408095000\",\n"
+            + "        \"schemaNames\": [\n"
+            + "          \"optest\"\n"
+            + "        ],\n"
+            + "        \"tableNames\": [\n"
+            + "          \"stu\"\n"
+            + "        ],\n"
+            + "        \"indexName\": \"PRIMARY\",\n"
+            + "        \"paramInfo\": [\n"
+            + "          {\n"
+            + "            \"type\": \"TableName\",\n"
+            + "            \"id\": 0,\n"
+            + "            \"isBit\": false,\n"
+            + "            \"isNullAble\": false\n"
+            + "          },\n"
+            + "          {\n"
+            + "            \"type\": \"SchemaName\",\n"
+            + "            \"id\": 0,\n"
+            + "            \"isBit\": false,\n"
+            + "            \"isNullAble\": false\n"
+            + "          }\n"
+            + "        ]\n"
+            + "      }\n"
+            + "    }\n"
+            + "  ]\n"
+            + "}";
+        expect = expect.replaceAll("\n", "").replaceAll("[\t ]", "");
+        boolean enableXPlan = XConnectionManager.getInstance().isEnableXplanTableScan();
+        try {
+            XConnectionManager.getInstance().setEnableXplanTableScan(true);
+            LogicalTableScan scan = LogicalTableScan.create(relOptCluster,
+                schema.getTableForMember(Arrays.asList("optest", "stu")));
+            LogicalView logicalView = LogicalView.create(scan, scan.getTable());
+            final RexBuilder rexBuilder = relOptCluster.getRexBuilder();
+            LogicalFilter filter = LogicalFilter.create(logicalView,
+                rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
+                    rexBuilder.makeFieldAccess(rexBuilder.makeRangeReference(logicalView), "operation", true),
+                    rexBuilder.makeInputRef(logicalView, 0)));
+            logicalView.push(filter);
+            PlannerContext.getPlannerContext(logicalView).setParams(new Parameters());
+            logicalView.getXPlan();
+            final DRDSRelJsonWriter writer = new DRDSRelJsonWriter(false);
+            logicalView.explain(writer);
+            String s = writer.asString();
+
+            assertThat(s.replaceAll("\n", "").replaceAll("[\t ]", ""), is(expect));
+
+            final DRDSRelJsonReader reader = new DRDSRelJsonReader(relOptCluster, schema, null, false);
+            RelNode node;
+            try {
+                node = reader.read(s);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+
+            assertTrue(node instanceof LogicalView);
+            assertTrue(((LogicalView) node).getXPlan().getTemplate().hasFilter());
+        } finally {
+            XConnectionManager.getInstance().setEnableXplanTableScan(enableXPlan);
+        }
+    }
+
+    @Test
+    public void testXPlanTemplateWriter() {
+        String checkHex =
+            "0801125D0A29121208084A0E0A0A746573745F7461626C65102D1A1308084A0F0A0B746573745F736368656D61102D12140A1208084A0E0A0A746573745F696E646578102D1A1A0A180A1008084A0C0A08746573745F6B6579102D120408095000";
+        String schema = "test_schema";
+        String table = "test_table";
+        String index = "test_index";
+        String key = "test_key";
+        PolarxExecPlan.AnyPlan plan = genXPlan(schema, table, index, key);
+        List tableNames = new ArrayList<>();
+        tableNames.add(new SqlIdentifier(ImmutableList.of(schema, table), SqlParserPos.ZERO));
+        List paramInfos = Lists.newArrayList();
+        RelDataType bitType = DataTypeUtil.jdbcTypeToRelDataType(-7, "BIT", 1, 0, 1, true);
+        RelDataType tinyIntType = DataTypeUtil.jdbcTypeToRelDataType(-7, "TINYINT", 3, 0, 1, true);
+        XPlanUtil.ScalarParamInfo paramInfo1 =
+            new XPlanUtil.ScalarParamInfo(XPlanUtil.ScalarParamInfo.Type.DynamicParam, 0, bitType,
+                true);
+        XPlanUtil.ScalarParamInfo paramInfo2 =
+            new XPlanUtil.ScalarParamInfo(XPlanUtil.ScalarParamInfo.Type.TableName, 0, tinyIntType,
+                true);
+        paramInfos.add(paramInfo1);
+        paramInfos.add(paramInfo2);
+
+        XPlanTemplate xPlanTemplate = new XPlanTemplate(plan, tableNames, paramInfos, index);
+
+        DRDSRelJson drdsRelJson = new DRDSRelJson(new JsonBuilder(), true);
+        Map o = (Map) drdsRelJson.toJson(xPlanTemplate);
+        System.out.println(o);
+
+        byte[] template = hexToBytes((String) o.get("template"));
+        List tableNamesCheck = (List) o.get("tableNames");
+        List schemaNamesCheck = (List) o.get("schemaNames");
+        String indexNameCheck = (String) o.get("indexName");
+        List paramInfosCheck = (List) o.get("paramInfo");
+
+        assertTrue(checkHex.equalsIgnoreCase(HexBin.encode(template)));
+        assertTrue(tableNamesCheck.size() == 1 && tableNamesCheck.get(0).equalsIgnoreCase(table));
+        assertTrue(schemaNamesCheck.size() == 1 && schemaNamesCheck.get(0).equalsIgnoreCase(schema));
+        assertTrue(indexNameCheck.equalsIgnoreCase(index));
+        assertTrue(paramInfosCheck.size() == 2);
+        assertTrue((paramInfosCheck.get(0).get("type").toString()
+            .equalsIgnoreCase(XPlanUtil.ScalarParamInfo.Type.DynamicParam.name())));
+        assertTrue(((Integer) (paramInfosCheck.get(0).get("id")) == 0));
+        assertTrue((Boolean) (paramInfosCheck.get(0).get("isBit")));
+        assertTrue((Boolean) (paramInfosCheck.get(0).get("isNullAble")));
+
+        assertTrue((paramInfosCheck.get(1).get("type").toString()
+            .equalsIgnoreCase(XPlanUtil.ScalarParamInfo.Type.TableName.name())));
+        assertTrue(((Integer) (paramInfosCheck.get(1).get("id")) == 0));
+        assertTrue(!(Boolean) (paramInfosCheck.get(1).get("isBit")));
+        assertTrue((Boolean) (paramInfosCheck.get(1).get("isNullAble")));
+    }
+
+    public static PolarxExecPlan.AnyPlan genXPlan(String schema, String table, String index, String key) {
+        final PolarxExecPlan.TableInfo.Builder tableBuilder = PolarxExecPlan.TableInfo.newBuilder();
+        tableBuilder.setSchemaName(XUtil.genUtf8StringScalar(schema));
+        tableBuilder.setName(XUtil.genUtf8StringScalar(table));
+        final PolarxExecPlan.IndexInfo.Builder indexBuilder = PolarxExecPlan.IndexInfo.newBuilder();
+        indexBuilder.setName(XUtil.genUtf8StringScalar(index));
+        final PolarxExecPlan.KeyExpr.Builder keyBuilder = PolarxExecPlan.KeyExpr.newBuilder();
+        keyBuilder.setField(XUtil.genUtf8StringScalar(key));
+        keyBuilder.setValue(XUtil.genPlaceholderScalar(0));
+        final PolarxExecPlan.GetExpr.Builder exprBuilder = PolarxExecPlan.GetExpr.newBuilder();
+        exprBuilder.addKeys(keyBuilder);
+        final PolarxExecPlan.GetPlan.Builder getBuilder = PolarxExecPlan.GetPlan.newBuilder();
+        getBuilder.setTableInfo(tableBuilder);
+        getBuilder.setIndexInfo(indexBuilder);
+        getBuilder.addKeys(exprBuilder);
+        final PolarxExecPlan.AnyPlan.Builder anyBuilder = PolarxExecPlan.AnyPlan.newBuilder();
+        anyBuilder.setPlanType(PolarxExecPlan.AnyPlan.PlanType.GET);
+        anyBuilder.setGetPlan(getBuilder);
+        return anyBuilder.build();
+//            final PolarxExecPlan.TableProject.Builder projBuilder = PolarxExecPlan.TableProject.newBuilder();
+//            projBuilder.setSubReadPlan(anyBuilder);
+//            projBuilder.addFields(XUtil.genUtf8StringScalar(target));
+//            final PolarxExecPlan.AnyPlan.Builder finalBuilder = PolarxExecPlan.AnyPlan.newBuilder();
+//            finalBuilder.setPlanType(PolarxExecPlan.AnyPlan.PlanType.TABLE_PROJECT);
+//            finalBuilder.setTableProject(projBuilder);
+//            return finalBuilder.build();
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/LogicalViewExternalizeTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/LogicalViewExternalizeTest.java
index bb39df7d5..c4d19336a 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/LogicalViewExternalizeTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/LogicalViewExternalizeTest.java
@@ -16,11 +16,12 @@
 
 package com.alibaba.polardbx.optimizer.planmanager;
 
+import com.alibaba.polardbx.optimizer.BaseRuleTest;
+import com.alibaba.polardbx.optimizer.PlannerContext;
 import com.alibaba.polardbx.optimizer.core.DrdsConvention;
 import com.alibaba.polardbx.optimizer.core.rel.HashAgg;
 import com.alibaba.polardbx.optimizer.core.rel.LogicalView;
 import com.google.common.collect.ImmutableList;
-import com.alibaba.polardbx.optimizer.BaseRuleTest;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.AggregateCall;
 import org.apache.calcite.rel.logical.LogicalFilter;
@@ -31,14 +32,17 @@
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.Util;
+import org.junit.Assert;
 import org.junit.Test;
 
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.util.Arrays;
 
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.AS_OF_57;
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 
 public class LogicalViewExternalizeTest extends BaseRuleTest {
     /**
@@ -63,12 +67,12 @@ public void testWriter() {
             ImmutableBitSet.of(0),
             null,
             ImmutableList.of(AggregateCall.create(SqlStdOperatorTable.COUNT,
-                true,
-                false,
-                ImmutableList.of(1),
-                -1,
-                bigIntType,
-                "c"),
+                    true,
+                    false,
+                    ImmutableList.of(1),
+                    -1,
+                    bigIntType,
+                    "c"),
                 AggregateCall.create(SqlStdOperatorTable.COUNT,
                     false,
                     false,
@@ -92,14 +96,59 @@ public void testReader() {
         final DRDSRelJsonReader reader = new DRDSRelJsonReader(relOptCluster, schema, null, false);
         RelNode node;
         try {
-            node = reader.read(XX);
+            node = reader.read(EXPECTED);
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
         final DRDSRelJsonWriter writer = new DRDSRelJsonWriter(false);
+        writer.setPlannerContext(PlannerContext.getPlannerContext(node));
         node.explain(writer);
         String s = writer.asString();
 
-        assertThat(Util.toLinux(s).replaceAll("\n", "").replaceAll("[\t ]", ""), is(XX));
+        PlannerContext plannerContext = PlannerContext.getPlannerContext(node);
+        assertTrue(plannerContext.isUseColumnar() && plannerContext.getColumnarMaxShardCnt() == 40);
+        assertThat(
+            Util.toLinux(s).replaceAll("\n", "").replaceAll("\\\\n", "").replaceAll("[\t ]", ""),
+            is(EXPECTED));
+    }
+
+    private final String EXPECTED =
+        "{\"rels\":[{\"id\":\"0\",\"relOp\":\"LogicalView\",\"table\":[\"optest\",\"emp\"],\"tableNames\":[\"emp\"],\"pushDownOpt\":{\"pushrels\":[{\"id\":\"0\",\"relOp\":\"LogicalTableScan\",\"table\":[\"optest\",\"emp\"],\"flashback\":null,\"inputs\":[]}]},\"schemaName\":\"optest\",\"partitions\":[],\"flashback\":null},{\"id\":\"1\",\"relOp\":\"LogicalFilter\",\"condition\":{\"op\":\"SqlBinaryOperator=\",\"operands\":[{\"input\":2,\"name\":\"$2\",\"type\":{\"type\":\"TINYINT\",\"nullable\":true,\"precision\":1}},10],\"type\":{\"type\":\"BIGINT\",\"nullable\":true}}},{\"id\":\"2\",\"relOp\":\"HashAgg\",\"group\":[0],\"aggs\":[{\"agg\":\"SqlCountAggFunctionCOUNT\",\"type\":{\"type\":\"BIGINT\",\"nullable\":true},\"distinct\":true,\"operands\":[1],\"filter\":-1},{\"agg\":\"SqlCountAggFunctionCOUNT\",\"type\":{\"type\":\"BIGINT\",\"nullable\":true},\"distinct\":false,\"operands\":[],\"filter\":-1}]}],\"args\":\"{\\\"columnarMaxShardCnt\\\":40,\\\"useColumnar\\\":true}\"}";
+
+    private final String AS_OF_TSO_WRITER =
+        "{  \"rels\": [    {      \"id\": \"0\",      \"relOp\": \"LogicalView\",      \"table\": [        \"optest\",        \"emp\"      ],      \"tableNames\": [        \"emp\"      ],      \"pushDownOpt\": {        \"pushrels\": [          {            \"id\": \"0\",            \"relOp\": \"LogicalTableScan\",            \"table\": [              \"optest\",              \"emp\"            ],            \"flashback\": {              \"index\": 0,              \"skindex\": -1,              \"subindex\": -1,              \"reltype\": {                \"type\": \"BIGINT\",                \"nullable\": true              },              \"type\": \"DYNAMIC\"            },            \"flashbackOperator\": \"SqlAsOf57OperatorAS OF TSO\",            \"inputs\": []          }        ]      },      \"schemaName\": \"optest\",      \"partitions\": [],      \"flashback\": {        \"index\": 0,        \"skindex\": -1,        \"subindex\": -1,        \"reltype\": {          \"type\": \"BIGINT\",          \"nullable\": true        },        \"type\": \"DYNAMIC\"      },      \"flashbackOperator\": \"SqlAsOf57OperatorAS OF TSO\"    }  ]}";
+
+    @Test
+    public void testAsOfTsoWriter() {
+        LogicalTableScan scan = LogicalTableScan.create(relOptCluster,
+            schema.getTableForMember(Arrays.asList("optest", "emp")));
+        LogicalView logicalView = LogicalView.create(scan, scan.getTable());
+        final RexBuilder rexBuilder = relOptCluster.getRexBuilder();
+        final RelDataType bigIntType = relOptCluster.getTypeFactory().createSqlType(SqlTypeName.BIGINT);
+        scan.setFlashback(rexBuilder.makeDynamicParam(bigIntType, 0));
+        scan.setFlashbackOperator(AS_OF_57);
+        logicalView.setFlashback(rexBuilder.makeDynamicParam(bigIntType, 0));
+        logicalView.setFlashbackOperator(AS_OF_57);
+
+        final DRDSRelJsonWriter writer = new DRDSRelJsonWriter(false);
+        logicalView.explain(writer);
+
+        String s = writer.asString();
+
+        assertThat(s.replaceAll("\n", "").replaceAll("\t", ""), is(AS_OF_TSO_WRITER));
+    }
+
+    @Test
+    public void testAsOfTsoReader() {
+        final DRDSRelJsonReader reader = new DRDSRelJsonReader(relOptCluster, schema, null, false);
+        RelNode node;
+        try {
+            node = reader.read(AS_OF_TSO_WRITER);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        Assert.assertTrue(node instanceof LogicalView);
+        Assert.assertNotNull(((LogicalView) node).getFlashback());
+        Assert.assertSame(((LogicalView) node).getFlashbackOperator(), AS_OF_57);
     }
 }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/LogicalViewTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/LogicalViewTest.java
index d00fbf7f8..f15c1dbe4 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/LogicalViewTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/LogicalViewTest.java
@@ -8,15 +8,14 @@
 import com.alibaba.polardbx.optimizer.core.rel.LogicalModifyView;
 import com.alibaba.polardbx.optimizer.core.rel.LogicalView;
 import com.alibaba.polardbx.optimizer.core.rel.OSSTableScan;
+import com.alibaba.polardbx.optimizer.utils.RelUtils;
 import com.clearspring.analytics.util.Lists;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.rel.logical.LogicalJoin;
 import org.apache.calcite.rel.logical.LogicalTableScan;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
-import org.apache.calcite.rel.type.RelDataTypeImpl;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.junit.Test;
@@ -89,4 +88,14 @@ public void testLogicalViewColumnOriginsCopy() {
         checkSize = ossTableScanCopy.getColumnOrigins().size();
         Assert.assertTrue(size == checkSize);
     }
+
+    @Test
+    public void testFlashBack() {
+        LogicalTableScan scan1 = LogicalTableScan.create(relOptCluster,
+            schema.getTableForMember(Arrays.asList("optest", "emp")));
+        org.junit.Assert.assertFalse(RelUtils.containFlashback(scan1));
+
+        scan1.setFlashback(relOptCluster.getRexBuilder().makeCall(SqlStdOperatorTable.CURRENT_TIMESTAMP));
+        org.junit.Assert.assertTrue(RelUtils.containFlashback(scan1));
+    }
 }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/PlanManagerUtilTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/PlanManagerUtilTest.java
new file mode 100644
index 000000000..a0bcd1eeb
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/planmanager/PlanManagerUtilTest.java
@@ -0,0 +1,432 @@
+package com.alibaba.polardbx.optimizer.planmanager;
+
+import com.alibaba.polardbx.common.jdbc.ParameterContext;
+import com.alibaba.polardbx.common.jdbc.ParameterMethod;
+import com.alibaba.polardbx.common.jdbc.Parameters;
+import com.alibaba.polardbx.common.jdbc.RawString;
+import com.alibaba.polardbx.common.properties.DynamicConfig;
+import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.optimizer.BaseRuleTest;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan;
+import com.alibaba.polardbx.optimizer.core.rel.LogicalView;
+import com.alibaba.polardbx.optimizer.parse.FastsqlParser;
+import com.clearspring.analytics.util.Lists;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.calcite.adapter.java.JavaTypeFactory;
+import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
+import org.apache.calcite.rel.logical.LogicalFilter;
+import org.apache.calcite.rel.logical.LogicalTableScan;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_PARAM_TYPE_CHANGE;
+import static com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil.getRexNodeTableMap;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.AND;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author fangwu
+ */
+public class PlanManagerUtilTest extends BaseRuleTest {
+
+    @Test
+    public void testRelNodeToJsonWithNullPlan() {
+        assert null == PlanManagerUtil.relNodeToJson(null, false);
+    }
+
+    @Test
+    public void testGettingTableSetFromAst() {
+        String sql1 = "WITH tb AS (\n"
+            + "  SELECT\n"
+            + "    a.c1 x, b.c2 y\n"
+            + "  FROM \n"
+            + "    db1.t1 a\n"
+            + "    JOIN db4.t2 b on a.name=b.name\n"
+            + ")\n"
+            + "\n"
+            + "SELECT \n"
+            + "  (tb.x + 1),\n"
+            + "  concat(tb.y, 'xx', a.name),\n"
+            + "  (select max(salary) from db5.t3),\n"
+            + "  b.salary\n"
+            + "FROM \n"
+            + "  db2.t1 a \n"
+            + "  JOIN db3.t2 b on a.id = b.id\n"
+            + "  JOIN tb c on a.age = c.age\n"
+            + "WHERE\n"
+            + "\tb.val > (select avg(val) from db6.t1)\n"
+            + "  AND NOT EXISTS ( SELECT 1 FROM t1 d WHERE d.id > 0);";
+        SqlNode sqlNode1 = new FastsqlParser().parse(sql1).get(0);
+        Set> tableSet1 = PlanManagerUtil.getTableSetFromAst(sqlNode1);
+        Set> real1 = new HashSet<>();
+        real1.add(Pair.of("db1", "t1"));
+        real1.add(Pair.of("db4", "t2"));
+        real1.add(Pair.of("db5", "t3"));
+        real1.add(Pair.of("db2", "t1"));
+        real1.add(Pair.of("db3", "t2"));
+        real1.add(Pair.of("db6", "t1"));
+        real1.add(Pair.of(null, "t1"));
+        Assert.assertTrue(tableSet1.size() == real1.size());
+        for (Pair pair : tableSet1) {
+            if (!real1.contains(pair)) {
+                Assert.fail();
+            }
+        }
+
+        String sql2 = "Select * from b.t b join a.t a on a.id=b.id where a.id = 2";
+        SqlNode sqlNode2 = new FastsqlParser().parse(sql2).get(0);
+        Set> tableSet2 = PlanManagerUtil.getTableSetFromAst(sqlNode2);
+        Set> real2 = new HashSet<>();
+        real2.add(Pair.of("a", "t"));
+        real2.add(Pair.of("b", "t"));
+        Assert.assertTrue(tableSet2.size() == real2.size());
+        for (Pair pair : tableSet2) {
+            if (!real2.contains(pair)) {
+                Assert.fail();
+            }
+        }
+
+        String sql3 = "select * from (select * from a.t1 a join b.t2 b on a.id = b.id)";
+        SqlNode sqlNode3 = new FastsqlParser().parse(sql3).get(0);
+        Set> tableSet3 = PlanManagerUtil.getTableSetFromAst(sqlNode3);
+        Set> real3 = new HashSet<>();
+        real3.add(Pair.of("a", "t1"));
+        real3.add(Pair.of("b", "t2"));
+        Assert.assertTrue(tableSet3.size() == real3.size());
+        for (Pair pair : tableSet3) {
+            if (!real3.contains(pair)) {
+                Assert.fail();
+            }
+        }
+
+    }
+
+    /**
+     * Does nothing if dynamic configuration disables parameter type changes.
+     */
+    @Test
+    public void testChangeParameterTypeByTableMetadataWhenDisabled() {
+        try {
+            DynamicConfig.getInstance().loadValue(null, ENABLE_PARAM_TYPE_CHANGE, "true");
+
+            ExecutionContext mockExecutionContext = mock(ExecutionContext.class);
+            ExecutionPlan mockExecutionPlan = mock(ExecutionPlan.class);
+
+            DynamicConfig.getInstance().setEnableChangeParamTypeByMeta(false);
+
+            PlanManagerUtil.changeParameterTypeByTableMetadata(mockExecutionContext, mockExecutionPlan);
+
+            // Verify no interactions occurred with execution context indicating no attempt at type conversion was made.
+            Mockito.verifyZeroInteractions(mockExecutionContext);
+        } finally {
+            DynamicConfig.getInstance().loadValue(null, ENABLE_PARAM_TYPE_CHANGE, "false");
+        }
+    }
+
+    /**
+     * When retrieving the table expression map from the execution plan fails,
+     * the function should return directly.
+     * Expected behavior: Direct return when getting the table expression map returns null.
+     */
+    @Test
+    public void testChangeParameterTypeByTableMetadataWithNullTableExpressionMap() {
+        try {
+            DynamicConfig.getInstance().loadValue(null, ENABLE_PARAM_TYPE_CHANGE, "true");
+
+            ExecutionContext executionContext = mock(ExecutionContext.class);
+            ExecutionPlan plan = mock(ExecutionPlan.class);
+            when(getRexNodeTableMap(plan.getPlan())).thenReturn(null);
+
+            PlanManagerUtil.changeParameterTypeByTableMetadata(executionContext, plan);
+
+            verifyNoInteractions(executionContext);
+        } finally {
+            DynamicConfig.getInstance().loadValue(null, ENABLE_PARAM_TYPE_CHANGE, "false");
+        }
+    }
+
+    /**
+     * When the table expression map retrieved from the execution plan is empty,
+     * the function should return directly.
+     * Expected behavior: Direct return when the expression map is empty.
+     */
+    @Test
+    public void testChangeParameterTypeByTableMetadataWithEmptyTableExpressionMap() {
+        try {
+            DynamicConfig.getInstance().loadValue(null, ENABLE_PARAM_TYPE_CHANGE, "true");
+
+            ExecutionContext executionContext = mock(ExecutionContext.class);
+            ExecutionPlan plan = mock(ExecutionPlan.class);
+
+            PlanManagerUtil.changeParameterTypeByTableMetadata(executionContext, plan);
+
+            verifyNoInteractions(executionContext);
+        } finally {
+            DynamicConfig.getInstance().loadValue(null, ENABLE_PARAM_TYPE_CHANGE, "false");
+        }
+    }
+
+    @Test
+    public void testChangeParameterTypeByTableMetadata() {
+        try {
+            DynamicConfig.getInstance().loadValue(null, ENABLE_PARAM_TYPE_CHANGE, "true");
+            ExecutionContext executionContext = new ExecutionContext("optest");
+            executionContext.setParams(new Parameters());
+            executionContext.getParams().getCurrentParameter()
+                .put(1, new ParameterContext(ParameterMethod.setString, new Object[] {1, "1"}));
+            executionContext.getParams().getCurrentParameter()
+                .put(2, new ParameterContext(ParameterMethod.setInt, new Object[] {2, 2}));
+            executionContext.getParams().getCurrentParameter()
+                .put(3, new ParameterContext(ParameterMethod.setObject1, new Object[] {
+                    3, new RawString(
+                    ImmutableList.of("1", "2", "3"))}));
+            executionContext.getParams().getCurrentParameter()
+                .put(4, new ParameterContext(ParameterMethod.setObject1, new Object[] {
+                    4, new RawString(
+                    ImmutableList.of(1, 2, 3))}));
+
+            ExecutionPlan plan = mock(ExecutionPlan.class);
+            LogicalTableScan scan = LogicalTableScan.create(relOptCluster,
+                schema.getTableForMember(Arrays.asList("optest", "emp")));
+            LogicalView logicalView = LogicalView.create(scan, scan.getTable());
+            final RexBuilder rexBuilder = relOptCluster.getRexBuilder();
+            JavaTypeFactory typeFactory = new JavaTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+            RelDataType rowTypeInt = typeFactory.createSqlType(SqlTypeName.BIGINT);
+            RelDataType rowTypeChar = typeFactory.createSqlType(SqlTypeName.VARCHAR);
+
+            // int = varchar
+            RexNode condition = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
+                rexBuilder.makeFieldAccess(rexBuilder.makeRangeReference(logicalView), "userId", true),
+                rexBuilder.makeDynamicParam(rowTypeChar, 0));
+
+            condition = rexBuilder.makeCall(AND, condition, rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
+                rexBuilder.makeDynamicParam(rowTypeChar, 0),
+                rexBuilder.makeFieldAccess(rexBuilder.makeRangeReference(logicalView), "userId", true)
+            ));
+
+            // varchar = int
+            condition = rexBuilder.makeCall(AND, condition, rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
+                rexBuilder.makeDynamicParam(rowTypeInt, 1),
+                rexBuilder.makeFieldAccess(rexBuilder.makeRangeReference(logicalView), "name", true)));
+
+            condition = rexBuilder.makeCall(AND, condition, rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
+                rexBuilder.makeFieldAccess(rexBuilder.makeRangeReference(logicalView), "name", true),
+                rexBuilder.makeDynamicParam(rowTypeInt, 1)));
+
+            // int IN ROW(varchar)
+            condition = rexBuilder.makeCall(AND, condition,
+                rexBuilder.makeCall(SqlStdOperatorTable.IN,
+                    rexBuilder.makeFieldAccess(rexBuilder.makeRangeReference(logicalView), "userId", true),
+                    rexBuilder.makeCall(SqlStdOperatorTable.ROW, rexBuilder.makeDynamicParam(rowTypeChar, 2)))
+            );
+
+            // varchar IN ROW(int)
+            condition = rexBuilder.makeCall(AND, condition,
+                rexBuilder.makeCall(SqlStdOperatorTable.IN,
+                    rexBuilder.makeFieldAccess(rexBuilder.makeRangeReference(logicalView), "name", true),
+                    rexBuilder.makeCall(SqlStdOperatorTable.ROW, rexBuilder.makeDynamicParam(rowTypeInt, 3)))
+            );
+
+            LogicalFilter filter = LogicalFilter.create(logicalView, condition);
+            when(plan.getPlan()).thenReturn(filter);
+            System.out.println(executionContext.getParams());
+            assertTrue("['1', 2, Raw('1','2','3'), Raw(1,2,3)]".equals(executionContext.getParams().toString()));
+            PlanManagerUtil.changeParameterTypeByTableMetadata(executionContext, plan);
+
+            System.out.println(executionContext.getParams());
+            assertTrue("[1, '2', Raw(1,2,3), Raw('1','2','3')]".equals(executionContext.getParams().toString()));
+        } finally {
+            DynamicConfig.getInstance().loadValue(null, ENABLE_PARAM_TYPE_CHANGE, "false");
+        }
+    }
+
+    /**
+     * Test case 1: Verify that when an empty string is passed, the correct fixed-length hex string is returned.
+     * Input: ""
+     * Expected output: "00000000" (Assuming TStringUtil.int2FixedLenHexStr converts integers to an 8-character hex string)
+     */
+    @Test
+    public void testGenerateTemplateIdWithEmptyString() {
+        String input = "";
+        String expectedOutput =
+            "00000000"; // Assuming hashCode(input) == 0, and the resulting hex string is also 8 characters long
+        String actualOutput = PlanManagerUtil.generateTemplateId(input);
+
+        assertEquals(expectedOutput, actualOutput);
+    }
+
+    /**
+     * Test case 2: Confirm that when a specific string is passed, the correct fixed-length hex string is returned.
+     * Input: "SELECT * FROM table WHERE id = ?"
+     * Output: Fixed-length hex string calculated from the hashCode of the above string
+     */
+    @Test
+    public void testGenerateTemplateIdWithSpecificString() {
+        String input = "SELECT * FROM table WHERE id = ?";
+        String expectedOutput = Integer.toHexString(input.hashCode()).toLowerCase(); // Calculate expected output
+        while (expectedOutput.length()
+            < 8) { // Ensure the string length is at least 8 characters long (pad with zeros if necessary)
+            expectedOutput = "0" + expectedOutput;
+        }
+        String actualOutput = PlanManagerUtil.generateTemplateId(input);
+
+        assertEquals(expectedOutput.toLowerCase(),
+            actualOutput); // Compare outputs after converting both strings to uppercase for consistent comparison
+    }
+
+    /**
+     * Test case 3: Check behavior with a longer string that results in a larger hashCode value.
+     * Input: "A very long SQL query with multiple conditions and joins."
+     * Expected output: Fixed-length hex string derived from the hashCode of the input string
+     */
+    @Test
+    public void testGenerateTemplateIdWithLongerString() {
+        String input = "A very long SQL query with multiple conditions and joins.";
+        String expectedOutput = Integer.toHexString(input.hashCode()).toLowerCase();
+        while (expectedOutput.length() < 8) {
+            expectedOutput = "0" + expectedOutput; // Pad with leading zeros to maintain fixed length
+        }
+        String actualOutput = PlanManagerUtil.generateTemplateId(input);
+
+        assertEquals(expectedOutput.toLowerCase(), actualOutput); // Perform comparison in uppercase for consistency
+    }
+
+    @Test
+    public void testConvertSimpleStringToLong() {
+        ExecutionContext mockExecutionContext;
+        Parameters mockParams;
+        ParameterContext mockParameterContext;
+        RawString mockRawString;
+        mockExecutionContext = Mockito.mock(ExecutionContext.class);
+        mockParams = Mockito.mock(Parameters.class);
+        mockParameterContext = Mockito.mock(ParameterContext.class);
+        mockRawString = Mockito.mock(RawString.class);
+
+        // 设置mock对象行为
+        when(mockExecutionContext.getParams()).thenReturn(mockParams);
+        when(mockParams.getCurrentParameter()).thenReturn(Maps.newHashMap());
+        List objList = Lists.newArrayList();
+        objList.add("10");
+        objList.add("20");
+        when(mockParameterContext.getValue()).thenReturn("10", "test", new RawString(objList));
+
+        Set indices = Sets.newHashSet();
+        indices.add(0);
+        Map map = Maps.newHashMap();
+        map.put(1, mockParameterContext);
+        when(mockParams.getCurrentParameter()).thenReturn(map);
+
+        PlanManagerUtil.convertCharToIntParameters(indices, mockExecutionContext);
+
+        verify(mockParameterContext).setParameterMethod(ParameterMethod.setLong);
+        verify(mockParameterContext).setValue(10L);
+    }
+
+    @Test
+    public void testConvertRawStringToListOfLongs() {
+        ExecutionContext mockExecutionContext;
+        Parameters mockParams;
+
+        ParameterContext mockParameterContext = new ParameterContext(ParameterMethod.setObject1, new Object[] {1, 20});
+        mockExecutionContext = Mockito.mock(ExecutionContext.class);
+        mockParams = Mockito.mock(Parameters.class);
+
+        Set indices = Sets.newHashSet();
+        indices.add(1);
+        Map map = Maps.newHashMap();
+        map.put(2, mockParameterContext);
+        when(mockExecutionContext.getParams()).thenReturn(mockParams);
+        when(mockParams.getCurrentParameter()).thenReturn(map);
+        List objList = Lists.newArrayList();
+        objList.add("10");
+        objList.add("20");
+        List objListCheck = Lists.newArrayList();
+        objListCheck.add(10L);
+        objListCheck.add(20L);
+        RawString mockRawString = new RawString(objList);
+        mockParameterContext.setValue(mockRawString);
+
+        PlanManagerUtil.convertCharToIntParameters(indices, mockExecutionContext);
+
+        RawString result = (RawString) mockParameterContext.getValue();
+        assertEquals(objListCheck, result.getObjList());
+    }
+
+    @Test
+    public void testConvertIntToCharParametersWithEmptyList() {
+        Set intToCharIndices = Sets.newHashSet();
+        ExecutionContext executionContext = new ExecutionContext();
+        executionContext.setParams(new Parameters());
+        executionContext.getParams().getCurrentParameter()
+            .put(1, new ParameterContext(ParameterMethod.setObject1, new Object[] {1, 20}));
+
+        PlanManagerUtil.convertIntToCharParameters(intToCharIndices, executionContext);
+
+        assertTrue(executionContext.getParams().getCurrentParameter().get(1).getValue() instanceof Integer);
+    }
+
+    @Test
+    public void testConvertIntToCharParametersWithNumberValue() {
+        Set intToCharIndices = Sets.newHashSet();
+        intToCharIndices.add(0); // 假设第一个参数应该被转换
+        ExecutionContext executionContext = new ExecutionContext();
+        executionContext.setParams(new Parameters());
+        executionContext.getParams().getCurrentParameter()
+            .put(1, new ParameterContext(ParameterMethod.setObject1, new Object[] {1, 20}));
+
+        PlanManagerUtil.convertIntToCharParameters(intToCharIndices, executionContext);
+
+        assertTrue(executionContext.getParams().getCurrentParameter().get(1).getParameterMethod()
+            == ParameterMethod.setString);
+        assertTrue(executionContext.getParams().getCurrentParameter().get(1).getValue().equals("20")); // 验证参数方法被正确设置
+    }
+
+    @Test
+    public void testConvertIntToCharParametersWithRawStringValue() {
+        Set intToCharIndices = Sets.newHashSet();
+        intToCharIndices.add(1);
+
+        List originalList = new ArrayList<>();
+        originalList.add(1);
+        originalList.add(2);
+        originalList.add(3);
+        RawString rawString = new RawString(originalList);
+        ExecutionContext executionContext = new ExecutionContext();
+        executionContext.setParams(new Parameters());
+        executionContext.getParams().getCurrentParameter()
+            .put(2, new ParameterContext(ParameterMethod.setObject1, new Object[] {2, rawString}));
+        List objList = Lists.newArrayList();
+        objList.add("1");
+        objList.add("2");
+        objList.add("3");
+        PlanManagerUtil.convertIntToCharParameters(intToCharIndices, executionContext);
+        RawString result = (RawString) executionContext.getParams().getCurrentParameter().get(2).getValue();
+
+        assertTrue(executionContext.getParams().getCurrentParameter().get(2).getParameterMethod()
+            == ParameterMethod.setObject1);
+        assertEquals(objList, result.getObjList());
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/sharding/advisor/ShardingAdvisorTestCommon.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/sharding/advisor/ShardingAdvisorTestCommon.java
index b210786e3..54e57f5dd 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/sharding/advisor/ShardingAdvisorTestCommon.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/sharding/advisor/ShardingAdvisorTestCommon.java
@@ -63,6 +63,7 @@ protected String getPlan(String testMethodName, String targetPlan) {
         executionContext.setInternalSystemSql(false);
 
         executionContext.setParams(new Parameters());
+        executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_AUTO_FORCE_INDEX, enableAutoForceIndex);
         executionContext.getExtraCmds().put(ConnectionProperties.PARALLELISM, enableParallelQuery ? -1 : 0);
         executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_JOIN_CLUSTERING, enableJoinClustering);
         executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_MPP, enableMpp);
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/spill/SpillSpaceManagerTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/spill/SpillSpaceManagerTest.java
new file mode 100644
index 000000000..55a4e789c
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/spill/SpillSpaceManagerTest.java
@@ -0,0 +1,23 @@
+package com.alibaba.polardbx.optimizer.spill;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class SpillSpaceManagerTest {
+
+    @Test(expected = RuntimeException.class)
+    public void testMaxLimit() {
+        SpillSpaceManager spillSpaceMonitor = Mockito.spy(new SpillSpaceManager());
+        Mockito.when(spillSpaceMonitor.getCurrentMaxSpillBytes()).thenReturn(100L);
+        spillSpaceMonitor.updateBytes(100);
+    }
+
+    @Test
+    public void testCleanup() {
+        SpillSpaceManager spillSpaceMonitor = Mockito.spy(new SpillSpaceManager());
+        Mockito.when(spillSpaceMonitor.getCurrentMaxSpillBytes()).thenReturn(200L);
+        spillSpaceMonitor.updateBytes(100);
+        spillSpaceMonitor.updateBytes(-100);
+        spillSpaceMonitor.updateBytes(102);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/statis/ColumnarTracerTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/statis/ColumnarTracerTest.java
new file mode 100644
index 000000000..319cfa5b3
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/statis/ColumnarTracerTest.java
@@ -0,0 +1,120 @@
+package com.alibaba.polardbx.optimizer.statis;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class ColumnarTracerTest {
+    private static String DEFAULT_TABLE = "DEFAULT_TABLE";
+
+    @Test
+    public void testColumnarTracerMergeNoOverlap() {
+        //both left and right ColumnarTracer are available
+        String filter1 = "varchar_test_2 EQUALS feed32feed";
+        //only left
+        String filter2 = "varchar_test_2 IN (Raw('nihaore'))";
+        //only right
+        String filter3 = "(integer_test_1 EQUALS 2)";
+        ColumnarTracer left = new ColumnarTracer("default");
+        ColumnarTracer right = new ColumnarTracer("default");
+        left.tracePruneResult(DEFAULT_TABLE, filter1, 1, 1, 1, 1);
+
+        left.tracePruneResult(DEFAULT_TABLE, filter2, 1, 1, 1, 1);
+
+        right.tracePruneResult(DEFAULT_TABLE, filter3, 1, 1, 1, 1);
+
+        left.mergeColumnarTracer(right);
+        Assert.assertEquals(3, left.getPruneRecordMap().size());
+        Assert.assertEquals(1,
+            left.getPruneRecordMap().get(left.getTracerKey(DEFAULT_TABLE, filter1)).getFileNum().get());
+        Assert.assertEquals(1,
+            left.getPruneRecordMap().get(left.getTracerKey(DEFAULT_TABLE, filter2)).getFileNum().get());
+        Assert.assertEquals(1,
+            left.getPruneRecordMap().get(left.getTracerKey(DEFAULT_TABLE, filter3)).getFileNum().get());
+    }
+
+    @Test
+    public void testColumnarTracerMergeOverlap() {
+        //both left and right ColumnarTracer are available
+        String filter1 = "varchar_test_2 EQUALS feed32feed";
+        //only left
+        String filter2 = "varchar_test_2 IN (Raw('nihaore'))";
+        //only right
+        String filter3 = "(integer_test_1 EQUALS 2)";
+        ColumnarTracer left = new ColumnarTracer("default");
+        ColumnarTracer right = new ColumnarTracer("default");
+        left.tracePruneResult(DEFAULT_TABLE, filter1, 1, 1, 1, 1);
+        right.tracePruneResult(DEFAULT_TABLE, filter1, 1, 1, 1, 1);
+
+        left.tracePruneResult(DEFAULT_TABLE, filter2, 1, 1, 1, 1);
+
+        right.tracePruneResult(DEFAULT_TABLE, filter3, 1, 1, 1, 1);
+
+        left.mergeColumnarTracer(right);
+        Assert.assertEquals(3, left.getPruneRecordMap().size());
+        Assert.assertEquals(2,
+            left.getPruneRecordMap().get(left.getTracerKey(DEFAULT_TABLE, filter1)).getFileNum().get());
+        Assert.assertEquals(1,
+            left.getPruneRecordMap().get(left.getTracerKey(DEFAULT_TABLE, filter2)).getFileNum().get());
+        Assert.assertEquals(1,
+            left.getPruneRecordMap().get(left.getTracerKey(DEFAULT_TABLE, filter3)).getFileNum().get());
+    }
+
+    @Test
+    public void serializeColumnarTracerTest() throws JsonProcessingException {
+        ColumnarTracer tracer = new ColumnarTracer("default");
+        tracer.tracePruneInit(DEFAULT_TABLE, "filter1", 100L);
+        tracer.tracePruneTime(DEFAULT_TABLE, "filter1", 200L);
+        tracer.tracePruneResult(DEFAULT_TABLE, "filter1", 1, 2, 3, 4);
+        tracer.tracePruneIndex(DEFAULT_TABLE, "filter1", 5, 6, 7);
+        ObjectMapper objectMapper = new ObjectMapper();
+        // 序列化ColumnarTracer
+        String json = objectMapper.writeValueAsString(tracer);
+
+        // 反序列化ColumnarTracer
+        ColumnarTracer deserializedTracer = objectMapper.readValue(json, ColumnarTracer.class);
+
+        // 验证序列化和反序列化后的对象是否一致
+        Assert.assertEquals(tracer.getPruneRecordMap(), deserializedTracer.getPruneRecordMap());
+    }
+
+    @Test
+    public void columnarPruneRecordSimpleTest() {
+        //both left and right ColumnarTracer are available
+        String filter1 = "varchar_test_2 EQUALS feed32feed";
+        ColumnarPruneRecord left = new ColumnarPruneRecord(DEFAULT_TABLE, filter1);
+        Assert.assertTrue(left.equals(left));
+        left.setFilter(filter1);
+        left.setTableName(DEFAULT_TABLE);
+        left.setInitIndexTime(new AtomicLong(1));
+        left.setIndexPruneTime(new AtomicLong(1));
+        left.setFileNum(new AtomicInteger(1));
+        left.setStripeNum(new AtomicInteger(1));
+        left.setRgNum(new AtomicInteger(1));
+        left.setRgLeftNum(new AtomicInteger(1));
+        left.setSortKeyPruneNum(new AtomicInteger(1));
+        left.setZoneMapPruneNum(new AtomicInteger(1));
+        left.setBitMapPruneNum(new AtomicInteger(1));
+
+        ColumnarPruneRecord right = new ColumnarPruneRecord(DEFAULT_TABLE, filter1);
+
+        right.setFilter(filter1);
+        right.setTableName(DEFAULT_TABLE);
+        right.setInitIndexTime(new AtomicLong(1));
+        right.setIndexPruneTime(new AtomicLong(1));
+        right.setFileNum(new AtomicInteger(1));
+        right.setStripeNum(new AtomicInteger(1));
+        right.setRgNum(new AtomicInteger(1));
+        right.setRgLeftNum(new AtomicInteger(1));
+        right.setSortKeyPruneNum(new AtomicInteger(1));
+        right.setZoneMapPruneNum(new AtomicInteger(1));
+        right.setBitMapPruneNum(new AtomicInteger(1));
+
+        Assert.assertTrue(left.equals(right));
+    }
+
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/ExecutionPlanPropertiesTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/ExecutionPlanPropertiesTest.java
new file mode 100644
index 000000000..b9c37f91c
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/ExecutionPlanPropertiesTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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 com.alibaba.polardbx.optimizer.utils;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.util.BitSet;
+
+public class ExecutionPlanPropertiesTest {
+    @Test
+    public void testGetPropertiesMaxValue() {
+        int maxValue = ExecutionPlanProperties.getMaxPropertyValue();
+        Assert.assertEquals(maxValue, ExecutionPlanProperties.MODIFY_FOREIGN_KEY + 1);
+    }
+
+    @Test
+    public void testBitSetMaxValue() throws Exception {
+        Field field = BitSet.class.getDeclaredField("sizeIsSticky");
+        field.setAccessible(true);
+
+        int maxValue = ExecutionPlanProperties.getMaxPropertyValue();
+        BitSet bitSetWithMaxValue = new BitSet(maxValue);
+        bitSetWithMaxValue.set(ExecutionPlanProperties.MODIFY_FOREIGN_KEY, true);
+
+        boolean sizeIsSticky = (boolean) field.get(bitSetWithMaxValue);
+        Assert.assertTrue(sizeIsSticky);
+
+        BitSet bitSet = new BitSet();
+        bitSet.set(ExecutionPlanProperties.MODIFY_FOREIGN_KEY, true);
+        bitSet.clone();
+        sizeIsSticky = (boolean) field.get(bitSet);
+        Assert.assertFalse(sizeIsSticky);
+    }
+
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/GsiUtils.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/GsiUtils.java
index 1b2cda2e2..a077c6c3d 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/GsiUtils.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/GsiUtils.java
@@ -112,7 +112,7 @@ public static void buildIndexMeta(List indexRecords,
             indexStatus));
 
         final GsiMetaManager.TableRecord tableRecord =
-            buildTableRecord(tableRule, catalog, schemaName, indexTableName, indexComment);
+            buildTableRecord(tableRule, catalog, schemaName, indexTableName, indexComment, indexDef.isColumnar());
 
         tableRecords.add(tableRecord);
     }
@@ -150,7 +150,7 @@ public static List buildIndexRecord(SqlIndexDefiniti
                 indexComment,
                 seqInIndex,
                 column,
-                indexDef.isClustered()));
+                indexDef.isClustered(), indexDef.isColumnar()));
             seqInIndex++;
         }
 
@@ -227,7 +227,7 @@ public static void buildIndexMeta(List indexRecords,
                 indexComment,
                 seqInIndex,
                 column,
-                createIndex.createClusteredIndex()));
+                createIndex.createClusteredIndex(), createIndex.createCci()));
             seqInIndex++;
         }
 
@@ -253,7 +253,8 @@ public static void buildIndexMeta(List indexRecords,
 
         if (createIndex != null && createIndex.getPartitioning() == null) {
             final GsiMetaManager.TableRecord
-                tableRecord = buildTableRecord(tableRule, catalog, schema, indexTableName, indexComment);
+                tableRecord =
+                buildTableRecord(tableRule, catalog, schema, indexTableName, indexComment, createIndex.createCci());
 
             tableRecords.add(tableRecord);
         }
@@ -350,7 +351,8 @@ public static void buildIndexMeta(List indexRecords,
     }
 
     private static GsiMetaManager.TableRecord buildTableRecord(TableRule tableRule, String catalog, String schema,
-                                                               String indexTableName, String comment) {
+                                                               String indexTableName, String comment,
+                                                               boolean columnar) {
         String dbPartitionPolicy = null;
         String tbPartitionPolicy = null;
 
@@ -359,7 +361,7 @@ private static GsiMetaManager.TableRecord buildTableRecord(TableRule tableRule,
                 catalog,
                 schema,
                 indexTableName,
-                GsiMetaManager.TableType.GSI.getValue(),
+                columnar ? GsiMetaManager.TableType.COLUMNAR.getValue() : GsiMetaManager.TableType.GSI.getValue(),
                 "",
                 "",
                 null,
@@ -410,7 +412,7 @@ private static GsiMetaManager.TableRecord buildTableRecord(TableRule tableRule,
             catalog,
             schema,
             indexTableName,
-            GsiMetaManager.TableType.GSI.getValue(),
+            columnar ? GsiMetaManager.TableType.COLUMNAR.getValue() : GsiMetaManager.TableType.GSI.getValue(),
             dbPartitionKey,
             dbPartitionPolicy,
             dbCount,
@@ -599,12 +601,17 @@ private static GsiMetaManager.IndexRecord indexColumnRecord(String catalog, Stri
                                                                 String indexType, int indexLocation,
                                                                 IndexStatus indexStatus,
                                                                 long version, String indexComment, int seqInIndex,
-                                                                SqlIndexColumnName column, boolean clusteredIndex) {
+                                                                SqlIndexColumnName column, boolean clusteredIndex,
+                                                                boolean cci) {
         final String columnName = column.getColumnNameStr();
         final String collation = null == column.isAsc() ? null : (column.isAsc() ? "A" : "D");
         final Long subPart = null == column.getLength() ? null : (RelUtils.longValue(column.getLength()));
         final String packed = null;
         final String comment = "INDEX";
+        long flag = 0L;
+        flag |= (clusteredIndex ? IndexesRecord.FLAG_CLUSTERED : 0L);
+        flag |= (cci ? IndexesRecord.FLAG_COLUMNAR : 0L);
+
         return new GsiMetaManager.IndexRecord(-1,
             catalog,
             schema,
@@ -627,7 +634,7 @@ private static GsiMetaManager.IndexRecord indexColumnRecord(String catalog, Stri
             indexTableName,
             indexStatus.getValue(),
             version,
-            clusteredIndex ? IndexesRecord.FLAG_CLUSTERED : 0L,
+            flag,
             IndexVisibility.VISIBLE.getValue());
     }
 
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/MppPlanCheckersTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/MppPlanCheckersTest.java
new file mode 100644
index 000000000..f732d6e1b
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/MppPlanCheckersTest.java
@@ -0,0 +1,202 @@
+package com.alibaba.polardbx.optimizer.utils;
+
+import com.alibaba.polardbx.common.properties.DynamicConfig;
+import com.alibaba.polardbx.optimizer.PlannerContext;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.utils.mppchecker.MppPlanCheckerInput;
+import org.junit.Test;
+
+import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_COLUMNAR_OPTIMIZER;
+import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR;
+import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_MPP;
+import static com.alibaba.polardbx.common.utils.Assert.assertTrue;
+import static com.alibaba.polardbx.druid.sql.ast.SqlType.SELECT;
+import static com.alibaba.polardbx.druid.sql.ast.SqlType.SELECT_FOR_UPDATE;
+import static com.alibaba.polardbx.optimizer.utils.mppchecker.MppPlanCheckers.COLUMNAR_TRANSACTION_CHECKER;
+import static com.alibaba.polardbx.optimizer.utils.mppchecker.MppPlanCheckers.ENABLE_COLUMNAR_CHECKER;
+import static com.alibaba.polardbx.optimizer.utils.mppchecker.MppPlanCheckers.EXPLAIN_EXECUTE_CHECKER;
+import static com.alibaba.polardbx.optimizer.utils.mppchecker.MppPlanCheckers.EXPLAIN_STATISTICS_CHECKER;
+import static com.alibaba.polardbx.optimizer.utils.mppchecker.MppPlanCheckers.INTERNAL_SYSTEM_SQL_CHECKER;
+import static com.alibaba.polardbx.optimizer.utils.mppchecker.MppPlanCheckers.MPP_ENABLED_CHECKER;
+import static com.alibaba.polardbx.optimizer.utils.mppchecker.MppPlanCheckers.TRANSACTION_CHECKER;
+import static com.alibaba.polardbx.optimizer.utils.mppchecker.MppPlanCheckers.UPDATE_CHECKER;
+
+/**
+ * @author fangwu
+ */
+public class MppPlanCheckersTest {
+
+    @Test
+    public void testMppEnable() {
+        PlannerContext plannerContext = new PlannerContext();
+        ExecutionContext ec1 = new ExecutionContext();
+        ec1.getParamManager().getProps().put(ENABLE_MPP, "false");
+
+        plannerContext.setExecutionContext(ec1);
+
+        ExecutionContext ec2 = new ExecutionContext();
+        ec2.getParamManager().getProps().put(ENABLE_MPP, "true");
+
+        MppPlanCheckerInput input = new MppPlanCheckerInput(null, plannerContext, ec2);
+
+        assertTrue(MPP_ENABLED_CHECKER.supportsMpp(input));
+
+        ec2.getParamManager().getProps().put(ENABLE_MPP, "false");
+
+        assertTrue(!MPP_ENABLED_CHECKER.supportsMpp(input));
+    }
+
+    @Test
+    public void testTransaction() {
+        PlannerContext plannerContext = new PlannerContext();
+        ExecutionContext ec1 = new ExecutionContext();
+        ec1.setAutoCommit(false);
+        plannerContext.setExecutionContext(ec1);
+
+        ExecutionContext ec2 = new ExecutionContext();
+        ec2.setAutoCommit(true);
+
+        MppPlanCheckerInput input = new MppPlanCheckerInput(null, plannerContext, ec2);
+
+        assertTrue(TRANSACTION_CHECKER.supportsMpp(input));
+
+        ec2.setAutoCommit(false);
+
+        assertTrue(!TRANSACTION_CHECKER.supportsMpp(input));
+    }
+
+    @Test
+    public void testColumnarTransaction() {
+        PlannerContext plannerContext = new PlannerContext();
+        ExecutionContext ec1 = new ExecutionContext();
+        ec1.setAutoCommit(false);
+        plannerContext.setExecutionContext(ec1);
+
+        ExecutionContext ec2 = new ExecutionContext();
+        ec2.setAutoCommit(true);
+
+        MppPlanCheckerInput input = new MppPlanCheckerInput(null, plannerContext, ec2);
+
+        assertTrue(COLUMNAR_TRANSACTION_CHECKER.supportsMpp(input));
+
+        ec2.setAutoCommit(false);
+
+        assertTrue(!COLUMNAR_TRANSACTION_CHECKER.supportsMpp(input));
+    }
+
+    @Test
+    public void testUpdateChecker() {
+        PlannerContext plannerContext = new PlannerContext();
+        ExecutionContext ec1 = new ExecutionContext();
+        ec1.setSqlType(SELECT_FOR_UPDATE);
+        plannerContext.setExecutionContext(ec1);
+
+        ExecutionContext ec2 = new ExecutionContext();
+        ec2.setSqlType(SELECT_FOR_UPDATE);
+
+        MppPlanCheckerInput input = new MppPlanCheckerInput(null, plannerContext, ec2);
+
+        assertTrue(!UPDATE_CHECKER.supportsMpp(input));
+
+        ec2.setSqlType(SELECT);
+
+        assertTrue(UPDATE_CHECKER.supportsMpp(input));
+    }
+
+    @Test
+    public void testInternalSystemSqlChecker() {
+        PlannerContext plannerContext = new PlannerContext();
+        ExecutionContext ec1 = new ExecutionContext();
+        ec1.setInternalSystemSql(true);
+        plannerContext.setExecutionContext(ec1);
+
+        ExecutionContext ec2 = new ExecutionContext();
+        ec2.setInternalSystemSql(true);
+
+        MppPlanCheckerInput input = new MppPlanCheckerInput(null, plannerContext, ec2);
+
+        assertTrue(!INTERNAL_SYSTEM_SQL_CHECKER.supportsMpp(input));
+
+        ec2.setInternalSystemSql(false);
+
+        assertTrue(INTERNAL_SYSTEM_SQL_CHECKER.supportsMpp(input));
+    }
+
+    @Test
+    public void testExplainExecuteChecker() {
+        PlannerContext plannerContext = new PlannerContext();
+        ExecutionContext ec1 = new ExecutionContext();
+        ec1.setExplain(new ExplainResult());
+        ec1.getExplain().explainMode = ExplainResult.ExplainMode.EXECUTE;
+        plannerContext.setExecutionContext(ec1);
+
+        ExecutionContext ec2 = new ExecutionContext();
+        ec2.setExplain(new ExplainResult());
+        ec2.getExplain().explainMode = ExplainResult.ExplainMode.OPTIMIZER;
+
+        MppPlanCheckerInput input = new MppPlanCheckerInput(null, plannerContext, ec2);
+
+        assertTrue(EXPLAIN_EXECUTE_CHECKER.supportsMpp(input));
+
+        ec2.getExplain().explainMode = ExplainResult.ExplainMode.EXECUTE;
+
+        assertTrue(!EXPLAIN_EXECUTE_CHECKER.supportsMpp(input));
+    }
+
+    @Test
+    public void testExplainStatisticsChecker() {
+        PlannerContext plannerContext = new PlannerContext();
+        ExecutionContext ec1 = new ExecutionContext();
+        ec1.setExplain(new ExplainResult());
+        ec1.getExplain().explainMode = ExplainResult.ExplainMode.STATISTICS;
+        plannerContext.setExecutionContext(ec1);
+
+        ExecutionContext ec2 = new ExecutionContext();
+        ec2.setExplain(new ExplainResult());
+        ec2.getExplain().explainMode = ExplainResult.ExplainMode.OPTIMIZER;
+
+        MppPlanCheckerInput input = new MppPlanCheckerInput(null, plannerContext, ec2);
+
+        assertTrue(EXPLAIN_STATISTICS_CHECKER.supportsMpp(input));
+
+        ec2.getExplain().explainMode = ExplainResult.ExplainMode.STATISTICS;
+
+        assertTrue(!EXPLAIN_STATISTICS_CHECKER.supportsMpp(input));
+    }
+
+    @Test
+    public void testEnableColumnarChecker() {
+        PlannerContext plannerContext = new PlannerContext();
+        ExecutionContext ec1 = new ExecutionContext();
+        ec1.getParamManager().getProps().put(ENABLE_COLUMNAR_OPTIMIZER, "false");
+
+        plannerContext.setExecutionContext(ec1);
+
+        ExecutionContext ec2 = new ExecutionContext();
+        ec2.getParamManager().getProps().put(ENABLE_COLUMNAR_OPTIMIZER, "true");
+
+        MppPlanCheckerInput input = new MppPlanCheckerInput(null, plannerContext, ec2);
+
+        assertTrue(ENABLE_COLUMNAR_CHECKER.supportsMpp(input));
+
+        ec2.getParamManager().getProps().put(ENABLE_COLUMNAR_OPTIMIZER, "false");
+
+        assertTrue(!ENABLE_COLUMNAR_CHECKER.supportsMpp(input));
+
+        ec2.getParamManager().getProps().put(ENABLE_COLUMNAR_OPTIMIZER, "false");
+
+        boolean orig = DynamicConfig.getInstance().existColumnarNodes();
+        try {
+            ec2.getParamManager().getProps().put(ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR, "true");
+            DynamicConfig.getInstance().existColumnarNodes(true);
+            assertTrue(ENABLE_COLUMNAR_CHECKER.supportsMpp(input));
+            ec2.getParamManager().getProps().put(ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR, "false");
+            assertTrue(!ENABLE_COLUMNAR_CHECKER.supportsMpp(input));
+            ec2.getParamManager().getProps().put(ENABLE_COLUMNAR_OPTIMIZER_WITH_COLUMNAR, "true");
+            DynamicConfig.getInstance().existColumnarNodes(false);
+            assertTrue(!ENABLE_COLUMNAR_CHECKER.supportsMpp(input));
+        } finally {
+            DynamicConfig.getInstance().existColumnarNodes(orig);
+        }
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/OptimizerUtilsTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/OptimizerUtilsTest.java
index afd9dfb27..021c084dc 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/OptimizerUtilsTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/OptimizerUtilsTest.java
@@ -9,6 +9,7 @@
 import com.alibaba.polardbx.common.properties.DynamicConfig;
 import com.alibaba.polardbx.common.utils.Assert;
 import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.optimizer.PlannerContext;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.rel.LogicalView;
 import com.alibaba.polardbx.optimizer.core.rel.PushDownOpt;
@@ -17,6 +18,8 @@
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.jetbrains.annotations.NotNull;
 import org.junit.Test;
 import org.mockito.MockedStatic;
@@ -31,6 +34,12 @@
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
+import static com.alibaba.polardbx.common.utils.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+
 /**
  * @author fangwu
  */
@@ -63,7 +72,7 @@ public void testBuildInExprKey() {
     @Test
     public void testFindAllRawStrings() {
         // params has raw string and which size > IN_PRUNE_SIZE
-        ExecutionContext executionContext = Mockito.mock(ExecutionContext.class);
+        ExecutionContext executionContext = mock(ExecutionContext.class);
         Parameters parameters = new Parameters();
         Map params = Maps.newHashMap();
         params.put(1,
@@ -75,7 +84,7 @@ public void testFindAllRawStrings() {
 
         parameters.setParams(params);
 
-        Mockito.when(executionContext.getParams()).thenReturn(parameters);
+        when(executionContext.getParams()).thenReturn(parameters);
         Assert.assertTrue(OptimizerUtils.findAllRawStrings(ImmutableSet.of(1, 2), executionContext).length == 2);
         Assert.assertTrue(OptimizerUtils.findAllRawStrings(ImmutableSet.of(2), executionContext).length == 1);
     }
@@ -111,47 +120,102 @@ public void testMergeRawStringParameters() {
     }
 
     @Test
-    public void testPruning() throws Exception {
+    public void testPruning() {
         // if 'DynamicConfig.getInstance().isEnablePruningIn' return false, then pruneRawStringMap is null
-        MockedStatic optimizerUtilsMockedStatic =
-            Mockito.mockStatic(OptimizerUtils.class, Mockito.CALLS_REAL_METHODS);
-        LogicalView testLogicalView = Mockito.mock(LogicalView.class);
-        PushDownOpt pushDownOpt = Mockito.mock(PushDownOpt.class);
-        Mockito.when(testLogicalView.getPushDownOpt()).thenReturn(pushDownOpt);
-        ExecutionContext executionContext = new ExecutionContext();
-        DynamicConfig.getInstance().loadValue(null, ConnectionProperties.ENABLE_PRUNING_IN, "false");
-        Map>, Parameters> rs =
-            OptimizerUtils.pruningInValue(testLogicalView, executionContext);
-        Assert.assertTrue(rs == null);
-
-        // 'is need prune' return true and findAllRawStrings return no raw string
-        DynamicConfig.getInstance().loadValue(null, ConnectionProperties.ENABLE_PRUNING_IN, "true");
-        //OptimizerUtils.findAllRawStrings(ImmutableSet.of(1), executionContext)
-        optimizerUtilsMockedStatic.when(() -> OptimizerUtils.findAllRawStrings(ImmutableSet.of(1), executionContext))
-            .thenReturn(new Pair[0]);
-
-        rs = OptimizerUtils.pruningInValue(testLogicalView, executionContext);
-        Assert.assertTrue(rs == null);
-
-        // 'is need prune' return true and findAllRawStrings return no raw string
-        Parameters parameters = new Parameters();
-        Map params = Maps.newHashMap();
-        params.put(1,
-            new ParameterContext(ParameterMethod.setObject1, new Object[] {
-                1, new RawString(IntStream.range(0, 10000).boxed().collect(
-                Collectors.toList()))}));
-        parameters.setParams(params);
-        executionContext.setParams(parameters);
-        optimizerUtilsMockedStatic.when(() -> OptimizerUtils.findAllRawStrings(ImmutableSet.of(1), executionContext))
-            .thenCallRealMethod();
+        try (MockedStatic optimizerUtilsMockedStatic =
+            Mockito.mockStatic(OptimizerUtils.class, Mockito.CALLS_REAL_METHODS)) {
+            LogicalView testLogicalView = mock(LogicalView.class);
+            PushDownOpt pushDownOpt = mock(PushDownOpt.class);
+            when(testLogicalView.getPushDownOpt()).thenReturn(pushDownOpt);
+            ExecutionContext executionContext = new ExecutionContext();
+            DynamicConfig.getInstance().loadValue(null, ConnectionProperties.ENABLE_PRUNING_IN, "false");
+            Map>, Parameters> rs =
+                OptimizerUtils.pruningInValue(testLogicalView, executionContext);
+            Assert.assertTrue(rs == null);
+
+            // 'is need prune' return true and findAllRawStrings return no raw string
+            DynamicConfig.getInstance().loadValue(null, ConnectionProperties.ENABLE_PRUNING_IN, "true");
+            //OptimizerUtils.findAllRawStrings(ImmutableSet.of(1), executionContext)
+            optimizerUtilsMockedStatic.when(
+                    () -> OptimizerUtils.findAllRawStrings(ImmutableSet.of(1), executionContext))
+                .thenReturn(new Pair[0]);
+
+            rs = OptimizerUtils.pruningInValue(testLogicalView, executionContext);
+            Assert.assertTrue(rs == null);
+
+            // 'is need prune' return true and findAllRawStrings return no raw string
+            Parameters parameters = new Parameters();
+            Map params = Maps.newHashMap();
+            params.put(1,
+                new ParameterContext(ParameterMethod.setObject1, new Object[] {
+                    1, new RawString(IntStream.range(0, 10000).boxed().collect(
+                    Collectors.toList()))}));
+            parameters.setParams(params);
+            executionContext.setParams(parameters);
+            optimizerUtilsMockedStatic.when(
+                    () -> OptimizerUtils.findAllRawStrings(ImmutableSet.of(1), executionContext))
+                .thenCallRealMethod();
+
+            // mock sharding
+            when(pushDownOpt.getShardRelatedInTypeParamIndexes()).thenReturn(ImmutableSet.of(1));
+            Mockito.doAnswer(invocationOnMock -> buildRandomSharding()).when(testLogicalView)
+                .buildTargetTables(Mockito.any());
+            rs = OptimizerUtils.pruningInValue(testLogicalView, executionContext);
+
+            Assert.assertTrue(rs.size() == 25);
+        }
+    }
+
+    /**
+     * Tests the scenario where the provided {@code RelNode} has non-empty parameters.
+     * Verifies that the returned map of parameters is not null.
+     */
+    @Test
+    public void testGetParametersMapForOptimizerWithNonEmptyParameters() {
+        // Mock a RelNode with non-empty parameters
+        RelNode relNode = mock(RelNode.class);
+        PlannerContext plannerContext = mock(PlannerContext.class);
+
+        when(plannerContext.getParams()).thenReturn(new Parameters());
+        try (MockedStatic plannerContextMockedStatic = mockStatic(PlannerContext.class)) {
+            plannerContextMockedStatic.when(() -> PlannerContext.getPlannerContext(relNode)).thenReturn(plannerContext);
+
+            Map result = OptimizerUtils.getParametersMapForOptimizer(relNode);
+
+            assertNotNull(result);
+        }
+    }
+
+    /**
+     * Validates that the method correctly retrieves non-null parameters from a PlannerContext.
+     */
+    @Test
+    public void testGetParametersForOptimizerWithNonEmptyParametersInContext() {
+        // Mock a PlannerContext with non-empty parameters
+        PlannerContext plannerContext = mock(PlannerContext.class);
+        when(plannerContext.getParams()).thenReturn(new Parameters());
+
+        Parameters result = OptimizerUtils.getParametersForOptimizer(plannerContext);
+
+        assertNotNull(result);
+    }
+
+    /**
+     * Ensures that the method falls back to the thread-local parameters when PlannerContext's parameters are null.
+     * Also checks that the thread-local variable is indeed null after the call.
+     */
+    @Test
+    public void testGetParametersForOptimizerWithNullParametersInContext() {
+        // Mock a PlannerContext with null parameters
+        PlannerContext plannerContext = mock(PlannerContext.class);
+        when(plannerContext.getParams()).thenReturn(null);
 
-        // mock sharding
-        Mockito.when(pushDownOpt.getShardRelatedInTypeParamIndexes()).thenReturn(ImmutableSet.of(1));
-        Mockito.doAnswer(invocationOnMock -> buildRandomSharding()).when(testLogicalView)
-            .buildTargetTables(Mockito.any());
-        rs = OptimizerUtils.pruningInValue(testLogicalView, executionContext);
+        // Call the method under test
+        Parameters result = OptimizerUtils.getParametersForOptimizer(plannerContext);
 
-        Assert.assertTrue(rs.size() == 25);
+        // Assert that both the thread-local and the method result are null
+        assertNull(RelMetadataQuery.THREAD_PARAMETERS.get());
+        assertNull(result);
     }
 
     @Test
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/RelUtilsTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/RelUtilsTest.java
new file mode 100644
index 000000000..87b4e37da
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/RelUtilsTest.java
@@ -0,0 +1,38 @@
+package com.alibaba.polardbx.optimizer.utils;
+
+import org.apache.calcite.plan.RelOptUtil;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Aggregate;
+import org.apache.calcite.util.Util;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static com.alibaba.polardbx.common.utils.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+/**
+ * @author fangwu
+ */
+public class RelUtilsTest {
+
+    /**
+     * test no agg found
+     */
+    @Test
+    public void testContainsAggWithoutAgg() {
+        RelNode nonAggNode = Mockito.mock(RelNode.class);
+
+        assertFalse(RelOptUtil.containsAgg(nonAggNode));
+    }
+
+    /**
+     * test agg node found
+     */
+    @Test
+    public void testContainsAggWithAgg() throws Util.FoundOne {
+        Aggregate aggNode = Mockito.mock(Aggregate.class);
+
+        assertTrue(RelOptUtil.containsAgg(aggNode));
+    }
+
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/RexUtilsTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/RexUtilsTest.java
index 506907f6e..c38b9428b 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/RexUtilsTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/RexUtilsTest.java
@@ -1,14 +1,33 @@
 package com.alibaba.polardbx.optimizer.utils;
 
+import com.alibaba.polardbx.common.exception.TddlRuntimeException;
+import com.alibaba.polardbx.common.utils.version.InstanceVersion;
+import com.alibaba.polardbx.optimizer.config.table.ColumnMeta;
+import com.alibaba.polardbx.optimizer.config.table.TableMeta;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.rel.LogicalInsert;
 import com.clearspring.analytics.util.Lists;
+import io.airlift.slice.Slice;
+import org.apache.calcite.avatica.util.ByteString;
+import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
 import org.apache.calcite.sql.dialect.MysqlSqlDialect;
 import org.junit.Test;
+import org.mockito.MockedStatic;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.function.Function;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 /**
  * @author fangwu
@@ -30,4 +49,76 @@ public void testIndexHintSerialization() {
         assert rs.contains("IGNORE INDEX(IDXID)");
         assert rs.contains("USE INDEX(IDXID1, NAME1, NAME2)");
     }
+
+    @Test
+    public void testHandleDefaultExpr() {
+        try (MockedStatic staticRexUtils = mockStatic(RexUtils.class)) {
+            try (MockedStatic staticInstance = mockStatic(InstanceVersion.class)) {
+                TableMeta tableMeta = mock(TableMeta.class);
+                LogicalInsert insert = mock(LogicalInsert.class);
+                ExecutionContext ec = mock(ExecutionContext.class);
+                ColumnMeta columnMeta = mock(ColumnMeta.class);
+                RexNode rexNode = mock(RexNode.class);
+                Slice slice = mock(Slice.class);
+                Function evalFunc = mock(Function.class);
+
+                staticInstance.when(() -> InstanceVersion.isMYSQL80()).thenReturn(true);
+                when(tableMeta.hasDefaultExprColumn()).thenReturn(true);
+                when(insert.getDefaultExprColRexNodes()).thenReturn(Collections.singletonList(rexNode));
+                when(insert.getDefaultExprColMetas()).thenReturn(Collections.singletonList(columnMeta));
+
+                staticRexUtils.when(() -> RexUtils.getEvalFunc(any(ExecutionContext.class))).thenReturn(evalFunc);
+                when(evalFunc.apply(rexNode)).thenReturn(slice);
+
+                when(RexUtils.isBinaryReturnType(any(RexNode.class))).thenReturn(true);
+                when(slice.getBytes()).thenReturn(new byte[] {1, 2, 3});
+
+                staticRexUtils.when(() -> RexUtils.handleDefaultExpr(any(TableMeta.class), any(LogicalInsert.class),
+                    any(ExecutionContext.class))).thenCallRealMethod();
+                RexUtils.handleDefaultExpr(tableMeta, insert, ec);
+                verify(evalFunc).apply(rexNode);
+                verify(slice).getBytes();
+
+                ByteString str = mock(ByteString.class);
+                when(str.getBytes()).thenReturn(new byte[] {1, 2, 3});
+                when(evalFunc.apply(rexNode)).thenReturn(str);
+                RexUtils.handleDefaultExpr(tableMeta, insert, ec);
+                verify(str).getBytes();
+            }
+        }
+    }
+
+    @Test(expected = TddlRuntimeException.class)
+    public void testHandleDefaultExprThrowErr() {
+        try (MockedStatic staticRexUtils = mockStatic(RexUtils.class)) {
+            try (MockedStatic staticInstance = mockStatic(InstanceVersion.class)) {
+                TableMeta tableMeta = mock(TableMeta.class);
+                LogicalInsert insert = mock(LogicalInsert.class);
+                ExecutionContext ec = mock(ExecutionContext.class);
+                ColumnMeta columnMeta = mock(ColumnMeta.class);
+                RexCall rexCall = mock(RexCall.class);
+                RexNode rexNode = mock(RexNode.class);
+                Function evalFunc = mock(Function.class);
+                List operands = mock(List.class);
+
+                staticInstance.when(() -> InstanceVersion.isMYSQL80()).thenReturn(true);
+                when(tableMeta.hasDefaultExprColumn()).thenReturn(true);
+                when(insert.getDefaultExprColRexNodes()).thenReturn(Collections.singletonList(rexCall));
+                when(insert.getDefaultExprColMetas()).thenReturn(Collections.singletonList(columnMeta));
+                when(rexCall.getOperands()).thenReturn(operands);
+                when(operands.get(0)).thenReturn(rexNode);
+                when(rexNode.toString()).thenReturn("UUID_TO_BIN");
+
+                staticRexUtils.when(() -> RexUtils.getEvalFunc(any(ExecutionContext.class))).thenReturn(evalFunc);
+                when(evalFunc.apply(rexCall)).thenThrow(UnsupportedOperationException.class);
+
+                when(RexUtils.isBinaryReturnType(any(RexNode.class))).thenReturn(true);
+
+                staticRexUtils.when(() -> RexUtils.handleDefaultExpr(any(TableMeta.class), any(LogicalInsert.class),
+                    any(ExecutionContext.class))).thenCallRealMethod();
+                RexUtils.handleDefaultExpr(tableMeta, insert, ec);
+            }
+        }
+    }
+
 }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/TimeZoneUtilsTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/TimeZoneUtilsTest.java
new file mode 100644
index 000000000..553b605e1
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/utils/TimeZoneUtilsTest.java
@@ -0,0 +1,56 @@
+package com.alibaba.polardbx.optimizer.utils;
+
+import com.alibaba.polardbx.common.utils.timezone.InternalTimeZone;
+import com.alibaba.polardbx.common.utils.timezone.TimeZoneUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TimeZoneUtilsTest {
+
+    @Test
+    public void testNamedTimeZone() throws Exception {
+        try {
+
+            String tzSh = "Asia/Shanghai";
+            InternalTimeZone timeZoneSh = TimeZoneUtils.convertFromMySqlTZ(tzSh);
+            String zoneIdSh = timeZoneSh.getTimeZone().getID();
+            int zoneIdShOffSet = timeZoneSh.getTimeZone().getRawOffset();
+            System.out.println(zoneIdSh);
+            System.out.println(zoneIdShOffSet);
+            Assert.assertTrue(zoneIdSh.equalsIgnoreCase(tzSh));
+            Assert.assertTrue(zoneIdShOffSet == 28800000);
+
+            String tz0800 = "+08:00";
+            InternalTimeZone timeZone0800 = TimeZoneUtils.convertFromMySqlTZ(tz0800);
+            String zoneId0800 = timeZone0800.getTimeZone().getID();
+            int zoneId0800OffSet = timeZone0800.getTimeZone().getRawOffset();
+            System.out.println(zoneId0800);
+            System.out.println(zoneId0800OffSet);
+            Assert.assertTrue(zoneId0800.equalsIgnoreCase("GMT+08:00"));
+            Assert.assertTrue(zoneId0800OffSet == 28800000);
+
+            String tzTy = "Asia/Tokyo";
+            InternalTimeZone timeZoneTy = TimeZoneUtils.convertFromMySqlTZ(tzTy);
+            String zoneIdTy = timeZoneTy.getTimeZone().getID();
+            int zoneIdTyOffSet = timeZoneTy.getTimeZone().getRawOffset();
+            System.out.println(zoneIdTy);
+            System.out.println(zoneIdTyOffSet);
+            Assert.assertTrue(zoneIdTy.equalsIgnoreCase(tzTy));
+            Assert.assertTrue(zoneIdTyOffSet == 32400000);
+
+            String tz0900 = "+09:00";
+            InternalTimeZone timeZone0900 = TimeZoneUtils.convertFromMySqlTZ(tz0900);
+            String zoneId0900 = timeZone0900.getTimeZone().getID();
+            int zoneId0900OffSet = timeZone0900.getTimeZone().getRawOffset();
+            System.out.println(zoneId0900);
+            System.out.println(zoneId0900OffSet);
+            Assert.assertTrue(zoneId0900.equalsIgnoreCase("GMT+09:00"));
+            Assert.assertTrue(zoneId0900OffSet == 32400000);
+
+        } catch (Throwable ex) {
+            ex.printStackTrace();
+            Assert.fail("failed");
+        }
+
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/view/InformationSchemaMetricTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/view/InformationSchemaMetricTest.java
new file mode 100644
index 000000000..108c45134
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/view/InformationSchemaMetricTest.java
@@ -0,0 +1,35 @@
+package com.alibaba.polardbx.optimizer.view;
+
+import com.alibaba.polardbx.common.utils.Assert;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.junit.Test;
+
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author fangwu
+ */
+public class InformationSchemaMetricTest {
+
+    @Test
+    public void testRowType(){
+        RelOptCluster cluster = mock(RelOptCluster.class);
+        RelDataTypeFactory factory = mock(RelDataTypeFactory.class);
+        RelDataType varcharMock = mock(RelDataType.class);
+        RelDataType resultMock = mock(RelDataType.class);
+        when(factory.createSqlType(SqlTypeName.VARCHAR)).thenReturn(varcharMock);
+        when(factory.createStructType(anyList())).thenReturn(resultMock);
+        when(cluster.getTypeFactory()).thenReturn(factory);
+
+        InformationSchemaMetric metric = new InformationSchemaMetric(cluster, mock(RelTraitSet.class));
+        RelDataType relDataType = metric.deriveRowType();
+
+        Assert.assertTrue(relDataType == resultMock);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/view/MySqlSchemaViewManagerTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/view/MySqlSchemaViewManagerTest.java
new file mode 100644
index 000000000..bfef89576
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/optimizer/view/MySqlSchemaViewManagerTest.java
@@ -0,0 +1,31 @@
+package com.alibaba.polardbx.optimizer.view;
+
+import com.alibaba.polardbx.common.utils.Assert;
+import com.alibaba.polardbx.config.ConfigDataMode;
+import org.junit.Test;
+import org.mockito.MockedStatic;
+
+import static org.mockito.Mockito.mockStatic;
+
+public class MySqlSchemaViewManagerTest {
+
+    @Test
+    public void testViewMangerContainsProcsPriv() {
+        MysqlSchemaViewManager mysqlSchemaViewManager = MysqlSchemaViewManager.getInstance();
+        try (MockedStatic configDataModeMockedStatic = mockStatic(ConfigDataMode.class)) {
+            configDataModeMockedStatic.when(() -> ConfigDataMode.isPolarDbX()).thenReturn(true);
+            mysqlSchemaViewManager.doInit();
+            Assert.assertTrue(mysqlSchemaViewManager.select("procs_priv") != null);
+        }
+    }
+
+    @Test
+    public void testUserViewContainsPasswordColumn() {
+        MysqlSchemaViewManager mysqlSchemaViewManager = MysqlSchemaViewManager.getInstance();
+        try (MockedStatic configDataModeMockedStatic = mockStatic(ConfigDataMode.class)) {
+            configDataModeMockedStatic.when(() -> ConfigDataMode.isPolarDbX()).thenReturn(true);
+            mysqlSchemaViewManager.doInit();
+            Assert.assertTrue(mysqlSchemaViewManager.select("user").getColumnList().contains("password"));
+        }
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/parser/ReplicaCheckerParserTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/parser/ReplicaCheckerParserTest.java
new file mode 100644
index 000000000..0bc448b1f
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/parser/ReplicaCheckerParserTest.java
@@ -0,0 +1,143 @@
+package com.alibaba.polardbx.parser;
+
+import com.alibaba.polardbx.druid.DbType;
+import com.alibaba.polardbx.druid.sql.ast.SQLStatement;
+import com.alibaba.polardbx.druid.sql.parser.SQLParserFeature;
+import com.alibaba.polardbx.druid.sql.parser.SQLParserUtils;
+import com.alibaba.polardbx.druid.sql.parser.SQLStatementParser;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * @author yudong
+ * @since 2024/6/27 10:45
+ **/
+public class ReplicaCheckerParserTest {
+    private final SQLParserFeature[] FEATURES = {
+        SQLParserFeature.EnableSQLBinaryOpExprGroup,
+        SQLParserFeature.UseInsertColumnsCache, SQLParserFeature.OptimizedForParameterized,
+        SQLParserFeature.TDDLHint, SQLParserFeature.EnableCurrentUserExpr, SQLParserFeature.DRDSAsyncDDL,
+        SQLParserFeature.DRDSBaseline, SQLParserFeature.DrdsMisc, SQLParserFeature.DrdsGSI, SQLParserFeature.DrdsCCL
+    };
+
+    @Test
+    public void testStartReplicaCheck() {
+        String sql = "check replica table `testdb`.`testtb` channel='test'";
+        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        List statementList = parser.parseStatementList();
+        SQLStatement statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` CHANNEL='test'", statement.toString());
+
+        sql = "check replica table `testdb` channel='test'";
+        parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        statementList = parser.parseStatementList();
+        statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb` CHANNEL='test'", statement.toString());
+
+        sql = "check replica table `testdb`.`testtb` channel='test' mode=direct";
+        parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        statementList = parser.parseStatementList();
+        statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` CHANNEL='test' MODE=direct", statement.toString());
+
+        sql = "check replica table `testdb`.`testtb` mode=direct";
+        parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        statementList = parser.parseStatementList();
+        statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` MODE=direct", statement.toString());
+    }
+
+    @Test
+    public void testPauseReplicaCheck() {
+        String sql = "check replica table `testdb`.`testtb` pause";
+        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        List statementList = parser.parseStatementList();
+        SQLStatement statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` PAUSE", statement.toString());
+
+        sql = "check replica table `testdb` pause";
+        parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        statementList = parser.parseStatementList();
+        statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb` PAUSE", statement.toString());
+    }
+
+    @Test
+    public void testContinueReplicaCheck() {
+        String sql = "check replica table `testdb`.`testtb` continue";
+        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        List statementList = parser.parseStatementList();
+        SQLStatement statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` CONTINUE", statement.toString());
+
+        sql = "check replica table `testdb` continue";
+        parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        statementList = parser.parseStatementList();
+        statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb` CONTINUE", statement.toString());
+    }
+
+    @Test
+    public void testCancelReplicaCheck() {
+        String sql = "check replica table `testdb`.`testtb` cancel";
+        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        List statementList = parser.parseStatementList();
+        SQLStatement statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` CANCEL", statement.toString());
+
+        sql = "check replica table `testdb` cancel";
+        parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        statementList = parser.parseStatementList();
+        statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb` CANCEL", statement.toString());
+    }
+
+    @Test
+    public void testResetReplicaCheck() {
+        String sql = "check replica table `testdb`.`testtb` reset";
+        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        List statementList = parser.parseStatementList();
+        SQLStatement statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` RESET", statement.toString());
+
+        sql = "check replica table `testdb` reset";
+        parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        statementList = parser.parseStatementList();
+        statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb` RESET", statement.toString());
+
+    }
+
+    @Test
+    public void testShowReplicaCheckProgress() {
+        String sql = "check replica table `testdb`.`testtb` show progress";
+        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        List statementList = parser.parseStatementList();
+        SQLStatement statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` SHOW PROGRESS", statement.toString());
+
+        sql = "check replica table `testdb` show progress";
+        parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        statementList = parser.parseStatementList();
+        statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb` SHOW PROGRESS", statement.toString());
+    }
+
+    @Test
+    public void testShowReplicaCheckDiff() {
+        String sql = "check replica table `testdb`.`testtb` show diff";
+        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        List statementList = parser.parseStatementList();
+        SQLStatement statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` SHOW DIFF", statement.toString());
+
+        sql = "check replica table `testdb` show diff";
+        parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES);
+        statementList = parser.parseStatementList();
+        statement = statementList.get(0);
+        Assert.assertEquals("CHECK REPLICA TABLE `testdb` SHOW DIFF", statement.toString());
+    }
+
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/parser/ReplicaParserTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/parser/ReplicaParserTest.java
index 168ceeec2..076d737ab 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/parser/ReplicaParserTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/parser/ReplicaParserTest.java
@@ -39,96 +39,137 @@ public void testVisitReplicaStatementWithoutCdc() {
             ExecutionContext ec = new ExecutionContext();
             visitor = new FastSqlToCalciteNodeVisitor(context, ec);
 
+            boolean runIntoException = false;
+
             try {
                 visitor.visit(Mockito.mock(MySqlChangeMasterStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(MySqlChangeReplicationFilterStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(MySqlStartSlaveStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(MySqlStopSlaveStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(MySqlResetSlaveStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(MySqlShowSlaveStatusStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLResetReplicaCheckTableStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLContinueReplicaCheckTableStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLCancelReplicaCheckTableStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLPauseReplicaCheckTableStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLStartReplicaCheckTableStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLShowReplicaCheckProgressStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLShowReplicaCheckDiffStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("replica is not support yet"));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
         }
     }
 
@@ -146,75 +187,107 @@ public void testVisitReplicaStatementWithNonGodUser() {
             ContextParameters context = new ContextParameters(false);
             visitor = new FastSqlToCalciteNodeVisitor(context, mockEc);
 
+            boolean runIntoException = false;
+
             try {
                 visitor.visit(Mockito.mock(MySqlChangeMasterStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(MySqlChangeReplicationFilterStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(MySqlStartSlaveStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(MySqlStopSlaveStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(MySqlResetSlaveStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLResetReplicaCheckTableStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLContinueReplicaCheckTableStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLCancelReplicaCheckTableStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLPauseReplicaCheckTableStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
 
             try {
                 visitor.visit(Mockito.mock(SQLStartReplicaCheckTableStatement.class));
             } catch (Exception e) {
                 Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
+                runIntoException = true;
             }
+            Assert.assertTrue(runIntoException);
+            runIntoException = false;
         }
     }
 
@@ -253,73 +326,65 @@ public void testVisitReplicaStatementWithGodUser() {
             ContextParameters context = new ContextParameters(false);
             visitor = new FastSqlToCalciteNodeVisitor(context, mockEc);
 
+            boolean runIntoException = false;
+
             try {
                 visitor.visit(Mockito.mock(MySqlChangeMasterStatement.class));
             } catch (Exception e) {
-                Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(!e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
             }
 
             try {
                 visitor.visit(Mockito.mock(MySqlChangeReplicationFilterStatement.class));
             } catch (Exception e) {
-                Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(!e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
             }
 
             try {
                 visitor.visit(Mockito.mock(MySqlStartSlaveStatement.class));
             } catch (Exception e) {
-                Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(!e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
             }
 
             try {
                 visitor.visit(Mockito.mock(MySqlStopSlaveStatement.class));
             } catch (Exception e) {
-                Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(!e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
             }
 
             try {
                 visitor.visit(Mockito.mock(MySqlResetSlaveStatement.class));
             } catch (Exception e) {
-                Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(!e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
             }
 
             try {
                 visitor.visit(Mockito.mock(SQLResetReplicaCheckTableStatement.class));
             } catch (Exception e) {
-                Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(!e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
             }
 
             try {
                 visitor.visit(Mockito.mock(SQLContinueReplicaCheckTableStatement.class));
             } catch (Exception e) {
-                Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(!e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
             }
 
             try {
                 visitor.visit(Mockito.mock(SQLCancelReplicaCheckTableStatement.class));
             } catch (Exception e) {
-                Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(!e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
             }
 
             try {
                 visitor.visit(Mockito.mock(SQLPauseReplicaCheckTableStatement.class));
             } catch (Exception e) {
-                Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(!e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
             }
 
             try {
                 visitor.visit(Mockito.mock(SQLStartReplicaCheckTableStatement.class));
             } catch (Exception e) {
-                Assert.assertTrue(e instanceof TddlRuntimeException);
                 Assert.assertTrue(!e.getMessage().contains("User testUser@'testHost' does not have 'GOD' privilege. "));
             }
 
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/cbo/RulePruneTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/cbo/RulePruneTest.java
index ad5acb85a..240b92eda 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/cbo/RulePruneTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/cbo/RulePruneTest.java
@@ -94,8 +94,6 @@ protected ExecutionContext getExecutionContext(SqlNode ast) {
                 partialAggBucketThreshold);
         }
 
-        // enable cbo rule counter
-        executionContext.setEnableRuleCounter(true);
         // disable push join limit
         executionContext.getExtraCmds().put(ConnectionProperties.CBO_RESTRICT_PUSH_JOIN_LIMIT, -1);
         return executionContext;
@@ -111,11 +109,12 @@ protected String getPlan(String testSql) {
 
         ExecutionContext executionContext = getExecutionContext(ast);
         PlannerContext plannerContext = PlannerContext.fromExecutionContext(executionContext);
+        plannerContext.setEnableRuleCounter(true);
         plannerContext.setSchemaName(appName);
 
         // reset cluster for every statement
         Planner.getInstance().getPlan(ast, plannerContext);
-        long prevCount = executionContext.getRuleCount();
+        long prevCount = plannerContext.getRuleCount();
 
         ast = new FastsqlParser().parse(testSql).get(0);
         executionContext = getExecutionContext(ast);
@@ -126,7 +125,7 @@ protected String getPlan(String testSql) {
         executionContext.getExtraCmds().put(ConnectionProperties.CBO_RESTRICT_PUSH_JOIN_LIMIT, 0);
         executionContext.getExtraCmds().put(ConnectionProperties.CBO_RESTRICT_PUSH_JOIN_COUNT, 0);
         Planner.getInstance().getPlan(ast, plannerContext);
-        long curCount = executionContext.getRuleCount();
+        long curCount = plannerContext.getRuleCount();
         assertTrue("previous is " + prevCount + " now is " + curCount, prevCount <= 0 || curCount < prevCount);
 
         return null;
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.java
similarity index 86%
rename from polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.java
rename to polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.java
index ac2f3ac28..507f9fa1e 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.java
@@ -1,7 +1,6 @@
-package com.alibaba.polardbx.planner.oss;
+package com.alibaba.polardbx.planner.columnar;
 
 import com.alibaba.polardbx.planner.common.ParameterizedTestCommon;
-import com.alibaba.polardbx.planner.common.PlanTestCommon;
 import org.junit.runners.Parameterized;
 
 import java.util.List;
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/columnar/ColumnarIndexSelectTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/columnar/ColumnarIndexSelectTest.java
new file mode 100644
index 000000000..7770485c1
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/columnar/ColumnarIndexSelectTest.java
@@ -0,0 +1,24 @@
+package com.alibaba.polardbx.planner.columnar;
+
+import com.alibaba.polardbx.planner.common.PlanTestCommon;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+public class ColumnarIndexSelectTest extends PlanTestCommon {
+
+    public ColumnarIndexSelectTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Override
+    protected void initBasePlannerTestEnv() {
+        this.useNewPartDb = true;
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(ColumnarIndexSelectTest.class);
+    }
+
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/columnar/ColumnarSortTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/columnar/ColumnarSortTest.java
new file mode 100644
index 000000000..f768ca98b
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/columnar/ColumnarSortTest.java
@@ -0,0 +1,18 @@
+package com.alibaba.polardbx.planner.columnar;
+
+import com.alibaba.polardbx.planner.common.ParameterizedTestCommon;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+public class ColumnarSortTest extends ParameterizedTestCommon {
+    public ColumnarSortTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+        //setExplainCost(true);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(ColumnarSortTest.class);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/AdvisorTestCommon.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/AdvisorTestCommon.java
index 201066ea8..905740af6 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/AdvisorTestCommon.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/AdvisorTestCommon.java
@@ -64,6 +64,8 @@ protected String getPlan(String testSql) {
             executionContext.getGroupHint());
 
         executionContext.setParams(new Parameters());
+        executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_AUTO_FORCE_INDEX, enableAutoForceIndex);
+        executionContext.getExtraCmds().putAll(configMaps);
         executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_RANDOM_PHY_TABLE_NAME, false);
         executionContext.getExtraCmds().put(ConnectionProperties.PARALLELISM, enableParallelQuery ? -1 : 0);
         executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_JOIN_CLUSTERING, enableJoinClustering);
@@ -94,7 +96,7 @@ protected String getPlan(String testSql) {
         ExecutionPlan executionPlan = Planner.getInstance().getPlan(ast, plannerContext);
         executionPlan = PostPlanner.getInstance().optimize(executionPlan, executionContext);
 
-        IndexAdvisor indexAdvisor = new IndexAdvisor(executionPlan, executionContext);
+        IndexAdvisor indexAdvisor = new IndexAdvisor(executionPlan, plannerContext.getExecutionContext());
         AdviceResult adviceResult = indexAdvisor.advise(adviseType);
 
         RelNode advisedPlan = adviceResult.getAfterPlan();
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/AdvisorUserCaseTestCommon.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/AdvisorUserCaseTestCommon.java
index 71bc82e15..1dc862aa9 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/AdvisorUserCaseTestCommon.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/AdvisorUserCaseTestCommon.java
@@ -42,6 +42,7 @@ protected String getPlan(String testSql) {
             executionContext.getGroupHint());
 
         executionContext.setParams(new Parameters());
+        executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_AUTO_FORCE_INDEX, enableAutoForceIndex);
         executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_RANDOM_PHY_TABLE_NAME, false);
         executionContext.getExtraCmds().put(ConnectionProperties.PARALLELISM, enableParallelQuery ? -1 : 0);
         executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_JOIN_CLUSTERING, enableJoinClustering);
@@ -72,7 +73,7 @@ protected String getPlan(String testSql) {
         ExecutionPlan executionPlan = Planner.getInstance().getPlan(ast, plannerContext);
         executionPlan = PostPlanner.getInstance().optimize(executionPlan, executionContext);
 
-        IndexAdvisor indexAdvisor = new IndexAdvisor(executionPlan, executionContext);
+        IndexAdvisor indexAdvisor = new IndexAdvisor(executionPlan, plannerContext.getExecutionContext());
 
         AdviceResult bestResult = null;
         IndexAdvisor.AdviseType[] types = {
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/BasePlannerTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/BasePlannerTest.java
index df6daba96..080dc1cb6 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/BasePlannerTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/BasePlannerTest.java
@@ -40,15 +40,27 @@
 import com.alibaba.polardbx.common.jdbc.Parameters;
 import com.alibaba.polardbx.common.model.Group;
 import com.alibaba.polardbx.common.model.Matrix;
+import com.alibaba.polardbx.common.properties.ConnectionParams;
+import com.alibaba.polardbx.common.properties.ConnectionProperties;
+import com.alibaba.polardbx.common.properties.ParamManager;
 import com.alibaba.polardbx.common.utils.CaseInsensitive;
 import com.alibaba.polardbx.common.utils.GeneralUtil;
 import com.alibaba.polardbx.common.utils.TStringUtil;
 import com.alibaba.polardbx.config.ConfigDataMode;
+import com.alibaba.polardbx.druid.sql.SQLUtils;
 import com.alibaba.polardbx.druid.sql.ast.SqlType;
+import com.alibaba.polardbx.druid.sql.ast.statement.SQLCreateJavaFunctionStatement;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
+import com.alibaba.polardbx.druid.util.JdbcConstants;
 import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager;
 import com.alibaba.polardbx.gms.metadb.table.IndexStatus;
+import com.alibaba.polardbx.gms.metadb.table.JavaFunctionRecord;
 import com.alibaba.polardbx.gms.partition.TablePartitionRecord;
+import com.alibaba.polardbx.gms.tablegroup.TableGroupUtils;
+import com.alibaba.polardbx.gms.topology.DbGroupInfoManager;
+import com.alibaba.polardbx.gms.topology.DbGroupInfoRecord;
 import com.alibaba.polardbx.gms.topology.DbInfoManager;
+import com.alibaba.polardbx.gms.util.GroupInfoUtil;
 import com.alibaba.polardbx.optimizer.OptimizerContext;
 import com.alibaba.polardbx.optimizer.PlannerContext;
 import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager;
@@ -61,13 +73,17 @@
 import com.alibaba.polardbx.optimizer.config.table.SchemaManager;
 import com.alibaba.polardbx.optimizer.config.table.SimpleSchemaManager;
 import com.alibaba.polardbx.optimizer.config.table.TableMeta;
+import com.alibaba.polardbx.optimizer.config.table.statistic.MockStatisticDatasource;
 import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticManager;
+import com.alibaba.polardbx.optimizer.context.DdlContext;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.expression.JavaFunctionManager;
 import com.alibaba.polardbx.optimizer.core.planner.SqlConverter;
 import com.alibaba.polardbx.optimizer.core.rel.ToDrdsRelVisitor;
 import com.alibaba.polardbx.optimizer.core.rel.ddl.LogicalCreateTable;
 import com.alibaba.polardbx.optimizer.core.rel.ddl.data.CreateTablePreparedData;
 import com.alibaba.polardbx.optimizer.core.rel.ddl.data.gsi.CreateGlobalIndexPreparedData;
+import com.alibaba.polardbx.optimizer.locality.LocalityManager;
 import com.alibaba.polardbx.optimizer.parse.FastsqlParser;
 import com.alibaba.polardbx.optimizer.parse.FastsqlUtils;
 import com.alibaba.polardbx.optimizer.parse.TableMetaParser;
@@ -91,6 +107,12 @@
 import com.alibaba.polardbx.rule.TddlRule;
 import com.alibaba.polardbx.rule.VirtualTableRoot;
 import com.alibaba.polardbx.rule.model.TargetDB;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.DDL;
@@ -126,6 +148,7 @@
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.sql.SQLSyntaxErrorException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -159,6 +182,11 @@
  */
 public abstract class BasePlannerTest {
 
+    /**
+     * when set this flag,
+     */
+    private static final boolean fixFlag = true;
+
     private Map ddlMaps = new HashMap<>();
 
     private Map javaUdfMaps = new HashMap<>();
@@ -188,12 +216,12 @@ public abstract class BasePlannerTest {
 
     protected String appName = "optest";
     public static final long ROW_COUNT = 100;
-    private static final boolean fixFlag = false;
 
     private Map appNameOptiContextMaps = new HashMap();
     private String nodetree;
 
     protected boolean enableParallelQuery = false;
+    protected boolean enableAutoForceIndex = true;
     protected boolean enablePlanManagementTest = false;
     protected boolean enableJoinClustering = true;
     protected int partialAggBucketThreshold = -1;
@@ -210,6 +238,7 @@ public abstract class BasePlannerTest {
     protected boolean ignoreBaseTest = false;
     protected ExecutionContext ec = new ExecutionContext();
     protected boolean useNewPartDb = false;
+    protected boolean withSingleGroup = false;
     private int corMaxNum = 10;
     private String targetEnvFile = this.getClass().getSimpleName();
 
@@ -391,13 +420,18 @@ public synchronized void initAppNameConfig(String appName) {
             useNewPartDb = (boolean) configMaps.get(key);
             //configMaps.remove(key);
         }
+        key = appName.equals(getAppName()) ? "defaltxxAPPName.withSingleGroup" : appName + ".withSingleGroup";
+        if (configMaps.containsKey(key)) {
+            withSingleGroup = (boolean) configMaps.get(key);
+            //configMaps.remove(key);
+        }
         key = appName.equals(getAppName()) ? "defaltxxAPPName.dbNumber" : appName + ".dbNumber";
         int dbNumber = 4;
         if (configMaps.containsKey(key)) {
             dbNumber = ((Number) configMaps.get(key)).intValue();
             //configMaps.remove(key);
         }
-        context = initOptiContext(appName, dbNumber, useNewPartDb);
+        context = initOptiContext(appName, dbNumber, useNewPartDb, withSingleGroup);
         appNameOptiContextMaps.put(appName, context);
         LocalityManager.setMockMode(true);
         OptimizerHelper.clear();
@@ -441,7 +475,8 @@ public long submitSubDDL(String schemaName, DdlContext parentDdlContext, long pa
         });
     }
 
-    public static OptimizerContext initOptiContext(String appName, int dbNumber, boolean useNewPartDb) {
+    public static OptimizerContext initOptiContext(String appName, int dbNumber, boolean useNewPartDb,
+                                                   boolean withSingleGroup) {
         OptimizerContext context = new OptimizerContext(appName);
         PartitionInfoManager partInfoMgr = new PartitionInfoManager(appName, appName, true);
         TableGroupInfoManager tableGroupInfoManager = new TableGroupInfoManager(appName);
@@ -449,12 +484,35 @@ public static OptimizerContext initOptiContext(String appName, int dbNumber, boo
         TddlRule tddlRule = new TddlRule();
         tddlRule.setAppName(appName);
         tddlRule.setAllowEmptyRule(true);
-        tddlRule.setDefaultDbIndex(appName + "_0000");
+        if (!useNewPartDb && withSingleGroup) {
+            tddlRule.setDefaultDbIndex(appName + "_single_group");
+            dbNumber = dbNumber - 1;
+        } else {
+            tddlRule.setDefaultDbIndex(appName + "_0000");
+        }
+        partInfoMgr.setDefaultDbIndex(tddlRule.getDefaultDbIndex());
         TddlRuleManager rule = new TddlRuleManager(tddlRule, partInfoMgr, tableGroupInfoManager, appName);
 
+        Map groupInfoRecordMap = new HashMap<>();
         List groups = new LinkedList<>();
         for (int i = 0; i < dbNumber; i++) {
-            groups.add(fakeGroup(appName, appName + String.format("_%04d", i)));
+            if (useNewPartDb) {
+                TableGroupUtils.mockTheOrderedLocation(appName).forEach(
+                    groupDetailInfoExRecord -> groups.add(fakeGroup(appName, groupDetailInfoExRecord.getGroupName())));
+            } else if (withSingleGroup) {
+                final String groupKey = appName + String.format("_%06d_group", i);
+                groups.add(fakeGroup(appName, groupKey));
+                groupInfoRecordMap.put(groupKey, fakeGroupInfo(appName, groupKey));
+            } else {
+                groups.add(fakeGroup(appName, appName + String.format("_%04d", i)));
+            }
+        }
+
+        if (!useNewPartDb && withSingleGroup) {
+            final String groupKey = appName + "_single_group";
+            groups.add(fakeGroup(appName, groupKey));
+            groupInfoRecordMap.put(groupKey, fakeGroupInfo(appName, groupKey));
+            DbGroupInfoManager.getInstance().mockDbGroupInfo(appName, groupInfoRecordMap);
         }
 
         Matrix matrix = new Matrix();
@@ -486,6 +544,15 @@ public static OptimizerContext initOptiContext(String appName, int dbNumber, boo
         return context;
     }
 
+    private static DbGroupInfoRecord fakeGroupInfo(String appName, String groupKey) {
+        final DbGroupInfoRecord result = new DbGroupInfoRecord();
+        result.dbName = appName;
+        result.groupName = groupKey;
+        result.phyDbName = groupKey;
+        result.groupType = DbGroupInfoRecord.GROUP_TYPE_NORMAL;
+        return result;
+    }
+
     private static Group fakeGroup(String appname, String name) {
         Group g = new Group();
         g.setAppName(appname);
@@ -586,7 +653,7 @@ public void buildTable(String appName, String tableDDL, long defaultRowCount) {
         storeTable(appName, tr, tm, useSequence);
 
         // init gsi meta
-        if (sqlCreateTable.createGsi()) {
+        if (sqlCreateTable.createGsi() || sqlCreateTable.createCci()) {
             final String mainTableDefinition = sqlCreateTable.rewriteForGsi().toString();
             final MySqlCreateTableStatement astCreateIndexTable =
                 (MySqlCreateTableStatement) SQLUtils.parseStatementsWithDefaultFeatures(mainTableDefinition,
@@ -608,7 +675,7 @@ public void buildTable(String appName, String tableDDL, long defaultRowCount) {
                 astCreateIndexTable,
                 allIndexRecords,
                 allTableRecords,
-                false, ec);
+                false, false, ec);
 
             // global unique secondary index
             storeGsi(appName,
@@ -622,7 +689,21 @@ public void buildTable(String appName, String tableDDL, long defaultRowCount) {
                 astCreateIndexTable,
                 allIndexRecords,
                 allTableRecords,
-                true, ec);
+                true, false, ec);
+
+            // columnar index
+            storeGsi(appName,
+                sqlCreateTable,
+                logicalTableName,
+                tm,
+                tr,
+                OptimizerContext.getContext(appName).getPartitionInfoManager().getPartitionInfo(logicalTableName),
+                logicalCreateTable,
+                mainTableDefinition,
+                astCreateIndexTable,
+                allIndexRecords,
+                allTableRecords,
+                false, true, ec);
 
             // store gsi meta for primary table
             final Map> tmpTableIndexMap =
@@ -735,6 +816,7 @@ public void storeGsi(String schema, SqlCreateTable sqlCreateTable, String logica
                          TableRule tr, PartitionInfo partitionInfo, LogicalCreateTable logicalCreateTable,
                          String mainTableDefinition, MySqlCreateTableStatement astCreateIndexTable,
                          List allIndexRecords, List allTableRecords, boolean gusi,
+                         boolean cci,
                          ExecutionContext ec) {
         final Map gsiTableRules = new HashMap<>();
         final Map gsiIndexDefs = new HashMap<>();
@@ -748,6 +830,10 @@ public void storeGsi(String schema, SqlCreateTable sqlCreateTable, String logica
             if (sqlCreateTable.getClusteredUniqueKeys() != null) {
                 gsiList.addAll(sqlCreateTable.getClusteredUniqueKeys());
             }
+        } else if (cci) {
+            if (sqlCreateTable.getColumnarKeys() != null) {
+                gsiList.addAll(sqlCreateTable.getColumnarKeys());
+            }
         } else {
             if (sqlCreateTable.getGlobalKeys() != null) {
                 gsiList.addAll(sqlCreateTable.getGlobalKeys());
@@ -810,6 +896,7 @@ public void storeGsi(String schema, SqlCreateTable sqlCreateTable, String logica
                     (MySqlCreateTableStatement) FastsqlUtils.parseSql(sqlCreateIndexTable.getSourceSql()).get(0);
                 indexTm = new TableMetaParser().parse(indexStat, ec);
                 indexTm.setHasPrimaryKey(indexTm.isHasPrimaryKey());
+                indexTm.setHasPrimaryKey(!useNewPartDb || indexTm.getPrimaryIndex() != null);
                 indexTm.setSchemaName(schema);
             } else {
 
@@ -841,6 +928,7 @@ public void storeGsi(String schema, SqlCreateTable sqlCreateTable, String logica
                         .get(0);
                 indexTm = new TableMetaParser().parse(indexStat, ec);
                 indexTm.setHasPrimaryKey(true);
+                indexTm.setHasPrimaryKey(!useNewPartDb || indexTm.getPrimaryIndex() != null);
                 indexTm.setSchemaName(schema);
             }
 
@@ -913,6 +1001,13 @@ public TableRule buildTableRule(String schema, TableMeta tm, SqlCreateTable sqlC
             tr = TableRuleUtil.buildBroadcastTableRuleWithoutRandomPhyTableName(logicalTableName, tm);
         } else if (sqlCreateTable.getDbpartitionBy() != null || sqlCreateTable.getTbpartitionBy() != null) {
             ec.getExtraCmds().put(ConnectionProperties.ENABLE_RANDOM_PHY_TABLE_NAME, false);
+
+            if (!useNewPartDb && withSingleGroup) {
+                // Add this for create partition table in drds mode database.
+                // Otherwise, partition table will be created in defaultDbIndex group.
+                // Details in com.alibaba.polardbx.optimizer.utils.newrule.RuleUtils.filterSpecialGroup
+                ConfigDataMode.setMode(ConfigDataMode.Mode.GMS);
+            }
             tr = TableRuleUtil.buildShardingTableRule(logicalTableName,
                 tm,
                 sqlCreateTable.getDbpartitionBy(),
@@ -920,6 +1015,9 @@ public TableRule buildTableRule(String schema, TableMeta tm, SqlCreateTable sqlC
                 sqlCreateTable.getTbpartitionBy(),
                 sqlCreateTable.getTbpartitions(),
                 OptimizerContext.getContext(schema), ec);
+            if (!useNewPartDb && withSingleGroup) {
+                ConfigDataMode.setMode(null);
+            }
         } else {
             tr = new TableRule();
             tr.setDbNamePattern(
@@ -1260,7 +1358,7 @@ public void doPlanTest() {
     }
 
     private int count = 1;
-    private final Map> commonCases = Maps.newHashMap();
+    private final static Map> commonCases = Maps.newHashMap();
     private static final Map caseContent = Maps.newHashMap();
     private static final Map casePath = Maps.newHashMap();
 
@@ -1310,16 +1408,18 @@ protected void execSqlAndVerifyPlan(String testMethodName, Integer sqlIdx, Strin
             targetSql,
             planStr);
 
-        if (commonCases.get(caseName) != null) {
-            commonCases.get(caseName).add(this);
-        } else {
-            List list = Lists.newArrayList();
-            list.add(this);
-            commonCases.put(caseName, list);
-        }
-        this.actual = planStr;
-        if (count++ == caseNum && fixFlag) {
-            printFullCases(commonCases);
+        if (fixFlag) {
+            if (commonCases.get(caseName) != null) {
+                commonCases.get(caseName).add(this);
+            } else {
+                List list = Lists.newArrayList();
+                list.add(this);
+                commonCases.put(caseName, list);
+            }
+            this.actual = planStr;
+            if (commonCases.values().stream().mapToInt(List::size).sum() == caseNum) {
+                printFullCases(commonCases);
+            }
         }
 
         IntStream.range(0, corMaxNum).forEach(i -> targetPlanVal[0] = targetPlanVal[0].replace("$cor" + i, "$cor"));
@@ -1363,7 +1463,7 @@ public static boolean writeTxtFile(String content, File fileName) throws Excepti
         FileOutputStream fileOutputStream = null;
         try {
             fileOutputStream = new FileOutputStream(fileName);
-            fileOutputStream.write(content.getBytes("gbk"));
+            fileOutputStream.write(content.getBytes(StandardCharsets.UTF_8));
             fileOutputStream.close();
             flag = true;
         } catch (Exception e) {
@@ -1377,6 +1477,17 @@ private String insertExpectPlan(int sqlIndex, String actual, String content) {
         for (int i = 0; i <= sqlIndex; i++) {
             caseIndexStart = content.indexOf("plan: |", caseIndexStart + 1);
         }
+
+        if ((totalMap.get(this.getClass()) != null)) {
+            int caseIndexEnd = content.indexOf("\n  -", caseIndexStart);
+            if (caseIndexEnd == -1) {
+                caseIndexEnd = content.indexOf("\nDDL:", caseIndexStart);
+            }
+            StringBuilder rs = new StringBuilder(content.substring(0, caseIndexStart + "plan: |".length() + 1));
+            actual = "      " + actual.replaceAll("\n", "\n      ");
+            rs.append(actual).append(content.substring(caseIndexEnd));
+            return rs.toString();
+        }
         int caseIndexEnd = content.indexOf("\n-", caseIndexStart);
         StringBuilder rs = new StringBuilder(content.substring(0, caseIndexStart + "plan: |".length() + 1));
         actual = "    " + actual.replaceAll("\n", "\n    ");
@@ -1467,6 +1578,8 @@ protected PartitionInfo buildPartitionInfoByLogCreateTbl(String schema, LogicalC
         } else if (logicalCreateTable.isBroadCastTable()) {
             tblType = PartitionTableType.BROADCAST_TABLE;
         }
+        ParamManager.setBooleanVal(executionContext.getParamManager().getProps(),
+            ConnectionParams.ENABLE_RANDOM_PHY_TABLE_NAME, false, true);
         DDL relDdl = logicalCreateTable.relDdl;
         CreateTablePreparedData preparedData = logicalCreateTable.getCreateTablePreparedData();
 
@@ -1494,9 +1607,12 @@ protected PartitionInfo buildPartitionInfoByLogCreateTbl(String schema, LogicalC
 
         // Set auto partition flag only on primary table.
         if (tblType == PartitionTableType.PARTITION_TABLE) {
-            assert relDdl.sqlNode instanceof SqlCreateTable;
-            partitionInfo.setPartFlags(
-                ((SqlCreateTable) relDdl.sqlNode).isAutoPartition() ? TablePartitionRecord.FLAG_AUTO_PARTITION : 0);
+            SqlCreateTable sqlCreateTblAst = (SqlCreateTable) relDdl.sqlNode;
+            long partFlags = partitionInfo.getPartFlags();
+            if (sqlCreateTblAst.isAutoPartition()) {
+                partFlags |= TablePartitionRecord.FLAG_AUTO_PARTITION;
+            }
+            partitionInfo.setPartFlags(partFlags);
         }
 
         return partitionInfo;
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/CreateGlobalIndexBuilder.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/CreateGlobalIndexBuilder.java
index 9cb6144a7..4ccd575f6 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/CreateGlobalIndexBuilder.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/CreateGlobalIndexBuilder.java
@@ -407,10 +407,6 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName,
                                         "multiple primary key definition");
                                 }
                                 pkList.add(new SQLSelectOrderByItem(columnDefinition.getName()));
-                                if (unique) {
-                                    // Remove pk constrain.
-                                    constraintIt.remove();
-                                }
                             } else if (constraint instanceof SQLColumnReference) {
                                 // remove foreign key
                                 constraintIt.remove();
@@ -429,20 +425,14 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName,
                 }
             } else if (tableElement instanceof MySqlPrimaryKey) {
                 withoutPk = false;
-                if (gsiPreparedData.getPrimaryPartitionInfo() != null &&
-                    gsiPreparedData.getIndexPartitionInfo() != null) {
-                    final MySqlPrimaryKey primaryKey = (MySqlPrimaryKey) tableElement;
-                    if (!pkList.isEmpty() && !isColumnar) {
-                        throw new TddlRuntimeException(
-                            ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_UNSUPPORTED_PRIMARY_TABLE_DEFINITION,
-                            "multiple primary key definition");
-                    }
-                    pkList.addAll(primaryKey.getColumns());
-                    if (unique) {
-                        // Remove PK.
-                        it.remove();
-                    }
+
+                final MySqlPrimaryKey primaryKey = (MySqlPrimaryKey) tableElement;
+                if (!pkList.isEmpty() && !isColumnar) {
+                    throw new TddlRuntimeException(
+                        ErrorCode.ERR_GLOBAL_SECONDARY_INDEX_UNSUPPORTED_PRIMARY_TABLE_DEFINITION,
+                        "multiple primary key definition");
                 }
+                pkList.addAll(primaryKey.getColumns());
             } else if (tableElement instanceof MySqlKey) {
                 final MySqlKey key = (MySqlKey) tableElement;
 
@@ -475,18 +465,6 @@ protected SqlNode createIndexTable(SqlIdentifier indexTableName,
             }
         }
 
-        // Generate simple index of pk on unique GSI.
-        if (unique && !pkList.isEmpty()) {
-            final MySqlTableIndex index = new MySqlTableIndex();
-            index.getIndexDefinition().setIndex(true);
-            index.getIndexDefinition().setName(new SQLIdentifierExpr(UGSI_PK_INDEX_NAME));
-            index.getIndexDefinition().getColumns().addAll(pkList);
-            index.getIndexDefinition().getOptions().setIndexType("BTREE");
-            index.getIndexDefinition().setParent(index);
-            index.setParent(indexTableStmt);
-            indexTableStmt.getTableElementList().add(index);
-        }
-
         final PlannerContext context = (PlannerContext) relDdl.getCluster().getPlanner().getContext();
         final boolean defaultCurrentTimestamp =
             context.getParamManager().getBoolean(ConnectionParams.GSI_DEFAULT_CURRENT_TIMESTAMP);
@@ -726,7 +704,7 @@ protected SqlNode createClusteredIndexTable(SqlIdentifier indexTableName,
             updateAddIndex(sqlAlterTable, 0, addIndex, newIndexDef);
         }
 
-        final List indexShardKey = gsiPreparedData.getIndexTableRule().getShardColumns();
+        final List indexShardKey = gsiPreparedData.getShardColumns();
         if (DbInfoManager.getInstance().isNewPartitionDb(schemaName)) {
             SqlCreateTable.addCompositeIndex(indexColumnMap, indexTableStmt, unique, options, true, indexShardKey,
                 false, "");
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/HotGsiTestCommon.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/HotGsiTestCommon.java
new file mode 100644
index 000000000..b8f911f41
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/HotGsiTestCommon.java
@@ -0,0 +1,76 @@
+package com.alibaba.polardbx.planner.common;
+
+import com.alibaba.polardbx.common.jdbc.ParameterContext;
+import com.alibaba.polardbx.common.jdbc.Parameters;
+import com.alibaba.polardbx.common.properties.ConnectionProperties;
+import com.alibaba.polardbx.common.utils.Pair;
+import com.alibaba.polardbx.druid.sql.parser.ByteString;
+import com.alibaba.polardbx.optimizer.PlannerContext;
+import com.alibaba.polardbx.optimizer.config.table.TableMeta;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan;
+import com.alibaba.polardbx.optimizer.core.planner.Planner;
+import com.alibaba.polardbx.optimizer.core.planner.PostPlanner;
+import com.alibaba.polardbx.optimizer.hint.HintPlanner;
+import com.alibaba.polardbx.optimizer.hint.operator.HintCmdOperator;
+import com.alibaba.polardbx.optimizer.parse.FastsqlParser;
+import com.alibaba.polardbx.optimizer.parse.SqlParameterizeUtils;
+import com.alibaba.polardbx.optimizer.parse.bean.SqlParameterized;
+import com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil;
+import com.alibaba.polardbx.optimizer.utils.OptimizerUtils;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public abstract class HotGsiTestCommon extends ParameterizedTestCommon {
+    public HotGsiTestCommon(String caseName, int sqlIndex, String sql, String expectedPlan,
+                            String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Override
+    protected String getPlan(String testSql) {
+        Map currentParameter = new HashMap<>();
+        ExecutionContext executionContext = new ExecutionContext();
+        executionContext.setServerVariables(new HashMap<>());
+        executionContext.setAppName(appName);
+        SqlParameterized sqlParameterized = SqlParameterizeUtils.parameterize(
+            ByteString.from(testSql), currentParameter, executionContext, false);
+        setSysDefVariable(sqlParameterized.getParameters());
+        Map param = OptimizerUtils.buildParam(sqlParameterized.getParameters());
+        SqlNodeList astList = new FastsqlParser().parse(
+            sqlParameterized.getSql(), sqlParameterized.getParameters(), executionContext);
+        SqlNode ast = astList.get(0);
+
+        Set> tableSet = PlanManagerUtil.getTableSetFromAst(ast);
+        final HintPlanner hintPlanner = HintPlanner.getInstance(appName, executionContext);
+        executionContext.setParams(new Parameters(param, false));
+        executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_AUTO_FORCE_INDEX, enableAutoForceIndex);
+        executionContext.getExtraCmds().putAll(configMaps);
+        final HintCmdOperator.CmdBean cmdBean = new HintCmdOperator.CmdBean(appName,
+            executionContext.getExtraCmds(),
+            executionContext.getGroupHint());
+
+        hintPlanner.collectAndPreExecute(ast, cmdBean, false, executionContext);
+        processParameter(sqlParameterized, executionContext);
+        PlannerContext plannerContext = PlannerContext.fromExecutionContext(executionContext);
+        plannerContext.setSchemaName(appName);
+
+        ExecutionPlan executionPlan = Planner.getInstance().getPlan(ast, plannerContext);
+        executionPlan = PostPlanner.getInstance().optimize(executionPlan, executionContext);
+
+        int tablesVersion = PlanManagerUtil.computeTablesVersion(tableSet, appName, executionContext);
+        Map tableMetaSet = PlanManagerUtil.getTableMetaSetByTableSet(tableSet, executionContext);
+        executionPlan.saveCacheState(tableSet, tablesVersion, null, tableMetaSet);
+
+        return validator(sqlParameterized, executionPlan, executionContext);
+    }
+
+    protected String validator(SqlParameterized sqlParameterized, ExecutionPlan executionPlan,
+                               ExecutionContext executionContext) {
+        return "";
+    }
+}
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/ParameterizedTestCommon.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/ParameterizedTestCommon.java
index 9816af3b6..722766487 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/ParameterizedTestCommon.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/ParameterizedTestCommon.java
@@ -16,6 +16,7 @@
 
 package com.alibaba.polardbx.planner.common;
 
+import com.alibaba.polardbx.common.MergedStorageInfo;
 import com.alibaba.polardbx.common.jdbc.ParameterContext;
 import com.alibaba.polardbx.common.jdbc.Parameters;
 import com.alibaba.polardbx.common.properties.ConnectionProperties;
@@ -73,17 +74,47 @@ public void setExplainCost(boolean explainCost) {
     protected String getPlan(String testSql) {
         Map currentParameter = new HashMap<>();
         ExecutionContext executionContext = new ExecutionContext();
+        executionContext.setStorageInfoSupplier((schema) -> new MergedStorageInfo(true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            false,
+            true,
+            true,
+            false,
+            true,
+            false,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true,
+            true));
         executionContext.setServerVariables(new HashMap<>());
         executionContext.setAppName(appName);
         SqlParameterized sqlParameterized = SqlParameterizeUtils.parameterize(
             ByteString.from(testSql), currentParameter, executionContext, false);
         setSysDefVariable(sqlParameterized.getParameters());
         Map param = OptimizerUtils.buildParam(sqlParameterized.getParameters());
+        executionContext.setParams(new Parameters(param, false));
         SqlNodeList astList = new FastsqlParser().parse(
             sqlParameterized.getSql(), sqlParameterized.getParameters(), executionContext);
         SqlNode ast = astList.get(0);
         final HintPlanner hintPlanner = HintPlanner.getInstance(appName, executionContext);
-        executionContext.setParams(new Parameters(param, false));
+        executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_AUTO_FORCE_INDEX, enableAutoForceIndex);
         executionContext.getExtraCmds().putAll(configMaps);
         final HintCmdOperator.CmdBean cmdBean = new HintCmdOperator.CmdBean(appName,
             executionContext.getExtraCmds(),
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/PlanTestCommon.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/PlanTestCommon.java
index 76adde933..48c0e63bd 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/PlanTestCommon.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/common/PlanTestCommon.java
@@ -101,6 +101,8 @@ protected ExecutionPlan getExecutionPlan(String testSql, ExecutionContext execut
         final HintCmdOperator.CmdBean cmdBean = new HintCmdOperator.CmdBean(appName, executionContext.getExtraCmds(),
             executionContext.getGroupHint());
 
+        executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_AUTO_FORCE_INDEX, enableAutoForceIndex);
+        executionContext.getExtraCmds().putAll(configMaps);
         executionContext.getExtraCmds().put(ConnectionProperties.PARALLELISM, enableParallelQuery ? -1 : 0);
         executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_JOIN_CLUSTERING, enableJoinClustering);
         executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_MPP, enableMpp);
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/dml/ModifyTopNTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/dml/ModifyTopNTest.java
new file mode 100644
index 000000000..967c0d195
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/dml/ModifyTopNTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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 com.alibaba.polardbx.planner.dml;
+
+import com.alibaba.polardbx.gms.config.impl.ConnPoolConfig;
+import com.alibaba.polardbx.gms.config.impl.ConnPoolConfigManager;
+import com.alibaba.polardbx.planner.common.ParameterizedTestCommon;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.runners.Parameterized;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.List;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ModifyTopNTest extends ParameterizedTestCommon {
+
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
+    private static MockedStatic connPoolConfigManagerMockedStatic;
+
+    public ModifyTopNTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @BeforeClass
+    public static void beforeClass() {
+        connPoolConfigManagerMockedStatic = Mockito.mockStatic(ConnPoolConfigManager.class);
+        connPoolConfigManagerMockedStatic.when(ConnPoolConfigManager::buildDefaultConnPoolConfig).thenCallRealMethod();
+
+        final ConnPoolConfig mockedConnPoolConfig = mock(ConnPoolConfig.class);
+        when(mockedConnPoolConfig.isStorageDbXprotoEnabled()).thenReturn(true);
+
+        final ConnPoolConfigManager mockedConnPoolConfigManager = mock(ConnPoolConfigManager.class);
+        when(mockedConnPoolConfigManager.getConnPoolConfig()).thenReturn(mockedConnPoolConfig);
+
+        connPoolConfigManagerMockedStatic.when(ConnPoolConfigManager::getInstance)
+            .thenReturn(mockedConnPoolConfigManager);
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        if (null != connPoolConfigManagerMockedStatic) {
+            connPoolConfigManagerMockedStatic.close();
+        }
+    }
+
+    @Override
+    protected void initBasePlannerTestEnv() {
+        this.useNewPartDb = true;
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(ModifyTopNTest.class);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/dml/OptimizeModifyWithReturningTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/dml/OptimizeModifyWithReturningTest.java
new file mode 100644
index 000000000..246e8aac6
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/dml/OptimizeModifyWithReturningTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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 com.alibaba.polardbx.planner.dml;
+
+import com.alibaba.polardbx.gms.config.impl.ConnPoolConfig;
+import com.alibaba.polardbx.gms.config.impl.ConnPoolConfigManager;
+import com.alibaba.polardbx.planner.common.ParameterizedTestCommon;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.runners.Parameterized;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.List;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class OptimizeModifyWithReturningTest extends ParameterizedTestCommon {
+
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
+    private static MockedStatic connPoolConfigManagerMockedStatic;
+
+    public OptimizeModifyWithReturningTest(String caseName, int sqlIndex, String sql, String expectedPlan,
+                                           String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @BeforeClass
+    public static void beforeClass() {
+        connPoolConfigManagerMockedStatic = Mockito.mockStatic(ConnPoolConfigManager.class);
+        connPoolConfigManagerMockedStatic.when(ConnPoolConfigManager::buildDefaultConnPoolConfig).thenCallRealMethod();
+
+        final ConnPoolConfig mockedConnPoolConfig = mock(ConnPoolConfig.class);
+        when(mockedConnPoolConfig.isStorageDbXprotoEnabled()).thenReturn(true);
+
+        final ConnPoolConfigManager mockedConnPoolConfigManager = mock(ConnPoolConfigManager.class);
+        when(mockedConnPoolConfigManager.getConnPoolConfig()).thenReturn(mockedConnPoolConfig);
+
+        connPoolConfigManagerMockedStatic.when(ConnPoolConfigManager::getInstance)
+            .thenReturn(mockedConnPoolConfigManager);
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        if (null != connPoolConfigManagerMockedStatic) {
+            connPoolConfigManagerMockedStatic.close();
+        }
+    }
+
+    @Override
+    protected void initBasePlannerTestEnv() {
+        this.useNewPartDb = true;
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(OptimizeModifyWithReturningTest.class);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/forceindex/ForceIndexAutoTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/forceindex/ForceIndexAutoTest.java
new file mode 100644
index 000000000..e42cf3bf9
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/forceindex/ForceIndexAutoTest.java
@@ -0,0 +1,18 @@
+package com.alibaba.polardbx.planner.forceindex;
+
+import com.alibaba.polardbx.planner.common.ParameterizedTestCommon;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+public class ForceIndexAutoTest extends ParameterizedTestCommon {
+    public ForceIndexAutoTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(ForceIndexAutoTest.class);
+    }
+
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/HintPlanTestCommon.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/HintPlanTestCommon.java
index 9164e3270..c0c7a7fea 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/HintPlanTestCommon.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/HintPlanTestCommon.java
@@ -18,6 +18,8 @@
 
 import com.alibaba.polardbx.common.jdbc.Parameters;
 import com.alibaba.polardbx.common.properties.ConnectionProperties;
+import com.alibaba.polardbx.common.properties.ConnectionParams;
+import com.alibaba.polardbx.common.properties.ConnectionProperties;
 import com.alibaba.polardbx.optimizer.PlannerContext;
 import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan;
@@ -63,6 +65,7 @@ protected String getPlan(String testSql) {
 
         PlannerContext plannerContext = new PlannerContext(executionContext);
         plannerContext.setExtraCmds(executionContext.getExtraCmds());
+        plannerContext.getExtraCmds().put(ConnectionProperties.ENABLE_AUTO_FORCE_INDEX, false);
         plannerContext.setExecutionContext(executionContext);
         plannerContext.setParams(new Parameters());
         if (hintCollection.cmdOnly()) {
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.java
new file mode 100644
index 000000000..2aa824619
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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 com.alibaba.polardbx.planner.hintplan.cmd;
+
+import com.alibaba.polardbx.planner.common.EclipseParameterized;
+import com.alibaba.polardbx.planner.hintplan.index.ParameterizedHintTestCommon;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.List;
+
+@RunWith(EclipseParameterized.class)
+public class CmdHintPlanSingleGroupTest extends ParameterizedHintTestCommon {
+    public CmdHintPlanSingleGroupTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(CmdHintPlanSingleGroupTest.class);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.java
index 76c6b99b5..0051ec7c6 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.java
@@ -17,7 +17,7 @@
 package com.alibaba.polardbx.planner.hintplan.cmd;
 
 import com.alibaba.polardbx.planner.common.EclipseParameterized;
-import com.alibaba.polardbx.planner.hintplan.HintPlanTestCommon;
+import com.alibaba.polardbx.planner.hintplan.index.ParameterizedHintTestCommon;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
 
@@ -27,7 +27,7 @@
  * @author chenmo.cm
  */
 @RunWith(EclipseParameterized.class)
-public class CmdHintPlanTest extends HintPlanTestCommon {
+public class CmdHintPlanTest extends ParameterizedHintTestCommon {
     public CmdHintPlanTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
         super(caseName, sqlIndex, sql, expectedPlan, lineNum);
     }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/cmd/PartitionCmdHintPlanTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/cmd/PartitionCmdHintPlanTest.java
new file mode 100644
index 000000000..4731f92a2
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/cmd/PartitionCmdHintPlanTest.java
@@ -0,0 +1,25 @@
+package com.alibaba.polardbx.planner.hintplan.cmd;
+
+import com.alibaba.polardbx.planner.common.EclipseParameterized;
+import com.alibaba.polardbx.planner.hintplan.index.ParameterizedHintTestCommon;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+@RunWith(EclipseParameterized.class)
+public class PartitionCmdHintPlanTest extends ParameterizedHintTestCommon {
+    public PartitionCmdHintPlanTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Override
+    protected void initBasePlannerTestEnv() {
+        this.useNewPartDb = true;
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(PartitionCmdHintPlanTest.class);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/index/ParameterizedHintTestCommon.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/index/ParameterizedHintTestCommon.java
index 8aecce9e9..57aacb0b0 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/index/ParameterizedHintTestCommon.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/hintplan/index/ParameterizedHintTestCommon.java
@@ -80,6 +80,7 @@ private ExecutionPlan optimize(Map param, SqlNodeList
         ec.getExtraCmds().put(ConnectionProperties.PARALLELISM, enableParallelQuery ? -1 : 0);
         ec.getExtraCmds().put(ConnectionProperties.ENABLE_JOIN_CLUSTERING, enableJoinClustering);
         ec.getExtraCmds().put(ConnectionProperties.ENABLE_MPP, enableMpp);
+        ec.getExtraCmds().put(ConnectionProperties.ENABLE_AUTO_FORCE_INDEX, false);
         if (forceWorkloadTypeAP) {
             ec.getExtraCmds().put(ConnectionProperties.WORKLOAD_TYPE, "AP");
         }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/htap/ColumnarWorkloadTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/htap/ColumnarWorkloadTest.java
new file mode 100644
index 000000000..12b5af842
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/htap/ColumnarWorkloadTest.java
@@ -0,0 +1,40 @@
+package com.alibaba.polardbx.planner.htap;
+
+import com.alibaba.polardbx.common.jdbc.ParameterContext;
+import com.alibaba.polardbx.common.utils.InstanceRole;
+import com.alibaba.polardbx.config.ConfigDataMode;
+import com.alibaba.polardbx.optimizer.PlannerContext;
+import com.alibaba.polardbx.planner.common.ParameterizedTestCommon;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.sql.SqlExplainLevel;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+import java.util.Map;
+
+public class ColumnarWorkloadTest extends ParameterizedTestCommon {
+    public ColumnarWorkloadTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(ColumnarWorkloadTest.class);
+    }
+
+    @Override
+    protected String getPlan(String testSql) {
+        try {
+            ConfigDataMode.setInstanceRole(InstanceRole.COLUMNAR_SLAVE);
+            return super.getPlan(testSql);
+        } finally {
+            ConfigDataMode.setInstanceRole(InstanceRole.MASTER);
+        }
+    }
+
+    @Override
+    public String removeSubqueryHashCode(String planStr, RelNode plan, Map param,
+                                         SqlExplainLevel sqlExplainLevel) {
+        return PlannerContext.getPlannerContext(plan).getWorkloadType().toString();
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/oss/Tpch1TColumnarModeTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/oss/Tpch1TColumnarModeTest.java
new file mode 100644
index 000000000..77cc6f1a6
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/oss/Tpch1TColumnarModeTest.java
@@ -0,0 +1,30 @@
+package com.alibaba.polardbx.planner.oss;
+
+import com.alibaba.polardbx.common.utils.InstanceRole;
+import com.alibaba.polardbx.config.ConfigDataMode;
+import com.alibaba.polardbx.planner.common.ParameterizedTestCommon;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+public class Tpch1TColumnarModeTest extends ParameterizedTestCommon {
+    public Tpch1TColumnarModeTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+        //setExplainCost(true);
+    }
+
+    @Override
+    protected String getPlan(String testSql) {
+        try {
+            ConfigDataMode.setInstanceRole(InstanceRole.COLUMNAR_SLAVE);
+            return super.getPlan(testSql);
+        } finally {
+            ConfigDataMode.setInstanceRole(InstanceRole.MASTER);
+        }
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(Tpch1TColumnarModeTest.class);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.java
new file mode 100644
index 000000000..35499dd0b
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.java
@@ -0,0 +1,36 @@
+package com.alibaba.polardbx.planner.partition;
+
+import com.alibaba.polardbx.planner.common.PlanTestCommon;
+import org.junit.Test;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+/**
+ * @author chenghui.lch
+ */
+public class PartitionRoutingPlan2Test extends PlanTestCommon {
+
+    public PartitionRoutingPlan2Test(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+
+    }
+
+    @Override
+    protected void initBasePlannerTestEnv() {
+        this.useNewPartDb = true;
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(PartitionRoutingPlan2Test.class);
+    }
+
+    @Test
+    public void testPartitionRouting() {
+
+        System.out.print("toBeAdd test case for ");
+    }
+
+}
+
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/BaselineInfoTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/BaselineInfoTest.java
index 4e04a18b5..c06b112fd 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/BaselineInfoTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/BaselineInfoTest.java
@@ -4,13 +4,11 @@
 import com.alibaba.polardbx.common.utils.Pair;
 import com.alibaba.polardbx.gms.config.impl.InstConfUtil;
 import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager;
-import com.alibaba.polardbx.optimizer.core.rel.BaseTableOperation;
 import com.alibaba.polardbx.optimizer.core.rel.DirectMultiDBTableOperation;
 import com.alibaba.polardbx.optimizer.core.rel.DirectShardingKeyTableOperation;
 import com.alibaba.polardbx.optimizer.core.rel.DirectTableOperation;
 import com.alibaba.polardbx.optimizer.core.rel.PhyDdlTableOperation;
 import com.alibaba.polardbx.optimizer.core.rel.PhyTableOperation;
-import com.alibaba.polardbx.optimizer.core.rel.SingleTableOperation;
 import com.alibaba.polardbx.optimizer.planmanager.BaselineInfo;
 import com.alibaba.polardbx.optimizer.planmanager.PlanInfo;
 import com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil;
@@ -18,10 +16,6 @@
 import org.apache.calcite.plan.ConventionTraitDef;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.volcano.VolcanoPlanner;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.Sample;
-import org.apache.calcite.rel.core.TableScan;
-import org.apache.calcite.rel.logical.LogicalDummy;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rel.type.RelDataTypeSystem;
 import org.apache.calcite.rex.RexBuilder;
@@ -105,6 +99,29 @@ public void testMergeFixPlanExceedMaxPlanSize() {
         Assert.assertTrue(b2.getFixPlans().size() == 12 && b2.getAcceptedPlans().size() == 12);
     }
 
+    @Test
+    public void testMergeHotEvolution() {
+        BaselineInfo b1 = new BaselineInfo("test sql", Collections.emptySet());
+        BaselineInfo b2 = new BaselineInfo("test sql", Collections.emptySet());
+
+        b1.setHotEvolution(true);
+        b2.merge("test", b1);
+        Assert.assertTrue(b2.isHotEvolution());
+
+        b1 = new BaselineInfo("test sql", Collections.emptySet());
+        b2 = new BaselineInfo("test sql", Collections.emptySet());
+
+        b2.setHotEvolution(true);
+        b2.merge("test", b1);
+        Assert.assertTrue(b2.isHotEvolution());
+
+        b1 = new BaselineInfo("test sql", Collections.emptySet());
+        b2 = new BaselineInfo("test sql", Collections.emptySet());
+
+        b2.merge("test", b1);
+        Assert.assertTrue(!b2.isHotEvolution());
+    }
+
     @Ignore
     public void testMergeExpiredPlan() {
         BaselineInfo b1 = new BaselineInfo("test sql", Collections.emptySet());
@@ -152,10 +169,29 @@ public void testRebuildAtLoadBaselineHintSerialized() {
         b1.setHint(hint);
         b1.setRebuildAtLoad(true);
         b1.setUsePostPlanner(true);
+        b1.setHotEvolution(true);
         Assert.assertTrue(b1.isRebuildAtLoad());
         String json = BaselineInfo.serializeToJson(b1, false);
         BaselineInfo b2 = BaselineInfo.deserializeFromJson(json);
         Assert.assertTrue(b2.isRebuildAtLoad() && StringUtils.isNotEmpty(b2.getHint()) && b2.isUsePostPlanner());
+        Assert.assertTrue(b2.isHotEvolution());
+    }
+
+    /**
+     * test RebuildAtLoad baseline serialize
+     */
+    @Test
+    public void testRebuildAtLoadBaselineHotEvolutionSerialized() {
+        BaselineInfo b1 = new BaselineInfo("test sql", Collections.emptySet());
+        b1.setHotEvolution(true);
+        String json = BaselineInfo.serializeToJson(b1, false);
+        BaselineInfo b2 = BaselineInfo.deserializeFromJson(json);
+        Assert.assertTrue(b2.isHotEvolution());
+
+        b1 = new BaselineInfo("test sql", Collections.emptySet());
+        json = BaselineInfo.serializeToJson(b1, false);
+        b2 = BaselineInfo.deserializeFromJson(json);
+        Assert.assertTrue(!b2.isHotEvolution());
     }
 
     @Test
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/PlanInfoTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/PlanInfoTest.java
index 8dd1307ba..13534499c 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/PlanInfoTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/PlanInfoTest.java
@@ -1,13 +1,24 @@
 package com.alibaba.polardbx.planner.planmanagement;
 
+import com.alibaba.polardbx.common.properties.ParamManager;
 import com.alibaba.polardbx.common.utils.Assert;
+import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager;
+import com.alibaba.polardbx.optimizer.PlannerContext;
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
 import com.alibaba.polardbx.optimizer.planmanager.PlanInfo;
+import com.alibaba.polardbx.optimizer.planmanager.PlanManager;
 import com.google.common.collect.Maps;
+import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.util.JsonBuilder;
 import org.junit.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
 
 import java.util.Map;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mockStatic;
+
 /**
  * @author fangwu
  */
@@ -30,4 +41,48 @@ public void testFixHintEncodeDecode() {
 
         Assert.assertTrue(planInfo1.getFixHint().equals(fixHint));
     }
+
+    @Test
+    public void testCanChooseColumnarPlan() {
+        MetaDbInstConfigManager.setConfigFromMetaDb(false);
+        PlanManager planManager = PlanManager.getInstance();
+        try (MockedStatic plannerContextMockedStatic = mockStatic(PlannerContext.class)) {
+            RelNode node = Mockito.mock(RelNode.class);
+            ExecutionContext ec = new ExecutionContext("hello");
+            ec.setAutoCommit(false);
+            PlanInfo planInfo = Mockito.mock(PlanInfo.class);
+            Mockito.when(planInfo.isFixed()).thenReturn(true);
+
+            ParamManager pm = Mockito.mock(ParamManager.class);
+            ec.setParamManager(pm);
+            Mockito.when(pm.getBoolean(any())).thenReturn(false);
+
+            plannerContextMockedStatic.when(() -> PlannerContext.getPlannerContext(Mockito.any(RelNode.class)))
+                .thenAnswer(
+                    invocation -> {
+                        PlannerContext pc = Mockito.mock(PlannerContext.class);
+                        Mockito.when(pc.isUseColumnar()).thenReturn(false);
+                        return pc;
+                    });
+            Assert.assertTrue(planManager.canChooseColumnarPlan(node, ec, planInfo));
+
+            plannerContextMockedStatic.when(() -> PlannerContext.getPlannerContext(Mockito.any(RelNode.class)))
+                .thenAnswer(
+                    invocation -> {
+                        PlannerContext pc = Mockito.mock(PlannerContext.class);
+                        Mockito.when(pc.isUseColumnar()).thenReturn(true);
+                        return pc;
+                    });
+            Assert.assertTrue(!planManager.canChooseColumnarPlan(node, ec, planInfo));
+
+            ec.setAutoCommit(true);
+            Assert.assertTrue(planManager.canChooseColumnarPlan(node, ec, planInfo));
+
+            Mockito.when(planInfo.isFixed()).thenReturn(false);
+            Assert.assertTrue(!planManager.canChooseColumnarPlan(node, ec, planInfo));
+
+            Mockito.when(pm.getBoolean(any())).thenReturn(true);
+            Assert.assertTrue(planManager.canChooseColumnarPlan(node, ec, planInfo));
+        }
+    }
 }
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/PlanManagerTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/PlanManagerTest.java
index f820cf93d..9f21ba98a 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/PlanManagerTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/planmanagement/PlanManagerTest.java
@@ -3,17 +3,53 @@
 import com.alibaba.polardbx.common.utils.Assert;
 import com.alibaba.polardbx.common.utils.Pair;
 import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager;
+import com.alibaba.polardbx.gms.metadb.table.BaselineInfoAccessor;
+import com.alibaba.polardbx.gms.module.LogLevel;
+import com.alibaba.polardbx.gms.module.LogPattern;
+import com.alibaba.polardbx.gms.module.Module;
+import com.alibaba.polardbx.gms.module.ModuleLogInfo;
+import com.alibaba.polardbx.gms.node.LeaderStatusBridge;
+import com.alibaba.polardbx.gms.util.MetaDbUtil;
+import com.alibaba.polardbx.gms.util.SyncUtil;
 import com.alibaba.polardbx.optimizer.planmanager.BaselineInfo;
+import com.alibaba.polardbx.optimizer.planmanager.PlanInfo;
 import com.alibaba.polardbx.optimizer.planmanager.PlanManager;
+import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.MockitoAnnotations;
 
+import java.sql.Connection;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import static com.alibaba.polardbx.gms.module.LogPattern.UNEXPECTED;
+import static javax.naming.ldap.Control.CRITICAL;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
 /**
  * @author fangwu
  */
@@ -22,6 +58,30 @@ public class PlanManagerTest {
     static String schema2 = "plan_manager_test_schema2";
     static String schema3 = "plan_manager_test_schema3";
 
+    PlanManager planManager;
+    MockedStatic bridgeStatic;
+
+    @Mock
+    private ModuleLogInfo mockModuleLogInfo;
+
+    private Map> baselineMap;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.openMocks(this);
+        baselineMap = new HashMap<>();
+        MetaDbInstConfigManager.setConfigFromMetaDb(false);
+        planManager = spy(mock(PlanManager.class));
+        bridgeStatic = mockStatic(LeaderStatusBridge.class);
+    }
+
+    @After
+    public void cleanUp() {
+        if (bridgeStatic != null) {
+            bridgeStatic.close();
+        }
+    }
+
     @Test
     public void testInvalidateSchema() {
         MetaDbInstConfigManager.setConfigFromMetaDb(false);
@@ -63,6 +123,77 @@ public void testInvalidateTable() {
         Assert.assertTrue(!planManager.resources().contains(schema3 + " baseline size:" + 1));
     }
 
+    /**
+     * When the baseline map is empty, no exceptions should be thrown and it returns immediately.
+     */
+    @Test
+    public void testDeleteBaselineWhenBaselineMapIsEmpty() {
+        // Prepare
+        String schema = "test_schema";
+        Integer baselineId = 1;
+        baselineMap.clear();
+
+        // Execute
+        PlanManager.deleteBaseline(schema, baselineId, baselineMap);
+    }
+
+    /**
+     * Successfully deletes an existing baseline and invokes the database access layer's delete method.
+     */
+    @Test
+    public void testDeleteBaselineSuccessfully() {
+        // Prepare
+        String schema = "test_schema";
+        Integer baselineId = 49;
+        Map bMap = new HashMap<>();
+        BaselineInfo info = new BaselineInfo("1", null);
+        bMap.put("key", info);
+        baselineMap.put(schema, bMap);
+
+        try (MockedStatic syncUtilMockedStatic = mockStatic(SyncUtil.class)) {
+            syncUtilMockedStatic.when(SyncUtil::isNodeWithSmallestId).thenReturn(true);
+
+            // Execute
+            PlanManager.deleteBaseline(schema, baselineId, baselineMap);
+
+            // Verify
+            assertFalse(bMap.containsKey("key"));
+        }
+    }
+
+    /**
+     * Test Case 5: During deletion process encounters an error, logs are recorded properly.
+     */
+    @Test
+    public void testDeleteBaselineWithErrorDuringDeletion() {
+        // Prepare
+        String schema = "test_schema";
+        Map bMap = new HashMap<>();
+        BaselineInfo info = new BaselineInfo("test sql", null);
+        Integer baselineId = info.getId();
+        bMap.put("key", info);
+        baselineMap.put(schema, bMap);
+
+        try (MockedStatic syncUtilMockedStatic = mockStatic(SyncUtil.class);
+            MockedStatic metaDbUtilMockedStatic = mockStatic(MetaDbUtil.class);
+            MockedStatic moduleLogInfoMockedStatic = mockStatic(ModuleLogInfo.class);
+        ) {
+            syncUtilMockedStatic.when(SyncUtil::isNodeWithSmallestId).thenReturn(true);
+            metaDbUtilMockedStatic.when(MetaDbUtil::getConnection).thenReturn(mock(Connection.class));
+            moduleLogInfoMockedStatic.when(ModuleLogInfo::getInstance).thenReturn(mockModuleLogInfo);
+
+            // Execute
+            PlanManager.deleteBaseline(schema, baselineId, baselineMap);
+
+            // Verify
+            verify(mockModuleLogInfo).logRecord(eq(Module.SPM),
+                eq(UNEXPECTED),
+                argThat(arr -> arr.length == 2 && arr[0].equals("BASELINE DELETE")),
+                eq(LogLevel.CRITICAL),
+                any(RuntimeException.class));
+        }
+    }
+
     @Test
     public void testInvalidateTableParrallel() throws InterruptedException {
         MetaDbInstConfigManager.setConfigFromMetaDb(false);
@@ -121,6 +252,84 @@ public void testInvalidateTableParrallel() throws InterruptedException {
         }
     }
 
+    /**
+     * Tests successful removal of a plan from a baseline and potential deletion of the entire baseline.
+     */
+    @Test
+    public void testDeleteBaselinePlanSuccessfulRemovalAndPotentialDeletionOfBaseline() {
+        // Arrange
+        String schema = "test_schema";
+        String sql = "select * from t1";
+        BaselineInfo info = new BaselineInfo(sql, null);
+        Integer baselineId = info.getId();
+        PlanInfo planInfo1 = new PlanInfo("1", baselineId, 0.0D, "", "", 0);
+        PlanInfo planInfo2 = new PlanInfo("2", baselineId, 0.0D, "", "", 0);
+        int planInfoId = planInfo1.getId();
+
+        info.addAcceptedPlan(planInfo1);
+        info.addUnacceptedPlan(planInfo2);
+
+        Map innerMap = new HashMap<>();
+
+        innerMap.put(sql, info);
+        baselineMap.put(schema, innerMap);
+
+        // Act
+        PlanManager.deleteBaselinePlan(schema, baselineId, planInfoId, baselineMap);
+
+        assertTrue(innerMap.isEmpty());
+    }
+
+    /**
+     * Verifies the method handles gracefully when the baseline map is empty.
+     */
+    @Test
+    public void testDeleteBaselinePlanWhenBaselineMapIsEmptyShouldReturnWithoutAction() {
+        String schema = "test_schema";
+        Integer baselineId = 1;
+        int planInfoId = 100;
+
+        PlanManager.deleteBaselinePlan(schema, baselineId, planInfoId, baselineMap);
+    }
+
+    /**
+     * Checks the method's response when the specified schema is not present in the baseline map.
+     */
+    @Test
+    public void testDeleteBaselinePlanWhenSchemaIsNotPresentInBaselineMapShouldReturnWithoutAction() {
+        // Arrange
+        String nonExistentSchema = "nonexistent_schema";
+        Integer baselineId = 1;
+        int planInfoId = 100;
+
+        Map> anotherBaselineMap = new HashMap<>();
+
+        // Act & Assert
+        PlanManager.deleteBaselinePlan(nonExistentSchema, baselineId, planInfoId, anotherBaselineMap);
+    }
+
+    /**
+     * Ensures the method behaves correctly if the baseline ID is not found within the specified schema's map.
+     */
+    @Test
+    public void testDeleteBaselinePlanWhenBaselineIdIsNotFoundShouldReturnWithoutAction() {
+        // Arrange
+        String schema = "test_schema";
+        Integer mismatchedBaselineId = 999;
+        int planInfoId = 100;
+
+        Map innerMap = new HashMap<>();
+        BaselineInfo info = mock(BaselineInfo.class);
+        when(info.getId()).thenReturn(1); // Different ID
+
+        innerMap.put("key", info);
+        baselineMap.put(schema, innerMap);
+
+        // Act & Assert
+        PlanManager.deleteBaselinePlan(schema, mismatchedBaselineId, planInfoId, baselineMap);
+        verify(info, never()).removeAcceptedPlan(anyInt());
+    }
+
     private void buildSchema(String schema, String tableName, boolean hasFixPlan,
                              PlanManager planManager) {
         Map schemaMap1 = planManager.getBaselineMap(schema);
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/rewriter/ColumnarPlanCacheTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/rewriter/ColumnarPlanCacheTest.java
new file mode 100644
index 000000000..3bb93156a
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/rewriter/ColumnarPlanCacheTest.java
@@ -0,0 +1,25 @@
+package com.alibaba.polardbx.planner.rewriter;
+
+import com.alibaba.polardbx.optimizer.context.ExecutionContext;
+import com.alibaba.polardbx.planner.common.EclipseParameterized;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+@RunWith(EclipseParameterized.class)
+public class ColumnarPlanCacheTest extends ConstantFoldRuleTest {
+
+    public ColumnarPlanCacheTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(ColumnarPlanCacheTest.class);
+    }
+
+    protected void enableExplainCost(ExecutionContext executionContext) {
+        executionContext.setColumnarPlanCache(true);
+    }
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/rewriter/XplanSkewTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/rewriter/XplanSkewTest.java
index 1c8481b3e..8a96eb543 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/rewriter/XplanSkewTest.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/rewriter/XplanSkewTest.java
@@ -48,6 +48,7 @@ protected String getPlan(String testSql) {
         final HintPlanner hintPlanner = HintPlanner.getInstance(appName, executionContext);
         executionContext.setInternalSystemSql(false);
         executionContext.setUsingPhySqlCache(true);
+        executionContext.getExtraCmds().putAll(configMaps);
 
         final HintCmdOperator.CmdBean cmdBean = new HintCmdOperator.CmdBean(appName, executionContext.getExtraCmds(),
             executionContext.getGroupHint());
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.java
new file mode 100644
index 000000000..a1a1c1513
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.java
@@ -0,0 +1,23 @@
+package com.alibaba.polardbx.planner.selectplan;
+
+import com.alibaba.polardbx.planner.common.PlanTestCommon;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.List;
+
+/**
+ * @author chenghui.lch 2018年1月4日 上午11:19:54
+ * @since 5.0.0
+ */
+public class BroadcastRandomReadLvTest extends PlanTestCommon {
+
+    public BroadcastRandomReadLvTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(BroadcastRandomReadLvTest.class);
+    }
+
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/selectplan/PhyPushAggTest.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/selectplan/PhyPushAggTest.java
new file mode 100644
index 000000000..46cfec010
--- /dev/null
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/selectplan/PhyPushAggTest.java
@@ -0,0 +1,18 @@
+package com.alibaba.polardbx.planner.selectplan;
+
+import com.alibaba.polardbx.planner.common.ParameterizedTestCommon;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+public class PhyPushAggTest extends ParameterizedTestCommon {
+    public PhyPushAggTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+        super(caseName, sqlIndex, sql, expectedPlan, lineNum);
+    }
+
+    @Parameterized.Parameters(name = "{0}:{1}")
+    public static List prepare() {
+        return loadSqls(PhyPushAggTest.class);
+    }
+
+}
diff --git a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/usercase/UserCaseTestAuto.java b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/usercase/UserCaseAutoTest.java
similarity index 67%
rename from polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/usercase/UserCaseTestAuto.java
rename to polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/usercase/UserCaseAutoTest.java
index 148ad2351..e87c8dd60 100644
--- a/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/usercase/UserCaseTestAuto.java
+++ b/polardbx-optimizer/src/test/java/com/alibaba/polardbx/planner/usercase/UserCaseAutoTest.java
@@ -1,5 +1,6 @@
 package com.alibaba.polardbx.planner.usercase;
 
+import com.alibaba.polardbx.planner.common.ParameterizedTestCommon;
 import com.alibaba.polardbx.planner.common.PlanTestCommon;
 import org.junit.runners.Parameterized;
 
@@ -8,15 +9,15 @@
 /**
  * @author fangwu
  */
-public class UserCaseTestAuto extends PlanTestCommon {
+public class UserCaseAutoTest extends ParameterizedTestCommon {
 
-    public UserCaseTestAuto(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
+    public UserCaseAutoTest(String caseName, int sqlIndex, String sql, String expectedPlan, String lineNum) {
         super(caseName, sqlIndex, sql, expectedPlan, lineNum);
     }
 
     @Parameterized.Parameters(name = "{0}:{1}")
     public static List prepare() {
-        return loadSqls(UserCaseTestAuto.class);
+        return loadSqls(UserCaseAutoTest.class);
     }
 
     @Override
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/config/meta/TableScanSelectivityEstimatorTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/config/meta/TableScanSelectivityEstimatorTest.yml
new file mode 100644
index 000000000..ccc0f4af6
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/config/meta/TableScanSelectivityEstimatorTest.yml
@@ -0,0 +1,38 @@
+SQL:
+  - sql: |
+      select * from cest_full_table_big where c_varchar ='0abdb';
+    plan: |
+      222320
+  - sql: |
+      select * from cest_full_table_big where c_varchar  like '0abdb';
+    plan: |
+      222686
+  - sql: |
+      select * from cest_full_table_big where c_varchar  like '0abdb%';
+    plan: |
+      222686
+DDL:
+  cest_full_table_big:
+    CREATE TABLE `cest_full_table_big` (      `c_varchar` varchar(10) DEFAULT NULL) ENGINE = InnoDB AUTO_INCREMENT = 9999976 DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`c_varchar`) PARTITIONS 32
+STATISTICS:
+  cest_full_table_big:
+    10146065
+  cest_full_table_big.c_varchar.TOPN:
+    { "countArr": [ 2433,1066,969,848,715,3308,1257,1527,4703,640,44010,7391,1950,14569 ],"valueArr": [ "0abdb","150e3","322e0ed","5ee951d192","75","817a071","8b","8b4283","8f4b82","920e8","ae093","b","bd4663a26","d9" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_varchar.cardinality:
+    16380
+  cest_full_table_big.c_varchar.histogram:
+    { "buckets": [ { "ndv": 6,"upper": "00a","lower": "0","count": 559,"preSum": 0 },{ "ndv": 52,"upper": "074b69539b","lower": "00c85b4","count": 231,"preSum": 559 },{ "ndv": 47,"upper": "0dc7e251","lower": "078e97e","count": 229,"preSum": 790 },{ "ndv": 45,"upper": "13b","lower": "0dceae5","count": 229,"preSum": 1019 },{ "ndv": 53,"upper": "1b00dc6b0","lower": "13c39952","count": 229,"preSum": 1248 },{ "ndv": 31,"upper": "1fd95","lower": "1b05b203c","count": 682,"preSum": 1477 },{ "ndv": 31,"upper": "2381ac2e","lower": "2","count": 231,"preSum": 2159 },{ "ndv": 20,"upper": "26480","lower": "23a039a182","count": 229,"preSum": 2390 },{ "ndv": 22,"upper": "29","lower": "266","count": 272,"preSum": 2619 },{ "ndv": 7,"upper": "2a33cd62","lower": "290","count": 374,"preSum": 2891 },{ "ndv": 21,"upper": "2c5f8","lower": "2a38b3e6","count": 295,"preSum": 3265 },{ "ndv": 39,"upper": "3100e1bed","lower": "2c881705c0","count": 232,"preSum": 3560 },{ "ndv": 104,"upper": "3e7b006b66","lower": "310e28","count": 236,"preSum": 3792 },{ "ndv": 38,"upper": "439d9","lower": "3f065cb89","count": 382,"preSum": 4028 },{ "ndv": 40,"upper": "4a9e0d0","lower": "43bebbfaa","count": 321,"preSum": 4410 },{ "ndv": 79,"upper": "55d20f80","lower": "4acf6","count": 248,"preSum": 4731 },{ "ndv": 40,"upper": "5bd6f342c","lower": "56854ff5bf","count": 609,"preSum": 4979 },{ "ndv": 36,"upper": "61","lower": "5c299","count": 231,"preSum": 5588 },{ "ndv": 48,"upper": "68718fec4","lower": "6136af56de","count": 229,"preSum": 5819 },{ "ndv": 64,"upper": "7","lower": "687d3","count": 237,"preSum": 6048 },{ "ndv": 40,"upper": "7645e370","lower": "7001a8263","count": 364,"preSum": 6285 },{ "ndv": 33,"upper": "7ad","lower": "7667f5ffef","count": 239,"preSum": 6649 },{ "ndv": 42,"upper": "7fc5796","lower": "7adf2","count": 233,"preSum": 6888 },{ "ndv": 37,"upper": "8526f8","lower": "7fe486c70","count": 229,"preSum": 7121 },{ "ndv": 31,"upper": "88bc","lower": "857","count": 395,"preSum": 7350 },{ "ndv": 46,"upper": "8f942aac4d","lower": "88d29a56","count": 229,"preSum": 7745 },{ "ndv": 30,"upper": "93a4db","lower": "8fab04","count": 356,"preSum": 7974 },{ "ndv": 27,"upper": "97e","lower": "93c76a5e","count": 528,"preSum": 8330 },{ "ndv": 32,"upper": "9bd3b47ab0","lower": "97e90","count": 233,"preSum": 8858 },{ "ndv": 51,"upper": "a3d0c","lower": "9be21b","count": 280,"preSum": 9091 },{ "ndv": 31,"upper": "a862","lower": "a4373237","count": 280,"preSum": 9371 },{ "ndv": 44,"upper": "af454e5e2","lower": "a87355","count": 229,"preSum": 9651 },{ "ndv": 24,"upper": "b4866c38cf","lower": "af6f6396","count": 601,"preSum": 9880 },{ "ndv": 63,"upper": "bcdcc4413","lower": "b497d9","count": 231,"preSum": 10481 },{ "ndv": 43,"upper": "c333418","lower": "bce","count": 247,"preSum": 10712 },{ "ndv": 13,"upper": "c69","lower": "c38d","count": 345,"preSum": 10959 },{ "ndv": 32,"upper": "cb1050e6","lower": "c69b9b575b","count": 335,"preSum": 11304 },{ "ndv": 38,"upper": "cf539a","lower": "cb11fa08","count": 231,"preSum": 11639 },{ "ndv": 17,"upper": "d1c8d334c9","lower": "cf5d486","count": 550,"preSum": 11870 },{ "ndv": 56,"upper": "d992","lower": "d1cecee0ab","count": 272,"preSum": 12420 },{ "ndv": 84,"upper": "e3d64","lower": "d9ecd163d","count": 229,"preSum": 12692 },{ "ndv": 36,"upper": "e98c","lower": "e3e391eee","count": 240,"preSum": 12921 },{ "ndv": 64,"upper": "f3","lower": "e9dd622b","count": 230,"preSum": 13161 },{ "ndv": 13,"upper": "f4ead0","lower": "f33c3","count": 331,"preSum": 13391 },{ "ndv": 32,"upper": "f95f6364e","lower": "f4f7b","count": 330,"preSum": 13722 },{ "ndv": 28,"upper": "fe2","lower": "f9aa89","count": 257,"preSum": 14052 },{ "ndv": 6,"upper": "ffb6b2558","lower": "fe31162","count": 304,"preSum": 14309 },{ "ndv": 2,"upper": "fff96","lower": "fff2","count": 2,"preSum": 14613 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_varchar.null_count:
+    0
+  cest_full_table_big.c_varchar.sample_rate:
+    0.010943651
+  cest_full_table_big.c_varchar.composite_cardinality:
+    25009
+CONFIG:
+  ENABLE_DIRECT_PLAN:
+    false
+  ENABLE_POST_PLANNER:
+    false
+  defaltxxAPPName.isNew:
+    true
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiCaptureTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiCaptureTest.yml
new file mode 100644
index 000000000..9ad626a21
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiCaptureTest.yml
@@ -0,0 +1,954 @@
+SQL:
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' and (c_text_long = '1' or id = 1)
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_timestamp_3_idx[p19]", sql="select `c_datetime`, `id`, `c_text_long`, `c_timestamp_3`, `c_double` from `c_timestamp_3_idx` as `c_timestamp_3_idx` where ((`c_timestamp_3` = ?) and ((`c_text_long` = ?) or (`id` = ?)))")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_timestamp_3` = ?) and ((`c_text_long` = ?) or (`id` = ?)) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' and c_text_long in (  '1','2','3')
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_timestamp_3_idx[p19]", sql="select `c_datetime`, `id`, `c_text_long`, `c_timestamp_3`, `c_double` from `c_timestamp_3_idx` as `c_timestamp_3_idx` where ((`c_timestamp_3` = ?) and (`c_text_long` in(?)))")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_timestamp_3` = ?) and (`c_text_long` in(?)) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where id = 1
+    plan: |
+      false
+      phytableoperation(tables="cest_full_table_big[p2]", sql="select `cest_full_table_big`.`c_tinyint_8`, `cest_full_table_big`.`c_datetime_6`, `cest_full_table_big`.`c_mediumint_24`, `cest_full_table_big`.`c_blob_medium`, `cest_full_table_big`.`c_text_tiny`, `cest_full_table_big`.`c_time_3`, `cest_full_table_big`.`c_int_32_un`, `cest_full_table_big`.`c_year`, `cest_full_table_big`.`c_tinyint_4_un`, `cest_full_table_big`.`c_time_1`, `cest_full_table_big`.`c_text_medium`, `cest_full_table_big`.`c_year_4`, `cest_full_table_big`.`c_text`, `cest_full_table_big`.`c_datetime`, `cest_full_table_big`.`c_tinyint_8_un`, `cest_full_table_big`.`c_timestamp`, `cest_full_table_big`.`c_int_1`, `cest_full_table_big`.`c_int_32`, `cest_full_table_big`.`c_double_un`, `cest_full_table_big`.`id`, `cest_full_table_big`.`c_mediumint_24_un`, `cest_full_table_big`.`c_smallint_16_un`, `cest_full_table_big`.`c_bigint_1`, `cest_full_table_big`.`c_blob`, `cest_full_table_big`.`c_text_long`, `cest_full_table_big`.`c_timestamp_1`, `cest_full_table_big`.`c_blob_long`, `cest_full_table_big`.`c_varchar`, `cest_full_table_big`.`c_datetime_1`, `cest_full_table_big`.`c_bit_8`, `cest_full_table_big`.`c_double_pr`, `cest_full_table_big`.`c_time_6`, `cest_full_table_big`.`c_char`, `cest_full_table_big`.`c_smallint_16`, `cest_full_table_big`.`c_float_pr`, `cest_full_table_big`.`c_float_un`, `cest_full_table_big`.`c_decimal`, `cest_full_table_big`.`c_timestamp_3`, `cest_full_table_big`.`c_bigint_64`, `cest_full_table_big`.`c_blob_tiny`, `cest_full_table_big`.`c_tinyint_1_un`, `cest_full_table_big`.`c_decimal_pr`, `cest_full_table_big`.`c_enum`, `cest_full_table_big`.`c_bigint_64_un`, `cest_full_table_big`.`c_binary`, `cest_full_table_big`.`c_time`, `cest_full_table_big`.`c_float`, `cest_full_table_big`.`c_timestamp_6`, `cest_full_table_big`.`c_bit_64`, `cest_full_table_big`.`c_date`, `cest_full_table_big`.`c_bit_32`, `cest_full_table_big`.`c_tinyint_4`, `cest_full_table_big`.`c_bit_16`, `cest_full_table_big`.`c_bit_1`, `cest_full_table_big`.`c_double`, `cest_full_table_big`.`c_datetime_3`, `cest_full_table_big`.`c_mediumint_1`, `cest_full_table_big`.`c_varbinary`, `cest_full_table_big`.`c_smallint_1`, `cest_full_table_big`.`c_tinyint_1` from ? as `cest_full_table_big` where (`cest_full_table_big`.`id` = ?)", params="1")
+  - sql: |
+      select * from cest_full_table_big where c_bigint_1 = 1
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_bigint_1_idx[p2]", sql="select `id`, `c_bigint_1` from `c_bigint_1_idx` as `c_bigint_1_idx` where (`c_bigint_1` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_bigint_1` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14 and c_bigint_1 = 1
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_bigint_1_idx[p2]", sql="select `id`, `c_bigint_1` from `c_bigint_1_idx` as `c_bigint_1_idx` where (`c_bigint_1` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_bigint_64` = ?) and (`c_bigint_1` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14 and c_bigint_64_un = 1
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_bigint_64_un_c_int_1_idx[p2]", sql="select `c_int_1`, `id`, `c_bigint_64_un` from `c_bigint_64_un_c_int_1_idx` as `c_bigint_64_un_c_int_1_idx` where (`c_bigint_64_un` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_bigint_64` = ?) and (`c_bigint_64_un` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_char = '1';
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`c_char` = ?)")
+  - sql: |
+      select * from cest_full_table_big where c_char = '1' + '2';
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`c_char` = (? + ?))")
+  - sql: |
+      select * from cest_full_table_big where c_varchar = '1' + '2';
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`c_varchar` = (? + ?))")
+  - sql: |
+      select * from cest_full_table_big where c_int_32 = 1;
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_int_32_idx[p27]", sql="select `c_int_32`, `id` from `c_int_32_idx` as `c_int_32_idx` where (`c_int_32` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_int_32` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_datetime = '2023-12-01 14:10:05';
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_datetime_idx[p14]", sql="select `c_datetime`, `id` from `c_datetime_idx` as `c_datetime_idx` where (`c_datetime` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_datetime` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64_un = 1;
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_bigint_64_un_c_int_1_idx[p2]", sql="select `c_int_1`, `id`, `c_bigint_64_un` from `c_bigint_64_un_c_int_1_idx` as `c_bigint_64_un_c_int_1_idx` where (`c_bigint_64_un` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_bigint_64_un` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_mediumint_24 = 1;
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_mediumint_24_idx[p17]", sql="select `c_mediumint_24`, `id` from `c_mediumint_24_idx` as `c_mediumint_24_idx` where (`c_mediumint_24` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_mediumint_24` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_1 = '2023-12-01 14:10:05';
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_timestamp_1_idx[p17]", sql="select `id`, `c_timestamp_1`, `c_varchar` from `c_timestamp_1_idx` as `c_timestamp_1_idx` where (`c_timestamp_1` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_timestamp_1` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05';
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_timestamp_3_idx[p19]", sql="select `c_datetime`, `id`, `c_text_long`, `c_timestamp_3`, `c_double` from `c_timestamp_3_idx` as `c_timestamp_3_idx` where (`c_timestamp_3` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_timestamp_3` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_6 = '2023-12-01 14:10:05';
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_timestamp_6_idx[p3]", sql="select `c_text`, `id`, `c_text_long`, `c_timestamp_6` from `c_timestamp_6_idx` as `c_timestamp_6_idx` where (`c_timestamp_6` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_timestamp_6` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_tinyint_1 = 1;
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`c_tinyint_1` = ?)")
+  - sql: |
+      select * from cest_full_table_big where c_tinyint_1_un = 1;
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`c_tinyint_1_un` = ?)")
+  - sql: |
+      select * from cest_full_table_big where c_tinyint_4 = 1;
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`c_tinyint_4` = ?)")
+  - sql: |
+      select * from cest_full_table_big where c_tinyint_8 = 1;
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`c_tinyint_8` = ?)")
+  - sql: |
+      select * from cest_full_table_big where c_tinyint_8_un = 1;
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`c_tinyint_8_un` = ?)")
+  - sql: |
+      select * from cest_full_table_big where c_varchar = '1';
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_6 = now();
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`c_timestamp_6` = ?)")
+  - sql: |
+      select * from cest_full_table_big where c_int_32+1 = 2;
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_int_32` + ?) = ?)")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_index_selection=false)*/select * from cest_full_table_big where c_varchar = '1';
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`c_varchar` = ?)")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_index_selection=false)*/select * from cest_full_table_big force index(c_varchar_idx) where c_varchar = '1';
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big force index(c_varchar_idx) where c_varchar = '1';
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      /*+TDDL:index(cest_full_table_big,c_varchar_idx)*/ select * from cest_full_table_big where c_varchar = '1';
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big ignore index(c_varchar_idx) where c_varchar = '1';
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`c_varchar` = ?)")
+  - sql: |
+      select * from cest_full_table_big ignore index(c_timestamp_3_idx) where c_varchar = '1' and c_timestamp_3= '2023-12-01 14:10:05';
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_timestamp_3` = ?) and (`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_varchar = '1' and c_timestamp_3= '2023-12-01 14:10:05';
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_timestamp_3_idx[p19]", sql="select `c_datetime`, `id`, `c_text_long`, `c_timestamp_3`, `c_double` from `c_timestamp_3_idx` as `c_timestamp_3_idx` where (`c_timestamp_3` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_timestamp_3` = ?) and (`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      select count(c_tinyint_8) from cest_full_table_big a where a.c_varchar = '1';
+    plan: |
+      true
+      hashagg(count(c_tinyint_8)="count(c_tinyint_8)")
+        project(c_tinyint_8="c_tinyint_8")
+          bkajoin(condition="id = id", type="inner")
+            indexscan(tables="c_varchar_idx[p22]", sql="select `id` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?)")
+            gather(concurrent=true)
+              logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `id` from `cest_full_table_big` as `cest_full_table_big` where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' and c_text_long = '1';
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_timestamp_3_idx[p19]", sql="select `c_datetime`, `id`, `c_text_long`, `c_timestamp_3`, `c_double` from `c_timestamp_3_idx` as `c_timestamp_3_idx` where ((`c_timestamp_3` = ?) and (`c_text_long` = ?))")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_timestamp_3` = ?) and (`c_text_long` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_varchar = '1' order by id limit 10;
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?) order by `id` limit ?")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_varchar = '1' order by c_text_tiny limit 10;
+    plan: |
+      true
+      topn(sort="c_text_tiny asc", offset=0, fetch=?1)
+        project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+          bkajoin(condition="id = id", type="inner")
+            indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?)")
+            gather(concurrent=true)
+              logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      select count(1) as cnt from cest_full_table_big where c_varchar = '1' group by c_text_tiny order by cnt limit 10;
+    plan: |
+      true
+      topn(sort="cnt asc", offset=0, fetch=?1)
+        project(cnt="cnt")
+          hashagg(group="c_text_tiny", cnt="count()")
+            project(c_text_tiny="c_text_tiny", $f1="1")
+              bkajoin(condition="id = id", type="inner")
+                indexscan(tables="c_varchar_idx[p22]", sql="select `id` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?)")
+                gather(concurrent=true)
+                  logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_text_tiny`, `id` from `cest_full_table_big` as `cest_full_table_big` where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_push_join=false enable_push_semi_join=false)*/ 
+      select * from cest_full_table_big b where b.id in (select id from cest_full_table_big a where a.c_varchar = '1');
+    plan: |
+      false
+      materializedsemijoin(condition="id = id", type="semi")
+        gather(concurrent=true)
+          logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where (`id` in (...))")
+        indexscan(tables="c_varchar_idx[p22]", sql="select `id` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?)")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_push_join=false)*/ select count(1) from cest_full_table_big a, cest_full_table_big b where a.c_varchar = '1' and a.id = b.id;
+    plan: |
+      false
+      hashagg(count(1)="count()")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `id` from `cest_full_table_big` as `cest_full_table_big` where (`id` in (...))")
+  - sql: |
+      select * from cest_full_table_big,cest_full_table_big a, cest_full_table_big b
+      where a.c_varchar = '1' and b.c_varchar = a.c_varchar;
+    plan: |
+      false
+      nljoin(condition="true", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big`")
+        sortmergejoin(condition="c_varchar = c_varchar", type="inner")
+          project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+            bkajoin(condition="id = id", type="inner")
+              indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?) order by `c_varchar`")
+              gather(concurrent=true)
+                logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_varchar` = ?) and (`id` in (...)))")
+          project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+            bkajoin(condition="id = id", type="inner")
+              indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?) order by `c_varchar`")
+              gather(concurrent=true)
+                logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big, cest_narrow_table
+    plan: |
+      false
+      nljoin(condition="true", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big`")
+        logicalview(tables="cest_narrow_table", shardcount=0, sql="select `c_varchar`, `c_datetime`, `id`, `c_enum`, `c_int_32` from `cest_narrow_table` as `cest_narrow_table`")
+DDL:
+  cest_full_table_big:
+    CREATE TABLE `cest_full_table_big` (   `c_tinyint_8` tinyint(8) DEFAULT NULL,   `c_datetime_6` datetime(6) DEFAULT NULL,   `c_mediumint_24` mediumint(24) DEFAULT NULL,   `c_blob_medium` mediumblob,   `c_text_tiny` tinytext,   `c_time_3` time(3) DEFAULT NULL,   `c_int_32_un` int(32) UNSIGNED DEFAULT NULL,   `c_year` year(4) DEFAULT NULL,   `c_tinyint_4_un` tinyint(4) UNSIGNED DEFAULT NULL,   `c_time_1` time(1) DEFAULT NULL,   `c_text_medium` mediumtext,   `c_year_4` year(4) DEFAULT NULL,   `c_text` text,   `c_datetime` datetime DEFAULT NULL,   `c_tinyint_8_un` tinyint(8) UNSIGNED DEFAULT NULL,   `c_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,   `c_int_1` int(1) DEFAULT NULL,   `c_int_32` int(32) NOT NULL DEFAULT '0' COMMENT 'For multi pk.',   `c_double_un` double(10, 3) UNSIGNED DEFAULT NULL,   `id` bigint(20) NOT NULL AUTO_INCREMENT,   `c_mediumint_24_un` mediumint(24) UNSIGNED DEFAULT NULL,   `c_smallint_16_un` smallint(16) UNSIGNED DEFAULT NULL,   `c_bigint_1` bigint(1) DEFAULT NULL,   `c_blob` blob,   `c_text_long` longtext,   `c_timestamp_1` timestamp(1) NOT NULL DEFAULT '1999-12-31 12:00:00.0',   `c_blob_long` longblob,   `c_varchar` varchar(10) DEFAULT NULL,   `c_datetime_1` datetime(1) DEFAULT NULL,   `c_bit_8` bit(8) DEFAULT NULL,   `c_double_pr` double(10, 3) DEFAULT NULL,   `c_time_6` time(6) DEFAULT NULL,   `c_char` char(10) DEFAULT NULL,   `c_smallint_16` smallint(16) DEFAULT NULL,   `c_float_pr` float(10, 3) DEFAULT NULL,   `c_float_un` float(10, 3) UNSIGNED DEFAULT NULL,   `c_decimal` decimal(10, 0) DEFAULT NULL,   `c_timestamp_3` timestamp(3) NOT NULL DEFAULT '1999-12-31 12:00:00.000',   `c_bigint_64` bigint(64) DEFAULT NULL,   `c_blob_tiny` tinyblob,   `c_tinyint_1_un` tinyint(1) UNSIGNED DEFAULT NULL,   `c_decimal_pr` decimal(65, 30) DEFAULT NULL,   `c_enum` enum('a', 'b', 'c') DEFAULT NULL,   `c_bigint_64_un` bigint(64) UNSIGNED DEFAULT NULL,   `c_binary` binary(10) DEFAULT NULL,   `c_time` time DEFAULT NULL,   `c_float` float DEFAULT NULL,   `c_timestamp_6` timestamp(6) NOT NULL DEFAULT '1999-12-31 12:00:00.000000',   `c_bit_64` bit(64) DEFAULT NULL,   `c_date` date DEFAULT NULL COMMENT 'date',   `c_bit_32` bit(32) DEFAULT NULL,   `c_tinyint_4` tinyint(4) DEFAULT NULL,   `c_bit_16` bit(16) DEFAULT NULL,   `c_bit_1` bit(1) DEFAULT NULL,   `c_double` double DEFAULT NULL,   `c_datetime_3` datetime(3) DEFAULT NULL,   `c_mediumint_1` mediumint(1) DEFAULT NULL,   `c_varbinary` varbinary(10) DEFAULT NULL,   `c_smallint_1` smallint(1) DEFAULT NULL,   `c_tinyint_1` tinyint(1) DEFAULT NULL,   PRIMARY KEY (`id`),   GLOBAL INDEX  `c_bigint_1_idx` (`c_bigint_1`, `id`)     PARTITION BY KEY(`c_bigint_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`, `id`)     PARTITION BY KEY(`c_bigint_64_un`,`c_int_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_datetime_idx` (`c_datetime`, `id`)     PARTITION BY KEY(`c_datetime`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_int_32_idx` (`c_int_32`, `id`)     PARTITION BY KEY(`c_int_32`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_mediumint_24_idx` (`c_mediumint_24`, `id`)     PARTITION BY KEY(`c_mediumint_24`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_timestamp_1_idx` (`c_timestamp_1`, `id`) COVERING (`c_varchar`)     PARTITION BY KEY(`c_timestamp_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_timestamp_3_idx` (`c_timestamp_3`, `id`) COVERING (`c_datetime`, `c_text_long`, `c_double`)     PARTITION BY KEY(`c_timestamp_3`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_timestamp_6_idx` (`c_timestamp_6`, `id`) COVERING (`c_text`, `c_text_long`)     PARTITION BY KEY(`c_timestamp_6`,`id`)     PARTITIONS 4,   GLOBAL INDEX  `c_tinyint_1_idx` (`c_tinyint_1`, `id`)     PARTITION BY KEY(`c_tinyint_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_tinyint_1_un_idx` (`c_tinyint_1_un`, `id`)     PARTITION BY KEY(`c_tinyint_1_un`,`id`)     PARTITIONS 32,   GLOBAL INDEX`c_tinyint_4_idx` (`c_tinyint_4`, `id`)     PARTITION BY KEY(`c_tinyint_4`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_tinyint_8_idx` (`c_tinyint_8`, `id`)     PARTITION BY KEY(`c_tinyint_8`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_tinyint_8_un_idx` (`c_tinyint_8_un`, `id`)     PARTITION BY KEY(`c_tinyint_8_un`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_varchar_idx` (`c_varchar`, `id`)     PARTITION BY KEY(`c_varchar`,`id`)     PARTITIONS 32,   LOCAL KEY `_local_c_varchar_idx` (`c_varchar`),   LOCAL KEY `_local_c_int_32_idx` (`c_int_32`),   LOCAL KEY `_local_c_datetime_idx` (`c_datetime`),   LOCAL KEY `_local_c_tinyint_1_idx` (`c_tinyint_1`),   LOCAL KEY `_local_c_tinyint_1_un_idx` (`c_tinyint_1_un`),   LOCAL KEY `_local_c_tinyint_8_idx` (`c_tinyint_8`),   LOCAL KEY `_local_c_bigint_1_idx` (`c_bigint_1`),   LOCAL KEY `_local_c_tinyint_8_un_idx` (`c_tinyint_8_un`),   LOCAL KEY `_local_c_mediumint_24_idx` (`c_mediumint_24`),   LOCAL KEY `_local_c_tinyint_4_idx` (`c_tinyint_4`),   LOCAL KEY `c_char_idx` (`c_char`),   LOCAL KEY `c_int_32_un_idx` (`c_int_32_un`),   LOCAL KEY `c_time_idx` (`c_time`),   LOCAL KEY `c_tinyint_4_un_idx` (`c_tinyint_4_un`),   LOCAL KEY `c_smallint_16_idx` (`c_smallint_16`),   LOCAL KEY `c_smallint_16_un_idx` (`c_smallint_16_un`),   LOCAL KEY `c_bigint_64_idx` (`c_bigint_64`),   LOCAL KEY `c_smallint_1_idx` (`c_smallint_1`),   LOCAL KEY `c_mediumint_24_un_idx` (`c_mediumint_24_un`),   LOCAL KEY `c_mediumint_1_idx` (`c_mediumint_1`),   LOCAL KEY `_local_c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`),   LOCAL KEY `c_date_c_datetime_1_c_timestamp_idx` (`c_date`, `c_datetime_1`, `c_timestamp`),   LOCAL KEY `c_datetime_3_c_datetime_6_idx` (`c_datetime_3`, `c_datetime_6`),   LOCAL KEY `c_bit_64_c_bit_32_c_bit_8_idx` (`c_bit_64`, `c_bit_32`, `c_bit_8`),   LOCAL KEY `_local_c_timestamp_1_idx` (`c_timestamp_1`),   LOCAL KEY `_local_c_timestamp_3_idx` (`c_timestamp_3`),   LOCAL KEY `_local_c_timestamp_6_idx` (`c_timestamp_6`) ) ENGINE = InnoDB AUTO_INCREMENT = 9999976 DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS 32
+  cest_narrow_table:
+    CREATE  TABLE `cest_narrow_table` (     `c_varchar` varchar(10) DEFAULT NULL,     `c_datetime` datetime DEFAULT NULL,     `id` bigint(20) NOT NULL AUTO_INCREMENT,     `c_enum` enum('a', 'b', 'c') DEFAULT NULL,     `c_int_32` int(32) NOT NULL DEFAULT '0' COMMENT 'For multi pk.',     PRIMARY KEY (`id`),     LOCAL INDEX  `c_int_32_idx` (`c_int_32`,`id`),     LOCAL INDEX `c_varchar_idx` (`c_varchar`,`id`)   ,     LOCAL KEY `_local_c_int_32_idx` (`c_int_32`),     LOCAL KEY `_local_c_varchar_idx` (`c_varchar`),     LOCAL KEY `c_datetime_idx` (`c_datetime`)     ) ENGINE = InnoDB AUTO_INCREMENT = 9915 DEFAULT CHARSET = utf8mb4     broadcast
+STATISTICS:
+  cest_full_table_big:
+    10146065
+  cest_narrow_table:
+    10000
+  cest_full_table_big.c_bigint_1.TOPN:
+    { "countArr": [ 7,8,7,7,7,7,7,7,8,7,7,7 ],"valueArr": [ -6376110534660341752,-6295860234981414021,-3387826301801300382,-3317629540485480748,-316510671619583280,2235619186577416414,5998302180515327641,7246557246978697801,8012792635540531924,8164713881782245490,8291899079068489613,8452645718485150018 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_bigint_1.cardinality:
+    515019
+  cest_full_table_big.c_bigint_1.histogram:
+    { "buckets": [ { "ndv": 955,"upper": -8932916535817943413,"lower": -9223263330713288104,"count": 1562,"preSum": 0 },{ "ndv": 969,"upper": -8633253116690592290,"lower": -8930905338028779562,"count": 1562,"preSum": 1562 },{ "ndv": 984,"upper": -8347089718084234233,"lower": -8633198632878975763,"count": 1562,"preSum": 3124 },{ "ndv": 968,"upper": -8060695010946051790,"lower": -8346593554111079269,"count": 1566,"preSum": 4686 },{ "ndv": 994,"upper": -7771584841519309202,"lower": -8060418882318543243,"count": 1562,"preSum": 6252 },{ "ndv": 1017,"upper": -7497444055272811665,"lower": -7771428776282755773,"count": 1562,"preSum": 7814 },{ "ndv": 995,"upper": -7195896885265305430,"lower": -7497128742749681004,"count": 1563,"preSum": 9376 },{ "ndv": 977,"upper": -6921540528489252564,"lower": -7195596509692484692,"count": 1562,"preSum": 10939 },{ "ndv": 977,"upper": -6624478349282213326,"lower": -6921303896397899311,"count": 1562,"preSum": 12501 },{ "ndv": 1013,"upper": -6326942704964228255,"lower": -6623706794207147909,"count": 1562,"preSum": 14063 },{ "ndv": 973,"upper": -6048730337678060000,"lower": -6326528978673752439,"count": 1562,"preSum": 15625 },{ "ndv": 989,"upper": -5766496232027761237,"lower": -6048644639004061559,"count": 1562,"preSum": 17187 },{ "ndv": 993,"upper": -5478889351592529936,"lower": -5766385033064508563,"count": 1562,"preSum": 18749 },{ "ndv": 993,"upper": -5183757245055358005,"lower": -5478579004929422994,"count": 1563,"preSum": 20311 },{ "ndv": 984,"upper": -4888332246776830554,"lower": -5183494763525666395,"count": 1562,"preSum": 21874 },{ "ndv": 997,"upper": -4600173769951461714,"lower": -4888158332288254714,"count": 1562,"preSum": 23436 },{ "ndv": 961,"upper": -4302524136056705094,"lower": -4600123077454563931,"count": 1562,"preSum": 24998 },{ "ndv": 1015,"upper": -4010460099681951372,"lower": -4302454593034289870,"count": 1563,"preSum": 26560 },{ "ndv": 985,"upper": -3740342398516062462,"lower": -4009700152265817765,"count": 1562,"preSum": 28123 },{ "ndv": 972,"upper": -3458448279442391397,"lower": -3739424094345203473,"count": 1562,"preSum": 29685 },{ "ndv": 994,"upper": -3174379453013748082,"lower": -3458444931032076409,"count": 1562,"preSum": 31247 },{ "ndv": 991,"upper": -2886995664117776327,"lower": -3174013781147822945,"count": 1562,"preSum": 32809 },{ "ndv": 1010,"upper": -2593937518025117187,"lower": -2886840346146487112,"count": 1562,"preSum": 34371 },{ "ndv": 972,"upper": -2311562007642626030,"lower": -2593882299551196295,"count": 1562,"preSum": 35933 },{ "ndv": 992,"upper": -2011003511050290501,"lower": -2311476196844441478,"count": 1564,"preSum": 37495 },{ "ndv": 953,"upper": -1742255962838330888,"lower": -2010565592079484691,"count": 1562,"preSum": 39059 },{ "ndv": 1004,"upper": -1446304444467700880,"lower": -1742197275185244859,"count": 1562,"preSum": 40621 },{ "ndv": 981,"upper": -1143697687274724334,"lower": -1446199600463342952,"count": 1562,"preSum": 42183 },{ "ndv": 983,"upper": -866222259907853852,"lower": -1143291573446824623,"count": 1562,"preSum": 43745 },{ "ndv": 1004,"upper": -584350384737477135,"lower": -866209985750491003,"count": 1562,"preSum": 45307 },{ "ndv": 1040,"upper": -293237826231828088,"lower": -584171325701628567,"count": 1563,"preSum": 46869 },{ "ndv": 968,"upper": -8962957024550713,"lower": -293158630105002746,"count": 1564,"preSum": 48432 },{ "ndv": 995,"upper": 289014090145346562,"lower": -8530435155574750,"count": 1562,"preSum": 49996 },{ "ndv": 973,"upper": 565383892780485287,"lower": 289175669607299880,"count": 1563,"preSum": 51558 },{ "ndv": 975,"upper": 848447355876816991,"lower": 565672321220056304,"count": 1563,"preSum": 53121 },{ "ndv": 1004,"upper": 1136074647801299479,"lower": 848662352035143350,"count": 1562,"preSum": 54684 },{ "ndv": 1008,"upper": 1432922108558858103,"lower": 1136218643792012375,"count": 1562,"preSum": 56246 },{ "ndv": 997,"upper": 1731797561341496566,"lower": 1433399712803562213,"count": 1562,"preSum": 57808 },{ "ndv": 995,"upper": 2032936705490195857,"lower": 1732069259803016485,"count": 1564,"preSum": 59370 },{ "ndv": 979,"upper": 2326247533596242869,"lower": 2033329708446977153,"count": 1563,"preSum": 60934 },{ "ndv": 959,"upper": 2599395117694496397,"lower": 2326657630256408017,"count": 1563,"preSum": 62497 },{ "ndv": 991,"upper": 2900207794012340689,"lower": 2599617877064126337,"count": 1562,"preSum": 64060 },{ "ndv": 987,"upper": 3189603177437229154,"lower": 2900235803545869503,"count": 1563,"preSum": 65622 },{ "ndv": 1005,"upper": 3466305078960912793,"lower": 3189678376842742472,"count": 1563,"preSum": 67185 },{ "ndv": 997,"upper": 3748639294042867377,"lower": 3466463443751822382,"count": 1562,"preSum": 68748 },{ "ndv": 1009,"upper": 4045900804832603324,"lower": 3748960732559814083,"count": 1562,"preSum": 70310 },{ "ndv": 1009,"upper": 4344431874025830765,"lower": 4045949775924867578,"count": 1563,"preSum": 71872 },{ "ndv": 988,"upper": 4638196035864790616,"lower": 4345009076246153201,"count": 1562,"preSum": 73435 },{ "ndv": 994,"upper": 4944116281860849910,"lower": 4638823964823667617,"count": 1562,"preSum": 74997 },{ "ndv": 969,"upper": 5231698846650469388,"lower": 4944165336651832704,"count": 1562,"preSum": 76559 },{ "ndv": 997,"upper": 5523908491842344986,"lower": 5231818855412248894,"count": 1562,"preSum": 78121 },{ "ndv": 981,"upper": 5804610566785176119,"lower": 5524111479999940640,"count": 1562,"preSum": 79683 },{ "ndv": 1002,"upper": 6099658477177476090,"lower": 5804726788198338959,"count": 1564,"preSum": 81245 },{ "ndv": 974,"upper": 6384757757508310454,"lower": 6100027216548278420,"count": 1564,"preSum": 82809 },{ "ndv": 981,"upper": 6683598916728893651,"lower": 6385320649890775146,"count": 1562,"preSum": 84373 },{ "ndv": 990,"upper": 6967851413342251172,"lower": 6683675949386287849,"count": 1562,"preSum": 85935 },{ "ndv": 961,"upper": 7244011662175329458,"lower": 6968012614441058684,"count": 1563,"preSum": 87497 },{ "ndv": 998,"upper": 7534768721890628552,"lower": 7244119637768392040,"count": 1563,"preSum": 89060 },{ "ndv": 980,"upper": 7829821680269365646,"lower": 7535170687427517096,"count": 1562,"preSum": 90623 },{ "ndv": 964,"upper": 8103561053582658750,"lower": 7830323587564297823,"count": 1563,"preSum": 92185 },{ "ndv": 983,"upper": 8380697517274768086,"lower": 8104166842624602828,"count": 1563,"preSum": 93748 },{ "ndv": 971,"upper": 8663964718733504185,"lower": 8381374097397087649,"count": 1562,"preSum": 95311 },{ "ndv": 1004,"upper": 8946431649187521322,"lower": 8664843373172145036,"count": 1562,"preSum": 96873 },{ "ndv": 951,"upper": 9223368416646677796,"lower": 8946495955711455132,"count": 1480,"preSum": 98435 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_bigint_1.null_count:
+    0
+  cest_full_table_big.c_bigint_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_bigint_64.TOPN:
+    { "countArr": [ 11,9,9,10,11 ],"valueArr": [ -2139856704982564776,3604401462128241404,5895609790243533074,6384367082947171809,8141441578623813109 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_bigint_64.cardinality:
+    507720
+  cest_full_table_big.c_bigint_64.histogram:
+    { "buckets": [ { "ndv": 974,"upper": -8927652724343991035,"lower": -9221953023920127215,"count": 1562,"preSum": 0 },{ "ndv": 957,"upper": -8645377269407381398,"lower": -8927626395656871171,"count": 1562,"preSum": 1562 },{ "ndv": 1001,"upper": -8357482973612175818,"lower": -8645025410541154150,"count": 1562,"preSum": 3124 },{ "ndv": 963,"upper": -8071163862868158255,"lower": -8357399745597816913,"count": 1563,"preSum": 4686 },{ "ndv": 947,"upper": -7801304497065031829,"lower": -8070754093745276790,"count": 1562,"preSum": 6249 },{ "ndv": 982,"upper": -7523111844037817506,"lower": -7801079253921539712,"count": 1562,"preSum": 7811 },{ "ndv": 945,"upper": -7224945841412218120,"lower": -7522491706882582664,"count": 1562,"preSum": 9373 },{ "ndv": 995,"upper": -6932928303864761465,"lower": -7224785332881895610,"count": 1562,"preSum": 10935 },{ "ndv": 966,"upper": -6633032474716097388,"lower": -6932777725893798434,"count": 1562,"preSum": 12497 },{ "ndv": 991,"upper": -6338962830680978647,"lower": -6632952602866611368,"count": 1562,"preSum": 14059 },{ "ndv": 984,"upper": -6049666523782641271,"lower": -6338820433510408773,"count": 1563,"preSum": 15621 },{ "ndv": 985,"upper": -5767030579201038752,"lower": -6048526935521097555,"count": 1562,"preSum": 17184 },{ "ndv": 975,"upper": -5486778587757501916,"lower": -5766496232027761237,"count": 1563,"preSum": 18746 },{ "ndv": 982,"upper": -5195097482955811760,"lower": -5486645638968993348,"count": 1562,"preSum": 20309 },{ "ndv": 976,"upper": -4902039972138417389,"lower": -5194479412016387267,"count": 1563,"preSum": 21871 },{ "ndv": 976,"upper": -4635035793469966235,"lower": -4901998951985754401,"count": 1562,"preSum": 23434 },{ "ndv": 967,"upper": -4343734941873064980,"lower": -4634995718672950716,"count": 1562,"preSum": 24996 },{ "ndv": 971,"upper": -4064214794213234450,"lower": -4342573435506866753,"count": 1562,"preSum": 26558 },{ "ndv": 976,"upper": -3784216762723187176,"lower": -4064094323026008352,"count": 1562,"preSum": 28120 },{ "ndv": 1003,"upper": -3490063651182759733,"lower": -3784166997837250680,"count": 1563,"preSum": 29682 },{ "ndv": 956,"upper": -3210391855701750124,"lower": -3489815654062641151,"count": 1562,"preSum": 31245 },{ "ndv": 989,"upper": -2924551650030569848,"lower": -3210277999615960835,"count": 1562,"preSum": 32807 },{ "ndv": 969,"upper": -2631889191589542345,"lower": -2924235065092792431,"count": 1562,"preSum": 34369 },{ "ndv": 992,"upper": -2331124480461480735,"lower": -2631838183991566611,"count": 1562,"preSum": 35931 },{ "ndv": 1006,"upper": -2028804414273433010,"lower": -2331121738021200846,"count": 1562,"preSum": 37493 },{ "ndv": 952,"upper": -1752505327032626946,"lower": -2028625588226558123,"count": 1562,"preSum": 39055 },{ "ndv": 961,"upper": -1464823780554854666,"lower": -1752305527592966287,"count": 1564,"preSum": 40617 },{ "ndv": 989,"upper": -1170518052089825006,"lower": -1464720541236534307,"count": 1565,"preSum": 42181 },{ "ndv": 979,"upper": -887539743230306985,"lower": -1170110354477136381,"count": 1562,"preSum": 43746 },{ "ndv": 963,"upper": -618671002352385657,"lower": -887380669048133633,"count": 1564,"preSum": 45308 },{ "ndv": 978,"upper": -339779468330121399,"lower": -618449293753472813,"count": 1562,"preSum": 46872 },{ "ndv": 982,"upper": -51190505142903525,"lower": -339641946093281022,"count": 1563,"preSum": 48434 },{ "ndv": 967,"upper": 245034521167601632,"lower": -51121299341228867,"count": 1562,"preSum": 49997 },{ "ndv": 969,"upper": 531972614665271851,"lower": 245528587755148298,"count": 1562,"preSum": 51559 },{ "ndv": 980,"upper": 834570659374192796,"lower": 532234255208282424,"count": 1562,"preSum": 53121 },{ "ndv": 978,"upper": 1125291162926658849,"lower": 834602870654686463,"count": 1562,"preSum": 54683 },{ "ndv": 968,"upper": 1416834335347697711,"lower": 1126498666922816046,"count": 1564,"preSum": 56245 },{ "ndv": 974,"upper": 1708351694030344908,"lower": 1417465801344927021,"count": 1562,"preSum": 57809 },{ "ndv": 973,"upper": 2014740113807020384,"lower": 1708713415351951727,"count": 1562,"preSum": 59371 },{ "ndv": 947,"upper": 2306214426255473950,"lower": 2014798145582240824,"count": 1562,"preSum": 60933 },{ "ndv": 960,"upper": 2583890310137764084,"lower": 2306687122755612056,"count": 1563,"preSum": 62495 },{ "ndv": 1000,"upper": 2888725916247312801,"lower": 2584419043930102348,"count": 1562,"preSum": 64058 },{ "ndv": 983,"upper": 3181085200360805576,"lower": 2889873977121670667,"count": 1562,"preSum": 65620 },{ "ndv": 947,"upper": 3453576748211652303,"lower": 3181205136028523299,"count": 1564,"preSum": 67182 },{ "ndv": 979,"upper": 3726999859958230969,"lower": 3453702161231164603,"count": 1562,"preSum": 68746 },{ "ndv": 965,"upper": 4021525841481259504,"lower": 3727100714871809343,"count": 1562,"preSum": 70308 },{ "ndv": 965,"upper": 4308977407949652679,"lower": 4021567027175024161,"count": 1562,"preSum": 71870 },{ "ndv": 969,"upper": 4592963815714766171,"lower": 4309098545058768256,"count": 1565,"preSum": 73432 },{ "ndv": 933,"upper": 4868560980107919099,"lower": 4593246952544232442,"count": 1563,"preSum": 74997 },{ "ndv": 974,"upper": 5161688584651565371,"lower": 4868702937838814306,"count": 1562,"preSum": 76560 },{ "ndv": 1015,"upper": 5467786254106652615,"lower": 5161747802209442774,"count": 1562,"preSum": 78122 },{ "ndv": 953,"upper": 5758009387669823829,"lower": 5467900057526414914,"count": 1564,"preSum": 79684 },{ "ndv": 952,"upper": 6047173272322026182,"lower": 5758157582495916503,"count": 1563,"preSum": 81248 },{ "ndv": 963,"upper": 6323937186291356159,"lower": 6047578614464235417,"count": 1562,"preSum": 82811 },{ "ndv": 973,"upper": 6620279004340986701,"lower": 6324082993966485591,"count": 1562,"preSum": 84373 },{ "ndv": 994,"upper": 6907303486686254686,"lower": 6620672258935052639,"count": 1562,"preSum": 85935 },{ "ndv": 1003,"upper": 7201907485813775722,"lower": 6907530072799722514,"count": 1562,"preSum": 87497 },{ "ndv": 983,"upper": 7488695778476717378,"lower": 7202414871973059255,"count": 1562,"preSum": 89059 },{ "ndv": 986,"upper": 7783479751010090542,"lower": 7488737058134285018,"count": 1564,"preSum": 90621 },{ "ndv": 960,"upper": 8075703067812911185,"lower": 7783627772132782912,"count": 1562,"preSum": 92185 },{ "ndv": 975,"upper": 8371810814678495132,"lower": 8076044346743846592,"count": 1562,"preSum": 93747 },{ "ndv": 964,"upper": 8660192452159111802,"lower": 8372011850341689619,"count": 1562,"preSum": 95309 },{ "ndv": 967,"upper": 8937066045403710355,"lower": 8660396494288787560,"count": 1563,"preSum": 96871 },{ "ndv": 945,"upper": 9223368416646677796,"lower": 8937108356296816145,"count": 1517,"preSum": 98434 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_bigint_64.null_count:
+    0
+  cest_full_table_big.c_bigint_64.sample_rate:
+    0.010943651
+  cest_full_table_big.c_bigint_64_un.TOPN:
+    { "countArr": [ 46,30,23,23,68,39,26,32,37,31,28,23,24,22 ],"valueArr": [ 1087415032127319091,2205333288883142026,2308903691487232314,4334470004175531145,4865701636426374745,5117146957233732947,5895609790243533074,6062398447322397185,6453287398387609666,7717652110091062802,7948952639898675160,8064225747288595905,8141441578623813109,8814454888702235556 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_bigint_64_un.cardinality:
+    481649
+  cest_full_table_big.c_bigint_64_un.histogram:
+    { "buckets": [ { "ndv": 884,"upper": 143377523619721811,"lower": 48763137239300,"count": 1556,"preSum": 0 },{ "ndv": 910,"upper": 278960979219336984,"lower": 143385790312369667,"count": 1557,"preSum": 1556 },{ "ndv": 896,"upper": 422481661680937196,"lower": 278978069770671518,"count": 1558,"preSum": 3113 },{ "ndv": 927,"upper": 571002079246882457,"lower": 422490326292301016,"count": 1556,"preSum": 4671 },{ "ndv": 917,"upper": 710397180378655937,"lower": 571100093057756793,"count": 1557,"preSum": 6227 },{ "ndv": 875,"upper": 856240586300382824,"lower": 710406670071220563,"count": 1559,"preSum": 7784 },{ "ndv": 910,"upper": 1001325815362217438,"lower": 856326990306782999,"count": 1556,"preSum": 9343 },{ "ndv": 906,"upper": 1133889128214770304,"lower": 1001424214832296359,"count": 1556,"preSum": 10899 },{ "ndv": 913,"upper": 1280492970288967986,"lower": 1134219074404788743,"count": 1556,"preSum": 12455 },{ "ndv": 923,"upper": 1424443687254168158,"lower": 1280536135210107024,"count": 1556,"preSum": 14011 },{ "ndv": 921,"upper": 1570369751549112190,"lower": 1424759401696924147,"count": 1557,"preSum": 15567 },{ "ndv": 913,"upper": 1713505058205858015,"lower": 1570372282640251292,"count": 1558,"preSum": 17124 },{ "ndv": 913,"upper": 1860763515744064094,"lower": 1713664450679998847,"count": 1556,"preSum": 18682 },{ "ndv": 892,"upper": 2005758496573551087,"lower": 1860821526087774653,"count": 1556,"preSum": 20238 },{ "ndv": 939,"upper": 2153185515065391758,"lower": 2005807777991284473,"count": 1556,"preSum": 21794 },{ "ndv": 921,"upper": 2296967325801289082,"lower": 2153463132978324890,"count": 1556,"preSum": 23350 },{ "ndv": 914,"upper": 2439910797737537444,"lower": 2297078372560990054,"count": 1556,"preSum": 24906 },{ "ndv": 899,"upper": 2578309608929371819,"lower": 2439970236514597673,"count": 1560,"preSum": 26462 },{ "ndv": 915,"upper": 2722157710924967763,"lower": 2578458336108821504,"count": 1556,"preSum": 28022 },{ "ndv": 966,"upper": 2875832933937672621,"lower": 2722489815856241916,"count": 1556,"preSum": 29578 },{ "ndv": 909,"upper": 3018990177152731392,"lower": 2875904160566482321,"count": 1557,"preSum": 31134 },{ "ndv": 953,"upper": 3172565256796861719,"lower": 3019071324435221576,"count": 1556,"preSum": 32691 },{ "ndv": 909,"upper": 3310379546667968991,"lower": 3172583056621813908,"count": 1556,"preSum": 34247 },{ "ndv": 915,"upper": 3456410952154959009,"lower": 3310489134269323687,"count": 1556,"preSum": 35803 },{ "ndv": 915,"upper": 3592078775692058317,"lower": 3456728230672968593,"count": 1557,"preSum": 37359 },{ "ndv": 906,"upper": 3728411275616190674,"lower": 3592191727706987198,"count": 1556,"preSum": 38916 },{ "ndv": 936,"upper": 3868141116051374336,"lower": 3728476038328611867,"count": 1560,"preSum": 40472 },{ "ndv": 920,"upper": 4016137179277765472,"lower": 3868162460822064573,"count": 1558,"preSum": 42032 },{ "ndv": 908,"upper": 4157136919545294989,"lower": 4016265401698310826,"count": 1556,"preSum": 43590 },{ "ndv": 912,"upper": 4297295899841478402,"lower": 4157195099505157168,"count": 1556,"preSum": 45146 },{ "ndv": 924,"upper": 4438445496415010361,"lower": 4297338045176787786,"count": 1556,"preSum": 46702 },{ "ndv": 938,"upper": 4586617466945791923,"lower": 4438710085756478322,"count": 1564,"preSum": 48258 },{ "ndv": 947,"upper": 4733894406450754828,"lower": 4586705939535379448,"count": 1556,"preSum": 49822 },{ "ndv": 909,"upper": 4871530266753000007,"lower": 4733960083903262756,"count": 1556,"preSum": 51378 },{ "ndv": 945,"upper": 5029156725544930304,"lower": 4871760827818674555,"count": 1559,"preSum": 52934 },{ "ndv": 934,"upper": 5178592058910890967,"lower": 5029525773577266910,"count": 1559,"preSum": 54493 },{ "ndv": 918,"upper": 5326292209784721061,"lower": 5178607350840304529,"count": 1556,"preSum": 56052 },{ "ndv": 957,"upper": 5482290778155050178,"lower": 5326303098111382594,"count": 1557,"preSum": 57608 },{ "ndv": 918,"upper": 5625922138218461838,"lower": 5482356166425261076,"count": 1556,"preSum": 59165 },{ "ndv": 894,"upper": 5764488275573736873,"lower": 5626062356027442354,"count": 1557,"preSum": 60721 },{ "ndv": 912,"upper": 5914251657147044094,"lower": 5764494083989547798,"count": 1556,"preSum": 62278 },{ "ndv": 932,"upper": 6062346217045254294,"lower": 5914601855409356436,"count": 1557,"preSum": 63834 },{ "ndv": 934,"upper": 6205276567806062527,"lower": 6062803603034453082,"count": 1557,"preSum": 65391 },{ "ndv": 930,"upper": 6351731061576669929,"lower": 6205437903667178170,"count": 1557,"preSum": 66948 },{ "ndv": 903,"upper": 6491174946873541390,"lower": 6351816449475929255,"count": 1556,"preSum": 68505 },{ "ndv": 948,"upper": 6640948085671180476,"lower": 6491321911696706086,"count": 1556,"preSum": 70061 },{ "ndv": 933,"upper": 6787892547095806325,"lower": 6640949038969401276,"count": 1556,"preSum": 71617 },{ "ndv": 946,"upper": 6939238647275224531,"lower": 6788043195538016093,"count": 1558,"preSum": 73173 },{ "ndv": 951,"upper": 7089615225886080583,"lower": 6939445177801584002,"count": 1556,"preSum": 74731 },{ "ndv": 937,"upper": 7238428823910129839,"lower": 7089709620746364317,"count": 1556,"preSum": 76287 },{ "ndv": 922,"upper": 7386622925184515132,"lower": 7238713692628446857,"count": 1556,"preSum": 77843 },{ "ndv": 915,"upper": 7535888888824309201,"lower": 7386654043414518139,"count": 1556,"preSum": 79399 },{ "ndv": 919,"upper": 7681604746335359873,"lower": 7536090657654927705,"count": 1556,"preSum": 80955 },{ "ndv": 944,"upper": 7830242705068044791,"lower": 7681630263029259631,"count": 1556,"preSum": 82511 },{ "ndv": 912,"upper": 7962170075137872397,"lower": 7830323587564297823,"count": 1557,"preSum": 84067 },{ "ndv": 874,"upper": 8104770429408762642,"lower": 7962308988243478983,"count": 1556,"preSum": 85624 },{ "ndv": 915,"upper": 8239992543374518734,"lower": 8104842357604407276,"count": 1558,"preSum": 87180 },{ "ndv": 920,"upper": 8373870773188886278,"lower": 8240018739885202418,"count": 1559,"preSum": 88738 },{ "ndv": 929,"upper": 8521614543274947002,"lower": 8373938387502758943,"count": 1562,"preSum": 90297 },{ "ndv": 909,"upper": 8662816396873233441,"lower": 8521625759312967401,"count": 1556,"preSum": 91859 },{ "ndv": 915,"upper": 8806478312334200916,"lower": 8663201177912903052,"count": 1556,"preSum": 93415 },{ "ndv": 928,"upper": 8949846182062769226,"lower": 8806540315290452943,"count": 1556,"preSum": 94971 },{ "ndv": 913,"upper": 9091397889701681890,"lower": 8949864789900045536,"count": 1556,"preSum": 96527 },{ "ndv": 879,"upper": 9223368416646677796,"lower": 9091452900128267010,"count": 1466,"preSum": 98083 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_bigint_64_un.null_count:
+    0
+  cest_full_table_big.c_bigint_64_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_char.TOPN:
+    { "countArr": [ 45,50,154,110,52,52,62,80,52,43,63,80,73 ],"valueArr": [ "150e33107d","322e0ed9c2","34d9c309ae","5bf106c3d9","5ee951d192","61367328af","716a1a9e0a","7bd0172e8f","8b4283c7d3","8bbeb466cd","b556d066bd","b5c6978fb3","c477a1d481" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_char.cardinality:
+    462831
+  cest_full_table_big.c_char.histogram:
+    { "buckets": [ { "ndv": 876,"upper": "0405fc807d","lower": "000048feb9","count": 1550,"preSum": 0 },{ "ndv": 873,"upper": "07d86ec9c3","lower": "04061ddbde","count": 1549,"preSum": 1550 },{ "ndv": 883,"upper": "0bba872b40","lower": "07d8a6e17d","count": 1553,"preSum": 3099 },{ "ndv": 851,"upper": "0f8552964f","lower": "0bbbc0aba3","count": 1550,"preSum": 4652 },{ "ndv": 823,"upper": "1353f0a4c2","lower": "0f85a9c567","count": 1549,"preSum": 6202 },{ "ndv": 865,"upper": "176269ef41","lower": "135426bf4c","count": 1559,"preSum": 7751 },{ "ndv": 880,"upper": "1b6e924452","lower": "17646390fa","count": 1550,"preSum": 9310 },{ "ndv": 863,"upper": "1f4b57f199","lower": "1b70368d34","count": 1553,"preSum": 10860 },{ "ndv": 904,"upper": "237c2d96e5","lower": "1f551aea58","count": 1549,"preSum": 12413 },{ "ndv": 823,"upper": "2741c6a9ed","lower": "237de85e8e","count": 1549,"preSum": 13962 },{ "ndv": 888,"upper": "2b0aaef93e","lower": "274291fe50","count": 1550,"preSum": 15511 },{ "ndv": 877,"upper": "2f2f76a7ad","lower": "2b0ab2732c","count": 1549,"preSum": 17061 },{ "ndv": 906,"upper": "3334172ee9","lower": "2f2fcf938b","count": 1549,"preSum": 18610 },{ "ndv": 870,"upper": "372241e487","lower": "3337fdfac2","count": 1549,"preSum": 20159 },{ "ndv": 831,"upper": "3af3873033","lower": "372277971a","count": 1549,"preSum": 21708 },{ "ndv": 895,"upper": "3f42485805","lower": "3af3a48b97","count": 1549,"preSum": 23257 },{ "ndv": 913,"upper": "435a8cc58f","lower": "3f430cc0c2","count": 1549,"preSum": 24806 },{ "ndv": 847,"upper": "475fc56ed6","lower": "435bd74ceb","count": 1550,"preSum": 26355 },{ "ndv": 884,"upper": "4bc9a76292","lower": "47611ff4da","count": 1551,"preSum": 27905 },{ "ndv": 861,"upper": "4fe4266ae0","lower": "4bca6ee704","count": 1549,"preSum": 29456 },{ "ndv": 896,"upper": "53cedf2291","lower": "4fe429a3b5","count": 1552,"preSum": 31005 },{ "ndv": 893,"upper": "57dbd94fd1","lower": "53cf7f9d1f","count": 1549,"preSum": 32557 },{ "ndv": 888,"upper": "5bd6f342c7","lower": "57dde82542","count": 1572,"preSum": 34106 },{ "ndv": 896,"upper": "60124e4e44","lower": "5bd7574264","count": 1549,"preSum": 35678 },{ "ndv": 839,"upper": "63f899fb01","lower": "60126193bf","count": 1551,"preSum": 37227 },{ "ndv": 899,"upper": "67fec64646","lower": "63fa5cb511","count": 1551,"preSum": 38778 },{ "ndv": 858,"upper": "6bf7c2f383","lower": "67fec7b8b0","count": 1549,"preSum": 40329 },{ "ndv": 892,"upper": "700d0fec91","lower": "6bfd69afd0","count": 1549,"preSum": 41878 },{ "ndv": 880,"upper": "743b9adc51","lower": "700df27f46","count": 1549,"preSum": 43427 },{ "ndv": 874,"upper": "78101d75af","lower": "743bf7af56","count": 1549,"preSum": 44976 },{ "ndv": 878,"upper": "7c0e99eaf9","lower": "78104cbb6a","count": 1551,"preSum": 46525 },{ "ndv": 931,"upper": "80844b8282","lower": "7c105a60e9","count": 1549,"preSum": 48076 },{ "ndv": 856,"upper": "8456ccf69a","lower": "8084d5cab2","count": 1549,"preSum": 49625 },{ "ndv": 847,"upper": "882ee64180","lower": "8459dce4f4","count": 1551,"preSum": 51174 },{ "ndv": 887,"upper": "8bfa54082d","lower": "882f02e256","count": 1550,"preSum": 52725 },{ "ndv": 864,"upper": "900fe1d0fa","lower": "8bfa86f172","count": 1549,"preSum": 54275 },{ "ndv": 881,"upper": "9418d3cd43","lower": "901134d92c","count": 1550,"preSum": 55824 },{ "ndv": 889,"upper": "982d7b1b66","lower": "9419421896","count": 1550,"preSum": 57374 },{ "ndv": 853,"upper": "9c4299731f","lower": "982ef9e0ad","count": 1549,"preSum": 58924 },{ "ndv": 892,"upper": "a0485a33b2","lower": "9c42a93785","count": 1551,"preSum": 60473 },{ "ndv": 864,"upper": "a437323744","lower": "a048f2d4e2","count": 1557,"preSum": 62024 },{ "ndv": 893,"upper": "a805bfad12","lower": "a4373ddbff","count": 1549,"preSum": 63581 },{ "ndv": 884,"upper": "ac1a35c93f","lower": "a80615a7ca","count": 1549,"preSum": 65130 },{ "ndv": 876,"upper": "b03389efea","lower": "ac1a7da36c","count": 1550,"preSum": 66679 },{ "ndv": 877,"upper": "b46bf37e8b","lower": "b034c7bbcb","count": 1549,"preSum": 68229 },{ "ndv": 876,"upper": "b87590d633","lower": "b46bf7bcc5","count": 1549,"preSum": 69778 },{ "ndv": 857,"upper": "bc7e4a1826","lower": "b876b99639","count": 1549,"preSum": 71327 },{ "ndv": 858,"upper": "c0485d2fea","lower": "bc7e642804","count": 1549,"preSum": 72876 },{ "ndv": 896,"upper": "c47e297c8a","lower": "c048b01a4f","count": 1549,"preSum": 74425 },{ "ndv": 896,"upper": "c87a531faf","lower": "c47f57e5c8","count": 1549,"preSum": 75974 },{ "ndv": 852,"upper": "cc59158712","lower": "c87de76837","count": 1549,"preSum": 77523 },{ "ndv": 821,"upper": "d030b5d7a0","lower": "cc5a14b6e5","count": 1553,"preSum": 79072 },{ "ndv": 873,"upper": "d40fd8f898","lower": "d03195ce25","count": 1549,"preSum": 80625 },{ "ndv": 897,"upper": "d839e65db7","lower": "d40fdf53b1","count": 1552,"preSum": 82174 },{ "ndv": 833,"upper": "dc1e43fd1c","lower": "d83ad1b8c9","count": 1550,"preSum": 83726 },{ "ndv": 863,"upper": "dfeefff295","lower": "dc1ef9ccf1","count": 1549,"preSum": 85276 },{ "ndv": 893,"upper": "e3d6459ddd","lower": "dff141088e","count": 1549,"preSum": 86825 },{ "ndv": 891,"upper": "e81307cc42","lower": "e3d67249dd","count": 1549,"preSum": 88374 },{ "ndv": 850,"upper": "ec20059941","lower": "e813d09eea","count": 1551,"preSum": 89923 },{ "ndv": 874,"upper": "f035ef2008","lower": "ec20912bb0","count": 1554,"preSum": 91474 },{ "ndv": 902,"upper": "f483943b70","lower": "f036799f11","count": 1549,"preSum": 93028 },{ "ndv": 865,"upper": "f825bdd07c","lower": "f48401ac6e","count": 1550,"preSum": 94577 },{ "ndv": 877,"upper": "fc60d801bb","lower": "f825eaad04","count": 1550,"preSum": 96127 },{ "ndv": 771,"upper": "ffffb91afe","lower": "fc60fe2ddf","count": 1408,"preSum": 97677 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_char.null_count:
+    0
+  cest_full_table_big.c_char.sample_rate:
+    0.010943651
+  cest_full_table_big.c_date.TOPN:
+    { "countArr": [ 314,313,318,320,317,315,334,322,319,313,331,317,315,314 ],"valueArr": [ 1849873338151731200,1849901925454053376,1849972294198231040,1850029468802875392,1850060255128453120,1850086643407519744,1850154813128441856,1850181201407508480,1850187798477275136,1850200992616808448,1850471472477241344,1850541841221419008,1850546239267930112,1850610010942341120 ],"type": "Date","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_date.cardinality:
+    365
+  cest_full_table_big.c_date.histogram:
+    { "buckets": [ { "ndv": 6,"upper": "1849796372337786880","lower": "1849785377221509120","count": 1652,"preSum": 0 },{ "ndv": 6,"upper": "1849809566477320192","lower": "1849798571361042432","count": 1665,"preSum": 1652 },{ "ndv": 6,"upper": "1849822760616853504","lower": "1849811765500575744","count": 1636,"preSum": 3317 },{ "ndv": 6,"upper": "1849835954756386816","lower": "1849824959640109056","count": 1558,"preSum": 4953 },{ "ndv": 6,"upper": "1849849148895920128","lower": "1849838153779642368","count": 1593,"preSum": 6511 },{ "ndv": 6,"upper": "1849864542058708992","lower": "1849851347919175680","count": 1675,"preSum": 8104 },{ "ndv": 6,"upper": "1849879935221497856","lower": "1849866741081964544","count": 1643,"preSum": 9779 },{ "ndv": 6,"upper": "1849893129361031168","lower": "1849882134244753408","count": 1699,"preSum": 11422 },{ "ndv": 6,"upper": "1849908522523820032","lower": "1849895328384286720","count": 1575,"preSum": 13121 },{ "ndv": 6,"upper": "1849930512756375552","lower": "1849910721547075584","count": 1631,"preSum": 14696 },{ "ndv": 6,"upper": "1849943706895908864","lower": "1849932711779631104","count": 1571,"preSum": 16327 },{ "ndv": 6,"upper": "1849956901035442176","lower": "1849945905919164416","count": 1639,"preSum": 17898 },{ "ndv": 6,"upper": "1849970095174975488","lower": "1849959100058697728","count": 1622,"preSum": 19537 },{ "ndv": 6,"upper": "1849985488337764352","lower": "1849974493221486592","count": 1616,"preSum": 21159 },{ "ndv": 6,"upper": "1850000881500553216","lower": "1849987687361019904","count": 1641,"preSum": 22775 },{ "ndv": 6,"upper": "1850014075640086528","lower": "1850003080523808768","count": 1599,"preSum": 24416 },{ "ndv": 6,"upper": "1850027269779619840","lower": "1850016274663342080","count": 1685,"preSum": 26015 },{ "ndv": 6,"upper": "1850042662942408704","lower": "1850031667826130944","count": 1634,"preSum": 27700 },{ "ndv": 6,"upper": "1850055857081942016","lower": "1850044861965664256","count": 1619,"preSum": 29334 },{ "ndv": 6,"upper": "1850075648291241984","lower": "1850058056105197568","count": 1580,"preSum": 30953 },{ "ndv": 6,"upper": "1850091041454030848","lower": "1850077847314497536","count": 1601,"preSum": 32533 },{ "ndv": 6,"upper": "1850104235593564160","lower": "1850093240477286400","count": 1617,"preSum": 34134 },{ "ndv": 6,"upper": "1850117429733097472","lower": "1850106434616819712","count": 1579,"preSum": 35751 },{ "ndv": 6,"upper": "1850130623872630784","lower": "1850119628756353024","count": 1616,"preSum": 37330 },{ "ndv": 6,"upper": "1850146017035419648","lower": "1850132822895886336","count": 1715,"preSum": 38946 },{ "ndv": 6,"upper": "1850161410198208512","lower": "1850148216058675200","count": 1709,"preSum": 40661 },{ "ndv": 6,"upper": "1850174604337741824","lower": "1850163609221464064","count": 1623,"preSum": 42370 },{ "ndv": 6,"upper": "1850192196523786240","lower": "1850176803360997376","count": 1658,"preSum": 43993 },{ "ndv": 6,"upper": "1850211987733086208","lower": "1850194395547041792","count": 1638,"preSum": 45651 },{ "ndv": 6,"upper": "1850225181872619520","lower": "1850214186756341760","count": 1586,"preSum": 47289 },{ "ndv": 6,"upper": "1850238376012152832","lower": "1850227380895875072","count": 1697,"preSum": 48875 },{ "ndv": 6,"upper": "1850251570151686144","lower": "1850240575035408384","count": 1575,"preSum": 50572 },{ "ndv": 6,"upper": "1850264764291219456","lower": "1850253769174941696","count": 1588,"preSum": 52147 },{ "ndv": 6,"upper": "1850280157454008320","lower": "1850266963314475008","count": 1631,"preSum": 53735 },{ "ndv": 6,"upper": "1850293351593541632","lower": "1850282356477263872","count": 1693,"preSum": 55366 },{ "ndv": 6,"upper": "1850306545733074944","lower": "1850295550616797184","count": 1651,"preSum": 57059 },{ "ndv": 6,"upper": "1850319739872608256","lower": "1850308744756330496","count": 1635,"preSum": 58710 },{ "ndv": 6,"upper": "1850332934012141568","lower": "1850321938895863808","count": 1601,"preSum": 60345 },{ "ndv": 6,"upper": "1850348327174930432","lower": "1850335133035397120","count": 1597,"preSum": 61946 },{ "ndv": 6,"upper": "1850361521314463744","lower": "1850350526198185984","count": 1716,"preSum": 63543 },{ "ndv": 6,"upper": "1850374715453997056","lower": "1850363720337719296","count": 1713,"preSum": 65259 },{ "ndv": 6,"upper": "1850387909593530368","lower": "1850376914477252608","count": 1718,"preSum": 66972 },{ "ndv": 6,"upper": "1850401103733063680","lower": "1850390108616785920","count": 1585,"preSum": 68690 },{ "ndv": 6,"upper": "1850418695919108096","lower": "1850403302756319232","count": 1650,"preSum": 70275 },{ "ndv": 6,"upper": "1850431890058641408","lower": "1850420894942363648","count": 1694,"preSum": 71925 },{ "ndv": 6,"upper": "1850445084198174720","lower": "1850434089081896960","count": 1663,"preSum": 73619 },{ "ndv": 6,"upper": "1850458278337708032","lower": "1850447283221430272","count": 1549,"preSum": 75282 },{ "ndv": 6,"upper": "1850473671500496896","lower": "1850460477360963584","count": 1656,"preSum": 76831 },{ "ndv": 6,"upper": "1850489064663285760","lower": "1850475870523752448","count": 1607,"preSum": 78487 },{ "ndv": 6,"upper": "1850502258802819072","lower": "1850491263686541312","count": 1640,"preSum": 80094 },{ "ndv": 6,"upper": "1850515452942352384","lower": "1850504457826074624","count": 1600,"preSum": 81734 },{ "ndv": 6,"upper": "1850528647081885696","lower": "1850517651965607936","count": 1637,"preSum": 83334 },{ "ndv": 6,"upper": "1850544040244674560","lower": "1850530846105141248","count": 1577,"preSum": 84971 },{ "ndv": 6,"upper": "1850563831453974528","lower": "1850548438291185664","count": 1639,"preSum": 86548 },{ "ndv": 6,"upper": "1850577025593507840","lower": "1850566030477230080","count": 1626,"preSum": 88187 },{ "ndv": 6,"upper": "1850590219733041152","lower": "1850579224616763392","count": 1662,"preSum": 89813 },{ "ndv": 6,"upper": "1850603413872574464","lower": "1850592418756296704","count": 1621,"preSum": 91475 },{ "ndv": 6,"upper": "1850618807035363328","lower": "1850605612895830016","count": 1704,"preSum": 93096 },{ "ndv": 3,"upper": "1850625404105129984","lower": "1850621006058618880","count": 739,"preSum": 94800 } ],"maxBucketSize": 64,"type": "Date","sampleRate": 0.90062594 }
+  cest_full_table_big.c_date.null_count:
+    0
+  cest_full_table_big.c_date.sample_rate:
+    0.010943651
+  cest_full_table_big.c_datetime.TOPN:
+    { "countArr": [ 7,8,7,7,8,7,7 ],"valueArr": [ 1849856379473362944,1849966883126640640,1850096458666082304,1850112028845277184,1850159979386896384,1850408374944923648,1850600075777015808 ],"type": "Datetime","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_datetime.cardinality:
+    515198
+  cest_full_table_big.c_datetime.histogram:
+    { "buckets": [ { "ndv": 988,"upper": "1849797349442846720","lower": "1849785388378357760","count": 1563,"preSum": 0 },{ "ndv": 994,"upper": "1849810007432888320","lower": "1849797352949284864","count": 1563,"preSum": 1563 },{ "ndv": 998,"upper": "1849822169907855360","lower": "1849810009664258048","count": 1562,"preSum": 3126 },{ "ndv": 993,"upper": "1849835987757170688","lower": "1849822185108013056","count": 1564,"preSum": 4688 },{ "ndv": 1004,"upper": "1849848516512317440","lower": "1849835990038872064","count": 1562,"preSum": 6252 },{ "ndv": 990,"upper": "1849863290562281472","lower": "1849848521394487296","count": 1562,"preSum": 7814 },{ "ndv": 976,"upper": "1849875556552671232","lower": "1849863306248978432","count": 1565,"preSum": 9376 },{ "ndv": 1011,"upper": "1849887891413532672","lower": "1849875561652944896","count": 1562,"preSum": 10941 },{ "ndv": 1007,"upper": "1849900578210054144","lower": "1849887894282436608","count": 1562,"preSum": 12503 },{ "ndv": 960,"upper": "1849912344541396992","lower": "1849900608560037888","count": 1562,"preSum": 14065 },{ "ndv": 1006,"upper": "1849934999990566912","lower": "1849912352191807488","count": 1562,"preSum": 15627 },{ "ndv": 989,"upper": "1849947243063279616","lower": "1849935035474378752","count": 1562,"preSum": 17189 },{ "ndv": 995,"upper": "1849960156536766464","lower": "1849947243667259392","count": 1562,"preSum": 18751 },{ "ndv": 996,"upper": "1849972736445644800","lower": "1849960173850853376","count": 1563,"preSum": 20313 },{ "ndv": 990,"upper": "1849985731322183680","lower": "1849972736663748608","count": 1563,"preSum": 21876 },{ "ndv": 1007,"upper": "1850000072838742016","lower": "1849985735147388928","count": 1562,"preSum": 23439 },{ "ndv": 984,"upper": "1850012695227531264","lower": "1850000073291726848","count": 1562,"preSum": 25001 },{ "ndv": 989,"upper": "1850025523472760832","lower": "1850012707474898944","count": 1562,"preSum": 26563 },{ "ndv": 961,"upper": "1850037400969936896","lower": "1850025536441548800","count": 1562,"preSum": 28125 },{ "ndv": 1022,"upper": "1850049990894813184","lower": "1850037414257491968","count": 1562,"preSum": 29687 },{ "ndv": 980,"upper": "1850067127914987520","lower": "1850049995558879232","count": 1562,"preSum": 31249 },{ "ndv": 959,"upper": "1850079478009561088","lower": "1850067137998094336","count": 1564,"preSum": 32811 },{ "ndv": 986,"upper": "1850092294141640704","lower": "1850080048921444352","count": 1562,"preSum": 34375 },{ "ndv": 969,"upper": "1850105086299078656","lower": "1850092315482259456","count": 1562,"preSum": 35937 },{ "ndv": 994,"upper": "1850118003564216320","lower": "1850105099469193216","count": 1562,"preSum": 37499 },{ "ndv": 970,"upper": "1850130906283507712","lower": "1850118004688289792","count": 1564,"preSum": 39061 },{ "ndv": 969,"upper": "1850145197317423104","lower": "1850130906535165952","count": 1562,"preSum": 40625 },{ "ndv": 990,"upper": "1850157220558274560","lower": "1850145197401309184","count": 1562,"preSum": 42187 },{ "ndv": 986,"upper": "1850169175700406272","lower": "1850157232872751104","count": 1562,"preSum": 43749 },{ "ndv": 985,"upper": "1850181877176991744","lower": "1850169189642272768","count": 1562,"preSum": 45311 },{ "ndv": 974,"upper": "1850193542475939840","lower": "1850181915093499904","count": 1562,"preSum": 46873 },{ "ndv": 991,"upper": "1850210275685302272","lower": "1850193559622254592","count": 1562,"preSum": 48435 },{ "ndv": 981,"upper": "1850223335640662016","lower": "1850210280517140480","count": 1562,"preSum": 49997 },{ "ndv": 962,"upper": "1850235437096894464","lower": "1850223338979328000","count": 1562,"preSum": 51559 },{ "ndv": 1005,"upper": "1850248266667524096","lower": "1850235446408249344","count": 1562,"preSum": 53121 },{ "ndv": 1005,"upper": "1850261234734071808","lower": "1850248286884069376","count": 1562,"preSum": 54683 },{ "ndv": 1017,"upper": "1850274085242667008","lower": "1850261236898332672","count": 1562,"preSum": 56245 },{ "ndv": 994,"upper": "1850288998493192192","lower": "1850274121951215616","count": 1564,"preSum": 57807 },{ "ndv": 971,"upper": "1850300960866304000","lower": "1850289004633653248","count": 1562,"preSum": 59371 },{ "ndv": 1023,"upper": "1850313627177844736","lower": "1850300970462871552","count": 1562,"preSum": 60933 },{ "ndv": 998,"upper": "1850326463392251904","lower": "1850313636052992000","count": 1562,"preSum": 62495 },{ "ndv": 972,"upper": "1850338940792340480","lower": "1850326481276764160","count": 1563,"preSum": 64057 },{ "ndv": 1005,"upper": "1850354048759234560","lower": "1850338942033854464","count": 1562,"preSum": 65620 },{ "ndv": 962,"upper": "1850366065406640128","lower": "1850354053993725952","count": 1563,"preSum": 67182 },{ "ndv": 968,"upper": "1850378032846471168","lower": "1850366074164346880","count": 1562,"preSum": 68745 },{ "ndv": 976,"upper": "1850390280918794240","lower": "1850378070209331200","count": 1562,"preSum": 70307 },{ "ndv": 990,"upper": "1850403330036072448","lower": "1850390285616414720","count": 1562,"preSum": 71869 },{ "ndv": 974,"upper": "1850419937953185792","lower": "1850403335538999296","count": 1562,"preSum": 73431 },{ "ndv": 1028,"upper": "1850432499725893632","lower": "1850419941459623936","count": 1563,"preSum": 74993 },{ "ndv": 974,"upper": "1850444275922239488","lower": "1850432503752425472","count": 1562,"preSum": 76556 },{ "ndv": 994,"upper": "1850457377787084800","lower": "1850444281592938496","count": 1564,"preSum": 78118 },{ "ndv": 993,"upper": "1850470384005021696","lower": "1850457397701640192","count": 1562,"preSum": 79682 },{ "ndv": 989,"upper": "1850482957035241472","lower": "1850470398617976832","count": 1562,"preSum": 81244 },{ "ndv": 992,"upper": "1850497236643872768","lower": "1850482970490568704","count": 1562,"preSum": 82806 },{ "ndv": 986,"upper": "1850509872588652544","lower": "1850497246324326400","count": 1562,"preSum": 84368 },{ "ndv": 998,"upper": "1850522829548683264","lower": "1850509874081824768","count": 1562,"preSum": 85930 },{ "ndv": 972,"upper": "1850535566777516032","lower": "1850522844815949824","count": 1562,"preSum": 87492 },{ "ndv": 971,"upper": "1850547688936833024","lower": "1850535569277321216","count": 1563,"preSum": 89054 },{ "ndv": 988,"upper": "1850564802838003712","lower": "1850547693215023104","count": 1562,"preSum": 90617 },{ "ndv": 987,"upper": "1850577718693855232","lower": "1850564811948032000","count": 1562,"preSum": 92179 },{ "ndv": 986,"upper": "1850590382069383168","lower": "1850577720438685696","count": 1562,"preSum": 93741 },{ "ndv": 1006,"upper": "1850602489129205760","lower": "1850590384569188352","count": 1563,"preSum": 95303 },{ "ndv": 973,"upper": "1850614653063790592","lower": "1850602496645398528","count": 1562,"preSum": 96866 },{ "ndv": 977,"upper": "1850627048289075200","lower": "1850614685896802304","count": 1522,"preSum": 98428 } ],"maxBucketSize": 64,"type": "Datetime","sampleRate": 0.90062594 }
+  cest_full_table_big.c_datetime.null_count:
+    0
+  cest_full_table_big.c_datetime.sample_rate:
+    0.010943651
+  cest_full_table_big.c_datetime_1.TOPN:
+    { "countArr": [ 7,8,7,7,8,7,7 ],"valueArr": [ 1849856379473362944,1849966883126640640,1850096458666082304,1850112028845277184,1850159979386896384,1850408374944923648,1850600075777015808 ],"type": "Datetime","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_datetime_1.cardinality:
+    515198
+  cest_full_table_big.c_datetime_1.histogram:
+    { "buckets": [ { "ndv": 988,"upper": "1849797349442846720","lower": "1849785388378357760","count": 1563,"preSum": 0 },{ "ndv": 994,"upper": "1849810007432888320","lower": "1849797352949284864","count": 1563,"preSum": 1563 },{ "ndv": 998,"upper": "1849822169907855360","lower": "1849810009664258048","count": 1562,"preSum": 3126 },{ "ndv": 993,"upper": "1849835987757170688","lower": "1849822185108013056","count": 1564,"preSum": 4688 },{ "ndv": 1004,"upper": "1849848516512317440","lower": "1849835990038872064","count": 1562,"preSum": 6252 },{ "ndv": 990,"upper": "1849863290562281472","lower": "1849848521394487296","count": 1562,"preSum": 7814 },{ "ndv": 976,"upper": "1849875556552671232","lower": "1849863306248978432","count": 1565,"preSum": 9376 },{ "ndv": 1011,"upper": "1849887891413532672","lower": "1849875561652944896","count": 1562,"preSum": 10941 },{ "ndv": 1007,"upper": "1849900578210054144","lower": "1849887894282436608","count": 1562,"preSum": 12503 },{ "ndv": 960,"upper": "1849912344541396992","lower": "1849900608560037888","count": 1562,"preSum": 14065 },{ "ndv": 1006,"upper": "1849934999990566912","lower": "1849912352191807488","count": 1562,"preSum": 15627 },{ "ndv": 989,"upper": "1849947243063279616","lower": "1849935035474378752","count": 1562,"preSum": 17189 },{ "ndv": 995,"upper": "1849960156536766464","lower": "1849947243667259392","count": 1562,"preSum": 18751 },{ "ndv": 996,"upper": "1849972736445644800","lower": "1849960173850853376","count": 1563,"preSum": 20313 },{ "ndv": 990,"upper": "1849985731322183680","lower": "1849972736663748608","count": 1563,"preSum": 21876 },{ "ndv": 1007,"upper": "1850000072838742016","lower": "1849985735147388928","count": 1562,"preSum": 23439 },{ "ndv": 984,"upper": "1850012695227531264","lower": "1850000073291726848","count": 1562,"preSum": 25001 },{ "ndv": 989,"upper": "1850025523472760832","lower": "1850012707474898944","count": 1562,"preSum": 26563 },{ "ndv": 961,"upper": "1850037400969936896","lower": "1850025536441548800","count": 1562,"preSum": 28125 },{ "ndv": 1022,"upper": "1850049990894813184","lower": "1850037414257491968","count": 1562,"preSum": 29687 },{ "ndv": 980,"upper": "1850067127914987520","lower": "1850049995558879232","count": 1562,"preSum": 31249 },{ "ndv": 959,"upper": "1850079478009561088","lower": "1850067137998094336","count": 1564,"preSum": 32811 },{ "ndv": 986,"upper": "1850092294141640704","lower": "1850080048921444352","count": 1562,"preSum": 34375 },{ "ndv": 969,"upper": "1850105086299078656","lower": "1850092315482259456","count": 1562,"preSum": 35937 },{ "ndv": 994,"upper": "1850118003564216320","lower": "1850105099469193216","count": 1562,"preSum": 37499 },{ "ndv": 970,"upper": "1850130906283507712","lower": "1850118004688289792","count": 1564,"preSum": 39061 },{ "ndv": 969,"upper": "1850145197317423104","lower": "1850130906535165952","count": 1562,"preSum": 40625 },{ "ndv": 990,"upper": "1850157220558274560","lower": "1850145197401309184","count": 1562,"preSum": 42187 },{ "ndv": 986,"upper": "1850169175700406272","lower": "1850157232872751104","count": 1562,"preSum": 43749 },{ "ndv": 985,"upper": "1850181877176991744","lower": "1850169189642272768","count": 1562,"preSum": 45311 },{ "ndv": 974,"upper": "1850193542475939840","lower": "1850181915093499904","count": 1562,"preSum": 46873 },{ "ndv": 991,"upper": "1850210275685302272","lower": "1850193559622254592","count": 1562,"preSum": 48435 },{ "ndv": 981,"upper": "1850223335640662016","lower": "1850210280517140480","count": 1562,"preSum": 49997 },{ "ndv": 962,"upper": "1850235437096894464","lower": "1850223338979328000","count": 1562,"preSum": 51559 },{ "ndv": 1005,"upper": "1850248266667524096","lower": "1850235446408249344","count": 1562,"preSum": 53121 },{ "ndv": 1005,"upper": "1850261234734071808","lower": "1850248286884069376","count": 1562,"preSum": 54683 },{ "ndv": 1017,"upper": "1850274085242667008","lower": "1850261236898332672","count": 1562,"preSum": 56245 },{ "ndv": 994,"upper": "1850288998493192192","lower": "1850274121951215616","count": 1564,"preSum": 57807 },{ "ndv": 971,"upper": "1850300960866304000","lower": "1850289004633653248","count": 1562,"preSum": 59371 },{ "ndv": 1023,"upper": "1850313627177844736","lower": "1850300970462871552","count": 1562,"preSum": 60933 },{ "ndv": 998,"upper": "1850326463392251904","lower": "1850313636052992000","count": 1562,"preSum": 62495 },{ "ndv": 972,"upper": "1850338940792340480","lower": "1850326481276764160","count": 1563,"preSum": 64057 },{ "ndv": 1005,"upper": "1850354048759234560","lower": "1850338942033854464","count": 1562,"preSum": 65620 },{ "ndv": 962,"upper": "1850366065406640128","lower": "1850354053993725952","count": 1563,"preSum": 67182 },{ "ndv": 968,"upper": "1850378032846471168","lower": "1850366074164346880","count": 1562,"preSum": 68745 },{ "ndv": 976,"upper": "1850390280918794240","lower": "1850378070209331200","count": 1562,"preSum": 70307 },{ "ndv": 990,"upper": "1850403330036072448","lower": "1850390285616414720","count": 1562,"preSum": 71869 },{ "ndv": 974,"upper": "1850419937953185792","lower": "1850403335538999296","count": 1562,"preSum": 73431 },{ "ndv": 1028,"upper": "1850432499725893632","lower": "1850419941459623936","count": 1563,"preSum": 74993 },{ "ndv": 974,"upper": "1850444275922239488","lower": "1850432503752425472","count": 1562,"preSum": 76556 },{ "ndv": 994,"upper": "1850457377787084800","lower": "1850444281592938496","count": 1564,"preSum": 78118 },{ "ndv": 993,"upper": "1850470384005021696","lower": "1850457397701640192","count": 1562,"preSum": 79682 },{ "ndv": 989,"upper": "1850482957035241472","lower": "1850470398617976832","count": 1562,"preSum": 81244 },{ "ndv": 992,"upper": "1850497236643872768","lower": "1850482970490568704","count": 1562,"preSum": 82806 },{ "ndv": 986,"upper": "1850509872588652544","lower": "1850497246324326400","count": 1562,"preSum": 84368 },{ "ndv": 998,"upper": "1850522829548683264","lower": "1850509874081824768","count": 1562,"preSum": 85930 },{ "ndv": 972,"upper": "1850535566777516032","lower": "1850522844815949824","count": 1562,"preSum": 87492 },{ "ndv": 971,"upper": "1850547688936833024","lower": "1850535569277321216","count": 1563,"preSum": 89054 },{ "ndv": 988,"upper": "1850564802838003712","lower": "1850547693215023104","count": 1562,"preSum": 90617 },{ "ndv": 987,"upper": "1850577718693855232","lower": "1850564811948032000","count": 1562,"preSum": 92179 },{ "ndv": 986,"upper": "1850590382069383168","lower": "1850577720438685696","count": 1562,"preSum": 93741 },{ "ndv": 1006,"upper": "1850602489129205760","lower": "1850590384569188352","count": 1563,"preSum": 95303 },{ "ndv": 973,"upper": "1850614653063790592","lower": "1850602496645398528","count": 1562,"preSum": 96866 },{ "ndv": 977,"upper": "1850627048289075200","lower": "1850614685896802304","count": 1522,"preSum": 98428 } ],"maxBucketSize": 64,"type": "Datetime","sampleRate": 0.90062594 }
+  cest_full_table_big.c_datetime_1.null_count:
+    0
+  cest_full_table_big.c_datetime_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_datetime_3.TOPN:
+    { "countArr": [ 7,8,7,7,8,7,7 ],"valueArr": [ 1849856379473362944,1849966883126640640,1850096458666082304,1850112028845277184,1850159979386896384,1850408374944923648,1850600075777015808 ],"type": "Datetime","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_datetime_3.cardinality:
+    515198
+  cest_full_table_big.c_datetime_3.histogram:
+    { "buckets": [ { "ndv": 988,"upper": "1849797349442846720","lower": "1849785388378357760","count": 1563,"preSum": 0 },{ "ndv": 994,"upper": "1849810007432888320","lower": "1849797352949284864","count": 1563,"preSum": 1563 },{ "ndv": 998,"upper": "1849822169907855360","lower": "1849810009664258048","count": 1562,"preSum": 3126 },{ "ndv": 993,"upper": "1849835987757170688","lower": "1849822185108013056","count": 1564,"preSum": 4688 },{ "ndv": 1004,"upper": "1849848516512317440","lower": "1849835990038872064","count": 1562,"preSum": 6252 },{ "ndv": 990,"upper": "1849863290562281472","lower": "1849848521394487296","count": 1562,"preSum": 7814 },{ "ndv": 976,"upper": "1849875556552671232","lower": "1849863306248978432","count": 1565,"preSum": 9376 },{ "ndv": 1011,"upper": "1849887891413532672","lower": "1849875561652944896","count": 1562,"preSum": 10941 },{ "ndv": 1007,"upper": "1849900578210054144","lower": "1849887894282436608","count": 1562,"preSum": 12503 },{ "ndv": 960,"upper": "1849912344541396992","lower": "1849900608560037888","count": 1562,"preSum": 14065 },{ "ndv": 1006,"upper": "1849934999990566912","lower": "1849912352191807488","count": 1562,"preSum": 15627 },{ "ndv": 989,"upper": "1849947243063279616","lower": "1849935035474378752","count": 1562,"preSum": 17189 },{ "ndv": 995,"upper": "1849960156536766464","lower": "1849947243667259392","count": 1562,"preSum": 18751 },{ "ndv": 996,"upper": "1849972736445644800","lower": "1849960173850853376","count": 1563,"preSum": 20313 },{ "ndv": 990,"upper": "1849985731322183680","lower": "1849972736663748608","count": 1563,"preSum": 21876 },{ "ndv": 1007,"upper": "1850000072838742016","lower": "1849985735147388928","count": 1562,"preSum": 23439 },{ "ndv": 984,"upper": "1850012695227531264","lower": "1850000073291726848","count": 1562,"preSum": 25001 },{ "ndv": 989,"upper": "1850025523472760832","lower": "1850012707474898944","count": 1562,"preSum": 26563 },{ "ndv": 961,"upper": "1850037400969936896","lower": "1850025536441548800","count": 1562,"preSum": 28125 },{ "ndv": 1022,"upper": "1850049990894813184","lower": "1850037414257491968","count": 1562,"preSum": 29687 },{ "ndv": 980,"upper": "1850067127914987520","lower": "1850049995558879232","count": 1562,"preSum": 31249 },{ "ndv": 959,"upper": "1850079478009561088","lower": "1850067137998094336","count": 1564,"preSum": 32811 },{ "ndv": 986,"upper": "1850092294141640704","lower": "1850080048921444352","count": 1562,"preSum": 34375 },{ "ndv": 969,"upper": "1850105086299078656","lower": "1850092315482259456","count": 1562,"preSum": 35937 },{ "ndv": 994,"upper": "1850118003564216320","lower": "1850105099469193216","count": 1562,"preSum": 37499 },{ "ndv": 970,"upper": "1850130906283507712","lower": "1850118004688289792","count": 1564,"preSum": 39061 },{ "ndv": 969,"upper": "1850145197317423104","lower": "1850130906535165952","count": 1562,"preSum": 40625 },{ "ndv": 990,"upper": "1850157220558274560","lower": "1850145197401309184","count": 1562,"preSum": 42187 },{ "ndv": 986,"upper": "1850169175700406272","lower": "1850157232872751104","count": 1562,"preSum": 43749 },{ "ndv": 985,"upper": "1850181877176991744","lower": "1850169189642272768","count": 1562,"preSum": 45311 },{ "ndv": 974,"upper": "1850193542475939840","lower": "1850181915093499904","count": 1562,"preSum": 46873 },{ "ndv": 991,"upper": "1850210275685302272","lower": "1850193559622254592","count": 1562,"preSum": 48435 },{ "ndv": 981,"upper": "1850223335640662016","lower": "1850210280517140480","count": 1562,"preSum": 49997 },{ "ndv": 962,"upper": "1850235437096894464","lower": "1850223338979328000","count": 1562,"preSum": 51559 },{ "ndv": 1005,"upper": "1850248266667524096","lower": "1850235446408249344","count": 1562,"preSum": 53121 },{ "ndv": 1005,"upper": "1850261234734071808","lower": "1850248286884069376","count": 1562,"preSum": 54683 },{ "ndv": 1017,"upper": "1850274085242667008","lower": "1850261236898332672","count": 1562,"preSum": 56245 },{ "ndv": 994,"upper": "1850288998493192192","lower": "1850274121951215616","count": 1564,"preSum": 57807 },{ "ndv": 971,"upper": "1850300960866304000","lower": "1850289004633653248","count": 1562,"preSum": 59371 },{ "ndv": 1023,"upper": "1850313627177844736","lower": "1850300970462871552","count": 1562,"preSum": 60933 },{ "ndv": 998,"upper": "1850326463392251904","lower": "1850313636052992000","count": 1562,"preSum": 62495 },{ "ndv": 972,"upper": "1850338940792340480","lower": "1850326481276764160","count": 1563,"preSum": 64057 },{ "ndv": 1005,"upper": "1850354048759234560","lower": "1850338942033854464","count": 1562,"preSum": 65620 },{ "ndv": 962,"upper": "1850366065406640128","lower": "1850354053993725952","count": 1563,"preSum": 67182 },{ "ndv": 968,"upper": "1850378032846471168","lower": "1850366074164346880","count": 1562,"preSum": 68745 },{ "ndv": 976,"upper": "1850390280918794240","lower": "1850378070209331200","count": 1562,"preSum": 70307 },{ "ndv": 990,"upper": "1850403330036072448","lower": "1850390285616414720","count": 1562,"preSum": 71869 },{ "ndv": 974,"upper": "1850419937953185792","lower": "1850403335538999296","count": 1562,"preSum": 73431 },{ "ndv": 1028,"upper": "1850432499725893632","lower": "1850419941459623936","count": 1563,"preSum": 74993 },{ "ndv": 974,"upper": "1850444275922239488","lower": "1850432503752425472","count": 1562,"preSum": 76556 },{ "ndv": 994,"upper": "1850457377787084800","lower": "1850444281592938496","count": 1564,"preSum": 78118 },{ "ndv": 993,"upper": "1850470384005021696","lower": "1850457397701640192","count": 1562,"preSum": 79682 },{ "ndv": 989,"upper": "1850482957035241472","lower": "1850470398617976832","count": 1562,"preSum": 81244 },{ "ndv": 992,"upper": "1850497236643872768","lower": "1850482970490568704","count": 1562,"preSum": 82806 },{ "ndv": 986,"upper": "1850509872588652544","lower": "1850497246324326400","count": 1562,"preSum": 84368 },{ "ndv": 998,"upper": "1850522829548683264","lower": "1850509874081824768","count": 1562,"preSum": 85930 },{ "ndv": 972,"upper": "1850535566777516032","lower": "1850522844815949824","count": 1562,"preSum": 87492 },{ "ndv": 971,"upper": "1850547688936833024","lower": "1850535569277321216","count": 1563,"preSum": 89054 },{ "ndv": 988,"upper": "1850564802838003712","lower": "1850547693215023104","count": 1562,"preSum": 90617 },{ "ndv": 987,"upper": "1850577718693855232","lower": "1850564811948032000","count": 1562,"preSum": 92179 },{ "ndv": 986,"upper": "1850590382069383168","lower": "1850577720438685696","count": 1562,"preSum": 93741 },{ "ndv": 1006,"upper": "1850602489129205760","lower": "1850590384569188352","count": 1563,"preSum": 95303 },{ "ndv": 973,"upper": "1850614653063790592","lower": "1850602496645398528","count": 1562,"preSum": 96866 },{ "ndv": 977,"upper": "1850627048289075200","lower": "1850614685896802304","count": 1522,"preSum": 98428 } ],"maxBucketSize": 64,"type": "Datetime","sampleRate": 0.90062594 }
+  cest_full_table_big.c_datetime_3.null_count:
+    0
+  cest_full_table_big.c_datetime_3.sample_rate:
+    0.010943651
+  cest_full_table_big.c_datetime_6.TOPN:
+    { "countArr": [ 7,8,7,7,8,7,7 ],"valueArr": [ 1849856379473362944,1849966883126640640,1850096458666082304,1850112028845277184,1850159979386896384,1850408374944923648,1850600075777015808 ],"type": "Datetime","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_datetime_6.cardinality:
+    515198
+  cest_full_table_big.c_datetime_6.histogram:
+    { "buckets": [ { "ndv": 988,"upper": "1849797349442846720","lower": "1849785388378357760","count": 1563,"preSum": 0 },{ "ndv": 994,"upper": "1849810007432888320","lower": "1849797352949284864","count": 1563,"preSum": 1563 },{ "ndv": 998,"upper": "1849822169907855360","lower": "1849810009664258048","count": 1562,"preSum": 3126 },{ "ndv": 993,"upper": "1849835987757170688","lower": "1849822185108013056","count": 1564,"preSum": 4688 },{ "ndv": 1004,"upper": "1849848516512317440","lower": "1849835990038872064","count": 1562,"preSum": 6252 },{ "ndv": 990,"upper": "1849863290562281472","lower": "1849848521394487296","count": 1562,"preSum": 7814 },{ "ndv": 976,"upper": "1849875556552671232","lower": "1849863306248978432","count": 1565,"preSum": 9376 },{ "ndv": 1011,"upper": "1849887891413532672","lower": "1849875561652944896","count": 1562,"preSum": 10941 },{ "ndv": 1007,"upper": "1849900578210054144","lower": "1849887894282436608","count": 1562,"preSum": 12503 },{ "ndv": 960,"upper": "1849912344541396992","lower": "1849900608560037888","count": 1562,"preSum": 14065 },{ "ndv": 1006,"upper": "1849934999990566912","lower": "1849912352191807488","count": 1562,"preSum": 15627 },{ "ndv": 989,"upper": "1849947243063279616","lower": "1849935035474378752","count": 1562,"preSum": 17189 },{ "ndv": 995,"upper": "1849960156536766464","lower": "1849947243667259392","count": 1562,"preSum": 18751 },{ "ndv": 996,"upper": "1849972736445644800","lower": "1849960173850853376","count": 1563,"preSum": 20313 },{ "ndv": 990,"upper": "1849985731322183680","lower": "1849972736663748608","count": 1563,"preSum": 21876 },{ "ndv": 1007,"upper": "1850000072838742016","lower": "1849985735147388928","count": 1562,"preSum": 23439 },{ "ndv": 984,"upper": "1850012695227531264","lower": "1850000073291726848","count": 1562,"preSum": 25001 },{ "ndv": 989,"upper": "1850025523472760832","lower": "1850012707474898944","count": 1562,"preSum": 26563 },{ "ndv": 961,"upper": "1850037400969936896","lower": "1850025536441548800","count": 1562,"preSum": 28125 },{ "ndv": 1022,"upper": "1850049990894813184","lower": "1850037414257491968","count": 1562,"preSum": 29687 },{ "ndv": 980,"upper": "1850067127914987520","lower": "1850049995558879232","count": 1562,"preSum": 31249 },{ "ndv": 959,"upper": "1850079478009561088","lower": "1850067137998094336","count": 1564,"preSum": 32811 },{ "ndv": 986,"upper": "1850092294141640704","lower": "1850080048921444352","count": 1562,"preSum": 34375 },{ "ndv": 969,"upper": "1850105086299078656","lower": "1850092315482259456","count": 1562,"preSum": 35937 },{ "ndv": 994,"upper": "1850118003564216320","lower": "1850105099469193216","count": 1562,"preSum": 37499 },{ "ndv": 970,"upper": "1850130906283507712","lower": "1850118004688289792","count": 1564,"preSum": 39061 },{ "ndv": 969,"upper": "1850145197317423104","lower": "1850130906535165952","count": 1562,"preSum": 40625 },{ "ndv": 990,"upper": "1850157220558274560","lower": "1850145197401309184","count": 1562,"preSum": 42187 },{ "ndv": 986,"upper": "1850169175700406272","lower": "1850157232872751104","count": 1562,"preSum": 43749 },{ "ndv": 985,"upper": "1850181877176991744","lower": "1850169189642272768","count": 1562,"preSum": 45311 },{ "ndv": 974,"upper": "1850193542475939840","lower": "1850181915093499904","count": 1562,"preSum": 46873 },{ "ndv": 991,"upper": "1850210275685302272","lower": "1850193559622254592","count": 1562,"preSum": 48435 },{ "ndv": 981,"upper": "1850223335640662016","lower": "1850210280517140480","count": 1562,"preSum": 49997 },{ "ndv": 962,"upper": "1850235437096894464","lower": "1850223338979328000","count": 1562,"preSum": 51559 },{ "ndv": 1005,"upper": "1850248266667524096","lower": "1850235446408249344","count": 1562,"preSum": 53121 },{ "ndv": 1005,"upper": "1850261234734071808","lower": "1850248286884069376","count": 1562,"preSum": 54683 },{ "ndv": 1017,"upper": "1850274085242667008","lower": "1850261236898332672","count": 1562,"preSum": 56245 },{ "ndv": 994,"upper": "1850288998493192192","lower": "1850274121951215616","count": 1564,"preSum": 57807 },{ "ndv": 971,"upper": "1850300960866304000","lower": "1850289004633653248","count": 1562,"preSum": 59371 },{ "ndv": 1023,"upper": "1850313627177844736","lower": "1850300970462871552","count": 1562,"preSum": 60933 },{ "ndv": 998,"upper": "1850326463392251904","lower": "1850313636052992000","count": 1562,"preSum": 62495 },{ "ndv": 972,"upper": "1850338940792340480","lower": "1850326481276764160","count": 1563,"preSum": 64057 },{ "ndv": 1005,"upper": "1850354048759234560","lower": "1850338942033854464","count": 1562,"preSum": 65620 },{ "ndv": 962,"upper": "1850366065406640128","lower": "1850354053993725952","count": 1563,"preSum": 67182 },{ "ndv": 968,"upper": "1850378032846471168","lower": "1850366074164346880","count": 1562,"preSum": 68745 },{ "ndv": 976,"upper": "1850390280918794240","lower": "1850378070209331200","count": 1562,"preSum": 70307 },{ "ndv": 990,"upper": "1850403330036072448","lower": "1850390285616414720","count": 1562,"preSum": 71869 },{ "ndv": 974,"upper": "1850419937953185792","lower": "1850403335538999296","count": 1562,"preSum": 73431 },{ "ndv": 1028,"upper": "1850432499725893632","lower": "1850419941459623936","count": 1563,"preSum": 74993 },{ "ndv": 974,"upper": "1850444275922239488","lower": "1850432503752425472","count": 1562,"preSum": 76556 },{ "ndv": 994,"upper": "1850457377787084800","lower": "1850444281592938496","count": 1564,"preSum": 78118 },{ "ndv": 993,"upper": "1850470384005021696","lower": "1850457397701640192","count": 1562,"preSum": 79682 },{ "ndv": 989,"upper": "1850482957035241472","lower": "1850470398617976832","count": 1562,"preSum": 81244 },{ "ndv": 992,"upper": "1850497236643872768","lower": "1850482970490568704","count": 1562,"preSum": 82806 },{ "ndv": 986,"upper": "1850509872588652544","lower": "1850497246324326400","count": 1562,"preSum": 84368 },{ "ndv": 998,"upper": "1850522829548683264","lower": "1850509874081824768","count": 1562,"preSum": 85930 },{ "ndv": 972,"upper": "1850535566777516032","lower": "1850522844815949824","count": 1562,"preSum": 87492 },{ "ndv": 971,"upper": "1850547688936833024","lower": "1850535569277321216","count": 1563,"preSum": 89054 },{ "ndv": 988,"upper": "1850564802838003712","lower": "1850547693215023104","count": 1562,"preSum": 90617 },{ "ndv": 987,"upper": "1850577718693855232","lower": "1850564811948032000","count": 1562,"preSum": 92179 },{ "ndv": 986,"upper": "1850590382069383168","lower": "1850577720438685696","count": 1562,"preSum": 93741 },{ "ndv": 1006,"upper": "1850602489129205760","lower": "1850590384569188352","count": 1563,"preSum": 95303 },{ "ndv": 973,"upper": "1850614653063790592","lower": "1850602496645398528","count": 1562,"preSum": 96866 },{ "ndv": 977,"upper": "1850627048289075200","lower": "1850614685896802304","count": 1522,"preSum": 98428 } ],"maxBucketSize": 64,"type": "Datetime","sampleRate": 0.90062594 }
+  cest_full_table_big.c_datetime_6.null_count:
+    0
+  cest_full_table_big.c_datetime_6.sample_rate:
+    0.010943651
+  cest_full_table_big.c_decimal.TOPN:
+    { "countArr": [ 8,9,8,7,7,7,8 ],"valueArr": [ -3161637812,-2338453878,2761250206,4794313941,4985089198,9211629936,9396373784 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_decimal.cardinality:
+    513404
+  cest_full_table_big.c_decimal.histogram:
+    { "buckets": [ { "ndv": 979,"upper": -9687155776,"lower": -9999947084,"count": 1564,"preSum": 0 },{ "ndv": 966,"upper": -9387009540,"lower": -9687058700,"count": 1562,"preSum": 1564 },{ "ndv": 969,"upper": -9074381923,"lower": -9386696920,"count": 1562,"preSum": 3126 },{ "ndv": 981,"upper": -8771714857,"lower": -9074360681,"count": 1562,"preSum": 4688 },{ "ndv": 994,"upper": -8452531843,"lower": -8771397797,"count": 1562,"preSum": 6250 },{ "ndv": 983,"upper": -8134112376,"lower": -8452198570,"count": 1563,"preSum": 7812 },{ "ndv": 982,"upper": -7813532690,"lower": -8133170724,"count": 1563,"preSum": 9375 },{ "ndv": 1007,"upper": -7480104096,"lower": -7813027807,"count": 1562,"preSum": 10938 },{ "ndv": 992,"upper": -7173906190,"lower": -7479661468,"count": 1562,"preSum": 12500 },{ "ndv": 1008,"upper": -6846432644,"lower": -7173396952,"count": 1564,"preSum": 14062 },{ "ndv": 958,"upper": -6548406963,"lower": -6846149635,"count": 1563,"preSum": 15626 },{ "ndv": 995,"upper": -6243151080,"lower": -6548248992,"count": 1563,"preSum": 17189 },{ "ndv": 1010,"upper": -5941574866,"lower": -6242814299,"count": 1563,"preSum": 18752 },{ "ndv": 973,"upper": -5620422904,"lower": -5941469150,"count": 1562,"preSum": 20315 },{ "ndv": 994,"upper": -5297157054,"lower": -5620268272,"count": 1562,"preSum": 21877 },{ "ndv": 986,"upper": -4995542508,"lower": -5297020067,"count": 1563,"preSum": 23439 },{ "ndv": 982,"upper": -4686876573,"lower": -4995130422,"count": 1563,"preSum": 25002 },{ "ndv": 980,"upper": -4364186451,"lower": -4685947583,"count": 1562,"preSum": 26565 },{ "ndv": 978,"upper": -4047621091,"lower": -4363387676,"count": 1562,"preSum": 28127 },{ "ndv": 960,"upper": -3744861812,"lower": -4047498413,"count": 1562,"preSum": 29689 },{ "ndv": 1005,"upper": -3419877589,"lower": -3744361330,"count": 1564,"preSum": 31251 },{ "ndv": 965,"upper": -3117911334,"lower": -3419837746,"count": 1563,"preSum": 32815 },{ "ndv": 999,"upper": -2801900157,"lower": -3117649944,"count": 1562,"preSum": 34378 },{ "ndv": 991,"upper": -2492832347,"lower": -2801528498,"count": 1562,"preSum": 35940 },{ "ndv": 991,"upper": -2177734926,"lower": -2492532666,"count": 1562,"preSum": 37502 },{ "ndv": 1014,"upper": -1861156575,"lower": -2177661031,"count": 1563,"preSum": 39064 },{ "ndv": 1011,"upper": -1534527933,"lower": -1860715408,"count": 1562,"preSum": 40627 },{ "ndv": 978,"upper": -1229701813,"lower": -1534419842,"count": 1562,"preSum": 42189 },{ "ndv": 953,"upper": -932502951,"lower": -1229489935,"count": 1562,"preSum": 43751 },{ "ndv": 992,"upper": -614271098,"lower": -932126004,"count": 1562,"preSum": 45313 },{ "ndv": 975,"upper": -300381404,"lower": -613275464,"count": 1563,"preSum": 46875 },{ "ndv": 999,"upper": 18832841,"lower": -300259505,"count": 1562,"preSum": 48438 },{ "ndv": 965,"upper": 337975912,"lower": 18865885,"count": 1562,"preSum": 50000 },{ "ndv": 1007,"upper": 665449719,"lower": 338194274,"count": 1562,"preSum": 51562 },{ "ndv": 1003,"upper": 974574942,"lower": 665902670,"count": 1562,"preSum": 53124 },{ "ndv": 943,"upper": 1265231376,"lower": 974635572,"count": 1563,"preSum": 54686 },{ "ndv": 975,"upper": 1571632351,"lower": 1265917720,"count": 1562,"preSum": 56249 },{ "ndv": 981,"upper": 1875185000,"lower": 1571785457,"count": 1562,"preSum": 57811 },{ "ndv": 989,"upper": 2197245103,"lower": 1875301292,"count": 1564,"preSum": 59373 },{ "ndv": 993,"upper": 2515308936,"lower": 2197562867,"count": 1562,"preSum": 60937 },{ "ndv": 986,"upper": 2837273069,"lower": 2516093763,"count": 1562,"preSum": 62499 },{ "ndv": 994,"upper": 3147598748,"lower": 2837284756,"count": 1562,"preSum": 64061 },{ "ndv": 972,"upper": 3451064745,"lower": 3147603468,"count": 1562,"preSum": 65623 },{ "ndv": 968,"upper": 3763307089,"lower": 3451392751,"count": 1563,"preSum": 67185 },{ "ndv": 987,"upper": 4081448171,"lower": 3763887359,"count": 1562,"preSum": 68748 },{ "ndv": 1016,"upper": 4413998253,"lower": 4081846339,"count": 1562,"preSum": 70310 },{ "ndv": 985,"upper": 4716613047,"lower": 4414562394,"count": 1562,"preSum": 71872 },{ "ndv": 987,"upper": 5031329080,"lower": 4716718911,"count": 1562,"preSum": 73434 },{ "ndv": 982,"upper": 5363093185,"lower": 5031338352,"count": 1563,"preSum": 74996 },{ "ndv": 973,"upper": 5677889496,"lower": 5363184935,"count": 1562,"preSum": 76559 },{ "ndv": 1004,"upper": 5989660023,"lower": 5678200705,"count": 1562,"preSum": 78121 },{ "ndv": 977,"upper": 6287839524,"lower": 5989760776,"count": 1562,"preSum": 79683 },{ "ndv": 963,"upper": 6594007466,"lower": 6288155489,"count": 1562,"preSum": 81245 },{ "ndv": 972,"upper": 6907327360,"lower": 6594052884,"count": 1563,"preSum": 82807 },{ "ndv": 976,"upper": 7213171688,"lower": 6908357525,"count": 1563,"preSum": 84370 },{ "ndv": 969,"upper": 7518062598,"lower": 7213464031,"count": 1562,"preSum": 85933 },{ "ndv": 1004,"upper": 7841327765,"lower": 7518240655,"count": 1563,"preSum": 87495 },{ "ndv": 968,"upper": 8148806019,"lower": 7841638007,"count": 1562,"preSum": 89058 },{ "ndv": 980,"upper": 8469742895,"lower": 8149425222,"count": 1562,"preSum": 90620 },{ "ndv": 972,"upper": 8777957541,"lower": 8469853449,"count": 1563,"preSum": 92182 },{ "ndv": 1002,"upper": 9083831652,"lower": 8779382880,"count": 1562,"preSum": 93745 },{ "ndv": 975,"upper": 9389817052,"lower": 9084054191,"count": 1562,"preSum": 95307 },{ "ndv": 998,"upper": 9696105680,"lower": 9390001677,"count": 1563,"preSum": 96869 },{ "ndv": 960,"upper": 9999769928,"lower": 9696234677,"count": 1515,"preSum": 98432 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_decimal.null_count:
+    0
+  cest_full_table_big.c_decimal.sample_rate:
+    0.010943651
+  cest_full_table_big.c_decimal_pr.TOPN:
+    { "countArr": [ 7,7,7,8,7,7,7,7,8,7,7,7 ],"valueArr": [ -75761368346928600000000000000000000.000000000000000000000000000000,-34966276527066760000000000000000000.000000000000000000000000000000,-21432670686651130000000000000000000.000000000000000000000000000000,-13125128156279190000000000000000000.000000000000000000000000000000,-11477993890510120000000000000000000.000000000000000000000000000000,-10099048338993650000000000000000000.000000000000000000000000000000,-8356233796409413000000000000000000.000000000000000000000000000000,30870071669858136000000000000000000.000000000000000000000000000000,31740144295914382000000000000000000.000000000000000000000000000000,63269113195223930000000000000000000.000000000000000000000000000000,64030190359573910000000000000000000.000000000000000000000000000000,96568383584898280000000000000000000.000000000000000000000000000000 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_decimal_pr.cardinality:
+    515051
+  cest_full_table_big.c_decimal_pr.histogram:
+    { "buckets": [ { "ndv": 993,"upper": -96764760248984260000000000000000000.000000000000000000000000000000,"lower": -99999470851927990000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 0 },{ "ndv": 974,"upper": -93804787163083860000000000000000000.000000000000000000000000000000,"lower": -96761703454929480000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 1562 },{ "ndv": 975,"upper": -90703672605533540000000000000000000.000000000000000000000000000000,"lower": -93803234355070480000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 3124 },{ "ndv": 1004,"upper": -87610692065699920000000000000000000.000000000000000000000000000000,"lower": -90702475778546280000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 4687 },{ "ndv": 1007,"upper": -84392001962304410000000000000000000.000000000000000000000000000000,"lower": -87609035883403950000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 6249 },{ "ndv": 1002,"upper": -81140807947839370000000000000000000.000000000000000000000000000000,"lower": -84388163109519000000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 7811 },{ "ndv": 990,"upper": -77855755190734450000000000000000000.000000000000000000000000000000,"lower": -81128022206230505000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 9375 },{ "ndv": 982,"upper": -74702356738829845000000000000000000.000000000000000000000000000000,"lower": -77855675578527520000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 10938 },{ "ndv": 955,"upper": -71731668161870890000000000000000000.000000000000000000000000000000,"lower": -74699687726076200000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 12500 },{ "ndv": 994,"upper": -68475108907170895000000000000000000.000000000000000000000000000000,"lower": -71727226843110515000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 14063 },{ "ndv": 991,"upper": -65326503654777840000000000000000000.000000000000000000000000000000,"lower": -68475070280057480000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 15626 },{ "ndv": 1001,"upper": -62331277771692280000000000000000000.000000000000000000000000000000,"lower": -65322651104484510000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 17188 },{ "ndv": 999,"upper": -59253213734725300000000000000000000.000000000000000000000000000000,"lower": -62330281584613620000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 18752 },{ "ndv": 1008,"upper": -56044631802295880000000000000000000.000000000000000000000000000000,"lower": -59252261364557940000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 20314 },{ "ndv": 1010,"upper": -52814432683893570000000000000000000.000000000000000000000000000000,"lower": -56044169472641150000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 21876 },{ "ndv": 983,"upper": -49635397736884590000000000000000000.000000000000000000000000000000,"lower": -52814311404538600000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 23438 },{ "ndv": 994,"upper": -46313839997966160000000000000000000.000000000000000000000000000000,"lower": -49630307794800680000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 25001 },{ "ndv": 971,"upper": -43217909076822320000000000000000000.000000000000000000000000000000,"lower": -46308399922183560000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 26564 },{ "ndv": 1001,"upper": -40014754300594737000000000000000000.000000000000000000000000000000,"lower": -43213231634298700000000000000000000.000000000000000000000000000000,"count": 1565,"preSum": 28126 },{ "ndv": 984,"upper": -36968613426251330000000000000000000.000000000000000000000000000000,"lower": -40013854845576490000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 29691 },{ "ndv": 996,"upper": -33794274180256955000000000000000000.000000000000000000000000000000,"lower": -36960861221231900000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 31254 },{ "ndv": 974,"upper": -30701228922008240000000000000000000.000000000000000000000000000000,"lower": -33791958828386238000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 32816 },{ "ndv": 979,"upper": -27447343436703160000000000000000000.000000000000000000000000000000,"lower": -30696198399764984000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 34378 },{ "ndv": 991,"upper": -24381195704457823000000000000000000.000000000000000000000000000000,"lower": -27446506902191150000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 35940 },{ "ndv": 962,"upper": -21362266818647366000000000000000000.000000000000000000000000000000,"lower": -24379199415851268000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 37502 },{ "ndv": 996,"upper": -18251458819185501000000000000000000.000000000000000000000000000000,"lower": -21361865771311275000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 39064 },{ "ndv": 981,"upper": -15043190548683188000000000000000000.000000000000000000000000000000,"lower": -18250455261974796000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 40626 },{ "ndv": 965,"upper": -12061693407409863000000000000000000.000000000000000000000000000000,"lower": -15041988462860400000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 42188 },{ "ndv": 981,"upper": -9048310149931673000000000000000000.000000000000000000000000000000,"lower": -12056613831847590000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 43751 },{ "ndv": 970,"upper": -5967322532621562000000000000000000.000000000000000000000000000000,"lower": -9046237716838896000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 45313 },{ "ndv": 1007,"upper": -2919916448995425600000000000000000.000000000000000000000000000000,"lower": -5966752358488224000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 46875 },{ "ndv": 989,"upper": 228129686512528060000000000000000.000000000000000000000000000000,"lower": -2915119805609480400000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 48437 },{ "ndv": 979,"upper": 3413396390386313400000000000000000.000000000000000000000000000000,"lower": 230187624771446120000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 50000 },{ "ndv": 959,"upper": 6649808345010481000000000000000000.000000000000000000000000000000,"lower": 3425654210272463500000000000000000.000000000000000000000000000000,"count": 1565,"preSum": 51563 },{ "ndv": 986,"upper": 9719505641315776000000000000000000.000000000000000000000000000000,"lower": 6653972599633518000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 53128 },{ "ndv": 966,"upper": 12885142964243597000000000000000000.000000000000000000000000000000,"lower": 9721949549579901000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 54690 },{ "ndv": 992,"upper": 15918120791954309000000000000000000.000000000000000000000000000000,"lower": 12889264768915870000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 56253 },{ "ndv": 1020,"upper": 18983388834533566000000000000000000.000000000000000000000000000000,"lower": 15918765700076414000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 57815 },{ "ndv": 998,"upper": 22249861368062440000000000000000000.000000000000000000000000000000,"lower": 18991173167423447000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 59379 },{ "ndv": 976,"upper": 25270796353303115000000000000000000.000000000000000000000000000000,"lower": 22254600390718250000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 60941 },{ "ndv": 969,"upper": 28440262055333450000000000000000000.000000000000000000000000000000,"lower": 25275601950143930000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 62503 },{ "ndv": 1021,"upper": 31633982760932696000000000000000000.000000000000000000000000000000,"lower": 28440774888748122000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 64066 },{ "ndv": 974,"upper": 34677804526956190000000000000000000.000000000000000000000000000000,"lower": 31634388633217940000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 65628 },{ "ndv": 988,"upper": 37738250878196130000000000000000000.000000000000000000000000000000,"lower": 34679982243149920000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 67190 },{ "ndv": 996,"upper": 40887364483041470000000000000000000.000000000000000000000000000000,"lower": 37741610955565540000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 68752 },{ "ndv": 987,"upper": 44049083830563690000000000000000000.000000000000000000000000000000,"lower": 40892341414678855000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 70314 },{ "ndv": 980,"upper": 47235497745549170000000000000000000.000000000000000000000000000000,"lower": 44049937406698890000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 71876 },{ "ndv": 998,"upper": 50329130476583295000000000000000000.000000000000000000000000000000,"lower": 47237496208773160000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 73439 },{ "ndv": 963,"upper": 53580622920766525000000000000000000.000000000000000000000000000000,"lower": 50330104888326540000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 75002 },{ "ndv": 1014,"upper": 56760007036575375000000000000000000.000000000000000000000000000000,"lower": 53586353827825520000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 76564 },{ "ndv": 997,"upper": 59716685383194960000000000000000000.000000000000000000000000000000,"lower": 56763671287478610000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 78127 },{ "ndv": 967,"upper": 62789399633927270000000000000000000.000000000000000000000000000000,"lower": 59717024548634790000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 79689 },{ "ndv": 992,"upper": 65865496876144730000000000000000000.000000000000000000000000000000,"lower": 62791640305228830000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 81251 },{ "ndv": 992,"upper": 68951981803271280000000000000000000.000000000000000000000000000000,"lower": 65867203350094750000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 82815 },{ "ndv": 1006,"upper": 72101857669478700000000000000000000.000000000000000000000000000000,"lower": 68955555252929870000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 84377 },{ "ndv": 978,"upper": 75238866718773990000000000000000000.000000000000000000000000000000,"lower": 72102218238260540000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 85941 },{ "ndv": 989,"upper": 78439709896384835000000000000000000.000000000000000000000000000000,"lower": 75239335741185000000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 87505 },{ "ndv": 948,"upper": 81368581999259250000000000000000000.000000000000000000000000000000,"lower": 78446555956882450000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 89067 },{ "ndv": 1015,"upper": 84624953753426320000000000000000000.000000000000000000000000000000,"lower": 81370115974721590000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 90630 },{ "ndv": 976,"upper": 87821666896224470000000000000000000.000000000000000000000000000000,"lower": 84629494107429300000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 92192 },{ "ndv": 985,"upper": 90840541919112480000000000000000000.000000000000000000000000000000,"lower": 87822866551836360000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 93754 },{ "ndv": 1010,"upper": 93960951017907040000000000000000000.000000000000000000000000000000,"lower": 90841263590764140000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 95316 },{ "ndv": 1029,"upper": 97096949982376130000000000000000000.000000000000000000000000000000,"lower": 93963737850341840000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 96879 },{ "ndv": 915,"upper": 99995669049052540000000000000000000.000000000000000000000000000000,"lower": 97107137834917060000000000000000000.000000000000000000000000000000,"count": 1474,"preSum": 98441 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_decimal_pr.null_count:
+    0
+  cest_full_table_big.c_decimal_pr.sample_rate:
+    0.010943651
+  cest_full_table_big.c_double.TOPN:
+    { "countArr": [ 7,7,7,7,7,8,7,7,7,7,7 ],"valueArr": [ 1.8033788670816908E307,2.2899803125719695E307,2.7689427755292624E307,3.3082804620162163E307,4.1423139809431574E307,4.324383600297211E307,5.843728541219235E307,5.945158417129865E307,1.1567488646249857E308,1.2083505338264966E308,1.305120637062738E308 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_double.cardinality:
+    513331
+  cest_full_table_big.c_double.histogram:
+    { "buckets": [ { "ndv": 979,"upper": 2.8915727853583585E306,"lower": 4.756229282033632E302,"count": 1562,"preSum": 0 },{ "ndv": 1012,"upper": 5.802923817060523E306,"lower": 2.900326993377809E306,"count": 1564,"preSum": 1562 },{ "ndv": 1008,"upper": 8.771023244366165E306,"lower": 5.807824712517648E306,"count": 1565,"preSum": 3126 },{ "ndv": 987,"upper": 1.1668980982078657E307,"lower": 8.774290405283191E306,"count": 1562,"preSum": 4691 },{ "ndv": 991,"upper": 1.4381202591495974E307,"lower": 1.16694501740653E307,"count": 1563,"preSum": 6253 },{ "ndv": 981,"upper": 1.721513265437389E307,"lower": 1.4389073269828172E307,"count": 1563,"preSum": 7816 },{ "ndv": 977,"upper": 2.0156194609916194E307,"lower": 1.7217224049904065E307,"count": 1562,"preSum": 9379 },{ "ndv": 1000,"upper": 2.3116005320726376E307,"lower": 2.0157410466959296E307,"count": 1563,"preSum": 10941 },{ "ndv": 970,"upper": 2.5909193845642066E307,"lower": 2.3116058793833675E307,"count": 1562,"preSum": 12504 },{ "ndv": 963,"upper": 2.8646972152127453E307,"lower": 2.591252504806782E307,"count": 1563,"preSum": 14066 },{ "ndv": 970,"upper": 3.134452127665627E307,"lower": 2.8650264852350487E307,"count": 1563,"preSum": 15629 },{ "ndv": 971,"upper": 3.403946804568662E307,"lower": 3.13473430277891E307,"count": 1562,"preSum": 17192 },{ "ndv": 1009,"upper": 3.6824117619673936E307,"lower": 3.4041223232046506E307,"count": 1562,"preSum": 18754 },{ "ndv": 986,"upper": 3.973959770822522E307,"lower": 3.682439354788304E307,"count": 1562,"preSum": 20316 },{ "ndv": 964,"upper": 4.2512942787207503E307,"lower": 3.974996470162016E307,"count": 1564,"preSum": 21878 },{ "ndv": 998,"upper": 4.533391414381247E307,"lower": 4.25175785998827E307,"count": 1562,"preSum": 23442 },{ "ndv": 992,"upper": 4.835077685244063E307,"lower": 4.533503960675152E307,"count": 1564,"preSum": 25004 },{ "ndv": 948,"upper": 5.114725922071461E307,"lower": 4.835621719862478E307,"count": 1563,"preSum": 26568 },{ "ndv": 975,"upper": 5.397186698761041E307,"lower": 5.115174776166815E307,"count": 1564,"preSum": 28131 },{ "ndv": 991,"upper": 5.676347253293591E307,"lower": 5.397690822080555E307,"count": 1564,"preSum": 29695 },{ "ndv": 1001,"upper": 5.964754460785259E307,"lower": 5.67704765259023E307,"count": 1562,"preSum": 31259 },{ "ndv": 990,"upper": 6.238529793184719E307,"lower": 5.964843662137904E307,"count": 1562,"preSum": 32821 },{ "ndv": 967,"upper": 6.529150476162594E307,"lower": 6.238929851968796E307,"count": 1564,"preSum": 34383 },{ "ndv": 1020,"upper": 6.81481713002287E307,"lower": 6.529769871550759E307,"count": 1562,"preSum": 35947 },{ "ndv": 998,"upper": 7.095776740971467E307,"lower": 6.815562346553893E307,"count": 1562,"preSum": 37509 },{ "ndv": 993,"upper": 7.376977549538845E307,"lower": 7.095939880766819E307,"count": 1562,"preSum": 39071 },{ "ndv": 996,"upper": 7.669324957047895E307,"lower": 7.376986334883062E307,"count": 1563,"preSum": 40633 },{ "ndv": 986,"upper": 7.952223685190678E307,"lower": 7.669877724135277E307,"count": 1562,"preSum": 42196 },{ "ndv": 1026,"upper": 8.243335013856233E307,"lower": 7.952391722688576E307,"count": 1563,"preSum": 43758 },{ "ndv": 959,"upper": 8.5193481560909E307,"lower": 8.243794535832331E307,"count": 1562,"preSum": 45321 },{ "ndv": 990,"upper": 8.801366577028062E307,"lower": 8.519388571905995E307,"count": 1563,"preSum": 46883 },{ "ndv": 979,"upper": 9.072012020157078E307,"lower": 8.801528047871531E307,"count": 1562,"preSum": 48446 },{ "ndv": 975,"upper": 9.35662485951967E307,"lower": 9.072027225791882E307,"count": 1562,"preSum": 50008 },{ "ndv": 988,"upper": 9.63090758795388E307,"lower": 9.356727773783428E307,"count": 1564,"preSum": 51570 },{ "ndv": 995,"upper": 9.897210003498544E307,"lower": 9.63135072499096E307,"count": 1563,"preSum": 53134 },{ "ndv": 967,"upper": 1.0172971969516795E308,"lower": 9.897288684435532E307,"count": 1562,"preSum": 54697 },{ "ndv": 993,"upper": 1.0442401616132107E308,"lower": 1.0174317081163393E308,"count": 1562,"preSum": 56259 },{ "ndv": 987,"upper": 1.0709709928762785E308,"lower": 1.0442462843053817E308,"count": 1562,"preSum": 57821 },{ "ndv": 1000,"upper": 1.100933532991876E308,"lower": 1.071036045373335E308,"count": 1562,"preSum": 59383 },{ "ndv": 969,"upper": 1.1286261509061276E308,"lower": 1.1009765361700323E308,"count": 1562,"preSum": 60945 },{ "ndv": 1001,"upper": 1.1571905196806554E308,"lower": 1.1286331533437651E308,"count": 1565,"preSum": 62507 },{ "ndv": 999,"upper": 1.1861296270192985E308,"lower": 1.1572087018205442E308,"count": 1563,"preSum": 64072 },{ "ndv": 997,"upper": 1.2134614643693616E308,"lower": 1.1861333622749254E308,"count": 1563,"preSum": 65635 },{ "ndv": 980,"upper": 1.2418700035971612E308,"lower": 1.2134718120082815E308,"count": 1562,"preSum": 67198 },{ "ndv": 985,"upper": 1.2691499515332054E308,"lower": 1.241922037299704E308,"count": 1562,"preSum": 68760 },{ "ndv": 980,"upper": 1.2964567726454612E308,"lower": 1.2692154294513629E308,"count": 1563,"preSum": 70322 },{ "ndv": 995,"upper": 1.3252506384017688E308,"lower": 1.2964814717611366E308,"count": 1562,"preSum": 71885 },{ "ndv": 968,"upper": 1.3514161099861431E308,"lower": 1.325272675922444E308,"count": 1563,"preSum": 73447 },{ "ndv": 972,"upper": 1.3806007864738376E308,"lower": 1.3514637942462712E308,"count": 1563,"preSum": 75010 },{ "ndv": 1003,"upper": 1.409320106809102E308,"lower": 1.380611555545838E308,"count": 1562,"preSum": 76573 },{ "ndv": 998,"upper": 1.4374931168432786E308,"lower": 1.4093583744597833E308,"count": 1562,"preSum": 78135 },{ "ndv": 995,"upper": 1.4652557067046356E308,"lower": 1.4375210813985848E308,"count": 1562,"preSum": 79697 },{ "ndv": 972,"upper": 1.4923393819991763E308,"lower": 1.4652710729347972E308,"count": 1563,"preSum": 81259 },{ "ndv": 999,"upper": 1.520870512354084E308,"lower": 1.4923912449753145E308,"count": 1562,"preSum": 82822 },{ "ndv": 943,"upper": 1.5480509182944984E308,"lower": 1.5209436362511451E308,"count": 1562,"preSum": 84384 },{ "ndv": 984,"upper": 1.576218813758102E308,"lower": 1.5480814819592918E308,"count": 1562,"preSum": 85946 },{ "ndv": 997,"upper": 1.6039884578126058E308,"lower": 1.5764266798675781E308,"count": 1562,"preSum": 87508 },{ "ndv": 983,"upper": 1.6307096565078577E308,"lower": 1.6040858849774968E308,"count": 1562,"preSum": 89070 },{ "ndv": 943,"upper": 1.65803142861061E308,"lower": 1.630710017803611E308,"count": 1563,"preSum": 90632 },{ "ndv": 998,"upper": 1.6881230721320153E308,"lower": 1.658068234717274E308,"count": 1566,"preSum": 92195 },{ "ndv": 968,"upper": 1.7144074279398087E308,"lower": 1.6881239139188576E308,"count": 1564,"preSum": 93761 },{ "ndv": 982,"upper": 1.7413961630376678E308,"lower": 1.714410965762671E308,"count": 1563,"preSum": 95325 },{ "ndv": 993,"upper": 1.7698576327467139E308,"lower": 1.7414298567922518E308,"count": 1562,"preSum": 96888 },{ "ndv": 935,"upper": 1.7976542062583872E308,"lower": 1.7699036945643326E308,"count": 1473,"preSum": 98450 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_double.null_count:
+    0
+  cest_full_table_big.c_double.sample_rate:
+    0.010943651
+  cest_full_table_big.c_double_pr.TOPN:
+    { "countArr": [ 8,7,7,7,7,7,9,7,9,8 ],"valueArr": [ -9451013.9,-7755523.335,-6507204.215,-6073291.268,-2830413.985,-2551571.757,-965631.401,4587748.045,7917370.358,8381951.922 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_double_pr.cardinality:
+    517354
+  cest_full_table_big.c_double_pr.histogram:
+    { "buckets": [ { "ndv": 976,"upper": -9698710.869,"lower": -9999451.812,"count": 1562,"preSum": 0 },{ "ndv": 996,"upper": -9383217.511,"lower": -9698657.366,"count": 1562,"preSum": 1562 },{ "ndv": 996,"upper": -9057861.619,"lower": -9382896.233,"count": 1563,"preSum": 3124 },{ "ndv": 990,"upper": -8741496.846,"lower": -9057583.967,"count": 1562,"preSum": 4687 },{ "ndv": 972,"upper": -8448199.852,"lower": -8741414.179,"count": 1563,"preSum": 6249 },{ "ndv": 994,"upper": -8137517.688,"lower": -8447880.659,"count": 1565,"preSum": 7812 },{ "ndv": 996,"upper": -7815510.652,"lower": -8137114.211,"count": 1563,"preSum": 9377 },{ "ndv": 1006,"upper": -7482956.068,"lower": -7815483.878,"count": 1562,"preSum": 10940 },{ "ndv": 989,"upper": -7165460.269,"lower": -7482705.283,"count": 1563,"preSum": 12502 },{ "ndv": 1000,"upper": -6844443.105,"lower": -7165006.364,"count": 1562,"preSum": 14065 },{ "ndv": 990,"upper": -6520640.097,"lower": -6844376.828,"count": 1562,"preSum": 15627 },{ "ndv": 967,"upper": -6223687.9,"lower": -6520612.807,"count": 1562,"preSum": 17189 },{ "ndv": 1004,"upper": -5914138.632,"lower": -6223564.674,"count": 1562,"preSum": 18751 },{ "ndv": 1006,"upper": -5585899.646,"lower": -5914015.578,"count": 1564,"preSum": 20313 },{ "ndv": 978,"upper": -5271848.95,"lower": -5585655.573,"count": 1562,"preSum": 21877 },{ "ndv": 985,"upper": -4964081.047,"lower": -5271638.986,"count": 1562,"preSum": 23439 },{ "ndv": 976,"upper": -4636185.513,"lower": -4963539.277,"count": 1562,"preSum": 25001 },{ "ndv": 1006,"upper": -4308782.404,"lower": -4636182.338,"count": 1563,"preSum": 26563 },{ "ndv": 968,"upper": -3993252.58,"lower": -4308278.223,"count": 1562,"preSum": 28126 },{ "ndv": 1010,"upper": -3675490.617,"lower": -3992692.119,"count": 1562,"preSum": 29688 },{ "ndv": 990,"upper": -3366418.328,"lower": -3674777.151,"count": 1562,"preSum": 31250 },{ "ndv": 1006,"upper": -3048803.74,"lower": -3366212.892,"count": 1563,"preSum": 32812 },{ "ndv": 971,"upper": -2740122.818,"lower": -3047892.944,"count": 1563,"preSum": 34375 },{ "ndv": 965,"upper": -2436098.683,"lower": -2740099.643,"count": 1562,"preSum": 35938 },{ "ndv": 993,"upper": -2121642.264,"lower": -2435944.65,"count": 1562,"preSum": 37500 },{ "ndv": 1014,"upper": -1799195.828,"lower": -2121482.122,"count": 1562,"preSum": 39062 },{ "ndv": 990,"upper": -1481937.888,"lower": -1799099.502,"count": 1562,"preSum": 40624 },{ "ndv": 995,"upper": -1161751.644,"lower": -1481662.026,"count": 1562,"preSum": 42186 },{ "ndv": 975,"upper": -869974.438,"lower": -1161262.104,"count": 1562,"preSum": 43748 },{ "ndv": 986,"upper": -544154.737,"lower": -869328.08,"count": 1562,"preSum": 45310 },{ "ndv": 977,"upper": -230218.798,"lower": -543942.361,"count": 1564,"preSum": 46872 },{ "ndv": 1008,"upper": 81374.344,"lower": -230021.253,"count": 1562,"preSum": 48436 },{ "ndv": 1008,"upper": 400872.418,"lower": 81612.613,"count": 1563,"preSum": 49998 },{ "ndv": 964,"upper": 717144.149,"lower": 401006.767,"count": 1563,"preSum": 51561 },{ "ndv": 980,"upper": 1009794.659,"lower": 717192.583,"count": 1562,"preSum": 53124 },{ "ndv": 1000,"upper": 1325832.039,"lower": 1010508.178,"count": 1562,"preSum": 54686 },{ "ndv": 968,"upper": 1622177.472,"lower": 1326388.151,"count": 1563,"preSum": 56248 },{ "ndv": 1009,"upper": 1945886.811,"lower": 1622179.743,"count": 1562,"preSum": 57811 },{ "ndv": 984,"upper": 2272604.934,"lower": 1948517.759,"count": 1562,"preSum": 59373 },{ "ndv": 989,"upper": 2585899.522,"lower": 2272767.819,"count": 1562,"preSum": 60935 },{ "ndv": 1001,"upper": 2908624.863,"lower": 2586689.392,"count": 1562,"preSum": 62497 },{ "ndv": 969,"upper": 3225611.512,"lower": 2908923.187,"count": 1563,"preSum": 64059 },{ "ndv": 998,"upper": 3533925.395,"lower": 3225647.877,"count": 1563,"preSum": 65622 },{ "ndv": 1002,"upper": 3852021.739,"lower": 3534243.08,"count": 1562,"preSum": 67185 },{ "ndv": 998,"upper": 4165362.828,"lower": 3852211.87,"count": 1562,"preSum": 68747 },{ "ndv": 975,"upper": 4478687.007,"lower": 4165378.782,"count": 1562,"preSum": 70309 },{ "ndv": 979,"upper": 4787949.769,"lower": 4478843.076,"count": 1562,"preSum": 71871 },{ "ndv": 989,"upper": 5099407.334,"lower": 4788050.956,"count": 1563,"preSum": 73433 },{ "ndv": 984,"upper": 5429261.883,"lower": 5099901.103,"count": 1562,"preSum": 74996 },{ "ndv": 977,"upper": 5745636.757,"lower": 5429666.212,"count": 1562,"preSum": 76558 },{ "ndv": 999,"upper": 6051435.761,"lower": 5745843.396,"count": 1562,"preSum": 78120 },{ "ndv": 970,"upper": 6357134.031,"lower": 6051652.815,"count": 1562,"preSum": 79682 },{ "ndv": 973,"upper": 6647614.001,"lower": 6357416.086,"count": 1563,"preSum": 81244 },{ "ndv": 987,"upper": 6958801.058,"lower": 6647811.304,"count": 1562,"preSum": 82807 },{ "ndv": 1006,"upper": 7278085.187,"lower": 6959099.223,"count": 1563,"preSum": 84369 },{ "ndv": 955,"upper": 7575729.667,"lower": 7278096.703,"count": 1563,"preSum": 85932 },{ "ndv": 953,"upper": 7884497.19,"lower": 7575828.386,"count": 1566,"preSum": 87495 },{ "ndv": 958,"upper": 8181003.153,"lower": 7884649.775,"count": 1563,"preSum": 89061 },{ "ndv": 947,"upper": 8485436.854,"lower": 8181192.258,"count": 1562,"preSum": 90624 },{ "ndv": 977,"upper": 8792801.024,"lower": 8485498.154,"count": 1562,"preSum": 92186 },{ "ndv": 968,"upper": 9089914.984,"lower": 8792920.014,"count": 1562,"preSum": 93748 },{ "ndv": 1012,"upper": 9407722.157,"lower": 9089984.322,"count": 1563,"preSum": 95310 },{ "ndv": 975,"upper": 9705075.149,"lower": 9407969.716,"count": 1562,"preSum": 96873 },{ "ndv": 932,"upper": 9999485.995,"lower": 9705280.986,"count": 1490,"preSum": 98435 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_double_pr.null_count:
+    0
+  cest_full_table_big.c_double_pr.sample_rate:
+    0.010943651
+  cest_full_table_big.c_double_un.TOPN:
+    { "countArr": [ 9,15,11,10,15,10,9,9,9,12,10 ],"valueArr": [ 579376.864,589488.812,1195513.356,2268986.695,5361838.797,5652397.646,6284442.196,7175706.635,8951003.459,8996708.706,9289791.517 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_double_un.cardinality:
+    501587
+  cest_full_table_big.c_double_un.histogram:
+    { "buckets": [ { "ndv": 970,"upper": 159246.627,"lower": 26.457,"count": 1561,"preSum": 0 },{ "ndv": 971,"upper": 314434.056,"lower": 159692.554,"count": 1563,"preSum": 1561 },{ "ndv": 968,"upper": 475173.029,"lower": 314619.316,"count": 1561,"preSum": 3124 },{ "ndv": 954,"upper": 623368.486,"lower": 475240.355,"count": 1561,"preSum": 4685 },{ "ndv": 963,"upper": 773875.089,"lower": 623476.169,"count": 1561,"preSum": 6246 },{ "ndv": 964,"upper": 932282.886,"lower": 774107.105,"count": 1562,"preSum": 7807 },{ "ndv": 974,"upper": 1087350.587,"lower": 932407.214,"count": 1562,"preSum": 9369 },{ "ndv": 978,"upper": 1246042.724,"lower": 1087380.079,"count": 1561,"preSum": 10931 },{ "ndv": 929,"upper": 1386788.029,"lower": 1246043.441,"count": 1562,"preSum": 12492 },{ "ndv": 989,"upper": 1544649.258,"lower": 1386795.856,"count": 1562,"preSum": 14054 },{ "ndv": 961,"upper": 1701283.736,"lower": 1545115.988,"count": 1561,"preSum": 15616 },{ "ndv": 989,"upper": 1853724.921,"lower": 1701311.884,"count": 1563,"preSum": 17177 },{ "ndv": 988,"upper": 2008732.195,"lower": 1853748.04,"count": 1561,"preSum": 18740 },{ "ndv": 964,"upper": 2166881.233,"lower": 2008929.12,"count": 1561,"preSum": 20301 },{ "ndv": 949,"upper": 2328526.388,"lower": 2167097.492,"count": 1561,"preSum": 21862 },{ "ndv": 978,"upper": 2478771.234,"lower": 2328617.193,"count": 1561,"preSum": 23423 },{ "ndv": 977,"upper": 2639328.987,"lower": 2478795.732,"count": 1561,"preSum": 24984 },{ "ndv": 958,"upper": 2800017.192,"lower": 2639523.393,"count": 1562,"preSum": 26545 },{ "ndv": 977,"upper": 2959900.118,"lower": 2800284.925,"count": 1561,"preSum": 28107 },{ "ndv": 949,"upper": 3115957.242,"lower": 2960105.781,"count": 1561,"preSum": 29668 },{ "ndv": 953,"upper": 3273609.171,"lower": 3116424.073,"count": 1561,"preSum": 31229 },{ "ndv": 958,"upper": 3435578.642,"lower": 3273746.521,"count": 1561,"preSum": 32790 },{ "ndv": 972,"upper": 3594827.153,"lower": 3435789.982,"count": 1561,"preSum": 34351 },{ "ndv": 961,"upper": 3749012.432,"lower": 3594833.382,"count": 1561,"preSum": 35912 },{ "ndv": 966,"upper": 3906995.326,"lower": 3749126.212,"count": 1561,"preSum": 37473 },{ "ndv": 979,"upper": 4061573.658,"lower": 3907103.398,"count": 1561,"preSum": 39034 },{ "ndv": 979,"upper": 4234017.338,"lower": 4061790.658,"count": 1561,"preSum": 40595 },{ "ndv": 947,"upper": 4388272.834,"lower": 4234112.103,"count": 1563,"preSum": 42156 },{ "ndv": 1010,"upper": 4542816.868,"lower": 4388318.04,"count": 1561,"preSum": 43719 },{ "ndv": 957,"upper": 4699133.092,"lower": 4542969.239,"count": 1561,"preSum": 45280 },{ "ndv": 989,"upper": 4858917.967,"lower": 4699166.786,"count": 1561,"preSum": 46841 },{ "ndv": 974,"upper": 5015784.431,"lower": 4858919.707,"count": 1561,"preSum": 48402 },{ "ndv": 940,"upper": 5172193.14,"lower": 5015808.583,"count": 1561,"preSum": 49963 },{ "ndv": 946,"upper": 5329967.803,"lower": 5172253.411,"count": 1561,"preSum": 51524 },{ "ndv": 950,"upper": 5485807.676,"lower": 5330430.054,"count": 1561,"preSum": 53085 },{ "ndv": 966,"upper": 5638953.389,"lower": 5486096.929,"count": 1561,"preSum": 54646 },{ "ndv": 963,"upper": 5785892.15,"lower": 5639192.583,"count": 1561,"preSum": 56207 },{ "ndv": 992,"upper": 5946566.835,"lower": 5786019.379,"count": 1561,"preSum": 57768 },{ "ndv": 968,"upper": 6115256.316,"lower": 5946793.059,"count": 1563,"preSum": 59329 },{ "ndv": 973,"upper": 6271303.24,"lower": 6115692.319,"count": 1561,"preSum": 60892 },{ "ndv": 987,"upper": 6432002.686,"lower": 6271318.667,"count": 1563,"preSum": 62453 },{ "ndv": 957,"upper": 6585659.36,"lower": 6432017.873,"count": 1561,"preSum": 64016 },{ "ndv": 958,"upper": 6739287.757,"lower": 6585686.714,"count": 1562,"preSum": 65577 },{ "ndv": 974,"upper": 6892079.205,"lower": 6739340.65,"count": 1561,"preSum": 67139 },{ "ndv": 951,"upper": 7041550.54,"lower": 6892259.675,"count": 1562,"preSum": 68700 },{ "ndv": 937,"upper": 7196266.843,"lower": 7041885.308,"count": 1561,"preSum": 70262 },{ "ndv": 972,"upper": 7350123.268,"lower": 7196481.513,"count": 1561,"preSum": 71823 },{ "ndv": 958,"upper": 7502472.326,"lower": 7350203.104,"count": 1562,"preSum": 73384 },{ "ndv": 961,"upper": 7670739.671,"lower": 7502571.826,"count": 1562,"preSum": 74946 },{ "ndv": 970,"upper": 7824962.233,"lower": 7670751.482,"count": 1561,"preSum": 76508 },{ "ndv": 986,"upper": 7980863.433,"lower": 7825007.99,"count": 1561,"preSum": 78069 },{ "ndv": 958,"upper": 8132716.43,"lower": 7980980.515,"count": 1561,"preSum": 79630 },{ "ndv": 944,"upper": 8278706.714,"lower": 8133046.463,"count": 1561,"preSum": 81191 },{ "ndv": 969,"upper": 8437950.574,"lower": 8278715.044,"count": 1562,"preSum": 82752 },{ "ndv": 969,"upper": 8592619.679,"lower": 8438103.5,"count": 1562,"preSum": 84314 },{ "ndv": 994,"upper": 8749085.919,"lower": 8592691.063,"count": 1561,"preSum": 85876 },{ "ndv": 974,"upper": 8908659.712,"lower": 8749358.531,"count": 1561,"preSum": 87437 },{ "ndv": 957,"upper": 9065845.31,"lower": 8908675.535,"count": 1561,"preSum": 88998 },{ "ndv": 983,"upper": 9219235.611,"lower": 9066003.256,"count": 1562,"preSum": 90559 },{ "ndv": 942,"upper": 9372290.098,"lower": 9219407.511,"count": 1561,"preSum": 92121 },{ "ndv": 967,"upper": 9526104.452,"lower": 9372312.77,"count": 1562,"preSum": 93682 },{ "ndv": 970,"upper": 9678405.216,"lower": 9526176.203,"count": 1561,"preSum": 95244 },{ "ndv": 963,"upper": 9838694.24,"lower": 9678788.337,"count": 1562,"preSum": 96805 },{ "ndv": 959,"upper": 9999883.965,"lower": 9839480.156,"count": 1515,"preSum": 98367 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_double_un.null_count:
+    0
+  cest_full_table_big.c_double_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_enum.TOPN:
+    null
+  cest_full_table_big.c_enum.cardinality:
+    6077822
+  cest_full_table_big.c_enum.histogram:
+    { "buckets": [ { "ndv": 1,"upper": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@6cff8cd2","lower": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@6cff8cd2","count": 58717,"preSum": 0 },{ "ndv": 1,"upper": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@2f31f310","lower": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@2f31f310","count": 25535,"preSum": 58717 },{ "ndv": 1,"upper": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@42d263e4","lower": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@42d263e4","count": 15749,"preSum": 84252 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_enum.null_count:
+    0
+  cest_full_table_big.c_enum.sample_rate:
+    0.010943651
+  cest_full_table_big.c_float.TOPN:
+    { "countArr": [ 7,7,7,8,7,7,7,7,8,7,7,7,7 ],"valueArr": [ 4.1239891E37,1.1064914E38,1.3367538E38,1.4780993E38,1.5061238E38,1.5295853E38,1.5592378E38,2.2266388E38,2.2414423E38,2.7778798E38,2.790829E38,3.3444375E38,3.3500825E38 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_float.cardinality:
+    513663
+  cest_full_table_big.c_float.histogram:
+    { "buckets": [ { "ndv": 993,"upper": 5.504475E36,"lower": 9.002987E32,"count": 1562,"preSum": 0 },{ "ndv": 973,"upper": 1.0540608E37,"lower": 5.509676E36,"count": 1562,"preSum": 1562 },{ "ndv": 975,"upper": 1.5816881E37,"lower": 1.054325E37,"count": 1563,"preSum": 3124 },{ "ndv": 1004,"upper": 2.1079314E37,"lower": 1.5818917E37,"count": 1562,"preSum": 4687 },{ "ndv": 1007,"upper": 2.6555632E37,"lower": 2.1082132E37,"count": 1562,"preSum": 6249 },{ "ndv": 1001,"upper": 3.208725E37,"lower": 2.6562163E37,"count": 1564,"preSum": 7811 },{ "ndv": 988,"upper": 3.7676477E37,"lower": 3.2109004E37,"count": 1563,"preSum": 9375 },{ "ndv": 982,"upper": 4.3041707E37,"lower": 3.7676614E37,"count": 1562,"preSum": 10938 },{ "ndv": 955,"upper": 4.8096073E37,"lower": 4.304625E37,"count": 1563,"preSum": 12500 },{ "ndv": 994,"upper": 5.363682E37,"lower": 4.810363E37,"count": 1563,"preSum": 14063 },{ "ndv": 991,"upper": 5.8993893E37,"lower": 5.3636883E37,"count": 1562,"preSum": 15626 },{ "ndv": 1001,"upper": 6.4090006E37,"lower": 5.900045E37,"count": 1564,"preSum": 17188 },{ "ndv": 999,"upper": 6.932706E37,"lower": 6.40917E37,"count": 1562,"preSum": 18752 },{ "ndv": 1008,"upper": 7.478618E37,"lower": 6.932868E37,"count": 1562,"preSum": 20314 },{ "ndv": 1008,"upper": 8.0282077E37,"lower": 7.4786964E37,"count": 1562,"preSum": 21876 },{ "ndv": 982,"upper": 8.569093E37,"lower": 8.0282285E37,"count": 1563,"preSum": 23438 },{ "ndv": 993,"upper": 9.134226E37,"lower": 8.569959E37,"count": 1563,"preSum": 25001 },{ "ndv": 969,"upper": 9.660971E37,"lower": 9.135152E37,"count": 1562,"preSum": 26564 },{ "ndv": 1000,"upper": 1.020596E38,"lower": 9.661767E37,"count": 1565,"preSum": 28126 },{ "ndv": 984,"upper": 1.0724234E38,"lower": 1.0206114E38,"count": 1563,"preSum": 29691 },{ "ndv": 996,"upper": 1.126432E38,"lower": 1.0725553E38,"count": 1562,"preSum": 31254 },{ "ndv": 974,"upper": 1.1790574E38,"lower": 1.1264713E38,"count": 1562,"preSum": 32816 },{ "ndv": 975,"upper": 1.2344194E38,"lower": 1.179143E38,"count": 1562,"preSum": 34378 },{ "ndv": 989,"upper": 1.2865872E38,"lower": 1.2344337E38,"count": 1562,"preSum": 35940 },{ "ndv": 960,"upper": 1.3379517E38,"lower": 1.2866211E38,"count": 1562,"preSum": 37502 },{ "ndv": 996,"upper": 1.3908793E38,"lower": 1.3379585E38,"count": 1562,"preSum": 39064 },{ "ndv": 981,"upper": 1.4454652E38,"lower": 1.3908964E38,"count": 1562,"preSum": 40626 },{ "ndv": 965,"upper": 1.4961927E38,"lower": 1.4454856E38,"count": 1563,"preSum": 42188 },{ "ndv": 980,"upper": 1.5474628E38,"lower": 1.4962791E38,"count": 1562,"preSum": 43751 },{ "ndv": 970,"upper": 1.599883E38,"lower": 1.547498E38,"count": 1562,"preSum": 45313 },{ "ndv": 1005,"upper": 1.6517319E38,"lower": 1.5998927E38,"count": 1562,"preSum": 46875 },{ "ndv": 989,"upper": 1.705293E38,"lower": 1.6518135E38,"count": 1563,"preSum": 48437 },{ "ndv": 979,"upper": 1.7594877E38,"lower": 1.7053282E38,"count": 1563,"preSum": 50000 },{ "ndv": 957,"upper": 1.8145524E38,"lower": 1.7596962E38,"count": 1565,"preSum": 51563 },{ "ndv": 985,"upper": 1.8667806E38,"lower": 1.8146232E38,"count": 1562,"preSum": 53128 },{ "ndv": 963,"upper": 1.9206412E38,"lower": 1.8668222E38,"count": 1563,"preSum": 54690 },{ "ndv": 992,"upper": 1.9722445E38,"lower": 1.9207111E38,"count": 1562,"preSum": 56253 },{ "ndv": 1016,"upper": 2.0243972E38,"lower": 1.9722554E38,"count": 1564,"preSum": 57815 },{ "ndv": 996,"upper": 2.0799735E38,"lower": 2.0245297E38,"count": 1562,"preSum": 59379 },{ "ndv": 974,"upper": 2.131372E38,"lower": 2.0800542E38,"count": 1562,"preSum": 60941 },{ "ndv": 964,"upper": 2.1852976E38,"lower": 2.1314539E38,"count": 1563,"preSum": 62503 },{ "ndv": 1020,"upper": 2.239636E38,"lower": 2.1853063E38,"count": 1562,"preSum": 64066 },{ "ndv": 973,"upper": 2.2914239E38,"lower": 2.2396429E38,"count": 1562,"preSum": 65628 },{ "ndv": 985,"upper": 2.3434947E38,"lower": 2.291461E38,"count": 1562,"preSum": 67190 },{ "ndv": 991,"upper": 2.3970741E38,"lower": 2.343552E38,"count": 1562,"preSum": 68752 },{ "ndv": 986,"upper": 2.450868E38,"lower": 2.397159E38,"count": 1562,"preSum": 70314 },{ "ndv": 979,"upper": 2.505082E38,"lower": 2.4508826E38,"count": 1563,"preSum": 71876 },{ "ndv": 998,"upper": 2.5577175E38,"lower": 2.5051161E38,"count": 1563,"preSum": 73439 },{ "ndv": 961,"upper": 2.6130388E38,"lower": 2.557734E38,"count": 1562,"preSum": 75002 },{ "ndv": 1013,"upper": 2.6671332E38,"lower": 2.6131362E38,"count": 1563,"preSum": 76564 },{ "ndv": 994,"upper": 2.7174385E38,"lower": 2.6671955E38,"count": 1562,"preSum": 78127 },{ "ndv": 965,"upper": 2.769718E38,"lower": 2.7174441E38,"count": 1562,"preSum": 79689 },{ "ndv": 989,"upper": 2.8220551E38,"lower": 2.7697561E38,"count": 1564,"preSum": 81251 },{ "ndv": 990,"upper": 2.874569E38,"lower": 2.8220841E38,"count": 1562,"preSum": 82815 },{ "ndv": 1005,"upper": 2.9281611E38,"lower": 2.8746296E38,"count": 1564,"preSum": 84377 },{ "ndv": 977,"upper": 2.9815347E38,"lower": 2.9281674E38,"count": 1564,"preSum": 85941 },{ "ndv": 988,"upper": 3.0359942E38,"lower": 2.9815426E38,"count": 1562,"preSum": 87505 },{ "ndv": 947,"upper": 3.0858262E38,"lower": 3.0361106E38,"count": 1563,"preSum": 89067 },{ "ndv": 1014,"upper": 3.1412307E38,"lower": 3.0858524E38,"count": 1562,"preSum": 90630 },{ "ndv": 974,"upper": 3.1956198E38,"lower": 3.141308E38,"count": 1562,"preSum": 92192 },{ "ndv": 982,"upper": 3.2469834E38,"lower": 3.1956403E38,"count": 1562,"preSum": 93754 },{ "ndv": 1008,"upper": 3.3000744E38,"lower": 3.2469957E38,"count": 1563,"preSum": 95316 },{ "ndv": 1030,"upper": 3.353673E38,"lower": 3.3001219E38,"count": 1562,"preSum": 96879 },{ "ndv": 911,"upper": 3.4027498E38,"lower": 3.3536897E38,"count": 1467,"preSum": 98441 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_float.null_count:
+    0
+  cest_full_table_big.c_float.sample_rate:
+    0.010943651
+  cest_full_table_big.c_float_pr.TOPN:
+    { "countArr": [ 9,9,10,11,11 ],"valueArr": [ -6092099.5,-3607966.8,-3078055.0,-1173031.5,7679962.0 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_float_pr.cardinality:
+    505636
+  cest_full_table_big.c_float_pr.histogram:
+    { "buckets": [ { "ndv": 964,"upper": -9684324.0,"lower": -9999946.0,"count": 1564,"preSum": 0 },{ "ndv": 976,"upper": -9369876.0,"lower": -9683913.0,"count": 1562,"preSum": 1564 },{ "ndv": 974,"upper": -9046497.0,"lower": -9369645.0,"count": 1563,"preSum": 3126 },{ "ndv": 966,"upper": -8731335.0,"lower": -9046170.0,"count": 1562,"preSum": 4689 },{ "ndv": 973,"upper": -8417582.0,"lower": -8731202.0,"count": 1562,"preSum": 6251 },{ "ndv": 972,"upper": -8093540.0,"lower": -8417506.0,"count": 1562,"preSum": 7813 },{ "ndv": 970,"upper": -7760209.0,"lower": -8093490.5,"count": 1562,"preSum": 9375 },{ "ndv": 957,"upper": -7448782.5,"lower": -7760201.5,"count": 1563,"preSum": 10937 },{ "ndv": 958,"upper": -7140704.5,"lower": -7448777.5,"count": 1562,"preSum": 12500 },{ "ndv": 1003,"upper": -6814441.0,"lower": -7140374.0,"count": 1563,"preSum": 14062 },{ "ndv": 970,"upper": -6505989.0,"lower": -6814231.0,"count": 1563,"preSum": 15625 },{ "ndv": 952,"upper": -6216140.5,"lower": -6505895.0,"count": 1563,"preSum": 17188 },{ "ndv": 968,"upper": -5910459.5,"lower": -6216120.0,"count": 1562,"preSum": 18751 },{ "ndv": 970,"upper": -5591733.5,"lower": -5910418.5,"count": 1562,"preSum": 20313 },{ "ndv": 963,"upper": -5284048.5,"lower": -5591710.0,"count": 1562,"preSum": 21875 },{ "ndv": 973,"upper": -4976923.0,"lower": -5283625.0,"count": 1562,"preSum": 23437 },{ "ndv": 919,"upper": -4669777.0,"lower": -4976309.0,"count": 1562,"preSum": 24999 },{ "ndv": 983,"upper": -4350905.5,"lower": -4669552.5,"count": 1562,"preSum": 26561 },{ "ndv": 1014,"upper": -4025384.5,"lower": -4350720.5,"count": 1562,"preSum": 28123 },{ "ndv": 950,"upper": -3709999.5,"lower": -4025063.5,"count": 1562,"preSum": 29685 },{ "ndv": 938,"upper": -3405368.2,"lower": -3709328.2,"count": 1562,"preSum": 31247 },{ "ndv": 976,"upper": -3097215.8,"lower": -3405120.2,"count": 1563,"preSum": 32809 },{ "ndv": 983,"upper": -2772088.5,"lower": -3096911.8,"count": 1562,"preSum": 34372 },{ "ndv": 998,"upper": -2460747.5,"lower": -2771973.0,"count": 1562,"preSum": 35934 },{ "ndv": 998,"upper": -2137111.0,"lower": -2459697.0,"count": 1563,"preSum": 37496 },{ "ndv": 989,"upper": -1831150.8,"lower": -2136815.2,"count": 1562,"preSum": 39059 },{ "ndv": 968,"upper": -1510433.4,"lower": -1830351.4,"count": 1563,"preSum": 40621 },{ "ndv": 959,"upper": -1196050.2,"lower": -1510194.9,"count": 1563,"preSum": 42184 },{ "ndv": 977,"upper": -879686.0,"lower": -1195765.8,"count": 1562,"preSum": 43747 },{ "ndv": 951,"upper": -569589.06,"lower": -879521.2,"count": 1563,"preSum": 45309 },{ "ndv": 984,"upper": -250843.02,"lower": -568810.25,"count": 1562,"preSum": 46872 },{ "ndv": 979,"upper": 56949.613,"lower": -250737.78,"count": 1563,"preSum": 48434 },{ "ndv": 973,"upper": 376945.3,"lower": 57204.12,"count": 1564,"preSum": 49997 },{ "ndv": 961,"upper": 680584.1,"lower": 377233.84,"count": 1562,"preSum": 51561 },{ "ndv": 989,"upper": 993792.2,"lower": 681034.2,"count": 1564,"preSum": 53123 },{ "ndv": 974,"upper": 1306808.1,"lower": 993849.56,"count": 1562,"preSum": 54687 },{ "ndv": 939,"upper": 1593479.2,"lower": 1306939.1,"count": 1562,"preSum": 56249 },{ "ndv": 980,"upper": 1907529.1,"lower": 1593729.1,"count": 1562,"preSum": 57811 },{ "ndv": 958,"upper": 2229117.5,"lower": 1907937.8,"count": 1562,"preSum": 59373 },{ "ndv": 984,"upper": 2544615.5,"lower": 2229840.0,"count": 1565,"preSum": 60935 },{ "ndv": 971,"upper": 2864125.5,"lower": 2545569.8,"count": 1562,"preSum": 62500 },{ "ndv": 995,"upper": 3186146.5,"lower": 2864261.5,"count": 1562,"preSum": 64062 },{ "ndv": 978,"upper": 3502067.0,"lower": 3186152.8,"count": 1562,"preSum": 65624 },{ "ndv": 982,"upper": 3809239.5,"lower": 3502283.8,"count": 1563,"preSum": 67186 },{ "ndv": 959,"upper": 4104175.8,"lower": 3809307.2,"count": 1562,"preSum": 68749 },{ "ndv": 1000,"upper": 4423520.0,"lower": 4104301.8,"count": 1563,"preSum": 70311 },{ "ndv": 965,"upper": 4730817.0,"lower": 4423834.5,"count": 1562,"preSum": 71874 },{ "ndv": 986,"upper": 5025642.0,"lower": 4731352.5,"count": 1563,"preSum": 73436 },{ "ndv": 962,"upper": 5343345.0,"lower": 5025767.5,"count": 1563,"preSum": 74999 },{ "ndv": 969,"upper": 5654442.5,"lower": 5343345.5,"count": 1562,"preSum": 76562 },{ "ndv": 975,"upper": 5956735.0,"lower": 5654894.0,"count": 1562,"preSum": 78124 },{ "ndv": 1002,"upper": 6278939.5,"lower": 5956743.0,"count": 1562,"preSum": 79686 },{ "ndv": 954,"upper": 6578534.0,"lower": 6278957.5,"count": 1563,"preSum": 81248 },{ "ndv": 995,"upper": 6887688.5,"lower": 6578604.0,"count": 1562,"preSum": 82811 },{ "ndv": 976,"upper": 7206946.5,"lower": 6887787.0,"count": 1562,"preSum": 84373 },{ "ndv": 987,"upper": 7526653.0,"lower": 7207063.0,"count": 1562,"preSum": 85935 },{ "ndv": 994,"upper": 7860585.5,"lower": 7527041.0,"count": 1563,"preSum": 87497 },{ "ndv": 948,"upper": 8160759.0,"lower": 7860812.0,"count": 1563,"preSum": 89060 },{ "ndv": 964,"upper": 8474385.0,"lower": 8160832.0,"count": 1563,"preSum": 90623 },{ "ndv": 988,"upper": 8789618.0,"lower": 8474826.0,"count": 1562,"preSum": 92186 },{ "ndv": 962,"upper": 9078129.0,"lower": 8790325.0,"count": 1562,"preSum": 93748 },{ "ndv": 971,"upper": 9384573.0,"lower": 9078236.0,"count": 1563,"preSum": 95310 },{ "ndv": 977,"upper": 9682653.0,"lower": 9385154.0,"count": 1562,"preSum": 96873 },{ "ndv": 949,"upper": 9999486.0,"lower": 9682788.0,"count": 1516,"preSum": 98435 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_float_pr.null_count:
+    0
+  cest_full_table_big.c_float_pr.sample_rate:
+    0.010943651
+  cest_full_table_big.c_float_un.TOPN:
+    { "countArr": [ 20,16,13,12,14,13,17,14 ],"valueArr": [ 589488.8,1195513.4,2414704.2,2637702.0,3286432.5,5361839.0,6819963.5,9475507.0 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_float_un.cardinality:
+    494291
+  cest_full_table_big.c_float_un.histogram:
+    { "buckets": [ { "ndv": 936,"upper": 151688.97,"lower": 86.998,"count": 1564,"preSum": 0 },{ "ndv": 938,"upper": 310237.72,"lower": 151814.73,"count": 1561,"preSum": 1564 },{ "ndv": 971,"upper": 473776.72,"lower": 311067.66,"count": 1562,"preSum": 3125 },{ "ndv": 924,"upper": 621165.4,"lower": 474045.16,"count": 1563,"preSum": 4687 },{ "ndv": 966,"upper": 775226.06,"lower": 621214.7,"count": 1561,"preSum": 6250 },{ "ndv": 956,"upper": 938563.6,"lower": 775343.0,"count": 1561,"preSum": 7811 },{ "ndv": 959,"upper": 1097381.8,"lower": 938809.25,"count": 1562,"preSum": 9372 },{ "ndv": 937,"upper": 1256796.2,"lower": 1097590.2,"count": 1561,"preSum": 10934 },{ "ndv": 963,"upper": 1417155.1,"lower": 1256848.8,"count": 1561,"preSum": 12495 },{ "ndv": 950,"upper": 1578052.6,"lower": 1417496.4,"count": 1561,"preSum": 14056 },{ "ndv": 978,"upper": 1739527.4,"lower": 1578738.0,"count": 1562,"preSum": 15617 },{ "ndv": 938,"upper": 1886050.5,"lower": 1739601.4,"count": 1562,"preSum": 17179 },{ "ndv": 928,"upper": 2030263.6,"lower": 1886084.4,"count": 1563,"preSum": 18741 },{ "ndv": 993,"upper": 2203592.8,"lower": 2030274.4,"count": 1563,"preSum": 20304 },{ "ndv": 926,"upper": 2356762.0,"lower": 2203654.2,"count": 1564,"preSum": 21867 },{ "ndv": 984,"upper": 2517586.2,"lower": 2356784.8,"count": 1561,"preSum": 23431 },{ "ndv": 936,"upper": 2675512.8,"lower": 2517688.0,"count": 1561,"preSum": 24992 },{ "ndv": 953,"upper": 2832216.8,"lower": 2675596.8,"count": 1561,"preSum": 26553 },{ "ndv": 942,"upper": 2991048.0,"lower": 2832394.0,"count": 1561,"preSum": 28114 },{ "ndv": 950,"upper": 3138771.8,"lower": 2991117.2,"count": 1562,"preSum": 29675 },{ "ndv": 970,"upper": 3302888.0,"lower": 3138937.0,"count": 1561,"preSum": 31237 },{ "ndv": 987,"upper": 3459885.2,"lower": 3303147.8,"count": 1561,"preSum": 32798 },{ "ndv": 974,"upper": 3627328.5,"lower": 3459954.8,"count": 1561,"preSum": 34359 },{ "ndv": 954,"upper": 3785672.0,"lower": 3627513.2,"count": 1561,"preSum": 35920 },{ "ndv": 945,"upper": 3941444.2,"lower": 3785861.8,"count": 1562,"preSum": 37481 },{ "ndv": 946,"upper": 4089786.0,"lower": 3941446.0,"count": 1561,"preSum": 39043 },{ "ndv": 966,"upper": 4255241.0,"lower": 4089934.8,"count": 1562,"preSum": 40604 },{ "ndv": 959,"upper": 4414551.5,"lower": 4255396.5,"count": 1562,"preSum": 42166 },{ "ndv": 947,"upper": 4568288.5,"lower": 4414555.5,"count": 1561,"preSum": 43728 },{ "ndv": 963,"upper": 4726591.0,"lower": 4568316.0,"count": 1562,"preSum": 45289 },{ "ndv": 966,"upper": 4887419.0,"lower": 4726607.0,"count": 1563,"preSum": 46851 },{ "ndv": 978,"upper": 5045942.5,"lower": 4887621.0,"count": 1563,"preSum": 48414 },{ "ndv": 957,"upper": 5205647.5,"lower": 5046174.0,"count": 1561,"preSum": 49977 },{ "ndv": 929,"upper": 5359276.5,"lower": 5205724.5,"count": 1561,"preSum": 51538 },{ "ndv": 945,"upper": 5511453.5,"lower": 5359427.0,"count": 1561,"preSum": 53099 },{ "ndv": 905,"upper": 5662793.0,"lower": 5511467.0,"count": 1562,"preSum": 54660 },{ "ndv": 973,"upper": 5815646.0,"lower": 5662834.0,"count": 1562,"preSum": 56222 },{ "ndv": 967,"upper": 5976476.0,"lower": 5815878.0,"count": 1561,"preSum": 57784 },{ "ndv": 930,"upper": 6140401.0,"lower": 5976720.5,"count": 1561,"preSum": 59345 },{ "ndv": 937,"upper": 6290344.5,"lower": 6140456.5,"count": 1562,"preSum": 60906 },{ "ndv": 973,"upper": 6447959.5,"lower": 6290541.0,"count": 1562,"preSum": 62468 },{ "ndv": 945,"upper": 6600870.0,"lower": 6448226.0,"count": 1561,"preSum": 64030 },{ "ndv": 943,"upper": 6751195.0,"lower": 6601013.0,"count": 1562,"preSum": 65591 },{ "ndv": 928,"upper": 6904822.0,"lower": 6751454.5,"count": 1562,"preSum": 67153 },{ "ndv": 951,"upper": 7064430.0,"lower": 6904928.0,"count": 1564,"preSum": 68715 },{ "ndv": 942,"upper": 7226650.0,"lower": 7064552.5,"count": 1562,"preSum": 70279 },{ "ndv": 944,"upper": 7383956.0,"lower": 7226743.5,"count": 1561,"preSum": 71841 },{ "ndv": 960,"upper": 7538594.5,"lower": 7383957.0,"count": 1561,"preSum": 73402 },{ "ndv": 952,"upper": 7704869.0,"lower": 7538627.0,"count": 1561,"preSum": 74963 },{ "ndv": 984,"upper": 7866691.0,"lower": 7704933.0,"count": 1562,"preSum": 76524 },{ "ndv": 946,"upper": 8012367.0,"lower": 7866694.0,"count": 1561,"preSum": 78086 },{ "ndv": 965,"upper": 8165894.0,"lower": 8012714.5,"count": 1561,"preSum": 79647 },{ "ndv": 937,"upper": 8312316.5,"lower": 8165947.0,"count": 1562,"preSum": 81208 },{ "ndv": 927,"upper": 8459721.0,"lower": 8312752.0,"count": 1561,"preSum": 82770 },{ "ndv": 935,"upper": 8617789.0,"lower": 8460122.0,"count": 1561,"preSum": 84331 },{ "ndv": 942,"upper": 8767813.0,"lower": 8617907.0,"count": 1562,"preSum": 85892 },{ "ndv": 935,"upper": 8926592.0,"lower": 8767903.0,"count": 1561,"preSum": 87454 },{ "ndv": 926,"upper": 9076115.0,"lower": 8926674.0,"count": 1561,"preSum": 89015 },{ "ndv": 960,"upper": 9233239.0,"lower": 9076390.0,"count": 1561,"preSum": 90576 },{ "ndv": 927,"upper": 9391142.0,"lower": 9233739.0,"count": 1561,"preSum": 92137 },{ "ndv": 953,"upper": 9539327.0,"lower": 9391275.0,"count": 1561,"preSum": 93698 },{ "ndv": 941,"upper": 9692483.0,"lower": 9539341.0,"count": 1563,"preSum": 95259 },{ "ndv": 980,"upper": 9850446.0,"lower": 9692830.0,"count": 1561,"preSum": 96822 },{ "ndv": 923,"upper": 9999782.0,"lower": 9850470.0,"count": 1499,"preSum": 98383 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_float_un.null_count:
+    0
+  cest_full_table_big.c_float_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_int_1.TOPN:
+    { "countArr": [ 599,663,293,2213,428,966,461,287,361,373,1220,510,265,351 ],"valueArr": [ -2114287725,-1882521012,-1829648591,-1366704471,-1342386297,-1284743463,-1111039198,-1024432730,-845681049,-750951495,-652330026,171784479,1975875333,2102038600 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_int_1.cardinality:
+    366727
+  cest_full_table_big.c_int_1.histogram:
+    { "buckets": [ { "ndv": 684,"upper": -2074506914,"lower": -2147478353,"count": 1423,"preSum": 0 },{ "ndv": 629,"upper": -2003232477,"lower": -2074494945,"count": 1423,"preSum": 1423 },{ "ndv": 624,"upper": -1938580814,"lower": -2002908070,"count": 1424,"preSum": 2846 },{ "ndv": 638,"upper": -1864280238,"lower": -1938527048,"count": 1424,"preSum": 4270 },{ "ndv": 603,"upper": -1798986376,"lower": -1864275902,"count": 1424,"preSum": 5694 },{ "ndv": 634,"upper": -1728917649,"lower": -1798894717,"count": 1423,"preSum": 7118 },{ "ndv": 662,"upper": -1650596497,"lower": -1728840458,"count": 1423,"preSum": 8541 },{ "ndv": 632,"upper": -1585988361,"lower": -1650401255,"count": 1424,"preSum": 9964 },{ "ndv": 709,"upper": -1512170179,"lower": -1585866030,"count": 1423,"preSum": 11388 },{ "ndv": 539,"upper": -1450527960,"lower": -1512103099,"count": 1438,"preSum": 12811 },{ "ndv": 649,"upper": -1377339432,"lower": -1450477080,"count": 1423,"preSum": 14249 },{ "ndv": 709,"upper": -1299879330,"lower": -1377141060,"count": 1423,"preSum": 15672 },{ "ndv": 562,"upper": -1240840843,"lower": -1299825740,"count": 1423,"preSum": 17095 },{ "ndv": 654,"upper": -1170100321,"lower": -1240786007,"count": 1520,"preSum": 18518 },{ "ndv": 663,"upper": -1099961725,"lower": -1169992660,"count": 1423,"preSum": 20038 },{ "ndv": 618,"upper": -1031130346,"lower": -1099871492,"count": 1434,"preSum": 21461 },{ "ndv": 569,"upper": -971805522,"lower": -1030992917,"count": 1455,"preSum": 22895 },{ "ndv": 587,"upper": -909262959,"lower": -971758662,"count": 1426,"preSum": 24350 },{ "ndv": 618,"upper": -843504224,"lower": -909138280,"count": 1469,"preSum": 25776 },{ "ndv": 588,"upper": -783789132,"lower": -843284510,"count": 1584,"preSum": 27245 },{ "ndv": 758,"upper": -698081811,"lower": -783768125,"count": 1425,"preSum": 28829 },{ "ndv": 559,"upper": -638568104,"lower": -698046210,"count": 1424,"preSum": 30254 },{ "ndv": 738,"upper": -557684205,"lower": -638506136,"count": 1424,"preSum": 31678 },{ "ndv": 612,"upper": -491814823,"lower": -557560574,"count": 1452,"preSum": 33102 },{ "ndv": 629,"upper": -425091649,"lower": -491771542,"count": 1479,"preSum": 34554 },{ "ndv": 658,"upper": -354359116,"lower": -425085893,"count": 1423,"preSum": 36033 },{ "ndv": 674,"upper": -278890396,"lower": -354350566,"count": 1423,"preSum": 37456 },{ "ndv": 714,"upper": -202483880,"lower": -278790320,"count": 1425,"preSum": 38879 },{ "ndv": 616,"upper": -138008072,"lower": -202478059,"count": 1423,"preSum": 40304 },{ "ndv": 629,"upper": -65784201,"lower": -137983234,"count": 1423,"preSum": 41727 },{ "ndv": 618,"upper": 759812,"lower": -65762336,"count": 1423,"preSum": 43150 },{ "ndv": 734,"upper": 78550570,"lower": 821495,"count": 1423,"preSum": 44573 },{ "ndv": 536,"upper": 137680427,"lower": 78723384,"count": 1444,"preSum": 45996 },{ "ndv": 610,"upper": 201480868,"lower": 137799148,"count": 1425,"preSum": 47440 },{ "ndv": 577,"upper": 262650263,"lower": 201699875,"count": 1423,"preSum": 48865 },{ "ndv": 624,"upper": 329276030,"lower": 262713290,"count": 1452,"preSum": 50288 },{ "ndv": 702,"upper": 404705759,"lower": 329280136,"count": 1423,"preSum": 51740 },{ "ndv": 691,"upper": 477201339,"lower": 404753441,"count": 1428,"preSum": 53163 },{ "ndv": 539,"upper": 536183934,"lower": 477326151,"count": 1424,"preSum": 54591 },{ "ndv": 693,"upper": 607524911,"lower": 536234121,"count": 1428,"preSum": 56015 },{ "ndv": 594,"upper": 668675773,"lower": 607659991,"count": 1423,"preSum": 57443 },{ "ndv": 564,"upper": 727868155,"lower": 668696283,"count": 1423,"preSum": 58866 },{ "ndv": 592,"upper": 795317526,"lower": 728006460,"count": 1423,"preSum": 60289 },{ "ndv": 539,"upper": 850744436,"lower": 795337566,"count": 1423,"preSum": 61712 },{ "ndv": 613,"upper": 916150895,"lower": 850753944,"count": 1425,"preSum": 63135 },{ "ndv": 550,"upper": 974090564,"lower": 916216339,"count": 1423,"preSum": 64560 },{ "ndv": 706,"upper": 1048554634,"lower": 974236554,"count": 1425,"preSum": 65983 },{ "ndv": 527,"upper": 1110516419,"lower": 1048646249,"count": 1423,"preSum": 67408 },{ "ndv": 594,"upper": 1174541012,"lower": 1110535263,"count": 1423,"preSum": 68831 },{ "ndv": 655,"upper": 1243516297,"lower": 1174574580,"count": 1502,"preSum": 70254 },{ "ndv": 721,"upper": 1321715633,"lower": 1243544252,"count": 1423,"preSum": 71756 },{ "ndv": 702,"upper": 1399808382,"lower": 1321736658,"count": 1424,"preSum": 73179 },{ "ndv": 625,"upper": 1468262346,"lower": 1399841778,"count": 1424,"preSum": 74603 },{ "ndv": 540,"upper": 1529108592,"lower": 1468291810,"count": 1423,"preSum": 76027 },{ "ndv": 601,"upper": 1591902937,"lower": 1529174618,"count": 1423,"preSum": 77450 },{ "ndv": 597,"upper": 1650723944,"lower": 1591979163,"count": 1424,"preSum": 78873 },{ "ndv": 692,"upper": 1727531405,"lower": 1650769428,"count": 1423,"preSum": 80297 },{ "ndv": 580,"upper": 1790674608,"lower": 1727740641,"count": 1423,"preSum": 81720 },{ "ndv": 636,"upper": 1858104612,"lower": 1790870562,"count": 1424,"preSum": 83143 },{ "ndv": 648,"upper": 1928294403,"lower": 1858139999,"count": 1423,"preSum": 84567 },{ "ndv": 625,"upper": 1992647664,"lower": 1928468477,"count": 1539,"preSum": 85990 },{ "ndv": 725,"upper": 2061649554,"lower": 1992836751,"count": 1439,"preSum": 87529 },{ "ndv": 562,"upper": 2116878413,"lower": 2061735788,"count": 1444,"preSum": 88968 },{ "ndv": 272,"upper": 2147283591,"lower": 2116884239,"count": 599,"preSum": 90412 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_int_1.null_count:
+    0
+  cest_full_table_big.c_int_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_int_32.TOPN:
+    { "countArr": [ 1689,2040,617,8210,1126,2782,1175,720,815,872,4184,1391,575,745 ],"valueArr": [ -2114287725,-1882521012,-1829648591,-1366704471,-1342386297,-1284743463,-1111039198,-1024432730,-845681049,-750951495,-652330026,171784479,1975875333,2102038600 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_int_32.cardinality:
+    243421
+  cest_full_table_big.c_int_32.histogram:
+    { "buckets": [ { "ndv": 481,"upper": -2059568640,"lower": -2147478353,"count": 1195,"preSum": 0 },{ "ndv": 464,"upper": -1976243250,"lower": -2059567210,"count": 1142,"preSum": 1195 },{ "ndv": 421,"upper": -1902459046,"lower": -1976174034,"count": 1143,"preSum": 2337 },{ "ndv": 371,"upper": -1836186294,"lower": -1902320799,"count": 1568,"preSum": 3480 },{ "ndv": 494,"upper": -1745723374,"lower": -1836001401,"count": 1161,"preSum": 5048 },{ "ndv": 408,"upper": -1673084409,"lower": -1745693414,"count": 1153,"preSum": 6209 },{ "ndv": 447,"upper": -1598399519,"lower": -1672451140,"count": 1142,"preSum": 7362 },{ "ndv": 499,"upper": -1512206281,"lower": -1598280131,"count": 1145,"preSum": 8504 },{ "ndv": 306,"upper": -1461569257,"lower": -1512170179,"count": 1171,"preSum": 9649 },{ "ndv": 434,"upper": -1380131638,"lower": -1461516726,"count": 1144,"preSum": 10820 },{ "ndv": 472,"upper": -1293657631,"lower": -1380099151,"count": 1147,"preSum": 11964 },{ "ndv": 304,"upper": -1241458321,"lower": -1293572679,"count": 1143,"preSum": 13111 },{ "ndv": 379,"upper": -1170100321,"lower": -1241335228,"count": 1287,"preSum": 14254 },{ "ndv": 482,"upper": -1087612618,"lower": -1169975712,"count": 1142,"preSum": 15541 },{ "ndv": 349,"upper": -1029590024,"lower": -1087561375,"count": 1146,"preSum": 16683 },{ "ndv": 334,"upper": -971805522,"lower": -1029441603,"count": 1228,"preSum": 17829 },{ "ndv": 278,"upper": -922860550,"lower": -971743209,"count": 1143,"preSum": 19057 },{ "ndv": 377,"upper": -855680901,"lower": -922551552,"count": 1142,"preSum": 20200 },{ "ndv": 308,"upper": -805093714,"lower": -855412029,"count": 1142,"preSum": 21342 },{ "ndv": 387,"upper": -732762352,"lower": -805067111,"count": 1142,"preSum": 22484 },{ "ndv": 408,"upper": -658487795,"lower": -732527512,"count": 1354,"preSum": 23626 },{ "ndv": 500,"upper": -565840013,"lower": -658312674,"count": 1146,"preSum": 24980 },{ "ndv": 328,"upper": -509590838,"lower": -565300275,"count": 1197,"preSum": 26126 },{ "ndv": 353,"upper": -448463230,"lower": -509569129,"count": 1145,"preSum": 27323 },{ "ndv": 324,"upper": -390087326,"lower": -448182367,"count": 1145,"preSum": 28468 },{ "ndv": 462,"upper": -302136078,"lower": -389792263,"count": 1143,"preSum": 29613 },{ "ndv": 458,"upper": -224950358,"lower": -302041887,"count": 1175,"preSum": 30756 },{ "ndv": 428,"upper": -154230186,"lower": -224457087,"count": 1157,"preSum": 31931 },{ "ndv": 288,"upper": -101053521,"lower": -154068748,"count": 1142,"preSum": 33088 },{ "ndv": 468,"upper": -13225259,"lower": -101016076,"count": 1270,"preSum": 34230 },{ "ndv": 543,"upper": 76068590,"lower": -12850435,"count": 1164,"preSum": 35500 },{ "ndv": 319,"upper": 128732106,"lower": 76193911,"count": 1190,"preSum": 36664 },{ "ndv": 234,"upper": 166737107,"lower": 128823998,"count": 1150,"preSum": 37854 },{ "ndv": 444,"upper": 242848040,"lower": 166929910,"count": 1186,"preSum": 39004 },{ "ndv": 394,"upper": 310897256,"lower": 242937616,"count": 1152,"preSum": 40190 },{ "ndv": 517,"upper": 399681040,"lower": 311130615,"count": 1142,"preSum": 41342 },{ "ndv": 470,"upper": 485427209,"lower": 399706744,"count": 1142,"preSum": 42484 },{ "ndv": 255,"upper": 533217626,"lower": 485711904,"count": 1256,"preSum": 43626 },{ "ndv": 426,"upper": 609471793,"lower": 533230999,"count": 1196,"preSum": 44882 },{ "ndv": 383,"upper": 672822679,"lower": 609519810,"count": 1142,"preSum": 46078 },{ "ndv": 333,"upper": 732857150,"lower": 672914799,"count": 1142,"preSum": 47220 },{ "ndv": 342,"upper": 799751831,"lower": 732860103,"count": 1149,"preSum": 48362 },{ "ndv": 248,"upper": 842116146,"lower": 799812868,"count": 1190,"preSum": 49511 },{ "ndv": 366,"upper": 909252806,"lower": 842274177,"count": 1143,"preSum": 50701 },{ "ndv": 310,"upper": 961469422,"lower": 909520175,"count": 1142,"preSum": 51844 },{ "ndv": 471,"upper": 1046507890,"lower": 961899431,"count": 1142,"preSum": 52986 },{ "ndv": 291,"upper": 1100624309,"lower": 1046595744,"count": 1164,"preSum": 54128 },{ "ndv": 348,"upper": 1164768208,"lower": 1100625895,"count": 1142,"preSum": 55292 },{ "ndv": 439,"upper": 1240328180,"lower": 1164777182,"count": 1142,"preSum": 56434 },{ "ndv": 401,"upper": 1307206398,"lower": 1240530312,"count": 1142,"preSum": 57576 },{ "ndv": 548,"upper": 1405102988,"lower": 1307369657,"count": 1168,"preSum": 58718 },{ "ndv": 447,"upper": 1480838532,"lower": 1405152654,"count": 1142,"preSum": 59886 },{ "ndv": 261,"upper": 1528822093,"lower": 1481009657,"count": 1303,"preSum": 61028 },{ "ndv": 400,"upper": 1596971174,"lower": 1529105540,"count": 1143,"preSum": 62331 },{ "ndv": 338,"upper": 1652837140,"lower": 1597008497,"count": 1142,"preSum": 63474 },{ "ndv": 479,"upper": 1740254580,"lower": 1653100644,"count": 1143,"preSum": 64616 },{ "ndv": 304,"upper": 1795509045,"lower": 1740597775,"count": 1168,"preSum": 65759 },{ "ndv": 443,"upper": 1864662820,"lower": 1795527319,"count": 1142,"preSum": 66927 },{ "ndv": 404,"upper": 1936645028,"lower": 1864681439,"count": 1146,"preSum": 68069 },{ "ndv": 348,"upper": 1997127321,"lower": 1936700220,"count": 1142,"preSum": 69215 },{ "ndv": 507,"upper": 2079632219,"lower": 1997200038,"count": 1142,"preSum": 70357 },{ "ndv": 251,"upper": 2124107623,"lower": 2080211293,"count": 1142,"preSum": 71499 },{ "ndv": 143,"upper": 2147083146,"lower": 2124491826,"count": 419,"preSum": 72641 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_int_32.null_count:
+    0
+  cest_full_table_big.c_int_32.sample_rate:
+    0.010943651
+  cest_full_table_big.c_int_32_un.TOPN:
+    { "countArr": [ 2792,2316,3757,888,19669,1626,5129,1931,987,1212,1427,8436,858,1088 ],"valueArr": [ 33195923,171784479,264962636,317835057,780779177,805097351,862740185,1036444450,1123050918,1301802599,1396532153,1495153622,1975875333,2102038600 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_int_32_un.cardinality:
+    115437
+  cest_full_table_big.c_int_32_un.histogram:
+    { "buckets": [ { "ndv": 260,"upper": 51911622,"lower": 5295,"count": 749,"preSum": 0 },{ "ndv": 191,"upper": 95943779,"lower": 52856262,"count": 910,"preSum": 749 },{ "ndv": 236,"upper": 137680427,"lower": 96710486,"count": 862,"preSum": 1659 },{ "ndv": 150,"upper": 166492152,"lower": 138230437,"count": 1083,"preSum": 2521 },{ "ndv": 223,"upper": 208902840,"lower": 166737107,"count": 749,"preSum": 3604 },{ "ndv": 216,"upper": 247401951,"lower": 208902965,"count": 749,"preSum": 4353 },{ "ndv": 144,"upper": 274099910,"lower": 247601336,"count": 771,"preSum": 5102 },{ "ndv": 204,"upper": 311297354,"lower": 274103362,"count": 1316,"preSum": 5873 },{ "ndv": 278,"upper": 364997941,"lower": 311311439,"count": 758,"preSum": 7189 },{ "ndv": 297,"upper": 421955227,"lower": 365054463,"count": 749,"preSum": 7947 },{ "ndv": 268,"upper": 474399239,"lower": 422063244,"count": 778,"preSum": 8696 },{ "ndv": 236,"upper": 517269091,"lower": 474419183,"count": 751,"preSum": 9474 },{ "ndv": 39,"upper": 525980030,"lower": 517384958,"count": 943,"preSum": 10225 },{ "ndv": 211,"upper": 563330507,"lower": 525985770,"count": 749,"preSum": 11168 },{ "ndv": 234,"upper": 610644978,"lower": 563847197,"count": 749,"preSum": 11917 },{ "ndv": 201,"upper": 648154117,"lower": 610953376,"count": 759,"preSum": 12666 },{ "ndv": 154,"upper": 675721687,"lower": 648243995,"count": 757,"preSum": 13425 },{ "ndv": 171,"upper": 707024195,"lower": 675740785,"count": 763,"preSum": 14182 },{ "ndv": 190,"upper": 744178917,"lower": 707538630,"count": 764,"preSum": 14945 },{ "ndv": 219,"upper": 784220410,"lower": 744423484,"count": 842,"preSum": 15709 },{ "ndv": 198,"upper": 820578404,"lower": 784258726,"count": 804,"preSum": 16551 },{ "ndv": 139,"upper": 848587288,"lower": 820601861,"count": 778,"preSum": 17355 },{ "ndv": 143,"upper": 872869048,"lower": 848840055,"count": 1271,"preSum": 18133 },{ "ndv": 204,"upper": 914346491,"lower": 872976425,"count": 774,"preSum": 19404 },{ "ndv": 186,"upper": 947641586,"lower": 914376534,"count": 890,"preSum": 20178 },{ "ndv": 178,"upper": 980669282,"lower": 947750011,"count": 768,"preSum": 21068 },{ "ndv": 226,"upper": 1017981521,"lower": 980703413,"count": 772,"preSum": 21836 },{ "ndv": 269,"upper": 1069696352,"lower": 1017981846,"count": 750,"preSum": 22608 },{ "ndv": 186,"upper": 1105269469,"lower": 1069849436,"count": 969,"preSum": 23358 },{ "ndv": 105,"upper": 1125979808,"lower": 1105397138,"count": 791,"preSum": 24327 },{ "ndv": 259,"upper": 1174541012,"lower": 1126315148,"count": 775,"preSum": 25118 },{ "ndv": 137,"upper": 1205235491,"lower": 1174551463,"count": 1318,"preSum": 25893 },{ "ndv": 193,"upper": 1238692391,"lower": 1205408341,"count": 750,"preSum": 27211 },{ "ndv": 187,"upper": 1278799410,"lower": 1239163407,"count": 917,"preSum": 27961 },{ "ndv": 204,"upper": 1315771187,"lower": 1279173223,"count": 749,"preSum": 28878 },{ "ndv": 236,"upper": 1360515634,"lower": 1315967094,"count": 753,"preSum": 29627 },{ "ndv": 105,"upper": 1381281554,"lower": 1360578245,"count": 775,"preSum": 30380 },{ "ndv": 298,"upper": 1437784952,"lower": 1381312941,"count": 820,"preSum": 31155 },{ "ndv": 213,"upper": 1483182213,"lower": 1437885471,"count": 1233,"preSum": 31975 },{ "ndv": 46,"upper": 1494371053,"lower": 1483221406,"count": 804,"preSum": 33208 },{ "ndv": 231,"upper": 1537548292,"lower": 1494538502,"count": 749,"preSum": 34012 },{ "ndv": 259,"upper": 1585293283,"lower": 1537713630,"count": 772,"preSum": 34761 },{ "ndv": 134,"upper": 1611812771,"lower": 1585691140,"count": 749,"preSum": 35533 },{ "ndv": 159,"upper": 1644855264,"lower": 1612180374,"count": 775,"preSum": 36282 },{ "ndv": 248,"upper": 1691808023,"lower": 1645106875,"count": 1018,"preSum": 37057 },{ "ndv": 172,"upper": 1722402852,"lower": 1691996010,"count": 752,"preSum": 38075 },{ "ndv": 189,"upper": 1758737198,"lower": 1722637560,"count": 751,"preSum": 38827 },{ "ndv": 154,"upper": 1789523027,"lower": 1758911387,"count": 749,"preSum": 39578 },{ "ndv": 221,"upper": 1832508714,"lower": 1790093600,"count": 749,"preSum": 40327 },{ "ndv": 300,"upper": 1885425308,"lower": 1832544264,"count": 755,"preSum": 41076 },{ "ndv": 209,"upper": 1926020744,"lower": 1885643442,"count": 750,"preSum": 41831 },{ "ndv": 136,"upper": 1953124538,"lower": 1926465194,"count": 982,"preSum": 42581 },{ "ndv": 226,"upper": 1992647664,"lower": 1953220251,"count": 852,"preSum": 43563 },{ "ndv": 168,"upper": 2023053384,"lower": 1992883514,"count": 890,"preSum": 44415 },{ "ndv": 283,"upper": 2074276230,"lower": 2023054825,"count": 750,"preSum": 45305 },{ "ndv": 136,"upper": 2102143275,"lower": 2074604253,"count": 749,"preSum": 46055 },{ "ndv": 157,"upper": 2134258389,"lower": 2102460426,"count": 822,"preSum": 46804 },{ "ndv": 83,"upper": 2147353621,"lower": 2134289989,"count": 259,"preSum": 47626 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_int_32_un.null_count:
+    0
+  cest_full_table_big.c_int_32_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_mediumint_1.TOPN:
+    { "countArr": [ 13,8,10,10,9,11,8,8 ],"valueArr": [ -7399610,-6342339,-5316156,-3963279,-2519378,607065,3425154,5407120 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_mediumint_1.cardinality:
+    505764
+  cest_full_table_big.c_mediumint_1.histogram:
+    { "buckets": [ { "ndv": 942,"upper": -8144386,"lower": -8388463,"count": 1563,"preSum": 0 },{ "ndv": 1002,"upper": -7875850,"lower": -8144143,"count": 1562,"preSum": 1563 },{ "ndv": 968,"upper": -7610713,"lower": -7875837,"count": 1562,"preSum": 3125 },{ "ndv": 961,"upper": -7351185,"lower": -7610530,"count": 1563,"preSum": 4687 },{ "ndv": 999,"upper": -7081497,"lower": -7351054,"count": 1562,"preSum": 6250 },{ "ndv": 963,"upper": -6811824,"lower": -7081158,"count": 1562,"preSum": 7812 },{ "ndv": 971,"upper": -6521072,"lower": -6811263,"count": 1562,"preSum": 9374 },{ "ndv": 965,"upper": -6263983,"lower": -6521048,"count": 1564,"preSum": 10936 },{ "ndv": 964,"upper": -6009392,"lower": -6263889,"count": 1562,"preSum": 12500 },{ "ndv": 977,"upper": -5718986,"lower": -6009023,"count": 1562,"preSum": 14062 },{ "ndv": 963,"upper": -5461282,"lower": -5718904,"count": 1562,"preSum": 15624 },{ "ndv": 966,"upper": -5200523,"lower": -5461090,"count": 1562,"preSum": 17186 },{ "ndv": 975,"upper": -4945722,"lower": -5199709,"count": 1562,"preSum": 18748 },{ "ndv": 1001,"upper": -4669215,"lower": -4945552,"count": 1564,"preSum": 20310 },{ "ndv": 973,"upper": -4409275,"lower": -4668995,"count": 1562,"preSum": 21874 },{ "ndv": 985,"upper": -4141919,"lower": -4409236,"count": 1562,"preSum": 23436 },{ "ndv": 976,"upper": -3869814,"lower": -4141831,"count": 1563,"preSum": 24998 },{ "ndv": 941,"upper": -3623110,"lower": -3869775,"count": 1562,"preSum": 26561 },{ "ndv": 969,"upper": -3358584,"lower": -3622777,"count": 1563,"preSum": 28123 },{ "ndv": 971,"upper": -3105806,"lower": -3358580,"count": 1562,"preSum": 29686 },{ "ndv": 971,"upper": -2839836,"lower": -3105145,"count": 1562,"preSum": 31248 },{ "ndv": 949,"upper": -2580918,"lower": -2839723,"count": 1562,"preSum": 32810 },{ "ndv": 964,"upper": -2311755,"lower": -2580746,"count": 1562,"preSum": 34372 },{ "ndv": 956,"upper": -2047226,"lower": -2311733,"count": 1564,"preSum": 35934 },{ "ndv": 942,"upper": -1805037,"lower": -2046720,"count": 1563,"preSum": 37498 },{ "ndv": 985,"upper": -1559139,"lower": -1804911,"count": 1562,"preSum": 39061 },{ "ndv": 982,"upper": -1300436,"lower": -1558885,"count": 1563,"preSum": 40623 },{ "ndv": 985,"upper": -1031000,"lower": -1300300,"count": 1562,"preSum": 42186 },{ "ndv": 953,"upper": -774466,"lower": -1030963,"count": 1565,"preSum": 43748 },{ "ndv": 955,"upper": -523385,"lower": -774308,"count": 1565,"preSum": 45313 },{ "ndv": 986,"upper": -257176,"lower": -523281,"count": 1562,"preSum": 46878 },{ "ndv": 967,"upper": 1439,"lower": -257049,"count": 1562,"preSum": 48440 },{ "ndv": 964,"upper": 257637,"lower": 1889,"count": 1564,"preSum": 50002 },{ "ndv": 951,"upper": 521328,"lower": 257736,"count": 1562,"preSum": 51566 },{ "ndv": 989,"upper": 789581,"lower": 521408,"count": 1562,"preSum": 53128 },{ "ndv": 989,"upper": 1041212,"lower": 790073,"count": 1562,"preSum": 54690 },{ "ndv": 963,"upper": 1297393,"lower": 1042073,"count": 1563,"preSum": 56252 },{ "ndv": 971,"upper": 1562470,"lower": 1297394,"count": 1563,"preSum": 57815 },{ "ndv": 992,"upper": 1828712,"lower": 1562727,"count": 1563,"preSum": 59378 },{ "ndv": 993,"upper": 2092331,"lower": 1828887,"count": 1563,"preSum": 60941 },{ "ndv": 975,"upper": 2374162,"lower": 2092882,"count": 1562,"preSum": 62504 },{ "ndv": 1013,"upper": 2645722,"lower": 2374470,"count": 1562,"preSum": 64066 },{ "ndv": 968,"upper": 2908213,"lower": 2645746,"count": 1563,"preSum": 65628 },{ "ndv": 955,"upper": 3160439,"lower": 2908250,"count": 1562,"preSum": 67191 },{ "ndv": 977,"upper": 3425395,"lower": 3160676,"count": 1562,"preSum": 68753 },{ "ndv": 993,"upper": 3703308,"lower": 3425972,"count": 1563,"preSum": 70315 },{ "ndv": 948,"upper": 3957282,"lower": 3703431,"count": 1563,"preSum": 71878 },{ "ndv": 956,"upper": 4221694,"lower": 3957325,"count": 1562,"preSum": 73441 },{ "ndv": 971,"upper": 4500933,"lower": 4221765,"count": 1564,"preSum": 75003 },{ "ndv": 977,"upper": 4756843,"lower": 4500960,"count": 1564,"preSum": 76567 },{ "ndv": 955,"upper": 5017876,"lower": 4757055,"count": 1562,"preSum": 78131 },{ "ndv": 952,"upper": 5265892,"lower": 5017925,"count": 1562,"preSum": 79693 },{ "ndv": 955,"upper": 5516860,"lower": 5265994,"count": 1562,"preSum": 81255 },{ "ndv": 975,"upper": 5777220,"lower": 5517068,"count": 1562,"preSum": 82817 },{ "ndv": 1006,"upper": 6040616,"lower": 5777280,"count": 1562,"preSum": 84379 },{ "ndv": 979,"upper": 6305771,"lower": 6041277,"count": 1562,"preSum": 85941 },{ "ndv": 997,"upper": 6575281,"lower": 6306048,"count": 1562,"preSum": 87503 },{ "ndv": 976,"upper": 6841357,"lower": 6575436,"count": 1562,"preSum": 89065 },{ "ndv": 955,"upper": 7085539,"lower": 6841422,"count": 1562,"preSum": 90627 },{ "ndv": 977,"upper": 7351748,"lower": 7085812,"count": 1562,"preSum": 92189 },{ "ndv": 1007,"upper": 7608910,"lower": 7352382,"count": 1562,"preSum": 93751 },{ "ndv": 981,"upper": 7858480,"lower": 7609090,"count": 1562,"preSum": 95313 },{ "ndv": 997,"upper": 8138849,"lower": 7858809,"count": 1562,"preSum": 96875 },{ "ndv": 890,"upper": 8388497,"lower": 8139178,"count": 1487,"preSum": 98437 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_mediumint_1.null_count:
+    0
+  cest_full_table_big.c_mediumint_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_mediumint_24.TOPN:
+    { "countArr": [ 44,22,51,28,34,22,57,24,37,32,36,34 ],"valueArr": [ -7399610,-6819370,-3963279,-3407157,-2874889,-1369445,607065,1094542,2735753,3053392,5651230,5856876 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_mediumint_24.cardinality:
+    480838
+  cest_full_table_big.c_mediumint_24.histogram:
+    { "buckets": [ { "ndv": 912,"upper": -8140422,"lower": -8388483,"count": 1556,"preSum": 0 },{ "ndv": 924,"upper": -7880122,"lower": -8140258,"count": 1564,"preSum": 1556 },{ "ndv": 943,"upper": -7602511,"lower": -7880099,"count": 1556,"preSum": 3120 },{ "ndv": 918,"upper": -7342554,"lower": -7602190,"count": 1558,"preSum": 4676 },{ "ndv": 916,"upper": -7081497,"lower": -7342210,"count": 1559,"preSum": 6234 },{ "ndv": 915,"upper": -6818265,"lower": -7081158,"count": 1556,"preSum": 7793 },{ "ndv": 902,"upper": -6535188,"lower": -6818146,"count": 1558,"preSum": 9349 },{ "ndv": 918,"upper": -6265868,"lower": -6535147,"count": 1556,"preSum": 10907 },{ "ndv": 890,"upper": -6011737,"lower": -6265865,"count": 1556,"preSum": 12463 },{ "ndv": 947,"upper": -5728427,"lower": -6011243,"count": 1556,"preSum": 14019 },{ "ndv": 944,"upper": -5449636,"lower": -5728297,"count": 1556,"preSum": 15575 },{ "ndv": 935,"upper": -5190446,"lower": -5449014,"count": 1556,"preSum": 17131 },{ "ndv": 910,"upper": -4933071,"lower": -5190322,"count": 1556,"preSum": 18687 },{ "ndv": 925,"upper": -4658327,"lower": -4932871,"count": 1559,"preSum": 20243 },{ "ndv": 911,"upper": -4383831,"lower": -4658321,"count": 1558,"preSum": 21802 },{ "ndv": 888,"upper": -4124319,"lower": -4383702,"count": 1557,"preSum": 23360 },{ "ndv": 922,"upper": -3852620,"lower": -4124254,"count": 1558,"preSum": 24917 },{ "ndv": 887,"upper": -3612109,"lower": -3852413,"count": 1557,"preSum": 26475 },{ "ndv": 929,"upper": -3346051,"lower": -3611966,"count": 1557,"preSum": 28032 },{ "ndv": 924,"upper": -3079320,"lower": -3345570,"count": 1558,"preSum": 29589 },{ "ndv": 938,"upper": -2805427,"lower": -3079101,"count": 1557,"preSum": 31147 },{ "ndv": 895,"upper": -2539032,"lower": -2805137,"count": 1556,"preSum": 32704 },{ "ndv": 893,"upper": -2269020,"lower": -2539026,"count": 1559,"preSum": 34260 },{ "ndv": 923,"upper": -1997687,"lower": -2268804,"count": 1556,"preSum": 35819 },{ "ndv": 923,"upper": -1750335,"lower": -1997614,"count": 1557,"preSum": 37375 },{ "ndv": 909,"upper": -1501426,"lower": -1750252,"count": 1558,"preSum": 38932 },{ "ndv": 900,"upper": -1253331,"lower": -1501022,"count": 1556,"preSum": 40490 },{ "ndv": 893,"upper": -988550,"lower": -1253313,"count": 1556,"preSum": 42046 },{ "ndv": 912,"upper": -734645,"lower": -988527,"count": 1556,"preSum": 43602 },{ "ndv": 927,"upper": -462156,"lower": -734281,"count": 1556,"preSum": 45158 },{ "ndv": 898,"upper": -204739,"lower": -462045,"count": 1556,"preSum": 46714 },{ "ndv": 894,"upper": 42288,"lower": -203605,"count": 1559,"preSum": 48270 },{ "ndv": 935,"upper": 308434,"lower": 43637,"count": 1556,"preSum": 49829 },{ "ndv": 922,"upper": 574336,"lower": 309044,"count": 1556,"preSum": 51385 },{ "ndv": 935,"upper": 835980,"lower": 574966,"count": 1557,"preSum": 52941 },{ "ndv": 939,"upper": 1092640,"lower": 836263,"count": 1556,"preSum": 54498 },{ "ndv": 929,"upper": 1358789,"lower": 1092762,"count": 1556,"preSum": 56054 },{ "ndv": 943,"upper": 1632328,"lower": 1359271,"count": 1557,"preSum": 57610 },{ "ndv": 907,"upper": 1888073,"lower": 1632448,"count": 1557,"preSum": 59167 },{ "ndv": 918,"upper": 2146902,"lower": 1888148,"count": 1556,"preSum": 60724 },{ "ndv": 921,"upper": 2408379,"lower": 2147146,"count": 1556,"preSum": 62280 },{ "ndv": 874,"upper": 2638111,"lower": 2408884,"count": 1556,"preSum": 63836 },{ "ndv": 909,"upper": 2893322,"lower": 2638126,"count": 1557,"preSum": 65392 },{ "ndv": 937,"upper": 3162632,"lower": 2893620,"count": 1556,"preSum": 66949 },{ "ndv": 952,"upper": 3439226,"lower": 3163177,"count": 1557,"preSum": 68505 },{ "ndv": 887,"upper": 3702498,"lower": 3439592,"count": 1557,"preSum": 70062 },{ "ndv": 901,"upper": 3956942,"lower": 3702731,"count": 1556,"preSum": 71619 },{ "ndv": 917,"upper": 4223956,"lower": 3957191,"count": 1556,"preSum": 73175 },{ "ndv": 907,"upper": 4490513,"lower": 4224111,"count": 1556,"preSum": 74731 },{ "ndv": 944,"upper": 4749636,"lower": 4490791,"count": 1556,"preSum": 76287 },{ "ndv": 909,"upper": 5016031,"lower": 4749814,"count": 1557,"preSum": 77843 },{ "ndv": 937,"upper": 5282831,"lower": 5016383,"count": 1557,"preSum": 79400 },{ "ndv": 909,"upper": 5524360,"lower": 5282895,"count": 1556,"preSum": 80957 },{ "ndv": 924,"upper": 5779708,"lower": 5524829,"count": 1556,"preSum": 82513 },{ "ndv": 931,"upper": 6031771,"lower": 5780182,"count": 1556,"preSum": 84069 },{ "ndv": 903,"upper": 6285721,"lower": 6031807,"count": 1557,"preSum": 85625 },{ "ndv": 916,"upper": 6541526,"lower": 6286008,"count": 1556,"preSum": 87182 },{ "ndv": 893,"upper": 6799864,"lower": 6541706,"count": 1558,"preSum": 88738 },{ "ndv": 908,"upper": 7037419,"lower": 6800835,"count": 1556,"preSum": 90296 },{ "ndv": 935,"upper": 7303324,"lower": 7037518,"count": 1556,"preSum": 91852 },{ "ndv": 956,"upper": 7574171,"lower": 7303612,"count": 1556,"preSum": 93408 },{ "ndv": 937,"upper": 7830384,"lower": 7574347,"count": 1558,"preSum": 94964 },{ "ndv": 942,"upper": 8114383,"lower": 7830636,"count": 1556,"preSum": 96522 },{ "ndv": 882,"upper": 8388415,"lower": 8114469,"count": 1502,"preSum": 98078 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_mediumint_24.null_count:
+    0
+  cest_full_table_big.c_mediumint_24.sample_rate:
+    0.010943651
+  cest_full_table_big.c_mediumint_24_un.TOPN:
+    { "countArr": [ 157,84,83,84,219,124,97,93,413,95,276,124,189,136 ],"valueArr": [ 494499,1002869,1023134,1143267,2212664,2490725,2756859,4450302,4497836,4834301,5562180,5721000,7019919,7122742 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_mediumint_24_un.cardinality:
+    438709
+  cest_full_table_big.c_mediumint_24_un.histogram:
+    { "buckets": [ { "ndv": 823,"upper": 129197,"lower": 207,"count": 1529,"preSum": 0 },{ "ndv": 783,"upper": 254482,"lower": 129215,"count": 1531,"preSum": 1529 },{ "ndv": 807,"upper": 389373,"lower": 254547,"count": 1530,"preSum": 3060 },{ "ndv": 784,"upper": 515802,"lower": 389726,"count": 1529,"preSum": 4590 },{ "ndv": 812,"upper": 649486,"lower": 516146,"count": 1529,"preSum": 6119 },{ "ndv": 833,"upper": 779620,"lower": 649585,"count": 1529,"preSum": 7648 },{ "ndv": 790,"upper": 919355,"lower": 779660,"count": 1529,"preSum": 9177 },{ "ndv": 844,"upper": 1055037,"lower": 919469,"count": 1529,"preSum": 10706 },{ "ndv": 800,"upper": 1177239,"lower": 1055167,"count": 1532,"preSum": 12235 },{ "ndv": 829,"upper": 1319189,"lower": 1177402,"count": 1541,"preSum": 13767 },{ "ndv": 870,"upper": 1459021,"lower": 1319233,"count": 1529,"preSum": 15308 },{ "ndv": 860,"upper": 1598201,"lower": 1459045,"count": 1529,"preSum": 16837 },{ "ndv": 781,"upper": 1721664,"lower": 1598229,"count": 1529,"preSum": 18366 },{ "ndv": 838,"upper": 1865305,"lower": 1722243,"count": 1530,"preSum": 19895 },{ "ndv": 793,"upper": 1999211,"lower": 1865389,"count": 1529,"preSum": 21425 },{ "ndv": 815,"upper": 2133117,"lower": 1999867,"count": 1532,"preSum": 22954 },{ "ndv": 812,"upper": 2268373,"lower": 2133328,"count": 1529,"preSum": 24486 },{ "ndv": 742,"upper": 2377765,"lower": 2268713,"count": 1530,"preSum": 26015 },{ "ndv": 812,"upper": 2510609,"lower": 2378021,"count": 1529,"preSum": 27545 },{ "ndv": 795,"upper": 2644537,"lower": 2510632,"count": 1529,"preSum": 29074 },{ "ndv": 809,"upper": 2780027,"lower": 2644556,"count": 1529,"preSum": 30603 },{ "ndv": 854,"upper": 2917355,"lower": 2780157,"count": 1530,"preSum": 32132 },{ "ndv": 819,"upper": 3054294,"lower": 2917401,"count": 1530,"preSum": 33662 },{ "ndv": 848,"upper": 3193264,"lower": 3054361,"count": 1529,"preSum": 35192 },{ "ndv": 798,"upper": 3318258,"lower": 3193306,"count": 1531,"preSum": 36721 },{ "ndv": 802,"upper": 3443591,"lower": 3318636,"count": 1536,"preSum": 38252 },{ "ndv": 807,"upper": 3572458,"lower": 3443843,"count": 1529,"preSum": 39788 },{ "ndv": 764,"upper": 3701204,"lower": 3572530,"count": 1530,"preSum": 41317 },{ "ndv": 824,"upper": 3833066,"lower": 3701295,"count": 1539,"preSum": 42847 },{ "ndv": 825,"upper": 3965351,"lower": 3833170,"count": 1529,"preSum": 44386 },{ "ndv": 791,"upper": 4091053,"lower": 3965509,"count": 1529,"preSum": 45915 },{ "ndv": 798,"upper": 4218792,"lower": 4091335,"count": 1537,"preSum": 47444 },{ "ndv": 849,"upper": 4363422,"lower": 4218863,"count": 1530,"preSum": 48981 },{ "ndv": 820,"upper": 4502081,"lower": 4363561,"count": 1529,"preSum": 50511 },{ "ndv": 807,"upper": 4627180,"lower": 4502427,"count": 1529,"preSum": 52040 },{ "ndv": 764,"upper": 4747624,"lower": 4627182,"count": 1534,"preSum": 53569 },{ "ndv": 828,"upper": 4876886,"lower": 4747735,"count": 1529,"preSum": 55103 },{ "ndv": 892,"upper": 5027954,"lower": 4877431,"count": 1529,"preSum": 56632 },{ "ndv": 812,"upper": 5156335,"lower": 5028019,"count": 1530,"preSum": 58161 },{ "ndv": 783,"upper": 5280912,"lower": 5156458,"count": 1529,"preSum": 59691 },{ "ndv": 836,"upper": 5417558,"lower": 5281801,"count": 1529,"preSum": 61220 },{ "ndv": 764,"upper": 5533986,"lower": 5417561,"count": 1529,"preSum": 62749 },{ "ndv": 769,"upper": 5657604,"lower": 5534030,"count": 1529,"preSum": 64278 },{ "ndv": 807,"upper": 5792645,"lower": 5658398,"count": 1530,"preSum": 65807 },{ "ndv": 819,"upper": 5923512,"lower": 5792668,"count": 1529,"preSum": 67337 },{ "ndv": 786,"upper": 6062154,"lower": 5923710,"count": 1529,"preSum": 68866 },{ "ndv": 757,"upper": 6185996,"lower": 6062306,"count": 1531,"preSum": 70395 },{ "ndv": 826,"upper": 6325175,"lower": 6186203,"count": 1537,"preSum": 71926 },{ "ndv": 784,"upper": 6461631,"lower": 6325293,"count": 1529,"preSum": 73463 },{ "ndv": 869,"upper": 6599965,"lower": 6461878,"count": 1535,"preSum": 74992 },{ "ndv": 784,"upper": 6724423,"lower": 6600141,"count": 1529,"preSum": 76527 },{ "ndv": 828,"upper": 6861587,"lower": 6724497,"count": 1529,"preSum": 78056 },{ "ndv": 812,"upper": 6995511,"lower": 6861606,"count": 1531,"preSum": 79585 },{ "ndv": 809,"upper": 7117570,"lower": 6995565,"count": 1529,"preSum": 81116 },{ "ndv": 798,"upper": 7247047,"lower": 7117622,"count": 1530,"preSum": 82645 },{ "ndv": 756,"upper": 7368862,"lower": 7247203,"count": 1529,"preSum": 84175 },{ "ndv": 777,"upper": 7497516,"lower": 7369345,"count": 1561,"preSum": 85704 },{ "ndv": 705,"upper": 7617363,"lower": 7497537,"count": 1529,"preSum": 87265 },{ "ndv": 779,"upper": 7732926,"lower": 7617410,"count": 1540,"preSum": 88794 },{ "ndv": 819,"upper": 7863201,"lower": 7733189,"count": 1529,"preSum": 90334 },{ "ndv": 799,"upper": 7986290,"lower": 7863519,"count": 1530,"preSum": 91863 },{ "ndv": 827,"upper": 8113061,"lower": 7986292,"count": 1529,"preSum": 93393 },{ "ndv": 859,"upper": 8251583,"lower": 8113066,"count": 1550,"preSum": 94922 },{ "ndv": 823,"upper": 8388552,"lower": 8251638,"count": 1355,"preSum": 96472 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_mediumint_24_un.null_count:
+    0
+  cest_full_table_big.c_mediumint_24_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_smallint_1.TOPN:
+    { "countArr": [ 3468,1158,1015,839,6974,1806,1444,32505,1336,12201,2163,4658,2665,850 ],"valueArr": [ -28905,-24934,-24775,-23837,-15482,-13310,-11231,2371,4999,10686,11927,22075,22878,26192 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_smallint_1.cardinality:
+    38995
+  cest_full_table_big.c_smallint_1.histogram:
+    { "buckets": [ { "ndv": 92,"upper": -31369,"lower": -32761,"count": 606,"preSum": 0 },{ "ndv": 114,"upper": -29504,"lower": -31365,"count": 421,"preSum": 606 },{ "ndv": 33,"upper": -28971,"lower": -29465,"count": 450,"preSum": 1027 },{ "ndv": 144,"upper": -26823,"lower": -28969,"count": 423,"preSum": 1477 },{ "ndv": 124,"upper": -25055,"lower": -26811,"count": 421,"preSum": 1900 },{ "ndv": 79,"upper": -23697,"lower": -25029,"count": 506,"preSum": 2321 },{ "ndv": 80,"upper": -22406,"lower": -23695,"count": 437,"preSum": 2827 },{ "ndv": 138,"upper": -20025,"lower": -22383,"count": 701,"preSum": 3264 },{ "ndv": 67,"upper": -19091,"lower": -20019,"count": 422,"preSum": 3965 },{ "ndv": 95,"upper": -17369,"lower": -19078,"count": 525,"preSum": 4387 },{ "ndv": 85,"upper": -15979,"lower": -17361,"count": 421,"preSum": 4912 },{ "ndv": 99,"upper": -14589,"lower": -15967,"count": 907,"preSum": 5333 },{ "ndv": 30,"upper": -14192,"lower": -14583,"count": 704,"preSum": 6240 },{ "ndv": 38,"upper": -13558,"lower": -14178,"count": 439,"preSum": 6944 },{ "ndv": 100,"upper": -11990,"lower": -13501,"count": 473,"preSum": 7383 },{ "ndv": 16,"upper": -11751,"lower": -11969,"count": 421,"preSum": 7856 },{ "ndv": 139,"upper": -9842,"lower": -11745,"count": 751,"preSum": 8277 },{ "ndv": 110,"upper": -7590,"lower": -9825,"count": 421,"preSum": 9028 },{ "ndv": 46,"upper": -6804,"lower": -7586,"count": 421,"preSum": 9449 },{ "ndv": 35,"upper": -6162,"lower": -6729,"count": 666,"preSum": 9870 },{ "ndv": 47,"upper": -5350,"lower": -6133,"count": 487,"preSum": 10536 },{ "ndv": 69,"upper": -4245,"lower": -5349,"count": 425,"preSum": 11023 },{ "ndv": 37,"upper": -3844,"lower": -4242,"count": 454,"preSum": 11448 },{ "ndv": 102,"upper": -2175,"lower": -3835,"count": 563,"preSum": 11902 },{ "ndv": 85,"upper": -914,"lower": -2163,"count": 433,"preSum": 12465 },{ "ndv": 47,"upper": -62,"lower": -862,"count": 544,"preSum": 12898 },{ "ndv": 92,"upper": 1424,"lower": -52,"count": 437,"preSum": 13442 },{ "ndv": 29,"upper": 1999,"lower": 1431,"count": 721,"preSum": 13879 },{ "ndv": 131,"upper": 3669,"lower": 2051,"count": 421,"preSum": 14600 },{ "ndv": 40,"upper": 4275,"lower": 3685,"count": 651,"preSum": 15021 },{ "ndv": 68,"upper": 5501,"lower": 4283,"count": 434,"preSum": 15672 },{ "ndv": 123,"upper": 7461,"lower": 5520,"count": 428,"preSum": 16106 },{ "ndv": 86,"upper": 8599,"lower": 7465,"count": 423,"preSum": 16534 },{ "ndv": 67,"upper": 9829,"lower": 8609,"count": 669,"preSum": 16957 },{ "ndv": 42,"upper": 10483,"lower": 9841,"count": 894,"preSum": 17626 },{ "ndv": 84,"upper": 11884,"lower": 10485,"count": 507,"preSum": 18520 },{ "ndv": 91,"upper": 13396,"lower": 11885,"count": 421,"preSum": 19027 },{ "ndv": 66,"upper": 14572,"lower": 13422,"count": 484,"preSum": 19448 },{ "ndv": 7,"upper": 14691,"lower": 14588,"count": 622,"preSum": 19932 },{ "ndv": 87,"upper": 15990,"lower": 14729,"count": 422,"preSum": 20554 },{ "ndv": 71,"upper": 17011,"lower": 15992,"count": 436,"preSum": 20976 },{ "ndv": 112,"upper": 18948,"lower": 17067,"count": 422,"preSum": 21412 },{ "ndv": 103,"upper": 20790,"lower": 18975,"count": 492,"preSum": 21834 },{ "ndv": 88,"upper": 22204,"lower": 20793,"count": 494,"preSum": 22326 },{ "ndv": 115,"upper": 24155,"lower": 22215,"count": 444,"preSum": 22820 },{ "ndv": 61,"upper": 24921,"lower": 24157,"count": 426,"preSum": 23264 },{ "ndv": 65,"upper": 25774,"lower": 24929,"count": 421,"preSum": 23690 },{ "ndv": 6,"upper": 25829,"lower": 25784,"count": 477,"preSum": 24111 },{ "ndv": 27,"upper": 26164,"lower": 25839,"count": 655,"preSum": 24588 },{ "ndv": 123,"upper": 27978,"lower": 26178,"count": 431,"preSum": 25243 },{ "ndv": 104,"upper": 29330,"lower": 28004,"count": 449,"preSum": 25674 },{ "ndv": 97,"upper": 30839,"lower": 29338,"count": 529,"preSum": 26123 },{ "ndv": 105,"upper": 32759,"lower": 30878,"count": 267,"preSum": 26652 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_smallint_1.null_count:
+    0
+  cest_full_table_big.c_smallint_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_smallint_16.TOPN:
+    { "countArr": [ 3296,926,784,647,7555,1563,1298,43525,1050,14468,1943,4858,2559,684 ],"valueArr": [ -28905,-24934,-24775,-23837,-15482,-13310,-11231,2371,4999,10686,11927,22075,22878,26192 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_smallint_16.cardinality:
+    15445
+  cest_full_table_big.c_smallint_16.histogram:
+    { "buckets": [ { "ndv": 40,"upper": -31369,"lower": -32699,"count": 311,"preSum": 0 },{ "ndv": 44,"upper": -29370,"lower": -31365,"count": 284,"preSum": 311 },{ "ndv": 45,"upper": -28120,"lower": -29369,"count": 235,"preSum": 595 },{ "ndv": 64,"upper": -26095,"lower": -28118,"count": 233,"preSum": 830 },{ "ndv": 56,"upper": -23697,"lower": -26050,"count": 321,"preSum": 1063 },{ "ndv": 32,"upper": -22075,"lower": -23695,"count": 234,"preSum": 1384 },{ "ndv": 54,"upper": -20025,"lower": -22064,"count": 362,"preSum": 1618 },{ "ndv": 47,"upper": -18512,"lower": -20019,"count": 232,"preSum": 1980 },{ "ndv": 25,"upper": -17323,"lower": -18440,"count": 235,"preSum": 2212 },{ "ndv": 66,"upper": -15023,"lower": -17309,"count": 232,"preSum": 2447 },{ "ndv": 10,"upper": -14589,"lower": -14950,"count": 520,"preSum": 2679 },{ "ndv": 12,"upper": -14192,"lower": -14503,"count": 493,"preSum": 3199 },{ "ndv": 14,"upper": -13606,"lower": -14132,"count": 247,"preSum": 3692 },{ "ndv": 48,"upper": -11990,"lower": -13569,"count": 263,"preSum": 3939 },{ "ndv": 6,"upper": -11823,"lower": -11894,"count": 277,"preSum": 4202 },{ "ndv": 50,"upper": -9842,"lower": -11791,"count": 436,"preSum": 4479 },{ "ndv": 63,"upper": -7308,"lower": -9829,"count": 284,"preSum": 4915 },{ "ndv": 27,"upper": -6162,"lower": -7270,"count": 594,"preSum": 5199 },{ "ndv": 24,"upper": -5350,"lower": -6120,"count": 288,"preSum": 5793 },{ "ndv": 35,"upper": -4181,"lower": -5340,"count": 250,"preSum": 6081 },{ "ndv": 11,"upper": -3844,"lower": -4145,"count": 246,"preSum": 6331 },{ "ndv": 42,"upper": -2175,"lower": -3796,"count": 273,"preSum": 6577 },{ "ndv": 43,"upper": -480,"lower": -2080,"count": 232,"preSum": 6850 },{ "ndv": 8,"upper": -62,"lower": -460,"count": 304,"preSum": 7082 },{ "ndv": 43,"upper": 1424,"lower": -52,"count": 235,"preSum": 7386 },{ "ndv": 15,"upper": 1999,"lower": 1431,"count": 555,"preSum": 7621 },{ "ndv": 64,"upper": 3889,"lower": 2009,"count": 265,"preSum": 8176 },{ "ndv": 19,"upper": 4275,"lower": 3891,"count": 354,"preSum": 8441 },{ "ndv": 35,"upper": 5675,"lower": 4283,"count": 233,"preSum": 8795 },{ "ndv": 71,"upper": 7884,"lower": 5686,"count": 246,"preSum": 9028 },{ "ndv": 55,"upper": 9784,"lower": 7908,"count": 268,"preSum": 9274 },{ "ndv": 3,"upper": 9829,"lower": 9799,"count": 269,"preSum": 9542 },{ "ndv": 22,"upper": 10483,"lower": 9871,"count": 639,"preSum": 9811 },{ "ndv": 45,"upper": 11884,"lower": 10516,"count": 281,"preSum": 10450 },{ "ndv": 51,"upper": 13807,"lower": 11890,"count": 232,"preSum": 10731 },{ "ndv": 28,"upper": 14588,"lower": 13839,"count": 232,"preSum": 10963 },{ "ndv": 5,"upper": 14691,"lower": 14602,"count": 444,"preSum": 11195 },{ "ndv": 42,"upper": 16285,"lower": 14729,"count": 250,"preSum": 11639 },{ "ndv": 31,"upper": 17258,"lower": 16287,"count": 233,"preSum": 11889 },{ "ndv": 67,"upper": 19609,"lower": 17379,"count": 232,"preSum": 12122 },{ "ndv": 53,"upper": 21810,"lower": 19616,"count": 257,"preSum": 12354 },{ "ndv": 47,"upper": 23826,"lower": 21830,"count": 242,"preSum": 12611 },{ "ndv": 22,"upper": 24834,"lower": 23900,"count": 232,"preSum": 12853 },{ "ndv": 27,"upper": 25806,"lower": 24874,"count": 257,"preSum": 13085 },{ "ndv": 3,"upper": 25829,"lower": 25817,"count": 257,"preSum": 13342 },{ "ndv": 16,"upper": 26164,"lower": 25843,"count": 486,"preSum": 13599 },{ "ndv": 60,"upper": 28576,"lower": 26178,"count": 234,"preSum": 14085 },{ "ndv": 32,"upper": 29833,"lower": 28622,"count": 232,"preSum": 14319 },{ "ndv": 45,"upper": 31656,"lower": 29862,"count": 233,"preSum": 14551 },{ "ndv": 22,"upper": 32672,"lower": 31697,"count": 61,"preSum": 14784 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_smallint_16.null_count:
+    0
+  cest_full_table_big.c_smallint_16.sample_rate:
+    0.010943651
+  cest_full_table_big.c_smallint_16_un.TOPN:
+    { "countArr": [ 2899,706,623,454,7421,1252,1048,53117,878,15224,1576,4317,2057,504 ],"valueArr": [ 1931,3917,3996,4465,8643,9729,10768,17569,18883,21727,22347,27421,27823,29480 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_smallint_16_un.cardinality:
+    6580
+  cest_full_table_big.c_smallint_16_un.histogram:
+    { "buckets": [ { "ndv": 16,"upper": 699,"lower": 32,"count": 154,"preSum": 0 },{ "ndv": 27,"upper": 1699,"lower": 701,"count": 124,"preSum": 154 },{ "ndv": 36,"upper": 2986,"lower": 1727,"count": 124,"preSum": 278 },{ "ndv": 28,"upper": 4150,"lower": 3002,"count": 124,"preSum": 402 },{ "ndv": 15,"upper": 4742,"lower": 4229,"count": 124,"preSum": 526 },{ "ndv": 32,"upper": 6371,"lower": 4817,"count": 256,"preSum": 650 },{ "ndv": 21,"upper": 7330,"lower": 6374,"count": 138,"preSum": 906 },{ "ndv": 24,"upper": 8147,"lower": 7435,"count": 142,"preSum": 1044 },{ "ndv": 33,"upper": 9089,"lower": 8158,"count": 396,"preSum": 1186 },{ "ndv": 8,"upper": 9288,"lower": 9132,"count": 276,"preSum": 1582 },{ "ndv": 8,"upper": 9633,"lower": 9296,"count": 125,"preSum": 1858 },{ "ndv": 17,"upper": 10472,"lower": 9699,"count": 249,"preSum": 1983 },{ "ndv": 23,"upper": 11463,"lower": 10488,"count": 223,"preSum": 2232 },{ "ndv": 32,"upper": 12798,"lower": 11501,"count": 146,"preSum": 2455 },{ "ndv": 13,"upper": 13303,"lower": 12804,"count": 307,"preSum": 2601 },{ "ndv": 9,"upper": 13709,"lower": 13326,"count": 147,"preSum": 2908 },{ "ndv": 15,"upper": 14293,"lower": 13732,"count": 137,"preSum": 3055 },{ "ndv": 6,"upper": 14462,"lower": 14311,"count": 189,"preSum": 3192 },{ "ndv": 20,"upper": 15296,"lower": 14477,"count": 167,"preSum": 3381 },{ "ndv": 29,"upper": 16232,"lower": 15344,"count": 195,"preSum": 3548 },{ "ndv": 18,"upper": 17096,"lower": 16275,"count": 193,"preSum": 3743 },{ "ndv": 6,"upper": 17383,"lower": 17185,"count": 409,"preSum": 3936 },{ "ndv": 31,"upper": 18427,"lower": 17423,"count": 124,"preSum": 4345 },{ "ndv": 3,"upper": 18521,"lower": 18435,"count": 213,"preSum": 4469 },{ "ndv": 21,"upper": 19484,"lower": 18525,"count": 124,"preSum": 4682 },{ "ndv": 25,"upper": 20555,"lower": 19562,"count": 125,"preSum": 4806 },{ "ndv": 20,"upper": 21298,"lower": 20569,"count": 229,"preSum": 4931 },{ "ndv": 11,"upper": 21625,"lower": 21321,"count": 425,"preSum": 5160 },{ "ndv": 19,"upper": 22326,"lower": 21642,"count": 135,"preSum": 5585 },{ "ndv": 27,"upper": 23192,"lower": 22359,"count": 124,"preSum": 5720 },{ "ndv": 13,"upper": 23729,"lower": 23213,"count": 443,"preSum": 5844 },{ "ndv": 13,"upper": 24526,"lower": 23748,"count": 134,"preSum": 6287 },{ "ndv": 13,"upper": 25133,"lower": 24562,"count": 148,"preSum": 6421 },{ "ndv": 40,"upper": 27034,"lower": 25231,"count": 124,"preSum": 6569 },{ "ndv": 26,"upper": 28033,"lower": 27061,"count": 124,"preSum": 6693 },{ "ndv": 13,"upper": 28507,"lower": 28046,"count": 143,"preSum": 6817 },{ "ndv": 29,"upper": 29121,"lower": 28533,"count": 124,"preSum": 6960 },{ "ndv": 5,"upper": 29298,"lower": 29139,"count": 179,"preSum": 7084 },{ "ndv": 6,"upper": 29466,"lower": 29305,"count": 291,"preSum": 7263 },{ "ndv": 34,"upper": 30709,"lower": 29470,"count": 124,"preSum": 7554 },{ "ndv": 26,"upper": 31568,"lower": 30769,"count": 124,"preSum": 7678 },{ "ndv": 21,"upper": 32757,"lower": 31573,"count": 123,"preSum": 7802 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_smallint_16_un.null_count:
+    0
+  cest_full_table_big.c_smallint_16_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_text.TOPN:
+    { "countArr": [ 2129,747,1152,2604,1061,4041,663,8212,877,1720,929,1401,654,622 ],"valueArr": [ "272901f7b4866c38cfdad0ee58e710055bd6f342c756efa3ea2c5414d1c8d334c9cd42fff815d8c800a1a7bc096cf77897e8375e32b12cb22a33cd62d840c68d","2aa4d5c39254825a73c8285fdfd0cb082cdbc465bff473642e153dbf9818be56f217072a5c7867fbcecbf15e47b88de9d80f468b8f6a85f955d20f808c77d42a","4a9e0d094ccec5f3ab0ee0ccdae5d42db6ff517ba578c8d9487aece02602c334733224fac97026bf3367678500458693ccb86eb285b","5ee951d1927147b17bb57cf07545f785341b9aeb920e85ca1c","884e206f2e3ec07a388151bddf4d2362db2a90a8ece685e96e1c2befd992ca6d4320460c618cf5ec78a7932c7cc4ae2a50962f5e8b820853f2773ec79f9aa865","8f4b82ccc477a1d4817a0713716a1a9e0abdb99fb556d066bd4663a261367328af7c4f078b4283c7d3bde3398bbeb466cd176ee7150e33107dca10c8322e0e","9081f4c0e8c85ee47ead80cdbc5f081e9cc6428718903b5f35107125e08896ba5f5172f9b5428ba371a6137715b9433d6b85cbb56c7f274ce7f86b6f66a5e313","ae093e295bf106c3d99ebb56b5c6978fb3e","b200919aa862b99712074cde83b3c18e25c4fd15","bc10f23cffb6b25587d94e646accc5b988bcb651c161925d2c5f8aa0bac12f1f290ab10f38fb5c727ad5da443c2daad1fe27901a5b9f79cd93a","c292b6a83f3518061f48c1dad1fa4d2c3e19eefcf6d90a0b08b456ab655a4c1e28257a3691b286cd81108acb9981558e411ab13520eaae125e4160f7d409d7f9","ce073c56e6291d3fcb1050e6a705e143712f1272439d96200d18b826e","cfe9b21e9d0bee82cf485c1644e7fc722764462d88e885b27cea8dead24cf1279a75c78df843678c4244278a8c7172d240d27e597f4975610eaf6da3176269ef","dd946928cf4b699b145e020fde6ca56b98c6bcb81e47f3dc93c76a5e2c6b9487a" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_text.cardinality:
+    243039
+  cest_full_table_big.c_text.histogram:
+    { "buckets": [ { "ndv": 166,"upper": "01dde7823023499a10f85591dc6af7747d89c8aa5b5","lower": "0","count": 1144,"preSum": 0 },{ "ndv": 571,"upper": "07cdf3cec6575290c3605446ed","lower": "01de5a4451a0e2648f4124d2e6c725a8302e48c132bc53022ca7462861f814dabb4f87ffc3a1e9357194adf600e97ac3e9816416b348fbb7d993843ca4861a9c","count": 1144,"preSum": 1144 },{ "ndv": 385,"upper": "0b9a1d61777836df3728cafa83c438b50f788c8c877bf0","lower": "07ceb4fa2aa3d114bf15a103d51f2a325543269a30de9b082851","count": 1145,"preSum": 2288 },{ "ndv": 511,"upper": "1113f79e0f5556eb128234780d9dc43dac44ff6f02d36cfe453ce7740f7bbacc9cbd9c8fff34e16bcf2f0d4d2f8b14990aba3f5d557e19d21dac182b7eaed214","lower": "0b9c4e79f1ff05e2dcf2cc92ae6d00c41dae43730263ca5658c0d3a3d1bf1c3a517bde9064e517d7eb344db3ca6a078a2ae3061c3f186809b3350dd9770f816c","count": 1190,"preSum": 3433 },{ "ndv": 190,"upper": "1311e1fd42260161612493575ce96bb850c6d5bcff96788f2e684e4b85bdfa805b539b0f6dd915c4a950ec4","lower": "111522044fa68d83ef2dc4c163eef6bbff2f6ee58fd5e6b0779a3558a95cc073723bbe5a27ebb52868941fa6a6fbafbce2b4dab2ff54b80a7b0a868b67d2e804","count": 1449,"preSum": 4623 },{ "ndv": 495,"upper": "17f78","lower": "1312df8d2b0b162234bf63e35e04457ca5c44cb3a93f0fdb9d4e676bedbd18dd42ac0efbcdfc822acfe3","count": 1293,"preSum": 6072 },{ "ndv": 330,"upper": "1b2b044fa17eb9b2ff7798fdbdacfd9375b20ca0f022e75c6da410673d96","lower": "17f7c2386996a38ce235cba0f1b009829aa9816a794437c4eeab3afb5094145d083","count": 1145,"preSum": 7365 },{ "ndv": 508,"upper": "205bb8f17e5224cfe3f2a340724491356c2e44adb8225890e19d820326c8a1392530aec1f4d07f994db22c6dabf1d230c81133038161de925bde002ffa9abbbe","lower": "1b2ccd0ca37e1b3902f4794b5fb5ba11","count": 1166,"preSum": 8510 },{ "ndv": 395,"upper": "2489cf31553d6e40d04c8f6","lower": "20609b96de0278b56462c3e104ef76f789e074927d7ee81d207b1fafcbe3f8266f4a268476909d8e2e7a","count": 1204,"preSum": 9676 },{ "ndv": 431,"upper": "28b02ac065e2cc1bbe517930e1d07f04e5cd8ec8c01488f9","lower": "248c920cebc921cb395d00fd3e2b567572e36fc773","count": 1144,"preSum": 10880 },{ "ndv": 369,"upper": "2cb456ee2d29c4703cfe26e290adffa03be1df47c17bc21332782fd9a067867edb1cc436cfc019762b0ab2732cfc735487969d8dd3ddf25e","lower": "28b0526659a25aefb71d8d34c6c146378bb40abd36f74d3694ebb61939c5f0bf8d5d828e86987619287886c4f901b89b6a57a45fde4fed074cb5c749e355d446","count": 1145,"preSum": 12024 },{ "ndv": 401,"upper": "310a1471df0f7661b08941c102ecf376","lower": "2cb527aa5bfd4468f64fa2d2ac61ecaf45615ca1965c91bd9c6be1cb2255377ced816533f80c91bafb93c0dfcc71de9c164","count": 1202,"preSum": 13169 },{ "ndv": 461,"upper": "35c6c1279085e58dc930071b7bdd15114913135ea39ad2ac6d1ef39cd07d","lower": "310b22f9931e4f311fe42fca59b4f23ed1e6dae708a59af169e491dba8ac7e98eb60070b40d253c3d8c0b5e9573b08f009c02ad44124d3609f9e400105b155","count": 1146,"preSum": 14371 },{ "ndv": 384,"upper": "393c28a88a013c7c969d008ea2972ec2a0d1ffd23cb361656617ae133e1357a14411438fc5a447e0bd9e0427cadea0dcf6af6a9bfc8abf0ec361fd91d66d5382","lower": "35c9f453764aaa291bcc895f7e258eb13eb04da91c0101c90365e41fbfb22ee953916a708d67c3dbbd287c3c0072d31d1fab8d9f3e97fea5d91f952e3319df0f","count": 1144,"preSum": 15517 },{ "ndv": 373,"upper": "3d307f1902b9f2d8bcd78b556f3b6f62208153308d7bf810cc471cb9fc47dabb68fbbd2f1a8e95a6fb5183389132f0e0dcf8f52e3a1c9bb3","lower": "3942568ee95b7b3f8573f806857903cd4dc87f88c3a9982797b2f2f578bd37e19dc8d8bd652efe5c713bfbab387e24e9c065","count": 1144,"preSum": 16661 },{ "ndv": 381,"upper": "410e26cac9e7f8d25b7689111f0a62a21eb4d63ea6169f95e7c167c5ca784b190127","lower": "3d323107538c7e2059be414e5cf6","count": 1144,"preSum": 17805 },{ "ndv": 218,"upper": "435a8cc58fc6c26aa437323744258f622fe49f4a06ef984d93be","lower": "4111485b903225eb7ad50fa9f854b7dbdfa9d051922c03b99fbddbd6afd7d34dc0d3189","count": 1164,"preSum": 18949 },{ "ndv": 423,"upper": "4771f0477e5fdc9a9cb582cac0a78809adc7504e6671ab16171db96f7667f5ffef8746e6f7d10100afdd78132ab081f0c585061ff62cd8d9ecfeea1fdbd01f26","lower": "435aa344d995f0d25513e501b98dbe5cf979c29e00ba08173ffda95a3e9a50c446d28b344049ccdbcb102c25cccd","count": 1164,"preSum": 20113 },{ "ndv": 581,"upper": "4da801e50c2431beab882819538ac3ba91868f642acbff073b68daa20b0f9c73b91a5d14b6b31bc507bb538a799c01b3507c41c02debda78f0f225f8eab84083","lower": "47737e5333b789dfe19c9e5ef8f417d87f1efbbdf29b539b5e88501f7e78b240080155e1cf7aaaccb5fd95740b3154566a1926d159c42f2","count": 1148,"preSum": 21277 },{ "ndv": 370,"upper": "519bef86b1ccf9a9f129a7b279e6adea1e505aef2cab78ff299182674ee5a488c7ffce8626a4","lower": "4da9d3313d55edf9e34b87eef7bc3696","count": 1144,"preSum": 22425 },{ "ndv": 297,"upper": "551a06c68d3a9bb87456c05c97d467af6daa215a60d785b5fdc549e04aaca3c877ce53236bc762d96f09","lower": "51a409db586ec283c1fc2132165ac08fb45","count": 1164,"preSum": 23569 },{ "ndv": 348,"upper": "58cbf97af20e30bc9d364928e1277d20437cecc31581e9889103826d6267","lower": "551de0f7595d913b67db679d834eea6abe1adbd3dba6e54a79eac7cbfa6b6295fa98bd8c89e58b81074fa267b633f76ad5e4c2788a61d1c3615daba6cff41f62","count": 1144,"preSum": 24733 },{ "ndv": 409,"upper": "5d8640d86728c786910ba253a149dd6aca1b6ecd3cd474e5ce7b5a73535d5aaa8","lower": "58ccca4da871e16053350dc6133b61a2f0e3347919d530830d6a304a28ef227228e6499a369b277c022a4fea645a4ffca685eb74a46de26f804bfaff856af6da","count": 1144,"preSum": 25877 },{ "ndv": 250,"upper": "600517214987915eb4b511d","lower": "5d89b00c7ae9609a56f860145a17288025d78e89f9d25d82fb9f52d004b7de35f7a4320","count": 1149,"preSum": 27021 },{ "ndv": 426,"upper": "64964da26aa4e7a9af119b294728d91b4de9a2325df7c48d84b5b3967cffa705b3a0eabe9e77238d531f32755f38e508d4a259664ad61a3e8920e091cf9556e5","lower": "600555308b687a517a222010da541b87bc91e20a575e2","count": 1144,"preSum": 28170 },{ "ndv": 429,"upper": "6942ff1081136f3da0b7476533b69326ca477b5a73247af40f888805800ce02eeb1f961226f894ab5f73a83c8f58540f05d7a0ea4c9d2f72bcafe13b0d09749","lower": "649b84b63259e926e711a3fc8833fb57de343facf70438e3ad2262f29e95d4a0221e4d0cbb758557c4e773bc91f8e13fecf6193eca7924fd01635801f5ede29f","count": 1157,"preSum": 29314 },{ "ndv": 380,"upper": "6cddfd7e5019351d73d33114f9ab41d5998d5239d08d6673030de3aab26e013e0051223e70e8c3ad32f0c5d47f28ec8a1241d4efcf9","lower": "6943ec3","count": 1145,"preSum": 30471 },{ "ndv": 376,"upper": "70fbc0f930b1fd11fc8c5dd41d03c6a00e394aaded595d2d814cd7fcb906dcf74ddf86204a23aadcebc88a0b9df27acef465a4e9e8501c9b0511d5378740821b","lower": "6cde863eb5663a369a80e89d284b25dbc41087ec66c990fe6ad024f8362a58354a47bef569f97c59d793268ac9bf88517d7ec1c1153cf05d53557fca79642d62","count": 1176,"preSum": 31616 },{ "ndv": 511,"upper": "75ef4b54dc599d666e7a3de4041871b3956eebd9ed09a18fed3f3f65","lower": "70fc35302222e96999a91ed3e97ac107b23108f6c3432f907b3fd7452bf39906197c75253a451f24cf9fd0","count": 1145,"preSum": 32792 },{ "ndv": 238,"upper": "78a7366861ab7ce92b374eb5360e91c26cbbdd07cefd0e5d3214ea9846e42fbea5cecc0a5047718128b3d6c602f","lower": "75f563470684ec8915306216a68b20018b7f6c62eeb00e6719d0d3012a7f24c1185b70c17ae6d87ec0da05d92c5cdfe5af6562771","count": 1293,"preSum": 33937 },{ "ndv": 305,"upper": "7bce56eca9c26cb210a25dffcf43059de09f3455e2cccd5df1485d7511f91179336950b328e85fd9a71b01a97859e615aeb2e42dd54848c3f8c344bcb5832cf1","lower": "78adc2ff26e81b837ce112db9a0d2f93f60f6854c4f3237d3a748547b5cfe69c445d","count": 1144,"preSum": 35230 },{ "ndv": 420,"upper": "80363a49a4cc7341902df6ce6fbfd74d954bd5","lower": "7bcea9d50d31c8498d8cf8","count": 1144,"preSum": 36374 },{ "ndv": 570,"upper": "865a67b","lower": "803726da7566e2b0997a69ea4fef74b1defc4fdd4626c05a489f20fd","count": 1155,"preSum": 37518 },{ "ndv": 472,"upper": "8bad08a020fa6c69a6d854adc3a9a69adeb827c241c58e8cd0ed5b764acafe8ebb4994f7a154c759c22121","lower": "865e3e30150c71ef5c147e2f791824baaecdc6c8348ad3016d988480dc75860d2","count": 1159,"preSum": 38673 },{ "ndv": 396,"upper": "8fc094b25226d","lower": "8baea5bc5b18b57f390565b1e4498111518376b44835305301e6a63c15a10da0186006de2553b825a511fedc880a48e7e1ae465f31a7441dc74","count": 1193,"preSum": 39832 },{ "ndv": 487,"upper": "94e6805e4cb50b0de6452fdb1f13903ff5f43da62c386918a03e9b4088f6038990496b92e277f28","lower": "8fc221e7d48e26840ad9176d73748fc070afbb17bc7d997d85013d3ffbc9eecc7842f33c0f28842299e7a3e8986504d421c73a9f24c40bd1e31a5e527b1f8d46","count": 1147,"preSum": 41025 },{ "ndv": 413,"upper": "9915b87a2041bf6a270e45975bfd1a09a462398feb3a5e67d1846ef1e7b25a5a3d6017d194f1eab439fa11f4d45791efd25bf3907e746c6a621c40434","lower": "94eaa84fb21c92eda965a7ff6f09eaec008894f9b63690334eca1c194b46be91207585f40e44a131f599162a09dbebe47a1509f9512f375246184286f8b577c5","count": 1150,"preSum": 42172 },{ "ndv": 445,"upper": "9df4d4a6cf35bd72af2b434aa0074c1","lower": "99188be58a271d35dfd9f40cd8dd7f409b1","count": 1187,"preSum": 43322 },{ "ndv": 406,"upper": "a2593a8baa44859a28391d02f76cc5cb45cfd2c2be7fb4b3a51f165b26b38e6c14ad81976bd9f4484","lower": "9df89145d45c9621914c9de1dc953e3ffbe0d6da6292cf4199d15b2635339a2e785fbd00b76a9","count": 1144,"preSum": 44509 },{ "ndv": 381,"upper": "a63b8c7670964cd0cfff43dc7a9e8f9c579fa0e3c37623a740b66cfd4a9071585e1266bd497","lower": "a25a0736f3a0ccb5d4b50d82a4f394629e1fd392ef4521262431e43082f46befeb8d54faa5d120800b496b24c667ab0487030b8963fa464","count": 1144,"preSum": 45653 },{ "ndv": 133,"upper": "a78433bb821ad674545f2bc3e330c9","lower": "a63ea9052d2cbba45d76706520b6953","count": 1148,"preSum": 46797 },{ "ndv": 275,"upper": "aa87e20d809ea68cec8432c2ad232f96d0131083ec9889a4facbcceba06e2ee999dc5c73c9b0","lower": "a7880d21936c3741daf312fc59a9802ba4b69bac0b585a2e992534319b2adc08b6aaff5acf5a2d904b6c0df7d60780dcf7986b085208042e97ce70104d61ccc1","count": 1145,"preSum": 47945 },{ "ndv": 326,"upper": "ad81e341f78942b","lower": "aa8802ae6bb9b04944e3264fd8684e5645bd7d1a646a47452fe71b4ed11ea5e8ed66573","count": 1228,"preSum": 49090 },{ "ndv": 327,"upper": "b0d576543155bf9f29a26a879c787ecd9f373ad5f7c2f1f7620430d6b2ac81e207dd76788de62d2","lower": "ad84002312b9d0734e48f7f04cf2a3bfc3db0c25d0cec1f0114906ad","count": 1145,"preSum": 50318 },{ "ndv": 286,"upper": "b3fde7a2d12db2df9ec2697488f2f358bd2289618feb27461ee1710072eaccda","lower": "b0dfac283ebe21769c6f9e9142b43837fbb95333c3a964809aea45b1898a8adf025e649f616f2f2cf2d0a865c79c1a364ec0b47c1638a767e5d1fe","count": 1148,"preSum": 51463 },{ "ndv": 377,"upper": "b842dbb21a8c84a7f74ab68d92cbc4e956115b9dcf6b72d9e0ec63b25c7acdb12eddba1360fb37feba526f32d00679164184c4df88efee76c875c39f6341c9d8","lower": "b3ff048dfe3df932fa34248fc748cd97627a64c8","count": 1144,"preSum": 52611 },{ "ndv": 474,"upper": "bd12f5300e","lower": "b8441c2092789be9997850426d03ba7b2a5a05ebdbc5f99318413d860a80","count": 1151,"preSum": 53755 },{ "ndv": 463,"upper": "c2081b11e74107819a055179b7b8dbae75fd2c76da570b5644e5d191bbdfae9d18b4beaf025e0ef11d83d4bb8d06263322216d3662cff64e6eb886b2cce9cc4b","lower": "bd1352ca904f61edad8ad5577ecef08c5dd97e9ee79e662b789a37d741e80479435026edc36b3620bc1aa27f989f049acfd9ad6a6fdb57a06b7651295623b873","count": 1173,"preSum": 54906 },{ "ndv": 379,"upper": "c62b9455f9e6c7b9f68fe953575f5f9d35cfd3b591451fe5da7b282e0f493a6a88a818ff42d02d270d55ba476e03d3b5dc6da6245a968a8e839cd8509f985aa7","lower": "c20d91b52e16834d284f2e726f08b20234545d4","count": 1144,"preSum": 56079 },{ "ndv": 395,"upper": "ca4c35f99bfd3e05e12934db4","lower": "c62cbe63bfe40e26eb92b04bd60a0a64b8e4088128ad1458dd0041bfde2d9fb8c725b8b7366696a6ee14c38752ecd27b377b2ef80cd2c4d055869f4e5edb9ced","count": 1144,"preSum": 57223 },{ "ndv": 464,"upper": "cf7891b44f7dd6d7095ed9","lower": "ca4d8032af9b36de8060d272645e0d7d7fcb6f57c52b2ebf82a8ef","count": 1146,"preSum": 58367 },{ "ndv": 458,"upper": "d454a6d07f437a9e64e6","lower": "cf790731e1f5d6d4185db7e3f593b92ca6e8e0aec77384db9792efab2f332e2093ce1cd3ad40c64ea07aa436be557b49418fef4b7e8170044bb4925e7496b2fe","count": 1146,"preSum": 59513 },{ "ndv": 394,"upper": "d878e482d6334a6c662d69f11f134ee3eeff2170ce21e80ff0e96e135d1f803e452b73c952d4435039769efe467cdcda83ad27ebe7ebccf314d1ecf7e7f96e13","lower": "d456143","count": 1154,"preSum": 60659 },{ "ndv": 360,"upper": "dc0e7da4200ca9a3ec8a6e16f42","lower": "d87929e38417eae8835340af4c0fbaf412e056570c487e016afe69656e885787b92c06d8cc9b384b2155a7bcc86e5ea0281b0aa8b9ad9399dcf0687ce2d2d780","count": 1144,"preSum": 61813 },{ "ndv": 421,"upper": "e09e86ce83605d38880c6491a69f2755d7ca5715675f0403aefb2a302fc28010704c296f","lower": "dc1623326522a343","count": 1144,"preSum": 62957 },{ "ndv": 355,"upper": "e4504b2a1dee2aea0d09c559dcf1caeb50fe5b0c59c8c0acc8e24208ae89ea2efc618866d8d747072389f79753af97969da70a701b6e1062e8cefafe9de98711","lower": "e09f02af00ab5e7025e43d06c6f4c128e01d32b4c806dcf1fc95a749c9d81b794bf0b295bb7c5b538431d0880ec374e0af5fb7ad2807457709d648b5f1554031","count": 1144,"preSum": 64101 },{ "ndv": 432,"upper": "e8baa59dfd4044601121ce6ad0160649f4f79a11a9e582f5108a6f0f3f58a1a5e07aff705a585f2b05a89984333d70a917ad942c618adbc9559cec9d817eb937","lower": "e451bdf0d7fd0d48d1c5ab7f16d08582992286531cf1b9a3e1f3d10439e","count": 1145,"preSum": 65245 },{ "ndv": 442,"upper": "edc5fb707b60b40c546cc3eb09dd4323ab4ea43c520dc3dce14bb02364ab1473aca79929e3963abfabb3c41e2fee43f005f429d76cb404ac90b163cc9fcaaf9a","lower": "e8bb7926864e4aef02b247e52f55b47979941b10cd4b709c0f5a9fd2270f6514e4d9d7c67acb8442c7f2e56ded318952ca0cd83d7266e8416f49951ad17a8789","count": 1144,"preSum": 66390 },{ "ndv": 396,"upper": "f1b6b62ace4cc416c97c45cf3831e1a47249f9753fb1c15fa694cd10237a597d3587ca099f8707ef5bf7cdda6cb843c45ded20d2963","lower": "edc723027c6aba7bef4dbc91bbb3602e5bca2848dbbdba121a36dbafc224b2aea18b874a86a23f790004a271c902b25dbe5942bbcdcde5e9c6daa35f33c324b9","count": 1145,"preSum": 67534 },{ "ndv": 425,"upper": "f6142003c59c5ebe8a978edee6529242f50894519c338ed2e4a199d3a14c501b0ba463d08dc27d0f96d14768985bd89c6ed5164be5caecddec46efa7109cd63c","lower": "f1bb5c7eeff9b184f42ddeada669","count": 1144,"preSum": 68679 },{ "ndv": 368,"upper": "fa0d4de16b01a9993262227728e9b287384cca5210f17f529d8dbabc8beefc55e1b644c85335e77b5030a2339559f13b0a17199c18f0689de84bf4865e3c0e81","lower": "f620ee113e5e40e36aed2282209513d0bfb9ceb9473209","count": 1146,"preSum": 69823 },{ "ndv": 370,"upper": "fded7fa41eb780622315ce0a7","lower": "fa0d702adecc9bf","count": 1599,"preSum": 70969 },{ "ndv": 181,"upper": "fffc62ed702e63782b0ac3ebdbe63aa14e2d9b7c68a","lower": "fded80d4d500ef1ba8aec25c271debd038834fb213eece768b4adc402d914dc16fee1fae59807380e22b3a80c92ffba671d817ec4b7d919253930b2d0","count": 621,"preSum": 72568 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_text.null_count:
+    0
+  cest_full_table_big.c_text.sample_rate:
+    0.010943651
+  cest_full_table_big.c_text_long.TOPN:
+    { "countArr": [ 2129,747,1152,2604,1061,4041,663,8212,877,1720,929,1401,654,622 ],"valueArr": [ "272901f7b4866c38cfdad0ee58e710055bd6f342c756efa3ea2c5414d1c8d334c9cd42fff815d8c800a1a7bc096cf77897e8375e32b12cb22a33cd62d840c68d","2aa4d5c39254825a73c8285fdfd0cb082cdbc465bff473642e153dbf9818be56f217072a5c7867fbcecbf15e47b88de9d80f468b8f6a85f955d20f808c77d42a","4a9e0d094ccec5f3ab0ee0ccdae5d42db6ff517ba578c8d9487aece02602c334733224fac97026bf3367678500458693ccb86eb285b","5ee951d1927147b17bb57cf07545f785341b9aeb920e85ca1c","884e206f2e3ec07a388151bddf4d2362db2a90a8ece685e96e1c2befd992ca6d4320460c618cf5ec78a7932c7cc4ae2a50962f5e8b820853f2773ec79f9aa865","8f4b82ccc477a1d4817a0713716a1a9e0abdb99fb556d066bd4663a261367328af7c4f078b4283c7d3bde3398bbeb466cd176ee7150e33107dca10c8322e0e","9081f4c0e8c85ee47ead80cdbc5f081e9cc6428718903b5f35107125e08896ba5f5172f9b5428ba371a6137715b9433d6b85cbb56c7f274ce7f86b6f66a5e313","ae093e295bf106c3d99ebb56b5c6978fb3e","b200919aa862b99712074cde83b3c18e25c4fd15","bc10f23cffb6b25587d94e646accc5b988bcb651c161925d2c5f8aa0bac12f1f290ab10f38fb5c727ad5da443c2daad1fe27901a5b9f79cd93a","c292b6a83f3518061f48c1dad1fa4d2c3e19eefcf6d90a0b08b456ab655a4c1e28257a3691b286cd81108acb9981558e411ab13520eaae125e4160f7d409d7f9","ce073c56e6291d3fcb1050e6a705e143712f1272439d96200d18b826e","cfe9b21e9d0bee82cf485c1644e7fc722764462d88e885b27cea8dead24cf1279a75c78df843678c4244278a8c7172d240d27e597f4975610eaf6da3176269ef","dd946928cf4b699b145e020fde6ca56b98c6bcb81e47f3dc93c76a5e2c6b9487a" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_text_long.cardinality:
+    243039
+  cest_full_table_big.c_text_long.histogram:
+    { "buckets": [ { "ndv": 166,"upper": "01dde7823023499a10f85591dc6af7747d89c8aa5b5","lower": "0","count": 1144,"preSum": 0 },{ "ndv": 571,"upper": "07cdf3cec6575290c3605446ed","lower": "01de5a4451a0e2648f4124d2e6c725a8302e48c132bc53022ca7462861f814dabb4f87ffc3a1e9357194adf600e97ac3e9816416b348fbb7d993843ca4861a9c","count": 1144,"preSum": 1144 },{ "ndv": 385,"upper": "0b9a1d61777836df3728cafa83c438b50f788c8c877bf0","lower": "07ceb4fa2aa3d114bf15a103d51f2a325543269a30de9b082851","count": 1145,"preSum": 2288 },{ "ndv": 511,"upper": "1113f79e0f5556eb128234780d9dc43dac44ff6f02d36cfe453ce7740f7bbacc9cbd9c8fff34e16bcf2f0d4d2f8b14990aba3f5d557e19d21dac182b7eaed214","lower": "0b9c4e79f1ff05e2dcf2cc92ae6d00c41dae43730263ca5658c0d3a3d1bf1c3a517bde9064e517d7eb344db3ca6a078a2ae3061c3f186809b3350dd9770f816c","count": 1190,"preSum": 3433 },{ "ndv": 190,"upper": "1311e1fd42260161612493575ce96bb850c6d5bcff96788f2e684e4b85bdfa805b539b0f6dd915c4a950ec4","lower": "111522044fa68d83ef2dc4c163eef6bbff2f6ee58fd5e6b0779a3558a95cc073723bbe5a27ebb52868941fa6a6fbafbce2b4dab2ff54b80a7b0a868b67d2e804","count": 1449,"preSum": 4623 },{ "ndv": 495,"upper": "17f78","lower": "1312df8d2b0b162234bf63e35e04457ca5c44cb3a93f0fdb9d4e676bedbd18dd42ac0efbcdfc822acfe3","count": 1293,"preSum": 6072 },{ "ndv": 330,"upper": "1b2b044fa17eb9b2ff7798fdbdacfd9375b20ca0f022e75c6da410673d96","lower": "17f7c2386996a38ce235cba0f1b009829aa9816a794437c4eeab3afb5094145d083","count": 1145,"preSum": 7365 },{ "ndv": 508,"upper": "205bb8f17e5224cfe3f2a340724491356c2e44adb8225890e19d820326c8a1392530aec1f4d07f994db22c6dabf1d230c81133038161de925bde002ffa9abbbe","lower": "1b2ccd0ca37e1b3902f4794b5fb5ba11","count": 1166,"preSum": 8510 },{ "ndv": 395,"upper": "2489cf31553d6e40d04c8f6","lower": "20609b96de0278b56462c3e104ef76f789e074927d7ee81d207b1fafcbe3f8266f4a268476909d8e2e7a","count": 1204,"preSum": 9676 },{ "ndv": 431,"upper": "28b02ac065e2cc1bbe517930e1d07f04e5cd8ec8c01488f9","lower": "248c920cebc921cb395d00fd3e2b567572e36fc773","count": 1144,"preSum": 10880 },{ "ndv": 369,"upper": "2cb456ee2d29c4703cfe26e290adffa03be1df47c17bc21332782fd9a067867edb1cc436cfc019762b0ab2732cfc735487969d8dd3ddf25e","lower": "28b0526659a25aefb71d8d34c6c146378bb40abd36f74d3694ebb61939c5f0bf8d5d828e86987619287886c4f901b89b6a57a45fde4fed074cb5c749e355d446","count": 1145,"preSum": 12024 },{ "ndv": 401,"upper": "310a1471df0f7661b08941c102ecf376","lower": "2cb527aa5bfd4468f64fa2d2ac61ecaf45615ca1965c91bd9c6be1cb2255377ced816533f80c91bafb93c0dfcc71de9c164","count": 1202,"preSum": 13169 },{ "ndv": 461,"upper": "35c6c1279085e58dc930071b7bdd15114913135ea39ad2ac6d1ef39cd07d","lower": "310b22f9931e4f311fe42fca59b4f23ed1e6dae708a59af169e491dba8ac7e98eb60070b40d253c3d8c0b5e9573b08f009c02ad44124d3609f9e400105b155","count": 1146,"preSum": 14371 },{ "ndv": 384,"upper": "393c28a88a013c7c969d008ea2972ec2a0d1ffd23cb361656617ae133e1357a14411438fc5a447e0bd9e0427cadea0dcf6af6a9bfc8abf0ec361fd91d66d5382","lower": "35c9f453764aaa291bcc895f7e258eb13eb04da91c0101c90365e41fbfb22ee953916a708d67c3dbbd287c3c0072d31d1fab8d9f3e97fea5d91f952e3319df0f","count": 1144,"preSum": 15517 },{ "ndv": 373,"upper": "3d307f1902b9f2d8bcd78b556f3b6f62208153308d7bf810cc471cb9fc47dabb68fbbd2f1a8e95a6fb5183389132f0e0dcf8f52e3a1c9bb3","lower": "3942568ee95b7b3f8573f806857903cd4dc87f88c3a9982797b2f2f578bd37e19dc8d8bd652efe5c713bfbab387e24e9c065","count": 1144,"preSum": 16661 },{ "ndv": 381,"upper": "410e26cac9e7f8d25b7689111f0a62a21eb4d63ea6169f95e7c167c5ca784b190127","lower": "3d323107538c7e2059be414e5cf6","count": 1144,"preSum": 17805 },{ "ndv": 218,"upper": "435a8cc58fc6c26aa437323744258f622fe49f4a06ef984d93be","lower": "4111485b903225eb7ad50fa9f854b7dbdfa9d051922c03b99fbddbd6afd7d34dc0d3189","count": 1164,"preSum": 18949 },{ "ndv": 423,"upper": "4771f0477e5fdc9a9cb582cac0a78809adc7504e6671ab16171db96f7667f5ffef8746e6f7d10100afdd78132ab081f0c585061ff62cd8d9ecfeea1fdbd01f26","lower": "435aa344d995f0d25513e501b98dbe5cf979c29e00ba08173ffda95a3e9a50c446d28b344049ccdbcb102c25cccd","count": 1164,"preSum": 20113 },{ "ndv": 581,"upper": "4da801e50c2431beab882819538ac3ba91868f642acbff073b68daa20b0f9c73b91a5d14b6b31bc507bb538a799c01b3507c41c02debda78f0f225f8eab84083","lower": "47737e5333b789dfe19c9e5ef8f417d87f1efbbdf29b539b5e88501f7e78b240080155e1cf7aaaccb5fd95740b3154566a1926d159c42f2","count": 1148,"preSum": 21277 },{ "ndv": 370,"upper": "519bef86b1ccf9a9f129a7b279e6adea1e505aef2cab78ff299182674ee5a488c7ffce8626a4","lower": "4da9d3313d55edf9e34b87eef7bc3696","count": 1144,"preSum": 22425 },{ "ndv": 297,"upper": "551a06c68d3a9bb87456c05c97d467af6daa215a60d785b5fdc549e04aaca3c877ce53236bc762d96f09","lower": "51a409db586ec283c1fc2132165ac08fb45","count": 1164,"preSum": 23569 },{ "ndv": 348,"upper": "58cbf97af20e30bc9d364928e1277d20437cecc31581e9889103826d6267","lower": "551de0f7595d913b67db679d834eea6abe1adbd3dba6e54a79eac7cbfa6b6295fa98bd8c89e58b81074fa267b633f76ad5e4c2788a61d1c3615daba6cff41f62","count": 1144,"preSum": 24733 },{ "ndv": 409,"upper": "5d8640d86728c786910ba253a149dd6aca1b6ecd3cd474e5ce7b5a73535d5aaa8","lower": "58ccca4da871e16053350dc6133b61a2f0e3347919d530830d6a304a28ef227228e6499a369b277c022a4fea645a4ffca685eb74a46de26f804bfaff856af6da","count": 1144,"preSum": 25877 },{ "ndv": 250,"upper": "600517214987915eb4b511d","lower": "5d89b00c7ae9609a56f860145a17288025d78e89f9d25d82fb9f52d004b7de35f7a4320","count": 1149,"preSum": 27021 },{ "ndv": 426,"upper": "64964da26aa4e7a9af119b294728d91b4de9a2325df7c48d84b5b3967cffa705b3a0eabe9e77238d531f32755f38e508d4a259664ad61a3e8920e091cf9556e5","lower": "600555308b687a517a222010da541b87bc91e20a575e2","count": 1144,"preSum": 28170 },{ "ndv": 429,"upper": "6942ff1081136f3da0b7476533b69326ca477b5a73247af40f888805800ce02eeb1f961226f894ab5f73a83c8f58540f05d7a0ea4c9d2f72bcafe13b0d09749","lower": "649b84b63259e926e711a3fc8833fb57de343facf70438e3ad2262f29e95d4a0221e4d0cbb758557c4e773bc91f8e13fecf6193eca7924fd01635801f5ede29f","count": 1157,"preSum": 29314 },{ "ndv": 380,"upper": "6cddfd7e5019351d73d33114f9ab41d5998d5239d08d6673030de3aab26e013e0051223e70e8c3ad32f0c5d47f28ec8a1241d4efcf9","lower": "6943ec3","count": 1145,"preSum": 30471 },{ "ndv": 376,"upper": "70fbc0f930b1fd11fc8c5dd41d03c6a00e394aaded595d2d814cd7fcb906dcf74ddf86204a23aadcebc88a0b9df27acef465a4e9e8501c9b0511d5378740821b","lower": "6cde863eb5663a369a80e89d284b25dbc41087ec66c990fe6ad024f8362a58354a47bef569f97c59d793268ac9bf88517d7ec1c1153cf05d53557fca79642d62","count": 1176,"preSum": 31616 },{ "ndv": 511,"upper": "75ef4b54dc599d666e7a3de4041871b3956eebd9ed09a18fed3f3f65","lower": "70fc35302222e96999a91ed3e97ac107b23108f6c3432f907b3fd7452bf39906197c75253a451f24cf9fd0","count": 1145,"preSum": 32792 },{ "ndv": 238,"upper": "78a7366861ab7ce92b374eb5360e91c26cbbdd07cefd0e5d3214ea9846e42fbea5cecc0a5047718128b3d6c602f","lower": "75f563470684ec8915306216a68b20018b7f6c62eeb00e6719d0d3012a7f24c1185b70c17ae6d87ec0da05d92c5cdfe5af6562771","count": 1293,"preSum": 33937 },{ "ndv": 305,"upper": "7bce56eca9c26cb210a25dffcf43059de09f3455e2cccd5df1485d7511f91179336950b328e85fd9a71b01a97859e615aeb2e42dd54848c3f8c344bcb5832cf1","lower": "78adc2ff26e81b837ce112db9a0d2f93f60f6854c4f3237d3a748547b5cfe69c445d","count": 1144,"preSum": 35230 },{ "ndv": 420,"upper": "80363a49a4cc7341902df6ce6fbfd74d954bd5","lower": "7bcea9d50d31c8498d8cf8","count": 1144,"preSum": 36374 },{ "ndv": 570,"upper": "865a67b","lower": "803726da7566e2b0997a69ea4fef74b1defc4fdd4626c05a489f20fd","count": 1155,"preSum": 37518 },{ "ndv": 472,"upper": "8bad08a020fa6c69a6d854adc3a9a69adeb827c241c58e8cd0ed5b764acafe8ebb4994f7a154c759c22121","lower": "865e3e30150c71ef5c147e2f791824baaecdc6c8348ad3016d988480dc75860d2","count": 1159,"preSum": 38673 },{ "ndv": 396,"upper": "8fc094b25226d","lower": "8baea5bc5b18b57f390565b1e4498111518376b44835305301e6a63c15a10da0186006de2553b825a511fedc880a48e7e1ae465f31a7441dc74","count": 1193,"preSum": 39832 },{ "ndv": 487,"upper": "94e6805e4cb50b0de6452fdb1f13903ff5f43da62c386918a03e9b4088f6038990496b92e277f28","lower": "8fc221e7d48e26840ad9176d73748fc070afbb17bc7d997d85013d3ffbc9eecc7842f33c0f28842299e7a3e8986504d421c73a9f24c40bd1e31a5e527b1f8d46","count": 1147,"preSum": 41025 },{ "ndv": 413,"upper": "9915b87a2041bf6a270e45975bfd1a09a462398feb3a5e67d1846ef1e7b25a5a3d6017d194f1eab439fa11f4d45791efd25bf3907e746c6a621c40434","lower": "94eaa84fb21c92eda965a7ff6f09eaec008894f9b63690334eca1c194b46be91207585f40e44a131f599162a09dbebe47a1509f9512f375246184286f8b577c5","count": 1150,"preSum": 42172 },{ "ndv": 445,"upper": "9df4d4a6cf35bd72af2b434aa0074c1","lower": "99188be58a271d35dfd9f40cd8dd7f409b1","count": 1187,"preSum": 43322 },{ "ndv": 406,"upper": "a2593a8baa44859a28391d02f76cc5cb45cfd2c2be7fb4b3a51f165b26b38e6c14ad81976bd9f4484","lower": "9df89145d45c9621914c9de1dc953e3ffbe0d6da6292cf4199d15b2635339a2e785fbd00b76a9","count": 1144,"preSum": 44509 },{ "ndv": 381,"upper": "a63b8c7670964cd0cfff43dc7a9e8f9c579fa0e3c37623a740b66cfd4a9071585e1266bd497","lower": "a25a0736f3a0ccb5d4b50d82a4f394629e1fd392ef4521262431e43082f46befeb8d54faa5d120800b496b24c667ab0487030b8963fa464","count": 1144,"preSum": 45653 },{ "ndv": 133,"upper": "a78433bb821ad674545f2bc3e330c9","lower": "a63ea9052d2cbba45d76706520b6953","count": 1148,"preSum": 46797 },{ "ndv": 275,"upper": "aa87e20d809ea68cec8432c2ad232f96d0131083ec9889a4facbcceba06e2ee999dc5c73c9b0","lower": "a7880d21936c3741daf312fc59a9802ba4b69bac0b585a2e992534319b2adc08b6aaff5acf5a2d904b6c0df7d60780dcf7986b085208042e97ce70104d61ccc1","count": 1145,"preSum": 47945 },{ "ndv": 326,"upper": "ad81e341f78942b","lower": "aa8802ae6bb9b04944e3264fd8684e5645bd7d1a646a47452fe71b4ed11ea5e8ed66573","count": 1228,"preSum": 49090 },{ "ndv": 327,"upper": "b0d576543155bf9f29a26a879c787ecd9f373ad5f7c2f1f7620430d6b2ac81e207dd76788de62d2","lower": "ad84002312b9d0734e48f7f04cf2a3bfc3db0c25d0cec1f0114906ad","count": 1145,"preSum": 50318 },{ "ndv": 286,"upper": "b3fde7a2d12db2df9ec2697488f2f358bd2289618feb27461ee1710072eaccda","lower": "b0dfac283ebe21769c6f9e9142b43837fbb95333c3a964809aea45b1898a8adf025e649f616f2f2cf2d0a865c79c1a364ec0b47c1638a767e5d1fe","count": 1148,"preSum": 51463 },{ "ndv": 377,"upper": "b842dbb21a8c84a7f74ab68d92cbc4e956115b9dcf6b72d9e0ec63b25c7acdb12eddba1360fb37feba526f32d00679164184c4df88efee76c875c39f6341c9d8","lower": "b3ff048dfe3df932fa34248fc748cd97627a64c8","count": 1144,"preSum": 52611 },{ "ndv": 474,"upper": "bd12f5300e","lower": "b8441c2092789be9997850426d03ba7b2a5a05ebdbc5f99318413d860a80","count": 1151,"preSum": 53755 },{ "ndv": 463,"upper": "c2081b11e74107819a055179b7b8dbae75fd2c76da570b5644e5d191bbdfae9d18b4beaf025e0ef11d83d4bb8d06263322216d3662cff64e6eb886b2cce9cc4b","lower": "bd1352ca904f61edad8ad5577ecef08c5dd97e9ee79e662b789a37d741e80479435026edc36b3620bc1aa27f989f049acfd9ad6a6fdb57a06b7651295623b873","count": 1173,"preSum": 54906 },{ "ndv": 379,"upper": "c62b9455f9e6c7b9f68fe953575f5f9d35cfd3b591451fe5da7b282e0f493a6a88a818ff42d02d270d55ba476e03d3b5dc6da6245a968a8e839cd8509f985aa7","lower": "c20d91b52e16834d284f2e726f08b20234545d4","count": 1144,"preSum": 56079 },{ "ndv": 395,"upper": "ca4c35f99bfd3e05e12934db4","lower": "c62cbe63bfe40e26eb92b04bd60a0a64b8e4088128ad1458dd0041bfde2d9fb8c725b8b7366696a6ee14c38752ecd27b377b2ef80cd2c4d055869f4e5edb9ced","count": 1144,"preSum": 57223 },{ "ndv": 464,"upper": "cf7891b44f7dd6d7095ed9","lower": "ca4d8032af9b36de8060d272645e0d7d7fcb6f57c52b2ebf82a8ef","count": 1146,"preSum": 58367 },{ "ndv": 458,"upper": "d454a6d07f437a9e64e6","lower": "cf790731e1f5d6d4185db7e3f593b92ca6e8e0aec77384db9792efab2f332e2093ce1cd3ad40c64ea07aa436be557b49418fef4b7e8170044bb4925e7496b2fe","count": 1146,"preSum": 59513 },{ "ndv": 394,"upper": "d878e482d6334a6c662d69f11f134ee3eeff2170ce21e80ff0e96e135d1f803e452b73c952d4435039769efe467cdcda83ad27ebe7ebccf314d1ecf7e7f96e13","lower": "d456143","count": 1154,"preSum": 60659 },{ "ndv": 360,"upper": "dc0e7da4200ca9a3ec8a6e16f42","lower": "d87929e38417eae8835340af4c0fbaf412e056570c487e016afe69656e885787b92c06d8cc9b384b2155a7bcc86e5ea0281b0aa8b9ad9399dcf0687ce2d2d780","count": 1144,"preSum": 61813 },{ "ndv": 421,"upper": "e09e86ce83605d38880c6491a69f2755d7ca5715675f0403aefb2a302fc28010704c296f","lower": "dc1623326522a343","count": 1144,"preSum": 62957 },{ "ndv": 355,"upper": "e4504b2a1dee2aea0d09c559dcf1caeb50fe5b0c59c8c0acc8e24208ae89ea2efc618866d8d747072389f79753af97969da70a701b6e1062e8cefafe9de98711","lower": "e09f02af00ab5e7025e43d06c6f4c128e01d32b4c806dcf1fc95a749c9d81b794bf0b295bb7c5b538431d0880ec374e0af5fb7ad2807457709d648b5f1554031","count": 1144,"preSum": 64101 },{ "ndv": 432,"upper": "e8baa59dfd4044601121ce6ad0160649f4f79a11a9e582f5108a6f0f3f58a1a5e07aff705a585f2b05a89984333d70a917ad942c618adbc9559cec9d817eb937","lower": "e451bdf0d7fd0d48d1c5ab7f16d08582992286531cf1b9a3e1f3d10439e","count": 1145,"preSum": 65245 },{ "ndv": 442,"upper": "edc5fb707b60b40c546cc3eb09dd4323ab4ea43c520dc3dce14bb02364ab1473aca79929e3963abfabb3c41e2fee43f005f429d76cb404ac90b163cc9fcaaf9a","lower": "e8bb7926864e4aef02b247e52f55b47979941b10cd4b709c0f5a9fd2270f6514e4d9d7c67acb8442c7f2e56ded318952ca0cd83d7266e8416f49951ad17a8789","count": 1144,"preSum": 66390 },{ "ndv": 396,"upper": "f1b6b62ace4cc416c97c45cf3831e1a47249f9753fb1c15fa694cd10237a597d3587ca099f8707ef5bf7cdda6cb843c45ded20d2963","lower": "edc723027c6aba7bef4dbc91bbb3602e5bca2848dbbdba121a36dbafc224b2aea18b874a86a23f790004a271c902b25dbe5942bbcdcde5e9c6daa35f33c324b9","count": 1145,"preSum": 67534 },{ "ndv": 425,"upper": "f6142003c59c5ebe8a978edee6529242f50894519c338ed2e4a199d3a14c501b0ba463d08dc27d0f96d14768985bd89c6ed5164be5caecddec46efa7109cd63c","lower": "f1bb5c7eeff9b184f42ddeada669","count": 1144,"preSum": 68679 },{ "ndv": 368,"upper": "fa0d4de16b01a9993262227728e9b287384cca5210f17f529d8dbabc8beefc55e1b644c85335e77b5030a2339559f13b0a17199c18f0689de84bf4865e3c0e81","lower": "f620ee113e5e40e36aed2282209513d0bfb9ceb9473209","count": 1146,"preSum": 69823 },{ "ndv": 370,"upper": "fded7fa41eb780622315ce0a7","lower": "fa0d702adecc9bf","count": 1599,"preSum": 70969 },{ "ndv": 181,"upper": "fffc62ed702e63782b0ac3ebdbe63aa14e2d9b7c68a","lower": "fded80d4d500ef1ba8aec25c271debd038834fb213eece768b4adc402d914dc16fee1fae59807380e22b3a80c92ffba671d817ec4b7d919253930b2d0","count": 621,"preSum": 72568 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_text_long.null_count:
+    0
+  cest_full_table_big.c_text_long.sample_rate:
+    0.010943651
+  cest_full_table_big.c_text_medium.TOPN:
+    { "countArr": [ 2129,747,1152,2604,1061,4041,663,8212,877,1720,929,1401,654,622 ],"valueArr": [ "272901f7b4866c38cfdad0ee58e710055bd6f342c756efa3ea2c5414d1c8d334c9cd42fff815d8c800a1a7bc096cf77897e8375e32b12cb22a33cd62d840c68d","2aa4d5c39254825a73c8285fdfd0cb082cdbc465bff473642e153dbf9818be56f217072a5c7867fbcecbf15e47b88de9d80f468b8f6a85f955d20f808c77d42a","4a9e0d094ccec5f3ab0ee0ccdae5d42db6ff517ba578c8d9487aece02602c334733224fac97026bf3367678500458693ccb86eb285b","5ee951d1927147b17bb57cf07545f785341b9aeb920e85ca1c","884e206f2e3ec07a388151bddf4d2362db2a90a8ece685e96e1c2befd992ca6d4320460c618cf5ec78a7932c7cc4ae2a50962f5e8b820853f2773ec79f9aa865","8f4b82ccc477a1d4817a0713716a1a9e0abdb99fb556d066bd4663a261367328af7c4f078b4283c7d3bde3398bbeb466cd176ee7150e33107dca10c8322e0e","9081f4c0e8c85ee47ead80cdbc5f081e9cc6428718903b5f35107125e08896ba5f5172f9b5428ba371a6137715b9433d6b85cbb56c7f274ce7f86b6f66a5e313","ae093e295bf106c3d99ebb56b5c6978fb3e","b200919aa862b99712074cde83b3c18e25c4fd15","bc10f23cffb6b25587d94e646accc5b988bcb651c161925d2c5f8aa0bac12f1f290ab10f38fb5c727ad5da443c2daad1fe27901a5b9f79cd93a","c292b6a83f3518061f48c1dad1fa4d2c3e19eefcf6d90a0b08b456ab655a4c1e28257a3691b286cd81108acb9981558e411ab13520eaae125e4160f7d409d7f9","ce073c56e6291d3fcb1050e6a705e143712f1272439d96200d18b826e","cfe9b21e9d0bee82cf485c1644e7fc722764462d88e885b27cea8dead24cf1279a75c78df843678c4244278a8c7172d240d27e597f4975610eaf6da3176269ef","dd946928cf4b699b145e020fde6ca56b98c6bcb81e47f3dc93c76a5e2c6b9487a" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_text_medium.cardinality:
+    243039
+  cest_full_table_big.c_text_medium.histogram:
+    { "buckets": [ { "ndv": 166,"upper": "01dde7823023499a10f85591dc6af7747d89c8aa5b5","lower": "0","count": 1144,"preSum": 0 },{ "ndv": 571,"upper": "07cdf3cec6575290c3605446ed","lower": "01de5a4451a0e2648f4124d2e6c725a8302e48c132bc53022ca7462861f814dabb4f87ffc3a1e9357194adf600e97ac3e9816416b348fbb7d993843ca4861a9c","count": 1144,"preSum": 1144 },{ "ndv": 385,"upper": "0b9a1d61777836df3728cafa83c438b50f788c8c877bf0","lower": "07ceb4fa2aa3d114bf15a103d51f2a325543269a30de9b082851","count": 1145,"preSum": 2288 },{ "ndv": 511,"upper": "1113f79e0f5556eb128234780d9dc43dac44ff6f02d36cfe453ce7740f7bbacc9cbd9c8fff34e16bcf2f0d4d2f8b14990aba3f5d557e19d21dac182b7eaed214","lower": "0b9c4e79f1ff05e2dcf2cc92ae6d00c41dae43730263ca5658c0d3a3d1bf1c3a517bde9064e517d7eb344db3ca6a078a2ae3061c3f186809b3350dd9770f816c","count": 1190,"preSum": 3433 },{ "ndv": 190,"upper": "1311e1fd42260161612493575ce96bb850c6d5bcff96788f2e684e4b85bdfa805b539b0f6dd915c4a950ec4","lower": "111522044fa68d83ef2dc4c163eef6bbff2f6ee58fd5e6b0779a3558a95cc073723bbe5a27ebb52868941fa6a6fbafbce2b4dab2ff54b80a7b0a868b67d2e804","count": 1449,"preSum": 4623 },{ "ndv": 495,"upper": "17f78","lower": "1312df8d2b0b162234bf63e35e04457ca5c44cb3a93f0fdb9d4e676bedbd18dd42ac0efbcdfc822acfe3","count": 1293,"preSum": 6072 },{ "ndv": 330,"upper": "1b2b044fa17eb9b2ff7798fdbdacfd9375b20ca0f022e75c6da410673d96","lower": "17f7c2386996a38ce235cba0f1b009829aa9816a794437c4eeab3afb5094145d083","count": 1145,"preSum": 7365 },{ "ndv": 508,"upper": "205bb8f17e5224cfe3f2a340724491356c2e44adb8225890e19d820326c8a1392530aec1f4d07f994db22c6dabf1d230c81133038161de925bde002ffa9abbbe","lower": "1b2ccd0ca37e1b3902f4794b5fb5ba11","count": 1166,"preSum": 8510 },{ "ndv": 395,"upper": "2489cf31553d6e40d04c8f6","lower": "20609b96de0278b56462c3e104ef76f789e074927d7ee81d207b1fafcbe3f8266f4a268476909d8e2e7a","count": 1204,"preSum": 9676 },{ "ndv": 431,"upper": "28b02ac065e2cc1bbe517930e1d07f04e5cd8ec8c01488f9","lower": "248c920cebc921cb395d00fd3e2b567572e36fc773","count": 1144,"preSum": 10880 },{ "ndv": 369,"upper": "2cb456ee2d29c4703cfe26e290adffa03be1df47c17bc21332782fd9a067867edb1cc436cfc019762b0ab2732cfc735487969d8dd3ddf25e","lower": "28b0526659a25aefb71d8d34c6c146378bb40abd36f74d3694ebb61939c5f0bf8d5d828e86987619287886c4f901b89b6a57a45fde4fed074cb5c749e355d446","count": 1145,"preSum": 12024 },{ "ndv": 401,"upper": "310a1471df0f7661b08941c102ecf376","lower": "2cb527aa5bfd4468f64fa2d2ac61ecaf45615ca1965c91bd9c6be1cb2255377ced816533f80c91bafb93c0dfcc71de9c164","count": 1202,"preSum": 13169 },{ "ndv": 461,"upper": "35c6c1279085e58dc930071b7bdd15114913135ea39ad2ac6d1ef39cd07d","lower": "310b22f9931e4f311fe42fca59b4f23ed1e6dae708a59af169e491dba8ac7e98eb60070b40d253c3d8c0b5e9573b08f009c02ad44124d3609f9e400105b155","count": 1146,"preSum": 14371 },{ "ndv": 384,"upper": "393c28a88a013c7c969d008ea2972ec2a0d1ffd23cb361656617ae133e1357a14411438fc5a447e0bd9e0427cadea0dcf6af6a9bfc8abf0ec361fd91d66d5382","lower": "35c9f453764aaa291bcc895f7e258eb13eb04da91c0101c90365e41fbfb22ee953916a708d67c3dbbd287c3c0072d31d1fab8d9f3e97fea5d91f952e3319df0f","count": 1144,"preSum": 15517 },{ "ndv": 373,"upper": "3d307f1902b9f2d8bcd78b556f3b6f62208153308d7bf810cc471cb9fc47dabb68fbbd2f1a8e95a6fb5183389132f0e0dcf8f52e3a1c9bb3","lower": "3942568ee95b7b3f8573f806857903cd4dc87f88c3a9982797b2f2f578bd37e19dc8d8bd652efe5c713bfbab387e24e9c065","count": 1144,"preSum": 16661 },{ "ndv": 381,"upper": "410e26cac9e7f8d25b7689111f0a62a21eb4d63ea6169f95e7c167c5ca784b190127","lower": "3d323107538c7e2059be414e5cf6","count": 1144,"preSum": 17805 },{ "ndv": 218,"upper": "435a8cc58fc6c26aa437323744258f622fe49f4a06ef984d93be","lower": "4111485b903225eb7ad50fa9f854b7dbdfa9d051922c03b99fbddbd6afd7d34dc0d3189","count": 1164,"preSum": 18949 },{ "ndv": 423,"upper": "4771f0477e5fdc9a9cb582cac0a78809adc7504e6671ab16171db96f7667f5ffef8746e6f7d10100afdd78132ab081f0c585061ff62cd8d9ecfeea1fdbd01f26","lower": "435aa344d995f0d25513e501b98dbe5cf979c29e00ba08173ffda95a3e9a50c446d28b344049ccdbcb102c25cccd","count": 1164,"preSum": 20113 },{ "ndv": 581,"upper": "4da801e50c2431beab882819538ac3ba91868f642acbff073b68daa20b0f9c73b91a5d14b6b31bc507bb538a799c01b3507c41c02debda78f0f225f8eab84083","lower": "47737e5333b789dfe19c9e5ef8f417d87f1efbbdf29b539b5e88501f7e78b240080155e1cf7aaaccb5fd95740b3154566a1926d159c42f2","count": 1148,"preSum": 21277 },{ "ndv": 370,"upper": "519bef86b1ccf9a9f129a7b279e6adea1e505aef2cab78ff299182674ee5a488c7ffce8626a4","lower": "4da9d3313d55edf9e34b87eef7bc3696","count": 1144,"preSum": 22425 },{ "ndv": 297,"upper": "551a06c68d3a9bb87456c05c97d467af6daa215a60d785b5fdc549e04aaca3c877ce53236bc762d96f09","lower": "51a409db586ec283c1fc2132165ac08fb45","count": 1164,"preSum": 23569 },{ "ndv": 348,"upper": "58cbf97af20e30bc9d364928e1277d20437cecc31581e9889103826d6267","lower": "551de0f7595d913b67db679d834eea6abe1adbd3dba6e54a79eac7cbfa6b6295fa98bd8c89e58b81074fa267b633f76ad5e4c2788a61d1c3615daba6cff41f62","count": 1144,"preSum": 24733 },{ "ndv": 409,"upper": "5d8640d86728c786910ba253a149dd6aca1b6ecd3cd474e5ce7b5a73535d5aaa8","lower": "58ccca4da871e16053350dc6133b61a2f0e3347919d530830d6a304a28ef227228e6499a369b277c022a4fea645a4ffca685eb74a46de26f804bfaff856af6da","count": 1144,"preSum": 25877 },{ "ndv": 250,"upper": "600517214987915eb4b511d","lower": "5d89b00c7ae9609a56f860145a17288025d78e89f9d25d82fb9f52d004b7de35f7a4320","count": 1149,"preSum": 27021 },{ "ndv": 426,"upper": "64964da26aa4e7a9af119b294728d91b4de9a2325df7c48d84b5b3967cffa705b3a0eabe9e77238d531f32755f38e508d4a259664ad61a3e8920e091cf9556e5","lower": "600555308b687a517a222010da541b87bc91e20a575e2","count": 1144,"preSum": 28170 },{ "ndv": 429,"upper": "6942ff1081136f3da0b7476533b69326ca477b5a73247af40f888805800ce02eeb1f961226f894ab5f73a83c8f58540f05d7a0ea4c9d2f72bcafe13b0d09749","lower": "649b84b63259e926e711a3fc8833fb57de343facf70438e3ad2262f29e95d4a0221e4d0cbb758557c4e773bc91f8e13fecf6193eca7924fd01635801f5ede29f","count": 1157,"preSum": 29314 },{ "ndv": 380,"upper": "6cddfd7e5019351d73d33114f9ab41d5998d5239d08d6673030de3aab26e013e0051223e70e8c3ad32f0c5d47f28ec8a1241d4efcf9","lower": "6943ec3","count": 1145,"preSum": 30471 },{ "ndv": 376,"upper": "70fbc0f930b1fd11fc8c5dd41d03c6a00e394aaded595d2d814cd7fcb906dcf74ddf86204a23aadcebc88a0b9df27acef465a4e9e8501c9b0511d5378740821b","lower": "6cde863eb5663a369a80e89d284b25dbc41087ec66c990fe6ad024f8362a58354a47bef569f97c59d793268ac9bf88517d7ec1c1153cf05d53557fca79642d62","count": 1176,"preSum": 31616 },{ "ndv": 511,"upper": "75ef4b54dc599d666e7a3de4041871b3956eebd9ed09a18fed3f3f65","lower": "70fc35302222e96999a91ed3e97ac107b23108f6c3432f907b3fd7452bf39906197c75253a451f24cf9fd0","count": 1145,"preSum": 32792 },{ "ndv": 238,"upper": "78a7366861ab7ce92b374eb5360e91c26cbbdd07cefd0e5d3214ea9846e42fbea5cecc0a5047718128b3d6c602f","lower": "75f563470684ec8915306216a68b20018b7f6c62eeb00e6719d0d3012a7f24c1185b70c17ae6d87ec0da05d92c5cdfe5af6562771","count": 1293,"preSum": 33937 },{ "ndv": 305,"upper": "7bce56eca9c26cb210a25dffcf43059de09f3455e2cccd5df1485d7511f91179336950b328e85fd9a71b01a97859e615aeb2e42dd54848c3f8c344bcb5832cf1","lower": "78adc2ff26e81b837ce112db9a0d2f93f60f6854c4f3237d3a748547b5cfe69c445d","count": 1144,"preSum": 35230 },{ "ndv": 420,"upper": "80363a49a4cc7341902df6ce6fbfd74d954bd5","lower": "7bcea9d50d31c8498d8cf8","count": 1144,"preSum": 36374 },{ "ndv": 570,"upper": "865a67b","lower": "803726da7566e2b0997a69ea4fef74b1defc4fdd4626c05a489f20fd","count": 1155,"preSum": 37518 },{ "ndv": 472,"upper": "8bad08a020fa6c69a6d854adc3a9a69adeb827c241c58e8cd0ed5b764acafe8ebb4994f7a154c759c22121","lower": "865e3e30150c71ef5c147e2f791824baaecdc6c8348ad3016d988480dc75860d2","count": 1159,"preSum": 38673 },{ "ndv": 396,"upper": "8fc094b25226d","lower": "8baea5bc5b18b57f390565b1e4498111518376b44835305301e6a63c15a10da0186006de2553b825a511fedc880a48e7e1ae465f31a7441dc74","count": 1193,"preSum": 39832 },{ "ndv": 487,"upper": "94e6805e4cb50b0de6452fdb1f13903ff5f43da62c386918a03e9b4088f6038990496b92e277f28","lower": "8fc221e7d48e26840ad9176d73748fc070afbb17bc7d997d85013d3ffbc9eecc7842f33c0f28842299e7a3e8986504d421c73a9f24c40bd1e31a5e527b1f8d46","count": 1147,"preSum": 41025 },{ "ndv": 413,"upper": "9915b87a2041bf6a270e45975bfd1a09a462398feb3a5e67d1846ef1e7b25a5a3d6017d194f1eab439fa11f4d45791efd25bf3907e746c6a621c40434","lower": "94eaa84fb21c92eda965a7ff6f09eaec008894f9b63690334eca1c194b46be91207585f40e44a131f599162a09dbebe47a1509f9512f375246184286f8b577c5","count": 1150,"preSum": 42172 },{ "ndv": 445,"upper": "9df4d4a6cf35bd72af2b434aa0074c1","lower": "99188be58a271d35dfd9f40cd8dd7f409b1","count": 1187,"preSum": 43322 },{ "ndv": 406,"upper": "a2593a8baa44859a28391d02f76cc5cb45cfd2c2be7fb4b3a51f165b26b38e6c14ad81976bd9f4484","lower": "9df89145d45c9621914c9de1dc953e3ffbe0d6da6292cf4199d15b2635339a2e785fbd00b76a9","count": 1144,"preSum": 44509 },{ "ndv": 381,"upper": "a63b8c7670964cd0cfff43dc7a9e8f9c579fa0e3c37623a740b66cfd4a9071585e1266bd497","lower": "a25a0736f3a0ccb5d4b50d82a4f394629e1fd392ef4521262431e43082f46befeb8d54faa5d120800b496b24c667ab0487030b8963fa464","count": 1144,"preSum": 45653 },{ "ndv": 133,"upper": "a78433bb821ad674545f2bc3e330c9","lower": "a63ea9052d2cbba45d76706520b6953","count": 1148,"preSum": 46797 },{ "ndv": 275,"upper": "aa87e20d809ea68cec8432c2ad232f96d0131083ec9889a4facbcceba06e2ee999dc5c73c9b0","lower": "a7880d21936c3741daf312fc59a9802ba4b69bac0b585a2e992534319b2adc08b6aaff5acf5a2d904b6c0df7d60780dcf7986b085208042e97ce70104d61ccc1","count": 1145,"preSum": 47945 },{ "ndv": 326,"upper": "ad81e341f78942b","lower": "aa8802ae6bb9b04944e3264fd8684e5645bd7d1a646a47452fe71b4ed11ea5e8ed66573","count": 1228,"preSum": 49090 },{ "ndv": 327,"upper": "b0d576543155bf9f29a26a879c787ecd9f373ad5f7c2f1f7620430d6b2ac81e207dd76788de62d2","lower": "ad84002312b9d0734e48f7f04cf2a3bfc3db0c25d0cec1f0114906ad","count": 1145,"preSum": 50318 },{ "ndv": 286,"upper": "b3fde7a2d12db2df9ec2697488f2f358bd2289618feb27461ee1710072eaccda","lower": "b0dfac283ebe21769c6f9e9142b43837fbb95333c3a964809aea45b1898a8adf025e649f616f2f2cf2d0a865c79c1a364ec0b47c1638a767e5d1fe","count": 1148,"preSum": 51463 },{ "ndv": 377,"upper": "b842dbb21a8c84a7f74ab68d92cbc4e956115b9dcf6b72d9e0ec63b25c7acdb12eddba1360fb37feba526f32d00679164184c4df88efee76c875c39f6341c9d8","lower": "b3ff048dfe3df932fa34248fc748cd97627a64c8","count": 1144,"preSum": 52611 },{ "ndv": 474,"upper": "bd12f5300e","lower": "b8441c2092789be9997850426d03ba7b2a5a05ebdbc5f99318413d860a80","count": 1151,"preSum": 53755 },{ "ndv": 463,"upper": "c2081b11e74107819a055179b7b8dbae75fd2c76da570b5644e5d191bbdfae9d18b4beaf025e0ef11d83d4bb8d06263322216d3662cff64e6eb886b2cce9cc4b","lower": "bd1352ca904f61edad8ad5577ecef08c5dd97e9ee79e662b789a37d741e80479435026edc36b3620bc1aa27f989f049acfd9ad6a6fdb57a06b7651295623b873","count": 1173,"preSum": 54906 },{ "ndv": 379,"upper": "c62b9455f9e6c7b9f68fe953575f5f9d35cfd3b591451fe5da7b282e0f493a6a88a818ff42d02d270d55ba476e03d3b5dc6da6245a968a8e839cd8509f985aa7","lower": "c20d91b52e16834d284f2e726f08b20234545d4","count": 1144,"preSum": 56079 },{ "ndv": 395,"upper": "ca4c35f99bfd3e05e12934db4","lower": "c62cbe63bfe40e26eb92b04bd60a0a64b8e4088128ad1458dd0041bfde2d9fb8c725b8b7366696a6ee14c38752ecd27b377b2ef80cd2c4d055869f4e5edb9ced","count": 1144,"preSum": 57223 },{ "ndv": 464,"upper": "cf7891b44f7dd6d7095ed9","lower": "ca4d8032af9b36de8060d272645e0d7d7fcb6f57c52b2ebf82a8ef","count": 1146,"preSum": 58367 },{ "ndv": 458,"upper": "d454a6d07f437a9e64e6","lower": "cf790731e1f5d6d4185db7e3f593b92ca6e8e0aec77384db9792efab2f332e2093ce1cd3ad40c64ea07aa436be557b49418fef4b7e8170044bb4925e7496b2fe","count": 1146,"preSum": 59513 },{ "ndv": 394,"upper": "d878e482d6334a6c662d69f11f134ee3eeff2170ce21e80ff0e96e135d1f803e452b73c952d4435039769efe467cdcda83ad27ebe7ebccf314d1ecf7e7f96e13","lower": "d456143","count": 1154,"preSum": 60659 },{ "ndv": 360,"upper": "dc0e7da4200ca9a3ec8a6e16f42","lower": "d87929e38417eae8835340af4c0fbaf412e056570c487e016afe69656e885787b92c06d8cc9b384b2155a7bcc86e5ea0281b0aa8b9ad9399dcf0687ce2d2d780","count": 1144,"preSum": 61813 },{ "ndv": 421,"upper": "e09e86ce83605d38880c6491a69f2755d7ca5715675f0403aefb2a302fc28010704c296f","lower": "dc1623326522a343","count": 1144,"preSum": 62957 },{ "ndv": 355,"upper": "e4504b2a1dee2aea0d09c559dcf1caeb50fe5b0c59c8c0acc8e24208ae89ea2efc618866d8d747072389f79753af97969da70a701b6e1062e8cefafe9de98711","lower": "e09f02af00ab5e7025e43d06c6f4c128e01d32b4c806dcf1fc95a749c9d81b794bf0b295bb7c5b538431d0880ec374e0af5fb7ad2807457709d648b5f1554031","count": 1144,"preSum": 64101 },{ "ndv": 432,"upper": "e8baa59dfd4044601121ce6ad0160649f4f79a11a9e582f5108a6f0f3f58a1a5e07aff705a585f2b05a89984333d70a917ad942c618adbc9559cec9d817eb937","lower": "e451bdf0d7fd0d48d1c5ab7f16d08582992286531cf1b9a3e1f3d10439e","count": 1145,"preSum": 65245 },{ "ndv": 442,"upper": "edc5fb707b60b40c546cc3eb09dd4323ab4ea43c520dc3dce14bb02364ab1473aca79929e3963abfabb3c41e2fee43f005f429d76cb404ac90b163cc9fcaaf9a","lower": "e8bb7926864e4aef02b247e52f55b47979941b10cd4b709c0f5a9fd2270f6514e4d9d7c67acb8442c7f2e56ded318952ca0cd83d7266e8416f49951ad17a8789","count": 1144,"preSum": 66390 },{ "ndv": 396,"upper": "f1b6b62ace4cc416c97c45cf3831e1a47249f9753fb1c15fa694cd10237a597d3587ca099f8707ef5bf7cdda6cb843c45ded20d2963","lower": "edc723027c6aba7bef4dbc91bbb3602e5bca2848dbbdba121a36dbafc224b2aea18b874a86a23f790004a271c902b25dbe5942bbcdcde5e9c6daa35f33c324b9","count": 1145,"preSum": 67534 },{ "ndv": 425,"upper": "f6142003c59c5ebe8a978edee6529242f50894519c338ed2e4a199d3a14c501b0ba463d08dc27d0f96d14768985bd89c6ed5164be5caecddec46efa7109cd63c","lower": "f1bb5c7eeff9b184f42ddeada669","count": 1144,"preSum": 68679 },{ "ndv": 368,"upper": "fa0d4de16b01a9993262227728e9b287384cca5210f17f529d8dbabc8beefc55e1b644c85335e77b5030a2339559f13b0a17199c18f0689de84bf4865e3c0e81","lower": "f620ee113e5e40e36aed2282209513d0bfb9ceb9473209","count": 1146,"preSum": 69823 },{ "ndv": 370,"upper": "fded7fa41eb780622315ce0a7","lower": "fa0d702adecc9bf","count": 1599,"preSum": 70969 },{ "ndv": 181,"upper": "fffc62ed702e63782b0ac3ebdbe63aa14e2d9b7c68a","lower": "fded80d4d500ef1ba8aec25c271debd038834fb213eece768b4adc402d914dc16fee1fae59807380e22b3a80c92ffba671d817ec4b7d919253930b2d0","count": 621,"preSum": 72568 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_text_medium.null_count:
+    0
+  cest_full_table_big.c_text_medium.sample_rate:
+    0.010943651
+  cest_full_table_big.c_text_tiny.TOPN:
+    { "countArr": [ 2129,747,1152,2604,1061,4041,663,8212,877,1720,929,1401,654,622 ],"valueArr": [ "272901f7b4866c38cfdad0ee58e710055bd6f342c756efa3ea2c5414d1c8d334c9cd42fff815d8c800a1a7bc096cf77897e8375e32b12cb22a33cd62d840c68d","2aa4d5c39254825a73c8285fdfd0cb082cdbc465bff473642e153dbf9818be56f217072a5c7867fbcecbf15e47b88de9d80f468b8f6a85f955d20f808c77d42a","4a9e0d094ccec5f3ab0ee0ccdae5d42db6ff517ba578c8d9487aece02602c334733224fac97026bf3367678500458693ccb86eb285b","5ee951d1927147b17bb57cf07545f785341b9aeb920e85ca1c","884e206f2e3ec07a388151bddf4d2362db2a90a8ece685e96e1c2befd992ca6d4320460c618cf5ec78a7932c7cc4ae2a50962f5e8b820853f2773ec79f9aa865","8f4b82ccc477a1d4817a0713716a1a9e0abdb99fb556d066bd4663a261367328af7c4f078b4283c7d3bde3398bbeb466cd176ee7150e33107dca10c8322e0e","9081f4c0e8c85ee47ead80cdbc5f081e9cc6428718903b5f35107125e08896ba5f5172f9b5428ba371a6137715b9433d6b85cbb56c7f274ce7f86b6f66a5e313","ae093e295bf106c3d99ebb56b5c6978fb3e","b200919aa862b99712074cde83b3c18e25c4fd15","bc10f23cffb6b25587d94e646accc5b988bcb651c161925d2c5f8aa0bac12f1f290ab10f38fb5c727ad5da443c2daad1fe27901a5b9f79cd93a","c292b6a83f3518061f48c1dad1fa4d2c3e19eefcf6d90a0b08b456ab655a4c1e28257a3691b286cd81108acb9981558e411ab13520eaae125e4160f7d409d7f9","ce073c56e6291d3fcb1050e6a705e143712f1272439d96200d18b826e","cfe9b21e9d0bee82cf485c1644e7fc722764462d88e885b27cea8dead24cf1279a75c78df843678c4244278a8c7172d240d27e597f4975610eaf6da3176269ef","dd946928cf4b699b145e020fde6ca56b98c6bcb81e47f3dc93c76a5e2c6b9487a" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_text_tiny.cardinality:
+    243039
+  cest_full_table_big.c_text_tiny.histogram:
+    { "buckets": [ { "ndv": 166,"upper": "01dde7823023499a10f85591dc6af7747d89c8aa5b5","lower": "0","count": 1144,"preSum": 0 },{ "ndv": 571,"upper": "07cdf3cec6575290c3605446ed","lower": "01de5a4451a0e2648f4124d2e6c725a8302e48c132bc53022ca7462861f814dabb4f87ffc3a1e9357194adf600e97ac3e9816416b348fbb7d993843ca4861a9c","count": 1144,"preSum": 1144 },{ "ndv": 385,"upper": "0b9a1d61777836df3728cafa83c438b50f788c8c877bf0","lower": "07ceb4fa2aa3d114bf15a103d51f2a325543269a30de9b082851","count": 1145,"preSum": 2288 },{ "ndv": 511,"upper": "1113f79e0f5556eb128234780d9dc43dac44ff6f02d36cfe453ce7740f7bbacc9cbd9c8fff34e16bcf2f0d4d2f8b14990aba3f5d557e19d21dac182b7eaed214","lower": "0b9c4e79f1ff05e2dcf2cc92ae6d00c41dae43730263ca5658c0d3a3d1bf1c3a517bde9064e517d7eb344db3ca6a078a2ae3061c3f186809b3350dd9770f816c","count": 1190,"preSum": 3433 },{ "ndv": 190,"upper": "1311e1fd42260161612493575ce96bb850c6d5bcff96788f2e684e4b85bdfa805b539b0f6dd915c4a950ec4","lower": "111522044fa68d83ef2dc4c163eef6bbff2f6ee58fd5e6b0779a3558a95cc073723bbe5a27ebb52868941fa6a6fbafbce2b4dab2ff54b80a7b0a868b67d2e804","count": 1449,"preSum": 4623 },{ "ndv": 495,"upper": "17f78","lower": "1312df8d2b0b162234bf63e35e04457ca5c44cb3a93f0fdb9d4e676bedbd18dd42ac0efbcdfc822acfe3","count": 1293,"preSum": 6072 },{ "ndv": 330,"upper": "1b2b044fa17eb9b2ff7798fdbdacfd9375b20ca0f022e75c6da410673d96","lower": "17f7c2386996a38ce235cba0f1b009829aa9816a794437c4eeab3afb5094145d083","count": 1145,"preSum": 7365 },{ "ndv": 508,"upper": "205bb8f17e5224cfe3f2a340724491356c2e44adb8225890e19d820326c8a1392530aec1f4d07f994db22c6dabf1d230c81133038161de925bde002ffa9abbbe","lower": "1b2ccd0ca37e1b3902f4794b5fb5ba11","count": 1166,"preSum": 8510 },{ "ndv": 395,"upper": "2489cf31553d6e40d04c8f6","lower": "20609b96de0278b56462c3e104ef76f789e074927d7ee81d207b1fafcbe3f8266f4a268476909d8e2e7a","count": 1204,"preSum": 9676 },{ "ndv": 431,"upper": "28b02ac065e2cc1bbe517930e1d07f04e5cd8ec8c01488f9","lower": "248c920cebc921cb395d00fd3e2b567572e36fc773","count": 1144,"preSum": 10880 },{ "ndv": 369,"upper": "2cb456ee2d29c4703cfe26e290adffa03be1df47c17bc21332782fd9a067867edb1cc436cfc019762b0ab2732cfc735487969d8dd3ddf25e","lower": "28b0526659a25aefb71d8d34c6c146378bb40abd36f74d3694ebb61939c5f0bf8d5d828e86987619287886c4f901b89b6a57a45fde4fed074cb5c749e355d446","count": 1145,"preSum": 12024 },{ "ndv": 401,"upper": "310a1471df0f7661b08941c102ecf376","lower": "2cb527aa5bfd4468f64fa2d2ac61ecaf45615ca1965c91bd9c6be1cb2255377ced816533f80c91bafb93c0dfcc71de9c164","count": 1202,"preSum": 13169 },{ "ndv": 461,"upper": "35c6c1279085e58dc930071b7bdd15114913135ea39ad2ac6d1ef39cd07d","lower": "310b22f9931e4f311fe42fca59b4f23ed1e6dae708a59af169e491dba8ac7e98eb60070b40d253c3d8c0b5e9573b08f009c02ad44124d3609f9e400105b155","count": 1146,"preSum": 14371 },{ "ndv": 384,"upper": "393c28a88a013c7c969d008ea2972ec2a0d1ffd23cb361656617ae133e1357a14411438fc5a447e0bd9e0427cadea0dcf6af6a9bfc8abf0ec361fd91d66d5382","lower": "35c9f453764aaa291bcc895f7e258eb13eb04da91c0101c90365e41fbfb22ee953916a708d67c3dbbd287c3c0072d31d1fab8d9f3e97fea5d91f952e3319df0f","count": 1144,"preSum": 15517 },{ "ndv": 373,"upper": "3d307f1902b9f2d8bcd78b556f3b6f62208153308d7bf810cc471cb9fc47dabb68fbbd2f1a8e95a6fb5183389132f0e0dcf8f52e3a1c9bb3","lower": "3942568ee95b7b3f8573f806857903cd4dc87f88c3a9982797b2f2f578bd37e19dc8d8bd652efe5c713bfbab387e24e9c065","count": 1144,"preSum": 16661 },{ "ndv": 381,"upper": "410e26cac9e7f8d25b7689111f0a62a21eb4d63ea6169f95e7c167c5ca784b190127","lower": "3d323107538c7e2059be414e5cf6","count": 1144,"preSum": 17805 },{ "ndv": 218,"upper": "435a8cc58fc6c26aa437323744258f622fe49f4a06ef984d93be","lower": "4111485b903225eb7ad50fa9f854b7dbdfa9d051922c03b99fbddbd6afd7d34dc0d3189","count": 1164,"preSum": 18949 },{ "ndv": 423,"upper": "4771f0477e5fdc9a9cb582cac0a78809adc7504e6671ab16171db96f7667f5ffef8746e6f7d10100afdd78132ab081f0c585061ff62cd8d9ecfeea1fdbd01f26","lower": "435aa344d995f0d25513e501b98dbe5cf979c29e00ba08173ffda95a3e9a50c446d28b344049ccdbcb102c25cccd","count": 1164,"preSum": 20113 },{ "ndv": 581,"upper": "4da801e50c2431beab882819538ac3ba91868f642acbff073b68daa20b0f9c73b91a5d14b6b31bc507bb538a799c01b3507c41c02debda78f0f225f8eab84083","lower": "47737e5333b789dfe19c9e5ef8f417d87f1efbbdf29b539b5e88501f7e78b240080155e1cf7aaaccb5fd95740b3154566a1926d159c42f2","count": 1148,"preSum": 21277 },{ "ndv": 370,"upper": "519bef86b1ccf9a9f129a7b279e6adea1e505aef2cab78ff299182674ee5a488c7ffce8626a4","lower": "4da9d3313d55edf9e34b87eef7bc3696","count": 1144,"preSum": 22425 },{ "ndv": 297,"upper": "551a06c68d3a9bb87456c05c97d467af6daa215a60d785b5fdc549e04aaca3c877ce53236bc762d96f09","lower": "51a409db586ec283c1fc2132165ac08fb45","count": 1164,"preSum": 23569 },{ "ndv": 348,"upper": "58cbf97af20e30bc9d364928e1277d20437cecc31581e9889103826d6267","lower": "551de0f7595d913b67db679d834eea6abe1adbd3dba6e54a79eac7cbfa6b6295fa98bd8c89e58b81074fa267b633f76ad5e4c2788a61d1c3615daba6cff41f62","count": 1144,"preSum": 24733 },{ "ndv": 409,"upper": "5d8640d86728c786910ba253a149dd6aca1b6ecd3cd474e5ce7b5a73535d5aaa8","lower": "58ccca4da871e16053350dc6133b61a2f0e3347919d530830d6a304a28ef227228e6499a369b277c022a4fea645a4ffca685eb74a46de26f804bfaff856af6da","count": 1144,"preSum": 25877 },{ "ndv": 250,"upper": "600517214987915eb4b511d","lower": "5d89b00c7ae9609a56f860145a17288025d78e89f9d25d82fb9f52d004b7de35f7a4320","count": 1149,"preSum": 27021 },{ "ndv": 426,"upper": "64964da26aa4e7a9af119b294728d91b4de9a2325df7c48d84b5b3967cffa705b3a0eabe9e77238d531f32755f38e508d4a259664ad61a3e8920e091cf9556e5","lower": "600555308b687a517a222010da541b87bc91e20a575e2","count": 1144,"preSum": 28170 },{ "ndv": 429,"upper": "6942ff1081136f3da0b7476533b69326ca477b5a73247af40f888805800ce02eeb1f961226f894ab5f73a83c8f58540f05d7a0ea4c9d2f72bcafe13b0d09749","lower": "649b84b63259e926e711a3fc8833fb57de343facf70438e3ad2262f29e95d4a0221e4d0cbb758557c4e773bc91f8e13fecf6193eca7924fd01635801f5ede29f","count": 1157,"preSum": 29314 },{ "ndv": 380,"upper": "6cddfd7e5019351d73d33114f9ab41d5998d5239d08d6673030de3aab26e013e0051223e70e8c3ad32f0c5d47f28ec8a1241d4efcf9","lower": "6943ec3","count": 1145,"preSum": 30471 },{ "ndv": 376,"upper": "70fbc0f930b1fd11fc8c5dd41d03c6a00e394aaded595d2d814cd7fcb906dcf74ddf86204a23aadcebc88a0b9df27acef465a4e9e8501c9b0511d5378740821b","lower": "6cde863eb5663a369a80e89d284b25dbc41087ec66c990fe6ad024f8362a58354a47bef569f97c59d793268ac9bf88517d7ec1c1153cf05d53557fca79642d62","count": 1176,"preSum": 31616 },{ "ndv": 511,"upper": "75ef4b54dc599d666e7a3de4041871b3956eebd9ed09a18fed3f3f65","lower": "70fc35302222e96999a91ed3e97ac107b23108f6c3432f907b3fd7452bf39906197c75253a451f24cf9fd0","count": 1145,"preSum": 32792 },{ "ndv": 238,"upper": "78a7366861ab7ce92b374eb5360e91c26cbbdd07cefd0e5d3214ea9846e42fbea5cecc0a5047718128b3d6c602f","lower": "75f563470684ec8915306216a68b20018b7f6c62eeb00e6719d0d3012a7f24c1185b70c17ae6d87ec0da05d92c5cdfe5af6562771","count": 1293,"preSum": 33937 },{ "ndv": 305,"upper": "7bce56eca9c26cb210a25dffcf43059de09f3455e2cccd5df1485d7511f91179336950b328e85fd9a71b01a97859e615aeb2e42dd54848c3f8c344bcb5832cf1","lower": "78adc2ff26e81b837ce112db9a0d2f93f60f6854c4f3237d3a748547b5cfe69c445d","count": 1144,"preSum": 35230 },{ "ndv": 420,"upper": "80363a49a4cc7341902df6ce6fbfd74d954bd5","lower": "7bcea9d50d31c8498d8cf8","count": 1144,"preSum": 36374 },{ "ndv": 570,"upper": "865a67b","lower": "803726da7566e2b0997a69ea4fef74b1defc4fdd4626c05a489f20fd","count": 1155,"preSum": 37518 },{ "ndv": 472,"upper": "8bad08a020fa6c69a6d854adc3a9a69adeb827c241c58e8cd0ed5b764acafe8ebb4994f7a154c759c22121","lower": "865e3e30150c71ef5c147e2f791824baaecdc6c8348ad3016d988480dc75860d2","count": 1159,"preSum": 38673 },{ "ndv": 396,"upper": "8fc094b25226d","lower": "8baea5bc5b18b57f390565b1e4498111518376b44835305301e6a63c15a10da0186006de2553b825a511fedc880a48e7e1ae465f31a7441dc74","count": 1193,"preSum": 39832 },{ "ndv": 487,"upper": "94e6805e4cb50b0de6452fdb1f13903ff5f43da62c386918a03e9b4088f6038990496b92e277f28","lower": "8fc221e7d48e26840ad9176d73748fc070afbb17bc7d997d85013d3ffbc9eecc7842f33c0f28842299e7a3e8986504d421c73a9f24c40bd1e31a5e527b1f8d46","count": 1147,"preSum": 41025 },{ "ndv": 413,"upper": "9915b87a2041bf6a270e45975bfd1a09a462398feb3a5e67d1846ef1e7b25a5a3d6017d194f1eab439fa11f4d45791efd25bf3907e746c6a621c40434","lower": "94eaa84fb21c92eda965a7ff6f09eaec008894f9b63690334eca1c194b46be91207585f40e44a131f599162a09dbebe47a1509f9512f375246184286f8b577c5","count": 1150,"preSum": 42172 },{ "ndv": 445,"upper": "9df4d4a6cf35bd72af2b434aa0074c1","lower": "99188be58a271d35dfd9f40cd8dd7f409b1","count": 1187,"preSum": 43322 },{ "ndv": 406,"upper": "a2593a8baa44859a28391d02f76cc5cb45cfd2c2be7fb4b3a51f165b26b38e6c14ad81976bd9f4484","lower": "9df89145d45c9621914c9de1dc953e3ffbe0d6da6292cf4199d15b2635339a2e785fbd00b76a9","count": 1144,"preSum": 44509 },{ "ndv": 381,"upper": "a63b8c7670964cd0cfff43dc7a9e8f9c579fa0e3c37623a740b66cfd4a9071585e1266bd497","lower": "a25a0736f3a0ccb5d4b50d82a4f394629e1fd392ef4521262431e43082f46befeb8d54faa5d120800b496b24c667ab0487030b8963fa464","count": 1144,"preSum": 45653 },{ "ndv": 133,"upper": "a78433bb821ad674545f2bc3e330c9","lower": "a63ea9052d2cbba45d76706520b6953","count": 1148,"preSum": 46797 },{ "ndv": 275,"upper": "aa87e20d809ea68cec8432c2ad232f96d0131083ec9889a4facbcceba06e2ee999dc5c73c9b0","lower": "a7880d21936c3741daf312fc59a9802ba4b69bac0b585a2e992534319b2adc08b6aaff5acf5a2d904b6c0df7d60780dcf7986b085208042e97ce70104d61ccc1","count": 1145,"preSum": 47945 },{ "ndv": 326,"upper": "ad81e341f78942b","lower": "aa8802ae6bb9b04944e3264fd8684e5645bd7d1a646a47452fe71b4ed11ea5e8ed66573","count": 1228,"preSum": 49090 },{ "ndv": 327,"upper": "b0d576543155bf9f29a26a879c787ecd9f373ad5f7c2f1f7620430d6b2ac81e207dd76788de62d2","lower": "ad84002312b9d0734e48f7f04cf2a3bfc3db0c25d0cec1f0114906ad","count": 1145,"preSum": 50318 },{ "ndv": 286,"upper": "b3fde7a2d12db2df9ec2697488f2f358bd2289618feb27461ee1710072eaccda","lower": "b0dfac283ebe21769c6f9e9142b43837fbb95333c3a964809aea45b1898a8adf025e649f616f2f2cf2d0a865c79c1a364ec0b47c1638a767e5d1fe","count": 1148,"preSum": 51463 },{ "ndv": 377,"upper": "b842dbb21a8c84a7f74ab68d92cbc4e956115b9dcf6b72d9e0ec63b25c7acdb12eddba1360fb37feba526f32d00679164184c4df88efee76c875c39f6341c9d8","lower": "b3ff048dfe3df932fa34248fc748cd97627a64c8","count": 1144,"preSum": 52611 },{ "ndv": 474,"upper": "bd12f5300e","lower": "b8441c2092789be9997850426d03ba7b2a5a05ebdbc5f99318413d860a80","count": 1151,"preSum": 53755 },{ "ndv": 463,"upper": "c2081b11e74107819a055179b7b8dbae75fd2c76da570b5644e5d191bbdfae9d18b4beaf025e0ef11d83d4bb8d06263322216d3662cff64e6eb886b2cce9cc4b","lower": "bd1352ca904f61edad8ad5577ecef08c5dd97e9ee79e662b789a37d741e80479435026edc36b3620bc1aa27f989f049acfd9ad6a6fdb57a06b7651295623b873","count": 1173,"preSum": 54906 },{ "ndv": 379,"upper": "c62b9455f9e6c7b9f68fe953575f5f9d35cfd3b591451fe5da7b282e0f493a6a88a818ff42d02d270d55ba476e03d3b5dc6da6245a968a8e839cd8509f985aa7","lower": "c20d91b52e16834d284f2e726f08b20234545d4","count": 1144,"preSum": 56079 },{ "ndv": 395,"upper": "ca4c35f99bfd3e05e12934db4","lower": "c62cbe63bfe40e26eb92b04bd60a0a64b8e4088128ad1458dd0041bfde2d9fb8c725b8b7366696a6ee14c38752ecd27b377b2ef80cd2c4d055869f4e5edb9ced","count": 1144,"preSum": 57223 },{ "ndv": 464,"upper": "cf7891b44f7dd6d7095ed9","lower": "ca4d8032af9b36de8060d272645e0d7d7fcb6f57c52b2ebf82a8ef","count": 1146,"preSum": 58367 },{ "ndv": 458,"upper": "d454a6d07f437a9e64e6","lower": "cf790731e1f5d6d4185db7e3f593b92ca6e8e0aec77384db9792efab2f332e2093ce1cd3ad40c64ea07aa436be557b49418fef4b7e8170044bb4925e7496b2fe","count": 1146,"preSum": 59513 },{ "ndv": 394,"upper": "d878e482d6334a6c662d69f11f134ee3eeff2170ce21e80ff0e96e135d1f803e452b73c952d4435039769efe467cdcda83ad27ebe7ebccf314d1ecf7e7f96e13","lower": "d456143","count": 1154,"preSum": 60659 },{ "ndv": 360,"upper": "dc0e7da4200ca9a3ec8a6e16f42","lower": "d87929e38417eae8835340af4c0fbaf412e056570c487e016afe69656e885787b92c06d8cc9b384b2155a7bcc86e5ea0281b0aa8b9ad9399dcf0687ce2d2d780","count": 1144,"preSum": 61813 },{ "ndv": 421,"upper": "e09e86ce83605d38880c6491a69f2755d7ca5715675f0403aefb2a302fc28010704c296f","lower": "dc1623326522a343","count": 1144,"preSum": 62957 },{ "ndv": 355,"upper": "e4504b2a1dee2aea0d09c559dcf1caeb50fe5b0c59c8c0acc8e24208ae89ea2efc618866d8d747072389f79753af97969da70a701b6e1062e8cefafe9de98711","lower": "e09f02af00ab5e7025e43d06c6f4c128e01d32b4c806dcf1fc95a749c9d81b794bf0b295bb7c5b538431d0880ec374e0af5fb7ad2807457709d648b5f1554031","count": 1144,"preSum": 64101 },{ "ndv": 432,"upper": "e8baa59dfd4044601121ce6ad0160649f4f79a11a9e582f5108a6f0f3f58a1a5e07aff705a585f2b05a89984333d70a917ad942c618adbc9559cec9d817eb937","lower": "e451bdf0d7fd0d48d1c5ab7f16d08582992286531cf1b9a3e1f3d10439e","count": 1145,"preSum": 65245 },{ "ndv": 442,"upper": "edc5fb707b60b40c546cc3eb09dd4323ab4ea43c520dc3dce14bb02364ab1473aca79929e3963abfabb3c41e2fee43f005f429d76cb404ac90b163cc9fcaaf9a","lower": "e8bb7926864e4aef02b247e52f55b47979941b10cd4b709c0f5a9fd2270f6514e4d9d7c67acb8442c7f2e56ded318952ca0cd83d7266e8416f49951ad17a8789","count": 1144,"preSum": 66390 },{ "ndv": 396,"upper": "f1b6b62ace4cc416c97c45cf3831e1a47249f9753fb1c15fa694cd10237a597d3587ca099f8707ef5bf7cdda6cb843c45ded20d2963","lower": "edc723027c6aba7bef4dbc91bbb3602e5bca2848dbbdba121a36dbafc224b2aea18b874a86a23f790004a271c902b25dbe5942bbcdcde5e9c6daa35f33c324b9","count": 1145,"preSum": 67534 },{ "ndv": 425,"upper": "f6142003c59c5ebe8a978edee6529242f50894519c338ed2e4a199d3a14c501b0ba463d08dc27d0f96d14768985bd89c6ed5164be5caecddec46efa7109cd63c","lower": "f1bb5c7eeff9b184f42ddeada669","count": 1144,"preSum": 68679 },{ "ndv": 368,"upper": "fa0d4de16b01a9993262227728e9b287384cca5210f17f529d8dbabc8beefc55e1b644c85335e77b5030a2339559f13b0a17199c18f0689de84bf4865e3c0e81","lower": "f620ee113e5e40e36aed2282209513d0bfb9ceb9473209","count": 1146,"preSum": 69823 },{ "ndv": 370,"upper": "fded7fa41eb780622315ce0a7","lower": "fa0d702adecc9bf","count": 1599,"preSum": 70969 },{ "ndv": 181,"upper": "fffc62ed702e63782b0ac3ebdbe63aa14e2d9b7c68a","lower": "fded80d4d500ef1ba8aec25c271debd038834fb213eece768b4adc402d914dc16fee1fae59807380e22b3a80c92ffba671d817ec4b7d919253930b2d0","count": 621,"preSum": 72568 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_text_tiny.null_count:
+    0
+  cest_full_table_big.c_text_tiny.sample_rate:
+    0.010943651
+  cest_full_table_big.c_time.TOPN:
+    { "countArr": [ 29,31,34,31,78,32,28,40,53,56,39,29,28,33 ],"valueArr": [ 48737812480,170355851264,277763588096,531015663616,535713284096,593544347648,626192809984,766450335744,790508863488,915633340416,1318471073792,1565314252800,1598365368320,1644251054080 ],"type": "Time","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_time.cardinality:
+    206052
+  cest_full_table_big.c_time.histogram:
+    { "buckets": [ { "ndv": 685,"upper": "24746393600","lower": "16777216","count": 1557,"preSum": 0 },{ "ndv": 667,"upper": "47630516224","lower": "24763170816","count": 1560,"preSum": 1557 },{ "ndv": 656,"upper": "76587991040","lower": "47680847872","count": 1555,"preSum": 3117 },{ "ndv": 646,"upper": "99757326336","lower": "76621545472","count": 1555,"preSum": 4672 },{ "ndv": 659,"upper": "125074145280","lower": "99874766848","count": 1555,"preSum": 6227 },{ "ndv": 674,"upper": "153142427648","lower": "125090922496","count": 1555,"preSum": 7782 },{ "ndv": 662,"upper": "177368727552","lower": "153159204864","count": 1563,"preSum": 9337 },{ "ndv": 660,"upper": "206561083392","lower": "177419059200","count": 1555,"preSum": 10900 },{ "ndv": 677,"upper": "231324254208","lower": "206577860608","count": 1558,"preSum": 12455 },{ "ndv": 672,"upper": "255701549056","lower": "231424917504","count": 1556,"preSum": 14013 },{ "ndv": 697,"upper": "285296558080","lower": "255785435136","count": 1556,"preSum": 15569 },{ "ndv": 620,"upper": "307006275584","lower": "285313335296","count": 1555,"preSum": 17125 },{ "ndv": 657,"upper": "331232575488","lower": "307123716096","count": 1555,"preSum": 18680 },{ "ndv": 681,"upper": "361179906048","lower": "331299684352","count": 1556,"preSum": 20235 },{ "ndv": 632,"upper": "383661375488","lower": "361314123776","count": 1556,"preSum": 21791 },{ "ndv": 651,"upper": "406126067712","lower": "383694929920","count": 1557,"preSum": 23347 },{ "ndv": 645,"upper": "434261458944","lower": "406142844928","count": 1557,"preSum": 24904 },{ "ndv": 682,"upper": "459595055104","lower": "434278236160","count": 1555,"preSum": 26461 },{ "ndv": 649,"upper": "488334426112","lower": "459611832320","count": 1558,"preSum": 28016 },{ "ndv": 661,"upper": "513030488064","lower": "488351203328","count": 1555,"preSum": 29574 },{ "ndv": 695,"upper": "538548633600","lower": "513064042496","count": 1555,"preSum": 31129 },{ "ndv": 630,"upper": "567153786880","lower": "538565410816","count": 1555,"preSum": 32684 },{ "ndv": 646,"upper": "591715631104","lower": "567170564096","count": 1557,"preSum": 34239 },{ "ndv": 669,"upper": "620740214784","lower": "591732408320","count": 1555,"preSum": 35796 },{ "ndv": 660,"upper": "644563861504","lower": "620756992000","count": 1555,"preSum": 37351 },{ "ndv": 629,"upper": "667179548672","lower": "644614193152","count": 1555,"preSum": 38906 },{ "ndv": 665,"upper": "694912286720","lower": "667196325888","count": 1557,"preSum": 40461 },{ "ndv": 681,"upper": "719876784128","lower": "694929063936","count": 1555,"preSum": 42018 },{ "ndv": 640,"upper": "743398440960","lower": "719910338560","count": 1556,"preSum": 43573 },{ "ndv": 663,"upper": "772339138560","lower": "743415218176","count": 1555,"preSum": 45129 },{ "ndv": 671,"upper": "797521739776","lower": "772389470208","count": 1555,"preSum": 46684 },{ "ndv": 672,"upper": "825422249984","lower": "797538516992","count": 1555,"preSum": 48239 },{ "ndv": 664,"upper": "849715658752","lower": "825455804416","count": 1555,"preSum": 49794 },{ "ndv": 662,"upper": "873874849792","lower": "849732435968","count": 1555,"preSum": 51349 },{ "ndv": 688,"upper": "903906066432","lower": "873908404224","count": 1555,"preSum": 52904 },{ "ndv": 656,"upper": "928451133440","lower": "903956398080","count": 1555,"preSum": 54459 },{ "ndv": 658,"upper": "952543215616","lower": "928467910656","count": 1555,"preSum": 56014 },{ "ndv": 658,"upper": "980930265088","lower": "952593547264","count": 1559,"preSum": 57569 },{ "ndv": 672,"upper": "1004854575104","lower": "980963819520","count": 1556,"preSum": 59128 },{ "ndv": 662,"upper": "1034114039808","lower": "1004871352320","count": 1555,"preSum": 60684 },{ "ndv": 650,"upper": "1058424225792","lower": "1034214703104","count": 1555,"preSum": 62239 },{ "ndv": 656,"upper": "1081895550976","lower": "1058474557440","count": 1558,"preSum": 63794 },{ "ndv": 635,"upper": "1109628289024","lower": "1081929105408","count": 1559,"preSum": 65352 },{ "ndv": 683,"upper": "1135347761152","lower": "1109645066240","count": 1555,"preSum": 66911 },{ "ndv": 648,"upper": "1159255293952","lower": "1135364538368","count": 1558,"preSum": 68466 },{ "ndv": 621,"upper": "1187625566208","lower": "1159305625600","count": 1555,"preSum": 70024 },{ "ndv": 706,"upper": "1213126934528","lower": "1187642343424","count": 1555,"preSum": 71579 },{ "ndv": 693,"upper": "1242235404288","lower": "1213143711744","count": 1556,"preSum": 73134 },{ "ndv": 637,"upper": "1265371185152","lower": "1242403176448","count": 1557,"preSum": 74690 },{ "ndv": 638,"upper": "1289832366080","lower": "1265387962368","count": 1557,"preSum": 76247 },{ "ndv": 666,"upper": "1316793352192","lower": "1289849143296","count": 1558,"preSum": 77804 },{ "ndv": 695,"upper": "1343838224384","lower": "1316843683840","count": 1556,"preSum": 79362 },{ "ndv": 671,"upper": "1367695425536","lower": "1343888556032","count": 1555,"preSum": 80918 },{ "ndv": 632,"upper": "1395914702848","lower": "1367712202752","count": 1556,"preSum": 82473 },{ "ndv": 668,"upper": "1420023562240","lower": "1395931480064","count": 1558,"preSum": 84029 },{ "ndv": 645,"upper": "1447185874944","lower": "1420057116672","count": 1556,"preSum": 85587 },{ "ndv": 633,"upper": "1470237769728","lower": "1447219429376","count": 1555,"preSum": 87143 },{ "ndv": 642,"upper": "1494413737984","lower": "1470254546944","count": 1555,"preSum": 88698 },{ "ndv": 664,"upper": "1521525719040","lower": "1494430515200","count": 1558,"preSum": 90253 },{ "ndv": 677,"upper": "1545970122752","lower": "1521542496256","count": 1556,"preSum": 91811 },{ "ndv": 673,"upper": "1569860878336","lower": "1546020454400","count": 1556,"preSum": 93367 },{ "ndv": 673,"upper": "1598835130368","lower": "1569911209984","count": 1555,"preSum": 94923 },{ "ndv": 643,"upper": "1621635366912","lower": "1598935793664","count": 1555,"preSum": 96478 },{ "ndv": 622,"upper": "1644871811072","lower": "1621652144128","count": 1427,"preSum": 98033 } ],"maxBucketSize": 64,"type": "Time","sampleRate": 0.90062594 }
+  cest_full_table_big.c_time.null_count:
+    0
+  cest_full_table_big.c_time.sample_rate:
+    0.010943651
+  cest_full_table_big.c_timestamp.TOPN:
+    { "countArr": [ 89,85,125,163,113,119,140,158,82,113,87,209,457,254 ],"valueArr": [ 1849903403040243712,1849931202266398720,1849950766194753536,1850040677442781184,1850054339180101632,1850081569406976000,1850082433316159488,1850190555997274112,1850303237668732928,1850340303152611328,1850377691262353408,1850390337793556480,1850485867848663040,1850625578856611840 ],"type": "Timestamp","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_timestamp.cardinality:
+    439971
+  cest_full_table_big.c_timestamp.histogram:
+    { "buckets": [ { "ndv": 764,"upper": "1849796805206736896","lower": "1849785396146208768","count": 1530,"preSum": 0 },{ "ndv": 835,"upper": "1849809829560844288","lower": "1849796815944155136","count": 1530,"preSum": 1530 },{ "ndv": 806,"upper": "1849821438102470656","lower": "1849809831037239296","count": 1530,"preSum": 3060 },{ "ndv": 845,"upper": "1849834635580669952","lower": "1849821440652607488","count": 1529,"preSum": 4590 },{ "ndv": 790,"upper": "1849846288447700992","lower": "1849834640227958784","count": 1530,"preSum": 6119 },{ "ndv": 825,"upper": "1849861598445830144","lower": "1849846300443410432","count": 1530,"preSum": 7649 },{ "ndv": 807,"upper": "1849873845024980992","lower": "1849861609686564864","count": 1529,"preSum": 9179 },{ "ndv": 772,"upper": "1849885437477257216","lower": "1849873845410856960","count": 1529,"preSum": 10708 },{ "ndv": 849,"upper": "1849898561957789696","lower": "1849885466803830784","count": 1529,"preSum": 12237 },{ "ndv": 873,"upper": "1849911950729805824","lower": "1849898568131805184","count": 1539,"preSum": 13766 },{ "ndv": 786,"upper": "1849933480176123904","lower": "1849911951786770432","count": 1533,"preSum": 15305 },{ "ndv": 838,"upper": "1849946946442100736","lower": "1849933500711436288","count": 1529,"preSum": 16838 },{ "ndv": 798,"upper": "1849959875417735168","lower": "1849946952364457984","count": 1530,"preSum": 18367 },{ "ndv": 796,"upper": "1849972553506881536","lower": "1849959884661981184","count": 1565,"preSum": 19897 },{ "ndv": 797,"upper": "1849984823070818304","lower": "1849972554328965120","count": 1532,"preSum": 21462 },{ "ndv": 791,"upper": "1849998967488643072","lower": "1849984828556967936","count": 1529,"preSum": 22994 },{ "ndv": 758,"upper": "1850010802271027200","lower": "1849998984920170496","count": 1530,"preSum": 24523 },{ "ndv": 830,"upper": "1850023739165507584","lower": "1850010807086088192","count": 1529,"preSum": 26053 },{ "ndv": 853,"upper": "1850036857404915712","lower": "1850023751328989184","count": 1530,"preSum": 27582 },{ "ndv": 815,"upper": "1850049370456588288","lower": "1850036860257042432","count": 1530,"preSum": 29112 },{ "ndv": 813,"upper": "1850061250168356864","lower": "1850049404396896256","count": 1531,"preSum": 30642 },{ "ndv": 752,"upper": "1850078265469829120","lower": "1850061251560865792","count": 1530,"preSum": 32173 },{ "ndv": 848,"upper": "1850091398238306304","lower": "1850078266812006400","count": 1570,"preSum": 33703 },{ "ndv": 844,"upper": "1850104871852703744","lower": "1850091400251572224","count": 1535,"preSum": 35273 },{ "ndv": 779,"upper": "1850116543644434432","lower": "1850104874805493760","count": 1529,"preSum": 36808 },{ "ndv": 797,"upper": "1850129666531131392","lower": "1850116549331910656","count": 1529,"preSum": 38337 },{ "ndv": 815,"upper": "1850144941867532288","lower": "1850129668930273280","count": 1529,"preSum": 39866 },{ "ndv": 854,"upper": "1850157870507622400","lower": "1850144942823833600","count": 1529,"preSum": 41395 },{ "ndv": 827,"upper": "1850170428555788288","lower": "1850157883677736960","count": 1530,"preSum": 42924 },{ "ndv": 798,"upper": "1850182648173953024","lower": "1850170444359925760","count": 1543,"preSum": 44454 },{ "ndv": 864,"upper": "1850195608019664896","lower": "1850182650606649344","count": 1530,"preSum": 45997 },{ "ndv": 870,"upper": "1850213621632598016","lower": "1850195608489426944","count": 1531,"preSum": 47527 },{ "ndv": 812,"upper": "1850227411363299328","lower": "1850213627034861568","count": 1531,"preSum": 49058 },{ "ndv": 779,"upper": "1850239240189771776","lower": "1850227412101496832","count": 1529,"preSum": 50589 },{ "ndv": 715,"upper": "1850250242067267584","lower": "1850239244065308672","count": 1529,"preSum": 52118 },{ "ndv": 843,"upper": "1850263944069906432","lower": "1850250247586971648","count": 1529,"preSum": 53647 },{ "ndv": 756,"upper": "1850275169117929472","lower": "1850263949589610496","count": 1530,"preSum": 55176 },{ "ndv": 774,"upper": "1850289404401156096","lower": "1850275169403142144","count": 1529,"preSum": 56706 },{ "ndv": 866,"upper": "1850302561244938240","lower": "1850289427620823040","count": 1529,"preSum": 58235 },{ "ndv": 778,"upper": "1850314352373006336","lower": "1850302562503229440","count": 1531,"preSum": 59764 },{ "ndv": 793,"upper": "1850326797393068032","lower": "1850314363966062592","count": 1529,"preSum": 61295 },{ "ndv": 849,"upper": "1850340154472923136","lower": "1850326801503485952","count": 1530,"preSum": 62824 },{ "ndv": 761,"upper": "1850354307329687552","lower": "1850340160932151296","count": 1529,"preSum": 64354 },{ "ndv": 828,"upper": "1850366848046989312","lower": "1850354308738973696","count": 1529,"preSum": 65883 },{ "ndv": 880,"upper": "1850380214907961344","lower": "1850366850731343872","count": 1532,"preSum": 67412 },{ "ndv": 807,"upper": "1850392965726339072","lower": "1850380252505702400","count": 1530,"preSum": 68944 },{ "ndv": 789,"upper": "1850405820580233216","lower": "1850392972906987520","count": 1529,"preSum": 70474 },{ "ndv": 810,"upper": "1850421903605366784","lower": "1850405831787413504","count": 1529,"preSum": 72003 },{ "ndv": 832,"upper": "1850434527185338368","lower": "1850421903655698432","count": 1537,"preSum": 73532 },{ "ndv": 780,"upper": "1850446533330206720","lower": "1850434553307463680","count": 1529,"preSum": 75069 },{ "ndv": 773,"upper": "1850459426033500160","lower": "1850446539370004480","count": 1531,"preSum": 76598 },{ "ndv": 841,"upper": "1850472238692696064","lower": "1850459437190348800","count": 1530,"preSum": 78129 },{ "ndv": 823,"upper": "1850484903125188608","lower": "1850472247953719296","count": 1530,"preSum": 79659 },{ "ndv": 853,"upper": "1850499351596498944","lower": "1850484925170450432","count": 1530,"preSum": 81189 },{ "ndv": 815,"upper": "1850512298439868416","lower": "1850499353056116736","count": 1529,"preSum": 82719 },{ "ndv": 800,"upper": "1850524841656975360","lower": "1850512301627539456","count": 1538,"preSum": 84248 },{ "ndv": 822,"upper": "1850538202025164800","lower": "1850524846304264192","count": 1529,"preSum": 85786 },{ "ndv": 834,"upper": "1850551672502222848","lower": "1850538203518337024","count": 1529,"preSum": 87315 },{ "ndv": 810,"upper": "1850568608934002688","lower": "1850551678676238336","count": 1530,"preSum": 88844 },{ "ndv": 794,"upper": "1850581624614289408","lower": "1850568613581291520","count": 1529,"preSum": 90374 },{ "ndv": 792,"upper": "1850592932759863296","lower": "1850581625402818560","count": 1545,"preSum": 91903 },{ "ndv": 840,"upper": "1850606168590778368","lower": "1850592934907346944","count": 1529,"preSum": 93448 },{ "ndv": 808,"upper": "1850618014949441536","lower": "1850606175670763520","count": 1529,"preSum": 94977 },{ "ndv": 601,"upper": "1850627048289075200","lower": "1850618016325173248","count": 1301,"preSum": 96506 } ],"maxBucketSize": 64,"type": "Timestamp","sampleRate": 0.90062594 }
+  cest_full_table_big.c_timestamp.null_count:
+    0
+  cest_full_table_big.c_timestamp.sample_rate:
+    0.010943651
+  cest_full_table_big.c_timestamp_1.TOPN:
+    { "countArr": [ 10,9,9,11,11 ],"valueArr": [ 1849867804321251328,1849915730821120000,1850303237668732928,1850307336611037184,1850377691262353408 ],"type": "Timestamp","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_timestamp_1.cardinality:
+    506425
+  cest_full_table_big.c_timestamp_1.histogram:
+    { "buckets": [ { "ndv": 942,"upper": "1849797248628555776","lower": "1849785393881284608","count": 1562,"preSum": 0 },{ "ndv": 1005,"upper": "1849810337491058688","lower": "1849797256346075136","count": 1562,"preSum": 1562 },{ "ndv": 955,"upper": "1849822103553966080","lower": "1849810337977597952","count": 1562,"preSum": 3124 },{ "ndv": 1004,"upper": "1849835073684111360","lower": "1849822104912920576","count": 1565,"preSum": 4686 },{ "ndv": 960,"upper": "1849847814553600000","lower": "1849835075529605120","count": 1562,"preSum": 6251 },{ "ndv": 963,"upper": "1849862699366744064","lower": "1849847823193866240","count": 1562,"preSum": 7813 },{ "ndv": 973,"upper": "1849874460547481600","lower": "1849862716093628416","count": 1562,"preSum": 9375 },{ "ndv": 993,"upper": "1849887293590994944","lower": "1849874470479593472","count": 1562,"preSum": 10937 },{ "ndv": 977,"upper": "1849900082040668160","lower": "1849887295453265920","count": 1563,"preSum": 12499 },{ "ndv": 978,"upper": "1849912242737250304","lower": "1849900084792131584","count": 1563,"preSum": 14062 },{ "ndv": 965,"upper": "1849933880832819200","lower": "1849912243509002240","count": 1562,"preSum": 15625 },{ "ndv": 948,"upper": "1849946815646924800","lower": "1849933881302581248","count": 1562,"preSum": 17187 },{ "ndv": 979,"upper": "1849959410923732992","lower": "1849946817693745152","count": 1562,"preSum": 18749 },{ "ndv": 968,"upper": "1849972336611033088","lower": "1849959417936609280","count": 1564,"preSum": 20311 },{ "ndv": 1004,"upper": "1849984705462534144","lower": "1849972349093281792","count": 1562,"preSum": 21875 },{ "ndv": 969,"upper": "1849999474093457408","lower": "1849984712055980032","count": 1562,"preSum": 23437 },{ "ndv": 972,"upper": "1850012130120564736","lower": "1849999474747768832","count": 1566,"preSum": 24999 },{ "ndv": 967,"upper": "1850024145945886720","lower": "1850012137653534720","count": 1562,"preSum": 26565 },{ "ndv": 976,"upper": "1850036678526238720","lower": "1850024153445302272","count": 1562,"preSum": 28127 },{ "ndv": 971,"upper": "1850049347354361856","lower": "1850036691411140608","count": 1563,"preSum": 29689 },{ "ndv": 978,"upper": "1850061274461765632","lower": "1850049351817101312","count": 1562,"preSum": 31252 },{ "ndv": 948,"upper": "1850078765162430464","lower": "1850061279880806400","count": 1564,"preSum": 32814 },{ "ndv": 927,"upper": "1850091219812614144","lower": "1850078775463641088","count": 1562,"preSum": 34378 },{ "ndv": 968,"upper": "1850104495355199488","lower": "1850091250263261184","count": 1562,"preSum": 35940 },{ "ndv": 957,"upper": "1850116511952273408","lower": "1850104497234247680","count": 1562,"preSum": 37502 },{ "ndv": 1001,"upper": "1850130883818815488","lower": "1850116525122387968","count": 1562,"preSum": 39064 },{ "ndv": 974,"upper": "1850145198105952256","lower": "1850130904656117760","count": 1562,"preSum": 40626 },{ "ndv": 969,"upper": "1850157654618406912","lower": "1850145205504704512","count": 1563,"preSum": 42188 },{ "ndv": 991,"upper": "1850169421687947264","lower": "1850157657034326016","count": 1562,"preSum": 43751 },{ "ndv": 955,"upper": "1850181920042778624","lower": "1850169432979013632","count": 1562,"preSum": 45313 },{ "ndv": 980,"upper": "1850193663087345664","lower": "1850181924639735808","count": 1562,"preSum": 46875 },{ "ndv": 991,"upper": "1850211000813355008","lower": "1850193667701080064","count": 1562,"preSum": 48437 },{ "ndv": 979,"upper": "1850223906066006016","lower": "1850211003665481728","count": 1562,"preSum": 49999 },{ "ndv": 983,"upper": "1850236483558965248","lower": "1850223912726560768","count": 1562,"preSum": 51561 },{ "ndv": 982,"upper": "1850248556024168448","lower": "1850236489045114880","count": 1562,"preSum": 53123 },{ "ndv": 982,"upper": "1850261132174950400","lower": "1850248557550895104","count": 1563,"preSum": 54685 },{ "ndv": 959,"upper": "1850273896582873088","lower": "1850261148583067648","count": 1564,"preSum": 56248 },{ "ndv": 972,"upper": "1850287953809506304","lower": "1850273906431098880","count": 1562,"preSum": 57812 },{ "ndv": 987,"upper": "1850300715499520000","lower": "1850287959664754688","count": 1562,"preSum": 59374 },{ "ndv": 1000,"upper": "1850313468247277568","lower": "1850300722294292480","count": 1563,"preSum": 60936 },{ "ndv": 975,"upper": "1850325675752292352","lower": "1850313481383837696","count": 1562,"preSum": 62499 },{ "ndv": 975,"upper": "1850338162648285184","lower": "1850325676842811392","count": 1562,"preSum": 64061 },{ "ndv": 968,"upper": "1850352921883967488","lower": "1850338162933497856","count": 1562,"preSum": 65623 },{ "ndv": 957,"upper": "1850364849293361152","lower": "1850352926564810752","count": 1563,"preSum": 67185 },{ "ndv": 959,"upper": "1850377280958758912","lower": "1850364857765855232","count": 1563,"preSum": 68748 },{ "ndv": 987,"upper": "1850390265198542848","lower": "1850377281025867776","count": 1562,"preSum": 70311 },{ "ndv": 963,"upper": "1850402304428081152","lower": "1850390280918794240","count": 1562,"preSum": 71873 },{ "ndv": 980,"upper": "1850419441767022592","lower": "1850402304830734336","count": 1562,"preSum": 73435 },{ "ndv": 973,"upper": "1850431335705870336","lower": "1850419451866906624","count": 1563,"preSum": 74997 },{ "ndv": 956,"upper": "1850443877949898752","lower": "1850431904587710464","count": 1562,"preSum": 76560 },{ "ndv": 966,"upper": "1850456614490865664","lower": "1850443878218334208","count": 1562,"preSum": 78122 },{ "ndv": 967,"upper": "1850469322913218560","lower": "1850456615849820160","count": 1562,"preSum": 79684 },{ "ndv": 968,"upper": "1850481322280091648","lower": "1850469333113765888","count": 1562,"preSum": 81246 },{ "ndv": 972,"upper": "1850496523545083904","lower": "1850481325618757632","count": 1564,"preSum": 82808 },{ "ndv": 977,"upper": "1850509007639281664","lower": "1850496534869704704","count": 1562,"preSum": 84372 },{ "ndv": 984,"upper": "1850521354495852544","lower": "1850509014635380736","count": 1562,"preSum": 85934 },{ "ndv": 956,"upper": "1850534388933066752","lower": "1850521362951569408","count": 1562,"preSum": 87496 },{ "ndv": 971,"upper": "1850547739436253184","lower": "1850534394184335360","count": 1563,"preSum": 89058 },{ "ndv": 991,"upper": "1850565056291405824","lower": "1850547762756583424","count": 1565,"preSum": 90621 },{ "ndv": 970,"upper": "1850578198455123968","lower": "1850565056710836224","count": 1564,"preSum": 92186 },{ "ndv": 973,"upper": "1850590948535304192","lower": "1850578213353291776","count": 1562,"preSum": 93750 },{ "ndv": 969,"upper": "1850602504513912832","lower": "1850590957813104640","count": 1562,"preSum": 95312 },{ "ndv": 986,"upper": "1850615271639744512","lower": "1850602510956363776","count": 1562,"preSum": 96874 },{ "ndv": 941,"upper": "1850627038390517760","lower": "1850615278551957504","count": 1515,"preSum": 98436 } ],"maxBucketSize": 64,"type": "Timestamp","sampleRate": 0.90062594 }
+  cest_full_table_big.c_timestamp_1.null_count:
+    0
+  cest_full_table_big.c_timestamp_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_timestamp_3.TOPN:
+    { "countArr": [ 337,317,473,607,396,437,497,673,296,340,276,902,2272,1283 ],"valueArr": [ 1849903403040243712,1849931202266398720,1849950766194753536,1850040677442781184,1850054339180101632,1850081569406976000,1850082433316159488,1850190555997274112,1850303237668732928,1850340303152611328,1850377691262353408,1850390337793556480,1850485867848663040,1850625578856611840 ],"type": "Timestamp","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_timestamp_3.cardinality:
+    366823
+  cest_full_table_big.c_timestamp_3.histogram:
+    { "buckets": [ { "ndv": 612,"upper": "1849797440090144768","lower": "1849785396146208768","count": 1422,"preSum": 0 },{ "ndv": 620,"upper": "1849810543146172416","lower": "1849797447035912192","count": 1422,"preSum": 1422 },{ "ndv": 589,"upper": "1849821918820040704","lower": "1849810549823504384","count": 1421,"preSum": 2844 },{ "ndv": 632,"upper": "1849835994031849472","lower": "1849821924423630848","count": 1422,"preSum": 4265 },{ "ndv": 599,"upper": "1849847844182163456","lower": "1849835996380659712","count": 1421,"preSum": 5687 },{ "ndv": 662,"upper": "1849863743077351424","lower": "1849847859717865472","count": 1421,"preSum": 7108 },{ "ndv": 533,"upper": "1849874224794042368","lower": "1849863827768737792","count": 1421,"preSum": 8529 },{ "ndv": 445,"upper": "1849883392183631872","lower": "1849874272676216832","count": 1446,"preSum": 9950 },{ "ndv": 665,"upper": "1849896438247456768","lower": "1849883396445044736","count": 1440,"preSum": 11396 },{ "ndv": 733,"upper": "1849911665382916096","lower": "1849896474301693952","count": 1421,"preSum": 12836 },{ "ndv": 546,"upper": "1849931793545822208","lower": "1849911690146086912","count": 1476,"preSum": 14257 },{ "ndv": 660,"upper": "1849945328732602368","lower": "1849931794183356416","count": 1421,"preSum": 15733 },{ "ndv": 640,"upper": "1849957923254435840","lower": "1849945333128232960","count": 1421,"preSum": 17154 },{ "ndv": 622,"upper": "1849970695581204480","lower": "1849957924781162496","count": 1422,"preSum": 18575 },{ "ndv": 500,"upper": "1849981095408304128","lower": "1849970699389632512","count": 1421,"preSum": 19997 },{ "ndv": 595,"upper": "1849992465226924032","lower": "1849981110172254208","count": 1421,"preSum": 21418 },{ "ndv": 565,"upper": "1850005372090187776","lower": "1849992483765747712","count": 1421,"preSum": 22839 },{ "ndv": 590,"upper": "1850017193819897856","lower": "1850005391400763392","count": 1432,"preSum": 24260 },{ "ndv": 674,"upper": "1850030453793226752","lower": "1850017204070776832","count": 1426,"preSum": 25692 },{ "ndv": 558,"upper": "1850041437568106496","lower": "1850030455437393920","count": 1431,"preSum": 27118 },{ "ndv": 679,"upper": "1850055289710051328","lower": "1850041462868148224","count": 1421,"preSum": 28549 },{ "ndv": 616,"upper": "1850071976144535552","lower": "1850055869312532480","count": 1434,"preSum": 29970 },{ "ndv": 627,"upper": "1850085352585297920","lower": "1850071979751636992","count": 1429,"preSum": 31404 },{ "ndv": 623,"upper": "1850098314041622528","lower": "1850085371711324160","count": 1441,"preSum": 32833 },{ "ndv": 662,"upper": "1850111620353622016","lower": "1850098370647949312","count": 1422,"preSum": 34274 },{ "ndv": 645,"upper": "1850124866838069248","lower": "1850111658270130176","count": 1421,"preSum": 35696 },{ "ndv": 564,"upper": "1850138055642447872","lower": "1850124891668348928","count": 1423,"preSum": 37117 },{ "ndv": 720,"upper": "1850152672875773952","lower": "1850138075775107072","count": 1421,"preSum": 38540 },{ "ndv": 671,"upper": "1850166022724648960","lower": "1850152688294035456","count": 1421,"preSum": 39961 },{ "ndv": 627,"upper": "1850178321933926400","lower": "1850166038411345920","count": 1421,"preSum": 41382 },{ "ndv": 630,"upper": "1850191052032442368","lower": "1850178326296002560","count": 1422,"preSum": 42803 },{ "ndv": 700,"upper": "1850209186827206656","lower": "1850191083271618560","count": 1421,"preSum": 44225 },{ "ndv": 666,"upper": "1850223591728087040","lower": "1850209207580622848","count": 1421,"preSum": 45646 },{ "ndv": 665,"upper": "1850236651985436672","lower": "1850223593439363072","count": 1421,"preSum": 47067 },{ "ndv": 597,"upper": "1850248627813875712","lower": "1850236670457151488","count": 1530,"preSum": 48488 },{ "ndv": 535,"upper": "1850259725036290048","lower": "1850248636856795136","count": 1421,"preSum": 50018 },{ "ndv": 653,"upper": "1850272843393138688","lower": "1850259736914558976","count": 1421,"preSum": 51439 },{ "ndv": 510,"upper": "1850285810771820544","lower": "1850272850036916224","count": 1426,"preSum": 52860 },{ "ndv": 722,"upper": "1850300574084366336","lower": "1850285849611075584","count": 1421,"preSum": 54286 },{ "ndv": 578,"upper": "1850311925666152448","lower": "1850300579184640000","count": 1421,"preSum": 55707 },{ "ndv": 610,"upper": "1850324937873555456","lower": "1850311929055150080","count": 1422,"preSum": 57128 },{ "ndv": 689,"upper": "1850338578740019200","lower": "1850324939400282112","count": 1421,"preSum": 58550 },{ "ndv": 619,"upper": "1850353165774356480","lower": "1850338603100536832","count": 1453,"preSum": 59971 },{ "ndv": 647,"upper": "1850365331537657856","lower": "1850353171663159296","count": 1421,"preSum": 61424 },{ "ndv": 714,"upper": "1850379511036641280","lower": "1850365352274296832","count": 1421,"preSum": 62845 },{ "ndv": 638,"upper": "1850392803960422400","lower": "1850379519089704960","count": 1421,"preSum": 64266 },{ "ndv": 627,"upper": "1850406579698925568","lower": "1850392814496514048","count": 1432,"preSum": 65687 },{ "ndv": 680,"upper": "1850423898315685888","lower": "1850406587701657600","count": 1448,"preSum": 67119 },{ "ndv": 678,"upper": "1850437022846550016","lower": "1850423906351972352","count": 1422,"preSum": 68567 },{ "ndv": 555,"upper": "1850447674533216256","lower": "1850437048700239872","count": 1421,"preSum": 69989 },{ "ndv": 601,"upper": "1850459640278548480","lower": "1850447674717765632","count": 1421,"preSum": 71410 },{ "ndv": 676,"upper": "1850472525633421312","lower": "1850459653851316224","count": 1455,"preSum": 72831 },{ "ndv": 646,"upper": "1850485461521268736","lower": "1850472533216722944","count": 1421,"preSum": 74286 },{ "ndv": 721,"upper": "1850502580220723200","lower": "1850485470480302080","count": 1421,"preSum": 75707 },{ "ndv": 654,"upper": "1850515691011047424","lower": "1850502583324508160","count": 1422,"preSum": 77128 },{ "ndv": 603,"upper": "1850527525441110016","lower": "1850515699483541504","count": 1421,"preSum": 78550 },{ "ndv": 698,"upper": "1850542559571476480","lower": "1850527559633076224","count": 1421,"preSum": 79971 },{ "ndv": 671,"upper": "1850560756156727296","lower": "1850542572540264448","count": 1421,"preSum": 81392 },{ "ndv": 517,"upper": "1850571650458714112","lower": "1850560777312796672","count": 1422,"preSum": 82813 },{ "ndv": 582,"upper": "1850583672139284480","lower": "1850571659065425920","count": 1421,"preSum": 84235 },{ "ndv": 654,"upper": "1850595725008699392","lower": "1850583699972685824","count": 1421,"preSum": 85656 },{ "ndv": 684,"upper": "1850609356446367744","lower": "1850595742205345792","count": 1421,"preSum": 87077 },{ "ndv": 636,"upper": "1850622093557760000","lower": "1850609402298499072","count": 1422,"preSum": 88498 },{ "ndv": 255,"upper": "1850627038390517760","lower": "1850622112516014080","count": 975,"preSum": 89920 } ],"maxBucketSize": 64,"type": "Timestamp","sampleRate": 0.90062594 }
+  cest_full_table_big.c_timestamp_3.null_count:
+    0
+  cest_full_table_big.c_timestamp_3.sample_rate:
+    0.010943651
+  cest_full_table_big.c_timestamp_6.TOPN:
+    { "countArr": [ 713,685,1163,1712,860,995,1375,2002,633,859,554,2732,8084,4097 ],"valueArr": [ 1849903403040243712,1849931202266398720,1849950766194753536,1850040677442781184,1850054339180101632,1850081569406976000,1850082433316159488,1850190555997274112,1850303237668732928,1850340303152611328,1850377691262353408,1850390337793556480,1850485867848663040,1850625578856611840 ],"type": "Timestamp","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_timestamp_6.cardinality:
+    244985
+  cest_full_table_big.c_timestamp_6.histogram:
+    { "buckets": [ { "ndv": 382,"upper": "1849796950866526208","lower": "1849785385593339904","count": 1152,"preSum": 0 },{ "ndv": 439,"upper": "1849811990365601792","lower": "1849796967492747264","count": 1157,"preSum": 1152 },{ "ndv": 312,"upper": "1849821743514910720","lower": "1849812000868139008","count": 1150,"preSum": 2309 },{ "ndv": 431,"upper": "1849836801955463168","lower": "1849821746098601984","count": 1266,"preSum": 3459 },{ "ndv": 332,"upper": "1849848106443603968","lower": "1849836855458004992","count": 1275,"preSum": 4725 },{ "ndv": 535,"upper": "1849867257367232512","lower": "1849848111661318144","count": 1169,"preSum": 6000 },{ "ndv": 238,"upper": "1849874316817072128","lower": "1849867259917369344","count": 1180,"preSum": 7169 },{ "ndv": 193,"upper": "1849881078303555584","lower": "1849874336261865472","count": 1150,"preSum": 8349 },{ "ndv": 396,"upper": "1849893412073897984","lower": "1849881084913778688","count": 1151,"preSum": 9499 },{ "ndv": 506,"upper": "1849909682701860864","lower": "1849893418013032448","count": 1150,"preSum": 10650 },{ "ndv": 353,"upper": "1849930912272220160","lower": "1849909722111541248","count": 1228,"preSum": 11800 },{ "ndv": 433,"upper": "1849944846874181632","lower": "1849930938293682176","count": 1167,"preSum": 13028 },{ "ndv": 412,"upper": "1849959285128167424","lower": "1849944997718130688","count": 1161,"preSum": 14195 },{ "ndv": 362,"upper": "1849971093654208512","lower": "1849959291704836096","count": 1324,"preSum": 15356 },{ "ndv": 321,"upper": "1849981625836765184","lower": "1849971115800133632","count": 1150,"preSum": 16680 },{ "ndv": 333,"upper": "1849992531815694336","lower": "1849981678164901888","count": 1150,"preSum": 17830 },{ "ndv": 372,"upper": "1850006183805452288","lower": "1849992557333839872","count": 1199,"preSum": 18980 },{ "ndv": 371,"upper": "1850018928651141120","lower": "1850006189878804480","count": 1150,"preSum": 20179 },{ "ndv": 401,"upper": "1850031714047361024","lower": "1850018944824377344","count": 1209,"preSum": 21329 },{ "ndv": 354,"upper": "1850043178019717120","lower": "1850031759580725248","count": 1157,"preSum": 22538 },{ "ndv": 502,"upper": "1850059046883688448","lower": "1850043220499628032","count": 1152,"preSum": 23695 },{ "ndv": 357,"upper": "1850074329367183360","lower": "1850059053527465984","count": 1150,"preSum": 24847 },{ "ndv": 471,"upper": "1850089951035654144","lower": "1850074329602064384","count": 1150,"preSum": 25997 },{ "ndv": 378,"upper": "1850102621575053312","lower": "1850089952293945344","count": 1153,"preSum": 27147 },{ "ndv": 401,"upper": "1850115981892911104","lower": "1850102694237175808","count": 1172,"preSum": 28300 },{ "ndv": 432,"upper": "1850129963655626752","lower": "1850115989711093760","count": 1150,"preSum": 29472 },{ "ndv": 382,"upper": "1850145169584685056","lower": "1850129985415675904","count": 1150,"preSum": 30622 },{ "ndv": 546,"upper": "1850161903347695616","lower": "1850145174684958720","count": 1185,"preSum": 31772 },{ "ndv": 375,"upper": "1850174954931224576","lower": "1850161974449537024","count": 1150,"preSum": 32957 },{ "ndv": 349,"upper": "1850186479720988672","lower": "1850174963252723712","count": 1154,"preSum": 34107 },{ "ndv": 533,"upper": "1850208454770163712","lower": "1850186509836091392","count": 1150,"preSum": 35261 },{ "ndv": 357,"upper": "1850221306889371648","lower": "1850208466061230080","count": 1151,"preSum": 36411 },{ "ndv": 476,"upper": "1850236869787254784","lower": "1850221430352904192","count": 1165,"preSum": 37562 },{ "ndv": 356,"upper": "1850248579982032896","lower": "1850236914733416448","count": 1151,"preSum": 38727 },{ "ndv": 229,"upper": "1850256488140898304","lower": "1850248591977742336","count": 1244,"preSum": 39878 },{ "ndv": 418,"upper": "1850270210964062208","lower": "1850256518792871936","count": 1150,"preSum": 41122 },{ "ndv": 279,"upper": "1850281282735439872","lower": "1850270222305460224","count": 1183,"preSum": 42272 },{ "ndv": 388,"upper": "1850294318095400960","lower": "1850281291124047872","count": 1183,"preSum": 43455 },{ "ndv": 397,"upper": "1850307336611037184","lower": "1850294322407145472","count": 1338,"preSum": 44638 },{ "ndv": 416,"upper": "1850320206262435840","lower": "1850307352884936704","count": 1155,"preSum": 45976 },{ "ndv": 469,"upper": "1850335705977323520","lower": "1850320209735319552","count": 1158,"preSum": 47131 },{ "ndv": 425,"upper": "1850351755045371904","lower": "1850335728274243584","count": 1158,"preSum": 48289 },{ "ndv": 408,"upper": "1850364849293361152","lower": "1850351766118334464","count": 1150,"preSum": 49447 },{ "ndv": 514,"upper": "1850380355836575744","lower": "1850364851524730880","count": 1151,"preSum": 50597 },{ "ndv": 377,"upper": "1850393242600734720","lower": "1850380371137396736","count": 1150,"preSum": 51748 },{ "ndv": 409,"upper": "1850406622413717504","lower": "1850393264645996544","count": 1170,"preSum": 52898 },{ "ndv": 444,"upper": "1850425620798898176","lower": "1850406644844855296","count": 1152,"preSum": 54068 },{ "ndv": 378,"upper": "1850437878937550848","lower": "1850425663681462272","count": 1166,"preSum": 55220 },{ "ndv": 387,"upper": "1850450291997016064","lower": "1850438492614557696","count": 1312,"preSum": 56386 },{ "ndv": 465,"upper": "1850465908917534720","lower": "1850450330651721728","count": 1159,"preSum": 57698 },{ "ndv": 360,"upper": "1850478174018732032","lower": "1850465913631932416","count": 1150,"preSum": 58857 },{ "ndv": 462,"upper": "1850494951150845952","lower": "1850478194201722880","count": 1150,"preSum": 60007 },{ "ndv": 473,"upper": "1850509532816474112","lower": "1850494960713859072","count": 1150,"preSum": 61157 },{ "ndv": 383,"upper": "1850522052864245760","lower": "1850509551288188928","count": 1185,"preSum": 62307 },{ "ndv": 382,"upper": "1850534461007986688","lower": "1850522061236076544","count": 1151,"preSum": 63492 },{ "ndv": 450,"upper": "1850549553271406592","lower": "1850534532730585088","count": 1157,"preSum": 64643 },{ "ndv": 227,"upper": "1850562175207211008","lower": "1850549618551554048","count": 1249,"preSum": 65800 },{ "ndv": 418,"upper": "1850577441886568448","lower": "1850562223844360192","count": 1465,"preSum": 67049 },{ "ndv": 504,"upper": "1850592932759863296","lower": "1850577513273622528","count": 1498,"preSum": 68514 },{ "ndv": 528,"upper": "1850610186566238208","lower": "1850592936064974848","count": 1151,"preSum": 70012 },{ "ndv": 386,"upper": "1850622628532846592","lower": "1850610197001666560","count": 1539,"preSum": 71163 },{ "ndv": 128,"upper": "1850627017788096512","lower": "1850623220550467584","count": 835,"preSum": 72702 } ],"maxBucketSize": 64,"type": "Timestamp","sampleRate": 0.90062594 }
+  cest_full_table_big.c_timestamp_6.null_count:
+    0
+  cest_full_table_big.c_timestamp_6.sample_rate:
+    0.010943651
+  cest_full_table_big.c_time_1.TOPN:
+    { "countArr": [ 59,83,75,64,215,63,60,85,163,125,122,76,58 ],"valueArr": [ 48737812480,170355851264,277763588096,531015663616,535713284096,626192809984,637718757376,766450335744,790508863488,915633340416,1318471073792,1565314252800,1600814841856 ],"type": "Time","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_time_1.cardinality:
+    212682
+  cest_full_table_big.c_time_1.histogram:
+    { "buckets": [ { "ndv": 675,"upper": "24930942976","lower": "16777216","count": 1546,"preSum": 0 },{ "ndv": 635,"upper": "48570040320","lower": "24947720192","count": 1544,"preSum": 1546 },{ "ndv": 653,"upper": "79456894976","lower": "48586817536","count": 1544,"preSum": 3090 },{ "ndv": 611,"upper": "102710116352","lower": "79473672192","count": 1545,"preSum": 4634 },{ "ndv": 649,"upper": "127993380864","lower": "102743670784","count": 1545,"preSum": 6179 },{ "ndv": 634,"upper": "155977777152","lower": "128010158080","count": 1545,"preSum": 7724 },{ "ndv": 646,"upper": "181076492288","lower": "156011331584","count": 1546,"preSum": 9269 },{ "ndv": 663,"upper": "210872827904","lower": "181093269504","count": 1544,"preSum": 10815 },{ "ndv": 664,"upper": "236474859520","lower": "210889605120","count": 1544,"preSum": 12359 },{ "ndv": 614,"upper": "260315283456","lower": "236491636736","count": 1544,"preSum": 13903 },{ "ndv": 658,"upper": "289759297536","lower": "260348837888","count": 1545,"preSum": 15447 },{ "ndv": 603,"upper": "312660197376","lower": "289792851968","count": 1546,"preSum": 16992 },{ "ndv": 610,"upper": "335863087104","lower": "312693751808","count": 1544,"preSum": 18538 },{ "ndv": 666,"upper": "366145961984","lower": "335879864320","count": 1544,"preSum": 20082 },{ "ndv": 573,"upper": "388140892160","lower": "366179516416","count": 1545,"preSum": 21626 },{ "ndv": 664,"upper": "417383579648","lower": "388157669376","count": 1546,"preSum": 23171 },{ "ndv": 610,"upper": "440368365568","lower": "417467465728","count": 1550,"preSum": 24717 },{ "ndv": 660,"upper": "466440159232","lower": "440401920000","count": 1546,"preSum": 26267 },{ "ndv": 596,"upper": "493820575744","lower": "466490490880","count": 1549,"preSum": 27813 },{ "ndv": 626,"upper": "517275123712","lower": "493837352960","count": 1545,"preSum": 29362 },{ "ndv": 667,"upper": "543850233856","lower": "517308678144","count": 1548,"preSum": 30907 },{ "ndv": 638,"upper": "572153397248","lower": "543900565504","count": 1555,"preSum": 32455 },{ "ndv": 593,"upper": "594953633792","lower": "572186951680","count": 1544,"preSum": 34010 },{ "ndv": 666,"upper": "623139356672","lower": "594987188224","count": 1546,"preSum": 35554 },{ "ndv": 663,"upper": "649009823744","lower": "623172911104","count": 1544,"preSum": 37100 },{ "ndv": 569,"upper": "670685986816","lower": "649043378176","count": 1545,"preSum": 38644 },{ "ndv": 638,"upper": "699291140096","lower": "670736318464","count": 1544,"preSum": 40189 },{ "ndv": 657,"upper": "724490518528","lower": "699307917312","count": 1544,"preSum": 41733 },{ "ndv": 630,"upper": "749371129856","lower": "724540850176","count": 1545,"preSum": 43277 },{ "ndv": 670,"upper": "779368792064","lower": "749387907072","count": 1550,"preSum": 44822 },{ "ndv": 597,"upper": "802672345088","lower": "779385569280","count": 1544,"preSum": 46372 },{ "ndv": 623,"upper": "830438637568","lower": "802689122304","count": 1545,"preSum": 47916 },{ "ndv": 642,"upper": "855252140032","lower": "830455414784","count": 1547,"preSum": 49461 },{ "ndv": 601,"upper": "878320812032","lower": "855285694464","count": 1544,"preSum": 51008 },{ "ndv": 633,"upper": "908234588160","lower": "878337589248","count": 1544,"preSum": 52552 },{ "ndv": 642,"upper": "933115199488","lower": "908251365376","count": 1544,"preSum": 54096 },{ "ndv": 614,"upper": "955781218304","lower": "933131976704","count": 1544,"preSum": 55640 },{ "ndv": 611,"upper": "982524100608","lower": "955797995520","count": 1544,"preSum": 57184 },{ "ndv": 649,"upper": "1006649737216","lower": "982540877824","count": 1545,"preSum": 58728 },{ "ndv": 617,"upper": "1034567024640","lower": "1006683291648","count": 1544,"preSum": 60273 },{ "ndv": 639,"upper": "1060303273984","lower": "1034701242368","count": 1545,"preSum": 61817 },{ "ndv": 623,"upper": "1083724267520","lower": "1060336828416","count": 1546,"preSum": 63362 },{ "ndv": 626,"upper": "1112497192960","lower": "1083741044736","count": 1546,"preSum": 64908 },{ "ndv": 603,"upper": "1136270508032","lower": "1112530747392","count": 1544,"preSum": 66454 },{ "ndv": 610,"upper": "1159959937024","lower": "1136320839680","count": 1545,"preSum": 67998 },{ "ndv": 601,"upper": "1187206135808","lower": "1159976714240","count": 1546,"preSum": 69543 },{ "ndv": 668,"upper": "1213714137088","lower": "1187222913024","count": 1551,"preSum": 71089 },{ "ndv": 651,"upper": "1242621280256","lower": "1213781245952","count": 1547,"preSum": 72640 },{ "ndv": 642,"upper": "1267149570048","lower": "1242671611904","count": 1544,"preSum": 74187 },{ "ndv": 634,"upper": "1292650938368","lower": "1267183124480","count": 1546,"preSum": 75731 },{ "ndv": 637,"upper": "1320299790336","lower": "1292667715584","count": 1544,"preSum": 77277 },{ "ndv": 652,"upper": "1346757459968","lower": "1320333344768","count": 1544,"preSum": 78821 },{ "ndv": 612,"upper": "1369977126912","lower": "1346791014400","count": 1575,"preSum": 80365 },{ "ndv": 584,"upper": "1397105885184","lower": "1374389534720","count": 1546,"preSum": 81940 },{ "ndv": 667,"upper": "1421650952192","lower": "1397122662400","count": 1545,"preSum": 83486 },{ "ndv": 616,"upper": "1449182363648","lower": "1421684506624","count": 1544,"preSum": 85031 },{ "ndv": 609,"upper": "1472938901504","lower": "1449199140864","count": 1546,"preSum": 86575 },{ "ndv": 612,"upper": "1497450414080","lower": "1473073119232","count": 1544,"preSum": 88121 },{ "ndv": 628,"upper": "1524159741952","lower": "1497517522944","count": 1544,"preSum": 89665 },{ "ndv": 624,"upper": "1546993532928","lower": "1524176519168","count": 1547,"preSum": 91209 },{ "ndv": 618,"upper": "1570397749248","lower": "1547043864576","count": 1546,"preSum": 92756 },{ "ndv": 607,"upper": "1599070011392","lower": "1570431303680","count": 1545,"preSum": 94302 },{ "ndv": 640,"upper": "1622524559360","lower": "1599137120256","count": 1544,"preSum": 95847 },{ "ndv": 592,"upper": "1644804702208","lower": "1622591668224","count": 1362,"preSum": 97391 } ],"maxBucketSize": 64,"type": "Time","sampleRate": 0.90062594 }
+  cest_full_table_big.c_time_1.null_count:
+    0
+  cest_full_table_big.c_time_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_time_3.TOPN:
+    { "countArr": [ 148,239,181,171,761,143,194,131,291,449,324,330,216,141 ],"valueArr": [ 48737812480,170355851264,277763588096,531015663616,535713284096,593544347648,626192809984,637718757376,766450335744,790508863488,915633340416,1318471073792,1565314252800,1600814841856 ],"type": "Time","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_time_3.cardinality:
+    221045
+  cest_full_table_big.c_time_3.histogram:
+    { "buckets": [ { "ndv": 616,"upper": "24461180928","lower": "16777216","count": 1508,"preSum": 0 },{ "ndv": 576,"upper": "48419045376","lower": "24477958144","count": 1507,"preSum": 1508 },{ "ndv": 556,"upper": "77460406272","lower": "48486154240","count": 1512,"preSum": 3015 },{ "ndv": 550,"upper": "100394860544","lower": "77477183488","count": 1506,"preSum": 4527 },{ "ndv": 605,"upper": "126332436480","lower": "100411637760","count": 1519,"preSum": 6033 },{ "ndv": 542,"upper": "152219680768","lower": "126349213696","count": 1506,"preSum": 7552 },{ "ndv": 614,"upper": "179063226368","lower": "152236457984","count": 1506,"preSum": 9058 },{ "ndv": 617,"upper": "208641458176","lower": "179080003584","count": 1505,"preSum": 10564 },{ "ndv": 630,"upper": "233689841664","lower": "208725344256","count": 1507,"preSum": 12069 },{ "ndv": 562,"upper": "257614151680","lower": "233706618880","count": 1505,"preSum": 13576 },{ "ndv": 635,"upper": "288098353152","lower": "257698037760","count": 1506,"preSum": 15081 },{ "ndv": 506,"upper": "308834992128","lower": "288131907584","count": 1527,"preSum": 16587 },{ "ndv": 573,"upper": "333648494592","lower": "308851769344","count": 1507,"preSum": 18114 },{ "ndv": 574,"upper": "362152984576","lower": "333665271808","count": 1505,"preSum": 19621 },{ "ndv": 547,"upper": "384315686912","lower": "362169761792","count": 1505,"preSum": 21126 },{ "ndv": 630,"upper": "414044913664","lower": "384399572992","count": 1505,"preSum": 22631 },{ "ndv": 540,"upper": "436878704640","lower": "414078468096","count": 1506,"preSum": 24136 },{ "ndv": 600,"upper": "461792870400","lower": "436912259072","count": 1508,"preSum": 25642 },{ "ndv": 544,"upper": "489290727424","lower": "461809647616","count": 1505,"preSum": 27150 },{ "ndv": 575,"upper": "513852571648","lower": "489307504640","count": 1562,"preSum": 28655 },{ "ndv": 626,"upper": "540645785600","lower": "514003566592","count": 1507,"preSum": 30217 },{ "ndv": 590,"upper": "569989136384","lower": "540696117248","count": 1508,"preSum": 31724 },{ "ndv": 534,"upper": "592017620992","lower": "570005913600","count": 1512,"preSum": 33232 },{ "ndv": 630,"upper": "622636040192","lower": "592034398208","count": 1509,"preSum": 34744 },{ "ndv": 643,"upper": "651408965632","lower": "622669594624","count": 1505,"preSum": 36253 },{ "ndv": 471,"upper": "670635655168","lower": "651425742848","count": 1506,"preSum": 37758 },{ "ndv": 577,"upper": "698485833728","lower": "670652432384","count": 1505,"preSum": 39264 },{ "ndv": 626,"upper": "724121419776","lower": "698519388160","count": 1508,"preSum": 40769 },{ "ndv": 537,"upper": "747592744960","lower": "724138196992","count": 1508,"preSum": 42277 },{ "ndv": 581,"upper": "777238085632","lower": "747659853824","count": 1506,"preSum": 43785 },{ "ndv": 595,"upper": "801766375424","lower": "777254862848","count": 1507,"preSum": 45291 },{ "ndv": 570,"upper": "828760915968","lower": "801816707072","count": 1508,"preSum": 46798 },{ "ndv": 601,"upper": "854329393152","lower": "828794470400","count": 1508,"preSum": 48306 },{ "ndv": 538,"upper": "877012189184","lower": "854346170368","count": 1506,"preSum": 49814 },{ "ndv": 572,"upper": "905751560192","lower": "877028966400","count": 1506,"preSum": 51320 },{ "ndv": 616,"upper": "932158898176","lower": "905768337408","count": 1505,"preSum": 52826 },{ "ndv": 566,"upper": "955764441088","lower": "932226007040","count": 1505,"preSum": 54331 },{ "ndv": 569,"upper": "983128080384","lower": "955781218304","count": 1508,"preSum": 55836 },{ "ndv": 607,"upper": "1008897884160","lower": "983262298112","count": 1505,"preSum": 57344 },{ "ndv": 599,"upper": "1039096872960","lower": "1008981770240","count": 1512,"preSum": 58849 },{ "ndv": 609,"upper": "1063558053888","lower": "1039113650176","count": 1505,"preSum": 60361 },{ "ndv": 586,"upper": "1088505774080","lower": "1063574831104","count": 1505,"preSum": 61866 },{ "ndv": 601,"upper": "1118084005888","lower": "1088522551296","count": 1505,"preSum": 63371 },{ "ndv": 577,"upper": "1142914285568","lower": "1118285332480","count": 1513,"preSum": 64876 },{ "ndv": 546,"upper": "1170512805888","lower": "1142947840000","count": 1506,"preSum": 66389 },{ "ndv": 547,"upper": "1193363374080","lower": "1170529583104","count": 1507,"preSum": 67895 },{ "ndv": 622,"upper": "1219250618368","lower": "1193380151296","count": 1505,"preSum": 69402 },{ "ndv": 619,"upper": "1250691121152","lower": "1219267395584","count": 1507,"preSum": 70907 },{ "ndv": 593,"upper": "1276142157824","lower": "1250758230016","count": 1511,"preSum": 72414 },{ "ndv": 550,"upper": "1299445710848","lower": "1276192489472","count": 1505,"preSum": 73925 },{ "ndv": 608,"upper": "1328772284416","lower": "1299462488064","count": 1507,"preSum": 75430 },{ "ndv": 614,"upper": "1355750047744","lower": "1328872947712","count": 1508,"preSum": 76937 },{ "ndv": 556,"upper": "1383398899712","lower": "1355766824960","count": 1508,"preSum": 78445 },{ "ndv": 525,"upper": "1405360275456","lower": "1383415676928","count": 1508,"preSum": 79953 },{ "ndv": 567,"upper": "1428412170240","lower": "1405393829888","count": 1505,"preSum": 81461 },{ "ndv": 534,"upper": "1453577994240","lower": "1428428947456","count": 1506,"preSum": 82966 },{ "ndv": 590,"upper": "1478743818240","lower": "1453594771456","count": 1505,"preSum": 84472 },{ "ndv": 548,"upper": "1501644718080","lower": "1478794149888","count": 1506,"preSum": 85977 },{ "ndv": 581,"upper": "1529008357376","lower": "1501678272512","count": 1507,"preSum": 87483 },{ "ndv": 536,"upper": "1550365753344","lower": "1529025134592","count": 1505,"preSum": 88990 },{ "ndv": 535,"upper": "1572931108864","lower": "1550399307776","count": 1514,"preSum": 90495 },{ "ndv": 504,"upper": "1599539773440","lower": "1573031772160","count": 1506,"preSum": 92009 },{ "ndv": 594,"upper": "1624168726528","lower": "1599573327872","count": 1506,"preSum": 93515 },{ "ndv": 505,"upper": "1644804702208","lower": "1624219058176","count": 1261,"preSum": 95021 } ],"maxBucketSize": 64,"type": "Time","sampleRate": 0.90062594 }
+  cest_full_table_big.c_time_3.null_count:
+    0
+  cest_full_table_big.c_time_3.sample_rate:
+    0.010943651
+  cest_full_table_big.c_time_6.TOPN:
+    { "countArr": [ 282,413,305,311,1785,228,316,229,511,1018,731,642,384,263 ],"valueArr": [ 48737812480,170355851264,277763588096,531015663616,535713284096,593544347648,626192809984,637718757376,766450335744,790508863488,915633340416,1318471073792,1565314252800,1600814841856 ],"type": "Time","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_time_6.cardinality:
+    218730
+  cest_full_table_big.c_time_6.histogram:
+    { "buckets": [ { "ndv": 557,"upper": "26038239232","lower": "16777216","count": 1450,"preSum": 0 },{ "ndv": 559,"upper": "50667192320","lower": "26055016448","count": 1447,"preSum": 1450 },{ "ndv": 492,"upper": "79171682304","lower": "50801410048","count": 1449,"preSum": 2897 },{ "ndv": 492,"upper": "100931731456","lower": "79255568384","count": 1463,"preSum": 4346 },{ "ndv": 515,"upper": "126349213696","lower": "100948508672","count": 1447,"preSum": 5809 },{ "ndv": 453,"upper": "150005088256","lower": "126416322560","count": 1447,"preSum": 7256 },{ "ndv": 577,"upper": "178274697216","lower": "150038642688","count": 1447,"preSum": 8703 },{ "ndv": 546,"upper": "207517384704","lower": "178308251648","count": 1448,"preSum": 10150 },{ "ndv": 592,"upper": "234528702464","lower": "207651602432","count": 1450,"preSum": 11598 },{ "ndv": 486,"upper": "258184577024","lower": "234545479680","count": 1455,"preSum": 13048 },{ "ndv": 579,"upper": "289222426624","lower": "258218131456","count": 1447,"preSum": 14503 },{ "ndv": 417,"upper": "308834992128","lower": "289272758272","count": 1475,"preSum": 15950 },{ "ndv": 517,"upper": "332222431232","lower": "308851769344","count": 1447,"preSum": 17425 },{ "ndv": 563,"upper": "362454974464","lower": "332289540096","count": 1457,"preSum": 18872 },{ "ndv": 482,"upper": "384802226176","lower": "362471751680","count": 1447,"preSum": 20329 },{ "ndv": 572,"upper": "415991070720","lower": "384869335040","count": 1447,"preSum": 21776 },{ "ndv": 491,"upper": "438841638912","lower": "416041402368","count": 1447,"preSum": 23223 },{ "ndv": 553,"upper": "464024240128","lower": "438858416128","count": 1447,"preSum": 24670 },{ "ndv": 489,"upper": "490616127488","lower": "464091348992","count": 1447,"preSum": 26117 },{ "ndv": 525,"upper": "515865837568","lower": "490750345216","count": 1447,"preSum": 27564 },{ "ndv": 615,"upper": "550041026560","lower": "515882614784","count": 1447,"preSum": 29011 },{ "ndv": 492,"upper": "572556050432","lower": "550124912640","count": 1448,"preSum": 30458 },{ "ndv": 464,"upper": "592252502016","lower": "572572827648","count": 1450,"preSum": 31906 },{ "ndv": 624,"upper": "624968073216","lower": "592437051392","count": 1447,"preSum": 33356 },{ "ndv": 629,"upper": "654244315136","lower": "625035182080","count": 1450,"preSum": 34803 },{ "ndv": 355,"upper": "670048452608","lower": "654277869568","count": 1447,"preSum": 36253 },{ "ndv": 543,"upper": "698469056512","lower": "670082007040","count": 1448,"preSum": 37700 },{ "ndv": 539,"upper": "724473741312","lower": "698485833728","count": 1447,"preSum": 39148 },{ "ndv": 548,"upper": "749522124800","lower": "724540850176","count": 1447,"preSum": 40595 },{ "ndv": 550,"upper": "779955994624","lower": "749555679232","count": 1448,"preSum": 42042 },{ "ndv": 506,"upper": "804014522368","lower": "779989549056","count": 1447,"preSum": 43490 },{ "ndv": 540,"upper": "833525645312","lower": "804031299584","count": 1447,"preSum": 44937 },{ "ndv": 539,"upper": "858607583232","lower": "833626308608","count": 1448,"preSum": 46384 },{ "ndv": 478,"upper": "882078908416","lower": "858691469312","count": 1451,"preSum": 47832 },{ "ndv": 464,"upper": "908922454016","lower": "882112462848","count": 1453,"preSum": 49283 },{ "ndv": 613,"upper": "937863151616","lower": "908989562880","count": 1447,"preSum": 50736 },{ "ndv": 517,"upper": "965562335232","lower": "937930260480","count": 1453,"preSum": 52183 },{ "ndv": 522,"upper": "988278685696","lower": "965595889664","count": 1448,"preSum": 53636 },{ "ndv": 530,"upper": "1011901005824","lower": "988312240128","count": 1447,"preSum": 55084 },{ "ndv": 564,"upper": "1042720751616","lower": "1011984891904","count": 1447,"preSum": 56531 },{ "ndv": 538,"upper": "1066896719872","lower": "1042771083264","count": 1447,"preSum": 57978 },{ "ndv": 504,"upper": "1090401599488","lower": "1066947051520","count": 1483,"preSum": 59425 },{ "ndv": 565,"upper": "1121825325056","lower": "1090451931136","count": 1448,"preSum": 60908 },{ "ndv": 490,"upper": "1144105467904","lower": "1121875656704","count": 1448,"preSum": 62356 },{ "ndv": 495,"upper": "1171536216064","lower": "1144155799552","count": 1449,"preSum": 63804 },{ "ndv": 474,"upper": "1194151903232","lower": "1171586547712","count": 1448,"preSum": 65253 },{ "ndv": 614,"upper": "1222052413440","lower": "1194185457664","count": 1450,"preSum": 66701 },{ "ndv": 555,"upper": "1252737941504","lower": "1222069190656","count": 1449,"preSum": 68151 },{ "ndv": 565,"upper": "1279648595968","lower": "1252771495936","count": 1477,"preSum": 69600 },{ "ndv": 558,"upper": "1308924837888","lower": "1279749259264","count": 1447,"preSum": 71077 },{ "ndv": 592,"upper": "1336053596160","lower": "1308941615104","count": 1447,"preSum": 72524 },{ "ndv": 577,"upper": "1362343493632","lower": "1336120705024","count": 1452,"preSum": 73971 },{ "ndv": 432,"upper": "1386922115072","lower": "1362360270848","count": 1448,"preSum": 75423 },{ "ndv": 480,"upper": "1409739128832","lower": "1386972446720","count": 1448,"preSum": 76871 },{ "ndv": 554,"upper": "1433965428736","lower": "1409839792128","count": 1447,"preSum": 78319 },{ "ndv": 476,"upper": "1459718455296","lower": "1433998983168","count": 1447,"preSum": 79766 },{ "ndv": 522,"upper": "1484364185600","lower": "1459768786944","count": 1454,"preSum": 81213 },{ "ndv": 452,"upper": "1504211632128","lower": "1484380962816","count": 1447,"preSum": 82667 },{ "ndv": 558,"upper": "1533454319616","lower": "1504228409344","count": 1464,"preSum": 84114 },{ "ndv": 449,"upper": "1553805082624","lower": "1533487874048","count": 1553,"preSum": 85578 },{ "ndv": 480,"upper": "1580833177600","lower": "1553838637056","count": 1449,"preSum": 87131 },{ "ndv": 445,"upper": "1601821474816","lower": "1580866732032","count": 1495,"preSum": 88580 },{ "ndv": 547,"upper": "1626215546880","lower": "1601905360896","count": 1447,"preSum": 90075 },{ "ndv": 386,"upper": "1644787924992","lower": "1626349764608","count": 1061,"preSum": 91522 } ],"maxBucketSize": 64,"type": "Time","sampleRate": 0.90062594 }
+  cest_full_table_big.c_time_6.null_count:
+    0
+  cest_full_table_big.c_time_6.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_1.TOPN:
+    { "countArr": [ 548,509,479,551,495,541,488,583,489,493,538,517,581,510 ],"valueArr": [ -113,-98,-78,-61,-57,-52,-44,9,19,38,41,46,86,89 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_1.cardinality:
+    256
+  cest_full_table_big.c_tinyint_1.histogram:
+    { "buckets": [ { "ndv": 4,"upper": -125,"lower": -128,"count": 1528,"preSum": 0 },{ "ndv": 4,"upper": -121,"lower": -124,"count": 1519,"preSum": 1528 },{ "ndv": 4,"upper": -117,"lower": -120,"count": 1478,"preSum": 3047 },{ "ndv": 4,"upper": -112,"lower": -116,"count": 1552,"preSum": 4525 },{ "ndv": 4,"upper": -108,"lower": -111,"count": 1530,"preSum": 6077 },{ "ndv": 4,"upper": -104,"lower": -107,"count": 1527,"preSum": 7607 },{ "ndv": 4,"upper": -100,"lower": -103,"count": 1453,"preSum": 9134 },{ "ndv": 4,"upper": -95,"lower": -99,"count": 1633,"preSum": 10587 },{ "ndv": 4,"upper": -91,"lower": -94,"count": 1624,"preSum": 12220 },{ "ndv": 4,"upper": -87,"lower": -90,"count": 1484,"preSum": 13844 },{ "ndv": 5,"upper": -82,"lower": -86,"count": 1800,"preSum": 15328 },{ "ndv": 4,"upper": -77,"lower": -81,"count": 1564,"preSum": 17128 },{ "ndv": 5,"upper": -72,"lower": -76,"count": 1805,"preSum": 18692 },{ "ndv": 4,"upper": -68,"lower": -71,"count": 1565,"preSum": 20497 },{ "ndv": 4,"upper": -64,"lower": -67,"count": 1506,"preSum": 22062 },{ "ndv": 4,"upper": -59,"lower": -63,"count": 1566,"preSum": 23568 },{ "ndv": 4,"upper": -54,"lower": -58,"count": 1632,"preSum": 25134 },{ "ndv": 4,"upper": -49,"lower": -53,"count": 1606,"preSum": 26766 },{ "ndv": 4,"upper": -45,"lower": -48,"count": 1606,"preSum": 28372 },{ "ndv": 5,"upper": -39,"lower": -43,"count": 1861,"preSum": 29978 },{ "ndv": 4,"upper": -35,"lower": -38,"count": 1557,"preSum": 31839 },{ "ndv": 4,"upper": -31,"lower": -34,"count": 1517,"preSum": 33396 },{ "ndv": 4,"upper": -27,"lower": -30,"count": 1556,"preSum": 34913 },{ "ndv": 4,"upper": -23,"lower": -26,"count": 1599,"preSum": 36469 },{ "ndv": 4,"upper": -19,"lower": -22,"count": 1541,"preSum": 38068 },{ "ndv": 4,"upper": -15,"lower": -18,"count": 1631,"preSum": 39609 },{ "ndv": 5,"upper": -10,"lower": -14,"count": 1791,"preSum": 41240 },{ "ndv": 4,"upper": -6,"lower": -9,"count": 1609,"preSum": 43031 },{ "ndv": 4,"upper": -2,"lower": -5,"count": 1550,"preSum": 44640 },{ "ndv": 4,"upper": 2,"lower": -1,"count": 1470,"preSum": 46190 },{ "ndv": 4,"upper": 6,"lower": 3,"count": 1554,"preSum": 47660 },{ "ndv": 4,"upper": 11,"lower": 7,"count": 1627,"preSum": 49214 },{ "ndv": 4,"upper": 15,"lower": 12,"count": 1524,"preSum": 50841 },{ "ndv": 4,"upper": 20,"lower": 16,"count": 1662,"preSum": 52365 },{ "ndv": 4,"upper": 24,"lower": 21,"count": 1502,"preSum": 54027 },{ "ndv": 4,"upper": 28,"lower": 25,"count": 1459,"preSum": 55529 },{ "ndv": 4,"upper": 32,"lower": 29,"count": 1624,"preSum": 56988 },{ "ndv": 4,"upper": 36,"lower": 33,"count": 1463,"preSum": 58612 },{ "ndv": 4,"upper": 42,"lower": 37,"count": 1553,"preSum": 60075 },{ "ndv": 4,"upper": 47,"lower": 43,"count": 1525,"preSum": 61628 },{ "ndv": 4,"upper": 51,"lower": 48,"count": 1466,"preSum": 63153 },{ "ndv": 4,"upper": 55,"lower": 52,"count": 1563,"preSum": 64619 },{ "ndv": 4,"upper": 59,"lower": 56,"count": 1711,"preSum": 66182 },{ "ndv": 4,"upper": 63,"lower": 60,"count": 1529,"preSum": 67893 },{ "ndv": 4,"upper": 67,"lower": 64,"count": 1474,"preSum": 69422 },{ "ndv": 4,"upper": 71,"lower": 68,"count": 1510,"preSum": 70896 },{ "ndv": 4,"upper": 75,"lower": 72,"count": 1464,"preSum": 72406 },{ "ndv": 4,"upper": 79,"lower": 76,"count": 1533,"preSum": 73870 },{ "ndv": 4,"upper": 83,"lower": 80,"count": 1496,"preSum": 75403 },{ "ndv": 4,"upper": 88,"lower": 84,"count": 1511,"preSum": 76899 },{ "ndv": 4,"upper": 93,"lower": 90,"count": 1522,"preSum": 78410 },{ "ndv": 4,"upper": 97,"lower": 94,"count": 1567,"preSum": 79932 },{ "ndv": 4,"upper": 101,"lower": 98,"count": 1549,"preSum": 81499 },{ "ndv": 4,"upper": 105,"lower": 102,"count": 1519,"preSum": 83048 },{ "ndv": 4,"upper": 109,"lower": 106,"count": 1525,"preSum": 84567 },{ "ndv": 4,"upper": 113,"lower": 110,"count": 1488,"preSum": 86092 },{ "ndv": 4,"upper": 117,"lower": 114,"count": 1477,"preSum": 87580 },{ "ndv": 4,"upper": 121,"lower": 118,"count": 1463,"preSum": 89057 },{ "ndv": 4,"upper": 125,"lower": 122,"count": 1449,"preSum": 90520 },{ "ndv": 2,"upper": 127,"lower": 126,"count": 710,"preSum": 91969 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_1.null_count:
+    0
+  cest_full_table_big.c_tinyint_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_1_un.TOPN:
+    { "countArr": [ 1274,1046,963,1354,1090,1069,1700,1067,1359,1131,1017,1236,1171,997 ],"valueArr": [ 7,15,17,33,38,42,68,73,84,87,92,107,108,115 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_1_un.cardinality:
+    128
+  cest_full_table_big.c_tinyint_1_un.histogram:
+    { "buckets": [ { "ndv": 3,"upper": 2,"lower": 0,"count": 2132,"preSum": 0 },{ "ndv": 2,"upper": 4,"lower": 3,"count": 1311,"preSum": 2132 },{ "ndv": 2,"upper": 6,"lower": 5,"count": 1520,"preSum": 3443 },{ "ndv": 2,"upper": 9,"lower": 8,"count": 1423,"preSum": 4963 },{ "ndv": 2,"upper": 11,"lower": 10,"count": 1462,"preSum": 6386 },{ "ndv": 3,"upper": 14,"lower": 12,"count": 1923,"preSum": 7848 },{ "ndv": 2,"upper": 18,"lower": 16,"count": 1422,"preSum": 9771 },{ "ndv": 2,"upper": 20,"lower": 19,"count": 1434,"preSum": 11193 },{ "ndv": 2,"upper": 22,"lower": 21,"count": 1399,"preSum": 12627 },{ "ndv": 2,"upper": 24,"lower": 23,"count": 1455,"preSum": 14026 },{ "ndv": 2,"upper": 26,"lower": 25,"count": 1458,"preSum": 15481 },{ "ndv": 2,"upper": 28,"lower": 27,"count": 1349,"preSum": 16939 },{ "ndv": 2,"upper": 30,"lower": 29,"count": 1425,"preSum": 18288 },{ "ndv": 2,"upper": 32,"lower": 31,"count": 1400,"preSum": 19713 },{ "ndv": 2,"upper": 35,"lower": 34,"count": 1655,"preSum": 21113 },{ "ndv": 2,"upper": 37,"lower": 36,"count": 1787,"preSum": 22768 },{ "ndv": 2,"upper": 40,"lower": 39,"count": 1570,"preSum": 24555 },{ "ndv": 3,"upper": 44,"lower": 41,"count": 2198,"preSum": 26125 },{ "ndv": 2,"upper": 46,"lower": 45,"count": 1355,"preSum": 28323 },{ "ndv": 2,"upper": 48,"lower": 47,"count": 1394,"preSum": 29678 },{ "ndv": 2,"upper": 50,"lower": 49,"count": 1550,"preSum": 31072 },{ "ndv": 2,"upper": 52,"lower": 51,"count": 1607,"preSum": 32622 },{ "ndv": 2,"upper": 54,"lower": 53,"count": 1533,"preSum": 34229 },{ "ndv": 2,"upper": 56,"lower": 55,"count": 1753,"preSum": 35762 },{ "ndv": 2,"upper": 58,"lower": 57,"count": 1369,"preSum": 37515 },{ "ndv": 2,"upper": 60,"lower": 59,"count": 1633,"preSum": 38884 },{ "ndv": 2,"upper": 62,"lower": 61,"count": 1466,"preSum": 40517 },{ "ndv": 2,"upper": 64,"lower": 63,"count": 1495,"preSum": 41983 },{ "ndv": 2,"upper": 66,"lower": 65,"count": 1479,"preSum": 43478 },{ "ndv": 2,"upper": 69,"lower": 67,"count": 1645,"preSum": 44957 },{ "ndv": 2,"upper": 71,"lower": 70,"count": 1458,"preSum": 46602 },{ "ndv": 2,"upper": 74,"lower": 72,"count": 1763,"preSum": 48060 },{ "ndv": 2,"upper": 76,"lower": 75,"count": 1315,"preSum": 49823 },{ "ndv": 2,"upper": 78,"lower": 77,"count": 1380,"preSum": 51138 },{ "ndv": 2,"upper": 80,"lower": 79,"count": 1479,"preSum": 52518 },{ "ndv": 2,"upper": 82,"lower": 81,"count": 1348,"preSum": 53997 },{ "ndv": 2,"upper": 85,"lower": 83,"count": 1510,"preSum": 55345 },{ "ndv": 2,"upper": 88,"lower": 86,"count": 1350,"preSum": 56855 },{ "ndv": 2,"upper": 90,"lower": 89,"count": 1447,"preSum": 58205 },{ "ndv": 2,"upper": 93,"lower": 91,"count": 1497,"preSum": 59652 },{ "ndv": 2,"upper": 95,"lower": 94,"count": 1468,"preSum": 61149 },{ "ndv": 2,"upper": 97,"lower": 96,"count": 1534,"preSum": 62617 },{ "ndv": 2,"upper": 99,"lower": 98,"count": 1396,"preSum": 64151 },{ "ndv": 2,"upper": 101,"lower": 100,"count": 1372,"preSum": 65547 },{ "ndv": 2,"upper": 103,"lower": 102,"count": 1315,"preSum": 66919 },{ "ndv": 2,"upper": 105,"lower": 104,"count": 1422,"preSum": 68234 },{ "ndv": 2,"upper": 109,"lower": 106,"count": 1484,"preSum": 69656 },{ "ndv": 2,"upper": 111,"lower": 110,"count": 1562,"preSum": 71140 },{ "ndv": 2,"upper": 113,"lower": 112,"count": 1464,"preSum": 72702 },{ "ndv": 2,"upper": 116,"lower": 114,"count": 1496,"preSum": 74166 },{ "ndv": 2,"upper": 118,"lower": 117,"count": 1498,"preSum": 75662 },{ "ndv": 2,"upper": 120,"lower": 119,"count": 1443,"preSum": 77160 },{ "ndv": 2,"upper": 122,"lower": 121,"count": 1443,"preSum": 78603 },{ "ndv": 2,"upper": 124,"lower": 123,"count": 1482,"preSum": 80046 },{ "ndv": 2,"upper": 126,"lower": 125,"count": 1376,"preSum": 81528 },{ "ndv": 1,"upper": 127,"lower": 127,"count": 623,"preSum": 82904 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_1_un.null_count:
+    0
+  cest_full_table_big.c_tinyint_1_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_4.TOPN:
+    { "countArr": [ 1111,818,807,761,1458,966,937,2201,862,1706,1045,1198,1076,809 ],"valueArr": [ -113,-98,-97,-94,-61,-52,-44,9,19,41,46,86,89,102 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_4.cardinality:
+    256
+  cest_full_table_big.c_tinyint_4.histogram:
+    { "buckets": [ { "ndv": 5,"upper": -124,"lower": -128,"count": 1430,"preSum": 0 },{ "ndv": 4,"upper": -120,"lower": -123,"count": 1406,"preSum": 1430 },{ "ndv": 5,"upper": -115,"lower": -119,"count": 1761,"preSum": 2836 },{ "ndv": 5,"upper": -109,"lower": -114,"count": 1661,"preSum": 4597 },{ "ndv": 5,"upper": -104,"lower": -108,"count": 1529,"preSum": 6258 },{ "ndv": 5,"upper": -99,"lower": -103,"count": 1377,"preSum": 7787 },{ "ndv": 4,"upper": -92,"lower": -96,"count": 1600,"preSum": 9164 },{ "ndv": 5,"upper": -87,"lower": -91,"count": 1548,"preSum": 10764 },{ "ndv": 5,"upper": -82,"lower": -86,"count": 1443,"preSum": 12312 },{ "ndv": 4,"upper": -78,"lower": -81,"count": 1630,"preSum": 13755 },{ "ndv": 5,"upper": -73,"lower": -77,"count": 1380,"preSum": 15385 },{ "ndv": 4,"upper": -69,"lower": -72,"count": 1406,"preSum": 16765 },{ "ndv": 4,"upper": -65,"lower": -68,"count": 1489,"preSum": 18171 },{ "ndv": 5,"upper": -59,"lower": -64,"count": 1433,"preSum": 19660 },{ "ndv": 3,"upper": -56,"lower": -58,"count": 1635,"preSum": 21093 },{ "ndv": 4,"upper": -51,"lower": -55,"count": 1610,"preSum": 22728 },{ "ndv": 4,"upper": -47,"lower": -50,"count": 1469,"preSum": 24338 },{ "ndv": 5,"upper": -41,"lower": -46,"count": 1384,"preSum": 25807 },{ "ndv": 4,"upper": -37,"lower": -40,"count": 1607,"preSum": 27191 },{ "ndv": 5,"upper": -32,"lower": -36,"count": 1602,"preSum": 28798 },{ "ndv": 4,"upper": -28,"lower": -31,"count": 1425,"preSum": 30400 },{ "ndv": 3,"upper": -25,"lower": -27,"count": 1335,"preSum": 31825 },{ "ndv": 4,"upper": -21,"lower": -24,"count": 1507,"preSum": 33160 },{ "ndv": 4,"upper": -17,"lower": -20,"count": 1564,"preSum": 34667 },{ "ndv": 4,"upper": -13,"lower": -16,"count": 1579,"preSum": 36231 },{ "ndv": 5,"upper": -8,"lower": -12,"count": 1555,"preSum": 37810 },{ "ndv": 4,"upper": -4,"lower": -7,"count": 1426,"preSum": 39365 },{ "ndv": 3,"upper": -1,"lower": -3,"count": 1320,"preSum": 40791 },{ "ndv": 5,"upper": 4,"lower": 0,"count": 1432,"preSum": 42111 },{ "ndv": 3,"upper": 7,"lower": 5,"count": 1573,"preSum": 43543 },{ "ndv": 4,"upper": 12,"lower": 8,"count": 1420,"preSum": 45116 },{ "ndv": 4,"upper": 16,"lower": 13,"count": 1561,"preSum": 46536 },{ "ndv": 4,"upper": 21,"lower": 17,"count": 1465,"preSum": 48097 },{ "ndv": 5,"upper": 26,"lower": 22,"count": 1478,"preSum": 49562 },{ "ndv": 5,"upper": 31,"lower": 27,"count": 1739,"preSum": 51040 },{ "ndv": 5,"upper": 36,"lower": 32,"count": 1518,"preSum": 52779 },{ "ndv": 4,"upper": 40,"lower": 37,"count": 2007,"preSum": 54297 },{ "ndv": 4,"upper": 45,"lower": 42,"count": 1417,"preSum": 56304 },{ "ndv": 6,"upper": 52,"lower": 47,"count": 1778,"preSum": 57721 },{ "ndv": 4,"upper": 56,"lower": 53,"count": 1584,"preSum": 59499 },{ "ndv": 3,"upper": 59,"lower": 57,"count": 1388,"preSum": 61083 },{ "ndv": 4,"upper": 63,"lower": 60,"count": 1480,"preSum": 62471 },{ "ndv": 4,"upper": 67,"lower": 64,"count": 1529,"preSum": 63951 },{ "ndv": 5,"upper": 72,"lower": 68,"count": 1492,"preSum": 65480 },{ "ndv": 5,"upper": 77,"lower": 73,"count": 1527,"preSum": 66972 },{ "ndv": 5,"upper": 82,"lower": 78,"count": 1571,"preSum": 68499 },{ "ndv": 4,"upper": 87,"lower": 83,"count": 1382,"preSum": 70070 },{ "ndv": 5,"upper": 93,"lower": 88,"count": 1555,"preSum": 71452 },{ "ndv": 4,"upper": 97,"lower": 94,"count": 1477,"preSum": 73007 },{ "ndv": 3,"upper": 100,"lower": 98,"count": 1347,"preSum": 74484 },{ "ndv": 5,"upper": 106,"lower": 101,"count": 1424,"preSum": 75831 },{ "ndv": 4,"upper": 110,"lower": 107,"count": 1348,"preSum": 77255 },{ "ndv": 4,"upper": 114,"lower": 111,"count": 1544,"preSum": 78603 },{ "ndv": 5,"upper": 119,"lower": 115,"count": 1522,"preSum": 80147 },{ "ndv": 4,"upper": 123,"lower": 120,"count": 1504,"preSum": 81669 },{ "ndv": 4,"upper": 127,"lower": 124,"count": 1073,"preSum": 83173 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_4.null_count:
+    0
+  cest_full_table_big.c_tinyint_4.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_4_un.TOPN:
+    { "countArr": [ 3185,1686,1496,4750,2208,1952,1361,11522,1900,6644,2420,3782,2698,1594 ],"valueArr": [ 7,15,17,33,38,42,67,68,73,84,87,107,108,115 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_4_un.cardinality:
+    128
+  cest_full_table_big.c_tinyint_4_un.histogram:
+    { "buckets": [ { "ndv": 3,"upper": 2,"lower": 0,"count": 1463,"preSum": 0 },{ "ndv": 3,"upper": 5,"lower": 3,"count": 940,"preSum": 1463 },{ "ndv": 2,"upper": 8,"lower": 6,"count": 942,"preSum": 2403 },{ "ndv": 3,"upper": 11,"lower": 9,"count": 1123,"preSum": 3345 },{ "ndv": 3,"upper": 14,"lower": 12,"count": 878,"preSum": 4468 },{ "ndv": 3,"upper": 19,"lower": 16,"count": 1035,"preSum": 5346 },{ "ndv": 2,"upper": 21,"lower": 20,"count": 932,"preSum": 6381 },{ "ndv": 3,"upper": 24,"lower": 22,"count": 1455,"preSum": 7313 },{ "ndv": 2,"upper": 26,"lower": 25,"count": 831,"preSum": 8768 },{ "ndv": 3,"upper": 29,"lower": 27,"count": 1069,"preSum": 9599 },{ "ndv": 2,"upper": 31,"lower": 30,"count": 1021,"preSum": 10668 },{ "ndv": 3,"upper": 35,"lower": 32,"count": 1921,"preSum": 11689 },{ "ndv": 1,"upper": 36,"lower": 36,"count": 1103,"preSum": 13610 },{ "ndv": 2,"upper": 39,"lower": 37,"count": 1098,"preSum": 14713 },{ "ndv": 1,"upper": 40,"lower": 40,"count": 980,"preSum": 15811 },{ "ndv": 3,"upper": 44,"lower": 41,"count": 1579,"preSum": 16791 },{ "ndv": 3,"upper": 47,"lower": 45,"count": 964,"preSum": 18370 },{ "ndv": 2,"upper": 49,"lower": 48,"count": 947,"preSum": 19334 },{ "ndv": 2,"upper": 51,"lower": 50,"count": 1690,"preSum": 20281 },{ "ndv": 2,"upper": 53,"lower": 52,"count": 1184,"preSum": 21971 },{ "ndv": 2,"upper": 55,"lower": 54,"count": 1049,"preSum": 23155 },{ "ndv": 1,"upper": 56,"lower": 56,"count": 878,"preSum": 24204 },{ "ndv": 3,"upper": 59,"lower": 57,"count": 1371,"preSum": 25082 },{ "ndv": 3,"upper": 62,"lower": 60,"count": 1028,"preSum": 26453 },{ "ndv": 2,"upper": 64,"lower": 63,"count": 980,"preSum": 27481 },{ "ndv": 2,"upper": 66,"lower": 65,"count": 908,"preSum": 28461 },{ "ndv": 3,"upper": 71,"lower": 69,"count": 1233,"preSum": 29369 },{ "ndv": 1,"upper": 72,"lower": 72,"count": 1055,"preSum": 30602 },{ "ndv": 2,"upper": 75,"lower": 74,"count": 996,"preSum": 31657 },{ "ndv": 3,"upper": 78,"lower": 76,"count": 961,"preSum": 32653 },{ "ndv": 2,"upper": 80,"lower": 79,"count": 898,"preSum": 33614 },{ "ndv": 3,"upper": 83,"lower": 81,"count": 1518,"preSum": 34512 },{ "ndv": 3,"upper": 88,"lower": 85,"count": 986,"preSum": 36030 },{ "ndv": 2,"upper": 90,"lower": 89,"count": 896,"preSum": 37016 },{ "ndv": 2,"upper": 92,"lower": 91,"count": 1576,"preSum": 37912 },{ "ndv": 2,"upper": 94,"lower": 93,"count": 1056,"preSum": 39488 },{ "ndv": 3,"upper": 97,"lower": 95,"count": 1387,"preSum": 40544 },{ "ndv": 3,"upper": 100,"lower": 98,"count": 852,"preSum": 41931 },{ "ndv": 3,"upper": 103,"lower": 101,"count": 969,"preSum": 42783 },{ "ndv": 2,"upper": 105,"lower": 104,"count": 837,"preSum": 43752 },{ "ndv": 3,"upper": 110,"lower": 106,"count": 1287,"preSum": 44589 },{ "ndv": 2,"upper": 112,"lower": 111,"count": 908,"preSum": 45876 },{ "ndv": 2,"upper": 114,"lower": 113,"count": 1458,"preSum": 46784 },{ "ndv": 3,"upper": 118,"lower": 116,"count": 1096,"preSum": 48242 },{ "ndv": 2,"upper": 120,"lower": 119,"count": 929,"preSum": 49338 },{ "ndv": 3,"upper": 123,"lower": 121,"count": 1072,"preSum": 50267 },{ "ndv": 2,"upper": 125,"lower": 124,"count": 1005,"preSum": 51339 },{ "ndv": 2,"upper": 127,"lower": 126,"count": 459,"preSum": 52344 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_4_un.null_count:
+    0
+  cest_full_table_big.c_tinyint_4_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_8.TOPN:
+    { "countArr": [ 3252,1478,1402,5391,2091,1799,16518,1620,1123,8182,2234,3954,2767,1265 ],"valueArr": [ -113,-98,-97,-61,-52,-44,9,19,40,41,46,86,89,102 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_8.cardinality:
+    256
+  cest_full_table_big.c_tinyint_8.histogram:
+    { "buckets": [ { "ndv": 6,"upper": -123,"lower": -128,"count": 1180,"preSum": 0 },{ "ndv": 7,"upper": -116,"lower": -122,"count": 831,"preSum": 1180 },{ "ndv": 4,"upper": -111,"lower": -115,"count": 800,"preSum": 2011 },{ "ndv": 6,"upper": -105,"lower": -110,"count": 832,"preSum": 2811 },{ "ndv": 7,"upper": -96,"lower": -104,"count": 987,"preSum": 3643 },{ "ndv": 2,"upper": -94,"lower": -95,"count": 1165,"preSum": 4630 },{ "ndv": 5,"upper": -89,"lower": -93,"count": 798,"preSum": 5795 },{ "ndv": 5,"upper": -84,"lower": -88,"count": 753,"preSum": 6593 },{ "ndv": 5,"upper": -79,"lower": -83,"count": 1021,"preSum": 7346 },{ "ndv": 5,"upper": -74,"lower": -78,"count": 767,"preSum": 8367 },{ "ndv": 5,"upper": -69,"lower": -73,"count": 811,"preSum": 9134 },{ "ndv": 4,"upper": -65,"lower": -68,"count": 911,"preSum": 9945 },{ "ndv": 7,"upper": -57,"lower": -64,"count": 1635,"preSum": 10856 },{ "ndv": 1,"upper": -56,"lower": -56,"count": 786,"preSum": 12491 },{ "ndv": 3,"upper": -53,"lower": -55,"count": 777,"preSum": 13277 },{ "ndv": 5,"upper": -47,"lower": -51,"count": 1211,"preSum": 14054 },{ "ndv": 7,"upper": -39,"lower": -46,"count": 1344,"preSum": 15265 },{ "ndv": 6,"upper": -33,"lower": -38,"count": 750,"preSum": 16609 },{ "ndv": 4,"upper": -29,"lower": -32,"count": 796,"preSum": 17359 },{ "ndv": 4,"upper": -25,"lower": -28,"count": 1379,"preSum": 18155 },{ "ndv": 4,"upper": -21,"lower": -24,"count": 1033,"preSum": 19534 },{ "ndv": 4,"upper": -17,"lower": -20,"count": 891,"preSum": 20567 },{ "ndv": 3,"upper": -14,"lower": -16,"count": 783,"preSum": 21458 },{ "ndv": 5,"upper": -9,"lower": -13,"count": 965,"preSum": 22241 },{ "ndv": 5,"upper": -4,"lower": -8,"count": 813,"preSum": 23206 },{ "ndv": 3,"upper": -1,"lower": -3,"count": 951,"preSum": 24019 },{ "ndv": 6,"upper": 5,"lower": 0,"count": 938,"preSum": 24970 },{ "ndv": 2,"upper": 7,"lower": 6,"count": 1259,"preSum": 25908 },{ "ndv": 6,"upper": 14,"lower": 8,"count": 766,"preSum": 27167 },{ "ndv": 2,"upper": 16,"lower": 15,"count": 1125,"preSum": 27933 },{ "ndv": 4,"upper": 21,"lower": 17,"count": 797,"preSum": 29058 },{ "ndv": 6,"upper": 27,"lower": 22,"count": 759,"preSum": 29855 },{ "ndv": 5,"upper": 32,"lower": 28,"count": 895,"preSum": 30614 },{ "ndv": 6,"upper": 38,"lower": 33,"count": 1204,"preSum": 31509 },{ "ndv": 5,"upper": 45,"lower": 39,"count": 783,"preSum": 32713 },{ "ndv": 6,"upper": 52,"lower": 47,"count": 817,"preSum": 33496 },{ "ndv": 4,"upper": 56,"lower": 53,"count": 942,"preSum": 34313 },{ "ndv": 1,"upper": 57,"lower": 57,"count": 964,"preSum": 35255 },{ "ndv": 3,"upper": 60,"lower": 58,"count": 750,"preSum": 36219 },{ "ndv": 6,"upper": 66,"lower": 61,"count": 1047,"preSum": 36969 },{ "ndv": 6,"upper": 72,"lower": 67,"count": 768,"preSum": 38016 },{ "ndv": 6,"upper": 78,"lower": 73,"count": 758,"preSum": 38784 },{ "ndv": 6,"upper": 84,"lower": 79,"count": 813,"preSum": 39542 },{ "ndv": 6,"upper": 92,"lower": 85,"count": 761,"preSum": 40355 },{ "ndv": 3,"upper": 95,"lower": 93,"count": 763,"preSum": 41116 },{ "ndv": 5,"upper": 100,"lower": 96,"count": 1244,"preSum": 41879 },{ "ndv": 6,"upper": 107,"lower": 101,"count": 858,"preSum": 43123 },{ "ndv": 5,"upper": 112,"lower": 108,"count": 854,"preSum": 43981 },{ "ndv": 6,"upper": 118,"lower": 113,"count": 820,"preSum": 44835 },{ "ndv": 4,"upper": 122,"lower": 119,"count": 780,"preSum": 45655 },{ "ndv": 5,"upper": 127,"lower": 123,"count": 490,"preSum": 46435 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_8.null_count:
+    0
+  cest_full_table_big.c_tinyint_8.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_8_un.TOPN:
+    { "countArr": [ 3936,1637,1197,7353,2259,1892,1157,27104,1742,11584,2613,5053,3087,1355 ],"valueArr": [ 7,15,17,33,38,42,67,68,73,84,87,107,108,115 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_8_un.cardinality:
+    128
+  cest_full_table_big.c_tinyint_8_un.histogram:
+    { "buckets": [ { "ndv": 3,"upper": 2,"lower": 0,"count": 778,"preSum": 0 },{ "ndv": 4,"upper": 6,"lower": 3,"count": 701,"preSum": 778 },{ "ndv": 4,"upper": 11,"lower": 8,"count": 675,"preSum": 1479 },{ "ndv": 4,"upper": 16,"lower": 12,"count": 537,"preSum": 2154 },{ "ndv": 3,"upper": 20,"lower": 18,"count": 523,"preSum": 2691 },{ "ndv": 4,"upper": 24,"lower": 21,"count": 912,"preSum": 3214 },{ "ndv": 2,"upper": 26,"lower": 25,"count": 462,"preSum": 4126 },{ "ndv": 3,"upper": 29,"lower": 27,"count": 448,"preSum": 4588 },{ "ndv": 2,"upper": 31,"lower": 30,"count": 519,"preSum": 5036 },{ "ndv": 3,"upper": 35,"lower": 32,"count": 1324,"preSum": 5555 },{ "ndv": 1,"upper": 36,"lower": 36,"count": 736,"preSum": 6879 },{ "ndv": 1,"upper": 37,"lower": 37,"count": 495,"preSum": 7615 },{ "ndv": 2,"upper": 40,"lower": 39,"count": 751,"preSum": 8110 },{ "ndv": 3,"upper": 44,"lower": 41,"count": 970,"preSum": 8861 },{ "ndv": 4,"upper": 48,"lower": 45,"count": 540,"preSum": 9831 },{ "ndv": 2,"upper": 50,"lower": 49,"count": 480,"preSum": 10371 },{ "ndv": 1,"upper": 51,"lower": 51,"count": 906,"preSum": 10851 },{ "ndv": 2,"upper": 53,"lower": 52,"count": 702,"preSum": 11757 },{ "ndv": 2,"upper": 55,"lower": 54,"count": 596,"preSum": 12459 },{ "ndv": 1,"upper": 56,"lower": 56,"count": 608,"preSum": 13055 },{ "ndv": 3,"upper": 59,"lower": 57,"count": 725,"preSum": 13663 },{ "ndv": 3,"upper": 62,"lower": 60,"count": 457,"preSum": 14388 },{ "ndv": 1,"upper": 63,"lower": 63,"count": 470,"preSum": 14845 },{ "ndv": 3,"upper": 66,"lower": 64,"count": 615,"preSum": 15315 },{ "ndv": 3,"upper": 71,"lower": 69,"count": 511,"preSum": 15930 },{ "ndv": 1,"upper": 72,"lower": 72,"count": 851,"preSum": 16441 },{ "ndv": 2,"upper": 75,"lower": 74,"count": 527,"preSum": 17292 },{ "ndv": 4,"upper": 79,"lower": 76,"count": 607,"preSum": 17819 },{ "ndv": 4,"upper": 83,"lower": 80,"count": 1114,"preSum": 18426 },{ "ndv": 3,"upper": 88,"lower": 85,"count": 460,"preSum": 19540 },{ "ndv": 2,"upper": 90,"lower": 89,"count": 459,"preSum": 20000 },{ "ndv": 2,"upper": 92,"lower": 91,"count": 1121,"preSum": 20459 },{ "ndv": 2,"upper": 94,"lower": 93,"count": 543,"preSum": 21580 },{ "ndv": 3,"upper": 97,"lower": 95,"count": 720,"preSum": 22123 },{ "ndv": 4,"upper": 101,"lower": 98,"count": 581,"preSum": 22843 },{ "ndv": 3,"upper": 104,"lower": 102,"count": 478,"preSum": 23424 },{ "ndv": 3,"upper": 109,"lower": 105,"count": 496,"preSum": 23902 },{ "ndv": 2,"upper": 111,"lower": 110,"count": 563,"preSum": 24398 },{ "ndv": 2,"upper": 113,"lower": 112,"count": 464,"preSum": 24961 },{ "ndv": 1,"upper": 114,"lower": 114,"count": 504,"preSum": 25425 },{ "ndv": 3,"upper": 118,"lower": 116,"count": 483,"preSum": 25929 },{ "ndv": 2,"upper": 120,"lower": 119,"count": 468,"preSum": 26412 },{ "ndv": 4,"upper": 124,"lower": 121,"count": 790,"preSum": 26880 },{ "ndv": 3,"upper": 127,"lower": 125,"count": 362,"preSum": 27670 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_8_un.null_count:
+    0
+  cest_full_table_big.c_tinyint_8_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_varchar.TOPN:
+    { "countArr": [ 2433,1066,969,848,715,3308,1257,1527,4703,640,44010,7391,1950,14569 ],"valueArr": [ "0abdb","150e3","322e0ed","5ee951d192","75","817a071","8b","8b4283","8f4b82","920e8","ae093","b","bd4663a26","d9" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_varchar.cardinality:
+    16380
+  cest_full_table_big.c_varchar.histogram:
+    { "buckets": [ { "ndv": 6,"upper": "00a","lower": "0","count": 559,"preSum": 0 },{ "ndv": 52,"upper": "074b69539b","lower": "00c85b4","count": 231,"preSum": 559 },{ "ndv": 47,"upper": "0dc7e251","lower": "078e97e","count": 229,"preSum": 790 },{ "ndv": 45,"upper": "13b","lower": "0dceae5","count": 229,"preSum": 1019 },{ "ndv": 53,"upper": "1b00dc6b0","lower": "13c39952","count": 229,"preSum": 1248 },{ "ndv": 31,"upper": "1fd95","lower": "1b05b203c","count": 682,"preSum": 1477 },{ "ndv": 31,"upper": "2381ac2e","lower": "2","count": 231,"preSum": 2159 },{ "ndv": 20,"upper": "26480","lower": "23a039a182","count": 229,"preSum": 2390 },{ "ndv": 22,"upper": "29","lower": "266","count": 272,"preSum": 2619 },{ "ndv": 7,"upper": "2a33cd62","lower": "290","count": 374,"preSum": 2891 },{ "ndv": 21,"upper": "2c5f8","lower": "2a38b3e6","count": 295,"preSum": 3265 },{ "ndv": 39,"upper": "3100e1bed","lower": "2c881705c0","count": 232,"preSum": 3560 },{ "ndv": 104,"upper": "3e7b006b66","lower": "310e28","count": 236,"preSum": 3792 },{ "ndv": 38,"upper": "439d9","lower": "3f065cb89","count": 382,"preSum": 4028 },{ "ndv": 40,"upper": "4a9e0d0","lower": "43bebbfaa","count": 321,"preSum": 4410 },{ "ndv": 79,"upper": "55d20f80","lower": "4acf6","count": 248,"preSum": 4731 },{ "ndv": 40,"upper": "5bd6f342c","lower": "56854ff5bf","count": 609,"preSum": 4979 },{ "ndv": 36,"upper": "61","lower": "5c299","count": 231,"preSum": 5588 },{ "ndv": 48,"upper": "68718fec4","lower": "6136af56de","count": 229,"preSum": 5819 },{ "ndv": 64,"upper": "7","lower": "687d3","count": 237,"preSum": 6048 },{ "ndv": 40,"upper": "7645e370","lower": "7001a8263","count": 364,"preSum": 6285 },{ "ndv": 33,"upper": "7ad","lower": "7667f5ffef","count": 239,"preSum": 6649 },{ "ndv": 42,"upper": "7fc5796","lower": "7adf2","count": 233,"preSum": 6888 },{ "ndv": 37,"upper": "8526f8","lower": "7fe486c70","count": 229,"preSum": 7121 },{ "ndv": 31,"upper": "88bc","lower": "857","count": 395,"preSum": 7350 },{ "ndv": 46,"upper": "8f942aac4d","lower": "88d29a56","count": 229,"preSum": 7745 },{ "ndv": 30,"upper": "93a4db","lower": "8fab04","count": 356,"preSum": 7974 },{ "ndv": 27,"upper": "97e","lower": "93c76a5e","count": 528,"preSum": 8330 },{ "ndv": 32,"upper": "9bd3b47ab0","lower": "97e90","count": 233,"preSum": 8858 },{ "ndv": 51,"upper": "a3d0c","lower": "9be21b","count": 280,"preSum": 9091 },{ "ndv": 31,"upper": "a862","lower": "a4373237","count": 280,"preSum": 9371 },{ "ndv": 44,"upper": "af454e5e2","lower": "a87355","count": 229,"preSum": 9651 },{ "ndv": 24,"upper": "b4866c38cf","lower": "af6f6396","count": 601,"preSum": 9880 },{ "ndv": 63,"upper": "bcdcc4413","lower": "b497d9","count": 231,"preSum": 10481 },{ "ndv": 43,"upper": "c333418","lower": "bce","count": 247,"preSum": 10712 },{ "ndv": 13,"upper": "c69","lower": "c38d","count": 345,"preSum": 10959 },{ "ndv": 32,"upper": "cb1050e6","lower": "c69b9b575b","count": 335,"preSum": 11304 },{ "ndv": 38,"upper": "cf539a","lower": "cb11fa08","count": 231,"preSum": 11639 },{ "ndv": 17,"upper": "d1c8d334c9","lower": "cf5d486","count": 550,"preSum": 11870 },{ "ndv": 56,"upper": "d992","lower": "d1cecee0ab","count": 272,"preSum": 12420 },{ "ndv": 84,"upper": "e3d64","lower": "d9ecd163d","count": 229,"preSum": 12692 },{ "ndv": 36,"upper": "e98c","lower": "e3e391eee","count": 240,"preSum": 12921 },{ "ndv": 64,"upper": "f3","lower": "e9dd622b","count": 230,"preSum": 13161 },{ "ndv": 13,"upper": "f4ead0","lower": "f33c3","count": 331,"preSum": 13391 },{ "ndv": 32,"upper": "f95f6364e","lower": "f4f7b","count": 330,"preSum": 13722 },{ "ndv": 28,"upper": "fe2","lower": "f9aa89","count": 257,"preSum": 14052 },{ "ndv": 6,"upper": "ffb6b2558","lower": "fe31162","count": 304,"preSum": 14309 },{ "ndv": 2,"upper": "fff96","lower": "fff2","count": 2,"preSum": 14613 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_varchar.null_count:
+    0
+  cest_full_table_big.c_varchar.sample_rate:
+    0.010943651
+  cest_full_table_big.c_year.TOPN:
+    { "countArr": [ 100001 ],"valueArr": [ 2022 ],"type": "Year","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_year.cardinality:
+    1
+  cest_full_table_big.c_year.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "Year","sampleRate": 0.90062594 }
+  cest_full_table_big.c_year.null_count:
+    0
+  cest_full_table_big.c_year.sample_rate:
+    0.010943651
+  cest_full_table_big.c_year_4.TOPN:
+    { "countArr": [ 100001 ],"valueArr": [ 2022 ],"type": "Year","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_year_4.cardinality:
+    1
+  cest_full_table_big.c_year_4.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "Year","sampleRate": 0.90062594 }
+  cest_full_table_big.c_year_4.null_count:
+    0
+  cest_full_table_big.c_year_4.sample_rate:
+    0.010943651
+  cest_full_table_big.id.TOPN:
+    null
+  cest_full_table_big.id.cardinality:
+    6134006
+  cest_full_table_big.id.histogram:
+    { "buckets": [ { "ndv": 1563,"upper": 171092,"lower": 1378,"count": 1563,"preSum": 0 },{ "ndv": 1563,"upper": 340379,"lower": 171124,"count": 1563,"preSum": 1563 },{ "ndv": 1563,"upper": 503266,"lower": 340386,"count": 1563,"preSum": 3126 },{ "ndv": 1563,"upper": 646819,"lower": 503267,"count": 1563,"preSum": 4689 },{ "ndv": 1563,"upper": 821446,"lower": 646934,"count": 1563,"preSum": 6252 },{ "ndv": 1563,"upper": 991470,"lower": 821457,"count": 1563,"preSum": 7815 },{ "ndv": 1563,"upper": 1152808,"lower": 991471,"count": 1563,"preSum": 9378 },{ "ndv": 1563,"upper": 1305101,"lower": 1152847,"count": 1563,"preSum": 10941 },{ "ndv": 1563,"upper": 1458965,"lower": 1305134,"count": 1563,"preSum": 12504 },{ "ndv": 1563,"upper": 1633026,"lower": 1458975,"count": 1563,"preSum": 14067 },{ "ndv": 1563,"upper": 1804056,"lower": 1633076,"count": 1563,"preSum": 15630 },{ "ndv": 1563,"upper": 1952241,"lower": 1804287,"count": 1563,"preSum": 17193 },{ "ndv": 1563,"upper": 2092635,"lower": 1952265,"count": 1563,"preSum": 18756 },{ "ndv": 1563,"upper": 2250240,"lower": 2092717,"count": 1563,"preSum": 20319 },{ "ndv": 1563,"upper": 2383628,"lower": 2250254,"count": 1563,"preSum": 21882 },{ "ndv": 1563,"upper": 2543830,"lower": 2383630,"count": 1563,"preSum": 23445 },{ "ndv": 1563,"upper": 2713201,"lower": 2543858,"count": 1563,"preSum": 25008 },{ "ndv": 1563,"upper": 2853899,"lower": 2713231,"count": 1563,"preSum": 26571 },{ "ndv": 1563,"upper": 2993810,"lower": 2853930,"count": 1563,"preSum": 28134 },{ "ndv": 1563,"upper": 3137124,"lower": 2993823,"count": 1563,"preSum": 29697 },{ "ndv": 1563,"upper": 3297101,"lower": 3137167,"count": 1563,"preSum": 31260 },{ "ndv": 1563,"upper": 3418225,"lower": 3297133,"count": 1563,"preSum": 32823 },{ "ndv": 1563,"upper": 3575122,"lower": 3418228,"count": 1563,"preSum": 34386 },{ "ndv": 1563,"upper": 3724748,"lower": 3575138,"count": 1563,"preSum": 35949 },{ "ndv": 1563,"upper": 3902433,"lower": 3724751,"count": 1563,"preSum": 37512 },{ "ndv": 1563,"upper": 4045654,"lower": 3902434,"count": 1563,"preSum": 39075 },{ "ndv": 1563,"upper": 4222180,"lower": 4045684,"count": 1563,"preSum": 40638 },{ "ndv": 1563,"upper": 4358869,"lower": 4222182,"count": 1563,"preSum": 42201 },{ "ndv": 1563,"upper": 4520898,"lower": 4358898,"count": 1563,"preSum": 43764 },{ "ndv": 1563,"upper": 4696584,"lower": 4520899,"count": 1563,"preSum": 45327 },{ "ndv": 1563,"upper": 4861215,"lower": 4696931,"count": 1563,"preSum": 46890 },{ "ndv": 1563,"upper": 5012824,"lower": 4861231,"count": 1563,"preSum": 48453 },{ "ndv": 1563,"upper": 5195721,"lower": 5012837,"count": 1563,"preSum": 50016 },{ "ndv": 1563,"upper": 5363451,"lower": 5195722,"count": 1563,"preSum": 51579 },{ "ndv": 1563,"upper": 5516861,"lower": 5363481,"count": 1563,"preSum": 53142 },{ "ndv": 1563,"upper": 5667553,"lower": 5516888,"count": 1563,"preSum": 54705 },{ "ndv": 1563,"upper": 5820559,"lower": 5667554,"count": 1563,"preSum": 56268 },{ "ndv": 1563,"upper": 5958760,"lower": 5820606,"count": 1563,"preSum": 57831 },{ "ndv": 1563,"upper": 6095618,"lower": 5958792,"count": 1563,"preSum": 59394 },{ "ndv": 1563,"upper": 6271159,"lower": 6095652,"count": 1563,"preSum": 60957 },{ "ndv": 1563,"upper": 6425242,"lower": 6271175,"count": 1563,"preSum": 62520 },{ "ndv": 1563,"upper": 6570405,"lower": 6425259,"count": 1563,"preSum": 64083 },{ "ndv": 1563,"upper": 6701022,"lower": 6570409,"count": 1563,"preSum": 65646 },{ "ndv": 1563,"upper": 6864180,"lower": 6701054,"count": 1563,"preSum": 67209 },{ "ndv": 1563,"upper": 6994513,"lower": 6864181,"count": 1563,"preSum": 68772 },{ "ndv": 1563,"upper": 7140428,"lower": 6994537,"count": 1563,"preSum": 70335 },{ "ndv": 1563,"upper": 7302078,"lower": 7140438,"count": 1563,"preSum": 71898 },{ "ndv": 1563,"upper": 7480547,"lower": 7302154,"count": 1563,"preSum": 73461 },{ "ndv": 1563,"upper": 7649156,"lower": 7480567,"count": 1563,"preSum": 75024 },{ "ndv": 1563,"upper": 7807790,"lower": 7649174,"count": 1563,"preSum": 76587 },{ "ndv": 1563,"upper": 7945345,"lower": 7807800,"count": 1563,"preSum": 78150 },{ "ndv": 1563,"upper": 8096420,"lower": 7945380,"count": 1563,"preSum": 79713 },{ "ndv": 1563,"upper": 8255887,"lower": 8096427,"count": 1563,"preSum": 81276 },{ "ndv": 1563,"upper": 8408097,"lower": 8255893,"count": 1563,"preSum": 82839 },{ "ndv": 1563,"upper": 8587830,"lower": 8408141,"count": 1563,"preSum": 84402 },{ "ndv": 1563,"upper": 8745625,"lower": 8587866,"count": 1563,"preSum": 85965 },{ "ndv": 1563,"upper": 8887410,"lower": 8745629,"count": 1563,"preSum": 87528 },{ "ndv": 1563,"upper": 9058990,"lower": 8887431,"count": 1563,"preSum": 89091 },{ "ndv": 1563,"upper": 9221690,"lower": 9059077,"count": 1563,"preSum": 90654 },{ "ndv": 1563,"upper": 9370975,"lower": 9221710,"count": 1563,"preSum": 92217 },{ "ndv": 1563,"upper": 9522875,"lower": 9370981,"count": 1563,"preSum": 93780 },{ "ndv": 1563,"upper": 9688324,"lower": 9522917,"count": 1563,"preSum": 95343 },{ "ndv": 1563,"upper": 9856912,"lower": 9688333,"count": 1563,"preSum": 96906 },{ "ndv": 1532,"upper": 9998440,"lower": 9859678,"count": 1532,"preSum": 98469 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.id.null_count:
+    0
+  cest_full_table_big.id.sample_rate:
+    0.010943651
+  cest_full_table_big.c_bigint_1.composite_cardinality:
+    100465
+  cest_full_table_big.c_bigint_64.composite_cardinality:
+    100465
+  cest_full_table_big.c_bigint_64_un.composite_cardinality:
+    99782
+  cest_full_table_big.c_bigint_64_un,c_int_1.composite_cardinality:
+    9523658
+  cest_full_table_big.c_bit_32,c_bit_64.composite_cardinality:
+    9427873
+  cest_full_table_big.c_bit_32,c_bit_64,c_bit_8.composite_cardinality:
+    10061980
+  cest_full_table_big.c_bit_64.composite_cardinality:
+    99782
+  cest_full_table_big.c_char.composite_cardinality:
+    100308
+  cest_full_table_big.c_date.composite_cardinality:
+    368
+  cest_full_table_big.c_date,c_datetime_1.composite_cardinality:
+    100732
+  cest_full_table_big.c_date,c_datetime_1,c_timestamp.composite_cardinality:
+    9912587
+  cest_full_table_big.c_datetime.composite_cardinality:
+    99678
+  cest_full_table_big.c_datetime_1.composite_cardinality:
+    100498
+  cest_full_table_big.c_datetime_3.composite_cardinality:
+    100064
+  cest_full_table_big.c_datetime_3,c_datetime_6.composite_cardinality:
+    99597
+  cest_full_table_big.c_datetime_6.composite_cardinality:
+    99561
+  cest_full_table_big.c_decimal.composite_cardinality:
+    99283
+  cest_full_table_big.c_decimal_pr.composite_cardinality:
+    102195
+  cest_full_table_big.c_double.composite_cardinality:
+    100276
+  cest_full_table_big.c_double_pr.composite_cardinality:
+    100257
+  cest_full_table_big.c_double_un.composite_cardinality:
+    100073
+  cest_full_table_big.c_enum.composite_cardinality:
+    3
+  cest_full_table_big.c_float.composite_cardinality:
+    100638
+  cest_full_table_big.c_float_pr.composite_cardinality:
+    100680
+  cest_full_table_big.c_float_un.composite_cardinality:
+    100964
+  cest_full_table_big.c_int_1.composite_cardinality:
+    100711
+  cest_full_table_big.c_int_32.composite_cardinality:
+    100711
+  cest_full_table_big.c_int_32_un.composite_cardinality:
+    95894
+  cest_full_table_big.c_mediumint_1.composite_cardinality:
+    99264
+  cest_full_table_big.c_mediumint_24.composite_cardinality:
+    99264
+  cest_full_table_big.c_mediumint_24_un.composite_cardinality:
+    99154
+  cest_full_table_big.c_smallint_1.composite_cardinality:
+    44076
+  cest_full_table_big.c_smallint_16.composite_cardinality:
+    23278
+  cest_full_table_big.c_smallint_16_un.composite_cardinality:
+    9292
+  cest_full_table_big.c_text.composite_cardinality:
+    98172
+  cest_full_table_big.c_text_long.composite_cardinality:
+    98172
+  cest_full_table_big.c_text_medium.composite_cardinality:
+    98172
+  cest_full_table_big.c_text_tiny.composite_cardinality:
+    98172
+  cest_full_table_big.c_time.composite_cardinality:
+    59385
+  cest_full_table_big.c_timestamp.composite_cardinality:
+    99678
+  cest_full_table_big.c_timestamp_1.composite_cardinality:
+    100498
+  cest_full_table_big.c_timestamp_3.composite_cardinality:
+    100064
+  cest_full_table_big.c_timestamp_6.composite_cardinality:
+    99561
+  cest_full_table_big.c_time_1.composite_cardinality:
+    59502
+  cest_full_table_big.c_time_3.composite_cardinality:
+    59069
+  cest_full_table_big.c_time_6.composite_cardinality:
+    60387
+  cest_full_table_big.c_tinyint_1.composite_cardinality:
+    254
+  cest_full_table_big.c_tinyint_1_un.composite_cardinality:
+    126
+  cest_full_table_big.c_tinyint_4.composite_cardinality:
+    254
+  cest_full_table_big.c_tinyint_4_un.composite_cardinality:
+    126
+  cest_full_table_big.c_tinyint_8.composite_cardinality:
+    254
+  cest_full_table_big.c_tinyint_8_un.composite_cardinality:
+    126
+  cest_full_table_big.c_varchar.composite_cardinality:
+    25009
+  cest_full_table_big.c_year.composite_cardinality:
+    1
+  cest_full_table_big.c_year_4.composite_cardinality:
+    1
+  cest_full_table_big.id.composite_cardinality:
+    10080526
+CONFIG:
+  ENABLE_AUTO_FORCE_INDEX:
+    false
+  HOT_GSI_EVOLUTION_THRESHOLD:
+    5000
+  defaltxxAPPName.isNew:
+    true
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionDisableEvolutionTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionDisableEvolutionTest.yml
new file mode 100644
index 000000000..c58921e3e
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionDisableEvolutionTest.yml
@@ -0,0 +1,22 @@
+SQL:
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' and c_bigint_64_un = 14 and c_int_32=12 and c_tinyint_1=1
+    plan: |
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_tinyint_1_idx[p3]", sql="select `id`, `c_tinyint_1` from `c_tinyint_1_idx` as `c_tinyint_1_idx` force index(`i_c_tinyint_1_id`) where (`c_tinyint_1` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_timestamp_3` = ?) and (`c_bigint_64_un` = ?) and (`c_int_32` = ?) and (`c_tinyint_1` = ?) and (`id` in (...)))")
+DDL:
+  cest_full_table_big:
+    CREATE TABLE `cest_full_table_big` (   `c_tinyint_8` tinyint(8) DEFAULT NULL,   `c_datetime_6` datetime(6) DEFAULT NULL,   `c_mediumint_24` mediumint(24) DEFAULT NULL,   `c_blob_medium` mediumblob,   `c_text_tiny` tinytext,   `c_time_3` time(3) DEFAULT NULL,   `c_int_32_un` int(32) UNSIGNED DEFAULT NULL,   `c_year` year(4) DEFAULT NULL,   `c_tinyint_4_un` tinyint(4) UNSIGNED DEFAULT NULL,   `c_time_1` time(1) DEFAULT NULL,   `c_text_medium` mediumtext,   `c_year_4` year(4) DEFAULT NULL,   `c_text` text,   `c_datetime` datetime DEFAULT NULL,   `c_tinyint_8_un` tinyint(8) UNSIGNED DEFAULT NULL,   `c_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,   `c_int_1` int(1) DEFAULT NULL,   `c_int_32` int(32) NOT NULL DEFAULT '0' COMMENT 'For multi pk.',   `c_double_un` double(10, 3) UNSIGNED DEFAULT NULL,   `id` bigint(20) NOT NULL AUTO_INCREMENT,   `c_mediumint_24_un` mediumint(24) UNSIGNED DEFAULT NULL,   `c_smallint_16_un` smallint(16) UNSIGNED DEFAULT NULL,   `c_bigint_1` bigint(1) DEFAULT NULL,   `c_blob` blob,   `c_text_long` longtext,   `c_timestamp_1` timestamp(1) NOT NULL DEFAULT '1999-12-31 12:00:00.0',   `c_blob_long` longblob,   `c_varchar` varchar(10) DEFAULT NULL,   `c_datetime_1` datetime(1) DEFAULT NULL,   `c_bit_8` bit(8) DEFAULT NULL,   `c_double_pr` double(10, 3) DEFAULT NULL,   `c_time_6` time(6) DEFAULT NULL,   `c_char` char(10) DEFAULT NULL,   `c_smallint_16` smallint(16) DEFAULT NULL,   `c_float_pr` float(10, 3) DEFAULT NULL,   `c_float_un` float(10, 3) UNSIGNED DEFAULT NULL,   `c_decimal` decimal(10, 0) DEFAULT NULL,   `c_timestamp_3` timestamp(3) NOT NULL DEFAULT '1999-12-31 12:00:00.000',   `c_bigint_64` bigint(64) DEFAULT NULL,   `c_blob_tiny` tinyblob,   `c_tinyint_1_un` tinyint(1) UNSIGNED DEFAULT NULL,   `c_decimal_pr` decimal(65, 30) DEFAULT NULL,   `c_enum` enum('a', 'b', 'c') DEFAULT NULL,   `c_bigint_64_un` bigint(64) UNSIGNED DEFAULT NULL,   `c_binary` binary(10) DEFAULT NULL,   `c_time` time DEFAULT NULL,   `c_float` float DEFAULT NULL,   `c_timestamp_6` timestamp(6) NOT NULL DEFAULT '1999-12-31 12:00:00.000000',   `c_bit_64` bit(64) DEFAULT NULL,   `c_date` date DEFAULT NULL COMMENT 'date',   `c_bit_32` bit(32) DEFAULT NULL,   `c_tinyint_4` tinyint(4) DEFAULT NULL,   `c_bit_16` bit(16) DEFAULT NULL,   `c_bit_1` bit(1) DEFAULT NULL,   `c_double` double DEFAULT NULL,   `c_datetime_3` datetime(3) DEFAULT NULL,   `c_mediumint_1` mediumint(1) DEFAULT NULL,   `c_varbinary` varbinary(10) DEFAULT NULL,   `c_smallint_1` smallint(1) DEFAULT NULL,   `c_tinyint_1` tinyint(1) DEFAULT NULL,   PRIMARY KEY (`id`),   GLOBAL INDEX  `c_bigint_1_idx` (`c_bigint_1`, `id`)     PARTITION BY KEY(`c_bigint_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`, `id`)     PARTITION BY KEY(`c_bigint_64_un`,`c_int_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_datetime_idx` (`c_datetime`, `id`)     PARTITION BY KEY(`c_datetime`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_int_32_idx` (`c_int_32`, `id`)     PARTITION BY KEY(`c_int_32`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_mediumint_24_idx` (`c_mediumint_24`, `id`)     PARTITION BY KEY(`c_mediumint_24`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_timestamp_1_idx` (`c_timestamp_1`, `id`) COVERING (`c_varchar`)     PARTITION BY KEY(`c_timestamp_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_timestamp_3_idx` (`c_timestamp_3`, `id`) COVERING (`c_datetime`, `c_text_long`, `c_double`)     PARTITION BY KEY(`c_timestamp_3`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_timestamp_6_idx` (`c_timestamp_6`, `id`) COVERING (`c_text`, `c_text_long`)     PARTITION BY KEY(`c_timestamp_6`,`id`)     PARTITIONS 4,   GLOBAL INDEX  `c_tinyint_1_idx` (`c_tinyint_1`, `id`)     PARTITION BY KEY(`c_tinyint_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_tinyint_1_un_idx` (`c_tinyint_1_un`, `id`)     PARTITION BY KEY(`c_tinyint_1_un`,`id`)     PARTITIONS 32,   GLOBAL INDEX`c_tinyint_4_idx` (`c_tinyint_4`, `id`)     PARTITION BY KEY(`c_tinyint_4`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_tinyint_8_idx` (`c_tinyint_8`, `id`)     PARTITION BY KEY(`c_tinyint_8`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_tinyint_8_un_idx` (`c_tinyint_8_un`, `id`)     PARTITION BY KEY(`c_tinyint_8_un`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_varchar_idx` (`c_varchar`, `id`)     PARTITION BY KEY(`c_varchar`,`id`)     PARTITIONS 32,   LOCAL KEY `_local_c_varchar_idx` (`c_varchar`),   LOCAL KEY `_local_c_int_32_idx` (`c_int_32`),   LOCAL KEY `_local_c_datetime_idx` (`c_datetime`),   LOCAL KEY `_local_c_tinyint_1_idx` (`c_tinyint_1`),   LOCAL KEY `_local_c_tinyint_1_un_idx` (`c_tinyint_1_un`),   LOCAL KEY `_local_c_tinyint_8_idx` (`c_tinyint_8`),   LOCAL KEY `_local_c_bigint_1_idx` (`c_bigint_1`),   LOCAL KEY `_local_c_tinyint_8_un_idx` (`c_tinyint_8_un`),   LOCAL KEY `_local_c_mediumint_24_idx` (`c_mediumint_24`),   LOCAL KEY `_local_c_tinyint_4_idx` (`c_tinyint_4`),   LOCAL KEY `c_char_idx` (`c_char`),   LOCAL KEY `c_int_32_un_idx` (`c_int_32_un`),   LOCAL KEY `c_time_idx` (`c_time`),   LOCAL KEY `c_tinyint_4_un_idx` (`c_tinyint_4_un`),   LOCAL KEY `c_smallint_16_idx` (`c_smallint_16`),   LOCAL KEY `c_smallint_16_un_idx` (`c_smallint_16_un`),   LOCAL KEY `c_bigint_64_idx` (`c_bigint_64`),   LOCAL KEY `c_smallint_1_idx` (`c_smallint_1`),   LOCAL KEY `c_mediumint_24_un_idx` (`c_mediumint_24_un`),   LOCAL KEY `c_mediumint_1_idx` (`c_mediumint_1`),   LOCAL KEY `_local_c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`),   LOCAL KEY `c_date_c_datetime_1_c_timestamp_idx` (`c_date`, `c_datetime_1`, `c_timestamp`),   LOCAL KEY `c_datetime_3_c_datetime_6_idx` (`c_datetime_3`, `c_datetime_6`),   LOCAL KEY `c_bit_64_c_bit_32_c_bit_8_idx` (`c_bit_64`, `c_bit_32`, `c_bit_8`),   LOCAL KEY `_local_c_timestamp_1_idx` (`c_timestamp_1`),   LOCAL KEY `_local_c_timestamp_3_idx` (`c_timestamp_3`),   LOCAL KEY `_local_c_timestamp_6_idx` (`c_timestamp_6`) ) ENGINE = InnoDB AUTO_INCREMENT = 9999976 DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS 32
+STATISTICS:
+  cest_full_table_big:
+    10146065
+CONFIG:
+  ENABLE_HOT_GSI_EVOLUTION:
+    true
+  HOT_GSI_EVOLUTION_THRESHOLD:
+    -1
+  defaltxxAPPName.isNew:
+    true
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionTest.yml
new file mode 100644
index 000000000..5d45f3edf
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiEvolutionTest.yml
@@ -0,0 +1,56 @@
+SQL:
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' and c_bigint_64_un = 14 and c_int_32=12 and c_tinyint_1=1
+    plan: |
+      5
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_tinyint_1_idx[p3]", sql="select `id`, `c_tinyint_1` from `c_tinyint_1_idx` as `c_tinyint_1_idx` force index(`i_c_tinyint_1_id`) where (`c_tinyint_1` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_timestamp_3` = ?) and (`c_bigint_64_un` = ?) and (`c_int_32` = ?) and (`c_tinyint_1` = ?) and (`id` in (...)))")
+  - sql: |
+      /*+TDDL:cmd_extra(SPM_MAX_ACCEPTED_PLAN_SIZE_PER_BASELINE=3)*/ select * from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' and c_bigint_64_un = 14 and c_int_32=12 and c_tinyint_1=1
+    plan: |
+      3
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_tinyint_1_idx[p3]", sql="select `id`, `c_tinyint_1` from `c_tinyint_1_idx` as `c_tinyint_1_idx` force index(`i_c_tinyint_1_id`) where (`c_tinyint_1` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_timestamp_3` = ?) and (`c_bigint_64_un` = ?) and (`c_int_32` = ?) and (`c_tinyint_1` = ?) and (`id` in (...)))")
+  - sql: |
+      /*+TDDL:cmd_extra(SPM_MAX_ACCEPTED_PLAN_SIZE_PER_BASELINE=4)*/ select * from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' and c_bigint_64_un in(14,2)
+    plan: |
+      3
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_timestamp_3_idx[p19]", sql="select `c_datetime`, `id`, `c_text_long`, `c_timestamp_3`, `c_double` from `c_timestamp_3_idx` as `c_timestamp_3_idx` force index(`i_c_timestamp_3_id`) where (`c_timestamp_3` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_timestamp_3` = ?) and (`c_bigint_64_un` in(?)) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' and c_bigint_64 = 14
+    plan: |
+      2
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_timestamp_3_idx[p19]", sql="select `c_datetime`, `id`, `c_text_long`, `c_timestamp_3`, `c_double` from `c_timestamp_3_idx` as `c_timestamp_3_idx` force index(`i_c_timestamp_3_id`) where (`c_timestamp_3` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_timestamp_3` = ?) and (`c_bigint_64` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where id in (1,2,43)
+    plan: |
+      1
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p2,p11,p24]", shardcount=3, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where (`id` in(?))", pruninginfo="all size:3*3(part), pruning size:6")
+DDL:
+  cest_full_table_big:
+    CREATE TABLE `cest_full_table_big` (   `c_tinyint_8` tinyint(8) DEFAULT NULL,   `c_datetime_6` datetime(6) DEFAULT NULL,   `c_mediumint_24` mediumint(24) DEFAULT NULL,   `c_blob_medium` mediumblob,   `c_text_tiny` tinytext,   `c_time_3` time(3) DEFAULT NULL,   `c_int_32_un` int(32) UNSIGNED DEFAULT NULL,   `c_year` year(4) DEFAULT NULL,   `c_tinyint_4_un` tinyint(4) UNSIGNED DEFAULT NULL,   `c_time_1` time(1) DEFAULT NULL,   `c_text_medium` mediumtext,   `c_year_4` year(4) DEFAULT NULL,   `c_text` text,   `c_datetime` datetime DEFAULT NULL,   `c_tinyint_8_un` tinyint(8) UNSIGNED DEFAULT NULL,   `c_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,   `c_int_1` int(1) DEFAULT NULL,   `c_int_32` int(32) NOT NULL DEFAULT '0' COMMENT 'For multi pk.',   `c_double_un` double(10, 3) UNSIGNED DEFAULT NULL,   `id` bigint(20) NOT NULL AUTO_INCREMENT,   `c_mediumint_24_un` mediumint(24) UNSIGNED DEFAULT NULL,   `c_smallint_16_un` smallint(16) UNSIGNED DEFAULT NULL,   `c_bigint_1` bigint(1) DEFAULT NULL,   `c_blob` blob,   `c_text_long` longtext,   `c_timestamp_1` timestamp(1) NOT NULL DEFAULT '1999-12-31 12:00:00.0',   `c_blob_long` longblob,   `c_varchar` varchar(10) DEFAULT NULL,   `c_datetime_1` datetime(1) DEFAULT NULL,   `c_bit_8` bit(8) DEFAULT NULL,   `c_double_pr` double(10, 3) DEFAULT NULL,   `c_time_6` time(6) DEFAULT NULL,   `c_char` char(10) DEFAULT NULL,   `c_smallint_16` smallint(16) DEFAULT NULL,   `c_float_pr` float(10, 3) DEFAULT NULL,   `c_float_un` float(10, 3) UNSIGNED DEFAULT NULL,   `c_decimal` decimal(10, 0) DEFAULT NULL,   `c_timestamp_3` timestamp(3) NOT NULL DEFAULT '1999-12-31 12:00:00.000',   `c_bigint_64` bigint(64) DEFAULT NULL,   `c_blob_tiny` tinyblob,   `c_tinyint_1_un` tinyint(1) UNSIGNED DEFAULT NULL,   `c_decimal_pr` decimal(65, 30) DEFAULT NULL,   `c_enum` enum('a', 'b', 'c') DEFAULT NULL,   `c_bigint_64_un` bigint(64) UNSIGNED DEFAULT NULL,   `c_binary` binary(10) DEFAULT NULL,   `c_time` time DEFAULT NULL,   `c_float` float DEFAULT NULL,   `c_timestamp_6` timestamp(6) NOT NULL DEFAULT '1999-12-31 12:00:00.000000',   `c_bit_64` bit(64) DEFAULT NULL,   `c_date` date DEFAULT NULL COMMENT 'date',   `c_bit_32` bit(32) DEFAULT NULL,   `c_tinyint_4` tinyint(4) DEFAULT NULL,   `c_bit_16` bit(16) DEFAULT NULL,   `c_bit_1` bit(1) DEFAULT NULL,   `c_double` double DEFAULT NULL,   `c_datetime_3` datetime(3) DEFAULT NULL,   `c_mediumint_1` mediumint(1) DEFAULT NULL,   `c_varbinary` varbinary(10) DEFAULT NULL,   `c_smallint_1` smallint(1) DEFAULT NULL,   `c_tinyint_1` tinyint(1) DEFAULT NULL,   PRIMARY KEY (`id`),   GLOBAL INDEX  `c_bigint_1_idx` (`c_bigint_1`, `id`)     PARTITION BY KEY(`c_bigint_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`, `id`)     PARTITION BY KEY(`c_bigint_64_un`,`c_int_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_datetime_idx` (`c_datetime`, `id`)     PARTITION BY KEY(`c_datetime`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_int_32_idx` (`c_int_32`, `id`)     PARTITION BY KEY(`c_int_32`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_mediumint_24_idx` (`c_mediumint_24`, `id`)     PARTITION BY KEY(`c_mediumint_24`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_timestamp_1_idx` (`c_timestamp_1`, `id`) COVERING (`c_varchar`)     PARTITION BY KEY(`c_timestamp_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_timestamp_3_idx` (`c_timestamp_3`, `id`) COVERING (`c_datetime`, `c_text_long`, `c_double`)     PARTITION BY KEY(`c_timestamp_3`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_timestamp_6_idx` (`c_timestamp_6`, `id`) COVERING (`c_text`, `c_text_long`)     PARTITION BY KEY(`c_timestamp_6`,`id`)     PARTITIONS 4,   GLOBAL INDEX  `c_tinyint_1_idx` (`c_tinyint_1`, `id`)     PARTITION BY KEY(`c_tinyint_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_tinyint_1_un_idx` (`c_tinyint_1_un`, `id`)     PARTITION BY KEY(`c_tinyint_1_un`,`id`)     PARTITIONS 32,   GLOBAL INDEX`c_tinyint_4_idx` (`c_tinyint_4`, `id`)     PARTITION BY KEY(`c_tinyint_4`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_tinyint_8_idx` (`c_tinyint_8`, `id`)     PARTITION BY KEY(`c_tinyint_8`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_tinyint_8_un_idx` (`c_tinyint_8_un`, `id`)     PARTITION BY KEY(`c_tinyint_8_un`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_varchar_idx` (`c_varchar`, `id`)     PARTITION BY KEY(`c_varchar`,`id`)     PARTITIONS 32,   LOCAL KEY `_local_c_varchar_idx` (`c_varchar`),   LOCAL KEY `_local_c_int_32_idx` (`c_int_32`),   LOCAL KEY `_local_c_datetime_idx` (`c_datetime`),   LOCAL KEY `_local_c_tinyint_1_idx` (`c_tinyint_1`),   LOCAL KEY `_local_c_tinyint_1_un_idx` (`c_tinyint_1_un`),   LOCAL KEY `_local_c_tinyint_8_idx` (`c_tinyint_8`),   LOCAL KEY `_local_c_bigint_1_idx` (`c_bigint_1`),   LOCAL KEY `_local_c_tinyint_8_un_idx` (`c_tinyint_8_un`),   LOCAL KEY `_local_c_mediumint_24_idx` (`c_mediumint_24`),   LOCAL KEY `_local_c_tinyint_4_idx` (`c_tinyint_4`),   LOCAL KEY `c_char_idx` (`c_char`),   LOCAL KEY `c_int_32_un_idx` (`c_int_32_un`),   LOCAL KEY `c_time_idx` (`c_time`),   LOCAL KEY `c_tinyint_4_un_idx` (`c_tinyint_4_un`),   LOCAL KEY `c_smallint_16_idx` (`c_smallint_16`),   LOCAL KEY `c_smallint_16_un_idx` (`c_smallint_16_un`),   LOCAL KEY `c_bigint_64_idx` (`c_bigint_64`),   LOCAL KEY `c_smallint_1_idx` (`c_smallint_1`),   LOCAL KEY `c_mediumint_24_un_idx` (`c_mediumint_24_un`),   LOCAL KEY `c_mediumint_1_idx` (`c_mediumint_1`),   LOCAL KEY `_local_c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`),   LOCAL KEY `c_date_c_datetime_1_c_timestamp_idx` (`c_date`, `c_datetime_1`, `c_timestamp`),   LOCAL KEY `c_datetime_3_c_datetime_6_idx` (`c_datetime_3`, `c_datetime_6`),   LOCAL KEY `c_bit_64_c_bit_32_c_bit_8_idx` (`c_bit_64`, `c_bit_32`, `c_bit_8`),   LOCAL KEY `_local_c_timestamp_1_idx` (`c_timestamp_1`),   LOCAL KEY `_local_c_timestamp_3_idx` (`c_timestamp_3`),   LOCAL KEY `_local_c_timestamp_6_idx` (`c_timestamp_6`) ) ENGINE = InnoDB AUTO_INCREMENT = 9999976 DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS 32
+STATISTICS:
+  cest_full_table_big:
+    10146065
+CONFIG:
+  ENABLE_HOT_GSI_EVOLUTION:
+    true
+  HOT_GSI_EVOLUTION_THRESHOLD:
+    -1
+  defaltxxAPPName.isNew:
+    true
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiPatternTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiPatternTest.yml
new file mode 100644
index 000000000..adb7528e4
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiPatternTest.yml
@@ -0,0 +1,210 @@
+SQL:
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' and (c_text_long = '1' or id = 1)
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_timestamp_3_idx[p19]", sql="select `c_datetime`, `id`, `c_text_long`, `c_timestamp_3`, `c_double` from `c_timestamp_3_idx` as `c_timestamp_3_idx` where ((`c_timestamp_3` = ?) and ((`c_text_long` = ?) or (`id` = ?)))")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_timestamp_3` = ?) and ((`c_text_long` = ?) or (`id` = ?)) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' and c_text_long in (  '1','2','3')
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_timestamp_3_idx[p19]", sql="select `c_datetime`, `id`, `c_text_long`, `c_timestamp_3`, `c_double` from `c_timestamp_3_idx` as `c_timestamp_3_idx` where ((`c_timestamp_3` = ?) and (`c_text_long` in(?)))")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_timestamp_3` = ?) and (`c_text_long` in(?)) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_varchar = '1' order by id limit 10;
+    plan: |
+      true
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` force index(`i_c_varchar_id`) where (`c_varchar` = ?) order by `id` limit ?")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      select * from cest_full_table_big where c_varchar = '1' order by c_text_tiny limit 10;
+    plan: |
+      true
+      topn(sort="c_text_tiny asc", offset=0, fetch=?1)
+        project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+          bkajoin(condition="id = id", type="inner")
+            indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` force index(`i_c_varchar_id`) where (`c_varchar` = ?)")
+            gather(concurrent=true)
+              logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      /*+TDDL:cmd_extra(PREFER_PUSH_AGG=false)*/select count(1) as cnt from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' group by c_text_long;
+    plan: |
+      false
+      project(cnt="cnt")
+        hashagg(group="c_text_long", cnt="count()")
+          indexscan(tables="c_timestamp_3_idx[p19]", sql="select `c_text_long`, 1 as `$f1` from `c_timestamp_3_idx` as `c_timestamp_3_idx` force index(`i_c_timestamp_3_id`) where (`c_timestamp_3` = ?)")
+  - sql: |
+      select count(1) as cnt from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05' group by id;
+    plan: |
+      false
+      indexscan(tables="c_timestamp_3_idx[p19]", sql="select count(*) as `cnt` from `c_timestamp_3_idx` as `c_timestamp_3_idx` force index(`i_c_timestamp_3_id`) where (`c_timestamp_3` = ?) group by `id`")
+  - sql: |
+      select count(1) as cnt from cest_full_table_big where c_varchar = '1' group by c_text_long;
+    plan: |
+      true
+      project(cnt="cnt")
+        hashagg(group="c_text_long", cnt="count()")
+          project(c_text_long="c_text_long", $f1="1")
+            bkajoin(condition="id = id", type="inner")
+              indexscan(tables="c_varchar_idx[p22]", sql="select `id` from `c_varchar_idx` as `c_varchar_idx` force index(`i_c_varchar_id`) where (`c_varchar` = ?)")
+              gather(concurrent=true)
+                logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `id`, `c_text_long` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      select *, 
+        count(id) over(partition by c_varchar) 
+      from cest_full_table_big where c_timestamp_3 = '2023-12-01 14:10:05';
+    plan: |
+      false
+      hashwindow(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1", f60w0$o0="window#0count($19)", reference windows="window#0=window(partition {27} order by [] range between unbounded preceding and unbounded following aggs [count($19)])")
+        project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+          bkajoin(condition="id = id", type="inner")
+            indexscan(tables="c_timestamp_3_idx[p19]", sql="select `c_datetime`, `id`, `c_text_long`, `c_timestamp_3`, `c_double` from `c_timestamp_3_idx` as `c_timestamp_3_idx` force index(`i_c_timestamp_3_id`) where (`c_timestamp_3` = ?)")
+            gather(concurrent=true)
+              logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_timestamp_3` = ?) and (`id` in (...)))")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_push_join=false enable_cbo_push_join=false)*/ 
+      select a.c_tinyint_8 from cest_full_table_big a where a.c_varchar = '1' and a.id in (select b.id from  cest_full_table_big b where b.c_varchar = '2');
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8")
+        materializedsemijoin(condition="id = id", type="semi")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `id` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_varchar` = ?) and (`id` in (...)))")
+          indexscan(tables="c_varchar_idx[p18]", sql="select `id` from `c_varchar_idx` as `c_varchar_idx` force index(`i_c_varchar_id`) where (`c_varchar` = ?)")
+  - sql: |
+      select a.c_tinyint_8 from cest_full_table_big a where a.c_varchar = '1' and a.c_datetime in (select b.c_datetime from  cest_full_table_big b where b.id = 1 limit 1);
+    plan: |
+      false
+      gather(concurrent=true)
+        logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8` from `cest_full_table_big` as `cest_full_table_big` where ((`c_varchar` = ?) and (`c_datetime` in(?)))")
+      
+      >> individual scalar subquery :
+      logicalview(tables="cest_full_table_big[p2]", sql="select `c_datetime` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where (`id` = ?) limit ?")
+  - sql: |
+      /*+TDDL:cmd_extra(ENABLE_PUSH_CORRELATE=false)*/
+        select a.c_tinyint_8 from cest_full_table_big a where a.c_varchar = '1' and a.c_datetime in (select b.c_datetime from  cest_full_table_big b where b.id = 1 limit 1);
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8")
+        filter(condition="apply_boolean")
+          correlateapply(cor=$cor0, leftconditions=[$1], opkind=equals, type=semi)
+            project(c_tinyint_8="c_tinyint_8", c_datetime="c_datetime")
+              bkajoin(condition="id = id", type="inner")
+                indexscan(tables="c_varchar_idx[p22]", sql="select `id` from `c_varchar_idx` as `c_varchar_idx` force index(`i_c_varchar_id`) where (`c_varchar` = ?)")
+                gather(concurrent=true)
+                  logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime`, `id` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_varchar` = ?) and (`id` in (...)))")
+            logicalview(tables="cest_full_table_big[p2]", sql="select `c_datetime` as `$f0` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where (`id` = ?) limit ?")
+      cache node:
+      
+      project(c_tinyint_8="c_tinyint_8", c_datetime="c_datetime")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id` from `c_varchar_idx` as `c_varchar_idx` force index(`i_c_varchar_id`) where (`c_varchar` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime`, `id` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_varchar` = ?) and (`id` in (...)))")
+      logicalview(tables="cest_full_table_big[p2]", sql="select `c_datetime` as `$f0` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where (`id` = ?) limit ?")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_push_join=false enable_cbo_push_join=false)*/ 
+      select b.c_tinyint_8 from cest_full_table_big a force index(c_varchar_idx), cest_full_table_big b where a.c_varchar = '1' and a.id = b.id;
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id` from `c_varchar_idx` as `c_varchar_idx` force index(`i_c_varchar_id`) where (`c_varchar` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `id` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where (`id` in (...))")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_push_join=false enable_cbo_push_join=false enable_index_selection=false) bka_join(cest_full_table_big,cest_full_table_big)*/ 
+      select * from cest_full_table_big a, cest_full_table_big b where a.c_varchar = '1' and a.id = b.id;
+    plan: |
+      false
+      bkajoin(condition="id = id", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`_local_c_varchar_idx`) where (`c_varchar` = ?)")
+        gather(concurrent=true)
+          logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where (`id` in (...))")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_push_join=false  enable_cbo_push_join=false)*/ select count(1) from cest_full_table_big a, cest_full_table_big b where a.c_varchar = '1' and a.id = b.id;
+    plan: |
+      false
+      hashagg(count(1)="count()")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id` from `c_varchar_idx` as `c_varchar_idx` force index(`i_c_varchar_id`) where (`c_varchar` = ?)")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `id` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where (`id` in (...))")
+  - sql: |
+      select * from cest_full_table_big,cest_full_table_big a, cest_full_table_big b
+      where a.c_varchar = '1' and b.c_varchar = a.c_varchar;
+    plan: |
+      false
+      nljoin(condition="true", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big`")
+        sortmergejoin(condition="c_varchar = c_varchar", type="inner")
+          project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+            bkajoin(condition="id = id", type="inner")
+              indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?) order by `c_varchar`")
+              gather(concurrent=true)
+                logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_varchar` = ?) and (`id` in (...)))")
+          project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+            bkajoin(condition="id = id", type="inner")
+              indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` where (`c_varchar` = ?) order by `c_varchar`")
+              gather(concurrent=true)
+                logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_varchar` = ?) and (`id` in (...)))")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_push_join=false)*/ 
+        delete from cest_full_table_big b where b.id in (select id from cest_full_table_big a where a.c_varchar = '1');
+    plan: |
+      false
+      logicalmodify(type="delete", tables="optest.cest_full_table_big")
+        materializedsemijoin(condition="id = id", type="semi")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_varchar`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where (`id` in (...)) for update")
+          project(id="id")
+            bkajoin(condition="id = id", type="inner")
+              indexscan(tables="c_varchar_idx[p22]", sql="select `id` from `c_varchar_idx` as `c_varchar_idx` force index(`i_c_varchar_id`) where (`c_varchar` = ?) for update")
+              gather(concurrent=true)
+                logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `id` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_varchar` = ?) and (`id` in (...))) for update")
+  - sql: |
+      select * from cest_full_table_big where c_varchar = '1' and c_timestamp_3= '2023-12-01 14:10:05' for update;
+    plan: |
+      false
+      project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1")
+        bkajoin(condition="id = id", type="inner")
+          indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` force index(`i_c_varchar_id`) where (`c_varchar` = ?) for update")
+          gather(concurrent=true)
+            logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_varchar` = ?) and (`c_timestamp_3` = ?) and (`id` in (...))) for update")
+  - sql: |
+      update cest_full_table_big set id = 1 where c_varchar = '1';
+    plan: |
+      false
+      logicalrelocate(type=update, set="cest_full_table_big.id=?0", relocate="cest_full_table_big", update="c_bigint_1_idx, c_bigint_64_un_c_int_1_idx, c_datetime_idx, c_int_32_idx, c_mediumint_24_idx, c_timestamp_1_idx, c_timestamp_3_idx, c_timestamp_6_idx, c_tinyint_1_idx, c_tinyint_1_un_idx, c_tinyint_4_idx, c_tinyint_8_idx, c_tinyint_8_un_idx, c_varchar_idx")
+        project(c_tinyint_8="c_tinyint_8", c_datetime_6="c_datetime_6", c_mediumint_24="c_mediumint_24", c_blob_medium="c_blob_medium", c_text_tiny="c_text_tiny", c_time_3="c_time_3", c_int_32_un="c_int_32_un", c_year="c_year", c_tinyint_4_un="c_tinyint_4_un", c_time_1="c_time_1", c_text_medium="c_text_medium", c_year_4="c_year_4", c_text="c_text", c_datetime="c_datetime", c_tinyint_8_un="c_tinyint_8_un", c_timestamp="c_timestamp", c_int_1="c_int_1", c_int_32="c_int_32", c_double_un="c_double_un", id="id", c_mediumint_24_un="c_mediumint_24_un", c_smallint_16_un="c_smallint_16_un", c_bigint_1="c_bigint_1", c_blob="c_blob", c_text_long="c_text_long", c_timestamp_1="c_timestamp_1", c_blob_long="c_blob_long", c_varchar="c_varchar", c_datetime_1="c_datetime_1", c_bit_8="c_bit_8", c_double_pr="c_double_pr", c_time_6="c_time_6", c_char="c_char", c_smallint_16="c_smallint_16", c_float_pr="c_float_pr", c_float_un="c_float_un", c_decimal="c_decimal", c_timestamp_3="c_timestamp_3", c_bigint_64="c_bigint_64", c_blob_tiny="c_blob_tiny", c_tinyint_1_un="c_tinyint_1_un", c_decimal_pr="c_decimal_pr", c_enum="c_enum", c_bigint_64_un="c_bigint_64_un", c_binary="c_binary", c_time="c_time", c_float="c_float", c_timestamp_6="c_timestamp_6", c_bit_64="c_bit_64", c_date="c_date", c_bit_32="c_bit_32", c_tinyint_4="c_tinyint_4", c_bit_16="c_bit_16", c_bit_1="c_bit_1", c_double="c_double", c_datetime_3="c_datetime_3", c_mediumint_1="c_mediumint_1", c_varbinary="c_varbinary", c_smallint_1="c_smallint_1", c_tinyint_1="c_tinyint_1", gen$0="?0")
+          bkajoin(condition="id = id", type="inner")
+            indexscan(tables="c_varchar_idx[p22]", sql="select `id`, `c_varchar` from `c_varchar_idx` as `c_varchar_idx` force index(`i_c_varchar_id`) where (`c_varchar` = ?) for update")
+            gather(concurrent=true)
+              logicalview(tables="cest_full_table_big[p1,p2,p3,...p32]", shardcount=32, sql="select `c_tinyint_8`, `c_datetime_6`, `c_mediumint_24`, `c_blob_medium`, `c_text_tiny`, `c_time_3`, `c_int_32_un`, `c_year`, `c_tinyint_4_un`, `c_time_1`, `c_text_medium`, `c_year_4`, `c_text`, `c_datetime`, `c_tinyint_8_un`, `c_timestamp`, `c_int_1`, `c_int_32`, `c_double_un`, `id`, `c_mediumint_24_un`, `c_smallint_16_un`, `c_bigint_1`, `c_blob`, `c_text_long`, `c_timestamp_1`, `c_blob_long`, `c_datetime_1`, `c_bit_8`, `c_double_pr`, `c_time_6`, `c_char`, `c_smallint_16`, `c_float_pr`, `c_float_un`, `c_decimal`, `c_timestamp_3`, `c_bigint_64`, `c_blob_tiny`, `c_tinyint_1_un`, `c_decimal_pr`, `c_enum`, `c_bigint_64_un`, `c_binary`, `c_time`, `c_float`, `c_timestamp_6`, `c_bit_64`, `c_date`, `c_bit_32`, `c_tinyint_4`, `c_bit_16`, `c_bit_1`, `c_double`, `c_datetime_3`, `c_mediumint_1`, `c_varbinary`, `c_smallint_1`, `c_tinyint_1` from `cest_full_table_big` as `cest_full_table_big` force index(`primary`) where ((`c_varchar` = ?) and (`id` in (...))) for update")
+DDL:
+  cest_full_table_big:
+    CREATE TABLE `cest_full_table_big` (   `c_tinyint_8` tinyint(8) DEFAULT NULL,   `c_datetime_6` datetime(6) DEFAULT NULL,   `c_mediumint_24` mediumint(24) DEFAULT NULL,   `c_blob_medium` mediumblob,   `c_text_tiny` tinytext,   `c_time_3` time(3) DEFAULT NULL,   `c_int_32_un` int(32) UNSIGNED DEFAULT NULL,   `c_year` year(4) DEFAULT NULL,   `c_tinyint_4_un` tinyint(4) UNSIGNED DEFAULT NULL,   `c_time_1` time(1) DEFAULT NULL,   `c_text_medium` mediumtext,   `c_year_4` year(4) DEFAULT NULL,   `c_text` text,   `c_datetime` datetime DEFAULT NULL,   `c_tinyint_8_un` tinyint(8) UNSIGNED DEFAULT NULL,   `c_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,   `c_int_1` int(1) DEFAULT NULL,   `c_int_32` int(32) NOT NULL DEFAULT '0' COMMENT 'For multi pk.',   `c_double_un` double(10, 3) UNSIGNED DEFAULT NULL,   `id` bigint(20) NOT NULL AUTO_INCREMENT,   `c_mediumint_24_un` mediumint(24) UNSIGNED DEFAULT NULL,   `c_smallint_16_un` smallint(16) UNSIGNED DEFAULT NULL,   `c_bigint_1` bigint(1) DEFAULT NULL,   `c_blob` blob,   `c_text_long` longtext,   `c_timestamp_1` timestamp(1) NOT NULL DEFAULT '1999-12-31 12:00:00.0',   `c_blob_long` longblob,   `c_varchar` varchar(10) DEFAULT NULL,   `c_datetime_1` datetime(1) DEFAULT NULL,   `c_bit_8` bit(8) DEFAULT NULL,   `c_double_pr` double(10, 3) DEFAULT NULL,   `c_time_6` time(6) DEFAULT NULL,   `c_char` char(10) DEFAULT NULL,   `c_smallint_16` smallint(16) DEFAULT NULL,   `c_float_pr` float(10, 3) DEFAULT NULL,   `c_float_un` float(10, 3) UNSIGNED DEFAULT NULL,   `c_decimal` decimal(10, 0) DEFAULT NULL,   `c_timestamp_3` timestamp(3) NOT NULL DEFAULT '1999-12-31 12:00:00.000',   `c_bigint_64` bigint(64) DEFAULT NULL,   `c_blob_tiny` tinyblob,   `c_tinyint_1_un` tinyint(1) UNSIGNED DEFAULT NULL,   `c_decimal_pr` decimal(65, 30) DEFAULT NULL,   `c_enum` enum('a', 'b', 'c') DEFAULT NULL,   `c_bigint_64_un` bigint(64) UNSIGNED DEFAULT NULL,   `c_binary` binary(10) DEFAULT NULL,   `c_time` time DEFAULT NULL,   `c_float` float DEFAULT NULL,   `c_timestamp_6` timestamp(6) NOT NULL DEFAULT '1999-12-31 12:00:00.000000',   `c_bit_64` bit(64) DEFAULT NULL,   `c_date` date DEFAULT NULL COMMENT 'date',   `c_bit_32` bit(32) DEFAULT NULL,   `c_tinyint_4` tinyint(4) DEFAULT NULL,   `c_bit_16` bit(16) DEFAULT NULL,   `c_bit_1` bit(1) DEFAULT NULL,   `c_double` double DEFAULT NULL,   `c_datetime_3` datetime(3) DEFAULT NULL,   `c_mediumint_1` mediumint(1) DEFAULT NULL,   `c_varbinary` varbinary(10) DEFAULT NULL,   `c_smallint_1` smallint(1) DEFAULT NULL,   `c_tinyint_1` tinyint(1) DEFAULT NULL,   PRIMARY KEY (`id`),   GLOBAL INDEX  `c_bigint_1_idx` (`c_bigint_1`, `id`)     PARTITION BY KEY(`c_bigint_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`, `id`)     PARTITION BY KEY(`c_bigint_64_un`,`c_int_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_datetime_idx` (`c_datetime`, `id`)     PARTITION BY KEY(`c_datetime`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_int_32_idx` (`c_int_32`, `id`)     PARTITION BY KEY(`c_int_32`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_mediumint_24_idx` (`c_mediumint_24`, `id`)     PARTITION BY KEY(`c_mediumint_24`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_timestamp_1_idx` (`c_timestamp_1`, `id`) COVERING (`c_varchar`)     PARTITION BY KEY(`c_timestamp_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_timestamp_3_idx` (`c_timestamp_3`, `id`) COVERING (`c_datetime`, `c_text_long`, `c_double`)     PARTITION BY KEY(`c_timestamp_3`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_timestamp_6_idx` (`c_timestamp_6`, `id`) COVERING (`c_text`, `c_text_long`)     PARTITION BY KEY(`c_timestamp_6`,`id`)     PARTITIONS 4,   GLOBAL INDEX  `c_tinyint_1_idx` (`c_tinyint_1`, `id`)     PARTITION BY KEY(`c_tinyint_1`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_tinyint_1_un_idx` (`c_tinyint_1_un`, `id`)     PARTITION BY KEY(`c_tinyint_1_un`,`id`)     PARTITIONS 32,   GLOBAL INDEX`c_tinyint_4_idx` (`c_tinyint_4`, `id`)     PARTITION BY KEY(`c_tinyint_4`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_tinyint_8_idx` (`c_tinyint_8`, `id`)     PARTITION BY KEY(`c_tinyint_8`,`id`)     PARTITIONS 32,   GLOBAL INDEX  `c_tinyint_8_un_idx` (`c_tinyint_8_un`, `id`)     PARTITION BY KEY(`c_tinyint_8_un`,`id`)     PARTITIONS 32,   GLOBAL INDEX `c_varchar_idx` (`c_varchar`, `id`)     PARTITION BY KEY(`c_varchar`,`id`)     PARTITIONS 32,   LOCAL KEY `_local_c_varchar_idx` (`c_varchar`),   LOCAL KEY `_local_c_int_32_idx` (`c_int_32`),   LOCAL KEY `_local_c_datetime_idx` (`c_datetime`),   LOCAL KEY `_local_c_tinyint_1_idx` (`c_tinyint_1`),   LOCAL KEY `_local_c_tinyint_1_un_idx` (`c_tinyint_1_un`),   LOCAL KEY `_local_c_tinyint_8_idx` (`c_tinyint_8`),   LOCAL KEY `_local_c_bigint_1_idx` (`c_bigint_1`),   LOCAL KEY `_local_c_tinyint_8_un_idx` (`c_tinyint_8_un`),   LOCAL KEY `_local_c_mediumint_24_idx` (`c_mediumint_24`),   LOCAL KEY `_local_c_tinyint_4_idx` (`c_tinyint_4`),   LOCAL KEY `c_char_idx` (`c_char`),   LOCAL KEY `c_int_32_un_idx` (`c_int_32_un`),   LOCAL KEY `c_time_idx` (`c_time`),   LOCAL KEY `c_tinyint_4_un_idx` (`c_tinyint_4_un`),   LOCAL KEY `c_smallint_16_idx` (`c_smallint_16`),   LOCAL KEY `c_smallint_16_un_idx` (`c_smallint_16_un`),   LOCAL KEY `c_bigint_64_idx` (`c_bigint_64`),   LOCAL KEY `c_smallint_1_idx` (`c_smallint_1`),   LOCAL KEY `c_mediumint_24_un_idx` (`c_mediumint_24_un`),   LOCAL KEY `c_mediumint_1_idx` (`c_mediumint_1`),   LOCAL KEY `_local_c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`),   LOCAL KEY `c_date_c_datetime_1_c_timestamp_idx` (`c_date`, `c_datetime_1`, `c_timestamp`),   LOCAL KEY `c_datetime_3_c_datetime_6_idx` (`c_datetime_3`, `c_datetime_6`),   LOCAL KEY `c_bit_64_c_bit_32_c_bit_8_idx` (`c_bit_64`, `c_bit_32`, `c_bit_8`),   LOCAL KEY `_local_c_timestamp_1_idx` (`c_timestamp_1`),   LOCAL KEY `_local_c_timestamp_3_idx` (`c_timestamp_3`),   LOCAL KEY `_local_c_timestamp_6_idx` (`c_timestamp_6`) ) ENGINE = InnoDB AUTO_INCREMENT = 9999976 DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS 32
+  cest_narrow_table:
+    CREATE  TABLE `cest_narrow_table` (     `c_varchar` varchar(10) DEFAULT NULL,     `c_datetime` datetime DEFAULT NULL,     `id` bigint(20) NOT NULL AUTO_INCREMENT,     `c_enum` enum('a', 'b', 'c') DEFAULT NULL,     `c_int_32` int(32) NOT NULL DEFAULT '0' COMMENT 'For multi pk.',     PRIMARY KEY (`id`),     LOCAL INDEX  `c_int_32_idx` (`c_int_32`,`id`),     LOCAL INDEX `c_varchar_idx` (`c_varchar`,`id`)   ,     LOCAL KEY `_local_c_int_32_idx` (`c_int_32`),     LOCAL KEY `_local_c_varchar_idx` (`c_varchar`),     LOCAL KEY `c_datetime_idx` (`c_datetime`)     ) ENGINE = InnoDB AUTO_INCREMENT = 9915 DEFAULT CHARSET = utf8mb4     broadcast
+STATISTICS:
+  cest_full_table_big:
+    10146065
+  cest_narrow_table:
+    10000
+CONFIG:
+  HOT_GSI_EVOLUTION_THRESHOLD:
+    5000
+  defaltxxAPPName.isNew:
+    true
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiSelectivityUpperLimitEstimatorTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiSelectivityUpperLimitEstimatorTest.yml
new file mode 100644
index 000000000..c65e8870c
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/optimizer/hotgsi/HotGsiSelectivityUpperLimitEstimatorTest.yml
@@ -0,0 +1,960 @@
+SQL:
+  # test free
+  - sql: |
+      select * from cest_full_table_big where id < 1;
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_float_pr <= 1+3;
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_tinyint_1_un >= 1-2;
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_tinyint_8 > 1+2;
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where 1+2 > c_tinyint_8;
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_mediumint_1 != 1;
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where 1 != c_mediumint_1;
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_mediumint_1 <> 1;
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where 1 <> c_mediumint_1;
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_date not in ('2023-12-01','2023-12-02');
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_time_6 between '2023-12-01' and '2023-12-02';
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_6 not between '1996-12-01' and '2023-12-02';
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where  c_char like '%a';
+    plan: |
+      10146065
+  # test bound
+  - sql: |
+      select * from cest_full_table_big where  c_bigint_1=1;
+    plan: |
+      731
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14*100
+    plan: |
+      1005
+  - sql: |
+      select * from cest_full_table_big where c_datetime = '2023-12-01 14:10:05';
+    plan: |
+      731
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_1 = '2023-12-01 14:10:05';
+    plan: |
+      1005
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_3 <=> '1999-12-31 12:00:00.000';
+    plan: |
+      207608
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 in (14*100,312,'gg');
+    plan: |
+      3015
+  - sql: |
+      select * from cest_full_table_big where c_double_un is null;
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where c_text_long is not null;
+    plan: |
+      10146065
+  # test unknown
+  - sql: |
+      select * from cest_full_table_big where c_char+'11'= '011';
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where (c_char,c_varchar) = ('1', '2');
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where c_char in (c_varchar, '1');
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where (c_char,c_varchar) in ('1', '2');
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where (c_char,c_varchar) in (c_varchar, '1');
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where  c_bigint_1=c_bigint_64+1;
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where cast (c_bigint_1 as unsigned int)=1;
+    plan: |
+      0
+  # test in
+  - sql: |
+      select * from cest_full_table_big where c_char in ('2', c_varchar, '1');
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where c_char in ('2', '1');
+    plan: |
+      703600
+  - sql: |
+      select * from cest_full_table_big where c_char in ('2'+'1');
+    plan: |
+      14072
+  - sql: |
+      select * from cest_full_table_big where c_char in ('2'+'1', '1');
+    plan: |
+      28144
+  - sql: |
+      select * from cest_full_table_big where c_char = '2' or c_char = '1';
+    plan: |
+      28144
+  # test composite
+  - sql: |
+      select * from cest_full_table_big where id < 1 and c_tinyint_8 > 1+2
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where id < 1 and c_bigint_64 = 14*100
+    plan: |
+      1005
+  - sql: |
+      select * from cest_full_table_big where id < 1 and c_char in (c_varchar, '1')
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14*100 and c_datetime = '2023-12-01 14:10:05'
+    plan: |
+      7
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14*100 and c_char in (c_varchar, '1')
+    plan: |
+      1005
+  - sql: |
+      select * from cest_full_table_big where c_char in (c_varchar, '1') and c_bigint_1=c_bigint_64+1
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where id < 1 and c_tinyint_8 > 1+2 and c_bigint_64 = 14*100
+    plan: |
+      1005
+  - sql: |
+      select * from cest_full_table_big where id < 1 and c_tinyint_8 > 1+2 and c_char in (c_varchar, '1')
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where id < 1 and c_bigint_64 = 14*100 and c_datetime = '2023-12-01 14:10:05'
+    plan: |
+      7
+  - sql: |
+      select * from cest_full_table_big where id < 1 and c_bigint_64 = 14*100 and c_char in (c_varchar, '1')
+    plan: |
+      1005
+  - sql: |
+      select * from cest_full_table_big where id < 1 and c_char in (c_varchar, '1') and c_bigint_1=c_bigint_64+1
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14*100 and c_datetime = '2023-12-01 14:10:05' and c_char in (c_varchar, '1')
+    plan: |
+      7
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14*100 and c_char in (c_varchar, '1') and c_bigint_1=c_bigint_64+1
+    plan: |
+      1005
+  - sql: |
+      select * from cest_full_table_big where id < 1 or c_tinyint_8 > 1+2
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where id < 1 or c_bigint_64 = 14*100
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where id < 1 or c_char in (c_varchar, '1')
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14*100 or c_datetime = '2023-12-01 14:10:05'
+    plan: |
+      1736
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14*100 or c_char in (c_varchar, '1')
+    plan: |
+      1005
+  - sql: |
+      select * from cest_full_table_big where c_char in (c_varchar, '1') or c_bigint_1=c_bigint_64+1
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where id < 1 or c_tinyint_8 > 1+2 or c_bigint_64 = 14*100
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where id < 1 or c_tinyint_8 > 1+2 or c_char in (c_varchar, '1')
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where id < 1 or c_bigint_64 = 14*100 or c_datetime = '2023-12-01 14:10:05'
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where id < 1 or c_bigint_64 = 14*100 or c_char in (c_varchar, '1')
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where id < 1 or c_char in (c_varchar, '1') or c_bigint_1=c_bigint_64+1
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14*100 or c_datetime = '2023-12-01 14:10:05' or c_char in (c_varchar, '1')
+    plan: |
+      1736
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14*100 or c_char in (c_varchar, '1') or c_bigint_1=c_bigint_64+1
+    plan: |
+      1005
+  - sql: |
+      select * from cest_full_table_big where (not c_char like '%a') or c_bigint_1=1;
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where  c_bigint_1 in (1) and c_tinyint_8>1;
+    plan: |
+      36550
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14 and c_bigint_1 = 1
+    plan: |
+      7
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14 or c_bigint_1 = 1
+    plan: |
+      1736
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14 or c_bigint_64 = 1
+    plan: |
+      2010
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14 and c_bigint_64 = 1 and c_bigint_64 = 2 and 1=1
+    plan: |
+      1005
+  - sql: |
+      select * from cest_full_table_big where c_bigint_64 = 14 or c_bigint_64 = 1 or c_bigint_64 = 2 or 1=1
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where c_tinyint_8 = 14 and c_timestamp_3 <=> '1999-12-31 12:00:00.000';
+    plan: |
+      80074
+  - sql: |
+      select * from cest_full_table_big where c_tinyint_8 = 14 and c_timestamp_3 <=> '1999-12-31 12:00:00.000' and c_text_long is not null;
+    plan: |
+      80074
+  - sql: |
+      select * from cest_full_table_big where c_tinyint_8 = 14 and c_timestamp_3 <=> '1999-12-31 12:00:00.000' and  c_bigint_64 in (14*100,312,'gg') and c_text_long is not null;
+    plan: |
+      268
+  - sql: |
+      select * from cest_full_table_big where c_tinyint_8 = 16 and c_tinyint_8 = 14 and c_timestamp_3 <=> '1999-12-31 12:00:00.000' and  c_bigint_64 in (14*100,312,'gg') and c_text_long is not null;
+    plan: |
+      268
+  - sql: |
+      select * from cest_full_table_big where not (c_bigint_64 in (16));
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where not (c_tinyint_8 < 16);
+    plan: |
+      10146065
+  - sql: |
+      select * from cest_full_table_big where not (c_tinyint_8 = 16+ c_bigint_1);
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where (not (c_bigint_64 in (16))) and c_bigint_64 = 1;
+    plan: |
+      1005
+  - sql: |
+      select * from cest_full_table_big where (c_bigint_64 = 14*100 or c_char in (c_varchar, '1')) and  c_bigint_64 = 1;
+    plan: |
+      10
+  - sql: |
+      select * from cest_full_table_big where (not (c_bigint_64 in (16))) or c_bigint_64 = 1;
+    plan: |
+      10146065
+  # test pk and uk
+  - sql: |
+      /*+TDDL:cmd_extra(enable_post_planner=false)*/select * from cest_full_table_big where id = 1 and id in (1,2,3)
+    plan: |
+      1
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_6 = '2023-12-01 14:10:05';
+    plan: |
+      738693
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_6 = '2023-12-01 14:10:05' and c_mediumint_24=11;
+    plan: |
+      1
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_6 = '2023-12-01 14:10:05' and c_mediumint_24 in (11);
+    plan: |
+      70263
+  - sql: |
+      select * from cest_full_table_big where (c_timestamp_6,c_mediumint_24) in ('2023-12-01 14:10:05', '11');
+    plan: |
+      0
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_6 = '2023-12-01 14:10:05' and c_mediumint_24='11' and c_bigint_1 in (1,1,2);
+    plan: |
+      1
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_6 = '2023-12-01 14:10:05' and c_mediumint_24='11' and c_bigint_1 in (1,c_bigint_1,2);
+    plan: |
+      1
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_6 = '2023-12-01 14:10:05' or (c_mediumint_24='11');
+    plan: |
+      743901
+  - sql: |
+      select * from cest_full_table_big where c_timestamp_6 = '2023-12-01 14:10:05' or (c_mediumint_24='11' and c_bigint_1 in (1,1,2));
+    plan: |
+      739006
+DDL:
+  cest_full_table_big:
+    CREATE TABLE `cest_full_table_big` (    `c_tinyint_8` tinyint(8) DEFAULT NULL,    `c_datetime_6` datetime(6) DEFAULT NULL,    `c_mediumint_24` mediumint(24) DEFAULT NULL,    `c_blob_medium` mediumblob,    `c_text_tiny` tinytext,    `c_time_3` time(3) DEFAULT NULL,    `c_int_32_un` int(32) UNSIGNED DEFAULT NULL,    `c_year` year(4) DEFAULT NULL,    `c_tinyint_4_un` tinyint(4) UNSIGNED DEFAULT NULL,    `c_time_1` time(1) DEFAULT NULL,    `c_text_medium` mediumtext,    `c_year_4` year(4) DEFAULT NULL,    `c_text` text,    `c_datetime` datetime DEFAULT NULL,    `c_tinyint_8_un` tinyint(8) UNSIGNED DEFAULT NULL,    `c_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,    `c_int_1` int(1) DEFAULT NULL,    `c_int_32` int(32) NOT NULL DEFAULT '0' COMMENT 'For multi pk.',    `c_double_un` double(10, 3) UNSIGNED DEFAULT NULL,    `id` bigint(20) NOT NULL AUTO_INCREMENT,    `c_mediumint_24_un` mediumint(24) UNSIGNED DEFAULT NULL,    `c_smallint_16_un` smallint(16) UNSIGNED DEFAULT NULL,    `c_bigint_1` bigint(1) DEFAULT NULL,    `c_blob` blob,    `c_text_long` longtext,    `c_timestamp_1` timestamp(1) NOT NULL DEFAULT '1999-12-31 12:00:00.0',    `c_blob_long` longblob,    `c_varchar` varchar(10) DEFAULT NULL,    `c_datetime_1` datetime(1) DEFAULT NULL,    `c_bit_8` bit(8) DEFAULT NULL,    `c_double_pr` double(10, 3) DEFAULT NULL,    `c_time_6` time(6) DEFAULT NULL,    `c_char` char(10) DEFAULT NULL,    `c_smallint_16` smallint(16) DEFAULT NULL,    `c_float_pr` float(10, 3) DEFAULT NULL,    `c_float_un` float(10, 3) UNSIGNED DEFAULT NULL,    `c_decimal` decimal(10, 0) DEFAULT NULL,    `c_timestamp_3` timestamp(3) NOT NULL DEFAULT '1999-12-31 12:00:00.000',    `c_bigint_64` bigint(64) DEFAULT NULL,    `c_blob_tiny` tinyblob,    `c_tinyint_1_un` tinyint(1) UNSIGNED DEFAULT NULL,    `c_decimal_pr` decimal(65, 30) DEFAULT NULL,    `c_enum` enum('a', 'b', 'c') DEFAULT NULL,    `c_bigint_64_un` bigint(64) UNSIGNED DEFAULT NULL,    `c_binary` binary(10) DEFAULT NULL,    `c_time` time DEFAULT NULL,    `c_float` float DEFAULT NULL,    `c_timestamp_6` timestamp(6) NOT NULL DEFAULT '1999-12-31 12:00:00.000000',    `c_bit_64` bit(64) DEFAULT NULL,    `c_date` date DEFAULT NULL COMMENT 'date',    `c_bit_32` bit(32) DEFAULT NULL,    `c_tinyint_4` tinyint(4) DEFAULT NULL,    `c_bit_16` bit(16) DEFAULT NULL,    `c_bit_1` bit(1) DEFAULT NULL,    `c_double` double DEFAULT NULL,    `c_datetime_3` datetime(3) DEFAULT NULL,    `c_mediumint_1` mediumint(1) DEFAULT NULL,    `c_varbinary` varbinary(10) DEFAULT NULL,    `c_smallint_1` smallint(1) DEFAULT NULL,    `c_tinyint_1` tinyint(1) DEFAULT NULL,    PRIMARY KEY (`id`), UNIQUE KEY (`c_mediumint_24`,`c_timestamp_6`)) ENGINE = InnoDB AUTO_INCREMENT = 9999976 DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS 32
+STATISTICS:
+  cest_full_table_big:
+    10146065
+  cest_full_table_big.c_bigint_1.TOPN:
+    { "countArr": [ 7,8,7,7,7,7,7,7,8,7,7,7 ],"valueArr": [ -6376110534660341752,-6295860234981414021,-3387826301801300382,-3317629540485480748,-316510671619583280,2235619186577416414,5998302180515327641,7246557246978697801,8012792635540531924,8164713881782245490,8291899079068489613,8452645718485150018 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_bigint_1.cardinality:
+    515019
+  cest_full_table_big.c_bigint_1.histogram:
+    { "buckets": [ { "ndv": 955,"upper": -8932916535817943413,"lower": -9223263330713288104,"count": 1562,"preSum": 0 },{ "ndv": 969,"upper": -8633253116690592290,"lower": -8930905338028779562,"count": 1562,"preSum": 1562 },{ "ndv": 984,"upper": -8347089718084234233,"lower": -8633198632878975763,"count": 1562,"preSum": 3124 },{ "ndv": 968,"upper": -8060695010946051790,"lower": -8346593554111079269,"count": 1566,"preSum": 4686 },{ "ndv": 994,"upper": -7771584841519309202,"lower": -8060418882318543243,"count": 1562,"preSum": 6252 },{ "ndv": 1017,"upper": -7497444055272811665,"lower": -7771428776282755773,"count": 1562,"preSum": 7814 },{ "ndv": 995,"upper": -7195896885265305430,"lower": -7497128742749681004,"count": 1563,"preSum": 9376 },{ "ndv": 977,"upper": -6921540528489252564,"lower": -7195596509692484692,"count": 1562,"preSum": 10939 },{ "ndv": 977,"upper": -6624478349282213326,"lower": -6921303896397899311,"count": 1562,"preSum": 12501 },{ "ndv": 1013,"upper": -6326942704964228255,"lower": -6623706794207147909,"count": 1562,"preSum": 14063 },{ "ndv": 973,"upper": -6048730337678060000,"lower": -6326528978673752439,"count": 1562,"preSum": 15625 },{ "ndv": 989,"upper": -5766496232027761237,"lower": -6048644639004061559,"count": 1562,"preSum": 17187 },{ "ndv": 993,"upper": -5478889351592529936,"lower": -5766385033064508563,"count": 1562,"preSum": 18749 },{ "ndv": 993,"upper": -5183757245055358005,"lower": -5478579004929422994,"count": 1563,"preSum": 20311 },{ "ndv": 984,"upper": -4888332246776830554,"lower": -5183494763525666395,"count": 1562,"preSum": 21874 },{ "ndv": 997,"upper": -4600173769951461714,"lower": -4888158332288254714,"count": 1562,"preSum": 23436 },{ "ndv": 961,"upper": -4302524136056705094,"lower": -4600123077454563931,"count": 1562,"preSum": 24998 },{ "ndv": 1015,"upper": -4010460099681951372,"lower": -4302454593034289870,"count": 1563,"preSum": 26560 },{ "ndv": 985,"upper": -3740342398516062462,"lower": -4009700152265817765,"count": 1562,"preSum": 28123 },{ "ndv": 972,"upper": -3458448279442391397,"lower": -3739424094345203473,"count": 1562,"preSum": 29685 },{ "ndv": 994,"upper": -3174379453013748082,"lower": -3458444931032076409,"count": 1562,"preSum": 31247 },{ "ndv": 991,"upper": -2886995664117776327,"lower": -3174013781147822945,"count": 1562,"preSum": 32809 },{ "ndv": 1010,"upper": -2593937518025117187,"lower": -2886840346146487112,"count": 1562,"preSum": 34371 },{ "ndv": 972,"upper": -2311562007642626030,"lower": -2593882299551196295,"count": 1562,"preSum": 35933 },{ "ndv": 992,"upper": -2011003511050290501,"lower": -2311476196844441478,"count": 1564,"preSum": 37495 },{ "ndv": 953,"upper": -1742255962838330888,"lower": -2010565592079484691,"count": 1562,"preSum": 39059 },{ "ndv": 1004,"upper": -1446304444467700880,"lower": -1742197275185244859,"count": 1562,"preSum": 40621 },{ "ndv": 981,"upper": -1143697687274724334,"lower": -1446199600463342952,"count": 1562,"preSum": 42183 },{ "ndv": 983,"upper": -866222259907853852,"lower": -1143291573446824623,"count": 1562,"preSum": 43745 },{ "ndv": 1004,"upper": -584350384737477135,"lower": -866209985750491003,"count": 1562,"preSum": 45307 },{ "ndv": 1040,"upper": -293237826231828088,"lower": -584171325701628567,"count": 1563,"preSum": 46869 },{ "ndv": 968,"upper": -8962957024550713,"lower": -293158630105002746,"count": 1564,"preSum": 48432 },{ "ndv": 995,"upper": 289014090145346562,"lower": -8530435155574750,"count": 1562,"preSum": 49996 },{ "ndv": 973,"upper": 565383892780485287,"lower": 289175669607299880,"count": 1563,"preSum": 51558 },{ "ndv": 975,"upper": 848447355876816991,"lower": 565672321220056304,"count": 1563,"preSum": 53121 },{ "ndv": 1004,"upper": 1136074647801299479,"lower": 848662352035143350,"count": 1562,"preSum": 54684 },{ "ndv": 1008,"upper": 1432922108558858103,"lower": 1136218643792012375,"count": 1562,"preSum": 56246 },{ "ndv": 997,"upper": 1731797561341496566,"lower": 1433399712803562213,"count": 1562,"preSum": 57808 },{ "ndv": 995,"upper": 2032936705490195857,"lower": 1732069259803016485,"count": 1564,"preSum": 59370 },{ "ndv": 979,"upper": 2326247533596242869,"lower": 2033329708446977153,"count": 1563,"preSum": 60934 },{ "ndv": 959,"upper": 2599395117694496397,"lower": 2326657630256408017,"count": 1563,"preSum": 62497 },{ "ndv": 991,"upper": 2900207794012340689,"lower": 2599617877064126337,"count": 1562,"preSum": 64060 },{ "ndv": 987,"upper": 3189603177437229154,"lower": 2900235803545869503,"count": 1563,"preSum": 65622 },{ "ndv": 1005,"upper": 3466305078960912793,"lower": 3189678376842742472,"count": 1563,"preSum": 67185 },{ "ndv": 997,"upper": 3748639294042867377,"lower": 3466463443751822382,"count": 1562,"preSum": 68748 },{ "ndv": 1009,"upper": 4045900804832603324,"lower": 3748960732559814083,"count": 1562,"preSum": 70310 },{ "ndv": 1009,"upper": 4344431874025830765,"lower": 4045949775924867578,"count": 1563,"preSum": 71872 },{ "ndv": 988,"upper": 4638196035864790616,"lower": 4345009076246153201,"count": 1562,"preSum": 73435 },{ "ndv": 994,"upper": 4944116281860849910,"lower": 4638823964823667617,"count": 1562,"preSum": 74997 },{ "ndv": 969,"upper": 5231698846650469388,"lower": 4944165336651832704,"count": 1562,"preSum": 76559 },{ "ndv": 997,"upper": 5523908491842344986,"lower": 5231818855412248894,"count": 1562,"preSum": 78121 },{ "ndv": 981,"upper": 5804610566785176119,"lower": 5524111479999940640,"count": 1562,"preSum": 79683 },{ "ndv": 1002,"upper": 6099658477177476090,"lower": 5804726788198338959,"count": 1564,"preSum": 81245 },{ "ndv": 974,"upper": 6384757757508310454,"lower": 6100027216548278420,"count": 1564,"preSum": 82809 },{ "ndv": 981,"upper": 6683598916728893651,"lower": 6385320649890775146,"count": 1562,"preSum": 84373 },{ "ndv": 990,"upper": 6967851413342251172,"lower": 6683675949386287849,"count": 1562,"preSum": 85935 },{ "ndv": 961,"upper": 7244011662175329458,"lower": 6968012614441058684,"count": 1563,"preSum": 87497 },{ "ndv": 998,"upper": 7534768721890628552,"lower": 7244119637768392040,"count": 1563,"preSum": 89060 },{ "ndv": 980,"upper": 7829821680269365646,"lower": 7535170687427517096,"count": 1562,"preSum": 90623 },{ "ndv": 964,"upper": 8103561053582658750,"lower": 7830323587564297823,"count": 1563,"preSum": 92185 },{ "ndv": 983,"upper": 8380697517274768086,"lower": 8104166842624602828,"count": 1563,"preSum": 93748 },{ "ndv": 971,"upper": 8663964718733504185,"lower": 8381374097397087649,"count": 1562,"preSum": 95311 },{ "ndv": 1004,"upper": 8946431649187521322,"lower": 8664843373172145036,"count": 1562,"preSum": 96873 },{ "ndv": 951,"upper": 9223368416646677796,"lower": 8946495955711455132,"count": 1480,"preSum": 98435 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_bigint_1.null_count:
+    0
+  cest_full_table_big.c_bigint_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_bigint_64.TOPN:
+    { "countArr": [ 11,9,9,10,11 ],"valueArr": [ -2139856704982564776,3604401462128241404,5895609790243533074,6384367082947171809,8141441578623813109 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_bigint_64.cardinality:
+    507720
+  cest_full_table_big.c_bigint_64.histogram:
+    { "buckets": [ { "ndv": 974,"upper": -8927652724343991035,"lower": -9221953023920127215,"count": 1562,"preSum": 0 },{ "ndv": 957,"upper": -8645377269407381398,"lower": -8927626395656871171,"count": 1562,"preSum": 1562 },{ "ndv": 1001,"upper": -8357482973612175818,"lower": -8645025410541154150,"count": 1562,"preSum": 3124 },{ "ndv": 963,"upper": -8071163862868158255,"lower": -8357399745597816913,"count": 1563,"preSum": 4686 },{ "ndv": 947,"upper": -7801304497065031829,"lower": -8070754093745276790,"count": 1562,"preSum": 6249 },{ "ndv": 982,"upper": -7523111844037817506,"lower": -7801079253921539712,"count": 1562,"preSum": 7811 },{ "ndv": 945,"upper": -7224945841412218120,"lower": -7522491706882582664,"count": 1562,"preSum": 9373 },{ "ndv": 995,"upper": -6932928303864761465,"lower": -7224785332881895610,"count": 1562,"preSum": 10935 },{ "ndv": 966,"upper": -6633032474716097388,"lower": -6932777725893798434,"count": 1562,"preSum": 12497 },{ "ndv": 991,"upper": -6338962830680978647,"lower": -6632952602866611368,"count": 1562,"preSum": 14059 },{ "ndv": 984,"upper": -6049666523782641271,"lower": -6338820433510408773,"count": 1563,"preSum": 15621 },{ "ndv": 985,"upper": -5767030579201038752,"lower": -6048526935521097555,"count": 1562,"preSum": 17184 },{ "ndv": 975,"upper": -5486778587757501916,"lower": -5766496232027761237,"count": 1563,"preSum": 18746 },{ "ndv": 982,"upper": -5195097482955811760,"lower": -5486645638968993348,"count": 1562,"preSum": 20309 },{ "ndv": 976,"upper": -4902039972138417389,"lower": -5194479412016387267,"count": 1563,"preSum": 21871 },{ "ndv": 976,"upper": -4635035793469966235,"lower": -4901998951985754401,"count": 1562,"preSum": 23434 },{ "ndv": 967,"upper": -4343734941873064980,"lower": -4634995718672950716,"count": 1562,"preSum": 24996 },{ "ndv": 971,"upper": -4064214794213234450,"lower": -4342573435506866753,"count": 1562,"preSum": 26558 },{ "ndv": 976,"upper": -3784216762723187176,"lower": -4064094323026008352,"count": 1562,"preSum": 28120 },{ "ndv": 1003,"upper": -3490063651182759733,"lower": -3784166997837250680,"count": 1563,"preSum": 29682 },{ "ndv": 956,"upper": -3210391855701750124,"lower": -3489815654062641151,"count": 1562,"preSum": 31245 },{ "ndv": 989,"upper": -2924551650030569848,"lower": -3210277999615960835,"count": 1562,"preSum": 32807 },{ "ndv": 969,"upper": -2631889191589542345,"lower": -2924235065092792431,"count": 1562,"preSum": 34369 },{ "ndv": 992,"upper": -2331124480461480735,"lower": -2631838183991566611,"count": 1562,"preSum": 35931 },{ "ndv": 1006,"upper": -2028804414273433010,"lower": -2331121738021200846,"count": 1562,"preSum": 37493 },{ "ndv": 952,"upper": -1752505327032626946,"lower": -2028625588226558123,"count": 1562,"preSum": 39055 },{ "ndv": 961,"upper": -1464823780554854666,"lower": -1752305527592966287,"count": 1564,"preSum": 40617 },{ "ndv": 989,"upper": -1170518052089825006,"lower": -1464720541236534307,"count": 1565,"preSum": 42181 },{ "ndv": 979,"upper": -887539743230306985,"lower": -1170110354477136381,"count": 1562,"preSum": 43746 },{ "ndv": 963,"upper": -618671002352385657,"lower": -887380669048133633,"count": 1564,"preSum": 45308 },{ "ndv": 978,"upper": -339779468330121399,"lower": -618449293753472813,"count": 1562,"preSum": 46872 },{ "ndv": 982,"upper": -51190505142903525,"lower": -339641946093281022,"count": 1563,"preSum": 48434 },{ "ndv": 967,"upper": 245034521167601632,"lower": -51121299341228867,"count": 1562,"preSum": 49997 },{ "ndv": 969,"upper": 531972614665271851,"lower": 245528587755148298,"count": 1562,"preSum": 51559 },{ "ndv": 980,"upper": 834570659374192796,"lower": 532234255208282424,"count": 1562,"preSum": 53121 },{ "ndv": 978,"upper": 1125291162926658849,"lower": 834602870654686463,"count": 1562,"preSum": 54683 },{ "ndv": 968,"upper": 1416834335347697711,"lower": 1126498666922816046,"count": 1564,"preSum": 56245 },{ "ndv": 974,"upper": 1708351694030344908,"lower": 1417465801344927021,"count": 1562,"preSum": 57809 },{ "ndv": 973,"upper": 2014740113807020384,"lower": 1708713415351951727,"count": 1562,"preSum": 59371 },{ "ndv": 947,"upper": 2306214426255473950,"lower": 2014798145582240824,"count": 1562,"preSum": 60933 },{ "ndv": 960,"upper": 2583890310137764084,"lower": 2306687122755612056,"count": 1563,"preSum": 62495 },{ "ndv": 1000,"upper": 2888725916247312801,"lower": 2584419043930102348,"count": 1562,"preSum": 64058 },{ "ndv": 983,"upper": 3181085200360805576,"lower": 2889873977121670667,"count": 1562,"preSum": 65620 },{ "ndv": 947,"upper": 3453576748211652303,"lower": 3181205136028523299,"count": 1564,"preSum": 67182 },{ "ndv": 979,"upper": 3726999859958230969,"lower": 3453702161231164603,"count": 1562,"preSum": 68746 },{ "ndv": 965,"upper": 4021525841481259504,"lower": 3727100714871809343,"count": 1562,"preSum": 70308 },{ "ndv": 965,"upper": 4308977407949652679,"lower": 4021567027175024161,"count": 1562,"preSum": 71870 },{ "ndv": 969,"upper": 4592963815714766171,"lower": 4309098545058768256,"count": 1565,"preSum": 73432 },{ "ndv": 933,"upper": 4868560980107919099,"lower": 4593246952544232442,"count": 1563,"preSum": 74997 },{ "ndv": 974,"upper": 5161688584651565371,"lower": 4868702937838814306,"count": 1562,"preSum": 76560 },{ "ndv": 1015,"upper": 5467786254106652615,"lower": 5161747802209442774,"count": 1562,"preSum": 78122 },{ "ndv": 953,"upper": 5758009387669823829,"lower": 5467900057526414914,"count": 1564,"preSum": 79684 },{ "ndv": 952,"upper": 6047173272322026182,"lower": 5758157582495916503,"count": 1563,"preSum": 81248 },{ "ndv": 963,"upper": 6323937186291356159,"lower": 6047578614464235417,"count": 1562,"preSum": 82811 },{ "ndv": 973,"upper": 6620279004340986701,"lower": 6324082993966485591,"count": 1562,"preSum": 84373 },{ "ndv": 994,"upper": 6907303486686254686,"lower": 6620672258935052639,"count": 1562,"preSum": 85935 },{ "ndv": 1003,"upper": 7201907485813775722,"lower": 6907530072799722514,"count": 1562,"preSum": 87497 },{ "ndv": 983,"upper": 7488695778476717378,"lower": 7202414871973059255,"count": 1562,"preSum": 89059 },{ "ndv": 986,"upper": 7783479751010090542,"lower": 7488737058134285018,"count": 1564,"preSum": 90621 },{ "ndv": 960,"upper": 8075703067812911185,"lower": 7783627772132782912,"count": 1562,"preSum": 92185 },{ "ndv": 975,"upper": 8371810814678495132,"lower": 8076044346743846592,"count": 1562,"preSum": 93747 },{ "ndv": 964,"upper": 8660192452159111802,"lower": 8372011850341689619,"count": 1562,"preSum": 95309 },{ "ndv": 967,"upper": 8937066045403710355,"lower": 8660396494288787560,"count": 1563,"preSum": 96871 },{ "ndv": 945,"upper": 9223368416646677796,"lower": 8937108356296816145,"count": 1517,"preSum": 98434 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_bigint_64.null_count:
+    0
+  cest_full_table_big.c_bigint_64.sample_rate:
+    0.010943651
+  cest_full_table_big.c_bigint_64_un.TOPN:
+    { "countArr": [ 46,30,23,23,68,39,26,32,37,31,28,23,24,22 ],"valueArr": [ 1087415032127319091,2205333288883142026,2308903691487232314,4334470004175531145,4865701636426374745,5117146957233732947,5895609790243533074,6062398447322397185,6453287398387609666,7717652110091062802,7948952639898675160,8064225747288595905,8141441578623813109,8814454888702235556 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_bigint_64_un.cardinality:
+    481649
+  cest_full_table_big.c_bigint_64_un.histogram:
+    { "buckets": [ { "ndv": 884,"upper": 143377523619721811,"lower": 48763137239300,"count": 1556,"preSum": 0 },{ "ndv": 910,"upper": 278960979219336984,"lower": 143385790312369667,"count": 1557,"preSum": 1556 },{ "ndv": 896,"upper": 422481661680937196,"lower": 278978069770671518,"count": 1558,"preSum": 3113 },{ "ndv": 927,"upper": 571002079246882457,"lower": 422490326292301016,"count": 1556,"preSum": 4671 },{ "ndv": 917,"upper": 710397180378655937,"lower": 571100093057756793,"count": 1557,"preSum": 6227 },{ "ndv": 875,"upper": 856240586300382824,"lower": 710406670071220563,"count": 1559,"preSum": 7784 },{ "ndv": 910,"upper": 1001325815362217438,"lower": 856326990306782999,"count": 1556,"preSum": 9343 },{ "ndv": 906,"upper": 1133889128214770304,"lower": 1001424214832296359,"count": 1556,"preSum": 10899 },{ "ndv": 913,"upper": 1280492970288967986,"lower": 1134219074404788743,"count": 1556,"preSum": 12455 },{ "ndv": 923,"upper": 1424443687254168158,"lower": 1280536135210107024,"count": 1556,"preSum": 14011 },{ "ndv": 921,"upper": 1570369751549112190,"lower": 1424759401696924147,"count": 1557,"preSum": 15567 },{ "ndv": 913,"upper": 1713505058205858015,"lower": 1570372282640251292,"count": 1558,"preSum": 17124 },{ "ndv": 913,"upper": 1860763515744064094,"lower": 1713664450679998847,"count": 1556,"preSum": 18682 },{ "ndv": 892,"upper": 2005758496573551087,"lower": 1860821526087774653,"count": 1556,"preSum": 20238 },{ "ndv": 939,"upper": 2153185515065391758,"lower": 2005807777991284473,"count": 1556,"preSum": 21794 },{ "ndv": 921,"upper": 2296967325801289082,"lower": 2153463132978324890,"count": 1556,"preSum": 23350 },{ "ndv": 914,"upper": 2439910797737537444,"lower": 2297078372560990054,"count": 1556,"preSum": 24906 },{ "ndv": 899,"upper": 2578309608929371819,"lower": 2439970236514597673,"count": 1560,"preSum": 26462 },{ "ndv": 915,"upper": 2722157710924967763,"lower": 2578458336108821504,"count": 1556,"preSum": 28022 },{ "ndv": 966,"upper": 2875832933937672621,"lower": 2722489815856241916,"count": 1556,"preSum": 29578 },{ "ndv": 909,"upper": 3018990177152731392,"lower": 2875904160566482321,"count": 1557,"preSum": 31134 },{ "ndv": 953,"upper": 3172565256796861719,"lower": 3019071324435221576,"count": 1556,"preSum": 32691 },{ "ndv": 909,"upper": 3310379546667968991,"lower": 3172583056621813908,"count": 1556,"preSum": 34247 },{ "ndv": 915,"upper": 3456410952154959009,"lower": 3310489134269323687,"count": 1556,"preSum": 35803 },{ "ndv": 915,"upper": 3592078775692058317,"lower": 3456728230672968593,"count": 1557,"preSum": 37359 },{ "ndv": 906,"upper": 3728411275616190674,"lower": 3592191727706987198,"count": 1556,"preSum": 38916 },{ "ndv": 936,"upper": 3868141116051374336,"lower": 3728476038328611867,"count": 1560,"preSum": 40472 },{ "ndv": 920,"upper": 4016137179277765472,"lower": 3868162460822064573,"count": 1558,"preSum": 42032 },{ "ndv": 908,"upper": 4157136919545294989,"lower": 4016265401698310826,"count": 1556,"preSum": 43590 },{ "ndv": 912,"upper": 4297295899841478402,"lower": 4157195099505157168,"count": 1556,"preSum": 45146 },{ "ndv": 924,"upper": 4438445496415010361,"lower": 4297338045176787786,"count": 1556,"preSum": 46702 },{ "ndv": 938,"upper": 4586617466945791923,"lower": 4438710085756478322,"count": 1564,"preSum": 48258 },{ "ndv": 947,"upper": 4733894406450754828,"lower": 4586705939535379448,"count": 1556,"preSum": 49822 },{ "ndv": 909,"upper": 4871530266753000007,"lower": 4733960083903262756,"count": 1556,"preSum": 51378 },{ "ndv": 945,"upper": 5029156725544930304,"lower": 4871760827818674555,"count": 1559,"preSum": 52934 },{ "ndv": 934,"upper": 5178592058910890967,"lower": 5029525773577266910,"count": 1559,"preSum": 54493 },{ "ndv": 918,"upper": 5326292209784721061,"lower": 5178607350840304529,"count": 1556,"preSum": 56052 },{ "ndv": 957,"upper": 5482290778155050178,"lower": 5326303098111382594,"count": 1557,"preSum": 57608 },{ "ndv": 918,"upper": 5625922138218461838,"lower": 5482356166425261076,"count": 1556,"preSum": 59165 },{ "ndv": 894,"upper": 5764488275573736873,"lower": 5626062356027442354,"count": 1557,"preSum": 60721 },{ "ndv": 912,"upper": 5914251657147044094,"lower": 5764494083989547798,"count": 1556,"preSum": 62278 },{ "ndv": 932,"upper": 6062346217045254294,"lower": 5914601855409356436,"count": 1557,"preSum": 63834 },{ "ndv": 934,"upper": 6205276567806062527,"lower": 6062803603034453082,"count": 1557,"preSum": 65391 },{ "ndv": 930,"upper": 6351731061576669929,"lower": 6205437903667178170,"count": 1557,"preSum": 66948 },{ "ndv": 903,"upper": 6491174946873541390,"lower": 6351816449475929255,"count": 1556,"preSum": 68505 },{ "ndv": 948,"upper": 6640948085671180476,"lower": 6491321911696706086,"count": 1556,"preSum": 70061 },{ "ndv": 933,"upper": 6787892547095806325,"lower": 6640949038969401276,"count": 1556,"preSum": 71617 },{ "ndv": 946,"upper": 6939238647275224531,"lower": 6788043195538016093,"count": 1558,"preSum": 73173 },{ "ndv": 951,"upper": 7089615225886080583,"lower": 6939445177801584002,"count": 1556,"preSum": 74731 },{ "ndv": 937,"upper": 7238428823910129839,"lower": 7089709620746364317,"count": 1556,"preSum": 76287 },{ "ndv": 922,"upper": 7386622925184515132,"lower": 7238713692628446857,"count": 1556,"preSum": 77843 },{ "ndv": 915,"upper": 7535888888824309201,"lower": 7386654043414518139,"count": 1556,"preSum": 79399 },{ "ndv": 919,"upper": 7681604746335359873,"lower": 7536090657654927705,"count": 1556,"preSum": 80955 },{ "ndv": 944,"upper": 7830242705068044791,"lower": 7681630263029259631,"count": 1556,"preSum": 82511 },{ "ndv": 912,"upper": 7962170075137872397,"lower": 7830323587564297823,"count": 1557,"preSum": 84067 },{ "ndv": 874,"upper": 8104770429408762642,"lower": 7962308988243478983,"count": 1556,"preSum": 85624 },{ "ndv": 915,"upper": 8239992543374518734,"lower": 8104842357604407276,"count": 1558,"preSum": 87180 },{ "ndv": 920,"upper": 8373870773188886278,"lower": 8240018739885202418,"count": 1559,"preSum": 88738 },{ "ndv": 929,"upper": 8521614543274947002,"lower": 8373938387502758943,"count": 1562,"preSum": 90297 },{ "ndv": 909,"upper": 8662816396873233441,"lower": 8521625759312967401,"count": 1556,"preSum": 91859 },{ "ndv": 915,"upper": 8806478312334200916,"lower": 8663201177912903052,"count": 1556,"preSum": 93415 },{ "ndv": 928,"upper": 8949846182062769226,"lower": 8806540315290452943,"count": 1556,"preSum": 94971 },{ "ndv": 913,"upper": 9091397889701681890,"lower": 8949864789900045536,"count": 1556,"preSum": 96527 },{ "ndv": 879,"upper": 9223368416646677796,"lower": 9091452900128267010,"count": 1466,"preSum": 98083 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_bigint_64_un.null_count:
+    0
+  cest_full_table_big.c_bigint_64_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_char.TOPN:
+    { "countArr": [ 45,50,154,110,52,52,62,80,52,43,63,80,73 ],"valueArr": [ "150e33107d","322e0ed9c2","34d9c309ae","5bf106c3d9","5ee951d192","61367328af","716a1a9e0a","7bd0172e8f","8b4283c7d3","8bbeb466cd","b556d066bd","b5c6978fb3","c477a1d481" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_char.cardinality:
+    462831
+  cest_full_table_big.c_char.histogram:
+    { "buckets": [ { "ndv": 876,"upper": "0405fc807d","lower": "000048feb9","count": 1550,"preSum": 0 },{ "ndv": 873,"upper": "07d86ec9c3","lower": "04061ddbde","count": 1549,"preSum": 1550 },{ "ndv": 883,"upper": "0bba872b40","lower": "07d8a6e17d","count": 1553,"preSum": 3099 },{ "ndv": 851,"upper": "0f8552964f","lower": "0bbbc0aba3","count": 1550,"preSum": 4652 },{ "ndv": 823,"upper": "1353f0a4c2","lower": "0f85a9c567","count": 1549,"preSum": 6202 },{ "ndv": 865,"upper": "176269ef41","lower": "135426bf4c","count": 1559,"preSum": 7751 },{ "ndv": 880,"upper": "1b6e924452","lower": "17646390fa","count": 1550,"preSum": 9310 },{ "ndv": 863,"upper": "1f4b57f199","lower": "1b70368d34","count": 1553,"preSum": 10860 },{ "ndv": 904,"upper": "237c2d96e5","lower": "1f551aea58","count": 1549,"preSum": 12413 },{ "ndv": 823,"upper": "2741c6a9ed","lower": "237de85e8e","count": 1549,"preSum": 13962 },{ "ndv": 888,"upper": "2b0aaef93e","lower": "274291fe50","count": 1550,"preSum": 15511 },{ "ndv": 877,"upper": "2f2f76a7ad","lower": "2b0ab2732c","count": 1549,"preSum": 17061 },{ "ndv": 906,"upper": "3334172ee9","lower": "2f2fcf938b","count": 1549,"preSum": 18610 },{ "ndv": 870,"upper": "372241e487","lower": "3337fdfac2","count": 1549,"preSum": 20159 },{ "ndv": 831,"upper": "3af3873033","lower": "372277971a","count": 1549,"preSum": 21708 },{ "ndv": 895,"upper": "3f42485805","lower": "3af3a48b97","count": 1549,"preSum": 23257 },{ "ndv": 913,"upper": "435a8cc58f","lower": "3f430cc0c2","count": 1549,"preSum": 24806 },{ "ndv": 847,"upper": "475fc56ed6","lower": "435bd74ceb","count": 1550,"preSum": 26355 },{ "ndv": 884,"upper": "4bc9a76292","lower": "47611ff4da","count": 1551,"preSum": 27905 },{ "ndv": 861,"upper": "4fe4266ae0","lower": "4bca6ee704","count": 1549,"preSum": 29456 },{ "ndv": 896,"upper": "53cedf2291","lower": "4fe429a3b5","count": 1552,"preSum": 31005 },{ "ndv": 893,"upper": "57dbd94fd1","lower": "53cf7f9d1f","count": 1549,"preSum": 32557 },{ "ndv": 888,"upper": "5bd6f342c7","lower": "57dde82542","count": 1572,"preSum": 34106 },{ "ndv": 896,"upper": "60124e4e44","lower": "5bd7574264","count": 1549,"preSum": 35678 },{ "ndv": 839,"upper": "63f899fb01","lower": "60126193bf","count": 1551,"preSum": 37227 },{ "ndv": 899,"upper": "67fec64646","lower": "63fa5cb511","count": 1551,"preSum": 38778 },{ "ndv": 858,"upper": "6bf7c2f383","lower": "67fec7b8b0","count": 1549,"preSum": 40329 },{ "ndv": 892,"upper": "700d0fec91","lower": "6bfd69afd0","count": 1549,"preSum": 41878 },{ "ndv": 880,"upper": "743b9adc51","lower": "700df27f46","count": 1549,"preSum": 43427 },{ "ndv": 874,"upper": "78101d75af","lower": "743bf7af56","count": 1549,"preSum": 44976 },{ "ndv": 878,"upper": "7c0e99eaf9","lower": "78104cbb6a","count": 1551,"preSum": 46525 },{ "ndv": 931,"upper": "80844b8282","lower": "7c105a60e9","count": 1549,"preSum": 48076 },{ "ndv": 856,"upper": "8456ccf69a","lower": "8084d5cab2","count": 1549,"preSum": 49625 },{ "ndv": 847,"upper": "882ee64180","lower": "8459dce4f4","count": 1551,"preSum": 51174 },{ "ndv": 887,"upper": "8bfa54082d","lower": "882f02e256","count": 1550,"preSum": 52725 },{ "ndv": 864,"upper": "900fe1d0fa","lower": "8bfa86f172","count": 1549,"preSum": 54275 },{ "ndv": 881,"upper": "9418d3cd43","lower": "901134d92c","count": 1550,"preSum": 55824 },{ "ndv": 889,"upper": "982d7b1b66","lower": "9419421896","count": 1550,"preSum": 57374 },{ "ndv": 853,"upper": "9c4299731f","lower": "982ef9e0ad","count": 1549,"preSum": 58924 },{ "ndv": 892,"upper": "a0485a33b2","lower": "9c42a93785","count": 1551,"preSum": 60473 },{ "ndv": 864,"upper": "a437323744","lower": "a048f2d4e2","count": 1557,"preSum": 62024 },{ "ndv": 893,"upper": "a805bfad12","lower": "a4373ddbff","count": 1549,"preSum": 63581 },{ "ndv": 884,"upper": "ac1a35c93f","lower": "a80615a7ca","count": 1549,"preSum": 65130 },{ "ndv": 876,"upper": "b03389efea","lower": "ac1a7da36c","count": 1550,"preSum": 66679 },{ "ndv": 877,"upper": "b46bf37e8b","lower": "b034c7bbcb","count": 1549,"preSum": 68229 },{ "ndv": 876,"upper": "b87590d633","lower": "b46bf7bcc5","count": 1549,"preSum": 69778 },{ "ndv": 857,"upper": "bc7e4a1826","lower": "b876b99639","count": 1549,"preSum": 71327 },{ "ndv": 858,"upper": "c0485d2fea","lower": "bc7e642804","count": 1549,"preSum": 72876 },{ "ndv": 896,"upper": "c47e297c8a","lower": "c048b01a4f","count": 1549,"preSum": 74425 },{ "ndv": 896,"upper": "c87a531faf","lower": "c47f57e5c8","count": 1549,"preSum": 75974 },{ "ndv": 852,"upper": "cc59158712","lower": "c87de76837","count": 1549,"preSum": 77523 },{ "ndv": 821,"upper": "d030b5d7a0","lower": "cc5a14b6e5","count": 1553,"preSum": 79072 },{ "ndv": 873,"upper": "d40fd8f898","lower": "d03195ce25","count": 1549,"preSum": 80625 },{ "ndv": 897,"upper": "d839e65db7","lower": "d40fdf53b1","count": 1552,"preSum": 82174 },{ "ndv": 833,"upper": "dc1e43fd1c","lower": "d83ad1b8c9","count": 1550,"preSum": 83726 },{ "ndv": 863,"upper": "dfeefff295","lower": "dc1ef9ccf1","count": 1549,"preSum": 85276 },{ "ndv": 893,"upper": "e3d6459ddd","lower": "dff141088e","count": 1549,"preSum": 86825 },{ "ndv": 891,"upper": "e81307cc42","lower": "e3d67249dd","count": 1549,"preSum": 88374 },{ "ndv": 850,"upper": "ec20059941","lower": "e813d09eea","count": 1551,"preSum": 89923 },{ "ndv": 874,"upper": "f035ef2008","lower": "ec20912bb0","count": 1554,"preSum": 91474 },{ "ndv": 902,"upper": "f483943b70","lower": "f036799f11","count": 1549,"preSum": 93028 },{ "ndv": 865,"upper": "f825bdd07c","lower": "f48401ac6e","count": 1550,"preSum": 94577 },{ "ndv": 877,"upper": "fc60d801bb","lower": "f825eaad04","count": 1550,"preSum": 96127 },{ "ndv": 771,"upper": "ffffb91afe","lower": "fc60fe2ddf","count": 1408,"preSum": 97677 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_char.null_count:
+    0
+  cest_full_table_big.c_char.sample_rate:
+    0.010943651
+  cest_full_table_big.c_date.TOPN:
+    { "countArr": [ 314,313,318,320,317,315,334,322,319,313,331,317,315,314 ],"valueArr": [ 1849873338151731200,1849901925454053376,1849972294198231040,1850029468802875392,1850060255128453120,1850086643407519744,1850154813128441856,1850181201407508480,1850187798477275136,1850200992616808448,1850471472477241344,1850541841221419008,1850546239267930112,1850610010942341120 ],"type": "Date","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_date.cardinality:
+    365
+  cest_full_table_big.c_date.histogram:
+    { "buckets": [ { "ndv": 6,"upper": "1849796372337786880","lower": "1849785377221509120","count": 1652,"preSum": 0 },{ "ndv": 6,"upper": "1849809566477320192","lower": "1849798571361042432","count": 1665,"preSum": 1652 },{ "ndv": 6,"upper": "1849822760616853504","lower": "1849811765500575744","count": 1636,"preSum": 3317 },{ "ndv": 6,"upper": "1849835954756386816","lower": "1849824959640109056","count": 1558,"preSum": 4953 },{ "ndv": 6,"upper": "1849849148895920128","lower": "1849838153779642368","count": 1593,"preSum": 6511 },{ "ndv": 6,"upper": "1849864542058708992","lower": "1849851347919175680","count": 1675,"preSum": 8104 },{ "ndv": 6,"upper": "1849879935221497856","lower": "1849866741081964544","count": 1643,"preSum": 9779 },{ "ndv": 6,"upper": "1849893129361031168","lower": "1849882134244753408","count": 1699,"preSum": 11422 },{ "ndv": 6,"upper": "1849908522523820032","lower": "1849895328384286720","count": 1575,"preSum": 13121 },{ "ndv": 6,"upper": "1849930512756375552","lower": "1849910721547075584","count": 1631,"preSum": 14696 },{ "ndv": 6,"upper": "1849943706895908864","lower": "1849932711779631104","count": 1571,"preSum": 16327 },{ "ndv": 6,"upper": "1849956901035442176","lower": "1849945905919164416","count": 1639,"preSum": 17898 },{ "ndv": 6,"upper": "1849970095174975488","lower": "1849959100058697728","count": 1622,"preSum": 19537 },{ "ndv": 6,"upper": "1849985488337764352","lower": "1849974493221486592","count": 1616,"preSum": 21159 },{ "ndv": 6,"upper": "1850000881500553216","lower": "1849987687361019904","count": 1641,"preSum": 22775 },{ "ndv": 6,"upper": "1850014075640086528","lower": "1850003080523808768","count": 1599,"preSum": 24416 },{ "ndv": 6,"upper": "1850027269779619840","lower": "1850016274663342080","count": 1685,"preSum": 26015 },{ "ndv": 6,"upper": "1850042662942408704","lower": "1850031667826130944","count": 1634,"preSum": 27700 },{ "ndv": 6,"upper": "1850055857081942016","lower": "1850044861965664256","count": 1619,"preSum": 29334 },{ "ndv": 6,"upper": "1850075648291241984","lower": "1850058056105197568","count": 1580,"preSum": 30953 },{ "ndv": 6,"upper": "1850091041454030848","lower": "1850077847314497536","count": 1601,"preSum": 32533 },{ "ndv": 6,"upper": "1850104235593564160","lower": "1850093240477286400","count": 1617,"preSum": 34134 },{ "ndv": 6,"upper": "1850117429733097472","lower": "1850106434616819712","count": 1579,"preSum": 35751 },{ "ndv": 6,"upper": "1850130623872630784","lower": "1850119628756353024","count": 1616,"preSum": 37330 },{ "ndv": 6,"upper": "1850146017035419648","lower": "1850132822895886336","count": 1715,"preSum": 38946 },{ "ndv": 6,"upper": "1850161410198208512","lower": "1850148216058675200","count": 1709,"preSum": 40661 },{ "ndv": 6,"upper": "1850174604337741824","lower": "1850163609221464064","count": 1623,"preSum": 42370 },{ "ndv": 6,"upper": "1850192196523786240","lower": "1850176803360997376","count": 1658,"preSum": 43993 },{ "ndv": 6,"upper": "1850211987733086208","lower": "1850194395547041792","count": 1638,"preSum": 45651 },{ "ndv": 6,"upper": "1850225181872619520","lower": "1850214186756341760","count": 1586,"preSum": 47289 },{ "ndv": 6,"upper": "1850238376012152832","lower": "1850227380895875072","count": 1697,"preSum": 48875 },{ "ndv": 6,"upper": "1850251570151686144","lower": "1850240575035408384","count": 1575,"preSum": 50572 },{ "ndv": 6,"upper": "1850264764291219456","lower": "1850253769174941696","count": 1588,"preSum": 52147 },{ "ndv": 6,"upper": "1850280157454008320","lower": "1850266963314475008","count": 1631,"preSum": 53735 },{ "ndv": 6,"upper": "1850293351593541632","lower": "1850282356477263872","count": 1693,"preSum": 55366 },{ "ndv": 6,"upper": "1850306545733074944","lower": "1850295550616797184","count": 1651,"preSum": 57059 },{ "ndv": 6,"upper": "1850319739872608256","lower": "1850308744756330496","count": 1635,"preSum": 58710 },{ "ndv": 6,"upper": "1850332934012141568","lower": "1850321938895863808","count": 1601,"preSum": 60345 },{ "ndv": 6,"upper": "1850348327174930432","lower": "1850335133035397120","count": 1597,"preSum": 61946 },{ "ndv": 6,"upper": "1850361521314463744","lower": "1850350526198185984","count": 1716,"preSum": 63543 },{ "ndv": 6,"upper": "1850374715453997056","lower": "1850363720337719296","count": 1713,"preSum": 65259 },{ "ndv": 6,"upper": "1850387909593530368","lower": "1850376914477252608","count": 1718,"preSum": 66972 },{ "ndv": 6,"upper": "1850401103733063680","lower": "1850390108616785920","count": 1585,"preSum": 68690 },{ "ndv": 6,"upper": "1850418695919108096","lower": "1850403302756319232","count": 1650,"preSum": 70275 },{ "ndv": 6,"upper": "1850431890058641408","lower": "1850420894942363648","count": 1694,"preSum": 71925 },{ "ndv": 6,"upper": "1850445084198174720","lower": "1850434089081896960","count": 1663,"preSum": 73619 },{ "ndv": 6,"upper": "1850458278337708032","lower": "1850447283221430272","count": 1549,"preSum": 75282 },{ "ndv": 6,"upper": "1850473671500496896","lower": "1850460477360963584","count": 1656,"preSum": 76831 },{ "ndv": 6,"upper": "1850489064663285760","lower": "1850475870523752448","count": 1607,"preSum": 78487 },{ "ndv": 6,"upper": "1850502258802819072","lower": "1850491263686541312","count": 1640,"preSum": 80094 },{ "ndv": 6,"upper": "1850515452942352384","lower": "1850504457826074624","count": 1600,"preSum": 81734 },{ "ndv": 6,"upper": "1850528647081885696","lower": "1850517651965607936","count": 1637,"preSum": 83334 },{ "ndv": 6,"upper": "1850544040244674560","lower": "1850530846105141248","count": 1577,"preSum": 84971 },{ "ndv": 6,"upper": "1850563831453974528","lower": "1850548438291185664","count": 1639,"preSum": 86548 },{ "ndv": 6,"upper": "1850577025593507840","lower": "1850566030477230080","count": 1626,"preSum": 88187 },{ "ndv": 6,"upper": "1850590219733041152","lower": "1850579224616763392","count": 1662,"preSum": 89813 },{ "ndv": 6,"upper": "1850603413872574464","lower": "1850592418756296704","count": 1621,"preSum": 91475 },{ "ndv": 6,"upper": "1850618807035363328","lower": "1850605612895830016","count": 1704,"preSum": 93096 },{ "ndv": 3,"upper": "1850625404105129984","lower": "1850621006058618880","count": 739,"preSum": 94800 } ],"maxBucketSize": 64,"type": "Date","sampleRate": 0.90062594 }
+  cest_full_table_big.c_date.null_count:
+    0
+  cest_full_table_big.c_date.sample_rate:
+    0.010943651
+  cest_full_table_big.c_datetime.TOPN:
+    { "countArr": [ 7,8,7,7,8,7,7 ],"valueArr": [ 1849856379473362944,1849966883126640640,1850096458666082304,1850112028845277184,1850159979386896384,1850408374944923648,1850600075777015808 ],"type": "Datetime","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_datetime.cardinality:
+    515198
+  cest_full_table_big.c_datetime.histogram:
+    { "buckets": [ { "ndv": 988,"upper": "1849797349442846720","lower": "1849785388378357760","count": 1563,"preSum": 0 },{ "ndv": 994,"upper": "1849810007432888320","lower": "1849797352949284864","count": 1563,"preSum": 1563 },{ "ndv": 998,"upper": "1849822169907855360","lower": "1849810009664258048","count": 1562,"preSum": 3126 },{ "ndv": 993,"upper": "1849835987757170688","lower": "1849822185108013056","count": 1564,"preSum": 4688 },{ "ndv": 1004,"upper": "1849848516512317440","lower": "1849835990038872064","count": 1562,"preSum": 6252 },{ "ndv": 990,"upper": "1849863290562281472","lower": "1849848521394487296","count": 1562,"preSum": 7814 },{ "ndv": 976,"upper": "1849875556552671232","lower": "1849863306248978432","count": 1565,"preSum": 9376 },{ "ndv": 1011,"upper": "1849887891413532672","lower": "1849875561652944896","count": 1562,"preSum": 10941 },{ "ndv": 1007,"upper": "1849900578210054144","lower": "1849887894282436608","count": 1562,"preSum": 12503 },{ "ndv": 960,"upper": "1849912344541396992","lower": "1849900608560037888","count": 1562,"preSum": 14065 },{ "ndv": 1006,"upper": "1849934999990566912","lower": "1849912352191807488","count": 1562,"preSum": 15627 },{ "ndv": 989,"upper": "1849947243063279616","lower": "1849935035474378752","count": 1562,"preSum": 17189 },{ "ndv": 995,"upper": "1849960156536766464","lower": "1849947243667259392","count": 1562,"preSum": 18751 },{ "ndv": 996,"upper": "1849972736445644800","lower": "1849960173850853376","count": 1563,"preSum": 20313 },{ "ndv": 990,"upper": "1849985731322183680","lower": "1849972736663748608","count": 1563,"preSum": 21876 },{ "ndv": 1007,"upper": "1850000072838742016","lower": "1849985735147388928","count": 1562,"preSum": 23439 },{ "ndv": 984,"upper": "1850012695227531264","lower": "1850000073291726848","count": 1562,"preSum": 25001 },{ "ndv": 989,"upper": "1850025523472760832","lower": "1850012707474898944","count": 1562,"preSum": 26563 },{ "ndv": 961,"upper": "1850037400969936896","lower": "1850025536441548800","count": 1562,"preSum": 28125 },{ "ndv": 1022,"upper": "1850049990894813184","lower": "1850037414257491968","count": 1562,"preSum": 29687 },{ "ndv": 980,"upper": "1850067127914987520","lower": "1850049995558879232","count": 1562,"preSum": 31249 },{ "ndv": 959,"upper": "1850079478009561088","lower": "1850067137998094336","count": 1564,"preSum": 32811 },{ "ndv": 986,"upper": "1850092294141640704","lower": "1850080048921444352","count": 1562,"preSum": 34375 },{ "ndv": 969,"upper": "1850105086299078656","lower": "1850092315482259456","count": 1562,"preSum": 35937 },{ "ndv": 994,"upper": "1850118003564216320","lower": "1850105099469193216","count": 1562,"preSum": 37499 },{ "ndv": 970,"upper": "1850130906283507712","lower": "1850118004688289792","count": 1564,"preSum": 39061 },{ "ndv": 969,"upper": "1850145197317423104","lower": "1850130906535165952","count": 1562,"preSum": 40625 },{ "ndv": 990,"upper": "1850157220558274560","lower": "1850145197401309184","count": 1562,"preSum": 42187 },{ "ndv": 986,"upper": "1850169175700406272","lower": "1850157232872751104","count": 1562,"preSum": 43749 },{ "ndv": 985,"upper": "1850181877176991744","lower": "1850169189642272768","count": 1562,"preSum": 45311 },{ "ndv": 974,"upper": "1850193542475939840","lower": "1850181915093499904","count": 1562,"preSum": 46873 },{ "ndv": 991,"upper": "1850210275685302272","lower": "1850193559622254592","count": 1562,"preSum": 48435 },{ "ndv": 981,"upper": "1850223335640662016","lower": "1850210280517140480","count": 1562,"preSum": 49997 },{ "ndv": 962,"upper": "1850235437096894464","lower": "1850223338979328000","count": 1562,"preSum": 51559 },{ "ndv": 1005,"upper": "1850248266667524096","lower": "1850235446408249344","count": 1562,"preSum": 53121 },{ "ndv": 1005,"upper": "1850261234734071808","lower": "1850248286884069376","count": 1562,"preSum": 54683 },{ "ndv": 1017,"upper": "1850274085242667008","lower": "1850261236898332672","count": 1562,"preSum": 56245 },{ "ndv": 994,"upper": "1850288998493192192","lower": "1850274121951215616","count": 1564,"preSum": 57807 },{ "ndv": 971,"upper": "1850300960866304000","lower": "1850289004633653248","count": 1562,"preSum": 59371 },{ "ndv": 1023,"upper": "1850313627177844736","lower": "1850300970462871552","count": 1562,"preSum": 60933 },{ "ndv": 998,"upper": "1850326463392251904","lower": "1850313636052992000","count": 1562,"preSum": 62495 },{ "ndv": 972,"upper": "1850338940792340480","lower": "1850326481276764160","count": 1563,"preSum": 64057 },{ "ndv": 1005,"upper": "1850354048759234560","lower": "1850338942033854464","count": 1562,"preSum": 65620 },{ "ndv": 962,"upper": "1850366065406640128","lower": "1850354053993725952","count": 1563,"preSum": 67182 },{ "ndv": 968,"upper": "1850378032846471168","lower": "1850366074164346880","count": 1562,"preSum": 68745 },{ "ndv": 976,"upper": "1850390280918794240","lower": "1850378070209331200","count": 1562,"preSum": 70307 },{ "ndv": 990,"upper": "1850403330036072448","lower": "1850390285616414720","count": 1562,"preSum": 71869 },{ "ndv": 974,"upper": "1850419937953185792","lower": "1850403335538999296","count": 1562,"preSum": 73431 },{ "ndv": 1028,"upper": "1850432499725893632","lower": "1850419941459623936","count": 1563,"preSum": 74993 },{ "ndv": 974,"upper": "1850444275922239488","lower": "1850432503752425472","count": 1562,"preSum": 76556 },{ "ndv": 994,"upper": "1850457377787084800","lower": "1850444281592938496","count": 1564,"preSum": 78118 },{ "ndv": 993,"upper": "1850470384005021696","lower": "1850457397701640192","count": 1562,"preSum": 79682 },{ "ndv": 989,"upper": "1850482957035241472","lower": "1850470398617976832","count": 1562,"preSum": 81244 },{ "ndv": 992,"upper": "1850497236643872768","lower": "1850482970490568704","count": 1562,"preSum": 82806 },{ "ndv": 986,"upper": "1850509872588652544","lower": "1850497246324326400","count": 1562,"preSum": 84368 },{ "ndv": 998,"upper": "1850522829548683264","lower": "1850509874081824768","count": 1562,"preSum": 85930 },{ "ndv": 972,"upper": "1850535566777516032","lower": "1850522844815949824","count": 1562,"preSum": 87492 },{ "ndv": 971,"upper": "1850547688936833024","lower": "1850535569277321216","count": 1563,"preSum": 89054 },{ "ndv": 988,"upper": "1850564802838003712","lower": "1850547693215023104","count": 1562,"preSum": 90617 },{ "ndv": 987,"upper": "1850577718693855232","lower": "1850564811948032000","count": 1562,"preSum": 92179 },{ "ndv": 986,"upper": "1850590382069383168","lower": "1850577720438685696","count": 1562,"preSum": 93741 },{ "ndv": 1006,"upper": "1850602489129205760","lower": "1850590384569188352","count": 1563,"preSum": 95303 },{ "ndv": 973,"upper": "1850614653063790592","lower": "1850602496645398528","count": 1562,"preSum": 96866 },{ "ndv": 977,"upper": "1850627048289075200","lower": "1850614685896802304","count": 1522,"preSum": 98428 } ],"maxBucketSize": 64,"type": "Datetime","sampleRate": 0.90062594 }
+  cest_full_table_big.c_datetime.null_count:
+    0
+  cest_full_table_big.c_datetime.sample_rate:
+    0.010943651
+  cest_full_table_big.c_datetime_1.TOPN:
+    { "countArr": [ 7,8,7,7,8,7,7 ],"valueArr": [ 1849856379473362944,1849966883126640640,1850096458666082304,1850112028845277184,1850159979386896384,1850408374944923648,1850600075777015808 ],"type": "Datetime","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_datetime_1.cardinality:
+    515198
+  cest_full_table_big.c_datetime_1.histogram:
+    { "buckets": [ { "ndv": 988,"upper": "1849797349442846720","lower": "1849785388378357760","count": 1563,"preSum": 0 },{ "ndv": 994,"upper": "1849810007432888320","lower": "1849797352949284864","count": 1563,"preSum": 1563 },{ "ndv": 998,"upper": "1849822169907855360","lower": "1849810009664258048","count": 1562,"preSum": 3126 },{ "ndv": 993,"upper": "1849835987757170688","lower": "1849822185108013056","count": 1564,"preSum": 4688 },{ "ndv": 1004,"upper": "1849848516512317440","lower": "1849835990038872064","count": 1562,"preSum": 6252 },{ "ndv": 990,"upper": "1849863290562281472","lower": "1849848521394487296","count": 1562,"preSum": 7814 },{ "ndv": 976,"upper": "1849875556552671232","lower": "1849863306248978432","count": 1565,"preSum": 9376 },{ "ndv": 1011,"upper": "1849887891413532672","lower": "1849875561652944896","count": 1562,"preSum": 10941 },{ "ndv": 1007,"upper": "1849900578210054144","lower": "1849887894282436608","count": 1562,"preSum": 12503 },{ "ndv": 960,"upper": "1849912344541396992","lower": "1849900608560037888","count": 1562,"preSum": 14065 },{ "ndv": 1006,"upper": "1849934999990566912","lower": "1849912352191807488","count": 1562,"preSum": 15627 },{ "ndv": 989,"upper": "1849947243063279616","lower": "1849935035474378752","count": 1562,"preSum": 17189 },{ "ndv": 995,"upper": "1849960156536766464","lower": "1849947243667259392","count": 1562,"preSum": 18751 },{ "ndv": 996,"upper": "1849972736445644800","lower": "1849960173850853376","count": 1563,"preSum": 20313 },{ "ndv": 990,"upper": "1849985731322183680","lower": "1849972736663748608","count": 1563,"preSum": 21876 },{ "ndv": 1007,"upper": "1850000072838742016","lower": "1849985735147388928","count": 1562,"preSum": 23439 },{ "ndv": 984,"upper": "1850012695227531264","lower": "1850000073291726848","count": 1562,"preSum": 25001 },{ "ndv": 989,"upper": "1850025523472760832","lower": "1850012707474898944","count": 1562,"preSum": 26563 },{ "ndv": 961,"upper": "1850037400969936896","lower": "1850025536441548800","count": 1562,"preSum": 28125 },{ "ndv": 1022,"upper": "1850049990894813184","lower": "1850037414257491968","count": 1562,"preSum": 29687 },{ "ndv": 980,"upper": "1850067127914987520","lower": "1850049995558879232","count": 1562,"preSum": 31249 },{ "ndv": 959,"upper": "1850079478009561088","lower": "1850067137998094336","count": 1564,"preSum": 32811 },{ "ndv": 986,"upper": "1850092294141640704","lower": "1850080048921444352","count": 1562,"preSum": 34375 },{ "ndv": 969,"upper": "1850105086299078656","lower": "1850092315482259456","count": 1562,"preSum": 35937 },{ "ndv": 994,"upper": "1850118003564216320","lower": "1850105099469193216","count": 1562,"preSum": 37499 },{ "ndv": 970,"upper": "1850130906283507712","lower": "1850118004688289792","count": 1564,"preSum": 39061 },{ "ndv": 969,"upper": "1850145197317423104","lower": "1850130906535165952","count": 1562,"preSum": 40625 },{ "ndv": 990,"upper": "1850157220558274560","lower": "1850145197401309184","count": 1562,"preSum": 42187 },{ "ndv": 986,"upper": "1850169175700406272","lower": "1850157232872751104","count": 1562,"preSum": 43749 },{ "ndv": 985,"upper": "1850181877176991744","lower": "1850169189642272768","count": 1562,"preSum": 45311 },{ "ndv": 974,"upper": "1850193542475939840","lower": "1850181915093499904","count": 1562,"preSum": 46873 },{ "ndv": 991,"upper": "1850210275685302272","lower": "1850193559622254592","count": 1562,"preSum": 48435 },{ "ndv": 981,"upper": "1850223335640662016","lower": "1850210280517140480","count": 1562,"preSum": 49997 },{ "ndv": 962,"upper": "1850235437096894464","lower": "1850223338979328000","count": 1562,"preSum": 51559 },{ "ndv": 1005,"upper": "1850248266667524096","lower": "1850235446408249344","count": 1562,"preSum": 53121 },{ "ndv": 1005,"upper": "1850261234734071808","lower": "1850248286884069376","count": 1562,"preSum": 54683 },{ "ndv": 1017,"upper": "1850274085242667008","lower": "1850261236898332672","count": 1562,"preSum": 56245 },{ "ndv": 994,"upper": "1850288998493192192","lower": "1850274121951215616","count": 1564,"preSum": 57807 },{ "ndv": 971,"upper": "1850300960866304000","lower": "1850289004633653248","count": 1562,"preSum": 59371 },{ "ndv": 1023,"upper": "1850313627177844736","lower": "1850300970462871552","count": 1562,"preSum": 60933 },{ "ndv": 998,"upper": "1850326463392251904","lower": "1850313636052992000","count": 1562,"preSum": 62495 },{ "ndv": 972,"upper": "1850338940792340480","lower": "1850326481276764160","count": 1563,"preSum": 64057 },{ "ndv": 1005,"upper": "1850354048759234560","lower": "1850338942033854464","count": 1562,"preSum": 65620 },{ "ndv": 962,"upper": "1850366065406640128","lower": "1850354053993725952","count": 1563,"preSum": 67182 },{ "ndv": 968,"upper": "1850378032846471168","lower": "1850366074164346880","count": 1562,"preSum": 68745 },{ "ndv": 976,"upper": "1850390280918794240","lower": "1850378070209331200","count": 1562,"preSum": 70307 },{ "ndv": 990,"upper": "1850403330036072448","lower": "1850390285616414720","count": 1562,"preSum": 71869 },{ "ndv": 974,"upper": "1850419937953185792","lower": "1850403335538999296","count": 1562,"preSum": 73431 },{ "ndv": 1028,"upper": "1850432499725893632","lower": "1850419941459623936","count": 1563,"preSum": 74993 },{ "ndv": 974,"upper": "1850444275922239488","lower": "1850432503752425472","count": 1562,"preSum": 76556 },{ "ndv": 994,"upper": "1850457377787084800","lower": "1850444281592938496","count": 1564,"preSum": 78118 },{ "ndv": 993,"upper": "1850470384005021696","lower": "1850457397701640192","count": 1562,"preSum": 79682 },{ "ndv": 989,"upper": "1850482957035241472","lower": "1850470398617976832","count": 1562,"preSum": 81244 },{ "ndv": 992,"upper": "1850497236643872768","lower": "1850482970490568704","count": 1562,"preSum": 82806 },{ "ndv": 986,"upper": "1850509872588652544","lower": "1850497246324326400","count": 1562,"preSum": 84368 },{ "ndv": 998,"upper": "1850522829548683264","lower": "1850509874081824768","count": 1562,"preSum": 85930 },{ "ndv": 972,"upper": "1850535566777516032","lower": "1850522844815949824","count": 1562,"preSum": 87492 },{ "ndv": 971,"upper": "1850547688936833024","lower": "1850535569277321216","count": 1563,"preSum": 89054 },{ "ndv": 988,"upper": "1850564802838003712","lower": "1850547693215023104","count": 1562,"preSum": 90617 },{ "ndv": 987,"upper": "1850577718693855232","lower": "1850564811948032000","count": 1562,"preSum": 92179 },{ "ndv": 986,"upper": "1850590382069383168","lower": "1850577720438685696","count": 1562,"preSum": 93741 },{ "ndv": 1006,"upper": "1850602489129205760","lower": "1850590384569188352","count": 1563,"preSum": 95303 },{ "ndv": 973,"upper": "1850614653063790592","lower": "1850602496645398528","count": 1562,"preSum": 96866 },{ "ndv": 977,"upper": "1850627048289075200","lower": "1850614685896802304","count": 1522,"preSum": 98428 } ],"maxBucketSize": 64,"type": "Datetime","sampleRate": 0.90062594 }
+  cest_full_table_big.c_datetime_1.null_count:
+    0
+  cest_full_table_big.c_datetime_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_datetime_3.TOPN:
+    { "countArr": [ 7,8,7,7,8,7,7 ],"valueArr": [ 1849856379473362944,1849966883126640640,1850096458666082304,1850112028845277184,1850159979386896384,1850408374944923648,1850600075777015808 ],"type": "Datetime","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_datetime_3.cardinality:
+    515198
+  cest_full_table_big.c_datetime_3.histogram:
+    { "buckets": [ { "ndv": 988,"upper": "1849797349442846720","lower": "1849785388378357760","count": 1563,"preSum": 0 },{ "ndv": 994,"upper": "1849810007432888320","lower": "1849797352949284864","count": 1563,"preSum": 1563 },{ "ndv": 998,"upper": "1849822169907855360","lower": "1849810009664258048","count": 1562,"preSum": 3126 },{ "ndv": 993,"upper": "1849835987757170688","lower": "1849822185108013056","count": 1564,"preSum": 4688 },{ "ndv": 1004,"upper": "1849848516512317440","lower": "1849835990038872064","count": 1562,"preSum": 6252 },{ "ndv": 990,"upper": "1849863290562281472","lower": "1849848521394487296","count": 1562,"preSum": 7814 },{ "ndv": 976,"upper": "1849875556552671232","lower": "1849863306248978432","count": 1565,"preSum": 9376 },{ "ndv": 1011,"upper": "1849887891413532672","lower": "1849875561652944896","count": 1562,"preSum": 10941 },{ "ndv": 1007,"upper": "1849900578210054144","lower": "1849887894282436608","count": 1562,"preSum": 12503 },{ "ndv": 960,"upper": "1849912344541396992","lower": "1849900608560037888","count": 1562,"preSum": 14065 },{ "ndv": 1006,"upper": "1849934999990566912","lower": "1849912352191807488","count": 1562,"preSum": 15627 },{ "ndv": 989,"upper": "1849947243063279616","lower": "1849935035474378752","count": 1562,"preSum": 17189 },{ "ndv": 995,"upper": "1849960156536766464","lower": "1849947243667259392","count": 1562,"preSum": 18751 },{ "ndv": 996,"upper": "1849972736445644800","lower": "1849960173850853376","count": 1563,"preSum": 20313 },{ "ndv": 990,"upper": "1849985731322183680","lower": "1849972736663748608","count": 1563,"preSum": 21876 },{ "ndv": 1007,"upper": "1850000072838742016","lower": "1849985735147388928","count": 1562,"preSum": 23439 },{ "ndv": 984,"upper": "1850012695227531264","lower": "1850000073291726848","count": 1562,"preSum": 25001 },{ "ndv": 989,"upper": "1850025523472760832","lower": "1850012707474898944","count": 1562,"preSum": 26563 },{ "ndv": 961,"upper": "1850037400969936896","lower": "1850025536441548800","count": 1562,"preSum": 28125 },{ "ndv": 1022,"upper": "1850049990894813184","lower": "1850037414257491968","count": 1562,"preSum": 29687 },{ "ndv": 980,"upper": "1850067127914987520","lower": "1850049995558879232","count": 1562,"preSum": 31249 },{ "ndv": 959,"upper": "1850079478009561088","lower": "1850067137998094336","count": 1564,"preSum": 32811 },{ "ndv": 986,"upper": "1850092294141640704","lower": "1850080048921444352","count": 1562,"preSum": 34375 },{ "ndv": 969,"upper": "1850105086299078656","lower": "1850092315482259456","count": 1562,"preSum": 35937 },{ "ndv": 994,"upper": "1850118003564216320","lower": "1850105099469193216","count": 1562,"preSum": 37499 },{ "ndv": 970,"upper": "1850130906283507712","lower": "1850118004688289792","count": 1564,"preSum": 39061 },{ "ndv": 969,"upper": "1850145197317423104","lower": "1850130906535165952","count": 1562,"preSum": 40625 },{ "ndv": 990,"upper": "1850157220558274560","lower": "1850145197401309184","count": 1562,"preSum": 42187 },{ "ndv": 986,"upper": "1850169175700406272","lower": "1850157232872751104","count": 1562,"preSum": 43749 },{ "ndv": 985,"upper": "1850181877176991744","lower": "1850169189642272768","count": 1562,"preSum": 45311 },{ "ndv": 974,"upper": "1850193542475939840","lower": "1850181915093499904","count": 1562,"preSum": 46873 },{ "ndv": 991,"upper": "1850210275685302272","lower": "1850193559622254592","count": 1562,"preSum": 48435 },{ "ndv": 981,"upper": "1850223335640662016","lower": "1850210280517140480","count": 1562,"preSum": 49997 },{ "ndv": 962,"upper": "1850235437096894464","lower": "1850223338979328000","count": 1562,"preSum": 51559 },{ "ndv": 1005,"upper": "1850248266667524096","lower": "1850235446408249344","count": 1562,"preSum": 53121 },{ "ndv": 1005,"upper": "1850261234734071808","lower": "1850248286884069376","count": 1562,"preSum": 54683 },{ "ndv": 1017,"upper": "1850274085242667008","lower": "1850261236898332672","count": 1562,"preSum": 56245 },{ "ndv": 994,"upper": "1850288998493192192","lower": "1850274121951215616","count": 1564,"preSum": 57807 },{ "ndv": 971,"upper": "1850300960866304000","lower": "1850289004633653248","count": 1562,"preSum": 59371 },{ "ndv": 1023,"upper": "1850313627177844736","lower": "1850300970462871552","count": 1562,"preSum": 60933 },{ "ndv": 998,"upper": "1850326463392251904","lower": "1850313636052992000","count": 1562,"preSum": 62495 },{ "ndv": 972,"upper": "1850338940792340480","lower": "1850326481276764160","count": 1563,"preSum": 64057 },{ "ndv": 1005,"upper": "1850354048759234560","lower": "1850338942033854464","count": 1562,"preSum": 65620 },{ "ndv": 962,"upper": "1850366065406640128","lower": "1850354053993725952","count": 1563,"preSum": 67182 },{ "ndv": 968,"upper": "1850378032846471168","lower": "1850366074164346880","count": 1562,"preSum": 68745 },{ "ndv": 976,"upper": "1850390280918794240","lower": "1850378070209331200","count": 1562,"preSum": 70307 },{ "ndv": 990,"upper": "1850403330036072448","lower": "1850390285616414720","count": 1562,"preSum": 71869 },{ "ndv": 974,"upper": "1850419937953185792","lower": "1850403335538999296","count": 1562,"preSum": 73431 },{ "ndv": 1028,"upper": "1850432499725893632","lower": "1850419941459623936","count": 1563,"preSum": 74993 },{ "ndv": 974,"upper": "1850444275922239488","lower": "1850432503752425472","count": 1562,"preSum": 76556 },{ "ndv": 994,"upper": "1850457377787084800","lower": "1850444281592938496","count": 1564,"preSum": 78118 },{ "ndv": 993,"upper": "1850470384005021696","lower": "1850457397701640192","count": 1562,"preSum": 79682 },{ "ndv": 989,"upper": "1850482957035241472","lower": "1850470398617976832","count": 1562,"preSum": 81244 },{ "ndv": 992,"upper": "1850497236643872768","lower": "1850482970490568704","count": 1562,"preSum": 82806 },{ "ndv": 986,"upper": "1850509872588652544","lower": "1850497246324326400","count": 1562,"preSum": 84368 },{ "ndv": 998,"upper": "1850522829548683264","lower": "1850509874081824768","count": 1562,"preSum": 85930 },{ "ndv": 972,"upper": "1850535566777516032","lower": "1850522844815949824","count": 1562,"preSum": 87492 },{ "ndv": 971,"upper": "1850547688936833024","lower": "1850535569277321216","count": 1563,"preSum": 89054 },{ "ndv": 988,"upper": "1850564802838003712","lower": "1850547693215023104","count": 1562,"preSum": 90617 },{ "ndv": 987,"upper": "1850577718693855232","lower": "1850564811948032000","count": 1562,"preSum": 92179 },{ "ndv": 986,"upper": "1850590382069383168","lower": "1850577720438685696","count": 1562,"preSum": 93741 },{ "ndv": 1006,"upper": "1850602489129205760","lower": "1850590384569188352","count": 1563,"preSum": 95303 },{ "ndv": 973,"upper": "1850614653063790592","lower": "1850602496645398528","count": 1562,"preSum": 96866 },{ "ndv": 977,"upper": "1850627048289075200","lower": "1850614685896802304","count": 1522,"preSum": 98428 } ],"maxBucketSize": 64,"type": "Datetime","sampleRate": 0.90062594 }
+  cest_full_table_big.c_datetime_3.null_count:
+    0
+  cest_full_table_big.c_datetime_3.sample_rate:
+    0.010943651
+  cest_full_table_big.c_datetime_6.TOPN:
+    { "countArr": [ 7,8,7,7,8,7,7 ],"valueArr": [ 1849856379473362944,1849966883126640640,1850096458666082304,1850112028845277184,1850159979386896384,1850408374944923648,1850600075777015808 ],"type": "Datetime","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_datetime_6.cardinality:
+    515198
+  cest_full_table_big.c_datetime_6.histogram:
+    { "buckets": [ { "ndv": 988,"upper": "1849797349442846720","lower": "1849785388378357760","count": 1563,"preSum": 0 },{ "ndv": 994,"upper": "1849810007432888320","lower": "1849797352949284864","count": 1563,"preSum": 1563 },{ "ndv": 998,"upper": "1849822169907855360","lower": "1849810009664258048","count": 1562,"preSum": 3126 },{ "ndv": 993,"upper": "1849835987757170688","lower": "1849822185108013056","count": 1564,"preSum": 4688 },{ "ndv": 1004,"upper": "1849848516512317440","lower": "1849835990038872064","count": 1562,"preSum": 6252 },{ "ndv": 990,"upper": "1849863290562281472","lower": "1849848521394487296","count": 1562,"preSum": 7814 },{ "ndv": 976,"upper": "1849875556552671232","lower": "1849863306248978432","count": 1565,"preSum": 9376 },{ "ndv": 1011,"upper": "1849887891413532672","lower": "1849875561652944896","count": 1562,"preSum": 10941 },{ "ndv": 1007,"upper": "1849900578210054144","lower": "1849887894282436608","count": 1562,"preSum": 12503 },{ "ndv": 960,"upper": "1849912344541396992","lower": "1849900608560037888","count": 1562,"preSum": 14065 },{ "ndv": 1006,"upper": "1849934999990566912","lower": "1849912352191807488","count": 1562,"preSum": 15627 },{ "ndv": 989,"upper": "1849947243063279616","lower": "1849935035474378752","count": 1562,"preSum": 17189 },{ "ndv": 995,"upper": "1849960156536766464","lower": "1849947243667259392","count": 1562,"preSum": 18751 },{ "ndv": 996,"upper": "1849972736445644800","lower": "1849960173850853376","count": 1563,"preSum": 20313 },{ "ndv": 990,"upper": "1849985731322183680","lower": "1849972736663748608","count": 1563,"preSum": 21876 },{ "ndv": 1007,"upper": "1850000072838742016","lower": "1849985735147388928","count": 1562,"preSum": 23439 },{ "ndv": 984,"upper": "1850012695227531264","lower": "1850000073291726848","count": 1562,"preSum": 25001 },{ "ndv": 989,"upper": "1850025523472760832","lower": "1850012707474898944","count": 1562,"preSum": 26563 },{ "ndv": 961,"upper": "1850037400969936896","lower": "1850025536441548800","count": 1562,"preSum": 28125 },{ "ndv": 1022,"upper": "1850049990894813184","lower": "1850037414257491968","count": 1562,"preSum": 29687 },{ "ndv": 980,"upper": "1850067127914987520","lower": "1850049995558879232","count": 1562,"preSum": 31249 },{ "ndv": 959,"upper": "1850079478009561088","lower": "1850067137998094336","count": 1564,"preSum": 32811 },{ "ndv": 986,"upper": "1850092294141640704","lower": "1850080048921444352","count": 1562,"preSum": 34375 },{ "ndv": 969,"upper": "1850105086299078656","lower": "1850092315482259456","count": 1562,"preSum": 35937 },{ "ndv": 994,"upper": "1850118003564216320","lower": "1850105099469193216","count": 1562,"preSum": 37499 },{ "ndv": 970,"upper": "1850130906283507712","lower": "1850118004688289792","count": 1564,"preSum": 39061 },{ "ndv": 969,"upper": "1850145197317423104","lower": "1850130906535165952","count": 1562,"preSum": 40625 },{ "ndv": 990,"upper": "1850157220558274560","lower": "1850145197401309184","count": 1562,"preSum": 42187 },{ "ndv": 986,"upper": "1850169175700406272","lower": "1850157232872751104","count": 1562,"preSum": 43749 },{ "ndv": 985,"upper": "1850181877176991744","lower": "1850169189642272768","count": 1562,"preSum": 45311 },{ "ndv": 974,"upper": "1850193542475939840","lower": "1850181915093499904","count": 1562,"preSum": 46873 },{ "ndv": 991,"upper": "1850210275685302272","lower": "1850193559622254592","count": 1562,"preSum": 48435 },{ "ndv": 981,"upper": "1850223335640662016","lower": "1850210280517140480","count": 1562,"preSum": 49997 },{ "ndv": 962,"upper": "1850235437096894464","lower": "1850223338979328000","count": 1562,"preSum": 51559 },{ "ndv": 1005,"upper": "1850248266667524096","lower": "1850235446408249344","count": 1562,"preSum": 53121 },{ "ndv": 1005,"upper": "1850261234734071808","lower": "1850248286884069376","count": 1562,"preSum": 54683 },{ "ndv": 1017,"upper": "1850274085242667008","lower": "1850261236898332672","count": 1562,"preSum": 56245 },{ "ndv": 994,"upper": "1850288998493192192","lower": "1850274121951215616","count": 1564,"preSum": 57807 },{ "ndv": 971,"upper": "1850300960866304000","lower": "1850289004633653248","count": 1562,"preSum": 59371 },{ "ndv": 1023,"upper": "1850313627177844736","lower": "1850300970462871552","count": 1562,"preSum": 60933 },{ "ndv": 998,"upper": "1850326463392251904","lower": "1850313636052992000","count": 1562,"preSum": 62495 },{ "ndv": 972,"upper": "1850338940792340480","lower": "1850326481276764160","count": 1563,"preSum": 64057 },{ "ndv": 1005,"upper": "1850354048759234560","lower": "1850338942033854464","count": 1562,"preSum": 65620 },{ "ndv": 962,"upper": "1850366065406640128","lower": "1850354053993725952","count": 1563,"preSum": 67182 },{ "ndv": 968,"upper": "1850378032846471168","lower": "1850366074164346880","count": 1562,"preSum": 68745 },{ "ndv": 976,"upper": "1850390280918794240","lower": "1850378070209331200","count": 1562,"preSum": 70307 },{ "ndv": 990,"upper": "1850403330036072448","lower": "1850390285616414720","count": 1562,"preSum": 71869 },{ "ndv": 974,"upper": "1850419937953185792","lower": "1850403335538999296","count": 1562,"preSum": 73431 },{ "ndv": 1028,"upper": "1850432499725893632","lower": "1850419941459623936","count": 1563,"preSum": 74993 },{ "ndv": 974,"upper": "1850444275922239488","lower": "1850432503752425472","count": 1562,"preSum": 76556 },{ "ndv": 994,"upper": "1850457377787084800","lower": "1850444281592938496","count": 1564,"preSum": 78118 },{ "ndv": 993,"upper": "1850470384005021696","lower": "1850457397701640192","count": 1562,"preSum": 79682 },{ "ndv": 989,"upper": "1850482957035241472","lower": "1850470398617976832","count": 1562,"preSum": 81244 },{ "ndv": 992,"upper": "1850497236643872768","lower": "1850482970490568704","count": 1562,"preSum": 82806 },{ "ndv": 986,"upper": "1850509872588652544","lower": "1850497246324326400","count": 1562,"preSum": 84368 },{ "ndv": 998,"upper": "1850522829548683264","lower": "1850509874081824768","count": 1562,"preSum": 85930 },{ "ndv": 972,"upper": "1850535566777516032","lower": "1850522844815949824","count": 1562,"preSum": 87492 },{ "ndv": 971,"upper": "1850547688936833024","lower": "1850535569277321216","count": 1563,"preSum": 89054 },{ "ndv": 988,"upper": "1850564802838003712","lower": "1850547693215023104","count": 1562,"preSum": 90617 },{ "ndv": 987,"upper": "1850577718693855232","lower": "1850564811948032000","count": 1562,"preSum": 92179 },{ "ndv": 986,"upper": "1850590382069383168","lower": "1850577720438685696","count": 1562,"preSum": 93741 },{ "ndv": 1006,"upper": "1850602489129205760","lower": "1850590384569188352","count": 1563,"preSum": 95303 },{ "ndv": 973,"upper": "1850614653063790592","lower": "1850602496645398528","count": 1562,"preSum": 96866 },{ "ndv": 977,"upper": "1850627048289075200","lower": "1850614685896802304","count": 1522,"preSum": 98428 } ],"maxBucketSize": 64,"type": "Datetime","sampleRate": 0.90062594 }
+  cest_full_table_big.c_datetime_6.null_count:
+    0
+  cest_full_table_big.c_datetime_6.sample_rate:
+    0.010943651
+  cest_full_table_big.c_decimal.TOPN:
+    { "countArr": [ 8,9,8,7,7,7,8 ],"valueArr": [ -3161637812,-2338453878,2761250206,4794313941,4985089198,9211629936,9396373784 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_decimal.cardinality:
+    513404
+  cest_full_table_big.c_decimal.histogram:
+    { "buckets": [ { "ndv": 979,"upper": -9687155776,"lower": -9999947084,"count": 1564,"preSum": 0 },{ "ndv": 966,"upper": -9387009540,"lower": -9687058700,"count": 1562,"preSum": 1564 },{ "ndv": 969,"upper": -9074381923,"lower": -9386696920,"count": 1562,"preSum": 3126 },{ "ndv": 981,"upper": -8771714857,"lower": -9074360681,"count": 1562,"preSum": 4688 },{ "ndv": 994,"upper": -8452531843,"lower": -8771397797,"count": 1562,"preSum": 6250 },{ "ndv": 983,"upper": -8134112376,"lower": -8452198570,"count": 1563,"preSum": 7812 },{ "ndv": 982,"upper": -7813532690,"lower": -8133170724,"count": 1563,"preSum": 9375 },{ "ndv": 1007,"upper": -7480104096,"lower": -7813027807,"count": 1562,"preSum": 10938 },{ "ndv": 992,"upper": -7173906190,"lower": -7479661468,"count": 1562,"preSum": 12500 },{ "ndv": 1008,"upper": -6846432644,"lower": -7173396952,"count": 1564,"preSum": 14062 },{ "ndv": 958,"upper": -6548406963,"lower": -6846149635,"count": 1563,"preSum": 15626 },{ "ndv": 995,"upper": -6243151080,"lower": -6548248992,"count": 1563,"preSum": 17189 },{ "ndv": 1010,"upper": -5941574866,"lower": -6242814299,"count": 1563,"preSum": 18752 },{ "ndv": 973,"upper": -5620422904,"lower": -5941469150,"count": 1562,"preSum": 20315 },{ "ndv": 994,"upper": -5297157054,"lower": -5620268272,"count": 1562,"preSum": 21877 },{ "ndv": 986,"upper": -4995542508,"lower": -5297020067,"count": 1563,"preSum": 23439 },{ "ndv": 982,"upper": -4686876573,"lower": -4995130422,"count": 1563,"preSum": 25002 },{ "ndv": 980,"upper": -4364186451,"lower": -4685947583,"count": 1562,"preSum": 26565 },{ "ndv": 978,"upper": -4047621091,"lower": -4363387676,"count": 1562,"preSum": 28127 },{ "ndv": 960,"upper": -3744861812,"lower": -4047498413,"count": 1562,"preSum": 29689 },{ "ndv": 1005,"upper": -3419877589,"lower": -3744361330,"count": 1564,"preSum": 31251 },{ "ndv": 965,"upper": -3117911334,"lower": -3419837746,"count": 1563,"preSum": 32815 },{ "ndv": 999,"upper": -2801900157,"lower": -3117649944,"count": 1562,"preSum": 34378 },{ "ndv": 991,"upper": -2492832347,"lower": -2801528498,"count": 1562,"preSum": 35940 },{ "ndv": 991,"upper": -2177734926,"lower": -2492532666,"count": 1562,"preSum": 37502 },{ "ndv": 1014,"upper": -1861156575,"lower": -2177661031,"count": 1563,"preSum": 39064 },{ "ndv": 1011,"upper": -1534527933,"lower": -1860715408,"count": 1562,"preSum": 40627 },{ "ndv": 978,"upper": -1229701813,"lower": -1534419842,"count": 1562,"preSum": 42189 },{ "ndv": 953,"upper": -932502951,"lower": -1229489935,"count": 1562,"preSum": 43751 },{ "ndv": 992,"upper": -614271098,"lower": -932126004,"count": 1562,"preSum": 45313 },{ "ndv": 975,"upper": -300381404,"lower": -613275464,"count": 1563,"preSum": 46875 },{ "ndv": 999,"upper": 18832841,"lower": -300259505,"count": 1562,"preSum": 48438 },{ "ndv": 965,"upper": 337975912,"lower": 18865885,"count": 1562,"preSum": 50000 },{ "ndv": 1007,"upper": 665449719,"lower": 338194274,"count": 1562,"preSum": 51562 },{ "ndv": 1003,"upper": 974574942,"lower": 665902670,"count": 1562,"preSum": 53124 },{ "ndv": 943,"upper": 1265231376,"lower": 974635572,"count": 1563,"preSum": 54686 },{ "ndv": 975,"upper": 1571632351,"lower": 1265917720,"count": 1562,"preSum": 56249 },{ "ndv": 981,"upper": 1875185000,"lower": 1571785457,"count": 1562,"preSum": 57811 },{ "ndv": 989,"upper": 2197245103,"lower": 1875301292,"count": 1564,"preSum": 59373 },{ "ndv": 993,"upper": 2515308936,"lower": 2197562867,"count": 1562,"preSum": 60937 },{ "ndv": 986,"upper": 2837273069,"lower": 2516093763,"count": 1562,"preSum": 62499 },{ "ndv": 994,"upper": 3147598748,"lower": 2837284756,"count": 1562,"preSum": 64061 },{ "ndv": 972,"upper": 3451064745,"lower": 3147603468,"count": 1562,"preSum": 65623 },{ "ndv": 968,"upper": 3763307089,"lower": 3451392751,"count": 1563,"preSum": 67185 },{ "ndv": 987,"upper": 4081448171,"lower": 3763887359,"count": 1562,"preSum": 68748 },{ "ndv": 1016,"upper": 4413998253,"lower": 4081846339,"count": 1562,"preSum": 70310 },{ "ndv": 985,"upper": 4716613047,"lower": 4414562394,"count": 1562,"preSum": 71872 },{ "ndv": 987,"upper": 5031329080,"lower": 4716718911,"count": 1562,"preSum": 73434 },{ "ndv": 982,"upper": 5363093185,"lower": 5031338352,"count": 1563,"preSum": 74996 },{ "ndv": 973,"upper": 5677889496,"lower": 5363184935,"count": 1562,"preSum": 76559 },{ "ndv": 1004,"upper": 5989660023,"lower": 5678200705,"count": 1562,"preSum": 78121 },{ "ndv": 977,"upper": 6287839524,"lower": 5989760776,"count": 1562,"preSum": 79683 },{ "ndv": 963,"upper": 6594007466,"lower": 6288155489,"count": 1562,"preSum": 81245 },{ "ndv": 972,"upper": 6907327360,"lower": 6594052884,"count": 1563,"preSum": 82807 },{ "ndv": 976,"upper": 7213171688,"lower": 6908357525,"count": 1563,"preSum": 84370 },{ "ndv": 969,"upper": 7518062598,"lower": 7213464031,"count": 1562,"preSum": 85933 },{ "ndv": 1004,"upper": 7841327765,"lower": 7518240655,"count": 1563,"preSum": 87495 },{ "ndv": 968,"upper": 8148806019,"lower": 7841638007,"count": 1562,"preSum": 89058 },{ "ndv": 980,"upper": 8469742895,"lower": 8149425222,"count": 1562,"preSum": 90620 },{ "ndv": 972,"upper": 8777957541,"lower": 8469853449,"count": 1563,"preSum": 92182 },{ "ndv": 1002,"upper": 9083831652,"lower": 8779382880,"count": 1562,"preSum": 93745 },{ "ndv": 975,"upper": 9389817052,"lower": 9084054191,"count": 1562,"preSum": 95307 },{ "ndv": 998,"upper": 9696105680,"lower": 9390001677,"count": 1563,"preSum": 96869 },{ "ndv": 960,"upper": 9999769928,"lower": 9696234677,"count": 1515,"preSum": 98432 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_decimal.null_count:
+    0
+  cest_full_table_big.c_decimal.sample_rate:
+    0.010943651
+  cest_full_table_big.c_decimal_pr.TOPN:
+    { "countArr": [ 7,7,7,8,7,7,7,7,8,7,7,7 ],"valueArr": [ -75761368346928600000000000000000000.000000000000000000000000000000,-34966276527066760000000000000000000.000000000000000000000000000000,-21432670686651130000000000000000000.000000000000000000000000000000,-13125128156279190000000000000000000.000000000000000000000000000000,-11477993890510120000000000000000000.000000000000000000000000000000,-10099048338993650000000000000000000.000000000000000000000000000000,-8356233796409413000000000000000000.000000000000000000000000000000,30870071669858136000000000000000000.000000000000000000000000000000,31740144295914382000000000000000000.000000000000000000000000000000,63269113195223930000000000000000000.000000000000000000000000000000,64030190359573910000000000000000000.000000000000000000000000000000,96568383584898280000000000000000000.000000000000000000000000000000 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_decimal_pr.cardinality:
+    515051
+  cest_full_table_big.c_decimal_pr.histogram:
+    { "buckets": [ { "ndv": 993,"upper": -96764760248984260000000000000000000.000000000000000000000000000000,"lower": -99999470851927990000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 0 },{ "ndv": 974,"upper": -93804787163083860000000000000000000.000000000000000000000000000000,"lower": -96761703454929480000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 1562 },{ "ndv": 975,"upper": -90703672605533540000000000000000000.000000000000000000000000000000,"lower": -93803234355070480000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 3124 },{ "ndv": 1004,"upper": -87610692065699920000000000000000000.000000000000000000000000000000,"lower": -90702475778546280000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 4687 },{ "ndv": 1007,"upper": -84392001962304410000000000000000000.000000000000000000000000000000,"lower": -87609035883403950000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 6249 },{ "ndv": 1002,"upper": -81140807947839370000000000000000000.000000000000000000000000000000,"lower": -84388163109519000000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 7811 },{ "ndv": 990,"upper": -77855755190734450000000000000000000.000000000000000000000000000000,"lower": -81128022206230505000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 9375 },{ "ndv": 982,"upper": -74702356738829845000000000000000000.000000000000000000000000000000,"lower": -77855675578527520000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 10938 },{ "ndv": 955,"upper": -71731668161870890000000000000000000.000000000000000000000000000000,"lower": -74699687726076200000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 12500 },{ "ndv": 994,"upper": -68475108907170895000000000000000000.000000000000000000000000000000,"lower": -71727226843110515000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 14063 },{ "ndv": 991,"upper": -65326503654777840000000000000000000.000000000000000000000000000000,"lower": -68475070280057480000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 15626 },{ "ndv": 1001,"upper": -62331277771692280000000000000000000.000000000000000000000000000000,"lower": -65322651104484510000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 17188 },{ "ndv": 999,"upper": -59253213734725300000000000000000000.000000000000000000000000000000,"lower": -62330281584613620000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 18752 },{ "ndv": 1008,"upper": -56044631802295880000000000000000000.000000000000000000000000000000,"lower": -59252261364557940000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 20314 },{ "ndv": 1010,"upper": -52814432683893570000000000000000000.000000000000000000000000000000,"lower": -56044169472641150000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 21876 },{ "ndv": 983,"upper": -49635397736884590000000000000000000.000000000000000000000000000000,"lower": -52814311404538600000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 23438 },{ "ndv": 994,"upper": -46313839997966160000000000000000000.000000000000000000000000000000,"lower": -49630307794800680000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 25001 },{ "ndv": 971,"upper": -43217909076822320000000000000000000.000000000000000000000000000000,"lower": -46308399922183560000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 26564 },{ "ndv": 1001,"upper": -40014754300594737000000000000000000.000000000000000000000000000000,"lower": -43213231634298700000000000000000000.000000000000000000000000000000,"count": 1565,"preSum": 28126 },{ "ndv": 984,"upper": -36968613426251330000000000000000000.000000000000000000000000000000,"lower": -40013854845576490000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 29691 },{ "ndv": 996,"upper": -33794274180256955000000000000000000.000000000000000000000000000000,"lower": -36960861221231900000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 31254 },{ "ndv": 974,"upper": -30701228922008240000000000000000000.000000000000000000000000000000,"lower": -33791958828386238000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 32816 },{ "ndv": 979,"upper": -27447343436703160000000000000000000.000000000000000000000000000000,"lower": -30696198399764984000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 34378 },{ "ndv": 991,"upper": -24381195704457823000000000000000000.000000000000000000000000000000,"lower": -27446506902191150000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 35940 },{ "ndv": 962,"upper": -21362266818647366000000000000000000.000000000000000000000000000000,"lower": -24379199415851268000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 37502 },{ "ndv": 996,"upper": -18251458819185501000000000000000000.000000000000000000000000000000,"lower": -21361865771311275000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 39064 },{ "ndv": 981,"upper": -15043190548683188000000000000000000.000000000000000000000000000000,"lower": -18250455261974796000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 40626 },{ "ndv": 965,"upper": -12061693407409863000000000000000000.000000000000000000000000000000,"lower": -15041988462860400000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 42188 },{ "ndv": 981,"upper": -9048310149931673000000000000000000.000000000000000000000000000000,"lower": -12056613831847590000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 43751 },{ "ndv": 970,"upper": -5967322532621562000000000000000000.000000000000000000000000000000,"lower": -9046237716838896000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 45313 },{ "ndv": 1007,"upper": -2919916448995425600000000000000000.000000000000000000000000000000,"lower": -5966752358488224000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 46875 },{ "ndv": 989,"upper": 228129686512528060000000000000000.000000000000000000000000000000,"lower": -2915119805609480400000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 48437 },{ "ndv": 979,"upper": 3413396390386313400000000000000000.000000000000000000000000000000,"lower": 230187624771446120000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 50000 },{ "ndv": 959,"upper": 6649808345010481000000000000000000.000000000000000000000000000000,"lower": 3425654210272463500000000000000000.000000000000000000000000000000,"count": 1565,"preSum": 51563 },{ "ndv": 986,"upper": 9719505641315776000000000000000000.000000000000000000000000000000,"lower": 6653972599633518000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 53128 },{ "ndv": 966,"upper": 12885142964243597000000000000000000.000000000000000000000000000000,"lower": 9721949549579901000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 54690 },{ "ndv": 992,"upper": 15918120791954309000000000000000000.000000000000000000000000000000,"lower": 12889264768915870000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 56253 },{ "ndv": 1020,"upper": 18983388834533566000000000000000000.000000000000000000000000000000,"lower": 15918765700076414000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 57815 },{ "ndv": 998,"upper": 22249861368062440000000000000000000.000000000000000000000000000000,"lower": 18991173167423447000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 59379 },{ "ndv": 976,"upper": 25270796353303115000000000000000000.000000000000000000000000000000,"lower": 22254600390718250000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 60941 },{ "ndv": 969,"upper": 28440262055333450000000000000000000.000000000000000000000000000000,"lower": 25275601950143930000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 62503 },{ "ndv": 1021,"upper": 31633982760932696000000000000000000.000000000000000000000000000000,"lower": 28440774888748122000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 64066 },{ "ndv": 974,"upper": 34677804526956190000000000000000000.000000000000000000000000000000,"lower": 31634388633217940000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 65628 },{ "ndv": 988,"upper": 37738250878196130000000000000000000.000000000000000000000000000000,"lower": 34679982243149920000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 67190 },{ "ndv": 996,"upper": 40887364483041470000000000000000000.000000000000000000000000000000,"lower": 37741610955565540000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 68752 },{ "ndv": 987,"upper": 44049083830563690000000000000000000.000000000000000000000000000000,"lower": 40892341414678855000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 70314 },{ "ndv": 980,"upper": 47235497745549170000000000000000000.000000000000000000000000000000,"lower": 44049937406698890000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 71876 },{ "ndv": 998,"upper": 50329130476583295000000000000000000.000000000000000000000000000000,"lower": 47237496208773160000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 73439 },{ "ndv": 963,"upper": 53580622920766525000000000000000000.000000000000000000000000000000,"lower": 50330104888326540000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 75002 },{ "ndv": 1014,"upper": 56760007036575375000000000000000000.000000000000000000000000000000,"lower": 53586353827825520000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 76564 },{ "ndv": 997,"upper": 59716685383194960000000000000000000.000000000000000000000000000000,"lower": 56763671287478610000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 78127 },{ "ndv": 967,"upper": 62789399633927270000000000000000000.000000000000000000000000000000,"lower": 59717024548634790000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 79689 },{ "ndv": 992,"upper": 65865496876144730000000000000000000.000000000000000000000000000000,"lower": 62791640305228830000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 81251 },{ "ndv": 992,"upper": 68951981803271280000000000000000000.000000000000000000000000000000,"lower": 65867203350094750000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 82815 },{ "ndv": 1006,"upper": 72101857669478700000000000000000000.000000000000000000000000000000,"lower": 68955555252929870000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 84377 },{ "ndv": 978,"upper": 75238866718773990000000000000000000.000000000000000000000000000000,"lower": 72102218238260540000000000000000000.000000000000000000000000000000,"count": 1564,"preSum": 85941 },{ "ndv": 989,"upper": 78439709896384835000000000000000000.000000000000000000000000000000,"lower": 75239335741185000000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 87505 },{ "ndv": 948,"upper": 81368581999259250000000000000000000.000000000000000000000000000000,"lower": 78446555956882450000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 89067 },{ "ndv": 1015,"upper": 84624953753426320000000000000000000.000000000000000000000000000000,"lower": 81370115974721590000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 90630 },{ "ndv": 976,"upper": 87821666896224470000000000000000000.000000000000000000000000000000,"lower": 84629494107429300000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 92192 },{ "ndv": 985,"upper": 90840541919112480000000000000000000.000000000000000000000000000000,"lower": 87822866551836360000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 93754 },{ "ndv": 1010,"upper": 93960951017907040000000000000000000.000000000000000000000000000000,"lower": 90841263590764140000000000000000000.000000000000000000000000000000,"count": 1563,"preSum": 95316 },{ "ndv": 1029,"upper": 97096949982376130000000000000000000.000000000000000000000000000000,"lower": 93963737850341840000000000000000000.000000000000000000000000000000,"count": 1562,"preSum": 96879 },{ "ndv": 915,"upper": 99995669049052540000000000000000000.000000000000000000000000000000,"lower": 97107137834917060000000000000000000.000000000000000000000000000000,"count": 1474,"preSum": 98441 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_decimal_pr.null_count:
+    0
+  cest_full_table_big.c_decimal_pr.sample_rate:
+    0.010943651
+  cest_full_table_big.c_double.TOPN:
+    { "countArr": [ 7,7,7,7,7,8,7,7,7,7,7 ],"valueArr": [ 1.8033788670816908E307,2.2899803125719695E307,2.7689427755292624E307,3.3082804620162163E307,4.1423139809431574E307,4.324383600297211E307,5.843728541219235E307,5.945158417129865E307,1.1567488646249857E308,1.2083505338264966E308,1.305120637062738E308 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_double.cardinality:
+    513331
+  cest_full_table_big.c_double.histogram:
+    { "buckets": [ { "ndv": 979,"upper": 2.8915727853583585E306,"lower": 4.756229282033632E302,"count": 1562,"preSum": 0 },{ "ndv": 1012,"upper": 5.802923817060523E306,"lower": 2.900326993377809E306,"count": 1564,"preSum": 1562 },{ "ndv": 1008,"upper": 8.771023244366165E306,"lower": 5.807824712517648E306,"count": 1565,"preSum": 3126 },{ "ndv": 987,"upper": 1.1668980982078657E307,"lower": 8.774290405283191E306,"count": 1562,"preSum": 4691 },{ "ndv": 991,"upper": 1.4381202591495974E307,"lower": 1.16694501740653E307,"count": 1563,"preSum": 6253 },{ "ndv": 981,"upper": 1.721513265437389E307,"lower": 1.4389073269828172E307,"count": 1563,"preSum": 7816 },{ "ndv": 977,"upper": 2.0156194609916194E307,"lower": 1.7217224049904065E307,"count": 1562,"preSum": 9379 },{ "ndv": 1000,"upper": 2.3116005320726376E307,"lower": 2.0157410466959296E307,"count": 1563,"preSum": 10941 },{ "ndv": 970,"upper": 2.5909193845642066E307,"lower": 2.3116058793833675E307,"count": 1562,"preSum": 12504 },{ "ndv": 963,"upper": 2.8646972152127453E307,"lower": 2.591252504806782E307,"count": 1563,"preSum": 14066 },{ "ndv": 970,"upper": 3.134452127665627E307,"lower": 2.8650264852350487E307,"count": 1563,"preSum": 15629 },{ "ndv": 971,"upper": 3.403946804568662E307,"lower": 3.13473430277891E307,"count": 1562,"preSum": 17192 },{ "ndv": 1009,"upper": 3.6824117619673936E307,"lower": 3.4041223232046506E307,"count": 1562,"preSum": 18754 },{ "ndv": 986,"upper": 3.973959770822522E307,"lower": 3.682439354788304E307,"count": 1562,"preSum": 20316 },{ "ndv": 964,"upper": 4.2512942787207503E307,"lower": 3.974996470162016E307,"count": 1564,"preSum": 21878 },{ "ndv": 998,"upper": 4.533391414381247E307,"lower": 4.25175785998827E307,"count": 1562,"preSum": 23442 },{ "ndv": 992,"upper": 4.835077685244063E307,"lower": 4.533503960675152E307,"count": 1564,"preSum": 25004 },{ "ndv": 948,"upper": 5.114725922071461E307,"lower": 4.835621719862478E307,"count": 1563,"preSum": 26568 },{ "ndv": 975,"upper": 5.397186698761041E307,"lower": 5.115174776166815E307,"count": 1564,"preSum": 28131 },{ "ndv": 991,"upper": 5.676347253293591E307,"lower": 5.397690822080555E307,"count": 1564,"preSum": 29695 },{ "ndv": 1001,"upper": 5.964754460785259E307,"lower": 5.67704765259023E307,"count": 1562,"preSum": 31259 },{ "ndv": 990,"upper": 6.238529793184719E307,"lower": 5.964843662137904E307,"count": 1562,"preSum": 32821 },{ "ndv": 967,"upper": 6.529150476162594E307,"lower": 6.238929851968796E307,"count": 1564,"preSum": 34383 },{ "ndv": 1020,"upper": 6.81481713002287E307,"lower": 6.529769871550759E307,"count": 1562,"preSum": 35947 },{ "ndv": 998,"upper": 7.095776740971467E307,"lower": 6.815562346553893E307,"count": 1562,"preSum": 37509 },{ "ndv": 993,"upper": 7.376977549538845E307,"lower": 7.095939880766819E307,"count": 1562,"preSum": 39071 },{ "ndv": 996,"upper": 7.669324957047895E307,"lower": 7.376986334883062E307,"count": 1563,"preSum": 40633 },{ "ndv": 986,"upper": 7.952223685190678E307,"lower": 7.669877724135277E307,"count": 1562,"preSum": 42196 },{ "ndv": 1026,"upper": 8.243335013856233E307,"lower": 7.952391722688576E307,"count": 1563,"preSum": 43758 },{ "ndv": 959,"upper": 8.5193481560909E307,"lower": 8.243794535832331E307,"count": 1562,"preSum": 45321 },{ "ndv": 990,"upper": 8.801366577028062E307,"lower": 8.519388571905995E307,"count": 1563,"preSum": 46883 },{ "ndv": 979,"upper": 9.072012020157078E307,"lower": 8.801528047871531E307,"count": 1562,"preSum": 48446 },{ "ndv": 975,"upper": 9.35662485951967E307,"lower": 9.072027225791882E307,"count": 1562,"preSum": 50008 },{ "ndv": 988,"upper": 9.63090758795388E307,"lower": 9.356727773783428E307,"count": 1564,"preSum": 51570 },{ "ndv": 995,"upper": 9.897210003498544E307,"lower": 9.63135072499096E307,"count": 1563,"preSum": 53134 },{ "ndv": 967,"upper": 1.0172971969516795E308,"lower": 9.897288684435532E307,"count": 1562,"preSum": 54697 },{ "ndv": 993,"upper": 1.0442401616132107E308,"lower": 1.0174317081163393E308,"count": 1562,"preSum": 56259 },{ "ndv": 987,"upper": 1.0709709928762785E308,"lower": 1.0442462843053817E308,"count": 1562,"preSum": 57821 },{ "ndv": 1000,"upper": 1.100933532991876E308,"lower": 1.071036045373335E308,"count": 1562,"preSum": 59383 },{ "ndv": 969,"upper": 1.1286261509061276E308,"lower": 1.1009765361700323E308,"count": 1562,"preSum": 60945 },{ "ndv": 1001,"upper": 1.1571905196806554E308,"lower": 1.1286331533437651E308,"count": 1565,"preSum": 62507 },{ "ndv": 999,"upper": 1.1861296270192985E308,"lower": 1.1572087018205442E308,"count": 1563,"preSum": 64072 },{ "ndv": 997,"upper": 1.2134614643693616E308,"lower": 1.1861333622749254E308,"count": 1563,"preSum": 65635 },{ "ndv": 980,"upper": 1.2418700035971612E308,"lower": 1.2134718120082815E308,"count": 1562,"preSum": 67198 },{ "ndv": 985,"upper": 1.2691499515332054E308,"lower": 1.241922037299704E308,"count": 1562,"preSum": 68760 },{ "ndv": 980,"upper": 1.2964567726454612E308,"lower": 1.2692154294513629E308,"count": 1563,"preSum": 70322 },{ "ndv": 995,"upper": 1.3252506384017688E308,"lower": 1.2964814717611366E308,"count": 1562,"preSum": 71885 },{ "ndv": 968,"upper": 1.3514161099861431E308,"lower": 1.325272675922444E308,"count": 1563,"preSum": 73447 },{ "ndv": 972,"upper": 1.3806007864738376E308,"lower": 1.3514637942462712E308,"count": 1563,"preSum": 75010 },{ "ndv": 1003,"upper": 1.409320106809102E308,"lower": 1.380611555545838E308,"count": 1562,"preSum": 76573 },{ "ndv": 998,"upper": 1.4374931168432786E308,"lower": 1.4093583744597833E308,"count": 1562,"preSum": 78135 },{ "ndv": 995,"upper": 1.4652557067046356E308,"lower": 1.4375210813985848E308,"count": 1562,"preSum": 79697 },{ "ndv": 972,"upper": 1.4923393819991763E308,"lower": 1.4652710729347972E308,"count": 1563,"preSum": 81259 },{ "ndv": 999,"upper": 1.520870512354084E308,"lower": 1.4923912449753145E308,"count": 1562,"preSum": 82822 },{ "ndv": 943,"upper": 1.5480509182944984E308,"lower": 1.5209436362511451E308,"count": 1562,"preSum": 84384 },{ "ndv": 984,"upper": 1.576218813758102E308,"lower": 1.5480814819592918E308,"count": 1562,"preSum": 85946 },{ "ndv": 997,"upper": 1.6039884578126058E308,"lower": 1.5764266798675781E308,"count": 1562,"preSum": 87508 },{ "ndv": 983,"upper": 1.6307096565078577E308,"lower": 1.6040858849774968E308,"count": 1562,"preSum": 89070 },{ "ndv": 943,"upper": 1.65803142861061E308,"lower": 1.630710017803611E308,"count": 1563,"preSum": 90632 },{ "ndv": 998,"upper": 1.6881230721320153E308,"lower": 1.658068234717274E308,"count": 1566,"preSum": 92195 },{ "ndv": 968,"upper": 1.7144074279398087E308,"lower": 1.6881239139188576E308,"count": 1564,"preSum": 93761 },{ "ndv": 982,"upper": 1.7413961630376678E308,"lower": 1.714410965762671E308,"count": 1563,"preSum": 95325 },{ "ndv": 993,"upper": 1.7698576327467139E308,"lower": 1.7414298567922518E308,"count": 1562,"preSum": 96888 },{ "ndv": 935,"upper": 1.7976542062583872E308,"lower": 1.7699036945643326E308,"count": 1473,"preSum": 98450 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_double.null_count:
+    0
+  cest_full_table_big.c_double.sample_rate:
+    0.010943651
+  cest_full_table_big.c_double_pr.TOPN:
+    { "countArr": [ 8,7,7,7,7,7,9,7,9,8 ],"valueArr": [ -9451013.9,-7755523.335,-6507204.215,-6073291.268,-2830413.985,-2551571.757,-965631.401,4587748.045,7917370.358,8381951.922 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_double_pr.cardinality:
+    517354
+  cest_full_table_big.c_double_pr.histogram:
+    { "buckets": [ { "ndv": 976,"upper": -9698710.869,"lower": -9999451.812,"count": 1562,"preSum": 0 },{ "ndv": 996,"upper": -9383217.511,"lower": -9698657.366,"count": 1562,"preSum": 1562 },{ "ndv": 996,"upper": -9057861.619,"lower": -9382896.233,"count": 1563,"preSum": 3124 },{ "ndv": 990,"upper": -8741496.846,"lower": -9057583.967,"count": 1562,"preSum": 4687 },{ "ndv": 972,"upper": -8448199.852,"lower": -8741414.179,"count": 1563,"preSum": 6249 },{ "ndv": 994,"upper": -8137517.688,"lower": -8447880.659,"count": 1565,"preSum": 7812 },{ "ndv": 996,"upper": -7815510.652,"lower": -8137114.211,"count": 1563,"preSum": 9377 },{ "ndv": 1006,"upper": -7482956.068,"lower": -7815483.878,"count": 1562,"preSum": 10940 },{ "ndv": 989,"upper": -7165460.269,"lower": -7482705.283,"count": 1563,"preSum": 12502 },{ "ndv": 1000,"upper": -6844443.105,"lower": -7165006.364,"count": 1562,"preSum": 14065 },{ "ndv": 990,"upper": -6520640.097,"lower": -6844376.828,"count": 1562,"preSum": 15627 },{ "ndv": 967,"upper": -6223687.9,"lower": -6520612.807,"count": 1562,"preSum": 17189 },{ "ndv": 1004,"upper": -5914138.632,"lower": -6223564.674,"count": 1562,"preSum": 18751 },{ "ndv": 1006,"upper": -5585899.646,"lower": -5914015.578,"count": 1564,"preSum": 20313 },{ "ndv": 978,"upper": -5271848.95,"lower": -5585655.573,"count": 1562,"preSum": 21877 },{ "ndv": 985,"upper": -4964081.047,"lower": -5271638.986,"count": 1562,"preSum": 23439 },{ "ndv": 976,"upper": -4636185.513,"lower": -4963539.277,"count": 1562,"preSum": 25001 },{ "ndv": 1006,"upper": -4308782.404,"lower": -4636182.338,"count": 1563,"preSum": 26563 },{ "ndv": 968,"upper": -3993252.58,"lower": -4308278.223,"count": 1562,"preSum": 28126 },{ "ndv": 1010,"upper": -3675490.617,"lower": -3992692.119,"count": 1562,"preSum": 29688 },{ "ndv": 990,"upper": -3366418.328,"lower": -3674777.151,"count": 1562,"preSum": 31250 },{ "ndv": 1006,"upper": -3048803.74,"lower": -3366212.892,"count": 1563,"preSum": 32812 },{ "ndv": 971,"upper": -2740122.818,"lower": -3047892.944,"count": 1563,"preSum": 34375 },{ "ndv": 965,"upper": -2436098.683,"lower": -2740099.643,"count": 1562,"preSum": 35938 },{ "ndv": 993,"upper": -2121642.264,"lower": -2435944.65,"count": 1562,"preSum": 37500 },{ "ndv": 1014,"upper": -1799195.828,"lower": -2121482.122,"count": 1562,"preSum": 39062 },{ "ndv": 990,"upper": -1481937.888,"lower": -1799099.502,"count": 1562,"preSum": 40624 },{ "ndv": 995,"upper": -1161751.644,"lower": -1481662.026,"count": 1562,"preSum": 42186 },{ "ndv": 975,"upper": -869974.438,"lower": -1161262.104,"count": 1562,"preSum": 43748 },{ "ndv": 986,"upper": -544154.737,"lower": -869328.08,"count": 1562,"preSum": 45310 },{ "ndv": 977,"upper": -230218.798,"lower": -543942.361,"count": 1564,"preSum": 46872 },{ "ndv": 1008,"upper": 81374.344,"lower": -230021.253,"count": 1562,"preSum": 48436 },{ "ndv": 1008,"upper": 400872.418,"lower": 81612.613,"count": 1563,"preSum": 49998 },{ "ndv": 964,"upper": 717144.149,"lower": 401006.767,"count": 1563,"preSum": 51561 },{ "ndv": 980,"upper": 1009794.659,"lower": 717192.583,"count": 1562,"preSum": 53124 },{ "ndv": 1000,"upper": 1325832.039,"lower": 1010508.178,"count": 1562,"preSum": 54686 },{ "ndv": 968,"upper": 1622177.472,"lower": 1326388.151,"count": 1563,"preSum": 56248 },{ "ndv": 1009,"upper": 1945886.811,"lower": 1622179.743,"count": 1562,"preSum": 57811 },{ "ndv": 984,"upper": 2272604.934,"lower": 1948517.759,"count": 1562,"preSum": 59373 },{ "ndv": 989,"upper": 2585899.522,"lower": 2272767.819,"count": 1562,"preSum": 60935 },{ "ndv": 1001,"upper": 2908624.863,"lower": 2586689.392,"count": 1562,"preSum": 62497 },{ "ndv": 969,"upper": 3225611.512,"lower": 2908923.187,"count": 1563,"preSum": 64059 },{ "ndv": 998,"upper": 3533925.395,"lower": 3225647.877,"count": 1563,"preSum": 65622 },{ "ndv": 1002,"upper": 3852021.739,"lower": 3534243.08,"count": 1562,"preSum": 67185 },{ "ndv": 998,"upper": 4165362.828,"lower": 3852211.87,"count": 1562,"preSum": 68747 },{ "ndv": 975,"upper": 4478687.007,"lower": 4165378.782,"count": 1562,"preSum": 70309 },{ "ndv": 979,"upper": 4787949.769,"lower": 4478843.076,"count": 1562,"preSum": 71871 },{ "ndv": 989,"upper": 5099407.334,"lower": 4788050.956,"count": 1563,"preSum": 73433 },{ "ndv": 984,"upper": 5429261.883,"lower": 5099901.103,"count": 1562,"preSum": 74996 },{ "ndv": 977,"upper": 5745636.757,"lower": 5429666.212,"count": 1562,"preSum": 76558 },{ "ndv": 999,"upper": 6051435.761,"lower": 5745843.396,"count": 1562,"preSum": 78120 },{ "ndv": 970,"upper": 6357134.031,"lower": 6051652.815,"count": 1562,"preSum": 79682 },{ "ndv": 973,"upper": 6647614.001,"lower": 6357416.086,"count": 1563,"preSum": 81244 },{ "ndv": 987,"upper": 6958801.058,"lower": 6647811.304,"count": 1562,"preSum": 82807 },{ "ndv": 1006,"upper": 7278085.187,"lower": 6959099.223,"count": 1563,"preSum": 84369 },{ "ndv": 955,"upper": 7575729.667,"lower": 7278096.703,"count": 1563,"preSum": 85932 },{ "ndv": 953,"upper": 7884497.19,"lower": 7575828.386,"count": 1566,"preSum": 87495 },{ "ndv": 958,"upper": 8181003.153,"lower": 7884649.775,"count": 1563,"preSum": 89061 },{ "ndv": 947,"upper": 8485436.854,"lower": 8181192.258,"count": 1562,"preSum": 90624 },{ "ndv": 977,"upper": 8792801.024,"lower": 8485498.154,"count": 1562,"preSum": 92186 },{ "ndv": 968,"upper": 9089914.984,"lower": 8792920.014,"count": 1562,"preSum": 93748 },{ "ndv": 1012,"upper": 9407722.157,"lower": 9089984.322,"count": 1563,"preSum": 95310 },{ "ndv": 975,"upper": 9705075.149,"lower": 9407969.716,"count": 1562,"preSum": 96873 },{ "ndv": 932,"upper": 9999485.995,"lower": 9705280.986,"count": 1490,"preSum": 98435 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_double_pr.null_count:
+    0
+  cest_full_table_big.c_double_pr.sample_rate:
+    0.010943651
+  cest_full_table_big.c_double_un.TOPN:
+    { "countArr": [ 9,15,11,10,15,10,9,9,9,12,10 ],"valueArr": [ 579376.864,589488.812,1195513.356,2268986.695,5361838.797,5652397.646,6284442.196,7175706.635,8951003.459,8996708.706,9289791.517 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_double_un.cardinality:
+    501587
+  cest_full_table_big.c_double_un.histogram:
+    { "buckets": [ { "ndv": 970,"upper": 159246.627,"lower": 26.457,"count": 1561,"preSum": 0 },{ "ndv": 971,"upper": 314434.056,"lower": 159692.554,"count": 1563,"preSum": 1561 },{ "ndv": 968,"upper": 475173.029,"lower": 314619.316,"count": 1561,"preSum": 3124 },{ "ndv": 954,"upper": 623368.486,"lower": 475240.355,"count": 1561,"preSum": 4685 },{ "ndv": 963,"upper": 773875.089,"lower": 623476.169,"count": 1561,"preSum": 6246 },{ "ndv": 964,"upper": 932282.886,"lower": 774107.105,"count": 1562,"preSum": 7807 },{ "ndv": 974,"upper": 1087350.587,"lower": 932407.214,"count": 1562,"preSum": 9369 },{ "ndv": 978,"upper": 1246042.724,"lower": 1087380.079,"count": 1561,"preSum": 10931 },{ "ndv": 929,"upper": 1386788.029,"lower": 1246043.441,"count": 1562,"preSum": 12492 },{ "ndv": 989,"upper": 1544649.258,"lower": 1386795.856,"count": 1562,"preSum": 14054 },{ "ndv": 961,"upper": 1701283.736,"lower": 1545115.988,"count": 1561,"preSum": 15616 },{ "ndv": 989,"upper": 1853724.921,"lower": 1701311.884,"count": 1563,"preSum": 17177 },{ "ndv": 988,"upper": 2008732.195,"lower": 1853748.04,"count": 1561,"preSum": 18740 },{ "ndv": 964,"upper": 2166881.233,"lower": 2008929.12,"count": 1561,"preSum": 20301 },{ "ndv": 949,"upper": 2328526.388,"lower": 2167097.492,"count": 1561,"preSum": 21862 },{ "ndv": 978,"upper": 2478771.234,"lower": 2328617.193,"count": 1561,"preSum": 23423 },{ "ndv": 977,"upper": 2639328.987,"lower": 2478795.732,"count": 1561,"preSum": 24984 },{ "ndv": 958,"upper": 2800017.192,"lower": 2639523.393,"count": 1562,"preSum": 26545 },{ "ndv": 977,"upper": 2959900.118,"lower": 2800284.925,"count": 1561,"preSum": 28107 },{ "ndv": 949,"upper": 3115957.242,"lower": 2960105.781,"count": 1561,"preSum": 29668 },{ "ndv": 953,"upper": 3273609.171,"lower": 3116424.073,"count": 1561,"preSum": 31229 },{ "ndv": 958,"upper": 3435578.642,"lower": 3273746.521,"count": 1561,"preSum": 32790 },{ "ndv": 972,"upper": 3594827.153,"lower": 3435789.982,"count": 1561,"preSum": 34351 },{ "ndv": 961,"upper": 3749012.432,"lower": 3594833.382,"count": 1561,"preSum": 35912 },{ "ndv": 966,"upper": 3906995.326,"lower": 3749126.212,"count": 1561,"preSum": 37473 },{ "ndv": 979,"upper": 4061573.658,"lower": 3907103.398,"count": 1561,"preSum": 39034 },{ "ndv": 979,"upper": 4234017.338,"lower": 4061790.658,"count": 1561,"preSum": 40595 },{ "ndv": 947,"upper": 4388272.834,"lower": 4234112.103,"count": 1563,"preSum": 42156 },{ "ndv": 1010,"upper": 4542816.868,"lower": 4388318.04,"count": 1561,"preSum": 43719 },{ "ndv": 957,"upper": 4699133.092,"lower": 4542969.239,"count": 1561,"preSum": 45280 },{ "ndv": 989,"upper": 4858917.967,"lower": 4699166.786,"count": 1561,"preSum": 46841 },{ "ndv": 974,"upper": 5015784.431,"lower": 4858919.707,"count": 1561,"preSum": 48402 },{ "ndv": 940,"upper": 5172193.14,"lower": 5015808.583,"count": 1561,"preSum": 49963 },{ "ndv": 946,"upper": 5329967.803,"lower": 5172253.411,"count": 1561,"preSum": 51524 },{ "ndv": 950,"upper": 5485807.676,"lower": 5330430.054,"count": 1561,"preSum": 53085 },{ "ndv": 966,"upper": 5638953.389,"lower": 5486096.929,"count": 1561,"preSum": 54646 },{ "ndv": 963,"upper": 5785892.15,"lower": 5639192.583,"count": 1561,"preSum": 56207 },{ "ndv": 992,"upper": 5946566.835,"lower": 5786019.379,"count": 1561,"preSum": 57768 },{ "ndv": 968,"upper": 6115256.316,"lower": 5946793.059,"count": 1563,"preSum": 59329 },{ "ndv": 973,"upper": 6271303.24,"lower": 6115692.319,"count": 1561,"preSum": 60892 },{ "ndv": 987,"upper": 6432002.686,"lower": 6271318.667,"count": 1563,"preSum": 62453 },{ "ndv": 957,"upper": 6585659.36,"lower": 6432017.873,"count": 1561,"preSum": 64016 },{ "ndv": 958,"upper": 6739287.757,"lower": 6585686.714,"count": 1562,"preSum": 65577 },{ "ndv": 974,"upper": 6892079.205,"lower": 6739340.65,"count": 1561,"preSum": 67139 },{ "ndv": 951,"upper": 7041550.54,"lower": 6892259.675,"count": 1562,"preSum": 68700 },{ "ndv": 937,"upper": 7196266.843,"lower": 7041885.308,"count": 1561,"preSum": 70262 },{ "ndv": 972,"upper": 7350123.268,"lower": 7196481.513,"count": 1561,"preSum": 71823 },{ "ndv": 958,"upper": 7502472.326,"lower": 7350203.104,"count": 1562,"preSum": 73384 },{ "ndv": 961,"upper": 7670739.671,"lower": 7502571.826,"count": 1562,"preSum": 74946 },{ "ndv": 970,"upper": 7824962.233,"lower": 7670751.482,"count": 1561,"preSum": 76508 },{ "ndv": 986,"upper": 7980863.433,"lower": 7825007.99,"count": 1561,"preSum": 78069 },{ "ndv": 958,"upper": 8132716.43,"lower": 7980980.515,"count": 1561,"preSum": 79630 },{ "ndv": 944,"upper": 8278706.714,"lower": 8133046.463,"count": 1561,"preSum": 81191 },{ "ndv": 969,"upper": 8437950.574,"lower": 8278715.044,"count": 1562,"preSum": 82752 },{ "ndv": 969,"upper": 8592619.679,"lower": 8438103.5,"count": 1562,"preSum": 84314 },{ "ndv": 994,"upper": 8749085.919,"lower": 8592691.063,"count": 1561,"preSum": 85876 },{ "ndv": 974,"upper": 8908659.712,"lower": 8749358.531,"count": 1561,"preSum": 87437 },{ "ndv": 957,"upper": 9065845.31,"lower": 8908675.535,"count": 1561,"preSum": 88998 },{ "ndv": 983,"upper": 9219235.611,"lower": 9066003.256,"count": 1562,"preSum": 90559 },{ "ndv": 942,"upper": 9372290.098,"lower": 9219407.511,"count": 1561,"preSum": 92121 },{ "ndv": 967,"upper": 9526104.452,"lower": 9372312.77,"count": 1562,"preSum": 93682 },{ "ndv": 970,"upper": 9678405.216,"lower": 9526176.203,"count": 1561,"preSum": 95244 },{ "ndv": 963,"upper": 9838694.24,"lower": 9678788.337,"count": 1562,"preSum": 96805 },{ "ndv": 959,"upper": 9999883.965,"lower": 9839480.156,"count": 1515,"preSum": 98367 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_double_un.null_count:
+    0
+  cest_full_table_big.c_double_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_enum.TOPN:
+    null
+  cest_full_table_big.c_enum.cardinality:
+    6077822
+  cest_full_table_big.c_enum.histogram:
+    { "buckets": [ { "ndv": 1,"upper": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@6cff8cd2","lower": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@6cff8cd2","count": 58717,"preSum": 0 },{ "ndv": 1,"upper": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@2f31f310","lower": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@2f31f310","count": 25535,"preSum": 58717 },{ "ndv": 1,"upper": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@42d263e4","lower": "com.alibaba.polardbx.optimizer.core.expression.bean.EnumValue@42d263e4","count": 15749,"preSum": 84252 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_enum.null_count:
+    0
+  cest_full_table_big.c_enum.sample_rate:
+    0.010943651
+  cest_full_table_big.c_float.TOPN:
+    { "countArr": [ 7,7,7,8,7,7,7,7,8,7,7,7,7 ],"valueArr": [ 4.1239891E37,1.1064914E38,1.3367538E38,1.4780993E38,1.5061238E38,1.5295853E38,1.5592378E38,2.2266388E38,2.2414423E38,2.7778798E38,2.790829E38,3.3444375E38,3.3500825E38 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_float.cardinality:
+    513663
+  cest_full_table_big.c_float.histogram:
+    { "buckets": [ { "ndv": 993,"upper": 5.504475E36,"lower": 9.002987E32,"count": 1562,"preSum": 0 },{ "ndv": 973,"upper": 1.0540608E37,"lower": 5.509676E36,"count": 1562,"preSum": 1562 },{ "ndv": 975,"upper": 1.5816881E37,"lower": 1.054325E37,"count": 1563,"preSum": 3124 },{ "ndv": 1004,"upper": 2.1079314E37,"lower": 1.5818917E37,"count": 1562,"preSum": 4687 },{ "ndv": 1007,"upper": 2.6555632E37,"lower": 2.1082132E37,"count": 1562,"preSum": 6249 },{ "ndv": 1001,"upper": 3.208725E37,"lower": 2.6562163E37,"count": 1564,"preSum": 7811 },{ "ndv": 988,"upper": 3.7676477E37,"lower": 3.2109004E37,"count": 1563,"preSum": 9375 },{ "ndv": 982,"upper": 4.3041707E37,"lower": 3.7676614E37,"count": 1562,"preSum": 10938 },{ "ndv": 955,"upper": 4.8096073E37,"lower": 4.304625E37,"count": 1563,"preSum": 12500 },{ "ndv": 994,"upper": 5.363682E37,"lower": 4.810363E37,"count": 1563,"preSum": 14063 },{ "ndv": 991,"upper": 5.8993893E37,"lower": 5.3636883E37,"count": 1562,"preSum": 15626 },{ "ndv": 1001,"upper": 6.4090006E37,"lower": 5.900045E37,"count": 1564,"preSum": 17188 },{ "ndv": 999,"upper": 6.932706E37,"lower": 6.40917E37,"count": 1562,"preSum": 18752 },{ "ndv": 1008,"upper": 7.478618E37,"lower": 6.932868E37,"count": 1562,"preSum": 20314 },{ "ndv": 1008,"upper": 8.0282077E37,"lower": 7.4786964E37,"count": 1562,"preSum": 21876 },{ "ndv": 982,"upper": 8.569093E37,"lower": 8.0282285E37,"count": 1563,"preSum": 23438 },{ "ndv": 993,"upper": 9.134226E37,"lower": 8.569959E37,"count": 1563,"preSum": 25001 },{ "ndv": 969,"upper": 9.660971E37,"lower": 9.135152E37,"count": 1562,"preSum": 26564 },{ "ndv": 1000,"upper": 1.020596E38,"lower": 9.661767E37,"count": 1565,"preSum": 28126 },{ "ndv": 984,"upper": 1.0724234E38,"lower": 1.0206114E38,"count": 1563,"preSum": 29691 },{ "ndv": 996,"upper": 1.126432E38,"lower": 1.0725553E38,"count": 1562,"preSum": 31254 },{ "ndv": 974,"upper": 1.1790574E38,"lower": 1.1264713E38,"count": 1562,"preSum": 32816 },{ "ndv": 975,"upper": 1.2344194E38,"lower": 1.179143E38,"count": 1562,"preSum": 34378 },{ "ndv": 989,"upper": 1.2865872E38,"lower": 1.2344337E38,"count": 1562,"preSum": 35940 },{ "ndv": 960,"upper": 1.3379517E38,"lower": 1.2866211E38,"count": 1562,"preSum": 37502 },{ "ndv": 996,"upper": 1.3908793E38,"lower": 1.3379585E38,"count": 1562,"preSum": 39064 },{ "ndv": 981,"upper": 1.4454652E38,"lower": 1.3908964E38,"count": 1562,"preSum": 40626 },{ "ndv": 965,"upper": 1.4961927E38,"lower": 1.4454856E38,"count": 1563,"preSum": 42188 },{ "ndv": 980,"upper": 1.5474628E38,"lower": 1.4962791E38,"count": 1562,"preSum": 43751 },{ "ndv": 970,"upper": 1.599883E38,"lower": 1.547498E38,"count": 1562,"preSum": 45313 },{ "ndv": 1005,"upper": 1.6517319E38,"lower": 1.5998927E38,"count": 1562,"preSum": 46875 },{ "ndv": 989,"upper": 1.705293E38,"lower": 1.6518135E38,"count": 1563,"preSum": 48437 },{ "ndv": 979,"upper": 1.7594877E38,"lower": 1.7053282E38,"count": 1563,"preSum": 50000 },{ "ndv": 957,"upper": 1.8145524E38,"lower": 1.7596962E38,"count": 1565,"preSum": 51563 },{ "ndv": 985,"upper": 1.8667806E38,"lower": 1.8146232E38,"count": 1562,"preSum": 53128 },{ "ndv": 963,"upper": 1.9206412E38,"lower": 1.8668222E38,"count": 1563,"preSum": 54690 },{ "ndv": 992,"upper": 1.9722445E38,"lower": 1.9207111E38,"count": 1562,"preSum": 56253 },{ "ndv": 1016,"upper": 2.0243972E38,"lower": 1.9722554E38,"count": 1564,"preSum": 57815 },{ "ndv": 996,"upper": 2.0799735E38,"lower": 2.0245297E38,"count": 1562,"preSum": 59379 },{ "ndv": 974,"upper": 2.131372E38,"lower": 2.0800542E38,"count": 1562,"preSum": 60941 },{ "ndv": 964,"upper": 2.1852976E38,"lower": 2.1314539E38,"count": 1563,"preSum": 62503 },{ "ndv": 1020,"upper": 2.239636E38,"lower": 2.1853063E38,"count": 1562,"preSum": 64066 },{ "ndv": 973,"upper": 2.2914239E38,"lower": 2.2396429E38,"count": 1562,"preSum": 65628 },{ "ndv": 985,"upper": 2.3434947E38,"lower": 2.291461E38,"count": 1562,"preSum": 67190 },{ "ndv": 991,"upper": 2.3970741E38,"lower": 2.343552E38,"count": 1562,"preSum": 68752 },{ "ndv": 986,"upper": 2.450868E38,"lower": 2.397159E38,"count": 1562,"preSum": 70314 },{ "ndv": 979,"upper": 2.505082E38,"lower": 2.4508826E38,"count": 1563,"preSum": 71876 },{ "ndv": 998,"upper": 2.5577175E38,"lower": 2.5051161E38,"count": 1563,"preSum": 73439 },{ "ndv": 961,"upper": 2.6130388E38,"lower": 2.557734E38,"count": 1562,"preSum": 75002 },{ "ndv": 1013,"upper": 2.6671332E38,"lower": 2.6131362E38,"count": 1563,"preSum": 76564 },{ "ndv": 994,"upper": 2.7174385E38,"lower": 2.6671955E38,"count": 1562,"preSum": 78127 },{ "ndv": 965,"upper": 2.769718E38,"lower": 2.7174441E38,"count": 1562,"preSum": 79689 },{ "ndv": 989,"upper": 2.8220551E38,"lower": 2.7697561E38,"count": 1564,"preSum": 81251 },{ "ndv": 990,"upper": 2.874569E38,"lower": 2.8220841E38,"count": 1562,"preSum": 82815 },{ "ndv": 1005,"upper": 2.9281611E38,"lower": 2.8746296E38,"count": 1564,"preSum": 84377 },{ "ndv": 977,"upper": 2.9815347E38,"lower": 2.9281674E38,"count": 1564,"preSum": 85941 },{ "ndv": 988,"upper": 3.0359942E38,"lower": 2.9815426E38,"count": 1562,"preSum": 87505 },{ "ndv": 947,"upper": 3.0858262E38,"lower": 3.0361106E38,"count": 1563,"preSum": 89067 },{ "ndv": 1014,"upper": 3.1412307E38,"lower": 3.0858524E38,"count": 1562,"preSum": 90630 },{ "ndv": 974,"upper": 3.1956198E38,"lower": 3.141308E38,"count": 1562,"preSum": 92192 },{ "ndv": 982,"upper": 3.2469834E38,"lower": 3.1956403E38,"count": 1562,"preSum": 93754 },{ "ndv": 1008,"upper": 3.3000744E38,"lower": 3.2469957E38,"count": 1563,"preSum": 95316 },{ "ndv": 1030,"upper": 3.353673E38,"lower": 3.3001219E38,"count": 1562,"preSum": 96879 },{ "ndv": 911,"upper": 3.4027498E38,"lower": 3.3536897E38,"count": 1467,"preSum": 98441 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_float.null_count:
+    0
+  cest_full_table_big.c_float.sample_rate:
+    0.010943651
+  cest_full_table_big.c_float_pr.TOPN:
+    { "countArr": [ 9,9,10,11,11 ],"valueArr": [ -6092099.5,-3607966.8,-3078055.0,-1173031.5,7679962.0 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_float_pr.cardinality:
+    505636
+  cest_full_table_big.c_float_pr.histogram:
+    { "buckets": [ { "ndv": 964,"upper": -9684324.0,"lower": -9999946.0,"count": 1564,"preSum": 0 },{ "ndv": 976,"upper": -9369876.0,"lower": -9683913.0,"count": 1562,"preSum": 1564 },{ "ndv": 974,"upper": -9046497.0,"lower": -9369645.0,"count": 1563,"preSum": 3126 },{ "ndv": 966,"upper": -8731335.0,"lower": -9046170.0,"count": 1562,"preSum": 4689 },{ "ndv": 973,"upper": -8417582.0,"lower": -8731202.0,"count": 1562,"preSum": 6251 },{ "ndv": 972,"upper": -8093540.0,"lower": -8417506.0,"count": 1562,"preSum": 7813 },{ "ndv": 970,"upper": -7760209.0,"lower": -8093490.5,"count": 1562,"preSum": 9375 },{ "ndv": 957,"upper": -7448782.5,"lower": -7760201.5,"count": 1563,"preSum": 10937 },{ "ndv": 958,"upper": -7140704.5,"lower": -7448777.5,"count": 1562,"preSum": 12500 },{ "ndv": 1003,"upper": -6814441.0,"lower": -7140374.0,"count": 1563,"preSum": 14062 },{ "ndv": 970,"upper": -6505989.0,"lower": -6814231.0,"count": 1563,"preSum": 15625 },{ "ndv": 952,"upper": -6216140.5,"lower": -6505895.0,"count": 1563,"preSum": 17188 },{ "ndv": 968,"upper": -5910459.5,"lower": -6216120.0,"count": 1562,"preSum": 18751 },{ "ndv": 970,"upper": -5591733.5,"lower": -5910418.5,"count": 1562,"preSum": 20313 },{ "ndv": 963,"upper": -5284048.5,"lower": -5591710.0,"count": 1562,"preSum": 21875 },{ "ndv": 973,"upper": -4976923.0,"lower": -5283625.0,"count": 1562,"preSum": 23437 },{ "ndv": 919,"upper": -4669777.0,"lower": -4976309.0,"count": 1562,"preSum": 24999 },{ "ndv": 983,"upper": -4350905.5,"lower": -4669552.5,"count": 1562,"preSum": 26561 },{ "ndv": 1014,"upper": -4025384.5,"lower": -4350720.5,"count": 1562,"preSum": 28123 },{ "ndv": 950,"upper": -3709999.5,"lower": -4025063.5,"count": 1562,"preSum": 29685 },{ "ndv": 938,"upper": -3405368.2,"lower": -3709328.2,"count": 1562,"preSum": 31247 },{ "ndv": 976,"upper": -3097215.8,"lower": -3405120.2,"count": 1563,"preSum": 32809 },{ "ndv": 983,"upper": -2772088.5,"lower": -3096911.8,"count": 1562,"preSum": 34372 },{ "ndv": 998,"upper": -2460747.5,"lower": -2771973.0,"count": 1562,"preSum": 35934 },{ "ndv": 998,"upper": -2137111.0,"lower": -2459697.0,"count": 1563,"preSum": 37496 },{ "ndv": 989,"upper": -1831150.8,"lower": -2136815.2,"count": 1562,"preSum": 39059 },{ "ndv": 968,"upper": -1510433.4,"lower": -1830351.4,"count": 1563,"preSum": 40621 },{ "ndv": 959,"upper": -1196050.2,"lower": -1510194.9,"count": 1563,"preSum": 42184 },{ "ndv": 977,"upper": -879686.0,"lower": -1195765.8,"count": 1562,"preSum": 43747 },{ "ndv": 951,"upper": -569589.06,"lower": -879521.2,"count": 1563,"preSum": 45309 },{ "ndv": 984,"upper": -250843.02,"lower": -568810.25,"count": 1562,"preSum": 46872 },{ "ndv": 979,"upper": 56949.613,"lower": -250737.78,"count": 1563,"preSum": 48434 },{ "ndv": 973,"upper": 376945.3,"lower": 57204.12,"count": 1564,"preSum": 49997 },{ "ndv": 961,"upper": 680584.1,"lower": 377233.84,"count": 1562,"preSum": 51561 },{ "ndv": 989,"upper": 993792.2,"lower": 681034.2,"count": 1564,"preSum": 53123 },{ "ndv": 974,"upper": 1306808.1,"lower": 993849.56,"count": 1562,"preSum": 54687 },{ "ndv": 939,"upper": 1593479.2,"lower": 1306939.1,"count": 1562,"preSum": 56249 },{ "ndv": 980,"upper": 1907529.1,"lower": 1593729.1,"count": 1562,"preSum": 57811 },{ "ndv": 958,"upper": 2229117.5,"lower": 1907937.8,"count": 1562,"preSum": 59373 },{ "ndv": 984,"upper": 2544615.5,"lower": 2229840.0,"count": 1565,"preSum": 60935 },{ "ndv": 971,"upper": 2864125.5,"lower": 2545569.8,"count": 1562,"preSum": 62500 },{ "ndv": 995,"upper": 3186146.5,"lower": 2864261.5,"count": 1562,"preSum": 64062 },{ "ndv": 978,"upper": 3502067.0,"lower": 3186152.8,"count": 1562,"preSum": 65624 },{ "ndv": 982,"upper": 3809239.5,"lower": 3502283.8,"count": 1563,"preSum": 67186 },{ "ndv": 959,"upper": 4104175.8,"lower": 3809307.2,"count": 1562,"preSum": 68749 },{ "ndv": 1000,"upper": 4423520.0,"lower": 4104301.8,"count": 1563,"preSum": 70311 },{ "ndv": 965,"upper": 4730817.0,"lower": 4423834.5,"count": 1562,"preSum": 71874 },{ "ndv": 986,"upper": 5025642.0,"lower": 4731352.5,"count": 1563,"preSum": 73436 },{ "ndv": 962,"upper": 5343345.0,"lower": 5025767.5,"count": 1563,"preSum": 74999 },{ "ndv": 969,"upper": 5654442.5,"lower": 5343345.5,"count": 1562,"preSum": 76562 },{ "ndv": 975,"upper": 5956735.0,"lower": 5654894.0,"count": 1562,"preSum": 78124 },{ "ndv": 1002,"upper": 6278939.5,"lower": 5956743.0,"count": 1562,"preSum": 79686 },{ "ndv": 954,"upper": 6578534.0,"lower": 6278957.5,"count": 1563,"preSum": 81248 },{ "ndv": 995,"upper": 6887688.5,"lower": 6578604.0,"count": 1562,"preSum": 82811 },{ "ndv": 976,"upper": 7206946.5,"lower": 6887787.0,"count": 1562,"preSum": 84373 },{ "ndv": 987,"upper": 7526653.0,"lower": 7207063.0,"count": 1562,"preSum": 85935 },{ "ndv": 994,"upper": 7860585.5,"lower": 7527041.0,"count": 1563,"preSum": 87497 },{ "ndv": 948,"upper": 8160759.0,"lower": 7860812.0,"count": 1563,"preSum": 89060 },{ "ndv": 964,"upper": 8474385.0,"lower": 8160832.0,"count": 1563,"preSum": 90623 },{ "ndv": 988,"upper": 8789618.0,"lower": 8474826.0,"count": 1562,"preSum": 92186 },{ "ndv": 962,"upper": 9078129.0,"lower": 8790325.0,"count": 1562,"preSum": 93748 },{ "ndv": 971,"upper": 9384573.0,"lower": 9078236.0,"count": 1563,"preSum": 95310 },{ "ndv": 977,"upper": 9682653.0,"lower": 9385154.0,"count": 1562,"preSum": 96873 },{ "ndv": 949,"upper": 9999486.0,"lower": 9682788.0,"count": 1516,"preSum": 98435 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_float_pr.null_count:
+    0
+  cest_full_table_big.c_float_pr.sample_rate:
+    0.010943651
+  cest_full_table_big.c_float_un.TOPN:
+    { "countArr": [ 20,16,13,12,14,13,17,14 ],"valueArr": [ 589488.8,1195513.4,2414704.2,2637702.0,3286432.5,5361839.0,6819963.5,9475507.0 ],"type": "Double","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_float_un.cardinality:
+    494291
+  cest_full_table_big.c_float_un.histogram:
+    { "buckets": [ { "ndv": 936,"upper": 151688.97,"lower": 86.998,"count": 1564,"preSum": 0 },{ "ndv": 938,"upper": 310237.72,"lower": 151814.73,"count": 1561,"preSum": 1564 },{ "ndv": 971,"upper": 473776.72,"lower": 311067.66,"count": 1562,"preSum": 3125 },{ "ndv": 924,"upper": 621165.4,"lower": 474045.16,"count": 1563,"preSum": 4687 },{ "ndv": 966,"upper": 775226.06,"lower": 621214.7,"count": 1561,"preSum": 6250 },{ "ndv": 956,"upper": 938563.6,"lower": 775343.0,"count": 1561,"preSum": 7811 },{ "ndv": 959,"upper": 1097381.8,"lower": 938809.25,"count": 1562,"preSum": 9372 },{ "ndv": 937,"upper": 1256796.2,"lower": 1097590.2,"count": 1561,"preSum": 10934 },{ "ndv": 963,"upper": 1417155.1,"lower": 1256848.8,"count": 1561,"preSum": 12495 },{ "ndv": 950,"upper": 1578052.6,"lower": 1417496.4,"count": 1561,"preSum": 14056 },{ "ndv": 978,"upper": 1739527.4,"lower": 1578738.0,"count": 1562,"preSum": 15617 },{ "ndv": 938,"upper": 1886050.5,"lower": 1739601.4,"count": 1562,"preSum": 17179 },{ "ndv": 928,"upper": 2030263.6,"lower": 1886084.4,"count": 1563,"preSum": 18741 },{ "ndv": 993,"upper": 2203592.8,"lower": 2030274.4,"count": 1563,"preSum": 20304 },{ "ndv": 926,"upper": 2356762.0,"lower": 2203654.2,"count": 1564,"preSum": 21867 },{ "ndv": 984,"upper": 2517586.2,"lower": 2356784.8,"count": 1561,"preSum": 23431 },{ "ndv": 936,"upper": 2675512.8,"lower": 2517688.0,"count": 1561,"preSum": 24992 },{ "ndv": 953,"upper": 2832216.8,"lower": 2675596.8,"count": 1561,"preSum": 26553 },{ "ndv": 942,"upper": 2991048.0,"lower": 2832394.0,"count": 1561,"preSum": 28114 },{ "ndv": 950,"upper": 3138771.8,"lower": 2991117.2,"count": 1562,"preSum": 29675 },{ "ndv": 970,"upper": 3302888.0,"lower": 3138937.0,"count": 1561,"preSum": 31237 },{ "ndv": 987,"upper": 3459885.2,"lower": 3303147.8,"count": 1561,"preSum": 32798 },{ "ndv": 974,"upper": 3627328.5,"lower": 3459954.8,"count": 1561,"preSum": 34359 },{ "ndv": 954,"upper": 3785672.0,"lower": 3627513.2,"count": 1561,"preSum": 35920 },{ "ndv": 945,"upper": 3941444.2,"lower": 3785861.8,"count": 1562,"preSum": 37481 },{ "ndv": 946,"upper": 4089786.0,"lower": 3941446.0,"count": 1561,"preSum": 39043 },{ "ndv": 966,"upper": 4255241.0,"lower": 4089934.8,"count": 1562,"preSum": 40604 },{ "ndv": 959,"upper": 4414551.5,"lower": 4255396.5,"count": 1562,"preSum": 42166 },{ "ndv": 947,"upper": 4568288.5,"lower": 4414555.5,"count": 1561,"preSum": 43728 },{ "ndv": 963,"upper": 4726591.0,"lower": 4568316.0,"count": 1562,"preSum": 45289 },{ "ndv": 966,"upper": 4887419.0,"lower": 4726607.0,"count": 1563,"preSum": 46851 },{ "ndv": 978,"upper": 5045942.5,"lower": 4887621.0,"count": 1563,"preSum": 48414 },{ "ndv": 957,"upper": 5205647.5,"lower": 5046174.0,"count": 1561,"preSum": 49977 },{ "ndv": 929,"upper": 5359276.5,"lower": 5205724.5,"count": 1561,"preSum": 51538 },{ "ndv": 945,"upper": 5511453.5,"lower": 5359427.0,"count": 1561,"preSum": 53099 },{ "ndv": 905,"upper": 5662793.0,"lower": 5511467.0,"count": 1562,"preSum": 54660 },{ "ndv": 973,"upper": 5815646.0,"lower": 5662834.0,"count": 1562,"preSum": 56222 },{ "ndv": 967,"upper": 5976476.0,"lower": 5815878.0,"count": 1561,"preSum": 57784 },{ "ndv": 930,"upper": 6140401.0,"lower": 5976720.5,"count": 1561,"preSum": 59345 },{ "ndv": 937,"upper": 6290344.5,"lower": 6140456.5,"count": 1562,"preSum": 60906 },{ "ndv": 973,"upper": 6447959.5,"lower": 6290541.0,"count": 1562,"preSum": 62468 },{ "ndv": 945,"upper": 6600870.0,"lower": 6448226.0,"count": 1561,"preSum": 64030 },{ "ndv": 943,"upper": 6751195.0,"lower": 6601013.0,"count": 1562,"preSum": 65591 },{ "ndv": 928,"upper": 6904822.0,"lower": 6751454.5,"count": 1562,"preSum": 67153 },{ "ndv": 951,"upper": 7064430.0,"lower": 6904928.0,"count": 1564,"preSum": 68715 },{ "ndv": 942,"upper": 7226650.0,"lower": 7064552.5,"count": 1562,"preSum": 70279 },{ "ndv": 944,"upper": 7383956.0,"lower": 7226743.5,"count": 1561,"preSum": 71841 },{ "ndv": 960,"upper": 7538594.5,"lower": 7383957.0,"count": 1561,"preSum": 73402 },{ "ndv": 952,"upper": 7704869.0,"lower": 7538627.0,"count": 1561,"preSum": 74963 },{ "ndv": 984,"upper": 7866691.0,"lower": 7704933.0,"count": 1562,"preSum": 76524 },{ "ndv": 946,"upper": 8012367.0,"lower": 7866694.0,"count": 1561,"preSum": 78086 },{ "ndv": 965,"upper": 8165894.0,"lower": 8012714.5,"count": 1561,"preSum": 79647 },{ "ndv": 937,"upper": 8312316.5,"lower": 8165947.0,"count": 1562,"preSum": 81208 },{ "ndv": 927,"upper": 8459721.0,"lower": 8312752.0,"count": 1561,"preSum": 82770 },{ "ndv": 935,"upper": 8617789.0,"lower": 8460122.0,"count": 1561,"preSum": 84331 },{ "ndv": 942,"upper": 8767813.0,"lower": 8617907.0,"count": 1562,"preSum": 85892 },{ "ndv": 935,"upper": 8926592.0,"lower": 8767903.0,"count": 1561,"preSum": 87454 },{ "ndv": 926,"upper": 9076115.0,"lower": 8926674.0,"count": 1561,"preSum": 89015 },{ "ndv": 960,"upper": 9233239.0,"lower": 9076390.0,"count": 1561,"preSum": 90576 },{ "ndv": 927,"upper": 9391142.0,"lower": 9233739.0,"count": 1561,"preSum": 92137 },{ "ndv": 953,"upper": 9539327.0,"lower": 9391275.0,"count": 1561,"preSum": 93698 },{ "ndv": 941,"upper": 9692483.0,"lower": 9539341.0,"count": 1563,"preSum": 95259 },{ "ndv": 980,"upper": 9850446.0,"lower": 9692830.0,"count": 1561,"preSum": 96822 },{ "ndv": 923,"upper": 9999782.0,"lower": 9850470.0,"count": 1499,"preSum": 98383 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90062594 }
+  cest_full_table_big.c_float_un.null_count:
+    0
+  cest_full_table_big.c_float_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_int_1.TOPN:
+    { "countArr": [ 599,663,293,2213,428,966,461,287,361,373,1220,510,265,351 ],"valueArr": [ -2114287725,-1882521012,-1829648591,-1366704471,-1342386297,-1284743463,-1111039198,-1024432730,-845681049,-750951495,-652330026,171784479,1975875333,2102038600 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_int_1.cardinality:
+    366727
+  cest_full_table_big.c_int_1.histogram:
+    { "buckets": [ { "ndv": 684,"upper": -2074506914,"lower": -2147478353,"count": 1423,"preSum": 0 },{ "ndv": 629,"upper": -2003232477,"lower": -2074494945,"count": 1423,"preSum": 1423 },{ "ndv": 624,"upper": -1938580814,"lower": -2002908070,"count": 1424,"preSum": 2846 },{ "ndv": 638,"upper": -1864280238,"lower": -1938527048,"count": 1424,"preSum": 4270 },{ "ndv": 603,"upper": -1798986376,"lower": -1864275902,"count": 1424,"preSum": 5694 },{ "ndv": 634,"upper": -1728917649,"lower": -1798894717,"count": 1423,"preSum": 7118 },{ "ndv": 662,"upper": -1650596497,"lower": -1728840458,"count": 1423,"preSum": 8541 },{ "ndv": 632,"upper": -1585988361,"lower": -1650401255,"count": 1424,"preSum": 9964 },{ "ndv": 709,"upper": -1512170179,"lower": -1585866030,"count": 1423,"preSum": 11388 },{ "ndv": 539,"upper": -1450527960,"lower": -1512103099,"count": 1438,"preSum": 12811 },{ "ndv": 649,"upper": -1377339432,"lower": -1450477080,"count": 1423,"preSum": 14249 },{ "ndv": 709,"upper": -1299879330,"lower": -1377141060,"count": 1423,"preSum": 15672 },{ "ndv": 562,"upper": -1240840843,"lower": -1299825740,"count": 1423,"preSum": 17095 },{ "ndv": 654,"upper": -1170100321,"lower": -1240786007,"count": 1520,"preSum": 18518 },{ "ndv": 663,"upper": -1099961725,"lower": -1169992660,"count": 1423,"preSum": 20038 },{ "ndv": 618,"upper": -1031130346,"lower": -1099871492,"count": 1434,"preSum": 21461 },{ "ndv": 569,"upper": -971805522,"lower": -1030992917,"count": 1455,"preSum": 22895 },{ "ndv": 587,"upper": -909262959,"lower": -971758662,"count": 1426,"preSum": 24350 },{ "ndv": 618,"upper": -843504224,"lower": -909138280,"count": 1469,"preSum": 25776 },{ "ndv": 588,"upper": -783789132,"lower": -843284510,"count": 1584,"preSum": 27245 },{ "ndv": 758,"upper": -698081811,"lower": -783768125,"count": 1425,"preSum": 28829 },{ "ndv": 559,"upper": -638568104,"lower": -698046210,"count": 1424,"preSum": 30254 },{ "ndv": 738,"upper": -557684205,"lower": -638506136,"count": 1424,"preSum": 31678 },{ "ndv": 612,"upper": -491814823,"lower": -557560574,"count": 1452,"preSum": 33102 },{ "ndv": 629,"upper": -425091649,"lower": -491771542,"count": 1479,"preSum": 34554 },{ "ndv": 658,"upper": -354359116,"lower": -425085893,"count": 1423,"preSum": 36033 },{ "ndv": 674,"upper": -278890396,"lower": -354350566,"count": 1423,"preSum": 37456 },{ "ndv": 714,"upper": -202483880,"lower": -278790320,"count": 1425,"preSum": 38879 },{ "ndv": 616,"upper": -138008072,"lower": -202478059,"count": 1423,"preSum": 40304 },{ "ndv": 629,"upper": -65784201,"lower": -137983234,"count": 1423,"preSum": 41727 },{ "ndv": 618,"upper": 759812,"lower": -65762336,"count": 1423,"preSum": 43150 },{ "ndv": 734,"upper": 78550570,"lower": 821495,"count": 1423,"preSum": 44573 },{ "ndv": 536,"upper": 137680427,"lower": 78723384,"count": 1444,"preSum": 45996 },{ "ndv": 610,"upper": 201480868,"lower": 137799148,"count": 1425,"preSum": 47440 },{ "ndv": 577,"upper": 262650263,"lower": 201699875,"count": 1423,"preSum": 48865 },{ "ndv": 624,"upper": 329276030,"lower": 262713290,"count": 1452,"preSum": 50288 },{ "ndv": 702,"upper": 404705759,"lower": 329280136,"count": 1423,"preSum": 51740 },{ "ndv": 691,"upper": 477201339,"lower": 404753441,"count": 1428,"preSum": 53163 },{ "ndv": 539,"upper": 536183934,"lower": 477326151,"count": 1424,"preSum": 54591 },{ "ndv": 693,"upper": 607524911,"lower": 536234121,"count": 1428,"preSum": 56015 },{ "ndv": 594,"upper": 668675773,"lower": 607659991,"count": 1423,"preSum": 57443 },{ "ndv": 564,"upper": 727868155,"lower": 668696283,"count": 1423,"preSum": 58866 },{ "ndv": 592,"upper": 795317526,"lower": 728006460,"count": 1423,"preSum": 60289 },{ "ndv": 539,"upper": 850744436,"lower": 795337566,"count": 1423,"preSum": 61712 },{ "ndv": 613,"upper": 916150895,"lower": 850753944,"count": 1425,"preSum": 63135 },{ "ndv": 550,"upper": 974090564,"lower": 916216339,"count": 1423,"preSum": 64560 },{ "ndv": 706,"upper": 1048554634,"lower": 974236554,"count": 1425,"preSum": 65983 },{ "ndv": 527,"upper": 1110516419,"lower": 1048646249,"count": 1423,"preSum": 67408 },{ "ndv": 594,"upper": 1174541012,"lower": 1110535263,"count": 1423,"preSum": 68831 },{ "ndv": 655,"upper": 1243516297,"lower": 1174574580,"count": 1502,"preSum": 70254 },{ "ndv": 721,"upper": 1321715633,"lower": 1243544252,"count": 1423,"preSum": 71756 },{ "ndv": 702,"upper": 1399808382,"lower": 1321736658,"count": 1424,"preSum": 73179 },{ "ndv": 625,"upper": 1468262346,"lower": 1399841778,"count": 1424,"preSum": 74603 },{ "ndv": 540,"upper": 1529108592,"lower": 1468291810,"count": 1423,"preSum": 76027 },{ "ndv": 601,"upper": 1591902937,"lower": 1529174618,"count": 1423,"preSum": 77450 },{ "ndv": 597,"upper": 1650723944,"lower": 1591979163,"count": 1424,"preSum": 78873 },{ "ndv": 692,"upper": 1727531405,"lower": 1650769428,"count": 1423,"preSum": 80297 },{ "ndv": 580,"upper": 1790674608,"lower": 1727740641,"count": 1423,"preSum": 81720 },{ "ndv": 636,"upper": 1858104612,"lower": 1790870562,"count": 1424,"preSum": 83143 },{ "ndv": 648,"upper": 1928294403,"lower": 1858139999,"count": 1423,"preSum": 84567 },{ "ndv": 625,"upper": 1992647664,"lower": 1928468477,"count": 1539,"preSum": 85990 },{ "ndv": 725,"upper": 2061649554,"lower": 1992836751,"count": 1439,"preSum": 87529 },{ "ndv": 562,"upper": 2116878413,"lower": 2061735788,"count": 1444,"preSum": 88968 },{ "ndv": 272,"upper": 2147283591,"lower": 2116884239,"count": 599,"preSum": 90412 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_int_1.null_count:
+    0
+  cest_full_table_big.c_int_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_int_32.TOPN:
+    { "countArr": [ 1689,2040,617,8210,1126,2782,1175,720,815,872,4184,1391,575,745 ],"valueArr": [ -2114287725,-1882521012,-1829648591,-1366704471,-1342386297,-1284743463,-1111039198,-1024432730,-845681049,-750951495,-652330026,171784479,1975875333,2102038600 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_int_32.cardinality:
+    243421
+  cest_full_table_big.c_int_32.histogram:
+    { "buckets": [ { "ndv": 481,"upper": -2059568640,"lower": -2147478353,"count": 1195,"preSum": 0 },{ "ndv": 464,"upper": -1976243250,"lower": -2059567210,"count": 1142,"preSum": 1195 },{ "ndv": 421,"upper": -1902459046,"lower": -1976174034,"count": 1143,"preSum": 2337 },{ "ndv": 371,"upper": -1836186294,"lower": -1902320799,"count": 1568,"preSum": 3480 },{ "ndv": 494,"upper": -1745723374,"lower": -1836001401,"count": 1161,"preSum": 5048 },{ "ndv": 408,"upper": -1673084409,"lower": -1745693414,"count": 1153,"preSum": 6209 },{ "ndv": 447,"upper": -1598399519,"lower": -1672451140,"count": 1142,"preSum": 7362 },{ "ndv": 499,"upper": -1512206281,"lower": -1598280131,"count": 1145,"preSum": 8504 },{ "ndv": 306,"upper": -1461569257,"lower": -1512170179,"count": 1171,"preSum": 9649 },{ "ndv": 434,"upper": -1380131638,"lower": -1461516726,"count": 1144,"preSum": 10820 },{ "ndv": 472,"upper": -1293657631,"lower": -1380099151,"count": 1147,"preSum": 11964 },{ "ndv": 304,"upper": -1241458321,"lower": -1293572679,"count": 1143,"preSum": 13111 },{ "ndv": 379,"upper": -1170100321,"lower": -1241335228,"count": 1287,"preSum": 14254 },{ "ndv": 482,"upper": -1087612618,"lower": -1169975712,"count": 1142,"preSum": 15541 },{ "ndv": 349,"upper": -1029590024,"lower": -1087561375,"count": 1146,"preSum": 16683 },{ "ndv": 334,"upper": -971805522,"lower": -1029441603,"count": 1228,"preSum": 17829 },{ "ndv": 278,"upper": -922860550,"lower": -971743209,"count": 1143,"preSum": 19057 },{ "ndv": 377,"upper": -855680901,"lower": -922551552,"count": 1142,"preSum": 20200 },{ "ndv": 308,"upper": -805093714,"lower": -855412029,"count": 1142,"preSum": 21342 },{ "ndv": 387,"upper": -732762352,"lower": -805067111,"count": 1142,"preSum": 22484 },{ "ndv": 408,"upper": -658487795,"lower": -732527512,"count": 1354,"preSum": 23626 },{ "ndv": 500,"upper": -565840013,"lower": -658312674,"count": 1146,"preSum": 24980 },{ "ndv": 328,"upper": -509590838,"lower": -565300275,"count": 1197,"preSum": 26126 },{ "ndv": 353,"upper": -448463230,"lower": -509569129,"count": 1145,"preSum": 27323 },{ "ndv": 324,"upper": -390087326,"lower": -448182367,"count": 1145,"preSum": 28468 },{ "ndv": 462,"upper": -302136078,"lower": -389792263,"count": 1143,"preSum": 29613 },{ "ndv": 458,"upper": -224950358,"lower": -302041887,"count": 1175,"preSum": 30756 },{ "ndv": 428,"upper": -154230186,"lower": -224457087,"count": 1157,"preSum": 31931 },{ "ndv": 288,"upper": -101053521,"lower": -154068748,"count": 1142,"preSum": 33088 },{ "ndv": 468,"upper": -13225259,"lower": -101016076,"count": 1270,"preSum": 34230 },{ "ndv": 543,"upper": 76068590,"lower": -12850435,"count": 1164,"preSum": 35500 },{ "ndv": 319,"upper": 128732106,"lower": 76193911,"count": 1190,"preSum": 36664 },{ "ndv": 234,"upper": 166737107,"lower": 128823998,"count": 1150,"preSum": 37854 },{ "ndv": 444,"upper": 242848040,"lower": 166929910,"count": 1186,"preSum": 39004 },{ "ndv": 394,"upper": 310897256,"lower": 242937616,"count": 1152,"preSum": 40190 },{ "ndv": 517,"upper": 399681040,"lower": 311130615,"count": 1142,"preSum": 41342 },{ "ndv": 470,"upper": 485427209,"lower": 399706744,"count": 1142,"preSum": 42484 },{ "ndv": 255,"upper": 533217626,"lower": 485711904,"count": 1256,"preSum": 43626 },{ "ndv": 426,"upper": 609471793,"lower": 533230999,"count": 1196,"preSum": 44882 },{ "ndv": 383,"upper": 672822679,"lower": 609519810,"count": 1142,"preSum": 46078 },{ "ndv": 333,"upper": 732857150,"lower": 672914799,"count": 1142,"preSum": 47220 },{ "ndv": 342,"upper": 799751831,"lower": 732860103,"count": 1149,"preSum": 48362 },{ "ndv": 248,"upper": 842116146,"lower": 799812868,"count": 1190,"preSum": 49511 },{ "ndv": 366,"upper": 909252806,"lower": 842274177,"count": 1143,"preSum": 50701 },{ "ndv": 310,"upper": 961469422,"lower": 909520175,"count": 1142,"preSum": 51844 },{ "ndv": 471,"upper": 1046507890,"lower": 961899431,"count": 1142,"preSum": 52986 },{ "ndv": 291,"upper": 1100624309,"lower": 1046595744,"count": 1164,"preSum": 54128 },{ "ndv": 348,"upper": 1164768208,"lower": 1100625895,"count": 1142,"preSum": 55292 },{ "ndv": 439,"upper": 1240328180,"lower": 1164777182,"count": 1142,"preSum": 56434 },{ "ndv": 401,"upper": 1307206398,"lower": 1240530312,"count": 1142,"preSum": 57576 },{ "ndv": 548,"upper": 1405102988,"lower": 1307369657,"count": 1168,"preSum": 58718 },{ "ndv": 447,"upper": 1480838532,"lower": 1405152654,"count": 1142,"preSum": 59886 },{ "ndv": 261,"upper": 1528822093,"lower": 1481009657,"count": 1303,"preSum": 61028 },{ "ndv": 400,"upper": 1596971174,"lower": 1529105540,"count": 1143,"preSum": 62331 },{ "ndv": 338,"upper": 1652837140,"lower": 1597008497,"count": 1142,"preSum": 63474 },{ "ndv": 479,"upper": 1740254580,"lower": 1653100644,"count": 1143,"preSum": 64616 },{ "ndv": 304,"upper": 1795509045,"lower": 1740597775,"count": 1168,"preSum": 65759 },{ "ndv": 443,"upper": 1864662820,"lower": 1795527319,"count": 1142,"preSum": 66927 },{ "ndv": 404,"upper": 1936645028,"lower": 1864681439,"count": 1146,"preSum": 68069 },{ "ndv": 348,"upper": 1997127321,"lower": 1936700220,"count": 1142,"preSum": 69215 },{ "ndv": 507,"upper": 2079632219,"lower": 1997200038,"count": 1142,"preSum": 70357 },{ "ndv": 251,"upper": 2124107623,"lower": 2080211293,"count": 1142,"preSum": 71499 },{ "ndv": 143,"upper": 2147083146,"lower": 2124491826,"count": 419,"preSum": 72641 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_int_32.null_count:
+    0
+  cest_full_table_big.c_int_32.sample_rate:
+    0.010943651
+  cest_full_table_big.c_int_32_un.TOPN:
+    { "countArr": [ 2792,2316,3757,888,19669,1626,5129,1931,987,1212,1427,8436,858,1088 ],"valueArr": [ 33195923,171784479,264962636,317835057,780779177,805097351,862740185,1036444450,1123050918,1301802599,1396532153,1495153622,1975875333,2102038600 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_int_32_un.cardinality:
+    115437
+  cest_full_table_big.c_int_32_un.histogram:
+    { "buckets": [ { "ndv": 260,"upper": 51911622,"lower": 5295,"count": 749,"preSum": 0 },{ "ndv": 191,"upper": 95943779,"lower": 52856262,"count": 910,"preSum": 749 },{ "ndv": 236,"upper": 137680427,"lower": 96710486,"count": 862,"preSum": 1659 },{ "ndv": 150,"upper": 166492152,"lower": 138230437,"count": 1083,"preSum": 2521 },{ "ndv": 223,"upper": 208902840,"lower": 166737107,"count": 749,"preSum": 3604 },{ "ndv": 216,"upper": 247401951,"lower": 208902965,"count": 749,"preSum": 4353 },{ "ndv": 144,"upper": 274099910,"lower": 247601336,"count": 771,"preSum": 5102 },{ "ndv": 204,"upper": 311297354,"lower": 274103362,"count": 1316,"preSum": 5873 },{ "ndv": 278,"upper": 364997941,"lower": 311311439,"count": 758,"preSum": 7189 },{ "ndv": 297,"upper": 421955227,"lower": 365054463,"count": 749,"preSum": 7947 },{ "ndv": 268,"upper": 474399239,"lower": 422063244,"count": 778,"preSum": 8696 },{ "ndv": 236,"upper": 517269091,"lower": 474419183,"count": 751,"preSum": 9474 },{ "ndv": 39,"upper": 525980030,"lower": 517384958,"count": 943,"preSum": 10225 },{ "ndv": 211,"upper": 563330507,"lower": 525985770,"count": 749,"preSum": 11168 },{ "ndv": 234,"upper": 610644978,"lower": 563847197,"count": 749,"preSum": 11917 },{ "ndv": 201,"upper": 648154117,"lower": 610953376,"count": 759,"preSum": 12666 },{ "ndv": 154,"upper": 675721687,"lower": 648243995,"count": 757,"preSum": 13425 },{ "ndv": 171,"upper": 707024195,"lower": 675740785,"count": 763,"preSum": 14182 },{ "ndv": 190,"upper": 744178917,"lower": 707538630,"count": 764,"preSum": 14945 },{ "ndv": 219,"upper": 784220410,"lower": 744423484,"count": 842,"preSum": 15709 },{ "ndv": 198,"upper": 820578404,"lower": 784258726,"count": 804,"preSum": 16551 },{ "ndv": 139,"upper": 848587288,"lower": 820601861,"count": 778,"preSum": 17355 },{ "ndv": 143,"upper": 872869048,"lower": 848840055,"count": 1271,"preSum": 18133 },{ "ndv": 204,"upper": 914346491,"lower": 872976425,"count": 774,"preSum": 19404 },{ "ndv": 186,"upper": 947641586,"lower": 914376534,"count": 890,"preSum": 20178 },{ "ndv": 178,"upper": 980669282,"lower": 947750011,"count": 768,"preSum": 21068 },{ "ndv": 226,"upper": 1017981521,"lower": 980703413,"count": 772,"preSum": 21836 },{ "ndv": 269,"upper": 1069696352,"lower": 1017981846,"count": 750,"preSum": 22608 },{ "ndv": 186,"upper": 1105269469,"lower": 1069849436,"count": 969,"preSum": 23358 },{ "ndv": 105,"upper": 1125979808,"lower": 1105397138,"count": 791,"preSum": 24327 },{ "ndv": 259,"upper": 1174541012,"lower": 1126315148,"count": 775,"preSum": 25118 },{ "ndv": 137,"upper": 1205235491,"lower": 1174551463,"count": 1318,"preSum": 25893 },{ "ndv": 193,"upper": 1238692391,"lower": 1205408341,"count": 750,"preSum": 27211 },{ "ndv": 187,"upper": 1278799410,"lower": 1239163407,"count": 917,"preSum": 27961 },{ "ndv": 204,"upper": 1315771187,"lower": 1279173223,"count": 749,"preSum": 28878 },{ "ndv": 236,"upper": 1360515634,"lower": 1315967094,"count": 753,"preSum": 29627 },{ "ndv": 105,"upper": 1381281554,"lower": 1360578245,"count": 775,"preSum": 30380 },{ "ndv": 298,"upper": 1437784952,"lower": 1381312941,"count": 820,"preSum": 31155 },{ "ndv": 213,"upper": 1483182213,"lower": 1437885471,"count": 1233,"preSum": 31975 },{ "ndv": 46,"upper": 1494371053,"lower": 1483221406,"count": 804,"preSum": 33208 },{ "ndv": 231,"upper": 1537548292,"lower": 1494538502,"count": 749,"preSum": 34012 },{ "ndv": 259,"upper": 1585293283,"lower": 1537713630,"count": 772,"preSum": 34761 },{ "ndv": 134,"upper": 1611812771,"lower": 1585691140,"count": 749,"preSum": 35533 },{ "ndv": 159,"upper": 1644855264,"lower": 1612180374,"count": 775,"preSum": 36282 },{ "ndv": 248,"upper": 1691808023,"lower": 1645106875,"count": 1018,"preSum": 37057 },{ "ndv": 172,"upper": 1722402852,"lower": 1691996010,"count": 752,"preSum": 38075 },{ "ndv": 189,"upper": 1758737198,"lower": 1722637560,"count": 751,"preSum": 38827 },{ "ndv": 154,"upper": 1789523027,"lower": 1758911387,"count": 749,"preSum": 39578 },{ "ndv": 221,"upper": 1832508714,"lower": 1790093600,"count": 749,"preSum": 40327 },{ "ndv": 300,"upper": 1885425308,"lower": 1832544264,"count": 755,"preSum": 41076 },{ "ndv": 209,"upper": 1926020744,"lower": 1885643442,"count": 750,"preSum": 41831 },{ "ndv": 136,"upper": 1953124538,"lower": 1926465194,"count": 982,"preSum": 42581 },{ "ndv": 226,"upper": 1992647664,"lower": 1953220251,"count": 852,"preSum": 43563 },{ "ndv": 168,"upper": 2023053384,"lower": 1992883514,"count": 890,"preSum": 44415 },{ "ndv": 283,"upper": 2074276230,"lower": 2023054825,"count": 750,"preSum": 45305 },{ "ndv": 136,"upper": 2102143275,"lower": 2074604253,"count": 749,"preSum": 46055 },{ "ndv": 157,"upper": 2134258389,"lower": 2102460426,"count": 822,"preSum": 46804 },{ "ndv": 83,"upper": 2147353621,"lower": 2134289989,"count": 259,"preSum": 47626 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_int_32_un.null_count:
+    0
+  cest_full_table_big.c_int_32_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_mediumint_1.TOPN:
+    { "countArr": [ 13,8,10,10,9,11,8,8 ],"valueArr": [ -7399610,-6342339,-5316156,-3963279,-2519378,607065,3425154,5407120 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_mediumint_1.cardinality:
+    505764
+  cest_full_table_big.c_mediumint_1.histogram:
+    { "buckets": [ { "ndv": 942,"upper": -8144386,"lower": -8388463,"count": 1563,"preSum": 0 },{ "ndv": 1002,"upper": -7875850,"lower": -8144143,"count": 1562,"preSum": 1563 },{ "ndv": 968,"upper": -7610713,"lower": -7875837,"count": 1562,"preSum": 3125 },{ "ndv": 961,"upper": -7351185,"lower": -7610530,"count": 1563,"preSum": 4687 },{ "ndv": 999,"upper": -7081497,"lower": -7351054,"count": 1562,"preSum": 6250 },{ "ndv": 963,"upper": -6811824,"lower": -7081158,"count": 1562,"preSum": 7812 },{ "ndv": 971,"upper": -6521072,"lower": -6811263,"count": 1562,"preSum": 9374 },{ "ndv": 965,"upper": -6263983,"lower": -6521048,"count": 1564,"preSum": 10936 },{ "ndv": 964,"upper": -6009392,"lower": -6263889,"count": 1562,"preSum": 12500 },{ "ndv": 977,"upper": -5718986,"lower": -6009023,"count": 1562,"preSum": 14062 },{ "ndv": 963,"upper": -5461282,"lower": -5718904,"count": 1562,"preSum": 15624 },{ "ndv": 966,"upper": -5200523,"lower": -5461090,"count": 1562,"preSum": 17186 },{ "ndv": 975,"upper": -4945722,"lower": -5199709,"count": 1562,"preSum": 18748 },{ "ndv": 1001,"upper": -4669215,"lower": -4945552,"count": 1564,"preSum": 20310 },{ "ndv": 973,"upper": -4409275,"lower": -4668995,"count": 1562,"preSum": 21874 },{ "ndv": 985,"upper": -4141919,"lower": -4409236,"count": 1562,"preSum": 23436 },{ "ndv": 976,"upper": -3869814,"lower": -4141831,"count": 1563,"preSum": 24998 },{ "ndv": 941,"upper": -3623110,"lower": -3869775,"count": 1562,"preSum": 26561 },{ "ndv": 969,"upper": -3358584,"lower": -3622777,"count": 1563,"preSum": 28123 },{ "ndv": 971,"upper": -3105806,"lower": -3358580,"count": 1562,"preSum": 29686 },{ "ndv": 971,"upper": -2839836,"lower": -3105145,"count": 1562,"preSum": 31248 },{ "ndv": 949,"upper": -2580918,"lower": -2839723,"count": 1562,"preSum": 32810 },{ "ndv": 964,"upper": -2311755,"lower": -2580746,"count": 1562,"preSum": 34372 },{ "ndv": 956,"upper": -2047226,"lower": -2311733,"count": 1564,"preSum": 35934 },{ "ndv": 942,"upper": -1805037,"lower": -2046720,"count": 1563,"preSum": 37498 },{ "ndv": 985,"upper": -1559139,"lower": -1804911,"count": 1562,"preSum": 39061 },{ "ndv": 982,"upper": -1300436,"lower": -1558885,"count": 1563,"preSum": 40623 },{ "ndv": 985,"upper": -1031000,"lower": -1300300,"count": 1562,"preSum": 42186 },{ "ndv": 953,"upper": -774466,"lower": -1030963,"count": 1565,"preSum": 43748 },{ "ndv": 955,"upper": -523385,"lower": -774308,"count": 1565,"preSum": 45313 },{ "ndv": 986,"upper": -257176,"lower": -523281,"count": 1562,"preSum": 46878 },{ "ndv": 967,"upper": 1439,"lower": -257049,"count": 1562,"preSum": 48440 },{ "ndv": 964,"upper": 257637,"lower": 1889,"count": 1564,"preSum": 50002 },{ "ndv": 951,"upper": 521328,"lower": 257736,"count": 1562,"preSum": 51566 },{ "ndv": 989,"upper": 789581,"lower": 521408,"count": 1562,"preSum": 53128 },{ "ndv": 989,"upper": 1041212,"lower": 790073,"count": 1562,"preSum": 54690 },{ "ndv": 963,"upper": 1297393,"lower": 1042073,"count": 1563,"preSum": 56252 },{ "ndv": 971,"upper": 1562470,"lower": 1297394,"count": 1563,"preSum": 57815 },{ "ndv": 992,"upper": 1828712,"lower": 1562727,"count": 1563,"preSum": 59378 },{ "ndv": 993,"upper": 2092331,"lower": 1828887,"count": 1563,"preSum": 60941 },{ "ndv": 975,"upper": 2374162,"lower": 2092882,"count": 1562,"preSum": 62504 },{ "ndv": 1013,"upper": 2645722,"lower": 2374470,"count": 1562,"preSum": 64066 },{ "ndv": 968,"upper": 2908213,"lower": 2645746,"count": 1563,"preSum": 65628 },{ "ndv": 955,"upper": 3160439,"lower": 2908250,"count": 1562,"preSum": 67191 },{ "ndv": 977,"upper": 3425395,"lower": 3160676,"count": 1562,"preSum": 68753 },{ "ndv": 993,"upper": 3703308,"lower": 3425972,"count": 1563,"preSum": 70315 },{ "ndv": 948,"upper": 3957282,"lower": 3703431,"count": 1563,"preSum": 71878 },{ "ndv": 956,"upper": 4221694,"lower": 3957325,"count": 1562,"preSum": 73441 },{ "ndv": 971,"upper": 4500933,"lower": 4221765,"count": 1564,"preSum": 75003 },{ "ndv": 977,"upper": 4756843,"lower": 4500960,"count": 1564,"preSum": 76567 },{ "ndv": 955,"upper": 5017876,"lower": 4757055,"count": 1562,"preSum": 78131 },{ "ndv": 952,"upper": 5265892,"lower": 5017925,"count": 1562,"preSum": 79693 },{ "ndv": 955,"upper": 5516860,"lower": 5265994,"count": 1562,"preSum": 81255 },{ "ndv": 975,"upper": 5777220,"lower": 5517068,"count": 1562,"preSum": 82817 },{ "ndv": 1006,"upper": 6040616,"lower": 5777280,"count": 1562,"preSum": 84379 },{ "ndv": 979,"upper": 6305771,"lower": 6041277,"count": 1562,"preSum": 85941 },{ "ndv": 997,"upper": 6575281,"lower": 6306048,"count": 1562,"preSum": 87503 },{ "ndv": 976,"upper": 6841357,"lower": 6575436,"count": 1562,"preSum": 89065 },{ "ndv": 955,"upper": 7085539,"lower": 6841422,"count": 1562,"preSum": 90627 },{ "ndv": 977,"upper": 7351748,"lower": 7085812,"count": 1562,"preSum": 92189 },{ "ndv": 1007,"upper": 7608910,"lower": 7352382,"count": 1562,"preSum": 93751 },{ "ndv": 981,"upper": 7858480,"lower": 7609090,"count": 1562,"preSum": 95313 },{ "ndv": 997,"upper": 8138849,"lower": 7858809,"count": 1562,"preSum": 96875 },{ "ndv": 890,"upper": 8388497,"lower": 8139178,"count": 1487,"preSum": 98437 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_mediumint_1.null_count:
+    0
+  cest_full_table_big.c_mediumint_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_mediumint_24.TOPN:
+    { "countArr": [ 44,22,51,28,34,22,57,24,37,32,36,34 ],"valueArr": [ -7399610,-6819370,-3963279,-3407157,-2874889,-1369445,607065,1094542,2735753,3053392,5651230,5856876 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_mediumint_24.cardinality:
+    480838
+  cest_full_table_big.c_mediumint_24.histogram:
+    { "buckets": [ { "ndv": 912,"upper": -8140422,"lower": -8388483,"count": 1556,"preSum": 0 },{ "ndv": 924,"upper": -7880122,"lower": -8140258,"count": 1564,"preSum": 1556 },{ "ndv": 943,"upper": -7602511,"lower": -7880099,"count": 1556,"preSum": 3120 },{ "ndv": 918,"upper": -7342554,"lower": -7602190,"count": 1558,"preSum": 4676 },{ "ndv": 916,"upper": -7081497,"lower": -7342210,"count": 1559,"preSum": 6234 },{ "ndv": 915,"upper": -6818265,"lower": -7081158,"count": 1556,"preSum": 7793 },{ "ndv": 902,"upper": -6535188,"lower": -6818146,"count": 1558,"preSum": 9349 },{ "ndv": 918,"upper": -6265868,"lower": -6535147,"count": 1556,"preSum": 10907 },{ "ndv": 890,"upper": -6011737,"lower": -6265865,"count": 1556,"preSum": 12463 },{ "ndv": 947,"upper": -5728427,"lower": -6011243,"count": 1556,"preSum": 14019 },{ "ndv": 944,"upper": -5449636,"lower": -5728297,"count": 1556,"preSum": 15575 },{ "ndv": 935,"upper": -5190446,"lower": -5449014,"count": 1556,"preSum": 17131 },{ "ndv": 910,"upper": -4933071,"lower": -5190322,"count": 1556,"preSum": 18687 },{ "ndv": 925,"upper": -4658327,"lower": -4932871,"count": 1559,"preSum": 20243 },{ "ndv": 911,"upper": -4383831,"lower": -4658321,"count": 1558,"preSum": 21802 },{ "ndv": 888,"upper": -4124319,"lower": -4383702,"count": 1557,"preSum": 23360 },{ "ndv": 922,"upper": -3852620,"lower": -4124254,"count": 1558,"preSum": 24917 },{ "ndv": 887,"upper": -3612109,"lower": -3852413,"count": 1557,"preSum": 26475 },{ "ndv": 929,"upper": -3346051,"lower": -3611966,"count": 1557,"preSum": 28032 },{ "ndv": 924,"upper": -3079320,"lower": -3345570,"count": 1558,"preSum": 29589 },{ "ndv": 938,"upper": -2805427,"lower": -3079101,"count": 1557,"preSum": 31147 },{ "ndv": 895,"upper": -2539032,"lower": -2805137,"count": 1556,"preSum": 32704 },{ "ndv": 893,"upper": -2269020,"lower": -2539026,"count": 1559,"preSum": 34260 },{ "ndv": 923,"upper": -1997687,"lower": -2268804,"count": 1556,"preSum": 35819 },{ "ndv": 923,"upper": -1750335,"lower": -1997614,"count": 1557,"preSum": 37375 },{ "ndv": 909,"upper": -1501426,"lower": -1750252,"count": 1558,"preSum": 38932 },{ "ndv": 900,"upper": -1253331,"lower": -1501022,"count": 1556,"preSum": 40490 },{ "ndv": 893,"upper": -988550,"lower": -1253313,"count": 1556,"preSum": 42046 },{ "ndv": 912,"upper": -734645,"lower": -988527,"count": 1556,"preSum": 43602 },{ "ndv": 927,"upper": -462156,"lower": -734281,"count": 1556,"preSum": 45158 },{ "ndv": 898,"upper": -204739,"lower": -462045,"count": 1556,"preSum": 46714 },{ "ndv": 894,"upper": 42288,"lower": -203605,"count": 1559,"preSum": 48270 },{ "ndv": 935,"upper": 308434,"lower": 43637,"count": 1556,"preSum": 49829 },{ "ndv": 922,"upper": 574336,"lower": 309044,"count": 1556,"preSum": 51385 },{ "ndv": 935,"upper": 835980,"lower": 574966,"count": 1557,"preSum": 52941 },{ "ndv": 939,"upper": 1092640,"lower": 836263,"count": 1556,"preSum": 54498 },{ "ndv": 929,"upper": 1358789,"lower": 1092762,"count": 1556,"preSum": 56054 },{ "ndv": 943,"upper": 1632328,"lower": 1359271,"count": 1557,"preSum": 57610 },{ "ndv": 907,"upper": 1888073,"lower": 1632448,"count": 1557,"preSum": 59167 },{ "ndv": 918,"upper": 2146902,"lower": 1888148,"count": 1556,"preSum": 60724 },{ "ndv": 921,"upper": 2408379,"lower": 2147146,"count": 1556,"preSum": 62280 },{ "ndv": 874,"upper": 2638111,"lower": 2408884,"count": 1556,"preSum": 63836 },{ "ndv": 909,"upper": 2893322,"lower": 2638126,"count": 1557,"preSum": 65392 },{ "ndv": 937,"upper": 3162632,"lower": 2893620,"count": 1556,"preSum": 66949 },{ "ndv": 952,"upper": 3439226,"lower": 3163177,"count": 1557,"preSum": 68505 },{ "ndv": 887,"upper": 3702498,"lower": 3439592,"count": 1557,"preSum": 70062 },{ "ndv": 901,"upper": 3956942,"lower": 3702731,"count": 1556,"preSum": 71619 },{ "ndv": 917,"upper": 4223956,"lower": 3957191,"count": 1556,"preSum": 73175 },{ "ndv": 907,"upper": 4490513,"lower": 4224111,"count": 1556,"preSum": 74731 },{ "ndv": 944,"upper": 4749636,"lower": 4490791,"count": 1556,"preSum": 76287 },{ "ndv": 909,"upper": 5016031,"lower": 4749814,"count": 1557,"preSum": 77843 },{ "ndv": 937,"upper": 5282831,"lower": 5016383,"count": 1557,"preSum": 79400 },{ "ndv": 909,"upper": 5524360,"lower": 5282895,"count": 1556,"preSum": 80957 },{ "ndv": 924,"upper": 5779708,"lower": 5524829,"count": 1556,"preSum": 82513 },{ "ndv": 931,"upper": 6031771,"lower": 5780182,"count": 1556,"preSum": 84069 },{ "ndv": 903,"upper": 6285721,"lower": 6031807,"count": 1557,"preSum": 85625 },{ "ndv": 916,"upper": 6541526,"lower": 6286008,"count": 1556,"preSum": 87182 },{ "ndv": 893,"upper": 6799864,"lower": 6541706,"count": 1558,"preSum": 88738 },{ "ndv": 908,"upper": 7037419,"lower": 6800835,"count": 1556,"preSum": 90296 },{ "ndv": 935,"upper": 7303324,"lower": 7037518,"count": 1556,"preSum": 91852 },{ "ndv": 956,"upper": 7574171,"lower": 7303612,"count": 1556,"preSum": 93408 },{ "ndv": 937,"upper": 7830384,"lower": 7574347,"count": 1558,"preSum": 94964 },{ "ndv": 942,"upper": 8114383,"lower": 7830636,"count": 1556,"preSum": 96522 },{ "ndv": 882,"upper": 8388415,"lower": 8114469,"count": 1502,"preSum": 98078 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_mediumint_24.null_count:
+    0
+  cest_full_table_big.c_mediumint_24.sample_rate:
+    0.010943651
+  cest_full_table_big.c_mediumint_24_un.TOPN:
+    { "countArr": [ 157,84,83,84,219,124,97,93,413,95,276,124,189,136 ],"valueArr": [ 494499,1002869,1023134,1143267,2212664,2490725,2756859,4450302,4497836,4834301,5562180,5721000,7019919,7122742 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_mediumint_24_un.cardinality:
+    438709
+  cest_full_table_big.c_mediumint_24_un.histogram:
+    { "buckets": [ { "ndv": 823,"upper": 129197,"lower": 207,"count": 1529,"preSum": 0 },{ "ndv": 783,"upper": 254482,"lower": 129215,"count": 1531,"preSum": 1529 },{ "ndv": 807,"upper": 389373,"lower": 254547,"count": 1530,"preSum": 3060 },{ "ndv": 784,"upper": 515802,"lower": 389726,"count": 1529,"preSum": 4590 },{ "ndv": 812,"upper": 649486,"lower": 516146,"count": 1529,"preSum": 6119 },{ "ndv": 833,"upper": 779620,"lower": 649585,"count": 1529,"preSum": 7648 },{ "ndv": 790,"upper": 919355,"lower": 779660,"count": 1529,"preSum": 9177 },{ "ndv": 844,"upper": 1055037,"lower": 919469,"count": 1529,"preSum": 10706 },{ "ndv": 800,"upper": 1177239,"lower": 1055167,"count": 1532,"preSum": 12235 },{ "ndv": 829,"upper": 1319189,"lower": 1177402,"count": 1541,"preSum": 13767 },{ "ndv": 870,"upper": 1459021,"lower": 1319233,"count": 1529,"preSum": 15308 },{ "ndv": 860,"upper": 1598201,"lower": 1459045,"count": 1529,"preSum": 16837 },{ "ndv": 781,"upper": 1721664,"lower": 1598229,"count": 1529,"preSum": 18366 },{ "ndv": 838,"upper": 1865305,"lower": 1722243,"count": 1530,"preSum": 19895 },{ "ndv": 793,"upper": 1999211,"lower": 1865389,"count": 1529,"preSum": 21425 },{ "ndv": 815,"upper": 2133117,"lower": 1999867,"count": 1532,"preSum": 22954 },{ "ndv": 812,"upper": 2268373,"lower": 2133328,"count": 1529,"preSum": 24486 },{ "ndv": 742,"upper": 2377765,"lower": 2268713,"count": 1530,"preSum": 26015 },{ "ndv": 812,"upper": 2510609,"lower": 2378021,"count": 1529,"preSum": 27545 },{ "ndv": 795,"upper": 2644537,"lower": 2510632,"count": 1529,"preSum": 29074 },{ "ndv": 809,"upper": 2780027,"lower": 2644556,"count": 1529,"preSum": 30603 },{ "ndv": 854,"upper": 2917355,"lower": 2780157,"count": 1530,"preSum": 32132 },{ "ndv": 819,"upper": 3054294,"lower": 2917401,"count": 1530,"preSum": 33662 },{ "ndv": 848,"upper": 3193264,"lower": 3054361,"count": 1529,"preSum": 35192 },{ "ndv": 798,"upper": 3318258,"lower": 3193306,"count": 1531,"preSum": 36721 },{ "ndv": 802,"upper": 3443591,"lower": 3318636,"count": 1536,"preSum": 38252 },{ "ndv": 807,"upper": 3572458,"lower": 3443843,"count": 1529,"preSum": 39788 },{ "ndv": 764,"upper": 3701204,"lower": 3572530,"count": 1530,"preSum": 41317 },{ "ndv": 824,"upper": 3833066,"lower": 3701295,"count": 1539,"preSum": 42847 },{ "ndv": 825,"upper": 3965351,"lower": 3833170,"count": 1529,"preSum": 44386 },{ "ndv": 791,"upper": 4091053,"lower": 3965509,"count": 1529,"preSum": 45915 },{ "ndv": 798,"upper": 4218792,"lower": 4091335,"count": 1537,"preSum": 47444 },{ "ndv": 849,"upper": 4363422,"lower": 4218863,"count": 1530,"preSum": 48981 },{ "ndv": 820,"upper": 4502081,"lower": 4363561,"count": 1529,"preSum": 50511 },{ "ndv": 807,"upper": 4627180,"lower": 4502427,"count": 1529,"preSum": 52040 },{ "ndv": 764,"upper": 4747624,"lower": 4627182,"count": 1534,"preSum": 53569 },{ "ndv": 828,"upper": 4876886,"lower": 4747735,"count": 1529,"preSum": 55103 },{ "ndv": 892,"upper": 5027954,"lower": 4877431,"count": 1529,"preSum": 56632 },{ "ndv": 812,"upper": 5156335,"lower": 5028019,"count": 1530,"preSum": 58161 },{ "ndv": 783,"upper": 5280912,"lower": 5156458,"count": 1529,"preSum": 59691 },{ "ndv": 836,"upper": 5417558,"lower": 5281801,"count": 1529,"preSum": 61220 },{ "ndv": 764,"upper": 5533986,"lower": 5417561,"count": 1529,"preSum": 62749 },{ "ndv": 769,"upper": 5657604,"lower": 5534030,"count": 1529,"preSum": 64278 },{ "ndv": 807,"upper": 5792645,"lower": 5658398,"count": 1530,"preSum": 65807 },{ "ndv": 819,"upper": 5923512,"lower": 5792668,"count": 1529,"preSum": 67337 },{ "ndv": 786,"upper": 6062154,"lower": 5923710,"count": 1529,"preSum": 68866 },{ "ndv": 757,"upper": 6185996,"lower": 6062306,"count": 1531,"preSum": 70395 },{ "ndv": 826,"upper": 6325175,"lower": 6186203,"count": 1537,"preSum": 71926 },{ "ndv": 784,"upper": 6461631,"lower": 6325293,"count": 1529,"preSum": 73463 },{ "ndv": 869,"upper": 6599965,"lower": 6461878,"count": 1535,"preSum": 74992 },{ "ndv": 784,"upper": 6724423,"lower": 6600141,"count": 1529,"preSum": 76527 },{ "ndv": 828,"upper": 6861587,"lower": 6724497,"count": 1529,"preSum": 78056 },{ "ndv": 812,"upper": 6995511,"lower": 6861606,"count": 1531,"preSum": 79585 },{ "ndv": 809,"upper": 7117570,"lower": 6995565,"count": 1529,"preSum": 81116 },{ "ndv": 798,"upper": 7247047,"lower": 7117622,"count": 1530,"preSum": 82645 },{ "ndv": 756,"upper": 7368862,"lower": 7247203,"count": 1529,"preSum": 84175 },{ "ndv": 777,"upper": 7497516,"lower": 7369345,"count": 1561,"preSum": 85704 },{ "ndv": 705,"upper": 7617363,"lower": 7497537,"count": 1529,"preSum": 87265 },{ "ndv": 779,"upper": 7732926,"lower": 7617410,"count": 1540,"preSum": 88794 },{ "ndv": 819,"upper": 7863201,"lower": 7733189,"count": 1529,"preSum": 90334 },{ "ndv": 799,"upper": 7986290,"lower": 7863519,"count": 1530,"preSum": 91863 },{ "ndv": 827,"upper": 8113061,"lower": 7986292,"count": 1529,"preSum": 93393 },{ "ndv": 859,"upper": 8251583,"lower": 8113066,"count": 1550,"preSum": 94922 },{ "ndv": 823,"upper": 8388552,"lower": 8251638,"count": 1355,"preSum": 96472 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_mediumint_24_un.null_count:
+    0
+  cest_full_table_big.c_mediumint_24_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_smallint_1.TOPN:
+    { "countArr": [ 3468,1158,1015,839,6974,1806,1444,32505,1336,12201,2163,4658,2665,850 ],"valueArr": [ -28905,-24934,-24775,-23837,-15482,-13310,-11231,2371,4999,10686,11927,22075,22878,26192 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_smallint_1.cardinality:
+    38995
+  cest_full_table_big.c_smallint_1.histogram:
+    { "buckets": [ { "ndv": 92,"upper": -31369,"lower": -32761,"count": 606,"preSum": 0 },{ "ndv": 114,"upper": -29504,"lower": -31365,"count": 421,"preSum": 606 },{ "ndv": 33,"upper": -28971,"lower": -29465,"count": 450,"preSum": 1027 },{ "ndv": 144,"upper": -26823,"lower": -28969,"count": 423,"preSum": 1477 },{ "ndv": 124,"upper": -25055,"lower": -26811,"count": 421,"preSum": 1900 },{ "ndv": 79,"upper": -23697,"lower": -25029,"count": 506,"preSum": 2321 },{ "ndv": 80,"upper": -22406,"lower": -23695,"count": 437,"preSum": 2827 },{ "ndv": 138,"upper": -20025,"lower": -22383,"count": 701,"preSum": 3264 },{ "ndv": 67,"upper": -19091,"lower": -20019,"count": 422,"preSum": 3965 },{ "ndv": 95,"upper": -17369,"lower": -19078,"count": 525,"preSum": 4387 },{ "ndv": 85,"upper": -15979,"lower": -17361,"count": 421,"preSum": 4912 },{ "ndv": 99,"upper": -14589,"lower": -15967,"count": 907,"preSum": 5333 },{ "ndv": 30,"upper": -14192,"lower": -14583,"count": 704,"preSum": 6240 },{ "ndv": 38,"upper": -13558,"lower": -14178,"count": 439,"preSum": 6944 },{ "ndv": 100,"upper": -11990,"lower": -13501,"count": 473,"preSum": 7383 },{ "ndv": 16,"upper": -11751,"lower": -11969,"count": 421,"preSum": 7856 },{ "ndv": 139,"upper": -9842,"lower": -11745,"count": 751,"preSum": 8277 },{ "ndv": 110,"upper": -7590,"lower": -9825,"count": 421,"preSum": 9028 },{ "ndv": 46,"upper": -6804,"lower": -7586,"count": 421,"preSum": 9449 },{ "ndv": 35,"upper": -6162,"lower": -6729,"count": 666,"preSum": 9870 },{ "ndv": 47,"upper": -5350,"lower": -6133,"count": 487,"preSum": 10536 },{ "ndv": 69,"upper": -4245,"lower": -5349,"count": 425,"preSum": 11023 },{ "ndv": 37,"upper": -3844,"lower": -4242,"count": 454,"preSum": 11448 },{ "ndv": 102,"upper": -2175,"lower": -3835,"count": 563,"preSum": 11902 },{ "ndv": 85,"upper": -914,"lower": -2163,"count": 433,"preSum": 12465 },{ "ndv": 47,"upper": -62,"lower": -862,"count": 544,"preSum": 12898 },{ "ndv": 92,"upper": 1424,"lower": -52,"count": 437,"preSum": 13442 },{ "ndv": 29,"upper": 1999,"lower": 1431,"count": 721,"preSum": 13879 },{ "ndv": 131,"upper": 3669,"lower": 2051,"count": 421,"preSum": 14600 },{ "ndv": 40,"upper": 4275,"lower": 3685,"count": 651,"preSum": 15021 },{ "ndv": 68,"upper": 5501,"lower": 4283,"count": 434,"preSum": 15672 },{ "ndv": 123,"upper": 7461,"lower": 5520,"count": 428,"preSum": 16106 },{ "ndv": 86,"upper": 8599,"lower": 7465,"count": 423,"preSum": 16534 },{ "ndv": 67,"upper": 9829,"lower": 8609,"count": 669,"preSum": 16957 },{ "ndv": 42,"upper": 10483,"lower": 9841,"count": 894,"preSum": 17626 },{ "ndv": 84,"upper": 11884,"lower": 10485,"count": 507,"preSum": 18520 },{ "ndv": 91,"upper": 13396,"lower": 11885,"count": 421,"preSum": 19027 },{ "ndv": 66,"upper": 14572,"lower": 13422,"count": 484,"preSum": 19448 },{ "ndv": 7,"upper": 14691,"lower": 14588,"count": 622,"preSum": 19932 },{ "ndv": 87,"upper": 15990,"lower": 14729,"count": 422,"preSum": 20554 },{ "ndv": 71,"upper": 17011,"lower": 15992,"count": 436,"preSum": 20976 },{ "ndv": 112,"upper": 18948,"lower": 17067,"count": 422,"preSum": 21412 },{ "ndv": 103,"upper": 20790,"lower": 18975,"count": 492,"preSum": 21834 },{ "ndv": 88,"upper": 22204,"lower": 20793,"count": 494,"preSum": 22326 },{ "ndv": 115,"upper": 24155,"lower": 22215,"count": 444,"preSum": 22820 },{ "ndv": 61,"upper": 24921,"lower": 24157,"count": 426,"preSum": 23264 },{ "ndv": 65,"upper": 25774,"lower": 24929,"count": 421,"preSum": 23690 },{ "ndv": 6,"upper": 25829,"lower": 25784,"count": 477,"preSum": 24111 },{ "ndv": 27,"upper": 26164,"lower": 25839,"count": 655,"preSum": 24588 },{ "ndv": 123,"upper": 27978,"lower": 26178,"count": 431,"preSum": 25243 },{ "ndv": 104,"upper": 29330,"lower": 28004,"count": 449,"preSum": 25674 },{ "ndv": 97,"upper": 30839,"lower": 29338,"count": 529,"preSum": 26123 },{ "ndv": 105,"upper": 32759,"lower": 30878,"count": 267,"preSum": 26652 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_smallint_1.null_count:
+    0
+  cest_full_table_big.c_smallint_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_smallint_16.TOPN:
+    { "countArr": [ 3296,926,784,647,7555,1563,1298,43525,1050,14468,1943,4858,2559,684 ],"valueArr": [ -28905,-24934,-24775,-23837,-15482,-13310,-11231,2371,4999,10686,11927,22075,22878,26192 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_smallint_16.cardinality:
+    15445
+  cest_full_table_big.c_smallint_16.histogram:
+    { "buckets": [ { "ndv": 40,"upper": -31369,"lower": -32699,"count": 311,"preSum": 0 },{ "ndv": 44,"upper": -29370,"lower": -31365,"count": 284,"preSum": 311 },{ "ndv": 45,"upper": -28120,"lower": -29369,"count": 235,"preSum": 595 },{ "ndv": 64,"upper": -26095,"lower": -28118,"count": 233,"preSum": 830 },{ "ndv": 56,"upper": -23697,"lower": -26050,"count": 321,"preSum": 1063 },{ "ndv": 32,"upper": -22075,"lower": -23695,"count": 234,"preSum": 1384 },{ "ndv": 54,"upper": -20025,"lower": -22064,"count": 362,"preSum": 1618 },{ "ndv": 47,"upper": -18512,"lower": -20019,"count": 232,"preSum": 1980 },{ "ndv": 25,"upper": -17323,"lower": -18440,"count": 235,"preSum": 2212 },{ "ndv": 66,"upper": -15023,"lower": -17309,"count": 232,"preSum": 2447 },{ "ndv": 10,"upper": -14589,"lower": -14950,"count": 520,"preSum": 2679 },{ "ndv": 12,"upper": -14192,"lower": -14503,"count": 493,"preSum": 3199 },{ "ndv": 14,"upper": -13606,"lower": -14132,"count": 247,"preSum": 3692 },{ "ndv": 48,"upper": -11990,"lower": -13569,"count": 263,"preSum": 3939 },{ "ndv": 6,"upper": -11823,"lower": -11894,"count": 277,"preSum": 4202 },{ "ndv": 50,"upper": -9842,"lower": -11791,"count": 436,"preSum": 4479 },{ "ndv": 63,"upper": -7308,"lower": -9829,"count": 284,"preSum": 4915 },{ "ndv": 27,"upper": -6162,"lower": -7270,"count": 594,"preSum": 5199 },{ "ndv": 24,"upper": -5350,"lower": -6120,"count": 288,"preSum": 5793 },{ "ndv": 35,"upper": -4181,"lower": -5340,"count": 250,"preSum": 6081 },{ "ndv": 11,"upper": -3844,"lower": -4145,"count": 246,"preSum": 6331 },{ "ndv": 42,"upper": -2175,"lower": -3796,"count": 273,"preSum": 6577 },{ "ndv": 43,"upper": -480,"lower": -2080,"count": 232,"preSum": 6850 },{ "ndv": 8,"upper": -62,"lower": -460,"count": 304,"preSum": 7082 },{ "ndv": 43,"upper": 1424,"lower": -52,"count": 235,"preSum": 7386 },{ "ndv": 15,"upper": 1999,"lower": 1431,"count": 555,"preSum": 7621 },{ "ndv": 64,"upper": 3889,"lower": 2009,"count": 265,"preSum": 8176 },{ "ndv": 19,"upper": 4275,"lower": 3891,"count": 354,"preSum": 8441 },{ "ndv": 35,"upper": 5675,"lower": 4283,"count": 233,"preSum": 8795 },{ "ndv": 71,"upper": 7884,"lower": 5686,"count": 246,"preSum": 9028 },{ "ndv": 55,"upper": 9784,"lower": 7908,"count": 268,"preSum": 9274 },{ "ndv": 3,"upper": 9829,"lower": 9799,"count": 269,"preSum": 9542 },{ "ndv": 22,"upper": 10483,"lower": 9871,"count": 639,"preSum": 9811 },{ "ndv": 45,"upper": 11884,"lower": 10516,"count": 281,"preSum": 10450 },{ "ndv": 51,"upper": 13807,"lower": 11890,"count": 232,"preSum": 10731 },{ "ndv": 28,"upper": 14588,"lower": 13839,"count": 232,"preSum": 10963 },{ "ndv": 5,"upper": 14691,"lower": 14602,"count": 444,"preSum": 11195 },{ "ndv": 42,"upper": 16285,"lower": 14729,"count": 250,"preSum": 11639 },{ "ndv": 31,"upper": 17258,"lower": 16287,"count": 233,"preSum": 11889 },{ "ndv": 67,"upper": 19609,"lower": 17379,"count": 232,"preSum": 12122 },{ "ndv": 53,"upper": 21810,"lower": 19616,"count": 257,"preSum": 12354 },{ "ndv": 47,"upper": 23826,"lower": 21830,"count": 242,"preSum": 12611 },{ "ndv": 22,"upper": 24834,"lower": 23900,"count": 232,"preSum": 12853 },{ "ndv": 27,"upper": 25806,"lower": 24874,"count": 257,"preSum": 13085 },{ "ndv": 3,"upper": 25829,"lower": 25817,"count": 257,"preSum": 13342 },{ "ndv": 16,"upper": 26164,"lower": 25843,"count": 486,"preSum": 13599 },{ "ndv": 60,"upper": 28576,"lower": 26178,"count": 234,"preSum": 14085 },{ "ndv": 32,"upper": 29833,"lower": 28622,"count": 232,"preSum": 14319 },{ "ndv": 45,"upper": 31656,"lower": 29862,"count": 233,"preSum": 14551 },{ "ndv": 22,"upper": 32672,"lower": 31697,"count": 61,"preSum": 14784 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_smallint_16.null_count:
+    0
+  cest_full_table_big.c_smallint_16.sample_rate:
+    0.010943651
+  cest_full_table_big.c_smallint_16_un.TOPN:
+    { "countArr": [ 2899,706,623,454,7421,1252,1048,53117,878,15224,1576,4317,2057,504 ],"valueArr": [ 1931,3917,3996,4465,8643,9729,10768,17569,18883,21727,22347,27421,27823,29480 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_smallint_16_un.cardinality:
+    6580
+  cest_full_table_big.c_smallint_16_un.histogram:
+    { "buckets": [ { "ndv": 16,"upper": 699,"lower": 32,"count": 154,"preSum": 0 },{ "ndv": 27,"upper": 1699,"lower": 701,"count": 124,"preSum": 154 },{ "ndv": 36,"upper": 2986,"lower": 1727,"count": 124,"preSum": 278 },{ "ndv": 28,"upper": 4150,"lower": 3002,"count": 124,"preSum": 402 },{ "ndv": 15,"upper": 4742,"lower": 4229,"count": 124,"preSum": 526 },{ "ndv": 32,"upper": 6371,"lower": 4817,"count": 256,"preSum": 650 },{ "ndv": 21,"upper": 7330,"lower": 6374,"count": 138,"preSum": 906 },{ "ndv": 24,"upper": 8147,"lower": 7435,"count": 142,"preSum": 1044 },{ "ndv": 33,"upper": 9089,"lower": 8158,"count": 396,"preSum": 1186 },{ "ndv": 8,"upper": 9288,"lower": 9132,"count": 276,"preSum": 1582 },{ "ndv": 8,"upper": 9633,"lower": 9296,"count": 125,"preSum": 1858 },{ "ndv": 17,"upper": 10472,"lower": 9699,"count": 249,"preSum": 1983 },{ "ndv": 23,"upper": 11463,"lower": 10488,"count": 223,"preSum": 2232 },{ "ndv": 32,"upper": 12798,"lower": 11501,"count": 146,"preSum": 2455 },{ "ndv": 13,"upper": 13303,"lower": 12804,"count": 307,"preSum": 2601 },{ "ndv": 9,"upper": 13709,"lower": 13326,"count": 147,"preSum": 2908 },{ "ndv": 15,"upper": 14293,"lower": 13732,"count": 137,"preSum": 3055 },{ "ndv": 6,"upper": 14462,"lower": 14311,"count": 189,"preSum": 3192 },{ "ndv": 20,"upper": 15296,"lower": 14477,"count": 167,"preSum": 3381 },{ "ndv": 29,"upper": 16232,"lower": 15344,"count": 195,"preSum": 3548 },{ "ndv": 18,"upper": 17096,"lower": 16275,"count": 193,"preSum": 3743 },{ "ndv": 6,"upper": 17383,"lower": 17185,"count": 409,"preSum": 3936 },{ "ndv": 31,"upper": 18427,"lower": 17423,"count": 124,"preSum": 4345 },{ "ndv": 3,"upper": 18521,"lower": 18435,"count": 213,"preSum": 4469 },{ "ndv": 21,"upper": 19484,"lower": 18525,"count": 124,"preSum": 4682 },{ "ndv": 25,"upper": 20555,"lower": 19562,"count": 125,"preSum": 4806 },{ "ndv": 20,"upper": 21298,"lower": 20569,"count": 229,"preSum": 4931 },{ "ndv": 11,"upper": 21625,"lower": 21321,"count": 425,"preSum": 5160 },{ "ndv": 19,"upper": 22326,"lower": 21642,"count": 135,"preSum": 5585 },{ "ndv": 27,"upper": 23192,"lower": 22359,"count": 124,"preSum": 5720 },{ "ndv": 13,"upper": 23729,"lower": 23213,"count": 443,"preSum": 5844 },{ "ndv": 13,"upper": 24526,"lower": 23748,"count": 134,"preSum": 6287 },{ "ndv": 13,"upper": 25133,"lower": 24562,"count": 148,"preSum": 6421 },{ "ndv": 40,"upper": 27034,"lower": 25231,"count": 124,"preSum": 6569 },{ "ndv": 26,"upper": 28033,"lower": 27061,"count": 124,"preSum": 6693 },{ "ndv": 13,"upper": 28507,"lower": 28046,"count": 143,"preSum": 6817 },{ "ndv": 29,"upper": 29121,"lower": 28533,"count": 124,"preSum": 6960 },{ "ndv": 5,"upper": 29298,"lower": 29139,"count": 179,"preSum": 7084 },{ "ndv": 6,"upper": 29466,"lower": 29305,"count": 291,"preSum": 7263 },{ "ndv": 34,"upper": 30709,"lower": 29470,"count": 124,"preSum": 7554 },{ "ndv": 26,"upper": 31568,"lower": 30769,"count": 124,"preSum": 7678 },{ "ndv": 21,"upper": 32757,"lower": 31573,"count": 123,"preSum": 7802 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_smallint_16_un.null_count:
+    0
+  cest_full_table_big.c_smallint_16_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_text.TOPN:
+    { "countArr": [ 2129,747,1152,2604,1061,4041,663,8212,877,1720,929,1401,654,622 ],"valueArr": [ "272901f7b4866c38cfdad0ee58e710055bd6f342c756efa3ea2c5414d1c8d334c9cd42fff815d8c800a1a7bc096cf77897e8375e32b12cb22a33cd62d840c68d","2aa4d5c39254825a73c8285fdfd0cb082cdbc465bff473642e153dbf9818be56f217072a5c7867fbcecbf15e47b88de9d80f468b8f6a85f955d20f808c77d42a","4a9e0d094ccec5f3ab0ee0ccdae5d42db6ff517ba578c8d9487aece02602c334733224fac97026bf3367678500458693ccb86eb285b","5ee951d1927147b17bb57cf07545f785341b9aeb920e85ca1c","884e206f2e3ec07a388151bddf4d2362db2a90a8ece685e96e1c2befd992ca6d4320460c618cf5ec78a7932c7cc4ae2a50962f5e8b820853f2773ec79f9aa865","8f4b82ccc477a1d4817a0713716a1a9e0abdb99fb556d066bd4663a261367328af7c4f078b4283c7d3bde3398bbeb466cd176ee7150e33107dca10c8322e0e","9081f4c0e8c85ee47ead80cdbc5f081e9cc6428718903b5f35107125e08896ba5f5172f9b5428ba371a6137715b9433d6b85cbb56c7f274ce7f86b6f66a5e313","ae093e295bf106c3d99ebb56b5c6978fb3e","b200919aa862b99712074cde83b3c18e25c4fd15","bc10f23cffb6b25587d94e646accc5b988bcb651c161925d2c5f8aa0bac12f1f290ab10f38fb5c727ad5da443c2daad1fe27901a5b9f79cd93a","c292b6a83f3518061f48c1dad1fa4d2c3e19eefcf6d90a0b08b456ab655a4c1e28257a3691b286cd81108acb9981558e411ab13520eaae125e4160f7d409d7f9","ce073c56e6291d3fcb1050e6a705e143712f1272439d96200d18b826e","cfe9b21e9d0bee82cf485c1644e7fc722764462d88e885b27cea8dead24cf1279a75c78df843678c4244278a8c7172d240d27e597f4975610eaf6da3176269ef","dd946928cf4b699b145e020fde6ca56b98c6bcb81e47f3dc93c76a5e2c6b9487a" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_text.cardinality:
+    243039
+  cest_full_table_big.c_text.histogram:
+    { "buckets": [ { "ndv": 166,"upper": "01dde7823023499a10f85591dc6af7747d89c8aa5b5","lower": "0","count": 1144,"preSum": 0 },{ "ndv": 571,"upper": "07cdf3cec6575290c3605446ed","lower": "01de5a4451a0e2648f4124d2e6c725a8302e48c132bc53022ca7462861f814dabb4f87ffc3a1e9357194adf600e97ac3e9816416b348fbb7d993843ca4861a9c","count": 1144,"preSum": 1144 },{ "ndv": 385,"upper": "0b9a1d61777836df3728cafa83c438b50f788c8c877bf0","lower": "07ceb4fa2aa3d114bf15a103d51f2a325543269a30de9b082851","count": 1145,"preSum": 2288 },{ "ndv": 511,"upper": "1113f79e0f5556eb128234780d9dc43dac44ff6f02d36cfe453ce7740f7bbacc9cbd9c8fff34e16bcf2f0d4d2f8b14990aba3f5d557e19d21dac182b7eaed214","lower": "0b9c4e79f1ff05e2dcf2cc92ae6d00c41dae43730263ca5658c0d3a3d1bf1c3a517bde9064e517d7eb344db3ca6a078a2ae3061c3f186809b3350dd9770f816c","count": 1190,"preSum": 3433 },{ "ndv": 190,"upper": "1311e1fd42260161612493575ce96bb850c6d5bcff96788f2e684e4b85bdfa805b539b0f6dd915c4a950ec4","lower": "111522044fa68d83ef2dc4c163eef6bbff2f6ee58fd5e6b0779a3558a95cc073723bbe5a27ebb52868941fa6a6fbafbce2b4dab2ff54b80a7b0a868b67d2e804","count": 1449,"preSum": 4623 },{ "ndv": 495,"upper": "17f78","lower": "1312df8d2b0b162234bf63e35e04457ca5c44cb3a93f0fdb9d4e676bedbd18dd42ac0efbcdfc822acfe3","count": 1293,"preSum": 6072 },{ "ndv": 330,"upper": "1b2b044fa17eb9b2ff7798fdbdacfd9375b20ca0f022e75c6da410673d96","lower": "17f7c2386996a38ce235cba0f1b009829aa9816a794437c4eeab3afb5094145d083","count": 1145,"preSum": 7365 },{ "ndv": 508,"upper": "205bb8f17e5224cfe3f2a340724491356c2e44adb8225890e19d820326c8a1392530aec1f4d07f994db22c6dabf1d230c81133038161de925bde002ffa9abbbe","lower": "1b2ccd0ca37e1b3902f4794b5fb5ba11","count": 1166,"preSum": 8510 },{ "ndv": 395,"upper": "2489cf31553d6e40d04c8f6","lower": "20609b96de0278b56462c3e104ef76f789e074927d7ee81d207b1fafcbe3f8266f4a268476909d8e2e7a","count": 1204,"preSum": 9676 },{ "ndv": 431,"upper": "28b02ac065e2cc1bbe517930e1d07f04e5cd8ec8c01488f9","lower": "248c920cebc921cb395d00fd3e2b567572e36fc773","count": 1144,"preSum": 10880 },{ "ndv": 369,"upper": "2cb456ee2d29c4703cfe26e290adffa03be1df47c17bc21332782fd9a067867edb1cc436cfc019762b0ab2732cfc735487969d8dd3ddf25e","lower": "28b0526659a25aefb71d8d34c6c146378bb40abd36f74d3694ebb61939c5f0bf8d5d828e86987619287886c4f901b89b6a57a45fde4fed074cb5c749e355d446","count": 1145,"preSum": 12024 },{ "ndv": 401,"upper": "310a1471df0f7661b08941c102ecf376","lower": "2cb527aa5bfd4468f64fa2d2ac61ecaf45615ca1965c91bd9c6be1cb2255377ced816533f80c91bafb93c0dfcc71de9c164","count": 1202,"preSum": 13169 },{ "ndv": 461,"upper": "35c6c1279085e58dc930071b7bdd15114913135ea39ad2ac6d1ef39cd07d","lower": "310b22f9931e4f311fe42fca59b4f23ed1e6dae708a59af169e491dba8ac7e98eb60070b40d253c3d8c0b5e9573b08f009c02ad44124d3609f9e400105b155","count": 1146,"preSum": 14371 },{ "ndv": 384,"upper": "393c28a88a013c7c969d008ea2972ec2a0d1ffd23cb361656617ae133e1357a14411438fc5a447e0bd9e0427cadea0dcf6af6a9bfc8abf0ec361fd91d66d5382","lower": "35c9f453764aaa291bcc895f7e258eb13eb04da91c0101c90365e41fbfb22ee953916a708d67c3dbbd287c3c0072d31d1fab8d9f3e97fea5d91f952e3319df0f","count": 1144,"preSum": 15517 },{ "ndv": 373,"upper": "3d307f1902b9f2d8bcd78b556f3b6f62208153308d7bf810cc471cb9fc47dabb68fbbd2f1a8e95a6fb5183389132f0e0dcf8f52e3a1c9bb3","lower": "3942568ee95b7b3f8573f806857903cd4dc87f88c3a9982797b2f2f578bd37e19dc8d8bd652efe5c713bfbab387e24e9c065","count": 1144,"preSum": 16661 },{ "ndv": 381,"upper": "410e26cac9e7f8d25b7689111f0a62a21eb4d63ea6169f95e7c167c5ca784b190127","lower": "3d323107538c7e2059be414e5cf6","count": 1144,"preSum": 17805 },{ "ndv": 218,"upper": "435a8cc58fc6c26aa437323744258f622fe49f4a06ef984d93be","lower": "4111485b903225eb7ad50fa9f854b7dbdfa9d051922c03b99fbddbd6afd7d34dc0d3189","count": 1164,"preSum": 18949 },{ "ndv": 423,"upper": "4771f0477e5fdc9a9cb582cac0a78809adc7504e6671ab16171db96f7667f5ffef8746e6f7d10100afdd78132ab081f0c585061ff62cd8d9ecfeea1fdbd01f26","lower": "435aa344d995f0d25513e501b98dbe5cf979c29e00ba08173ffda95a3e9a50c446d28b344049ccdbcb102c25cccd","count": 1164,"preSum": 20113 },{ "ndv": 581,"upper": "4da801e50c2431beab882819538ac3ba91868f642acbff073b68daa20b0f9c73b91a5d14b6b31bc507bb538a799c01b3507c41c02debda78f0f225f8eab84083","lower": "47737e5333b789dfe19c9e5ef8f417d87f1efbbdf29b539b5e88501f7e78b240080155e1cf7aaaccb5fd95740b3154566a1926d159c42f2","count": 1148,"preSum": 21277 },{ "ndv": 370,"upper": "519bef86b1ccf9a9f129a7b279e6adea1e505aef2cab78ff299182674ee5a488c7ffce8626a4","lower": "4da9d3313d55edf9e34b87eef7bc3696","count": 1144,"preSum": 22425 },{ "ndv": 297,"upper": "551a06c68d3a9bb87456c05c97d467af6daa215a60d785b5fdc549e04aaca3c877ce53236bc762d96f09","lower": "51a409db586ec283c1fc2132165ac08fb45","count": 1164,"preSum": 23569 },{ "ndv": 348,"upper": "58cbf97af20e30bc9d364928e1277d20437cecc31581e9889103826d6267","lower": "551de0f7595d913b67db679d834eea6abe1adbd3dba6e54a79eac7cbfa6b6295fa98bd8c89e58b81074fa267b633f76ad5e4c2788a61d1c3615daba6cff41f62","count": 1144,"preSum": 24733 },{ "ndv": 409,"upper": "5d8640d86728c786910ba253a149dd6aca1b6ecd3cd474e5ce7b5a73535d5aaa8","lower": "58ccca4da871e16053350dc6133b61a2f0e3347919d530830d6a304a28ef227228e6499a369b277c022a4fea645a4ffca685eb74a46de26f804bfaff856af6da","count": 1144,"preSum": 25877 },{ "ndv": 250,"upper": "600517214987915eb4b511d","lower": "5d89b00c7ae9609a56f860145a17288025d78e89f9d25d82fb9f52d004b7de35f7a4320","count": 1149,"preSum": 27021 },{ "ndv": 426,"upper": "64964da26aa4e7a9af119b294728d91b4de9a2325df7c48d84b5b3967cffa705b3a0eabe9e77238d531f32755f38e508d4a259664ad61a3e8920e091cf9556e5","lower": "600555308b687a517a222010da541b87bc91e20a575e2","count": 1144,"preSum": 28170 },{ "ndv": 429,"upper": "6942ff1081136f3da0b7476533b69326ca477b5a73247af40f888805800ce02eeb1f961226f894ab5f73a83c8f58540f05d7a0ea4c9d2f72bcafe13b0d09749","lower": "649b84b63259e926e711a3fc8833fb57de343facf70438e3ad2262f29e95d4a0221e4d0cbb758557c4e773bc91f8e13fecf6193eca7924fd01635801f5ede29f","count": 1157,"preSum": 29314 },{ "ndv": 380,"upper": "6cddfd7e5019351d73d33114f9ab41d5998d5239d08d6673030de3aab26e013e0051223e70e8c3ad32f0c5d47f28ec8a1241d4efcf9","lower": "6943ec3","count": 1145,"preSum": 30471 },{ "ndv": 376,"upper": "70fbc0f930b1fd11fc8c5dd41d03c6a00e394aaded595d2d814cd7fcb906dcf74ddf86204a23aadcebc88a0b9df27acef465a4e9e8501c9b0511d5378740821b","lower": "6cde863eb5663a369a80e89d284b25dbc41087ec66c990fe6ad024f8362a58354a47bef569f97c59d793268ac9bf88517d7ec1c1153cf05d53557fca79642d62","count": 1176,"preSum": 31616 },{ "ndv": 511,"upper": "75ef4b54dc599d666e7a3de4041871b3956eebd9ed09a18fed3f3f65","lower": "70fc35302222e96999a91ed3e97ac107b23108f6c3432f907b3fd7452bf39906197c75253a451f24cf9fd0","count": 1145,"preSum": 32792 },{ "ndv": 238,"upper": "78a7366861ab7ce92b374eb5360e91c26cbbdd07cefd0e5d3214ea9846e42fbea5cecc0a5047718128b3d6c602f","lower": "75f563470684ec8915306216a68b20018b7f6c62eeb00e6719d0d3012a7f24c1185b70c17ae6d87ec0da05d92c5cdfe5af6562771","count": 1293,"preSum": 33937 },{ "ndv": 305,"upper": "7bce56eca9c26cb210a25dffcf43059de09f3455e2cccd5df1485d7511f91179336950b328e85fd9a71b01a97859e615aeb2e42dd54848c3f8c344bcb5832cf1","lower": "78adc2ff26e81b837ce112db9a0d2f93f60f6854c4f3237d3a748547b5cfe69c445d","count": 1144,"preSum": 35230 },{ "ndv": 420,"upper": "80363a49a4cc7341902df6ce6fbfd74d954bd5","lower": "7bcea9d50d31c8498d8cf8","count": 1144,"preSum": 36374 },{ "ndv": 570,"upper": "865a67b","lower": "803726da7566e2b0997a69ea4fef74b1defc4fdd4626c05a489f20fd","count": 1155,"preSum": 37518 },{ "ndv": 472,"upper": "8bad08a020fa6c69a6d854adc3a9a69adeb827c241c58e8cd0ed5b764acafe8ebb4994f7a154c759c22121","lower": "865e3e30150c71ef5c147e2f791824baaecdc6c8348ad3016d988480dc75860d2","count": 1159,"preSum": 38673 },{ "ndv": 396,"upper": "8fc094b25226d","lower": "8baea5bc5b18b57f390565b1e4498111518376b44835305301e6a63c15a10da0186006de2553b825a511fedc880a48e7e1ae465f31a7441dc74","count": 1193,"preSum": 39832 },{ "ndv": 487,"upper": "94e6805e4cb50b0de6452fdb1f13903ff5f43da62c386918a03e9b4088f6038990496b92e277f28","lower": "8fc221e7d48e26840ad9176d73748fc070afbb17bc7d997d85013d3ffbc9eecc7842f33c0f28842299e7a3e8986504d421c73a9f24c40bd1e31a5e527b1f8d46","count": 1147,"preSum": 41025 },{ "ndv": 413,"upper": "9915b87a2041bf6a270e45975bfd1a09a462398feb3a5e67d1846ef1e7b25a5a3d6017d194f1eab439fa11f4d45791efd25bf3907e746c6a621c40434","lower": "94eaa84fb21c92eda965a7ff6f09eaec008894f9b63690334eca1c194b46be91207585f40e44a131f599162a09dbebe47a1509f9512f375246184286f8b577c5","count": 1150,"preSum": 42172 },{ "ndv": 445,"upper": "9df4d4a6cf35bd72af2b434aa0074c1","lower": "99188be58a271d35dfd9f40cd8dd7f409b1","count": 1187,"preSum": 43322 },{ "ndv": 406,"upper": "a2593a8baa44859a28391d02f76cc5cb45cfd2c2be7fb4b3a51f165b26b38e6c14ad81976bd9f4484","lower": "9df89145d45c9621914c9de1dc953e3ffbe0d6da6292cf4199d15b2635339a2e785fbd00b76a9","count": 1144,"preSum": 44509 },{ "ndv": 381,"upper": "a63b8c7670964cd0cfff43dc7a9e8f9c579fa0e3c37623a740b66cfd4a9071585e1266bd497","lower": "a25a0736f3a0ccb5d4b50d82a4f394629e1fd392ef4521262431e43082f46befeb8d54faa5d120800b496b24c667ab0487030b8963fa464","count": 1144,"preSum": 45653 },{ "ndv": 133,"upper": "a78433bb821ad674545f2bc3e330c9","lower": "a63ea9052d2cbba45d76706520b6953","count": 1148,"preSum": 46797 },{ "ndv": 275,"upper": "aa87e20d809ea68cec8432c2ad232f96d0131083ec9889a4facbcceba06e2ee999dc5c73c9b0","lower": "a7880d21936c3741daf312fc59a9802ba4b69bac0b585a2e992534319b2adc08b6aaff5acf5a2d904b6c0df7d60780dcf7986b085208042e97ce70104d61ccc1","count": 1145,"preSum": 47945 },{ "ndv": 326,"upper": "ad81e341f78942b","lower": "aa8802ae6bb9b04944e3264fd8684e5645bd7d1a646a47452fe71b4ed11ea5e8ed66573","count": 1228,"preSum": 49090 },{ "ndv": 327,"upper": "b0d576543155bf9f29a26a879c787ecd9f373ad5f7c2f1f7620430d6b2ac81e207dd76788de62d2","lower": "ad84002312b9d0734e48f7f04cf2a3bfc3db0c25d0cec1f0114906ad","count": 1145,"preSum": 50318 },{ "ndv": 286,"upper": "b3fde7a2d12db2df9ec2697488f2f358bd2289618feb27461ee1710072eaccda","lower": "b0dfac283ebe21769c6f9e9142b43837fbb95333c3a964809aea45b1898a8adf025e649f616f2f2cf2d0a865c79c1a364ec0b47c1638a767e5d1fe","count": 1148,"preSum": 51463 },{ "ndv": 377,"upper": "b842dbb21a8c84a7f74ab68d92cbc4e956115b9dcf6b72d9e0ec63b25c7acdb12eddba1360fb37feba526f32d00679164184c4df88efee76c875c39f6341c9d8","lower": "b3ff048dfe3df932fa34248fc748cd97627a64c8","count": 1144,"preSum": 52611 },{ "ndv": 474,"upper": "bd12f5300e","lower": "b8441c2092789be9997850426d03ba7b2a5a05ebdbc5f99318413d860a80","count": 1151,"preSum": 53755 },{ "ndv": 463,"upper": "c2081b11e74107819a055179b7b8dbae75fd2c76da570b5644e5d191bbdfae9d18b4beaf025e0ef11d83d4bb8d06263322216d3662cff64e6eb886b2cce9cc4b","lower": "bd1352ca904f61edad8ad5577ecef08c5dd97e9ee79e662b789a37d741e80479435026edc36b3620bc1aa27f989f049acfd9ad6a6fdb57a06b7651295623b873","count": 1173,"preSum": 54906 },{ "ndv": 379,"upper": "c62b9455f9e6c7b9f68fe953575f5f9d35cfd3b591451fe5da7b282e0f493a6a88a818ff42d02d270d55ba476e03d3b5dc6da6245a968a8e839cd8509f985aa7","lower": "c20d91b52e16834d284f2e726f08b20234545d4","count": 1144,"preSum": 56079 },{ "ndv": 395,"upper": "ca4c35f99bfd3e05e12934db4","lower": "c62cbe63bfe40e26eb92b04bd60a0a64b8e4088128ad1458dd0041bfde2d9fb8c725b8b7366696a6ee14c38752ecd27b377b2ef80cd2c4d055869f4e5edb9ced","count": 1144,"preSum": 57223 },{ "ndv": 464,"upper": "cf7891b44f7dd6d7095ed9","lower": "ca4d8032af9b36de8060d272645e0d7d7fcb6f57c52b2ebf82a8ef","count": 1146,"preSum": 58367 },{ "ndv": 458,"upper": "d454a6d07f437a9e64e6","lower": "cf790731e1f5d6d4185db7e3f593b92ca6e8e0aec77384db9792efab2f332e2093ce1cd3ad40c64ea07aa436be557b49418fef4b7e8170044bb4925e7496b2fe","count": 1146,"preSum": 59513 },{ "ndv": 394,"upper": "d878e482d6334a6c662d69f11f134ee3eeff2170ce21e80ff0e96e135d1f803e452b73c952d4435039769efe467cdcda83ad27ebe7ebccf314d1ecf7e7f96e13","lower": "d456143","count": 1154,"preSum": 60659 },{ "ndv": 360,"upper": "dc0e7da4200ca9a3ec8a6e16f42","lower": "d87929e38417eae8835340af4c0fbaf412e056570c487e016afe69656e885787b92c06d8cc9b384b2155a7bcc86e5ea0281b0aa8b9ad9399dcf0687ce2d2d780","count": 1144,"preSum": 61813 },{ "ndv": 421,"upper": "e09e86ce83605d38880c6491a69f2755d7ca5715675f0403aefb2a302fc28010704c296f","lower": "dc1623326522a343","count": 1144,"preSum": 62957 },{ "ndv": 355,"upper": "e4504b2a1dee2aea0d09c559dcf1caeb50fe5b0c59c8c0acc8e24208ae89ea2efc618866d8d747072389f79753af97969da70a701b6e1062e8cefafe9de98711","lower": "e09f02af00ab5e7025e43d06c6f4c128e01d32b4c806dcf1fc95a749c9d81b794bf0b295bb7c5b538431d0880ec374e0af5fb7ad2807457709d648b5f1554031","count": 1144,"preSum": 64101 },{ "ndv": 432,"upper": "e8baa59dfd4044601121ce6ad0160649f4f79a11a9e582f5108a6f0f3f58a1a5e07aff705a585f2b05a89984333d70a917ad942c618adbc9559cec9d817eb937","lower": "e451bdf0d7fd0d48d1c5ab7f16d08582992286531cf1b9a3e1f3d10439e","count": 1145,"preSum": 65245 },{ "ndv": 442,"upper": "edc5fb707b60b40c546cc3eb09dd4323ab4ea43c520dc3dce14bb02364ab1473aca79929e3963abfabb3c41e2fee43f005f429d76cb404ac90b163cc9fcaaf9a","lower": "e8bb7926864e4aef02b247e52f55b47979941b10cd4b709c0f5a9fd2270f6514e4d9d7c67acb8442c7f2e56ded318952ca0cd83d7266e8416f49951ad17a8789","count": 1144,"preSum": 66390 },{ "ndv": 396,"upper": "f1b6b62ace4cc416c97c45cf3831e1a47249f9753fb1c15fa694cd10237a597d3587ca099f8707ef5bf7cdda6cb843c45ded20d2963","lower": "edc723027c6aba7bef4dbc91bbb3602e5bca2848dbbdba121a36dbafc224b2aea18b874a86a23f790004a271c902b25dbe5942bbcdcde5e9c6daa35f33c324b9","count": 1145,"preSum": 67534 },{ "ndv": 425,"upper": "f6142003c59c5ebe8a978edee6529242f50894519c338ed2e4a199d3a14c501b0ba463d08dc27d0f96d14768985bd89c6ed5164be5caecddec46efa7109cd63c","lower": "f1bb5c7eeff9b184f42ddeada669","count": 1144,"preSum": 68679 },{ "ndv": 368,"upper": "fa0d4de16b01a9993262227728e9b287384cca5210f17f529d8dbabc8beefc55e1b644c85335e77b5030a2339559f13b0a17199c18f0689de84bf4865e3c0e81","lower": "f620ee113e5e40e36aed2282209513d0bfb9ceb9473209","count": 1146,"preSum": 69823 },{ "ndv": 370,"upper": "fded7fa41eb780622315ce0a7","lower": "fa0d702adecc9bf","count": 1599,"preSum": 70969 },{ "ndv": 181,"upper": "fffc62ed702e63782b0ac3ebdbe63aa14e2d9b7c68a","lower": "fded80d4d500ef1ba8aec25c271debd038834fb213eece768b4adc402d914dc16fee1fae59807380e22b3a80c92ffba671d817ec4b7d919253930b2d0","count": 621,"preSum": 72568 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_text.null_count:
+    0
+  cest_full_table_big.c_text.sample_rate:
+    0.010943651
+  cest_full_table_big.c_text_long.TOPN:
+    { "countArr": [ 2129,747,1152,2604,1061,4041,663,8212,877,1720,929,1401,654,622 ],"valueArr": [ "272901f7b4866c38cfdad0ee58e710055bd6f342c756efa3ea2c5414d1c8d334c9cd42fff815d8c800a1a7bc096cf77897e8375e32b12cb22a33cd62d840c68d","2aa4d5c39254825a73c8285fdfd0cb082cdbc465bff473642e153dbf9818be56f217072a5c7867fbcecbf15e47b88de9d80f468b8f6a85f955d20f808c77d42a","4a9e0d094ccec5f3ab0ee0ccdae5d42db6ff517ba578c8d9487aece02602c334733224fac97026bf3367678500458693ccb86eb285b","5ee951d1927147b17bb57cf07545f785341b9aeb920e85ca1c","884e206f2e3ec07a388151bddf4d2362db2a90a8ece685e96e1c2befd992ca6d4320460c618cf5ec78a7932c7cc4ae2a50962f5e8b820853f2773ec79f9aa865","8f4b82ccc477a1d4817a0713716a1a9e0abdb99fb556d066bd4663a261367328af7c4f078b4283c7d3bde3398bbeb466cd176ee7150e33107dca10c8322e0e","9081f4c0e8c85ee47ead80cdbc5f081e9cc6428718903b5f35107125e08896ba5f5172f9b5428ba371a6137715b9433d6b85cbb56c7f274ce7f86b6f66a5e313","ae093e295bf106c3d99ebb56b5c6978fb3e","b200919aa862b99712074cde83b3c18e25c4fd15","bc10f23cffb6b25587d94e646accc5b988bcb651c161925d2c5f8aa0bac12f1f290ab10f38fb5c727ad5da443c2daad1fe27901a5b9f79cd93a","c292b6a83f3518061f48c1dad1fa4d2c3e19eefcf6d90a0b08b456ab655a4c1e28257a3691b286cd81108acb9981558e411ab13520eaae125e4160f7d409d7f9","ce073c56e6291d3fcb1050e6a705e143712f1272439d96200d18b826e","cfe9b21e9d0bee82cf485c1644e7fc722764462d88e885b27cea8dead24cf1279a75c78df843678c4244278a8c7172d240d27e597f4975610eaf6da3176269ef","dd946928cf4b699b145e020fde6ca56b98c6bcb81e47f3dc93c76a5e2c6b9487a" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_text_long.cardinality:
+    243039
+  cest_full_table_big.c_text_long.histogram:
+    { "buckets": [ { "ndv": 166,"upper": "01dde7823023499a10f85591dc6af7747d89c8aa5b5","lower": "0","count": 1144,"preSum": 0 },{ "ndv": 571,"upper": "07cdf3cec6575290c3605446ed","lower": "01de5a4451a0e2648f4124d2e6c725a8302e48c132bc53022ca7462861f814dabb4f87ffc3a1e9357194adf600e97ac3e9816416b348fbb7d993843ca4861a9c","count": 1144,"preSum": 1144 },{ "ndv": 385,"upper": "0b9a1d61777836df3728cafa83c438b50f788c8c877bf0","lower": "07ceb4fa2aa3d114bf15a103d51f2a325543269a30de9b082851","count": 1145,"preSum": 2288 },{ "ndv": 511,"upper": "1113f79e0f5556eb128234780d9dc43dac44ff6f02d36cfe453ce7740f7bbacc9cbd9c8fff34e16bcf2f0d4d2f8b14990aba3f5d557e19d21dac182b7eaed214","lower": "0b9c4e79f1ff05e2dcf2cc92ae6d00c41dae43730263ca5658c0d3a3d1bf1c3a517bde9064e517d7eb344db3ca6a078a2ae3061c3f186809b3350dd9770f816c","count": 1190,"preSum": 3433 },{ "ndv": 190,"upper": "1311e1fd42260161612493575ce96bb850c6d5bcff96788f2e684e4b85bdfa805b539b0f6dd915c4a950ec4","lower": "111522044fa68d83ef2dc4c163eef6bbff2f6ee58fd5e6b0779a3558a95cc073723bbe5a27ebb52868941fa6a6fbafbce2b4dab2ff54b80a7b0a868b67d2e804","count": 1449,"preSum": 4623 },{ "ndv": 495,"upper": "17f78","lower": "1312df8d2b0b162234bf63e35e04457ca5c44cb3a93f0fdb9d4e676bedbd18dd42ac0efbcdfc822acfe3","count": 1293,"preSum": 6072 },{ "ndv": 330,"upper": "1b2b044fa17eb9b2ff7798fdbdacfd9375b20ca0f022e75c6da410673d96","lower": "17f7c2386996a38ce235cba0f1b009829aa9816a794437c4eeab3afb5094145d083","count": 1145,"preSum": 7365 },{ "ndv": 508,"upper": "205bb8f17e5224cfe3f2a340724491356c2e44adb8225890e19d820326c8a1392530aec1f4d07f994db22c6dabf1d230c81133038161de925bde002ffa9abbbe","lower": "1b2ccd0ca37e1b3902f4794b5fb5ba11","count": 1166,"preSum": 8510 },{ "ndv": 395,"upper": "2489cf31553d6e40d04c8f6","lower": "20609b96de0278b56462c3e104ef76f789e074927d7ee81d207b1fafcbe3f8266f4a268476909d8e2e7a","count": 1204,"preSum": 9676 },{ "ndv": 431,"upper": "28b02ac065e2cc1bbe517930e1d07f04e5cd8ec8c01488f9","lower": "248c920cebc921cb395d00fd3e2b567572e36fc773","count": 1144,"preSum": 10880 },{ "ndv": 369,"upper": "2cb456ee2d29c4703cfe26e290adffa03be1df47c17bc21332782fd9a067867edb1cc436cfc019762b0ab2732cfc735487969d8dd3ddf25e","lower": "28b0526659a25aefb71d8d34c6c146378bb40abd36f74d3694ebb61939c5f0bf8d5d828e86987619287886c4f901b89b6a57a45fde4fed074cb5c749e355d446","count": 1145,"preSum": 12024 },{ "ndv": 401,"upper": "310a1471df0f7661b08941c102ecf376","lower": "2cb527aa5bfd4468f64fa2d2ac61ecaf45615ca1965c91bd9c6be1cb2255377ced816533f80c91bafb93c0dfcc71de9c164","count": 1202,"preSum": 13169 },{ "ndv": 461,"upper": "35c6c1279085e58dc930071b7bdd15114913135ea39ad2ac6d1ef39cd07d","lower": "310b22f9931e4f311fe42fca59b4f23ed1e6dae708a59af169e491dba8ac7e98eb60070b40d253c3d8c0b5e9573b08f009c02ad44124d3609f9e400105b155","count": 1146,"preSum": 14371 },{ "ndv": 384,"upper": "393c28a88a013c7c969d008ea2972ec2a0d1ffd23cb361656617ae133e1357a14411438fc5a447e0bd9e0427cadea0dcf6af6a9bfc8abf0ec361fd91d66d5382","lower": "35c9f453764aaa291bcc895f7e258eb13eb04da91c0101c90365e41fbfb22ee953916a708d67c3dbbd287c3c0072d31d1fab8d9f3e97fea5d91f952e3319df0f","count": 1144,"preSum": 15517 },{ "ndv": 373,"upper": "3d307f1902b9f2d8bcd78b556f3b6f62208153308d7bf810cc471cb9fc47dabb68fbbd2f1a8e95a6fb5183389132f0e0dcf8f52e3a1c9bb3","lower": "3942568ee95b7b3f8573f806857903cd4dc87f88c3a9982797b2f2f578bd37e19dc8d8bd652efe5c713bfbab387e24e9c065","count": 1144,"preSum": 16661 },{ "ndv": 381,"upper": "410e26cac9e7f8d25b7689111f0a62a21eb4d63ea6169f95e7c167c5ca784b190127","lower": "3d323107538c7e2059be414e5cf6","count": 1144,"preSum": 17805 },{ "ndv": 218,"upper": "435a8cc58fc6c26aa437323744258f622fe49f4a06ef984d93be","lower": "4111485b903225eb7ad50fa9f854b7dbdfa9d051922c03b99fbddbd6afd7d34dc0d3189","count": 1164,"preSum": 18949 },{ "ndv": 423,"upper": "4771f0477e5fdc9a9cb582cac0a78809adc7504e6671ab16171db96f7667f5ffef8746e6f7d10100afdd78132ab081f0c585061ff62cd8d9ecfeea1fdbd01f26","lower": "435aa344d995f0d25513e501b98dbe5cf979c29e00ba08173ffda95a3e9a50c446d28b344049ccdbcb102c25cccd","count": 1164,"preSum": 20113 },{ "ndv": 581,"upper": "4da801e50c2431beab882819538ac3ba91868f642acbff073b68daa20b0f9c73b91a5d14b6b31bc507bb538a799c01b3507c41c02debda78f0f225f8eab84083","lower": "47737e5333b789dfe19c9e5ef8f417d87f1efbbdf29b539b5e88501f7e78b240080155e1cf7aaaccb5fd95740b3154566a1926d159c42f2","count": 1148,"preSum": 21277 },{ "ndv": 370,"upper": "519bef86b1ccf9a9f129a7b279e6adea1e505aef2cab78ff299182674ee5a488c7ffce8626a4","lower": "4da9d3313d55edf9e34b87eef7bc3696","count": 1144,"preSum": 22425 },{ "ndv": 297,"upper": "551a06c68d3a9bb87456c05c97d467af6daa215a60d785b5fdc549e04aaca3c877ce53236bc762d96f09","lower": "51a409db586ec283c1fc2132165ac08fb45","count": 1164,"preSum": 23569 },{ "ndv": 348,"upper": "58cbf97af20e30bc9d364928e1277d20437cecc31581e9889103826d6267","lower": "551de0f7595d913b67db679d834eea6abe1adbd3dba6e54a79eac7cbfa6b6295fa98bd8c89e58b81074fa267b633f76ad5e4c2788a61d1c3615daba6cff41f62","count": 1144,"preSum": 24733 },{ "ndv": 409,"upper": "5d8640d86728c786910ba253a149dd6aca1b6ecd3cd474e5ce7b5a73535d5aaa8","lower": "58ccca4da871e16053350dc6133b61a2f0e3347919d530830d6a304a28ef227228e6499a369b277c022a4fea645a4ffca685eb74a46de26f804bfaff856af6da","count": 1144,"preSum": 25877 },{ "ndv": 250,"upper": "600517214987915eb4b511d","lower": "5d89b00c7ae9609a56f860145a17288025d78e89f9d25d82fb9f52d004b7de35f7a4320","count": 1149,"preSum": 27021 },{ "ndv": 426,"upper": "64964da26aa4e7a9af119b294728d91b4de9a2325df7c48d84b5b3967cffa705b3a0eabe9e77238d531f32755f38e508d4a259664ad61a3e8920e091cf9556e5","lower": "600555308b687a517a222010da541b87bc91e20a575e2","count": 1144,"preSum": 28170 },{ "ndv": 429,"upper": "6942ff1081136f3da0b7476533b69326ca477b5a73247af40f888805800ce02eeb1f961226f894ab5f73a83c8f58540f05d7a0ea4c9d2f72bcafe13b0d09749","lower": "649b84b63259e926e711a3fc8833fb57de343facf70438e3ad2262f29e95d4a0221e4d0cbb758557c4e773bc91f8e13fecf6193eca7924fd01635801f5ede29f","count": 1157,"preSum": 29314 },{ "ndv": 380,"upper": "6cddfd7e5019351d73d33114f9ab41d5998d5239d08d6673030de3aab26e013e0051223e70e8c3ad32f0c5d47f28ec8a1241d4efcf9","lower": "6943ec3","count": 1145,"preSum": 30471 },{ "ndv": 376,"upper": "70fbc0f930b1fd11fc8c5dd41d03c6a00e394aaded595d2d814cd7fcb906dcf74ddf86204a23aadcebc88a0b9df27acef465a4e9e8501c9b0511d5378740821b","lower": "6cde863eb5663a369a80e89d284b25dbc41087ec66c990fe6ad024f8362a58354a47bef569f97c59d793268ac9bf88517d7ec1c1153cf05d53557fca79642d62","count": 1176,"preSum": 31616 },{ "ndv": 511,"upper": "75ef4b54dc599d666e7a3de4041871b3956eebd9ed09a18fed3f3f65","lower": "70fc35302222e96999a91ed3e97ac107b23108f6c3432f907b3fd7452bf39906197c75253a451f24cf9fd0","count": 1145,"preSum": 32792 },{ "ndv": 238,"upper": "78a7366861ab7ce92b374eb5360e91c26cbbdd07cefd0e5d3214ea9846e42fbea5cecc0a5047718128b3d6c602f","lower": "75f563470684ec8915306216a68b20018b7f6c62eeb00e6719d0d3012a7f24c1185b70c17ae6d87ec0da05d92c5cdfe5af6562771","count": 1293,"preSum": 33937 },{ "ndv": 305,"upper": "7bce56eca9c26cb210a25dffcf43059de09f3455e2cccd5df1485d7511f91179336950b328e85fd9a71b01a97859e615aeb2e42dd54848c3f8c344bcb5832cf1","lower": "78adc2ff26e81b837ce112db9a0d2f93f60f6854c4f3237d3a748547b5cfe69c445d","count": 1144,"preSum": 35230 },{ "ndv": 420,"upper": "80363a49a4cc7341902df6ce6fbfd74d954bd5","lower": "7bcea9d50d31c8498d8cf8","count": 1144,"preSum": 36374 },{ "ndv": 570,"upper": "865a67b","lower": "803726da7566e2b0997a69ea4fef74b1defc4fdd4626c05a489f20fd","count": 1155,"preSum": 37518 },{ "ndv": 472,"upper": "8bad08a020fa6c69a6d854adc3a9a69adeb827c241c58e8cd0ed5b764acafe8ebb4994f7a154c759c22121","lower": "865e3e30150c71ef5c147e2f791824baaecdc6c8348ad3016d988480dc75860d2","count": 1159,"preSum": 38673 },{ "ndv": 396,"upper": "8fc094b25226d","lower": "8baea5bc5b18b57f390565b1e4498111518376b44835305301e6a63c15a10da0186006de2553b825a511fedc880a48e7e1ae465f31a7441dc74","count": 1193,"preSum": 39832 },{ "ndv": 487,"upper": "94e6805e4cb50b0de6452fdb1f13903ff5f43da62c386918a03e9b4088f6038990496b92e277f28","lower": "8fc221e7d48e26840ad9176d73748fc070afbb17bc7d997d85013d3ffbc9eecc7842f33c0f28842299e7a3e8986504d421c73a9f24c40bd1e31a5e527b1f8d46","count": 1147,"preSum": 41025 },{ "ndv": 413,"upper": "9915b87a2041bf6a270e45975bfd1a09a462398feb3a5e67d1846ef1e7b25a5a3d6017d194f1eab439fa11f4d45791efd25bf3907e746c6a621c40434","lower": "94eaa84fb21c92eda965a7ff6f09eaec008894f9b63690334eca1c194b46be91207585f40e44a131f599162a09dbebe47a1509f9512f375246184286f8b577c5","count": 1150,"preSum": 42172 },{ "ndv": 445,"upper": "9df4d4a6cf35bd72af2b434aa0074c1","lower": "99188be58a271d35dfd9f40cd8dd7f409b1","count": 1187,"preSum": 43322 },{ "ndv": 406,"upper": "a2593a8baa44859a28391d02f76cc5cb45cfd2c2be7fb4b3a51f165b26b38e6c14ad81976bd9f4484","lower": "9df89145d45c9621914c9de1dc953e3ffbe0d6da6292cf4199d15b2635339a2e785fbd00b76a9","count": 1144,"preSum": 44509 },{ "ndv": 381,"upper": "a63b8c7670964cd0cfff43dc7a9e8f9c579fa0e3c37623a740b66cfd4a9071585e1266bd497","lower": "a25a0736f3a0ccb5d4b50d82a4f394629e1fd392ef4521262431e43082f46befeb8d54faa5d120800b496b24c667ab0487030b8963fa464","count": 1144,"preSum": 45653 },{ "ndv": 133,"upper": "a78433bb821ad674545f2bc3e330c9","lower": "a63ea9052d2cbba45d76706520b6953","count": 1148,"preSum": 46797 },{ "ndv": 275,"upper": "aa87e20d809ea68cec8432c2ad232f96d0131083ec9889a4facbcceba06e2ee999dc5c73c9b0","lower": "a7880d21936c3741daf312fc59a9802ba4b69bac0b585a2e992534319b2adc08b6aaff5acf5a2d904b6c0df7d60780dcf7986b085208042e97ce70104d61ccc1","count": 1145,"preSum": 47945 },{ "ndv": 326,"upper": "ad81e341f78942b","lower": "aa8802ae6bb9b04944e3264fd8684e5645bd7d1a646a47452fe71b4ed11ea5e8ed66573","count": 1228,"preSum": 49090 },{ "ndv": 327,"upper": "b0d576543155bf9f29a26a879c787ecd9f373ad5f7c2f1f7620430d6b2ac81e207dd76788de62d2","lower": "ad84002312b9d0734e48f7f04cf2a3bfc3db0c25d0cec1f0114906ad","count": 1145,"preSum": 50318 },{ "ndv": 286,"upper": "b3fde7a2d12db2df9ec2697488f2f358bd2289618feb27461ee1710072eaccda","lower": "b0dfac283ebe21769c6f9e9142b43837fbb95333c3a964809aea45b1898a8adf025e649f616f2f2cf2d0a865c79c1a364ec0b47c1638a767e5d1fe","count": 1148,"preSum": 51463 },{ "ndv": 377,"upper": "b842dbb21a8c84a7f74ab68d92cbc4e956115b9dcf6b72d9e0ec63b25c7acdb12eddba1360fb37feba526f32d00679164184c4df88efee76c875c39f6341c9d8","lower": "b3ff048dfe3df932fa34248fc748cd97627a64c8","count": 1144,"preSum": 52611 },{ "ndv": 474,"upper": "bd12f5300e","lower": "b8441c2092789be9997850426d03ba7b2a5a05ebdbc5f99318413d860a80","count": 1151,"preSum": 53755 },{ "ndv": 463,"upper": "c2081b11e74107819a055179b7b8dbae75fd2c76da570b5644e5d191bbdfae9d18b4beaf025e0ef11d83d4bb8d06263322216d3662cff64e6eb886b2cce9cc4b","lower": "bd1352ca904f61edad8ad5577ecef08c5dd97e9ee79e662b789a37d741e80479435026edc36b3620bc1aa27f989f049acfd9ad6a6fdb57a06b7651295623b873","count": 1173,"preSum": 54906 },{ "ndv": 379,"upper": "c62b9455f9e6c7b9f68fe953575f5f9d35cfd3b591451fe5da7b282e0f493a6a88a818ff42d02d270d55ba476e03d3b5dc6da6245a968a8e839cd8509f985aa7","lower": "c20d91b52e16834d284f2e726f08b20234545d4","count": 1144,"preSum": 56079 },{ "ndv": 395,"upper": "ca4c35f99bfd3e05e12934db4","lower": "c62cbe63bfe40e26eb92b04bd60a0a64b8e4088128ad1458dd0041bfde2d9fb8c725b8b7366696a6ee14c38752ecd27b377b2ef80cd2c4d055869f4e5edb9ced","count": 1144,"preSum": 57223 },{ "ndv": 464,"upper": "cf7891b44f7dd6d7095ed9","lower": "ca4d8032af9b36de8060d272645e0d7d7fcb6f57c52b2ebf82a8ef","count": 1146,"preSum": 58367 },{ "ndv": 458,"upper": "d454a6d07f437a9e64e6","lower": "cf790731e1f5d6d4185db7e3f593b92ca6e8e0aec77384db9792efab2f332e2093ce1cd3ad40c64ea07aa436be557b49418fef4b7e8170044bb4925e7496b2fe","count": 1146,"preSum": 59513 },{ "ndv": 394,"upper": "d878e482d6334a6c662d69f11f134ee3eeff2170ce21e80ff0e96e135d1f803e452b73c952d4435039769efe467cdcda83ad27ebe7ebccf314d1ecf7e7f96e13","lower": "d456143","count": 1154,"preSum": 60659 },{ "ndv": 360,"upper": "dc0e7da4200ca9a3ec8a6e16f42","lower": "d87929e38417eae8835340af4c0fbaf412e056570c487e016afe69656e885787b92c06d8cc9b384b2155a7bcc86e5ea0281b0aa8b9ad9399dcf0687ce2d2d780","count": 1144,"preSum": 61813 },{ "ndv": 421,"upper": "e09e86ce83605d38880c6491a69f2755d7ca5715675f0403aefb2a302fc28010704c296f","lower": "dc1623326522a343","count": 1144,"preSum": 62957 },{ "ndv": 355,"upper": "e4504b2a1dee2aea0d09c559dcf1caeb50fe5b0c59c8c0acc8e24208ae89ea2efc618866d8d747072389f79753af97969da70a701b6e1062e8cefafe9de98711","lower": "e09f02af00ab5e7025e43d06c6f4c128e01d32b4c806dcf1fc95a749c9d81b794bf0b295bb7c5b538431d0880ec374e0af5fb7ad2807457709d648b5f1554031","count": 1144,"preSum": 64101 },{ "ndv": 432,"upper": "e8baa59dfd4044601121ce6ad0160649f4f79a11a9e582f5108a6f0f3f58a1a5e07aff705a585f2b05a89984333d70a917ad942c618adbc9559cec9d817eb937","lower": "e451bdf0d7fd0d48d1c5ab7f16d08582992286531cf1b9a3e1f3d10439e","count": 1145,"preSum": 65245 },{ "ndv": 442,"upper": "edc5fb707b60b40c546cc3eb09dd4323ab4ea43c520dc3dce14bb02364ab1473aca79929e3963abfabb3c41e2fee43f005f429d76cb404ac90b163cc9fcaaf9a","lower": "e8bb7926864e4aef02b247e52f55b47979941b10cd4b709c0f5a9fd2270f6514e4d9d7c67acb8442c7f2e56ded318952ca0cd83d7266e8416f49951ad17a8789","count": 1144,"preSum": 66390 },{ "ndv": 396,"upper": "f1b6b62ace4cc416c97c45cf3831e1a47249f9753fb1c15fa694cd10237a597d3587ca099f8707ef5bf7cdda6cb843c45ded20d2963","lower": "edc723027c6aba7bef4dbc91bbb3602e5bca2848dbbdba121a36dbafc224b2aea18b874a86a23f790004a271c902b25dbe5942bbcdcde5e9c6daa35f33c324b9","count": 1145,"preSum": 67534 },{ "ndv": 425,"upper": "f6142003c59c5ebe8a978edee6529242f50894519c338ed2e4a199d3a14c501b0ba463d08dc27d0f96d14768985bd89c6ed5164be5caecddec46efa7109cd63c","lower": "f1bb5c7eeff9b184f42ddeada669","count": 1144,"preSum": 68679 },{ "ndv": 368,"upper": "fa0d4de16b01a9993262227728e9b287384cca5210f17f529d8dbabc8beefc55e1b644c85335e77b5030a2339559f13b0a17199c18f0689de84bf4865e3c0e81","lower": "f620ee113e5e40e36aed2282209513d0bfb9ceb9473209","count": 1146,"preSum": 69823 },{ "ndv": 370,"upper": "fded7fa41eb780622315ce0a7","lower": "fa0d702adecc9bf","count": 1599,"preSum": 70969 },{ "ndv": 181,"upper": "fffc62ed702e63782b0ac3ebdbe63aa14e2d9b7c68a","lower": "fded80d4d500ef1ba8aec25c271debd038834fb213eece768b4adc402d914dc16fee1fae59807380e22b3a80c92ffba671d817ec4b7d919253930b2d0","count": 621,"preSum": 72568 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_text_long.null_count:
+    0
+  cest_full_table_big.c_text_long.sample_rate:
+    0.010943651
+  cest_full_table_big.c_text_medium.TOPN:
+    { "countArr": [ 2129,747,1152,2604,1061,4041,663,8212,877,1720,929,1401,654,622 ],"valueArr": [ "272901f7b4866c38cfdad0ee58e710055bd6f342c756efa3ea2c5414d1c8d334c9cd42fff815d8c800a1a7bc096cf77897e8375e32b12cb22a33cd62d840c68d","2aa4d5c39254825a73c8285fdfd0cb082cdbc465bff473642e153dbf9818be56f217072a5c7867fbcecbf15e47b88de9d80f468b8f6a85f955d20f808c77d42a","4a9e0d094ccec5f3ab0ee0ccdae5d42db6ff517ba578c8d9487aece02602c334733224fac97026bf3367678500458693ccb86eb285b","5ee951d1927147b17bb57cf07545f785341b9aeb920e85ca1c","884e206f2e3ec07a388151bddf4d2362db2a90a8ece685e96e1c2befd992ca6d4320460c618cf5ec78a7932c7cc4ae2a50962f5e8b820853f2773ec79f9aa865","8f4b82ccc477a1d4817a0713716a1a9e0abdb99fb556d066bd4663a261367328af7c4f078b4283c7d3bde3398bbeb466cd176ee7150e33107dca10c8322e0e","9081f4c0e8c85ee47ead80cdbc5f081e9cc6428718903b5f35107125e08896ba5f5172f9b5428ba371a6137715b9433d6b85cbb56c7f274ce7f86b6f66a5e313","ae093e295bf106c3d99ebb56b5c6978fb3e","b200919aa862b99712074cde83b3c18e25c4fd15","bc10f23cffb6b25587d94e646accc5b988bcb651c161925d2c5f8aa0bac12f1f290ab10f38fb5c727ad5da443c2daad1fe27901a5b9f79cd93a","c292b6a83f3518061f48c1dad1fa4d2c3e19eefcf6d90a0b08b456ab655a4c1e28257a3691b286cd81108acb9981558e411ab13520eaae125e4160f7d409d7f9","ce073c56e6291d3fcb1050e6a705e143712f1272439d96200d18b826e","cfe9b21e9d0bee82cf485c1644e7fc722764462d88e885b27cea8dead24cf1279a75c78df843678c4244278a8c7172d240d27e597f4975610eaf6da3176269ef","dd946928cf4b699b145e020fde6ca56b98c6bcb81e47f3dc93c76a5e2c6b9487a" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_text_medium.cardinality:
+    243039
+  cest_full_table_big.c_text_medium.histogram:
+    { "buckets": [ { "ndv": 166,"upper": "01dde7823023499a10f85591dc6af7747d89c8aa5b5","lower": "0","count": 1144,"preSum": 0 },{ "ndv": 571,"upper": "07cdf3cec6575290c3605446ed","lower": "01de5a4451a0e2648f4124d2e6c725a8302e48c132bc53022ca7462861f814dabb4f87ffc3a1e9357194adf600e97ac3e9816416b348fbb7d993843ca4861a9c","count": 1144,"preSum": 1144 },{ "ndv": 385,"upper": "0b9a1d61777836df3728cafa83c438b50f788c8c877bf0","lower": "07ceb4fa2aa3d114bf15a103d51f2a325543269a30de9b082851","count": 1145,"preSum": 2288 },{ "ndv": 511,"upper": "1113f79e0f5556eb128234780d9dc43dac44ff6f02d36cfe453ce7740f7bbacc9cbd9c8fff34e16bcf2f0d4d2f8b14990aba3f5d557e19d21dac182b7eaed214","lower": "0b9c4e79f1ff05e2dcf2cc92ae6d00c41dae43730263ca5658c0d3a3d1bf1c3a517bde9064e517d7eb344db3ca6a078a2ae3061c3f186809b3350dd9770f816c","count": 1190,"preSum": 3433 },{ "ndv": 190,"upper": "1311e1fd42260161612493575ce96bb850c6d5bcff96788f2e684e4b85bdfa805b539b0f6dd915c4a950ec4","lower": "111522044fa68d83ef2dc4c163eef6bbff2f6ee58fd5e6b0779a3558a95cc073723bbe5a27ebb52868941fa6a6fbafbce2b4dab2ff54b80a7b0a868b67d2e804","count": 1449,"preSum": 4623 },{ "ndv": 495,"upper": "17f78","lower": "1312df8d2b0b162234bf63e35e04457ca5c44cb3a93f0fdb9d4e676bedbd18dd42ac0efbcdfc822acfe3","count": 1293,"preSum": 6072 },{ "ndv": 330,"upper": "1b2b044fa17eb9b2ff7798fdbdacfd9375b20ca0f022e75c6da410673d96","lower": "17f7c2386996a38ce235cba0f1b009829aa9816a794437c4eeab3afb5094145d083","count": 1145,"preSum": 7365 },{ "ndv": 508,"upper": "205bb8f17e5224cfe3f2a340724491356c2e44adb8225890e19d820326c8a1392530aec1f4d07f994db22c6dabf1d230c81133038161de925bde002ffa9abbbe","lower": "1b2ccd0ca37e1b3902f4794b5fb5ba11","count": 1166,"preSum": 8510 },{ "ndv": 395,"upper": "2489cf31553d6e40d04c8f6","lower": "20609b96de0278b56462c3e104ef76f789e074927d7ee81d207b1fafcbe3f8266f4a268476909d8e2e7a","count": 1204,"preSum": 9676 },{ "ndv": 431,"upper": "28b02ac065e2cc1bbe517930e1d07f04e5cd8ec8c01488f9","lower": "248c920cebc921cb395d00fd3e2b567572e36fc773","count": 1144,"preSum": 10880 },{ "ndv": 369,"upper": "2cb456ee2d29c4703cfe26e290adffa03be1df47c17bc21332782fd9a067867edb1cc436cfc019762b0ab2732cfc735487969d8dd3ddf25e","lower": "28b0526659a25aefb71d8d34c6c146378bb40abd36f74d3694ebb61939c5f0bf8d5d828e86987619287886c4f901b89b6a57a45fde4fed074cb5c749e355d446","count": 1145,"preSum": 12024 },{ "ndv": 401,"upper": "310a1471df0f7661b08941c102ecf376","lower": "2cb527aa5bfd4468f64fa2d2ac61ecaf45615ca1965c91bd9c6be1cb2255377ced816533f80c91bafb93c0dfcc71de9c164","count": 1202,"preSum": 13169 },{ "ndv": 461,"upper": "35c6c1279085e58dc930071b7bdd15114913135ea39ad2ac6d1ef39cd07d","lower": "310b22f9931e4f311fe42fca59b4f23ed1e6dae708a59af169e491dba8ac7e98eb60070b40d253c3d8c0b5e9573b08f009c02ad44124d3609f9e400105b155","count": 1146,"preSum": 14371 },{ "ndv": 384,"upper": "393c28a88a013c7c969d008ea2972ec2a0d1ffd23cb361656617ae133e1357a14411438fc5a447e0bd9e0427cadea0dcf6af6a9bfc8abf0ec361fd91d66d5382","lower": "35c9f453764aaa291bcc895f7e258eb13eb04da91c0101c90365e41fbfb22ee953916a708d67c3dbbd287c3c0072d31d1fab8d9f3e97fea5d91f952e3319df0f","count": 1144,"preSum": 15517 },{ "ndv": 373,"upper": "3d307f1902b9f2d8bcd78b556f3b6f62208153308d7bf810cc471cb9fc47dabb68fbbd2f1a8e95a6fb5183389132f0e0dcf8f52e3a1c9bb3","lower": "3942568ee95b7b3f8573f806857903cd4dc87f88c3a9982797b2f2f578bd37e19dc8d8bd652efe5c713bfbab387e24e9c065","count": 1144,"preSum": 16661 },{ "ndv": 381,"upper": "410e26cac9e7f8d25b7689111f0a62a21eb4d63ea6169f95e7c167c5ca784b190127","lower": "3d323107538c7e2059be414e5cf6","count": 1144,"preSum": 17805 },{ "ndv": 218,"upper": "435a8cc58fc6c26aa437323744258f622fe49f4a06ef984d93be","lower": "4111485b903225eb7ad50fa9f854b7dbdfa9d051922c03b99fbddbd6afd7d34dc0d3189","count": 1164,"preSum": 18949 },{ "ndv": 423,"upper": "4771f0477e5fdc9a9cb582cac0a78809adc7504e6671ab16171db96f7667f5ffef8746e6f7d10100afdd78132ab081f0c585061ff62cd8d9ecfeea1fdbd01f26","lower": "435aa344d995f0d25513e501b98dbe5cf979c29e00ba08173ffda95a3e9a50c446d28b344049ccdbcb102c25cccd","count": 1164,"preSum": 20113 },{ "ndv": 581,"upper": "4da801e50c2431beab882819538ac3ba91868f642acbff073b68daa20b0f9c73b91a5d14b6b31bc507bb538a799c01b3507c41c02debda78f0f225f8eab84083","lower": "47737e5333b789dfe19c9e5ef8f417d87f1efbbdf29b539b5e88501f7e78b240080155e1cf7aaaccb5fd95740b3154566a1926d159c42f2","count": 1148,"preSum": 21277 },{ "ndv": 370,"upper": "519bef86b1ccf9a9f129a7b279e6adea1e505aef2cab78ff299182674ee5a488c7ffce8626a4","lower": "4da9d3313d55edf9e34b87eef7bc3696","count": 1144,"preSum": 22425 },{ "ndv": 297,"upper": "551a06c68d3a9bb87456c05c97d467af6daa215a60d785b5fdc549e04aaca3c877ce53236bc762d96f09","lower": "51a409db586ec283c1fc2132165ac08fb45","count": 1164,"preSum": 23569 },{ "ndv": 348,"upper": "58cbf97af20e30bc9d364928e1277d20437cecc31581e9889103826d6267","lower": "551de0f7595d913b67db679d834eea6abe1adbd3dba6e54a79eac7cbfa6b6295fa98bd8c89e58b81074fa267b633f76ad5e4c2788a61d1c3615daba6cff41f62","count": 1144,"preSum": 24733 },{ "ndv": 409,"upper": "5d8640d86728c786910ba253a149dd6aca1b6ecd3cd474e5ce7b5a73535d5aaa8","lower": "58ccca4da871e16053350dc6133b61a2f0e3347919d530830d6a304a28ef227228e6499a369b277c022a4fea645a4ffca685eb74a46de26f804bfaff856af6da","count": 1144,"preSum": 25877 },{ "ndv": 250,"upper": "600517214987915eb4b511d","lower": "5d89b00c7ae9609a56f860145a17288025d78e89f9d25d82fb9f52d004b7de35f7a4320","count": 1149,"preSum": 27021 },{ "ndv": 426,"upper": "64964da26aa4e7a9af119b294728d91b4de9a2325df7c48d84b5b3967cffa705b3a0eabe9e77238d531f32755f38e508d4a259664ad61a3e8920e091cf9556e5","lower": "600555308b687a517a222010da541b87bc91e20a575e2","count": 1144,"preSum": 28170 },{ "ndv": 429,"upper": "6942ff1081136f3da0b7476533b69326ca477b5a73247af40f888805800ce02eeb1f961226f894ab5f73a83c8f58540f05d7a0ea4c9d2f72bcafe13b0d09749","lower": "649b84b63259e926e711a3fc8833fb57de343facf70438e3ad2262f29e95d4a0221e4d0cbb758557c4e773bc91f8e13fecf6193eca7924fd01635801f5ede29f","count": 1157,"preSum": 29314 },{ "ndv": 380,"upper": "6cddfd7e5019351d73d33114f9ab41d5998d5239d08d6673030de3aab26e013e0051223e70e8c3ad32f0c5d47f28ec8a1241d4efcf9","lower": "6943ec3","count": 1145,"preSum": 30471 },{ "ndv": 376,"upper": "70fbc0f930b1fd11fc8c5dd41d03c6a00e394aaded595d2d814cd7fcb906dcf74ddf86204a23aadcebc88a0b9df27acef465a4e9e8501c9b0511d5378740821b","lower": "6cde863eb5663a369a80e89d284b25dbc41087ec66c990fe6ad024f8362a58354a47bef569f97c59d793268ac9bf88517d7ec1c1153cf05d53557fca79642d62","count": 1176,"preSum": 31616 },{ "ndv": 511,"upper": "75ef4b54dc599d666e7a3de4041871b3956eebd9ed09a18fed3f3f65","lower": "70fc35302222e96999a91ed3e97ac107b23108f6c3432f907b3fd7452bf39906197c75253a451f24cf9fd0","count": 1145,"preSum": 32792 },{ "ndv": 238,"upper": "78a7366861ab7ce92b374eb5360e91c26cbbdd07cefd0e5d3214ea9846e42fbea5cecc0a5047718128b3d6c602f","lower": "75f563470684ec8915306216a68b20018b7f6c62eeb00e6719d0d3012a7f24c1185b70c17ae6d87ec0da05d92c5cdfe5af6562771","count": 1293,"preSum": 33937 },{ "ndv": 305,"upper": "7bce56eca9c26cb210a25dffcf43059de09f3455e2cccd5df1485d7511f91179336950b328e85fd9a71b01a97859e615aeb2e42dd54848c3f8c344bcb5832cf1","lower": "78adc2ff26e81b837ce112db9a0d2f93f60f6854c4f3237d3a748547b5cfe69c445d","count": 1144,"preSum": 35230 },{ "ndv": 420,"upper": "80363a49a4cc7341902df6ce6fbfd74d954bd5","lower": "7bcea9d50d31c8498d8cf8","count": 1144,"preSum": 36374 },{ "ndv": 570,"upper": "865a67b","lower": "803726da7566e2b0997a69ea4fef74b1defc4fdd4626c05a489f20fd","count": 1155,"preSum": 37518 },{ "ndv": 472,"upper": "8bad08a020fa6c69a6d854adc3a9a69adeb827c241c58e8cd0ed5b764acafe8ebb4994f7a154c759c22121","lower": "865e3e30150c71ef5c147e2f791824baaecdc6c8348ad3016d988480dc75860d2","count": 1159,"preSum": 38673 },{ "ndv": 396,"upper": "8fc094b25226d","lower": "8baea5bc5b18b57f390565b1e4498111518376b44835305301e6a63c15a10da0186006de2553b825a511fedc880a48e7e1ae465f31a7441dc74","count": 1193,"preSum": 39832 },{ "ndv": 487,"upper": "94e6805e4cb50b0de6452fdb1f13903ff5f43da62c386918a03e9b4088f6038990496b92e277f28","lower": "8fc221e7d48e26840ad9176d73748fc070afbb17bc7d997d85013d3ffbc9eecc7842f33c0f28842299e7a3e8986504d421c73a9f24c40bd1e31a5e527b1f8d46","count": 1147,"preSum": 41025 },{ "ndv": 413,"upper": "9915b87a2041bf6a270e45975bfd1a09a462398feb3a5e67d1846ef1e7b25a5a3d6017d194f1eab439fa11f4d45791efd25bf3907e746c6a621c40434","lower": "94eaa84fb21c92eda965a7ff6f09eaec008894f9b63690334eca1c194b46be91207585f40e44a131f599162a09dbebe47a1509f9512f375246184286f8b577c5","count": 1150,"preSum": 42172 },{ "ndv": 445,"upper": "9df4d4a6cf35bd72af2b434aa0074c1","lower": "99188be58a271d35dfd9f40cd8dd7f409b1","count": 1187,"preSum": 43322 },{ "ndv": 406,"upper": "a2593a8baa44859a28391d02f76cc5cb45cfd2c2be7fb4b3a51f165b26b38e6c14ad81976bd9f4484","lower": "9df89145d45c9621914c9de1dc953e3ffbe0d6da6292cf4199d15b2635339a2e785fbd00b76a9","count": 1144,"preSum": 44509 },{ "ndv": 381,"upper": "a63b8c7670964cd0cfff43dc7a9e8f9c579fa0e3c37623a740b66cfd4a9071585e1266bd497","lower": "a25a0736f3a0ccb5d4b50d82a4f394629e1fd392ef4521262431e43082f46befeb8d54faa5d120800b496b24c667ab0487030b8963fa464","count": 1144,"preSum": 45653 },{ "ndv": 133,"upper": "a78433bb821ad674545f2bc3e330c9","lower": "a63ea9052d2cbba45d76706520b6953","count": 1148,"preSum": 46797 },{ "ndv": 275,"upper": "aa87e20d809ea68cec8432c2ad232f96d0131083ec9889a4facbcceba06e2ee999dc5c73c9b0","lower": "a7880d21936c3741daf312fc59a9802ba4b69bac0b585a2e992534319b2adc08b6aaff5acf5a2d904b6c0df7d60780dcf7986b085208042e97ce70104d61ccc1","count": 1145,"preSum": 47945 },{ "ndv": 326,"upper": "ad81e341f78942b","lower": "aa8802ae6bb9b04944e3264fd8684e5645bd7d1a646a47452fe71b4ed11ea5e8ed66573","count": 1228,"preSum": 49090 },{ "ndv": 327,"upper": "b0d576543155bf9f29a26a879c787ecd9f373ad5f7c2f1f7620430d6b2ac81e207dd76788de62d2","lower": "ad84002312b9d0734e48f7f04cf2a3bfc3db0c25d0cec1f0114906ad","count": 1145,"preSum": 50318 },{ "ndv": 286,"upper": "b3fde7a2d12db2df9ec2697488f2f358bd2289618feb27461ee1710072eaccda","lower": "b0dfac283ebe21769c6f9e9142b43837fbb95333c3a964809aea45b1898a8adf025e649f616f2f2cf2d0a865c79c1a364ec0b47c1638a767e5d1fe","count": 1148,"preSum": 51463 },{ "ndv": 377,"upper": "b842dbb21a8c84a7f74ab68d92cbc4e956115b9dcf6b72d9e0ec63b25c7acdb12eddba1360fb37feba526f32d00679164184c4df88efee76c875c39f6341c9d8","lower": "b3ff048dfe3df932fa34248fc748cd97627a64c8","count": 1144,"preSum": 52611 },{ "ndv": 474,"upper": "bd12f5300e","lower": "b8441c2092789be9997850426d03ba7b2a5a05ebdbc5f99318413d860a80","count": 1151,"preSum": 53755 },{ "ndv": 463,"upper": "c2081b11e74107819a055179b7b8dbae75fd2c76da570b5644e5d191bbdfae9d18b4beaf025e0ef11d83d4bb8d06263322216d3662cff64e6eb886b2cce9cc4b","lower": "bd1352ca904f61edad8ad5577ecef08c5dd97e9ee79e662b789a37d741e80479435026edc36b3620bc1aa27f989f049acfd9ad6a6fdb57a06b7651295623b873","count": 1173,"preSum": 54906 },{ "ndv": 379,"upper": "c62b9455f9e6c7b9f68fe953575f5f9d35cfd3b591451fe5da7b282e0f493a6a88a818ff42d02d270d55ba476e03d3b5dc6da6245a968a8e839cd8509f985aa7","lower": "c20d91b52e16834d284f2e726f08b20234545d4","count": 1144,"preSum": 56079 },{ "ndv": 395,"upper": "ca4c35f99bfd3e05e12934db4","lower": "c62cbe63bfe40e26eb92b04bd60a0a64b8e4088128ad1458dd0041bfde2d9fb8c725b8b7366696a6ee14c38752ecd27b377b2ef80cd2c4d055869f4e5edb9ced","count": 1144,"preSum": 57223 },{ "ndv": 464,"upper": "cf7891b44f7dd6d7095ed9","lower": "ca4d8032af9b36de8060d272645e0d7d7fcb6f57c52b2ebf82a8ef","count": 1146,"preSum": 58367 },{ "ndv": 458,"upper": "d454a6d07f437a9e64e6","lower": "cf790731e1f5d6d4185db7e3f593b92ca6e8e0aec77384db9792efab2f332e2093ce1cd3ad40c64ea07aa436be557b49418fef4b7e8170044bb4925e7496b2fe","count": 1146,"preSum": 59513 },{ "ndv": 394,"upper": "d878e482d6334a6c662d69f11f134ee3eeff2170ce21e80ff0e96e135d1f803e452b73c952d4435039769efe467cdcda83ad27ebe7ebccf314d1ecf7e7f96e13","lower": "d456143","count": 1154,"preSum": 60659 },{ "ndv": 360,"upper": "dc0e7da4200ca9a3ec8a6e16f42","lower": "d87929e38417eae8835340af4c0fbaf412e056570c487e016afe69656e885787b92c06d8cc9b384b2155a7bcc86e5ea0281b0aa8b9ad9399dcf0687ce2d2d780","count": 1144,"preSum": 61813 },{ "ndv": 421,"upper": "e09e86ce83605d38880c6491a69f2755d7ca5715675f0403aefb2a302fc28010704c296f","lower": "dc1623326522a343","count": 1144,"preSum": 62957 },{ "ndv": 355,"upper": "e4504b2a1dee2aea0d09c559dcf1caeb50fe5b0c59c8c0acc8e24208ae89ea2efc618866d8d747072389f79753af97969da70a701b6e1062e8cefafe9de98711","lower": "e09f02af00ab5e7025e43d06c6f4c128e01d32b4c806dcf1fc95a749c9d81b794bf0b295bb7c5b538431d0880ec374e0af5fb7ad2807457709d648b5f1554031","count": 1144,"preSum": 64101 },{ "ndv": 432,"upper": "e8baa59dfd4044601121ce6ad0160649f4f79a11a9e582f5108a6f0f3f58a1a5e07aff705a585f2b05a89984333d70a917ad942c618adbc9559cec9d817eb937","lower": "e451bdf0d7fd0d48d1c5ab7f16d08582992286531cf1b9a3e1f3d10439e","count": 1145,"preSum": 65245 },{ "ndv": 442,"upper": "edc5fb707b60b40c546cc3eb09dd4323ab4ea43c520dc3dce14bb02364ab1473aca79929e3963abfabb3c41e2fee43f005f429d76cb404ac90b163cc9fcaaf9a","lower": "e8bb7926864e4aef02b247e52f55b47979941b10cd4b709c0f5a9fd2270f6514e4d9d7c67acb8442c7f2e56ded318952ca0cd83d7266e8416f49951ad17a8789","count": 1144,"preSum": 66390 },{ "ndv": 396,"upper": "f1b6b62ace4cc416c97c45cf3831e1a47249f9753fb1c15fa694cd10237a597d3587ca099f8707ef5bf7cdda6cb843c45ded20d2963","lower": "edc723027c6aba7bef4dbc91bbb3602e5bca2848dbbdba121a36dbafc224b2aea18b874a86a23f790004a271c902b25dbe5942bbcdcde5e9c6daa35f33c324b9","count": 1145,"preSum": 67534 },{ "ndv": 425,"upper": "f6142003c59c5ebe8a978edee6529242f50894519c338ed2e4a199d3a14c501b0ba463d08dc27d0f96d14768985bd89c6ed5164be5caecddec46efa7109cd63c","lower": "f1bb5c7eeff9b184f42ddeada669","count": 1144,"preSum": 68679 },{ "ndv": 368,"upper": "fa0d4de16b01a9993262227728e9b287384cca5210f17f529d8dbabc8beefc55e1b644c85335e77b5030a2339559f13b0a17199c18f0689de84bf4865e3c0e81","lower": "f620ee113e5e40e36aed2282209513d0bfb9ceb9473209","count": 1146,"preSum": 69823 },{ "ndv": 370,"upper": "fded7fa41eb780622315ce0a7","lower": "fa0d702adecc9bf","count": 1599,"preSum": 70969 },{ "ndv": 181,"upper": "fffc62ed702e63782b0ac3ebdbe63aa14e2d9b7c68a","lower": "fded80d4d500ef1ba8aec25c271debd038834fb213eece768b4adc402d914dc16fee1fae59807380e22b3a80c92ffba671d817ec4b7d919253930b2d0","count": 621,"preSum": 72568 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_text_medium.null_count:
+    0
+  cest_full_table_big.c_text_medium.sample_rate:
+    0.010943651
+  cest_full_table_big.c_text_tiny.TOPN:
+    { "countArr": [ 2129,747,1152,2604,1061,4041,663,8212,877,1720,929,1401,654,622 ],"valueArr": [ "272901f7b4866c38cfdad0ee58e710055bd6f342c756efa3ea2c5414d1c8d334c9cd42fff815d8c800a1a7bc096cf77897e8375e32b12cb22a33cd62d840c68d","2aa4d5c39254825a73c8285fdfd0cb082cdbc465bff473642e153dbf9818be56f217072a5c7867fbcecbf15e47b88de9d80f468b8f6a85f955d20f808c77d42a","4a9e0d094ccec5f3ab0ee0ccdae5d42db6ff517ba578c8d9487aece02602c334733224fac97026bf3367678500458693ccb86eb285b","5ee951d1927147b17bb57cf07545f785341b9aeb920e85ca1c","884e206f2e3ec07a388151bddf4d2362db2a90a8ece685e96e1c2befd992ca6d4320460c618cf5ec78a7932c7cc4ae2a50962f5e8b820853f2773ec79f9aa865","8f4b82ccc477a1d4817a0713716a1a9e0abdb99fb556d066bd4663a261367328af7c4f078b4283c7d3bde3398bbeb466cd176ee7150e33107dca10c8322e0e","9081f4c0e8c85ee47ead80cdbc5f081e9cc6428718903b5f35107125e08896ba5f5172f9b5428ba371a6137715b9433d6b85cbb56c7f274ce7f86b6f66a5e313","ae093e295bf106c3d99ebb56b5c6978fb3e","b200919aa862b99712074cde83b3c18e25c4fd15","bc10f23cffb6b25587d94e646accc5b988bcb651c161925d2c5f8aa0bac12f1f290ab10f38fb5c727ad5da443c2daad1fe27901a5b9f79cd93a","c292b6a83f3518061f48c1dad1fa4d2c3e19eefcf6d90a0b08b456ab655a4c1e28257a3691b286cd81108acb9981558e411ab13520eaae125e4160f7d409d7f9","ce073c56e6291d3fcb1050e6a705e143712f1272439d96200d18b826e","cfe9b21e9d0bee82cf485c1644e7fc722764462d88e885b27cea8dead24cf1279a75c78df843678c4244278a8c7172d240d27e597f4975610eaf6da3176269ef","dd946928cf4b699b145e020fde6ca56b98c6bcb81e47f3dc93c76a5e2c6b9487a" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_text_tiny.cardinality:
+    243039
+  cest_full_table_big.c_text_tiny.histogram:
+    { "buckets": [ { "ndv": 166,"upper": "01dde7823023499a10f85591dc6af7747d89c8aa5b5","lower": "0","count": 1144,"preSum": 0 },{ "ndv": 571,"upper": "07cdf3cec6575290c3605446ed","lower": "01de5a4451a0e2648f4124d2e6c725a8302e48c132bc53022ca7462861f814dabb4f87ffc3a1e9357194adf600e97ac3e9816416b348fbb7d993843ca4861a9c","count": 1144,"preSum": 1144 },{ "ndv": 385,"upper": "0b9a1d61777836df3728cafa83c438b50f788c8c877bf0","lower": "07ceb4fa2aa3d114bf15a103d51f2a325543269a30de9b082851","count": 1145,"preSum": 2288 },{ "ndv": 511,"upper": "1113f79e0f5556eb128234780d9dc43dac44ff6f02d36cfe453ce7740f7bbacc9cbd9c8fff34e16bcf2f0d4d2f8b14990aba3f5d557e19d21dac182b7eaed214","lower": "0b9c4e79f1ff05e2dcf2cc92ae6d00c41dae43730263ca5658c0d3a3d1bf1c3a517bde9064e517d7eb344db3ca6a078a2ae3061c3f186809b3350dd9770f816c","count": 1190,"preSum": 3433 },{ "ndv": 190,"upper": "1311e1fd42260161612493575ce96bb850c6d5bcff96788f2e684e4b85bdfa805b539b0f6dd915c4a950ec4","lower": "111522044fa68d83ef2dc4c163eef6bbff2f6ee58fd5e6b0779a3558a95cc073723bbe5a27ebb52868941fa6a6fbafbce2b4dab2ff54b80a7b0a868b67d2e804","count": 1449,"preSum": 4623 },{ "ndv": 495,"upper": "17f78","lower": "1312df8d2b0b162234bf63e35e04457ca5c44cb3a93f0fdb9d4e676bedbd18dd42ac0efbcdfc822acfe3","count": 1293,"preSum": 6072 },{ "ndv": 330,"upper": "1b2b044fa17eb9b2ff7798fdbdacfd9375b20ca0f022e75c6da410673d96","lower": "17f7c2386996a38ce235cba0f1b009829aa9816a794437c4eeab3afb5094145d083","count": 1145,"preSum": 7365 },{ "ndv": 508,"upper": "205bb8f17e5224cfe3f2a340724491356c2e44adb8225890e19d820326c8a1392530aec1f4d07f994db22c6dabf1d230c81133038161de925bde002ffa9abbbe","lower": "1b2ccd0ca37e1b3902f4794b5fb5ba11","count": 1166,"preSum": 8510 },{ "ndv": 395,"upper": "2489cf31553d6e40d04c8f6","lower": "20609b96de0278b56462c3e104ef76f789e074927d7ee81d207b1fafcbe3f8266f4a268476909d8e2e7a","count": 1204,"preSum": 9676 },{ "ndv": 431,"upper": "28b02ac065e2cc1bbe517930e1d07f04e5cd8ec8c01488f9","lower": "248c920cebc921cb395d00fd3e2b567572e36fc773","count": 1144,"preSum": 10880 },{ "ndv": 369,"upper": "2cb456ee2d29c4703cfe26e290adffa03be1df47c17bc21332782fd9a067867edb1cc436cfc019762b0ab2732cfc735487969d8dd3ddf25e","lower": "28b0526659a25aefb71d8d34c6c146378bb40abd36f74d3694ebb61939c5f0bf8d5d828e86987619287886c4f901b89b6a57a45fde4fed074cb5c749e355d446","count": 1145,"preSum": 12024 },{ "ndv": 401,"upper": "310a1471df0f7661b08941c102ecf376","lower": "2cb527aa5bfd4468f64fa2d2ac61ecaf45615ca1965c91bd9c6be1cb2255377ced816533f80c91bafb93c0dfcc71de9c164","count": 1202,"preSum": 13169 },{ "ndv": 461,"upper": "35c6c1279085e58dc930071b7bdd15114913135ea39ad2ac6d1ef39cd07d","lower": "310b22f9931e4f311fe42fca59b4f23ed1e6dae708a59af169e491dba8ac7e98eb60070b40d253c3d8c0b5e9573b08f009c02ad44124d3609f9e400105b155","count": 1146,"preSum": 14371 },{ "ndv": 384,"upper": "393c28a88a013c7c969d008ea2972ec2a0d1ffd23cb361656617ae133e1357a14411438fc5a447e0bd9e0427cadea0dcf6af6a9bfc8abf0ec361fd91d66d5382","lower": "35c9f453764aaa291bcc895f7e258eb13eb04da91c0101c90365e41fbfb22ee953916a708d67c3dbbd287c3c0072d31d1fab8d9f3e97fea5d91f952e3319df0f","count": 1144,"preSum": 15517 },{ "ndv": 373,"upper": "3d307f1902b9f2d8bcd78b556f3b6f62208153308d7bf810cc471cb9fc47dabb68fbbd2f1a8e95a6fb5183389132f0e0dcf8f52e3a1c9bb3","lower": "3942568ee95b7b3f8573f806857903cd4dc87f88c3a9982797b2f2f578bd37e19dc8d8bd652efe5c713bfbab387e24e9c065","count": 1144,"preSum": 16661 },{ "ndv": 381,"upper": "410e26cac9e7f8d25b7689111f0a62a21eb4d63ea6169f95e7c167c5ca784b190127","lower": "3d323107538c7e2059be414e5cf6","count": 1144,"preSum": 17805 },{ "ndv": 218,"upper": "435a8cc58fc6c26aa437323744258f622fe49f4a06ef984d93be","lower": "4111485b903225eb7ad50fa9f854b7dbdfa9d051922c03b99fbddbd6afd7d34dc0d3189","count": 1164,"preSum": 18949 },{ "ndv": 423,"upper": "4771f0477e5fdc9a9cb582cac0a78809adc7504e6671ab16171db96f7667f5ffef8746e6f7d10100afdd78132ab081f0c585061ff62cd8d9ecfeea1fdbd01f26","lower": "435aa344d995f0d25513e501b98dbe5cf979c29e00ba08173ffda95a3e9a50c446d28b344049ccdbcb102c25cccd","count": 1164,"preSum": 20113 },{ "ndv": 581,"upper": "4da801e50c2431beab882819538ac3ba91868f642acbff073b68daa20b0f9c73b91a5d14b6b31bc507bb538a799c01b3507c41c02debda78f0f225f8eab84083","lower": "47737e5333b789dfe19c9e5ef8f417d87f1efbbdf29b539b5e88501f7e78b240080155e1cf7aaaccb5fd95740b3154566a1926d159c42f2","count": 1148,"preSum": 21277 },{ "ndv": 370,"upper": "519bef86b1ccf9a9f129a7b279e6adea1e505aef2cab78ff299182674ee5a488c7ffce8626a4","lower": "4da9d3313d55edf9e34b87eef7bc3696","count": 1144,"preSum": 22425 },{ "ndv": 297,"upper": "551a06c68d3a9bb87456c05c97d467af6daa215a60d785b5fdc549e04aaca3c877ce53236bc762d96f09","lower": "51a409db586ec283c1fc2132165ac08fb45","count": 1164,"preSum": 23569 },{ "ndv": 348,"upper": "58cbf97af20e30bc9d364928e1277d20437cecc31581e9889103826d6267","lower": "551de0f7595d913b67db679d834eea6abe1adbd3dba6e54a79eac7cbfa6b6295fa98bd8c89e58b81074fa267b633f76ad5e4c2788a61d1c3615daba6cff41f62","count": 1144,"preSum": 24733 },{ "ndv": 409,"upper": "5d8640d86728c786910ba253a149dd6aca1b6ecd3cd474e5ce7b5a73535d5aaa8","lower": "58ccca4da871e16053350dc6133b61a2f0e3347919d530830d6a304a28ef227228e6499a369b277c022a4fea645a4ffca685eb74a46de26f804bfaff856af6da","count": 1144,"preSum": 25877 },{ "ndv": 250,"upper": "600517214987915eb4b511d","lower": "5d89b00c7ae9609a56f860145a17288025d78e89f9d25d82fb9f52d004b7de35f7a4320","count": 1149,"preSum": 27021 },{ "ndv": 426,"upper": "64964da26aa4e7a9af119b294728d91b4de9a2325df7c48d84b5b3967cffa705b3a0eabe9e77238d531f32755f38e508d4a259664ad61a3e8920e091cf9556e5","lower": "600555308b687a517a222010da541b87bc91e20a575e2","count": 1144,"preSum": 28170 },{ "ndv": 429,"upper": "6942ff1081136f3da0b7476533b69326ca477b5a73247af40f888805800ce02eeb1f961226f894ab5f73a83c8f58540f05d7a0ea4c9d2f72bcafe13b0d09749","lower": "649b84b63259e926e711a3fc8833fb57de343facf70438e3ad2262f29e95d4a0221e4d0cbb758557c4e773bc91f8e13fecf6193eca7924fd01635801f5ede29f","count": 1157,"preSum": 29314 },{ "ndv": 380,"upper": "6cddfd7e5019351d73d33114f9ab41d5998d5239d08d6673030de3aab26e013e0051223e70e8c3ad32f0c5d47f28ec8a1241d4efcf9","lower": "6943ec3","count": 1145,"preSum": 30471 },{ "ndv": 376,"upper": "70fbc0f930b1fd11fc8c5dd41d03c6a00e394aaded595d2d814cd7fcb906dcf74ddf86204a23aadcebc88a0b9df27acef465a4e9e8501c9b0511d5378740821b","lower": "6cde863eb5663a369a80e89d284b25dbc41087ec66c990fe6ad024f8362a58354a47bef569f97c59d793268ac9bf88517d7ec1c1153cf05d53557fca79642d62","count": 1176,"preSum": 31616 },{ "ndv": 511,"upper": "75ef4b54dc599d666e7a3de4041871b3956eebd9ed09a18fed3f3f65","lower": "70fc35302222e96999a91ed3e97ac107b23108f6c3432f907b3fd7452bf39906197c75253a451f24cf9fd0","count": 1145,"preSum": 32792 },{ "ndv": 238,"upper": "78a7366861ab7ce92b374eb5360e91c26cbbdd07cefd0e5d3214ea9846e42fbea5cecc0a5047718128b3d6c602f","lower": "75f563470684ec8915306216a68b20018b7f6c62eeb00e6719d0d3012a7f24c1185b70c17ae6d87ec0da05d92c5cdfe5af6562771","count": 1293,"preSum": 33937 },{ "ndv": 305,"upper": "7bce56eca9c26cb210a25dffcf43059de09f3455e2cccd5df1485d7511f91179336950b328e85fd9a71b01a97859e615aeb2e42dd54848c3f8c344bcb5832cf1","lower": "78adc2ff26e81b837ce112db9a0d2f93f60f6854c4f3237d3a748547b5cfe69c445d","count": 1144,"preSum": 35230 },{ "ndv": 420,"upper": "80363a49a4cc7341902df6ce6fbfd74d954bd5","lower": "7bcea9d50d31c8498d8cf8","count": 1144,"preSum": 36374 },{ "ndv": 570,"upper": "865a67b","lower": "803726da7566e2b0997a69ea4fef74b1defc4fdd4626c05a489f20fd","count": 1155,"preSum": 37518 },{ "ndv": 472,"upper": "8bad08a020fa6c69a6d854adc3a9a69adeb827c241c58e8cd0ed5b764acafe8ebb4994f7a154c759c22121","lower": "865e3e30150c71ef5c147e2f791824baaecdc6c8348ad3016d988480dc75860d2","count": 1159,"preSum": 38673 },{ "ndv": 396,"upper": "8fc094b25226d","lower": "8baea5bc5b18b57f390565b1e4498111518376b44835305301e6a63c15a10da0186006de2553b825a511fedc880a48e7e1ae465f31a7441dc74","count": 1193,"preSum": 39832 },{ "ndv": 487,"upper": "94e6805e4cb50b0de6452fdb1f13903ff5f43da62c386918a03e9b4088f6038990496b92e277f28","lower": "8fc221e7d48e26840ad9176d73748fc070afbb17bc7d997d85013d3ffbc9eecc7842f33c0f28842299e7a3e8986504d421c73a9f24c40bd1e31a5e527b1f8d46","count": 1147,"preSum": 41025 },{ "ndv": 413,"upper": "9915b87a2041bf6a270e45975bfd1a09a462398feb3a5e67d1846ef1e7b25a5a3d6017d194f1eab439fa11f4d45791efd25bf3907e746c6a621c40434","lower": "94eaa84fb21c92eda965a7ff6f09eaec008894f9b63690334eca1c194b46be91207585f40e44a131f599162a09dbebe47a1509f9512f375246184286f8b577c5","count": 1150,"preSum": 42172 },{ "ndv": 445,"upper": "9df4d4a6cf35bd72af2b434aa0074c1","lower": "99188be58a271d35dfd9f40cd8dd7f409b1","count": 1187,"preSum": 43322 },{ "ndv": 406,"upper": "a2593a8baa44859a28391d02f76cc5cb45cfd2c2be7fb4b3a51f165b26b38e6c14ad81976bd9f4484","lower": "9df89145d45c9621914c9de1dc953e3ffbe0d6da6292cf4199d15b2635339a2e785fbd00b76a9","count": 1144,"preSum": 44509 },{ "ndv": 381,"upper": "a63b8c7670964cd0cfff43dc7a9e8f9c579fa0e3c37623a740b66cfd4a9071585e1266bd497","lower": "a25a0736f3a0ccb5d4b50d82a4f394629e1fd392ef4521262431e43082f46befeb8d54faa5d120800b496b24c667ab0487030b8963fa464","count": 1144,"preSum": 45653 },{ "ndv": 133,"upper": "a78433bb821ad674545f2bc3e330c9","lower": "a63ea9052d2cbba45d76706520b6953","count": 1148,"preSum": 46797 },{ "ndv": 275,"upper": "aa87e20d809ea68cec8432c2ad232f96d0131083ec9889a4facbcceba06e2ee999dc5c73c9b0","lower": "a7880d21936c3741daf312fc59a9802ba4b69bac0b585a2e992534319b2adc08b6aaff5acf5a2d904b6c0df7d60780dcf7986b085208042e97ce70104d61ccc1","count": 1145,"preSum": 47945 },{ "ndv": 326,"upper": "ad81e341f78942b","lower": "aa8802ae6bb9b04944e3264fd8684e5645bd7d1a646a47452fe71b4ed11ea5e8ed66573","count": 1228,"preSum": 49090 },{ "ndv": 327,"upper": "b0d576543155bf9f29a26a879c787ecd9f373ad5f7c2f1f7620430d6b2ac81e207dd76788de62d2","lower": "ad84002312b9d0734e48f7f04cf2a3bfc3db0c25d0cec1f0114906ad","count": 1145,"preSum": 50318 },{ "ndv": 286,"upper": "b3fde7a2d12db2df9ec2697488f2f358bd2289618feb27461ee1710072eaccda","lower": "b0dfac283ebe21769c6f9e9142b43837fbb95333c3a964809aea45b1898a8adf025e649f616f2f2cf2d0a865c79c1a364ec0b47c1638a767e5d1fe","count": 1148,"preSum": 51463 },{ "ndv": 377,"upper": "b842dbb21a8c84a7f74ab68d92cbc4e956115b9dcf6b72d9e0ec63b25c7acdb12eddba1360fb37feba526f32d00679164184c4df88efee76c875c39f6341c9d8","lower": "b3ff048dfe3df932fa34248fc748cd97627a64c8","count": 1144,"preSum": 52611 },{ "ndv": 474,"upper": "bd12f5300e","lower": "b8441c2092789be9997850426d03ba7b2a5a05ebdbc5f99318413d860a80","count": 1151,"preSum": 53755 },{ "ndv": 463,"upper": "c2081b11e74107819a055179b7b8dbae75fd2c76da570b5644e5d191bbdfae9d18b4beaf025e0ef11d83d4bb8d06263322216d3662cff64e6eb886b2cce9cc4b","lower": "bd1352ca904f61edad8ad5577ecef08c5dd97e9ee79e662b789a37d741e80479435026edc36b3620bc1aa27f989f049acfd9ad6a6fdb57a06b7651295623b873","count": 1173,"preSum": 54906 },{ "ndv": 379,"upper": "c62b9455f9e6c7b9f68fe953575f5f9d35cfd3b591451fe5da7b282e0f493a6a88a818ff42d02d270d55ba476e03d3b5dc6da6245a968a8e839cd8509f985aa7","lower": "c20d91b52e16834d284f2e726f08b20234545d4","count": 1144,"preSum": 56079 },{ "ndv": 395,"upper": "ca4c35f99bfd3e05e12934db4","lower": "c62cbe63bfe40e26eb92b04bd60a0a64b8e4088128ad1458dd0041bfde2d9fb8c725b8b7366696a6ee14c38752ecd27b377b2ef80cd2c4d055869f4e5edb9ced","count": 1144,"preSum": 57223 },{ "ndv": 464,"upper": "cf7891b44f7dd6d7095ed9","lower": "ca4d8032af9b36de8060d272645e0d7d7fcb6f57c52b2ebf82a8ef","count": 1146,"preSum": 58367 },{ "ndv": 458,"upper": "d454a6d07f437a9e64e6","lower": "cf790731e1f5d6d4185db7e3f593b92ca6e8e0aec77384db9792efab2f332e2093ce1cd3ad40c64ea07aa436be557b49418fef4b7e8170044bb4925e7496b2fe","count": 1146,"preSum": 59513 },{ "ndv": 394,"upper": "d878e482d6334a6c662d69f11f134ee3eeff2170ce21e80ff0e96e135d1f803e452b73c952d4435039769efe467cdcda83ad27ebe7ebccf314d1ecf7e7f96e13","lower": "d456143","count": 1154,"preSum": 60659 },{ "ndv": 360,"upper": "dc0e7da4200ca9a3ec8a6e16f42","lower": "d87929e38417eae8835340af4c0fbaf412e056570c487e016afe69656e885787b92c06d8cc9b384b2155a7bcc86e5ea0281b0aa8b9ad9399dcf0687ce2d2d780","count": 1144,"preSum": 61813 },{ "ndv": 421,"upper": "e09e86ce83605d38880c6491a69f2755d7ca5715675f0403aefb2a302fc28010704c296f","lower": "dc1623326522a343","count": 1144,"preSum": 62957 },{ "ndv": 355,"upper": "e4504b2a1dee2aea0d09c559dcf1caeb50fe5b0c59c8c0acc8e24208ae89ea2efc618866d8d747072389f79753af97969da70a701b6e1062e8cefafe9de98711","lower": "e09f02af00ab5e7025e43d06c6f4c128e01d32b4c806dcf1fc95a749c9d81b794bf0b295bb7c5b538431d0880ec374e0af5fb7ad2807457709d648b5f1554031","count": 1144,"preSum": 64101 },{ "ndv": 432,"upper": "e8baa59dfd4044601121ce6ad0160649f4f79a11a9e582f5108a6f0f3f58a1a5e07aff705a585f2b05a89984333d70a917ad942c618adbc9559cec9d817eb937","lower": "e451bdf0d7fd0d48d1c5ab7f16d08582992286531cf1b9a3e1f3d10439e","count": 1145,"preSum": 65245 },{ "ndv": 442,"upper": "edc5fb707b60b40c546cc3eb09dd4323ab4ea43c520dc3dce14bb02364ab1473aca79929e3963abfabb3c41e2fee43f005f429d76cb404ac90b163cc9fcaaf9a","lower": "e8bb7926864e4aef02b247e52f55b47979941b10cd4b709c0f5a9fd2270f6514e4d9d7c67acb8442c7f2e56ded318952ca0cd83d7266e8416f49951ad17a8789","count": 1144,"preSum": 66390 },{ "ndv": 396,"upper": "f1b6b62ace4cc416c97c45cf3831e1a47249f9753fb1c15fa694cd10237a597d3587ca099f8707ef5bf7cdda6cb843c45ded20d2963","lower": "edc723027c6aba7bef4dbc91bbb3602e5bca2848dbbdba121a36dbafc224b2aea18b874a86a23f790004a271c902b25dbe5942bbcdcde5e9c6daa35f33c324b9","count": 1145,"preSum": 67534 },{ "ndv": 425,"upper": "f6142003c59c5ebe8a978edee6529242f50894519c338ed2e4a199d3a14c501b0ba463d08dc27d0f96d14768985bd89c6ed5164be5caecddec46efa7109cd63c","lower": "f1bb5c7eeff9b184f42ddeada669","count": 1144,"preSum": 68679 },{ "ndv": 368,"upper": "fa0d4de16b01a9993262227728e9b287384cca5210f17f529d8dbabc8beefc55e1b644c85335e77b5030a2339559f13b0a17199c18f0689de84bf4865e3c0e81","lower": "f620ee113e5e40e36aed2282209513d0bfb9ceb9473209","count": 1146,"preSum": 69823 },{ "ndv": 370,"upper": "fded7fa41eb780622315ce0a7","lower": "fa0d702adecc9bf","count": 1599,"preSum": 70969 },{ "ndv": 181,"upper": "fffc62ed702e63782b0ac3ebdbe63aa14e2d9b7c68a","lower": "fded80d4d500ef1ba8aec25c271debd038834fb213eece768b4adc402d914dc16fee1fae59807380e22b3a80c92ffba671d817ec4b7d919253930b2d0","count": 621,"preSum": 72568 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_text_tiny.null_count:
+    0
+  cest_full_table_big.c_text_tiny.sample_rate:
+    0.010943651
+  cest_full_table_big.c_time.TOPN:
+    { "countArr": [ 29,31,34,31,78,32,28,40,53,56,39,29,28,33 ],"valueArr": [ 48737812480,170355851264,277763588096,531015663616,535713284096,593544347648,626192809984,766450335744,790508863488,915633340416,1318471073792,1565314252800,1598365368320,1644251054080 ],"type": "Time","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_time.cardinality:
+    206052
+  cest_full_table_big.c_time.histogram:
+    { "buckets": [ { "ndv": 685,"upper": "24746393600","lower": "16777216","count": 1557,"preSum": 0 },{ "ndv": 667,"upper": "47630516224","lower": "24763170816","count": 1560,"preSum": 1557 },{ "ndv": 656,"upper": "76587991040","lower": "47680847872","count": 1555,"preSum": 3117 },{ "ndv": 646,"upper": "99757326336","lower": "76621545472","count": 1555,"preSum": 4672 },{ "ndv": 659,"upper": "125074145280","lower": "99874766848","count": 1555,"preSum": 6227 },{ "ndv": 674,"upper": "153142427648","lower": "125090922496","count": 1555,"preSum": 7782 },{ "ndv": 662,"upper": "177368727552","lower": "153159204864","count": 1563,"preSum": 9337 },{ "ndv": 660,"upper": "206561083392","lower": "177419059200","count": 1555,"preSum": 10900 },{ "ndv": 677,"upper": "231324254208","lower": "206577860608","count": 1558,"preSum": 12455 },{ "ndv": 672,"upper": "255701549056","lower": "231424917504","count": 1556,"preSum": 14013 },{ "ndv": 697,"upper": "285296558080","lower": "255785435136","count": 1556,"preSum": 15569 },{ "ndv": 620,"upper": "307006275584","lower": "285313335296","count": 1555,"preSum": 17125 },{ "ndv": 657,"upper": "331232575488","lower": "307123716096","count": 1555,"preSum": 18680 },{ "ndv": 681,"upper": "361179906048","lower": "331299684352","count": 1556,"preSum": 20235 },{ "ndv": 632,"upper": "383661375488","lower": "361314123776","count": 1556,"preSum": 21791 },{ "ndv": 651,"upper": "406126067712","lower": "383694929920","count": 1557,"preSum": 23347 },{ "ndv": 645,"upper": "434261458944","lower": "406142844928","count": 1557,"preSum": 24904 },{ "ndv": 682,"upper": "459595055104","lower": "434278236160","count": 1555,"preSum": 26461 },{ "ndv": 649,"upper": "488334426112","lower": "459611832320","count": 1558,"preSum": 28016 },{ "ndv": 661,"upper": "513030488064","lower": "488351203328","count": 1555,"preSum": 29574 },{ "ndv": 695,"upper": "538548633600","lower": "513064042496","count": 1555,"preSum": 31129 },{ "ndv": 630,"upper": "567153786880","lower": "538565410816","count": 1555,"preSum": 32684 },{ "ndv": 646,"upper": "591715631104","lower": "567170564096","count": 1557,"preSum": 34239 },{ "ndv": 669,"upper": "620740214784","lower": "591732408320","count": 1555,"preSum": 35796 },{ "ndv": 660,"upper": "644563861504","lower": "620756992000","count": 1555,"preSum": 37351 },{ "ndv": 629,"upper": "667179548672","lower": "644614193152","count": 1555,"preSum": 38906 },{ "ndv": 665,"upper": "694912286720","lower": "667196325888","count": 1557,"preSum": 40461 },{ "ndv": 681,"upper": "719876784128","lower": "694929063936","count": 1555,"preSum": 42018 },{ "ndv": 640,"upper": "743398440960","lower": "719910338560","count": 1556,"preSum": 43573 },{ "ndv": 663,"upper": "772339138560","lower": "743415218176","count": 1555,"preSum": 45129 },{ "ndv": 671,"upper": "797521739776","lower": "772389470208","count": 1555,"preSum": 46684 },{ "ndv": 672,"upper": "825422249984","lower": "797538516992","count": 1555,"preSum": 48239 },{ "ndv": 664,"upper": "849715658752","lower": "825455804416","count": 1555,"preSum": 49794 },{ "ndv": 662,"upper": "873874849792","lower": "849732435968","count": 1555,"preSum": 51349 },{ "ndv": 688,"upper": "903906066432","lower": "873908404224","count": 1555,"preSum": 52904 },{ "ndv": 656,"upper": "928451133440","lower": "903956398080","count": 1555,"preSum": 54459 },{ "ndv": 658,"upper": "952543215616","lower": "928467910656","count": 1555,"preSum": 56014 },{ "ndv": 658,"upper": "980930265088","lower": "952593547264","count": 1559,"preSum": 57569 },{ "ndv": 672,"upper": "1004854575104","lower": "980963819520","count": 1556,"preSum": 59128 },{ "ndv": 662,"upper": "1034114039808","lower": "1004871352320","count": 1555,"preSum": 60684 },{ "ndv": 650,"upper": "1058424225792","lower": "1034214703104","count": 1555,"preSum": 62239 },{ "ndv": 656,"upper": "1081895550976","lower": "1058474557440","count": 1558,"preSum": 63794 },{ "ndv": 635,"upper": "1109628289024","lower": "1081929105408","count": 1559,"preSum": 65352 },{ "ndv": 683,"upper": "1135347761152","lower": "1109645066240","count": 1555,"preSum": 66911 },{ "ndv": 648,"upper": "1159255293952","lower": "1135364538368","count": 1558,"preSum": 68466 },{ "ndv": 621,"upper": "1187625566208","lower": "1159305625600","count": 1555,"preSum": 70024 },{ "ndv": 706,"upper": "1213126934528","lower": "1187642343424","count": 1555,"preSum": 71579 },{ "ndv": 693,"upper": "1242235404288","lower": "1213143711744","count": 1556,"preSum": 73134 },{ "ndv": 637,"upper": "1265371185152","lower": "1242403176448","count": 1557,"preSum": 74690 },{ "ndv": 638,"upper": "1289832366080","lower": "1265387962368","count": 1557,"preSum": 76247 },{ "ndv": 666,"upper": "1316793352192","lower": "1289849143296","count": 1558,"preSum": 77804 },{ "ndv": 695,"upper": "1343838224384","lower": "1316843683840","count": 1556,"preSum": 79362 },{ "ndv": 671,"upper": "1367695425536","lower": "1343888556032","count": 1555,"preSum": 80918 },{ "ndv": 632,"upper": "1395914702848","lower": "1367712202752","count": 1556,"preSum": 82473 },{ "ndv": 668,"upper": "1420023562240","lower": "1395931480064","count": 1558,"preSum": 84029 },{ "ndv": 645,"upper": "1447185874944","lower": "1420057116672","count": 1556,"preSum": 85587 },{ "ndv": 633,"upper": "1470237769728","lower": "1447219429376","count": 1555,"preSum": 87143 },{ "ndv": 642,"upper": "1494413737984","lower": "1470254546944","count": 1555,"preSum": 88698 },{ "ndv": 664,"upper": "1521525719040","lower": "1494430515200","count": 1558,"preSum": 90253 },{ "ndv": 677,"upper": "1545970122752","lower": "1521542496256","count": 1556,"preSum": 91811 },{ "ndv": 673,"upper": "1569860878336","lower": "1546020454400","count": 1556,"preSum": 93367 },{ "ndv": 673,"upper": "1598835130368","lower": "1569911209984","count": 1555,"preSum": 94923 },{ "ndv": 643,"upper": "1621635366912","lower": "1598935793664","count": 1555,"preSum": 96478 },{ "ndv": 622,"upper": "1644871811072","lower": "1621652144128","count": 1427,"preSum": 98033 } ],"maxBucketSize": 64,"type": "Time","sampleRate": 0.90062594 }
+  cest_full_table_big.c_time.null_count:
+    0
+  cest_full_table_big.c_time.sample_rate:
+    0.010943651
+  cest_full_table_big.c_timestamp.TOPN:
+    { "countArr": [ 89,85,125,163,113,119,140,158,82,113,87,209,457,254 ],"valueArr": [ 1849903403040243712,1849931202266398720,1849950766194753536,1850040677442781184,1850054339180101632,1850081569406976000,1850082433316159488,1850190555997274112,1850303237668732928,1850340303152611328,1850377691262353408,1850390337793556480,1850485867848663040,1850625578856611840 ],"type": "Timestamp","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_timestamp.cardinality:
+    439971
+  cest_full_table_big.c_timestamp.histogram:
+    { "buckets": [ { "ndv": 764,"upper": "1849796805206736896","lower": "1849785396146208768","count": 1530,"preSum": 0 },{ "ndv": 835,"upper": "1849809829560844288","lower": "1849796815944155136","count": 1530,"preSum": 1530 },{ "ndv": 806,"upper": "1849821438102470656","lower": "1849809831037239296","count": 1530,"preSum": 3060 },{ "ndv": 845,"upper": "1849834635580669952","lower": "1849821440652607488","count": 1529,"preSum": 4590 },{ "ndv": 790,"upper": "1849846288447700992","lower": "1849834640227958784","count": 1530,"preSum": 6119 },{ "ndv": 825,"upper": "1849861598445830144","lower": "1849846300443410432","count": 1530,"preSum": 7649 },{ "ndv": 807,"upper": "1849873845024980992","lower": "1849861609686564864","count": 1529,"preSum": 9179 },{ "ndv": 772,"upper": "1849885437477257216","lower": "1849873845410856960","count": 1529,"preSum": 10708 },{ "ndv": 849,"upper": "1849898561957789696","lower": "1849885466803830784","count": 1529,"preSum": 12237 },{ "ndv": 873,"upper": "1849911950729805824","lower": "1849898568131805184","count": 1539,"preSum": 13766 },{ "ndv": 786,"upper": "1849933480176123904","lower": "1849911951786770432","count": 1533,"preSum": 15305 },{ "ndv": 838,"upper": "1849946946442100736","lower": "1849933500711436288","count": 1529,"preSum": 16838 },{ "ndv": 798,"upper": "1849959875417735168","lower": "1849946952364457984","count": 1530,"preSum": 18367 },{ "ndv": 796,"upper": "1849972553506881536","lower": "1849959884661981184","count": 1565,"preSum": 19897 },{ "ndv": 797,"upper": "1849984823070818304","lower": "1849972554328965120","count": 1532,"preSum": 21462 },{ "ndv": 791,"upper": "1849998967488643072","lower": "1849984828556967936","count": 1529,"preSum": 22994 },{ "ndv": 758,"upper": "1850010802271027200","lower": "1849998984920170496","count": 1530,"preSum": 24523 },{ "ndv": 830,"upper": "1850023739165507584","lower": "1850010807086088192","count": 1529,"preSum": 26053 },{ "ndv": 853,"upper": "1850036857404915712","lower": "1850023751328989184","count": 1530,"preSum": 27582 },{ "ndv": 815,"upper": "1850049370456588288","lower": "1850036860257042432","count": 1530,"preSum": 29112 },{ "ndv": 813,"upper": "1850061250168356864","lower": "1850049404396896256","count": 1531,"preSum": 30642 },{ "ndv": 752,"upper": "1850078265469829120","lower": "1850061251560865792","count": 1530,"preSum": 32173 },{ "ndv": 848,"upper": "1850091398238306304","lower": "1850078266812006400","count": 1570,"preSum": 33703 },{ "ndv": 844,"upper": "1850104871852703744","lower": "1850091400251572224","count": 1535,"preSum": 35273 },{ "ndv": 779,"upper": "1850116543644434432","lower": "1850104874805493760","count": 1529,"preSum": 36808 },{ "ndv": 797,"upper": "1850129666531131392","lower": "1850116549331910656","count": 1529,"preSum": 38337 },{ "ndv": 815,"upper": "1850144941867532288","lower": "1850129668930273280","count": 1529,"preSum": 39866 },{ "ndv": 854,"upper": "1850157870507622400","lower": "1850144942823833600","count": 1529,"preSum": 41395 },{ "ndv": 827,"upper": "1850170428555788288","lower": "1850157883677736960","count": 1530,"preSum": 42924 },{ "ndv": 798,"upper": "1850182648173953024","lower": "1850170444359925760","count": 1543,"preSum": 44454 },{ "ndv": 864,"upper": "1850195608019664896","lower": "1850182650606649344","count": 1530,"preSum": 45997 },{ "ndv": 870,"upper": "1850213621632598016","lower": "1850195608489426944","count": 1531,"preSum": 47527 },{ "ndv": 812,"upper": "1850227411363299328","lower": "1850213627034861568","count": 1531,"preSum": 49058 },{ "ndv": 779,"upper": "1850239240189771776","lower": "1850227412101496832","count": 1529,"preSum": 50589 },{ "ndv": 715,"upper": "1850250242067267584","lower": "1850239244065308672","count": 1529,"preSum": 52118 },{ "ndv": 843,"upper": "1850263944069906432","lower": "1850250247586971648","count": 1529,"preSum": 53647 },{ "ndv": 756,"upper": "1850275169117929472","lower": "1850263949589610496","count": 1530,"preSum": 55176 },{ "ndv": 774,"upper": "1850289404401156096","lower": "1850275169403142144","count": 1529,"preSum": 56706 },{ "ndv": 866,"upper": "1850302561244938240","lower": "1850289427620823040","count": 1529,"preSum": 58235 },{ "ndv": 778,"upper": "1850314352373006336","lower": "1850302562503229440","count": 1531,"preSum": 59764 },{ "ndv": 793,"upper": "1850326797393068032","lower": "1850314363966062592","count": 1529,"preSum": 61295 },{ "ndv": 849,"upper": "1850340154472923136","lower": "1850326801503485952","count": 1530,"preSum": 62824 },{ "ndv": 761,"upper": "1850354307329687552","lower": "1850340160932151296","count": 1529,"preSum": 64354 },{ "ndv": 828,"upper": "1850366848046989312","lower": "1850354308738973696","count": 1529,"preSum": 65883 },{ "ndv": 880,"upper": "1850380214907961344","lower": "1850366850731343872","count": 1532,"preSum": 67412 },{ "ndv": 807,"upper": "1850392965726339072","lower": "1850380252505702400","count": 1530,"preSum": 68944 },{ "ndv": 789,"upper": "1850405820580233216","lower": "1850392972906987520","count": 1529,"preSum": 70474 },{ "ndv": 810,"upper": "1850421903605366784","lower": "1850405831787413504","count": 1529,"preSum": 72003 },{ "ndv": 832,"upper": "1850434527185338368","lower": "1850421903655698432","count": 1537,"preSum": 73532 },{ "ndv": 780,"upper": "1850446533330206720","lower": "1850434553307463680","count": 1529,"preSum": 75069 },{ "ndv": 773,"upper": "1850459426033500160","lower": "1850446539370004480","count": 1531,"preSum": 76598 },{ "ndv": 841,"upper": "1850472238692696064","lower": "1850459437190348800","count": 1530,"preSum": 78129 },{ "ndv": 823,"upper": "1850484903125188608","lower": "1850472247953719296","count": 1530,"preSum": 79659 },{ "ndv": 853,"upper": "1850499351596498944","lower": "1850484925170450432","count": 1530,"preSum": 81189 },{ "ndv": 815,"upper": "1850512298439868416","lower": "1850499353056116736","count": 1529,"preSum": 82719 },{ "ndv": 800,"upper": "1850524841656975360","lower": "1850512301627539456","count": 1538,"preSum": 84248 },{ "ndv": 822,"upper": "1850538202025164800","lower": "1850524846304264192","count": 1529,"preSum": 85786 },{ "ndv": 834,"upper": "1850551672502222848","lower": "1850538203518337024","count": 1529,"preSum": 87315 },{ "ndv": 810,"upper": "1850568608934002688","lower": "1850551678676238336","count": 1530,"preSum": 88844 },{ "ndv": 794,"upper": "1850581624614289408","lower": "1850568613581291520","count": 1529,"preSum": 90374 },{ "ndv": 792,"upper": "1850592932759863296","lower": "1850581625402818560","count": 1545,"preSum": 91903 },{ "ndv": 840,"upper": "1850606168590778368","lower": "1850592934907346944","count": 1529,"preSum": 93448 },{ "ndv": 808,"upper": "1850618014949441536","lower": "1850606175670763520","count": 1529,"preSum": 94977 },{ "ndv": 601,"upper": "1850627048289075200","lower": "1850618016325173248","count": 1301,"preSum": 96506 } ],"maxBucketSize": 64,"type": "Timestamp","sampleRate": 0.90062594 }
+  cest_full_table_big.c_timestamp.null_count:
+    0
+  cest_full_table_big.c_timestamp.sample_rate:
+    0.010943651
+  cest_full_table_big.c_timestamp_1.TOPN:
+    { "countArr": [ 10,9,9,11,11 ],"valueArr": [ 1849867804321251328,1849915730821120000,1850303237668732928,1850307336611037184,1850377691262353408 ],"type": "Timestamp","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_timestamp_1.cardinality:
+    506425
+  cest_full_table_big.c_timestamp_1.histogram:
+    { "buckets": [ { "ndv": 942,"upper": "1849797248628555776","lower": "1849785393881284608","count": 1562,"preSum": 0 },{ "ndv": 1005,"upper": "1849810337491058688","lower": "1849797256346075136","count": 1562,"preSum": 1562 },{ "ndv": 955,"upper": "1849822103553966080","lower": "1849810337977597952","count": 1562,"preSum": 3124 },{ "ndv": 1004,"upper": "1849835073684111360","lower": "1849822104912920576","count": 1565,"preSum": 4686 },{ "ndv": 960,"upper": "1849847814553600000","lower": "1849835075529605120","count": 1562,"preSum": 6251 },{ "ndv": 963,"upper": "1849862699366744064","lower": "1849847823193866240","count": 1562,"preSum": 7813 },{ "ndv": 973,"upper": "1849874460547481600","lower": "1849862716093628416","count": 1562,"preSum": 9375 },{ "ndv": 993,"upper": "1849887293590994944","lower": "1849874470479593472","count": 1562,"preSum": 10937 },{ "ndv": 977,"upper": "1849900082040668160","lower": "1849887295453265920","count": 1563,"preSum": 12499 },{ "ndv": 978,"upper": "1849912242737250304","lower": "1849900084792131584","count": 1563,"preSum": 14062 },{ "ndv": 965,"upper": "1849933880832819200","lower": "1849912243509002240","count": 1562,"preSum": 15625 },{ "ndv": 948,"upper": "1849946815646924800","lower": "1849933881302581248","count": 1562,"preSum": 17187 },{ "ndv": 979,"upper": "1849959410923732992","lower": "1849946817693745152","count": 1562,"preSum": 18749 },{ "ndv": 968,"upper": "1849972336611033088","lower": "1849959417936609280","count": 1564,"preSum": 20311 },{ "ndv": 1004,"upper": "1849984705462534144","lower": "1849972349093281792","count": 1562,"preSum": 21875 },{ "ndv": 969,"upper": "1849999474093457408","lower": "1849984712055980032","count": 1562,"preSum": 23437 },{ "ndv": 972,"upper": "1850012130120564736","lower": "1849999474747768832","count": 1566,"preSum": 24999 },{ "ndv": 967,"upper": "1850024145945886720","lower": "1850012137653534720","count": 1562,"preSum": 26565 },{ "ndv": 976,"upper": "1850036678526238720","lower": "1850024153445302272","count": 1562,"preSum": 28127 },{ "ndv": 971,"upper": "1850049347354361856","lower": "1850036691411140608","count": 1563,"preSum": 29689 },{ "ndv": 978,"upper": "1850061274461765632","lower": "1850049351817101312","count": 1562,"preSum": 31252 },{ "ndv": 948,"upper": "1850078765162430464","lower": "1850061279880806400","count": 1564,"preSum": 32814 },{ "ndv": 927,"upper": "1850091219812614144","lower": "1850078775463641088","count": 1562,"preSum": 34378 },{ "ndv": 968,"upper": "1850104495355199488","lower": "1850091250263261184","count": 1562,"preSum": 35940 },{ "ndv": 957,"upper": "1850116511952273408","lower": "1850104497234247680","count": 1562,"preSum": 37502 },{ "ndv": 1001,"upper": "1850130883818815488","lower": "1850116525122387968","count": 1562,"preSum": 39064 },{ "ndv": 974,"upper": "1850145198105952256","lower": "1850130904656117760","count": 1562,"preSum": 40626 },{ "ndv": 969,"upper": "1850157654618406912","lower": "1850145205504704512","count": 1563,"preSum": 42188 },{ "ndv": 991,"upper": "1850169421687947264","lower": "1850157657034326016","count": 1562,"preSum": 43751 },{ "ndv": 955,"upper": "1850181920042778624","lower": "1850169432979013632","count": 1562,"preSum": 45313 },{ "ndv": 980,"upper": "1850193663087345664","lower": "1850181924639735808","count": 1562,"preSum": 46875 },{ "ndv": 991,"upper": "1850211000813355008","lower": "1850193667701080064","count": 1562,"preSum": 48437 },{ "ndv": 979,"upper": "1850223906066006016","lower": "1850211003665481728","count": 1562,"preSum": 49999 },{ "ndv": 983,"upper": "1850236483558965248","lower": "1850223912726560768","count": 1562,"preSum": 51561 },{ "ndv": 982,"upper": "1850248556024168448","lower": "1850236489045114880","count": 1562,"preSum": 53123 },{ "ndv": 982,"upper": "1850261132174950400","lower": "1850248557550895104","count": 1563,"preSum": 54685 },{ "ndv": 959,"upper": "1850273896582873088","lower": "1850261148583067648","count": 1564,"preSum": 56248 },{ "ndv": 972,"upper": "1850287953809506304","lower": "1850273906431098880","count": 1562,"preSum": 57812 },{ "ndv": 987,"upper": "1850300715499520000","lower": "1850287959664754688","count": 1562,"preSum": 59374 },{ "ndv": 1000,"upper": "1850313468247277568","lower": "1850300722294292480","count": 1563,"preSum": 60936 },{ "ndv": 975,"upper": "1850325675752292352","lower": "1850313481383837696","count": 1562,"preSum": 62499 },{ "ndv": 975,"upper": "1850338162648285184","lower": "1850325676842811392","count": 1562,"preSum": 64061 },{ "ndv": 968,"upper": "1850352921883967488","lower": "1850338162933497856","count": 1562,"preSum": 65623 },{ "ndv": 957,"upper": "1850364849293361152","lower": "1850352926564810752","count": 1563,"preSum": 67185 },{ "ndv": 959,"upper": "1850377280958758912","lower": "1850364857765855232","count": 1563,"preSum": 68748 },{ "ndv": 987,"upper": "1850390265198542848","lower": "1850377281025867776","count": 1562,"preSum": 70311 },{ "ndv": 963,"upper": "1850402304428081152","lower": "1850390280918794240","count": 1562,"preSum": 71873 },{ "ndv": 980,"upper": "1850419441767022592","lower": "1850402304830734336","count": 1562,"preSum": 73435 },{ "ndv": 973,"upper": "1850431335705870336","lower": "1850419451866906624","count": 1563,"preSum": 74997 },{ "ndv": 956,"upper": "1850443877949898752","lower": "1850431904587710464","count": 1562,"preSum": 76560 },{ "ndv": 966,"upper": "1850456614490865664","lower": "1850443878218334208","count": 1562,"preSum": 78122 },{ "ndv": 967,"upper": "1850469322913218560","lower": "1850456615849820160","count": 1562,"preSum": 79684 },{ "ndv": 968,"upper": "1850481322280091648","lower": "1850469333113765888","count": 1562,"preSum": 81246 },{ "ndv": 972,"upper": "1850496523545083904","lower": "1850481325618757632","count": 1564,"preSum": 82808 },{ "ndv": 977,"upper": "1850509007639281664","lower": "1850496534869704704","count": 1562,"preSum": 84372 },{ "ndv": 984,"upper": "1850521354495852544","lower": "1850509014635380736","count": 1562,"preSum": 85934 },{ "ndv": 956,"upper": "1850534388933066752","lower": "1850521362951569408","count": 1562,"preSum": 87496 },{ "ndv": 971,"upper": "1850547739436253184","lower": "1850534394184335360","count": 1563,"preSum": 89058 },{ "ndv": 991,"upper": "1850565056291405824","lower": "1850547762756583424","count": 1565,"preSum": 90621 },{ "ndv": 970,"upper": "1850578198455123968","lower": "1850565056710836224","count": 1564,"preSum": 92186 },{ "ndv": 973,"upper": "1850590948535304192","lower": "1850578213353291776","count": 1562,"preSum": 93750 },{ "ndv": 969,"upper": "1850602504513912832","lower": "1850590957813104640","count": 1562,"preSum": 95312 },{ "ndv": 986,"upper": "1850615271639744512","lower": "1850602510956363776","count": 1562,"preSum": 96874 },{ "ndv": 941,"upper": "1850627038390517760","lower": "1850615278551957504","count": 1515,"preSum": 98436 } ],"maxBucketSize": 64,"type": "Timestamp","sampleRate": 0.90062594 }
+  cest_full_table_big.c_timestamp_1.null_count:
+    0
+  cest_full_table_big.c_timestamp_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_timestamp_3.TOPN:
+    { "countArr": [ 337,317,473,607,396,437,497,673,296,340,276,902,2272,1283 ],"valueArr": [ 1849903403040243712,1849931202266398720,1849950766194753536,1850040677442781184,1850054339180101632,1850081569406976000,1850082433316159488,1850190555997274112,1850303237668732928,1850340303152611328,1850377691262353408,1850390337793556480,1850485867848663040,1850625578856611840 ],"type": "Timestamp","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_timestamp_3.cardinality:
+    366823
+  cest_full_table_big.c_timestamp_3.histogram:
+    { "buckets": [ { "ndv": 612,"upper": "1849797440090144768","lower": "1849785396146208768","count": 1422,"preSum": 0 },{ "ndv": 620,"upper": "1849810543146172416","lower": "1849797447035912192","count": 1422,"preSum": 1422 },{ "ndv": 589,"upper": "1849821918820040704","lower": "1849810549823504384","count": 1421,"preSum": 2844 },{ "ndv": 632,"upper": "1849835994031849472","lower": "1849821924423630848","count": 1422,"preSum": 4265 },{ "ndv": 599,"upper": "1849847844182163456","lower": "1849835996380659712","count": 1421,"preSum": 5687 },{ "ndv": 662,"upper": "1849863743077351424","lower": "1849847859717865472","count": 1421,"preSum": 7108 },{ "ndv": 533,"upper": "1849874224794042368","lower": "1849863827768737792","count": 1421,"preSum": 8529 },{ "ndv": 445,"upper": "1849883392183631872","lower": "1849874272676216832","count": 1446,"preSum": 9950 },{ "ndv": 665,"upper": "1849896438247456768","lower": "1849883396445044736","count": 1440,"preSum": 11396 },{ "ndv": 733,"upper": "1849911665382916096","lower": "1849896474301693952","count": 1421,"preSum": 12836 },{ "ndv": 546,"upper": "1849931793545822208","lower": "1849911690146086912","count": 1476,"preSum": 14257 },{ "ndv": 660,"upper": "1849945328732602368","lower": "1849931794183356416","count": 1421,"preSum": 15733 },{ "ndv": 640,"upper": "1849957923254435840","lower": "1849945333128232960","count": 1421,"preSum": 17154 },{ "ndv": 622,"upper": "1849970695581204480","lower": "1849957924781162496","count": 1422,"preSum": 18575 },{ "ndv": 500,"upper": "1849981095408304128","lower": "1849970699389632512","count": 1421,"preSum": 19997 },{ "ndv": 595,"upper": "1849992465226924032","lower": "1849981110172254208","count": 1421,"preSum": 21418 },{ "ndv": 565,"upper": "1850005372090187776","lower": "1849992483765747712","count": 1421,"preSum": 22839 },{ "ndv": 590,"upper": "1850017193819897856","lower": "1850005391400763392","count": 1432,"preSum": 24260 },{ "ndv": 674,"upper": "1850030453793226752","lower": "1850017204070776832","count": 1426,"preSum": 25692 },{ "ndv": 558,"upper": "1850041437568106496","lower": "1850030455437393920","count": 1431,"preSum": 27118 },{ "ndv": 679,"upper": "1850055289710051328","lower": "1850041462868148224","count": 1421,"preSum": 28549 },{ "ndv": 616,"upper": "1850071976144535552","lower": "1850055869312532480","count": 1434,"preSum": 29970 },{ "ndv": 627,"upper": "1850085352585297920","lower": "1850071979751636992","count": 1429,"preSum": 31404 },{ "ndv": 623,"upper": "1850098314041622528","lower": "1850085371711324160","count": 1441,"preSum": 32833 },{ "ndv": 662,"upper": "1850111620353622016","lower": "1850098370647949312","count": 1422,"preSum": 34274 },{ "ndv": 645,"upper": "1850124866838069248","lower": "1850111658270130176","count": 1421,"preSum": 35696 },{ "ndv": 564,"upper": "1850138055642447872","lower": "1850124891668348928","count": 1423,"preSum": 37117 },{ "ndv": 720,"upper": "1850152672875773952","lower": "1850138075775107072","count": 1421,"preSum": 38540 },{ "ndv": 671,"upper": "1850166022724648960","lower": "1850152688294035456","count": 1421,"preSum": 39961 },{ "ndv": 627,"upper": "1850178321933926400","lower": "1850166038411345920","count": 1421,"preSum": 41382 },{ "ndv": 630,"upper": "1850191052032442368","lower": "1850178326296002560","count": 1422,"preSum": 42803 },{ "ndv": 700,"upper": "1850209186827206656","lower": "1850191083271618560","count": 1421,"preSum": 44225 },{ "ndv": 666,"upper": "1850223591728087040","lower": "1850209207580622848","count": 1421,"preSum": 45646 },{ "ndv": 665,"upper": "1850236651985436672","lower": "1850223593439363072","count": 1421,"preSum": 47067 },{ "ndv": 597,"upper": "1850248627813875712","lower": "1850236670457151488","count": 1530,"preSum": 48488 },{ "ndv": 535,"upper": "1850259725036290048","lower": "1850248636856795136","count": 1421,"preSum": 50018 },{ "ndv": 653,"upper": "1850272843393138688","lower": "1850259736914558976","count": 1421,"preSum": 51439 },{ "ndv": 510,"upper": "1850285810771820544","lower": "1850272850036916224","count": 1426,"preSum": 52860 },{ "ndv": 722,"upper": "1850300574084366336","lower": "1850285849611075584","count": 1421,"preSum": 54286 },{ "ndv": 578,"upper": "1850311925666152448","lower": "1850300579184640000","count": 1421,"preSum": 55707 },{ "ndv": 610,"upper": "1850324937873555456","lower": "1850311929055150080","count": 1422,"preSum": 57128 },{ "ndv": 689,"upper": "1850338578740019200","lower": "1850324939400282112","count": 1421,"preSum": 58550 },{ "ndv": 619,"upper": "1850353165774356480","lower": "1850338603100536832","count": 1453,"preSum": 59971 },{ "ndv": 647,"upper": "1850365331537657856","lower": "1850353171663159296","count": 1421,"preSum": 61424 },{ "ndv": 714,"upper": "1850379511036641280","lower": "1850365352274296832","count": 1421,"preSum": 62845 },{ "ndv": 638,"upper": "1850392803960422400","lower": "1850379519089704960","count": 1421,"preSum": 64266 },{ "ndv": 627,"upper": "1850406579698925568","lower": "1850392814496514048","count": 1432,"preSum": 65687 },{ "ndv": 680,"upper": "1850423898315685888","lower": "1850406587701657600","count": 1448,"preSum": 67119 },{ "ndv": 678,"upper": "1850437022846550016","lower": "1850423906351972352","count": 1422,"preSum": 68567 },{ "ndv": 555,"upper": "1850447674533216256","lower": "1850437048700239872","count": 1421,"preSum": 69989 },{ "ndv": 601,"upper": "1850459640278548480","lower": "1850447674717765632","count": 1421,"preSum": 71410 },{ "ndv": 676,"upper": "1850472525633421312","lower": "1850459653851316224","count": 1455,"preSum": 72831 },{ "ndv": 646,"upper": "1850485461521268736","lower": "1850472533216722944","count": 1421,"preSum": 74286 },{ "ndv": 721,"upper": "1850502580220723200","lower": "1850485470480302080","count": 1421,"preSum": 75707 },{ "ndv": 654,"upper": "1850515691011047424","lower": "1850502583324508160","count": 1422,"preSum": 77128 },{ "ndv": 603,"upper": "1850527525441110016","lower": "1850515699483541504","count": 1421,"preSum": 78550 },{ "ndv": 698,"upper": "1850542559571476480","lower": "1850527559633076224","count": 1421,"preSum": 79971 },{ "ndv": 671,"upper": "1850560756156727296","lower": "1850542572540264448","count": 1421,"preSum": 81392 },{ "ndv": 517,"upper": "1850571650458714112","lower": "1850560777312796672","count": 1422,"preSum": 82813 },{ "ndv": 582,"upper": "1850583672139284480","lower": "1850571659065425920","count": 1421,"preSum": 84235 },{ "ndv": 654,"upper": "1850595725008699392","lower": "1850583699972685824","count": 1421,"preSum": 85656 },{ "ndv": 684,"upper": "1850609356446367744","lower": "1850595742205345792","count": 1421,"preSum": 87077 },{ "ndv": 636,"upper": "1850622093557760000","lower": "1850609402298499072","count": 1422,"preSum": 88498 },{ "ndv": 255,"upper": "1850627038390517760","lower": "1850622112516014080","count": 975,"preSum": 89920 } ],"maxBucketSize": 64,"type": "Timestamp","sampleRate": 0.90062594 }
+  cest_full_table_big.c_timestamp_3.null_count:
+    0
+  cest_full_table_big.c_timestamp_3.sample_rate:
+    0.010943651
+  cest_full_table_big.c_timestamp_6.TOPN:
+    { "countArr": [ 713,685,1163,1712,860,995,1375,2002,633,859,554,2732,8084,4097 ],"valueArr": [ 1849903403040243712,1849931202266398720,1849950766194753536,1850040677442781184,1850054339180101632,1850081569406976000,1850082433316159488,1850190555997274112,1850303237668732928,1850340303152611328,1850377691262353408,1850390337793556480,1850485867848663040,1850625578856611840 ],"type": "Timestamp","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_timestamp_6.cardinality:
+    244985
+  cest_full_table_big.c_timestamp_6.histogram:
+    { "buckets": [ { "ndv": 382,"upper": "1849796950866526208","lower": "1849785385593339904","count": 1152,"preSum": 0 },{ "ndv": 439,"upper": "1849811990365601792","lower": "1849796967492747264","count": 1157,"preSum": 1152 },{ "ndv": 312,"upper": "1849821743514910720","lower": "1849812000868139008","count": 1150,"preSum": 2309 },{ "ndv": 431,"upper": "1849836801955463168","lower": "1849821746098601984","count": 1266,"preSum": 3459 },{ "ndv": 332,"upper": "1849848106443603968","lower": "1849836855458004992","count": 1275,"preSum": 4725 },{ "ndv": 535,"upper": "1849867257367232512","lower": "1849848111661318144","count": 1169,"preSum": 6000 },{ "ndv": 238,"upper": "1849874316817072128","lower": "1849867259917369344","count": 1180,"preSum": 7169 },{ "ndv": 193,"upper": "1849881078303555584","lower": "1849874336261865472","count": 1150,"preSum": 8349 },{ "ndv": 396,"upper": "1849893412073897984","lower": "1849881084913778688","count": 1151,"preSum": 9499 },{ "ndv": 506,"upper": "1849909682701860864","lower": "1849893418013032448","count": 1150,"preSum": 10650 },{ "ndv": 353,"upper": "1849930912272220160","lower": "1849909722111541248","count": 1228,"preSum": 11800 },{ "ndv": 433,"upper": "1849944846874181632","lower": "1849930938293682176","count": 1167,"preSum": 13028 },{ "ndv": 412,"upper": "1849959285128167424","lower": "1849944997718130688","count": 1161,"preSum": 14195 },{ "ndv": 362,"upper": "1849971093654208512","lower": "1849959291704836096","count": 1324,"preSum": 15356 },{ "ndv": 321,"upper": "1849981625836765184","lower": "1849971115800133632","count": 1150,"preSum": 16680 },{ "ndv": 333,"upper": "1849992531815694336","lower": "1849981678164901888","count": 1150,"preSum": 17830 },{ "ndv": 372,"upper": "1850006183805452288","lower": "1849992557333839872","count": 1199,"preSum": 18980 },{ "ndv": 371,"upper": "1850018928651141120","lower": "1850006189878804480","count": 1150,"preSum": 20179 },{ "ndv": 401,"upper": "1850031714047361024","lower": "1850018944824377344","count": 1209,"preSum": 21329 },{ "ndv": 354,"upper": "1850043178019717120","lower": "1850031759580725248","count": 1157,"preSum": 22538 },{ "ndv": 502,"upper": "1850059046883688448","lower": "1850043220499628032","count": 1152,"preSum": 23695 },{ "ndv": 357,"upper": "1850074329367183360","lower": "1850059053527465984","count": 1150,"preSum": 24847 },{ "ndv": 471,"upper": "1850089951035654144","lower": "1850074329602064384","count": 1150,"preSum": 25997 },{ "ndv": 378,"upper": "1850102621575053312","lower": "1850089952293945344","count": 1153,"preSum": 27147 },{ "ndv": 401,"upper": "1850115981892911104","lower": "1850102694237175808","count": 1172,"preSum": 28300 },{ "ndv": 432,"upper": "1850129963655626752","lower": "1850115989711093760","count": 1150,"preSum": 29472 },{ "ndv": 382,"upper": "1850145169584685056","lower": "1850129985415675904","count": 1150,"preSum": 30622 },{ "ndv": 546,"upper": "1850161903347695616","lower": "1850145174684958720","count": 1185,"preSum": 31772 },{ "ndv": 375,"upper": "1850174954931224576","lower": "1850161974449537024","count": 1150,"preSum": 32957 },{ "ndv": 349,"upper": "1850186479720988672","lower": "1850174963252723712","count": 1154,"preSum": 34107 },{ "ndv": 533,"upper": "1850208454770163712","lower": "1850186509836091392","count": 1150,"preSum": 35261 },{ "ndv": 357,"upper": "1850221306889371648","lower": "1850208466061230080","count": 1151,"preSum": 36411 },{ "ndv": 476,"upper": "1850236869787254784","lower": "1850221430352904192","count": 1165,"preSum": 37562 },{ "ndv": 356,"upper": "1850248579982032896","lower": "1850236914733416448","count": 1151,"preSum": 38727 },{ "ndv": 229,"upper": "1850256488140898304","lower": "1850248591977742336","count": 1244,"preSum": 39878 },{ "ndv": 418,"upper": "1850270210964062208","lower": "1850256518792871936","count": 1150,"preSum": 41122 },{ "ndv": 279,"upper": "1850281282735439872","lower": "1850270222305460224","count": 1183,"preSum": 42272 },{ "ndv": 388,"upper": "1850294318095400960","lower": "1850281291124047872","count": 1183,"preSum": 43455 },{ "ndv": 397,"upper": "1850307336611037184","lower": "1850294322407145472","count": 1338,"preSum": 44638 },{ "ndv": 416,"upper": "1850320206262435840","lower": "1850307352884936704","count": 1155,"preSum": 45976 },{ "ndv": 469,"upper": "1850335705977323520","lower": "1850320209735319552","count": 1158,"preSum": 47131 },{ "ndv": 425,"upper": "1850351755045371904","lower": "1850335728274243584","count": 1158,"preSum": 48289 },{ "ndv": 408,"upper": "1850364849293361152","lower": "1850351766118334464","count": 1150,"preSum": 49447 },{ "ndv": 514,"upper": "1850380355836575744","lower": "1850364851524730880","count": 1151,"preSum": 50597 },{ "ndv": 377,"upper": "1850393242600734720","lower": "1850380371137396736","count": 1150,"preSum": 51748 },{ "ndv": 409,"upper": "1850406622413717504","lower": "1850393264645996544","count": 1170,"preSum": 52898 },{ "ndv": 444,"upper": "1850425620798898176","lower": "1850406644844855296","count": 1152,"preSum": 54068 },{ "ndv": 378,"upper": "1850437878937550848","lower": "1850425663681462272","count": 1166,"preSum": 55220 },{ "ndv": 387,"upper": "1850450291997016064","lower": "1850438492614557696","count": 1312,"preSum": 56386 },{ "ndv": 465,"upper": "1850465908917534720","lower": "1850450330651721728","count": 1159,"preSum": 57698 },{ "ndv": 360,"upper": "1850478174018732032","lower": "1850465913631932416","count": 1150,"preSum": 58857 },{ "ndv": 462,"upper": "1850494951150845952","lower": "1850478194201722880","count": 1150,"preSum": 60007 },{ "ndv": 473,"upper": "1850509532816474112","lower": "1850494960713859072","count": 1150,"preSum": 61157 },{ "ndv": 383,"upper": "1850522052864245760","lower": "1850509551288188928","count": 1185,"preSum": 62307 },{ "ndv": 382,"upper": "1850534461007986688","lower": "1850522061236076544","count": 1151,"preSum": 63492 },{ "ndv": 450,"upper": "1850549553271406592","lower": "1850534532730585088","count": 1157,"preSum": 64643 },{ "ndv": 227,"upper": "1850562175207211008","lower": "1850549618551554048","count": 1249,"preSum": 65800 },{ "ndv": 418,"upper": "1850577441886568448","lower": "1850562223844360192","count": 1465,"preSum": 67049 },{ "ndv": 504,"upper": "1850592932759863296","lower": "1850577513273622528","count": 1498,"preSum": 68514 },{ "ndv": 528,"upper": "1850610186566238208","lower": "1850592936064974848","count": 1151,"preSum": 70012 },{ "ndv": 386,"upper": "1850622628532846592","lower": "1850610197001666560","count": 1539,"preSum": 71163 },{ "ndv": 128,"upper": "1850627017788096512","lower": "1850623220550467584","count": 835,"preSum": 72702 } ],"maxBucketSize": 64,"type": "Timestamp","sampleRate": 0.90062594 }
+  cest_full_table_big.c_timestamp_6.null_count:
+    0
+  cest_full_table_big.c_timestamp_6.sample_rate:
+    0.010943651
+  cest_full_table_big.c_time_1.TOPN:
+    { "countArr": [ 59,83,75,64,215,63,60,85,163,125,122,76,58 ],"valueArr": [ 48737812480,170355851264,277763588096,531015663616,535713284096,626192809984,637718757376,766450335744,790508863488,915633340416,1318471073792,1565314252800,1600814841856 ],"type": "Time","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_time_1.cardinality:
+    212682
+  cest_full_table_big.c_time_1.histogram:
+    { "buckets": [ { "ndv": 675,"upper": "24930942976","lower": "16777216","count": 1546,"preSum": 0 },{ "ndv": 635,"upper": "48570040320","lower": "24947720192","count": 1544,"preSum": 1546 },{ "ndv": 653,"upper": "79456894976","lower": "48586817536","count": 1544,"preSum": 3090 },{ "ndv": 611,"upper": "102710116352","lower": "79473672192","count": 1545,"preSum": 4634 },{ "ndv": 649,"upper": "127993380864","lower": "102743670784","count": 1545,"preSum": 6179 },{ "ndv": 634,"upper": "155977777152","lower": "128010158080","count": 1545,"preSum": 7724 },{ "ndv": 646,"upper": "181076492288","lower": "156011331584","count": 1546,"preSum": 9269 },{ "ndv": 663,"upper": "210872827904","lower": "181093269504","count": 1544,"preSum": 10815 },{ "ndv": 664,"upper": "236474859520","lower": "210889605120","count": 1544,"preSum": 12359 },{ "ndv": 614,"upper": "260315283456","lower": "236491636736","count": 1544,"preSum": 13903 },{ "ndv": 658,"upper": "289759297536","lower": "260348837888","count": 1545,"preSum": 15447 },{ "ndv": 603,"upper": "312660197376","lower": "289792851968","count": 1546,"preSum": 16992 },{ "ndv": 610,"upper": "335863087104","lower": "312693751808","count": 1544,"preSum": 18538 },{ "ndv": 666,"upper": "366145961984","lower": "335879864320","count": 1544,"preSum": 20082 },{ "ndv": 573,"upper": "388140892160","lower": "366179516416","count": 1545,"preSum": 21626 },{ "ndv": 664,"upper": "417383579648","lower": "388157669376","count": 1546,"preSum": 23171 },{ "ndv": 610,"upper": "440368365568","lower": "417467465728","count": 1550,"preSum": 24717 },{ "ndv": 660,"upper": "466440159232","lower": "440401920000","count": 1546,"preSum": 26267 },{ "ndv": 596,"upper": "493820575744","lower": "466490490880","count": 1549,"preSum": 27813 },{ "ndv": 626,"upper": "517275123712","lower": "493837352960","count": 1545,"preSum": 29362 },{ "ndv": 667,"upper": "543850233856","lower": "517308678144","count": 1548,"preSum": 30907 },{ "ndv": 638,"upper": "572153397248","lower": "543900565504","count": 1555,"preSum": 32455 },{ "ndv": 593,"upper": "594953633792","lower": "572186951680","count": 1544,"preSum": 34010 },{ "ndv": 666,"upper": "623139356672","lower": "594987188224","count": 1546,"preSum": 35554 },{ "ndv": 663,"upper": "649009823744","lower": "623172911104","count": 1544,"preSum": 37100 },{ "ndv": 569,"upper": "670685986816","lower": "649043378176","count": 1545,"preSum": 38644 },{ "ndv": 638,"upper": "699291140096","lower": "670736318464","count": 1544,"preSum": 40189 },{ "ndv": 657,"upper": "724490518528","lower": "699307917312","count": 1544,"preSum": 41733 },{ "ndv": 630,"upper": "749371129856","lower": "724540850176","count": 1545,"preSum": 43277 },{ "ndv": 670,"upper": "779368792064","lower": "749387907072","count": 1550,"preSum": 44822 },{ "ndv": 597,"upper": "802672345088","lower": "779385569280","count": 1544,"preSum": 46372 },{ "ndv": 623,"upper": "830438637568","lower": "802689122304","count": 1545,"preSum": 47916 },{ "ndv": 642,"upper": "855252140032","lower": "830455414784","count": 1547,"preSum": 49461 },{ "ndv": 601,"upper": "878320812032","lower": "855285694464","count": 1544,"preSum": 51008 },{ "ndv": 633,"upper": "908234588160","lower": "878337589248","count": 1544,"preSum": 52552 },{ "ndv": 642,"upper": "933115199488","lower": "908251365376","count": 1544,"preSum": 54096 },{ "ndv": 614,"upper": "955781218304","lower": "933131976704","count": 1544,"preSum": 55640 },{ "ndv": 611,"upper": "982524100608","lower": "955797995520","count": 1544,"preSum": 57184 },{ "ndv": 649,"upper": "1006649737216","lower": "982540877824","count": 1545,"preSum": 58728 },{ "ndv": 617,"upper": "1034567024640","lower": "1006683291648","count": 1544,"preSum": 60273 },{ "ndv": 639,"upper": "1060303273984","lower": "1034701242368","count": 1545,"preSum": 61817 },{ "ndv": 623,"upper": "1083724267520","lower": "1060336828416","count": 1546,"preSum": 63362 },{ "ndv": 626,"upper": "1112497192960","lower": "1083741044736","count": 1546,"preSum": 64908 },{ "ndv": 603,"upper": "1136270508032","lower": "1112530747392","count": 1544,"preSum": 66454 },{ "ndv": 610,"upper": "1159959937024","lower": "1136320839680","count": 1545,"preSum": 67998 },{ "ndv": 601,"upper": "1187206135808","lower": "1159976714240","count": 1546,"preSum": 69543 },{ "ndv": 668,"upper": "1213714137088","lower": "1187222913024","count": 1551,"preSum": 71089 },{ "ndv": 651,"upper": "1242621280256","lower": "1213781245952","count": 1547,"preSum": 72640 },{ "ndv": 642,"upper": "1267149570048","lower": "1242671611904","count": 1544,"preSum": 74187 },{ "ndv": 634,"upper": "1292650938368","lower": "1267183124480","count": 1546,"preSum": 75731 },{ "ndv": 637,"upper": "1320299790336","lower": "1292667715584","count": 1544,"preSum": 77277 },{ "ndv": 652,"upper": "1346757459968","lower": "1320333344768","count": 1544,"preSum": 78821 },{ "ndv": 612,"upper": "1369977126912","lower": "1346791014400","count": 1575,"preSum": 80365 },{ "ndv": 584,"upper": "1397105885184","lower": "1374389534720","count": 1546,"preSum": 81940 },{ "ndv": 667,"upper": "1421650952192","lower": "1397122662400","count": 1545,"preSum": 83486 },{ "ndv": 616,"upper": "1449182363648","lower": "1421684506624","count": 1544,"preSum": 85031 },{ "ndv": 609,"upper": "1472938901504","lower": "1449199140864","count": 1546,"preSum": 86575 },{ "ndv": 612,"upper": "1497450414080","lower": "1473073119232","count": 1544,"preSum": 88121 },{ "ndv": 628,"upper": "1524159741952","lower": "1497517522944","count": 1544,"preSum": 89665 },{ "ndv": 624,"upper": "1546993532928","lower": "1524176519168","count": 1547,"preSum": 91209 },{ "ndv": 618,"upper": "1570397749248","lower": "1547043864576","count": 1546,"preSum": 92756 },{ "ndv": 607,"upper": "1599070011392","lower": "1570431303680","count": 1545,"preSum": 94302 },{ "ndv": 640,"upper": "1622524559360","lower": "1599137120256","count": 1544,"preSum": 95847 },{ "ndv": 592,"upper": "1644804702208","lower": "1622591668224","count": 1362,"preSum": 97391 } ],"maxBucketSize": 64,"type": "Time","sampleRate": 0.90062594 }
+  cest_full_table_big.c_time_1.null_count:
+    0
+  cest_full_table_big.c_time_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_time_3.TOPN:
+    { "countArr": [ 148,239,181,171,761,143,194,131,291,449,324,330,216,141 ],"valueArr": [ 48737812480,170355851264,277763588096,531015663616,535713284096,593544347648,626192809984,637718757376,766450335744,790508863488,915633340416,1318471073792,1565314252800,1600814841856 ],"type": "Time","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_time_3.cardinality:
+    221045
+  cest_full_table_big.c_time_3.histogram:
+    { "buckets": [ { "ndv": 616,"upper": "24461180928","lower": "16777216","count": 1508,"preSum": 0 },{ "ndv": 576,"upper": "48419045376","lower": "24477958144","count": 1507,"preSum": 1508 },{ "ndv": 556,"upper": "77460406272","lower": "48486154240","count": 1512,"preSum": 3015 },{ "ndv": 550,"upper": "100394860544","lower": "77477183488","count": 1506,"preSum": 4527 },{ "ndv": 605,"upper": "126332436480","lower": "100411637760","count": 1519,"preSum": 6033 },{ "ndv": 542,"upper": "152219680768","lower": "126349213696","count": 1506,"preSum": 7552 },{ "ndv": 614,"upper": "179063226368","lower": "152236457984","count": 1506,"preSum": 9058 },{ "ndv": 617,"upper": "208641458176","lower": "179080003584","count": 1505,"preSum": 10564 },{ "ndv": 630,"upper": "233689841664","lower": "208725344256","count": 1507,"preSum": 12069 },{ "ndv": 562,"upper": "257614151680","lower": "233706618880","count": 1505,"preSum": 13576 },{ "ndv": 635,"upper": "288098353152","lower": "257698037760","count": 1506,"preSum": 15081 },{ "ndv": 506,"upper": "308834992128","lower": "288131907584","count": 1527,"preSum": 16587 },{ "ndv": 573,"upper": "333648494592","lower": "308851769344","count": 1507,"preSum": 18114 },{ "ndv": 574,"upper": "362152984576","lower": "333665271808","count": 1505,"preSum": 19621 },{ "ndv": 547,"upper": "384315686912","lower": "362169761792","count": 1505,"preSum": 21126 },{ "ndv": 630,"upper": "414044913664","lower": "384399572992","count": 1505,"preSum": 22631 },{ "ndv": 540,"upper": "436878704640","lower": "414078468096","count": 1506,"preSum": 24136 },{ "ndv": 600,"upper": "461792870400","lower": "436912259072","count": 1508,"preSum": 25642 },{ "ndv": 544,"upper": "489290727424","lower": "461809647616","count": 1505,"preSum": 27150 },{ "ndv": 575,"upper": "513852571648","lower": "489307504640","count": 1562,"preSum": 28655 },{ "ndv": 626,"upper": "540645785600","lower": "514003566592","count": 1507,"preSum": 30217 },{ "ndv": 590,"upper": "569989136384","lower": "540696117248","count": 1508,"preSum": 31724 },{ "ndv": 534,"upper": "592017620992","lower": "570005913600","count": 1512,"preSum": 33232 },{ "ndv": 630,"upper": "622636040192","lower": "592034398208","count": 1509,"preSum": 34744 },{ "ndv": 643,"upper": "651408965632","lower": "622669594624","count": 1505,"preSum": 36253 },{ "ndv": 471,"upper": "670635655168","lower": "651425742848","count": 1506,"preSum": 37758 },{ "ndv": 577,"upper": "698485833728","lower": "670652432384","count": 1505,"preSum": 39264 },{ "ndv": 626,"upper": "724121419776","lower": "698519388160","count": 1508,"preSum": 40769 },{ "ndv": 537,"upper": "747592744960","lower": "724138196992","count": 1508,"preSum": 42277 },{ "ndv": 581,"upper": "777238085632","lower": "747659853824","count": 1506,"preSum": 43785 },{ "ndv": 595,"upper": "801766375424","lower": "777254862848","count": 1507,"preSum": 45291 },{ "ndv": 570,"upper": "828760915968","lower": "801816707072","count": 1508,"preSum": 46798 },{ "ndv": 601,"upper": "854329393152","lower": "828794470400","count": 1508,"preSum": 48306 },{ "ndv": 538,"upper": "877012189184","lower": "854346170368","count": 1506,"preSum": 49814 },{ "ndv": 572,"upper": "905751560192","lower": "877028966400","count": 1506,"preSum": 51320 },{ "ndv": 616,"upper": "932158898176","lower": "905768337408","count": 1505,"preSum": 52826 },{ "ndv": 566,"upper": "955764441088","lower": "932226007040","count": 1505,"preSum": 54331 },{ "ndv": 569,"upper": "983128080384","lower": "955781218304","count": 1508,"preSum": 55836 },{ "ndv": 607,"upper": "1008897884160","lower": "983262298112","count": 1505,"preSum": 57344 },{ "ndv": 599,"upper": "1039096872960","lower": "1008981770240","count": 1512,"preSum": 58849 },{ "ndv": 609,"upper": "1063558053888","lower": "1039113650176","count": 1505,"preSum": 60361 },{ "ndv": 586,"upper": "1088505774080","lower": "1063574831104","count": 1505,"preSum": 61866 },{ "ndv": 601,"upper": "1118084005888","lower": "1088522551296","count": 1505,"preSum": 63371 },{ "ndv": 577,"upper": "1142914285568","lower": "1118285332480","count": 1513,"preSum": 64876 },{ "ndv": 546,"upper": "1170512805888","lower": "1142947840000","count": 1506,"preSum": 66389 },{ "ndv": 547,"upper": "1193363374080","lower": "1170529583104","count": 1507,"preSum": 67895 },{ "ndv": 622,"upper": "1219250618368","lower": "1193380151296","count": 1505,"preSum": 69402 },{ "ndv": 619,"upper": "1250691121152","lower": "1219267395584","count": 1507,"preSum": 70907 },{ "ndv": 593,"upper": "1276142157824","lower": "1250758230016","count": 1511,"preSum": 72414 },{ "ndv": 550,"upper": "1299445710848","lower": "1276192489472","count": 1505,"preSum": 73925 },{ "ndv": 608,"upper": "1328772284416","lower": "1299462488064","count": 1507,"preSum": 75430 },{ "ndv": 614,"upper": "1355750047744","lower": "1328872947712","count": 1508,"preSum": 76937 },{ "ndv": 556,"upper": "1383398899712","lower": "1355766824960","count": 1508,"preSum": 78445 },{ "ndv": 525,"upper": "1405360275456","lower": "1383415676928","count": 1508,"preSum": 79953 },{ "ndv": 567,"upper": "1428412170240","lower": "1405393829888","count": 1505,"preSum": 81461 },{ "ndv": 534,"upper": "1453577994240","lower": "1428428947456","count": 1506,"preSum": 82966 },{ "ndv": 590,"upper": "1478743818240","lower": "1453594771456","count": 1505,"preSum": 84472 },{ "ndv": 548,"upper": "1501644718080","lower": "1478794149888","count": 1506,"preSum": 85977 },{ "ndv": 581,"upper": "1529008357376","lower": "1501678272512","count": 1507,"preSum": 87483 },{ "ndv": 536,"upper": "1550365753344","lower": "1529025134592","count": 1505,"preSum": 88990 },{ "ndv": 535,"upper": "1572931108864","lower": "1550399307776","count": 1514,"preSum": 90495 },{ "ndv": 504,"upper": "1599539773440","lower": "1573031772160","count": 1506,"preSum": 92009 },{ "ndv": 594,"upper": "1624168726528","lower": "1599573327872","count": 1506,"preSum": 93515 },{ "ndv": 505,"upper": "1644804702208","lower": "1624219058176","count": 1261,"preSum": 95021 } ],"maxBucketSize": 64,"type": "Time","sampleRate": 0.90062594 }
+  cest_full_table_big.c_time_3.null_count:
+    0
+  cest_full_table_big.c_time_3.sample_rate:
+    0.010943651
+  cest_full_table_big.c_time_6.TOPN:
+    { "countArr": [ 282,413,305,311,1785,228,316,229,511,1018,731,642,384,263 ],"valueArr": [ 48737812480,170355851264,277763588096,531015663616,535713284096,593544347648,626192809984,637718757376,766450335744,790508863488,915633340416,1318471073792,1565314252800,1600814841856 ],"type": "Time","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_time_6.cardinality:
+    218730
+  cest_full_table_big.c_time_6.histogram:
+    { "buckets": [ { "ndv": 557,"upper": "26038239232","lower": "16777216","count": 1450,"preSum": 0 },{ "ndv": 559,"upper": "50667192320","lower": "26055016448","count": 1447,"preSum": 1450 },{ "ndv": 492,"upper": "79171682304","lower": "50801410048","count": 1449,"preSum": 2897 },{ "ndv": 492,"upper": "100931731456","lower": "79255568384","count": 1463,"preSum": 4346 },{ "ndv": 515,"upper": "126349213696","lower": "100948508672","count": 1447,"preSum": 5809 },{ "ndv": 453,"upper": "150005088256","lower": "126416322560","count": 1447,"preSum": 7256 },{ "ndv": 577,"upper": "178274697216","lower": "150038642688","count": 1447,"preSum": 8703 },{ "ndv": 546,"upper": "207517384704","lower": "178308251648","count": 1448,"preSum": 10150 },{ "ndv": 592,"upper": "234528702464","lower": "207651602432","count": 1450,"preSum": 11598 },{ "ndv": 486,"upper": "258184577024","lower": "234545479680","count": 1455,"preSum": 13048 },{ "ndv": 579,"upper": "289222426624","lower": "258218131456","count": 1447,"preSum": 14503 },{ "ndv": 417,"upper": "308834992128","lower": "289272758272","count": 1475,"preSum": 15950 },{ "ndv": 517,"upper": "332222431232","lower": "308851769344","count": 1447,"preSum": 17425 },{ "ndv": 563,"upper": "362454974464","lower": "332289540096","count": 1457,"preSum": 18872 },{ "ndv": 482,"upper": "384802226176","lower": "362471751680","count": 1447,"preSum": 20329 },{ "ndv": 572,"upper": "415991070720","lower": "384869335040","count": 1447,"preSum": 21776 },{ "ndv": 491,"upper": "438841638912","lower": "416041402368","count": 1447,"preSum": 23223 },{ "ndv": 553,"upper": "464024240128","lower": "438858416128","count": 1447,"preSum": 24670 },{ "ndv": 489,"upper": "490616127488","lower": "464091348992","count": 1447,"preSum": 26117 },{ "ndv": 525,"upper": "515865837568","lower": "490750345216","count": 1447,"preSum": 27564 },{ "ndv": 615,"upper": "550041026560","lower": "515882614784","count": 1447,"preSum": 29011 },{ "ndv": 492,"upper": "572556050432","lower": "550124912640","count": 1448,"preSum": 30458 },{ "ndv": 464,"upper": "592252502016","lower": "572572827648","count": 1450,"preSum": 31906 },{ "ndv": 624,"upper": "624968073216","lower": "592437051392","count": 1447,"preSum": 33356 },{ "ndv": 629,"upper": "654244315136","lower": "625035182080","count": 1450,"preSum": 34803 },{ "ndv": 355,"upper": "670048452608","lower": "654277869568","count": 1447,"preSum": 36253 },{ "ndv": 543,"upper": "698469056512","lower": "670082007040","count": 1448,"preSum": 37700 },{ "ndv": 539,"upper": "724473741312","lower": "698485833728","count": 1447,"preSum": 39148 },{ "ndv": 548,"upper": "749522124800","lower": "724540850176","count": 1447,"preSum": 40595 },{ "ndv": 550,"upper": "779955994624","lower": "749555679232","count": 1448,"preSum": 42042 },{ "ndv": 506,"upper": "804014522368","lower": "779989549056","count": 1447,"preSum": 43490 },{ "ndv": 540,"upper": "833525645312","lower": "804031299584","count": 1447,"preSum": 44937 },{ "ndv": 539,"upper": "858607583232","lower": "833626308608","count": 1448,"preSum": 46384 },{ "ndv": 478,"upper": "882078908416","lower": "858691469312","count": 1451,"preSum": 47832 },{ "ndv": 464,"upper": "908922454016","lower": "882112462848","count": 1453,"preSum": 49283 },{ "ndv": 613,"upper": "937863151616","lower": "908989562880","count": 1447,"preSum": 50736 },{ "ndv": 517,"upper": "965562335232","lower": "937930260480","count": 1453,"preSum": 52183 },{ "ndv": 522,"upper": "988278685696","lower": "965595889664","count": 1448,"preSum": 53636 },{ "ndv": 530,"upper": "1011901005824","lower": "988312240128","count": 1447,"preSum": 55084 },{ "ndv": 564,"upper": "1042720751616","lower": "1011984891904","count": 1447,"preSum": 56531 },{ "ndv": 538,"upper": "1066896719872","lower": "1042771083264","count": 1447,"preSum": 57978 },{ "ndv": 504,"upper": "1090401599488","lower": "1066947051520","count": 1483,"preSum": 59425 },{ "ndv": 565,"upper": "1121825325056","lower": "1090451931136","count": 1448,"preSum": 60908 },{ "ndv": 490,"upper": "1144105467904","lower": "1121875656704","count": 1448,"preSum": 62356 },{ "ndv": 495,"upper": "1171536216064","lower": "1144155799552","count": 1449,"preSum": 63804 },{ "ndv": 474,"upper": "1194151903232","lower": "1171586547712","count": 1448,"preSum": 65253 },{ "ndv": 614,"upper": "1222052413440","lower": "1194185457664","count": 1450,"preSum": 66701 },{ "ndv": 555,"upper": "1252737941504","lower": "1222069190656","count": 1449,"preSum": 68151 },{ "ndv": 565,"upper": "1279648595968","lower": "1252771495936","count": 1477,"preSum": 69600 },{ "ndv": 558,"upper": "1308924837888","lower": "1279749259264","count": 1447,"preSum": 71077 },{ "ndv": 592,"upper": "1336053596160","lower": "1308941615104","count": 1447,"preSum": 72524 },{ "ndv": 577,"upper": "1362343493632","lower": "1336120705024","count": 1452,"preSum": 73971 },{ "ndv": 432,"upper": "1386922115072","lower": "1362360270848","count": 1448,"preSum": 75423 },{ "ndv": 480,"upper": "1409739128832","lower": "1386972446720","count": 1448,"preSum": 76871 },{ "ndv": 554,"upper": "1433965428736","lower": "1409839792128","count": 1447,"preSum": 78319 },{ "ndv": 476,"upper": "1459718455296","lower": "1433998983168","count": 1447,"preSum": 79766 },{ "ndv": 522,"upper": "1484364185600","lower": "1459768786944","count": 1454,"preSum": 81213 },{ "ndv": 452,"upper": "1504211632128","lower": "1484380962816","count": 1447,"preSum": 82667 },{ "ndv": 558,"upper": "1533454319616","lower": "1504228409344","count": 1464,"preSum": 84114 },{ "ndv": 449,"upper": "1553805082624","lower": "1533487874048","count": 1553,"preSum": 85578 },{ "ndv": 480,"upper": "1580833177600","lower": "1553838637056","count": 1449,"preSum": 87131 },{ "ndv": 445,"upper": "1601821474816","lower": "1580866732032","count": 1495,"preSum": 88580 },{ "ndv": 547,"upper": "1626215546880","lower": "1601905360896","count": 1447,"preSum": 90075 },{ "ndv": 386,"upper": "1644787924992","lower": "1626349764608","count": 1061,"preSum": 91522 } ],"maxBucketSize": 64,"type": "Time","sampleRate": 0.90062594 }
+  cest_full_table_big.c_time_6.null_count:
+    0
+  cest_full_table_big.c_time_6.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_1.TOPN:
+    { "countArr": [ 548,509,479,551,495,541,488,583,489,493,538,517,581,510 ],"valueArr": [ -113,-98,-78,-61,-57,-52,-44,9,19,38,41,46,86,89 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_1.cardinality:
+    256
+  cest_full_table_big.c_tinyint_1.histogram:
+    { "buckets": [ { "ndv": 4,"upper": -125,"lower": -128,"count": 1528,"preSum": 0 },{ "ndv": 4,"upper": -121,"lower": -124,"count": 1519,"preSum": 1528 },{ "ndv": 4,"upper": -117,"lower": -120,"count": 1478,"preSum": 3047 },{ "ndv": 4,"upper": -112,"lower": -116,"count": 1552,"preSum": 4525 },{ "ndv": 4,"upper": -108,"lower": -111,"count": 1530,"preSum": 6077 },{ "ndv": 4,"upper": -104,"lower": -107,"count": 1527,"preSum": 7607 },{ "ndv": 4,"upper": -100,"lower": -103,"count": 1453,"preSum": 9134 },{ "ndv": 4,"upper": -95,"lower": -99,"count": 1633,"preSum": 10587 },{ "ndv": 4,"upper": -91,"lower": -94,"count": 1624,"preSum": 12220 },{ "ndv": 4,"upper": -87,"lower": -90,"count": 1484,"preSum": 13844 },{ "ndv": 5,"upper": -82,"lower": -86,"count": 1800,"preSum": 15328 },{ "ndv": 4,"upper": -77,"lower": -81,"count": 1564,"preSum": 17128 },{ "ndv": 5,"upper": -72,"lower": -76,"count": 1805,"preSum": 18692 },{ "ndv": 4,"upper": -68,"lower": -71,"count": 1565,"preSum": 20497 },{ "ndv": 4,"upper": -64,"lower": -67,"count": 1506,"preSum": 22062 },{ "ndv": 4,"upper": -59,"lower": -63,"count": 1566,"preSum": 23568 },{ "ndv": 4,"upper": -54,"lower": -58,"count": 1632,"preSum": 25134 },{ "ndv": 4,"upper": -49,"lower": -53,"count": 1606,"preSum": 26766 },{ "ndv": 4,"upper": -45,"lower": -48,"count": 1606,"preSum": 28372 },{ "ndv": 5,"upper": -39,"lower": -43,"count": 1861,"preSum": 29978 },{ "ndv": 4,"upper": -35,"lower": -38,"count": 1557,"preSum": 31839 },{ "ndv": 4,"upper": -31,"lower": -34,"count": 1517,"preSum": 33396 },{ "ndv": 4,"upper": -27,"lower": -30,"count": 1556,"preSum": 34913 },{ "ndv": 4,"upper": -23,"lower": -26,"count": 1599,"preSum": 36469 },{ "ndv": 4,"upper": -19,"lower": -22,"count": 1541,"preSum": 38068 },{ "ndv": 4,"upper": -15,"lower": -18,"count": 1631,"preSum": 39609 },{ "ndv": 5,"upper": -10,"lower": -14,"count": 1791,"preSum": 41240 },{ "ndv": 4,"upper": -6,"lower": -9,"count": 1609,"preSum": 43031 },{ "ndv": 4,"upper": -2,"lower": -5,"count": 1550,"preSum": 44640 },{ "ndv": 4,"upper": 2,"lower": -1,"count": 1470,"preSum": 46190 },{ "ndv": 4,"upper": 6,"lower": 3,"count": 1554,"preSum": 47660 },{ "ndv": 4,"upper": 11,"lower": 7,"count": 1627,"preSum": 49214 },{ "ndv": 4,"upper": 15,"lower": 12,"count": 1524,"preSum": 50841 },{ "ndv": 4,"upper": 20,"lower": 16,"count": 1662,"preSum": 52365 },{ "ndv": 4,"upper": 24,"lower": 21,"count": 1502,"preSum": 54027 },{ "ndv": 4,"upper": 28,"lower": 25,"count": 1459,"preSum": 55529 },{ "ndv": 4,"upper": 32,"lower": 29,"count": 1624,"preSum": 56988 },{ "ndv": 4,"upper": 36,"lower": 33,"count": 1463,"preSum": 58612 },{ "ndv": 4,"upper": 42,"lower": 37,"count": 1553,"preSum": 60075 },{ "ndv": 4,"upper": 47,"lower": 43,"count": 1525,"preSum": 61628 },{ "ndv": 4,"upper": 51,"lower": 48,"count": 1466,"preSum": 63153 },{ "ndv": 4,"upper": 55,"lower": 52,"count": 1563,"preSum": 64619 },{ "ndv": 4,"upper": 59,"lower": 56,"count": 1711,"preSum": 66182 },{ "ndv": 4,"upper": 63,"lower": 60,"count": 1529,"preSum": 67893 },{ "ndv": 4,"upper": 67,"lower": 64,"count": 1474,"preSum": 69422 },{ "ndv": 4,"upper": 71,"lower": 68,"count": 1510,"preSum": 70896 },{ "ndv": 4,"upper": 75,"lower": 72,"count": 1464,"preSum": 72406 },{ "ndv": 4,"upper": 79,"lower": 76,"count": 1533,"preSum": 73870 },{ "ndv": 4,"upper": 83,"lower": 80,"count": 1496,"preSum": 75403 },{ "ndv": 4,"upper": 88,"lower": 84,"count": 1511,"preSum": 76899 },{ "ndv": 4,"upper": 93,"lower": 90,"count": 1522,"preSum": 78410 },{ "ndv": 4,"upper": 97,"lower": 94,"count": 1567,"preSum": 79932 },{ "ndv": 4,"upper": 101,"lower": 98,"count": 1549,"preSum": 81499 },{ "ndv": 4,"upper": 105,"lower": 102,"count": 1519,"preSum": 83048 },{ "ndv": 4,"upper": 109,"lower": 106,"count": 1525,"preSum": 84567 },{ "ndv": 4,"upper": 113,"lower": 110,"count": 1488,"preSum": 86092 },{ "ndv": 4,"upper": 117,"lower": 114,"count": 1477,"preSum": 87580 },{ "ndv": 4,"upper": 121,"lower": 118,"count": 1463,"preSum": 89057 },{ "ndv": 4,"upper": 125,"lower": 122,"count": 1449,"preSum": 90520 },{ "ndv": 2,"upper": 127,"lower": 126,"count": 710,"preSum": 91969 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_1.null_count:
+    0
+  cest_full_table_big.c_tinyint_1.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_1_un.TOPN:
+    { "countArr": [ 1274,1046,963,1354,1090,1069,1700,1067,1359,1131,1017,1236,1171,997 ],"valueArr": [ 7,15,17,33,38,42,68,73,84,87,92,107,108,115 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_1_un.cardinality:
+    128
+  cest_full_table_big.c_tinyint_1_un.histogram:
+    { "buckets": [ { "ndv": 3,"upper": 2,"lower": 0,"count": 2132,"preSum": 0 },{ "ndv": 2,"upper": 4,"lower": 3,"count": 1311,"preSum": 2132 },{ "ndv": 2,"upper": 6,"lower": 5,"count": 1520,"preSum": 3443 },{ "ndv": 2,"upper": 9,"lower": 8,"count": 1423,"preSum": 4963 },{ "ndv": 2,"upper": 11,"lower": 10,"count": 1462,"preSum": 6386 },{ "ndv": 3,"upper": 14,"lower": 12,"count": 1923,"preSum": 7848 },{ "ndv": 2,"upper": 18,"lower": 16,"count": 1422,"preSum": 9771 },{ "ndv": 2,"upper": 20,"lower": 19,"count": 1434,"preSum": 11193 },{ "ndv": 2,"upper": 22,"lower": 21,"count": 1399,"preSum": 12627 },{ "ndv": 2,"upper": 24,"lower": 23,"count": 1455,"preSum": 14026 },{ "ndv": 2,"upper": 26,"lower": 25,"count": 1458,"preSum": 15481 },{ "ndv": 2,"upper": 28,"lower": 27,"count": 1349,"preSum": 16939 },{ "ndv": 2,"upper": 30,"lower": 29,"count": 1425,"preSum": 18288 },{ "ndv": 2,"upper": 32,"lower": 31,"count": 1400,"preSum": 19713 },{ "ndv": 2,"upper": 35,"lower": 34,"count": 1655,"preSum": 21113 },{ "ndv": 2,"upper": 37,"lower": 36,"count": 1787,"preSum": 22768 },{ "ndv": 2,"upper": 40,"lower": 39,"count": 1570,"preSum": 24555 },{ "ndv": 3,"upper": 44,"lower": 41,"count": 2198,"preSum": 26125 },{ "ndv": 2,"upper": 46,"lower": 45,"count": 1355,"preSum": 28323 },{ "ndv": 2,"upper": 48,"lower": 47,"count": 1394,"preSum": 29678 },{ "ndv": 2,"upper": 50,"lower": 49,"count": 1550,"preSum": 31072 },{ "ndv": 2,"upper": 52,"lower": 51,"count": 1607,"preSum": 32622 },{ "ndv": 2,"upper": 54,"lower": 53,"count": 1533,"preSum": 34229 },{ "ndv": 2,"upper": 56,"lower": 55,"count": 1753,"preSum": 35762 },{ "ndv": 2,"upper": 58,"lower": 57,"count": 1369,"preSum": 37515 },{ "ndv": 2,"upper": 60,"lower": 59,"count": 1633,"preSum": 38884 },{ "ndv": 2,"upper": 62,"lower": 61,"count": 1466,"preSum": 40517 },{ "ndv": 2,"upper": 64,"lower": 63,"count": 1495,"preSum": 41983 },{ "ndv": 2,"upper": 66,"lower": 65,"count": 1479,"preSum": 43478 },{ "ndv": 2,"upper": 69,"lower": 67,"count": 1645,"preSum": 44957 },{ "ndv": 2,"upper": 71,"lower": 70,"count": 1458,"preSum": 46602 },{ "ndv": 2,"upper": 74,"lower": 72,"count": 1763,"preSum": 48060 },{ "ndv": 2,"upper": 76,"lower": 75,"count": 1315,"preSum": 49823 },{ "ndv": 2,"upper": 78,"lower": 77,"count": 1380,"preSum": 51138 },{ "ndv": 2,"upper": 80,"lower": 79,"count": 1479,"preSum": 52518 },{ "ndv": 2,"upper": 82,"lower": 81,"count": 1348,"preSum": 53997 },{ "ndv": 2,"upper": 85,"lower": 83,"count": 1510,"preSum": 55345 },{ "ndv": 2,"upper": 88,"lower": 86,"count": 1350,"preSum": 56855 },{ "ndv": 2,"upper": 90,"lower": 89,"count": 1447,"preSum": 58205 },{ "ndv": 2,"upper": 93,"lower": 91,"count": 1497,"preSum": 59652 },{ "ndv": 2,"upper": 95,"lower": 94,"count": 1468,"preSum": 61149 },{ "ndv": 2,"upper": 97,"lower": 96,"count": 1534,"preSum": 62617 },{ "ndv": 2,"upper": 99,"lower": 98,"count": 1396,"preSum": 64151 },{ "ndv": 2,"upper": 101,"lower": 100,"count": 1372,"preSum": 65547 },{ "ndv": 2,"upper": 103,"lower": 102,"count": 1315,"preSum": 66919 },{ "ndv": 2,"upper": 105,"lower": 104,"count": 1422,"preSum": 68234 },{ "ndv": 2,"upper": 109,"lower": 106,"count": 1484,"preSum": 69656 },{ "ndv": 2,"upper": 111,"lower": 110,"count": 1562,"preSum": 71140 },{ "ndv": 2,"upper": 113,"lower": 112,"count": 1464,"preSum": 72702 },{ "ndv": 2,"upper": 116,"lower": 114,"count": 1496,"preSum": 74166 },{ "ndv": 2,"upper": 118,"lower": 117,"count": 1498,"preSum": 75662 },{ "ndv": 2,"upper": 120,"lower": 119,"count": 1443,"preSum": 77160 },{ "ndv": 2,"upper": 122,"lower": 121,"count": 1443,"preSum": 78603 },{ "ndv": 2,"upper": 124,"lower": 123,"count": 1482,"preSum": 80046 },{ "ndv": 2,"upper": 126,"lower": 125,"count": 1376,"preSum": 81528 },{ "ndv": 1,"upper": 127,"lower": 127,"count": 623,"preSum": 82904 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_1_un.null_count:
+    0
+  cest_full_table_big.c_tinyint_1_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_4.TOPN:
+    { "countArr": [ 1111,818,807,761,1458,966,937,2201,862,1706,1045,1198,1076,809 ],"valueArr": [ -113,-98,-97,-94,-61,-52,-44,9,19,41,46,86,89,102 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_4.cardinality:
+    256
+  cest_full_table_big.c_tinyint_4.histogram:
+    { "buckets": [ { "ndv": 5,"upper": -124,"lower": -128,"count": 1430,"preSum": 0 },{ "ndv": 4,"upper": -120,"lower": -123,"count": 1406,"preSum": 1430 },{ "ndv": 5,"upper": -115,"lower": -119,"count": 1761,"preSum": 2836 },{ "ndv": 5,"upper": -109,"lower": -114,"count": 1661,"preSum": 4597 },{ "ndv": 5,"upper": -104,"lower": -108,"count": 1529,"preSum": 6258 },{ "ndv": 5,"upper": -99,"lower": -103,"count": 1377,"preSum": 7787 },{ "ndv": 4,"upper": -92,"lower": -96,"count": 1600,"preSum": 9164 },{ "ndv": 5,"upper": -87,"lower": -91,"count": 1548,"preSum": 10764 },{ "ndv": 5,"upper": -82,"lower": -86,"count": 1443,"preSum": 12312 },{ "ndv": 4,"upper": -78,"lower": -81,"count": 1630,"preSum": 13755 },{ "ndv": 5,"upper": -73,"lower": -77,"count": 1380,"preSum": 15385 },{ "ndv": 4,"upper": -69,"lower": -72,"count": 1406,"preSum": 16765 },{ "ndv": 4,"upper": -65,"lower": -68,"count": 1489,"preSum": 18171 },{ "ndv": 5,"upper": -59,"lower": -64,"count": 1433,"preSum": 19660 },{ "ndv": 3,"upper": -56,"lower": -58,"count": 1635,"preSum": 21093 },{ "ndv": 4,"upper": -51,"lower": -55,"count": 1610,"preSum": 22728 },{ "ndv": 4,"upper": -47,"lower": -50,"count": 1469,"preSum": 24338 },{ "ndv": 5,"upper": -41,"lower": -46,"count": 1384,"preSum": 25807 },{ "ndv": 4,"upper": -37,"lower": -40,"count": 1607,"preSum": 27191 },{ "ndv": 5,"upper": -32,"lower": -36,"count": 1602,"preSum": 28798 },{ "ndv": 4,"upper": -28,"lower": -31,"count": 1425,"preSum": 30400 },{ "ndv": 3,"upper": -25,"lower": -27,"count": 1335,"preSum": 31825 },{ "ndv": 4,"upper": -21,"lower": -24,"count": 1507,"preSum": 33160 },{ "ndv": 4,"upper": -17,"lower": -20,"count": 1564,"preSum": 34667 },{ "ndv": 4,"upper": -13,"lower": -16,"count": 1579,"preSum": 36231 },{ "ndv": 5,"upper": -8,"lower": -12,"count": 1555,"preSum": 37810 },{ "ndv": 4,"upper": -4,"lower": -7,"count": 1426,"preSum": 39365 },{ "ndv": 3,"upper": -1,"lower": -3,"count": 1320,"preSum": 40791 },{ "ndv": 5,"upper": 4,"lower": 0,"count": 1432,"preSum": 42111 },{ "ndv": 3,"upper": 7,"lower": 5,"count": 1573,"preSum": 43543 },{ "ndv": 4,"upper": 12,"lower": 8,"count": 1420,"preSum": 45116 },{ "ndv": 4,"upper": 16,"lower": 13,"count": 1561,"preSum": 46536 },{ "ndv": 4,"upper": 21,"lower": 17,"count": 1465,"preSum": 48097 },{ "ndv": 5,"upper": 26,"lower": 22,"count": 1478,"preSum": 49562 },{ "ndv": 5,"upper": 31,"lower": 27,"count": 1739,"preSum": 51040 },{ "ndv": 5,"upper": 36,"lower": 32,"count": 1518,"preSum": 52779 },{ "ndv": 4,"upper": 40,"lower": 37,"count": 2007,"preSum": 54297 },{ "ndv": 4,"upper": 45,"lower": 42,"count": 1417,"preSum": 56304 },{ "ndv": 6,"upper": 52,"lower": 47,"count": 1778,"preSum": 57721 },{ "ndv": 4,"upper": 56,"lower": 53,"count": 1584,"preSum": 59499 },{ "ndv": 3,"upper": 59,"lower": 57,"count": 1388,"preSum": 61083 },{ "ndv": 4,"upper": 63,"lower": 60,"count": 1480,"preSum": 62471 },{ "ndv": 4,"upper": 67,"lower": 64,"count": 1529,"preSum": 63951 },{ "ndv": 5,"upper": 72,"lower": 68,"count": 1492,"preSum": 65480 },{ "ndv": 5,"upper": 77,"lower": 73,"count": 1527,"preSum": 66972 },{ "ndv": 5,"upper": 82,"lower": 78,"count": 1571,"preSum": 68499 },{ "ndv": 4,"upper": 87,"lower": 83,"count": 1382,"preSum": 70070 },{ "ndv": 5,"upper": 93,"lower": 88,"count": 1555,"preSum": 71452 },{ "ndv": 4,"upper": 97,"lower": 94,"count": 1477,"preSum": 73007 },{ "ndv": 3,"upper": 100,"lower": 98,"count": 1347,"preSum": 74484 },{ "ndv": 5,"upper": 106,"lower": 101,"count": 1424,"preSum": 75831 },{ "ndv": 4,"upper": 110,"lower": 107,"count": 1348,"preSum": 77255 },{ "ndv": 4,"upper": 114,"lower": 111,"count": 1544,"preSum": 78603 },{ "ndv": 5,"upper": 119,"lower": 115,"count": 1522,"preSum": 80147 },{ "ndv": 4,"upper": 123,"lower": 120,"count": 1504,"preSum": 81669 },{ "ndv": 4,"upper": 127,"lower": 124,"count": 1073,"preSum": 83173 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_4.null_count:
+    0
+  cest_full_table_big.c_tinyint_4.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_4_un.TOPN:
+    { "countArr": [ 3185,1686,1496,4750,2208,1952,1361,11522,1900,6644,2420,3782,2698,1594 ],"valueArr": [ 7,15,17,33,38,42,67,68,73,84,87,107,108,115 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_4_un.cardinality:
+    128
+  cest_full_table_big.c_tinyint_4_un.histogram:
+    { "buckets": [ { "ndv": 3,"upper": 2,"lower": 0,"count": 1463,"preSum": 0 },{ "ndv": 3,"upper": 5,"lower": 3,"count": 940,"preSum": 1463 },{ "ndv": 2,"upper": 8,"lower": 6,"count": 942,"preSum": 2403 },{ "ndv": 3,"upper": 11,"lower": 9,"count": 1123,"preSum": 3345 },{ "ndv": 3,"upper": 14,"lower": 12,"count": 878,"preSum": 4468 },{ "ndv": 3,"upper": 19,"lower": 16,"count": 1035,"preSum": 5346 },{ "ndv": 2,"upper": 21,"lower": 20,"count": 932,"preSum": 6381 },{ "ndv": 3,"upper": 24,"lower": 22,"count": 1455,"preSum": 7313 },{ "ndv": 2,"upper": 26,"lower": 25,"count": 831,"preSum": 8768 },{ "ndv": 3,"upper": 29,"lower": 27,"count": 1069,"preSum": 9599 },{ "ndv": 2,"upper": 31,"lower": 30,"count": 1021,"preSum": 10668 },{ "ndv": 3,"upper": 35,"lower": 32,"count": 1921,"preSum": 11689 },{ "ndv": 1,"upper": 36,"lower": 36,"count": 1103,"preSum": 13610 },{ "ndv": 2,"upper": 39,"lower": 37,"count": 1098,"preSum": 14713 },{ "ndv": 1,"upper": 40,"lower": 40,"count": 980,"preSum": 15811 },{ "ndv": 3,"upper": 44,"lower": 41,"count": 1579,"preSum": 16791 },{ "ndv": 3,"upper": 47,"lower": 45,"count": 964,"preSum": 18370 },{ "ndv": 2,"upper": 49,"lower": 48,"count": 947,"preSum": 19334 },{ "ndv": 2,"upper": 51,"lower": 50,"count": 1690,"preSum": 20281 },{ "ndv": 2,"upper": 53,"lower": 52,"count": 1184,"preSum": 21971 },{ "ndv": 2,"upper": 55,"lower": 54,"count": 1049,"preSum": 23155 },{ "ndv": 1,"upper": 56,"lower": 56,"count": 878,"preSum": 24204 },{ "ndv": 3,"upper": 59,"lower": 57,"count": 1371,"preSum": 25082 },{ "ndv": 3,"upper": 62,"lower": 60,"count": 1028,"preSum": 26453 },{ "ndv": 2,"upper": 64,"lower": 63,"count": 980,"preSum": 27481 },{ "ndv": 2,"upper": 66,"lower": 65,"count": 908,"preSum": 28461 },{ "ndv": 3,"upper": 71,"lower": 69,"count": 1233,"preSum": 29369 },{ "ndv": 1,"upper": 72,"lower": 72,"count": 1055,"preSum": 30602 },{ "ndv": 2,"upper": 75,"lower": 74,"count": 996,"preSum": 31657 },{ "ndv": 3,"upper": 78,"lower": 76,"count": 961,"preSum": 32653 },{ "ndv": 2,"upper": 80,"lower": 79,"count": 898,"preSum": 33614 },{ "ndv": 3,"upper": 83,"lower": 81,"count": 1518,"preSum": 34512 },{ "ndv": 3,"upper": 88,"lower": 85,"count": 986,"preSum": 36030 },{ "ndv": 2,"upper": 90,"lower": 89,"count": 896,"preSum": 37016 },{ "ndv": 2,"upper": 92,"lower": 91,"count": 1576,"preSum": 37912 },{ "ndv": 2,"upper": 94,"lower": 93,"count": 1056,"preSum": 39488 },{ "ndv": 3,"upper": 97,"lower": 95,"count": 1387,"preSum": 40544 },{ "ndv": 3,"upper": 100,"lower": 98,"count": 852,"preSum": 41931 },{ "ndv": 3,"upper": 103,"lower": 101,"count": 969,"preSum": 42783 },{ "ndv": 2,"upper": 105,"lower": 104,"count": 837,"preSum": 43752 },{ "ndv": 3,"upper": 110,"lower": 106,"count": 1287,"preSum": 44589 },{ "ndv": 2,"upper": 112,"lower": 111,"count": 908,"preSum": 45876 },{ "ndv": 2,"upper": 114,"lower": 113,"count": 1458,"preSum": 46784 },{ "ndv": 3,"upper": 118,"lower": 116,"count": 1096,"preSum": 48242 },{ "ndv": 2,"upper": 120,"lower": 119,"count": 929,"preSum": 49338 },{ "ndv": 3,"upper": 123,"lower": 121,"count": 1072,"preSum": 50267 },{ "ndv": 2,"upper": 125,"lower": 124,"count": 1005,"preSum": 51339 },{ "ndv": 2,"upper": 127,"lower": 126,"count": 459,"preSum": 52344 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_4_un.null_count:
+    0
+  cest_full_table_big.c_tinyint_4_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_8.TOPN:
+    { "countArr": [ 3252,1478,1402,5391,2091,1799,16518,1620,1123,8182,2234,3954,2767,1265 ],"valueArr": [ -113,-98,-97,-61,-52,-44,9,19,40,41,46,86,89,102 ],"type": "Int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_8.cardinality:
+    256
+  cest_full_table_big.c_tinyint_8.histogram:
+    { "buckets": [ { "ndv": 6,"upper": -123,"lower": -128,"count": 1180,"preSum": 0 },{ "ndv": 7,"upper": -116,"lower": -122,"count": 831,"preSum": 1180 },{ "ndv": 4,"upper": -111,"lower": -115,"count": 800,"preSum": 2011 },{ "ndv": 6,"upper": -105,"lower": -110,"count": 832,"preSum": 2811 },{ "ndv": 7,"upper": -96,"lower": -104,"count": 987,"preSum": 3643 },{ "ndv": 2,"upper": -94,"lower": -95,"count": 1165,"preSum": 4630 },{ "ndv": 5,"upper": -89,"lower": -93,"count": 798,"preSum": 5795 },{ "ndv": 5,"upper": -84,"lower": -88,"count": 753,"preSum": 6593 },{ "ndv": 5,"upper": -79,"lower": -83,"count": 1021,"preSum": 7346 },{ "ndv": 5,"upper": -74,"lower": -78,"count": 767,"preSum": 8367 },{ "ndv": 5,"upper": -69,"lower": -73,"count": 811,"preSum": 9134 },{ "ndv": 4,"upper": -65,"lower": -68,"count": 911,"preSum": 9945 },{ "ndv": 7,"upper": -57,"lower": -64,"count": 1635,"preSum": 10856 },{ "ndv": 1,"upper": -56,"lower": -56,"count": 786,"preSum": 12491 },{ "ndv": 3,"upper": -53,"lower": -55,"count": 777,"preSum": 13277 },{ "ndv": 5,"upper": -47,"lower": -51,"count": 1211,"preSum": 14054 },{ "ndv": 7,"upper": -39,"lower": -46,"count": 1344,"preSum": 15265 },{ "ndv": 6,"upper": -33,"lower": -38,"count": 750,"preSum": 16609 },{ "ndv": 4,"upper": -29,"lower": -32,"count": 796,"preSum": 17359 },{ "ndv": 4,"upper": -25,"lower": -28,"count": 1379,"preSum": 18155 },{ "ndv": 4,"upper": -21,"lower": -24,"count": 1033,"preSum": 19534 },{ "ndv": 4,"upper": -17,"lower": -20,"count": 891,"preSum": 20567 },{ "ndv": 3,"upper": -14,"lower": -16,"count": 783,"preSum": 21458 },{ "ndv": 5,"upper": -9,"lower": -13,"count": 965,"preSum": 22241 },{ "ndv": 5,"upper": -4,"lower": -8,"count": 813,"preSum": 23206 },{ "ndv": 3,"upper": -1,"lower": -3,"count": 951,"preSum": 24019 },{ "ndv": 6,"upper": 5,"lower": 0,"count": 938,"preSum": 24970 },{ "ndv": 2,"upper": 7,"lower": 6,"count": 1259,"preSum": 25908 },{ "ndv": 6,"upper": 14,"lower": 8,"count": 766,"preSum": 27167 },{ "ndv": 2,"upper": 16,"lower": 15,"count": 1125,"preSum": 27933 },{ "ndv": 4,"upper": 21,"lower": 17,"count": 797,"preSum": 29058 },{ "ndv": 6,"upper": 27,"lower": 22,"count": 759,"preSum": 29855 },{ "ndv": 5,"upper": 32,"lower": 28,"count": 895,"preSum": 30614 },{ "ndv": 6,"upper": 38,"lower": 33,"count": 1204,"preSum": 31509 },{ "ndv": 5,"upper": 45,"lower": 39,"count": 783,"preSum": 32713 },{ "ndv": 6,"upper": 52,"lower": 47,"count": 817,"preSum": 33496 },{ "ndv": 4,"upper": 56,"lower": 53,"count": 942,"preSum": 34313 },{ "ndv": 1,"upper": 57,"lower": 57,"count": 964,"preSum": 35255 },{ "ndv": 3,"upper": 60,"lower": 58,"count": 750,"preSum": 36219 },{ "ndv": 6,"upper": 66,"lower": 61,"count": 1047,"preSum": 36969 },{ "ndv": 6,"upper": 72,"lower": 67,"count": 768,"preSum": 38016 },{ "ndv": 6,"upper": 78,"lower": 73,"count": 758,"preSum": 38784 },{ "ndv": 6,"upper": 84,"lower": 79,"count": 813,"preSum": 39542 },{ "ndv": 6,"upper": 92,"lower": 85,"count": 761,"preSum": 40355 },{ "ndv": 3,"upper": 95,"lower": 93,"count": 763,"preSum": 41116 },{ "ndv": 5,"upper": 100,"lower": 96,"count": 1244,"preSum": 41879 },{ "ndv": 6,"upper": 107,"lower": 101,"count": 858,"preSum": 43123 },{ "ndv": 5,"upper": 112,"lower": 108,"count": 854,"preSum": 43981 },{ "ndv": 6,"upper": 118,"lower": 113,"count": 820,"preSum": 44835 },{ "ndv": 4,"upper": 122,"lower": 119,"count": 780,"preSum": 45655 },{ "ndv": 5,"upper": 127,"lower": 123,"count": 490,"preSum": 46435 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_8.null_count:
+    0
+  cest_full_table_big.c_tinyint_8.sample_rate:
+    0.010943651
+  cest_full_table_big.c_tinyint_8_un.TOPN:
+    { "countArr": [ 3936,1637,1197,7353,2259,1892,1157,27104,1742,11584,2613,5053,3087,1355 ],"valueArr": [ 7,15,17,33,38,42,67,68,73,84,87,107,108,115 ],"type": "unsigned_int","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_tinyint_8_un.cardinality:
+    128
+  cest_full_table_big.c_tinyint_8_un.histogram:
+    { "buckets": [ { "ndv": 3,"upper": 2,"lower": 0,"count": 778,"preSum": 0 },{ "ndv": 4,"upper": 6,"lower": 3,"count": 701,"preSum": 778 },{ "ndv": 4,"upper": 11,"lower": 8,"count": 675,"preSum": 1479 },{ "ndv": 4,"upper": 16,"lower": 12,"count": 537,"preSum": 2154 },{ "ndv": 3,"upper": 20,"lower": 18,"count": 523,"preSum": 2691 },{ "ndv": 4,"upper": 24,"lower": 21,"count": 912,"preSum": 3214 },{ "ndv": 2,"upper": 26,"lower": 25,"count": 462,"preSum": 4126 },{ "ndv": 3,"upper": 29,"lower": 27,"count": 448,"preSum": 4588 },{ "ndv": 2,"upper": 31,"lower": 30,"count": 519,"preSum": 5036 },{ "ndv": 3,"upper": 35,"lower": 32,"count": 1324,"preSum": 5555 },{ "ndv": 1,"upper": 36,"lower": 36,"count": 736,"preSum": 6879 },{ "ndv": 1,"upper": 37,"lower": 37,"count": 495,"preSum": 7615 },{ "ndv": 2,"upper": 40,"lower": 39,"count": 751,"preSum": 8110 },{ "ndv": 3,"upper": 44,"lower": 41,"count": 970,"preSum": 8861 },{ "ndv": 4,"upper": 48,"lower": 45,"count": 540,"preSum": 9831 },{ "ndv": 2,"upper": 50,"lower": 49,"count": 480,"preSum": 10371 },{ "ndv": 1,"upper": 51,"lower": 51,"count": 906,"preSum": 10851 },{ "ndv": 2,"upper": 53,"lower": 52,"count": 702,"preSum": 11757 },{ "ndv": 2,"upper": 55,"lower": 54,"count": 596,"preSum": 12459 },{ "ndv": 1,"upper": 56,"lower": 56,"count": 608,"preSum": 13055 },{ "ndv": 3,"upper": 59,"lower": 57,"count": 725,"preSum": 13663 },{ "ndv": 3,"upper": 62,"lower": 60,"count": 457,"preSum": 14388 },{ "ndv": 1,"upper": 63,"lower": 63,"count": 470,"preSum": 14845 },{ "ndv": 3,"upper": 66,"lower": 64,"count": 615,"preSum": 15315 },{ "ndv": 3,"upper": 71,"lower": 69,"count": 511,"preSum": 15930 },{ "ndv": 1,"upper": 72,"lower": 72,"count": 851,"preSum": 16441 },{ "ndv": 2,"upper": 75,"lower": 74,"count": 527,"preSum": 17292 },{ "ndv": 4,"upper": 79,"lower": 76,"count": 607,"preSum": 17819 },{ "ndv": 4,"upper": 83,"lower": 80,"count": 1114,"preSum": 18426 },{ "ndv": 3,"upper": 88,"lower": 85,"count": 460,"preSum": 19540 },{ "ndv": 2,"upper": 90,"lower": 89,"count": 459,"preSum": 20000 },{ "ndv": 2,"upper": 92,"lower": 91,"count": 1121,"preSum": 20459 },{ "ndv": 2,"upper": 94,"lower": 93,"count": 543,"preSum": 21580 },{ "ndv": 3,"upper": 97,"lower": 95,"count": 720,"preSum": 22123 },{ "ndv": 4,"upper": 101,"lower": 98,"count": 581,"preSum": 22843 },{ "ndv": 3,"upper": 104,"lower": 102,"count": 478,"preSum": 23424 },{ "ndv": 3,"upper": 109,"lower": 105,"count": 496,"preSum": 23902 },{ "ndv": 2,"upper": 111,"lower": 110,"count": 563,"preSum": 24398 },{ "ndv": 2,"upper": 113,"lower": 112,"count": 464,"preSum": 24961 },{ "ndv": 1,"upper": 114,"lower": 114,"count": 504,"preSum": 25425 },{ "ndv": 3,"upper": 118,"lower": 116,"count": 483,"preSum": 25929 },{ "ndv": 2,"upper": 120,"lower": 119,"count": 468,"preSum": 26412 },{ "ndv": 4,"upper": 124,"lower": 121,"count": 790,"preSum": 26880 },{ "ndv": 3,"upper": 127,"lower": 125,"count": 362,"preSum": 27670 } ],"maxBucketSize": 64,"type": "unsigned_int","sampleRate": 0.90062594 }
+  cest_full_table_big.c_tinyint_8_un.null_count:
+    0
+  cest_full_table_big.c_tinyint_8_un.sample_rate:
+    0.010943651
+  cest_full_table_big.c_varchar.TOPN:
+    { "countArr": [ 2433,1066,969,848,715,3308,1257,1527,4703,640,44010,7391,1950,14569 ],"valueArr": [ "0abdb","150e3","322e0ed","5ee951d192","75","817a071","8b","8b4283","8f4b82","920e8","ae093","b","bd4663a26","d9" ],"type": "String","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_varchar.cardinality:
+    16380
+  cest_full_table_big.c_varchar.histogram:
+    { "buckets": [ { "ndv": 6,"upper": "00a","lower": "0","count": 559,"preSum": 0 },{ "ndv": 52,"upper": "074b69539b","lower": "00c85b4","count": 231,"preSum": 559 },{ "ndv": 47,"upper": "0dc7e251","lower": "078e97e","count": 229,"preSum": 790 },{ "ndv": 45,"upper": "13b","lower": "0dceae5","count": 229,"preSum": 1019 },{ "ndv": 53,"upper": "1b00dc6b0","lower": "13c39952","count": 229,"preSum": 1248 },{ "ndv": 31,"upper": "1fd95","lower": "1b05b203c","count": 682,"preSum": 1477 },{ "ndv": 31,"upper": "2381ac2e","lower": "2","count": 231,"preSum": 2159 },{ "ndv": 20,"upper": "26480","lower": "23a039a182","count": 229,"preSum": 2390 },{ "ndv": 22,"upper": "29","lower": "266","count": 272,"preSum": 2619 },{ "ndv": 7,"upper": "2a33cd62","lower": "290","count": 374,"preSum": 2891 },{ "ndv": 21,"upper": "2c5f8","lower": "2a38b3e6","count": 295,"preSum": 3265 },{ "ndv": 39,"upper": "3100e1bed","lower": "2c881705c0","count": 232,"preSum": 3560 },{ "ndv": 104,"upper": "3e7b006b66","lower": "310e28","count": 236,"preSum": 3792 },{ "ndv": 38,"upper": "439d9","lower": "3f065cb89","count": 382,"preSum": 4028 },{ "ndv": 40,"upper": "4a9e0d0","lower": "43bebbfaa","count": 321,"preSum": 4410 },{ "ndv": 79,"upper": "55d20f80","lower": "4acf6","count": 248,"preSum": 4731 },{ "ndv": 40,"upper": "5bd6f342c","lower": "56854ff5bf","count": 609,"preSum": 4979 },{ "ndv": 36,"upper": "61","lower": "5c299","count": 231,"preSum": 5588 },{ "ndv": 48,"upper": "68718fec4","lower": "6136af56de","count": 229,"preSum": 5819 },{ "ndv": 64,"upper": "7","lower": "687d3","count": 237,"preSum": 6048 },{ "ndv": 40,"upper": "7645e370","lower": "7001a8263","count": 364,"preSum": 6285 },{ "ndv": 33,"upper": "7ad","lower": "7667f5ffef","count": 239,"preSum": 6649 },{ "ndv": 42,"upper": "7fc5796","lower": "7adf2","count": 233,"preSum": 6888 },{ "ndv": 37,"upper": "8526f8","lower": "7fe486c70","count": 229,"preSum": 7121 },{ "ndv": 31,"upper": "88bc","lower": "857","count": 395,"preSum": 7350 },{ "ndv": 46,"upper": "8f942aac4d","lower": "88d29a56","count": 229,"preSum": 7745 },{ "ndv": 30,"upper": "93a4db","lower": "8fab04","count": 356,"preSum": 7974 },{ "ndv": 27,"upper": "97e","lower": "93c76a5e","count": 528,"preSum": 8330 },{ "ndv": 32,"upper": "9bd3b47ab0","lower": "97e90","count": 233,"preSum": 8858 },{ "ndv": 51,"upper": "a3d0c","lower": "9be21b","count": 280,"preSum": 9091 },{ "ndv": 31,"upper": "a862","lower": "a4373237","count": 280,"preSum": 9371 },{ "ndv": 44,"upper": "af454e5e2","lower": "a87355","count": 229,"preSum": 9651 },{ "ndv": 24,"upper": "b4866c38cf","lower": "af6f6396","count": 601,"preSum": 9880 },{ "ndv": 63,"upper": "bcdcc4413","lower": "b497d9","count": 231,"preSum": 10481 },{ "ndv": 43,"upper": "c333418","lower": "bce","count": 247,"preSum": 10712 },{ "ndv": 13,"upper": "c69","lower": "c38d","count": 345,"preSum": 10959 },{ "ndv": 32,"upper": "cb1050e6","lower": "c69b9b575b","count": 335,"preSum": 11304 },{ "ndv": 38,"upper": "cf539a","lower": "cb11fa08","count": 231,"preSum": 11639 },{ "ndv": 17,"upper": "d1c8d334c9","lower": "cf5d486","count": 550,"preSum": 11870 },{ "ndv": 56,"upper": "d992","lower": "d1cecee0ab","count": 272,"preSum": 12420 },{ "ndv": 84,"upper": "e3d64","lower": "d9ecd163d","count": 229,"preSum": 12692 },{ "ndv": 36,"upper": "e98c","lower": "e3e391eee","count": 240,"preSum": 12921 },{ "ndv": 64,"upper": "f3","lower": "e9dd622b","count": 230,"preSum": 13161 },{ "ndv": 13,"upper": "f4ead0","lower": "f33c3","count": 331,"preSum": 13391 },{ "ndv": 32,"upper": "f95f6364e","lower": "f4f7b","count": 330,"preSum": 13722 },{ "ndv": 28,"upper": "fe2","lower": "f9aa89","count": 257,"preSum": 14052 },{ "ndv": 6,"upper": "ffb6b2558","lower": "fe31162","count": 304,"preSum": 14309 },{ "ndv": 2,"upper": "fff96","lower": "fff2","count": 2,"preSum": 14613 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90062594 }
+  cest_full_table_big.c_varchar.null_count:
+    0
+  cest_full_table_big.c_varchar.sample_rate:
+    0.010943651
+  cest_full_table_big.c_year.TOPN:
+    { "countArr": [ 100001 ],"valueArr": [ 2022 ],"type": "Year","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_year.cardinality:
+    1
+  cest_full_table_big.c_year.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "Year","sampleRate": 0.90062594 }
+  cest_full_table_big.c_year.null_count:
+    0
+  cest_full_table_big.c_year.sample_rate:
+    0.010943651
+  cest_full_table_big.c_year_4.TOPN:
+    { "countArr": [ 100001 ],"valueArr": [ 2022 ],"type": "Year","sampleRate": 0.9006259287612014 }
+  cest_full_table_big.c_year_4.cardinality:
+    1
+  cest_full_table_big.c_year_4.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "Year","sampleRate": 0.90062594 }
+  cest_full_table_big.c_year_4.null_count:
+    0
+  cest_full_table_big.c_year_4.sample_rate:
+    0.010943651
+  cest_full_table_big.id.TOPN:
+    null
+  cest_full_table_big.id.cardinality:
+    6134006
+  cest_full_table_big.id.histogram:
+    { "buckets": [ { "ndv": 1563,"upper": 171092,"lower": 1378,"count": 1563,"preSum": 0 },{ "ndv": 1563,"upper": 340379,"lower": 171124,"count": 1563,"preSum": 1563 },{ "ndv": 1563,"upper": 503266,"lower": 340386,"count": 1563,"preSum": 3126 },{ "ndv": 1563,"upper": 646819,"lower": 503267,"count": 1563,"preSum": 4689 },{ "ndv": 1563,"upper": 821446,"lower": 646934,"count": 1563,"preSum": 6252 },{ "ndv": 1563,"upper": 991470,"lower": 821457,"count": 1563,"preSum": 7815 },{ "ndv": 1563,"upper": 1152808,"lower": 991471,"count": 1563,"preSum": 9378 },{ "ndv": 1563,"upper": 1305101,"lower": 1152847,"count": 1563,"preSum": 10941 },{ "ndv": 1563,"upper": 1458965,"lower": 1305134,"count": 1563,"preSum": 12504 },{ "ndv": 1563,"upper": 1633026,"lower": 1458975,"count": 1563,"preSum": 14067 },{ "ndv": 1563,"upper": 1804056,"lower": 1633076,"count": 1563,"preSum": 15630 },{ "ndv": 1563,"upper": 1952241,"lower": 1804287,"count": 1563,"preSum": 17193 },{ "ndv": 1563,"upper": 2092635,"lower": 1952265,"count": 1563,"preSum": 18756 },{ "ndv": 1563,"upper": 2250240,"lower": 2092717,"count": 1563,"preSum": 20319 },{ "ndv": 1563,"upper": 2383628,"lower": 2250254,"count": 1563,"preSum": 21882 },{ "ndv": 1563,"upper": 2543830,"lower": 2383630,"count": 1563,"preSum": 23445 },{ "ndv": 1563,"upper": 2713201,"lower": 2543858,"count": 1563,"preSum": 25008 },{ "ndv": 1563,"upper": 2853899,"lower": 2713231,"count": 1563,"preSum": 26571 },{ "ndv": 1563,"upper": 2993810,"lower": 2853930,"count": 1563,"preSum": 28134 },{ "ndv": 1563,"upper": 3137124,"lower": 2993823,"count": 1563,"preSum": 29697 },{ "ndv": 1563,"upper": 3297101,"lower": 3137167,"count": 1563,"preSum": 31260 },{ "ndv": 1563,"upper": 3418225,"lower": 3297133,"count": 1563,"preSum": 32823 },{ "ndv": 1563,"upper": 3575122,"lower": 3418228,"count": 1563,"preSum": 34386 },{ "ndv": 1563,"upper": 3724748,"lower": 3575138,"count": 1563,"preSum": 35949 },{ "ndv": 1563,"upper": 3902433,"lower": 3724751,"count": 1563,"preSum": 37512 },{ "ndv": 1563,"upper": 4045654,"lower": 3902434,"count": 1563,"preSum": 39075 },{ "ndv": 1563,"upper": 4222180,"lower": 4045684,"count": 1563,"preSum": 40638 },{ "ndv": 1563,"upper": 4358869,"lower": 4222182,"count": 1563,"preSum": 42201 },{ "ndv": 1563,"upper": 4520898,"lower": 4358898,"count": 1563,"preSum": 43764 },{ "ndv": 1563,"upper": 4696584,"lower": 4520899,"count": 1563,"preSum": 45327 },{ "ndv": 1563,"upper": 4861215,"lower": 4696931,"count": 1563,"preSum": 46890 },{ "ndv": 1563,"upper": 5012824,"lower": 4861231,"count": 1563,"preSum": 48453 },{ "ndv": 1563,"upper": 5195721,"lower": 5012837,"count": 1563,"preSum": 50016 },{ "ndv": 1563,"upper": 5363451,"lower": 5195722,"count": 1563,"preSum": 51579 },{ "ndv": 1563,"upper": 5516861,"lower": 5363481,"count": 1563,"preSum": 53142 },{ "ndv": 1563,"upper": 5667553,"lower": 5516888,"count": 1563,"preSum": 54705 },{ "ndv": 1563,"upper": 5820559,"lower": 5667554,"count": 1563,"preSum": 56268 },{ "ndv": 1563,"upper": 5958760,"lower": 5820606,"count": 1563,"preSum": 57831 },{ "ndv": 1563,"upper": 6095618,"lower": 5958792,"count": 1563,"preSum": 59394 },{ "ndv": 1563,"upper": 6271159,"lower": 6095652,"count": 1563,"preSum": 60957 },{ "ndv": 1563,"upper": 6425242,"lower": 6271175,"count": 1563,"preSum": 62520 },{ "ndv": 1563,"upper": 6570405,"lower": 6425259,"count": 1563,"preSum": 64083 },{ "ndv": 1563,"upper": 6701022,"lower": 6570409,"count": 1563,"preSum": 65646 },{ "ndv": 1563,"upper": 6864180,"lower": 6701054,"count": 1563,"preSum": 67209 },{ "ndv": 1563,"upper": 6994513,"lower": 6864181,"count": 1563,"preSum": 68772 },{ "ndv": 1563,"upper": 7140428,"lower": 6994537,"count": 1563,"preSum": 70335 },{ "ndv": 1563,"upper": 7302078,"lower": 7140438,"count": 1563,"preSum": 71898 },{ "ndv": 1563,"upper": 7480547,"lower": 7302154,"count": 1563,"preSum": 73461 },{ "ndv": 1563,"upper": 7649156,"lower": 7480567,"count": 1563,"preSum": 75024 },{ "ndv": 1563,"upper": 7807790,"lower": 7649174,"count": 1563,"preSum": 76587 },{ "ndv": 1563,"upper": 7945345,"lower": 7807800,"count": 1563,"preSum": 78150 },{ "ndv": 1563,"upper": 8096420,"lower": 7945380,"count": 1563,"preSum": 79713 },{ "ndv": 1563,"upper": 8255887,"lower": 8096427,"count": 1563,"preSum": 81276 },{ "ndv": 1563,"upper": 8408097,"lower": 8255893,"count": 1563,"preSum": 82839 },{ "ndv": 1563,"upper": 8587830,"lower": 8408141,"count": 1563,"preSum": 84402 },{ "ndv": 1563,"upper": 8745625,"lower": 8587866,"count": 1563,"preSum": 85965 },{ "ndv": 1563,"upper": 8887410,"lower": 8745629,"count": 1563,"preSum": 87528 },{ "ndv": 1563,"upper": 9058990,"lower": 8887431,"count": 1563,"preSum": 89091 },{ "ndv": 1563,"upper": 9221690,"lower": 9059077,"count": 1563,"preSum": 90654 },{ "ndv": 1563,"upper": 9370975,"lower": 9221710,"count": 1563,"preSum": 92217 },{ "ndv": 1563,"upper": 9522875,"lower": 9370981,"count": 1563,"preSum": 93780 },{ "ndv": 1563,"upper": 9688324,"lower": 9522917,"count": 1563,"preSum": 95343 },{ "ndv": 1563,"upper": 9856912,"lower": 9688333,"count": 1563,"preSum": 96906 },{ "ndv": 1532,"upper": 9998440,"lower": 9859678,"count": 1532,"preSum": 98469 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90062594 }
+  cest_full_table_big.id.null_count:
+    0
+  cest_full_table_big.id.sample_rate:
+    0.010943651
+  cest_full_table_big.c_bigint_1.composite_cardinality:
+    100465
+  cest_full_table_big.c_bigint_64.composite_cardinality:
+    100465
+  cest_full_table_big.c_bigint_64_un.composite_cardinality:
+    99782
+  cest_full_table_big.c_bigint_64_un,c_int_1.composite_cardinality:
+    9523658
+  cest_full_table_big.c_bit_32,c_bit_64.composite_cardinality:
+    9427873
+  cest_full_table_big.c_bit_32,c_bit_64,c_bit_8.composite_cardinality:
+    10061980
+  cest_full_table_big.c_bit_64.composite_cardinality:
+    99782
+  cest_full_table_big.c_char.composite_cardinality:
+    100308
+  cest_full_table_big.c_date.composite_cardinality:
+    368
+  cest_full_table_big.c_date,c_datetime_1.composite_cardinality:
+    100732
+  cest_full_table_big.c_date,c_datetime_1,c_timestamp.composite_cardinality:
+    9912587
+  cest_full_table_big.c_datetime.composite_cardinality:
+    99678
+  cest_full_table_big.c_datetime_1.composite_cardinality:
+    100498
+  cest_full_table_big.c_datetime_3.composite_cardinality:
+    100064
+  cest_full_table_big.c_datetime_3,c_datetime_6.composite_cardinality:
+    99597
+  cest_full_table_big.c_datetime_6.composite_cardinality:
+    99561
+  cest_full_table_big.c_decimal.composite_cardinality:
+    99283
+  cest_full_table_big.c_decimal_pr.composite_cardinality:
+    102195
+  cest_full_table_big.c_double.composite_cardinality:
+    100276
+  cest_full_table_big.c_double_pr.composite_cardinality:
+    100257
+  cest_full_table_big.c_double_un.composite_cardinality:
+    100073
+  cest_full_table_big.c_enum.composite_cardinality:
+    3
+  cest_full_table_big.c_float.composite_cardinality:
+    100638
+  cest_full_table_big.c_float_pr.composite_cardinality:
+    100680
+  cest_full_table_big.c_float_un.composite_cardinality:
+    100964
+  cest_full_table_big.c_int_1.composite_cardinality:
+    100711
+  cest_full_table_big.c_int_32.composite_cardinality:
+    100711
+  cest_full_table_big.c_int_32_un.composite_cardinality:
+    95894
+  cest_full_table_big.c_mediumint_1.composite_cardinality:
+    99264
+  cest_full_table_big.c_mediumint_24.composite_cardinality:
+    99264
+  cest_full_table_big.c_mediumint_24_un.composite_cardinality:
+    99154
+  cest_full_table_big.c_smallint_1.composite_cardinality:
+    44076
+  cest_full_table_big.c_smallint_16.composite_cardinality:
+    23278
+  cest_full_table_big.c_smallint_16_un.composite_cardinality:
+    9292
+  cest_full_table_big.c_text.composite_cardinality:
+    98172
+  cest_full_table_big.c_text_long.composite_cardinality:
+    98172
+  cest_full_table_big.c_text_medium.composite_cardinality:
+    98172
+  cest_full_table_big.c_text_tiny.composite_cardinality:
+    98172
+  cest_full_table_big.c_time.composite_cardinality:
+    59385
+  cest_full_table_big.c_timestamp.composite_cardinality:
+    99678
+  cest_full_table_big.c_timestamp_1.composite_cardinality:
+    100498
+  cest_full_table_big.c_timestamp_3.composite_cardinality:
+    100064
+  cest_full_table_big.c_timestamp_6.composite_cardinality:
+    99561
+  cest_full_table_big.c_time_1.composite_cardinality:
+    59502
+  cest_full_table_big.c_time_3.composite_cardinality:
+    59069
+  cest_full_table_big.c_time_6.composite_cardinality:
+    60387
+  cest_full_table_big.c_tinyint_1.composite_cardinality:
+    254
+  cest_full_table_big.c_tinyint_1_un.composite_cardinality:
+    126
+  cest_full_table_big.c_tinyint_4.composite_cardinality:
+    254
+  cest_full_table_big.c_tinyint_4_un.composite_cardinality:
+    126
+  cest_full_table_big.c_tinyint_8.composite_cardinality:
+    254
+  cest_full_table_big.c_tinyint_8_un.composite_cardinality:
+    126
+  cest_full_table_big.c_varchar.composite_cardinality:
+    25009
+  cest_full_table_big.c_year.composite_cardinality:
+    1
+  cest_full_table_big.c_year_4.composite_cardinality:
+    1
+  cest_full_table_big.id.composite_cardinality:
+    10080526
+CONFIG:
+  HOT_GSI_EVOLUTION_THRESHOLD:
+    5000000
+  defaltxxAPPName.isNew:
+    true
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/GlobalCoveringIndexAdvisorPlanTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/GlobalCoveringIndexAdvisorPlanTest.yml
index 4e0b11199..1058f8f0d 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/GlobalCoveringIndexAdvisorPlanTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/GlobalCoveringIndexAdvisorPlanTest.yml
@@ -11,6 +11,7 @@
          WHERE l_partkey = p_partkey);
 
   plan: |
+
     project(avg_yearly="$f0 / 7.0")
       hashagg($f0="sum(l_extendedprice)")
         filter(condition="l_quantity < 0.2 * f16w0$o0")
@@ -49,12 +50,13 @@
       value desc;
 
   plan: |
+
     memsort(sort="value desc")
       project(ps_partkey="ps_partkey", value="value")
         nljoin(condition="value > $f0 * 0.0001", type="inner")
-          hashagg(group="ps_partkey", value="sum(__*__)")
+          hashagg(group="ps_partkey", value="sum(value)")
             gather(concurrent=true)
-              indexscan(tables="[0000-0003].supplier_[00-15],nation,partsupp__what_if_gsi_ps_suppkey_[00-15]", shardcount=16, sql="select `supplier`.`s_suppkey`, `partsupp__what_if_gsi_ps_suppkey`.`ps_partkey`, `partsupp__what_if_gsi_ps_suppkey`.`ps_suppkey`, (`partsupp__what_if_gsi_ps_suppkey`.`ps_supplycost` * `partsupp__what_if_gsi_ps_suppkey`.`ps_availqty`) as `__*__` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany')) inner join `partsupp__what_if_gsi_ps_suppkey` as `partsupp__what_if_gsi_ps_suppkey` on (`supplier`.`s_suppkey` = `partsupp__what_if_gsi_ps_suppkey`.`ps_suppkey`)")
+              indexscan(tables="[0000-0003].supplier_[00-15],nation,partsupp__what_if_gsi_ps_suppkey_[00-15]", shardcount=16, sql="select `partsupp__what_if_gsi_ps_suppkey`.`ps_partkey`, sum((`partsupp__what_if_gsi_ps_suppkey`.`ps_supplycost` * `partsupp__what_if_gsi_ps_suppkey`.`ps_availqty`)) as `value` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany')) inner join `partsupp__what_if_gsi_ps_suppkey` as `partsupp__what_if_gsi_ps_suppkey` on (`supplier`.`s_suppkey` = `partsupp__what_if_gsi_ps_suppkey`.`ps_suppkey`) group by `partsupp__what_if_gsi_ps_suppkey`.`ps_partkey`")
           hashagg($f0="sum($f0)")
             gather(concurrent=true)
               indexscan(tables="[0000-0003].supplier_[00-15],nation,partsupp__what_if_gsi_ps_suppkey_[00-15]", shardcount=16, sql="select sum((`partsupp__what_if_gsi_ps_suppkey`.`ps_supplycost` * `partsupp__what_if_gsi_ps_suppkey`.`ps_availqty`)) as `$f0` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany')) inner join `partsupp__what_if_gsi_ps_suppkey` as `partsupp__what_if_gsi_ps_suppkey` on (`supplier`.`s_suppkey` = `partsupp__what_if_gsi_ps_suppkey`.`ps_suppkey`)")
@@ -93,6 +95,7 @@
     );
 
   plan: |
+
     hashagg(revenue="sum(revenue)")
       gather(concurrent=true)
         indexscan(tables="[0000-0003].part_[00-15],lineitem__what_if_gsi_l_partkey_[00-15]", shardcount=16, sql="select sum((`lineitem__what_if_gsi_l_partkey`.`l_extendedprice` * (1 - `lineitem__what_if_gsi_l_partkey`.`l_discount`))) as `revenue` from `part` as `part` inner join `lineitem__what_if_gsi_l_partkey` as `lineitem__what_if_gsi_l_partkey` on ((`part`.`p_partkey` = `lineitem__what_if_gsi_l_partkey`.`l_partkey`) and (((`part`.`p_partkey` = `lineitem__what_if_gsi_l_partkey`.`l_partkey`) and (`part`.`p_brand` = 'brand#12') and (`part`.`p_container` in('sm case', 'sm box', 'sm pack', 'sm pkg')) and (`lineitem__what_if_gsi_l_partkey`.`l_quantity` >= 1) and (`lineitem__what_if_gsi_l_partkey`.`l_quantity` <= (1 + 10)) and (`part`.`p_size` between 1 and 5) and (`lineitem__what_if_gsi_l_partkey`.`l_shipmode` in('air', 'air reg')) and (`lineitem__what_if_gsi_l_partkey`.`l_shipinstruct` = 'deliver in person')) or ((`part`.`p_partkey` = `lineitem__what_if_gsi_l_partkey`.`l_partkey`) and (`part`.`p_brand` = 'brand#23') and (`part`.`p_container` in('med bag', 'med box', 'med pkg', 'med pack')) and (`lineitem__what_if_gsi_l_partkey`.`l_quantity` >= 10) and (`lineitem__what_if_gsi_l_partkey`.`l_quantity` <= (20 + 10)) and (`part`.`p_size` between 1 and 10) and (`lineitem__what_if_gsi_l_partkey`.`l_shipmode` in('air', 'air reg')) and (`lineitem__what_if_gsi_l_partkey`.`l_shipinstruct` = 'deliver in person')) or ((`part`.`p_partkey` = `lineitem__what_if_gsi_l_partkey`.`l_partkey`) and (`part`.`p_brand` = 'brand#34') and (`part`.`p_container` in('lg case', 'lg box', 'lg pack', 'lg pkg')) and (`lineitem__what_if_gsi_l_partkey`.`l_quantity` >= 20) and (`lineitem__what_if_gsi_l_partkey`.`l_quantity` <= (20 + 10)) and (`part`.`p_size` between 1 and 15) and (`lineitem__what_if_gsi_l_partkey`.`l_shipmode` in('air', 'air reg')) and (`lineitem__what_if_gsi_l_partkey`.`l_shipinstruct` = 'deliver in person')))) where ((((`part`.`p_brand` = 'brand#12') and (`part`.`p_container` in('sm case', 'sm box', 'sm pack', 'sm pkg')) and (`part`.`p_size` between 1 and 5)) or ((`part`.`p_brand` = 'brand#23') and (`part`.`p_container` in('med bag', 'med box', 'med pkg', 'med pack')) and (`part`.`p_size` between 1 and 10)) or ((`part`.`p_brand` = 'brand#34') and (`part`.`p_container` in('lg case', 'lg box', 'lg pack', 'lg pkg')) and (`part`.`p_size` between 1 and 15))) and (((`lineitem__what_if_gsi_l_partkey`.`l_quantity` >= 1) and (`lineitem__what_if_gsi_l_partkey`.`l_quantity` <= (1 + 10)) and (`lineitem__what_if_gsi_l_partkey`.`l_shipmode` in('air', 'air reg')) and (`lineitem__what_if_gsi_l_partkey`.`l_shipinstruct` = 'deliver in person')) or ((`lineitem__what_if_gsi_l_partkey`.`l_quantity` >= 10) and (`lineitem__what_if_gsi_l_partkey`.`l_quantity` <= (20 + 10)) and (`lineitem__what_if_gsi_l_partkey`.`l_shipmode` in('air', 'air reg')) and (`lineitem__what_if_gsi_l_partkey`.`l_shipinstruct` = 'deliver in person')) or ((`lineitem__what_if_gsi_l_partkey`.`l_quantity` >= 20) and (`lineitem__what_if_gsi_l_partkey`.`l_quantity` <= (20 + 10)) and (`lineitem__what_if_gsi_l_partkey`.`l_shipmode` in('air', 'air reg')) and (`lineitem__what_if_gsi_l_partkey`.`l_shipinstruct` = 'deliver in person'))))")
@@ -100,7 +103,8 @@
 - sql: |
     select * from orders where o_custkey = 1;
   plan: |
-    indexscan(tables="optest_0001.orders__what_if_gsi_o_custkey", sql="select `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders__what_if_gsi_o_custkey` as `orders__what_if_gsi_o_custkey` where (`o_custkey` = 1)")
+
+    indexscan(tables="optest_0001.orders__what_if_gsi_o_custkey", sql="select `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders__what_if_gsi_o_custkey` as `orders__what_if_gsi_o_custkey` force index(`orders__what_if_o_custkey`) where (`o_custkey` = 1)")
 
 -
   sql: |
@@ -117,24 +121,27 @@
         bkajoin(condition="k1 = k1 and k = k1", type="inner")
           bkajoin(condition="k1 = k", type="inner")
             mergesort(sort="id asc")
-              logicalview(tables="[0000-0003].test_index_join", shardcount=4, sql="select `id`, `k` from `test_index_join` as `test_index_join` order by `id`")
+              logicalview(tables="[0000-0003].test_index_join", shardcount=4, sql="select `id`, `k` from `test_index_join` as `test_index_join` force index(`primary`) order by `id`")
             gather(concurrent=true)
-              indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1` where (`k1` in (...))")
+              indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1` force index(`test_index__what_if_k1`) where (`k1` in (...))")
           gather(concurrent=true)
-            indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1` where (`k1` in (...))")
+            indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1` force index(`test_index__what_if_k1`) where (`k1` in (...))")
 
 -
   sql: |
     select * from orders where o_comment != 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq'  and o_custkey in (select c_custkey from customer where c_name = 'Customer#00000112')
 
   plan: |
+
     gather(concurrent=true)
       indexscan(tables="[0000-0003].orders__what_if_gsi_o_custkey_[00-15],customer_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders__what_if_gsi_o_custkey` as `orders__what_if_gsi_o_custkey` where ((`o_comment` <> 'debkaz9t2gdu00wqkyrvnvp3rlrqrp32mil2b4kq') and (`o_custkey` in (select `c_custkey` from `customer` as `customer` where (`c_name` = 'customer#00000112'))))")
+
 -
   sql: |
     SELECT * FROM customer left JOIN (select * from orders where o_comment != 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') a ON o_custkey = c_custkey  WHERE c_name = 'Customer#00000112'
 
   plan: |
+
     gather(concurrent=true)
       indexscan(tables="[0000-0003].customer_[00-15],orders__what_if_gsi_o_custkey_[00-15]", shardcount=16, sql="select `customer`.`c_custkey`, `customer`.`c_name`, `customer`.`c_address`, `customer`.`c_nationkey`, `customer`.`c_phone`, `customer`.`c_acctbal`, `customer`.`c_mktsegment`, `customer`.`c_comment`, `t0`.`o_orderkey`, `t0`.`o_custkey`, `t0`.`o_orderstatus`, `t0`.`o_totalprice`, `t0`.`o_orderdate`, `t0`.`o_orderpriority`, `t0`.`o_clerk`, `t0`.`o_shippriority`, `t0`.`o_comment` from `customer` as `customer` left join (select `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders__what_if_gsi_o_custkey` as `orders__what_if_gsi_o_custkey` where (`o_comment` <> 'debkaz9t2gdu00wqkyrvnvp3rlrqrp32mil2b4kq')) as `t0` on (`customer`.`c_custkey` = `t0`.`o_custkey`) where (`customer`.`c_name` = 'customer#00000112')")
 
@@ -143,41 +150,26 @@
     SELECT * FROM customer where c_custkey in (select o_custkey from orders where o_comment != 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') and c_name = 'Customer#00000112'
 
   plan: |
+
     gather(concurrent=true)
       logicalview(tables="[0000-0003].customer_[00-15],orders__what_if_gsi_o_custkey_[00-15]", shardcount=16, sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` from `customer` as `customer` where ((`c_name` = 'customer#00000112') and (`c_custkey` in (select `o_custkey` from `orders__what_if_gsi_o_custkey` as `orders__what_if_gsi_o_custkey` where (`o_comment` <> 'debkaz9t2gdu00wqkyrvnvp3rlrqrp32mil2b4kq'))))")
 
-  # 3. order by 利用索引的顺序
 - sql: |
     select * from test_index order by k1 limit 10;
 
   plan: |
+
     mergesort(sort="k1 asc", offset=0, fetch=10)
-      indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1` order by `k1` limit 10")
+      indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1` force index(`test_index__what_if_k1`) order by `k1` limit 10")
 
 - sql: |
     select * from test_index order by k2 limit 10;
 
   plan: |
+
     mergesort(sort="k2 asc", offset=0, fetch=10)
-      indexscan(tables="[0000-0003].test_index__what_if_gsi_k2", shardcount=4, sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index__what_if_gsi_k2` as `test_index__what_if_gsi_k2` order by `k2` limit 10")
-
-  # 1.3. GSI DO NOT SUPPORT Index Merge recommendation
-#- sql: |
-#    select * from test_index where k2 = 10 or k1 = 10;
-#
-#  plan: |
-#    Project(id="id", k1="k1", k2="k2", value="value", d1="d1", d2="d2", d3="d3", d4="d4", d5="d5")
-#      BKAJoin(condition="id = id", type="inner")
-#        HashAgg(group="id")
-#          UnionAll(concurrent=true)
-#            Gather(concurrent=true)
-#              IndexScan(tables="optest_0000.test_index__what_if_gsi_k2", sql="SELECT `id` FROM `test_index__what_if_gsi_k2` AS `test_index__what_if_gsi_k2` WHERE (`k2` = 10)")
-#            Gather(concurrent=true)
-#              IndexScan(tables="optest_0000.test_index__what_if_gsi_k1", sql="SELECT `id` FROM `test_index__what_if_gsi_k1` AS `test_index__what_if_gsi_k1` WHERE (`k1` = 10)")
-#        Gather(concurrent=true)
-#          LogicalView(tables="[0000-0003].test_index", shardCount=4, sql="SELECT `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` FROM `test_index` AS `test_index` WHERE (((`k2` = 10) OR (`k1` = 10)) AND (`id` IN (...)))")
-
-  # 6. MIN/MAX 聚合函数利用索引
+      indexscan(tables="[0000-0003].test_index__what_if_gsi_k2", shardcount=4, sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index__what_if_gsi_k2` as `test_index__what_if_gsi_k2` force index(`test_index__what_if_k2`) order by `k2` limit 10")
+
 - sql: |
     select min(k1), max(k1) from test_index;
 
@@ -185,13 +177,11 @@
     hashagg(min(k1)="min(min(k1))", max(k1)="max(max(k1))")
       gather(concurrent=true)
         indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select min(`k1`) as `min(k1)`, max(`k1`) as `max(k1)` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1`")
-
-  # 7. GSI join index
 - sql: |
     /*+TDDL:cmd_extra(enable_post_planner=false)*/select a.*, b.k2,b.value from test_index a join test_index b on a.k1 = b.k2 where a.id = 1;
 
   plan: |
     bkajoin(condition="k2 = k1", type="inner")
-      logicalview(tables="optest_0001.test_index", sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index` as `test_index` where (`id` = 1)")
+      logicalview(tables="optest_0001.test_index", sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index` as `test_index` force index(`primary`) where (`id` = 1)")
       gather(concurrent=true)
-        indexscan(tables="[0000-0003].test_index__what_if_gsi_k2", shardcount=4, sql="select `k2`, `value` from `test_index__what_if_gsi_k2` as `test_index__what_if_gsi_k2` where (`k2` in (...))")
\ No newline at end of file
+        indexscan(tables="[0000-0003].test_index__what_if_gsi_k2", shardcount=4, sql="select `k2`, `value` from `test_index__what_if_gsi_k2` as `test_index__what_if_gsi_k2` force index(`test_index__what_if_k2`) where (`k2` in (...))")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/GlobalIndexAdvisorPlanTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/GlobalIndexAdvisorPlanTest.yml
index 136eaea63..2d71a82ee 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/GlobalIndexAdvisorPlanTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/GlobalIndexAdvisorPlanTest.yml
@@ -11,6 +11,7 @@
          WHERE l_partkey = p_partkey);
 
   plan: |
+
     project(avg_yearly="$f0 / 7.0")
       hashagg($f0="sum(l_extendedprice)")
         filter(condition="l_quantity < 0.2 * f16w0$o0")
@@ -21,7 +22,7 @@
               project(l_partkey="l_partkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice")
                 bkajoin(condition="l_linenumber = l_linenumber and l_orderkey = l_orderkey", type="inner")
                   gather(concurrent=true)
-                    indexscan(tables="[0000-0003].lineitem__what_if_gsi_l_partkey_[00-15]", shardcount=16, sql="select `l_linenumber`, `l_orderkey`, `l_partkey` from `lineitem__what_if_gsi_l_partkey` as `lineitem__what_if_gsi_l_partkey` where (`l_partkey` in (...))")
+                    indexscan(tables="[0000-0003].lineitem__what_if_gsi_l_partkey_[00-15]", shardcount=16, sql="select `l_linenumber`, `l_orderkey`, `l_partkey` from `lineitem__what_if_gsi_l_partkey` as `lineitem__what_if_gsi_l_partkey` force index(`lineitem__what_if_l_partkey`) where (`l_partkey` in (...))")
                   gather(concurrent=true)
                     logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_linenumber`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem` where (((`l_linenumber`, `l_orderkey`)) in (...))")
 
@@ -56,29 +57,30 @@
       value desc;
 
   plan: |
-    MemSort(sort="value DESC")
-      Project(ps_partkey="ps_partkey", value="value")
-        NlJoin(condition="value > $f0 * 0.0001", type="inner")
-          HashAgg(group="ps_partkey", value="SUM(__*__)")
-            BKAJoin(condition="ps_suppkey = s_suppkey", type="inner")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].supplier_[00-15],nation", shardCount=16, sql="SELECT `supplier`.`s_suppkey` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) AND (`nation`.`n_name` = 'GERMANY'))")
-              Project(ps_partkey="ps_partkey", ps_suppkey="ps_suppkey", __*__="ps_supplycost * ps_availqty")
-                BKAJoin(condition="ps_partkey = ps_partkey AND ps_suppkey = ps_suppkey", type="inner")
-                  Gather(concurrent=true)
-                    IndexScan(tables="[0000-0003].partsupp__what_if_gsi_ps_suppkey_[00-15]", shardCount=16, sql="SELECT `ps_partkey`, `ps_suppkey` FROM `partsupp__what_if_gsi_ps_suppkey` AS `partsupp__what_if_gsi_ps_suppkey` WHERE (`ps_suppkey` IN (...))")
-                  Gather(concurrent=true)
-                    LogicalView(tables="[0000-0003].partsupp_[00-15]", shardCount=16, sql="SELECT `ps_partkey`, `ps_suppkey`, `ps_availqty`, `ps_supplycost` FROM `partsupp` AS `partsupp` WHERE (((`ps_partkey`, `ps_suppkey`)) IN (...))")
-          HashAgg($f0="SUM(__*__)")
-            BKAJoin(condition="ps_suppkey = s_suppkey", type="inner")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].supplier_[00-15],nation", shardCount=16, sql="SELECT `supplier`.`s_suppkey` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) AND (`nation`.`n_name` = 'GERMANY'))")
-              Project(ps_suppkey="ps_suppkey", __*__="ps_supplycost * ps_availqty")
-                BKAJoin(condition="ps_partkey = ps_partkey AND ps_suppkey = ps_suppkey", type="inner")
-                  Gather(concurrent=true)
-                    IndexScan(tables="[0000-0003].partsupp__what_if_gsi_ps_suppkey_[00-15]", shardCount=16, sql="SELECT `ps_partkey`, `ps_suppkey` FROM `partsupp__what_if_gsi_ps_suppkey` AS `partsupp__what_if_gsi_ps_suppkey` WHERE (`ps_suppkey` IN (...))")
-                  Gather(concurrent=true)
-                    LogicalView(tables="[0000-0003].partsupp_[00-15]", shardCount=16, sql="SELECT `ps_partkey`, `ps_suppkey`, `ps_availqty`, `ps_supplycost` FROM `partsupp` AS `partsupp` WHERE (((`ps_partkey`, `ps_suppkey`)) IN (...))")
+
+    memsort(sort="value desc")
+      project(ps_partkey="ps_partkey", value="value")
+        nljoin(condition="value > $f0 * 0.0001", type="inner")
+          hashagg(group="ps_partkey", value="sum(__*__)")
+            bkajoin(condition="ps_suppkey = s_suppkey", type="inner")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany'))")
+              project(ps_partkey="ps_partkey", ps_suppkey="ps_suppkey", __*__="ps_supplycost * ps_availqty")
+                bkajoin(condition="ps_partkey = ps_partkey and ps_suppkey = ps_suppkey", type="inner")
+                  gather(concurrent=true)
+                    indexscan(tables="[0000-0003].partsupp__what_if_gsi_ps_suppkey_[00-15]", shardcount=16, sql="select `ps_partkey`, `ps_suppkey` from `partsupp__what_if_gsi_ps_suppkey` as `partsupp__what_if_gsi_ps_suppkey` force index(`partsupp__what_if_ps_suppkey`) where (`ps_suppkey` in (...))")
+                  gather(concurrent=true)
+                    logicalview(tables="[0000-0003].partsupp_[00-15]", shardcount=16, sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty`, `ps_supplycost` from `partsupp` as `partsupp` force index(`primary`) where (((`ps_partkey`, `ps_suppkey`)) in (...))")
+          hashagg($f0="sum(__*__)")
+            bkajoin(condition="ps_suppkey = s_suppkey", type="inner")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany'))")
+              project(ps_suppkey="ps_suppkey", __*__="ps_supplycost * ps_availqty")
+                bkajoin(condition="ps_partkey = ps_partkey and ps_suppkey = ps_suppkey", type="inner")
+                  gather(concurrent=true)
+                    indexscan(tables="[0000-0003].partsupp__what_if_gsi_ps_suppkey_[00-15]", shardcount=16, sql="select `ps_partkey`, `ps_suppkey` from `partsupp__what_if_gsi_ps_suppkey` as `partsupp__what_if_gsi_ps_suppkey` force index(`partsupp__what_if_ps_suppkey`) where (`ps_suppkey` in (...))")
+                  gather(concurrent=true)
+                    logicalview(tables="[0000-0003].partsupp_[00-15]", shardcount=16, sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty`, `ps_supplycost` from `partsupp` as `partsupp` force index(`primary`) where (((`ps_partkey`, `ps_suppkey`)) in (...))")
 
 - sql: |
     select
@@ -114,6 +116,7 @@
     );
 
   plan: |
+
     hashagg(revenue="sum(__*__)")
       bkajoin(condition="p_partkey = l_partkey and ((p_partkey = l_partkey and = and in and >= and <= and between asymmetric and in and =) or (p_partkey = l_partkey and =4 and in5 and >=6 and <=7 and between asymmetric6 and in and =) or (p_partkey = l_partkey and =7 and in8 and >=8 and <=7 and between asymmetric9 and in and =))", type="inner")
         gather(concurrent=true)
@@ -121,18 +124,19 @@
         project(l_partkey="l_partkey", __*__="l_extendedprice * 1 - l_discount", >=="l_quantity >= 1", <=="l_quantity <= 1 + 10", in="l_shipmode in row('air', 'air reg')", =="l_shipinstruct = 'deliver in person'", >=6="l_quantity >= 10", <=7="l_quantity <= 20 + 10", >=8="l_quantity >= 20")
           bkajoin(condition="l_linenumber = l_linenumber and l_orderkey = l_orderkey", type="inner")
             gather(concurrent=true)
-              indexscan(tables="[0000-0003].lineitem__what_if_gsi_l_partkey_[00-15]", shardcount=16, sql="select `l_linenumber`, `l_orderkey`, `l_partkey` from `lineitem__what_if_gsi_l_partkey` as `lineitem__what_if_gsi_l_partkey` where (`l_partkey` in (...))")
+              indexscan(tables="[0000-0003].lineitem__what_if_gsi_l_partkey_[00-15]", shardcount=16, sql="select `l_linenumber`, `l_orderkey`, `l_partkey` from `lineitem__what_if_gsi_l_partkey` as `lineitem__what_if_gsi_l_partkey` force index(`lineitem__what_if_l_partkey`) where (`l_partkey` in (...))")
             gather(concurrent=true)
               logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_shipinstruct`, `l_shipmode` from `lineitem` as `lineitem` where ((((`l_quantity` >= 1) and (`l_quantity` <= (1 + 10)) and (`l_shipmode` in('air', 'air reg')) and (`l_shipinstruct` = 'deliver in person')) or ((`l_quantity` >= 10) and (`l_quantity` <= (20 + 10)) and (`l_shipmode` in('air', 'air reg')) and (`l_shipinstruct` = 'deliver in person')) or ((`l_quantity` >= 20) and (`l_quantity` <= (20 + 10)) and (`l_shipmode` in('air', 'air reg')) and (`l_shipinstruct` = 'deliver in person'))) and (((`l_linenumber`, `l_orderkey`)) in (...)))")
 
 - sql: |
     select * from orders where o_custkey = 1;
   plan: |
-    Project(o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderstatus="o_orderstatus", o_totalprice="o_totalprice", o_orderdate="o_orderdate", o_orderpriority="o_orderpriority", o_clerk="o_clerk", o_shippriority="o_shippriority", o_comment="o_comment")
+
+    project(o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderstatus="o_orderstatus", o_totalprice="o_totalprice", o_orderdate="o_orderdate", o_orderpriority="o_orderpriority", o_clerk="o_clerk", o_shippriority="o_shippriority", o_comment="o_comment")
       bkajoin(condition="o_orderkey = o_orderkey", type="inner")
-        IndexScan(tables="optest_0001.orders__what_if_gsi_o_custkey", sql="SELECT `o_custkey`, `o_orderkey` FROM `orders__what_if_gsi_o_custkey` AS `orders__what_if_gsi_o_custkey` WHERE (`o_custkey` = 1)")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_orderkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` FROM `orders` AS `orders` WHERE ((`o_custkey` = 1) AND (`o_orderkey` IN (...)))")
+        indexscan(tables="optest_0001.orders__what_if_gsi_o_custkey", sql="select `o_custkey`, `o_orderkey` from `orders__what_if_gsi_o_custkey` as `orders__what_if_gsi_o_custkey` force index(`orders__what_if_o_custkey`) where (`o_custkey` = 1)")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders` as `orders` force index(`primary`) where ((`o_custkey` = 1) and (`o_orderkey` in (...)))")
 
 -
   sql: |
@@ -149,119 +153,108 @@
         bkajoin(condition="k1 = k1 and k = k1", type="inner")
           bkajoin(condition="k1 = k", type="inner")
             mergesort(sort="id asc")
-              logicalview(tables="[0000-0003].test_index_join", shardcount=4, sql="select `id`, `k` from `test_index_join` as `test_index_join` order by `id`")
+              logicalview(tables="[0000-0003].test_index_join", shardcount=4, sql="select `id`, `k` from `test_index_join` as `test_index_join` force index(`primary`) order by `id`")
             project(id="id", k1="k1", k2="k2", value="value", d1="d1", d2="d2", d3="d3", d4="d4", d5="d5")
               bkajoin(condition="id = id", type="inner")
                 gather(concurrent=true)
-                  indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select `id`, `k1` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1` where (`k1` in (...))")
+                  indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select `id`, `k1` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1` force index(`test_index__what_if_k1`) where (`k1` in (...))")
                 gather(concurrent=true)
-                  logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index` as `test_index` where (`id` in (...))")
+                  logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index` as `test_index` force index(`primary`) where (`id` in (...))")
           project(id="id", k1="k1", k2="k2", value="value", d1="d1", d2="d2", d3="d3", d4="d4", d5="d5")
             bkajoin(condition="id = id", type="inner")
               gather(concurrent=true)
-                indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select `id`, `k1` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1` where (`k1` in (...))")
+                indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select `id`, `k1` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1` force index(`test_index__what_if_k1`) where (`k1` in (...))")
               gather(concurrent=true)
-                logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index` as `test_index` where (`id` in (...))")
+                logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index` as `test_index` force index(`primary`) where (`id` in (...))")
 
 -
   sql: |
     select * from orders where o_comment != 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq'  and o_custkey in (select c_custkey from customer where c_name = 'Customer#00000112')
 
   plan: |
-    MaterializedSemiJoin(condition="o_custkey = c_custkey", type="semi")
-      Project(o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderstatus="o_orderstatus", o_totalprice="o_totalprice", o_orderdate="o_orderdate", o_orderpriority="o_orderpriority", o_clerk="o_clerk", o_shippriority="o_shippriority", o_comment="o_comment")
+
+    materializedsemijoin(condition="o_custkey = c_custkey", type="semi")
+      project(o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderstatus="o_orderstatus", o_totalprice="o_totalprice", o_orderdate="o_orderdate", o_orderpriority="o_orderpriority", o_clerk="o_clerk", o_shippriority="o_shippriority", o_comment="o_comment")
         bkajoin(condition="o_orderkey = o_orderkey", type="inner")
-          Gather(concurrent=true)
-            IndexScan(tables="[0000-0003].orders__what_if_gsi_o_custkey_[00-15]", shardCount=16, sql="SELECT `o_custkey`, `o_orderkey` FROM `orders__what_if_gsi_o_custkey` AS `orders__what_if_gsi_o_custkey` WHERE (`o_custkey` IN (...))")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_orderkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` FROM `orders` AS `orders` WHERE ((`o_comment` <> 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') AND (`o_orderkey` IN (...)))")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey` FROM `customer` AS `customer` WHERE (`c_name` = 'Customer#00000112')")
+          gather(concurrent=true)
+            indexscan(tables="[0000-0003].orders__what_if_gsi_o_custkey_[00-15]", shardcount=16, sql="select `o_custkey`, `o_orderkey` from `orders__what_if_gsi_o_custkey` as `orders__what_if_gsi_o_custkey` force index(`orders__what_if_o_custkey`) where (`o_custkey` in (...))")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders` as `orders` force index(`primary`) where ((`o_comment` <> 'debkaz9t2gdu00wqkyrvnvp3rlrqrp32mil2b4kq') and (`o_orderkey` in (...)))")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey` from `customer` as `customer` where (`c_name` = 'customer#00000112')")
 
 -
   sql: |
     SELECT * FROM customer left JOIN (select * from orders where o_comment != 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') a ON o_custkey = c_custkey  WHERE c_name = 'Customer#00000112'
 
   plan: |
-    BKAJoin(condition="o_custkey = c_custkey", type="left")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` FROM `customer` AS `customer` WHERE (`c_name` = 'Customer#00000112')")
-      Project(o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderstatus="o_orderstatus", o_totalprice="o_totalprice", o_orderdate="o_orderdate", o_orderpriority="o_orderpriority", o_clerk="o_clerk", o_shippriority="o_shippriority", o_comment="o_comment")
+
+    bkajoin(condition="o_custkey = c_custkey", type="left")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` from `customer` as `customer` where (`c_name` = 'customer#00000112')")
+      project(o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderstatus="o_orderstatus", o_totalprice="o_totalprice", o_orderdate="o_orderdate", o_orderpriority="o_orderpriority", o_clerk="o_clerk", o_shippriority="o_shippriority", o_comment="o_comment")
         bkajoin(condition="o_orderkey = o_orderkey", type="inner")
-          Gather(concurrent=true)
-            IndexScan(tables="[0000-0003].orders__what_if_gsi_o_custkey_[00-15]", shardCount=16, sql="SELECT `o_custkey`, `o_orderkey` FROM `orders__what_if_gsi_o_custkey` AS `orders__what_if_gsi_o_custkey` WHERE (`o_custkey` IN (...))")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_orderkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` FROM `orders` AS `orders` WHERE ((`o_comment` <> 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') AND (`o_orderkey` IN (...)))")
+          gather(concurrent=true)
+            indexscan(tables="[0000-0003].orders__what_if_gsi_o_custkey_[00-15]", shardcount=16, sql="select `o_custkey`, `o_orderkey` from `orders__what_if_gsi_o_custkey` as `orders__what_if_gsi_o_custkey` force index(`orders__what_if_o_custkey`) where (`o_custkey` in (...))")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders` as `orders` force index(`primary`) where ((`o_comment` <> 'debkaz9t2gdu00wqkyrvnvp3rlrqrp32mil2b4kq') and (`o_orderkey` in (...)))")
 
 -
   sql: |
     SELECT * FROM customer where c_custkey in (select o_custkey from orders where o_comment != 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') and c_name = 'Customer#00000112'
 
   plan: |
-    SemiBKAJoin(condition="c_custkey = o_custkey", type="semi")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` FROM `customer` AS `customer` WHERE (`c_name` = 'Customer#00000112')")
-      Project(o_custkey="o_custkey")
+
+    semibkajoin(condition="c_custkey = o_custkey", type="semi")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` from `customer` as `customer` where (`c_name` = 'customer#00000112')")
+      project(o_custkey="o_custkey")
         bkajoin(condition="o_orderkey = o_orderkey", type="inner")
-          Gather(concurrent=true)
-            IndexScan(tables="[0000-0003].orders__what_if_gsi_o_custkey_[00-15]", shardCount=16, sql="SELECT `o_custkey`, `o_orderkey` FROM `orders__what_if_gsi_o_custkey` AS `orders__what_if_gsi_o_custkey` WHERE (`o_custkey` IN (...))")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_orderkey` FROM `orders` AS `orders` WHERE ((`o_comment` <> 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') AND (`o_orderkey` IN (...)))")
+          gather(concurrent=true)
+            indexscan(tables="[0000-0003].orders__what_if_gsi_o_custkey_[00-15]", shardcount=16, sql="select `o_custkey`, `o_orderkey` from `orders__what_if_gsi_o_custkey` as `orders__what_if_gsi_o_custkey` force index(`orders__what_if_o_custkey`) where (`o_custkey` in (...))")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey` from `orders` as `orders` force index(`primary`) where ((`o_comment` <> 'debkaz9t2gdu00wqkyrvnvp3rlrqrp32mil2b4kq') and (`o_orderkey` in (...)))")
 
-  # 3. order by 利用索引的顺序
 - sql: |
     select * from test_index order by k1 limit 10;
 
   plan: |
-    Project(id="id", k1="k1", k2="k2", value="value", d1="d1", d2="d2", d3="d3", d4="d4", d5="d5")
-      BKAJoin(condition="id = id", type="inner")
-        MergeSort(sort="k1 ASC", offset=0, fetch=10)
-          IndexScan(tables="[0000-0003].test_index__what_if_gsi_k1", shardCount=4, sql="SELECT `id`, `k1` FROM `test_index__what_if_gsi_k1` AS `test_index__what_if_gsi_k1` ORDER BY `k1` LIMIT 10")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_index", shardCount=4, sql="SELECT `id`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` FROM `test_index` AS `test_index` WHERE (`id` IN (...))")
+
+    project(id="id", k1="k1", k2="k2", value="value", d1="d1", d2="d2", d3="d3", d4="d4", d5="d5")
+      bkajoin(condition="id = id", type="inner")
+        mergesort(sort="k1 asc", offset=0, fetch=10)
+          indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select `id`, `k1` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1` force index(`test_index__what_if_k1`) order by `k1` limit 10")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index` as `test_index` force index(`primary`) where (`id` in (...))")
 
 - sql: |
     select * from test_index order by k2 limit 10;
 
   plan: |
-    Project(id="id", k1="k1", k2="k2", value="value", d1="d1", d2="d2", d3="d3", d4="d4", d5="d5")
-      BKAJoin(condition="id = id", type="inner")
-        MergeSort(sort="k2 ASC", offset=0, fetch=10)
-          IndexScan(tables="[0000-0003].test_index__what_if_gsi_k2", shardCount=4, sql="SELECT `id`, `k2` FROM `test_index__what_if_gsi_k2` AS `test_index__what_if_gsi_k2` ORDER BY `k2` LIMIT 10")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_index", shardCount=4, sql="SELECT `id`, `k1`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` FROM `test_index` AS `test_index` WHERE (`id` IN (...))")
-
-  # 1.3. GSI DO NOT SUPPORT Index Merge recommendation
-#- sql: |
-#    select * from test_index where k2 = 10 or k1 = 10;
-#
-#  plan: |
-#    Project(id="id", k1="k1", k2="k2", value="value", d1="d1", d2="d2", d3="d3", d4="d4", d5="d5")
-#      BKAJoin(condition="id = id", type="inner")
-#        Gather(concurrent=true)
-#          IndexScan(tables="optest_0000.test_index__what_if_gsi_k1_k2", sql="SELECT `id`, `k1`, `k2` FROM `test_index__what_if_gsi_k1_k2` AS `test_index__what_if_gsi_k1_k2` WHERE ((`k2` = 10) OR (`k1` = 10))")
-#        Gather(concurrent=true)
-#          LogicalView(tables="[0000-0003].test_index", shardCount=4, sql="SELECT `id`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` FROM `test_index` AS `test_index` WHERE (((`k2` = 10) OR (`k1` = 10)) AND (`id` IN (...)))")
-
-  # 6. MIN/MAX 聚合函数利用索引
+
+    project(id="id", k1="k1", k2="k2", value="value", d1="d1", d2="d2", d3="d3", d4="d4", d5="d5")
+      bkajoin(condition="id = id", type="inner")
+        mergesort(sort="k2 asc", offset=0, fetch=10)
+          indexscan(tables="[0000-0003].test_index__what_if_gsi_k2", shardcount=4, sql="select `id`, `k2` from `test_index__what_if_gsi_k2` as `test_index__what_if_gsi_k2` force index(`test_index__what_if_k2`) order by `k2` limit 10")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k1`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index` as `test_index` force index(`primary`) where (`id` in (...))")
+
 - sql: |
     select min(k1), max(k1) from test_index;
 
   plan: |
-    HashAgg(min(k1)="MIN(min(k1))", max(k1)="MAX(max(k1))")
-      Gather(concurrent=true)
-        IndexScan(tables="[0000-0003].test_index__what_if_gsi_k1", shardCount=4, sql="SELECT MIN(`k1`) AS `min(k1)`, MAX(`k1`) AS `max(k1)` FROM `test_index__what_if_gsi_k1` AS `test_index__what_if_gsi_k1`")
-
-  # 7. GSI join index
+    hashagg(min(k1)="min(min(k1))", max(k1)="max(max(k1))")
+      gather(concurrent=true)
+        indexscan(tables="[0000-0003].test_index__what_if_gsi_k1", shardcount=4, sql="select min(`k1`) as `min(k1)`, max(`k1`) as `max(k1)` from `test_index__what_if_gsi_k1` as `test_index__what_if_gsi_k1`")
 - sql: |
     /*+TDDL:cmd_extra(enable_post_planner=false)*/select a.*, b.k2,b.value from test_index a join test_index b on a.k1 = b.k2 where a.id = 1;
 
   plan: |
     bkajoin(condition="k2 = k1", type="inner")
-      logicalview(tables="optest_0001.test_index", sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index` as `test_index` where (`id` = 1)")
+      logicalview(tables="optest_0001.test_index", sql="select `id`, `k1`, `k2`, `value`, `d1`, `d2`, `d3`, `d4`, `d5` from `test_index` as `test_index` force index(`primary`) where (`id` = 1)")
       project(k2="k2", value="value")
         bkajoin(condition="id = id", type="inner")
           gather(concurrent=true)
-            indexscan(tables="[0000-0003].test_index__what_if_gsi_k2", shardcount=4, sql="select `id`, `k2` from `test_index__what_if_gsi_k2` as `test_index__what_if_gsi_k2` where (`k2` in (...))")
+            indexscan(tables="[0000-0003].test_index__what_if_gsi_k2", shardcount=4, sql="select `id`, `k2` from `test_index__what_if_gsi_k2` as `test_index__what_if_gsi_k2` force index(`test_index__what_if_k2`) where (`k2` in (...))")
           gather(concurrent=true)
-            logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `value` from `test_index` as `test_index` where (`id` in (...))")
+            logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `value` from `test_index` as `test_index` force index(`primary`) where (`id` in (...))")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/LocalIndexAdvisorPlanTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/LocalIndexAdvisorPlanTest.yml
index 815179079..9032d2558 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/LocalIndexAdvisorPlanTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/advisor/LocalIndexAdvisorPlanTest.yml
@@ -11,6 +11,7 @@
          WHERE l_partkey = p_partkey);
 
   plan: |
+
     project(avg_yearly="$f0 / 7.0")
       hashagg($f0="sum(l_extendedprice)")
         filter(condition="l_quantity < 0.2 * f16w0$o0")
@@ -19,7 +20,7 @@
               gather(concurrent=true)
                 logicalview(tables="[0000-0003].part_[00-15]", shardcount=16, sql="select `p_partkey` from `part` as `part` where ((`p_container` = 'med box') and (`p_brand` = 'brand#23'))")
               gather(concurrent=true)
-                logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem` where (`l_partkey` in (...))")
+                logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem` force index(`lineitem__what_if_l_partkey`) where (`l_partkey` in (...))")
 
 - sql: |
     select * from (select
@@ -52,21 +53,22 @@
       value desc;
 
   plan: |
-    MemSort(sort="value DESC")
-      Project(ps_partkey="ps_partkey", value="value")
-        NlJoin(condition="value > $f0 * 0.0001", type="inner")
-          HashAgg(group="ps_partkey", value="SUM(__*__)")
-            BKAJoin(condition="ps_suppkey = s_suppkey", type="inner")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].supplier_[00-15],nation", shardCount=16, sql="SELECT `supplier`.`s_suppkey` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) AND (`nation`.`n_name` = 'GERMANY'))")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].partsupp_[00-15]", shardCount=16, sql="SELECT `ps_partkey`, `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) AS `__*__` FROM `partsupp` AS `partsupp` WHERE (`ps_suppkey` IN (...))")
-          HashAgg($f0="SUM(__*__)")
-            BKAJoin(condition="ps_suppkey = s_suppkey", type="inner")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].supplier_[00-15],nation", shardCount=16, sql="SELECT `supplier`.`s_suppkey` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) AND (`nation`.`n_name` = 'GERMANY'))")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].partsupp_[00-15]", shardCount=16, sql="SELECT `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) AS `__*__` FROM `partsupp` AS `partsupp` WHERE (`ps_suppkey` IN (...))")
+
+    memsort(sort="value desc")
+      project(ps_partkey="ps_partkey", value="value")
+        nljoin(condition="value > $f0 * 0.0001", type="inner")
+          hashagg(group="ps_partkey", value="sum(__*__)")
+            bkajoin(condition="ps_suppkey = s_suppkey", type="inner")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany'))")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].partsupp_[00-15]", shardcount=16, sql="select `ps_partkey`, `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) as `__*__` from `partsupp` as `partsupp` force index(`partsupp__what_if_ps_suppkey`) where (`ps_suppkey` in (...))")
+          hashagg($f0="sum(__*__)")
+            bkajoin(condition="ps_suppkey = s_suppkey", type="inner")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany'))")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].partsupp_[00-15]", shardcount=16, sql="select `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) as `__*__` from `partsupp` as `partsupp` force index(`partsupp__what_if_ps_suppkey`) where (`ps_suppkey` in (...))")
 
 - sql: |
     select
@@ -102,6 +104,7 @@
     );
 
   plan: |
+
     hashagg(revenue="sum(__*__)")
       bkajoin(condition="p_partkey = l_partkey and ((p_partkey = l_partkey and = and in and >= and <= and between asymmetric and in and =) or (p_partkey = l_partkey and =4 and in5 and >=6 and <=7 and between asymmetric6 and in and =) or (p_partkey = l_partkey and =7 and in8 and >=8 and <=7 and between asymmetric9 and in and =))", type="inner")
         gather(concurrent=true)
@@ -112,13 +115,15 @@
 - sql: |
     select * from orders where o_custkey = 1;
   plan: |
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` FROM `orders` AS `orders` WHERE (`o_custkey` = 1)")
+
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders` as `orders` force index(`orders__what_if_o_custkey`) where (`o_custkey` = 1)")
 
 - sql: |
     update orders set o_comment = 'xxx' where o_custkey = 1
   plan: |
-    LogicalModifyView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="UPDATE `orders` AS `orders` SET `o_comment` = 'xxx' WHERE (`o_custkey` = 1)")
+
+    logicalmodifyview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="update `orders` as `orders` force index(`orders__what_if_o_custkey`) set `o_comment` = 'xxx' where (`o_custkey` = 1)")
 
 -
   sql: |
@@ -135,83 +140,87 @@
         bkajoin(condition="k1 = k1 and k = k1", type="inner")
           bkajoin(condition="k1 = k", type="inner")
             mergesort(sort="id asc")
-              logicalview(tables="[0000-0003].test_index_join", shardcount=4, sql="select `id`, `k` from `test_index_join` as `test_index_join` order by `id`")
+              logicalview(tables="[0000-0003].test_index_join", shardcount=4, sql="select `id`, `k` from `test_index_join` as `test_index_join` force index(`primary`) order by `id`")
             gather(concurrent=true)
-              logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k1`, `k2`, `value` from `test_index` as `test_index` where (`k1` in (...))")
+              logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k1`, `k2`, `value` from `test_index` as `test_index` force index(`test_index__what_if_k1`) where (`k1` in (...))")
           gather(concurrent=true)
-            logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k1`, `k2`, `value` from `test_index` as `test_index` where (`k1` in (...))")
+            logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k1`, `k2`, `value` from `test_index` as `test_index` force index(`test_index__what_if_k1`) where (`k1` in (...))")
 
 -
   sql: |
     select * from orders where o_comment != 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq'  and o_custkey in (select c_custkey from customer where c_name = 'Customer#00000112')
 
   plan: |
-    MaterializedSemiJoin(condition="o_custkey = c_custkey", type="semi")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` FROM `orders` AS `orders` WHERE ((`o_comment` <> 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') AND (`o_custkey` IN (...)))")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey` FROM `customer` AS `customer` WHERE (`c_name` = 'Customer#00000112')")
+
+    materializedsemijoin(condition="o_custkey = c_custkey", type="semi")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders` as `orders` where ((`o_comment` <> 'debkaz9t2gdu00wqkyrvnvp3rlrqrp32mil2b4kq') and (`o_custkey` in (...)))")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey` from `customer` as `customer` force index(`customer__what_if_c_name`) where (`c_name` = 'customer#00000112')")
 
 -
   sql: |
     SELECT * FROM customer left JOIN (select * from orders where o_comment != 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') a ON o_custkey = c_custkey  WHERE c_name = 'Customer#00000112'
 
   plan: |
-    BKAJoin(condition="o_custkey = c_custkey", type="left")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` FROM `customer` AS `customer` WHERE (`c_name` = 'Customer#00000112')")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` FROM `orders` AS `orders` WHERE ((`o_comment` <> 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') AND (`o_custkey` IN (...)))")
+
+    bkajoin(condition="o_custkey = c_custkey", type="left")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` from `customer` as `customer` force index(`customer__what_if_c_name`) where (`c_name` = 'customer#00000112')")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders` as `orders` where ((`o_comment` <> 'debkaz9t2gdu00wqkyrvnvp3rlrqrp32mil2b4kq') and (`o_custkey` in (...)))")
 
 -
   sql: |
     SELECT * FROM customer where c_custkey in (select o_custkey from orders where o_comment != 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') and c_name = 'Customer#00000112'
 
   plan: |
-    SemiBKAJoin(condition="c_custkey = o_custkey", type="semi")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` FROM `customer` AS `customer` WHERE (`c_name` = 'Customer#00000112')")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_custkey` FROM `orders` AS `orders` WHERE ((`o_comment` <> 'DEBkaZ9T2gdU00WQkYrvnvp3Rlrqrp32mIl2b4kq') AND (`o_custkey` IN (...)))")
 
-  # 3. order by 利用索引的顺序
+    semibkajoin(condition="c_custkey = o_custkey", type="semi")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` from `customer` as `customer` force index(`customer__what_if_c_name`) where (`c_name` = 'customer#00000112')")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_custkey` from `orders` as `orders` where ((`o_comment` <> 'debkaz9t2gdu00wqkyrvnvp3rlrqrp32mil2b4kq') and (`o_custkey` in (...)))")
+
 - sql: |
     select * from test_index order by k1 limit 10;
 
   plan: |
-    MergeSort(sort="k1 ASC", offset=0, fetch=10)
-      LogicalView(tables="[0000-0003].test_index", shardCount=4, sql="SELECT `id`, `k1`, `k2`, `value` FROM `test_index` AS `test_index` ORDER BY `k1` LIMIT 10")
+
+    mergesort(sort="k1 asc", offset=0, fetch=10)
+      logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k1`, `k2`, `value` from `test_index` as `test_index` force index(`test_index__what_if_k1`) order by `k1` limit 10")
 
 - sql: |
     select * from test_index order by k2 limit 10;
 
   plan: |
-    MergeSort(sort="k2 ASC", offset=0, fetch=10)
-      LogicalView(tables="[0000-0003].test_index", shardCount=4, sql="SELECT `id`, `k1`, `k2`, `value` FROM `test_index` AS `test_index` ORDER BY `k2` LIMIT 10")
 
-  # 1.3. Index Merge
+    mergesort(sort="k2 asc", offset=0, fetch=10)
+      logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k1`, `k2`, `value` from `test_index` as `test_index` force index(`test_index__what_if_k2`) order by `k2` limit 10")
+
 - sql: |
     select * from test_index where k2 = 10 or k1 = 10;
 
   plan: |
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_index", shardCount=4, sql="SELECT `id`, `k1`, `k2`, `value` FROM `test_index` AS `test_index` WHERE ((`k2` = 10) OR (`k1` = 10))")
 
-  # 6. MIN/MAX 聚合函数利用索引
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `id`, `k1`, `k2`, `value` from `test_index` as `test_index` where ((`k2` = 10) or (`k1` = 10))")
+
 - sql: |
     select min(k1), min(k2), max(k1), max(k2) from test_index;
 
   plan: |
-    HashAgg(min(k1)="MIN(min(k1))", min(k2)="MIN(min(k2))", max(k1)="MAX(max(k1))", max(k2)="MAX(max(k2))")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_index", shardCount=4, sql="SELECT MIN(`k1`) AS `min(k1)`, MIN(`k2`) AS `min(k2)`, MAX(`k1`) AS `max(k1)`, MAX(`k2`) AS `max(k2)` FROM `test_index` AS `test_index`")
 
-  # 7. GSI join index
+    hashagg(min(k1)="min(min(k1))", min(k2)="min(min(k2))", max(k1)="max(max(k1))", max(k2)="max(max(k2))")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select min(`k1`) as `min(k1)`, min(`k2`) as `min(k2)`, max(`k1`) as `max(k1)`, max(`k2`) as `max(k2)` from `test_index` as `test_index`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_post_planner=false)*/select a.*, b.k2,b.value from test_index a join test_index b on a.k1 = b.k2 where a.id = 1;
 
   plan: |
-    BKAJoin(condition="k2 = k1", type="inner")
-      LogicalView(tables="optest_0001.test_index", sql="SELECT `id`, `k1`, `k2`, `value` FROM `test_index` AS `test_index` WHERE (`id` = 1)")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_index", shardCount=4, sql="SELECT `k2`, `value` FROM `test_index` AS `test_index` WHERE (`k2` IN (...))")
\ No newline at end of file
+
+    bkajoin(condition="k2 = k1", type="inner")
+      logicalview(tables="optest_0001.test_index", sql="select `id`, `k1`, `k2`, `value` from `test_index` as `test_index` force index(`primary`) where (`id` = 1)")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_index", shardcount=4, sql="select `k2`, `value` from `test_index` as `test_index` force index(`test_index__what_if_k2`) where (`k2` in (...))")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOIndexSelectionPruneTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOIndexSelectionPruneTest.yml
index 32a347dd1..b3c8477ed 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOIndexSelectionPruneTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOIndexSelectionPruneTest.yml
@@ -3,7 +3,7 @@ SQL:
       select k1 from test_index2 where d1 = '1' limit 1;
     plan: |
       mergesort(sort="", offset=0, fetch=1)
-        logicalview(tables="test_index2[p1,p2,p3,p4]", shardcount=4, sql="select `k1` from `test_index2` as `test_index2` where (`d1` = '1') limit 1")
+        logicalview(tables="test_index2[p1,p2,p3,p4]", shardcount=4, sql="select `k1` from `test_index2` as `test_index2` force index(`idx_d1`) where (`d1` = '1') limit 1")
   - sql: |
       /*+TDDL:cmd_extra(ENABLE_INDEX_SELECTION_PRUNE=false)*/select k1 from test_index2 where d1 = '1' limit 1;
     plan: |
@@ -33,12 +33,12 @@ SQL:
       select d3 from test_index2 where d1 = '1' limit 1;
     plan: |
       mergesort(sort="", offset=0, fetch=1)
-        logicalview(tables="test_index2[p1,p2,p3,p4]", shardcount=4, sql="select `d3` from `test_index2` as `test_index2` where (`d1` = '1') limit 1")
+        logicalview(tables="test_index2[p1,p2,p3,p4]", shardcount=4, sql="select `d3` from `test_index2` as `test_index2` force index(`idx_d1`) where (`d1` = '1') limit 1")
   - sql: |
       /*+TDDL:cmd_extra(ENABLE_INDEX_SELECTION_PRUNE=false)*/select d3 from test_index2 where d1 = '1' limit 1;
     plan: |
       mergesort(sort="", offset=0, fetch=1)
-        logicalview(tables="test_index2[p1,p2,p3,p4]", shardcount=4, sql="select `d3` from `test_index2` as `test_index2` where (`d1` = '1') limit 1")
+        logicalview(tables="test_index2[p1,p2,p3,p4]", shardcount=4, sql="select `d3` from `test_index2` as `test_index2` force index(`idx_d1`) where (`d1` = '1') limit 1")
   - sql: |
       select * from (select k1 from test_index2 where d1 = '1' limit 1) A join test_index2 B on A.k1 = B.k2;
     plan: |
@@ -50,7 +50,7 @@ SQL:
             gather(concurrent=true)
               indexscan(tables="idx_k1_k2_d2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `k1`, `k2`, `d2` from `idx_k1_k2_d2` as `idx_k1_k2_d2`")
           gather(concurrent=true)
-            logicalview(tables="test_index2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `value`, `d1`, `d3` from `test_index2` as `test_index2` where (`id` in (...))")
+            logicalview(tables="test_index2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `value`, `d1`, `d3` from `test_index2` as `test_index2` force index(`primary`) where (`id` in (...))")
 DDL:
   test_index2:
     CREATE TABLE `test_index2` (
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOIndexSelectionTest.AccessPathTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOIndexSelectionTest.AccessPathTest.yml
index 8162072f7..528a7f78c 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOIndexSelectionTest.AccessPathTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOIndexSelectionTest.AccessPathTest.yml
@@ -970,7 +970,7 @@
     delete from orders where o_custkey = 1
 
   plan: |
-    LogicalModify(TYPE="DELETE", TABLES="optest.orders")
+    LogicalModify(TYPE="DELETE", TABLES="optest.orders", optimizebyreturning=true)
       Project(o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderstatus="o_orderstatus", o_totalprice="o_totalprice", o_orderdate="o_orderdate", o_orderpriority="o_orderpriority", o_clerk="o_clerk", o_shippriority="o_shippriority", o_comment="o_comment")
         bkajoin(condition="o_orderkey = o_orderkey", type="inner")
           IndexScan(tables="optest_0001.orders_idx_custkey", sql="SELECT `o_orderkey`, `o_custkey` FROM `orders_idx_custkey` AS `orders_idx_custkey` WHERE (`o_custkey` = 1) FOR UPDATE")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOIndexSelectionTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOIndexSelectionTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOIndexSelectionTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOJoinPlanTest.testJoinReorder.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOJoinPlanTest.testJoinReorder.yml
index 4a51ab355..9afcf6635 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOJoinPlanTest.testJoinReorder.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOJoinPlanTest.testJoinReorder.yml
@@ -5,27 +5,27 @@
       hashjoin(condition="name = name and =", type="right", build="right")
         gather(concurrent=true)
           logicalview(tables="[0000-0003].t_shard_id2", shardcount=4, sql="select `name` from `t_shard_id2` as `t_shard_id2`")
-        logicalview(tables="optest_0002.t_shard_id1", sql="select `id`, `name`, (`id` = 1) as `=` from `t_shard_id1` as `t_shard_id1` where (`id` = 2)")
+        logicalview(tables="optest_0002.t_shard_id1", sql="select `id`, `name`, (`id` = 1) as `=` from `t_shard_id1` as `t_shard_id1` force index(`primary`) where (`id` = 2)")
 - sql: |
     select t_shard_id1.id from (t_shard_id1 left join t_shard_id2 on t_shard_id1.name = t_shard_id2.name and t_shard_id2.id = 1) where t_shard_id1.id = 2
   plan: |
     project(id="id")
       hashjoin(condition="name = name", type="right")
-        logicalview(tables="optest_0001.t_shard_id2", sql="select `name` from `t_shard_id2` as `t_shard_id2` where (`id` = 1)")
-        logicalview(tables="optest_0002.t_shard_id1", sql="select `id`, `name` from `t_shard_id1` as `t_shard_id1` where (`id` = 2)")
+        logicalview(tables="optest_0001.t_shard_id2", sql="select `name` from `t_shard_id2` as `t_shard_id2` force index(`primary`) where (`id` = 1)")
+        logicalview(tables="optest_0002.t_shard_id1", sql="select `id`, `name` from `t_shard_id1` as `t_shard_id1` force index(`primary`) where (`id` = 2)")
 - sql: |
     select t_shard_id1.id from (t_shard_id1 left join t_shard_id2 on t_shard_id1.name = t_shard_id2.name and t_shard_id1.id = 1) where t_shard_id2.id = 2
   plan: |
     project(id="id")
       hashjoin(condition="name = name", type="inner")
-        logicalview(tables="optest_0001.t_shard_id1", sql="select `id`, `name` from `t_shard_id1` as `t_shard_id1` where (`id` = 1)")
-        logicalview(tables="optest_0002.t_shard_id2", sql="select `name` from `t_shard_id2` as `t_shard_id2` where (`id` = 2)")
+        logicalview(tables="optest_0001.t_shard_id1", sql="select `id`, `name` from `t_shard_id1` as `t_shard_id1` force index(`primary`) where (`id` = 1)")
+        logicalview(tables="optest_0002.t_shard_id2", sql="select `name` from `t_shard_id2` as `t_shard_id2` force index(`primary`) where (`id` = 2)")
 - sql: |
     select t_shard_id1.id from (t_shard_id1 left join t_shard_id2 on t_shard_id1.name = t_shard_id2.name and t_shard_id2.id = 1 and t_shard_id1.id = 2)
   plan: |
     project(id="id")
       hashjoin(condition="name = name and =", type="right")
-        logicalview(tables="optest_0001.t_shard_id2", sql="select `name` from `t_shard_id2` as `t_shard_id2` where (`id` = 1)")
+        logicalview(tables="optest_0001.t_shard_id2", sql="select `name` from `t_shard_id2` as `t_shard_id2` force index(`primary`) where (`id` = 1)")
         gather(concurrent=true)
           logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `id`, `name`, (`id` = 2) as `=` from `t_shard_id1` as `t_shard_id1`")
 - sql: |
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOSortJoinTransposePlanTest.test.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOSortJoinTransposePlanTest.test.yml
index 97e6f2f9f..204b19482 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOSortJoinTransposePlanTest.test.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOSortJoinTransposePlanTest.test.yml
@@ -5,12 +5,12 @@
 
   plan: |
 
-    Project(id="id")
-      HashJoin(condition="name = name", type="inner")
-        MergeSort(sort="id ASC")
-          LogicalView(tables="[0000-0003].t_shard_id1", shardCount=4, sql="SELECT `id`, `name` FROM `t_shard_id1` AS `t_shard_id1` ORDER BY `id`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_id2", shardCount=4, sql="SELECT `name` FROM `t_shard_id2` AS `t_shard_id2`")
+    project(id="id")
+      hashjoin(condition="name = name", type="inner")
+        mergesort(sort="id asc")
+          logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `id`, `name` from `t_shard_id1` as `t_shard_id1` force index(`primary`) order by `id`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_id2", shardcount=4, sql="select `name` from `t_shard_id2` as `t_shard_id2`")
 
 -
   sql: |
@@ -19,12 +19,12 @@
 
   plan: |
 
-    Project(id="id0")
-      HashJoin(condition="name = name", type="inner")
-        MergeSort(sort="id ASC")
-          LogicalView(tables="[0000-0003].t_shard_id2", shardCount=4, sql="SELECT `id`, `name` FROM `t_shard_id2` AS `t_shard_id2` ORDER BY `id`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_id1", shardCount=4, sql="SELECT `id`, `name` FROM `t_shard_id1` AS `t_shard_id1`")
+    project(id="id0")
+      hashjoin(condition="name = name", type="inner")
+        mergesort(sort="id asc")
+          logicalview(tables="[0000-0003].t_shard_id2", shardcount=4, sql="select `id`, `name` from `t_shard_id2` as `t_shard_id2` force index(`primary`) order by `id`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `id`, `name` from `t_shard_id1` as `t_shard_id1`")
 
 -
   sql: |
@@ -33,14 +33,14 @@
 
   plan: |
 
-    Project(id="id")
-      MemSort(sort="id0 ASC,id ASC")
-        Project(id="id", id0="id0")
-          HashJoin(condition="name = name", type="inner")
-            Gather(concurrent=true)
-              LogicalView(tables="[0000-0003].t_shard_id1", shardCount=4, sql="SELECT `id`, `name` FROM `t_shard_id1` AS `t_shard_id1`")
-            Gather(concurrent=true)
-              LogicalView(tables="[0000-0003].t_shard_id2", shardCount=4, sql="SELECT `id`, `name` FROM `t_shard_id2` AS `t_shard_id2`")
+    project(id="id")
+      memsort(sort="id0 asc,id asc")
+        project(id="id", id0="id0")
+          hashjoin(condition="name = name", type="inner")
+            gather(concurrent=true)
+              logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `id`, `name` from `t_shard_id1` as `t_shard_id1`")
+            gather(concurrent=true)
+              logicalview(tables="[0000-0003].t_shard_id2", shardcount=4, sql="select `id`, `name` from `t_shard_id2` as `t_shard_id2`")
 
 -
   sql: |
@@ -49,12 +49,12 @@
 
   plan: |
 
-    Project(id="id")
-      HashJoin(condition="name = name", type="left")
-        MergeSort(sort="id ASC", offset=10, fetch=10)
-          LogicalView(tables="[0000-0003].t_one", shardCount=4, sql="SELECT `id`, `name` FROM `t_one` AS `t_one` ORDER BY `id` LIMIT 20")
-        LogicalView(tables="optest_0002.t_two", sql="SELECT `name` FROM `t_two` AS `t_two` WHERE (`id` = 2) GROUP BY `name`")
-    
+    project(id="id")
+      hashjoin(condition="name = name", type="left")
+        mergesort(sort="id asc", offset=10, fetch=10)
+          logicalview(tables="[0000-0003].t_one", shardcount=4, sql="select `id`, `name` from `t_one` as `t_one` force index(`primary`) order by `id` limit 20")
+        logicalview(tables="optest_0002.t_two", sql="select `name` from `t_two` as `t_two` force index(`primary`) where (`id` = 2) group by `name`")
+
 -
   sql: |
     /*+TDDL:HASH_OUTER_JOIN(t_one,t_two)*/
@@ -65,15 +65,18 @@
     topn(sort="id asc", offset=10, fetch=10)
       project(id="id")
         hashjoin(condition="name = name", type="left", build="left")
-          logicalview(tables="optest_0001.t_one", sql="select `id`, `name` from `t_one` as `t_one` where (`id` = 1)")
-          logicalview(tables="optest_0002.t_two", sql="select `name` from `t_two` as `t_two` where (`id` = 2) group by `name`")
+          logicalview(tables="optest_0001.t_one", sql="select `id`, `name` from `t_one` as `t_one` force index(`primary`) where (`id` = 1)")
+          logicalview(tables="optest_0002.t_two", sql="select `name` from `t_two` as `t_two` force index(`primary`) where (`id` = 2) group by `name`")
 
-- sql: |
-    select a.id from (select id, name from t_one) a left join ( select name from t_two where id = 2 group by name ) b  on a.name = b.name order by a.id limit 10, 10;
+-
+  sql: |
+    select * from t_broadcast right join t_shard_id3 on (70>=80);
 
   plan: |
-    project(id="id")
-      hashjoin(condition="name = name", type="left")
-        mergesort(sort="id asc", offset=10, fetch=10)
-          logicalview(tables="[0000-0003].t_one", shardcount=4, sql="select `id`, `name` from `t_one` as `t_one` order by `id` limit 20")
-        logicalview(tables="optest_0002.t_two", sql="select `name` from `t_two` as `t_two` where (`id` = 2) group by `name`")
+
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].t_broadcast,t_shard_id3_[0-3]", shardcount=16, sql="select `t_broadcast`.`id`, `t_broadcast`.`name`, `t_broadcast`.`create_time`, `t_shard_id3`.`id` as `id0`, `t_shard_id3`.`name` as `name0`, `t_shard_id3`.`create_time` as `create_time0` from `t_broadcast` as `t_broadcast` right join `t_shard_id3` as `t_shard_id3` on (70 >= 80)")
+    
+    
+    
+    
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOTraitPassThroughPlanTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOTraitPassThroughPlanTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/CBOTraitPassThroughPlanTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/LimitTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/LimitTest.yml
index 6aa67c022..348895a8c 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/LimitTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/LimitTest.yml
@@ -1,4 +1,9 @@
 SQL:
+  - sql: |
+      SELECT * from xt where name in (null);
+    plan: |
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].xt", shardcount=4, sql="select `id`, `name` from `xt` as `xt` force index(`name`) where (`name` in(?))")
   - sql: |
       SELECT foo.id AS foo_id, foo.bar AS foo_bar, foo.`range` AS foo_range FROM alchemy_foo as foo ORDER BY foo.bar LIMIT 10, 18446744073709551615;
     plan: |
@@ -12,27 +17,27 @@ SQL:
   - sql: |
       SELECT foo.id AS foo_id, foo.bar AS foo_bar, foo.`range` AS foo_range FROM alchemy_foo as foo ORDER BY foo.bar LIMIT -1, 18446744073709551615;
     plan: |
-      ERR-CODE: [TDDL-4501][ERR_OPTIMIZER] optimize error by get rex -1
+      err-code: [pxc-4501][err_optimizer] optimize error by get rex -1
   - sql: |
       SELECT foo.id AS foo_id, foo.bar AS foo_bar, foo.`range` AS foo_range FROM alchemy_foo as foo ORDER BY foo.bar LIMIT 18446744073709551615, -1;
     plan: |
-      ERR-CODE: [TDDL-4501][ERR_OPTIMIZER] optimize error by get rex -1
+      err-code: [pxc-4501][err_optimizer] optimize error by get rex -1
   - sql: |
       SELECT foo.id AS foo_id, foo.bar AS foo_bar, foo.`range` AS foo_range FROM alchemy_foo as foo ORDER BY foo.bar LIMIT -1, 10;
     plan: |
-      ERR-CODE: [TDDL-4501][ERR_OPTIMIZER] optimize error by get rex -1
+      err-code: [pxc-4501][err_optimizer] optimize error by get rex -1
   - sql: |
       SELECT foo.id AS foo_id, foo.bar AS foo_bar, foo.`range` AS foo_range FROM alchemy_foo as foo ORDER BY foo.bar LIMIT 10, -1;
     plan: |
-      ERR-CODE: [TDDL-4501][ERR_OPTIMIZER] optimize error by get rex -1
+      err-code: [pxc-4501][err_optimizer] optimize error by get rex -1
   - sql: |
       SELECT foo.id AS foo_id, foo.bar AS foo_bar, foo.`range` AS foo_range FROM alchemy_foo as foo ORDER BY foo.bar LIMIT 10, -11;
     plan: |
-      ERR-CODE: [TDDL-4501][ERR_OPTIMIZER] optimize error by get rex -11
+      err-code: [pxc-4501][err_optimizer] optimize error by get rex -11
   - sql: |
       SELECT foo.id AS foo_id, foo.bar AS foo_bar, foo.`range` AS foo_range FROM alchemy_foo as foo ORDER BY foo.bar LIMIT 10, -18446744073709551615;
     plan: |
-      ERR-CODE: [TDDL-4501][ERR_OPTIMIZER] optimize error by get rex -18446744073709551615
+      err-code: [pxc-4501][err_optimizer] optimize error by get rex -18446744073709551615
   - sql: |
       SELECT foo.id AS foo_id, foo.bar AS foo_bar, foo.`range` AS foo_range FROM alchemy_foo as foo ORDER BY foo.bar LIMIT 10, 0;
     plan: |
@@ -43,7 +48,7 @@ SQL:
     plan: |
       error occurred while applying rule drdssortconvertrule:smp_instance
   - sql: |
-        SELECT foo.id AS foo_id, foo.bar AS foo_bar, foo.`range` AS foo_range FROM alchemy_foo as foo ORDER BY foo.bar LIMIT 10, 1+2;
+      SELECT foo.id AS foo_id, foo.bar AS foo_bar, foo.`range` AS foo_range FROM alchemy_foo as foo ORDER BY foo.bar LIMIT 10, 1+2;
     plan: |
       not a literal: +(?1, ?2)
   - sql: |
@@ -56,7 +61,7 @@ SQL:
       project(anon_1_id="id", anon_1_name="name")
         hashjoin(condition="id = user_id", type="inner")
           mergesort(sort="id asc", offset=?0, fetch=?1)
-            logicalview(tables="[0000-0003].alchemy_users", shardcount=4, sql="select `id`, `name` from `alchemy_users` as `alchemy_users` order by `id` limit (? + ?)")
+            logicalview(tables="[0000-0003].alchemy_users", shardcount=4, sql="select `id`, `name` from `alchemy_users` as `alchemy_users` force index(`primary`) order by `id` limit (? + ?)")
           gather(concurrent=true)
             logicalview(tables="[0000-0003].alchemy_orders", shardcount=4, sql="select `user_id` from `alchemy_orders` as `alchemy_orders`")
 DDL:
@@ -66,6 +71,8 @@ DDL:
     CREATE TABLE `alchemy_users` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `name` varchar(30) NOT NULL,  PRIMARY KEY (`id`)) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4  dbpartition by hash(`id`);
   alchemy_orders:
     CREATE TABLE `alchemy_orders` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `user_id` int(11) DEFAULT NULL,  `address_id` int(11) DEFAULT NULL,  `description` varchar(30) DEFAULT NULL,  `isopen` int(11) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4  dbpartition by hash(`id`);
+  xt:
+    CREATE TABLE `xt` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `name` varchar(30) NOT NULL,  PRIMARY KEY (`id`), key(name)) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4  dbpartition by hash(`id`);
 STATISTICS:
   alchemy_foo:
     100000
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/MppCBOPlanTest.testExchange.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/MppCBOPlanTest.testExchange.yml
index a6bd874a3..2daaa50fe 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/MppCBOPlanTest.testExchange.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cbo/MppCBOPlanTest.testExchange.yml
@@ -23,6 +23,7 @@
               logicalview(tables="[0000-0003].l2_[0-7]", shardcount=8, sql="select `id` from `l2` as `l2`")
         exchange(distribution=hash[0], collation=[])
           logicalview(tables="[0000-0003].l1", shardcount=4, sql="select `id` from `l1` as `l1`")
+
 -
   sql: |
     /*+TDDL:cmd_extra(enable_broadcast_join=false) SEMI_HASH_JOIN(t1,t3) HASH_JOIN((t1,t3),t2)*/
@@ -55,6 +56,7 @@
       AND l6.id = l7.id
       AND l7.id = l8.id
   plan: |
+
     project(id="id6")
       bkajoin(condition="id = id5", type="inner")
         bkajoin(condition="id = id4", type="inner")
@@ -67,13 +69,14 @@
                       project(id="id0", id0="id")
                         bkajoin(condition="id = id", type="inner")
                           logicalview(tables="[0000-0003].l8_[00-31]", shardcount=32, sql="select `id` from `l8` as `l8`")
-                          logicalview(tables="[0000-0003].l7_[00-27]", shardcount=28, sql="select `id` from `l7` as `l7` where (`id` in (...))")
-                      logicalview(tables="[0000-0003].l6_[00-23]", shardcount=24, sql="select `id` from `l6` as `l6` where (`id` in (...))")
-                  logicalview(tables="[0000-0003].l5_[00-19]", shardcount=20, sql="select `id` from `l5` as `l5` where (`id` in (...))")
-              logicalview(tables="[0000-0003].l4_[00-15]", shardcount=16, sql="select `id` from `l4` as `l4` where (`id` in (...))")
-            logicalview(tables="[0000-0003].l3_[00-11]", shardcount=12, sql="select `id` from `l3` as `l3` where (`id` in (...))")
-          logicalview(tables="[0000-0003].l2_[0-7]", shardcount=8, sql="select `id` from `l2` as `l2` where (`id` in (...))")
-        logicalview(tables="[0000-0003].l1", shardcount=4, sql="select `id` from `l1` as `l1` where (`id` in (...))")
+                          logicalview(tables="[0000-0003].l7_[00-27]", shardcount=28, sql="select `id` from `l7` as `l7` force index(`primary`) where (`id` in (...))")
+                      logicalview(tables="[0000-0003].l6_[00-23]", shardcount=24, sql="select `id` from `l6` as `l6` force index(`primary`) where (`id` in (...))")
+                  logicalview(tables="[0000-0003].l5_[00-19]", shardcount=20, sql="select `id` from `l5` as `l5` force index(`primary`) where (`id` in (...))")
+              logicalview(tables="[0000-0003].l4_[00-15]", shardcount=16, sql="select `id` from `l4` as `l4` force index(`primary`) where (`id` in (...))")
+            logicalview(tables="[0000-0003].l3_[00-11]", shardcount=12, sql="select `id` from `l3` as `l3` force index(`primary`) where (`id` in (...))")
+          logicalview(tables="[0000-0003].l2_[0-7]", shardcount=8, sql="select `id` from `l2` as `l2` force index(`primary`) where (`id` in (...))")
+        logicalview(tables="[0000-0003].l1", shardcount=4, sql="select `id` from `l1` as `l1` force index(`primary`) where (`id` in (...))")
+
 -
   sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(fact,l6) HASH_JOIN((fact,l6),l5) HASH_JOIN((fact,l6,l5),l4) HASH_JOIN((fact,l6,l5,l4),l3) HASH_JOIN((fact,l6,l5,l4,l3),l2) HASH_JOIN((fact,l6,l5,l4,l3,l2),l1) */
@@ -85,6 +88,7 @@
     left join l5 on l5.id = fact.id5
     left join l6 on l6.id = fact.id6
   plan: |
+
     project(id="id", id1="id1", id2="id2", id3="id3", id4="id4", id5="id5", id6="id6", id7="id7", id8="id8", id9="id9", id10="id10", id11="id15", name0="name4", create_time0="create_time4", id0="id11", name="name0", create_time="create_time0", id12="id0", name1="name", create_time1="create_time", id13="id12", name2="name1", create_time2="create_time1", id14="id13", name3="name2", create_time3="create_time2", id15="id14", name4="name3", create_time4="create_time3")
       hashjoin(condition="id = id1", type="left")
         project(id="id", id1="id1", id2="id2", id3="id3", id4="id4", id5="id5", id6="id6", id7="id7", id8="id8", id9="id9", id10="id10", id11="id14", name0="name3", create_time0="create_time3", id0="id11", name="name0", create_time="create_time0", id12="id0", name1="name", create_time1="create_time", id13="id12", name2="name1", create_time2="create_time1", id14="id13", name3="name2", create_time3="create_time2")
@@ -121,6 +125,7 @@
     /*+TDDL: cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v1,v3) HASH_JOIN(v4,v2) HASH_JOIN((v1,v3),(v4,v2)) */
     select v1_k, v2_k, v3_k, v4_k from v1 inner join v2 on v1_k = v2_k inner join (v3 inner join v4 on v3_k = v4_k)  on name1 = name3 and name2 = name4;
   plan: |
+
     project(v1_k="v1_k", v2_k="v2_k", v3_k="v3_k", v4_k="v4_k")
       hashjoin(condition="v4_k = v3_k and v2_k = v1_k", type="inner")
         exchange(distribution=hash[2, 0], collation=[])
@@ -142,42 +147,47 @@
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v3, v2)*/
     select * from v3 join v2 on v3.id = v2.id
   plan: |
-    HashJoin(condition="id = id", type="inner")
-      Exchange(distribution=hash[0], collation=[])
-        LogicalView(tables="[0000-0003].v3_[00-11]", shardCount=12, sql="SELECT `id`, `v3_k`, `name3`, `create_time` FROM `v3` AS `v3`")
-      Exchange(distribution=hash[0], collation=[])
-        LogicalView(tables="[0000-0003].v2_[0-7]", shardCount=8, sql="SELECT `id`, `v2_k`, `name2`, `create_time` FROM `v2` AS `v2`")
+
+    hashjoin(condition="id = id", type="inner")
+      exchange(distribution=hash[0], collation=[])
+        logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+      exchange(distribution=hash[0], collation=[])
+        logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
 
 -
   sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v3, v2)*/
     select count(*) from v3 join v2 on v3.id = v2.id
   plan: |
-    HashAgg(count(*)="SUM(count(*))")
-      Exchange(distribution=single, collation=[])
-        PartialHashAgg(count(*)="COUNT()")
-          HashJoin(condition="id = id", type="inner")
-            Exchange(distribution=hash[0], collation=[])
-              LogicalView(tables="[0000-0003].v3_[00-11]", shardCount=12, sql="SELECT `id` FROM `v3` AS `v3`")
-            Exchange(distribution=hash[0], collation=[])
-              LogicalView(tables="[0000-0003].v2_[0-7]", shardCount=8, sql="SELECT `id` FROM `v2` AS `v2`")
+
+    hashagg(count(*)="sum(count(*))")
+      exchange(distribution=single, collation=[])
+        partialhashagg(count(*)="count()")
+          hashjoin(condition="id = id", type="inner")
+            exchange(distribution=hash[0], collation=[])
+              logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id` from `v3` as `v3`")
+            exchange(distribution=hash[0], collation=[])
+              logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id` from `v2` as `v2`")
+
 -
   sql: |
     /*+TDDL: BKA_JOIN(v3, v2)*/
     select count(*) from v3 join v2 on v3.id = v2.id group by v3.name3
   plan: |
+
     project(count(*)="count(*)")
       sortagg(group="name3", count(*)="count()")
         exchange(distribution=hash[1], collation=[1 asc-nulls-first])
           bkajoin(condition="id = id", type="inner")
             logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `name3` from `v3` as `v3` order by `name3`")
-            logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id` from `v2` as `v2` where (`id` in (...))")
+            logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id` from `v2` as `v2` force index(`primary`) where (`id` in (...))")
 
 -
   sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v3, v2)*/
     select * from v3 join v2 on v3.id = v2.id order by v3.name3 limit 2, 3
   plan: |
+
     limit(offset=2, fetch=3)
       exchange(distribution=single, collation=[2 asc-nulls-first])
         hashjoin(condition="id = id", type="inner")
@@ -191,20 +201,22 @@
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v3, v2)*/
     select * from v3 join v2 on v3.id = v2.id limit 2, 3
   plan: |
-    Limit(offset=2, fetch=3)
-      Exchange(distribution=single, collation=[])
-        Limit(fetch=5)
-          HashJoin(condition="id = id", type="inner")
-            Exchange(distribution=hash[0], collation=[])
-              LogicalView(tables="[0000-0003].v3_[00-11]", shardCount=12, sql="SELECT `id`, `v3_k`, `name3`, `create_time` FROM `v3` AS `v3`")
-            Exchange(distribution=hash[0], collation=[])
-              LogicalView(tables="[0000-0003].v2_[0-7]", shardCount=8, sql="SELECT `id`, `v2_k`, `name2`, `create_time` FROM `v2` AS `v2`")
+
+    limit(offset=2, fetch=3)
+      exchange(distribution=single, collation=[])
+        limit(fetch=5)
+          hashjoin(condition="id = id", type="inner")
+            exchange(distribution=hash[0], collation=[])
+              logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+            exchange(distribution=hash[0], collation=[])
+              logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
 
 -
   sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v3, v2)*/
     select * from v3 join v2 on v3.id = v2.id order by v3.name3
   plan: |
+
     exchange(distribution=single, collation=[2 asc-nulls-first])
       hashjoin(condition="id = id", type="inner")
         exchange(distribution=hash[0], collation=[2 asc-nulls-first])
@@ -217,68 +229,73 @@
     /*+TDDL:cmd_extra(ENABLE_SORT_MERGE_JOIN=true,enable_broadcast_join=false) SORT_MERGE_JOIN(v3, v2)*/
     select count(*) from v3 join v2 on v3.id = v2.id group by v3.name3
   plan: |
-    Project(count(*)="count(*)")
-      HashAgg(group="name3", count(*)="SUM(count(*))")
-        Exchange(distribution=hash[0], collation=[])
-          PartialHashAgg(group="name3", count(*)="COUNT()")
-            SortMergeJoin(condition="id = id", type="inner")
-              Exchange(distribution=hash[0], collation=[0 ASC-nulls-first])
-                LogicalView(tables="[0000-0003].v3_[00-11]", shardCount=12, sql="SELECT `id`, `name3` FROM `v3` AS `v3` ORDER BY `id`")
-              Exchange(distribution=hash[0], collation=[0 ASC-nulls-first])
-                LogicalView(tables="[0000-0003].v2_[0-7]", shardCount=8, sql="SELECT `id` FROM `v2` AS `v2` ORDER BY `id`")
+
+    project(count(*)="count(*)")
+      hashagg(group="name3", count(*)="sum(count(*))")
+        exchange(distribution=hash[0], collation=[])
+          partialhashagg(group="name3", count(*)="count()")
+            sortmergejoin(condition="id = id", type="inner")
+              exchange(distribution=hash[0], collation=[0 asc-nulls-first])
+                logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `name3` from `v3` as `v3` force index(`primary`) order by `id`")
+              exchange(distribution=hash[0], collation=[0 asc-nulls-first])
+                logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id` from `v2` as `v2` force index(`primary`) order by `id`")
 
 -
   sql: |
     /*+TDDL:cmd_extra(ENABLE_SORT_MERGE_JOIN=true,enable_broadcast_join=false) SORT_MERGE_JOIN(v3, v2)*/
     select * from v3 join v2 on v3.id = v2.id order by v3.id
   plan: |
-    Exchange(distribution=single, collation=[0 ASC-nulls-first])
-      SortMergeJoin(condition="id = id", type="inner")
-        Exchange(distribution=hash[0], collation=[0 ASC-nulls-first])
-          LogicalView(tables="[0000-0003].v3_[00-11]", shardCount=12, sql="SELECT `id`, `v3_k`, `name3`, `create_time` FROM `v3` AS `v3` ORDER BY `id`")
-        Exchange(distribution=hash[0], collation=[0 ASC-nulls-first])
-          LogicalView(tables="[0000-0003].v2_[0-7]", shardCount=8, sql="SELECT `id`, `v2_k`, `name2`, `create_time` FROM `v2` AS `v2` ORDER BY `id`")
 
+    exchange(distribution=single, collation=[0 asc-nulls-first])
+      sortmergejoin(condition="id = id", type="inner")
+        exchange(distribution=hash[0], collation=[0 asc-nulls-first])
+          logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3` force index(`primary`) order by `id`")
+        exchange(distribution=hash[0], collation=[0 asc-nulls-first])
+          logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2` force index(`primary`) order by `id`")
 
 -
   sql: |
     /*+TDDL:cmd_extra(ENABLE_HASH_AGG=FALSE)*/
     select count(*) from v3 group by v3.name3 order by v3.name3
   plan: |
-    Project(count(*)="count(*)")
-      Exchange(distribution=single, collation=[0 ASC-nulls-first])
-        SortAgg(group="name3", count(*)="SUM(count(*))")
-          Exchange(distribution=hash[0], collation=[0 ASC-nulls-first])
-            LogicalView(tables="[0000-0003].v3_[00-11]", shardCount=12, sql="SELECT `name3`, COUNT(*) AS `count(*)` FROM `v3` AS `v3` GROUP BY `name3` ORDER BY `name3`")
+
+    project(count(*)="count(*)")
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        sortagg(group="name3", count(*)="sum(count(*))")
+          exchange(distribution=hash[0], collation=[0 asc-nulls-first])
+            logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `name3`, count(*) as `count(*)` from `v3` as `v3` group by `name3` order by `name3`")
 
 -
   sql: |
     /*+TDDL:cmd_extra(ENABLE_HASH_AGG=FALSE)*/
     select count(*) from v3 group by v3.name3 order by v3.name3 desc
   plan: |
-    Project(count(*)="count(*)")
-      Exchange(distribution=single, collation=[0 DESC-nulls-last])
-        SortAgg(group="name3", count(*)="SUM(count(*))")
-          Exchange(distribution=hash[0], collation=[0 DESC-nulls-last])
-            LogicalView(tables="[0000-0003].v3_[00-11]", shardCount=12, sql="SELECT `name3`, COUNT(*) AS `count(*)` FROM `v3` AS `v3` GROUP BY `name3` ORDER BY `name3` DESC")
+
+    project(count(*)="count(*)")
+      exchange(distribution=single, collation=[0 desc-nulls-last])
+        sortagg(group="name3", count(*)="sum(count(*))")
+          exchange(distribution=hash[0], collation=[0 desc-nulls-last])
+            logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `name3`, count(*) as `count(*)` from `v3` as `v3` group by `name3` order by `name3` desc")
 
 -
   sql: |
     /*+TDDL:cmd_extra(ENABLE_HASH_AGG=FALSE)*/
     select count(*) from v3 group by v3.name3 order by v3.name3 desc limit 1,2
   plan: |
-    Project(count(*)="count(*)")
-      Limit(offset=1, fetch=2)
-        Exchange(distribution=single, collation=[0 DESC-nulls-last])
-          SortAgg(group="name3", count(*)="SUM(count(*))")
-            Exchange(distribution=hash[0], collation=[0 DESC-nulls-last])
-              LogicalView(tables="[0000-0003].v3_[00-11]", shardCount=12, sql="SELECT `name3`, COUNT(*) AS `count(*)` FROM `v3` AS `v3` GROUP BY `name3` ORDER BY `name3` DESC")
+
+    project(count(*)="count(*)")
+      limit(offset=1, fetch=2)
+        exchange(distribution=single, collation=[0 desc-nulls-last])
+          sortagg(group="name3", count(*)="sum(count(*))")
+            exchange(distribution=hash[0], collation=[0 desc-nulls-last])
+              logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `name3`, count(*) as `count(*)` from `v3` as `v3` group by `name3` order by `name3` desc")
 
 -
   sql: |
     /*+TDDL:cmd_extra(ENABLE_HASH_AGG=FALSE)*/
     select count(*) from v3 group by v3.name3 limit 1,2
   plan: |
+
     limit(offset=1, fetch=2)
       exchange(distribution=single, collation=[])
         limit(fetch=3)
@@ -292,42 +309,46 @@
     /*+TDDL: SEMI_SORT_MERGE_JOIN(v3, v2)*/
     select * from v3 where v3.id in (select id from v2)
   plan: |
+
     semisortmergejoin(condition="id = id", type="semi")
-      logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3` order by `id`")
+      logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3` force index(`primary`) order by `id`")
       exchange(distribution=broadcast, collation=[0 asc-nulls-first])
-        logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id` from `v2` as `v2` order by `id`")
+        logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id` from `v2` as `v2` force index(`primary`) order by `id`")
 
 -
   sql: |
     /*+TDDL: SEMI_SORT_MERGE_JOIN(v3, v2)*/
     select * from v3 where v3.id in (select id from v2) order by v3.id
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first])
       semisortmergejoin(condition="id = id", type="semi")
-        logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3` order by `id`")
+        logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3` force index(`primary`) order by `id`")
         exchange(distribution=broadcast, collation=[0 asc-nulls-first])
-          logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id` from `v2` as `v2` order by `id`")
+          logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id` from `v2` as `v2` force index(`primary`) order by `id`")
 
 -
   sql: |
     /*+TDDL: MATERIALIZED_SEMI_JOIN(v3, v2)*/
     select count(*) from v3 where v3.id in (select id from v2) group by v3.name3 order by v3.name3
   plan: |
-    Project(count(*)="count(*)")
-      Exchange(distribution=single, collation=[0 ASC-nulls-first])
-        SortAgg(group="name3", count(*)="COUNT()")
-          MemSort(sort="name3 ASC")
-            Exchange(distribution=hash[1], collation=[])
-              MaterializedSemiJoin(condition="id = id", type="semi")
-                LogicalView(tables="[0000-0003].v3_[00-11]", shardCount=12, sql="SELECT `id`, `name3` FROM `v3` AS `v3` WHERE (`id` IN (...))")
-                Exchange(distribution=broadcast, collation=[])
-                  LogicalView(tables="[0000-0003].v2_[0-7]", shardCount=8, sql="SELECT `id` FROM `v2` AS `v2`")
+
+    project(count(*)="count(*)")
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        sortagg(group="name3", count(*)="count()")
+          memsort(sort="name3 asc")
+            exchange(distribution=hash[1], collation=[])
+              materializedsemijoin(condition="id = id", type="semi")
+                logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `name3` from `v3` as `v3` force index(`primary`) where (`id` in (...))")
+                exchange(distribution=broadcast, collation=[])
+                  logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id` from `v2` as `v2`")
 
 -
   sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v2, v3)*/
     select * from v2 left join v3 on v2.id = v3.id limit 2
   plan: |
+
     exchange(distribution=single, collation=[])
       hashjoin(condition="id = id", type="left")
         exchange(distribution=hash[0], collation=[])
@@ -342,12 +363,13 @@
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v2, v3)*/
     select * from v2 left join v3 on v2.id = v3.id order by v2.id limit 2
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first])
       hashjoin(condition="id = id", type="left")
         exchange(distribution=hash[0], collation=[0 asc-nulls-first])
           limit(offset=0, fetch=2)
             exchange(distribution=single, collation=[0 asc-nulls-first])
-              logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2` order by `id` limit 2")
+              logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2` force index(`primary`) order by `id` limit 2")
         exchange(distribution=hash[0], collation=[])
           logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
 
@@ -356,36 +378,38 @@
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v2, v3)*/
     select * from v2 left join v3 on v2.id = v3.v3_k order by v2.id limit 2
   plan: |
+
     limit(offset=0, fetch=2)
       exchange(distribution=single, collation=[0 asc-nulls-first])
         hashjoin(condition="id = v3_k", type="left")
           exchange(distribution=hash[0], collation=[0 asc-nulls-first])
             limit(fetch=2)
-              logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2` order by `id` limit 2")
+              logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2` force index(`primary`) order by `id` limit 2")
           exchange(distribution=hash[1], collation=[])
             logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+
 -
   sql: |
     /*+TDDL: cmd_extra(enable_broadcast_join=false,PARTIAL_AGG_SELECTIVITY_THRESHOLD=0) HASH_JOIN(v2, v3)*/
     select * from v2 left join (select name3 from v3 group by name3) v3 on v2.name2 = v3.name3
   plan: |
-    HashJoin(condition="name2 = name3", type="left")
-      Exchange(distribution=hash[2], collation=[])
-        LogicalView(tables="[0000-0003].v2_[0-7]", shardCount=8, sql="SELECT `id`, `v2_k`, `name2`, `create_time` FROM `v2` AS `v2`")
-      HashAgg(group="name3")
-        Exchange(distribution=hash[0], collation=[])
-          LogicalView(tables="[0000-0003].v3_[00-11]", shardCount=12, sql="SELECT `name3` FROM `v3` AS `v3` GROUP BY `name3`")
 
+    hashjoin(condition="name2 = name3", type="left")
+      exchange(distribution=hash[2], collation=[])
+        logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
+      hashagg(group="name3")
+        exchange(distribution=hash[0], collation=[])
+          logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `name3` from `v3` as `v3` group by `name3`")
 
 -
   sql: |
     /*+TDDL: cmd_extra(enable_broadcast_join=false) HASH_JOIN(v2, v3)*/
     select * from v2 left join (select name3, count(*) from v3 group by name3) v3 on v2.name2 = v3.name3
   plan: |
-    HashJoin(condition="name2 = name3", type="left")
-      Exchange(distribution=hash[2], collation=[])
-        LogicalView(tables="[0000-0003].v2_[0-7]", shardCount=8, sql="SELECT `id`, `v2_k`, `name2`, `create_time` FROM `v2` AS `v2`")
-      HashAgg(group="name3", count(*)="SUM(count(*))")
-        Exchange(distribution=hash[0], collation=[])
-          LogicalView(tables="[0000-0003].v3_[00-11]", shardCount=12, sql="SELECT `name3`, COUNT(*) AS `count(*)` FROM `v3` AS `v3` GROUP BY `name3`")
 
+    hashjoin(condition="name2 = name3", type="left")
+      exchange(distribution=hash[2], collation=[])
+        logicalview(tables="[0000-0003].v2_[0-7]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
+      hashagg(group="name3", count(*)="sum(count(*))")
+        exchange(distribution=hash[0], collation=[])
+          logicalview(tables="[0000-0003].v3_[00-11]", shardcount=12, sql="select `name3`, count(*) as `count(*)` from `v3` as `v3` group by `name3`")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.config.yml
similarity index 56%
rename from polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.config.yml
rename to polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.config.yml
index 291e9440d..b4458eff5 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.config.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.config.yml
@@ -5,8 +5,4 @@ WORKLOAD_TYPE:
 ENABLE_COLUMNAR_OPTIMIZER:
   true
 ENABLE_RUNTIME_FILTER:
-  false
-WORKLOAD_OSS_NET_THRESHOLD:
-  -1
-ENABLE_OSS_MOCK_COLUMNAR:
-  true
\ No newline at end of file
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.ddl.yml
new file mode 100644
index 000000000..a5bd39bc2
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.ddl.yml
@@ -0,0 +1,337 @@
+t_shard_id1:
+  CREATE TABLE `t_shard_id1` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  )  ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 4;
+
+t_shard_id2:
+  CREATE TABLE `t_shard_id2` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  KEY `auto_shard_key_ID_0` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t_shard_id2` on t_shard_id2(`ID`) PARTITION BY key(`ID`) PARTITIONS 4
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 4;
+
+t_shard_id3:
+  CREATE TABLE `t_shard_id3` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  KEY `auto_shard_key_ID_0` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t_shard_id3` on t_shard_id3(`ID`) PARTITION BY key(`ID`) PARTITIONS 4
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 4;
+
+t_shard_id4:
+  CREATE TABLE `t_shard_id4` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  KEY `auto_shard_key_ID_0` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t_shard_id4` on t_shard_id4(`ID`) PARTITION BY key(`ID`) PARTITIONS 4
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 4;
+
+t1:
+  CREATE TABLE `t1` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t1` on t1(`ID`) PARTITION BY key(`ID`) PARTITIONS 4
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 4;
+
+t2:
+  CREATE TABLE `t2` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t1` on t2(`ID`) PARTITION BY key(`ID`) PARTITIONS 8
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 8;
+
+t3:
+  CREATE TABLE `t3` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t3` on t3(`ID`) PARTITION BY key(`ID`) PARTITIONS 12
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 12;
+
+t4:
+  CREATE TABLE `t4` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t4` on t4(`ID`) PARTITION BY key(`ID`) PARTITIONS 16
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 16;
+
+t5:
+  CREATE TABLE `t5` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t5` on t5(`ID`) PARTITION BY key(`ID`) PARTITIONS 28
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 20;
+
+t6:
+  CREATE TABLE `t6` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t6` on t6(`ID`) PARTITION BY key(`ID`) PARTITIONS 24
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 24;
+
+t7:
+  CREATE TABLE `t7` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t7` on t7(`ID`) PARTITION BY key(`ID`) PARTITIONS 28
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 28;
+
+t8:
+  CREATE TABLE `t8` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t8` on t8(`ID`) PARTITION BY key(`ID`) PARTITIONS 32
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 32;
+
+ts:
+  CREATE TABLE `ts` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_t8` on t8(`ID`) PARTITION BY key(`ID`) PARTITIONS 32
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 single;
+
+l1:
+  CREATE TABLE `l1` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_l1` on l1(`ID`) PARTITION BY key(`ID`) PARTITIONS 5
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 5;
+
+l2:
+  CREATE TABLE `l2` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_l2` on l2(`ID`) PARTITION BY key(`ID`) PARTITIONS 8
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 8;
+
+l3:
+  CREATE TABLE `l3` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_l3` on l3(`ID`) PARTITION BY key(`ID`) PARTITIONS 12
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 12;
+
+l4:
+  CREATE TABLE `l4` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_l4` on l4(`ID`) PARTITION BY key(`ID`) PARTITIONS 16
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 16;
+
+l5:
+  CREATE TABLE `l5` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_l5` on l5(`ID`) PARTITION BY key(`ID`) PARTITIONS 20
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 20;
+
+l6:
+  CREATE TABLE `l6` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_l6` on l6(`ID`) PARTITION BY key(`ID`) PARTITIONS 24
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 24;
+
+l7:
+  CREATE TABLE `l7` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_l7` on l7(`ID`) PARTITION BY key(`ID`) PARTITIONS 28
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 28;
+
+l8:
+  CREATE TABLE `l8` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_l8` on l8(`ID`) PARTITION BY key(`ID`) PARTITIONS 32
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 32;
+
+l9:
+  CREATE TABLE `l9` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_l9` on l9(`ID`) PARTITION BY key(`ID`) PARTITIONS 36
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 36;
+
+fact:
+  CREATE TABLE `fact` (
+  `id` int(11) NOT NULL AUTO_INCREMENT BY GROUP,
+  `id1` int(11) DEFAULT NULL,
+  `id2` int(11) DEFAULT NULL,
+  `id3` int(11) DEFAULT NULL,
+  `id4` int(11) DEFAULT NULL,
+  `id5` int(11) DEFAULT NULL,
+  `id6` int(11) DEFAULT NULL,
+  `id7` int(11) DEFAULT NULL,
+  `id8` int(11) DEFAULT NULL,
+  `id9` int(11) DEFAULT NULL,
+  `id10` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_fact` on fact(`ID`) PARTITION BY key(`ID`) PARTITIONS 40
+  ) ENGINE=InnoDB AUTO_INCREMENT=1501888 DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 40;
+
+v1:
+  CREATE TABLE `v1` (
+  `id` int(11) NOT NULL,
+  `v1_k` int(11) NOT NULL,
+  `name1` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_v1` on v1(`ID`) PARTITION BY key(`ID`) PARTITIONS 5
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 5;
+
+v2:
+  CREATE TABLE `v2` (
+  `id` int(11) NOT NULL,
+  `v2_k` int(11) NOT NULL,
+  `name2` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_v2` on v2(`ID`) PARTITION BY key(`ID`) PARTITIONS 8
+  ) DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 8;
+
+v3:
+  CREATE TABLE `v3` (
+  `id` int(11) NOT NULL,
+  `v3_k` int(11) NOT NULL,
+  `name3` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_v3` on v3(`ID`) PARTITION BY key(`ID`) PARTITIONS 12
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 12;
+
+v4:
+  CREATE TABLE `v4` (
+  `id` int(11) NOT NULL,
+  `v4_k` int(11) NOT NULL,
+  `name4` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_v4` on v4(`ID`) PARTITION BY key(`ID`) PARTITIONS 16
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 16;
+
+S1:
+  CREATE TABLE `s1` (
+  `id` int(11) NOT NULL,
+  `v4_k` int(11) NOT NULL,
+  `name4` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_s1` on s1(`ID`) PARTITION BY hash(`ID`) PARTITIONS 16
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(id) partitions 16;
+
+S2:
+  CREATE TABLE `s2` (
+  `id` int(11) NOT NULL,
+  `v4_k` int(11) NOT NULL,
+  `name4` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_s2` on s2(`ID`) PARTITION BY hash(YEAR(create_time)) PARTITIONS 16
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by HASH(YEAR(create_time)) partitions 16;
+
+S3:
+  CREATE TABLE `s3` (
+  `id` int(11) NOT NULL,
+  `v4_k` int(11) NOT NULL,
+  `name4` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_s3` on s3(`ID`) PARTITION BY hash(id,v4_k) PARTITIONS 16
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(id,v4_k) partitions 16;
+
+S4:
+  CREATE TABLE `s4` (
+  `id` int(11) NOT NULL,
+  `v4_k` int(11) NOT NULL,
+  `name4` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_s4` on s4(`ID`) PARTITION BY key(id,v4_k) PARTITIONS 16
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(id,v4_k) partitions 16;
+
+S5:
+  CREATE TABLE `s5` (
+  `id` int(11) NOT NULL,
+  `v4_k` int(11) NOT NULL,
+  `name4` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  CLUSTERED COLUMNAR INDEX `cci_s5` on s5(`ID`) PARTITION BY key(v4_k,id) PARTITIONS 16
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(v4_k,id) partitions 16;
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.statistic.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.statistic.yml
similarity index 100%
rename from polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.statistic.yml
rename to polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.statistic.yml
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.yml
similarity index 59%
rename from polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.yml
rename to polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.yml
index 0877c4a32..b077fa557 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarCBOPlanTest.yml
@@ -1,6 +1,108 @@
+- sql: |
+    select * from t4 where exists (select * from t3 where t3.id = t4.id or t3.id > 10);
+  plan: |
+    
+    project(id="id", name="name", create_time="create_time")
+      filter(condition="apply_boolean")
+        correlateapply(cor=$cor0, leftconditions=[], opkind=null, type=semi)
+          logicalview(tables="t4[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `name`, `create_time` from `t4` as `t4`")
+          logicalview(tables="t3[p1,p2,p3,...p12]", shardcount=12, sql="select `id`, `name`, `create_time` from `t3` as `t3` where ((`id` = `id`) or (`id` > ?))")
+- sql: |
+    select *
+    from
+      ts
+    where
+       ts.id = (
+                  select id
+                  from t5 b
+                  limit 1
+                )
+  plan: |
+    logicalview(tables="ts[p1]", sql="select `id`, `name`, `create_time` from `ts` as `ts` where (`id` = ?)")
+
+    >> individual scalar subquery :
+    mergesort(sort="", offset=0, fetch=?0)
+      logicalview(tables="t5[p1,p2,p3,...p20]", shardcount=20, sql="select `id` from `t5` as `t5` limit (? + 0)")
+
+- sql: |
+    /*+TDDL:cmd_extra(enable_direct_plan=false enable_post_planner=false)*/select *
+    from
+      ts
+    where
+       ts.id = (
+                  select id
+                  from ts b
+                  limit 1
+                )
+  plan: |
+    logicalview(tables="ts[p1],ts[p1]", sql="select `id`, `name`, `create_time` from `ts` as `ts` where (`id` = (((select `id` from `ts` as `ts0` limit ? offset 0))))")
+- sql: |
+    select *,
+    (
+                  select id
+                  from t5 b
+                  limit 1
+                )
+    from
+      t5
+  plan: |
+    logicalview(tables="t5[p1,p2,p3,...p20]", shardcount=20, sql="select `id`, `name`, `create_time`, ? as `$f3` from `t5` as `t5`")
+
+    >> individual scalar subquery :
+    mergesort(sort="", offset=0, fetch=?0)
+      logicalview(tables="t5[p1,p2,p3,...p20]", shardcount=20, sql="select `id` from `t5` as `t5` limit (? + 0)")
+
+- sql: |
+    /*+TDDL:cmd_extra(enable_direct_plan=false enable_post_planner=false)*/select *,
+    (
+                  select id
+                  from ts b
+                  limit 1
+                )
+    from
+      ts
+  plan: |
+    logicalview(tables="ts[p1],ts[p1]", sql="select `id`, `name`, `create_time`, (((select `id` from `ts` as `ts0` limit ? offset 0))) as `$f3` from `ts` as `ts`")
+- sql: |
+    select * from t4 where exists (select * from t3 where t3.id = t4.id);
+  plan: |
+    semihashjoin(condition="id = id", type="semi", build="inner")
+      osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id`, `name`, `create_time` from `cci_t4` as `cci_t4`")
+      exchange(distribution=hash[0]16, collation=[])
+        osstablescan(tables="cci_t3[p1,p2,p3,...p12]", shardcount=12, sql="select `id`, `name`, `create_time` from `cci_t3` as `cci_t3`")
+
+- sql: |
+    select * from ts b where exists (select * from ts a where a.id = b.id);
+  plan: |
+    semihashjoin(condition="id = id", type="semi", build="inner", partition=[local])
+      osstablescan(tables="cci_t8[p1,p2,p3,...p32]", shardcount=32, partition=[local, remote], sql="select `id`, `name`, `create_time` from `cci_t8` as `cci_t8`")
+      osstablescan(tables="cci_t8[p1,p2,p3,...p32]", shardcount=32, partition=[local, remote], sql="select `id`, `name`, `create_time` from `cci_t8` as `cci_t8`")
+- sql: |
+    select count(1) from ts a left join ts b on a.id = b.name and a.name in (select name from ts c where c.id = a.id);
+  plan: |
+    logicalview(tables="optest_p00000_group.ts,ts,ts", sql="select count(1) as `count(1)` from `ts` as `a` left join `ts` as `b` on ((`a`.`id` = `b`.`name`) and (`a`.`name` in (select `c`.`name` as `name` from `ts` as `c` where (`c`.`id` = `a`.`id`))))")
+- sql: |
+    select * from t4 limit 10,20;
+  plan: |
+
+    limit(offset=?0, fetch=?1)
+      exchange(distribution=single, collation=[])
+        limit(fetch=+(?1, ?0))
+          osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `name`, `create_time` from `cci_t4` as `cci_t4`")
+
+- sql: |
+    select * from t4 limit 20;
+  plan: |
+
+    limit(offset=0, fetch=?0)
+      exchange(distribution=single, collation=[])
+        limit(fetch=+(?0, 0))
+          osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `name`, `create_time` from `cci_t4` as `cci_t4`")
+
 - sql: |
     select count(1) from t4 a left join t4 b on a.id = b.name;
   plan: |
+
     hashagg(count(1)="sum(count(1))")
       exchange(distribution=single, collation=[])
         partialhashagg(count(1)="count()")
@@ -8,56 +110,66 @@
             project(id="id")
               exchange(distribution=hash[1], collation=[])
                 project(id="id", id_shuffle__="cast(id)")
-                  osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `t4` as `t4`")
+                  osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `cci_t4` as `cci_t4`")
             project(name="name")
               exchange(distribution=hash[1], collation=[])
                 project(name="name", name_shuffle__="cast(name)")
-                  osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, sql="select `name` from `t4` as `t4`")
+                  osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, sql="select `name` from `cci_t4` as `cci_t4`")
+
 - sql: |
     select count(1) from t4 a left join t4 b on a.id = b.id group by b.id;
   plan: |
+
     project(count(1)="count(1)")
       hashagg(group="id0", count(1)="sum(count(1))")
         exchange(distribution=hash[0]16, collation=[])
           partialhashagg(group="id0", count(1)="count()")
             hashjoin(condition="id = id", type="left", partition=[local])
-              osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
-              osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
+              osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+              osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+
 - sql: |
     select count(1) from t4 a left join t4 b on a.id = b.id group by a.id;
   plan: |
+
     project(count(1)="count(1)")
       hashgroupjoin(condition="id = id", type="left", partition=[local])
-        osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
-        osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
+        osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+        osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+
 - sql: |
     select count(1) from t4 a left join t4 b on a.id = b.id group by a.id + 1;
   plan: |
+
     project(count(1)="count(1)")
       hashagg(group="+", count(1)="sum(count(1))")
         exchange(distribution=hash[0]16, collation=[])
           partialhashagg(group="+", count(1)="count()")
             project(id="id0", +="id0 + ?0", id0="id")
               hashjoin(condition="id = id", type="right", partition=[local])
-                osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
-                osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
+                osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+                osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_OUTER_JOIN_REORDER=false enable_broadcast_join=false)*/
     select count(1) from t4 a left join t4 b on a.id = b.id left join t4 c on b.id = c.id;
   plan: |
+
     hashagg(count(1)="sum(count(1))")
       exchange(distribution=single, collation=[])
         partialhashagg(count(1)="count()")
           hashjoin(condition="id0 = id", type="left")
             exchange(distribution=hash[1]16, collation=[])
               hashjoin(condition="id = id", type="left", partition=[local])
-                osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
-                osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
-            osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `t4` as `t4`")
+                osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+                osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+            osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `cci_t4` as `cci_t4`")
+
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_OUTER_JOIN_REORDER=false enable_broadcast_join=false)*/
     select count(1) from t4 a left join t4 b on a.id = b.id left join t4 c on b.id = c.id group by c.id;
   plan: |
+
     project(count(1)="count(1)")
       hashagg(group="id1", count(1)="sum(count(1))")
         exchange(distribution=hash[0]16, collation=[])
@@ -65,130 +177,165 @@
             hashjoin(condition="id0 = id", type="left")
               exchange(distribution=hash[1]16, collation=[])
                 hashjoin(condition="id = id", type="left", partition=[local])
-                  osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
-                  osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
-              osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `t4` as `t4`")
+                  osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+                  osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+              osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `cci_t4` as `cci_t4`")
+
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_OUTER_JOIN_REORDER=false enable_broadcast_join=false)*/ 
     select count(1) from t4 a left join t4 b on a.id = b.id join t4 c on b.id = c.id;
   plan: |
+
     hashagg(count(1)="sum(count(1))")
       exchange(distribution=single, collation=[])
         partialhashagg(count(1)="count()")
           hashjoin(condition="id0 = id", type="inner")
             exchange(distribution=hash[1]16, collation=[])
               hashjoin(condition="id = id", type="left", partition=[local])
-                osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
-                osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
-            osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `t4` as `t4`")
+                osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+                osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+            osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `cci_t4` as `cci_t4`")
+
 - sql: |
     select count(1) from t4 a where exists (select 1 from t4 b where a.id = b.id) group by id;
   plan: |
+
     project(count(1)="count(1)")
       hashagg(group="id", count(1)="count()")
         semihashjoin(condition="id = id", type="semi", build="inner", partition=[local])
-          osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
-          osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
+          osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+          osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+
 - sql: |
     select count(1) from t4 a where not exists (select 1 from t4 b where a.id = b.id) group by id;
   plan: |
+
     project(count(1)="count(1)")
       hashagg(group="id", count(1)="count()")
         semihashjoin(condition="id = id", type="anti", build="inner", partition=[local])
-          osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
-          osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `t4` as `t4`")
+          osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+          osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_t4` as `cci_t4`")
+
 - sql: |
     select count(1) from t4 a where not exists (select 1 from t4 b where a.id != b.id) group by id;
   plan: |
+
     project(count(1)="count(1)")
       hashagg(group="id", count(1)="sum(count(1))")
         exchange(distribution=hash[0]16, collation=[])
           partialhashagg(group="id", count(1)="count()")
             seminljoin(condition="id <> id", type="anti")
               exchange(distribution=single, collation=[])
-                osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `t4` as `t4`")
+                osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `cci_t4` as `cci_t4`")
               exchange(distribution=single, collation=[])
-                osstablescan(tables="t4[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `t4` as `t4`")
+                osstablescan(tables="cci_t4[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `cci_t4` as `cci_t4`")
+
 - sql: |
     select 1 from s2 a group by a.create_time;
   plan: |
+
     project(1="?0")
       hashagg(group="create_time")
         exchange(distribution=hash[0]16, collation=[])
           partialhashagg(group="create_time")
-            osstablescan(tables="s2[p1,p2,p3,...p16]", shardcount=16, sql="select `create_time` from `s2` as `s2`")
+            osstablescan(tables="cci_s2[p1,p2,p3,...p16]", shardcount=16, sql="select `create_time` from `cci_s2` as `cci_s2`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_broadcast_join=false)*/select 1 from s1 a, v4 b where a.id = b.id group by a.id;
   plan: |
+
     project(1="?0")
       hashjoin(condition="id = id", type="inner", partition=[local])
-        osstablescan(tables="s1[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `s1` as `s1`")
-        osstablescan(tables="v4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `v4` as `v4`")
+        osstablescan(tables="cci_s1[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_s1` as `cci_s1`")
+        osstablescan(tables="cci_v4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `cci_v4` as `cci_v4`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_broadcast_join=false)*/ select 1 from s2 a, s2 b where a.create_time = b.create_time;
   plan: |
+
     project(1="?0")
       hashjoin(condition="create_time = create_time", type="inner")
         project(create_time="create_time")
           exchange(distribution=hash[1], collation=[])
             project(create_time="create_time", create_time_shuffle__="cast(create_time)")
-              osstablescan(tables="s2[p1,p2,p3,...p16]", shardcount=16, sql="select `create_time` from `s2` as `s2`")
+              osstablescan(tables="cci_s2[p1,p2,p3,...p16]", shardcount=16, sql="select `create_time` from `cci_s2` as `cci_s2`")
         project(create_time="create_time")
           exchange(distribution=hash[1], collation=[])
             project(create_time="create_time", create_time_shuffle__="cast(create_time)")
-              osstablescan(tables="s2[p1,p2,p3,...p16]", shardcount=16, sql="select `create_time` from `s2` as `s2`")
+              osstablescan(tables="cci_s2[p1,p2,p3,...p16]", shardcount=16, sql="select `create_time` from `cci_s2` as `cci_s2`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_broadcast_join=false)*/select 1 from s4 a, v4 b where a.id = b.id;
   plan: |
+
     project(1="?0")
-      hashjoin(condition="id = id", type="inner", partition=[local])
-        osstablescan(tables="s4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `s4` as `s4`")
-        osstablescan(tables="v4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `v4` as `v4`")
+      hashjoin(condition="id = id", type="inner")
+        exchange(distribution=hash[0]16, collation=[])
+          osstablescan(tables="cci_s4[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `cci_s4` as `cci_s4`")
+        osstablescan(tables="cci_v4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `cci_v4` as `cci_v4`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_broadcast_join=false)*/select 1 from s3 a, v4 b where a.id = b.id;
   plan: |
+
     project(1="?0")
       hashjoin(condition="id = id", type="inner")
         exchange(distribution=hash[0]16, collation=[])
-          osstablescan(tables="s3[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `s3` as `s3`")
-        osstablescan(tables="v4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `v4` as `v4`")
+          osstablescan(tables="cci_s3[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `cci_s3` as `cci_s3`")
+        osstablescan(tables="cci_v4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `cci_v4` as `cci_v4`")
+
 - sql: |
     select count(1) from s5 a group by a.v4_k;
   plan: |
+
     project(count(1)="count(1)")
-      hashagg(group="v4_k", count(1)="count()", partition=[local])
-        osstablescan(tables="s5[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `v4_k` from `s5` as `s5`")
+      hashagg(group="v4_k", count(1)="sum(count(1))")
+        exchange(distribution=hash[0]16, collation=[])
+          partialhashagg(group="v4_k", count(1)="count()")
+            osstablescan(tables="cci_s5[p1,p2,p3,...p16]", shardcount=16, sql="select `v4_k` from `cci_s5` as `cci_s5`")
+
 - sql: |
     select sum(id) from s5 a group by a.v4_k,a.create_time;
   plan: |
+
     project(sum(id)="sum(id)")
-      hashagg(group="v4_k,create_time", sum(id)="sum(id)", partition=[local])
-        osstablescan(tables="s5[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id`, `v4_k`, `create_time` from `s5` as `s5`")
+      hashagg(group="v4_k,create_time", sum(id)="sum(sum(id))")
+        exchange(distribution=hash[0]16, collation=[])
+          partialhashagg(group="v4_k,create_time", sum(id)="sum(id)")
+            osstablescan(tables="cci_s5[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `v4_k`, `create_time` from `cci_s5` as `cci_s5`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_broadcast_join=false)*/select 1 from s5 a, v4 b where a.v4_k = b.id;
   plan: |
+
     project(1="?0")
-      hashjoin(condition="v4_k = id", type="inner", partition=[local])
-        osstablescan(tables="s5[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `v4_k` from `s5` as `s5`")
-        osstablescan(tables="v4[p1,p2,p3,...p16]", shardcount=16, partition=[local, remote], sql="select `id` from `v4` as `v4`")
+      hashjoin(condition="v4_k = id", type="inner")
+        exchange(distribution=hash[0]16, collation=[])
+          osstablescan(tables="cci_s5[p1,p2,p3,...p16]", shardcount=16, sql="select `v4_k` from `cci_s5` as `cci_s5`")
+        osstablescan(tables="cci_v4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `cci_v4` as `cci_v4`")
+
 - sql: |
     select 1 from t_shard_id2 group by id-3;
   plan: |
+
     project(1="?0")
       hashagg(group="$f0")
         exchange(distribution=hash[0]4, collation=[])
           partialhashagg(group="$f0")
             project($f0="id - ?1")
-              osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id` from `t_shard_id2` as `t_shard_id2`")
+              osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id` from `cci_t_shard_id2` as `cci_t_shard_id2`")
+
 - sql: |
-    /*+TDDL:cmd_extra(PARTIAL_AGG_ONLY=true)*/ select 1 from t_shard_id2 group by id-3;
+    /*+TDDL:cmd_extra(PREFER_PARTIAL_AGG=true)*/ select 1 from t_shard_id2 group by id-3;
   plan: |
+
     project(1="?0")
       hashagg(group="$f0")
         exchange(distribution=hash[0]4, collation=[])
           partialhashagg(group="$f0")
             project($f0="id - ?1")
-              osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id` from `t_shard_id2` as `t_shard_id2`")
+              osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id` from `cci_t_shard_id2` as `cci_t_shard_id2`")
+
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false, enable_broadcast_join=false)  HASH_JOIN(l4,l3) HASH_JOIN((l4,l3),l2)
      HASH_JOIN((l4,l3,l2),l1) ENABLE_RUNTIME_FILTER=false */
@@ -198,33 +345,37 @@
        AND l2.id = l3.id
        AND l3.id = l4.id
   plan: |
+
     project(id="id")
       hashjoin(condition="id00 = id", type="inner")
         project(id00="id0")
           hashjoin(condition="id0 = id", type="inner")
             project(id0="id")
               hashjoin(condition="id = id", type="inner")
-                osstablescan(tables="l4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `l4` as `l4`")
+                osstablescan(tables="cci_l4[p1,p2,p3,...p16]", shardcount=16, partition=[remote], sql="select `id` from `cci_l4` as `cci_l4`")
                 exchange(distribution=hash[0]16, collation=[])
-                  osstablescan(tables="l3[p1,p2,p3,...p12]", shardcount=12, sql="select `id` from `l3` as `l3`")
+                  osstablescan(tables="cci_l3[p1,p2,p3,...p12]", shardcount=12, sql="select `id` from `cci_l3` as `cci_l3`")
             exchange(distribution=hash[0]16, collation=[])
-              osstablescan(tables="l2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `l2` as `l2`")
+              osstablescan(tables="cci_l2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `cci_l2` as `cci_l2`")
         exchange(distribution=hash[0]16, collation=[])
-          osstablescan(tables="l1[p1,p2,p3,p4,p5]", shardcount=5, sql="select `id` from `l1` as `l1`")
+          osstablescan(tables="cci_l1[p1,p2,p3,p4,p5]", shardcount=5, sql="select `id` from `cci_l1` as `cci_l1`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_broadcast_join=false) SEMI_HASH_JOIN(t1,t3) HASH_JOIN((t1,t3),t2)*/
     select * from t1 inner join t2 on t1.id = t2.id where t1.name in (select name from t3)
 
   plan: |
+
     hashjoin(condition="id = id", type="inner")
       exchange(distribution=hash[0]12, collation=[])
         semihashjoin(condition="name = name", type="semi", build="inner")
           exchange(distribution=hash[1]12, collation=[])
-            osstablescan(tables="t1[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name`, `create_time` from `t1` as `t1`")
+            osstablescan(tables="cci_t1[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name`, `create_time` from `cci_t1` as `cci_t1`")
           exchange(distribution=hash[0]12, collation=[])
-            osstablescan(tables="t3[p1,p2,p3,...p12]", shardcount=12, sql="select `name` from `t3` as `t3`")
+            osstablescan(tables="cci_t3[p1,p2,p3,...p12]", shardcount=12, sql="select `name` from `cci_t3` as `cci_t3`")
       exchange(distribution=hash[0]12, collation=[])
-        osstablescan(tables="t2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `name`, `create_time` from `t2` as `t2`")
+        osstablescan(tables="cci_t1[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `name`, `create_time` from `cci_t1` as `cci_t1`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_sort_merge_join=false,enable_hash_join=false,enable_broadcast_join=false) */
     SELECT l1.id
@@ -237,6 +388,7 @@
       AND l6.id = l7.id
       AND l7.id = l8.id
   plan: |
+
     project(id="id2")
       nljoin(condition="id = id", type="inner")
         nljoin(condition="id = id00", type="inner")
@@ -244,27 +396,28 @@
             nljoin(condition="id = id0", type="inner")
               nljoin(condition="id = id", type="inner")
                 exchange(distribution=single, collation=[])
-                  osstablescan(tables="l3[p1,p2,p3,...p12]", shardcount=12, sql="select `id` from `l3` as `l3`")
+                  osstablescan(tables="cci_l3[p1,p2,p3,...p12]", shardcount=12, sql="select `id` from `cci_l3` as `cci_l3`")
                 exchange(distribution=single, collation=[])
-                  osstablescan(tables="l2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `l2` as `l2`")
+                  osstablescan(tables="cci_l2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `cci_l2` as `cci_l2`")
               project(id="id0", id0="id")
                 nljoin(condition="id = id", type="inner")
                   exchange(distribution=single, collation=[])
-                    osstablescan(tables="l4[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `l4` as `l4`")
+                    osstablescan(tables="cci_l4[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `cci_l4` as `cci_l4`")
                   exchange(distribution=single, collation=[])
-                    osstablescan(tables="l5[p1,p2,p3,...p20]", shardcount=20, sql="select `id` from `l5` as `l5`")
+                    osstablescan(tables="cci_l5[p1,p2,p3,...p20]", shardcount=20, sql="select `id` from `cci_l5` as `cci_l5`")
           exchange(distribution=single, collation=[])
-            osstablescan(tables="l1[p1,p2,p3,p4,p5]", shardcount=5, sql="select `id` from `l1` as `l1`")
+            osstablescan(tables="cci_l1[p1,p2,p3,p4,p5]", shardcount=5, sql="select `id` from `cci_l1` as `cci_l1`")
         project(id="id1", id0="id", id00="id0")
           nljoin(condition="id = id", type="inner")
             project(id="id0", id0="id")
               nljoin(condition="id = id", type="inner")
                 exchange(distribution=single, collation=[])
-                  osstablescan(tables="l8[p1,p2,p3,...p32]", shardcount=32, sql="select `id` from `l8` as `l8`")
+                  osstablescan(tables="cci_l8[p1,p2,p3,...p32]", shardcount=32, sql="select `id` from `cci_l8` as `cci_l8`")
                 exchange(distribution=single, collation=[])
-                  osstablescan(tables="l7[p1,p2,p3,...p28]", shardcount=28, sql="select `id` from `l7` as `l7`")
+                  osstablescan(tables="cci_l7[p1,p2,p3,...p28]", shardcount=28, sql="select `id` from `cci_l7` as `cci_l7`")
             exchange(distribution=single, collation=[])
-              osstablescan(tables="l6[p1,p2,p3,...p24]", shardcount=24, sql="select `id` from `l6` as `l6`")
+              osstablescan(tables="cci_l6[p1,p2,p3,...p24]", shardcount=24, sql="select `id` from `cci_l6` as `cci_l6`")
+
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(fact,l6) HASH_JOIN((fact,l6),l5) HASH_JOIN((fact,l6,l5),l4) HASH_JOIN((fact,l6,l5,l4),l3) HASH_JOIN((fact,l6,l5,l4,l3),l2) HASH_JOIN((fact,l6,l5,l4,l3,l2),l1) */
     SELECT *
@@ -275,40 +428,43 @@
     left join l5 on l5.id = fact.id5
     left join l6 on l6.id = fact.id6
   plan: |
+
     project(id="id0", id1="id1", id2="id2", id3="id3", id4="id4", id5="id5", id6="id6", id7="id7", id8="id8", id9="id9", id10="id10", id0="id00", name="name0", create_time="create_time0", id11="id11", name0="name00", create_time0="create_time00", id12="id12", name1="name1", create_time1="create_time1", id13="id14", name2="name3", create_time2="create_time3", id15="id", name4="name", create_time4="create_time", id14="id13", name3="name2", create_time3="create_time2")
       hashjoin(condition="id = id5", type="right")
         exchange(distribution=hash[0]40, collation=[])
-          osstablescan(tables="l5[p1,p2,p3,...p20]", shardcount=20, sql="select `id`, `name`, `create_time` from `l5` as `l5`")
+          osstablescan(tables="cci_l5[p1,p2,p3,...p20]", shardcount=20, sql="select `id`, `name`, `create_time` from `cci_l5` as `cci_l5`")
         project(id="id0", id1="id1", id2="id2", id3="id3", id4="id4", id5="id5", id6="id6", id7="id7", id8="id8", id9="id9", id10="id10", id0="id00", name="name0", create_time="create_time0", id11="id11", name0="name00", create_time0="create_time00", id12="id12", name1="name1", create_time1="create_time1", id14="id", name3="name", create_time3="create_time", id13="id13", name2="name2", create_time2="create_time2")
           exchange(distribution=hash[8]40, collation=[])
             hashjoin(condition="id = id4", type="right")
               exchange(distribution=hash[0]40, collation=[])
-                osstablescan(tables="l4[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `name`, `create_time` from `l4` as `l4`")
+                osstablescan(tables="cci_l4[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `name`, `create_time` from `cci_l4` as `cci_l4`")
               project(id="id0", id1="id1", id2="id2", id3="id3", id4="id4", id5="id5", id6="id6", id7="id7", id8="id8", id9="id9", id10="id10", id0="id00", name="name0", create_time="create_time0", id11="id11", name0="name00", create_time0="create_time00", id13="id", name2="name", create_time2="create_time", id12="id12", name1="name1", create_time1="create_time1")
                 exchange(distribution=hash[7]40, collation=[])
                   hashjoin(condition="id = id3", type="right")
                     exchange(distribution=hash[0]40, collation=[])
-                      osstablescan(tables="l3[p1,p2,p3,...p12]", shardcount=12, sql="select `id`, `name`, `create_time` from `l3` as `l3`")
+                      osstablescan(tables="cci_l3[p1,p2,p3,...p12]", shardcount=12, sql="select `id`, `name`, `create_time` from `cci_l3` as `cci_l3`")
                     project(id="id0", id1="id1", id2="id2", id3="id3", id4="id4", id5="id5", id6="id6", id7="id7", id8="id8", id9="id9", id10="id10", id0="id00", name="name0", create_time="create_time0", id12="id", name1="name", create_time1="create_time", id11="id11", name0="name00", create_time0="create_time00")
                       exchange(distribution=hash[6]40, collation=[])
                         hashjoin(condition="id = id2", type="right")
                           exchange(distribution=hash[0]40, collation=[])
-                            osstablescan(tables="l2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `name`, `create_time` from `l2` as `l2`")
+                            osstablescan(tables="cci_l2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `name`, `create_time` from `cci_l2` as `cci_l2`")
                           project(id="id0", id1="id1", id2="id2", id3="id3", id4="id4", id5="id5", id6="id6", id7="id7", id8="id8", id9="id9", id10="id10", id11="id", name0="name", create_time0="create_time", id0="id00", name="name0", create_time="create_time0")
                             exchange(distribution=hash[5]40, collation=[])
                               hashjoin(condition="id = id1", type="right")
                                 exchange(distribution=hash[0]40, collation=[])
-                                  osstablescan(tables="l1[p1,p2,p3,p4,p5]", shardcount=5, sql="select `id`, `name`, `create_time` from `l1` as `l1`")
+                                  osstablescan(tables="cci_l1[p1,p2,p3,p4,p5]", shardcount=5, sql="select `id`, `name`, `create_time` from `cci_l1` as `cci_l1`")
                                 exchange(distribution=hash[1]40, collation=[])
                                   hashjoin(condition="id = id6", type="left")
                                     exchange(distribution=hash[6]40, collation=[])
-                                      osstablescan(tables="fact[p1,p2,p3,...p40]", shardcount=40, sql="select `id`, `id1`, `id2`, `id3`, `id4`, `id5`, `id6`, `id7`, `id8`, `id9`, `id10` from `fact` as `fact`")
+                                      osstablescan(tables="cci_fact[p1,p2,p3,...p40]", shardcount=40, sql="select `id`, `id1`, `id2`, `id3`, `id4`, `id5`, `id6`, `id7`, `id8`, `id9`, `id10` from `cci_fact` as `cci_fact`")
                                     exchange(distribution=hash[0]40, collation=[])
-                                      osstablescan(tables="l6[p1,p2,p3,...p24]", shardcount=24, sql="select `id`, `name`, `create_time` from `l6` as `l6`")
+                                      osstablescan(tables="cci_l6[p1,p2,p3,...p24]", shardcount=24, sql="select `id`, `name`, `create_time` from `cci_l6` as `cci_l6`")
+
 - sql: |
     /*+TDDL: cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v1,v3) HASH_JOIN(v4,v2) HASH_JOIN((v1,v3),(v4,v2)) */
     select v1_k, v2_k, v3_k, v4_k from v1 inner join v2 on v1_k = v2_k inner join (v3 inner join v4 on v3_k = v4_k)  on name1 = name3 and name2 = name4;
   plan: |
+
     project(v1_k="v1_k", v2_k="v2_k", v3_k="v3_k", v4_k="v4_k")
       hashjoin(condition="v1_k = v2_k and v3_k = v4_k", type="inner")
         project(v3_k="v3_k", v1_k="v1_k")
@@ -316,124 +472,146 @@
             project(v3_k="v3_k", name3="name3", v1_k="v1_k", name1="name1")
               hashjoin(condition="name3 = name1", type="inner")
                 exchange(distribution=hash[1]16, collation=[])
-                  osstablescan(tables="v1[p1,p2,p3,p4,p5]", shardcount=5, sql="select `v1_k`, `name1` from `v1` as `v1`")
+                  osstablescan(tables="cci_v1[p1,p2,p3,p4,p5]", shardcount=5, sql="select `v1_k`, `name1` from `cci_v1` as `cci_v1`")
                 exchange(distribution=hash[1]16, collation=[])
-                  osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, sql="select `v3_k`, `name3` from `v3` as `v3`")
+                  osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, sql="select `v3_k`, `name3` from `cci_v3` as `cci_v3`")
         project(v4_k="v4_k", v2_k="v2_k")
           exchange(distribution=hash[2]16, collation=[])
             hashjoin(condition="name2 = name4", type="inner")
               exchange(distribution=hash[1]16, collation=[])
-                osstablescan(tables="v4[p1,p2,p3,...p16]", shardcount=16, sql="select `v4_k`, `name4` from `v4` as `v4`")
+                osstablescan(tables="cci_v4[p1,p2,p3,...p16]", shardcount=16, sql="select `v4_k`, `name4` from `cci_v4` as `cci_v4`")
               exchange(distribution=hash[1]16, collation=[])
-                osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `v2_k`, `name2` from `v2` as `v2`")
+                osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `v2_k`, `name2` from `cci_v2` as `cci_v2`")
+
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v3, v2)*/
     select * from v3 join v2 on v3.id = v2.id
   plan: |
+
     hashjoin(condition="id = id", type="inner")
-      osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+      osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `cci_v3` as `cci_v3`")
       exchange(distribution=hash[0]12, collation=[])
-        osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
+        osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `cci_v2` as `cci_v2`")
+
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v3, v2)*/
     select count(*) from v3 join v2 on v3.id = v2.id
   plan: |
-    hashagg(count(*)="count()")
+
+    hashagg(count(*)="sum(count(*))")
       exchange(distribution=single, collation=[])
-        hashjoin(condition="id = id", type="inner")
-          osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id` from `v3` as `v3`")
-          exchange(distribution=hash[0]12, collation=[])
-            osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `v2` as `v2`")
+        partialhashagg(count(*)="count()")
+          hashjoin(condition="id = id", type="inner")
+            osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id` from `cci_v3` as `cci_v3`")
+            exchange(distribution=hash[0]12, collation=[])
+              osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `cci_v2` as `cci_v2`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_broadcast_join=false ENABLE_RUNTIME_FILTER=false)*/
     select count(*) from v3 join v2 on v3.id = v2.id group by v3.name3
   plan: |
+
     project(count(*)="count(*)")
       hashagg(group="name3", count(*)="sum(count(*))")
         exchange(distribution=hash[0]12, collation=[])
           partialhashagg(group="name3", count(*)="count()")
             hashjoin(condition="id = id", type="inner")
               exchange(distribution=hash[0]12, collation=[])
-                osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `v2` as `v2`")
-              osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `name3` from `v3` as `v3`")
+                osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `cci_v2` as `cci_v2`")
+              osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `name3` from `cci_v3` as `cci_v3`")
+
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v3, v2)*/
     select * from v3 join v2 on v3.id = v2.id order by v3.name3 limit 2, 3
   plan: |
+
     topn(sort="name3 asc", offset=?0, fetch=?1)
       exchange(distribution=single, collation=[2 asc-nulls-first])
         topn(sort="name3 asc", fetch=+(?1, ?0))
           hashjoin(condition="id = id", type="inner")
-            osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+            osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `cci_v3` as `cci_v3`")
             exchange(distribution=hash[0]12, collation=[])
-              osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
+              osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `cci_v2` as `cci_v2`")
+
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false enable_nl_join=false enable_broadcast_join=false) HASH_JOIN(v3, v2)*/
     select * from v3 join v2 on v3.id = v2.id limit 2, 3
   plan: |
+
     limit(offset=?0, fetch=?1)
       exchange(distribution=single, collation=[])
         hashjoin(condition="id = id", type="inner")
-          osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+          osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `cci_v3` as `cci_v3`")
           exchange(distribution=hash[0]12, collation=[])
-            osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
+            osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `cci_v2` as `cci_v2`")
 
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false, enable_nl_join=false) HASH_JOIN(v3, v2)*/
     select * from v3 join v2 on v3.id = v2.id order by v3.name3
   plan: |
+
     exchange(distribution=single, collation=[2 asc-nulls-first])
       memsort(sort="name3 asc")
         hashjoin(condition="id = id", type="inner")
-          osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+          osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `cci_v3` as `cci_v3`")
           exchange(distribution=hash[0]12, collation=[])
-            osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
+            osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `cci_v2` as `cci_v2`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_broadcast_join=false)*/
     select count(*) from v3 join v2 on v3.id = v2.id group by v3.name3
   plan: |
+
     project(count(*)="count(*)")
       hashagg(group="name3", count(*)="sum(count(*))")
         exchange(distribution=hash[0]12, collation=[])
           partialhashagg(group="name3", count(*)="count()")
             hashjoin(condition="id = id", type="inner")
               exchange(distribution=hash[0]12, collation=[])
-                osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `v2` as `v2`")
-              osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `name3` from `v3` as `v3`")
+                osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `cci_v2` as `cci_v2`")
+              osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `name3` from `cci_v3` as `cci_v3`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_broadcast_join=false)*/
     select * from v3 join v2 on v3.id = v2.id order by v3.id
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first])
       memsort(sort="id asc")
         project(id="id0", v3_k="v3_k", name3="name3", create_time="create_time0", id0="id", v2_k="v2_k", name2="name2", create_time0="create_time")
           hashjoin(condition="id = id", type="inner")
             exchange(distribution=hash[0]12, collation=[])
-              osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
-            osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+              osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `cci_v2` as `cci_v2`")
+            osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `cci_v3` as `cci_v3`")
+
 - sql: |
     select count(*) from v3 group by v3.name3 order by v3.name3
   plan: |
+
     project(count(*)="count(*)")
       exchange(distribution=single, collation=[0 asc-nulls-first])
         memsort(sort="name3 asc")
           hashagg(group="name3", count(*)="sum(count(*))")
             exchange(distribution=hash[0]12, collation=[])
               partialhashagg(group="name3", count(*)="count()")
-                osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `v3` as `v3`")
+                osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `cci_v3` as `cci_v3`")
+
 - sql: |
     select count(*) from v3 group by v3.name3 order by v3.name3 desc
   plan: |
+
     project(count(*)="count(*)")
       exchange(distribution=single, collation=[0 desc-nulls-last])
         memsort(sort="name3 desc")
           hashagg(group="name3", count(*)="sum(count(*))")
             exchange(distribution=hash[0]12, collation=[])
               partialhashagg(group="name3", count(*)="count()")
-                osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `v3` as `v3`")
+                osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `cci_v3` as `cci_v3`")
+
 - sql: |
     select count(*) from v3 group by v3.name3 order by v3.name3 desc limit 1,2
   plan: |
+
     project(count(*)="count(*)")
       topn(sort="name3 desc", offset=?0, fetch=?1)
         exchange(distribution=single, collation=[0 desc-nulls-last])
@@ -441,38 +619,46 @@
             hashagg(group="name3", count(*)="sum(count(*))")
               exchange(distribution=hash[0]12, collation=[])
                 partialhashagg(group="name3", count(*)="count()")
-                  osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `v3` as `v3`")
+                  osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `cci_v3` as `cci_v3`")
+
 - sql: |
     select count(*) from v3 group by v3.name3 limit 1,2
   plan: |
+
     limit(offset=?0, fetch=?1)
       exchange(distribution=single, collation=[])
-        limit(offset=?0, fetch=?1)
+        limit(fetch=+(?1, ?0))
           project(count(*)="count(*)")
             hashagg(group="name3", count(*)="sum(count(*))")
               exchange(distribution=hash[0]12, collation=[])
                 partialhashagg(group="name3", count(*)="count()")
-                  osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `v3` as `v3`")
+                  osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `cci_v3` as `cci_v3`")
+
 - sql: |
     select * from v3 where v3.id in (select id from v2)
   plan: |
+
     semihashjoin(condition="id = id", type="semi", build="outer")
-      osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+      osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `cci_v3` as `cci_v3`")
       exchange(distribution=hash[0]12, collation=[])
-        osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `v2` as `v2`")
+        osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `cci_v2` as `cci_v2`")
+
 - sql: |
     select * from v3 where v3.id in (select id from v2) order by v3.id
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first])
       memsort(sort="id asc")
         semihashjoin(condition="id = id", type="semi", build="outer")
-          osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+          osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `cci_v3` as `cci_v3`")
           exchange(distribution=hash[0]12, collation=[])
-            osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `v2` as `v2`")
+            osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `cci_v2` as `cci_v2`")
+
 - sql: |
     /*+TDDL:cmd_extra()*/
     select count(*) from v3 where v3.id in (select id from v2 order by id) group by v3.name3 order by v3.name3
   plan: |
+
     project(count(*)="count(*)")
       exchange(distribution=single, collation=[0 asc-nulls-first])
         memsort(sort="name3 asc")
@@ -480,9 +666,10 @@
             exchange(distribution=hash[0]12, collation=[])
               partialhashagg(group="name3", count(*)="count()")
                 semihashjoin(condition="id = id", type="semi", build="outer")
-                  osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `name3` from `v3` as `v3`")
+                  osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `name3` from `cci_v3` as `cci_v3`")
                   exchange(distribution=hash[0]12, collation=[])
-                    osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `v2` as `v2`")
+                    osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id` from `cci_v2` as `cci_v2`")
+
 - sql: |
     /*+TDDL: cmd_extra()*/
     select count(*) from v3 where v3.id in (select id from v2 where id = 1) group by v3.name3 order by v3.name3
@@ -490,237 +677,249 @@
     project(count(*)="count(*)")
       exchange(distribution=single, collation=[0 asc-nulls-first])
         memsort(sort="name3 asc")
-          hashagg(group="name3", count(*)="count()")
-            exchange(distribution=hash[1]12, collation=[])
-              semihashjoin(condition="id = id", type="semi", build="inner")
-                osstablescan(tables="v3[p11]", partition=[remote], sql="select `id`, `name3` from `v3` as `v3` where (`id` = ?)")
-                exchange(distribution=hash[0]12, collation=[])
-                  osstablescan(tables="v2[p7]", sql="select `id` from `v2` as `v2` where (`id` = ?)")
+          hashagg(group="name3", count(*)="sum(count(*))")
+            exchange(distribution=hash[0]12, collation=[])
+              partialhashagg(group="name3", count(*)="count()")
+                semihashjoin(condition="id = id", type="semi", build="inner")
+                  osstablescan(tables="cci_v3[p11]", partition=[remote], sql="select `id`, `name3` from `cci_v3` as `cci_v3` where (`id` = ?)")
+                  exchange(distribution=hash[0]12, collation=[])
+                    osstablescan(tables="cci_v2[p7]", sql="select `id` from `cci_v2` as `cci_v2` where (`id` = ?)")
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false,enable_nl_join=false, enable_sort_merge_join=false) HASH_JOIN(v2, v3)*/
     select * from v2 left join v3 on v2.id = v3.id limit 2
   plan: |
-    exchange(distribution=single, collation=[])
-      hashjoin(condition="id = id", type="left")
-        exchange(distribution=hash[0]12, collation=[])
-          limit(offset=0, fetch=?0)
-            exchange(distribution=single, collation=[])
-              limit(offset=0, fetch=?0)
-                osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
-        osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+    limit(offset=0, fetch=?0)
+      exchange(distribution=single, collation=[])
+        hashjoin(condition="id = id", type="left")
+          exchange(distribution=hash[0]12, collation=[])
+            limit(fetch=+(?0, 0))
+              exchange(distribution=single, collation=[])
+                limit(fetch=+(?0, 0))
+                  osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `cci_v2` as `cci_v2`")
+          osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `cci_v3` as `cci_v3`")
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v2, v3)*/
     select * from v2 left join v3 on v2.id = v3.v3_k order by v2.id limit 2
   plan: |
-    memsort(sort="id asc")
-      limit(offset=0, fetch=?0)
-        exchange(distribution=single, collation=[])
+    limit(offset=0, fetch=?0)
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        memsort(sort="id asc")
           hashjoin(condition="id = v3_k", type="left")
-            exchange(distribution=hash[0]12, collation=[0 asc-nulls-first])
+            exchange(distribution=hash[0]12, collation=[])
               topn(sort="id asc", fetch=+(?0, 0))
                 exchange(distribution=single, collation=[0 asc-nulls-first])
                   topn(sort="id asc", fetch=+(?0, 0))
-                    osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
+                    osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `cci_v2` as `cci_v2`")
             exchange(distribution=hash[1]12, collation=[])
-              osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+              osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `cci_v3` as `cci_v3`")
+
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v2, v3)*/
     select * from v2 left join v3 on v2.id = v3.id order by v2.id limit 2
   plan: |
-    exchange(distribution=single, collation=[0 asc-nulls-first])
-      memsort(sort="id asc")
-        hashjoin(condition="id = id", type="left")
-          exchange(distribution=hash[0]12, collation=[0 asc-nulls-first])
-            topn(sort="id asc", offset=0, fetch=?0)
-              exchange(distribution=single, collation=[0 asc-nulls-first])
-                topn(sort="id asc", fetch=+(?0, 0))
-                  osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
-          osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
-- sql: |
-    /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=false,enable_broadcast_join=false) HASH_JOIN(v2, v3)*/
-    select * from v2 left join v3 on v2.id = v3.v3_k order by v2.id limit 2
-  plan: |
-    memsort(sort="id asc")
-      limit(offset=0, fetch=?0)
-        exchange(distribution=single, collation=[])
-          hashjoin(condition="id = v3_k", type="left")
-            exchange(distribution=hash[0]12, collation=[0 asc-nulls-first])
+    limit(offset=0, fetch=?0)
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        memsort(sort="id asc")
+          hashjoin(condition="id = id", type="left")
+            exchange(distribution=hash[0]12, collation=[])
               topn(sort="id asc", fetch=+(?0, 0))
                 exchange(distribution=single, collation=[0 asc-nulls-first])
                   topn(sort="id asc", fetch=+(?0, 0))
-                    osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
-            exchange(distribution=hash[1]12, collation=[])
-              osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, sql="select `id`, `v3_k`, `name3`, `create_time` from `v3` as `v3`")
+                    osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `cci_v2` as `cci_v2`")
+            osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, partition=[remote], sql="select `id`, `v3_k`, `name3`, `create_time` from `cci_v3` as `cci_v3`")
+
 - sql: |
     /*+TDDL: cmd_extra(enable_broadcast_join=false,PARTIAL_AGG_SELECTIVITY_THRESHOLD=0) HASH_JOIN(v2, v3)*/
     select * from v2 left join (select name3 from v3 group by name3) v3 on v2.name2 = v3.name3
   plan: |
+
     hashjoin(condition="name2 = name3", type="left")
       exchange(distribution=hash[2]12, collation=[])
-        osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
+        osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `cci_v2` as `cci_v2`")
       hashagg(group="name3")
         exchange(distribution=hash[0]12, collation=[])
-          osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `v3` as `v3`")
+          partialhashagg(group="name3")
+            osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `cci_v3` as `cci_v3`")
+
 - sql: |
     /*+TDDL: cmd_extra(enable_broadcast_join=false) HASH_JOIN(v2, v3)*/
     select * from v2 left join (select name3, count(*) from v3 group by name3) v3 on v2.name2 = v3.name3
   plan: |
+
     hashjoin(condition="name2 = name3", type="left")
       exchange(distribution=hash[2]12, collation=[])
-        osstablescan(tables="v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `v2` as `v2`")
+        osstablescan(tables="cci_v2[p1,p2,p3,p4,p5,p6,p7,p8]", shardcount=8, sql="select `id`, `v2_k`, `name2`, `create_time` from `cci_v2` as `cci_v2`")
       hashagg(group="name3", count(*)="sum(count(*))")
         exchange(distribution=hash[0]12, collation=[])
           partialhashagg(group="name3", count(*)="count()")
-            osstablescan(tables="v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `v3` as `v3`")
+            osstablescan(tables="cci_v3[p1,p2,p3,...p12]", shardcount=12, sql="select `name3` from `cci_v3` as `cci_v3`")
 
 - sql: |
     select count(*) over(partition by id), max(create_time) over(partition by id), id from t_shard_id2;
   plan: |
+
     project(count(*) over (partition by id )="f3w0$o0", max(create_time) over (partition by id )="f4w0$o1", id="id")
       hashwindow(id="id", create_time="create_time", f2w0$o0="window#0count()", f3w0$o1="window#0max($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [count(), max($1)])", partition=[local])
-        osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+        osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     select count(*) over(partition by id, name), max(create_time) over(partition by id), id from t_shard_id2;
   plan: |
+
     project(count(*) over (partition by id, name )="f3w0$o0", max(create_time) over (partition by id )="f4w1$o0", id="id")
       hashwindow(id="id", create_time="create_time", f3w0$o0="f3w0$o0", f3w0$o0="window#0max($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($1)])")
         project(id="id", create_time="create_time", f3w0$o0="f3w0$o0")
           hashwindow(id="id", name="name", create_time="create_time", f3w0$o0="window#0count()", reference windows="window#0=window(partition {0, 1} order by [] range between unbounded preceding and unbounded following aggs [count()])", partition=[local])
-            osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `name`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+            osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `name`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_PARTITION_WISE_WINDOW=false)*/ select count(*) over(partition by id, name), max(create_time) over(partition by id), id from t_shard_id2;
   plan: |
+
     project(count(*) over (partition by id, name )="f3w0$o0", max(create_time) over (partition by id )="f4w1$o0", id="id")
       hashwindow(id="id", create_time="create_time", f3w0$o0="f3w0$o0", f3w0$o0="window#0max($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($1)])")
         exchange(distribution=hash[0], collation=[])
           project(id="id", create_time="create_time", f3w0$o0="f3w0$o0")
             hashwindow(id="id", name="name", create_time="create_time", f3w0$o0="window#0count()", reference windows="window#0=window(partition {0, 1} order by [] range between unbounded preceding and unbounded following aggs [count()])")
               exchange(distribution=hash[0, 1], collation=[])
-                osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+                osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     select max(create_time) over(partition by id), count(*) over(partition by id, name), id from t_shard_id2;
   plan: |
+
     project(max(create_time) over (partition by id )="f3w0$o0", count(*) over (partition by id, name )="f4w1$o0", id="id")
       hashwindow(id="id", name="name", f3w0$o0="f3w0$o0", f3w0$o0="window#0count()", reference windows="window#0=window(partition {0, 1} order by [] range between unbounded preceding and unbounded following aggs [count()])")
         project(id="id", name="name", f3w0$o0="f3w0$o0")
           hashwindow(id="id", name="name", create_time="create_time", f3w0$o0="window#0max($2)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($2)])", partition=[local])
-            osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `name`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+            osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `name`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_PARTITION_WISE_WINDOW=false)*/ select max(create_time) over(partition by id), count(*) over(partition by id, name), id from t_shard_id2;
   plan: |
+
     project(max(create_time) over (partition by id )="f3w0$o0", count(*) over (partition by id, name )="f4w1$o0", id="id")
       hashwindow(id="id", name="name", f3w0$o0="f3w0$o0", f3w0$o0="window#0count()", reference windows="window#0=window(partition {0, 1} order by [] range between unbounded preceding and unbounded following aggs [count()])")
         exchange(distribution=hash[0, 1], collation=[])
           project(id="id", name="name", f3w0$o0="f3w0$o0")
             sortwindow(id="id", name="name", create_time="create_time", f3w0$o0="window#0max($2)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($2)])")
               memsort(sort="id asc")
-                osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[remote], sql="select `id`, `name`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+                osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[remote], sql="select `id`, `name`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     select max(create_time) over(partition by id), count(*) over(partition by name), id from t_shard_id2;
   plan: |
+
     project(max(create_time) over (partition by id )="f3w0$o0", count(*) over (partition by name )="f4w1$o0", id="id")
       hashwindow(id="id", name="name", f3w0$o0="f3w0$o0", f3w0$o0="window#0count()", reference windows="window#0=window(partition {1} order by [] range between unbounded preceding and unbounded following aggs [count()])")
         exchange(distribution=hash[1]4, collation=[])
           project(id="id", name="name", f3w0$o0="f3w0$o0")
             hashwindow(id="id", name="name", create_time="create_time", f3w0$o0="window#0max($2)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($2)])", partition=[local])
-              osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `name`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+              osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `name`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     select max(create_time) over(), count(*) over(), id from t_shard_id2;
   plan: |
+
     project(max(create_time) over ()="f3w0$o0", count(*) over ()="f4w0$o1", id="id")
       hashwindow(id="id", create_time="create_time", f2w0$o0="window#0max($1)", f3w0$o1="window#0count()", reference windows="window#0=window(partition {} order by [] range between unbounded preceding and unbounded following aggs [max($1), count()])")
         exchange(distribution=single, collation=[])
-          osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+          osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     select max(create_time) over(partition by id), count(*) over(), id from t_shard_id2;
   plan: |
+
     project(max(create_time) over (partition by id )="f3w0$o0", count(*) over ()="f4w1$o0", id="id")
       hashwindow(id="id", f3w0$o0="f3w0$o0", f2w0$o0="window#0count()", reference windows="window#0=window(partition {} order by [] range between unbounded preceding and unbounded following aggs [count()])")
         exchange(distribution=single, collation=[])
           project(id="id", f3w0$o0="f3w0$o0")
             hashwindow(id="id", create_time="create_time", f2w0$o0="window#0max($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($1)])", partition=[local])
-              osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+              osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     select id, count(*) from (select max(create_time), id from t_shard_id2 group by id) t;
   plan: |
+
     hashagg(id="__first_value(id)", count(*)="sum(count(*))")
       exchange(distribution=single, collation=[])
         partialhashagg(id="__first_value(id)", count(*)="count()")
           hashagg(group="id", max(create_time)="max(create_time)", partition=[local])
-            osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+            osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     select max(create_time), id from t_shard_id2 group by id;
   plan: |
+
     project(max(create_time)="max(create_time)", id="id")
       hashagg(group="id", max(create_time)="max(create_time)", partition=[local])
-        osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+        osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     select sum(id) over(partition by name rows between unbounded preceding and unbounded following), count(*) over(partition by name rows between unbounded preceding and unbounded following), id from t_shard_id2;
   plan: |
+
     project(sum(id) over (partition by name  rows between unbounded preceding and unbounded following)="f3w0$o0", count(*) over (partition by name  rows between unbounded preceding and unbounded following)="f4w0$o1", id="id")
       hashwindow(id="id", name="name", f2w0$o0="window#0sum($0)", f3w0$o1="window#0count()", reference windows="window#0=window(partition {1} order by [] rows between unbounded preceding and unbounded following aggs [sum($0), count()])")
         exchange(distribution=hash[1]4, collation=[])
-          osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name` from `t_shard_id2` as `t_shard_id2`")
+          osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     select id, count(*) from( select id, max(create_time) over(partition by name) as max_time from t_shard_id2) t group by id;
   plan: |
+
     hashagg(group="id", count(*)="sum(count(*))")
       exchange(distribution=hash[0]4, collation=[])
         partialhashagg(group="id", count(*)="count()")
           hashwindow(id="id", name="name", create_time="create_time", f3w0$o0="window#0max($2)", reference windows="window#0=window(partition {1} order by [] range between unbounded preceding and unbounded following aggs [max($2)])")
             exchange(distribution=hash[1]4, collation=[])
-              osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+              osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_PARTITION_WISE_WINDOW=false)*/ select id, count(*) from( select id, max(create_time) over(partition by name) as max_time from t_shard_id2) t group by id;
   plan: |
+
     hashagg(group="id", count(*)="sum(count(*))")
       exchange(distribution=hash[0]4, collation=[])
         partialhashagg(group="id", count(*)="count()")
           hashwindow(id="id", name="name", create_time="create_time", f3w0$o0="window#0max($2)", reference windows="window#0=window(partition {1} order by [] range between unbounded preceding and unbounded following aggs [max($2)])")
             exchange(distribution=hash[1], collation=[])
-              osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+              osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     select id, count(*) from( select create_time, id, max(create_time) over(partition by id) as max_time from t_shard_id2) t group by id;
   plan: |
+
     hashagg(group="id", count(*)="count()")
       hashwindow(id="id", create_time="create_time", f2w0$o0="window#0max($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($1)])", partition=[local])
-        osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+        osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[local, remote], sql="select `id`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_PARTITION_WISE_WINDOW=false)*/ select id, count(*) from( select create_time, id, max(create_time) over(partition by id) as max_time from t_shard_id2) t group by id;
   plan: |
+
     hashagg(group="id", count(*)="count()")
       sortwindow(id="id", create_time="create_time", f2w0$o0="window#0max($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($1)])")
         memsort(sort="id asc")
-          osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[remote], sql="select `id`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+          osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, partition=[remote], sql="select `id`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
+
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_SORT_WINDOW=FALSE ENABLE_PARTITION_WISE_WINDOW=false)*/ select id, count(*) from( select create_time, id, max(create_time) over(partition by id) as max_time from t_shard_id2) t group by id;
   plan: |
+
     hashagg(group="id", count(*)="sum(count(*))")
       exchange(distribution=hash[0]4, collation=[])
         partialhashagg(group="id", count(*)="count()")
           hashwindow(id="id", create_time="create_time", f2w0$o0="window#0max($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($1)])")
             exchange(distribution=hash[0], collation=[])
-              osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `create_time` from `t_shard_id2` as `t_shard_id2`")
+              osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
 
 - sql: |
     /*+TDDL:PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD=100000 ENABLE_EXPAND_DISTINCTAGG=false*/select CHECK_SUM(id), CHECK_SUM_V2(id) from t_shard_id2 group by create_time;
   plan: |
+
     project(check_sum(id)="check_sum(id)", check_sum_v2(id)="check_sum_v2(id)")
       hashagg(group="create_time", check_sum(id)="check_sum_merge(check_sum(id))", check_sum_v2(id)="check_sum_v2_merge(check_sum_v2(id))")
         exchange(distribution=hash[0]4, collation=[])
           partialhashagg(group="create_time", check_sum(id)="check_sum(id)", check_sum_v2(id)="check_sum_v2(id)")
-            osstablescan(tables="t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `create_time` from `t_shard_id2` as `t_shard_id2`")
\ No newline at end of file
+            osstablescan(tables="cci_t_shard_id2[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `create_time` from `cci_t_shard_id2` as `cci_t_shard_id2`")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarIndexSelectTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarIndexSelectTest.ddl.yml
new file mode 100644
index 000000000..b1da0f66c
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarIndexSelectTest.ddl.yml
@@ -0,0 +1,36 @@
+t_order:
+  CREATE TABLE `t_order` (
+      `id` bigint(11) NOT NULL AUTO_INCREMENT,
+      `order_id` varchar(20) DEFAULT NULL,
+      `buyer_id` varchar(20) DEFAULT NULL,
+      `seller_id` varchar(20) DEFAULT NULL,
+      `order_snapshot` longtext,
+      `order_detail` longtext,
+      PRIMARY KEY (`id`),
+      KEY `auto_shard_key_order_id` USING BTREE (`order_id`),
+      GLOBAL INDEX `g_i_buyer`(`buyer_id`) COVERING (`id`, `order_id`, `seller_id`, `order_snapshot`) PARTITION BY HASH(`buyer_id`) PARTITIONS 3,
+      UNIQUE GLOBAL KEY `g_i_seller` (`seller_id`) COVERING (`id`, `order_id`, `buyer_id`, `order_snapshot`) PARTITION BY HASH(`seller_id`) PARTITIONS 3,
+      CLUSTERED COLUMNAR INDEX `cc_i_seller` ON t_order (`seller_id`) partition by hash(`order_id`) partitions 16
+  ) ENGINE = InnoDB AUTO_INCREMENT = 2300006 DEFAULT CHARSET = latin1 partition by hash(`order_id`) PARTITIONS 3,
+
+lineitem:
+    CREATE TABLE IF NOT EXISTS `lineitem` (
+    `l_orderkey` int(11) NOT NULL,
+    `l_partkey` int(11) NOT NULL,
+    `l_suppkey` int(11) NOT NULL,
+    `l_linenumber` int(11) NOT NULL,
+    `l_quantity` decimal(15, 2) NOT NULL,
+    `l_extendedprice` decimal(15, 2) NOT NULL,
+    `l_discount` decimal(15, 2) NOT NULL,
+    `l_tax` decimal(15, 2) NOT NULL,
+    `l_returnflag` varchar(1) NOT NULL,
+    `l_linestatus` varchar(1) NOT NULL,
+    `l_shipdate` date NOT NULL,
+    `l_commitdate` date NOT NULL,
+    `l_receiptdate` date NOT NULL,
+    `l_shipinstruct` varchar(25) NOT NULL,
+    `l_shipmode` varchar(10) NOT NULL,
+    `l_comment` varchar(44) NOT NULL,
+    PRIMARY KEY (`l_orderkey`, `l_linenumber`),
+    CLUSTERED COLUMNAR INDEX `lineitem_col_index` on lineitem(`l_shipdate`, `l_orderkey`) PARTITION BY HASH(`l_orderkey`) PARTITIONS 16
+    ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`l_orderkey`) PARTITIONS 8;
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarIndexSelectTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarIndexSelectTest.yml
new file mode 100644
index 000000000..14fd00e0f
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarIndexSelectTest.yml
@@ -0,0 +1,20 @@
+-
+  sql: |
+
+    /*+TDDL:enable_columnar_optimizer=true*/select count(*) from t_order force index(`cc_i_seller`);
+
+  plan: |
+    
+    hashagg(count(*)="count()")
+      gather(concurrent=true)
+        osstablescan(tables="cc_i_seller[p1,p2,p3,...p16]", shardcount=16, sql="select `id` from `cc_i_seller` as `cc_i_seller`")
+
+
+- sql: |
+    /*+TDDL:enable_columnar_optimizer=true */ select  count(*) from lineitem force index(`lineitem_col_index`);
+
+
+  plan: |
+    hashagg(count(*)="count()")
+      gather(concurrent=true)
+        osstablescan(tables="lineitem_col_index[p1,p2,p3,...p16]", shardcount=16, sql="select `l_orderkey` from `lineitem_col_index` as `lineitem_col_index`")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarSortTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarSortTest.yml
new file mode 100644
index 000000000..6440e7182
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/columnar/ColumnarSortTest.yml
@@ -0,0 +1,113 @@
+SQL:
+  - sql: |
+      select * from t_order order by order_id limit 10;
+    plan: |
+      topn(sort="order_id asc", offset=0, fetch=?0)
+        exchange(distribution=single, collation=[1 asc-nulls-first])
+          topn(sort="order_id asc", fetch=+(?0, 0))
+            osstablescan(tables="cc_i_seller[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot`, `order_detail` from `cc_i_seller` as `cc_i_seller`")
+  - sql: |
+      /*+TDDL:cmd_extra(ENABLE_TOPN=false)*/select * from t_order order by order_id limit 10;
+    plan: |
+      limit(offset=0, fetch=?0)
+        exchange(distribution=single, collation=[1 asc-nulls-first])
+          memsort(sort="order_id asc")
+            osstablescan(tables="cc_i_seller[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot`, `order_detail` from `cc_i_seller` as `cc_i_seller`")
+  - sql: |
+      /*+TDDL:cmd_extra(ENABLE_TOPN=false ENABLE_PARTIAL_LIMIT=false)*/select * from t_order order by order_id limit 10;
+    plan: |
+      limit(offset=0, fetch=?0)
+        exchange(distribution=single, collation=[1 asc-nulls-first])
+          memsort(sort="order_id asc")
+            osstablescan(tables="cc_i_seller[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot`, `order_detail` from `cc_i_seller` as `cc_i_seller`")
+  - sql: |
+      /*+TDDL:cmd_extra(ENABLE_PARTIAL_LIMIT=false)*/select * from t_order limit 10;
+    plan: |
+      limit(offset=0, fetch=?0)
+        exchange(distribution=single, collation=[])
+          osstablescan(tables="cc_i_seller[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot`, `order_detail` from `cc_i_seller` as `cc_i_seller`")
+  - sql: |
+     /*+TDDL:cmd_extra(ENABLE_TOPN=false ENABLE_LIMIT=false)*/select * from t_order limit 10;
+    plan: |
+      columnar sql could not be implemented
+  - sql: |
+      /*+TDDL:cmd_extra(ENABLE_LIMIT=false)*/select * from t_order limit 10;
+    plan: |
+      columnar sql could not be implemented
+  - sql: |
+      select * from (select * from t_order order by order_id) limit 10;
+    plan: |
+      limit(offset=0, fetch=?0)
+        exchange(distribution=single, collation=[])
+          limit(fetch=+(?0, 0))
+            osstablescan(tables="cc_i_seller[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot`, `order_detail` from `cc_i_seller` as `cc_i_seller`")
+  - sql: |
+      select * from (select * from t_order order by order_id)  order by id limit 10;
+    plan: |
+      topn(sort="id asc", offset=0, fetch=?0)
+        exchange(distribution=single, collation=[0 asc-nulls-first])
+          topn(sort="id asc", fetch=+(?0, 0))
+            osstablescan(tables="cc_i_seller[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot`, `order_detail` from `cc_i_seller` as `cc_i_seller`")
+  - sql: |
+      select * from (select * from t_order order by order_id limit 20 )  order by id limit 10;
+    plan: |
+      limit(offset=0, fetch=?1)
+        memsort(sort="id asc")
+          topn(sort="order_id asc", offset=0, fetch=?0)
+            exchange(distribution=single, collation=[1 asc-nulls-first])
+              topn(sort="order_id asc", fetch=+(?0, 0))
+                osstablescan(tables="cc_i_seller[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot`, `order_detail` from `cc_i_seller` as `cc_i_seller`")
+  - sql: |
+      select * from (select * from t_order limit 20 )  order by id limit 10;
+    plan: |
+      limit(offset=0, fetch=?1)
+        memsort(sort="id asc")
+          limit(offset=0, fetch=?0)
+            exchange(distribution=single, collation=[])
+              limit(fetch=+(?0, 0))
+                osstablescan(tables="cc_i_seller[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot`, `order_detail` from `cc_i_seller` as `cc_i_seller`")
+  - sql: |
+      select * from (select * from t_order order by order_id limit 20 ) limit 10;
+    plan: |
+      limit(offset=0, fetch=?1)
+        topn(sort="order_id asc", offset=0, fetch=?0)
+          exchange(distribution=single, collation=[1 asc-nulls-first])
+            topn(sort="order_id asc", fetch=+(?0, 0))
+              osstablescan(tables="cc_i_seller[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot`, `order_detail` from `cc_i_seller` as `cc_i_seller`")
+  - sql: |
+      select * from (select * from t_order order by order_id limit 20 ) order by id;
+    plan: |
+      memsort(sort="id asc")
+        topn(sort="order_id asc", offset=0, fetch=?0)
+          exchange(distribution=single, collation=[1 asc-nulls-first])
+            topn(sort="order_id asc", fetch=+(?0, 0))
+              osstablescan(tables="cc_i_seller[p1,p2,p3,...p16]", shardcount=16, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot`, `order_detail` from `cc_i_seller` as `cc_i_seller`")
+DDL:
+  t_order:
+    CREATE TABLE `t_order` (
+    `id` bigint(11) NOT NULL AUTO_INCREMENT,
+    `order_id` varchar(20) DEFAULT NULL,
+    `buyer_id` varchar(20) DEFAULT NULL,
+    `seller_id` varchar(20) DEFAULT NULL,
+    `order_snapshot` longtext,
+    `order_detail` longtext,
+    PRIMARY KEY (`id`),
+    KEY `auto_shard_key_order_id` USING BTREE (`order_id`),
+    GLOBAL INDEX `g_i_buyer`(`buyer_id`) COVERING (`id`, `order_id`, `seller_id`, `order_snapshot`) PARTITION BY HASH(`buyer_id`) PARTITIONS 3,
+    UNIQUE GLOBAL KEY `g_i_seller` (`seller_id`) COVERING (`id`, `order_id`, `buyer_id`, `order_snapshot`) PARTITION BY HASH(`seller_id`) PARTITIONS 3,
+    CLUSTERED COLUMNAR INDEX `cc_i_seller` ON t_order (`seller_id`) partition by hash(`order_id`) partitions 16
+    ) ENGINE = InnoDB AUTO_INCREMENT = 2300006 DEFAULT CHARSET = latin1 partition by hash(`order_id`) PARTITIONS 3
+STATISTICS:
+  t_order:
+    100000000
+CONFIG:
+  WORKLOAD_TYPE:
+    ap
+  ENABLE_COLUMNAR_OPTIMIZER:
+    true
+  ENABLE_MPP:
+    true
+  defaltxxAPPName.isNew:
+    true
+
+
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cte/CTEPlanTest.testCTE.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cte/CTEPlanTest.testCTE.yml
index fb0455ac0..6e2102485 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cte/CTEPlanTest.testCTE.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/cte/CTEPlanTest.testCTE.yml
@@ -12,12 +12,11 @@
     with cte as (select * from t1), cte2 as (select * from t2) select * from cte join cte2 on cte.id = cte2.id
 
   plan: |
-    BKAJoin(condition="id = id", type="inner")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].t1", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `t1` AS `t1`")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].t2_[0-7]", shardCount=8, sql="SELECT `id`, `name`, `create_time` FROM `t2` AS `t2` WHERE (`id` IN (...))")
-
+    bkajoin(condition="id = id", type="inner")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].t1", shardcount=4, sql="select `id`, `name`, `create_time` from `t1` as `t1`")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].t2_[0-7]", shardcount=8, sql="select `id`, `name`, `create_time` from `t2` as `t2` force index(`primary`) where (`id` in (...))")
 -
   sql: |
     with cte as (select * from t1), cte2 as (select count(*) from cte) select * from cte2
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.ddl.yml
index 3702d9a9e..424920ce8 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.ddl.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.ddl.yml
@@ -482,3 +482,28 @@ test_hash_tb2:
   KEY `auto_shard_key_ID` (`id`),
   KEY `auto_shard_key_ID_0` (`id`)
   ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`ID`);
+
+t1_upsert:
+   CREATE TABLE `t1_upsert` (
+     `ID` varchar(32) NOT NULL ,
+     `XX_DATE` date NOT NULL,
+     PRIMARY KEY (`ID`)
+  ) dbpartition by UNI_HASH(`id`) tbpartition by DD(`xx_date`) tbpartitions 31;
+
+t2_upsert:
+  CREATE TABLE `t2_upsert` (
+  `ID` varchar(32) NOT NULL ,
+  `name` varchar(30) DEFAULT NULL,
+  `XX_DATE` date NOT NULL,
+  PRIMARY KEY (`ID`),
+  GLOBAL INDEX `g_i_name`(`name`) DBPARTITION BY HASH(`name`)
+  ) dbpartition by UNI_HASH(`id`) tbpartition by DD(`xx_date`) tbpartitions 31;
+
+t3_upsert:
+  CREATE TABLE `t3_upsert` (
+  `ID` varchar(32) NOT NULL AUTO_INCREMENT,
+  `name` varchar(30) DEFAULT NULL,
+  `XX_DATE` date NOT NULL,
+  PRIMARY KEY (`ID`),
+  UNIQUE KEY `u_i_name`(`name`)
+  ) dbpartition by HASH(`name`) tbpartition by DD(`xx_date`) tbpartitions 31;
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.delete.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.delete.yml
index e5606fd86..ac5b42f07 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.delete.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.delete.yml
@@ -383,3 +383,44 @@
               logicalview(tables="[0000-0003].test_hash_ta", shardcount=4, sql="select `name`, `create_time`, `id` from `test_hash_ta` as `test_hash_ta` for update")
           gather(concurrent=true)
             logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` where (`id` in (...)) for update")
+
+- sql: |
+    delete t1 , t2 from test_hash_tb t1 force index(primary,xxx) , test_hash_ta t2 force index(xxx,primary) where t1.id = t2.id and t1.id = 1
+
+  plan: |
+    logicalmodifyview(tables="optest_0001.test_hash_tb,test_hash_ta", sql="delete `test_hash_tb`, `test_hash_ta` from `test_hash_tb` as `test_hash_tb` force index(primary) inner join `test_hash_ta` as `test_hash_ta` on ((`test_hash_tb`.`id` = ?) and (`test_hash_ta`.`id` = ?) and (`test_hash_tb`.`id` = `test_hash_ta`.`id`))")
+
+- sql: |
+    delete from t1 , t2 using test_hash_tb t1 force index(primary,xxx) , test_hash_ta t2 force index(xxx,primary) where t1.id = t2.id and t1.id = 1
+
+  plan: |
+    logicalmodifyview(tables="optest_0001.test_hash_tb,test_hash_ta", sql="delete `test_hash_tb`, `test_hash_ta` from `test_hash_tb` as `test_hash_tb` force index(primary) inner join `test_hash_ta` as `test_hash_ta` on ((`test_hash_tb`.`id` = ?) and (`test_hash_ta`.`id` = ?) and (`test_hash_tb`.`id` = `test_hash_ta`.`id`))")
+
+- sql: |
+    delete t1, t2 from test_hash_tb t1 force index(primary,xxx) , test_hash_ta t2 force index(auto_shard_key_ID,xxx) where t1.id = t2.id and t1.id = 1
+
+  plan: |
+    logicalmodifyview(tables="optest_0001.test_hash_tb,test_hash_ta", sql="delete `test_hash_tb`, `test_hash_ta` from `test_hash_tb` as `test_hash_tb` force index(primary) inner join `test_hash_ta` as `test_hash_ta` force index(auto_shard_key_id) on ((`test_hash_tb`.`id` = ?) and (`test_hash_ta`.`id` = ?) and (`test_hash_tb`.`id` = `test_hash_ta`.`id`))")
+
+- sql: |
+    delete t1, t2 from test_hash_tb t1 force index(primary,xxx) , test_hash_ta t2 force index(auto_shard_key_ID,xxx) where t1.name = t2.name
+
+  plan: |
+    logicalmodify(type="delete", tables="optest.test_hash_tb, optest.test_hash_ta")
+      bkajoin(condition="name = name", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(primary) for update")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_ta", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_ta` as `test_hash_ta` force index(auto_shard_key_id) where (`name` in (...)) for update")
+
+- sql: |
+    delete t1, t2 from test_hash_tb t1 force index(primary,xxx) , test_hash_ta t2 force index(auto_shard_key_ID,xxx),test_hash_tc t3 force index(xxx) where t1.name = t2.name and t1.id = t3.id and t1.id = 1
+
+  plan: |
+    logicalmodify(type="delete", tables="optest.test_hash_tb, optest.test_hash_ta")
+      project(id="id", name="name", create_time="create_time", id1="id1", name0="name0", create_time1="create_time1", id0="id0", key="key", create_time0="create_time0")
+        bkajoin(condition="name = name", type="inner")
+          gather(concurrent=true)
+            logicalview(tables="optest_0001.test_hash_tb,test_hash_tc", sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tc`.`id` as `id0`, `test_hash_tc`.`key`, `test_hash_tc`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` force index(primary) inner join `test_hash_tc` as `test_hash_tc` on ((`test_hash_tc`.`id` = ?) and (`test_hash_tb`.`id` = ?) and (`test_hash_tb`.`id` = `test_hash_tc`.`id`)) for update")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].test_hash_ta", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_ta` as `test_hash_ta` force index(auto_shard_key_id) where (`name` in (...)) for update")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.insert.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.insert.yml
index d3bf01471..a4390f901 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.insert.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.insert.yml
@@ -583,4 +583,36 @@
     cache node:
 
     gather(concurrent=true)
-      logicalview(tables="[0000-0003].test_hash_tb2", shardcount=4, sql="select `id`, `name`, `create_time`, `int_col1`, `int_col2`, `int_col3`, `int_col4`, `int_col5`, `int_col6` from `test_hash_tb2` as `test_hash_tb2`")
\ No newline at end of file
+      logicalview(tables="[0000-0003].test_hash_tb2", shardcount=4, sql="select `id`, `name`, `create_time`, `int_col1`, `int_col2`, `int_col3`, `int_col4`, `int_col5`, `int_col6` from `test_hash_tb2` as `test_hash_tb2`")
+
+- sql: |
+    
+    insert into t1_upsert(id, xx_date) values (1, "2024-01-27 00:00:00.0") on duplicate key update xx_date=values(xx_date);
+
+  plan: |
+    
+    phytableoperation(tables="optest_0001.[t1_upsert_27]", sql="insert into ? (`id`, `xx_date`) values(?, ?) on duplicate key update `xx_date` = values(`xx_date`)", params="`t1_upsert_27`,1,2024-01-27 00:00:00.0")
+    
+- sql: |
+    
+    insert into t2_upsert(id, name, xx_date) values (1, "b", "2024-01-27 00:00:00.0") on duplicate key update xx_date=values(xx_date);
+
+  plan: |
+    
+    logicalupsert(sql="insert into ? (`id`, `name`, `xx_date`) values(?, ?, ?) on duplicate key update `xx_date` = ?", uniquekeyselect=[select [[id]] on t2_upsert])
+
+- sql: |
+    
+    insert into t2_upsert(id, name, xx_date) values (1, "b", "2024-01-27 00:00:00.0") on duplicate key update xx_date=values(xx_date), name=values(name);
+
+  plan: |
+    
+    logicalupsert(sql="insert into ? (`id`, `name`, `xx_date`) values(?, ?, ?) on duplicate key update `xx_date` = ?, `name` = ?", uniquekeyselect=[select [[id]] on t2_upsert])
+
+- sql: |
+    
+    insert into t3_upsert(name, xx_date) values ("b", "2024-01-27 00:00:00.0") on duplicate key update xx_date=values(xx_date);
+
+  plan: |
+    
+    logicalupsert(sql="insert into ? (`id`, `name`, `xx_date`) values(?, ?, ?) on duplicate key update `xx_date` = ?", uniquekeyselect=[select [[id], [name]] on t3_upsert])
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.update.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.update.yml
deleted file mode 100644
index 3e57c6704..000000000
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ComplexDmlTest.update.yml
+++ /dev/null
@@ -1,358 +0,0 @@
-# one sharding table
-- sql: |
-    update test_hash_ta a set a.name = "a" where a.id = 1;
-
-  plan: |
-
-    LogicalModifyView(tables="optest_0001.test_hash_ta", sql="UPDATE `test_hash_ta` AS `test_hash_ta` SET `name` = ? WHERE (`id` = ?)")
-
-- sql: |
-    update test_hash_ta a, test_hash_ta b set b.name = "a" where a.id = b.id and a.id = 1;
-
-  plan: |
-    logicalmodifyview(tables="optest_0001.test_hash_ta", sql="update `test_hash_ta` as `test_hash_ta` inner join `test_hash_ta` as `test_hash_ta0` on ((`test_hash_ta`.`id` = ?) and (`test_hash_ta0`.`id` = ?) and (`test_hash_ta`.`id` = `test_hash_ta0`.`id`)) set `test_hash_ta0`.`name` = ?")
-
-- sql: |
-    update test_broadcast a, test_broadcast b set b.name = "a" where a.id = b.id and a.id = 1;
-
-  plan: |
-
-    LogicalView(tables="optest_0000.test_broadcast,test_broadcast", sql="UPDATE `test_broadcast` AS `a`, `test_broadcast` AS `b` SET `b`.`name` = ? WHERE ((`a`.`id` = `b`.`id`) AND (`a`.`id` = ?))", params="a,1")
-
-- sql: |
-    update test_hash_tb, test_hash_ta set test_hash_ta.name = "a" where test_hash_ta.id = test_hash_tb.id;
-
-  plan: |
-
-    LogicalModifyView(tables="[0000-0003].test_hash_tb,test_hash_ta", shardCount=4, sql="UPDATE `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_ta` AS `test_hash_ta` ON (`test_hash_tb`.`id` = `test_hash_ta`.`id`) SET `test_hash_ta`.`name` = ?")
-
-- sql: |
-    update test_hash_tb b, test_hash_ta a set a.name = "a" where a.id = b.id and a.id = 1;
-
-  plan: |
-    logicalmodifyview(tables="optest_0001.test_hash_tb,test_hash_ta", sql="update `test_hash_tb` as `test_hash_tb` inner join `test_hash_ta` as `test_hash_ta` on ((`test_hash_tb`.`id` = ?) and (`test_hash_ta`.`id` = ?) and (`test_hash_tb`.`id` = `test_hash_ta`.`id`)) set `test_hash_ta`.`name` = ?")
-
-- sql: |
-    update test_hash_tb as test_hash_ta, test_hash_ta as test_hash_tb set test_hash_tb.name = "a" where test_hash_ta.id = test_hash_tb.id and test_hash_tb.id = 1;
-
-  plan: |
-    logicalmodifyview(tables="optest_0001.test_hash_tb,test_hash_ta", sql="update `test_hash_tb` as `test_hash_tb` inner join `test_hash_ta` as `test_hash_ta` on ((`test_hash_tb`.`id` = ?) and (`test_hash_ta`.`id` = ?) and (`test_hash_tb`.`id` = `test_hash_ta`.`id`)) set `test_hash_ta`.`name` = ?")
-
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,FORBID_EXECUTE_DML_ALL=false)*/
-    update test_hash_tb a, test_hash_ta b set a.name = "a";
-
-  plan: |
-
-    LogicalModify(TYPE="UPDATE", SET="test_hash_tb.name=?0")
-      Project(id="id0", name="name0", create_time="create_time0", id0="id", name0="name", create_time0="create_time", gen$0="?0")
-        NlJoin(condition="true", type="inner")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].test_hash_ta", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_ta` AS `test_hash_ta` FOR UPDATE")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` FOR UPDATE")
-
-- sql: |
-    update test_hash_tc a set a.key = last_insert_id(a.key + 1) where a.key = 1;
-
-  plan: |
-    
-    logicalmodifyview(tables="[0000-0003].test_hash_tc", shardcount=4, sql="update `test_hash_tc` as `test_hash_tc` set `key` = last_insert_id((`key` + ?)) where (`key` = ?)")
-
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/
-    update test_broadcast a, test_hash_tb b set a.name = "a" where a.id = b.id and a.id = 1;
-
-  plan: |
-    logicalmodify(type="update", set="test_broadcast.name=?0")
-      logicalview(tables="optest_0001.test_hash_tb,test_broadcast", sql="select `test_broadcast`.`id`, `test_broadcast`.`name`, `test_broadcast`.`create_time`, `test_hash_tb`.`id` as `id0`, `test_hash_tb`.`name` as `name0`, `test_hash_tb`.`create_time` as `create_time0`, ? from `test_hash_tb` as `test_hash_tb` inner join `test_broadcast` as `test_broadcast` on ((`test_broadcast`.`id` = ?) and (`test_hash_tb`.`id` = ?) and (`test_hash_tb`.`id` = `test_broadcast`.`id`)) for update")
-- sql: |
-    update test_broadcast a, test_hash_tb b set b.name = "a" where a.id = b.id and a.id = 1;
-
-  plan: |
-    logicalmodifyview(tables="optest_0001.test_hash_tb,test_broadcast", sql="update `test_hash_tb` as `test_hash_tb` inner join `test_broadcast` as `test_broadcast` on ((`test_broadcast`.`id` = ?) and (`test_hash_tb`.`id` = ?) and (`test_hash_tb`.`id` = `test_broadcast`.`id`)) set `test_hash_tb`.`name` = ?")
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/
-    update test_broadcast a, test_hash_tb b set a.name = "a", b.name = "b" where a.id = b.id and a.id = 1;
-
-  plan: |
-    logicalmodify(type="update", set="test_broadcast.name=?0, test_hash_tb.name=?1")
-      logicalview(tables="optest_0001.test_hash_tb,test_broadcast", sql="select `test_broadcast`.`id`, `test_broadcast`.`name`, `test_broadcast`.`create_time`, `test_hash_tb`.`id` as `id0`, `test_hash_tb`.`name` as `name0`, `test_hash_tb`.`create_time` as `create_time0`, ?, ? as `gen$1` from `test_hash_tb` as `test_hash_tb` inner join `test_broadcast` as `test_broadcast` on ((`test_broadcast`.`id` = ?) and (`test_hash_tb`.`id` = ?) and (`test_hash_tb`.`id` = `test_broadcast`.`id`)) for update")
-- sql: |
-    update test_broadcast a set a.id = last_insert_id(a.id + 1) where a.id = 1;
-
-  plan: |
-
-    logicalmodify(type="update", set="test_broadcast.id=last_insert_id(+($0, ?0))")
-      project(id="id", name="name", create_time="create_time", gen$0="last_insert_id(id + ?0)")
-        logicalview(tables="optest_0000.test_broadcast", sql="select `id`, `name`, `create_time` from `test_broadcast` as `test_broadcast` where (`id` = ?) for update")
-
-- sql: |
-    update test_broadcast a, test_hash_tb b set a.id = last_insert_id(a.id + 1), b.name = "b" where a.id = b.id and a.id = 1;
-
-  plan: |
-
-    logicalmodify(type="update", set="test_broadcast.id=last_insert_id(+($0, ?0)), test_hash_tb.name=?1")
-      project(id="id0", name="name0", create_time="create_time0", id0="id", name0="name", create_time0="create_time", gen$0="last_insert_id(id0 + ?0)", gen$1="?1")
-        logicalview(tables="optest_0001.test_hash_tb,test_broadcast", sql="select `test_broadcast`.`id` as `id0`, `test_broadcast`.`name` as `name0`, `test_broadcast`.`create_time` as `create_time0`, `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time` from `test_hash_tb` as `test_hash_tb` inner join `test_broadcast` as `test_broadcast` on ((`test_broadcast`.`id` = ?) and (`test_hash_tb`.`id` = ?) and (`test_hash_tb`.`id` = `test_broadcast`.`id`)) for update")
-
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/
-    update test_single a, test_hash_tb b set b.name = "a" where a.id = b.id and a.id = 1;
-
-  plan: |
-
-    LogicalModify(TYPE="UPDATE", SET="test_hash_tb.name=?0")
-      Project(id="id0", name="name0", create_time="create_time0", id0="id", name0="name", create_time0="create_time", gen$0="?0")
-        HashJoin(condition="id = id", type="inner")
-          LogicalView(tables="optest_0001.test_hash_tb", sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` WHERE (`id` = ?) FOR UPDATE")
-          LogicalView(tables="optest_0000.test_single", sql="SELECT `id`, `name`, `create_time` FROM `test_single` AS `test_single` WHERE (`id` = ?) FOR UPDATE")
-
-- sql: |
-    update test_single a join test_hash_tb b set b.name = "a" where a.id = b.id and a.id = 0;
-
-  plan: |
-
-    PhyTableOperation(tables="optest_0000.[test_single, test_hash_tb]", sql="UPDATE ? AS `a` INNER JOIN ? AS `b` SET `b`.`name` = ? WHERE ((`a`.`id` = `b`.`id`) AND (`a`.`id` = ?))", params="`test_single`,`test_hash_tb`,a,0")
-
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/
-    update test_single a, test_hash_tb b set a.name = "a", b.name = "b" where a.id = b.id and a.id = 1;
-
-  plan: |
-
-    LogicalModify(TYPE="UPDATE", SET="test_single.name=?0, test_hash_tb.name=?1")
-      Project(id="id0", name="name0", create_time="create_time0", id0="id", name0="name", create_time0="create_time", gen$0="?0", gen$1="?1")
-        HashJoin(condition="id = id", type="inner")
-          LogicalView(tables="optest_0001.test_hash_tb", sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` WHERE (`id` = ?) FOR UPDATE")
-          LogicalView(tables="optest_0000.test_single", sql="SELECT `id`, `name`, `create_time` FROM `test_single` AS `test_single` WHERE (`id` = ?) FOR UPDATE")
-
-- sql: |
-    update test_broadcast a, test_broadcast_b b set a.name = "a" where a.id = b.id and a.id = 1;
-
-  plan: |
-
-    LogicalView(tables="optest_0000.test_broadcast,test_broadcast_b", sql="UPDATE `test_broadcast` AS `a`, `test_broadcast_b` AS `b` SET `a`.`name` = ? WHERE ((`a`.`id` = `b`.`id`) AND (`a`.`id` = ?))", params="a,1")
-
-- sql: |
-    update test_broadcast a, test_broadcast_b b set b.name = "b" where a.id = b.id and a.id = 1;
-
-  plan: |
-
-    LogicalView(tables="optest_0000.test_broadcast,test_broadcast_b", sql="UPDATE `test_broadcast` AS `a`, `test_broadcast_b` AS `b` SET `b`.`name` = ? WHERE ((`a`.`id` = `b`.`id`) AND (`a`.`id` = ?))", params="b,1")
-
-- sql: |
-    update test_hash_ta a join (select name, id from test_hash_tb b where b.name = "c" and b.id = 1) b set a.name = b.name where a.id = b.id;
-
-  plan: |
-
-    PhyTableOperation(tables="optest_0001.[test_hash_ta, test_hash_tb]", sql="UPDATE ? AS `a` INNER JOIN (SELECT `b`.`name` AS `name`, `b`.`id` AS `id` FROM ? AS `b` WHERE ((`b`.`name` = ?) AND (`b`.`id` = ?))) AS `b` SET `a`.`name` = `b`.`name` WHERE (`a`.`id` = `b`.`id`)", params="`test_hash_ta`,`test_hash_tb`,c,1")
-
-- sql: |
-    update test_broadcast a join (select name, id from test_broadcast b where b.name = "c" and b.id = 1) b set a.name = b.name where a.id = b.id;
-
-  plan: |
-
-    LogicalView(tables="optest_0000.test_broadcast,test_broadcast", sql="UPDATE `test_broadcast` AS `a` INNER JOIN (SELECT `b`.`name` AS `name`, `b`.`id` AS `id` FROM `test_broadcast` AS `b` WHERE ((`b`.`name` = ?) AND (`b`.`id` = ?))) AS `b` SET `a`.`name` = `b`.`name` WHERE (`a`.`id` = `b`.`id`)", params="c,1")
-
-- sql: |
-    update test_hash_tb a join (select name, id from test_broadcast b where b.name = "c" and b.id = 1) b set a.name = b.name where a.id = b.id;
-
-  plan: |
-
-    PhyTableOperation(tables="optest_0001.[test_hash_tb, test_broadcast]", sql="UPDATE ? AS `a` INNER JOIN (SELECT `b`.`name` AS `name`, `b`.`id` AS `id` FROM ? AS `b` WHERE ((`b`.`name` = ?) AND (`b`.`id` = ?))) AS `b` SET `a`.`name` = `b`.`name` WHERE (`a`.`id` = `b`.`id`)", params="`test_hash_tb`,`test_broadcast`,c,1")
-
-- sql: |
-    update test_hash_tb a join (select name, id from test_broadcast b where b.name = "c" and b.id = 1) b set a.id = last_insert_id(a.id + 1) where a.id = b.id;
-
-  plan: |
-
-    logicalrelocate(type=update, set="test_hash_tb.id=last_insert_id(+($0, ?2))", relocate="test_hash_tb")
-      project(id="id0", name="name0", create_time="create_time", name0="name", id0="id", gen$0="last_insert_id(id0 + ?2)")
-        gather(concurrent=true)
-          logicalview(tables="optest_0001.test_broadcast,test_hash_tb", sql="select `test_hash_tb`.`id` as `id0`, `test_hash_tb`.`name` as `name0`, `test_hash_tb`.`create_time`, `test_broadcast`.`name`, `test_broadcast`.`id` from `test_broadcast` as `test_broadcast` inner join `test_hash_tb` as `test_hash_tb` on (`test_broadcast`.`id` = `test_hash_tb`.`id`) where ((`test_broadcast`.`id` = ?) and (`test_broadcast`.`name` = ?)) for update")
-
-- sql: |
-    update test_broadcast a join (select name, id from test_hash_ta b where b.name = "c" and b.id = 1) b set a.name = b.name where a.id = b.id;
-
-  plan: |
-    logicalmodify(type="update", set="test_broadcast.name=$3")
-      logicalview(tables="optest_0001.test_hash_ta,test_broadcast", sql="select `test_broadcast`.`id`, `test_broadcast`.`name`, `test_broadcast`.`create_time`, `test_hash_ta`.`name` as `name0`, `test_hash_ta`.`id` as `id0`, `test_hash_ta`.`name` as `gen$0` from `test_hash_ta` as `test_hash_ta` inner join `test_broadcast` as `test_broadcast` on (`test_hash_ta`.`id` = `test_broadcast`.`id`) where ((`test_hash_ta`.`id` = ?) and (`test_hash_ta`.`name` = ?)) for update")
-
-- sql: |
-    update test_broadcast a join (select name, id from test_hash_ta b where b.name = "c" and b.id = 1) b set a.id = last_insert_id(a.id + 1) where a.id = b.id;
-
-  plan: |
-    logicalmodify(type="update", set="test_broadcast.id=last_insert_id(+($0, ?2))")
-      project(id="id0", name="name0", create_time="create_time", name0="name", id0="id", gen$0="last_insert_id(id0 + ?2)")
-        logicalview(tables="optest_0001.test_hash_ta,test_broadcast", sql="select `test_broadcast`.`id` as `id0`, `test_broadcast`.`name` as `name0`, `test_broadcast`.`create_time`, `test_hash_ta`.`name`, `test_hash_ta`.`id` from `test_hash_ta` as `test_hash_ta` inner join `test_broadcast` as `test_broadcast` on (`test_hash_ta`.`id` = `test_broadcast`.`id`) where ((`test_hash_ta`.`id` = ?) and (`test_hash_ta`.`name` = ?)) for update")
-
-
-  # Modify sharding key
-
-# Modify sharding key of primary
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_MODIFY_SHARDING_COLUMN = true)*/
-    update test_hash_tb a set a.id = "3", a.name = "b" where a.id = 1;
-
-  plan: |
-
-    LogicalRelocate(TYPE=UPDATE, SET="test_hash_tb.id=?0, test_hash_tb.name=?1", RELOCATE="test_hash_tb")
-      LogicalView(tables="optest_0001.test_hash_tb", sql="SELECT `id`, `name`, `create_time`, ?, ? as `gen$1` FROM `test_hash_tb` AS `test_hash_tb` WHERE (`id` = ?) FOR UPDATE")
-
-- sql: |
-    update test_hash_tc a set a.id = last_insert_id(a.id + 1) where a.id = 1;
-
-  plan: |
-    
-    logicalrelocate(type=update, set="test_hash_tc.id=last_insert_id(+($0, ?0))", relocate="test_hash_tc")
-      project(id="id", key="key", create_time="create_time", gen$0="last_insert_id(id + ?0)")
-        logicalview(tables="optest_0001.test_hash_tc", sql="select `id`, `key`, `create_time` from `test_hash_tc` as `test_hash_tc` where (`id` = ?) for update")
-
-  # Modify sharding key of primary and not gsi
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_MODIFY_SHARDING_COLUMN = true)*/
-    update t1 a set a.c1 = 1 where a.c1 = 3;
-
-  plan: |
-
-    LogicalRelocate(TYPE=UPDATE, SET="t1.c1=?0", RELOCATE="t1", UPDATE="t1_i_a, t1_i_b")
-      LogicalView(tables="optest_0000.t1_03", sql="SELECT `pk`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`, ? FROM `t1` AS `t1` WHERE (`c1` = ?) FOR UPDATE")
-
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_MODIFY_SHARDING_COLUMN = true)*/
-    update t1 a set a.c1 = last_insert_id(a.c1 + 1) where a.c1 = 3;
-
-  plan: |
-
-    logicalrelocate(type=update, set="t1.c1=last_insert_id(+($1, ?0))", relocate="t1", update="t1_i_a, t1_i_b")
-      project(pk="pk", c1="c1", c2="c2", c3="c3", c4="c4", c5="c5", c6="c6", c7="c7", c8="c8", gen$0="last_insert_id(c1 + ?0)")
-        logicalview(tables="optest_0000.t1_03", sql="select `pk`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` from `t1` as `t1` where (`c1` = ?) for update")
-
-  # Modify sharding key of primary and one gsi
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_MODIFY_SHARDING_COLUMN = true)*/
-    update t1 a set a.c1 = 1, a.c2 = 2 where a.c1 = 3;
-
-  plan: |
-
-    LogicalRelocate(TYPE=UPDATE, SET="t1.c1=?0, t1.c2=?1", RELOCATE="t1, t1_i_b", UPDATE="t1_i_a")
-      LogicalView(tables="optest_0000.t1_03", sql="SELECT `pk`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`, ?, ? as `gen$1` FROM `t1` AS `t1` WHERE (`c1` = ?) FOR UPDATE")
-
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_MODIFY_SHARDING_COLUMN = true)*/
-    update t1 a set a.c1 = 1, a.c2 = last_insert_id(a.c2 + 1) where a.c1 = 3;
-
-  plan: |
-
-    logicalrelocate(type=update, set="t1.c1=?0, t1.c2=last_insert_id(+($2, ?1))", relocate="t1, t1_i_b", update="t1_i_a")
-      project(pk="pk", c1="c1", c2="c2", c3="c3", c4="c4", c5="c5", c6="c6", c7="c7", c8="c8", gen$0="?0", gen$1="last_insert_id(c2 + ?1)")
-        logicalview(tables="optest_0000.t1_03", sql="select `pk`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` from `t1` as `t1` where (`c1` = ?) for update")
-
-  # Modify sharding key of one gsi not primary and skip another gsi
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_MODIFY_SHARDING_COLUMN = true)*/
-    update t1 a set a.c3 = 1, a.c6 = 2 where a.c3 = 3;
-
-  plan: |
-
-    LogicalRelocate(TYPE=UPDATE, SET="t1.c3=?0, t1.c6=?1", RELOCATE="t1_i_a", UPDATE="t1")
-      Project(pk="pk", c1="c1", c2="c2", c3="c3", c4="c4", c5="c5", c6="c6", c7="c7", c8="c8", gen$0="?0", gen$1="?1")
-        BKAJoin(condition="pk = pk AND c1 <=> c1", type="inner")
-          IndexScan(tables="optest_0000.t1_i_a_03", sql="SELECT `pk`, `c1`, `c3`, `c5`, `c6` FROM `t1_i_a` AS `t1_i_a` WHERE (`c3` = ?) FOR UPDATE")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].t1_[00-27]", shardCount=28, sql="SELECT `pk`, `c1`, `c2`, `c4`, `c7`, `c8` FROM `t1` AS `t1` WHERE ((`c3` = ?) AND (`pk` IN (...))) FOR UPDATE")
-
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_MODIFY_SHARDING_COLUMN = true)*/
-    update t1 a set a.c3 = last_insert_id(a.c3 + 1), a.c6 = last_insert_id(a.c6 + 2) where a.c3 = 3;
-
-  plan: |
-
-    logicalrelocate(type=update, set="t1.c3=last_insert_id(+($3, ?0)), t1.c6=last_insert_id(+(cast($6):bigint, ?1))", relocate="t1_i_a", update="t1")
-      project(pk="pk", c1="c1", c2="c2", c3="c3", c4="c4", c5="c5", c6="c6", c7="c7", c8="c8", gen$0="last_insert_id(c3 + ?0)", gen$1="last_insert_id(cast(c6) + ?1)")
-        bkajoin(condition="pk = pk and c1 <=> c1", type="inner")
-          indexscan(tables="optest_0000.t1_i_a_03", sql="select `pk`, `c1`, `c3`, `c5`, `c6` from `t1_i_a` as `t1_i_a` where (`c3` = ?) for update")
-          gather(concurrent=true)
-            logicalview(tables="[0000-0003].t1_[00-27]", shardcount=28, sql="select `pk`, `c1`, `c2`, `c4`, `c7`, `c8` from `t1` as `t1` where ((`c3` = ?) and (`pk` in (...))) for update")
-
-
-- sql: |
-    /*+TDDL:CMD_EXTRA(ENABLE_MODIFY_SHARDING_COLUMN = true)*/
-    update test_hash_ta a join test_hash_tb b on a.id = b.id set a.id = b.id * 2;
-
-  plan: |
-
-    LogicalRelocate(TYPE=UPDATE, SET="test_hash_ta.id=*($3, ?0)", RELOCATE="test_hash_ta")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_hash_ta,test_hash_tb", shardCount=4, sql="SELECT `test_hash_ta`.`id`, `test_hash_ta`.`name`, `test_hash_ta`.`create_time`, `test_hash_tb`.`id` AS `id0`, `test_hash_tb`.`name` AS `name0`, `test_hash_tb`.`create_time` AS `create_time0`, (`test_hash_tb`.`id` * ?) FROM `test_hash_ta` AS `test_hash_ta` INNER JOIN `test_hash_tb` AS `test_hash_tb` ON (`test_hash_ta`.`id` = `test_hash_tb`.`id`) FOR UPDATE")
-
-# Fastsql bug fixed
-- sql: |
-    UPDATE gx_brand_votelist SET itemid= "3674133",brandid= "1527519",name= "章丘市万源有色金属铸造有限公司",introduce= "" WHERE itemid = 3674133 AND brandid = 1527519
-
-  plan: |
-    err-code: [pxc-4500][err_parser] syntax error, error in :'" b.pk set a.pk = a.pk * 2, b.pk = b.pk * 5
-
-  plan: |
-
-    LogicalModifyView(tables="[0000-0003].self_join_t1", shardCount=4, sql="UPDATE `self_join_t1` AS `self_join_t1` INNER JOIN `self_join_t1` AS `self_join_t10` ON ((`self_join_t1`.`c1` = `self_join_t10`.`c1`) AND (`self_join_t1`.`pk` > `self_join_t10`.`pk`)) SET `self_join_t1`.`pk` = (`self_join_t1`.`pk` * ?) , `self_join_t10`.`pk` = (`self_join_t10`.`pk` * ?)")
-
-- sql: |
-    update deliver_task task join( select ot.deliver_task_id, count(1) outbound_quantity from deliver_task dt join outbound_transaction ot on dt.relation_bill= ot.relation_bill and dt.id= ot.deliver_task_id where dt.status= 'UN_EXECUTE' and dt.deliver_type= 'ALLOCATION' group by ot.deliver_task_id) org on task.id= org.deliver_task_id set task.actual_deliver_quantity= org.outbound_quantity where task.actual_deliver_quantity!= org.outbound_quantity
-
-  plan: |
-    logicalmodify(type="update", set="deliver_task.actual_deliver_quantity=$34")
-      project(id="id", approve_id="approve_id", status="status", relation_bill="relation_bill", deliver_date="deliver_date", material_type_code="material_type_code", material_type_name="material_type_name", unit="unit", deliver_type="deliver_type", deliver_site_code="deliver_site_code", deliver_site_name="deliver_site_name", deliver_site_type="deliver_site_type", to_site_code="to_site_code", to_site_name="to_site_name", to_site_type="to_site_type", execute_employee_no="execute_employee_no", execute_employee_name="execute_employee_name", execute_date="execute_date", deliver_quantity="deliver_quantity", actual_deliver_quantity="actual_deliver_quantity", deploy_employee_no="deploy_employee_no", deploy_employee_name="deploy_employee_name", deploy_date="deploy_date", remarks="remarks", creator="creator", gmt_create="gmt_create", modifier="modifier", gmt_modified="gmt_modified", requisition_no="requisition_no", display_flag="display_flag", operate_machine_type="operate_machine_type", operate_machine_serial="operate_machine_serial", cancel_remarks="cancel_remarks", deliver_task_id="deliver_task_id", outbound_quantity="outbound_quantity", gen$0="outbound_quantity")
-        bkajoin(condition="deliver_task_id = id and actual_deliver_quantity <> outbound_quantity", type="inner")
-          hashagg(group="deliver_task_id", outbound_quantity="count()")
-            bkajoin(condition="deliver_task_id = id and relation_bill = relation_bill", type="inner")
-              logicalview(tables="optest_0000.deliver_task", sql="select `id`, `relation_bill` from `deliver_task` as `deliver_task` where ((`status` = ?) and (`deliver_type` = ?)) for update")
-              gather(concurrent=true)
-                logicalview(tables="[0000-0003].outbound_transaction_[000-511]", shardcount=512, sql="select `relation_bill`, `deliver_task_id` from `outbound_transaction` as `outbound_transaction` where (((`deliver_task_id`, `relation_bill`)) in (...)) for update")
-          logicalview(tables="optest_0000.deliver_task", sql="select `id`, `approve_id`, `status`, `relation_bill`, `deliver_date`, `material_type_code`, `material_type_name`, `unit`, `deliver_type`, `deliver_site_code`, `deliver_site_name`, `deliver_site_type`, `to_site_code`, `to_site_name`, `to_site_type`, `execute_employee_no`, `execute_employee_name`, `execute_date`, `deliver_quantity`, `actual_deliver_quantity`, `deploy_employee_no`, `deploy_employee_name`, `deploy_date`, `remarks`, `creator`, `gmt_create`, `modifier`, `gmt_modified`, `requisition_no`, `display_flag`, `operate_machine_type`, `operate_machine_serial`, `cancel_remarks` from `deliver_task` as `deliver_task` where ((`id` is not null) and (`id` in (...))) for update")
-
-- sql: |
-    update `optest`.`img` set `optest`.`img`.`ding_count` = (`optest`.`img`.`ding_count` + 1), `optest`.`img`.`is_ding` = 1 where `optest`.`img`.`imgid` in (1618372744)
-
-  plan: |
-
-    LogicalModifyView(tables="optest_0003.img_40", sql="UPDATE `img` AS `img` SET `ding_count` = (`ding_count` + ?) , `is_ding` = ? WHERE (`imgid` IN(?))")
-
-- sql: |
-    update test_hash_tb m,( select 'byname1' as name,'2024-05-10 11:50:00' as create_time, 1 as id union all select 'byname2' ,'2024-05-10 11:51:00', 2 ) r set m.name = r.name, m.create_time=r.create_time where m.id = r.id
-
-  plan: |
-
-    logicalmodify(type="update", set="test_hash_tb.name=$3, test_hash_tb.create_time=$4")
-      project(id="id0", name="name0", create_time="create_time0", name0="name", create_time0="create_time", id0="id", gen$0="name", gen$1="create_time")
-        bkajoin(condition="id = id", type="inner")
-          dynamicvalues(tuples=[{ ?0, ?1, ?2 }, { ?3, ?4, ?5 }])
-          gather(concurrent=true)
-            logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` where (`id` in (...)) for update")
-
-- sql: |
-    update test_hash_tb m,( select 'byname1' as name,'2024-05-10 11:50:00' as create_time, 1 as id union all select name, create_time, id from test_hash_ta ) r set m.name = r.name, m.create_time=r.create_time where m.id = r.id
-
-  plan: |
-
-    logicalmodify(type="update", set="test_hash_tb.name=$3, test_hash_tb.create_time=$4")
-      project(id="id0", name="name0", create_time="create_time0", name0="name", create_time0="create_time", id0="id", gen$0="name", gen$1="create_time")
-        bkajoin(condition="id = id", type="inner")
-          unionall(concurrent=true)
-            project(name="?0", create_time="?1", id="?2")
-              values(table="dual")
-            gather(concurrent=true)
-              logicalview(tables="[0000-0003].test_hash_ta", shardcount=4, sql="select `name`, `create_time`, `id` from `test_hash_ta` as `test_hash_ta` for update")
-          gather(concurrent=true)
-            logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` where (`id` in (...)) for update")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ModifyTopNTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ModifyTopNTest.ddl.yml
new file mode 100644
index 000000000..dae037d63
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ModifyTopNTest.ddl.yml
@@ -0,0 +1,546 @@
+test_hash_tb:
+  CREATE TABLE `test_hash_tb` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_hash_ta:
+  CREATE TABLE `test_hash_ta` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_hash_tc:
+  CREATE TABLE `test_hash_tc` (
+  `id` int(11) NOT NULL,
+  `key` int(11) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_single:
+  CREATE TABLE `test_single` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 single;
+
+test_broadcast:
+  CREATE TABLE `test_broadcast` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST;
+
+test_broadcast_b:
+  CREATE TABLE `test_broadcast_b` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST;
+
+test_group_sequence:
+  CREATE TABLE `test_group_sequence` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_time_sequence:
+  CREATE TABLE `test_time_sequence` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT BY TIME,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` timestamp,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_compound_key:
+  CREATE TABLE `test_compound_key` (
+  `id` bigint(20) NOT NULL,
+  `name` bigint(20) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`) subpartition by hash(`NAME`) subpartitions 2;
+
+test_tb_without_pk:
+  CREATE TABLE `test_tb_without_pk` (
+  `id`                BIGINT(11)   NOT NULL DEFAULT 1,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_without_pk_has_uk:
+  CREATE TABLE `test_tb_without_pk_has_uk` (
+  `id`                BIGINT(11)   NOT NULL DEFAULT 1,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  UNIQUE KEY (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_auto_increment:
+  CREATE TABLE `test_tb_pk_auto_increment` (
+  `pk`                BIGINT(11)   NOT NULL AUTO_INCREMENT,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_no_auto_increment_no_default:
+  CREATE TABLE `test_tb_pk_no_auto_increment_no_default` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_no_auto_increment_default_1:
+  CREATE TABLE `test_tb_pk_no_auto_increment_default_1` (
+  `pk`                BIGINT(11)   NOT NULL DEFAULT 1,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_auto_increment_with_ugsi:
+  CREATE TABLE `test_tb_pk_auto_increment_with_ugsi` (
+  `pk`                BIGINT(11)   NOT NULL AUTO_INCREMENT,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  UNIQUE INDEX uk_c4(c4, c3),
+  GLOBAL UNIQUE INDEX g_u_c2_a(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_no_auto_increment_no_default_with_ugsi:
+  CREATE TABLE `test_tb_pk_no_auto_increment_no_default_with_ugsi` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  UNIQUE INDEX uk_c4(c4, c3),
+  GLOBAL UNIQUE INDEX g_u_c2_b(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_no_auto_increment_default_1_with_ugsi:
+  CREATE TABLE `test_tb_pk_no_auto_increment_default_1_with_ugsi` (
+  `pk`                BIGINT(11)   NOT NULL DEFAULT 1,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  UNIQUE INDEX uk_c4(c4, c3),
+  GLOBAL UNIQUE INDEX g_u_c2_c(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+t1:
+  CREATE TABLE `t1` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  GLOBAL INDEX t1_i_a(c3) COVERING(c5, c6) partition BY HASH(c3) subpartition by HASH(c3) subpartitions 7,
+  GLOBAL UNIQUE INDEX t1_i_b(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+t2:
+  CREATE TABLE `t2` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  GLOBAL INDEX t2_i_a(c3) COVERING(c5, c6) partition BY HASH(c3) subpartition by HASH(c3) subpartitions 7,
+  GLOBAL UNIQUE INDEX t2_i_b(c1) COVERING(c5) partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+
+t3:
+  CREATE TABLE `t3` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  GLOBAL INDEX t3_i_a(c3) COVERING(c5, c6) partition BY HASH(c3) subpartition by HASH(c3) subpartitions 7,
+  GLOBAL UNIQUE INDEX t3_i_b(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+t4:
+  CREATE TABLE `t4` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  UNIQUE INDEX uk_c4(c4),
+  GLOBAL INDEX t4_i_a(c3) COVERING(c5, c6) partition BY HASH(c3) subpartition by HASH(c3) subpartitions 7,
+  GLOBAL UNIQUE INDEX t4_i_b(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+gx_brand_votelist:
+  CREATE TABLE `gx_brand_votelist` (
+  `itemid` int(20) UNSIGNED NOT NULL AUTO_INCREMENT BY GROUP,
+  `brandid` int(20) UNSIGNED NOT NULL DEFAULT '0'                                                     ,
+  `groupid` int(11) UNSIGNED NOT NULL DEFAULT '0'                                                     ,
+  `num` int(3) UNSIGNED NOT NULL DEFAULT '0'                                                          ,
+  `name` varchar(100) NOT NULL DEFAULT ''                                                             ,
+  `introduce` text NOT NULL                                                                           ,
+  `video` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT ''                                         ,
+  `votes` int(20) UNSIGNED NOT NULL DEFAULT '0'                                                       ,
+  `status` int(2) UNSIGNED NOT NULL DEFAULT '3'                                                       ,
+  `zvote` int(20) UNSIGNED NOT NULL DEFAULT '0'                                                       ,
+  `zvote1` int(11) UNSIGNED NOT NULL DEFAULT '0'                                                      ,
+  `kouvote` int(11) UNSIGNED NOT NULL DEFAULT '0'                                                     ,
+  `truevote` int(20) UNSIGNED NOT NULL DEFAULT '0'                                                    ,
+  `yzm` tinyint(3) UNSIGNED NOT NULL DEFAULT '4'                                                      ,
+  `shuatime` decimal(3, 1) UNSIGNED NOT NULL DEFAULT '99.0'                                           ,
+  `shuanum` tinyint(4) UNSIGNED NOT NULL DEFAULT '1'                                                  ,
+  `addtime` int(11) UNSIGNED NOT NULL DEFAULT '0'                                                     ,
+  `userid` int(10) UNSIGNED NOT NULL DEFAULT '0'                                                      ,
+  `usertype` tinyint(2) UNSIGNED NOT NULL DEFAULT '0'                                                 ,
+  `is_ht` tinyint(1) NOT NULL DEFAULT '0'                                                             ,
+  `is_apply` tinyint(1) NOT NULL DEFAULT '0'                                                          ,
+  `ranking` smallint(5) UNSIGNED NOT NULL DEFAULT '0'                                                 ,
+  `username` varchar(30) CHARACTER SET utf8 NOT NULL DEFAULT ''                                        ,
+  `erweima` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT ''                                        ,
+  `editor` varchar(50) CHARACTER SET utf8 NOT NULL DEFAULT ''                                          ,
+  `edittime` int(11) UNSIGNED NOT NULL DEFAULT '0'                                                    ,
+  `shebei` int(11) UNSIGNED NOT NULL DEFAULT '0'                                                      ,
+  `note` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT ''                                          ,
+  `sid` varchar(30) NOT NULL DEFAULT ''                                                               ,
+  `top_ten` tinyint(3) UNSIGNED NOT NULL DEFAULT '2'                                                  ,
+  `email` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT ''                                         ,
+  `tel` varchar(255) NOT NULL DEFAULT ''                                                              ,
+  `qq` varchar(50) NOT NULL DEFAULT ''                                                                ,
+  `remark` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT ''                                        ,
+  `web` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT ''                                           ,
+  `xianzhi` smallint(5) UNSIGNED NOT NULL DEFAULT '0'                                                 ,
+  `wxnum` int(10) UNSIGNED NOT NULL DEFAULT '0'                                                       ,
+  `backgift` int(10) UNSIGNED NOT NULL DEFAULT '0'                                                    ,
+  `giftvote` int(10) UNSIGNED NOT NULL DEFAULT '0'                                                    ,
+  `regCapital` decimal(10, 2) NOT NULL DEFAULT '0.00'                                                 ,
+  `actualCapital` decimal(10, 2) NOT NULL DEFAULT '0.00'                                              ,
+  `attention` int(11) NOT NULL DEFAULT '0'                                                            ,
+  `tuiguang` tinyint(1) UNSIGNED NOT NULL DEFAULT '1'                                                 ,
+  `regyear` varchar(255) NOT NULL DEFAULT ''                                                          ,
+  `is_new` tinyint(1) UNSIGNED NOT NULL DEFAULT '1'                                                   ,
+  `is_sign` tinyint(1) UNSIGNED NOT NULL DEFAULT '2'                                                  ,
+  `gongsi_status` tinyint(2) NOT NULL DEFAULT '0'                                                     ,
+  `share_count` int(11) UNSIGNED NOT NULL DEFAULT '0'                                                 ,
+  `share_click` int(11) UNSIGNED NOT NULL DEFAULT '0'                                                 ,
+  `company_status` tinyint(1) NOT NULL DEFAULT '0'                                                    ,
+  `address` varchar(255) NOT NULL DEFAULT ''                                                          ,
+  `shenhe_pingtai_status` tinyint(4) NOT NULL DEFAULT '0'                                             ,
+  `video_url` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT ''                                     ,
+  `anjian_num` int(10) UNSIGNED NOT NULL DEFAULT '0'                                                  ,
+  PRIMARY KEY (`itemid`),
+  KEY `brandid` (`brandid`),
+  KEY `status` USING BTREE (`status`),
+  KEY `votes` USING BTREE (`votes`),
+  KEY `rds_idx_0` (`shuatime`, `brandid`, `status`),
+  KEY `shuatime` USING BTREE (`shuatime`),
+  KEY `idx_name` USING BTREE (`name`),
+  KEY `idx_brandid_shuatime_status_shuanum` USING BTREE (`brandid`, `status`, `shuatime`, `shuanum`),
+  KEY `idx_yzm_status` USING BTREE (`status`, `yzm`),
+  KEY `idx_status_isht_isapply_addtime` USING BTREE (`status`, `addtime`, `is_ht`, `is_apply`)
+  ) ENGINE = InnoDB AUTO_INCREMENT = 8519643 DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC partition by hash(`brandid`)
+
+self_join_t1:
+  CREATE TABLE `self_join_t1` (
+  `pk` int(11) NOT NULL,
+  `c1` int(11) DEFAULT NULL,
+  PRIMARY KEY (`pk`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 partition BY HASH(c1)
+
+deliver_task:
+  CREATE TABLE `deliver_task` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `approve_id` char(20) DEFAULT NULL,
+  `status` varchar(32) NOT NULL                                    COMMENT '',
+  `relation_bill` varchar(32) NOT NULL                             COMMENT '',
+  `deliver_date` datetime NOT NULL                                 COMMENT '',
+  `material_type_code` varchar(32) NOT NULL                        COMMENT '',
+  `material_type_name` varchar(64) NOT NULL                        COMMENT '',
+  `unit` varchar(16) NOT NULL                                      COMMENT '',
+  `deliver_type` varchar(32) NOT NULL                              COMMENT '',
+  `deliver_site_code` varchar(32) NOT NULL                         COMMENT '',
+  `deliver_site_name` varchar(128) NOT NULL                        COMMENT '',
+  `deliver_site_type` varchar(32) NOT NULL                         COMMENT '',
+  `to_site_code` varchar(32) NOT NULL                              COMMENT '',
+  `to_site_name` varchar(128) NOT NULL                             COMMENT '',
+  `to_site_type` varchar(32) NOT NULL                              COMMENT '',
+  `execute_employee_no` varchar(32) DEFAULT NULL                   COMMENT '',
+  `execute_employee_name` varchar(64) DEFAULT NULL                 COMMENT '',
+  `execute_date` datetime DEFAULT NULL                             COMMENT '',
+  `deliver_quantity` int(11) DEFAULT '0'                           COMMENT '',
+  `actual_deliver_quantity` int(11) DEFAULT '0'                    COMMENT '',
+  `deploy_employee_no` varchar(32) DEFAULT NULL                    COMMENT '',
+  `deploy_employee_name` varchar(64) DEFAULT NULL                  COMMENT '',
+  `deploy_date` datetime DEFAULT NULL                              COMMENT '',
+  `remarks` varchar(2048) DEFAULT NULL                             COMMENT '',
+  `creator` varchar(64) NOT NULL                                   COMMENT '',
+  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP         COMMENT '',
+  `modifier` varchar(64) DEFAULT NULL                              COMMENT '',
+  `gmt_modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '',
+  `requisition_no` varchar(32) DEFAULT NULL                        COMMENT '',
+  `display_flag` varchar(32) DEFAULT NULL                          COMMENT '',
+  `operate_machine_type` varchar(64) DEFAULT NULL                  COMMENT '',
+  `operate_machine_serial` varchar(64) DEFAULT NULL                COMMENT '',
+  `cancel_remarks` varchar(2048) DEFAULT NULL                      COMMENT '',
+  PRIMARY KEY (`id`),
+  KEY `idx_deliver_site_code` (`deliver_site_code`),
+  KEY `idx_to_site_code` (`to_site_code`),
+  KEY `idx_deliver_type` (`deliver_type`),
+  KEY `idx_status` (`status`)
+  ) ENGINE = InnoDB AUTO_INCREMENT = 617 DEFAULT CHARSET = utf8mb4     COMMENT ''
+
+img:
+  CREATE TABLE `img` (
+  `imgid` bigint(20) NOT NULL AUTO_INCREMENT BY GROUP,
+  `imgid_md5` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+  `uid` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+  `picurl` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+  `picisnull` tinyint(1) UNSIGNED NOT NULL DEFAULT '1',
+  `img_title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+  `img_info` text COLLATE utf8mb4_unicode_ci,
+  `img_param` text COLLATE utf8mb4_unicode_ci,
+  `font_id` text COLLATE utf8mb4_unicode_ci,
+  `store` int(11) UNSIGNED DEFAULT '0',
+  `ding_count` int(5) UNSIGNED DEFAULT '0',
+  `like_count` int(5) UNSIGNED DEFAULT '0',
+  `comment` int(4) UNSIGNED DEFAULT '0',
+  `ps` mediumtext COLLATE utf8mb4_unicode_ci,
+  `ps_content` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+  `ps_content_keywords` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+  `ps_origin_imgid` int(11) UNSIGNED DEFAULT '0',
+  `ps_origin_uid` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+  `square` int(11) DEFAULT '0',
+  `is_ding` tinyint(1) UNSIGNED DEFAULT '0',
+  `is_del` tinyint(1) UNSIGNED DEFAULT '0',
+  `is_private` tinyint(1) UNSIGNED DEFAULT '0',
+  `activity_id` int(11) UNSIGNED DEFAULT '0',
+  `ding_weight` int(3) UNSIGNED DEFAULT '0',
+  `admin_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY (`imgid`),
+  KEY `like_count` (`like_count`),
+  KEY `ding_weight` (`ding_weight`, `imgid`),
+  KEY `ps_origin_imgid` (`ps_origin_imgid`),
+  KEY `activity_id` (`activity_id`, `ding_weight`),
+  KEY `uid_is_null` (`uid`, `is_del`, `picisnull`),
+  KEY `imgid_cover` (`imgid`, `is_del`, `picisnull`, `is_private`),
+  KEY `uid_imgid_is_del_picisnull` USING BTREE (`uid`, `imgid`, `picisnull`, `is_del`),
+  KEY `idx_picurl` (`picurl`),
+  KEY `idx_imgid_md5` (`imgid_md5`),
+  KEY `idx_uid_admin_cover` (`uid`, `admin_time`, `picisnull`, `is_del`, `is_private`, `like_count`, `imgid`),
+  KEY `date` (`admin_time`, `imgid`)
+  ) ENGINE = InnoDB AUTO_INCREMENT = 1620733506 DEFAULT CHARSET = utf8mb4 DEFAULT COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC  partition by hash(`imgid`) subpartition by hash(`imgid`) subpartitions 13
+
+test_hash_tb1:
+  CREATE TABLE `test_hash_tb1` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  `int_col1` int DEFAULT NULL,
+  `int_col2` int DEFAULT NULL,
+  `int_col3` int DEFAULT NULL,
+  `int_col4` int DEFAULT NULL,
+  `int_col5` int DEFAULT NULL,
+  `int_col6` int DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_hash_tb2:
+  CREATE TABLE `test_hash_tb2` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  `int_col1` int DEFAULT NULL,
+  `int_col2` int DEFAULT NULL,
+  `int_col3` int DEFAULT NULL,
+  `int_col4` int DEFAULT NULL,
+  `int_col5` int DEFAULT NULL,
+  `int_col6` int DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  KEY `auto_shard_key_ID_0` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_ordered_subpartition:
+  CREATE TABLE `test_ordered_subpartition` (
+  `id` varchar(32) NOT NULL,
+  `user_id` varchar(32) NOT NULL ,
+  `pad` varchar(32) NOT NULL ,
+  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY USING BTREE (`id`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
+  PARTITION BY KEY(user_id)
+  PARTITIONS 16
+  SUBPARTITION BY RANGE COLUMNS(create_time)
+  (
+  SUBPARTITION sp202403a VALUES LESS THAN('2024-03-11'),
+  SUBPARTITION sp202403b VALUES LESS THAN('2024-03-21'),
+  SUBPARTITION sp202403c VALUES LESS THAN('2024-04-01'),
+  SUBPARTITION sp202404a VALUES LESS THAN('2024-04-11'),
+  SUBPARTITION sp202404b VALUES LESS THAN('2024-04-21'),
+  SUBPARTITION sp202404c VALUES LESS THAN('2024-05-01')
+  );
+
+test_ordered_subpartition_b:
+  CREATE TABLE `test_ordered_subpartition_b` (
+  `id` varchar(32) NOT NULL,
+  `user_id` varchar(32) NOT NULL ,
+  `pad` varchar(32) NOT NULL ,
+  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY USING BTREE (`id`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
+  PARTITION BY KEY(user_id)
+  PARTITIONS 16
+  SUBPARTITION BY RANGE COLUMNS(create_time)
+  (
+  SUBPARTITION sp202403a VALUES LESS THAN('2024-03-11'),
+  SUBPARTITION sp202403b VALUES LESS THAN('2024-03-21'),
+  SUBPARTITION sp202403c VALUES LESS THAN('2024-04-01'),
+  SUBPARTITION sp202404a VALUES LESS THAN('2024-04-11'),
+  SUBPARTITION sp202404b VALUES LESS THAN('2024-04-21'),
+  SUBPARTITION sp202404c VALUES LESS THAN('2024-05-01')
+  );
+
+test_ordered_subpartition_c:
+  CREATE TABLE `test_ordered_subpartition_c` (
+  `id` varchar(32) NOT NULL,
+  `user_id` varchar(32) NOT NULL ,
+  `pad` varchar(32) NOT NULL ,
+  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY USING BTREE (`id`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 
+  PARTITION BY RANGE COLUMNS(create_time)
+  SUBPARTITION BY KEY(user_id)
+  SUBPARTITIONS 16
+  (
+  PARTITION sp202403a VALUES LESS THAN('2024-03-11'),
+  PARTITION sp202403b VALUES LESS THAN('2024-03-21'),
+  PARTITION sp202403c VALUES LESS THAN('2024-04-01'),
+  PARTITION sp202404a VALUES LESS THAN('2024-04-11'),
+  PARTITION sp202404b VALUES LESS THAN('2024-04-21'),
+  PARTITION sp202404c VALUES LESS THAN('2024-05-01')
+  );
+
+test_ordered_partition:
+  CREATE TABLE `test_ordered_partition` (
+  `id` varchar(32) NOT NULL,
+  `user_id` varchar(32) NOT NULL ,
+  `pad` varchar(32) NOT NULL ,
+  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY USING BTREE (`id`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
+  PARTITION BY RANGE COLUMNS(create_time)
+  (
+  SUBPARTITION sp202403a VALUES LESS THAN('2024-03-11'),
+  SUBPARTITION sp202403b VALUES LESS THAN('2024-03-21'),
+  SUBPARTITION sp202403c VALUES LESS THAN('2024-04-01'),
+  SUBPARTITION sp202404a VALUES LESS THAN('2024-04-11'),
+  SUBPARTITION sp202404b VALUES LESS THAN('2024-04-21'),
+  SUBPARTITION sp202404c VALUES LESS THAN('2024-05-01')
+  );
+
+test_ordered_partition_b:
+  CREATE TABLE `test_ordered_partition_b` (
+  `id` varchar(32) NOT NULL,
+  `user_id` varchar(32) NOT NULL ,
+  `pad` varchar(32) NOT NULL ,
+  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY USING BTREE (`id`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
+  PARTITION BY RANGE COLUMNS(create_time)
+  (
+  SUBPARTITION sp202403a VALUES LESS THAN('2024-03-11'),
+  SUBPARTITION sp202403b VALUES LESS THAN('2024-03-21'),
+  SUBPARTITION sp202403c VALUES LESS THAN('2024-04-01'),
+  SUBPARTITION sp202404a VALUES LESS THAN('2024-04-11'),
+  SUBPARTITION sp202404b VALUES LESS THAN('2024-04-21'),
+  SUBPARTITION sp202404c VALUES LESS THAN('2024-05-01')
+  );
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ModifyTopNTest.delete.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ModifyTopNTest.delete.yml
new file mode 100644
index 000000000..450583d7b
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/ModifyTopNTest.delete.yml
@@ -0,0 +1,483 @@
+# one sharding table
+- sql: |
+    delete a from test_hash_ta a where a.id = 1;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p54]", sql="delete from `test_hash_ta` where (`id` = ?)")
+
+- sql: |
+    delete a from test_hash_ta a where a.id = last_insert_id();
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p5]", sql="delete from `test_hash_ta` where (`id` = ?)")
+
+- sql: |
+    delete a from test_single a where a.id = last_insert_id(1);
+
+  plan: |
+
+    logicalview(tables="optest_p00000_group.test_single", sql="delete `a` from `test_single` as `a` where (`a`.`id` = last_insert_id(?))", params="1")
+
+- sql: |
+    delete from a using test_hash_ta a where a.id = 1;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p54]", sql="delete from `test_hash_ta` where (`id` = ?)")
+
+- sql: |
+    delete a from test_hash_ta a, test_hash_ta b where a.id = b.id and a.id = 1;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p54],test_hash_ta[p54]", sql="delete `test_hash_ta` from `test_hash_ta` as `test_hash_ta` inner join `test_hash_ta` as `test_hash_ta0` on ((`test_hash_ta`.`id` = ?) and (`test_hash_ta0`.`id` = ?) and (`test_hash_ta`.`id` = `test_hash_ta0`.`id`))")
+
+- sql: |
+    delete a from test_broadcast a, test_broadcast b where a.id = b.id and a.id = 1;
+
+  plan: |
+
+    logicalview(tables="optest_0000.test_broadcast,test_broadcast", sql="delete `a` from `test_broadcast` as `a`, `test_broadcast` as `b` where ((`a`.`id` = `b`.`id`) and (`a`.`id` = ?))", params="1")
+
+- sql: |
+    delete test_hash_tb from test_hash_tb, test_hash_ta where test_hash_ta.id = test_hash_tb.id;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_tb[p1,p2,p3,...p64],test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete `test_hash_tb` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_ta` as `test_hash_ta` on (`test_hash_tb`.`id` = `test_hash_ta`.`id`)")
+
+- sql: |
+    delete a from test_hash_tb b, test_hash_ta a where a.id = b.id and a.id = 1;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_tb[p54],test_hash_ta[p54]", sql="delete `test_hash_ta` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_ta` as `test_hash_ta` on ((`test_hash_tb`.`id` = ?) and (`test_hash_ta`.`id` = ?) and (`test_hash_tb`.`id` = `test_hash_ta`.`id`))")
+
+- sql: |
+    delete from a,b using test_hash_tb b, test_hash_ta a where a.id = b.id and a.id = 1;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_tb[p54],test_hash_ta[p54]", sql="delete `test_hash_ta`, `test_hash_tb` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_ta` as `test_hash_ta` on ((`test_hash_tb`.`id` = ?) and (`test_hash_ta`.`id` = ?) and (`test_hash_tb`.`id` = `test_hash_ta`.`id`))")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,FORBID_EXECUTE_DML_ALL=false)*/
+    delete a from test_hash_tb a, test_hash_ta;
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_hash_tb")
+      nljoin(condition="true", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="test_hash_tb[p1,p2,p3,...p64]", shardcount=64, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` for update")
+        gather(concurrent=true)
+          logicalview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="select `id`, `name`, `create_time` from `test_hash_ta` as `test_hash_ta` for update")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/
+    delete a from test_broadcast a, test_hash_tb b where a.id = b.id and a.id = 1;
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_broadcast")
+      logicalview(tables="test_hash_tb[p54],test_broadcast", sql="select `test_broadcast`.`id` as `id0`, `test_broadcast`.`name` as `name0`, `test_broadcast`.`create_time` as `create_time0`, `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time` from `test_hash_tb` as `test_hash_tb` inner join `test_broadcast` as `test_broadcast` on ((`test_broadcast`.`id` = ?) and (`test_hash_tb`.`id` = ?) and (`test_hash_tb`.`id` = `test_broadcast`.`id`)) for update")
+
+- sql: |
+    delete b from test_broadcast a, test_hash_tb b where a.id = b.id and a.id = 1;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_tb[p54],test_broadcast", sql="delete `test_hash_tb` from `test_hash_tb` as `test_hash_tb` inner join `test_broadcast` as `test_broadcast` on ((`test_broadcast`.`id` = ?) and (`test_hash_tb`.`id` = ?) and (`test_hash_tb`.`id` = `test_broadcast`.`id`))")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/
+    delete a,b from test_broadcast a, test_hash_tb b where a.id = b.id and a.id = 1;
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_broadcast, optest.test_hash_tb")
+      logicalview(tables="test_hash_tb[p54],test_broadcast", sql="select `test_broadcast`.`id` as `id0`, `test_broadcast`.`name` as `name0`, `test_broadcast`.`create_time` as `create_time0`, `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time` from `test_hash_tb` as `test_hash_tb` inner join `test_broadcast` as `test_broadcast` on ((`test_broadcast`.`id` = ?) and (`test_hash_tb`.`id` = ?) and (`test_hash_tb`.`id` = `test_broadcast`.`id`)) for update")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/
+    delete a from test_single a, test_hash_tb b where a.id = b.id and a.id = 1;
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_single")
+      hashjoin(condition="id = id", type="inner")
+        logicalview(tables="test_single[p1]", sql="select `id`, `name`, `create_time` from `test_single` as `test_single` force index(`primary`) where (`id` = ?) for update")
+        logicalview(tables="test_hash_tb[p54]", sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where (`id` = ?) for update")
+
+- sql: |
+    delete b from test_single a join test_hash_tb b where a.id = b.id and a.id = 0;
+
+  plan: |
+
+    phytableoperation(tables="test_single[p1],test_hash_tb[p5]", sql="delete `b` from ? as `a` inner join ? as `b` where ((`a`.`id` = `b`.`id`) and (`a`.`id` = ?))", params="`test_single`,`test_hash_tb_00004`,0")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/
+    delete a,b from test_single a, test_hash_tb b where a.id = b.id and a.id = 1;
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_single, optest.test_hash_tb")
+      hashjoin(condition="id = id", type="inner")
+        logicalview(tables="test_single[p1]", sql="select `id`, `name`, `create_time` from `test_single` as `test_single` force index(`primary`) where (`id` = ?) for update")
+        logicalview(tables="test_hash_tb[p54]", sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where (`id` = ?) for update")
+
+- sql: |
+    delete a from test_broadcast a, test_broadcast_b b where a.id = b.id and a.id = 1;
+
+  plan: |
+
+    logicalview(tables="optest_0000.test_broadcast,test_broadcast_b", sql="delete `a` from `test_broadcast` as `a`, `test_broadcast_b` as `b` where ((`a`.`id` = `b`.`id`) and (`a`.`id` = ?))", params="1")
+
+- sql: |
+    delete a,b from test_broadcast a, test_broadcast_b b where a.id = b.id and a.id = 1;
+
+  plan: |
+
+    logicalview(tables="optest_0000.test_broadcast,test_broadcast_b", sql="delete `a`, `b` from `test_broadcast` as `a`, `test_broadcast_b` as `b` where ((`a`.`id` = `b`.`id`) and (`a`.`id` = ?))", params="1")
+
+- sql: |
+    delete a from test_hash_ta a join (select name, id from test_hash_tb b where b.name = "c" and b.id = 1) b where a.id = b.id;
+
+  plan: |
+
+    phytableoperation(tables="test_hash_ta[p54],test_hash_tb[p54]", sql="delete `a` from ? as `a` inner join (select `b`.`name` as `name`, `b`.`id` as `id` from ? as `b` where ((`b`.`name` = ?) and (`b`.`id` = ?))) as `b` where (`a`.`id` = `b`.`id`)", params="`test_hash_ta_00053`,`test_hash_tb_00053`,c,1")
+
+- sql: |
+    delete a from test_broadcast a join (select name, id from test_broadcast b where b.name = "c" and b.id = 1) b where a.id = b.id;
+
+  plan: |
+
+    logicalview(tables="optest_0000.test_broadcast,test_broadcast", sql="delete `a` from `test_broadcast` as `a` inner join (select `b`.`name` as `name`, `b`.`id` as `id` from `test_broadcast` as `b` where ((`b`.`name` = ?) and (`b`.`id` = ?))) as `b` where (`a`.`id` = `b`.`id`)", params="c,1")
+
+- sql: |
+    delete a from test_hash_tb a join (select name, id from test_broadcast b where b.name = "c" and b.id = 1) b where a.id = b.id;
+
+  plan: |
+
+    phytableoperation(tables="test_hash_tb[p54],test_broadcast[p2]", sql="delete `a` from ? as `a` inner join (select `b`.`name` as `name`, `b`.`id` as `id` from ? as `b` where ((`b`.`name` = ?) and (`b`.`id` = ?))) as `b` where (`a`.`id` = `b`.`id`)", params="`test_hash_tb_00053`,`test_broadcast`,c,1")
+
+- sql: |
+    delete a from test_broadcast a join (select name, id from test_hash_ta b where b.name = "c" and b.id = 1) b where a.id = b.id;
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_broadcast")
+      logicalview(tables="test_hash_ta[p54],test_broadcast", sql="select `test_broadcast`.`id` as `id0`, `test_broadcast`.`name` as `name0`, `test_broadcast`.`create_time`, `test_hash_ta`.`name`, `test_hash_ta`.`id` from `test_hash_ta` as `test_hash_ta` inner join `test_broadcast` as `test_broadcast` on (`test_hash_ta`.`id` = `test_broadcast`.`id`) where ((`test_hash_ta`.`id` = ?) and (`test_hash_ta`.`name` = ?)) for update")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete from test_hash_ta;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete test_hash_ta from test_hash_ta;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete test_hash_ta from optest.test_hash_ta;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete optest.test_hash_ta from test_hash_ta;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete optest.test_hash_ta from optest.test_hash_ta;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete test_hash_ta from optest1.test_hash_ta;
+
+  plan: |
+
+    err-code: [pxc-4518][err_validate] : object 'optest1' not found
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete optest1.test_hash_ta from test_hash_ta;
+
+  plan: |
+
+    err-code: [pxc-4518][err_validate] : table 'optest1.test_hash_ta' not found
+
+- sql: |
+    delete optest.test_hash_ta from optest1.test_hash_ta;
+
+  plan: |
+
+    err-code: [pxc-4518][err_validate] : object 'optest1' not found
+
+- sql: |
+    delete optest1.test_hash_ta from optest.test_hash_ta;
+
+  plan: |
+
+    err-code: [pxc-4518][err_validate] : table 'optest1.test_hash_ta' not found
+
+- sql: |
+    delete optest1.test_hash_ta from optest1.test_hash_ta;
+
+  plan: |
+
+    err-code: [pxc-4518][err_validate] : object 'optest1' not found
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete from test_hash_ta a;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete from test_hash_ta AS a;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete a from test_hash_ta AS a;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    delete from test_hash_ta AS `a-a` where `a-a`.id = 1;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p54]", sql="delete from `test_hash_ta` where (`id` = ?)")
+
+- sql: |
+    delete `a-a` from test_hash_ta AS `a-a` where `a-a`.id = 1;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p54]", sql="delete from `test_hash_ta` where (`id` = ?)")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete from optest.test_hash_ta;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete from optest.test_hash_ta a;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete from optest.test_hash_ta AS a;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete a from optest.test_hash_ta AS a;
+
+  plan: |
+
+    logicalmodifyview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="delete from `test_hash_ta`")
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete optest.test_hash_tb, test_hash_ta from optest.test_hash_ta join test_hash_tb;
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_hash_tb, optest.test_hash_ta")
+      nljoin(condition="true", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="select `id`, `name`, `create_time` from `test_hash_ta` as `test_hash_ta` for update")
+        gather(concurrent=true)
+          logicalview(tables="test_hash_tb[p1,p2,p3,...p64]", shardcount=64, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` for update")
+
+- sql: |
+    delete optest1.test_hash_tb, test_hash_ta from optest.test_hash_ta join test_hash_tb;
+
+  plan: |
+
+    err-code: [pxc-4518][err_validate] : unknown table 'optest1.test_hash_tb' in multi delete
+
+- sql: |
+    /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete optest.test_hash_tb, a from optest.test_hash_ta as a join test_hash_tb;
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_hash_tb, optest.test_hash_ta")
+      nljoin(condition="true", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="test_hash_ta[p1,p2,p3,...p64]", shardcount=64, sql="select `id`, `name`, `create_time` from `test_hash_ta` as `test_hash_ta` for update")
+        gather(concurrent=true)
+          logicalview(tables="test_hash_tb[p1,p2,p3,...p64]", shardcount=64, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` for update")
+
+- sql: |
+    delete optest.test_hash_tb, optest.test_hash_ta from optest.test_hash_ta as a join test_hash_tb;
+
+  plan: |
+
+    err-code: [pxc-4518][err_validate] : unknown table 'optest.test_hash_ta' in multi delete
+
+- sql: |
+    delete b from self_join_t1 a join self_join_t1 b on a.c1 = b.c1 and a.pk > b.pk where a.pk > 0;
+
+  plan: |
+
+    logicalmodifyview(tables="self_join_t1[p1,p2,p3,...p64],self_join_t1[p1,p2,p3,...p64]", shardcount=64, sql="delete `self_join_t10` from `self_join_t1` as `self_join_t1` inner join `self_join_t1` as `self_join_t10` on ((`self_join_t1`.`c1` = `self_join_t10`.`c1`) and (`self_join_t1`.`pk` > `self_join_t10`.`pk`) and (`self_join_t1`.`pk` > ?))")
+
+- sql: |
+    delete from test_broadcast where id > 0 and exists (select id from test_broadcast_b where test_broadcast.name = name);
+
+  plan: |
+
+    logicalview(tables="optest_0000.test_broadcast,test_broadcast_b", sql="delete `test_broadcast` from `test_broadcast` as `test_broadcast` where ((`id` > ?) and (exists (select `test_broadcast_b`.`id` as `id` from `test_broadcast_b` as `test_broadcast_b` where (`test_broadcast`.`name` = `test_broadcast_b`.`name`))))", params="0")
+
+- sql: |
+    delete from optest.test_broadcast where id > 0 and exists (select id from optest.test_broadcast_b where test_broadcast.name = name);
+
+  plan: |
+
+    logicalview(tables="optest_0000.test_broadcast,test_broadcast_b", sql="delete `test_broadcast` from `test_broadcast` as `test_broadcast` where ((`id` > ?) and (exists (select `test_broadcast_b`.`id` as `id` from `test_broadcast_b` as `test_broadcast_b` where (`test_broadcast`.`name` = `test_broadcast_b`.`name`))))", params="0")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete test_ordered_subpartition where user_id = 1 and create_time<="2024-04-23" order by create_time desc limit 1; 
+
+  plan: |
+
+    logicalmodifyview(tables="test_ordered_subpartition[p11sp202403a,p11sp202403b,p11sp202403c,p11sp202404a,p11sp202404b,p11sp202404c]", shardcount=6, sql="delete from `test_ordered_subpartition` where ((`user_id` = ?) and (`create_time` <= ?)) order by `create_time` desc limit ?")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete test_ordered_subpartition where user_id in (1, 1) and create_time<="2024-04-23" order by create_time desc limit 1; 
+
+  plan: |
+
+    logicalmodifyview(tables="test_ordered_subpartition[p11sp202403a,p11sp202403b,p11sp202403c,p11sp202404a,p11sp202404b,p11sp202404c]", shardcount=6, sql="delete from `test_ordered_subpartition` where ((`user_id` in(?)) and (`create_time` <= ?)) order by `create_time` desc limit ?")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete test_ordered_subpartition_c where user_id in (1, 1) and create_time<="2024-04-23" order by create_time desc limit 1; 
+
+  plan: |
+
+    logicalmodifyview(tables="test_ordered_subpartition_c[sp202403asp11,sp202403bsp11,sp202403csp11,sp202404asp11,sp202404bsp11,sp202404csp11]", shardcount=6, sql="delete from `test_ordered_subpartition_c` where ((`user_id` in(?)) and (`create_time` <= ?)) order by `create_time` desc limit ?")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete test_ordered_partition where user_id = 1 and create_time<="2024-04-23" order by create_time desc limit 1; 
+
+  plan: |
+
+    logicalmodifyview(tables="test_ordered_partition[sp202403a,sp202403b,sp202403c,sp202404a,sp202404b,sp202404c]", shardcount=6, sql="delete from `test_ordered_partition` where ((`user_id` = ?) and (`create_time` <= ?)) order by `create_time` desc limit ?")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete a from test_ordered_subpartition a join test_ordered_subpartition_b b on a.user_id = b.user_id and a.create_time = b.create_time where a.user_id = 1 and a.create_time<="2024-04-23" order by a.create_time desc limit 1; 
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_ordered_subpartition")
+      mergesort(sort="create_time desc", fetch=?2)
+        logicalview(tables="test_ordered_subpartition[p11sp202403a,p11sp202403b,p11sp202403c,p11sp202404a,p11sp202404b,p11sp202404c],test_ordered_subpartition_b[p11sp202403a,p11sp202403b,p11sp202403c,p11sp202404a,p11sp202404b,p11sp202404c]", shardcount=6, sql="select `test_ordered_subpartition`.`id`, `test_ordered_subpartition`.`user_id`, `test_ordered_subpartition`.`pad`, `test_ordered_subpartition`.`create_time`, `test_ordered_subpartition_b`.`id` as `id0`, `test_ordered_subpartition_b`.`user_id` as `user_id0`, `test_ordered_subpartition_b`.`pad` as `pad0`, `test_ordered_subpartition_b`.`create_time` as `create_time0` from `test_ordered_subpartition` as `test_ordered_subpartition` inner join `test_ordered_subpartition_b` as `test_ordered_subpartition_b` on ((`test_ordered_subpartition_b`.`user_id` = ?) and (`test_ordered_subpartition`.`user_id` = `test_ordered_subpartition_b`.`user_id`) and (`test_ordered_subpartition`.`user_id` = ?) and (`test_ordered_subpartition`.`create_time` = `test_ordered_subpartition_b`.`create_time`) and (`test_ordered_subpartition`.`create_time` <= ?)) order by `test_ordered_subpartition`.`create_time` desc limit ? for update")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete a from test_ordered_partition a join test_ordered_partition_b b on a.create_time = b.create_time where a.user_id = 1 and a.create_time<="2024-04-23" order by a.create_time desc limit 1; 
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_ordered_partition")
+      mergesort(sort="create_time desc", fetch=?2)
+        logicalview(tables="test_ordered_partition[sp202403a,sp202403b,sp202403c,sp202404a,sp202404b,sp202404c],test_ordered_partition_b[sp202403a,sp202403b,sp202403c,sp202404a,sp202404b,sp202404c]", shardcount=6, sql="select `test_ordered_partition`.`id`, `test_ordered_partition`.`user_id`, `test_ordered_partition`.`pad`, `test_ordered_partition`.`create_time`, `test_ordered_partition_b`.`id` as `id0`, `test_ordered_partition_b`.`user_id` as `user_id0`, `test_ordered_partition_b`.`pad` as `pad0`, `test_ordered_partition_b`.`create_time` as `create_time0` from `test_ordered_partition` as `test_ordered_partition` inner join `test_ordered_partition_b` as `test_ordered_partition_b` on ((`test_ordered_partition`.`user_id` = ?) and (`test_ordered_partition`.`create_time` = `test_ordered_partition_b`.`create_time`) and (`test_ordered_partition`.`create_time` <= ?)) order by `test_ordered_partition`.`create_time` desc limit ? for update")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete test_ordered_partition where user_id = 1 and create_time<="2024-04-23" order by create_time desc limit 0,1; 
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_ordered_partition")
+      mergesort(sort="create_time desc", offset=?2, fetch=?3)
+        logicalview(tables="test_ordered_partition[sp202403a,sp202403b,sp202403c,sp202404a,sp202404b,sp202404c]", shardcount=6, sql="select `id`, `user_id`, `pad`, `create_time` from `test_ordered_partition` as `test_ordered_partition` where ((`user_id` = ?) and (`create_time` <= ?)) order by `create_time` desc limit (? + ?) for update")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete a from test_ordered_subpartition a join test_ordered_subpartition_b b on a.id = b.id and a.create_time = b.create_time where a.user_id = 1 and a.create_time<="2024-04-23" order by a.create_time desc limit 1; 
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_ordered_subpartition")
+      topn(sort="create_time desc", fetch=?2)
+        bkajoin(condition="id = id and create_time = create_time", type="inner")
+          gather(concurrent=true)
+            logicalview(tables="test_ordered_subpartition[p11sp202403a,p11sp202403b,p11sp202403c,p11sp202404a,p11sp202404b,p11sp202404c]", shardcount=6, sql="select `id`, `user_id`, `pad`, `create_time` from `test_ordered_subpartition` as `test_ordered_subpartition` where ((`user_id` = ?) and (`create_time` <= ?)) for update")
+          gather(concurrent=true)
+            logicalview(tables="test_ordered_subpartition_b[p1sp202403a,p1sp202403b,p1sp202403c,...p16sp202404c]", shardcount=96, sql="select `id`, `user_id`, `pad`, `create_time` from `test_ordered_subpartition_b` as `test_ordered_subpartition_b` force index(`primary`) where ((`create_time` <= ?) and (((`id`, `create_time`)) in (...))) for update")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete test_hash_tb where name = "b" and create_time<="2024-04-23" order by create_time desc limit 1; 
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_hash_tb")
+      mergesort(sort="create_time desc", fetch=?2)
+        logicalview(tables="test_hash_tb[p1,p2,p3,...p64]", shardcount=64, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` where ((`name` = ?) and (`create_time` <= ?)) order by `create_time` desc limit ? for update")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete test_broadcast where name = "b" and create_time<="2024-04-23" order by create_time desc limit 1; 
+
+  plan: |
+
+    logicalview(tables="optest_0000.test_broadcast", sql="delete from `test_broadcast` where ((`name` = ?) and (`create_time` <= ?)) order by `create_time` desc limit ?", params="b,2024-04-23,1")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete test_single where name = "b" and create_time<="2024-04-23" order by create_time desc limit 1; 
+
+  plan: |
+
+    logicalview(tables="optest_p00000_group.test_single", sql="delete from `test_single` where ((`name` = ?) and (`create_time` <= ?)) order by `create_time` desc limit ?", params="b,2024-04-23,1")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete test_ordered_subpartition where user_id in (1, 2) and create_time<="2024-04-23" order by create_time desc limit 1; 
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_ordered_subpartition", ismodifytopn=true)
+      mergesort(sort="create_time desc", fetch=?2)
+        logicalview(tables="test_ordered_subpartition[p9sp202403a,p9sp202403b,p9sp202403c,...p11sp202404c]", shardcount=12, sql="select `id`, `user_id`, `pad`, `create_time` from `test_ordered_subpartition` as `test_ordered_subpartition` where ((`user_id` in(?)) and (`create_time` <= ?)) order by `create_time` desc limit ? for update", pruninginfo="all size:2*12(part), pruning size:12")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete test_ordered_subpartition where user_id in (1, 2) and create_time<="2024-04-23" order by create_time desc limit 1; 
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_ordered_subpartition", ismodifytopn=true)
+      mergesort(sort="create_time desc", fetch=?2)
+        logicalview(tables="test_ordered_subpartition[p9sp202403a,p9sp202403b,p9sp202403c,...p11sp202404c]", shardcount=12, sql="select `id`, `user_id`, `pad`, `create_time` from `test_ordered_subpartition` as `test_ordered_subpartition` where ((`user_id` in(?)) and (`create_time` <= ?)) order by `create_time` desc limit ? for update", pruninginfo="all size:2*12(part), pruning size:12")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/ delete test_ordered_subpartition_c where user_id in (1, 2) and create_time<="2024-04-23" order by create_time desc limit 1; 
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_ordered_subpartition_c", ismodifytopn=true)
+      mergesort(sort="create_time desc", fetch=?2)
+        logicalview(tables="test_ordered_subpartition_c[sp202403asp9,sp202403asp11,sp202403bsp9,...sp202404csp11]", shardcount=12, sql="select `id`, `user_id`, `pad`, `create_time` from `test_ordered_subpartition_c` as `test_ordered_subpartition_c` where ((`user_id` in(?)) and (`create_time` <= ?)) order by `create_time` desc limit ? for update", pruninginfo="all size:2*12(part), pruning size:12")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/OptimizeModifyWithReturningTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/OptimizeModifyWithReturningTest.ddl.yml
new file mode 100644
index 000000000..c4eb1546e
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/OptimizeModifyWithReturningTest.ddl.yml
@@ -0,0 +1,395 @@
+test_hash_tb:
+  CREATE TABLE `test_hash_tb` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_hash_ta:
+  CREATE TABLE `test_hash_ta` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_hash_tc:
+  CREATE TABLE `test_hash_tc` (
+  `id` int(11) NOT NULL,
+  `key` int(11) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_single:
+  CREATE TABLE `test_single` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 single;
+
+test_broadcast:
+  CREATE TABLE `test_broadcast` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST;
+
+test_broadcast_b:
+  CREATE TABLE `test_broadcast_b` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST;
+
+test_group_sequence:
+  CREATE TABLE `test_group_sequence` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_time_sequence:
+  CREATE TABLE `test_time_sequence` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT BY TIME,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` timestamp,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_compound_key:
+  CREATE TABLE `test_compound_key` (
+  `id` bigint(20) NOT NULL,
+  `name` bigint(20) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`) subpartition by hash(`NAME`) subpartitions 2;
+
+test_tb_without_pk:
+  CREATE TABLE `test_tb_without_pk` (
+  `id`                BIGINT(11)   NOT NULL DEFAULT 1,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_without_pk_has_uk:
+  CREATE TABLE `test_tb_without_pk_has_uk` (
+  `id`                BIGINT(11)   NOT NULL DEFAULT 1,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  UNIQUE KEY (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_auto_increment:
+  CREATE TABLE `test_tb_pk_auto_increment` (
+  `pk`                BIGINT(11)   NOT NULL AUTO_INCREMENT,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_no_auto_increment_no_default:
+  CREATE TABLE `test_tb_pk_no_auto_increment_no_default` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_no_auto_increment_default_1:
+  CREATE TABLE `test_tb_pk_no_auto_increment_default_1` (
+  `pk`                BIGINT(11)   NOT NULL DEFAULT 1,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_auto_increment_with_ugsi:
+  CREATE TABLE `test_tb_pk_auto_increment_with_ugsi` (
+  `pk`                BIGINT(11)   NOT NULL AUTO_INCREMENT,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  UNIQUE INDEX uk_c4(c4, c3),
+  GLOBAL UNIQUE INDEX g_u_c2_a(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_no_auto_increment_no_default_with_ugsi:
+  CREATE TABLE `test_tb_pk_no_auto_increment_no_default_with_ugsi` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  UNIQUE INDEX uk_c4(c4, c3),
+  GLOBAL UNIQUE INDEX g_u_c2_b(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+test_tb_pk_no_auto_increment_default_1_with_ugsi:
+  CREATE TABLE `test_tb_pk_no_auto_increment_default_1_with_ugsi` (
+  `pk`                BIGINT(11)   NOT NULL DEFAULT 1,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  UNIQUE INDEX uk_c4(c4, c3),
+  GLOBAL UNIQUE INDEX g_u_c2_c(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+t1:
+  CREATE TABLE `t1` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  GLOBAL INDEX t1_i_a(c3) COVERING(c5, c6) partition BY HASH(c3) subpartition by HASH(c3) subpartitions 7,
+  GLOBAL UNIQUE INDEX t1_i_b(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+t2:
+  CREATE TABLE `t2` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  GLOBAL INDEX t2_i_a(c3) COVERING(c5, c6) partition BY HASH(c3) subpartition by HASH(c3) subpartitions 7,
+  GLOBAL UNIQUE INDEX t2_i_b(c1) COVERING(c5) partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+
+t3:
+  CREATE TABLE `t3` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  GLOBAL INDEX t3_i_a(c3) COVERING(c5, c6) partition BY HASH(c3) subpartition by HASH(c3) subpartitions 7,
+  GLOBAL UNIQUE INDEX t3_i_b(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+t4:
+  CREATE TABLE `t4` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `c1`                BIGINT       DEFAULT NULL,
+  `c2`                BIGINT       DEFAULT NULL,
+  `c3`                BIGINT       DEFAULT NULL,
+  `c4`                BIGINT       DEFAULT NULL,
+  `c5`                VARCHAR(255) DEFAULT NULL,
+  `c6`                DATETIME     DEFAULT NULL,
+  `c7`                TEXT         DEFAULT NULL,
+  `c8`                TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`),
+  UNIQUE INDEX uk_c4(c4),
+  GLOBAL INDEX t4_i_a(c3) COVERING(c5, c6) partition BY HASH(c3) subpartition by HASH(c3) subpartitions 7,
+  GLOBAL UNIQUE INDEX t4_i_b(c2) COVERING(c5) partition BY HASH(c2) subpartition by HASH(c2) subpartitions 2
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition BY HASH(c1) subpartition by HASH(c1) subpartitions 7
+
+self_join_t1:
+  CREATE TABLE `self_join_t1` (
+  `pk` int(11) NOT NULL,
+  `c1` int(11) DEFAULT NULL,
+  PRIMARY KEY (`pk`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 partition BY HASH(c1)
+
+test_hash_tb1:
+  CREATE TABLE `test_hash_tb1` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  `int_col1` int DEFAULT NULL,
+  `int_col2` int DEFAULT NULL,
+  `int_col3` int DEFAULT NULL,
+  `int_col4` int DEFAULT NULL,
+  `int_col5` int DEFAULT NULL,
+  `int_col6` int DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_hash_tb2:
+  CREATE TABLE `test_hash_tb2` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  `int_col1` int DEFAULT NULL,
+  `int_col2` int DEFAULT NULL,
+  `int_col3` int DEFAULT NULL,
+  `int_col4` int DEFAULT NULL,
+  `int_col5` int DEFAULT NULL,
+  `int_col6` int DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  KEY `auto_shard_key_ID_0` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`);
+
+test_ordered_subpartition:
+  CREATE TABLE `test_ordered_subpartition` (
+  `id` varchar(32) NOT NULL,
+  `user_id` varchar(32) NOT NULL ,
+  `pad` varchar(32) NOT NULL ,
+  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY USING BTREE (`id`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
+  PARTITION BY KEY(user_id)
+  PARTITIONS 16
+  SUBPARTITION BY RANGE COLUMNS(create_time)
+  (
+  SUBPARTITION sp202403a VALUES LESS THAN('2024-03-11'),
+  SUBPARTITION sp202403b VALUES LESS THAN('2024-03-21'),
+  SUBPARTITION sp202403c VALUES LESS THAN('2024-04-01'),
+  SUBPARTITION sp202404a VALUES LESS THAN('2024-04-11'),
+  SUBPARTITION sp202404b VALUES LESS THAN('2024-04-21'),
+  SUBPARTITION sp202404c VALUES LESS THAN('2024-05-01')
+  );
+
+test_ordered_subpartition_b:
+  CREATE TABLE `test_ordered_subpartition_b` (
+  `id` varchar(32) NOT NULL,
+  `user_id` varchar(32) NOT NULL ,
+  `pad` varchar(32) NOT NULL ,
+  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY USING BTREE (`id`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
+  PARTITION BY KEY(user_id)
+  PARTITIONS 16
+  SUBPARTITION BY RANGE COLUMNS(create_time)
+  (
+  SUBPARTITION sp202403a VALUES LESS THAN('2024-03-11'),
+  SUBPARTITION sp202403b VALUES LESS THAN('2024-03-21'),
+  SUBPARTITION sp202403c VALUES LESS THAN('2024-04-01'),
+  SUBPARTITION sp202404a VALUES LESS THAN('2024-04-11'),
+  SUBPARTITION sp202404b VALUES LESS THAN('2024-04-21'),
+  SUBPARTITION sp202404c VALUES LESS THAN('2024-05-01')
+  );
+
+test_ordered_subpartition_c:
+  CREATE TABLE `test_ordered_subpartition_c` (
+  `id` varchar(32) NOT NULL,
+  `user_id` varchar(32) NOT NULL ,
+  `pad` varchar(32) NOT NULL ,
+  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY USING BTREE (`id`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 
+  PARTITION BY RANGE COLUMNS(create_time)
+  SUBPARTITION BY KEY(user_id)
+  SUBPARTITIONS 16
+  (
+  PARTITION sp202403a VALUES LESS THAN('2024-03-11'),
+  PARTITION sp202403b VALUES LESS THAN('2024-03-21'),
+  PARTITION sp202403c VALUES LESS THAN('2024-04-01'),
+  PARTITION sp202404a VALUES LESS THAN('2024-04-11'),
+  PARTITION sp202404b VALUES LESS THAN('2024-04-21'),
+  PARTITION sp202404c VALUES LESS THAN('2024-05-01')
+  );
+
+test_ordered_partition:
+  CREATE TABLE `test_ordered_partition` (
+  `id` varchar(32) NOT NULL,
+  `user_id` varchar(32) NOT NULL ,
+  `pad` varchar(32) NOT NULL ,
+  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY USING BTREE (`id`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
+  PARTITION BY RANGE COLUMNS(create_time)
+  (
+  SUBPARTITION sp202403a VALUES LESS THAN('2024-03-11'),
+  SUBPARTITION sp202403b VALUES LESS THAN('2024-03-21'),
+  SUBPARTITION sp202403c VALUES LESS THAN('2024-04-01'),
+  SUBPARTITION sp202404a VALUES LESS THAN('2024-04-11'),
+  SUBPARTITION sp202404b VALUES LESS THAN('2024-04-21'),
+  SUBPARTITION sp202404c VALUES LESS THAN('2024-05-01')
+  );
+
+test_ordered_partition_b:
+  CREATE TABLE `test_ordered_partition_b` (
+  `id` varchar(32) NOT NULL,
+  `user_id` varchar(32) NOT NULL ,
+  `pad` varchar(32) NOT NULL ,
+  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY USING BTREE (`id`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
+  PARTITION BY RANGE COLUMNS(create_time)
+  (
+  SUBPARTITION sp202403a VALUES LESS THAN('2024-03-11'),
+  SUBPARTITION sp202403b VALUES LESS THAN('2024-03-21'),
+  SUBPARTITION sp202403c VALUES LESS THAN('2024-04-01'),
+  SUBPARTITION sp202404a VALUES LESS THAN('2024-04-11'),
+  SUBPARTITION sp202404b VALUES LESS THAN('2024-04-21'),
+  SUBPARTITION sp202404c VALUES LESS THAN('2024-05-01')
+  );
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/OptimizeModifyWithReturningTest.delete.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/OptimizeModifyWithReturningTest.delete.yml
new file mode 100644
index 000000000..4c8641e41
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/OptimizeModifyWithReturningTest.delete.yml
@@ -0,0 +1,75 @@
+# one sharding table
+- sql: |
+    delete a from test_tb_pk_auto_increment_with_ugsi a where a.c1 = 1;
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_tb_pk_auto_increment_with_ugsi", optimizebyreturning=true)
+      logicalview(tables="test_tb_pk_auto_increment_with_ugsi[p4sp1]", sql="select `pk`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` from `test_tb_pk_auto_increment_with_ugsi` as `test_tb_pk_auto_increment_with_ugsi` where (`c1` = ?) for update")
+
+- sql: |
+    delete a from test_tb_pk_auto_increment_with_ugsi a where a.c1 = last_insert_id();
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.test_tb_pk_auto_increment_with_ugsi", optimizebyreturning=true)
+      logicalview(tables="test_tb_pk_auto_increment_with_ugsi[p33sp4]", sql="select `pk`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` from `test_tb_pk_auto_increment_with_ugsi` as `test_tb_pk_auto_increment_with_ugsi` where (`c1` = ?) for update")
+
+# TODO optimize this with returning
+- sql: |
+    delete a from t1 a where a.c3 = last_insert_id(1);
+
+  plan: |
+    logicalmodify(type="delete", tables="optest.t1")
+      filter(condition="c3 = last_insert_id(?0)")
+        project(pk="pk", c1="c1", c2="c2", c3="c3", c4="c4", c5="c5", c6="c6", c7="c7", c8="c8")
+          bkajoin(condition="pk = pk and c1 <=> c1", type="inner")
+            gather(concurrent=true)
+              indexscan(tables="t1_i_b[p1sp1,p1sp2,p2sp1,...p64sp2]", shardcount=128, sql="select `pk`, `c1`, `c2`, `c5` from `t1_i_b` as `t1_i_b` for update")
+            gather(concurrent=true)
+              logicalview(tables="t1[p1sp1,p1sp2,p1sp3,...p64sp7]", shardcount=448, sql="select `pk`, `c1`, `c3`, `c4`, `c6`, `c7`, `c8` from `t1` as `t1` force index(`primary`) where (`pk` in (...)) for update")
+
+- sql: |
+    delete a from t1 a where a.c3 = 1;
+
+  plan: |
+    logicalmodify(type="delete", tables="optest.t1", optimizebyreturning=true)
+      project(pk="pk", c1="c1", c2="c2", c3="c3", c4="c4", c5="c5", c6="c6", c7="c7", c8="c8")
+        bkajoin(condition="pk = pk and c1 <=> c1", type="inner")
+          indexscan(tables="t1_i_a[p4sp1]", sql="select `pk`, `c1`, `c3`, `c5`, `c6` from `t1_i_a` as `t1_i_a` force index(`auto_shard_key_c3`) where (`c3` = ?) for update")
+          gather(concurrent=true)
+            logicalview(tables="t1[p1sp1,p1sp2,p1sp3,...p64sp7]", shardcount=448, sql="select `pk`, `c1`, `c2`, `c4`, `c7`, `c8` from `t1` as `t1` force index(`primary`) where ((`c3` = ?) and (`pk` in (...))) for update")
+
+- sql: |
+    delete a from t1 a, t2 b where a.c3 = b.c3 and a.c3 = 1;
+
+  plan: |
+    logicalmodify(type="delete", tables="optest.t1")
+      bkajoin(condition="c3 = c3", type="inner")
+        project(pk="pk", c1="c1", c2="c2", c3="c3", c4="c4", c5="c5", c6="c6", c7="c7", c8="c8")
+          bkajoin(condition="pk = pk and c1 <=> c1", type="inner")
+            indexscan(tables="t1_i_a[p4sp1]", sql="select `pk`, `c1`, `c3`, `c5`, `c6` from `t1_i_a` as `t1_i_a` force index(`auto_shard_key_c3`) where (`c3` = ?) for update")
+            gather(concurrent=true)
+              logicalview(tables="t1[p1sp1,p1sp2,p1sp3,...p64sp7]", shardcount=448, sql="select `pk`, `c1`, `c2`, `c4`, `c7`, `c8` from `t1` as `t1` force index(`primary`) where ((`c3` = ?) and (`pk` in (...))) for update")
+        gather(concurrent=true)
+          logicalview(tables="t2[p1sp1,p1sp2,p2sp1,...p64sp2]", shardcount=128, sql="select `pk`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` from `t2` as `t2` where ((`c3` = ?) and (`c3` in (...))) for update")
+
+# TODO 多表下推给 DN 会报错
+- sql: |
+    delete b from t1 a join t1 b on a.c1 = b.c1 and a.pk > b.pk where a.pk > 0;
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.t1", optimizebyreturning=true)
+      gather(concurrent=true)
+        logicalview(tables="t1[p1sp1,p1sp2,p1sp3,...p64sp7],t1[p1sp1,p1sp2,p1sp3,...p64sp7]", shardcount=448, sql="select `t1`.`pk`, `t1`.`c1`, `t1`.`c2`, `t1`.`c3`, `t1`.`c4`, `t1`.`c5`, `t1`.`c6`, `t1`.`c7`, `t1`.`c8`, `t10`.`pk` as `pk0`, `t10`.`c1` as `c10`, `t10`.`c2` as `c20`, `t10`.`c3` as `c30`, `t10`.`c4` as `c40`, `t10`.`c5` as `c50`, `t10`.`c6` as `c60`, `t10`.`c7` as `c70`, `t10`.`c8` as `c80` from `t1` as `t1` inner join `t1` as `t10` on ((`t1`.`c1` = `t10`.`c1`) and (`t1`.`pk` > `t10`.`pk`) and (`t1`.`pk` > ?)) for update")
+
+# TODO 多表下推给 DN 会报错
+- sql: |
+    delete from t1 where c1 > 0 and exists (select id from test_broadcast_b where t1.c5 = name);
+
+  plan: |
+
+    logicalmodify(type="delete", tables="optest.t1", optimizebyreturning=true)
+      gather(concurrent=true)
+        logicalview(tables="t1[p1sp1,p1sp2,p1sp3,...p64sp7],test_broadcast_b", shardcount=448, sql="select `pk`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` from `t1` as `t1` where ((`c1` > ?) and (exists (select `id` from `test_broadcast_b` as `test_broadcast_b` where (`t1`.`c5` = `name`)))) for update")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.ddl.yml
index b0cedaa2a..51a66b226 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.ddl.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.ddl.yml
@@ -49,4 +49,12 @@ test_compound_key:
   `name` bigint(20) NOT NULL,
   PRIMARY KEY (`id`),
   KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`ID`) tbpartition by hash(`NAME`) tbpartitions 2;
+
+test_force_gsi:
+  CREATE TABLE `test_force_gsi` (
+  `id` bigint(20) NOT NULL,
+  `name` bigint(20) NOT NULL,
+  PRIMARY KEY (`id`),
+  GLOBAL INDEX `g_idx_name` (`name`) dbpartition by hash(`NAME`) tbpartition by hash(`NAME`) tbpartitions 2
   ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`ID`) tbpartition by hash(`NAME`) tbpartitions 2;
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.delete.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.delete.yml
index 8f098e08b..5a034e305 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.delete.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.delete.yml
@@ -1,3 +1,57 @@
+- sql: |
+    delete from test_force_gsi force index(g_idx_name.auto_shard_key_name) where name = "xxx";
+
+  plan: |
+    logicalmodify(type="delete", tables="optest.test_force_gsi", optimizebyreturning=true)
+      indexscan(tables="optest_0000.g_idx_name_0", sql="select `id`, `name` from `g_idx_name` as `g_idx_name` force index(auto_shard_key_name) where (`name` = ?) for update")
+
+- sql: |
+    delete from test_force_gsi force index(g_idx_name) where name = "xxx";
+
+  plan: |
+    logicalmodify(type="delete", tables="optest.test_force_gsi", optimizebyreturning=true)
+      indexscan(tables="optest_0000.g_idx_name_0", sql="select `id`, `name` from `g_idx_name` as `g_idx_name` force index(`auto_shard_key_name`) where (`name` = ?) for update")
+
+- sql: |
+    delete from test_force_gsi force index(primary) where name = "xxx";
+
+  plan: |
+    logicalmodify(type="delete", tables="optest.test_force_gsi", optimizebyreturning=true)
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_force_gsi_0", shardcount=4, sql="select `id`, `name` from `test_force_gsi` as `test_force_gsi` force index(primary) where (`name` = ?) for update")
+
+- sql: |
+    delete from test_force_gsi force index(g_idx_name.xxx) where name = "xxx";
+
+  plan: |
+    logicalmodify(type="delete", tables="optest.test_force_gsi", optimizebyreturning=true)
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_force_gsi_0", shardcount=4, sql="select `id`, `name` from `test_force_gsi` as `test_force_gsi` where (`name` = ?) for update")
+
+- sql: |
+    delete from test_hash_tb force index(xxx) where id = 1;
+
+  plan: |
+    logicalmodifyview(tables="optest_0001.test_hash_tb", sql="delete from `test_hash_tb` where (`id` = ?)")
+
+- sql: |
+    delete from test_hash_tb force index(xxx) where name = "xxx";
+
+  plan: |
+    logicalmodifyview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="delete from `test_hash_tb` where (`name` = ?)")
+
+- sql: |
+    delete from test_hash_tb force index(primary) where id = 1;
+
+  plan: |
+    LogicalModifyView(tables="optest_0001.test_hash_tb", sql="DELETE `test_hash_tb` FROM `test_hash_tb` as `test_hash_tb` force index(primary) WHERE (`id` = ?)")
+
+- sql: |
+    delete from test_single force index(primary) where id = 1;
+
+  plan: |
+    logicalview(tables="optest_0000.test_single", sql="delete `test_single` from `test_single` as `test_single` force index(primary) where (`id` = ?)", params="1")
+
 - sql: |
     delete from test_hash_tb where id = 1;
 
@@ -53,11 +107,9 @@
     delete from test_hash_tb order by id limit 10;
 
   plan: |
-
-    LogicalModify(TYPE="DELETE", TABLES="optest.test_hash_tb")
-      MergeSort(sort="id ASC", fetch=?0)
-        LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` ORDER BY `id` LIMIT ? FOR UPDATE")
-
+    logicalmodify(type="delete", tables="optest.test_hash_tb")
+      mergesort(sort="id asc", fetch=?0)
+        logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) order by `id` limit ? for update")
 - sql: |
     delete from test_hash_tb where id = 1 limit 10;
 
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.update.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.update.yml
index 40c007afb..971a56a4d 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.update.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/dml/SimpleDmlTest.update.yml
@@ -2,9 +2,7 @@
     update test_hash_tb set name = 'a' where id = 1;
 
   plan: |
-
-    LogicalModifyView(tables="optest_0001.test_hash_tb", sql="UPDATE `test_hash_tb` AS `test_hash_tb` SET `name` = ? WHERE (`id` = ?)")
-
+    logicalmodifyview(tables="optest_0001.test_hash_tb", sql="update `test_hash_tb` as `test_hash_tb` force index(`primary`) set `name` = ? where (`id` = ?)")
   # UnSupport update ignore
 #- sql: |
 #    update ignore test_hash_tb set name = 'a' where id = 1;
@@ -46,16 +44,12 @@
     update test_hash_tb set name = 'a' where id = 1 limit 10;
 
   plan: |
-
-    LogicalModifyView(tables="optest_0001.test_hash_tb", sql="UPDATE `test_hash_tb` AS `test_hash_tb` SET `name` = ? WHERE (`id` = ?) LIMIT ?")
-
+    logicalmodifyview(tables="optest_0001.test_hash_tb", sql="update `test_hash_tb` as `test_hash_tb` force index(`primary`) set `name` = ? where (`id` = ?) limit ?")
 - sql: |
     update test_hash_tb set name = 'a' where id = 1 order by id limit 10;
 
   plan: |
-
-    LogicalModifyView(tables="optest_0001.test_hash_tb", sql="UPDATE `test_hash_tb` AS `test_hash_tb` SET `name` = ? WHERE (`id` = ?) ORDER BY `id` LIMIT ?")
-
+    logicalmodifyview(tables="optest_0001.test_hash_tb", sql="update `test_hash_tb` as `test_hash_tb` force index(`primary`) set `name` = ? where (`id` = ?) order by `id` limit ?")
 - sql: |
     /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/update test_hash_tb set name = 'a' order by id;
 
@@ -67,10 +61,8 @@
     update test_hash_tb set id = 5 where id = 1 order by id limit 10;
 
   plan: |
-
-    LogicalRelocate(TYPE=UPDATE, SET="test_hash_tb.id=?0", RELOCATE="test_hash_tb")
-      LogicalView(tables="optest_0001.test_hash_tb", sql="SELECT `id`, `name`, `create_time`, ? FROM `test_hash_tb` AS `test_hash_tb` WHERE (`id` = ?) ORDER BY `id` LIMIT ? FOR UPDATE")
-
+    logicalrelocate(type=update, set="test_hash_tb.id=?0", relocate="test_hash_tb")
+      logicalview(tables="optest_0001.test_hash_tb", sql="select `id`, `name`, `create_time`, ? from `test_hash_tb` as `test_hash_tb` force index(`primary`) where (`id` = ?) order by `id` limit ? for update")
 - sql: |
     /*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/update test_single set name = 'a'
 
@@ -103,15 +95,12 @@
     update test_single set id = 5 where id in (select id from test_hash_ta where id > 10);
 
   plan: |
-
-    LogicalModify(TYPE="UPDATE", SET="test_single.id=?0")
-      Project(id="id", name="name", create_time="create_time", gen$0="?0")
-        SemiBKAJoin(condition="id = id", type="semi")
-          LogicalView(tables="optest_0000.test_single", sql="SELECT `id`, `name`, `create_time` FROM `test_single` AS `test_single` WHERE (`id` > ?) FOR UPDATE")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].test_hash_ta", shardCount=4, sql="SELECT `id` FROM `test_hash_ta` AS `test_hash_ta` WHERE ((`id` > ?) AND (`id` IN (...))) FOR UPDATE")
-
-
+    logicalmodify(type="update", set="test_single.id=?0")
+      project(id="id", name="name", create_time="create_time", gen$0="?0")
+        semibkajoin(condition="id = id", type="semi")
+          logicalview(tables="optest_0000.test_single", sql="select `id`, `name`, `create_time` from `test_single` as `test_single` where (`id` > ?) for update")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].test_hash_ta", shardcount=4, sql="select `id` from `test_hash_ta` as `test_hash_ta` force index(`primary`) where ((`id` > ?) and (`id` in (...))) for update")
 - sql: |
     update optest.test_single set test_single.name = 'a' where optest.test_single.name = 'test' order by optest.test_single.name limit 10;
 
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/flashback/FlashbackQueryTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/flashback/FlashbackQueryTest.config.yml
index 4dadd5932..b69cbca6f 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/flashback/FlashbackQueryTest.config.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/flashback/FlashbackQueryTest.config.yml
@@ -1,2 +1,4 @@
 ENABLE_BROADCAST_RANDOM_READ:
   false
+ENABLE_AUTO_FORCE_INDEX:
+    false
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/forceindex/ForceIndexAutoTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/forceindex/ForceIndexAutoTest.yml
new file mode 100644
index 000000000..33eeeef4a
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/forceindex/ForceIndexAutoTest.yml
@@ -0,0 +1,371 @@
+SQL:
+  # primary key
+  - sql: |
+      select * from t_order where id = 1 union all
+      select * from t_order where id in (1,2,3) union all
+      select * from t_order where id in (1,2,3+4) union all
+      select * from t_order where id in (1,2,'3') union all
+      select * from t_order where id in (1,2,id) union all
+      select * from t_order where (id,order_snapshot) in ((1,'321')) union all
+      select * from t_order where (id,order_snapshot) = (1,'321')
+    plan: |
+      unionall(concurrent=true)
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where (`id` = ?)")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where (`id` in(?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where (`id` in(?, ?, (? + ?)))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where (`id` in(?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where (`id` in(?, ?, `id`))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where (((`id`, `order_snapshot`)) in(?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where ((`id`, `order_snapshot`) =(?, ?))")
+  - sql: |
+      select * from t_order where id = 1 and 1=1 union all
+      select * from t_order where id = 1 and 1>1 union all
+      select * from t_order where id = 1 or 1>1 union all
+      select * from t_order where id = 1 and order_detail>id union all
+      select * from t_order where id = 1 or order_detail>id union all
+      select * from t_order where not id = 1 union all
+      select * from t_order where not id <> 1
+    plan: |
+      unionall(concurrent=true)
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where ((`id` = ?) and (1 = 1))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where ((1 > 1) and (`id` = ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((`id` = ?) or (1 > 1))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where ((`id` = ?) and (`order_detail` > `id`))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((`id` = ?) or (`order_detail` > `id`))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where (not (`id` = ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where (not (`id` <> ?))")
+  - sql: |
+      select * from t_order where id+1 = 1 union all
+      select * from t_order where id is null union all
+      select * from t_order where id = 1 and order_detail>1 union all
+      select * from t_order where (order_snapshot, id) in (('321',1)) union all
+      select * from t_order where (1,'321')= (id,order_snapshot) union all
+      select * from t_order where (1,'321')= (id-1,order_snapshot) union all
+      select * from t_order where ('321',1)= (order_snapshot, id)
+    plan: |
+      unionall(concurrent=true)
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((`id` + ?) = ?)")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where (`id` is null)")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where ((`id` = ?) and (`order_detail` > ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where (((`order_snapshot`, `id`)) in(?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where ((?, ?) =(`id`, `order_snapshot`))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((?, ?) =((`id` - ?), `order_snapshot`))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((?, ?) =(`order_snapshot`, `id`))")
+  - sql: |
+      select * from (select sum(id) as id from t_order group by order_id) where id = 1 union all
+      select * from (select id+1 as id from t_order) where id = 1 union all
+      select * from (select cast(id as decimal(10,0)) as id from t_order) where id = 1
+    plan: |
+      unionall(concurrent=true)
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id` from (select `order_id`, sum(`id`) as `id` from `t_order` as `t_order` group by `order_id` having (sum(`id`) = ?)) as `t0`")
+        gather(concurrent=true)
+          indexscan(tables="g_i_seller[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select (`id` + ?) as `id` from `g_i_seller` as `g_i_seller` where ((`id` + ?) = ?)")
+        gather(concurrent=true)
+          indexscan(tables="g_i_seller[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select cast(`id` as decimal(10, 0)) as `id` from `g_i_seller` as `g_i_seller` where (cast(`id` as decimal(10, 0)) = ?)")
+  - sql: |
+      select * from t_order where product_id = 1 and order_snapshot='1' union all
+      select * from t_order where product_id = 1 and order_snapshot in('1','2') union all
+      select * from t_order where product_id in(1,2) and order_snapshot in('1','2') union all
+      select * from t_order where product_id in(1,2) and order_snapshot='1' union all
+      select * from t_order where (product_id,order_snapshot) in((1,'2')) union all
+      select * from t_order where (product_id,order_snapshot) =((1,'2')) union all
+      select * from t_order where (order_snapshot,product_id) in(('2',1)) union all
+      select * from t_order where (order_snapshot,product_id) =(('2',1))
+    plan: |
+      unionall(concurrent=true)
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`uk`) where ((`product_id` = ?) and (`order_snapshot` = ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`uk`) where ((`product_id` = ?) and (`order_snapshot` in(?)))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`uk`) where ((`product_id` in(?)) and (`order_snapshot` in(?)))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`uk`) where ((`product_id` in(?)) and (`order_snapshot` = ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where (((`product_id`, `order_snapshot`)) in(?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((`product_id`, `order_snapshot`) =(?, ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`uk`) where (((`order_snapshot`, `product_id`)) in(?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`uk`) where ((`order_snapshot`, `product_id`) =(?, ?))")
+  - sql: |
+      select * from t_order where product_id = 1 and order_snapshot='1' and seller_id=1 union all
+      select * from t_order where product_id = 1 and order_snapshot='1' and seller_id=product_id union all
+      select * from t_order where product_id = 1 and order_snapshot='1' and (seller_id=1 or order_snapshot='2') union all
+      select * from t_order where (order_snapshot+1,product_id) in(('2',1)) union all
+      (select * from (select * from t_order where (order_snapshot,product_id) in(('2',1)) ) where id > 1 order by id) union all
+      (select * from (select * from t_order order by id) where (order_snapshot,product_id) in(('2',1)) )
+    plan: |
+      unionall(concurrent=true)
+        project(id="id", order_id="order_id", buyer_id="buyer_id", seller_id="seller_id", product_id="product_id", extra_id="extra_id", order_snapshot="order_snapshot", order_detail="order_detail")
+          bkajoin(condition="id = id and order_id <=> order_id", type="inner")
+            indexscan(tables="g_i_seller[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot` from `g_i_seller` as `g_i_seller` where ((`order_snapshot` = ?) and (`seller_id` = ?))")
+            gather(concurrent=true)
+              logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `product_id`, `extra_id`, `order_detail` from `t_order` as `t_order` force index(`primary`) where ((`product_id` = ?) and (`order_snapshot` = ?) and (`seller_id` = ?) and (`id` in (...)))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`uk`) where ((`seller_id` = `product_id`) and (`product_id` = ?) and (`order_snapshot` = ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`uk`) where ((`product_id` = ?) and (`order_snapshot` = ?) and ((`seller_id` = ?) or (`order_snapshot` = ?)))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((((`order_snapshot` + ?), `product_id`)) in(?))")
+        mergesort(sort="id asc")
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`uk`) where ((((`order_snapshot`, `product_id`)) in(?)) and (`id` > ?)) order by `id`")
+        mergesort(sort="id asc")
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`uk`) where (((`order_snapshot`, `product_id`)) in(?)) order by `id`")
+  - sql: |
+      select * from t_order where product_id = 1 union all
+      select * from t_order where product_id = 1 and order_detail='1' union all
+      select * from t_order where product_id = 1 and order_id=1 union all
+      select * from t_order where order_id=1 union all
+      select * from t_order where product_id = 1 and order_detail='1' and extra_id=1 union all
+      select * from t_order where product_id = 1 and order_detail='1' and buyer_id>1
+    plan: |
+      unionall(concurrent=true)
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`prdo`) where (`product_id` = ?)")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`product_id`) where ((`product_id` = ?) and (`order_detail` = ?))")
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`prdo`) where ((`product_id` = ?) and (`order_id` = ?))")
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`auto_shard_key_order_id`) where (`order_id` = ?)")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((`extra_id` = ?) and (`product_id` = ?) and (`order_detail` = ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((`product_id` = ?) and (`order_detail` = ?) and (`buyer_id` > ?))")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_index_selection=false)*/
+      select * from t_order where product_id = '1' and (`order_id`,`seller_id`) in (('1','2')) union all
+      select * from t_order where product_id = '1' and (`order_id`,`order_detail`) in (('1','2')) union all
+      select * from t_order where product_id = '1' and (`order_id`,`seller_id`)= ('1','2') union all
+      select * from t_order where product_id = '1' and (`order_id`,`seller_id`)= ('1',order_detail) union all
+      select * from t_order where product_id = '1' and (`order_id`,`seller_id`)in (('1',order_detail)) union all
+      select * from t_order where product_id = '1' and ('1','2')=(`order_id`,`seller_id`) union all
+      select * from t_order where product_id = '1' and (order_id,order_detail)=('1','2')
+    plan: |
+      unionall(concurrent=true)
+        gather(concurrent=true)
+          logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`prdo`) where ((((`order_id`, `seller_id`)) in(?)) and (`product_id` = ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((((`order_id`, `order_detail`)) in(?)) and (`product_id` = ?))")
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`prdo`) where (((`order_id`, `seller_id`) =(?, ?)) and (`product_id` = ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where (((`order_id`, `seller_id`) =(?, `order_detail`)) and (`product_id` = ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((((`order_id`, `seller_id`)) in((?, `order_detail`))) and (`product_id` = ?))")
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`prdo`) where (((?, ?) =(`order_id`, `seller_id`)) and (`product_id` = ?))")
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where (((`order_id`, `order_detail`) =(?, ?)) and (`product_id` = ?))")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_index_selection=false)*/
+      select * from t_order where (`product_id`,`order_detail`,`buyer_id`,id)=('1','1','1',1) union all
+      select * from t_order where (`product_id`,`order_detail`)=('1','1') and (`buyer_id`,id)=('1',1) union all
+      select * from t_order where (`product_id`,`order_detail`,`buyer_id`)=('1','1','1') union all
+      select * from t_order where id > 1 and (`product_id`,`order_detail`,`buyer_id`)=('1','1','1') union all
+      select * from t_order where id between(1,2) and (`product_id`,`order_detail`,`buyer_id`)=('1','1','1') union all
+      select * from t_order where (1=2 or 2=3) and (`product_id`,`order_detail`,`buyer_id`)=('1','1','1')  union all
+      select * from t_order where (substring(buyer_id, 4)='1') and (`product_id`,`order_detail`,`buyer_id`)=('1','1','1')
+    plan: |
+      unionall(concurrent=true)
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((`product_id`, `order_detail`, `buyer_id`, `id`) =(?, ?, ?, ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where (((`product_id`, `order_detail`) =(?, ?)) and ((`buyer_id`, `id`) =(?, ?)))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`product_id`) where ((`product_id`, `order_detail`, `buyer_id`) =(?, ?, ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where (((`product_id`, `order_detail`, `buyer_id`) =(?, ?, ?)) and (`id` > ?))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where (`id` between(?, ?) and ((`product_id`, `order_detail`, `buyer_id`) =(?, ?, ?)))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`product_id`) where (((`product_id`, `order_detail`, `buyer_id`) =(?, ?, ?)) and ((1 = 2) or (2 = 3)))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((substring(`buyer_id`, ?) = ?) and ((`product_id`, `order_detail`, `buyer_id`) =(?, ?, ?)))")
+  - sql: |
+      /*+TDDL:cmd_extra(enable_index_selection=false)*/
+      (select * from t_order where (`product_id`,`order_id`,`seller_id`)=('1','1','1') order by buyer_id desc) union all
+      (select * from t_order where (`product_id`,`order_id`,`seller_id`)=('1','1','1') order by seller_id desc) union all
+      (select * from t_order where (`product_id`,`order_id`)=('1','1') order by seller_id desc,buyer_id) union all
+      (select * from t_order where (`product_id`,`order_id`)=('1','1') order by seller_id,buyer_id desc, id) union all
+      (select * from t_order where (`product_id`,`order_id`)=('1','1') order by seller_id desc, buyer_id limit 10) union all
+      (select * from t_order where (`product_id`,`order_id`)=('1','1') order by buyer_id,seller_id desc) union all
+      (select * from t_order where (`product_id`,`order_id`)=('1','1') order by seller_id+1 desc, buyer_id limit 10)
+    plan: |
+      unionall(concurrent=true)
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`prdo_long`) where ((`product_id`, `order_id`, `seller_id`) =(?, ?, ?)) order by `buyer_id` desc")
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((`product_id`, `order_id`, `seller_id`) =(?, ?, ?)) order by `seller_id` desc")
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`prdo_long`) where ((`product_id`, `order_id`) =(?, ?)) order by `seller_id` desc, `buyer_id`")
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((`product_id`, `order_id`) =(?, ?)) order by `seller_id`, `buyer_id` desc, `id`")
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`prdo_long`) where ((`product_id`, `order_id`) =(?, ?)) order by `seller_id` desc, `buyer_id` limit ?")
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((`product_id`, `order_id`) =(?, ?)) order by `buyer_id`, `seller_id` desc")
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where ((`product_id`, `order_id`) =(?, ?)) order by (`seller_id` + ?) desc, `buyer_id` limit ?")
+  - sql: |
+      select * from t_order force index(primary) where product_id = 1 union all
+      select * from t_order force index(g_i_seller) where product_id = 1 union all
+      select * from t_order use index(primary) where product_id = 1 union all
+      select * from t_order ignore index(primary) where product_id = 1
+    plan: |
+      unionall(concurrent=true)
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(primary) where (`product_id` = ?)")
+        project(id="id", order_id="order_id", buyer_id="buyer_id", seller_id="seller_id", product_id="product_id", extra_id="extra_id", order_snapshot="order_snapshot", order_detail="order_detail")
+          bkajoin(condition="id = id and order_id <=> order_id", type="inner")
+            gather(concurrent=true)
+              indexscan(tables="g_i_seller[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot` from `g_i_seller` as `g_i_seller`")
+            gather(concurrent=true)
+              logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `product_id`, `extra_id`, `order_detail` from `t_order` as `t_order` force index(`primary`) where ((`product_id` = ?) and (`id` in (...)))")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` use index(primary) where (`product_id` = ?)")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` ignore index(primary) where (`product_id` = ?)")
+  - sql: |
+      /*+TDDL:index(t_order,g_i_buyer)*/ select * from t_order where product_id = 1
+    plan: |
+      project(id="id", order_id="order_id", buyer_id="buyer_id", seller_id="seller_id", product_id="product_id", extra_id="extra_id", order_snapshot="order_snapshot", order_detail="order_detail")
+        bkajoin(condition="id = id and order_id <=> order_id", type="inner")
+          gather(concurrent=true)
+            indexscan(tables="g_i_buyer[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `order_snapshot` from `g_i_buyer` as `g_i_buyer`")
+          gather(concurrent=true)
+            logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `product_id`, `extra_id`, `order_detail` from `t_order` as `t_order` force index(`primary`) where ((`product_id` = ?) and (`id` in (...)))")
+  - sql: |
+      /*+TDDL:cmd_extra(ENABLE_AUTO_FORCE_INDEX=false)*/ select * from t_order where product_id = 1
+    plan: |
+      gather(concurrent=true)
+        logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` where (`product_id` = ?)")
+  - sql: |
+      select * from t_order t1, t_order t2 where t1.id =1 and t1.product_id = t2.product_id;
+    plan: |
+      bkajoin(condition="product_id = product_id", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where (`id` = ?)")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`prdo`) where (`product_id` in (...))")
+  - sql: |
+      select * from t_order t1, t_order t2 where t1.product_id = t2.product_id and t1.order_detail= t2.order_detail;
+    plan: |
+      bkajoin(condition="product_id = product_id and order_detail = order_detail", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order`")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`product_id`) where (((`product_id`, `order_detail`)) in (...))")
+  - sql: |
+      select * from t_order t1, t_order t2 where t1.id =1 and t1.product_id = t2.product_id and t1.order_id = t2.order_id;
+    plan: |
+      gather(concurrent=true)
+        logicalview(tables="t_order[p1,p2,p3,p4,p5,p6],t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `t_order`.`id`, `t_order`.`order_id`, `t_order`.`buyer_id`, `t_order`.`seller_id`, `t_order`.`product_id`, `t_order`.`extra_id`, `t_order`.`order_snapshot`, `t_order`.`order_detail`, `t_order0`.`id` as `id0`, `t_order0`.`order_id` as `order_id0`, `t_order0`.`buyer_id` as `buyer_id0`, `t_order0`.`seller_id` as `seller_id0`, `t_order0`.`product_id` as `product_id0`, `t_order0`.`extra_id` as `extra_id0`, `t_order0`.`order_snapshot` as `order_snapshot0`, `t_order0`.`order_detail` as `order_detail0` from `t_order` as `t_order` inner join `t_order` as `t_order0` on ((`t_order`.`product_id` = `t_order0`.`product_id`) and (`t_order`.`id` = ?) and (`t_order`.`order_id` = `t_order0`.`order_id`))")
+  - sql: |
+      select * from t_order t1, t_order t2 where t1.id =1 and t1.product_id = t2.product_id order by t1.product_id;
+    plan: |
+      bkajoin(condition="product_id = product_id", type="inner")
+        mergesort(sort="product_id asc")
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`primary`) where (`id` = ?) order by `product_id`")
+        gather(concurrent=true)
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`prdo`) where (`product_id` in (...))")
+  - sql: |
+      (select order_id, count(1) from t_order t1 group by order_id order by order_id) union all
+      (select order_id, count(1) from t_order t1 group by `product_id`,`order_id`,`seller_id` order by order_id) union all
+      (select order_id, count(1) from t_order t1 group by `product_id`,`order_id`,`seller_id` order by `product_id`,`order_id`) ;
+    plan: |
+      unionall(concurrent=true)
+        mergesort(sort="order_id asc")
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `order_id`, count(*) as `count(1)` from `t_order` as `t_order` force index(`auto_shard_key_order_id`) group by `order_id` order by `order_id`")
+        project(order_id="order_id", count(1)="count(1)")
+          mergesort(sort="order_id asc")
+            logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `product_id`, `order_id`, `seller_id`, count(*) as `count(1)` from `t_order` as `t_order` force index(`auto_shard_key_order_id`) group by `order_id`, `seller_id`, `product_id` order by `order_id`")
+        project(order_id="order_id", count(1)="count(1)")
+          mergesort(sort="product_id asc,order_id asc")
+            logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `product_id`, `order_id`, `seller_id`, count(*) as `count(1)` from `t_order` as `t_order` force index(`prdo`) group by `order_id`, `seller_id`, `product_id` order by `product_id`, `order_id`")
+  - sql: |
+      select order_id, count(1) from t_order t1 group by order_id order by `product_id`,`order_id`,`seller_id`;
+    plan: |
+      project(order_id="order_id", count(1)="count(1)")
+        mergesort(sort="$f2 asc,order_id asc,$f3 asc")
+          logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `order_id`, count(*) as `count(1)`, (`product_id`) as `$f2`, (`seller_id`) as `$f3` from `t_order` as `t_order` group by `order_id` order by (`product_id`), `order_id`, (`seller_id`)")
+  - sql: |
+      select * from t_order t1 group by buyer_id order by order_id;
+    plan: |
+      project(id="id", order_id="order_id", buyer_id="buyer_id", seller_id="seller_id", product_id="product_id", extra_id="extra_id", order_snapshot="order_snapshot", order_detail="order_detail")
+        memsort(sort="order_id asc")
+          hashagg(group="buyer_id", id="__first_value(id)", order_id="__first_value(order_id)", seller_id="__first_value(seller_id)", product_id="__first_value(product_id)", extra_id="__first_value(extra_id)", order_snapshot="__first_value(order_snapshot)", order_detail="__first_value(order_detail)")
+            gather(concurrent=true)
+              logicalview(tables="t_order[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `buyer_id`, (`id`) as `id`, (`order_id`) as `order_id`, (`seller_id`) as `seller_id`, (`product_id`) as `product_id`, (`extra_id`) as `extra_id`, (`order_snapshot`) as `order_snapshot`, (`order_detail`) as `order_detail` from `t_order` as `t_order` group by `buyer_id`")
+  - sql: |
+      select * from t_order where `product_id`=1 and `order_id` = 1 group by buyer_id order by seller_id;
+    plan: |
+      phytableoperation(tables="t_order[p6]", sql="select (`t_order`.`id`) as `id`, (`t_order`.`order_id`) as `order_id`, `t_order`.`buyer_id`, (`t_order`.`seller_id`) as `seller_id`, (`t_order`.`product_id`) as `product_id`, (`t_order`.`extra_id`) as `extra_id`, (`t_order`.`order_snapshot`) as `order_snapshot`, (`t_order`.`order_detail`) as `order_detail` from ? as `t_order` where ((`t_order`.`product_id` = ?) and (`t_order`.`order_id` = ?)) group by `t_order`.`buyer_id` order by `seller_id`", params="1,1")
+  - sql: |
+      select * from t_order where `order_id` = 1;
+    plan: |
+      phytableoperation(tables="t_order[p6]", sql="select `t_order`.`id`, `t_order`.`order_id`, `t_order`.`buyer_id`, `t_order`.`seller_id`, `t_order`.`product_id`, `t_order`.`extra_id`, `t_order`.`order_snapshot`, `t_order`.`order_detail` from ? as `t_order` where (`t_order`.`order_id` = ?)", params="1")
+  - sql: |
+      select 1 from t_order where `seller_id` in(1);
+    plan: |
+      gather(concurrent=true)
+        indexscan(tables="g_i_seller[p6]", sql="select ? as `1` from `g_i_seller` as `g_i_seller` force index(`auto_shard_key_seller_id`) where (`seller_id` in(?))")
+  - sql: |
+      select * from t_order where `order_id` in(1);
+    plan: |
+      gather(concurrent=true)
+        logicalview(tables="t_order[p6]", sql="select `id`, `order_id`, `buyer_id`, `seller_id`, `product_id`, `extra_id`, `order_snapshot`, `order_detail` from `t_order` as `t_order` force index(`auto_shard_key_order_id`) where (`order_id` in(?))")
+  - sql: |
+      select * from t_special where `buyer_id` in(1);
+    plan: |
+      gather(concurrent=true)
+        logicalview(tables="t_special[p1,p2,p3,p4,p5,p6]", shardcount=6, sql="select `id`, `order_id`, `buyer_id` from `t_special` as `t_special` force index(`gg-sp`) where (`buyer_id` in(?))")
+DDL:
+  t_order:
+    CREATE TABLE `t_order` (
+    `id` bigint(11) NOT NULL AUTO_INCREMENT,
+    `order_id` int(20) DEFAULT NULL,
+    `buyer_id` int(20) DEFAULT NULL,
+    `seller_id` int(20) DEFAULT NULL,
+    `product_id` int(20) DEFAULT NULL,
+    `extra_id` int(20) DEFAULT NULL,
+    `order_snapshot` longtext,
+    `order_detail` longtext,
+    PRIMARY KEY (`id`),
+    KEY `auto_shard_key_order_id` USING BTREE (`order_id`),
+    KEY(`product_id`,`order_detail`,`buyer_id`),
+    KEY `prdo` (`product_id`,`order_id`,`seller_id`),
+    KEY `prdo_long` (`product_id`,`order_id`,`seller_id`,`buyer_id`),
+    unique KEY `uk` USING BTREE (`order_snapshot`,`product_id`),
+    GLOBAL INDEX `g_i_buyer`(`buyer_id`) COVERING (`id`, `order_id`, `seller_id`, `order_snapshot`) partition by key(`buyer_id`) PARTITIONS 6,
+    GLOBAL INDEX `g_i_seller` (`seller_id`) COVERING (`id`, `order_id`, `buyer_id`, `order_snapshot`) partition by key(`seller_id`) PARTITIONS 6
+    ) ENGINE = InnoDB AUTO_INCREMENT = 2300006 CHARSET = utf8 partition by key(`order_id`) PARTITIONS 6
+  t_special:
+    CREATE TABLE `t_special` (
+    `id` bigint(11) NOT NULL AUTO_INCREMENT,
+    `order_id` int(20) DEFAULT NULL,
+    `buyer_id` int(20) DEFAULT NULL,
+    PRIMARY KEY (`id`),
+    KEY `auto_shard_key_order_id` USING BTREE (`order_id`),
+    KEY `gg-sp`(`buyer_id`)
+    ) ENGINE = InnoDB AUTO_INCREMENT = 2300006 CHARSET = utf8 partition by key(`order_id`) PARTITIONS 6
+STATISTICS:
+  t_order:
+    100
+  t_special:
+    100
+CONFIG:
+  defaltxxAPPName.isNew:
+    true
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/foreignkey/DeleteCascadeTest.delete.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/foreignkey/DeleteCascadeTest.delete.yml
index 349ee2885..1814e5a96 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/foreignkey/DeleteCascadeTest.delete.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/foreignkey/DeleteCascadeTest.delete.yml
@@ -2,10 +2,8 @@
     delete from test_hash_ta where id = 1;
 
   plan: |
-
     logicalmodify(type="delete", tables="optest.test_hash_ta")
-      logicalview(tables="optest_0001.test_hash_ta", sql="select `id`, `name`, `school`, `create_time` from `test_hash_ta` as `test_hash_ta` where (`id` = ?) for update")
-
+      logicalview(tables="optest_0001.test_hash_ta", sql="select `id`, `name`, `school`, `create_time` from `test_hash_ta` as `test_hash_ta` force index(`primary`) where (`id` = ?) for update")
 - sql: |
     delete from test_hash_ta where name = 'test';
 
@@ -35,10 +33,8 @@
     delete from test_hash_single_1 where id = 1;
 
   plan: |
-
     logicalmodify(type="delete", tables="optest.test_hash_single_1")
-      logicalview(tables="optest_0000.test_hash_single_1", sql="select `id`, `name`, `create_time` from `test_hash_single_1` as `test_hash_single_1` where (`id` = ?) for update")
-
+      logicalview(tables="optest_0000.test_hash_single_1", sql="select `id`, `name`, `create_time` from `test_hash_single_1` as `test_hash_single_1` force index(`primary`) where (`id` = ?) for update")
 - sql: |
     delete from test_hash_single_1 where name = 'test';
 
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/foreignkey/UpdateCascadeTest.update.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/foreignkey/UpdateCascadeTest.update.yml
index 202d977a0..f24b4c208 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/foreignkey/UpdateCascadeTest.update.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/foreignkey/UpdateCascadeTest.update.yml
@@ -2,10 +2,8 @@
     update test_hash_ta set id = 2 where id = 1;
 
   plan: |
-
     logicalrelocate(type=update, set="test_hash_ta.id=?0", relocate="test_hash_ta")
-      logicalview(tables="optest_0001.test_hash_ta", sql="select `id`, `name`, `school`, `create_time`, ? from `test_hash_ta` as `test_hash_ta` where (`id` = ?) for update")
-
+      logicalview(tables="optest_0001.test_hash_ta", sql="select `id`, `name`, `school`, `create_time`, ? from `test_hash_ta` as `test_hash_ta` force index(`primary`) where (`id` = ?) for update")
 - sql: |
     update test_hash_ta set name = 'test1' where name = 'test';
 
@@ -26,18 +24,14 @@
     update test_hash_tb set id = 2 where id = 1;
 
   plan: |
-
     logicalrelocate(type=update, set="test_hash_tb.id=?0", relocate="test_hash_tb")
-      logicalview(tables="optest_0001.test_hash_tb", sql="select `id`, `name`, `create_time`, ? from `test_hash_tb` as `test_hash_tb` where (`id` = ?) for update")
-
+      logicalview(tables="optest_0001.test_hash_tb", sql="select `id`, `name`, `create_time`, ? from `test_hash_tb` as `test_hash_tb` force index(`primary`) where (`id` = ?) for update")
 - sql: |
     update test_hash_single_1 set id = 2 where id = 1;
 
   plan: |
-
     logicalmodify(type="update", set="test_hash_single_1.id=?0")
-      logicalview(tables="optest_0000.test_hash_single_1", sql="select `id`, `name`, `create_time`, ? from `test_hash_single_1` as `test_hash_single_1` where (`id` = ?) for update")
-
+      logicalview(tables="optest_0000.test_hash_single_1", sql="select `id`, `name`, `create_time`, ? from `test_hash_single_1` as `test_hash_single_1` force index(`primary`) where (`id` = ?) for update")
 - sql: |
     update test_hash_single_1 set name = 'test1' where name = 'test';
 
@@ -49,6 +43,5 @@
     update test_hash_single_2 set id = 2 where id = 1;
 
   plan: |
-
     logicalmodify(type="update", set="test_hash_single_2.id=?0")
-      logicalview(tables="optest_0000.test_hash_single_2", sql="select `id`, `name`, `create_time`, ? from `test_hash_single_2` as `test_hash_single_2` where (`id` = ?) for update")
\ No newline at end of file
+      logicalview(tables="optest_0000.test_hash_single_2", sql="select `id`, `name`, `create_time`, ? from `test_hash_single_2` as `test_hash_single_2` force index(`primary`) where (`id` = ?) for update")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/gencol/GeneratedColumnTest.select.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/gencol/GeneratedColumnTest.select.yml
index 1d45686dd..26bd9bbc7 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/gencol/GeneratedColumnTest.select.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/gencol/GeneratedColumnTest.select.yml
@@ -235,9 +235,8 @@
     /*TDDL:GEN_COL_SUBSTITUTION=TRUE*/ select * from gc_test_tbl_3 where a+1=10 and c+1=10 and a+1+1=10
 
   plan: |
-    phytableoperation(tables="optest_0002.[gc_test_tbl_3]", sql="select `gc_test_tbl_3`.`a`, `gc_test_tbl_3`.`b`, `gc_test_tbl_3`.`c` from ? as `gc_test_tbl_3` where ((`gc_test_tbl_3`.`c` = ?) and (`gc_test_tbl_3`.`b` = ?) and (`gc_test_tbl_3`.`b` = ?))", params="10,1,10,1,1,10,1")
-
-
+    gather(concurrent=true)
+      logicalview(tables="optest_0002.gc_test_tbl_3", sql="select `a`, `b`, `c` from `gc_test_tbl_3` as `gc_test_tbl_3` where ((`c` = ?) and (`b` = ?) and (`b` = ?))")
 - sql: |
     /*TDDL:GEN_COL_SUBSTITUTION=TRUE*/ select a+1+1 from gc_test_tbl_3
 
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.config.yml
new file mode 100644
index 000000000..d17376931
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.config.yml
@@ -0,0 +1,6 @@
+defaltxxAPPName.isNew:
+  false
+defaltxxAPPName.withSingleGroup:
+  true
+defaltxxAPPName.dbNumber:
+  5
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.ddl.yml
new file mode 100644
index 000000000..06efd5b0a
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.ddl.yml
@@ -0,0 +1,70 @@
+test_table_a:
+  CREATE TABLE `test_table_a` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `bigint_test`       BIGINT       DEFAULT NULL,
+  `varchar_test_p255` VARCHAR(255) DEFAULT NULL,
+  `datetime_test`     DATETIME     DEFAULT NULL,
+  `text_test`         TEXT         DEFAULT NULL,
+  `timestamp_test`    TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 DBPARTITION BY HASH(pk) TBPARTITION BY HASH(pk) TBPARTITIONS 7
+
+test_table_b:
+  CREATE TABLE `test_table_b` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `bigint_test`       BIGINT       DEFAULT NULL,
+  `varchar_test_p255` VARCHAR(255) DEFAULT NULL,
+  `datetime_test`     DATETIME     DEFAULT NULL,
+  `text_test`         TEXT         DEFAULT NULL,
+  `timestamp_test`    TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 DBPARTITION BY HASH(pk) TBPARTITION BY HASH(pk) TBPARTITIONS 7
+
+test_table_c:
+  CREATE TABLE `test_table_c` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `bigint_test`       BIGINT       DEFAULT NULL,
+  `varchar_test_p255` VARCHAR(255) DEFAULT NULL,
+  `datetime_test`     DATETIME     DEFAULT NULL,
+  `text_test`         TEXT         DEFAULT NULL,
+  `timestamp_test`    TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 BROADCAST
+
+test_table_d:
+  CREATE TABLE `test_table_single` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `bigint_test`       BIGINT       DEFAULT NULL,
+  `varchar_test_p255` VARCHAR(255) DEFAULT NULL,
+  `datetime_test`     DATETIME     DEFAULT NULL,
+  `text_test`         TEXT         DEFAULT NULL,
+  `timestamp_test`    TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8
+
+test_single:
+  CREATE TABLE `test_single` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+test_broadcast:
+  CREATE TABLE `test_broadcast` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST;
+
+test_broadcast_b:
+  CREATE TABLE `test_broadcast_b` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST;
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.testNodeHint.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.testNodeHint.yml
new file mode 100644
index 000000000..3d62cecab
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanSingleGroupTest.testNodeHint.yml
@@ -0,0 +1,129 @@
+# CoronaDB HINT
+
+## node
+- sql: |
+    select /*+TDDL: node(0)*/
+    pk from test_table_a;
+
+  plan: |
+
+    PhyQuery(node="optest_000000_group", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
+
+- sql: |
+    select /*+TDDL: node("0,1,3")*/
+    pk from test_table_a;
+
+  plan: |
+
+    PhyViewUnion(concurrent=true)
+      PhyQuery(node="optest_000000_group", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
+      PhyQuery(node="optest_000001_group", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
+      PhyQuery(node="optest_000003_group", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
+
+- sql: |
+    /*+TDDL: node(0)*/
+    show tables like "%test%"
+
+  plan: |
+
+    PhyQuery(node="optest_000000_group", sql="SHOW TABLES LIKE '%test%'")
+
+- sql: |
+    /*+TDDL: node('0, 1')*/
+    show tables like "%test%"
+
+  plan: |
+
+    PhyViewUnion(concurrent=true)
+      PhyQuery(node="optest_000000_group", sql="show tables like '%test%'")
+      PhyQuery(node="optest_000001_group", sql="show tables like '%test%'")
+
+- sql: |
+    /*+TDDL: node(0)*/
+    desc test_table_a
+
+  plan: |
+
+    PhyQuery(node="optest_000000_group", sql="desc `test_table_a`")
+
+- sql: |
+    /*+TDDL: node(0) cmd_extra(PUSHDOWN_HINT_ON_BROADCAST=true)*/ 
+    insert into test_broadcast(id, name, create_time) values(1, "a", "2024-09-03 19:15:11");
+
+  plan: |
+
+    PhyQuery(node="optest_000000_group", sql="insert into `test_broadcast` (`id`, `name`, `create_time`) values(?, ?, ?)")
+
+- sql: |
+    /*+TDDL: node(0) cmd_extra(COPY_MODIFY_NODE0_TO_SINGLE=true, PUSHDOWN_HINT_ON_BROADCAST=true)*/ 
+    insert into test_single(id, name, create_time) values(1, "a", "2024-09-03 19:15:11");
+
+  plan: |
+
+    PhyQuery(node="optest_single_group", sql="insert into `test_single` (`id`, `name`, `create_time`) values(?, ?, ?)")
+
+- sql: |
+    /*+TDDL: node(0) cmd_extra(COPY_MODIFY_NODE0_TO_SINGLE=true, PUSHDOWN_HINT_ON_BROADCAST=true)*/ 
+    insert into test_broadcast(id, name, create_time) values(1, "a", "2024-09-03 19:15:11");
+
+  plan: |
+
+    PhyViewUnion(concurrent=true)
+      PhyQuery(node="optest_000000_group", sql="insert into `test_broadcast` (`id`, `name`, `create_time`) values(?, ?, ?)")
+      PhyQuery(node="optest_single_group", sql="insert into `test_broadcast` (`id`, `name`, `create_time`) values(?, ?, ?)")
+
+- sql: |
+    /*+TDDL: node("optest_000000_group,optest_single_group") cmd_extra(COPY_MODIFY_NODE0_TO_SINGLE=true, PUSHDOWN_HINT_ON_BROADCAST=true)*/ 
+    insert into test_broadcast(id, name, create_time) values(1, "a", "2024-09-03 19:15:11");
+
+  plan: |
+
+    PhyViewUnion(concurrent=true)
+      PhyQuery(node="optest_000000_group", sql="insert into `test_broadcast` (`id`, `name`, `create_time`) values(?, ?, ?)")
+      PhyQuery(node="optest_single_group", sql="insert into `test_broadcast` (`id`, `name`, `create_time`) values(?, ?, ?)")
+
+- sql: |
+    /*+TDDL: node(0) cmd_extra(COPY_MODIFY_NODE0_TO_SINGLE=true, PUSHDOWN_HINT_ON_BROADCAST=true)*/ 
+    update test_broadcast set name = "b", create_time = "2024-09-03 19:15:11" where id = 1;
+
+  plan: |
+
+    PhyViewUnion(concurrent=true)
+      PhyQuery(node="optest_000000_group", sql="update `test_broadcast` as `test_broadcast` set `name` = ? , `create_time` = ? where (`id` = ?)")
+      PhyQuery(node="optest_single_group", sql="update `test_broadcast` as `test_broadcast` set `name` = ? , `create_time` = ? where (`id` = ?)")
+
+- sql: |
+    /*+TDDL: node(0) cmd_extra(COPY_MODIFY_NODE0_TO_SINGLE=true, PUSHDOWN_HINT_ON_BROADCAST=true)*/ 
+    delete from test_broadcast where id = 1;
+
+  plan: |
+
+    PhyViewUnion(concurrent=true)
+      PhyQuery(node="optest_000000_group", sql="delete from `test_broadcast` where (`id` = ?)")
+      PhyQuery(node="optest_single_group", sql="delete from `test_broadcast` where (`id` = ?)")
+
+- sql: |
+    /*+TDDL: node(0) cmd_extra(COPY_MODIFY_NODE0_TO_SINGLE=true, PUSHDOWN_HINT_ON_BROADCAST=true)*/ 
+    delete b from test_broadcast a join test_broadcast_b b on a.id = b.id where b.name = "b";
+
+  plan: |
+
+    PhyViewUnion(concurrent=true)
+      PhyQuery(node="optest_000000_group", sql="delete `b` from `test_broadcast` as `a` inner join `test_broadcast_b` as `b` on (`a`.`id` = `b`.`id`) where (`b`.`name` = ?)")
+      PhyQuery(node="optest_single_group", sql="delete `b` from `test_broadcast` as `a` inner join `test_broadcast_b` as `b` on (`a`.`id` = `b`.`id`) where (`b`.`name` = ?)")
+
+- sql: |
+    /*+TDDL: node(0) cmd_extra(COPY_MODIFY_NODE0_TO_SINGLE=true, PUSHDOWN_HINT_ON_BROADCAST=true)*/ 
+    delete b from test_broadcast a join test_table_b b on a.id = b.pk where b.varchar_test_p255 = "b";
+
+  plan: |
+
+    PhyQuery(node="optest_000000_group", sql="delete `b` from `test_broadcast` as `a` inner join `test_table_b` as `b` on (`a`.`id` = `b`.`pk`) where (`b`.`varchar_test_p255` = ?)")
+
+- sql: |
+    /*+TDDL: node(0) cmd_extra(COPY_MODIFY_NODE0_TO_SINGLE=true, PUSHDOWN_HINT_ON_BROADCAST=true)*/ 
+    delete b from test_broadcast a join test_single b on a.id = b.id where b.name = "b";
+
+  plan: |
+
+    PhyQuery(node="optest_single_group", sql="delete `b` from `test_broadcast` as `a` inner join `test_single` as `b` on (`a`.`id` = `b`.`id`) where (`b`.`name` = ?)")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.ddl.yml
index 655b8d181..06efd5b0a 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.ddl.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.ddl.yml
@@ -41,3 +41,30 @@ test_table_d:
   `timestamp_test`    TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
   PRIMARY KEY (`pk`)
   ) ENGINE=InnoDB DEFAULT CHARSET=UTF8
+
+test_single:
+  CREATE TABLE `test_single` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+test_broadcast:
+  CREATE TABLE `test_broadcast` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST;
+
+test_broadcast_b:
+  CREATE TABLE `test_broadcast_b` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST;
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testNodeHint.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testNodeHint.yml
index 693449471..723fea49f 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testNodeHint.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testNodeHint.yml
@@ -7,8 +7,7 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="optest_0000.test_table_a_[00-06]", shardCount=7, sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+    PhyQuery(node="optest_0000", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
 
 - sql: |
     select /*+TDDL: node("0,1,3")*/
@@ -16,8 +15,10 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000,0001,0003].test_table_a_[00-13,21-27]", shardCount=21, sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+    PhyViewUnion(concurrent=true)
+      PhyQuery(node="optest_0000", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
+      PhyQuery(node="optest_0001", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
+      PhyQuery(node="optest_0003", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
 
 - sql: |
     /*+TDDL: node(0)*/
@@ -34,7 +35,8 @@
   plan: |
 
     PhyViewUnion(concurrent=true)
-      PhyQuery(node="[0000,0001]", sql="SHOW TABLES LIKE '%test%'")
+      PhyQuery(node="optest_0000", sql="show tables like '%test%'")
+      PhyQuery(node="optest_0001", sql="show tables like '%test%'")
 
 - sql: |
     /*+TDDL: node(0)*/
@@ -42,4 +44,4 @@
 
   plan: |
 
-    PhyQuery(node="optest_0000", sql="SHOW COLUMNS FROM `test_table_a` WHERE (`field` <> '_drds_implicit_id_')")
+    PhyQuery(node="optest_0000", sql="desc `test_table_a`")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testRandomNodeHint.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testRandomNodeHint.yml
index 1b08c22f9..6aeed7b66 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testRandomNodeHint.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testRandomNodeHint.yml
@@ -7,8 +7,7 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="optest_0000.test_table_a_[00-06]", shardCount=7, sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+    PhyQuery(node="optest_0000", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
 
 - sql: |
     select /*+TDDL: random_node("0,1,3", 3)*/
@@ -16,8 +15,10 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000,0001,0003].test_table_a_[00-13,21-27]", shardCount=21, sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+    PhyViewUnion(concurrent=true)
+      PhyQuery(node="optest_0000", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
+      PhyQuery(node="optest_0001", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
+      PhyQuery(node="optest_0003", sql="select `pk` as `pk` from `test_table_a` as `test_table_a`")
 
 - sql: |
     /*+TDDL: random_node(0)*/
@@ -34,7 +35,8 @@
   plan: |
 
     PhyViewUnion(concurrent=true)
-      PhyQuery(node="[0000,0001]", sql="SHOW TABLES LIKE '%test%'")
+      PhyQuery(node="optest_0000", sql="show tables like '%test%'")
+      PhyQuery(node="optest_0001", sql="show tables like '%test%'")
 
 - sql: |
     /*+TDDL: random_node(0)*/
@@ -42,7 +44,7 @@
 
   plan: |
 
-    PhyQuery(node="optest_0000", sql="SHOW COLUMNS FROM `test_table_a` WHERE (`field` <> '_drds_implicit_id_')")
+    PhyQuery(node="optest_0000", sql="desc `test_table_a`")
 
 ## random_node for single table
 - sql: |
@@ -51,7 +53,7 @@
 
   plan: |
 
-    LogicalView(tables="optest_0000.test_table_single", sql="SELECT `test_table_single`.`pk` FROM `test_table_single` AS `test_table_single`")
+    PhyQuery(node="optest_0000", sql="select `pk` as `pk` from `test_table_single` as `test_table_single`")
 
 - sql: |
     select /*+TDDL: random_node("0,1,3", 3)*/
@@ -59,7 +61,10 @@
 
   plan: |
 
-    PhyTableOperation(tables="optest_0000.[test_table_single]", sql="SELECT `test_table_single`.`pk` FROM `test_table_single` AS `test_table_single`")
+    PhyViewUnion(concurrent=true)
+      PhyQuery(node="optest_0000", sql="select `pk` as `pk` from `test_table_single` as `test_table_single`")
+      PhyQuery(node="optest_0001", sql="select `pk` as `pk` from `test_table_single` as `test_table_single`")
+      PhyQuery(node="optest_0003", sql="select `pk` as `pk` from `test_table_single` as `test_table_single`")
 
 - sql: |
     /*+TDDL: random_node(0)*/
@@ -67,5 +72,5 @@
 
   plan: |
 
-    PhyQuery(node="optest_0000", sql="SHOW COLUMNS FROM `test_table_single` WHERE (`field` <> '_drds_implicit_id_')")
+    PhyQuery(node="optest_0000", sql="desc `test_table_single`")
 
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testScanHint.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testScanHint.yml
index 01c021fc5..2b855b584 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testScanHint.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/CmdHintPlanTest.testScanHint.yml
@@ -9,7 +9,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_table_a_[00-27]", shardCount=28, sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+      LogicalView(tables="[0000-0003].test_table_a_[00-27]", shardCount=28, sql="SELECT `test_table_a`.`pk` as `pk` FROM `test_table_a` AS `test_table_a`")
 
 - sql: |
     /*+TDDL: scan()*/
@@ -27,7 +27,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_table_a_[00-27]", shardCount=28, sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+      LogicalView(tables="[0000-0003].test_table_a_[00-27]", shardCount=28, sql="SELECT `test_table_a`.`pk` as `pk` FROM `test_table_a` AS `test_table_a`")
 
 - sql: |
     select /*+TDDL: scan(node = "1,2")*/
@@ -36,7 +36,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0001,0002].test_table_a_[07-20]", shardCount=14, sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+      LogicalView(tables="[0001,0002].test_table_a_[07-20]", shardCount=14, sql="SELECT `test_table_a`.`pk` as `pk` FROM `test_table_a` AS `test_table_a`")
 
 - sql: |
     select /*+TDDL: scan("test_table_a", "1,2")*/
@@ -45,7 +45,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0001,0002].test_table_a_[07-20]", shardCount=14, sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+      LogicalView(tables="[0001,0002].test_table_a_[07-20]", shardCount=14, sql="SELECT `test_table_a`.`pk` as `pk` FROM `test_table_a` AS `test_table_a`")
 
 - sql: |
     select /*+TDDL: scan("test_table_a", condition="test_table_a.pk = 9")*/
@@ -53,7 +53,7 @@
 
   plan: |
 
-    LogicalView(tables="optest_0001.test_table_a_09", sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+    LogicalView(tables="optest_0001.test_table_a_09", sql="SELECT `test_table_a`.`pk` as `pk` FROM `test_table_a` AS `test_table_a`")
 
 - sql: |
     select /*+TDDL: scan("test_table_a", condition="test_table_a.pk = 9 or pk = 19")*/
@@ -62,7 +62,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0001,0002].test_table_a_[09,19]", shardCount=2, sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+      LogicalView(tables="[0001,0002].test_table_a_[09,19]", shardCount=2, sql="SELECT `test_table_a`.`pk` as `pk` FROM `test_table_a` AS `test_table_a`")
 
 - sql: |
     select /*+TDDL: scan("test_table_a a join test_table_b b on a.pk = b.pk join test_table_c c on b.pk = c.pk", condition="a.pk = 9 or a.pk = 19")*/
@@ -71,7 +71,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0001,0002].test_table_a_[09,19],test_table_b_[09,19],test_table_c", shardCount=2, sql="SELECT `a`.`pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_c`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_c` AS `test_table_c`))))")
+      LogicalView(tables="[0001,0002].test_table_a_[09,19],test_table_b_[09,19],test_table_c", shardCount=2, sql="SELECT `a`.`pk` as `pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_c`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_c` AS `test_table_c`))))")
 
 - sql: |
     select /*+TDDL: scan("test_table_a a , test_table_b b , test_table_c c ", condition="(a.pk = 9 or a.pk = 19) and (b.pk = 9 or b.pk = 19)")*/
@@ -80,7 +80,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0001,0002].test_table_a_[09,19],test_table_b_[09,19],test_table_c", shardCount=2, sql="SELECT `a`.`pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_c`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_c` AS `test_table_c`))))")
+      LogicalView(tables="[0001,0002].test_table_a_[09,19],test_table_b_[09,19],test_table_c", shardCount=2, sql="SELECT `a`.`pk` as `pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_c`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_c` AS `test_table_c`))))")
 
 - sql: |
     select /*+TDDL: scan("test_table_a a , test_table_b b ", condition="(a.pk = 9 or a.pk = 19) and (b.pk = 9 or b.pk = 19)")*/
@@ -89,7 +89,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0001,0002].test_table_a_[09,19],test_table_b_[09,19]", shardCount=2, sql="SELECT `a`.`pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_b`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_b` AS `test_table_b`))))")
+      LogicalView(tables="[0001,0002].test_table_a_[09,19],test_table_b_[09,19]", shardCount=2, sql="SELECT `a`.`pk` as `pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_b`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_b` AS `test_table_b`))))")
 
 - sql: |
     insert /*+TDDL: scan("test_table_a a, test_table_b b, test_table_c c", condition="(a.pk=0 and b.pk=0 and c.pk=0)")*/
@@ -97,7 +97,7 @@
 
   plan: |
 
-    LogicalModifyView(tables="optest_0000.test_table_a_00,test_table_b_00,test_table_c", sql="INSERT INTO `test_table_a` (`pk`, `bigint_test`) (SELECT `test_table_b`.`pk`, `test_table_b`.`bigint_test` FROM `test_table_b` AS `test_table_b` INNER JOIN `test_table_c` AS `test_table_c` ON (`test_table_b`.`pk` = `test_table_c`.`pk`))")
+    LogicalModifyView(tables="optest_0000.test_table_a_00,test_table_b_00,test_table_c", sql="INSERT INTO `test_table_a` (`pk`, `bigint_test`) (SELECT `test_table_b`.`pk` as `pk`, `test_table_b`.`bigint_test` as `bigint_test` FROM `test_table_b` AS `test_table_b` INNER JOIN `test_table_c` AS `test_table_c` ON (`test_table_b`.`pk` = `test_table_c`.`pk`))")
 
 - sql: |
     select /*+TDDL: scan("test_table_a", real_table=("test_table_a_00", "test_table_a_01"))*/
@@ -106,7 +106,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_table_a_[00,01]", shardCount=8, sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+      LogicalView(tables="[0000-0003].test_table_a_[00,01]", shardCount=8, sql="SELECT `test_table_a`.`pk` as `pk` FROM `test_table_a` AS `test_table_a`")
 
 - sql: |
     select /*+TDDL: scan("test_table_a", "0,3", real_table=("test_table_a_00", "test_table_a_01"))*/
@@ -115,7 +115,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0000,0003].test_table_a_[00,01]", shardCount=4, sql="SELECT `test_table_a`.`pk` FROM `test_table_a` AS `test_table_a`")
+      LogicalView(tables="[0000,0003].test_table_a_[00,01]", shardCount=4, sql="SELECT `test_table_a`.`pk` as `pk` FROM `test_table_a` AS `test_table_a`")
 
 - sql: |
     select /*+TDDL: scan("test_table_a, test_table_b, test_table_c", real_table=("test_table_a_00, test_table_b_00, test_table_c", "test_table_a_09, test_table_b_09, test_table_c"))*/
@@ -124,7 +124,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_table_a_[00,09],test_table_b_[00,09],test_table_c", shardCount=8, sql="SELECT `a`.`pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_c`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_c` AS `test_table_c`))))")
+      LogicalView(tables="[0000-0003].test_table_a_[00,09],test_table_b_[00,09],test_table_c", shardCount=8, sql="SELECT `a`.`pk` as `pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_c`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_c` AS `test_table_c`))))")
 
 - sql: |
     select /*+TDDL: scan("test_table_a, test_table_b", real_table=("test_table_a_00, test_table_b_00", "test_table_a_09, test_table_b_09"))*/
@@ -133,7 +133,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_table_a_[00,09],test_table_b_[00,09],test_table_c", shardCount=8, sql="SELECT `a`.`pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_c`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_c` AS `test_table_c`))))")
+      LogicalView(tables="[0000-0003].test_table_a_[00,09],test_table_b_[00,09],test_table_c", shardCount=8, sql="SELECT `a`.`pk` as `pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_c`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_c` AS `test_table_c`))))")
 
 - sql: |
     select /*+TDDL: scan("test_table_a, test_table_b, test_table_b", real_table=("test_table_a_00, test_table_b_00, test_table_b_00", "test_table_a_09, test_table_b_09, test_table_b_09"))*/
@@ -142,7 +142,7 @@
   plan: |
 
     Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_table_a_[00,09],test_table_b_[00,09]", shardCount=8, sql="SELECT `a`.`pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_b`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_b` AS `test_table_b`))))")
+      LogicalView(tables="[0000-0003].test_table_a_[00,09],test_table_b_[00,09]", shardCount=8, sql="SELECT `a`.`pk` as `pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE (`a`.`bigint_test` > (((SELECT MAX(`test_table_b`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_b` AS `test_table_b`))))")
 
 - sql: |
     insert /*+TDDL: scan("test_table_a, test_table_b, test_table_c", real_table=("test_table_a_01, test_table_b_00, test_table_c"))*/
@@ -151,4 +151,26 @@
   plan: |
 
     AffectedRowsSum(Concurrent:=true)
-      LogicalModifyView(tables="[0000-0003].test_table_a_01,test_table_b_00,test_table_c", shardCount=4, sql="INSERT INTO `test_table_a` (`pk`, `bigint_test`) (SELECT `test_table_b`.`pk`, `test_table_b`.`bigint_test` FROM `test_table_b` AS `test_table_b` INNER JOIN `test_table_c` AS `test_table_c` ON (`test_table_b`.`pk` = `test_table_c`.`pk`))")
+      LogicalModifyView(tables="[0000-0003].test_table_a_01,test_table_b_00,test_table_c", shardCount=4, sql="INSERT INTO `test_table_a` (`pk`, `bigint_test`) (SELECT `test_table_b`.`pk` as `pk`, `test_table_b`.`bigint_test` as `bigint_test` FROM `test_table_b` AS `test_table_b` INNER JOIN `test_table_c` AS `test_table_c` ON (`test_table_b`.`pk` = `test_table_c`.`pk`))")
+
+- sql: |
+    /*+TDDL: scan("test_table_a", real_table=("test_table_a_00"))*/ select a.bigint_test from test_table_a a where a.pk in (1, 2, 3);
+
+  plan: |
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_table_a_00", shardcount=4, sql="select `a`.`bigint_test` as `bigint_test` from `test_table_a` as `a` where (`a`.`pk` in (?))")
+
+- sql: |
+    select /*+TDDL: scan("test_table_a, test_table_b, test_table_b", real_table=("test_table_a_00, test_table_b_00, test_table_b_00", "test_table_a_09, test_table_b_09, test_table_b_09"))*/
+    a.pk from test_table_a a join test_table_b b on a.pk = b.pk where a.bigint_test > (select max(bigint_test) from test_table_b) and a.pk in (1, 2, 3, 4);
+
+  plan: |
+    Gather(concurrent=true)
+      LogicalView(tables="[0000-0003].test_table_a_[00,09],test_table_b_[00,09]", shardCount=8, sql="SELECT `a`.`pk` as `pk` FROM `test_table_a` AS `a` INNER JOIN `test_table_b` AS `b` ON (`a`.`pk` = `b`.`pk`) WHERE ((`a`.`bigint_test` > (((SELECT MAX(`test_table_b`.`bigint_test`) AS `max(bigint_test)` FROM `test_table_b` AS `test_table_b`)))) and (`a`.`pk` in (?)))")
+
+- sql: |
+    /*+TDDL: scan("test_table_a", real_table=("test_table_a_00"))*/ select a.bigint_test from test_table_a a where a.pk in (1, 2, 3);
+
+  plan: |
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_table_a_00", shardcount=4, sql="select `a`.`bigint_test` as `bigint_test` from `test_table_a` as `a` where (`a`.`pk` in (?))")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/PartitionCmdHintPlanTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/PartitionCmdHintPlanTest.ddl.yml
new file mode 100644
index 000000000..07b57f531
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/PartitionCmdHintPlanTest.ddl.yml
@@ -0,0 +1,10 @@
+test_table_a:
+  CREATE TABLE `test_table_a` (
+  `pk`                BIGINT(11)   NOT NULL,
+  `bigint_test`       BIGINT       DEFAULT NULL,
+  `varchar_test_p255` VARCHAR(255) DEFAULT NULL,
+  `datetime_test`     DATETIME     DEFAULT NULL,
+  `text_test`         TEXT         DEFAULT NULL,
+  `timestamp_test`    TIMESTAMP    NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`pk`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=UTF8 partition by hash(pk) partitions 7
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/PartitionCmdHintPlanTest.testScanHint.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/PartitionCmdHintPlanTest.testScanHint.yml
new file mode 100644
index 000000000..405dc6969
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/cmd/PartitionCmdHintPlanTest.testScanHint.yml
@@ -0,0 +1,6 @@
+- sql: |
+    /*+TDDL: scan("test_table_a", real_table=("test_table_a_00000"))*/ select a.bigint_test from test_table_a a where a.pk in (1, 2, 3);
+
+  plan: |
+    gather(concurrent=true)
+      logicalview(tables="test_table_a[p1]", sql="select `a`.`bigint_test` as `bigint_test` from `test_table_a` as `a` where (`a`.`pk` in (?))")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/push/PushAggHintPlanTest.testPushAggFunction.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/push/PushAggHintPlanTest.testPushAggFunction.yml
index 0d2d3d6e0..74feb0d69 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/push/PushAggHintPlanTest.testPushAggFunction.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/hintplan/push/PushAggHintPlanTest.testPushAggFunction.yml
@@ -130,3 +130,16 @@
 
     Gather(concurrent=true)
       LogicalView(tables="[0000-0003].test_table_a_[00-27]", shardCount=28, sql="SELECT `pk`, `bigint_test`, `varchar_test_p255`, `datetime_test`, `text_test`, `timestamp_test`, `pk`, COUNT(`bigint_test`) AS `count(bigint_test)`, SUM(`bigint_test`) AS `sum(bigint_test)`, MAX(`bigint_test`) AS `max(bigint_test)` FROM `test_table_a` AS `test_table_a` GROUP BY `pk`")
+
+- sql: |
+    select /* +TDDL: construct()
+    push_agg(
+      agg      = 'pk, json_objectagg(varchar_test_p255, bigint_test), json_arrayagg(datetime_test)',
+      group_by = pk)
+    add_un()*/ * from test_table_a;
+
+  plan: |
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_table_a_[00-27]", shardcount=28, sql="select `pk`, `bigint_test`, `varchar_test_p255`, `datetime_test`, `text_test`, `timestamp_test`, `pk`, (json_objectagg(`varchar_test_p255`, `bigint_test`)) as `json_objectagg(varchar_test_p255, bigint_test)`, (json_arrayagg(`datetime_test`)) as `json_arrayagg(datetime_test)` from `test_table_a` as `test_table_a` group by `pk`")
+ 
+ 
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/ApTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/ApTest.yml
index 3ee5f6653..8c74fa036 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/ApTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/ApTest.yml
@@ -1,33 +1,3 @@
-#-
-#  sql: |
-#    select
-#      l_returnflag,
-#      l_linestatus,
-#      sum(l_quantity) as sum_qty,
-#      sum(l_extendedprice) as sum_base_price,
-#      sum(l_extendedprice*(1-l_discount)) as sum_disc_price,
-#      sum(l_extendedprice*(1-l_discount)*(1+l_tax)) as sum_charge,
-#      avg(l_quantity) as avg_qty,
-#      avg(l_extendedprice) as avg_price,
-#      avg(l_discount) as avg_disc,
-#      count(*) as count_order
-#    from
-#      lineitem
-#    where
-#      l_shipdate <= date_add(cast('1998-12-01' as date ), Interval -90 day )
-#    group by
-#      l_returnflag,
-#      l_linestatus
-#    order by
-#      l_returnflag,
-#      l_linestatus;
-#
-#  plan: |
-#    MemSort(sort="l_returnflag ASC,l_linestatus ASC")
-#      Project(l_returnflag="l_returnflag", l_linestatus="l_linestatus", sum_qty="sum_qty", sum_base_price="sum_base_price", sum_disc_price="sum_disc_price", sum_charge="sum_charge", avg_qty="sum_pushed_sum / sum_pushed_count", avg_price="sum_pushed_sum_0 / sum_pushed_count_0", avg_disc="sum_pushed_sum_1 / sum_pushed_count_1", count_order="count_order")
-#        HashAgg(group="l_returnflag,l_linestatus", sum_qty="SUM(sum_qty)", sum_base_price="SUM(sum_base_price)", sum_disc_price="SUM(sum_disc_price)", sum_charge="SUM(sum_charge)", sum_pushed_sum="SUM(pushed_sum)", sum_pushed_sum_0="SUM(pushed_sum_0)", sum_pushed_sum_1="SUM(pushed_sum_1)", count_order="SUM(count_order)", sum_pushed_count="SUM(pushed_count)", sum_pushed_count_0="SUM(pushed_count_0)", sum_pushed_count_1="SUM(pushed_count_1)")
-#          Gather(concurrent=true)
-#            LogicalView(tables="[0000-0003].lineitem_[00-15]", shardCount=16, sql="SELECT `l_returnflag`, `l_linestatus`, SUM(`l_quantity`) AS `sum_qty`, SUM(`l_extendedprice`) AS `sum_base_price`, SUM((`l_extendedprice` * (1 - `l_discount`))) AS `sum_disc_price`, SUM(((`l_extendedprice` * (1 - `l_discount`)) * (1 + `l_tax`))) AS `sum_charge`, SUM(`l_quantity`) AS `pushed_sum`, SUM(`l_extendedprice`) AS `pushed_sum_0`, SUM(`l_discount`) AS `pushed_sum_1`, COUNT(*) AS `count_order`, COUNT(`l_quantity`) AS `pushed_count`, COUNT(`l_extendedprice`) AS `pushed_count_0`, COUNT(`l_discount`) AS `pushed_count_1` FROM `lineitem` AS `lineitem` WHERE (`l_shipdate` <= DATE_ADD(CAST('1998-12-01' AS DATE), INTERVAL -90 DAY)) GROUP BY `l_returnflag`, `l_linestatus`")
 
 - sql: |
     select
@@ -75,6 +45,7 @@
       p_partkey;
 
   plan: |
+
     memsort(sort="s_acctbal desc,n_name asc,s_name asc,p_partkey asc")
       project(s_acctbal="s_acctbal", s_name="s_name", n_name="n_name", p_partkey="p_partkey", p_mfgr="p_mfgr", s_address="s_address", s_phone="s_phone", s_comment="s_comment")
         hashjoin(condition="ps_suppkey = s_suppkey", type="inner")
@@ -116,6 +87,7 @@
       o_orderdate;
 
   plan: |
+
     project(l_orderkey="l_orderkey", revenue="revenue", o_orderdate="o_orderdate", o_shippriority="o_shippriority")
       memsort(sort="revenue desc,o_orderdate asc")
         project(l_orderkey="l_orderkey", o_orderdate="o_orderdate", o_shippriority="o_shippriority", revenue="revenue")
@@ -140,10 +112,12 @@
     ) group by o_orderpriority order by o_orderpriority;
 
   plan: |
+
     memsort(sort="o_orderpriority asc")
-      hashagg(group="o_orderpriority", order_count="count()")
+      hashagg(group="o_orderpriority", order_count="sum(order_count)")
         gather(concurrent=true)
-          logicalview(tables="[0000-0003].orders_[00-15],lineitem_[00-15]", shardcount=16, sql="select `o_orderpriority` from `orders` as `orders` where ((`o_orderdate` < date_add(cast('1993-07-01' as date), interval 3 month)) and (`o_orderdate` >= '1993-07-01') and (exists (select `l_orderkey` from `lineitem` as `lineitem` where ((`l_orderkey` = `orders`.`o_orderkey`) and (`l_commitdate` < `l_receiptdate`)))))")
+          logicalview(tables="[0000-0003].orders_[00-15],lineitem_[00-15]", shardcount=16, sql="select `o_orderpriority`, count(*) as `order_count` from `orders` as `orders` where ((`o_orderdate` < date_add(cast('1993-07-01' as date), interval 3 month)) and (`o_orderdate` >= '1993-07-01') and (exists (select `l_orderkey` from `lineitem` as `lineitem` where ((`l_orderkey` = `orders`.`o_orderkey`) and (`l_commitdate` < `l_receiptdate`))))) group by `o_orderpriority`")
+
 - sql: |
     select
     n_name,
@@ -158,6 +132,7 @@
     revenue desc;
 
   plan: |
+
     memsort(sort="revenue desc")
       hashagg(group="n_name", revenue="sum(__*__)")
         project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", c_custkey="c_custkey", c_nationkey="c_nationkey", n_nationkey="n_nationkey", n_name="n_name", o_custkey="o_custkey", l_suppkey="l_suppkey", __*__="__*__")
@@ -182,6 +157,7 @@
     and l_discount between 0.06 - 0.01 and 0.06 + 0.01 and l_quantity < 24;
 
   plan: |
+
     hashagg(revenue="sum(revenue)")
       gather(concurrent=true)
         logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select sum((`l_extendedprice` * `l_discount`)) as `revenue` from `lineitem` as `lineitem` where ((`l_discount` between (0.06 - 0.01) and (0.06 + 0.01)) and (`l_shipdate` < date_add(cast('1994-01-01' as date), interval 1 year)) and (`l_quantity` < 24) and (`l_shipdate` >= '1994-01-01'))")
@@ -230,18 +206,19 @@
       l_year;
 
   plan: |
-    MemSort(sort="n_name ASC,n_name0 ASC,EXTRACT ASC")
-      HashAgg(group="n_name,n_name0,EXTRACT", revenue="SUM(__*__)")
-        Project(s_suppkey="s_suppkey", n_name="n_name", n_nationkey0="n_nationkey0", n_name0="n_name0", c_custkey="c_custkey", c_nationkey="c_nationkey", l_suppkey="l_suppkey", o_custkey="o_custkey", EXTRACT="EXTRACT", __*__="__*__")
-          HashJoin(condition="o_custkey = c_custkey AND n_nationkey0 = c_nationkey", type="inner")
-            Gather(concurrent=true)
-              LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey`, `c_nationkey` FROM `customer` AS `customer`")
-            Project(s_suppkey="s_suppkey", n_name="n_name", n_nationkey0="n_nationkey0", n_name0="n_name0", l_suppkey="l_suppkey", o_custkey="o_custkey", EXTRACT="EXTRACT", __*__="__*__")
-              HashJoin(condition="l_suppkey = s_suppkey", type="inner")
-                Gather(concurrent=true)
-                  LogicalView(tables="[0000-0003].lineitem_[00-15],orders_[00-15]", shardCount=16, sql="SELECT `lineitem`.`l_suppkey`, `orders`.`o_custkey`, EXTRACT(YEAR FROM `lineitem`.`l_shipdate`) AS `EXTRACT`, (`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`)) AS `__*__` FROM `lineitem` AS `lineitem` INNER JOIN `orders` AS `orders` ON ((`lineitem`.`l_orderkey` = `orders`.`o_orderkey`) AND (`lineitem`.`l_shipdate` BETWEEN '1995-01-01' AND '1996-12-31'))")
-                Gather(concurrent=true)
-                  LogicalView(tables="[0000-0003].supplier_[00-15],nation", shardCount=16, sql="SELECT `supplier`.`s_suppkey`, `nation`.`n_name`, `nation0`.`n_nationkey` AS `n_nationkey0`, `nation0`.`n_name` AS `n_name0` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON (`supplier`.`s_nationkey` = `nation`.`n_nationkey`) INNER JOIN `nation` AS `nation0` ON (((`nation`.`n_name` = 'FRANCE') AND (`nation0`.`n_name` = 'GERMANY')) OR ((`nation`.`n_name` = 'GERMANY') AND (`nation0`.`n_name` = 'FRANCE')))")
+
+    memsort(sort="n_name asc,n_name0 asc,extract asc")
+      hashagg(group="n_name,n_name0,extract", revenue="sum(__*__)")
+        project(s_suppkey="s_suppkey", n_name="n_name", n_nationkey0="n_nationkey0", n_name0="n_name0", c_custkey="c_custkey", c_nationkey="c_nationkey", l_suppkey="l_suppkey", o_custkey="o_custkey", extract="extract", __*__="__*__")
+          hashjoin(condition="o_custkey = c_custkey and n_nationkey0 = c_nationkey", type="inner")
+            gather(concurrent=true)
+              logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey`, `c_nationkey` from `customer` as `customer`")
+            project(s_suppkey="s_suppkey", n_name="n_name", n_nationkey0="n_nationkey0", n_name0="n_name0", l_suppkey="l_suppkey", o_custkey="o_custkey", extract="extract", __*__="__*__")
+              hashjoin(condition="l_suppkey = s_suppkey", type="inner")
+                gather(concurrent=true)
+                  logicalview(tables="[0000-0003].lineitem_[00-15],orders_[00-15]", shardcount=16, sql="select `lineitem`.`l_suppkey`, `orders`.`o_custkey`, extract(year from `lineitem`.`l_shipdate`) as `extract`, (`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`)) as `__*__` from `lineitem` as `lineitem` inner join `orders` as `orders` on ((`lineitem`.`l_orderkey` = `orders`.`o_orderkey`) and (`lineitem`.`l_shipdate` between '1995-01-01' and '1996-12-31'))")
+                gather(concurrent=true)
+                  logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey`, `nation`.`n_name`, `nation0`.`n_nationkey` as `n_nationkey0`, `nation0`.`n_name` as `n_name0` from `supplier` as `supplier` inner join `nation` as `nation` on (`supplier`.`s_nationkey` = `nation`.`n_nationkey`) inner join `nation` as `nation0` on (((`nation`.`n_name` = 'france') and (`nation0`.`n_name` = 'germany')) or ((`nation`.`n_name` = 'germany') and (`nation0`.`n_name` = 'france')))")
 
 - sql: |
     select
@@ -270,22 +247,23 @@
     o_year;
 
   plan: |
-    MemSort(sort="o_year ASC")
-      Project(o_year="EXTRACT", mkt_share="$f1 / $f2")
-        HashAgg(group="EXTRACT", $f1="SUM(CASE)", $f2="SUM(__*__)")
-          Project(o_custkey="o_custkey", EXTRACT="EXTRACT", CASE="CASE($8, $6, CAST(0):DECIMAL(37, 4) NOT NULL)", __*__="__*__", c_custkey="c_custkey")
-            HashJoin(condition="o_custkey = c_custkey", type="inner")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].customer_[00-15],nation,region", shardCount=16, sql="SELECT `customer`.`c_custkey` FROM `customer` AS `customer` INNER JOIN `nation` AS `nation` ON (`customer`.`c_nationkey` = `nation`.`n_nationkey`) INNER JOIN `region` AS `region` ON ((`nation`.`n_regionkey` = `region`.`r_regionkey`) AND (`region`.`r_name` = 'AMERICA'))")
-              HashJoin(condition="s_suppkey = l_suppkey", type="inner")
-                Project(p_partkey="p_partkey", l_partkey="l_partkey", l_suppkey="l_suppkey", o_custkey="o_custkey", EXTRACT="EXTRACT", __*__="__*__")
-                  HashJoin(condition="p_partkey = l_partkey", type="inner")
-                    Gather(concurrent=true)
-                      LogicalView(tables="[0000-0003].lineitem_[00-15],orders_[00-15]", shardCount=16, sql="SELECT `lineitem`.`l_partkey`, `lineitem`.`l_suppkey`, `orders`.`o_custkey`, EXTRACT(YEAR FROM `orders`.`o_orderdate`) AS `EXTRACT`, (`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`)) AS `__*__` FROM `lineitem` AS `lineitem` INNER JOIN `orders` AS `orders` ON ((`lineitem`.`l_orderkey` = `orders`.`o_orderkey`) AND (`orders`.`o_orderdate` BETWEEN '1995-01-01' AND '1996-12-31'))")
-                    Gather(concurrent=true)
-                      LogicalView(tables="[0000-0003].part_[00-15]", shardCount=16, sql="SELECT `p_partkey` FROM `part` AS `part` WHERE (`p_type` = 'ECONOMY ANODIZED STEEL')")
-                Gather(concurrent=true)
-                  LogicalView(tables="[0000-0003].supplier_[00-15],nation", shardCount=16, sql="SELECT `supplier`.`s_suppkey`, (`nation`.`n_name` = 'BRAZIL') AS `=` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON (`supplier`.`s_nationkey` = `nation`.`n_nationkey`)")
+
+    memsort(sort="o_year asc")
+      project(o_year="extract", mkt_share="$f1 / $f2")
+        hashagg(group="extract", $f1="sum(case)", $f2="sum(__*__)")
+          project(o_custkey="o_custkey", extract="extract", case="case($8, $6, cast(0):decimal(37, 4) not null)", __*__="__*__", c_custkey="c_custkey")
+            hashjoin(condition="o_custkey = c_custkey", type="inner")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].customer_[00-15],nation,region", shardcount=16, sql="select `customer`.`c_custkey` from `customer` as `customer` inner join `nation` as `nation` on (`customer`.`c_nationkey` = `nation`.`n_nationkey`) inner join `region` as `region` on ((`nation`.`n_regionkey` = `region`.`r_regionkey`) and (`region`.`r_name` = 'america'))")
+              hashjoin(condition="s_suppkey = l_suppkey", type="inner")
+                project(p_partkey="p_partkey", l_partkey="l_partkey", l_suppkey="l_suppkey", o_custkey="o_custkey", extract="extract", __*__="__*__")
+                  hashjoin(condition="p_partkey = l_partkey", type="inner")
+                    gather(concurrent=true)
+                      logicalview(tables="[0000-0003].lineitem_[00-15],orders_[00-15]", shardcount=16, sql="select `lineitem`.`l_partkey`, `lineitem`.`l_suppkey`, `orders`.`o_custkey`, extract(year from `orders`.`o_orderdate`) as `extract`, (`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`)) as `__*__` from `lineitem` as `lineitem` inner join `orders` as `orders` on ((`lineitem`.`l_orderkey` = `orders`.`o_orderkey`) and (`orders`.`o_orderdate` between '1995-01-01' and '1996-12-31'))")
+                    gather(concurrent=true)
+                      logicalview(tables="[0000-0003].part_[00-15]", shardcount=16, sql="select `p_partkey` from `part` as `part` where (`p_type` = 'economy anodized steel')")
+                gather(concurrent=true)
+                  logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey`, (`nation`.`n_name` = 'brazil') as `=` from `supplier` as `supplier` inner join `nation` as `nation` on (`supplier`.`s_nationkey` = `nation`.`n_nationkey`)")
 
 - sql: |
     select
@@ -321,6 +299,7 @@
       o_year desc;
 
   plan: |
+
     sortagg(group="nation,o_year", sum_profit="sum(amount)")
       memsort(sort="nation asc,o_year desc")
         project(nation="n_name", o_year="extract", amount="__*__ - ps_supplycost * l_quantity")
@@ -369,6 +348,7 @@
       o_year desc;
 
   plan: |
+
     sortagg(group="nation,o_year", sum_profit="sum(amount)")
       project(nation="n_name", o_year="extract", amount="__*__ - ps_supplycost * l_quantity")
         hashjoin(condition="ps_partkey = l_partkey and p_partkey = l_partkey and ps_suppkey = l_suppkey and ps_suppkey = s_suppkey", type="inner")
@@ -406,16 +386,16 @@
     revenue desc;
 
   plan: |
+
     project(c_custkey="c_custkey", c_name="c_name", revenue="$f10", c_acctbal="c_acctbal", n_name="n_name", c_address="c_address", c_phone="c_phone", c_comment="c_comment")
       memsort(sort="$f10 desc")
         project(c_custkey="c_custkey", n_name="n_name", c_name="c_name", c_acctbal="c_acctbal", c_phone="c_phone", c_address="c_address", c_comment="c_comment", $f10="$f7 * revenue")
           hashjoin(condition="o_custkey = c_custkey", type="inner")
-            hashagg(group="c_custkey,n_name", c_name="__first_value(c_name)", c_acctbal="__first_value(c_acctbal)", c_phone="__first_value(c_phone)", c_address="__first_value(c_address)", c_comment="__first_value(c_comment)", $f7="count()")
-              gather(concurrent=true)
-                logicalview(tables="[0000-0003].customer_[00-15],nation", shardcount=16, sql="select `customer`.`c_custkey`, `customer`.`c_name`, `customer`.`c_address`, `customer`.`c_phone`, `customer`.`c_acctbal`, `customer`.`c_comment`, `nation`.`n_name` from `customer` as `customer` inner join `nation` as `nation` on (`customer`.`c_nationkey` = `nation`.`n_nationkey`)")
-            hashagg(group="o_custkey", revenue="sum(__*__)")
+            gather(concurrent=true)
+              logicalview(tables="[0000-0003].customer_[00-15],nation", shardcount=16, sql="select `customer`.`c_custkey`, `nation`.`n_name`, (`customer`.`c_name`) as `c_name`, (`customer`.`c_acctbal`) as `c_acctbal`, (`customer`.`c_phone`) as `c_phone`, (`customer`.`c_address`) as `c_address`, (`customer`.`c_comment`) as `c_comment`, count(*) as `$f7` from `customer` as `customer` inner join `nation` as `nation` on (`customer`.`c_nationkey` = `nation`.`n_nationkey`) group by `customer`.`c_custkey`, `nation`.`n_name`")
+            hashagg(group="o_custkey", revenue="sum(revenue)")
               gather(concurrent=true)
-                logicalview(tables="[0000-0003].orders_[00-15],lineitem_[00-15]", shardcount=16, sql="select `orders`.`o_custkey`, (`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`)) as `__*__` from `orders` as `orders` inner join `lineitem` as `lineitem` on ((`orders`.`o_orderkey` = `lineitem`.`l_orderkey`) and (`lineitem`.`l_returnflag` = 'r') and (`orders`.`o_orderdate` >= '1993-10-01') and (`orders`.`o_orderdate` < date_add(cast('1993-10-01' as date), interval 3 month)))")
+                logicalview(tables="[0000-0003].orders_[00-15],lineitem_[00-15]", shardcount=16, sql="select `orders`.`o_custkey`, sum((`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`))) as `revenue` from `orders` as `orders` inner join `lineitem` as `lineitem` on ((`orders`.`o_orderkey` = `lineitem`.`l_orderkey`) and (`lineitem`.`l_returnflag` = 'r') and (`orders`.`o_orderdate` >= '1993-10-01') and (`orders`.`o_orderdate` < date_add(cast('1993-10-01' as date), interval 3 month))) group by `orders`.`o_custkey`")
 
 - sql: |
     select * from (select
@@ -448,21 +428,22 @@
       value desc;
 
   plan: |
-    MemSort(sort="value DESC")
-      Project(ps_partkey="ps_partkey", value="value")
-        NlJoin(condition="value > $f0 * 0.0001", type="inner")
-          HashAgg(group="ps_partkey", value="SUM(__*__)")
-            BKAJoin(condition="ps_suppkey = s_suppkey", type="inner")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].supplier_[00-15],nation", shardCount=16, sql="SELECT `supplier`.`s_suppkey` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) AND (`nation`.`n_name` = 'GERMANY'))")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].partsupp_[00-15]", shardCount=16, sql="SELECT `ps_partkey`, `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) AS `__*__` FROM `partsupp` AS `partsupp` WHERE (`ps_suppkey` IN (...))")
-          HashAgg($f0="SUM(__*__)")
-            BKAJoin(condition="ps_suppkey = s_suppkey", type="inner")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].supplier_[00-15],nation", shardCount=16, sql="SELECT `supplier`.`s_suppkey` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) AND (`nation`.`n_name` = 'GERMANY'))")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].partsupp_[00-15]", shardCount=16, sql="SELECT `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) AS `__*__` FROM `partsupp` AS `partsupp` WHERE (`ps_suppkey` IN (...))")
+
+    memsort(sort="value desc")
+      project(ps_partkey="ps_partkey", value="value")
+        nljoin(condition="value > $f0 * 0.0001", type="inner")
+          hashagg(group="ps_partkey", value="sum(__*__)")
+            bkajoin(condition="ps_suppkey = s_suppkey", type="inner")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany'))")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].partsupp_[00-15]", shardcount=16, sql="select `ps_partkey`, `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) as `__*__` from `partsupp` as `partsupp` force index(`idx_partsupp_suppkey`) where (`ps_suppkey` in (...))")
+          hashagg($f0="sum(__*__)")
+            bkajoin(condition="ps_suppkey = s_suppkey", type="inner")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany'))")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].partsupp_[00-15]", shardcount=16, sql="select `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) as `__*__` from `partsupp` as `partsupp` force index(`idx_partsupp_suppkey`) where (`ps_suppkey` in (...))")
 
 - sql: |
     select
@@ -488,6 +469,7 @@
     group by l_shipmode
     order by l_shipmode;
   plan: |
+
     sortagg(group="l_shipmode", high_line_count="sum(high_line_count)", low_line_count="sum(low_line_count)")
       mergesort(sort="l_shipmode asc")
         logicalview(tables="[0000-0003].orders_[00-15],lineitem_[00-15]", shardcount=16, sql="select `lineitem`.`l_shipmode`, sum((case when ((`orders`.`o_orderpriority` = '1-urgent') or (`orders`.`o_orderpriority` = '2-high')) then 1 else 0 end)) as `high_line_count`, sum((case when ((`orders`.`o_orderpriority` <> '1-urgent') and (`orders`.`o_orderpriority` <> '2-high')) then 1 else 0 end)) as `low_line_count` from `orders` as `orders` inner join `lineitem` as `lineitem` on ((`orders`.`o_orderkey` = `lineitem`.`l_orderkey`) and (`lineitem`.`l_shipmode` in('mail', 'ship')) and (`lineitem`.`l_commitdate` < `lineitem`.`l_receiptdate`) and (`lineitem`.`l_shipdate` < `lineitem`.`l_commitdate`) and (`lineitem`.`l_receiptdate` >= '1994-01-01') and (`lineitem`.`l_receiptdate` < date_add(cast('1994-01-01' as date), interval 1 year))) group by `lineitem`.`l_shipmode` order by `lineitem`.`l_shipmode`")
@@ -509,13 +491,14 @@
     custdist desc, c_count desc;
 
   plan: |
-    MemSort(sort="custdist DESC,c_count DESC")
-      HashAgg(group="c_count", custdist="COUNT()")
-        HashGroupJoin(condition="c_custkey = o_custkey", type="left")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey` FROM `customer` AS `customer`")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_orderkey`, `o_custkey` FROM `orders` AS `orders` WHERE (`o_comment` NOT LIKE '%special%requests%')")
+
+    memsort(sort="custdist desc,c_count desc")
+      hashagg(group="c_count", custdist="count()")
+        hashgroupjoin(condition="c_custkey = o_custkey", type="left")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey` from `customer` as `customer`")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_custkey` from `orders` as `orders` where (`o_comment` not like '%special%requests%')")
 
 - sql: |
     select
@@ -533,14 +516,15 @@
       and l_shipdate < date_add(cast('1995-09-01' as date ), Interval 1 year );
 
   plan: |
-    Project(promo_revenue="100.00 * $f0 / $f1")
-      HashAgg($f0="SUM($f0)", $f1="SUM($f1)")
-        Project($f0="CASE($3, $1, CAST(0):DECIMAL(37, 4) NOT NULL)", $f1="__*__")
-          HashJoin(condition="l_partkey = p_partkey", type="inner")
-            Gather(concurrent=true)
-              LogicalView(tables="[0000-0003].lineitem_[00-15]", shardCount=16, sql="SELECT `l_partkey`, (`l_extendedprice` * (1 - `l_discount`)) AS `__*__` FROM `lineitem` AS `lineitem` WHERE ((`l_shipdate` >= '1995-09-01') AND (`l_shipdate` < DATE_ADD(CAST('1995-09-01' AS DATE), INTERVAL 1 YEAR)))")
-            Gather(concurrent=true)
-              LogicalView(tables="[0000-0003].part_[00-15]", shardCount=16, sql="SELECT `p_partkey`, (`p_type` LIKE 'PROMO%') AS `LIKE` FROM `part` AS `part`")
+
+    project(promo_revenue="100.00 * $f0 / $f1")
+      hashagg($f0="sum($f0)", $f1="sum($f1)")
+        project($f0="case($3, $1, cast(0):decimal(37, 4) not null)", $f1="__*__")
+          hashjoin(condition="l_partkey = p_partkey", type="inner")
+            gather(concurrent=true)
+              logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, (`l_extendedprice` * (1 - `l_discount`)) as `__*__` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1995-09-01') and (`l_shipdate` < date_add(cast('1995-09-01' as date), interval 1 year)))")
+            gather(concurrent=true)
+              logicalview(tables="[0000-0003].part_[00-15]", shardcount=16, sql="select `p_partkey`, (`p_type` like 'promo%') as `like` from `part` as `part`")
 
 - sql: |
     select
@@ -580,19 +564,20 @@
     s_suppkey;
 
   plan: |
+
     project(s_suppkey="s_suppkey", s_name="s_name", s_address="s_address", s_phone="s_phone", total_revenue="total_revenue")
       hashjoin(condition="supplier_no = s_suppkey", type="inner")
         mergesort(sort="s_suppkey asc")
-          logicalview(tables="[0000-0003].supplier_[00-15]", shardcount=16, sql="select `s_suppkey`, `s_name`, `s_address`, `s_phone` from `supplier` as `supplier` order by `s_suppkey`")
+          logicalview(tables="[0000-0003].supplier_[00-15]", shardcount=16, sql="select `s_suppkey`, `s_name`, `s_address`, `s_phone` from `supplier` as `supplier` force index(`primary`) order by `s_suppkey`")
         project(max(total_revenue)="max(total_revenue)", supplier_no="supplier_no", total_revenue="total_revenue")
           hashjoin(condition="max(total_revenue) = total_revenue", type="inner")
-            hashagg(group="supplier_no", total_revenue="sum($f1)")
+            hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
               gather(concurrent=true)
-                logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_suppkey` as `supplier_no`, (`l_extendedprice` * (1 - `l_discount`)) as `$f1` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add(cast('1996-01-01' as date), interval 3 month)))")
+                logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_suppkey` as `supplier_no`, sum((`l_extendedprice` * (1 - `l_discount`))) as `total_revenue` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add(cast('1996-01-01' as date), interval 3 month))) group by `l_suppkey`")
             hashagg(max(total_revenue)="max(total_revenue)")
-              hashagg(group="supplier_no", total_revenue="sum($f1)")
+              hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
                 gather(concurrent=true)
-                  logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_suppkey` as `supplier_no`, (`l_extendedprice` * (1 - `l_discount`)) as `$f1` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add(cast('1996-01-01' as date), interval 3 month)))")
+                  logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_suppkey` as `supplier_no`, sum((`l_extendedprice` * (1 - `l_discount`))) as `total_revenue` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add(cast('1996-01-01' as date), interval 3 month))) group by `l_suppkey`")
 
 - sql: |
     select
@@ -627,6 +612,7 @@
       p_size;
 
   plan: |
+
     memsort(sort="supplier_cnt desc,p_brand asc,p_type asc,p_size asc")
       hashagg(group="p_brand,p_type,p_size", supplier_cnt="count(ps_suppkey)")
         hashagg(group="p_brand,p_type,p_size,ps_suppkey")
@@ -657,6 +643,7 @@
       );
 
   plan: |
+
     project(avg_yearly="$f0 / 7.0")
       hashagg($f0="sum(l_extendedprice)")
         filter(condition="l_quantity < 0.2 * f16w0$o0")
@@ -665,7 +652,7 @@
               gather(concurrent=true)
                 logicalview(tables="[0000-0003].part_[00-15]", shardcount=16, sql="select `p_partkey` from `part` as `part` where ((`p_container` = 'med box') and (`p_brand` = 'brand#23'))")
               gather(concurrent=true)
-                logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem` where (`l_partkey` in (...))")
+                logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem` force index(`i_l_partkey`) where (`l_partkey` in (...))")
 
 - sql: |
     select
@@ -688,15 +675,15 @@
     o_orderdate;
 
   plan: |
+
     project(c_name="c_name", c_custkey="c_custkey", o_orderkey="o_orderkey", o_orderdate="o_orderdate", o_totalprice="o_totalprice", sum(l_quantity)="sum(l_quantity)")
       memsort(sort="o_totalprice desc,o_orderdate asc")
         project(c_custkey="c_custkey", o_orderkey="o_orderkey", o_orderdate="o_orderdate", o_totalprice="o_totalprice", c_name="c_name", sum(l_quantity)="sum(l_quantity)")
           hashjoin(condition="o_custkey = c_custkey", type="inner")
             gather(concurrent=true)
               logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey`, `c_name` from `customer` as `customer`")
-            hashagg(group="o_orderkey,o_custkey", o_orderdate="__first_value(o_orderdate)", o_totalprice="__first_value(o_totalprice)", sum(l_quantity)="sum(l_quantity)")
-              gather(concurrent=true)
-                logicalview(tables="[0000-0003].orders_[00-15],lineitem_[00-15]", shardcount=16, sql="select `orders`.`o_orderkey`, `orders`.`o_custkey`, `orders`.`o_totalprice`, `orders`.`o_orderdate`, `lineitem`.`l_quantity` from `orders` as `orders` inner join `lineitem` as `lineitem` on (`orders`.`o_orderkey` = `lineitem`.`l_orderkey`) where (`orders`.`o_orderkey` in (select `l_orderkey` from (select `l_orderkey`, sum(`l_quantity`) as `$f1` from `lineitem` as `lineitem0` group by `l_orderkey` having (sum(`l_quantity`) > 300)) as `t0`))")
+            gather(concurrent=true)
+              logicalview(tables="[0000-0003].orders_[00-15],lineitem_[00-15]", shardcount=16, sql="select `orders`.`o_orderkey`, `orders`.`o_custkey`, (`orders`.`o_orderdate`) as `o_orderdate`, (`orders`.`o_totalprice`) as `o_totalprice`, sum(`lineitem`.`l_quantity`) as `sum(l_quantity)` from `orders` as `orders` inner join `lineitem` as `lineitem` on (`orders`.`o_orderkey` = `lineitem`.`l_orderkey`) where (`orders`.`o_orderkey` in (select `l_orderkey` from (select `l_orderkey`, sum(`l_quantity`) as `$f1` from `lineitem` as `lineitem0` group by `l_orderkey` having (sum(`l_quantity`) > 300)) as `t0`)) group by `orders`.`o_orderkey`, `orders`.`o_custkey`")
 
 - sql: |
     select
@@ -732,6 +719,7 @@
     );
 
   plan: |
+
     hashagg(revenue="sum(__*__)")
       bkajoin(condition="p_partkey = l_partkey and ((p_partkey = l_partkey and = and in and >= and <= and between asymmetric and in and =) or (p_partkey = l_partkey and =4 and in5 and >=6 and <=7 and between asymmetric6 and in and =) or (p_partkey = l_partkey and =7 and in8 and >=8 and <=7 and between asymmetric9 and in and =))", type="inner")
         gather(concurrent=true)
@@ -781,6 +769,7 @@
       s_name;
 
   plan: |
+
     memsort(sort="s_name asc")
       project(s_name="s_name", s_address="s_address")
         semihashjoin(condition="s_suppkey = ps_suppkey", type="semi", build="inner")
@@ -788,9 +777,9 @@
             logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey`, `supplier`.`s_name`, `supplier`.`s_address` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'canada'))")
           project(ps_suppkey="ps_suppkey")
             hashjoin(condition="l_partkey = ps_partkey and l_suppkey = ps_suppkey and ps_availqty > 0.5 * $f2", type="inner")
-              hashagg(group="l_partkey,l_suppkey", $f2="sum(l_quantity)")
+              hashagg(group="l_partkey,l_suppkey", $f2="sum($f2)")
                 gather(concurrent=true)
-                  logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_quantity`, `l_partkey`, `l_suppkey` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(cast('1994-01-01' as date), interval 1 year)) and (`l_shipdate` >= '1994-01-01'))")
+                  logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, `l_suppkey`, sum(`l_quantity`) as `$f2` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(cast('1994-01-01' as date), interval 1 year)) and (`l_shipdate` >= '1994-01-01')) group by `l_partkey`, `l_suppkey`")
               gather(concurrent=true)
                 logicalview(tables="[0000-0003].partsupp_[00-15],part_[00-15]", shardcount=16, sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp` as `partsupp` where (`ps_partkey` in (select `p_partkey` from `part` as `part` where ((`p_name` like 'forest%') and (`partsupp`.`ps_partkey` = `p_partkey`))))")
 
@@ -836,6 +825,7 @@
       s_name;
 
   plan: |
+
     memsort(sort="numwait desc,s_name asc")
       hashagg(group="s_name", numwait="count()")
         semibkajoin(condition="l_orderkey = l_orderkey and l_suppkey <> l_suppkey", type="semi")
@@ -846,7 +836,7 @@
               gather(concurrent=true)
                 logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey`, `supplier`.`s_name` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'saudi arabia'))")
           gather(concurrent=true)
-            logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem` where (`l_orderkey` in (...))")
+            logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem` force index(`primary`) where (`l_orderkey` in (...))")
 
 - sql: |
     /*+TDDL:cmd_extra(CBO_RESTRICT_PUSH_JOIN_LIMIT=0, CBO_RESTRICT_PUSH_JOIN_COUNT=0)*/
@@ -891,6 +881,7 @@
       s_name;
 
   plan: |
+
     memsort(sort="numwait desc,s_name asc")
       hashagg(group="s_name", numwait="count()")
         semibkajoin(condition="l_orderkey = l_orderkey and l_suppkey <> l_suppkey", type="semi")
@@ -904,156 +895,116 @@
             gather(concurrent=true)
               logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem` where (`l_receiptdate` > `l_commitdate`)")
           gather(concurrent=true)
-            logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem` where (`l_orderkey` in (...))")
+            logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem` force index(`primary`) where (`l_orderkey` in (...))")
 
 - sql: |
     select count(*) from orders;
 
   plan: |
-    HashAgg(count(*)="SUM(count(*))")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT COUNT(*) AS `count(*)` FROM `orders` AS `orders`")
+
+    hashagg(count(*)="sum(count(*))")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select count(*) as `count(*)` from `orders` as `orders`")
 
 - sql: |
     select * from lineitem order by l_orderkey desc, l_linenumber limit 2;
 
   plan: |
-    MergeSort(sort="l_orderkey DESC,l_linenumber ASC", offset=0, fetch=2)
-      LogicalView(tables="[0000-0003].lineitem_[00-15]", shardCount=16, sql="SELECT `l_orderkey`, `l_partkey`, `l_suppkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus`, `l_shipdate`, `l_commitdate`, `l_receiptdate`, `l_shipinstruct`, `l_shipmode`, `l_comment` FROM `lineitem` AS `lineitem` ORDER BY `l_orderkey` DESC, `l_linenumber` LIMIT 2")
+
+    mergesort(sort="l_orderkey desc,l_linenumber asc", offset=0, fetch=2)
+      logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus`, `l_shipdate`, `l_commitdate`, `l_receiptdate`, `l_shipinstruct`, `l_shipmode`, `l_comment` from `lineitem` as `lineitem` force index(`primary`) order by `l_orderkey` desc, `l_linenumber` limit 2")
 
 - sql: |
     select * from lineitem order by l_linenumber limit 2;
 
   plan: |
-    MergeSort(sort="l_linenumber ASC", offset=0, fetch=2)
-      LogicalView(tables="[0000-0003].lineitem_[00-15]", shardCount=16, sql="SELECT `l_orderkey`, `l_partkey`, `l_suppkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus`, `l_shipdate`, `l_commitdate`, `l_receiptdate`, `l_shipinstruct`, `l_shipmode`, `l_comment` FROM `lineitem` AS `lineitem` ORDER BY `l_linenumber` LIMIT 2")
 
+    mergesort(sort="l_linenumber asc", offset=0, fetch=2)
+      logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus`, `l_shipdate`, `l_commitdate`, `l_receiptdate`, `l_shipinstruct`, `l_shipmode`, `l_comment` from `lineitem` as `lineitem` order by `l_linenumber` limit 2")
 
 - sql: |
     select * from lineitem order by l_orderkey limit 100000000,2;
 
   plan: |
-    MergeSort(sort="l_orderkey ASC", offset=100000000, fetch=2)
-      LogicalView(tables="[0000-0003].lineitem_[00-15]", shardCount=16, sql="SELECT `l_orderkey`, `l_partkey`, `l_suppkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus`, `l_shipdate`, `l_commitdate`, `l_receiptdate`, `l_shipinstruct`, `l_shipmode`, `l_comment` FROM `lineitem` AS `lineitem` ORDER BY `l_orderkey` LIMIT 100000002")
+
+    mergesort(sort="l_orderkey asc", offset=100000000, fetch=2)
+      logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus`, `l_shipdate`, `l_commitdate`, `l_receiptdate`, `l_shipinstruct`, `l_shipmode`, `l_comment` from `lineitem` as `lineitem` force index(`primary`) order by `l_orderkey` limit 100000002")
 
 - sql: |
     select * from lineitem limit 100000000,2;
 
   plan: |
-    MergeSort(sort="", offset=100000000, fetch=2)
-      LogicalView(tables="[0000-0003].lineitem_[00-15]", shardCount=16, sql="SELECT `l_orderkey`, `l_partkey`, `l_suppkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus`, `l_shipdate`, `l_commitdate`, `l_receiptdate`, `l_shipinstruct`, `l_shipmode`, `l_comment` FROM `lineitem` AS `lineitem` LIMIT 100000002")
+
+    mergesort(sort="", offset=100000000, fetch=2)
+      logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus`, `l_shipdate`, `l_commitdate`, `l_receiptdate`, `l_shipinstruct`, `l_shipmode`, `l_comment` from `lineitem` as `lineitem` limit 100000002")
 
 - sql: |
     select * from lineitem ignore index(primary) where l_orderkey = 1;
 
   plan: |
+
     phytableoperation(tables="optest_0000.[lineitem_00]", sql="select `lineitem`.`l_orderkey`, `lineitem`.`l_partkey`, `lineitem`.`l_suppkey`, `lineitem`.`l_linenumber`, `lineitem`.`l_quantity`, `lineitem`.`l_extendedprice`, `lineitem`.`l_discount`, `lineitem`.`l_tax`, `lineitem`.`l_returnflag`, `lineitem`.`l_linestatus`, `lineitem`.`l_shipdate`, `lineitem`.`l_commitdate`, `lineitem`.`l_receiptdate`, `lineitem`.`l_shipinstruct`, `lineitem`.`l_shipmode`, `lineitem`.`l_comment` from ? as `lineitem` ignore index(primary) where (`lineitem`.`l_orderkey` = 1)")
 
 - sql: |
     select * from lineitem ignore index(primary) join orders on o_orderkey =  l_orderkey where o_custkey = 1;
 
   plan: |
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].lineitem_[00-15],orders_[00-15]", shardCount=16, sql="SELECT `lineitem`.`l_orderkey`, `lineitem`.`l_partkey`, `lineitem`.`l_suppkey`, `lineitem`.`l_linenumber`, `lineitem`.`l_quantity`, `lineitem`.`l_extendedprice`, `lineitem`.`l_discount`, `lineitem`.`l_tax`, `lineitem`.`l_returnflag`, `lineitem`.`l_linestatus`, `lineitem`.`l_shipdate`, `lineitem`.`l_commitdate`, `lineitem`.`l_receiptdate`, `lineitem`.`l_shipinstruct`, `lineitem`.`l_shipmode`, `lineitem`.`l_comment`, `orders`.`o_orderkey`, `orders`.`o_custkey`, `orders`.`o_orderstatus`, `orders`.`o_totalprice`, `orders`.`o_orderdate`, `orders`.`o_orderpriority`, `orders`.`o_clerk`, `orders`.`o_shippriority`, `orders`.`o_comment` FROM `lineitem` AS `lineitem` IGNORE INDEX(PRIMARY) INNER JOIN `orders` AS `orders` ON ((`orders`.`o_custkey` = 1) AND (`lineitem`.`l_orderkey` = `orders`.`o_orderkey`))")
+
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].lineitem_[00-15],orders_[00-15]", shardcount=16, sql="select `lineitem`.`l_orderkey`, `lineitem`.`l_partkey`, `lineitem`.`l_suppkey`, `lineitem`.`l_linenumber`, `lineitem`.`l_quantity`, `lineitem`.`l_extendedprice`, `lineitem`.`l_discount`, `lineitem`.`l_tax`, `lineitem`.`l_returnflag`, `lineitem`.`l_linestatus`, `lineitem`.`l_shipdate`, `lineitem`.`l_commitdate`, `lineitem`.`l_receiptdate`, `lineitem`.`l_shipinstruct`, `lineitem`.`l_shipmode`, `lineitem`.`l_comment`, `orders`.`o_orderkey`, `orders`.`o_custkey`, `orders`.`o_orderstatus`, `orders`.`o_totalprice`, `orders`.`o_orderdate`, `orders`.`o_orderpriority`, `orders`.`o_clerk`, `orders`.`o_shippriority`, `orders`.`o_comment` from `lineitem` as `lineitem` ignore index(primary) inner join `orders` as `orders` on ((`orders`.`o_custkey` = 1) and (`lineitem`.`l_orderkey` = `orders`.`o_orderkey`))")
 
 - sql: |
     select * from lineitem ignore index(primary) order by l_orderkey desc, l_linenumber desc,l_orderkey limit 2;
 
   plan: |
-    MergeSort(sort="l_orderkey DESC,l_linenumber DESC,l_orderkey ASC", offset=0, fetch=2)
-      LogicalView(tables="[0000-0003].lineitem_[00-15]", shardCount=16, sql="SELECT `l_orderkey`, `l_partkey`, `l_suppkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus`, `l_shipdate`, `l_commitdate`, `l_receiptdate`, `l_shipinstruct`, `l_shipmode`, `l_comment` FROM `lineitem` AS `lineitem` IGNORE INDEX(PRIMARY) ORDER BY `l_orderkey` DESC, `l_linenumber` DESC, `l_orderkey` LIMIT 2")
 
+    mergesort(sort="l_orderkey desc,l_linenumber desc,l_orderkey asc", offset=0, fetch=2)
+      logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus`, `l_shipdate`, `l_commitdate`, `l_receiptdate`, `l_shipinstruct`, `l_shipmode`, `l_comment` from `lineitem` as `lineitem` ignore index(primary) order by `l_orderkey` desc, `l_linenumber` desc, `l_orderkey` limit 2")
 
 - sql: |
     /*+TDDL:cmd_extra(enable_push_agg=false,enable_cbo_push_agg=false)*/
     select distinct l_orderkey from lineitem order by l_orderkey;
 
   plan: |
-    SortAgg(group="l_orderkey")
-      MergeSort(sort="l_orderkey ASC")
-        LogicalView(tables="[0000-0003].lineitem_[00-15]", shardCount=16, sql="SELECT `l_orderkey` FROM `lineitem` AS `lineitem` ORDER BY `l_orderkey`")
 
-  # test o_orderstatus = 0 multi time will only count one
+    sortagg(group="l_orderkey")
+      mergesort(sort="l_orderkey asc")
+        logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey` from `lineitem` as `lineitem` force index(`primary`) order by `l_orderkey`")
+
 - sql: |
     select * from orders join customer on o_custkey = c_custkey where  o_orderstatus = 0 and  o_orderstatus = 0 and  o_orderstatus = 0 and  o_orderstatus = 0 and  o_orderstatus = 0 and  o_orderstatus = 0 and  o_orderstatus = 0 and  o_orderstatus = 0 and  o_orderstatus = 0 and  o_orderstatus = 0 and  o_orderstatus = 0 and  o_orderstatus = 0;
 
   plan: |
-    bkajoin(condition="o_custkey = c_custkey", type="inner")
+
+    hashjoin(condition="o_custkey = c_custkey", type="inner")
       gather(concurrent=true)
         logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders` as `orders` where (`o_orderstatus` = 0)")
       gather(concurrent=true)
-        logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` from `customer` as `customer` where (`c_custkey` in (...))")
+        logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` from `customer` as `customer`")
 
-# test o_clerk = 'Clerk#000000951' and o_orderdate = '1996-01-02' will produce low selectivity
 - sql: |
     select * from orders join customer on o_custkey = c_custkey where o_clerk = 'Clerk#000000951' and o_orderdate = '1996-01-02'
 
   plan: |
+
     bkajoin(condition="o_custkey = c_custkey", type="inner")
       gather(concurrent=true)
         logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders` as `orders` where ((`o_clerk` = 'clerk#000000951') and (`o_orderdate` = '1996-01-02'))")
       gather(concurrent=true)
-        logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` from `customer` as `customer` where (`c_custkey` in (...))")
+        logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_mktsegment`, `c_comment` from `customer` as `customer` force index(`primary`) where (`c_custkey` in (...))")
+
 - sql: |
     select * from orders where 1=1
   plan: |
+
     gather(concurrent=true)
       logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_custkey`, `o_orderstatus`, `o_totalprice`, `o_orderdate`, `o_orderpriority`, `o_clerk`, `o_shippriority`, `o_comment` from `orders` as `orders` where (1 = 1)")
+
 - sql: |
     /*+TDDL:cmd_extra(workload_type=ap)*/ select 1 from (select sum(l_orderkey)as t,l_partkey  from lineitem group by l_partkey) as ll where ll.l_partkey=12;
   plan: |
+
     project(1="1")
       hashagg(group="l_partkey", t="sum(t)")
         gather(concurrent=true)
-          logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, sum(`l_orderkey`) as `t` from `lineitem` as `lineitem` where (`l_partkey` = 12) group by `l_partkey`")
-  #-
-#  sql: |
-#    select
-#      cntrycode,
-#      count(*) as numcust,
-#      sum(c_acctbal) as totacctbal
-#    from
-#      (
-#      select
-#        substring(c_phone ,1, 2) as cntrycode,
-#        c_acctbal
-#      from
-#        customer
-#      where
-#        substring(c_phone ,1, 2) in ('13','31','23','29','30','18','17')
-#        and c_acctbal > (
-#          select
-#            avg(c_acctbal)
-#          from
-#            customer
-#          where
-#            c_acctbal > 0.00
-#            and substring (c_phone , 1, 2) in ('13','31','23','29','30','18','17')
-#        )
-#        and not exists (
-#          select
-#            *
-#          from
-#            orders
-#          where
-#            o_custkey = c_custkey
-#        )
-#      ) as custsale
-#    group by
-#      cntrycode
-#    order by
-#      cntrycode;
-#
-#  plan: |
-#    MemSort(sort="cntrycode ASC")
-#      HashAgg(group="cntrycode", numcust="COUNT()", totacctbal="SUM(c_acctbal)")
-#        Project(cntrycode="SUBSTRING(c_phone, 1, 2)", c_acctbal="c_acctbal")
-#          NlJoin(condition="c_acctbal > sum_pushed_sum / sum_pushed_count", type="inner")
-#            SemiHashJoin(condition="c_custkey = o_custkey", type="anti")
-#              Gather(concurrent=true)
-#                LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey`, `c_phone`, `c_acctbal` FROM `customer` AS `customer` WHERE ((SUBSTRING(`c_phone`, 1, 2)) IN('13', '31', '23', '29', '30', '18', '17'))")
-#              Gather(concurrent=true)
-#                LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_custkey` FROM `orders` AS `orders`")
-#            HashAgg(sum_pushed_sum="SUM(pushed_sum)", sum_pushed_count="SUM(pushed_count)")
-#              Gather(concurrent=true)
-#                LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT SUM(`c_acctbal`) AS `pushed_sum`, COUNT(`c_acctbal`) AS `pushed_count` FROM `customer` AS `customer` WHERE ((`c_acctbal` > 0.00) AND ((SUBSTRING(`c_phone`, 1, 2)) IN('13', '31', '23', '29', '30', '18', '17')))")
+          logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, sum(`l_orderkey`) as `t` from `lineitem` as `lineitem` force index(`i_l_partkey`) where (`l_partkey` = 12) group by `l_partkey`")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/ColumnarWorkloadTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/ColumnarWorkloadTest.yml
new file mode 100644
index 000000000..4718f77b0
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/ColumnarWorkloadTest.yml
@@ -0,0 +1,47 @@
+SQL:
+  - sql: |
+      select 1 from customer;
+    plan: |
+      ap
+  - sql: |
+      /*+TDDL:cmd_extra(workload_type=tp)*/select 1 from customer;
+    plan: |
+      tp
+  - sql: |
+      /*+TDDL:cmd_extra(workload_type=null)*/select 1 from customer;
+    plan: |
+      ap
+  - sql: |
+      select 1 from customer where c_custkey=1;
+    plan: |
+      ap
+  - sql: |
+        /*+TDDL:cmd_extra(workload_type="")*/select 1 from customer where c_custkey=1;
+    plan: |
+      ap
+  - sql: |
+        /*+TDDL:cmd_extra(workload_type=tp)*/select 1 from customer where c_custkey=1;
+    plan: |
+      tp
+  - sql: |
+        /*+TDDL:cmd_extra(workload_type=ap)*/select 1 from customer where c_custkey=1;
+    plan: |
+      ap
+  - sql: |
+       /*+TDDL:cmd_extra(workload_type=tp)*/select 1 from customer force index(customer_col_index);
+    plan: |
+      tp
+DDL:
+  customer:
+    CREATE TABLE IF NOT EXISTS `customer` (  `c_custkey` int(11) NOT NULL,  `c_name` varchar(25) NOT NULL,  `c_address` varchar(40) NOT NULL,  `c_nationkey` int(11) NOT NULL,  `c_phone` varchar(15) NOT NULL,  `c_acctbal` decimal(15, 2) NOT NULL,  `c_mktsegment` varchar(10) NOT NULL,  `c_comment` varchar(117) NOT NULL,  PRIMARY KEY (`c_custkey`),  CLUSTERED COLUMNAR INDEX `customer_col_index`(`c_custkey`) PARTITION BY HASH (`c_custkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`c_custkey`) PARTITIONS 128;
+STATISTICS:
+  customer:
+    168648768
+CONFIG:
+  ENABLE_MPP:
+    true
+  ENABLE_COLUMNAR_OPTIMIZER:
+    true
+  defaltxxAPPName.isNew:
+    true
+
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/TpParameterizedTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/TpParameterizedTest.yml
index f54bc1587..5ce54b53b 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/TpParameterizedTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/TpParameterizedTest.yml
@@ -8,8 +8,7 @@
     update orders set o_orderstatus = 'A' where o_orderkey in (1,1000);
 
   plan: |
-    logicalmodifyview(tables="[0000,0003].orders_[00,15]", shardcount=2, sql="update `orders` as `orders` set `o_orderstatus` = ? where (`o_orderkey` in(?))", pruninginfo="all size:2*2(part), pruning size:2")
-
+    logicalmodifyview(tables="[0000,0003].orders_[00,15]", shardcount=2, sql="update `orders` as `orders` force index(`primary`) set `o_orderstatus` = ? where (`o_orderkey` in(?))", pruninginfo="all size:2*2(part), pruning size:2")
 - sql: |
     delete from orders where o_orderkey = 1 or o_orderkey = 1000;
 
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/TpTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/TpTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/htap/TpTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/BKAJoinPlanTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/BKAJoinPlanTest.ddl.yml
index 05effa447..33188fead 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/BKAJoinPlanTest.ddl.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/BKAJoinPlanTest.ddl.yml
@@ -94,3 +94,10 @@ tt:
   `c2` int(11) DEFAULT NULL,
   KEY `auto_shard_key_c1` USING BTREE (`c1`)
   ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4  dbpartition by hash(`c1`);
+
+tt_broadcast:
+  CREATE TABLE `tt_broadcast` (
+  `c1` int(11) DEFAULT NULL,
+  `c2` int(11) DEFAULT NULL,
+  KEY `auto_shard_key_c1` USING BTREE (`c1`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4  broadcast;
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/BKAJoinPlanTest.testEnableBKAJoin.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/BKAJoinPlanTest.yml
similarity index 51%
rename from polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/BKAJoinPlanTest.testEnableBKAJoin.yml
rename to polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/BKAJoinPlanTest.yml
index 34e14cdb1..6357cb069 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/BKAJoinPlanTest.testEnableBKAJoin.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/BKAJoinPlanTest.yml
@@ -19,12 +19,12 @@
 
   plan: |
 
-    Project(id="id")
-      BKAJoin(condition="id = id", type="inner")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_id1", shardCount=4, sql="SELECT `name` AS `id` FROM `t_shard_id1` AS `t_shard_id1`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_id2", shardCount=4, sql="SELECT `name` AS `id` FROM `t_shard_id2` AS `t_shard_id2` WHERE (`name` IN (...))")
+    project(id="id")
+      bkajoin(condition="id = id", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `name` as `id` from `t_shard_id1` as `t_shard_id1`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_id2", shardcount=4, sql="select `name` as `id` from `t_shard_id2` as `t_shard_id2` where (`name` in (...))")
 
 - sql: |
     /*+TDDL:BKA_JOIN(t_shard_id1, t_shard_id2)*/ select a.id
@@ -47,12 +47,13 @@
     where a.id=5
 
   plan: |
-    Project(id="id")
-      BKAJoin(condition="id = id", type="inner")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_id1", shardCount=4, sql="SELECT `name` AS `id` FROM `t_shard_id1` AS `t_shard_id1` WHERE (`name` = 5)")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_id2", shardCount=4, sql="SELECT `name` AS `id` FROM `t_shard_id2` AS `t_shard_id2` WHERE ((`name` = 5) AND (`name` IN (...)))")
+
+    project(id="id")
+      bkajoin(condition="id = id", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `name` as `id` from `t_shard_id1` as `t_shard_id1` where (`name` = 5)")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_id2", shardcount=4, sql="select `name` as `id` from `t_shard_id2` as `t_shard_id2` where ((`name` = 5) and (`name` in (...)))")
 
 - sql: |
     /*+TDDL:BKA_JOIN((t_shard_id1,t_shard_business_id), t_shard_name)*/ select
@@ -68,37 +69,37 @@
 
   plan: |
 
-    Project(name="name", 状态="CASE", 冻结状态="CASE2")
-      BKAJoin(condition="name = name0", type="left")
-        Gather(concurrent=true)
-          LogicalView(tables="[0002,0003].t_shard_id1,t_shard_business_id", shardCount=2, sql="SELECT `t_shard_business_id`.`name` AS `name0`, (CASE WHEN (`t_shard_business_id`.`business_id` = 0) THEN '预处理' WHEN (`t_shard_business_id`.`business_id` = 1) THEN '待付款' WHEN (`t_shard_business_id`.`business_id` = 91) THEN '终止' ELSE NULL END) AS `CASE`, (CASE WHEN (`t_shard_id1`.`id` = 0) THEN '正常' WHEN (`t_shard_id1`.`id` = 4) THEN '退货中' ELSE NULL END) AS `CASE2` FROM `t_shard_id1` AS `t_shard_id1` LEFT JOIN `t_shard_business_id` AS `t_shard_business_id` ON (`t_shard_id1`.`id` = `t_shard_business_id`.`business_id`) WHERE (`t_shard_id1`.`id` IN('100002', '100003'))")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_name", shardCount=4, sql="SELECT `name` FROM `t_shard_name` AS `t_shard_name` WHERE (`name` IN (...))")
+    project(name="name", 状态="case", 冻结状态="case2")
+      bkajoin(condition="name = name0", type="left")
+        gather(concurrent=true)
+          logicalview(tables="[0002,0003].t_shard_id1,t_shard_business_id", shardcount=2, sql="select `t_shard_business_id`.`name` as `name0`, (case when (`t_shard_business_id`.`business_id` = 0) then '预处理' when (`t_shard_business_id`.`business_id` = 1) then '待付款' when (`t_shard_business_id`.`business_id` = 91) then '终止' else null end) as `case`, (case when (`t_shard_id1`.`id` = 0) then '正常' when (`t_shard_id1`.`id` = 4) then '退货中' else null end) as `case2` from `t_shard_id1` as `t_shard_id1` left join `t_shard_business_id` as `t_shard_business_id` on (`t_shard_id1`.`id` = `t_shard_business_id`.`business_id`) where (`t_shard_id1`.`id` in('100002', '100003'))")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_name", shardcount=4, sql="select `name` from `t_shard_name` as `t_shard_name` where (`name` in (...))")
 
 - sql: |
     select * from t_shard_id1 a join (select id + 1 as id, name from t_shard_business_id) b on a.id = b.id ;
 
   plan: |
 
-    Project(id="id0", name="name0", create_time="create_time", id0="id", name0="name")
-      BKAJoin(condition="id = id", type="inner")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_business_id", shardCount=4, sql="SELECT (`id` + 1) AS `id`, `name` FROM `t_shard_business_id` AS `t_shard_business_id`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_id1", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `t_shard_id1` AS `t_shard_id1` WHERE (`id` IN (...))")
+    project(id="id0", name="name0", create_time="create_time", id0="id", name0="name")
+      bkajoin(condition="id = id", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_business_id", shardcount=4, sql="select (`id` + 1) as `id`, `name` from `t_shard_business_id` as `t_shard_business_id`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `id`, `name`, `create_time` from `t_shard_id1` as `t_shard_id1` force index(`primary`) where (`id` in (...))")
 
 - sql: |
     /*+TDDL:BKA_JOIN(t_shard_business_id,t_shard_id1)*/ select * from t_shard_id1 a join (select count(*) as id, name from t_shard_business_id group by name) b on a.name = b.name ;
 
   plan: |
 
-    Project(id0="id0", name0="name0", create_time="create_time", id="id", name="name")
-      BKAJoin(condition="name = name", type="inner")
-        HashAgg(group="name", id="SUM(id)")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].t_shard_business_id", shardCount=4, sql="SELECT `name`, COUNT(*) AS `id` FROM `t_shard_business_id` AS `t_shard_business_id` GROUP BY `name`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_id1", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `t_shard_id1` AS `t_shard_id1` WHERE (`name` IN (...))")
+    project(id0="id0", name0="name0", create_time="create_time", id="id", name="name")
+      bkajoin(condition="name = name", type="inner")
+        hashagg(group="name", id="sum(id)")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].t_shard_business_id", shardcount=4, sql="select `name`, count(*) as `id` from `t_shard_business_id` as `t_shard_business_id` group by `name`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `id`, `name`, `create_time` from `t_shard_id1` as `t_shard_id1` where (`name` in (...))")
 
 - sql: |
     /*+TDDL:BKA_JOIN(t_shard_name, t_composite_pk_shard_id)*/ select a.id
@@ -109,12 +110,13 @@
     on a.id=b.id and a.id1=b.name
 
   plan: |
-    Project(id="id0")
-      BKAJoin(condition="id = id AND name = id1", type="inner")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_name", shardCount=4, sql="SELECT `id`, `name` FROM `t_shard_name` AS `t_shard_name`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_composite_pk_shard_id", shardCount=4, sql="SELECT `id`, `id1` FROM `t_composite_pk_shard_id` AS `t_composite_pk_shard_id` WHERE (((`id`, `id1`)) IN (...))")
+
+    project(id="id0")
+      bkajoin(condition="id = id and name = id1", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_name", shardcount=4, sql="select `id`, `name` from `t_shard_name` as `t_shard_name`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_composite_pk_shard_id", shardcount=4, sql="select `id`, `id1` from `t_composite_pk_shard_id` as `t_composite_pk_shard_id` force index(`primary`) where (((`id`, `id1`)) in (...))")
 
 - sql: |
     /*+TDDL:BKA_JOIN(t_shard_name, t_composite_pk_shard_id)*/ select a.id
@@ -125,11 +127,12 @@
     on a.id=b.id and a.id1=b.name where a.id = 'a';
 
   plan: |
-    project(id="id")
-      bkajoin(condition="name = id1", type="inner")
+
+    project(id="id0")
+      bkajoin(condition="id = id and name = id1", type="inner")
         gather(concurrent=true)
-          logicalview(tables="[0000-0003].t_shard_name", shardcount=4, sql="select `name` from `t_shard_name` as `t_shard_name` where (`id` = 'a')")
-        logicalview(tables="optest_0000.t_composite_pk_shard_id", sql="select `id`, `id1` from `t_composite_pk_shard_id` as `t_composite_pk_shard_id` where ((`id` = 'a') and (`id1` in (...)))")
+          logicalview(tables="[0000-0003].t_shard_name", shardcount=4, sql="select `id`, `name` from `t_shard_name` as `t_shard_name` force index(`primary`) where (`id` = 'a')")
+        logicalview(tables="optest_0000.t_composite_pk_shard_id", sql="select `id`, `id1` from `t_composite_pk_shard_id` as `t_composite_pk_shard_id` where ((`id` = 'a') and (((`id`, `id1`)) in (...)))")
 
 - sql: |
     /*+TDDL:BKA_JOIN(t_shard_name, t_composite_pk_shard_id)*/ select a.id
@@ -140,26 +143,29 @@
     on a.id=b.id and a.id1=b.name where a.id = 'a';
 
   plan: |
-    project(id="id")
-      bkajoin(condition="id1 = name", type="right")
+
+    project(id="id0")
+      bkajoin(condition="id = id and id1 = name", type="right")
         gather(concurrent=true)
-          logicalview(tables="[0000-0003].t_shard_name", shardcount=4, sql="select `name` from `t_shard_name` as `t_shard_name` where ((`id` = 'a') and (`name` in (...)))")
-        logicalview(tables="optest_0000.t_composite_pk_shard_id", sql="select `id`, `id1` from `t_composite_pk_shard_id` as `t_composite_pk_shard_id` where (`id` = 'a')")
+          logicalview(tables="[0000-0003].t_shard_name", shardcount=4, sql="select `id`, `name` from `t_shard_name` as `t_shard_name` force index(`primary`) where ((`id` = 'a') and (((`id`, `name`)) in (...)))")
+        logicalview(tables="optest_0000.t_composite_pk_shard_id", sql="select `id`, `id1` from `t_composite_pk_shard_id` as `t_composite_pk_shard_id` force index(`auto_shard_key_id`) where (`id` = 'a')")
 
 - sql: |
     /*+TDDL:BKA_JOIN(t_null_safe1, t_null_safe2)*/ select * from t_null_safe1 left join t_null_safe2 on t_null_safe2.id <=> t_null_safe1.id;
 
   plan: |
+
     bkajoin(condition="id <=> id", type="left")
       gather(concurrent=true)
         logicalview(tables="[0000-0003].t_null_safe1", shardcount=4, sql="select `id`, `id_nullable`, `name`, `create_time` from `t_null_safe1` as `t_null_safe1`")
       gather(concurrent=true)
-        logicalview(tables="[0000-0003].t_null_safe2", shardcount=4, sql="select `id`, `id_nullable`, `name`, `create_time` from `t_null_safe2` as `t_null_safe2` where (`id` in (...))")
+        logicalview(tables="[0000-0003].t_null_safe2", shardcount=4, sql="select `id`, `id_nullable`, `name`, `create_time` from `t_null_safe2` as `t_null_safe2` force index(`primary`) where (`id` in (...))")
 
 - sql: |
     select * from t_null_safe1 left join t_null_safe2 on t_null_safe2.id <=> t_null_safe1.id_nullable;
 
   plan: |
+
     hashjoin(condition="id <=> id_nullable", type="left")
       gather(concurrent=true)
         logicalview(tables="[0000-0003].t_null_safe1", shardcount=4, sql="select `id`, `id_nullable`, `name`, `create_time` from `t_null_safe1` as `t_null_safe1`")
@@ -170,6 +176,7 @@
     select * from t_null_safe1 left join t_null_safe2 on t_null_safe2.id_nullable <=> t_null_safe1.id;
 
   plan: |
+
     hashjoin(condition="id_nullable <=> id", type="left")
       gather(concurrent=true)
         logicalview(tables="[0000-0003].t_null_safe1", shardcount=4, sql="select `id`, `id_nullable`, `name`, `create_time` from `t_null_safe1` as `t_null_safe1`")
@@ -180,6 +187,7 @@
     /*+TDDL: IN_SUB_QUERY_THRESHOLD=8 */ select * from tt where c1 in (1,1,1,1,1,1,1,1,1,1) and c2 in (3,4);
 
   plan: |
+
     project(c1="c1", c2="c2")
       bkajoin(condition="expr$0 = c1", type="inner")
         hashagg(group="expr$0")
@@ -191,4 +199,14 @@
     /*+TDDL: IN_SUB_QUERY_THRESHOLD=8 */ select * from tt where c1 in (1,1) and c2 in (3,4);
 
   plan: |
-    phytableoperation(tables="optest_0001.[tt]", sql="select `tt`.`c1`, `tt`.`c2` from ? as `tt` where ((`tt`.`c1` in (1, 1)) and (`tt`.`c2` in (3, 4)))")
+
+    gather(concurrent=true)
+      logicalview(tables="optest_0001.tt", sql="select `c1`, `c2` from `tt` as `tt` where ((`c2` in(3, 4)) and (`c1` in(1, 1)))")
+
+
+- sql: |
+    select tt.c1 from tt left join tt_broadcast on tt.c1=tt_broadcast.c1 where tt_broadcast.c1 is null;
+
+  plan: |
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].tt,tt_broadcast", shardcount=4, sql="select `tt`.`c1` from `tt` as `tt` left join `tt_broadcast` as `tt_broadcast` on (`tt`.`c1` = `tt_broadcast`.`c1`) where (`tt_broadcast`.`c1` is null)")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/HeuristicJoinPlanTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/HeuristicJoinPlanTest.yml
index f7aa55333..c9a355dc5 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/HeuristicJoinPlanTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/HeuristicJoinPlanTest.yml
@@ -325,22 +325,20 @@
     left join t_shard_business_id b on a.id=b.id join t_shard_name c on a.name = c.name join t_shard_id3 d on b.create_time= d.create_time;
 
   plan: |
-    HashAgg(count(a.name)="SUM($f4)")
-      Project(name="name", count(a.name)="count(a.name)", name0="name0", $f1="$f1", $f4="count(a.name) * $f1")
-        HashJoin(condition="name = name", type="inner")
-          HashAgg(group="name", count(a.name)="COUNT(name)")
-            HashJoin(condition="create_time = create_time", type="inner")
-              Gather(concurrent=true)
-                LogicalView(tables="[0000-0003].t_shard_id3_[0-3]", shardCount=16, sql="SELECT `create_time` FROM `t_shard_id3` AS `t_shard_id3`")
-              HashJoin(condition="id = id", type="left")
-                Gather(concurrent=true)
-                  LogicalView(tables="[0000-0003].t_shard_id1", shardCount=4, sql="SELECT `id`, `name` FROM `t_shard_id1` AS `t_shard_id1`")
-                Gather(concurrent=true)
-                  LogicalView(tables="[0000-0003].t_shard_business_id", shardCount=4, sql="SELECT `id`, `create_time` FROM `t_shard_business_id` AS `t_shard_business_id`")
-          HashAgg(group="name", $f1="COUNT()")
-            Gather(concurrent=true)
-              LogicalView(tables="[0000-0003].t_shard_name", shardCount=4, sql="SELECT `name` FROM `t_shard_name` AS `t_shard_name`")
-
+    hashagg(count(a.name)="sum($f4)")
+      project(name="name", count(a.name)="count(a.name)", name0="name0", $f1="$f1", $f4="count(a.name) * $f1")
+        hashjoin(condition="name = name", type="inner")
+          hashagg(group="name", count(a.name)="count(name)")
+            hashjoin(condition="create_time = create_time", type="inner")
+              gather(concurrent=true)
+                logicalview(tables="[0000-0003].t_shard_id3_[0-3]", shardcount=16, sql="select `create_time` from `t_shard_id3` as `t_shard_id3`")
+              hashjoin(condition="id = id", type="left")
+                gather(concurrent=true)
+                  logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `id`, `name` from `t_shard_id1` as `t_shard_id1`")
+                gather(concurrent=true)
+                  logicalview(tables="[0000-0003].t_shard_business_id", shardcount=4, sql="select `id`, `create_time` from `t_shard_business_id` as `t_shard_business_id`")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].t_shard_name", shardcount=4, sql="select `name`, count(*) as `$f1` from `t_shard_name` as `t_shard_name` group by `name`")
 - sql: |
     /*+TDDL:cmd_extra(RBO_HEURISTIC_JOIN_REORDER_LIMIT=1,CBO_TOO_MANY_JOIN_LIMIT=0,CBO_LEFT_DEEP_TREE_JOIN_LIMIT=0,CBO_ZIG_ZAG_TREE_JOIN_LIMIT=0,CBO_BUSHY_TREE_JOIN_LIMIT=0)*/
     select count(a.name) from t_shard_id1 a
@@ -376,6 +374,6 @@
                 logicalview(tables="[0000-0003].t_shard_business_id", shardcount=4, sql="select `name`, `create_time` from `t_shard_business_id` as `t_shard_business_id` order by `name`")
               gather(concurrent=true)
                 logicalview(tables="[0000-0003].t_shard_business_id", shardcount=4, sql="select `create_time` from `t_shard_business_id` as `t_shard_business_id`")
-          hashagg(group="name", $f1="count()")
+          hashagg(group="name", $f1="sum($f1)")
             gather(concurrent=true)
-              logicalview(tables="[0000-0003].t_shard_business_id", shardcount=4, sql="select `name` from `t_shard_business_id` as `t_shard_business_id`")
\ No newline at end of file
+              logicalview(tables="[0000-0003].t_shard_business_id", shardcount=4, sql="select `name`, count(*) as `$f1` from `t_shard_business_id` as `t_shard_business_id` group by `name`")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testAggShardingKeyJoinPlan.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testAggShardingKeyJoinPlan.yml
index 9ea51e2ad..0b0870aab 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testAggShardingKeyJoinPlan.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testAggShardingKeyJoinPlan.yml
@@ -4,9 +4,9 @@
 
   plan: |
 
-    HashAgg(count(*)="SUM(count(*))")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT COUNT(*) AS `count(*)` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON ((`test_hash_tb`.`name` = 'xx') AND (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
+    hashagg(count(*)="sum(count(*))")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`name` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
 
 -
   sql: |
@@ -14,10 +14,10 @@
 
   plan: |
 
-    Project(count(*)="count(*)")
-      HashAgg(group="name", count(*)="SUM(count(*))")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`name`, COUNT(*) AS `count(*)` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) GROUP BY `test_hash_tb`.`name`")
+    project(count(*)="count(*)")
+      hashagg(group="name", count(*)="sum(count(*))")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`name`, count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) group by `test_hash_tb`.`name`")
 
 -
   sql: |
@@ -25,11 +25,11 @@
 
   plan: |
 
-    MemSort(sort="count(*) ASC")
-      Project(count(*)="count(*)")
-        HashAgg(group="name", count(*)="SUM(count(*))")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`name`, COUNT(*) AS `count(*)` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) GROUP BY `test_hash_tb`.`name`")
+    memsort(sort="count(*) asc")
+      project(count(*)="count(*)")
+        hashagg(group="name", count(*)="sum(count(*))")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`name`, count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) group by `test_hash_tb`.`name`")
 
 -
   sql: |
@@ -41,4 +41,4 @@
       project(count(1)="count(1)")
         hashagg(group="name", count(1)="sum(count(1))")
           gather(concurrent=true)
-            logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`name`, count(*) as `count(1)` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) group by `test_hash_tb`.`name`")
\ No newline at end of file
+            logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`name`, count(*) as `count(1)` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) group by `test_hash_tb`.`name`")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testAggShardingKeyJoinWhereShardingKeyPlan.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testAggShardingKeyJoinWhereShardingKeyPlan.yml
index 5665c9d78..00fa1c5f0 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testAggShardingKeyJoinWhereShardingKeyPlan.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testAggShardingKeyJoinWhereShardingKeyPlan.yml
@@ -3,6 +3,7 @@
     select count(*) from test_hash_tb a join test_hash_tb b where a.id=b.id and a.id=1;
 
   plan: |
+
     phytableoperation(tables="optest_0001.[test_hash_tb, test_hash_tb]", sql="select count(*) as `count(*)` from ? as `a` inner join ? as `b` where ((`a`.`id` = `b`.`id`) and (`a`.`id` = 1))")
 
 -
@@ -10,6 +11,7 @@
     select count(*) from test_hash_tb a join test_hash_tb b where a.id=b.id and a.id=1 group by a.name;
 
   plan: |
+
     phytableoperation(tables="optest_0001.[test_hash_tb, test_hash_tb]", sql="select count(*) as `count(*)` from ? as `a` inner join ? as `b` where ((`a`.`id` = `b`.`id`) and (`a`.`id` = 1)) group by `a`.`name`")
 
 -
@@ -17,6 +19,7 @@
     select count(*) from test_hash_tb a join test_hash_tb b where a.id=b.id and a.id=1 group by a.name order by count(*);
 
   plan: |
+
     phytableoperation(tables="optest_0001.[test_hash_tb, test_hash_tb]", sql="select count(*) as `count(*)` from ? as `a` inner join ? as `b` where ((`a`.`id` = `b`.`id`) and (`a`.`id` = 1)) group by `a`.`name` order by count(*)")
 
 -
@@ -24,4 +27,5 @@
     select count(1) from test_hash_tb a join test_hash_tb b where a.id=b.id and a.id=1 group by a.name order by count(1);
 
   plan: |
-    phytableoperation(tables="optest_0001.[test_hash_tb, test_hash_tb]", sql="select count(1) as `count(1)` from ? as `a` inner join ? as `b` where ((`a`.`id` = `b`.`id`) and (`a`.`id` = 1)) group by `a`.`name` order by count(1)")
\ No newline at end of file
+
+    phytableoperation(tables="optest_0001.[test_hash_tb, test_hash_tb]", sql="select count(1) as `count(1)` from ? as `a` inner join ? as `b` where ((`a`.`id` = `b`.`id`) and (`a`.`id` = 1)) group by `a`.`name` order by count(1)")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testBaseMultiJoinPlan.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testBaseMultiJoinPlan.yml
index 39907b5ad..7d29ebe1b 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testBaseMultiJoinPlan.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testBaseMultiJoinPlan.yml
@@ -3,21 +3,27 @@
     select * from test_hash_tb a join test_hash_tb b on a.id=b.id join test_hash_tb c  on b.id=c.id where a.id="xx";
 
   plan: |
-    phytableoperation(tables="optest_0000.[test_hash_tb, test_hash_tb, test_hash_tb]", sql="select `a`.`id`, `a`.`name`, `a`.`create_time`, `b`.`id`, `b`.`name`, `b`.`create_time`, `c`.`id`, `c`.`name`, `c`.`create_time` from ? as `a` inner join ? as `b` on (`a`.`id` = `b`.`id`) inner join ? as `c` on (`b`.`id` = `c`.`id`) where (`a`.`id` = 'xx')")
+
+    gather(concurrent=true)
+      logicalview(tables="optest_0000.test_hash_tb", sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0`, `test_hash_tb1`.`id` as `id1`, `test_hash_tb1`.`name` as `name1`, `test_hash_tb1`.`create_time` as `create_time1` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`id` = 'xx') and (`test_hash_tb0`.`id` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)) inner join `test_hash_tb` as `test_hash_tb1` on ((`test_hash_tb1`.`id` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb1`.`id`) and (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
 
 -
   sql: |
     select * from test_hash_tb a join test_hash_tb b join test_hash_tb c on a.id=b.id and a.id=c.id where a.id="xx";
 
   plan: |
-    phytableoperation(tables="optest_0000.[test_hash_tb, test_hash_tb, test_hash_tb]", sql="select `a`.`id`, `a`.`name`, `a`.`create_time`, `b`.`id`, `b`.`name`, `b`.`create_time`, `c`.`id`, `c`.`name`, `c`.`create_time` from ? as `a` inner join ? as `b` inner join ? as `c` on ((`a`.`id` = `b`.`id`) and (`a`.`id` = `c`.`id`)) where (`a`.`id` = 'xx')")
+
+    gather(concurrent=true)
+      logicalview(tables="optest_0000.test_hash_tb", sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0`, `test_hash_tb1`.`id` as `id1`, `test_hash_tb1`.`name` as `name1`, `test_hash_tb1`.`create_time` as `create_time1` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`id` = 'xx') and (`test_hash_tb0`.`id` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)) inner join `test_hash_tb` as `test_hash_tb1` on ((`test_hash_tb1`.`id` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb1`.`id`) and (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
 
 -
   sql: |
     select * from test_hash_tb a left join test_hash_tb b on a.id = b.id and b.id = 'xx' left join test_hash_tb c on b.id = c.id and c.id = 'xx' where a.id = 'xx';
 
   plan: |
-    phytableoperation(tables="optest_0000.[test_hash_tb, test_hash_tb, test_hash_tb]", sql="select `a`.`id`, `a`.`name`, `a`.`create_time`, `b`.`id`, `b`.`name`, `b`.`create_time`, `c`.`id`, `c`.`name`, `c`.`create_time` from ? as `a` left join ? as `b` on ((`a`.`id` = `b`.`id`) and (`b`.`id` = 'xx')) left join ? as `c` on ((`b`.`id` = `c`.`id`) and (`c`.`id` = 'xx')) where (`a`.`id` = 'xx')")
+
+    gather(concurrent=true)
+      logicalview(tables="optest_0000.test_hash_tb", sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0`, `test_hash_tb1`.`id` as `id1`, `test_hash_tb1`.`name` as `name1`, `test_hash_tb1`.`create_time` as `create_time1` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`id` = `test_hash_tb0`.`id`) and (`test_hash_tb0`.`id` = 'xx')) left join `test_hash_tb` as `test_hash_tb1` on ((`test_hash_tb0`.`id` = `test_hash_tb1`.`id`) and (`test_hash_tb1`.`id` = 'xx')) where (`test_hash_tb`.`id` = 'xx')")
 
 -
   sql: |
@@ -25,8 +31,8 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0`, `test_hash_tb1`.`id` AS `id1`, `test_hash_tb1`.`name` AS `name1`, `test_hash_tb1`.`create_time` AS `create_time1` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) INNER JOIN `test_hash_tb` AS `test_hash_tb1` ON ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) AND (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0`, `test_hash_tb1`.`id` as `id1`, `test_hash_tb1`.`name` as `name1`, `test_hash_tb1`.`create_time` as `create_time1` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) inner join `test_hash_tb` as `test_hash_tb1` on ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) and (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
 
 -
   sql: |
@@ -34,25 +40,8 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0`, `test_hash_tb1`.`id` AS `id1`, `test_hash_tb1`.`name` AS `name1`, `test_hash_tb1`.`create_time` AS `create_time1` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) INNER JOIN `test_hash_tb` AS `test_hash_tb1` ON ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) AND (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
-
-#-
-#  sql: |
-#    SELECT A.REFERENCED_TABLE_SCHEMA AS PKTABLE_CAT, NULL AS PKTABLE_SCHEM, A.REFERENCED_TABLE_NAME AS PKTABLE_NAME, A.REFERENCED_COLUMN_NAME AS PKCOLUMN_NAME, A.TABLE_SCHEMA AS FKTABLE_CAT, NULL AS FKTABLE_SCHEM, A.TABLE_NAME AS FKTABLE_NAME, A.COLUMN_NAME AS FKCOLUMN_NAME, A.ORDINAL_POSITION AS KEY_SEQ, CASE WHEN R.UPDATE_RULE = 'CASCADE' THEN 0 WHEN R.UPDATE_RULE = 'SET NULL' THEN 2 WHEN R.UPDATE_RULE = 'SET DEFAULT' THEN 4 WHEN R.UPDATE_RULE = 'SET RESTRICT' THEN 1 WHEN R.UPDATE_RULE = 'SET NO ACTION' THEN 3 ELSE 3 END AS UPDATE_RULE, CASE WHEN R.DELETE_RULE = 'CASCADE' THEN 0 WHEN R.DELETE_RULE = 'SET NULL' THEN 2 WHEN R.DELETE_RULE = 'SET DEFAULT' THEN 4 WHEN R.DELETE_RULE = 'SET RESTRICT' THEN 1 WHEN R.DELETE_RULE = 'SET NO ACTION' THEN 3 ELSE 3 END AS DELETE_RULE, A.CONSTRAINT_NAME AS FK_NAME, 'PRIMARY' AS PK_NAME, 7 AS DEFERRABILITY FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE A JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE D ON (D.TABLE_SCHEMA=A.REFERENCED_TABLE_SCHEMA AND D.TABLE_NAME=A.REFERENCED_TABLE_NAME AND D.COLUMN_NAME=A.REFERENCED_COLUMN_NAME) JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R ON (R.CONSTRAINT_NAME = A.CONSTRAINT_NAME AND R.TABLE_NAME = A.TABLE_NAME AND R.CONSTRAINT_SCHEMA = A.TABLE_SCHEMA) WHERE D.CONSTRAINT_NAME IS NOT NULL AND A.TABLE_SCHEMA = 'tpch'AND A.TABLE_NAME = 'lineitem' ORDER BY FKTABLE_CAT, FKTABLE_NAME, KEY_SEQ, PKTABLE_NAME;
-#
-#  plan: |
-#
-#    MemSort(sort="FKTABLE_CAT ASC,FKTABLE_NAME ASC,KEY_SEQ ASC,PKTABLE_NAME ASC")
-#      Project(PKTABLE_CAT="REFERENCED_TABLE_SCHEMA", PKTABLE_SCHEM="null", PKTABLE_NAME="REFERENCED_TABLE_NAME", PKCOLUMN_NAME="REFERENCED_COLUMN_NAME", FKTABLE_CAT="TABLE_SCHEMA", FKTABLE_SCHEM="null", FKTABLE_NAME="TABLE_NAME", FKCOLUMN_NAME="COLUMN_NAME", KEY_SEQ="ORDINAL_POSITION", UPDATE_RULE="CASE(=($31, 'CASCADE'), 0, =($31, 'SET NULL'), 2, =($31, 'SET DEFAULT'), 4, =($31, 'SET RESTRICT'), 1, =($31, 'SET NO ACTION'), 3, 3)", DELETE_RULE="CASE(=($32, 'CASCADE'), 0, =($32, 'SET NULL'), 2, =($32, 'SET DEFAULT'), 4, =($32, 'SET RESTRICT'), 1, =($32, 'SET NO ACTION'), 3, 3)", FK_NAME="CONSTRAINT_NAME", PK_NAME="'PRIMARY'", DEFERRABILITY="7")
-#        HashJoin(condition="CONSTRAINT_NAME = CONSTRAINT_NAME", type="inner")
-#          HashJoin(condition="REFERENCED_TABLE_NAME = TABLE_NAME AND REFERENCED_COLUMN_NAME = COLUMN_NAME AND TABLE_SCHEMA = REFERENCED_TABLE_SCHEMA", type="inner")
-#            Filter(condition="TABLE_NAME = 'lineitem' AND TABLE_SCHEMA = 'tpch'")
-#              VirtualView(virtualViewType="KEY_COLUMN_USAGE")
-#            Filter(condition="IS NOT NULL(CONSTRAINT_NAME)")
-#              VirtualView(virtualViewType="KEY_COLUMN_USAGE")
-#          Filter(condition="TABLE_NAME = 'lineitem' AND CONSTRAINT_SCHEMA = 'tpch'")
-#            VirtualView(virtualViewType="REFERENTIAL_CONSTRAINTS")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0`, `test_hash_tb1`.`id` as `id1`, `test_hash_tb1`.`name` as `name1`, `test_hash_tb1`.`create_time` as `create_time1` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) inner join `test_hash_tb` as `test_hash_tb1` on ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) and (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
 
 -
   sql: |
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testBasicJoinPlan.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testBasicJoinPlan.yml
index 1cad4daac..30991820a 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testBasicJoinPlan.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testBasicJoinPlan.yml
@@ -5,13 +5,16 @@
     JOIN single_c c ON a.id=b.id and c.id = a.int_col1;
 
   plan: |
+
     logicalview(tables="optest_0000.single_a,single_b,single_c", sql="select 1 from (`single_a` as `a`, `single_b` as `b`) inner join `single_c` as `c` on ((`a`.`id` = `b`.`id`) and (`c`.`id` = `a`.`int_col1`))")
+
 -
   sql: |
     SELECT 1 FROM 
        single_a a join single_b b
     JOIN single_c c ON a.id=b.id and c.id = a.int_col1;
   plan: |
+
     logicalview(tables="optest_0000.single_a,single_b,single_c", sql="select 1 from `single_a` as `a` inner join `single_b` as `b` inner join `single_c` as `c` on ((`a`.`id` = `b`.`id`) and (`c`.`id` = `a`.`int_col1`))")
 
 -
@@ -21,21 +24,27 @@
     JOIN single_d d on d.id = a.int_col1;
 
   plan: |
+
     logicalview(tables="optest_0000.single_a,single_b,single_c,single_d", sql="select 1 from (`single_a` as `a`, `single_b` as `b`) left join `single_c` as `c` on (`a`.`id` = `c`.`id`) inner join `single_d` as `d` on (`d`.`id` = `a`.`int_col1`)")
+
 -
   sql: |
     SELECT 1 FROM 
       single_a a left join single_b b ON a.id=b.id 
     JOIN single_c c on c.id = a.int_col1;
   plan: |
+
     logicalview(tables="optest_0000.single_a,single_b,single_c", sql="select 1 from `single_a` as `a` left join `single_b` as `b` on (`a`.`id` = `b`.`id`) inner join `single_c` as `c` on (`c`.`id` = `a`.`int_col1`)")
+
 -
   sql: |
     SELECT 1 FROM 
        (single_a a, single_b b)
     left JOIN (single_c c, single_d d) ON a.id=b.id and c.id = a.int_col1;
   plan: |
+
     logicalview(tables="optest_0000.single_a,single_b,single_c,single_d", sql="select 1 from (`single_a` as `a`, `single_b` as `b`) left join (`single_c` as `c`, `single_d` as `d`) on ((`a`.`id` = `b`.`id`) and (`c`.`id` = `a`.`int_col1`))")
+
 -
   sql: |
     
@@ -44,22 +53,26 @@
     left JOIN (single_c c left join single_d d on c.int_col1 = d.int_col2) ON a.id=b.id and c.id = a.int_col1;
 
   plan: |
+
     logicalview(tables="optest_0000.single_a,single_b,single_c,single_d", sql="select 1 from ((select `single_a`.`id`, `single_a`.`int_col1`, `single_a`.`int_col2`, `single_a`.`int_col3`, `single_a`.`int_col4` from `single_a` as `single_a` where (1 = 1)) as `a`, (select `single_b`.`id`, `single_b`.`int_col1`, `single_b`.`int_col2`, `single_b`.`int_col3`, `single_b`.`int_col4` from `single_b` as `single_b`) as `b`) left join (`single_c` as `c` left join `single_d` as `d` on (`c`.`int_col1` = `d`.`int_col2`)) on ((`a`.`id` = `b`.`id`) and (`c`.`id` = `a`.`int_col1`))")
+
 -
   sql: |
     select * from test_hash_tb a join test_hash_tb b where a.id=b.id and a.name="xx";
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON ((`test_hash_tb`.`name` = 'xx') AND (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`name` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
 
 -
   sql: |
     select * from test_hash_tb a join test_hash_tb b where a.id=b.id and a.id="xx";
 
   plan: |
-    phytableoperation(tables="optest_0000.[test_hash_tb, test_hash_tb]", sql="select `a`.`id`, `a`.`name`, `a`.`create_time`, `b`.`id`, `b`.`name`, `b`.`create_time` from ? as `a` inner join ? as `b` where ((`a`.`id` = `b`.`id`) and (`a`.`id` = 'xx'))")
+
+    gather(concurrent=true)
+      logicalview(tables="optest_0000.test_hash_tb", sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`id` = 'xx') and (`test_hash_tb0`.`id` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
 
 -
   sql: |
@@ -67,8 +80,8 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON ((`test_hash_tb`.`name` = 'xx') AND (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`name` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
 
 -
   sql: |
@@ -76,22 +89,26 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON ((`test_hash_tb`.`name` = 'xx') AND (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`name` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
 
 -
   sql: |
     select * from test_hash_tb a join test_Hash_tb b on a.id=b.id where a.name="xx";
 
   plan: |
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb,test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_Hash_tb0`.`id` AS `id0`, `test_Hash_tb0`.`name` AS `name0`, `test_Hash_tb0`.`create_time` AS `create_time0` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_Hash_tb` AS `test_Hash_tb0` ON ((`test_hash_tb`.`name` = 'xx') AND (`test_hash_tb`.`id` = `test_Hash_tb0`.`id`))")
+
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb,test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`name` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
+
 -
   sql: |
     select * from test_hash_tb a join test_hash_tb b on a.id=b.id where a.id="xx";
 
   plan: |
-    phytableoperation(tables="optest_0000.[test_hash_tb, test_hash_tb]", sql="select `a`.`id`, `a`.`name`, `a`.`create_time`, `b`.`id`, `b`.`name`, `b`.`create_time` from ? as `a` inner join ? as `b` on (`a`.`id` = `b`.`id`) where (`a`.`id` = 'xx')")
+
+    gather(concurrent=true)
+      logicalview(tables="optest_0000.test_hash_tb", sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`id` = 'xx') and (`test_hash_tb0`.`id` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
 
 -
   sql: |
@@ -118,10 +135,10 @@
 
   plan: |
 
-    HashAgg(count(*)="SUM(count(*))")
-      BKAJoin(condition="id = id0", type="inner")
-        HashAgg(group="id0", count(*)="SUM(count(*))")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].test_hash_tb,test_broadcast", shardCount=4, sql="SELECT `test_broadcast`.`id` AS `id0`, COUNT(*) AS `count(*)` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_broadcast` AS `test_broadcast` ON (`test_hash_tb`.`name` = `test_broadcast`.`name`) GROUP BY `test_broadcast`.`id`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb2", shardCount=4, sql="SELECT `id` FROM `test_hash_tb2` AS `test_hash_tb2` WHERE (`id` IN (...))")
+    hashagg(count(*)="sum(count(*))")
+      bkajoin(condition="id = id0", type="inner")
+        hashagg(group="id0", count(*)="sum(count(*))")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].test_hash_tb,test_broadcast", shardcount=4, sql="select `test_broadcast`.`id` as `id0`, count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` inner join `test_broadcast` as `test_broadcast` on (`test_hash_tb`.`name` = `test_broadcast`.`name`) group by `test_broadcast`.`id`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb2", shardcount=4, sql="select `id` from `test_hash_tb2` as `test_hash_tb2` force index(`primary`) where (`id` in (...))")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testImplicitMultiJoinPlan.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testImplicitMultiJoinPlan.yml
index 3d9e1125c..153a8f7fe 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testImplicitMultiJoinPlan.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testImplicitMultiJoinPlan.yml
@@ -4,8 +4,8 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)")
 
 -
   sql: |
@@ -13,8 +13,8 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0`, `test_hash_tb1`.`id` AS `id1`, `test_hash_tb1`.`name` AS `name1`, `test_hash_tb1`.`create_time` AS `create_time1` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) INNER JOIN `test_hash_tb` AS `test_hash_tb1` ON ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) AND (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0`, `test_hash_tb1`.`id` as `id1`, `test_hash_tb1`.`name` as `name1`, `test_hash_tb1`.`create_time` as `create_time1` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) inner join `test_hash_tb` as `test_hash_tb1` on ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) and (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
 
 -
   sql: |
@@ -22,8 +22,8 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0`, `test_hash_tb1`.`id` AS `id1`, `test_hash_tb1`.`name` AS `name1`, `test_hash_tb1`.`create_time` AS `create_time1` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) INNER JOIN `test_hash_tb` AS `test_hash_tb1` ON ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) AND (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0`, `test_hash_tb1`.`id` as `id1`, `test_hash_tb1`.`name` as `name1`, `test_hash_tb1`.`create_time` as `create_time1` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) inner join `test_hash_tb` as `test_hash_tb1` on ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) and (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
 
 -
   sql: |
@@ -44,6 +44,7 @@
       and t2.id=t5.id
 
   plan: |
+
     gather(concurrent=true)
       logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0`, `test_hash_tb1`.`id` as `id1`, `test_hash_tb1`.`name` as `name1`, `test_hash_tb1`.`create_time` as `create_time1`, `test_hash_tb2`.`id` as `id2`, `test_hash_tb2`.`name` as `name2`, `test_hash_tb2`.`create_time` as `create_time2`, `test_hash_tb5`.`id` as `id5`, `test_hash_tb5`.`name` as `name5`, `test_hash_tb5`.`create_time` as `create_time5`, `test_hash_tb3`.`id` as `id3`, `test_hash_tb3`.`name` as `name3`, `test_hash_tb3`.`create_time` as `create_time3`, `test_hash_tb4`.`id` as `id4`, `test_hash_tb4`.`name` as `name4`, `test_hash_tb4`.`create_time` as `create_time4` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) inner join `test_hash_tb` as `test_hash_tb1` on (`test_hash_tb`.`id` = `test_hash_tb1`.`id`) inner join `test_hash_tb` as `test_hash_tb2` on (`test_hash_tb1`.`id` = `test_hash_tb2`.`id`) inner join `test_hash_tb` as `test_hash_tb3` on ((`test_hash_tb1`.`id` = `test_hash_tb3`.`id`) and (`test_hash_tb2`.`id` = `test_hash_tb3`.`id`)) inner join `test_hash_tb` as `test_hash_tb4` on ((`test_hash_tb1`.`id` = `test_hash_tb4`.`id`) and (`test_hash_tb2`.`id` = `test_hash_tb4`.`id`) and (`test_hash_tb3`.`id` = `test_hash_tb4`.`id`)) inner join `test_hash_tb` as `test_hash_tb5` on (`test_hash_tb0`.`id` = `test_hash_tb5`.`id`)")
 
@@ -67,6 +68,7 @@
 
 
   plan: |
+
     project(id="id", name="name", create_time="create_time", id0="id0", name0="name0", create_time0="create_time0", id1="id1", name1="name1", create_time1="create_time1", id2="id2", name2="name2", create_time2="create_time2", id5="id5", name5="name5", create_time5="create_time5", id3="id3", name3="name3", create_time3="create_time3", id4="id4", name4="name4", create_time4="create_time4")
       nljoin(condition="true", type="inner")
         gather(concurrent=true)
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testJoinWithLimitAndOrderBy.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testJoinWithLimitAndOrderBy.yml
index 302665029..6f1408f5d 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testJoinWithLimitAndOrderBy.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testJoinWithLimitAndOrderBy.yml
@@ -10,11 +10,11 @@
 
   plan: |
 
-    HashJoin(condition="name = name", type="inner")
-      MergeSort(sort="id ASC")
-        LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` ORDER BY `id`")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb`")
+    hashjoin(condition="name = name", type="inner")
+      mergesort(sort="id asc")
+        logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) order by `id`")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb`")
 
 -
   sql: |
@@ -22,12 +22,12 @@
 
   plan: |
 
-    Limit(offset=0, fetch=10)
-      HashJoin(condition="name = name", type="inner")
-        MergeSort(sort="id ASC")
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` ORDER BY `id`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb`")
+    limit(offset=0, fetch=10)
+      hashjoin(condition="name = name", type="inner")
+        mergesort(sort="id asc")
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) order by `id`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb`")
 
 -
   sql: |
@@ -35,12 +35,12 @@
 
   plan: |
 
-    Limit(offset=5, fetch=10)
-      HashJoin(condition="name = name", type="inner")
-        MergeSort(sort="id ASC")
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` ORDER BY `id`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb`")
+    limit(offset=5, fetch=10)
+      hashjoin(condition="name = name", type="inner")
+        mergesort(sort="id asc")
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) order by `id`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb`")
 
 -
   sql: |
@@ -49,8 +49,8 @@
 
   plan: |
 
-    MergeSort(sort="id ASC", offset=0, fetch=10)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) ORDER BY `test_hash_tb`.`id` LIMIT 10")
+    mergesort(sort="id asc", offset=0, fetch=10)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) order by `test_hash_tb`.`id` limit 10")
 
 -
   sql: |
@@ -58,8 +58,8 @@
 
   plan: |
 
-    MergeSort(sort="name ASC", offset=0, fetch=10)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) ORDER BY `test_hash_tb`.`name` LIMIT 10")
+    mergesort(sort="name asc", offset=0, fetch=10)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) order by `test_hash_tb`.`name` limit 10")
 
 -
   sql: |
@@ -67,8 +67,8 @@
 
   plan: |
 
-    MergeSort(sort="name0 ASC", offset=0, fetch=10)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) ORDER BY `test_hash_tb0`.`name` LIMIT 10")
+    mergesort(sort="name0 asc", offset=0, fetch=10)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) order by `test_hash_tb0`.`name` limit 10")
 
 -
   sql: |
@@ -89,32 +89,34 @@
 
   plan: |
 
-    TopN(sort="name ASC", offset=0, fetch=10)
-      HashJoin(condition="name = name", type="right")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb`")
+    topn(sort="name asc", offset=0, fetch=10)
+      hashjoin(condition="name = name", type="right")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb`")
 
 -
   sql: |
     select * from test_hash_tb t1 left join test_hash_tb t2 on t1.name=t2.name order by t1.id limit 10
 
   plan: |
+
     limit(offset=0, fetch=10)
       hashjoin(condition="name = name", type="left")
         mergesort(sort="id asc", fetch=10)
-          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` order by `id` limit 10")
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) order by `id` limit 10")
         gather(concurrent=true)
           logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb`")
+
 -
   sql: |
     select * from test_hash_tb t1 left join test_hash_tb t2 on t1.name=t2.name and t1.id=t2.id order by t1.id limit 10
 
   plan: |
 
-    MergeSort(sort="id ASC", offset=0, fetch=10)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0` FROM `test_hash_tb` AS `test_hash_tb` LEFT JOIN `test_hash_tb` AS `test_hash_tb0` ON ((`test_hash_tb`.`name` = `test_hash_tb0`.`name`) AND (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)) ORDER BY `test_hash_tb`.`id` LIMIT 10")
+    mergesort(sort="id asc", offset=0, fetch=10)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`name` = `test_hash_tb0`.`name`) and (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)) order by `test_hash_tb`.`id` limit 10")
 
 -
   sql: |
@@ -123,12 +125,12 @@
 
   plan: |
 
-    Project(id="id0", name="name0", create_time="create_time0", id0="id", name0="name", create_time0="create_time")
-      HashJoin(condition="name = name", type="inner")
-        MergeSort(sort="id ASC")
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` ORDER BY `id`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb`")
+    project(id="id0", name="name0", create_time="create_time0", id0="id", name0="name", create_time0="create_time")
+      hashjoin(condition="name = name", type="inner")
+        mergesort(sort="id asc")
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) order by `id`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb`")
 
 -
   sql: |
@@ -140,7 +142,7 @@
       project(id="id0", name="name0", create_time="create_time0", id0="id", name0="name", create_time0="create_time")
         hashjoin(condition="name = name", type="inner")
           mergesort(sort="id asc")
-            logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` order by `id`")
+            logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) order by `id`")
           gather(concurrent=true)
             logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb`")
 
@@ -150,12 +152,12 @@
 
   plan: |
 
-    HashAgg(group="name")
-      HashJoin(condition="name = name", type="inner")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `name` FROM `test_hash_tb` AS `test_hash_tb`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `name` FROM `test_hash_tb` AS `test_hash_tb`")
+    hashagg(group="name")
+      hashjoin(condition="name = name", type="inner")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `name` from `test_hash_tb` as `test_hash_tb`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `name` from `test_hash_tb` as `test_hash_tb`")
 
 -
   sql: |
@@ -171,14 +173,13 @@
 
   plan: |
 
-    Project(min(t2.id)="min(t2.id)")
-      HashAgg(group="create_time,name0", min(t2.id)="MIN(id)")
-        HashJoin(condition="name = name", type="inner")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb`")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name` FROM `test_hash_tb` AS `test_hash_tb`")
-
+    project(min(t2.id)="min(t2.id)")
+      hashagg(group="create_time,name0", min(t2.id)="min(id)")
+        hashjoin(condition="name = name", type="inner")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `name`, `create_time` from `test_hash_tb` as `test_hash_tb`")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name` from `test_hash_tb` as `test_hash_tb`")
 
 -
   sql: |
@@ -193,9 +194,10 @@
        t1.name in (2134, 123100) and t1.int_col1!=1243 and t1.int_col2!=1243 and t1.int_col3!=1243 and t1.int_col4!=1243
 
   plan: |
+
     project(1="1")
       hashjoin(condition="name = name", type="inner")
         gather(concurrent=true)
           logicalview(tables="[0000-0003].test_hash_tb4", shardcount=4, sql="select `name` from `test_hash_tb4` as `test_hash_tb4` where ((`name` in(2134, 123100)) and (`int_col1` <> 1243) and (`int_col2` <> 1243) and (`int_col3` <> 1243) and (`int_col4` <> 1243))")
         gather(concurrent=true)
-          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `name` from `test_hash_tb` as `test_hash_tb` where (`name` in(2134, 123100))")
\ No newline at end of file
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `name` from `test_hash_tb` as `test_hash_tb` where (`name` in(2134, 123100))")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testNullGeneratingJoin.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testNullGeneratingJoin.yml
index 32dbd64ee..8317443d1 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testNullGeneratingJoin.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinPlanTest.testNullGeneratingJoin.yml
@@ -1,82 +1,98 @@
 - sql: |
     /*+TDDL:cmd_extra(PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD=100000000)*/select count(*) from test_hash_tb a left join test_hash_tb b on a.id=b.id group by b.id;
   plan: |
+
     project(count(*)="count(*)")
       hashagg(group="id0", count(*)="sum(count(*))")
         gather(concurrent=true)
           logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb0`.`id` as `id0`, count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) group by `test_hash_tb0`.`id`")
+
 - sql: |
     /*+TDDL:cmd_extra(PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD=100000000)*/select count(*) from test_hash_tb a right join test_hash_tb b on a.id=b.id group by b.id;
   plan: |
+
     gather(concurrent=true)
       logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` right join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) group by `test_hash_tb0`.`id`")
+
 - sql: |
     /*+TDDL:cmd_extra(PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD=100000000)*/select count(*) from test_hash_tb a join test_hash_tb b on a.id=b.id group by b.id;
 
   plan: |
+
     gather(concurrent=true)
       logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) group by `test_hash_tb0`.`id`")
-- sql: |
-    select count(*) from test_hash_tb a left join test_hash_tb b on a.id=b.id group by b.id;
-  plan: |
-    project(count(*)="count(*)")
-      hashagg(group="id0", count(*)="count()")
-        gather(concurrent=true)
-          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb0`.`id` as `id0` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)")
+
 - sql: |
     /*+TDDL:cmd_extra(PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD=100000000)*/select count(a.id) from test_hash_tb a left join test_hash_tb b on a.id=b.id group by b.id;
   plan: |
+
     project(count(a.id)="count(a.id)")
       hashagg(group="id0", count(a.id)="sum(count(a.id))")
         gather(concurrent=true)
           logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb0`.`id` as `id0`, count(*) as `count(a.id)` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) group by `test_hash_tb0`.`id`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_outer_join_reorder=false)*/ select count(*) from test_hash_tb a left join test_hash_tb2 b on a.id=b.id left join test_broadcast c on b.id = c.id;
   plan: |
+
     hashagg(count(*)="sum(count(*))")
       gather(concurrent=true)
         logicalview(tables="[0000-0003].test_hash_tb,test_hash_tb2,test_broadcast", shardcount=4, sql="select count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb2` as `test_hash_tb2` on (`test_hash_tb`.`id` = `test_hash_tb2`.`id`) left join `test_broadcast` as `test_broadcast` on (`test_hash_tb2`.`id` = `test_broadcast`.`id`)")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_outer_join_reorder=false)*/ select count(*) from test_hash_tb a left join test_hash_tb2 b on a.id=b.id left join test_hash_tb c on a.id = c.id;
   plan: |
+
     hashagg(count(*)="sum(count(*))")
       gather(concurrent=true)
         logicalview(tables="[0000-0003].test_hash_tb,test_hash_tb2", shardcount=4, sql="select count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb2` as `test_hash_tb2` on (`test_hash_tb`.`id` = `test_hash_tb2`.`id`) left join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_outer_join_reorder=false)*/ select count(*) from test_hash_tb a left join test_hash_tb2 b on a.id=b.id left join test_hash_tb c on b.id = c.id;
   plan: |
+
     hashagg(count(*)="sum(count(*))")
       gather(concurrent=true)
         logicalview(tables="[0000-0003].test_hash_tb,test_hash_tb2", shardcount=4, sql="select count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb2` as `test_hash_tb2` on (`test_hash_tb`.`id` = `test_hash_tb2`.`id`) left join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb2`.`id` = `test_hash_tb0`.`id`)")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_outer_join_reorder=false PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD=100000000)*/ select count(*) from test_hash_tb a left join test_hash_tb2 b on a.id=b.id left join test_hash_tb c on b.id = c.id group by b.id;
   plan: |
+
     project(count(*)="count(*)")
       hashagg(group="id0", count(*)="sum(count(*))")
         gather(concurrent=true)
           logicalview(tables="[0000-0003].test_hash_tb,test_hash_tb2", shardcount=4, sql="select `test_hash_tb2`.`id` as `id0`, count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb2` as `test_hash_tb2` on (`test_hash_tb`.`id` = `test_hash_tb2`.`id`) left join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb2`.`id` = `test_hash_tb0`.`id`) group by `test_hash_tb2`.`id`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_outer_join_reorder=false PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD=100000000)*/ select count(*) from test_hash_tb a left join test_hash_tb2 b on a.id=b.id left join test_hash_tb c on b.id = c.id group by c.id;
   plan: |
+
     project(count(*)="count(*)")
       hashagg(group="id1", count(*)="sum(count(*))")
         gather(concurrent=true)
           logicalview(tables="[0000-0003].test_hash_tb,test_hash_tb2", shardcount=4, sql="select `test_hash_tb0`.`id` as `id1`, count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb2` as `test_hash_tb2` on (`test_hash_tb`.`id` = `test_hash_tb2`.`id`) left join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb2`.`id` = `test_hash_tb0`.`id`) group by `test_hash_tb0`.`id`")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_outer_join_reorder=false)*/ select count(*) from test_hash_tb a left join test_hash_tb b on a.id=b.id left join test_hash_tb2 c on b.id = c.id;
   plan: |
+
     hashagg(count(*)="sum(count(*))")
       gather(concurrent=true)
         logicalview(tables="[0000-0003].test_hash_tb,test_hash_tb2", shardcount=4, sql="select count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) left join `test_hash_tb2` as `test_hash_tb2` on (`test_hash_tb0`.`id` = `test_hash_tb2`.`id`)")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_outer_join_reorder=false)*/ select count(*) from test_hash_tb a left join test_broadcast b on a.id=b.id left join test_hash_tb c on b.id = c.id;
   plan: |
+
     hashagg(count(*)="sum(count(*))")
       gather(concurrent=true)
         logicalview(tables="[0000-0003].test_hash_tb,test_broadcast", shardcount=4, sql="select count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` left join `test_broadcast` as `test_broadcast` on (`test_hash_tb`.`id` = `test_broadcast`.`id`) left join `test_hash_tb` as `test_hash_tb0` on (`test_broadcast`.`id` = `test_hash_tb0`.`id`)")
+
 - sql: |
     /*+TDDL:cmd_extra(enable_outer_join_reorder=false)*/ select count(*) from test_broadcast a left join test_hash_tb b on a.id=b.id left join test_hash_tb c on b.id = c.id;
   plan: |
+
     hashagg(count(*)="count()")
       hashjoin(condition="id0 = id", type="left")
         hashjoin(condition="id = id", type="left")
@@ -84,4 +100,4 @@
           gather(concurrent=true)
             logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id` from `test_hash_tb` as `test_hash_tb`")
         gather(concurrent=true)
-          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id` from `test_hash_tb` as `test_hash_tb`")
\ No newline at end of file
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id` from `test_hash_tb` as `test_hash_tb`")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinTypeSimplifyTest.testJoinTypeSimplify.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinTypeSimplifyTest.testJoinTypeSimplify.yml
index 133050277..6fbc9cbd2 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinTypeSimplifyTest.testJoinTypeSimplify.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/JoinTypeSimplifyTest.testJoinTypeSimplify.yml
@@ -4,9 +4,9 @@
 
   plan: |
 
-    HashJoin(condition="id = id", type="inner")
-      LogicalView(tables="optest_0002.test_hash_tb", sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` WHERE (`id` = ?)")
-      LogicalView(tables="optest_0000.test_hash_single", sql="SELECT `id`, `name`, `create_time` FROM `test_hash_single` AS `test_hash_single` WHERE (`id` = ?)")
+    hashjoin(condition="id = id", type="inner")
+      logicalview(tables="optest_0002.test_hash_tb", sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where (`id` = ?)")
+      logicalview(tables="optest_0000.test_hash_single", sql="select `id`, `name`, `create_time` from `test_hash_single` as `test_hash_single` force index(`primary`) where (`id` = ?)")
 
 -
   sql: |
@@ -14,15 +14,16 @@
 
   plan: |
 
-    HashJoin(condition="id = id", type="left")
-      LogicalView(tables="optest_0002.test_hash_tb", sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` WHERE (`id` = ?)")
-      LogicalView(tables="optest_0000.test_hash_single", sql="SELECT `id`, `name`, `create_time` FROM `test_hash_single` AS `test_hash_single` WHERE (`id` = ?)")
+    hashjoin(condition="id = id", type="left")
+      logicalview(tables="optest_0002.test_hash_tb", sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where (`id` = ?)")
+      logicalview(tables="optest_0000.test_hash_single", sql="select `id`, `name`, `create_time` from `test_hash_single` as `test_hash_single` force index(`primary`) where (`id` = ?)")
 
 -
   sql: |
     select a.id from test_hash_tb a left join test_hash_broadcast b on a.id=b.id where b.id=2 limit 5,10;
 
   plan: |
+
     phytableoperation(tables="optest_0002.[test_hash_tb, test_hash_broadcast]", sql="select `a`.`id` as `id` from ? as `a` left join ? as `b` on (`a`.`id` = `b`.`id`) where (`b`.`id` = ?) limit ? offset ?", params="5,2,10")
 
 -
@@ -39,10 +40,10 @@
 
   plan: |
 
-    HashJoin(condition="id = id AND id = ?0", type="left")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb`")
-      LogicalView(tables="optest_0000.test_hash_single", sql="SELECT `id`, `name`, `create_time` FROM `test_hash_single` AS `test_hash_single`")
+    hashjoin(condition="id = id and id = ?0", type="left")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb`")
+      logicalview(tables="optest_0000.test_hash_single", sql="select `id`, `name`, `create_time` from `test_hash_single` as `test_hash_single`")
 
 -
   sql: |
@@ -50,10 +51,10 @@
 
   plan: |
 
-    HashJoin(condition="id = id", type="left")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb`")
-      LogicalView(tables="optest_0000.test_hash_single", sql="SELECT `id`, `name`, `create_time` FROM `test_hash_single` AS `test_hash_single` WHERE (`id` = ?)")
+    hashjoin(condition="id = id", type="left")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb`")
+      logicalview(tables="optest_0000.test_hash_single", sql="select `id`, `name`, `create_time` from `test_hash_single` as `test_hash_single` force index(`primary`) where (`id` = ?)")
 
 -
   sql: |
@@ -61,28 +62,33 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb,test_hash_tb2", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb2`.`id` AS `id0`, `test_hash_tb2`.`name` AS `name0`, `test_hash_tb2`.`create_time` AS `create_time0` FROM `test_hash_tb` AS `test_hash_tb` LEFT JOIN `test_hash_tb2` AS `test_hash_tb2` ON ((`test_hash_tb`.`id` = `test_hash_tb2`.`id`) AND (`test_hash_tb`.`id` = ?))")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb,test_hash_tb2", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb2`.`id` as `id0`, `test_hash_tb2`.`name` as `name0`, `test_hash_tb2`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb2` as `test_hash_tb2` on ((`test_hash_tb`.`id` = `test_hash_tb2`.`id`) and (`test_hash_tb`.`id` = ?))")
 
 -
   sql: |
     select * from test_hash_tb a left join test_hash_tb2 b on a.id=b.id where a.id=2;
 
   plan: |
-    phytableoperation(tables="optest_0002.[test_hash_tb, test_hash_tb2]", sql="select `a`.`id`, `a`.`name`, `a`.`create_time`, `b`.`id`, `b`.`name`, `b`.`create_time` from ? as `a` left join ? as `b` on (`a`.`id` = `b`.`id`) where (`a`.`id` = ?)", params="2")
+
+    gather(concurrent=true)
+      logicalview(tables="optest_0002.test_hash_tb,test_hash_tb2", sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb2`.`id` as `id0`, `test_hash_tb2`.`name` as `name0`, `test_hash_tb2`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb2` as `test_hash_tb2` on (`test_hash_tb`.`id` = `test_hash_tb2`.`id`) where (`test_hash_tb`.`id` = ?)")
 
 -
   sql: |
     select * from test_hash_tb a left join test_hash_tb2 b on a.id=b.id where b.id=2;
 
   plan: |
-    phytableoperation(tables="optest_0002.[test_hash_tb, test_hash_tb2]", sql="select `a`.`id`, `a`.`name`, `a`.`create_time`, `b`.`id`, `b`.`name`, `b`.`create_time` from ? as `a` left join ? as `b` on (`a`.`id` = `b`.`id`) where (`b`.`id` = ?)", params="2")
+
+    gather(concurrent=true)
+      logicalview(tables="optest_0002.test_hash_tb,test_hash_tb2", sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb2`.`id` as `id0`, `test_hash_tb2`.`name` as `name0`, `test_hash_tb2`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb2` as `test_hash_tb2` on ((`test_hash_tb`.`id` = ?) and (`test_hash_tb2`.`id` = ?) and (`test_hash_tb`.`id` = `test_hash_tb2`.`id`))")
 
 -
   sql: |
     select a.id from test_hash_tb a left join test_hash_tb2 b on a.id=b.id where a.id=2 limit 5,10;
 
   plan: |
+
     phytableoperation(tables="optest_0002.[test_hash_tb, test_hash_tb2]", sql="select `a`.`id` as `id` from ? as `a` left join ? as `b` on (`a`.`id` = `b`.`id`) where (`a`.`id` = ?) limit ? offset ?", params="5,2,10")
 
 -
@@ -91,8 +97,8 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb,test_hash_tb2", shardCount=4, sql="SELECT `test_hash_tb`.`id` FROM `test_hash_tb` AS `test_hash_tb` LEFT JOIN `test_hash_tb2` AS `test_hash_tb2` ON (`test_hash_tb`.`id` = `test_hash_tb2`.`id`) WHERE (`test_hash_tb`.`name` = ?)")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb,test_hash_tb2", shardcount=4, sql="select `test_hash_tb`.`id` from `test_hash_tb` as `test_hash_tb` left join `test_hash_tb2` as `test_hash_tb2` on (`test_hash_tb`.`id` = `test_hash_tb2`.`id`) where (`test_hash_tb`.`name` = ?)")
 
 -
   sql: |
@@ -100,6 +106,5 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb0`.`name` AS `id` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) WHERE (`test_hash_tb0`.`name` = ?)")
-
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb0`.`name` as `id` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) where (`test_hash_tb0`.`name` = ?)")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/SortJoinTransposeTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/SortJoinTransposeTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/SortJoinTransposeTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/SubqueryJoinPlanTest.testSubqueryJoinPlan.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/SubqueryJoinPlanTest.testSubqueryJoinPlan.yml
index a34079b3f..5d5c43c99 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/SubqueryJoinPlanTest.testSubqueryJoinPlan.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/joinplan/SubqueryJoinPlanTest.testSubqueryJoinPlan.yml
@@ -1,70 +1,72 @@
--        
+-
   sql: |
     select * from (select * from test_hash_tb ) t1 join (select * from test_hash_tb) t2 on t1.id=t2.id
-    
+
   plan: |
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)")
 
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)")
 
--        
+-
   sql: |
     select * from (select * from test_hash_tb ) t1 join (select * from test_hash_tb) t2 on t1.id=t2.id join (select * from test_hash_tb) t3 on t1.id=t3.id
-    
+
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0`, `test_hash_tb1`.`id` AS `id1`, `test_hash_tb1`.`name` AS `name1`, `test_hash_tb1`.`create_time` AS `create_time1` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) INNER JOIN `test_hash_tb` AS `test_hash_tb1` ON ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) AND (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0`, `test_hash_tb1`.`id` as `id1`, `test_hash_tb1`.`name` as `name1`, `test_hash_tb1`.`create_time` as `create_time1` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) inner join `test_hash_tb` as `test_hash_tb1` on ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) and (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
 
--        
+-
   sql: |
     select * from (select * from test_hash_tb ) t1 join (select * from test_hash_tb) t2 on t1.id=t2.id join (select * from test_hash_tb) t3 on t2.id=t3.id
-    
+
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0`, `test_hash_tb1`.`id` AS `id1`, `test_hash_tb1`.`name` AS `name1`, `test_hash_tb1`.`create_time` AS `create_time1` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) INNER JOIN `test_hash_tb` AS `test_hash_tb1` ON ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) AND (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0`, `test_hash_tb1`.`id` as `id1`, `test_hash_tb1`.`name` as `name1`, `test_hash_tb1`.`create_time` as `create_time1` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) inner join `test_hash_tb` as `test_hash_tb1` on ((`test_hash_tb`.`id` = `test_hash_tb1`.`id`) and (`test_hash_tb0`.`id` = `test_hash_tb1`.`id`))")
 
 -
   sql: |
     select * from (select * from test_hash_tb t1 where t1.id = 3) t1 join test_hash_tb t2 on t1.id=t2.id;
 
   plan: |
-    phytableoperation(tables="optest_0003.[test_hash_tb, test_hash_tb]", sql="select `t1`.`id`, `t1`.`name`, `t1`.`create_time`, `t2`.`id`, `t2`.`name`, `t2`.`create_time` from (select `t1`.`id`, `t1`.`name`, `t1`.`create_time` from ? as `t1` where (`t1`.`id` = 3)) as `t1` inner join ? as `t2` on (`t1`.`id` = `t2`.`id`)")
+
+    gather(concurrent=true)
+      logicalview(tables="optest_0003.test_hash_tb", sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`) where (`test_hash_tb`.`id` = 3)")
 
 -
   sql: |
     select * from (select * from test_hash_tb t1 order by id limit 10) t1 join test_hash_tb t2 on t1.id=t2.id;
-    
+
   plan: |
 
-    BKAJoin(condition="id = id", type="inner")
-      MergeSort(sort="id ASC", offset=0, fetch=10)
-        LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` ORDER BY `id` LIMIT 10")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` WHERE (`id` IN (...))")
+    bkajoin(condition="id = id", type="inner")
+      mergesort(sort="id asc", offset=0, fetch=10)
+        logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) order by `id` limit 10")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where (`id` in (...))")
 
 -
   sql: |
     select * from (select * from test_hash_tb t1) t1 join (select * from test_hash_tb t2 order by id limit 10) t2 on t1.id=t2.id;
-    
+
   plan: |
 
-    Project(id0="id0", name0="name0", create_time0="create_time0", id="id", name="name", create_time="create_time")
-      BKAJoin(condition="id = id", type="inner")
-        MergeSort(sort="id ASC", offset=0, fetch=10)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` ORDER BY `id` LIMIT 10")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` WHERE (`id` IN (...))")
+    project(id0="id0", name0="name0", create_time0="create_time0", id="id", name="name", create_time="create_time")
+      bkajoin(condition="id = id", type="inner")
+        mergesort(sort="id asc", offset=0, fetch=10)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) order by `id` limit 10")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where (`id` in (...))")
+
 -
   sql: |
     select * from (select * from test_hash_tb t1) t1 join (select distinct id from test_hash_tb t2 ) t2 on t1.id=t2.id;
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)")
-
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on (`test_hash_tb`.`id` = `test_hash_tb0`.`id`)")
 
 -
   sql: |
@@ -72,49 +74,56 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name`, `test_hash_tb0`.`create_time`, `t`.`count(*)`, `t`.`id` FROM (SELECT `id`, COUNT(*) AS `count(*)` FROM `test_hash_tb` AS `test_hash_tb` GROUP BY `id`) AS `t` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON (`t`.`id` = `test_hash_tb0`.`id`)")
-
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name`, `test_hash_tb0`.`create_time`, `t`.`count(*)`, `t`.`id` from (select `id`, count(*) as `count(*)` from `test_hash_tb` as `test_hash_tb` group by `id`) as `t` inner join `test_hash_tb` as `test_hash_tb0` on (`t`.`id` = `test_hash_tb0`.`id`)")
 
 -
   sql: |
     select create_time, (select id from test_hash_tb2 a where a.name = b.name) as id from test_hash_tb b where b.id = 1 and b.create_time > 0;
 
   plan: |
-    Project(create_time="create_time", id="id0", cor=[$cor0])
-      SemiBKAJoin(condition="name = name", type="left")
-        LogicalView(tables="optest_0001.test_hash_tb", sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` WHERE ((`id` = 1) AND (`create_time` > 0))")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb2", shardCount=4, sql="SELECT `id`, `name` FROM `test_hash_tb2` AS `test_hash_tb2` WHERE (`name` IN (...))")
+
+    project(create_time="create_time", id="id0", cor=[$cor0])
+      semibkajoin(condition="name = name", type="left")
+        logicalview(tables="optest_0001.test_hash_tb", sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where ((`id` = 1) and (`create_time` > 0))")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb2", shardcount=4, sql="select `id`, `name` from `test_hash_tb2` as `test_hash_tb2` where (`name` in (...))")
 
 -
   sql: |
     select create_time, (select id from test_hash_tb2 a where a.name = b.name and a.create_time=b.create_time and a.id=b.id) as id from test_hash_tb b where b.id = 1 and b.create_time > 0;
   plan: |
+
     gather(concurrent=true)
       logicalview(tables="[0000-0003].test_hash_tb2,test_hash_tb", shardcount=4, sql="select `create_time`, (((select `id` from `test_hash_tb2` as `test_hash_tb2` where ((`name` = `t`.`name`) and (`create_time` = `t`.`create_time`) and (`id` = `t`.`id`))))) as `id` from (select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` where ((`id` = 1) and (`create_time` > 0))) as `t`")
+
 -
   sql: |
     select create_time, (select id from test_tb4 a where a.name = b.name and a.name1=b.name1 and a.name2=b.name2) as id from test_tb4 b where b.id = 1 and b.create_time > 0;
   plan: |
+
     project(create_time="create_time", id="id0", cor=[$cor2])
       semibkajoin(condition="name = name and name1 = name1 and name2 = name2", type="left")
-        logicalview(tables="optest_0001.test_tb4", sql="select `id`, `name`, `name1`, `name2`, `create_time` from `test_tb4` as `test_tb4` where ((`id` = 1) and (`create_time` > 0))")
+        logicalview(tables="optest_0001.test_tb4", sql="select `id`, `name`, `name1`, `name2`, `create_time` from `test_tb4` as `test_tb4` force index(`primary`) where ((`id` = 1) and (`create_time` > 0))")
         gather(concurrent=true)
           logicalview(tables="[0000-0003].test_tb4", shardcount=4, sql="select `id`, `name`, `name1`, `name2` from `test_tb4` as `test_tb4` where (((`name`, `name1`, `name2`)) in (...))")
+
 -
   sql: |
     select create_time, (select id from test_tb4 a where a.name2 = b.name2 and a.name1=b.name1 and a.name=b.name and a.create_time=b.create_time) as id from test_tb4 b where b.id = 1 ;
   plan: |
-    project(create_time="create_time", id="id0", cor=[$cor])
+
+    project(create_time="create_time", id="id0", cor=[$cor1])
       semibkajoin(condition="name2 = name2 and name1 = name1 and name = name and create_time = create_time", type="left")
-        logicalview(tables="optest_0001.test_tb4", sql="select `id`, `name`, `name1`, `name2`, `create_time` from `test_tb4` as `test_tb4` where (`id` = 1)")
+        logicalview(tables="optest_0001.test_tb4", sql="select `id`, `name`, `name1`, `name2`, `create_time` from `test_tb4` as `test_tb4` force index(`primary`) where (`id` = 1)")
         gather(concurrent=true)
           logicalview(tables="[0000-0003].test_tb4", shardcount=4, sql="select `id`, `name`, `name1`, `name2`, `create_time` from `test_tb4` as `test_tb4` where (((`name2`, `name1`, `name`, `create_time`)) in (...))")
+
 -
   sql: |
     select create_time from test_tb4 b where b.id >all (select id from test_tb4 a where a.name2 = b.name2 and a.name1=b.name1 and a.name=b.name and a.create_time=b.create_time) ;
   plan: |
+
     project(create_time="create_time")
       seminljoin(condition="id <= id and name2 = name2 and name1 = name1 and name = name and create_time = create_time", type="anti")
         gather(concurrent=true)
@@ -139,14 +148,15 @@
        WHERE g.name = a.name)
     FROM single_tbl2 a
   plan: |
-    project(expr$0="$f0", (((select 1 from single_tbl2 as g where (g.name = a.name))))="1", cor=[$cor])
+
+    project(expr$0="$f0", (((select 1 from single_tbl2 as g where (g.name = a.name))))="1", cor=[$cor0])
       semihashjoin(condition="name = name", type="left", build="inner")
-        correlateapply(cor=$cor, leftconditions=[], opkind=null, type=left)
+        correlateapply(cor=$cor0, leftconditions=[], opkind=null, type=left)
           logicalview(tables="optest_0000.single_tbl2", sql="select `id`, `bid`, `name` from `single_tbl2` as `single_tbl2`")
           project($f0="apply_boolean or apply_boolean0")
-            correlateapply(cor=$cor, leftconditions=[], opkind=null, type=semi)
+            correlateapply(cor=$cor3, leftconditions=[], opkind=null, type=semi)
               project(apply_boolean="apply_boolean")
-                correlateapply(cor=$cor, leftconditions=[], opkind=null, type=semi)
+                correlateapply(cor=$cor3, leftconditions=[], opkind=null, type=semi)
                   values(table="dual")
                   logicalview(tables="optest_0000.single_tbl", sql="select `id`, `bid`, `name` from `single_tbl` as `single_tbl` where (`id` = `id`)")
               logicalview(tables="optest_0000.single_tbl1", sql="select `id`, `bid`, `name` from `single_tbl1` as `single_tbl1` where (`bid` = `bid`)")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.ddl.yml
deleted file mode 100644
index b283003a6..000000000
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/ColumnarCBOPlanTest.ddl.yml
+++ /dev/null
@@ -1,298 +0,0 @@
-t_shard_id1:
-  CREATE TABLE `t_shard_id1` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  )  ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 4;
-
-t_shard_id2:
-  CREATE TABLE `t_shard_id2` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`),
-  KEY `auto_shard_key_ID_0` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 4;
-
-t_shard_id3:
-  CREATE TABLE `t_shard_id3` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`),
-  KEY `auto_shard_key_ID_0` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 4;
-
-t_shard_id4:
-  CREATE TABLE `t_shard_id4` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`),
-  KEY `auto_shard_key_ID_0` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 4;
-
-t1:
-  CREATE TABLE `t1` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 4;
-
-t2:
-  CREATE TABLE `t2` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 8;
-
-t3:
-  CREATE TABLE `t3` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 12;
-
-t4:
-  CREATE TABLE `t4` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 16;
-
-t5:
-  CREATE TABLE `t5` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 20;
-
-t6:
-  CREATE TABLE `t6` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 24;
-
-t7:
-  CREATE TABLE `t7` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 28;
-
-t8:
-  CREATE TABLE `t8` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 32;
-
-
-l1:
-  CREATE TABLE `l1` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 5;
-
-l2:
-  CREATE TABLE `l2` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 8;
-
-l3:
-  CREATE TABLE `l3` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 12;
-
-l4:
-  CREATE TABLE `l4` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 16;
-
-l5:
-  CREATE TABLE `l5` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 20;
-
-l6:
-  CREATE TABLE `l6` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 24;
-
-l7:
-  CREATE TABLE `l7` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 28;
-
-l8:
-  CREATE TABLE `l8` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 32;
-
-l9:
-  CREATE TABLE `l9` (
-  `id` int(11) NOT NULL,
-  `name` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 36;
-
-fact:
-  CREATE TABLE `fact` (
-  `id` int(11) NOT NULL AUTO_INCREMENT BY GROUP,
-  `id1` int(11) DEFAULT NULL,
-  `id2` int(11) DEFAULT NULL,
-  `id3` int(11) DEFAULT NULL,
-  `id4` int(11) DEFAULT NULL,
-  `id5` int(11) DEFAULT NULL,
-  `id6` int(11) DEFAULT NULL,
-  `id7` int(11) DEFAULT NULL,
-  `id8` int(11) DEFAULT NULL,
-  `id9` int(11) DEFAULT NULL,
-  `id10` int(11) DEFAULT NULL,
-  PRIMARY KEY (`id`)
-  ) ENGINE='LOCAL_DISK' AUTO_INCREMENT=1501888 DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 40;
-
-v1:
-  CREATE TABLE `v1` (
-  `id` int(11) NOT NULL,
-  `v1_k` int(11) NOT NULL,
-  `name1` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 5;
-
-v2:
-  CREATE TABLE `v2` (
-  `id` int(11) NOT NULL,
-  `v2_k` int(11) NOT NULL,
-  `name2` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 8;
-
-v3:
-  CREATE TABLE `v3` (
-  `id` int(11) NOT NULL,
-  `v3_k` int(11) NOT NULL,
-  `name3` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 12;
-
-v4:
-  CREATE TABLE `v4` (
-  `id` int(11) NOT NULL,
-  `v4_k` int(11) NOT NULL,
-  `name4` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(`ID`) partitions 16;
-
-S1:
-  CREATE TABLE `s1` (
-  `id` int(11) NOT NULL,
-  `v4_k` int(11) NOT NULL,
-  `name4` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by hash(id) partitions 16;
-
-S2:
-  CREATE TABLE `s2` (
-  `id` int(11) NOT NULL,
-  `v4_k` int(11) NOT NULL,
-  `name4` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by HASH(YEAR(create_time)) partitions 16;
-
-S3:
-  CREATE TABLE `s3` (
-  `id` int(11) NOT NULL,
-  `v4_k` int(11) NOT NULL,
-  `name4` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by hash(id,v4_k) partitions 16;
-
-S4:
-  CREATE TABLE `s4` (
-  `id` int(11) NOT NULL,
-  `v4_k` int(11) NOT NULL,
-  `name4` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(id,v4_k) partitions 16;
-
-S5:
-  CREATE TABLE `s5` (
-  `id` int(11) NOT NULL,
-  `v4_k` int(11) NOT NULL,
-  `name4` varchar(30) DEFAULT NULL,
-  `create_time` datetime DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  KEY `auto_shard_key_ID` (`id`)
-  ) ENGINE='LOCAL_DISK' DEFAULT CHARSET=utf8 partition by key(v4_k,id) partitions 16;
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/OssExchangeRemoveTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/OssExchangeRemoveTest.yml
index e486ae7e7..2de7beab6 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/OssExchangeRemoveTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/OssExchangeRemoveTest.yml
@@ -217,11 +217,11 @@ SQL:
         topn(sort="revenue desc", offset=0, fetch=?4)
           exchange(distribution=single, collation=[7 desc-nulls-last])
             topn(sort="revenue desc", fetch=+(?4, 0))
-              hashagg(group="c_custkey,n_name", c_name="__first_value(c_name)", c_acctbal="__first_value(c_acctbal)", c_phone="__first_value(c_phone)", c_address="__first_value(c_address)", c_comment="__first_value(c_comment)", revenue="sum(__*__)")
+              hashagg(group="c_custkey,n_name", c_name="__first_value(c_name)", c_acctbal="__first_value(c_acctbal)", c_phone="__first_value(c_phone)", c_address="__first_value(c_address)", c_comment="__first_value(c_comment)", revenue="sum(__*__)", partition=[local])
                 project(c_custkey="c_custkey", c_name="c_name", c_address="c_address", c_nationkey="c_nationkey", c_phone="c_phone", c_acctbal="c_acctbal", c_comment="c_comment", n_nationkey="n_nationkey", n_name="n_name", o_orderkey="o_orderkey", o_custkey="o_custkey", l_orderkey="l_orderkey", __*__="l_extendedprice * ?0 - l_discount")
                   hashjoin(condition="n_nationkey = c_nationkey", type="inner")
                     hashjoin(condition="o_custkey = c_custkey", type="inner")
-                      osstablescan(tables="customer[p1,p2,p3,...p192]", shardcount=192, partition=[remote], sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_comment` from `customer` as `customer`")
+                      osstablescan(tables="customer[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_comment` from `customer` as `customer`")
                       exchange(distribution=hash[1]192, collation=[])
                         project(o_orderkey="o_orderkey", o_custkey="o_custkey", l_orderkey="l_orderkey", l_extendedprice="l_extendedprice", l_discount="l_discount")
                           hashjoin(condition="l_orderkey = o_orderkey", type="inner", partition=[local])
@@ -310,32 +310,37 @@ SQL:
               osstablescan(tables="supplier[p1,p2,p3,...p192]", shardcount=192, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_address`, `s_phone` from `supplier` as `supplier`")
               project(supplier_no="supplier_no", total_revenue="total_revenue")
                 hashjoin(condition="max(total_revenue) = total_revenue", type="inner")
-                  hashagg(group="supplier_no", total_revenue="sum($f1)")
+                  hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
                     exchange(distribution=hash[0]192, collation=[])
-                      project(supplier_no="l_suppkey", $f1="l_extendedprice * ?0 - l_discount")
-                        osstablescan(tables="lineitem[p1,p2,p3,...p192]", shardcount=192, sql="select `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(?, interval '3' month)) and (`l_shipdate` >= ?))")
+                      partialhashagg(group="supplier_no", total_revenue="sum($f1)")
+                        project(supplier_no="l_suppkey", $f1="l_extendedprice * ?0 - l_discount")
+                          osstablescan(tables="lineitem[p1,p2,p3,...p192]", shardcount=192, sql="select `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(?, interval '3' month)) and (`l_shipdate` >= ?))")
                   exchange(distribution=broadcast, collation=[])
                     hashagg(max(total_revenue)="max(max(total_revenue))")
                       exchange(distribution=single, collation=[])
                         partialhashagg(max(total_revenue)="max(total_revenue)")
-                          hashagg(group="supplier_no", total_revenue="sum($f1)")
+                          hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
                             exchange(distribution=hash[0]192, collation=[])
-                              project(supplier_no="l_suppkey", $f1="l_extendedprice * ?3 - l_discount")
-                                osstablescan(tables="lineitem[p1,p2,p3,...p192]", shardcount=192, sql="select `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(?, interval '3' month)) and (`l_shipdate` >= ?))")
+                              partialhashagg(group="supplier_no", total_revenue="sum($f1)")
+                                project(supplier_no="l_suppkey", $f1="l_extendedprice * ?3 - l_discount")
+                                  osstablescan(tables="lineitem[p1,p2,p3,...p192]", shardcount=192, sql="select `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(?, interval '3' month)) and (`l_shipdate` >= ?))")
   # q16
   - sql: |
       select   p_brand,        p_type,         p_size,         count(distinct ps_suppkey) as supplier_cnt from         partsupp,       part where      p_partkey = ps_partkey  and p_brand <> 'Brand#15'       and p_type not like 'STANDARD BRUSHED%'         and p_size in (5, 29, 4, 49, 30, 42, 33, 39)    and ps_suppkey not in (                 select                  s_suppkey               from                    supplier                where                   s_comment like '%Customer%Complaints%'  ) group by      p_brand,        p_type,         p_size order by         supplier_cnt desc,      p_brand,        p_type,         p_size;
     plan: |
       exchange(distribution=single, collation=[3 desc-nulls-last, 0 asc-nulls-first, 1 asc-nulls-first, 2 asc-nulls-first])
         memsort(sort="supplier_cnt desc,p_brand asc,p_type asc,p_size asc")
-          hashagg(group="p_brand,p_type,p_size", supplier_cnt="count(distinct ps_suppkey)")
-            exchange(distribution=hash[4]192, collation=[])
-              semihashjoin(condition="ps_suppkey = s_suppkey", type="anti", build="inner")
-                hashjoin(condition="p_partkey = ps_partkey", type="inner", partition=[local])
-                  osstablescan(tables="partsupp[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey` from `partsupp` as `partsupp`")
-                  osstablescan(tables="part[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `p_partkey`, `p_brand`, `p_type`, `p_size` from `part` as `part` where ((`p_size` in(?)) and (`p_brand` <> ?) and (`p_type` not like ?))")
-                exchange(distribution=broadcast, collation=[])
-                  osstablescan(tables="supplier[p1,p2,p3,...p192]", shardcount=192, sql="select `s_suppkey` from `supplier` as `supplier` where (`s_comment` like ?)")
+          hashagg(group="p_brand,p_type,p_size", supplier_cnt="count(ps_suppkey)")
+            hashagg(group="p_brand,p_type,p_size,ps_suppkey")
+              exchange(distribution=hash[2]192, collation=[])
+                project(p_brand="p_brand", p_type="p_type", p_size="p_size", ps_suppkey="ps_suppkey")
+                  partialhashagg(group="ps_suppkey,p_brand,p_type,p_size")
+                    semihashjoin(condition="ps_suppkey = s_suppkey", type="anti", build="inner")
+                      hashjoin(condition="p_partkey = ps_partkey", type="inner", partition=[local])
+                        osstablescan(tables="partsupp[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey` from `partsupp` as `partsupp`")
+                        osstablescan(tables="part[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `p_partkey`, `p_brand`, `p_type`, `p_size` from `part` as `part` where ((`p_size` in(?)) and (`p_brand` <> ?) and (`p_type` not like ?))")
+                      exchange(distribution=broadcast, collation=[])
+                        osstablescan(tables="supplier[p1,p2,p3,...p192]", shardcount=192, sql="select `s_suppkey` from `supplier` as `supplier` where (`s_comment` like ?)")
   # q17
   - sql: |
       /*+TDDL:cmd_extra(ENABLE_BRANCH_AND_BOUND_OPTIMIZATION=false)*/select   sum(l_extendedprice) / 7.0 as avg_yearly from   lineitem,       part where      p_partkey = l_partkey   and p_brand = 'Brand#51'        and p_container = 'SM JAR'      and l_quantity < (              select                  0.2 * avg(l_quantity)           from                    lineitem                where                   l_partkey = p_partkey   );
@@ -399,22 +404,24 @@ SQL:
               project(s_name="s_name", s_address="s_address", s_nationkey="s_nationkey")
                 semihashjoin(condition="s_suppkey = ps_suppkey", type="semi", build="inner")
                   osstablescan(tables="supplier[p1,p2,p3,...p192]", shardcount=192, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_address`, `s_nationkey` from `supplier` as `supplier`")
-                  project(ps_suppkey="ps_suppkey")
-                    exchange(distribution=hash[4]192, collation=[])
+                  exchange(distribution=hash[0]192, collation=[])
+                    project(ps_suppkey="ps_suppkey")
                       hashjoin(condition="l_partkey = ps_partkey and l_suppkey = ps_suppkey and ps_availqty > ?1 * $f2", type="inner")
-                        hashagg(group="l_partkey,l_suppkey", $f2="sum(l_quantity)")
+                        hashagg(group="l_partkey,l_suppkey", $f2="sum($f2)")
                           exchange(distribution=hash[0]192, collation=[])
-                            semihashjoin(condition="l_partkey = ps_partkey and l_suppkey = ps_suppkey", type="semi", build="inner")
-                              osstablescan(tables="lineitem[p1,p2,p3,...p192]", shardcount=192, partition=[remote], sql="select `l_partkey`, `l_suppkey`, `l_quantity` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(?, interval '1' year)) and (`l_shipdate` >= ?))")
-                              exchange(distribution=broadcast, collation=[])
-                                semihashjoin(condition="ps_partkey = p_partkey", type="semi", build="inner", partition=[local])
-                                  osstablescan(tables="partsupp[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp` as `partsupp`")
-                                  osstablescan(tables="part[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `p_partkey` from `part` as `part` where (`p_name` like ?)")
+                            partialhashagg(group="l_partkey,l_suppkey", $f2="sum(l_quantity)")
+                              semihashjoin(condition="l_partkey = ps_partkey and l_suppkey = ps_suppkey", type="semi", build="inner")
+                                osstablescan(tables="lineitem[p1,p2,p3,...p192]", shardcount=192, partition=[remote], sql="select `l_partkey`, `l_suppkey`, `l_quantity` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(?, interval '1' year)) and (`l_shipdate` >= ?))")
+                                exchange(distribution=broadcast, collation=[])
+                                  semihashjoin(condition="ps_partkey = p_partkey", type="semi", build="inner", partition=[local])
+                                    osstablescan(tables="partsupp[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp` as `partsupp`")
+                                    osstablescan(tables="part[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `p_partkey` from `part` as `part` where (`p_name` like ?)")
                         semihashjoin(condition="ps_partkey = p_partkey", type="semi", build="inner", partition=[local])
                           osstablescan(tables="partsupp[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp` as `partsupp`")
                           osstablescan(tables="part[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `p_partkey` from `part` as `part` where (`p_name` like ?)")
               exchange(distribution=broadcast, collation=[])
                 osstablescan(tables="nation", shardcount=0, sql="select `n_nationkey` from `nation` as `nation` where (`n_name` = ?)")
+
   # q21
   - sql: |
       select   s_name,         count(*) as numwait from        supplier,       lineitem l1,    orders,         nation where    s_suppkey = l1.l_suppkey        and o_orderkey = l1.l_orderkey  and o_orderstatus = 'F'         and l1.l_receiptdate > l1.l_commitdate  and exists (            select                  *               from                    lineitem l2             where                   l2.l_orderkey = l1.l_orderkey                   and l2.l_suppkey <> l1.l_suppkey        )       and not exists (                select                  *               from                    lineitem l3             where                   l3.l_orderkey = l1.l_orderkey                   and l3.l_suppkey <> l1.l_suppkey                        and l3.l_receiptdate > l3.l_commitdate  )       and s_nationkey = n_nationkey   and n_name = 'ARGENTINA' group by       s_name order by         numwait desc,   s_name limit 100;
@@ -445,20 +452,21 @@ SQL:
     plan: |
       exchange(distribution=single, collation=[0 asc-nulls-first])
         memsort(sort="cntrycode asc")
-          hashagg(group="cntrycode", numcust="count()", totacctbal="sum(c_acctbal)")
+          hashagg(group="cntrycode", numcust="sum(numcust)", totacctbal="sum(totacctbal)")
             exchange(distribution=hash[0]192, collation=[])
-              project(cntrycode="substring(c_phone, ?0, ?1)", c_acctbal="c_acctbal")
-                semihashjoin(condition="o_custkey = c_custkey", type="anti", build="outer")
-                  project($f0="$f0", $f1="$f1", c_custkey="c_custkey", c_phone="c_phone", c_acctbal="c_acctbal")
-                    nljoin(condition="c_acctbal > $f0 / $f1", type="inner")
-                      osstablescan(tables="customer[p1,p2,p3,...p192]", shardcount=192, partition=[remote], sql="select `c_custkey`, `c_phone`, `c_acctbal` from `customer` as `customer` where ((substring(`c_phone`, ?, ?)) in(?))")
-                      exchange(distribution=broadcast, collation=[])
-                        hashagg($f0="sum($f0)", $f1="sum($f1)")
-                          exchange(distribution=single, collation=[])
-                            partialhashagg($f0="sum(c_acctbal)", $f1="count()")
-                              osstablescan(tables="customer[p1,p2,p3,...p192]", shardcount=192, sql="select `c_acctbal` from `customer` as `customer` where (((substring(`c_phone`, ?, ?)) in(?)) and (`c_acctbal` > ?))")
-                  exchange(distribution=hash[0]192, collation=[])
-                    osstablescan(tables="orders[p1,p2,p3,...p192]", shardcount=192, sql="select `o_custkey` from `orders` as `orders`")
+              partialhashagg(group="cntrycode", numcust="count()", totacctbal="sum(c_acctbal)")
+                project(cntrycode="substring(c_phone, ?0, ?1)", c_acctbal="c_acctbal")
+                  semihashjoin(condition="o_custkey = c_custkey", type="anti", build="outer")
+                    project($f0="$f0", $f1="$f1", c_custkey="c_custkey", c_phone="c_phone", c_acctbal="c_acctbal")
+                      nljoin(condition="c_acctbal > $f0 / $f1", type="inner")
+                        osstablescan(tables="customer[p1,p2,p3,...p192]", shardcount=192, partition=[remote], sql="select `c_custkey`, `c_phone`, `c_acctbal` from `customer` as `customer` where ((substring(`c_phone`, ?, ?)) in(?))")
+                        exchange(distribution=broadcast, collation=[])
+                          hashagg($f0="sum($f0)", $f1="sum($f1)")
+                            exchange(distribution=single, collation=[])
+                              partialhashagg($f0="sum(c_acctbal)", $f1="count()")
+                                osstablescan(tables="customer[p1,p2,p3,...p192]", shardcount=192, sql="select `c_acctbal` from `customer` as `customer` where (((substring(`c_phone`, ?, ?)) in(?)) and (`c_acctbal` > ?))")
+                    exchange(distribution=hash[0]192, collation=[])
+                      osstablescan(tables="orders[p1,p2,p3,...p192]", shardcount=192, sql="select `o_custkey` from `orders` as `orders`")
   - sql: |
       select         n_name from         customer,         orders,         nation where         c_custkey = o_custkey         and c_nationkey = n_nationkey         and o_orderdate >=  '1996-01-01'         and o_orderdate < '1997-01-01';
     plan: |
@@ -493,7 +501,40 @@ SQL:
       hashjoin(condition="p_partkey = l_orderkey", type="left", partition=[local])
         osstablescan(tables="lineitem[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_linenumber`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus`, `l_shipdate`, `l_commitdate`, `l_receiptdate`, `l_shipinstruct`, `l_shipmode`, `l_comment` from `lineitem` as `lineitem`")
         osstablescan(tables="part[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `p_partkey`, `p_name`, `p_mfgr`, `p_brand`, `p_type`, `p_size`, `p_container`, `p_retailprice`, `p_comment` from `part` as `part`")
-
+  - sql: |
+      /*+TDDL:cmd_extra(PARTIAL_AGG_SELECTIVITY_THRESHOLD=0)*/select   sum(l_extendedprice* (1 - l_discount)) as revenue from  lineitem,       part where      (               p_partkey = l_partkey           and p_brand = 'Brand#13'                and p_container in ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG')           and l_quantity >= 7 and l_quantity <= 7 + 10            and p_size between 1 and 5              and l_shipmode in ('AIR', 'AIR REG')            and l_shipinstruct = 'DELIVER IN PERSON'        )       or      (               p_partkey = l_partkey           and p_brand = 'Brand#15'                and p_container in ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK')                and l_quantity >= 18 and l_quantity <= 18 + 10          and p_size between 1 and 10             and l_shipmode in ('AIR', 'AIR REG')            and l_shipinstruct = 'DELIVER IN PERSON'        )       or      (               p_partkey = l_partkey           and p_brand = 'Brand#35'                and p_container in ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG')           and l_quantity >= 21 and l_quantity <= 21 + 10          and p_size between 1 and 15             and l_shipmode in ('AIR', 'AIR REG')            and l_shipinstruct = 'DELIVER IN PERSON'        );
+    plan: |
+      hashagg(revenue="sum(revenue)")
+        exchange(distribution=single, collation=[])
+          partialhashagg(revenue="sum(__*__)")
+            project(p_partkey="p_partkey", =="p_brand = ?1", in="p_container in row(?2)", between asymmetric="between asymmetric($8, ?6, ?7)", =4="p_brand = ?10", in5="p_container in row(?11)", between asymmetric6="between asymmetric($8, ?15, ?16)", =7="p_brand = ?19", in8="p_container in row(?20)", between asymmetric9="between asymmetric($8, ?24, ?25)", l_partkey="l_partkey", __*__="l_extendedprice * ?0 - l_discount", >=="l_quantity >= ?3", <=="l_quantity <= 17", in0="l_shipmode in row(?8)", =0="l_shipinstruct = ?9", >=6="l_quantity >= ?12", <=7="l_quantity <= 28", in80="l_shipmode in row(?17)", =9="l_shipinstruct = ?18", >=10="l_quantity >= ?21", <=11="l_quantity <= 31", in12="l_shipmode in row(?26)", =13="l_shipinstruct = ?27")
+              hashjoin(condition="p_partkey = l_partkey and ((p_partkey = l_partkey and p_brand = ?1 and p_container in row(?2) and l_quantity >= ?3 and l_quantity <= ?4 + ?5 and between asymmetric($8, ?6, ?7) and l_shipmode in row(?8) and l_shipinstruct = ?9) or (p_partkey = l_partkey and p_brand = ?10 and p_container in row(?11) and l_quantity >= ?12 and l_quantity <= ?13 + ?14 and between asymmetric($8, ?15, ?16) and l_shipmode in row(?17) and l_shipinstruct = ?18) or (p_partkey = l_partkey and p_brand = ?19 and p_container in row(?20) and l_quantity >= ?21 and l_quantity <= ?22 + ?23 and between asymmetric($8, ?24, ?25) and l_shipmode in row(?26) and l_shipinstruct = ?27))", type="inner")
+                osstablescan(tables="lineitem[p1,p2,p3,...p192]", shardcount=192, partition=[remote], sql="select `l_partkey`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_shipinstruct`, `l_shipmode` from `lineitem` as `lineitem` where (((`l_quantity` >= ?) and (`l_quantity` <= (? + ?)) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)) or ((`l_quantity` >= ?) and (`l_quantity` <= (? + ?)) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)) or ((`l_quantity` >= ?) and (`l_quantity` <= (? + ?)) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)))")
+                exchange(distribution=broadcast, collation=[])
+                  osstablescan(tables="part[p1,p2,p3,...p192]", shardcount=192, sql="select `p_partkey`, `p_brand`, `p_size`, `p_container` from `part` as `part` where (((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)) or ((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)) or ((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)))")
+  - sql: |
+      /*+TDDL:cmd_extra(ENABLE_PARTIAL_AGG=false)*/ select   l_shipmode,     sum(case                when o_orderpriority = '1-URGENT'                       or o_orderpriority = '2-HIGH'                   then 1          else 0  end) as high_line_count,        sum(case                when o_orderpriority <> '1-URGENT'                      and o_orderpriority <> '2-HIGH'                         then 1          else 0  end) as low_line_count from     orders,         lineitem where  o_orderkey = l_orderkey         and l_shipmode in ('AIR', 'REG AIR')    and l_commitdate < l_receiptdate        and l_shipdate < l_commitdate   and l_receiptdate >= '1993-01-01'       and l_receiptdate < '1993-01-01' + interval '1' year group by   l_shipmode order by     l_shipmode;
+    plan: |
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        memsort(sort="l_shipmode asc")
+          hashagg(group="l_shipmode", high_line_count="sum(case)", low_line_count="sum(case2)")
+            project(o_orderkey="o_orderkey", case="case(in($1, row(?0, ?1)), ?2, ?3)", case2="case(and(<>($1, ?4), <>($1, ?5)), ?6, ?7)", l_orderkey="l_orderkey", l_shipmode="l_shipmode")
+              exchange(distribution=hash[3]192, collation=[])
+                hashjoin(condition="l_orderkey = o_orderkey", type="inner", partition=[local])
+                  osstablescan(tables="orders[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `o_orderkey`, `o_orderpriority` from `orders` as `orders`")
+                  osstablescan(tables="lineitem[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `l_orderkey`, `l_shipmode` from `lineitem` as `lineitem` where ((`l_receiptdate` < date_add(?, interval '1' year)) and (`l_shipmode` in(?)) and (`l_commitdate` < `l_receiptdate`) and (`l_shipdate` < `l_commitdate`) and (`l_receiptdate` >= ?))")
+  - sql: |
+      /*+TDDL:cmd_extra(PARTIAL_AGG_SELECTIVITY_THRESHOLD=0)*/ select   l_shipmode,     sum(case                when o_orderpriority = '1-URGENT'                       or o_orderpriority = '2-HIGH'                   then 1          else 0  end) as high_line_count,        sum(case                when o_orderpriority <> '1-URGENT'                      and o_orderpriority <> '2-HIGH'                         then 1          else 0  end) as low_line_count from     orders,         lineitem where  o_orderkey = l_orderkey         and l_shipmode in ('AIR', 'REG AIR')    and l_commitdate < l_receiptdate        and l_shipdate < l_commitdate   and l_receiptdate >= '1993-01-01'       and l_receiptdate < '1993-01-01' + interval '1' year group by   l_shipmode order by     l_shipmode;
+    plan: |
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        memsort(sort="l_shipmode asc")
+          hashagg(group="l_shipmode", high_line_count="sum(high_line_count)", low_line_count="sum(low_line_count)")
+            exchange(distribution=hash[0]192, collation=[])
+              partialhashagg(group="l_shipmode", high_line_count="sum(case)", low_line_count="sum(case2)")
+                project(o_orderkey="o_orderkey", case="case(in($1, row(?0, ?1)), ?2, ?3)", case2="case(and(<>($1, ?4), <>($1, ?5)), ?6, ?7)", l_orderkey="l_orderkey", l_shipmode="l_shipmode")
+                  hashjoin(condition="l_orderkey = o_orderkey", type="inner", partition=[local])
+                    osstablescan(tables="orders[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `o_orderkey`, `o_orderpriority` from `orders` as `orders`")
+                    osstablescan(tables="lineitem[p1,p2,p3,...p192]", shardcount=192, partition=[local, remote], sql="select `l_orderkey`, `l_shipmode` from `lineitem` as `lineitem` where ((`l_receiptdate` < date_add(?, interval '1' year)) and (`l_shipmode` in(?)) and (`l_commitdate` < `l_receiptdate`) and (`l_shipdate` < `l_commitdate`) and (`l_receiptdate` >= ?))")
 DDL:
   customer:
     CREATE TABLE `customer` ( 	`c_custkey` int(11) NOT NULL, 	`c_name` varchar(25) NOT NULL, 	`c_address` varchar(40) NOT NULL, 	`c_nationkey` int(11) NOT NULL, 	`c_phone` varchar(15) NOT NULL, 	`c_acctbal` decimal(15, 2) NOT NULL, 	`c_mktsegment` varchar(10) NOT NULL, 	`c_comment` varchar(117) NOT NULL, 	PRIMARY KEY (`c_custkey`) ) ENGINE = 'LOCAL_DISK' DEFAULT CHARSET = latin1 PARTITION BY KEY (`c_custkey`) PARTITIONS 192;
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/Tpch1TColumnarModeTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/Tpch1TColumnarModeTest.yml
new file mode 100644
index 000000000..8e1963865
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/Tpch1TColumnarModeTest.yml
@@ -0,0 +1,1427 @@
+SQL:
+  - sql: |
+      select   l_returnflag,   l_linestatus,   sum(l_quantity) as sum_qty,     sum(l_extendedprice) as sum_base_price,         sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,      sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,    avg(l_quantity) as avg_qty,     avg(l_extendedprice) as avg_price,      avg(l_discount) as avg_disc,    count(*) as count_order from    lineitem where  l_shipdate <= '1998-12-01' - interval '118' day group by        l_returnflag,   l_linestatus order by   l_returnflag,   l_linestatus;
+    plan: |
+      project(l_returnflag="l_returnflag", l_linestatus="l_linestatus", sum_qty="sum_qty", sum_base_price="sum_base_price", sum_disc_price="sum_disc_price", sum_charge="sum_charge", avg_qty="sum_qty / $f6", avg_price="sum_base_price / $f6", avg_disc="$f7 / $f6", count_order="$f6")
+        exchange(distribution=single, collation=[0 asc-nulls-first, 1 asc-nulls-first])
+          memsort(sort="l_returnflag asc,l_linestatus asc")
+            hashagg(group="l_returnflag,l_linestatus", sum_qty="sum(sum_qty)", sum_base_price="sum(sum_base_price)", sum_disc_price="sum(sum_disc_price)", sum_charge="sum(sum_charge)", $f6="sum($f6)", $f7="sum($f7)")
+              exchange(distribution=hash[0]96, collation=[])
+                partialhashagg(group="l_returnflag,l_linestatus", sum_qty="sum(l_quantity)", sum_base_price="sum(l_extendedprice)", sum_disc_price="sum($f4)", sum_charge="sum($f5)", $f6="count()", $f7="sum(l_discount)")
+                  project(l_returnflag="l_returnflag", l_linestatus="l_linestatus", l_quantity="l_quantity", l_extendedprice="l_extendedprice", $f4="l_extendedprice * ?0 - l_discount", $f5="l_extendedprice * ?1 - l_discount * ?2 + l_tax", l_discount="l_discount")
+                    osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus` from `lineitem_col_index` as `lineitem_col_index` where (`l_shipdate` <= '1998-08-05')")
+  - sql: |
+      select   s_acctbal,      s_name,         n_name,         p_partkey,      p_mfgr,         s_address,      s_phone,        s_comment from  part,   supplier,       partsupp,       nation,         region where    p_partkey = ps_partkey  and s_suppkey = ps_suppkey      and p_size = 15         and p_type like '%STEEL'        and s_nationkey = n_nationkey   and n_regionkey = r_regionkey   and r_name = 'MIDDLE EAST'      and ps_supplycost = (           select                  min(ps_supplycost)              from                    partsupp,                       supplier,                       nation,                         region          where                   p_partkey = ps_partkey                  and s_suppkey = ps_suppkey                      and s_nationkey = n_nationkey                   and n_regionkey = r_regionkey                   and r_name = 'MIDDLE EAST'      ) order by      s_acctbal desc,         n_name,         s_name,         p_partkey limit 100;
+    plan: |
+      topn(sort="s_acctbal desc,n_name asc,s_name asc,p_partkey asc", offset=0, fetch=?4)
+        exchange(distribution=single, collation=[0 desc-nulls-last, 2 asc-nulls-first, 1 asc-nulls-first, 3 asc-nulls-first])
+          topn(sort="s_acctbal desc,n_name asc,s_name asc,p_partkey asc", fetch=+(?4, 0))
+            project(s_acctbal="s_acctbal", s_name="s_name", n_name="n_name", p_partkey="p_partkey", p_mfgr="p_mfgr", s_address="s_address", s_phone="s_phone", s_comment="s_comment")
+              hashjoin(condition="ps_partkey = ps_partkey and ps_supplycost = min(ps_supplycost)", type="inner")
+                hashagg(group="ps_partkey", min(ps_supplycost)="min(ps_supplycost)", partition=[local])
+                  hashjoin(condition="ps_suppkey = s_suppkey", type="inner")
+                    osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_supplycost` from `partsupp_col_index` as `partsupp_col_index`")
+                    exchange(distribution=broadcast, collation=[])
+                      hashjoin(condition="n_nationkey = s_nationkey", type="inner")
+                        osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
+                        exchange(distribution=broadcast, collation=[])
+                          hashjoin(condition="r_regionkey = n_regionkey", type="inner")
+                            osstablescan(tables="nation_col_index[p1]", partition=[remote], sql="select `n_nationkey`, `n_regionkey` from `nation_col_index` as `nation_col_index`")
+                            exchange(distribution=broadcast, collation=[])
+                              osstablescan(tables="region_col_index[p1]", sql="select `r_regionkey` from `region_col_index` as `region_col_index` where (`r_name` = ?)")
+                exchange(distribution=hash[8]96, collation=[])
+                  project(s_name="s_name", s_address="s_address", s_phone="s_phone", s_acctbal="s_acctbal", s_comment="s_comment", n_name="n_name", p_partkey="p_partkey", p_mfgr="p_mfgr", ps_partkey="ps_partkey", ps_supplycost="ps_supplycost")
+                    hashjoin(condition="s_nationkey = n_nationkey", type="inner")
+                      project(s_name="s_name", s_address="s_address", s_nationkey="s_nationkey", s_phone="s_phone", s_acctbal="s_acctbal", s_comment="s_comment", p_partkey="p_partkey", p_mfgr="p_mfgr", ps_partkey="ps_partkey", ps_supplycost="ps_supplycost")
+                        hashjoin(condition="ps_suppkey = s_suppkey", type="inner")
+                          osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_address`, `s_nationkey`, `s_phone`, `s_acctbal`, `s_comment` from `supplier_col_index` as `supplier_col_index`")
+                          exchange(distribution=hash[3]96, collation=[])
+                            project(p_partkey="p_partkey", p_mfgr="p_mfgr", ps_partkey="ps_partkey", ps_suppkey="ps_suppkey", ps_supplycost="ps_supplycost")
+                              hashjoin(condition="ps_partkey = p_partkey", type="inner", partition=[local])
+                                osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_supplycost` from `partsupp_col_index` as `partsupp_col_index`")
+                                osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey`, `p_mfgr` from `part_col_index` as `part_col_index` where ((`p_size` = ?) and (`p_type` like ?))")
+                      project(n_nationkey="n_nationkey", n_name="n_name")
+                        exchange(distribution=broadcast, collation=[])
+                          hashjoin(condition="n_regionkey = r_regionkey", type="inner")
+                            osstablescan(tables="nation_col_index[p1]", partition=[remote], sql="select `n_nationkey`, `n_name`, `n_regionkey` from `nation_col_index` as `nation_col_index`")
+                            exchange(distribution=broadcast, collation=[])
+                              osstablescan(tables="region_col_index[p1]", sql="select `r_regionkey` from `region_col_index` as `region_col_index` where (`r_name` = ?)")
+  - sql: |
+      select   l_orderkey,     sum(l_extendedprice * (1 - l_discount)) as revenue,     o_orderdate,    o_shippriority from     customer,       orders,         lineitem where  c_mktsegment = 'HOUSEHOLD'      and c_custkey = o_custkey       and l_orderkey = o_orderkey     and o_orderdate < '1995-03-29'  and l_shipdate > '1995-03-29' group by  l_orderkey,     o_orderdate,    o_shippriority order by         revenue desc,   o_orderdate limit 10;
+    plan: |
+      project(l_orderkey="l_orderkey", revenue="revenue", o_orderdate="o_orderdate", o_shippriority="o_shippriority")
+        topn(sort="revenue desc,o_orderdate asc", offset=0, fetch=?4)
+          exchange(distribution=single, collation=[3 desc-nulls-last, 0 asc-nulls-first])
+            topn(sort="revenue desc,o_orderdate asc", fetch=+(?4, 0))
+              hashagg(group="o_orderdate,o_shippriority,l_orderkey", revenue="sum(__*__)")
+                project(c_custkey="c_custkey", o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderdate="o_orderdate", o_shippriority="o_shippriority", l_orderkey="l_orderkey", __*__="l_extendedprice * ?0 - l_discount")
+                  hashjoin(condition="o_orderkey = l_orderkey", type="inner", partition=[local])
+                    osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where (`l_shipdate` > ?)")
+                    project(c_custkey="c_custkey", o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderdate="o_orderdate", o_shippriority="o_shippriority")
+                      hashjoin(condition="o_custkey = c_custkey", type="inner")
+                        osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey`, `o_orderdate`, `o_shippriority` from `orders_col_index` as `orders_col_index` where (`o_orderdate` < ?)")
+                        exchange(distribution=broadcast, collation=[])
+                          osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `c_custkey` from `customer_col_index` as `customer_col_index` where (`c_mktsegment` = ?)")
+  - sql: |
+      select   o_orderpriority,        count(*) as order_count from    orders where    o_orderdate >= '1997-05-01'     and o_orderdate < '1997-05-01' + interval '3' month     and exists (            select                  *               from                    lineitem                where                   l_orderkey = o_orderkey                         and l_commitdate < l_receiptdate        ) group by      o_orderpriority order by        o_orderpriority;
+    plan: |
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        memsort(sort="o_orderpriority asc")
+          hashagg(group="o_orderpriority", order_count="sum(order_count)")
+            exchange(distribution=hash[0]96, collation=[])
+              partialhashagg(group="o_orderpriority", order_count="count()")
+                semihashjoin(condition="l_orderkey = o_orderkey", type="semi", build="outer", partition=[local])
+                  osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_orderpriority` from `orders_col_index` as `orders_col_index` where ((`o_orderdate` >= ?) and (`o_orderdate` < '1997-08-01'))")
+                  osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey` from `lineitem_col_index` as `lineitem_col_index` where (`l_commitdate` < `l_receiptdate`)")
+  - sql: |
+      select   n_name,         sum(l_extendedprice * (1 - l_discount)) as revenue from         customer,       orders,         lineitem,       supplier,       nation,         region where    c_custkey = o_custkey   and l_orderkey = o_orderkey     and l_suppkey = s_suppkey       and c_nationkey = s_nationkey   and s_nationkey = n_nationkey   and n_regionkey = r_regionkey   and r_name = 'AMERICA'  and o_orderdate >= '1996-01-01'         and o_orderdate < '1996-01-01' + interval '1' year group by     n_name order by         revenue desc;
+    plan: |
+      exchange(distribution=single, collation=[1 desc-nulls-last])
+        memsort(sort="revenue desc")
+          hashagg(group="n_name", revenue="sum(revenue)")
+            exchange(distribution=hash[0]96, collation=[])
+              partialhashagg(group="n_name", revenue="sum(__*__)")
+                project(c_custkey="c_custkey", c_nationkey="c_nationkey", n_nationkey="n_nationkey", n_name="n_name", n_regionkey="n_regionkey", r_regionkey="r_regionkey", s_suppkey="s_suppkey", s_nationkey="s_nationkey", o_orderkey="o_orderkey", o_custkey="o_custkey", l_orderkey="l_orderkey", l_suppkey="l_suppkey", __*__="l_extendedprice * ?0 - l_discount")
+                  hashjoin(condition="l_suppkey = s_suppkey and n_nationkey = s_nationkey", type="inner")
+                    project(c_custkey="c_custkey", c_nationkey="c_nationkey", n_nationkey="n_nationkey", n_name="n_name", n_regionkey="n_regionkey", r_regionkey="r_regionkey", o_orderkey="o_orderkey", o_custkey="o_custkey", l_orderkey="l_orderkey", l_suppkey="l_suppkey", l_extendedprice="l_extendedprice", l_discount="l_discount")
+                      hashjoin(condition="l_orderkey = o_orderkey", type="inner")
+                        osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_orderkey`, `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index`")
+                        exchange(distribution=hash[6]96, collation=[])
+                          project(c_custkey="c_custkey", c_nationkey="c_nationkey", n_nationkey="n_nationkey", n_name="n_name", n_regionkey="n_regionkey", r_regionkey="r_regionkey", o_orderkey="o_orderkey", o_custkey="o_custkey")
+                            hashjoin(condition="o_custkey = c_custkey", type="inner")
+                              exchange(distribution=hash[1]96, collation=[])
+                                osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `o_orderkey`, `o_custkey` from `orders_col_index` as `orders_col_index` where ((`o_orderdate` >= ?) and (`o_orderdate` < '1997-01-01'))")
+                              hashjoin(condition="n_nationkey = c_nationkey", type="inner")
+                                osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_nationkey` from `customer_col_index` as `customer_col_index`")
+                                exchange(distribution=broadcast, collation=[])
+                                  hashjoin(condition="n_regionkey = r_regionkey", type="inner")
+                                    osstablescan(tables="nation_col_index[p1]", partition=[remote], sql="select `n_nationkey`, `n_name`, `n_regionkey` from `nation_col_index` as `nation_col_index`")
+                                    exchange(distribution=broadcast, collation=[])
+                                      osstablescan(tables="region_col_index[p1]", sql="select `r_regionkey` from `region_col_index` as `region_col_index` where (`r_name` = ?)")
+                    exchange(distribution=broadcast, collation=[])
+                      osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
+  - sql: |
+      select   sum(l_extendedprice * l_discount) as revenue from       lineitem where  l_shipdate >= '1996-01-01'      and l_shipdate < '1996-01-01' + interval '1' year       and l_discount between 0.09 - 0.01 and 0.09 + 0.01      and l_quantity < 24;
+    plan: |
+      hashagg(revenue="sum(revenue)")
+        exchange(distribution=single, collation=[])
+          partialhashagg(revenue="sum($f0)")
+            project($f0="l_extendedprice * l_discount")
+              osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where ((`l_discount` between '0.08' and '0.10') and (`l_shipdate` >= ?) and (`l_quantity` < ?) and (`l_shipdate` < '1997-01-01'))")
+  - sql: |
+      select   supp_nation,    cust_nation,    l_year,         sum(volume) as revenue from     (               select                  n1.n_name as supp_nation,                       n2.n_name as cust_nation,                       extract(year from l_shipdate) as l_year,                        l_extendedprice * (1 - l_discount) as volume            from                    supplier,                       lineitem,                       orders,                         customer,                       nation n1,                      nation n2               where                   s_suppkey = l_suppkey                   and o_orderkey = l_orderkey                     and c_custkey = o_custkey                       and s_nationkey = n1.n_nationkey                        and c_nationkey = n2.n_nationkey                        and (                           (n1.n_name = 'UNITED STATES' and n2.n_name = 'INDIA')                           or (n1.n_name = 'INDIA' and n2.n_name = 'UNITED STATES')                        )                       and l_shipdate between '1995-01-01' and '1996-12-31'    ) as shipping group by  supp_nation,    cust_nation,    l_year order by         supp_nation,    cust_nation,    l_year;
+    plan: |
+      exchange(distribution=single, collation=[0 asc-nulls-first, 1 asc-nulls-first, 2 asc-nulls-first])
+        memsort(sort="n_name asc,n_name0 asc,extract asc")
+          hashagg(group="n_name,n_name0,extract", revenue="sum(revenue)")
+            exchange(distribution=hash[0]96, collation=[])
+              partialhashagg(group="n_name,n_name0,extract", revenue="sum(__*__)")
+                project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", n_nationkey="n_nationkey", n_name="n_name", =="n_name = ?1", =3="n_name = ?3", n_nationkey0="n_nationkey0", n_name0="n_name0", =0="n_name0 = ?2", =30="n_name0 = ?4", c_custkey="c_custkey", c_nationkey="c_nationkey", l_orderkey="l_orderkey", l_suppkey="l_suppkey", extract="extract(year, l_shipdate)", __*__="l_extendedprice * ?0 - l_discount", o_orderkey="o_orderkey", o_custkey="o_custkey")
+                  hashjoin(condition="o_custkey = c_custkey and ((n_name = ?1 and n_name = ?2) or (n_name = ?3 and n_name = ?4))", type="inner")
+                    project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", n_nationkey="n_nationkey", n_name="n_name", l_orderkey="l_orderkey", l_suppkey="l_suppkey", l_extendedprice="l_extendedprice", l_discount="l_discount", l_shipdate="l_shipdate", o_orderkey="o_orderkey", o_custkey="o_custkey")
+                      exchange(distribution=hash[1]96, collation=[])
+                        hashjoin(condition="l_orderkey = o_orderkey", type="inner", partition=[local])
+                          osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey` from `orders_col_index` as `orders_col_index`")
+                          project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", n_nationkey="n_nationkey", n_name="n_name", l_orderkey="l_orderkey", l_suppkey="l_suppkey", l_extendedprice="l_extendedprice", l_discount="l_discount", l_shipdate="l_shipdate")
+                            hashjoin(condition="l_suppkey = s_suppkey", type="inner")
+                              osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_suppkey`, `l_extendedprice`, `l_discount`, `l_shipdate` from `lineitem_col_index` as `lineitem_col_index` where (`l_shipdate` between ? and ?)")
+                              exchange(distribution=broadcast, collation=[])
+                                hashjoin(condition="n_nationkey = s_nationkey", type="inner")
+                                  osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
+                                  exchange(distribution=broadcast, collation=[])
+                                    osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey`, `n_name` from `nation_col_index` as `nation_col_index` where ((`n_name` = ?) or (`n_name` = ?))")
+                    project(n_nationkey="n_nationkey", n_name="n_name", c_custkey="c_custkey", c_nationkey="c_nationkey")
+                      hashjoin(condition="n_nationkey = c_nationkey", type="inner")
+                        osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_nationkey` from `customer_col_index` as `customer_col_index`")
+                        exchange(distribution=broadcast, collation=[])
+                          osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey`, `n_name` from `nation_col_index` as `nation_col_index` where ((`n_name` = ?) or (`n_name` = ?))")
+  - sql: |
+      select   o_year,         sum(case                when nation = 'INDIA' then volume               else 0  end) / sum(volume) as mkt_share from    (               select                  extract(year from o_orderdate) as o_year,                       l_extendedprice * (1 - l_discount) as volume,                   n2.n_name as nation             from                    part,                   supplier,                       lineitem,                       orders,                         customer,                       nation n1,                      nation n2,                      region          where                   p_partkey = l_partkey                   and s_suppkey = l_suppkey                       and l_orderkey = o_orderkey                     and o_custkey = c_custkey                       and c_nationkey = n1.n_nationkey                        and n1.n_regionkey = r_regionkey                        and r_name = 'ASIA'                     and s_nationkey = n2.n_nationkey                        and o_orderdate between '1995-01-01' and '1996-12-31'                   and p_type = 'MEDIUM ANODIZED STEEL'    ) as all_nations group by       o_year order by         o_year;
+    plan: |
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        memsort(sort="o_year asc")
+          project(o_year="extract", mkt_share="$f1 / $f2")
+            hashagg(group="extract", $f1="sum($f1)", $f2="sum($f2)")
+              exchange(distribution=hash[0]96, collation=[])
+                partialhashagg(group="extract", $f1="sum(case)", $f2="sum(__*__)")
+                  project(l_partkey="l_partkey", extract="extract(year, o_orderdate)", case="case(=($7, ?0), *($2, -(?2, $3)), cast(?1):decimal(37, 4))", __*__="l_extendedprice * ?2 - l_discount", p_partkey="p_partkey")
+                    hashjoin(condition="s_suppkey = l_suppkey", type="inner")
+                      project(l_partkey="l_partkey", l_suppkey="l_suppkey", l_extendedprice="l_extendedprice", l_discount="l_discount", o_orderdate="o_orderdate", p_partkey="p_partkey")
+                        exchange(distribution=hash[7]96, collation=[])
+                          project(c_custkey="c_custkey", c_nationkey="c_nationkey", n_nationkey="n_nationkey", n_regionkey="n_regionkey", r_regionkey="r_regionkey", l_orderkey="l_orderkey", l_partkey="l_partkey", l_suppkey="l_suppkey", l_extendedprice="l_extendedprice", l_discount="l_discount", o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderdate="o_orderdate", p_partkey="p_partkey")
+                            hashjoin(condition="o_custkey = c_custkey", type="inner")
+                              project(l_orderkey="l_orderkey", l_partkey="l_partkey", l_suppkey="l_suppkey", l_extendedprice="l_extendedprice", l_discount="l_discount", o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderdate="o_orderdate", p_partkey="p_partkey")
+                                exchange(distribution=hash[1]96, collation=[])
+                                  hashjoin(condition="o_orderkey = l_orderkey", type="inner", partition=[local])
+                                    osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey`, `o_orderdate` from `orders_col_index` as `orders_col_index` where (`o_orderdate` between ? and ?)")
+                                    hashjoin(condition="p_partkey = l_partkey", type="inner")
+                                      osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index`")
+                                      exchange(distribution=broadcast, collation=[])
+                                        osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey` from `part_col_index` as `part_col_index` where (`p_type` = ?)")
+                              hashjoin(condition="c_nationkey = n_nationkey", type="inner")
+                                osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_nationkey` from `customer_col_index` as `customer_col_index`")
+                                exchange(distribution=broadcast, collation=[])
+                                  hashjoin(condition="n_regionkey = r_regionkey", type="inner")
+                                    osstablescan(tables="nation_col_index[p1]", partition=[remote], sql="select `n_nationkey`, `n_regionkey` from `nation_col_index` as `nation_col_index`")
+                                    exchange(distribution=broadcast, collation=[])
+                                      osstablescan(tables="region_col_index[p1]", sql="select `r_regionkey` from `region_col_index` as `region_col_index` where (`r_name` = ?)")
+                      project(s_suppkey="s_suppkey", n_name="n_name")
+                        hashjoin(condition="s_nationkey = n_nationkey", type="inner")
+                          osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
+                          exchange(distribution=broadcast, collation=[])
+                            osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey`, `n_name` from `nation_col_index` as `nation_col_index`")
+  - sql: |
+      select   nation,         o_year,         sum(amount) as sum_profit from  (               select                  n_name as nation,                       extract(year from o_orderdate) as o_year,                       l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount               from                    part,                   supplier,                       lineitem,                       partsupp,                       orders,                         nation          where                   s_suppkey = l_suppkey                   and ps_suppkey = l_suppkey                      and ps_partkey = l_partkey                      and p_partkey = l_partkey                       and o_orderkey = l_orderkey                     and s_nationkey = n_nationkey                   and p_name like '%goldenrod%'   ) as profit group by    nation,         o_year order by         nation,         o_year desc;
+    plan: |
+      exchange(distribution=single, collation=[0 asc-nulls-first, 1 desc-nulls-last])
+        memsort(sort="nation asc,o_year desc")
+          hashagg(group="nation,o_year", sum_profit="sum(sum_profit)")
+            exchange(distribution=hash[0]96, collation=[])
+              partialhashagg(group="nation,o_year", sum_profit="sum(amount)")
+                project(nation="n_name", o_year="extract(year, o_orderdate)", amount="-")
+                  hashjoin(condition="n_nationkey = s_nationkey", type="inner")
+                    project(s_nationkey="s_nationkey", o_orderdate="o_orderdate", -="-")
+                      hashjoin(condition="l_suppkey = s_suppkey", type="inner")
+                        project(l_suppkey="l_suppkey", o_orderdate="o_orderdate", -="l_extendedprice * ?0 - l_discount - ps_supplycost * l_quantity")
+                          hashjoin(condition="ps_partkey = l_partkey and ps_suppkey = l_suppkey", type="inner")
+                            osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_supplycost` from `partsupp_col_index` as `partsupp_col_index`")
+                            project(l_partkey="l_partkey", l_suppkey="l_suppkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice", l_discount="l_discount", o_orderdate="o_orderdate")
+                              exchange(distribution=hash[2]96, collation=[])
+                                project(p_partkey="p_partkey", l_orderkey="l_orderkey", l_partkey="l_partkey", l_suppkey="l_suppkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice", l_discount="l_discount", o_orderkey="o_orderkey", o_orderdate="o_orderdate")
+                                  hashjoin(condition="o_orderkey = l_orderkey", type="inner", partition=[local])
+                                    osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_orderdate` from `orders_col_index` as `orders_col_index`")
+                                    project(p_partkey="p_partkey", l_orderkey="l_orderkey", l_partkey="l_partkey", l_suppkey="l_suppkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice", l_discount="l_discount")
+                                      hashjoin(condition="p_partkey = l_partkey", type="inner")
+                                        osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_quantity`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index`")
+                                        exchange(distribution=broadcast, collation=[])
+                                          osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey` from `part_col_index` as `part_col_index` where (`p_name` like ?)")
+                        exchange(distribution=broadcast, collation=[])
+                          osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
+                    exchange(distribution=broadcast, collation=[])
+                      osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey`, `n_name` from `nation_col_index` as `nation_col_index`")
+  - sql: |
+      select   c_custkey,      c_name,         sum(l_extendedprice * (1 - l_discount)) as revenue,     c_acctbal,      n_name,         c_address,      c_phone,        c_comment from  customer,       orders,         lineitem,       nation where    c_custkey = o_custkey   and l_orderkey = o_orderkey     and o_orderdate >= '1995-01-01'         and o_orderdate < '1995-01-01' + interval '3' month     and l_returnflag = 'R'  and c_nationkey = n_nationkey group by  c_custkey,      c_name,         c_acctbal,      c_phone,        n_name,         c_address,      c_comment order by      revenue desc limit 20;
+    plan: |
+      project(c_custkey="c_custkey", c_name="c_name", revenue="revenue", c_acctbal="c_acctbal", n_name="n_name", c_address="c_address", c_phone="c_phone", c_comment="c_comment")
+        topn(sort="revenue desc", offset=0, fetch=?4)
+          exchange(distribution=single, collation=[7 desc-nulls-last])
+            topn(sort="revenue desc", fetch=+(?4, 0))
+              hashagg(group="c_custkey,n_name", c_name="__first_value(c_name)", c_acctbal="__first_value(c_acctbal)", c_phone="__first_value(c_phone)", c_address="__first_value(c_address)", c_comment="__first_value(c_comment)", revenue="sum(__*__)", partition=[local])
+                project(c_custkey="c_custkey", c_name="c_name", c_address="c_address", c_nationkey="c_nationkey", c_phone="c_phone", c_acctbal="c_acctbal", c_comment="c_comment", n_nationkey="n_nationkey", n_name="n_name", o_orderkey="o_orderkey", o_custkey="o_custkey", l_orderkey="l_orderkey", __*__="l_extendedprice * ?0 - l_discount")
+                  hashjoin(condition="n_nationkey = c_nationkey", type="inner")
+                    hashjoin(condition="o_custkey = c_custkey", type="inner")
+                      osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_comment` from `customer_col_index` as `customer_col_index`")
+                      exchange(distribution=hash[1]96, collation=[])
+                        project(o_orderkey="o_orderkey", o_custkey="o_custkey", l_orderkey="l_orderkey", l_extendedprice="l_extendedprice", l_discount="l_discount")
+                          hashjoin(condition="l_orderkey = o_orderkey", type="inner", partition=[local])
+                            osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where (`l_returnflag` = ?)")
+                            osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey` from `orders_col_index` as `orders_col_index` where ((`o_orderdate` < '1995-04-01') and (`o_orderdate` >= ?))")
+                    exchange(distribution=broadcast, collation=[])
+                      osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey`, `n_name` from `nation_col_index` as `nation_col_index`")
+  - sql: |
+      select   ps_partkey,     sum(ps_supplycost * ps_availqty) as value from  partsupp,       supplier,       nation where    ps_suppkey = s_suppkey  and s_nationkey = n_nationkey   and n_name = 'EGYPT' group by   ps_partkey having               sum(ps_supplycost * ps_availqty) > (                    select                          sum(ps_supplycost * ps_availqty) * 0.0000020000                         from                            partsupp,                               supplier,                               nation                  where                           ps_suppkey = s_suppkey                          and s_nationkey = n_nationkey                           and n_name = 'EGYPT'            ) order by      value desc;
+    plan: |
+      exchange(distribution=single, collation=[1 desc-nulls-last])
+        memsort(sort="value desc")
+          project(ps_partkey="ps_partkey", value="value")
+            nljoin(condition="value > $f0 * ?1", type="inner")
+              hashagg(group="ps_partkey", value="sum(__*__)", partition=[local])
+                project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", n_nationkey="n_nationkey", ps_partkey="ps_partkey", ps_suppkey="ps_suppkey", __*__="ps_supplycost * ps_availqty")
+                  hashjoin(condition="ps_suppkey = s_suppkey", type="inner")
+                    osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty`, `ps_supplycost` from `partsupp_col_index` as `partsupp_col_index`")
+                    exchange(distribution=broadcast, collation=[])
+                      hashjoin(condition="n_nationkey = s_nationkey", type="inner")
+                        osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
+                        exchange(distribution=broadcast, collation=[])
+                          osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey` from `nation_col_index` as `nation_col_index` where (`n_name` = ?)")
+              exchange(distribution=broadcast, collation=[])
+                hashagg($f0="sum($f0)")
+                  exchange(distribution=single, collation=[])
+                    partialhashagg($f0="sum(__*__)")
+                      project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", n_nationkey="n_nationkey", ps_suppkey="ps_suppkey", __*__="ps_supplycost * ps_availqty")
+                        hashjoin(condition="ps_suppkey = s_suppkey", type="inner")
+                          osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `ps_suppkey`, `ps_availqty`, `ps_supplycost` from `partsupp_col_index` as `partsupp_col_index`")
+                          exchange(distribution=broadcast, collation=[])
+                            hashjoin(condition="n_nationkey = s_nationkey", type="inner")
+                              osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
+                              exchange(distribution=broadcast, collation=[])
+                                osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey` from `nation_col_index` as `nation_col_index` where (`n_name` = ?)")
+  - sql: |
+      select   l_shipmode,     sum(case                when o_orderpriority = '1-URGENT'                       or o_orderpriority = '2-HIGH'                   then 1          else 0  end) as high_line_count,        sum(case                when o_orderpriority <> '1-URGENT'                      and o_orderpriority <> '2-HIGH'                         then 1          else 0  end) as low_line_count from     orders,         lineitem where  o_orderkey = l_orderkey         and l_shipmode in ('AIR', 'REG AIR')    and l_commitdate < l_receiptdate        and l_shipdate < l_commitdate   and l_receiptdate >= '1993-01-01'       and l_receiptdate < '1993-01-01' + interval '1' year group by   l_shipmode order by     l_shipmode;
+    plan: |
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        memsort(sort="l_shipmode asc")
+          hashagg(group="l_shipmode", high_line_count="sum(high_line_count)", low_line_count="sum(low_line_count)")
+            exchange(distribution=hash[0]96, collation=[])
+              partialhashagg(group="l_shipmode", high_line_count="sum(case)", low_line_count="sum(case2)")
+                project(o_orderkey="o_orderkey", case="case(in($1, row(?0, ?1)), ?2, ?3)", case2="case(and(<>($1, ?4), <>($1, ?5)), ?6, ?7)", l_orderkey="l_orderkey", l_shipmode="l_shipmode")
+                  hashjoin(condition="l_orderkey = o_orderkey", type="inner", partition=[local])
+                    osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_orderpriority` from `orders_col_index` as `orders_col_index`")
+                    osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_shipmode` from `lineitem_col_index` as `lineitem_col_index` where ((`l_receiptdate` < '1994-01-01') and (`l_shipmode` in(?)) and (`l_commitdate` < `l_receiptdate`) and (`l_shipdate` < `l_commitdate`) and (`l_receiptdate` >= ?))")
+  - sql: |
+      select   c_count,        count(*) as custdist from       (               select                  c_custkey,                      count(o_orderkey) as c_count            from                    customer left outer join orders on                              c_custkey = o_custkey                           and o_comment not like '%special%packages%'             group by                        c_custkey       ) c_orders group by     c_count order by        custdist desc,  c_count desc;
+    plan: |
+      exchange(distribution=single, collation=[1 desc-nulls-last, 0 desc-nulls-last])
+        memsort(sort="custdist desc,c_count desc")
+          hashagg(group="c_count", custdist="sum(custdist)")
+            exchange(distribution=hash[0]96, collation=[])
+              partialhashagg(group="c_count", custdist="count()")
+                hashgroupjoin(condition="c_custkey = o_custkey", type="left")
+                  osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey` from `customer_col_index` as `customer_col_index`")
+                  exchange(distribution=hash[1]96, collation=[])
+                    osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `o_orderkey`, `o_custkey` from `orders_col_index` as `orders_col_index` where (`o_comment` not like ?)")
+  - sql: |
+      select   100.00 * sum(case               when p_type like 'PROMO%'                       then l_extendedprice * (1 - l_discount)                 else 0  end) / sum(l_extendedprice * (1 - l_discount)) as promo_revenue from    lineitem,       part where      l_partkey = p_partkey   and l_shipdate >= '1993-11-01'  and l_shipdate < '1993-11-01' + interval '1' month;
+    plan: |
+      project(promo_revenue="?0 * $f0 / $f1")
+        hashagg($f0="sum($f0)", $f1="sum($f1)")
+          exchange(distribution=single, collation=[])
+            partialhashagg($f0="sum($f0)", $f1="sum($f1)")
+              project($f0="case(like($1, ?1), *($3, -(?2, $4)), cast(?3):decimal(37, 4))", $f1="l_extendedprice * ?4 - l_discount")
+                hashjoin(condition="l_partkey = p_partkey", type="inner")
+                  osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `p_partkey`, `p_type` from `part_col_index` as `part_col_index`")
+                  exchange(distribution=hash[0]96, collation=[])
+                    osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `l_partkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where ((`l_shipdate` < '1993-12-01') and (`l_shipdate` >= ?))")
+  - sql: |
+      select   s_suppkey,      s_name,         s_address,      s_phone,        total_revenue from      supplier,       (               select                  l_suppkey as supplier_no,                       sum(l_extendedprice * (1 - l_discount)) as total_revenue                from                    lineitem                where                   l_shipdate >= '1995-02-01'                      and l_shipdate < '1995-02-01' + interval '3' month              group by                        l_suppkey       ) revenue0 where        s_suppkey = supplier_no         and total_revenue = (           select                  max(total_revenue)              from                    (                               select                                  l_suppkey as supplier_no,                                       sum(l_extendedprice * (1 - l_discount)) as total_revenue                                from                                    lineitem                                where                                   l_shipdate >= '1995-02-01'                                      and l_shipdate < '1995-02-01' + interval '3' month                              group by                                        l_suppkey                       ) revenue0      ) order by      s_suppkey;
+    plan: |
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        memsort(sort="s_suppkey asc")
+          project(s_suppkey="s_suppkey", s_name="s_name", s_address="s_address", s_phone="s_phone", total_revenue="total_revenue")
+            hashjoin(condition="supplier_no = s_suppkey", type="inner")
+              osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_address`, `s_phone` from `supplier_col_index` as `supplier_col_index`")
+              project(supplier_no="supplier_no", total_revenue="total_revenue")
+                hashjoin(condition="max(total_revenue) = total_revenue", type="inner")
+                  hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
+                    exchange(distribution=hash[0]96, collation=[])
+                      partialhashagg(group="supplier_no", total_revenue="sum($f1)")
+                        project(supplier_no="l_suppkey", $f1="l_extendedprice * ?0 - l_discount")
+                          osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where ((`l_shipdate` < '1995-05-01') and (`l_shipdate` >= ?))")
+                  exchange(distribution=broadcast, collation=[])
+                    hashagg(max(total_revenue)="max(max(total_revenue))")
+                      exchange(distribution=single, collation=[])
+                        partialhashagg(max(total_revenue)="max(total_revenue)")
+                          hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
+                            exchange(distribution=hash[0]96, collation=[])
+                              partialhashagg(group="supplier_no", total_revenue="sum($f1)")
+                                project(supplier_no="l_suppkey", $f1="l_extendedprice * ?3 - l_discount")
+                                  osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where ((`l_shipdate` < '1995-05-01') and (`l_shipdate` >= ?))")
+  - sql: |
+      select   p_brand,        p_type,         p_size,         count(distinct ps_suppkey) as supplier_cnt from         partsupp,       part where      p_partkey = ps_partkey  and p_brand <> 'Brand#15'       and p_type not like 'STANDARD BRUSHED%'         and p_size in (5, 29, 4, 49, 30, 42, 33, 39)    and ps_suppkey not in (                 select                  s_suppkey               from                    supplier                where                   s_comment like '%Customer%Complaints%'  ) group by      p_brand,        p_type,         p_size order by         supplier_cnt desc,      p_brand,        p_type,         p_size;
+    plan: |
+      exchange(distribution=single, collation=[3 desc-nulls-last, 0 asc-nulls-first, 1 asc-nulls-first, 2 asc-nulls-first])
+        memsort(sort="supplier_cnt desc,p_brand asc,p_type asc,p_size asc")
+          hashagg(group="p_brand,p_type,p_size", supplier_cnt="count(ps_suppkey)")
+            hashagg(group="p_brand,p_type,p_size,ps_suppkey")
+              exchange(distribution=hash[1]96, collation=[])
+                project(p_brand="p_brand", p_type="p_type", p_size="p_size", ps_suppkey="ps_suppkey")
+                  partialhashagg(group="ps_suppkey,p_brand,p_type,p_size")
+                    semihashjoin(condition="ps_suppkey = s_suppkey", type="anti", build="inner")
+                      hashjoin(condition="p_partkey = ps_partkey", type="inner", partition=[local])
+                        osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey` from `partsupp_col_index` as `partsupp_col_index`")
+                        osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey`, `p_brand`, `p_type`, `p_size` from `part_col_index` as `part_col_index` where ((`p_size` in(?)) and (`p_brand` <> ?) and (`p_type` not like ?))")
+                      exchange(distribution=broadcast, collation=[])
+                        osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `s_suppkey` from `supplier_col_index` as `supplier_col_index` where (`s_comment` like ?)")
+  - sql: |
+      select   sum(l_extendedprice) / 7.0 as avg_yearly from   lineitem,       part where      p_partkey = l_partkey   and p_brand = 'Brand#51'        and p_container = 'SM JAR'      and l_quantity < (              select                  0.2 * avg(l_quantity)           from                    lineitem                where                   l_partkey = p_partkey   );
+    plan: |
+      project(avg_yearly="$f0 / ?0")
+        hashagg($f0="sum($f0)")
+          exchange(distribution=single, collation=[])
+            partialhashagg($f0="sum(l_extendedprice)")
+              filter(condition="l_quantity < ?3 * f16w0$o0")
+                hashwindow(p_partkey="p_partkey", l_partkey="l_partkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice", f4w0$o0="window#0avg($2)", reference windows="window#0=window(partition {1} order by [] range between unbounded preceding and unbounded following aggs [avg($2)])")
+                  exchange(distribution=hash[1]96, collation=[])
+                    project(p_partkey="p_partkey", l_partkey="l_partkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice")
+                      hashjoin(condition="l_partkey = p_partkey", type="inner")
+                        osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem_col_index` as `lineitem_col_index`")
+                        exchange(distribution=broadcast, collation=[])
+                          osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey` from `part_col_index` as `part_col_index` where ((`p_container` = ?) and (`p_brand` = ?))")
+  - sql: |
+      select   c_name,         c_custkey,      o_orderkey,     o_orderdate,    o_totalprice,   sum(l_quantity) from    customer,       orders,         lineitem where  o_orderkey in (                 select                  l_orderkey              from                    lineitem                group by                        l_orderkey having                               sum(l_quantity) > 312   )       and c_custkey = o_custkey       and o_orderkey = l_orderkey group by    c_name,         c_custkey,      o_orderkey,     o_orderdate,    o_totalprice order by   o_totalprice desc,      o_orderdate limit 100;
+    plan: |
+      project(c_name="c_name", c_custkey="c_custkey", o_orderkey="o_orderkey", o_orderdate="o_orderdate", o_totalprice="o_totalprice", sum(l_quantity)="sum(l_quantity)")
+        topn(sort="o_totalprice desc,o_orderdate asc", offset=0, fetch=?1)
+          exchange(distribution=single, collation=[3 desc-nulls-last, 2 asc-nulls-first])
+            topn(sort="o_totalprice desc,o_orderdate asc", fetch=+(?1, 0))
+              project(c_custkey="c_custkey", o_orderkey="o_orderkey", o_orderdate="o_orderdate", o_totalprice="o_totalprice", c_name="c_name", sum(l_quantity)="sum(l_quantity)")
+                hashjoin(condition="o_custkey = c_custkey", type="inner")
+                  osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_name` from `customer_col_index` as `customer_col_index`")
+                  exchange(distribution=hash[1]96, collation=[])
+                    hashagg(group="o_orderkey,o_custkey", o_orderdate="__first_value(o_orderdate)", o_totalprice="__first_value(o_totalprice)", sum(l_quantity)="sum(l_quantity)")
+                      hashjoin(condition="o_orderkey = l_orderkey", type="inner", partition=[local])
+                        osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_quantity` from `lineitem_col_index` as `lineitem_col_index`")
+                        semihashjoin(condition="o_orderkey = l_orderkey", type="semi", build="inner")
+                          osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey`, `o_totalprice`, `o_orderdate` from `orders_col_index` as `orders_col_index`")
+                          project(l_orderkey="l_orderkey")
+                            filter(condition="$f1 > ?0")
+                              hashagg(group="l_orderkey", $f1="sum(l_quantity)", partition=[local])
+                                osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_quantity` from `lineitem_col_index` as `lineitem_col_index`")
+  - sql: |
+      select   sum(l_extendedprice* (1 - l_discount)) as revenue from  lineitem,       part where      (               p_partkey = l_partkey           and p_brand = 'Brand#13'                and p_container in ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG')           and l_quantity >= 7 and l_quantity <= 7 + 10            and p_size between 1 and 5              and l_shipmode in ('AIR', 'AIR REG')            and l_shipinstruct = 'DELIVER IN PERSON'        )       or      (               p_partkey = l_partkey           and p_brand = 'Brand#15'                and p_container in ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK')                and l_quantity >= 18 and l_quantity <= 18 + 10          and p_size between 1 and 10             and l_shipmode in ('AIR', 'AIR REG')            and l_shipinstruct = 'DELIVER IN PERSON'        )       or      (               p_partkey = l_partkey           and p_brand = 'Brand#35'                and p_container in ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG')           and l_quantity >= 21 and l_quantity <= 21 + 10          and p_size between 1 and 15             and l_shipmode in ('AIR', 'AIR REG')            and l_shipinstruct = 'DELIVER IN PERSON'        );
+    plan: |
+      hashagg(revenue="sum(revenue)")
+        exchange(distribution=single, collation=[])
+          partialhashagg(revenue="sum(__*__)")
+            project(p_partkey="p_partkey", =="p_brand = ?1", in="p_container in row(?2)", between asymmetric="between asymmetric($8, ?6, ?7)", =4="p_brand = ?10", in5="p_container in row(?11)", between asymmetric6="between asymmetric($8, ?15, ?16)", =7="p_brand = ?19", in8="p_container in row(?20)", between asymmetric9="between asymmetric($8, ?24, ?25)", l_partkey="l_partkey", __*__="l_extendedprice * ?0 - l_discount", >=="l_quantity >= ?3", <=="l_quantity <= 17", in0="l_shipmode in row(?8)", =0="l_shipinstruct = ?9", >=6="l_quantity >= ?12", <=7="l_quantity <= 28", in80="l_shipmode in row(?17)", =9="l_shipinstruct = ?18", >=10="l_quantity >= ?21", <=11="l_quantity <= 31", in12="l_shipmode in row(?26)", =13="l_shipinstruct = ?27")
+              hashjoin(condition="p_partkey = l_partkey and ((p_partkey = l_partkey and p_brand = ?1 and p_container in row(?2) and l_quantity >= ?3 and l_quantity <= 17 and between asymmetric($8, ?6, ?7) and l_shipmode in row(?8) and l_shipinstruct = ?9) or (p_partkey = l_partkey and p_brand = ?10 and p_container in row(?11) and l_quantity >= ?12 and l_quantity <= 28 and between asymmetric($8, ?15, ?16) and l_shipmode in row(?17) and l_shipinstruct = ?18) or (p_partkey = l_partkey and p_brand = ?19 and p_container in row(?20) and l_quantity >= ?21 and l_quantity <= 31 and between asymmetric($8, ?24, ?25) and l_shipmode in row(?26) and l_shipinstruct = ?27))", type="inner")
+                osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_partkey`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_shipinstruct`, `l_shipmode` from `lineitem_col_index` as `lineitem_col_index` where (((`l_quantity` >= ?) and (`l_quantity` <= 17) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)) or ((`l_quantity` >= ?) and (`l_quantity` <= 28) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)) or ((`l_quantity` >= ?) and (`l_quantity` <= 31) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)))")
+                exchange(distribution=broadcast, collation=[])
+                  osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey`, `p_brand`, `p_size`, `p_container` from `part_col_index` as `part_col_index` where (((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)) or ((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)) or ((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)))")
+  - sql: |
+      select   s_name,         s_address from  supplier,       nation where    s_suppkey in (          select                  ps_suppkey              from                    partsupp                where                   ps_partkey in (                                 select                                  p_partkey                               from                                    part                            where                                   p_name like 'mint%'                     )                       and ps_availqty > (                             select                                  0.5 * sum(l_quantity)                           from                                    lineitem                                where                                   l_partkey = ps_partkey                                  and l_suppkey = ps_suppkey                                      and l_shipdate >= '1993-01-01'                                  and l_shipdate < '1993-01-01' + interval '1' year                       )       )       and s_nationkey = n_nationkey   and n_name = 'UNITED STATES' order by   s_name;
+    plan: |
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        memsort(sort="s_name asc")
+          project(s_name="s_name", s_address="s_address")
+            hashjoin(condition="n_nationkey = s_nationkey", type="inner")
+              project(s_name="s_name", s_address="s_address", s_nationkey="s_nationkey")
+                semihashjoin(condition="s_suppkey = ps_suppkey", type="semi", build="inner")
+                  osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_address`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
+                  project(ps_suppkey="ps_suppkey")
+                    hashjoin(condition="l_partkey = ps_partkey and l_suppkey = ps_suppkey and ps_availqty > ?1 * $f2", type="inner")
+                      hashagg(group="l_partkey,l_suppkey", $f2="sum($f2)")
+                        exchange(distribution=hash[1]96, collation=[])
+                          partialhashagg(group="l_partkey,l_suppkey", $f2="sum(l_quantity)")
+                            semihashjoin(condition="l_partkey = ps_partkey and l_suppkey = ps_suppkey", type="semi", build="inner")
+                              project(l_quantity="l_quantity", l_partkey="l_partkey", l_suppkey="l_suppkey")
+                                osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_partkey`, `l_suppkey`, `l_quantity` from `lineitem_col_index` as `lineitem_col_index` where ((`l_shipdate` < '1994-01-01') and (`l_shipdate` >= ?))")
+                              exchange(distribution=broadcast, collation=[])
+                                semihashjoin(condition="ps_partkey = p_partkey", type="semi", build="inner", partition=[local])
+                                  osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp_col_index` as `partsupp_col_index`")
+                                  osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey` from `part_col_index` as `part_col_index` where (`p_name` like ?)")
+                      exchange(distribution=hash[1]96, collation=[])
+                        semihashjoin(condition="ps_partkey = p_partkey", type="semi", build="inner", partition=[local])
+                          osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp_col_index` as `partsupp_col_index`")
+                          osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey` from `part_col_index` as `part_col_index` where (`p_name` like ?)")
+              exchange(distribution=broadcast, collation=[])
+                osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey` from `nation_col_index` as `nation_col_index` where (`n_name` = ?)")
+  - sql: |
+      select   s_name,         count(*) as numwait from        supplier,       lineitem l1,    orders,         nation where    s_suppkey = l1.l_suppkey        and o_orderkey = l1.l_orderkey  and o_orderstatus = 'F'         and l1.l_receiptdate > l1.l_commitdate  and exists (            select                  *               from                    lineitem l2             where                   l2.l_orderkey = l1.l_orderkey                   and l2.l_suppkey <> l1.l_suppkey        )       and not exists (                select                  *               from                    lineitem l3             where                   l3.l_orderkey = l1.l_orderkey                   and l3.l_suppkey <> l1.l_suppkey                        and l3.l_receiptdate > l3.l_commitdate  )       and s_nationkey = n_nationkey   and n_name = 'ARGENTINA' group by       s_name order by         numwait desc,   s_name limit 100;
+    plan: |
+      topn(sort="numwait desc,s_name asc", offset=0, fetch=?2)
+        exchange(distribution=single, collation=[1 desc-nulls-last, 0 asc-nulls-first])
+          topn(sort="numwait desc,s_name asc", fetch=+(?2, 0))
+            hashagg(group="s_name", numwait="sum(numwait)")
+              exchange(distribution=hash[0]96, collation=[])
+                partialhashagg(group="s_name", numwait="count()")
+                  hashjoin(condition="l_orderkey = o_orderkey", type="inner")
+                    osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `o_orderkey` from `orders_col_index` as `orders_col_index` where (`o_orderstatus` = ?)")
+                    semihashjoin(condition="l_orderkey = l_orderkey and l_suppkey <> l_suppkey", type="semi", build="outer")
+                      semihashjoin(condition="l_orderkey = l_orderkey and l_suppkey <> l_suppkey", type="anti", build="outer", partition=[local])
+                        project(s_suppkey="s_suppkey", s_name="s_name", s_nationkey="s_nationkey", n_nationkey="n_nationkey", l_orderkey="l_orderkey", l_suppkey="l_suppkey")
+                          hashjoin(condition="l_suppkey = s_suppkey", type="inner")
+                            osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_suppkey` from `lineitem_col_index` as `lineitem_col_index` where (`l_receiptdate` > `l_commitdate`)")
+                            exchange(distribution=broadcast, collation=[])
+                              hashjoin(condition="n_nationkey = s_nationkey", type="inner")
+                                osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
+                                exchange(distribution=broadcast, collation=[])
+                                  osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey` from `nation_col_index` as `nation_col_index` where (`n_name` = ?)")
+                        osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_suppkey` from `lineitem_col_index` as `lineitem_col_index` where (`l_receiptdate` > `l_commitdate`)")
+                      osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_orderkey`, `l_suppkey` from `lineitem_col_index` as `lineitem_col_index`")
+  - sql: |
+      select   cntrycode,      count(*) as numcust,    sum(c_acctbal) as totacctbal from       (               select                  substring(c_phone from 1 for 2) as cntrycode,                   c_acctbal               from                    customer                where                   substring(c_phone from 1 for 2) in                              ('34', '24', '30', '26', '29', '17', '33')                      and c_acctbal > (                               select                                  avg(c_acctbal)                          from                                    customer                                where                                   c_acctbal > 0.00                                        and substring(c_phone from 1 for 2) in                                          ('34', '24', '30', '26', '29', '17', '33')                      )                       and not exists (                                select                                  *                               from                                    orders                          where                                   o_custkey = c_custkey                   )       ) as custsale group by  cntrycode order by      cntrycode;
+    plan: |
+      exchange(distribution=single, collation=[0 asc-nulls-first])
+        memsort(sort="cntrycode asc")
+          hashagg(group="cntrycode", numcust="sum(numcust)", totacctbal="sum(totacctbal)")
+            exchange(distribution=hash[0]96, collation=[])
+              partialhashagg(group="cntrycode", numcust="count()", totacctbal="sum(c_acctbal)")
+                project(cntrycode="substring(c_phone, ?0, ?1)", c_acctbal="c_acctbal")
+                  semihashjoin(condition="o_custkey = c_custkey", type="anti", build="outer")
+                    project($f0="$f0", $f1="$f1", c_custkey="c_custkey", c_phone="c_phone", c_acctbal="c_acctbal")
+                      nljoin(condition="c_acctbal > $f0 / $f1", type="inner")
+                        osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_phone`, `c_acctbal` from `customer_col_index` as `customer_col_index` where ((substring(`c_phone`, ?, ?)) in(?))")
+                        exchange(distribution=broadcast, collation=[])
+                          hashagg($f0="sum($f0)", $f1="sum($f1)")
+                            exchange(distribution=single, collation=[])
+                              partialhashagg($f0="sum(c_acctbal)", $f1="count()")
+                                osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `c_acctbal` from `customer_col_index` as `customer_col_index` where (((substring(`c_phone`, ?, ?)) in(?)) and (`c_acctbal` > ?))")
+                    exchange(distribution=hash[0]96, collation=[])
+                      osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `o_custkey` from `orders_col_index` as `orders_col_index`")
+DDL:
+  customer:
+    CREATE TABLE IF NOT EXISTS `customer` (  `c_custkey` int(11) NOT NULL,  `c_name` varchar(25) NOT NULL,  `c_address` varchar(40) NOT NULL,  `c_nationkey` int(11) NOT NULL,  `c_phone` varchar(15) NOT NULL,  `c_acctbal` decimal(15, 2) NOT NULL,  `c_mktsegment` varchar(10) NOT NULL,  `c_comment` varchar(117) NOT NULL,  PRIMARY KEY (`c_custkey`),  CLUSTERED COLUMNAR INDEX `customer_col_index`(`c_custkey`) PARTITION BY HASH (`c_custkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`c_custkey`) PARTITIONS 128;
+  lineitem:
+    CREATE TABLE IF NOT EXISTS `lineitem` (  `l_orderkey` bigint(20) NOT NULL,  `l_partkey` int(11) NOT NULL,  `l_suppkey` int(11) NOT NULL,  `l_linenumber` bigint(20) NOT NULL,  `l_quantity` decimal(15, 2) NOT NULL,  `l_extendedprice` decimal(15, 2) NOT NULL,  `l_discount` decimal(15, 2) NOT NULL,  `l_tax` decimal(15, 2) NOT NULL,  `l_returnflag` varchar(1) NOT NULL,  `l_linestatus` varchar(1) NOT NULL,  `l_shipdate` date NOT NULL,  `l_commitdate` date NOT NULL,  `l_receiptdate` date NOT NULL,  `l_shipinstruct` varchar(25) NOT NULL,  `l_shipmode` varchar(10) NOT NULL,  `l_comment` varchar(44) NOT NULL,  PRIMARY KEY (`l_orderkey`, `l_linenumber`),  CLUSTERED COLUMNAR INDEX `lineitem_col_index`(`l_shipdate`, `l_orderkey`) PARTITION BY HASH (`l_orderkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`l_orderkey`) PARTITIONS 128;
+  nation:
+    CREATE TABLE IF NOT EXISTS `nation` (  `n_nationkey` int(11) NOT NULL,  `n_name` varchar(25) NOT NULL,  `n_regionkey` int(11) NOT NULL,  `n_comment` varchar(152) DEFAULT NULL,  PRIMARY KEY (`n_nationkey`),  CLUSTERED COLUMNAR INDEX `nation_col_index`(`n_nationkey`) PARTITION BY HASH (`n_nationkey`) PARTITIONS 1 ) BROADCAST ENGINE = InnoDB DEFAULT CHARSET = latin1;
+  orders:
+    CREATE TABLE IF NOT EXISTS `orders` (  `o_orderkey` bigint(20) NOT NULL,  `o_custkey` int(11) NOT NULL,  `o_orderstatus` varchar(1) NOT NULL,  `o_totalprice` decimal(15, 2) NOT NULL,  `o_orderdate` date NOT NULL,  `o_orderpriority` varchar(15) NOT NULL,  `o_clerk` varchar(15) NOT NULL,  `o_shippriority` bigint(20) NOT NULL,  `o_comment` varchar(79) NOT NULL,  PRIMARY KEY (`o_orderkey`),  CLUSTERED COLUMNAR INDEX `orders_col_index`(`o_orderdate`, `o_orderkey`) PARTITION BY HASH (`o_orderkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`o_orderkey`) PARTITIONS 128;
+  part:
+    CREATE TABLE IF NOT EXISTS `part` (  `p_partkey` int(11) NOT NULL,  `p_name` varchar(55) NOT NULL,  `p_mfgr` varchar(25) NOT NULL,  `p_brand` varchar(10) NOT NULL,  `p_type` varchar(25) NOT NULL,  `p_size` int(11) NOT NULL,  `p_container` varchar(10) NOT NULL,  `p_retailprice` decimal(15, 2) NOT NULL,  `p_comment` varchar(23) NOT NULL,  PRIMARY KEY (`p_partkey`),  CLUSTERED COLUMNAR INDEX `part_col_index`(`p_size`) PARTITION BY HASH (`p_partkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`p_partkey`) PARTITIONS 128;
+  partsupp:
+    CREATE TABLE IF NOT EXISTS `partsupp` (  `ps_partkey` int(11) NOT NULL,  `ps_suppkey` int(11) NOT NULL,  `ps_availqty` int(11) NOT NULL,  `ps_supplycost` decimal(15, 2) NOT NULL,  `ps_comment` varchar(199) NOT NULL,  PRIMARY KEY (`ps_partkey`, `ps_suppkey`),  CLUSTERED COLUMNAR INDEX `partsupp_col_index`(`ps_partkey`) PARTITION BY HASH (`ps_partkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`ps_partkey`) PARTITIONS 128;
+  region:
+    CREATE TABLE IF NOT EXISTS `region` (  `r_regionkey` int(11) NOT NULL,  `r_name` varchar(25) NOT NULL,  `r_comment` varchar(152) DEFAULT NULL,  PRIMARY KEY (`r_regionkey`),  CLUSTERED COLUMNAR INDEX `region_col_index`(`r_regionkey`) PARTITION BY HASH (`r_regionkey`) PARTITIONS 1 ) BROADCAST ENGINE = InnoDB DEFAULT CHARSET = latin1;
+  supplier:
+    CREATE TABLE IF NOT EXISTS `supplier` (  `s_suppkey` int(11) NOT NULL,  `s_name` varchar(25) NOT NULL,  `s_address` varchar(40) NOT NULL,  `s_nationkey` int(11) NOT NULL,  `s_phone` varchar(15) NOT NULL,  `s_acctbal` decimal(15, 2) NOT NULL,  `s_comment` varchar(101) NOT NULL,  PRIMARY KEY (`s_suppkey`),  CLUSTERED COLUMNAR INDEX `supplier_col_index`(`s_suppkey`) PARTITION BY HASH (`s_suppkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`s_suppkey`) PARTITIONS 128;
+
+STATISTICS:
+  customer:
+    168648768
+  lineitem:
+    6860984320
+  nation:
+    25
+  orders:
+    1660557312
+  part:
+    220466800
+  partsupp:
+    883230464
+  region:
+    5
+  supplier:
+    10826645
+  customer.c_acctbal.TOPN:
+    { "countArr": [ 4,4,4,4 ],"valueArr": [ -102.30,1989.73,4426.01,9380.49 ],"type": "Double","sampleRate": 1.0 }
+  customer.c_acctbal.cardinality:
+    11480877
+  customer.c_acctbal.histogram:
+    { "buckets": [ { "ndv": 1459,"upper": -829.35,"lower": -999.94,"count": 1543,"preSum": 0 },{ "ndv": 1463,"upper": -658.71,"lower": -829.30,"count": 1543,"preSum": 1543 },{ "ndv": 1485,"upper": -486.81,"lower": -658.70,"count": 1543,"preSum": 3086 },{ "ndv": 1466,"upper": -318.53,"lower": -486.70,"count": 1543,"preSum": 4629 },{ "ndv": 1479,"upper": -141.90,"lower": -318.27,"count": 1543,"preSum": 6172 },{ "ndv": 1471,"upper": 26.75,"lower": -141.40,"count": 1543,"preSum": 7715 },{ "ndv": 1481,"upper": 206.21,"lower": 26.78,"count": 1543,"preSum": 9258 },{ "ndv": 1486,"upper": 375.90,"lower": 206.32,"count": 1543,"preSum": 10801 },{ "ndv": 1471,"upper": 543.63,"lower": 375.98,"count": 1543,"preSum": 12344 },{ "ndv": 1476,"upper": 718.56,"lower": 544.05,"count": 1543,"preSum": 13887 },{ "ndv": 1486,"upper": 894.75,"lower": 718.59,"count": 1543,"preSum": 15430 },{ "ndv": 1486,"upper": 1068.07,"lower": 895.15,"count": 1543,"preSum": 16973 },{ "ndv": 1476,"upper": 1243.82,"lower": 1068.12,"count": 1544,"preSum": 18516 },{ "ndv": 1478,"upper": 1422.57,"lower": 1243.91,"count": 1543,"preSum": 20060 },{ "ndv": 1485,"upper": 1597.16,"lower": 1422.60,"count": 1543,"preSum": 21603 },{ "ndv": 1475,"upper": 1768.47,"lower": 1597.26,"count": 1543,"preSum": 23146 },{ "ndv": 1471,"upper": 1954.16,"lower": 1768.63,"count": 1543,"preSum": 24689 },{ "ndv": 1475,"upper": 2122.20,"lower": 1954.40,"count": 1543,"preSum": 26232 },{ "ndv": 1478,"upper": 2297.07,"lower": 2122.23,"count": 1543,"preSum": 27775 },{ "ndv": 1457,"upper": 2476.98,"lower": 2297.19,"count": 1543,"preSum": 29318 },{ "ndv": 1485,"upper": 2648.86,"lower": 2477.04,"count": 1543,"preSum": 30861 },{ "ndv": 1475,"upper": 2813.45,"lower": 2649.17,"count": 1543,"preSum": 32404 },{ "ndv": 1473,"upper": 2992.81,"lower": 2813.67,"count": 1543,"preSum": 33947 },{ "ndv": 1475,"upper": 3159.03,"lower": 2992.94,"count": 1543,"preSum": 35490 },{ "ndv": 1485,"upper": 3328.68,"lower": 3159.08,"count": 1545,"preSum": 37033 },{ "ndv": 1467,"upper": 3500.26,"lower": 3328.97,"count": 1543,"preSum": 38578 },{ "ndv": 1470,"upper": 3669.90,"lower": 3500.41,"count": 1543,"preSum": 40121 },{ "ndv": 1475,"upper": 3844.36,"lower": 3670.02,"count": 1544,"preSum": 41664 },{ "ndv": 1481,"upper": 4018.93,"lower": 3844.40,"count": 1543,"preSum": 43208 },{ "ndv": 1481,"upper": 4188.39,"lower": 4018.94,"count": 1543,"preSum": 44751 },{ "ndv": 1485,"upper": 4357.02,"lower": 4188.51,"count": 1543,"preSum": 46294 },{ "ndv": 1464,"upper": 4522.00,"lower": 4357.04,"count": 1543,"preSum": 47837 },{ "ndv": 1481,"upper": 4696.98,"lower": 4522.43,"count": 1543,"preSum": 49380 },{ "ndv": 1469,"upper": 4870.38,"lower": 4697.10,"count": 1543,"preSum": 50923 },{ "ndv": 1477,"upper": 5044.93,"lower": 4870.52,"count": 1543,"preSum": 52466 },{ "ndv": 1479,"upper": 5217.87,"lower": 5045.01,"count": 1543,"preSum": 54009 },{ "ndv": 1475,"upper": 5386.58,"lower": 5217.88,"count": 1543,"preSum": 55552 },{ "ndv": 1478,"upper": 5556.96,"lower": 5386.60,"count": 1543,"preSum": 57095 },{ "ndv": 1464,"upper": 5724.46,"lower": 5557.04,"count": 1543,"preSum": 58638 },{ "ndv": 1483,"upper": 5895.47,"lower": 5724.48,"count": 1544,"preSum": 60181 },{ "ndv": 1468,"upper": 6062.59,"lower": 5895.51,"count": 1543,"preSum": 61725 },{ "ndv": 1473,"upper": 6240.16,"lower": 6062.61,"count": 1543,"preSum": 63268 },{ "ndv": 1484,"upper": 6411.24,"lower": 6240.31,"count": 1543,"preSum": 64811 },{ "ndv": 1482,"upper": 6581.81,"lower": 6411.46,"count": 1543,"preSum": 66354 },{ "ndv": 1480,"upper": 6755.15,"lower": 6581.89,"count": 1543,"preSum": 67897 },{ "ndv": 1476,"upper": 6923.15,"lower": 6755.17,"count": 1543,"preSum": 69440 },{ "ndv": 1471,"upper": 7098.06,"lower": 6923.32,"count": 1543,"preSum": 70983 },{ "ndv": 1482,"upper": 7268.10,"lower": 7098.09,"count": 1543,"preSum": 72526 },{ "ndv": 1475,"upper": 7437.47,"lower": 7268.36,"count": 1543,"preSum": 74069 },{ "ndv": 1479,"upper": 7608.64,"lower": 7437.67,"count": 1543,"preSum": 75612 },{ "ndv": 1478,"upper": 7780.93,"lower": 7608.76,"count": 1543,"preSum": 77155 },{ "ndv": 1453,"upper": 7945.84,"lower": 7780.97,"count": 1543,"preSum": 78698 },{ "ndv": 1484,"upper": 8121.79,"lower": 7945.96,"count": 1543,"preSum": 80241 },{ "ndv": 1472,"upper": 8294.56,"lower": 8121.84,"count": 1543,"preSum": 81784 },{ "ndv": 1475,"upper": 8462.84,"lower": 8294.57,"count": 1543,"preSum": 83327 },{ "ndv": 1474,"upper": 8635.29,"lower": 8462.93,"count": 1543,"preSum": 84870 },{ "ndv": 1470,"upper": 8806.08,"lower": 8635.30,"count": 1543,"preSum": 86413 },{ "ndv": 1468,"upper": 8978.45,"lower": 8806.10,"count": 1543,"preSum": 87956 },{ "ndv": 1462,"upper": 9144.35,"lower": 8978.52,"count": 1543,"preSum": 89499 },{ "ndv": 1460,"upper": 9305.06,"lower": 9144.45,"count": 1543,"preSum": 91042 },{ "ndv": 1491,"upper": 9479.08,"lower": 9305.17,"count": 1543,"preSum": 92585 },{ "ndv": 1484,"upper": 9653.96,"lower": 9479.30,"count": 1543,"preSum": 94128 },{ "ndv": 1483,"upper": 9829.96,"lower": 9654.27,"count": 1543,"preSum": 95671 },{ "ndv": 1411,"upper": 9999.98,"lower": 9830.20,"count": 1482,"preSum": 97214 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 1.0 }
+  customer.c_acctbal.null_count:
+    0
+  customer.c_acctbal.sample_rate:
+    5.8531115E-4
+  customer.c_address.TOPN:
+    null
+  customer.c_address.cardinality:
+    26136945
+  customer.c_address.histogram:
+    { "buckets": [ { "ndv": 1543,"upper": " Zw1Qr9dWwIh UrnRz","lower": "   5L06W67,Mw8G","count": 1543,"preSum": 0 },{ "ndv": 1543,"upper": "0,RZZCjopIC05ZzZ4wl32RPq3D7lGUqc5S","lower": " ZXDwCvgAy7WpeBpRLUgCZpbMnl8jFwuwM5","count": 1543,"preSum": 1543 },{ "ndv": 1543,"upper": "0ZjBnPrW5eje3WR","lower": "0,S9OFZ0dBo","count": 1543,"preSum": 3086 },{ "ndv": 1543,"upper": "1ZhmZWMN8dCkif0YawkJV","lower": "0ZJOe5dqOO23wB1d2VEATI","count": 1543,"preSum": 4629 },{ "ndv": 1543,"upper": "2xUXb9Bd AYboJ8NeEhb","lower": "1zhN9pH0uM8T680RUV5hoLDKEGYPSsRrHQ8s","count": 1543,"preSum": 6172 },{ "ndv": 1543,"upper": "3XWxrIEi3Iz15nWP4pDEO5Zg","lower": "2XUYE143V,ryjV UDOwbLxOokNFy3ZcE","count": 1543,"preSum": 7715 },{ "ndv": 1543,"upper": "4X6hy9Z3QVAvMA4GOpD","lower": "3xx0NQVFxCNZWdW","count": 1543,"preSum": 9258 },{ "ndv": 1543,"upper": "5x q94TDGwcypW","lower": "4x77gUWS6Y","count": 1543,"preSum": 10801 },{ "ndv": 1543,"upper": "6WqPiZ7ja41L","lower": "5x uHIXC7gUCNb2WF7rB","count": 1543,"preSum": 12344 },{ "ndv": 1543,"upper": "7WUYSOqhRxW5hoOMGCLEXvj","lower": "6wr3Hsr6GTK3dAZsAd8sbfv","count": 1543,"preSum": 13887 },{ "ndv": 1543,"upper": "8Xah2WmKfGoQGt","lower": "7wvCZ88C1Qnm6aV2Bp","count": 1543,"preSum": 15430 },{ "ndv": 1543,"upper": "9z9kuobFnYf6h5gRFV","lower": "8xBtCf62Je3DMDqTr80amweCDs1fil85,BCR5q","count": 1543,"preSum": 16973 },{ "ndv": 1543,"upper": "AJ4GDp3xB7yB,Mj0guQIKaWqQXB,","lower": "9Za97RT2wUisrmePhs0 YM62LrEC2UTvHUufCAk1","count": 1543,"preSum": 18516 },{ "ndv": 1543,"upper": "aZ9Xe9cuunnX4a3UW2obN9XF","lower": "aj5rbfWCcQH6N86OiRtH1","count": 1543,"preSum": 20059 },{ "ndv": 1543,"upper": "BJD01XWx7eWv,wr7Pm3Qx0cs4Dsnl6Miq0l","lower": "AZaN44IQwjbqbSkdB4lBhGbFC88cwR6mCg,RX","count": 1543,"preSum": 21602 },{ "ndv": 1543,"upper": "BzDNU80pTvHKHIhzEr","lower": "bjDecc0,TlWT8EC,rrt","count": 1543,"preSum": 23145 },{ "ndv": 1543,"upper": "cJIljpNTpGHlRfr77R6v","lower": "bZds2rX,o0Fgg0AVa3JAsf 2wdYeW1huBkFU","count": 1543,"preSum": 24688 },{ "ndv": 1543,"upper": "cZOUiO e,boyvc9","lower": "CjimKC4rx5OAlccO9SUWo G2oF8s,C","count": 1543,"preSum": 26231 },{ "ndv": 1543,"upper": "DJTdpPVqHdv69hcMc4IEPBMEUGk","lower": "czpDVkpCd7pr","count": 1543,"preSum": 27774 },{ "ndv": 1543,"upper": "DZSIPfzu7WQFPCD2hoTMh7wHcOkgAV","lower": "DjTOUotC7CBmib1ZgC0WgXm7uX4Apulw","count": 1543,"preSum": 29317 },{ "ndv": 1543,"upper": "Ek56iwUGvWhU81Z0oP6t7t7","lower": "dzt5RBm7jkdTVKCTDVepjS09sJhR13E6zkqHGzea","count": 1543,"preSum": 30860 },{ "ndv": 1543,"upper": "EZrXlqCrnNAY6lCE9inoopu","lower": "ek72pBodfV2kO3LxTg","count": 1543,"preSum": 32403 },{ "ndv": 1543,"upper": "FJF4fWKZLiRenJXc0WmOpQI","lower": "EzrxOpaHbg99rVI5","count": 1543,"preSum": 33946 },{ "ndv": 1543,"upper": "fyS36ZmWHxDQbo","lower": "fJFkef,hvlDxMH9,v","count": 1543,"preSum": 35489 },{ "ndv": 1543,"upper": "GIVmWHIKk,8U4Zwe ","lower": "fYsaMqciVKyrQ,","count": 1543,"preSum": 37032 },{ "ndv": 1543,"upper": "gZCqYtmcSq","lower": "Giw1IZK47BGdgLb1HPMHcji","count": 1543,"preSum": 38575 },{ "ndv": 1543,"upper": "HjCUfQxv1zSEGZsovVUg","lower": "GZcv81pq9V","count": 1543,"preSum": 40118 },{ "ndv": 1543,"upper": "hZpAPE7H7bwO8jgERaIh1FhYHg2","lower": "hJdKg6eIXuS5f7opp8ck3n0MYgg lgZ","count": 1543,"preSum": 41661 },{ "ndv": 1543,"upper": "IjFBoCYqLgzDATrXMSy","lower": "hZPNQ8a9QRM ,SYdTdoW9hw","count": 1543,"preSum": 43204 },{ "ndv": 1543,"upper": "izYXemCV7GAnMMG4","lower": "ijfispfdLUrx4Ay6Yz6Qks0ceHu78","count": 1543,"preSum": 44747 },{ "ndv": 1543,"upper": "Jj,8cEFhEcD","lower": "IzzGjwzO6jqcJcwjWTRHkjrv20G","count": 1543,"preSum": 46290 },{ "ndv": 1543,"upper": "jzPAMJMub3gFg,Wy77LxnL7txn","lower": "jj,XQGayjz2 t","count": 1543,"preSum": 47833 },{ "ndv": 1543,"upper": "kk35mUR7F8UYrQIuup3Hn","lower": "JZPChU21aN2Cro  5BVb66YC8Ls7tPhBcfa","count": 1543,"preSum": 49376 },{ "ndv": 1543,"upper": "kzXzmT0qNU5ypd 2m3HVlsey6VoKZ5kLOevZg","lower": "Kk3DYNYU0xBicRPi","count": 1543,"preSum": 50919 },{ "ndv": 1543,"upper": "LK85Np6MWyCj4rYcuS7fKUkTqvp4UYAn0","lower": "kZy4LxlpXU","count": 1543,"preSum": 52462 },{ "ndv": 1543,"upper": "m,NsBHNlik9CLo","lower": "LKaS75O,BD4RYWoj4,IGZK","count": 1543,"preSum": 54005 },{ "ndv": 1543,"upper": "mkzqK5TLLAeO","lower": "M,NTaVK5o9","count": 1543,"preSum": 55548 },{ "ndv": 1543,"upper": "n V IeJxgUIgL7zcuMi9NIFYwwypsy 1LRfbN","lower": "mL j3U hp9J4Im","count": 1543,"preSum": 57091 },{ "ndv": 1543,"upper": "nk5APBcAnR6TbEFR3SIA,zhmJch0ur4ouo N9","lower": "n v6CEt2cq7ENqfC98E4Hzfrc1ezi6VJMuM z","count": 1543,"preSum": 58634 },{ "ndv": 1543,"upper": "nZzJMsEaEVNE5Gg5Arpz46zpGcqcf2j3I3 hU","lower": "nK5d1c0muk1R9 HLo7laROL6KY3XWoKPJp J","count": 1543,"preSum": 60177 },{ "ndv": 1543,"upper": "Ok8n1hp9bx","lower": "O 0oI zXZWIVugfrr8CMXMomroTw5ky","count": 1543,"preSum": 61720 },{ "ndv": 1543,"upper": "p,2tweVhXG56d3zFfRzu0q8VntwwQyz","lower": "ok9cFAV2zrM,zig,VXFVaDz ATz58zUbfHw","count": 1543,"preSum": 63263 },{ "ndv": 1543,"upper": "PKI02x1AI9KhKlwHcpNHqfiS","lower": "P,4KIW7f9BCuBy3KnJBOVqor","count": 1543,"preSum": 64806 },{ "ndv": 1543,"upper": "q,7YlBJqYB","lower": "PkIFKTZM TVkR13YaDxqjcjXPBS,j7SCuEkA3PD","count": 1543,"preSum": 66349 },{ "ndv": 1543,"upper": "qkmsCu58E5 hiaOjC,4iogCttu4VK","lower": "Q,9wgSlnxHgOFTIB9TKXcgt219Z3gHZ4O2JY","count": 1543,"preSum": 67892 },{ "ndv": 1543,"upper": "QzZFhYgKiIwpaVjL4","lower": "QkmuOCgSTBYVCSuVxCkx74RoINwJtnknxx,V0K0X","count": 1543,"preSum": 69435 },{ "ndv": 1543,"upper": "rJV2xFMMb5DgzXndBxf","lower": "r 12Ozg1FoD6vL2sM0TaM,NiWej7e5","count": 1543,"preSum": 70978 },{ "ndv": 1543,"upper": "s,4y4MkGchzHm5o969bBdID1ThtPDQO2KCNE3","lower": "RJv9a8Q2H39cbrzSkwnQIx5FKVelhlo6Vu","count": 1543,"preSum": 72521 },{ "ndv": 1543,"upper": "sjZLk42vU8pSk4L At30taKedequ3pl,","lower": "S,6ajyDFO3WUQ0Qr","count": 1543,"preSum": 74064 },{ "ndv": 1543,"upper": "t,QZv,mEkLfqiUYyhAhftgrjiWhXqGKN5cLdPd5S","lower": "sjzWepU3PTw5kGKJMICnUgoBZ yUIg","count": 1543,"preSum": 75607 },{ "ndv": 1543,"upper": "tL80Vo3HWUT3DIEqU","lower": "t,RcJaPgYNmjL","count": 1543,"preSum": 77150 },{ "ndv": 1543,"upper": "U0bfBA0klqiCyUi98RL4YUhmSrL9TW0Vaane24","lower": "Tl8aG4SAkMltuymKwBHSC","count": 1543,"preSum": 78693 },{ "ndv": 1543,"upper": "ukS iOMsWe7wl2ui5wsSrDaIt74X20M3nG3OUpPK","lower": "u0BTN5D25HTcDPv74","count": 1543,"preSum": 80236 },{ "ndv": 1543,"upper": "v,a0VBpA63edy7Rh3YCPJayhDn5HzkU1Nd","lower": "UKSfqik0UYFZd25lbY 9R4BY7Yd0q0q","count": 1543,"preSum": 81779 },{ "ndv": 1543,"upper": "vKc0tOF6ivFLdlbzUygLKNOX8Ize5pAJ0NG5d7t","lower": "V,BD7I mpUTn0S","count": 1543,"preSum": 83322 },{ "ndv": 1543,"upper": "vzzrb3RUlMtHt9K7h4luUXA","lower": "vkccHgLmSQZ oTro8hZOYYI4AXBC3V57wmcN4va","count": 1543,"preSum": 84865 },{ "ndv": 1543,"upper": "WjK4lUin fojwxmyJZETFjInojE3","lower": "w  qp3YEUgVVqTkAUvAHJW8sGS2VIFza2BYq","count": 1543,"preSum": 86408 },{ "ndv": 1543,"upper": "WZKuJJgNadtP0lbkXaaWYqy,G8wjDVS9ppJqBGs","lower": "WjK9dl,kCTFk2UvrsWgWsEyFquGJL","count": 1543,"preSum": 87951 },{ "ndv": 1543,"upper": "xjr6625uH16dSe56Fd32 eCSpJ1wurO8wHBblAGL","lower": "wzl,JC5tQVTREEG5,6K7D","count": 1543,"preSum": 89494 },{ "ndv": 1543,"upper": "XZXbgusNWNvKhXNOnanOaTJ 7lmri,mz4","lower": "xJSFqeclgLfgWHg7Ny","count": 1543,"preSum": 91037 },{ "ndv": 1543,"upper": "YJp,X0fUZI3 hDv8","lower": "xZXLNFI2tlkpyOYpbzdE","count": 1543,"preSum": 92580 },{ "ndv": 1543,"upper": "yZtCckEeMg,u,XKuhx3V6hNmNnv FYfcCkR,vW","lower": "YJpABKtR8DpISmHEkJ,EzFGttb3KQtDSDmakW","count": 1543,"preSum": 94123 },{ "ndv": 1543,"upper": "zK9ecOyxwo4JS85HzvwsIGh,o6zDXgQokX","lower": "yZtr0jgetIz7pal9t9asYs2UHZK0","count": 1543,"preSum": 95666 },{ "ndv": 1503,"upper": "zzZuPI DYNHaZEnLiA4f jrtXHbJIjF","lower": "ZKa3a7kUW5R,b8Pgy","count": 1503,"preSum": 97209 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  customer.c_address.null_count:
+    0
+  customer.c_address.sample_rate:
+    5.8531115E-4
+  customer.c_comment.TOPN:
+    null
+  customer.c_comment.cardinality:
+    26489630
+  customer.c_comment.histogram:
+    { "buckets": [ { "ndv": 1543,"upper": " asymptotes sleep blithely across the furiously regular packages. slyly brave theodolites","lower": " about the accounts. finally regular ideas according to the bl","count": 1543,"preSum": 0 },{ "ndv": 1543,"upper": " carefully final deposits affix near the deposits. requests boost sly","lower": " asymptotes sleep closely regular platelets; carefully pending instructions affix carefully according to t","count": 1543,"preSum": 1543 },{ "ndv": 1543,"upper": " excuses impress slyly blithely regular requests. pending instructions use slyly along","lower": " carefully final deposits affix. slyly pending requ","count": 1543,"preSum": 3086 },{ "ndv": 1542,"upper": " furiously since the quickly bold deposits. asymptotes after the carefully special instructions use carefu","lower": " excuses integrate fluffily above the deposits-- regular foxes play carefully inst","count": 1543,"preSum": 4629 },{ "ndv": 1543,"upper": " of the fluffily bold deposits. accounts along the quic","lower": " furiously sly instructions. iron","count": 1543,"preSum": 6172 },{ "ndv": 1543,"upper": " regular deposits. slyly even requests use slyly. pinto beans wake. carefully bold instructio","lower": " of the furiously daring request","count": 1543,"preSum": 7715 },{ "ndv": 1543,"upper": " slyly regular foxes after the final grouches affix careful","lower": " regular deposits: furiously silent theodolites hag","count": 1543,"preSum": 9258 },{ "ndv": 1543,"upper": " theodolites. express ideas above the foxes should","lower": " slyly regular foxes alongside of the packages are furiously against the finally even accounts. carefully regula","count": 1543,"preSum": 10801 },{ "ndv": 1543,"upper": ". carefully ironic requests nag carefully. accounts use quickly about the final ideas. special f","lower": " theodolites. express warthogs lose carefully among the carefully bold instruc","count": 1543,"preSum": 12344 },{ "ndv": 1543,"upper": "according to the deposits. stealthy, ironic excuses boost. ironic pinto beans among the car","lower": ". carefully ironic requests promise","count": 1543,"preSum": 13887 },{ "ndv": 1543,"upper": "ages wake quickly. excuses hinder. slyly ironic requests sleep fluffily above t","lower": "according to the even accounts haggle daringly packages. quickly ironic ideas are qui","count": 1543,"preSum": 15430 },{ "ndv": 1543,"upper": "al requests. slyly express deposits","lower": "ages wake quickly. silently bold requests against the carefully express foxes are carefully express packages. fur","count": 1543,"preSum": 16973 },{ "ndv": 1543,"upper": "arefully busy asymptotes cajole blithely bold ideas-- furiously final packages nag fluffily? blithely regular pinto","lower": "al requests. slyly final deposits haggle quickly stealthy theodolites. ironic foxes among the slyly b","count": 1543,"preSum": 18516 },{ "ndv": 1543,"upper": "blithely furiously even accounts. pending,","lower": "arefully busy deposits affix. unusual, pending dolphins no","count": 1543,"preSum": 20059 },{ "ndv": 1543,"upper": "carefully against the always ironic depen","lower": "blithely furiously final deposits. ironic, silent dependencies wake quickly unusual d","count": 1543,"preSum": 21602 },{ "ndv": 1542,"upper": "ckages sleep quickly. quickly ironic theodolites haggle e","lower": "carefully against the carefully","count": 1543,"preSum": 23145 },{ "ndv": 1542,"upper": "d accounts sublate carefully among the carefully regular asymptot","lower": "ckages sleep quiet requests. furiously even deposits sleep furio","count": 1543,"preSum": 24688 },{ "ndv": 1542,"upper": "ding to the slyly express dugouts. regular excuses alongside of the furiously eve","lower": "d accounts to the packages detect furiou","count": 1543,"preSum": 26231 },{ "ndv": 1543,"upper": "e furiously. furiously ironic pinto bea","lower": "ding to the slyly express packages sleep furiously along the grouches. carefully silent notornis am","count": 1543,"preSum": 27774 },{ "ndv": 1543,"upper": "ecial deposits. quickly final accounts c","lower": "e furiously. furiously regular deposits ","count": 1543,"preSum": 29317 },{ "ndv": 1543,"upper": "egular theodolites? carefully even pinto beans wa","lower": "ecial deposits. slyly even escap","count": 1543,"preSum": 30860 },{ "ndv": 1543,"upper": "ent requests. regular pinto beans sleep fluffily final packages. regular accounts wake.","lower": "egular theodolites? slyly ironic the","count": 1543,"preSum": 32403 },{ "ndv": 1543,"upper": "es about the unusual requests unwind blithely the","lower": "ent requests. slyly unusual theodolite","count": 1543,"preSum": 33946 },{ "ndv": 1543,"upper": "ests nag according to the fluffily special accounts. bravely ironic packages despite th","lower": "es above the bold packages doubt around the pending platelets. quietly final theodolites boost along the ","count": 1543,"preSum": 35489 },{ "ndv": 1543,"upper": "fily express ideas haggle furiously r","lower": "ests nag along the carefully special deposits; pending, regular ideas engage carefully ironic a","count": 1543,"preSum": 37032 },{ "ndv": 1542,"upper": "fully regular requests. quickly final pinto ","lower": "fily express requests about the unusual theodolites are fluffily final the","count": 1543,"preSum": 38575 },{ "ndv": 1543,"upper": "ges integrate along the instructions. bravely iro","lower": "fully regular sentiments wake busily after the theodolites. ironic ideas across the regularly final package","count": 1543,"preSum": 40118 },{ "ndv": 1543,"upper": "haggle furiously after the regular packages. ironic, regular foxes haggle","lower": "ges integrate carefully blithely ironic pinto beans","count": 1543,"preSum": 41661 },{ "ndv": 1543,"upper": "heodolites are fluffily. excuses are carefully at the final dolphins. slowly unusual packages haggle carefully ","lower": "haggle furiously against the blithely final pearls. furiously even accounts nag f","count": 1543,"preSum": 43204 },{ "ndv": 1543,"upper": "ideas hinder fluffily carefully special excuses! ironic","lower": "heodolites are furiously ironic packages. blithely express requests above the slyly final deposits are fluffily ","count": 1543,"preSum": 44747 },{ "ndv": 1543,"upper": "inments whithout the furiously even deposits cajole closely","lower": "ideas integrate fluffily even ideas; pending packages according to the slyly final pinto beans ru","count": 1543,"preSum": 46290 },{ "ndv": 1543,"upper": "ironic orbits sleep. bold excuses around the fluffily regular pinto beans sleep slyly accord","lower": "inments. carefully regular instructions haggle carefully slow packages. slyly even packages kindle blithely special","count": 1543,"preSum": 47833 },{ "ndv": 1543,"upper": "jole. final, regular accounts sleep fluffily slyly bold or","lower": "ironic orbits wake regular deposits. quick accounts against the packages would nag across the carefully expre","count": 1543,"preSum": 49376 },{ "ndv": 1543,"upper": "l requests are quickly. blithely ironic dep","lower": "jole. furiously special ideas nag. busily final deposits nag slyly final, regular","count": 1543,"preSum": 50919 },{ "ndv": 1542,"upper": "le slyly furiously final deposits. pending ","lower": "l requests are slyly above the ironic, final packages: regular, pending packages boost carefully alongside o","count": 1543,"preSum": 52462 },{ "ndv": 1543,"upper": "lly regular asymptotes wake f","lower": "le slyly furiously ironic requests. carefully special dependencies hag","count": 1543,"preSum": 54005 },{ "ndv": 1542,"upper": "ly express asymptotes. ironically ironic foxes cajole carefully. slyly final theodolites about the slyly furiou","lower": "lly regular asymptotes. carefully even frets use. express theodolites","count": 1543,"preSum": 55548 },{ "ndv": 1543,"upper": "ly special requests. express, express instruction","lower": "ly express braids cajole carefully furiously ironic platelets. final, idle platelets for the furiously regular p","count": 1543,"preSum": 57091 },{ "ndv": 1543,"upper": "n requests nag furiously after the final, final ","lower": "ly special requests. instructions cajole blithely above the silently final instructions. platelets caj","count": 1543,"preSum": 58634 },{ "ndv": 1543,"upper": "ng the ruthless, regular packages nag furiously expr","lower": "n requests nag quickly carefully even dependencies. ironic packages are evenly dogged pack","count": 1543,"preSum": 60177 },{ "ndv": 1543,"upper": "nt packages affix furiously busily ironic packages. idle, special pi","lower": "ng the ruthlessly even excuses haggle accor","count": 1543,"preSum": 61720 },{ "ndv": 1543,"upper": "old accounts are ironic frets. final, final packages among the quickly regular pinto ","lower": "nt packages affix quickly furiously regular foxes; quickly ","count": 1543,"preSum": 63263 },{ "ndv": 1543,"upper": "ons. packages against the slyly special deposits cajole quickly express deposits; blithely iron","lower": "old accounts are quickly slyly special requests? slyly ironic deposits wake slyly bold cour","count": 1543,"preSum": 64806 },{ "ndv": 1543,"upper": "ously around the accounts. packages haggle blithely ironic, idle ac","lower": "ons. pending, ironic foxes according to the instructions wake slyly slyly pen","count": 1543,"preSum": 66349 },{ "ndv": 1542,"upper": "pecial deposits cajole blithely among the carefully final foxes: express, final p","lower": "ously around the bold, special excuses. depths wake carefully alongside of the furiously unusual excuses. final p","count": 1543,"preSum": 67892 },{ "ndv": 1543,"upper": "press requests run alongside of the sly","lower": "pecial deposits cajole fluffily decoys. sometimes","count": 1543,"preSum": 69435 },{ "ndv": 1543,"upper": "r, express ideas haggle blithely. express, special foxes use closely according to the doggedly unusual asymptotes. p","lower": "press requests run blithely across the pending packages. slyly ironic dolphins cajole slyly amon","count": 1543,"preSum": 70978 },{ "ndv": 1543,"upper": "requests according to the slyly regular excuses snooze blithely along the even packages. final requests use care","lower": "r, express instructions. furiously bold depths lose blithely silent packages. even, final deposits cajole quickly f","count": 1543,"preSum": 72521 },{ "ndv": 1543,"upper": "ronic requests eat. slyly pending packages haggle quickly final requests","lower": "requests across the furiously ironic foxes sleep quickly furiously unusu","count": 1543,"preSum": 74064 },{ "ndv": 1543,"upper": "s dazzle furiously ironic requests. bold foxes haggle slyly. furious","lower": "ronic requests haggle blithely. slowly ironic ideas against the fluffily ","count": 1543,"preSum": 75607 },{ "ndv": 1542,"upper": "s. always regular deposits affix blithely theodolites. furiously silent requests about the furious, ironic acco","lower": "s dazzle quickly final accounts. close foxes cajole blithely. special","count": 1543,"preSum": 77150 },{ "ndv": 1542,"upper": "side of the pending requests. furiously regular pinto beans would sleep carefully final excuses. carefully ironic d","lower": "s. always unusual requests was about the slyly special requests. asympto","count": 1543,"preSum": 78693 },{ "ndv": 1543,"upper": "slyly fluffily unusual accounts. bold instr","lower": "side of the pinto beans. slyly express theodolites sleep regular, special platelets. slyly bold depos","count": 1543,"preSum": 80236 },{ "ndv": 1543,"upper": "sts. slyly ironic ideas beyond the regular ideas cajole ironic, bold escapades. regular ","lower": "slyly furious requests. fluffily even accounts along ","count": 1543,"preSum": 81779 },{ "ndv": 1543,"upper": "tes. quiet deposits are above the regular packages. bol","lower": "sts. slyly pending packages haggle about the regular, final pinto beans. silent, ironic req","count": 1543,"preSum": 83322 },{ "ndv": 1543,"upper": "thily special ideas thrash blithely about the slyly express deposits. acco","lower": "tes. regular deposits are across the slyly ironic foxes. pending, ironic packages sleep according to the quickly ","count": 1543,"preSum": 84865 },{ "ndv": 1543,"upper": "ts kindle quickly. quickly ironic ideas haggle express accounts. express r","lower": "thin courts. blithely regular multipliers are furiously regular orbits. regular instructions boost fluffily. fur","count": 1543,"preSum": 86408 },{ "ndv": 1542,"upper": "uests x-ray bold foxes. slyly bold deposits ","lower": "ts kindle. permanently ironic accounts grow carefully furiously regular packages-- final ideas whit","count": 1543,"preSum": 87951 },{ "ndv": 1543,"upper": "ully final dependencies sleep across the bold, final instructions. theodolites wake fluffily along the quick","lower": "uests x-ray ironically ironic, special ideas. furiously regular a","count": 1543,"preSum": 89494 },{ "ndv": 1542,"upper": "urts. carefully silent pinto beans s","lower": "ully final dependencies sleep. carefully final ideas haggle fu","count": 1543,"preSum": 91037 },{ "ndv": 1543,"upper": "ven requests wake. express, special deposits haggle across the regular packages. final, regular ex","lower": "urts. decoys about the ideas sleep about the deposits. even theodolites haggle across the bold deposits. blithel","count": 1543,"preSum": 92580 },{ "ndv": 1543,"upper": "y carefully final grouches. carefully ironic multipliers sleep carefully. regular theodolites sleep quickly. fur","lower": "ven requests. blithely pending requests kindle. f","count": 1543,"preSum": 94123 },{ "ndv": 1543,"upper": "y regular pinto beans across the even packag","lower": "y carefully final pearls. regular deposits grow blithely across ","count": 1543,"preSum": 95666 },{ "ndv": 1502,"upper": "zzle-- final, unusual platelets above the carefully pending platelets can wake slyly along the carefully final ","lower": "y regular pinto beans after the carefully even requests detect quickly around the carefully final account","count": 1503,"preSum": 97209 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  customer.c_comment.null_count:
+    0
+  customer.c_comment.sample_rate:
+    5.8531115E-4
+  customer.c_custkey.TOPN:
+    null
+  customer.c_custkey.cardinality:
+    25502255
+  customer.c_custkey.histogram:
+    { "buckets": [ { "ndv": 1543,"upper": 1552,"lower": 1,"count": 1543,"preSum": 0 },{ "ndv": 1543,"upper": 3147,"lower": 1553,"count": 1543,"preSum": 1543 },{ "ndv": 1543,"upper": 4825,"lower": 3148,"count": 1543,"preSum": 3086 },{ "ndv": 1543,"upper": 6813,"lower": 4826,"count": 1543,"preSum": 4629 },{ "ndv": 1543,"upper": 243881,"lower": 6814,"count": 1543,"preSum": 6172 },{ "ndv": 1543,"upper": 3605921,"lower": 243997,"count": 1543,"preSum": 7715 },{ "ndv": 1543,"upper": 5782857,"lower": 3606174,"count": 1543,"preSum": 9258 },{ "ndv": 1543,"upper": 8010128,"lower": 5782889,"count": 1543,"preSum": 10801 },{ "ndv": 1543,"upper": 10582972,"lower": 8010825,"count": 1543,"preSum": 12344 },{ "ndv": 1543,"upper": 12868648,"lower": 10582975,"count": 1543,"preSum": 13887 },{ "ndv": 1543,"upper": 15268996,"lower": 12868754,"count": 1543,"preSum": 15430 },{ "ndv": 1543,"upper": 17333201,"lower": 15269060,"count": 1543,"preSum": 16973 },{ "ndv": 1543,"upper": 19854858,"lower": 17333233,"count": 1543,"preSum": 18516 },{ "ndv": 1543,"upper": 21667621,"lower": 19854918,"count": 1543,"preSum": 20059 },{ "ndv": 1543,"upper": 24290113,"lower": 21667635,"count": 1543,"preSum": 21602 },{ "ndv": 1543,"upper": 26429189,"lower": 24290126,"count": 1543,"preSum": 23145 },{ "ndv": 1543,"upper": 28344030,"lower": 26429213,"count": 1543,"preSum": 24688 },{ "ndv": 1543,"upper": 30394610,"lower": 28344062,"count": 1543,"preSum": 26231 },{ "ndv": 1543,"upper": 34224059,"lower": 30394611,"count": 1543,"preSum": 27774 },{ "ndv": 1543,"upper": 36732026,"lower": 34224095,"count": 1543,"preSum": 29317 },{ "ndv": 1543,"upper": 39416568,"lower": 36842778,"count": 1543,"preSum": 30860 },{ "ndv": 1543,"upper": 41506227,"lower": 39416668,"count": 1543,"preSum": 32403 },{ "ndv": 1543,"upper": 44201297,"lower": 41506313,"count": 1543,"preSum": 33946 },{ "ndv": 1543,"upper": 46579633,"lower": 44201329,"count": 1543,"preSum": 35489 },{ "ndv": 1543,"upper": 48797120,"lower": 46580819,"count": 1543,"preSum": 37032 },{ "ndv": 1543,"upper": 50928577,"lower": 48797121,"count": 1543,"preSum": 38575 },{ "ndv": 1543,"upper": 53965317,"lower": 50928578,"count": 1543,"preSum": 40118 },{ "ndv": 1543,"upper": 56888396,"lower": 53965724,"count": 1543,"preSum": 41661 },{ "ndv": 1543,"upper": 60170567,"lower": 56888410,"count": 1543,"preSum": 43204 },{ "ndv": 1543,"upper": 62740707,"lower": 60170599,"count": 1543,"preSum": 44747 },{ "ndv": 1543,"upper": 64595607,"lower": 62741070,"count": 1543,"preSum": 46290 },{ "ndv": 1543,"upper": 66556821,"lower": 64595972,"count": 1543,"preSum": 47833 },{ "ndv": 1543,"upper": 69535893,"lower": 66556852,"count": 1543,"preSum": 49376 },{ "ndv": 1543,"upper": 72058148,"lower": 69536659,"count": 1543,"preSum": 50919 },{ "ndv": 1543,"upper": 74334494,"lower": 72058180,"count": 1543,"preSum": 52462 },{ "ndv": 1543,"upper": 77519578,"lower": 74334601,"count": 1543,"preSum": 54005 },{ "ndv": 1543,"upper": 79230375,"lower": 77519579,"count": 1543,"preSum": 55548 },{ "ndv": 1543,"upper": 82133383,"lower": 79230383,"count": 1543,"preSum": 57091 },{ "ndv": 1543,"upper": 84556463,"lower": 82133563,"count": 1543,"preSum": 58634 },{ "ndv": 1543,"upper": 87347159,"lower": 84556548,"count": 1543,"preSum": 60177 },{ "ndv": 1543,"upper": 88976619,"lower": 87347184,"count": 1543,"preSum": 61720 },{ "ndv": 1543,"upper": 91830354,"lower": 88976673,"count": 1543,"preSum": 63263 },{ "ndv": 1543,"upper": 94537428,"lower": 91830386,"count": 1543,"preSum": 64806 },{ "ndv": 1543,"upper": 97272808,"lower": 94537429,"count": 1543,"preSum": 66349 },{ "ndv": 1543,"upper": 100157299,"lower": 97272809,"count": 1543,"preSum": 67892 },{ "ndv": 1543,"upper": 103160640,"lower": 100157325,"count": 1543,"preSum": 69435 },{ "ndv": 1543,"upper": 106040916,"lower": 103160886,"count": 1543,"preSum": 70978 },{ "ndv": 1543,"upper": 108895695,"lower": 106040948,"count": 1543,"preSum": 72521 },{ "ndv": 1543,"upper": 111618823,"lower": 108895724,"count": 1543,"preSum": 74064 },{ "ndv": 1543,"upper": 114220265,"lower": 111618970,"count": 1543,"preSum": 75607 },{ "ndv": 1543,"upper": 116276242,"lower": 114220266,"count": 1543,"preSum": 77150 },{ "ndv": 1543,"upper": 118743161,"lower": 116276303,"count": 1543,"preSum": 78693 },{ "ndv": 1543,"upper": 121091785,"lower": 118743221,"count": 1543,"preSum": 80236 },{ "ndv": 1543,"upper": 123437220,"lower": 121091786,"count": 1543,"preSum": 81779 },{ "ndv": 1543,"upper": 126342796,"lower": 123437478,"count": 1543,"preSum": 83322 },{ "ndv": 1543,"upper": 127827475,"lower": 126342827,"count": 1543,"preSum": 84865 },{ "ndv": 1543,"upper": 130722361,"lower": 127827645,"count": 1543,"preSum": 86408 },{ "ndv": 1543,"upper": 133142332,"lower": 130722776,"count": 1543,"preSum": 87951 },{ "ndv": 1543,"upper": 135846876,"lower": 133142359,"count": 1543,"preSum": 89494 },{ "ndv": 1543,"upper": 138672626,"lower": 135846877,"count": 1543,"preSum": 91037 },{ "ndv": 1543,"upper": 142004230,"lower": 138672627,"count": 1543,"preSum": 92580 },{ "ndv": 1543,"upper": 144773115,"lower": 142004308,"count": 1543,"preSum": 94123 },{ "ndv": 1543,"upper": 146998400,"lower": 144773623,"count": 1543,"preSum": 95666 },{ "ndv": 1503,"upper": 149965863,"lower": 146998480,"count": 1503,"preSum": 97209 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  customer.c_custkey.null_count:
+    0
+  customer.c_custkey.sample_rate:
+    5.8531115E-4
+  customer.c_mktsegment.TOPN:
+    { "countArr": [ 19874,19942,19586,19665,19645 ],"valueArr": [ "AUTOMOBILE","BUILDING","FURNITURE","HOUSEHOLD","MACHINERY" ],"type": "String","sampleRate": 1.0 }
+  customer.c_mktsegment.cardinality:
+    5
+  customer.c_mktsegment.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  customer.c_mktsegment.null_count:
+    0
+  customer.c_mktsegment.sample_rate:
+    5.8531115E-4
+  customer.c_name.TOPN:
+    null
+  customer.c_name.cardinality:
+    26406121
+  customer.c_name.histogram:
+    { "buckets": [ { "ndv": 1543,"upper": "Customer#000001552","lower": "Customer#000000001","count": 1543,"preSum": 0 },{ "ndv": 1543,"upper": "Customer#000003147","lower": "Customer#000001553","count": 1543,"preSum": 1543 },{ "ndv": 1543,"upper": "Customer#000004825","lower": "Customer#000003148","count": 1543,"preSum": 3086 },{ "ndv": 1543,"upper": "Customer#000006813","lower": "Customer#000004826","count": 1543,"preSum": 4629 },{ "ndv": 1543,"upper": "Customer#000243881","lower": "Customer#000006814","count": 1543,"preSum": 6172 },{ "ndv": 1543,"upper": "Customer#003605921","lower": "Customer#000243997","count": 1543,"preSum": 7715 },{ "ndv": 1543,"upper": "Customer#005782857","lower": "Customer#003606174","count": 1543,"preSum": 9258 },{ "ndv": 1543,"upper": "Customer#008010128","lower": "Customer#005782889","count": 1543,"preSum": 10801 },{ "ndv": 1543,"upper": "Customer#010582972","lower": "Customer#008010825","count": 1543,"preSum": 12344 },{ "ndv": 1543,"upper": "Customer#012868648","lower": "Customer#010582975","count": 1543,"preSum": 13887 },{ "ndv": 1543,"upper": "Customer#015268996","lower": "Customer#012868754","count": 1543,"preSum": 15430 },{ "ndv": 1543,"upper": "Customer#017333201","lower": "Customer#015269060","count": 1543,"preSum": 16973 },{ "ndv": 1543,"upper": "Customer#019854858","lower": "Customer#017333233","count": 1543,"preSum": 18516 },{ "ndv": 1543,"upper": "Customer#021667621","lower": "Customer#019854918","count": 1543,"preSum": 20059 },{ "ndv": 1543,"upper": "Customer#024290113","lower": "Customer#021667635","count": 1543,"preSum": 21602 },{ "ndv": 1543,"upper": "Customer#026429189","lower": "Customer#024290126","count": 1543,"preSum": 23145 },{ "ndv": 1543,"upper": "Customer#028344030","lower": "Customer#026429213","count": 1543,"preSum": 24688 },{ "ndv": 1543,"upper": "Customer#030394610","lower": "Customer#028344062","count": 1543,"preSum": 26231 },{ "ndv": 1543,"upper": "Customer#034224059","lower": "Customer#030394611","count": 1543,"preSum": 27774 },{ "ndv": 1543,"upper": "Customer#036732026","lower": "Customer#034224095","count": 1543,"preSum": 29317 },{ "ndv": 1543,"upper": "Customer#039416568","lower": "Customer#036842778","count": 1543,"preSum": 30860 },{ "ndv": 1543,"upper": "Customer#041506227","lower": "Customer#039416668","count": 1543,"preSum": 32403 },{ "ndv": 1543,"upper": "Customer#044201297","lower": "Customer#041506313","count": 1543,"preSum": 33946 },{ "ndv": 1543,"upper": "Customer#046579633","lower": "Customer#044201329","count": 1543,"preSum": 35489 },{ "ndv": 1543,"upper": "Customer#048797120","lower": "Customer#046580819","count": 1543,"preSum": 37032 },{ "ndv": 1543,"upper": "Customer#050928577","lower": "Customer#048797121","count": 1543,"preSum": 38575 },{ "ndv": 1543,"upper": "Customer#053965317","lower": "Customer#050928578","count": 1543,"preSum": 40118 },{ "ndv": 1543,"upper": "Customer#056888396","lower": "Customer#053965724","count": 1543,"preSum": 41661 },{ "ndv": 1543,"upper": "Customer#060170567","lower": "Customer#056888410","count": 1543,"preSum": 43204 },{ "ndv": 1543,"upper": "Customer#062740707","lower": "Customer#060170599","count": 1543,"preSum": 44747 },{ "ndv": 1543,"upper": "Customer#064595607","lower": "Customer#062741070","count": 1543,"preSum": 46290 },{ "ndv": 1543,"upper": "Customer#066556821","lower": "Customer#064595972","count": 1543,"preSum": 47833 },{ "ndv": 1543,"upper": "Customer#069535893","lower": "Customer#066556852","count": 1543,"preSum": 49376 },{ "ndv": 1543,"upper": "Customer#072058148","lower": "Customer#069536659","count": 1543,"preSum": 50919 },{ "ndv": 1543,"upper": "Customer#074334494","lower": "Customer#072058180","count": 1543,"preSum": 52462 },{ "ndv": 1543,"upper": "Customer#077519578","lower": "Customer#074334601","count": 1543,"preSum": 54005 },{ "ndv": 1543,"upper": "Customer#079230375","lower": "Customer#077519579","count": 1543,"preSum": 55548 },{ "ndv": 1543,"upper": "Customer#082133383","lower": "Customer#079230383","count": 1543,"preSum": 57091 },{ "ndv": 1543,"upper": "Customer#084556463","lower": "Customer#082133563","count": 1543,"preSum": 58634 },{ "ndv": 1543,"upper": "Customer#087347159","lower": "Customer#084556548","count": 1543,"preSum": 60177 },{ "ndv": 1543,"upper": "Customer#088976619","lower": "Customer#087347184","count": 1543,"preSum": 61720 },{ "ndv": 1543,"upper": "Customer#091830354","lower": "Customer#088976673","count": 1543,"preSum": 63263 },{ "ndv": 1543,"upper": "Customer#094537428","lower": "Customer#091830386","count": 1543,"preSum": 64806 },{ "ndv": 1543,"upper": "Customer#097272808","lower": "Customer#094537429","count": 1543,"preSum": 66349 },{ "ndv": 1543,"upper": "Customer#100157299","lower": "Customer#097272809","count": 1543,"preSum": 67892 },{ "ndv": 1543,"upper": "Customer#103160640","lower": "Customer#100157325","count": 1543,"preSum": 69435 },{ "ndv": 1543,"upper": "Customer#106040916","lower": "Customer#103160886","count": 1543,"preSum": 70978 },{ "ndv": 1543,"upper": "Customer#108895695","lower": "Customer#106040948","count": 1543,"preSum": 72521 },{ "ndv": 1543,"upper": "Customer#111618823","lower": "Customer#108895724","count": 1543,"preSum": 74064 },{ "ndv": 1543,"upper": "Customer#114220265","lower": "Customer#111618970","count": 1543,"preSum": 75607 },{ "ndv": 1543,"upper": "Customer#116276242","lower": "Customer#114220266","count": 1543,"preSum": 77150 },{ "ndv": 1543,"upper": "Customer#118743161","lower": "Customer#116276303","count": 1543,"preSum": 78693 },{ "ndv": 1543,"upper": "Customer#121091785","lower": "Customer#118743221","count": 1543,"preSum": 80236 },{ "ndv": 1543,"upper": "Customer#123437220","lower": "Customer#121091786","count": 1543,"preSum": 81779 },{ "ndv": 1543,"upper": "Customer#126342796","lower": "Customer#123437478","count": 1543,"preSum": 83322 },{ "ndv": 1543,"upper": "Customer#127827475","lower": "Customer#126342827","count": 1543,"preSum": 84865 },{ "ndv": 1543,"upper": "Customer#130722361","lower": "Customer#127827645","count": 1543,"preSum": 86408 },{ "ndv": 1543,"upper": "Customer#133142332","lower": "Customer#130722776","count": 1543,"preSum": 87951 },{ "ndv": 1543,"upper": "Customer#135846876","lower": "Customer#133142359","count": 1543,"preSum": 89494 },{ "ndv": 1543,"upper": "Customer#138672626","lower": "Customer#135846877","count": 1543,"preSum": 91037 },{ "ndv": 1543,"upper": "Customer#142004230","lower": "Customer#138672627","count": 1543,"preSum": 92580 },{ "ndv": 1543,"upper": "Customer#144773115","lower": "Customer#142004308","count": 1543,"preSum": 94123 },{ "ndv": 1543,"upper": "Customer#146998400","lower": "Customer#144773623","count": 1543,"preSum": 95666 },{ "ndv": 1503,"upper": "Customer#149965863","lower": "Customer#146998480","count": 1503,"preSum": 97209 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  customer.c_name.null_count:
+    0
+  customer.c_name.sample_rate:
+    5.8531115E-4
+  customer.c_nationkey.TOPN:
+    { "countArr": [ 3972,3963,3961,4009,3938,3966,3970,4047,3968,3961,4025,4042,3961,3984 ],"valueArr": [ 1,2,4,5,7,9,11,15,17,19,21,22,23,24 ],"type": "Int","sampleRate": 1.0 }
+  customer.c_nationkey.cardinality:
+    25
+  customer.c_nationkey.histogram:
+    { "buckets": [ { "ndv": 1,"upper": 0,"lower": 0,"count": 3881,"preSum": 0 },{ "ndv": 1,"upper": 3,"lower": 3,"count": 3919,"preSum": 3881 },{ "ndv": 1,"upper": 6,"lower": 6,"count": 3921,"preSum": 7800 },{ "ndv": 1,"upper": 8,"lower": 8,"count": 3933,"preSum": 11721 },{ "ndv": 1,"upper": 10,"lower": 10,"count": 3905,"preSum": 15654 },{ "ndv": 1,"upper": 12,"lower": 12,"count": 3924,"preSum": 19559 },{ "ndv": 1,"upper": 13,"lower": 13,"count": 3913,"preSum": 23483 },{ "ndv": 1,"upper": 14,"lower": 14,"count": 3849,"preSum": 27396 },{ "ndv": 1,"upper": 16,"lower": 16,"count": 3934,"preSum": 31245 },{ "ndv": 1,"upper": 18,"lower": 18,"count": 3839,"preSum": 35179 },{ "ndv": 1,"upper": 20,"lower": 20,"count": 3927,"preSum": 39018 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  customer.c_nationkey.null_count:
+    0
+  customer.c_nationkey.sample_rate:
+    5.8531115E-4
+  customer.c_phone.TOPN:
+    null
+  customer.c_phone.cardinality:
+    25708904
+  customer.c_phone.histogram:
+    { "buckets": [ { "ndv": 1543,"upper": "10-445-192-2840","lower": "10-100-157-8855","count": 1543,"preSum": 0 },{ "ndv": 1543,"upper": "10-807-168-3490","lower": "10-445-568-8835","count": 1543,"preSum": 1543 },{ "ndv": 1543,"upper": "11-265-382-6067","lower": "10-807-226-7225","count": 1543,"preSum": 3086 },{ "ndv": 1543,"upper": "11-611-702-6738","lower": "11-265-520-8831","count": 1543,"preSum": 4629 },{ "ndv": 1543,"upper": "11-967-766-6303","lower": "11-611-769-7796","count": 1543,"preSum": 6172 },{ "ndv": 1543,"upper": "12-419-957-9385","lower": "11-968-178-7389","count": 1543,"preSum": 7715 },{ "ndv": 1543,"upper": "12-759-198-4121","lower": "12-420-271-8606","count": 1543,"preSum": 9258 },{ "ndv": 1543,"upper": "13-225-754-2861","lower": "12-759-251-3174","count": 1543,"preSum": 10801 },{ "ndv": 1543,"upper": "13-570-144-3326","lower": "13-225-834-3330","count": 1543,"preSum": 12344 },{ "ndv": 1543,"upper": "13-930-645-9210","lower": "13-570-333-7053","count": 1543,"preSum": 13887 },{ "ndv": 1543,"upper": "14-389-556-3643","lower": "13-930-976-3992","count": 1543,"preSum": 15430 },{ "ndv": 1543,"upper": "14-737-548-5766","lower": "14-389-883-1447","count": 1543,"preSum": 16973 },{ "ndv": 1543,"upper": "15-182-688-5786","lower": "14-737-596-8196","count": 1543,"preSum": 18516 },{ "ndv": 1543,"upper": "15-523-622-2600","lower": "15-183-241-8154","count": 1543,"preSum": 20059 },{ "ndv": 1543,"upper": "15-871-828-2503","lower": "15-524-173-5237","count": 1543,"preSum": 21602 },{ "ndv": 1543,"upper": "16-322-926-2370","lower": "15-872-144-4978","count": 1543,"preSum": 23145 },{ "ndv": 1543,"upper": "16-674-444-9392","lower": "16-323-260-5256","count": 1543,"preSum": 24688 },{ "ndv": 1543,"upper": "17-128-318-3692","lower": "16-674-588-3330","count": 1543,"preSum": 26231 },{ "ndv": 1543,"upper": "17-486-373-7798","lower": "17-128-385-4011","count": 1543,"preSum": 27774 },{ "ndv": 1543,"upper": "17-850-387-8517","lower": "17-486-384-6410","count": 1543,"preSum": 29317 },{ "ndv": 1543,"upper": "18-302-575-3509","lower": "17-850-584-4603","count": 1543,"preSum": 30860 },{ "ndv": 1543,"upper": "18-659-334-9394","lower": "18-303-157-6412","count": 1543,"preSum": 32403 },{ "ndv": 1543,"upper": "18-998-797-6780","lower": "18-659-742-7524","count": 1543,"preSum": 33946 },{ "ndv": 1543,"upper": "19-458-267-2017","lower": "18-999-148-1049","count": 1543,"preSum": 35489 },{ "ndv": 1543,"upper": "19-804-409-3962","lower": "19-458-653-5937","count": 1543,"preSum": 37032 },{ "ndv": 1543,"upper": "20-243-550-1594","lower": "19-804-510-1393","count": 1543,"preSum": 38575 },{ "ndv": 1543,"upper": "20-600-270-1560","lower": "20-243-672-4974","count": 1543,"preSum": 40118 },{ "ndv": 1543,"upper": "20-961-524-1322","lower": "20-600-354-1647","count": 1543,"preSum": 41661 },{ "ndv": 1543,"upper": "21-413-108-9516","lower": "20-961-780-2699","count": 1543,"preSum": 43204 },{ "ndv": 1543,"upper": "21-766-674-4058","lower": "21-413-166-3123","count": 1543,"preSum": 44747 },{ "ndv": 1543,"upper": "22-215-199-9619","lower": "21-766-712-1161","count": 1543,"preSum": 46290 },{ "ndv": 1543,"upper": "22-570-367-7247","lower": "22-215-549-2774","count": 1543,"preSum": 47833 },{ "ndv": 1543,"upper": "22-921-206-8431","lower": "22-570-447-7104","count": 1543,"preSum": 49376 },{ "ndv": 1543,"upper": "23-358-532-2073","lower": "22-921-406-7573","count": 1543,"preSum": 50919 },{ "ndv": 1543,"upper": "23-723-698-6347","lower": "23-358-543-4791","count": 1543,"preSum": 52462 },{ "ndv": 1543,"upper": "24-179-649-9214","lower": "23-723-712-1536","count": 1543,"preSum": 54005 },{ "ndv": 1543,"upper": "24-551-325-1596","lower": "24-179-830-8941","count": 1543,"preSum": 55548 },{ "ndv": 1543,"upper": "24-908-381-3465","lower": "24-551-342-8911","count": 1543,"preSum": 57091 },{ "ndv": 1543,"upper": "25-349-903-7736","lower": "24-908-682-4518","count": 1543,"preSum": 58634 },{ "ndv": 1543,"upper": "25-687-775-2302","lower": "25-350-121-9158","count": 1543,"preSum": 60177 },{ "ndv": 1543,"upper": "26-142-912-8052","lower": "25-687-926-6714","count": 1543,"preSum": 61720 },{ "ndv": 1543,"upper": "26-497-211-6072","lower": "26-143-412-1698","count": 1543,"preSum": 63263 },{ "ndv": 1543,"upper": "26-844-537-8159","lower": "26-497-515-7910","count": 1543,"preSum": 64806 },{ "ndv": 1543,"upper": "27-308-950-7827","lower": "26-844-679-1540","count": 1543,"preSum": 66349 },{ "ndv": 1543,"upper": "27-660-748-4032","lower": "27-309-305-2455","count": 1543,"preSum": 67892 },{ "ndv": 1543,"upper": "28-102-363-4931","lower": "27-660-845-1320","count": 1543,"preSum": 69435 },{ "ndv": 1543,"upper": "28-465-202-9678","lower": "28-102-395-8263","count": 1543,"preSum": 70978 },{ "ndv": 1543,"upper": "28-821-279-3248","lower": "28-465-312-8785","count": 1543,"preSum": 72521 },{ "ndv": 1543,"upper": "29-281-554-7405","lower": "28-821-481-9922","count": 1543,"preSum": 74064 },{ "ndv": 1543,"upper": "29-639-105-2401","lower": "29-281-694-5534","count": 1543,"preSum": 75607 },{ "ndv": 1543,"upper": "29-982-496-2528","lower": "29-639-278-8056","count": 1543,"preSum": 77150 },{ "ndv": 1543,"upper": "30-432-115-2732","lower": "29-982-521-1618","count": 1543,"preSum": 78693 },{ "ndv": 1543,"upper": "30-786-518-4678","lower": "30-432-175-4200","count": 1543,"preSum": 80236 },{ "ndv": 1543,"upper": "31-233-730-3788","lower": "30-786-960-7152","count": 1543,"preSum": 81779 },{ "ndv": 1543,"upper": "31-573-126-9200","lower": "31-234-132-2870","count": 1543,"preSum": 83322 },{ "ndv": 1543,"upper": "31-923-543-7765","lower": "31-573-170-9616","count": 1543,"preSum": 84865 },{ "ndv": 1543,"upper": "32-375-927-2509","lower": "31-923-632-8740","count": 1543,"preSum": 86408 },{ "ndv": 1543,"upper": "32-725-456-4078","lower": "32-375-931-7206","count": 1543,"preSum": 87951 },{ "ndv": 1543,"upper": "33-157-238-4994","lower": "32-725-666-4667","count": 1543,"preSum": 89494 },{ "ndv": 1543,"upper": "33-516-911-1728","lower": "33-157-279-6120","count": 1543,"preSum": 91037 },{ "ndv": 1543,"upper": "33-864-170-7646","lower": "33-517-156-6120","count": 1543,"preSum": 92580 },{ "ndv": 1543,"upper": "34-313-376-1387","lower": "33-864-367-2505","count": 1543,"preSum": 94123 },{ "ndv": 1543,"upper": "34-663-864-4508","lower": "34-313-610-2278","count": 1543,"preSum": 95666 },{ "ndv": 1503,"upper": "34-999-811-2153","lower": "34-664-172-8789","count": 1503,"preSum": 97209 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  customer.c_phone.null_count:
+    0
+  customer.c_phone.sample_rate:
+    5.8531115E-4
+  lineitem.l_comment.TOPN:
+    { "countArr": [ 9,11,13,11,11,12,14,11,19,11,9,9,10 ],"valueArr": [ " across th"," blithely "," carefully"," carefully "," deposits "," furiously"," furiously "," requests ","carefully ","furiously ","heodolites","ly regular ","y regular " ],"type": "String","sampleRate": 1.0 }
+  lineitem.l_comment.cardinality:
+    86365427
+  lineitem.l_comment.histogram:
+    { "buckets": [ { "ndv": 1326,"upper": " asymptotes. regular","lower": " about the","count": 1426,"preSum": 0 },{ "ndv": 1351,"upper": " carefully ironic ideas. slyly bold","lower": " asymptotes. sly","count": 1426,"preSum": 1426 },{ "ndv": 1352,"upper": " express dependencies. blithely","lower": " carefully ironic instruct","count": 1426,"preSum": 2852 },{ "ndv": 1340,"upper": " gifts. quickly regular requests hag","lower": " express dependencies. slyly s","count": 1426,"preSum": 4278 },{ "ndv": 1350,"upper": " packages among the slyly bold accounts u","lower": " gifts. slyly silent requ","count": 1426,"preSum": 5704 },{ "ndv": 1329,"upper": " regular ideas. bold packages above ","lower": " packages are ","count": 1426,"preSum": 7130 },{ "ndv": 1345,"upper": " slyly regular pinto beans wake slyl","lower": " regular ideas. bold reque","count": 1426,"preSum": 8556 },{ "ndv": 1322,"upper": " theodolites. slowly ironic idea","lower": " slyly regular pinto beans. theodolites us","count": 1426,"preSum": 9982 },{ "ndv": 1369,"upper": ". carefully special deposits haggle carefu","lower": " theodolites. slyly ","count": 1426,"preSum": 11408 },{ "ndv": 1348,"upper": "according to the fluffily fina","lower": ". carefully special dolphins sle","count": 1426,"preSum": 12834 },{ "ndv": 1365,"upper": "ages. carefully even foxes","lower": "according to the fluffily final ","count": 1426,"preSum": 14260 },{ "ndv": 1364,"upper": "al waters are deposits. pending,","lower": "ages. carefully quiet inst","count": 1426,"preSum": 15686 },{ "ndv": 1375,"upper": "arefully express pinto beans. slyl","lower": "al, blithe request","count": 1426,"preSum": 17112 },{ "ndv": 1362,"upper": "blithely ironic packages. furiousl","lower": "arefully express pinto beans: entic","count": 1426,"preSum": 18538 },{ "ndv": 1386,"upper": "carefully bold accoun","lower": "blithely ironic packages; slyly pen","count": 1426,"preSum": 19964 },{ "ndv": 1340,"upper": "ckages! blithely","lower": "carefully bold dependenc","count": 1426,"preSum": 21390 },{ "ndv": 1372,"upper": "d deposits. regular ","lower": "ckages! blithely enticing deposi","count": 1426,"preSum": 22816 },{ "ndv": 1394,"upper": "dogged requests. slyly even plate","lower": "d deposits. sly deposits ","count": 1426,"preSum": 24242 },{ "ndv": 1357,"upper": "e of the ironic, unu","lower": "dogged, even requests: ","count": 1426,"preSum": 25668 },{ "ndv": 1399,"upper": "ecial theodolites cajole furiously ","lower": "e of the ironically even requests are f","count": 1426,"preSum": 27094 },{ "ndv": 1359,"upper": "elets. quickly regular accounts caj","lower": "ecial theodolites cajole furiously flu","count": 1426,"preSum": 28520 },{ "ndv": 1382,"upper": "eodolites. pending, ironic requests af","lower": "elets. quietly pending acco","count": 1426,"preSum": 29946 },{ "ndv": 1388,"upper": "es boost furiously afte","lower": "eodolites. platelets sleep s","count": 1426,"preSum": 31372 },{ "ndv": 1391,"upper": "ests. blithely even packages ca","lower": "es boost furiously final foxes. carefully","count": 1426,"preSum": 32798 },{ "ndv": 1397,"upper": "fily regular instructions sleep slyl","lower": "ests. blithely even packages detect","count": 1426,"preSum": 34224 },{ "ndv": 1359,"upper": "fully silent deposits sleep","lower": "fily regular instructions x-r","count": 1426,"preSum": 35650 },{ "ndv": 1376,"upper": "ges haggle according to the sl","lower": "fully silent deposits.","count": 1426,"preSum": 37076 },{ "ndv": 1356,"upper": "haggle carefully above the blithely regu","lower": "ges haggle after the slyly ironi","count": 1426,"preSum": 38502 },{ "ndv": 1356,"upper": "heodolites b","lower": "haggle carefully above the carefully pen","count": 1427,"preSum": 39928 },{ "ndv": 1396,"upper": "ideas are of the slyly bold sh","lower": "heodolites behind the fu","count": 1426,"preSum": 41355 },{ "ndv": 1395,"upper": "ing, express deposits doubt furiously ","lower": "ideas are quickly pack","count": 1426,"preSum": 42781 },{ "ndv": 1337,"upper": "ironic excuses. fluffily b","lower": "ing, express platelets","count": 1426,"preSum": 44207 },{ "ndv": 1384,"upper": "k pinto beans. sile","lower": "ironic forges print flu","count": 1426,"preSum": 45633 },{ "ndv": 1368,"upper": "l requests along the furiously bold courts ","lower": "k platelets a","count": 1426,"preSum": 47059 },{ "ndv": 1383,"upper": "le slowly. carefully regul","lower": "l requests among the","count": 1426,"preSum": 48485 },{ "ndv": 1379,"upper": "lly regular accoun","lower": "le slyly abou","count": 1426,"preSum": 49911 },{ "ndv": 1364,"upper": "ly express excuses ","lower": "lly regular account","count": 1426,"preSum": 51337 },{ "ndv": 1304,"upper": "ly unusual depos","lower": "ly express excuses after the senti","count": 1426,"preSum": 52763 },{ "ndv": 1384,"upper": "n, even theodolites ","lower": "ly unusual deposits affix","count": 1426,"preSum": 54189 },{ "ndv": 1385,"upper": "ng, final deposits ","lower": "n, even theodolites x-ray carefully ","count": 1426,"preSum": 55615 },{ "ndv": 1387,"upper": "nt, pending packages","lower": "ng, final foxes. furiously even requests ca","count": 1426,"preSum": 57041 },{ "ndv": 1406,"upper": "old accounts haggle furiously pending acc","lower": "nt, regular ac","count": 1426,"preSum": 58467 },{ "ndv": 1377,"upper": "ons? quickly pending sentiments dazzle bli","lower": "old accounts impress furiously pint","count": 1426,"preSum": 59893 },{ "ndv": 1379,"upper": "ously across the ironic, ","lower": "ons? special, special accounts after","count": 1426,"preSum": 61319 },{ "ndv": 1393,"upper": "packages. slyly ","lower": "ously across the quic","count": 1426,"preSum": 62745 },{ "ndv": 1371,"upper": "press quickly final requests. slyly furious","lower": "packages. slyly even","count": 1426,"preSum": 64171 },{ "ndv": 1372,"upper": "r theodolites haggle furiously after t","lower": "press requ","count": 1426,"preSum": 65597 },{ "ndv": 1331,"upper": "regularly carefully even idea","lower": "r theodolites sleep above the b","count": 1426,"preSum": 67023 },{ "ndv": 1345,"upper": "ronic packages wake furiously furiously ir","lower": "regularly expres","count": 1426,"preSum": 68449 },{ "ndv": 1359,"upper": "s cajole. slyly ","lower": "ronic packages wake. carefully pendi","count": 1426,"preSum": 69875 },{ "ndv": 1390,"upper": "s. blithely bold pa","lower": "s cajole. slyly close courts nod f","count": 1426,"preSum": 71301 },{ "ndv": 1363,"upper": "side of the de","lower": "s. blithely bold packa","count": 1426,"preSum": 72727 },{ "ndv": 1381,"upper": "slyly express packages wake c","lower": "side of the dependencies. quickly fi","count": 1426,"preSum": 74153 },{ "ndv": 1394,"upper": "sts. carefull","lower": "slyly express pi","count": 1426,"preSum": 75579 },{ "ndv": 1400,"upper": "tes wake carefully. sl","lower": "sts. carefully","count": 1426,"preSum": 77005 },{ "ndv": 1334,"upper": "theodolites boos","lower": "tes wake daringly special accounts. thinly","count": 1426,"preSum": 78431 },{ "ndv": 1389,"upper": "ts engage quickly. fur","lower": "theodolites boost along t","count": 1426,"preSum": 79857 },{ "ndv": 1395,"upper": "uests haggle furiously enticing, pendin","lower": "ts engage special requests.","count": 1426,"preSum": 81283 },{ "ndv": 1359,"upper": "ully even accounts","lower": "uests haggle furiously furious instructions","count": 1426,"preSum": 82709 },{ "ndv": 1348,"upper": "uriously unusual pack","lower": "ully even accounts wake above","count": 1426,"preSum": 84135 },{ "ndv": 1381,"upper": "ven dugouts use slyly slowly unusual pac","lower": "uriously unusual realms wake along the b","count": 1426,"preSum": 85561 },{ "ndv": 1378,"upper": "y bold deposits wak","lower": "ven epitaphs. ruthlessl","count": 1426,"preSum": 86987 },{ "ndv": 1335,"upper": "y regular pain","lower": "y bold deposits wake blith","count": 1426,"preSum": 88413 },{ "ndv": 1340,"upper": "zzle: pending i","lower": "y regular patterns nag closel","count": 1382,"preSum": 89839 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  lineitem.l_comment.null_count:
+    0
+  lineitem.l_comment.sample_rate:
+    1.3317477E-5
+  lineitem.l_commitdate.TOPN:
+    { "countArr": [ 56,58,56,55,56,55,56,69,58,57 ],"valueArr": [ 1823482860061851648,1824723109177982976,1824775885736116224,1825283860108148736,1825675286247636992,1826693434014957568,1827482883363700736,1828188769828732928,1828254740526399488,1828270133689188352 ],"type": "Date","sampleRate": 1.0 }
+  lineitem.l_commitdate.cardinality:
+    3321
+  lineitem.l_commitdate.histogram:
+    { "buckets": [ { "ndv": 66,"upper": "1822563668341030912","lower": "1822407537689886720","count": 1431,"preSum": 0 },{ "ndv": 39,"upper": "1822653828294508544","lower": "1822565867364286464","count": 1424,"preSum": 1431 },{ "ndv": 39,"upper": "1822741789224730624","lower": "1822656027317764096","count": 1450,"preSum": 2855 },{ "ndv": 38,"upper": "1822829750154952704","lower": "1822743988247986176","count": 1435,"preSum": 4305 },{ "ndv": 38,"upper": "1822917711085174784","lower": "1822834148201463808","count": 1437,"preSum": 5740 },{ "ndv": 39,"upper": "1823007871038652416","lower": "1822919910108430336","count": 1443,"preSum": 7177 },{ "ndv": 37,"upper": "1823091433922363392","lower": "1823010070061907968","count": 1428,"preSum": 8620 },{ "ndv": 38,"upper": "1823179394852585472","lower": "1823093632945618944","count": 1424,"preSum": 10048 },{ "ndv": 39,"upper": "1823339923550240768","lower": "1823181593875841024","count": 1454,"preSum": 11472 },{ "ndv": 38,"upper": "1823432282526973952","lower": "1823342122573496320","count": 1431,"preSum": 12926 },{ "ndv": 35,"upper": "1823513646387429376","lower": "1823434481550229504","count": 1422,"preSum": 14357 },{ "ndv": 37,"upper": "1823599408294395904","lower": "1823515845410684928","count": 1419,"preSum": 15779 },{ "ndv": 41,"upper": "1823696165317640192","lower": "1823601607317651456","count": 1433,"preSum": 17198 },{ "ndv": 40,"upper": "1823786325271117824","lower": "1823698364340895744","count": 1439,"preSum": 18631 },{ "ndv": 37,"upper": "1823869888154828800","lower": "1823788524294373376","count": 1434,"preSum": 20070 },{ "ndv": 38,"upper": "1823960048108306432","lower": "1823872087178084352","count": 1422,"preSum": 21504 },{ "ndv": 40,"upper": "1824052407085039616","lower": "1823962247131561984","count": 1446,"preSum": 22926 },{ "ndv": 38,"upper": "1824208537736183808","lower": "1824054606108295168","count": 1454,"preSum": 24372 },{ "ndv": 36,"upper": "1824289901596639232","lower": "1824210736759439360","count": 1441,"preSum": 25826 },{ "ndv": 38,"upper": "1824384459596627968","lower": "1824292100619894784","count": 1438,"preSum": 27267 },{ "ndv": 43,"upper": "1824483415643127808","lower": "1824386658619883520","count": 1459,"preSum": 28705 },{ "ndv": 38,"upper": "1824569177550094336","lower": "1824485614666383360","count": 1420,"preSum": 30164 },{ "ndv": 39,"upper": "1824659337503571968","lower": "1824571376573349888","count": 1421,"preSum": 31584 },{ "ndv": 37,"upper": "1824747298433794048","lower": "1824663735550083072","count": 1439,"preSum": 33005 },{ "ndv": 39,"upper": "1824839657410527232","lower": "1824749497457049600","count": 1421,"preSum": 34444 },{ "ndv": 37,"upper": "1824923220294238208","lower": "1824841856433782784","count": 1450,"preSum": 35865 },{ "ndv": 37,"upper": "1825008982201204736","lower": "1824925419317493760","count": 1446,"preSum": 37315 },{ "ndv": 39,"upper": "1825169510898860032","lower": "1825011181224460288","count": 1458,"preSum": 38761 },{ "ndv": 37,"upper": "1825259670852337664","lower": "1825171709922115584","count": 1444,"preSum": 40219 },{ "ndv": 37,"upper": "1825345432759304192","lower": "1825261869875593216","count": 1436,"preSum": 41663 },{ "ndv": 37,"upper": "1825431194666270720","lower": "1825347631782559744","count": 1445,"preSum": 43099 },{ "ndv": 38,"upper": "1825521354619748352","lower": "1825433393689526272","count": 1426,"preSum": 44544 },{ "ndv": 36,"upper": "1825602718480203776","lower": "1825523553643003904","count": 1421,"preSum": 45970 },{ "ndv": 39,"upper": "1825692878433681408","lower": "1825604917503459328","count": 1433,"preSum": 47391 },{ "ndv": 36,"upper": "1825776441317392384","lower": "1825695077456936960","count": 1436,"preSum": 48824 },{ "ndv": 34,"upper": "1825853407131336704","lower": "1825778640340647936","count": 1428,"preSum": 50260 },{ "ndv": 37,"upper": "1826011736805736448","lower": "1825860004201103360","count": 1447,"preSum": 51688 },{ "ndv": 38,"upper": "1826097498712702976","lower": "1826013935828992000","count": 1421,"preSum": 53135 },{ "ndv": 38,"upper": "1826187658666180608","lower": "1826099697735958528","count": 1438,"preSum": 54556 },{ "ndv": 39,"upper": "1826275619596402688","lower": "1826189857689436160","count": 1430,"preSum": 55994 },{ "ndv": 40,"upper": "1826370177596391424","lower": "1826282216666169344","count": 1448,"preSum": 57424 },{ "ndv": 40,"upper": "1826462536573124608","lower": "1826372376619646976","count": 1434,"preSum": 58872 },{ "ndv": 36,"upper": "1826543900433580032","lower": "1826464735596380160","count": 1460,"preSum": 60306 },{ "ndv": 38,"upper": "1826634060387057664","lower": "1826546099456835584","count": 1430,"preSum": 61766 },{ "ndv": 35,"upper": "1826715424247513088","lower": "1826636259410313216","count": 1426,"preSum": 63196 },{ "ndv": 38,"upper": "1826803385177735168","lower": "1826717623270768640","count": 1450,"preSum": 64622 },{ "ndv": 37,"upper": "1826957316805623808","lower": "1826805584200990720","count": 1441,"preSum": 66072 },{ "ndv": 36,"upper": "1827038680666079232","lower": "1826959515828879360","count": 1438,"preSum": 67513 },{ "ndv": 37,"upper": "1827131039642812416","lower": "1827040879689334784","count": 1450,"preSum": 68951 },{ "ndv": 37,"upper": "1827216801549778944","lower": "1827133238666067968","count": 1449,"preSum": 70401 },{ "ndv": 39,"upper": "1827304762480001024","lower": "1827219000573034496","count": 1443,"preSum": 71850 },{ "ndv": 40,"upper": "1827397121456734208","lower": "1827306961503256576","count": 1443,"preSum": 73293 },{ "ndv": 40,"upper": "1827491679456722944","lower": "1827399320479989760","count": 1456,"preSum": 74736 },{ "ndv": 38,"upper": "1827579640386945024","lower": "1827493878479978496","count": 1424,"preSum": 76192 },{ "ndv": 41,"upper": "1827671999363678208","lower": "1827581839410200576","count": 1427,"preSum": 77616 },{ "ndv": 40,"upper": "1827836926107844608","lower": "1827674198386933760","count": 1439,"preSum": 79043 },{ "ndv": 39,"upper": "1827924887038066688","lower": "1827839125131100160","count": 1448,"preSum": 80482 },{ "ndv": 38,"upper": "1828017246014799872","lower": "1827927086061322240","count": 1458,"preSum": 81930 },{ "ndv": 37,"upper": "1828100808898510848","lower": "1828019445038055424","count": 1448,"preSum": 83388 },{ "ndv": 38,"upper": "1828193167875244032","lower": "1828103007921766400","count": 1459,"preSum": 84836 },{ "ndv": 37,"upper": "1828283327828721664","lower": "1828195366898499584","count": 1427,"preSum": 86295 },{ "ndv": 37,"upper": "1828366890712432640","lower": "1828285526851977216","count": 1434,"preSum": 87722 },{ "ndv": 47,"upper": "1828476841875210240","lower": "1828369089735688192","count": 1424,"preSum": 89156 },{ "ndv": 23,"upper": "1828529618433343488","lower": "1828479040898465792","count": 215,"preSum": 90580 } ],"maxBucketSize": 64,"type": "Date","sampleRate": 1.0 }
+  lineitem.l_commitdate.null_count:
+    0
+  lineitem.l_commitdate.sample_rate:
+    1.3317477E-5
+  lineitem.l_discount.TOPN:
+    { "countArr": [ 8315,8420,8434,8123,8246,8122,8333,8367,8268,8414,8329 ],"valueArr": [ 0.00,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.10 ],"type": "Double","sampleRate": 1.0 }
+  lineitem.l_discount.cardinality:
+    11
+  lineitem.l_discount.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "Double","sampleRate": 1.0 }
+  lineitem.l_discount.null_count:
+    0
+  lineitem.l_discount.sample_rate:
+    1.3317477E-5
+  lineitem.l_extendedprice.TOPN:
+    { "countArr": [ ],"valueArr": [ ],"type": "Double","sampleRate": 1.0 }
+  lineitem.l_extendedprice.cardinality:
+    105321562
+  lineitem.l_extendedprice.histogram:
+    { "buckets": [ { "ndv": 1416,"upper": 1784.37,"lower": 914.87,"count": 1428,"preSum": 0 },{ "ndv": 1418,"upper": 3106.22,"lower": 1785.40,"count": 1428,"preSum": 1428 },{ "ndv": 1414,"upper": 4113.24,"lower": 3106.66,"count": 1428,"preSum": 2856 },{ "ndv": 1410,"upper": 5309.35,"lower": 4113.51,"count": 1428,"preSum": 4284 },{ "ndv": 1407,"upper": 6379.80,"lower": 5310.45,"count": 1428,"preSum": 5712 },{ "ndv": 1403,"upper": 7541.25,"lower": 6379.90,"count": 1428,"preSum": 7140 },{ "ndv": 1409,"upper": 8619.45,"lower": 7541.46,"count": 1428,"preSum": 8568 },{ "ndv": 1405,"upper": 9692.83,"lower": 8619.52,"count": 1428,"preSum": 9996 },{ "ndv": 1408,"upper": 10835.16,"lower": 9694.38,"count": 1428,"preSum": 11424 },{ "ndv": 1406,"upper": 11953.62,"lower": 10835.55,"count": 1428,"preSum": 12852 },{ "ndv": 1407,"upper": 13067.19,"lower": 11954.16,"count": 1428,"preSum": 14280 },{ "ndv": 1407,"upper": 14181.20,"lower": 13067.60,"count": 1428,"preSum": 15708 },{ "ndv": 1400,"upper": 15325.60,"lower": 14181.42,"count": 1428,"preSum": 17136 },{ "ndv": 1408,"upper": 16464.96,"lower": 15327.30,"count": 1428,"preSum": 18564 },{ "ndv": 1402,"upper": 17594.64,"lower": 16465.26,"count": 1428,"preSum": 19992 },{ "ndv": 1398,"upper": 18640.44,"lower": 17595.70,"count": 1428,"preSum": 21420 },{ "ndv": 1409,"upper": 19788.21,"lower": 18640.71,"count": 1428,"preSum": 22848 },{ "ndv": 1394,"upper": 20920.14,"lower": 19788.31,"count": 1428,"preSum": 24276 },{ "ndv": 1409,"upper": 22016.15,"lower": 20920.80,"count": 1428,"preSum": 25704 },{ "ndv": 1398,"upper": 23182.66,"lower": 22018.80,"count": 1428,"preSum": 27132 },{ "ndv": 1404,"upper": 24316.56,"lower": 23183.86,"count": 1428,"preSum": 28560 },{ "ndv": 1401,"upper": 25445.76,"lower": 24317.60,"count": 1428,"preSum": 29988 },{ "ndv": 1400,"upper": 26585.60,"lower": 25446.54,"count": 1428,"preSum": 31416 },{ "ndv": 1396,"upper": 27735.50,"lower": 26586.00,"count": 1428,"preSum": 32844 },{ "ndv": 1396,"upper": 28825.67,"lower": 27736.02,"count": 1428,"preSum": 34272 },{ "ndv": 1404,"upper": 29949.91,"lower": 28825.86,"count": 1428,"preSum": 35700 },{ "ndv": 1393,"upper": 31046.00,"lower": 29950.40,"count": 1428,"preSum": 37128 },{ "ndv": 1400,"upper": 32175.74,"lower": 31047.00,"count": 1428,"preSum": 38556 },{ "ndv": 1407,"upper": 33286.34,"lower": 32178.08,"count": 1428,"preSum": 39984 },{ "ndv": 1398,"upper": 34397.44,"lower": 33287.28,"count": 1428,"preSum": 41412 },{ "ndv": 1404,"upper": 35500.93,"lower": 34397.52,"count": 1428,"preSum": 42840 },{ "ndv": 1394,"upper": 36650.38,"lower": 35501.00,"count": 1428,"preSum": 44268 },{ "ndv": 1396,"upper": 37744.56,"lower": 36650.78,"count": 1428,"preSum": 45696 },{ "ndv": 1398,"upper": 38836.56,"lower": 37746.90,"count": 1428,"preSum": 47124 },{ "ndv": 1396,"upper": 40012.90,"lower": 38837.34,"count": 1428,"preSum": 48552 },{ "ndv": 1396,"upper": 41158.32,"lower": 40013.75,"count": 1428,"preSum": 49980 },{ "ndv": 1399,"upper": 42267.15,"lower": 41158.88,"count": 1428,"preSum": 51408 },{ "ndv": 1398,"upper": 43384.38,"lower": 42267.40,"count": 1428,"preSum": 52836 },{ "ndv": 1409,"upper": 44533.28,"lower": 43385.09,"count": 1428,"preSum": 54264 },{ "ndv": 1398,"upper": 45645.39,"lower": 44533.53,"count": 1428,"preSum": 55692 },{ "ndv": 1393,"upper": 46794.00,"lower": 45646.22,"count": 1428,"preSum": 57120 },{ "ndv": 1395,"upper": 47895.20,"lower": 46795.38,"count": 1428,"preSum": 58548 },{ "ndv": 1403,"upper": 49042.19,"lower": 47895.79,"count": 1428,"preSum": 59976 },{ "ndv": 1402,"upper": 50256.44,"lower": 49043.98,"count": 1428,"preSum": 61404 },{ "ndv": 1405,"upper": 51438.08,"lower": 50258.04,"count": 1428,"preSum": 62832 },{ "ndv": 1402,"upper": 52645.56,"lower": 51438.09,"count": 1428,"preSum": 64260 },{ "ndv": 1395,"upper": 53928.96,"lower": 52646.19,"count": 1428,"preSum": 65688 },{ "ndv": 1406,"upper": 55241.92,"lower": 53929.44,"count": 1428,"preSum": 67116 },{ "ndv": 1404,"upper": 56524.05,"lower": 55242.88,"count": 1428,"preSum": 68544 },{ "ndv": 1398,"upper": 57859.84,"lower": 56525.70,"count": 1428,"preSum": 69972 },{ "ndv": 1404,"upper": 59333.40,"lower": 57861.18,"count": 1428,"preSum": 71400 },{ "ndv": 1405,"upper": 60875.10,"lower": 59335.50,"count": 1428,"preSum": 72828 },{ "ndv": 1400,"upper": 62371.50,"lower": 60875.60,"count": 1428,"preSum": 74256 },{ "ndv": 1408,"upper": 64010.52,"lower": 62373.24,"count": 1428,"preSum": 75684 },{ "ndv": 1408,"upper": 65723.70,"lower": 64010.88,"count": 1428,"preSum": 77112 },{ "ndv": 1399,"upper": 67637.15,"lower": 65725.00,"count": 1428,"preSum": 78540 },{ "ndv": 1403,"upper": 69656.82,"lower": 67637.16,"count": 1428,"preSum": 79968 },{ "ndv": 1404,"upper": 71895.24,"lower": 69656.88,"count": 1428,"preSum": 81396 },{ "ndv": 1404,"upper": 74337.60,"lower": 71896.50,"count": 1428,"preSum": 82824 },{ "ndv": 1416,"upper": 77103.84,"lower": 74342.70,"count": 1428,"preSum": 84252 },{ "ndv": 1408,"upper": 80348.66,"lower": 77106.04,"count": 1428,"preSum": 85680 },{ "ndv": 1417,"upper": 84179.38,"lower": 80349.72,"count": 1428,"preSum": 87108 },{ "ndv": 1416,"upper": 89299.35,"lower": 84180.00,"count": 1428,"preSum": 88536 },{ "ndv": 1390,"upper": 104126.00,"lower": 89301.18,"count": 1407,"preSum": 89964 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 1.0 }
+  lineitem.l_extendedprice.null_count:
+    0
+  lineitem.l_extendedprice.sample_rate:
+    1.3317477E-5
+  lineitem.l_linenumber.TOPN:
+    { "countArr": [ 22833,19574,16253,13068,9821,6599,3223 ],"valueArr": [ 1,2,3,4,5,6,7 ],"type": "Int","sampleRate": 1.0 }
+  lineitem.l_linenumber.cardinality:
+    7
+  lineitem.l_linenumber.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  lineitem.l_linenumber.null_count:
+    0
+  lineitem.l_linenumber.sample_rate:
+    1.3317477E-5
+  lineitem.l_linestatus.TOPN:
+    { "countArr": [ 45424,45947 ],"valueArr": [ "F","O" ],"type": "String","sampleRate": 1.0 }
+  lineitem.l_linestatus.cardinality:
+    2
+  lineitem.l_linestatus.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  lineitem.l_linestatus.null_count:
+    0
+  lineitem.l_linestatus.sample_rate:
+    1.3317477E-5
+  lineitem.l_orderkey.TOPN:
+    { "countArr": [ ],"valueArr": [ ],"type": "Int","sampleRate": 1.0 }
+  lineitem.l_orderkey.cardinality:
+    1309416
+  lineitem.l_orderkey.histogram:
+    { "buckets": [ { "ndv": 366,"upper": 1447,"lower": 1,"count": 1430,"preSum": 0 },{ "ndv": 344,"upper": 2855,"lower": 1472,"count": 1428,"preSum": 1430 },{ "ndv": 363,"upper": 4388,"lower": 2880,"count": 1428,"preSum": 2858 },{ "ndv": 370,"upper": 6022,"lower": 4389,"count": 1434,"preSum": 4286 },{ "ndv": 383,"upper": 8002,"lower": 6023,"count": 1430,"preSum": 5720 },{ "ndv": 376,"upper": 11014,"lower": 8004,"count": 1430,"preSum": 7150 },{ "ndv": 381,"upper": 27530208,"lower": 11045,"count": 1428,"preSum": 8580 },{ "ndv": 381,"upper": 182333411,"lower": 27530209,"count": 1434,"preSum": 10008 },{ "ndv": 373,"upper": 272629476,"lower": 182333732,"count": 1432,"preSum": 11442 },{ "ndv": 385,"upper": 362235236,"lower": 272629478,"count": 1432,"preSum": 12874 },{ "ndv": 388,"upper": 499843587,"lower": 362235328,"count": 1432,"preSum": 14306 },{ "ndv": 377,"upper": 558705795,"lower": 499844001,"count": 1433,"preSum": 15738 },{ "ndv": 386,"upper": 687995298,"lower": 558706208,"count": 1433,"preSum": 17171 },{ "ndv": 361,"upper": 791372295,"lower": 687995554,"count": 1431,"preSum": 18604 },{ "ndv": 377,"upper": 928739620,"lower": 791372577,"count": 1433,"preSum": 20035 },{ "ndv": 391,"upper": 998652934,"lower": 928740610,"count": 1431,"preSum": 21468 },{ "ndv": 401,"upper": 1128689125,"lower": 998653574,"count": 1431,"preSum": 22899 },{ "ndv": 378,"upper": 1216507751,"lower": 1128689154,"count": 1432,"preSum": 24330 },{ "ndv": 395,"upper": 1279763458,"lower": 1216508739,"count": 1429,"preSum": 25762 },{ "ndv": 370,"upper": 1427142530,"lower": 1279765253,"count": 1434,"preSum": 27191 },{ "ndv": 378,"upper": 1536289991,"lower": 1427142657,"count": 1430,"preSum": 28625 },{ "ndv": 362,"upper": 1643663073,"lower": 1536290023,"count": 1429,"preSum": 30055 },{ "ndv": 377,"upper": 1733329248,"lower": 1643663074,"count": 1430,"preSum": 31484 },{ "ndv": 371,"upper": 1814659234,"lower": 1733330245,"count": 1428,"preSum": 32914 },{ "ndv": 351,"upper": 1923957091,"lower": 1814659461,"count": 1428,"preSum": 34342 },{ "ndv": 360,"upper": 2001741701,"lower": 1923957191,"count": 1433,"preSum": 35770 },{ "ndv": 375,"upper": 2155568486,"lower": 2001742244,"count": 1430,"preSum": 37203 },{ "ndv": 382,"upper": 2230802375,"lower": 2155569669,"count": 1433,"preSum": 38633 },{ "ndv": 361,"upper": 2331820709,"lower": 2230802400,"count": 1431,"preSum": 40066 },{ "ndv": 375,"upper": 2465636992,"lower": 2331820834,"count": 1429,"preSum": 41497 },{ "ndv": 390,"upper": 2563249476,"lower": 2465637701,"count": 1428,"preSum": 42926 },{ "ndv": 376,"upper": 2644128966,"lower": 2563249508,"count": 1428,"preSum": 44354 },{ "ndv": 392,"upper": 2745895972,"lower": 2644128996,"count": 1431,"preSum": 45782 },{ "ndv": 375,"upper": 2858447206,"lower": 2745896002,"count": 1430,"preSum": 47213 },{ "ndv": 364,"upper": 2997474599,"lower": 2858450052,"count": 1431,"preSum": 48643 },{ "ndv": 361,"upper": 3111944035,"lower": 2997475232,"count": 1429,"preSum": 50074 },{ "ndv": 365,"upper": 3197985505,"lower": 3111944135,"count": 1428,"preSum": 51503 },{ "ndv": 392,"upper": 3289539683,"lower": 3197985506,"count": 1429,"preSum": 52931 },{ "ndv": 389,"upper": 3417917029,"lower": 3289539783,"count": 1429,"preSum": 54360 },{ "ndv": 389,"upper": 3508897959,"lower": 3417918790,"count": 1428,"preSum": 55789 },{ "ndv": 395,"upper": 3597389413,"lower": 3508898052,"count": 1429,"preSum": 57217 },{ "ndv": 381,"upper": 3744521699,"lower": 3597389637,"count": 1428,"preSum": 58646 },{ "ndv": 392,"upper": 3854317605,"lower": 3744523683,"count": 1428,"preSum": 60074 },{ "ndv": 376,"upper": 3991298823,"lower": 3854317955,"count": 1433,"preSum": 61502 },{ "ndv": 378,"upper": 4119767911,"lower": 3991301280,"count": 1429,"preSum": 62935 },{ "ndv": 382,"upper": 4211017543,"lower": 4119769664,"count": 1434,"preSum": 64364 },{ "ndv": 370,"upper": 4329050176,"lower": 4211017575,"count": 1432,"preSum": 65798 },{ "ndv": 363,"upper": 4474924228,"lower": 4329050308,"count": 1432,"preSum": 67230 },{ "ndv": 379,"upper": 4581756930,"lower": 4474924230,"count": 1433,"preSum": 68662 },{ "ndv": 375,"upper": 4684109697,"lower": 4581759109,"count": 1429,"preSum": 70095 },{ "ndv": 371,"upper": 4771212675,"lower": 4684111685,"count": 1431,"preSum": 71524 },{ "ndv": 361,"upper": 4830716935,"lower": 4771212931,"count": 1430,"preSum": 72955 },{ "ndv": 382,"upper": 4926602919,"lower": 4830717447,"count": 1433,"preSum": 74385 },{ "ndv": 363,"upper": 5008638243,"lower": 4926605122,"count": 1428,"preSum": 75818 },{ "ndv": 389,"upper": 5099167847,"lower": 5008638245,"count": 1431,"preSum": 77246 },{ "ndv": 370,"upper": 5251885506,"lower": 5099171110,"count": 1433,"preSum": 78677 },{ "ndv": 390,"upper": 5347222915,"lower": 5251885507,"count": 1429,"preSum": 80110 },{ "ndv": 389,"upper": 5480629664,"lower": 5347223331,"count": 1428,"preSum": 81539 },{ "ndv": 371,"upper": 5559056007,"lower": 5480634052,"count": 1429,"preSum": 82967 },{ "ndv": 390,"upper": 5656045604,"lower": 5559057927,"count": 1432,"preSum": 84396 },{ "ndv": 385,"upper": 5742084256,"lower": 5656046083,"count": 1431,"preSum": 85828 },{ "ndv": 362,"upper": 5811188487,"lower": 5742084388,"count": 1428,"preSum": 87259 },{ "ndv": 388,"upper": 5907018624,"lower": 5811189408,"count": 1428,"preSum": 88687 },{ "ndv": 327,"upper": 5996402690,"lower": 5907018628,"count": 1256,"preSum": 90115 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  lineitem.l_orderkey.null_count:
+    0
+  lineitem.l_orderkey.sample_rate:
+    1.3317477E-5
+  lineitem.l_partkey.TOPN:
+    null
+  lineitem.l_partkey.cardinality:
+    167753526
+  lineitem.l_partkey.histogram:
+    { "buckets": [ { "ndv": 1427,"upper": 3083750,"lower": 1102,"count": 1428,"preSum": 0 },{ "ndv": 1427,"upper": 6122161,"lower": 3086127,"count": 1428,"preSum": 1428 },{ "ndv": 1428,"upper": 9180224,"lower": 6122711,"count": 1428,"preSum": 2856 },{ "ndv": 1428,"upper": 12346001,"lower": 9184029,"count": 1428,"preSum": 4284 },{ "ndv": 1427,"upper": 15468379,"lower": 12349131,"count": 1428,"preSum": 5712 },{ "ndv": 1427,"upper": 18633949,"lower": 15469465,"count": 1428,"preSum": 7140 },{ "ndv": 1428,"upper": 21767319,"lower": 18636945,"count": 1428,"preSum": 8568 },{ "ndv": 1428,"upper": 24870045,"lower": 21769090,"count": 1428,"preSum": 9996 },{ "ndv": 1428,"upper": 28013210,"lower": 24870078,"count": 1428,"preSum": 11424 },{ "ndv": 1426,"upper": 31385169,"lower": 28013513,"count": 1428,"preSum": 12852 },{ "ndv": 1428,"upper": 34391269,"lower": 31385888,"count": 1428,"preSum": 14280 },{ "ndv": 1427,"upper": 37397562,"lower": 34391888,"count": 1428,"preSum": 15708 },{ "ndv": 1428,"upper": 40502527,"lower": 37397819,"count": 1428,"preSum": 17136 },{ "ndv": 1427,"upper": 43683626,"lower": 40505937,"count": 1428,"preSum": 18564 },{ "ndv": 1428,"upper": 46929014,"lower": 43686588,"count": 1428,"preSum": 19992 },{ "ndv": 1428,"upper": 49897832,"lower": 46934563,"count": 1428,"preSum": 21420 },{ "ndv": 1428,"upper": 53106133,"lower": 49898097,"count": 1428,"preSum": 22848 },{ "ndv": 1427,"upper": 56134102,"lower": 53107721,"count": 1428,"preSum": 24276 },{ "ndv": 1428,"upper": 59213296,"lower": 56135162,"count": 1428,"preSum": 25704 },{ "ndv": 1427,"upper": 62310971,"lower": 59219694,"count": 1428,"preSum": 27132 },{ "ndv": 1428,"upper": 65399213,"lower": 62311427,"count": 1428,"preSum": 28560 },{ "ndv": 1428,"upper": 68505120,"lower": 65399414,"count": 1428,"preSum": 29988 },{ "ndv": 1426,"upper": 71633327,"lower": 68511611,"count": 1428,"preSum": 31416 },{ "ndv": 1428,"upper": 74737658,"lower": 71634140,"count": 1428,"preSum": 32844 },{ "ndv": 1428,"upper": 77794231,"lower": 74739772,"count": 1428,"preSum": 34272 },{ "ndv": 1426,"upper": 81136921,"lower": 77797065,"count": 1428,"preSum": 35700 },{ "ndv": 1428,"upper": 84401235,"lower": 81137210,"count": 1428,"preSum": 37128 },{ "ndv": 1428,"upper": 87690870,"lower": 84406031,"count": 1428,"preSum": 38556 },{ "ndv": 1428,"upper": 90835550,"lower": 87694642,"count": 1428,"preSum": 39984 },{ "ndv": 1427,"upper": 94055069,"lower": 90837334,"count": 1428,"preSum": 41412 },{ "ndv": 1428,"upper": 97154879,"lower": 94055466,"count": 1428,"preSum": 42840 },{ "ndv": 1427,"upper": 100338352,"lower": 97156029,"count": 1428,"preSum": 44268 },{ "ndv": 1428,"upper": 103435914,"lower": 100342873,"count": 1428,"preSum": 45696 },{ "ndv": 1428,"upper": 106440129,"lower": 103439121,"count": 1428,"preSum": 47124 },{ "ndv": 1428,"upper": 109559425,"lower": 106440299,"count": 1428,"preSum": 48552 },{ "ndv": 1428,"upper": 112761399,"lower": 109560111,"count": 1428,"preSum": 49980 },{ "ndv": 1428,"upper": 115768582,"lower": 112764393,"count": 1428,"preSum": 51408 },{ "ndv": 1427,"upper": 118847212,"lower": 115768722,"count": 1428,"preSum": 52836 },{ "ndv": 1428,"upper": 121907199,"lower": 118849918,"count": 1428,"preSum": 54264 },{ "ndv": 1428,"upper": 125010526,"lower": 121915364,"count": 1428,"preSum": 55692 },{ "ndv": 1428,"upper": 128187337,"lower": 125015543,"count": 1428,"preSum": 57120 },{ "ndv": 1428,"upper": 131280909,"lower": 128190746,"count": 1428,"preSum": 58548 },{ "ndv": 1428,"upper": 134446284,"lower": 131281399,"count": 1428,"preSum": 59976 },{ "ndv": 1428,"upper": 137578899,"lower": 134446684,"count": 1428,"preSum": 61404 },{ "ndv": 1427,"upper": 140596958,"lower": 137583378,"count": 1428,"preSum": 62832 },{ "ndv": 1428,"upper": 143698634,"lower": 140598936,"count": 1428,"preSum": 64260 },{ "ndv": 1428,"upper": 146898476,"lower": 143700267,"count": 1428,"preSum": 65688 },{ "ndv": 1428,"upper": 150066696,"lower": 146901755,"count": 1428,"preSum": 67116 },{ "ndv": 1427,"upper": 153384825,"lower": 150067183,"count": 1428,"preSum": 68544 },{ "ndv": 1428,"upper": 156493605,"lower": 153385825,"count": 1428,"preSum": 69972 },{ "ndv": 1428,"upper": 159670350,"lower": 156495754,"count": 1428,"preSum": 71400 },{ "ndv": 1428,"upper": 162841575,"lower": 159671374,"count": 1428,"preSum": 72828 },{ "ndv": 1428,"upper": 166032432,"lower": 162844141,"count": 1428,"preSum": 74256 },{ "ndv": 1427,"upper": 169063684,"lower": 166036045,"count": 1428,"preSum": 75684 },{ "ndv": 1427,"upper": 172272585,"lower": 169065005,"count": 1428,"preSum": 77112 },{ "ndv": 1428,"upper": 175270439,"lower": 172273937,"count": 1428,"preSum": 78540 },{ "ndv": 1428,"upper": 178383069,"lower": 175272355,"count": 1428,"preSum": 79968 },{ "ndv": 1428,"upper": 181364269,"lower": 178385034,"count": 1428,"preSum": 81396 },{ "ndv": 1427,"upper": 184422001,"lower": 181364635,"count": 1428,"preSum": 82824 },{ "ndv": 1428,"upper": 187486974,"lower": 184422602,"count": 1428,"preSum": 84252 },{ "ndv": 1427,"upper": 190564341,"lower": 187487201,"count": 1428,"preSum": 85680 },{ "ndv": 1428,"upper": 193748577,"lower": 190564517,"count": 1428,"preSum": 87108 },{ "ndv": 1428,"upper": 196981867,"lower": 193748844,"count": 1428,"preSum": 88536 },{ "ndv": 1407,"upper": 199999568,"lower": 196984010,"count": 1407,"preSum": 89964 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  lineitem.l_partkey.null_count:
+    0
+  lineitem.l_partkey.sample_rate:
+    1.3317477E-5
+  lineitem.l_quantity.TOPN:
+    { "countArr": [ 1852,1940,1866,1889,1864,1902,1881,1844,1865,1849,1862,1884,1891 ],"valueArr": [ 3.00,5.00,6.00,17.00,22.00,23.00,25.00,31.00,36.00,39.00,47.00,48.00,49.00 ],"type": "Double","sampleRate": 1.0 }
+  lineitem.l_quantity.cardinality:
+    50
+  lineitem.l_quantity.histogram:
+    { "buckets": [ { "ndv": 1,"upper": 1.00,"lower": 1.00,"count": 1795,"preSum": 0 },{ "ndv": 1,"upper": 2.00,"lower": 2.00,"count": 1764,"preSum": 1795 },{ "ndv": 1,"upper": 4.00,"lower": 4.00,"count": 1780,"preSum": 3559 },{ "ndv": 1,"upper": 7.00,"lower": 7.00,"count": 1838,"preSum": 5339 },{ "ndv": 1,"upper": 8.00,"lower": 8.00,"count": 1830,"preSum": 7177 },{ "ndv": 1,"upper": 9.00,"lower": 9.00,"count": 1820,"preSum": 9007 },{ "ndv": 1,"upper": 10.00,"lower": 10.00,"count": 1803,"preSum": 10827 },{ "ndv": 1,"upper": 11.00,"lower": 11.00,"count": 1803,"preSum": 12630 },{ "ndv": 1,"upper": 12.00,"lower": 12.00,"count": 1843,"preSum": 14433 },{ "ndv": 1,"upper": 13.00,"lower": 13.00,"count": 1824,"preSum": 16276 },{ "ndv": 1,"upper": 14.00,"lower": 14.00,"count": 1721,"preSum": 18100 },{ "ndv": 1,"upper": 15.00,"lower": 15.00,"count": 1828,"preSum": 19821 },{ "ndv": 1,"upper": 16.00,"lower": 16.00,"count": 1830,"preSum": 21649 },{ "ndv": 1,"upper": 18.00,"lower": 18.00,"count": 1838,"preSum": 23479 },{ "ndv": 1,"upper": 19.00,"lower": 19.00,"count": 1796,"preSum": 25317 },{ "ndv": 1,"upper": 20.00,"lower": 20.00,"count": 1842,"preSum": 27113 },{ "ndv": 1,"upper": 21.00,"lower": 21.00,"count": 1834,"preSum": 28955 },{ "ndv": 1,"upper": 24.00,"lower": 24.00,"count": 1807,"preSum": 30789 },{ "ndv": 1,"upper": 26.00,"lower": 26.00,"count": 1794,"preSum": 32596 },{ "ndv": 1,"upper": 27.00,"lower": 27.00,"count": 1811,"preSum": 34390 },{ "ndv": 1,"upper": 28.00,"lower": 28.00,"count": 1842,"preSum": 36201 },{ "ndv": 1,"upper": 29.00,"lower": 29.00,"count": 1793,"preSum": 38043 },{ "ndv": 1,"upper": 30.00,"lower": 30.00,"count": 1823,"preSum": 39836 },{ "ndv": 1,"upper": 32.00,"lower": 32.00,"count": 1833,"preSum": 41659 },{ "ndv": 1,"upper": 33.00,"lower": 33.00,"count": 1812,"preSum": 43492 },{ "ndv": 1,"upper": 34.00,"lower": 34.00,"count": 1785,"preSum": 45304 },{ "ndv": 1,"upper": 35.00,"lower": 35.00,"count": 1821,"preSum": 47089 },{ "ndv": 1,"upper": 37.00,"lower": 37.00,"count": 1842,"preSum": 48910 },{ "ndv": 1,"upper": 38.00,"lower": 38.00,"count": 1826,"preSum": 50752 },{ "ndv": 1,"upper": 40.00,"lower": 40.00,"count": 1828,"preSum": 52578 },{ "ndv": 1,"upper": 41.00,"lower": 41.00,"count": 1781,"preSum": 54406 },{ "ndv": 1,"upper": 42.00,"lower": 42.00,"count": 1782,"preSum": 56187 },{ "ndv": 1,"upper": 43.00,"lower": 43.00,"count": 1831,"preSum": 57969 },{ "ndv": 1,"upper": 44.00,"lower": 44.00,"count": 1768,"preSum": 59800 },{ "ndv": 1,"upper": 45.00,"lower": 45.00,"count": 1769,"preSum": 61568 },{ "ndv": 1,"upper": 46.00,"lower": 46.00,"count": 1802,"preSum": 63337 },{ "ndv": 1,"upper": 50.00,"lower": 50.00,"count": 1843,"preSum": 65139 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 1.0 }
+  lineitem.l_quantity.null_count:
+    0
+  lineitem.l_quantity.sample_rate:
+    1.3317477E-5
+  lineitem.l_receiptdate.TOPN:
+    { "countArr": [ 57,57,62,59,57,59,58,57,57 ],"valueArr": [ 1822781371643330560,1824195343596650496,1825193700154671104,1825268466945359872,1825325641550004224,1825483971224403968,1825668689177870336,1826101896759214080,1826403162945224704 ],"type": "Date","sampleRate": 1.0 }
+  lineitem.l_receiptdate.cardinality:
+    5966
+  lineitem.l_receiptdate.histogram:
+    { "buckets": [ { "ndv": 103,"upper": "1822596653689864192","lower": "1822356960155009024","count": 1446,"preSum": 0 },{ "ndv": 41,"upper": "1822693410713108480","lower": "1822598852713119744","count": 1445,"preSum": 1446 },{ "ndv": 38,"upper": "1822783570666586112","lower": "1822695609736364032","count": 1432,"preSum": 2891 },{ "ndv": 41,"upper": "1822875929643319296","lower": "1822785769689841664","count": 1442,"preSum": 4323 },{ "ndv": 38,"upper": "1822961691550285824","lower": "1822878128666574848","count": 1451,"preSum": 5765 },{ "ndv": 39,"upper": "1823054050527019008","lower": "1822963890573541376","count": 1430,"preSum": 7216 },{ "ndv": 37,"upper": "1823139812433985536","lower": "1823056249550274560","count": 1466,"preSum": 8646 },{ "ndv": 37,"upper": "1823293744061874176","lower": "1823142011457241088","count": 1428,"preSum": 10112 },{ "ndv": 38,"upper": "1823379505968840704","lower": "1823295943085129728","count": 1428,"preSum": 11540 },{ "ndv": 39,"upper": "1823476262992084992","lower": "1823381704992096256","count": 1454,"preSum": 12968 },{ "ndv": 37,"upper": "1823562024899051520","lower": "1823478462015340544","count": 1444,"preSum": 14422 },{ "ndv": 39,"upper": "1823649985829273600","lower": "1823564223922307072","count": 1449,"preSum": 15866 },{ "ndv": 39,"upper": "1823740145782751232","lower": "1823652184852529152","count": 1447,"preSum": 17315 },{ "ndv": 38,"upper": "1823828106712973312","lower": "1823742344806006784","count": 1440,"preSum": 18762 },{ "ndv": 39,"upper": "1823918266666450944","lower": "1823830305736228864","count": 1450,"preSum": 20202 },{ "ndv": 39,"upper": "1824006227596673024","lower": "1823920465689706496","count": 1459,"preSum": 21652 },{ "ndv": 38,"upper": "1824094188526895104","lower": "1824008426619928576","count": 1423,"preSum": 23111 },{ "ndv": 38,"upper": "1824254717224550400","lower": "1824096387550150656","count": 1441,"preSum": 24534 },{ "ndv": 38,"upper": "1824347076201283584","lower": "1824256916247805952","count": 1426,"preSum": 25975 },{ "ndv": 39,"upper": "1824435037131505664","lower": "1824349275224539136","count": 1441,"preSum": 27401 },{ "ndv": 39,"upper": "1824527396108238848","lower": "1824437236154761216","count": 1425,"preSum": 28842 },{ "ndv": 38,"upper": "1824615357038460928","lower": "1824529595131494400","count": 1420,"preSum": 30267 },{ "ndv": 40,"upper": "1824705516991938560","lower": "1824617556061716480","count": 1452,"preSum": 31687 },{ "ndv": 38,"upper": "1824791278898905088","lower": "1824707716015194112","count": 1435,"preSum": 33139 },{ "ndv": 38,"upper": "1824881438852382720","lower": "1824793477922160640","count": 1432,"preSum": 34574 },{ "ndv": 37,"upper": "1824967200759349248","lower": "1824883637875638272","count": 1434,"preSum": 36006 },{ "ndv": 37,"upper": "1825121132387237888","lower": "1824969399782604800","count": 1444,"preSum": 37440 },{ "ndv": 38,"upper": "1825209093317459968","lower": "1825123331410493440","count": 1422,"preSum": 38884 },{ "ndv": 39,"upper": "1825308049363959808","lower": "1825211292340715520","count": 1453,"preSum": 40306 },{ "ndv": 35,"upper": "1825391612247670784","lower": "1825310248387215360","count": 1422,"preSum": 41759 },{ "ndv": 38,"upper": "1825477374154637312","lower": "1825393811270926336","count": 1421,"preSum": 43181 },{ "ndv": 39,"upper": "1825569733131370496","lower": "1825479573177892864","count": 1449,"preSum": 44602 },{ "ndv": 36,"upper": "1825653296015081472","lower": "1825571932154626048","count": 1424,"preSum": 46051 },{ "ndv": 38,"upper": "1825743455968559104","lower": "1825655495038337024","count": 1442,"preSum": 47475 },{ "ndv": 36,"upper": "1825824819829014528","lower": "1825745654991814656","count": 1422,"preSum": 48917 },{ "ndv": 35,"upper": "1825906183689469952","lower": "1825827018852270080","count": 1450,"preSum": 50339 },{ "ndv": 37,"upper": "1826060115317358592","lower": "1825908382712725504","count": 1422,"preSum": 51789 },{ "ndv": 38,"upper": "1826154673317347328","lower": "1826062314340614144","count": 1423,"preSum": 53211 },{ "ndv": 38,"upper": "1826240435224313856","lower": "1826156872340602880","count": 1422,"preSum": 54634 },{ "ndv": 41,"upper": "1826334993224302592","lower": "1826242634247569408","count": 1452,"preSum": 56056 },{ "ndv": 40,"upper": "1826431750247546880","lower": "1826337192247558144","count": 1447,"preSum": 57508 },{ "ndv": 38,"upper": "1826517512154513408","lower": "1826433949270802432","count": 1442,"preSum": 58955 },{ "ndv": 37,"upper": "1826601075038224384","lower": "1826519711177768960","count": 1447,"preSum": 60397 },{ "ndv": 37,"upper": "1826686836945190912","lower": "1826603274061479936","count": 1447,"preSum": 61844 },{ "ndv": 37,"upper": "1826774797875412992","lower": "1826689035968446464","count": 1448,"preSum": 63291 },{ "ndv": 37,"upper": "1826928729503301632","lower": "1826776996898668544","count": 1447,"preSum": 64739 },{ "ndv": 38,"upper": "1827014491410268160","lower": "1826930928526557184","count": 1458,"preSum": 66186 },{ "ndv": 36,"upper": "1827102452340490240","lower": "1827016690433523712","count": 1429,"preSum": 67644 },{ "ndv": 37,"upper": "1827186015224201216","lower": "1827104651363745792","count": 1442,"preSum": 69073 },{ "ndv": 36,"upper": "1827271777131167744","lower": "1827188214247456768","count": 1449,"preSum": 70515 },{ "ndv": 38,"upper": "1827359738061389824","lower": "1827273976154423296","count": 1441,"preSum": 71964 },{ "ndv": 40,"upper": "1827449898014867456","lower": "1827361937084645376","count": 1445,"preSum": 73405 },{ "ndv": 39,"upper": "1827537858945089536","lower": "1827452097038123008","count": 1422,"preSum": 74850 },{ "ndv": 40,"upper": "1827632416945078272","lower": "1827540057968345088","count": 1421,"preSum": 76272 },{ "ndv": 41,"upper": "1827726974945067008","lower": "1827634615968333824","count": 1460,"preSum": 77693 },{ "ndv": 39,"upper": "1827885304619466752","lower": "1827729173968322560","count": 1449,"preSum": 79153 },{ "ndv": 39,"upper": "1827982061642711040","lower": "1827887503642722304","count": 1423,"preSum": 80602 },{ "ndv": 38,"upper": "1828067823549677568","lower": "1827984260665966592","count": 1429,"preSum": 82025 },{ "ndv": 36,"upper": "1828151386433388544","lower": "1828070022572933120","count": 1448,"preSum": 83454 },{ "ndv": 38,"upper": "1828237148340355072","lower": "1828153585456644096","count": 1432,"preSum": 84902 },{ "ndv": 36,"upper": "1828322910247321600","lower": "1828239347363610624","count": 1441,"preSum": 86334 },{ "ndv": 38,"upper": "1828408672154288128","lower": "1828325109270577152","count": 1428,"preSum": 87775 },{ "ndv": 66,"upper": "1828560404758921216","lower": "1828410871177543680","count": 1432,"preSum": 89203 },{ "ndv": 38,"upper": "1828657161782165504","lower": "1828562603782176768","count": 213,"preSum": 90635 } ],"maxBucketSize": 64,"type": "Date","sampleRate": 1.0 }
+  lineitem.l_receiptdate.null_count:
+    0
+  lineitem.l_receiptdate.sample_rate:
+    1.3317477E-5
+  lineitem.l_returnflag.TOPN:
+    { "countArr": [ 22448,46560,22363 ],"valueArr": [ "A","N","R" ],"type": "String","sampleRate": 1.0 }
+  lineitem.l_returnflag.cardinality:
+    3
+  lineitem.l_returnflag.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  lineitem.l_returnflag.null_count:
+    0
+  lineitem.l_returnflag.sample_rate:
+    1.3317477E-5
+  lineitem.l_shipdate.TOPN:
+    { "countArr": [ 56,58,56,55,57,55,56,59,59,55,59,58,61,56 ],"valueArr": [ 1822853939410763776,1823062846620041216,1823065045643296768,1824008426619928576,1824773686712860672,1824815468154716160,1824879239829127168,1824969399782604800,1825472976108126208,1825543344852303872,1825580728247648256,1826640657456824320,1826796788107968512,1828296521968254976 ],"type": "Date","sampleRate": 1.0 }
+  lineitem.l_shipdate.cardinality:
+    3665
+  lineitem.l_shipdate.histogram:
+    { "buckets": [ { "ndv": 93,"upper": "1822561469317775360","lower": "1822345965038731264","count": 1425,"preSum": 0 },{ "ndv": 41,"upper": "1822656027317764096","lower": "1822563668341030912","count": 1443,"preSum": 1425 },{ "ndv": 38,"upper": "1822741789224730624","lower": "1822658226341019648","count": 1453,"preSum": 2868 },{ "ndv": 41,"upper": "1822838546247974912","lower": "1822743988247986176","count": 1454,"preSum": 4321 },{ "ndv": 38,"upper": "1822926507178196992","lower": "1822840745271230464","count": 1430,"preSum": 5775 },{ "ndv": 39,"upper": "1823016667131674624","lower": "1822928706201452544","count": 1447,"preSum": 7205 },{ "ndv": 38,"upper": "1823106827085152256","lower": "1823018866154930176","count": 1451,"preSum": 8652 },{ "ndv": 37,"upper": "1823265156759552000","lower": "1823109026108407808","count": 1425,"preSum": 10103 },{ "ndv": 38,"upper": "1823350918666518528","lower": "1823267355782807552","count": 1441,"preSum": 11528 },{ "ndv": 39,"upper": "1823445476666507264","lower": "1823353117689774080","count": 1439,"preSum": 12969 },{ "ndv": 36,"upper": "1823526840526962688","lower": "1823447675689762816","count": 1427,"preSum": 14408 },{ "ndv": 39,"upper": "1823619199503695872","lower": "1823529039550218240","count": 1424,"preSum": 15835 },{ "ndv": 38,"upper": "1823707160433917952","lower": "1823621398526951424","count": 1419,"preSum": 17259 },{ "ndv": 39,"upper": "1823795121364140032","lower": "1823709359457173504","count": 1440,"preSum": 18678 },{ "ndv": 39,"upper": "1823883082294362112","lower": "1823797320387395584","count": 1452,"preSum": 20118 },{ "ndv": 37,"upper": "1823971043224584192","lower": "1823889679364128768","count": 1419,"preSum": 21570 },{ "ndv": 39,"upper": "1824063402201317376","lower": "1823973242247839744","count": 1423,"preSum": 22989 },{ "ndv": 38,"upper": "1824219532852461568","lower": "1824065601224572928","count": 1446,"preSum": 24412 },{ "ndv": 37,"upper": "1824311891829194752","lower": "1824221731875717120","count": 1437,"preSum": 25858 },{ "ndv": 40,"upper": "1824402051782672384","lower": "1824314090852450304","count": 1437,"preSum": 27295 },{ "ndv": 39,"upper": "1824492211736150016","lower": "1824404250805927936","count": 1442,"preSum": 28732 },{ "ndv": 39,"upper": "1824580172666372096","lower": "1824494410759405568","count": 1439,"preSum": 30174 },{ "ndv": 40,"upper": "1824674730666360832","lower": "1824582371689627648","count": 1448,"preSum": 31613 },{ "ndv": 38,"upper": "1824760492573327360","lower": "1824676929689616384","count": 1437,"preSum": 33061 },{ "ndv": 38,"upper": "1824852851550060544","lower": "1824762691596582912","count": 1424,"preSum": 34498 },{ "ndv": 38,"upper": "1824945210526793728","lower": "1824855050573316096","count": 1434,"preSum": 35922 },{ "ndv": 37,"upper": "1825101341177937920","lower": "1824947409550049280","count": 1431,"preSum": 37356 },{ "ndv": 38,"upper": "1825187103084904448","lower": "1825103540201193472","count": 1420,"preSum": 38787 },{ "ndv": 36,"upper": "1825275064015126528","lower": "1825189302108160000","count": 1422,"preSum": 40207 },{ "ndv": 36,"upper": "1825356427875581952","lower": "1825277263038382080","count": 1427,"preSum": 41629 },{ "ndv": 38,"upper": "1825446587829059584","lower": "1825358626898837504","count": 1433,"preSum": 43056 },{ "ndv": 38,"upper": "1825536747782537216","lower": "1825448786852315136","count": 1437,"preSum": 44489 },{ "ndv": 38,"upper": "1825626907736014848","lower": "1825538946805792768","count": 1442,"preSum": 45926 },{ "ndv": 37,"upper": "1825710470619725824","lower": "1825629106759270400","count": 1422,"preSum": 47368 },{ "ndv": 36,"upper": "1825796232526692352","lower": "1825712669642981376","count": 1445,"preSum": 48790 },{ "ndv": 35,"upper": "1825877596387147776","lower": "1825798431549947904","count": 1436,"preSum": 50235 },{ "ndv": 37,"upper": "1826031528015036416","lower": "1825879795410403328","count": 1418,"preSum": 51671 },{ "ndv": 38,"upper": "1826117289922002944","lower": "1826033727038291968","count": 1423,"preSum": 53089 },{ "ndv": 38,"upper": "1826207449875480576","lower": "1826119488945258496","count": 1451,"preSum": 54512 },{ "ndv": 39,"upper": "1826299808852213760","lower": "1826211847921991680","count": 1417,"preSum": 55963 },{ "ndv": 40,"upper": "1826389968805691392","lower": "1826302007875469312","count": 1428,"preSum": 57380 },{ "ndv": 38,"upper": "1826477929735913472","lower": "1826392167828946944","count": 1421,"preSum": 58808 },{ "ndv": 36,"upper": "1826559293596368896","lower": "1826480128759169024","count": 1419,"preSum": 60229 },{ "ndv": 37,"upper": "1826649453549846528","lower": "1826563691642880000","count": 1438,"preSum": 61648 },{ "ndv": 37,"upper": "1826733016433557504","lower": "1826651652573102080","count": 1440,"preSum": 63086 },{ "ndv": 37,"upper": "1826820977363779584","lower": "1826735215456813056","count": 1433,"preSum": 64526 },{ "ndv": 38,"upper": "1826977108014923776","lower": "1826823176387035136","count": 1443,"preSum": 65959 },{ "ndv": 35,"upper": "1827065068945145856","lower": "1826979307038179328","count": 1421,"preSum": 67402 },{ "ndv": 37,"upper": "1827148631828856832","lower": "1827067267968401408","count": 1443,"preSum": 68823 },{ "ndv": 36,"upper": "1827232194712567808","lower": "1827150830852112384","count": 1422,"preSum": 70266 },{ "ndv": 38,"upper": "1827317956619534336","lower": "1827234393735823360","count": 1431,"preSum": 71688 },{ "ndv": 40,"upper": "1827412514619523072","lower": "1827320155642789888","count": 1436,"preSum": 73119 },{ "ndv": 39,"upper": "1827500475549745152","lower": "1827414713642778624","count": 1442,"preSum": 74555 },{ "ndv": 39,"upper": "1827590635503222784","lower": "1827502674573000704","count": 1419,"preSum": 75997 },{ "ndv": 41,"upper": "1827682994479955968","lower": "1827592834526478336","count": 1438,"preSum": 77416 },{ "ndv": 39,"upper": "1827845722200866816","lower": "1827689591549722624","count": 1432,"preSum": 78854 },{ "ndv": 39,"upper": "1827933683131088896","lower": "1827847921224122368","count": 1432,"preSum": 80286 },{ "ndv": 38,"upper": "1828026042107822080","lower": "1827935882154344448","count": 1443,"preSum": 81718 },{ "ndv": 37,"upper": "1828114003038044160","lower": "1828028241131077632","count": 1443,"preSum": 83161 },{ "ndv": 37,"upper": "1828197565921755136","lower": "1828116202061299712","count": 1432,"preSum": 84604 },{ "ndv": 37,"upper": "1828283327828721664","lower": "1828199764945010688","count": 1448,"preSum": 86036 },{ "ndv": 37,"upper": "1828369089735688192","lower": "1828285526851977216","count": 1426,"preSum": 87484 },{ "ndv": 64,"upper": "1828516424293810176","lower": "1828371288758943744","count": 1421,"preSum": 88910 },{ "ndv": 36,"upper": "1828604385224032256","lower": "1828518623317065728","count": 240,"preSum": 90331 } ],"maxBucketSize": 64,"type": "Date","sampleRate": 1.0 }
+  lineitem.l_shipdate.null_count:
+    0
+  lineitem.l_shipdate.sample_rate:
+    1.3317477E-5
+  lineitem.l_shipinstruct.TOPN:
+    { "countArr": [ 22628,23195,22787,22761 ],"valueArr": [ "COLLECT COD","DELIVER IN PERSON","NONE","TAKE BACK RETURN" ],"type": "String","sampleRate": 1.0 }
+  lineitem.l_shipinstruct.cardinality:
+    4
+  lineitem.l_shipinstruct.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  lineitem.l_shipinstruct.null_count:
+    0
+  lineitem.l_shipinstruct.sample_rate:
+    1.3317477E-5
+  lineitem.l_shipmode.TOPN:
+    { "countArr": [ 12939,13100,13160,12868,13108,13141,13055 ],"valueArr": [ "AIR","FOB","MAIL","RAIL","REG AIR","SHIP","TRUCK" ],"type": "String","sampleRate": 1.0 }
+  lineitem.l_shipmode.cardinality:
+    7
+  lineitem.l_shipmode.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  lineitem.l_shipmode.null_count:
+    0
+  lineitem.l_shipmode.sample_rate:
+    1.3317477E-5
+  lineitem.l_suppkey.TOPN:
+    { "countArr": [ 3,3,3,3 ],"valueArr": [ 3759322,5278754,7469718,8418627 ],"type": "Int","sampleRate": 1.0 }
+  lineitem.l_suppkey.cardinality:
+    138253467
+  lineitem.l_suppkey.histogram:
+    { "buckets": [ { "ndv": 1420,"upper": 155628,"lower": 68,"count": 1428,"preSum": 0 },{ "ndv": 1422,"upper": 299702,"lower": 155629,"count": 1428,"preSum": 1428 },{ "ndv": 1418,"upper": 456398,"lower": 299838,"count": 1428,"preSum": 2856 },{ "ndv": 1424,"upper": 618551,"lower": 456749,"count": 1428,"preSum": 4284 },{ "ndv": 1421,"upper": 776188,"lower": 618564,"count": 1428,"preSum": 5712 },{ "ndv": 1419,"upper": 932291,"lower": 776244,"count": 1428,"preSum": 7140 },{ "ndv": 1419,"upper": 1092345,"lower": 932410,"count": 1428,"preSum": 8568 },{ "ndv": 1421,"upper": 1249582,"lower": 1092498,"count": 1428,"preSum": 9996 },{ "ndv": 1418,"upper": 1408239,"lower": 1249626,"count": 1428,"preSum": 11424 },{ "ndv": 1422,"upper": 1567808,"lower": 1408256,"count": 1428,"preSum": 12852 },{ "ndv": 1422,"upper": 1719582,"lower": 1567881,"count": 1428,"preSum": 14280 },{ "ndv": 1422,"upper": 1871123,"lower": 1719616,"count": 1428,"preSum": 15708 },{ "ndv": 1424,"upper": 2026384,"lower": 1871391,"count": 1428,"preSum": 17136 },{ "ndv": 1423,"upper": 2184567,"lower": 2026420,"count": 1428,"preSum": 18564 },{ "ndv": 1417,"upper": 2341646,"lower": 2184650,"count": 1428,"preSum": 19992 },{ "ndv": 1421,"upper": 2498334,"lower": 2341847,"count": 1428,"preSum": 21420 },{ "ndv": 1422,"upper": 2652055,"lower": 2498496,"count": 1428,"preSum": 22848 },{ "ndv": 1418,"upper": 2801710,"lower": 2652156,"count": 1428,"preSum": 24276 },{ "ndv": 1415,"upper": 2955948,"lower": 2801711,"count": 1428,"preSum": 25704 },{ "ndv": 1419,"upper": 3113513,"lower": 2955958,"count": 1428,"preSum": 27132 },{ "ndv": 1425,"upper": 3276309,"lower": 3113956,"count": 1428,"preSum": 28560 },{ "ndv": 1420,"upper": 3434274,"lower": 3276711,"count": 1428,"preSum": 29988 },{ "ndv": 1420,"upper": 3580947,"lower": 3434306,"count": 1428,"preSum": 31416 },{ "ndv": 1422,"upper": 3744137,"lower": 3581126,"count": 1428,"preSum": 32844 },{ "ndv": 1421,"upper": 3892304,"lower": 3744509,"count": 1428,"preSum": 34272 },{ "ndv": 1424,"upper": 4053059,"lower": 3892877,"count": 1428,"preSum": 35700 },{ "ndv": 1417,"upper": 4213307,"lower": 4053294,"count": 1428,"preSum": 37128 },{ "ndv": 1414,"upper": 4365544,"lower": 4213562,"count": 1428,"preSum": 38556 },{ "ndv": 1421,"upper": 4518106,"lower": 4365724,"count": 1428,"preSum": 39984 },{ "ndv": 1421,"upper": 4675501,"lower": 4518111,"count": 1428,"preSum": 41412 },{ "ndv": 1417,"upper": 4830862,"lower": 4675862,"count": 1428,"preSum": 42840 },{ "ndv": 1417,"upper": 4986248,"lower": 4830880,"count": 1428,"preSum": 44268 },{ "ndv": 1420,"upper": 5144112,"lower": 4986627,"count": 1428,"preSum": 45696 },{ "ndv": 1421,"upper": 5303801,"lower": 5144119,"count": 1428,"preSum": 47124 },{ "ndv": 1426,"upper": 5464545,"lower": 5303802,"count": 1428,"preSum": 48552 },{ "ndv": 1422,"upper": 5625830,"lower": 5464886,"count": 1428,"preSum": 49980 },{ "ndv": 1419,"upper": 5785026,"lower": 5625939,"count": 1428,"preSum": 51408 },{ "ndv": 1421,"upper": 5943969,"lower": 5785250,"count": 1428,"preSum": 52836 },{ "ndv": 1421,"upper": 6099974,"lower": 5944163,"count": 1428,"preSum": 54264 },{ "ndv": 1420,"upper": 6257305,"lower": 6100014,"count": 1428,"preSum": 55692 },{ "ndv": 1421,"upper": 6416457,"lower": 6257370,"count": 1428,"preSum": 57120 },{ "ndv": 1422,"upper": 6572590,"lower": 6416691,"count": 1428,"preSum": 58548 },{ "ndv": 1418,"upper": 6738621,"lower": 6572920,"count": 1428,"preSum": 59976 },{ "ndv": 1417,"upper": 6895938,"lower": 6738629,"count": 1428,"preSum": 61404 },{ "ndv": 1422,"upper": 7060721,"lower": 6895988,"count": 1428,"preSum": 62832 },{ "ndv": 1424,"upper": 7211061,"lower": 7060734,"count": 1428,"preSum": 64260 },{ "ndv": 1421,"upper": 7363150,"lower": 7211077,"count": 1428,"preSum": 65688 },{ "ndv": 1421,"upper": 7512110,"lower": 7363240,"count": 1428,"preSum": 67116 },{ "ndv": 1419,"upper": 7657990,"lower": 7512198,"count": 1428,"preSum": 68544 },{ "ndv": 1418,"upper": 7820221,"lower": 7658103,"count": 1428,"preSum": 69972 },{ "ndv": 1421,"upper": 7973017,"lower": 7820836,"count": 1428,"preSum": 71400 },{ "ndv": 1420,"upper": 8129851,"lower": 7973069,"count": 1428,"preSum": 72828 },{ "ndv": 1415,"upper": 8289153,"lower": 8129933,"count": 1428,"preSum": 74256 },{ "ndv": 1418,"upper": 8444024,"lower": 8289226,"count": 1428,"preSum": 75684 },{ "ndv": 1423,"upper": 8599274,"lower": 8444255,"count": 1428,"preSum": 77112 },{ "ndv": 1418,"upper": 8756773,"lower": 8599530,"count": 1428,"preSum": 78540 },{ "ndv": 1414,"upper": 8918816,"lower": 8756868,"count": 1428,"preSum": 79968 },{ "ndv": 1422,"upper": 9076080,"lower": 8918846,"count": 1428,"preSum": 81396 },{ "ndv": 1423,"upper": 9231292,"lower": 9076091,"count": 1428,"preSum": 82824 },{ "ndv": 1421,"upper": 9388488,"lower": 9231303,"count": 1428,"preSum": 84252 },{ "ndv": 1423,"upper": 9538745,"lower": 9388589,"count": 1428,"preSum": 85680 },{ "ndv": 1424,"upper": 9689796,"lower": 9538985,"count": 1428,"preSum": 87108 },{ "ndv": 1422,"upper": 9852558,"lower": 9689800,"count": 1428,"preSum": 88536 },{ "ndv": 1391,"upper": 9999961,"lower": 9852625,"count": 1395,"preSum": 89964 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  lineitem.l_suppkey.null_count:
+    0
+  lineitem.l_suppkey.sample_rate:
+    1.3317477E-5
+  lineitem.l_tax.TOPN:
+    { "countArr": [ 10070,9962,10102,10189,10125,10236,10355,10056,10276 ],"valueArr": [ 0.00,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08 ],"type": "Double","sampleRate": 1.0 }
+  lineitem.l_tax.cardinality:
+    9
+  lineitem.l_tax.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "Double","sampleRate": 1.0 }
+  lineitem.l_tax.null_count:
+    0
+  lineitem.l_tax.sample_rate:
+    1.3317477E-5
+  nation.n_comment.TOPN:
+    null
+  nation.n_comment.cardinality:
+    25
+  nation.n_comment.histogram:
+    { "buckets": [ { "ndv": 4,"upper": " slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull","lower": " haggle. carefully final deposits detect slyly agai","count": 4,"preSum": 0 },{ "ndv": 4,"upper": "eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold","lower": "al foxes promise slyly according to the regular accounts. bold requests alon","count": 4,"preSum": 4 },{ "ndv": 4,"upper": "l platelets. regular accounts x-ray: unusual, regular acco","lower": "efully alongside of the slyly final dependencies. ","count": 4,"preSum": 8 },{ "ndv": 4,"upper": "refully final requests. regular, ironi","lower": "nic deposits boost atop the quickly final requests? quickly regula","count": 4,"preSum": 12 },{ "ndv": 4,"upper": "ts. silent requests haggle. closely express packages sleep across the blithely","lower": "rns. blithely bold courts among the closely regular packages use furiously bold platelets?","count": 4,"preSum": 16 },{ "ndv": 4,"upper": "y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special ","lower": "ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account","count": 4,"preSum": 20 },{ "ndv": 1,"upper": "y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be","lower": "y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be","count": 1,"preSum": 24 } ],"maxBucketSize": 8,"type": "String","sampleRate": 1.0 }
+  nation.n_comment.null_count:
+    0
+  nation.n_comment.sample_rate:
+    1.0
+  nation.n_name.TOPN:
+    null
+  nation.n_name.cardinality:
+    25
+  nation.n_name.histogram:
+    { "buckets": [ { "ndv": 4,"upper": "CANADA","lower": "ALGERIA","count": 4,"preSum": 0 },{ "ndv": 4,"upper": "FRANCE","lower": "CHINA","count": 4,"preSum": 4 },{ "ndv": 4,"upper": "IRAN","lower": "GERMANY","count": 4,"preSum": 8 },{ "ndv": 4,"upper": "KENYA","lower": "IRAQ","count": 4,"preSum": 12 },{ "ndv": 4,"upper": "ROMANIA","lower": "MOROCCO","count": 4,"preSum": 16 },{ "ndv": 4,"upper": "UNITED STATES","lower": "RUSSIA","count": 4,"preSum": 20 },{ "ndv": 1,"upper": "VIETNAM","lower": "VIETNAM","count": 1,"preSum": 24 } ],"maxBucketSize": 8,"type": "String","sampleRate": 1.0 }
+  nation.n_name.null_count:
+    0
+  nation.n_name.sample_rate:
+    1.0
+  nation.n_nationkey.TOPN:
+    null
+  nation.n_nationkey.cardinality:
+    24
+  nation.n_nationkey.histogram:
+    { "buckets": [ { "ndv": 4,"upper": 3,"lower": 0,"count": 4,"preSum": 0 },{ "ndv": 4,"upper": 7,"lower": 4,"count": 4,"preSum": 4 },{ "ndv": 4,"upper": 11,"lower": 8,"count": 4,"preSum": 8 },{ "ndv": 4,"upper": 15,"lower": 12,"count": 4,"preSum": 12 },{ "ndv": 4,"upper": 19,"lower": 16,"count": 4,"preSum": 16 },{ "ndv": 4,"upper": 23,"lower": 20,"count": 4,"preSum": 20 },{ "ndv": 1,"upper": 24,"lower": 24,"count": 1,"preSum": 24 } ],"maxBucketSize": 8,"type": "Int","sampleRate": 1.0 }
+  nation.n_nationkey.null_count:
+    0
+  nation.n_nationkey.sample_rate:
+    1.0
+  nation.n_regionkey.TOPN:
+    { "countArr": [ 5,5,5,5,5 ],"valueArr": [ 0,1,2,3,4 ],"type": "Int","sampleRate": 1.0 }
+  nation.n_regionkey.cardinality:
+    5
+  nation.n_regionkey.histogram:
+    { "buckets": [ ],"maxBucketSize": 8,"type": "Int","sampleRate": 1.0 }
+  nation.n_regionkey.null_count:
+    0
+  nation.n_regionkey.sample_rate:
+    1.0
+  orders.o_clerk.TOPN:
+    { "countArr": [ 4,4 ],"valueArr": [ "Clerk#000138469","Clerk#000604446" ],"type": "String","sampleRate": 1.0 }
+  orders.o_clerk.cardinality:
+    35246272
+  orders.o_clerk.histogram:
+    { "buckets": [ { "ndv": 1436,"upper": "Clerk#000015759","lower": "Clerk#000000001","count": 1504,"preSum": 0 },{ "ndv": 1446,"upper": "Clerk#000030820","lower": "Clerk#000015776","count": 1504,"preSum": 1504 },{ "ndv": 1455,"upper": "Clerk#000047073","lower": "Clerk#000030842","count": 1504,"preSum": 3008 },{ "ndv": 1428,"upper": "Clerk#000062760","lower": "Clerk#000047082","count": 1504,"preSum": 4512 },{ "ndv": 1416,"upper": "Clerk#000078118","lower": "Clerk#000062764","count": 1504,"preSum": 6016 },{ "ndv": 1430,"upper": "Clerk#000093457","lower": "Clerk#000078122","count": 1505,"preSum": 7520 },{ "ndv": 1430,"upper": "Clerk#000108777","lower": "Clerk#000093461","count": 1504,"preSum": 9025 },{ "ndv": 1437,"upper": "Clerk#000124861","lower": "Clerk#000108784","count": 1504,"preSum": 10529 },{ "ndv": 1432,"upper": "Clerk#000140812","lower": "Clerk#000124864","count": 1504,"preSum": 12033 },{ "ndv": 1432,"upper": "Clerk#000156391","lower": "Clerk#000140826","count": 1504,"preSum": 13537 },{ "ndv": 1424,"upper": "Clerk#000171930","lower": "Clerk#000156411","count": 1504,"preSum": 15041 },{ "ndv": 1440,"upper": "Clerk#000187339","lower": "Clerk#000171940","count": 1504,"preSum": 16545 },{ "ndv": 1443,"upper": "Clerk#000202918","lower": "Clerk#000187340","count": 1504,"preSum": 18049 },{ "ndv": 1439,"upper": "Clerk#000218320","lower": "Clerk#000202930","count": 1504,"preSum": 19553 },{ "ndv": 1432,"upper": "Clerk#000234328","lower": "Clerk#000218324","count": 1504,"preSum": 21057 },{ "ndv": 1427,"upper": "Clerk#000249841","lower": "Clerk#000234370","count": 1504,"preSum": 22561 },{ "ndv": 1430,"upper": "Clerk#000265443","lower": "Clerk#000249850","count": 1504,"preSum": 24065 },{ "ndv": 1430,"upper": "Clerk#000280769","lower": "Clerk#000265445","count": 1504,"preSum": 25569 },{ "ndv": 1438,"upper": "Clerk#000296661","lower": "Clerk#000280819","count": 1504,"preSum": 27073 },{ "ndv": 1447,"upper": "Clerk#000313066","lower": "Clerk#000296671","count": 1504,"preSum": 28577 },{ "ndv": 1431,"upper": "Clerk#000328537","lower": "Clerk#000313102","count": 1504,"preSum": 30081 },{ "ndv": 1447,"upper": "Clerk#000344236","lower": "Clerk#000328547","count": 1504,"preSum": 31585 },{ "ndv": 1434,"upper": "Clerk#000359383","lower": "Clerk#000344240","count": 1504,"preSum": 33089 },{ "ndv": 1433,"upper": "Clerk#000375121","lower": "Clerk#000359390","count": 1504,"preSum": 34593 },{ "ndv": 1429,"upper": "Clerk#000390607","lower": "Clerk#000375151","count": 1504,"preSum": 36097 },{ "ndv": 1429,"upper": "Clerk#000406184","lower": "Clerk#000390609","count": 1504,"preSum": 37601 },{ "ndv": 1436,"upper": "Clerk#000421594","lower": "Clerk#000406191","count": 1504,"preSum": 39105 },{ "ndv": 1430,"upper": "Clerk#000437378","lower": "Clerk#000421606","count": 1504,"preSum": 40609 },{ "ndv": 1434,"upper": "Clerk#000453357","lower": "Clerk#000437386","count": 1504,"preSum": 42113 },{ "ndv": 1442,"upper": "Clerk#000469158","lower": "Clerk#000453374","count": 1504,"preSum": 43617 },{ "ndv": 1438,"upper": "Clerk#000484618","lower": "Clerk#000469165","count": 1504,"preSum": 45121 },{ "ndv": 1442,"upper": "Clerk#000500370","lower": "Clerk#000484620","count": 1504,"preSum": 46625 },{ "ndv": 1446,"upper": "Clerk#000516464","lower": "Clerk#000500377","count": 1504,"preSum": 48129 },{ "ndv": 1419,"upper": "Clerk#000531912","lower": "Clerk#000516474","count": 1504,"preSum": 49633 },{ "ndv": 1434,"upper": "Clerk#000547136","lower": "Clerk#000531947","count": 1504,"preSum": 51137 },{ "ndv": 1435,"upper": "Clerk#000562794","lower": "Clerk#000547139","count": 1504,"preSum": 52641 },{ "ndv": 1429,"upper": "Clerk#000577775","lower": "Clerk#000562801","count": 1504,"preSum": 54145 },{ "ndv": 1433,"upper": "Clerk#000593717","lower": "Clerk#000577776","count": 1504,"preSum": 55649 },{ "ndv": 1445,"upper": "Clerk#000609282","lower": "Clerk#000593737","count": 1504,"preSum": 57153 },{ "ndv": 1436,"upper": "Clerk#000624422","lower": "Clerk#000609284","count": 1504,"preSum": 58657 },{ "ndv": 1431,"upper": "Clerk#000639826","lower": "Clerk#000624430","count": 1504,"preSum": 60161 },{ "ndv": 1437,"upper": "Clerk#000655184","lower": "Clerk#000639849","count": 1504,"preSum": 61665 },{ "ndv": 1434,"upper": "Clerk#000670493","lower": "Clerk#000655200","count": 1504,"preSum": 63169 },{ "ndv": 1434,"upper": "Clerk#000686082","lower": "Clerk#000670498","count": 1504,"preSum": 64673 },{ "ndv": 1432,"upper": "Clerk#000701971","lower": "Clerk#000686091","count": 1504,"preSum": 66177 },{ "ndv": 1435,"upper": "Clerk#000717532","lower": "Clerk#000701999","count": 1504,"preSum": 67681 },{ "ndv": 1438,"upper": "Clerk#000733856","lower": "Clerk#000717549","count": 1504,"preSum": 69185 },{ "ndv": 1447,"upper": "Clerk#000749905","lower": "Clerk#000733864","count": 1504,"preSum": 70689 },{ "ndv": 1442,"upper": "Clerk#000765312","lower": "Clerk#000749911","count": 1504,"preSum": 72193 },{ "ndv": 1434,"upper": "Clerk#000780882","lower": "Clerk#000765325","count": 1504,"preSum": 73697 },{ "ndv": 1438,"upper": "Clerk#000797038","lower": "Clerk#000780883","count": 1504,"preSum": 75201 },{ "ndv": 1433,"upper": "Clerk#000812650","lower": "Clerk#000797044","count": 1504,"preSum": 76705 },{ "ndv": 1433,"upper": "Clerk#000827905","lower": "Clerk#000812663","count": 1504,"preSum": 78209 },{ "ndv": 1430,"upper": "Clerk#000844159","lower": "Clerk#000827916","count": 1504,"preSum": 79713 },{ "ndv": 1425,"upper": "Clerk#000859405","lower": "Clerk#000844163","count": 1504,"preSum": 81217 },{ "ndv": 1434,"upper": "Clerk#000876217","lower": "Clerk#000859437","count": 1504,"preSum": 82721 },{ "ndv": 1426,"upper": "Clerk#000891564","lower": "Clerk#000876221","count": 1504,"preSum": 84225 },{ "ndv": 1437,"upper": "Clerk#000907349","lower": "Clerk#000891573","count": 1504,"preSum": 85729 },{ "ndv": 1435,"upper": "Clerk#000922843","lower": "Clerk#000907358","count": 1504,"preSum": 87233 },{ "ndv": 1431,"upper": "Clerk#000938371","lower": "Clerk#000922862","count": 1504,"preSum": 88737 },{ "ndv": 1420,"upper": "Clerk#000953791","lower": "Clerk#000938379","count": 1504,"preSum": 90241 },{ "ndv": 1442,"upper": "Clerk#000969708","lower": "Clerk#000953813","count": 1504,"preSum": 91745 },{ "ndv": 1442,"upper": "Clerk#000985273","lower": "Clerk#000969713","count": 1504,"preSum": 93249 },{ "ndv": 1376,"upper": "Clerk#000999994","lower": "Clerk#000985274","count": 1441,"preSum": 94753 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  orders.o_clerk.null_count:
+    0
+  orders.o_clerk.sample_rate:
+    5.793356E-5
+  orders.o_comment.TOPN:
+    { "countArr": [ 3,3,3 ],"valueArr": [ " special pinto bean","carefully regular deposit","ly special packages" ],"type": "String","sampleRate": 1.0 }
+  orders.o_comment.cardinality:
+    78330091
+  orders.o_comment.histogram:
+    { "buckets": [ { "ndv": 1499,"upper": " asymptotes was. even theodolites boost ","lower": " about the accounts sleep furiously around the fluffily regul","count": 1504,"preSum": 0 },{ "ndv": 1503,"upper": " carefully furiously special packages. slyly regular ideas was blithely fin","lower": " asymptotes! ironic platelets are pinto beans: carefully even ","count": 1504,"preSum": 1504 },{ "ndv": 1503,"upper": " excuses. blithely even packages alongside of the ","lower": " carefully furiously u","count": 1504,"preSum": 3008 },{ "ndv": 1501,"upper": " grow above the blithely r","lower": " excuses. blithely final theodolites are accordin","count": 1504,"preSum": 4512 },{ "ndv": 1499,"upper": " packages impress slyly along the quickly final p","lower": " grow alongside of the ironically ironic foxes. ironically final acc","count": 1504,"preSum": 6016 },{ "ndv": 1503,"upper": " regular requests are blithely according to the sly dependencies. regul","lower": " packages integrate above the acco","count": 1504,"preSum": 7520 },{ "ndv": 1503,"upper": " special dependencies. blit","lower": " regular requests are blithely alongside of the ideas. s","count": 1504,"preSum": 9024 },{ "ndv": 1501,"upper": " unusual deposits. instructions after the dogged instru","lower": " special dependencies. slyly regular pinto beans wake after the reg","count": 1504,"preSum": 10528 },{ "ndv": 1500,"upper": ". fluffily final deposits atop the final depende","lower": " unusual deposits. ironic ideas accordin","count": 1504,"preSum": 12032 },{ "ndv": 1501,"upper": "accounts. final foxes cajole fluffily daring Tiresias. c","lower": ". fluffily final packages cajole fu","count": 1504,"preSum": 13536 },{ "ndv": 1503,"upper": "aggle unusual, final pinto beans. slyly f","lower": "accounts. final requests sleep. ideas are about the slyly even requests. blith","count": 1504,"preSum": 15040 },{ "ndv": 1503,"upper": "along the slyly fluffy accounts. ","lower": "aggle-- even dolphins about the packages detect perm","count": 1504,"preSum": 16544 },{ "ndv": 1503,"upper": "arefully regular dolphins sleep sl","lower": "along the slyly regular deposits affix across the quickly pending packa","count": 1504,"preSum": 18048 },{ "ndv": 1501,"upper": "blithely unusual platelets above the slyly reg","lower": "arefully regular dugouts. packages along the blithely express t","count": 1504,"preSum": 19552 },{ "ndv": 1502,"upper": "carefully ironic platelets use regularly about the furiously ironic","lower": "blithely unusual reques","count": 1504,"preSum": 21056 },{ "ndv": 1502,"upper": "ckly enticing deposits sleep blithely against the e","lower": "carefully ironic requests boost slyly regular packages.","count": 1504,"preSum": 22560 },{ "ndv": 1499,"upper": "d, bold requests use final ideas. carefully bold packages haggle quickly a","lower": "ckly enticing packages cajole quickly. ins","count": 1504,"preSum": 24064 },{ "ndv": 1504,"upper": "dolites. furiously special","lower": "d, bold tithes. bold courts are quickly. even pinto beans sleep sl","count": 1504,"preSum": 25568 },{ "ndv": 1501,"upper": "e quickly ironic deposits. ironic asymptotes according to the deposi","lower": "dolites. instructions haggle","count": 1504,"preSum": 27072 },{ "ndv": 1504,"upper": "eep blithely regular requests. ironic, brave requests alongside of the special","lower": "e quickly ironic deposits? quickly even ","count": 1504,"preSum": 28576 },{ "ndv": 1504,"upper": "ely express packages cajole furiously finally iron","lower": "eep blithely regular, final pinto beans. blithely pending t","count": 1504,"preSum": 30080 },{ "ndv": 1504,"upper": "ependencies. packages boost ironic, ex","lower": "ely express packages use carefully express packa","count": 1504,"preSum": 31584 },{ "ndv": 1502,"upper": "es sleep slyly blithely regular ","lower": "ependencies. pinto beans ac","count": 1504,"preSum": 33088 },{ "ndv": 1503,"upper": "even deposits. blithely express packages cajole quickly regula","lower": "es sleep slyly ironic requests. slyly pending pac","count": 1504,"preSum": 34592 },{ "ndv": 1503,"upper": "final requests. quickly bold accounts across the blithely express foxes slee","lower": "even deposits. blithely unusual packages about ","count": 1504,"preSum": 36096 },{ "ndv": 1501,"upper": "furiously ironic pinto beans. bold accounts are slyl","lower": "final requests. regular ","count": 1504,"preSum": 37600 },{ "ndv": 1503,"upper": "ggle quickly. slyly ironic ideas use idly fluffily unusu","lower": "furiously ironic pinto beans. instruction","count": 1504,"preSum": 39104 },{ "ndv": 1503,"upper": "he final asymptotes. final requests wake slyly furiously express foxe","lower": "ggle quickly. slyly silent packages ","count": 1504,"preSum": 40608 },{ "ndv": 1500,"upper": "ial foxes haggle among the final p","lower": "he final deposits. furiously even dolphins are slyly agai","count": 1504,"preSum": 42112 },{ "ndv": 1502,"upper": "ily bold waters wake after the requests. carefully final ideas play s","lower": "ial foxes hang across the fluffily ironic foxes. ","count": 1504,"preSum": 43616 },{ "ndv": 1502,"upper": "integrate slyly among the carefully express deposits","lower": "ily careful accounts are slyly care","count": 1504,"preSum": 45120 },{ "ndv": 1502,"upper": "ites sleep even, regular dependencies. final pinto bean","lower": "integrate slyly carefully ironic packages. packages alongside of the slyl","count": 1504,"preSum": 46624 },{ "ndv": 1502,"upper": "kages. regular, busy instructions haggle regular foxes. car","lower": "ites sleep furiously across the carefully even warthogs. f","count": 1504,"preSum": 48128 },{ "ndv": 1503,"upper": "lar accounts. furiously ironic accounts haggle slyly ","lower": "kages. regular, pending pinto b","count": 1504,"preSum": 49632 },{ "ndv": 1504,"upper": "leep: permanently final deposits around the quickly ","lower": "lar accounts. ideas sleep according to the blithely ","count": 1504,"preSum": 51136 },{ "ndv": 1501,"upper": "longside of the final orbits. blithely ironic requests cajole unusual d","lower": "leep; slyly final gifts use ","count": 1504,"preSum": 52640 },{ "ndv": 1499,"upper": "ly final pinto beans. regular, even instructions agai","lower": "longside of the fluffily bold requests cajole about the express, ir","count": 1504,"preSum": 54144 },{ "ndv": 1500,"upper": "ly. quickly regular accounts might sleep. slyly pending accounts use flu","lower": "ly final pinto beans. s","count": 1504,"preSum": 55648 },{ "ndv": 1504,"upper": "nal ideas play silently furiously ","lower": "ly. quickly regular attainments boost ironic,","count": 1504,"preSum": 57152 },{ "ndv": 1504,"upper": "nic ideas alongside of the blithely ir","lower": "nal ideas sleep blithel","count": 1504,"preSum": 58656 },{ "ndv": 1502,"upper": "nts are slyly after the bold, express requests! quickly unusual ","lower": "nic ideas are alongside of the slyly ironic theodolites. even","count": 1504,"preSum": 60160 },{ "ndv": 1503,"upper": "ole. braids hinder ironic, regular requests. foxes cajole carefully pending id","lower": "nts are slyly around the pending depos","count": 1504,"preSum": 61664 },{ "ndv": 1501,"upper": "osits alongside of the quickly final packa","lower": "ole. carefully express foxes sleep fluffily slyly bold requ","count": 1504,"preSum": 63168 },{ "ndv": 1504,"upper": "ously regular accou","lower": "osits among the furiously final theodoli","count": 1504,"preSum": 64672 },{ "ndv": 1501,"upper": "pendencies. carefully final packages c","lower": "ously regular accounts after the ironic theodolites nag acros","count": 1504,"preSum": 66176 },{ "ndv": 1502,"upper": "quests haggle special platelets. final deposits boost carefully foxes. b","lower": "pendencies. carefully ironic deposits cajole furiously f","count": 1504,"preSum": 67680 },{ "ndv": 1501,"upper": "re above the finally even packages. carefully special re","lower": "quests haggle. regular, idle ","count": 1504,"preSum": 69184 },{ "ndv": 1499,"upper": "requests. enticingly pending accounts sublate","lower": "re according to the carefully express requests. carefully","count": 1504,"preSum": 70688 },{ "ndv": 1504,"upper": "ross the even dependencies wake quickly carefully special platelets. ","lower": "requests. even dependencies wake carefu","count": 1504,"preSum": 72192 },{ "ndv": 1504,"upper": "s doze fluffily even foxes. thinly unusual warh","lower": "ross the even requests. s","count": 1504,"preSum": 73696 },{ "ndv": 1503,"upper": "s. carefully even requests solve furiously","lower": "s doze fluffily. slyly i","count": 1504,"preSum": 75200 },{ "ndv": 1501,"upper": "sits affix quickly above the final instructions. carefully regular accounts d","lower": "s. carefully even theodolites haggle. ironic packages are fu","count": 1504,"preSum": 76704 },{ "ndv": 1503,"upper": "slyly slyly ironic instructions. express ","lower": "sits affix quickly. expr","count": 1504,"preSum": 78208 },{ "ndv": 1503,"upper": "sual frays about the final accounts haggle blithely even deposits","lower": "slyly slyly ironic packages. evenly unusual packages","count": 1504,"preSum": 79712 },{ "ndv": 1504,"upper": "the blithely express instructio","lower": "sual frays. final packages against the stealthily spec","count": 1504,"preSum": 81216 },{ "ndv": 1501,"upper": "thinly pending accounts cajole quickly ironic pinto beans. blithely regular p","lower": "the blithely express instructions. carefully regular request","count": 1504,"preSum": 82720 },{ "ndv": 1504,"upper": "ts poach fluffily unusual instructions. blit","lower": "thinly regular instructions. flu","count": 1504,"preSum": 84224 },{ "ndv": 1504,"upper": "uests. blithe requests nag slyly pending","lower": "ts poach slyly furiously final foxes. closely even requests a","count": 1504,"preSum": 85728 },{ "ndv": 1501,"upper": "ully final dependencies against the spe","lower": "uests. blithely blithe theodolites detec","count": 1504,"preSum": 87232 },{ "ndv": 1501,"upper": "uriously special th","lower": "ully final dependencies are. carefully unusual foxes hag","count": 1504,"preSum": 88736 },{ "ndv": 1504,"upper": "ven excuses boost slyly alongsi","lower": "uriously stealthy packages. fluffily ironic foxes across the ","count": 1504,"preSum": 90240 },{ "ndv": 1504,"upper": "y bold deposits. bold deposits cajole slyly alon","lower": "ven excuses cajole. ideas across the ","count": 1504,"preSum": 91744 },{ "ndv": 1503,"upper": "y regular packages. dolphin","lower": "y bold deposits. carefully pending requests kindle blithely ","count": 1504,"preSum": 93248 },{ "ndv": 1437,"upper": "zzle. carefully enticing deposits nag furio","lower": "y regular packages. fluffily busy acco","count": 1441,"preSum": 94752 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  orders.o_comment.null_count:
+    0
+  orders.o_comment.sample_rate:
+    5.793356E-5
+  orders.o_custkey.TOPN:
+    null
+  orders.o_custkey.cardinality:
+    78330071
+  orders.o_custkey.histogram:
+    { "buckets": [ { "ndv": 1504,"upper": 2373841,"lower": 79,"count": 1504,"preSum": 0 },{ "ndv": 1503,"upper": 4735894,"lower": 2373970,"count": 1504,"preSum": 1504 },{ "ndv": 1502,"upper": 7095994,"lower": 4736203,"count": 1504,"preSum": 3008 },{ "ndv": 1504,"upper": 9382030,"lower": 7098107,"count": 1504,"preSum": 4512 },{ "ndv": 1503,"upper": 11737610,"lower": 9382561,"count": 1504,"preSum": 6016 },{ "ndv": 1503,"upper": 14152252,"lower": 11739127,"count": 1504,"preSum": 7520 },{ "ndv": 1504,"upper": 16401658,"lower": 14152979,"count": 1504,"preSum": 9024 },{ "ndv": 1504,"upper": 18796024,"lower": 16402355,"count": 1504,"preSum": 10528 },{ "ndv": 1504,"upper": 21146707,"lower": 18796669,"count": 1504,"preSum": 12032 },{ "ndv": 1503,"upper": 23441240,"lower": 21147349,"count": 1504,"preSum": 13536 },{ "ndv": 1504,"upper": 25691164,"lower": 23443942,"count": 1504,"preSum": 15040 },{ "ndv": 1503,"upper": 28123357,"lower": 25695016,"count": 1504,"preSum": 16544 },{ "ndv": 1502,"upper": 30506740,"lower": 28125884,"count": 1504,"preSum": 18048 },{ "ndv": 1504,"upper": 32835524,"lower": 30507349,"count": 1504,"preSum": 19552 },{ "ndv": 1502,"upper": 35116798,"lower": 32836159,"count": 1504,"preSum": 21056 },{ "ndv": 1504,"upper": 37483354,"lower": 35120942,"count": 1504,"preSum": 22560 },{ "ndv": 1503,"upper": 39775126,"lower": 37483754,"count": 1504,"preSum": 24064 },{ "ndv": 1503,"upper": 42240322,"lower": 39775145,"count": 1504,"preSum": 25568 },{ "ndv": 1504,"upper": 44552185,"lower": 42240959,"count": 1504,"preSum": 27072 },{ "ndv": 1503,"upper": 46896503,"lower": 44554894,"count": 1504,"preSum": 28576 },{ "ndv": 1502,"upper": 49183865,"lower": 46902376,"count": 1504,"preSum": 30080 },{ "ndv": 1504,"upper": 51461971,"lower": 49183909,"count": 1504,"preSum": 31584 },{ "ndv": 1504,"upper": 53776948,"lower": 51463391,"count": 1504,"preSum": 33088 },{ "ndv": 1504,"upper": 56193673,"lower": 53778308,"count": 1504,"preSum": 34592 },{ "ndv": 1504,"upper": 58483943,"lower": 56194693,"count": 1504,"preSum": 36096 },{ "ndv": 1503,"upper": 60773044,"lower": 58485502,"count": 1504,"preSum": 37600 },{ "ndv": 1504,"upper": 63205333,"lower": 60774928,"count": 1504,"preSum": 39104 },{ "ndv": 1504,"upper": 65593753,"lower": 63206291,"count": 1504,"preSum": 40608 },{ "ndv": 1504,"upper": 67958110,"lower": 65596496,"count": 1504,"preSum": 42112 },{ "ndv": 1504,"upper": 70267340,"lower": 67959050,"count": 1504,"preSum": 43616 },{ "ndv": 1503,"upper": 72709397,"lower": 70268497,"count": 1504,"preSum": 45120 },{ "ndv": 1502,"upper": 75108379,"lower": 72709553,"count": 1504,"preSum": 46624 },{ "ndv": 1503,"upper": 77447102,"lower": 75108808,"count": 1504,"preSum": 48128 },{ "ndv": 1502,"upper": 79836880,"lower": 77449726,"count": 1504,"preSum": 49632 },{ "ndv": 1503,"upper": 82110817,"lower": 79838332,"count": 1504,"preSum": 51136 },{ "ndv": 1503,"upper": 84451846,"lower": 82111000,"count": 1504,"preSum": 52640 },{ "ndv": 1503,"upper": 86847014,"lower": 84455768,"count": 1504,"preSum": 54144 },{ "ndv": 1501,"upper": 89202487,"lower": 86848799,"count": 1504,"preSum": 55648 },{ "ndv": 1503,"upper": 91582612,"lower": 89208853,"count": 1504,"preSum": 57152 },{ "ndv": 1503,"upper": 93959485,"lower": 91585313,"count": 1504,"preSum": 58656 },{ "ndv": 1502,"upper": 96137938,"lower": 93959968,"count": 1504,"preSum": 60160 },{ "ndv": 1503,"upper": 98416406,"lower": 96139277,"count": 1504,"preSum": 61664 },{ "ndv": 1503,"upper": 100779121,"lower": 98416801,"count": 1504,"preSum": 63168 },{ "ndv": 1504,"upper": 103201141,"lower": 100779172,"count": 1504,"preSum": 64672 },{ "ndv": 1503,"upper": 105539692,"lower": 103202282,"count": 1504,"preSum": 66176 },{ "ndv": 1503,"upper": 107868487,"lower": 105541261,"count": 1504,"preSum": 67680 },{ "ndv": 1501,"upper": 110193005,"lower": 107868776,"count": 1504,"preSum": 69184 },{ "ndv": 1503,"upper": 112561168,"lower": 110195222,"count": 1504,"preSum": 70688 },{ "ndv": 1503,"upper": 114871675,"lower": 112563008,"count": 1504,"preSum": 72192 },{ "ndv": 1502,"upper": 117244678,"lower": 114872956,"count": 1504,"preSum": 73696 },{ "ndv": 1504,"upper": 119653433,"lower": 117251002,"count": 1504,"preSum": 75200 },{ "ndv": 1503,"upper": 121957684,"lower": 119653664,"count": 1504,"preSum": 76704 },{ "ndv": 1504,"upper": 124356391,"lower": 121958890,"count": 1504,"preSum": 78208 },{ "ndv": 1503,"upper": 126612587,"lower": 124356416,"count": 1504,"preSum": 79712 },{ "ndv": 1504,"upper": 128959993,"lower": 126613516,"count": 1504,"preSum": 81216 },{ "ndv": 1504,"upper": 131351177,"lower": 128960773,"count": 1504,"preSum": 82720 },{ "ndv": 1504,"upper": 133778792,"lower": 131351518,"count": 1504,"preSum": 84224 },{ "ndv": 1504,"upper": 136099577,"lower": 133779172,"count": 1504,"preSum": 85728 },{ "ndv": 1504,"upper": 138360661,"lower": 136103606,"count": 1504,"preSum": 87232 },{ "ndv": 1504,"upper": 140858962,"lower": 138362167,"count": 1504,"preSum": 88736 },{ "ndv": 1504,"upper": 143185927,"lower": 140863390,"count": 1504,"preSum": 90240 },{ "ndv": 1503,"upper": 145529131,"lower": 143186134,"count": 1504,"preSum": 91744 },{ "ndv": 1503,"upper": 147808762,"lower": 145530032,"count": 1504,"preSum": 93248 },{ "ndv": 1449,"upper": 149999387,"lower": 147810031,"count": 1450,"preSum": 94752 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  orders.o_custkey.null_count:
+    0
+  orders.o_custkey.sample_rate:
+    5.793356E-5
+  orders.o_orderdate.TOPN:
+    { "countArr": [ 59,65,59,60,63,61,62,61,60,60,61,68 ],"valueArr": [ 1822385547457331200,1822908914992152576,1822968288620052480,1823289346015363072,1824347076201283584,1824349275224539136,1824406449829183488,1824687924805894144,1825002385131438080,1825345432759304192,1825657694061592576,1826746210573090816 ],"type": "Date","sampleRate": 1.0 }
+  orders.o_orderdate.cardinality:
+    2406
+  orders.o_orderdate.histogram:
+    { "buckets": [ { "ndv": 38,"upper": "1822427328899186688","lower": "1822341566992220160","count": 1536,"preSum": 0 },{ "ndv": 39,"upper": "1822519687875919872","lower": "1822429527922442240","count": 1513,"preSum": 1536 },{ "ndv": 38,"upper": "1822605449782886400","lower": "1822521886899175424","count": 1527,"preSum": 3049 },{ "ndv": 38,"upper": "1822695609736364032","lower": "1822607648806141952","count": 1527,"preSum": 4576 },{ "ndv": 39,"upper": "1822785769689841664","lower": "1822697808759619584","count": 1496,"preSum": 6103 },{ "ndv": 36,"upper": "1822867133550297088","lower": "1822787968713097216","count": 1504,"preSum": 7599 },{ "ndv": 37,"upper": "1822952895457263616","lower": "1822869332573552640","count": 1524,"preSum": 9103 },{ "ndv": 38,"upper": "1823045254433996800","lower": "1822955094480519168","count": 1518,"preSum": 10627 },{ "ndv": 39,"upper": "1823135414387474432","lower": "1823047453457252352","count": 1500,"preSum": 12145 },{ "ndv": 38,"upper": "1823293744061874176","lower": "1823137613410729984","count": 1518,"preSum": 13645 },{ "ndv": 38,"upper": "1823379505968840704","lower": "1823295943085129728","count": 1521,"preSum": 15163 },{ "ndv": 39,"upper": "1823476262992084992","lower": "1823381704992096256","count": 1517,"preSum": 16684 },{ "ndv": 39,"upper": "1823566422945562624","lower": "1823478462015340544","count": 1504,"preSum": 18201 },{ "ndv": 36,"upper": "1823647786806018048","lower": "1823568621968818176","count": 1530,"preSum": 19705 },{ "ndv": 39,"upper": "1823737946759495680","lower": "1823649985829273600","count": 1513,"preSum": 21235 },{ "ndv": 37,"upper": "1823823708666462208","lower": "1823740145782751232","count": 1498,"preSum": 22748 },{ "ndv": 37,"upper": "1823909470573428736","lower": "1823825907689717760","count": 1498,"preSum": 24246 },{ "ndv": 40,"upper": "1823999630526906368","lower": "1823911669596684288","count": 1518,"preSum": 25744 },{ "ndv": 37,"upper": "1824085392433872896","lower": "1824001829550161920","count": 1506,"preSum": 27262 },{ "ndv": 37,"upper": "1824241523085017088","lower": "1824087591457128448","count": 1516,"preSum": 28768 },{ "ndv": 38,"upper": "1824333882061750272","lower": "1824243722108272640","count": 1504,"preSum": 30284 },{ "ndv": 38,"upper": "1824426241038483456","lower": "1824336081085005824","count": 1516,"preSum": 31788 },{ "ndv": 39,"upper": "1824516400991961088","lower": "1824428440061739008","count": 1525,"preSum": 33304 },{ "ndv": 39,"upper": "1824608759968694272","lower": "1824518600015216640","count": 1492,"preSum": 34829 },{ "ndv": 38,"upper": "1824696720898916352","lower": "1824610958991949824","count": 1528,"preSum": 36321 },{ "ndv": 38,"upper": "1824782482805882880","lower": "1824698919922171904","count": 1523,"preSum": 37849 },{ "ndv": 39,"upper": "1824874841782616064","lower": "1824784681829138432","count": 1507,"preSum": 39372 },{ "ndv": 39,"upper": "1824965001736093696","lower": "1824877040805871616","count": 1519,"preSum": 40879 },{ "ndv": 37,"upper": "1825121132387237888","lower": "1824967200759349248","count": 1508,"preSum": 42398 },{ "ndv": 38,"upper": "1825206894294204416","lower": "1825123331410493440","count": 1495,"preSum": 43906 },{ "ndv": 38,"upper": "1825301452294193152","lower": "1825209093317459968","count": 1514,"preSum": 45401 },{ "ndv": 37,"upper": "1825389413224415232","lower": "1825303651317448704","count": 1512,"preSum": 46915 },{ "ndv": 38,"upper": "1825475175131381760","lower": "1825391612247670784","count": 1524,"preSum": 48427 },{ "ndv": 37,"upper": "1825560937038348288","lower": "1825477374154637312","count": 1514,"preSum": 49951 },{ "ndv": 38,"upper": "1825648897968570368","lower": "1825563136061603840","count": 1522,"preSum": 51465 },{ "ndv": 39,"upper": "1825741256945303552","lower": "1825651096991825920","count": 1508,"preSum": 52987 },{ "ndv": 37,"upper": "1825824819829014528","lower": "1825743455968559104","count": 1521,"preSum": 54495 },{ "ndv": 39,"upper": "1825914979782492160","lower": "1825827018852270080","count": 1515,"preSum": 56016 },{ "ndv": 40,"upper": "1826077707503403008","lower": "1825917178805747712","count": 1525,"preSum": 57531 },{ "ndv": 37,"upper": "1826165668433625088","lower": "1826079906526658560","count": 1501,"preSum": 59056 },{ "ndv": 36,"upper": "1826247032294080512","lower": "1826167867456880640","count": 1508,"preSum": 60557 },{ "ndv": 37,"upper": "1826332794201047040","lower": "1826249231317336064","count": 1519,"preSum": 62065 },{ "ndv": 38,"upper": "1826422954154524672","lower": "1826334993224302592","count": 1498,"preSum": 63584 },{ "ndv": 38,"upper": "1826508716061491200","lower": "1826425153177780224","count": 1531,"preSum": 65082 },{ "ndv": 37,"upper": "1826592278945202176","lower": "1826510915084746752","count": 1525,"preSum": 66613 },{ "ndv": 38,"upper": "1826680239875424256","lower": "1826594477968457728","count": 1516,"preSum": 68138 },{ "ndv": 38,"upper": "1826768200805646336","lower": "1826682438898679808","count": 1518,"preSum": 69654 },{ "ndv": 38,"upper": "1826928729503301632","lower": "1826774797875412992","count": 1502,"preSum": 71172 },{ "ndv": 37,"upper": "1827012292387012608","lower": "1826930928526557184","count": 1519,"preSum": 72674 },{ "ndv": 38,"upper": "1827104651363745792","lower": "1827014491410268160","count": 1502,"preSum": 74193 },{ "ndv": 38,"upper": "1827190413270712320","lower": "1827106850387001344","count": 1510,"preSum": 75695 },{ "ndv": 39,"upper": "1827282772247445504","lower": "1827197010340478976","count": 1496,"preSum": 77205 },{ "ndv": 38,"upper": "1827370733177667584","lower": "1827284971270701056","count": 1510,"preSum": 78701 },{ "ndv": 38,"upper": "1827456495084634112","lower": "1827372932200923136","count": 1526,"preSum": 80211 },{ "ndv": 39,"upper": "1827548854061367296","lower": "1827458694107889664","count": 1511,"preSum": 81737 },{ "ndv": 38,"upper": "1827634615968333824","lower": "1827551053084622848","count": 1511,"preSum": 83248 },{ "ndv": 37,"upper": "1827720377875300352","lower": "1827636814991589376","count": 1513,"preSum": 84759 },{ "ndv": 38,"upper": "1827876508526444544","lower": "1827722576898555904","count": 1496,"preSum": 86272 },{ "ndv": 38,"upper": "1827971066526433280","lower": "1827878707549700096","count": 1526,"preSum": 87768 },{ "ndv": 38,"upper": "1828056828433399808","lower": "1827973265549688832","count": 1525,"preSum": 89294 },{ "ndv": 37,"upper": "1828142590340366336","lower": "1828059027456655360","count": 1500,"preSum": 90819 },{ "ndv": 38,"upper": "1828228352247332864","lower": "1828144789363621888","count": 1514,"preSum": 92319 },{ "ndv": 38,"upper": "1828316313177554944","lower": "1828230551270588416","count": 1501,"preSum": 93833 },{ "ndv": 3,"upper": "1828325109270577152","lower": "1828318512200810496","count": 129,"preSum": 95334 } ],"maxBucketSize": 64,"type": "Date","sampleRate": 1.0 }
+  orders.o_orderdate.null_count:
+    0
+  orders.o_orderdate.sample_rate:
+    5.793356E-5
+  orders.o_orderkey.TOPN:
+    null
+  orders.o_orderkey.cardinality:
+    84863050
+  orders.o_orderkey.histogram:
+    { "buckets": [ { "ndv": 1504,"upper": 6016,"lower": 1,"count": 1504,"preSum": 0 },{ "ndv": 1504,"upper": 12032,"lower": 6017,"count": 1504,"preSum": 1504 },{ "ndv": 1504,"upper": 18117,"lower": 12033,"count": 1504,"preSum": 3008 },{ "ndv": 1504,"upper": 25316,"lower": 18118,"count": 1504,"preSum": 4512 },{ "ndv": 1504,"upper": 3618756,"lower": 25317,"count": 1504,"preSum": 6016 },{ "ndv": 1504,"upper": 137342342,"lower": 3618758,"count": 1504,"preSum": 7520 },{ "ndv": 1504,"upper": 215218340,"lower": 137342784,"count": 1504,"preSum": 9024 },{ "ndv": 1504,"upper": 349451175,"lower": 215219365,"count": 1504,"preSum": 10528 },{ "ndv": 1504,"upper": 498103425,"lower": 349451527,"count": 1504,"preSum": 12032 },{ "ndv": 1504,"upper": 583847046,"lower": 498103975,"count": 1504,"preSum": 13536 },{ "ndv": 1504,"upper": 674474279,"lower": 583847302,"count": 1504,"preSum": 15040 },{ "ndv": 1504,"upper": 748502309,"lower": 674476615,"count": 1504,"preSum": 16544 },{ "ndv": 1504,"upper": 868461027,"lower": 748504224,"count": 1504,"preSum": 18048 },{ "ndv": 1504,"upper": 961300195,"lower": 868461378,"count": 1504,"preSum": 19552 },{ "ndv": 1504,"upper": 1055652357,"lower": 961302917,"count": 1504,"preSum": 21056 },{ "ndv": 1504,"upper": 1172626147,"lower": 1055652613,"count": 1504,"preSum": 22560 },{ "ndv": 1504,"upper": 1250971906,"lower": 1172626241,"count": 1504,"preSum": 24064 },{ "ndv": 1504,"upper": 1357375940,"lower": 1250972163,"count": 1504,"preSum": 25568 },{ "ndv": 1504,"upper": 1435943074,"lower": 1357375942,"count": 1504,"preSum": 27072 },{ "ndv": 1504,"upper": 1513087590,"lower": 1435943330,"count": 1504,"preSum": 28576 },{ "ndv": 1504,"upper": 1621796387,"lower": 1513087814,"count": 1504,"preSum": 30080 },{ "ndv": 1504,"upper": 1715366982,"lower": 1621796900,"count": 1504,"preSum": 31584 },{ "ndv": 1504,"upper": 1795459168,"lower": 1715367014,"count": 1504,"preSum": 33088 },{ "ndv": 1504,"upper": 1904849830,"lower": 1795459494,"count": 1504,"preSum": 34592 },{ "ndv": 1504,"upper": 1998692576,"lower": 1904850855,"count": 1504,"preSum": 36096 },{ "ndv": 1504,"upper": 2071015873,"lower": 1998692577,"count": 1504,"preSum": 37600 },{ "ndv": 1504,"upper": 2178945218,"lower": 2071015874,"count": 1504,"preSum": 39104 },{ "ndv": 1504,"upper": 2249259109,"lower": 2178945219,"count": 1504,"preSum": 40608 },{ "ndv": 1504,"upper": 2350304227,"lower": 2249259168,"count": 1504,"preSum": 42112 },{ "ndv": 1504,"upper": 2456379457,"lower": 2350305796,"count": 1504,"preSum": 43616 },{ "ndv": 1504,"upper": 2544540929,"lower": 2456379489,"count": 1504,"preSum": 45120 },{ "ndv": 1504,"upper": 2679655941,"lower": 2544541955,"count": 1504,"preSum": 46624 },{ "ndv": 1504,"upper": 2796827619,"lower": 2679656261,"count": 1504,"preSum": 48128 },{ "ndv": 1504,"upper": 2900358660,"lower": 2796827652,"count": 1504,"preSum": 49632 },{ "ndv": 1504,"upper": 3014187362,"lower": 2900358978,"count": 1504,"preSum": 51136 },{ "ndv": 1504,"upper": 3103593120,"lower": 3014187430,"count": 1504,"preSum": 52640 },{ "ndv": 1504,"upper": 3199743780,"lower": 3103593509,"count": 1504,"preSum": 54144 },{ "ndv": 1504,"upper": 3296792196,"lower": 3199745284,"count": 1504,"preSum": 55648 },{ "ndv": 1504,"upper": 3383555142,"lower": 3297928836,"count": 1504,"preSum": 57152 },{ "ndv": 1504,"upper": 3481888836,"lower": 3383555174,"count": 1504,"preSum": 58656 },{ "ndv": 1504,"upper": 3556959587,"lower": 3481888868,"count": 1504,"preSum": 60160 },{ "ndv": 1504,"upper": 3626505636,"lower": 3556959591,"count": 1504,"preSum": 61664 },{ "ndv": 1504,"upper": 3750712580,"lower": 3626505859,"count": 1504,"preSum": 63168 },{ "ndv": 1504,"upper": 3876709125,"lower": 3750713184,"count": 1504,"preSum": 64672 },{ "ndv": 1504,"upper": 3955793351,"lower": 3876710401,"count": 1504,"preSum": 66176 },{ "ndv": 1504,"upper": 4054460103,"lower": 3955793383,"count": 1504,"preSum": 67680 },{ "ndv": 1504,"upper": 4137779811,"lower": 4054460135,"count": 1504,"preSum": 69184 },{ "ndv": 1504,"upper": 4260399814,"lower": 4137779911,"count": 1504,"preSum": 70688 },{ "ndv": 1504,"upper": 4361900229,"lower": 4260399844,"count": 1504,"preSum": 72192 },{ "ndv": 1504,"upper": 4469979938,"lower": 4361900261,"count": 1504,"preSum": 73696 },{ "ndv": 1504,"upper": 4591779047,"lower": 4469980038,"count": 1504,"preSum": 75200 },{ "ndv": 1504,"upper": 4691152262,"lower": 4591779139,"count": 1504,"preSum": 76704 },{ "ndv": 1504,"upper": 4781244001,"lower": 4691152708,"count": 1504,"preSum": 78208 },{ "ndv": 1504,"upper": 4878900736,"lower": 4786397414,"count": 1504,"preSum": 79712 },{ "ndv": 1504,"upper": 5007317316,"lower": 4878901254,"count": 1504,"preSum": 81216 },{ "ndv": 1504,"upper": 5146308995,"lower": 5007317348,"count": 1504,"preSum": 82720 },{ "ndv": 1504,"upper": 5280076678,"lower": 5146309124,"count": 1504,"preSum": 84224 },{ "ndv": 1504,"upper": 5361779876,"lower": 5280077184,"count": 1504,"preSum": 85728 },{ "ndv": 1504,"upper": 5520798085,"lower": 5361781286,"count": 1504,"preSum": 87232 },{ "ndv": 1504,"upper": 5599022950,"lower": 5520798114,"count": 1504,"preSum": 88736 },{ "ndv": 1504,"upper": 5686351239,"lower": 5599024037,"count": 1504,"preSum": 90240 },{ "ndv": 1504,"upper": 5781249249,"lower": 5686351940,"count": 1504,"preSum": 91744 },{ "ndv": 1504,"upper": 5900032513,"lower": 5781249250,"count": 1504,"preSum": 93248 },{ "ndv": 1450,"upper": 5989870052,"lower": 5900032775,"count": 1450,"preSum": 94752 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  orders.o_orderkey.null_count:
+    0
+  orders.o_orderkey.sample_rate:
+    5.793356E-5
+  orders.o_orderpriority.TOPN:
+    { "countArr": [ 19288,19063,19373,19393,19085 ],"valueArr": [ "1-URGENT","2-HIGH","3-MEDIUM","4-NOT SPECIFIED","5-LOW" ],"type": "String","sampleRate": 1.0 }
+  orders.o_orderpriority.cardinality:
+    5
+  orders.o_orderpriority.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  orders.o_orderpriority.null_count:
+    0
+  orders.o_orderpriority.sample_rate:
+    5.793356E-5
+  orders.o_orderstatus.TOPN:
+    { "countArr": [ 46813,46875,2514 ],"valueArr": [ "F","O","P" ],"type": "String","sampleRate": 1.0 }
+  orders.o_orderstatus.cardinality:
+    3
+  orders.o_orderstatus.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  orders.o_orderstatus.null_count:
+    0
+  orders.o_orderstatus.sample_rate:
+    5.793356E-5
+  orders.o_shippriority.TOPN:
+    { "countArr": [ 96202 ],"valueArr": [ 0 ],"type": "Int","sampleRate": 1.0 }
+  orders.o_shippriority.cardinality:
+    1
+  orders.o_shippriority.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  orders.o_shippriority.null_count:
+    0
+  orders.o_shippriority.sample_rate:
+    5.793356E-5
+  orders.o_totalprice.TOPN:
+    null
+  orders.o_totalprice.cardinality:
+    77765773
+  orders.o_totalprice.histogram:
+    { "buckets": [ { "ndv": 1501,"upper": 8593.09,"lower": 882.13,"count": 1504,"preSum": 0 },{ "ndv": 1502,"upper": 15315.35,"lower": 8593.28,"count": 1504,"preSum": 1504 },{ "ndv": 1502,"upper": 21131.84,"lower": 15315.63,"count": 1504,"preSum": 3008 },{ "ndv": 1501,"upper": 26949.70,"lower": 21133.76,"count": 1504,"preSum": 4512 },{ "ndv": 1502,"upper": 32115.72,"lower": 26951.97,"count": 1504,"preSum": 6016 },{ "ndv": 1501,"upper": 36746.75,"lower": 32116.32,"count": 1504,"preSum": 7520 },{ "ndv": 1501,"upper": 41319.51,"lower": 36748.75,"count": 1504,"preSum": 9024 },{ "ndv": 1500,"upper": 45649.01,"lower": 41320.40,"count": 1504,"preSum": 10528 },{ "ndv": 1503,"upper": 49901.18,"lower": 45650.29,"count": 1504,"preSum": 12032 },{ "ndv": 1502,"upper": 53895.40,"lower": 49907.65,"count": 1504,"preSum": 13536 },{ "ndv": 1499,"upper": 57704.74,"lower": 53900.80,"count": 1504,"preSum": 15040 },{ "ndv": 1502,"upper": 61509.23,"lower": 57705.19,"count": 1504,"preSum": 16544 },{ "ndv": 1496,"upper": 65517.14,"lower": 61511.17,"count": 1504,"preSum": 18048 },{ "ndv": 1502,"upper": 69504.43,"lower": 65519.49,"count": 1504,"preSum": 19552 },{ "ndv": 1500,"upper": 73464.42,"lower": 69505.29,"count": 1504,"preSum": 21056 },{ "ndv": 1502,"upper": 77411.90,"lower": 73466.16,"count": 1504,"preSum": 22560 },{ "ndv": 1502,"upper": 81292.04,"lower": 77412.24,"count": 1504,"preSum": 24064 },{ "ndv": 1500,"upper": 85377.94,"lower": 81294.37,"count": 1504,"preSum": 25568 },{ "ndv": 1500,"upper": 89533.01,"lower": 85378.07,"count": 1504,"preSum": 27072 },{ "ndv": 1501,"upper": 93695.12,"lower": 89535.64,"count": 1504,"preSum": 28576 },{ "ndv": 1504,"upper": 97897.48,"lower": 93703.29,"count": 1504,"preSum": 30080 },{ "ndv": 1500,"upper": 102116.80,"lower": 97905.44,"count": 1504,"preSum": 31584 },{ "ndv": 1502,"upper": 106540.48,"lower": 102118.07,"count": 1504,"preSum": 33088 },{ "ndv": 1500,"upper": 110829.29,"lower": 106541.55,"count": 1504,"preSum": 34592 },{ "ndv": 1502,"upper": 114923.81,"lower": 110829.99,"count": 1504,"preSum": 36096 },{ "ndv": 1504,"upper": 118862.76,"lower": 114925.62,"count": 1504,"preSum": 37600 },{ "ndv": 1501,"upper": 123097.80,"lower": 118864.47,"count": 1504,"preSum": 39104 },{ "ndv": 1502,"upper": 127313.69,"lower": 123097.87,"count": 1504,"preSum": 40608 },{ "ndv": 1500,"upper": 131568.07,"lower": 127319.67,"count": 1504,"preSum": 42112 },{ "ndv": 1502,"upper": 135734.74,"lower": 131573.13,"count": 1504,"preSum": 43616 },{ "ndv": 1500,"upper": 139838.45,"lower": 135735.32,"count": 1504,"preSum": 45120 },{ "ndv": 1500,"upper": 144028.95,"lower": 139841.53,"count": 1504,"preSum": 46624 },{ "ndv": 1504,"upper": 148308.27,"lower": 144030.51,"count": 1504,"preSum": 48128 },{ "ndv": 1500,"upper": 152486.46,"lower": 148311.06,"count": 1504,"preSum": 49632 },{ "ndv": 1501,"upper": 156699.08,"lower": 152486.52,"count": 1504,"preSum": 51136 },{ "ndv": 1501,"upper": 160798.70,"lower": 156699.21,"count": 1504,"preSum": 52640 },{ "ndv": 1501,"upper": 165184.20,"lower": 160798.90,"count": 1504,"preSum": 54144 },{ "ndv": 1501,"upper": 169513.30,"lower": 165184.69,"count": 1504,"preSum": 55648 },{ "ndv": 1501,"upper": 173808.69,"lower": 169514.42,"count": 1504,"preSum": 57152 },{ "ndv": 1499,"upper": 178047.48,"lower": 173810.07,"count": 1504,"preSum": 58656 },{ "ndv": 1502,"upper": 182353.60,"lower": 178048.52,"count": 1504,"preSum": 60160 },{ "ndv": 1502,"upper": 186688.86,"lower": 182356.22,"count": 1504,"preSum": 61664 },{ "ndv": 1501,"upper": 191218.10,"lower": 186689.13,"count": 1504,"preSum": 63168 },{ "ndv": 1502,"upper": 195850.60,"lower": 191219.02,"count": 1504,"preSum": 64672 },{ "ndv": 1501,"upper": 200425.84,"lower": 195855.22,"count": 1504,"preSum": 66176 },{ "ndv": 1503,"upper": 205030.87,"lower": 200430.01,"count": 1504,"preSum": 67680 },{ "ndv": 1504,"upper": 209756.52,"lower": 205035.97,"count": 1504,"preSum": 69184 },{ "ndv": 1503,"upper": 214811.49,"lower": 209760.78,"count": 1504,"preSum": 70688 },{ "ndv": 1502,"upper": 219967.82,"lower": 214813.51,"count": 1504,"preSum": 72192 },{ "ndv": 1503,"upper": 225378.09,"lower": 219975.85,"count": 1504,"preSum": 73696 },{ "ndv": 1501,"upper": 231005.37,"lower": 225378.85,"count": 1504,"preSum": 75200 },{ "ndv": 1503,"upper": 236567.26,"lower": 231010.12,"count": 1504,"preSum": 76704 },{ "ndv": 1503,"upper": 242178.11,"lower": 236569.72,"count": 1504,"preSum": 78208 },{ "ndv": 1503,"upper": 248062.77,"lower": 242189.65,"count": 1504,"preSum": 79712 },{ "ndv": 1503,"upper": 254907.70,"lower": 248063.66,"count": 1504,"preSum": 81216 },{ "ndv": 1501,"upper": 261604.78,"lower": 254908.44,"count": 1504,"preSum": 82720 },{ "ndv": 1502,"upper": 268989.05,"lower": 261609.61,"count": 1504,"preSum": 84224 },{ "ndv": 1502,"upper": 276800.33,"lower": 268990.32,"count": 1504,"preSum": 85728 },{ "ndv": 1503,"upper": 285860.47,"lower": 276801.40,"count": 1504,"preSum": 87232 },{ "ndv": 1504,"upper": 296464.63,"lower": 285873.49,"count": 1504,"preSum": 88736 },{ "ndv": 1503,"upper": 309092.49,"lower": 296464.92,"count": 1504,"preSum": 90240 },{ "ndv": 1504,"upper": 324325.67,"lower": 309106.48,"count": 1504,"preSum": 91744 },{ "ndv": 1504,"upper": 349317.41,"lower": 324327.55,"count": 1504,"preSum": 93248 },{ "ndv": 1449,"upper": 486405.93,"lower": 349321.17,"count": 1450,"preSum": 94752 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 1.0 }
+  orders.o_totalprice.null_count:
+    0
+  orders.o_totalprice.sample_rate:
+    5.793356E-5
+  part.p_brand.TOPN:
+    { "countArr": [ 3954,3936,3918,3883,3926,3941,3889,3857,3860,3964,3886,3883,3920,3967 ],"valueArr": [ "Brand#12","Brand#21","Brand#22","Brand#31","Brand#32","Brand#33","Brand#34","Brand#42","Brand#43","Brand#44","Brand#45","Brand#51","Brand#53","Brand#54" ],"type": "String","sampleRate": 1.0 }
+  part.p_brand.cardinality:
+    25
+  part.p_brand.histogram:
+    { "buckets": [ { "ndv": 1,"upper": "Brand#11","lower": "Brand#11","count": 3778,"preSum": 0 },{ "ndv": 1,"upper": "Brand#13","lower": "Brand#13","count": 3849,"preSum": 3778 },{ "ndv": 1,"upper": "Brand#14","lower": "Brand#14","count": 3838,"preSum": 7627 },{ "ndv": 1,"upper": "Brand#15","lower": "Brand#15","count": 3856,"preSum": 11465 },{ "ndv": 1,"upper": "Brand#23","lower": "Brand#23","count": 3718,"preSum": 15321 },{ "ndv": 1,"upper": "Brand#24","lower": "Brand#24","count": 3851,"preSum": 19039 },{ "ndv": 1,"upper": "Brand#25","lower": "Brand#25","count": 3842,"preSum": 22890 },{ "ndv": 1,"upper": "Brand#35","lower": "Brand#35","count": 3831,"preSum": 26732 },{ "ndv": 1,"upper": "Brand#41","lower": "Brand#41","count": 3805,"preSum": 30563 },{ "ndv": 1,"upper": "Brand#52","lower": "Brand#52","count": 3793,"preSum": 34368 },{ "ndv": 1,"upper": "Brand#55","lower": "Brand#55","count": 3827,"preSum": 38161 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  part.p_brand.null_count:
+    0
+  part.p_brand.sample_rate:
+    4.3894138E-4
+  part.p_comment.TOPN:
+    { "countArr": [ 36,48,34,35,37,34,34,37,37,39,36,35 ],"valueArr": [ " regula"," the ","arefu","caref","egula","eposit","final","ously","regul","regular","riously","uriou" ],"type": "String","sampleRate": 1.0 }
+  part.p_comment.cardinality:
+    5341315
+  part.p_comment.histogram:
+    { "buckets": [ { "ndv": 884,"upper": " asymptotes. ironic","lower": " abou","count": 1506,"preSum": 0 },{ "ndv": 886,"upper": " carefully d","lower": " asymptotes. permane","count": 1506,"preSum": 1506 },{ "ndv": 996,"upper": " excuses haggle. pend","lower": " carefully dogged ","count": 1506,"preSum": 3012 },{ "ndv": 867,"upper": " furiously reg","lower": " excuses impress reg","count": 1507,"preSum": 4518 },{ "ndv": 991,"upper": " of t","lower": " furiously regu","count": 1507,"preSum": 6025 },{ "ndv": 859,"upper": " regular ","lower": " of th","count": 1556,"preSum": 7532 },{ "ndv": 933,"upper": " slyly ironic hock","lower": " regular a","count": 1506,"preSum": 9088 },{ "ndv": 952,"upper": " theodolites. ir","lower": " slyly ironic i","count": 1506,"preSum": 10594 },{ "ndv": 1111,"upper": ". carefully express i","lower": " theodolites. ironi","count": 1506,"preSum": 12100 },{ "ndv": 1044,"upper": "above the slyly unusua","lower": ". carefully express pl","count": 1506,"preSum": 13606 },{ "ndv": 989,"upper": "ages snooze. slyly re","lower": "above the someti","count": 1506,"preSum": 15112 },{ "ndv": 1086,"upper": "al platelets.","lower": "ages solve pending req","count": 1506,"preSum": 16618 },{ "ndv": 1148,"upper": "are. unusual, ironi","lower": "al platelets. i","count": 1506,"preSum": 18124 },{ "ndv": 1147,"upper": "blith","lower": "are; carefully reg","count": 1517,"preSum": 19630 },{ "ndv": 1090,"upper": "cajole quickly accord","lower": "blithe","count": 1506,"preSum": 21147 },{ "ndv": 971,"upper": "ckages alongsid","lower": "cajole quickly across ","count": 1506,"preSum": 22653 },{ "ndv": 1134,"upper": "cuses after th","lower": "ckages among ","count": 1506,"preSum": 24159 },{ "ndv": 1141,"upper": "ding to t","lower": "cuses after the ","count": 1514,"preSum": 25665 },{ "ndv": 1028,"upper": "e furiously pendi","lower": "ding to th","count": 1506,"preSum": 27179 },{ "ndv": 1235,"upper": "ecial accoun","lower": "e furiously pending ","count": 1507,"preSum": 28685 },{ "ndv": 1013,"upper": "egular, ironic waters","lower": "ecial account","count": 1506,"preSum": 30192 },{ "ndv": 1195,"upper": "eodolites against ","lower": "egular, pend","count": 1506,"preSum": 31698 },{ "ndv": 1133,"upper": "es are slyly","lower": "eodolites among the ","count": 1507,"preSum": 33204 },{ "ndv": 1211,"upper": "ests. qui","lower": "es are slyly accor","count": 1507,"preSum": 34711 },{ "ndv": 1164,"upper": "final accounts","lower": "ests. quickly ","count": 1507,"preSum": 36218 },{ "ndv": 1051,"upper": "furious","lower": "final accounts acc","count": 1519,"preSum": 37725 },{ "ndv": 1141,"upper": "ges. qu","lower": "furious dep","count": 1506,"preSum": 39244 },{ "ndv": 1118,"upper": "he blithely ironic ","lower": "ges. quickly","count": 1507,"preSum": 40750 },{ "ndv": 1081,"upper": "hinly regular gift","lower": "he blithely ironic re","count": 1506,"preSum": 42257 },{ "ndv": 1249,"upper": "iet foxes r","lower": "hinly regular p","count": 1506,"preSum": 43763 },{ "ndv": 1142,"upper": "instruction","lower": "iet instr","count": 1506,"preSum": 45269 },{ "ndv": 982,"upper": "ironic, bold accounts ","lower": "instructions ","count": 1506,"preSum": 46775 },{ "ndv": 1186,"upper": "kages wake dur","lower": "ironic, bold packag","count": 1506,"preSum": 48281 },{ "ndv": 1140,"upper": "l, ironic dependen","lower": "kages wake foxes. r","count": 1506,"preSum": 49787 },{ "ndv": 1173,"upper": "leep?","lower": "l, ironic depo","count": 1506,"preSum": 51293 },{ "ndv": 1145,"upper": "longs","lower": "leep? carefully iron","count": 1508,"preSum": 52799 },{ "ndv": 982,"upper": "ly final asymptotes","lower": "longsi","count": 1506,"preSum": 54307 },{ "ndv": 869,"upper": "ly. blithely regular ","lower": "ly final asymptotes.","count": 1507,"preSum": 55813 },{ "ndv": 1189,"upper": "nal accounts.","lower": "ly. blithely regular p","count": 1506,"preSum": 57320 },{ "ndv": 1152,"upper": "nic a","lower": "nal accounts. bold, i","count": 1508,"preSum": 58826 },{ "ndv": 1156,"upper": "nto beans detect","lower": "nic ac","count": 1506,"preSum": 60334 },{ "ndv": 1197,"upper": "old, exp","lower": "nto beans h","count": 1506,"preSum": 61840 },{ "ndv": 1130,"upper": "ording to","lower": "old, expre","count": 1513,"preSum": 63346 },{ "ndv": 1160,"upper": "ously final dec","lower": "ording to t","count": 1506,"preSum": 64859 },{ "ndv": 1136,"upper": "pecial instructions","lower": "ously final dep","count": 1506,"preSum": 66365 },{ "ndv": 1048,"upper": "quest","lower": "pecial instructions no","count": 1507,"preSum": 67871 },{ "ndv": 1158,"upper": "rbits sle","lower": "quests","count": 1506,"preSum": 69378 },{ "ndv": 849,"upper": "requests detect","lower": "rbits. carefu","count": 1506,"preSum": 70884 },{ "ndv": 1067,"upper": "ronic, sile","lower": "requests detect. iron","count": 1506,"preSum": 72390 },{ "ndv": 1091,"upper": "s eat furiously","lower": "ronic, special depe","count": 1506,"preSum": 73896 },{ "ndv": 1149,"upper": "s. blithely regular r","lower": "s eat idly final de","count": 1506,"preSum": 75402 },{ "ndv": 1120,"upper": "sits affix ","lower": "s. blithely spec","count": 1506,"preSum": 76908 },{ "ndv": 1132,"upper": "slyly throughout the ","lower": "sits affix closely fin","count": 1506,"preSum": 78414 },{ "ndv": 1170,"upper": "sual p","lower": "slyly unu","count": 1506,"preSum": 79920 },{ "ndv": 1250,"upper": "the bold","lower": "sual pa","count": 1508,"preSum": 81426 },{ "ndv": 1006,"upper": "timen","lower": "the bold ac","count": 1506,"preSum": 82934 },{ "ndv": 1129,"upper": "ts sleep fur","lower": "timents","count": 1506,"preSum": 84440 },{ "ndv": 1195,"upper": "uffil","lower": "ts sleep furious","count": 1511,"preSum": 85946 },{ "ndv": 1082,"upper": "ully r","lower": "uffily ","count": 1506,"preSum": 87457 },{ "ndv": 1079,"upper": "use. carefully daring ","lower": "ully re","count": 1506,"preSum": 88963 },{ "ndv": 1161,"upper": "ven, e","lower": "use. carefully expr","count": 1506,"preSum": 90469 },{ "ndv": 1185,"upper": "y carefull","lower": "ven, ev","count": 1509,"preSum": 91975 },{ "ndv": 917,"upper": "y requests. quickly ","lower": "y carefully ","count": 1506,"preSum": 93484 },{ "ndv": 1022,"upper": "zzle. sl","lower": "y requests? furiou","count": 1340,"preSum": 94990 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  part.p_comment.null_count:
+    0
+  part.p_comment.sample_rate:
+    4.3894138E-4
+  part.p_container.TOPN:
+    { "countArr": [ 2479,2466,2443,2483,2471,2449,2440,2464,2440,2483,2488,2472,2469,2450 ],"valueArr": [ "JUMBO BOX","JUMBO CAN","JUMBO CASE","JUMBO DRUM","JUMBO JAR","LG BAG","LG JAR","LG PKG","MED CASE","MED PKG","SM BAG","SM CAN","SM CASE","WRAP PACK" ],"type": "String","sampleRate": 1.0 }
+  part.p_container.cardinality:
+    40
+  part.p_container.histogram:
+    { "buckets": [ { "ndv": 1,"upper": "JUMBO BAG","lower": "JUMBO BAG","count": 2437,"preSum": 0 },{ "ndv": 1,"upper": "JUMBO PACK","lower": "JUMBO PACK","count": 2380,"preSum": 2437 },{ "ndv": 1,"upper": "JUMBO PKG","lower": "JUMBO PKG","count": 2342,"preSum": 4817 },{ "ndv": 1,"upper": "LG BOX","lower": "LG BOX","count": 2386,"preSum": 7159 },{ "ndv": 1,"upper": "LG CAN","lower": "LG CAN","count": 2358,"preSum": 9545 },{ "ndv": 1,"upper": "LG CASE","lower": "LG CASE","count": 2366,"preSum": 11903 },{ "ndv": 1,"upper": "LG DRUM","lower": "LG DRUM","count": 2415,"preSum": 14269 },{ "ndv": 1,"upper": "LG PACK","lower": "LG PACK","count": 2378,"preSum": 16684 },{ "ndv": 1,"upper": "MED BAG","lower": "MED BAG","count": 2436,"preSum": 19062 },{ "ndv": 1,"upper": "MED BOX","lower": "MED BOX","count": 2396,"preSum": 21498 },{ "ndv": 1,"upper": "MED CAN","lower": "MED CAN","count": 2406,"preSum": 23894 },{ "ndv": 1,"upper": "MED DRUM","lower": "MED DRUM","count": 2397,"preSum": 26300 },{ "ndv": 1,"upper": "MED JAR","lower": "MED JAR","count": 2398,"preSum": 28697 },{ "ndv": 1,"upper": "MED PACK","lower": "MED PACK","count": 2399,"preSum": 31095 },{ "ndv": 1,"upper": "SM BOX","lower": "SM BOX","count": 2379,"preSum": 33494 },{ "ndv": 1,"upper": "SM DRUM","lower": "SM DRUM","count": 2386,"preSum": 35873 },{ "ndv": 1,"upper": "SM JAR","lower": "SM JAR","count": 2391,"preSum": 38259 },{ "ndv": 1,"upper": "SM PACK","lower": "SM PACK","count": 2434,"preSum": 40650 },{ "ndv": 1,"upper": "SM PKG","lower": "SM PKG","count": 2402,"preSum": 43084 },{ "ndv": 1,"upper": "WRAP BAG","lower": "WRAP BAG","count": 2405,"preSum": 45486 },{ "ndv": 1,"upper": "WRAP BOX","lower": "WRAP BOX","count": 2388,"preSum": 47891 },{ "ndv": 1,"upper": "WRAP CAN","lower": "WRAP CAN","count": 2389,"preSum": 50279 },{ "ndv": 1,"upper": "WRAP CASE","lower": "WRAP CASE","count": 2401,"preSum": 52668 },{ "ndv": 1,"upper": "WRAP DRUM","lower": "WRAP DRUM","count": 2420,"preSum": 55069 },{ "ndv": 1,"upper": "WRAP JAR","lower": "WRAP JAR","count": 2412,"preSum": 57489 },{ "ndv": 1,"upper": "WRAP PKG","lower": "WRAP PKG","count": 2374,"preSum": 59901 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  part.p_container.null_count:
+    0
+  part.p_container.sample_rate:
+    4.3894138E-4
+  part.p_mfgr.TOPN:
+    { "countArr": [ 19275,19265,19470,19372,19390 ],"valueArr": [ "Manufacturer#1","Manufacturer#2","Manufacturer#3","Manufacturer#4","Manufacturer#5" ],"type": "String","sampleRate": 1.0 }
+  part.p_mfgr.cardinality:
+    5
+  part.p_mfgr.histogram:
+    { "buckets": [ ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  part.p_mfgr.null_count:
+    0
+  part.p_mfgr.sample_rate:
+    4.3894138E-4
+  part.p_name.TOPN:
+    null
+  part.p_name.cardinality:
+    29788569
+  part.p_name.histogram:
+    { "buckets": [ { "ndv": 1513,"upper": "antique light dodger khaki tomato","lower": "almond antique bisque frosted navy","count": 1513,"preSum": 0 },{ "ndv": 1513,"upper": "aquamarine sky tan hot slate","lower": "antique light floral peach midnight","count": 1513,"preSum": 1513 },{ "ndv": 1513,"upper": "beige ghost peru blanched steel","lower": "aquamarine slate bisque cyan rose","count": 1513,"preSum": 3026 },{ "ndv": 1513,"upper": "bisque rose peach yellow tan","lower": "beige ghost spring lavender coral","count": 1513,"preSum": 4539 },{ "ndv": 1513,"upper": "blanched dark medium tomato azure","lower": "bisque rose sienna forest indian","count": 1513,"preSum": 6052 },{ "ndv": 1513,"upper": "blue moccasin smoke pale royal","lower": "blanched dark orange bisque blush","count": 1513,"preSum": 7565 },{ "ndv": 1513,"upper": "blush yellow orange rosy almond","lower": "blue navajo dim burlywood khaki","count": 1513,"preSum": 9078 },{ "ndv": 1513,"upper": "burlywood honeydew powder smoke lawn","lower": "blush yellow red dodger navy","count": 1513,"preSum": 10591 },{ "ndv": 1513,"upper": "burnished sky aquamarine peach wheat","lower": "burlywood honeydew puff cream floral","count": 1513,"preSum": 12104 },{ "ndv": 1513,"upper": "chiffon dim ghost lime medium","lower": "burnished sky cyan royal bisque","count": 1513,"preSum": 13617 },{ "ndv": 1513,"upper": "chocolate pale frosted lavender saddle","lower": "chiffon dim grey cornsilk seashell","count": 1513,"preSum": 15130 },{ "ndv": 1513,"upper": "cornflower blue antique purple ivory","lower": "chocolate pale hot royal khaki","count": 1513,"preSum": 16643 },{ "ndv": 1513,"upper": "cornsilk midnight black maroon forest","lower": "cornflower blue black magenta grey","count": 1513,"preSum": 18156 },{ "ndv": 1513,"upper": "cyan antique blush dodger thistle","lower": "cornsilk midnight burnished pale turquoise","count": 1513,"preSum": 19669 },{ "ndv": 1513,"upper": "dark ivory royal midnight honeydew","lower": "cyan antique blush olive snow","count": 1513,"preSum": 21182 },{ "ndv": 1513,"upper": "deep tomato midnight steel antique","lower": "dark ivory smoke linen orange","count": 1513,"preSum": 22695 },{ "ndv": 1513,"upper": "dodger gainsboro olive azure aquamarine","lower": "deep tomato navajo tan lemon","count": 1513,"preSum": 24208 },{ "ndv": 1513,"upper": "drab salmon frosted maroon smoke","lower": "dodger gainsboro olive tan orchid","count": 1513,"preSum": 25721 },{ "ndv": 1513,"upper": "floral coral salmon olive wheat","lower": "drab salmon grey medium navajo","count": 1513,"preSum": 27234 },{ "ndv": 1513,"upper": "forest papaya goldenrod almond cornflower","lower": "floral coral sandy rose mint","count": 1513,"preSum": 28747 },{ "ndv": 1513,"upper": "gainsboro bisque green navy snow","lower": "forest papaya grey azure mint","count": 1513,"preSum": 30260 },{ "ndv": 1513,"upper": "ghost lime medium antique papaya","lower": "gainsboro bisque khaki magenta maroon","count": 1513,"preSum": 31773 },{ "ndv": 1513,"upper": "goldenrod thistle peach deep salmon","lower": "ghost lime midnight tan violet","count": 1513,"preSum": 33286 },{ "ndv": 1513,"upper": "grey ivory firebrick blanched orange","lower": "goldenrod thistle peach moccasin burnished","count": 1513,"preSum": 34799 },{ "ndv": 1513,"upper": "honeydew slate puff gainsboro beige","lower": "grey ivory firebrick chiffon khaki","count": 1513,"preSum": 36312 },{ "ndv": 1513,"upper": "indian ghost chartreuse burlywood green","lower": "honeydew slate saddle yellow forest","count": 1513,"preSum": 37825 },{ "ndv": 1513,"upper": "ivory saddle orchid rose lace","lower": "indian ghost chiffon powder grey","count": 1513,"preSum": 39338 },{ "ndv": 1513,"upper": "lace dodger navajo lavender violet","lower": "ivory saddle slate floral purple","count": 1513,"preSum": 40851 },{ "ndv": 1513,"upper": "lavender peru coral tan maroon","lower": "lace dodger puff slate white","count": 1513,"preSum": 42364 },{ "ndv": 1513,"upper": "lemon coral bisque chiffon rose","lower": "lavender peru cornsilk dim rosy","count": 1513,"preSum": 43877 },{ "ndv": 1513,"upper": "light papaya almond misty blue","lower": "lemon coral chartreuse orange slate","count": 1513,"preSum": 45390 },{ "ndv": 1513,"upper": "linen burlywood tomato peach forest","lower": "light papaya azure burnished misty","count": 1513,"preSum": 46903 },{ "ndv": 1513,"upper": "magenta misty lawn salmon navajo","lower": "linen burlywood white salmon chartreuse","count": 1513,"preSum": 48416 },{ "ndv": 1513,"upper": "maroon wheat smoke honeydew navy","lower": "magenta misty mint aquamarine cream","count": 1513,"preSum": 49929 },{ "ndv": 1513,"upper": "metallic ivory dark deep papaya","lower": "maroon white antique black slate","count": 1513,"preSum": 51442 },{ "ndv": 1513,"upper": "midnight slate royal navy ivory","lower": "metallic ivory floral cornsilk burnished","count": 1513,"preSum": 52955 },{ "ndv": 1513,"upper": "misty gainsboro sky honeydew plum","lower": "midnight slate salmon goldenrod antique","count": 1513,"preSum": 54468 },{ "ndv": 1513,"upper": "moccasin powder honeydew snow burlywood","lower": "misty gainsboro sky turquoise forest","count": 1513,"preSum": 55981 },{ "ndv": 1513,"upper": "navy azure white violet maroon","lower": "moccasin powder light blush navajo","count": 1513,"preSum": 57494 },{ "ndv": 1513,"upper": "olive light deep brown medium","lower": "navy beige aquamarine tan rosy","count": 1513,"preSum": 59007 },{ "ndv": 1513,"upper": "orange steel brown khaki lace","lower": "olive light dim violet maroon","count": 1513,"preSum": 60520 },{ "ndv": 1513,"upper": "pale green aquamarine misty salmon","lower": "orange steel chocolate violet rosy","count": 1513,"preSum": 62033 },{ "ndv": 1513,"upper": "papaya rose medium blanched chiffon","lower": "pale green aquamarine white linen","count": 1513,"preSum": 63546 },{ "ndv": 1513,"upper": "peru dark turquoise misty orange","lower": "papaya rose orchid burlywood antique","count": 1513,"preSum": 65059 },{ "ndv": 1513,"upper": "pink papaya turquoise indian grey","lower": "peru dark turquoise pink medium","count": 1513,"preSum": 66572 },{ "ndv": 1513,"upper": "powder coral chiffon linen smoke","lower": "pink peach blanched chartreuse cornsilk","count": 1513,"preSum": 68085 },{ "ndv": 1513,"upper": "puff olive papaya lavender spring","lower": "powder coral hot cornsilk dodger","count": 1513,"preSum": 69598 },{ "ndv": 1513,"upper": "red azure lemon dark sandy","lower": "puff olive peach cornflower navajo","count": 1513,"preSum": 71111 },{ "ndv": 1513,"upper": "rose lemon sky beige aquamarine","lower": "red azure mint thistle black","count": 1513,"preSum": 72624 },{ "ndv": 1513,"upper": "rosy tan puff floral pale","lower": "rose lemon turquoise hot bisque","count": 1513,"preSum": 74137 },{ "ndv": 1513,"upper": "saddle khaki medium purple linen","lower": "rosy tan puff green bisque","count": 1513,"preSum": 75650 },{ "ndv": 1513,"upper": "salmon slate violet steel spring","lower": "saddle khaki peach chartreuse light","count": 1513,"preSum": 77163 },{ "ndv": 1513,"upper": "seashell drab antique pale hot","lower": "salmon slate yellow blue snow","count": 1513,"preSum": 78676 },{ "ndv": 1513,"upper": "sienna pink saddle seashell purple","lower": "seashell drab deep moccasin gainsboro","count": 1513,"preSum": 80189 },{ "ndv": 1513,"upper": "slate chiffon lime saddle white","lower": "sienna pink snow midnight frosted","count": 1513,"preSum": 81702 },{ "ndv": 1513,"upper": "smoke navy misty burlywood peach","lower": "slate chiffon metallic sandy lavender","count": 1513,"preSum": 83215 },{ "ndv": 1513,"upper": "spring brown orange tan cyan","lower": "smoke navy misty navajo azure","count": 1513,"preSum": 84728 },{ "ndv": 1513,"upper": "steel metallic khaki lavender orchid","lower": "spring brown orchid lemon dark","count": 1513,"preSum": 86241 },{ "ndv": 1513,"upper": "tan white smoke green misty","lower": "steel metallic navajo sky chartreuse","count": 1513,"preSum": 87754 },{ "ndv": 1513,"upper": "tomato ivory forest lavender plum","lower": "tan white tomato magenta hot","count": 1513,"preSum": 89267 },{ "ndv": 1513,"upper": "turquoise sienna indian blue orange","lower": "tomato ivory gainsboro hot puff","count": 1513,"preSum": 90780 },{ "ndv": 1513,"upper": "wheat cornsilk royal lime lawn","lower": "turquoise sienna light purple cream","count": 1513,"preSum": 92293 },{ "ndv": 1513,"upper": "white papaya dodger indian peru","lower": "wheat cornsilk tan burlywood misty","count": 1513,"preSum": 93806 },{ "ndv": 1453,"upper": "yellow white wheat midnight turquoise","lower": "white papaya lavender coral smoke","count": 1453,"preSum": 95319 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  part.p_name.null_count:
+    0
+  part.p_name.sample_rate:
+    4.3894138E-4
+  part.p_partkey.TOPN:
+    null
+  part.p_partkey.cardinality:
+    29294026
+  part.p_partkey.histogram:
+    { "buckets": [ { "ndv": 1513,"upper": 1590,"lower": 1,"count": 1513,"preSum": 0 },{ "ndv": 1513,"upper": 3333,"lower": 1591,"count": 1513,"preSum": 1513 },{ "ndv": 1513,"upper": 5433,"lower": 3334,"count": 1513,"preSum": 3026 },{ "ndv": 1513,"upper": 8972,"lower": 5434,"count": 1513,"preSum": 4539 },{ "ndv": 1513,"upper": 711375,"lower": 8973,"count": 1513,"preSum": 6052 },{ "ndv": 1513,"upper": 5993636,"lower": 711404,"count": 1513,"preSum": 7565 },{ "ndv": 1513,"upper": 10588743,"lower": 5993735,"count": 1513,"preSum": 9078 },{ "ndv": 1513,"upper": 14591246,"lower": 10588775,"count": 1513,"preSum": 10591 },{ "ndv": 1513,"upper": 17498286,"lower": 14591260,"count": 1513,"preSum": 12104 },{ "ndv": 1513,"upper": 21229908,"lower": 17498458,"count": 1513,"preSum": 13617 },{ "ndv": 1513,"upper": 25424799,"lower": 21229940,"count": 1513,"preSum": 15130 },{ "ndv": 1513,"upper": 28973403,"lower": 25424898,"count": 1513,"preSum": 16643 },{ "ndv": 1513,"upper": 31605350,"lower": 28973509,"count": 1513,"preSum": 18156 },{ "ndv": 1513,"upper": 36607787,"lower": 31605393,"count": 1513,"preSum": 19669 },{ "ndv": 1513,"upper": 38925493,"lower": 36607832,"count": 1513,"preSum": 21182 },{ "ndv": 1513,"upper": 43380518,"lower": 38925749,"count": 1513,"preSum": 22695 },{ "ndv": 1513,"upper": 45890797,"lower": 43380671,"count": 1513,"preSum": 24208 },{ "ndv": 1513,"upper": 49459069,"lower": 45890798,"count": 1513,"preSum": 25721 },{ "ndv": 1513,"upper": 52330138,"lower": 49459344,"count": 1513,"preSum": 27234 },{ "ndv": 1513,"upper": 56141672,"lower": 52330144,"count": 1513,"preSum": 28747 },{ "ndv": 1513,"upper": 59564704,"lower": 56141890,"count": 1513,"preSum": 30260 },{ "ndv": 1513,"upper": 61729521,"lower": 59564809,"count": 1513,"preSum": 31773 },{ "ndv": 1513,"upper": 64809215,"lower": 61729598,"count": 1513,"preSum": 33286 },{ "ndv": 1513,"upper": 68389733,"lower": 64809344,"count": 1513,"preSum": 34799 },{ "ndv": 1513,"upper": 70942429,"lower": 68389751,"count": 1513,"preSum": 36312 },{ "ndv": 1513,"upper": 73755593,"lower": 70942460,"count": 1513,"preSum": 37825 },{ "ndv": 1513,"upper": 76043364,"lower": 73755594,"count": 1513,"preSum": 39338 },{ "ndv": 1513,"upper": 78684387,"lower": 76043472,"count": 1513,"preSum": 40851 },{ "ndv": 1513,"upper": 82141575,"lower": 78684495,"count": 1513,"preSum": 42364 },{ "ndv": 1513,"upper": 84390693,"lower": 82141755,"count": 1513,"preSum": 43877 },{ "ndv": 1513,"upper": 87472774,"lower": 84391216,"count": 1513,"preSum": 45390 },{ "ndv": 1513,"upper": 90995596,"lower": 87473165,"count": 1513,"preSum": 46903 },{ "ndv": 1513,"upper": 94281411,"lower": 90995637,"count": 1513,"preSum": 48416 },{ "ndv": 1513,"upper": 98231968,"lower": 94281440,"count": 1513,"preSum": 49929 },{ "ndv": 1513,"upper": 101991788,"lower": 98232385,"count": 1513,"preSum": 51442 },{ "ndv": 1513,"upper": 105968526,"lower": 101991840,"count": 1513,"preSum": 52955 },{ "ndv": 1513,"upper": 109351079,"lower": 105968782,"count": 1513,"preSum": 54468 },{ "ndv": 1513,"upper": 111992860,"lower": 109351311,"count": 1513,"preSum": 55981 },{ "ndv": 1513,"upper": 115650942,"lower": 111993004,"count": 1513,"preSum": 57494 },{ "ndv": 1513,"upper": 120072787,"lower": 115651124,"count": 1513,"preSum": 59007 },{ "ndv": 1513,"upper": 123348126,"lower": 120072819,"count": 1513,"preSum": 60520 },{ "ndv": 1513,"upper": 127803085,"lower": 123348654,"count": 1513,"preSum": 62033 },{ "ndv": 1513,"upper": 131120452,"lower": 127803086,"count": 1513,"preSum": 63546 },{ "ndv": 1513,"upper": 133457254,"lower": 131120459,"count": 1513,"preSum": 65059 },{ "ndv": 1513,"upper": 136827970,"lower": 133457285,"count": 1513,"preSum": 66572 },{ "ndv": 1513,"upper": 140473655,"lower": 136828002,"count": 1513,"preSum": 68085 },{ "ndv": 1513,"upper": 144291343,"lower": 140474389,"count": 1513,"preSum": 69598 },{ "ndv": 1513,"upper": 148054514,"lower": 144291462,"count": 1513,"preSum": 71111 },{ "ndv": 1513,"upper": 151025718,"lower": 148054515,"count": 1513,"preSum": 72624 },{ "ndv": 1513,"upper": 154657232,"lower": 151025935,"count": 1513,"preSum": 74137 },{ "ndv": 1513,"upper": 158223434,"lower": 154657264,"count": 1513,"preSum": 75650 },{ "ndv": 1513,"upper": 161992115,"lower": 158223442,"count": 1513,"preSum": 77163 },{ "ndv": 1513,"upper": 165317103,"lower": 161992200,"count": 1513,"preSum": 78676 },{ "ndv": 1513,"upper": 169622744,"lower": 165317206,"count": 1513,"preSum": 80189 },{ "ndv": 1513,"upper": 173100131,"lower": 169622752,"count": 1513,"preSum": 81702 },{ "ndv": 1513,"upper": 175197259,"lower": 173100139,"count": 1513,"preSum": 83215 },{ "ndv": 1513,"upper": 177888222,"lower": 175197283,"count": 1513,"preSum": 84728 },{ "ndv": 1513,"upper": 181878475,"lower": 177888254,"count": 1513,"preSum": 86241 },{ "ndv": 1513,"upper": 185382292,"lower": 181878486,"count": 1513,"preSum": 87754 },{ "ndv": 1513,"upper": 188180102,"lower": 185382474,"count": 1513,"preSum": 89267 },{ "ndv": 1513,"upper": 191513423,"lower": 188180411,"count": 1513,"preSum": 90780 },{ "ndv": 1513,"upper": 194400274,"lower": 191513451,"count": 1513,"preSum": 92293 },{ "ndv": 1513,"upper": 197675368,"lower": 194400382,"count": 1513,"preSum": 93806 },{ "ndv": 1453,"upper": 199800235,"lower": 197675403,"count": 1453,"preSum": 95319 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  part.p_partkey.null_count:
+    0
+  part.p_partkey.sample_rate:
+    4.3894138E-4
+  part.p_retailprice.TOPN:
+    { "countArr": [ 11,11,11,11,11,11,11,12,11 ],"valueArr": [ 1100.19,1118.21,1178.27,1187.28,1438.53,1480.57,1529.62,1568.66,1698.79 ],"type": "Double","sampleRate": 1.0 }
+  part.p_retailprice.cardinality:
+    2680705
+  part.p_retailprice.histogram:
+    { "buckets": [ { "ndv": 1017,"upper": 969.48,"lower": 900.43,"count": 1511,"preSum": 0 },{ "ndv": 1085,"upper": 1003.85,"lower": 969.50,"count": 1511,"preSum": 1511 },{ "ndv": 1069,"upper": 1030.30,"lower": 1003.87,"count": 1512,"preSum": 3022 },{ "ndv": 1027,"upper": 1052.19,"lower": 1030.31,"count": 1514,"preSum": 4534 },{ "ndv": 959,"upper": 1071.17,"lower": 1052.20,"count": 1514,"preSum": 6048 },{ "ndv": 968,"upper": 1088.31,"lower": 1071.19,"count": 1511,"preSum": 7562 },{ "ndv": 920,"upper": 1103.48,"lower": 1088.32,"count": 1511,"preSum": 9073 },{ "ndv": 918,"upper": 1118.64,"lower": 1103.52,"count": 1511,"preSum": 10584 },{ "ndv": 921,"upper": 1134.35,"lower": 1118.67,"count": 1511,"preSum": 12095 },{ "ndv": 919,"upper": 1149.89,"lower": 1134.36,"count": 1511,"preSum": 13606 },{ "ndv": 898,"upper": 1164.92,"lower": 1149.90,"count": 1511,"preSum": 15117 },{ "ndv": 934,"upper": 1180.69,"lower": 1164.93,"count": 1512,"preSum": 16628 },{ "ndv": 896,"upper": 1195.61,"lower": 1180.70,"count": 1511,"preSum": 18140 },{ "ndv": 938,"upper": 1211.85,"lower": 1195.63,"count": 1511,"preSum": 19651 },{ "ndv": 947,"upper": 1227.56,"lower": 1211.86,"count": 1511,"preSum": 21162 },{ "ndv": 916,"upper": 1243.33,"lower": 1227.57,"count": 1515,"preSum": 22673 },{ "ndv": 922,"upper": 1259.02,"lower": 1243.34,"count": 1511,"preSum": 24188 },{ "ndv": 920,"upper": 1274.77,"lower": 1259.05,"count": 1512,"preSum": 25699 },{ "ndv": 953,"upper": 1290.74,"lower": 1274.78,"count": 1511,"preSum": 27211 },{ "ndv": 931,"upper": 1306.28,"lower": 1290.77,"count": 1511,"preSum": 28722 },{ "ndv": 949,"upper": 1322.21,"lower": 1306.29,"count": 1512,"preSum": 30233 },{ "ndv": 933,"upper": 1337.68,"lower": 1322.23,"count": 1511,"preSum": 31745 },{ "ndv": 960,"upper": 1354.08,"lower": 1337.70,"count": 1511,"preSum": 33256 },{ "ndv": 915,"upper": 1369.88,"lower": 1354.09,"count": 1511,"preSum": 34767 },{ "ndv": 927,"upper": 1385.89,"lower": 1369.89,"count": 1511,"preSum": 36278 },{ "ndv": 931,"upper": 1401.18,"lower": 1385.91,"count": 1511,"preSum": 37789 },{ "ndv": 929,"upper": 1416.94,"lower": 1401.19,"count": 1513,"preSum": 39300 },{ "ndv": 952,"upper": 1432.87,"lower": 1416.95,"count": 1511,"preSum": 40813 },{ "ndv": 937,"upper": 1448.48,"lower": 1432.89,"count": 1511,"preSum": 42324 },{ "ndv": 927,"upper": 1463.87,"lower": 1448.52,"count": 1512,"preSum": 43835 },{ "ndv": 935,"upper": 1479.62,"lower": 1463.88,"count": 1512,"preSum": 45347 },{ "ndv": 960,"upper": 1496.07,"lower": 1479.63,"count": 1511,"preSum": 46859 },{ "ndv": 945,"upper": 1511.92,"lower": 1496.08,"count": 1511,"preSum": 48370 },{ "ndv": 914,"upper": 1527.75,"lower": 1511.95,"count": 1511,"preSum": 49881 },{ "ndv": 940,"upper": 1543.34,"lower": 1527.76,"count": 1513,"preSum": 51392 },{ "ndv": 915,"upper": 1558.36,"lower": 1543.38,"count": 1511,"preSum": 52905 },{ "ndv": 960,"upper": 1574.34,"lower": 1558.37,"count": 1515,"preSum": 54416 },{ "ndv": 917,"upper": 1589.53,"lower": 1574.39,"count": 1512,"preSum": 55931 },{ "ndv": 910,"upper": 1604.90,"lower": 1589.54,"count": 1511,"preSum": 57443 },{ "ndv": 932,"upper": 1620.76,"lower": 1604.91,"count": 1511,"preSum": 58954 },{ "ndv": 926,"upper": 1636.32,"lower": 1620.78,"count": 1511,"preSum": 60465 },{ "ndv": 922,"upper": 1651.92,"lower": 1636.38,"count": 1511,"preSum": 61976 },{ "ndv": 934,"upper": 1666.76,"lower": 1651.94,"count": 1511,"preSum": 63487 },{ "ndv": 931,"upper": 1682.43,"lower": 1666.78,"count": 1512,"preSum": 64998 },{ "ndv": 952,"upper": 1698.06,"lower": 1682.44,"count": 1511,"preSum": 66510 },{ "ndv": 912,"upper": 1713.56,"lower": 1698.07,"count": 1511,"preSum": 68021 },{ "ndv": 952,"upper": 1729.46,"lower": 1713.57,"count": 1515,"preSum": 69532 },{ "ndv": 939,"upper": 1745.45,"lower": 1729.47,"count": 1511,"preSum": 71047 },{ "ndv": 928,"upper": 1761.10,"lower": 1745.46,"count": 1511,"preSum": 72558 },{ "ndv": 941,"upper": 1776.74,"lower": 1761.11,"count": 1511,"preSum": 74069 },{ "ndv": 900,"upper": 1791.85,"lower": 1776.75,"count": 1511,"preSum": 75580 },{ "ndv": 931,"upper": 1807.39,"lower": 1791.86,"count": 1511,"preSum": 77091 },{ "ndv": 940,"upper": 1823.20,"lower": 1807.40,"count": 1512,"preSum": 78602 },{ "ndv": 898,"upper": 1837.96,"lower": 1823.21,"count": 1511,"preSum": 80114 },{ "ndv": 927,"upper": 1853.31,"lower": 1837.98,"count": 1513,"preSum": 81625 },{ "ndv": 928,"upper": 1868.23,"lower": 1853.32,"count": 1511,"preSum": 83138 },{ "ndv": 950,"upper": 1884.15,"lower": 1868.24,"count": 1511,"preSum": 84649 },{ "ndv": 951,"upper": 1900.01,"lower": 1884.16,"count": 1513,"preSum": 86160 },{ "ndv": 985,"upper": 1917.44,"lower": 1900.04,"count": 1511,"preSum": 87673 },{ "ndv": 1073,"upper": 1937.82,"lower": 1917.46,"count": 1512,"preSum": 89184 },{ "ndv": 1071,"upper": 1959.71,"lower": 1937.83,"count": 1512,"preSum": 90696 },{ "ndv": 1113,"upper": 1984.92,"lower": 1959.72,"count": 1511,"preSum": 92208 },{ "ndv": 1225,"upper": 2019.82,"lower": 1984.93,"count": 1511,"preSum": 93719 },{ "ndv": 1271,"upper": 2097.89,"lower": 2019.85,"count": 1442,"preSum": 95230 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 1.0 }
+  part.p_retailprice.null_count:
+    0
+  part.p_retailprice.sample_rate:
+    4.3894138E-4
+  part.p_size.TOPN:
+    { "countArr": [ 1966,1998,1978,1973,1972,1981,1960,2013,2024,1999,1974,1967,1991,1976 ],"valueArr": [ 4,5,6,7,8,11,16,18,19,26,32,41,48,49 ],"type": "Int","sampleRate": 1.0 }
+  part.p_size.cardinality:
+    50
+  part.p_size.histogram:
+    { "buckets": [ { "ndv": 1,"upper": 1,"lower": 1,"count": 1957,"preSum": 0 },{ "ndv": 1,"upper": 2,"lower": 2,"count": 1892,"preSum": 1957 },{ "ndv": 1,"upper": 3,"lower": 3,"count": 1914,"preSum": 3849 },{ "ndv": 1,"upper": 9,"lower": 9,"count": 1924,"preSum": 5763 },{ "ndv": 1,"upper": 10,"lower": 10,"count": 1909,"preSum": 7687 },{ "ndv": 1,"upper": 12,"lower": 12,"count": 1894,"preSum": 9596 },{ "ndv": 1,"upper": 13,"lower": 13,"count": 1944,"preSum": 11490 },{ "ndv": 1,"upper": 14,"lower": 14,"count": 1916,"preSum": 13434 },{ "ndv": 1,"upper": 15,"lower": 15,"count": 1892,"preSum": 15350 },{ "ndv": 1,"upper": 17,"lower": 17,"count": 1948,"preSum": 17242 },{ "ndv": 1,"upper": 20,"lower": 20,"count": 1913,"preSum": 19190 },{ "ndv": 1,"upper": 21,"lower": 21,"count": 1952,"preSum": 21103 },{ "ndv": 1,"upper": 22,"lower": 22,"count": 1887,"preSum": 23055 },{ "ndv": 1,"upper": 23,"lower": 23,"count": 1915,"preSum": 24942 },{ "ndv": 1,"upper": 24,"lower": 24,"count": 1949,"preSum": 26857 },{ "ndv": 1,"upper": 25,"lower": 25,"count": 1924,"preSum": 28806 },{ "ndv": 1,"upper": 27,"lower": 27,"count": 1918,"preSum": 30730 },{ "ndv": 1,"upper": 28,"lower": 28,"count": 1823,"preSum": 32648 },{ "ndv": 1,"upper": 29,"lower": 29,"count": 1952,"preSum": 34471 },{ "ndv": 1,"upper": 30,"lower": 30,"count": 1860,"preSum": 36423 },{ "ndv": 1,"upper": 31,"lower": 31,"count": 1904,"preSum": 38283 },{ "ndv": 1,"upper": 33,"lower": 33,"count": 1894,"preSum": 40187 },{ "ndv": 1,"upper": 34,"lower": 34,"count": 1949,"preSum": 42081 },{ "ndv": 1,"upper": 35,"lower": 35,"count": 1890,"preSum": 44030 },{ "ndv": 1,"upper": 36,"lower": 36,"count": 1934,"preSum": 45920 },{ "ndv": 1,"upper": 37,"lower": 37,"count": 1947,"preSum": 47854 },{ "ndv": 1,"upper": 38,"lower": 38,"count": 1951,"preSum": 49801 },{ "ndv": 1,"upper": 39,"lower": 39,"count": 1916,"preSum": 51752 },{ "ndv": 1,"upper": 40,"lower": 40,"count": 1910,"preSum": 53668 },{ "ndv": 1,"upper": 42,"lower": 42,"count": 1919,"preSum": 55578 },{ "ndv": 1,"upper": 43,"lower": 43,"count": 1917,"preSum": 57497 },{ "ndv": 1,"upper": 44,"lower": 44,"count": 1953,"preSum": 59414 },{ "ndv": 1,"upper": 45,"lower": 45,"count": 1894,"preSum": 61367 },{ "ndv": 1,"upper": 46,"lower": 46,"count": 1939,"preSum": 63261 },{ "ndv": 1,"upper": 47,"lower": 47,"count": 1951,"preSum": 65200 },{ "ndv": 1,"upper": 50,"lower": 50,"count": 1849,"preSum": 67151 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  part.p_size.null_count:
+    0
+  part.p_size.sample_rate:
+    4.3894138E-4
+  part.p_type.TOPN:
+    { "countArr": [ 687,689,687,681,693,678,681,685,680,682,685,699,684,687 ],"valueArr": [ "ECONOMY BRUSHED COPPER","LARGE ANODIZED TIN","LARGE BRUSHED STEEL","MEDIUM BRUSHED COPPER","MEDIUM BURNISHED STEEL","MEDIUM BURNISHED TIN","MEDIUM PLATED STEEL","MEDIUM PLATED TIN","MEDIUM POLISHED TIN","SMALL BURNISHED COPPER","SMALL PLATED TIN","SMALL POLISHED TIN","STANDARD BRUSHED BRASS","STANDARD BURNISHED NICKEL" ],"type": "String","sampleRate": 1.0 }
+  part.p_type.cardinality:
+    150
+  part.p_type.histogram:
+    { "buckets": [ { "ndv": 3,"upper": "ECONOMY ANODIZED NICKEL","lower": "ECONOMY ANODIZED BRASS","count": 1881,"preSum": 0 },{ "ndv": 3,"upper": "ECONOMY BRUSHED BRASS","lower": "ECONOMY ANODIZED STEEL","count": 1967,"preSum": 1881 },{ "ndv": 3,"upper": "ECONOMY BRUSHED TIN","lower": "ECONOMY BRUSHED NICKEL","count": 1904,"preSum": 3848 },{ "ndv": 3,"upper": "ECONOMY BURNISHED NICKEL","lower": "ECONOMY BURNISHED BRASS","count": 1909,"preSum": 5752 },{ "ndv": 3,"upper": "ECONOMY PLATED BRASS","lower": "ECONOMY BURNISHED STEEL","count": 1957,"preSum": 7661 },{ "ndv": 3,"upper": "ECONOMY PLATED STEEL","lower": "ECONOMY PLATED COPPER","count": 1974,"preSum": 9618 },{ "ndv": 3,"upper": "ECONOMY POLISHED COPPER","lower": "ECONOMY PLATED TIN","count": 1922,"preSum": 11592 },{ "ndv": 3,"upper": "ECONOMY POLISHED TIN","lower": "ECONOMY POLISHED NICKEL","count": 1931,"preSum": 13514 },{ "ndv": 3,"upper": "LARGE ANODIZED NICKEL","lower": "LARGE ANODIZED BRASS","count": 1973,"preSum": 15445 },{ "ndv": 3,"upper": "LARGE BRUSHED COPPER","lower": "LARGE ANODIZED STEEL","count": 1939,"preSum": 17418 },{ "ndv": 3,"upper": "LARGE BURNISHED BRASS","lower": "LARGE BRUSHED NICKEL","count": 1939,"preSum": 19357 },{ "ndv": 3,"upper": "LARGE BURNISHED STEEL","lower": "LARGE BURNISHED COPPER","count": 1952,"preSum": 21296 },{ "ndv": 3,"upper": "LARGE PLATED COPPER","lower": "LARGE BURNISHED TIN","count": 1922,"preSum": 23248 },{ "ndv": 3,"upper": "LARGE PLATED TIN","lower": "LARGE PLATED NICKEL","count": 1909,"preSum": 25170 },{ "ndv": 3,"upper": "LARGE POLISHED NICKEL","lower": "LARGE POLISHED BRASS","count": 1941,"preSum": 27079 },{ "ndv": 3,"upper": "MEDIUM ANODIZED BRASS","lower": "LARGE POLISHED STEEL","count": 1869,"preSum": 29020 },{ "ndv": 3,"upper": "MEDIUM ANODIZED STEEL","lower": "MEDIUM ANODIZED COPPER","count": 1855,"preSum": 30889 },{ "ndv": 3,"upper": "MEDIUM BRUSHED NICKEL","lower": "MEDIUM ANODIZED TIN","count": 1984,"preSum": 32744 },{ "ndv": 3,"upper": "MEDIUM BURNISHED BRASS","lower": "MEDIUM BRUSHED STEEL","count": 1913,"preSum": 34728 },{ "ndv": 3,"upper": "MEDIUM PLATED BRASS","lower": "MEDIUM BURNISHED COPPER","count": 1935,"preSum": 36641 },{ "ndv": 3,"upper": "MEDIUM POLISHED BRASS","lower": "MEDIUM PLATED COPPER","count": 1850,"preSum": 38576 },{ "ndv": 3,"upper": "MEDIUM POLISHED STEEL","lower": "MEDIUM POLISHED COPPER","count": 1989,"preSum": 40426 },{ "ndv": 3,"upper": "PROMO ANODIZED NICKEL","lower": "PROMO ANODIZED BRASS","count": 1948,"preSum": 42415 },{ "ndv": 3,"upper": "PROMO BRUSHED BRASS","lower": "PROMO ANODIZED STEEL","count": 1963,"preSum": 44363 },{ "ndv": 3,"upper": "PROMO BRUSHED STEEL","lower": "PROMO BRUSHED COPPER","count": 1930,"preSum": 46326 },{ "ndv": 3,"upper": "PROMO BURNISHED COPPER","lower": "PROMO BRUSHED TIN","count": 1862,"preSum": 48256 },{ "ndv": 3,"upper": "PROMO BURNISHED TIN","lower": "PROMO BURNISHED NICKEL","count": 1905,"preSum": 50118 },{ "ndv": 3,"upper": "PROMO PLATED NICKEL","lower": "PROMO PLATED BRASS","count": 1932,"preSum": 52023 },{ "ndv": 3,"upper": "PROMO POLISHED BRASS","lower": "PROMO PLATED STEEL","count": 1881,"preSum": 53955 },{ "ndv": 3,"upper": "PROMO POLISHED STEEL","lower": "PROMO POLISHED COPPER","count": 1903,"preSum": 55836 },{ "ndv": 3,"upper": "SMALL ANODIZED COPPER","lower": "PROMO POLISHED TIN","count": 1908,"preSum": 57739 },{ "ndv": 3,"upper": "SMALL ANODIZED TIN","lower": "SMALL ANODIZED NICKEL","count": 1952,"preSum": 59647 },{ "ndv": 3,"upper": "SMALL BRUSHED NICKEL","lower": "SMALL BRUSHED BRASS","count": 1909,"preSum": 61599 },{ "ndv": 3,"upper": "SMALL BURNISHED BRASS","lower": "SMALL BRUSHED STEEL","count": 1921,"preSum": 63508 },{ "ndv": 3,"upper": "SMALL BURNISHED TIN","lower": "SMALL BURNISHED NICKEL","count": 1926,"preSum": 65429 },{ "ndv": 3,"upper": "SMALL PLATED NICKEL","lower": "SMALL PLATED BRASS","count": 1944,"preSum": 67355 },{ "ndv": 3,"upper": "SMALL POLISHED COPPER","lower": "SMALL PLATED STEEL","count": 1942,"preSum": 69299 },{ "ndv": 3,"upper": "STANDARD ANODIZED BRASS","lower": "SMALL POLISHED NICKEL","count": 1913,"preSum": 71241 },{ "ndv": 3,"upper": "STANDARD ANODIZED STEEL","lower": "STANDARD ANODIZED COPPER","count": 1907,"preSum": 73154 },{ "ndv": 3,"upper": "STANDARD BRUSHED NICKEL","lower": "STANDARD ANODIZED TIN","count": 1957,"preSum": 75061 },{ "ndv": 3,"upper": "STANDARD BURNISHED BRASS","lower": "STANDARD BRUSHED STEEL","count": 1918,"preSum": 77018 },{ "ndv": 3,"upper": "STANDARD BURNISHED TIN","lower": "STANDARD BURNISHED COPPER","count": 1933,"preSum": 78936 },{ "ndv": 3,"upper": "STANDARD PLATED NICKEL","lower": "STANDARD PLATED BRASS","count": 1878,"preSum": 80869 },{ "ndv": 3,"upper": "STANDARD POLISHED BRASS","lower": "STANDARD PLATED STEEL","count": 1850,"preSum": 82747 },{ "ndv": 3,"upper": "STANDARD POLISHED STEEL","lower": "STANDARD POLISHED COPPER","count": 1918,"preSum": 84597 },{ "ndv": 1,"upper": "STANDARD POLISHED TIN","lower": "STANDARD POLISHED TIN","count": 659,"preSum": 86515 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  part.p_type.null_count:
+    0
+  part.p_type.sample_rate:
+    4.3894138E-4
+  partsupp.ps_availqty.TOPN:
+    { "countArr": [ 22,21,21,23,22,21,23,21,22,21,23,22,21,24 ],"valueArr": [ 946,1210,1700,2671,2684,3610,5178,5573,5890,6115,6811,7501,8723,8880 ],"type": "Int","sampleRate": 1.0 }
+  partsupp.ps_availqty.cardinality:
+    10097
+  partsupp.ps_availqty.histogram:
+    { "buckets": [ { "ndv": 152,"upper": 152,"lower": 1,"count": 1483,"preSum": 0 },{ "ndv": 154,"upper": 306,"lower": 153,"count": 1483,"preSum": 1483 },{ "ndv": 154,"upper": 460,"lower": 307,"count": 1483,"preSum": 2966 },{ "ndv": 151,"upper": 611,"lower": 461,"count": 1485,"preSum": 4449 },{ "ndv": 165,"upper": 776,"lower": 612,"count": 1479,"preSum": 5934 },{ "ndv": 165,"upper": 941,"lower": 777,"count": 1480,"preSum": 7413 },{ "ndv": 158,"upper": 1100,"lower": 942,"count": 1484,"preSum": 8893 },{ "ndv": 154,"upper": 1255,"lower": 1101,"count": 1486,"preSum": 10377 },{ "ndv": 155,"upper": 1410,"lower": 1256,"count": 1482,"preSum": 11863 },{ "ndv": 154,"upper": 1564,"lower": 1411,"count": 1487,"preSum": 13345 },{ "ndv": 157,"upper": 1722,"lower": 1565,"count": 1484,"preSum": 14832 },{ "ndv": 163,"upper": 1885,"lower": 1723,"count": 1484,"preSum": 16316 },{ "ndv": 159,"upper": 2044,"lower": 1886,"count": 1478,"preSum": 17800 },{ "ndv": 157,"upper": 2201,"lower": 2045,"count": 1486,"preSum": 19278 },{ "ndv": 156,"upper": 2357,"lower": 2202,"count": 1482,"preSum": 20764 },{ "ndv": 151,"upper": 2508,"lower": 2358,"count": 1485,"preSum": 22246 },{ "ndv": 150,"upper": 2658,"lower": 2509,"count": 1488,"preSum": 23731 },{ "ndv": 158,"upper": 2818,"lower": 2659,"count": 1481,"preSum": 25219 },{ "ndv": 160,"upper": 2978,"lower": 2819,"count": 1483,"preSum": 26700 },{ "ndv": 154,"upper": 3132,"lower": 2979,"count": 1485,"preSum": 28183 },{ "ndv": 153,"upper": 3285,"lower": 3133,"count": 1484,"preSum": 29668 },{ "ndv": 156,"upper": 3441,"lower": 3286,"count": 1482,"preSum": 31152 },{ "ndv": 155,"upper": 3596,"lower": 3442,"count": 1482,"preSum": 32634 },{ "ndv": 162,"upper": 3759,"lower": 3597,"count": 1486,"preSum": 34116 },{ "ndv": 152,"upper": 3911,"lower": 3760,"count": 1478,"preSum": 35602 },{ "ndv": 159,"upper": 4070,"lower": 3912,"count": 1487,"preSum": 37080 },{ "ndv": 157,"upper": 4227,"lower": 4071,"count": 1487,"preSum": 38567 },{ "ndv": 156,"upper": 4383,"lower": 4228,"count": 1486,"preSum": 40054 },{ "ndv": 153,"upper": 4536,"lower": 4384,"count": 1478,"preSum": 41540 },{ "ndv": 161,"upper": 4697,"lower": 4537,"count": 1480,"preSum": 43018 },{ "ndv": 156,"upper": 4853,"lower": 4698,"count": 1483,"preSum": 44498 },{ "ndv": 150,"upper": 5003,"lower": 4854,"count": 1478,"preSum": 45981 },{ "ndv": 156,"upper": 5159,"lower": 5004,"count": 1486,"preSum": 47459 },{ "ndv": 151,"upper": 5311,"lower": 5160,"count": 1481,"preSum": 48945 },{ "ndv": 152,"upper": 5463,"lower": 5312,"count": 1480,"preSum": 50426 },{ "ndv": 155,"upper": 5619,"lower": 5464,"count": 1486,"preSum": 51906 },{ "ndv": 159,"upper": 5778,"lower": 5620,"count": 1482,"preSum": 53392 },{ "ndv": 158,"upper": 5937,"lower": 5779,"count": 1481,"preSum": 54874 },{ "ndv": 150,"upper": 6087,"lower": 5938,"count": 1485,"preSum": 56355 },{ "ndv": 157,"upper": 6245,"lower": 6088,"count": 1483,"preSum": 57840 },{ "ndv": 154,"upper": 6399,"lower": 6246,"count": 1483,"preSum": 59323 },{ "ndv": 150,"upper": 6549,"lower": 6400,"count": 1478,"preSum": 60806 },{ "ndv": 153,"upper": 6702,"lower": 6550,"count": 1486,"preSum": 62284 },{ "ndv": 163,"upper": 6866,"lower": 6703,"count": 1482,"preSum": 63770 },{ "ndv": 153,"upper": 7019,"lower": 6867,"count": 1483,"preSum": 65252 },{ "ndv": 154,"upper": 7173,"lower": 7020,"count": 1486,"preSum": 66735 },{ "ndv": 165,"upper": 7338,"lower": 7174,"count": 1482,"preSum": 68221 },{ "ndv": 159,"upper": 7497,"lower": 7339,"count": 1485,"preSum": 69703 },{ "ndv": 158,"upper": 7656,"lower": 7498,"count": 1484,"preSum": 71188 },{ "ndv": 161,"upper": 7817,"lower": 7657,"count": 1483,"preSum": 72672 },{ "ndv": 158,"upper": 7975,"lower": 7818,"count": 1479,"preSum": 74155 },{ "ndv": 157,"upper": 8132,"lower": 7976,"count": 1482,"preSum": 75634 },{ "ndv": 156,"upper": 8288,"lower": 8133,"count": 1487,"preSum": 77116 },{ "ndv": 161,"upper": 8449,"lower": 8289,"count": 1484,"preSum": 78603 },{ "ndv": 154,"upper": 8603,"lower": 8450,"count": 1481,"preSum": 80087 },{ "ndv": 159,"upper": 8763,"lower": 8604,"count": 1479,"preSum": 81568 },{ "ndv": 160,"upper": 8924,"lower": 8764,"count": 1481,"preSum": 83047 },{ "ndv": 158,"upper": 9082,"lower": 8925,"count": 1479,"preSum": 84528 },{ "ndv": 164,"upper": 9246,"lower": 9083,"count": 1484,"preSum": 86007 },{ "ndv": 157,"upper": 9403,"lower": 9247,"count": 1486,"preSum": 87491 },{ "ndv": 165,"upper": 9568,"lower": 9404,"count": 1487,"preSum": 88977 },{ "ndv": 159,"upper": 9727,"lower": 9569,"count": 1484,"preSum": 90464 },{ "ndv": 153,"upper": 9880,"lower": 9728,"count": 1483,"preSum": 91948 },{ "ndv": 119,"upper": 9999,"lower": 9881,"count": 1139,"preSum": 93431 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  partsupp.ps_availqty.null_count:
+    0
+  partsupp.ps_availqty.sample_rate:
+    1.07420434E-4
+  partsupp.ps_comment.TOPN:
+    null
+  partsupp.ps_comment.cardinality:
+    61567892
+  partsupp.ps_comment.histogram:
+    { "buckets": [ { "ndv": 1483,"upper": " asymptotes wake. silent ideas sleep carefully against the pending asymptotes. slyly unusual requests play within the never iron","lower": " about the always final requests. ironic, unusual platelets use. furiously unusual courts wake","count": 1483,"preSum": 0 },{ "ndv": 1483,"upper": " carefully even packages sleep furiously around the special courts. fluffily pending packages sleep? furiously bold platelets bo","lower": " asymptotes! special, ironic foxes are carefully packages. iro","count": 1483,"preSum": 1483 },{ "ndv": 1482,"upper": " even, fluffy foxes-- dogged pinto beans haggle blithely. even ideas boost. fluffily pending requests sleep carefully slyly iron","lower": " carefully even packages. even theodolites after the even sautern","count": 1483,"preSum": 2966 },{ "ndv": 1483,"upper": " furiously silent deposits above the ironic accounts haggle carefully carefully ironic foxes. close platelets haggle furiously s","lower": " even, ironic deposits boost quickly. furiously regular reques","count": 1483,"preSum": 4449 },{ "ndv": 1483,"upper": " of the special excuses integrate fluffily about the even deposits. ironically final deposits slee","lower": " furiously silent deposits wake furiously after the","count": 1483,"preSum": 5932 },{ "ndv": 1483,"upper": " regular deposits wake carefully according to the carefully express asymptotes. ironi","lower": " of the special pinto beans. fluffily ironic dugouts sleep. furiously even foxes lose carefully even requests. slyly final ideas","count": 1483,"preSum": 7415 },{ "ndv": 1483,"upper": " slyly quickly regular theodolites-- quickly express deposits are blithely. blithely silent instructions wake deposits. furious","lower": " regular deposits wake carefully fluffily careful theodolites. ironic packages are blithely-- regular deposits ought to are acco","count": 1483,"preSum": 8898 },{ "ndv": 1483,"upper": " theodolites. deposits nag furiously. regular, final foxes nag across the blithely regular ","lower": " slyly quickly unusual packages. ironic, pending ideas about the even deposits cajole instructions. quickly pending requests a","count": 1483,"preSum": 10381 },{ "ndv": 1483,"upper": ". carefully ironic platelets sleep. fluffily ironic requests alongside of the slyly bold sentiments shall are across the even, r","lower": " theodolites. final accounts wake after the quickly even dependencies! furi","count": 1483,"preSum": 11864 },{ "ndv": 1483,"upper": "according to the blithely final requests. regular theodolites nag blithely according to the pending frays. final reques","lower": ". carefully ironic requests boost. blithe, pending pinto beans are quickly; ideas wake deposits. slyly regular de","count": 1483,"preSum": 13347 },{ "ndv": 1483,"upper": "ages sleep after the special requests. unusual tithes doze carefully. furiously regular excuses nag. slyly iron","lower": "according to the blithely ironic orbits haggle slyly","count": 1483,"preSum": 14830 },{ "ndv": 1483,"upper": "al pinto beans! slyly ironic excuses boost after the packages. express foxes integrate carefully. pending, regular theodolites ","lower": "ages sleep against the theodolites. carefully regular requests according to the even, bold requests nag furiously alongside of t","count": 1483,"preSum": 16313 },{ "ndv": 1483,"upper": "areful pinto beans. fluffy frays are against the carefully regular foxes. never regular requests nag slyly after the even, bold ","lower": "al pinto beans. bold, regular deposits about the slyly regular requests haggle after the slyly ironic deposits. furiously even t","count": 1483,"preSum": 17796 },{ "ndv": 1482,"upper": "blithely bold theodolites haggle silently. carefully bold packages poach fluffily ironic requests. express requests haggle slyly","lower": "areful requests nag furiously. furiously final packages haggle among the unusual deposits. ironic, unusual ideas cajole","count": 1483,"preSum": 19279 },{ "ndv": 1483,"upper": "cajole. carefully express asymptotes sleep. final dependencies after the carefully ir","lower": "blithely bold theodolites. instructions cajole quickly above the regular, even ","count": 1483,"preSum": 20762 },{ "ndv": 1483,"upper": "ckages haggle carefully deposits. pending, bold instructions sleep quickly fu","lower": "cajole. carefully final grouches was slyly. furiously final requests boost quickly. deposits alongside of the even theodolites s","count": 1483,"preSum": 22245 },{ "ndv": 1483,"upper": "cuses. pending, bold escapades boost fluffily even, ruthless deposits. quickly ironic req","lower": "ckages haggle carefully pending pinto beans. ironic pinto beans are. express requests nag after the pinto beans. deposits affix?","count": 1483,"preSum": 23728 },{ "ndv": 1483,"upper": "ding to the furiously ironic requests. carefully ironic packages use fluffily according to the furiously idle requests. regular ","lower": "cuses. pinto beans use furiously. fluffily even accounts boost? unusual deposits haggle special, unusual ","count": 1483,"preSum": 25211 },{ "ndv": 1483,"upper": "e furiously. regular gifts along the carefully ironic accounts detect carefully foxes. furiously pending platelets haggle slyly ","lower": "ding to the furiously pending deposits. carefully ironic asymptotes haggle quickly along the blithely bold dolphins. blithely ir","count": 1483,"preSum": 26694 },{ "ndv": 1483,"upper": "ecial instructions along the carefully bold dependencies are carefully even deposits. carefully bold ","lower": "e furiously. regular orbits alongside of the slyly final accounts boost furiously above the carefully ironic dinos. ironically r","count": 1483,"preSum": 28177 },{ "ndv": 1483,"upper": "elets should wake evenly. ironic, unusual packages haggle. regular deposits are unusual dependencies. ironic, bold deposits hagg","lower": "ecial instructions dazzle furiously special braids. furiously even foxes wake blithely. pending requests after the regular packa","count": 1483,"preSum": 29660 },{ "ndv": 1483,"upper": "eodolites cajole furiously furiously express ideas. final, unusual dolphins sleep after the regular, ","lower": "elets sleep even packages. bold packages thrash carefully final accounts. blithely e","count": 1483,"preSum": 31143 },{ "ndv": 1483,"upper": "es among the special, brave excuses wake around the unusual excuses? blithely regular instructions integrate furiously alongside","lower": "eodolites cajole furiously upon the blithely regular accounts. slyly regular accounts hang carefully alongside of the ideas. pac","count": 1483,"preSum": 32626 },{ "ndv": 1483,"upper": "ests until the slyly regular grouches sleep carefully along the blithely final instructions. furiously special foxes sleep quick","lower": "es among the unusual platelets maintain alongside of the express, even dependencies. slyly regular requests use fluffily about t","count": 1483,"preSum": 34109 },{ "ndv": 1483,"upper": "fily regular foxes affix furiously. bold pinto beans are carefully across t","lower": "ests use above the ideas. sometimes even foxes sleep slyly regular dependencies. regular deposits hinder furiously dependenc","count": 1483,"preSum": 35592 },{ "ndv": 1483,"upper": "fully regular requests cajole furiously ironic gifts. pinto beans nag. blithely ","lower": "fily regular gifts. express ideas are furiously whithout the final notornis. carefully regular instr","count": 1483,"preSum": 37075 },{ "ndv": 1483,"upper": "ges haggle quickly. packages cajole blithely near the doggedly final deposits. depo","lower": "fully regular requests do x-ray final accounts. slyly special escapades snooze furiously furiously ironic pinto ","count": 1483,"preSum": 38558 },{ "ndv": 1483,"upper": "haggle fluffily final asymptotes. quickly even excuses boost alongside of the carefully ironic requests. quickly special excuses","lower": "ges haggle slyly fluffily bold packages. carefully even courts detect blithely across the ","count": 1483,"preSum": 40041 },{ "ndv": 1483,"upper": "heodolites integrate furiously blithely special packages. regular, bold foxes detect. quickly ironic asymptotes at the fluffily ","lower": "haggle fluffily furiously unusual deposits. careful requests are at the quickly regular packages. b","count": 1483,"preSum": 41524 },{ "ndv": 1482,"upper": "ideas. blithely final accounts are slyly. final req","lower": "heodolites integrate furiously carefully even pinto beans. f","count": 1483,"preSum": 43007 },{ "ndv": 1483,"upper": "ingly blithely ironic pinto beans. quickly unusual pinto beans wak","lower": "ideas. blithely final theodolites against the accounts integrate inside the final foxes. bold packages according to the furiousl","count": 1483,"preSum": 44490 },{ "ndv": 1483,"upper": "ironic deposits. special deposits nag blithely across the blithely pending pinto beans. blithe, bold instructions wake quickly s","lower": "ingly blithely regular deposits. slyly express accounts across the furiously pending deposits boost across the carefully even de","count": 1483,"preSum": 45973 },{ "ndv": 1483,"upper": "jole permanently. quickly final theodolites thrash after the final pinto beans? furiously express packages at the blithely final","lower": "ironic deposits: furiously ironic deposits boost carefully according to the blithely express theodolites! packages among the acc","count": 1483,"preSum": 47456 },{ "ndv": 1483,"upper": "l packages. furiously unusual foxes are fluffily ironic accounts. furiously bold packages cajole. furiously pending a","lower": "jole quickly about the blithely pending deposits. slyly even accoun","count": 1483,"preSum": 48939 },{ "ndv": 1483,"upper": "le quickly above the quickly even packages; pinto beans haggle alongside of the furiously ironic theodolites. accounts integrate","lower": "l packages. instructions around the blithely idle theodolites cajole along the requests. final, furious deposits cajole across t","count": 1483,"preSum": 50422 },{ "ndv": 1482,"upper": "lly furiously pending asymptotes! slyly pending accounts boost sometimes fin","lower": "le quickly according to the carefully even ideas. carefully daring pinto beans sleep. blithely regular dugouts above t","count": 1483,"preSum": 51905 },{ "ndv": 1483,"upper": "ly even pinto beans. blithely express packages affix slyly even foxes. instructio","lower": "lly furiously silent theodolites. fluffily bold theodolites snooze quickly furiously ironic deposits. brave requests are above t","count": 1483,"preSum": 53388 },{ "ndv": 1483,"upper": "ly special requests among the carefully express packages detect against the blithely ironic packages. blithely special packages ","lower": "ly even pinto beans. blithely regular instructions nod along the accounts. carefully unusual asymptotes cajole after the fluffil","count": 1483,"preSum": 54871 },{ "ndv": 1483,"upper": "n theodolites. carefully even packages haggle furiously across the furiously even accounts. carefully b","lower": "ly special requests are blithely pending requests. furiously special requests are against the qui","count": 1483,"preSum": 56354 },{ "ndv": 1483,"upper": "ng, ironic requests. blithely final packages nod; slyly final packages hi","lower": "n theodolites. furiously permanent realms are carefully furiously final instructions. furiously ironic excuses are among the qui","count": 1483,"preSum": 57837 },{ "ndv": 1483,"upper": "nto beans are furiously blithely pending instructions. ideas along the pending deposits wake blithely regular foxes. blithely ir","lower": "ng, pending pinto beans. bold pinto beans are busily. ironic theodolites around the regular, even courts mold against the final,","count": 1483,"preSum": 59320 },{ "ndv": 1483,"upper": "old pinto beans hinder carefully alongside of the special, special dependencies. final, express requests cajole. furio","lower": "nto beans are pending, regular theodolites. regular excuses are fluffily against the ironic dolphins. carefully regular accounts","count": 1483,"preSum": 60803 },{ "ndv": 1483,"upper": "ording to the quickly final accounts wake above the final theodolites. special deposits was slyly after the evenly final fox","lower": "old pinto beans sleep across the furiously quick foxes. asymptotes against the slyly regular multipliers wake bold pains. slyly ","count": 1483,"preSum": 62286 },{ "ndv": 1483,"upper": "ously final foxes cajole carefully alongside of the regular, even ideas. special accounts use even theodolites. furi","lower": "ording to the quickly final frays wake alongside of the final ideas: unusual ideas above the furiously unusual accounts haggle s","count": 1483,"preSum": 63769 },{ "ndv": 1483,"upper": "pecial foxes doubt. furiously ironic requests after the even, even deposits sleep furiously above the careful deposits. final co","lower": "ously final foxes snooze slyly quickly final pinto beans. slyly regular foxes thrash theodolites. carefully permanent pack","count": 1483,"preSum": 65252 },{ "ndv": 1483,"upper": "ptotes haggle furiously foxes. regular excuses run after the quickly quiet deposits. slyly final platelets sleep. carefully regu","lower": "pecial foxes haggle according to the furiously regular asymptotes. ironic deposits alongside of the furiously bold fox","count": 1483,"preSum": 66735 },{ "ndv": 1482,"upper": "rate carefully even packages. accounts about the furiously regular requests haggle slyly across the pinto beans. carefully regul","lower": "ptotes haggle slyly slyly special dolphins. deposits print around the regular, pending deposits. requests integrate. forges use ","count": 1483,"preSum": 68218 },{ "ndv": 1482,"upper": "requests along the requests wake finally according to the regular requests. slyly even","lower": "rate carefully final deposits. instructions cajole a","count": 1483,"preSum": 69701 },{ "ndv": 1483,"upper": "ronic packages. accounts above the carefully express requests are carefully regular instructions. special theodolites are accord","lower": "requests alongside of the carefully ironic ideas sleep quickly regular theodolites. furiously bold requests haggle. sly","count": 1483,"preSum": 71184 },{ "ndv": 1483,"upper": "s deposits haggle according to the deposits. slow theodolites integrate. carefully even instructions cajole ironically ","lower": "ronic packages. blithely bold accounts wake blithely. theodolites haggle fluffily according to the ironic, ironic deposits. quie","count": 1483,"preSum": 72667 },{ "ndv": 1483,"upper": "s. blithely ironic foxes haggle quickly final, ironic requests. fluffily ironic accounts according to the pend","lower": "s deposits nag slyly along the quickly silent packages. packages cajole fluffily. furiously silent requests among the furiously ","count": 1483,"preSum": 74150 },{ "ndv": 1483,"upper": "silent sentiments. quickly bold theodolites are regularly deposits; final foxes cajole slyly. slyly ironic foxes against the flu","lower": "s. blithely ironic packages across the furiously expre","count": 1483,"preSum": 75633 },{ "ndv": 1483,"upper": "slyly quickly special pinto beans. final, regular theodolites wake blithely slyly iron","lower": "silent theodolites nag doggedly blithely special accounts; carefully regular packages wake furiously regular instructions. silen","count": 1483,"preSum": 77116 },{ "ndv": 1483,"upper": "sual asymptotes. slyly brave deposits toward the final packages are slyly across the slyly pending requests. slowly final accoun","lower": "slyly quiet accounts use. slyly unusual deposits boost slyly. pending, pending packages cajole. furiously pending warhorses are.","count": 1483,"preSum": 78599 },{ "ndv": 1483,"upper": "the blithely final accounts: close foxes cajole iron","lower": "sual attainments alongside of the unusual theodolites wake above the slyly bold accounts. furiously even orbits solve furiously ","count": 1483,"preSum": 80082 },{ "ndv": 1483,"upper": "thes. ideas across the slyly pending requests cajole special instructions. carefully ironic requests detect quickly deposits. fi","lower": "the blithely final dugouts. fluffily special dependencies nag quickly duri","count": 1483,"preSum": 81565 },{ "ndv": 1483,"upper": "ts nag about the ideas. pending requests wake carefully about the slyly regular foxes. carefully final dolphins dazzle blithely ","lower": "thes. ironic foxes integrate across the final, even deposits. final, final packages after the quickly regular","count": 1483,"preSum": 83048 },{ "ndv": 1483,"upper": "uests. furiously even deposits haggle special packages. final, express dependencies are in place of the pending requests. reques","lower": "ts nag above the carefully even deposits. bold, express accounts det","count": 1483,"preSum": 84531 },{ "ndv": 1483,"upper": "ully final foxes sleep alongside of the accounts. ideas about the quickly final requests boost packages. blithely ironic forges ","lower": "uests. furiously even epitaphs about the regular packages sleep furiously regular packages. quickly final deposits are blithely ","count": 1483,"preSum": 86014 },{ "ndv": 1482,"upper": "urts haggle furiously blithely unusual deposits: closely silent waters cajole blithely about the carefully even accounts. final ","lower": "ully final frays boost quickly above the daringly final braids. furiously regular platelets sle","count": 1483,"preSum": 87497 },{ "ndv": 1483,"upper": "ven requests sleep of the regular foxes. permanent requests poach across the carefully even courts. thinly ironi","lower": "urts haggle slyly evenly express requests. furiously close packages detect slyly carefully unusual platelets. even accounts slee","count": 1483,"preSum": 88980 },{ "ndv": 1483,"upper": "y bold requests wake quickly until the furiously ironic packages. slyly pending accounts after the slyly final packages impress ","lower": "ven requests sleep quickly furiously bold theodolites. deposits on the regularly fluffy packages are furiously according to the ","count": 1483,"preSum": 90463 },{ "ndv": 1483,"upper": "y regular requests wake at the furiously silent theodolites. final theodolites alongside of the busy deposits sleep furiously pe","lower": "y bold requests. blithely blithe instructions affix slyl","count": 1483,"preSum": 91946 },{ "ndv": 1447,"upper": "zzle. regular requests around the fluffily final ide","lower": "y regular requests wake blithely across the slyly even accounts. quickly ironic braids sleep. silent, regular pinto beans boo","count": 1448,"preSum": 93429 } ],"maxBucketSize": 64,"type": "String","sampleRate": 1.0 }
+  partsupp.ps_comment.null_count:
+    0
+  partsupp.ps_comment.sample_rate:
+    1.07420434E-4
+  partsupp.ps_partkey.TOPN:
+    { "countArr": [ ],"valueArr": [ ],"type": "Int","sampleRate": 1.0 }
+  partsupp.ps_partkey.cardinality:
+    195025
+  partsupp.ps_partkey.histogram:
+    { "buckets": [ { "ndv": 372,"upper": 381,"lower": 1,"count": 1484,"preSum": 0 },{ "ndv": 374,"upper": 788,"lower": 382,"count": 1486,"preSum": 1484 },{ "ndv": 376,"upper": 1213,"lower": 789,"count": 1483,"preSum": 2970 },{ "ndv": 382,"upper": 1778,"lower": 1214,"count": 1483,"preSum": 4453 },{ "ndv": 397,"upper": 2826,"lower": 1779,"count": 1485,"preSum": 5936 },{ "ndv": 398,"upper": 855748,"lower": 2832,"count": 1483,"preSum": 7421 },{ "ndv": 400,"upper": 3924211,"lower": 855750,"count": 1484,"preSum": 8904 },{ "ndv": 394,"upper": 6632047,"lower": 3924212,"count": 1486,"preSum": 10388 },{ "ndv": 404,"upper": 9857976,"lower": 6632121,"count": 1485,"preSum": 11874 },{ "ndv": 402,"upper": 13582063,"lower": 9857979,"count": 1483,"preSum": 13359 },{ "ndv": 400,"upper": 18377176,"lower": 13582397,"count": 1485,"preSum": 14842 },{ "ndv": 395,"upper": 20815260,"lower": 18377208,"count": 1483,"preSum": 16327 },{ "ndv": 402,"upper": 24069145,"lower": 20815262,"count": 1483,"preSum": 17810 },{ "ndv": 410,"upper": 28369474,"lower": 24069160,"count": 1486,"preSum": 19293 },{ "ndv": 398,"upper": 31414923,"lower": 28369478,"count": 1485,"preSum": 20779 },{ "ndv": 405,"upper": 34407347,"lower": 31415093,"count": 1484,"preSum": 22264 },{ "ndv": 407,"upper": 38277067,"lower": 34408195,"count": 1485,"preSum": 23748 },{ "ndv": 401,"upper": 42085600,"lower": 38277096,"count": 1484,"preSum": 25233 },{ "ndv": 403,"upper": 46161466,"lower": 42085601,"count": 1484,"preSum": 26717 },{ "ndv": 395,"upper": 49148198,"lower": 46161684,"count": 1486,"preSum": 28201 },{ "ndv": 398,"upper": 51844737,"lower": 49148213,"count": 1483,"preSum": 29687 },{ "ndv": 399,"upper": 54023860,"lower": 51844795,"count": 1486,"preSum": 31170 },{ "ndv": 403,"upper": 57766934,"lower": 54024344,"count": 1483,"preSum": 32656 },{ "ndv": 395,"upper": 60436698,"lower": 57767048,"count": 1486,"preSum": 34139 },{ "ndv": 404,"upper": 63424233,"lower": 60436699,"count": 1484,"preSum": 35625 },{ "ndv": 406,"upper": 68088998,"lower": 63424234,"count": 1485,"preSum": 37109 },{ "ndv": 398,"upper": 72384160,"lower": 68089137,"count": 1485,"preSum": 38594 },{ "ndv": 398,"upper": 75145700,"lower": 72384166,"count": 1485,"preSum": 40079 },{ "ndv": 403,"upper": 78624227,"lower": 75145702,"count": 1485,"preSum": 41564 },{ "ndv": 393,"upper": 81382442,"lower": 78624304,"count": 1485,"preSum": 43049 },{ "ndv": 409,"upper": 85068912,"lower": 81382533,"count": 1486,"preSum": 44534 },{ "ndv": 404,"upper": 87571310,"lower": 85069124,"count": 1485,"preSum": 46020 },{ "ndv": 401,"upper": 91086633,"lower": 87571409,"count": 1485,"preSum": 47505 },{ "ndv": 410,"upper": 94508261,"lower": 91086877,"count": 1485,"preSum": 48990 },{ "ndv": 410,"upper": 99200680,"lower": 94508341,"count": 1485,"preSum": 50475 },{ "ndv": 404,"upper": 102479143,"lower": 99200688,"count": 1483,"preSum": 51960 },{ "ndv": 413,"upper": 105885295,"lower": 102479436,"count": 1486,"preSum": 53443 },{ "ndv": 395,"upper": 109323403,"lower": 105885394,"count": 1485,"preSum": 54929 },{ "ndv": 396,"upper": 113207918,"lower": 109323591,"count": 1485,"preSum": 56414 },{ "ndv": 409,"upper": 116800341,"lower": 113207958,"count": 1486,"preSum": 57899 },{ "ndv": 400,"upper": 120630485,"lower": 116800373,"count": 1483,"preSum": 59385 },{ "ndv": 404,"upper": 124617206,"lower": 120630514,"count": 1486,"preSum": 60868 },{ "ndv": 404,"upper": 128292576,"lower": 124617339,"count": 1486,"preSum": 62354 },{ "ndv": 400,"upper": 131979933,"lower": 128292577,"count": 1483,"preSum": 63840 },{ "ndv": 406,"upper": 134146541,"lower": 131979950,"count": 1484,"preSum": 65323 },{ "ndv": 401,"upper": 138684901,"lower": 134146542,"count": 1483,"preSum": 66807 },{ "ndv": 398,"upper": 142428368,"lower": 138685275,"count": 1484,"preSum": 68290 },{ "ndv": 408,"upper": 145696348,"lower": 142428400,"count": 1484,"preSum": 69774 },{ "ndv": 401,"upper": 149473841,"lower": 145743810,"count": 1483,"preSum": 71258 },{ "ndv": 403,"upper": 152892665,"lower": 149473916,"count": 1486,"preSum": 72741 },{ "ndv": 408,"upper": 156474511,"lower": 152892666,"count": 1483,"preSum": 74227 },{ "ndv": 395,"upper": 159982837,"lower": 156474908,"count": 1485,"preSum": 75710 },{ "ndv": 401,"upper": 163473990,"lower": 159982976,"count": 1483,"preSum": 77195 },{ "ndv": 403,"upper": 166632098,"lower": 163474011,"count": 1483,"preSum": 78678 },{ "ndv": 403,"upper": 170538680,"lower": 166632230,"count": 1483,"preSum": 80161 },{ "ndv": 404,"upper": 173579840,"lower": 170538790,"count": 1486,"preSum": 81644 },{ "ndv": 407,"upper": 176326222,"lower": 173580065,"count": 1486,"preSum": 83130 },{ "ndv": 396,"upper": 179029730,"lower": 176326254,"count": 1483,"preSum": 84616 },{ "ndv": 401,"upper": 181769726,"lower": 179029731,"count": 1485,"preSum": 86099 },{ "ndv": 411,"upper": 186526424,"lower": 181769785,"count": 1486,"preSum": 87584 },{ "ndv": 396,"upper": 189998099,"lower": 186526456,"count": 1483,"preSum": 89070 },{ "ndv": 405,"upper": 193146551,"lower": 189998108,"count": 1486,"preSum": 90553 },{ "ndv": 403,"upper": 196423979,"lower": 193146659,"count": 1486,"preSum": 92039 },{ "ndv": 362,"upper": 199995855,"lower": 196424247,"count": 1352,"preSum": 93525 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  partsupp.ps_partkey.null_count:
+    0
+  partsupp.ps_partkey.sample_rate:
+    1.07420434E-4
+  partsupp.ps_suppkey.TOPN:
+    { "countArr": [ 3 ],"valueArr": [ 744 ],"type": "Int","sampleRate": 1.0 }
+  partsupp.ps_suppkey.cardinality:
+    50326890
+  partsupp.ps_suppkey.histogram:
+    { "buckets": [ { "ndv": 1465,"upper": 1712,"lower": 2,"count": 1483,"preSum": 0 },{ "ndv": 1472,"upper": 95357,"lower": 1713,"count": 1483,"preSum": 1483 },{ "ndv": 1477,"upper": 267051,"lower": 95358,"count": 1483,"preSum": 2966 },{ "ndv": 1477,"upper": 459576,"lower": 267054,"count": 1483,"preSum": 4449 },{ "ndv": 1476,"upper": 636574,"lower": 459661,"count": 1483,"preSum": 5932 },{ "ndv": 1478,"upper": 808987,"lower": 638162,"count": 1483,"preSum": 7415 },{ "ndv": 1476,"upper": 988791,"lower": 809019,"count": 1483,"preSum": 8898 },{ "ndv": 1475,"upper": 1133386,"lower": 988792,"count": 1483,"preSum": 10381 },{ "ndv": 1477,"upper": 1302611,"lower": 1133387,"count": 1483,"preSum": 11864 },{ "ndv": 1472,"upper": 1482188,"lower": 1302612,"count": 1483,"preSum": 13347 },{ "ndv": 1479,"upper": 1655679,"lower": 1482190,"count": 1483,"preSum": 14830 },{ "ndv": 1475,"upper": 1817547,"lower": 1655938,"count": 1483,"preSum": 16313 },{ "ndv": 1474,"upper": 1974194,"lower": 1817570,"count": 1483,"preSum": 17796 },{ "ndv": 1474,"upper": 2145470,"lower": 1974195,"count": 1483,"preSum": 19279 },{ "ndv": 1472,"upper": 2315066,"lower": 2145471,"count": 1483,"preSum": 20762 },{ "ndv": 1474,"upper": 2494730,"lower": 2315067,"count": 1483,"preSum": 22245 },{ "ndv": 1465,"upper": 2501646,"lower": 2494731,"count": 1483,"preSum": 23728 },{ "ndv": 1472,"upper": 2595328,"lower": 2501647,"count": 1483,"preSum": 25211 },{ "ndv": 1473,"upper": 2766542,"lower": 2595329,"count": 1483,"preSum": 26694 },{ "ndv": 1478,"upper": 2958939,"lower": 2766568,"count": 1483,"preSum": 28177 },{ "ndv": 1477,"upper": 3138170,"lower": 2958971,"count": 1483,"preSum": 29660 },{ "ndv": 1480,"upper": 3310011,"lower": 3138474,"count": 1483,"preSum": 31143 },{ "ndv": 1478,"upper": 3488841,"lower": 3310110,"count": 1483,"preSum": 32626 },{ "ndv": 1475,"upper": 3634583,"lower": 3488842,"count": 1483,"preSum": 34109 },{ "ndv": 1475,"upper": 3804186,"lower": 3634624,"count": 1483,"preSum": 35592 },{ "ndv": 1479,"upper": 3983965,"lower": 3804431,"count": 1483,"preSum": 37075 },{ "ndv": 1478,"upper": 4157110,"lower": 3983982,"count": 1483,"preSum": 38558 },{ "ndv": 1480,"upper": 4317865,"lower": 4157142,"count": 1483,"preSum": 40041 },{ "ndv": 1477,"upper": 4474592,"lower": 4318015,"count": 1483,"preSum": 41524 },{ "ndv": 1482,"upper": 4648808,"lower": 4474700,"count": 1483,"preSum": 43007 },{ "ndv": 1473,"upper": 4819607,"lower": 4650249,"count": 1483,"preSum": 44490 },{ "ndv": 1477,"upper": 4996200,"lower": 4819630,"count": 1483,"preSum": 45973 },{ "ndv": 1465,"upper": 5001681,"lower": 4996319,"count": 1483,"preSum": 47456 },{ "ndv": 1469,"upper": 5100634,"lower": 5001683,"count": 1483,"preSum": 48939 },{ "ndv": 1475,"upper": 5267802,"lower": 5100781,"count": 1483,"preSum": 50422 },{ "ndv": 1476,"upper": 5460615,"lower": 5267843,"count": 1483,"preSum": 51905 },{ "ndv": 1480,"upper": 5640782,"lower": 5460618,"count": 1483,"preSum": 53388 },{ "ndv": 1478,"upper": 5811888,"lower": 5640884,"count": 1483,"preSum": 54871 },{ "ndv": 1481,"upper": 5989556,"lower": 5811916,"count": 1483,"preSum": 56354 },{ "ndv": 1480,"upper": 6135012,"lower": 5989562,"count": 1483,"preSum": 57837 },{ "ndv": 1476,"upper": 6307922,"lower": 6135220,"count": 1483,"preSum": 59320 },{ "ndv": 1472,"upper": 6488794,"lower": 6307971,"count": 1483,"preSum": 60803 },{ "ndv": 1478,"upper": 6662897,"lower": 6489063,"count": 1483,"preSum": 62286 },{ "ndv": 1475,"upper": 6823654,"lower": 6662925,"count": 1483,"preSum": 63769 },{ "ndv": 1481,"upper": 6976332,"lower": 6823687,"count": 1483,"preSum": 65252 },{ "ndv": 1478,"upper": 7161760,"lower": 6976369,"count": 1483,"preSum": 66735 },{ "ndv": 1478,"upper": 7321026,"lower": 7161966,"count": 1483,"preSum": 68218 },{ "ndv": 1477,"upper": 7499493,"lower": 7321039,"count": 1483,"preSum": 69701 },{ "ndv": 1466,"upper": 7501746,"lower": 7499580,"count": 1483,"preSum": 71184 },{ "ndv": 1468,"upper": 7609130,"lower": 7501747,"count": 1483,"preSum": 72667 },{ "ndv": 1480,"upper": 7774836,"lower": 7609752,"count": 1483,"preSum": 74150 },{ "ndv": 1483,"upper": 7963455,"lower": 7774858,"count": 1483,"preSum": 75633 },{ "ndv": 1472,"upper": 8143405,"lower": 7963474,"count": 1483,"preSum": 77116 },{ "ndv": 1478,"upper": 8315135,"lower": 8143567,"count": 1483,"preSum": 78599 },{ "ndv": 1476,"upper": 8497791,"lower": 8315157,"count": 1483,"preSum": 80082 },{ "ndv": 1476,"upper": 8639241,"lower": 8497993,"count": 1483,"preSum": 81565 },{ "ndv": 1480,"upper": 8813084,"lower": 8639842,"count": 1483,"preSum": 83048 },{ "ndv": 1477,"upper": 8994033,"lower": 8813085,"count": 1483,"preSum": 84531 },{ "ndv": 1475,"upper": 9173245,"lower": 8994154,"count": 1483,"preSum": 86014 },{ "ndv": 1479,"upper": 9329831,"lower": 9173316,"count": 1483,"preSum": 87497 },{ "ndv": 1476,"upper": 9479734,"lower": 9329832,"count": 1484,"preSum": 88980 },{ "ndv": 1475,"upper": 9663279,"lower": 9479973,"count": 1483,"preSum": 90464 },{ "ndv": 1472,"upper": 9824307,"lower": 9663756,"count": 1483,"preSum": 91947 },{ "ndv": 1439,"upper": 9999835,"lower": 9824324,"count": 1444,"preSum": 93430 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 1.0 }
+  partsupp.ps_suppkey.null_count:
+    0
+  partsupp.ps_suppkey.sample_rate:
+    1.07420434E-4
+  partsupp.ps_supplycost.TOPN:
+    { "countArr": [ 7,7,7,7 ],"valueArr": [ 226.91,693.22,861.62,980.69 ],"type": "Double","sampleRate": 1.0 }
+  partsupp.ps_supplycost.cardinality:
+    5143574
+  partsupp.ps_supplycost.histogram:
+    { "buckets": [ { "ndv": 966,"upper": 16.36,"lower": 1.01,"count": 1484,"preSum": 0 },{ "ndv": 951,"upper": 31.59,"lower": 16.37,"count": 1483,"preSum": 1484 },{ "ndv": 963,"upper": 47.25,"lower": 31.61,"count": 1484,"preSum": 2967 },{ "ndv": 942,"upper": 62.19,"lower": 47.26,"count": 1483,"preSum": 4451 },{ "ndv": 940,"upper": 77.52,"lower": 62.20,"count": 1483,"preSum": 5934 },{ "ndv": 1000,"upper": 93.84,"lower": 77.53,"count": 1483,"preSum": 7417 },{ "ndv": 992,"upper": 109.76,"lower": 93.85,"count": 1483,"preSum": 8900 },{ "ndv": 953,"upper": 124.92,"lower": 109.77,"count": 1484,"preSum": 10383 },{ "ndv": 964,"upper": 140.74,"lower": 124.93,"count": 1484,"preSum": 11867 },{ "ndv": 970,"upper": 156.27,"lower": 140.75,"count": 1483,"preSum": 13351 },{ "ndv": 948,"upper": 171.78,"lower": 156.28,"count": 1483,"preSum": 14834 },{ "ndv": 937,"upper": 188.10,"lower": 171.79,"count": 1483,"preSum": 16317 },{ "ndv": 969,"upper": 203.92,"lower": 188.12,"count": 1483,"preSum": 17800 },{ "ndv": 962,"upper": 219.96,"lower": 203.93,"count": 1483,"preSum": 19283 },{ "ndv": 942,"upper": 235.23,"lower": 219.97,"count": 1484,"preSum": 20766 },{ "ndv": 960,"upper": 250.63,"lower": 235.24,"count": 1484,"preSum": 22250 },{ "ndv": 931,"upper": 265.74,"lower": 250.64,"count": 1483,"preSum": 23734 },{ "ndv": 941,"upper": 281.29,"lower": 265.75,"count": 1483,"preSum": 25217 },{ "ndv": 968,"upper": 296.99,"lower": 281.31,"count": 1484,"preSum": 26700 },{ "ndv": 950,"upper": 312.80,"lower": 297.00,"count": 1484,"preSum": 28184 },{ "ndv": 971,"upper": 328.51,"lower": 312.83,"count": 1483,"preSum": 29668 },{ "ndv": 960,"upper": 344.44,"lower": 328.52,"count": 1484,"preSum": 31151 },{ "ndv": 959,"upper": 359.80,"lower": 344.49,"count": 1485,"preSum": 32635 },{ "ndv": 995,"upper": 376.39,"lower": 359.81,"count": 1485,"preSum": 34120 },{ "ndv": 987,"upper": 392.32,"lower": 376.41,"count": 1483,"preSum": 35605 },{ "ndv": 942,"upper": 407.75,"lower": 392.33,"count": 1483,"preSum": 37088 },{ "ndv": 943,"upper": 423.06,"lower": 407.76,"count": 1483,"preSum": 38571 },{ "ndv": 958,"upper": 439.05,"lower": 423.07,"count": 1483,"preSum": 40054 },{ "ndv": 948,"upper": 454.54,"lower": 439.06,"count": 1483,"preSum": 41537 },{ "ndv": 967,"upper": 470.32,"lower": 454.56,"count": 1483,"preSum": 43020 },{ "ndv": 933,"upper": 485.73,"lower": 470.33,"count": 1483,"preSum": 44503 },{ "ndv": 942,"upper": 501.40,"lower": 485.76,"count": 1483,"preSum": 45986 },{ "ndv": 970,"upper": 517.21,"lower": 501.41,"count": 1483,"preSum": 47469 },{ "ndv": 963,"upper": 532.73,"lower": 517.22,"count": 1485,"preSum": 48952 },{ "ndv": 976,"upper": 548.79,"lower": 532.75,"count": 1483,"preSum": 50437 },{ "ndv": 963,"upper": 564.60,"lower": 548.81,"count": 1483,"preSum": 51920 },{ "ndv": 946,"upper": 580.33,"lower": 564.61,"count": 1483,"preSum": 53403 },{ "ndv": 962,"upper": 595.88,"lower": 580.34,"count": 1484,"preSum": 54886 },{ "ndv": 967,"upper": 611.56,"lower": 595.89,"count": 1483,"preSum": 56370 },{ "ndv": 938,"upper": 626.68,"lower": 611.57,"count": 1486,"preSum": 57853 },{ "ndv": 961,"upper": 642.11,"lower": 626.69,"count": 1484,"preSum": 59339 },{ "ndv": 941,"upper": 657.43,"lower": 642.12,"count": 1483,"preSum": 60823 },{ "ndv": 941,"upper": 673.08,"lower": 657.47,"count": 1484,"preSum": 62306 },{ "ndv": 967,"upper": 688.47,"lower": 673.09,"count": 1483,"preSum": 63790 },{ "ndv": 974,"upper": 704.40,"lower": 688.48,"count": 1483,"preSum": 65273 },{ "ndv": 953,"upper": 719.57,"lower": 704.41,"count": 1485,"preSum": 66756 },{ "ndv": 952,"upper": 735.07,"lower": 719.58,"count": 1484,"preSum": 68241 },{ "ndv": 980,"upper": 750.95,"lower": 735.08,"count": 1483,"preSum": 69725 },{ "ndv": 966,"upper": 766.72,"lower": 750.97,"count": 1484,"preSum": 71208 },{ "ndv": 945,"upper": 781.81,"lower": 766.77,"count": 1483,"preSum": 72692 },{ "ndv": 951,"upper": 797.20,"lower": 781.82,"count": 1483,"preSum": 74175 },{ "ndv": 984,"upper": 813.23,"lower": 797.21,"count": 1483,"preSum": 75658 },{ "ndv": 968,"upper": 829.42,"lower": 813.24,"count": 1483,"preSum": 77141 },{ "ndv": 966,"upper": 845.17,"lower": 829.43,"count": 1483,"preSum": 78624 },{ "ndv": 943,"upper": 861.12,"lower": 845.18,"count": 1484,"preSum": 80107 },{ "ndv": 967,"upper": 876.77,"lower": 861.15,"count": 1483,"preSum": 81591 },{ "ndv": 957,"upper": 892.19,"lower": 876.78,"count": 1483,"preSum": 83074 },{ "ndv": 945,"upper": 907.11,"lower": 892.20,"count": 1484,"preSum": 84557 },{ "ndv": 943,"upper": 922.27,"lower": 907.12,"count": 1484,"preSum": 86041 },{ "ndv": 954,"upper": 937.72,"lower": 922.28,"count": 1483,"preSum": 87525 },{ "ndv": 976,"upper": 953.88,"lower": 937.73,"count": 1483,"preSum": 89008 },{ "ndv": 951,"upper": 969.59,"lower": 953.89,"count": 1483,"preSum": 90491 },{ "ndv": 976,"upper": 985.46,"lower": 969.62,"count": 1483,"preSum": 91974 },{ "ndv": 896,"upper": 1000.00,"lower": 985.53,"count": 1392,"preSum": 93457 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 1.0 }
+  partsupp.ps_supplycost.null_count:
+    0
+  partsupp.ps_supplycost.sample_rate:
+    1.07420434E-4
+  region.r_comment.TOPN:
+    null
+  region.r_comment.cardinality:
+    5
+  region.r_comment.histogram:
+    { "buckets": [ { "ndv": 2,"upper": "hs use ironic, even requests. s","lower": "ges. thinly even pinto beans ca","count": 2,"preSum": 0 },{ "ndv": 2,"upper": "ly final courts cajole furiously final excuse","lower": "lar deposits. blithely final packages cajole. regular waters are final requests. regular accounts are according to ","count": 2,"preSum": 2 },{ "ndv": 1,"upper": "uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl","lower": "uickly special accounts cajole carefully blithely close requests. carefully final asymptotes haggle furiousl","count": 1,"preSum": 4 } ],"maxBucketSize": 4,"type": "String","sampleRate": 1.0 }
+  region.r_comment.null_count:
+    0
+  region.r_comment.sample_rate:
+    1.0
+  region.r_name.TOPN:
+    null
+  region.r_name.cardinality:
+    5
+  region.r_name.histogram:
+    { "buckets": [ { "ndv": 2,"upper": "AMERICA","lower": "AFRICA","count": 2,"preSum": 0 },{ "ndv": 2,"upper": "EUROPE","lower": "ASIA","count": 2,"preSum": 2 },{ "ndv": 1,"upper": "MIDDLE EAST","lower": "MIDDLE EAST","count": 1,"preSum": 4 } ],"maxBucketSize": 4,"type": "String","sampleRate": 1.0 }
+  region.r_name.null_count:
+    0
+  region.r_name.sample_rate:
+    1.0
+  region.r_regionkey.TOPN:
+    null
+  region.r_regionkey.cardinality:
+    5
+  region.r_regionkey.histogram:
+    { "buckets": [ { "ndv": 2,"upper": 1,"lower": 0,"count": 2,"preSum": 0 },{ "ndv": 2,"upper": 3,"lower": 2,"count": 2,"preSum": 2 },{ "ndv": 1,"upper": 4,"lower": 4,"count": 1,"preSum": 4 } ],"maxBucketSize": 4,"type": "Int","sampleRate": 1.0 }
+  region.r_regionkey.null_count:
+    0
+  region.r_regionkey.sample_rate:
+    1.0
+  supplier.s_acctbal.TOPN:
+    { "countArr": [ 4,4,4,4 ],"valueArr": [ 4745.67,5500.93,6399.78,8571.88 ],"type": "Double","sampleRate": 0.9077713528381187 }
+  supplier.s_acctbal.cardinality:
+    2793079
+  supplier.s_acctbal.histogram:
+    { "buckets": [ { "ndv": 1493,"upper": -831.70,"lower": -999.93,"count": 1563,"preSum": 0 },{ "ndv": 1501,"upper": -652.84,"lower": -831.16,"count": 1563,"preSum": 1563 },{ "ndv": 1504,"upper": -475.35,"lower": -652.82,"count": 1563,"preSum": 3126 },{ "ndv": 1495,"upper": -298.94,"lower": -475.30,"count": 1563,"preSum": 4689 },{ "ndv": 1511,"upper": -127.13,"lower": -298.47,"count": 1563,"preSum": 6252 },{ "ndv": 1501,"upper": 50.91,"lower": -127.09,"count": 1563,"preSum": 7815 },{ "ndv": 1497,"upper": 223.60,"lower": 50.94,"count": 1563,"preSum": 9378 },{ "ndv": 1508,"upper": 394.92,"lower": 223.69,"count": 1563,"preSum": 10941 },{ "ndv": 1502,"upper": 563.12,"lower": 395.03,"count": 1563,"preSum": 12504 },{ "ndv": 1479,"upper": 739.32,"lower": 563.13,"count": 1563,"preSum": 14067 },{ "ndv": 1499,"upper": 910.37,"lower": 739.51,"count": 1564,"preSum": 15630 },{ "ndv": 1493,"upper": 1086.08,"lower": 910.41,"count": 1563,"preSum": 17194 },{ "ndv": 1485,"upper": 1255.67,"lower": 1086.18,"count": 1563,"preSum": 18757 },{ "ndv": 1492,"upper": 1420.29,"lower": 1255.70,"count": 1563,"preSum": 20320 },{ "ndv": 1497,"upper": 1595.65,"lower": 1420.38,"count": 1563,"preSum": 21883 },{ "ndv": 1493,"upper": 1766.71,"lower": 1595.68,"count": 1563,"preSum": 23446 },{ "ndv": 1481,"upper": 1934.09,"lower": 1766.89,"count": 1563,"preSum": 25009 },{ "ndv": 1492,"upper": 2105.48,"lower": 1934.32,"count": 1563,"preSum": 26572 },{ "ndv": 1489,"upper": 2281.65,"lower": 2105.62,"count": 1563,"preSum": 28135 },{ "ndv": 1488,"upper": 2457.42,"lower": 2281.89,"count": 1563,"preSum": 29698 },{ "ndv": 1499,"upper": 2634.09,"lower": 2457.54,"count": 1563,"preSum": 31261 },{ "ndv": 1517,"upper": 2815.07,"lower": 2634.21,"count": 1563,"preSum": 32824 },{ "ndv": 1503,"upper": 2989.28,"lower": 2815.08,"count": 1563,"preSum": 34387 },{ "ndv": 1487,"upper": 3158.97,"lower": 2989.45,"count": 1563,"preSum": 35950 },{ "ndv": 1498,"upper": 3335.05,"lower": 3159.24,"count": 1563,"preSum": 37513 },{ "ndv": 1491,"upper": 3501.16,"lower": 3335.21,"count": 1563,"preSum": 39076 },{ "ndv": 1489,"upper": 3681.52,"lower": 3501.24,"count": 1563,"preSum": 40639 },{ "ndv": 1500,"upper": 3857.04,"lower": 3681.82,"count": 1563,"preSum": 42202 },{ "ndv": 1506,"upper": 4029.60,"lower": 3857.13,"count": 1563,"preSum": 43765 },{ "ndv": 1481,"upper": 4198.67,"lower": 4029.94,"count": 1563,"preSum": 45328 },{ "ndv": 1493,"upper": 4369.90,"lower": 4198.70,"count": 1563,"preSum": 46891 },{ "ndv": 1489,"upper": 4538.57,"lower": 4369.94,"count": 1563,"preSum": 48454 },{ "ndv": 1492,"upper": 4699.74,"lower": 4538.62,"count": 1563,"preSum": 50017 },{ "ndv": 1503,"upper": 4873.20,"lower": 4699.75,"count": 1563,"preSum": 51580 },{ "ndv": 1488,"upper": 5044.80,"lower": 4873.51,"count": 1563,"preSum": 53143 },{ "ndv": 1499,"upper": 5215.71,"lower": 5045.07,"count": 1563,"preSum": 54706 },{ "ndv": 1499,"upper": 5386.72,"lower": 5215.88,"count": 1563,"preSum": 56269 },{ "ndv": 1487,"upper": 5557.19,"lower": 5386.86,"count": 1563,"preSum": 57832 },{ "ndv": 1484,"upper": 5726.46,"lower": 5557.32,"count": 1563,"preSum": 59395 },{ "ndv": 1502,"upper": 5894.15,"lower": 5726.57,"count": 1563,"preSum": 60958 },{ "ndv": 1482,"upper": 6065.71,"lower": 5894.25,"count": 1563,"preSum": 62521 },{ "ndv": 1500,"upper": 6238.60,"lower": 6065.92,"count": 1563,"preSum": 64084 },{ "ndv": 1487,"upper": 6404.32,"lower": 6238.69,"count": 1563,"preSum": 65647 },{ "ndv": 1487,"upper": 6570.77,"lower": 6404.34,"count": 1563,"preSum": 67210 },{ "ndv": 1489,"upper": 6748.23,"lower": 6570.82,"count": 1563,"preSum": 68773 },{ "ndv": 1496,"upper": 6914.18,"lower": 6748.33,"count": 1563,"preSum": 70336 },{ "ndv": 1499,"upper": 7080.44,"lower": 6914.34,"count": 1564,"preSum": 71899 },{ "ndv": 1499,"upper": 7247.69,"lower": 7080.46,"count": 1563,"preSum": 73463 },{ "ndv": 1496,"upper": 7416.55,"lower": 7247.94,"count": 1563,"preSum": 75026 },{ "ndv": 1493,"upper": 7587.99,"lower": 7416.62,"count": 1563,"preSum": 76589 },{ "ndv": 1502,"upper": 7763.33,"lower": 7588.27,"count": 1563,"preSum": 78152 },{ "ndv": 1489,"upper": 7935.53,"lower": 7763.40,"count": 1563,"preSum": 79715 },{ "ndv": 1490,"upper": 8101.62,"lower": 7935.63,"count": 1563,"preSum": 81278 },{ "ndv": 1491,"upper": 8276.87,"lower": 8101.72,"count": 1563,"preSum": 82841 },{ "ndv": 1495,"upper": 8446.39,"lower": 8276.92,"count": 1563,"preSum": 84404 },{ "ndv": 1489,"upper": 8610.19,"lower": 8446.51,"count": 1563,"preSum": 85967 },{ "ndv": 1507,"upper": 8792.95,"lower": 8610.42,"count": 1563,"preSum": 87530 },{ "ndv": 1487,"upper": 8957.39,"lower": 8793.04,"count": 1563,"preSum": 89093 },{ "ndv": 1488,"upper": 9135.99,"lower": 8957.40,"count": 1563,"preSum": 90656 },{ "ndv": 1487,"upper": 9306.78,"lower": 9136.03,"count": 1563,"preSum": 92219 },{ "ndv": 1500,"upper": 9477.67,"lower": 9306.82,"count": 1563,"preSum": 93782 },{ "ndv": 1488,"upper": 9649.75,"lower": 9477.70,"count": 1563,"preSum": 95345 },{ "ndv": 1501,"upper": 9823.96,"lower": 9649.76,"count": 1563,"preSum": 96908 },{ "ndv": 1453,"upper": 9999.86,"lower": 9824.02,"count": 1514,"preSum": 98471 } ],"maxBucketSize": 64,"type": "Double","sampleRate": 0.90777135 }
+  supplier.s_acctbal.null_count:
+    0
+  supplier.s_acctbal.sample_rate:
+    0.010174989
+  supplier.s_address.TOPN:
+    null
+  supplier.s_address.cardinality:
+    6325188
+  supplier.s_address.histogram:
+    { "buckets": [ { "ndv": 1563,"upper": ", ,NLdY8mvXt,9KIhcV","lower": "   cg 4VnlvN2jU9tn1T","count": 1563,"preSum": 0 },{ "ndv": 1563,"upper": "0,fhY6gCXXqhOChpws9Gt","lower": ", aTcdLNxMf8gnxjsxcx5,ayvtSUN61DdVxAt4gZ","count": 1563,"preSum": 1563 },{ "ndv": 1563,"upper": "0Zq0QaodF1UBZuO4Embc","lower": "0,fr,ykC2dT0YzEO0JGwydg0U4","count": 1563,"preSum": 3126 },{ "ndv": 1563,"upper": "2 POK1DxLhsXfeuMn7YKYzMqqM","lower": "0zqo6OurzQmaN5GxHUSWm2nglJ7ChW3","count": 1563,"preSum": 4689 },{ "ndv": 1563,"upper": "3 Cadf Crv","lower": "2 QTlyK5V0,41VmN 0Mtf0VdMP4jWViEkeF","count": 1563,"preSum": 6252 },{ "ndv": 1563,"upper": "4 aqs8a1cr3H64McEoTH6CCfbrH9GN8","lower": "3 cX2 ic7eB5tH2p0BaD2MI2R","count": 1563,"preSum": 7815 },{ "ndv": 1563,"upper": "5 frOg3bkSXc2yii3iLCfVq","lower": "4 GFPc,amPqgnvFJKkkikWYjnJIxGXW0Gyaio","count": 1563,"preSum": 9378 },{ "ndv": 1563,"upper": "60i17MNkuxXv","lower": "5 GQLEVc3xwAVPfoga5h4Ge8yaF","count": 1563,"preSum": 10941 },{ "ndv": 1563,"upper": "718sgIOpY9gXk4s24p","lower": "60I5NP7MHSGnVnd3Nqx2qL80moys","count": 1563,"preSum": 12504 },{ "ndv": 1563,"upper": "80lhK ijyKS6IS","lower": "718t0Vip w ULJQA4qGbVx bPOF1Bax9c","count": 1563,"preSum": 14067 },{ "ndv": 1563,"upper": "9,C6lvXPJZ,FQhWJXFA97xGM3qR,qGDWCQ","lower": "80NEX1JZ90D","count": 1563,"preSum": 15630 },{ "ndv": 1563,"upper": "9zb0BarToUfex9QAGuO","lower": "9,FXi4TEXVNk,oepIBt466owV63BncsKN88a","count": 1563,"preSum": 17193 },{ "ndv": 1563,"upper": "AK8Urbg3CUjD97ZqeOM","lower": "9zB1Z99kNmD2E7Sa4LF","count": 1563,"preSum": 18756 },{ "ndv": 1563,"upper": "b cU,w4Ki5LO27WeTzNR","lower": "ak9ewB99LyauQNggO0TllohqDq","count": 1563,"preSum": 20319 },{ "ndv": 1563,"upper": "bknJNbRKHISpT82CWckF","lower": "b eLpgRW08BIv I3","count": 1563,"preSum": 21882 },{ "ndv": 1563,"upper": "C0FdhNx4jp522avoDHr34SqAuURL","lower": "bknzvQeK,,j0vcWrL4ybPm","count": 1563,"preSum": 23445 },{ "ndv": 1563,"upper": "CKsdgJ8pSW v0Fft0tCwj,w","lower": "c0G7uP9YIL2kpmPl1rhAGS","count": 1563,"preSum": 25008 },{ "ndv": 1563,"upper": "D0Dqso,V0kptn","lower": "CKswf,3nsiDPjHlAtv9C HfAI","count": 1563,"preSum": 26571 },{ "ndv": 1563,"upper": "DkzEJvIVVxTBWfSbFt","lower": "d0DSDuBcFCmu9jVJn,sVnyG","count": 1563,"preSum": 28134 },{ "ndv": 1563,"upper": "e05XwxpU51L n OtsMFjr","lower": "DL,5eHJRF8jOsaJ,tyh","count": 1563,"preSum": 29697 },{ "ndv": 1563,"upper": "El2I7we,049SPrvomUm4hZwJoOhZkvLxLJXgVH","lower": "e0AmK5Spfib dgbwokqeuiFuxn2lOVnrup","count": 1563,"preSum": 31260 },{ "ndv": 1563,"upper": "F0m ,Jk6gxFUCHaXjiyc,7LR,OIZn3IKFmeAHjOy","lower": "EL360Tro5SRX,jBVg0,dK8musM","count": 1563,"preSum": 32823 },{ "ndv": 1563,"upper": "FljhhKDqImDRWIL2z51K5XKn6Qe8J6v7F","lower": "f0MgEcMMPMfEGUq2moPxkE0A2T1tc5vwlr","count": 1563,"preSum": 34386 },{ "ndv": 1563,"upper": "g2gtsRJYt5xGkZ,4CKD7PnUJs2d","lower": "fLKc1jNxgVPfvoapKIQ ejQZl2D6v","count": 1563,"preSum": 35949 },{ "ndv": 1563,"upper": "gMbgr4iK2SM2JeLdJltEHEnOn3c18O7a0LZ","lower": "g2hp7k0y8XhX,p ","count": 1563,"preSum": 37512 },{ "ndv": 1563,"upper": "h2XSn3HQRyK8,cKcceoWymwRlg WEsgtGp7ltaz","lower": "gMBIQm8dwryZ8oBaustd","count": 1563,"preSum": 39075 },{ "ndv": 1563,"upper": "HmKArPJGRj8,gmY95K6ySYGQmMuZHH","lower": "H2y49QXG75d6KBAu63qvrIm MzHK72ospZ,A","count": 1563,"preSum": 40638 },{ "ndv": 1563,"upper": "i3DDzvJNI1P","lower": "HMKblGZtK,oaOEac","count": 1563,"preSum": 42201 },{ "ndv": 1563,"upper": "imRGbmyhdDjbfTQxitp3NrCqiY9KEbN6tuY","lower": "i3DSJy5ORhL1JxdIX","count": 1563,"preSum": 43764 },{ "ndv": 1563,"upper": "j3FbTzy7gYpc,Gjludw4KylNBWLjSHpGhCLG","lower": "iMrk7HUD87at3IIh4rBi","count": 1563,"preSum": 45327 },{ "ndv": 1563,"upper": "JmbjO,KVaMGCcaF","lower": "J3FlGFVQn4ZIVfh hV4G1qpzmACY EzSzME","count": 1563,"preSum": 46890 },{ "ndv": 1563,"upper": "K3JZ3xLkMbFWc26Gr4iHLgZ9YrCwY5pH","lower": "jmBpPvXBAJT9","count": 1563,"preSum": 48453 },{ "ndv": 1563,"upper": "Kmarrj2lXUa,dThvX2x2tKlcPaduxkBwd3yJ","lower": "k3KGy3YdhbFNoCmprrv102Pr aiRX3B1m","count": 1563,"preSum": 50016 },{ "ndv": 1563,"upper": "L2Kx29dU8Ei4CBut","lower": "KMaw9RY8JulDAPB","count": 1563,"preSum": 51579 },{ "ndv": 1563,"upper": "lLXXwOnPRAtskOuhXTYRyZnPRAXz4P50UWpYi","lower": "L2LqBMmxZV jxET 0mEvhDFiy78MTjMb7IwF","count": 1563,"preSum": 53142 },{ "ndv": 1563,"upper": "M1ZxudB0DFMLIPLKPwtzO QmrCZefa","lower": "LlyCyGLVFX5y1IF4wpIlowK35I5tLpZt3C3U8M,4","count": 1563,"preSum": 54705 },{ "ndv": 1563,"upper": "mLUYbnO2aI4OVAD7HPOYN","lower": "m2,uBMCYWi7liO0CvzisxM0Cco 7XowawCj9WxKF","count": 1563,"preSum": 56268 },{ "ndv": 1563,"upper": "n0zbaCEMluqTyxDH3af13ncqO0WSzzF2","lower": "MlvQOCqaUzOVeuTEnNvbi s ","count": 1563,"preSum": 57831 },{ "ndv": 1563,"upper": "NlLzsMPBGMcfDwNmUEBmcDe41UyntYyxbiGWUfgO","lower": "N10ImLsiy3d5VqxcqGax46","count": 1563,"preSum": 59394 },{ "ndv": 1563,"upper": "O0N4fIHIELXYQvqDarlwrd2hqKs","lower": "NLm heWylyopF6","count": 1563,"preSum": 60957 },{ "ndv": 1563,"upper": "OLGihYYny12uc4FWJvBOeGon26G","lower": "o0NIf WZB,9Fbom6cBtDobMnPuLvOdkKKoe","count": 1563,"preSum": 62520 },{ "ndv": 1563,"upper": "p1Mx7ooygPzJJPybFZq5yRNXKwR","lower": "Olgmw93btPPoA0ppHj","count": 1563,"preSum": 64083 },{ "ndv": 1563,"upper": "PLhZHnYBFmWaTsf3ATyDJ68TwTmpoO","lower": "p1mXUxX4Wlv HfdM","count": 1563,"preSum": 65646 },{ "ndv": 1563,"upper": "q0YigG6Nixe7QzbEZRgJCsWl","lower": "plInmQ2b2Hm3jyJivgULHd4","count": 1563,"preSum": 67209 },{ "ndv": 1563,"upper": "qM dwluCOcNOb37ln7ilbPYb8UZbmZmCL PZ","lower": "Q0zJSldJHwB5Iq0qTjR 9X0vN","count": 1563,"preSum": 68772 },{ "ndv": 1563,"upper": "R15TMXJBLYG6JbC,fnTRHmBxb","lower": "qM Ir6lCjtvjjY923wo1tZ","count": 1563,"preSum": 70335 },{ "ndv": 1563,"upper": "RLjweofZA6zJOWttz3d","lower": "R17FmOOMrc,DlQiKrX5","count": 1563,"preSum": 71898 },{ "ndv": 1563,"upper": "s07L2qW10DCSmVvXw bmMm4yTzeRAVXVz3EcL","lower": "rLkAcZoRIttWlBOXvI8qA","count": 1563,"preSum": 73461 },{ "ndv": 1563,"upper": "sl,81OCiLvX,fF2r rfAgPRgSQ","lower": "s08s,CPDVNXi","count": 1563,"preSum": 75024 },{ "ndv": 1563,"upper": "t0KBWnOt2UsbowRifxILCwOO1cyRrbb","lower": "sL,mqRW71dkUNay0RCW","count": 1563,"preSum": 76587 },{ "ndv": 1563,"upper": "TlHRZvvyRcFpRr6wJ9GWl9g71ND,wnrfICprEEp","lower": "t0LsSQF43vI0a,vt Wt29Vt62cfboLhT0","count": 1563,"preSum": 78150 },{ "ndv": 1563,"upper": "U,m3OTOxcSMxW2W","lower": "tliDpFwXBy0Rwsx1T1Q6lpr,f0PkOpEtyuQ6","count": 1563,"preSum": 79713 },{ "ndv": 1563,"upper": "UKvavouonYW","lower": "u,N,TCdSCUHKmkjaL3x6SonwjfT,to3","count": 1563,"preSum": 81276 },{ "ndv": 1563,"upper": "V pXcCiEw9GciWrdBXCIWRhqlADH7D","lower": "ukVhf2GhFD2CT6RXEhX9npo0P7bE6g1U","count": 1563,"preSum": 82839 },{ "ndv": 1563,"upper": "vkNyc2Htc3b1i8Z DKOLNB4y ","lower": "v QHazrZC4xaNWteqBNZ4gK4qlUv","count": 1563,"preSum": 84402 },{ "ndv": 1563,"upper": "W Gaj,AGUpWM0CVVMQYq4C1RANlTweYnuGsq","lower": "VKo6F7T9dO2sIs3Hho","count": 1563,"preSum": 85965 },{ "ndv": 1563,"upper": "wkchN20pV0OblWAi5aT,J","lower": "W h,YQYRwOHfB2Vjsv90iWWvXvEaNBboja0sFH","count": 1563,"preSum": 87528 },{ "ndv": 1563,"upper": "x,5PRZsDhF","lower": "WkcONAO7Fx0TRCXNY","count": 1563,"preSum": 89091 },{ "ndv": 1563,"upper": "Xk,kHVHg2XVCZKQlr","lower": "X,5QF9VoVsd69zE e","count": 1563,"preSum": 90654 },{ "ndv": 1563,"upper": "Y PVZF9i59X3 xazg25PTZ6kmCeDQV","lower": "XK0FveOGFhb,jkwIwMcRlQ2ukc1,Ut","count": 1563,"preSum": 92217 },{ "ndv": 1563,"upper": "YkcZ2ZxgnqAj7Rh SyTpsYEcg0y","lower": "y q8nA5HUyzTEDrK ,","count": 1563,"preSum": 93780 },{ "ndv": 1563,"upper": "z mW1,zl 9J5rqAvXU,YO","lower": "YKDHz7281vCTw w,5KSkV","count": 1563,"preSum": 95343 },{ "ndv": 1563,"upper": "ZJOoS8aOUj7t EKrPl d0SSt2","lower": "z n0scmWI 3JXW","count": 1563,"preSum": 96906 },{ "ndv": 1532,"upper": "ZZzWW90GBmhzJB5g","lower": "zJp86CNcs8NIXyAdKpRX","count": 1532,"preSum": 98469 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90777135 }
+  supplier.s_address.null_count:
+    0
+  supplier.s_address.sample_rate:
+    0.010174989
+  supplier.s_comment.TOPN:
+    null
+  supplier.s_comment.cardinality:
+    6124464
+  supplier.s_comment.histogram:
+    { "buckets": [ { "ndv": 1563,"upper": " asymptotes. regular, ironic foxes are carefully. package","lower": " abCustomer uriously final theodolites are furiously against the quickly silRecommends regular, e","count": 1563,"preSum": 0 },{ "ndv": 1563,"upper": " carefully ironic deposits. carefully final requests integrate blithely pending deposits.","lower": " asymptotes. slyly regular packages according to the closely ironic frays thrash slyly according to ","count": 1563,"preSum": 1563 },{ "ndv": 1562,"upper": " excuses integrate closely iron","lower": " carefully ironic deposits. dolphins wake slyly. pending, fluffy theodolites cajole. final","count": 1563,"preSum": 3126 },{ "ndv": 1562,"upper": " furiously regular deposits. blithely ironic requests around the blithely","lower": " excuses integrate quickly carefully regular packages; iron","count": 1563,"preSum": 4689 },{ "ndv": 1563,"upper": " never except the ironic, ironic pa","lower": " furiously regular deposits. ironic, pending depend","count": 1563,"preSum": 6252 },{ "ndv": 1562,"upper": " regular deposits. carefully unusual accounts haggle ironic,","lower": " never final packages cajole against the blithely even deposits. furiously final deposits ca","count": 1563,"preSum": 7815 },{ "ndv": 1563,"upper": " slyly outside the slyly busy reque","lower": " regular deposits. express ","count": 1563,"preSum": 9378 },{ "ndv": 1563,"upper": " theodolites haggle slyly. regular pinto beans abo","lower": " slyly packages. ironic ideas nag. requests affix carefully pending excuses. i","count": 1563,"preSum": 10941 },{ "ndv": 1563,"upper": ". bravely even deposits around the furiously regular deposits believe sl","lower": " theodolites haggle-- asymptotes alongside of the special, final foxes cajole furiously ","count": 1563,"preSum": 12504 },{ "ndv": 1562,"upper": "above the regular, regular deposits. furiously final requests haggle slyly ","lower": ". busily bold sheaves sleep slyly. slyly even deposits haggle blithely. final packages cajo","count": 1563,"preSum": 14067 },{ "ndv": 1562,"upper": "ages. carefully final packages sleep at the quickly even dependencies. qui","lower": "above the regular, regular requests eat express p","count": 1563,"preSum": 15630 },{ "ndv": 1563,"upper": "al requests serve fluffily. quickly even dolphins ","lower": "ages. carefully ironic accounts sleep across the unus","count": 1563,"preSum": 17193 },{ "ndv": 1562,"upper": "arefully among the blithely even foxes. re","lower": "al requests sleep blithely idea","count": 1563,"preSum": 18756 },{ "ndv": 1563,"upper": "blithely express excuses are carefully. quickly f","lower": "arefully among the blithely regular instructions. fluffily p","count": 1563,"preSum": 20319 },{ "ndv": 1563,"upper": "cajole. carefully express deposits are packa","lower": "blithely express foxes are accounts. doggedly even acco","count": 1563,"preSum": 21882 },{ "ndv": 1563,"upper": "ckages sleep against the speci","lower": "cajole. carefully final requests solve. blithely ironic instructions believe","count": 1563,"preSum": 23445 },{ "ndv": 1562,"upper": "Customer ly special pinto beans. regular, express deRecommendse fu","lower": "ckages sleep among the slyly express excuses. special, regular pinto beans are carefully: express d","count": 1563,"preSum": 25008 },{ "ndv": 1563,"upper": "ding to the ironic theodolites. dolphins wake bravely","lower": "Customer lyly regular dComplaints slyly above t","count": 1563,"preSum": 26571 },{ "ndv": 1563,"upper": "e furiously ruthlessly final depo","lower": "ding to the ironic, even requests cajole slyly up the carefully","count": 1563,"preSum": 28134 },{ "ndv": 1563,"upper": "ecial accounts x-ray carefully. platelets nag furiously at the regular asymptotes. iron","lower": "e furiously silent foxes. carefully express theodolites wake.","count": 1563,"preSum": 29697 },{ "ndv": 1562,"upper": "egular requests. carefully final instructions use blithely daringly final ideas. pending, expre","lower": "ecial accounts. busy, even theodolites cajole quickly final ideas.","count": 1563,"preSum": 31260 },{ "ndv": 1563,"upper": "ent, idle deposits believe blithely. quickly unusual foxes cajole carefully.","lower": "egular requests. carefully pending accounts after the slyly final accounts wake flu","count": 1563,"preSum": 32823 },{ "ndv": 1562,"upper": "es affix silently along the final, express ideas. carefully express pack","lower": "ent, pending packages doz","count": 1563,"preSum": 34386 },{ "ndv": 1563,"upper": "ests wake furiously after the instructions; quiet asymptotes wake carefully. slyly final accounts","lower": "es affix slyly after the quickly pending dolphins. carefully regular theodolites sleep slyly","count": 1563,"preSum": 35949 },{ "ndv": 1562,"upper": "fily ironic foxes kindle doggedly. regular, final deposits nod. slyly unusual requests sleep abo","lower": "ests wake furiously after the packages. fina","count": 1563,"preSum": 37512 },{ "ndv": 1562,"upper": "fully regular accounts use. blithely ironic theodolites promise slyl","lower": "fily ironic foxes sleep slyly agai","count": 1563,"preSum": 39075 },{ "ndv": 1562,"upper": "ges nag fluffily after th","lower": "fully regular accounts. carefully final fo","count": 1563,"preSum": 40638 },{ "ndv": 1563,"upper": "haggle furiously. slyly expres","lower": "ges nag fluffily. quickly express platelets serve enticingly accordi","count": 1563,"preSum": 42201 },{ "ndv": 1563,"upper": "heodolites solve according to the ironic packages. quickly regular grouches mold slyly ir","lower": "haggle furiously. unusual, even requests haggle blithel","count": 1563,"preSum": 43764 },{ "ndv": 1563,"upper": "ideas use. regular theodolites are around the unusual packages; qui","lower": "heodolites solve carefully above the deposits. furiously ironic sentiments are accor","count": 1563,"preSum": 45327 },{ "ndv": 1563,"upper": "ing, ironic requests was along the blithely express instructions. express dug","lower": "ideas wake across the ironic deposits. even requests cajole above the slyly special accoun","count": 1563,"preSum": 46890 },{ "ndv": 1563,"upper": "ironic frays haggle slyly. foxes sleep slyly. blithely ","lower": "ing, regular foxes would cajole slyly after the b","count": 1563,"preSum": 48453 },{ "ndv": 1563,"upper": "jole silently. blithely bol","lower": "ironic frets about the doggedly quick multipliers cajole carefully after the ","count": 1563,"preSum": 50016 },{ "ndv": 1563,"upper": "l pinto beans. carefully final deposits should are again","lower": "jole slyly about the blithely silent warthogs. unusual, final orbit","count": 1563,"preSum": 51579 },{ "ndv": 1563,"upper": "le slyly. slyly bold instructions alongside of the quickly pending depo","lower": "l pinto beans. even, ironic packag","count": 1563,"preSum": 53142 },{ "ndv": 1563,"upper": "lly regular frays cajole final, regular packages. quickly spe","lower": "le slyly; regular pains integrate furiously. pending, even platelets wake bl","count": 1563,"preSum": 54705 },{ "ndv": 1563,"upper": "ly express theodolites sleep ","lower": "lly regular grouches cajole slyly after the thinly blithe instructions. carefully special the","count": 1563,"preSum": 56268 },{ "ndv": 1563,"upper": "ly. blithely close foxes use carefully final excuses. careful tithes along ","lower": "ly express theodolites sleep furiously after the final, dogged foxes. express, ironic request","count": 1563,"preSum": 57831 },{ "ndv": 1563,"upper": "nag carefully. slyly final packages haggle q","lower": "ly. blithely even asymptotes maintain furiously. fluffily ironic packages wake carefully.","count": 1563,"preSum": 59394 },{ "ndv": 1563,"upper": "ng, final deposits sleep furiously regular acc","lower": "nag carefully; carefully special instructions wake slyly blithely final deposi","count": 1563,"preSum": 60957 },{ "ndv": 1563,"upper": "ntegrate blithely after the fluffily pending accounts. carefully even ideas across the fu","lower": "ng, final dolphins are alongside of the fi","count": 1563,"preSum": 62520 },{ "ndv": 1563,"upper": "ogs cajole blithely. final requests eat carefully accounts. deposits integrate furiously: express, ","lower": "ntegrate blithely after the ironic platelets. blithely regular","count": 1563,"preSum": 64083 },{ "ndv": 1563,"upper": "ons. slyly unusual foxes haggle. quickly regular gifts believe doggedly. unusual requ","lower": "ogs cajole carefully above the ironic","count": 1563,"preSum": 65646 },{ "ndv": 1562,"upper": "ously about the slyly regular accounts. final requests sleep quickly. even patte","lower": "ons. special foxes may boo","count": 1563,"preSum": 67209 },{ "ndv": 1563,"upper": "pains haggle slyly requests. furiously express ideas sublate ac","lower": "ously about the slyly special realms. final ex","count": 1563,"preSum": 68772 },{ "ndv": 1562,"upper": "press requests. packages sleep about the slyly unu","lower": "pains sleep ironically inside the furiously silent instructions. quietly bold dolph","count": 1563,"preSum": 70335 },{ "ndv": 1563,"upper": "r, unusual deposits boost iro","lower": "press requests. regular, express excuses boost blithely. ironic ideas run quic","count": 1563,"preSum": 71898 },{ "ndv": 1562,"upper": "requests against the ironic, regular ideas should ","lower": "r, unusual deposits cajole","count": 1563,"preSum": 73461 },{ "ndv": 1562,"upper": "ronic packages haggle. idle deposits after the close instructions kindle slyly final acco","lower": "requests along the even, ironic dependencies poach thinly unusual, regula","count": 1563,"preSum": 75024 },{ "ndv": 1563,"upper": "s cajole quickly according to the regular, regular dependencies. ","lower": "ronic packages impress-- regul","count": 1563,"preSum": 76587 },{ "ndv": 1562,"upper": "s, blithe packages. carefully ironic packages ","lower": "s cajole quickly across the final ideas! fina","count": 1563,"preSum": 78150 },{ "ndv": 1563,"upper": "side of the blithely ironic instructions. pinto beans ","lower": "s, bold theodolites use at the blithely ","count": 1563,"preSum": 79713 },{ "ndv": 1563,"upper": "slyly fluffily regular packages. fluffily regular platelets cajole slyly furiously e","lower": "side of the blithely regular deposits. slyly express requests among the slyly fi","count": 1563,"preSum": 81276 },{ "ndv": 1563,"upper": "sts. carefully bold platelets","lower": "slyly fluffily slow foxes. b","count": 1563,"preSum": 82839 },{ "ndv": 1563,"upper": "tes until the carefully ironic","lower": "sts. carefully final accounts haggle. ","count": 1563,"preSum": 84402 },{ "ndv": 1563,"upper": "theodolites detect quietly. slyly regular accounts","lower": "tes use about the furiousl","count": 1563,"preSum": 85965 },{ "ndv": 1563,"upper": "ts haggle bravely according to the somas. unusual deposits are never special a","lower": "theodolites haggle along the final, bold pinto ","count": 1563,"preSum": 87528 },{ "ndv": 1562,"upper": "uests wake even, express packages. blithely","lower": "ts haggle carefully above t","count": 1563,"preSum": 89091 },{ "ndv": 1563,"upper": "ully furiously ironic packages. regular packages cajole; quickly furious instructi","lower": "uests wake final, final requests! blithely expr","count": 1563,"preSum": 90654 },{ "ndv": 1563,"upper": "urts? ironic, special theodol","lower": "ully furiously ironic pinto beans. carefully even a","count": 1563,"preSum": 92217 },{ "ndv": 1563,"upper": "ven pinto beans nag furiousl","lower": "us accounts affix furiously above the carefully final pinto ","count": 1563,"preSum": 93780 },{ "ndv": 1562,"upper": "y bold requests against the ironic asymptotes ","lower": "ven pinto beans should have to wake","count": 1563,"preSum": 95343 },{ "ndv": 1563,"upper": "y regular pinto beans. blithely special r","lower": "y bold requests are furiously furiously ironic accounts. even reques","count": 1563,"preSum": 96906 },{ "ndv": 1532,"upper": "zzle. regular requests detect quickly. bold, final accounts across the slyly eve","lower": "y regular pinto beans. bold requ","count": 1532,"preSum": 98469 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90777135 }
+  supplier.s_comment.null_count:
+    0
+  supplier.s_comment.sample_rate:
+    0.010174989
+  supplier.s_name.TOPN:
+    null
+  supplier.s_name.cardinality:
+    6361440
+  supplier.s_name.histogram:
+    { "buckets": [ { "ndv": 1563,"upper": "Supplier#000001850","lower": "Supplier#000000001","count": 1563,"preSum": 0 },{ "ndv": 1563,"upper": "Supplier#000004064","lower": "Supplier#000001852","count": 1563,"preSum": 1563 },{ "ndv": 1563,"upper": "Supplier#000006498","lower": "Supplier#000004065","count": 1563,"preSum": 3126 },{ "ndv": 1563,"upper": "Supplier#000009512","lower": "Supplier#000006499","count": 1563,"preSum": 4689 },{ "ndv": 1563,"upper": "Supplier#000053046","lower": "Supplier#000009514","count": 1563,"preSum": 6252 },{ "ndv": 1563,"upper": "Supplier#000258953","lower": "Supplier#000053250","count": 1563,"preSum": 7815 },{ "ndv": 1563,"upper": "Supplier#000483216","lower": "Supplier#000258968","count": 1563,"preSum": 9378 },{ "ndv": 1563,"upper": "Supplier#000647963","lower": "Supplier#000483480","count": 1563,"preSum": 10941 },{ "ndv": 1563,"upper": "Supplier#000830873","lower": "Supplier#000647964","count": 1563,"preSum": 12504 },{ "ndv": 1563,"upper": "Supplier#001003393","lower": "Supplier#000830932","count": 1563,"preSum": 14067 },{ "ndv": 1563,"upper": "Supplier#001143526","lower": "Supplier#001003826","count": 1563,"preSum": 15630 },{ "ndv": 1563,"upper": "Supplier#001271490","lower": "Supplier#001143733","count": 1563,"preSum": 17193 },{ "ndv": 1563,"upper": "Supplier#001506735","lower": "Supplier#001271491","count": 1563,"preSum": 18756 },{ "ndv": 1563,"upper": "Supplier#001636292","lower": "Supplier#001507247","count": 1563,"preSum": 20319 },{ "ndv": 1563,"upper": "Supplier#001791419","lower": "Supplier#001636294","count": 1563,"preSum": 21882 },{ "ndv": 1563,"upper": "Supplier#001950168","lower": "Supplier#001791540","count": 1563,"preSum": 23445 },{ "ndv": 1563,"upper": "Supplier#002153084","lower": "Supplier#001950180","count": 1563,"preSum": 25008 },{ "ndv": 1563,"upper": "Supplier#002331072","lower": "Supplier#002153103","count": 1563,"preSum": 26571 },{ "ndv": 1563,"upper": "Supplier#002511324","lower": "Supplier#002331073","count": 1563,"preSum": 28134 },{ "ndv": 1563,"upper": "Supplier#002684870","lower": "Supplier#002511325","count": 1563,"preSum": 29697 },{ "ndv": 1563,"upper": "Supplier#002777124","lower": "Supplier#002684900","count": 1563,"preSum": 31260 },{ "ndv": 1563,"upper": "Supplier#002982595","lower": "Supplier#002777129","count": 1563,"preSum": 32823 },{ "ndv": 1563,"upper": "Supplier#003171630","lower": "Supplier#002982624","count": 1563,"preSum": 34386 },{ "ndv": 1563,"upper": "Supplier#003356564","lower": "Supplier#003171719","count": 1563,"preSum": 35949 },{ "ndv": 1563,"upper": "Supplier#003535684","lower": "Supplier#003356723","count": 1563,"preSum": 37512 },{ "ndv": 1563,"upper": "Supplier#003692605","lower": "Supplier#003535716","count": 1563,"preSum": 39075 },{ "ndv": 1563,"upper": "Supplier#003878838","lower": "Supplier#003692633","count": 1563,"preSum": 40638 },{ "ndv": 1563,"upper": "Supplier#004016669","lower": "Supplier#003878938","count": 1563,"preSum": 42201 },{ "ndv": 1563,"upper": "Supplier#004145795","lower": "Supplier#004016670","count": 1563,"preSum": 43764 },{ "ndv": 1563,"upper": "Supplier#004300901","lower": "Supplier#004145813","count": 1563,"preSum": 45327 },{ "ndv": 1563,"upper": "Supplier#004480489","lower": "Supplier#004301000","count": 1563,"preSum": 46890 },{ "ndv": 1563,"upper": "Supplier#004653315","lower": "Supplier#004480490","count": 1563,"preSum": 48453 },{ "ndv": 1563,"upper": "Supplier#004785480","lower": "Supplier#004653346","count": 1563,"preSum": 50016 },{ "ndv": 1563,"upper": "Supplier#004931244","lower": "Supplier#004785558","count": 1563,"preSum": 51579 },{ "ndv": 1563,"upper": "Supplier#005087484","lower": "Supplier#004931261","count": 1563,"preSum": 53142 },{ "ndv": 1563,"upper": "Supplier#005276991","lower": "Supplier#005087485","count": 1563,"preSum": 54705 },{ "ndv": 1563,"upper": "Supplier#005483793","lower": "Supplier#005277014","count": 1563,"preSum": 56268 },{ "ndv": 1563,"upper": "Supplier#005611904","lower": "Supplier#005483870","count": 1563,"preSum": 57831 },{ "ndv": 1563,"upper": "Supplier#005764332","lower": "Supplier#005611938","count": 1563,"preSum": 59394 },{ "ndv": 1563,"upper": "Supplier#005935456","lower": "Supplier#005764333","count": 1563,"preSum": 60957 },{ "ndv": 1563,"upper": "Supplier#006137053","lower": "Supplier#005935473","count": 1563,"preSum": 62520 },{ "ndv": 1563,"upper": "Supplier#006300509","lower": "Supplier#006137084","count": 1563,"preSum": 64083 },{ "ndv": 1563,"upper": "Supplier#006460653","lower": "Supplier#006300592","count": 1563,"preSum": 65646 },{ "ndv": 1563,"upper": "Supplier#006617328","lower": "Supplier#006460654","count": 1563,"preSum": 67209 },{ "ndv": 1563,"upper": "Supplier#006796378","lower": "Supplier#006617403","count": 1563,"preSum": 68772 },{ "ndv": 1563,"upper": "Supplier#007011421","lower": "Supplier#006796410","count": 1563,"preSum": 70335 },{ "ndv": 1563,"upper": "Supplier#007176767","lower": "Supplier#007011426","count": 1563,"preSum": 71898 },{ "ndv": 1563,"upper": "Supplier#007366028","lower": "Supplier#007176844","count": 1563,"preSum": 73461 },{ "ndv": 1563,"upper": "Supplier#007513845","lower": "Supplier#007366182","count": 1563,"preSum": 75024 },{ "ndv": 1563,"upper": "Supplier#007693552","lower": "Supplier#007514025","count": 1563,"preSum": 76587 },{ "ndv": 1563,"upper": "Supplier#007877152","lower": "Supplier#007693570","count": 1563,"preSum": 78150 },{ "ndv": 1563,"upper": "Supplier#008035878","lower": "Supplier#007877900","count": 1563,"preSum": 79713 },{ "ndv": 1563,"upper": "Supplier#008206082","lower": "Supplier#008035928","count": 1563,"preSum": 81276 },{ "ndv": 1563,"upper": "Supplier#008333763","lower": "Supplier#008206218","count": 1563,"preSum": 82839 },{ "ndv": 1563,"upper": "Supplier#008549135","lower": "Supplier#008333792","count": 1563,"preSum": 84402 },{ "ndv": 1563,"upper": "Supplier#008696495","lower": "Supplier#008549420","count": 1563,"preSum": 85965 },{ "ndv": 1563,"upper": "Supplier#008854051","lower": "Supplier#008696503","count": 1563,"preSum": 87528 },{ "ndv": 1563,"upper": "Supplier#008988611","lower": "Supplier#008854299","count": 1563,"preSum": 89091 },{ "ndv": 1563,"upper": "Supplier#009202397","lower": "Supplier#008988640","count": 1563,"preSum": 90654 },{ "ndv": 1563,"upper": "Supplier#009397081","lower": "Supplier#009202417","count": 1563,"preSum": 92217 },{ "ndv": 1563,"upper": "Supplier#009598153","lower": "Supplier#009397084","count": 1563,"preSum": 93780 },{ "ndv": 1563,"upper": "Supplier#009743118","lower": "Supplier#009598154","count": 1563,"preSum": 95343 },{ "ndv": 1563,"upper": "Supplier#009855907","lower": "Supplier#009743646","count": 1563,"preSum": 96906 },{ "ndv": 1532,"upper": "Supplier#009999884","lower": "Supplier#009856008","count": 1532,"preSum": 98469 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90777135 }
+  supplier.s_name.null_count:
+    0
+  supplier.s_name.sample_rate:
+    0.010174989
+  supplier.s_nationkey.TOPN:
+    { "countArr": [ 4043,4160,4006,4001,4046,4036,4083,4095,4021,4016,4052,4057,4054,4014 ],"valueArr": [ 1,2,3,6,7,8,9,12,14,16,17,18,21,22 ],"type": "Int","sampleRate": 0.9077713528381187 }
+  supplier.s_nationkey.cardinality:
+    25
+  supplier.s_nationkey.histogram:
+    { "buckets": [ { "ndv": 1,"upper": 0,"lower": 0,"count": 3989,"preSum": 0 },{ "ndv": 1,"upper": 4,"lower": 4,"count": 3922,"preSum": 3989 },{ "ndv": 1,"upper": 5,"lower": 5,"count": 3837,"preSum": 7911 },{ "ndv": 1,"upper": 10,"lower": 10,"count": 3906,"preSum": 11748 },{ "ndv": 1,"upper": 11,"lower": 11,"count": 3930,"preSum": 15654 },{ "ndv": 1,"upper": 13,"lower": 13,"count": 3872,"preSum": 19584 },{ "ndv": 1,"upper": 15,"lower": 15,"count": 3993,"preSum": 23456 },{ "ndv": 1,"upper": 19,"lower": 19,"count": 3989,"preSum": 27449 },{ "ndv": 1,"upper": 20,"lower": 20,"count": 3987,"preSum": 31438 },{ "ndv": 1,"upper": 23,"lower": 23,"count": 3943,"preSum": 35425 },{ "ndv": 1,"upper": 24,"lower": 24,"count": 3949,"preSum": 39368 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90777135 }
+  supplier.s_nationkey.null_count:
+    0
+  supplier.s_nationkey.sample_rate:
+    0.010174989
+  supplier.s_phone.TOPN:
+    null
+  supplier.s_phone.cardinality:
+    6254422
+  supplier.s_phone.histogram:
+    { "buckets": [ { "ndv": 1563,"upper": "10-449-809-3862","lower": "10-100-266-7476","count": 1563,"preSum": 0 },{ "ndv": 1563,"upper": "10-793-262-2962","lower": "10-449-954-4690","count": 1563,"preSum": 1563 },{ "ndv": 1563,"upper": "11-257-146-4844","lower": "10-793-314-1058","count": 1563,"preSum": 3126 },{ "ndv": 1563,"upper": "11-607-587-9331","lower": "11-257-471-1718","count": 1563,"preSum": 4689 },{ "ndv": 1563,"upper": "11-951-886-3215","lower": "11-608-338-7486","count": 1563,"preSum": 6252 },{ "ndv": 1563,"upper": "12-394-144-4005","lower": "11-952-231-1857","count": 1563,"preSum": 7815 },{ "ndv": 1563,"upper": "12-725-177-1373","lower": "12-394-333-1854","count": 1563,"preSum": 9378 },{ "ndv": 1563,"upper": "13-169-910-6786","lower": "12-725-368-5158","count": 1563,"preSum": 10941 },{ "ndv": 1563,"upper": "13-517-283-5538","lower": "13-169-911-6787","count": 1563,"preSum": 12504 },{ "ndv": 1563,"upper": "13-874-360-9233","lower": "13-517-374-6414","count": 1563,"preSum": 14067 },{ "ndv": 1563,"upper": "14-326-907-5704","lower": "13-874-668-2659","count": 1563,"preSum": 15630 },{ "ndv": 1563,"upper": "14-680-821-9775","lower": "14-327-120-9632","count": 1563,"preSum": 17193 },{ "ndv": 1563,"upper": "15-143-543-2358","lower": "14-680-851-9453","count": 1563,"preSum": 18756 },{ "ndv": 1563,"upper": "15-528-877-5652","lower": "15-143-826-5409","count": 1563,"preSum": 20319 },{ "ndv": 1563,"upper": "15-886-265-5484","lower": "15-528-932-3507","count": 1563,"preSum": 21882 },{ "ndv": 1563,"upper": "16-335-601-1171","lower": "15-886-290-1422","count": 1563,"preSum": 23445 },{ "ndv": 1563,"upper": "16-685-932-5851","lower": "16-335-844-9797","count": 1563,"preSum": 25008 },{ "ndv": 1563,"upper": "17-142-812-4673","lower": "16-686-400-8373","count": 1563,"preSum": 26571 },{ "ndv": 1563,"upper": "17-482-626-4174","lower": "17-142-850-9335","count": 1563,"preSum": 28134 },{ "ndv": 1563,"upper": "17-826-654-1306","lower": "17-482-848-2673","count": 1563,"preSum": 29697 },{ "ndv": 1563,"upper": "18-272-780-5807","lower": "17-826-914-4766","count": 1563,"preSum": 31260 },{ "ndv": 1563,"upper": "18-622-127-8119","lower": "18-272-944-8602","count": 1563,"preSum": 32823 },{ "ndv": 1563,"upper": "18-979-554-8348","lower": "18-622-172-4584","count": 1563,"preSum": 34386 },{ "ndv": 1563,"upper": "19-415-856-7881","lower": "18-979-906-4273","count": 1563,"preSum": 35949 },{ "ndv": 1563,"upper": "19-762-494-6962","lower": "19-415-890-1172","count": 1563,"preSum": 37512 },{ "ndv": 1563,"upper": "20-216-558-7043","lower": "19-762-861-3110","count": 1563,"preSum": 39075 },{ "ndv": 1563,"upper": "20-577-456-9995","lower": "20-216-636-4032","count": 1563,"preSum": 40638 },{ "ndv": 1563,"upper": "20-945-122-2933","lower": "20-577-959-8291","count": 1563,"preSum": 42201 },{ "ndv": 1563,"upper": "21-388-845-7056","lower": "20-945-336-2340","count": 1563,"preSum": 43764 },{ "ndv": 1563,"upper": "21-752-202-8257","lower": "21-388-999-5994","count": 1563,"preSum": 45327 },{ "ndv": 1563,"upper": "22-203-542-1017","lower": "21-752-590-1894","count": 1563,"preSum": 46890 },{ "ndv": 1563,"upper": "22-547-348-2331","lower": "22-203-596-3566","count": 1563,"preSum": 48453 },{ "ndv": 1563,"upper": "22-896-204-5171","lower": "22-547-685-5761","count": 1563,"preSum": 50016 },{ "ndv": 1563,"upper": "23-347-493-6569","lower": "22-896-774-2560","count": 1563,"preSum": 51579 },{ "ndv": 1563,"upper": "23-727-904-5971","lower": "23-347-546-8517","count": 1563,"preSum": 53142 },{ "ndv": 1563,"upper": "24-180-738-4696","lower": "23-728-278-8885","count": 1563,"preSum": 54705 },{ "ndv": 1563,"upper": "24-524-986-8756","lower": "24-181-159-5103","count": 1563,"preSum": 56268 },{ "ndv": 1563,"upper": "24-873-490-2508","lower": "24-525-363-4485","count": 1563,"preSum": 57831 },{ "ndv": 1563,"upper": "25-329-531-7534","lower": "24-873-515-8730","count": 1563,"preSum": 59394 },{ "ndv": 1563,"upper": "25-686-363-5782","lower": "25-330-128-2316","count": 1563,"preSum": 60957 },{ "ndv": 1563,"upper": "26-128-837-5709","lower": "25-686-709-5167","count": 1563,"preSum": 62520 },{ "ndv": 1563,"upper": "26-476-975-6335","lower": "26-129-134-4105","count": 1563,"preSum": 64083 },{ "ndv": 1563,"upper": "26-833-384-3747","lower": "26-477-100-7094","count": 1563,"preSum": 65646 },{ "ndv": 1563,"upper": "27-277-943-8351","lower": "26-833-440-5483","count": 1563,"preSum": 67209 },{ "ndv": 1563,"upper": "27-626-904-3406","lower": "27-278-261-4723","count": 1563,"preSum": 68772 },{ "ndv": 1563,"upper": "27-977-494-1963","lower": "27-626-994-4952","count": 1563,"preSum": 70335 },{ "ndv": 1563,"upper": "28-420-710-3493","lower": "27-977-536-2220","count": 1563,"preSum": 71898 },{ "ndv": 1563,"upper": "28-773-137-4302","lower": "28-420-712-1197","count": 1563,"preSum": 73461 },{ "ndv": 1563,"upper": "29-213-744-4539","lower": "28-773-182-4576","count": 1563,"preSum": 75024 },{ "ndv": 1563,"upper": "29-557-783-8312","lower": "29-213-823-3411","count": 1563,"preSum": 76587 },{ "ndv": 1563,"upper": "29-926-231-7372","lower": "29-557-798-5113","count": 1563,"preSum": 78150 },{ "ndv": 1563,"upper": "30-374-802-7102","lower": "29-926-569-9761","count": 1563,"preSum": 79713 },{ "ndv": 1563,"upper": "30-730-919-7120","lower": "30-375-268-8925","count": 1563,"preSum": 81276 },{ "ndv": 1563,"upper": "31-186-385-2516","lower": "30-731-346-3837","count": 1563,"preSum": 82839 },{ "ndv": 1563,"upper": "31-539-388-7434","lower": "31-186-456-2607","count": 1563,"preSum": 84402 },{ "ndv": 1563,"upper": "31-874-557-7873","lower": "31-539-413-2374","count": 1563,"preSum": 85965 },{ "ndv": 1563,"upper": "32-331-361-9581","lower": "31-874-704-5907","count": 1563,"preSum": 87528 },{ "ndv": 1563,"upper": "32-669-321-7344","lower": "32-331-385-6489","count": 1563,"preSum": 89091 },{ "ndv": 1563,"upper": "33-123-269-3408","lower": "32-669-661-7325","count": 1563,"preSum": 90654 },{ "ndv": 1563,"upper": "33-484-154-9190","lower": "33-123-607-3331","count": 1563,"preSum": 92217 },{ "ndv": 1563,"upper": "33-836-567-2829","lower": "33-484-566-2159","count": 1563,"preSum": 93780 },{ "ndv": 1563,"upper": "34-292-865-2856","lower": "33-836-660-1680","count": 1563,"preSum": 95343 },{ "ndv": 1563,"upper": "34-651-309-7291","lower": "34-293-585-6183","count": 1563,"preSum": 96906 },{ "ndv": 1532,"upper": "34-999-903-5682","lower": "34-651-499-7523","count": 1532,"preSum": 98469 } ],"maxBucketSize": 64,"type": "String","sampleRate": 0.90777135 }
+  supplier.s_phone.null_count:
+    0
+  supplier.s_phone.sample_rate:
+    0.010174989
+  supplier.s_suppkey.TOPN:
+    null
+  supplier.s_suppkey.cardinality:
+    6222516
+  supplier.s_suppkey.histogram:
+    { "buckets": [ { "ndv": 1563,"upper": 1850,"lower": 1,"count": 1563,"preSum": 0 },{ "ndv": 1563,"upper": 4064,"lower": 1852,"count": 1563,"preSum": 1563 },{ "ndv": 1563,"upper": 6498,"lower": 4065,"count": 1563,"preSum": 3126 },{ "ndv": 1563,"upper": 9512,"lower": 6499,"count": 1563,"preSum": 4689 },{ "ndv": 1563,"upper": 53046,"lower": 9514,"count": 1563,"preSum": 6252 },{ "ndv": 1563,"upper": 258953,"lower": 53250,"count": 1563,"preSum": 7815 },{ "ndv": 1563,"upper": 483216,"lower": 258968,"count": 1563,"preSum": 9378 },{ "ndv": 1563,"upper": 647963,"lower": 483480,"count": 1563,"preSum": 10941 },{ "ndv": 1563,"upper": 830873,"lower": 647964,"count": 1563,"preSum": 12504 },{ "ndv": 1563,"upper": 1003393,"lower": 830932,"count": 1563,"preSum": 14067 },{ "ndv": 1563,"upper": 1143526,"lower": 1003826,"count": 1563,"preSum": 15630 },{ "ndv": 1563,"upper": 1271490,"lower": 1143733,"count": 1563,"preSum": 17193 },{ "ndv": 1563,"upper": 1506735,"lower": 1271491,"count": 1563,"preSum": 18756 },{ "ndv": 1563,"upper": 1636292,"lower": 1507247,"count": 1563,"preSum": 20319 },{ "ndv": 1563,"upper": 1791419,"lower": 1636294,"count": 1563,"preSum": 21882 },{ "ndv": 1563,"upper": 1950168,"lower": 1791540,"count": 1563,"preSum": 23445 },{ "ndv": 1563,"upper": 2153084,"lower": 1950180,"count": 1563,"preSum": 25008 },{ "ndv": 1563,"upper": 2331072,"lower": 2153103,"count": 1563,"preSum": 26571 },{ "ndv": 1563,"upper": 2511324,"lower": 2331073,"count": 1563,"preSum": 28134 },{ "ndv": 1563,"upper": 2684870,"lower": 2511325,"count": 1563,"preSum": 29697 },{ "ndv": 1563,"upper": 2777124,"lower": 2684900,"count": 1563,"preSum": 31260 },{ "ndv": 1563,"upper": 2982595,"lower": 2777129,"count": 1563,"preSum": 32823 },{ "ndv": 1563,"upper": 3171630,"lower": 2982624,"count": 1563,"preSum": 34386 },{ "ndv": 1563,"upper": 3356564,"lower": 3171719,"count": 1563,"preSum": 35949 },{ "ndv": 1563,"upper": 3535684,"lower": 3356723,"count": 1563,"preSum": 37512 },{ "ndv": 1563,"upper": 3692605,"lower": 3535716,"count": 1563,"preSum": 39075 },{ "ndv": 1563,"upper": 3878838,"lower": 3692633,"count": 1563,"preSum": 40638 },{ "ndv": 1563,"upper": 4016669,"lower": 3878938,"count": 1563,"preSum": 42201 },{ "ndv": 1563,"upper": 4145795,"lower": 4016670,"count": 1563,"preSum": 43764 },{ "ndv": 1563,"upper": 4300901,"lower": 4145813,"count": 1563,"preSum": 45327 },{ "ndv": 1563,"upper": 4480489,"lower": 4301000,"count": 1563,"preSum": 46890 },{ "ndv": 1563,"upper": 4653315,"lower": 4480490,"count": 1563,"preSum": 48453 },{ "ndv": 1563,"upper": 4785480,"lower": 4653346,"count": 1563,"preSum": 50016 },{ "ndv": 1563,"upper": 4931244,"lower": 4785558,"count": 1563,"preSum": 51579 },{ "ndv": 1563,"upper": 5087484,"lower": 4931261,"count": 1563,"preSum": 53142 },{ "ndv": 1563,"upper": 5276991,"lower": 5087485,"count": 1563,"preSum": 54705 },{ "ndv": 1563,"upper": 5483793,"lower": 5277014,"count": 1563,"preSum": 56268 },{ "ndv": 1563,"upper": 5611904,"lower": 5483870,"count": 1563,"preSum": 57831 },{ "ndv": 1563,"upper": 5764332,"lower": 5611938,"count": 1563,"preSum": 59394 },{ "ndv": 1563,"upper": 5935456,"lower": 5764333,"count": 1563,"preSum": 60957 },{ "ndv": 1563,"upper": 6137053,"lower": 5935473,"count": 1563,"preSum": 62520 },{ "ndv": 1563,"upper": 6300509,"lower": 6137084,"count": 1563,"preSum": 64083 },{ "ndv": 1563,"upper": 6460653,"lower": 6300592,"count": 1563,"preSum": 65646 },{ "ndv": 1563,"upper": 6617328,"lower": 6460654,"count": 1563,"preSum": 67209 },{ "ndv": 1563,"upper": 6796378,"lower": 6617403,"count": 1563,"preSum": 68772 },{ "ndv": 1563,"upper": 7011421,"lower": 6796410,"count": 1563,"preSum": 70335 },{ "ndv": 1563,"upper": 7176767,"lower": 7011426,"count": 1563,"preSum": 71898 },{ "ndv": 1563,"upper": 7366028,"lower": 7176844,"count": 1563,"preSum": 73461 },{ "ndv": 1563,"upper": 7513845,"lower": 7366182,"count": 1563,"preSum": 75024 },{ "ndv": 1563,"upper": 7693552,"lower": 7514025,"count": 1563,"preSum": 76587 },{ "ndv": 1563,"upper": 7877152,"lower": 7693570,"count": 1563,"preSum": 78150 },{ "ndv": 1563,"upper": 8035878,"lower": 7877900,"count": 1563,"preSum": 79713 },{ "ndv": 1563,"upper": 8206082,"lower": 8035928,"count": 1563,"preSum": 81276 },{ "ndv": 1563,"upper": 8333763,"lower": 8206218,"count": 1563,"preSum": 82839 },{ "ndv": 1563,"upper": 8549135,"lower": 8333792,"count": 1563,"preSum": 84402 },{ "ndv": 1563,"upper": 8696495,"lower": 8549420,"count": 1563,"preSum": 85965 },{ "ndv": 1563,"upper": 8854051,"lower": 8696503,"count": 1563,"preSum": 87528 },{ "ndv": 1563,"upper": 8988611,"lower": 8854299,"count": 1563,"preSum": 89091 },{ "ndv": 1563,"upper": 9202397,"lower": 8988640,"count": 1563,"preSum": 90654 },{ "ndv": 1563,"upper": 9397081,"lower": 9202417,"count": 1563,"preSum": 92217 },{ "ndv": 1563,"upper": 9598153,"lower": 9397084,"count": 1563,"preSum": 93780 },{ "ndv": 1563,"upper": 9743118,"lower": 9598154,"count": 1563,"preSum": 95343 },{ "ndv": 1563,"upper": 9855907,"lower": 9743646,"count": 1563,"preSum": 96906 },{ "ndv": 1532,"upper": 9999884,"lower": 9856008,"count": 1532,"preSum": 98469 } ],"maxBucketSize": 64,"type": "Int","sampleRate": 0.90777135 }
+  supplier.s_suppkey.null_count:
+    0
+  supplier.s_suppkey.sample_rate:
+    0.010174989
+  customer.c_acctbal.composite_cardinality:
+    1095823
+  customer.c_address.composite_cardinality:
+    150121260
+  customer.c_comment.composite_cardinality:
+    121857067
+  customer.c_custkey.composite_cardinality:
+    150027277
+  customer.c_mktsegment.composite_cardinality:
+    5
+  customer.c_name.composite_cardinality:
+    151136790
+  customer.c_nationkey.composite_cardinality:
+    25
+  customer.c_phone.composite_cardinality:
+    150165609
+  lineitem.l_comment.composite_cardinality:
+    156837732
+  lineitem.l_commitdate.composite_cardinality:
+    2458
+  lineitem.l_discount.composite_cardinality:
+    11
+  lineitem.l_extendedprice.composite_cardinality:
+    3796623
+  lineitem.l_linenumber.composite_cardinality:
+    7
+  lineitem.l_linenumber,l_orderkey.composite_cardinality:
+    6003705558
+  lineitem.l_linestatus.composite_cardinality:
+    2
+  lineitem.l_orderkey.composite_cardinality:
+    1471993298
+  lineitem.l_partkey.composite_cardinality:
+    201110181
+  lineitem.l_quantity.composite_cardinality:
+    50
+  lineitem.l_receiptdate.composite_cardinality:
+    2544
+  lineitem.l_returnflag.composite_cardinality:
+    3
+  lineitem.l_shipdate.composite_cardinality:
+    2514
+  lineitem.l_shipinstruct.composite_cardinality:
+    4
+  lineitem.l_shipmode.composite_cardinality:
+    7
+  lineitem.l_suppkey.composite_cardinality:
+    9888407
+  lineitem.l_tax.composite_cardinality:
+    9
+  nation.n_comment.composite_cardinality:
+    25
+  nation.n_name.composite_cardinality:
+    25
+  nation.n_nationkey.composite_cardinality:
+    25
+  nation.n_regionkey.composite_cardinality:
+    5
+  orders.o_clerk.composite_cardinality:
+    1006018
+  orders.o_comment.composite_cardinality:
+    273755277
+  orders.o_custkey.composite_cardinality:
+    99636871
+  orders.o_orderdate.composite_cardinality:
+    2400
+  orders.o_orderkey.composite_cardinality:
+    1471993298
+  orders.o_orderpriority.composite_cardinality:
+    5
+  orders.o_orderstatus.composite_cardinality:
+    3
+  orders.o_shippriority.composite_cardinality:
+    1
+  orders.o_totalprice.composite_cardinality:
+    41404958
+  part.p_brand.composite_cardinality:
+    25
+  part.p_comment.composite_cardinality:
+    13921479
+  part.p_container.composite_cardinality:
+    40
+  part.p_mfgr.composite_cardinality:
+    5
+  part.p_name.composite_cardinality:
+    199472661
+  part.p_partkey.composite_cardinality:
+    201110181
+  part.p_retailprice.composite_cardinality:
+    119040
+  part.p_size.composite_cardinality:
+    50
+  part.p_type.composite_cardinality:
+    151
+  partsupp.ps_availqty.composite_cardinality:
+    9922
+  partsupp.ps_comment.composite_cardinality:
+    302446959
+  partsupp.ps_partkey.composite_cardinality:
+    201110181
+  partsupp.ps_partkey,ps_suppkey.composite_cardinality:
+    801137965
+  partsupp.ps_suppkey.composite_cardinality:
+    9888407
+  partsupp.ps_supplycost.composite_cardinality:
+    99249
+  region.r_comment.composite_cardinality:
+    5
+  region.r_name.composite_cardinality:
+    5
+  region.r_regionkey.composite_cardinality:
+    5
+  supplier.s_acctbal.composite_cardinality:
+    1095823
+  supplier.s_address.composite_cardinality:
+    9997612
+  supplier.s_comment.composite_cardinality:
+    9830837
+  supplier.s_name.composite_cardinality:
+    10072419
+  supplier.s_nationkey.composite_cardinality:
+    25
+  supplier.s_phone.composite_cardinality:
+    10030270
+  supplier.s_suppkey.composite_cardinality:
+    9888407
+CONFIG:
+  ENABLE_BKA_JOIN:
+    true
+  MPP_METRIC_LEVEL:
+    0
+  ENABLE_SPM:
+    TRUE
+  ENABLE_AUTO_USE_COLUMNS_PARTITION:
+    true
+  CONN_POOL_XPROTO_PURE_ASYNC_MPP:
+    true
+  RECORD_SQL:
+    TRUE
+  CONN_POOL_XPROTO_CHUNK_RESULT:
+    true
+  ENABLE_SCALE_OUT_FEATURE:
+    true
+  MAX_PHYSICAL_PARTITION_COUNT:
+    8192
+  FORBID_EXECUTE_DML_ALL:
+    FALSE
+  AUTO_PARTITION_PARTITIONS:
+    48
+  GROUP_SEQ_CHECK_INTERVAL:
+    5
+  CONN_POOL_XPROTO_SLOW_THRESH:
+    1000
+  COMMIT_TIMEOUT:
+    180000
+  GROUP_PARALLELISM:
+    8
+  MPP_RPC_LOCAL_ENABLED:
+    false
+  CONN_POOL_MAX_POOL_SIZE:
+    60
+  ENABLE_OSS_MOCK_COLUMNAR:
+    true
+  SQL_DELAY_CUTOFF:
+    2
+  CONN_POOL_PROPERTIES:
+    connectTimeout=5000;characterEncoding=utf8;autoReconnect=true;failOverReadOnly=false;socketTimeout=12000;rewriteBatchedStatements=true;useServerPrepStmts=false;useSSL=false
+  PARTITIONS_HEATMAP_COLLECTION_MAX_SINGLE_LOGIC_SCHEMA_COUNT:
+    500
+  CONN_POOL_XPROTO_MAX_PACKET_SIZE:
+    67108864
+  CONN_POOL_XPROTO_DIRECT_WRITE:
+    false
+  CONN_POOL_XPROTO_MAX_SESSION_PER_CLIENT:
+    1024
+  STATISTIC_COLLECTOR_FROM_RULE:
+    true
+  CONN_POOL_BLOCK_TIMEOUT:
+    5000
+  MPP_TABLESCAN_CONNECTION_STRATEGY:
+    0
+  CONN_POOL_IDLE_TIMEOUT:
+    60
+  CONN_POOL_XPROTO_XPLAN_EXPEND_STAR:
+    true
+  CONN_POOL_XPROTO_STORAGE_DB_PORT:
+    0
+  MAX_PARTITION_COLUMN_COUNT:
+    5
+  PROCESS_AUTO_INCREMENT_BY_SEQUENCE:
+    true
+  ALLOW_SIMPLE_SEQUENCE:
+    false
+  PURGE_TRANS_BEFORE:
+    604801
+  SHOW_TABLE_GROUP_NAME:
+    false
+  ENABLE_CONST_EXPR_EVAL_CACHE:
+    true
+  SOCKET_TIMEOUT:
+    900000
+  ENABLE_INTERVAL_ENUMERATION_IN_PRUNING:
+    true
+  CONN_POOL_XPROTO_META_DB_PORT:
+    0
+  CONN_POOL_MIN_POOL_SIZE:
+    5
+  ENABLE_ALTER_DDL:
+    true
+  CONN_POOL_XPROTO_PLAN_CACHE:
+    true
+  MAX_ENUMERABLE_INTERVAL_LENGTH:
+    32
+  CONN_POOL_XPROTO_MAX_CLIENT_PER_INST:
+    32
+  ENABLE_SELF_CROSS_JOIN:
+    true
+  CONN_POOL_XPROTO_FLAG:
+    0
+  USE_CHUNK_EXECUTOR:
+    AUTO
+  SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE:
+    false
+  FORCE_APPLY_CACHE:
+    TRUE
+  CONN_POOL_XPROTO_XPLAN_TABLE_SCAN:
+    false
+  ENABLE_MPP:
+    true
+  CONN_POOL_MAX_WAIT_THREAD_COUNT:
+    0
+  CONN_POOL_XPROTO_CONFIG:
+
+  CONN_POOL_XPROTO_MAX_POOLED_SESSION_PER_INST:
+    512
+  CONN_POOL_XPROTO_SESSION_AGING_TIME:
+    600000
+  CONN_POOL_XPROTO_MIN_POOLED_SESSION_PER_INST:
+    32
+  SQL_SIMPLE_MAX_LENGTH:
+    1005
+  ENABLE_CDC_META_BUILD_SNAPSHOT:
+    true
+  SCAN_TIMEOUT_INTERVAL:
+    121
+  CHOOSE_STREAMING:
+    true
+  ENABLE_DELETE_WITH_LIMIT:
+    TRUE
+  ENABLE_RUNTIME_FILTER:
+    false
+  ENABLE_AUTO_MERGE_INTERVALS_IN_PRUNING:
+    true
+  WORKLOAD_OSS_NET_THRESHOLD:
+    -1
+  MAX_IN_SUBQUERY_PRUNING_SIZE:
+    8192
+  CONN_POOL_XPROTO_QUERY_TOKEN:
+    10000
+  HINT_PARSER_FLAG:
+    TRUE
+  ENABLE_AUTO_USE_RANGE_FOR_TIME_INDEX:
+    false
+  GET_TSO_TIMEOUT:
+    5000
+  LOGICAL_DB_TIME_ZONE:
+    +08:00
+  STORAGE_SUPPORTS_BLOOM_FILTER:
+    true
+  TRUE:
+    FALSE
+  ENABLE_SIMPLE_SEQUENCE:
+    TRUE
+  INIT_CONCURRENT_POOL_EVERY_CONNECTION:
+    false
+  COLLATION_SERVER:
+    utf8mb4_general_ci
+  SINGLE_GROUP_STORAGE_INST_LIST:
+    polardbx-storage-0-master
+  CONN_POOL_XPROTO_CHECKER:
+    true
+  ENABLE_RUNTIME_FILTER_XXHASH:
+    true
+  ENABLE_UPDATE_PARTITION_KEY:
+    false
+  USE_FAST_SINGLE_POINT_INTERVAL_MERGING:
+    false
+  CONN_POOL_XPROTO_AUTH:
+    true
+  ENABLE_UPDATE_WITH_LIMIT:
+    TRUE
+  ENABLE_CBO:
+    TRUE
+  SERVER_ID:
+    1
+  ENABLE_DDL:
+    TRUE
+  DEFAULT_PARTITION_MODE:
+    drds
+  CONN_POOL_XPROTO_PIPE_BUFFER_SIZE:
+    268435456
+  PURGE_TRANS_INTERVAL:
+    86401
+  CONN_POOL_XPROTO_FEEDBACK:
+    true
+  CONN_POOL_XPROTO_MESSAGE_TIMESTAMP:
+    true
+  PARALLELISM:
+    -1
+  ENABLE_COLUMNAR_OPTIMIZER:
+    true
+  PARTITION_PRUNING_STEP_COUNT_LIMIT:
+    1024
+  ENABLE_FORBID_PUSH_DML_WITH_HINT:
+    FALSE
+  ENABLE_MASTER_MPP:
+    true
+  SHARD_DB_COUNT_EACH_STORAGE_INST:
+    2
+  PLAN_EXTERNALIZE_TEST:
+    TRUE
+  NET_WRITE_TIMEOUT:
+    28800
+  CONN_POOL_XPROTO_XPLAN:
+    true
+  INIT_WORKER:
+    FALSE
+  CDC_STARTUP_MODE:
+    1
+  CONN_POOL_XPROTO_TRX_LEAK_CHECK:
+    false
+  RETRY_ERROR_SQL_ON_OLD_SERVER:
+    true
+  MAX_LOGICAL_DB_COUNT:
+    2048
+  CONN_POOL_XPROTO_AUTO_COMMIT_OPTIMIZE:
+    true
+  SHOW_HASH_PARTITIONS_BY_RANGE:
+    false
+  defaltxxAPPName.isNew:
+    true
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/Tpch1TTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/Tpch1TTest.yml
index cdbd4ce0a..8e1963865 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/Tpch1TTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/Tpch1TTest.yml
@@ -9,7 +9,7 @@ SQL:
               exchange(distribution=hash[0]96, collation=[])
                 partialhashagg(group="l_returnflag,l_linestatus", sum_qty="sum(l_quantity)", sum_base_price="sum(l_extendedprice)", sum_disc_price="sum($f4)", sum_charge="sum($f5)", $f6="count()", $f7="sum(l_discount)")
                   project(l_returnflag="l_returnflag", l_linestatus="l_linestatus", l_quantity="l_quantity", l_extendedprice="l_extendedprice", $f4="l_extendedprice * ?0 - l_discount", $f5="l_extendedprice * ?1 - l_discount * ?2 + l_tax", l_discount="l_discount")
-                    osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, sql="select `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus` from `lineitem` as `lineitem` where (`l_shipdate` <= date_sub(?, interval '118' day))")
+                    osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `l_quantity`, `l_extendedprice`, `l_discount`, `l_tax`, `l_returnflag`, `l_linestatus` from `lineitem_col_index` as `lineitem_col_index` where (`l_shipdate` <= '1998-08-05')")
   - sql: |
       select   s_acctbal,      s_name,         n_name,         p_partkey,      p_mfgr,         s_address,      s_phone,        s_comment from  part,   supplier,       partsupp,       nation,         region where    p_partkey = ps_partkey  and s_suppkey = ps_suppkey      and p_size = 15         and p_type like '%STEEL'        and s_nationkey = n_nationkey   and n_regionkey = r_regionkey   and r_name = 'MIDDLE EAST'      and ps_supplycost = (           select                  min(ps_supplycost)              from                    partsupp,                       supplier,                       nation,                         region          where                   p_partkey = ps_partkey                  and s_suppkey = ps_suppkey                      and s_nationkey = n_nationkey                   and n_regionkey = r_regionkey                   and r_name = 'MIDDLE EAST'      ) order by      s_acctbal desc,         n_name,         s_name,         p_partkey limit 100;
     plan: |
@@ -20,32 +20,32 @@ SQL:
               hashjoin(condition="ps_partkey = ps_partkey and ps_supplycost = min(ps_supplycost)", type="inner")
                 hashagg(group="ps_partkey", min(ps_supplycost)="min(ps_supplycost)", partition=[local])
                   hashjoin(condition="ps_suppkey = s_suppkey", type="inner")
-                    osstablescan(tables="partsupp[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_supplycost` from `partsupp` as `partsupp`")
+                    osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_supplycost` from `partsupp_col_index` as `partsupp_col_index`")
                     exchange(distribution=broadcast, collation=[])
                       hashjoin(condition="n_nationkey = s_nationkey", type="inner")
-                        osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier` as `supplier`")
+                        osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
                         exchange(distribution=broadcast, collation=[])
                           hashjoin(condition="r_regionkey = n_regionkey", type="inner")
-                            osstablescan(tables="nation", shardcount=0, partition=[remote], sql="select `n_nationkey`, `n_regionkey` from `nation` as `nation`")
+                            osstablescan(tables="nation_col_index[p1]", partition=[remote], sql="select `n_nationkey`, `n_regionkey` from `nation_col_index` as `nation_col_index`")
                             exchange(distribution=broadcast, collation=[])
-                              osstablescan(tables="region", shardcount=0, sql="select `r_regionkey` from `region` as `region` where (`r_name` = ?)")
+                              osstablescan(tables="region_col_index[p1]", sql="select `r_regionkey` from `region_col_index` as `region_col_index` where (`r_name` = ?)")
                 exchange(distribution=hash[8]96, collation=[])
                   project(s_name="s_name", s_address="s_address", s_phone="s_phone", s_acctbal="s_acctbal", s_comment="s_comment", n_name="n_name", p_partkey="p_partkey", p_mfgr="p_mfgr", ps_partkey="ps_partkey", ps_supplycost="ps_supplycost")
                     hashjoin(condition="s_nationkey = n_nationkey", type="inner")
                       project(s_name="s_name", s_address="s_address", s_nationkey="s_nationkey", s_phone="s_phone", s_acctbal="s_acctbal", s_comment="s_comment", p_partkey="p_partkey", p_mfgr="p_mfgr", ps_partkey="ps_partkey", ps_supplycost="ps_supplycost")
                         hashjoin(condition="ps_suppkey = s_suppkey", type="inner")
-                          osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_address`, `s_nationkey`, `s_phone`, `s_acctbal`, `s_comment` from `supplier` as `supplier`")
+                          osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_address`, `s_nationkey`, `s_phone`, `s_acctbal`, `s_comment` from `supplier_col_index` as `supplier_col_index`")
                           exchange(distribution=hash[3]96, collation=[])
                             project(p_partkey="p_partkey", p_mfgr="p_mfgr", ps_partkey="ps_partkey", ps_suppkey="ps_suppkey", ps_supplycost="ps_supplycost")
                               hashjoin(condition="ps_partkey = p_partkey", type="inner", partition=[local])
-                                osstablescan(tables="partsupp[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_supplycost` from `partsupp` as `partsupp`")
-                                osstablescan(tables="part[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey`, `p_mfgr` from `part` as `part` where ((`p_size` = ?) and (`p_type` like ?))")
+                                osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_supplycost` from `partsupp_col_index` as `partsupp_col_index`")
+                                osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey`, `p_mfgr` from `part_col_index` as `part_col_index` where ((`p_size` = ?) and (`p_type` like ?))")
                       project(n_nationkey="n_nationkey", n_name="n_name")
                         exchange(distribution=broadcast, collation=[])
                           hashjoin(condition="n_regionkey = r_regionkey", type="inner")
-                            osstablescan(tables="nation", shardcount=0, partition=[remote], sql="select `n_nationkey`, `n_name`, `n_regionkey` from `nation` as `nation`")
+                            osstablescan(tables="nation_col_index[p1]", partition=[remote], sql="select `n_nationkey`, `n_name`, `n_regionkey` from `nation_col_index` as `nation_col_index`")
                             exchange(distribution=broadcast, collation=[])
-                              osstablescan(tables="region", shardcount=0, sql="select `r_regionkey` from `region` as `region` where (`r_name` = ?)")
+                              osstablescan(tables="region_col_index[p1]", sql="select `r_regionkey` from `region_col_index` as `region_col_index` where (`r_name` = ?)")
   - sql: |
       select   l_orderkey,     sum(l_extendedprice * (1 - l_discount)) as revenue,     o_orderdate,    o_shippriority from     customer,       orders,         lineitem where  c_mktsegment = 'HOUSEHOLD'      and c_custkey = o_custkey       and l_orderkey = o_orderkey     and o_orderdate < '1995-03-29'  and l_shipdate > '1995-03-29' group by  l_orderkey,     o_orderdate,    o_shippriority order by         revenue desc,   o_orderdate limit 10;
     plan: |
@@ -56,12 +56,12 @@ SQL:
               hashagg(group="o_orderdate,o_shippriority,l_orderkey", revenue="sum(__*__)")
                 project(c_custkey="c_custkey", o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderdate="o_orderdate", o_shippriority="o_shippriority", l_orderkey="l_orderkey", __*__="l_extendedprice * ?0 - l_discount")
                   hashjoin(condition="o_orderkey = l_orderkey", type="inner", partition=[local])
-                    osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem` where (`l_shipdate` > ?)")
+                    osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where (`l_shipdate` > ?)")
                     project(c_custkey="c_custkey", o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderdate="o_orderdate", o_shippriority="o_shippriority")
                       hashjoin(condition="o_custkey = c_custkey", type="inner")
-                        osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey`, `o_orderdate`, `o_shippriority` from `orders` as `orders` where (`o_orderdate` < ?)")
+                        osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey`, `o_orderdate`, `o_shippriority` from `orders_col_index` as `orders_col_index` where (`o_orderdate` < ?)")
                         exchange(distribution=broadcast, collation=[])
-                          osstablescan(tables="customer[p1,p2,p3,...p96]", shardcount=96, sql="select `c_custkey` from `customer` as `customer` where (`c_mktsegment` = ?)")
+                          osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `c_custkey` from `customer_col_index` as `customer_col_index` where (`c_mktsegment` = ?)")
   - sql: |
       select   o_orderpriority,        count(*) as order_count from    orders where    o_orderdate >= '1997-05-01'     and o_orderdate < '1997-05-01' + interval '3' month     and exists (            select                  *               from                    lineitem                where                   l_orderkey = o_orderkey                         and l_commitdate < l_receiptdate        ) group by      o_orderpriority order by        o_orderpriority;
     plan: |
@@ -71,8 +71,8 @@ SQL:
             exchange(distribution=hash[0]96, collation=[])
               partialhashagg(group="o_orderpriority", order_count="count()")
                 semihashjoin(condition="l_orderkey = o_orderkey", type="semi", build="outer", partition=[local])
-                  osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_orderpriority` from `orders` as `orders` where ((`o_orderdate` >= ?) and (`o_orderdate` < date_add(?, interval '3' month)))")
-                  osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey` from `lineitem` as `lineitem` where (`l_commitdate` < `l_receiptdate`)")
+                  osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_orderpriority` from `orders_col_index` as `orders_col_index` where ((`o_orderdate` >= ?) and (`o_orderdate` < '1997-08-01'))")
+                  osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey` from `lineitem_col_index` as `lineitem_col_index` where (`l_commitdate` < `l_receiptdate`)")
   - sql: |
       select   n_name,         sum(l_extendedprice * (1 - l_discount)) as revenue from         customer,       orders,         lineitem,       supplier,       nation,         region where    c_custkey = o_custkey   and l_orderkey = o_orderkey     and l_suppkey = s_suppkey       and c_nationkey = s_nationkey   and s_nationkey = n_nationkey   and n_regionkey = r_regionkey   and r_name = 'AMERICA'  and o_orderdate >= '1996-01-01'         and o_orderdate < '1996-01-01' + interval '1' year group by     n_name order by         revenue desc;
     plan: |
@@ -85,21 +85,21 @@ SQL:
                   hashjoin(condition="l_suppkey = s_suppkey and n_nationkey = s_nationkey", type="inner")
                     project(c_custkey="c_custkey", c_nationkey="c_nationkey", n_nationkey="n_nationkey", n_name="n_name", n_regionkey="n_regionkey", r_regionkey="r_regionkey", o_orderkey="o_orderkey", o_custkey="o_custkey", l_orderkey="l_orderkey", l_suppkey="l_suppkey", l_extendedprice="l_extendedprice", l_discount="l_discount")
                       hashjoin(condition="l_orderkey = o_orderkey", type="inner")
-                        osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_orderkey`, `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem`")
+                        osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_orderkey`, `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index`")
                         exchange(distribution=hash[6]96, collation=[])
                           project(c_custkey="c_custkey", c_nationkey="c_nationkey", n_nationkey="n_nationkey", n_name="n_name", n_regionkey="n_regionkey", r_regionkey="r_regionkey", o_orderkey="o_orderkey", o_custkey="o_custkey")
                             hashjoin(condition="o_custkey = c_custkey", type="inner")
                               exchange(distribution=hash[1]96, collation=[])
-                                osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, sql="select `o_orderkey`, `o_custkey` from `orders` as `orders` where ((`o_orderdate` >= ?) and (`o_orderdate` < date_add(?, interval '1' year)))")
+                                osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `o_orderkey`, `o_custkey` from `orders_col_index` as `orders_col_index` where ((`o_orderdate` >= ?) and (`o_orderdate` < '1997-01-01'))")
                               hashjoin(condition="n_nationkey = c_nationkey", type="inner")
-                                osstablescan(tables="customer[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_nationkey` from `customer` as `customer`")
+                                osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_nationkey` from `customer_col_index` as `customer_col_index`")
                                 exchange(distribution=broadcast, collation=[])
                                   hashjoin(condition="n_regionkey = r_regionkey", type="inner")
-                                    osstablescan(tables="nation", shardcount=0, partition=[remote], sql="select `n_nationkey`, `n_name`, `n_regionkey` from `nation` as `nation`")
+                                    osstablescan(tables="nation_col_index[p1]", partition=[remote], sql="select `n_nationkey`, `n_name`, `n_regionkey` from `nation_col_index` as `nation_col_index`")
                                     exchange(distribution=broadcast, collation=[])
-                                      osstablescan(tables="region", shardcount=0, sql="select `r_regionkey` from `region` as `region` where (`r_name` = ?)")
+                                      osstablescan(tables="region_col_index[p1]", sql="select `r_regionkey` from `region_col_index` as `region_col_index` where (`r_name` = ?)")
                     exchange(distribution=broadcast, collation=[])
-                      osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, sql="select `s_suppkey`, `s_nationkey` from `supplier` as `supplier`")
+                      osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
   - sql: |
       select   sum(l_extendedprice * l_discount) as revenue from       lineitem where  l_shipdate >= '1996-01-01'      and l_shipdate < '1996-01-01' + interval '1' year       and l_discount between 0.09 - 0.01 and 0.09 + 0.01      and l_quantity < 24;
     plan: |
@@ -107,7 +107,7 @@ SQL:
         exchange(distribution=single, collation=[])
           partialhashagg(revenue="sum($f0)")
             project($f0="l_extendedprice * l_discount")
-              osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, sql="select `l_extendedprice`, `l_discount` from `lineitem` as `lineitem` where ((`l_discount` between (? - ?) and (? + ?)) and (`l_shipdate` >= ?) and (`l_quantity` < ?) and (`l_shipdate` < date_add(?, interval '1' year)))")
+              osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where ((`l_discount` between '0.08' and '0.10') and (`l_shipdate` >= ?) and (`l_quantity` < ?) and (`l_shipdate` < '1997-01-01'))")
   - sql: |
       select   supp_nation,    cust_nation,    l_year,         sum(volume) as revenue from     (               select                  n1.n_name as supp_nation,                       n2.n_name as cust_nation,                       extract(year from l_shipdate) as l_year,                        l_extendedprice * (1 - l_discount) as volume            from                    supplier,                       lineitem,                       orders,                         customer,                       nation n1,                      nation n2               where                   s_suppkey = l_suppkey                   and o_orderkey = l_orderkey                     and c_custkey = o_custkey                       and s_nationkey = n1.n_nationkey                        and c_nationkey = n2.n_nationkey                        and (                           (n1.n_name = 'UNITED STATES' and n2.n_name = 'INDIA')                           or (n1.n_name = 'INDIA' and n2.n_name = 'UNITED STATES')                        )                       and l_shipdate between '1995-01-01' and '1996-12-31'    ) as shipping group by  supp_nation,    cust_nation,    l_year order by         supp_nation,    cust_nation,    l_year;
     plan: |
@@ -116,25 +116,25 @@ SQL:
           hashagg(group="n_name,n_name0,extract", revenue="sum(revenue)")
             exchange(distribution=hash[0]96, collation=[])
               partialhashagg(group="n_name,n_name0,extract", revenue="sum(__*__)")
-                project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", n_nationkey="n_nationkey", n_name="n_name", n_nationkey0="n_nationkey0", n_name0="n_name0", c_custkey="c_custkey", c_nationkey="c_nationkey", l_orderkey="l_orderkey", l_suppkey="l_suppkey", extract="extract(year, l_shipdate)", __*__="l_extendedprice * ?0 - l_discount", o_orderkey="o_orderkey", o_custkey="o_custkey")
+                project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", n_nationkey="n_nationkey", n_name="n_name", =="n_name = ?1", =3="n_name = ?3", n_nationkey0="n_nationkey0", n_name0="n_name0", =0="n_name0 = ?2", =30="n_name0 = ?4", c_custkey="c_custkey", c_nationkey="c_nationkey", l_orderkey="l_orderkey", l_suppkey="l_suppkey", extract="extract(year, l_shipdate)", __*__="l_extendedprice * ?0 - l_discount", o_orderkey="o_orderkey", o_custkey="o_custkey")
                   hashjoin(condition="o_custkey = c_custkey and ((n_name = ?1 and n_name = ?2) or (n_name = ?3 and n_name = ?4))", type="inner")
                     project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", n_nationkey="n_nationkey", n_name="n_name", l_orderkey="l_orderkey", l_suppkey="l_suppkey", l_extendedprice="l_extendedprice", l_discount="l_discount", l_shipdate="l_shipdate", o_orderkey="o_orderkey", o_custkey="o_custkey")
                       exchange(distribution=hash[1]96, collation=[])
                         hashjoin(condition="l_orderkey = o_orderkey", type="inner", partition=[local])
-                          osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey` from `orders` as `orders`")
+                          osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey` from `orders_col_index` as `orders_col_index`")
                           project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", n_nationkey="n_nationkey", n_name="n_name", l_orderkey="l_orderkey", l_suppkey="l_suppkey", l_extendedprice="l_extendedprice", l_discount="l_discount", l_shipdate="l_shipdate")
                             hashjoin(condition="l_suppkey = s_suppkey", type="inner")
-                              osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_suppkey`, `l_extendedprice`, `l_discount`, `l_shipdate` from `lineitem` as `lineitem` where (`l_shipdate` between ? and ?)")
+                              osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_suppkey`, `l_extendedprice`, `l_discount`, `l_shipdate` from `lineitem_col_index` as `lineitem_col_index` where (`l_shipdate` between ? and ?)")
                               exchange(distribution=broadcast, collation=[])
                                 hashjoin(condition="n_nationkey = s_nationkey", type="inner")
-                                  osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier` as `supplier`")
+                                  osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
                                   exchange(distribution=broadcast, collation=[])
-                                    osstablescan(tables="nation", shardcount=0, sql="select `n_nationkey`, `n_name` from `nation` as `nation` where ((`n_name` = ?) or (`n_name` = ?))")
+                                    osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey`, `n_name` from `nation_col_index` as `nation_col_index` where ((`n_name` = ?) or (`n_name` = ?))")
                     project(n_nationkey="n_nationkey", n_name="n_name", c_custkey="c_custkey", c_nationkey="c_nationkey")
                       hashjoin(condition="n_nationkey = c_nationkey", type="inner")
-                        osstablescan(tables="customer[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_nationkey` from `customer` as `customer`")
+                        osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_nationkey` from `customer_col_index` as `customer_col_index`")
                         exchange(distribution=broadcast, collation=[])
-                          osstablescan(tables="nation", shardcount=0, sql="select `n_nationkey`, `n_name` from `nation` as `nation` where ((`n_name` = ?) or (`n_name` = ?))")
+                          osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey`, `n_name` from `nation_col_index` as `nation_col_index` where ((`n_name` = ?) or (`n_name` = ?))")
   - sql: |
       select   o_year,         sum(case                when nation = 'INDIA' then volume               else 0  end) / sum(volume) as mkt_share from    (               select                  extract(year from o_orderdate) as o_year,                       l_extendedprice * (1 - l_discount) as volume,                   n2.n_name as nation             from                    part,                   supplier,                       lineitem,                       orders,                         customer,                       nation n1,                      nation n2,                      region          where                   p_partkey = l_partkey                   and s_suppkey = l_suppkey                       and l_orderkey = o_orderkey                     and o_custkey = c_custkey                       and c_nationkey = n1.n_nationkey                        and n1.n_regionkey = r_regionkey                        and r_name = 'ASIA'                     and s_nationkey = n2.n_nationkey                        and o_orderdate between '1995-01-01' and '1996-12-31'                   and p_type = 'MEDIUM ANODIZED STEEL'    ) as all_nations group by       o_year order by         o_year;
     plan: |
@@ -153,23 +153,23 @@ SQL:
                               project(l_orderkey="l_orderkey", l_partkey="l_partkey", l_suppkey="l_suppkey", l_extendedprice="l_extendedprice", l_discount="l_discount", o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderdate="o_orderdate", p_partkey="p_partkey")
                                 exchange(distribution=hash[1]96, collation=[])
                                   hashjoin(condition="o_orderkey = l_orderkey", type="inner", partition=[local])
-                                    osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey`, `o_orderdate` from `orders` as `orders` where (`o_orderdate` between ? and ?)")
+                                    osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey`, `o_orderdate` from `orders_col_index` as `orders_col_index` where (`o_orderdate` between ? and ?)")
                                     hashjoin(condition="p_partkey = l_partkey", type="inner")
-                                      osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem`")
+                                      osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index`")
                                       exchange(distribution=broadcast, collation=[])
-                                        osstablescan(tables="part[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey` from `part` as `part` where (`p_type` = ?)")
+                                        osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey` from `part_col_index` as `part_col_index` where (`p_type` = ?)")
                               hashjoin(condition="c_nationkey = n_nationkey", type="inner")
-                                osstablescan(tables="customer[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_nationkey` from `customer` as `customer`")
+                                osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_nationkey` from `customer_col_index` as `customer_col_index`")
                                 exchange(distribution=broadcast, collation=[])
                                   hashjoin(condition="n_regionkey = r_regionkey", type="inner")
-                                    osstablescan(tables="nation", shardcount=0, partition=[remote], sql="select `n_nationkey`, `n_regionkey` from `nation` as `nation`")
+                                    osstablescan(tables="nation_col_index[p1]", partition=[remote], sql="select `n_nationkey`, `n_regionkey` from `nation_col_index` as `nation_col_index`")
                                     exchange(distribution=broadcast, collation=[])
-                                      osstablescan(tables="region", shardcount=0, sql="select `r_regionkey` from `region` as `region` where (`r_name` = ?)")
+                                      osstablescan(tables="region_col_index[p1]", sql="select `r_regionkey` from `region_col_index` as `region_col_index` where (`r_name` = ?)")
                       project(s_suppkey="s_suppkey", n_name="n_name")
                         hashjoin(condition="s_nationkey = n_nationkey", type="inner")
-                          osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier` as `supplier`")
+                          osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
                           exchange(distribution=broadcast, collation=[])
-                            osstablescan(tables="nation", shardcount=0, sql="select `n_nationkey`, `n_name` from `nation` as `nation`")
+                            osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey`, `n_name` from `nation_col_index` as `nation_col_index`")
   - sql: |
       select   nation,         o_year,         sum(amount) as sum_profit from  (               select                  n_name as nation,                       extract(year from o_orderdate) as o_year,                       l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount               from                    part,                   supplier,                       lineitem,                       partsupp,                       orders,                         nation          where                   s_suppkey = l_suppkey                   and ps_suppkey = l_suppkey                      and ps_partkey = l_partkey                      and p_partkey = l_partkey                       and o_orderkey = l_orderkey                     and s_nationkey = n_nationkey                   and p_name like '%goldenrod%'   ) as profit group by    nation,         o_year order by         nation,         o_year desc;
     plan: |
@@ -184,21 +184,21 @@ SQL:
                       hashjoin(condition="l_suppkey = s_suppkey", type="inner")
                         project(l_suppkey="l_suppkey", o_orderdate="o_orderdate", -="l_extendedprice * ?0 - l_discount - ps_supplycost * l_quantity")
                           hashjoin(condition="ps_partkey = l_partkey and ps_suppkey = l_suppkey", type="inner")
-                            osstablescan(tables="partsupp[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_supplycost` from `partsupp` as `partsupp`")
+                            osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_supplycost` from `partsupp_col_index` as `partsupp_col_index`")
                             project(l_partkey="l_partkey", l_suppkey="l_suppkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice", l_discount="l_discount", o_orderdate="o_orderdate")
                               exchange(distribution=hash[2]96, collation=[])
                                 project(p_partkey="p_partkey", l_orderkey="l_orderkey", l_partkey="l_partkey", l_suppkey="l_suppkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice", l_discount="l_discount", o_orderkey="o_orderkey", o_orderdate="o_orderdate")
                                   hashjoin(condition="o_orderkey = l_orderkey", type="inner", partition=[local])
-                                    osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_orderdate` from `orders` as `orders`")
+                                    osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_orderdate` from `orders_col_index` as `orders_col_index`")
                                     project(p_partkey="p_partkey", l_orderkey="l_orderkey", l_partkey="l_partkey", l_suppkey="l_suppkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice", l_discount="l_discount")
                                       hashjoin(condition="p_partkey = l_partkey", type="inner")
-                                        osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_quantity`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem`")
+                                        osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_partkey`, `l_suppkey`, `l_quantity`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index`")
                                         exchange(distribution=broadcast, collation=[])
-                                          osstablescan(tables="part[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey` from `part` as `part` where (`p_name` like ?)")
+                                          osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey` from `part_col_index` as `part_col_index` where (`p_name` like ?)")
                         exchange(distribution=broadcast, collation=[])
-                          osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, sql="select `s_suppkey`, `s_nationkey` from `supplier` as `supplier`")
+                          osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
                     exchange(distribution=broadcast, collation=[])
-                      osstablescan(tables="nation", shardcount=0, sql="select `n_nationkey`, `n_name` from `nation` as `nation`")
+                      osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey`, `n_name` from `nation_col_index` as `nation_col_index`")
   - sql: |
       select   c_custkey,      c_name,         sum(l_extendedprice * (1 - l_discount)) as revenue,     c_acctbal,      n_name,         c_address,      c_phone,        c_comment from  customer,       orders,         lineitem,       nation where    c_custkey = o_custkey   and l_orderkey = o_orderkey     and o_orderdate >= '1995-01-01'         and o_orderdate < '1995-01-01' + interval '3' month     and l_returnflag = 'R'  and c_nationkey = n_nationkey group by  c_custkey,      c_name,         c_acctbal,      c_phone,        n_name,         c_address,      c_comment order by      revenue desc limit 20;
     plan: |
@@ -206,18 +206,18 @@ SQL:
         topn(sort="revenue desc", offset=0, fetch=?4)
           exchange(distribution=single, collation=[7 desc-nulls-last])
             topn(sort="revenue desc", fetch=+(?4, 0))
-              hashagg(group="c_custkey,n_name", c_name="__first_value(c_name)", c_acctbal="__first_value(c_acctbal)", c_phone="__first_value(c_phone)", c_address="__first_value(c_address)", c_comment="__first_value(c_comment)", revenue="sum(__*__)")
+              hashagg(group="c_custkey,n_name", c_name="__first_value(c_name)", c_acctbal="__first_value(c_acctbal)", c_phone="__first_value(c_phone)", c_address="__first_value(c_address)", c_comment="__first_value(c_comment)", revenue="sum(__*__)", partition=[local])
                 project(c_custkey="c_custkey", c_name="c_name", c_address="c_address", c_nationkey="c_nationkey", c_phone="c_phone", c_acctbal="c_acctbal", c_comment="c_comment", n_nationkey="n_nationkey", n_name="n_name", o_orderkey="o_orderkey", o_custkey="o_custkey", l_orderkey="l_orderkey", __*__="l_extendedprice * ?0 - l_discount")
                   hashjoin(condition="n_nationkey = c_nationkey", type="inner")
                     hashjoin(condition="o_custkey = c_custkey", type="inner")
-                      osstablescan(tables="customer[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_comment` from `customer` as `customer`")
+                      osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `c_custkey`, `c_name`, `c_address`, `c_nationkey`, `c_phone`, `c_acctbal`, `c_comment` from `customer_col_index` as `customer_col_index`")
                       exchange(distribution=hash[1]96, collation=[])
                         project(o_orderkey="o_orderkey", o_custkey="o_custkey", l_orderkey="l_orderkey", l_extendedprice="l_extendedprice", l_discount="l_discount")
                           hashjoin(condition="l_orderkey = o_orderkey", type="inner", partition=[local])
-                            osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem` where (`l_returnflag` = ?)")
-                            osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey` from `orders` as `orders` where ((`o_orderdate` < date_add(?, interval '3' month)) and (`o_orderdate` >= ?))")
+                            osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where (`l_returnflag` = ?)")
+                            osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey` from `orders_col_index` as `orders_col_index` where ((`o_orderdate` < '1995-04-01') and (`o_orderdate` >= ?))")
                     exchange(distribution=broadcast, collation=[])
-                      osstablescan(tables="nation", shardcount=0, sql="select `n_nationkey`, `n_name` from `nation` as `nation`")
+                      osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey`, `n_name` from `nation_col_index` as `nation_col_index`")
   - sql: |
       select   ps_partkey,     sum(ps_supplycost * ps_availqty) as value from  partsupp,       supplier,       nation where    ps_suppkey = s_suppkey  and s_nationkey = n_nationkey   and n_name = 'EGYPT' group by   ps_partkey having               sum(ps_supplycost * ps_availqty) > (                    select                          sum(ps_supplycost * ps_availqty) * 0.0000020000                         from                            partsupp,                               supplier,                               nation                  where                           ps_suppkey = s_suppkey                          and s_nationkey = n_nationkey                           and n_name = 'EGYPT'            ) order by      value desc;
     plan: |
@@ -226,28 +226,26 @@ SQL:
           project(ps_partkey="ps_partkey", value="value")
             nljoin(condition="value > $f0 * ?1", type="inner")
               hashagg(group="ps_partkey", value="sum(__*__)", partition=[local])
-                project(s_suppkey="s_suppkey", ps_partkey="ps_partkey", ps_suppkey="ps_suppkey", __*__="ps_supplycost * ps_availqty")
+                project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", n_nationkey="n_nationkey", ps_partkey="ps_partkey", ps_suppkey="ps_suppkey", __*__="ps_supplycost * ps_availqty")
                   hashjoin(condition="ps_suppkey = s_suppkey", type="inner")
-                    osstablescan(tables="partsupp[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty`, `ps_supplycost` from `partsupp` as `partsupp`")
+                    osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty`, `ps_supplycost` from `partsupp_col_index` as `partsupp_col_index`")
                     exchange(distribution=broadcast, collation=[])
-                      project(s_suppkey="s_suppkey")
-                        hashjoin(condition="n_nationkey = s_nationkey", type="inner")
-                          osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier` as `supplier`")
-                          exchange(distribution=broadcast, collation=[])
-                            osstablescan(tables="nation", shardcount=0, sql="select `n_nationkey` from `nation` as `nation` where (`n_name` = ?)")
+                      hashjoin(condition="n_nationkey = s_nationkey", type="inner")
+                        osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
+                        exchange(distribution=broadcast, collation=[])
+                          osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey` from `nation_col_index` as `nation_col_index` where (`n_name` = ?)")
               exchange(distribution=broadcast, collation=[])
                 hashagg($f0="sum($f0)")
                   exchange(distribution=single, collation=[])
                     partialhashagg($f0="sum(__*__)")
-                      project(s_suppkey="s_suppkey", ps_suppkey="ps_suppkey", __*__="ps_supplycost * ps_availqty")
+                      project(s_suppkey="s_suppkey", s_nationkey="s_nationkey", n_nationkey="n_nationkey", ps_suppkey="ps_suppkey", __*__="ps_supplycost * ps_availqty")
                         hashjoin(condition="ps_suppkey = s_suppkey", type="inner")
-                          osstablescan(tables="partsupp[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `ps_suppkey`, `ps_availqty`, `ps_supplycost` from `partsupp` as `partsupp`")
+                          osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `ps_suppkey`, `ps_availqty`, `ps_supplycost` from `partsupp_col_index` as `partsupp_col_index`")
                           exchange(distribution=broadcast, collation=[])
-                            project(s_suppkey="s_suppkey")
-                              hashjoin(condition="n_nationkey = s_nationkey", type="inner")
-                                osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier` as `supplier`")
-                                exchange(distribution=broadcast, collation=[])
-                                  osstablescan(tables="nation", shardcount=0, sql="select `n_nationkey` from `nation` as `nation` where (`n_name` = ?)")
+                            hashjoin(condition="n_nationkey = s_nationkey", type="inner")
+                              osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
+                              exchange(distribution=broadcast, collation=[])
+                                osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey` from `nation_col_index` as `nation_col_index` where (`n_name` = ?)")
   - sql: |
       select   l_shipmode,     sum(case                when o_orderpriority = '1-URGENT'                       or o_orderpriority = '2-HIGH'                   then 1          else 0  end) as high_line_count,        sum(case                when o_orderpriority <> '1-URGENT'                      and o_orderpriority <> '2-HIGH'                         then 1          else 0  end) as low_line_count from     orders,         lineitem where  o_orderkey = l_orderkey         and l_shipmode in ('AIR', 'REG AIR')    and l_commitdate < l_receiptdate        and l_shipdate < l_commitdate   and l_receiptdate >= '1993-01-01'       and l_receiptdate < '1993-01-01' + interval '1' year group by   l_shipmode order by     l_shipmode;
     plan: |
@@ -258,8 +256,8 @@ SQL:
               partialhashagg(group="l_shipmode", high_line_count="sum(case)", low_line_count="sum(case2)")
                 project(o_orderkey="o_orderkey", case="case(in($1, row(?0, ?1)), ?2, ?3)", case2="case(and(<>($1, ?4), <>($1, ?5)), ?6, ?7)", l_orderkey="l_orderkey", l_shipmode="l_shipmode")
                   hashjoin(condition="l_orderkey = o_orderkey", type="inner", partition=[local])
-                    osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_orderpriority` from `orders` as `orders`")
-                    osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_shipmode` from `lineitem` as `lineitem` where ((`l_receiptdate` < date_add(?, interval '1' year)) and (`l_shipmode` in(?)) and (`l_commitdate` < `l_receiptdate`) and (`l_shipdate` < `l_commitdate`) and (`l_receiptdate` >= ?))")
+                    osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_orderpriority` from `orders_col_index` as `orders_col_index`")
+                    osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_shipmode` from `lineitem_col_index` as `lineitem_col_index` where ((`l_receiptdate` < '1994-01-01') and (`l_shipmode` in(?)) and (`l_commitdate` < `l_receiptdate`) and (`l_shipdate` < `l_commitdate`) and (`l_receiptdate` >= ?))")
   - sql: |
       select   c_count,        count(*) as custdist from       (               select                  c_custkey,                      count(o_orderkey) as c_count            from                    customer left outer join orders on                              c_custkey = o_custkey                           and o_comment not like '%special%packages%'             group by                        c_custkey       ) c_orders group by     c_count order by        custdist desc,  c_count desc;
     plan: |
@@ -269,9 +267,9 @@ SQL:
             exchange(distribution=hash[0]96, collation=[])
               partialhashagg(group="c_count", custdist="count()")
                 hashgroupjoin(condition="c_custkey = o_custkey", type="left")
-                  osstablescan(tables="customer[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey` from `customer` as `customer`")
+                  osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey` from `customer_col_index` as `customer_col_index`")
                   exchange(distribution=hash[1]96, collation=[])
-                    osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, sql="select `o_orderkey`, `o_custkey` from `orders` as `orders` where (`o_comment` not like ?)")
+                    osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `o_orderkey`, `o_custkey` from `orders_col_index` as `orders_col_index` where (`o_comment` not like ?)")
   - sql: |
       select   100.00 * sum(case               when p_type like 'PROMO%'                       then l_extendedprice * (1 - l_discount)                 else 0  end) / sum(l_extendedprice * (1 - l_discount)) as promo_revenue from    lineitem,       part where      l_partkey = p_partkey   and l_shipdate >= '1993-11-01'  and l_shipdate < '1993-11-01' + interval '1' month;
     plan: |
@@ -281,9 +279,9 @@ SQL:
             partialhashagg($f0="sum($f0)", $f1="sum($f1)")
               project($f0="case(like($1, ?1), *($3, -(?2, $4)), cast(?3):decimal(37, 4))", $f1="l_extendedprice * ?4 - l_discount")
                 hashjoin(condition="l_partkey = p_partkey", type="inner")
-                  osstablescan(tables="part[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `p_partkey`, `p_type` from `part` as `part`")
+                  osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `p_partkey`, `p_type` from `part_col_index` as `part_col_index`")
                   exchange(distribution=hash[0]96, collation=[])
-                    osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, sql="select `l_partkey`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(?, interval '1' month)) and (`l_shipdate` >= ?))")
+                    osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `l_partkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where ((`l_shipdate` < '1993-12-01') and (`l_shipdate` >= ?))")
   - sql: |
       select   s_suppkey,      s_name,         s_address,      s_phone,        total_revenue from      supplier,       (               select                  l_suppkey as supplier_no,                       sum(l_extendedprice * (1 - l_discount)) as total_revenue                from                    lineitem                where                   l_shipdate >= '1995-02-01'                      and l_shipdate < '1995-02-01' + interval '3' month              group by                        l_suppkey       ) revenue0 where        s_suppkey = supplier_no         and total_revenue = (           select                  max(total_revenue)              from                    (                               select                                  l_suppkey as supplier_no,                                       sum(l_extendedprice * (1 - l_discount)) as total_revenue                                from                                    lineitem                                where                                   l_shipdate >= '1995-02-01'                                      and l_shipdate < '1995-02-01' + interval '3' month                              group by                                        l_suppkey                       ) revenue0      ) order by      s_suppkey;
     plan: |
@@ -291,34 +289,39 @@ SQL:
         memsort(sort="s_suppkey asc")
           project(s_suppkey="s_suppkey", s_name="s_name", s_address="s_address", s_phone="s_phone", total_revenue="total_revenue")
             hashjoin(condition="supplier_no = s_suppkey", type="inner")
-              osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_address`, `s_phone` from `supplier` as `supplier`")
+              osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_address`, `s_phone` from `supplier_col_index` as `supplier_col_index`")
               project(supplier_no="supplier_no", total_revenue="total_revenue")
                 hashjoin(condition="max(total_revenue) = total_revenue", type="inner")
-                  hashagg(group="supplier_no", total_revenue="sum($f1)")
+                  hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
                     exchange(distribution=hash[0]96, collation=[])
-                      project(supplier_no="l_suppkey", $f1="l_extendedprice * ?0 - l_discount")
-                        osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, sql="select `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(?, interval '3' month)) and (`l_shipdate` >= ?))")
+                      partialhashagg(group="supplier_no", total_revenue="sum($f1)")
+                        project(supplier_no="l_suppkey", $f1="l_extendedprice * ?0 - l_discount")
+                          osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where ((`l_shipdate` < '1995-05-01') and (`l_shipdate` >= ?))")
                   exchange(distribution=broadcast, collation=[])
                     hashagg(max(total_revenue)="max(max(total_revenue))")
                       exchange(distribution=single, collation=[])
                         partialhashagg(max(total_revenue)="max(total_revenue)")
-                          hashagg(group="supplier_no", total_revenue="sum($f1)")
+                          hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
                             exchange(distribution=hash[0]96, collation=[])
-                              project(supplier_no="l_suppkey", $f1="l_extendedprice * ?3 - l_discount")
-                                osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, sql="select `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(?, interval '3' month)) and (`l_shipdate` >= ?))")
+                              partialhashagg(group="supplier_no", total_revenue="sum($f1)")
+                                project(supplier_no="l_suppkey", $f1="l_extendedprice * ?3 - l_discount")
+                                  osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `l_suppkey`, `l_extendedprice`, `l_discount` from `lineitem_col_index` as `lineitem_col_index` where ((`l_shipdate` < '1995-05-01') and (`l_shipdate` >= ?))")
   - sql: |
       select   p_brand,        p_type,         p_size,         count(distinct ps_suppkey) as supplier_cnt from         partsupp,       part where      p_partkey = ps_partkey  and p_brand <> 'Brand#15'       and p_type not like 'STANDARD BRUSHED%'         and p_size in (5, 29, 4, 49, 30, 42, 33, 39)    and ps_suppkey not in (                 select                  s_suppkey               from                    supplier                where                   s_comment like '%Customer%Complaints%'  ) group by      p_brand,        p_type,         p_size order by         supplier_cnt desc,      p_brand,        p_type,         p_size;
     plan: |
       exchange(distribution=single, collation=[3 desc-nulls-last, 0 asc-nulls-first, 1 asc-nulls-first, 2 asc-nulls-first])
         memsort(sort="supplier_cnt desc,p_brand asc,p_type asc,p_size asc")
-          hashagg(group="p_brand,p_type,p_size", supplier_cnt="count(distinct ps_suppkey)")
-            exchange(distribution=hash[4]96, collation=[])
-              semihashjoin(condition="ps_suppkey = s_suppkey", type="anti", build="inner")
-                hashjoin(condition="p_partkey = ps_partkey", type="inner", partition=[local])
-                  osstablescan(tables="partsupp[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey` from `partsupp` as `partsupp`")
-                  osstablescan(tables="part[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey`, `p_brand`, `p_type`, `p_size` from `part` as `part` where ((`p_size` in(?)) and (`p_brand` <> ?) and (`p_type` not like ?))")
-                exchange(distribution=broadcast, collation=[])
-                  osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, sql="select `s_suppkey` from `supplier` as `supplier` where (`s_comment` like ?)")
+          hashagg(group="p_brand,p_type,p_size", supplier_cnt="count(ps_suppkey)")
+            hashagg(group="p_brand,p_type,p_size,ps_suppkey")
+              exchange(distribution=hash[1]96, collation=[])
+                project(p_brand="p_brand", p_type="p_type", p_size="p_size", ps_suppkey="ps_suppkey")
+                  partialhashagg(group="ps_suppkey,p_brand,p_type,p_size")
+                    semihashjoin(condition="ps_suppkey = s_suppkey", type="anti", build="inner")
+                      hashjoin(condition="p_partkey = ps_partkey", type="inner", partition=[local])
+                        osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey` from `partsupp_col_index` as `partsupp_col_index`")
+                        osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey`, `p_brand`, `p_type`, `p_size` from `part_col_index` as `part_col_index` where ((`p_size` in(?)) and (`p_brand` <> ?) and (`p_type` not like ?))")
+                      exchange(distribution=broadcast, collation=[])
+                        osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `s_suppkey` from `supplier_col_index` as `supplier_col_index` where (`s_comment` like ?)")
   - sql: |
       select   sum(l_extendedprice) / 7.0 as avg_yearly from   lineitem,       part where      p_partkey = l_partkey   and p_brand = 'Brand#51'        and p_container = 'SM JAR'      and l_quantity < (              select                  0.2 * avg(l_quantity)           from                    lineitem                where                   l_partkey = p_partkey   );
     plan: |
@@ -331,9 +334,9 @@ SQL:
                   exchange(distribution=hash[1]96, collation=[])
                     project(p_partkey="p_partkey", l_partkey="l_partkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice")
                       hashjoin(condition="l_partkey = p_partkey", type="inner")
-                        osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem`")
+                        osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem_col_index` as `lineitem_col_index`")
                         exchange(distribution=broadcast, collation=[])
-                          osstablescan(tables="part[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey` from `part` as `part` where ((`p_container` = ?) and (`p_brand` = ?))")
+                          osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey` from `part_col_index` as `part_col_index` where ((`p_container` = ?) and (`p_brand` = ?))")
   - sql: |
       select   c_name,         c_custkey,      o_orderkey,     o_orderdate,    o_totalprice,   sum(l_quantity) from    customer,       orders,         lineitem where  o_orderkey in (                 select                  l_orderkey              from                    lineitem                group by                        l_orderkey having                               sum(l_quantity) > 312   )       and c_custkey = o_custkey       and o_orderkey = l_orderkey group by    c_name,         c_custkey,      o_orderkey,     o_orderdate,    o_totalprice order by   o_totalprice desc,      o_orderdate limit 100;
     plan: |
@@ -343,17 +346,17 @@ SQL:
             topn(sort="o_totalprice desc,o_orderdate asc", fetch=+(?1, 0))
               project(c_custkey="c_custkey", o_orderkey="o_orderkey", o_orderdate="o_orderdate", o_totalprice="o_totalprice", c_name="c_name", sum(l_quantity)="sum(l_quantity)")
                 hashjoin(condition="o_custkey = c_custkey", type="inner")
-                  osstablescan(tables="customer[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_name` from `customer` as `customer`")
+                  osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_name` from `customer_col_index` as `customer_col_index`")
                   exchange(distribution=hash[1]96, collation=[])
                     hashagg(group="o_orderkey,o_custkey", o_orderdate="__first_value(o_orderdate)", o_totalprice="__first_value(o_totalprice)", sum(l_quantity)="sum(l_quantity)")
                       hashjoin(condition="o_orderkey = l_orderkey", type="inner", partition=[local])
-                        osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_quantity` from `lineitem` as `lineitem`")
+                        osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_quantity` from `lineitem_col_index` as `lineitem_col_index`")
                         semihashjoin(condition="o_orderkey = l_orderkey", type="semi", build="inner")
-                          osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey`, `o_totalprice`, `o_orderdate` from `orders` as `orders`")
+                          osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `o_orderkey`, `o_custkey`, `o_totalprice`, `o_orderdate` from `orders_col_index` as `orders_col_index`")
                           project(l_orderkey="l_orderkey")
                             filter(condition="$f1 > ?0")
                               hashagg(group="l_orderkey", $f1="sum(l_quantity)", partition=[local])
-                                osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_quantity` from `lineitem` as `lineitem`")
+                                osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_quantity` from `lineitem_col_index` as `lineitem_col_index`")
   - sql: |
       select   sum(l_extendedprice* (1 - l_discount)) as revenue from  lineitem,       part where      (               p_partkey = l_partkey           and p_brand = 'Brand#13'                and p_container in ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG')           and l_quantity >= 7 and l_quantity <= 7 + 10            and p_size between 1 and 5              and l_shipmode in ('AIR', 'AIR REG')            and l_shipinstruct = 'DELIVER IN PERSON'        )       or      (               p_partkey = l_partkey           and p_brand = 'Brand#15'                and p_container in ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK')                and l_quantity >= 18 and l_quantity <= 18 + 10          and p_size between 1 and 10             and l_shipmode in ('AIR', 'AIR REG')            and l_shipinstruct = 'DELIVER IN PERSON'        )       or      (               p_partkey = l_partkey           and p_brand = 'Brand#35'                and p_container in ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG')           and l_quantity >= 21 and l_quantity <= 21 + 10          and p_size between 1 and 15             and l_shipmode in ('AIR', 'AIR REG')            and l_shipinstruct = 'DELIVER IN PERSON'        );
     plan: |
@@ -361,10 +364,10 @@ SQL:
         exchange(distribution=single, collation=[])
           partialhashagg(revenue="sum(__*__)")
             project(p_partkey="p_partkey", =="p_brand = ?1", in="p_container in row(?2)", between asymmetric="between asymmetric($8, ?6, ?7)", =4="p_brand = ?10", in5="p_container in row(?11)", between asymmetric6="between asymmetric($8, ?15, ?16)", =7="p_brand = ?19", in8="p_container in row(?20)", between asymmetric9="between asymmetric($8, ?24, ?25)", l_partkey="l_partkey", __*__="l_extendedprice * ?0 - l_discount", >=="l_quantity >= ?3", <=="l_quantity <= 17", in0="l_shipmode in row(?8)", =0="l_shipinstruct = ?9", >=6="l_quantity >= ?12", <=7="l_quantity <= 28", in80="l_shipmode in row(?17)", =9="l_shipinstruct = ?18", >=10="l_quantity >= ?21", <=11="l_quantity <= 31", in12="l_shipmode in row(?26)", =13="l_shipinstruct = ?27")
-              hashjoin(condition="p_partkey = l_partkey and ((p_partkey = l_partkey and p_brand = ?1 and p_container in row(?2) and l_quantity >= ?3 and l_quantity <= ?4 + ?5 and between asymmetric($8, ?6, ?7) and l_shipmode in row(?8) and l_shipinstruct = ?9) or (p_partkey = l_partkey and p_brand = ?10 and p_container in row(?11) and l_quantity >= ?12 and l_quantity <= ?13 + ?14 and between asymmetric($8, ?15, ?16) and l_shipmode in row(?17) and l_shipinstruct = ?18) or (p_partkey = l_partkey and p_brand = ?19 and p_container in row(?20) and l_quantity >= ?21 and l_quantity <= ?22 + ?23 and between asymmetric($8, ?24, ?25) and l_shipmode in row(?26) and l_shipinstruct = ?27))", type="inner")
-                osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_partkey`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_shipinstruct`, `l_shipmode` from `lineitem` as `lineitem` where (((`l_quantity` >= ?) and (`l_quantity` <= (? + ?)) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)) or ((`l_quantity` >= ?) and (`l_quantity` <= (? + ?)) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)) or ((`l_quantity` >= ?) and (`l_quantity` <= (? + ?)) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)))")
+              hashjoin(condition="p_partkey = l_partkey and ((p_partkey = l_partkey and p_brand = ?1 and p_container in row(?2) and l_quantity >= ?3 and l_quantity <= 17 and between asymmetric($8, ?6, ?7) and l_shipmode in row(?8) and l_shipinstruct = ?9) or (p_partkey = l_partkey and p_brand = ?10 and p_container in row(?11) and l_quantity >= ?12 and l_quantity <= 28 and between asymmetric($8, ?15, ?16) and l_shipmode in row(?17) and l_shipinstruct = ?18) or (p_partkey = l_partkey and p_brand = ?19 and p_container in row(?20) and l_quantity >= ?21 and l_quantity <= 31 and between asymmetric($8, ?24, ?25) and l_shipmode in row(?26) and l_shipinstruct = ?27))", type="inner")
+                osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_partkey`, `l_quantity`, `l_extendedprice`, `l_discount`, `l_shipinstruct`, `l_shipmode` from `lineitem_col_index` as `lineitem_col_index` where (((`l_quantity` >= ?) and (`l_quantity` <= 17) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)) or ((`l_quantity` >= ?) and (`l_quantity` <= 28) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)) or ((`l_quantity` >= ?) and (`l_quantity` <= 31) and (`l_shipmode` in(?)) and (`l_shipinstruct` = ?)))")
                 exchange(distribution=broadcast, collation=[])
-                  osstablescan(tables="part[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey`, `p_brand`, `p_size`, `p_container` from `part` as `part` where (((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)) or ((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)) or ((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)))")
+                  osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `p_partkey`, `p_brand`, `p_size`, `p_container` from `part_col_index` as `part_col_index` where (((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)) or ((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)) or ((`p_brand` = ?) and (`p_container` in(?)) and (`p_size` between ? and ?)))")
   - sql: |
       select   s_name,         s_address from  supplier,       nation where    s_suppkey in (          select                  ps_suppkey              from                    partsupp                where                   ps_partkey in (                                 select                                  p_partkey                               from                                    part                            where                                   p_name like 'mint%'                     )                       and ps_availqty > (                             select                                  0.5 * sum(l_quantity)                           from                                    lineitem                                where                                   l_partkey = ps_partkey                                  and l_suppkey = ps_suppkey                                      and l_shipdate >= '1993-01-01'                                  and l_shipdate < '1993-01-01' + interval '1' year                       )       )       and s_nationkey = n_nationkey   and n_name = 'UNITED STATES' order by   s_name;
     plan: |
@@ -373,24 +376,26 @@ SQL:
           project(s_name="s_name", s_address="s_address")
             hashjoin(condition="n_nationkey = s_nationkey", type="inner")
               project(s_name="s_name", s_address="s_address", s_nationkey="s_nationkey")
-                semihashjoin(condition="s_suppkey = ps_suppkey", type="semi", build="inner", partition=[local])
-                  osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `s_suppkey`, `s_name`, `s_address`, `s_nationkey` from `supplier` as `supplier`")
+                semihashjoin(condition="s_suppkey = ps_suppkey", type="semi", build="inner")
+                  osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_address`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
                   project(ps_suppkey="ps_suppkey")
                     hashjoin(condition="l_partkey = ps_partkey and l_suppkey = ps_suppkey and ps_availqty > ?1 * $f2", type="inner")
-                      hashagg(group="l_partkey,l_suppkey", $f2="sum(l_quantity)")
+                      hashagg(group="l_partkey,l_suppkey", $f2="sum($f2)")
                         exchange(distribution=hash[1]96, collation=[])
-                          semihashjoin(condition="l_partkey = ps_partkey and l_suppkey = ps_suppkey", type="semi", build="inner")
-                            osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_partkey`, `l_suppkey`, `l_quantity` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(?, interval '1' year)) and (`l_shipdate` >= ?))")
-                            exchange(distribution=broadcast, collation=[])
-                              semihashjoin(condition="ps_partkey = p_partkey", type="semi", build="inner", partition=[local])
-                                osstablescan(tables="partsupp[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp` as `partsupp`")
-                                osstablescan(tables="part[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey` from `part` as `part` where (`p_name` like ?)")
+                          partialhashagg(group="l_partkey,l_suppkey", $f2="sum(l_quantity)")
+                            semihashjoin(condition="l_partkey = ps_partkey and l_suppkey = ps_suppkey", type="semi", build="inner")
+                              project(l_quantity="l_quantity", l_partkey="l_partkey", l_suppkey="l_suppkey")
+                                osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_partkey`, `l_suppkey`, `l_quantity` from `lineitem_col_index` as `lineitem_col_index` where ((`l_shipdate` < '1994-01-01') and (`l_shipdate` >= ?))")
+                              exchange(distribution=broadcast, collation=[])
+                                semihashjoin(condition="ps_partkey = p_partkey", type="semi", build="inner", partition=[local])
+                                  osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp_col_index` as `partsupp_col_index`")
+                                  osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey` from `part_col_index` as `part_col_index` where (`p_name` like ?)")
                       exchange(distribution=hash[1]96, collation=[])
                         semihashjoin(condition="ps_partkey = p_partkey", type="semi", build="inner", partition=[local])
-                          osstablescan(tables="partsupp[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp` as `partsupp`")
-                          osstablescan(tables="part[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey` from `part` as `part` where (`p_name` like ?)")
+                          osstablescan(tables="partsupp_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp_col_index` as `partsupp_col_index`")
+                          osstablescan(tables="part_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `p_partkey` from `part_col_index` as `part_col_index` where (`p_name` like ?)")
               exchange(distribution=broadcast, collation=[])
-                osstablescan(tables="nation", shardcount=0, sql="select `n_nationkey` from `nation` as `nation` where (`n_name` = ?)")
+                osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey` from `nation_col_index` as `nation_col_index` where (`n_name` = ?)")
   - sql: |
       select   s_name,         count(*) as numwait from        supplier,       lineitem l1,    orders,         nation where    s_suppkey = l1.l_suppkey        and o_orderkey = l1.l_orderkey  and o_orderstatus = 'F'         and l1.l_receiptdate > l1.l_commitdate  and exists (            select                  *               from                    lineitem l2             where                   l2.l_orderkey = l1.l_orderkey                   and l2.l_suppkey <> l1.l_suppkey        )       and not exists (                select                  *               from                    lineitem l3             where                   l3.l_orderkey = l1.l_orderkey                   and l3.l_suppkey <> l1.l_suppkey                        and l3.l_receiptdate > l3.l_commitdate  )       and s_nationkey = n_nationkey   and n_name = 'ARGENTINA' group by       s_name order by         numwait desc,   s_name limit 100;
     plan: |
@@ -401,55 +406,57 @@ SQL:
               exchange(distribution=hash[0]96, collation=[])
                 partialhashagg(group="s_name", numwait="count()")
                   hashjoin(condition="l_orderkey = o_orderkey", type="inner")
-                    osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `o_orderkey` from `orders` as `orders` where (`o_orderstatus` = ?)")
+                    osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `o_orderkey` from `orders_col_index` as `orders_col_index` where (`o_orderstatus` = ?)")
                     semihashjoin(condition="l_orderkey = l_orderkey and l_suppkey <> l_suppkey", type="semi", build="outer")
                       semihashjoin(condition="l_orderkey = l_orderkey and l_suppkey <> l_suppkey", type="anti", build="outer", partition=[local])
                         project(s_suppkey="s_suppkey", s_name="s_name", s_nationkey="s_nationkey", n_nationkey="n_nationkey", l_orderkey="l_orderkey", l_suppkey="l_suppkey")
                           hashjoin(condition="l_suppkey = s_suppkey", type="inner")
-                            osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem` where (`l_receiptdate` > `l_commitdate`)")
+                            osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_suppkey` from `lineitem_col_index` as `lineitem_col_index` where (`l_receiptdate` > `l_commitdate`)")
                             exchange(distribution=broadcast, collation=[])
                               hashjoin(condition="n_nationkey = s_nationkey", type="inner")
-                                osstablescan(tables="supplier[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_nationkey` from `supplier` as `supplier`")
+                                osstablescan(tables="supplier_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `s_suppkey`, `s_name`, `s_nationkey` from `supplier_col_index` as `supplier_col_index`")
                                 exchange(distribution=broadcast, collation=[])
-                                  osstablescan(tables="nation", shardcount=0, sql="select `n_nationkey` from `nation` as `nation` where (`n_name` = ?)")
-                        osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem` where (`l_receiptdate` > `l_commitdate`)")
-                      osstablescan(tables="lineitem[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem`")
+                                  osstablescan(tables="nation_col_index[p1]", sql="select `n_nationkey` from `nation_col_index` as `nation_col_index` where (`n_name` = ?)")
+                        osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[local, remote], sql="select `l_orderkey`, `l_suppkey` from `lineitem_col_index` as `lineitem_col_index` where (`l_receiptdate` > `l_commitdate`)")
+                      osstablescan(tables="lineitem_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `l_orderkey`, `l_suppkey` from `lineitem_col_index` as `lineitem_col_index`")
   - sql: |
       select   cntrycode,      count(*) as numcust,    sum(c_acctbal) as totacctbal from       (               select                  substring(c_phone from 1 for 2) as cntrycode,                   c_acctbal               from                    customer                where                   substring(c_phone from 1 for 2) in                              ('34', '24', '30', '26', '29', '17', '33')                      and c_acctbal > (                               select                                  avg(c_acctbal)                          from                                    customer                                where                                   c_acctbal > 0.00                                        and substring(c_phone from 1 for 2) in                                          ('34', '24', '30', '26', '29', '17', '33')                      )                       and not exists (                                select                                  *                               from                                    orders                          where                                   o_custkey = c_custkey                   )       ) as custsale group by  cntrycode order by      cntrycode;
     plan: |
       exchange(distribution=single, collation=[0 asc-nulls-first])
         memsort(sort="cntrycode asc")
-          hashagg(group="cntrycode", numcust="count()", totacctbal="sum(c_acctbal)")
+          hashagg(group="cntrycode", numcust="sum(numcust)", totacctbal="sum(totacctbal)")
             exchange(distribution=hash[0]96, collation=[])
-              project(cntrycode="substring(c_phone, ?0, ?1)", c_acctbal="c_acctbal")
-                semihashjoin(condition="o_custkey = c_custkey", type="anti", build="outer")
-                  project($f0="$f0", $f1="$f1", c_custkey="c_custkey", c_phone="c_phone", c_acctbal="c_acctbal")
-                    nljoin(condition="c_acctbal > $f0 / $f1", type="inner")
-                      osstablescan(tables="customer[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_phone`, `c_acctbal` from `customer` as `customer` where ((substring(`c_phone`, ?, ?)) in(?))")
-                      exchange(distribution=broadcast, collation=[])
-                        hashagg($f0="sum($f0)", $f1="sum($f1)")
-                          exchange(distribution=single, collation=[])
-                            partialhashagg($f0="sum(c_acctbal)", $f1="count()")
-                              osstablescan(tables="customer[p1,p2,p3,...p96]", shardcount=96, sql="select `c_acctbal` from `customer` as `customer` where (((substring(`c_phone`, ?, ?)) in(?)) and (`c_acctbal` > ?))")
-                  exchange(distribution=hash[0]96, collation=[])
-                    osstablescan(tables="orders[p1,p2,p3,...p96]", shardcount=96, sql="select `o_custkey` from `orders` as `orders`")
+              partialhashagg(group="cntrycode", numcust="count()", totacctbal="sum(c_acctbal)")
+                project(cntrycode="substring(c_phone, ?0, ?1)", c_acctbal="c_acctbal")
+                  semihashjoin(condition="o_custkey = c_custkey", type="anti", build="outer")
+                    project($f0="$f0", $f1="$f1", c_custkey="c_custkey", c_phone="c_phone", c_acctbal="c_acctbal")
+                      nljoin(condition="c_acctbal > $f0 / $f1", type="inner")
+                        osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, partition=[remote], sql="select `c_custkey`, `c_phone`, `c_acctbal` from `customer_col_index` as `customer_col_index` where ((substring(`c_phone`, ?, ?)) in(?))")
+                        exchange(distribution=broadcast, collation=[])
+                          hashagg($f0="sum($f0)", $f1="sum($f1)")
+                            exchange(distribution=single, collation=[])
+                              partialhashagg($f0="sum(c_acctbal)", $f1="count()")
+                                osstablescan(tables="customer_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `c_acctbal` from `customer_col_index` as `customer_col_index` where (((substring(`c_phone`, ?, ?)) in(?)) and (`c_acctbal` > ?))")
+                    exchange(distribution=hash[0]96, collation=[])
+                      osstablescan(tables="orders_col_index[p1,p2,p3,...p96]", shardcount=96, sql="select `o_custkey` from `orders_col_index` as `orders_col_index`")
 DDL:
   customer:
-    CREATE TABLE `customer` ( 	`c_custkey` int(11) NOT NULL, 	`c_name` varchar(25) NOT NULL, 	`c_address` varchar(40) NOT NULL, 	`c_nationkey` int(11) NOT NULL, 	`c_phone` varchar(15) NOT NULL, 	`c_acctbal` decimal(15, 2) NOT NULL, 	`c_mktsegment` varchar(10) NOT NULL, 	`c_comment` varchar(117) NOT NULL, 	PRIMARY KEY (`c_custkey`) ) ENGINE = 'LOCAL_DISK' DEFAULT CHARSET = latin1 PARTITION BY KEY (`c_custkey`) PARTITIONS 96;
+    CREATE TABLE IF NOT EXISTS `customer` (  `c_custkey` int(11) NOT NULL,  `c_name` varchar(25) NOT NULL,  `c_address` varchar(40) NOT NULL,  `c_nationkey` int(11) NOT NULL,  `c_phone` varchar(15) NOT NULL,  `c_acctbal` decimal(15, 2) NOT NULL,  `c_mktsegment` varchar(10) NOT NULL,  `c_comment` varchar(117) NOT NULL,  PRIMARY KEY (`c_custkey`),  CLUSTERED COLUMNAR INDEX `customer_col_index`(`c_custkey`) PARTITION BY HASH (`c_custkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`c_custkey`) PARTITIONS 128;
   lineitem:
-    CREATE TABLE `lineitem` ( 	`l_orderkey` bigint(20) NOT NULL, 	`l_partkey` int(11) NOT NULL, 	`l_suppkey` int(11) NOT NULL, 	`l_linenumber` bigint(20) NOT NULL, 	`l_quantity` decimal(15, 2) NOT NULL, 	`l_extendedprice` decimal(15, 2) NOT NULL, 	`l_discount` decimal(15, 2) NOT NULL, 	`l_tax` decimal(15, 2) NOT NULL, 	`l_returnflag` varchar(1) NOT NULL, 	`l_linestatus` varchar(1) NOT NULL, 	`l_shipdate` date NOT NULL, 	`l_commitdate` date NOT NULL, 	`l_receiptdate` date NOT NULL, 	`l_shipinstruct` varchar(25) NOT NULL, 	`l_shipmode` varchar(10) NOT NULL, 	`l_comment` varchar(44) NOT NULL, 	PRIMARY KEY (`l_orderkey`, `l_linenumber`), 	KEY `i_l_partkey` (`l_partkey`), 	KEY `auto_shard_key_l_orderkey` USING BTREE (`l_orderkey`) ) ENGINE = 'LOCAL_DISK' DEFAULT CHARSET = latin1 PARTITION BY KEY (`l_orderkey`) PARTITIONS 96;
+    CREATE TABLE IF NOT EXISTS `lineitem` (  `l_orderkey` bigint(20) NOT NULL,  `l_partkey` int(11) NOT NULL,  `l_suppkey` int(11) NOT NULL,  `l_linenumber` bigint(20) NOT NULL,  `l_quantity` decimal(15, 2) NOT NULL,  `l_extendedprice` decimal(15, 2) NOT NULL,  `l_discount` decimal(15, 2) NOT NULL,  `l_tax` decimal(15, 2) NOT NULL,  `l_returnflag` varchar(1) NOT NULL,  `l_linestatus` varchar(1) NOT NULL,  `l_shipdate` date NOT NULL,  `l_commitdate` date NOT NULL,  `l_receiptdate` date NOT NULL,  `l_shipinstruct` varchar(25) NOT NULL,  `l_shipmode` varchar(10) NOT NULL,  `l_comment` varchar(44) NOT NULL,  PRIMARY KEY (`l_orderkey`, `l_linenumber`),  CLUSTERED COLUMNAR INDEX `lineitem_col_index`(`l_shipdate`, `l_orderkey`) PARTITION BY HASH (`l_orderkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`l_orderkey`) PARTITIONS 128;
   nation:
-    CREATE TABLE `nation` ( 	`n_nationkey` int(11) NOT NULL, 	`n_name` varchar(25) NOT NULL, 	`n_regionkey` int(11) NOT NULL, 	`n_comment` varchar(152) DEFAULT NULL, 	PRIMARY KEY (`n_nationkey`) ) BROADCAST ENGINE = 'LOCAL_DISK' DEFAULT CHARSET = latin1;
+    CREATE TABLE IF NOT EXISTS `nation` (  `n_nationkey` int(11) NOT NULL,  `n_name` varchar(25) NOT NULL,  `n_regionkey` int(11) NOT NULL,  `n_comment` varchar(152) DEFAULT NULL,  PRIMARY KEY (`n_nationkey`),  CLUSTERED COLUMNAR INDEX `nation_col_index`(`n_nationkey`) PARTITION BY HASH (`n_nationkey`) PARTITIONS 1 ) BROADCAST ENGINE = InnoDB DEFAULT CHARSET = latin1;
   orders:
-    CREATE TABLE `orders` ( 	`o_orderkey` bigint(20) NOT NULL, 	`o_custkey` int(11) NOT NULL, 	`o_orderstatus` varchar(1) NOT NULL, 	`o_totalprice` decimal(15, 2) NOT NULL, 	`o_orderdate` date NOT NULL, 	`o_orderpriority` varchar(15) NOT NULL, 	`o_clerk` varchar(15) NOT NULL, 	`o_shippriority` bigint(20) NOT NULL, 	`o_comment` varchar(79) NOT NULL, 	PRIMARY KEY (`o_orderkey`), 	KEY `auto_shard_key_o_orderkey` USING BTREE (`o_orderkey`) ) ENGINE = 'LOCAL_DISK' DEFAULT CHARSET = latin1 PARTITION BY KEY (`o_orderkey`) PARTITIONS 96;
+    CREATE TABLE IF NOT EXISTS `orders` (  `o_orderkey` bigint(20) NOT NULL,  `o_custkey` int(11) NOT NULL,  `o_orderstatus` varchar(1) NOT NULL,  `o_totalprice` decimal(15, 2) NOT NULL,  `o_orderdate` date NOT NULL,  `o_orderpriority` varchar(15) NOT NULL,  `o_clerk` varchar(15) NOT NULL,  `o_shippriority` bigint(20) NOT NULL,  `o_comment` varchar(79) NOT NULL,  PRIMARY KEY (`o_orderkey`),  CLUSTERED COLUMNAR INDEX `orders_col_index`(`o_orderdate`, `o_orderkey`) PARTITION BY HASH (`o_orderkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`o_orderkey`) PARTITIONS 128;
   part:
-    CREATE TABLE `part` ( 	`p_partkey` int(11) NOT NULL, 	`p_name` varchar(55) NOT NULL, 	`p_mfgr` varchar(25) NOT NULL, 	`p_brand` varchar(10) NOT NULL, 	`p_type` varchar(25) NOT NULL, 	`p_size` int(11) NOT NULL, 	`p_container` varchar(10) NOT NULL, 	`p_retailprice` decimal(15, 2) NOT NULL, 	`p_comment` varchar(23) NOT NULL, 	PRIMARY KEY (`p_partkey`) ) ENGINE = 'LOCAL_DISK' DEFAULT CHARSET = latin1 PARTITION BY KEY (`p_partkey`) PARTITIONS 96;
+    CREATE TABLE IF NOT EXISTS `part` (  `p_partkey` int(11) NOT NULL,  `p_name` varchar(55) NOT NULL,  `p_mfgr` varchar(25) NOT NULL,  `p_brand` varchar(10) NOT NULL,  `p_type` varchar(25) NOT NULL,  `p_size` int(11) NOT NULL,  `p_container` varchar(10) NOT NULL,  `p_retailprice` decimal(15, 2) NOT NULL,  `p_comment` varchar(23) NOT NULL,  PRIMARY KEY (`p_partkey`),  CLUSTERED COLUMNAR INDEX `part_col_index`(`p_size`) PARTITION BY HASH (`p_partkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`p_partkey`) PARTITIONS 128;
   partsupp:
-    CREATE TABLE `partsupp` ( 	`ps_partkey` int(11) NOT NULL, 	`ps_suppkey` int(11) NOT NULL, 	`ps_availqty` int(11) NOT NULL, 	`ps_supplycost` decimal(15, 2) NOT NULL, 	`ps_comment` varchar(199) NOT NULL, 	PRIMARY KEY (`ps_partkey`, `ps_suppkey`), 	KEY `IDX_PARTSUPP_SUPPKEY` (`ps_suppkey`) ) ENGINE = 'LOCAL_DISK' DEFAULT CHARSET = latin1 PARTITION BY KEY (`ps_partkey`) PARTITIONS 96;
+    CREATE TABLE IF NOT EXISTS `partsupp` (  `ps_partkey` int(11) NOT NULL,  `ps_suppkey` int(11) NOT NULL,  `ps_availqty` int(11) NOT NULL,  `ps_supplycost` decimal(15, 2) NOT NULL,  `ps_comment` varchar(199) NOT NULL,  PRIMARY KEY (`ps_partkey`, `ps_suppkey`),  CLUSTERED COLUMNAR INDEX `partsupp_col_index`(`ps_partkey`) PARTITION BY HASH (`ps_partkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`ps_partkey`) PARTITIONS 128;
   region:
-    CREATE TABLE `region` ( 	`r_regionkey` int(11) NOT NULL, 	`r_name` varchar(25) NOT NULL, 	`r_comment` varchar(152) DEFAULT NULL, 	PRIMARY KEY (`r_regionkey`) ) BROADCAST ENGINE = 'LOCAL_DISK' DEFAULT CHARSET = latin1;
+    CREATE TABLE IF NOT EXISTS `region` (  `r_regionkey` int(11) NOT NULL,  `r_name` varchar(25) NOT NULL,  `r_comment` varchar(152) DEFAULT NULL,  PRIMARY KEY (`r_regionkey`),  CLUSTERED COLUMNAR INDEX `region_col_index`(`r_regionkey`) PARTITION BY HASH (`r_regionkey`) PARTITIONS 1 ) BROADCAST ENGINE = InnoDB DEFAULT CHARSET = latin1;
   supplier:
-    CREATE TABLE `supplier` ( 	`s_suppkey` int(11) NOT NULL, 	`s_name` varchar(25) NOT NULL, 	`s_address` varchar(40) NOT NULL, 	`s_nationkey` int(11) NOT NULL, 	`s_phone` varchar(15) NOT NULL, 	`s_acctbal` decimal(15, 2) NOT NULL, 	`s_comment` varchar(101) NOT NULL, 	PRIMARY KEY (`s_suppkey`) ) ENGINE = 'LOCAL_DISK' DEFAULT CHARSET = latin1 PARTITION BY KEY (`s_suppkey`) PARTITIONS 96;
+    CREATE TABLE IF NOT EXISTS `supplier` (  `s_suppkey` int(11) NOT NULL,  `s_name` varchar(25) NOT NULL,  `s_address` varchar(40) NOT NULL,  `s_nationkey` int(11) NOT NULL,  `s_phone` varchar(15) NOT NULL,  `s_acctbal` decimal(15, 2) NOT NULL,  `s_comment` varchar(101) NOT NULL,  PRIMARY KEY (`s_suppkey`),  CLUSTERED COLUMNAR INDEX `supplier_col_index`(`s_suppkey`) PARTITION BY HASH (`s_suppkey`) PARTITIONS 96 ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY (`s_suppkey`) PARTITIONS 128;
+
 STATISTICS:
   customer:
     168648768
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/WindowTypeTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/WindowTypeTest.yml
index 44f3ce319..16807dc05 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/WindowTypeTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/oss/WindowTypeTest.yml
@@ -76,8 +76,7 @@ SQL:
                   exchange(distribution=hash[1], collation=[])
                     bkajoin(condition="l_partkey = p_partkey", type="inner")
                       logicalview(tables="part[p1,p2,p3,p4]", shardcount=4, sql="select `p_partkey` from `part` as `part` where (`p_brand` = 'brand#51')")
-                      logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem` where (`l_partkey` in (...))")
-
+                      logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem` force index(`i_l_partkey`) where (`l_partkey` in (...))")
   - sql: |
       select          
         l_shipdate,          
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGlobalCoveringIndexAdvisorPlanTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGlobalCoveringIndexAdvisorPlanTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGlobalCoveringIndexAdvisorPlanTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGlobalCoveringIndexAdvisorPlanTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGlobalCoveringIndexAdvisorPlanTest.yml
index cf4d60309..444d03f69 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGlobalCoveringIndexAdvisorPlanTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGlobalCoveringIndexAdvisorPlanTest.yml
@@ -52,13 +52,12 @@
     memsort(sort="value desc")
       project(ps_partkey="ps_partkey", value="value")
         nljoin(condition="value > $f0 * 0.0001", type="inner")
-          hashagg(group="ps_partkey", value="sum(__*__)")
+          hashagg(group="ps_partkey", value="sum(value)")
             gather(concurrent=true)
-              indexscan(tables="supplier[p1,p2,p3,p4],nation,partsupp__what_if_gsi_ps_suppkey[p1,p2,p3,p4]", shardcount=4, sql="select `supplier`.`s_suppkey`, `partsupp__what_if_gsi_ps_suppkey`.`ps_partkey`, `partsupp__what_if_gsi_ps_suppkey`.`ps_suppkey`, (`partsupp__what_if_gsi_ps_suppkey`.`ps_supplycost` * `partsupp__what_if_gsi_ps_suppkey`.`ps_availqty`) as `__*__` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany')) inner join `partsupp__what_if_gsi_ps_suppkey` as `partsupp__what_if_gsi_ps_suppkey` on (`supplier`.`s_suppkey` = `partsupp__what_if_gsi_ps_suppkey`.`ps_suppkey`)")
+              indexscan(tables="supplier[p1,p2,p3,p4],nation,partsupp__what_if_gsi_ps_suppkey[p1,p2,p3,p4]", shardcount=4, sql="select `partsupp__what_if_gsi_ps_suppkey`.`ps_partkey`, sum((`partsupp__what_if_gsi_ps_suppkey`.`ps_supplycost` * `partsupp__what_if_gsi_ps_suppkey`.`ps_availqty`)) as `value` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany')) inner join `partsupp__what_if_gsi_ps_suppkey` as `partsupp__what_if_gsi_ps_suppkey` on (`supplier`.`s_suppkey` = `partsupp__what_if_gsi_ps_suppkey`.`ps_suppkey`) group by `partsupp__what_if_gsi_ps_suppkey`.`ps_partkey`")
           hashagg($f0="sum($f0)")
             gather(concurrent=true)
               indexscan(tables="supplier[p1,p2,p3,p4],nation,partsupp__what_if_gsi_ps_suppkey[p1,p2,p3,p4]", shardcount=4, sql="select sum((`partsupp__what_if_gsi_ps_suppkey`.`ps_supplycost` * `partsupp__what_if_gsi_ps_suppkey`.`ps_availqty`)) as `$f0` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany')) inner join `partsupp__what_if_gsi_ps_suppkey` as `partsupp__what_if_gsi_ps_suppkey` on (`supplier`.`s_suppkey` = `partsupp__what_if_gsi_ps_suppkey`.`ps_suppkey`)")
-
 - sql: |
     select
     sum(l_extendedprice * (1 - l_discount) ) as revenue
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGlobalIndexAdvisorPlanTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGlobalIndexAdvisorPlanTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGlobalIndexAdvisorPlanTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGsiPlanTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGsiPlanTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGsiPlanTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGsiPlanTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGsiPlanTest.ddl.yml
index 4bca7c0c1..af5c4fe3d 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGsiPlanTest.ddl.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGsiPlanTest.ddl.yml
@@ -1,3 +1,10 @@
+test_compound_key:
+  CREATE TABLE `test_compound_key` (
+  `id` bigint(20) NOT NULL,
+  `name` bigint(20) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`ID`) subpartition by hash(`NAME`) subpartitions 2;
 t_order:
   CREATE TABLE `t_order` (
   `id` bigint(11) NOT NULL AUTO_INCREMENT,
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGsiPlanTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGsiPlanTest.yml
index 7a480504e..f345c6700 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGsiPlanTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionGsiPlanTest.yml
@@ -863,7 +863,7 @@
     delete from orders where o_custkey = 1
 
   plan: |
-    LogicalModify(TYPE="DELETE", TABLES="optest.orders")
+    LogicalModify(TYPE="DELETE", TABLES="optest.orders", optimizebyreturning=true)
       Project(o_orderkey="o_orderkey", o_custkey="o_custkey", o_orderstatus="o_orderstatus", o_totalprice="o_totalprice", o_orderdate="o_orderdate", o_orderpriority="o_orderpriority", o_clerk="o_clerk", o_shippriority="o_shippriority", o_comment="o_comment")
         bkajoin(condition="o_orderkey = o_orderkey", type="inner")
           IndexScan(tables="orders_idx_custkey[p4]", sql="SELECT `o_orderkey`, `o_custkey` FROM `orders_idx_custkey` AS `orders_idx_custkey` WHERE (`o_custkey` = 1) FOR UPDATE")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionLocalIndexAdvisorPlanTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionLocalIndexAdvisorPlanTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionLocalIndexAdvisorPlanTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionPlanTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionPlanTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionPlanTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionPlanTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionPlanTest.yml
index e58bb1608..d9999eba8 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionPlanTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionPlanTest.yml
@@ -60,7 +60,8 @@
     select * from t_a_range where a in (1,2)
 
   plan: |
-    phytableoperation(tables="t_a_range[p0]", sql="select `t_a_range`.`a`, `t_a_range`.`b` from ? as `t_a_range` where (`t_a_range`.`a` in (1, 2))")
+    gather(concurrent=true)
+      logicalview(tables="t_a_range[p0]", sql="select `a`, `b` from `t_a_range` as `t_a_range` where (`a` in(1, 2))")
 
 - sql: |
     select * from t_a_range where a < 1 or a > 20
@@ -75,9 +76,8 @@
     select * from t_a_list where a in (10,30)
 
   plan: |
-    phytableoperation(tables="t_a_list[p0]", sql="select `t_a_list`.`a`, `t_a_list`.`b` from ? as `t_a_list` where (`t_a_list`.`a` in (10, 30))")
-
-
+    gather(concurrent=true)
+      logicalview(tables="t_a_list[p0]", sql="select `a`, `b` from `t_a_list` as `t_a_list` where (`a` in(10, 30))")
 - sql: |
     select * from t_ab_range join t_ab_hash on t_ab_range.a = t_ab_hash.a and t_ab_range.b = t_ab_hash.b
 
@@ -161,8 +161,8 @@
     select * from t_range_bigint where (bigint_test < 10 or bigint_test > 10000) and pk = 1 and (bigint_test < 20)
 
   plan: |
-    phytableoperation(tables="t_range_bigint[p0]", sql="select `t_range_bigint`.`pk`, `t_range_bigint`.`integer_test`, `t_range_bigint`.`varchar_test`, `t_range_bigint`.`char_test`, `t_range_bigint`.`blob_test`, `t_range_bigint`.`tinyint_test`, `t_range_bigint`.`tinyint_1bit_test`, `t_range_bigint`.`smallint_test`, `t_range_bigint`.`mediumint_test`, `t_range_bigint`.`bit_test`, `t_range_bigint`.`bigint_test`, `t_range_bigint`.`float_test`, `t_range_bigint`.`double_test`, `t_range_bigint`.`decimal_test`, `t_range_bigint`.`date_test`, `t_range_bigint`.`time_test`, `t_range_bigint`.`datetime_test`, `t_range_bigint`.`timestamp_test`, `t_range_bigint`.`year_test`, `t_range_bigint`.`mediumtext_test` from ? as `t_range_bigint` where (((`t_range_bigint`.`bigint_test` < 10) or (`t_range_bigint`.`bigint_test` > 10000)) and (`t_range_bigint`.`pk` = 1) and (`t_range_bigint`.`bigint_test` < 20))")
-
+    gather(concurrent=true)
+      logicalview(tables="t_range_bigint[p0]", sql="select `pk`, `integer_test`, `varchar_test`, `char_test`, `blob_test`, `tinyint_test`, `tinyint_1bit_test`, `smallint_test`, `mediumint_test`, `bit_test`, `bigint_test`, `float_test`, `double_test`, `decimal_test`, `date_test`, `time_test`, `datetime_test`, `timestamp_test`, `year_test`, `mediumtext_test` from `t_range_bigint` as `t_range_bigint` where ((`pk` = 1) and (`bigint_test` < 20) and ((`bigint_test` < 10) or (`bigint_test` > 10000)))")
 - sql: |
     select * from t_range_bigint where (bigint_test < 10 or bigint_test > 10000) and pk = 1 and (bigint_test between 5 and 10005)
 
@@ -173,8 +173,8 @@
     select * from t_range_bigint where (bigint_test < 10 or bigint_test > 10000) and pk = 1 and (bigint_test between 20 and 10005)
 
   plan: |
-    phytableoperation(tables="t_range_bigint[p2]", sql="select `t_range_bigint`.`pk`, `t_range_bigint`.`integer_test`, `t_range_bigint`.`varchar_test`, `t_range_bigint`.`char_test`, `t_range_bigint`.`blob_test`, `t_range_bigint`.`tinyint_test`, `t_range_bigint`.`tinyint_1bit_test`, `t_range_bigint`.`smallint_test`, `t_range_bigint`.`mediumint_test`, `t_range_bigint`.`bit_test`, `t_range_bigint`.`bigint_test`, `t_range_bigint`.`float_test`, `t_range_bigint`.`double_test`, `t_range_bigint`.`decimal_test`, `t_range_bigint`.`date_test`, `t_range_bigint`.`time_test`, `t_range_bigint`.`datetime_test`, `t_range_bigint`.`timestamp_test`, `t_range_bigint`.`year_test`, `t_range_bigint`.`mediumtext_test` from ? as `t_range_bigint` where (((`t_range_bigint`.`bigint_test` < 10) or (`t_range_bigint`.`bigint_test` > 10000)) and (`t_range_bigint`.`pk` = 1) and (`t_range_bigint`.`bigint_test` between 20 and 10005))")
-
+    gather(concurrent=true)
+      logicalview(tables="t_range_bigint[p2]", sql="select `pk`, `integer_test`, `varchar_test`, `char_test`, `blob_test`, `tinyint_test`, `tinyint_1bit_test`, `smallint_test`, `mediumint_test`, `bit_test`, `bigint_test`, `float_test`, `double_test`, `decimal_test`, `date_test`, `time_test`, `datetime_test`, `timestamp_test`, `year_test`, `mediumtext_test` from `t_range_bigint` as `t_range_bigint` where ((`pk` = 1) and (`bigint_test` between 20 and 10005) and ((`bigint_test` < 10) or (`bigint_test` > 10000)))")
 - sql: |
     select * from t_range_bigint where (bigint_test < 10 or bigint_test > 10000) and pk = 1 and (bigint_test between 20 and 9999)
 
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.ddl.yml
new file mode 100644
index 000000000..e9ad3ef6a
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.ddl.yml
@@ -0,0 +1,438 @@
+customer:
+  CREATE TABLE `customer` (
+  `c_custkey` int(11) NOT NULL,
+  `c_name` varchar(25) NOT NULL,
+  `c_address` varchar(40) NOT NULL,
+  `c_nationkey` int(11) NOT NULL,
+  `c_phone` varchar(15) NOT NULL,
+  `c_acctbal` decimal(15,2) NOT NULL,
+  `c_mktsegment` varchar(10) NOT NULL,
+  `c_comment` varchar(117) NOT NULL,
+  PRIMARY KEY (`c_custkey`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY HASH(c_custkey) PARTITIONS 4;
+
+lineitem:
+  CREATE TABLE `lineitem` (
+  `l_orderkey` int(11) NOT NULL,
+  `l_partkey` int(11) NOT NULL,
+  `l_suppkey` int(11) NOT NULL,
+  `l_linenumber` int(11) NOT NULL,
+  `l_quantity` decimal(15,2) NOT NULL,
+  `l_extendedprice` decimal(15,2) NOT NULL,
+  `l_discount` decimal(15,2) NOT NULL,
+  `l_tax` decimal(15,2) NOT NULL,
+  `l_returnflag` varchar(1) NOT NULL,
+  `l_linestatus` varchar(1) NOT NULL,
+  `l_shipdate` date NOT NULL,
+  `l_commitdate` date NOT NULL,
+  `l_receiptdate` date NOT NULL,
+  `l_shipinstruct` varchar(25) NOT NULL,
+  `l_shipmode` varchar(10) NOT NULL,
+  `l_comment` varchar(44) NOT NULL,
+  PRIMARY KEY (`l_orderkey`,`l_linenumber`),
+  KEY `i_l_partkey` (`l_partkey`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY HASH(l_orderkey) PARTITIONS 4;
+
+nation:
+  CREATE TABLE `nation` (
+  `n_nationkey` int(11) NOT NULL,
+  `n_name` varchar(25) NOT NULL,
+  `n_regionkey` int(11) NOT NULL,
+  `n_comment` varchar(152) DEFAULT NULL,
+  PRIMARY KEY (`n_nationkey`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=latin1 broadcast;
+
+orders:
+  CREATE TABLE `orders` (
+  `o_orderkey` int(11) NOT NULL,
+  `o_custkey` int(11) NOT NULL,
+  `o_orderstatus` varchar(1) NOT NULL,
+  `o_totalprice` decimal(15,2) NOT NULL,
+  `o_orderdate` date NOT NULL,
+  `o_orderpriority` varchar(15) NOT NULL,
+  `o_clerk` varchar(15) NOT NULL,
+  `o_shippriority` int(11) NOT NULL,
+  `o_comment` varchar(79) NOT NULL,
+  PRIMARY KEY (`o_orderkey`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY HASH(O_ORDERKEY) PARTITIONS 4;
+
+part:
+  CREATE TABLE `part` (
+  `p_partkey` int(11) NOT NULL,
+  `p_name` varchar(55) NOT NULL,
+  `p_mfgr` varchar(25) NOT NULL,
+  `p_brand` varchar(10) NOT NULL,
+  `p_type` varchar(25) NOT NULL,
+  `p_size` int(11) NOT NULL,
+  `p_container` varchar(10) NOT NULL,
+  `p_retailprice` decimal(15,2) NOT NULL,
+  `p_comment` varchar(23) NOT NULL,
+  PRIMARY KEY (`p_partkey`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY HASH(p_partkey) PARTITIONS 4;
+
+partsupp:
+  CREATE TABLE `partsupp` (
+  `ps_partkey` int(11) NOT NULL,
+  `ps_suppkey` int(11) NOT NULL,
+  `ps_availqty` int(11) NOT NULL,
+  `ps_supplycost` decimal(15,2) NOT NULL,
+  `ps_comment` varchar(199) NOT NULL,
+  PRIMARY KEY (`ps_partkey`,`ps_suppkey`),
+  KEY `IDX_PARTSUPP_SUPPKEY` (`PS_SUPPKEY`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY HASH(ps_partkey) PARTITIONS 4;
+
+region:
+  CREATE TABLE `region` (
+  `r_regionkey` int(11) NOT NULL,
+  `r_name` varchar(25) NOT NULL,
+  `r_comment` varchar(152) DEFAULT NULL,
+  PRIMARY KEY (`r_regionkey`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=latin1 broadcast;
+
+supplier:
+  CREATE TABLE `supplier` (
+  `s_suppkey` int(11) NOT NULL,
+  `s_name` varchar(25) NOT NULL,
+  `s_address` varchar(40) NOT NULL,
+  `s_nationkey` int(11) NOT NULL,
+  `s_phone` varchar(15) NOT NULL,
+  `s_acctbal` decimal(15,2) NOT NULL,
+  `s_comment` varchar(101) NOT NULL,
+  PRIMARY KEY (`s_suppkey`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=latin1 PARTITION BY HASH(s_suppkey) PARTITIONS 4;
+
+t_a_hash:
+  CREATE TABLE `t_a_hash` (
+  `a` int(11) NOT NULL,
+  `b` int(11) NOT NULL,
+  PRIMARY KEY (`a`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY HASH(a) PARTITIONS 4
+
+
+t_ab_hash:
+  CREATE TABLE `t_ab_hash` (
+  `a` int(11) NOT NULL,
+  `b` int(11) NOT NULL,
+  PRIMARY KEY (`a`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY(a,b) PARTITIONS 4
+
+t_a_range:
+  CREATE TABLE `t_a_range` (
+  `a` int(11) NOT NULL,
+  `b` int(11) NOT NULL,
+  PRIMARY KEY (`a`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = latin1
+  partition by range columns(a)
+  ( partition p0 values less than (10),
+  partition p1 values less than (20),
+  partition p2 values less than (30)
+  );
+
+t_ab_range:
+  CREATE TABLE `t_ab_range` (
+  `a` int(11) NOT NULL,
+  `b` int(11) NOT NULL,
+  PRIMARY KEY (`a`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = latin1
+  partition by range columns(a,b)
+  ( partition p0 values less than (10, 100),
+  partition p1 values less than (20, 200),
+  partition p2 values less than (30, 300)
+  );
+
+t_a_list:
+  CREATE TABLE `t_a_list` (
+  `a` int(11) NOT NULL,
+  `b` int(11) NOT NULL,
+  PRIMARY KEY (`a`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = latin1
+  partition by list columns (a)
+  ( partition p0 values in (10,30),
+  partition p1 values in (20,40)
+  );
+
+t_ab_list:
+  CREATE TABLE `t_ab_list` (
+  `a` int(11) NOT NULL,
+  `b` int(11) NOT NULL,
+  PRIMARY KEY (`a`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = latin1
+  partition by list columns (a,b)
+  ( partition p0 values in ((10, 100),(30, 300)),
+  partition p1 values in ((20, 200),(40, 400))
+  );
+
+t_hash_varchar:
+  CREATE TABLE `t_hash_varchar` (
+  `pk` bigint(11) NOT NULL,
+  `integer_test` int(11) DEFAULT NULL,
+  `varchar_test` varchar(255) DEFAULT NULL,
+  `char_test` char(255) DEFAULT NULL,
+  `blob_test` blob,
+  `tinyint_test` tinyint(4) DEFAULT NULL,
+  `tinyint_1bit_test` tinyint(1) DEFAULT NULL,
+  `smallint_test` smallint(6) DEFAULT NULL,
+  `mediumint_test` mediumint(9) DEFAULT NULL,
+  `bit_test` bit(1) DEFAULT NULL,
+  `bigint_test` bigint(20) DEFAULT NULL,
+  `float_test` float DEFAULT NULL,
+  `double_test` double DEFAULT NULL,
+  `decimal_test` decimal(10, 0) DEFAULT NULL,
+  `date_test` date DEFAULT NULL,
+  `time_test` time DEFAULT NULL,
+  `datetime_test` datetime DEFAULT NULL,
+  `timestamp_test` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  `year_test` year(4) DEFAULT NULL,
+  `mediumtext_test` mediumtext,
+  PRIMARY KEY (`pk`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(varchar_test) PARTITIONS 4
+
+t_hash_bigint:
+  CREATE TABLE `t_hash_bigint` (
+  `pk` bigint(11) NOT NULL,
+  `integer_test` int(11) DEFAULT NULL,
+  `varchar_test` varchar(255) DEFAULT NULL,
+  `char_test` char(255) DEFAULT NULL,
+  `blob_test` blob,
+  `tinyint_test` tinyint(4) DEFAULT NULL,
+  `tinyint_1bit_test` tinyint(1) DEFAULT NULL,
+  `smallint_test` smallint(6) DEFAULT NULL,
+  `mediumint_test` mediumint(9) DEFAULT NULL,
+  `bit_test` bit(1) DEFAULT NULL,
+  `bigint_test` bigint(20) DEFAULT NULL,
+  `float_test` float DEFAULT NULL,
+  `double_test` double DEFAULT NULL,
+  `decimal_test` decimal(10, 0) DEFAULT NULL,
+  `date_test` date DEFAULT NULL,
+  `time_test` time DEFAULT NULL,
+  `datetime_test` datetime DEFAULT NULL,
+  `timestamp_test` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  `year_test` year(4) DEFAULT NULL,
+  `mediumtext_test` mediumtext,
+  PRIMARY KEY (`pk`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(bigint_test) PARTITIONS 4
+
+t_hash_date:
+  CREATE TABLE `t_hash_date` (
+  `pk` bigint(11) NOT NULL,
+  `integer_test` int(11) DEFAULT NULL,
+  `varchar_test` varchar(255) DEFAULT NULL,
+  `char_test` char(255) DEFAULT NULL,
+  `blob_test` blob,
+  `tinyint_test` tinyint(4) DEFAULT NULL,
+  `tinyint_1bit_test` tinyint(1) DEFAULT NULL,
+  `smallint_test` smallint(6) DEFAULT NULL,
+  `mediumint_test` mediumint(9) DEFAULT NULL,
+  `bit_test` bit(1) DEFAULT NULL,
+  `bigint_test` bigint(20) DEFAULT NULL,
+  `float_test` float DEFAULT NULL,
+  `double_test` double DEFAULT NULL,
+  `decimal_test` decimal(10, 0) DEFAULT NULL,
+  `date_test` date DEFAULT NULL,
+  `time_test` time DEFAULT NULL,
+  `datetime_test` datetime DEFAULT NULL,
+  `timestamp_test` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  `year_test` year(4) DEFAULT NULL,
+  `mediumtext_test` mediumtext,
+  PRIMARY KEY (`pk`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(date_test) PARTITIONS 4
+
+t_hash_timestamp:
+  CREATE TABLE `t_hash_timestamp` (
+  `pk` bigint(11) NOT NULL,
+  `integer_test` int(11) DEFAULT NULL,
+  `varchar_test` varchar(255) DEFAULT NULL,
+  `char_test` char(255) DEFAULT NULL,
+  `blob_test` blob,
+  `tinyint_test` tinyint(4) DEFAULT NULL,
+  `tinyint_1bit_test` tinyint(1) DEFAULT NULL,
+  `smallint_test` smallint(6) DEFAULT NULL,
+  `mediumint_test` mediumint(9) DEFAULT NULL,
+  `bit_test` bit(1) DEFAULT NULL,
+  `bigint_test` bigint(20) DEFAULT NULL,
+  `float_test` float DEFAULT NULL,
+  `double_test` double DEFAULT NULL,
+  `decimal_test` decimal(10, 0) DEFAULT NULL,
+  `date_test` date DEFAULT NULL,
+  `time_test` time DEFAULT NULL,
+  `datetime_test` datetime DEFAULT NULL,
+  `timestamp_test` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  `year_test` year(4) DEFAULT NULL,
+  `mediumtext_test` mediumtext,
+  PRIMARY KEY (`pk`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(timestamp_test) PARTITIONS 4
+
+t_range_varchar:
+  CREATE TABLE `t_range_varchar` (
+  `pk` bigint(11) NOT NULL,
+  `integer_test` int(11) DEFAULT NULL,
+  `varchar_test` varchar(255) DEFAULT NULL,
+  `char_test` char(255) DEFAULT NULL,
+  `blob_test` blob,
+  `tinyint_test` tinyint(4) DEFAULT NULL,
+  `tinyint_1bit_test` tinyint(1) DEFAULT NULL,
+  `smallint_test` smallint(6) DEFAULT NULL,
+  `mediumint_test` mediumint(9) DEFAULT NULL,
+  `bit_test` bit(1) DEFAULT NULL,
+  `bigint_test` bigint(20) DEFAULT NULL,
+  `float_test` float DEFAULT NULL,
+  `double_test` double DEFAULT NULL,
+  `decimal_test` decimal(10, 0) DEFAULT NULL,
+  `date_test` date DEFAULT NULL,
+  `time_test` time DEFAULT NULL,
+  `datetime_test` datetime DEFAULT NULL,
+  `timestamp_test` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  `year_test` year(4) DEFAULT NULL,
+  `mediumtext_test` mediumtext,
+  PRIMARY KEY (`pk`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY RANGE COLUMNS(varchar_test) (
+  partition p0 values less than('CCC'),
+  partition p1 values less than('GGG'),
+  partition p2 values less than('ZZZ')
+  )
+t_range_bigint:
+  CREATE TABLE `t_range_bigint` (
+  `pk` bigint(11) NOT NULL,
+  `integer_test` int(11) DEFAULT NULL,
+  `varchar_test` varchar(255) DEFAULT NULL,
+  `char_test` char(255) DEFAULT NULL,
+  `blob_test` blob,
+  `tinyint_test` tinyint(4) DEFAULT NULL,
+  `tinyint_1bit_test` tinyint(1) DEFAULT NULL,
+  `smallint_test` smallint(6) DEFAULT NULL,
+  `mediumint_test` mediumint(9) DEFAULT NULL,
+  `bit_test` bit(1) DEFAULT NULL,
+  `bigint_test` bigint(20) DEFAULT NULL,
+  `float_test` float DEFAULT NULL,
+  `double_test` double DEFAULT NULL,
+  `decimal_test` decimal(10, 0) DEFAULT NULL,
+  `date_test` date DEFAULT NULL,
+  `time_test` time DEFAULT NULL,
+  `datetime_test` datetime DEFAULT NULL,
+  `timestamp_test` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  `year_test` year(4) DEFAULT NULL,
+  `mediumtext_test` mediumtext,
+  PRIMARY KEY (`pk`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY RANGE COLUMNS(bigint_test) (
+  partition p0 values less than(100),
+  partition p1 values less than(1000),
+  partition p2 values less than(100000000)
+  )
+t_range_date:
+  CREATE TABLE `t_range_date` (
+  `pk` bigint(11) NOT NULL,
+  `integer_test` int(11) DEFAULT NULL,
+  `varchar_test` varchar(255) DEFAULT NULL,
+  `char_test` char(255) DEFAULT NULL,
+  `blob_test` blob,
+  `tinyint_test` tinyint(4) DEFAULT NULL,
+  `tinyint_1bit_test` tinyint(1) DEFAULT NULL,
+  `smallint_test` smallint(6) DEFAULT NULL,
+  `mediumint_test` mediumint(9) DEFAULT NULL,
+  `bit_test` bit(1) DEFAULT NULL,
+  `bigint_test` bigint(20) DEFAULT NULL,
+  `float_test` float DEFAULT NULL,
+  `double_test` double DEFAULT NULL,
+  `decimal_test` decimal(10, 0) DEFAULT NULL,
+  `date_test` date DEFAULT NULL,
+  `time_test` time DEFAULT NULL,
+  `datetime_test` datetime DEFAULT NULL,
+  `timestamp_test` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+  `year_test` year(4) DEFAULT NULL,
+  `mediumtext_test` mediumtext,
+  PRIMARY KEY (`pk`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY RANGE COLUMNS(date_test) (
+  partition p0 values less than('2014-02-12'),
+  partition p1 values less than('2021-02-12'),
+  partition p2 values less than('2025-02-12')
+  )
+  
+t_rng_cols:
+  CREATE TABLE `t_rng_cols` (
+  `pk1` bigint(11) NOT NULL,
+  `pk2` bigint(11) NOT NULL,
+  `pk3` bigint(11) NOT NULL,
+  PRIMARY KEY (pk1,pk2)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY RANGE COLUMNS(pk1,pk2) (
+  partition p0 values less than(100, 1000),
+  partition p1 values less than(300, 1000),
+  partition p2 values less than(300, 4000),
+  partition p3 values less than(500, 1000),  
+  partition p4 values less than(500, 8000) 
+  );
+
+t_key:
+  CREATE TABLE `t_key` (
+  `pk1` bigint(11) NOT NULL,
+  `pk2` bigint(11) NOT NULL,
+  `pk3` bigint(11) NOT NULL,
+  PRIMARY KEY (`pk1`)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8 
+  PARTITION BY KEY (pk1)
+  PARTITIONS 4;
+
+random_pruning_test:
+  CREATE TABLE `random_pruning_test` (
+          a bigint(20) NOT NULL,
+          b bigint(20) NOT NULL,
+          c bigint(20) NOT NULL,
+          d bigint(20) NOT NULL,
+          e bigint(20) NOT NULL,         
+          PRIMARY KEY (a,b,c)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4  
+  PARTITION BY RANGE COLUMNS(a,b,c)
+  (PARTITION p1 VALUES LESS THAN (100,1000,10000) ENGINE = InnoDB,
+   PARTITION p2 VALUES LESS THAN (200,2000,20000) ENGINE = InnoDB,
+   PARTITION p3 VALUES LESS THAN (300,3000,30000) ENGINE = InnoDB,
+   PARTITION p4 VALUES LESS THAN (400,4000,40000) ENGINE = InnoDB,
+   PARTITION p5 VALUES LESS THAN (500,5000,50000) ENGINE = InnoDB,
+   PARTITION p6 VALUES LESS THAN (600,6000,60000) ENGINE = InnoDB,
+   PARTITION p7 VALUES LESS THAN (700,7000,70000) ENGINE = InnoDB,
+   PARTITION p8 VALUES LESS THAN (800,8000,80000) ENGINE = InnoDB,
+   PARTITION p9 VALUES LESS THAN (900,9000,90000) ENGINE = InnoDB,
+   PARTITION p10 VALUES LESS THAN (1000,10000,100000) ENGINE = InnoDB);
+
+rng_tbl:
+  CREATE TABLE `rng_tbl` (
+          a bigint(20) NOT NULL,
+          b bigint(20) NOT NULL,
+          c bigint(20) NOT NULL,
+          d bigint(20) NOT NULL,
+          e bigint(20) NOT NULL,         
+          PRIMARY KEY (a,b,c)
+  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4  
+  PARTITION BY RANGE COLUMNS(a)
+  (PARTITION p1 VALUES LESS THAN (100) ENGINE = InnoDB,
+   PARTITION p2 VALUES LESS THAN (200) ENGINE = InnoDB,
+   PARTITION p3 VALUES LESS THAN (300) ENGINE = InnoDB,
+   PARTITION p4 VALUES LESS THAN (400) ENGINE = InnoDB,
+   PARTITION p5 VALUES LESS THAN (500) ENGINE = InnoDB,
+   PARTITION p6 VALUES LESS THAN (600) ENGINE = InnoDB,
+   PARTITION p7 VALUES LESS THAN (700) ENGINE = InnoDB,
+   PARTITION p8 VALUES LESS THAN (800) ENGINE = InnoDB,
+   PARTITION p9 VALUES LESS THAN (900) ENGINE = InnoDB,
+   PARTITION p10 VALUES LESS THAN (1000) ENGINE = InnoDB);
+
+   
+sp_k_r_month:
+  CREATE TABLE `sp_k_r_month` (
+  `id` bigint(18) NOT NULL AUTO_INCREMENT,
+  `vehicle_id` bigint(18) NOT NULL,
+  `snap_time` datetime NOT NULL,
+  `school_id` bigint(18) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+  ) ENGINE = InnoDB AUTO_INCREMENT = 1684206033 DEFAULT CHARSET = utf8
+  PARTITION BY KEY(`school_id`,`id`)
+  PARTITIONS 64
+  SUBPARTITION BY RANGE(MONTH(`snap_time`))
+  (SUBPARTITION `sp2` VALUES LESS THAN (2),
+  SUBPARTITION `sp3` VALUES LESS THAN (3),
+  SUBPARTITION `sp4` VALUES LESS THAN (4),
+  SUBPARTITION `sp5` VALUES LESS THAN (5),
+  SUBPARTITION `sp6` VALUES LESS THAN (6),
+  SUBPARTITION `sp7` VALUES LESS THAN (7),
+  SUBPARTITION `sp8` VALUES LESS THAN (8),
+  SUBPARTITION `sp9` VALUES LESS THAN (9),
+  SUBPARTITION `sp10` VALUES LESS THAN (10),
+  SUBPARTITION `sp11` VALUES LESS THAN (11),
+  SUBPARTITION `spd` VALUES LESS THAN (MAXVALUE));
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.statistic.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.statistic.yml
new file mode 100644
index 000000000..79a4de4ec
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.statistic.yml
@@ -0,0 +1,399 @@
+lineitem:
+  596099371
+partsupp:
+  78923264
+nation:
+  25
+part:
+  19831642
+supplier:
+  990645
+orders:
+  148767864
+region:
+  5
+customer:
+  14836390
+lineitem.l_receiptdate.cardinality:
+  3600
+lineitem.l_returnflag.cardinality:
+  3
+lineitem.l_tax.cardinality:
+  9
+lineitem.l_shipmode.cardinality:
+  7
+lineitem.l_suppkey.cardinality:
+  20814384
+lineitem.l_shipdate.cardinality:
+  3206
+lineitem.l_commitdate.cardinality:
+  2616
+lineitem.l_partkey.cardinality:
+  47337731
+lineitem.l_orderkey.cardinality:
+  49577834
+lineitem.l_quantity.cardinality:
+  50
+lineitem.l_comment.cardinality:
+  25032109
+lineitem.l_linestatus.cardinality:
+  2
+lineitem.l_extendedprice.cardinality:
+  30880030
+lineitem.l_linenumber.cardinality:
+  7
+lineitem.l_discount.cardinality:
+  11
+lineitem.l_shipinstruct.cardinality:
+  4
+partsupp.ps_availqty.cardinality:
+  10053
+partsupp.ps_suppkey.cardinality:
+  7882836
+partsupp.ps_comment.cardinality:
+  25435245
+partsupp.ps_partkey.cardinality:
+  23272706
+partsupp.ps_supplycost.cardinality:
+  1469797
+nation.n_comment.cardinality:
+  25
+nation.n_nationkey.cardinality:
+  24
+nation.n_regionkey.cardinality:
+  5
+nation.n_name.cardinality:
+  25
+part.p_partkey.cardinality:
+  10453419
+part.p_container.cardinality:
+  40
+part.p_comment.cardinality:
+  1587399
+part.p_name.cardinality:
+  10878176
+part.p_brand.cardinality:
+  25
+part.p_retailprice.cardinality:
+  835924
+part.p_type.cardinality:
+  150
+part.p_mfgr.cardinality:
+  5
+part.p_size.cardinality:
+  50
+supplier.s_comment.cardinality:
+  983865
+supplier.s_phone.cardinality:
+  984732
+supplier.s_nationkey.cardinality:
+  25
+supplier.s_name.cardinality:
+  984486
+supplier.s_acctbal.cardinality:
+  925288
+supplier.s_address.cardinality:
+  984599
+supplier.s_suppkey.cardinality:
+  984192
+orders.o_clerk.cardinality:
+  1996652
+orders.o_orderstatus.cardinality:
+  3
+orders.o_orderdate.cardinality:
+  2406
+orders.o_shippriority.cardinality:
+  1
+orders.o_custkey.cardinality:
+  22594507
+orders.o_totalprice.cardinality:
+  28133638
+orders.o_comment.cardinality:
+  27899127
+orders.o_orderkey.cardinality:
+  29497477
+orders.o_orderpriority.cardinality:
+  5
+region.r_regionkey.cardinality:
+  5
+region.r_comment.cardinality:
+  5
+region.r_name.cardinality:
+  5
+customer.c_custkey.cardinality:
+  10381233
+customer.c_acctbal.cardinality:
+  3520338
+customer.c_phone.cardinality:
+  10525467
+customer.c_mktsegment.cardinality:
+  5
+customer.c_address.cardinality:
+  10404871
+customer.c_nationkey.cardinality:
+  25
+customer.c_name.cardinality:
+  10197606
+customer.c_comment.cardinality:
+  10012526
+customer.c_acctbal.histogram:
+  {"buckets":[{"ndv":156,"upper":-836.11,"lower":-997.89,"count":157,"preSum":0},{"ndv":157,"upper":-671.41,"lower":-832.82,"count":157,"preSum":157},{"ndv":156,"upper":-503.67,"lower":-670.79,"count":157,"preSum":314},{"ndv":157,"upper":-336.51,"lower":-503.62,"count":157,"preSum":471},{"ndv":157,"upper":-147.81,"lower":-336.50,"count":157,"preSum":628},{"ndv":156,"upper":16.75,"lower":-146.01,"count":157,"preSum":785},{"ndv":156,"upper":189.57,"lower":16.97,"count":157,"preSum":942},{"ndv":157,"upper":360.51,"lower":190.01,"count":157,"preSum":1099},{"ndv":156,"upper":507.35,"lower":361.86,"count":157,"preSum":1256},{"ndv":156,"upper":661.61,"lower":507.87,"count":157,"preSum":1413},{"ndv":154,"upper":837.74,"lower":661.85,"count":157,"preSum":1570},{"ndv":153,"upper":1004.10,"lower":841.43,"count":157,"preSum":1727},{"ndv":156,"upper":1171.58,"lower":1004.95,"count":157,"preSum":1884},{"ndv":155,"upper":1357.10,"lower":1171.94,"count":157,"preSum":2041},{"ndv":157,"upper":1525.99,"lower":1359.98,"count":157,"preSum":2198},{"ndv":155,"upper":1684.21,"lower":1526.06,"count":157,"preSum":2355},{"ndv":157,"upper":1862.28,"lower":1684.72,"count":157,"preSum":2512},{"ndv":157,"upper":2025.27,"lower":1862.36,"count":157,"preSum":2669},{"ndv":156,"upper":2222.44,"lower":2026.35,"count":157,"preSum":2826},{"ndv":157,"upper":2393.96,"lower":2226.21,"count":157,"preSum":2983},{"ndv":155,"upper":2553.96,"lower":2394.41,"count":157,"preSum":3140},{"ndv":157,"upper":2745.61,"lower":2554.05,"count":157,"preSum":3297},{"ndv":156,"upper":2912.20,"lower":2745.85,"count":157,"preSum":3454},{"ndv":157,"upper":3075.31,"lower":2914.49,"count":157,"preSum":3611},{"ndv":156,"upper":3263.31,"lower":3075.48,"count":157,"preSum":3768},{"ndv":156,"upper":3440.37,"lower":3265.06,"count":157,"preSum":3925},{"ndv":157,"upper":3599.35,"lower":3440.62,"count":157,"preSum":4082},{"ndv":157,"upper":3778.70,"lower":3601.09,"count":157,"preSum":4239},{"ndv":156,"upper":3948.46,"lower":3780.35,"count":157,"preSum":4396},{"ndv":157,"upper":4137.47,"lower":3950.70,"count":157,"preSum":4553},{"ndv":156,"upper":4312.67,"lower":4139.76,"count":157,"preSum":4710},{"ndv":157,"upper":4478.48,"lower":4313.79,"count":157,"preSum":4867},{"ndv":156,"upper":4679.82,"lower":4481.47,"count":157,"preSum":5024},{"ndv":156,"upper":4816.55,"lower":4680.40,"count":157,"preSum":5181},{"ndv":157,"upper":5004.69,"lower":4817.52,"count":157,"preSum":5338},{"ndv":157,"upper":5207.53,"lower":5005.19,"count":157,"preSum":5495},{"ndv":157,"upper":5387.18,"lower":5208.38,"count":157,"preSum":5652},{"ndv":157,"upper":5557.45,"lower":5388.31,"count":157,"preSum":5809},{"ndv":157,"upper":5707.75,"lower":5558.76,"count":157,"preSum":5966},{"ndv":154,"upper":5889.50,"lower":5708.51,"count":157,"preSum":6123},{"ndv":156,"upper":6054.55,"lower":5890.03,"count":157,"preSum":6280},{"ndv":157,"upper":6214.12,"lower":6055.36,"count":157,"preSum":6437},{"ndv":156,"upper":6387.87,"lower":6215.38,"count":157,"preSum":6594},{"ndv":155,"upper":6563.57,"lower":6389.91,"count":157,"preSum":6751},{"ndv":156,"upper":6742.37,"lower":6564.97,"count":157,"preSum":6908},{"ndv":156,"upper":6916.42,"lower":6743.08,"count":157,"preSum":7065},{"ndv":157,"upper":7108.60,"lower":6916.88,"count":157,"preSum":7222},{"ndv":157,"upper":7303.23,"lower":7108.97,"count":157,"preSum":7379},{"ndv":156,"upper":7482.24,"lower":7306.47,"count":157,"preSum":7536},{"ndv":156,"upper":7654.92,"lower":7483.74,"count":157,"preSum":7693},{"ndv":156,"upper":7848.86,"lower":7655.54,"count":157,"preSum":7850},{"ndv":156,"upper":8019.29,"lower":7852.47,"count":157,"preSum":8007},{"ndv":156,"upper":8221.92,"lower":8019.60,"count":157,"preSum":8164},{"ndv":157,"upper":8385.80,"lower":8222.70,"count":157,"preSum":8321},{"ndv":157,"upper":8554.67,"lower":8386.87,"count":157,"preSum":8478},{"ndv":157,"upper":8709.58,"lower":8554.86,"count":157,"preSum":8635},{"ndv":156,"upper":8879.79,"lower":8711.15,"count":157,"preSum":8792},{"ndv":157,"upper":9041.36,"lower":8879.80,"count":157,"preSum":8949},{"ndv":156,"upper":9216.57,"lower":9041.92,"count":157,"preSum":9106},{"ndv":157,"upper":9390.82,"lower":9219.25,"count":157,"preSum":9263},{"ndv":157,"upper":9540.57,"lower":9390.83,"count":157,"preSum":9420},{"ndv":157,"upper":9727.41,"lower":9540.98,"count":157,"preSum":9577},{"ndv":157,"upper":9896.74,"lower":9728.57,"count":157,"preSum":9734},{"ndv":109,"upper":9999.06,"lower":9897.61,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Double","sampleRate":0.09889925}
+customer.c_address.histogram:
+  {"buckets":[{"ndv":157,"upper":" XX0kIS256BjLPmHbDUS","lower":" ,92Boege0vVF6v7sxKg","count":157,"preSum":0},{"ndv":157,"upper":",WFtGhOIRXCGKQ4plzXY","lower":" xyQmwwqY58U8X2CBf3,","count":157,"preSum":157},{"ndv":157,"upper":"0uZouL9QXL5VgFRBw1Zk","lower":",wNTD,gOppVYIA6 kqar","count":157,"preSum":314},{"ndv":157,"upper":"1v65IOoVEmh 4 o","lower":"0v0UKYncJzaqAOSjCS b","count":157,"preSum":471},{"ndv":157,"upper":"2YEQEMFps9EREo1e","lower":"1VBVyYwc,ce7uKCuTRcz","count":157,"preSum":628},{"ndv":157,"upper":"3tWwPhC8tOD","lower":"2yGLrTLPScfpd1o8ws A","count":157,"preSum":785},{"ndv":157,"upper":"4u3TbdZ7nIputJj7pkZd","lower":"3uH5nVh5xo32uMn0cD50","count":157,"preSum":942},{"ndv":157,"upper":"5VK3K0hVp1","lower":"4uCzIC67i CKl7ge56v","count":157,"preSum":1099},{"ndv":157,"upper":"6sLsnuowP0","lower":"5Vni UVh4l","count":157,"preSum":1256},{"ndv":157,"upper":"7Q3o2R2JlX6DFJG5m6XG","lower":"6slZAZN1LkLr","count":157,"preSum":1413},{"ndv":157,"upper":"8omkyHsm0eXX37ZHHSuL","lower":"7qlNht5VjUYPIVq6","count":157,"preSum":1570},{"ndv":157,"upper":"9MSagng8WmLOZP1I26q0","lower":"8os6kx,,5DMZYC,OMG5p","count":157,"preSum":1727},{"ndv":157,"upper":"aClpxkPsV4ZR","lower":"9msmt6bSILkQ1PrE9kdX","count":157,"preSum":1884},{"ndv":157,"upper":"atzgSSnWes9zQ9kyRtdz","lower":"ACpkF5UCjj4MVg6HnBT4","count":157,"preSum":2041},{"ndv":157,"upper":"BCWD9EXo0sRApnFeou1C","lower":"AU22m9ar7O4C3Iy2c4fB","count":157,"preSum":2198},{"ndv":157,"upper":"BTz6HmqyUJ2xM","lower":"BD kz1ltwKNnUQPiMhIQ","count":157,"preSum":2355},{"ndv":157,"upper":"cEMhGPzR39GTNHih7,BM","lower":"bu7q1,m0wMFsjZb G6Am","count":157,"preSum":2512},{"ndv":157,"upper":"cUmLM6x3ciGgBKrQ1zDL","lower":"CeprzRA8ZJZ 92,P","count":157,"preSum":2669},{"ndv":157,"upper":"DCpIrWJOyKdBB,tSmSLE","lower":"CUpZa,3B3aJBu","count":157,"preSum":2826},{"ndv":157,"upper":"ds0Nm42GhBnLCWFOXb5f","lower":"dcsBn3n7QKnLNvAmJR90","count":157,"preSum":2983},{"ndv":157,"upper":"ebr5imGtzeGQt63ZJQ5n","lower":"DsByJhA u0KdNosADOFL","count":157,"preSum":3140},{"ndv":157,"upper":"etfjx 8104zCGEwJkrYx","lower":"ec VtjC1RZeHRxtx6jxA","count":157,"preSum":3297},{"ndv":157,"upper":"FCtzBpioSFTS4","lower":"EtgFH1fl9d,zmCdJa0m","count":157,"preSum":3454},{"ndv":157,"upper":"fTf091SP9wZyooPYK6mK","lower":"fcV8FjayE95kX9VMtVY8","count":157,"preSum":3611},{"ndv":157,"upper":"Gccl3KOhRMCuDZ lsYSW","lower":"fTI3rnv95IVB7,yxa","count":157,"preSum":3768},{"ndv":157,"upper":"gRCEq8nmvDF5iE0kj7dp","lower":"GcdJoDvUbecruCm7kNBo","count":157,"preSum":3925},{"ndv":157,"upper":"HcsbDY57qk","lower":"GRcyq36BtbLeVZ85GOI0","count":157,"preSum":4082},{"ndv":157,"upper":"hRxWZT KQ2mITwKBabcA","lower":"HD,kqeFij,71d9zMmrU5","count":157,"preSum":4239},{"ndv":157,"upper":"iCBLlkhkHe2Rc,n9Q,5m","lower":"HRZ3heU7KHJw02b4wckX","count":157,"preSum":4396},{"ndv":157,"upper":"irioYBeVeQ57etuXEx b","lower":"IcDk0NVt8E MRDJ1Ze8G","count":157,"preSum":4553},{"ndv":157,"upper":"JAeUb9DhBxPh1","lower":"IRkpxE DO1pbHzuDdyBJ","count":157,"preSum":4710},{"ndv":157,"upper":"JQsW0E1tiX5Gn4ixcJ U","lower":"JAoQHqDmcSNMcbddpz8T","count":157,"preSum":4867},{"ndv":157,"upper":"kE0XO9CudkFiSxvGd1","lower":"jqyc,XMCwQLFDJ9CLJUQ","count":157,"preSum":5024},{"ndv":157,"upper":"kSCWzCGIxZt8lz7 0r2f","lower":"ke6TRvjoF5VRwkXwJL0K","count":157,"preSum":5181},{"ndv":157,"upper":"Lbg5F,UVs9vvfM","lower":"KSGlfPOSO7rE557oUXd9","count":157,"preSum":5338},{"ndv":157,"upper":"lR7Bfwxan wuwc,zwC I","lower":"lBhPwxhAU,","count":157,"preSum":5495},{"ndv":157,"upper":"MCUR8s0Rl9D5Ep7hn2Qu","lower":"LRaafLfHDSOMpWuX0","count":157,"preSum":5652},{"ndv":157,"upper":"Mv,oP3AJafFi1eaYx6QC","lower":"MCZAnZxWvR,9jaW","count":157,"preSum":5809},{"ndv":157,"upper":"neprceg8YIe o2gQNb1y","lower":"MVHpYfhVyDJ61PCrDaed","count":157,"preSum":5966},{"ndv":157,"upper":"ntlvWMUgXxdQLVoslwIK","lower":"nER7zNrBvzHE","count":157,"preSum":6123},{"ndv":157,"upper":"OcHS,P kTU97fzQLOplT","lower":"NTMnARrQI7sexGlg4lyn","count":157,"preSum":6280},{"ndv":157,"upper":"oSVYTdMzIcIzccgmsNQN","lower":"oCKzFEzcIgZ2yXcKWQgH","count":157,"preSum":6437},{"ndv":157,"upper":"pbw,r45cr14t31bLo3N1","lower":"oSXpdykJZpr","count":157,"preSum":6594},{"ndv":157,"upper":"PSSgBB0v0pSChfesRTs","lower":"PBW9Yzob4We5r96zAOBk","count":157,"preSum":6751},{"ndv":157,"upper":"QE5r8iGEE144z,wyOXgg","lower":"psx5GlZAhSVFibIrWZj","count":157,"preSum":6908},{"ndv":157,"upper":"qThOPTsOs640ybR03Xde","lower":"Qe6zbphsUIOjoK7F2QoG","count":157,"preSum":7065},{"ndv":157,"upper":"rFfLJMMax,TUilv7urnh","lower":"QTIu26D  g3rp","count":157,"preSum":7222},{"ndv":157,"upper":"rut  T8tTypJ4HnykMcS","lower":"RFJfyTdPDgF8 DekDr","count":157,"preSum":7379},{"ndv":157,"upper":"sEZgC12MOrna7hS7cM","lower":"rutkM2zt8PT9q7q","count":157,"preSum":7536},{"ndv":157,"upper":"stkIqgkWnOSr2qgAzuQA","lower":"sf55,c0pzfDDXVmO8d9i","count":157,"preSum":7693},{"ndv":157,"upper":"TetoTw4I uWFSSTmtDXn","lower":"StqDxeomZWZTKBNk6pFt","count":157,"preSum":7850},{"ndv":157,"upper":"TYZiLWsFl9xmd,nJugb","lower":"tetwXdnXqKWPLxc35mtR","count":157,"preSum":8007},{"ndv":157,"upper":"uhk1r7ePNRpY KqwwNi","lower":"tYZp 4iW z8u3cRLNrzn","count":157,"preSum":8164},{"ndv":157,"upper":"UZ3TqAuStTOOXjGmD364","lower":"uHoLQhA5AQ,YXsuABTe5","count":157,"preSum":8321},{"ndv":157,"upper":"vLbKfARATK","lower":"uZ3y9f562gK37bmQl F,","count":157,"preSum":8478},{"ndv":157,"upper":"w6ON3,1J9hiC9nfc4Et8","lower":"vLdrffUQUOlU8TqEI5","count":157,"preSum":8635},{"ndv":157,"upper":"WO1QsO2EJEpMssn29I7L","lower":"W7bJ6txbG7P","count":157,"preSum":8792},{"ndv":157,"upper":"X3Uuk, QqXLh1HGiCp3Q","lower":"WOC,74oNKkqB9mhQi1Of","count":157,"preSum":8949},{"ndv":157,"upper":"xMVQb7BvtXIIekAHd3 z","lower":"x42P8B1Hbobdj","count":157,"preSum":9106},{"ndv":157,"upper":"Y49UNikOZWKVimET","lower":"xn,fjk,R9cxKD7MB lsc","count":157,"preSum":9263},{"ndv":157,"upper":"YM1s7QixnhDXl","lower":"y4a4ZLTGLQgL3l4l,McR","count":157,"preSum":9420},{"ndv":157,"upper":"z5CbbGVt5mVon","lower":"yMaa0LkjjJExGSedMd70","count":157,"preSum":9577},{"ndv":157,"upper":"zOI Hv4WTtCvjwfingvH","lower":"z5k9y5IWUWFOVIFEGgJ0","count":157,"preSum":9734},{"ndv":109,"upper":"ZzwxVgw3JQnM7q","lower":"ZOrMjL0EZq0J04TrJIoA","count":109,"preSum":9891}],"maxBucketSize":64,"type":"String","sampleRate":0.09889925}
+customer.c_comment.histogram:
+  {"buckets":[{"ndv":138,"upper":" are slyly ideas. sl","lower":" about the asymptote","count":157,"preSum":0},{"ndv":149,"upper":" can nag slyly dolph","lower":" are slyly ironic pi","count":157,"preSum":157},{"ndv":139,"upper":" even ideas are abou","lower":" careful deposits wa","count":157,"preSum":314},{"ndv":150,"upper":" furiously express i","lower":" even instructions n","count":157,"preSum":471},{"ndv":136,"upper":" ironic theodolites!","lower":" furiously express p","count":157,"preSum":628},{"ndv":142,"upper":" quickly special ins","lower":" ironic theodolites.","count":157,"preSum":785},{"ndv":142,"upper":" slyly along the fin","lower":" quickly special pin","count":157,"preSum":942},{"ndv":141,"upper":" the slyly regular p","lower":" slyly alongside of ","count":157,"preSum":1099},{"ndv":151,"upper":". asymptotes cajole ","lower":" the slyly special f","count":157,"preSum":1256},{"ndv":149,"upper":". sometimes special ","lower":". attainments about ","count":157,"preSum":1413},{"ndv":149,"upper":"against the blithely","lower":". special excuses na","count":157,"preSum":1570},{"ndv":154,"upper":"al foxes cajole. iro","lower":"against the carefull","count":157,"preSum":1727},{"ndv":151,"upper":"ar instructions cajo","lower":"al foxes sleep furio","count":157,"preSum":1884},{"ndv":150,"upper":"ate quickly about th","lower":"ar instructions hagg","count":157,"preSum":2041},{"ndv":155,"upper":"c grouches. dependen","lower":"ate quickly special,","count":157,"preSum":2198},{"ndv":147,"upper":"cial accounts. fluff","lower":"c ideas nag carefull","count":157,"preSum":2355},{"ndv":150,"upper":"courts kindle blithe","lower":"cial accounts. reque","count":157,"preSum":2512},{"ndv":151,"upper":"deposits haggle alon","lower":"courts. evenly ironi","count":157,"preSum":2669},{"ndv":147,"upper":"e carefully final pa","lower":"deposits haggle blit","count":158,"preSum":2826},{"ndv":145,"upper":"e unusual hockey pla","lower":"e carefully furiousl","count":157,"preSum":2984},{"ndv":151,"upper":"efully; quickly pend","lower":"e unusual, bold asym","count":157,"preSum":3141},{"ndv":148,"upper":"endencies. carefully","lower":"efully? theodolites ","count":157,"preSum":3298},{"ndv":151,"upper":"equests nag. blithel","lower":"endencies. even idea","count":157,"preSum":3455},{"ndv":154,"upper":"escapades integrate ","lower":"equests need to hagg","count":157,"preSum":3612},{"ndv":151,"upper":"ey players! carefull","lower":"ess about the reques","count":157,"preSum":3769},{"ndv":153,"upper":"foxes. furiously reg","lower":"ey players. even pin","count":157,"preSum":3926},{"ndv":146,"upper":"g the regular, even ","lower":"foxes. ironically fi","count":157,"preSum":4083},{"ndv":154,"upper":"gular foxes are furi","lower":"g the regular, speci","count":157,"preSum":4240},{"ndv":152,"upper":"hely dogged requests","lower":"gular foxes cajole s","count":157,"preSum":4397},{"ndv":156,"upper":"ickly express depend","lower":"hely even accounts a","count":157,"preSum":4554},{"ndv":154,"upper":"ind carefully of the","lower":"ickly express foxes.","count":157,"preSum":4711},{"ndv":146,"upper":"iously ironic accoun","lower":"inder blithely at th","count":157,"preSum":4868},{"ndv":147,"upper":"ithely regular, iron","lower":"iously ironic deposi","count":157,"preSum":5025},{"ndv":154,"upper":"l accounts haggle qu","lower":"ithely ruthless depo","count":157,"preSum":5182},{"ndv":154,"upper":"latelets are furious","lower":"l accounts hang iron","count":157,"preSum":5339},{"ndv":156,"upper":"lithely express gift","lower":"latelets are slyly f","count":157,"preSum":5496},{"ndv":151,"upper":"ly according to the ","lower":"lithely final deposi","count":161,"preSum":5653},{"ndv":135,"upper":"ly quick foxes. care","lower":"ly across the carefu","count":157,"preSum":5814},{"ndv":131,"upper":"mes silent deposits ","lower":"ly quickly final fox","count":157,"preSum":5971},{"ndv":156,"upper":"ng ideas nag careful","lower":"mise slyly according","count":157,"preSum":6128},{"ndv":152,"upper":"nstructions. daringl","lower":"ng multipliers. care","count":157,"preSum":6285},{"ndv":146,"upper":"odolites. slyly expr","lower":"nstructions. express","count":157,"preSum":6442},{"ndv":152,"upper":"onic theodolites are","lower":"odolites. slyly unus","count":157,"preSum":6599},{"ndv":152,"upper":"ounts sleep. fluffil","lower":"onic theodolites hag","count":157,"preSum":6756},{"ndv":153,"upper":"packages was careful","lower":"ounts! carefully iro","count":157,"preSum":6913},{"ndv":152,"upper":"press ideas. pending","lower":"packages-- express a","count":157,"preSum":7070},{"ndv":152,"upper":"raids wake furiously","lower":"press instructions. ","count":157,"preSum":7227},{"ndv":141,"upper":"regular, even excuse","lower":"rash according to th","count":157,"preSum":7384},{"ndv":143,"upper":"ronic deposits. care","lower":"regular, final decoy","count":157,"preSum":7541},{"ndv":151,"upper":"s cajole special pac","lower":"ronic deposits. fina","count":157,"preSum":7698},{"ndv":155,"upper":"s. bold, ironic inst","lower":"s cajole. carefully ","count":157,"preSum":7855},{"ndv":146,"upper":"silent platelets sle","lower":"s. bold, unusual fox","count":157,"preSum":8012},{"ndv":149,"upper":"special accounts: bl","lower":"silent platelets wak","count":157,"preSum":8169},{"ndv":155,"upper":"sual, pending pinto ","lower":"special asymptotes. ","count":157,"preSum":8326},{"ndv":154,"upper":"the carefully ironic","lower":"sual, regular foxes ","count":158,"preSum":8483},{"ndv":148,"upper":"tions are quickly ca","lower":"the carefully pendin","count":157,"preSum":8641},{"ndv":153,"upper":"ts wake carefully re","lower":"tions cajole slyly a","count":157,"preSum":8798},{"ndv":149,"upper":"uffily regular, regu","lower":"ts wake final, final","count":157,"preSum":8955},{"ndv":148,"upper":"ully. special packag","lower":"uffily. busy pinto b","count":157,"preSum":9112},{"ndv":149,"upper":"usly busy requests u","lower":"ully? regular, pendi","count":157,"preSum":9269},{"ndv":148,"upper":"wake. slyly fluffy e","lower":"usly carefully unusu","count":157,"preSum":9426},{"ndv":151,"upper":"y final deposits cou","lower":"warthogs nag fluffil","count":157,"preSum":9583},{"ndv":136,"upper":"y unusual theodolite","lower":"y final dolphins. de","count":157,"preSum":9740},{"ndv":98,"upper":"zzle. pinto beans ar","lower":"y unusual Tiresias a","count":103,"preSum":9897}],"maxBucketSize":64,"type":"String","sampleRate":0.09889925}
+customer.c_custkey.histogram:
+  {"buckets":[{"ndv":157,"upper":241611,"lower":1311,"count":157,"preSum":0},{"ndv":157,"upper":484352,"lower":243120,"count":157,"preSum":157},{"ndv":157,"upper":726980,"lower":485015,"count":157,"preSum":314},{"ndv":157,"upper":966848,"lower":728081,"count":157,"preSum":471},{"ndv":157,"upper":1204316,"lower":967411,"count":157,"preSum":628},{"ndv":157,"upper":1432425,"lower":1205487,"count":157,"preSum":785},{"ndv":157,"upper":1667088,"lower":1433445,"count":157,"preSum":942},{"ndv":157,"upper":1873549,"lower":1667541,"count":157,"preSum":1099},{"ndv":157,"upper":2130907,"lower":1873845,"count":157,"preSum":1256},{"ndv":157,"upper":2393907,"lower":2133279,"count":157,"preSum":1413},{"ndv":157,"upper":2642447,"lower":2394710,"count":157,"preSum":1570},{"ndv":157,"upper":2858374,"lower":2642486,"count":157,"preSum":1727},{"ndv":157,"upper":3097033,"lower":2860014,"count":157,"preSum":1884},{"ndv":157,"upper":3318570,"lower":3098483,"count":157,"preSum":2041},{"ndv":157,"upper":3569365,"lower":3320083,"count":157,"preSum":2198},{"ndv":157,"upper":3796548,"lower":3572446,"count":157,"preSum":2355},{"ndv":157,"upper":4049652,"lower":3798854,"count":157,"preSum":2512},{"ndv":157,"upper":4306697,"lower":4050298,"count":157,"preSum":2669},{"ndv":157,"upper":4557830,"lower":4307586,"count":157,"preSum":2826},{"ndv":157,"upper":4797805,"lower":4561432,"count":157,"preSum":2983},{"ndv":157,"upper":5031890,"lower":4798179,"count":157,"preSum":3140},{"ndv":157,"upper":5263166,"lower":5032206,"count":157,"preSum":3297},{"ndv":157,"upper":5478779,"lower":5264577,"count":157,"preSum":3454},{"ndv":157,"upper":5701751,"lower":5479288,"count":157,"preSum":3611},{"ndv":157,"upper":5936373,"lower":5701889,"count":157,"preSum":3768},{"ndv":157,"upper":6146768,"lower":5937434,"count":157,"preSum":3925},{"ndv":157,"upper":6377606,"lower":6148185,"count":157,"preSum":4082},{"ndv":157,"upper":6604474,"lower":6377613,"count":157,"preSum":4239},{"ndv":157,"upper":6822928,"lower":6604521,"count":157,"preSum":4396},{"ndv":157,"upper":7045652,"lower":6825405,"count":157,"preSum":4553},{"ndv":157,"upper":7264097,"lower":7047649,"count":157,"preSum":4710},{"ndv":157,"upper":7537102,"lower":7265550,"count":157,"preSum":4867},{"ndv":157,"upper":7745846,"lower":7540386,"count":157,"preSum":5024},{"ndv":157,"upper":7970132,"lower":7746163,"count":157,"preSum":5181},{"ndv":157,"upper":8217051,"lower":7970925,"count":157,"preSum":5338},{"ndv":157,"upper":8447729,"lower":8217135,"count":157,"preSum":5495},{"ndv":157,"upper":8692339,"lower":8449361,"count":157,"preSum":5652},{"ndv":157,"upper":8906554,"lower":8692570,"count":157,"preSum":5809},{"ndv":157,"upper":9129760,"lower":8907650,"count":157,"preSum":5966},{"ndv":157,"upper":9360894,"lower":9136964,"count":157,"preSum":6123},{"ndv":157,"upper":9628175,"lower":9364583,"count":157,"preSum":6280},{"ndv":157,"upper":9860918,"lower":9631333,"count":157,"preSum":6437},{"ndv":157,"upper":10086949,"lower":9863508,"count":157,"preSum":6594},{"ndv":157,"upper":10327540,"lower":10088909,"count":157,"preSum":6751},{"ndv":157,"upper":10560058,"lower":10327900,"count":157,"preSum":6908},{"ndv":157,"upper":10828009,"lower":10560475,"count":157,"preSum":7065},{"ndv":157,"upper":11091270,"lower":10833202,"count":157,"preSum":7222},{"ndv":157,"upper":11319099,"lower":11092426,"count":157,"preSum":7379},{"ndv":157,"upper":11532225,"lower":11319212,"count":157,"preSum":7536},{"ndv":157,"upper":11774785,"lower":11535174,"count":157,"preSum":7693},{"ndv":157,"upper":11984216,"lower":11775243,"count":157,"preSum":7850},{"ndv":157,"upper":12203405,"lower":11985095,"count":157,"preSum":8007},{"ndv":157,"upper":12429006,"lower":12207836,"count":157,"preSum":8164},{"ndv":157,"upper":12670934,"lower":12429143,"count":157,"preSum":8321},{"ndv":157,"upper":12903202,"lower":12673469,"count":157,"preSum":8478},{"ndv":157,"upper":13131063,"lower":12903424,"count":157,"preSum":8635},{"ndv":157,"upper":13370243,"lower":13131937,"count":157,"preSum":8792},{"ndv":157,"upper":13638258,"lower":13370672,"count":157,"preSum":8949},{"ndv":157,"upper":13864583,"lower":13640583,"count":157,"preSum":9106},{"ndv":157,"upper":14099765,"lower":13865389,"count":157,"preSum":9263},{"ndv":157,"upper":14338074,"lower":14104481,"count":157,"preSum":9420},{"ndv":157,"upper":14585451,"lower":14343086,"count":157,"preSum":9577},{"ndv":157,"upper":14832558,"lower":14588523,"count":157,"preSum":9734},{"ndv":109,"upper":14996522,"lower":14833547,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Int","sampleRate":0.09889925}
+customer.c_mktsegment.histogram:
+  {"buckets":[{"ndv":1,"upper":"AUTOMOBILE","lower":"AUTOMOBILE","count":1969,"preSum":0},{"ndv":1,"upper":"BUILDING","lower":"BUILDING","count":2042,"preSum":1969},{"ndv":1,"upper":"FURNITURE","lower":"FURNITURE","count":1931,"preSum":4011},{"ndv":1,"upper":"HOUSEHOLD","lower":"HOUSEHOLD","count":1998,"preSum":5942},{"ndv":1,"upper":"MACHINERY","lower":"MACHINERY","count":2060,"preSum":7940}],"maxBucketSize":64,"type":"String","sampleRate":0.09889925}
+customer.c_name.histogram:
+  {"buckets":[{"ndv":157,"upper":"Customer#000244760","lower":"Customer#000000822","count":157,"preSum":0},{"ndv":157,"upper":"Customer#000524348","lower":"Customer#000245025","count":157,"preSum":157},{"ndv":157,"upper":"Customer#000795432","lower":"Customer#000526155","count":157,"preSum":314},{"ndv":157,"upper":"Customer#001025244","lower":"Customer#000796405","count":157,"preSum":471},{"ndv":157,"upper":"Customer#001256820","lower":"Customer#001025431","count":157,"preSum":628},{"ndv":157,"upper":"Customer#001523087","lower":"Customer#001257793","count":157,"preSum":785},{"ndv":157,"upper":"Customer#001753232","lower":"Customer#001524343","count":157,"preSum":942},{"ndv":157,"upper":"Customer#001998583","lower":"Customer#001761276","count":157,"preSum":1099},{"ndv":157,"upper":"Customer#002253859","lower":"Customer#002000603","count":157,"preSum":1256},{"ndv":157,"upper":"Customer#002481421","lower":"Customer#002256025","count":157,"preSum":1413},{"ndv":157,"upper":"Customer#002697757","lower":"Customer#002482682","count":157,"preSum":1570},{"ndv":157,"upper":"Customer#002925434","lower":"Customer#002698406","count":157,"preSum":1727},{"ndv":157,"upper":"Customer#003170261","lower":"Customer#002928208","count":157,"preSum":1884},{"ndv":157,"upper":"Customer#003443358","lower":"Customer#003172042","count":157,"preSum":2041},{"ndv":157,"upper":"Customer#003660557","lower":"Customer#003446291","count":157,"preSum":2198},{"ndv":157,"upper":"Customer#003900075","lower":"Customer#003661528","count":157,"preSum":2355},{"ndv":157,"upper":"Customer#004123349","lower":"Customer#003901059","count":157,"preSum":2512},{"ndv":157,"upper":"Customer#004314700","lower":"Customer#004128305","count":157,"preSum":2669},{"ndv":157,"upper":"Customer#004543818","lower":"Customer#004315094","count":157,"preSum":2826},{"ndv":157,"upper":"Customer#004752214","lower":"Customer#004544564","count":157,"preSum":2983},{"ndv":157,"upper":"Customer#005015583","lower":"Customer#004754703","count":157,"preSum":3140},{"ndv":157,"upper":"Customer#005249129","lower":"Customer#005017468","count":157,"preSum":3297},{"ndv":157,"upper":"Customer#005463393","lower":"Customer#005250604","count":157,"preSum":3454},{"ndv":157,"upper":"Customer#005705394","lower":"Customer#005465514","count":157,"preSum":3611},{"ndv":157,"upper":"Customer#005917371","lower":"Customer#005707688","count":157,"preSum":3768},{"ndv":157,"upper":"Customer#006168191","lower":"Customer#005919851","count":157,"preSum":3925},{"ndv":157,"upper":"Customer#006395989","lower":"Customer#006168409","count":157,"preSum":4082},{"ndv":157,"upper":"Customer#006649448","lower":"Customer#006396908","count":157,"preSum":4239},{"ndv":157,"upper":"Customer#006904680","lower":"Customer#006649770","count":157,"preSum":4396},{"ndv":157,"upper":"Customer#007114789","lower":"Customer#006905258","count":157,"preSum":4553},{"ndv":157,"upper":"Customer#007351255","lower":"Customer#007120384","count":157,"preSum":4710},{"ndv":157,"upper":"Customer#007594831","lower":"Customer#007351525","count":157,"preSum":4867},{"ndv":157,"upper":"Customer#007831978","lower":"Customer#007594913","count":157,"preSum":5024},{"ndv":157,"upper":"Customer#008075543","lower":"Customer#007833004","count":157,"preSum":5181},{"ndv":157,"upper":"Customer#008301926","lower":"Customer#008076704","count":157,"preSum":5338},{"ndv":157,"upper":"Customer#008518726","lower":"Customer#008302064","count":157,"preSum":5495},{"ndv":157,"upper":"Customer#008759843","lower":"Customer#008519325","count":157,"preSum":5652},{"ndv":157,"upper":"Customer#009013534","lower":"Customer#008762983","count":157,"preSum":5809},{"ndv":157,"upper":"Customer#009285507","lower":"Customer#009015797","count":157,"preSum":5966},{"ndv":157,"upper":"Customer#009506381","lower":"Customer#009285835","count":157,"preSum":6123},{"ndv":157,"upper":"Customer#009735956","lower":"Customer#009506422","count":157,"preSum":6280},{"ndv":157,"upper":"Customer#009970706","lower":"Customer#009738210","count":157,"preSum":6437},{"ndv":157,"upper":"Customer#010186340","lower":"Customer#009971275","count":157,"preSum":6594},{"ndv":157,"upper":"Customer#010477568","lower":"Customer#010186420","count":157,"preSum":6751},{"ndv":157,"upper":"Customer#010711724","lower":"Customer#010481458","count":157,"preSum":6908},{"ndv":157,"upper":"Customer#010937767","lower":"Customer#010716651","count":157,"preSum":7065},{"ndv":157,"upper":"Customer#011158130","lower":"Customer#010937985","count":157,"preSum":7222},{"ndv":157,"upper":"Customer#011416732","lower":"Customer#011158554","count":157,"preSum":7379},{"ndv":157,"upper":"Customer#011620907","lower":"Customer#011416928","count":157,"preSum":7536},{"ndv":157,"upper":"Customer#011857445","lower":"Customer#011621202","count":157,"preSum":7693},{"ndv":157,"upper":"Customer#012071099","lower":"Customer#011861230","count":157,"preSum":7850},{"ndv":157,"upper":"Customer#012259466","lower":"Customer#012071133","count":157,"preSum":8007},{"ndv":157,"upper":"Customer#012467434","lower":"Customer#012261062","count":157,"preSum":8164},{"ndv":157,"upper":"Customer#012716546","lower":"Customer#012468142","count":157,"preSum":8321},{"ndv":157,"upper":"Customer#012962132","lower":"Customer#012718311","count":157,"preSum":8478},{"ndv":157,"upper":"Customer#013203199","lower":"Customer#012962704","count":157,"preSum":8635},{"ndv":157,"upper":"Customer#013415546","lower":"Customer#013204120","count":157,"preSum":8792},{"ndv":157,"upper":"Customer#013655471","lower":"Customer#013415906","count":157,"preSum":8949},{"ndv":157,"upper":"Customer#013887398","lower":"Customer#013656065","count":157,"preSum":9106},{"ndv":157,"upper":"Customer#014127064","lower":"Customer#013887489","count":157,"preSum":9263},{"ndv":157,"upper":"Customer#014373277","lower":"Customer#014128676","count":157,"preSum":9420},{"ndv":157,"upper":"Customer#014618761","lower":"Customer#014374617","count":157,"preSum":9577},{"ndv":157,"upper":"Customer#014834225","lower":"Customer#014620707","count":157,"preSum":9734},{"ndv":109,"upper":"Customer#014999258","lower":"Customer#014837832","count":109,"preSum":9891}],"maxBucketSize":64,"type":"String","sampleRate":0.09889925}
+customer.c_nationkey.histogram:
+  {"buckets":[{"ndv":1,"upper":0,"lower":0,"count":393,"preSum":0},{"ndv":1,"upper":1,"lower":1,"count":393,"preSum":393},{"ndv":1,"upper":2,"lower":2,"count":368,"preSum":786},{"ndv":1,"upper":3,"lower":3,"count":381,"preSum":1154},{"ndv":1,"upper":4,"lower":4,"count":424,"preSum":1535},{"ndv":1,"upper":5,"lower":5,"count":420,"preSum":1959},{"ndv":1,"upper":6,"lower":6,"count":426,"preSum":2379},{"ndv":1,"upper":7,"lower":7,"count":396,"preSum":2805},{"ndv":1,"upper":8,"lower":8,"count":407,"preSum":3201},{"ndv":1,"upper":9,"lower":9,"count":414,"preSum":3608},{"ndv":1,"upper":10,"lower":10,"count":416,"preSum":4022},{"ndv":1,"upper":11,"lower":11,"count":389,"preSum":4438},{"ndv":1,"upper":12,"lower":12,"count":363,"preSum":4827},{"ndv":1,"upper":13,"lower":13,"count":362,"preSum":5190},{"ndv":1,"upper":14,"lower":14,"count":408,"preSum":5552},{"ndv":1,"upper":15,"lower":15,"count":384,"preSum":5960},{"ndv":1,"upper":16,"lower":16,"count":419,"preSum":6344},{"ndv":1,"upper":17,"lower":17,"count":416,"preSum":6763},{"ndv":1,"upper":18,"lower":18,"count":409,"preSum":7179},{"ndv":1,"upper":19,"lower":19,"count":370,"preSum":7588},{"ndv":1,"upper":20,"lower":20,"count":403,"preSum":7958},{"ndv":1,"upper":21,"lower":21,"count":423,"preSum":8361},{"ndv":1,"upper":22,"lower":22,"count":390,"preSum":8784},{"ndv":1,"upper":23,"lower":23,"count":435,"preSum":9174},{"ndv":1,"upper":24,"lower":24,"count":391,"preSum":9609}],"maxBucketSize":64,"type":"Int","sampleRate":0.09889925}
+customer.c_phone.histogram:
+  {"buckets":[{"ndv":157,"upper":"10-393-418-6964","lower":"10-100-313-2731","count":157,"preSum":0},{"ndv":157,"upper":"10-712-814-7027","lower":"10-394-104-9753","count":157,"preSum":157},{"ndv":157,"upper":"11-157-672-1944","lower":"10-713-295-8205","count":157,"preSum":314},{"ndv":157,"upper":"11-487-746-4078","lower":"11-160-755-1428","count":157,"preSum":471},{"ndv":157,"upper":"11-833-496-1129","lower":"11-487-813-8989","count":157,"preSum":628},{"ndv":157,"upper":"12-302-329-1784","lower":"11-834-681-6234","count":157,"preSum":785},{"ndv":157,"upper":"12-681-518-5111","lower":"12-303-102-8014","count":157,"preSum":942},{"ndv":157,"upper":"13-138-351-5613","lower":"12-682-448-2822","count":157,"preSum":1099},{"ndv":157,"upper":"13-489-676-1788","lower":"13-139-772-5234","count":157,"preSum":1256},{"ndv":157,"upper":"13-837-648-6805","lower":"13-490-529-8402","count":157,"preSum":1413},{"ndv":157,"upper":"14-259-797-7091","lower":"13-840-202-3908","count":157,"preSum":1570},{"ndv":157,"upper":"14-625-297-1315","lower":"14-260-446-6233","count":157,"preSum":1727},{"ndv":157,"upper":"14-937-276-8500","lower":"14-625-541-4723","count":157,"preSum":1884},{"ndv":157,"upper":"15-370-559-6568","lower":"14-941-105-8346","count":157,"preSum":2041},{"ndv":157,"upper":"15-675-208-7429","lower":"15-372-566-7426","count":157,"preSum":2198},{"ndv":157,"upper":"16-124-508-6726","lower":"15-679-175-9910","count":157,"preSum":2355},{"ndv":157,"upper":"16-478-786-4204","lower":"16-124-552-8284","count":157,"preSum":2512},{"ndv":157,"upper":"16-898-288-4114","lower":"16-479-992-1023","count":157,"preSum":2669},{"ndv":157,"upper":"17-344-722-4209","lower":"16-900-369-7705","count":157,"preSum":2826},{"ndv":157,"upper":"17-725-410-3290","lower":"17-346-210-2166","count":157,"preSum":2983},{"ndv":157,"upper":"18-179-647-3322","lower":"17-726-198-5695","count":157,"preSum":3140},{"ndv":157,"upper":"18-554-608-2645","lower":"18-179-765-5958","count":157,"preSum":3297},{"ndv":157,"upper":"18-874-778-6458","lower":"18-555-210-1939","count":157,"preSum":3454},{"ndv":157,"upper":"19-373-140-2777","lower":"18-877-662-4633","count":157,"preSum":3611},{"ndv":157,"upper":"19-746-845-4277","lower":"19-374-132-7321","count":157,"preSum":3768},{"ndv":157,"upper":"20-239-275-8439","lower":"19-751-571-4992","count":157,"preSum":3925},{"ndv":157,"upper":"20-572-276-1803","lower":"20-240-325-7489","count":157,"preSum":4082},{"ndv":157,"upper":"20-946-662-1540","lower":"20-580-276-3476","count":157,"preSum":4239},{"ndv":157,"upper":"21-393-213-7862","lower":"20-949-425-3722","count":157,"preSum":4396},{"ndv":157,"upper":"21-761-414-1673","lower":"21-394-931-8719","count":157,"preSum":4553},{"ndv":157,"upper":"22-242-113-2589","lower":"21-762-472-8944","count":157,"preSum":4710},{"ndv":157,"upper":"22-608-463-8557","lower":"22-245-935-1060","count":157,"preSum":4867},{"ndv":157,"upper":"22-923-160-2562","lower":"22-608-476-8524","count":157,"preSum":5024},{"ndv":157,"upper":"23-361-187-9374","lower":"22-926-654-6939","count":157,"preSum":5181},{"ndv":157,"upper":"23-749-508-3225","lower":"23-361-687-8110","count":157,"preSum":5338},{"ndv":157,"upper":"24-219-230-1405","lower":"23-749-758-4497","count":157,"preSum":5495},{"ndv":157,"upper":"24-540-619-3016","lower":"24-219-625-3179","count":157,"preSum":5652},{"ndv":157,"upper":"24-876-325-9377","lower":"24-542-503-4787","count":157,"preSum":5809},{"ndv":157,"upper":"25-344-220-7182","lower":"24-881-645-8295","count":157,"preSum":5966},{"ndv":157,"upper":"25-707-776-3599","lower":"25-347-758-1362","count":157,"preSum":6123},{"ndv":157,"upper":"26-159-181-4551","lower":"25-708-625-1210","count":157,"preSum":6280},{"ndv":157,"upper":"26-502-433-5108","lower":"26-161-156-7668","count":157,"preSum":6437},{"ndv":157,"upper":"26-894-494-6389","lower":"26-506-982-4215","count":157,"preSum":6594},{"ndv":157,"upper":"27-348-579-2120","lower":"26-895-690-2287","count":157,"preSum":6751},{"ndv":157,"upper":"27-733-271-9045","lower":"27-351-476-7693","count":157,"preSum":6908},{"ndv":157,"upper":"28-179-715-5851","lower":"27-735-283-8522","count":157,"preSum":7065},{"ndv":157,"upper":"28-569-203-8176","lower":"28-184-612-7555","count":157,"preSum":7222},{"ndv":157,"upper":"28-905-233-9885","lower":"28-571-382-8712","count":157,"preSum":7379},{"ndv":157,"upper":"29-348-360-8072","lower":"28-905-352-3478","count":157,"preSum":7536},{"ndv":157,"upper":"29-690-461-6599","lower":"29-351-627-9153","count":157,"preSum":7693},{"ndv":157,"upper":"30-132-785-6066","lower":"29-691-432-2699","count":157,"preSum":7850},{"ndv":157,"upper":"30-448-820-9534","lower":"30-133-250-5008","count":157,"preSum":8007},{"ndv":157,"upper":"30-811-666-4360","lower":"30-449-782-9691","count":157,"preSum":8164},{"ndv":157,"upper":"31-250-445-6203","lower":"30-811-735-9727","count":157,"preSum":8321},{"ndv":157,"upper":"31-574-785-2683","lower":"31-252-409-5775","count":157,"preSum":8478},{"ndv":157,"upper":"32-110-348-9402","lower":"31-578-717-1960","count":157,"preSum":8635},{"ndv":157,"upper":"32-430-653-9885","lower":"32-111-698-6021","count":157,"preSum":8792},{"ndv":157,"upper":"32-769-882-4028","lower":"32-432-742-3641","count":157,"preSum":8949},{"ndv":157,"upper":"33-252-723-9233","lower":"32-770-209-3243","count":157,"preSum":9106},{"ndv":157,"upper":"33-578-104-2131","lower":"33-253-166-4849","count":157,"preSum":9263},{"ndv":157,"upper":"33-922-569-7370","lower":"33-578-731-8431","count":157,"preSum":9420},{"ndv":157,"upper":"34-416-189-6572","lower":"33-925-147-1011","count":157,"preSum":9577},{"ndv":157,"upper":"34-739-125-8720","lower":"34-416-502-1314","count":157,"preSum":9734},{"ndv":109,"upper":"34-998-799-9691","lower":"34-739-147-4471","count":109,"preSum":9891}],"maxBucketSize":64,"type":"String","sampleRate":0.09889925}
+lineitem.l_comment.histogram:
+  {"buckets":[{"ndv":146,"upper":" around the fluffily","lower":" about the","count":157,"preSum":0},{"ndv":150,"upper":" carefully final p","lower":" around the ironic p","count":157,"preSum":157},{"ndv":150,"upper":" excuses after ","lower":" carefully final pac","count":157,"preSum":314},{"ndv":150,"upper":" furiously furiously","lower":" excuses are","count":157,"preSum":471},{"ndv":149,"upper":" maintain furiously.","lower":" furiously i","count":157,"preSum":628},{"ndv":153,"upper":" quickly regul","lower":" mold carefully fina","count":157,"preSum":785},{"ndv":150,"upper":" sleep. special forg","lower":" quickly regula","count":157,"preSum":942},{"ndv":148,"upper":" the regularly silen","lower":" slow attainments. s","count":157,"preSum":1099},{"ndv":149,"upper":", special grouches g","lower":" the requests haggle","count":157,"preSum":1256},{"ndv":150,"upper":". stealthy, special ","lower":", special instructio","count":157,"preSum":1413},{"ndv":145,"upper":"against the carefull","lower":". theodolites agains","count":157,"preSum":1570},{"ndv":154,"upper":"al deposits. careful","lower":"against the final pa","count":157,"preSum":1727},{"ndv":154,"upper":"ar pinto b","lower":"al deposits. even de","count":157,"preSum":1884},{"ndv":151,"upper":"atelets. depen","lower":"ar pinto beans sleep","count":157,"preSum":2041},{"ndv":151,"upper":"bove the stealthily","lower":"atelets. final accou","count":157,"preSum":2198},{"ndv":152,"upper":"ccounts nag blithely","lower":"braids haggle carefu","count":157,"preSum":2355},{"ndv":150,"upper":"counts cajole carefu","lower":"ccounts nag slyly ac","count":158,"preSum":2512},{"ndv":152,"upper":"deposits cajole quic","lower":"counts cajole quickl","count":157,"preSum":2670},{"ndv":150,"upper":"e carefully across t","lower":"deposits d","count":157,"preSum":2827},{"ndv":149,"upper":"e. blithely final re","lower":"e carefully at the s","count":157,"preSum":2984},{"ndv":155,"upper":"egular accounts wake","lower":"e. carefull","count":157,"preSum":3141},{"ndv":151,"upper":"ending foxes wake sl","lower":"egular accounts. exp","count":157,"preSum":3298},{"ndv":154,"upper":"equests. blithely ir","lower":"ending foxes. silent","count":157,"preSum":3455},{"ndv":154,"upper":"ess requests. bold d","lower":"equests. car","count":157,"preSum":3612},{"ndv":152,"upper":"ffily even dependenc","lower":"ess sauternes. furio","count":157,"preSum":3769},{"ndv":152,"upper":"fully express, unusu","lower":"ffily even pinto bea","count":157,"preSum":3926},{"ndv":150,"upper":"gainst the careful","lower":"fully final accounts","count":157,"preSum":4083},{"ndv":154,"upper":"haggle against the e","lower":"gainst the slyly fin","count":157,"preSum":4240},{"ndv":149,"upper":"hely regular package","lower":"haggle against the f","count":157,"preSum":4397},{"ndv":152,"upper":"ickly regular instru","lower":"hely special ac","count":157,"preSum":4554},{"ndv":154,"upper":"ing accounts are flu","lower":"ickly regular s","count":157,"preSum":4711},{"ndv":152,"upper":"iously regular ideas","lower":"ing accounts sleep a","count":157,"preSum":4868},{"ndv":151,"upper":"its. expres","lower":"iously regular instr","count":157,"preSum":5025},{"ndv":155,"upper":"l ideas. ide","lower":"its. express escapad","count":157,"preSum":5182},{"ndv":155,"upper":"le carefully. ironic","lower":"l ideas. regular din","count":157,"preSum":5339},{"ndv":154,"upper":"lly express accounts","lower":"le closely according","count":157,"preSum":5496},{"ndv":148,"upper":"ly carefully iro","lower":"lly express deposits","count":157,"preSum":5653},{"ndv":134,"upper":"ly slyly express r","lower":"ly carefully regular","count":157,"preSum":5810},{"ndv":152,"upper":"n instructions wake ","lower":"ly slyly special the","count":157,"preSum":5967},{"ndv":152,"upper":"ng ideas. carefu","lower":"n instructions. d","count":157,"preSum":6124},{"ndv":153,"upper":"nstructions","lower":"ng instruction","count":157,"preSum":6281},{"ndv":153,"upper":"o beans lose blithel","lower":"nstructions ","count":157,"preSum":6438},{"ndv":156,"upper":"onic accounts sleep ","lower":"o beans nag furiousl","count":157,"preSum":6595},{"ndv":155,"upper":"ost carefull","lower":"onic accounts wake f","count":157,"preSum":6752},{"ndv":154,"upper":"oxes. quickly d","lower":"ost carefully blithe","count":157,"preSum":6909},{"ndv":151,"upper":"posits after the unu","lower":"oxes. regu","count":157,"preSum":7066},{"ndv":155,"upper":"r requests. requ","lower":"posits along the bli","count":157,"preSum":7223},{"ndv":151,"upper":"regular epitaphs thr","lower":"r sheaves x-ray alon","count":157,"preSum":7380},{"ndv":154,"upper":"riously special inst","lower":"regular excus","count":157,"preSum":7537},{"ndv":154,"upper":"s cajole about the","lower":"riously unusual depo","count":157,"preSum":7694},{"ndv":155,"upper":"s wake. regular hock","lower":"s cajole above the q","count":157,"preSum":7851},{"ndv":152,"upper":"sias. ironic, f","lower":"s wake. regular, sil","count":157,"preSum":8008},{"ndv":152,"upper":"slyly regula","lower":"side of the blithely","count":157,"preSum":8165},{"ndv":153,"upper":"sual deposits. ","lower":"slyly regular ","count":157,"preSum":8322},{"ndv":149,"upper":"the even, r","lower":"sual dolphins. slyly","count":157,"preSum":8479},{"ndv":151,"upper":"to beans from the fl","lower":"the even, regular re","count":157,"preSum":8636},{"ndv":152,"upper":"ts. bold foxes","lower":"to beans haggle alwa","count":157,"preSum":8793},{"ndv":156,"upper":"uickly reg","lower":"ts. braids lose busi","count":157,"preSum":8950},{"ndv":148,"upper":"unts mold fluffily. ","lower":"uickly regul","count":157,"preSum":9107},{"ndv":150,"upper":"usly express request","lower":"unts nag bl","count":157,"preSum":9264},{"ndv":154,"upper":"x. daring, silent th","lower":"usly final accounts.","count":157,"preSum":9421},{"ndv":152,"upper":"y final depo","lower":"xcuses according to ","count":157,"preSum":9578},{"ndv":149,"upper":"y theodolites","lower":"y final deposits hag","count":157,"preSum":9735},{"ndv":105,"upper":"zzle slyly foxes. id","lower":"y theodolites. caref","count":108,"preSum":9892}],"maxBucketSize":64,"type":"String","sampleRate":0.09979044}
+lineitem.l_commitdate.histogram:
+  {"buckets":[{"ndv":56,"upper":"1992-04-08","lower":"1992-02-06","count":158,"preSum":0},{"ndv":37,"upper":"1992-05-15","lower":"1992-04-09","count":158,"preSum":158},{"ndv":40,"upper":"1992-06-25","lower":"1992-05-16","count":157,"preSum":316},{"ndv":40,"upper":"1992-08-05","lower":"1992-06-26","count":157,"preSum":473},{"ndv":37,"upper":"1992-09-11","lower":"1992-08-06","count":157,"preSum":630},{"ndv":34,"upper":"1992-10-16","lower":"1992-09-12","count":158,"preSum":787},{"ndv":33,"upper":"1992-11-18","lower":"1992-10-17","count":157,"preSum":945},{"ndv":38,"upper":"1992-12-26","lower":"1992-11-19","count":159,"preSum":1102},{"ndv":39,"upper":"1993-02-03","lower":"1992-12-27","count":157,"preSum":1261},{"ndv":34,"upper":"1993-03-11","lower":"1993-02-04","count":158,"preSum":1418},{"ndv":35,"upper":"1993-04-15","lower":"1993-03-12","count":158,"preSum":1576},{"ndv":37,"upper":"1993-05-22","lower":"1993-04-16","count":163,"preSum":1734},{"ndv":39,"upper":"1993-06-30","lower":"1993-05-23","count":157,"preSum":1897},{"ndv":43,"upper":"1993-08-12","lower":"1993-07-01","count":158,"preSum":2054},{"ndv":34,"upper":"1993-09-15","lower":"1993-08-13","count":161,"preSum":2212},{"ndv":41,"upper":"1993-10-27","lower":"1993-09-16","count":160,"preSum":2373},{"ndv":40,"upper":"1993-12-06","lower":"1993-10-28","count":159,"preSum":2533},{"ndv":35,"upper":"1994-01-11","lower":"1993-12-07","count":157,"preSum":2692},{"ndv":36,"upper":"1994-02-18","lower":"1994-01-12","count":162,"preSum":2849},{"ndv":38,"upper":"1994-03-30","lower":"1994-02-19","count":157,"preSum":3011},{"ndv":40,"upper":"1994-05-10","lower":"1994-03-31","count":158,"preSum":3168},{"ndv":34,"upper":"1994-06-15","lower":"1994-05-11","count":163,"preSum":3326},{"ndv":38,"upper":"1994-07-27","lower":"1994-06-16","count":159,"preSum":3489},{"ndv":42,"upper":"1994-09-07","lower":"1994-07-28","count":158,"preSum":3648},{"ndv":36,"upper":"1994-10-14","lower":"1994-09-08","count":161,"preSum":3806},{"ndv":35,"upper":"1994-11-18","lower":"1994-10-15","count":160,"preSum":3967},{"ndv":41,"upper":"1994-12-30","lower":"1994-11-19","count":164,"preSum":4127},{"ndv":36,"upper":"1995-02-06","lower":"1994-12-31","count":160,"preSum":4291},{"ndv":37,"upper":"1995-03-15","lower":"1995-02-07","count":158,"preSum":4451},{"ndv":38,"upper":"1995-04-22","lower":"1995-03-16","count":160,"preSum":4609},{"ndv":41,"upper":"1995-06-02","lower":"1995-04-23","count":159,"preSum":4769},{"ndv":42,"upper":"1995-07-16","lower":"1995-06-03","count":159,"preSum":4928},{"ndv":41,"upper":"1995-08-27","lower":"1995-07-17","count":157,"preSum":5087},{"ndv":38,"upper":"1995-10-04","lower":"1995-08-28","count":159,"preSum":5244},{"ndv":36,"upper":"1995-11-09","lower":"1995-10-05","count":157,"preSum":5403},{"ndv":34,"upper":"1995-12-13","lower":"1995-11-10","count":157,"preSum":5560},{"ndv":37,"upper":"1996-01-19","lower":"1995-12-14","count":160,"preSum":5717},{"ndv":37,"upper":"1996-02-25","lower":"1996-01-20","count":157,"preSum":5877},{"ndv":36,"upper":"1996-04-02","lower":"1996-02-26","count":161,"preSum":6034},{"ndv":38,"upper":"1996-05-10","lower":"1996-04-03","count":160,"preSum":6195},{"ndv":32,"upper":"1996-06-12","lower":"1996-05-11","count":160,"preSum":6355},{"ndv":40,"upper":"1996-07-22","lower":"1996-06-13","count":158,"preSum":6515},{"ndv":40,"upper":"1996-09-01","lower":"1996-07-23","count":159,"preSum":6673},{"ndv":38,"upper":"1996-10-09","lower":"1996-09-02","count":159,"preSum":6832},{"ndv":41,"upper":"1996-11-20","lower":"1996-10-10","count":160,"preSum":6991},{"ndv":38,"upper":"1996-12-28","lower":"1996-11-21","count":161,"preSum":7151},{"ndv":40,"upper":"1997-02-06","lower":"1996-12-29","count":158,"preSum":7312},{"ndv":43,"upper":"1997-03-22","lower":"1997-02-07","count":162,"preSum":7470},{"ndv":36,"upper":"1997-04-27","lower":"1997-03-23","count":159,"preSum":7632},{"ndv":39,"upper":"1997-06-05","lower":"1997-04-28","count":157,"preSum":7791},{"ndv":35,"upper":"1997-07-11","lower":"1997-06-06","count":161,"preSum":7948},{"ndv":35,"upper":"1997-08-15","lower":"1997-07-12","count":159,"preSum":8109},{"ndv":38,"upper":"1997-09-22","lower":"1997-08-16","count":158,"preSum":8268},{"ndv":38,"upper":"1997-10-31","lower":"1997-09-23","count":160,"preSum":8426},{"ndv":38,"upper":"1997-12-08","lower":"1997-11-01","count":157,"preSum":8586},{"ndv":39,"upper":"1998-01-16","lower":"1997-12-09","count":160,"preSum":8743},{"ndv":38,"upper":"1998-02-23","lower":"1998-01-17","count":159,"preSum":8903},{"ndv":30,"upper":"1998-03-26","lower":"1998-02-24","count":159,"preSum":9062},{"ndv":38,"upper":"1998-05-03","lower":"1998-03-27","count":158,"preSum":9221},{"ndv":35,"upper":"1998-06-07","lower":"1998-05-04","count":161,"preSum":9379},{"ndv":37,"upper":"1998-07-14","lower":"1998-06-08","count":159,"preSum":9540},{"ndv":43,"upper":"1998-08-27","lower":"1998-07-15","count":159,"preSum":9699},{"ndv":53,"upper":"1998-10-28","lower":"1998-08-28","count":142,"preSum":9858}],"maxBucketSize":64,"type":"Date","sampleRate":0.09979044}
+lineitem.l_discount.histogram:
+  {"buckets":[{"ndv":1,"upper":0.00,"lower":0.00,"count":849,"preSum":0},{"ndv":1,"upper":0.01,"lower":0.01,"count":936,"preSum":849},{"ndv":1,"upper":0.02,"lower":0.02,"count":942,"preSum":1785},{"ndv":1,"upper":0.03,"lower":0.03,"count":911,"preSum":2727},{"ndv":1,"upper":0.04,"lower":0.04,"count":904,"preSum":3638},{"ndv":1,"upper":0.05,"lower":0.05,"count":855,"preSum":4542},{"ndv":1,"upper":0.06,"lower":0.06,"count":945,"preSum":5397},{"ndv":1,"upper":0.07,"lower":0.07,"count":947,"preSum":6342},{"ndv":1,"upper":0.08,"lower":0.08,"count":900,"preSum":7289},{"ndv":1,"upper":0.09,"lower":0.09,"count":891,"preSum":8189},{"ndv":1,"upper":0.10,"lower":0.10,"count":920,"preSum":9080}],"maxBucketSize":64,"type":"Double","sampleRate":0.09979044}
+lineitem.l_extendedprice.histogram:
+  {"buckets":[{"ndv":157,"upper":1905.46,"lower":989.11,"count":157,"preSum":0},{"ndv":157,"upper":3111.48,"lower":1907.13,"count":157,"preSum":157},{"ndv":157,"upper":3892.50,"lower":3120.58,"count":157,"preSum":314},{"ndv":157,"upper":5216.49,"lower":3894.46,"count":157,"preSum":471},{"ndv":157,"upper":6268.85,"lower":5217.48,"count":157,"preSum":628},{"ndv":157,"upper":7417.12,"lower":6281.45,"count":157,"preSum":785},{"ndv":156,"upper":8564.29,"lower":7418.60,"count":157,"preSum":942},{"ndv":156,"upper":9692.65,"lower":8571.99,"count":157,"preSum":1099},{"ndv":157,"upper":11009.40,"lower":9698.22,"count":157,"preSum":1256},{"ndv":157,"upper":12036.42,"lower":11009.46,"count":157,"preSum":1413},{"ndv":157,"upper":13297.92,"lower":12037.62,"count":157,"preSum":1570},{"ndv":157,"upper":14232.92,"lower":13303.92,"count":157,"preSum":1727},{"ndv":157,"upper":15515.46,"lower":14238.12,"count":157,"preSum":1884},{"ndv":157,"upper":16765.00,"lower":15526.56,"count":157,"preSum":2041},{"ndv":157,"upper":18008.21,"lower":16798.50,"count":157,"preSum":2198},{"ndv":157,"upper":19054.92,"lower":18014.08,"count":157,"preSum":2355},{"ndv":157,"upper":20093.76,"lower":19058.62,"count":157,"preSum":2512},{"ndv":156,"upper":21178.82,"lower":20095.20,"count":157,"preSum":2669},{"ndv":157,"upper":22215.27,"lower":21183.86,"count":157,"preSum":2826},{"ndv":157,"upper":23393.70,"lower":22216.61,"count":157,"preSum":2983},{"ndv":157,"upper":24490.80,"lower":23409.14,"count":157,"preSum":3140},{"ndv":156,"upper":25560.90,"lower":24497.68,"count":157,"preSum":3297},{"ndv":155,"upper":26684.00,"lower":25566.13,"count":157,"preSum":3454},{"ndv":157,"upper":27887.86,"lower":26685.36,"count":157,"preSum":3611},{"ndv":157,"upper":29030.25,"lower":27898.53,"count":157,"preSum":3768},{"ndv":157,"upper":30408.60,"lower":29030.76,"count":157,"preSum":3925},{"ndv":156,"upper":31604.53,"lower":30419.00,"count":157,"preSum":4082},{"ndv":157,"upper":32733.21,"lower":31612.58,"count":157,"preSum":4239},{"ndv":157,"upper":33794.75,"lower":32733.75,"count":157,"preSum":4396},{"ndv":157,"upper":34824.75,"lower":33798.15,"count":157,"preSum":4553},{"ndv":157,"upper":36058.40,"lower":34872.21,"count":157,"preSum":4710},{"ndv":157,"upper":37230.27,"lower":36064.50,"count":157,"preSum":4867},{"ndv":156,"upper":38332.35,"lower":37239.28,"count":157,"preSum":5024},{"ndv":157,"upper":39521.16,"lower":38351.24,"count":157,"preSum":5181},{"ndv":157,"upper":40627.60,"lower":39525.12,"count":157,"preSum":5338},{"ndv":155,"upper":41687.91,"lower":40647.12,"count":157,"preSum":5495},{"ndv":157,"upper":42827.08,"lower":41712.96,"count":157,"preSum":5652},{"ndv":157,"upper":43961.91,"lower":42828.10,"count":157,"preSum":5809},{"ndv":157,"upper":45028.43,"lower":43969.44,"count":157,"preSum":5966},{"ndv":157,"upper":46138.56,"lower":45030.03,"count":157,"preSum":6123},{"ndv":157,"upper":47276.80,"lower":46148.52,"count":157,"preSum":6280},{"ndv":157,"upper":48402.20,"lower":47281.08,"count":157,"preSum":6437},{"ndv":157,"upper":49452.83,"lower":48413.40,"count":157,"preSum":6594},{"ndv":156,"upper":50573.50,"lower":49453.60,"count":157,"preSum":6751},{"ndv":157,"upper":51676.20,"lower":50577.15,"count":157,"preSum":6908},{"ndv":156,"upper":52819.89,"lower":51676.94,"count":157,"preSum":7065},{"ndv":157,"upper":54140.40,"lower":52835.47,"count":157,"preSum":7222},{"ndv":156,"upper":55556.20,"lower":54141.18,"count":157,"preSum":7379},{"ndv":157,"upper":56892.75,"lower":55562.92,"count":157,"preSum":7536},{"ndv":157,"upper":58198.98,"lower":56904.50,"count":157,"preSum":7693},{"ndv":155,"upper":59778.53,"lower":58207.93,"count":157,"preSum":7850},{"ndv":157,"upper":61415.98,"lower":59803.11,"count":157,"preSum":8007},{"ndv":157,"upper":63170.50,"lower":61421.63,"count":157,"preSum":8164},{"ndv":157,"upper":65068.15,"lower":63193.62,"count":157,"preSum":8321},{"ndv":156,"upper":66794.52,"lower":65068.92,"count":157,"preSum":8478},{"ndv":156,"upper":68591.70,"lower":66804.32,"count":157,"preSum":8635},{"ndv":157,"upper":70816.80,"lower":68604.12,"count":157,"preSum":8792},{"ndv":156,"upper":73000.50,"lower":70818.37,"count":157,"preSum":8949},{"ndv":156,"upper":75566.80,"lower":73026.53,"count":157,"preSum":9106},{"ndv":157,"upper":78339.80,"lower":75586.26,"count":157,"preSum":9263},{"ndv":157,"upper":81829.02,"lower":78373.55,"count":157,"preSum":9420},{"ndv":156,"upper":85339.32,"lower":81903.36,"count":157,"preSum":9577},{"ndv":157,"upper":90356.00,"lower":85347.00,"count":157,"preSum":9734},{"ndv":109,"upper":104667.00,"lower":90378.04,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Double","sampleRate":0.09979044}
+lineitem.l_linenumber.histogram:
+  {"buckets":[{"ndv":1,"upper":1,"lower":1,"count":2499,"preSum":0},{"ndv":1,"upper":2,"lower":2,"count":2141,"preSum":2499},{"ndv":1,"upper":3,"lower":3,"count":1788,"preSum":4640},{"ndv":1,"upper":4,"lower":4,"count":1438,"preSum":6428},{"ndv":1,"upper":5,"lower":5,"count":1054,"preSum":7866},{"ndv":1,"upper":6,"lower":6,"count":701,"preSum":8920},{"ndv":1,"upper":7,"lower":7,"count":379,"preSum":9621}],"maxBucketSize":64,"type":"Int","sampleRate":0.09979044}
+lineitem.l_linestatus.histogram:
+  {"buckets":[{"ndv":1,"upper":"F","lower":"F","count":5071,"preSum":0},{"ndv":1,"upper":"O","lower":"O","count":4929,"preSum":5071}],"maxBucketSize":64,"type":"String","sampleRate":0.09979044}
+lineitem.l_orderkey.histogram:
+  {"buckets":[{"ndv":157,"upper":9629060,"lower":35845,"count":157,"preSum":0},{"ndv":157,"upper":19086852,"lower":9740449,"count":157,"preSum":157},{"ndv":157,"upper":28627495,"lower":19143623,"count":157,"preSum":314},{"ndv":157,"upper":36875685,"lower":28692768,"count":157,"preSum":471},{"ndv":157,"upper":47447910,"lower":36965217,"count":157,"preSum":628},{"ndv":157,"upper":56455362,"lower":47528259,"count":157,"preSum":785},{"ndv":157,"upper":65534373,"lower":56494374,"count":157,"preSum":942},{"ndv":157,"upper":74497062,"lower":65651074,"count":157,"preSum":1099},{"ndv":157,"upper":85175207,"lower":74547650,"count":157,"preSum":1256},{"ndv":157,"upper":94792000,"lower":85254403,"count":157,"preSum":1413},{"ndv":157,"upper":104562020,"lower":94883138,"count":157,"preSum":1570},{"ndv":157,"upper":114686561,"lower":104627652,"count":157,"preSum":1727},{"ndv":157,"upper":124461157,"lower":114778913,"count":157,"preSum":1884},{"ndv":157,"upper":133654048,"lower":124588865,"count":157,"preSum":2041},{"ndv":157,"upper":142415971,"lower":133722663,"count":157,"preSum":2198},{"ndv":157,"upper":150821122,"lower":142571846,"count":157,"preSum":2355},{"ndv":157,"upper":160380613,"lower":150918821,"count":157,"preSum":2512},{"ndv":157,"upper":170925377,"lower":160469766,"count":157,"preSum":2669},{"ndv":157,"upper":181446976,"lower":170984548,"count":157,"preSum":2826},{"ndv":157,"upper":192087714,"lower":181459366,"count":157,"preSum":2983},{"ndv":157,"upper":201747683,"lower":192554213,"count":157,"preSum":3140},{"ndv":157,"upper":211951908,"lower":201800804,"count":157,"preSum":3297},{"ndv":157,"upper":220703619,"lower":211977347,"count":157,"preSum":3454},{"ndv":157,"upper":230752645,"lower":220870884,"count":157,"preSum":3611},{"ndv":157,"upper":240387205,"lower":230816038,"count":157,"preSum":3768},{"ndv":157,"upper":249883267,"lower":240441223,"count":157,"preSum":3925},{"ndv":157,"upper":258828065,"lower":249904643,"count":157,"preSum":4082},{"ndv":157,"upper":267492128,"lower":258828997,"count":157,"preSum":4239},{"ndv":157,"upper":276775392,"lower":267552640,"count":157,"preSum":4396},{"ndv":157,"upper":285729473,"lower":276825223,"count":157,"preSum":4553},{"ndv":157,"upper":295278215,"lower":285733312,"count":157,"preSum":4710},{"ndv":157,"upper":304795264,"lower":295306336,"count":157,"preSum":4867},{"ndv":157,"upper":315039872,"lower":304827648,"count":157,"preSum":5024},{"ndv":157,"upper":324176135,"lower":315052805,"count":157,"preSum":5181},{"ndv":157,"upper":333709730,"lower":324206370,"count":157,"preSum":5338},{"ndv":157,"upper":342394465,"lower":333737216,"count":157,"preSum":5495},{"ndv":157,"upper":352386501,"lower":342448998,"count":157,"preSum":5652},{"ndv":157,"upper":362903751,"lower":352441893,"count":157,"preSum":5809},{"ndv":157,"upper":373254051,"lower":362908129,"count":157,"preSum":5966},{"ndv":157,"upper":382624385,"lower":373283617,"count":157,"preSum":6123},{"ndv":157,"upper":392876740,"lower":382637445,"count":157,"preSum":6280},{"ndv":157,"upper":402692579,"lower":392913350,"count":157,"preSum":6437},{"ndv":157,"upper":411227046,"lower":402717600,"count":157,"preSum":6594},{"ndv":157,"upper":421346403,"lower":411240071,"count":157,"preSum":6751},{"ndv":157,"upper":430644930,"lower":421386915,"count":157,"preSum":6908},{"ndv":157,"upper":439706338,"lower":430694912,"count":157,"preSum":7065},{"ndv":157,"upper":448968516,"lower":439723622,"count":157,"preSum":7222},{"ndv":157,"upper":458116966,"lower":448997095,"count":157,"preSum":7379},{"ndv":157,"upper":468002406,"lower":458165186,"count":157,"preSum":7536},{"ndv":157,"upper":476924005,"lower":468028389,"count":157,"preSum":7693},{"ndv":157,"upper":486526949,"lower":476959491,"count":157,"preSum":7850},{"ndv":157,"upper":495099431,"lower":486534055,"count":157,"preSum":8007},{"ndv":157,"upper":503040036,"lower":495141061,"count":157,"preSum":8164},{"ndv":157,"upper":511755655,"lower":503106690,"count":157,"preSum":8321},{"ndv":157,"upper":519911651,"lower":511863267,"count":157,"preSum":8478},{"ndv":157,"upper":528594085,"lower":520140070,"count":157,"preSum":8635},{"ndv":157,"upper":537962594,"lower":528595232,"count":157,"preSum":8792},{"ndv":157,"upper":546646817,"lower":538000677,"count":157,"preSum":8949},{"ndv":157,"upper":555001605,"lower":546665347,"count":157,"preSum":9106},{"ndv":157,"upper":564123841,"lower":555008707,"count":157,"preSum":9263},{"ndv":157,"upper":575259392,"lower":564138080,"count":157,"preSum":9420},{"ndv":157,"upper":584490755,"lower":575269696,"count":157,"preSum":9577},{"ndv":157,"upper":593553760,"lower":584539074,"count":157,"preSum":9734},{"ndv":109,"upper":599958629,"lower":593560929,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Int","sampleRate":0.09979044}
+lineitem.l_partkey.histogram:
+  {"buckets":[{"ndv":157,"upper":305375,"lower":2491,"count":157,"preSum":0},{"ndv":157,"upper":595118,"lower":305457,"count":157,"preSum":157},{"ndv":157,"upper":896521,"lower":599745,"count":157,"preSum":314},{"ndv":157,"upper":1230643,"lower":897652,"count":157,"preSum":471},{"ndv":157,"upper":1535478,"lower":1231892,"count":157,"preSum":628},{"ndv":157,"upper":1852729,"lower":1535602,"count":157,"preSum":785},{"ndv":157,"upper":2158985,"lower":1855038,"count":157,"preSum":942},{"ndv":157,"upper":2483051,"lower":2159902,"count":157,"preSum":1099},{"ndv":157,"upper":2786689,"lower":2491802,"count":157,"preSum":1256},{"ndv":157,"upper":3075930,"lower":2787471,"count":157,"preSum":1413},{"ndv":157,"upper":3398345,"lower":3077928,"count":157,"preSum":1570},{"ndv":157,"upper":3767095,"lower":3400351,"count":157,"preSum":1727},{"ndv":157,"upper":4068050,"lower":3767399,"count":157,"preSum":1884},{"ndv":157,"upper":4444953,"lower":4068407,"count":157,"preSum":2041},{"ndv":157,"upper":4738038,"lower":4450684,"count":157,"preSum":2198},{"ndv":157,"upper":5048742,"lower":4740337,"count":157,"preSum":2355},{"ndv":157,"upper":5331310,"lower":5048748,"count":157,"preSum":2512},{"ndv":157,"upper":5619696,"lower":5331446,"count":157,"preSum":2669},{"ndv":157,"upper":5920984,"lower":5621825,"count":157,"preSum":2826},{"ndv":157,"upper":6236852,"lower":5921698,"count":157,"preSum":2983},{"ndv":157,"upper":6523839,"lower":6239465,"count":157,"preSum":3140},{"ndv":157,"upper":6850698,"lower":6525914,"count":157,"preSum":3297},{"ndv":157,"upper":7144056,"lower":6856156,"count":157,"preSum":3454},{"ndv":157,"upper":7470417,"lower":7146151,"count":157,"preSum":3611},{"ndv":157,"upper":7780604,"lower":7470715,"count":157,"preSum":3768},{"ndv":156,"upper":8095617,"lower":7784115,"count":157,"preSum":3925},{"ndv":157,"upper":8435321,"lower":8096078,"count":157,"preSum":4082},{"ndv":157,"upper":8758836,"lower":8436211,"count":157,"preSum":4239},{"ndv":157,"upper":9075726,"lower":8760727,"count":157,"preSum":4396},{"ndv":157,"upper":9380932,"lower":9077101,"count":157,"preSum":4553},{"ndv":157,"upper":9671939,"lower":9381662,"count":157,"preSum":4710},{"ndv":157,"upper":10012928,"lower":9673204,"count":157,"preSum":4867},{"ndv":157,"upper":10338086,"lower":10015145,"count":157,"preSum":5024},{"ndv":157,"upper":10613089,"lower":10340200,"count":157,"preSum":5181},{"ndv":157,"upper":10929329,"lower":10614113,"count":157,"preSum":5338},{"ndv":157,"upper":11237463,"lower":10930744,"count":157,"preSum":5495},{"ndv":157,"upper":11534779,"lower":11237699,"count":157,"preSum":5652},{"ndv":157,"upper":11837484,"lower":11535041,"count":157,"preSum":5809},{"ndv":157,"upper":12213611,"lower":11839626,"count":157,"preSum":5966},{"ndv":157,"upper":12517665,"lower":12214795,"count":157,"preSum":6123},{"ndv":157,"upper":12848375,"lower":12518248,"count":157,"preSum":6280},{"ndv":157,"upper":13169652,"lower":12848898,"count":157,"preSum":6437},{"ndv":156,"upper":13517891,"lower":13170915,"count":157,"preSum":6594},{"ndv":157,"upper":13820194,"lower":13518441,"count":157,"preSum":6751},{"ndv":157,"upper":14151737,"lower":13822639,"count":157,"preSum":6908},{"ndv":157,"upper":14470700,"lower":14155287,"count":157,"preSum":7065},{"ndv":157,"upper":14763777,"lower":14471952,"count":157,"preSum":7222},{"ndv":157,"upper":15057177,"lower":14764348,"count":157,"preSum":7379},{"ndv":157,"upper":15410121,"lower":15063168,"count":157,"preSum":7536},{"ndv":157,"upper":15762627,"lower":15410668,"count":157,"preSum":7693},{"ndv":157,"upper":16035404,"lower":15768220,"count":157,"preSum":7850},{"ndv":157,"upper":16356288,"lower":16036793,"count":157,"preSum":8007},{"ndv":157,"upper":16675698,"lower":16356488,"count":157,"preSum":8164},{"ndv":157,"upper":17006506,"lower":16676472,"count":157,"preSum":8321},{"ndv":157,"upper":17302003,"lower":17007787,"count":157,"preSum":8478},{"ndv":157,"upper":17617187,"lower":17303537,"count":157,"preSum":8635},{"ndv":157,"upper":17896450,"lower":17618517,"count":157,"preSum":8792},{"ndv":157,"upper":18199451,"lower":17896880,"count":157,"preSum":8949},{"ndv":157,"upper":18515549,"lower":18200039,"count":157,"preSum":9106},{"ndv":157,"upper":18855499,"lower":18517360,"count":157,"preSum":9263},{"ndv":157,"upper":19159141,"lower":18859172,"count":157,"preSum":9420},{"ndv":157,"upper":19427989,"lower":19159527,"count":157,"preSum":9577},{"ndv":157,"upper":19804488,"lower":19428258,"count":157,"preSum":9734},{"ndv":109,"upper":19999129,"lower":19805165,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Int","sampleRate":0.09979044}
+lineitem.l_quantity.histogram:
+  {"buckets":[{"ndv":1,"upper":1.00,"lower":1.00,"count":202,"preSum":0},{"ndv":1,"upper":2.00,"lower":2.00,"count":199,"preSum":202},{"ndv":1,"upper":3.00,"lower":3.00,"count":232,"preSum":401},{"ndv":1,"upper":4.00,"lower":4.00,"count":185,"preSum":633},{"ndv":1,"upper":5.00,"lower":5.00,"count":188,"preSum":818},{"ndv":1,"upper":6.00,"lower":6.00,"count":206,"preSum":1006},{"ndv":1,"upper":7.00,"lower":7.00,"count":213,"preSum":1212},{"ndv":1,"upper":8.00,"lower":8.00,"count":232,"preSum":1425},{"ndv":1,"upper":9.00,"lower":9.00,"count":212,"preSum":1657},{"ndv":1,"upper":10.00,"lower":10.00,"count":180,"preSum":1869},{"ndv":1,"upper":11.00,"lower":11.00,"count":191,"preSum":2049},{"ndv":1,"upper":12.00,"lower":12.00,"count":188,"preSum":2240},{"ndv":1,"upper":13.00,"lower":13.00,"count":215,"preSum":2428},{"ndv":1,"upper":14.00,"lower":14.00,"count":168,"preSum":2643},{"ndv":1,"upper":15.00,"lower":15.00,"count":186,"preSum":2811},{"ndv":1,"upper":16.00,"lower":16.00,"count":220,"preSum":2997},{"ndv":1,"upper":17.00,"lower":17.00,"count":193,"preSum":3217},{"ndv":1,"upper":18.00,"lower":18.00,"count":199,"preSum":3410},{"ndv":1,"upper":19.00,"lower":19.00,"count":186,"preSum":3609},{"ndv":1,"upper":20.00,"lower":20.00,"count":199,"preSum":3795},{"ndv":1,"upper":21.00,"lower":21.00,"count":225,"preSum":3994},{"ndv":1,"upper":22.00,"lower":22.00,"count":198,"preSum":4219},{"ndv":1,"upper":23.00,"lower":23.00,"count":205,"preSum":4417},{"ndv":1,"upper":24.00,"lower":24.00,"count":193,"preSum":4622},{"ndv":1,"upper":25.00,"lower":25.00,"count":204,"preSum":4815},{"ndv":1,"upper":26.00,"lower":26.00,"count":188,"preSum":5019},{"ndv":1,"upper":27.00,"lower":27.00,"count":212,"preSum":5207},{"ndv":1,"upper":28.00,"lower":28.00,"count":210,"preSum":5419},{"ndv":1,"upper":29.00,"lower":29.00,"count":217,"preSum":5629},{"ndv":1,"upper":30.00,"lower":30.00,"count":202,"preSum":5846},{"ndv":1,"upper":31.00,"lower":31.00,"count":213,"preSum":6048},{"ndv":1,"upper":32.00,"lower":32.00,"count":187,"preSum":6261},{"ndv":1,"upper":33.00,"lower":33.00,"count":217,"preSum":6448},{"ndv":1,"upper":34.00,"lower":34.00,"count":211,"preSum":6665},{"ndv":1,"upper":35.00,"lower":35.00,"count":199,"preSum":6876},{"ndv":1,"upper":36.00,"lower":36.00,"count":209,"preSum":7075},{"ndv":1,"upper":37.00,"lower":37.00,"count":181,"preSum":7284},{"ndv":1,"upper":38.00,"lower":38.00,"count":225,"preSum":7465},{"ndv":1,"upper":39.00,"lower":39.00,"count":200,"preSum":7690},{"ndv":1,"upper":40.00,"lower":40.00,"count":175,"preSum":7890},{"ndv":1,"upper":41.00,"lower":41.00,"count":203,"preSum":8065},{"ndv":1,"upper":42.00,"lower":42.00,"count":208,"preSum":8268},{"ndv":1,"upper":43.00,"lower":43.00,"count":184,"preSum":8476},{"ndv":1,"upper":44.00,"lower":44.00,"count":199,"preSum":8660},{"ndv":1,"upper":45.00,"lower":45.00,"count":173,"preSum":8859},{"ndv":1,"upper":46.00,"lower":46.00,"count":183,"preSum":9032},{"ndv":1,"upper":47.00,"lower":47.00,"count":171,"preSum":9215},{"ndv":1,"upper":48.00,"lower":48.00,"count":198,"preSum":9386},{"ndv":1,"upper":49.00,"lower":49.00,"count":206,"preSum":9584},{"ndv":1,"upper":50.00,"lower":50.00,"count":210,"preSum":9790}],"maxBucketSize":64,"type":"Double","sampleRate":0.09979044}
+lineitem.l_receiptdate.histogram:
+  {"buckets":[{"ndv":71,"upper":"1992-04-24","lower":"1992-01-14","count":158,"preSum":0},{"ndv":38,"upper":"1992-06-01","lower":"1992-04-25","count":159,"preSum":158},{"ndv":34,"upper":"1992-07-07","lower":"1992-06-03","count":160,"preSum":317},{"ndv":35,"upper":"1992-08-12","lower":"1992-07-08","count":159,"preSum":477},{"ndv":42,"upper":"1992-09-24","lower":"1992-08-14","count":158,"preSum":636},{"ndv":33,"upper":"1992-10-27","lower":"1992-09-25","count":161,"preSum":794},{"ndv":33,"upper":"1992-11-29","lower":"1992-10-28","count":158,"preSum":955},{"ndv":37,"upper":"1993-01-05","lower":"1992-11-30","count":160,"preSum":1113},{"ndv":36,"upper":"1993-02-10","lower":"1993-01-06","count":157,"preSum":1273},{"ndv":32,"upper":"1993-03-17","lower":"1993-02-12","count":161,"preSum":1430},{"ndv":33,"upper":"1993-04-19","lower":"1993-03-18","count":161,"preSum":1591},{"ndv":39,"upper":"1993-05-29","lower":"1993-04-20","count":159,"preSum":1752},{"ndv":36,"upper":"1993-07-05","lower":"1993-05-30","count":157,"preSum":1911},{"ndv":39,"upper":"1993-08-14","lower":"1993-07-06","count":164,"preSum":2068},{"ndv":36,"upper":"1993-09-20","lower":"1993-08-15","count":159,"preSum":2232},{"ndv":39,"upper":"1993-10-29","lower":"1993-09-21","count":158,"preSum":2391},{"ndv":37,"upper":"1993-12-05","lower":"1993-10-30","count":157,"preSum":2549},{"ndv":34,"upper":"1994-01-08","lower":"1993-12-06","count":157,"preSum":2706},{"ndv":36,"upper":"1994-02-13","lower":"1994-01-09","count":157,"preSum":2863},{"ndv":37,"upper":"1994-03-23","lower":"1994-02-14","count":158,"preSum":3020},{"ndv":37,"upper":"1994-04-29","lower":"1994-03-24","count":159,"preSum":3178},{"ndv":40,"upper":"1994-06-08","lower":"1994-04-30","count":157,"preSum":3337},{"ndv":45,"upper":"1994-07-23","lower":"1994-06-09","count":160,"preSum":3494},{"ndv":36,"upper":"1994-08-29","lower":"1994-07-24","count":158,"preSum":3654},{"ndv":42,"upper":"1994-10-11","lower":"1994-08-30","count":157,"preSum":3812},{"ndv":37,"upper":"1994-11-18","lower":"1994-10-12","count":157,"preSum":3969},{"ndv":41,"upper":"1994-12-29","lower":"1994-11-19","count":162,"preSum":4126},{"ndv":36,"upper":"1995-02-04","lower":"1994-12-30","count":160,"preSum":4288},{"ndv":41,"upper":"1995-03-18","lower":"1995-02-05","count":160,"preSum":4448},{"ndv":39,"upper":"1995-04-26","lower":"1995-03-19","count":158,"preSum":4608},{"ndv":38,"upper":"1995-06-04","lower":"1995-04-27","count":158,"preSum":4766},{"ndv":42,"upper":"1995-07-16","lower":"1995-06-05","count":159,"preSum":4924},{"ndv":36,"upper":"1995-08-22","lower":"1995-07-17","count":161,"preSum":5083},{"ndv":37,"upper":"1995-09-28","lower":"1995-08-23","count":161,"preSum":5244},{"ndv":35,"upper":"1995-11-02","lower":"1995-09-29","count":157,"preSum":5405},{"ndv":37,"upper":"1995-12-09","lower":"1995-11-03","count":159,"preSum":5562},{"ndv":34,"upper":"1996-01-12","lower":"1995-12-10","count":159,"preSum":5721},{"ndv":41,"upper":"1996-02-23","lower":"1996-01-13","count":157,"preSum":5880},{"ndv":39,"upper":"1996-04-02","lower":"1996-02-24","count":158,"preSum":6037},{"ndv":38,"upper":"1996-05-11","lower":"1996-04-03","count":162,"preSum":6195},{"ndv":43,"upper":"1996-06-24","lower":"1996-05-12","count":157,"preSum":6357},{"ndv":40,"upper":"1996-08-03","lower":"1996-06-25","count":159,"preSum":6514},{"ndv":38,"upper":"1996-09-11","lower":"1996-08-04","count":160,"preSum":6673},{"ndv":43,"upper":"1996-10-25","lower":"1996-09-12","count":157,"preSum":6833},{"ndv":29,"upper":"1996-11-23","lower":"1996-10-26","count":157,"preSum":6990},{"ndv":39,"upper":"1997-01-02","lower":"1996-11-24","count":159,"preSum":7147},{"ndv":39,"upper":"1997-02-10","lower":"1997-01-03","count":157,"preSum":7306},{"ndv":41,"upper":"1997-03-24","lower":"1997-02-11","count":159,"preSum":7463},{"ndv":37,"upper":"1997-05-01","lower":"1997-03-25","count":157,"preSum":7622},{"ndv":41,"upper":"1997-06-12","lower":"1997-05-02","count":166,"preSum":7779},{"ndv":43,"upper":"1997-07-25","lower":"1997-06-13","count":158,"preSum":7945},{"ndv":36,"upper":"1997-08-30","lower":"1997-07-26","count":157,"preSum":8103},{"ndv":33,"upper":"1997-10-02","lower":"1997-08-31","count":158,"preSum":8260},{"ndv":35,"upper":"1997-11-06","lower":"1997-10-03","count":162,"preSum":8418},{"ndv":39,"upper":"1997-12-15","lower":"1997-11-07","count":161,"preSum":8580},{"ndv":36,"upper":"1998-01-21","lower":"1997-12-16","count":159,"preSum":8741},{"ndv":40,"upper":"1998-03-03","lower":"1998-01-22","count":160,"preSum":8900},{"ndv":40,"upper":"1998-04-12","lower":"1998-03-04","count":160,"preSum":9060},{"ndv":38,"upper":"1998-05-20","lower":"1998-04-13","count":159,"preSum":9220},{"ndv":35,"upper":"1998-06-24","lower":"1998-05-21","count":157,"preSum":9379},{"ndv":40,"upper":"1998-08-03","lower":"1998-06-25","count":158,"preSum":9536},{"ndv":41,"upper":"1998-09-14","lower":"1998-08-04","count":157,"preSum":9694},{"ndv":68,"upper":"1998-12-22","lower":"1998-09-15","count":149,"preSum":9851}],"maxBucketSize":64,"type":"Date","sampleRate":0.09979044}
+lineitem.l_returnflag.histogram:
+  {"buckets":[{"ndv":1,"upper":"A","lower":"A","count":2482,"preSum":0},{"ndv":1,"upper":"N","lower":"N","count":5026,"preSum":2482},{"ndv":1,"upper":"R","lower":"R","count":2492,"preSum":7508}],"maxBucketSize":64,"type":"String","sampleRate":0.09979044}
+lineitem.l_shipdate.histogram:
+  {"buckets":[{"ndv":64,"upper":"1992-03-31","lower":"1992-01-07","count":158,"preSum":0},{"ndv":38,"upper":"1992-05-08","lower":"1992-04-01","count":158,"preSum":158},{"ndv":37,"upper":"1992-06-18","lower":"1992-05-09","count":157,"preSum":316},{"ndv":34,"upper":"1992-07-22","lower":"1992-06-19","count":162,"preSum":473},{"ndv":44,"upper":"1992-09-06","lower":"1992-07-23","count":164,"preSum":635},{"ndv":36,"upper":"1992-10-12","lower":"1992-09-07","count":159,"preSum":799},{"ndv":31,"upper":"1992-11-13","lower":"1992-10-13","count":157,"preSum":958},{"ndv":35,"upper":"1992-12-18","lower":"1992-11-14","count":158,"preSum":1115},{"ndv":38,"upper":"1993-01-28","lower":"1992-12-19","count":159,"preSum":1273},{"ndv":37,"upper":"1993-03-06","lower":"1993-01-29","count":157,"preSum":1432},{"ndv":40,"upper":"1993-04-15","lower":"1993-03-07","count":158,"preSum":1589},{"ndv":36,"upper":"1993-05-22","lower":"1993-04-16","count":159,"preSum":1747},{"ndv":40,"upper":"1993-07-02","lower":"1993-05-23","count":157,"preSum":1906},{"ndv":34,"upper":"1993-08-05","lower":"1993-07-03","count":158,"preSum":2063},{"ndv":39,"upper":"1993-09-14","lower":"1993-08-06","count":161,"preSum":2221},{"ndv":35,"upper":"1993-10-20","lower":"1993-09-15","count":157,"preSum":2382},{"ndv":34,"upper":"1993-11-24","lower":"1993-10-21","count":157,"preSum":2539},{"ndv":37,"upper":"1994-01-01","lower":"1993-11-25","count":157,"preSum":2696},{"ndv":39,"upper":"1994-02-09","lower":"1994-01-02","count":158,"preSum":2853},{"ndv":36,"upper":"1994-03-17","lower":"1994-02-10","count":162,"preSum":3011},{"ndv":35,"upper":"1994-04-21","lower":"1994-03-18","count":157,"preSum":3173},{"ndv":35,"upper":"1994-05-26","lower":"1994-04-22","count":158,"preSum":3330},{"ndv":38,"upper":"1994-07-06","lower":"1994-05-27","count":158,"preSum":3488},{"ndv":37,"upper":"1994-08-13","lower":"1994-07-07","count":158,"preSum":3646},{"ndv":36,"upper":"1994-09-19","lower":"1994-08-14","count":157,"preSum":3804},{"ndv":40,"upper":"1994-10-30","lower":"1994-09-20","count":158,"preSum":3961},{"ndv":40,"upper":"1994-12-10","lower":"1994-10-31","count":159,"preSum":4119},{"ndv":33,"upper":"1995-01-14","lower":"1994-12-11","count":157,"preSum":4278},{"ndv":38,"upper":"1995-02-22","lower":"1995-01-15","count":159,"preSum":4435},{"ndv":37,"upper":"1995-04-01","lower":"1995-02-23","count":157,"preSum":4594},{"ndv":37,"upper":"1995-05-09","lower":"1995-04-02","count":162,"preSum":4751},{"ndv":40,"upper":"1995-06-18","lower":"1995-05-10","count":158,"preSum":4913},{"ndv":41,"upper":"1995-07-29","lower":"1995-06-19","count":157,"preSum":5071},{"ndv":37,"upper":"1995-09-05","lower":"1995-07-30","count":158,"preSum":5228},{"ndv":41,"upper":"1995-10-16","lower":"1995-09-06","count":163,"preSum":5386},{"ndv":37,"upper":"1995-11-24","lower":"1995-10-17","count":160,"preSum":5549},{"ndv":36,"upper":"1995-12-30","lower":"1995-11-25","count":161,"preSum":5709},{"ndv":38,"upper":"1996-02-07","lower":"1995-12-31","count":157,"preSum":5870},{"ndv":39,"upper":"1996-03-17","lower":"1996-02-08","count":158,"preSum":6027},{"ndv":36,"upper":"1996-04-23","lower":"1996-03-18","count":160,"preSum":6185},{"ndv":33,"upper":"1996-05-26","lower":"1996-04-24","count":157,"preSum":6345},{"ndv":41,"upper":"1996-07-07","lower":"1996-05-27","count":160,"preSum":6502},{"ndv":39,"upper":"1996-08-16","lower":"1996-07-08","count":159,"preSum":6662},{"ndv":39,"upper":"1996-09-24","lower":"1996-08-17","count":157,"preSum":6821},{"ndv":41,"upper":"1996-11-05","lower":"1996-09-25","count":164,"preSum":6978},{"ndv":36,"upper":"1996-12-12","lower":"1996-11-06","count":160,"preSum":7142},{"ndv":38,"upper":"1997-01-19","lower":"1996-12-13","count":159,"preSum":7302},{"ndv":38,"upper":"1997-02-28","lower":"1997-01-20","count":158,"preSum":7461},{"ndv":39,"upper":"1997-04-09","lower":"1997-03-01","count":157,"preSum":7619},{"ndv":39,"upper":"1997-05-18","lower":"1997-04-10","count":157,"preSum":7776},{"ndv":41,"upper":"1997-06-28","lower":"1997-05-19","count":163,"preSum":7933},{"ndv":38,"upper":"1997-08-06","lower":"1997-06-30","count":159,"preSum":8096},{"ndv":39,"upper":"1997-09-15","lower":"1997-08-07","count":159,"preSum":8255},{"ndv":37,"upper":"1997-10-22","lower":"1997-09-16","count":158,"preSum":8414},{"ndv":35,"upper":"1997-11-26","lower":"1997-10-23","count":158,"preSum":8572},{"ndv":39,"upper":"1998-01-04","lower":"1997-11-27","count":157,"preSum":8730},{"ndv":42,"upper":"1998-02-16","lower":"1998-01-05","count":161,"preSum":8887},{"ndv":42,"upper":"1998-03-30","lower":"1998-02-17","count":162,"preSum":9048},{"ndv":37,"upper":"1998-05-06","lower":"1998-03-31","count":164,"preSum":9210},{"ndv":39,"upper":"1998-06-14","lower":"1998-05-07","count":161,"preSum":9374},{"ndv":35,"upper":"1998-07-19","lower":"1998-06-15","count":157,"preSum":9535},{"ndv":41,"upper":"1998-09-01","lower":"1998-07-20","count":159,"preSum":9692},{"ndv":70,"upper":"1998-11-25","lower":"1998-09-02","count":149,"preSum":9851}],"maxBucketSize":64,"type":"Date","sampleRate":0.09979044}
+lineitem.l_shipinstruct.histogram:
+  {"buckets":[{"ndv":1,"upper":"COLLECT COD","lower":"COLLECT COD","count":2585,"preSum":0},{"ndv":1,"upper":"DELIVER IN PERSON","lower":"DELIVER IN PERSON","count":2537,"preSum":2585},{"ndv":1,"upper":"NONE","lower":"NONE","count":2423,"preSum":5122},{"ndv":1,"upper":"TAKE BACK RETURN","lower":"TAKE BACK RETURN","count":2455,"preSum":7545}],"maxBucketSize":64,"type":"String","sampleRate":0.09979044}
+lineitem.l_shipmode.histogram:
+  {"buckets":[{"ndv":1,"upper":"AIR","lower":"AIR","count":1442,"preSum":0},{"ndv":1,"upper":"FOB","lower":"FOB","count":1493,"preSum":1442},{"ndv":1,"upper":"MAIL","lower":"MAIL","count":1419,"preSum":2935},{"ndv":1,"upper":"RAIL","lower":"RAIL","count":1421,"preSum":4354},{"ndv":1,"upper":"REG AIR","lower":"REG AIR","count":1464,"preSum":5775},{"ndv":1,"upper":"SHIP","lower":"SHIP","count":1386,"preSum":7239},{"ndv":1,"upper":"TRUCK","lower":"TRUCK","count":1375,"preSum":8625}],"maxBucketSize":64,"type":"String","sampleRate":0.09979044}
+lineitem.l_suppkey.histogram:
+  {"buckets":[{"ndv":155,"upper":15353,"lower":386,"count":157,"preSum":0},{"ndv":156,"upper":32123,"lower":15356,"count":157,"preSum":157},{"ndv":157,"upper":46976,"lower":32154,"count":157,"preSum":314},{"ndv":157,"upper":61788,"lower":47146,"count":157,"preSum":471},{"ndv":157,"upper":78598,"lower":62017,"count":157,"preSum":628},{"ndv":157,"upper":91425,"lower":78600,"count":157,"preSum":785},{"ndv":157,"upper":106321,"lower":91596,"count":157,"preSum":942},{"ndv":156,"upper":123351,"lower":106364,"count":157,"preSum":1099},{"ndv":154,"upper":138443,"lower":123352,"count":157,"preSum":1256},{"ndv":157,"upper":153230,"lower":138471,"count":157,"preSum":1413},{"ndv":156,"upper":167898,"lower":153388,"count":157,"preSum":1570},{"ndv":157,"upper":182365,"lower":168053,"count":157,"preSum":1727},{"ndv":157,"upper":196151,"lower":182476,"count":157,"preSum":1884},{"ndv":155,"upper":211895,"lower":196173,"count":157,"preSum":2041},{"ndv":156,"upper":228619,"lower":212007,"count":157,"preSum":2198},{"ndv":157,"upper":245433,"lower":228674,"count":157,"preSum":2355},{"ndv":157,"upper":260423,"lower":245544,"count":157,"preSum":2512},{"ndv":157,"upper":277201,"lower":260509,"count":157,"preSum":2669},{"ndv":157,"upper":290360,"lower":277251,"count":157,"preSum":2826},{"ndv":157,"upper":307392,"lower":290423,"count":157,"preSum":2983},{"ndv":156,"upper":324096,"lower":307481,"count":157,"preSum":3140},{"ndv":156,"upper":339114,"lower":324233,"count":157,"preSum":3297},{"ndv":156,"upper":356541,"lower":339149,"count":157,"preSum":3454},{"ndv":157,"upper":372056,"lower":356564,"count":157,"preSum":3611},{"ndv":157,"upper":387152,"lower":372100,"count":157,"preSum":3768},{"ndv":155,"upper":402966,"lower":387176,"count":157,"preSum":3925},{"ndv":156,"upper":418683,"lower":403021,"count":157,"preSum":4082},{"ndv":157,"upper":435003,"lower":418740,"count":157,"preSum":4239},{"ndv":157,"upper":450755,"lower":435098,"count":157,"preSum":4396},{"ndv":157,"upper":466965,"lower":450795,"count":157,"preSum":4553},{"ndv":156,"upper":483011,"lower":467008,"count":157,"preSum":4710},{"ndv":157,"upper":500558,"lower":483100,"count":157,"preSum":4867},{"ndv":154,"upper":515949,"lower":500559,"count":157,"preSum":5024},{"ndv":157,"upper":531105,"lower":516059,"count":157,"preSum":5181},{"ndv":157,"upper":547699,"lower":531231,"count":157,"preSum":5338},{"ndv":157,"upper":563876,"lower":547863,"count":157,"preSum":5495},{"ndv":157,"upper":581792,"lower":563884,"count":157,"preSum":5652},{"ndv":156,"upper":597655,"lower":581913,"count":157,"preSum":5809},{"ndv":156,"upper":615257,"lower":597789,"count":157,"preSum":5966},{"ndv":155,"upper":631308,"lower":615444,"count":157,"preSum":6123},{"ndv":155,"upper":648074,"lower":631326,"count":157,"preSum":6280},{"ndv":156,"upper":663672,"lower":648089,"count":157,"preSum":6437},{"ndv":156,"upper":678766,"lower":663735,"count":157,"preSum":6594},{"ndv":155,"upper":695690,"lower":678803,"count":157,"preSum":6751},{"ndv":157,"upper":709298,"lower":695912,"count":158,"preSum":6908},{"ndv":156,"upper":723868,"lower":709300,"count":157,"preSum":7066},{"ndv":154,"upper":738821,"lower":723872,"count":157,"preSum":7223},{"ndv":156,"upper":752838,"lower":738891,"count":157,"preSum":7380},{"ndv":155,"upper":765762,"lower":752844,"count":157,"preSum":7537},{"ndv":157,"upper":782485,"lower":765838,"count":157,"preSum":7694},{"ndv":157,"upper":799017,"lower":782503,"count":157,"preSum":7851},{"ndv":157,"upper":812989,"lower":799066,"count":157,"preSum":8008},{"ndv":155,"upper":830449,"lower":813068,"count":157,"preSum":8165},{"ndv":154,"upper":845187,"lower":830941,"count":157,"preSum":8322},{"ndv":157,"upper":860949,"lower":845363,"count":157,"preSum":8479},{"ndv":157,"upper":877032,"lower":861050,"count":157,"preSum":8636},{"ndv":157,"upper":895506,"lower":877111,"count":157,"preSum":8793},{"ndv":154,"upper":910400,"lower":895510,"count":157,"preSum":8950},{"ndv":156,"upper":924014,"lower":910401,"count":157,"preSum":9107},{"ndv":157,"upper":942237,"lower":924084,"count":157,"preSum":9264},{"ndv":157,"upper":958190,"lower":942264,"count":157,"preSum":9421},{"ndv":156,"upper":973972,"lower":958215,"count":157,"preSum":9578},{"ndv":156,"upper":991029,"lower":973986,"count":157,"preSum":9735},{"ndv":107,"upper":999945,"lower":991043,"count":108,"preSum":9892}],"maxBucketSize":64,"type":"Int","sampleRate":0.09979044}
+lineitem.l_tax.histogram:
+  {"buckets":[{"ndv":1,"upper":0.00,"lower":0.00,"count":1093,"preSum":0},{"ndv":1,"upper":0.01,"lower":0.01,"count":1079,"preSum":1093},{"ndv":1,"upper":0.02,"lower":0.02,"count":1133,"preSum":2172},{"ndv":1,"upper":0.03,"lower":0.03,"count":1080,"preSum":3305},{"ndv":1,"upper":0.04,"lower":0.04,"count":1108,"preSum":4385},{"ndv":1,"upper":0.05,"lower":0.05,"count":1146,"preSum":5493},{"ndv":1,"upper":0.06,"lower":0.06,"count":1136,"preSum":6639},{"ndv":1,"upper":0.07,"lower":0.07,"count":1081,"preSum":7775},{"ndv":1,"upper":0.08,"lower":0.08,"count":1144,"preSum":8856}],"maxBucketSize":64,"type":"Double","sampleRate":0.09979044}
+nation.n_comment.histogram:
+  {"buckets":[{"ndv":4,"upper":" slyly express asymp","lower":" haggle. carefully f","count":4,"preSum":0},{"ndv":4,"upper":"eas hang ironic, sil","lower":"al foxes promise sly","count":4,"preSum":4},{"ndv":4,"upper":"l platelets. regular","lower":"efully alongside of ","count":4,"preSum":8},{"ndv":4,"upper":"refully final reques","lower":"nic deposits boost a","count":4,"preSum":12},{"ndv":4,"upper":"ts. silent requests ","lower":"rns. blithely bold c","count":4,"preSum":16},{"ndv":4,"upper":"y alongside of the p","lower":"ular asymptotes are ","count":4,"preSum":20},{"ndv":1,"upper":"y final packages. sl","lower":"y final packages. sl","count":1,"preSum":24}],"maxBucketSize":8,"type":"String","sampleRate":1.0}
+nation.n_name.histogram:
+  {"buckets":[{"ndv":4,"upper":"CANADA","lower":"ALGERIA","count":4,"preSum":0},{"ndv":4,"upper":"FRANCE","lower":"CHINA","count":4,"preSum":4},{"ndv":4,"upper":"IRAN","lower":"GERMANY","count":4,"preSum":8},{"ndv":4,"upper":"KENYA","lower":"IRAQ","count":4,"preSum":12},{"ndv":4,"upper":"ROMANIA","lower":"MOROCCO","count":4,"preSum":16},{"ndv":4,"upper":"UNITED STATES","lower":"RUSSIA","count":4,"preSum":20},{"ndv":1,"upper":"VIETNAM","lower":"VIETNAM","count":1,"preSum":24}],"maxBucketSize":8,"type":"String","sampleRate":1.0}
+nation.n_nationkey.histogram:
+  {"buckets":[{"ndv":4,"upper":3,"lower":0,"count":4,"preSum":0},{"ndv":4,"upper":7,"lower":4,"count":4,"preSum":4},{"ndv":4,"upper":11,"lower":8,"count":4,"preSum":8},{"ndv":4,"upper":15,"lower":12,"count":4,"preSum":12},{"ndv":4,"upper":19,"lower":16,"count":4,"preSum":16},{"ndv":4,"upper":23,"lower":20,"count":4,"preSum":20},{"ndv":1,"upper":24,"lower":24,"count":1,"preSum":24}],"maxBucketSize":8,"type":"Int","sampleRate":1.0}
+nation.n_regionkey.histogram:
+  {"buckets":[{"ndv":1,"upper":0,"lower":0,"count":5,"preSum":0},{"ndv":1,"upper":1,"lower":1,"count":5,"preSum":5},{"ndv":1,"upper":2,"lower":2,"count":5,"preSum":10},{"ndv":1,"upper":3,"lower":3,"count":5,"preSum":15},{"ndv":1,"upper":4,"lower":4,"count":5,"preSum":20}],"maxBucketSize":8,"type":"Int","sampleRate":1.0}
+orders.o_clerk.histogram:
+  {"buckets":[{"ndv":149,"upper":"Clerk#000001343","lower":"Clerk#000000009","count":157,"preSum":0},{"ndv":149,"upper":"Clerk#000002988","lower":"Clerk#000001345","count":157,"preSum":157},{"ndv":150,"upper":"Clerk#000004437","lower":"Clerk#000002996","count":157,"preSum":314},{"ndv":149,"upper":"Clerk#000005976","lower":"Clerk#000004443","count":157,"preSum":471},{"ndv":151,"upper":"Clerk#000007633","lower":"Clerk#000005988","count":157,"preSum":628},{"ndv":153,"upper":"Clerk#000009109","lower":"Clerk#000007635","count":157,"preSum":785},{"ndv":144,"upper":"Clerk#000010665","lower":"Clerk#000009139","count":158,"preSum":942},{"ndv":152,"upper":"Clerk#000012302","lower":"Clerk#000010678","count":157,"preSum":1100},{"ndv":148,"upper":"Clerk#000013896","lower":"Clerk#000012303","count":157,"preSum":1257},{"ndv":149,"upper":"Clerk#000015375","lower":"Clerk#000013913","count":157,"preSum":1414},{"ndv":151,"upper":"Clerk#000017000","lower":"Clerk#000015388","count":157,"preSum":1571},{"ndv":148,"upper":"Clerk#000018390","lower":"Clerk#000017006","count":157,"preSum":1728},{"ndv":149,"upper":"Clerk#000019995","lower":"Clerk#000018393","count":157,"preSum":1885},{"ndv":151,"upper":"Clerk#000021486","lower":"Clerk#000020017","count":157,"preSum":2042},{"ndv":149,"upper":"Clerk#000023002","lower":"Clerk#000021489","count":157,"preSum":2199},{"ndv":146,"upper":"Clerk#000024684","lower":"Clerk#000023004","count":157,"preSum":2356},{"ndv":150,"upper":"Clerk#000026382","lower":"Clerk#000024713","count":157,"preSum":2513},{"ndv":146,"upper":"Clerk#000027891","lower":"Clerk#000026390","count":157,"preSum":2670},{"ndv":149,"upper":"Clerk#000029435","lower":"Clerk#000027932","count":157,"preSum":2827},{"ndv":146,"upper":"Clerk#000030793","lower":"Clerk#000029441","count":157,"preSum":2984},{"ndv":152,"upper":"Clerk#000032331","lower":"Clerk#000030797","count":157,"preSum":3141},{"ndv":150,"upper":"Clerk#000034049","lower":"Clerk#000032334","count":157,"preSum":3298},{"ndv":148,"upper":"Clerk#000035282","lower":"Clerk#000034055","count":157,"preSum":3455},{"ndv":145,"upper":"Clerk#000036844","lower":"Clerk#000035288","count":157,"preSum":3612},{"ndv":146,"upper":"Clerk#000038329","lower":"Clerk#000036897","count":157,"preSum":3769},{"ndv":152,"upper":"Clerk#000039887","lower":"Clerk#000038336","count":157,"preSum":3926},{"ndv":153,"upper":"Clerk#000041478","lower":"Clerk#000039905","count":157,"preSum":4083},{"ndv":151,"upper":"Clerk#000043066","lower":"Clerk#000041504","count":157,"preSum":4240},{"ndv":151,"upper":"Clerk#000044637","lower":"Clerk#000043089","count":159,"preSum":4397},{"ndv":144,"upper":"Clerk#000046123","lower":"Clerk#000044639","count":157,"preSum":4556},{"ndv":149,"upper":"Clerk#000047656","lower":"Clerk#000046134","count":157,"preSum":4713},{"ndv":149,"upper":"Clerk#000049273","lower":"Clerk#000047659","count":157,"preSum":4870},{"ndv":147,"upper":"Clerk#000050846","lower":"Clerk#000049278","count":157,"preSum":5027},{"ndv":146,"upper":"Clerk#000052441","lower":"Clerk#000050851","count":157,"preSum":5184},{"ndv":155,"upper":"Clerk#000054093","lower":"Clerk#000052447","count":157,"preSum":5341},{"ndv":151,"upper":"Clerk#000055572","lower":"Clerk#000054098","count":157,"preSum":5498},{"ndv":146,"upper":"Clerk#000057130","lower":"Clerk#000055605","count":157,"preSum":5655},{"ndv":151,"upper":"Clerk#000058612","lower":"Clerk#000057142","count":157,"preSum":5812},{"ndv":149,"upper":"Clerk#000060309","lower":"Clerk#000058627","count":157,"preSum":5969},{"ndv":147,"upper":"Clerk#000061958","lower":"Clerk#000060319","count":157,"preSum":6126},{"ndv":150,"upper":"Clerk#000063422","lower":"Clerk#000061964","count":157,"preSum":6283},{"ndv":150,"upper":"Clerk#000065032","lower":"Clerk#000063429","count":157,"preSum":6440},{"ndv":149,"upper":"Clerk#000066536","lower":"Clerk#000065059","count":157,"preSum":6597},{"ndv":152,"upper":"Clerk#000068410","lower":"Clerk#000066552","count":157,"preSum":6754},{"ndv":152,"upper":"Clerk#000070179","lower":"Clerk#000068429","count":157,"preSum":6911},{"ndv":150,"upper":"Clerk#000071939","lower":"Clerk#000070181","count":157,"preSum":7068},{"ndv":151,"upper":"Clerk#000073531","lower":"Clerk#000071958","count":157,"preSum":7225},{"ndv":150,"upper":"Clerk#000075040","lower":"Clerk#000073541","count":157,"preSum":7382},{"ndv":151,"upper":"Clerk#000076731","lower":"Clerk#000075041","count":157,"preSum":7539},{"ndv":148,"upper":"Clerk#000078231","lower":"Clerk#000076734","count":157,"preSum":7696},{"ndv":149,"upper":"Clerk#000079884","lower":"Clerk#000078250","count":157,"preSum":7853},{"ndv":149,"upper":"Clerk#000081549","lower":"Clerk#000079891","count":157,"preSum":8010},{"ndv":148,"upper":"Clerk#000083038","lower":"Clerk#000081552","count":157,"preSum":8167},{"ndv":152,"upper":"Clerk#000084744","lower":"Clerk#000083060","count":157,"preSum":8324},{"ndv":150,"upper":"Clerk#000086091","lower":"Clerk#000084764","count":157,"preSum":8481},{"ndv":152,"upper":"Clerk#000087906","lower":"Clerk#000086092","count":157,"preSum":8638},{"ndv":155,"upper":"Clerk#000089500","lower":"Clerk#000087916","count":157,"preSum":8795},{"ndv":144,"upper":"Clerk#000091208","lower":"Clerk#000089505","count":157,"preSum":8952},{"ndv":150,"upper":"Clerk#000092631","lower":"Clerk#000091216","count":157,"preSum":9109},{"ndv":154,"upper":"Clerk#000094225","lower":"Clerk#000092641","count":157,"preSum":9266},{"ndv":148,"upper":"Clerk#000095812","lower":"Clerk#000094227","count":157,"preSum":9423},{"ndv":147,"upper":"Clerk#000097306","lower":"Clerk#000095822","count":158,"preSum":9580},{"ndv":151,"upper":"Clerk#000098972","lower":"Clerk#000097310","count":157,"preSum":9738},{"ndv":97,"upper":"Clerk#000099989","lower":"Clerk#000098982","count":105,"preSum":9895}],"maxBucketSize":64,"type":"String","sampleRate":0.09921718}
+orders.o_comment.histogram:
+  {"buckets":[{"ndv":144,"upper":" asymptotes boost bl","lower":" about the always da","count":157,"preSum":0},{"ndv":143,"upper":" carefully even theo","lower":" asymptotes detect q","count":157,"preSum":157},{"ndv":143,"upper":" excuses. blithely i","lower":" carefully express a","count":157,"preSum":314},{"ndv":142,"upper":" furiously thinly re","lower":" excuses. slow depos","count":157,"preSum":471},{"ndv":146,"upper":" nag thinly furiousl","lower":" furiously unusual i","count":157,"preSum":628},{"ndv":149,"upper":" regular ideas. slyl","lower":" nag. ironic, even p","count":157,"preSum":785},{"ndv":128,"upper":" slyly pending accou","lower":" regular instruction","count":157,"preSum":942},{"ndv":142,"upper":" thrash furiously ar","lower":" slyly pending depos","count":157,"preSum":1099},{"ndv":153,"upper":". even pinto beans a","lower":" through the deposit","count":157,"preSum":1256},{"ndv":140,"upper":"accounts boost aroun","lower":". even, final orbits","count":157,"preSum":1413},{"ndv":150,"upper":"ages. slyly final fo","lower":"accounts cajole alon","count":157,"preSum":1570},{"ndv":152,"upper":"al theodolites affix","lower":"ages. slyly final pi","count":157,"preSum":1727},{"ndv":155,"upper":"arefully express pin","lower":"al theodolites cajol","count":157,"preSum":1884},{"ndv":148,"upper":"blithely furiously p","lower":"arefully express req","count":157,"preSum":2041},{"ndv":146,"upper":"carefully bold foxes","lower":"blithely ironic excu","count":157,"preSum":2198},{"ndv":150,"upper":"ckages. even platele","lower":"carefully carefully ","count":157,"preSum":2355},{"ndv":153,"upper":"d blithely even acco","lower":"ckages. even, even d","count":157,"preSum":2512},{"ndv":150,"upper":"dolites boost after ","lower":"d carefully through ","count":157,"preSum":2669},{"ndv":149,"upper":"e quickly regular ac","lower":"dolites boost. instr","count":157,"preSum":2826},{"ndv":151,"upper":"ect carefully. stea","lower":"e quickly slyly unus","count":157,"preSum":2983},{"ndv":153,"upper":"ely about the pendin","lower":"ect quickly. furious","count":157,"preSum":3140},{"ndv":153,"upper":"ep furiously unusual","lower":"ely about the quickl","count":157,"preSum":3297},{"ndv":154,"upper":"es haggle slyly bold","lower":"ep furiously. slyly ","count":157,"preSum":3454},{"ndv":150,"upper":"etect. unusual ideas","lower":"es haggle. busy, fin","count":157,"preSum":3611},{"ndv":152,"upper":"final deposits. quic","lower":"etimes regular asymp","count":157,"preSum":3768},{"ndv":149,"upper":"furiously alongside ","lower":"final deposits. slyl","count":157,"preSum":3925},{"ndv":146,"upper":"ges sleep across the","lower":"furiously bold braid","count":157,"preSum":4082},{"ndv":150,"upper":"he accounts sleep sl","lower":"ges sleep against th","count":157,"preSum":4239},{"ndv":148,"upper":"hins cajole blithely","lower":"he accounts. regula","count":157,"preSum":4396},{"ndv":156,"upper":"ideas wake: blithely","lower":"hins haggle above th","count":157,"preSum":4553},{"ndv":153,"upper":"instructions across ","lower":"ideas-- unusual asym","count":157,"preSum":4710},{"ndv":149,"upper":"ironic, unusual pint","lower":"instructions against","count":157,"preSum":4867},{"ndv":154,"upper":"kages may detect car","lower":"ironically ironic as","count":157,"preSum":5024},{"ndv":153,"upper":"l requests wake blit","lower":"kages nag across the","count":157,"preSum":5181},{"ndv":153,"upper":"le slyly on the requ","lower":"l theodolites after ","count":157,"preSum":5338},{"ndv":152,"upper":"lly ironic, regular ","lower":"le sometimes unusual","count":157,"preSum":5495},{"ndv":146,"upper":"ly even foxes. caref","lower":"lly pending asymptot","count":157,"preSum":5652},{"ndv":126,"upper":"ly slyly regular dep","lower":"ly even instructions","count":157,"preSum":5809},{"ndv":145,"upper":"nag blithely furiou","lower":"ly slyly regular ins","count":157,"preSum":5966},{"ndv":153,"upper":"nic deposits. boldly","lower":"nag blithely slyly t","count":157,"preSum":6123},{"ndv":154,"upper":"nts after the furiou","lower":"nic deposits. furiou","count":157,"preSum":6280},{"ndv":154,"upper":"old, bold pinto bean","lower":"nts along the carefu","count":157,"preSum":6437},{"ndv":149,"upper":"osits integrate blit","lower":"oldly regular reques","count":157,"preSum":6594},{"ndv":149,"upper":"ously. blithely spec","lower":"osits sleep about th","count":157,"preSum":6751},{"ndv":144,"upper":"pending packages amo","lower":"ously. final, pendin","count":157,"preSum":6908},{"ndv":152,"upper":"quests. ironic accou","lower":"pending packages hag","count":157,"preSum":7065},{"ndv":153,"upper":"re blithely. boldly ","lower":"quests. ironic packa","count":157,"preSum":7222},{"ndv":146,"upper":"requests wake furiou","lower":"re bravely furiously","count":157,"preSum":7379},{"ndv":150,"upper":"ronic, final package","lower":"requests! ironic Tir","count":157,"preSum":7536},{"ndv":152,"upper":"s cajole. instructio","lower":"ronic, regular patte","count":157,"preSum":7693},{"ndv":155,"upper":"s! dependencies use ","lower":"s carefully. ironic,","count":157,"preSum":7850},{"ndv":148,"upper":"silent deposits. qui","lower":"s! ironic, express n","count":157,"preSum":8007},{"ndv":146,"upper":"slyly regular reques","lower":"silent excuses sleep","count":157,"preSum":8164},{"ndv":151,"upper":"sual asymptotes are ","lower":"slyly regular theodo","count":157,"preSum":8321},{"ndv":152,"upper":"the blithely regular","lower":"sual deposits nag ca","count":158,"preSum":8478},{"ndv":140,"upper":"theodolites accordin","lower":"the blithely silent ","count":157,"preSum":8636},{"ndv":154,"upper":"ts haggle across the","lower":"theodolites across t","count":157,"preSum":8793},{"ndv":152,"upper":"uests breach pending","lower":"ts haggle blithely a","count":157,"preSum":8950},{"ndv":152,"upper":"ully carefully final","lower":"uests cajole careful","count":157,"preSum":9107},{"ndv":149,"upper":"us requests. careful","lower":"ully carefully ironi","count":157,"preSum":9264},{"ndv":151,"upper":"ven requests wake fl","lower":"use about the expres","count":157,"preSum":9421},{"ndv":152,"upper":"y carefully final ac","lower":"ven requests! carefu","count":157,"preSum":9578},{"ndv":137,"upper":"y special pinto bean","lower":"y carefully pending ","count":157,"preSum":9735},{"ndv":106,"upper":"zzle furiously-- car","lower":"y thin instructions ","count":108,"preSum":9892}],"maxBucketSize":64,"type":"String","sampleRate":0.09921718}
+orders.o_custkey.histogram:
+  {"buckets":[{"ndv":157,"upper":229774,"lower":487,"count":157,"preSum":0},{"ndv":157,"upper":474593,"lower":232457,"count":157,"preSum":157},{"ndv":157,"upper":735490,"lower":476407,"count":157,"preSum":314},{"ndv":157,"upper":953794,"lower":736277,"count":157,"preSum":471},{"ndv":157,"upper":1168123,"lower":953905,"count":157,"preSum":628},{"ndv":157,"upper":1386718,"lower":1169341,"count":157,"preSum":785},{"ndv":157,"upper":1640359,"lower":1387196,"count":157,"preSum":942},{"ndv":157,"upper":1838914,"lower":1642102,"count":157,"preSum":1099},{"ndv":157,"upper":2095450,"lower":1840540,"count":157,"preSum":1256},{"ndv":157,"upper":2333155,"lower":2097385,"count":157,"preSum":1413},{"ndv":157,"upper":2586340,"lower":2337400,"count":157,"preSum":1570},{"ndv":157,"upper":2830405,"lower":2588006,"count":157,"preSum":1727},{"ndv":157,"upper":3032927,"lower":2834017,"count":157,"preSum":1884},{"ndv":157,"upper":3253610,"lower":3033047,"count":157,"preSum":2041},{"ndv":157,"upper":3506830,"lower":3254716,"count":157,"preSum":2198},{"ndv":157,"upper":3728741,"lower":3512146,"count":157,"preSum":2355},{"ndv":157,"upper":3985255,"lower":3729370,"count":157,"preSum":2512},{"ndv":157,"upper":4249804,"lower":3986725,"count":157,"preSum":2669},{"ndv":157,"upper":4525132,"lower":4251142,"count":157,"preSum":2826},{"ndv":157,"upper":4734677,"lower":4526894,"count":157,"preSum":2983},{"ndv":157,"upper":4975765,"lower":4735193,"count":157,"preSum":3140},{"ndv":157,"upper":5211091,"lower":4976348,"count":157,"preSum":3297},{"ndv":157,"upper":5411194,"lower":5211938,"count":157,"preSum":3454},{"ndv":157,"upper":5679934,"lower":5411714,"count":157,"preSum":3611},{"ndv":157,"upper":5913118,"lower":5680984,"count":157,"preSum":3768},{"ndv":157,"upper":6130234,"lower":5915926,"count":157,"preSum":3925},{"ndv":157,"upper":6357439,"lower":6132893,"count":157,"preSum":4082},{"ndv":157,"upper":6582737,"lower":6360478,"count":157,"preSum":4239},{"ndv":157,"upper":6816932,"lower":6583748,"count":157,"preSum":4396},{"ndv":157,"upper":7056676,"lower":6817124,"count":157,"preSum":4553},{"ndv":157,"upper":7301456,"lower":7060714,"count":157,"preSum":4710},{"ndv":157,"upper":7527523,"lower":7304995,"count":157,"preSum":4867},{"ndv":157,"upper":7757740,"lower":7530536,"count":157,"preSum":5024},{"ndv":157,"upper":7977673,"lower":7759837,"count":157,"preSum":5181},{"ndv":157,"upper":8195281,"lower":7977826,"count":157,"preSum":5338},{"ndv":157,"upper":8475935,"lower":8195501,"count":157,"preSum":5495},{"ndv":157,"upper":8740693,"lower":8482481,"count":157,"preSum":5652},{"ndv":157,"upper":8988653,"lower":8742577,"count":157,"preSum":5809},{"ndv":157,"upper":9236129,"lower":8989468,"count":157,"preSum":5966},{"ndv":157,"upper":9466913,"lower":9237031,"count":157,"preSum":6123},{"ndv":157,"upper":9696547,"lower":9467365,"count":157,"preSum":6280},{"ndv":157,"upper":9911531,"lower":9698668,"count":157,"preSum":6437},{"ndv":156,"upper":10128674,"lower":9912551,"count":157,"preSum":6594},{"ndv":157,"upper":10342997,"lower":10128706,"count":157,"preSum":6751},{"ndv":157,"upper":10577005,"lower":10347064,"count":157,"preSum":6908},{"ndv":157,"upper":10830260,"lower":10578248,"count":157,"preSum":7065},{"ndv":157,"upper":11079172,"lower":10832110,"count":157,"preSum":7222},{"ndv":157,"upper":11331670,"lower":11081101,"count":157,"preSum":7379},{"ndv":157,"upper":11565940,"lower":11332396,"count":157,"preSum":7536},{"ndv":157,"upper":11786270,"lower":11567519,"count":157,"preSum":7693},{"ndv":156,"upper":12008855,"lower":11788988,"count":157,"preSum":7850},{"ndv":156,"upper":12231463,"lower":12008975,"count":157,"preSum":8007},{"ndv":157,"upper":12452617,"lower":12231475,"count":157,"preSum":8164},{"ndv":157,"upper":12682034,"lower":12453224,"count":157,"preSum":8321},{"ndv":157,"upper":12908881,"lower":12682699,"count":157,"preSum":8478},{"ndv":157,"upper":13155797,"lower":12909451,"count":157,"preSum":8635},{"ndv":156,"upper":13394041,"lower":13158088,"count":157,"preSum":8792},{"ndv":157,"upper":13618823,"lower":13394092,"count":157,"preSum":8949},{"ndv":157,"upper":13860955,"lower":13619258,"count":157,"preSum":9106},{"ndv":157,"upper":14113345,"lower":13861924,"count":157,"preSum":9263},{"ndv":157,"upper":14367931,"lower":14115790,"count":157,"preSum":9420},{"ndv":157,"upper":14623378,"lower":14368417,"count":157,"preSum":9577},{"ndv":157,"upper":14849170,"lower":14624953,"count":157,"preSum":9734},{"ndv":109,"upper":14999627,"lower":14849444,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Int","sampleRate":0.09921718}
+orders.o_orderdate.histogram:
+  {"buckets":[{"ndv":34,"upper":"1992-02-03","lower":"1992-01-01","count":157,"preSum":0},{"ndv":38,"upper":"1992-03-12","lower":"1992-02-04","count":160,"preSum":157},{"ndv":37,"upper":"1992-04-18","lower":"1992-03-13","count":159,"preSum":317},{"ndv":36,"upper":"1992-05-24","lower":"1992-04-19","count":157,"preSum":476},{"ndv":39,"upper":"1992-07-02","lower":"1992-05-25","count":157,"preSum":633},{"ndv":37,"upper":"1992-08-08","lower":"1992-07-03","count":160,"preSum":790},{"ndv":38,"upper":"1992-09-16","lower":"1992-08-09","count":157,"preSum":950},{"ndv":35,"upper":"1992-10-21","lower":"1992-09-17","count":157,"preSum":1107},{"ndv":32,"upper":"1992-11-22","lower":"1992-10-22","count":158,"preSum":1264},{"ndv":34,"upper":"1992-12-27","lower":"1992-11-23","count":158,"preSum":1422},{"ndv":33,"upper":"1993-01-31","lower":"1992-12-28","count":158,"preSum":1580},{"ndv":35,"upper":"1993-03-08","lower":"1993-02-01","count":157,"preSum":1738},{"ndv":41,"upper":"1993-04-19","lower":"1993-03-09","count":159,"preSum":1895},{"ndv":35,"upper":"1993-05-26","lower":"1993-04-20","count":161,"preSum":2054},{"ndv":41,"upper":"1993-07-08","lower":"1993-05-27","count":160,"preSum":2215},{"ndv":37,"upper":"1993-08-14","lower":"1993-07-09","count":159,"preSum":2375},{"ndv":35,"upper":"1993-09-19","lower":"1993-08-15","count":157,"preSum":2534},{"ndv":36,"upper":"1993-10-26","lower":"1993-09-20","count":157,"preSum":2691},{"ndv":36,"upper":"1993-12-01","lower":"1993-10-27","count":158,"preSum":2848},{"ndv":38,"upper":"1994-01-08","lower":"1993-12-02","count":158,"preSum":3006},{"ndv":32,"upper":"1994-02-09","lower":"1994-01-09","count":158,"preSum":3164},{"ndv":36,"upper":"1994-03-17","lower":"1994-02-10","count":161,"preSum":3322},{"ndv":37,"upper":"1994-04-24","lower":"1994-03-18","count":159,"preSum":3483},{"ndv":35,"upper":"1994-05-29","lower":"1994-04-25","count":158,"preSum":3642},{"ndv":37,"upper":"1994-07-05","lower":"1994-05-30","count":157,"preSum":3800},{"ndv":43,"upper":"1994-08-18","lower":"1994-07-06","count":158,"preSum":3957},{"ndv":41,"upper":"1994-09-28","lower":"1994-08-19","count":157,"preSum":4115},{"ndv":39,"upper":"1994-11-06","lower":"1994-09-29","count":157,"preSum":4272},{"ndv":39,"upper":"1994-12-15","lower":"1994-11-07","count":157,"preSum":4429},{"ndv":39,"upper":"1995-01-23","lower":"1994-12-16","count":159,"preSum":4586},{"ndv":37,"upper":"1995-03-02","lower":"1995-01-24","count":157,"preSum":4745},{"ndv":44,"upper":"1995-04-17","lower":"1995-03-03","count":158,"preSum":4902},{"ndv":34,"upper":"1995-05-22","lower":"1995-04-18","count":158,"preSum":5060},{"ndv":42,"upper":"1995-07-04","lower":"1995-05-23","count":158,"preSum":5218},{"ndv":40,"upper":"1995-08-15","lower":"1995-07-06","count":160,"preSum":5376},{"ndv":36,"upper":"1995-09-20","lower":"1995-08-16","count":157,"preSum":5536},{"ndv":30,"upper":"1995-10-21","lower":"1995-09-21","count":161,"preSum":5693},{"ndv":36,"upper":"1995-11-26","lower":"1995-10-22","count":161,"preSum":5854},{"ndv":35,"upper":"1995-12-31","lower":"1995-11-27","count":159,"preSum":6015},{"ndv":37,"upper":"1996-02-08","lower":"1996-01-01","count":157,"preSum":6174},{"ndv":41,"upper":"1996-03-20","lower":"1996-02-09","count":157,"preSum":6331},{"ndv":36,"upper":"1996-04-28","lower":"1996-03-23","count":159,"preSum":6488},{"ndv":39,"upper":"1996-06-07","lower":"1996-04-29","count":158,"preSum":6647},{"ndv":38,"upper":"1996-07-16","lower":"1996-06-08","count":161,"preSum":6805},{"ndv":39,"upper":"1996-08-27","lower":"1996-07-17","count":159,"preSum":6966},{"ndv":38,"upper":"1996-10-04","lower":"1996-08-28","count":160,"preSum":7125},{"ndv":39,"upper":"1996-11-13","lower":"1996-10-05","count":160,"preSum":7285},{"ndv":39,"upper":"1996-12-23","lower":"1996-11-14","count":161,"preSum":7445},{"ndv":39,"upper":"1997-02-01","lower":"1996-12-24","count":158,"preSum":7606},{"ndv":39,"upper":"1997-03-14","lower":"1997-02-02","count":157,"preSum":7764},{"ndv":40,"upper":"1997-04-24","lower":"1997-03-15","count":158,"preSum":7921},{"ndv":42,"upper":"1997-06-05","lower":"1997-04-25","count":161,"preSum":8079},{"ndv":38,"upper":"1997-07-15","lower":"1997-06-06","count":159,"preSum":8240},{"ndv":36,"upper":"1997-08-20","lower":"1997-07-16","count":161,"preSum":8399},{"ndv":32,"upper":"1997-09-22","lower":"1997-08-21","count":161,"preSum":8560},{"ndv":35,"upper":"1997-10-28","lower":"1997-09-23","count":160,"preSum":8721},{"ndv":37,"upper":"1997-12-04","lower":"1997-10-29","count":158,"preSum":8881},{"ndv":41,"upper":"1998-01-15","lower":"1997-12-05","count":160,"preSum":9039},{"ndv":40,"upper":"1998-02-25","lower":"1998-01-16","count":157,"preSum":9199},{"ndv":36,"upper":"1998-04-02","lower":"1998-02-26","count":157,"preSum":9356},{"ndv":42,"upper":"1998-05-14","lower":"1998-04-03","count":159,"preSum":9513},{"ndv":39,"upper":"1998-06-25","lower":"1998-05-15","count":158,"preSum":9672},{"ndv":34,"upper":"1998-07-29","lower":"1998-06-26","count":161,"preSum":9830},{"ndv":3,"upper":"1998-08-02","lower":"1998-07-31","count":9,"preSum":9991}],"maxBucketSize":64,"type":"Date","sampleRate":0.09921718}
+orders.o_orderkey.histogram:
+  {"buckets":[{"ndv":157,"upper":9976514,"lower":18496,"count":157,"preSum":0},{"ndv":157,"upper":21146405,"lower":10015041,"count":157,"preSum":157},{"ndv":157,"upper":30684962,"lower":21163943,"count":157,"preSum":314},{"ndv":157,"upper":40478337,"lower":30700132,"count":157,"preSum":471},{"ndv":157,"upper":48660774,"lower":40587107,"count":157,"preSum":628},{"ndv":157,"upper":57859878,"lower":48712515,"count":157,"preSum":785},{"ndv":157,"upper":66684615,"lower":57895331,"count":157,"preSum":942},{"ndv":157,"upper":76864231,"lower":66718789,"count":157,"preSum":1099},{"ndv":157,"upper":86150436,"lower":77157284,"count":157,"preSum":1256},{"ndv":157,"upper":94966084,"lower":86155971,"count":157,"preSum":1413},{"ndv":157,"upper":104668965,"lower":95035265,"count":157,"preSum":1570},{"ndv":157,"upper":114976675,"lower":104746019,"count":157,"preSum":1727},{"ndv":157,"upper":125537382,"lower":115018435,"count":157,"preSum":1884},{"ndv":157,"upper":135053282,"lower":125569154,"count":157,"preSum":2041},{"ndv":157,"upper":144726916,"lower":135141350,"count":157,"preSum":2198},{"ndv":157,"upper":155790533,"lower":144770823,"count":157,"preSum":2355},{"ndv":157,"upper":164349959,"lower":155867365,"count":157,"preSum":2512},{"ndv":157,"upper":172907559,"lower":164376994,"count":157,"preSum":2669},{"ndv":157,"upper":181813061,"lower":173197637,"count":157,"preSum":2826},{"ndv":157,"upper":191315077,"lower":181825990,"count":157,"preSum":2983},{"ndv":157,"upper":199392005,"lower":191460743,"count":157,"preSum":3140},{"ndv":157,"upper":209128161,"lower":199401349,"count":157,"preSum":3297},{"ndv":157,"upper":218395492,"lower":209170373,"count":157,"preSum":3454},{"ndv":157,"upper":227173699,"lower":218456806,"count":157,"preSum":3611},{"ndv":157,"upper":236107330,"lower":227208519,"count":157,"preSum":3768},{"ndv":157,"upper":245465378,"lower":236108001,"count":157,"preSum":3925},{"ndv":157,"upper":253253411,"lower":245727459,"count":157,"preSum":4082},{"ndv":157,"upper":262926819,"lower":253313286,"count":157,"preSum":4239},{"ndv":157,"upper":272751972,"lower":262971780,"count":157,"preSum":4396},{"ndv":157,"upper":282808548,"lower":272875457,"count":157,"preSum":4553},{"ndv":157,"upper":292196774,"lower":282854210,"count":157,"preSum":4710},{"ndv":157,"upper":302725920,"lower":292329412,"count":157,"preSum":4867},{"ndv":157,"upper":311079207,"lower":302767520,"count":157,"preSum":5024},{"ndv":157,"upper":320693794,"lower":311161862,"count":157,"preSum":5181},{"ndv":157,"upper":330100487,"lower":320694690,"count":157,"preSum":5338},{"ndv":157,"upper":339269895,"lower":330108705,"count":157,"preSum":5495},{"ndv":157,"upper":348372384,"lower":339373539,"count":157,"preSum":5652},{"ndv":157,"upper":358308901,"lower":348384772,"count":157,"preSum":5809},{"ndv":157,"upper":367836770,"lower":358335781,"count":157,"preSum":5966},{"ndv":157,"upper":377351524,"lower":367919875,"count":157,"preSum":6123},{"ndv":157,"upper":387029568,"lower":377356228,"count":157,"preSum":6280},{"ndv":157,"upper":395425382,"lower":387093733,"count":157,"preSum":6437},{"ndv":157,"upper":403221536,"lower":395602466,"count":157,"preSum":6594},{"ndv":157,"upper":412347746,"lower":403299713,"count":157,"preSum":6751},{"ndv":157,"upper":421318726,"lower":412401028,"count":157,"preSum":6908},{"ndv":157,"upper":430763045,"lower":421325828,"count":157,"preSum":7065},{"ndv":157,"upper":440097506,"lower":430936900,"count":157,"preSum":7222},{"ndv":157,"upper":449838598,"lower":440289700,"count":157,"preSum":7379},{"ndv":157,"upper":459851748,"lower":449869509,"count":157,"preSum":7536},{"ndv":157,"upper":469083552,"lower":459864324,"count":157,"preSum":7693},{"ndv":157,"upper":478908071,"lower":469123681,"count":157,"preSum":7850},{"ndv":157,"upper":488653378,"lower":478941571,"count":157,"preSum":8007},{"ndv":157,"upper":497721862,"lower":488662468,"count":157,"preSum":8164},{"ndv":157,"upper":506843392,"lower":497743139,"count":157,"preSum":8321},{"ndv":157,"upper":516430886,"lower":506847426,"count":157,"preSum":8478},{"ndv":157,"upper":525611200,"lower":516460992,"count":157,"preSum":8635},{"ndv":157,"upper":534898150,"lower":525749634,"count":157,"preSum":8792},{"ndv":157,"upper":544390627,"lower":534907557,"count":157,"preSum":8949},{"ndv":157,"upper":554915431,"lower":544398406,"count":157,"preSum":9106},{"ndv":157,"upper":564037029,"lower":555008359,"count":157,"preSum":9263},{"ndv":157,"upper":573353221,"lower":564078627,"count":157,"preSum":9420},{"ndv":157,"upper":582841447,"lower":573359972,"count":157,"preSum":9577},{"ndv":157,"upper":593007650,"lower":582928512,"count":157,"preSum":9734},{"ndv":109,"upper":599963776,"lower":593038915,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Int","sampleRate":0.09921718}
+orders.o_orderpriority.histogram:
+  {"buckets":[{"ndv":1,"upper":"1-URGENT","lower":"1-URGENT","count":1989,"preSum":0},{"ndv":1,"upper":"2-HIGH","lower":"2-HIGH","count":1961,"preSum":1989},{"ndv":1,"upper":"3-MEDIUM","lower":"3-MEDIUM","count":2055,"preSum":3950},{"ndv":1,"upper":"4-NOT SPECIFIED","lower":"4-NOT SPECIFIED","count":1993,"preSum":6005},{"ndv":1,"upper":"5-LOW","lower":"5-LOW","count":2002,"preSum":7998}],"maxBucketSize":64,"type":"String","sampleRate":0.09921718}
+orders.o_orderstatus.histogram:
+  {"buckets":[{"ndv":1,"upper":"F","lower":"F","count":4887,"preSum":0},{"ndv":1,"upper":"O","lower":"O","count":4857,"preSum":4887},{"ndv":1,"upper":"P","lower":"P","count":256,"preSum":9744}],"maxBucketSize":64,"type":"String","sampleRate":0.09921718}
+orders.o_shippriority.histogram:
+  {"buckets":[{"ndv":1,"upper":0,"lower":0,"count":10000,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":0.09921718}
+orders.o_totalprice.histogram:
+  {"buckets":[{"ndv":157,"upper":8870.29,"lower":967.72,"count":157,"preSum":0},{"ndv":157,"upper":16159.99,"lower":8883.07,"count":157,"preSum":157},{"ndv":157,"upper":22235.25,"lower":16179.82,"count":157,"preSum":314},{"ndv":157,"upper":28032.46,"lower":22334.81,"count":157,"preSum":471},{"ndv":157,"upper":32858.45,"lower":28042.04,"count":157,"preSum":628},{"ndv":157,"upper":37031.07,"lower":32886.02,"count":157,"preSum":785},{"ndv":157,"upper":41561.76,"lower":37036.46,"count":157,"preSum":942},{"ndv":157,"upper":45787.20,"lower":41582.37,"count":157,"preSum":1099},{"ndv":157,"upper":50169.44,"lower":45802.04,"count":157,"preSum":1256},{"ndv":157,"upper":54468.09,"lower":50216.37,"count":157,"preSum":1413},{"ndv":157,"upper":58473.45,"lower":54487.51,"count":157,"preSum":1570},{"ndv":157,"upper":62271.33,"lower":58482.71,"count":157,"preSum":1727},{"ndv":157,"upper":65829.51,"lower":62286.24,"count":157,"preSum":1884},{"ndv":157,"upper":69548.41,"lower":65878.54,"count":157,"preSum":2041},{"ndv":157,"upper":73429.80,"lower":69574.45,"count":157,"preSum":2198},{"ndv":157,"upper":77106.61,"lower":73453.48,"count":157,"preSum":2355},{"ndv":157,"upper":81665.92,"lower":77122.23,"count":157,"preSum":2512},{"ndv":157,"upper":85408.79,"lower":81692.66,"count":157,"preSum":2669},{"ndv":157,"upper":89263.53,"lower":85447.75,"count":157,"preSum":2826},{"ndv":157,"upper":93836.25,"lower":89317.09,"count":157,"preSum":2983},{"ndv":157,"upper":98012.79,"lower":93858.76,"count":157,"preSum":3140},{"ndv":157,"upper":102117.09,"lower":98024.73,"count":157,"preSum":3297},{"ndv":157,"upper":105663.66,"lower":102152.57,"count":157,"preSum":3454},{"ndv":157,"upper":109448.77,"lower":105667.82,"count":157,"preSum":3611},{"ndv":157,"upper":114288.69,"lower":109451.33,"count":157,"preSum":3768},{"ndv":157,"upper":119093.03,"lower":114395.34,"count":157,"preSum":3925},{"ndv":157,"upper":123756.00,"lower":119093.80,"count":157,"preSum":4082},{"ndv":157,"upper":127486.96,"lower":123786.57,"count":157,"preSum":4239},{"ndv":157,"upper":131916.94,"lower":127505.81,"count":157,"preSum":4396},{"ndv":157,"upper":136362.93,"lower":131942.75,"count":157,"preSum":4553},{"ndv":157,"upper":140732.27,"lower":136409.61,"count":157,"preSum":4710},{"ndv":157,"upper":145587.40,"lower":140812.06,"count":157,"preSum":4867},{"ndv":157,"upper":149355.66,"lower":145588.83,"count":157,"preSum":5024},{"ndv":157,"upper":153562.48,"lower":149410.39,"count":157,"preSum":5181},{"ndv":157,"upper":157814.13,"lower":153571.98,"count":157,"preSum":5338},{"ndv":157,"upper":161579.82,"lower":157822.98,"count":157,"preSum":5495},{"ndv":157,"upper":165511.17,"lower":161592.91,"count":157,"preSum":5652},{"ndv":157,"upper":170090.88,"lower":165518.87,"count":157,"preSum":5809},{"ndv":157,"upper":174737.22,"lower":170217.08,"count":157,"preSum":5966},{"ndv":157,"upper":179079.97,"lower":174776.51,"count":157,"preSum":6123},{"ndv":157,"upper":183736.04,"lower":179100.01,"count":157,"preSum":6280},{"ndv":157,"upper":187889.20,"lower":183739.85,"count":157,"preSum":6437},{"ndv":157,"upper":192593.00,"lower":187924.78,"count":157,"preSum":6594},{"ndv":157,"upper":197110.31,"lower":192596.25,"count":157,"preSum":6751},{"ndv":157,"upper":201943.80,"lower":197135.74,"count":157,"preSum":6908},{"ndv":157,"upper":207222.44,"lower":201994.51,"count":157,"preSum":7065},{"ndv":157,"upper":212074.57,"lower":207265.79,"count":157,"preSum":7222},{"ndv":157,"upper":217860.79,"lower":212146.67,"count":157,"preSum":7379},{"ndv":157,"upper":222823.20,"lower":217878.40,"count":157,"preSum":7536},{"ndv":157,"upper":227775.01,"lower":222823.27,"count":157,"preSum":7693},{"ndv":157,"upper":233892.29,"lower":227871.40,"count":157,"preSum":7850},{"ndv":157,"upper":240170.60,"lower":233949.85,"count":157,"preSum":8007},{"ndv":157,"upper":245735.57,"lower":240173.34,"count":157,"preSum":8164},{"ndv":157,"upper":251907.44,"lower":245748.04,"count":157,"preSum":8321},{"ndv":157,"upper":258589.33,"lower":251937.35,"count":157,"preSum":8478},{"ndv":157,"upper":266130.11,"lower":258641.75,"count":157,"preSum":8635},{"ndv":157,"upper":273754.45,"lower":266185.54,"count":157,"preSum":8792},{"ndv":157,"upper":281129.67,"lower":273757.72,"count":157,"preSum":8949},{"ndv":157,"upper":289109.38,"lower":281142.42,"count":157,"preSum":9106},{"ndv":157,"upper":298809.47,"lower":289125.90,"count":157,"preSum":9263},{"ndv":157,"upper":312024.66,"lower":298868.93,"count":157,"preSum":9420},{"ndv":157,"upper":332537.77,"lower":312108.86,"count":157,"preSum":9577},{"ndv":157,"upper":362236.27,"lower":332585.64,"count":157,"preSum":9734},{"ndv":109,"upper":452769.39,"lower":362949.28,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Double","sampleRate":0.09921718}
+part.p_brand.histogram:
+  {"buckets":[{"ndv":1,"upper":"Brand#11","lower":"Brand#11","count":443,"preSum":0},{"ndv":1,"upper":"Brand#12","lower":"Brand#12","count":389,"preSum":443},{"ndv":1,"upper":"Brand#13","lower":"Brand#13","count":400,"preSum":832},{"ndv":1,"upper":"Brand#14","lower":"Brand#14","count":402,"preSum":1232},{"ndv":1,"upper":"Brand#15","lower":"Brand#15","count":397,"preSum":1634},{"ndv":1,"upper":"Brand#21","lower":"Brand#21","count":406,"preSum":2031},{"ndv":1,"upper":"Brand#22","lower":"Brand#22","count":369,"preSum":2437},{"ndv":1,"upper":"Brand#23","lower":"Brand#23","count":402,"preSum":2806},{"ndv":1,"upper":"Brand#24","lower":"Brand#24","count":343,"preSum":3208},{"ndv":1,"upper":"Brand#25","lower":"Brand#25","count":395,"preSum":3551},{"ndv":1,"upper":"Brand#31","lower":"Brand#31","count":369,"preSum":3946},{"ndv":1,"upper":"Brand#32","lower":"Brand#32","count":394,"preSum":4315},{"ndv":1,"upper":"Brand#33","lower":"Brand#33","count":453,"preSum":4709},{"ndv":1,"upper":"Brand#34","lower":"Brand#34","count":434,"preSum":5162},{"ndv":1,"upper":"Brand#35","lower":"Brand#35","count":393,"preSum":5596},{"ndv":1,"upper":"Brand#41","lower":"Brand#41","count":377,"preSum":5989},{"ndv":1,"upper":"Brand#42","lower":"Brand#42","count":391,"preSum":6366},{"ndv":1,"upper":"Brand#43","lower":"Brand#43","count":403,"preSum":6757},{"ndv":1,"upper":"Brand#44","lower":"Brand#44","count":424,"preSum":7160},{"ndv":1,"upper":"Brand#45","lower":"Brand#45","count":405,"preSum":7584},{"ndv":1,"upper":"Brand#51","lower":"Brand#51","count":373,"preSum":7989},{"ndv":1,"upper":"Brand#52","lower":"Brand#52","count":400,"preSum":8362},{"ndv":1,"upper":"Brand#53","lower":"Brand#53","count":414,"preSum":8762},{"ndv":1,"upper":"Brand#54","lower":"Brand#54","count":411,"preSum":9176},{"ndv":1,"upper":"Brand#55","lower":"Brand#55","count":413,"preSum":9587}],"maxBucketSize":64,"type":"String","sampleRate":0.09926839}
+part.p_comment.histogram:
+  {"buckets":[{"ndv":140,"upper":" around the slyly ","lower":" abou","count":157,"preSum":0},{"ndv":128,"upper":" carefully ","lower":" asympt","count":160,"preSum":157},{"ndv":139,"upper":" excuses. fu","lower":" carefully according","count":157,"preSum":317},{"ndv":138,"upper":" furiously ironic pa","lower":" excuses. grouc","count":157,"preSum":474},{"ndv":135,"upper":" nag fluffily ","lower":" furiously pen","count":157,"preSum":631},{"ndv":131,"upper":" quickly. pending de","lower":" nag qui","count":157,"preSum":788},{"ndv":124,"upper":" slyly after the r","lower":" quickly: fluffily e","count":157,"preSum":945},{"ndv":139,"upper":" theodolites can wak","lower":" slyly against the s","count":157,"preSum":1102},{"ndv":148,"upper":". carefully final du","lower":" theodolites haggl","count":157,"preSum":1259},{"ndv":146,"upper":"about the","lower":". carefully ir","count":158,"preSum":1416},{"ndv":139,"upper":"ages agains","lower":"about the busil","count":157,"preSum":1574},{"ndv":145,"upper":"al packages. theodol","lower":"ages are","count":157,"preSum":1731},{"ndv":151,"upper":"arefull","lower":"al pinto bea","count":161,"preSum":1888},{"ndv":142,"upper":"blithely s","lower":"arefully","count":157,"preSum":2049},{"ndv":136,"upper":"carefully ","lower":"blithely silent r","count":157,"preSum":2206},{"ndv":146,"upper":"ckages. furio","lower":"carefully above ","count":157,"preSum":2363},{"ndv":143,"upper":"d accounts against t","lower":"ckages. furiously","count":157,"preSum":2520},{"ndv":148,"upper":"ding to","lower":"d across the car","count":158,"preSum":2677},{"ndv":150,"upper":"e of the care","lower":"ding to ","count":157,"preSum":2835},{"ndv":147,"upper":"ecial requests. qui","lower":"e of the quickly exp","count":157,"preSum":2992},{"ndv":144,"upper":"ely express, ","lower":"ecial, exp","count":157,"preSum":3149},{"ndv":150,"upper":"ep pinto b","lower":"ely fin","count":157,"preSum":3306},{"ndv":149,"upper":"es integrate","lower":"ep quietly aga","count":157,"preSum":3463},{"ndv":153,"upper":"ets sleep. fo","lower":"es integrate blithel","count":157,"preSum":3620},{"ndv":150,"upper":"final fox","lower":"ets. furiously thin ","count":157,"preSum":3777},{"ndv":137,"upper":"furiously along t","lower":"final foxes. p","count":157,"preSum":3934},{"ndv":152,"upper":"ggle req","lower":"furiously blit","count":157,"preSum":4091},{"ndv":140,"upper":"he final requests ","lower":"ggle slyly sl","count":157,"preSum":4248},{"ndv":145,"upper":"ic accou","lower":"he flu","count":158,"preSum":4405},{"ndv":154,"upper":"ily qui","lower":"ic accounts","count":157,"preSum":4563},{"ndv":146,"upper":"into beans along th","lower":"ily quietly si","count":157,"preSum":4720},{"ndv":146,"upper":"ites ca","lower":"into beans ar","count":157,"preSum":4877},{"ndv":149,"upper":"ke carefully bl","lower":"ites cajole bl","count":157,"preSum":5034},{"ndv":147,"upper":"lar acco","lower":"ke carefully regular","count":157,"preSum":5191},{"ndv":153,"upper":"leep toward the sl","lower":"lar accounts a","count":157,"preSum":5348},{"ndv":149,"upper":"long the quickly fin","lower":"leep. ","count":157,"preSum":5505},{"ndv":143,"upper":"ly final ideas ","lower":"long the silently sl","count":157,"preSum":5662},{"ndv":135,"upper":"lyly about the ","lower":"ly final instruc","count":157,"preSum":5819},{"ndv":153,"upper":"ncies are a","lower":"lyly above the silen","count":157,"preSum":5976},{"ndv":148,"upper":"nis. ","lower":"ncies are blithely. ","count":157,"preSum":6133},{"ndv":147,"upper":"nts. blith","lower":"nments unwind carefu","count":157,"preSum":6290},{"ndv":147,"upper":"ole. quickly reg","lower":"nts. blithel","count":157,"preSum":6447},{"ndv":147,"upper":"osits are along t","lower":"olite","count":157,"preSum":6604},{"ndv":143,"upper":"ously. unusual ","lower":"osits are blithel","count":157,"preSum":6761},{"ndv":142,"upper":"pendin","lower":"ously? bold i","count":158,"preSum":6918},{"ndv":147,"upper":"quests against the","lower":"pending","count":157,"preSum":7076},{"ndv":147,"upper":"re against the qui","lower":"quests ar","count":157,"preSum":7233},{"ndv":128,"upper":"ress de","lower":"re always. stealthi","count":157,"preSum":7390},{"ndv":136,"upper":"rts sleep abov","lower":"ress dependencies. ","count":157,"preSum":7547},{"ndv":144,"upper":"s hinder sly","lower":"ructi","count":157,"preSum":7704},{"ndv":153,"upper":"s. final","lower":"s idea","count":157,"preSum":7861},{"ndv":151,"upper":"sits wake car","lower":"s. final ideas slee","count":157,"preSum":8018},{"ndv":144,"upper":"ss th","lower":"sits wake. quickl","count":157,"preSum":8175},{"ndv":153,"upper":"t slyly sl","lower":"ss the","count":157,"preSum":8332},{"ndv":149,"upper":"the pendi","lower":"t slyly. ideas slee","count":157,"preSum":8489},{"ndv":142,"upper":"to beans will have t","lower":"the pending plate","count":157,"preSum":8646},{"ndv":149,"upper":"ts. blithely ","lower":"to beans.","count":158,"preSum":8803},{"ndv":151,"upper":"uffily special hocke","lower":"ts. blithely si","count":157,"preSum":8961},{"ndv":145,"upper":"unts solve","lower":"uffily. quickly iro","count":157,"preSum":9118},{"ndv":133,"upper":"usly dogged p","lower":"unts sublate sl","count":157,"preSum":9275},{"ndv":152,"upper":"wake. spe","lower":"usly eve","count":157,"preSum":9432},{"ndv":147,"upper":"y express realms ","lower":"warhorses. ","count":157,"preSum":9589},{"ndv":142,"upper":"y thin theodolites d","lower":"y express theodolite","count":157,"preSum":9746},{"ndv":92,"upper":"zzle abov","lower":"y to the carefull","count":97,"preSum":9903}],"maxBucketSize":64,"type":"String","sampleRate":0.09926839}
+part.p_container.histogram:
+  {"buckets":[{"ndv":1,"upper":"JUMBO BAG","lower":"JUMBO BAG","count":222,"preSum":0},{"ndv":1,"upper":"JUMBO BOX","lower":"JUMBO BOX","count":203,"preSum":222},{"ndv":1,"upper":"JUMBO CAN","lower":"JUMBO CAN","count":250,"preSum":425},{"ndv":1,"upper":"JUMBO CASE","lower":"JUMBO CASE","count":272,"preSum":675},{"ndv":1,"upper":"JUMBO DRUM","lower":"JUMBO DRUM","count":245,"preSum":947},{"ndv":1,"upper":"JUMBO JAR","lower":"JUMBO JAR","count":267,"preSum":1192},{"ndv":1,"upper":"JUMBO PACK","lower":"JUMBO PACK","count":229,"preSum":1459},{"ndv":1,"upper":"JUMBO PKG","lower":"JUMBO PKG","count":266,"preSum":1688},{"ndv":1,"upper":"LG BAG","lower":"LG BAG","count":255,"preSum":1954},{"ndv":1,"upper":"LG BOX","lower":"LG BOX","count":259,"preSum":2209},{"ndv":1,"upper":"LG CAN","lower":"LG CAN","count":275,"preSum":2468},{"ndv":1,"upper":"LG CASE","lower":"LG CASE","count":247,"preSum":2743},{"ndv":1,"upper":"LG DRUM","lower":"LG DRUM","count":269,"preSum":2990},{"ndv":1,"upper":"LG JAR","lower":"LG JAR","count":246,"preSum":3259},{"ndv":1,"upper":"LG PACK","lower":"LG PACK","count":254,"preSum":3505},{"ndv":1,"upper":"LG PKG","lower":"LG PKG","count":237,"preSum":3759},{"ndv":1,"upper":"MED BAG","lower":"MED BAG","count":246,"preSum":3996},{"ndv":1,"upper":"MED BOX","lower":"MED BOX","count":256,"preSum":4242},{"ndv":1,"upper":"MED CAN","lower":"MED CAN","count":268,"preSum":4498},{"ndv":1,"upper":"MED CASE","lower":"MED CASE","count":262,"preSum":4766},{"ndv":1,"upper":"MED DRUM","lower":"MED DRUM","count":251,"preSum":5028},{"ndv":1,"upper":"MED JAR","lower":"MED JAR","count":245,"preSum":5279},{"ndv":1,"upper":"MED PACK","lower":"MED PACK","count":247,"preSum":5524},{"ndv":1,"upper":"MED PKG","lower":"MED PKG","count":242,"preSum":5771},{"ndv":1,"upper":"SM BAG","lower":"SM BAG","count":234,"preSum":6013},{"ndv":1,"upper":"SM BOX","lower":"SM BOX","count":266,"preSum":6247},{"ndv":1,"upper":"SM CAN","lower":"SM CAN","count":239,"preSum":6513},{"ndv":1,"upper":"SM CASE","lower":"SM CASE","count":251,"preSum":6752},{"ndv":1,"upper":"SM DRUM","lower":"SM DRUM","count":242,"preSum":7003},{"ndv":1,"upper":"SM JAR","lower":"SM JAR","count":259,"preSum":7245},{"ndv":1,"upper":"SM PACK","lower":"SM PACK","count":258,"preSum":7504},{"ndv":1,"upper":"SM PKG","lower":"SM PKG","count":247,"preSum":7762},{"ndv":1,"upper":"WRAP BAG","lower":"WRAP BAG","count":276,"preSum":8009},{"ndv":1,"upper":"WRAP BOX","lower":"WRAP BOX","count":216,"preSum":8285},{"ndv":1,"upper":"WRAP CAN","lower":"WRAP CAN","count":248,"preSum":8501},{"ndv":1,"upper":"WRAP CASE","lower":"WRAP CASE","count":248,"preSum":8749},{"ndv":1,"upper":"WRAP DRUM","lower":"WRAP DRUM","count":236,"preSum":8997},{"ndv":1,"upper":"WRAP JAR","lower":"WRAP JAR","count":271,"preSum":9233},{"ndv":1,"upper":"WRAP PACK","lower":"WRAP PACK","count":240,"preSum":9504},{"ndv":1,"upper":"WRAP PKG","lower":"WRAP PKG","count":256,"preSum":9744}],"maxBucketSize":64,"type":"String","sampleRate":0.09926839}
+part.p_mfgr.histogram:
+  {"buckets":[{"ndv":1,"upper":"Manufacturer#1","lower":"Manufacturer#1","count":2034,"preSum":0},{"ndv":1,"upper":"Manufacturer#2","lower":"Manufacturer#2","count":1973,"preSum":2034},{"ndv":1,"upper":"Manufacturer#3","lower":"Manufacturer#3","count":1957,"preSum":4007},{"ndv":1,"upper":"Manufacturer#4","lower":"Manufacturer#4","count":2011,"preSum":5964},{"ndv":1,"upper":"Manufacturer#5","lower":"Manufacturer#5","count":2025,"preSum":7975}],"maxBucketSize":64,"type":"String","sampleRate":0.09926839}
+part.p_name.histogram:
+  {"buckets":[{"ndv":154,"upper":"antique lace royal k","lower":"almond antique white","count":157,"preSum":0},{"ndv":148,"upper":"aquamarine slate roy","lower":"antique lavender azu","count":157,"preSum":157},{"ndv":157,"upper":"beige honeydew misty","lower":"aquamarine spring vi","count":157,"preSum":314},{"ndv":156,"upper":"bisque pale honeydew","lower":"beige hot aquamarine","count":157,"preSum":471},{"ndv":157,"upper":"black slate grey moc","lower":"bisque papaya hot li","count":157,"preSum":628},{"ndv":156,"upper":"blue ghost dark blan","lower":"black spring misty t","count":157,"preSum":785},{"ndv":157,"upper":"blush rose violet be","lower":"blue ghost lavender ","count":157,"preSum":942},{"ndv":151,"upper":"burlywood cornflower","lower":"blush rosy brown lem","count":157,"preSum":1099},{"ndv":146,"upper":"burnished honeydew b","lower":"burlywood cornsilk g","count":157,"preSum":1256},{"ndv":152,"upper":"chartreuse saddle bl","lower":"burnished honeydew r","count":157,"preSum":1413},{"ndv":153,"upper":"chocolate chartreuse","lower":"chartreuse sandy azu","count":158,"preSum":1570},{"ndv":154,"upper":"coral peru seashell ","lower":"chocolate chiffon sm","count":157,"preSum":1728},{"ndv":146,"upper":"cornsilk azure flora","lower":"coral pink lawn lave","count":157,"preSum":1885},{"ndv":155,"upper":"cream lemon cornflow","lower":"cornsilk blanched ma","count":157,"preSum":2042},{"ndv":156,"upper":"cyan spring orange o","lower":"cream lemon lawn hot","count":157,"preSum":2199},{"ndv":157,"upper":"deep forest bisque s","lower":"cyan steel aquamarin","count":157,"preSum":2356},{"ndv":157,"upper":"dim purple magenta d","lower":"deep frosted burnish","count":157,"preSum":2513},{"ndv":157,"upper":"drab dark medium law","lower":"dim purple powder tu","count":157,"preSum":2670},{"ndv":152,"upper":"firebrick orange sno","lower":"drab deep chocolate ","count":157,"preSum":2827},{"ndv":156,"upper":"floral wheat forest ","lower":"firebrick orchid chi","count":157,"preSum":2984},{"ndv":157,"upper":"frosted green metall","lower":"floral yellow almond","count":157,"preSum":3141},{"ndv":155,"upper":"gainsboro plum fireb","lower":"frosted green puff m","count":157,"preSum":3298},{"ndv":154,"upper":"goldenrod forest lim","lower":"gainsboro puff maroo","count":157,"preSum":3455},{"ndv":156,"upper":"green rosy goldenrod","lower":"goldenrod forest sla","count":157,"preSum":3612},{"ndv":156,"upper":"honeydew goldenrod c","lower":"green royal honeydew","count":157,"preSum":3769},{"ndv":157,"upper":"hot red powder cyan ","lower":"honeydew green ivory","count":157,"preSum":3926},{"ndv":157,"upper":"ivory chartreuse flo","lower":"hot rose lime light ","count":157,"preSum":4083},{"ndv":157,"upper":"khaki olive cyan cre","lower":"ivory chartreuse hon","count":157,"preSum":4240},{"ndv":154,"upper":"lavender cyan green ","lower":"khaki olive maroon r","count":157,"preSum":4397},{"ndv":156,"upper":"lawn maroon mint thi","lower":"lavender dark rosy m","count":157,"preSum":4554},{"ndv":157,"upper":"light almond papaya ","lower":"lawn medium linen ol","count":157,"preSum":4711},{"ndv":157,"upper":"lime lavender misty ","lower":"light antique chiffo","count":157,"preSum":4868},{"ndv":157,"upper":"linen sandy dodger b","lower":"lime lawn honeydew c","count":157,"preSum":5025},{"ndv":153,"upper":"maroon forest dodger","lower":"linen sandy sienna o","count":157,"preSum":5182},{"ndv":157,"upper":"medium metallic sky ","lower":"maroon forest indian","count":157,"preSum":5339},{"ndv":152,"upper":"metallic turquoise l","lower":"medium midnight hone","count":157,"preSum":5496},{"ndv":156,"upper":"mint green blush dra","lower":"metallic turquoise m","count":157,"preSum":5653},{"ndv":155,"upper":"misty pale honeydew ","lower":"mint green plum toma","count":157,"preSum":5810},{"ndv":152,"upper":"moccasin steel sandy","lower":"misty papaya pale bl","count":157,"preSum":5967},{"ndv":157,"upper":"navy magenta powder ","lower":"moccasin tan gainsbo","count":157,"preSum":6124},{"ndv":157,"upper":"olive steel deep lac","lower":"navy maroon snow gre","count":157,"preSum":6281},{"ndv":157,"upper":"orchid light magenta","lower":"olive tan antique wh","count":157,"preSum":6438},{"ndv":157,"upper":"pale tomato chocolat","lower":"orchid lime chartreu","count":157,"preSum":6595},{"ndv":154,"upper":"peach lace sienna cr","lower":"pale tomato salmon l","count":157,"preSum":6752},{"ndv":157,"upper":"peru turquoise viole","lower":"peach lavender burni","count":157,"preSum":6909},{"ndv":157,"upper":"plum moccasin royal ","lower":"peru wheat blush lim","count":157,"preSum":7066},{"ndv":157,"upper":"puff blanched plum s","lower":"plum navajo medium g","count":157,"preSum":7223},{"ndv":157,"upper":"purple lime chiffon ","lower":"puff blanched sandy ","count":157,"preSum":7380},{"ndv":157,"upper":"red wheat lemon hone","lower":"purple lime gainsbor","count":157,"preSum":7537},{"ndv":156,"upper":"rosy magenta tomato ","lower":"red white burnished ","count":157,"preSum":7694},{"ndv":157,"upper":"saddle black spring ","lower":"rosy maroon cyan per","count":157,"preSum":7851},{"ndv":157,"upper":"salmon magenta snow ","lower":"saddle blanched azur","count":157,"preSum":8008},{"ndv":157,"upper":"sandy tomato coral p","lower":"salmon maroon midnig","count":157,"preSum":8165},{"ndv":154,"upper":"sienna hot bisque iv","lower":"sandy violet blanche","count":157,"preSum":8322},{"ndv":156,"upper":"sky salmon cornflowe","lower":"sienna hot indian mi","count":157,"preSum":8479},{"ndv":157,"upper":"smoke lace blue mint","lower":"sky salmon red gains","count":157,"preSum":8636},{"ndv":157,"upper":"snow violet saddle a","lower":"smoke lace medium se","count":157,"preSum":8793},{"ndv":157,"upper":"steel lavender flora","lower":"snow wheat azure sea","count":157,"preSum":8950},{"ndv":157,"upper":"tan spring pink powd","lower":"steel lavender lace ","count":157,"preSum":9107},{"ndv":157,"upper":"tomato moccasin ivor","lower":"tan steel maroon blu","count":157,"preSum":9264},{"ndv":156,"upper":"violet azure light g","lower":"tomato navajo blue r","count":157,"preSum":9421},{"ndv":156,"upper":"wheat lime peru lemo","lower":"violet beige smoke p","count":157,"preSum":9578},{"ndv":156,"upper":"yellow aquamarine ro","lower":"wheat magenta gainsb","count":157,"preSum":9735},{"ndv":108,"upper":"yellow white drab de","lower":"yellow azure hot cor","count":108,"preSum":9892}],"maxBucketSize":64,"type":"String","sampleRate":0.09926839}
+part.p_partkey.histogram:
+  {"buckets":[{"ndv":157,"upper":299854,"lower":5509,"count":157,"preSum":0},{"ndv":157,"upper":613873,"lower":302085,"count":157,"preSum":157},{"ndv":157,"upper":972410,"lower":618442,"count":157,"preSum":314},{"ndv":157,"upper":1326761,"lower":973174,"count":157,"preSum":471},{"ndv":157,"upper":1628244,"lower":1330646,"count":157,"preSum":628},{"ndv":157,"upper":1919797,"lower":1630465,"count":157,"preSum":785},{"ndv":157,"upper":2239132,"lower":1921326,"count":157,"preSum":942},{"ndv":157,"upper":2580593,"lower":2240030,"count":157,"preSum":1099},{"ndv":157,"upper":2904554,"lower":2587884,"count":157,"preSum":1256},{"ndv":157,"upper":3238825,"lower":2907772,"count":157,"preSum":1413},{"ndv":157,"upper":3567207,"lower":3239580,"count":157,"preSum":1570},{"ndv":157,"upper":3861752,"lower":3567743,"count":157,"preSum":1727},{"ndv":157,"upper":4177527,"lower":3866105,"count":157,"preSum":1884},{"ndv":157,"upper":4470290,"lower":4177826,"count":157,"preSum":2041},{"ndv":157,"upper":4750484,"lower":4470787,"count":157,"preSum":2198},{"ndv":157,"upper":5065861,"lower":4751671,"count":157,"preSum":2355},{"ndv":157,"upper":5392898,"lower":5067318,"count":157,"preSum":2512},{"ndv":157,"upper":5702821,"lower":5393026,"count":157,"preSum":2669},{"ndv":157,"upper":6036838,"lower":5704102,"count":157,"preSum":2826},{"ndv":157,"upper":6340691,"lower":6037515,"count":157,"preSum":2983},{"ndv":157,"upper":6675245,"lower":6341818,"count":157,"preSum":3140},{"ndv":157,"upper":6976221,"lower":6675954,"count":157,"preSum":3297},{"ndv":157,"upper":7261174,"lower":6978183,"count":157,"preSum":3454},{"ndv":157,"upper":7585520,"lower":7261431,"count":157,"preSum":3611},{"ndv":157,"upper":7886623,"lower":7586050,"count":157,"preSum":3768},{"ndv":157,"upper":8190260,"lower":7892691,"count":157,"preSum":3925},{"ndv":157,"upper":8509605,"lower":8192848,"count":157,"preSum":4082},{"ndv":157,"upper":8812086,"lower":8514233,"count":157,"preSum":4239},{"ndv":157,"upper":9123370,"lower":8813564,"count":157,"preSum":4396},{"ndv":157,"upper":9423409,"lower":9124186,"count":157,"preSum":4553},{"ndv":157,"upper":9729739,"lower":9423658,"count":157,"preSum":4710},{"ndv":157,"upper":10039835,"lower":9733083,"count":157,"preSum":4867},{"ndv":157,"upper":10396509,"lower":10042659,"count":157,"preSum":5024},{"ndv":157,"upper":10707403,"lower":10397243,"count":157,"preSum":5181},{"ndv":157,"upper":11026217,"lower":10708979,"count":157,"preSum":5338},{"ndv":157,"upper":11369220,"lower":11026867,"count":157,"preSum":5495},{"ndv":157,"upper":11698748,"lower":11371796,"count":157,"preSum":5652},{"ndv":157,"upper":11988979,"lower":11702514,"count":157,"preSum":5809},{"ndv":157,"upper":12282898,"lower":11989563,"count":157,"preSum":5966},{"ndv":157,"upper":12603014,"lower":12283752,"count":157,"preSum":6123},{"ndv":157,"upper":12908012,"lower":12603345,"count":157,"preSum":6280},{"ndv":157,"upper":13217866,"lower":12909539,"count":157,"preSum":6437},{"ndv":157,"upper":13506279,"lower":13219838,"count":157,"preSum":6594},{"ndv":157,"upper":13857417,"lower":13511030,"count":157,"preSum":6751},{"ndv":157,"upper":14155158,"lower":13857553,"count":157,"preSum":6908},{"ndv":157,"upper":14486059,"lower":14158234,"count":157,"preSum":7065},{"ndv":157,"upper":14824207,"lower":14486613,"count":157,"preSum":7222},{"ndv":157,"upper":15145820,"lower":14829657,"count":157,"preSum":7379},{"ndv":157,"upper":15460501,"lower":15147691,"count":157,"preSum":7536},{"ndv":157,"upper":15773406,"lower":15460864,"count":157,"preSum":7693},{"ndv":157,"upper":16075965,"lower":15777044,"count":157,"preSum":7850},{"ndv":157,"upper":16352102,"lower":16076334,"count":157,"preSum":8007},{"ndv":157,"upper":16656741,"lower":16352594,"count":157,"preSum":8164},{"ndv":157,"upper":16996235,"lower":16657849,"count":157,"preSum":8321},{"ndv":157,"upper":17286416,"lower":16998292,"count":157,"preSum":8478},{"ndv":157,"upper":17576062,"lower":17289162,"count":157,"preSum":8635},{"ndv":157,"upper":17843329,"lower":17577821,"count":157,"preSum":8792},{"ndv":157,"upper":18136093,"lower":17844183,"count":157,"preSum":8949},{"ndv":157,"upper":18446989,"lower":18136540,"count":157,"preSum":9106},{"ndv":157,"upper":18773463,"lower":18451338,"count":157,"preSum":9263},{"ndv":157,"upper":19136012,"lower":18774437,"count":157,"preSum":9420},{"ndv":157,"upper":19426983,"lower":19136642,"count":157,"preSum":9577},{"ndv":157,"upper":19772183,"lower":19427462,"count":157,"preSum":9734},{"ndv":109,"upper":19998469,"lower":19774780,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Int","sampleRate":0.09926839}
+part.p_retailprice.histogram:
+  {"buckets":[{"ndv":157,"upper":979.80,"lower":905.42,"count":157,"preSum":0},{"ndv":156,"upper":1013.93,"lower":980.00,"count":157,"preSum":157},{"ndv":150,"upper":1037.89,"lower":1013.98,"count":157,"preSum":314},{"ndv":153,"upper":1059.62,"lower":1037.96,"count":157,"preSum":471},{"ndv":154,"upper":1076.79,"lower":1059.69,"count":157,"preSum":628},{"ndv":150,"upper":1093.35,"lower":1076.84,"count":157,"preSum":785},{"ndv":149,"upper":1108.41,"lower":1093.62,"count":157,"preSum":942},{"ndv":155,"upper":1125.43,"lower":1108.42,"count":157,"preSum":1099},{"ndv":151,"upper":1141.01,"lower":1125.55,"count":157,"preSum":1256},{"ndv":150,"upper":1157.03,"lower":1141.10,"count":157,"preSum":1413},{"ndv":146,"upper":1173.13,"lower":1157.19,"count":157,"preSum":1570},{"ndv":154,"upper":1189.32,"lower":1173.35,"count":157,"preSum":1727},{"ndv":151,"upper":1203.67,"lower":1189.44,"count":157,"preSum":1884},{"ndv":151,"upper":1219.30,"lower":1203.81,"count":157,"preSum":2041},{"ndv":152,"upper":1236.16,"lower":1219.46,"count":158,"preSum":2198},{"ndv":149,"upper":1251.23,"lower":1236.19,"count":158,"preSum":2356},{"ndv":148,"upper":1266.77,"lower":1251.24,"count":157,"preSum":2514},{"ndv":147,"upper":1281.88,"lower":1266.95,"count":157,"preSum":2671},{"ndv":152,"upper":1297.97,"lower":1281.92,"count":157,"preSum":2828},{"ndv":150,"upper":1314.71,"lower":1298.05,"count":158,"preSum":2985},{"ndv":144,"upper":1330.27,"lower":1314.84,"count":157,"preSum":3143},{"ndv":148,"upper":1345.38,"lower":1330.42,"count":157,"preSum":3300},{"ndv":153,"upper":1361.47,"lower":1345.64,"count":157,"preSum":3457},{"ndv":149,"upper":1376.91,"lower":1361.49,"count":157,"preSum":3614},{"ndv":149,"upper":1390.92,"lower":1377.20,"count":157,"preSum":3771},{"ndv":151,"upper":1406.60,"lower":1390.94,"count":157,"preSum":3928},{"ndv":153,"upper":1423.61,"lower":1406.62,"count":157,"preSum":4085},{"ndv":148,"upper":1438.20,"lower":1423.72,"count":157,"preSum":4242},{"ndv":149,"upper":1454.83,"lower":1438.24,"count":157,"preSum":4399},{"ndv":148,"upper":1470.28,"lower":1454.88,"count":157,"preSum":4556},{"ndv":150,"upper":1483.46,"lower":1470.30,"count":157,"preSum":4713},{"ndv":152,"upper":1499.39,"lower":1483.51,"count":157,"preSum":4870},{"ndv":151,"upper":1513.81,"lower":1499.51,"count":157,"preSum":5027},{"ndv":148,"upper":1531.89,"lower":1513.86,"count":158,"preSum":5184},{"ndv":145,"upper":1547.22,"lower":1531.98,"count":157,"preSum":5342},{"ndv":149,"upper":1562.12,"lower":1547.57,"count":157,"preSum":5499},{"ndv":152,"upper":1576.25,"lower":1562.23,"count":157,"preSum":5656},{"ndv":148,"upper":1591.78,"lower":1576.27,"count":157,"preSum":5813},{"ndv":149,"upper":1605.81,"lower":1591.92,"count":157,"preSum":5970},{"ndv":152,"upper":1623.06,"lower":1605.84,"count":157,"preSum":6127},{"ndv":150,"upper":1636.94,"lower":1623.16,"count":157,"preSum":6284},{"ndv":154,"upper":1653.35,"lower":1637.03,"count":157,"preSum":6441},{"ndv":152,"upper":1671.09,"lower":1653.62,"count":157,"preSum":6598},{"ndv":150,"upper":1686.97,"lower":1671.15,"count":157,"preSum":6755},{"ndv":154,"upper":1700.92,"lower":1686.99,"count":157,"preSum":6912},{"ndv":151,"upper":1718.23,"lower":1700.95,"count":157,"preSum":7069},{"ndv":153,"upper":1735.06,"lower":1718.29,"count":157,"preSum":7226},{"ndv":144,"upper":1751.05,"lower":1735.11,"count":157,"preSum":7383},{"ndv":147,"upper":1764.68,"lower":1751.21,"count":157,"preSum":7540},{"ndv":151,"upper":1780.03,"lower":1764.73,"count":157,"preSum":7697},{"ndv":149,"upper":1794.99,"lower":1780.24,"count":157,"preSum":7854},{"ndv":151,"upper":1810.01,"lower":1795.10,"count":157,"preSum":8011},{"ndv":149,"upper":1823.55,"lower":1810.07,"count":157,"preSum":8168},{"ndv":151,"upper":1840.27,"lower":1823.63,"count":157,"preSum":8325},{"ndv":151,"upper":1857.53,"lower":1840.65,"count":157,"preSum":8482},{"ndv":148,"upper":1874.64,"lower":1857.60,"count":157,"preSum":8639},{"ndv":149,"upper":1895.03,"lower":1874.84,"count":157,"preSum":8796},{"ndv":149,"upper":1912.05,"lower":1895.05,"count":157,"preSum":8953},{"ndv":149,"upper":1930.06,"lower":1912.40,"count":157,"preSum":9110},{"ndv":150,"upper":1950.02,"lower":1930.78,"count":157,"preSum":9267},{"ndv":150,"upper":1973.10,"lower":1950.20,"count":157,"preSum":9424},{"ndv":157,"upper":2001.65,"lower":1973.27,"count":157,"preSum":9581},{"ndv":152,"upper":2038.02,"lower":2001.67,"count":157,"preSum":9738},{"ndv":105,"upper":2095.87,"lower":2038.06,"count":105,"preSum":9895}],"maxBucketSize":64,"type":"Double","sampleRate":0.09926839}
+part.p_size.histogram:
+  {"buckets":[{"ndv":1,"upper":1,"lower":1,"count":202,"preSum":0},{"ndv":1,"upper":2,"lower":2,"count":197,"preSum":202},{"ndv":1,"upper":3,"lower":3,"count":177,"preSum":399},{"ndv":1,"upper":4,"lower":4,"count":215,"preSum":576},{"ndv":1,"upper":5,"lower":5,"count":218,"preSum":791},{"ndv":1,"upper":6,"lower":6,"count":189,"preSum":1009},{"ndv":1,"upper":7,"lower":7,"count":187,"preSum":1198},{"ndv":1,"upper":8,"lower":8,"count":192,"preSum":1385},{"ndv":1,"upper":9,"lower":9,"count":177,"preSum":1577},{"ndv":1,"upper":10,"lower":10,"count":186,"preSum":1754},{"ndv":1,"upper":11,"lower":11,"count":213,"preSum":1940},{"ndv":1,"upper":12,"lower":12,"count":225,"preSum":2153},{"ndv":1,"upper":13,"lower":13,"count":185,"preSum":2378},{"ndv":1,"upper":14,"lower":14,"count":203,"preSum":2563},{"ndv":1,"upper":15,"lower":15,"count":192,"preSum":2766},{"ndv":1,"upper":16,"lower":16,"count":184,"preSum":2958},{"ndv":1,"upper":17,"lower":17,"count":182,"preSum":3142},{"ndv":1,"upper":18,"lower":18,"count":185,"preSum":3324},{"ndv":1,"upper":19,"lower":19,"count":194,"preSum":3509},{"ndv":1,"upper":20,"lower":20,"count":199,"preSum":3703},{"ndv":1,"upper":21,"lower":21,"count":214,"preSum":3902},{"ndv":1,"upper":22,"lower":22,"count":189,"preSum":4116},{"ndv":1,"upper":23,"lower":23,"count":205,"preSum":4305},{"ndv":1,"upper":24,"lower":24,"count":237,"preSum":4510},{"ndv":1,"upper":25,"lower":25,"count":190,"preSum":4747},{"ndv":1,"upper":26,"lower":26,"count":203,"preSum":4937},{"ndv":1,"upper":27,"lower":27,"count":183,"preSum":5140},{"ndv":1,"upper":28,"lower":28,"count":190,"preSum":5323},{"ndv":1,"upper":29,"lower":29,"count":226,"preSum":5513},{"ndv":1,"upper":30,"lower":30,"count":211,"preSum":5739},{"ndv":1,"upper":31,"lower":31,"count":208,"preSum":5950},{"ndv":1,"upper":32,"lower":32,"count":216,"preSum":6158},{"ndv":1,"upper":33,"lower":33,"count":207,"preSum":6374},{"ndv":1,"upper":34,"lower":34,"count":188,"preSum":6581},{"ndv":1,"upper":35,"lower":35,"count":196,"preSum":6769},{"ndv":1,"upper":36,"lower":36,"count":206,"preSum":6965},{"ndv":1,"upper":37,"lower":37,"count":209,"preSum":7171},{"ndv":1,"upper":38,"lower":38,"count":197,"preSum":7380},{"ndv":1,"upper":39,"lower":39,"count":198,"preSum":7577},{"ndv":1,"upper":40,"lower":40,"count":208,"preSum":7775},{"ndv":1,"upper":41,"lower":41,"count":208,"preSum":7983},{"ndv":1,"upper":42,"lower":42,"count":190,"preSum":8191},{"ndv":1,"upper":43,"lower":43,"count":185,"preSum":8381},{"ndv":1,"upper":44,"lower":44,"count":196,"preSum":8566},{"ndv":1,"upper":45,"lower":45,"count":195,"preSum":8762},{"ndv":1,"upper":46,"lower":46,"count":223,"preSum":8957},{"ndv":1,"upper":47,"lower":47,"count":201,"preSum":9180},{"ndv":1,"upper":48,"lower":48,"count":204,"preSum":9381},{"ndv":1,"upper":49,"lower":49,"count":189,"preSum":9585},{"ndv":1,"upper":50,"lower":50,"count":226,"preSum":9774}],"maxBucketSize":64,"type":"Int","sampleRate":0.09926839}
+part.p_type.histogram:
+  {"buckets":[{"ndv":3,"upper":"ECONOMY ANODIZED NIC","lower":"ECONOMY ANODIZED BRA","count":192,"preSum":0},{"ndv":3,"upper":"ECONOMY BRUSHED BRAS","lower":"ECONOMY ANODIZED STE","count":189,"preSum":192},{"ndv":3,"upper":"ECONOMY BRUSHED STEE","lower":"ECONOMY BRUSHED COPP","count":196,"preSum":381},{"ndv":3,"upper":"ECONOMY BURNISHED CO","lower":"ECONOMY BRUSHED TIN","count":199,"preSum":577},{"ndv":3,"upper":"ECONOMY BURNISHED TI","lower":"ECONOMY BURNISHED NI","count":215,"preSum":776},{"ndv":3,"upper":"ECONOMY PLATED NICKE","lower":"ECONOMY PLATED BRASS","count":220,"preSum":991},{"ndv":3,"upper":"ECONOMY POLISHED BRA","lower":"ECONOMY PLATED STEEL","count":190,"preSum":1211},{"ndv":3,"upper":"ECONOMY POLISHED STE","lower":"ECONOMY POLISHED COP","count":203,"preSum":1401},{"ndv":3,"upper":"LARGE ANODIZED COPPE","lower":"ECONOMY POLISHED TIN","count":206,"preSum":1604},{"ndv":3,"upper":"LARGE ANODIZED TIN","lower":"LARGE ANODIZED NICKE","count":217,"preSum":1810},{"ndv":3,"upper":"LARGE BRUSHED NICKEL","lower":"LARGE BRUSHED BRASS","count":202,"preSum":2027},{"ndv":3,"upper":"LARGE BURNISHED BRAS","lower":"LARGE BRUSHED STEEL","count":200,"preSum":2229},{"ndv":3,"upper":"LARGE BURNISHED STEE","lower":"LARGE BURNISHED COPP","count":206,"preSum":2429},{"ndv":3,"upper":"LARGE PLATED COPPER","lower":"LARGE BURNISHED TIN","count":201,"preSum":2635},{"ndv":3,"upper":"LARGE PLATED TIN","lower":"LARGE PLATED NICKEL","count":203,"preSum":2836},{"ndv":3,"upper":"LARGE POLISHED NICKE","lower":"LARGE POLISHED BRASS","count":182,"preSum":3039},{"ndv":2,"upper":"LARGE POLISHED TIN","lower":"LARGE POLISHED STEEL","count":157,"preSum":3221},{"ndv":3,"upper":"MEDIUM ANODIZED NICK","lower":"MEDIUM ANODIZED BRAS","count":192,"preSum":3378},{"ndv":3,"upper":"MEDIUM BRUSHED BRASS","lower":"MEDIUM ANODIZED STEE","count":201,"preSum":3570},{"ndv":3,"upper":"MEDIUM BRUSHED STEEL","lower":"MEDIUM BRUSHED COPPE","count":188,"preSum":3771},{"ndv":3,"upper":"MEDIUM BURNISHED COP","lower":"MEDIUM BRUSHED TIN","count":212,"preSum":3959},{"ndv":3,"upper":"MEDIUM BURNISHED TIN","lower":"MEDIUM BURNISHED NIC","count":218,"preSum":4171},{"ndv":3,"upper":"MEDIUM PLATED NICKEL","lower":"MEDIUM PLATED BRASS","count":215,"preSum":4389},{"ndv":3,"upper":"MEDIUM POLISHED BRAS","lower":"MEDIUM PLATED STEEL","count":209,"preSum":4604},{"ndv":3,"upper":"MEDIUM POLISHED STEE","lower":"MEDIUM POLISHED COPP","count":195,"preSum":4813},{"ndv":3,"upper":"PROMO ANODIZED COPPE","lower":"MEDIUM POLISHED TIN","count":184,"preSum":5008},{"ndv":3,"upper":"PROMO ANODIZED TIN","lower":"PROMO ANODIZED NICKE","count":187,"preSum":5192},{"ndv":3,"upper":"PROMO BRUSHED NICKEL","lower":"PROMO BRUSHED BRASS","count":201,"preSum":5379},{"ndv":3,"upper":"PROMO BURNISHED BRAS","lower":"PROMO BRUSHED STEEL","count":204,"preSum":5580},{"ndv":3,"upper":"PROMO BURNISHED STEE","lower":"PROMO BURNISHED COPP","count":203,"preSum":5784},{"ndv":3,"upper":"PROMO PLATED COPPER","lower":"PROMO BURNISHED TIN","count":195,"preSum":5987},{"ndv":3,"upper":"PROMO PLATED TIN","lower":"PROMO PLATED NICKEL","count":202,"preSum":6182},{"ndv":3,"upper":"PROMO POLISHED NICKE","lower":"PROMO POLISHED BRASS","count":208,"preSum":6384},{"ndv":3,"upper":"SMALL ANODIZED BRASS","lower":"PROMO POLISHED STEEL","count":199,"preSum":6592},{"ndv":3,"upper":"SMALL ANODIZED STEEL","lower":"SMALL ANODIZED COPPE","count":199,"preSum":6791},{"ndv":3,"upper":"SMALL BRUSHED COPPER","lower":"SMALL ANODIZED TIN","count":180,"preSum":6990},{"ndv":3,"upper":"SMALL BRUSHED TIN","lower":"SMALL BRUSHED NICKEL","count":225,"preSum":7170},{"ndv":3,"upper":"SMALL BURNISHED NICK","lower":"SMALL BURNISHED BRAS","count":174,"preSum":7395},{"ndv":3,"upper":"SMALL PLATED BRASS","lower":"SMALL BURNISHED STEE","count":202,"preSum":7569},{"ndv":3,"upper":"SMALL PLATED STEEL","lower":"SMALL PLATED COPPER","count":202,"preSum":7771},{"ndv":3,"upper":"SMALL POLISHED COPPE","lower":"SMALL PLATED TIN","count":176,"preSum":7973},{"ndv":3,"upper":"SMALL POLISHED TIN","lower":"SMALL POLISHED NICKE","count":212,"preSum":8149},{"ndv":3,"upper":"STANDARD ANODIZED NI","lower":"STANDARD ANODIZED BR","count":184,"preSum":8361},{"ndv":3,"upper":"STANDARD BRUSHED BRA","lower":"STANDARD ANODIZED ST","count":177,"preSum":8545},{"ndv":3,"upper":"STANDARD BRUSHED STE","lower":"STANDARD BRUSHED COP","count":200,"preSum":8722},{"ndv":3,"upper":"STANDARD BURNISHED C","lower":"STANDARD BRUSHED TIN","count":190,"preSum":8922},{"ndv":3,"upper":"STANDARD BURNISHED T","lower":"STANDARD BURNISHED N","count":201,"preSum":9112},{"ndv":2,"upper":"STANDARD PLATED COPP","lower":"STANDARD PLATED BRAS","count":159,"preSum":9313},{"ndv":3,"upper":"STANDARD PLATED TIN","lower":"STANDARD PLATED NICK","count":195,"preSum":9472},{"ndv":3,"upper":"STANDARD POLISHED NI","lower":"STANDARD POLISHED BR","count":186,"preSum":9667},{"ndv":2,"upper":"STANDARD POLISHED TI","lower":"STANDARD POLISHED ST","count":147,"preSum":9853}],"maxBucketSize":64,"type":"String","sampleRate":0.09926839}
+partsupp.ps_availqty.histogram:
+  {"buckets":[{"ndv":96,"upper":164,"lower":1,"count":157,"preSum":0},{"ndv":99,"upper":322,"lower":165,"count":157,"preSum":157},{"ndv":105,"upper":470,"lower":324,"count":157,"preSum":314},{"ndv":104,"upper":609,"lower":472,"count":157,"preSum":471},{"ndv":97,"upper":764,"lower":611,"count":157,"preSum":628},{"ndv":97,"upper":903,"lower":765,"count":157,"preSum":785},{"ndv":107,"upper":1072,"lower":905,"count":157,"preSum":942},{"ndv":96,"upper":1240,"lower":1073,"count":157,"preSum":1099},{"ndv":103,"upper":1400,"lower":1242,"count":157,"preSum":1256},{"ndv":104,"upper":1561,"lower":1401,"count":158,"preSum":1413},{"ndv":104,"upper":1736,"lower":1563,"count":159,"preSum":1571},{"ndv":101,"upper":1899,"lower":1738,"count":157,"preSum":1730},{"ndv":92,"upper":2039,"lower":1900,"count":157,"preSum":1887},{"ndv":107,"upper":2207,"lower":2041,"count":157,"preSum":2044},{"ndv":110,"upper":2389,"lower":2208,"count":158,"preSum":2201},{"ndv":98,"upper":2548,"lower":2390,"count":158,"preSum":2359},{"ndv":105,"upper":2711,"lower":2549,"count":160,"preSum":2517},{"ndv":94,"upper":2843,"lower":2712,"count":157,"preSum":2677},{"ndv":93,"upper":3002,"lower":2848,"count":157,"preSum":2834},{"ndv":101,"upper":3169,"lower":3004,"count":157,"preSum":2991},{"ndv":96,"upper":3328,"lower":3171,"count":158,"preSum":3148},{"ndv":91,"upper":3474,"lower":3329,"count":157,"preSum":3306},{"ndv":99,"upper":3620,"lower":3475,"count":158,"preSum":3463},{"ndv":103,"upper":3777,"lower":3621,"count":157,"preSum":3621},{"ndv":100,"upper":3947,"lower":3778,"count":157,"preSum":3778},{"ndv":98,"upper":4109,"lower":3948,"count":157,"preSum":3935},{"ndv":108,"upper":4279,"lower":4112,"count":158,"preSum":4092},{"ndv":102,"upper":4424,"lower":4280,"count":157,"preSum":4250},{"ndv":94,"upper":4560,"lower":4425,"count":158,"preSum":4407},{"ndv":96,"upper":4701,"lower":4562,"count":158,"preSum":4565},{"ndv":100,"upper":4853,"lower":4703,"count":157,"preSum":4723},{"ndv":100,"upper":5010,"lower":4855,"count":157,"preSum":4880},{"ndv":95,"upper":5157,"lower":5012,"count":157,"preSum":5037},{"ndv":110,"upper":5333,"lower":5158,"count":158,"preSum":5194},{"ndv":106,"upper":5517,"lower":5334,"count":157,"preSum":5352},{"ndv":106,"upper":5690,"lower":5518,"count":158,"preSum":5509},{"ndv":93,"upper":5840,"lower":5691,"count":158,"preSum":5667},{"ndv":98,"upper":6017,"lower":5842,"count":158,"preSum":5825},{"ndv":91,"upper":6154,"lower":6018,"count":160,"preSum":5983},{"ndv":103,"upper":6336,"lower":6155,"count":158,"preSum":6143},{"ndv":101,"upper":6483,"lower":6338,"count":157,"preSum":6301},{"ndv":102,"upper":6649,"lower":6484,"count":158,"preSum":6458},{"ndv":106,"upper":6838,"lower":6651,"count":157,"preSum":6616},{"ndv":101,"upper":6996,"lower":6839,"count":157,"preSum":6773},{"ndv":107,"upper":7167,"lower":6997,"count":157,"preSum":6930},{"ndv":108,"upper":7331,"lower":7168,"count":157,"preSum":7087},{"ndv":98,"upper":7485,"lower":7333,"count":157,"preSum":7244},{"ndv":98,"upper":7641,"lower":7486,"count":157,"preSum":7401},{"ndv":105,"upper":7800,"lower":7643,"count":158,"preSum":7558},{"ndv":91,"upper":7932,"lower":7802,"count":157,"preSum":7716},{"ndv":96,"upper":8078,"lower":7933,"count":157,"preSum":7873},{"ndv":103,"upper":8237,"lower":8079,"count":157,"preSum":8030},{"ndv":112,"upper":8422,"lower":8238,"count":158,"preSum":8187},{"ndv":105,"upper":8590,"lower":8423,"count":157,"preSum":8345},{"ndv":97,"upper":8742,"lower":8592,"count":158,"preSum":8502},{"ndv":96,"upper":8870,"lower":8744,"count":158,"preSum":8660},{"ndv":99,"upper":9039,"lower":8871,"count":157,"preSum":8818},{"ndv":101,"upper":9192,"lower":9040,"count":157,"preSum":8975},{"ndv":87,"upper":9323,"lower":9193,"count":157,"preSum":9132},{"ndv":102,"upper":9482,"lower":9324,"count":157,"preSum":9289},{"ndv":93,"upper":9614,"lower":9483,"count":157,"preSum":9446},{"ndv":96,"upper":9757,"lower":9615,"count":158,"preSum":9603},{"ndv":100,"upper":9925,"lower":9758,"count":158,"preSum":9761},{"ndv":43,"upper":9998,"lower":9926,"count":81,"preSum":9919}],"maxBucketSize":64,"type":"Int","sampleRate":0.09866019}
+partsupp.ps_comment.histogram:
+  {"buckets":[{"ndv":140,"upper":" beans around the sl","lower":" about the blithely ","count":157,"preSum":0},{"ndv":145,"upper":" carefully ironic as","lower":" beans dazzle fluffi","count":157,"preSum":157},{"ndv":146,"upper":" excuses. deposits s","lower":" carefully ironic pi","count":157,"preSum":314},{"ndv":137,"upper":" furiously ironic wa","lower":" excuses. quickly da","count":157,"preSum":471},{"ndv":141,"upper":" nag fluffily! quick","lower":" furiously pending p","count":157,"preSum":628},{"ndv":150,"upper":" quickly stealthy id","lower":" nag ironic accounts","count":157,"preSum":785},{"ndv":142,"upper":" slyly at the carefu","lower":" quickly unusual exc","count":157,"preSum":942},{"ndv":145,"upper":" the quick accounts ","lower":" slyly at the slyly ","count":157,"preSum":1099},{"ndv":146,"upper":", regular ideas! car","lower":" the quickly final a","count":157,"preSum":1256},{"ndv":151,"upper":": slyly even request","lower":", regular pinto bean","count":157,"preSum":1413},{"ndv":146,"upper":"against the pending ","lower":": slyly express dolp","count":157,"preSum":1570},{"ndv":156,"upper":"al ideas sleep among","lower":"against the slyly sl","count":157,"preSum":1727},{"ndv":150,"upper":"are carefully regula","lower":"al ideas sleep quick","count":157,"preSum":1884},{"ndv":153,"upper":"beans solve at the b","lower":"are carefully. furio","count":157,"preSum":2041},{"ndv":148,"upper":"c requests. carefull","lower":"beans use doggedly a","count":157,"preSum":2198},{"ndv":144,"upper":"cial theodolites. br","lower":"c requests. slyly ir","count":157,"preSum":2355},{"ndv":151,"upper":"ctions use about the","lower":"cial, final packages","count":157,"preSum":2512},{"ndv":153,"upper":"ding to the accounts","lower":"ctions. carefully bo","count":157,"preSum":2669},{"ndv":144,"upper":"e furiously even sau","lower":"ding to the blithely","count":157,"preSum":2826},{"ndv":154,"upper":"eas. dependencies ha","lower":"e furiously even the","count":157,"preSum":2983},{"ndv":144,"upper":"egular sauternes. sl","lower":"eas. furiously final","count":157,"preSum":3140},{"ndv":150,"upper":"ents wake slyly. bli","lower":"egular sentiments bo","count":157,"preSum":3297},{"ndv":151,"upper":"es are fluffily at t","lower":"ents. slyly unusual ","count":157,"preSum":3454},{"ndv":152,"upper":"ests. platelets thra","lower":"es are furiously reg","count":157,"preSum":3611},{"ndv":154,"upper":"final dinos use furi","lower":"ests. quickly even r","count":157,"preSum":3768},{"ndv":147,"upper":"furiously ironic req","lower":"final dolphins wake ","count":157,"preSum":3925},{"ndv":147,"upper":"ggle. slyly bold exc","lower":"furiously ironic the","count":157,"preSum":4082},{"ndv":149,"upper":"he ironic asymptotes","lower":"gh the accounts. car","count":157,"preSum":4239},{"ndv":149,"upper":"ic deposits are perm","lower":"he ironic excuses. f","count":157,"preSum":4396},{"ndv":153,"upper":"inal asymptotes snoo","lower":"ic deposits eat agai","count":157,"preSum":4553},{"ndv":148,"upper":"ions. furiously unus","lower":"inal asymptotes wake","count":157,"preSum":4710},{"ndv":152,"upper":"ithely special depen","lower":"ions. ironic courts ","count":157,"preSum":4867},{"ndv":152,"upper":"kly unusual accounts","lower":"ithely special packa","count":157,"preSum":5024},{"ndv":153,"upper":"latelets sleep slyly","lower":"kly unusual, ironic ","count":157,"preSum":5181},{"ndv":154,"upper":"lithely even account","lower":"latelets solve blith","count":159,"preSum":5338},{"ndv":150,"upper":"ly above the even pi","lower":"lithely even ideas. ","count":157,"preSum":5497},{"ndv":145,"upper":"ly ironic theodolite","lower":"ly above the furious","count":159,"preSum":5654},{"ndv":131,"upper":"lyly regular deposit","lower":"ly ironic tithes. ir","count":157,"preSum":5813},{"ndv":152,"upper":"nding dependencies. ","lower":"lyly regular foxes i","count":158,"preSum":5970},{"ndv":154,"upper":"ns nag slyly quickly","lower":"nding deposits unwin","count":157,"preSum":6128},{"ndv":153,"upper":"o beans haggle quick","lower":"ns print according t","count":157,"preSum":6285},{"ndv":154,"upper":"onic packages wake a","lower":"o beans haggle until","count":157,"preSum":6442},{"ndv":153,"upper":"otes. carefully fina","lower":"onic packages. final","count":157,"preSum":6599},{"ndv":148,"upper":"oxes! carefully fina","lower":"otes. carefully sile","count":157,"preSum":6756},{"ndv":152,"upper":"phs serve furiously ","lower":"oxes. blithely final","count":157,"preSum":6913},{"ndv":154,"upper":"quickly along the bl","lower":"pinto beans affix fu","count":157,"preSum":7070},{"ndv":149,"upper":"refully special plat","lower":"quickly along the ev","count":157,"preSum":7227},{"ndv":140,"upper":"riously bold account","lower":"refully unusual acco","count":157,"preSum":7384},{"ndv":144,"upper":"s across the deposit","lower":"riously bold ideas c","count":157,"preSum":7541},{"ndv":157,"upper":"s sleep furiously ab","lower":"s across the quickly","count":157,"preSum":7698},{"ndv":146,"upper":"s. slyly silent depe","lower":"s sleep furiously al","count":157,"preSum":7855},{"ndv":153,"upper":"sly bold instruction","lower":"s. slyly unusual ins","count":157,"preSum":8012},{"ndv":146,"upper":"ss the foxes. theodo","lower":"sly busy accounts ar","count":157,"preSum":8169},{"ndv":155,"upper":"t the final pains. t","lower":"ss the ironic deposi","count":157,"preSum":8326},{"ndv":152,"upper":"the quickly final in","lower":"t the final, even do","count":157,"preSum":8483},{"ndv":150,"upper":"to beans. furiously ","lower":"the quickly ironic i","count":157,"preSum":8640},{"ndv":150,"upper":"ts. quickly special ","lower":"to beans. slyly iron","count":157,"preSum":8797},{"ndv":154,"upper":"ular accounts wake s","lower":"ts. regular packages","count":157,"preSum":8954},{"ndv":149,"upper":"unts. packages wake.","lower":"ular accounts. regul","count":157,"preSum":9111},{"ndv":148,"upper":"usly final theodolit","lower":"unts. quickly even r","count":158,"preSum":9268},{"ndv":150,"upper":"x furiously. regular","lower":"usly fluffy deposits","count":157,"preSum":9426},{"ndv":147,"upper":"y express packages! ","lower":"x into the blithely ","count":157,"preSum":9583},{"ndv":132,"upper":"y unusual packages w","lower":"y express theodolite","count":157,"preSum":9740},{"ndv":96,"upper":"zzle silently. even,","lower":"y unusual pinto bean","count":103,"preSum":9897}],"maxBucketSize":64,"type":"String","sampleRate":0.09866019}
+partsupp.ps_partkey.histogram:
+  {"buckets":[{"ndv":157,"upper":304497,"lower":1449,"count":157,"preSum":0},{"ndv":157,"upper":613901,"lower":304792,"count":157,"preSum":157},{"ndv":157,"upper":928266,"lower":614351,"count":157,"preSum":314},{"ndv":157,"upper":1259887,"lower":929444,"count":157,"preSum":471},{"ndv":157,"upper":1596605,"lower":1260906,"count":157,"preSum":628},{"ndv":156,"upper":1927184,"lower":1598584,"count":157,"preSum":785},{"ndv":157,"upper":2225584,"lower":1928758,"count":157,"preSum":942},{"ndv":157,"upper":2553931,"lower":2226013,"count":157,"preSum":1099},{"ndv":157,"upper":2825839,"lower":2557823,"count":157,"preSum":1256},{"ndv":157,"upper":3160030,"lower":2826556,"count":157,"preSum":1413},{"ndv":157,"upper":3481857,"lower":3160516,"count":157,"preSum":1570},{"ndv":157,"upper":3812822,"lower":3482594,"count":157,"preSum":1727},{"ndv":157,"upper":4093873,"lower":3813580,"count":157,"preSum":1884},{"ndv":157,"upper":4437376,"lower":4097553,"count":157,"preSum":2041},{"ndv":157,"upper":4755204,"lower":4437833,"count":157,"preSum":2198},{"ndv":157,"upper":5095606,"lower":4755668,"count":157,"preSum":2355},{"ndv":157,"upper":5392324,"lower":5096509,"count":157,"preSum":2512},{"ndv":157,"upper":5722933,"lower":5394737,"count":157,"preSum":2669},{"ndv":157,"upper":6049875,"lower":5725773,"count":157,"preSum":2826},{"ndv":157,"upper":6353771,"lower":6050229,"count":157,"preSum":2983},{"ndv":157,"upper":6620543,"lower":6354866,"count":157,"preSum":3140},{"ndv":157,"upper":6931226,"lower":6621146,"count":157,"preSum":3297},{"ndv":157,"upper":7212326,"lower":6931666,"count":157,"preSum":3454},{"ndv":157,"upper":7530282,"lower":7212601,"count":157,"preSum":3611},{"ndv":157,"upper":7850951,"lower":7532083,"count":157,"preSum":3768},{"ndv":157,"upper":8157995,"lower":7851023,"count":157,"preSum":3925},{"ndv":157,"upper":8454982,"lower":8158089,"count":157,"preSum":4082},{"ndv":157,"upper":8801972,"lower":8458480,"count":157,"preSum":4239},{"ndv":157,"upper":9165346,"lower":8801981,"count":157,"preSum":4396},{"ndv":157,"upper":9475979,"lower":9170331,"count":157,"preSum":4553},{"ndv":157,"upper":9765312,"lower":9480402,"count":157,"preSum":4710},{"ndv":157,"upper":10096739,"lower":9771098,"count":157,"preSum":4867},{"ndv":157,"upper":10389939,"lower":10099569,"count":157,"preSum":5024},{"ndv":157,"upper":10686961,"lower":10392325,"count":157,"preSum":5181},{"ndv":157,"upper":10985964,"lower":10687565,"count":157,"preSum":5338},{"ndv":157,"upper":11299495,"lower":10986254,"count":157,"preSum":5495},{"ndv":157,"upper":11606818,"lower":11301698,"count":157,"preSum":5652},{"ndv":157,"upper":11949976,"lower":11607555,"count":157,"preSum":5809},{"ndv":157,"upper":12253020,"lower":11952520,"count":157,"preSum":5966},{"ndv":157,"upper":12558242,"lower":12254974,"count":157,"preSum":6123},{"ndv":157,"upper":12889631,"lower":12563218,"count":157,"preSum":6280},{"ndv":157,"upper":13195412,"lower":12889897,"count":157,"preSum":6437},{"ndv":157,"upper":13507340,"lower":13199883,"count":157,"preSum":6594},{"ndv":157,"upper":13836578,"lower":13507961,"count":157,"preSum":6751},{"ndv":157,"upper":14195776,"lower":13837446,"count":157,"preSum":6908},{"ndv":157,"upper":14496257,"lower":14197556,"count":157,"preSum":7065},{"ndv":157,"upper":14804434,"lower":14498859,"count":157,"preSum":7222},{"ndv":157,"upper":15100866,"lower":14806805,"count":157,"preSum":7379},{"ndv":157,"upper":15379531,"lower":15109303,"count":157,"preSum":7536},{"ndv":157,"upper":15664008,"lower":15380003,"count":157,"preSum":7693},{"ndv":157,"upper":15957787,"lower":15666930,"count":157,"preSum":7850},{"ndv":157,"upper":16230510,"lower":15959390,"count":157,"preSum":8007},{"ndv":157,"upper":16529776,"lower":16230830,"count":157,"preSum":8164},{"ndv":157,"upper":16855942,"lower":16534554,"count":157,"preSum":8321},{"ndv":157,"upper":17171801,"lower":16857565,"count":157,"preSum":8478},{"ndv":157,"upper":17470962,"lower":17175030,"count":157,"preSum":8635},{"ndv":157,"upper":17784274,"lower":17471161,"count":157,"preSum":8792},{"ndv":157,"upper":18098494,"lower":17786857,"count":157,"preSum":8949},{"ndv":157,"upper":18439650,"lower":18098753,"count":157,"preSum":9106},{"ndv":157,"upper":18735417,"lower":18443305,"count":157,"preSum":9263},{"ndv":157,"upper":19022763,"lower":18739424,"count":157,"preSum":9420},{"ndv":157,"upper":19391777,"lower":19026992,"count":157,"preSum":9577},{"ndv":157,"upper":19722944,"lower":19394175,"count":157,"preSum":9734},{"ndv":109,"upper":19998974,"lower":19727194,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Int","sampleRate":0.09866019}
+partsupp.ps_suppkey.histogram:
+  {"buckets":[{"ndv":156,"upper":16756,"lower":30,"count":157,"preSum":0},{"ndv":155,"upper":30887,"lower":16925,"count":157,"preSum":157},{"ndv":156,"upper":46810,"lower":30895,"count":157,"preSum":314},{"ndv":157,"upper":62640,"lower":47217,"count":157,"preSum":471},{"ndv":157,"upper":80924,"lower":62675,"count":157,"preSum":628},{"ndv":157,"upper":97802,"lower":81103,"count":157,"preSum":785},{"ndv":156,"upper":114126,"lower":97963,"count":157,"preSum":942},{"ndv":157,"upper":128368,"lower":114277,"count":157,"preSum":1099},{"ndv":156,"upper":142301,"lower":128607,"count":157,"preSum":1256},{"ndv":156,"upper":159901,"lower":142494,"count":157,"preSum":1413},{"ndv":157,"upper":173322,"lower":159954,"count":157,"preSum":1570},{"ndv":156,"upper":189616,"lower":173407,"count":157,"preSum":1727},{"ndv":156,"upper":206691,"lower":189623,"count":157,"preSum":1884},{"ndv":155,"upper":223568,"lower":206731,"count":157,"preSum":2041},{"ndv":156,"upper":239916,"lower":223585,"count":157,"preSum":2198},{"ndv":155,"upper":255227,"lower":239981,"count":157,"preSum":2355},{"ndv":157,"upper":272029,"lower":255308,"count":157,"preSum":2512},{"ndv":156,"upper":286244,"lower":272144,"count":157,"preSum":2669},{"ndv":156,"upper":300196,"lower":286283,"count":157,"preSum":2826},{"ndv":155,"upper":314845,"lower":300264,"count":157,"preSum":2983},{"ndv":156,"upper":331960,"lower":314847,"count":157,"preSum":3140},{"ndv":156,"upper":349391,"lower":332100,"count":157,"preSum":3297},{"ndv":156,"upper":367101,"lower":349513,"count":157,"preSum":3454},{"ndv":157,"upper":384092,"lower":367323,"count":157,"preSum":3611},{"ndv":157,"upper":398815,"lower":384134,"count":157,"preSum":3768},{"ndv":157,"upper":412538,"lower":398819,"count":157,"preSum":3925},{"ndv":154,"upper":429444,"lower":412894,"count":157,"preSum":4082},{"ndv":156,"upper":442462,"lower":429475,"count":157,"preSum":4239},{"ndv":157,"upper":460550,"lower":442469,"count":157,"preSum":4396},{"ndv":155,"upper":476370,"lower":460656,"count":157,"preSum":4553},{"ndv":156,"upper":492412,"lower":476413,"count":157,"preSum":4710},{"ndv":156,"upper":508051,"lower":492437,"count":157,"preSum":4867},{"ndv":156,"upper":524069,"lower":508253,"count":157,"preSum":5024},{"ndv":157,"upper":539789,"lower":524087,"count":157,"preSum":5181},{"ndv":156,"upper":553935,"lower":539819,"count":157,"preSum":5338},{"ndv":155,"upper":571423,"lower":554076,"count":157,"preSum":5495},{"ndv":157,"upper":586472,"lower":571447,"count":157,"preSum":5652},{"ndv":157,"upper":601980,"lower":586572,"count":157,"preSum":5809},{"ndv":156,"upper":618297,"lower":602149,"count":157,"preSum":5966},{"ndv":156,"upper":633069,"lower":618416,"count":157,"preSum":6123},{"ndv":157,"upper":647399,"lower":633089,"count":157,"preSum":6280},{"ndv":156,"upper":663968,"lower":647532,"count":157,"preSum":6437},{"ndv":157,"upper":679770,"lower":664241,"count":157,"preSum":6594},{"ndv":156,"upper":696658,"lower":679938,"count":157,"preSum":6751},{"ndv":157,"upper":711721,"lower":696753,"count":157,"preSum":6908},{"ndv":157,"upper":727037,"lower":711744,"count":157,"preSum":7065},{"ndv":157,"upper":741354,"lower":727258,"count":157,"preSum":7222},{"ndv":157,"upper":756779,"lower":741460,"count":157,"preSum":7379},{"ndv":157,"upper":770813,"lower":756826,"count":157,"preSum":7536},{"ndv":156,"upper":786540,"lower":770931,"count":157,"preSum":7693},{"ndv":157,"upper":802227,"lower":786672,"count":157,"preSum":7850},{"ndv":156,"upper":819056,"lower":802610,"count":157,"preSum":8007},{"ndv":157,"upper":835729,"lower":819122,"count":157,"preSum":8164},{"ndv":156,"upper":849455,"lower":835783,"count":157,"preSum":8321},{"ndv":155,"upper":865134,"lower":849483,"count":157,"preSum":8478},{"ndv":157,"upper":882109,"lower":865146,"count":157,"preSum":8635},{"ndv":157,"upper":896958,"lower":882117,"count":157,"preSum":8792},{"ndv":156,"upper":911426,"lower":897013,"count":157,"preSum":8949},{"ndv":156,"upper":926728,"lower":911437,"count":157,"preSum":9106},{"ndv":157,"upper":943102,"lower":926785,"count":157,"preSum":9263},{"ndv":156,"upper":958023,"lower":943241,"count":157,"preSum":9420},{"ndv":156,"upper":974656,"lower":958030,"count":157,"preSum":9577},{"ndv":157,"upper":990164,"lower":974658,"count":157,"preSum":9734},{"ndv":108,"upper":999983,"lower":990187,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Int","sampleRate":0.09866019}
+partsupp.ps_supplycost.histogram:
+  {"buckets":[{"ndv":150,"upper":16.98,"lower":1.00,"count":157,"preSum":0},{"ndv":146,"upper":30.97,"lower":17.00,"count":157,"preSum":157},{"ndv":148,"upper":46.95,"lower":31.03,"count":157,"preSum":314},{"ndv":150,"upper":63.19,"lower":46.99,"count":157,"preSum":471},{"ndv":147,"upper":77.27,"lower":63.26,"count":158,"preSum":628},{"ndv":154,"upper":92.41,"lower":77.38,"count":157,"preSum":786},{"ndv":153,"upper":109.80,"lower":92.61,"count":157,"preSum":943},{"ndv":148,"upper":126.16,"lower":109.99,"count":157,"preSum":1100},{"ndv":146,"upper":142.66,"lower":126.18,"count":157,"preSum":1257},{"ndv":145,"upper":159.24,"lower":142.76,"count":157,"preSum":1414},{"ndv":154,"upper":177.51,"lower":159.44,"count":157,"preSum":1571},{"ndv":154,"upper":194.25,"lower":177.69,"count":157,"preSum":1728},{"ndv":146,"upper":207.55,"lower":194.49,"count":157,"preSum":1885},{"ndv":151,"upper":224.76,"lower":207.65,"count":157,"preSum":2042},{"ndv":147,"upper":239.44,"lower":224.79,"count":157,"preSum":2199},{"ndv":148,"upper":254.50,"lower":239.48,"count":157,"preSum":2356},{"ndv":148,"upper":270.63,"lower":254.51,"count":157,"preSum":2513},{"ndv":149,"upper":287.85,"lower":270.64,"count":157,"preSum":2670},{"ndv":149,"upper":303.30,"lower":288.02,"count":157,"preSum":2827},{"ndv":150,"upper":317.18,"lower":303.51,"count":157,"preSum":2984},{"ndv":152,"upper":334.42,"lower":317.33,"count":157,"preSum":3141},{"ndv":148,"upper":348.19,"lower":334.44,"count":157,"preSum":3298},{"ndv":152,"upper":364.14,"lower":348.20,"count":158,"preSum":3455},{"ndv":151,"upper":378.75,"lower":364.32,"count":157,"preSum":3613},{"ndv":145,"upper":392.59,"lower":378.94,"count":157,"preSum":3770},{"ndv":149,"upper":405.60,"lower":392.66,"count":157,"preSum":3927},{"ndv":150,"upper":422.94,"lower":405.64,"count":157,"preSum":4084},{"ndv":148,"upper":437.00,"lower":423.01,"count":157,"preSum":4241},{"ndv":149,"upper":452.02,"lower":437.10,"count":157,"preSum":4398},{"ndv":149,"upper":468.26,"lower":452.15,"count":157,"preSum":4555},{"ndv":147,"upper":482.06,"lower":468.36,"count":157,"preSum":4712},{"ndv":148,"upper":496.43,"lower":482.19,"count":157,"preSum":4869},{"ndv":152,"upper":511.45,"lower":496.48,"count":157,"preSum":5026},{"ndv":151,"upper":525.90,"lower":511.52,"count":157,"preSum":5183},{"ndv":147,"upper":539.90,"lower":526.11,"count":157,"preSum":5340},{"ndv":149,"upper":558.87,"lower":539.98,"count":157,"preSum":5497},{"ndv":146,"upper":572.57,"lower":559.03,"count":157,"preSum":5654},{"ndv":147,"upper":588.49,"lower":572.58,"count":157,"preSum":5811},{"ndv":151,"upper":605.30,"lower":588.50,"count":157,"preSum":5968},{"ndv":147,"upper":621.52,"lower":605.66,"count":157,"preSum":6125},{"ndv":149,"upper":638.14,"lower":621.59,"count":157,"preSum":6282},{"ndv":152,"upper":657.69,"lower":638.16,"count":157,"preSum":6439},{"ndv":151,"upper":674.00,"lower":657.91,"count":157,"preSum":6596},{"ndv":154,"upper":690.30,"lower":674.33,"count":157,"preSum":6753},{"ndv":152,"upper":706.24,"lower":690.45,"count":158,"preSum":6910},{"ndv":145,"upper":720.57,"lower":706.26,"count":157,"preSum":7068},{"ndv":151,"upper":736.28,"lower":720.63,"count":157,"preSum":7225},{"ndv":149,"upper":752.49,"lower":736.30,"count":157,"preSum":7382},{"ndv":150,"upper":768.17,"lower":752.50,"count":157,"preSum":7539},{"ndv":149,"upper":785.34,"lower":768.18,"count":157,"preSum":7696},{"ndv":149,"upper":800.89,"lower":785.48,"count":157,"preSum":7853},{"ndv":149,"upper":818.38,"lower":800.90,"count":157,"preSum":8010},{"ndv":149,"upper":833.95,"lower":818.56,"count":157,"preSum":8167},{"ndv":149,"upper":847.76,"lower":833.99,"count":157,"preSum":8324},{"ndv":150,"upper":864.08,"lower":847.78,"count":158,"preSum":8481},{"ndv":146,"upper":880.67,"lower":864.19,"count":157,"preSum":8639},{"ndv":150,"upper":896.98,"lower":880.75,"count":157,"preSum":8796},{"ndv":149,"upper":913.55,"lower":897.12,"count":157,"preSum":8953},{"ndv":149,"upper":928.41,"lower":913.63,"count":157,"preSum":9110},{"ndv":150,"upper":943.55,"lower":928.64,"count":157,"preSum":9267},{"ndv":154,"upper":960.70,"lower":943.80,"count":157,"preSum":9424},{"ndv":152,"upper":974.36,"lower":960.88,"count":157,"preSum":9581},{"ndv":146,"upper":988.92,"lower":974.38,"count":157,"preSum":9738},{"ndv":102,"upper":1000.00,"lower":988.94,"count":105,"preSum":9895}],"maxBucketSize":64,"type":"Double","sampleRate":0.09866019}
+region.r_comment.histogram:
+  {"buckets":[{"ndv":2,"upper":"hs use ironic, even ","lower":"ges. thinly even pin","count":2,"preSum":0},{"ndv":2,"upper":"ly final courts cajo","lower":"lar deposits. blithe","count":2,"preSum":2},{"ndv":1,"upper":"uickly special accou","lower":"uickly special accou","count":1,"preSum":4}],"maxBucketSize":4,"type":"String","sampleRate":1.0}
+region.r_name.histogram:
+  {"buckets":[{"ndv":2,"upper":"AMERICA","lower":"AFRICA","count":2,"preSum":0},{"ndv":2,"upper":"EUROPE","lower":"ASIA","count":2,"preSum":2},{"ndv":1,"upper":"MIDDLE EAST","lower":"MIDDLE EAST","count":1,"preSum":4}],"maxBucketSize":4,"type":"String","sampleRate":1.0}
+region.r_regionkey.histogram:
+  {"buckets":[{"ndv":2,"upper":1,"lower":0,"count":2,"preSum":0},{"ndv":2,"upper":3,"lower":2,"count":2,"preSum":2},{"ndv":1,"upper":4,"lower":4,"count":1,"preSum":4}],"maxBucketSize":4,"type":"Int","sampleRate":1.0}
+supplier.s_acctbal.histogram:
+  {"buckets":[{"ndv":157,"upper":-828.40,"lower":-998.83,"count":157,"preSum":0},{"ndv":155,"upper":-672.63,"lower":-828.24,"count":157,"preSum":157},{"ndv":157,"upper":-501.60,"lower":-668.92,"count":157,"preSum":314},{"ndv":156,"upper":-329.17,"lower":-501.56,"count":157,"preSum":471},{"ndv":156,"upper":-163.36,"lower":-328.67,"count":157,"preSum":628},{"ndv":157,"upper":12.31,"lower":-162.48,"count":157,"preSum":785},{"ndv":156,"upper":178.90,"lower":12.33,"count":157,"preSum":942},{"ndv":157,"upper":329.72,"lower":179.99,"count":157,"preSum":1099},{"ndv":157,"upper":517.42,"lower":333.05,"count":157,"preSum":1256},{"ndv":156,"upper":665.32,"lower":517.86,"count":157,"preSum":1413},{"ndv":157,"upper":851.85,"lower":669.12,"count":157,"preSum":1570},{"ndv":156,"upper":1007.69,"lower":852.83,"count":157,"preSum":1727},{"ndv":157,"upper":1216.63,"lower":1011.97,"count":157,"preSum":1884},{"ndv":157,"upper":1394.31,"lower":1216.80,"count":157,"preSum":2041},{"ndv":156,"upper":1562.49,"lower":1400.22,"count":157,"preSum":2198},{"ndv":157,"upper":1738.87,"lower":1563.76,"count":157,"preSum":2355},{"ndv":157,"upper":1938.02,"lower":1739.94,"count":157,"preSum":2512},{"ndv":155,"upper":2121.56,"lower":1939.36,"count":157,"preSum":2669},{"ndv":156,"upper":2329.48,"lower":2123.28,"count":157,"preSum":2826},{"ndv":156,"upper":2522.85,"lower":2336.07,"count":157,"preSum":2983},{"ndv":155,"upper":2687.62,"lower":2522.92,"count":157,"preSum":3140},{"ndv":156,"upper":2859.42,"lower":2687.85,"count":157,"preSum":3297},{"ndv":156,"upper":3056.12,"lower":2859.63,"count":157,"preSum":3454},{"ndv":155,"upper":3196.07,"lower":3058.39,"count":157,"preSum":3611},{"ndv":156,"upper":3345.83,"lower":3199.55,"count":157,"preSum":3768},{"ndv":156,"upper":3491.43,"lower":3346.76,"count":157,"preSum":3925},{"ndv":157,"upper":3663.26,"lower":3494.95,"count":157,"preSum":4082},{"ndv":157,"upper":3835.41,"lower":3665.49,"count":157,"preSum":4239},{"ndv":157,"upper":4010.17,"lower":3837.45,"count":157,"preSum":4396},{"ndv":157,"upper":4197.67,"lower":4011.75,"count":157,"preSum":4553},{"ndv":157,"upper":4367.12,"lower":4199.79,"count":157,"preSum":4710},{"ndv":157,"upper":4565.82,"lower":4369.39,"count":157,"preSum":4867},{"ndv":155,"upper":4722.59,"lower":4567.01,"count":157,"preSum":5024},{"ndv":156,"upper":4909.91,"lower":4723.20,"count":157,"preSum":5181},{"ndv":156,"upper":5079.66,"lower":4910.00,"count":157,"preSum":5338},{"ndv":157,"upper":5259.27,"lower":5080.19,"count":157,"preSum":5495},{"ndv":157,"upper":5436.21,"lower":5259.69,"count":157,"preSum":5652},{"ndv":157,"upper":5617.80,"lower":5437.45,"count":157,"preSum":5809},{"ndv":154,"upper":5766.44,"lower":5617.81,"count":157,"preSum":5966},{"ndv":157,"upper":5930.86,"lower":5767.47,"count":157,"preSum":6123},{"ndv":156,"upper":6104.32,"lower":5930.94,"count":157,"preSum":6280},{"ndv":156,"upper":6281.27,"lower":6106.97,"count":157,"preSum":6437},{"ndv":156,"upper":6426.46,"lower":6281.97,"count":158,"preSum":6594},{"ndv":157,"upper":6602.54,"lower":6426.54,"count":157,"preSum":6752},{"ndv":156,"upper":6790.01,"lower":6602.81,"count":157,"preSum":6909},{"ndv":157,"upper":6973.12,"lower":6791.54,"count":157,"preSum":7066},{"ndv":157,"upper":7142.61,"lower":6973.34,"count":157,"preSum":7223},{"ndv":156,"upper":7326.14,"lower":7142.98,"count":157,"preSum":7380},{"ndv":157,"upper":7510.89,"lower":7326.79,"count":157,"preSum":7537},{"ndv":157,"upper":7698.24,"lower":7511.19,"count":157,"preSum":7694},{"ndv":155,"upper":7884.67,"lower":7698.47,"count":157,"preSum":7851},{"ndv":156,"upper":8044.32,"lower":7884.69,"count":157,"preSum":8008},{"ndv":156,"upper":8209.71,"lower":8045.64,"count":157,"preSum":8165},{"ndv":157,"upper":8371.57,"lower":8209.81,"count":157,"preSum":8322},{"ndv":157,"upper":8545.74,"lower":8374.81,"count":157,"preSum":8479},{"ndv":156,"upper":8725.39,"lower":8546.66,"count":157,"preSum":8636},{"ndv":156,"upper":8902.73,"lower":8725.47,"count":157,"preSum":8793},{"ndv":157,"upper":9067.42,"lower":8902.78,"count":157,"preSum":8950},{"ndv":157,"upper":9221.94,"lower":9067.98,"count":157,"preSum":9107},{"ndv":155,"upper":9375.30,"lower":9222.77,"count":157,"preSum":9264},{"ndv":157,"upper":9527.24,"lower":9378.24,"count":157,"preSum":9421},{"ndv":156,"upper":9701.60,"lower":9527.51,"count":157,"preSum":9578},{"ndv":157,"upper":9870.99,"lower":9703.18,"count":157,"preSum":9735},{"ndv":108,"upper":9998.93,"lower":9871.51,"count":108,"preSum":9892}],"maxBucketSize":64,"type":"Double","sampleRate":0.09891001}
+supplier.s_address.histogram:
+  {"buckets":[{"ndv":157,"upper":" xO,tcKMOuWLraK7L91t","lower":"  ,gSJkoBfKoCYClIfNA","count":157,"preSum":0},{"ndv":157,"upper":",xmBpklOBBO,uNnik0Fa","lower":" YfBSq IEt5u","count":157,"preSum":157},{"ndv":157,"upper":"0xj5ejtW7je97f7N32th","lower":",XpDLT tS2qIVSNCDCqV","count":157,"preSum":314},{"ndv":157,"upper":"1xXxfbF0rrG","lower":"0y17FOY4zqXbYHMfs9Tk","count":157,"preSum":471},{"ndv":157,"upper":"2xvEChyqj1Ktqth","lower":"1y17b78azxw k","count":157,"preSum":628},{"ndv":157,"upper":"3WjF7XpOlTSbwJAkv76n","lower":"2Xy2  P, oM51PrkUdaU","count":157,"preSum":785},{"ndv":157,"upper":"4XD0QB NZV EAi,cD3tF","lower":"3WJpnfVgMBp5Hfj79T1Y","count":157,"preSum":942},{"ndv":157,"upper":"5tR8ZX4ck6WJwKvu2,XQ","lower":"4xe25bA8NbiYlGq6NcjH","count":157,"preSum":1099},{"ndv":157,"upper":"6RqQgBYKsXAWlSxrLdwc","lower":"5U6xArmPopXUDr4n15jR","count":157,"preSum":1256},{"ndv":157,"upper":"7Sg924dPFefLgOdacEPg","lower":"6rv9DKj3rkXZK1cXjSvv","count":157,"preSum":1413},{"ndv":157,"upper":"8rRJgBI9m,Qk","lower":"7sL2MBjAZa5LTRT6vnMl","count":157,"preSum":1570},{"ndv":157,"upper":"9tW5yQAu03b4","lower":"8rYoRbZtFkwuJ sxp","count":157,"preSum":1727},{"ndv":157,"upper":"AgFmD3PBOm1DFlaxLLH,","lower":"9UcFEFXLv9N97KP4fn,,","count":157,"preSum":1884},{"ndv":157,"upper":"aWJmg3qIX1yahTIgZxzj","lower":"AgLIfv1gsTp QO2IzATV","count":157,"preSum":2041},{"ndv":157,"upper":"bhM,mBbjz4UF52is01vy","lower":"aWkkRXCT2k6wXz1h4","count":157,"preSum":2198},{"ndv":157,"upper":"BxYCRWJ0eT0TxyCxiR","lower":"bHNQGmjIiWLHNRI2c5Xf","count":157,"preSum":2355},{"ndv":157,"upper":"CgR0Qfr3EMpvy2k","lower":"by Hn1 8JUK","count":157,"preSum":2512},{"ndv":157,"upper":"CV hmb2qQxxlI7gUFGio","lower":"CgSID02Fa VkNzF4sdQr","count":157,"preSum":2669},{"ndv":157,"upper":"DEXCe5ylDsv6CJ YZmuc","lower":"cV1RkNcmKTicP","count":157,"preSum":2826},{"ndv":157,"upper":"duTlvDx0xG3yWgEcjE1t","lower":"DeZravXLNS4wrjP9vZqq","count":157,"preSum":2983},{"ndv":157,"upper":"EEjhAanr,z","lower":"dV413PJeLfJRAH2ZD09c","count":157,"preSum":3140},{"ndv":157,"upper":"evkA7vueCp9gBac91","lower":"Eely2UNQP5","count":157,"preSum":3297},{"ndv":157,"upper":"fGDv5PPINRwI5","lower":"eVQaWlA9jsgxBUDn1ANJ","count":157,"preSum":3454},{"ndv":157,"upper":"fUpTtac4o7DugP0Loojr","lower":"FgeYaNoRGj","count":157,"preSum":3611},{"ndv":157,"upper":"GfqJExS8JqlGC","lower":"FurkdkXbXKg7b Bh3qyA","count":157,"preSum":3768},{"ndv":157,"upper":"gx BaV,j0nX0L3jnL4RY","lower":"GGaSFyVfmYiMjItDCMyA","count":157,"preSum":3925},{"ndv":157,"upper":"HiTvBwHNSYR,1y6I4xVi","lower":"GXi,YNTT8U615jdEBwad","count":157,"preSum":4082},{"ndv":157,"upper":"I Yceh,KYI4xc5OE3Xpp","lower":"hIUxWd2uU3kAgZDYSQPQ","count":157,"preSum":4239},{"ndv":157,"upper":"ilyfT4q21TMX7vowjzwl","lower":"i,4byNi5bb6s5rbO,","count":157,"preSum":4396},{"ndv":157,"upper":"j6DAnoha5qy","lower":"ILyWxsTwAr4O1uo2b5FQ","count":157,"preSum":4553},{"ndv":157,"upper":"jmo8deK5NjQFM075cyOs","lower":"j6eYQ,in1wvpSc6","count":157,"preSum":4710},{"ndv":157,"upper":"K38BGN1ceEL2C","lower":"JmpBMwHscqERB3WzWkgL","count":157,"preSum":4867},{"ndv":157,"upper":"KnTph3ovyzs1ztRwceo9","lower":"k3DYFKaWwtBNXhMFS7Ow","count":157,"preSum":5024},{"ndv":157,"upper":"L4J30MitTgdxEkqlcbz ","lower":"kNV3iE0K23","count":157,"preSum":5181},{"ndv":157,"upper":"LQ1Jj7N6Asj0eok6 J5 ","lower":"L4n9ChBvabZdTKLcNpkI","count":157,"preSum":5338},{"ndv":157,"upper":"m7q0G2PW9T8EsVTmAOSX","lower":"Lqa5tkDONR06tkoBoh z","count":157,"preSum":5495},{"ndv":157,"upper":"mqvJAdeXVjwtPsreLGkI","lower":"m7y2m19OcOnb4aBIc0f","count":157,"preSum":5652},{"ndv":157,"upper":"NA4VYTArbtHdRV ","lower":"Mr,1uTnhUsPCh14laFVF","count":157,"preSum":5809},{"ndv":157,"upper":"NQOoC,FKl maZpatEcjF","lower":"NAAo98VwSnfQXyOBs,kv","count":157,"preSum":5966},{"ndv":157,"upper":"OAzaHpbq88DvzioCH2CL","lower":"NQvbXliymKFBV57z","count":157,"preSum":6123},{"ndv":157,"upper":"oRwOdFMASiIHfx4pzyxR","lower":"OAZhSUuQbiLH1ayJLb4S","count":157,"preSum":6280},{"ndv":157,"upper":"pCrvvfg2dS71Qa01fNDr","lower":"ORXDTHTn5aVTz39ljM56","count":157,"preSum":6437},{"ndv":157,"upper":"PQZspkoyV9WUqqGJ","lower":"PCS,E rSC3MbzdqmzAis","count":157,"preSum":6594},{"ndv":157,"upper":"qAI4joKRuV0UgUXEDD2y","lower":"Pr8YzaWZMaWhv3c5KnbD","count":157,"preSum":6751},{"ndv":157,"upper":"qqASkn9T1hFmw,3vPr9","lower":"QaluyKCd9bVS","count":157,"preSum":6908},{"ndv":157,"upper":"rB97B346FvbFduCpXXkK","lower":"QqB6VV4djrLc0fghKiYj","count":157,"preSum":7065},{"ndv":157,"upper":"RQsOrmFXq QZiLwdgL","lower":"RBqhcN4dyM","count":157,"preSum":7222},{"ndv":157,"upper":"s7ODdLy 7lZfudSLgO2O","lower":"rQss043foKmIH","count":157,"preSum":7379},{"ndv":157,"upper":"SmsScCsQSO","lower":"s7umVvZNZy40PXo27UW9","count":157,"preSum":7536},{"ndv":157,"upper":"t6IU7iOQN2qZGeQt4fZz","lower":"SmT0NyATf5U74l","count":157,"preSum":7693},{"ndv":157,"upper":"tPOIzmJg3jcS","lower":"T6kEMHZovot","count":157,"preSum":7850},{"ndv":157,"upper":"u9T8nthYgsndMaEc F0b","lower":"TPorDuFykLP8Xqy1jIBg","count":157,"preSum":8007},{"ndv":157,"upper":"us2gjvJ0No8WGsQf","lower":"u9vZ2N GAC","count":157,"preSum":8164},{"ndv":157,"upper":"vBlHNBWHsp5Ekr0lqG97","lower":"uS3NGPYqlCNHrsFgicJg","count":157,"preSum":8321},{"ndv":157,"upper":"VR778p3ww6,wm11","lower":"VBP4wz4ijiAABJ50wknh","count":157,"preSum":8478},{"ndv":157,"upper":"WdlSzX3T nlGeZky,i0y","lower":"VRbkXvJYQo ZT 3,zOJc","count":157,"preSum":8635},{"ndv":157,"upper":"WTqFGXwnWgH","lower":"WDpH05s71cqVs8","count":157,"preSum":8792},{"ndv":157,"upper":"XBrWkdZcf3hbxndvQj9r","lower":"wtSEZsTxz M8GmJnk","count":157,"preSum":8949},{"ndv":157,"upper":"XrOO5TJE8C81k7h","lower":"XBVIwpm6VUsKvp80Lwuv","count":157,"preSum":9106},{"ndv":157,"upper":"ybYbmXStKt","lower":"xroQlCwwyQ09h7UTgiBz","count":157,"preSum":9263},{"ndv":157,"upper":"YRUK1udc3bmhxWNBdhuH","lower":"yBZDzzLSfuNJFWpoZxi4","count":157,"preSum":9420},{"ndv":157,"upper":"ZCj,Arl Vj1bPrURyRxS","lower":"YRwwEKrXkp01kabCVge1","count":157,"preSum":9577},{"ndv":157,"upper":"zQEb3gVDnElho","lower":"ZcPTcW4TksM","count":157,"preSum":9734},{"ndv":109,"upper":"ZZy5TzW5BT9lovrBzmJd","lower":"zqgL1DtEBCl1yimfs9 s","count":109,"preSum":9891}],"maxBucketSize":64,"type":"String","sampleRate":0.09891001}
+supplier.s_comment.histogram:
+  {"buckets":[{"ndv":140,"upper":" around the furiousl","lower":" about the blithely ","count":157,"preSum":0},{"ndv":150,"upper":" carefully according","lower":" around the quickly ","count":157,"preSum":157},{"ndv":141,"upper":" engage furiously. b","lower":" carefully across th","count":157,"preSum":314},{"ndv":155,"upper":" frays about the car","lower":" epitaphs do are qui","count":157,"preSum":471},{"ndv":144,"upper":" ironic packages. sl","lower":" frays. furiously ir","count":157,"preSum":628},{"ndv":148,"upper":" regular accounts de","lower":" ironic pains. caref","count":157,"preSum":785},{"ndv":141,"upper":" slyly blithely spec","lower":" regular accounts ki","count":157,"preSum":942},{"ndv":139,"upper":" the silent packages","lower":" slyly bold deposits","count":157,"preSum":1099},{"ndv":154,"upper":", unusual deposits h","lower":" the silently ironic","count":157,"preSum":1256},{"ndv":141,"upper":". slyly regular requ","lower":", unusual deposits. ","count":157,"preSum":1413},{"ndv":147,"upper":"affix blithely after","lower":". slyly silent depos","count":157,"preSum":1570},{"ndv":155,"upper":"al accounts. account","lower":"affix bravely above ","count":157,"preSum":1727},{"ndv":151,"upper":"ar requests. dogged ","lower":"al accounts. tithes ","count":157,"preSum":1884},{"ndv":152,"upper":"blithely above the a","lower":"ar requests. final r","count":157,"preSum":2041},{"ndv":153,"upper":"careful deposits hag","lower":"blithely above the c","count":157,"preSum":2198},{"ndv":150,"upper":"ckages nag furiously","lower":"careful, regular req","count":157,"preSum":2355},{"ndv":152,"upper":"d asymptotes: slyly ","lower":"ckages nag slowly ag","count":157,"preSum":2512},{"ndv":152,"upper":"dolites. quickly bol","lower":"d cajole fluffily. e","count":157,"preSum":2669},{"ndv":147,"upper":"e quickly final pack","lower":"dolites. slow excuse","count":158,"preSum":2826},{"ndv":154,"upper":"eep across the caref","lower":"e quickly final, pen","count":158,"preSum":2984},{"ndv":148,"upper":"ely furiously specia","lower":"eep blithely slyly s","count":157,"preSum":3142},{"ndv":154,"upper":"ep after the slyly s","lower":"ely ironic packages ","count":157,"preSum":3299},{"ndv":150,"upper":"es nag furiously aft","lower":"ep alongside of the ","count":157,"preSum":3456},{"ndv":150,"upper":"even deposits are ca","lower":"es nag furiously bol","count":157,"preSum":3613},{"ndv":151,"upper":"final theodolites. q","lower":"even deposits. bold ","count":157,"preSum":3770},{"ndv":147,"upper":"furiously theodolite","lower":"final theodolites. u","count":157,"preSum":3927},{"ndv":150,"upper":"gle blithely. ironic","lower":"furiously unusual ac","count":157,"preSum":4084},{"ndv":146,"upper":"he ironic, final dep","lower":"gle carefully. caref","count":157,"preSum":4241},{"ndv":151,"upper":"ic asymptotes. dolph","lower":"he ironically final ","count":157,"preSum":4398},{"ndv":153,"upper":"ily express foxes ma","lower":"ic courts above the ","count":157,"preSum":4555},{"ndv":152,"upper":"ions was-- carefully","lower":"ily final ideas. dol","count":157,"preSum":4712},{"ndv":145,"upper":"ithely slyly fluffy ","lower":"ions. even packages ","count":157,"preSum":4869},{"ndv":156,"upper":"l deposits. blithely","lower":"ithely special accou","count":157,"preSum":5026},{"ndv":155,"upper":"ld, final courts acc","lower":"l deposits. furiousl","count":157,"preSum":5183},{"ndv":144,"upper":"lithely unusual depo","lower":"ld, regular platelet","count":157,"preSum":5340},{"ndv":138,"upper":"ly against the quick","lower":"lithely unusual theo","count":158,"preSum":5497},{"ndv":132,"upper":"ly pending ideas. fi","lower":"ly against the regul","count":157,"preSum":5655},{"ndv":135,"upper":"lyly pending package","lower":"ly pending instructi","count":157,"preSum":5812},{"ndv":152,"upper":"nal requests; fluffi","lower":"lyly pending pinto b","count":157,"preSum":5969},{"ndv":150,"upper":"nic ideas nag furiou","lower":"nal somas. ideas are","count":157,"preSum":6126},{"ndv":152,"upper":"nts wake about the b","lower":"nic ideas wake blith","count":157,"preSum":6283},{"ndv":152,"upper":"olites. silent pinto","lower":"nts wake carefully a","count":157,"preSum":6440},{"ndv":148,"upper":"osits haggle slyly a","lower":"olites. slyly regula","count":157,"preSum":6597},{"ndv":146,"upper":"ously regular wartho","lower":"osits integrate acro","count":157,"preSum":6754},{"ndv":154,"upper":"pecial hockey player","lower":"ously silent ideas o","count":157,"preSum":6911},{"ndv":147,"upper":"ptotes. final reques","lower":"pecial ideas. blithe","count":157,"preSum":7068},{"ndv":153,"upper":"rding to the careful","lower":"quests about the car","count":159,"preSum":7225},{"ndv":139,"upper":"requests are accordi","lower":"rding to the final r","count":157,"preSum":7384},{"ndv":149,"upper":"ronic platelets nag ","lower":"requests are blithel","count":157,"preSum":7541},{"ndv":152,"upper":"s doze carefully reg","lower":"ronic requests belie","count":157,"preSum":7698},{"ndv":144,"upper":"s. carefully special","lower":"s doze slyly. someti","count":157,"preSum":7855},{"ndv":153,"upper":"sits. quickly pendin","lower":"s. carefully thin ex","count":157,"preSum":8012},{"ndv":149,"upper":"special requests. ir","lower":"sits. quickly regula","count":157,"preSum":8169},{"ndv":153,"upper":"sual theodolites sle","lower":"special requests. pe","count":157,"preSum":8326},{"ndv":156,"upper":"the bold foxes snooz","lower":"sual theodolites use","count":157,"preSum":8483},{"ndv":145,"upper":"theodolites nag slyl","lower":"the bold foxes. furi","count":157,"preSum":8640},{"ndv":155,"upper":"ts doubt bravely. ca","lower":"theodolites sleep bl","count":157,"preSum":8797},{"ndv":152,"upper":"uests sleep furiousl","lower":"ts eat slyly accordi","count":157,"preSum":8954},{"ndv":150,"upper":"ully even dependenci","lower":"uests use slyly towa","count":157,"preSum":9111},{"ndv":146,"upper":"uriously special req","lower":"ully even ideas are ","count":157,"preSum":9268},{"ndv":156,"upper":"ven requests. blithe","lower":"uriously unusual acc","count":157,"preSum":9425},{"ndv":152,"upper":"y deposits sleep car","lower":"ven requests. carefu","count":157,"preSum":9582},{"ndv":146,"upper":"y special attainment","lower":"y dogged dolphins na","count":157,"preSum":9739},{"ndv":98,"upper":"zzle close requests.","lower":"y special deposits. ","count":104,"preSum":9896}],"maxBucketSize":64,"type":"String","sampleRate":0.09891001}
+supplier.s_name.histogram:
+  {"buckets":[{"ndv":157,"upper":"Supplier#000014868","lower":"Supplier#000000046","count":157,"preSum":0},{"ndv":157,"upper":"Supplier#000031103","lower":"Supplier#000014998","count":157,"preSum":157},{"ndv":157,"upper":"Supplier#000045558","lower":"Supplier#000031176","count":157,"preSum":314},{"ndv":157,"upper":"Supplier#000063652","lower":"Supplier#000045688","count":157,"preSum":471},{"ndv":157,"upper":"Supplier#000077609","lower":"Supplier#000063881","count":157,"preSum":628},{"ndv":157,"upper":"Supplier#000093389","lower":"Supplier#000077823","count":157,"preSum":785},{"ndv":157,"upper":"Supplier#000108479","lower":"Supplier#000093442","count":157,"preSum":942},{"ndv":157,"upper":"Supplier#000124331","lower":"Supplier#000108489","count":157,"preSum":1099},{"ndv":157,"upper":"Supplier#000140217","lower":"Supplier#000124457","count":157,"preSum":1256},{"ndv":157,"upper":"Supplier#000156136","lower":"Supplier#000140220","count":157,"preSum":1413},{"ndv":157,"upper":"Supplier#000170239","lower":"Supplier#000156206","count":157,"preSum":1570},{"ndv":157,"upper":"Supplier#000184389","lower":"Supplier#000170249","count":157,"preSum":1727},{"ndv":157,"upper":"Supplier#000200259","lower":"Supplier#000184440","count":157,"preSum":1884},{"ndv":157,"upper":"Supplier#000218387","lower":"Supplier#000200563","count":157,"preSum":2041},{"ndv":157,"upper":"Supplier#000233263","lower":"Supplier#000218418","count":157,"preSum":2198},{"ndv":157,"upper":"Supplier#000250331","lower":"Supplier#000233355","count":157,"preSum":2355},{"ndv":157,"upper":"Supplier#000265409","lower":"Supplier#000250372","count":157,"preSum":2512},{"ndv":157,"upper":"Supplier#000279520","lower":"Supplier#000265412","count":157,"preSum":2669},{"ndv":157,"upper":"Supplier#000293694","lower":"Supplier#000279532","count":157,"preSum":2826},{"ndv":157,"upper":"Supplier#000309501","lower":"Supplier#000293798","count":157,"preSum":2983},{"ndv":157,"upper":"Supplier#000327122","lower":"Supplier#000309543","count":157,"preSum":3140},{"ndv":157,"upper":"Supplier#000343298","lower":"Supplier#000327125","count":157,"preSum":3297},{"ndv":157,"upper":"Supplier#000358882","lower":"Supplier#000343308","count":157,"preSum":3454},{"ndv":157,"upper":"Supplier#000375298","lower":"Supplier#000358887","count":157,"preSum":3611},{"ndv":157,"upper":"Supplier#000390966","lower":"Supplier#000375393","count":157,"preSum":3768},{"ndv":157,"upper":"Supplier#000405629","lower":"Supplier#000390997","count":157,"preSum":3925},{"ndv":157,"upper":"Supplier#000420594","lower":"Supplier#000405633","count":157,"preSum":4082},{"ndv":157,"upper":"Supplier#000438670","lower":"Supplier#000420715","count":157,"preSum":4239},{"ndv":157,"upper":"Supplier#000455706","lower":"Supplier#000438743","count":157,"preSum":4396},{"ndv":157,"upper":"Supplier#000470374","lower":"Supplier#000455813","count":157,"preSum":4553},{"ndv":157,"upper":"Supplier#000484115","lower":"Supplier#000470645","count":157,"preSum":4710},{"ndv":157,"upper":"Supplier#000501114","lower":"Supplier#000484222","count":157,"preSum":4867},{"ndv":157,"upper":"Supplier#000517774","lower":"Supplier#000501178","count":157,"preSum":5024},{"ndv":157,"upper":"Supplier#000533369","lower":"Supplier#000517833","count":157,"preSum":5181},{"ndv":157,"upper":"Supplier#000551157","lower":"Supplier#000533484","count":157,"preSum":5338},{"ndv":157,"upper":"Supplier#000567187","lower":"Supplier#000551231","count":157,"preSum":5495},{"ndv":157,"upper":"Supplier#000583985","lower":"Supplier#000567333","count":157,"preSum":5652},{"ndv":157,"upper":"Supplier#000598613","lower":"Supplier#000584010","count":157,"preSum":5809},{"ndv":157,"upper":"Supplier#000616520","lower":"Supplier#000598835","count":157,"preSum":5966},{"ndv":157,"upper":"Supplier#000633732","lower":"Supplier#000616521","count":157,"preSum":6123},{"ndv":157,"upper":"Supplier#000649196","lower":"Supplier#000633766","count":157,"preSum":6280},{"ndv":157,"upper":"Supplier#000666440","lower":"Supplier#000649202","count":157,"preSum":6437},{"ndv":157,"upper":"Supplier#000683986","lower":"Supplier#000666448","count":157,"preSum":6594},{"ndv":157,"upper":"Supplier#000697483","lower":"Supplier#000683988","count":157,"preSum":6751},{"ndv":157,"upper":"Supplier#000712614","lower":"Supplier#000697533","count":157,"preSum":6908},{"ndv":157,"upper":"Supplier#000728304","lower":"Supplier#000712624","count":157,"preSum":7065},{"ndv":157,"upper":"Supplier#000744740","lower":"Supplier#000728371","count":157,"preSum":7222},{"ndv":157,"upper":"Supplier#000760007","lower":"Supplier#000744920","count":157,"preSum":7379},{"ndv":157,"upper":"Supplier#000775932","lower":"Supplier#000760021","count":157,"preSum":7536},{"ndv":157,"upper":"Supplier#000792496","lower":"Supplier#000776002","count":157,"preSum":7693},{"ndv":157,"upper":"Supplier#000807966","lower":"Supplier#000792685","count":157,"preSum":7850},{"ndv":157,"upper":"Supplier#000825292","lower":"Supplier#000808082","count":157,"preSum":8007},{"ndv":157,"upper":"Supplier#000840085","lower":"Supplier#000825322","count":157,"preSum":8164},{"ndv":157,"upper":"Supplier#000852658","lower":"Supplier#000840392","count":157,"preSum":8321},{"ndv":157,"upper":"Supplier#000868630","lower":"Supplier#000852852","count":157,"preSum":8478},{"ndv":157,"upper":"Supplier#000884216","lower":"Supplier#000868638","count":157,"preSum":8635},{"ndv":157,"upper":"Supplier#000900170","lower":"Supplier#000884612","count":157,"preSum":8792},{"ndv":157,"upper":"Supplier#000915111","lower":"Supplier#000900198","count":157,"preSum":8949},{"ndv":157,"upper":"Supplier#000930262","lower":"Supplier#000915176","count":157,"preSum":9106},{"ndv":157,"upper":"Supplier#000945715","lower":"Supplier#000930463","count":157,"preSum":9263},{"ndv":157,"upper":"Supplier#000959762","lower":"Supplier#000945926","count":157,"preSum":9420},{"ndv":157,"upper":"Supplier#000974977","lower":"Supplier#000959768","count":157,"preSum":9577},{"ndv":157,"upper":"Supplier#000990233","lower":"Supplier#000974991","count":157,"preSum":9734},{"ndv":109,"upper":"Supplier#000999977","lower":"Supplier#000990254","count":109,"preSum":9891}],"maxBucketSize":64,"type":"String","sampleRate":0.09891001}
+supplier.s_nationkey.histogram:
+  {"buckets":[{"ndv":1,"upper":0,"lower":0,"count":404,"preSum":0},{"ndv":1,"upper":1,"lower":1,"count":416,"preSum":404},{"ndv":1,"upper":2,"lower":2,"count":367,"preSum":820},{"ndv":1,"upper":3,"lower":3,"count":404,"preSum":1187},{"ndv":1,"upper":4,"lower":4,"count":429,"preSum":1591},{"ndv":1,"upper":5,"lower":5,"count":403,"preSum":2020},{"ndv":1,"upper":6,"lower":6,"count":399,"preSum":2423},{"ndv":1,"upper":7,"lower":7,"count":374,"preSum":2822},{"ndv":1,"upper":8,"lower":8,"count":434,"preSum":3196},{"ndv":1,"upper":9,"lower":9,"count":396,"preSum":3630},{"ndv":1,"upper":10,"lower":10,"count":388,"preSum":4026},{"ndv":1,"upper":11,"lower":11,"count":404,"preSum":4414},{"ndv":1,"upper":12,"lower":12,"count":416,"preSum":4818},{"ndv":1,"upper":13,"lower":13,"count":396,"preSum":5234},{"ndv":1,"upper":14,"lower":14,"count":390,"preSum":5630},{"ndv":1,"upper":15,"lower":15,"count":377,"preSum":6020},{"ndv":1,"upper":16,"lower":16,"count":384,"preSum":6397},{"ndv":1,"upper":17,"lower":17,"count":426,"preSum":6781},{"ndv":1,"upper":18,"lower":18,"count":410,"preSum":7207},{"ndv":1,"upper":19,"lower":19,"count":377,"preSum":7617},{"ndv":1,"upper":20,"lower":20,"count":420,"preSum":7994},{"ndv":1,"upper":21,"lower":21,"count":384,"preSum":8414},{"ndv":1,"upper":22,"lower":22,"count":418,"preSum":8798},{"ndv":1,"upper":23,"lower":23,"count":374,"preSum":9216},{"ndv":1,"upper":24,"lower":24,"count":410,"preSum":9590}],"maxBucketSize":64,"type":"Int","sampleRate":0.09891001}
+supplier.s_phone.histogram:
+  {"buckets":[{"ndv":157,"upper":"10-456-115-7976","lower":"10-103-216-2829","count":157,"preSum":0},{"ndv":157,"upper":"10-804-239-1090","lower":"10-457-658-8153","count":157,"preSum":157},{"ndv":157,"upper":"11-255-582-7418","lower":"10-804-579-6434","count":157,"preSum":314},{"ndv":157,"upper":"11-593-751-5656","lower":"11-262-260-1750","count":157,"preSum":471},{"ndv":157,"upper":"11-966-220-8847","lower":"11-594-638-6561","count":157,"preSum":628},{"ndv":157,"upper":"12-457-861-3318","lower":"11-966-486-9061","count":157,"preSum":785},{"ndv":157,"upper":"12-846-295-1298","lower":"12-462-534-1199","count":157,"preSum":942},{"ndv":157,"upper":"13-264-737-2836","lower":"12-850-538-8707","count":157,"preSum":1099},{"ndv":157,"upper":"13-653-641-6022","lower":"13-265-100-6298","count":157,"preSum":1256},{"ndv":157,"upper":"13-995-528-2574","lower":"13-655-296-9344","count":157,"preSum":1413},{"ndv":157,"upper":"14-421-794-4861","lower":"14-105-774-9435","count":157,"preSum":1570},{"ndv":157,"upper":"14-751-957-9140","lower":"14-422-540-3671","count":157,"preSum":1727},{"ndv":157,"upper":"15-236-611-3786","lower":"14-753-372-9201","count":157,"preSum":1884},{"ndv":157,"upper":"15-609-797-5993","lower":"15-236-990-5647","count":157,"preSum":2041},{"ndv":157,"upper":"15-986-477-7329","lower":"15-616-273-8885","count":157,"preSum":2198},{"ndv":157,"upper":"16-393-540-3042","lower":"15-986-798-1063","count":157,"preSum":2355},{"ndv":157,"upper":"16-747-830-5164","lower":"16-396-720-1822","count":157,"preSum":2512},{"ndv":157,"upper":"17-210-302-7272","lower":"16-748-134-8428","count":157,"preSum":2669},{"ndv":157,"upper":"17-563-621-8005","lower":"17-214-838-9709","count":157,"preSum":2826},{"ndv":157,"upper":"17-915-869-8375","lower":"17-564-787-7820","count":157,"preSum":2983},{"ndv":157,"upper":"18-338-582-4661","lower":"17-916-752-1187","count":157,"preSum":3140},{"ndv":157,"upper":"18-699-808-5916","lower":"18-340-124-3170","count":157,"preSum":3297},{"ndv":157,"upper":"19-146-536-2721","lower":"18-700-180-7759","count":157,"preSum":3454},{"ndv":157,"upper":"19-487-773-6008","lower":"19-147-861-1362","count":157,"preSum":3611},{"ndv":157,"upper":"19-897-174-7045","lower":"19-497-228-1392","count":157,"preSum":3768},{"ndv":157,"upper":"20-387-970-2909","lower":"19-901-865-2031","count":157,"preSum":3925},{"ndv":157,"upper":"20-747-136-2854","lower":"20-388-804-3989","count":157,"preSum":4082},{"ndv":157,"upper":"21-168-505-3652","lower":"20-747-861-4230","count":157,"preSum":4239},{"ndv":157,"upper":"21-512-983-8358","lower":"21-168-948-6229","count":157,"preSum":4396},{"ndv":157,"upper":"21-875-932-2456","lower":"21-513-666-5655","count":157,"preSum":4553},{"ndv":157,"upper":"22-339-552-5224","lower":"21-880-459-7140","count":157,"preSum":4710},{"ndv":157,"upper":"22-645-439-4694","lower":"22-339-855-3052","count":157,"preSum":4867},{"ndv":157,"upper":"23-137-871-2212","lower":"22-646-256-1655","count":157,"preSum":5024},{"ndv":157,"upper":"23-485-436-3979","lower":"23-138-347-5910","count":157,"preSum":5181},{"ndv":157,"upper":"23-837-232-5360","lower":"23-488-126-8295","count":157,"preSum":5338},{"ndv":157,"upper":"24-308-566-3423","lower":"23-837-363-5109","count":157,"preSum":5495},{"ndv":157,"upper":"24-639-330-1189","lower":"24-309-103-5181","count":157,"preSum":5652},{"ndv":157,"upper":"25-105-622-5350","lower":"24-639-594-5339","count":157,"preSum":5809},{"ndv":157,"upper":"25-404-136-1161","lower":"25-107-574-6653","count":157,"preSum":5966},{"ndv":157,"upper":"25-784-106-5647","lower":"25-405-439-8588","count":157,"preSum":6123},{"ndv":157,"upper":"26-222-761-3098","lower":"25-786-641-1353","count":157,"preSum":6280},{"ndv":157,"upper":"26-595-560-2553","lower":"26-228-297-7942","count":157,"preSum":6437},{"ndv":157,"upper":"26-951-313-8919","lower":"26-598-758-7679","count":157,"preSum":6594},{"ndv":157,"upper":"27-460-249-1275","lower":"26-953-178-7553","count":157,"preSum":6751},{"ndv":157,"upper":"27-815-857-9379","lower":"27-466-357-3495","count":157,"preSum":6908},{"ndv":157,"upper":"28-237-588-2028","lower":"27-817-665-8073","count":157,"preSum":7065},{"ndv":157,"upper":"28-606-151-5105","lower":"28-240-638-4469","count":157,"preSum":7222},{"ndv":157,"upper":"28-933-672-2905","lower":"28-607-588-7562","count":157,"preSum":7379},{"ndv":157,"upper":"29-386-763-5532","lower":"28-935-600-5948","count":157,"preSum":7536},{"ndv":157,"upper":"29-707-832-7176","lower":"29-386-941-5528","count":157,"preSum":7693},{"ndv":157,"upper":"30-209-984-8863","lower":"29-711-645-2205","count":157,"preSum":7850},{"ndv":157,"upper":"30-547-730-4709","lower":"30-217-426-6494","count":157,"preSum":8007},{"ndv":157,"upper":"30-898-379-6402","lower":"30-549-293-3645","count":157,"preSum":8164},{"ndv":157,"upper":"31-306-619-8699","lower":"30-899-573-4754","count":157,"preSum":8321},{"ndv":157,"upper":"31-652-659-4253","lower":"31-307-182-2344","count":157,"preSum":8478},{"ndv":157,"upper":"31-970-915-4206","lower":"31-657-248-8637","count":157,"preSum":8635},{"ndv":157,"upper":"32-413-789-1818","lower":"31-971-181-6032","count":157,"preSum":8792},{"ndv":157,"upper":"32-759-581-1736","lower":"32-413-810-9363","count":157,"preSum":8949},{"ndv":157,"upper":"33-189-494-6909","lower":"32-765-539-4807","count":157,"preSum":9106},{"ndv":157,"upper":"33-555-867-6362","lower":"33-191-376-3714","count":157,"preSum":9263},{"ndv":157,"upper":"33-925-172-7147","lower":"33-557-805-3392","count":157,"preSum":9420},{"ndv":157,"upper":"34-342-668-1706","lower":"33-926-271-8926","count":157,"preSum":9577},{"ndv":157,"upper":"34-708-915-7203","lower":"34-342-842-8901","count":157,"preSum":9734},{"ndv":109,"upper":"34-988-606-9699","lower":"34-710-671-7002","count":109,"preSum":9891}],"maxBucketSize":64,"type":"String","sampleRate":0.09891001}
+supplier.s_suppkey.histogram:
+  {"buckets":[{"ndv":157,"upper":14485,"lower":155,"count":157,"preSum":0},{"ndv":157,"upper":30807,"lower":14606,"count":157,"preSum":157},{"ndv":157,"upper":46073,"lower":30825,"count":157,"preSum":314},{"ndv":157,"upper":59528,"lower":46081,"count":157,"preSum":471},{"ndv":157,"upper":75251,"lower":59538,"count":157,"preSum":628},{"ndv":157,"upper":89287,"lower":75373,"count":157,"preSum":785},{"ndv":157,"upper":103469,"lower":89331,"count":157,"preSum":942},{"ndv":157,"upper":121003,"lower":103471,"count":157,"preSum":1099},{"ndv":157,"upper":135685,"lower":121025,"count":157,"preSum":1256},{"ndv":157,"upper":153455,"lower":135716,"count":157,"preSum":1413},{"ndv":157,"upper":169501,"lower":153545,"count":157,"preSum":1570},{"ndv":157,"upper":184381,"lower":169517,"count":157,"preSum":1727},{"ndv":157,"upper":201946,"lower":184461,"count":157,"preSum":1884},{"ndv":157,"upper":217689,"lower":202145,"count":157,"preSum":2041},{"ndv":157,"upper":234080,"lower":217726,"count":157,"preSum":2198},{"ndv":157,"upper":251589,"lower":234130,"count":157,"preSum":2355},{"ndv":157,"upper":268018,"lower":251617,"count":157,"preSum":2512},{"ndv":157,"upper":283246,"lower":268021,"count":157,"preSum":2669},{"ndv":157,"upper":298678,"lower":283251,"count":157,"preSum":2826},{"ndv":157,"upper":313906,"lower":298715,"count":157,"preSum":2983},{"ndv":157,"upper":331198,"lower":314044,"count":157,"preSum":3140},{"ndv":157,"upper":346146,"lower":331338,"count":157,"preSum":3297},{"ndv":157,"upper":359777,"lower":346402,"count":157,"preSum":3454},{"ndv":157,"upper":372794,"lower":359845,"count":157,"preSum":3611},{"ndv":157,"upper":387960,"lower":372856,"count":157,"preSum":3768},{"ndv":157,"upper":403573,"lower":388031,"count":157,"preSum":3925},{"ndv":157,"upper":418681,"lower":403738,"count":157,"preSum":4082},{"ndv":157,"upper":433459,"lower":418817,"count":157,"preSum":4239},{"ndv":157,"upper":449374,"lower":433535,"count":157,"preSum":4396},{"ndv":157,"upper":464363,"lower":449583,"count":157,"preSum":4553},{"ndv":157,"upper":480730,"lower":464508,"count":157,"preSum":4710},{"ndv":157,"upper":494982,"lower":480842,"count":157,"preSum":4867},{"ndv":157,"upper":511090,"lower":495033,"count":157,"preSum":5024},{"ndv":157,"upper":526354,"lower":511312,"count":157,"preSum":5181},{"ndv":157,"upper":540112,"lower":526529,"count":157,"preSum":5338},{"ndv":157,"upper":555193,"lower":540373,"count":157,"preSum":5495},{"ndv":157,"upper":571036,"lower":555318,"count":157,"preSum":5652},{"ndv":157,"upper":586357,"lower":571119,"count":157,"preSum":5809},{"ndv":157,"upper":604809,"lower":586418,"count":157,"preSum":5966},{"ndv":157,"upper":621774,"lower":604848,"count":157,"preSum":6123},{"ndv":157,"upper":638643,"lower":621782,"count":157,"preSum":6280},{"ndv":157,"upper":652511,"lower":638678,"count":157,"preSum":6437},{"ndv":157,"upper":669201,"lower":652575,"count":157,"preSum":6594},{"ndv":157,"upper":684864,"lower":669202,"count":157,"preSum":6751},{"ndv":157,"upper":701358,"lower":684890,"count":157,"preSum":6908},{"ndv":157,"upper":715967,"lower":701388,"count":157,"preSum":7065},{"ndv":157,"upper":731534,"lower":715991,"count":157,"preSum":7222},{"ndv":157,"upper":747317,"lower":731607,"count":157,"preSum":7379},{"ndv":157,"upper":763417,"lower":747613,"count":157,"preSum":7536},{"ndv":157,"upper":778451,"lower":763426,"count":157,"preSum":7693},{"ndv":157,"upper":795440,"lower":778599,"count":157,"preSum":7850},{"ndv":157,"upper":812323,"lower":795466,"count":157,"preSum":8007},{"ndv":157,"upper":827981,"lower":812352,"count":157,"preSum":8164},{"ndv":157,"upper":843089,"lower":828030,"count":157,"preSum":8321},{"ndv":157,"upper":859823,"lower":843216,"count":157,"preSum":8478},{"ndv":157,"upper":875567,"lower":859924,"count":157,"preSum":8635},{"ndv":157,"upper":894284,"lower":875918,"count":157,"preSum":8792},{"ndv":157,"upper":908854,"lower":894317,"count":157,"preSum":8949},{"ndv":157,"upper":924844,"lower":908965,"count":157,"preSum":9106},{"ndv":157,"upper":941572,"lower":925014,"count":157,"preSum":9263},{"ndv":157,"upper":957777,"lower":941600,"count":157,"preSum":9420},{"ndv":157,"upper":972526,"lower":957834,"count":157,"preSum":9577},{"ndv":157,"upper":986737,"lower":972554,"count":157,"preSum":9734},{"ndv":109,"upper":999811,"lower":986869,"count":109,"preSum":9891}],"maxBucketSize":64,"type":"Int","sampleRate":0.09891001}
+customer.sampleRate:
+  0.00674018
+lineitem.sampleRate:
+  0.000167757
+nation.sampleRate:
+  1
+orders.sampleRate:
+  0.000672188
+part.sampleRate:
+  0.00504245
+partsupp.sampleRate:
+  0.00126705
+region.sampleRate:
+  1
+supplier.sampleRate:
+  0.100944
+
+customer.c_acctbal.nullCount:
+  0
+customer.c_address.nullCount:
+  0
+customer.c_comment.nullCount:
+  0
+customer.c_custkey.nullCount:
+  0
+customer.c_mktsegment.nullCount:
+  0
+customer.c_name.nullCount:
+  0
+customer.c_nationkey.nullCount:
+  0
+customer.c_phone.nullCount:
+  0
+lineitem.l_comment.nullCount:
+  0
+lineitem.l_commitdate.nullCount:
+  0
+lineitem.l_discount.nullCount:
+  0
+lineitem.l_extendedprice.nullCount:
+  0
+lineitem.l_linenumber.nullCount:
+  0
+lineitem.l_linestatus.nullCount:
+  0
+lineitem.l_orderkey.nullCount:
+  0
+lineitem.l_partkey.nullCount:
+  0
+lineitem.l_quantity.nullCount:
+  0
+lineitem.l_receiptdate.nullCount:
+  0
+lineitem.l_returnflag.nullCount:
+  0
+lineitem.l_shipdate.nullCount:
+  0
+lineitem.l_shipinstruct.nullCount:
+  0
+lineitem.l_shipmode.nullCount:
+  0
+lineitem.l_suppkey.nullCount:
+  0
+lineitem.l_tax.nullCount:
+  0
+nation.n_comment.nullCount:
+  0
+nation.n_name.nullCount:
+  0
+nation.n_nationkey.nullCount:
+  0
+nation.n_regionkey.nullCount:
+  0
+orders.o_clerk.nullCount:
+  0
+orders.o_comment.nullCount:
+  0
+orders.o_custkey.nullCount:
+  0
+orders.o_orderdate.nullCount:
+  0
+orders.o_orderkey.nullCount:
+  0
+orders.o_orderpriority.nullCount:
+  0
+orders.o_orderstatus.nullCount:
+  0
+orders.o_shippriority.nullCount:
+  0
+orders.o_totalprice.nullCount:
+  0
+part.p_brand.nullCount:
+  0
+part.p_comment.nullCount:
+  0
+part.p_container.nullCount:
+  0
+part.p_mfgr.nullCount:
+  0
+part.p_name.nullCount:
+  0
+part.p_partkey.nullCount:
+  0
+part.p_retailprice.nullCount:
+  0
+part.p_size.nullCount:
+  0
+part.p_type.nullCount:
+  0
+partsupp.ps_availqty.nullCount:
+  0
+partsupp.ps_comment.nullCount:
+  0
+partsupp.ps_partkey.nullCount:
+  0
+partsupp.ps_suppkey.nullCount:
+  0
+partsupp.ps_supplycost.nullCount:
+  0
+region.r_comment.nullCount:
+  0
+region.r_name.nullCount:
+  0
+region.r_regionkey.nullCount:
+  0
+supplier.s_acctbal.nullCount:
+  0
+supplier.s_address.nullCount:
+  0
+supplier.s_comment.nullCount:
+  0
+supplier.s_name.nullCount:
+  0
+supplier.s_nationkey.nullCount:
+  0
+supplier.s_phone.nullCount:
+  0
+supplier.s_suppkey.nullCount:
+  0
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.yml
new file mode 100644
index 000000000..aa646d5c5
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlan2Test.yml
@@ -0,0 +1,12 @@
+
+- sql: |
+    select `snap_time` from `sp_k_r_month` t where t.snap_time >= '2024-05-21 17:30:27' and t.snap_time <= '2024-05-21 17:30:40' limit 10;
+  plan: |
+    mergesort(sort="", offset=0, fetch=10)
+      logicalview(tables="sp_k_r_month[p1sp6,p2sp6,p3sp6,...p64sp6]", shardcount=64, sql="select `snap_time` from `sp_k_r_month` as `sp_k_r_month` where ((`snap_time` >= '2024-05-21 17:30:27') and (`snap_time` <= '2024-05-21 17:30:40')) limit 10")
+
+- sql: |
+    select `snap_time` from `sp_k_r_month` t where t.snap_time >= '2024-05-21 17:30:27' and t.snap_time <= '2024-06-21 17:30:40' limit 10;
+  plan: |
+    mergesort(sort="", offset=0, fetch=10)
+      logicalview(tables="sp_k_r_month[p1sp6,p1sp7,p2sp6,...p64sp7]", shardcount=128, sql="select `snap_time` from `sp_k_r_month` as `sp_k_r_month` where ((`snap_time` >= '2024-05-21 17:30:27') and (`snap_time` <= '2024-06-21 17:30:40')) limit 10")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlanTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlanTest.yml
index 7a68a741d..44fe1d019 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlanTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/PartitionRoutingPlanTest.yml
@@ -37,9 +37,7 @@
     select * from rng_col_tbl a where (a,b) in ((300,2000), (600,5000))
   plan: |
     gather(concurrent=true)
-      logicalview(tables="rng_col_tbl[p3,p6]", shardcount=2, sql="select `a`, `b`, `c`, `d`, `e` from `rng_col_tbl` as `rng_col_tbl` where (((`a`, `b`)) in((300, 2000),(600, 5000)))")
-
-
+      logicalview(tables="rng_col_tbl[p3,p6]", shardcount=2, sql="select `a`, `b`, `c`, `d`, `e` from `rng_col_tbl` as `rng_col_tbl` force index(`primary`) where (((`a`, `b`)) in((300, 2000),(600, 5000)))")
 - sql: |
     select * from rng_tbl a where (b, e, c) in ((1,2,3),(4,5,6))
   plan: |
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/TpPartitionTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/TpPartitionTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/partition/TpPartitionTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/planmanagement/PlanManagementPlanTest.testSortJoin.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/planmanagement/PlanManagementPlanTest.testSortJoin.yml
index e885a7386..1ff167f66 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/planmanagement/PlanManagementPlanTest.testSortJoin.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/planmanagement/PlanManagementPlanTest.testSortJoin.yml
@@ -3,27 +3,23 @@
     select t_shard_id1.id from t_shard_id1, t_shard_id2 where t_shard_id1.name = t_shard_id2.name order by t_shard_id1.id;
 
   plan: |
-
-    Project(id="id")
-      HashJoin(condition="name = name", type="inner")
-        MergeSort(sort="id ASC")
-          LogicalView(tables="[0000-0003].t_shard_id1", shardCount=4, sql="SELECT `id`, `name` FROM `t_shard_id1` AS `t_shard_id1` ORDER BY `id`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_id2", shardCount=4, sql="SELECT `name` FROM `t_shard_id2` AS `t_shard_id2`")
-
+    project(id="id")
+      hashjoin(condition="name = name", type="inner")
+        mergesort(sort="id asc")
+          logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `id`, `name` from `t_shard_id1` as `t_shard_id1` force index(`primary`) order by `id`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_id2", shardcount=4, sql="select `name` from `t_shard_id2` as `t_shard_id2`")
 - sql: |
     /*+TDDL:HASH_JOIN(t_shard_id2,t_shard_id1)*/
     select t_shard_id1.id from t_shard_id1, t_shard_id2 where t_shard_id1.name = t_shard_id2.name order by t_shard_id2.id;
 
   plan: |
-
-    Project(id="id0")
-      HashJoin(condition="name = name", type="inner")
-        MergeSort(sort="id ASC")
-          LogicalView(tables="[0000-0003].t_shard_id2", shardCount=4, sql="SELECT `id`, `name` FROM `t_shard_id2` AS `t_shard_id2` ORDER BY `id`")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].t_shard_id1", shardCount=4, sql="SELECT `id`, `name` FROM `t_shard_id1` AS `t_shard_id1`")
-
+    project(id="id0")
+      hashjoin(condition="name = name", type="inner")
+        mergesort(sort="id asc")
+          logicalview(tables="[0000-0003].t_shard_id2", shardcount=4, sql="select `id`, `name` from `t_shard_id2` as `t_shard_id2` force index(`primary`) order by `id`")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].t_shard_id1", shardcount=4, sql="select `id`, `name` from `t_shard_id1` as `t_shard_id1`")
 - sql: |
     /*+TDDL:HASH_JOIN(t_shard_id1,t_shard_id2)*/
     select t_shard_id1.id from t_shard_id1, t_shard_id2 where t_shard_id1.name = t_shard_id2.name order by t_shard_id2.id, t_shard_id1.id;
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/AggRuleTest.test.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/AggRuleTest.test.yml
index f403a8e65..712956c85 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/AggRuleTest.test.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/AggRuleTest.test.yml
@@ -1,3 +1,16 @@
+- sql: |
+    select * from (select count(c) as t from test_tc) where t > 0;
+  plan: |
+    filter(condition="t > 0")
+      logicalagg(t="sum(t)")
+        logicalview(tables="[0000-0003].test_tc_[00-27]", shardcount=28, sql="select count(`c`) as `t` from `test_tc` as `test_tc`")
+- sql: |
+    select * from (select 1 as id , max(c) as t from test_tc) where id = 0;
+  plan: |
+    project(id="1", t="t")
+      filter(condition="1 = 0")
+        logicalagg(t="max(t)")
+          logicalview(tables="[0000-0003].test_tc_[00-27]", shardcount=28, sql="select max(`c`) as `t` from `test_tc` as `test_tc`")
 - sql: |
     select c from test_tc group by b
   plan: |
@@ -121,22 +134,6 @@
       LogicalAgg(group="name,actionDate", $f2="SUM($f2)", $f3="SUM($f3)")
         LogicalView(tables="[0000-0003].user_log_[0-6]", shardCount=28, sql="SELECT `name`, `actionDate`, SUM(`userId`) AS `$f2`, COUNT(`userId`) AS `$f3` FROM `user_log` AS `user_log` GROUP BY `name`, `actionDate`")
 
-- sql: |
-    select avg(userid) from user_log group by name, actionDate
-
-  plan: |
-    Project(avg(userid)="$f2 / $f3")
-      LogicalAgg(group="name,actionDate", $f2="SUM($f2)", $f3="SUM($f3)")
-        LogicalView(tables="[0000-0003].user_log_[0-6]", shardCount=28, sql="SELECT `name`, `actionDate`, SUM(`userId`) AS `$f2`, COUNT(`userId`) AS `$f3` FROM `user_log` AS `user_log` GROUP BY `name`, `actionDate`")
-
-- sql: |
-    select max(userid) from user_log group by name, actionDate
-
-  plan: |
-    Project(max(userid)="max(userid)")
-      LogicalAgg(group="name,actionDate", max(userid)="MAX(max(userid))")
-        LogicalView(tables="[0000-0003].user_log_[0-6]", shardCount=28, sql="SELECT `name`, `actionDate`, MAX(`userId`) AS `max(userid)` FROM `user_log` AS `user_log` GROUP BY `name`, `actionDate`")
-
 - sql: |
     select max(userid) from user_log group by name, actionDate
 
@@ -153,22 +150,6 @@
       LogicalAgg(group="name,actionDate", min(userid)="MIN(min(userid))")
         LogicalView(tables="[0000-0003].user_log_[0-6]", shardCount=28, sql="SELECT `name`, `actionDate`, MIN(`userId`) AS `min(userid)` FROM `user_log` AS `user_log` GROUP BY `name`, `actionDate`")
 
-- sql: |
-    select min(userid) from user_log group by name, actionDate
-
-  plan: |
-    Project(min(userid)="min(userid)")
-      LogicalAgg(group="name,actionDate", min(userid)="MIN(min(userid))")
-        LogicalView(tables="[0000-0003].user_log_[0-6]", shardCount=28, sql="SELECT `name`, `actionDate`, MIN(`userId`) AS `min(userid)` FROM `user_log` AS `user_log` GROUP BY `name`, `actionDate`")
-
-- sql: |
-    select sum(userid) from user_log group by name, actionDate
-
-  plan: |
-    Project(sum(userid)="sum(userid)")
-      LogicalAgg(group="name,actionDate", sum(userid)="SUM(sum(userid))")
-        LogicalView(tables="[0000-0003].user_log_[0-6]", shardCount=28, sql="SELECT `name`, `actionDate`, SUM(`userId`) AS `sum(userid)` FROM `user_log` AS `user_log` GROUP BY `name`, `actionDate`")
-
 - sql: |
     select sum(userid) from user_log group by name, actionDate
 
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/ColumnarPlanCacheTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/ColumnarPlanCacheTest.yml
new file mode 100644
index 000000000..5e495792f
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/ColumnarPlanCacheTest.yml
@@ -0,0 +1,29 @@
+SQL:
+  - sql: |
+      select 1+3<4 as a from lineitem where 1+3<2;
+    plan: |
+      project(a="1 + 3 < 4")
+        filter(condition="1 + 3 < 2")
+          logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_suppkey` from `lineitem` as `lineitem`")
+  - sql: |
+      select 11 as a from lineitem where true;
+    plan: |
+      project(a="11")
+        logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_suppkey` from `lineitem` as `lineitem`")
+
+  - sql: |
+      select 1+3=4 as a from lineitem where 1=1;
+    plan: |
+      project(a="1 + 3 = 4")
+        filter(condition="1 = 1")
+          logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_suppkey` from `lineitem` as `lineitem`")
+DDL:
+  lineitem:
+    CREATE TABLE `lineitem` (`l_suppkey` int(11) NOT NULL,KEY `auto_shard_key_l_suppkey` USING BTREE (`l_suppkey`) ) ENGINE = InnoDB DEFAULT CHARSET = latin1 DBPARTITION BY RIGHT_SHIFT(`l_suppkey`, 6) TBPARTITION BY RIGHT_SHIFT(`l_suppkey`, 6) TBPARTITIONS 4;
+STATISTICS:
+  lineitem:
+    5414964
+CONFIG:
+  defaltxxAPPName.isNew:
+    false
+
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/LogicalViewOptTest.test.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/LogicalViewOptTest.test.yml
index 611d06143..536fef57b 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/LogicalViewOptTest.test.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/LogicalViewOptTest.test.yml
@@ -20,20 +20,20 @@
             nljoin(condition="name < name0", type="inner")
               logicalview(tables="optest_0000.nation", sql="select `name` from `nation` as `nation`")
               nljoin(condition="name <> name", type="inner")
-                logicalview(tables="optest_0001.car_2", sql="select `name` from `car` as `car` where (`id` = 2)")
-                logicalview(tables="optest_0001.apple_2", sql="select `name`, `size` from `apple` as `apple` where (`id` = 2)")
+                logicalview(tables="optest_0001.car_2", sql="select `name` from `car` as `car` force index(`primary`) where (`id` = 2)")
+                logicalview(tables="optest_0001.apple_2", sql="select `name`, `size` from `apple` as `apple` force index(`primary`) where (`id` = 2)")
           hashagg(count(*)="count()")
             filter(condition="$cor0.size < height")
-              logicalview(tables="optest_0001.boy_2", sql="select `height` from `boy` as `boy` where ((2 = `id`) and (`money` > 8))")
+              logicalview(tables="optest_0001.boy_2", sql="select `height` from `boy` as `boy` force index(`primary`) where ((2 = `id`) and (`money` > 8))")
     cache node:
 
     project(size="size")
       nljoin(condition="name < name0", type="inner")
         logicalview(tables="optest_0000.nation", sql="select `name` from `nation` as `nation`")
         nljoin(condition="name <> name", type="inner")
-          logicalview(tables="optest_0001.car_2", sql="select `name` from `car` as `car` where (`id` = 2)")
-          logicalview(tables="optest_0001.apple_2", sql="select `name`, `size` from `apple` as `apple` where (`id` = 2)")
-    logicalview(tables="optest_0001.boy_2", sql="select `height` from `boy` as `boy` where ((2 = `id`) and (`money` > 8))")
+          logicalview(tables="optest_0001.car_2", sql="select `name` from `car` as `car` force index(`primary`) where (`id` = 2)")
+          logicalview(tables="optest_0001.apple_2", sql="select `name`, `size` from `apple` as `apple` force index(`primary`) where (`id` = 2)")
+    logicalview(tables="optest_0001.boy_2", sql="select `height` from `boy` as `boy` force index(`primary`) where ((2 = `id`) and (`money` > 8))")
 
 - sql: |
     select count(*)
@@ -125,7 +125,8 @@
     from boy b where money = (select id from apple a where a.id = b.id and price = 12);
   plan: |
     gather(concurrent=true)
-      logicalview(tables="[0000-0003].boy_[0-7],apple_[0-7]", shardcount=8, sql="select `name` from (select `id`, `name`, `birth_date`, `birth_place`, `money`, `height` from `boy` as `boy` where (`money` = (((select `id` from `apple` as `apple` where ((`price` = 12) and (`id` = `boy`.`id`))))))) as `t1`")
+      logicalview(tables="[0000-0003].apple_[0-7],boy_[0-7]", shardcount=8, sql="select `name` from (select `id`, `name`, `birth_date`, `birth_place`, `money`, `height`, (((select `id` from `apple` as `apple` where ((`price` = 12) and (`id` = `boy`.`id`))))) as `id0` from `boy` as `boy`) as `t1` where (`money` = `id0`)")
+
 - sql: |
     select b.name, (select id from apple a where (id = b.id and exists (select * from car c where c.id = a.id and c.price < a.price)))
     from boy b where id<10;
@@ -200,7 +201,7 @@
     project(name="name")
       hashagg(group="pick_date", name="__first_value(name)")
         gather(concurrent=true)
-          logicalview(tables="[0000-0003].boy_[0-7],apple_[0-7],car_[0-7]", shardcount=8, sql="select `apple`.`pick_date`, `boy`.`name` from `boy` as `boy` inner join `apple` as `apple` on ((`boy`.`id` = `apple`.`id`) and (`apple`.`price` in(12, 3, 4, 6))) where ((`boy`.`height` < some (select `size` from `car` as `car` where ((`boy`.`height` < `size`) and (`origin_place` = `boy`.`birth_place`) and (`id` = `boy`.`id`)))) and (`boy`.`money` > all (select `price` from `apple` as `apple0` where (`id` = `boy`.`id`))))")
+          logicalview(tables="[0000-0003].boy_[0-7],apple_[0-7],car_[0-7]", shardcount=8, sql="select `apple`.`pick_date`, (`boy`.`name`) as `name` from `boy` as `boy` inner join `apple` as `apple` on ((`boy`.`id` = `apple`.`id`) and (`apple`.`price` in(12, 3, 4, 6))) where ((`boy`.`height` < some (select `size` from `car` as `car` where ((`boy`.`height` < `size`) and (`origin_place` = `boy`.`birth_place`) and (`id` = `boy`.`id`)))) and (`boy`.`money` > all (select `price` from `apple` as `apple0` where (`id` = `boy`.`id`)))) group by `apple`.`pick_date`")
 - sql: |
     /*+TDDL:cmd_extra(enable_lv_subquery_unwrap=true)*/
     select b.height , a.size
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/XplanSkewTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/XplanSkewTest.yml
index fdba348b6..a0f5c7e56 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/XplanSkewTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rewriter/XplanSkewTest.yml
@@ -10,7 +10,7 @@ SQL:
   - sql: |
       /*+TDDL:cmd_extra(merge_union=false)*/select * from xplan where c_int_32=1;
     plan: |
-      null
+      {"plan": {"plan_type": "filter","filter": {"sub_read_plan": {"plan_type": "table_project","table_project": {"sub_read_plan": {"plan_type": "get","get_plan": {"table_info": {"name": {"type": "v_placeholder","v_position": 0},"schema_name": {"type": "v_placeholder","v_position": 1}},"index_info": {"name": {"type": "v_string","v_string": {"value": "c_int_32_c_varchar_idx","collation": 45}}},"keys": [{"keys": [{"field": {"type": "v_string","v_string": {"value": "c_int_32","collation": 45}},"value": {"type": "v_sint","v_signed_int": 1}}]}]}},"fields": [{"type": "v_string","v_string": {"value": "c_int_32_un","collation": 45}},{"type": "v_string","v_string": {"value": "c_char","collation": 45}},{"type": "v_string","v_string": {"value": "id","collation": 45}},{"type": "v_string","v_string": {"value": "c_datetime","collation": 45}},{"type": "v_string","v_string": {"value": "c_varchar","collation": 45}},{"type": "v_string","v_string": {"value": "c_int_32","collation": 45}}]}},"expr": {"type": "operator","operator": {"name": "==","param": [{"type": "ref","ref_id": 5},{"type": "literal","literal": {"type": "v_sint","v_signed_int": 1}}]}}}},"parameters": [{"type": "v_string","v_string": {"value": "xplan","collation": 45}},{"type": "v_string","v_string": {"value": "optest","collation": 45}}]}
   - sql: |
       /*+TDDL:cmd_extra(merge_union=false)*/select * from xplan where c_varchar='1';
     plan: |
@@ -18,7 +18,7 @@ SQL:
   - sql: |
       /*+TDDL:cmd_extra(merge_union=false)*/select * from xplan where c_int_32=1 and c_varchar='1';
     plan: |
-      null
+      {"plan": {"plan_type": "filter","filter": {"sub_read_plan": {"plan_type": "table_project","table_project": {"sub_read_plan": {"plan_type": "get","get_plan": {"table_info": {"name": {"type": "v_placeholder","v_position": 0},"schema_name": {"type": "v_placeholder","v_position": 1}},"index_info": {"name": {"type": "v_string","v_string": {"value": "c_int_32_c_varchar_idx","collation": 45}}},"keys": [{"keys": [{"field": {"type": "v_string","v_string": {"value": "c_int_32","collation": 45}},"value": {"type": "v_sint","v_signed_int": 1}},{"field": {"type": "v_string","v_string": {"value": "c_varchar","collation": 45}},"value": {"type": "v_string","v_string": {"value": "1","collation": 45}}}]}]}},"fields": [{"type": "v_string","v_string": {"value": "c_int_32_un","collation": 45}},{"type": "v_string","v_string": {"value": "c_char","collation": 45}},{"type": "v_string","v_string": {"value": "id","collation": 45}},{"type": "v_string","v_string": {"value": "c_datetime","collation": 45}},{"type": "v_string","v_string": {"value": "c_varchar","collation": 45}},{"type": "v_string","v_string": {"value": "c_int_32","collation": 45}}]}},"expr": {"type": "operator","operator": {"name": "&&","param": [{"type": "operator","operator": {"name": "==","param": [{"type": "ref","ref_id": 5},{"type": "literal","literal": {"type": "v_sint","v_signed_int": 1}}]}},{"type": "operator","operator": {"name": "==","param": [{"type": "ref","ref_id": 4},{"type": "literal","literal": {"type": "v_string","v_string": {"value": "1","collation": 45}}}]}}]}}}},"parameters": [{"type": "v_string","v_string": {"value": "xplan","collation": 45}},{"type": "v_string","v_string": {"value": "optest","collation": 45}}]}
   - sql: |
       /*+TDDL:cmd_extra(merge_union=false)*/select * from xplan where c_datetime='2023-01-01';
     plan: |
@@ -172,6 +172,8 @@ STATISTICS:
   xplan.id.composite_cardinality:
     200726
 CONFIG:
+  ENABLE_AUTO_FORCE_INDEX:
+    true
   ENABLE_BKA_JOIN:
     true
   MPP_METRIC_LEVEL:
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rule/RuleEqualityPlanTest.testSimpleRuleEquality.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rule/RuleEqualityPlanTest.testSimpleRuleEquality.yml
index 05757e0eb..042413e44 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rule/RuleEqualityPlanTest.testSimpleRuleEquality.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/rule/RuleEqualityPlanTest.testSimpleRuleEquality.yml
@@ -11,9 +11,8 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` AS `id0`, `test_hash_tb0`.`name` AS `name0`, `test_hash_tb0`.`create_time` AS `create_time0` FROM `test_hash_tb` AS `test_hash_tb` INNER JOIN `test_hash_tb` AS `test_hash_tb0` ON ((`test_hash_tb`.`name` = 'xx') AND (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
-
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb0`.`id` as `id0`, `test_hash_tb0`.`name` as `name0`, `test_hash_tb0`.`create_time` as `create_time0` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb` as `test_hash_tb0` on ((`test_hash_tb`.`name` = 'xx') and (`test_hash_tb`.`id` = `test_hash_tb0`.`id`))")
 
 - sql: |
     /*+TDDL:cmd_extra(enable_hash_join=false,enable_sort_merge_join=false,enable_nl_join=false)*/
@@ -26,8 +25,8 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_tb_shard_by_key,test_tb_shard_by_name", shardCount=4, sql="SELECT `test_tb_shard_by_key`.`id`, `test_tb_shard_by_key`.`name`, `test_tb_shard_by_key`.`key`, `test_tb_shard_by_key`.`create_time`, `test_tb_shard_by_name`.`id` AS `id0`, `test_tb_shard_by_name`.`name` AS `name0`, `test_tb_shard_by_name`.`key` AS `key0`, `test_tb_shard_by_name`.`create_time` AS `create_time0` FROM `test_tb_shard_by_key` AS `test_tb_shard_by_key` INNER JOIN `test_tb_shard_by_name` AS `test_tb_shard_by_name` ON ((`test_tb_shard_by_key`.`key` = `test_tb_shard_by_name`.`name`) AND (`test_tb_shard_by_key`.`name` = 'xx'))")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_tb_shard_by_key,test_tb_shard_by_name", shardcount=4, sql="select `test_tb_shard_by_key`.`id`, `test_tb_shard_by_key`.`name`, `test_tb_shard_by_key`.`key`, `test_tb_shard_by_key`.`create_time`, `test_tb_shard_by_name`.`id` as `id0`, `test_tb_shard_by_name`.`name` as `name0`, `test_tb_shard_by_name`.`key` as `key0`, `test_tb_shard_by_name`.`create_time` as `create_time0` from `test_tb_shard_by_key` as `test_tb_shard_by_key` inner join `test_tb_shard_by_name` as `test_tb_shard_by_name` on ((`test_tb_shard_by_key`.`key` = `test_tb_shard_by_name`.`name`) and (`test_tb_shard_by_key`.`name` = 'xx'))")
 
 - sql: |
     select *
@@ -42,9 +41,8 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_tb_shard_by_strhash_sk", shardCount=4, sql="SELECT `test_tb_shard_by_strhash_sk`.`id`, `test_tb_shard_by_strhash_sk`.`name`, `test_tb_shard_by_strhash_sk`.`sk`, `test_tb_shard_by_strhash_sk`.`create_time`, `test_tb_shard_by_strhash_sk0`.`id` AS `id0`, `test_tb_shard_by_strhash_sk0`.`name` AS `name0`, `test_tb_shard_by_strhash_sk0`.`sk` AS `sk0`, `test_tb_shard_by_strhash_sk0`.`create_time` AS `create_time0` FROM `test_tb_shard_by_strhash_sk` AS `test_tb_shard_by_strhash_sk` INNER JOIN `test_tb_shard_by_strhash_sk` AS `test_tb_shard_by_strhash_sk0` ON ((`test_tb_shard_by_strhash_sk`.`sk` = `test_tb_shard_by_strhash_sk0`.`sk`) AND (`test_tb_shard_by_strhash_sk`.`name` = 'xx'))")
-
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_tb_shard_by_strhash_sk", shardcount=4, sql="select `test_tb_shard_by_strhash_sk`.`id`, `test_tb_shard_by_strhash_sk`.`name`, `test_tb_shard_by_strhash_sk`.`sk`, `test_tb_shard_by_strhash_sk`.`create_time`, `test_tb_shard_by_strhash_sk0`.`id` as `id0`, `test_tb_shard_by_strhash_sk0`.`name` as `name0`, `test_tb_shard_by_strhash_sk0`.`sk` as `sk0`, `test_tb_shard_by_strhash_sk0`.`create_time` as `create_time0` from `test_tb_shard_by_strhash_sk` as `test_tb_shard_by_strhash_sk` inner join `test_tb_shard_by_strhash_sk` as `test_tb_shard_by_strhash_sk0` on ((`test_tb_shard_by_strhash_sk`.`sk` = `test_tb_shard_by_strhash_sk0`.`sk`) and (`test_tb_shard_by_strhash_sk`.`name` = 'xx'))")
 
 - sql: |
     select *
@@ -59,8 +57,8 @@
 
   plan: |
 
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_tb_shard_by_strhash_name,test_tb_shard_by_strhash_sk", shardCount=4, sql="SELECT `test_tb_shard_by_strhash_name`.`id`, `test_tb_shard_by_strhash_name`.`name`, `test_tb_shard_by_strhash_name`.`sk`, `test_tb_shard_by_strhash_name`.`create_time`, `test_tb_shard_by_strhash_sk`.`id` AS `id0`, `test_tb_shard_by_strhash_sk`.`name` AS `name0`, `test_tb_shard_by_strhash_sk`.`sk` AS `sk0`, `test_tb_shard_by_strhash_sk`.`create_time` AS `create_time0` FROM `test_tb_shard_by_strhash_name` AS `test_tb_shard_by_strhash_name` INNER JOIN `test_tb_shard_by_strhash_sk` AS `test_tb_shard_by_strhash_sk` ON ((`test_tb_shard_by_strhash_name`.`name` = `test_tb_shard_by_strhash_sk`.`sk`) AND (`test_tb_shard_by_strhash_name`.`id` = 5))")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_tb_shard_by_strhash_name,test_tb_shard_by_strhash_sk", shardcount=4, sql="select `test_tb_shard_by_strhash_name`.`id`, `test_tb_shard_by_strhash_name`.`name`, `test_tb_shard_by_strhash_name`.`sk`, `test_tb_shard_by_strhash_name`.`create_time`, `test_tb_shard_by_strhash_sk`.`id` as `id0`, `test_tb_shard_by_strhash_sk`.`name` as `name0`, `test_tb_shard_by_strhash_sk`.`sk` as `sk0`, `test_tb_shard_by_strhash_sk`.`create_time` as `create_time0` from `test_tb_shard_by_strhash_name` as `test_tb_shard_by_strhash_name` inner join `test_tb_shard_by_strhash_sk` as `test_tb_shard_by_strhash_sk` on ((`test_tb_shard_by_strhash_name`.`name` = `test_tb_shard_by_strhash_sk`.`sk`) and (`test_tb_shard_by_strhash_name`.`id` = 5))")
 
 - sql: |
     /*+TDDL:cmd_extra(enable_hash_join=false,enable_sort_merge_join=false,enable_nl_join=false)*/
@@ -76,11 +74,11 @@
 
   plan: |
 
-    BKAJoin(condition="name = name", type="inner")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_tb_shard_by_strhash_name", shardCount=4, sql="SELECT `id`, `name`, `sk`, `create_time` FROM `test_tb_shard_by_strhash_name` AS `test_tb_shard_by_strhash_name` WHERE (`id` = 5)")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_tb2_shard_by_strhash_name", shardCount=4, sql="SELECT `id`, `name`, `sk`, `create_time` FROM `test_tb2_shard_by_strhash_name` AS `test_tb2_shard_by_strhash_name` WHERE (`name` IN (...))")
+    bkajoin(condition="name = name", type="inner")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tb_shard_by_strhash_name", shardcount=4, sql="select `id`, `name`, `sk`, `create_time` from `test_tb_shard_by_strhash_name` as `test_tb_shard_by_strhash_name` force index(`primary`) where (`id` = 5)")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tb2_shard_by_strhash_name", shardcount=4, sql="select `id`, `name`, `sk`, `create_time` from `test_tb2_shard_by_strhash_name` as `test_tb2_shard_by_strhash_name` where (`name` in (...))")
 
 - sql: |
     /*+TDDL:BKA_JOIN(test_tb_shard_by_key,test_tb_shard_by_strhash_sk)*/
@@ -96,11 +94,11 @@
 
   plan: |
 
-    BKAJoin(condition="sk = key", type="inner")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_tb_shard_by_key", shardCount=4, sql="SELECT `id`, `name`, `key`, `create_time` FROM `test_tb_shard_by_key` AS `test_tb_shard_by_key` WHERE (`name` = 'xx')")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_tb_shard_by_strhash_sk", shardCount=4, sql="SELECT `id`, `name`, `sk`, `create_time` FROM `test_tb_shard_by_strhash_sk` AS `test_tb_shard_by_strhash_sk` WHERE (`sk` IN (...))")
+    bkajoin(condition="sk = key", type="inner")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tb_shard_by_key", shardcount=4, sql="select `id`, `name`, `key`, `create_time` from `test_tb_shard_by_key` as `test_tb_shard_by_key` where (`name` = 'xx')")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tb_shard_by_strhash_sk", shardcount=4, sql="select `id`, `name`, `sk`, `create_time` from `test_tb_shard_by_strhash_sk` as `test_tb_shard_by_strhash_sk` where (`sk` in (...))")
 
 - sql: |
     /*+TDDL:cmd_extra(enable_hash_join=false,enable_sort_merge_join=false,enable_nl_join=false)*/
@@ -118,11 +116,11 @@
 
   plan: |
 
-    BKAJoin(condition="id = id AND name = name", type="inner")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_tb_shard_by_hash_id_strhash_name_[0,1]", shardCount=8, sql="SELECT `id`, `name`, `sk`, `create_time` FROM `test_tb_shard_by_hash_id_strhash_name` AS `test_tb_shard_by_hash_id_strhash_name` WHERE (`sk` = 'xx')")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_tb2_shard_by_hash_id_strhash_name_[0,1]", shardCount=8, sql="SELECT `id`, `name`, `sk`, `create_time` FROM `test_tb2_shard_by_hash_id_strhash_name` AS `test_tb2_shard_by_hash_id_strhash_name` WHERE (((`id`, `name`)) IN (...))")
+    bkajoin(condition="id = id and name = name", type="inner")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tb_shard_by_hash_id_strhash_name_[0,1]", shardcount=8, sql="select `id`, `name`, `sk`, `create_time` from `test_tb_shard_by_hash_id_strhash_name` as `test_tb_shard_by_hash_id_strhash_name` where (`sk` = 'xx')")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tb2_shard_by_hash_id_strhash_name_[0,1]", shardcount=8, sql="select `id`, `name`, `sk`, `create_time` from `test_tb2_shard_by_hash_id_strhash_name` as `test_tb2_shard_by_hash_id_strhash_name` force index(`primary`) where (((`id`, `name`)) in (...))")
 
 - sql: |
     select *
@@ -137,10 +135,10 @@
         a.id>5;
 
   plan: |
+
     gather(concurrent=true)
       logicalview(tables="[0000-0003].test_tb_shard_by_hash_id_strhash_name_[0,1],test_tb3_shard_by_hash_id_strhash_sk_[0,1]", shardcount=8, sql="select `test_tb_shard_by_hash_id_strhash_name`.`id`, `test_tb_shard_by_hash_id_strhash_name`.`name`, `test_tb_shard_by_hash_id_strhash_name`.`sk`, `test_tb_shard_by_hash_id_strhash_name`.`create_time`, `test_tb3_shard_by_hash_id_strhash_sk`.`id` as `id0`, `test_tb3_shard_by_hash_id_strhash_sk`.`name` as `name0`, `test_tb3_shard_by_hash_id_strhash_sk`.`sk` as `sk0`, `test_tb3_shard_by_hash_id_strhash_sk`.`create_time` as `create_time0` from `test_tb_shard_by_hash_id_strhash_name` as `test_tb_shard_by_hash_id_strhash_name` inner join `test_tb3_shard_by_hash_id_strhash_sk` as `test_tb3_shard_by_hash_id_strhash_sk` on ((`test_tb_shard_by_hash_id_strhash_name`.`id` = `test_tb3_shard_by_hash_id_strhash_sk`.`id`) and (`test_tb_shard_by_hash_id_strhash_name`.`name` = `test_tb3_shard_by_hash_id_strhash_sk`.`sk`) and (`test_tb_shard_by_hash_id_strhash_name`.`id` > 5))")
 
-
 - sql: |
     select *
       from
@@ -154,6 +152,7 @@
         a.id>5;
 
   plan: |
+
     gather(concurrent=true)
       logicalview(tables="[0000-0003].test_tb_shard_by_hash_id_yyyymm_create_[0,1],test_tb2_shard_by_hash_id_yyyymm_modify_[0,1]", shardcount=8, sql="select `test_tb_shard_by_hash_id_yyyymm_create`.`id`, `test_tb_shard_by_hash_id_yyyymm_create`.`name`, `test_tb_shard_by_hash_id_yyyymm_create`.`sk`, `test_tb_shard_by_hash_id_yyyymm_create`.`create_time`, `test_tb2_shard_by_hash_id_yyyymm_modify`.`id` as `id0`, `test_tb2_shard_by_hash_id_yyyymm_modify`.`name` as `name0`, `test_tb2_shard_by_hash_id_yyyymm_modify`.`sk` as `sk0`, `test_tb2_shard_by_hash_id_yyyymm_modify`.`modify_time` from `test_tb_shard_by_hash_id_yyyymm_create` as `test_tb_shard_by_hash_id_yyyymm_create` inner join `test_tb2_shard_by_hash_id_yyyymm_modify` as `test_tb2_shard_by_hash_id_yyyymm_modify` on ((`test_tb_shard_by_hash_id_yyyymm_create`.`id` = `test_tb2_shard_by_hash_id_yyyymm_modify`.`id`) and (`test_tb_shard_by_hash_id_yyyymm_create`.`create_time` = `test_tb2_shard_by_hash_id_yyyymm_modify`.`modify_time`) and (`test_tb_shard_by_hash_id_yyyymm_create`.`id` > 5))")
 
@@ -172,11 +171,11 @@
 
   plan: |
 
-    BKAJoin(condition="id = id AND modify_time = create_time", type="inner")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_tb_shard_by_hash_id_yyyymm_create_[0,1]", shardCount=8, sql="SELECT `id`, `name`, `sk`, `create_time` FROM `test_tb_shard_by_hash_id_yyyymm_create` AS `test_tb_shard_by_hash_id_yyyymm_create` WHERE (`id` > 5)")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_tb3_shard_by_hash_id_yyyydd_modify_[0,1]", shardCount=8, sql="SELECT `id`, `name`, `sk`, `modify_time` FROM `test_tb3_shard_by_hash_id_yyyydd_modify` AS `test_tb3_shard_by_hash_id_yyyydd_modify` WHERE ((`id` > 5) AND (((`id`, `modify_time`)) IN (...)))")
+    bkajoin(condition="id = id and modify_time = create_time", type="inner")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tb_shard_by_hash_id_yyyymm_create_[0,1]", shardcount=8, sql="select `id`, `name`, `sk`, `create_time` from `test_tb_shard_by_hash_id_yyyymm_create` as `test_tb_shard_by_hash_id_yyyymm_create` where (`id` > 5)")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tb3_shard_by_hash_id_yyyydd_modify_[0,1]", shardcount=8, sql="select `id`, `name`, `sk`, `modify_time` from `test_tb3_shard_by_hash_id_yyyydd_modify` as `test_tb3_shard_by_hash_id_yyyydd_modify` force index(`primary`) where ((`id` > 5) and (((`id`, `modify_time`)) in (...)))")
 
 - sql: |
     select *
@@ -191,6 +190,7 @@
         a.id>5;
 
   plan: |
+
     gather(concurrent=true)
       logicalview(tables="[0000-0003].test_tb_shard_by_hash_id_mm_create_[00-11],test_tb2_shard_by_hash_id_mm_modify_[00-11]", shardcount=48, sql="select `test_tb_shard_by_hash_id_mm_create`.`id`, `test_tb_shard_by_hash_id_mm_create`.`name`, `test_tb_shard_by_hash_id_mm_create`.`sk`, `test_tb_shard_by_hash_id_mm_create`.`create_time`, `test_tb2_shard_by_hash_id_mm_modify`.`id` as `id0`, `test_tb2_shard_by_hash_id_mm_modify`.`name` as `name0`, `test_tb2_shard_by_hash_id_mm_modify`.`sk` as `sk0`, `test_tb2_shard_by_hash_id_mm_modify`.`modify_time` from `test_tb_shard_by_hash_id_mm_create` as `test_tb_shard_by_hash_id_mm_create` inner join `test_tb2_shard_by_hash_id_mm_modify` as `test_tb2_shard_by_hash_id_mm_modify` on ((`test_tb_shard_by_hash_id_mm_create`.`id` = `test_tb2_shard_by_hash_id_mm_modify`.`id`) and (`test_tb_shard_by_hash_id_mm_create`.`create_time` = `test_tb2_shard_by_hash_id_mm_modify`.`modify_time`) and (`test_tb_shard_by_hash_id_mm_create`.`id` > 5))")
 
@@ -209,11 +209,11 @@
 
   plan: |
 
-    BKAJoin(condition="modify_time = create_time AND id = id", type="inner")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` WHERE (`id` > 5)")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_tb2_shard_by_hash_id_mm_modify_[00-11]", shardCount=48, sql="SELECT `id`, `name`, `sk`, `modify_time` FROM `test_tb2_shard_by_hash_id_mm_modify` AS `test_tb2_shard_by_hash_id_mm_modify` WHERE ((`id` > 5) AND (((`modify_time`, `id`)) IN (...)))")
+    bkajoin(condition="modify_time = create_time and id = id", type="inner")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` where (`id` > 5)")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tb2_shard_by_hash_id_mm_modify_[00-11]", shardcount=48, sql="select `id`, `name`, `sk`, `modify_time` from `test_tb2_shard_by_hash_id_mm_modify` as `test_tb2_shard_by_hash_id_mm_modify` where ((`id` > 5) and (((`modify_time`, `id`)) in (...)))")
 
 - sql: |
     select *
@@ -228,6 +228,7 @@
         a.id>5;
 
   plan: |
+
     logicalview(tables="optest_0000.test_tb_no_shard,test_tb2_no_shard", sql="select `a`.`id`, `a`.`name`, `a`.`sk`, `a`.`create_time`, `a`.`modify_time`, `b`.`id`, `b`.`name`, `b`.`sk`, `b`.`create_time`, `b`.`modify_time` from `test_tb_no_shard` as `a` inner join `test_tb2_no_shard` as `b` on ((`a`.`id` = `b`.`id`) and (`a`.`create_time` = `b`.`modify_time`)) where (`a`.`id` > 5)")
 
 - sql: |
@@ -244,6 +245,7 @@
         a.id>5;
 
   plan: |
+
     logicalview(tables="optest_0000.test_tb_broadcast,test_tb2_broadcast", sql="select `a`.`id`, `a`.`name`, `a`.`sk`, `a`.`create_time`, `a`.`modify_time`, `b`.`id`, `b`.`name`, `b`.`sk`, `b`.`create_time`, `b`.`modify_time` from `test_tb_broadcast` as `a` inner join `test_tb2_broadcast` as `b` on ((`a`.`id` = `b`.`id`) and (`a`.`create_time` = `b`.`modify_time`)) where (`a`.`id` > 5)")
 
 - sql: |
@@ -259,6 +261,7 @@
         a.id>5;
 
   plan: |
+
     logicalview(tables="optest_0000.test_tb_no_shard,test_tb_broadcast", sql="select `a`.`id`, `a`.`name`, `a`.`sk`, `a`.`create_time`, `a`.`modify_time`, `b`.`id`, `b`.`name`, `b`.`sk`, `b`.`create_time`, `b`.`modify_time` from `test_tb_no_shard` as `a` inner join `test_tb_broadcast` as `b` on ((`a`.`id` = `b`.`id`) and (`a`.`create_time` = `b`.`modify_time`)) where (`a`.`id` > 5)")
 
 - sql: |
@@ -274,6 +277,7 @@
         a.id>5;
 
   plan: |
+
     gather(concurrent=true)
       logicalview(tables="[0000-0003].test_tb_shard_by_hash_id_yyyymm_create_[0,1],test_tb_broadcast", shardcount=8, sql="select `test_tb_shard_by_hash_id_yyyymm_create`.`id`, `test_tb_shard_by_hash_id_yyyymm_create`.`name`, `test_tb_shard_by_hash_id_yyyymm_create`.`sk`, `test_tb_shard_by_hash_id_yyyymm_create`.`create_time`, `test_tb_broadcast`.`id` as `id0`, `test_tb_broadcast`.`name` as `name0`, `test_tb_broadcast`.`sk` as `sk0`, `test_tb_broadcast`.`create_time` as `create_time0`, `test_tb_broadcast`.`modify_time` from `test_tb_shard_by_hash_id_yyyymm_create` as `test_tb_shard_by_hash_id_yyyymm_create` inner join `test_tb_broadcast` as `test_tb_broadcast` on ((`test_tb_shard_by_hash_id_yyyymm_create`.`id` = `test_tb_broadcast`.`id`) and (`test_tb_shard_by_hash_id_yyyymm_create`.`create_time` = `test_tb_broadcast`.`modify_time`) and (`test_tb_shard_by_hash_id_yyyymm_create`.`id` > 5))")
 
@@ -290,6 +294,7 @@
         a.id>5;
 
   plan: |
+
     gather(concurrent=true)
       logicalview(tables="[0000-0003].test_tb_uni_name,test_tb_uni_sk", shardcount=4, sql="select `test_tb_uni_name`.`id`, `test_tb_uni_name`.`name`, `test_tb_uni_name`.`sk`, `test_tb_uni_name`.`create_time`, `test_tb_uni_name`.`modify_time`, `test_tb_uni_sk`.`id` as `id0`, `test_tb_uni_sk`.`name` as `name0`, `test_tb_uni_sk`.`sk` as `sk0`, `test_tb_uni_sk`.`create_time` as `create_time0`, `test_tb_uni_sk`.`modify_time` as `modify_time0` from `test_tb_uni_name` as `test_tb_uni_name` inner join `test_tb_uni_sk` as `test_tb_uni_sk` on ((`test_tb_uni_name`.`id` = `test_tb_uni_sk`.`id`) and (`test_tb_uni_name`.`name` = `test_tb_uni_sk`.`sk`) and (`test_tb_uni_name`.`id` > 5))")
 
@@ -308,29 +313,11 @@
 
   plan: |
 
-    Project(id="id0", name="name0", sk="sk0", create_time="create_time0", modify_time="modify_time0", id0="id", name0="name", sk0="sk", create_time0="create_time", modify_time0="modify_time")
-      BKAJoin(condition="id = id AND sk = name", type="inner")
-        LogicalView(tables="optest_0000.test_tb_no_shard", sql="SELECT `id`, `name`, `sk`, `create_time`, `modify_time` FROM `test_tb_no_shard` AS `test_tb_no_shard` WHERE (`id` > 5)")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_tb_uni_name", shardCount=4, sql="SELECT `id`, `name`, `sk`, `create_time`, `modify_time` FROM `test_tb_uni_name` AS `test_tb_uni_name` WHERE ((`id` > 5) AND (((`id`, `name`)) IN (...)))")
-
-  #-
-#  sql: |
-#    select *
-#      from
-#        test_tb_range_id_name a
-#      join
-#        test_tb_range_id_sk b
-#      on
-#        a.name=b.sk
-#        and a.id=b.id
-#      where
-#        a.id>5;
-#
-#  plan: |
-#
-#    Gather(concurrent=true)
-#      LogicalView(tables="[0000-0003].test_tb_range_id_name,test_tb_range_id_sk", shardCount=4, sql="SELECT `id`, `name`, `sk`, `create_time`, `modify_time` FROM `test_tb_range_id_name` AS `test_tb_range_id_name` INNER JOIN `test_tb_range_id_sk` AS `test_tb_range_id_sk` ON ((((`test_tb_range_id_name`.`id` = `test_tb_range_id_sk`.`id`) AND (`test_tb_range_id_name`.`name` = `test_tb_range_id_sk`.`sk`)) AND (`test_tb_range_id_name`.`id` > 5)) AND (`test_tb_range_id_sk`.`id` > 5))")
+    project(id="id0", name="name0", sk="sk0", create_time="create_time0", modify_time="modify_time0", id0="id", name0="name", sk0="sk", create_time0="create_time", modify_time0="modify_time")
+      bkajoin(condition="id = id and sk = name", type="inner")
+        logicalview(tables="optest_0000.test_tb_no_shard", sql="select `id`, `name`, `sk`, `create_time`, `modify_time` from `test_tb_no_shard` as `test_tb_no_shard` where (`id` > 5)")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_tb_uni_name", shardcount=4, sql="select `id`, `name`, `sk`, `create_time`, `modify_time` from `test_tb_uni_name` as `test_tb_uni_name` force index(`primary`) where ((`id` > 5) and (((`id`, `name`)) in (...)))")
 
 - sql: |
     select *
@@ -344,11 +331,8 @@
         a.name='jack';
 
   plan: |
-
-    Gather(concurrent=true)
-      LogicalView(tables="[0000-0003].test_tb_shift_id,test_tb_shift_pk", shardCount=4, sql="SELECT `test_tb_shift_id`.`id`, `test_tb_shift_id`.`pk`, `test_tb_shift_id`.`name`, `test_tb_shift_id`.`sk`, `test_tb_shift_id`.`create_time`, `test_tb_shift_id`.`modify_time`, `test_tb_shift_pk`.`id` AS `id0`, `test_tb_shift_pk`.`pk` AS `pk0`, `test_tb_shift_pk`.`name` AS `name0`, `test_tb_shift_pk`.`sk` AS `sk0`, `test_tb_shift_pk`.`create_time` AS `create_time0`, `test_tb_shift_pk`.`modify_time` AS `modify_time0` FROM `test_tb_shift_id` AS `test_tb_shift_id` INNER JOIN `test_tb_shift_pk` AS `test_tb_shift_pk` ON ((`test_tb_shift_id`.`name` = 'jack') AND (`test_tb_shift_id`.`id` = `test_tb_shift_pk`.`pk`))")
-
-
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_tb_shift_id,test_tb_shift_pk", shardcount=4, sql="select `test_tb_shift_id`.`id`, `test_tb_shift_id`.`pk`, `test_tb_shift_id`.`name`, `test_tb_shift_id`.`sk`, `test_tb_shift_id`.`create_time`, `test_tb_shift_id`.`modify_time`, `test_tb_shift_pk`.`id` as `id0`, `test_tb_shift_pk`.`pk` as `pk0`, `test_tb_shift_pk`.`name` as `name0`, `test_tb_shift_pk`.`sk` as `sk0`, `test_tb_shift_pk`.`create_time` as `create_time0`, `test_tb_shift_pk`.`modify_time` as `modify_time0` from `test_tb_shift_id` as `test_tb_shift_id` inner join `test_tb_shift_pk` as `test_tb_shift_pk` on ((`test_tb_shift_id`.`name` = 'jack') and (`test_tb_shift_id`.`id` = `test_tb_shift_pk`.`pk`))")
 - sql: |
     /*+TDDL:BKA_JOIN(test_tb_shift_id,test_tb2_shift_pk)*/
     select *
@@ -362,13 +346,11 @@
         a.name='jack';
 
   plan: |
-
-    BKAJoin(condition="pk = id", type="inner")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_tb_shift_id", shardCount=4, sql="SELECT `id`, `pk`, `name`, `sk`, `create_time`, `modify_time` FROM `test_tb_shift_id` AS `test_tb_shift_id` WHERE (`name` = 'jack')")
-      Gather(concurrent=true)
-        LogicalView(tables="[0000-0003].test_tb2_shift_pk", shardCount=4, sql="SELECT `id`, `pk`, `name`, `sk`, `create_time`, `modify_time` FROM `test_tb2_shift_pk` AS `test_tb2_shift_pk` WHERE (`pk` IN (...))")
-
+    bkajoin(condition="pk = id", type="inner")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tb_shift_id", shardcount=4, sql="select `id`, `pk`, `name`, `sk`, `create_time`, `modify_time` from `test_tb_shift_id` as `test_tb_shift_id` where (`name` = 'jack')")
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tb2_shift_pk", shardcount=4, sql="select `id`, `pk`, `name`, `sk`, `create_time`, `modify_time` from `test_tb2_shift_pk` as `test_tb2_shift_pk` where (`pk` in (...))")
 - sql: |
     select *
       from
@@ -377,5 +359,5 @@
         a.MemberId=11;
 
   plan: |
-    phytableoperation(tables="optest_0003.[testorder]", sql="select `a`.`id`, `a`.`source`, `a`.`type`, `a`.`oriorderid`, `a`.`memberid` from ? as `a` where (`a`.`memberid` = 11)")
-
+    gather(concurrent=true)
+      logicalview(tables="optest_0003.testorder", sql="select `id`, `source`, `type`, `oriorderid`, `memberid` from `testorder` as `testorder` force index(`auto_shard_key_memberid`) where (`memberid` = 11)")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.config.yml
new file mode 100644
index 000000000..00aa0f6e2
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.config.yml
@@ -0,0 +1,8 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
+defaltxxAPPName.isNew:
+  false
+defaltxxAPPName.withSingleGroup:
+  true
+defaltxxAPPName.dbNumber:
+  2
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.ddl.yml
new file mode 100644
index 000000000..bbba4a0c7
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.ddl.yml
@@ -0,0 +1,68 @@
+test_hash_tb:
+  CREATE TABLE `test_hash_tb` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`ID`);
+
+test_hash_tb2:
+  CREATE TABLE `test_hash_tb2` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  KEY `auto_shard_key_ID_0` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`ID`);
+
+
+test_hash_tb3:
+  CREATE TABLE `test_hash_tb3` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  KEY `auto_shard_key_ID_0` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`ID`);
+
+test_hash_tb5:
+  CREATE TABLE `test_hash_tb5` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`),
+  KEY `auto_shard_key_ID_0` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`ID`) tbpartition by hash(id) tbpartitions 3;
+
+test_single:
+  CREATE TABLE `test_single` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+test_broadcast:
+  CREATE TABLE `test_broadcast` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST;
+
+test_broadcast_b:
+  CREATE TABLE `test_broadcast_b` (
+  `id` int(11) NOT NULL,
+  `name` varchar(30) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `auto_shard_key_ID` (`id`)
+  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST;
+
+
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.test.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.test.yml
new file mode 100644
index 000000000..ac39b2101
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/BroadcastRandomReadLvTest.test.yml
@@ -0,0 +1,59 @@
+- sql: |
+    /*+TDDL:CMD_EXTRA(ENABLE_PUSH_JOIN=FALSE, ENABLE_CBO_PUSH_JOIN=FALSE, ENABLE_DIRECT_PLAN=FALSE, ENABLE_POST_PLANNER=FALSE)*/
+    select a.id as b
+    from test_broadcast a left join test_hash_tb b on a.name = b.name 
+    where a.id=1;
+
+  plan: |
+    project(b="id")
+      hashjoin(condition="name = name", type="right", build="right")
+        logicalview(tables="optest_000000_group.test_hash_tb", sql="select `name` from `test_hash_tb` as `test_hash_tb`")
+        logicalview(tables="optest_single_group.test_broadcast", sql="select `id`, `name` from `test_broadcast` as `test_broadcast` where (`id` = 1)")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(ENABLE_PUSH_JOIN=FALSE, ENABLE_CBO_PUSH_JOIN=FALSE, ENABLE_DIRECT_PLAN=FALSE, ENABLE_POST_PLANNER=FALSE, BROADCAST_RANDOM_READ_IN_LOGICALVIEW=TRUE)*/
+    select a.id as b
+    from test_broadcast a left join test_hash_tb b on a.name = b.name 
+    where a.id=1;
+
+  plan: |
+    project(b="id")
+      hashjoin(condition="name = name", type="right", build="right")
+        logicalview(tables="optest_000000_group.test_hash_tb", sql="select `name` from `test_hash_tb` as `test_hash_tb`")
+        logicalview(tables="optest_000000_group.test_broadcast", sql="select `id`, `name` from `test_broadcast` as `test_broadcast` where (`id` = 1)")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(ENABLE_DIRECT_PLAN=FALSE, ENABLE_POST_PLANNER=FALSE, BROADCAST_RANDOM_READ_IN_LOGICALVIEW=TRUE)*/
+    select a.id as b
+    from test_broadcast a left join test_hash_tb b on a.name = b.name 
+    where a.id=1;
+
+  plan: |
+    logicalview(tables="optest_000000_group.test_broadcast,test_hash_tb", sql="select `test_broadcast`.`id` as `b` from `test_broadcast` as `test_broadcast` left join `test_hash_tb` as `test_hash_tb` on (`test_broadcast`.`name` = `test_hash_tb`.`name`) where (`test_broadcast`.`id` = 1)")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(ENABLE_DIRECT_PLAN=FALSE, ENABLE_POST_PLANNER=FALSE, BROADCAST_RANDOM_READ_IN_LOGICALVIEW=TRUE)*/
+    select a.id as b
+    from test_single a  
+    where a.id=1;
+
+  plan: |
+    logicalview(tables="optest_single_group.test_single", sql="select `id` as `b` from `test_single` as `test_single` where (`id` = 1)")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(ENABLE_DIRECT_PLAN=FALSE, ENABLE_POST_PLANNER=FALSE, BROADCAST_RANDOM_READ_IN_LOGICALVIEW=TRUE)*/
+    select a.id as b
+    from test_hash_tb a  
+    where a.id=1;
+
+  plan: |
+    logicalview(tables="optest_000000_group.test_hash_tb", sql="select `id` as `b` from `test_hash_tb` as `test_hash_tb` where (`id` = 1)")
+
+- sql: |
+    /*+TDDL:CMD_EXTRA(ENABLE_DIRECT_PLAN=FALSE, ENABLE_POST_PLANNER=FALSE, BROADCAST_RANDOM_READ_IN_LOGICALVIEW=TRUE)*/
+    select a.id as b
+    from test_hash_tb a  
+    where a.name='a';
+
+  plan: |
+    logicalview(tables="optest_000000_group.test_hash_tb", sql="select `id` as `b` from `test_hash_tb` as `test_hash_tb` where (`name` = 'a')")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/HashWindowPlanTest.test.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/HashWindowPlanTest.test.yml
index b334b512a..135b9e5c5 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/HashWindowPlanTest.test.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/HashWindowPlanTest.test.yml
@@ -62,12 +62,10 @@
     from t1 where c1 = 1;
 
   plan: |
-
     project(c1="c1", $1="f2w0$o0", $2="f3w0$o1")
       hashwindow(c1="c1", c2="c2", f2w0$o0="window#0sum($1)", f3w0$o1="window#0avg($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [sum($1), avg($1)])")
         exchange(distribution=hash[0], collation=[])
-          logicalview(tables="optest_0001.t1", sql="select `c1`, `c2` from `t1` as `t1` where (`c1` = 1)")
-
+          logicalview(tables="optest_0001.t1", sql="select `c1`, `c2` from `t1` as `t1` force index(`auto_shard_key_c1`) where (`c1` = 1)")
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_HASH_WINDOW=FALSE)*/
     select c1,
@@ -125,13 +123,11 @@
     from t1 order by c1;
 
   plan: |
-
     project(c1="c1", $1="f2w0$o0", $2="f3w0$o1")
       exchange(distribution=single, collation=[0 asc-nulls-first])
         sortwindow(c1="c1", c2="c2", f2w0$o0="window#0sum($1)", f3w0$o1="window#0avg($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [sum($1), avg($1)])")
           exchange(distribution=hash[0], collation=[0 asc-nulls-first])
-            logicalview(tables="[0000-0003].t1", shardcount=4, sql="select `c1`, `c2` from `t1` as `t1` order by `c1`")
-
+            logicalview(tables="[0000-0003].t1", shardcount=4, sql="select `c1`, `c2` from `t1` as `t1` force index(`auto_shard_key_c1`) order by `c1`")
 # window with scalar function
 - sql: |
     SELECT (3.14 DIV (   sum(     FROM_DAYS(248630980553))   OVER()   ) );
@@ -188,15 +184,13 @@
     );
 
   plan: |
-
     materializedsemijoin(condition="c1 = $0", type="semi")
-      logicalview(tables="[0000-0003].t1", shardcount=4, sql="select `c1`, `c2` from `t1` as `t1` where (`c1` in (...))")
+      logicalview(tables="[0000-0003].t1", shardcount=4, sql="select `c1`, `c2` from `t1` as `t1` force index(`auto_shard_key_c1`) where (`c1` in (...))")
       exchange(distribution=broadcast, collation=[])
         project($0="f2w0$o0")
           hashwindow(c1="c1", c2="c2", f2w0$o0="window#0max($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($1)])")
             exchange(distribution=hash[0], collation=[])
               logicalview(tables="[0000-0003].t2", shardcount=4, sql="select `c1`, `c2` from `t2` as `t2`")
-
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_SORT_WINDOW=FALSE)*/
     select *       
@@ -224,15 +218,13 @@
     );
 
   plan: |
-
     materializedsemijoin(condition="c1 = $0", type="semi")
-      logicalview(tables="[0000-0003].t1", shardcount=4, sql="select `c1`, `c2` from `t1` as `t1` where (`c1` in (...))")
+      logicalview(tables="[0000-0003].t1", shardcount=4, sql="select `c1`, `c2` from `t1` as `t1` force index(`auto_shard_key_c1`) where (`c1` in (...))")
       exchange(distribution=broadcast, collation=[])
         project($0="f2w0$o0")
           hashwindow(c1="c1", c2="c2", f2w0$o0="window#0max($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($1)])")
             exchange(distribution=hash[0], collation=[])
               logicalview(tables="[0000-0003].t2", shardcount=4, sql="select `c1`, `c2` from `t2` as `t2`")
-
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_SORT_WINDOW=FALSE)*/
     select *       
@@ -261,14 +253,12 @@
     ) t3 on t1.c1 = t3.max_c2;
 
   plan: |
-
     project(c10="c10", c2="c20", c1="c1", $1="f2w0$o0")
       bkajoin(condition="f2w0$o0 = c1", type="inner")
         hashwindow(c1="c1", c2="c2", f2w0$o0="window#0max($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [max($1)])")
           exchange(distribution=hash[0], collation=[])
             logicalview(tables="[0000-0003].t2", shardcount=4, sql="select `c1`, `c2` from `t2` as `t2`")
-        logicalview(tables="[0000-0003].t1", shardcount=4, sql="select `c1`, `c2` from `t1` as `t1` where (`c1` in (...))")
-
+        logicalview(tables="[0000-0003].t1", shardcount=4, sql="select `c1`, `c2` from `t1` as `t1` force index(`auto_shard_key_c1`) where (`c1` in (...))")
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_BKA_JOIN=FALSE ENABLE_BROADCAST_JOIN=FALSE ENABLE_SORT_WINDOW=FALSE)*/
     select *       
@@ -356,14 +346,12 @@
     from t_gsi force index(g_t_gsi);
 
   plan: |
-
     hashwindow(c1="c1", c2="c2", c3="c3", f3w0$o0="window#0sum($1)", f4w0$o1="window#0avg($1)", reference windows="window#0=window(partition {0} order by [] range between unbounded preceding and unbounded following aggs [sum($1), avg($1)])")
       exchange(distribution=hash[0], collation=[])
         project(c1="c1", c2="c2", c3="c3")
           bkajoin(condition="c1 = c1", type="inner")
             indexscan(tables="[0000-0003].g_t_gsi", shardcount=4, sql="select `c1`, `c2` from `g_t_gsi` as `g_t_gsi`")
-            logicalview(tables="[0000-0003].t_gsi", shardcount=4, sql="select `c1`, `c3` from `t_gsi` as `t_gsi` where (`c1` in (...))")
-
+            logicalview(tables="[0000-0003].t_gsi", shardcount=4, sql="select `c1`, `c3` from `t_gsi` as `t_gsi` force index(`primary`) where (`c1` in (...))")
 # with insert
 - sql: |
     /*+TDDL:cmd_extra(ENABLE_SORT_WINDOW=FALSE)*/
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/MppSelectWindowPlanTest.test.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/MppSelectWindowPlanTest.test.yml
index 2a7273869..37f3d06bc 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/MppSelectWindowPlanTest.test.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/MppSelectWindowPlanTest.test.yml
@@ -45,11 +45,9 @@
     from testwin;
 
   plan: |
-
-    SortWindow(id1="id1", id2="id2", id3="id3", f3w0$o0="window#0SUM($1)", f4w0$o1="window#0SUM($2)", Reference Windows="window#0=window(partition {0} order by [] rows between $3 PRECEDING and UNBOUNDED FOLLOWING aggs [SUM($1), SUM($2)])", constants="[1]")
-      Exchange(distribution=hash[0], collation=[0 ASC-nulls-first])
-        LogicalView(tables="[0000-0003].testwin", shardCount=4, sql="SELECT `id1`, `id2`, `id3` FROM `testwin` AS `testwin` ORDER BY `id1`")
-
+    sortwindow(id1="id1", id2="id2", id3="id3", f3w0$o0="window#0sum($1)", f4w0$o1="window#0sum($2)", reference windows="window#0=window(partition {0} order by [] rows between $3 preceding and unbounded following aggs [sum($1), sum($2)])", constants="[1]")
+      exchange(distribution=hash[0], collation=[0 asc-nulls-first])
+        logicalview(tables="[0000-0003].testwin", shardcount=4, sql="select `id1`, `id2`, `id3` from `testwin` as `testwin` force index(`auto_shard_key_id1`) order by `id1`")
 - sql: |
     select *,
      sum(id2) over (partition by id1 order by id2 asc ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) ow1,
@@ -163,7 +161,7 @@
                 exchange(distribution=hash[0], collation=[0 asc-nulls-first, 1 asc-nulls-first])
                   bkajoin(condition="id1 = pk", type="inner")
                     logicalview(tables="[0000-0003].testwin", shardcount=4, sql="select `id1`, `id2`, `id3` from `testwin` as `testwin` where ((`id1` < 10) and (`id1` in(1, 2))) order by `id1`, `id2`")
-                    logicalview(tables="[0000-0002].select_base_one_multi_db_multi_tb_[00-09]", shardcount=10, sql="select `pk`, `varchar_test`, `integer_test`, `char_test`, `tinyint_test`, `tinyint_1bit_test`, `smallint_test`, `mediumint_test`, `bit_test`, `bigint_test`, `float_test`, `double_test`, `decimal_test`, `date_test`, `time_test`, `datetime_test`, `timestamp_test`, `year_test` from `select_base_one_multi_db_multi_tb` as `select_base_one_multi_db_multi_tb` where ((`pk` in(1, 2)) and (`pk` < 10) and (`pk` in (...)))")
+                    logicalview(tables="[0000-0002].select_base_one_multi_db_multi_tb_[00-09]", shardcount=10, sql="select `pk`, `varchar_test`, `integer_test`, `char_test`, `tinyint_test`, `tinyint_1bit_test`, `smallint_test`, `mediumint_test`, `bit_test`, `bigint_test`, `float_test`, `double_test`, `decimal_test`, `date_test`, `time_test`, `datetime_test`, `timestamp_test`, `year_test` from `select_base_one_multi_db_multi_tb` as `select_base_one_multi_db_multi_tb` force index(`primary`) where ((`pk` in(1, 2)) and (`pk` < 10) and (`pk` in (...)))")
 - sql: |
     select *, rank() over(order by c1, c2) from tt order by c1;
 
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/PhyPushAggTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/PhyPushAggTest.yml
new file mode 100644
index 000000000..0e5921cda
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/PhyPushAggTest.yml
@@ -0,0 +1,159 @@
+SQL:
+  - sql: |
+      select count(*) from test_tc group by a,b
+    plan: |
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].test_tc_[00-27]", shardcount=28, sql="select count(*) as `count(*)` from `test_tc` as `test_tc` group by `a`, `b`")
+  - sql: |
+      select 1 from test_tc group by c
+    plan: |
+      project(1="?0")
+        hashagg(group="c")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].test_tc_[00-27]", shardcount=28, sql="select `c` from `test_tc` as `test_tc` group by `c`")
+  - sql: |
+      select count(userid) from user_log group by name, actionDate
+
+    plan: |
+      project(count(userid)="count(userid)")
+        hashagg(group="name,actiondate", count(userid)="sum(count(userid))")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].user_log_[0-6]", shardcount=28, sql="select `name`, `actiondate`, count(`userid`) as `count(userid)` from `user_log` as `user_log` group by `name`, `actiondate`")
+
+  - sql: |
+      select count(distinct userid),group_concat(operation, ',') from user_log group by name, actionDate
+
+    plan: |
+      project(count(distinct userid)="count(distinct userid)", group_concat(operation, ',')="group_concat(operation, ',')")
+        hashagg(group="name,actiondate", count(distinct userid)="count(userid) filter $4", group_concat(operation, ',')="min(group_concat(operation, ',')) filter $5")
+          project(name="name", actiondate="actiondate", userid="userid", group_concat(operation, ',')="group_concat(operation, ',')", $g_0="case(=($3, 0), 0, 1) = 0", $g_1="case(=($3, 0), 0, 1) = 1")
+            hashagg(group="name,actiondate,userid,$e", group_concat(operation, ',')="group_concat(operation, $f4)")
+              expand(projects="{name=name, actiondate=actiondate, userid=userid, operation=operation, $f4=$f4, $e=0}, {name=name, actiondate=actiondate, userid=null, operation=operation, $f4=$f4, $e=1}")
+                gather(concurrent=true)
+                  logicalview(tables="[0000-0003].user_log_[0-6]", shardcount=28, sql="select `name`, `actiondate`, `userid`, `operation`, ',' as `$f4` from `user_log` as `user_log`")
+  - sql: |
+      select count(*) from user_log limit 1
+
+    plan: |
+      limit(offset=0, fetch=?0)
+        hashagg(count(*)="sum(count(*))")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].user_log_[0-6]", shardcount=28, sql="select count(*) as `count(*)` from `user_log` as `user_log`")
+  - sql: |
+      select count(userid),group_concat(operation, ',') from user_log group by userid, name, actionDate
+
+    plan: |
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].user_log_[0-6]", shardcount=28, sql="select count(`userid`) as `count(userid)`, group_concat(`operation`, ','  ) as `group_concat(operation, ',')` from `user_log` as `user_log` group by `userid`, `name`, `actiondate`")
+  - sql: |
+      select count(*) from user_log
+
+    plan: |
+      hashagg(count(*)="sum(count(*))")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].user_log_[0-6]", shardcount=28, sql="select count(*) as `count(*)` from `user_log` as `user_log`")
+  - sql: |
+      select avg(userid) from user_log group by name, actionDate
+
+    plan: |
+      project(avg(userid)="$f2 / $f3")
+        hashagg(group="name,actiondate", $f2="sum($f2)", $f3="sum($f3)")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].user_log_[0-6]", shardcount=28, sql="select `name`, `actiondate`, sum(`userid`) as `$f2`, count(`userid`) as `$f3` from `user_log` as `user_log` group by `name`, `actiondate`")
+  - sql: |
+      select max(userid) from user_log group by name, actionDate
+
+    plan: |
+      project(max(userid)="max(userid)")
+        hashagg(group="name,actiondate", max(userid)="max(max(userid))")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].user_log_[0-6]", shardcount=28, sql="select `name`, `actiondate`, max(`userid`) as `max(userid)` from `user_log` as `user_log` group by `name`, `actiondate`")
+  - sql: |
+      select min(userid) from user_log group by name, actionDate
+
+    plan: |
+      project(min(userid)="min(userid)")
+        hashagg(group="name,actiondate", min(userid)="min(min(userid))")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].user_log_[0-6]", shardcount=28, sql="select `name`, `actiondate`, min(`userid`) as `min(userid)` from `user_log` as `user_log` group by `name`, `actiondate`")
+  - sql: |
+      select userid from user_log group by userid, name, actionDate
+
+    plan: |
+      gather(concurrent=true)
+        logicalview(tables="[0000-0003].user_log_[0-6]", shardcount=28, sql="select `userid` as `userid` from `user_log` as `user_log` group by `userid`, `name`, `actiondate`")
+  - sql: |
+      select distinct userid from user_log
+
+    plan: |
+      hashagg(group="userid")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].user_log_[0-6]", shardcount=28, sql="select `userid` from `user_log` as `user_log` group by `userid`")
+  - sql: |
+      select distinct userid from user_log  where userid!=3 order by userid
+
+    plan: |
+      memsort(sort="userid asc")
+        hashagg(group="userid")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].user_log_[0-6]", shardcount=28, sql="select `userid` from `user_log` as `user_log` where (`userid` <> ?) group by `userid`")
+  - sql: |
+      select b, c, avg(a), group_id() as g, grouping(b) as gb, grouping(c) as gc, grouping_id(b) as gib, GROUPING_ID(b, c) as gid from test_tb  group by cube(b, c)
+
+    plan: |
+      project(b="b", c="c", avg(a)="$f3 / $f4", g="case(=($2, 0), 0, =($2, 1), 0, =($2, 2), 0, 0)", gb="case(=($2, 0), 0, =($2, 1), 0, =($2, 2), 1, 1)", gc="case(=($2, 0), 0, =($2, 1), 1, =($2, 2), 0, 1)", gib="case(=($2, 0), 0, =($2, 1), 0, =($2, 2), 1, 1)", gid="case(=($2, 0), 0, =($2, 1), 1, =($2, 2), 2, 3)")
+        hashagg(group="b,c,$e", $f3="sum(a)", $f4="count(a)")
+          expand(projects="{b=b, c=c, a=a, $e=0}, {b=b, c=null, a=a, $e=1}, {b=null, c=c, a=a, $e=2}, {b=null, c=null, a=a, $e=3}")
+            gather(concurrent=true)
+              logicalview(tables="[0000-0003].test_tb_[00-27]", shardcount=28, sql="select `b`, `c`, `a` from `test_tb` as `test_tb`")
+  - sql: |
+      select b, c, avg(a) from test_tb group by rollup(b, c)
+
+    plan: |
+      project(b="b", c="c", avg(a)="$f3 / $f4")
+        hashagg(group="b,c,$e", $f3="sum(a)", $f4="count(a)")
+          expand(projects="{b=b, c=c, a=a, $e=0}, {b=b, c=null, a=a, $e=1}, {b=null, c=null, a=a, $e=3}")
+            gather(concurrent=true)
+              logicalview(tables="[0000-0003].test_tb_[00-27]", shardcount=28, sql="select `b`, `c`, `a` from `test_tb` as `test_tb`")
+DDL:
+  user_log:
+    CREATE TABLE user_log(
+    userId int,
+    name varchar(30),
+    operation varchar(30),
+    actionDate varchar(30)
+    ) dbpartition by hash(userId) tbpartition by HASH(actionDate) tbpartitions 7;
+
+  test_tb:
+    CREATE TABLE test_tb(
+    a int,
+    b bigint,
+    c int
+    ) dbpartition by hash(a) tbpartition by HASH(a) tbpartitions 7;
+
+  test_tc:
+    CREATE TABLE test_tc(
+    a int,
+    b bigint,
+    c int,
+    unique key(b,a),
+    unique key(c)
+    ) dbpartition by hash(a) tbpartition by HASH(a) tbpartitions 7;
+STATISTICS:
+  user_log:
+    10000
+  test_tb:
+    10000
+  test_tc:
+    10000
+CONFIG:
+  PUSH_AGG_INPUT_ROW_COUNT_THRESHOLD:
+    -1
+  PREFER_PUSH_AGG:
+    true
+  PREFER_PARTIAL_AGG:
+    true
+  ENABLE_CBO_PUSH_AGG:
+    false
+  defaltxxAPPName.isNew:
+    false
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectParameterizedTest.testLastInsertId.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectParameterizedTest.testLastInsertId.yml
index e2f01df49..d56fe5be5 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectParameterizedTest.testLastInsertId.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectParameterizedTest.testLastInsertId.yml
@@ -4,9 +4,7 @@
     where a.id = last_insert_id()
 
   plan: |
-
     phytableoperation(tables="optest_0000.[test_hash_tb]", sql="select `a`.`id` as `id` from ? as `a` where (`a`.`id` = ?)", params="0")
-
 - sql: |
       select id
       from test_hash_tb a
@@ -33,4 +31,4 @@
 
   plan: |
     project(last_insert_id(a.id + 100)="last_insert_id(id + ?0)")
-      logicalview(tables="optest_0002.test_hash_tb", sql="select `id` from `test_hash_tb` as `test_hash_tb` where (`id` = ?)")
\ No newline at end of file
+      logicalview(tables="optest_0002.test_hash_tb", sql="select `id` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where (`id` = ?)")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectParameterizedTest.testSelectLimitPlan.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectParameterizedTest.testSelectLimitPlan.yml
index daf04b17f..4cd3199fb 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectParameterizedTest.testSelectLimitPlan.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectParameterizedTest.testSelectLimitPlan.yml
@@ -43,7 +43,6 @@
     SELECT DISTINCT - + MIN( DISTINCT + + col0 ) col2 FROM random_groupby_12_tab1 AS cor0 GROUP BY col0 HAVING ( col0 ) IS NULL;;
 
   plan: |
-
     phytableoperation(tables="optest_0000.[random_groupby_12_tab1_00]", sql="select distinct (- (+ min(distinct (+ (+ `cor0`.`col0`))))) as `col2` from ? as `cor0` group by `cor0`.`col0` having (`col0` is null)")
 
 -
@@ -51,5 +50,4 @@
     SELECT DISTINCT - + MIN( DISTINCT + + id ) col2 FROM t_seller AS cor0 GROUP BY id HAVING ( id ) IS NULL;
 
   plan: |
-
-    phytableoperation(tables="optest_0000.[t_seller_00]", sql="select distinct (- (+ min(distinct (+ (+ `cor0`.`id`))))) as `col2` from ? as `cor0` group by `cor0`.`id` having (`id` is null)")
+    phytableoperation(tables="optest_0000.[t_seller_00]", sql="select distinct (- (+ min(distinct (+ (+ `cor0`.`id`))))) as `col2` from ? as `cor0` group by `cor0`.`id` having (`id` is null)")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectPlanTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectPlanTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectPlanTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWindowPlanTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWindowPlanTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWindowPlanTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithAggPlanTest.testSelectOrderBy.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithAggPlanTest.testSelectOrderBy.yml
index b77b34503..38cf298e8 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithAggPlanTest.testSelectOrderBy.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithAggPlanTest.testSelectOrderBy.yml
@@ -3,6 +3,5 @@ sql: |
 
 
 plan: |
-
-  MergeSort(sort="id ASC")
-    LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` ORDER BY `id`")
+  mergesort(sort="id asc")
+    logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) order by `id`")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithAggPlanTest.testSelectOrderByLimit.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithAggPlanTest.testSelectOrderByLimit.yml
index 562e79c2a..c1b4746b6 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithAggPlanTest.testSelectOrderByLimit.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithAggPlanTest.testSelectOrderByLimit.yml
@@ -3,6 +3,5 @@ sql: |
 
 
 plan: |
-
-  MergeSort(sort="id ASC", offset=5, fetch=10)
-    LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id`, `name`, `create_time` FROM `test_hash_tb` AS `test_hash_tb` ORDER BY `id` LIMIT 15")
+  mergesort(sort="id asc", offset=5, fetch=10)
+    logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id`, `name`, `create_time` from `test_hash_tb` as `test_hash_tb` force index(`primary`) order by `id` limit 15")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithAggPlanTest.testSelectWithJsonAggPlan.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithAggPlanTest.testSelectWithJsonAggPlan.yml
new file mode 100644
index 000000000..cad6d3634
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithAggPlanTest.testSelectWithJsonAggPlan.yml
@@ -0,0 +1,32 @@
+sql: |
+  select json_arrayagg(id) arr_agg, json_objectagg(name, create_time) obj_agg
+  from test_hash_tb a 
+  where a.name='xx';
+
+
+plan: | 
+  hashagg(arr_agg="json_array_globalagg(arr_agg)", obj_agg="json_object_globalagg(obj_agg)")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select (json_arrayagg(`id`)) as `arr_agg`, (json_objectagg(`name`, `create_time`)) as `obj_agg` from `test_hash_tb` as `test_hash_tb` where (`name` = 'xx')")
+
+sql: |
+  /*+TDDL:enable_push_agg=false*/select json_arrayagg(id) arr_agg, json_objectagg(name, create_time) obj_agg
+  from test_hash_tb a 
+  where a.name='xx';
+
+
+plan: |
+  hashagg(arr_agg="json_array_globalagg(arr_agg)", obj_agg="json_object_globalagg(obj_agg)")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select (json_arrayagg(`id`)) as `arr_agg`, (json_objectagg(`name`, `create_time`)) as `obj_agg` from `test_hash_tb` as `test_hash_tb` where (`name` = 'xx')")
+
+sql: |
+  /*+TDDL:enable_cbo_push_agg=false*/select json_arrayagg(id) arr_agg, json_objectagg(name, create_time) obj_agg
+  from test_hash_tb a 
+  where a.name='xx';
+
+
+plan: |
+  hashagg(arr_agg="json_array_globalagg(arr_agg)", obj_agg="json_object_globalagg(obj_agg)")
+    gather(concurrent=true)
+      logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select (json_arrayagg(`id`)) as `arr_agg`, (json_objectagg(`name`, `create_time`)) as `obj_agg` from `test_hash_tb` as `test_hash_tb` where (`name` = 'xx')")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithInPlanTest.testSelectInPlan.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithInPlanTest.testSelectInPlan.yml
index b526a3a26..7fed7605d 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithInPlanTest.testSelectInPlan.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/selectplan/SelectWithInPlanTest.testSelectInPlan.yml
@@ -16,12 +16,10 @@
 
 
   plan: |
-
     materializedsemijoin(condition="id = expr$0", type="semi")
       gather(concurrent=true)
-        logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id` from `test_hash_tb` as `test_hash_tb` where (`id` in (...))")
+        logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where (`id` in (...))")
       dynamicvalues(tuples=[{ 4 }, { 5 }, { 7 }])
-
 - sql: |
     select id
     from test_hash_tb a
@@ -60,14 +58,12 @@
 
 
   plan: |
-
     project(id="id")
       bkajoin(condition="expr$0 = id", type="inner")
         hashagg(group="expr$0")
           dynamicvalues(tuples=[{ 4 }, { 6 }, { 7 }])
         gather(concurrent=true)
-          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id` from `test_hash_tb` as `test_hash_tb` where ((`name` in('a', 'b', 'c')) and (`id` in (...)))")
-
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where ((`name` in('a', 'b', 'c')) and (`id` in (...)))")
 - sql: |
     select id
     from test_hash_tb a
@@ -86,11 +82,9 @@
 
 
   plan: |
-
-    LogicalInsert(table="test_hash_tb1", columns=RecordType(INTEGER id), mode=multi)
-      Gather(concurrent=true)
-        LogicalView(tables="[0001-0003].test_hash_tb", shardCount=3, sql="SELECT `id` FROM `test_hash_tb` AS `test_hash_tb` WHERE (`id` IN(5, 6, 7))")
-
+    logicalinsert(table="test_hash_tb1", columns=recordtype(integer id), mode=multi)
+      gather(concurrent=true)
+        logicalview(tables="[0001-0003].test_hash_tb", shardcount=3, sql="select `id` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where (`id` in(5, 6, 7))")
 - sql: |
     select id
     from test_hash_tb2 a
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/DerivedSubQueryPlanTest.testPushOptToDerivedNonCorrSubQuery.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/DerivedSubQueryPlanTest.testPushOptToDerivedNonCorrSubQuery.yml
index 91fd638b9..7b8a8aa40 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/DerivedSubQueryPlanTest.testPushOptToDerivedNonCorrSubQuery.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/DerivedSubQueryPlanTest.testPushOptToDerivedNonCorrSubQuery.yml
@@ -27,7 +27,6 @@
 
 
   plan: |
-
     phytableoperation(tables="optest_0001.[test_hash_tb]", sql="select `a`.`id`, `a`.`name` from (select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb`.`int_col1`, `test_hash_tb`.`int_col2`, `test_hash_tb`.`int_col3`, `test_hash_tb`.`int_col4`, `test_hash_tb`.`int_col5`, `test_hash_tb`.`int_col6` from ? as `test_hash_tb`) as `a` where (`a`.`id` = 5)")
 
 - sql: |
@@ -217,4 +216,4 @@
                   gather(concurrent=true)
                     logicalview(tables="[0000-0003].or_out_stock", shardcount=4, sql="select `trans_no`, count(*) as `butoon_type` from `or_out_stock` as `or_out_stock` group by `trans_no`")
       gather(concurrent=true)
-        logicalview(tables="[0000-0003].or_order_item", shardcount=4, sql="select `id`, `order_no`, `sub_order_no`, `bag_code`, `product_code`, `product_name`, `one_category_code`, `one_category_name`, `two_category_code`, `two_category_name`, `three_category_code`, `three_category_name`, `product_brand_code`, `product_brand_name`, `product_barcode`, `product_sku`, `product_price`, `product_spec`, `platform_product_sku`, `product_meter_unit`, `platform_product_code`, `platform_product_name`, `platform_product_url`, `buy_number`, `out_stock_number`, `product_weight`, `product_volume`, `discount_amount`, `share_amount`, `payable_amount`, `coupon_duct_amount`, `paid_amount`, `is_split`, `group_product_code`, `group_product_name`, `integral_share`, `is_out_stock`, `is_gift`, `activity_name`, `activity_id`, `platform_commision_point`, `platform_commision`, `distributor_commision`, `salesman_commision`, `return_type`, `factory_cost`, `is_cancel`, `erp_order_item_id`, `create_by`, `create_time`, `last_update_by`, `last_update_time`, `platform_product_index`, `salesman_second_commision` from `or_order_item` as `or_order_item` where (`order_no` in (...))")
+        logicalview(tables="[0000-0003].or_order_item", shardcount=4, sql="select `id`, `order_no`, `sub_order_no`, `bag_code`, `product_code`, `product_name`, `one_category_code`, `one_category_name`, `two_category_code`, `two_category_name`, `three_category_code`, `three_category_name`, `product_brand_code`, `product_brand_name`, `product_barcode`, `product_sku`, `product_price`, `product_spec`, `platform_product_sku`, `product_meter_unit`, `platform_product_code`, `platform_product_name`, `platform_product_url`, `buy_number`, `out_stock_number`, `product_weight`, `product_volume`, `discount_amount`, `share_amount`, `payable_amount`, `coupon_duct_amount`, `paid_amount`, `is_split`, `group_product_code`, `group_product_name`, `integral_share`, `is_out_stock`, `is_gift`, `activity_name`, `activity_id`, `platform_commision_point`, `platform_commision`, `distributor_commision`, `salesman_commision`, `return_type`, `factory_cost`, `is_cancel`, `erp_order_item_id`, `create_by`, `create_time`, `last_update_by`, `last_update_time`, `platform_product_index`, `salesman_second_commision` from `or_order_item` as `or_order_item` force index(`auto_shard_key_order_no`) where (`order_no` in (...))")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/DerivedSubQueryPlanTest.testPushOptToEmbedDerivedSubQuery.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/DerivedSubQueryPlanTest.testPushOptToEmbedDerivedSubQuery.yml
index 9a791ade4..92b035c72 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/DerivedSubQueryPlanTest.testPushOptToEmbedDerivedSubQuery.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/DerivedSubQueryPlanTest.testPushOptToEmbedDerivedSubQuery.yml
@@ -107,9 +107,8 @@
     group by tb.int_col1
 
   plan: |
-
     project(count(distinct tb.id)="count(distinct tb.id)", int_col1="int_col1")
       hashagg(group="int_col1", count(distinct tb.id)="count(id)")
         hashagg(group="int_col1,id")
           gather(concurrent=true)
-            logicalview(tables="[0000-0003].msg_tb_[0-7]", shardcount=8, sql="select `int_col1`, `id` from `msg_tb` as `msg_tb` where (`msg_id` > 1000)")
+            logicalview(tables="[0000-0003].msg_tb_[0-7]", shardcount=8, sql="select `int_col1`, `id` from `msg_tb` as `msg_tb` where (`msg_id` > 1000) group by `id`, `int_col1`")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/FilterSubQueryPlanTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/FilterSubQueryPlanTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/FilterSubQueryPlanTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/SimpleSubQueryPlanTest.config.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/SimpleSubQueryPlanTest.config.yml
new file mode 100644
index 000000000..e26534b78
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/SimpleSubQueryPlanTest.config.yml
@@ -0,0 +1,2 @@
+ENABLE_AUTO_FORCE_INDEX:
+  false
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/SimpleSubQueryPlanTest.testBaseFilterSubQuery.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/SimpleSubQueryPlanTest.testBaseFilterSubQuery.yml
index 21c1f7c32..ea2b3e58b 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/SimpleSubQueryPlanTest.testBaseFilterSubQuery.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/SimpleSubQueryPlanTest.testBaseFilterSubQuery.yml
@@ -391,3 +391,13 @@
       logicalview(tables="[0000-0003].select_dml_12_one_pk_no_uk_two_gsi_partition_by_pk_[00-11]", shardcount=12, sql="select `pk` from `select_dml_12_one_pk_no_uk_two_gsi_partition_by_pk` as `select_dml_12_one_pk_no_uk_two_gsi_partition_by_pk`")
     gather(concurrent=true)
       logicalview(tables="[0000-0003].select_dml_12_one_pk_no_uk_two_gsi_partition_by_pk_[00-11]", shardcount=12, sql="select `pk` from `select_dml_12_one_pk_no_uk_two_gsi_partition_by_pk` as `select_dml_12_one_pk_no_uk_two_gsi_partition_by_pk`")
+
+- sql: |
+    select sum(select sum(int_col1) from test_tb5 where id=t.id) as s1 from test_tb6 t join test_hash_tb2 t2 on t.name=t2.name;
+  plan: |
+    HashAgg(s1="SUM($f0)")
+      Project($f0="sum(int_col1)", cor=[$cor0])
+        BKAJoin(condition="name = name", type="inner")
+          LogicalView(tables="optest_0000.test_tb5,test_tb6", sql="SELECT `test_tb6`.`id`, `test_tb6`.`name`, `test_tb6`.`create_time`, `test_tb6`.`int_col1`, `test_tb6`.`int_col2`, `test_tb6`.`int_col3`, `test_tb6`.`int_col4`, `test_tb6`.`int_col5`, `test_tb6`.`int_col6`, `t0`.`sum(int_col1)`, `t0`.`id` AS `id0`, `t0`.`sum(int_col1)2` FROM (SELECT SUM(`int_col1`) AS `sum(int_col1)`, `id`, SUM(`int_col1`) AS `sum(int_col1)2` FROM `test_tb5` AS `test_tb5` GROUP BY `id`) AS `t0` RIGHT JOIN `test_tb6` AS `test_tb6` ON (`t0`.`id` = `test_tb6`.`id`)")
+          Gather(concurrent=true)
+            LogicalView(tables="[0000-0003].test_hash_tb2", shardCount=4, sql="SELECT `id`, `name`, `create_time`, `int_col1`, `int_col2`, `int_col3`, `int_col4`, `int_col5`, `int_col6` FROM `test_hash_tb2` AS `test_hash_tb2` WHERE (`name` IN (...))")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/SimpleSubQueryPlanTest.testPushFilterToJoinSubQuery.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/SimpleSubQueryPlanTest.testPushFilterToJoinSubQuery.yml
index 63e94bdd9..e1fe495ad 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/SimpleSubQueryPlanTest.testPushFilterToJoinSubQuery.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/SimpleSubQueryPlanTest.testPushFilterToJoinSubQuery.yml
@@ -17,8 +17,8 @@
 
 
   plan: |
-    phytableoperation(tables="optest_0001.[test_hash_tb, test_hash_tb2]", sql="select `a`.`id`, `a`.`name` from (select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb`.`int_col1`, `test_hash_tb`.`int_col2`, `test_hash_tb`.`int_col3`, `test_hash_tb`.`int_col4`, `test_hash_tb`.`int_col5`, `test_hash_tb`.`int_col6` from ? as `test_hash_tb`) as `a` inner join (select `test_hash_tb2`.`id`, `test_hash_tb2`.`name`, `test_hash_tb2`.`create_time`, `test_hash_tb2`.`int_col1`, `test_hash_tb2`.`int_col2`, `test_hash_tb2`.`int_col3`, `test_hash_tb2`.`int_col4`, `test_hash_tb2`.`int_col5`, `test_hash_tb2`.`int_col6` from ? as `test_hash_tb2`) as `b` on ((`b`.`id` = `a`.`id`) and (`a`.`id` = 1))")
-
+    gather(concurrent=true)
+      logicalview(tables="optest_0001.test_hash_tb,test_hash_tb2", sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name` from `test_hash_tb` as `test_hash_tb` inner join `test_hash_tb2` as `test_hash_tb2` on ((`test_hash_tb2`.`id` = 1) and (`test_hash_tb`.`id` = 1) and (`test_hash_tb`.`id` = `test_hash_tb2`.`id`))")
 - sql: |
     select
     	a.id,
@@ -51,8 +51,8 @@
 
 
   plan: |
-    phytableoperation(tables="optest_0002.[test_hash_tb, test_hash_tb2]", sql="select `a`.`id`, `a`.`name` from (select `test_hash_tb`.`id`, `test_hash_tb`.`name`, `test_hash_tb`.`create_time`, `test_hash_tb`.`int_col1`, `test_hash_tb`.`int_col2`, `test_hash_tb`.`int_col3`, `test_hash_tb`.`int_col4`, `test_hash_tb`.`int_col5`, `test_hash_tb`.`int_col6` from ? as `test_hash_tb` where (`test_hash_tb`.`int_col3` = 5)) as `a` inner join (select `test_hash_tb2`.`id`, `test_hash_tb2`.`name`, `test_hash_tb2`.`create_time`, `test_hash_tb2`.`int_col1`, `test_hash_tb2`.`int_col2`, `test_hash_tb2`.`int_col3`, `test_hash_tb2`.`int_col4`, `test_hash_tb2`.`int_col5`, `test_hash_tb2`.`int_col6` from ? as `test_hash_tb2` where (`test_hash_tb2`.`id` = 2)) as `b` on (`b`.`id` = `a`.`id`)")
-
+    gather(concurrent=true)
+      logicalview(tables="optest_0002.test_hash_tb2,test_hash_tb", sql="select `test_hash_tb`.`id`, `test_hash_tb`.`name` from `test_hash_tb2` as `test_hash_tb2` inner join `test_hash_tb` as `test_hash_tb` on (`test_hash_tb2`.`id` = `test_hash_tb`.`id`) where ((`test_hash_tb2`.`id` = 2) and (`test_hash_tb`.`int_col3` = 5))")
 - sql: |
     select 
       a.id, 
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/UnionSubQueryPlanTest.testPushOptToSingleUnionAllSubQuery.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/UnionSubQueryPlanTest.testPushOptToSingleUnionAllSubQuery.yml
index a071d1664..66fa9849c 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/UnionSubQueryPlanTest.testPushOptToSingleUnionAllSubQuery.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/UnionSubQueryPlanTest.testPushOptToSingleUnionAllSubQuery.yml
@@ -190,13 +190,12 @@
     where a_uni_b.id = c.id and c.id > 5
 
   plan: |
-
-    Project(id="id")
-      BKAJoin(condition="id = id", type="inner")
-        UnionAll(concurrent=true)
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id` FROM `test_hash_tb` AS `test_hash_tb` WHERE ((`name` = 'xx') AND (`id` > 5))")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].test_hash_tb2", shardCount=4, sql="SELECT `id` FROM `test_hash_tb2` AS `test_hash_tb2` WHERE ((`name` = 'xx') AND (`id` > 5))")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id` FROM `test_hash_tb` AS `test_hash_tb` WHERE ((`id` > 5) AND (`id` IN (...)))")
+    project(id="id")
+      bkajoin(condition="id = id", type="inner")
+        unionall(concurrent=true)
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id` from `test_hash_tb` as `test_hash_tb` where ((`name` = 'xx') and (`id` > 5))")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].test_hash_tb2", shardcount=4, sql="select `id` from `test_hash_tb2` as `test_hash_tb2` where ((`name` = 'xx') and (`id` > 5))")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where ((`id` > 5) and (`id` in (...)))")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/UnionSubQueryPlanTest.testPushOptToSingleUnionDistinctSubQuery.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/UnionSubQueryPlanTest.testPushOptToSingleUnionDistinctSubQuery.yml
index aad5138d9..ee89fbbe2 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/UnionSubQueryPlanTest.testPushOptToSingleUnionDistinctSubQuery.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/subqueryplan/UnionSubQueryPlanTest.testPushOptToSingleUnionDistinctSubQuery.yml
@@ -190,13 +190,12 @@
     where a_uni_b.id = c.id and c.id > 5
 
   plan: |
-
-    Project(id="id")
-      BKAJoin(condition="id = id", type="inner")
-        UnionAll(concurrent=true)
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id` FROM `test_hash_tb` AS `test_hash_tb` WHERE ((`name` = 'xx') AND (`id` > 5))")
-          Gather(concurrent=true)
-            LogicalView(tables="[0000-0003].test_hash_tb2", shardCount=4, sql="SELECT `id` FROM `test_hash_tb2` AS `test_hash_tb2` WHERE ((`name` = 'xx') AND (`id` > 5))")
-        Gather(concurrent=true)
-          LogicalView(tables="[0000-0003].test_hash_tb", shardCount=4, sql="SELECT `id` FROM `test_hash_tb` AS `test_hash_tb` WHERE ((`id` > 5) AND (`id` IN (...)))")
+    project(id="id")
+      bkajoin(condition="id = id", type="inner")
+        unionall(concurrent=true)
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id` from `test_hash_tb` as `test_hash_tb` where ((`name` = 'xx') and (`id` > 5))")
+          gather(concurrent=true)
+            logicalview(tables="[0000-0003].test_hash_tb2", shardcount=4, sql="select `id` from `test_hash_tb2` as `test_hash_tb2` where ((`name` = 'xx') and (`id` > 5))")
+        gather(concurrent=true)
+          logicalview(tables="[0000-0003].test_hash_tb", shardcount=4, sql="select `id` from `test_hash_tb` as `test_hash_tb` force index(`primary`) where ((`id` > 5) and (`id` in (...)))")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpcc/TpccPlanTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpcc/TpccPlanTest.yml
index 1b0bea911..32eac4771 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpcc/TpccPlanTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpcc/TpccPlanTest.yml
@@ -3,32 +3,38 @@
       WHERE c_w_id = 1 AND c_d_id = 1 AND c_id = 1
 
   plan: |
-    phytableoperation(tables="optest_0001.[bmsql_customer, bmsql_warehouse]", sql="select `bmsql_customer`.`c_discount`, `bmsql_customer`.`c_last`, `bmsql_customer`.`c_credit`, `bmsql_warehouse`.`w_tax` from ? as `bmsql_customer` inner join ? as `bmsql_warehouse` on (`bmsql_warehouse`.`w_id` = `bmsql_customer`.`c_w_id`) where ((`bmsql_customer`.`c_w_id` = 1) and (`bmsql_customer`.`c_d_id` = 1) and (`bmsql_customer`.`c_id` = 1))")
+
+    gather(concurrent=true)
+      logicalview(tables="optest_0001.bmsql_customer,bmsql_warehouse", sql="select `bmsql_customer`.`c_discount`, `bmsql_customer`.`c_last`, `bmsql_customer`.`c_credit`, `bmsql_warehouse`.`w_tax` from `bmsql_customer` as `bmsql_customer` inner join `bmsql_warehouse` as `bmsql_warehouse` on ((`bmsql_warehouse`.`w_id` = 1) and (`bmsql_customer`.`c_w_id` = 1) and (`bmsql_customer`.`c_d_id` = 1) and (`bmsql_customer`.`c_id` = 1) and (`bmsql_customer`.`c_w_id` = `bmsql_warehouse`.`w_id`) and (`bmsql_customer`.`c_d_id` = `bmsql_warehouse`.`w_id`) and (`bmsql_customer`.`c_id` = `bmsql_warehouse`.`w_id`) and (`bmsql_customer`.`c_w_id` = `bmsql_customer`.`c_d_id`) and (`bmsql_customer`.`c_w_id` = `bmsql_customer`.`c_id`) and (`bmsql_customer`.`c_d_id` = `bmsql_customer`.`c_id`))")
 
 - sql: |
     SELECT d_tax, d_next_o_id     FROM bmsql_district     WHERE d_w_id = 1 AND d_id = 1     FOR UPDATE
 
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_district]", sql="select `bmsql_district`.`d_tax`, `bmsql_district`.`d_next_o_id` from ? as `bmsql_district` where ((`bmsql_district`.`d_w_id` = 1) and (`bmsql_district`.`d_id` = 1)) for update")
 
 - sql: |
     UPDATE bmsql_district     SET d_next_o_id = d_next_o_id + 1     WHERE d_w_id = 1 AND d_id = 1
 
   plan: |
-    LogicalModifyView(tables="optest_0001.bmsql_district", sql="UPDATE `bmsql_district` AS `bmsql_district` SET `d_next_o_id` = (`d_next_o_id` + 1) WHERE ((`d_w_id` = 1) AND (`d_id` = 1))")
+
+    logicalmodifyview(tables="optest_0001.bmsql_district", sql="update `bmsql_district` as `bmsql_district` force index(`primary`) set `d_next_o_id` = (`d_next_o_id` + 1) where ((`d_w_id` = 1) and (`d_id` = 1))")
 
 - sql: |
     INSERT INTO bmsql_oorder (    o_id, o_d_id, o_w_id, o_c_id, o_entry_d,     o_ol_cnt, o_all_local) VALUES (1, 1,
     1, 1, 1, 1, 1)
 
   plan: |
-    PhyTableOperation(tables="optest_0001.[bmsql_oorder]", sql="INSERT INTO ? (`o_w_id`, `o_d_id`, `o_id`, `o_c_id`, `o_carrier_id`, `o_ol_cnt`, `o_all_local`, `o_entry_d`) VALUES(?, 1, 1, 1, NULL, 1, 1, 1)", params="`bmsql_oorder`,1")
+
+    phytableoperation(tables="optest_0001.[bmsql_oorder]", sql="insert into ? (`o_w_id`, `o_d_id`, `o_id`, `o_c_id`, `o_carrier_id`, `o_ol_cnt`, `o_all_local`, `o_entry_d`) values(?, 1, 1, 1, null, 1, 1, 1)", params="`bmsql_oorder`,1")
 
 - sql: |
     INSERT INTO bmsql_new_order (    no_o_id, no_d_id, no_w_id) VALUES (1, 1, 1)
 
   plan: |
-    PhyTableOperation(tables="optest_0001.[bmsql_new_order]", sql="INSERT INTO ? (`no_w_id`, `no_d_id`, `no_o_id`) VALUES(?, 1, 1)", params="`bmsql_new_order`,1")
+
+    phytableoperation(tables="optest_0001.[bmsql_new_order]", sql="insert into ? (`no_w_id`, `no_d_id`, `no_o_id`) values(?, 1, 1)", params="`bmsql_new_order`,1")
 
 - sql: |
     SELECT s_quantity, s_data,        s_dist_01, s_dist_02, s_dist_03, s_dist_04,        s_dist_05, s_dist_06,
@@ -36,103 +42,144 @@
     FOR UPDATE
 
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_stock]", sql="select `bmsql_stock`.`s_quantity`, `bmsql_stock`.`s_data`, `bmsql_stock`.`s_dist_01`, `bmsql_stock`.`s_dist_02`, `bmsql_stock`.`s_dist_03`, `bmsql_stock`.`s_dist_04`, `bmsql_stock`.`s_dist_05`, `bmsql_stock`.`s_dist_06`, `bmsql_stock`.`s_dist_07`, `bmsql_stock`.`s_dist_08`, `bmsql_stock`.`s_dist_09`, `bmsql_stock`.`s_dist_10` from ? as `bmsql_stock` where ((`bmsql_stock`.`s_w_id` = 1) and (`bmsql_stock`.`s_i_id` = 1)) for update")
 
 - sql: |
     SELECT i_price, i_name, i_data     FROM bmsql_item     WHERE i_id = 1
 
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_item]", sql="select `bmsql_item`.`i_price`, `bmsql_item`.`i_name`, `bmsql_item`.`i_data` from ? as `bmsql_item` where (`bmsql_item`.`i_id` = 1)")
 
 - sql: |
     UPDATE bmsql_stock     SET s_quantity = 1, s_ytd = s_ytd + 1,         s_order_cnt = s_order_cnt + 1,         s_remote_cnt = s_remote_cnt + 1     WHERE s_w_id = 1 AND s_i_id = 1
   plan: |
-    LogicalModifyView(tables="optest_0001.bmsql_stock", sql="UPDATE `bmsql_stock` AS `bmsql_stock` SET `s_quantity` = 1 , `s_ytd` = (`s_ytd` + 1) , `s_order_cnt` = (`s_order_cnt` + 1) , `s_remote_cnt` = (`s_remote_cnt` + 1) WHERE ((`s_w_id` = 1) AND (`s_i_id` = 1))")
+
+    logicalmodifyview(tables="optest_0001.bmsql_stock", sql="update `bmsql_stock` as `bmsql_stock` force index(`primary`) set `s_quantity` = 1 , `s_ytd` = (`s_ytd` + 1) , `s_order_cnt` = (`s_order_cnt` + 1) , `s_remote_cnt` = (`s_remote_cnt` + 1) where ((`s_w_id` = 1) and (`s_i_id` = 1))")
+
 - sql: |
     INSERT INTO bmsql_order_line (    ol_o_id, ol_d_id, ol_w_id, ol_number,     ol_i_id, ol_supply_w_id, ol_quantity,     ol_amount, ol_dist_info) VALUES (1, 1, 1, 1, 1, 1, 1, 1, 1)
   plan: |
-    PhyTableOperation(tables="optest_0001.[bmsql_order_line]", sql="INSERT INTO ? (`ol_w_id`, `ol_d_id`, `ol_o_id`, `ol_number`, `ol_i_id`, `ol_amount`, `ol_supply_w_id`, `ol_quantity`, `ol_dist_info`) VALUES(?, 1, 1, 1, 1, 1, 1, 1, 1)", params="`bmsql_order_line`,1")
+
+    phytableoperation(tables="optest_0001.[bmsql_order_line]", sql="insert into ? (`ol_w_id`, `ol_d_id`, `ol_o_id`, `ol_number`, `ol_i_id`, `ol_amount`, `ol_supply_w_id`, `ol_quantity`, `ol_dist_info`) values(?, 1, 1, 1, 1, 1, 1, 1, 1)", params="`bmsql_order_line`,1")
+
 - sql: |
     SELECT w_name, w_street_1, w_street_2, w_city,        w_state, w_zip     FROM bmsql_warehouse     WHERE w_id = 1
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_warehouse]", sql="select `bmsql_warehouse`.`w_name`, `bmsql_warehouse`.`w_street_1`, `bmsql_warehouse`.`w_street_2`, `bmsql_warehouse`.`w_city`, `bmsql_warehouse`.`w_state`, `bmsql_warehouse`.`w_zip` from ? as `bmsql_warehouse` where (`bmsql_warehouse`.`w_id` = 1)")
+
 - sql: |
     SELECT d_name, d_street_1, d_street_2, d_city,        d_state, d_zip     FROM bmsql_district     WHERE d_w_id = 1 AND d_id = 1
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_district]", sql="select `bmsql_district`.`d_name`, `bmsql_district`.`d_street_1`, `bmsql_district`.`d_street_2`, `bmsql_district`.`d_city`, `bmsql_district`.`d_state`, `bmsql_district`.`d_zip` from ? as `bmsql_district` where ((`bmsql_district`.`d_w_id` = 1) and (`bmsql_district`.`d_id` = 1))")
+
 - sql: |
     SELECT c_id     FROM bmsql_customer     WHERE c_w_id = 1 AND c_d_id = 1 AND c_last = 1     ORDER BY c_first
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_customer]", sql="select `bmsql_customer`.`c_id` from ? as `bmsql_customer` where ((`bmsql_customer`.`c_w_id` = 1) and (`bmsql_customer`.`c_d_id` = 1) and (`bmsql_customer`.`c_last` = 1)) order by `bmsql_customer`.`c_first`")
+
 - sql: |
     SELECT c_first, c_middle, c_last, c_street_1, c_street_2,        c_city, c_state, c_zip, c_phone, c_since, c_credit,        c_credit_lim, c_discount, c_balance     FROM bmsql_customer     WHERE c_w_id = 1 AND c_d_id = 1 AND c_id = 1     FOR UPDATE
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_customer]", sql="select `bmsql_customer`.`c_first`, `bmsql_customer`.`c_middle`, `bmsql_customer`.`c_last`, `bmsql_customer`.`c_street_1`, `bmsql_customer`.`c_street_2`, `bmsql_customer`.`c_city`, `bmsql_customer`.`c_state`, `bmsql_customer`.`c_zip`, `bmsql_customer`.`c_phone`, `bmsql_customer`.`c_since`, `bmsql_customer`.`c_credit`, `bmsql_customer`.`c_credit_lim`, `bmsql_customer`.`c_discount`, `bmsql_customer`.`c_balance` from ? as `bmsql_customer` where ((`bmsql_customer`.`c_w_id` = 1) and (`bmsql_customer`.`c_d_id` = 1) and (`bmsql_customer`.`c_id` = 1)) for update")
+
 - sql: |
     SELECT c_data     FROM bmsql_customer     WHERE c_w_id = 1 AND c_d_id = 1 AND c_id = 1
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_customer]", sql="select `bmsql_customer`.`c_data` from ? as `bmsql_customer` where ((`bmsql_customer`.`c_w_id` = 1) and (`bmsql_customer`.`c_d_id` = 1) and (`bmsql_customer`.`c_id` = 1))")
+
 - sql: |
     UPDATE bmsql_warehouse     SET w_ytd = w_ytd + 1     WHERE w_id = 1
   plan: |
-    LogicalModifyView(tables="optest_0001.bmsql_warehouse", sql="UPDATE `bmsql_warehouse` AS `bmsql_warehouse` SET `w_ytd` = (`w_ytd` + 1) WHERE (`w_id` = 1)")
+
+    logicalmodifyview(tables="optest_0001.bmsql_warehouse", sql="update `bmsql_warehouse` as `bmsql_warehouse` force index(`primary`) set `w_ytd` = (`w_ytd` + 1) where (`w_id` = 1)")
+
 - sql: |
     UPDATE bmsql_district     SET d_ytd = d_ytd + 1     WHERE d_w_id = 1 AND d_id = 1
   plan: |
-    LogicalModifyView(tables="optest_0001.bmsql_district", sql="UPDATE `bmsql_district` AS `bmsql_district` SET `d_ytd` = (`d_ytd` + 1) WHERE ((`d_w_id` = 1) AND (`d_id` = 1))")
+
+    logicalmodifyview(tables="optest_0001.bmsql_district", sql="update `bmsql_district` as `bmsql_district` force index(`primary`) set `d_ytd` = (`d_ytd` + 1) where ((`d_w_id` = 1) and (`d_id` = 1))")
+
 - sql: |
     UPDATE bmsql_customer     SET c_balance = c_balance - 1,         c_ytd_payment = c_ytd_payment + 1,         c_payment_cnt = c_payment_cnt + 1     WHERE c_w_id = 1 AND c_d_id = 1 AND c_id = 1
   plan: |
-    logicalmodifyview(tables="optest_0001.bmsql_customer", sql="update `bmsql_customer` as `bmsql_customer` set `c_balance` = (`c_balance` - 1) , `c_ytd_payment` = (`c_ytd_payment` + 1) , `c_payment_cnt` = (`c_payment_cnt` + 1) where ((`c_w_id` = 1) and (`c_d_id` = 1) and (`c_id` = 1))")
+
+    logicalmodifyview(tables="optest_0001.bmsql_customer", sql="update `bmsql_customer` as `bmsql_customer` force index(`primary`) set `c_balance` = (`c_balance` - 1) , `c_ytd_payment` = (`c_ytd_payment` + 1) , `c_payment_cnt` = (`c_payment_cnt` + 1) where ((`c_w_id` = 1) and (`c_d_id` = 1) and (`c_id` = 1))")
+
 - sql: |
     UPDATE bmsql_customer     SET c_balance = c_balance - 1,         c_ytd_payment = c_ytd_payment + 1,         c_payment_cnt = c_payment_cnt + 1,         c_data = 1     WHERE c_w_id = 1 AND c_d_id = 1 AND c_id = 1
   plan: |
-    logicalmodifyview(tables="optest_0001.bmsql_customer", sql="update `bmsql_customer` as `bmsql_customer` set `c_balance` = (`c_balance` - 1) , `c_ytd_payment` = (`c_ytd_payment` + 1) , `c_payment_cnt` = (`c_payment_cnt` + 1) , `c_data` = 1 where ((`c_w_id` = 1) and (`c_d_id` = 1) and (`c_id` = 1))")
-- sql: |
-    SELECT c_id     FROM bmsql_customer     WHERE c_w_id = 1 AND c_d_id = 1 AND c_last = 1     ORDER BY c_first
-  plan: |
-    phytableoperation(tables="optest_0001.[bmsql_customer]", sql="select `bmsql_customer`.`c_id` from ? as `bmsql_customer` where ((`bmsql_customer`.`c_w_id` = 1) and (`bmsql_customer`.`c_d_id` = 1) and (`bmsql_customer`.`c_last` = 1)) order by `bmsql_customer`.`c_first`")
+
+    logicalmodifyview(tables="optest_0001.bmsql_customer", sql="update `bmsql_customer` as `bmsql_customer` force index(`primary`) set `c_balance` = (`c_balance` - 1) , `c_ytd_payment` = (`c_ytd_payment` + 1) , `c_payment_cnt` = (`c_payment_cnt` + 1) , `c_data` = 1 where ((`c_w_id` = 1) and (`c_d_id` = 1) and (`c_id` = 1))")
+
 - sql: |
     SELECT c_first, c_middle, c_last, c_balance     FROM bmsql_customer     WHERE c_w_id = 1 AND c_d_id = 1 AND c_id = 1
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_customer]", sql="select `bmsql_customer`.`c_first`, `bmsql_customer`.`c_middle`, `bmsql_customer`.`c_last`, `bmsql_customer`.`c_balance` from ? as `bmsql_customer` where ((`bmsql_customer`.`c_w_id` = 1) and (`bmsql_customer`.`c_d_id` = 1) and (`bmsql_customer`.`c_id` = 1))")
+
 - sql: |
     SELECT o_id, o_entry_d, o_carrier_id     FROM bmsql_oorder     WHERE o_w_id = 1 AND o_d_id = 1 AND o_c_id = 1       AND o_id = (          SELECT max(o_id)               FROM bmsql_oorder               WHERE o_w_id = 1 AND o_d_id = 1 AND o_c_id = 1          )
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_oorder, bmsql_oorder]", sql="select `bmsql_oorder`.`o_id`, `bmsql_oorder`.`o_entry_d`, `bmsql_oorder`.`o_carrier_id` from ? as `bmsql_oorder` where ((`bmsql_oorder`.`o_w_id` = 1) and (`bmsql_oorder`.`o_d_id` = 1) and (`bmsql_oorder`.`o_c_id` = 1) and (`bmsql_oorder`.`o_id` = (((select max(`bmsql_oorder`.`o_id`) as `max(o_id)` from ? as `bmsql_oorder` where ((`bmsql_oorder`.`o_w_id` = 1) and (`bmsql_oorder`.`o_d_id` = 1) and (`bmsql_oorder`.`o_c_id` = 1)))))))")
+
 - sql: |
     SELECT ol_i_id, ol_supply_w_id, ol_quantity,        ol_amount, ol_delivery_d     FROM bmsql_order_line     WHERE ol_w_id = 1 AND ol_d_id = 1 AND ol_o_id = 1     ORDER BY ol_w_id, ol_d_id, ol_o_id, ol_number
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_order_line]", sql="select `bmsql_order_line`.`ol_i_id`, `bmsql_order_line`.`ol_supply_w_id`, `bmsql_order_line`.`ol_quantity`, `bmsql_order_line`.`ol_amount`, `bmsql_order_line`.`ol_delivery_d` from ? as `bmsql_order_line` where ((`bmsql_order_line`.`ol_w_id` = 1) and (`bmsql_order_line`.`ol_d_id` = 1) and (`bmsql_order_line`.`ol_o_id` = 1)) order by `bmsql_order_line`.`ol_w_id`, `bmsql_order_line`.`ol_d_id`, `bmsql_order_line`.`ol_o_id`, `bmsql_order_line`.`ol_number`")
+
 - sql: |
     SELECT count(*) AS low_stock FROM (    SELECT s_w_id, s_i_id, s_quantity         FROM bmsql_stock         WHERE s_w_id = 1 AND s_quantity < 1 AND s_i_id IN (            SELECT ol_i_id                 FROM bmsql_district                 JOIN bmsql_order_line ON ol_w_id = d_w_id                  AND ol_d_id = d_id                  AND ol_o_id >= d_next_o_id - 20                  AND ol_o_id < d_next_o_id                 WHERE d_w_id = 1 AND d_id = 1         )     ) AS L
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_stock, bmsql_district, bmsql_order_line]", sql="select count(*) as `low_stock` from (select `bmsql_stock`.`s_w_id`, `bmsql_stock`.`s_i_id`, `bmsql_stock`.`s_quantity` from ? as `bmsql_stock` where ((`bmsql_stock`.`s_w_id` = 1) and (`bmsql_stock`.`s_quantity` < 1) and (`bmsql_stock`.`s_i_id` in (select `bmsql_order_line`.`ol_i_id` from ? as `bmsql_district` inner join ? as `bmsql_order_line` on ((`bmsql_order_line`.`ol_w_id` = `bmsql_district`.`d_w_id`) and (`bmsql_order_line`.`ol_d_id` = `bmsql_district`.`d_id`) and (`bmsql_order_line`.`ol_o_id` >= (`bmsql_district`.`d_next_o_id` - 20)) and (`bmsql_order_line`.`ol_o_id` < `bmsql_district`.`d_next_o_id`)) where ((`bmsql_district`.`d_w_id` = 1) and (`bmsql_district`.`d_id` = 1)))))) as `l`")
+
 - sql: |
     SELECT no_o_id     FROM bmsql_new_order     WHERE no_w_id = 1 AND no_d_id = 1     ORDER BY no_o_id ASC
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_new_order]", sql="select `bmsql_new_order`.`no_o_id` from ? as `bmsql_new_order` where ((`bmsql_new_order`.`no_w_id` = 1) and (`bmsql_new_order`.`no_d_id` = 1)) order by `no_o_id`")
+
 - sql: |
     DELETE FROM bmsql_new_order     WHERE no_w_id = 1 AND no_d_id = 1 AND no_o_id = 1
   plan: |
+
     logicalmodifyview(tables="optest_0001.bmsql_new_order", sql="delete from `bmsql_new_order` where ((`no_w_id` = 1) and (`no_d_id` = 1) and (`no_o_id` = 1))")
+
 - sql: |
     SELECT o_c_id     FROM bmsql_oorder     WHERE o_w_id = 1 AND o_d_id = 1 AND o_id = 1
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_oorder]", sql="select `bmsql_oorder`.`o_c_id` from ? as `bmsql_oorder` where ((`bmsql_oorder`.`o_w_id` = 1) and (`bmsql_oorder`.`o_d_id` = 1) and (`bmsql_oorder`.`o_id` = 1))")
+
 - sql: |
     UPDATE bmsql_oorder     SET o_carrier_id = 1     WHERE o_w_id = 1 AND o_d_id = 1 AND o_id = 1
   plan: |
-    logicalmodifyview(tables="optest_0001.bmsql_oorder", sql="update `bmsql_oorder` as `bmsql_oorder` set `o_carrier_id` = 1 where ((`o_w_id` = 1) and (`o_d_id` = 1) and (`o_id` = 1))")
+
+    logicalmodifyview(tables="optest_0001.bmsql_oorder", sql="update `bmsql_oorder` as `bmsql_oorder` force index(`primary`) set `o_carrier_id` = 1 where ((`o_w_id` = 1) and (`o_d_id` = 1) and (`o_id` = 1))")
+
 - sql: |
     SELECT sum(ol_amount) AS sum_ol_amount     FROM bmsql_order_line     WHERE ol_w_id = 1 AND ol_d_id = 1 AND ol_o_id = 1
   plan: |
+
     phytableoperation(tables="optest_0001.[bmsql_order_line]", sql="select sum(`bmsql_order_line`.`ol_amount`) as `sum_ol_amount` from ? as `bmsql_order_line` where ((`bmsql_order_line`.`ol_w_id` = 1) and (`bmsql_order_line`.`ol_d_id` = 1) and (`bmsql_order_line`.`ol_o_id` = 1))")
+
 - sql: |
     UPDATE bmsql_order_line     SET ol_delivery_d = 1     WHERE ol_w_id = 1 AND ol_d_id = 1 AND ol_o_id = 1
   plan: |
-    logicalmodifyview(tables="optest_0001.bmsql_order_line", sql="update `bmsql_order_line` as `bmsql_order_line` set `ol_delivery_d` = 1 where ((`ol_w_id` = 1) and (`ol_d_id` = 1) and (`ol_o_id` = 1))")
+
+    logicalmodifyview(tables="optest_0001.bmsql_order_line", sql="update `bmsql_order_line` as `bmsql_order_line` force index(`primary`) set `ol_delivery_d` = 1 where ((`ol_w_id` = 1) and (`ol_d_id` = 1) and (`ol_o_id` = 1))")
+
 - sql: |
     UPDATE bmsql_customer     SET c_balance = c_balance + 1,         c_delivery_cnt = c_delivery_cnt + 1     WHERE c_w_id = 1 AND c_d_id = 1 AND c_id = 1
   plan: |
-    logicalmodifyview(tables="optest_0001.bmsql_customer", sql="update `bmsql_customer` as `bmsql_customer` set `c_balance` = (`c_balance` + 1) , `c_delivery_cnt` = (`c_delivery_cnt` + 1) where ((`c_w_id` = 1) and (`c_d_id` = 1) and (`c_id` = 1))")
\ No newline at end of file
+
+    logicalmodifyview(tables="optest_0001.bmsql_customer", sql="update `bmsql_customer` as `bmsql_customer` force index(`primary`) set `c_balance` = (`c_balance` + 1) , `c_delivery_cnt` = (`c_delivery_cnt` + 1) where ((`c_w_id` = 1) and (`c_d_id` = 1) and (`c_id` = 1))")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpch/MppTpchPlan100gPartitionTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpch/MppTpchPlan100gPartitionTest.yml
index 224b7378a..7159588c7 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpch/MppTpchPlan100gPartitionTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpch/MppTpchPlan100gPartitionTest.yml
@@ -1,33 +1,3 @@
-#-
-#  sql: |
-#    select
-#      l_returnflag,
-#      l_linestatus,
-#      sum(l_quantity) as sum_qty,
-#      sum(l_extendedprice) as sum_base_price,
-#      sum(l_extendedprice*(1-l_discount)) as sum_disc_price,
-#      sum(l_extendedprice*(1-l_discount)*(1+l_tax)) as sum_charge,
-#      avg(l_quantity) as avg_qty,
-#      avg(l_extendedprice) as avg_price,
-#      avg(l_discount) as avg_disc,
-#      count(*) as count_order
-#    from
-#      lineitem
-#    where
-#      l_shipdate <= date_add(cast('1998-12-01' as date ), Interval -90 day )
-#    group by
-#      l_returnflag,
-#      l_linestatus
-#    order by
-#      l_returnflag,
-#      l_linestatus;
-#
-#  plan: |
-#    MemSort(sort="l_returnflag ASC,l_linestatus ASC")
-#      Project(l_returnflag="l_returnflag", l_linestatus="l_linestatus", sum_qty="sum_qty", sum_base_price="sum_base_price", sum_disc_price="sum_disc_price", sum_charge="sum_charge", avg_qty="sum_pushed_sum / sum_pushed_count", avg_price="sum_pushed_sum_0 / sum_pushed_count_0", avg_disc="sum_pushed_sum_1 / sum_pushed_count_1", count_order="count_order")
-#        HashAgg(group="l_returnflag,l_linestatus", sum_qty="SUM(sum_qty)", sum_base_price="SUM(sum_base_price)", sum_disc_price="SUM(sum_disc_price)", sum_charge="SUM(sum_charge)", sum_pushed_sum="SUM(pushed_sum)", sum_pushed_sum_0="SUM(pushed_sum_0)", sum_pushed_sum_1="SUM(pushed_sum_1)", count_order="SUM(count_order)", sum_pushed_count="SUM(pushed_count)", sum_pushed_count_0="SUM(pushed_count_0)", sum_pushed_count_1="SUM(pushed_count_1)")
-#          Gather(concurrent=true)
-#            LogicalView(tables="[0000-0003].lineitem_[00-15]", shardCount=16, sql="SELECT `l_returnflag`, `l_linestatus`, SUM(`l_quantity`) AS `sum_qty`, SUM(`l_extendedprice`) AS `sum_base_price`, SUM((`l_extendedprice` * (1 - `l_discount`))) AS `sum_disc_price`, SUM(((`l_extendedprice` * (1 - `l_discount`)) * (1 + `l_tax`))) AS `sum_charge`, SUM(`l_quantity`) AS `pushed_sum`, SUM(`l_extendedprice`) AS `pushed_sum_0`, SUM(`l_discount`) AS `pushed_sum_1`, COUNT(*) AS `count_order`, COUNT(`l_quantity`) AS `pushed_count`, COUNT(`l_extendedprice`) AS `pushed_count_0`, COUNT(`l_discount`) AS `pushed_count_1` FROM `lineitem` AS `lineitem` WHERE (`l_shipdate` <= DATE_ADD(CAST('1998-12-01' AS DATE), INTERVAL -90 DAY)) GROUP BY `l_returnflag`, `l_linestatus`")
 
 - sql: |
     select
@@ -75,6 +45,7 @@
       p_partkey;
 
   plan: |
+
     exchange(distribution=single, collation=[0 desc-nulls-last, 2 asc-nulls-first, 1 asc-nulls-first, 3 asc-nulls-first])
       memsort(sort="s_acctbal desc,n_name asc,s_name asc,p_partkey asc")
         project(s_acctbal="s_acctbal", s_name="s_name", n_name="n_name", p_partkey="p_partkey", p_mfgr="p_mfgr", s_address="s_address", s_phone="s_phone", s_comment="s_comment")
@@ -120,6 +91,7 @@
       o_orderdate;
 
   plan: |
+
     project(l_orderkey="l_orderkey", revenue="revenue", o_orderdate="o_orderdate", o_shippriority="o_shippriority")
       exchange(distribution=single, collation=[3 desc-nulls-last, 1 asc-nulls-first])
         memsort(sort="revenue desc,o_orderdate asc")
@@ -145,12 +117,12 @@
     ) group by o_orderpriority order by o_orderpriority;
 
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first])
       memsort(sort="o_orderpriority asc")
         hashagg(group="o_orderpriority", order_count="sum(order_count)")
           exchange(distribution=hash[0], collation=[])
-            partialhashagg(group="o_orderpriority", order_count="count()")
-              logicalview(tables="orders[p1,p2,p3,p4],lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `o_orderpriority` from `orders` as `orders` where ((`o_orderdate` < date_add('1993-07-01', interval 3 month)) and (`o_orderdate` >= '1993-07-01') and (exists (select `l_orderkey` from `lineitem` as `lineitem` where ((`l_orderkey` = `orders`.`o_orderkey`) and (`l_commitdate` < `l_receiptdate`)))))")
+            logicalview(tables="orders[p1,p2,p3,p4],lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `o_orderpriority`, count(*) as `order_count` from `orders` as `orders` where ((`o_orderdate` < date_add('1993-07-01', interval 3 month)) and (`o_orderdate` >= '1993-07-01') and (exists (select `l_orderkey` from `lineitem` as `lineitem` where ((`l_orderkey` = `orders`.`o_orderkey`) and (`l_commitdate` < `l_receiptdate`))))) group by `o_orderpriority`")
 
 - sql: |
     select
@@ -166,6 +138,7 @@
     revenue desc;
 
   plan: |
+
     exchange(distribution=single, collation=[1 desc-nulls-last])
       memsort(sort="revenue desc")
         hashagg(group="n_name", revenue="sum(revenue)")
@@ -193,6 +166,7 @@
     and l_discount between 0.06 - 0.01 and 0.06 + 0.01 and l_quantity < 24;
 
   plan: |
+
     hashagg(revenue="sum(revenue)")
       exchange(distribution=single, collation=[])
         logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select sum((`l_extendedprice` * `l_discount`)) as `revenue` from `lineitem` as `lineitem` where ((`l_discount` between (0.06 - 0.01) and (0.06 + 0.01)) and (`l_shipdate` < date_add(cast('1994-01-01' as date), interval 1 year)) and (`l_quantity` < 24) and (`l_shipdate` >= '1994-01-01'))")
@@ -241,23 +215,24 @@
       l_year;
 
   plan: |
-    Exchange(distribution=single, collation=[0 ASC-nulls-first, 1 ASC-nulls-first, 2 ASC-nulls-first])
-      MemSort(sort="n_name ASC,n_name0 ASC,EXTRACT ASC")
-        HashAgg(group="n_name,n_name0,EXTRACT", revenue="SUM(revenue)")
-          Exchange(distribution=hash[0, 1, 2], collation=[])
-            PartialHashAgg(group="n_name,n_name0,EXTRACT", revenue="SUM(__*__)")
-              Project(s_suppkey="s_suppkey", n_name="n_name", n_nationkey0="n_nationkey0", n_name0="n_name0", c_custkey="c_custkey", c_nationkey="c_nationkey", l_suppkey="l_suppkey", o_custkey="o_custkey", EXTRACT="EXTRACT", __*__="__*__")
-                HashJoin(condition="o_custkey = c_custkey AND n_nationkey0 = c_nationkey", type="inner")
-                  Exchange(distribution=hash[0, 1], collation=[])
-                    LogicalView(tables="customer[p1,p2,p3,p4]", shardCount=4, sql="SELECT `c_custkey`, `c_nationkey` FROM `customer` AS `customer`")
-                  Exchange(distribution=hash[5, 2], collation=[])
-                    Project(s_suppkey="s_suppkey", n_name="n_name", n_nationkey0="n_nationkey0", n_name0="n_name0", l_suppkey="l_suppkey", o_custkey="o_custkey", EXTRACT="EXTRACT", __*__="__*__")
-                      HashJoin(condition="l_suppkey = s_suppkey", type="inner")
-                        Filter(condition="BLOOMFILTER(l_suppkey)")
-                          LogicalView(tables="lineitem[p1,p2,p3,p4],orders[p1,p2,p3,p4]", shardCount=4, sql="SELECT `lineitem`.`l_suppkey`, `orders`.`o_custkey`, EXTRACT(YEAR FROM `lineitem`.`l_shipdate`) AS `EXTRACT`, (`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`)) AS `__*__` FROM `lineitem` AS `lineitem` INNER JOIN `orders` AS `orders` ON ((`lineitem`.`l_orderkey` = `orders`.`o_orderkey`) AND (`lineitem`.`l_shipdate` BETWEEN '1995-01-01' AND '1996-12-31'))")
-                        Exchange(distribution=broadcast, collation=[])
-                          RuntimeFilterBuilder(condition="RUNTIME_FILTER_BUILDER_[0](s_suppkey)")
-                            LogicalView(tables="supplier[p1,p2,p3,p4],nation,nation", shardCount=4, sql="SELECT `supplier`.`s_suppkey`, `nation`.`n_name`, `nation0`.`n_nationkey` AS `n_nationkey0`, `nation0`.`n_name` AS `n_name0` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON (`supplier`.`s_nationkey` = `nation`.`n_nationkey`) INNER JOIN `nation` AS `nation0` ON (((`nation`.`n_name` = 'FRANCE') AND (`nation0`.`n_name` = 'GERMANY')) OR ((`nation`.`n_name` = 'GERMANY') AND (`nation0`.`n_name` = 'FRANCE')))")
+
+    exchange(distribution=single, collation=[0 asc-nulls-first, 1 asc-nulls-first, 2 asc-nulls-first])
+      memsort(sort="n_name asc,n_name0 asc,extract asc")
+        hashagg(group="n_name,n_name0,extract", revenue="sum(revenue)")
+          exchange(distribution=hash[0, 1, 2], collation=[])
+            partialhashagg(group="n_name,n_name0,extract", revenue="sum(__*__)")
+              project(s_suppkey="s_suppkey", n_name="n_name", n_nationkey0="n_nationkey0", n_name0="n_name0", c_custkey="c_custkey", c_nationkey="c_nationkey", l_suppkey="l_suppkey", o_custkey="o_custkey", extract="extract", __*__="__*__")
+                hashjoin(condition="o_custkey = c_custkey and n_nationkey0 = c_nationkey", type="inner")
+                  exchange(distribution=hash[0, 1], collation=[])
+                    logicalview(tables="customer[p1,p2,p3,p4]", shardcount=4, sql="select `c_custkey`, `c_nationkey` from `customer` as `customer`")
+                  exchange(distribution=hash[5, 2], collation=[])
+                    project(s_suppkey="s_suppkey", n_name="n_name", n_nationkey0="n_nationkey0", n_name0="n_name0", l_suppkey="l_suppkey", o_custkey="o_custkey", extract="extract", __*__="__*__")
+                      hashjoin(condition="l_suppkey = s_suppkey", type="inner")
+                        filter(condition="bloomfilter(l_suppkey)")
+                          logicalview(tables="lineitem[p1,p2,p3,p4],orders[p1,p2,p3,p4]", shardcount=4, sql="select `lineitem`.`l_suppkey`, `orders`.`o_custkey`, extract(year from `lineitem`.`l_shipdate`) as `extract`, (`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`)) as `__*__` from `lineitem` as `lineitem` inner join `orders` as `orders` on ((`lineitem`.`l_orderkey` = `orders`.`o_orderkey`) and (`lineitem`.`l_shipdate` between '1995-01-01' and '1996-12-31'))")
+                        exchange(distribution=broadcast, collation=[])
+                          runtimefilterbuilder(condition="runtime_filter_builder_[0](s_suppkey)")
+                            logicalview(tables="supplier[p1,p2,p3,p4],nation,nation", shardcount=4, sql="select `supplier`.`s_suppkey`, `nation`.`n_name`, `nation0`.`n_nationkey` as `n_nationkey0`, `nation0`.`n_name` as `n_name0` from `supplier` as `supplier` inner join `nation` as `nation` on (`supplier`.`s_nationkey` = `nation`.`n_nationkey`) inner join `nation` as `nation0` on (((`nation`.`n_name` = 'france') and (`nation0`.`n_name` = 'germany')) or ((`nation`.`n_name` = 'germany') and (`nation0`.`n_name` = 'france')))")
 
 - sql: |
     select
@@ -286,28 +261,29 @@
     o_year;
 
   plan: |
-    Exchange(distribution=single, collation=[0 ASC-nulls-first])
-      MemSort(sort="o_year ASC")
-        Project(o_year="EXTRACT", mkt_share="$f1 / $f2")
-          HashAgg(group="EXTRACT", $f1="SUM($f1)", $f2="SUM($f2)")
-            Exchange(distribution=hash[0], collation=[])
-              PartialHashAgg(group="EXTRACT", $f1="SUM(CASE)", $f2="SUM(__*__)")
-                Project(o_custkey="o_custkey", EXTRACT="EXTRACT", CASE="CASE($8, $6, CAST(0):DECIMAL(37, 4) NOT NULL)", __*__="__*__", c_custkey="c_custkey")
-                  HashJoin(condition="o_custkey = c_custkey", type="inner")
-                    Exchange(distribution=hash[0], collation=[])
-                      LogicalView(tables="customer[p1,p2,p3,p4],nation,region", shardCount=4, sql="SELECT `customer`.`c_custkey` FROM `customer` AS `customer` INNER JOIN `nation` AS `nation` ON (`customer`.`c_nationkey` = `nation`.`n_nationkey`) INNER JOIN `region` AS `region` ON ((`nation`.`n_regionkey` = `region`.`r_regionkey`) AND (`region`.`r_name` = 'AMERICA'))")
-                    Exchange(distribution=hash[3], collation=[])
-                      HashJoin(condition="s_suppkey = l_suppkey", type="inner")
-                        Exchange(distribution=hash[2], collation=[])
-                          Project(p_partkey="p_partkey", l_partkey="l_partkey", l_suppkey="l_suppkey", o_custkey="o_custkey", EXTRACT="EXTRACT", __*__="__*__")
-                            HashJoin(condition="p_partkey = l_partkey", type="inner")
-                              Filter(condition="BLOOMFILTER(l_partkey)")
-                                LogicalView(tables="lineitem[p1,p2,p3,p4],orders[p1,p2,p3,p4]", shardCount=4, sql="SELECT `lineitem`.`l_partkey`, `lineitem`.`l_suppkey`, `orders`.`o_custkey`, EXTRACT(YEAR FROM `orders`.`o_orderdate`) AS `EXTRACT`, (`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`)) AS `__*__` FROM `lineitem` AS `lineitem` INNER JOIN `orders` AS `orders` ON ((`lineitem`.`l_orderkey` = `orders`.`o_orderkey`) AND (`orders`.`o_orderdate` BETWEEN '1995-01-01' AND '1996-12-31'))")
-                              Exchange(distribution=broadcast, collation=[])
-                                RuntimeFilterBuilder(condition="RUNTIME_FILTER_BUILDER_[0](p_partkey)")
-                                  LogicalView(tables="part[p1,p2,p3,p4]", shardCount=4, sql="SELECT `p_partkey` FROM `part` AS `part` WHERE (`p_type` = 'ECONOMY ANODIZED STEEL')")
-                        Exchange(distribution=hash[0], collation=[])
-                          LogicalView(tables="supplier[p1,p2,p3,p4],nation", shardCount=4, sql="SELECT `supplier`.`s_suppkey`, (`nation`.`n_name` = 'BRAZIL') AS `=` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON (`supplier`.`s_nationkey` = `nation`.`n_nationkey`)")
+
+    exchange(distribution=single, collation=[0 asc-nulls-first])
+      memsort(sort="o_year asc")
+        project(o_year="extract", mkt_share="$f1 / $f2")
+          hashagg(group="extract", $f1="sum($f1)", $f2="sum($f2)")
+            exchange(distribution=hash[0], collation=[])
+              partialhashagg(group="extract", $f1="sum(case)", $f2="sum(__*__)")
+                project(o_custkey="o_custkey", extract="extract", case="case($8, $6, cast(0):decimal(37, 4) not null)", __*__="__*__", c_custkey="c_custkey")
+                  hashjoin(condition="o_custkey = c_custkey", type="inner")
+                    exchange(distribution=hash[0], collation=[])
+                      logicalview(tables="customer[p1,p2,p3,p4],nation,region", shardcount=4, sql="select `customer`.`c_custkey` from `customer` as `customer` inner join `nation` as `nation` on (`customer`.`c_nationkey` = `nation`.`n_nationkey`) inner join `region` as `region` on ((`nation`.`n_regionkey` = `region`.`r_regionkey`) and (`region`.`r_name` = 'america'))")
+                    exchange(distribution=hash[3], collation=[])
+                      hashjoin(condition="s_suppkey = l_suppkey", type="inner")
+                        exchange(distribution=hash[2], collation=[])
+                          project(p_partkey="p_partkey", l_partkey="l_partkey", l_suppkey="l_suppkey", o_custkey="o_custkey", extract="extract", __*__="__*__")
+                            hashjoin(condition="p_partkey = l_partkey", type="inner")
+                              filter(condition="bloomfilter(l_partkey)")
+                                logicalview(tables="lineitem[p1,p2,p3,p4],orders[p1,p2,p3,p4]", shardcount=4, sql="select `lineitem`.`l_partkey`, `lineitem`.`l_suppkey`, `orders`.`o_custkey`, extract(year from `orders`.`o_orderdate`) as `extract`, (`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`)) as `__*__` from `lineitem` as `lineitem` inner join `orders` as `orders` on ((`lineitem`.`l_orderkey` = `orders`.`o_orderkey`) and (`orders`.`o_orderdate` between '1995-01-01' and '1996-12-31'))")
+                              exchange(distribution=broadcast, collation=[])
+                                runtimefilterbuilder(condition="runtime_filter_builder_[0](p_partkey)")
+                                  logicalview(tables="part[p1,p2,p3,p4]", shardcount=4, sql="select `p_partkey` from `part` as `part` where (`p_type` = 'economy anodized steel')")
+                        exchange(distribution=hash[0], collation=[])
+                          logicalview(tables="supplier[p1,p2,p3,p4],nation", shardcount=4, sql="select `supplier`.`s_suppkey`, (`nation`.`n_name` = 'brazil') as `=` from `supplier` as `supplier` inner join `nation` as `nation` on (`supplier`.`s_nationkey` = `nation`.`n_nationkey`)")
 
 - sql: |
     select
@@ -343,6 +319,7 @@
       o_year desc;
 
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first, 1 desc-nulls-last])
       sortagg(group="nation,o_year", sum_profit="sum(amount)")
         memsort(sort="nation asc,o_year desc")
@@ -389,22 +366,23 @@
       value desc;
 
   plan: |
-    Exchange(distribution=single, collation=[1 DESC-nulls-last])
-      MemSort(sort="value DESC")
-        Project(ps_partkey="ps_partkey", value="value")
-          NlJoin(condition="value > $f0 * 0.0001", type="inner")
-            HashAgg(group="ps_partkey", value="SUM(__*__)")
-              Exchange(distribution=hash[1], collation=[])
-                BKAJoin(condition="ps_suppkey = s_suppkey", type="inner")
-                  LogicalView(tables="supplier[p1,p2,p3,p4],nation", shardCount=4, sql="SELECT `supplier`.`s_suppkey` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) AND (`nation`.`n_name` = 'GERMANY'))")
-                  LogicalView(tables="partsupp[p1,p2,p3,p4]", shardCount=4, sql="SELECT `ps_partkey`, `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) AS `__*__` FROM `partsupp` AS `partsupp` WHERE (`ps_suppkey` IN (...))")
-            Exchange(distribution=broadcast, collation=[])
-              HashAgg($f0="SUM($f0)")
-                Exchange(distribution=single, collation=[])
-                  PartialHashAgg($f0="SUM(__*__)")
-                    BKAJoin(condition="ps_suppkey = s_suppkey", type="inner")
-                      LogicalView(tables="supplier[p1,p2,p3,p4],nation", shardCount=4, sql="SELECT `supplier`.`s_suppkey` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) AND (`nation`.`n_name` = 'GERMANY'))")
-                      LogicalView(tables="partsupp[p1,p2,p3,p4]", shardCount=4, sql="SELECT `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) AS `__*__` FROM `partsupp` AS `partsupp` WHERE (`ps_suppkey` IN (...))")
+
+    exchange(distribution=single, collation=[1 desc-nulls-last])
+      memsort(sort="value desc")
+        project(ps_partkey="ps_partkey", value="value")
+          nljoin(condition="value > $f0 * 0.0001", type="inner")
+            hashagg(group="ps_partkey", value="sum(__*__)")
+              exchange(distribution=hash[1], collation=[])
+                bkajoin(condition="ps_suppkey = s_suppkey", type="inner")
+                  logicalview(tables="supplier[p1,p2,p3,p4],nation", shardcount=4, sql="select `supplier`.`s_suppkey` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany'))")
+                  logicalview(tables="partsupp[p1,p2,p3,p4]", shardcount=4, sql="select `ps_partkey`, `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) as `__*__` from `partsupp` as `partsupp` force index(`idx_partsupp_suppkey`) where (`ps_suppkey` in (...))")
+            exchange(distribution=broadcast, collation=[])
+              hashagg($f0="sum($f0)")
+                exchange(distribution=single, collation=[])
+                  partialhashagg($f0="sum(__*__)")
+                    bkajoin(condition="ps_suppkey = s_suppkey", type="inner")
+                      logicalview(tables="supplier[p1,p2,p3,p4],nation", shardcount=4, sql="select `supplier`.`s_suppkey` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany'))")
+                      logicalview(tables="partsupp[p1,p2,p3,p4]", shardcount=4, sql="select `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) as `__*__` from `partsupp` as `partsupp` force index(`idx_partsupp_suppkey`) where (`ps_suppkey` in (...))")
 
 - sql: |
     select
@@ -430,6 +408,7 @@
     group by l_shipmode
     order by l_shipmode;
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first])
       sortagg(group="l_shipmode", high_line_count="sum(high_line_count)", low_line_count="sum(low_line_count)")
         exchange(distribution=hash[0], collation=[0 asc-nulls-first])
@@ -452,15 +431,16 @@
     custdist desc, c_count desc;
 
   plan: |
-    Exchange(distribution=single, collation=[1 DESC-nulls-last, 0 DESC-nulls-last])
-      MemSort(sort="custdist DESC,c_count DESC")
-        HashAgg(group="c_count", custdist="COUNT()")
-          Exchange(distribution=hash[1], collation=[])
-            HashGroupJoin(condition="c_custkey = o_custkey", type="left")
-              Exchange(distribution=hash[0], collation=[])
-                LogicalView(tables="customer[p1,p2,p3,p4]", shardCount=4, sql="SELECT `c_custkey` FROM `customer` AS `customer`")
-              Exchange(distribution=hash[1], collation=[])
-                LogicalView(tables="orders[p1,p2,p3,p4]", shardCount=4, sql="SELECT `o_orderkey`, `o_custkey` FROM `orders` AS `orders` WHERE (`o_comment` NOT LIKE '%special%requests%')")
+
+    exchange(distribution=single, collation=[1 desc-nulls-last, 0 desc-nulls-last])
+      memsort(sort="custdist desc,c_count desc")
+        hashagg(group="c_count", custdist="count()")
+          exchange(distribution=hash[1], collation=[])
+            hashgroupjoin(condition="c_custkey = o_custkey", type="left")
+              exchange(distribution=hash[0], collation=[])
+                logicalview(tables="customer[p1,p2,p3,p4]", shardcount=4, sql="select `c_custkey` from `customer` as `customer`")
+              exchange(distribution=hash[1], collation=[])
+                logicalview(tables="orders[p1,p2,p3,p4]", shardcount=4, sql="select `o_orderkey`, `o_custkey` from `orders` as `orders` where (`o_comment` not like '%special%requests%')")
 
 - sql: |
     select
@@ -478,16 +458,17 @@
       and l_shipdate < date_add(cast('1995-09-01' as date ), Interval 1 year );
 
   plan: |
-    Project(promo_revenue="100.00 * $f0 / $f1")
-      HashAgg($f0="SUM($f0)", $f1="SUM($f1)")
-        Exchange(distribution=single, collation=[])
-          PartialHashAgg($f0="SUM($f0)", $f1="SUM($f1)")
-            Project($f0="CASE($3, $1, CAST(0):DECIMAL(37, 4) NOT NULL)", $f1="__*__")
-              HashJoin(condition="l_partkey = p_partkey", type="inner")
-                Exchange(distribution=hash[0], collation=[])
-                  LogicalView(tables="lineitem[p1,p2,p3,p4]", shardCount=4, sql="SELECT `l_partkey`, (`l_extendedprice` * (1 - `l_discount`)) AS `__*__` FROM `lineitem` AS `lineitem` WHERE ((`l_shipdate` >= '1995-09-01') AND (`l_shipdate` < DATE_ADD(CAST('1995-09-01' AS DATE), INTERVAL 1 YEAR)))")
-                Exchange(distribution=hash[0], collation=[])
-                  LogicalView(tables="part[p1,p2,p3,p4]", shardCount=4, sql="SELECT `p_partkey`, (`p_type` LIKE 'PROMO%') AS `LIKE` FROM `part` AS `part`")
+
+    project(promo_revenue="100.00 * $f0 / $f1")
+      hashagg($f0="sum($f0)", $f1="sum($f1)")
+        exchange(distribution=single, collation=[])
+          partialhashagg($f0="sum($f0)", $f1="sum($f1)")
+            project($f0="case($3, $1, cast(0):decimal(37, 4) not null)", $f1="__*__")
+              hashjoin(condition="l_partkey = p_partkey", type="inner")
+                exchange(distribution=hash[0], collation=[])
+                  logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_partkey`, (`l_extendedprice` * (1 - `l_discount`)) as `__*__` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1995-09-01') and (`l_shipdate` < date_add(cast('1995-09-01' as date), interval 1 year)))")
+                exchange(distribution=hash[0], collation=[])
+                  logicalview(tables="part[p1,p2,p3,p4]", shardcount=4, sql="select `p_partkey`, (`p_type` like 'promo%') as `like` from `part` as `part`")
 
 - sql: |
     select
@@ -527,25 +508,26 @@
     s_suppkey;
 
   plan: |
+
     project(s_suppkey="s_suppkey", s_name="s_name", s_address="s_address", s_phone="s_phone", total_revenue="total_revenue")
       exchange(distribution=single, collation=[0 asc-nulls-first])
         hashjoin(condition="supplier_no = s_suppkey", type="inner")
           exchange(distribution=hash[0], collation=[0 asc-nulls-first])
-            logicalview(tables="supplier[p1,p2,p3,p4]", shardcount=4, sql="select `s_suppkey`, `s_name`, `s_address`, `s_phone` from `supplier` as `supplier` order by `s_suppkey`")
+            logicalview(tables="supplier[p1,p2,p3,p4]", shardcount=4, sql="select `s_suppkey`, `s_name`, `s_address`, `s_phone` from `supplier` as `supplier` force index(`primary`) order by `s_suppkey`")
           project(max(total_revenue)="max(total_revenue)", supplier_no="supplier_no", total_revenue="total_revenue")
             hashjoin(condition="max(total_revenue) = total_revenue", type="inner")
               filter(condition="bloomfilter(total_revenue)")
-                hashagg(group="supplier_no", total_revenue="sum($f1)")
+                hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
                   exchange(distribution=hash[0], collation=[])
-                    logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_suppkey` as `supplier_no`, (`l_extendedprice` * (1 - `l_discount`)) as `$f1` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add('1996-01-01', interval 3 month)))")
+                    logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_suppkey` as `supplier_no`, sum((`l_extendedprice` * (1 - `l_discount`))) as `total_revenue` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add('1996-01-01', interval 3 month))) group by `l_suppkey`")
               exchange(distribution=broadcast, collation=[])
                 runtimefilterbuilder(condition="runtime_filter_builder_[0](max(total_revenue))")
                   hashagg(max(total_revenue)="max(max(total_revenue))")
                     exchange(distribution=single, collation=[])
                       partialhashagg(max(total_revenue)="max(total_revenue)")
-                        hashagg(group="supplier_no", total_revenue="sum($f1)")
+                        hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
                           exchange(distribution=hash[0], collation=[])
-                            logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_suppkey` as `supplier_no`, (`l_extendedprice` * (1 - `l_discount`)) as `$f1` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add(cast('1996-01-01' as date), interval 3 month)))")
+                            logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_suppkey` as `supplier_no`, sum((`l_extendedprice` * (1 - `l_discount`))) as `total_revenue` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add(cast('1996-01-01' as date), interval 3 month))) group by `l_suppkey`")
 
 - sql: |
     select
@@ -583,14 +565,14 @@
     exchange(distribution=single, collation=[3 desc-nulls-last, 0 asc-nulls-first, 1 asc-nulls-first, 2 asc-nulls-first])
       memsort(sort="supplier_cnt desc,p_brand asc,p_type asc,p_size asc")
         hashagg(group="p_brand,p_type,p_size", supplier_cnt="count(ps_suppkey)")
-          exchange(distribution=hash[0, 1, 2], collation=[])
-            hashagg(group="p_brand,p_type,p_size,ps_suppkey")
+          hashagg(group="p_brand,p_type,p_size,ps_suppkey")
+            exchange(distribution=hash[1], collation=[])
               project(p_brand="p_brand", p_type="p_type", p_size="p_size", ps_suppkey="ps_suppkey")
                 semihashjoin(condition="ps_suppkey = s_suppkey", type="anti", build="inner")
-                  exchange(distribution=hash[0], collation=[])
-                    logicalview(tables="partsupp[p1,p2,p3,p4],part[p1,p2,p3,p4]", shardcount=4, sql="select `partsupp`.`ps_suppkey`, `part`.`p_brand`, `part`.`p_type`, `part`.`p_size` from `partsupp` as `partsupp` inner join `part` as `part` on ((`partsupp`.`ps_partkey` = `part`.`p_partkey`) and (`part`.`p_brand` <> 'brand#45') and (`part`.`p_type` not like 'medium polished') and (`part`.`p_size` in(49, 14, 23, 45, 19, 3, 36, 9)))")
-                  exchange(distribution=hash[0], collation=[])
+                  logicalview(tables="partsupp[p1,p2,p3,p4],part[p1,p2,p3,p4]", shardcount=4, sql="select `partsupp`.`ps_suppkey`, `part`.`p_brand`, `part`.`p_type`, `part`.`p_size` from `partsupp` as `partsupp` inner join `part` as `part` on ((`partsupp`.`ps_partkey` = `part`.`p_partkey`) and (`part`.`p_brand` <> 'brand#45') and (`part`.`p_type` not like 'medium polished') and (`part`.`p_size` in(49, 14, 23, 45, 19, 3, 36, 9)))")
+                  exchange(distribution=broadcast, collation=[])
                     logicalview(tables="supplier[p1,p2,p3,p4]", shardcount=4, sql="select `s_suppkey` from `supplier` as `supplier` where (`s_comment` like '%customer%complaints%')")
+
 - sql: |
     select
       sum(l_extendedprice) / 7.0 as avg_yearly
@@ -611,47 +593,17 @@
       );
 
   plan: |
+
     project(avg_yearly="$f0 / 7.0")
       hashagg($f0="sum($f0)")
         exchange(distribution=single, collation=[])
-          PartialHashAgg($f0="sum(l_extendedprice)")
+          partialhashagg($f0="sum(l_extendedprice)")
             filter(condition="l_quantity < 0.2 * f16w0$o0")
               hashwindow(p_partkey="p_partkey", l_partkey="l_partkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice", f4w0$o0="window#0avg($2)", reference windows="window#0=window(partition {1} order by [] range between unbounded preceding and unbounded following aggs [avg($2)])")
                 exchange(distribution=hash[1], collation=[])
                   bkajoin(condition="l_partkey = p_partkey", type="inner")
                     logicalview(tables="part[p1,p2,p3,p4]", shardcount=4, sql="select `p_partkey` from `part` as `part` where ((`p_container` = 'med box') and (`p_brand` = 'brand#23'))")
-                    logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem` where (`l_partkey` in (...))")
-
-#- sql: |
-#    select
-#    c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice, sum(l_quantity)
-#    from
-#    customer,
-#    orders,
-#    lineitem where
-#    o_orderkey in ( select
-#    l_orderkey from
-#    lineitem group by
-#    l_orderkey having
-#    sum(l_quantity) > 300
-#    )
-#    and c_custkey = o_custkey and o_orderkey = l_orderkey
-#    group by c_name,
-#    c_custkey, o_orderkey, o_orderdate, o_totalprice
-#    order by
-#    o_totalprice desc,
-#    o_orderdate;
-#
-#  plan: |
-#    Project(c_name="c_name", c_custkey="c_custkey", o_orderkey="o_orderkey", o_orderdate="o_orderdate", o_totalprice="o_totalprice", sum(l_quantity)="$f8")
-#      Exchange(distribution=single, collation=[3 DESC-nulls-last, 2 ASC-nulls-first])
-#        MemSort(sort="o_totalprice DESC,o_orderdate ASC")
-#          Project(c_custkey="c_custkey", o_orderkey="o_orderkey", o_orderdate="o_orderdate", o_totalprice="o_totalprice", c_name="c_name", $f8="$f2 * sum(l_quantity)")
-#            HashJoin(condition="o_custkey = c_custkey", type="inner")
-#              Exchange(distribution=hash[0], collation=[])
-#                LogicalView(tables="customer[p1,p2,p3,p4]", shardCount=4, sql="SELECT `c_custkey`, (`c_name`) AS `c_name`, COUNT(*) AS `$f2` FROM `customer` AS `customer` GROUP BY `c_custkey`")
-#              Exchange(distribution=hash[1], collation=[])
-#                LogicalView(tables="orders[p1,p2,p3,p4],lineitem[p1,p2,p3,p4],lineitem[p1,p2,p3,p4]", shardCount=4, sql="SELECT `orders`.`o_orderkey`, `orders`.`o_custkey`, (`orders`.`o_orderdate`) AS `o_orderdate`, (`orders`.`o_totalprice`) AS `o_totalprice`, SUM(`lineitem`.`l_quantity`) AS `sum(l_quantity)` FROM `orders` AS `orders` INNER JOIN `lineitem` AS `lineitem` ON (`orders`.`o_orderkey` = `lineitem`.`l_orderkey`) WHERE (`orders`.`o_orderkey` IN (SELECT `l_orderkey` FROM (SELECT `l_orderkey`, SUM(`l_quantity`) AS `$f1` FROM `lineitem` AS `lineitem0` GROUP BY `l_orderkey` HAVING (SUM(`l_quantity`) > 300)) AS `t1`)) GROUP BY `orders`.`o_orderkey`, `orders`.`o_custkey`")
+                    logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem` force index(`i_l_partkey`) where (`l_partkey` in (...))")
 
 - sql: |
     select
@@ -687,6 +639,7 @@
     );
 
   plan: |
+
     hashagg(revenue="sum(revenue)")
       exchange(distribution=single, collation=[])
         partialhashagg(revenue="sum(__*__)")
@@ -736,6 +689,7 @@
       s_name;
 
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first])
       memsort(sort="s_name asc")
         project(s_name="s_name", s_address="s_address")
@@ -744,10 +698,10 @@
             exchange(distribution=broadcast, collation=[])
               project(ps_suppkey="ps_suppkey")
                 hashjoin(condition="l_partkey = ps_partkey and l_suppkey = ps_suppkey and ps_availqty > 0.5 * $f2", type="inner")
-                  hashagg(group="l_partkey,l_suppkey", $f2="sum(l_quantity)")
-                    exchange(distribution=hash[1, 2], collation=[])
+                  hashagg(group="l_partkey,l_suppkey", $f2="sum($f2)")
+                    exchange(distribution=hash[0, 1], collation=[])
                       filter(condition="bloomfilter(l_partkey) and bloomfilter(l_suppkey)")
-                        logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_quantity`, `l_partkey`, `l_suppkey` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(cast('1994-01-01' as date), interval 1 year)) and (`l_shipdate` >= '1994-01-01'))")
+                        logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_partkey`, `l_suppkey`, sum(`l_quantity`) as `$f2` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(cast('1994-01-01' as date), interval 1 year)) and (`l_shipdate` >= '1994-01-01')) group by `l_partkey`, `l_suppkey`")
                   exchange(distribution=hash[0, 1], collation=[])
                     runtimefilterbuilder(condition="runtime_filter_builder_[0](ps_partkey) and runtime_filter_builder_[1](ps_suppkey)")
                       logicalview(tables="partsupp[p1,p2,p3,p4],part[p1,p2,p3,p4]", shardcount=4, sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp` as `partsupp` where (`ps_partkey` in (select `p_partkey` from `part` as `part` where ((`p_name` like 'forest%') and (`partsupp`.`ps_partkey` = `p_partkey`))))")
@@ -794,6 +748,7 @@
       s_name;
 
   plan: |
+
     exchange(distribution=single, collation=[1 desc-nulls-last, 0 asc-nulls-first])
       memsort(sort="numwait desc,s_name asc")
         hashagg(group="s_name", numwait="count()")
@@ -806,12 +761,14 @@
                   exchange(distribution=broadcast, collation=[])
                     runtimefilterbuilder(condition="runtime_filter_builder_[0](s_suppkey)")
                       logicalview(tables="supplier[p1,p2,p3,p4],nation", shardcount=4, sql="select `supplier`.`s_suppkey`, `supplier`.`s_name` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'saudi arabia'))")
-              logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem` where (`l_orderkey` in (...))")
+              logicalview(tables="lineitem[p1,p2,p3,p4]", shardcount=4, sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem` force index(`primary`) where (`l_orderkey` in (...))")
+
 - sql: |
     /*+TDDL:ENABLE_RUNTIME_FILTER=false */
     select x.tt from customer join (select sum(o_custkey)+1 as tt from orders group by o_orderkey) x on c_nationkey > x.tt;
 
   plan: |
+
     project(tt="$f1 + 1")
       nljoin(condition="c_nationkey > $f1 + 1", type="inner")
         exchange(distribution=single, collation=[])
@@ -824,6 +781,7 @@
     select x.tt from customer join (select sum(o_custkey)+1 as tt from orders group by o_orderkey) x on c_nationkey = x.tt;
 
   plan: |
+
     project(tt="tt")
       hashjoin(condition="tt = c_nationkey", type="inner")
         exchange(distribution=hash[0], collation=[])
@@ -832,54 +790,3 @@
           exchange(distribution=hash[1], collation=[])
             project(c_nationkey="c_nationkey", c_nationkey_shuffle__="cast(c_nationkey)")
               logicalview(tables="customer[p1,p2,p3,p4]", shardcount=4, sql="select `c_nationkey` from `customer` as `customer`")
-#-
-#  sql: |
-#    select
-#      cntrycode,
-#      count(*) as numcust,
-#      sum(c_acctbal) as totacctbal
-#    from
-#      (
-#      select
-#        substring(c_phone ,1, 2) as cntrycode,
-#        c_acctbal
-#      from
-#        customer
-#      where
-#        substring(c_phone ,1, 2) in ('13','31','23','29','30','18','17')
-#        and c_acctbal > (
-#          select
-#            avg(c_acctbal)
-#          from
-#            customer
-#          where
-#            c_acctbal > 0.00
-#            and substring (c_phone , 1, 2) in ('13','31','23','29','30','18','17')
-#        )
-#        and not exists (
-#          select
-#            *
-#          from
-#            orders
-#          where
-#            o_custkey = c_custkey
-#        )
-#      ) as custsale
-#    group by
-#      cntrycode
-#    order by
-#      cntrycode;
-#
-#  plan: |
-#    MemSort(sort="cntrycode ASC")
-#      HashAgg(group="cntrycode", numcust="COUNT()", totacctbal="SUM(c_acctbal)")
-#        Project(cntrycode="SUBSTRING(c_phone, 1, 2)", c_acctbal="c_acctbal")
-#          NlJoin(condition="c_acctbal > sum_pushed_sum / sum_pushed_count", type="inner")
-#            SemiHashJoin(condition="c_custkey = o_custkey", type="anti")
-#              Gather(concurrent=true)
-#                LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey`, `c_phone`, `c_acctbal` FROM `customer` AS `customer` WHERE ((SUBSTRING(`c_phone`, 1, 2)) IN('13', '31', '23', '29', '30', '18', '17'))")
-#              Gather(concurrent=true)
-#                LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_custkey` FROM `orders` AS `orders`")
-#            HashAgg(sum_pushed_sum="SUM(pushed_sum)", sum_pushed_count="SUM(pushed_count)")
-#              Gather(concurrent=true)
-#                LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT SUM(`c_acctbal`) AS `pushed_sum`, COUNT(`c_acctbal`) AS `pushed_count` FROM `customer` AS `customer` WHERE ((`c_acctbal` > 0.00) AND ((SUBSTRING(`c_phone`, 1, 2)) IN('13', '31', '23', '29', '30', '18', '17')))")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpch/MppTpchPlan100gTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpch/MppTpchPlan100gTest.yml
index dda4ca40e..e051ebc12 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpch/MppTpchPlan100gTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/tpch/MppTpchPlan100gTest.yml
@@ -1,33 +1,3 @@
-#-
-#  sql: |
-#    select
-#      l_returnflag,
-#      l_linestatus,
-#      sum(l_quantity) as sum_qty,
-#      sum(l_extendedprice) as sum_base_price,
-#      sum(l_extendedprice*(1-l_discount)) as sum_disc_price,
-#      sum(l_extendedprice*(1-l_discount)*(1+l_tax)) as sum_charge,
-#      avg(l_quantity) as avg_qty,
-#      avg(l_extendedprice) as avg_price,
-#      avg(l_discount) as avg_disc,
-#      count(*) as count_order
-#    from
-#      lineitem
-#    where
-#      l_shipdate <= date_add(cast('1998-12-01' as date ), Interval -90 day )
-#    group by
-#      l_returnflag,
-#      l_linestatus
-#    order by
-#      l_returnflag,
-#      l_linestatus;
-#
-#  plan: |
-#    MemSort(sort="l_returnflag ASC,l_linestatus ASC")
-#      Project(l_returnflag="l_returnflag", l_linestatus="l_linestatus", sum_qty="sum_qty", sum_base_price="sum_base_price", sum_disc_price="sum_disc_price", sum_charge="sum_charge", avg_qty="sum_pushed_sum / sum_pushed_count", avg_price="sum_pushed_sum_0 / sum_pushed_count_0", avg_disc="sum_pushed_sum_1 / sum_pushed_count_1", count_order="count_order")
-#        HashAgg(group="l_returnflag,l_linestatus", sum_qty="SUM(sum_qty)", sum_base_price="SUM(sum_base_price)", sum_disc_price="SUM(sum_disc_price)", sum_charge="SUM(sum_charge)", sum_pushed_sum="SUM(pushed_sum)", sum_pushed_sum_0="SUM(pushed_sum_0)", sum_pushed_sum_1="SUM(pushed_sum_1)", count_order="SUM(count_order)", sum_pushed_count="SUM(pushed_count)", sum_pushed_count_0="SUM(pushed_count_0)", sum_pushed_count_1="SUM(pushed_count_1)")
-#          Gather(concurrent=true)
-#            LogicalView(tables="[0000-0003].lineitem_[00-15]", shardCount=16, sql="SELECT `l_returnflag`, `l_linestatus`, SUM(`l_quantity`) AS `sum_qty`, SUM(`l_extendedprice`) AS `sum_base_price`, SUM((`l_extendedprice` * (1 - `l_discount`))) AS `sum_disc_price`, SUM(((`l_extendedprice` * (1 - `l_discount`)) * (1 + `l_tax`))) AS `sum_charge`, SUM(`l_quantity`) AS `pushed_sum`, SUM(`l_extendedprice`) AS `pushed_sum_0`, SUM(`l_discount`) AS `pushed_sum_1`, COUNT(*) AS `count_order`, COUNT(`l_quantity`) AS `pushed_count`, COUNT(`l_extendedprice`) AS `pushed_count_0`, COUNT(`l_discount`) AS `pushed_count_1` FROM `lineitem` AS `lineitem` WHERE (`l_shipdate` <= DATE_ADD(CAST('1998-12-01' AS DATE), INTERVAL -90 DAY)) GROUP BY `l_returnflag`, `l_linestatus`")
 
 - sql: |
     /*+TDDL:ENABLE_RUNTIME_FILTER=true */
@@ -76,6 +46,7 @@
       p_partkey limit 100;
 
   plan: |
+
     topn(sort="s_acctbal desc,n_name asc,s_name asc,p_partkey asc", offset=0, fetch=100)
       exchange(distribution=single, collation=[0 desc-nulls-last, 2 asc-nulls-first, 1 asc-nulls-first, 3 asc-nulls-first])
         topn(sort="s_acctbal desc,n_name asc,s_name asc,p_partkey asc", fetch=100)
@@ -122,6 +93,7 @@
       o_orderdate;
 
   plan: |
+
     project(l_orderkey="l_orderkey", revenue="revenue", o_orderdate="o_orderdate", o_shippriority="o_shippriority")
       exchange(distribution=single, collation=[3 desc-nulls-last, 1 asc-nulls-first])
         memsort(sort="revenue desc,o_orderdate asc")
@@ -147,12 +119,12 @@
     ) group by o_orderpriority order by o_orderpriority;
 
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first])
       memsort(sort="o_orderpriority asc")
         hashagg(group="o_orderpriority", order_count="sum(order_count)")
           exchange(distribution=hash[0], collation=[])
-            partialhashagg(group="o_orderpriority", order_count="count()")
-              logicalview(tables="[0000-0003].orders_[00-15],lineitem_[00-15]", shardcount=16, sql="select `o_orderpriority` from `orders` as `orders` where ((`o_orderdate` < date_add('1993-07-01', interval 3 month)) and (`o_orderdate` >= '1993-07-01') and (exists (select `l_orderkey` from `lineitem` as `lineitem` where ((`l_orderkey` = `orders`.`o_orderkey`) and (`l_commitdate` < `l_receiptdate`)))))")
+            logicalview(tables="[0000-0003].orders_[00-15],lineitem_[00-15]", shardcount=16, sql="select `o_orderpriority`, count(*) as `order_count` from `orders` as `orders` where ((`o_orderdate` < date_add('1993-07-01', interval 3 month)) and (`o_orderdate` >= '1993-07-01') and (exists (select `l_orderkey` from `lineitem` as `lineitem` where ((`l_orderkey` = `orders`.`o_orderkey`) and (`l_commitdate` < `l_receiptdate`))))) group by `o_orderpriority`")
 
 - sql: |
     select
@@ -168,6 +140,7 @@
     revenue desc;
 
   plan: |
+
     exchange(distribution=single, collation=[1 desc-nulls-last])
       memsort(sort="revenue desc")
         hashagg(group="n_name", revenue="sum(revenue)")
@@ -195,6 +168,7 @@
     and l_discount between 0.06 - 0.01 and 0.06 + 0.01 and l_quantity < 24;
 
   plan: |
+
     hashagg(revenue="sum(revenue)")
       exchange(distribution=single, collation=[])
         logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select sum((`l_extendedprice` * `l_discount`)) as `revenue` from `lineitem` as `lineitem` where ((`l_discount` between (0.06 - 0.01) and (0.06 + 0.01)) and (`l_shipdate` < date_add(cast('1994-01-01' as date), interval 1 year)) and (`l_quantity` < 24) and (`l_shipdate` >= '1994-01-01'))")
@@ -244,6 +218,7 @@
       l_year;
 
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first, 1 asc-nulls-first, 2 asc-nulls-first])
       memsort(sort="n_name asc,n_name0 asc,extract asc")
         hashagg(group="n_name,n_name0,extract", revenue="sum(revenue)")
@@ -261,6 +236,7 @@
                         exchange(distribution=broadcast, collation=[])
                           runtimefilterbuilder(condition="runtime_filter_builder_[0](s_suppkey)")
                             logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey`, `nation`.`n_name`, `nation0`.`n_nationkey` as `n_nationkey0`, `nation0`.`n_name` as `n_name0` from `supplier` as `supplier` inner join `nation` as `nation` on (`supplier`.`s_nationkey` = `nation`.`n_nationkey`) inner join `nation` as `nation0` on (((`nation`.`n_name` = 'france') and (`nation0`.`n_name` = 'germany')) or ((`nation`.`n_name` = 'germany') and (`nation0`.`n_name` = 'france')))")
+
 - sql: |
     /*+TDDL:ENABLE_RUNTIME_FILTER=true */
     select
@@ -289,28 +265,29 @@
     o_year;
 
   plan: |
-    Exchange(distribution=single, collation=[0 ASC-nulls-first])
-      MemSort(sort="o_year ASC")
-        Project(o_year="EXTRACT", mkt_share="$f1 / $f2")
-          HashAgg(group="EXTRACT", $f1="SUM($f1)", $f2="SUM($f2)")
-            Exchange(distribution=hash[0], collation=[])
-              PartialHashAgg(group="EXTRACT", $f1="SUM(CASE)", $f2="SUM(__*__)")
-                Project(o_custkey="o_custkey", EXTRACT="EXTRACT", CASE="CASE($8, $6, CAST(0):DECIMAL(37, 4) NOT NULL)", __*__="__*__", c_custkey="c_custkey")
-                  HashJoin(condition="o_custkey = c_custkey", type="inner")
-                    Exchange(distribution=hash[0], collation=[])
-                      LogicalView(tables="[0000-0003].customer_[00-15],nation,region", shardCount=16, sql="SELECT `customer`.`c_custkey` FROM `customer` AS `customer` INNER JOIN `nation` AS `nation` ON (`customer`.`c_nationkey` = `nation`.`n_nationkey`) INNER JOIN `region` AS `region` ON ((`nation`.`n_regionkey` = `region`.`r_regionkey`) AND (`region`.`r_name` = 'AMERICA'))")
-                    Exchange(distribution=hash[3], collation=[])
-                      HashJoin(condition="s_suppkey = l_suppkey", type="inner")
-                        Exchange(distribution=hash[2], collation=[])
-                          Project(p_partkey="p_partkey", l_partkey="l_partkey", l_suppkey="l_suppkey", o_custkey="o_custkey", EXTRACT="EXTRACT", __*__="__*__")
-                            HashJoin(condition="p_partkey = l_partkey", type="inner")
-                              Filter(condition="BLOOMFILTER(l_partkey)")
-                                LogicalView(tables="[0000-0003].lineitem_[00-15],orders_[00-15]", shardCount=16, sql="SELECT `lineitem`.`l_partkey`, `lineitem`.`l_suppkey`, `orders`.`o_custkey`, EXTRACT(YEAR FROM `orders`.`o_orderdate`) AS `EXTRACT`, (`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`)) AS `__*__` FROM `lineitem` AS `lineitem` INNER JOIN `orders` AS `orders` ON ((`lineitem`.`l_orderkey` = `orders`.`o_orderkey`) AND (`orders`.`o_orderdate` BETWEEN '1995-01-01' AND '1996-12-31'))")
-                              Exchange(distribution=broadcast, collation=[])
-                                RuntimeFilterBuilder(condition="RUNTIME_FILTER_BUILDER_[0](p_partkey)")
-                                  LogicalView(tables="[0000-0003].part_[00-15]", shardCount=16, sql="SELECT `p_partkey` FROM `part` AS `part` WHERE (`p_type` = 'ECONOMY ANODIZED STEEL')")
-                        Exchange(distribution=hash[0], collation=[])
-                          LogicalView(tables="[0000-0003].supplier_[00-15],nation", shardCount=16, sql="SELECT `supplier`.`s_suppkey`, (`nation`.`n_name` = 'BRAZIL') AS `=` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON (`supplier`.`s_nationkey` = `nation`.`n_nationkey`)")
+
+    exchange(distribution=single, collation=[0 asc-nulls-first])
+      memsort(sort="o_year asc")
+        project(o_year="extract", mkt_share="$f1 / $f2")
+          hashagg(group="extract", $f1="sum($f1)", $f2="sum($f2)")
+            exchange(distribution=hash[0], collation=[])
+              partialhashagg(group="extract", $f1="sum(case)", $f2="sum(__*__)")
+                project(o_custkey="o_custkey", extract="extract", case="case($8, $6, cast(0):decimal(37, 4) not null)", __*__="__*__", c_custkey="c_custkey")
+                  hashjoin(condition="o_custkey = c_custkey", type="inner")
+                    exchange(distribution=hash[0], collation=[])
+                      logicalview(tables="[0000-0003].customer_[00-15],nation,region", shardcount=16, sql="select `customer`.`c_custkey` from `customer` as `customer` inner join `nation` as `nation` on (`customer`.`c_nationkey` = `nation`.`n_nationkey`) inner join `region` as `region` on ((`nation`.`n_regionkey` = `region`.`r_regionkey`) and (`region`.`r_name` = 'america'))")
+                    exchange(distribution=hash[3], collation=[])
+                      hashjoin(condition="s_suppkey = l_suppkey", type="inner")
+                        exchange(distribution=hash[2], collation=[])
+                          project(p_partkey="p_partkey", l_partkey="l_partkey", l_suppkey="l_suppkey", o_custkey="o_custkey", extract="extract", __*__="__*__")
+                            hashjoin(condition="p_partkey = l_partkey", type="inner")
+                              filter(condition="bloomfilter(l_partkey)")
+                                logicalview(tables="[0000-0003].lineitem_[00-15],orders_[00-15]", shardcount=16, sql="select `lineitem`.`l_partkey`, `lineitem`.`l_suppkey`, `orders`.`o_custkey`, extract(year from `orders`.`o_orderdate`) as `extract`, (`lineitem`.`l_extendedprice` * (1 - `lineitem`.`l_discount`)) as `__*__` from `lineitem` as `lineitem` inner join `orders` as `orders` on ((`lineitem`.`l_orderkey` = `orders`.`o_orderkey`) and (`orders`.`o_orderdate` between '1995-01-01' and '1996-12-31'))")
+                              exchange(distribution=broadcast, collation=[])
+                                runtimefilterbuilder(condition="runtime_filter_builder_[0](p_partkey)")
+                                  logicalview(tables="[0000-0003].part_[00-15]", shardcount=16, sql="select `p_partkey` from `part` as `part` where (`p_type` = 'economy anodized steel')")
+                        exchange(distribution=hash[0], collation=[])
+                          logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey`, (`nation`.`n_name` = 'brazil') as `=` from `supplier` as `supplier` inner join `nation` as `nation` on (`supplier`.`s_nationkey` = `nation`.`n_nationkey`)")
 
 - sql: |
     select
@@ -346,6 +323,7 @@
       o_year desc;
 
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first, 1 desc-nulls-last])
       sortagg(group="nation,o_year", sum_profit="sum(amount)")
         memsort(sort="nation asc,o_year desc")
@@ -392,22 +370,23 @@
       value desc;
 
   plan: |
-    Exchange(distribution=single, collation=[1 DESC-nulls-last])
-      MemSort(sort="value DESC")
-        Project(ps_partkey="ps_partkey", value="value")
-          NlJoin(condition="value > $f0 * 0.0001", type="inner")
-            HashAgg(group="ps_partkey", value="SUM(__*__)")
-              Exchange(distribution=hash[1], collation=[])
-                BKAJoin(condition="ps_suppkey = s_suppkey", type="inner")
-                  LogicalView(tables="[0000-0003].supplier_[00-15],nation", shardCount=16, sql="SELECT `supplier`.`s_suppkey` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) AND (`nation`.`n_name` = 'GERMANY'))")
-                  LogicalView(tables="[0000-0003].partsupp_[00-15]", shardCount=16, sql="SELECT `ps_partkey`, `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) AS `__*__` FROM `partsupp` AS `partsupp` WHERE (`ps_suppkey` IN (...))")
-            Exchange(distribution=broadcast, collation=[])
-              HashAgg($f0="SUM($f0)")
-                Exchange(distribution=single, collation=[])
-                  PartialHashAgg($f0="SUM(__*__)")
-                    BKAJoin(condition="ps_suppkey = s_suppkey", type="inner")
-                      LogicalView(tables="[0000-0003].supplier_[00-15],nation", shardCount=16, sql="SELECT `supplier`.`s_suppkey` FROM `supplier` AS `supplier` INNER JOIN `nation` AS `nation` ON ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) AND (`nation`.`n_name` = 'GERMANY'))")
-                      LogicalView(tables="[0000-0003].partsupp_[00-15]", shardCount=16, sql="SELECT `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) AS `__*__` FROM `partsupp` AS `partsupp` WHERE (`ps_suppkey` IN (...))")
+
+    exchange(distribution=single, collation=[1 desc-nulls-last])
+      memsort(sort="value desc")
+        project(ps_partkey="ps_partkey", value="value")
+          nljoin(condition="value > $f0 * 0.0001", type="inner")
+            hashagg(group="ps_partkey", value="sum(__*__)")
+              exchange(distribution=hash[1], collation=[])
+                bkajoin(condition="ps_suppkey = s_suppkey", type="inner")
+                  logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany'))")
+                  logicalview(tables="[0000-0003].partsupp_[00-15]", shardcount=16, sql="select `ps_partkey`, `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) as `__*__` from `partsupp` as `partsupp` force index(`idx_partsupp_suppkey`) where (`ps_suppkey` in (...))")
+            exchange(distribution=broadcast, collation=[])
+              hashagg($f0="sum($f0)")
+                exchange(distribution=single, collation=[])
+                  partialhashagg($f0="sum(__*__)")
+                    bkajoin(condition="ps_suppkey = s_suppkey", type="inner")
+                      logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'germany'))")
+                      logicalview(tables="[0000-0003].partsupp_[00-15]", shardcount=16, sql="select `ps_suppkey`, (`ps_supplycost` * `ps_availqty`) as `__*__` from `partsupp` as `partsupp` force index(`idx_partsupp_suppkey`) where (`ps_suppkey` in (...))")
 
 - sql: |
     select
@@ -433,6 +412,7 @@
     group by l_shipmode
     order by l_shipmode;
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first])
       sortagg(group="l_shipmode", high_line_count="sum(high_line_count)", low_line_count="sum(low_line_count)")
         exchange(distribution=hash[0], collation=[0 asc-nulls-first])
@@ -455,15 +435,16 @@
     custdist desc, c_count desc;
 
   plan: |
-    Exchange(distribution=single, collation=[1 DESC-nulls-last, 0 DESC-nulls-last])
-      MemSort(sort="custdist DESC,c_count DESC")
-        HashAgg(group="c_count", custdist="COUNT()")
-          Exchange(distribution=hash[1], collation=[])
-            HashGroupJoin(condition="c_custkey = o_custkey", type="left")
-              Exchange(distribution=hash[0], collation=[])
-                LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey` FROM `customer` AS `customer`")
-              Exchange(distribution=hash[1], collation=[])
-                LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_orderkey`, `o_custkey` FROM `orders` AS `orders` WHERE (`o_comment` NOT LIKE '%special%requests%')")
+
+    exchange(distribution=single, collation=[1 desc-nulls-last, 0 desc-nulls-last])
+      memsort(sort="custdist desc,c_count desc")
+        hashagg(group="c_count", custdist="count()")
+          exchange(distribution=hash[1], collation=[])
+            hashgroupjoin(condition="c_custkey = o_custkey", type="left")
+              exchange(distribution=hash[0], collation=[])
+                logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey` from `customer` as `customer`")
+              exchange(distribution=hash[1], collation=[])
+                logicalview(tables="[0000-0003].orders_[00-15]", shardcount=16, sql="select `o_orderkey`, `o_custkey` from `orders` as `orders` where (`o_comment` not like '%special%requests%')")
 
 - sql: |
     select
@@ -481,16 +462,17 @@
       and l_shipdate < date_add(cast('1995-09-01' as date ), Interval 1 year );
 
   plan: |
-    Project(promo_revenue="100.00 * $f0 / $f1")
-      HashAgg($f0="SUM($f0)", $f1="SUM($f1)")
-        Exchange(distribution=single, collation=[])
-          PartialHashAgg($f0="SUM($f0)", $f1="SUM($f1)")
-            Project($f0="CASE($3, $1, CAST(0):DECIMAL(37, 4) NOT NULL)", $f1="__*__")
-              HashJoin(condition="l_partkey = p_partkey", type="inner")
-                Exchange(distribution=hash[0], collation=[])
-                  LogicalView(tables="[0000-0003].lineitem_[00-15]", shardCount=16, sql="SELECT `l_partkey`, (`l_extendedprice` * (1 - `l_discount`)) AS `__*__` FROM `lineitem` AS `lineitem` WHERE ((`l_shipdate` >= '1995-09-01') AND (`l_shipdate` < DATE_ADD(CAST('1995-09-01' AS DATE), INTERVAL 1 YEAR)))")
-                Exchange(distribution=hash[0], collation=[])
-                  LogicalView(tables="[0000-0003].part_[00-15]", shardCount=16, sql="SELECT `p_partkey`, (`p_type` LIKE 'PROMO%') AS `LIKE` FROM `part` AS `part`")
+
+    project(promo_revenue="100.00 * $f0 / $f1")
+      hashagg($f0="sum($f0)", $f1="sum($f1)")
+        exchange(distribution=single, collation=[])
+          partialhashagg($f0="sum($f0)", $f1="sum($f1)")
+            project($f0="case($3, $1, cast(0):decimal(37, 4) not null)", $f1="__*__")
+              hashjoin(condition="l_partkey = p_partkey", type="inner")
+                exchange(distribution=hash[0], collation=[])
+                  logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, (`l_extendedprice` * (1 - `l_discount`)) as `__*__` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1995-09-01') and (`l_shipdate` < date_add(cast('1995-09-01' as date), interval 1 year)))")
+                exchange(distribution=hash[0], collation=[])
+                  logicalview(tables="[0000-0003].part_[00-15]", shardcount=16, sql="select `p_partkey`, (`p_type` like 'promo%') as `like` from `part` as `part`")
 
 - sql: |
     /*+TDDL:ENABLE_RUNTIME_FILTER=true */
@@ -531,25 +513,26 @@
     s_suppkey;
 
   plan: |
+
     project(s_suppkey="s_suppkey", s_name="s_name", s_address="s_address", s_phone="s_phone", total_revenue="total_revenue")
       exchange(distribution=single, collation=[0 asc-nulls-first])
         hashjoin(condition="supplier_no = s_suppkey", type="inner")
           exchange(distribution=hash[0], collation=[0 asc-nulls-first])
-            logicalview(tables="[0000-0003].supplier_[00-15]", shardcount=16, sql="select `s_suppkey`, `s_name`, `s_address`, `s_phone` from `supplier` as `supplier` order by `s_suppkey`")
+            logicalview(tables="[0000-0003].supplier_[00-15]", shardcount=16, sql="select `s_suppkey`, `s_name`, `s_address`, `s_phone` from `supplier` as `supplier` force index(`primary`) order by `s_suppkey`")
           project(max(total_revenue)="max(total_revenue)", supplier_no="supplier_no", total_revenue="total_revenue")
             hashjoin(condition="max(total_revenue) = total_revenue", type="inner")
               filter(condition="bloomfilter(total_revenue)")
-                hashagg(group="supplier_no", total_revenue="sum($f1)")
+                hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
                   exchange(distribution=hash[0], collation=[])
-                    logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_suppkey` as `supplier_no`, (`l_extendedprice` * (1 - `l_discount`)) as `$f1` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add('1996-01-01', interval 3 month)))")
+                    logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_suppkey` as `supplier_no`, sum((`l_extendedprice` * (1 - `l_discount`))) as `total_revenue` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add('1996-01-01', interval 3 month))) group by `l_suppkey`")
               exchange(distribution=broadcast, collation=[])
                 runtimefilterbuilder(condition="runtime_filter_builder_[0](max(total_revenue))")
                   hashagg(max(total_revenue)="max(max(total_revenue))")
                     exchange(distribution=single, collation=[])
                       partialhashagg(max(total_revenue)="max(total_revenue)")
-                        hashagg(group="supplier_no", total_revenue="sum($f1)")
+                        hashagg(group="supplier_no", total_revenue="sum(total_revenue)")
                           exchange(distribution=hash[0], collation=[])
-                            logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_suppkey` as `supplier_no`, (`l_extendedprice` * (1 - `l_discount`)) as `$f1` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add(cast('1996-01-01' as date), interval 3 month)))")
+                            logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_suppkey` as `supplier_no`, sum((`l_extendedprice` * (1 - `l_discount`))) as `total_revenue` from `lineitem` as `lineitem` where ((`l_shipdate` >= '1996-01-01') and (`l_shipdate` < date_add(cast('1996-01-01' as date), interval 3 month))) group by `l_suppkey`")
 
 - sql: |
     select
@@ -587,14 +570,14 @@
     exchange(distribution=single, collation=[3 desc-nulls-last, 0 asc-nulls-first, 1 asc-nulls-first, 2 asc-nulls-first])
       memsort(sort="supplier_cnt desc,p_brand asc,p_type asc,p_size asc")
         hashagg(group="p_brand,p_type,p_size", supplier_cnt="count(ps_suppkey)")
-          exchange(distribution=hash[0, 1, 2], collation=[])
-            hashagg(group="p_brand,p_type,p_size,ps_suppkey")
+          hashagg(group="p_brand,p_type,p_size,ps_suppkey")
+            exchange(distribution=hash[2], collation=[])
               project(p_brand="p_brand", p_type="p_type", p_size="p_size", ps_suppkey="ps_suppkey")
                 semihashjoin(condition="ps_suppkey = s_suppkey", type="anti", build="inner")
-                  exchange(distribution=hash[0], collation=[])
-                    logicalview(tables="[0000-0003].partsupp_[00-15],part_[00-15]", shardcount=16, sql="select `partsupp`.`ps_suppkey`, `part`.`p_brand`, `part`.`p_type`, `part`.`p_size` from `partsupp` as `partsupp` inner join `part` as `part` on ((`partsupp`.`ps_partkey` = `part`.`p_partkey`) and (`part`.`p_brand` <> 'brand#45') and (`part`.`p_type` not like 'medium polished') and (`part`.`p_size` in(49, 14, 23, 45, 19, 3, 36, 9)))")
-                  exchange(distribution=hash[0], collation=[])
+                  logicalview(tables="[0000-0003].partsupp_[00-15],part_[00-15]", shardcount=16, sql="select `partsupp`.`ps_suppkey`, `part`.`p_brand`, `part`.`p_type`, `part`.`p_size` from `partsupp` as `partsupp` inner join `part` as `part` on ((`partsupp`.`ps_partkey` = `part`.`p_partkey`) and (`part`.`p_brand` <> 'brand#45') and (`part`.`p_type` not like 'medium polished') and (`part`.`p_size` in(49, 14, 23, 45, 19, 3, 36, 9)))")
+                  exchange(distribution=broadcast, collation=[])
                     logicalview(tables="[0000-0003].supplier_[00-15]", shardcount=16, sql="select `s_suppkey` from `supplier` as `supplier` where (`s_comment` like '%customer%complaints%')")
+
 - sql: |
     select
       sum(l_extendedprice) / 7.0 as avg_yearly
@@ -615,6 +598,7 @@
       );
 
   plan: |
+
     project(avg_yearly="$f0 / 7.0")
       hashagg($f0="sum($f0)")
         exchange(distribution=single, collation=[])
@@ -624,7 +608,8 @@
                 exchange(distribution=hash[1], collation=[])
                   bkajoin(condition="l_partkey = p_partkey", type="inner")
                     logicalview(tables="[0000-0003].part_[00-15]", shardcount=16, sql="select `p_partkey` from `part` as `part` where ((`p_container` = 'med box') and (`p_brand` = 'brand#23'))")
-                    logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem` where (`l_partkey` in (...))")
+                    logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, `l_quantity`, `l_extendedprice` from `lineitem` as `lineitem` force index(`i_l_partkey`) where (`l_partkey` in (...))")
+
 - sql: |
     select
     c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice, sum(l_quantity)
@@ -646,6 +631,7 @@
     o_orderdate;
 
   plan: |
+
     project(c_name="c_name", c_custkey="c_custkey", o_orderkey="o_orderkey", o_orderdate="o_orderdate", o_totalprice="o_totalprice", sum(l_quantity)="sum(l_quantity)")
       exchange(distribution=single, collation=[3 desc-nulls-last, 2 asc-nulls-first])
         memsort(sort="o_totalprice desc,o_orderdate asc")
@@ -653,9 +639,8 @@
             hashjoin(condition="o_custkey = c_custkey", type="inner")
               exchange(distribution=hash[0], collation=[])
                 logicalview(tables="[0000-0003].customer_[00-15]", shardcount=16, sql="select `c_custkey`, `c_name` from `customer` as `customer`")
-              hashagg(group="o_orderkey,o_custkey", o_orderdate="__first_value(o_orderdate)", o_totalprice="__first_value(o_totalprice)", sum(l_quantity)="sum(l_quantity)")
-                exchange(distribution=hash[1], collation=[])
-                  logicalview(tables="[0000-0003].orders_[00-15],lineitem_[00-15]", shardcount=16, sql="select `orders`.`o_orderkey`, `orders`.`o_custkey`, `orders`.`o_totalprice`, `orders`.`o_orderdate`, `lineitem`.`l_quantity` from `orders` as `orders` inner join `lineitem` as `lineitem` on (`orders`.`o_orderkey` = `lineitem`.`l_orderkey`) where (`orders`.`o_orderkey` in (select `l_orderkey` from (select `l_orderkey`, sum(`l_quantity`) as `$f1` from `lineitem` as `lineitem0` group by `l_orderkey` having (sum(`l_quantity`) > 300)) as `t0`))")
+              exchange(distribution=hash[1], collation=[])
+                logicalview(tables="[0000-0003].orders_[00-15],lineitem_[00-15]", shardcount=16, sql="select `orders`.`o_orderkey`, `orders`.`o_custkey`, (`orders`.`o_orderdate`) as `o_orderdate`, (`orders`.`o_totalprice`) as `o_totalprice`, sum(`lineitem`.`l_quantity`) as `sum(l_quantity)` from `orders` as `orders` inner join `lineitem` as `lineitem` on (`orders`.`o_orderkey` = `lineitem`.`l_orderkey`) where (`orders`.`o_orderkey` in (select `l_orderkey` from (select `l_orderkey`, sum(`l_quantity`) as `$f1` from `lineitem` as `lineitem0` group by `l_orderkey` having (sum(`l_quantity`) > 300)) as `t0`)) group by `orders`.`o_orderkey`, `orders`.`o_custkey`")
 
 - sql: |
     select
@@ -691,6 +676,7 @@
     );
 
   plan: |
+
     hashagg(revenue="sum(revenue)")
       exchange(distribution=single, collation=[])
         partialhashagg(revenue="sum(__*__)")
@@ -740,6 +726,7 @@
       s_name;
 
   plan: |
+
     exchange(distribution=single, collation=[0 asc-nulls-first])
       memsort(sort="s_name asc")
         project(s_name="s_name", s_address="s_address")
@@ -749,10 +736,10 @@
             exchange(distribution=hash[0], collation=[])
               project(ps_suppkey="ps_suppkey")
                 hashjoin(condition="l_partkey = ps_partkey and l_suppkey = ps_suppkey and ps_availqty > 0.5 * $f2", type="inner")
-                  hashagg(group="l_partkey,l_suppkey", $f2="sum(l_quantity)")
-                    exchange(distribution=hash[1, 2], collation=[])
+                  hashagg(group="l_partkey,l_suppkey", $f2="sum($f2)")
+                    exchange(distribution=hash[0, 1], collation=[])
                       filter(condition="bloomfilter(l_partkey) and bloomfilter(l_suppkey)")
-                        logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_quantity`, `l_partkey`, `l_suppkey` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(cast('1994-01-01' as date), interval 1 year)) and (`l_shipdate` >= '1994-01-01'))")
+                        logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_partkey`, `l_suppkey`, sum(`l_quantity`) as `$f2` from `lineitem` as `lineitem` where ((`l_shipdate` < date_add(cast('1994-01-01' as date), interval 1 year)) and (`l_shipdate` >= '1994-01-01')) group by `l_partkey`, `l_suppkey`")
                   exchange(distribution=hash[0, 1], collation=[])
                     runtimefilterbuilder(condition="runtime_filter_builder_[0](ps_partkey) and runtime_filter_builder_[1](ps_suppkey)")
                       logicalview(tables="[0000-0003].partsupp_[00-15],part_[00-15]", shardcount=16, sql="select `ps_partkey`, `ps_suppkey`, `ps_availqty` from `partsupp` as `partsupp` where (`ps_partkey` in (select `p_partkey` from `part` as `part` where ((`p_name` like 'forest%') and (`partsupp`.`ps_partkey` = `p_partkey`))))")
@@ -800,6 +787,7 @@
       s_name;
 
   plan: |
+
     exchange(distribution=single, collation=[1 desc-nulls-last, 0 asc-nulls-first])
       memsort(sort="numwait desc,s_name asc")
         hashagg(group="s_name", numwait="count()")
@@ -812,56 +800,4 @@
                   exchange(distribution=broadcast, collation=[])
                     runtimefilterbuilder(condition="runtime_filter_builder_[0](s_suppkey)")
                       logicalview(tables="[0000-0003].supplier_[00-15],nation", shardcount=16, sql="select `supplier`.`s_suppkey`, `supplier`.`s_name` from `supplier` as `supplier` inner join `nation` as `nation` on ((`supplier`.`s_nationkey` = `nation`.`n_nationkey`) and (`nation`.`n_name` = 'saudi arabia'))")
-              logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem` where (`l_orderkey` in (...))")
-
-#-
-#  sql: |
-#    select
-#      cntrycode,
-#      count(*) as numcust,
-#      sum(c_acctbal) as totacctbal
-#    from
-#      (
-#      select
-#        substring(c_phone ,1, 2) as cntrycode,
-#        c_acctbal
-#      from
-#        customer
-#      where
-#        substring(c_phone ,1, 2) in ('13','31','23','29','30','18','17')
-#        and c_acctbal > (
-#          select
-#            avg(c_acctbal)
-#          from
-#            customer
-#          where
-#            c_acctbal > 0.00
-#            and substring (c_phone , 1, 2) in ('13','31','23','29','30','18','17')
-#        )
-#        and not exists (
-#          select
-#            *
-#          from
-#            orders
-#          where
-#            o_custkey = c_custkey
-#        )
-#      ) as custsale
-#    group by
-#      cntrycode
-#    order by
-#      cntrycode;
-#
-#  plan: |
-#    MemSort(sort="cntrycode ASC")
-#      HashAgg(group="cntrycode", numcust="COUNT()", totacctbal="SUM(c_acctbal)")
-#        Project(cntrycode="SUBSTRING(c_phone, 1, 2)", c_acctbal="c_acctbal")
-#          NlJoin(condition="c_acctbal > sum_pushed_sum / sum_pushed_count", type="inner")
-#            SemiHashJoin(condition="c_custkey = o_custkey", type="anti")
-#              Gather(concurrent=true)
-#                LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT `c_custkey`, `c_phone`, `c_acctbal` FROM `customer` AS `customer` WHERE ((SUBSTRING(`c_phone`, 1, 2)) IN('13', '31', '23', '29', '30', '18', '17'))")
-#              Gather(concurrent=true)
-#                LogicalView(tables="[0000-0003].orders_[00-15]", shardCount=16, sql="SELECT `o_custkey` FROM `orders` AS `orders`")
-#            HashAgg(sum_pushed_sum="SUM(pushed_sum)", sum_pushed_count="SUM(pushed_count)")
-#              Gather(concurrent=true)
-#                LogicalView(tables="[0000-0003].customer_[00-15]", shardCount=16, sql="SELECT SUM(`c_acctbal`) AS `pushed_sum`, COUNT(`c_acctbal`) AS `pushed_count` FROM `customer` AS `customer` WHERE ((`c_acctbal` > 0.00) AND ((SUBSTRING(`c_phone`, 1, 2)) IN('13', '31', '23', '29', '30', '18', '17')))")
+              logicalview(tables="[0000-0003].lineitem_[00-15]", shardcount=16, sql="select `l_orderkey`, `l_suppkey` from `lineitem` as `lineitem` force index(`primary`) where (`l_orderkey` in (...))")
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTest.yml
deleted file mode 100644
index e69de29bb..000000000
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTest2.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTest2.ddl.yml
deleted file mode 100644
index e69de29bb..000000000
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTest2.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTest2.yml
deleted file mode 100644
index e69de29bb..000000000
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTestAuto.ddl.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTestAuto.ddl.yml
deleted file mode 100644
index 5b5463ef6..000000000
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTestAuto.ddl.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-test1:
-  CREATE TABLE `test1` (
-  `CODE_CLS_VAL_ID` varchar(32) NOT NULL ,
-  `CODE_CLS_VAL` varchar(256) DEFAULT NULL,
-  `CODE_CLS_TYPE` varchar(64) DEFAULT NULL,
-  `CODE_CLS_VAL_NAME` varchar(1024) DEFAULT NULL,
-  `PRNT_CODE_CLS_VAL` varchar(1024) DEFAULT NULL,
-  PRIMARY KEY USING BTREE (`CODE_CLS_VAL_ID`)
-  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
-  BROADCAST
-test2:
-  CREATE TABLE `test2` (
-  `OBJ_ID` varchar(36) NOT NULL ,
-  `COMPUTE_OBJ_ID` varchar(36) NOT NULL,
-  `OBJ_DETAIL_ID` varchar(36) NOT NULL ,
-  `CLASSIFICATION_CODE` varchar(8) NOT NULL,
-  `AREA_CODE` varchar(8) DEFAULT NULL ,
-  PRIMARY KEY (`OBJ_ID`, `COMPUTE_OBJ_ID`, `OBJ_DETAIL_ID`)
-  ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
-  PARTITION BY KEY(`OBJ_DETAIL_ID`)
-  PARTITIONS 4
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTestAuto.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTestAuto.yml
deleted file mode 100644
index 70e72e9f9..000000000
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/usercase/UserCaseTestAuto.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-- sql : |
-    SELECT a.OBJ_DETAIL_ID AS objDetailId,
-           a.CLASSIFICATION_CODE AS classificationCode,
-      (SELECT pc.CODE_CLS_VAL_NAME
-       FROM test1 pc
-       WHERE pc.CODE_CLS_TYPE = 'FLDM'
-         AND pc.CODE_CLS_VAL = a.CLASSIFICATION_CODE) AS classificationName
-    FROM
-      (SELECT OBJ_DETAIL_ID,
-              CLASSIFICATION_CODE
-       FROM test2 ov
-       WHERE ov.AREA_CODE = '030600') a
-  plan : |
-    gather(concurrent=true)
-      logicalview(tables="test1,test2[p1,p2,p3,p4]", shardcount=4, sql="select `obj_detail_id`, `classification_code`, (((select `code_cls_val_name` from `test1` as `test1` where ((`code_cls_type` = 'fldm') and (`code_cls_val` = `t0`.`classification_code`))))) as `code_cls_val_name` from (select `obj_detail_id`, `classification_code` from `test2` as `test2` where (`area_code` = '030600')) as `t0`")
-- sql : |
-    /*TDDL:ENABLE_LV_SUBQUERY_UNWRAP=false*/
-    SELECT a.OBJ_DETAIL_ID AS objDetailId,
-           a.CLASSIFICATION_CODE AS classificationCode,
-      (SELECT pc.CODE_CLS_VAL_NAME
-       FROM test1 pc
-       WHERE pc.CODE_CLS_TYPE = 'FLDM'
-         AND pc.CODE_CLS_VAL = a.CLASSIFICATION_CODE) AS classificationName
-    FROM
-      (SELECT OBJ_DETAIL_ID,
-              CLASSIFICATION_CODE
-       FROM test2 ov
-       WHERE ov.AREA_CODE = '030600') a
-  plan : |
-    gather(concurrent=true)
-      logicalview(tables="test1,test2[p1,p2,p3,p4]", shardcount=4, sql="select `obj_detail_id`, `classification_code`, (((select `code_cls_val_name` from (select `code_cls_val_name`, `code_cls_val` from `test1` as `test1` where (`code_cls_type` = 'fldm')) as `t2` where (`code_cls_val` = `t0`.`classification_code`)))) as `$f2` from (select `obj_detail_id`, `classification_code` from `test2` as `test2` where (`area_code` = '030600')) as `t0`")
\ No newline at end of file
diff --git a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/values/ValuesPlanTest.yml b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/values/ValuesPlanTest.yml
index eaa559c45..d3fe09dfb 100644
--- a/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/values/ValuesPlanTest.yml
+++ b/polardbx-optimizer/src/test/resources/com/alibaba/polardbx/planner/values/ValuesPlanTest.yml
@@ -4,6 +4,7 @@
       row(2,'name2'); 
 
   plan: |
+
     dynamicvalues(tuples=[{ 1, 'name1' }, { 2, 'name2' }])
 
 - sql: |
@@ -18,6 +19,7 @@
       t(id, name);
 
   plan: |
+
     dynamicvalues(tuples=[{ 1, 'name1' }, { 2, 'name2' }])
 
 - sql: |
@@ -30,6 +32,7 @@
       1
 
   plan: |
+
     topn(sort="column_0 asc", offset=0, fetch=1)
       dynamicvalues(tuples=[{ 1, 'name1' }, { 2, 'name2' }])
 
@@ -49,6 +52,7 @@
       t(id, name);
 
   plan: |
+
     topn(sort="column_0 asc", offset=0, fetch=1)
       dynamicvalues(tuples=[{ 1, 'name1' }, { 2, 'name2' }])
 
@@ -63,12 +67,12 @@
       row(5,'name5');
 
   plan: |
+
     hashagg(group="column_0,column_1")
       unionall(concurrent=true)
         dynamicvalues(tuples=[{ 1, 'name1' }, { 2, 'name2' }])
         dynamicvalues(tuples=[{ 3, 'name3' }, { 4, 'name4' }, { 5, 'name5' }])
 
-
 - sql: |
     select 
       *
@@ -86,11 +90,12 @@
         t.id = test.id;
 
   plan: |
+
     bkajoin(condition="column_0 = id", type="inner")
       dynamicvalues(tuples=[{ 1, 'name1' }, { 2, 'name2' }])
       gather(concurrent=true)
-        logicalview(tables="test[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name` from `test` as `test` where (`id` in (...))")
-    
+        logicalview(tables="test[p1,p2,p3,p4]", shardcount=4, sql="select `id`, `name` from `test` as `test` force index(`primary`) where (`id` in (...))")
+
 - sql: |
     select
       l_orderkey,
@@ -131,6 +136,7 @@
       o_orderdate;
     
   plan: |
+
     project(l_orderkey="l_orderkey", revenue="revenue", o_orderdate="o_orderdate", o_shippriority="o_shippriority")
       exchange(distribution=single, collation=[3 desc-nulls-last, 1 asc-nulls-first])
         memsort(sort="revenue desc,o_orderdate asc")
@@ -145,4 +151,4 @@
                         exchange(distribution=broadcast, collation=[])
                           topn(sort="column_0 asc", offset=0, fetch=2)
                             dynamicvalues(tuples=[{ 1, 'name1' }, { 2, 'name2' }, { 3, 'name3' }, { 4, 'name4' }])
-                    logicalview(tables="customer[p1,p2,p3,p4]", shardcount=4, sql="select `c_custkey`, `c_name` from `customer` as `customer` where ((`c_mktsegment` = 'building') and (((`c_custkey`, `c_name`)) in (...)))")
+                    logicalview(tables="customer[p1,p2,p3,p4]", shardcount=4, sql="select `c_custkey`, `c_name` from `customer` as `customer` force index(`primary`) where ((`c_mktsegment` = 'building') and (((`c_custkey`, `c_name`)) in (...)))")
diff --git a/polardbx-optimizer/src/test/resources/logback.xml b/polardbx-optimizer/src/test/resources/logback.xml
new file mode 100644
index 000000000..2aba8913f
--- /dev/null
+++ b/polardbx-optimizer/src/test/resources/logback.xml
@@ -0,0 +1,13 @@
+
+    
+    
+        
+            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{56} - %msg%n
+            
+        
+    
+
+    
+        
+    
+
\ No newline at end of file
diff --git a/polardbx-orc-tools/dependency-reduced-pom.xml b/polardbx-orc-tools/dependency-reduced-pom.xml
new file mode 100644
index 000000000..9611cdb99
--- /dev/null
+++ b/polardbx-orc-tools/dependency-reduced-pom.xml
@@ -0,0 +1,261 @@
+
+
+  
+    polardbx
+    com.alibaba.polardbx
+    ${revision}
+  
+  4.0.0
+  polardbx-orc-tools
+  ${project.artifactId} module for polardbx ${project.version}
+  Tools for read and write ORC file with command line.
+        Usage: java -jar orc-tools-*.jar [--help] [--define X=Y] <command> <args>
+  
+    ${basedir}/src/java
+    ${basedir}/src/test
+    
+      
+        ${basedir}/src/test/resources
+      
+    
+    
+      
+        
+          org.codehaus.mojo
+          build-helper-maven-plugin
+          3.3.0
+          
+            
+              add-source
+              generate-sources
+              
+                add-source
+              
+              
+                
+                  ${project.build.directory}/generated-sources
+                
+              
+            
+          
+        
+        
+          maven-compiler-plugin
+          3.10.1
+        
+        
+          maven-shade-plugin
+          3.3.0
+        
+        
+          maven-javadoc-plugin
+          3.4.0
+          
+            true
+          
+        
+        
+          maven-dependency-plugin
+          3.1.2
+          
+            
+              package
+              
+                analyze-only
+              
+            
+          
+          
+            true
+            true
+          
+        
+      
+    
+    
+      
+        org.codehaus.mojo
+        build-helper-maven-plugin
+      
+      
+        maven-compiler-plugin
+        
+          8
+          8
+        
+      
+      
+        maven-shade-plugin
+        ${maven-shade-plugin.version}
+        
+          
+            package
+            
+              shade
+            
+            
+              
+                
+                  *:*
+                
+              
+              
+                
+                  org.apache.orc.tools.Driver
+                
+              
+              true
+              uber
+              
+                
+                  com.google.protobuf
+                  org.apache.orc.protobuf
+                
+                
+                  org.apache.hadoop.hive
+                  org.apache.orc.storage
+                
+                
+                  org.apache.hive
+                  org.apache.orc.storage
+                
+                
+                  org.apache.commons
+                  org.apache.orc.shade.commons
+                
+              
+              
+                
+                  *:*
+                  
+                    module-info.class
+                    META-INF/MANIFEST.MF
+                    META-INF/DEPENDENCIES
+                    META-INF/LICENSE
+                    META-INF/NOTICE
+                  
+                
+              
+            
+          
+        
+      
+      
+        maven-javadoc-plugin
+        
+          ${project.artifactId}
+        
+      
+      
+        maven-dependency-plugin
+        
+          
+            com.google.guava:guava
+            org.slf4j:slf4j-simple
+          
+          
+            org.apache.hadoop:hadoop-client-api
+            org.apache.hadoop:hadoop-client-runtime
+          
+        
+      
+    
+  
+  
+    
+      org.apache.hadoop
+      hadoop-hdfs
+      2.7.3
+      provided
+      
+        
+          jsr305
+          com.google.code.findbugs
+        
+        
+          jersey-server
+          com.sun.jersey
+        
+        
+          commons-daemon
+          commons-daemon
+        
+        
+          netty
+          io.netty
+        
+        
+          servlet-api
+          javax.servlet
+        
+        
+          jsp-api
+          javax.servlet.jsp
+        
+        
+          avro
+          org.apache.avro
+        
+        
+          leveldbjni-all
+          org.fusesource.leveldbjni
+        
+        
+          jetty
+          org.mortbay.jetty
+        
+        
+          jetty-util
+          org.mortbay.jetty
+        
+        
+          jasper-runtime
+          tomcat
+        
+        
+          xercesImpl
+          xerces
+        
+        
+          commons-cli
+          commons-cli
+        
+      
+    
+    
+      junit
+      junit
+      4.12
+      test
+      
+        
+          hamcrest-core
+          org.hamcrest
+        
+      
+    
+    
+      org.junit.jupiter
+      junit-jupiter-api
+      5.9.3
+      test
+      
+        
+          opentest4j
+          org.opentest4j
+        
+        
+          junit-platform-commons
+          org.junit.platform
+        
+        
+          apiguardian-api
+          org.apiguardian
+        
+      
+    
+  
+  
+    3.4.1
+  
+
diff --git a/polardbx-orc-tools/pom.xml b/polardbx-orc-tools/pom.xml
index 7267f4eee..821e76a05 100644
--- a/polardbx-orc-tools/pom.xml
+++ b/polardbx-orc-tools/pom.xml
@@ -61,11 +61,6 @@
                 
             
         
-        
-            org.apache.arrow
-            arrow-memory-netty
-            runtime
-        
         
             org.apache.commons
             commons-lang3
@@ -73,92 +68,18 @@
         
             org.apache.hadoop
             hadoop-common
-            ${min.hadoop.version}
-            compile
-            
-                
-                    com.google.code.findbugs
-                    jsr305
-                
-                
-                    com.sun.jersey
-                    jersey-json
-                
-                
-                    commons-beanutils
-                    commons-beanutils-core
-                
-                
-                    commons-daemon
-                    commons-daemon
-                
-                
-                    commons-digester
-                    commons-digester
-                
-                
-                    commons-el
-                    commons-el
-                
-                
-                    javax.servlet
-                    servlet-api
-                
-                
-                    javax.servlet.jsp
-                    jsp-api
-                
-                
-                    jdk.tools
-                    jdk.tools
-                
-                
-                    net.java.dev.jets3t
-                    jets3t
-                
-                
-                    org.tukaani
-                    xz
-                
-                
-                    org.apache.curator
-                    curator-recipes
-                
-                
-                    org.mortbay.jetty
-                    jetty
-                
-                
-                    org.mortbay.jetty
-                    jetty-util
-                
-                
-                    org.apache.avro
-                    avro
-                
-                
-                    tomcat
-                    jasper-compiler
-                
-                
-                    tomcat
-                    jasper-runtime
-                
-                
-                    commons-cli
-                    commons-cli
-                
-                
-                    commons-logging
-                    commons-logging
-                
-            
         
+
+        
+            org.slf4j
+            slf4j-api
+        
+
         
             org.apache.hadoop
             hadoop-hdfs
             ${min.hadoop.version}
-            compile
+            provided
             
                 
                     com.google.code.findbugs
@@ -230,11 +151,6 @@
             gson
             ${gson.version}
         
-        
-            org.slf4j
-            slf4j-api
-            compile
-        
         
             com.opencsv
             opencsv
diff --git a/polardbx-orc/pom.xml b/polardbx-orc/pom.xml
index da6b9f885..8965ed413 100644
--- a/polardbx-orc/pom.xml
+++ b/polardbx-orc/pom.xml
@@ -14,440 +14,345 @@
 -->
 
-  4.0.0
-  
-    com.alibaba.polardbx
-    polardbx
-    ${revision}
-    ../pom.xml
-  
+    4.0.0
+    
+        com.alibaba.polardbx
+        polardbx
+        ${revision}
+        ../pom.xml
+    
 
-  polardbx-orc
-  jar
-  ${project.artifactId} module for polardbx ${project.version}
-  
-    The core reader and writer for ORC files. Uses the vectorized column batch
-    for the in memory representation.
-  
+    polardbx-orc
+    jar
+    ${project.artifactId} module for polardbx ${project.version}
+    
+        The core reader and writer for ORC files. Uses the vectorized column batch
+        for the in memory representation.
+    
 
-  
-    
-    UTF-8
-    false
-    ${project.build.directory}/testing-tmp
-    ${project.basedir}/../../examples
+    
+        
+        UTF-8
+        false
+        ${project.build.directory}/testing-tmp
+        ${project.basedir}/../../examples
 
-    2.7.3
-    3.4.6
-    3.6.3
-    com.google.protobuf:protoc:3.17.3
-  
+        3.6.3
+        com.google.protobuf:protoc:3.17.3
+    
 
-  
+    
 
-    
-      org.apache.orc
-      orc-shims
-      1.6.9
-      
-        
-          slf4j-api
-          org.slf4j
-        
-      
-    
+        
+            org.apache.orc
+            orc-shims
+            1.6.9
+            
+                
+                    slf4j-api
+                    org.slf4j
+                
+            
+        
 
-    
-      com.google.protobuf
-      protobuf-java
-      3.17.3
-    
-    
-      org.apache.commons
-      commons-lang3
-      3.12.0
-    
-    
-      io.airlift
-      aircompressor
-      0.21
-    
+        
+            com.google.protobuf
+            protobuf-java
+            3.17.3
+        
+        
+            org.apache.commons
+            commons-lang3
+            3.12.0
+        
+        
+            io.airlift
+            aircompressor
+            ${aircompressor.version}
+        
 
-    
-      org.apache.hadoop
-      hadoop-common
-      ${min.hadoop.version}
-      provided
-      
-        
-          com.google.code.findbugs
-          jsr305
-        
-        
-          com.sun.jersey
-          jersey-json
-        
-        
-          commons-beanutils
-          commons-beanutils-core
-        
-        
-          commons-daemon
-          commons-daemon
-        
-        
-          commons-digester
-          commons-digester
-        
-        
-          commons-el
-          commons-el
-        
-        
-          javax.servlet
-          servlet-api
-        
-        
-          javax.servlet.jsp
-          jsp-api
-        
-        
-          jdk.tools
-          jdk.tools
-        
-        
-          net.java.dev.jets3t
-          jets3t
-        
-        
-          org.tukaani
-          xz
-        
-        
-          org.apache.curator
-          curator-recipes
-        
-        
-          org.mortbay.jetty
-          jetty
-        
-        
-          org.mortbay.jetty
-          jetty-util
-        
-        
-          org.apache.avro
-          avro
-        
-        
-          tomcat
-          jasper-compiler
-        
-        
-          tomcat
-          jasper-runtime
-        
-      
-    
-    
-      org.apache.hadoop
-      hadoop-hdfs
-      ${min.hadoop.version}
-      provided
-      
-        
-          com.google.code.findbugs
-          jsr305
-        
-        
-          com.sun.jersey
-          jersey-server
-        
-        
-          commons-daemon
-          commons-daemon
-        
-        
-          io.netty
-          netty
-        
-        
-          javax.servlet
-          servlet-api
-        
-        
-          javax.servlet.jsp
-          jsp-api
-        
-        
-          org.apache.avro
-          avro
-        
-        
-          org.fusesource.leveldbjni
-          leveldbjni-all
-        
-        
-          org.mortbay.jetty
-          jetty
-        
-        
-          org.mortbay.jetty
-          jetty-util
-        
-        
-          tomcat
-          jasper-runtime
-        
-        
-          xerces
-          xercesImpl
-        
-      
-    
-    
-      org.apache.hadoop
-      hadoop-mapreduce-client-core
-      ${min.hadoop.version}
-      provided
-      
-        
-          com.google.code.findbugs
-          jsr305
-        
-        
-          javax.servlet
-          servlet-api
-        
-        
-          javax.servlet.jsp
-          jsp-api
-        
-        
-          org.mortbay.jetty
-          jetty
-        
-        
-          org.mortbay.jetty
-          jetty-util
-        
-        
-          org.apache.avro
-          avro
-        
-      
-    
+        
+            org.apache.hadoop
+            hadoop-common
+        
 
-    
-      org.apache.hive
-      hive-storage-api
-      ${storage-api.version}
-      
-        
-          slf4j-api
-          org.slf4j
-        
-      
-    
-    
-      org.jetbrains
-      annotations
-      23.0.0
-    
-    
-      org.slf4j
-      slf4j-api
-      1.7.5
-    
-    
-      ch.qos.logback
-      logback-classic
-      provided
-    
-    
-      org.threeten
-      threetenbp
-      1.3.5
-    
-    
-      org.threeten
-      threeten-extra
-      1.5.0
-    
+        
+            org.apache.hadoop
+            hadoop-hdfs
+            ${min.hadoop.version}
+            provided
+            
+                
+                    com.google.code.findbugs
+                    jsr305
+                
+                
+                    com.sun.jersey
+                    jersey-server
+                
+                
+                    commons-daemon
+                    commons-daemon
+                
+                
+                    io.netty
+                    netty
+                
+                
+                    javax.servlet
+                    servlet-api
+                
+                
+                    javax.servlet.jsp
+                    jsp-api
+                
+                
+                    org.apache.avro
+                    avro
+                
+                
+                    org.fusesource.leveldbjni
+                    leveldbjni-all
+                
+                
+                    org.mortbay.jetty
+                    jetty
+                
+                
+                    org.mortbay.jetty
+                    jetty-util
+                
+                
+                    tomcat
+                    jasper-runtime
+                
+                
+                    xerces
+                    xercesImpl
+                
+            
+        
 
-    
-    
-      com.google.guava
-      guava
-      test
-    
-    
-      junit
-      junit
-      4.13.1
-      test
-    
-    
-      org.mockito
-      mockito-core
-      1.9.5
-      test
-      
-        
-          hamcrest-core
-          org.hamcrest
-        
-      
-    
-    
-      com.google.auto.service
-      auto-service
-      1.0
-      test
-    
+        
+            org.apache.hive
+            hive-storage-api
+            ${storage-api.version}
+            
+                
+                    slf4j-api
+                    org.slf4j
+                
+            
+        
+        
+            org.jetbrains
+            annotations
+            23.0.0
+        
 
-    
-      org.apache.arrow
-      arrow-vector
-    
-    
-      org.apache.arrow
-      arrow-memory-netty
-    
-      
-          org.roaringbitmap
-          RoaringBitmap
-      
+        
+            ch.qos.logback
+            logback-classic
+        
+        
+            org.slf4j
+            jcl-over-slf4j
+        
+        
+            org.slf4j
+            slf4j-api
+        
+        
+            org.slf4j
+            log4j-over-slf4j
+        
 
-  
+        
+        
+        
+        
+        
+        
+            org.threeten
+            threeten-extra
+            1.5.0
+        
 
-  
-    ${basedir}/src/java
-    ${basedir}/src/test
-    
-      
-        ${basedir}/src/resources
-      
-    
-    
-      
-        ${basedir}/src/test/resources
-      
-    
-    
-      
-        org.apache.maven.plugins
-        maven-jar-plugin
-        3.2.0
-        
-          
-            
-              true
-              true
-            
-          
-        
-      
-      
-        org.codehaus.mojo
-        build-helper-maven-plugin
-        3.2.0
-        
-          
-            add-source
-            generate-sources
-            
-              add-source
-            
-            
-              
-                ${project.build.directory}/generated-sources
-              
-            
-          
-        
-      
-      
-        com.github.os72
-        protoc-jar-maven-plugin
-        3.11.4
-        
-          
-            generate-sources
-            
-              run
-            
-            
-              ${protoc.artifact}
-              3.17.3
-              none
-              
-                src/proto
-              
-              
-                src/proto
-              
-            
-          
-        
-      
-      
-        org.apache.maven.plugins
-        maven-shade-plugin
-        3.2.4
-        
-          
-            package
-            
-              shade
-            
-            
-              
-                
-                  com.google.protobuf:protobuf-java
-                  org.apache.hive:hive-storage-api
-                
-              
-              true
-              nohive
-              
-                
-                  com.google.protobuf
-                  com.google.protobuf25
-                
-                
-                  org.apache.hadoop.hive
-                  org.apache.orc.storage
-                
-                
-                  org.apache.hive
-                  org.apache.orc.storage
-                
-              
-            
-          
-        
-      
-      
-        io.github.zlika
-        reproducible-build-maven-plugin
-        0.14
-      
+        
+        
+            com.google.guava
+            guava
+            test
+        
+        
+            junit
+            junit
+            4.13.1
+            test
+        
+        
+            org.mockito
+            mockito-core
+            1.9.5
+            test
+            
+                
+                    hamcrest-core
+                    org.hamcrest
+                
+            
+        
+        
+            com.google.auto.service
+            auto-service
+            1.0
+            test
+        
 
-      
-        org.apache.maven.plugins
-        maven-compiler-plugin
-      
-      
-        org.apache.maven.plugins
-        maven-javadoc-plugin
-        
-          
-            **/OrcProto.java
-          
-          ${project.artifactId}
-        
-      
-    
-  
+
+
+
+
+
+
+
+
+
+
+        
+            org.roaringbitmap
+            RoaringBitmap
+        
+
+    
+
+    
+        ${basedir}/src/java
+        ${basedir}/src/test
+        
+            
+                ${basedir}/src/resources
+            
+        
+        
+            
+                ${basedir}/src/test/resources
+            
+        
+        
+            
+                org.apache.maven.plugins
+                maven-jar-plugin
+                3.2.0
+                
+                    
+                        
+                            true
+                            true
+                        
+                    
+                
+            
+            
+                org.codehaus.mojo
+                build-helper-maven-plugin
+                3.2.0
+                
+                    
+                        add-source
+                        generate-sources
+                        
+                            add-source
+                        
+                        
+                            
+                                ${project.build.directory}/generated-sources
+                            
+                        
+                    
+                
+            
+            
+                com.github.os72
+                protoc-jar-maven-plugin
+                3.11.4
+                
+                    
+                        generate-sources
+                        
+                            run
+                        
+                        
+                            ${protoc.artifact}
+                            3.17.3
+                            none
+                            
+                                src/proto
+                            
+                            
+                                src/proto
+                            
+                        
+                    
+                
+            
+            
+                org.apache.maven.plugins
+                maven-shade-plugin
+                3.2.4
+                
+                    
+                        package
+                        
+                            shade
+                        
+                        
+                            
+                                
+                                    com.google.protobuf:protobuf-java
+                                    org.apache.hive:hive-storage-api
+                                
+                            
+                            true
+                            nohive
+                            
+                                
+                                    com.google.protobuf
+                                    com.google.protobuf25
+                                
+                                
+                                    org.apache.hadoop.hive
+                                    org.apache.orc.storage
+                                
+                                
+                                    org.apache.hive
+                                    org.apache.orc.storage
+                                
+                            
+                        
+                    
+                
+            
+            
+                io.github.zlika
+                reproducible-build-maven-plugin
+                0.14
+            
+
+            
+                org.apache.maven.plugins
+                maven-compiler-plugin
+            
+            
+                org.apache.maven.plugins
+                maven-javadoc-plugin
+                
+                    
+                        **/OrcProto.java
+                    
+                    ${project.artifactId}
+                
+            
+        
+    
 
diff --git a/polardbx-orc/src/java/org/apache/orc/customized/DefaultORCMemoryAllocator.java b/polardbx-orc/src/java/org/apache/orc/customized/DefaultORCMemoryAllocator.java
index 2fdcf8b6d..823acdfa3 100644
--- a/polardbx-orc/src/java/org/apache/orc/customized/DefaultORCMemoryAllocator.java
+++ b/polardbx-orc/src/java/org/apache/orc/customized/DefaultORCMemoryAllocator.java
@@ -16,14 +16,10 @@
 
 package org.apache.orc.customized;
 
-import org.apache.arrow.memory.ArrowBuf;
-import org.apache.arrow.memory.BufferAllocator;
-import org.apache.arrow.memory.RootAllocator;
-
 import java.nio.ByteBuffer;
 
 public class DefaultORCMemoryAllocator implements ORCMemoryAllocator {
-    private BufferAllocator allocator = new RootAllocator();
+//    private BufferAllocator allocator = new RootAllocator();
 
     @Override
     public ByteBuffer allocateOnHeap(int bufferSize) {
@@ -48,17 +44,18 @@ public ByteBuffer allocateOffHeap(int bufferSize) {
 
     @Override
     public Recyclable pooledDirect(int bufferSize) {
-        ArrowBuf arrowBuf = allocator.buffer(bufferSize);
-        return new Recyclable() {
-            @Override
-            public ByteBuffer get() {
-                return arrowBuf.nioBuffer();
-            }
-
-            @Override
-            public void recycle() {
-                arrowBuf.close();
-            }
-        };
+//        ArrowBuf arrowBuf = allocator.buffer(bufferSize);
+//        return new Recyclable() {
+//            @Override
+//            public ByteBuffer get() {
+//                return arrowBuf.nioBuffer();
+//            }
+//
+//            @Override
+//            public void recycle() {
+//                arrowBuf.close();
+//            }
+//        };
+        throw new UnsupportedOperationException();
     }
 }
diff --git a/polardbx-orc/src/java/org/apache/orc/impl/mask/SHA256MaskFactory.java b/polardbx-orc/src/java/org/apache/orc/impl/mask/SHA256MaskFactory.java
index 85264aad6..a1913c541 100644
--- a/polardbx-orc/src/java/org/apache/orc/impl/mask/SHA256MaskFactory.java
+++ b/polardbx-orc/src/java/org/apache/orc/impl/mask/SHA256MaskFactory.java
@@ -22,7 +22,6 @@
 import org.apache.orc.DataMask;
 import org.apache.orc.TypeDescription;
 
-import javax.xml.bind.DatatypeConverter;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
@@ -64,6 +63,8 @@ public class SHA256MaskFactory extends MaskFactory {
 
   private final MessageDigest md;
 
+  private static final char[] hexCode = "0123456789ABCDEF".toCharArray();
+
   SHA256MaskFactory() {
     super();
     try {
@@ -73,6 +74,20 @@ public class SHA256MaskFactory extends MaskFactory {
     }
   }
 
+  public String printHexBinary(byte[] data) {
+    StringBuilder r = new StringBuilder(data.length * 2);
+    byte[] arr$ = data;
+    int len$ = data.length;
+
+    for(int i$ = 0; i$ < len$; ++i$) {
+      byte b = arr$[i$];
+      r.append(hexCode[b >> 4 & 15]);
+      r.append(hexCode[b & 15]);
+    }
+
+    return r.toString();
+  }
+
   /**
    * Mask a string by finding the character category of each character
    * and replacing it with the matching literal.
@@ -87,8 +102,7 @@ void maskString(final BytesColumnVector source, final int row,
 
     // take SHA-256 Hash and convert to HEX
     md.update(source.vector[row], source.start[row], source.length[row]);
-    byte[] hash = DatatypeConverter.printHexBinary(md.digest())
-                      .getBytes(StandardCharsets.UTF_8);
+    byte[] hash = printHexBinary(md.digest()).getBytes(StandardCharsets.UTF_8);
     int targetLength = hash.length;
 
     switch (schema.getCategory()) {
diff --git a/polardbx-parser/pom.xml b/polardbx-parser/pom.xml
index 5079f348f..1d44c9438 100644
--- a/polardbx-parser/pom.xml
+++ b/polardbx-parser/pom.xml
@@ -44,23 +44,6 @@
                 
             
 
-            
-                org.apache.maven.plugins
-                maven-source-plugin
-                2.2.1
-                
-                    
-                        attach-sources
-                        
-                            jar-no-fork
-                        
-                    
-                
-                
-                    true
-                
-            
-
             
                 maven-javadoc-plugin
                 2.10.3
@@ -122,18 +105,6 @@
             fastjson
         
 
-        
-            commons-logging
-            commons-logging
-            ${jcl_version}
-            
-                
-                    javax.servlet
-                    servlet-api
-                
-            
-        
-
         
             org.mockito
             mockito-inline
@@ -142,8 +113,8 @@
         
 
         
-            log4j
-            log4j
+            org.slf4j
+            log4j-over-slf4j
         
         
             org.slf4j
@@ -151,7 +122,7 @@
         
         
             org.slf4j
-            slf4j-log4j12
+            log4j-over-slf4j
         
         
             org.apache.logging.log4j
@@ -256,6 +227,7 @@
             ${aliyun-sdk-oss.version}
             test
         
+
         
             com.aliyun.odps
             odps-sdk-udf
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/SQLUtils.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/SQLUtils.java
index 1c67b0f15..0d2036a8c 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/SQLUtils.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/SQLUtils.java
@@ -98,6 +98,7 @@
 import java.util.Map;
 import java.util.TimeZone;
 
+import static com.alibaba.polardbx.druid.sql.parser.SQLParserFeature.UpperCaseAgg;
 import static com.alibaba.polardbx.druid.util.FnvHash.fnv1a_64_lower;
 
 public class SQLUtils {
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/SQLIndexDefinition.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/SQLIndexDefinition.java
index d4ba2c2ae..bcf216b84 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/SQLIndexDefinition.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/SQLIndexDefinition.java
@@ -24,7 +24,9 @@
 import com.alibaba.polardbx.druid.util.FnvHash;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @version 1.0
@@ -72,6 +74,11 @@ public class SQLIndexDefinition extends SQLObjectImpl implements SQLIndex {
     private SQLName engineName;
     // Compatible layer.
     private List compatibleOptions = new ArrayList();
+    private final Map columnarOptions = new HashMap<>();
+
+    public Map getColumnarOptions() {
+        return columnarOptions;
+    }
 
     public SQLName getEngineName() {
         return engineName;
@@ -484,6 +491,14 @@ public void addOption(String name, SQLExpr value) {
         getCompatibleOptions().add(assignItem);
     }
 
+    public void addColumnarOption(String name, String value) {
+        getColumnarOptions().put(name.toUpperCase(), value.toUpperCase());
+    }
+
+    public void addColumnarOption(Map options) {
+        getColumnarOptions().putAll(options);
+    }
+
     public SQLExpr getOption(String name) {
         if (name == null) {
             return null;
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/SQLIndexOptions.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/SQLIndexOptions.java
index e1ed90c8c..e075ec663 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/SQLIndexOptions.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/SQLIndexOptions.java
@@ -35,6 +35,7 @@ public class SQLIndexOptions extends SQLObjectImpl {
     private String algorithm;
     private String lock;
     private String dictionaryColumns;
+    private String execComment;
     private List otherOptions = new ArrayList();
 
     public String getIndexType() {
@@ -148,6 +149,14 @@ public List getOtherOptions() {
         return otherOptions;
     }
 
+    public String getExecComment() {
+        return execComment;
+    }
+
+    public void setExecComment(String execComment) {
+        this.execComment = execComment;
+    }
+
     @Override
     protected void accept0(SQLASTVisitor visitor) {
         visitor.visit(this);
@@ -179,5 +188,6 @@ public void cloneTo(SQLIndexOptions options) {
             item1.setParent(parent);
             options.otherOptions.add(item1);
         }
+        options.execComment = execComment;
     }
 }
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLCastExpr.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLCastExpr.java
index 59601c42a..55f7926b4 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLCastExpr.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLCastExpr.java
@@ -31,6 +31,10 @@ public class SQLCastExpr extends SQLExprImpl implements SQLObjectWithDataType, S
     protected SQLExpr expr;
     protected SQLDataType dataType;
 
+    //mysql 80在8.0.17版本之后支持 CAST(expr AS type [ARRAY]);
+    //识别array关键字
+    protected boolean hasArray;
+
     public SQLCastExpr() {
 
     }
@@ -105,6 +109,9 @@ public boolean equals(Object o) {
         if (expr != null ? !expr.equals(castExpr.expr) : castExpr.expr != null) {
             return false;
         }
+        if (hasArray != castExpr.hasArray) {
+            return false;
+        }
         return dataType != null ? dataType.equals(castExpr.dataType) : castExpr.dataType == null;
     }
 
@@ -113,6 +120,7 @@ public int hashCode() {
         int result = (isTry ? 1 : 0);
         result = 31 * result + (expr != null ? expr.hashCode() : 0);
         result = 31 * result + (dataType != null ? dataType.hashCode() : 0);
+        result = 31 * result + (hasArray ? 1 : 0);
         return result;
     }
 
@@ -129,6 +137,7 @@ public SQLCastExpr clone() {
         if (dataType != null) {
             x.setDataType(dataType.clone());
         }
+        x.hasArray = hasArray;
         return x;
     }
 
@@ -152,4 +161,12 @@ public void setTry(boolean aTry) {
     public String toString() {
         return SQLUtils.toSQLString(this);
     }
+
+    public boolean isHasArray() {
+        return hasArray;
+    }
+
+    public void setHasArray(boolean hasArray) {
+        this.hasArray = hasArray;
+    }
 }
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLTimeToLiveDefinitionExpr.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLTimeToLiveDefinitionExpr.java
new file mode 100644
index 000000000..6604bb449
--- /dev/null
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLTimeToLiveDefinitionExpr.java
@@ -0,0 +1,344 @@
+package com.alibaba.polardbx.druid.sql.ast.expr;
+
+import com.alibaba.polardbx.druid.sql.ast.SQLExpr;
+import com.alibaba.polardbx.druid.sql.ast.SQLExprImpl;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
+import com.alibaba.polardbx.druid.sql.visitor.SQLASTVisitor;
+
+/**
+ * @author chenghui.lch
+ */
+public class SQLTimeToLiveDefinitionExpr extends SQLExprImpl {
+
+    protected SQLExpr ttlEnableExpr;
+    protected SQLExpr ttlExpr;
+    protected SQLExpr ttlJobExpr;
+    protected SQLExpr ttlFilterExpr;
+    protected SQLExpr archiveTypeExpr;
+    protected SQLExpr archiveTableSchemaExpr;
+    protected SQLExpr archiveTableNameExpr;
+    protected SQLExpr archiveTablePreAllocateExpr;
+    protected SQLExpr archiveTablePostAllocateExpr;
+
+    public SQLTimeToLiveDefinitionExpr() {
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        SQLTimeToLiveDefinitionExpr otherTtlDefineExpr = (SQLTimeToLiveDefinitionExpr) obj;
+        SQLExpr otherTtlEnableExpr = otherTtlDefineExpr.getTtlEnableExpr();
+        SQLExpr otherTtlExpr = otherTtlDefineExpr.getTtlExpr();
+        SQLExpr otherTtlJobExpr = otherTtlDefineExpr.getTtlJobExpr();
+        SQLExpr otherTtlFilterExpr = otherTtlDefineExpr.getTtlFilterExpr();
+        SQLExpr otherArchiveTypeExpr = otherTtlDefineExpr.getArchiveTypeExpr();
+        SQLExpr otherArchiveSchemaExpr = otherTtlDefineExpr.getArchiveTableSchemaExpr();
+        SQLExpr otherArchiveNameExpr = otherTtlDefineExpr.getArchiveTableNameExpr();
+        SQLExpr otherArchivePreAllocateExpr = otherTtlDefineExpr.getArchiveTablePreAllocateExpr();
+        SQLExpr otherArchivePostAllocateExpr = otherTtlDefineExpr.getArchiveTablePostAllocateExpr();
+
+        if (ttlEnableExpr != null) {
+            if (otherTtlEnableExpr == null) {
+                return false;
+            }
+            if (!ttlEnableExpr.equals(otherTtlEnableExpr)) {
+                return false;
+            }
+        } else {
+            if (otherTtlEnableExpr != null) {
+                return false;
+            }
+        }
+
+        if (ttlExpr != null) {
+            if (otherTtlExpr == null) {
+                return false;
+            }
+            if (!ttlExpr.equals(otherTtlExpr)) {
+                return false;
+            }
+        } else {
+            if (otherTtlExpr != null) {
+                return false;
+            }
+        }
+
+        if (ttlJobExpr != null) {
+            if (otherTtlJobExpr == null) {
+                return false;
+            }
+            if (!ttlJobExpr.equals(otherTtlJobExpr)) {
+                return false;
+            }
+        } else {
+            if (otherTtlJobExpr != null) {
+                return false;
+            }
+        }
+
+        if (ttlFilterExpr != null) {
+            if (otherTtlFilterExpr == null) {
+                return false;
+            }
+            if (!ttlExpr.equals(otherTtlFilterExpr)) {
+                return false;
+            }
+        } else {
+            if (otherTtlFilterExpr != null) {
+                return false;
+            }
+        }
+
+        if (archiveTypeExpr != null) {
+            if (otherArchiveTypeExpr == null) {
+                return false;
+            }
+            if (!archiveTypeExpr.equals(otherArchiveTypeExpr)) {
+                return false;
+            }
+        } else {
+            if (otherArchiveTypeExpr != null) {
+                return false;
+            }
+        }
+
+        if (archiveTableSchemaExpr != null) {
+            if (otherArchiveSchemaExpr == null) {
+                return false;
+            }
+            if (!archiveTableSchemaExpr.equals(otherArchiveSchemaExpr)) {
+                return false;
+            }
+        } else {
+            if (otherArchiveSchemaExpr != null) {
+                return false;
+            }
+        }
+
+        if (archiveTableNameExpr != null) {
+            if (otherArchiveNameExpr == null) {
+                return false;
+            }
+            if (!archiveTableNameExpr.equals(otherArchiveNameExpr)) {
+                return false;
+            }
+        } else {
+            if (otherArchiveNameExpr != null) {
+                return false;
+            }
+        }
+
+        if (archiveTablePreAllocateExpr != null) {
+            if (otherArchivePreAllocateExpr == null) {
+                return false;
+            }
+            if (!archiveTablePreAllocateExpr.equals(otherArchivePreAllocateExpr)) {
+                return false;
+            }
+        } else {
+            if (otherArchivePreAllocateExpr != null) {
+                return false;
+            }
+        }
+
+        if (archiveTablePostAllocateExpr != null) {
+            if (otherArchivePostAllocateExpr == null) {
+                return false;
+            }
+            if (!archiveTablePostAllocateExpr.equals(otherArchivePostAllocateExpr)) {
+                return false;
+            }
+        } else {
+            if (otherArchivePostAllocateExpr != null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("");
+        SQLASTVisitor visitor = new MySqlOutputVisitor(sb);
+        this.accept(visitor);
+        return sb.toString();
+    }
+
+    @Override
+    public int hashCode() {
+
+        int result = ttlEnableExpr != null ? ttlEnableExpr.hashCode() : 0;
+        result = 31 * result + (ttlExpr != null ? ttlExpr.hashCode() : 0);
+        result = 31 * result + (ttlJobExpr != null ? ttlJobExpr.hashCode() : 0);
+        result = 31 * result + (ttlFilterExpr != null ? ttlFilterExpr.hashCode() : 0);
+        result = 31 * result + (archiveTypeExpr != null ? archiveTypeExpr.hashCode() : 0);
+        result = 31 * result + (archiveTableSchemaExpr != null ? archiveTableSchemaExpr.hashCode() : 0);
+        result = 31 * result + (archiveTableNameExpr != null ? archiveTableNameExpr.hashCode() : 0);
+        result = 31 * result + (archiveTablePreAllocateExpr != null ? archiveTablePreAllocateExpr.hashCode() : 0);
+        result = 31 * result + (archiveTablePostAllocateExpr != null ? archiveTablePostAllocateExpr.hashCode() : 0);
+
+        return result;
+    }
+
+    @Override
+    public SQLExpr clone() {
+
+        SQLTimeToLiveDefinitionExpr sqlTimeToLiveDefinitionExpr = new SQLTimeToLiveDefinitionExpr();
+
+        if (ttlEnableExpr != null) {
+            sqlTimeToLiveDefinitionExpr.setTtlEnableExpr(ttlEnableExpr.clone());
+        }
+
+        if (ttlExpr != null) {
+            sqlTimeToLiveDefinitionExpr.setTtlExpr(ttlExpr.clone());
+        }
+
+        if (ttlJobExpr != null) {
+            sqlTimeToLiveDefinitionExpr.setTtlJobExpr(ttlJobExpr.clone());
+        }
+        if (archiveTypeExpr != null) {
+            sqlTimeToLiveDefinitionExpr.setArchiveTypeExpr(archiveTypeExpr.clone());
+        }
+
+        if (archiveTableSchemaExpr != null) {
+            sqlTimeToLiveDefinitionExpr.setArchiveTableSchemaExpr(archiveTableSchemaExpr.clone());
+        }
+
+        if (archiveTableNameExpr != null) {
+            sqlTimeToLiveDefinitionExpr.setArchiveTableNameExpr(archiveTableNameExpr.clone());
+        }
+
+        if (archiveTablePreAllocateExpr != null) {
+            sqlTimeToLiveDefinitionExpr.setArchiveTablePreAllocateExpr(archiveTablePreAllocateExpr.clone());
+        }
+
+        if (archiveTablePostAllocateExpr != null) {
+            sqlTimeToLiveDefinitionExpr.setArchiveTablePostAllocateExpr(archiveTablePostAllocateExpr.clone());
+        }
+
+        return sqlTimeToLiveDefinitionExpr;
+    }
+
+    @Override
+    protected void accept0(SQLASTVisitor visitor) {
+        if (visitor.visit(this)) {
+            if (ttlEnableExpr != null) {
+                acceptChild(visitor, ttlEnableExpr);
+            }
+
+            if (ttlExpr != null) {
+                acceptChild(visitor, ttlExpr);
+            }
+
+            if (ttlJobExpr != null) {
+                acceptChild(visitor, ttlJobExpr);
+            }
+
+            if (ttlFilterExpr != null) {
+                acceptChild(visitor, ttlFilterExpr);
+            }
+
+            if (archiveTypeExpr != null) {
+                acceptChild(visitor, archiveTypeExpr);
+            }
+
+            if (archiveTableSchemaExpr != null) {
+                acceptChild(visitor, archiveTableSchemaExpr);
+            }
+
+            if (archiveTableNameExpr != null) {
+                acceptChild(visitor, archiveTableNameExpr);
+            }
+
+            if (archiveTablePreAllocateExpr != null) {
+                acceptChild(visitor, archiveTablePreAllocateExpr);
+            }
+
+            if (archiveTablePostAllocateExpr != null) {
+                acceptChild(visitor, archiveTablePostAllocateExpr);
+            }
+        }
+        visitor.endVisit(this);
+    }
+
+    public SQLExpr getTtlEnableExpr() {
+        return ttlEnableExpr;
+    }
+
+    public void setTtlEnableExpr(SQLExpr ttlEnableExpr) {
+        this.ttlEnableExpr = ttlEnableExpr;
+    }
+
+    public SQLExpr getTtlExpr() {
+        return ttlExpr;
+    }
+
+    public void setTtlExpr(SQLExpr ttlExpr) {
+        this.ttlExpr = ttlExpr;
+    }
+
+    public SQLExpr getTtlJobExpr() {
+        return ttlJobExpr;
+    }
+
+    public void setTtlJobExpr(SQLExpr ttlJobExpr) {
+        this.ttlJobExpr = ttlJobExpr;
+    }
+
+    public SQLExpr getTtlFilterExpr() {
+        return ttlFilterExpr;
+    }
+
+    public void setTtlFilterExpr(SQLExpr ttlFilterExpr) {
+        this.ttlFilterExpr = ttlFilterExpr;
+    }
+
+    public SQLExpr getArchiveTypeExpr() {
+        return archiveTypeExpr;
+    }
+
+    public void setArchiveTypeExpr(SQLExpr archiveTypeExpr) {
+        this.archiveTypeExpr = archiveTypeExpr;
+    }
+
+    public SQLExpr getArchiveTableSchemaExpr() {
+        return archiveTableSchemaExpr;
+    }
+
+    public void setArchiveTableSchemaExpr(SQLExpr archiveTableSchemaExpr) {
+        this.archiveTableSchemaExpr = archiveTableSchemaExpr;
+    }
+
+    public SQLExpr getArchiveTableNameExpr() {
+        return archiveTableNameExpr;
+    }
+
+    public void setArchiveTableNameExpr(SQLExpr archiveTableNameExpr) {
+        this.archiveTableNameExpr = archiveTableNameExpr;
+    }
+
+    public SQLExpr getArchiveTablePreAllocateExpr() {
+        return archiveTablePreAllocateExpr;
+    }
+
+    public void setArchiveTablePreAllocateExpr(SQLExpr archiveTablePreAllocateExpr) {
+        this.archiveTablePreAllocateExpr = archiveTablePreAllocateExpr;
+    }
+
+    public SQLExpr getArchiveTablePostAllocateExpr() {
+        return archiveTablePostAllocateExpr;
+    }
+
+    public void setArchiveTablePostAllocateExpr(SQLExpr archiveTablePostAllocateExpr) {
+        this.archiveTablePostAllocateExpr = archiveTablePostAllocateExpr;
+    }
+}
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLTimeToLiveExpr.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLTimeToLiveExpr.java
new file mode 100644
index 000000000..5cf670d70
--- /dev/null
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLTimeToLiveExpr.java
@@ -0,0 +1,174 @@
+package com.alibaba.polardbx.druid.sql.ast.expr;
+
+import com.alibaba.polardbx.druid.sql.ast.SQLExpr;
+import com.alibaba.polardbx.druid.sql.ast.SQLExprImpl;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
+import com.alibaba.polardbx.druid.sql.visitor.SQLASTVisitor;
+
+/**
+ * @author chenghui.lch
+ */
+public class SQLTimeToLiveExpr extends SQLExprImpl {
+
+    protected SQLExpr column;
+    protected SQLExpr expireAfter;
+    protected SQLExpr unit;
+    protected SQLExpr timezone;
+
+    public SQLTimeToLiveExpr() {
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        SQLTimeToLiveExpr otherTtlExpr = (SQLTimeToLiveExpr) obj;
+        SQLExpr otherColumn = otherTtlExpr.getColumn();
+        SQLExpr otherExpireAfter = otherTtlExpr.getExpireAfter();
+        SQLExpr otherUnit = otherTtlExpr.getUnit();
+        SQLExpr otherTimezone = otherTtlExpr.getTimezone();
+
+        if (column != null) {
+            if (!column.equals(otherColumn)) {
+                return false;
+            }
+        } else {
+            if (otherColumn != null) {
+                return false;
+            }
+        }
+
+        if (expireAfter != null) {
+            if (!expireAfter.equals(otherExpireAfter)) {
+                return false;
+            }
+        } else {
+            if (otherExpireAfter != null) {
+                return false;
+            }
+        }
+
+        if (unit != null) {
+            if (!unit.equals(otherUnit)) {
+                return false;
+            }
+        } else {
+            if (otherUnit != null) {
+                return false;
+            }
+        }
+
+        if (timezone != null) {
+            if (!timezone.equals(otherTimezone)) {
+                return false;
+            }
+        } else {
+            if (otherTimezone != null) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = column != null ? column.hashCode() : 0;
+        result = 31 * result + (expireAfter != null ? expireAfter.hashCode() : 0);
+        result = 31 * result + (unit != null ? unit.hashCode() : 0);
+        result = 31 * result + (timezone != null ? timezone.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public SQLExpr clone() {
+        SQLTimeToLiveExpr newTtlExpr = new SQLTimeToLiveExpr();
+        if (column != null) {
+            newTtlExpr.setColumn(column.clone());
+        }
+
+        if (expireAfter != null) {
+            newTtlExpr.setExpireAfter(expireAfter.clone());
+        }
+
+        if (unit != null) {
+            newTtlExpr.setUnit(unit.clone());
+        }
+
+        if (timezone != null) {
+            newTtlExpr.setTimezone(timezone.clone());
+        }
+        return newTtlExpr;
+    }
+
+    @Override
+    protected void accept0(SQLASTVisitor visitor) {
+        if (visitor.visit(this)) {
+            if (this.column != null) {
+                acceptChild(visitor, this.column);
+            }
+
+            if (this.timezone != null) {
+                acceptChild(visitor, this.expireAfter);
+            }
+
+            if (this.unit != null) {
+                acceptChild(visitor, this.unit);
+            }
+
+            if (this.timezone != null) {
+                acceptChild(visitor, this.timezone);
+            }
+        }
+        visitor.endVisit(this);
+    }
+
+    @Override
+    public String toString() {
+
+        StringBuilder sb = new StringBuilder("");
+        SQLASTVisitor visitor = new MySqlOutputVisitor(sb);
+        this.accept(visitor);
+        return sb.toString();
+    }
+
+    public SQLExpr getColumn() {
+        return column;
+    }
+
+    public void setColumn(SQLExpr column) {
+        this.column = column;
+    }
+
+    public SQLExpr getExpireAfter() {
+        return expireAfter;
+    }
+
+    public void setExpireAfter(SQLExpr expireAfter) {
+        this.expireAfter = expireAfter;
+    }
+
+    public SQLExpr getUnit() {
+        return unit;
+    }
+
+    public void setUnit(SQLExpr unit) {
+        this.unit = unit;
+    }
+
+    public SQLExpr getTimezone() {
+        return timezone;
+    }
+
+    public void setTimezone(SQLExpr timezone) {
+        this.timezone = timezone;
+    }
+}
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLTimeToLiveJobExpr.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLTimeToLiveJobExpr.java
new file mode 100644
index 000000000..7a650b4cf
--- /dev/null
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/expr/SQLTimeToLiveJobExpr.java
@@ -0,0 +1,116 @@
+package com.alibaba.polardbx.druid.sql.ast.expr;
+
+import com.alibaba.polardbx.druid.sql.ast.SQLExpr;
+import com.alibaba.polardbx.druid.sql.ast.SQLExprImpl;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
+import com.alibaba.polardbx.druid.sql.visitor.SQLASTVisitor;
+
+/**
+ * @author chenghui.lch
+ */
+public class SQLTimeToLiveJobExpr extends SQLExprImpl {
+
+    protected SQLExpr cron;
+    protected SQLExpr timezone;
+
+    public SQLTimeToLiveJobExpr() {
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        SQLTimeToLiveJobExpr otherTtlExpr = (SQLTimeToLiveJobExpr) obj;
+        SQLExpr otherCron = otherTtlExpr.getCron();
+        SQLExpr otherTimezone = otherTtlExpr.getTimezone();
+
+        if (cron != null) {
+            if (!cron.equals(otherCron)) {
+                return false;
+            }
+        } else {
+            if (otherCron != null) {
+                return false;
+            }
+        }
+
+        if (timezone != null) {
+            if (!timezone.equals(otherTimezone)) {
+                return false;
+            }
+        } else {
+            if (otherTimezone != null) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("");
+        SQLASTVisitor visitor = new MySqlOutputVisitor(sb);
+        this.accept(visitor);
+        return sb.toString();
+    }
+
+    @Override
+    public int hashCode() {
+        int result = cron != null ? cron.hashCode() : 0;
+        result = 31 * result + (timezone != null ? timezone.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public SQLExpr clone() {
+        SQLTimeToLiveJobExpr newTtlExpr = new SQLTimeToLiveJobExpr();
+        if (cron != null) {
+            newTtlExpr.setCron(cron.clone());
+        }
+
+        if (timezone != null) {
+            newTtlExpr.setTimezone(timezone.clone());
+        }
+        return newTtlExpr;
+    }
+
+    @Override
+    protected void accept0(SQLASTVisitor visitor) {
+        if (visitor.visit(this)) {
+            if (cron != null) {
+                acceptChild(visitor, cron);
+            }
+
+            if (timezone != null) {
+                acceptChild(visitor, timezone);
+            }
+
+        }
+        visitor.endVisit(this);
+    }
+
+    public SQLExpr getTimezone() {
+        return timezone;
+    }
+
+    public void setTimezone(SQLExpr timezone) {
+        this.timezone = timezone;
+    }
+
+    public SQLExpr getCron() {
+        return cron;
+    }
+
+    public void setCron(SQLExpr cron) {
+        this.cron = cron;
+    }
+}
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/DrdsAlterTableCleanupExpiredData.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/DrdsAlterTableCleanupExpiredData.java
new file mode 100644
index 000000000..86572b497
--- /dev/null
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/DrdsAlterTableCleanupExpiredData.java
@@ -0,0 +1,17 @@
+package com.alibaba.polardbx.druid.sql.ast.statement;
+
+import com.alibaba.polardbx.druid.sql.ast.SQLObjectImpl;
+import com.alibaba.polardbx.druid.sql.visitor.SQLASTVisitor;
+
+public class DrdsAlterTableCleanupExpiredData extends SQLObjectImpl implements SQLAlterTableItem {
+
+    public DrdsAlterTableCleanupExpiredData() {
+        super();
+    }
+
+    @Override
+    protected void accept0(SQLASTVisitor visitor) {
+        visitor.visit(this);
+        visitor.endVisit(this);
+    }
+}
\ No newline at end of file
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/DrdsArchivePartition.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/DrdsArchivePartition.java
new file mode 100644
index 000000000..1b8516cc6
--- /dev/null
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/DrdsArchivePartition.java
@@ -0,0 +1,38 @@
+package com.alibaba.polardbx.druid.sql.ast.statement;
+
+import com.alibaba.polardbx.druid.sql.ast.SQLName;
+import com.alibaba.polardbx.druid.sql.ast.SQLObjectImpl;
+import com.alibaba.polardbx.druid.sql.visitor.SQLASTVisitor;
+
+import java.util.List;
+
+/**
+ * @author wumu
+ */
+public class DrdsArchivePartition extends SQLObjectImpl implements SQLAlterTableItem {
+    private List partitions;
+
+    private boolean subPartitionsArchive;
+
+    public List getPartitions() {
+        return partitions;
+    }
+
+    public void setPartitions(List partitions) {
+        this.partitions = partitions;
+    }
+
+    public boolean isSubPartitionsArchive() {
+        return subPartitionsArchive;
+    }
+
+    public void setSubPartitionsArchive(boolean subPartitionsArchive) {
+        this.subPartitionsArchive = subPartitionsArchive;
+    }
+
+    @Override
+    protected void accept0(SQLASTVisitor visitor) {
+        visitor.visit(this);
+        visitor.endVisit(this);
+    }
+}
\ No newline at end of file
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableAddIndex.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableAddIndex.java
index 3ed28f617..3fe5738c3 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableAddIndex.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableAddIndex.java
@@ -29,6 +29,10 @@
 
 public class SQLAlterTableAddIndex extends SQLObjectImpl implements SQLAlterTableItem, SQLIndex {
 
+    public void setIndexDefinition(SQLIndexDefinition indexDefinition) {
+        this.indexDefinition = indexDefinition;
+    }
+
     private SQLIndexDefinition indexDefinition = new SQLIndexDefinition();
 
     public SQLAlterTableAddIndex() {
@@ -282,4 +286,12 @@ public List getClusteredKeys() {
     public List getColumns() {
         return indexDefinition.getColumns();
     }
+
+    @Override
+    public SQLAlterTableAddIndex clone() {
+        SQLAlterTableAddIndex x = new SQLAlterTableAddIndex();
+        x.setIndexDefinition(indexDefinition);
+        x.setParent(parent);
+        return x;
+    }
 }
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableOptimizePartition.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableOptimizePartition.java
index a397bdf4c..08a2d5331 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableOptimizePartition.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableOptimizePartition.java
@@ -26,6 +26,8 @@ public class SQLAlterTableOptimizePartition extends SQLObjectImpl implements SQL
 
     private final List partitions = new ArrayList(4);
 
+    private boolean isSubPartition = false;
+
     public List getPartitions() {
         return partitions;
     }
@@ -44,4 +46,13 @@ protected void accept0(SQLASTVisitor visitor) {
         }
         visitor.endVisit(this);
     }
+
+    public boolean isSubPartition() {
+        return isSubPartition;
+    }
+
+    public void setSubPartition(boolean subPartition) {
+        isSubPartition = subPartition;
+    }
+
 }
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableStatement.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableStatement.java
index c73c14b1c..7109706ec 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableStatement.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLAlterTableStatement.java
@@ -24,6 +24,7 @@
 import com.alibaba.polardbx.druid.sql.ast.SqlType;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLIdentifierExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLPropertyExpr;
+import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveDefinitionExpr;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlignToTableGroup;
 import com.alibaba.polardbx.druid.sql.visitor.SQLASTVisitor;
 import com.alibaba.polardbx.druid.util.Pair;
@@ -34,6 +35,11 @@
 public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLStatement, SQLAlterStatement {
 
     private SQLExprTableSource tableSource;
+
+    public void setItems(List items) {
+        this.items = items;
+    }
+
     private List items = new ArrayList();
 
     // for mysql
@@ -52,6 +58,8 @@ public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLSt
     private SQLPartitionBy localPartition = null;
     private DrdsAlignToTableGroup alignToTableGroup = null;
 
+    private DrdsArchivePartition drdsArchivePartition = null;
+
     public SQLExpr getLocality() {
         return locality;
     }
@@ -321,6 +329,14 @@ public void setAlterIndexName(SQLName alterIndexName) {
         this.alterIndexName = alterIndexName;
     }
 
+    public DrdsArchivePartition getDrdsArchivePartition() {
+        return drdsArchivePartition;
+    }
+
+    public void setDrdsArchivePartition(DrdsArchivePartition drdsArchivePartition) {
+        this.drdsArchivePartition = drdsArchivePartition;
+    }
+
     @Override
     public SqlType getSqlType() {
         return SqlType.ALTER;
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLSelectOrderByItem.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLSelectOrderByItem.java
index 19a57e8a6..7380efbbd 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLSelectOrderByItem.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLSelectOrderByItem.java
@@ -34,6 +34,14 @@ public final class SQLSelectOrderByItem extends SQLObjectImpl implements SQLRepl
 
     protected transient SQLSelectItem resolvedSelectItem;
 
+    // 是否有括号包裹表达式,创建索引时,mysql 8.0 对于表达式需要用括号包裹,否则会报错,例如:
+    // INDEX ((col1 + col2), (col3 - col4)) 是可以的
+    // INDEX (col1 + col2, col3 - col4) 报错
+    // INDEX ((col1), (col2)) 报错
+    // INDEX ((CAST(XX))) 可以的
+    // INDEX (CAST(XX)) 报错
+    protected boolean hasParen;
+
     public SQLSelectOrderByItem() {
 
     }
@@ -99,6 +107,7 @@ public int hashCode() {
         result = prime * result + ((collate == null) ? 0 : collate.hashCode());
         result = prime * result + ((expr == null) ? 0 : expr.hashCode());
         result = prime * result + ((type == null) ? 0 : type.hashCode());
+        result = prime * result + (hasParen ? 1 : 0);
         return result;
     }
 
@@ -131,6 +140,10 @@ public boolean equals(Object obj) {
         if (type != other.type) {
             return false;
         }
+
+        if (hasParen != other.hasParen) {
+            return false;
+        }
         return true;
     }
 
@@ -170,6 +183,7 @@ public SQLSelectOrderByItem clone() {
         x.collate = collate;
         x.type = type;
         x.nullsOrderType = nullsOrderType;
+        x.hasParen = hasParen;
         return x;
     }
 
@@ -217,4 +231,12 @@ public boolean isDistributeBy() {
 
         return false;
     }
+
+    public boolean isHasParen() {
+        return hasParen;
+    }
+
+    public void setHasParen(boolean hasParen) {
+        this.hasParen = hasParen;
+    }
 }
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLStartReplicaCheckTableStatement.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLStartReplicaCheckTableStatement.java
index bcb2bf797..534b2954e 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLStartReplicaCheckTableStatement.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/ast/statement/SQLStartReplicaCheckTableStatement.java
@@ -30,6 +30,7 @@ public class SQLStartReplicaCheckTableStatement extends SQLStatementImpl {
     private SQLName channel;
     private SQLName dbName;
     private SQLName tableName;
+    private SQLName mode;
 
     @Override
     protected void accept0(SQLASTVisitor v) {
@@ -61,6 +62,14 @@ public void setTableName(SQLName tableName) {
         this.tableName = tableName;
     }
 
+    public SQLName getMode() {
+        return mode;
+    }
+
+    public void setMode(SQLName mode) {
+        this.mode = mode;
+    }
+
     @Override
     public SqlType getSqlType() {
         return null;
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsAlterTableModifyTtlOptions.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsAlterTableModifyTtlOptions.java
new file mode 100644
index 000000000..1e929cd85
--- /dev/null
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsAlterTableModifyTtlOptions.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 1999-2017 Alibaba Group Holding Ltd.
+ *
+ * Licensed 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 com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement;
+
+import com.alibaba.polardbx.druid.sql.ast.SQLExpr;
+import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableItem;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
+
+/**
+ * @author chenghui.lch
+ */
+public class DrdsAlterTableModifyTtlOptions extends MySqlObjectImpl implements SQLAlterTableItem {
+
+    protected SQLExpr ttlEnable;
+    protected SQLExpr ttlExpr;
+    protected SQLExpr ttlJob;
+    protected SQLExpr ttlFilter;
+
+    protected SQLExpr archiveTableSchema;
+    protected SQLExpr archiveTableName;
+    protected SQLExpr archiveKind;
+
+    protected SQLExpr arcPreAllocate;
+    protected SQLExpr arcPostAllocate;
+
+//    protected SQLExpr ttlArchiveCci;
+//    protected SQLExpr archiveView;
+
+    public DrdsAlterTableModifyTtlOptions() {
+    }
+
+    @Override
+    public void accept0(MySqlASTVisitor visitor) {
+        if (visitor.visit(this)) {
+            if (this.ttlEnable != null) {
+                this.ttlEnable.accept(visitor);
+            }
+
+            if (this.ttlExpr != null) {
+                this.ttlExpr.accept(visitor);
+            }
+
+            if (this.ttlJob != null) {
+                this.ttlJob.accept(visitor);
+            }
+
+            if (this.archiveKind != null) {
+                this.archiveKind.accept(visitor);
+            }
+
+            if (this.archiveTableSchema != null) {
+                this.archiveTableSchema.accept(visitor);
+            }
+
+            if (this.archiveTableName != null) {
+                this.archiveTableName.accept(visitor);
+            }
+        }
+        visitor.endVisit(this);
+    }
+
+    public SQLExpr getTtlEnable() {
+        return ttlEnable;
+    }
+
+    public void setTtlEnable(SQLExpr ttlEnable) {
+        this.ttlEnable = ttlEnable;
+    }
+
+    public SQLExpr getTtlExpr() {
+        return ttlExpr;
+    }
+
+    public void setTtlExpr(SQLExpr ttlExpr) {
+        this.ttlExpr = ttlExpr;
+    }
+
+    public SQLExpr getTtlJob() {
+        return ttlJob;
+    }
+
+    public void setTtlJob(SQLExpr ttlJob) {
+        this.ttlJob = ttlJob;
+    }
+
+    public SQLExpr getArchiveTableSchema() {
+        return archiveTableSchema;
+    }
+
+    public void setArchiveTableSchema(SQLExpr archiveTableSchema) {
+        this.archiveTableSchema = archiveTableSchema;
+    }
+
+    public SQLExpr getArchiveTableName() {
+        return archiveTableName;
+    }
+
+    public void setArchiveTableName(SQLExpr archiveTableName) {
+        this.archiveTableName = archiveTableName;
+    }
+
+    public SQLExpr getArchiveKind() {
+        return archiveKind;
+    }
+
+    public void setArchiveKind(SQLExpr archiveKind) {
+        this.archiveKind = archiveKind;
+    }
+
+    public SQLExpr getArcPreAllocate() {
+        return arcPreAllocate;
+    }
+
+    public void setArcPreAllocate(SQLExpr arcPreAllocate) {
+        this.arcPreAllocate = arcPreAllocate;
+    }
+
+    public SQLExpr getArcPostAllocate() {
+        return arcPostAllocate;
+    }
+
+    public void setArcPostAllocate(SQLExpr arcPostAllocate) {
+        this.arcPostAllocate = arcPostAllocate;
+    }
+
+    public SQLExpr getTtlFilter() {
+        return ttlFilter;
+    }
+
+    public void setTtlFilter(SQLExpr ttlFilter) {
+        this.ttlFilter = ttlFilter;
+    }
+}
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsAlterTableRemoveTtlOptions.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsAlterTableRemoveTtlOptions.java
new file mode 100644
index 000000000..5c2fbb82d
--- /dev/null
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsAlterTableRemoveTtlOptions.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 1999-2017 Alibaba Group Holding Ltd.
+ *
+ * Licensed 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 com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement;
+
+import com.alibaba.polardbx.druid.sql.ast.SQLExpr;
+import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableItem;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
+
+/**
+ * @author chenghui.lch
+ */
+public class DrdsAlterTableRemoveTtlOptions extends MySqlObjectImpl implements SQLAlterTableItem {
+
+    public DrdsAlterTableRemoveTtlOptions() {
+    }
+
+    @Override
+    public void accept0(MySqlASTVisitor visitor) {
+        visitor.visit(this);
+        visitor.endVisit(this);
+    }
+}
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsBaselineStatement.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsBaselineStatement.java
index 2a190b8c4..75316f701 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsBaselineStatement.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsBaselineStatement.java
@@ -38,6 +38,8 @@ public class DrdsBaselineStatement extends MySqlStatementImpl implements SQLStat
 
     private SQLStatement subStatement;
 
+    private String targetSql;
+
     public void accept0(MySqlASTVisitor visitor) {
         visitor.visit(this);
         visitor.endVisit(this);
@@ -79,4 +81,12 @@ public void setSubStatement(SQLStatement subStatement) {
     public SqlType getSqlType() {
         return null;
     }
+
+    public String getTargetSql() {
+        return targetSql;
+    }
+
+    public void setTargetSql(String targetSql) {
+        this.targetSql = targetSql;
+    }
 }
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsCheckColumnarIndex.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsCheckColumnarIndex.java
index 4e2589d78..e03d8da91 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsCheckColumnarIndex.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsCheckColumnarIndex.java
@@ -22,12 +22,17 @@
 import com.alibaba.polardbx.druid.sql.ast.statement.SQLShowStatement;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class DrdsCheckColumnarIndex extends MySqlStatementImpl implements SQLShowStatement {
 
     private SQLName indexName = null;
     private SQLName tableName = null;
     private String extraCmd = null;
 
+    private List extras = null;
+
     public void accept0(MySqlASTVisitor visitor) {
         visitor.visit(this);
         visitor.endVisit(this);
@@ -57,4 +62,15 @@ public String getExtraCmd() {
     public void setExtraCmd(String extraCmd) {
         this.extraCmd = extraCmd;
     }
+
+    public List getExtras() {
+        return extras;
+    }
+
+    public void setExtra(long extra) {
+        if (null == extras) {
+            extras = new ArrayList<>();
+        }
+        extras.add(extra);
+    }
 }
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsCheckColumnarSnapshot.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsCheckColumnarSnapshot.java
new file mode 100644
index 000000000..67ba75fe3
--- /dev/null
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsCheckColumnarSnapshot.java
@@ -0,0 +1,25 @@
+package com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement;
+
+import com.alibaba.polardbx.druid.sql.ast.SQLName;
+import com.alibaba.polardbx.druid.sql.ast.statement.SQLShowStatement;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
+
+public class DrdsCheckColumnarSnapshot extends MySqlStatementImpl implements SQLShowStatement {
+
+    private SQLName tableName = null;
+
+    @Override
+    public void accept0(MySqlASTVisitor v) {
+        v.visit(this);
+        v.endVisit(this);
+    }
+
+    public SQLName getTableName() {
+        return tableName;
+    }
+
+    public void setTableName(SQLName tableName) {
+        tableName.setParent(this);
+        this.tableName = tableName;
+    }
+}
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsResumeRebalanceJob.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsResumeRebalanceJob.java
new file mode 100644
index 000000000..f886107b9
--- /dev/null
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsResumeRebalanceJob.java
@@ -0,0 +1,15 @@
+package com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement;
+
+import com.alibaba.polardbx.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
+
+/**
+ * @author chenyi
+ */
+public class DrdsResumeRebalanceJob extends DrdsGenericDDLJob {
+
+    @Override
+    public void accept0(MySqlASTVisitor visitor) {
+        visitor.visit(this);
+        visitor.endVisit(this);
+    }
+}
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsShowDdlEngineStatus.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsShowDdlEngineStatus.java
new file mode 100644
index 000000000..96a0f2abd
--- /dev/null
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/DrdsShowDdlEngineStatus.java
@@ -0,0 +1,79 @@
+package com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement;
+
+import com.alibaba.polardbx.druid.sql.ast.SQLExpr;
+import com.alibaba.polardbx.druid.sql.ast.SQLLimit;
+import com.alibaba.polardbx.druid.sql.ast.SQLName;
+import com.alibaba.polardbx.druid.sql.ast.SQLOrderBy;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
+
+/**
+ * Created by jinkun.taojinkun.
+ *
+ * @author jinkun.taojinkun
+ */
+public class DrdsShowDdlEngineStatus extends MySqlStatementImpl implements MySqlShowStatement {
+    private SQLOrderBy orderBy;
+    private SQLExpr where;
+    private SQLLimit limit;
+    private SQLName name;
+    private boolean full = false;
+
+    private boolean status = false;
+
+    public SQLLimit getLimit() {
+        return limit;
+    }
+
+    public void setLimit(SQLLimit limit) {
+        this.limit = limit;
+    }
+
+    public SQLOrderBy getOrderBy() {
+        return orderBy;
+    }
+
+    public void setOrderBy(SQLOrderBy orderBy) {
+        this.orderBy = orderBy;
+    }
+
+    public SQLExpr getWhere() {
+        return where;
+    }
+
+    public void setWhere(SQLExpr where) {
+        this.where = where;
+    }
+
+    public SQLName getName() {
+        return name;
+    }
+
+    public void setName(SQLName name) {
+        this.name = name;
+    }
+
+    public void accept0(MySqlASTVisitor visitor) {
+        if (visitor.visit(this)) {
+            acceptChild(visitor, where);
+            acceptChild(visitor, orderBy);
+            acceptChild(visitor, limit);
+        }
+        visitor.endVisit(this);
+    }
+
+    public boolean getStatus() {
+        return status;
+    }
+
+    public void setFull(boolean full) {
+        this.full = full;
+    }
+
+    public Boolean isFull() {
+        return full;
+    }
+
+    public void setStatus(boolean status) {
+        this.status = status;
+    }
+}
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableModifyColumn.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableModifyColumn.java
index 882974d65..9f77e8387 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableModifyColumn.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableModifyColumn.java
@@ -30,6 +30,9 @@ public class MySqlAlterTableModifyColumn extends MySqlObjectImpl implements SQLA
     private SQLName firstColumn;
     private SQLName afterColumn;
 
+    public MySqlAlterTableModifyColumn() {
+    }
+
     @Override
     public void accept0(MySqlASTVisitor visitor) {
         if (visitor.visit(this)) {
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java
index 2bf7d60cb..973fa6e61 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java
@@ -25,6 +25,7 @@
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLBinaryOpExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLCharExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLIdentifierExpr;
+import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveDefinitionExpr;
 import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterCharacter;
 import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableAddColumn;
 import com.alibaba.polardbx.druid.sql.ast.statement.SQLAlterTableAddIndex;
@@ -105,6 +106,62 @@ public void setEngine(String engineName) {
         }
     }
 
+    public SQLAssignItem getTtlDefinitionOption() {
+        SQLAssignItem ttlDefinitionOption = null;
+        for (int i = 0; i < tableOptions.size(); i++) {
+            SQLAssignItem assignItem = tableOptions.get(i);
+            SQLExpr val = assignItem.getValue();
+            if (val instanceof SQLTimeToLiveDefinitionExpr) {
+                ttlDefinitionOption = assignItem;
+                break;
+            }
+        }
+        return ttlDefinitionOption;
+    }
+
+    public void removeArchiveCciInfoForTtlDefinitionOptionIfNeed() {
+        SQLAssignItem ttlDefinitionOption = null;
+        for (int i = 0; i < tableOptions.size(); i++) {
+            SQLAssignItem assignItem = tableOptions.get(i);
+            SQLExpr val = assignItem.getValue();
+            if (val instanceof SQLTimeToLiveDefinitionExpr) {
+                ttlDefinitionOption = assignItem;
+                break;
+            }
+        }
+        if (ttlDefinitionOption == null) {
+            return;
+        }
+
+        SQLExpr ttlDefExprAst = ttlDefinitionOption.getValue();
+        SQLTimeToLiveDefinitionExpr ttlDefExpr = (SQLTimeToLiveDefinitionExpr) ttlDefExprAst;
+
+        SQLExpr arcSchemaExpr = ttlDefExpr.getArchiveTableSchemaExpr();
+        SQLExpr arcTblNameExpr = ttlDefExpr.getArchiveTableNameExpr();
+
+        ttlDefExpr.setTtlEnableExpr(null);
+        ttlDefExpr.setArchiveTableSchemaExpr(null);
+        ttlDefExpr.setArchiveTableNameExpr(null);
+
+        MySqlTableIndex targetArcCci = null;
+        int elementIdx = -1;
+        for (int i = 0; i < tableElementList.size(); i++) {
+            SQLTableElement element = tableElementList.get(i);
+            if (element instanceof MySqlTableIndex)  {
+                MySqlTableIndex idx = (MySqlTableIndex) element;
+                if (idx.isColumnar()) {
+                    targetArcCci = idx;
+                    elementIdx = i;
+                    break;
+                }
+            }
+        }
+        if (targetArcCci != null) {
+            tableElementList.remove(elementIdx);
+        }
+    }
+
+
     public List getHints() {
         return hints;
     }
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java
index 032aa717d..88e467395 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java
@@ -45,6 +45,9 @@
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLIntegerExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLListExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveDefinitionExpr;
+import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveExpr;
+import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveJobExpr;
 import com.alibaba.polardbx.druid.sql.ast.statement.SQLCheck;
 import com.alibaba.polardbx.druid.sql.ast.statement.SQLColumnConstraint;
 import com.alibaba.polardbx.druid.sql.ast.statement.SQLColumnDefinition;
@@ -229,6 +232,12 @@ public MySqlCreateTableStatement parseCreateTable(boolean acceptCreate) {
                                 this.exprParser.parseIndex(idx.getIndexDefinition());
                                 idx.setIndexType("FULLTEXT");
                                 idx.setParent(stmt);
+                                if (lexer.token() == Token.HINT) {
+                                    String execComment = lexer.stringVal();
+                                    idx.getIndexDefinition().getOptions().setExecComment(execComment);
+                                    lexer.nextToken();
+                                }
+
                                 stmt.getTableElementList().add(idx);
 
                                 if (lexer.token() == Token.RPAREN) {
@@ -245,6 +254,12 @@ public MySqlCreateTableStatement parseCreateTable(boolean acceptCreate) {
                                 this.exprParser.parseIndex(idx.getIndexDefinition());
                                 idx.setIndexType("FULLTEXT");
                                 idx.setParent(stmt);
+                                if (lexer.token() == Token.HINT) {
+                                    String execComment = lexer.stringVal();
+                                    idx.getIndexDefinition().getOptions().setExecComment(execComment);
+                                    lexer.nextToken();
+                                }
+
                                 stmt.getTableElementList().add(idx);
 
                                 if (lexer.token() == Token.RPAREN) {
@@ -288,11 +303,13 @@ public MySqlCreateTableStatement parseCreateTable(boolean acceptCreate) {
                             this.exprParser.parseIndex(fulltextKey.getIndexDefinition());
                             fulltextKey.setIndexType("FULLTEXT");
                             fulltextKey.setParent(stmt);
-                            stmt.getTableElementList().add(fulltextKey);
 
-                            while (lexer.token() == Token.HINT) {
+                            if (lexer.token() == Token.HINT) {
+                                String execComment = lexer.stringVal();
+                                fulltextKey.getIndexDefinition().getOptions().setExecComment(execComment);
                                 lexer.nextToken();
                             }
+                            stmt.getTableElementList().add(fulltextKey);
 
                             if (lexer.token() == Token.RPAREN) {
                                 break;
@@ -305,6 +322,12 @@ public MySqlCreateTableStatement parseCreateTable(boolean acceptCreate) {
                             this.exprParser.parseIndex(idx.getIndexDefinition());
                             idx.setIndexType("FULLTEXT");
                             idx.setParent(stmt);
+
+                            if (lexer.token() == Token.HINT) {
+                                String execComment = lexer.stringVal();
+                                idx.getIndexDefinition().getOptions().setExecComment(execComment);
+                                lexer.nextToken();
+                            }
                             stmt.getTableElementList().add(idx);
 
                             if (lexer.token() == Token.RPAREN) {
@@ -1015,6 +1038,34 @@ public MySqlCreateTableStatement parseCreateTable(boolean acceptCreate) {
                 continue;
             }
 
+            if (lexer.identifierEquals(FnvHash.Constants.TTL)) {
+                lexer.nextToken();
+                accept(Token.EQ);
+                stmt.addOption("TTL", parseTimeToLiveDefinitionExpr(exprParser, lexer));
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.TTL_ENABLE)) {
+                lexer.nextToken();
+                accept(Token.EQ);
+                stmt.addOption("TTL_ENABLE", exprParser.charExpr());
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.TTL_EXPR)) {
+                lexer.nextToken();
+                accept(Token.EQ);
+                stmt.addOption("TTL_EXPR", parseTimeToLiveExpr(this.exprParser, this.lexer));
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.TTL_JOB)) {
+                lexer.nextToken();
+                accept(Token.EQ);
+                stmt.addOption("TTL_JOB", parseTimeToLiveJobExpr(this.exprParser, this.lexer));
+                continue;
+            }
+
             if (lexer.token() == Token.PARTITION) {
                 SQLPartitionBy partitionClause = parsePartitionBy();
                 stmt.setPartitioning(partitionClause);
@@ -2170,4 +2221,182 @@ private boolean checkNameValid(MySqlCreateTableStatement stmt, String checkName)
 
         return true;
     }
+
+    public static SQLExpr parseTimeToLiveDefinitionExpr(SQLExprParser exprParser, Lexer lexer) {
+
+        if (lexer.identifierEquals(FnvHash.Constants.TTL_DEFINITION)) {
+            lexer.nextToken();
+        }
+        SQLTimeToLiveDefinitionExpr sqlTimeToLiveDefinitionExpr = new SQLTimeToLiveDefinitionExpr();
+        boolean findOptions = false;
+        for (; ; ) {
+
+            findOptions = false;
+
+            if (lexer.token() == Token.EOF) {
+                break;
+            }
+
+            if (lexer.token() == Token.SEMI) {
+                break;
+            }
+
+            if (lexer.token() == Token.LPAREN) {
+                lexer.nextToken();
+                continue;
+            }
+
+            if (lexer.token() == Token.COMMA) {
+                lexer.nextToken();
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.TTL_ENABLE)) {
+                lexer.nextToken();
+                exprParser.accept(Token.EQ);
+                SQLExpr ttlEnableExpr = exprParser.charExpr();
+                sqlTimeToLiveDefinitionExpr.setTtlEnableExpr(ttlEnableExpr);
+                findOptions = true;
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.TTL_EXPR)) {
+                lexer.nextToken();
+                exprParser.accept(Token.EQ);
+                SQLExpr ttlExpr = parseTimeToLiveExpr(exprParser, lexer);
+                sqlTimeToLiveDefinitionExpr.setTtlExpr(ttlExpr);
+                findOptions = true;
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.TTL_JOB)) {
+                lexer.nextToken();
+                exprParser.accept(Token.EQ);
+                SQLExpr ttlJobExpr = parseTimeToLiveJobExpr(exprParser, lexer);
+                sqlTimeToLiveDefinitionExpr.setTtlJobExpr(ttlJobExpr);
+                findOptions = true;
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.TTL_FILTER)) {
+                lexer.nextToken();
+                exprParser.accept(Token.EQ);
+                SQLExpr ttlFilterExpr = exprParser.charExpr();
+                sqlTimeToLiveDefinitionExpr.setTtlFilterExpr(ttlFilterExpr);
+                findOptions = true;
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE_TYPE)) {
+                lexer.nextToken();
+                exprParser.accept(Token.EQ);
+                SQLExpr archiveTypeExpr = exprParser.charExpr();
+                sqlTimeToLiveDefinitionExpr.setArchiveTypeExpr(archiveTypeExpr);
+                findOptions = true;
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE_TABLE_SCHEMA)) {
+                lexer.nextToken();
+                exprParser.accept(Token.EQ);
+                SQLExpr archiveTableSchemaExpr = exprParser.charExpr();
+                sqlTimeToLiveDefinitionExpr.setArchiveTableSchemaExpr(archiveTableSchemaExpr);
+                findOptions = true;
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE_TABLE_NAME)) {
+                lexer.nextToken();
+                exprParser.accept(Token.EQ);
+                SQLExpr archiveTableNameExpr = exprParser.charExpr();
+                sqlTimeToLiveDefinitionExpr.setArchiveTableNameExpr(archiveTableNameExpr);
+                findOptions = true;
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE_TABLE_PRE_ALLOCATE)) {
+                lexer.nextToken();
+                exprParser.accept(Token.EQ);
+                SQLExpr arcPreAllocateExpr = exprParser.integerExpr();
+                sqlTimeToLiveDefinitionExpr.setArchiveTablePreAllocateExpr(arcPreAllocateExpr);
+                findOptions = true;
+                continue;
+            }
+
+            if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE_TABLE_POST_ALLOCATE)) {
+                lexer.nextToken();
+                exprParser.accept(Token.EQ);
+                SQLExpr arcPostAllocateExpr = exprParser.integerExpr();
+                sqlTimeToLiveDefinitionExpr.setArchiveTablePostAllocateExpr(arcPostAllocateExpr);
+                findOptions = true;
+                continue;
+            }
+
+            if (lexer.token() == Token.RPAREN) {
+                lexer.nextToken();
+                break;
+            }
+
+            if (!findOptions) {
+                throw new ParserException("syntax error " + lexer.info());
+            }
+        }
+        return sqlTimeToLiveDefinitionExpr;
+    }
+
+    public static SQLTimeToLiveJobExpr parseTimeToLiveJobExpr(SQLExprParser exprParser, Lexer lexer) {
+
+        SQLExpr cron = null;
+        SQLExpr timezone = null;
+        if (lexer.identifierEquals("CRON")) {
+            lexer.nextToken();
+            cron = exprParser.expr();
+        } else {
+            throw new ParserException("syntax error, 'CRON' must be after the second 'TTL_JOB' ");
+        }
+
+        if (lexer.identifierEquals("TIMEZONE")) {
+            lexer.nextToken();
+            timezone = exprParser.expr();
+        } else {
+            throw new ParserException("syntax error, 'TIMEZONE' must be after the second 'CRON' ");
+        }
+
+        SQLTimeToLiveJobExpr timeToLiveJobExpr = new SQLTimeToLiveJobExpr();
+        timeToLiveJobExpr.setCron(cron);
+        timeToLiveJobExpr.setTimezone(timezone);
+        return timeToLiveJobExpr;
+    }
+
+    public static SQLTimeToLiveExpr parseTimeToLiveExpr(SQLExprParser exprParser, Lexer lexer) {
+        SQLExpr ttlColumn = exprParser.expr();
+        if (lexer.identifierEquals("EXPIRE")) {
+            lexer.nextToken();
+        } else {
+            exprParser.setErrorEndPos(lexer.pos());
+            throw new ParserException("syntax error, 'expire' must be after the column identifier");
+        }
+        if (lexer.identifierEquals("AFTER")) {
+            lexer.nextToken();
+        } else {
+            exprParser.setErrorEndPos(lexer.pos());
+            throw new ParserException("syntax error, 'after' must be after 'expire' ");
+        }
+        SQLExpr expireInterval = exprParser.expr();
+        SQLExpr expireIntervalUnit = exprParser.expr();
+        SQLExpr ttlTimezone = null;
+        if (lexer.identifierEquals("TIMEZONE")) {
+            lexer.nextToken();
+            ttlTimezone = exprParser.expr();
+        } else {
+            throw new ParserException("syntax error, 'timezone' must be after the unit identifier");
+        }
+
+        SQLTimeToLiveExpr timeToLiveExpr = new SQLTimeToLiveExpr();
+        timeToLiveExpr.setColumn(ttlColumn);
+        timeToLiveExpr.setExpireAfter(expireInterval);
+        timeToLiveExpr.setUnit(expireIntervalUnit);
+        timeToLiveExpr.setTimezone(ttlTimezone);
+        return timeToLiveExpr;
+    }
 }
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlExprParser.java
index 772c89fb2..304c96e12 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlExprParser.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlExprParser.java
@@ -79,6 +79,7 @@
 import java.sql.Types;
 import java.util.Arrays;
 import java.util.List;
+import java.util.regex.Pattern;
 
 public class MySqlExprParser extends SQLExprParser {
     public final static String[] AGGREGATE_FUNCTIONS;
@@ -842,6 +843,10 @@ public final SQLExpr primaryRest(SQLExpr expr) {
                 return userNameRest(expr);
             } else if ("@`%`".equals(variant)) {
                 return userNameRest(expr);
+            } else if (Pattern.matches("@`(.*)`", variant)) {
+                /* MySqlLexer.java parser `root`@`127.0.0.1` to `root` and @`127.0.0.1` respectively,
+                    however @`127.0.0.1` isn't identified here before, therefore we use a Regex to handle it */
+                return userNameRest(expr);
             } else {
                 throw new ParserException("syntax error. " + lexer.info());
             }
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlSelectParser.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlSelectParser.java
index 391a2cae7..6d7973ea0 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlSelectParser.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlSelectParser.java
@@ -27,6 +27,7 @@
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLIdentifierExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLIntegerExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLListExpr;
+import com.alibaba.polardbx.druid.sql.ast.expr.SQLPropertyExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLSizeExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimestampExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLVariantRefExpr;
@@ -912,7 +913,20 @@ private void parseIndexHint(MySqlIndexHintImpl hint) {
         while (lexer.token() != Token.RPAREN && lexer.token() != Token.EOF) {
             if (lexer.token() == Token.PRIMARY) {
                 lexer.nextToken();
-                hint.getIndexList().add(new SQLIdentifierExpr("PRIMARY"));
+                // support force index(primary.local_index)
+                if (lexer.token() == Token.DOT) {
+                    lexer.nextToken();
+
+                    if (lexer.token() == Token.PRIMARY) {
+                        hint.getIndexList().add(new SQLPropertyExpr("PRIMARY", "PRIMARY"));
+                        lexer.nextToken();
+                    } else {
+                        SQLName name = this.exprParser.name();
+                        hint.getIndexList().add(new SQLPropertyExpr("PRIMARY", name.getSimpleName()));
+                    }
+                } else {
+                    hint.getIndexList().add(new SQLIdentifierExpr("PRIMARY"));
+                }
             } else {
                 if (lexer.token() == Token.LITERAL_CHARS) {
                     // Use literal char is not support in MySQL.
diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlStatementParser.java
index ee6802139..455e4933c 100644
--- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlStatementParser.java
+++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/parser/MySqlStatementParser.java
@@ -51,9 +51,11 @@
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLValuableExpr;
 import com.alibaba.polardbx.druid.sql.ast.expr.SQLVariantRefExpr;
 import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableAllocateLocalPartition;
+import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableCleanupExpiredData;
 import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableExpireLocalPartition;
 import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableGroupSetLocality;
 import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableGroupSetPartitionsLocality;
+import com.alibaba.polardbx.druid.sql.ast.statement.DrdsArchivePartition;
 import com.alibaba.polardbx.druid.sql.ast.statement.DrdsExtractHotKey;
 import com.alibaba.polardbx.druid.sql.ast.statement.DrdsInspectIndexStatement;
 import com.alibaba.polardbx.druid.sql.ast.statement.DrdsMergePartition;
@@ -228,8 +230,10 @@
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterFileStorageStatement;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableAsOfTimeStamp;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableBroadcast;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableModifyTtlOptions;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTablePartition;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTablePurgeBeforeTimeStamp;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableRemoveTtlOptions;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableSingle;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsBaselineStatement;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCancelDDLJob;
@@ -238,6 +242,7 @@
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsChangeRuleVersionStatement;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarIndex;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarPartition;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarSnapshot;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckGlobalIndex;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclRulesStatement;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclTriggersStatement;
@@ -266,7 +271,10 @@
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRecoverDDLJob;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRefreshLocalRulesStatement;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRemoveDDLJob;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsResumeRebalanceJob;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRollbackDDLJob;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowDdlEngineStatus;
+import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsTerminateRebalanceJob;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclRuleStatement;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclTriggerStatement;
 import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowChangeSet;
@@ -496,6 +504,7 @@
 import static com.alibaba.polardbx.druid.sql.parser.Token.JAVA;
 import static com.alibaba.polardbx.druid.sql.parser.Token.LITERAL_CHARS;
 import static com.alibaba.polardbx.druid.sql.parser.Token.LPAREN;
+import static com.alibaba.polardbx.druid.sql.parser.Token.MODE;
 import static com.alibaba.polardbx.druid.sql.parser.Token.OF;
 import static com.alibaba.polardbx.druid.sql.parser.Token.ON;
 import static com.alibaba.polardbx.druid.sql.parser.Token.PARTITION;
@@ -1516,6 +1525,13 @@ public SQLCreateIndexStatement parseCreateIndex(boolean acceptCreate) {
         SQLIndexDefinition sqlIndexDefinition = stmt.getIndexDefinition();
 
         this.exprParser.parseIndex(sqlIndexDefinition, true);
+
+        if (lexer.token() == Token.HINT) {
+            String execComment = lexer.stringVal();
+            sqlIndexDefinition.getOptions().setExecComment(execComment);
+            lexer.nextToken();
+        }
+
         parseAsyncOption(stmt);
         return stmt;
     }
@@ -2762,6 +2778,7 @@ public boolean parseStatementListDialect(List statementList) {
                 if (lexer.token() == Token.HINT) {
                     stmt.setHeadHints(this.exprParser.parseHints());
                 }
+                stmt.setTargetSql(lexer.token().toString() + " " + lexer.text.substring(lexer.pos()));
 
                 MySqlSelectParser selectParser = createSQLSelectParser();
                 stmt.setSelect(selectParser.select());
@@ -2772,6 +2789,7 @@ public boolean parseStatementListDialect(List statementList) {
                 if (lexer.token() == Token.HINT) {
                     stmt.setHeadHints(this.exprParser.parseHints());
                 }
+                stmt.setTargetSql(lexer.token().toString() + " " + lexer.text.substring(lexer.pos()));
                 stmt.setSubStatement(parseStatement());
             } else {
                 // Parse id list.
@@ -3154,6 +3172,11 @@ public boolean parseStatementListDialect(List statementList) {
                         // Extra command.
                         checkColumnarIndex.setExtraCmd(lexer.stringVal());
                         lexer.nextToken();
+
+                        while (lexer.token() != Token.EOF && lexer.token() != Token.SEMI) {
+                            checkColumnarIndex.setExtra(lexer.integerValue().longValue());
+                            lexer.nextToken();
+                        }
                     }
 
                     statementList.add(checkColumnarIndex);
@@ -3162,6 +3185,11 @@ public boolean parseStatementListDialect(List statementList) {
                     DrdsCheckColumnarPartition checkColumnarPartition = new DrdsCheckColumnarPartition();
                     checkColumnarPartition.setTableName(exprParser.name());
                     statementList.add(checkColumnarPartition);
+                } else if (lexer.token() == Token.SNAPSHOT || lexer.identifierEquals("SNAPSHOT")) {
+                    lexer.nextToken();;
+                    DrdsCheckColumnarSnapshot checkColumnarSnapshot = new DrdsCheckColumnarSnapshot();
+                    checkColumnarSnapshot.setTableName(exprParser.name());
+                    statementList.add(checkColumnarSnapshot);
                 } else {
                     setErrorEndPos(lexer.pos());
                     printError(lexer.token());
@@ -3178,14 +3206,22 @@ public boolean parseStatementListDialect(List statementList) {
                     lexer.nextToken();
                 }
 
-                if (lexer.token() == FOR) {
+                if (lexer.identifierEquals("CHANNEL")) {
                     lexer.nextToken();
-                    acceptIdentifier("CHANNEL");
+                    accept(EQ);
                     SQLName channel = this.exprParser.name();
+                    SQLName mode = null;
+                    if (lexer.identifierEquals("MODE")) {
+                        lexer.nextToken();
+                        accept(EQ);
+                        mode = this.exprParser.name();
+                    }
+
                     SQLStartReplicaCheckTableStatement stmt = new SQLStartReplicaCheckTableStatement();
                     stmt.setDbName(dbName);
                     stmt.setTableName(tbName);
                     stmt.setChannel(channel);
+                    stmt.setMode(mode);
                     statementList.add(stmt);
                 } else if (lexer.identifierEquals("PAUSE")) {
                     lexer.nextToken();
@@ -3227,10 +3263,17 @@ public boolean parseStatementListDialect(List statementList) {
                         statementList.add(stmt);
                     }
                 } else {
-                    // 如果check replica table不带for channel,则视为对""的fsm操作
+                    // 如果check replica table不带channel,则视为对""的fsm操作
+                    SQLName mode = null;
+                    if (lexer.identifierEquals("MODE")) {
+                        lexer.nextToken();
+                        accept(EQ);
+                        mode = this.exprParser.name();
+                    }
                     SQLStartReplicaCheckTableStatement stmt = new SQLStartReplicaCheckTableStatement();
                     stmt.setDbName(dbName);
                     stmt.setTableName(tbName);
+                    stmt.setMode(mode);
                     statementList.add(stmt);
                 }
             }
@@ -4099,8 +4142,10 @@ private MySqlExplainStatement parseExplain(MySqlExplainStatement explain) {
             explain.setType("COST_TRACE");
         } else if (lexer.identifierEquals("PIPELINE")) {
             lexer.nextToken();
-            ;
             explain.setType("PIPELINE");
+        } else if (lexer.identifierEquals("SNAPSHOT")) {
+            lexer.nextToken();
+            explain.setType("SNAPSHOT");
         }
 
         if (lexer.token() == Token.HINT) {
@@ -5758,6 +5803,16 @@ public SQLStatement parseShow() {
                 }
                 return drdsShowPhysicalDdl;
             }
+
+            if (lexer.identifierEquals("ENGINE")) {
+                DrdsShowDdlEngineStatus drdsShowDdlEngineStatus = new DrdsShowDdlEngineStatus();
+                lexer.nextToken();
+                if (lexer.identifierEquals("STATUS")) {
+                    lexer.nextToken();
+                    return drdsShowDdlEngineStatus;
+                }
+                return drdsShowDdlEngineStatus;
+            }
             if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && !lexer.identifierEquals("STATUS")) {
                 // SHOW [FULL] DDL [  [ ,  ] ... ].
                 DrdsShowDDLJobs showDDLJobs = new DrdsShowDDLJobs();
@@ -6719,6 +6774,20 @@ public SQLStatement parseTerminate() {
         throw new ParserException("Only support terminate rebalance .");
     }
 
+    public SQLStatement parseResume() {
+        acceptIdentifier("RESUME");
+
+        if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals("REBALANCE")) {
+            // RESUME REBALANCE { ALL |  [, ] ... }
+            lexer.nextToken();
+            DrdsResumeRebalanceJob stmt = new DrdsResumeRebalanceJob();
+            parseGenericDdlCommand(stmt);
+            return stmt;
+        }
+
+        throw new ParserException("Only support terminate rebalance .");
+    }
+
     public SQLStatement parseCommit() {
         acceptIdentifier("COMMIT");
 
@@ -8107,6 +8176,27 @@ protected SQLAlterTableTruncatePartition parseTruncatePartition() {
         return item;
     }
 
+    protected SQLAlterTableOptimizePartition parseOptimizePartition() {
+        SQLAlterTableOptimizePartition item = new SQLAlterTableOptimizePartition();
+
+        lexer.nextToken();
+
+        if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION)) {
+            item.setSubPartition(true);
+            lexer.nextToken();
+        } else {
+            accept(Token.PARTITION);
+        }
+
+        if (lexer.token() == Token.ALL) {
+            item.getPartitions().add(new SQLIdentifierExpr("ALL"));
+            lexer.nextToken();
+        } else {
+            this.exprParser.names(item.getPartitions(), item);
+        }
+        return item;
+    }
+
     protected SQLAlterTableAddPartition parseAddPartition() {
         accept(Token.PARTITION);
 
@@ -8207,6 +8297,137 @@ protected List parseModifyPartitionValues()
         return alterItems;
     }
 
+    protected DrdsAlterTableModifyTtlOptions parseModifyTtlOptions() {
+
+        DrdsAlterTableModifyTtlOptions modifyTtlOptions = new DrdsAlterTableModifyTtlOptions();
+
+        /**
+         * 
+         * MODIFY TTL
+         * SET
+         *  TTL_ENABLE = 'ON'
+         *  TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00'
+         *  TTL_JOB = CRON 'xxx' TIMEZONE '+08:00';
+         * 
+ */ + + // skip lexer 'TTL' + lexer.nextToken(); + // make sure next lexer must be set + if (lexer.token() == Token.SET) { + lexer.nextToken(); + } + + for (; ; ) { + boolean findOptions = false; + + if (lexer.token() == Token.EOF) { + break; + } + + if (lexer.token() == Token.SEMI) { + break; + } + + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + + if (lexer.identifierEquals(FnvHash.Constants.TTL_ENABLE)) { + lexer.nextToken(); + exprParser.accept(Token.EQ); + SQLExpr ttlEnableExpr = exprParser.charExpr(); + modifyTtlOptions.setTtlEnable(ttlEnableExpr); + findOptions = true; + continue; + } + + if (lexer.identifierEquals(FnvHash.Constants.TTL_EXPR)) { + lexer.nextToken(); + exprParser.accept(Token.EQ); + SQLExpr ttlExpr = MySqlCreateTableParser.parseTimeToLiveExpr(exprParser, lexer); + modifyTtlOptions.setTtlExpr(ttlExpr); + findOptions = true; + continue; + } + + if (lexer.identifierEquals(FnvHash.Constants.TTL_JOB)) { + lexer.nextToken(); + exprParser.accept(Token.EQ); + SQLExpr ttlJobExpr = MySqlCreateTableParser.parseTimeToLiveJobExpr(exprParser, lexer); + modifyTtlOptions.setTtlJob(ttlJobExpr); + findOptions = true; + continue; + } + + if (lexer.identifierEquals(FnvHash.Constants.TTL_FILTER)) { + lexer.nextToken(); + exprParser.accept(Token.EQ); + SQLExpr ttlFilter = exprParser.charExpr(); + modifyTtlOptions.setTtlFilter(ttlFilter); + findOptions = true; + continue; + } + + if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE_TYPE)) { + lexer.nextToken(); + exprParser.accept(Token.EQ); + SQLExpr archiveTypeExpr = exprParser.charExpr(); + modifyTtlOptions.setArchiveKind(archiveTypeExpr); + findOptions = true; + continue; + } + + if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE_TABLE_SCHEMA)) { + lexer.nextToken(); + exprParser.accept(Token.EQ); + SQLExpr archiveTableSchemaExpr = exprParser.charExpr(); + modifyTtlOptions.setArchiveTableSchema(archiveTableSchemaExpr); + findOptions = true; + continue; + } + + if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE_TABLE_NAME)) { + lexer.nextToken(); + exprParser.accept(Token.EQ); + SQLExpr archiveTableNameExpr = exprParser.charExpr(); + modifyTtlOptions.setArchiveTableName(archiveTableNameExpr); + findOptions = true; + continue; + } + + if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE_TABLE_PRE_ALLOCATE)) { + lexer.nextToken(); + exprParser.accept(Token.EQ); + SQLExpr arcPreAllocateExpr = exprParser.integerExpr(); + modifyTtlOptions.setArcPreAllocate(arcPreAllocateExpr); + findOptions = true; + continue; + } + + if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE_TABLE_POST_ALLOCATE)) { + lexer.nextToken(); + exprParser.accept(Token.EQ); + SQLExpr arcPostAllocateExpr = exprParser.integerExpr(); + modifyTtlOptions.setArcPostAllocate(arcPostAllocateExpr); + findOptions = true; + continue; + } + + if (lexer.token() == Token.RPAREN) { + lexer.nextToken(); + break; + } + + if (!findOptions) { + throw new ParserException("syntax error " + lexer.info()); + } + } + + return modifyTtlOptions; + } + // parse MODIFY SUBPARTITION [(] sub_part_name ADD|DROP VALUES(),sub_part_name ADD|DROP VALUES(), ... [)] protected List parseModifySubPartitionValues(SQLName partName) { // skip lexer 'SUBPARTITION' @@ -8365,6 +8586,31 @@ protected DrdsMergePartition parseMergePartition() { return item; } + protected DrdsArchivePartition parseArchivePartition() { + DrdsArchivePartition item = new DrdsArchivePartition(); + lexer.nextToken(); + + if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITIONS)) { + item.setSubPartitionsArchive(true); + lexer.nextToken(); + } else { + acceptIdentifier("PARTITIONS"); + } + + List partNames = new ArrayList<>(); + while (true) { + SQLName partitionName = this.exprParser.name(); + partNames.add(partitionName); + if (lexer.token() != Token.COMMA) { + break; + } + accept(Token.COMMA); + } + item.setPartitions(partNames); + + return item; + } + protected DrdsMovePartition parseMovePartition() { DrdsMovePartition item = new DrdsMovePartition(); lexer.nextToken(); @@ -9508,6 +9754,11 @@ private boolean parseAlterSpecification(SQLAlterTableStatement stmt) { // Index. SQLAlterTableAddIndex item = new SQLAlterTableAddIndex(); this.exprParser.parseIndex(item.getIndexDefinition()); + if (lexer.token() == Token.HINT) { + String execComment = lexer.stringVal(); + item.getIndexDefinition().getOptions().setExecComment(execComment); + lexer.nextToken(); + } stmt.addItem(item); } else if (lexer.identifierEquals(FnvHash.Constants.EXTPARTITION)) { // Caution: Not in MySql documents. @@ -9771,6 +10022,19 @@ private boolean parseAlterSpecification(SQLAlterTableStatement stmt) { stmt.addItem(items.get(i)); } + return true; + } else if (lexer.identifierEquals("TTL")) { + /** + *
+                     * MODIFY TTL
+                     * SET
+                     *  TTL_ENABLE = 'ON'
+                     *  TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00'
+                     *  TTL_JOB = CRON 'xxx' TIMEZONE '+08:00';
+                     * 
+ */ + DrdsAlterTableModifyTtlOptions modifyTtlOptions = parseModifyTtlOptions(); + stmt.addItem(modifyTtlOptions); return true; } else { // MODIFY [COLUMN] col_name column_definition [FIRST | AFTER col_name] @@ -9895,6 +10159,13 @@ private boolean parseAlterSpecification(SQLAlterTableStatement stmt) { this.exprParser.names(item.getPartitions(), item); stmt.addItem(item); return true; + } else if (lexer.identifierEquals("CLEANUP")) { + lexer.nextToken(); + acceptIdentifier("EXPIRED"); + acceptIdentifier("DATA"); + DrdsAlterTableCleanupExpiredData item = new DrdsAlterTableCleanupExpiredData(); + stmt.addItem(item); + return true; } else if (lexer.identifierEquals("REORGANIZE")) { // REORGANIZE PARTITION partition_names INTO (partition_definitions) SQLAlterTableReorgPartition item = parseReorgPartition(); @@ -9964,9 +10235,20 @@ private boolean parseAlterSpecification(SQLAlterTableStatement stmt) { acceptIdentifier("PARTITIONING"); stmt.setRemoveLocalPatiting(true); return true; + } else if (lexer.identifierEquals("TTL")) { + /** + *
+                     * REMOVE TTL
+                     * 
+ */ + lexer.nextToken(); + DrdsAlterTableRemoveTtlOptions removeTtlOptions = new DrdsAlterTableRemoveTtlOptions(); + stmt.addItem(removeTtlOptions); + return true; } acceptIdentifier("PARTITIONING"); stmt.setRemovePatiting(true); + return true; } else if (lexer.identifierEquals("UPGRADE")) { // UPGRADE PARTITIONING lexer.nextToken(); @@ -10369,15 +10651,18 @@ else if (lexer.identifierEquals(FnvHash.Constants.DBPARTITION)) { case OPTIMIZE: { // OPTIMIZE PARTITION {partition_names | ALL} - lexer.nextToken(); - accept(Token.PARTITION); - SQLAlterTableOptimizePartition item = new SQLAlterTableOptimizePartition(); - if (lexer.token() == Token.ALL) { - lexer.nextToken(); - item.getPartitions().add(new SQLIdentifierExpr("ALL")); - } else { - this.exprParser.names(item.getPartitions(), item); - } + SQLAlterTableOptimizePartition item = parseOptimizePartition(); + +// lexer.nextToken(); +// accept(Token.PARTITION); +// SQLAlterTableOptimizePartition item = new SQLAlterTableOptimizePartition(); +// if (lexer.token() == Token.ALL) { +// lexer.nextToken(); +// item.getPartitions().add(new SQLIdentifierExpr("ALL")); +// } else { +// this.exprParser.names(item.getPartitions(), item); +// } + stmt.addItem(item); return true; } @@ -10544,6 +10829,11 @@ protected SQLStatement parseAlterTable(boolean ignore, boolean online, boolean o stmt.setLocalPartition(localPartitionClause); } + if (lexer.identifierEquals("ARCHIVE")) { + DrdsArchivePartition archivePartition = parseArchivePartition(); + stmt.setDrdsArchivePartition(archivePartition); + } + // partition_options if (Token.PARTITION == lexer.token()) { Lexer.SavePoint mark = lexer.mark(); @@ -10580,7 +10870,7 @@ protected SQLStatement parseAlterTable(boolean ignore, boolean online, boolean o } } - if (stmt.getItems().size() >= 1 || (stmt.getItems().size() == 0 && stmt.getPartition() != null)) { + if (stmt.getItems().size() >= 1 || (stmt.getItems().size() == 0 && stmt.getPartition() != null) || stmt.isRemovePatiting()) { SQLAlterTableItem sqlAlterTableItem = stmt.getItems().size() >= 1 ? stmt.getItems().get(0) : null; boolean partitionReorg = sqlAlterTableItem instanceof DrdsSplitPartition @@ -10599,7 +10889,11 @@ protected SQLStatement parseAlterTable(boolean ignore, boolean online, boolean o || sqlAlterTableItem instanceof SQLAlterTableDropPartition || sqlAlterTableItem instanceof SQLAlterTableDropSubpartition || sqlAlterTableItem instanceof MySqlAlterTableModifyColumn - || stmt.getPartition() != null; + || stmt.getPartition() != null + || stmt.isRemovePatiting(); + if (!partitionReorg && stmt.getItems().size() > 1) { + partitionReorg = stmt.getItems().stream().anyMatch(o -> o instanceof MySqlAlterTableModifyColumn); + } if (partitionReorg) { if (lexer.token() == Token.WITH) { lexer.nextToken(); @@ -10731,12 +11025,14 @@ protected SQLStatement parseAlterIndex() { || lexer.identifierEquals(FnvHash.Constants.SET) || lexer.identifierEquals(FnvHash.Constants.DROP) || lexer.identifierEquals(FnvHash.Constants.TRUNCATE) + || lexer.identifierEquals(FnvHash.Constants.OPTIMIZER) || (opName.equalsIgnoreCase("SPLIT") || opName.equalsIgnoreCase("MERGE") || opName.equalsIgnoreCase("MOVE") || opName.equalsIgnoreCase("ADD") || opName.equalsIgnoreCase("MODIFY") || opName.equalsIgnoreCase("REORGANIZE") || opName.equalsIgnoreCase("RENAME") || opName.equalsIgnoreCase("SET") || opName.equalsIgnoreCase("EXTRACT") - || opName.equalsIgnoreCase("DROP") || opName.equalsIgnoreCase("TRUNCATE") + || opName.equalsIgnoreCase("DROP") || opName.equalsIgnoreCase("TRUNCATE") || opName.equalsIgnoreCase( + "OPTIMIZE") ) ) { diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java index 41b090dc2..f21be15c4 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java @@ -16,7 +16,9 @@ package com.alibaba.polardbx.druid.sql.dialect.mysql.visitor; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableAllocateLocalPartition; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableCleanupExpiredData; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableExpireLocalPartition; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsArchivePartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsExtractHotKey; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsInspectIndexStatement; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsMergePartition; @@ -68,6 +70,7 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsChangeRuleVersionStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarPartition; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarSnapshot; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckGlobalIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclRulesStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclTriggersStatement; @@ -107,8 +110,11 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRefreshLocalRulesStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRefreshTopology; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRemoveDDLJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsResumeRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRevokeSecurityLabelStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRollbackDDLJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowDdlEngineStatus; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsTerminateRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclRuleStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclTriggerStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowChangeSet; @@ -371,6 +377,10 @@ public interface MySqlASTVisitor extends SQLASTVisitor { boolean visit(DrdsShowDDLJobs x); + void endVisit(DrdsShowDdlEngineStatus x); + + boolean visit(DrdsShowDdlEngineStatus x); + void endVisit(DrdsShowDDLResults x); boolean visit(DrdsShowDDLResults x); @@ -427,6 +437,10 @@ public interface MySqlASTVisitor extends SQLASTVisitor { boolean visit(DrdsTerminateRebalanceJob x); + void endVisit(DrdsResumeRebalanceJob x); + + boolean visit(DrdsResumeRebalanceJob x); + void endVisit(DrdsSkipRebalanceSubjob x); boolean visit(DrdsSkipRebalanceSubjob x); @@ -481,6 +495,10 @@ public interface MySqlASTVisitor extends SQLASTVisitor { void endVisit(DrdsCheckColumnarIndex x); + boolean visit(DrdsCheckColumnarSnapshot x); + + void endVisit(DrdsCheckColumnarSnapshot x); + boolean visit(DrdsCheckColumnarIndex x); void endVisit(DrdsCreateCclRuleStatement x); @@ -1307,6 +1325,10 @@ public interface MySqlASTVisitor extends SQLASTVisitor { void endVisit(DrdsMovePartition x); + boolean visit(DrdsArchivePartition x); + + void endVisit(DrdsArchivePartition x); + boolean visit(DrdsExtractHotKey x); void endVisit(DrdsExtractHotKey x); @@ -1331,6 +1353,10 @@ public interface MySqlASTVisitor extends SQLASTVisitor { void endVisit(DrdsAlterTableExpireLocalPartition x); + boolean visit(DrdsAlterTableCleanupExpiredData x); + + void endVisit(DrdsAlterTableCleanupExpiredData x); + boolean visit(DrdsDropFileStorageStatement x); void endVisit(DrdsDropFileStorageStatement x); diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java index b5a1eeec9..4f388211b 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.druid.sql.ast.expr.SQLIntervalExpr; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableAllocateLocalPartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableExpireLocalPartition; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsArchivePartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsExtractHotKey; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsInspectIndexStatement; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsMergePartition; @@ -66,6 +67,7 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsChangeRuleVersionStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarPartition; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarSnapshot; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckGlobalIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclRulesStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclTriggersStatement; @@ -100,7 +102,10 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRefreshLocalRulesStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRefreshTopology; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRemoveDDLJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsResumeRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRollbackDDLJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowDdlEngineStatus; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsTerminateRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclRuleStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclTriggerStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowChangeSet; @@ -460,6 +465,16 @@ public void endVisit(DrdsShowDDLJobs x) { } + @Override + public boolean visit(DrdsShowDdlEngineStatus x) { + return true; + } + + @Override + public void endVisit(DrdsShowDdlEngineStatus x) { + + } + @Override public boolean visit(DrdsShowDDLJobs x) { return true; @@ -575,6 +590,17 @@ public boolean visit(DrdsTerminateRebalanceJob x) { return true; } + @Override + public void endVisit(DrdsResumeRebalanceJob x) { + + } + + @Override + public boolean visit(DrdsResumeRebalanceJob x) { + return true; + } + + @Override public void endVisit(DrdsSkipRebalanceSubjob x) { @@ -760,6 +786,16 @@ public void endVisit(DrdsCheckColumnarIndex x) { } + @Override + public boolean visit(DrdsCheckColumnarSnapshot x) { + return true; + } + + @Override + public void endVisit(DrdsCheckColumnarSnapshot x) { + + } + @Override public boolean visit(DrdsCheckColumnarIndex x) { return true; @@ -2800,6 +2836,16 @@ public void endVisit(DrdsMovePartition x) { } + @Override + public boolean visit(DrdsArchivePartition x) { + return false; + } + + @Override + public void endVisit(DrdsArchivePartition x) { + + } + @Override public boolean visit(DrdsExtractHotKey x) { return false; diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 5f3b152c3..443d16d4a 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -50,10 +50,14 @@ import com.alibaba.polardbx.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveDefinitionExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveJobExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimestampExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableAllocateLocalPartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableExpireLocalPartition; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsArchivePartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsExtractHotKey; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsInspectIndexStatement; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsMergePartition; @@ -146,8 +150,10 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterFileStorageStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableAsOfTimeStamp; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableBroadcast; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableModifyTtlOptions; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTablePartition; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTablePurgeBeforeTimeStamp; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableRemoveTtlOptions; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableSingle; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsBaselineStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCancelDDLJob; @@ -156,6 +162,7 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsChangeRuleVersionStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarPartition; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarSnapshot; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckGlobalIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclRulesStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclTriggersStatement; @@ -186,7 +193,10 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRefreshLocalRulesStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRefreshTopology; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRemoveDDLJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsResumeRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRollbackDDLJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowDdlEngineStatus; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsTerminateRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclRuleStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclTriggerStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowChangeSet; @@ -928,12 +938,7 @@ public boolean visit(MySqlTableIndex x) { } print('('); - for (int i = 0, size = x.getColumns().size(); i < size; ++i) { - if (i != 0) { - print0(", "); - } - x.getColumns().get(i).accept(this); - } + printIndexColumn(x.getColumns()); print(')'); if (x.getAnalyzerName() != null) { @@ -1093,13 +1098,7 @@ public boolean visit(MySqlKey x) { } print0(" ("); - - for (int i = 0, size = x.getColumns().size(); i < size; ++i) { - if (i != 0) { - print0(", "); - } - x.getColumns().get(i).accept(this); - } + printIndexColumn(x.getColumns()); print(')'); if (x.isWithImplicitTablegroup()) { @@ -1108,10 +1107,8 @@ public boolean visit(MySqlKey x) { print0(ucase ? " IMPLICIT" : " implicit"); } - SQLExpr comment = x.getComment(); - if (comment != null) { - print0(ucase ? " COMMENT " : " comment "); - printExpr(comment); + if (x.getIndexDefinition().hasOptions()) { + x.getIndexDefinition().getOptions().accept(this); } return false; @@ -2269,6 +2266,22 @@ public boolean visit(DrdsShowDDLJobs x) { return false; } + @Override + public void endVisit(DrdsShowDdlEngineStatus x) { + + } + + @Override + public boolean visit(DrdsShowDdlEngineStatus x) { + print0(ucase ? "SHOW " : "show "); + if (x.isFull()) { + print0(ucase ? "FULL " : "full "); + } + print0(ucase ? "DDL" : "ddl"); + boolean first = true; + return false; + } + @Override public void endVisit(DrdsShowDDLResults x) { @@ -2540,6 +2553,31 @@ public boolean visit(DrdsTerminateRebalanceJob x) { return false; } + @Override + public void endVisit(DrdsResumeRebalanceJob x) { + + } + + @Override + public boolean visit(DrdsResumeRebalanceJob x) { + print0(ucase ? "RESUME REBALANCE" : "resume rebalance"); + if (x.isAllJobs()) { + print0(ucase ? " ALL" : " all"); + } else { + boolean first = true; + for (Long id : x.getJobIds()) { + if (first) { + first = false; + print0(" "); + } else { + print0(", "); + } + print(id); + } + } + return false; + } + @Override public void endVisit(DrdsSkipRebalanceSubjob x) { @@ -2837,6 +2875,18 @@ public void endVisit(DrdsCheckColumnarIndex x) { } + @Override + public boolean visit(DrdsCheckColumnarSnapshot x) { + print0(ucase ? "CHECK COLUMNAR SNAPSHOT " : "check columnar snapshot "); + printExpr(x.getTableName(), parameterized); + return false; + } + + @Override + public void endVisit(DrdsCheckColumnarSnapshot x) { + + } + @Override public boolean visit(DrdsCheckColumnarIndex x) { print0(ucase ? "CHECK COLUMNAR INDEX" : "check columnar index"); @@ -5579,6 +5629,12 @@ public boolean visit(SQLAlterTableStatement x) { print0(ucase ? "UPGRADE PARTITIONING" : "upgrade partitioning"); } + if (x.getLocalPartition() != null) { + println(); + print0(ucase ? " LOCAL PARTITION BY " : " local partition by "); + x.getLocalPartition().accept(this); + } + if (x.getTableOptions().size() > 0) { if (x.getItems().size() > 0) { print(','); @@ -5633,9 +5689,10 @@ public boolean visit(SQLAlterTableStatement x) { for (int pos = 0; pos < x.getIndexTableGroupPair().size(); pos++) { print0(", "); print0(ucase ? "INDEX " : "index "); - x.getIndexTableGroupPair().get(pos).getKey().accept(this); + + printTableSourceExpr(x.getIndexTableGroupPair().get(pos).getKey()); print0(ucase ? " WITH TABLEGROUP=" : " with tablegroup="); - x.getIndexTableGroupPair().get(pos).getValue().accept(this); + printTableSourceExpr(x.getIndexTableGroupPair().get(pos).getValue()); print0(ucase ? " IMPLICIT" : " implicit"); } DrdsAlignToTableGroup alignToTableGroup = x.getAlignToTableGroup(); @@ -8624,6 +8681,28 @@ public void endVisit(DrdsMovePartition x) { } + @Override + public boolean visit(DrdsArchivePartition x) { + final String clause = "ARCHIVE " + (x.isSubPartitionsArchive() ? "SUBPARTITIONS " : "PARTITIONS "); + print0(ucase ? clause : clause.toLowerCase()); + + int i = 0; + List partitions = x.getPartitions(); + for (SQLName partition : partitions) { + if (i > 0) { + print0(", "); + } + partition.accept(this); + i++; + } + return false; + } + + @Override + public void endVisit(DrdsArchivePartition x) { + + } + @Override public boolean visit(DrdsExtractHotKey x) { print0(ucase ? "EXTRACT TO PARTITION " : "extract to partition "); @@ -8680,6 +8759,87 @@ public boolean visit(DrdsSplitHotKey x) { return false; } + @Override + public void endVisit(DrdsAlterTableModifyTtlOptions x) { + } + + @Override + public boolean visit(DrdsAlterTableModifyTtlOptions x) { + + print0(ucase ? "MODIFY TTL " : "modify ttl "); + print0(ucase ? "SET " : "set "); + SQLExpr ttlEnableAst = x.getTtlEnable(); + SQLExpr ttlExprAst = x.getTtlExpr(); + SQLExpr ttlJobAst = x.getTtlJob(); + + SQLExpr arcTblSchema = x.getArchiveTableSchema(); + SQLExpr arcTblName = x.getArchiveTableName(); + + SQLExpr arcKind = x.getArchiveKind(); + SQLExpr arcPreAllocate = x.getArcPreAllocate(); + SQLExpr arcPostAllocate = x.getArcPostAllocate(); + + if (ttlEnableAst != null) { + print0(ucase ? "TTL_ENABLE " : "ttl_enable "); + print0(" = "); + ttlEnableAst.accept(this); + } + + if (ttlExprAst != null) { + print0(ucase ? " TTL_EXPR " : " ttl_expr "); + print0(" = "); + ttlExprAst.accept(this); + } + + if (ttlJobAst != null) { + print0(ucase ? " TTL_JOB " : " ttl_job "); + print0(" = "); + ttlJobAst.accept(this); + } + + if (arcPreAllocate != null) { + print0(ucase ? " ARCHIVE_TABLE_PRE_ALLOCATE " : " archive_table_pre_allocate "); + print0(" = "); + arcPreAllocate.accept(this); + } + + if (arcPostAllocate != null) { + print0(ucase ? " ARCHIVE_TABLE_POST_ALLOCATE " : " archive_table_post_allocate "); + print0(" = "); + arcPostAllocate.accept(this); + } + + if (arcKind != null) { + print0(ucase ? " ARCHIVE_TYPE " : " archive_type "); + print0(" = "); + arcKind.accept(this); + } + + if (arcTblSchema != null) { + print0(ucase ? " ARCHIVE_TABLE_SCHEMA " : " archive_table_schema "); + print0(" = "); + arcTblSchema.accept(this); + } + + if (arcTblName != null) { + print0(ucase ? " ARCHIVE_TABLE_NAME " : " archive_table_name "); + print0(" = "); + arcTblName.accept(this); + } + + return false; + } + + @Override + public void endVisit(DrdsAlterTableRemoveTtlOptions x) { + } + + @Override + public boolean visit(DrdsAlterTableRemoveTtlOptions x) { + print0(ucase ? "REMOVE TTL " : "remove ttl "); + return false; + } + @Override public void endVisit(DrdsSplitHotKey x) { @@ -9084,4 +9244,144 @@ public boolean visit(MySqlFlushLogsStatement x) { public void endVisit(MySqlFlushLogsStatement x) { } + @Override + public boolean visit(SQLTimeToLiveDefinitionExpr x) { + SQLExpr ttlEnableExpr = x.getTtlEnableExpr(); + SQLExpr ttlExpr = x.getTtlExpr(); + SQLExpr ttlJobExpr = x.getTtlJobExpr(); + SQLExpr ttlFilterExpr = x.getTtlFilterExpr(); + SQLExpr archiveTypeExpr = x.getArchiveTypeExpr(); + SQLExpr archiveTableSchemaExpr = x.getArchiveTableSchemaExpr(); + SQLExpr archiveTableNameExpr = x.getArchiveTableNameExpr(); + SQLExpr archiveTablePreAllocate = x.getArchiveTablePreAllocateExpr(); + SQLExpr archiveTablePostAllocate = x.getArchiveTablePostAllocateExpr(); + + print0(ucase ? "TTL_DEFINITION" : "ttl_definition"); + print0("("); + + if (ttlEnableExpr != null) { + print0(ucase ? " TTL_ENABLE" : "ttl_enable"); + print0(" = "); + ttlEnableExpr.accept(this); + } + + if (ttlExpr != null) { + print0(","); + print0(ucase ? " TTL_EXPR" : "ttl_expr"); + print0(" = "); + ttlExpr.accept(this); + } + + if (ttlJobExpr != null) { + print0(","); + print0(ucase ? " TTL_JOB" : " ttl_job"); + print0(" = "); + ttlJobExpr.accept(this); + } + + if (ttlFilterExpr != null) { + print0(","); + print0(ucase ? " TTL_FILTER" : " ttl_filter"); + print0(" = "); + ttlFilterExpr.accept(this); + } + + if (archiveTypeExpr != null) { + print0(","); + print0(ucase ? " ARCHIVE_TYPE" : " archive_type"); + print0(" = "); + archiveTypeExpr.accept(this); + } + + if (archiveTableSchemaExpr != null) { + print0(","); + print0(ucase ? " ARCHIVE_TABLE_SCHEMA" : " archive_table_schema"); + print0(" = "); + archiveTableSchemaExpr.accept(this); + } + + if (archiveTableNameExpr != null) { + print0(","); + print0(ucase ? " ARCHIVE_TABLE_NAME" : " archive_table_name"); + print0(" = "); + archiveTableNameExpr.accept(this); + } + + if (archiveTablePreAllocate != null) { + print0(","); + print0(ucase ? " ARCHIVE_TABLE_PRE_ALLOCATE" : " archive_table_pre_allocate"); + print0(" = "); + archiveTablePreAllocate.accept(this); + + } + + if (archiveTablePostAllocate != null) { + print0(","); + print0(ucase ? " ARCHIVE_TABLE_POST_ALLOCATE" : " archive_table_post_allocate"); + print0(" = "); + archiveTablePostAllocate.accept(this); + } + + print0(" )"); + return false; + } + + @Override + public void endVisit(SQLTimeToLiveDefinitionExpr x) { + } + + @Override + public boolean visit(SQLTimeToLiveExpr x) { + + SQLExpr column = x.getColumn(); + SQLExpr expireAfter = x.getExpireAfter(); + SQLExpr unit = x.getUnit(); + SQLExpr timezone = x.getTimezone(); + + column.accept(this); + if (expireAfter != null) { + print0(" "); + print0(ucase ? "EXPIRE AFTER " : "expire after "); + expireAfter.accept(this); + if (unit != null) { + print0(" "); + unit.accept(this); + } + } + + if (timezone != null) { + print0(" "); + print0(ucase ? "TIMEZONE " : "timezone "); + timezone.accept(this); + } + + return false; + } + + @Override + public void endVisit(SQLTimeToLiveExpr x) { + } + + @Override + public boolean visit(SQLTimeToLiveJobExpr x) { + + SQLExpr cron = x.getCron(); + SQLExpr timezone = x.getTimezone(); + if (cron != null) { + print0(ucase ? "CRON " : "cron "); + cron.accept(this); + } + + if (timezone != null) { + print0(" "); + print0(ucase ? "TIMEZONE " : "timezone "); + timezone.accept(this); + } + return false; + } + + @Override + public void endVisit(SQLTimeToLiveJobExpr x) { + + } } // diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlParameterizedVisitor.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlParameterizedVisitor.java index 70e5de5a5..5d2d7b80e 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlParameterizedVisitor.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlParameterizedVisitor.java @@ -59,6 +59,7 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsChangeRuleVersionStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarPartition; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarSnapshot; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckGlobalIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclRulesStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclTriggersStatement; @@ -88,7 +89,10 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRecoverDDLJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRefreshLocalRulesStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRemoveDDLJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsResumeRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRollbackDDLJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowDdlEngineStatus; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsTerminateRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclRuleStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclTriggerStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowChangeSet; @@ -478,6 +482,16 @@ public void endVisit(DrdsShowDDLResults x) { } + @Override + public boolean visit(DrdsShowDdlEngineStatus x) { + return true; + } + + @Override + public void endVisit(DrdsShowDdlEngineStatus x) { + + } + @Override public boolean visit(DrdsShowDDLResults x) { return true; @@ -603,6 +617,16 @@ public boolean visit(DrdsTerminateRebalanceJob x) { return true; } + @Override + public void endVisit(DrdsResumeRebalanceJob x) { + + } + + @Override + public boolean visit(DrdsResumeRebalanceJob x) { + return true; + } + @Override public void endVisit(DrdsSkipRebalanceSubjob x) { @@ -758,6 +782,16 @@ public void endVisit(DrdsCheckColumnarPartition x) { } + @Override + public boolean visit(DrdsCheckColumnarSnapshot x) { + return true; + } + + @Override + public void endVisit(DrdsCheckColumnarSnapshot x) { + + } + @Override public boolean visit(DrdsCheckColumnarIndex x) { return true; diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java index edda1d28b..07bd04fdd 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java @@ -77,6 +77,7 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsChangeRuleVersionStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarPartition; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckColumnarSnapshot; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCheckGlobalIndex; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclRulesStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsClearCclTriggersStatement; @@ -106,7 +107,10 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRecoverDDLJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRefreshLocalRulesStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRemoveDDLJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsResumeRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsRollbackDDLJob; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowDdlEngineStatus; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsTerminateRebalanceJob; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclRuleStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowCclTriggerStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsShowChangeSet; @@ -543,6 +547,16 @@ public boolean visit(DrdsShowDDLJobs x) { return true; } + @Override + public void endVisit(DrdsShowDdlEngineStatus x) { + + } + + @Override + public boolean visit(DrdsShowDdlEngineStatus x) { + return true; + } + @Override public void endVisit(DrdsShowDDLResults x) { @@ -663,6 +677,16 @@ public boolean visit(DrdsTerminateRebalanceJob x) { return true; } + @Override + public void endVisit(DrdsResumeRebalanceJob x) { + + } + + @Override + public boolean visit(DrdsResumeRebalanceJob x) { + return true; + } + @Override public void endVisit(DrdsSkipRebalanceSubjob x) { @@ -828,6 +852,16 @@ public void endVisit(DrdsCheckColumnarIndex x) { } + @Override + public boolean visit(DrdsCheckColumnarSnapshot x) { + return true; + } + + @Override + public void endVisit(DrdsCheckColumnarSnapshot x) { + + } + @Override public boolean visit(DrdsCheckColumnarIndex x) { return true; diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLExprParser.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLExprParser.java index 40d222ca9..06cb97f9a 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLExprParser.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLExprParser.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.druid.sql.parser; +import com.alibaba.fastjson.JSON; import com.alibaba.polardbx.druid.DbType; import com.alibaba.polardbx.druid.sql.SQLUtils; import com.alibaba.polardbx.druid.sql.ast.AutoIncrementType; @@ -29,7 +30,6 @@ import com.alibaba.polardbx.druid.sql.ast.SQLExpr; import com.alibaba.polardbx.druid.sql.ast.SQLExprImpl; import com.alibaba.polardbx.druid.sql.ast.SQLIndexDefinition; -import com.alibaba.polardbx.druid.sql.ast.SQLIndexOptions; import com.alibaba.polardbx.druid.sql.ast.SQLLimit; import com.alibaba.polardbx.druid.sql.ast.SQLMapDataType; import com.alibaba.polardbx.druid.sql.ast.SQLName; @@ -137,6 +137,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Map; public class SQLExprParser extends SQLParser { @@ -943,6 +944,10 @@ public SQLExpr primary() { expr()); accept(Token.AS); cast.setDataType(parseDataType(false)); + if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) { + lexer.nextToken(); + cast.setHasArray(true); + } accept(Token.RPAREN); sqlExpr = cast; @@ -2521,6 +2526,10 @@ public SQLSelectOrderByItem parseSelectOrderByItem() { setAllowIdentifierMethod(false); try { + if (lexer.token == Token.LPAREN) { + //判断是否有括号包裹 + item.setHasParen(true); + } SQLExpr expr = expr(); if (isEnabled(SQLParserFeature.IgnoreNameQuotes)) { if (expr instanceof SQLPropertyExpr) { @@ -4797,6 +4806,23 @@ public void parseIndex(SQLIndexDefinition indexDefinition, boolean needTable) { lexer.nextToken(); accept(Token.EQ); indexDefinition.getOptions().setDictionaryColumns(lexer.stringVal); + indexDefinition.addColumnarOption("DICTIONARY_COLUMNS", lexer.stringVal); + lexer.nextToken(); + } else if (lexer.identifierEquals(FnvHash.Constants.COLUMNAR_OPTION) + || lexer.identifierEquals(FnvHash.Constants.COLUMNAR_OPTIONS)) { + lexer.nextToken(); + if (lexer.token() == Token.EQ) { + lexer.nextToken(); + } + if (lexer.token() != Token.LITERAL_CHARS) { + throw new ParserException( + "Columnar options should be a JSON string enclosed in single quotes, " + + "e.g. columnar_options='{\"a\":\"b\", \"c\":\"d\"}'"); + } + Map map = JSON.parseObject(lexer.stringVal, Map.class); + for (Map.Entry entry : map.entrySet()) { + indexDefinition.addColumnarOption(entry.getKey(), (String) entry.getValue()); + } lexer.nextToken(); } else { break _opts; diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLParser.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLParser.java index 343a57874..3d7dcf020 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLParser.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLParser.java @@ -566,7 +566,7 @@ public void match(Token token) { private int errorEndPos = -1; - protected void setErrorEndPos(int errPos) { + public void setErrorEndPos(int errPos) { if (errPos > errorEndPos) { errorEndPos = errPos; } diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLParserFeature.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLParserFeature.java index e408037dd..39c041b3b 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLParserFeature.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLParserFeature.java @@ -56,7 +56,7 @@ public enum SQLParserFeature { Spark, Presto, - ; + UpperCaseAgg; private SQLParserFeature() { mask = (1 << ordinal()); diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLStatementParser.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLStatementParser.java index f377ba06f..3f755ac01 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLStatementParser.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/SQLStatementParser.java @@ -866,6 +866,13 @@ public void parseStatementList(List statementList, int max, SQLObj continue; } + if(lexer.identifierEquals("RESUME")) { + SQLStatement stmt = parseResume(); + statementList.add(stmt); + stmt.setParent(parent); + continue; + } + if (lexer.identifierEquals("DUMP")) { SQLStatement stmt = parseDump(); statementList.add(stmt); @@ -984,6 +991,7 @@ public void parseStatementList(List statementList, int max, SQLObj // + lexer.stringVal() + ", pos " // + lexer.pos()); //throw new ParserException("not supported." + lexer.info()); + printError(lexer.token); } @@ -1740,6 +1748,11 @@ public SQLStatement parseTerminate() { throw new ParserException("Only support terminate rebalance ."); } + public SQLStatement parseResume() { + lexer.nextToken(); + throw new ParserException("Only support resume rebalance ."); + } + public SQLStatement parseCommit() { throw new ParserException("TODO " + lexer.info()); } diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/Token.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/Token.java index 1fc7c15c7..bdddc835a 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/Token.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/parser/Token.java @@ -263,6 +263,7 @@ public enum Token { KEEP_DUPLICATES("KEEP_DUPLICATES"), EXCEPTIONS("EXCEPTIONS"), PURGE("PURGE"), + SNAPSHOT("SNAPSHOT"), COMPUTE("COMPUTE"), ANALYZE("ANALYZE"), diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTOutputVisitor.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTOutputVisitor.java index d18f7a42e..0736b38dd 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTOutputVisitor.java @@ -127,7 +127,9 @@ import com.alibaba.polardbx.druid.sql.ast.expr.SQLValuesExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableAllocateLocalPartition; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableCleanupExpiredData; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableExpireLocalPartition; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsArchivePartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsExtractHotKey; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsMergePartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsMovePartition; @@ -410,6 +412,7 @@ import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.SQLAlterTableAddRoute; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.SQLCreateResourceGroupStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.SQLListResourceGroupStatement; +import com.alibaba.polardbx.druid.sql.parser.SQLParserFeature; import com.alibaba.polardbx.druid.util.FnvHash; import com.alibaba.polardbx.druid.util.Pair; import org.apache.commons.lang.StringUtils; @@ -436,6 +439,7 @@ import java.util.TimeZone; import java.util.stream.Collectors; +import static com.alibaba.polardbx.druid.sql.visitor.VisitorFeature.OutputUppercaseAgg; import static com.alibaba.polardbx.druid.util.Utils.getBoolean; public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements ParameterizedVisitor, PrintableVisitor { @@ -834,6 +838,16 @@ protected void printAndAccept(List nodes, String seperator) } } + // mysql 8.0 函数索引,表达式需要加上() + protected void printIndexColumn(List columns) { + for (int i = 0, size = columns.size(); i < size; ++i) { + if (i != 0) { + print0(", "); + } + columns.get(i).accept(this); + } + } + protected void printAndAccept(List nodes, String seperator, boolean parameterized) { for (int i = 0, size = nodes.size(); i < size; ++i) { if (i != 0) { @@ -1330,15 +1344,23 @@ public boolean visit(SQLBinaryOpExpr x) { if (operator.isRelational() && left instanceof SQLIntegerExpr && right instanceof SQLIntegerExpr) { - print(((SQLIntegerExpr) left).getNumber().longValue()); + + Number leftNumber = ((SQLIntegerExpr) left).getNumber(); + if (leftNumber instanceof BigInteger) { + print0(((BigInteger) leftNumber).toString()); + } else { + print(leftNumber.longValue()); + } + print(' '); printOperator(operator); print(' '); - Number number = ((SQLIntegerExpr) right).getNumber(); - if (number instanceof BigInteger) { - print0(((BigInteger) number).toString()); + + Number rightNumber = ((SQLIntegerExpr) right).getNumber(); + if (rightNumber instanceof BigInteger) { + print0(((BigInteger) rightNumber).toString()); } else { - print(number.longValue()); + print(rightNumber.longValue()); } return false; } @@ -1770,6 +1792,9 @@ public boolean visit(SQLCastExpr x) { x.getExpr().accept(this); print0(ucase ? " AS " : " as "); x.getDataType().accept(this); + if (x.isHasArray()) { + print0(ucase ? " ARRAY" : " array"); + } print0(")"); return false; @@ -2428,7 +2453,11 @@ public boolean visit(SQLAggregateExpr x) { } String methodName = x.getMethodName(); - print0(ucase ? methodName : methodName.toLowerCase()); + if (isEnabled(OutputUppercaseAgg)) { + print0(ucase ? methodName.toUpperCase() : methodName.toLowerCase()); + } else { + print0(ucase ? methodName : methodName.toLowerCase()); + } print('('); SQLAggregateOption option = x.getOption(); @@ -3065,6 +3094,10 @@ public boolean visit(SQLOrderBy x) { } public boolean visit(SQLSelectOrderByItem x) { + //有括号的话,补上括号 + if (x.isHasParen()) { + print('('); + } SQLExpr expr = x.getExpr(); if (expr instanceof SQLIntegerExpr) { @@ -3073,6 +3106,10 @@ public boolean visit(SQLSelectOrderByItem x) { printExpr(expr, parameterized); } + if (x.isHasParen()) { + print(')'); + } + SQLOrderingSpecification type = x.getType(); if (type != null) { print(' '); @@ -4640,7 +4677,7 @@ public boolean visit(SQLSubqueryTableSource x) { print(')'); final List columns = x.getColumns(); - final String alias = x.getAlias(); + String alias = x.getAlias(); if (alias != null) { if (columns.size() > 0) { print0(" AS "); @@ -5286,6 +5323,17 @@ public boolean visit(DrdsAlterTableExpireLocalPartition x) { return false; } + @Override + public void endVisit(DrdsAlterTableCleanupExpiredData x) { + + } + + @Override + public boolean visit(DrdsAlterTableCleanupExpiredData x) { + print0("CLEANUP EXPIRED DATA "); + return false; + } + @Override public boolean visit(DrdsMergePartition x) { if (!x.isSubPartitionsMerge()) { @@ -5386,6 +5434,28 @@ public void endVisit(DrdsMovePartition x) { } + @Override + public boolean visit(DrdsArchivePartition x) { + final String clause = "ARCHIVE " + (x.isSubPartitionsArchive() ? "SUBPARTITIONS " : "PARTITIONS "); + print0(ucase ? clause : clause.toLowerCase()); + + int i = 0; + List partitions = x.getPartitions(); + for (SQLName partition : partitions) { + if (i > 0) { + print0(", "); + } + partition.accept(this); + i++; + } + return false; + } + + @Override + public void endVisit(DrdsArchivePartition x) { + + } + @Override public boolean visit(DrdsExtractHotKey x) { print0(ucase ? "EXTRACT TO PARTITION " : "extract to partition "); @@ -6208,7 +6278,7 @@ public boolean visit(SQLCreateIndexStatement x) { x.getTable().accept(this); } print0(" ("); - printAndAccept(x.getItems(), ", "); + printIndexColumn(x.getItems()); print(')'); List covering = x.getCovering(); @@ -6273,6 +6343,18 @@ public boolean visit(SQLCreateIndexStatement x) { x.getIndexDefinition().getOptions().accept(this); } + Map columnarOptions = x.getIndexDefinition().getColumnarOptions(); + if (null != columnarOptions && !columnarOptions.isEmpty()) { + StringBuilder str = new StringBuilder(" \nCOLUMNAR_OPTIONS='{\n"); + for (Map.Entry option : columnarOptions.entrySet()) { + String key = option.getKey(); + String val = option.getValue(); + str.append("\t\"").append(key).append("\":\"").append(val).append("\",\n"); + } + str.append("}'"); + print0(" " + (ucase ? str.toString().toUpperCase() : str.toString().toLowerCase())); + } + return false; } @@ -6805,6 +6887,14 @@ public boolean visit(SQLIndexOptions x) { option.accept(this); } } + + String execComment = x.getExecComment(); + if (execComment != null) { + print0(" /*"); + print0(execComment); + print0("*/"); + } + return false; } @@ -6866,7 +6956,7 @@ public boolean visit(SQLIndexDefinition x) { } print('('); - printAndAccept(x.getColumns(), ", "); + printIndexColumn(x.getColumns()); print(')'); if (x.getAnalyzerName() != null) { @@ -6956,6 +7046,18 @@ public boolean visit(SQLIndexDefinition x) { print0(ucase ? " INVISIBLE " : " invisible "); } + Map columnarOptions = x.getColumnarOptions(); + if (null != columnarOptions && !columnarOptions.isEmpty()) { + StringBuilder str = new StringBuilder(" \n\t\tCOLUMNAR_OPTIONS='{\n"); + for (Map.Entry option : columnarOptions.entrySet()) { + String key = option.getKey(); + String val = option.getValue(); + str.append("\t\t\t\"").append(key).append("\":\"").append(val).append("\",\n"); + } + str.append("\t\t}'"); + print0(" " + (ucase ? str.toString().toUpperCase() : str.toString().toLowerCase())); + } + return false; } @@ -8077,10 +8179,34 @@ public boolean visit(SQLPartitionByRange x) { print(')'); } + if (x.getStartWith() != null) { + println(); + print0(ucase ? " STARTWITH " : " startwith "); + x.getStartWith().accept(this); + } + if (interval != null) { - print0(ucase ? " INTERVAL (" : " interval ("); + println(); + print0(" "); interval.accept(this); - print(')'); + } + + if (x.getExpireAfter() != null) { + println(); + print0(ucase ? " EXPIRE AFTER " : " expire after "); + x.getExpireAfter().accept(this); + } + + if (x.getPreAllocate() != null) { + println(); + print0(ucase ? " PRE ALLOCATE " : " pre allocate "); + x.getPreAllocate().accept(this); + } + + if (x.getPivotDateExpr() != null) { + println(); + print0(ucase ? " PIVOTDATE " : " pivotdate "); + x.getPivotDateExpr().accept(this); } } @@ -10651,6 +10777,13 @@ public boolean visit(MySqlCreateTableStatement x) { dbpartitions.accept(this); } + SQLPartitionBy localPartition = x.getLocalPartitioning(); + if (localPartition != null) { + println(); + print0(ucase ? "LOCAL PARTITION BY " : "local partition by "); + localPartition.accept(this); + } + SQLExpr tbPartitionsBy = x.getTablePartitionBy(); if (tbPartitionsBy != null) { println(); @@ -12200,9 +12333,13 @@ public boolean visit(SQLStartReplicaCheckTableStatement x) { } if (x.getChannel() != null) { - print0(ucase ? " FOR CHANNEL " : " for channel "); + print0(ucase ? " CHANNEL=" : " channel="); x.getChannel().accept(this); } + if (x.getMode() != null) { + print0(ucase ? " MODE=" : " mode="); + x.getMode().accept(this); + } return false; } diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTVisitor.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTVisitor.java index b179228c7..03b221fea 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTVisitor.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTVisitor.java @@ -103,15 +103,20 @@ import com.alibaba.polardbx.druid.sql.ast.expr.SQLSmallIntExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLSomeExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveDefinitionExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveJobExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimestampExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLTinyIntExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLValuesExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableAllocateLocalPartition; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableCleanupExpiredData; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableExpireLocalPartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableGroupSetLocality; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableGroupSetPartitionsLocality; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsArchivePartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsExtractHotKey; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsMergePartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsMovePartition; @@ -373,9 +378,11 @@ import com.alibaba.polardbx.druid.sql.ast.statement.SQLWithSubqueryClause; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterStoragePoolStatement; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableRemoveTtlOptions; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCreateSecurityLabelComponentStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCreateSecurityLabelStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCreateSecurityPolicyStatement; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableModifyTtlOptions; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCreateStoragePoolStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsDropSecurityLabelComponentStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsDropSecurityLabelStatement; @@ -931,6 +938,10 @@ public interface SQLASTVisitor { boolean visit(SQLUnionQueryTableSource x); + void endVisit(SQLTimeToLiveDefinitionExpr x); + + boolean visit(SQLTimeToLiveDefinitionExpr x); + void endVisit(SQLTimestampExpr x); boolean visit(SQLTimestampExpr x); @@ -947,6 +958,14 @@ public interface SQLASTVisitor { boolean visit(SQLFloatExpr x); + boolean visit(SQLTimeToLiveExpr x); + + void endVisit(SQLTimeToLiveExpr x); + + boolean visit(SQLTimeToLiveJobExpr x); + + void endVisit(SQLTimeToLiveJobExpr x); + void endVisit(SQLRevokeStatement x); boolean visit(SQLRevokeStatement x); @@ -1842,6 +1861,10 @@ public interface SQLASTVisitor { boolean visit(DrdsMovePartition x); + void endVisit(DrdsArchivePartition x); + + boolean visit(DrdsArchivePartition x); + void endVisit(DrdsExtractHotKey x); boolean visit(DrdsExtractHotKey x); @@ -1858,6 +1881,14 @@ public interface SQLASTVisitor { boolean visit(SQLAlterTableModifySubPartitionValues x); + void endVisit(DrdsAlterTableModifyTtlOptions x); + + boolean visit(DrdsAlterTableModifyTtlOptions x); + + void endVisit(DrdsAlterTableRemoveTtlOptions x); + + boolean visit(DrdsAlterTableRemoveTtlOptions x); + void endVisit(DrdsRenamePartition x); boolean visit(DrdsRenamePartition x); @@ -1890,6 +1921,10 @@ public interface SQLASTVisitor { boolean visit(DrdsAlterTableExpireLocalPartition x); + void endVisit(DrdsAlterTableCleanupExpiredData x); + + boolean visit(DrdsAlterTableCleanupExpiredData x); + void endVisit(DrdsRefreshTopology x); boolean visit(DrdsRefreshTopology x); diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTVisitorAdapter.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTVisitorAdapter.java index ec956f9ea..7615efd6c 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -104,15 +104,20 @@ import com.alibaba.polardbx.druid.sql.ast.expr.SQLSmallIntExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLSomeExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveDefinitionExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimeToLiveJobExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLTimestampExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLTinyIntExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLValuesExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableAllocateLocalPartition; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableCleanupExpiredData; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableExpireLocalPartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableGroupSetLocality; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsAlterTableGroupSetPartitionsLocality; +import com.alibaba.polardbx.druid.sql.ast.statement.DrdsArchivePartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsExtractHotKey; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsMergePartition; import com.alibaba.polardbx.druid.sql.ast.statement.DrdsMovePartition; @@ -375,9 +380,11 @@ import com.alibaba.polardbx.druid.sql.ast.statement.SQLWhoamiStatement; import com.alibaba.polardbx.druid.sql.ast.statement.SQLWithSubqueryClause; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterStoragePoolStatement; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableRemoveTtlOptions; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCreateSecurityLabelComponentStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCreateSecurityLabelStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCreateSecurityPolicyStatement; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsAlterTableModifyTtlOptions; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsCreateStoragePoolStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsDropSecurityLabelComponentStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.DrdsDropSecurityLabelStatement; @@ -1616,6 +1623,36 @@ public void endVisit(SQLFloatExpr x) { } + @Override + public boolean visit(SQLTimeToLiveDefinitionExpr x) { + return false; + } + + @Override + public void endVisit(SQLTimeToLiveDefinitionExpr x) { + + } + + @Override + public boolean visit(SQLTimeToLiveExpr x) { + return false; + } + + @Override + public void endVisit(SQLTimeToLiveExpr x) { + + } + + @Override + public boolean visit(SQLTimeToLiveJobExpr x) { + return false; + } + + @Override + public void endVisit(SQLTimeToLiveJobExpr x) { + + } + @Override public boolean visit(SQLDropCatalogStatement x) { return true; @@ -3803,6 +3840,16 @@ public void endVisit(DrdsAlterTableExpireLocalPartition x) { } + @Override + public boolean visit(DrdsAlterTableCleanupExpiredData x) { + return false; + } + + @Override + public void endVisit(DrdsAlterTableCleanupExpiredData x) { + + } + @Override public boolean visit(DrdsAlterTableExpireLocalPartition x) { return false; @@ -3828,6 +3875,16 @@ public void endVisit(DrdsMovePartition x) { } + @Override + public boolean visit(DrdsArchivePartition x) { + return false; + } + + @Override + public void endVisit(DrdsArchivePartition x) { + + } + @Override public boolean visit(DrdsExtractHotKey x) { return false; @@ -3862,6 +3919,24 @@ public boolean visit(SQLAlterTableModifySubPartitionValues x) { return false; } + @Override + public void endVisit(DrdsAlterTableRemoveTtlOptions x) { + } + + @Override + public boolean visit(DrdsAlterTableRemoveTtlOptions x) { + return false; + } + + @Override + public void endVisit(DrdsAlterTableModifyTtlOptions x) { + } + + @Override + public boolean visit(DrdsAlterTableModifyTtlOptions x) { + return false; + } + @Override public void endVisit(SQLAlterTableModifySubPartitionValues x) { diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/VisitorFeature.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/VisitorFeature.java index edca6779a..9ef71435b 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/VisitorFeature.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/sql/visitor/VisitorFeature.java @@ -40,7 +40,8 @@ public enum VisitorFeature { OutputDistributedLiteralInCreateTableStmt, OutputPlOnlyDefinition, OutputHashPartitionsByRange, - OutputMySQLIndentString; + OutputMySQLIndentString, + OutputUppercaseAgg; private VisitorFeature() { mask = (1 << ordinal()); diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/support/logging/Log4j2Impl.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/support/logging/Log4j2Impl.java deleted file mode 100644 index c810bbca3..000000000 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/support/logging/Log4j2Impl.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.druid.support.logging; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/* - * Copyright 1999-2017 Alibaba Group Holding Ltd. - * - * Licensed 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. - */ -public class Log4j2Impl implements Log { - - private Logger log; - - private int errorCount; - private int warnCount; - private int infoCount; - private int debugCount; - - /** - * @since 0.2.21 - * @param log - */ - public Log4j2Impl(Logger log){ - this.log = log; - } - - public Log4j2Impl(String loggerName){ - log = LogManager.getLogger(loggerName); - } - - public Logger getLog() { - return log; - } - - public boolean isDebugEnabled() { - return log.isDebugEnabled(); - } - - public void error(String s, Throwable e) { - errorCount++; - log.error(s, e); - } - - public void error(String s) { - errorCount++; - log.error(s); - } - - public void debug(String s) { - debugCount++; - log.debug(s); - } - - public void debug(String s, Throwable e) { - debugCount++; - log.debug(s, e); - } - - public void warn(String s) { - log.warn(s); - warnCount++; - } - - public void warn(String s, Throwable e) { - log.warn(s, e); - warnCount++; - } - - public int getWarnCount() { - return warnCount; - } - - public int getErrorCount() { - return errorCount; - } - - public void resetStat() { - errorCount = 0; - warnCount = 0; - infoCount = 0; - debugCount = 0; - } - - public int getDebugCount() { - return debugCount; - } - - public boolean isInfoEnabled() { - return log.isInfoEnabled(); - } - - public void info(String msg) { - infoCount++; - log.info(msg); - } - - public boolean isWarnEnabled() { - return log.isEnabled(Level.WARN); - } - - public boolean isErrorEnabled() { - return log.isErrorEnabled(); - } - - public int getInfoCount() { - return infoCount; - } - - public String toString() { - return log.toString(); - } - -} diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/util/CollationNameForParser.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/util/CollationNameForParser.java index 0ab49a947..49212346b 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/util/CollationNameForParser.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/util/CollationNameForParser.java @@ -556,6 +556,9 @@ public static CollationNameForParser defaultNumericCollation() { .put(new MixCollationKey(UTF8_BIN, LATIN1_SPANISH_CI), UTF8_BIN) .put(new MixCollationKey(UTF8_BIN, BIG5_BIN), UTF8_BIN) .put(new MixCollationKey(UTF8_BIN, BIG5_CHINESE_CI), UTF8_BIN) + .put(new MixCollationKey(UTF8_BIN, UTF8_GENERAL_CI), UTF8_BIN) + .put(new MixCollationKey(UTF8_BIN, UTF8_UNICODE_CI), UTF8_BIN) + .put(new MixCollationKey(UTF8_BIN, UTF8_GENERAL_MYSQL500_CI), UTF8_BIN) .put(new MixCollationKey(UTF8_UNICODE_CI, UTF8MB4_GENERAL_CI), UTF8MB4_GENERAL_CI) .put(new MixCollationKey(UTF8_UNICODE_CI, UTF8MB4_BIN), UTF8MB4_BIN) .put(new MixCollationKey(UTF8_UNICODE_CI, UTF8MB4_UNICODE_CI), UTF8MB4_UNICODE_CI) @@ -619,6 +622,11 @@ public static CollationNameForParser defaultNumericCollation() { .put(new MixCollationKey(UTF8MB4_BIN, LATIN1_SPANISH_CI), UTF8MB4_BIN) .put(new MixCollationKey(UTF8MB4_BIN, BIG5_BIN), UTF8MB4_BIN) .put(new MixCollationKey(UTF8MB4_BIN, BIG5_CHINESE_CI), UTF8MB4_BIN) + .put(new MixCollationKey(UTF8MB4_BIN, UTF8MB4_GENERAL_CI), UTF8MB4_BIN) + .put(new MixCollationKey(UTF8MB4_BIN, UTF8MB4_UNICODE_CI), UTF8MB4_BIN) + .put(new MixCollationKey(UTF8MB4_BIN, UTF8MB4_UNICODE_520_CI), UTF8MB4_BIN) + .put(new MixCollationKey(UTF8MB4_BIN, UTF8MB4_0900_AI_CI), UTF8MB4_BIN) + .put(new MixCollationKey(UTF8MB4_BIN, UTF8MB4_ZH_0900_AS_CS), UTF8MB4_BIN) .put(new MixCollationKey(UTF8MB4_UNICODE_CI, UTF16LE_GENERAL_CI), UTF16LE_GENERAL_CI) .put(new MixCollationKey(UTF8MB4_UNICODE_CI, UTF16LE_BIN), UTF16LE_BIN) .put(new MixCollationKey(UTF8MB4_UNICODE_CI, ASCII_GENERAL_CI), UTF8MB4_UNICODE_CI) @@ -679,6 +687,8 @@ public static CollationNameForParser defaultNumericCollation() { .put(new MixCollationKey(UTF16_BIN, LATIN1_SPANISH_CI), UTF16_BIN) .put(new MixCollationKey(UTF16_BIN, BIG5_BIN), UTF16_BIN) .put(new MixCollationKey(UTF16_BIN, BIG5_CHINESE_CI), UTF16_BIN) + .put(new MixCollationKey(UTF16_BIN, UTF16_GENERAL_CI), UTF16_BIN) + .put(new MixCollationKey(UTF16_BIN, UTF16_UNICODE_CI), UTF16_BIN) .put(new MixCollationKey(UTF16_UNICODE_CI, UTF16LE_GENERAL_CI), UTF16LE_GENERAL_CI) .put(new MixCollationKey(UTF16_UNICODE_CI, UTF16LE_BIN), UTF16LE_BIN) .put(new MixCollationKey(UTF16_UNICODE_CI, ASCII_GENERAL_CI), UTF16_UNICODE_CI) @@ -741,6 +751,7 @@ public static CollationNameForParser defaultNumericCollation() { .put(new MixCollationKey(UTF16LE_BIN, LATIN1_SPANISH_CI), UTF16LE_BIN) .put(new MixCollationKey(UTF16LE_BIN, BIG5_BIN), UTF16LE_BIN) .put(new MixCollationKey(UTF16LE_BIN, BIG5_CHINESE_CI), UTF16LE_BIN) + .put(new MixCollationKey(UTF16LE_BIN, UTF16LE_GENERAL_CI), UTF16LE_BIN) .put(new MixCollationKey(UTF32_GENERAL_CI, ASCII_GENERAL_CI), UTF32_GENERAL_CI) .put(new MixCollationKey(UTF32_GENERAL_CI, ASCII_BIN), UTF32_GENERAL_CI) .put(new MixCollationKey(UTF32_GENERAL_CI, BINARY), BINARY) @@ -777,6 +788,8 @@ public static CollationNameForParser defaultNumericCollation() { .put(new MixCollationKey(UTF32_BIN, LATIN1_SPANISH_CI), UTF32_BIN) .put(new MixCollationKey(UTF32_BIN, BIG5_BIN), UTF32_BIN) .put(new MixCollationKey(UTF32_BIN, BIG5_CHINESE_CI), UTF32_BIN) + .put(new MixCollationKey(UTF32_BIN, UTF32_GENERAL_CI), UTF32_BIN) + .put(new MixCollationKey(UTF32_BIN, UTF32_UNICODE_CI), UTF32_BIN) .put(new MixCollationKey(UTF32_UNICODE_CI, ASCII_GENERAL_CI), UTF32_UNICODE_CI) .put(new MixCollationKey(UTF32_UNICODE_CI, ASCII_BIN), UTF32_UNICODE_CI) .put(new MixCollationKey(UTF32_UNICODE_CI, BINARY), BINARY) @@ -812,6 +825,10 @@ public static CollationNameForParser defaultNumericCollation() { .put(new MixCollationKey(BINARY, LATIN1_SPANISH_CI), BINARY) .put(new MixCollationKey(BINARY, BIG5_BIN), BINARY) .put(new MixCollationKey(BINARY, BIG5_CHINESE_CI), BINARY) + // If UTF8MB4_0900_AI_CI exists, it means the server is in MySQL 80 mode and unicode_ci and general_ci + // should be compatible with it. + .put(new MixCollationKey(UTF8MB4_0900_AI_CI, UTF8MB4_GENERAL_CI), UTF8MB4_0900_AI_CI) + .put(new MixCollationKey(UTF8MB4_0900_AI_CI, UTF8MB4_UNICODE_CI), UTF8MB4_0900_AI_CI) .put(new MixCollationKey(UTF8MB4_0900_AI_CI, UTF8_GENERAL_CI), UTF8MB4_0900_AI_CI) .put(new MixCollationKey(UTF8MB4_0900_AI_CI, UTF8_BIN), UTF8MB4_0900_AI_CI) .put(new MixCollationKey(UTF8MB4_0900_AI_CI, UTF8_UNICODE_CI), UTF8MB4_0900_AI_CI) @@ -870,6 +887,18 @@ public static CollationNameForParser defaultNumericCollation() { .put(new MixCollationKey(UTF8MB4_UNICODE_520_CI, LATIN1_SPANISH_CI), UTF8MB4_UNICODE_520_CI) .put(new MixCollationKey(UTF8MB4_UNICODE_520_CI, BIG5_BIN), UTF8MB4_UNICODE_520_CI) .put(new MixCollationKey(UTF8MB4_UNICODE_520_CI, BIG5_CHINESE_CI), UTF8MB4_UNICODE_520_CI) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_SWEDISH_CI), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_GERMAN1_CI), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_DANISH_CI), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_GERMAN2_CI), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_GENERAL_CI), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_GENERAL_CS), LATIN1_BIN) + .put(new MixCollationKey(LATIN1_BIN, LATIN1_SPANISH_CI), LATIN1_BIN) + .put(new MixCollationKey(GB18030_BIN, GB18030_UNICODE_520_CI), GB18030_BIN) + .put(new MixCollationKey(GB18030_BIN, GB18030_CHINESE_CI), GB18030_BIN) + .put(new MixCollationKey(ASCII_BIN, ASCII_GENERAL_CI), ASCII_BIN) + .put(new MixCollationKey(GBK_BIN, GBK_CHINESE_CI), GBK_BIN) + .put(new MixCollationKey(BIG5_BIN, BIG5_CHINESE_CI), BIG5_BIN) .build(); private static class MixCollationKey { diff --git a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/util/FnvHash.java b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/util/FnvHash.java index 1a4952fdf..3f60eb890 100644 --- a/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/util/FnvHash.java +++ b/polardbx-parser/src/main/java/com/alibaba/polardbx/druid/util/FnvHash.java @@ -824,6 +824,8 @@ public static interface Constants { long DATABASES = fnv1a_64_lower("DATABASES"); long COLUMNS = fnv1a_64_lower("COLUMNS"); long DICTIONARY_COLUMNS = fnv1a_64_lower("DICTIONARY_COLUMNS"); + long COLUMNAR_OPTIONS = fnv1a_64_lower("COLUMNAR_OPTIONS"); + long COLUMNAR_OPTION = fnv1a_64_lower("COLUMNAR_OPTION"); long PROCESS = fnv1a_64_lower("PROCESS"); long PROCESSLIST = fnv1a_64_lower("PROCESSLIST"); long MPP = fnv1a_64_lower("MPP"); @@ -1175,6 +1177,18 @@ public static interface Constants { long JOINGROUP = fnv1a_64_lower("JOINGROUP"); + long TTL = fnv1a_64_lower("TTL"); + long TTL_DEFINITION = fnv1a_64_lower("TTL_DEFINITION"); + long TTL_ENABLE = fnv1a_64_lower("TTL_ENABLE"); + long TTL_EXPR = fnv1a_64_lower("TTL_EXPR"); + long TTL_JOB = fnv1a_64_lower("TTL_JOB"); + long TTL_FILTER = fnv1a_64_lower("TTL_FILTER"); + long ARCHIVE_TYPE = fnv1a_64_lower("ARCHIVE_TYPE"); + long ARCHIVE_TABLE_SCHEMA = fnv1a_64_lower("ARCHIVE_TABLE_SCHEMA"); + long ARCHIVE_TABLE_NAME = fnv1a_64_lower("ARCHIVE_TABLE_NAME"); + long ARCHIVE_TABLE_PRE_ALLOCATE = fnv1a_64_lower("ARCHIVE_TABLE_PRE_ALLOCATE"); + long ARCHIVE_TABLE_POST_ALLOCATE = fnv1a_64_lower("ARCHIVE_TABLE_POST_ALLOCATE"); + Set MYSQL_CHARACTER_SETS = ImmutableSet.of( _BIG5, _DEC8, _CP850, _HP8, _KOI8R, _LATIN1, _LATIN2, _SWE7, _ASCII, _UJIS, _SJIS, _HEBREW, _TIS620, _EUCKR, _KOI8U, _GB2312, _GREEK, _CP1250, _GBK, _LATIN5, _ARMSCII8, _UTF8, _UCS2, _CP866, _KEYBCS2, diff --git a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/PolarDBDDLAsyncOptiionTest.java b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/PolarDBDDLAsyncOptiionTest.java index 343bca2e7..97ac95eb9 100644 --- a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/PolarDBDDLAsyncOptiionTest.java +++ b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/PolarDBDDLAsyncOptiionTest.java @@ -123,6 +123,16 @@ public void testDDLManageJob() { parser = new MySqlStatementParser(ByteString.from(sql), SQLParserFeature.DRDSAsyncDDL); result = parser.parseStatementList().get(0); Assert.assertEquals(result.getAsync(), null); + + sql = "resume rebalance 1234 async=false"; + parser = new MySqlStatementParser(ByteString.from(sql), SQLParserFeature.DRDSAsyncDDL); + result = parser.parseStatementList().get(0); + Assert.assertEquals(result.getAsync(), Boolean.FALSE); + + sql = "resume rebalance 1234"; + parser = new MySqlStatementParser(ByteString.from(sql), SQLParserFeature.DRDSAsyncDDL); + result = parser.parseStatementList().get(0); + Assert.assertEquals(result.getAsync(), null); } public void testOptTable() { diff --git a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest.java b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest.java index 4e6aca82c..5af8d2f19 100644 --- a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest.java +++ b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest.java @@ -95,4 +95,17 @@ public void test_alter_6() throws Exception { SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); } + public void test_alter_7() throws Exception { + String sql = "ALTER TABLE `event_record`\n" + + " ADD COLUMN `notifyId` varchar(32) NOT NULL COMMENT '消息通知ID' AFTER `id`,\n" + + " MODIFY COLUMN `event_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '事件类型:order_pay,refund,refund_finish' AFTER `event_no`,\n" + + " MODIFY COLUMN `biz_type` tinyint NOT NULL COMMENT '业务类型:1订单,2履约,3退款' AFTER `event_type`,\n" + + " MODIFY COLUMN `user_id` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户id' AFTER `biz_no` WITH TABLEGROUP=tg28 IMPLICIT"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + Assert.assertEquals(sql, + SQLUtils.toMySqlString(stmt)); + } + } diff --git a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_13_polardbx.java b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_13_polardbx.java index d9487f828..ac6afb326 100644 --- a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_13_polardbx.java +++ b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_13_polardbx.java @@ -106,8 +106,70 @@ public void testFive() { String output = SQLUtils.toMySqlString(stmt); assertEquals( - "CREATE CLUSTERED COLUMNAR INDEX `nation_col_index` ON nation (`n_nationkey`) PARTITION BY HASH (`n_nationkey`) PARTITIONS 1 ENGINE = 'COLUMNAR' USING BTREE " - + "DICTIONARY_COLUMNS = 'n_name,n_comment' KEY_BLOCK_SIZE = 20 COMMENT 'CREATE CCI TEST' ALGORITHM = DEFAULT LOCK = DEFAULT;", + "CREATE CLUSTERED COLUMNAR INDEX `nation_col_index` ON nation (`n_nationkey`) PARTITION BY HASH (`n_nationkey`) PARTITIONS 1 ENGINE = 'COLUMNAR' USING BTREE DICTIONARY_COLUMNS = 'n_name,n_comment' KEY_BLOCK_SIZE = 20 COMMENT 'CREATE CCI TEST' ALGORITHM = DEFAULT LOCK = DEFAULT \n" + + "COLUMNAR_OPTIONS='{\n" + + "\t\"DICTIONARY_COLUMNS\":\"N_NAME,N_COMMENT\",\n" + + "}';", + output); + } + + @Test + public void testSix() { + String sql = + "create clustered columnar index `nation_col_index` on nation(`n_nationkey`) " + + "partition by hash(`n_nationkey`) partitions 1 " + + "ENGINE='COLUMNAR' " + + "USING BTREE KEY_BLOCK_SIZE=20 COMMENT 'CREATE CCI TEST' ALGORITHM=DEFAULT LOCK=DEFAULT " + + "DICTIONARY_COLUMNS='n_name,n_comment' " + + "COLUMNAR_OPTIONS='{" + + " \"TYPE\":\"SNAPSHOT\"," + + " \"SNAPSHOT_RETENTION_DAYS\":\"7\"" + + "}';"; + + List stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL); + + SQLStatement stmt = stmtList.get(0); + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + String output = SQLUtils.toMySqlString(stmt); + assertEquals( + "CREATE CLUSTERED COLUMNAR INDEX `nation_col_index` ON nation (`n_nationkey`) PARTITION BY HASH (`n_nationkey`) PARTITIONS 1 ENGINE = 'COLUMNAR' USING BTREE DICTIONARY_COLUMNS = 'n_name,n_comment' KEY_BLOCK_SIZE = 20 COMMENT 'CREATE CCI TEST' ALGORITHM = DEFAULT LOCK = DEFAULT \n" + + "COLUMNAR_OPTIONS='{\n" + + "\t\"DICTIONARY_COLUMNS\":\"N_NAME,N_COMMENT\",\n" + + "\t\"TYPE\":\"SNAPSHOT\",\n" + + "\t\"SNAPSHOT_RETENTION_DAYS\":\"7\",\n" + + "}';", + output); + } + + @Test + public void testSeven() { + String sql = + "create clustered columnar index `nation_col_index` on nation(`n_nationkey`) " + + "partition by hash(`n_nationkey`) partitions 1 " + + "ENGINE='COLUMNAR' " + + "USING BTREE KEY_BLOCK_SIZE=20 COMMENT 'CREATE CCI TEST' ALGORITHM=DEFAULT LOCK=DEFAULT " + + "COLUMNAR_OPTIONS='{" + + " \"TYPE\":\"SNAPSHOT\"," + + " \"DICTIONARY_COLUMNS\":\"N_NAME,N_COMMENT\",\n" + + " \"SNAPSHOT_RETENTION_DAYS\":\"7\"" + + "}';"; + + List stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL); + + SQLStatement stmt = stmtList.get(0); + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + String output = SQLUtils.toMySqlString(stmt); + assertEquals( + "CREATE CLUSTERED COLUMNAR INDEX `nation_col_index` ON nation (`n_nationkey`) PARTITION BY HASH (`n_nationkey`) PARTITIONS 1 ENGINE = 'COLUMNAR' USING BTREE KEY_BLOCK_SIZE = 20 COMMENT 'CREATE CCI TEST' ALGORITHM = DEFAULT LOCK = DEFAULT \n" + + "COLUMNAR_OPTIONS='{\n" + + "\t\"DICTIONARY_COLUMNS\":\"N_NAME,N_COMMENT\",\n" + + "\t\"TYPE\":\"SNAPSHOT\",\n" + + "\t\"SNAPSHOT_RETENTION_DAYS\":\"7\",\n" + + "}';", output); } } diff --git a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/createProc/MySqlCreateProcedureTest15.java b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/createProc/MySqlCreateProcedureTest15.java index 25474c1cb..13fdd48a0 100644 --- a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/createProc/MySqlCreateProcedureTest15.java +++ b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/bvt/sql/mysql/createProc/MySqlCreateProcedureTest15.java @@ -181,16 +181,4 @@ public void test_2() throws Exception { "END;", SQLUtils.toMySqlString(stmt)); } - public void test_fake() throws Exception { - String sql = - "UPDATE gx_brand_votelist SET itemid= \"3674133\",brandid= \"1527519\",groupid= \"0\",num= \"1001\",name= \"章丘市万源有色金属铸造有限公司\",introduce= \"铜铝铸件的加工、销售;金属材料、电线、电缆、铝锭、铅锭、铜锭、电解铜板、锌锭、稀有金属的销售。(依法须经批准的项目,经相关部门批准后方可开展经营活动)\",video= \"\",votes=0,status= \"3\",zvote=0,zvote1=0,kouvote=0,truevote=0,yzm= \"2\",shuatime= \"4.0\",shuanum= \"1\",addtime= \"1591346748\",userid= \"1200039\",usertype= \"1\",is_ht= \"1\",is_apply=\"2\",ranking=0,username= \"rew4_2\",erweima= \"code/twocode/202006/05/159134697047696370.png\",editor= \"rew4_2\",edittime= \"1591346970\",shebei= \"0\",note= \"\",sid= \"a7552457d09eeea9\",top_ten= \"2\",email= \"13586786952@qq.com\",tel= \"13953123778\",qq= \"\",remark= \"\",web= \"https://www.tianyancha.com/company/1581157368\",xianzhi= \"0\",wxnum=0,backgift=0,giftvote=0,regCapital= \"9800.00\",actualCapital= \"0.00\",attention=0,tuiguang= \"1\",regyear= \"\",is_new= \"1\",is_sign= \"2\",gongsi_status=\"0\",share_count= \"0\",share_click= \"0\",company_status= \"0\",address= \"\",shenhe_pingtai_status= \"0\",video_url= \"\",anjian_num= \"0\" WHERE itemid = 3674133 AND brandid = 1527519"; - - try { - SQLStatement statement = SQLUtils.parseSingleStatement(sql, DbType.mysql); - } catch (Exception e) { - assertEquals( - "syntax error, error in :'\" statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); + SQLStatement stmt = statementList.get(0); + + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL); + stmt.accept(visitor); + + assertEquals(output, + SQLUtils.toMySqlString(stmt)); + } + } + } diff --git a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/sql/parser/SQLStatementParserTest.java b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/sql/parser/SQLStatementParserTest.java index 7b44b8a9f..3cf17244e 100644 --- a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/sql/parser/SQLStatementParserTest.java +++ b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/sql/parser/SQLStatementParserTest.java @@ -40,121 +40,6 @@ public class SQLStatementParserTest { SQLParserFeature.DRDSBaseline, SQLParserFeature.DrdsMisc, SQLParserFeature.DrdsGSI, SQLParserFeature.DrdsCCL }; - @Test - public void testStartReplicaCheck() { - String sql = "check replica table `testdb`.`testtb` for channel 'test'"; - SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - List statementList = parser.parseStatementList(); - SQLStatement statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` FOR CHANNEL 'test'", statement.toString()); - - sql = "check replica table `testdb` for channel 'test'"; - parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - statementList = parser.parseStatementList(); - statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb` FOR CHANNEL 'test'", statement.toString()); - } - - @Test - public void testPauseReplicaCheck() { - String sql = "check replica table `testdb`.`testtb` pause"; - SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - List statementList = parser.parseStatementList(); - SQLStatement statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` PAUSE", statement.toString()); - - sql = "check replica table `testdb` pause"; - parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - statementList = parser.parseStatementList(); - statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb` PAUSE", statement.toString()); - } - - @Test - public void testContinueReplicaCheck() { - String sql = "check replica table `testdb`.`testtb` continue"; - SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - List statementList = parser.parseStatementList(); - SQLStatement statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` CONTINUE", statement.toString()); - - sql = "check replica table `testdb` continue"; - parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - statementList = parser.parseStatementList(); - statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb` CONTINUE", statement.toString()); - } - - @Test - public void testCancelReplicaCheck() { - String sql = "check replica table `testdb`.`testtb` cancel"; - SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - List statementList = parser.parseStatementList(); - SQLStatement statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` CANCEL", statement.toString()); - - sql = "check replica table `testdb` cancel"; - parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - statementList = parser.parseStatementList(); - statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb` CANCEL", statement.toString()); - } - - @Test - public void testResetReplicaCheck() { - String sql = "check replica table `testdb`.`testtb` reset"; - SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - List statementList = parser.parseStatementList(); - SQLStatement statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` RESET", statement.toString()); - - sql = "check replica table `testdb` reset"; - parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - statementList = parser.parseStatementList(); - statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb` RESET", statement.toString()); - - } - - @Test - public void testShowReplicaCheckProgress() { - String sql = "check replica table `testdb`.`testtb` show progress"; - SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - List statementList = parser.parseStatementList(); - SQLStatement statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` SHOW PROGRESS", statement.toString()); - - sql = "check replica table `testdb` show progress"; - parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - statementList = parser.parseStatementList(); - statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb` SHOW PROGRESS", statement.toString()); - } - - @Test - public void testShowReplicaCheckDiff() { - String sql = "check replica table `testdb`.`testtb` show diff"; - SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - List statementList = parser.parseStatementList(); - SQLStatement statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb`.`testtb` SHOW DIFF", statement.toString()); - - sql = "check replica table `testdb` show diff"; - parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - statementList = parser.parseStatementList(); - statement = statementList.get(0); - Assert.assertEquals("CHECK REPLICA TABLE `testdb` SHOW DIFF", statement.toString()); - } - - @Test - public void testReplicaHashcheck() { - String sql = - "replica hashcheck(col1, col2, col3) from test_tb where ( val1 <= pk1 < val2 AND val3 <= pk2 < val4)"; - SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, FEATURES); - List statementList = parser.parseStatementList(); - SQLStatement statement = statementList.get(0); - } - @Test public void testParseCreateTablePartitionBy() { String sql = diff --git a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/sql/repository/SchemaRepositoryTest.java b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/sql/repository/SchemaRepositoryTest.java index 5a16662a2..9db921bb0 100644 --- a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/sql/repository/SchemaRepositoryTest.java +++ b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/sql/repository/SchemaRepositoryTest.java @@ -1454,4 +1454,61 @@ public void testTableWithBlankName() { System.out.println(tableMeta7); System.out.println(tableMeta8); } + + @Test + public void testTableWithLocalPartition() { + + String sql1 = "ALTER TABLE t_ttl_single\n" + + "LOCAL PARTITION BY RANGE (gmt_modified)\n" + + "STARTWITH '2023-08-20'\n" + + "INTERVAL 1 MONTH\n" + + "EXPIRE AFTER 1\n" + + "PRE ALLOCATE 3\n" + + "PIVOTDATE now()"; + String sql2 = "ALTER TABLE t_ttl_single\n" + + "\t LOCAL PARTITION BY RANGE (gmt_modified)\n" + + "\t STARTWITH '2023-08-20'\n" + + "\t INTERVAL 1 MONTH\n" + + "\t EXPIRE AFTER 1\n" + + "\t PRE ALLOCATE 3\n" + + "\t PIVOTDATE now()"; + List stmtList = SQLUtils.parseStatements(sql1, DbType.mysql, FEATURES); + StringBuffer sb = new StringBuffer(); + stmtList.get(0).output(sb); + Assert.assertEquals(sql2, sb.toString()); + } + + @Test + public void testCreateTableWithLocalPartition() { + + String sql1 = "CREATE TABLE t_local_partition (\n" + + " id bigint NOT NULL AUTO_INCREMENT,\n" + + " gmt_modified DATETIME NOT NULL,\n" + + " PRIMARY KEY (id, gmt_modified)\n" + + ")\n" + + "PARTITION BY HASH(id) PARTITIONS 8\n" + + "LOCAL PARTITION BY RANGE (gmt_modified)\n" + + "STARTWITH '2023-08-20'\n" + + "INTERVAL 1 MONTH\n" + + "EXPIRE AFTER 1\n" + + "PRE ALLOCATE 3\n" + + "PIVOTDATE NOW();"; + String sql2 = "CREATE TABLE t_local_partition (\n" + + "\tid bigint NOT NULL AUTO_INCREMENT,\n" + + "\tgmt_modified DATETIME NOT NULL,\n" + + "\tPRIMARY KEY (id, gmt_modified)\n" + + ")\n" + + "PARTITION BY HASH (id) PARTITIONS 8\n" + + "LOCAL PARTITION BY RANGE (gmt_modified)\n" + + " STARTWITH '2023-08-20'\n" + + " INTERVAL 1 MONTH\n" + + " EXPIRE AFTER 1\n" + + " PRE ALLOCATE 3\n" + + " PIVOTDATE NOW();"; + List stmtList = SQLUtils.parseStatements(sql1, DbType.mysql, FEATURES); + StringBuffer sb = new StringBuffer(); + stmtList.get(0).output(sb); + System.out.println(sb.toString()); + Assert.assertEquals(sql2, sb.toString()); + } } diff --git a/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/sql/visitor/SQLIntegerExprTest.java b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/sql/visitor/SQLIntegerExprTest.java new file mode 100644 index 000000000..d18fa9d2f --- /dev/null +++ b/polardbx-parser/src/test/java/com/alibaba/polardbx/druid/sql/visitor/SQLIntegerExprTest.java @@ -0,0 +1,24 @@ +package com.alibaba.polardbx.druid.sql.visitor; + +import com.alibaba.polardbx.druid.sql.ast.expr.SQLBinaryOpExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLBinaryOperator; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLIntegerExpr; +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigInteger; + +public class SQLIntegerExprTest { + @Test + public void testBigNumber() { + SQLBinaryOpExpr expr = new SQLBinaryOpExpr( + new SQLIntegerExpr(new BigInteger("537456734573625873285347258234657354353425")), + SQLBinaryOperator.LessThan, + new SQLIntegerExpr(new BigInteger("-4457823452837432004173813010418234732483952952798543925")) + ); + + Assert.assertTrue( + "537456734573625873285347258234657354353425 < -4457823452837432004173813010418234732483952952798543925".equals( + expr.toString())); + } +} diff --git a/polardbx-rpc b/polardbx-rpc index 7a193e0a6..58a254a21 160000 --- a/polardbx-rpc +++ b/polardbx-rpc @@ -1 +1 @@ -Subproject commit 7a193e0a6bb750dfcf2e51a5b50a5b4d5cb28d03 +Subproject commit 58a254a21e9c461384c7870034567d196ff8304a diff --git a/polardbx-rule/src/main/java/com/alibaba/polardbx/rule/TddlRuleConfig.java b/polardbx-rule/src/main/java/com/alibaba/polardbx/rule/TddlRuleConfig.java index 74e66956b..5621ec741 100644 --- a/polardbx-rule/src/main/java/com/alibaba/polardbx/rule/TddlRuleConfig.java +++ b/polardbx-rule/src/main/java/com/alibaba/polardbx/rule/TddlRuleConfig.java @@ -18,7 +18,6 @@ import com.alibaba.polardbx.common.model.lifecycle.AbstractLifecycle; import com.alibaba.polardbx.common.model.lifecycle.Lifecycle; -import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.rule.exception.TddlRuleException; diff --git a/polardbx-rule/src/main/java/com/alibaba/polardbx/rule/gms/TddlRuleGmsConfig.java b/polardbx-rule/src/main/java/com/alibaba/polardbx/rule/gms/TddlRuleGmsConfig.java index d812f724c..3f738f7e9 100644 --- a/polardbx-rule/src/main/java/com/alibaba/polardbx/rule/gms/TddlRuleGmsConfig.java +++ b/polardbx-rule/src/main/java/com/alibaba/polardbx/rule/gms/TddlRuleGmsConfig.java @@ -23,6 +23,7 @@ import com.alibaba.polardbx.common.utils.TreeMaps; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.gms.metadb.record.RecordConverter; import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; import com.alibaba.polardbx.gms.metadb.table.TablesExtRecord; @@ -31,7 +32,6 @@ import com.alibaba.polardbx.rule.TableRule; import com.alibaba.polardbx.rule.TddlRuleConfig; import com.alibaba.polardbx.rule.VirtualTableRoot; -import com.alibaba.polardbx.rule.utils.RuleUtils; import com.google.common.collect.Maps; import java.sql.Connection; @@ -51,6 +51,18 @@ public class TddlRuleGmsConfig extends TddlRuleConfig { @Override public void doInit() { + if (ConfigDataMode.isFastMock()) { + // 构建versionIndex + int index = 0; + Map tempIndexMap = new HashMap(); + for (String version : vtrs.keySet()) { + tempIndexMap.put(index, version); + index++; + } + this.versionIndex = tempIndexMap; + this.lastTimestamp = System.currentTimeMillis(); + return; + } initRules(); } diff --git a/polardbx-rule/src/test/java/com/alibaba/polardbx/rule/GroovyRuleTest.java b/polardbx-rule/src/test/java/com/alibaba/polardbx/rule/GroovyRuleTest.java deleted file mode 100644 index cffb55f83..000000000 --- a/polardbx-rule/src/test/java/com/alibaba/polardbx/rule/GroovyRuleTest.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.rule; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -import com.alibaba.polardbx.rule.model.TargetDB; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.google.common.collect.Lists; -import com.alibaba.polardbx.common.exception.TddlException; -import com.alibaba.polardbx.common.model.sqljep.Comparative; -import com.alibaba.polardbx.rule.impl.GroovyRule; -import com.alibaba.polardbx.rule.model.MatcherResult; - -public class GroovyRuleTest extends BaseRuleTest { - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - } - - @Test - public void test_equal() { - Rule dbRule = new GroovyRule("\"db\"+(#id,1,64# % 64).intdiv(4)", false); - Rule tbRule = new GroovyRule("String.valueOf(#id,1,64# % 64)", false); - TableRule vt = new TableRule(); - List> dbRules = new ArrayList>(); - dbRules.add(dbRule); - vt.setDbShardRules(dbRules); - List> tbRules = new ArrayList>(); - tbRules.add(tbRule); - vt.setTbShardRules(tbRules); - vt.init(); - - Choicer choicer = new Choicer(); - choicer.addComparative("ID", new Comparative(Comparative.Equivalent, 18)); - VirtualTableRuleMatcher vtrm = new VirtualTableRuleMatcher(); - MatcherResult mr = vtrm.match(choicer, Lists.newArrayList(), vt, false); - List targetDb = mr.getCalculationResult(); - Assert.assertEquals(1, targetDb.size()); - Assert.assertEquals(1, targetDb.get(0).getTableNames().size()); - Assert.assertEquals("db4", targetDb.get(0).getDbIndex()); - Assert.assertEquals("18", targetDb.get(0).getTableNames().iterator().next()); - } - - @Test - public void testUpdateIn() { - Rule dbRule = new GroovyRule("\"db\"+(#id,1,64# % 64).intdiv(4)", false); - Rule tbRule = new GroovyRule("String.valueOf(#id,1,64# % 64)", false); - TableRule vt = new TableRule(); - List> dbRules = new ArrayList>(); - dbRules.add(dbRule); - vt.setDbShardRules(dbRules); - List> tbRules = new ArrayList>(); - tbRules.add(tbRule); - vt.setTbShardRules(tbRules); - vt.init(); - Choicer choicer = new Choicer(); - choicer.addComparative("ID", or(0, 4, 18, 19, 64)); - VirtualTableRuleMatcher vtrm = new VirtualTableRuleMatcher(); - MatcherResult mr = vtrm.match(choicer, Lists.newArrayList(), vt, false); - List targetDb = mr.getCalculationResult(); - Assert.assertEquals(3, targetDb.size()); - } - - @Test - public void testRange() throws ParseException, TddlException { - Rule dbRule = new GroovyRule("\"db\"+(getCalendar(#time,1_month,2#).get(Calendar.MONTH)%2)", - false); - Rule tbRule = new GroovyRule("\"\"+getCalendar(#time,1_date,365#).get(Calendar.DATE)", false); - TableRule vt = new TableRule(); - List> dbRules = new ArrayList>(); - dbRules.add(dbRule); - vt.setDbShardRules(dbRules); - List> tbRules = new ArrayList>(); - tbRules.add(tbRule); - vt.setTbShardRules(tbRules); - vt.init(); - Choicer choicer = new Choicer(); - SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); - Comparative d1 = new Comparative(Comparative.GreaterThan, df.parse("2010-10-29")); - Comparative d2 = new Comparative(Comparative.LessThan, df.parse("2010-11-03")); - choicer.addComparative("TIME", and(d1, d2)); - VirtualTableRuleMatcher vtrm = new VirtualTableRuleMatcher(); - MatcherResult mr = vtrm.match(choicer, Arrays.asList(new Object[] { 18 }), vt, false); - List targetDb = mr.getCalculationResult(); - Assert.assertEquals(2, targetDb.size()); - } - - @Test - public void testNull() throws ParseException, TddlException { - Rule dbRule = new GroovyRule("\"db\"+(#id,1,64#.toString())", false); - Rule tbRule = new GroovyRule("#id,1,64#.toString()", false); - TableRule vt = new TableRule(); - List> dbRules = new ArrayList>(); - dbRules.add(dbRule); - vt.setDbShardRules(dbRules); - List> tbRules = new ArrayList>(); - tbRules.add(tbRule); - vt.setTbShardRules(tbRules); - vt.init(); - - // null对象的toString()方法计算结果为null - Choicer choicer = new Choicer(); - choicer.addComparative("ID", new Comparative(Comparative.Equivalent, null)); - VirtualTableRuleMatcher vtrm = new VirtualTableRuleMatcher(); - MatcherResult mr = vtrm.match(choicer, Lists.newArrayList(), vt, false); - List targetDb = mr.getCalculationResult(); - Assert.assertEquals(1, targetDb.size()); - Assert.assertEquals(1, targetDb.get(0).getTableNames().size()); - Assert.assertEquals("dbnull", targetDb.get(0).getDbIndex()); - Assert.assertEquals("null", targetDb.get(0).getTableNames().iterator().next()); - } - - @Test - public void testDate() throws ParseException, TddlException { - Rule dbRule = new GroovyRule("\"db\"+(#id,1,64#.toString())", false); - Rule tbRule = new GroovyRule("(getCalendar(#gmt_create,1_date,31#).get(Calendar.DAY_OF_MONTH) % 32) - 1", - false); - TableRule vt = new TableRule(); - List> dbRules = new ArrayList>(); - dbRules.add(dbRule); - vt.setDbShardRules(dbRules); - List> tbRules = new ArrayList>(); - tbRules.add(tbRule); - vt.setTbShardRules(tbRules); - vt.init(); - Choicer choicer = new Choicer(); - choicer.addComparative("ID", new Comparative(Comparative.Equivalent, null)); - choicer.addComparative("GMT_CREATE", new Comparative(Comparative.Equivalent, getDate(2013, 1, 32, 12, 12, 12))); - VirtualTableRuleMatcher vtrm = new VirtualTableRuleMatcher(); - MatcherResult mr = vtrm.match(choicer, Lists.newArrayList(), vt, false); - List targetDb = mr.getCalculationResult(); - System.out.println(targetDb); - } - - @Test - public void testLongMaxValue() throws ParseException, TddlException { - Rule dbRule = new GroovyRule("\"db\"+(#id1,1,64#.longValue() + #id2,1,64#.longValue()).abs() % 1024", - false); - Rule tbRule = new GroovyRule("\"db\"+(#id1,1,64#.longValue() + #id2,1,64#.longValue()) % 1024", - false); - TableRule vt = new TableRule(); - List> dbRules = new ArrayList>(); - dbRules.add(dbRule); - vt.setDbShardRules(dbRules); - List> tbRules = new ArrayList>(); - tbRules.add(tbRule); - vt.setTbShardRules(tbRules); - vt.init(); - Choicer choicer = new Choicer(); - choicer.addComparative("ID1", new Comparative(Comparative.Equivalent, 9223372036854775807l)); - choicer.addComparative("ID2", new Comparative(Comparative.Equivalent, 2l)); - VirtualTableRuleMatcher vtrm = new VirtualTableRuleMatcher(); - MatcherResult mr = vtrm.match(choicer, Lists.newArrayList(), vt, false); - List targetDb = mr.getCalculationResult(); - Assert.assertEquals("db1023", targetDb.get(0).getDbIndex()); - Assert.assertEquals("db-1023", targetDb.get(0).getTableNames().iterator().next()); - } - - @Test - public void testOther() { - Rule dbRule = new GroovyRule("(Math.abs(#nick,1,128#.hashCode()) % 128).intdiv(16)", false); - Rule tbRule = new GroovyRule("Math.abs(#nick,1,128#.hashCode()) % 128", false); - TableRule vt = new TableRule(); - List> dbRules = new ArrayList>(); - dbRules.add(dbRule); - vt.setDbShardRules(dbRules); - List> tbRules = new ArrayList>(); - tbRules.add(tbRule); - vt.setTbShardRules(tbRules); - vt.init(); - Choicer choicer = new Choicer(); - choicer.addComparative("nick", new Comparative(Comparative.Equivalent, "c850002555")); - VirtualTableRuleMatcher vtrm = new VirtualTableRuleMatcher(); - MatcherResult mr = vtrm.match(choicer, Lists.newArrayList(), vt, false); - List targetDb = mr.getCalculationResult(); - System.out.println(targetDb); - } - - @Test - public void testNegativeHash() { - Rule dbRule = new GroovyRule("(Math.abs(#nick,1,128#.hashCode()) % 128).intdiv(16)", false); - Rule tbRule = new GroovyRule("Math.abs((#nick,1,128#.hashCode())/1234.56) % 127", false); - TableRule vt = new TableRule(); - List> dbRules = new ArrayList>(); - dbRules.add(dbRule); - vt.setDbShardRules(dbRules); - List> tbRules = new ArrayList>(); - tbRules.add(tbRule); - vt.setTbShardRules(tbRules); - vt.init(); - Choicer choicer = new Choicer(); - choicer.addComparative("nick", new Comparative(Comparative.Equivalent, "08:5d:dd:50:30:12")); - VirtualTableRuleMatcher vtrm = new VirtualTableRuleMatcher(); - MatcherResult mr = vtrm.match(choicer, Lists.newArrayList(), vt, false); - List targetDb = mr.getCalculationResult(); - Assert.assertEquals("7", targetDb.get(0).getTableNames().iterator().next()); - } - - @Test - public void testFloatAbs() { - Rule dbRule = new GroovyRule("(Math.abs(#nick,1,128#.hashCode()) % 128).intdiv(16)", false); - Rule tbRule = new GroovyRule("Math.abs((#nick,1,128#.hashCode())/1234.56) % 127", false); - TableRule vt = new TableRule(); - List> dbRules = new ArrayList>(); - dbRules.add(dbRule); - vt.setDbShardRules(dbRules); - List> tbRules = new ArrayList>(); - tbRules.add(tbRule); - vt.setTbShardRules(tbRules); - vt.init(); - Choicer choicer = new Choicer(); - choicer.addComparative("nick", new Comparative(Comparative.Equivalent, "08:5d:dd:50:30:12")); - VirtualTableRuleMatcher vtrm = new VirtualTableRuleMatcher(); - MatcherResult mr = vtrm.match(choicer, Lists.newArrayList(), vt, false); - List targetDb = mr.getCalculationResult(); - boolean equals = (Double.valueOf(targetDb.get(0).getTableNames().iterator().next()) - 80.88750648009591) < Double.MIN_VALUE; - Assert.assertTrue(equals); - } - - @SuppressWarnings("deprecation") - public Date getDate(int year, int month, int date, int hrs, int min, int sec) { - return new Date(year, month, date, hrs, min, sec); - } -} diff --git a/polardbx-server/pom.xml b/polardbx-server/pom.xml index 9cf6caa6d..c63308110 100644 --- a/polardbx-server/pom.xml +++ b/polardbx-server/pom.xml @@ -32,12 +32,6 @@ ${project.groupId} polardbx-executor ${project.version} - - - commons-beanutils - commons-beanutils - -
${project.groupId} @@ -59,15 +53,6 @@ logback-classic compile - - log4j - log4j - compile - - - - - com.googlecode.java-ipv6 java-ipv6 diff --git a/polardbx-server/src/main/bin/elastic_scale.sh b/polardbx-server/src/main/bin/elastic_scale.sh new file mode 100644 index 000000000..3fc45be22 --- /dev/null +++ b/polardbx-server/src/main/bin/elastic_scale.sh @@ -0,0 +1,235 @@ +#!/bin/bash + +cygwin=false; +linux=false; +case "`uname`" in + CYGWIN*) + bin_abs_path=`cd $(dirname $0); pwd` + cygwin=true + ;; + Linux*) + bin_abs_path=$(readlink -f $(dirname $0)) + linux=true + ;; + *) + bin_abs_path=`cd $(dirname $0); pwd` + ;; +esac + +get_pid() { + STR=$1 + PID=$2 + if $cygwin; then + JAVA_CMD="$JAVA_HOME\bin\java" + JAVA_CMD=`cygpath --path --unix $JAVA_CMD` + JAVA_PID=`ps |grep $JAVA_CMD |awk '{print $1}'` + else + if $linux; then + if [ ! -z "$PID" ]; then + JAVA_PID=`ps -C java -f --width 2000|grep "$STR"|grep "$PID"|grep -v grep|awk '{print $2}'` + else + JAVA_PID=`ps -C java -f --width 2000|grep "$STR"|grep -v grep|awk '{print $2}'` + fi + else + if [ ! -z "$PID" ]; then + JAVA_PID=`ps aux |grep "$STR"|grep "$PID"|grep -v grep|awk '{print $2}'` + else + JAVA_PID=`ps aux |grep "$STR"|grep -v grep|awk '{print $2}'` + fi + fi + fi + echo $JAVA_PID; +} + +base=${bin_abs_path}/.. +serverPort=3306 +eth0="0.0.0.0" +polardbx=false + +# load env for polardbx by server_env.sh +source /etc/profile +if [ -f /home/admin/bin/server_env.sh ] ; then + source /home/admin/bin/server_env.sh >> /dev/null 2>&1 +fi + +# try to load metadb env by config.properties +config="/home/admin/drds-server/env/config.properties" +if [ -f "$config" ] +then + while IFS='=' read -r key value + do + ## '.' replace as '-' + key=$(echo $key | tr '.' '_') + ## ignore the comment of properties + [[ -z $(echo "$key" | grep -P '\s*#+.*' ) ]] \ + && eval "${key}='${value}'" + done < "$config" +else + echo "metaDb env config not found: $config, then use server_env.sh instead." +fi + +# check polardbx mode +if [ x"$metaDbAddr" != "x" ]; then + polardbx=true +fi + +if [ "$polardbx" != "true" ]; then + echo "Elastic rescale only support PolarDB-X mode" + exit 1 +fi + +if [ x"$serverPort" == "x" ]; then + serverPort=3306 +fi + +TEMP=`getopt -o p:m:c:hD -- "$@"` +eval set -- "$TEMP" +while true ; do + case "$1" in + -h) usage; shift ;; + -p) serverPort=$2; shift 2;; + -m) memory=$2; shift 2 ;; + -c) cpu=$2; shift 2 ;; + --) shift;; + *) + shift; + if [ $# -eq 0 ]; then + break; + fi + ;; + esac +done + +if [ -z "$memory" ] && [ -z "$cpu" ]; then + #at least one argument is required + echo "memory(-m) or cpu(-c) is required" + exit 1 +fi + +pidfile=$base/bin/tddl.pid +name="appName=tddl" +if [ x"$serverPort" != "x" ]; then + pidfile=$base/bin/tddl_${serverPort}.pid + if [ x"$polardbx" == "xtrue" ]; then + pidfile=$base/bin/tddl.pid + fi + name="appName=tddl_$serverPort" +fi + +if [ ! -f "$pidfile" ];then + if [ x$serverPort != "x" ]; then + running=`netstat -tanp 2>/dev/null | grep java |grep "${eth0}:${serverPort} " | awk '{print $NF}' | sort | uniq | wc -l` + if [ $running -eq 0 ]; then + echo "PolarDB-X CN is not running." + exit 1 + else + echo "PolarDB-X CN is running, but with another pid." + exit 1 + fi + else + echo "PolarDB-X CN is not running." + exit 1 + fi +else + #get pid by ps command instead of reading from pidfile + pid=`ps -C java -f --width 2000|grep drds-server|grep 'DserverPort=${serverPort}'|awk '{print $2}'` + if [ x"$other" == "x" ]; then + args=`cat $pidfile | awk -F'#@#' '{print $2}'` + fi + + if [ "$pid" == "" ] ; then + pid=`get_pid "$name"` + fi + + #check current process enables elasticRescale + pid=`ps -C java -f --width 2000|grep ${pid}|grep "ElasticHeapMinHeapSize"|awk '{print $2}'` + if [ x"$pid" == "x" ]; then + echo "PolarDB-X CN is not running with elastic rescale" + exit 1 + fi + + if ps -C java -f --width 2000|grep drds-server|grep ${pid}|grep -q "UseWisp2"; then + echo "Elastic rescale does not support Wisp coroutine" + exit 1 + fi + + echo -e "`hostname`: Online elastic rescale PolarDB-X CN: $pid ... " + + #1. skip checking whether target memory and cores are available. just do the rescale + #2. skip checking whether target value is the same as current value + #3. no need to retry if failed + + if [ -z "$memory" ]; then + echo "Rescaling cores to: ${cpu}C" + output=$(jcmd $pid GC.elastic_heap parallel_gc_threads=$cpu 2>&1) + if echo "$output" | grep -q "succeed"; then + echo "Successfully rescale cores to: $cpu" + exit 0 + else + echo "Failed to rescale cores to: $cpu" + echo "$output" + exit 1 + fi + exit 0 + fi + + if [ -z "$cpu" ]; then + echo "Rescaling memory to: ${memory}G" + if [ $memory -eq 128 ] ; then + heapOpts="soft_min_heap_size=110G soft_max_heap_size=110G" + elif [ $memory -eq 64 ] ; then + heapOpts="soft_min_heap_size=50G soft_max_heap_size=50G" + elif [ $memory -eq 32 ] ; then + heapOpts="soft_min_heap_size=24G soft_max_heap_size=24G" + elif [ $memory -eq 16 ] ; then + heapOpts="soft_min_heap_size=10G soft_max_heap_size=10G" + elif [ $memory -eq 8 ] ; then + heapOpts="soft_min_heap_size=4G soft_max_heap_size=4G" + elif [ $memory -eq 4 ] ; then + heapOpts="soft_min_heap_size=2G soft_max_heap_size=2G" + else + echo "Do not support rescaling memory to: ${memory}G, only supports 4/8/16/32/64/128G currently" + exit 1 + fi + + output=$(jcmd $pid GC.elastic_heap $heapOpts 2>&1) + if echo "$output" | grep -q "succeed"; then + echo "Successfully rescale memory to: ${memory}G" + exit 0 + else + echo "Failed to rescale memory to: ${memory}G" + echo "$output" + exit 1 + fi + exit 0 + fi + + echo "Rescaling to: ${cpu}C${memory}G" + if [ $memory -eq 128 ] ; then + heapOpts="soft_min_heap_size=110G soft_max_heap_size=110G" + elif [ $memory -eq 64 ] ; then + heapOpts="soft_min_heap_size=50G soft_max_heap_size=50G" + elif [ $memory -eq 32 ] ; then + heapOpts="soft_min_heap_size=24G soft_max_heap_size=24G" + elif [ $memory -eq 16 ] ; then + heapOpts="soft_min_heap_size=10G soft_max_heap_size=10G" + elif [ $memory -eq 8 ] ; then + heapOpts="soft_min_heap_size=4G soft_max_heap_size=4G" + elif [ $memory -eq 4 ] ; then + heapOpts="soft_min_heap_size=2G soft_max_heap_size=2G" + else + echo "Do not support rescaling memory to: ${memory}G, only supports 4/8/16/32/64/128G currently" + exit 1 + fi + + output=$(jcmd $pid GC.elastic_heap $heapOpts parallel_gc_threads=$cpu 2>&1) + if echo "$output" | grep -q "succeed"; then + echo "Successfully rescale to: ${cpu}C${memory}G" + exit 0 + else + echo "Failed to rescale memory to: ${cpu}C${memory}G" + echo "$output" + exit 1 + fi + exit 0 +fi \ No newline at end of file diff --git a/polardbx-server/src/main/bin/startup.sh b/polardbx-server/src/main/bin/startup.sh index d767338bc..df626391f 100644 --- a/polardbx-server/src/main/bin/startup.sh +++ b/polardbx-server/src/main/bin/startup.sh @@ -386,6 +386,16 @@ if [ -f $pidfile ] ; then exit 1 fi +# -1: jvm not support +# 0: disable +# 1: <= 64G mode +# 2: > 64G mode +jvmElasticHeapSupport=`$JAVA -XX:+PrintFlagsFinal -version 2> /dev/null | grep ElasticHeapMinHeapSize` +elasticHeapMode=0 +if [ x"$jvmElasticHeapSupport" == "x" ]; then + elasticHeapMode=-1 +fi + str=`file -L $JAVA | grep 64-bit` if [ -n "$str" ]; then freecount=`free -m | grep 'Mem' |awk '{print $2}'` @@ -398,27 +408,63 @@ if [ -n "$str" ]; then freecount=`expr $memory / 1024 / 1024` fi - if [ $freecount -ge 131072 ] ; then - JAVA_OPTS="-server -Xms110g -Xmx110g -XX:MaxDirectMemorySize=16g" - elif [ $freecount -ge 65536 ] ; then - JAVA_OPTS="-server -Xms50g -Xmx50g -XX:MaxDirectMemorySize=12g" - elif [ $freecount -ge 32768 ] ; then - JAVA_OPTS="-server -Xms24g -Xmx24g -XX:MaxDirectMemorySize=6g" - elif [ $freecount -ge 16384 ] ; then - JAVA_OPTS="-server -Xms10g -Xmx10g -XX:MaxDirectMemorySize=3g" - elif [ $freecount -ge 8192 ] ; then - JAVA_OPTS="-server -Xms4g -Xmx4g " - elif [ $freecount -ge 4096 ] ; then - JAVA_OPTS="-server -Xms2g -Xmx2g " - elif [ $freecount -ge 2048 ] ; then - JAVA_OPTS="-server -Xms1024m -Xmx1024m " - elif [ $freecount -ge 1024 ] ; then - JAVA_OPTS="-server -Xms512m -Xmx512m " - elif [ $freecount -ge 512 ] ; then - JAVA_OPTS="-server -Xms256m -Xmx256m " - elif [ $freecount -ge 256 ] ; then - JAVA_OPTS="-server -Xms128m -Xmx128m " + if [ $elasticHeapMode -ge 0 ]; then + if [ $freecount -ge 131072 ] ; then + JAVA_OPTS="-server -Xms110g -Xmx110g -XX:MaxDirectMemorySize=16g " + elasticHeapMode=2 + elif [ $freecount -ge 65536 ] ; then + JAVA_OPTS="-server -Xms50g -Xmx50g -XX:MaxDirectMemorySize=12g " + elasticHeapMode=1 + elif [ $freecount -ge 32768 ] ; then + JAVA_OPTS="-server -Xms24g -Xmx24g -XX:MaxDirectMemorySize=6g " + elasticHeapMode=1 + elif [ $freecount -ge 16384 ] ; then + JAVA_OPTS="-server -Xms10g -Xmx10g -XX:MaxDirectMemorySize=3g " + elasticHeapMode=1 + elif [ $freecount -ge 8192 ] ; then + JAVA_OPTS="-server -Xms4g -Xmx4g " + elasticHeapMode=1 + elif [ $freecount -ge 4096 ] ; then + JAVA_OPTS="-server -Xms2g -Xmx2g " + elasticHeapMode=1 + elif [ $freecount -ge 2048 ] ; then + JAVA_OPTS="-server -Xms1024m -Xmx1024m " + elasticHeapMode=0 + elif [ $freecount -ge 1024 ] ; then + JAVA_OPTS="-server -Xms512m -Xmx512m " + elasticHeapMode=0 + elif [ $freecount -ge 512 ] ; then + JAVA_OPTS="-server -Xms256m -Xmx256m " + elasticHeapMode=0 + elif [ $freecount -ge 256 ] ; then + JAVA_OPTS="-server -Xms128m -Xmx128m " + elasticHeapMode=0 + fi + else + # do not support elasticHeap + if [ $freecount -ge 131072 ] ; then + JAVA_OPTS="-server -Xms110g -Xmx110g -XX:MaxDirectMemorySize=16g" + elif [ $freecount -ge 65536 ] ; then + JAVA_OPTS="-server -Xms50g -Xmx50g -XX:MaxDirectMemorySize=12g" + elif [ $freecount -ge 32768 ] ; then + JAVA_OPTS="-server -Xms24g -Xmx24g -XX:MaxDirectMemorySize=6g" + elif [ $freecount -ge 16384 ] ; then + JAVA_OPTS="-server -Xms10g -Xmx10g -XX:MaxDirectMemorySize=3g" + elif [ $freecount -ge 8192 ] ; then + JAVA_OPTS="-server -Xms4g -Xmx4g " + elif [ $freecount -ge 4096 ] ; then + JAVA_OPTS="-server -Xms2g -Xmx2g " + elif [ $freecount -ge 2048 ] ; then + JAVA_OPTS="-server -Xms1024m -Xmx1024m " + elif [ $freecount -ge 1024 ] ; then + JAVA_OPTS="-server -Xms512m -Xmx512m " + elif [ $freecount -ge 512 ] ; then + JAVA_OPTS="-server -Xms256m -Xmx256m " + elif [ $freecount -ge 256 ] ; then + JAVA_OPTS="-server -Xms128m -Xmx128m " + fi fi + else echo "not support 32-bit java startup" exit @@ -427,11 +473,31 @@ fi #2.6.32-220.23.2.al.ali1.1.alios6.x86_64 not support Wisp2 if [ "$wisp" == "wisp" ] && [ "$KERNEL_VERSION" != "2.6.32-220.23.2.al.ali1.1.alios6.x86_64" ]; then JAVA_OPTS="$JAVA_OPTS -XX:+UnlockExperimentalVMOptions -XX:+UseWisp2 -Dio.grpc.netty.shaded.io.netty.transport.noNative=true -Dio.netty.transport.noNative=true" + JAVA_OPTS="$JAVA_OPTS -XX:+UnlockExperimentalVMOptions -XX:+UseWisp2" + +fi + +#disable netty-native in order to support Wisp2 +TDDL_OPTS=" $TDDL_OPTS -Dio.grpc.netty.shaded.io.netty.transport.noNative=true -Dio.netty.transport.noNative=true" +#disable logback in Wisp2 +TDDL_OPTS=" $TDDL_OPTS -Dcom.alibaba.wisp.threadAsWisp.black=name:logback-*" + +if [ "$cgroup" == "cgroup" ] ; then + JAVA_OPTS="$JAVA_OPTS -XX:+MultiTenant -XX:+TenantCpuThrottling -XX:+TenantCpuAccounting" + TDDL_OPTS=" $TDDL_OPTS -Dcom.alibaba.polardbx.cgroup=true -Dcom.alibaba.wisp.threadAsWisp.black=name:ap-processor-*;logback-*" + echo "jgroup path=$JGROUP, dockerId=$dockerId" + + if [ x"$dockerId" != "x" ]; then + JAVA_OPTS="$JAVA_OPTS -Dcom.alibaba.tenant.jgroup.rootGroup=docker/$dockerId" + sudo $JGROUP -u admin -g admin -r docker/$dockerId + else + sudo $JGROUP -u admin -g admin + fi fi # in docker container, limit cpu cores if [ x"$cpu_cores" != "x" ]; then - JAVA_OPTS="$JAVA_OPTS -XX:ActiveProcessorCount=$cpu_cores" + JAVA_OPTS="$JAVA_OPTS -XX:ActiveProcessorCount=$cpu_cores -XX:ParallelGCThreads=$cpu_cores" fi #https://workitem.aone.alibaba-inc.com/req/33334239 @@ -445,8 +511,6 @@ else JAVA_OPTS="$JAVA_OPTS -XX:+UseFastAccessorMethods" fi -# For CMS and ParNew -#JAVA_OPTS="$JAVA_OPTS -XX:SurvivorRatio=10 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75" # For G1 JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:+UseGCOverheadLimit -XX:+ExplicitGCInvokesConcurrent " @@ -468,7 +532,6 @@ else JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime" fi JAVA_OPTS=" $JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$base_log -XX:+CrashOnOutOfMemoryError -XX:ErrorFile=$base_log/hs_err_pid%p.log" -# JAVA_OPTS=" $JAVA_OPTS -XX:+UseWisp2" TDDL_OPTS=" $TDDL_OPTS -Dlogback.configurationFile=$logback_configurationFile -Dtddl.conf=$tddl_conf" if [ -e $tddl_conf -a -e $logback_configurationFile ] diff --git a/polardbx-server/src/main/conf/logback.xml b/polardbx-server/src/main/conf/logback.xml index a2e0d17ef..80fc24953 100644 --- a/polardbx-server/src/main/conf/logback.xml +++ b/polardbx-server/src/main/conf/logback.xml @@ -256,6 +256,37 @@ + + + app + tddl + + + + ${loggerRoot:-..}/logs/${app}/ttl-task.log + + + + + ${loggerRoot:-..}/logs/${app}/%d{yyyy-MM-dd}/ttl-task-%d{yyyy-MM-dd}-%i.log.gz + + + + 512MB + + 30 + 10GB + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} - [%X{CONNECTION}] %msg%n + + + + + app @@ -987,6 +1018,10 @@ + + + + diff --git a/polardbx-server/src/main/conf/server.properties b/polardbx-server/src/main/conf/server.properties index 606454cec..14d5819c1 100644 --- a/polardbx-server/src/main/conf/server.properties +++ b/polardbx-server/src/main/conf/server.properties @@ -7,10 +7,16 @@ processorKillExecutor=128 syncExecutor=128 managerExecutor=128 serverExecutor=1024 +timeUpdatePeriod=20 idleTimeout= trustedIps=127.0.0.1 slowSqlTime=1000 maxConnection=20000 +flowControlThresold=100 +flowControlBuffer=1024 +#trustedIps=127.0.0.1,10.200.248.19,10.132.97.129,10.132.98.90,10.132.99.189 +#whiteIps= +#blackIps= allowManagerLogin=1 allowCrossDbQuery=true enableLogicalDbWarmmingUp=true @@ -20,3 +26,6 @@ metaDbXprotoPort=13306 metaDbUser=my_polarx metaDbName=polardbx_meta_db_polardbx instanceId=polardbx-polardbx + +socketSendBuffer=0 +socketRecvBuffer=0 \ No newline at end of file diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/CobarPrivileges.java b/polardbx-server/src/main/java/com/alibaba/polardbx/CobarPrivileges.java index c3b4ef10c..70183b33f 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/CobarPrivileges.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/CobarPrivileges.java @@ -16,15 +16,16 @@ package com.alibaba.polardbx; +import com.alibaba.polardbx.common.model.DbPriv; +import com.alibaba.polardbx.common.model.TbPriv; +import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.common.CommonUtils; import com.alibaba.polardbx.config.IUserHostDefination; import com.alibaba.polardbx.config.SchemaConfig; import com.alibaba.polardbx.config.UserConfig; import com.alibaba.polardbx.net.handler.Privileges; -import com.alibaba.polardbx.common.model.DbPriv; -import com.alibaba.polardbx.common.model.TbPriv; import com.taobao.tddl.common.privilege.EncrptPassword; -import com.alibaba.polardbx.config.ConfigDataMode; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import java.util.Collections; diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/CobarServer.java b/polardbx-server/src/main/java/com/alibaba/polardbx/CobarServer.java index f6a7d45dd..19f019f2b 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/CobarServer.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/CobarServer.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx; +import com.alibaba.polardbx.common.TddlConstants; import com.alibaba.polardbx.common.TddlConstants; import com.alibaba.polardbx.common.TddlNode; import com.alibaba.polardbx.common.cdc.CdcManagerHelper; @@ -151,6 +152,19 @@ public static final CobarServer getInstance() { protected String rpcPort; private CobarServer() { + if (ConfigDataMode.isMock()) { + // For UT only. + this.config = null; + this.scheduler = null; + this.syncExecutor = null; + this.managerExecutor = null; + this.killExecutor = null; + this.timerTaskExecutor = null; + this.serverExecutor = null; + this.isOnline = null; + this.forceOffline = null; + return; + } this.config = new CobarConfig(); SystemConfig system = config.getSystem(); checkSslEnable(system); @@ -263,25 +277,43 @@ protected void doInit() { } } - private static void tryInitServerVariables() throws SQLException { + protected static void tryInitServerVariables() throws SQLException { // If this is a new instance, not an upgraded one, set some aggressive variables for it. if (isNewInstance()) { - Properties properties = new Properties(); + // For CN: + Properties cnProperties = new Properties(); // Enable A/B table mechanism for trx log table. - properties.setProperty(ConnectionProperties.TRX_LOG_METHOD, String.valueOf(1)); + cnProperties.setProperty(ConnectionProperties.TRX_LOG_METHOD, String.valueOf(1)); // Enable auto-commit-tso trx by default. - properties.setProperty(ConnectionProperties.ENABLE_AUTO_COMMIT_TSO, "true"); + cnProperties.setProperty(ConnectionProperties.ENABLE_AUTO_COMMIT_TSO, "true"); // Ignore setting NO_TRANSACTION. - properties.setProperty(ConnectionProperties.IGNORE_TRANSACTION_POLICY_NO_TRANSACTION, "true"); + cnProperties.setProperty(ConnectionProperties.IGNORE_TRANSACTION_POLICY_NO_TRANSACTION, "true"); + // Collect accurate information_schema.tables statistics. + cnProperties.setProperty(ConnectionProperties.ENABLE_ACCURATE_INFO_SCHEMA_TABLES, "true"); + cnProperties.setProperty(ConnectionProperties.ENABLE_INFO_SCHEMA_TABLES_STAT_COLLECTION, "true"); + // Enable auto force index + cnProperties.setProperty(ConnectionProperties.ENABLE_AUTO_FORCE_INDEX, "true"); + cnProperties.setProperty(ConnectionProperties.IGNORE_TRANSACTION_POLICY_NO_TRANSACTION, "true"); + // Disable full table scan for duplicate check of upsert on table without UGSI + cnProperties.setProperty(ConnectionProperties.DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN, "false"); + + //忽略事务情况下,DML串行执行 + cnProperties.setProperty(ConnectionProperties.ENABLE_DML_GROUP_CONCURRENT_IN_TRANSACTION, "true"); //Disable udf - properties.setProperty(TddlConstants.ENABLE_JAVA_UDF, "false"); + cnProperties.setProperty(TddlConstants.ENABLE_JAVA_UDF, "false"); + + + // enable strict set global + cnProperties.setProperty(TddlConstants.ENABLE_STRICT_SET_GLOBAL, "true"); // Update inst config using insert ignore. try (Connection metaDbConn = MetaDbDataSource.getInstance().getConnection()) { - InstConfigAccessor instConfigAccessor = new InstConfigAccessor(); - instConfigAccessor.setConnection(metaDbConn); - instConfigAccessor.addInstConfigs(InstIdUtil.getInstId(), properties, true); + if (!cnProperties.isEmpty()) { + InstConfigAccessor instConfigAccessor = new InstConfigAccessor(); + instConfigAccessor.setConnection(metaDbConn); + instConfigAccessor.addInstConfigs(InstIdUtil.getInstId(), cnProperties, true); + } } catch (Throwable t) { logger.error("Try init server variables failed.", t); } @@ -323,7 +355,7 @@ private static boolean isOn(String paramValue) { return "on".equalsIgnoreCase(paramValue) || "true".equalsIgnoreCase(paramValue); } - private static boolean isNewInstance() { + protected static boolean isNewInstance() { try (Connection metaDbConn = MetaDbDataSource.getInstance().getConnection()) { InstConfigAccessor instConfigAccessor = new InstConfigAccessor(); instConfigAccessor.setConnection(metaDbConn); diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcDdlMarkSyncAction.java b/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcDdlMarkSyncAction.java index 490a00147..02622d678 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcDdlMarkSyncAction.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcDdlMarkSyncAction.java @@ -21,9 +21,11 @@ import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; import com.alibaba.polardbx.executor.sync.ISyncAction; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.gms.topology.SystemDbHelper; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.server.conn.InnerConnection; import lombok.Data; import lombok.SneakyThrows; @@ -48,10 +50,11 @@ public class CdcDdlMarkSyncAction implements ISyncAction { String metaInfo; CdcDdlMarkVisibility visibility; String ext; + boolean recordCommitTso; public CdcDdlMarkSyncAction(Long jobId, String sqlKind, String schema, String tableName, String ddlSql, String metaInfo, - CdcDdlMarkVisibility visibility, String ext) { + CdcDdlMarkVisibility visibility, String ext, boolean recordCommitTso) { this.jobId = jobId; this.sqlKind = sqlKind; this.schema = schema; @@ -60,25 +63,39 @@ public CdcDdlMarkSyncAction(Long jobId, String sqlKind, String schema, String ta this.metaInfo = metaInfo; this.visibility = visibility; this.ext = ext; + this.recordCommitTso = recordCommitTso; } @SneakyThrows @Override public ResultCursor sync() { + ResultCursor resultCursor = null; if (ConfigDataMode.isPolarDbX() && ConfigDataMode.isMasterMode() && ExecUtils.hasLeadership(null)) { - try (Connection connection = new InnerConnection(SystemDbHelper.CDC_DB_NAME)) { - doSync(connection); + try (Connection connection = new InnerConnection(SystemDbHelper.CDC_DB_NAME, recordCommitTso)) { + long tso = doSync(connection); + if (recordCommitTso) { + return buildReturnCursor(tso); + } } } else { throw new TddlRuntimeException(ErrorCode.ERR_SYNC_PRIVILEGE_FAILED, "current node is not leader, can`t do cdc ddl mark Action, with sql " + ddlSql); } - return null; + return resultCursor; + } + + public ResultCursor buildReturnCursor(long tso) { + //如果需要记录commit tso,返回结果 + ArrayResultCursor result = new ArrayResultCursor("cdc_mark_result"); + result.addColumn("COMMIT_TSO", DataTypes.LongType); + result.initMeta(); + result.addRow(new Object[] {tso}); + return result; } @SneakyThrows - public void doSync(Connection connection) { - CdcTableUtil.getInstance() + public long doSync(Connection connection) { + return CdcTableUtil.getInstance() .insertDdlRecord(connection, jobId, sqlKind, schema, tableName, ddlSql, metaInfo, visibility, ext); } } diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcManager.java b/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcManager.java index f23e3a0f6..9f8584785 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcManager.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcManager.java @@ -67,6 +67,7 @@ import com.alibaba.polardbx.gms.metadb.limit.LimitValidator; import com.alibaba.polardbx.gms.metadb.table.TablesExtAccessor; import com.alibaba.polardbx.gms.metadb.table.TablesExtRecord; +import com.alibaba.polardbx.gms.partition.TablePartitionAccessor; import com.alibaba.polardbx.gms.partition.TablePartitionConfig; import com.alibaba.polardbx.gms.partition.TablePartitionConfigUtil; import com.alibaba.polardbx.gms.topology.DbGroupInfoAccessor; @@ -136,6 +137,7 @@ import static com.alibaba.polardbx.executor.ddl.ImplicitTableGroupUtil.tryAttachImplicitTableGroup; import static com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcSqlUtils.SQL_PARSE_FEATURES; import static com.alibaba.polardbx.executor.utils.failpoint.FailPointKey.FP_INJECT_FAILURE_TO_CDC_AFTER_ADD_NEW_GROUP; +import static com.alibaba.polardbx.executor.utils.failpoint.FailPointKey.FP_OVERRIDE_NOW; import static com.alibaba.polardbx.gms.metadb.cdc.BinlogCommandRecord.COMMAND_STATUS.INITIAL; import static com.alibaba.polardbx.gms.metadb.cdc.BinlogCommandRecord.COMMAND_STATUS.READY; import static com.alibaba.polardbx.gms.metadb.cdc.BinlogCommandRecord.COMMAND_STATUS.SUCCESS; @@ -305,12 +307,18 @@ public void notifyDdl(CdcDDLContext cdcDDLContext) { Map extendParams = cdcDDLContext.getExtendParams(); // 对于if not exists 和 if exists,外部没有对长度进行判断,此处进行判断 - checkLength(schemaName, tableName); + if (!cdcDDLContext.isSequenceDdl()) { + checkLength(schemaName, tableName); + } boolean isGSI = isDdlOnGsi(cdcDDLContext, extendParams); extendParams.put(CDC_IS_GSI, isGSI); + boolean isCCI = isDdlOnCci(cdcDDLContext, extendParams); + + extendParams.put(CDC_IS_CCI, isCCI); + // check if ignore if (!checkDdl(schemaName, ddlSql, cdcDDLContext, extendParams)) { return; @@ -323,6 +331,9 @@ public void notifyDdl(CdcDDLContext cdcDDLContext) { checkSleep(extendParams); + final boolean recordCommitTso = extendParams.containsKey(CDC_MARK_RECORD_COMMIT_TSO) && + Boolean.parseBoolean(extendParams.get(CDC_MARK_RECORD_COMMIT_TSO).toString()); + Future future = managerCoreExecutor.submit(() -> { CdcManager.this.checkState(); synchronized (CdcManager.this) { @@ -331,7 +342,7 @@ public void notifyDdl(CdcDDLContext cdcDDLContext) { if (Thread.interrupted()) { throw new RuntimeException("cdc ddl mark is interrupted"); } - try (Connection connection = prepareConnection()) { + try (Connection connection = prepareConnection(recordCommitTso)) { // 虽然checkStorageChangeExecutor可以定时扫描Storage的变化,但这是一个异步操作,一旦Storage插入Storage_info表之后,就会 // 立即生效,所以,在checkStorageChangeExecutor扫描到变化之前,在新的Storage上可能已经发生了逻辑ddl和dml操作,所以这里加入 // 一个Barrier,每次ddl打标前,调用一下checkStorageChange方法,保证下游先收到storage的变化,再收到新的逻辑Schema变化 @@ -500,8 +511,24 @@ private boolean isGsiTable(CdcDDLContext cdcDDLContext) { return CBOUtil.isGsi(schemaName, tableName); } + public boolean isDdlOnCci(CdcDDLContext cdcDDLContext, Map extendParams) { + Boolean isCci = (Boolean) extendParams.get(ICdcManager.CDC_IS_CCI); + if (isCci != null && isCci) { + return true; + } + String schemaName = cdcDDLContext.getSchemaName(); + String tableName = cdcDDLContext.getTableName(); + TablePartitionAccessor tablePartitionAccessor = new TablePartitionAccessor(); + TablesExtAccessor tablesExtAccessor = new TablesExtAccessor(); + return CBOUtil.isCci(schemaName, tableName, tablePartitionAccessor, tablesExtAccessor); + } + private Connection prepareConnection() throws SQLException { - return new InnerConnection(SystemDbHelper.CDC_DB_NAME); + return prepareConnection(false); + } + + private Connection prepareConnection(boolean recordCommitTso) throws SQLException { + return new InnerConnection(SystemDbHelper.CDC_DB_NAME, recordCommitTso); } private List queryDdl(Connection connection, CdcDDLContext context) throws SQLException { @@ -519,10 +546,10 @@ private List queryDdlByJobId(Connection connection, CdcDDLContext context.getJobId()); } - private void recordDdl(Connection connection, String schema, String tableName, String sqlKind, String ddlSql, - CdcDDLContext cdcDDLContext, - CdcDdlMarkVisibility visibility, - Map extendParams) + public void recordDdl(Connection connection, String schema, String tableName, String sqlKind, String ddlSql, + CdcDDLContext cdcDDLContext, + CdcDdlMarkVisibility visibility, + Map extendParams) throws SQLException { if (cdcDDLContext.getJobId() != null) { // 如果job不为空,则需要进行幂等判断,防止重复执行 @@ -543,6 +570,28 @@ private void recordDdl(Connection connection, String schema, String tableName, S logger.warn("insert ddl record for job_id " + getJobId(cdcDDLContext)); } + DDLExtInfo extInfo = buildExtInfo(schema, tableName, ddlSql, cdcDDLContext, extendParams); + + boolean recordCommitTso = false; + if (extendParams.containsKey(CDC_MARK_RECORD_COMMIT_TSO)) { + recordCommitTso = Boolean.parseBoolean(extendParams.get(CDC_MARK_RECORD_COMMIT_TSO).toString()); + } + long commitTso = doFinalMark(connection, getJobId(cdcDDLContext), sqlKind, schema, tableName, ddlSql, + buildMetaInfo(cdcDDLContext.isRefreshTableMetaInfo(), + schema, + tableName, + sqlKind, + extendParams, + cdcDDLContext.getNewTableTopology(), + cdcDDLContext.getTablesExtInfoPair()), + visibility, + JSONObject.toJSONString(extInfo), recordCommitTso); + cdcDDLContext.setCommitTso(commitTso); + } + + public DDLExtInfo buildExtInfo(String schema, String tableName, String ddlSql, CdcDDLContext cdcDDLContext, + Map extendParams) + throws SQLException { DDLExtInfo extInfo = new DDLExtInfo(); extInfo.setTaskId(cdcDDLContext.getTaskId()); extInfo.setCreateSql4PhyTable(tryBuildCreateSql4PhyTable(schema, tableName, extendParams, cdcDDLContext)); @@ -560,13 +609,13 @@ private void recordDdl(Connection connection, String schema, String tableName, S } if (extendParams.containsKey(CDC_ORIGINAL_DDL)) { extInfo.setOriginalDdl(extendParams.get(CDC_ORIGINAL_DDL).toString()); - if (StringUtils.isNotBlank(extInfo.getOriginalDdl())) { - checkToString(extInfo.getOriginalDdl()); - } } if (extendParams.containsKey(CDC_IS_GSI)) { extInfo.setGsi((Boolean) extendParams.get(CDC_IS_GSI)); } + if (extendParams.containsKey(CDC_IS_CCI)) { + extInfo.setCci((Boolean) extendParams.get(CDC_IS_CCI)); + } if (extendParams.containsKey(CDC_GROUP_NAME)) { extInfo.setGroupName(extendParams.get(CDC_GROUP_NAME).toString()); } @@ -600,30 +649,47 @@ private void recordDdl(Connection connection, String schema, String tableName, S extInfo.setDdlScope(((DdlScope) extendParams.get(CDC_DDL_SCOPE)).getValue()); } + if (extendParams.containsKey(FP_OVERRIDE_NOW)) { + extInfo.addPolarxVariable(FP_OVERRIDE_NOW, extendParams.get(FP_OVERRIDE_NOW).toString()); + } + + if (extendParams.containsKey(FP_OVERRIDE_NOW)) { + extInfo.addPolarxVariable(FP_OVERRIDE_NOW, extendParams.get(FP_OVERRIDE_NOW).toString()); + } + tryAttachImplicitTableGroupInfo(schema, tableName, ddlSql, extInfo, extendParams); - doFinalMark(connection, getJobId(cdcDDLContext), sqlKind, schema, tableName, ddlSql, - buildMetaInfo(cdcDDLContext.isRefreshTableMetaInfo(), - schema, - tableName, - sqlKind, - extendParams, - cdcDDLContext.getNewTableTopology(), - cdcDDLContext.getTablesExtInfoPair()), - visibility, - JSONObject.toJSONString(extInfo)); + if (StringUtils.isNotBlank(extInfo.getOriginalDdl())) { + checkToString(extInfo.getOriginalDdl()); + } + + return extInfo; } - private void doFinalMark(Connection connection, Long jobId, String sqlKind, String schema, String tableName, - String ddlSql, String metaInfo, CdcDdlMarkVisibility visibility, String ext) { + /** + * @param recordCommitTso 是否需要记录commitTso + * @return 返回commitTso + */ + private long doFinalMark(Connection connection, Long jobId, String sqlKind, String schema, String tableName, + String ddlSql, String metaInfo, CdcDdlMarkVisibility visibility, String ext, + boolean recordCommitTso) { + long commitTso = -1L; CdcDdlMarkSyncAction syncAction = new CdcDdlMarkSyncAction( - jobId, sqlKind, schema, tableName, ddlSql, metaInfo, visibility, ext); - if (ExecUtils.hasLeadership(null)) { - syncAction.doSync(connection); + jobId, sqlKind, schema, tableName, ddlSql, metaInfo, visibility, ext, recordCommitTso); + //需要记录commitTso的,也不用sync到主节点进行执行。 + if (ExecUtils.hasLeadership(null) || recordCommitTso) { + commitTso = syncAction.doSync(connection); } else { boolean success = false; try { String leaderKey = ExecUtils.getLeaderKey(null); - SyncManagerHelper.sync(syncAction, SystemDbHelper.CDC_DB_NAME, leaderKey); + List> result = + SyncManagerHelper.sync(syncAction, SystemDbHelper.CDC_DB_NAME, leaderKey); + if (result != null && result.size() > 0) { + Object object = result.get(0).get("COMMIT_TSO"); + if (object != null) { + commitTso = (Long) object; + } + } success = true; } catch (Throwable e) { logger.error( @@ -632,9 +698,10 @@ private void doFinalMark(Connection connection, Long jobId, String sqlKind, Stri } if (!success) { - syncAction.doSync(connection); + commitTso = syncAction.doSync(connection); } } + return commitTso; } private void tryAttachImplicitTableGroupInfo(String schema, String tableName, String ddlSql, diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcTableUtil.java b/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcTableUtil.java index cfa2e28ab..92b667c92 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcTableUtil.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CdcTableUtil.java @@ -133,6 +133,9 @@ public class CdcTableUtil { String .format("SELECT COUNT(ID) FROM %s WHERE INSTRUCTION_TYPE =? and INSTRUCTION_ID =?", CDC_INSTRUCTION_TABLE); + public final static String QUERY_CDC_DDL_RECORD_LIMIT_1 = + "SELECT JOB_ID,EXT FROM `" + CDC_DDL_RECORD_TABLE + "` LIMIT 1"; + private CdcTableUtil() { } @@ -234,7 +237,10 @@ public List queryDdlRecordByJobId(@NotNull Connection connection, } } - public void insertDdlRecord(Connection connection, Long jobId, String sqlKind, String schema, String tableName, + /** + * @return 如果时TSO事务,返回insert的commitTso,该值意味着是该打标sql在binlog事件中的tso值 + */ + public long insertDdlRecord(Connection connection, Long jobId, String sqlKind, String schema, String tableName, String ddlSql, String metaInfo, CdcDdlMarkVisibility visibility, String ext) throws SQLException { if (ddlSql.lastIndexOf(";") == (ddlSql.length() - 1)) { @@ -257,6 +263,11 @@ public void insertDdlRecord(Connection connection, Long jobId, String sqlKind, S stmt.executeUpdate(); } }); + if (connection instanceof InnerConnection) { + return ((InnerConnection) connection).getCommitTso(); + } else { + return -1L; + } } /** @@ -300,7 +311,8 @@ public boolean isFileStoreTable(String schemaName, String tableName) { TablesAccessor tablesAccessor = new TablesAccessor(); tablesAccessor.setConnection(metaDbConn); TablesRecord tablesRecord = tablesAccessor.query(schemaName, tableName, false); - return tablesRecord != null && Engine.isFileStore(tablesRecord.engine); + return tablesRecord != null && Engine.isFileStore(tablesRecord.engine) + && !Engine.supportColumnar(Engine.of(tablesRecord.engine)); } } diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CommandScanner.java b/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CommandScanner.java index 961092f69..bf9180e8d 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CommandScanner.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/CommandScanner.java @@ -145,12 +145,17 @@ private void buildCdcMetaSnapshot(BinlogCommandRecord commandRecord) { logger.warn("build cdc meta snapshot finished."); } - private void buildSnapshotAndSend(BinlogCommandRecord commandRecord, ICdcManager.InstructionType instructionType, - String instructionId) throws SQLException, InterruptedException { + boolean buildSnapshotAndSend(BinlogCommandRecord commandRecord, ICdcManager.InstructionType instructionType, + String instructionId) throws SQLException, InterruptedException { long sleepTime = 10 * 1000; long round = 0; while (true) { + if (!ExecUtils.hasLeadership(null)) { + logger.warn("this node is not leader, will exit loop."); + return false; + } + round++; // 1. get pre ddl perform version @@ -168,12 +173,6 @@ private void buildSnapshotAndSend(BinlogCommandRecord commandRecord, ICdcManager try (Connection metaDbLockConn = MetaDbDataSource.getInstance().getConnection()) { // forbidden create/drop database ddl sql metaDbLockConn.setAutoCommit(false); -// try { -// LockUtil.acquireMetaDbLockByForUpdate(metaDbLockConn); -// } catch (Throwable ex) { -// throw new TddlRuntimeException(ErrorCode.ERR_GMS_GENERIC, ex, -// "Get metaDb lock timeout during cdc init"); -// } LockUtil.waitToAcquireMetaDbLock(String.format("Get metaDb lock timeout during cdc init"), metaDbLockConn); @@ -198,7 +197,7 @@ private void buildSnapshotAndSend(BinlogCommandRecord commandRecord, ICdcManager LockUtil.releaseMetaDbLockByCommit(metaDbLockConn); if (success.get()) { - break; + return true; } else { if (timeout.get()) { logger.warn("ddl version check time out, will retry."); diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/MetaBuilder.java b/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/MetaBuilder.java index cc4e076c5..3e4dd3a29 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/MetaBuilder.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/cdc/MetaBuilder.java @@ -42,10 +42,12 @@ import com.alibaba.polardbx.gms.util.InstIdUtil; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; +import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; import com.alibaba.polardbx.optimizer.partition.common.PartitionTableType; import com.alibaba.polardbx.rule.model.TargetDB; import com.alibaba.polardbx.server.conn.InnerConnection; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; import java.sql.Connection; @@ -259,19 +261,27 @@ private static void checkLogicDbMetaInternal(String logicSchema, LogicMeta.Logic }); } - private static Connection getPhyConnection(String schemaName, String groupName) + static Connection getPhyConnection(String schemaName, String groupName) throws SQLException { ExecutorContext executorContext = ExecutorContext.getContext(schemaName); if (executorContext != null) { IGroupExecutor groupExecutor = executorContext.getTopologyHandler().get(groupName); if (groupExecutor != null && groupExecutor.getDataSource() instanceof TGroupDataSource) { TGroupDataSource dataSource = (TGroupDataSource) groupExecutor.getDataSource(); - return dataSource.getConnection(); + TGroupDirectConnection connection = dataSource.getConnection(); + return connection == null ? null : preparePhyConnection(connection); } } return null; } + static TGroupDirectConnection preparePhyConnection(TGroupDirectConnection connection) throws SQLException { + Map variables = Maps.newHashMap(); + variables.put("sql_mode", ""); + connection.setServerVariables(variables); + return connection; + } + private static LogicMeta.LogicTableMeta buildLogicTableMetaInternal(String schemaName, TableMode tableMode, String tableName, diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/config/ServerConfigManager.java b/polardbx-server/src/main/java/com/alibaba/polardbx/config/ServerConfigManager.java index 49384942b..3481ec839 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/config/ServerConfigManager.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/config/ServerConfigManager.java @@ -17,6 +17,9 @@ package com.alibaba.polardbx.config; import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; import java.util.ArrayList; import java.util.List; @@ -24,6 +27,8 @@ import com.alibaba.polardbx.CobarServer; import com.alibaba.polardbx.common.DefaultSchema; +import com.alibaba.polardbx.common.ddl.Job; +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.model.Group; @@ -34,10 +39,12 @@ import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.common.utils.timezone.InternalTimeZone; import com.alibaba.polardbx.executor.ddl.sync.JobRequest; +import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; import com.alibaba.polardbx.gms.topology.DbGroupInfoAccessor; import com.alibaba.polardbx.gms.topology.DbGroupInfoRecord; import com.alibaba.polardbx.matrix.config.MatrixConfigHolder; +import com.alibaba.polardbx.matrix.jdbc.TConnection; import com.alibaba.polardbx.matrix.jdbc.TDataSource; import com.alibaba.polardbx.matrix.jdbc.utils.TDataSourceInitUtils; import com.alibaba.polardbx.optimizer.config.server.IServerConfigManager; @@ -45,6 +52,7 @@ import java.util.List; import java.util.Map; +import com.alibaba.polardbx.server.conn.InnerConnection; import java.util.List; import java.util.Map; @@ -205,4 +213,86 @@ public List getLoadedSchemas() { return loadedSchemas; } + @Override + public Object getTransConnection(String schema) throws SQLException { + return new InnerConnection(schema); + } + + @Override + public Object getTransConnection(String schema, Map sessionVariables) throws SQLException { + return new InnerConnection(schema, false, sessionVariables); + } + + @Override + public void closeTransConnection(Object transConn) throws SQLException { + ((InnerConnection) transConn).close(); + } + + @Override + public int executeBackgroundDmlByTransConnection(String sql, String schema, + InternalTimeZone timeZone, + Object transConn) { + InnerConnection connection = (InnerConnection) transConn; + int arows = 0; + Exception ex = null; + try (Statement stmt = connection.createStatement()) { + arows = stmt.executeUpdate(sql); + return arows; + } catch (SQLException e) { + ex = e; + throw new TddlNestableRuntimeException(e); + } finally { + if (ex == null) { + connection.releaseAutoSavepoint(); + } + } + + } + + @Override + public List> executeBackgroundQueryByTransConnection(String sql, String schema, + InternalTimeZone timeZone, + Object transConn) { + InnerConnection connection = (InnerConnection) transConn; + List> result = null; + Exception ex = null; + + try (Statement stmt = connection.createStatement()) { + ResultSet rs = stmt.executeQuery(sql); + result = ExecUtils.resultSetToList(rs); + return result; + } catch (SQLException e) { + ex = e; + throw new TddlNestableRuntimeException(e); + } finally { + if (ex == null) { + connection.releaseAutoSavepoint(); + } + } + } + + @Override + public void transConnectionBegin(Object transConn) throws SQLException { + InnerConnection conn = (InnerConnection) transConn; + conn.setAutoCommit(false); + } + + @Override + public void transConnectionCommit(Object transConn) throws SQLException { + InnerConnection conn = (InnerConnection) transConn; + conn.commit(); + } + + @Override + public void transConnectionRollback(Object transConn) throws SQLException { + InnerConnection conn = (InnerConnection) transConn; + conn.rollback(); + + } + + private void releaseAutoSavepoint(Object transConn) { + InnerConnection conn = (InnerConnection) transConn; + conn.releaseAutoSavepoint(); + } + } diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/AppLoader.java b/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/AppLoader.java index 7c1e7deec..bb0f4fa8b 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/AppLoader.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/AppLoader.java @@ -88,18 +88,21 @@ protected synchronized void loadSchema(final String dbName, final String appName ds.putConnectionProperties(ConnectionProperties.SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE, system.getDropOldDataBaseAfterSwitchDataSource()); - ds.putConnectionProperties( - ConnectionProperties.ENABLE_COLUMNAR_OPTIMIZER, ConfigDataMode.isColumnarMode() ? true : false); - ds.putConnectionProperties( - ConnectionProperties.ENABLE_DIRECT_PLAN, ConfigDataMode.isColumnarMode() ? false : true); + if (ConfigDataMode.isColumnarMode()) { + ds.putConnectionProperties(ConnectionProperties.ENABLE_COLUMNAR_OPTIMIZER, true); + } if (system.getWorkloadType() != null) { ds.putConnectionProperties(ConnectionProperties.WORKLOAD_TYPE, system.getWorkloadType()); } - ds.putConnectionProperties(ConnectionProperties.MPP_RPC_LOCAL_ENABLED, !system.isEnableRemoteRPC()); + if (system.isEnableRemoteRPC()) { + ds.putConnectionProperties(ConnectionProperties.MPP_RPC_LOCAL_ENABLED, false); + } - ds.putConnectionProperties(ConnectionProperties.ENABLE_MASTER_MPP, system.isEnableMasterMpp()); + if (system.isEnableMasterMpp()) { + ds.putConnectionProperties(ConnectionProperties.ENABLE_MASTER_MPP, true); + } // 共享一个线程池 ds.setGlobalExecutorService(CobarServer.getInstance().getServerExecutor()); @@ -127,11 +130,11 @@ protected synchronized void loadSchema(final String dbName, final String appName protected synchronized void unLoadSchema(final String dbName, final String appName) { SchemaConfig schema = schemas.remove(dbName); if (schema != null) { + schema.setDropped(true); TDataSource dataSource = schema.getDataSource(); if (dataSource != null) { dataSource.destroy(); } - schema.setDropped(true); } } diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/ClusterLoader.java b/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/ClusterLoader.java index 66ca9512b..42f7e500e 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/ClusterLoader.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/ClusterLoader.java @@ -31,6 +31,8 @@ import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.config.SystemConfig; import com.alibaba.polardbx.executor.common.GsiStatisticsManager; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlDataCleanupRateLimiter; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.TtlIntraTaskExecutor; import com.alibaba.polardbx.executor.ddl.workqueue.BackFillThreadPool; import com.alibaba.polardbx.executor.ddl.workqueue.ChangeSetThreadPool; import com.alibaba.polardbx.executor.ddl.workqueue.FastCheckerThreadPool; @@ -49,6 +51,7 @@ import com.alibaba.polardbx.optimizer.memory.MemoryManager; import com.alibaba.polardbx.optimizer.memory.MemorySetting; import com.alibaba.polardbx.optimizer.planmanager.PlanManager; +import com.alibaba.polardbx.optimizer.ttl.TtlConfigUtil; import com.alibaba.polardbx.optimizer.view.InformationSchemaViewManager; import com.alibaba.polardbx.server.util.LogUtils; import com.alibaba.polardbx.transaction.ColumnarTsoManager; @@ -435,6 +438,258 @@ protected void applyProperties(Properties p) { } } + /* ========ttl job config======== */ + if (p.containsKey(ConnectionProperties.TTL_GLOBAL_SELECT_WORKER_COUNT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_GLOBAL_SELECT_WORKER_COUNT); + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.TTL_GLOBAL_SELECT_WORKER_COUNT, valStr); + TtlIntraTaskExecutor.getInstance() + .adjustTaskExecutorWorkerCount(TtlIntraTaskExecutor.SELECT_TASK_EXECUTOR_TYPE, + DynamicConfig.getInstance().getTtlGlobalSelectWorkerCount()); + } + + if (p.containsKey(ConnectionProperties.TTL_GLOBAL_DELETE_WORKER_COUNT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_GLOBAL_DELETE_WORKER_COUNT); + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.TTL_GLOBAL_DELETE_WORKER_COUNT, valStr); + TtlIntraTaskExecutor.getInstance() + .adjustTaskExecutorWorkerCount(TtlIntraTaskExecutor.DELETE_TASK_EXECUTOR_TYPE, + DynamicConfig.getInstance().getTtlGlobalDeleteWorkerCount()); + } + + if (p.containsKey(ConnectionProperties.TTL_TMP_TBL_MAX_DATA_LENGTH)) { + String valStr = p.getProperty(ConnectionProperties.TTL_TMP_TBL_MAX_DATA_LENGTH); + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.TTL_TMP_TBL_MAX_DATA_LENGTH, valStr); + TtlConfigUtil.setMaxTtlTmpTableDataLength(DynamicConfig.getInstance().getTtlTmpTableMaxDataLength()); + } + + if (p.containsKey(ConnectionProperties.TTL_TBL_MAX_DATA_FREE_PERCENT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_TBL_MAX_DATA_FREE_PERCENT); + DynamicConfig.getInstance().loadValue(logger, ConnectionProperties.TTL_TBL_MAX_DATA_FREE_PERCENT, valStr); + TtlConfigUtil.setMaxDataFreePercentOfTtlTable( + DynamicConfig.getInstance().getTtlTmpTableMaxDataFreePercent()); + } + + if (p.containsKey(ConnectionProperties.TTL_INTRA_TASK_INTERRUPTION_MAX_WAIT_TIME)) { + String valStr = p.getProperty(ConnectionProperties.TTL_INTRA_TASK_INTERRUPTION_MAX_WAIT_TIME); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_INTRA_TASK_INTERRUPTION_MAX_WAIT_TIME, valStr); + TtlConfigUtil.setIntraTaskInterruptionMaxWaitTime( + DynamicConfig.getInstance().getTtlIntraTaskInterruptionMaxWaitTime()); + } + + if (p.containsKey(ConnectionProperties.TTL_INTRA_TASK_MONITOR_EACH_ROUTE_WAIT_TIME)) { + String valStr = p.getProperty(ConnectionProperties.TTL_INTRA_TASK_MONITOR_EACH_ROUTE_WAIT_TIME); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_INTRA_TASK_MONITOR_EACH_ROUTE_WAIT_TIME, valStr); + TtlConfigUtil.setIntraTaskDelegateEachRoundWaitTime( + DynamicConfig.getInstance().getTtlIntraTaskMonitorEachRoundWaitTime()); + } + + if (p.containsKey(ConnectionProperties.TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB)) { + String valStr = p.getProperty(ConnectionProperties.TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_ENABLE_AUTO_OPTIMIZE_TABLE_IN_TTL_JOB, valStr); + TtlConfigUtil.setEnableAutoControlOptiTblByTtlJob( + DynamicConfig.getInstance().isTtlEnableAutoOptimizeTableInTtlJob()); + } + + if (p.containsKey(ConnectionProperties.TTL_ENABLE_AUTO_EXEC_OPTIMIZE_TABLE_AFTER_ARCHIVING)) { + String valStr = p.getProperty(ConnectionProperties.TTL_ENABLE_AUTO_EXEC_OPTIMIZE_TABLE_AFTER_ARCHIVING); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_ENABLE_AUTO_EXEC_OPTIMIZE_TABLE_AFTER_ARCHIVING, valStr); + TtlConfigUtil.setEnablePerformAutoOptiTtlTableAfterArchiving( + DynamicConfig.getInstance().isTtlEnableAutoExecOptimizeTableAfterArchiving()); + } + + if (p.containsKey(ConnectionProperties.TTL_SCHEDULED_JOB_MAX_PARALLELISM)) { + String valStr = p.getProperty(ConnectionProperties.TTL_SCHEDULED_JOB_MAX_PARALLELISM); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_SCHEDULED_JOB_MAX_PARALLELISM, valStr); + TtlConfigUtil.setTtlScheduledJobMaxParallelism( + DynamicConfig.getInstance().getTtlScheduledJobMaxParallelism()); + } + + if (p.containsKey(ConnectionProperties.TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL)) { + String valStr = p.getProperty(ConnectionProperties.TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL, valStr); + + } + + if (p.containsKey(ConnectionProperties.TTL_JOB_DEFAULT_BATCH_SIZE)) { + String valStr = p.getProperty(ConnectionProperties.TTL_JOB_DEFAULT_BATCH_SIZE); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_JOB_DEFAULT_BATCH_SIZE, valStr); + TtlConfigUtil.setTtlJobDefaultBatchSize(DynamicConfig.getInstance().getTtlJobDefaultBatchSize()); + } + + if (p.containsKey(ConnectionProperties.TTL_CLEANUP_BOUND_INTERVAL_COUNT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_CLEANUP_BOUND_INTERVAL_COUNT); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_CLEANUP_BOUND_INTERVAL_COUNT, valStr); + TtlConfigUtil.setTtlCleanupBoundIntervalCount( + DynamicConfig.getInstance().getTtlCleanupBoundIntervalCount()); + } + + if (p.containsKey(ConnectionProperties.TTL_STOP_ALL_JOB_SCHEDULING)) { + String valStr = p.getProperty(ConnectionProperties.TTL_STOP_ALL_JOB_SCHEDULING); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_STOP_ALL_JOB_SCHEDULING, valStr); + TtlConfigUtil.setStopAllTtlTableJobScheduling(DynamicConfig.getInstance().isTtlStopAllJobScheduling()); + } + + if (p.containsKey(ConnectionProperties.TTL_USE_ARCHIVE_TRANS_POLICY)) { + String valStr = p.getProperty(ConnectionProperties.TTL_USE_ARCHIVE_TRANS_POLICY); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_USE_ARCHIVE_TRANS_POLICY, valStr); + TtlConfigUtil.setUseArchiveTransPolicy(DynamicConfig.getInstance().isTtlUseArchiveTransPolicy()); + } + + if (p.containsKey(ConnectionProperties.TTL_SELECT_MERGE_UNION_SIZE)) { + String valStr = p.getProperty(ConnectionProperties.TTL_SELECT_MERGE_UNION_SIZE); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_SELECT_MERGE_UNION_SIZE, valStr); + TtlConfigUtil.setMergeUnionSizeForSelectLowerBound( + DynamicConfig.getInstance().getTtlSelectMergeUnionSize()); + } + + if (p.containsKey(ConnectionProperties.TTL_SELECT_MERGE_CONCURRENT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_SELECT_MERGE_CONCURRENT); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_SELECT_MERGE_CONCURRENT, valStr); + TtlConfigUtil.setUseMergeConcurrentForSelectLowerBound( + DynamicConfig.getInstance().isTtlSelectMergeConcurrent()); + } + + if (p.containsKey(ConnectionProperties.TTL_SELECT_STMT_HINT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_SELECT_STMT_HINT); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_SELECT_STMT_HINT, valStr); + TtlConfigUtil.setQueryHintForSelectLowerBound(DynamicConfig.getInstance().getTtlSelectStmtHint()); + } + + if (p.containsKey(ConnectionProperties.TTL_DELETE_STMT_HINT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_DELETE_STMT_HINT); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_DELETE_STMT_HINT, valStr); + TtlConfigUtil.setQueryHintForDeleteExpiredData(DynamicConfig.getInstance().getTtlDeleteStmtHint()); + } + + if (p.containsKey(ConnectionProperties.TTL_INSERT_STMT_HINT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_INSERT_STMT_HINT); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_INSERT_STMT_HINT, valStr); + TtlConfigUtil.setQueryHintForInsertExpiredData(DynamicConfig.getInstance().getTtlInsertStmtHint()); + } + + if (p.containsKey(ConnectionProperties.TTL_OPTIMIZE_TABLE_STMT_HINT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_OPTIMIZE_TABLE_STMT_HINT); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_OPTIMIZE_TABLE_STMT_HINT, valStr); + TtlConfigUtil.setQueryHintForOptimizeTable(DynamicConfig.getInstance().getTtlOptimizeTableStmtHint()); + } + + if (p.containsKey(ConnectionProperties.TTL_ALTER_ADD_PART_STMT_HINT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_ALTER_ADD_PART_STMT_HINT); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_ALTER_ADD_PART_STMT_HINT, valStr); + TtlConfigUtil.setQueryHintForAutoAddParts(DynamicConfig.getInstance().getTtlAlterTableAddPartsStmtHint()); + } + + if (p.containsKey(ConnectionProperties.TTL_GROUP_PARALLELISM_ON_DQL_CONN)) { + String valStr = p.getProperty(ConnectionProperties.TTL_GROUP_PARALLELISM_ON_DQL_CONN); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_GROUP_PARALLELISM_ON_DQL_CONN, valStr); + TtlConfigUtil.setDefaultGroupParallelismOnDqlConn( + DynamicConfig.getInstance().getTtlGroupParallelismOnDqlConn()); + } + + if (p.containsKey(ConnectionProperties.TTL_GROUP_PARALLELISM_ON_DML_CONN)) { + String valStr = p.getProperty(ConnectionProperties.TTL_GROUP_PARALLELISM_ON_DML_CONN); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_GROUP_PARALLELISM_ON_DML_CONN, valStr); + TtlConfigUtil.setDefaultGroupParallelismOnDmlConn( + DynamicConfig.getInstance().getTtlGroupParallelismOnDmlConn()); + } + + if (p.containsKey(ConnectionProperties.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING)) { + String valStr = p.getProperty(ConnectionProperties.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING, valStr); + TtlConfigUtil.setAutoAddMaxValuePartForCci(DynamicConfig.getInstance().getTtlAddMaxValPartOnCciCreating()); + } + + if (p.containsKey(ConnectionProperties.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING)) { + String valStr = p.getProperty(ConnectionProperties.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_ADD_MAXVAL_PART_ON_CCI_CREATING, valStr); + TtlConfigUtil.setAutoAddMaxValuePartForCci(DynamicConfig.getInstance().getTtlAddMaxValPartOnCciCreating()); + } + + if (p.containsKey(ConnectionProperties.TTL_MAX_WAIT_ACQUIRE_RATE_PERMITS_PERIODS)) { + String valStr = p.getProperty(ConnectionProperties.TTL_MAX_WAIT_ACQUIRE_RATE_PERMITS_PERIODS); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_MAX_WAIT_ACQUIRE_RATE_PERMITS_PERIODS, valStr); + TtlConfigUtil.setMaxWaitAcquireRatePermitsPeriods( + DynamicConfig.getInstance().getTtlMaxWaitAcquireRatePermitsPeriods()); + } + + if (p.containsKey(ConnectionProperties.TTL_ENABLE_CLEANUP_ROWS_SPEED_LIMIT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_ENABLE_CLEANUP_ROWS_SPEED_LIMIT); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_ENABLE_CLEANUP_ROWS_SPEED_LIMIT, valStr); + TtlConfigUtil.setEnableTtlCleanupRowsSpeedLimit( + DynamicConfig.getInstance().getTtlEnableCleanupRowsSpeedLimit()); + } + + if (p.containsKey(ConnectionProperties.TTL_CLEANUP_ROWS_SPEED_LIMIT_EACH_DN)) { + String valStr = p.getProperty(ConnectionProperties.TTL_CLEANUP_ROWS_SPEED_LIMIT_EACH_DN); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_CLEANUP_ROWS_SPEED_LIMIT_EACH_DN, valStr); + TtlConfigUtil.setCleanupRowsSpeedLimitEachDn( + DynamicConfig.getInstance().getTtlCleanupRowsSpeedLimitEachDn()); + TtlDataCleanupRateLimiter.getInstance().adjustRate(TtlConfigUtil.getCleanupRowsSpeedLimitEachDn()); + + } + + if (p.containsKey(ConnectionProperties.TTL_IGNORE_MAINTAIN_WINDOW_IN_DDL_JOB)) { + String valStr = p.getProperty(ConnectionProperties.TTL_IGNORE_MAINTAIN_WINDOW_IN_DDL_JOB); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_IGNORE_MAINTAIN_WINDOW_IN_DDL_JOB, valStr); + TtlConfigUtil.setIgnoreMaintainWindowInTtlJob( + DynamicConfig.getInstance().getTtlIgnoreMaintainWindowInDdlJob()); + } + + if (p.containsKey(ConnectionProperties.TTL_GLOBAL_WORKER_DN_RATIO)) { + String valStr = p.getProperty(ConnectionProperties.TTL_GLOBAL_WORKER_DN_RATIO); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_GLOBAL_WORKER_DN_RATIO, valStr); + TtlConfigUtil.setTtlGlobalWorkerDnRatio(DynamicConfig.getInstance().getTtlGlobalWorkerDnRatio()); + } + + if (p.containsKey(ConnectionProperties.TTL_DEFAULT_ARC_PRE_ALLOCATE_COUNT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_DEFAULT_ARC_PRE_ALLOCATE_COUNT); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_DEFAULT_ARC_PRE_ALLOCATE_COUNT, valStr); + TtlConfigUtil.setPreBuiltPartCntForCreatColumnarIndex( + DynamicConfig.getInstance().getTtlDefaultArcPreAllocateCount()); + } + + if (p.containsKey(ConnectionProperties.TTL_DEFAULT_ARC_POST_ALLOCATE_COUNT)) { + String valStr = p.getProperty(ConnectionProperties.TTL_DEFAULT_ARC_POST_ALLOCATE_COUNT); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_DEFAULT_ARC_POST_ALLOCATE_COUNT, valStr); + TtlConfigUtil.setPostBuiltPartCntForCreateColumnarIndex( + DynamicConfig.getInstance().getTtlDefaultArcPostAllocateCount()); + } + + if (p.containsKey(ConnectionProperties.TTL_ENABLE_AUTO_ADD_PARTS_FOR_ARC_CCI)) { + String valStr = p.getProperty(ConnectionProperties.TTL_ENABLE_AUTO_ADD_PARTS_FOR_ARC_CCI); + DynamicConfig.getInstance() + .loadValue(logger, ConnectionProperties.TTL_ENABLE_AUTO_ADD_PARTS_FOR_ARC_CCI, valStr); + TtlConfigUtil.setEnableAutoAddPartsForArcCci( + DynamicConfig.getInstance().getTtlEnableAutoAddPartsForArcCci()); + } + if (CobarServer.getInstance().isInited()) { CobarServer.getInstance().reloadSystemConfig(); } diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/GmsClusterLoader.java b/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/GmsClusterLoader.java index 719c8109c..0d80e55b7 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/GmsClusterLoader.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/GmsClusterLoader.java @@ -21,8 +21,6 @@ import com.alibaba.polardbx.PolarQuarantineManager; import com.alibaba.polardbx.common.IdGenerator; import com.alibaba.polardbx.common.TrxIdGenerator; -import com.alibaba.polardbx.common.TddlNode; -import com.alibaba.polardbx.common.logger.LoggerInit; import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.IdGenerator; import com.alibaba.polardbx.common.TrxIdGenerator; @@ -30,6 +28,7 @@ import com.alibaba.polardbx.common.utils.CaseInsensitive; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.InstanceRole; +import com.alibaba.polardbx.common.utils.thread.ExecutorUtil; import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.config.InstanceRoleManager; @@ -62,17 +61,17 @@ import com.alibaba.polardbx.matrix.jdbc.utils.TDataSourceInitUtils; import com.alibaba.polardbx.optimizer.ccl.CclManager; import com.alibaba.polardbx.optimizer.core.expression.JavaFunctionManager; +import com.alibaba.polardbx.transaction.DeadlockManager; import org.apache.commons.lang.StringUtils; import java.sql.Connection; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Properties; import java.util.TreeMap; import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ThreadPoolExecutor; /** * @author chenghui.lch @@ -85,6 +84,10 @@ public class GmsClusterLoader extends ClusterLoader { protected String instanceType; protected boolean isUsing = false; protected Long opVersion = -1L; + /** + * A thread executor for async warming up new created db + */ + private ThreadPoolExecutor newCreatedDbWarmingUpExecutor; protected static class InstInfoListener implements ConfigListener { @@ -164,6 +167,53 @@ public void onHandleConfig(String dataId, long newOpVersion) { } } + protected static class WarmupOneSchemaTask implements Runnable { + + private SchemaConfig schema; + + public WarmupOneSchemaTask(SchemaConfig schemaConfig) { + this.schema = schemaConfig; + } + + @Override + public void run() { + if (schema == null) { + return; + } + + if (schema.isDropped()) { + return; + } + final TDataSource ds = schema.getDataSource(); + if (ds == null) { + return; + } + long startTime = System.nanoTime(); + Throwable ex = TDataSourceInitUtils.initDataSource(ds); + if (ex == null) { + + logger.info("Init schema '{}' costs {} secs", schema.getName(), + (System.nanoTime() - startTime) / 1e9); + + try { + // Before init the next schema, + // wait for this schema finish some init task, + // e.g. RotateTrxLogTask, StatisticsTask, etc. + long sleepSeconds = DynamicConfig.getInstance().getWarmUpDbInterval(); + if (sleepSeconds > 0 && 0 == DynamicConfig.getInstance().getTrxLogMethod()) { + Thread.sleep(sleepSeconds * 1000); + } + } catch (InterruptedException e) { + logger.info("LogicalDb-Warming-Up-Thread is interrupted unexpectedly"); + return; + } + } else { + logger.warn( + "Failed to init schema " + schema.getName() + ", cause is " + ex.getMessage(), ex); + } + } + } + public GmsClusterLoader(SystemConfig systemConfig) { super(systemConfig.getClusterName(), systemConfig.getUnitName()); this.systemConfig = systemConfig; @@ -171,6 +221,7 @@ public GmsClusterLoader(SystemConfig systemConfig) { @Override public void doInit() { + initAsyncDbWarmingUpExecutor(); this.appLoader = new GmsAppLoader(this.cluster, this.unitName); if (StringUtils.isNotEmpty(cluster)) { this.appLoader.init(); @@ -245,6 +296,13 @@ protected void loadPolarDbXCluster() { //init ccl CclManager.getService(); + + // start some background threads. + initBackgroundTasks(); + } + + private void initBackgroundTasks() { + DeadlockManager.getInstance(); } private void registerStoredFunction() { @@ -372,34 +430,41 @@ protected void warmingLogicalDb() { if (ConfigDataMode.isPolarDbX() && systemConfig.getEnableLogicalDbWarmmingUp()) { // Auto load all schemas here ConcurrentLinkedDeque schemas = new ConcurrentLinkedDeque<>(appLoader.getSchemas().values()); +// final Runnable warmupLogicalDbTask = () -> { +// SchemaConfig schema; +// while (null != (schema = schemas.poll())) { +// if (schema.isDropped()) { +// continue; +// } +// final TDataSource ds = schema.getDataSource(); +// long startTime = System.nanoTime(); +// Throwable ex = TDataSourceInitUtils.initDataSource(ds); +// if (ex == null) { +// logger.info("Init schema '{}' costs {} secs", schema.getName(), +// (System.nanoTime() - startTime) / 1e9); +// try { +// // Before init the next schema, +// // wait for this schema finish some init task, +// // e.g. RotateTrxLogTask, StatisticsTask, etc. +// long sleepSeconds = DynamicConfig.getInstance().getWarmUpDbInterval(); +// if (sleepSeconds > 0 && 0 == DynamicConfig.getInstance().getTrxLogMethod()) { +// Thread.sleep(sleepSeconds * 1000); +// } +// } catch (InterruptedException e) { +// logger.info("LogicalDb-Warming-Up-Thread is interrupted unexpectedly"); +// return; +// } +// } else { +// logger.warn( +// "Failed to init schema " + schema.getName() + ", cause is " + ex.getMessage(), ex); +// } +// } +// }; final Runnable warmupLogicalDbTask = () -> { SchemaConfig schema; while (null != (schema = schemas.poll())) { - if (schema.isDropped()) { - continue; - } - final TDataSource ds = schema.getDataSource(); - long startTime = System.nanoTime(); - Throwable ex = TDataSourceInitUtils.initDataSource(ds); - if (ex == null) { - logger.info("Init schema '{}' costs {} secs", schema.getName(), - (System.nanoTime() - startTime) / 1e9); - try { - // Before init the next schema, - // wait for this schema finish some init task, - // e.g. RotateTrxLogTask, StatisticsTask, etc. - long sleepSeconds = DynamicConfig.getInstance().getWarmUpDbInterval(); - if (sleepSeconds > 0 && 0 == DynamicConfig.getInstance().getTrxLogMethod()) { - Thread.sleep(sleepSeconds * 1000); - } - } catch (InterruptedException e) { - logger.info("LogicalDb-Warming-Up-Thread is interrupted unexpectedly"); - return; - } - } else { - logger.warn( - "Failed to init schema " + schema.getName() + ", cause is " + ex.getMessage(), ex); - } + WarmupOneSchemaTask warmupOneSchemaTask = new WarmupOneSchemaTask(schema); + warmupOneSchemaTask.run(); } }; @@ -486,6 +551,7 @@ protected void reloadDbInfoFromMetaDB() { protected void allocResourceForLogicalDb(String dbName) { this.appLoader.loadApp(dbName); + this.submitWarmingUpOneSchemaTask(dbName); } protected void releaseResourceForLogicalDb(String dbName) { @@ -537,4 +603,33 @@ public Long getOpVersion() { public void setOpVersion(Long opVersion) { this.opVersion = opVersion; } + + protected void initAsyncDbWarmingUpExecutor() { + ThreadPoolExecutor newCreatedDbWarmingUpExecutor = + ExecutorUtil.createBufferedExecutor("NewCreatedDbWarmingUpTaskExecutor", 1, + 1024); + this.newCreatedDbWarmingUpExecutor = newCreatedDbWarmingUpExecutor; + } + + protected void submitWarmingUpOneSchemaTask(String dbName) { + try { + SchemaConfig schemaConfig = this.appLoader.getSchemas().get(dbName); + if (schemaConfig == null) { + return; + } + if (schemaConfig.isDropped()) { + return; + } + if (schemaConfig.getDataSource() == null) { + return; + } + if (schemaConfig.getDataSource().isInited()) { + return; + } + WarmupOneSchemaTask warmupOneSchemaTask = new WarmupOneSchemaTask(schemaConfig); + this.newCreatedDbWarmingUpExecutor.submit(warmupOneSchemaTask); + } catch (Throwable ex) { + logger.warn(ex.getMessage(), ex); + } + } } diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/ServerLoader.java b/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/ServerLoader.java index 6904ed6d1..8df419c63 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/ServerLoader.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/config/loader/ServerLoader.java @@ -33,6 +33,7 @@ import com.alibaba.polardbx.config.ConfigException; import com.alibaba.polardbx.config.SystemConfig; import com.alibaba.polardbx.executor.balancer.Balancer; +import com.alibaba.polardbx.executor.common.CciMetaManager; import com.alibaba.polardbx.executor.common.GsiStatisticsManager; import com.alibaba.polardbx.executor.utils.SchemaMetaUtil; import com.alibaba.polardbx.gms.config.impl.ConnPoolConfigManager; @@ -274,6 +275,9 @@ private void initPolarDbXComponents() { // Init storage pool manager StoragePoolManager.getInstance(); + + //Init the cci meta manager + CciMetaManager.getInstance(); } protected void initPortInfoAndInstId() { diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/manager/parser/ManagerParseSelect.java b/polardbx-server/src/main/java/com/alibaba/polardbx/manager/parser/ManagerParseSelect.java index b1fa45c9c..acd151474 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/manager/parser/ManagerParseSelect.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/manager/parser/ManagerParseSelect.java @@ -16,6 +16,8 @@ package com.alibaba.polardbx.manager.parser; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.manager.response.AbstractSimpleSelect; import com.alibaba.polardbx.manager.response.MultiColumnSimpleSelect; import com.alibaba.polardbx.manager.response.NonsupportedStatement; @@ -23,9 +25,9 @@ import com.alibaba.polardbx.manager.response.SingleColumnSimpleSelect; import com.alibaba.polardbx.server.util.ParseUtil; import com.google.common.collect.Lists; +import org.apache.commons.lang3.StringUtils; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.TStringUtil; -import org.apache.commons.lang.StringUtils; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/matrix/config/MatrixConfigHolder.java b/polardbx-server/src/main/java/com/alibaba/polardbx/matrix/config/MatrixConfigHolder.java index 983eef82c..630102f33 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/matrix/config/MatrixConfigHolder.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/matrix/config/MatrixConfigHolder.java @@ -54,7 +54,6 @@ import com.alibaba.polardbx.executor.ddl.newengine.DdlPlanScheduler; import com.alibaba.polardbx.executor.ddl.newengine.cross.AsyncPhyObjectRecorder; import com.alibaba.polardbx.executor.ddl.sync.JobRequest; -import com.alibaba.polardbx.executor.gms.ColumnarManager; import com.alibaba.polardbx.executor.gms.GmsTableMetaManager; import com.alibaba.polardbx.executor.gms.TableListListener; import com.alibaba.polardbx.executor.gsi.GsiManager; @@ -68,6 +67,7 @@ import com.alibaba.polardbx.gms.listener.impl.MetaDbDataIdBuilder; import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; +import com.alibaba.polardbx.gms.topology.DbGroupInfoManager; import com.alibaba.polardbx.gms.topology.DbTopologyManager; import com.alibaba.polardbx.gms.topology.SystemDbHelper; import com.alibaba.polardbx.gms.util.MetaDbUtil; @@ -102,6 +102,7 @@ import com.alibaba.polardbx.repo.mysql.spi.MyDataSourceGetter; import com.alibaba.polardbx.rule.TddlRule; import com.alibaba.polardbx.server.conn.InnerConnectionManager; +import com.alibaba.polardbx.server.handler.SyncPointExecutor; import com.alibaba.polardbx.statistics.SQLRecorderLogger; import com.alibaba.polardbx.stats.MatrixStatistics; import com.alibaba.polardbx.transaction.TransactionExecutor; @@ -118,6 +119,8 @@ import java.util.Map; import java.util.Objects; +import static com.alibaba.polardbx.common.cdc.ICdcManager.DEFAULT_DDL_VERSION_ID; + /** * 依赖的组件 * @@ -260,20 +263,17 @@ public void doInit() { // Start XA recover task. In case of leader of CN without requests(in other AZ) // and that makes all pending trx unfinished forever. if (storageInfoManager.supportXA() || storageInfoManager.supportTso()) { - TransactionManager.getInstance(schemaName).enableXaRecoverScan(); - TransactionManager.getInstance(schemaName).enableKillTimeoutTransaction(); - TransactionManager.getInstance(schemaName).enableLogCleanTask(); - TransactionManager.getInstance(schemaName).scheduleTransactionStatisticsTask(); + transactionManager.scheduleTimerTask(); } if (ConfigDataMode.isPolarDbX()) { PurgeOssFileScheduleTask.getInstance().init(new ParamManager(dataSource.getConnectionProperties())); } - if (ConfigDataMode.isPolarDbX() && !ConfigDataMode.isFastMock()) { - executorContext.setReloadColumnarManager(ColumnarManager::reload); - } - executorContext.setInnerConnectionManager(InnerConnectionManager.getInstance()); + + this.executorContext.setSyncPointExecutor(SyncPointExecutor.getInstance()); + DbGroupInfoManager.getInstance().reloadGroupsOfDb(schemaName); + oc.setFinishInit(true);//Label oc of the db finish init } private void loadContext() { @@ -525,7 +525,7 @@ public void tableMetaDestroy() { try { try (Connection metaDbConn = MetaDbUtil.getConnection()) { metaDbConn.setAutoCommit(false); - SchemaMetaUtil.cleanupSchemaMeta(schemaName, metaDbConn); + SchemaMetaUtil.cleanupSchemaMeta(schemaName, metaDbConn, DEFAULT_DDL_VERSION_ID); metaDbConn.commit(); } catch (SQLException e) { throw new TddlRuntimeException(ErrorCode.ERR_GMS_GET_CONNECTION, e, e.getMessage()); @@ -719,6 +719,27 @@ public void executeBackgroundSql(String sql, String schema, InternalTimeZone tim } } + public int executeBackgroundDmlWithTConnection(String sql, + String schema, + InternalTimeZone timeZone, + TConnection conn) { + try { + if (timeZone != null) { + conn.setTimeZone(timeZone); + } + ExecutionContext executionContext = conn.getExecutionContext(); + executionContext.setSchemaName(schema); + executionContext.setPrivilegeMode(false); + int affectRows = 0; + try (ITStatement stmt = conn.createStatement()) { + affectRows = stmt.executeUpdate(sql); + } + return affectRows; + } catch (SQLException e) { + throw GeneralUtil.nestedException(e); + } + } + public long submitRebalanceDDL(String schema, String ddlSql) { try (TConnection conn = (TConnection) dataSource.getConnection()) { ExecutionContext executionContext = conn.getExecutionContext(); diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/matrix/jdbc/TConnection.java b/polardbx-server/src/main/java/com/alibaba/polardbx/matrix/jdbc/TConnection.java index 880bb9515..ce99a1cac 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/matrix/jdbc/TConnection.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/matrix/jdbc/TConnection.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.CobarServer; import com.alibaba.polardbx.common.TrxIdGenerator; +import com.alibaba.polardbx.common.cdc.ICdcManager; import com.alibaba.polardbx.common.constants.TransactionAttribute; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; @@ -27,7 +28,6 @@ import com.alibaba.polardbx.common.jdbc.Parameters; import com.alibaba.polardbx.common.jdbc.ShareReadViewPolicy; import com.alibaba.polardbx.common.lock.LockingFunctionHandle; -import com.alibaba.polardbx.server.lock.LockingFunctionManager; import com.alibaba.polardbx.common.logical.ITConnection; import com.alibaba.polardbx.common.logical.ITPrepareStatement; import com.alibaba.polardbx.common.logical.ITStatement; @@ -59,9 +59,10 @@ import com.alibaba.polardbx.executor.gsi.GsiUtils; import com.alibaba.polardbx.executor.mdl.MdlContext; import com.alibaba.polardbx.executor.mdl.MdlRequest; +import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; import com.alibaba.polardbx.executor.spi.ITransactionManager; import com.alibaba.polardbx.executor.utils.PolarPrivilegeUtils; -import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; +import com.alibaba.polardbx.gms.node.InternalNodeManager; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.group.utils.GroupHintParser; import com.alibaba.polardbx.matrix.jdbc.utils.ByteStringUtil; @@ -80,6 +81,7 @@ import com.alibaba.polardbx.optimizer.context.MultiDdlContext; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.core.planner.ExecutionPlan; +import com.alibaba.polardbx.optimizer.core.planner.PlanCache; import com.alibaba.polardbx.optimizer.core.planner.Planner; import com.alibaba.polardbx.optimizer.core.planner.rule.util.ExecutionStrategy; import com.alibaba.polardbx.optimizer.core.rel.BroadcastTableModify; @@ -104,14 +106,15 @@ import com.alibaba.polardbx.optimizer.utils.ITransaction; import com.alibaba.polardbx.optimizer.utils.InventoryMode; import com.alibaba.polardbx.repo.mysql.cursor.ResultSetCursor; +import com.alibaba.polardbx.server.lock.LockingFunctionManager; import com.alibaba.polardbx.statistics.RuntimeStatHelper; import com.alibaba.polardbx.statistics.RuntimeStatistics; import com.alibaba.polardbx.statistics.SQLRecorderLogger; import com.alibaba.polardbx.transaction.trx.ITsoTransaction; import com.alibaba.polardbx.transaction.trx.ReadOnlyTsoTransaction; +import com.alibaba.polardbx.transaction.trx.TsoTransaction; import org.apache.calcite.rel.AbstractRelNode; import org.apache.calcite.rel.RelNode; -import org.apache.calcite.rel.metadata.RelMetadataQuery; import org.apache.calcite.sql.OptimizerHint; import org.apache.calcite.sql.SqlAlterTable; import org.apache.calcite.sql.SqlCreateIndex; @@ -140,7 +143,10 @@ import static com.alibaba.polardbx.common.utils.GeneralUtil.unixTimeStamp; import static com.alibaba.polardbx.druid.sql.ast.SqlType.isDDL; import static com.alibaba.polardbx.druid.sql.ast.SqlType.isDML; +import static com.alibaba.polardbx.druid.util.ByteStringUtil.findTraceIndex; +import static com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil.changeParameterTypeByTableMetadata; import static com.alibaba.polardbx.optimizer.utils.ExecutionPlanProperties.DDL_STATEMENT; +import static com.alibaba.polardbx.optimizer.utils.ExecutionPlanProperties.DML_STATEMENT; import static com.alibaba.polardbx.optimizer.utils.ExecutionPlanProperties.MDL_REQUIRED_POLARDBX; import static com.alibaba.polardbx.optimizer.utils.ExecutionPlanProperties.MODIFY_TABLE; import static org.apache.calcite.sql.OptimizerHint.COMMIT_ON_SUCCESS; @@ -230,6 +236,11 @@ public class TConnection implements ITConnection { */ private LockingFunctionHandle lockHandle; private String traceId; + /** + * 如果是tso事务,保存commit tso + */ + private long commitTso = -1L; + /** * 事务级别 */ @@ -361,7 +372,8 @@ public ResultSet executeSQL(ByteString sql, Parameters params, TStatement stmt, if (trace > 0) { sql = sql.slice(trace); this.tracer = new SQLTracer(); - this.columnarTracer = new ColumnarTracer(); + InternalNodeManager manager = ServiceProvider.getInstance().getServer().getNodeManager(); + this.columnarTracer = new ColumnarTracer(manager.getCurrentNode().getHostPort()); executionContext.setEnableTrace(true); } else if (executionContext.getLoadDataContext() != null && executionContext.getLoadDataContext() .getParamManager() @@ -417,9 +429,9 @@ public ResultSet executeSQL(ByteString sql, Parameters params, TStatement stmt, String groupHint = GroupHintParser.extractTDDLGroupHint(sql); if (StringUtils.isNotEmpty(groupHint)) { OptimizerContext.getContext(executionContext.getSchemaName()).getStatistics().hintCount++; - - sql = GroupHintParser.removeTddlGroupHint(sql); executionContext.setGroupHint(GroupHintParser.buildTddlGroupHint(groupHint)); + + transformGroupIndexHintToMasterSlave(groupHint, extraCmd); } else { executionContext.setGroupHint(null); } @@ -444,6 +456,8 @@ public ResultSet executeSQL(ByteString sql, Parameters params, TStatement stmt, executionContext.setModifySelectParallel(false); executionContext.setTimeZone(this.logicalTimeZone); executionContext.getPrivilegeVerifyItems().clear(); + executionContext.setStorageInfoSupplier( + (schema) -> ExecutorContext.getContext(schema).getStorageInfoManager().getMergedStorageInfo()); if (executionContext.isInternalSystemSql()) { /** * When the sql is labeled as internal system sql of drds, the @@ -571,6 +585,29 @@ public ResultSet executeSQL(ByteString sql, Parameters params, TStatement stmt, } } + /** + * Transforms a group index hint into Master/Slave connection properties. + * + * @param groupHint The group index hint string, e.g., "groupindex:0" or "groupindex:1". + * @param extraCmd A map to store additional commands, including connection properties. + */ + protected static void transformGroupIndexHintToMasterSlave(String groupHint, Map extraCmd) { + // Check for non-null parameters + if (groupHint == null || extraCmd == null) { + return; + } + + switch (groupHint.toLowerCase()) { + case "groupindex:0": + extraCmd.put(ConnectionProperties.MASTER, Boolean.TRUE); + break; + case "groupindex:1": + extraCmd.put(ConnectionProperties.SLAVE, Boolean.TRUE); + break; + default: + } + } + /** * Separate execute(sql, ec) into two parts: plan and execute. If it's * writing into broadcast table and has no transaction, a new transaction @@ -587,10 +624,12 @@ private ResultCursor executeQuery(ByteString sql, ExecutionContext executionCont final Parameters originParams = executionContext.getParams().clone(); ExecutionPlan plan = Planner.getInstance().plan(sql, executionContext); + if (!executionContext.isFlashbackArea()) { + executionContext.setFlashbackArea(plan.isFlashbackArea()); + } databaseReadOnlyCheck(plan); instanceReadOnlyCheck(); - // [mysql behavior] // comment can be executed, sql example : "-- I can execute" if (plan == null) { @@ -694,6 +733,8 @@ private ResultCursor executeQuery(ByteString sql, ExecutionContext executionCont } // Trx object SHOULD NOT be changed from here. + checkSqlLogBinXForbiddenAutoCommit(); + trx.setMdlWaitTime(mdlWaitTime); if (0 == trx.getStartTimeInMs()) { trx.setStartTimeInMs(executionContext.getLogicalSqlStartTimeInMs()); @@ -723,6 +764,9 @@ private ResultCursor executeQuery(ByteString sql, ExecutionContext executionCont executionContext.setXplanStat(plan.isForbidXplan()); executionContext.setFinalPlan(plan); + + changeParameterTypeByTableMetadata(executionContext, plan); + if (!executionContext.isExecutingPreparedStmt()) { PolarPrivilegeUtils.checkPrivilege(plan, executionContext); PolarPrivilegeUtils.checkLBACColumnAccess(plan, executionContext); @@ -851,9 +895,11 @@ public Pair updatePlanManagementInfo(long lastExecuteUnixTime, // only deal with plan not null and not direct sharding point select RelNode plan = executionPlan.getPlan(); PlannerContext plannerContext = PlannerContext.getPlannerContext(plan); + BaselineInfo baselineInfo = plannerContext.getBaselineInfo(); PlanInfo planInfo = plannerContext.getPlanInfo(); if (planInfo != null && baselineInfo != null) { + PlanCache.getInstance().xplanFeedBack(executionPlan, executionContext); synchronized (baselineInfo) { PlanManager.getInstance().doEvolution(executionContext.getSchemaName(), baselineInfo, planInfo, lastExecuteUnixTime, executionTimeInSeconds, ec, ex); @@ -932,6 +978,12 @@ private void updateTableStatistic(ExecutionPlan executionPlan, ResultCursor resu * @return is transaction policy updated */ private boolean updateTransactionAndConcurrentPolicyForDml(ExecutionPlan plan, ExecutionContext ec) { + if (isAutoCommit && ec.isForbidAutoCommitTrx() && plan.is(DML_STATEMENT)) { + // Init a non-autocommit trx for DML. + ITransaction trx = forceInitTransaction(ec, false, true); + ec.setTransaction(trx); + return true; + } final BitSet properties = plan.getPlanProperties(); final boolean currentModifyBroadcast = properties.get(ExecutionPlanProperties.MODIFY_BROADCAST_TABLE); @@ -999,7 +1051,8 @@ private boolean updateTransactionAndConcurrentPolicyForDml(ExecutionPlan plan, E ITransactionPolicy policy = ITransactionPolicy.of(policyName); if (null != policy) { final boolean isDistributedTransaction = - policy.getTransactionType(false, false).isA(TransactionClass.DISTRIBUTED_TRANSACTION); + policy.getTransactionType(false, false, false, false) + .isA(TransactionClass.DISTRIBUTED_TRANSACTION); if (!isDistributedTransaction) { ec.getExtraCmds().put(ConnectionProperties.TRANSACTION_POLICY, null); } @@ -1017,8 +1070,8 @@ private boolean updateTransactionAndConcurrentPolicyForDml(ExecutionPlan plan, E * * @return is transaction policy updated */ - private boolean updateTransactionAndConcurrentPolicyForColumnar(ExecutionPlan plan, ExecutionContext ec) { - if (!plan.isUseColumnar()) { + private boolean updateTransactionAndConcurrentPolicyForColumnar(ExecutionContext ec) { + if (!ec.isUseColumnar()) { return false; } @@ -1034,7 +1087,7 @@ private boolean updateTransactionAndConcurrentPolicyForColumnar(ExecutionPlan pl * @return is transaction policy updated */ private boolean updateTransactionAndConcurrentPolicy(ExecutionPlan plan, ExecutionContext ec) { - if (updateTransactionAndConcurrentPolicyForColumnar(plan, ec)) { + if (updateTransactionAndConcurrentPolicyForColumnar(ec)) { return true; } @@ -1115,6 +1168,18 @@ private long acquireTransactionalMdl(final ByteString sql, final ExecutionPlan p return 0; } + private void checkSqlLogBinXForbiddenAutoCommit() { + Object sqlLoginBin = executionContext.getExtraServerVariables().get(ICdcManager.SQL_LOG_BIN); + if (sqlLoginBin != null && !(Boolean) sqlLoginBin) { + boolean isDML = isDML(executionContext.getSqlType()); + if (this.isAutoCommit && isDML) { + throw new TddlRuntimeException(ErrorCode.ERR_SQL_LOG_BIN_NOT_SUPPORT_AUTO_COMMIT, + "sql_log_bin_x not support auto commit transaction!"); + } + this.trxPolicy = TransactionAttribute.DEFAULT_IGNORE_BINLOG_TRANSACTION; + } + } + private boolean instanceReadOnly() { // Object val = DynamicConfig.getInstance().isInstanceReadOnly(); // if (val != null) { @@ -1154,9 +1219,11 @@ private void instanceReadOnlyCheck() { } //when database status is readOnly, we forbid all dml sql - private void databaseReadOnlyCheck(final ExecutionPlan plan) { - boolean isDML = isDML(executionContext.getSqlType()); - boolean isDDL = isDDL(executionContext.getSqlType()); + public void databaseReadOnlyCheck(final ExecutionPlan plan) { + final SqlNode sqlNode = plan.getAst(); + + boolean isDML = sqlNode != null && SqlKind.DML.contains(sqlNode.getKind()); + boolean isDDL = sqlNode != null && SqlKind.DDL.contains(sqlNode.getKind()); if (!isDML && !isDDL) { return; } @@ -1397,6 +1464,9 @@ public void commit() throws SQLException { try { // 事务结束,清理事务内容 this.trx.commit(); + if (this.trx instanceof TsoTransaction) { + commitTso = ((TsoTransaction) this.trx).getCommitTso(); + } } catch (Throwable e) { // 增加打印事务异常日志 logger.error(e); @@ -1739,6 +1809,11 @@ public void setEncoding(String encoding) { } private void beginTransaction() { + Object sqlLoginBin = executionContext.getExtraServerVariables().get(ICdcManager.SQL_LOG_BIN); + if (sqlLoginBin != null && !(Boolean) sqlLoginBin) { + // 这里先设置一下事务策略,checkSqlLogBinXForbiddenAutoCommit方法会判断是否需要限制autocommit + this.trxPolicy = TransactionAttribute.DEFAULT_IGNORE_BINLOG_TRANSACTION; + } beginTransaction(this.isAutoCommit); } @@ -1765,7 +1840,7 @@ private void beginTransaction(boolean autoCommit) { boolean readOnly = this.readOnly || (ConfigDataMode.isReadOnlyMode() && executionContext.getParamManager().getBoolean( ConnectionParams.ENABLE_CONSISTENT_REPLICA_READ)); - TransactionClass trxConfig = trxPolicy.getTransactionType(autoCommit, readOnly); + TransactionClass trxConfig = trxPolicy.getTransactionType(autoCommit, readOnly, false, false); if (logicalTimeZone != null) { setTimeZoneVariable(serverVariables); } @@ -1787,6 +1862,11 @@ private void beginTransaction(boolean autoCommit) { } private ITransaction forceInitTransaction(ExecutionContext executionContext, boolean isColumnarRead) { + return forceInitTransaction(executionContext, isColumnarRead, false); + } + + private ITransaction forceInitTransaction(ExecutionContext executionContext, boolean isColumnarRead, + boolean isForbidAutocommitTrx) { lock.lock(); try { @@ -1811,7 +1891,7 @@ private ITransaction forceInitTransaction(ExecutionContext executionContext, boo } trxConfig = trxPolicy.getTransactionType(false, executionContext.isReadOnly(), - isSingleShard); + isSingleShard, isForbidAutocommitTrx); } else { trxConfig = TransactionClass.COLUMNAR_READ_ONLY_TRANSACTION; } @@ -2242,4 +2322,8 @@ public void setClientFoundRows(boolean clientFoundRows) { public boolean isMppConnection() { return false; } + + public long getCommitTso() { + return commitTso; + } } diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/ServerConnection.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/ServerConnection.java index dbe041861..bbd291fe3 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/ServerConnection.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/ServerConnection.java @@ -28,11 +28,6 @@ import com.alibaba.polardbx.common.constants.IsolationLevel; import com.alibaba.polardbx.common.constants.ServerVariables; import com.alibaba.polardbx.common.encdb.EncdbException; -import com.alibaba.polardbx.gms.config.impl.InstConfUtil; -import com.alibaba.polardbx.gms.metadb.encdb.EncdbKeyManager; -import com.alibaba.polardbx.optimizer.utils.CalciteUtils; -import com.alibaba.polardbx.server.encdb.EncdbRuleSpreader; -import com.alibaba.polardbx.server.encdb.EncdbSessionState; import com.alibaba.polardbx.common.eventlogger.EventLogger; import com.alibaba.polardbx.common.eventlogger.EventType; import com.alibaba.polardbx.common.exception.TddlException; @@ -58,7 +53,6 @@ import com.alibaba.polardbx.common.utils.MergeHashMap; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.TStringUtil; -import com.alibaba.polardbx.common.utils.logger.Level; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.common.utils.thread.ThreadCpuStatUtil; @@ -75,9 +69,10 @@ import com.alibaba.polardbx.executor.mdl.MdlContext; import com.alibaba.polardbx.executor.mdl.MdlManager; import com.alibaba.polardbx.executor.utils.ExecUtils; -import com.alibaba.polardbx.server.lock.LockingFunctionManager; -import com.alibaba.polardbx.gms.metadb.encdb.EncdbRuleManager; import com.alibaba.polardbx.executor.utils.PolarPrivilegeUtils; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.metadb.encdb.EncdbKeyManager; +import com.alibaba.polardbx.gms.metadb.encdb.EncdbRuleManager; import com.alibaba.polardbx.gms.privilege.ActiveRoles; import com.alibaba.polardbx.gms.privilege.PolarAccount; import com.alibaba.polardbx.gms.privilege.PolarAccountInfo; @@ -137,6 +132,7 @@ import com.alibaba.polardbx.optimizer.planmanager.StatementMap; import com.alibaba.polardbx.optimizer.statis.SQLRecorder; import com.alibaba.polardbx.optimizer.statis.XplanStat; +import com.alibaba.polardbx.optimizer.utils.CalciteUtils; import com.alibaba.polardbx.optimizer.utils.ExplainResult; import com.alibaba.polardbx.optimizer.utils.ITransaction; import com.alibaba.polardbx.optimizer.utils.RelUtils; @@ -149,14 +145,16 @@ import com.alibaba.polardbx.rpc.cdc.DumpStream; import com.alibaba.polardbx.rpc.jdbc.CharsetMapping; import com.alibaba.polardbx.server.conn.ResultSetCachedObj; +import com.alibaba.polardbx.server.encdb.EncdbRuleSpreader; +import com.alibaba.polardbx.server.encdb.EncdbServer; +import com.alibaba.polardbx.server.encdb.EncdbSessionState; import com.alibaba.polardbx.server.executor.utils.BinaryResultSetUtil; import com.alibaba.polardbx.server.executor.utils.MysqlDefs; import com.alibaba.polardbx.server.executor.utils.ResultSetUtil; import com.alibaba.polardbx.server.handler.ServerLoadDataHandler; +import com.alibaba.polardbx.server.lock.LockingFunctionManager; import com.alibaba.polardbx.server.mock.MockExecutor; import com.alibaba.polardbx.server.response.Ping; -import com.alibaba.polardbx.server.encdb.EncdbResultSet; -import com.alibaba.polardbx.server.encdb.EncdbServer; import com.alibaba.polardbx.server.session.ServerSession; import com.alibaba.polardbx.server.ugly.hint.EagleeyeTestHintParser; import com.alibaba.polardbx.server.util.LogUtils; @@ -165,6 +163,7 @@ import com.alibaba.polardbx.server.util.StringUtil; import com.alibaba.polardbx.statistics.RuntimeStatistics; import com.alibaba.polardbx.stats.MatrixStatistics; +import com.alibaba.polardbx.transaction.DeadlockManager; import com.alibaba.polardbx.transaction.trx.ReadOnlyTsoTransaction; import com.alibaba.polardbx.transaction.trx.XATsoTransaction; import com.google.common.base.Preconditions; @@ -497,6 +496,16 @@ public Integer getVarIntegerValue(SqlNode oriValue) { return value; } + public Long getVarLongValue(SqlNode oriValue) { + long value; + if (oriValue instanceof SqlUserDefVar || oriValue instanceof SqlSystemVar) { + value = Long.parseLong(String.valueOf(this.getVarValueBySqlNode(oriValue))); + } else { + value = RelUtils.longValue(oriValue); + } + return value; + } + public Boolean getVarBooleanValue(SqlNode oriValue) { Object value = getVarValueBySqlNode(oriValue); if (value == null) { @@ -1114,7 +1123,6 @@ public void genTraceId() { */ public synchronized boolean innerExecute(ByteString sql, List> params, QueryResultHandler handler, LoadDataContext dataContext) { - ByteString realSql = dataContext != null ? ByteString.from(dataContext.getLoadDataSql()) : sql; long statExecCpuNano = 0; if (MetricLevel.isSQLMetricEnabled(RuntimeStat.getMetricLevel())) { @@ -1194,6 +1202,7 @@ public synchronized boolean innerExecute(ByteString sql, List extraServerVariables = new HashMap<>(); + private AtomicBoolean isClosed = new AtomicBoolean(false); + + private boolean recordCommitTso = false; + + private long commitTso = -1L; public InnerConnection() throws SQLException { this(SystemDbHelper.DEFAULT_DB_NAME); } public InnerConnection(String schemaName) throws SQLException { + this(schemaName, false, Maps.newHashMap()); + } + + public InnerConnection(String schemaName, boolean recordCommitTso) throws SQLException { + this(schemaName, recordCommitTso, Maps.newHashMap()); + } + + public InnerConnection(String schemaName, + boolean recordCommitTso, + Map sessionVariables) throws SQLException { this.schemaName = schemaName; this.id = ClusterAcceptIdGenerator.getInstance().nextId(); this.mdlContext = MdlManager.addContext(id); this.mdlContextLock = new Object(); + this.recordCommitTso = recordCommitTso; // JDBC会改成STRICT_TRANS_TABLES,为与MySQL兼容,需要改成global的设置 Map serverVariables = new HashMap<>(); @@ -137,6 +159,7 @@ public InnerConnection(String schemaName) throws SQLException { this.connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); this.connection.setAutoCommit(autoCommit); this.connection.setEncoding("utf8"); + this.connection.setTrxPolicy(trxPolicy, false); this.connection.setServerVariables(serverVariables); this.connection.setExtraServerVariables(extraServerVariables); @@ -144,6 +167,89 @@ public InnerConnection(String schemaName) throws SQLException { if (null != InnerConnectionManager.getActiveConnections().putIfAbsent(id, this)) { throw new TddlRuntimeException(ErrorCode.ERR_EXECUTOR, "Found duplicate inner connection id."); } + initConnBySessionVariables(sessionVariables); + } + + /** + * Init the InnerConnection by the session variables, + * so, its functions are added as needed, + */ + protected void initConnBySessionVariables(Map sessionVariables) { + + if (sessionVariables == null || sessionVariables.isEmpty()) { + return; + } + + Map sessionVariablesToBeSetOnDn = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + for (Map.Entry variableItem : sessionVariables.entrySet()) { + String key = variableItem.getKey(); + Object val = variableItem.getValue(); + if (key.equalsIgnoreCase("time_zone")) { + String tzStr = (String) SQLUtils.normalizeNoTrim((String) val); + if (!StringUtils.isEmpty(tzStr)) { + InternalTimeZone internalTz = TimeZoneUtils.convertFromMySqlTZ(tzStr); + this.connection.setTimeZone(internalTz); + } + continue; + } + + if (key.equalsIgnoreCase("sql_mode")) { + String sqlModeStr = (String) SQLUtils.normalizeNoTrim((String) val); + if (!StringUtils.isEmpty(sqlModeStr)) { + this.connection.setSqlMode(sqlModeStr); + } + continue; + } + + if (key.equalsIgnoreCase("names")) { + String charsetStr = (String) SQLUtils.normalizeNoTrim((String) val); + if (!StringUtils.isEmpty(charsetStr)) { + this.connection.setEncoding(charsetStr); + } + continue; + } + + if (key.equalsIgnoreCase("group_parallelism")) { + String groupParallelismStr = SQLUtils.normalizeNoTrim((String) val); + if (!StringUtils.isEmpty(groupParallelismStr)) { + Long grpParallelismVal = Long.valueOf(groupParallelismStr); + if (grpParallelismVal > 0) { + this.connection.setGroupParallelism(grpParallelismVal); + } + } + continue; + } + + if (key.equalsIgnoreCase("transaction_policy")) { + String trxPolicyStr = (String) SQLUtils.normalizeNoTrim((String) val); + if (!StringUtils.isEmpty(trxPolicyStr)) { + if (trxPolicyStr.equalsIgnoreCase("archive")) { + this.setTrxPolicy(ITransactionPolicy.ARCHIVE); + this.connection.setTrxPolicy(ITransactionPolicy.ARCHIVE, false); + } + } + continue; + } + sessionVariablesToBeSetOnDn.put(key, val); + } + +// if (!sessionVariablesToBeSetOnDn.isEmpty()) { +// this.connection.getServerVariables().putAll(sessionVariablesToBeSetOnDn); +// } + } + + public InnerConnection(TConnection connection) { + this.id = 0L; + this.connection = connection; + this.schemaName = "polardbx"; + this.mdlContextLock = new Object(); + } + + public void setExtraServerVariables(String key, Object value) { + if (null == this.connection.getExtraServerVariables()) { + this.connection.setExtraServerVariables(new HashMap<>()); + } + this.connection.getExtraServerVariables().put(key, value); } protected Object executeSql(String sql, List> params) throws SQLException { @@ -151,14 +257,18 @@ protected Object executeSql(String sql, List> pa int sqlSimpleMaxLen = CobarServer.getInstance().getConfig().getSystem().getSqlSimpleMaxLen(); sqlSample = sql.substring(0, Math.min(sqlSimpleMaxLen, sql.length())); boolean success = true; + String traceIdToLog = ""; + Integer updateCountToLog = 0; try { genTxIdAndTraceId(); CobarServer.getInstance().getServerExecutor().initTraceStats(traceId); + traceIdToLog = this.traceId; // 设置TrxPolicy & ExecutionContext信息 connection.setTrxPolicy(trxPolicy, false); // 变量定义 + boolean flag = false; Object result = null; Throwable exception = null; ITransaction trx = null; @@ -180,7 +290,7 @@ protected Object executeSql(String sql, List> pa processExecutionContextHooks(ec); fillParams(stmt, params); statementExecuting.set(true); - boolean flag = stmt.execute(); + flag = stmt.execute(); if (flag) { result = stmt.getResultSet(); result = buildResultSet((TResultSet) result); @@ -190,6 +300,13 @@ protected Object executeSql(String sql, List> pa } catch (Throwable t) { logger.error(t); exception = t; + if (!flag) { + updateCountToLog = -1; + } + } + + if (!flag && result != null) { + updateCountToLog = (Integer) result; } // 自动提交模式下,直接提交即可 @@ -265,7 +382,9 @@ protected Object executeSql(String sql, List> pa sql, success ? "0" : "1", // in milliseconds - (System.nanoTime() - lastActiveTime) / 1_000_000 + (System.nanoTime() - lastActiveTime) / 1_000_000, + traceIdToLog, + updateCountToLog })); // Reset. lastActiveTime = System.nanoTime(); @@ -366,6 +485,10 @@ private void fillParams(TPreparedStatement stmt, List hook) { executionContextInjectHooks.add(hook); @@ -425,6 +548,11 @@ public void commit() throws SQLException { if (this.connection != null) { connection.commit(); + + //如果需要搜集commitTso,判断到是TsoTransaction时,搜集commitTso + if (recordCommitTso) { + commitTso = connection.getCommitTso(); + } } } @@ -439,6 +567,9 @@ public void rollback() throws SQLException { @Override public void close() { + if (!isClosed.compareAndSet(false, true)) { + return; + } try { if (this.statementExecuting.get()) { if (connection.isDdlStatement()) { @@ -453,10 +584,7 @@ public void close() { int retry = 0; do { try { - if (connection != null) { - connection.kill(); - } - + connection.kill(); } catch (Exception ex) { logger.warn("error when kill", ex); } @@ -468,15 +596,14 @@ public void close() { } } while (statementExecuting.get() && ++retry < 10); + try { - if (connection != null) { - connection.close(); - } + connection.close(); } catch (Exception ex) { logger.warn("error when kill inner connection close", ex); } - if (retry >= 10) { + if (10 == retry) { logger.error("KILL Inner Connection Failed, retry: " + retry); } else { logger.warn("Inner Connection Killed"); @@ -557,6 +684,11 @@ public void setTimeZone(String timeZoneId) { } } + @Override + public int hashCode() { + return id.hashCode(); + } + private static class InnerResultCursor extends AbstractCursor { private final List rows = new ArrayList<>(); private Iterator iter = null; @@ -731,6 +863,12 @@ public void releaseSavepoint(Savepoint savepoint) throws SQLException { throw new UnsupportedOperationException("unsupported operation"); } + public void releaseAutoSavepoint() { + if (null != this.connection && null != this.connection.getTrx()) { + this.connection.getTrx().releaseAutoSavepoint(); + } + } + @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { @@ -853,4 +991,12 @@ public T unwrap(Class iface) throws SQLException { public boolean isWrapperFor(Class iface) throws SQLException { throw new UnsupportedOperationException("unsupported operation"); } + + public void setRecordCommitTso(boolean recordCommitTso) { + this.recordCommitTso = recordCommitTso; + } + + public long getCommitTso() { + return commitTso; + } } diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/conn/InnerConnectionManager.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/conn/InnerConnectionManager.java index 601025c2a..10920a350 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/conn/InnerConnectionManager.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/conn/InnerConnectionManager.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.server.conn; +import com.alibaba.polardbx.common.IInnerConnection; import com.alibaba.polardbx.common.IInnerConnectionManager; import java.sql.Connection; @@ -32,12 +33,12 @@ private InnerConnectionManager() { } @Override - public Connection getConnection() throws SQLException { + public IInnerConnection getConnection() throws SQLException { return new InnerConnection(); } @Override - public Connection getConnection(String schema) throws SQLException { + public IInnerConnection getConnection(String schema) throws SQLException { return new InnerConnection(schema); } diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/conn/InnerPreparedStatement.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/conn/InnerPreparedStatement.java index 69240c934..c0379df6c 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/conn/InnerPreparedStatement.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/conn/InnerPreparedStatement.java @@ -115,42 +115,62 @@ public void setShort(int parameterIndex, short x) throws SQLException { @Override public void setInt(int parameterIndex, int x) throws SQLException { + Pair pair = new Pair<>(parameterIndex, + new ParameterContext(ParameterMethod.setInt, new Object[] {parameterIndex, x})); + params.add(pair); } @Override public void setFloat(int parameterIndex, float x) throws SQLException { - +// Pair pair = new Pair<>(parameterIndex, +// new ParameterContext(ParameterMethod.setFloat, new Object[] {parameterIndex, x})); +// params.add(pair); } @Override public void setDouble(int parameterIndex, double x) throws SQLException { + Pair pair = new Pair<>(parameterIndex, + new ParameterContext(ParameterMethod.setDouble, new Object[] {parameterIndex, x})); + params.add(pair); } @Override public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { - +// Pair pair = new Pair<>(parameterIndex, +// new ParameterContext(ParameterMethod.setBigDecimal, new Object[] {parameterIndex, x})); +// params.add(pair); } @Override public void setBytes(int parameterIndex, byte[] x) throws SQLException { - + Pair pair = new Pair<>(parameterIndex, + new ParameterContext(ParameterMethod.setBytes, new Object[] {parameterIndex, x})); + params.add(pair); } @Override public void setDate(int parameterIndex, Date x) throws SQLException { + Pair pair = new Pair<>(parameterIndex, + new ParameterContext(ParameterMethod.setDate1, new Object[] {parameterIndex, x})); + params.add(pair); } @Override public void setTime(int parameterIndex, Time x) throws SQLException { +// Pair pair = new Pair<>(parameterIndex, +// new ParameterContext(ParameterMethod.setTime1, new Object[] {parameterIndex, x})); +// params.add(pair); } @Override public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { - +// Pair pair = new Pair<>(parameterIndex, +// new ParameterContext(ParameterMethod.setTimestamp1, new Object[] {parameterIndex, x})); +// params.add(pair); } @Override @@ -220,17 +240,24 @@ public ResultSetMetaData getMetaData() throws SQLException { @Override public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { +// Pair pair = new Pair<>(parameterIndex, +// new ParameterContext(ParameterMethod.setDate1, new Object[] {parameterIndex, x})); +// params.add(pair); } @Override public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { - +// Pair pair = new Pair<>(parameterIndex, +// new ParameterContext(ParameterMethod.setTime2, new Object[] {parameterIndex, x, cal})); +// params.add(pair); } @Override public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { - +// Pair pair = new Pair<>(parameterIndex, +// new ParameterContext(ParameterMethod.setTimestamp2, new Object[] {parameterIndex, x, cal})); +// params.add(pair); } @Override diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/encdb/EncdbResultSet.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/encdb/EncdbResultSet.java deleted file mode 100644 index 6aae6e421..000000000 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/encdb/EncdbResultSet.java +++ /dev/null @@ -1,1050 +0,0 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.server.encdb; - -import com.alibaba.polardbx.common.encdb.EncdbException; -import com.alibaba.polardbx.common.encdb.cipher.CipherForMySQL; -import org.bouncycastle.crypto.CryptoException; - -import java.io.InputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.security.NoSuchAlgorithmException; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Date; -import java.sql.NClob; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Base64; -import java.util.Calendar; -import java.util.Map; - -import static com.alibaba.polardbx.server.encdb.EncdbUtils.*; - -/** - * @author pangzhaoxing - */ -public class EncdbResultSet implements ResultSet { - - private ResultSet rs; - - private ResultSetMetaData metaData; - - private boolean[] colEncBitmap; - private EncdbSessionState encState; - - public EncdbResultSet(ResultSet rs, boolean[] colEncBitmap, EncdbSessionState encState) throws SQLException { - this.rs = rs; - this.metaData = rs.getMetaData(); - this.colEncBitmap = colEncBitmap; - this.encState = encState; - } - - private byte[] encrypt(byte[] bytes, int columnIndex) throws SQLException { - - CipherForMySQL cipher = CipherForMySQL.buildCipher( - sqlType2MysqlType(metaData.getColumnType(columnIndex), metaData.getScale(columnIndex)), - encState.getEncAlgo()); - try { - byte[] encrypted = Base64.getEncoder().encode( - cipher.encrypt(encState.getCcFlags(), encState.getDek(), bytes, encState.getNonce())); - return encrypted; - } catch (NoSuchAlgorithmException | CryptoException e) { - throw new EncdbException(e); - } - } - - @Override - public byte[] getBytes(int columnIndex) throws SQLException { - byte[] bytes = rs.getBytes(columnIndex); - if (bytes == null) { - return null; - } - return colEncBitmap[columnIndex - 1] ? encrypt(bytes, columnIndex) : bytes; - } - - @Override - public byte[] getBytes(String columnLabel) throws SQLException { - int columnIndex = rs.findColumn(columnLabel); - byte[] bytes = rs.getBytes(columnLabel); - if (bytes == null) { - return null; - } - return colEncBitmap[columnIndex - 1] ? encrypt(bytes, columnIndex) : bytes; - } - - @Override - public boolean absolute(int row) throws SQLException { - return rs.absolute(row); - } - - @Override - public void afterLast() throws SQLException { - rs.afterLast(); - } - - @Override - public void beforeFirst() throws SQLException { - rs.beforeFirst(); - } - - @Override - public void cancelRowUpdates() throws SQLException { - rs.cancelRowUpdates(); - } - - @Override - public void clearWarnings() throws SQLException { - rs.clearWarnings(); - } - - @Override - public void close() throws SQLException { - rs.close(); - } - - @Override - public void deleteRow() throws SQLException { - rs.deleteRow(); - } - - @Override - public int findColumn(String columnLabel) throws SQLException { - return rs.findColumn(columnLabel); - } - - @Override - public boolean first() throws SQLException { - return rs.first(); - } - - @Override - public Array getArray(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Array getArray(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public InputStream getAsciiStream(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public InputStream getAsciiStream(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - @SuppressWarnings("deprecation") - public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public BigDecimal getBigDecimal(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - @SuppressWarnings("deprecation") - public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public BigDecimal getBigDecimal(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public InputStream getBinaryStream(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public InputStream getBinaryStream(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Blob getBlob(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Blob getBlob(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public boolean getBoolean(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public boolean getBoolean(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public byte getByte(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public byte getByte(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Reader getCharacterStream(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Reader getCharacterStream(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Clob getClob(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Clob getClob(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public int getConcurrency() throws SQLException { - return rs.getConcurrency(); - } - - @Override - public String getCursorName() throws SQLException { - return rs.getCursorName(); - } - - @Override - public Date getDate(int columnIndex, Calendar cal) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Date getDate(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Date getDate(String columnLabel, Calendar cal) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Date getDate(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public double getDouble(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public double getDouble(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public int getFetchDirection() throws SQLException { - return rs.getFetchDirection(); - } - - @Override - public int getFetchSize() throws SQLException { - return rs.getFetchSize(); - } - - @Override - public float getFloat(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public float getFloat(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public int getHoldability() throws SQLException { - return rs.getHoldability(); - } - - @Override - public int getInt(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public int getInt(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public long getLong(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public long getLong(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public ResultSetMetaData getMetaData() throws SQLException { - return rs.getMetaData(); - } - - @Override - public Reader getNCharacterStream(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Reader getNCharacterStream(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public NClob getNClob(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public NClob getNClob(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public String getNString(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public String getNString(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Object getObject(int columnIndex, Map> map) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Object getObject(String columnLabel, Map> map) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Object getObject(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Object getObject(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Ref getRef(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Ref getRef(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public int getRow() throws SQLException { - return rs.getRow(); - } - - @Override - public RowId getRowId(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public RowId getRowId(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public SQLXML getSQLXML(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public SQLXML getSQLXML(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public short getShort(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public short getShort(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Statement getStatement() throws SQLException { - return rs.getStatement(); - } - - @Override - public String getString(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public String getString(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Time getTime(int columnIndex, Calendar cal) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Time getTime(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Time getTime(String columnLabel, Calendar cal) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Time getTime(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Timestamp getTimestamp(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public Timestamp getTimestamp(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public int getType() throws SQLException { - return rs.getType(); - } - - @Override - public URL getURL(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public URL getURL(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - @SuppressWarnings("deprecation") - public InputStream getUnicodeStream(int columnIndex) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - @SuppressWarnings("deprecation") - public InputStream getUnicodeStream(String columnLabel) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public T getObject(int columnIndex, Class type) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public T getObject(String columnLabel, Class type) throws SQLException { - throw new EncdbException(new UnsupportedOperationException("EncdbResultSet only support getBytes()")); - } - - @Override - public SQLWarning getWarnings() throws SQLException { - return rs.getWarnings(); - } - - @Override - public void insertRow() throws SQLException { - rs.insertRow(); - } - - @Override - public boolean isAfterLast() throws SQLException { - return rs.isAfterLast(); - } - - @Override - public boolean isBeforeFirst() throws SQLException { - return rs.isBeforeFirst(); - } - - @Override - public boolean isClosed() throws SQLException { - return rs.isClosed(); - } - - @Override - public boolean isFirst() throws SQLException { - return rs.isFirst(); - } - - @Override - public boolean isLast() throws SQLException { - return rs.isLast(); - } - - @Override - public boolean isWrapperFor(Class arg0) throws SQLException { - return rs.isWrapperFor(arg0); - } - - @Override - public boolean last() throws SQLException { - return rs.last(); - } - - @Override - public void moveToCurrentRow() throws SQLException { - rs.moveToCurrentRow(); - } - - @Override - public void moveToInsertRow() throws SQLException { - rs.moveToInsertRow(); - } - - @Override - public boolean next() throws SQLException { - return rs.next(); - } - - @Override - public boolean previous() throws SQLException { - return rs.previous(); - } - - @Override - public void refreshRow() throws SQLException { - rs.refreshRow(); - } - - @Override - public boolean relative(int rows) throws SQLException { - return rs.relative(rows); - } - - @Override - public boolean rowDeleted() throws SQLException { - return rs.rowDeleted(); - } - - @Override - public boolean rowInserted() throws SQLException { - return rs.rowInserted(); - } - - @Override - public boolean rowUpdated() throws SQLException { - return rs.rowUpdated(); - } - - @Override - public void setFetchDirection(int direction) throws SQLException { - rs.setFetchDirection(direction); - } - - @Override - public void setFetchSize(int rows) throws SQLException { - rs.setFetchSize(rows); - } - - @Override - public T unwrap(Class arg0) throws SQLException { - return rs.unwrap(arg0); - } - - @Override - public void updateArray(int columnIndex, Array x) throws SQLException { - rs.updateArray(columnIndex, x); - } - - @Override - public void updateArray(String columnLabel, Array x) throws SQLException { - rs.updateArray(columnLabel, x); - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { - rs.updateAsciiStream(columnIndex, x, length); - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { - rs.updateAsciiStream(columnIndex, x, length); - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { - rs.updateAsciiStream(columnIndex, x); - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException { - rs.updateAsciiStream(columnLabel, x, length); - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { - rs.updateAsciiStream(columnLabel, x, length); - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { - rs.updateAsciiStream(columnLabel, x); - } - - @Override - public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { - rs.updateBigDecimal(columnIndex, x); - } - - @Override - public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException { - rs.updateBigDecimal(columnLabel, x); - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { - rs.updateBinaryStream(columnIndex, x, length); - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { - rs.updateBinaryStream(columnIndex, x, length); - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { - rs.updateBinaryStream(columnIndex, x); - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException { - rs.updateBinaryStream(columnLabel, x, length); - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { - rs.updateBinaryStream(columnLabel, x, length); - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { - rs.updateBinaryStream(columnLabel, x); - } - - @Override - public void updateBlob(int columnIndex, Blob x) throws SQLException { - rs.updateBlob(columnIndex, x); - } - - @Override - public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { - rs.updateBlob(columnIndex, inputStream, length); - } - - @Override - public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { - rs.updateBlob(columnIndex, inputStream); - } - - @Override - public void updateBlob(String columnLabel, Blob x) throws SQLException { - rs.updateBlob(columnLabel, x); - } - - @Override - public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { - rs.updateBlob(columnLabel, inputStream, length); - } - - @Override - public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { - rs.updateBlob(columnLabel, inputStream); - } - - @Override - public void updateBoolean(int columnIndex, boolean x) throws SQLException { - rs.updateBoolean(columnIndex, x); - } - - @Override - public void updateBoolean(String columnLabel, boolean x) throws SQLException { - rs.updateBoolean(columnLabel, x); - } - - @Override - public void updateByte(int columnIndex, byte x) throws SQLException { - rs.updateByte(columnIndex, x); - } - - @Override - public void updateByte(String columnLabel, byte x) throws SQLException { - rs.updateByte(columnLabel, x); - } - - @Override - public void updateBytes(int columnIndex, byte[] x) throws SQLException { - rs.updateBytes(columnIndex, x); - } - - @Override - public void updateBytes(String columnLabel, byte[] x) throws SQLException { - rs.updateBytes(columnLabel, x); - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { - rs.updateCharacterStream(columnIndex, x, length); - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { - rs.updateCharacterStream(columnIndex, x, length); - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { - rs.updateCharacterStream(columnIndex, x); - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException { - rs.updateCharacterStream(columnLabel, reader, length); - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { - rs.updateCharacterStream(columnLabel, reader, length); - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { - rs.updateCharacterStream(columnLabel, reader); - } - - @Override - public void updateClob(int columnIndex, Clob x) throws SQLException { - rs.updateClob(columnIndex, x); - } - - @Override - public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { - rs.updateClob(columnIndex, reader, length); - } - - @Override - public void updateClob(int columnIndex, Reader reader) throws SQLException { - rs.updateClob(columnIndex, reader); - } - - @Override - public void updateClob(String columnLabel, Clob x) throws SQLException { - rs.updateClob(columnLabel, x); - } - - @Override - public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { - rs.updateClob(columnLabel, reader, length); - } - - @Override - public void updateClob(String columnLabel, Reader reader) throws SQLException { - rs.updateClob(columnLabel, reader); - } - - @Override - public void updateDate(int columnIndex, Date x) throws SQLException { - rs.updateDate(columnIndex, x); - } - - @Override - public void updateDate(String columnLabel, Date x) throws SQLException { - rs.updateDate(columnLabel, x); - } - - @Override - public void updateDouble(int columnIndex, double x) throws SQLException { - rs.updateDouble(columnIndex, x); - } - - @Override - public void updateDouble(String columnLabel, double x) throws SQLException { - rs.updateDouble(columnLabel, x); - } - - @Override - public void updateFloat(int columnIndex, float x) throws SQLException { - rs.updateFloat(columnIndex, x); - } - - @Override - public void updateFloat(String columnLabel, float x) throws SQLException { - rs.updateFloat(columnLabel, x); - } - - @Override - public void updateInt(int columnIndex, int x) throws SQLException { - rs.updateInt(columnIndex, x); - } - - @Override - public void updateInt(String columnLabel, int x) throws SQLException { - rs.updateInt(columnLabel, x); - } - - @Override - public void updateLong(int columnIndex, long x) throws SQLException { - rs.updateLong(columnIndex, x); - } - - @Override - public void updateLong(String columnLabel, long x) throws SQLException { - rs.updateLong(columnLabel, x); - } - - @Override - public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { - rs.updateNCharacterStream(columnIndex, x, length); - } - - @Override - public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { - rs.updateNCharacterStream(columnIndex, x); - } - - @Override - public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { - rs.updateNCharacterStream(columnLabel, reader, length); - } - - @Override - public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { - rs.updateNCharacterStream(columnLabel, reader); - } - - @Override - public void updateNClob(int columnIndex, NClob nClob) throws SQLException { - rs.updateNClob(columnIndex, nClob); - } - - @Override - public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { - rs.updateNClob(columnIndex, reader, length); - } - - @Override - public void updateNClob(int columnIndex, Reader reader) throws SQLException { - rs.updateNClob(columnIndex, reader); - } - - @Override - public void updateNClob(String columnLabel, NClob nClob) throws SQLException { - rs.updateNClob(columnLabel, nClob); - } - - @Override - public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { - rs.updateNClob(columnLabel, reader, length); - } - - @Override - public void updateNClob(String columnLabel, Reader reader) throws SQLException { - rs.updateNClob(columnLabel, reader); - } - - @Override - public void updateNString(int columnIndex, String nString) throws SQLException { - rs.updateNString(columnIndex, nString); - } - - @Override - public void updateNString(String columnLabel, String nString) throws SQLException { - rs.updateNString(columnLabel, nString); - } - - @Override - public void updateNull(int columnIndex) throws SQLException { - rs.updateNull(columnIndex); - } - - @Override - public void updateNull(String columnLabel) throws SQLException { - rs.updateNull(columnLabel); - } - - @Override - public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException { - rs.updateObject(columnIndex, x, scaleOrLength); - } - - @Override - public void updateObject(int columnIndex, Object x) throws SQLException { - rs.updateObject(columnIndex, x); - } - - @Override - public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException { - rs.updateObject(columnLabel, x, scaleOrLength); - } - - @Override - public void updateObject(String columnLabel, Object x) throws SQLException { - rs.updateObject(columnLabel, x); - } - - @Override - public void updateRef(int columnIndex, Ref x) throws SQLException { - rs.updateRef(columnIndex, x); - } - - @Override - public void updateRef(String columnLabel, Ref x) throws SQLException { - rs.updateRef(columnLabel, x); - } - - @Override - public void updateRow() throws SQLException { - rs.updateRow(); - } - - @Override - public void updateRowId(int columnIndex, RowId x) throws SQLException { - rs.updateRowId(columnIndex, x); - } - - @Override - public void updateRowId(String columnLabel, RowId x) throws SQLException { - rs.updateRowId(columnLabel, x); - } - - @Override - public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { - rs.updateSQLXML(columnIndex, xmlObject); - } - - @Override - public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { - rs.updateSQLXML(columnLabel, xmlObject); - } - - @Override - public void updateShort(int columnIndex, short x) throws SQLException { - rs.updateShort(columnIndex, x); - } - - @Override - public void updateShort(String columnLabel, short x) throws SQLException { - rs.updateShort(columnLabel, x); - } - - @Override - public void updateString(int columnIndex, String x) throws SQLException { - rs.updateString(columnIndex, x); - } - - @Override - public void updateString(String columnLabel, String x) throws SQLException { - rs.updateString(columnLabel, x); - } - - @Override - public void updateTime(int columnIndex, Time x) throws SQLException { - rs.updateTime(columnIndex, x); - } - - @Override - public void updateTime(String columnLabel, Time x) throws SQLException { - rs.updateTime(columnLabel, x); - } - - @Override - public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { - rs.updateTimestamp(columnIndex, x); - } - - @Override - public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException { - rs.updateTimestamp(columnLabel, x); - } - - @Override - public boolean wasNull() throws SQLException { - return rs.wasNull(); - } - -} \ No newline at end of file diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/executor/utils/BinaryResultSetUtil.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/executor/utils/BinaryResultSetUtil.java index 0f8fc6dec..79628ff68 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/executor/utils/BinaryResultSetUtil.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/executor/utils/BinaryResultSetUtil.java @@ -36,7 +36,6 @@ import com.alibaba.polardbx.optimizer.planmanager.PreparedStmtCache; import com.alibaba.polardbx.server.ServerConnection; import com.alibaba.polardbx.server.conn.ResultSetCachedObj; -import com.alibaba.polardbx.server.encdb.EncdbResultSet; import com.alibaba.polardbx.server.util.StringUtil; import com.mysql.jdbc.Field; @@ -61,9 +60,7 @@ public static IPacketOutputProxy resultSetToPacket(ResultSet rs, String charset, AtomicLong affectRow, PreparedStmtCache preparedStmtCache, long sqlSelectLimit) throws SQLException, IllegalAccessException { - if (rs instanceof EncdbResultSet) { - throw new EncdbException("Encdb only support text protocol"); - } + // 先执行一次next,因为存在lazy-init处理,可能写了packet head包出去,但实际获取数据时出错导致客户端出现lost // connection,没有任何其他异常 diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/ColumnarConfigHandler.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/ColumnarConfigHandler.java new file mode 100644 index 000000000..1eaf9807d --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/ColumnarConfigHandler.java @@ -0,0 +1,243 @@ +package com.alibaba.polardbx.server.handler; + +import com.alibaba.polardbx.common.ColumnarOptions; +import com.alibaba.polardbx.common.columnar.ColumnarOption; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ColumnarConfig; +import com.alibaba.polardbx.common.utils.CaseInsensitive; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * @author yaozhili + */ +public class ColumnarConfigHandler { + private static final Logger logger = LoggerFactory.getLogger(ColumnarConfigHandler.class); + /** + * Define columnar config properties here. + */ + private static final Map CONFIG = + new ImmutableMap.Builder() + + .put(ColumnarOptions.DICTIONARY_COLUMNS, new ColumnarOption( + ColumnarOptions.DICTIONARY_COLUMNS, null, + "Columnar index dictionary columns.", + null, null, null + )) + + .put(ColumnarOptions.TYPE, new ColumnarOption( + ColumnarOptions.TYPE, "default", + "Columnar index type, choices: default, snapshot.", + ColumnarConfigHandler::setIndexType, + null, + ColumnarConfigHandler::validateType + )) + + .put(ColumnarOptions.SNAPSHOT_RETENTION_DAYS, new ColumnarOption( + ColumnarOptions.SNAPSHOT_RETENTION_DAYS, "7", + "Columnar snapshot retention days, default is 7 days.", + ColumnarConfigHandler::setParamAndUpdateMeta, + ColumnarConfigHandler::setColumnarConfig, + ColumnarConfigHandler::validateSnapshotRetentionDays + )) + + .put(ColumnarOptions.AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL, new ColumnarOption( + ColumnarOptions.AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL, "-1", + "Columnar snapshot retention auto generated interval (in minutes), default is -1 (not auto-generated).", + ColumnarConfigHandler::setParamAndUpdateMeta, + ColumnarConfigHandler::setColumnarConfig, + ColumnarConfigHandler::validateAutoGenColumnarSnapshotInterval + )) + + .build(); + + private static void setParamAndUpdateMeta(ColumnarOption.Param param) { + setColumnarConfig(param); + } + + private static void setIndexType(ColumnarOption.Param param) { + try { + generateSchemaAndTableByTableId(param); + } catch (SQLException e) { + throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, "Failed to get schema and table name."); + } + // cci name -> config key -> val + Map> records = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + Map globalConfig = new TreeMap<>(CaseInsensitive.CASE_INSENSITIVE_ORDER); + MetaDbUtil.generateColumnarConfig(param.schemaName, param.tableName, records, globalConfig); + Map indexConfig = records.get(param.indexName); + + String currentType = null == indexConfig ? ColumnarConfig.DEFAULT : indexConfig.get(ColumnarOptions.TYPE); + try (Connection connection = MetaDbUtil.getConnection()) { + try { + connection.setAutoCommit(false); + if (!param.value.equalsIgnoreCase(currentType)) { + if (ColumnarConfig.DEFAULT.equalsIgnoreCase(currentType)) { + // default -> snapshot + Preconditions.checkArgument(ColumnarConfig.SNAPSHOT.equalsIgnoreCase(param.value)); + if (null == indexConfig || !indexConfig.containsKey( + ColumnarOptions.SNAPSHOT_RETENTION_DAYS)) { + ColumnarOption.Param tmpParam = param.shallowCopy(); + tmpParam.key = ColumnarOptions.SNAPSHOT_RETENTION_DAYS; + tmpParam.value = ColumnarConfig.getValue(tmpParam.key, null, globalConfig); + String columnarPurgeSaveMs = globalConfig.get(ColumnarOptions.COLUMNAR_PURGE_SAVE_MS); + if (null != columnarPurgeSaveMs) { + long columnarPurgeSaveDays = + 1 + Long.parseLong(columnarPurgeSaveMs) / 1000 / 60 / 60 / 24; + if (columnarPurgeSaveDays > Long.parseLong(tmpParam.value)) { + tmpParam.value = Long.toString(columnarPurgeSaveDays); + } + } + setColumnarConfig(tmpParam, connection); + } + if (null == indexConfig || !indexConfig.containsKey( + ColumnarOptions.AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL)) { + ColumnarOption.Param tmpParam = param.shallowCopy(); + tmpParam.key = ColumnarOptions.AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL; + tmpParam.value = ColumnarConfig.getValue(tmpParam.key, null, globalConfig); + setColumnarConfig(tmpParam, connection); + } + ColumnarTableMappingAccessor accessor = new ColumnarTableMappingAccessor(); + accessor.setConnection(connection); + accessor.updateTypeByTableId(param.tableId, ColumnarConfig.SNAPSHOT); + accessor.UpdateExtraByTableId(param.tableId, null); + } else { + // snapshot -> default + Preconditions.checkArgument(ColumnarConfig.SNAPSHOT.equalsIgnoreCase(currentType)); + Preconditions.checkArgument(ColumnarConfig.DEFAULT.equalsIgnoreCase(param.value)); + if (null != indexConfig && indexConfig.containsKey( + ColumnarOptions.SNAPSHOT_RETENTION_DAYS)) { + ColumnarOption.Param tmpParam = param.shallowCopy(); + tmpParam.key = ColumnarOptions.SNAPSHOT_RETENTION_DAYS; + deleteColumnarConfig(tmpParam, connection); + } + if (null != indexConfig && indexConfig.containsKey( + ColumnarOptions.AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL)) { + ColumnarOption.Param tmpParam = param.shallowCopy(); + tmpParam.key = ColumnarOptions.AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL; + deleteColumnarConfig(tmpParam, connection); + } + ColumnarTableMappingAccessor accessor = new ColumnarTableMappingAccessor(); + accessor.setConnection(connection); + accessor.updateTypeByTableId(param.tableId, null); + } + setColumnarConfig(param, connection); + connection.commit(); + } + } catch (Throwable t) { + connection.rollback(); + connection.setAutoCommit(true); + throw t; + } + } catch (SQLException e) { + logger.error(e); + throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, + "Set columnar config failed, caused by " + e.getMessage()); + } + } + + private static void validateType(ColumnarOption.Param param) { + if (!isOneOfString(param.value, ColumnarConfig.DEFAULT, ColumnarConfig.SNAPSHOT)) { + throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, "Invalid type " + param.value + + ", choices: " + ColumnarConfig.DEFAULT + ", " + ColumnarConfig.SNAPSHOT); + } + param.value = param.value.toUpperCase(); + } + + private static void validateSnapshotRetentionDays(ColumnarOption.Param param) { + long days = Long.parseLong(param.value); + if (days < 1) { + throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, "Value should larger than 0."); + } + param.value = Long.toString(days); + } + + private static void validateAutoGenColumnarSnapshotInterval(ColumnarOption.Param param) { + long minutes = Long.parseLong(param.value); + if (minutes >= 0 && minutes <= 5) { + throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, "Value too small, should >= 5"); + } + param.value = Long.toString(minutes); + } + + private static boolean isOneOfString(Object val, String... args) { + if (val == null) { + return false; + } + for (String s : args) { + if (s.equalsIgnoreCase(val.toString())) { + return true; + } + } + return false; + } + + private static void generateSchemaAndTableByTableId(ColumnarOption.Param param) throws SQLException { + if (null == param.schemaName) { + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarTableMappingAccessor columnarTableMappingAccessor = new ColumnarTableMappingAccessor(); + columnarTableMappingAccessor.setConnection(connection); + List records = columnarTableMappingAccessor.queryTableId(param.tableId); + if (records.isEmpty()) { + throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, + "Update table version failed: empty columnar records."); + } + param.schemaName = records.get(0).tableSchema; + param.tableName = records.get(0).tableName; + param.indexName = records.get(0).indexName; + } + } + } + + /** + * Record config in system table columnar_config. + */ + public static void setColumnarConfig(ColumnarOption.Param param) { + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + setColumnarConfig(param, metaDbConn); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void setColumnarConfig(ColumnarOption.Param param, Connection connection) { + ColumnarConfigAccessor accessor = new ColumnarConfigAccessor(); + accessor.setConnection(connection); + ColumnarConfigRecord record = new ColumnarConfigRecord(); + record.configKey = param.key.toUpperCase(); + record.configValue = param.value.toUpperCase(); + record.tableId = param.tableId; + accessor.insert(ImmutableList.of(record)); + } + + public static void deleteColumnarConfig(ColumnarOption.Param param, Connection connection) { + ColumnarConfigAccessor accessor = new ColumnarConfigAccessor(); + accessor.setConnection(connection); + ColumnarConfigRecord record = new ColumnarConfigRecord(); + record.configKey = param.key.toUpperCase(); + record.tableId = param.tableId; + accessor.deleteByTableIdAndKey(ImmutableList.of(record)); + } + + static { + ColumnarConfig.init(CONFIG); + } + + public static void init() { + } +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/SelectHandler.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/SelectHandler.java index 3af22b56c..a6e1afb39 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/SelectHandler.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/SelectHandler.java @@ -19,6 +19,7 @@ import com.alibaba.polardbx.druid.sql.parser.ByteString; import com.alibaba.polardbx.server.ServerConnection; import com.alibaba.polardbx.server.parser.ServerParseSelect; +import com.alibaba.polardbx.server.response.SelectColumnarFile; import com.alibaba.polardbx.server.response.SelectEncdbProcessMessage; import com.alibaba.polardbx.server.response.SelectCompatibilityLevel; import com.alibaba.polardbx.server.response.SelectPolardbVersion; @@ -81,6 +82,8 @@ public static boolean handle(ByteString stmt, ServerConnection c, int offs, bool return SelectCompatibilityLevel.execute(c, stmt); case ServerParseSelect.ENCDB_PROCESS_MESSAGE: return SelectEncdbProcessMessage.response(c, hasMore, (String) exData[0]); + case ServerParseSelect.COLUMNAR_FILE: + return SelectColumnarFile.execute(c, hasMore, stmt); default: recordSql = false; return c.execute(stmt, hasMore); diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/ServerLoadDataHandler.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/ServerLoadDataHandler.java index 3235edb94..344faed98 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/ServerLoadDataHandler.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/ServerLoadDataHandler.java @@ -16,12 +16,27 @@ package com.alibaba.polardbx.server.handler; +import com.alibaba.polardbx.PolarPrivileges; +import com.alibaba.polardbx.common.TddlConstants; +import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.logger.MDC; +import com.alibaba.polardbx.common.utils.memory.SizeOf; +import com.alibaba.polardbx.druid.sql.SQLUtils; +import com.alibaba.polardbx.druid.sql.ast.SQLCommentHint; import com.alibaba.polardbx.druid.sql.ast.SQLExpr; +import com.alibaba.polardbx.druid.sql.ast.SQLStatement; import com.alibaba.polardbx.druid.sql.ast.expr.SQLTextLiteralExpr; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlHintStatement; import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlLoadDataInFileStatement; -import com.alibaba.polardbx.common.exception.TddlRuntimeException; -import com.alibaba.polardbx.druid.sql.SQLUtils; +import com.alibaba.polardbx.druid.sql.parser.ByteString; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.privilege.PolarAccountInfo; import com.alibaba.polardbx.gms.topology.DbInfoManager; import com.alibaba.polardbx.druid.sql.ast.SQLExpr; import com.alibaba.polardbx.druid.sql.ast.expr.SQLTextLiteralExpr; @@ -32,20 +47,6 @@ import com.alibaba.polardbx.net.packet.MySQLPacket; import com.alibaba.polardbx.net.packet.OkPacket; import com.alibaba.polardbx.net.util.CharsetUtil; -import com.alibaba.polardbx.server.QueryResultHandler; -import com.alibaba.polardbx.server.ServerConnection; -import com.alibaba.polardbx.druid.sql.ast.SQLCommentHint; -import com.alibaba.polardbx.druid.sql.ast.SQLStatement; -import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlHintStatement; -import com.alibaba.polardbx.druid.sql.parser.ByteString; -import com.google.common.base.Splitter; -import com.alibaba.polardbx.common.exception.TddlNestableRuntimeException; -import com.alibaba.polardbx.common.properties.ConnectionParams; -import com.alibaba.polardbx.common.properties.ParamManager; -import com.alibaba.polardbx.common.utils.logger.Logger; -import com.alibaba.polardbx.common.utils.logger.LoggerFactory; -import com.alibaba.polardbx.common.utils.logger.MDC; -import com.alibaba.polardbx.common.utils.memory.SizeOf; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; import com.alibaba.polardbx.optimizer.config.table.TableMeta; @@ -60,6 +61,9 @@ import com.alibaba.polardbx.optimizer.parse.custruct.FastSqlConstructUtils; import com.alibaba.polardbx.optimizer.parse.visitor.ContextParameters; import com.alibaba.polardbx.optimizer.utils.LoadDataCacheManager; +import com.alibaba.polardbx.server.QueryResultHandler; +import com.alibaba.polardbx.server.ServerConnection; +import com.google.common.base.Splitter; import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.commons.lang.StringEscapeUtils; @@ -81,8 +85,8 @@ import java.util.stream.Collectors; import static com.alibaba.polardbx.common.TddlConstants.IMPLICIT_COL_NAME; -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static com.alibaba.polardbx.optimizer.context.LoadDataContext.END; +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; /** * mysql client need add --local-infile=1 @@ -657,6 +661,16 @@ public void open(String strSql) { dataContext.setSwapColumns(loadData.isSwapColumns()); if (loadData.isLocal()) { handler.sendRequestFilePacket(strSql); + } else { + PolarPrivileges polarPrivileges = (PolarPrivileges) serverConnection.getPrivileges(); + PolarAccountInfo polarUserInfo = polarPrivileges.checkAndGetMatchUser( + serverConnection.getUser(), serverConnection.getHost()); + if (!polarUserInfo.getAccountType().isGod()) { + if (!InstConfUtil.getValBool(TddlConstants.ENABLE_LOAD_DATA_FILE)) { + throw new TddlRuntimeException(ErrorCode.ERR_OPERATION_NOT_ALLOWED, + "load data infile is not enabled!"); + } + } } if (!isClosed.get()) { bStart = true; diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/SetHandler.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/SetHandler.java index 4ae389967..62c9707b3 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/SetHandler.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/SetHandler.java @@ -19,6 +19,8 @@ import com.alibaba.polardbx.PolarPrivileges; import com.alibaba.polardbx.atom.CacheVariables; import com.alibaba.polardbx.common.SQLMode; +import com.alibaba.polardbx.common.TddlConstants; +import com.alibaba.polardbx.common.cdc.ICdcManager; import com.alibaba.polardbx.common.constants.IsolationLevel; import com.alibaba.polardbx.common.constants.ServerVariables; import com.alibaba.polardbx.common.constants.TransactionAttribute; @@ -43,12 +45,18 @@ import com.alibaba.polardbx.executor.balancer.BalanceOptions; import com.alibaba.polardbx.executor.balancer.Balancer; import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.sync.FailPointClearSyncAction; +import com.alibaba.polardbx.executor.sync.FailPointDisableSyncAction; +import com.alibaba.polardbx.executor.sync.FailPointEnableSyncAction; +import com.alibaba.polardbx.executor.sync.SyncManagerHelper; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; import com.alibaba.polardbx.gms.ha.impl.StorageHaManager; import com.alibaba.polardbx.gms.ha.impl.StorageInstHaContext; +import com.alibaba.polardbx.gms.listener.impl.MetaDbConfigManager; +import com.alibaba.polardbx.gms.listener.impl.MetaDbDataIdBuilder; import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; import com.alibaba.polardbx.gms.metadb.cdc.CdcConfigAccessor; import com.alibaba.polardbx.gms.metadb.table.TableInfoManager; @@ -56,6 +64,7 @@ import com.alibaba.polardbx.gms.privilege.ActiveRoles; import com.alibaba.polardbx.gms.privilege.PolarAccountInfo; import com.alibaba.polardbx.gms.privilege.PolarPrivManager; +import com.alibaba.polardbx.gms.sync.SyncScope; import com.alibaba.polardbx.gms.topology.DbTopologyManager; import com.alibaba.polardbx.gms.topology.InstConfigAccessor; import com.alibaba.polardbx.gms.topology.ServerInstIdManager; @@ -129,6 +138,7 @@ public final class SetHandler { static Object RETURN_VALUE = new Object(); private static final String cdcVariablePrefix = "cdc_"; + private static final long UNSIGNED_INT_32_MAX = 0xFFFFFFFFL; /** * @return true:no error packet @@ -167,7 +177,8 @@ public static boolean handleV2(ByteString stmt, ServerConnection c, int offset, //FailPoint command, only works in java -ea mode if (FailPoint.isAssertEnable() && StringUtils.startsWith(lowerCaseKey, SET_PREFIX) && StringUtils.length(lowerCaseKey) >= 3) { - FailPoint.enable(lowerCaseKey, value); + SyncManagerHelper.syncWithDefaultDB(new FailPointEnableSyncAction(lowerCaseKey, value), + SyncScope.ALL); c.getUserDefVariables().put(FP_SHOW, FailPoint.show()); } } else if (oriValue instanceof SqlNumericLiteral) { @@ -177,7 +188,7 @@ public static boolean handleV2(ByteString stmt, ServerConnection c, int offset, c.getUserDefVariables().put(lowerCaseKey, RelUtils.booleanValue(oriValue)); //FailPoint command, only works in java -ea mode if (FailPoint.isAssertEnable() && StringUtils.equalsIgnoreCase(lowerCaseKey, FP_CLEAR)) { - FailPoint.clear(); + SyncManagerHelper.syncWithDefaultDB(new FailPointClearSyncAction(), SyncScope.ALL); c.getUserDefVariables().put(FP_SHOW, FailPoint.show()); } } else if (oriValue instanceof SqlLiteral @@ -186,7 +197,8 @@ public static boolean handleV2(ByteString stmt, ServerConnection c, int offset, c.getUserDefVariables().remove(lowerCaseKey); //FailPoint command, only works in java -ea mode if (FailPoint.isAssertEnable() && StringUtils.startsWith(lowerCaseKey, SET_PREFIX)) { - FailPoint.disable(lowerCaseKey); + SyncManagerHelper.syncWithDefaultDB(new FailPointDisableSyncAction(lowerCaseKey), + SyncScope.ALL); c.getUserDefVariables().put(FP_SHOW, FailPoint.show()); } } else if (oriValue instanceof SqlUserDefVar) { @@ -230,6 +242,12 @@ public static boolean handleV2(ByteString stmt, ServerConnection c, int offset, c.initTddlConnection(); } + if (ServerVariables.isVariablesBlackList(key.getName())) { + c.writeErrMessage(ErrorCode.ER_NOT_SUPPORTED_YET, + "The variable '" + key.getName() + "' is no supported setting"); + return false; + } + boolean enableSetGlobal = true; if (ConnectionProperties.ENABLE_SET_GLOBAL.equalsIgnoreCase(key.getName()) || ConfigDataMode.isFastMock()) { @@ -327,9 +345,38 @@ public static boolean handleV2(ByteString stmt, ServerConnection c, int offset, // ignore update不带主键就会报错 } else if ("NET_WRITE_TIMEOUT".equalsIgnoreCase(key.getName())) { // ignore超时参数,规避DRDS数据导出时,服务端主动关闭连接 - } else if ("SQL_LOG_BIN".equalsIgnoreCase(key.getName())) { - // ignore SQL_LOG_BIN,MySQL - // Dump会加入这种语句,下面的MySQL未必有权限 + } else if (ICdcManager.SQL_LOG_BIN.equalsIgnoreCase(key.getName())) { + if (key.getScope() != null && key.getScope().name().equalsIgnoreCase("global")) { + if (inProcedureCall) { + throw new RuntimeException("not support set global sql_log_bin"); + } + c.writeErrMessage(ErrorCode.ER_NOT_SUPPORTED_YET, + "not support set global sql_log_bin"); + return false; + } + try { + Boolean v; + String value = StringUtils.lowerCase(oriValue.toString()); + if (StringUtils.equals(value, "on")) { + v = true; + } else if (StringUtils.equals(value, "off")) { + v = false; + } else { + v = BooleanUtils.toBoolean(value, "true", "false"); + } + if (v == null) { + throw new RuntimeException( + "Variable 'sql_log_bin' can't be set to the value of " + oriValue); + } + c.getExtraServerVariables().put(ICdcManager.SQL_LOG_BIN, v); + } catch (Exception | Error e) { + if (inProcedureCall) { + throw new RuntimeException("Incorrect argument type to variable 'sql_log_bin'"); + } + c.writeErrMessage(ErrorCode.ER_WRONG_TYPE_FOR_VAR, + "Incorrect argument type to variable 'sql_log_bin'"); + return false; + } } else if ("TIMESTAMP".equalsIgnoreCase(key.getName())) { // ignore max_statement_time for 2.0 } else if ("MAX_STATEMENT_TIME".equalsIgnoreCase(key.getName())) { @@ -692,9 +739,12 @@ public static boolean handleV2(ByteString stmt, ServerConnection c, int offset, return false; } try { - int v = c.getVarIntegerValue(oriValue); + long v = c.getVarLongValue(oriValue); if (v <= 0) { - throw new RuntimeException("polardbx_server_id can`t be less than zero."); + throw new RuntimeException("polardbx_server_id can`t be equal or smaller than zero."); + } + if (v > UNSIGNED_INT_32_MAX) { + throw new RuntimeException("polardbx_server_id can`t be bigger than UNSIGNED_INT_MAX."); } c.getExtraServerVariables().put("polardbx_server_id", v); } catch (Exception | Error e) { @@ -707,13 +757,25 @@ public static boolean handleV2(ByteString stmt, ServerConnection c, int offset, } } else if ("time_zone".equalsIgnoreCase(key.getName())) { //在内部添加到customizeVar中 - c.setTimeZone(c.getVarStringValue(oriValue)); - Object parserValue = parserValue(oriValue, key, c); + String parserValue = String.valueOf(parserValue(oriValue, key, c)); + c.setTimeZone(parserValue); if (parserValue == RETURN_VALUE) { return true; } else if (parserValue != IGNORE_VALUE) { c.getServerVariables().put(key.getName().toLowerCase(), parserValue); } + if (enableSetGlobal && (key.getScope() == VariableScope.GLOBAL)) { + globalCnVariables.add(new Pair(ConnectionProperties.LOGICAL_DB_TIME_ZONE, + parserValue)); + } + } else if (ConnectionProperties.LOGICAL_DB_TIME_ZONE.equalsIgnoreCase(key.getName())) { + //在内部添加到customizeVar中 + String parserValue = String.valueOf(parserValue(oriValue, key, c)); + c.setTimeZone(parserValue); + if (enableSetGlobal && (key.getScope() == VariableScope.GLOBAL)) { + globalCnVariables.add(new Pair(ConnectionProperties.LOGICAL_DB_TIME_ZONE, + parserValue)); + } } else if (ConnectionProperties.SUPPORT_INSTANT_ADD_COLUMN.equalsIgnoreCase(key.getName())) { String value = StringUtils.strip(c.getVarStringValue(oriValue), "'\""); Boolean iacSupported; @@ -1069,7 +1131,43 @@ public static boolean handleV2(ByteString stmt, ServerConnection c, int offset, if (enableSetGlobal && (key.getScope() == VariableScope.GLOBAL)) { globalCnVariables.add(new Pair(key.getName(), Boolean.toString(enable))); } + } else if (ConnectionProperties.ENABLE_EXTERNAL_CONSISTENCY_FOR_WRITE_TRX + .equalsIgnoreCase(key.getName())) { + boolean enable = Boolean.parseBoolean(parserValue(oriValue, key, c).toString()); + c.getConnectionVariables() + .put(ConnectionProperties.ENABLE_EXTERNAL_CONSISTENCY_FOR_WRITE_TRX, enable); + if (enable) { + c.getConnectionVariables().put(ConnectionProperties.ENABLE_XA_TSO, true); + c.getConnectionVariables().put(ConnectionProperties.ENABLE_1PC_OPT, false); + c.getConnectionVariables().put(ConnectionProperties.FORBID_AUTO_COMMIT_TRX, true); + c.getConnectionVariables().put(ConnectionProperties.COMPLEX_DML_WITH_TRX, true); + } else { + c.getConnectionVariables().put(ConnectionProperties.ENABLE_1PC_OPT, true); + c.getConnectionVariables().put(ConnectionProperties.FORBID_AUTO_COMMIT_TRX, false); + c.getConnectionVariables().put(ConnectionProperties.COMPLEX_DML_WITH_TRX, false); + } + if (enableSetGlobal && (key.getScope() == VariableScope.GLOBAL)) { + globalCnVariables.add(new Pair<>(key.getName(), Boolean.toString(enable))); + if (enable) { + globalCnVariables.add( + new Pair<>(ConnectionProperties.ENABLE_XA_TSO, Boolean.toString(true))); + globalCnVariables.add( + new Pair<>(ConnectionProperties.ENABLE_1PC_OPT, Boolean.toString(false))); + globalCnVariables.add( + new Pair<>(ConnectionProperties.FORBID_AUTO_COMMIT_TRX, Boolean.toString(true))); + globalCnVariables.add( + new Pair<>(ConnectionProperties.COMPLEX_DML_WITH_TRX, Boolean.toString(true))); + } else { + globalCnVariables.add( + new Pair<>(ConnectionProperties.ENABLE_1PC_OPT, Boolean.toString(true))); + globalCnVariables.add( + new Pair<>(ConnectionProperties.FORBID_AUTO_COMMIT_TRX, Boolean.toString(false))); + globalCnVariables.add( + new Pair<>(ConnectionProperties.COMPLEX_DML_WITH_TRX, Boolean.toString(false))); + } + } } else if (!isCnVariable(key.getName())) { + // Processing DN variables. if (!ServerVariables.isWritable(key.getName())) { if (enableSetGlobal && key.getScope() == org.apache.calcite.sql.VariableScope.GLOBAL) { //ignore @@ -1145,6 +1243,7 @@ public static boolean handleV2(ByteString stmt, ServerConnection c, int offset, } } } else { + // Processing CN session/global variables. Object parserValue = parserValue(oriValue, key, c); if (parserValue == RETURN_VALUE) { return true; @@ -1388,7 +1487,7 @@ private static UserDefVarProcessingResult userDefVarProcessingFunc(ResultSet res } // return value demonstrates whether write packet - private static boolean handleGlobalVariable(ServerConnection c, List> globalCNVariableList, + protected static boolean handleGlobalVariable(ServerConnection c, List> globalCNVariableList, List> globalDNVariableList, List> globalCdcVariableList) { @@ -1447,7 +1546,7 @@ private static boolean handleGlobalVariable(ServerConnection c, List GROUP_DATASOURCE_CACHE = CacheBuilder.newBuilder() + .maximumSize(1024) + .expireAfterWrite(3600, TimeUnit.SECONDS) + .softValues() + .build(); + + @Override + public boolean execute() { + try (InnerConnection conn = (InnerConnection) InnerConnectionManager.getInstance() + .getConnection(CDC_TABLE_SCHEMA)) { + conn.setExtraServerVariables(ConnectionProperties.MARK_SYNC_POINT, "true"); + conn.setAutoCommit(false); + try (Statement stmt = conn.createStatement()) { + stmt.executeQuery(CdcTableUtil.QUERY_CDC_DDL_RECORD_LIMIT_1); + } + final ITransaction trx = conn.getTransaction(); + final String uuid = UUID.randomUUID().toString(); + if (trx instanceof SyncPointTransaction) { + // 0. Get all groups, group by host:port. + Map> groups = ExecUtils.getInstId2GroupList(CDC_TABLE_SCHEMA); + + ServerThreadPool threadPool = + TransactionManager.getInstance(CDC_TABLE_SCHEMA).getTransactionExecutor().getExecutorService(); + + // 1. Ensure all first-group has a table. + for (List groupList : groups.values()) { + if (groupList.isEmpty()) { + logger.warn("Found empty group."); + return false; + } + + TGroupDataSource firstGroup = groupList.get(0); + if (null != GROUP_DATASOURCE_CACHE.getIfPresent(firstGroup)) { + continue; + } + try (Connection phyConn = firstGroup.getConnection(MasterSlave.MASTER_ONLY); + Statement stmt = phyConn.createStatement()) { + ResultSet rs = stmt.executeQuery(SHOW_TABLE); + if (!rs.next()) { + // Table not found, create a new one. + stmt.execute(CREATE_TABLE); + } + GROUP_DATASOURCE_CACHE.put(firstGroup, true); + } + } + + // 2. Start a rw trx in each DN. + List> futures = new ArrayList<>(); + boolean success = true; + int i = 0; + for (final Map.Entry> entry : groups.entrySet()) { + Callable task = () -> { + try { + String groupName = entry.getKey(); + TGroupDataSource dataSource = entry.getValue().get(0); + IConnection phyConn = + trx.getConnection(CDC_TABLE_SCHEMA, groupName, dataSource, ITransaction.RW.WRITE); + try (Statement stmt = phyConn.createStatement()) { + // Make sure enable_sync_point is on. + ResultSet rs = stmt.executeQuery(SHOW_SYNC_POINT_VAR); + if (!rs.next() || !"ON".equalsIgnoreCase(rs.getString(2))) { + throw new RuntimeException("enable_sync_point is off for " + groupName); + } + // Delete out-dated data. + stmt.execute(DELETE_SQL); + // Insert new data. + stmt.execute(String.format(INSERT_SQL, uuid)); + } + } catch (Throwable t) { + logger.warn("Sync point trx error: " + t.getMessage()); + return false; + } + return true; + }; + i++; + if (i != groups.size()) { + futures.add(threadPool.submit(null, null, task)); + } else { + // Last DN is processed in this thread. + success = task.call(); + } + } + + for (Future future : futures) { + if (!future.get()) { + success = false; + } + } + + if (!success) { + conn.rollback(); + return false; + } + + // 3. Commit trx. + conn.commit(); + int participants = ((SyncPointTransaction) trx).getNumberOfPartitions(); + if (participants != groups.size()) { + throw new RuntimeException( + "Not all DN commit successfully expected: " + groups.size() + ", actual: " + participants); + } + + // 4. After committing trx successfully, write a record in meta-db. + long tso = ((SyncPointTransaction) trx).getCommitTso(); + SyncPointMetaAccessor accessor = new SyncPointMetaAccessor(); + try (Connection connection = MetaDbUtil.getConnection()) { + accessor.setConnection(connection); + // Delete out-dated records. + accessor.delete(); + // Insert a new record. + accessor.insert(uuid, participants, tso); + } + return true; + } + } catch (Throwable t) { + logger.error("Execute sync point trx failed.", t); + } + return false; + } +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/CallHandler.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/CallHandler.java index 08505bcf5..5b225de9a 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/CallHandler.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/CallHandler.java @@ -26,9 +26,9 @@ import com.alibaba.polardbx.executor.ddl.job.task.basic.pl.PlConstants; import com.alibaba.polardbx.executor.pl.PLUtils; import com.alibaba.polardbx.executor.pl.PlContext; +import com.alibaba.polardbx.executor.pl.ProcedureManager; import com.alibaba.polardbx.net.compress.IPacketOutputProxy; import com.alibaba.polardbx.net.compress.PacketOutputProxyFactory; -import com.alibaba.polardbx.executor.pl.ProcedureManager; import com.alibaba.polardbx.optimizer.memory.MemoryAllocatorCtx; import com.alibaba.polardbx.optimizer.memory.MemoryPool; import com.alibaba.polardbx.optimizer.parse.FastsqlUtils; @@ -36,6 +36,8 @@ import com.alibaba.polardbx.optimizer.spill.QuerySpillSpaceMonitor; import com.alibaba.polardbx.server.ServerConnection; import com.alibaba.polardbx.server.handler.SetHandler; +import com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureHandler; +import com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils; import com.alibaba.polardbx.server.util.ProcedureUtils; import java.util.Map; @@ -52,6 +54,10 @@ public boolean handle(ByteString sql, ServerConnection c, boolean hasMore) { ProcedureResultHandler handler = null; try { + if (InnerProcedureUtils.isInnerProcedure(statement)) { + InnerProcedureHandler.handle(statement, c, hasMore); + return true; + } SQLCreateProcedureStatement createProcedureStatement = getProcedureStmt(statement, c); // plContext and procedure result handler will only create once(call statement from user), internal call will reuse diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/BaseInnerProcedure.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/BaseInnerProcedure.java new file mode 100644 index 000000000..b241e185b --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/BaseInnerProcedure.java @@ -0,0 +1,16 @@ +package com.alibaba.polardbx.server.handler.pl.inner; + +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.server.ServerConnection; + +/** + * @author yaozhili + */ +public abstract class BaseInnerProcedure { + + /** + * @param cursor results returned to user + */ + abstract void execute(ServerConnection c, SQLCallStatement statement, ArrayResultCursor cursor); +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarBackupProcedure.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarBackupProcedure.java new file mode 100644 index 000000000..f051020c3 --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarBackupProcedure.java @@ -0,0 +1,32 @@ +package com.alibaba.polardbx.server.handler.pl.inner; + +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.server.ServerConnection; +import org.apache.calcite.sql.SqlKind; + +import static com.alibaba.polardbx.common.columnar.ColumnarUtils.AddCDCMarkEvent; +import static com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils.COLUMNAR_BACKUP; +import static com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils.POLARDBX_INNER_PROCEDURE; + +/** + * @author lijiu + */ +public class ColumnarBackupProcedure extends BaseInnerProcedure { + + @Override + public void execute(ServerConnection c, SQLCallStatement statement, ArrayResultCursor cursor) { + String sql = "call " + POLARDBX_INNER_PROCEDURE + "." + COLUMNAR_BACKUP + "()"; + + Long tso = AddCDCMarkEvent(sql, SqlKind.PROCEDURE_CALL.name()); + + if (tso == null || tso <= 0) { + throw new RuntimeException(sql + " is failed, because tso: " + tso); + } + + //返回结果 + cursor.addColumn("COMMIT_TSO", DataTypes.LongType); + cursor.addRow(new Object[] {tso}); + } +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarFlushProcedure.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarFlushProcedure.java new file mode 100644 index 000000000..854848016 --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarFlushProcedure.java @@ -0,0 +1,120 @@ +package com.alibaba.polardbx.server.handler.pl.inner; + +import com.alibaba.polardbx.druid.sql.ast.SQLExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLNumericLiteralExpr; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableStatus; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.server.ServerConnection; +import org.apache.calcite.sql.SqlKind; + +import java.sql.Connection; +import java.util.List; + +import static com.alibaba.polardbx.common.columnar.ColumnarUtils.AddCDCMarkEvent; +import static com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils.COLUMNAR_FLUSH; +import static com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils.POLARDBX_INNER_PROCEDURE; + +/** + * @author lijiu + */ +public class ColumnarFlushProcedure extends BaseInnerProcedure { + + @Override + public void execute(ServerConnection c, SQLCallStatement statement, ArrayResultCursor cursor) { + String sql = "call " + POLARDBX_INNER_PROCEDURE + "." + COLUMNAR_FLUSH + "()"; + + //支持三种参数: + // 1、columnar_flush(),实例级别 + // 2、columnar_flush(schemaName, tableName, indexName),通过库名、表名、索引名匹配 + // 3、columnar_flush(indexId),通过列存索引id匹配 + + if (statement.getParameters().size() > 0) { + long indexId = checkParameters(statement.getParameters(), statement); + //直接将参数替换成列存索引id + sql = "call " + POLARDBX_INNER_PROCEDURE + "." + COLUMNAR_FLUSH + "(" + indexId + ")"; + } + + Long tso = AddCDCMarkEvent(sql, SqlKind.PROCEDURE_CALL.name()); + + if (tso == null || tso <= 0) { + throw new RuntimeException(sql + " is failed, because tso: " + tso); + } + + //返回结果 + cursor.addColumn("COMMIT_TSO", DataTypes.LongType); + cursor.addRow(new Object[] {tso}); + } + + /** + * 检查参数,返回正确的列存索引ID,未找到则报错 + * + * @return 列存索引ID + */ + private long checkParameters(List params, SQLCallStatement statement) { + //0个参数不需要进该函数 + if (!(params.size() == 1 || params.size() == 3)) { + throw new IllegalArgumentException(statement.toString() + " parameters is not match 0/1/3 parameters"); + } + + if (params.size() == 1) { + //1个参数,代表列存索引ID + if (!(params.get(0) instanceof SQLNumericLiteralExpr)) { + throw new IllegalArgumentException( + statement.toString() + " first parameters need Long number when hava 1 parameters"); + } + long indexId = ((SQLNumericLiteralExpr) params.get(0)).getNumber().longValue(); + + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + ColumnarTableMappingAccessor accessor = new ColumnarTableMappingAccessor(); + accessor.setConnection(metaDbConn); + List records = accessor.queryTableId(indexId); + if (records.isEmpty()) { + throw new IllegalArgumentException( + statement.toString() + " indexId: " + indexId + " not found columnar index"); + } + if (!ColumnarTableStatus.PUBLIC.name().equalsIgnoreCase(records.get(0).status)) { + throw new IllegalArgumentException( + statement.toString() + " indexId: " + indexId + " is not PUBLIC columnar index, status is " + + records.get(0).status); + } + return records.get(0).tableId; + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + //3个参数,schemaName, tableName, indexName,通过库名、表名、索引名匹配 + if (!(params.get(0) instanceof SQLCharExpr) + || !(params.get(1) instanceof SQLCharExpr) + || !(params.get(2) instanceof SQLCharExpr)) { + throw new IllegalArgumentException( + statement.toString() + " first/second/third parameters need String when hava 3 parameters"); + } + + String schemaName = ((SQLCharExpr) params.get(0)).getText(); + String tableName = ((SQLCharExpr) params.get(1)).getText(); + String indexName = ((SQLCharExpr) params.get(2)).getText(); + + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + ColumnarTableMappingAccessor accessor = new ColumnarTableMappingAccessor(); + accessor.setConnection(metaDbConn); + List records = accessor.queryBySchemaTableIndexLike(schemaName, + tableName, indexName + '%', ColumnarTableStatus.PUBLIC.name()); + if (records.isEmpty()) { + throw new IllegalArgumentException( + String.format(" %s.%s index like %s not found columnar index", schemaName, tableName, + indexName)); + } + return records.get(0).tableId; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + } +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarGenerateSnapshots.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarGenerateSnapshots.java new file mode 100644 index 000000000..0aa6b7444 --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarGenerateSnapshots.java @@ -0,0 +1,25 @@ +package com.alibaba.polardbx.server.handler.pl.inner; + +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.scheduler.executor.trx.GenerateColumnarSnapshotScheduledJob; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.server.ServerConnection; + +import java.sql.SQLException; + +public class ColumnarGenerateSnapshots extends BaseInnerProcedure { + @Override + void execute(ServerConnection c, SQLCallStatement statement, ArrayResultCursor cursor) { + cursor.addColumn("STATUS", DataTypes.StringType); + cursor.addColumn("RESULT", DataTypes.StringType); + + StringBuffer sb = new StringBuffer(); + try { + GenerateColumnarSnapshotScheduledJob.generateColumnarSnapshots(sb, true); + cursor.addRow(new Object[] {"OK", sb.toString()}); + } catch (SQLException e) { + cursor.addRow(new Object[] {"FAIL", e.getMessage()}); + } + } +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarRollbackProcedure.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarRollbackProcedure.java new file mode 100644 index 000000000..f175d2c85 --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarRollbackProcedure.java @@ -0,0 +1,290 @@ +package com.alibaba.polardbx.server.handler.pl.inner; + +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.ddl.newengine.DdlType; +import com.alibaba.polardbx.common.utils.AddressUtils; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.druid.sql.ast.SQLExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLIntegerExpr; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.gms.engine.FileSystemManager; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarLeaseAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarLeaseRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPurgeHistoryAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPurgeHistoryRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableStatus; +import com.alibaba.polardbx.gms.metadb.table.FilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.FilesRecord; +import com.alibaba.polardbx.gms.privilege.PolarPrivUtil; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.server.ServerConnection; +import org.apache.commons.lang3.StringUtils; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; + +import java.sql.Connection; +import java.util.List; + +/** + * @author lijiu + */ +public class ColumnarRollbackProcedure extends BaseInnerProcedure { + + private static final Logger LOGGER = LoggerFactory.getLogger("COLUMNAR_TRANS"); + + //特殊值,用于标识rollback的pid + private static final long ROLLBACK_PID = 1; + + @Override + public void execute(ServerConnection c, SQLCallStatement statement, ArrayResultCursor cursor) { + List params = statement.getParameters(); + //必须polardbx_root用户执行,防止普通用户执行 + checkPrivilege(c); + //参数解析 + long tso = checkParameters(params, statement); + + columnarRollback(tso); + + //返回结果 + cursor.addColumn("ROLLBACK_TSO", DataTypes.LongType); + cursor.addRow(new Object[] {tso}); + } + + private void checkPrivilege(ServerConnection c) { + if (!PolarPrivUtil.isPolarxRootUser(c.getUser())) { + throw new RuntimeException("Access denied for user '" + c.getUser() + "'@'" + + c.getHost() + "'" + " to do columnar_rollback()"); + } + } + + private long checkParameters(List params, SQLCallStatement statement) { + if (params.size() != 1) { + throw new IllegalArgumentException(statement.toString() + " parameters is not match 1 parameters"); + } + if (!(params.get(0) instanceof SQLIntegerExpr)) { + throw new IllegalArgumentException(statement.toString() + " parameters need Long number"); + } + SQLIntegerExpr sqlIntegerExpr = (SQLIntegerExpr) params.get(0); + long tso = sqlIntegerExpr.getNumber().longValue(); + if (tso < 0) { + throw new IllegalArgumentException(statement.toString() + " parameters is invalid Long number, need >= 0"); + } + return tso; + } + + private void columnarRollback(long binlogTso) { + ColumnarCheckpointsRecord columnarCheckPoint; + //1、先检测tso值是否有效,获取列存对应的TSO + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + ColumnarCheckpointsAccessor checkpointsAccessor = new ColumnarCheckpointsAccessor(); + checkpointsAccessor.setConnection(metaDbConn); + + List checkpointsRecords = + checkpointsAccessor.queryColumnarTsoByBinlogTso(binlogTso); + if (checkpointsRecords.isEmpty()) { + throw new RuntimeException("Not found columnar commit tso, can't rollback to " + binlogTso); + } + columnarCheckPoint = checkpointsRecords.get(0); + + //获取purgeTso + ColumnarPurgeHistoryAccessor purgeHistoryAccessor = new ColumnarPurgeHistoryAccessor(); + purgeHistoryAccessor.setConnection(metaDbConn); + List purgeRecords = purgeHistoryAccessor.queryLastPurgeTso(); + long purgeTso = 0; + if (!purgeRecords.isEmpty()) { + purgeTso = purgeRecords.get(0).tso; + } + if (purgeTso > columnarCheckPoint.checkpointTso) { + throw new RuntimeException("Can't rollback to " + binlogTso + " which < purgeTso: " + purgeTso); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + LOGGER.warn( + "START to ROLLBACK COLUMNAR to " + columnarCheckPoint.checkpointTso + " from binlogTso: " + binlogTso); + + //2、抢主执行回滚操作 + String owner = getColumnarNodeName(); + long startMs; + long lastNodeLease; + try { + //抢主 + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + ColumnarLeaseAccessor leaseAccessor = new ColumnarLeaseAccessor(); + leaseAccessor.setConnection(metaDbConn); + + //默认1小时 + startMs = System.currentTimeMillis(); + lastNodeLease = leaseAccessor.forceElectInsert(owner, startMs, 3600 * 1000); + if (lastNodeLease < 0) { + //insert失败,开启事务执行, select for update + metaDbConn.setAutoCommit(false); + + //锁超时设置为5s,防止select for update等太久 + MetaDbUtil.execute("SET SESSION innodb_lock_wait_timeout = 5;", metaDbConn); + List lastLeaseRecords = leaseAccessor.forceElectSelectForUpdate(); + if (lastLeaseRecords.size() != 1) { + throw new RuntimeException("Force Elect columnar Leader failed by select for update"); + } + ColumnarLeaseRecord lastLeaseRecord = lastLeaseRecords.get(0); + String[] parts = lastLeaseRecord.owner.split("@"); + if (lastLeaseRecord.lease > startMs && parts.length == 3 + && Long.parseLong(parts[1]) == ROLLBACK_PID) { + //存在别的节点执行columnar_rollback() + throw new RuntimeException( + "Force Elect columnar Leader failed by have another columnar_rollback() op by " + parts[0]); + } + + startMs = System.currentTimeMillis(); + leaseAccessor.forceElectUpdate(owner, startMs, 3600 * 1000); + lastNodeLease = lastLeaseRecord.lease; + + metaDbConn.commit(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + //等待上一个节点的leader时间过期 + if (lastNodeLease > 0 && lastNodeLease > startMs) { + if ((lastNodeLease - startMs) > 100000) { + //超过100s,认为不可等待,抛错 + throw new RuntimeException( + "Can't rollback to " + binlogTso + ", because last columnar leader have lease time: " + + (lastNodeLease - startMs) + " ms > 100 s"); + } + LOGGER.warn("Wait last columnar leader lease time: " + (lastNodeLease - startMs) + " ms"); + Thread.sleep(lastNodeLease - startMs); + } + + //回滚列存元数据 + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + //TODO:事务超过DN限制的binlog大小,一般备份恢复不会时间间隔很大,暂时开事务,保证一致性 + metaDbConn.setAutoCommit(false); + FilesAccessor filesAccessor = new FilesAccessor(); + filesAccessor.setConnection(metaDbConn); + ColumnarCheckpointsAccessor checkpointsAccessor = new ColumnarCheckpointsAccessor(); + checkpointsAccessor.setConnection(metaDbConn); + + //1、删除新增的orc文件 + filesAccessor.deleteOrcMetaByCommitTso(columnarCheckPoint.checkpointTso); + + //2、修改remove_ts,删除文件删除标记 + filesAccessor.updateRemoveTsByTso(columnarCheckPoint.checkpointTso); + + //3、删除新增的追加写文件,csv文件,del文件,set文件 + filesAccessor.deleteThreeMetaByCommitTso(columnarCheckPoint.checkpointTso); + + //4、删除新增追加写的append记录 + ColumnarAppendedFilesAccessor appendedFilesAccessor = new ColumnarAppendedFilesAccessor(); + appendedFilesAccessor.setConnection(metaDbConn); + appendedFilesAccessor.deleteByTso(columnarCheckPoint.checkpointTso); + + //5、ddl事件恢复 + ColumnarTableEvolutionAccessor tableEvolutionAccessor = new ColumnarTableEvolutionAccessor(); + tableEvolutionAccessor.setConnection(metaDbConn); + List tableEvolutionRecords = + tableEvolutionAccessor.queryByOverCommitTs(columnarCheckPoint.checkpointTso); + if (!tableEvolutionRecords.isEmpty()) { + for (ColumnarTableEvolutionRecord tableEvolutionRecord : tableEvolutionRecords) { + if (tableEvolutionRecord.ddlType.equals(DdlType.CREATE_INDEX.name())) { + //创建索引,如果是public状态,改会creating状态 + ColumnarTableMappingAccessor tableMappingAccessor = new ColumnarTableMappingAccessor(); + tableMappingAccessor.setConnection(metaDbConn); + tableMappingAccessor.updateStatusByTableIdAndStatus(tableEvolutionRecord.tableId, + ColumnarTableStatus.PUBLIC.name(), ColumnarTableStatus.CREATING.name()); + } + //其它ddl,暂时没有额外操作 + } + //将ddl commit ts该回未提交状态 + tableEvolutionAccessor.updateCommitTs(columnarCheckPoint.checkpointTso); + } + + //6、compaction事件恢复 + if (columnarCheckPoint.minCompactionTso > 0) { + //如果有compaction,找到所有小于checkpoint Tso后提交的compaction + List columnarCheckpointsRecords = + checkpointsAccessor.queryCompactionByStartTsoAndEndTso(columnarCheckPoint.minCompactionTso, + columnarCheckPoint.checkpointTso); + for (ColumnarCheckpointsRecord compactionRecord : columnarCheckpointsRecords) { + //判断该compaction需不需要回滚 + boolean needRollback = false; + List compactionFilesRecords = + filesAccessor.queryCompactionFileByTsoAndTable(compactionRecord.checkpointTso, + compactionRecord.logicalSchema, compactionRecord.logicalTable); + if (!compactionFilesRecords.isEmpty()) { + //检查所有文件是否存在,理论上检查一个文件即可,因为批量文件提交是原子的 + try { + FileSystem fileSystem = FileSystemManager.getFileSystemGroup( + Engine.of(compactionFilesRecords.get(0).getEngine())).getMaster(); + boolean exists = fileSystem.exists(new Path(compactionFilesRecords.get(0).fileName)); + if (!exists) { + needRollback = true; + } + } catch (Exception e) { + //检查报错,认为需要回滚 + LOGGER.warn("check " + compactionFilesRecords.get(0).fileName + " file in " + + compactionFilesRecords.get(0).getEngine() + " exist failed!", e); + needRollback = true; + } + } + if (needRollback) { + LOGGER.warn(compactionRecord.info + " compaction will rollback, tso: " + + compactionRecord.checkpointTso); + //compaction 删除标的恢复 + filesAccessor.updateCompactionRemoveTsByTso(compactionRecord.logicalSchema, + compactionRecord.logicalTable, compactionRecord.checkpointTso); + //compaction 新增文件删除 + filesAccessor.deleteCompactionFileByCommitTso(compactionRecord.logicalSchema, + compactionRecord.logicalTable, compactionRecord.checkpointTso); + //compaction 追加写回滚 + appendedFilesAccessor.deleteByEqualTso(compactionRecord.checkpointTso); + //compaction 版本记录删除 + checkpointsAccessor.deleteCompactionByTso(compactionRecord.checkpointTso); + } + + } + } + + //7、删除多余的checkpoints + checkpointsAccessor.deleteByTso(columnarCheckPoint.checkpointTso); + metaDbConn.commit(); + } + + LOGGER.warn( + "Success ROLLBACK COLUMNAR to " + columnarCheckPoint.checkpointTso + " from binlogTso: " + binlogTso); + } catch (Exception e) { + LOGGER.warn(e); + throw new RuntimeException(e); + } finally { + //必须释放主 + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + ColumnarLeaseAccessor leaseAccessor = new ColumnarLeaseAccessor(); + leaseAccessor.setConnection(metaDbConn); + leaseAccessor.delete(owner); + } catch (Exception e) { + LOGGER.warn(e); + } + } + } + + public static String getColumnarNodeName() { + String nodeIp = AddressUtils.getHostIp(); + if (StringUtils.isEmpty(nodeIp)) { + nodeIp = "notFound"; + } + final long startTime = System.currentTimeMillis(); + + return nodeIp + '@' + ROLLBACK_PID + '@' + startTime; + } +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarSetConfigProcedure.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarSetConfigProcedure.java new file mode 100644 index 000000000..4fa7f166c --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarSetConfigProcedure.java @@ -0,0 +1,183 @@ +package com.alibaba.polardbx.server.handler.pl.inner; + +import com.alibaba.polardbx.druid.sql.ast.SQLExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLBooleanExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLIntegerExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLNumericLiteralExpr; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableStatus; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.server.ServerConnection; +import com.google.common.collect.ImmutableList; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author lijiu + */ +public class ColumnarSetConfigProcedure extends BaseInnerProcedure { + + @Override + public void execute(ServerConnection c, SQLCallStatement statement, ArrayResultCursor cursor) { + List params = statement.getParameters(); + //参数解析 + List parameters = checkParameters(params, statement); + + //设置列存参数 + List result = setColumnarConfig(parameters); + + if (result.size() == 3) { + cursor.addColumn("index_id", DataTypes.LongType); + cursor.addColumn("key", DataTypes.StringType); + cursor.addColumn("value", DataTypes.StringType); + cursor.addRow(new Object[] {result.get(0), result.get(1), result.get(2)}); + } else if (result.size() == 2) { + cursor.addColumn("key", DataTypes.StringType); + cursor.addColumn("value", DataTypes.StringType); + cursor.addRow(new Object[] {result.get(0), result.get(1)}); + } else if (result.size() == 6) { + cursor.addColumn("schema_name", DataTypes.StringType); + cursor.addColumn("table_name", DataTypes.StringType); + cursor.addColumn("index_name", DataTypes.StringType); + cursor.addColumn("index_id", DataTypes.LongType); + cursor.addColumn("key", DataTypes.StringType); + cursor.addColumn("value", DataTypes.StringType); + cursor.addRow(new Object[] { + result.get(0), result.get(1), result.get(2), result.get(3), result.get(4), + result.get(5)}); + } + } + + /** + * 3个参数时,第一个是table id,代表设置表级别;后面两个是key,value + * 2个参数时,代表实例级别;后面两个是key,value + * 5个参数时,代表设置某个索引的参数,schema、table、index、key、value + */ + private List checkParameters(List params, SQLCallStatement statement) { + //参数不是两个,或者3个,5个报错 + if (!(params.size() == 2 || params.size() == 3 || params.size() == 5)) { + throw new IllegalArgumentException(statement.toString() + " parameters is not match 2/3/5 parameters"); + } + if (params.size() == 3 && !(params.get(0) instanceof SQLIntegerExpr)) { + throw new IllegalArgumentException( + statement.toString() + " first parameters need Long number when hava 3 parameters"); + } + if (params.size() == 5 + && (!(params.get(0) instanceof SQLCharExpr) + || !(params.get(1) instanceof SQLCharExpr) + || !(params.get(2) instanceof SQLCharExpr))) { + throw new IllegalArgumentException( + statement.toString() + " first/second/third parameters need String when hava 5 parameters"); + } + //默认0是实例级别 + SQLExpr key; + SQLExpr value; + if (params.size() == 3) { + key = params.get(1); + value = params.get(2); + } else if (params.size() == 2) { + key = params.get(0); + value = params.get(1); + } else { + key = params.get(3); + value = params.get(4); + } + + if (!(key instanceof SQLCharExpr)) { + throw new IllegalArgumentException(statement.toString() + " key parameters need String"); + } + + String setKey = ((SQLCharExpr) key).getText(); + String setValue; + + if (value instanceof SQLCharExpr) { + setValue = ((SQLCharExpr) value).getText(); + } else if (value instanceof SQLNumericLiteralExpr) { + setValue = String.valueOf(((SQLNumericLiteralExpr) value).getNumber()); + } else if (value instanceof SQLBooleanExpr) { + setValue = String.valueOf(((SQLBooleanExpr) value).getBooleanValue()); + } else { + throw new IllegalArgumentException(value + " value parameters need String"); + } + + List result = new ArrayList<>(); + + if (params.size() == 3) { + long tableId = ((SQLIntegerExpr) params.get(0)).getNumber().longValue(); + result.add(tableId); + } else if (params.size() == 5) { + String schema_name = ((SQLCharExpr) params.get(0)).getText(); + String table_name = ((SQLCharExpr) params.get(1)).getText(); + String index_name = ((SQLCharExpr) params.get(2)).getText(); + result.add(schema_name); + result.add(table_name); + result.add(index_name); + } + + result.add(setKey); + result.add(setValue); + + return result; + } + + private List setColumnarConfig(List parameters) { + List result = parameters; + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + ColumnarConfigAccessor accessor = new ColumnarConfigAccessor(); + accessor.setConnection(metaDbConn); + ColumnarConfigRecord record = new ColumnarConfigRecord(); + if (parameters.size() == 3) { + record.tableId = (long) parameters.get(0); + record.configKey = (String) parameters.get(1); + record.configValue = (String) parameters.get(2); + } else if (parameters.size() == 2) { + record.configKey = (String) parameters.get(0); + record.configValue = (String) parameters.get(1); + } else if (parameters.size() == 5) { + ColumnarTableMappingAccessor tableMappingAccessor = new ColumnarTableMappingAccessor(); + tableMappingAccessor.setConnection(metaDbConn); + String schemaName = (String) parameters.get(0); + String tableName = (String) parameters.get(1); + String indexName = (String) parameters.get(2) + '%'; + List records = tableMappingAccessor.queryBySchemaTableIndexLike(schemaName, + tableName, indexName, ColumnarTableStatus.PUBLIC.name()); + if (records.isEmpty()) { + throw new IllegalArgumentException( + String.format(" %s.%s index like %s not found columnar index", schemaName, tableName, + indexName)); + } + if (records.size() >= 2) { + throw new IllegalArgumentException( + String.format(" %s.%s index %s found more than one columnar index[%s]", schemaName, tableName, + indexName, records.stream().map(r -> r.indexName).collect(Collectors.joining(",")))); + } + record.tableId = records.get(0).tableId; + record.configKey = (String) parameters.get(3); + record.configValue = (String) parameters.get(4); + + result = new ArrayList<>(6); + result.add(records.get(0).tableSchema); + result.add(records.get(0).tableName); + result.add(records.get(0).indexName); + result.add(records.get(0).tableId); + result.add(record.configKey); + result.add(record.configValue); + } + accessor.insert(ImmutableList.of(record)); + return result; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarSnapshotFilesProcedure.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarSnapshotFilesProcedure.java new file mode 100644 index 000000000..a80792e9a --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/ColumnarSnapshotFilesProcedure.java @@ -0,0 +1,170 @@ +package com.alibaba.polardbx.server.handler.pl.inner; + +import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.druid.sql.ast.SQLExpr; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLIntegerExpr; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPurgeHistoryAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPurgeHistoryRecord; +import com.alibaba.polardbx.gms.metadb.table.FileInfoRecord; +import com.alibaba.polardbx.gms.metadb.table.FilesAccessor; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.server.ServerConnection; +import lombok.Data; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + +/** + * @author lijiu + */ +public class ColumnarSnapshotFilesProcedure extends BaseInnerProcedure { + + @Override + public void execute(ServerConnection c, SQLCallStatement statement, ArrayResultCursor cursor) { + List params = statement.getParameters(); + //参数解析 + long tso = checkParameters(params, statement); + + //获取文件 + List fileInfos = getSnapshotFilesInfo(tso); + + //排序 + fileInfos.sort((o1, o2) -> { + if (o1.getFileType() == o2.getFileType()) { + return o1.getFileName().compareTo(o2.getFileName()); + } else { + return Integer.compare(o1.getFileType(), o2.getFileType()); + } + }); + + //返回结果 + cursor.addColumn("file_name", DataTypes.StringType); + cursor.addColumn("file_length", DataTypes.LongType); + cursor.addColumn("file_type", DataTypes.IntegerType); + for (FileInfo fileInfo : fileInfos) { + cursor.addRow(new Object[] {fileInfo.getFileName(), fileInfo.getFileLength(), fileInfo.getFileType()}); + } + } + + private long checkParameters(List params, SQLCallStatement statement) { + if (params.size() != 1) { + throw new IllegalArgumentException(statement.toString() + " parameters is not match 1 parameters"); + } + if (!(params.get(0) instanceof SQLIntegerExpr)) { + throw new IllegalArgumentException(statement.toString() + " parameters need Long number"); + } + SQLIntegerExpr sqlIntegerExpr = (SQLIntegerExpr) params.get(0); + long tso = sqlIntegerExpr.getNumber().longValue(); + if (tso < 0) { + throw new IllegalArgumentException(statement.toString() + " parameters is invalid Long number, need >= 0"); + } + return tso; + } + + @Data + private static class FileInfo { + String fileName; + long fileLength; + /** + * 0:固定长度文件;1:追加写文件 + */ + int fileType; + } + + private List getSnapshotFilesInfo(long binlogTso) { + List fileInfos = new ArrayList<>(); + try (Connection metaDbConn = MetaDbUtil.getConnection()) { + //1,根据行存的tso获取列存的tso + ColumnarCheckpointsAccessor checkpointsAccessor = new ColumnarCheckpointsAccessor(); + checkpointsAccessor.setConnection(metaDbConn); + ColumnarCheckpointsRecord columnarCheckPoint; + long waitTimeLimit = DynamicConfig.getInstance().getWaitForColumnarCommitMS(); + long waitTime = 0; + while (true) { + //循环等待1s查询,直到列存同步到该位点,或60s超时 + List checkpointsRecords = + checkpointsAccessor.queryColumnarTsoByBinlogTso(binlogTso); + if (!checkpointsRecords.isEmpty()) { + columnarCheckPoint = checkpointsRecords.get(0); + break; + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + waitTime += 1000; + if (waitTime > waitTimeLimit) { + throw new RuntimeException( + "Wait for Columnar commit to " + binlogTso + ", wait " + waitTimeLimit + " ms timeout."); + } + } + + //2、根据列存版本tso获取所有有效文件,长度,类型 + //a、获取purge的水位线,当作下水位限 + ColumnarPurgeHistoryAccessor purgeHistoryAccessor = new ColumnarPurgeHistoryAccessor(); + purgeHistoryAccessor.setConnection(metaDbConn); + List purgeRecords = purgeHistoryAccessor.queryLastPurgeTso(); + long purgeTso = 0; + if (!purgeRecords.isEmpty()) { + purgeTso = purgeRecords.get(0).tso; + } + //b、直接files系统表扫描,COLUMNAR_TABLE_MAPPING_TABLE表直接关联,以防冷数据归档文件,这样获取的文件可能会多一些,精细化的话要列存版本tso需要排除ddl操作的表,在恢复时处理更好 + //先获取固定长度文件,orc文件,主键索引sst文件 + FilesAccessor filesAccessor = new FilesAccessor(); + filesAccessor.setConnection(metaDbConn); + List filesRecords = + filesAccessor.queryORCAndSSTFileInfoByTso(purgeTso, columnarCheckPoint.checkpointTso); + for (FileInfoRecord fileInfoRecord : filesRecords) { + FileInfo fileInfo = new FileInfo(); + fileInfo.setFileName(fileInfoRecord.fileName); + fileInfo.setFileLength(fileInfoRecord.extentSize); + fileInfo.setFileType(0); + fileInfos.add(fileInfo); + } + //c、再获取追加写文件,csv文件、del文件、set文件,也需获取长度 + ColumnarAppendedFilesAccessor columnarAppendedFilesAccessor = new ColumnarAppendedFilesAccessor(); + columnarAppendedFilesAccessor.setConnection(metaDbConn); + List appendedFilesRecords = + columnarAppendedFilesAccessor.queryLastValidAppendByStartTsoAndEndTso(purgeTso, + columnarCheckPoint.checkpointTso); + for (ColumnarAppendedFilesRecord fileInfoRecord : appendedFilesRecords) { + if (fileInfoRecord.getAppendOffset() + fileInfoRecord.getAppendLength() == 0) { + //过滤长度为0的文件 + continue; + } + FileInfo fileInfo = new FileInfo(); + fileInfo.setFileName(fileInfoRecord.fileName); + fileInfo.setFileLength(fileInfoRecord.getAppendOffset() + fileInfoRecord.getAppendLength()); + fileInfo.setFileType(1); + fileInfos.add(fileInfo); + } + //d、获取主键索引的log文件和长度 + List pkIndexRecords = + columnarAppendedFilesAccessor.queryFilesByFileType("pk_idx_log_meta"); + for (ColumnarAppendedFilesRecord fileInfoRecord : pkIndexRecords) { + if (fileInfoRecord.getAppendOffset() + fileInfoRecord.getAppendLength() == 0) { + //过滤长度为0的文件 + continue; + } + FileInfo fileInfo = new FileInfo(); + fileInfo.setFileName(fileInfoRecord.fileName); + fileInfo.setFileLength(fileInfoRecord.getAppendOffset() + fileInfoRecord.getAppendLength()); + fileInfo.setFileType(1); + fileInfos.add(fileInfo); + } + + } catch (Exception e) { + throw new RuntimeException(e); + } + return fileInfos; + } +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/InnerProcedureHandler.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/InnerProcedureHandler.java new file mode 100644 index 000000000..87facab8a --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/InnerProcedureHandler.java @@ -0,0 +1,66 @@ +package com.alibaba.polardbx.server.handler.pl.inner; + +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.matrix.jdbc.TResultSet; +import com.alibaba.polardbx.server.QueryResultHandler; +import com.alibaba.polardbx.server.ServerConnection; +import com.google.common.collect.ImmutableMap; + +import java.util.concurrent.atomic.AtomicLong; + +import static com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils.COLUMNAR_BACKUP; +import static com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils.COLUMNAR_FLUSH; +import static com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils.COLUMNAR_GENERATE_SNAPSHOTS; +import static com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils.COLUMNAR_ROLLBACK; +import static com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils.COLUMNAR_SET_CONFIG; +import static com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils.COLUMNAR_SNAPSHOT_FILES; +import static com.alibaba.polardbx.server.handler.pl.inner.InnerProcedureUtils.TRIGGER_SYNC_POINT_TRX; + +/** + * @author yaozhili + */ +public class InnerProcedureHandler { + private static final ImmutableMap INNER_PROCEDURES; + + static { + INNER_PROCEDURES = ImmutableMap.builder() + .put(TRIGGER_SYNC_POINT_TRX, new TriggerSyncPointTrx()) + .put(COLUMNAR_FLUSH, new ColumnarFlushProcedure()) + .put(COLUMNAR_BACKUP, new ColumnarBackupProcedure()) + .put(COLUMNAR_SNAPSHOT_FILES, new ColumnarSnapshotFilesProcedure()) + .put(COLUMNAR_SET_CONFIG, new ColumnarSetConfigProcedure()) + .put(COLUMNAR_ROLLBACK, new ColumnarRollbackProcedure()) + .put(COLUMNAR_GENERATE_SNAPSHOTS, new ColumnarGenerateSnapshots()) + .build(); + } + + public static void handle(SQLCallStatement statement, + ServerConnection c, + boolean hashMore) { + String procedureName = statement.getProcedureName().getSimpleName().toLowerCase(); + BaseInnerProcedure procedure = INNER_PROCEDURES.get(procedureName); + if (null != procedure) { + ArrayResultCursor cursor = new ArrayResultCursor(procedureName); + // Execute inner procedure. + procedure.execute(c, statement, cursor); + // Send result. + sendResult(c, hashMore, cursor); + } else { + c.writeErrMessage(ErrorCode.ERR_PROCEDURE_NOT_FOUND, + "Not found any inner procedure " + procedureName); + } + } + + private static void sendResult(ServerConnection c, boolean hashMore, ArrayResultCursor cursor) { + QueryResultHandler queryResultHandler = c.createResultHandler(hashMore); + try { + queryResultHandler.sendSelectResult(new TResultSet(cursor, null), + new AtomicLong(0), Long.MAX_VALUE); + } catch (Throwable t) { + c.writeErrMessage(ErrorCode.ERR_PROCEDURE_EXECUTE, t.getMessage()); + } + queryResultHandler.sendPacketEnd(false); + } +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/InnerProcedureUtils.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/InnerProcedureUtils.java new file mode 100644 index 000000000..ca9c6ac2b --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/InnerProcedureUtils.java @@ -0,0 +1,27 @@ +package com.alibaba.polardbx.server.handler.pl.inner; + +import com.alibaba.polardbx.druid.sql.ast.SQLName; +import com.alibaba.polardbx.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; + +public class InnerProcedureUtils { + public static final String POLARDBX_INNER_PROCEDURE = "polardbx"; + + //忽略大小写 + public static final String TRIGGER_SYNC_POINT_TRX = "trigger_sync_point_trx"; + public static final String COLUMNAR_FLUSH = "columnar_flush"; + public static final String COLUMNAR_BACKUP = "columnar_backup"; + public static final String COLUMNAR_SNAPSHOT_FILES = "columnar_snapshot_files"; + public static final String COLUMNAR_SET_CONFIG = "columnar_set_config"; + public static final String COLUMNAR_ROLLBACK = "columnar_rollback"; + public static final String COLUMNAR_GENERATE_SNAPSHOTS = "columnar_generate_snapshots"; + + public static boolean isInnerProcedure(SQLCallStatement stmt) { + SQLName procedureName = stmt.getProcedureName(); + if (procedureName instanceof SQLPropertyExpr) { + String owner = ((SQLPropertyExpr) procedureName).getOwnerName(); + return POLARDBX_INNER_PROCEDURE.equalsIgnoreCase(owner); + } + return false; + } +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/TriggerSyncPointTrx.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/TriggerSyncPointTrx.java new file mode 100644 index 000000000..f789522fb --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/handler/pl/inner/TriggerSyncPointTrx.java @@ -0,0 +1,25 @@ +package com.alibaba.polardbx.server.handler.pl.inner; + +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; +import com.alibaba.polardbx.server.ServerConnection; +import com.alibaba.polardbx.server.handler.SyncPointExecutor; + +/** + * @author yaozhili + */ +public class TriggerSyncPointTrx extends BaseInnerProcedure { + + @Override + void execute(ServerConnection c, SQLCallStatement statement, ArrayResultCursor cursor) { + cursor.addColumn("RESULT", DataTypes.StringType); + + SyncPointExecutor executor = SyncPointExecutor.getInstance(); + if (executor.execute()) { + cursor.addRow(new Object[] {"OK"}); + } else { + cursor.addRow(new Object[] {"FAIL"}); + } + } +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/parser/ServerParseSelect.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/parser/ServerParseSelect.java index 5fb5d855b..309ca14a9 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/parser/ServerParseSelect.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/parser/ServerParseSelect.java @@ -48,7 +48,8 @@ public final class ServerParseSelect { public static final int POLARDB_VERSION = 16; public static final int COMPATIBILITY_LEVEL = 17; public static final int ENCDB_PROCESS_MESSAGE = 18; - public static final int SESSION_TRANSACTION_READ_ONLY = 19; + public static final int COLUMNAR_FILE = 19; + public static final int SESSION_TRANSACTION_READ_ONLY = 20; public static final Set PREPARE_UNSUPPORTED_SELECT_TYPE; private static final char[] _VERSION_COMMENT = "VERSION_COMMENT".toCharArray(); @@ -65,6 +66,7 @@ public final class ServerParseSelect { private static final char[] _SESSION_TRANSACTION_READ_ONLY = "SESSION.TRANSACTION_READ_ONLY".toCharArray(); private static final char[] _COMPATIBILITY_LEVEL = "COMPATIBILITY_LEVEL".toCharArray(); private static final char[] _ENCDB_PROCESS_MESSAGE = "ENCDB_PROCESS_MESSAGE".toCharArray(); + private static final char[] _COLUMNAR_FILE = "COLUMNAR_FILE".toCharArray(); static { PREPARE_UNSUPPORTED_SELECT_TYPE = new HashSet<>(); @@ -84,6 +86,7 @@ public final class ServerParseSelect { PREPARE_UNSUPPORTED_SELECT_TYPE.add(SEQ_SKIP_BENCHMARK); PREPARE_UNSUPPORTED_SELECT_TYPE.add(COMPATIBILITY_LEVEL); PREPARE_UNSUPPORTED_SELECT_TYPE.add(ENCDB_PROCESS_MESSAGE); + PREPARE_UNSUPPORTED_SELECT_TYPE.add(COLUMNAR_FILE); } public static int parse(String stmt, int offset, Object[] exData) { @@ -585,6 +588,8 @@ private static int cCheck(ByteString stmt, int offset) { } } else if (ParseUtil.compare(stmt, offset, _COMPATIBILITY_LEVEL)) { return COMPATIBILITY_LEVEL; + } else if (ParseUtil.compare(stmt, offset, _COLUMNAR_FILE)) { + return COLUMNAR_FILE; } return OTHER; } diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/PurgeTransHandler.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/PurgeTransHandler.java index f870f9945..e28fa9b49 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/PurgeTransHandler.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/PurgeTransHandler.java @@ -97,7 +97,7 @@ protected boolean doExecute() { } if (2 == v || 0 == v) { - StringBuilder remark = new StringBuilder(); + StringBuffer remark = new StringBuffer(); try { purgedCount += CleanLogTableTask.run(true, remark); } catch (Throwable ex) { diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ReloadHandler.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ReloadHandler.java index 36390abfe..7618b788b 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ReloadHandler.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ReloadHandler.java @@ -168,15 +168,61 @@ public static boolean handle(ByteString sqlBytes, ServerConnection c) { return true; } - pattern = "RELOAD[\\s]+COLUMNARMANAGER"; + pattern = "RELOAD[\\s]+COLUMNARMANAGER.*"; r = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); m = r.matcher(stmt); if (m.matches()) { - SyncManagerHelper - .sync(new ReloadSyncAction(ReloadUtils.ReloadType.COLUMNARMANAGER, c.getSchema()), c.getSchema(), - SyncScope.ALL); - PacketOutputProxyFactory.getInstance().createProxy(c).writeArrayAsPacket(OkPacket.OK); - return true; + String subPattern; + Pattern subR; + Matcher subM; + + subPattern = "RELOAD[\\s]+COLUMNARMANAGER[\\s]+CACHE"; + subR = Pattern.compile(subPattern, Pattern.CASE_INSENSITIVE); + subM = subR.matcher(stmt); + if (subM.matches()) { + SyncManagerHelper + .sync(new ReloadSyncAction(ReloadUtils.ReloadType.COLUMNARMANAGER_CACHE, c.getSchema()), + c.getSchema(), + SyncScope.ALL); + PacketOutputProxyFactory.getInstance().createProxy(c).writeArrayAsPacket(OkPacket.OK); + return true; + } + + subPattern = "RELOAD[\\s]+COLUMNARMANAGER[\\s]+SNAPSHOT"; + subR = Pattern.compile(subPattern, Pattern.CASE_INSENSITIVE); + subM = subR.matcher(stmt); + if (subM.matches()) { + SyncManagerHelper + .sync(new ReloadSyncAction(ReloadUtils.ReloadType.COLUMNARMANAGER_SNAPSHOT, c.getSchema()), + c.getSchema(), + SyncScope.ALL); + PacketOutputProxyFactory.getInstance().createProxy(c).writeArrayAsPacket(OkPacket.OK); + return true; + } + + subPattern = "RELOAD[\\s]+COLUMNARMANAGER[\\s]+SCHEMA"; + subR = Pattern.compile(subPattern, Pattern.CASE_INSENSITIVE); + subM = subR.matcher(stmt); + if (subM.matches()) { + SyncManagerHelper + .sync(new ReloadSyncAction(ReloadUtils.ReloadType.COLUMNARMANAGER_SCHEMA, c.getSchema()), + c.getSchema(), + SyncScope.ALL); + PacketOutputProxyFactory.getInstance().createProxy(c).writeArrayAsPacket(OkPacket.OK); + return true; + } + + subPattern = "RELOAD[\\s]+COLUMNARMANAGER"; + subR = Pattern.compile(subPattern, Pattern.CASE_INSENSITIVE); + subM = subR.matcher(stmt); + if (subM.matches()) { + SyncManagerHelper + .sync(new ReloadSyncAction(ReloadUtils.ReloadType.COLUMNARMANAGER, c.getSchema()), + c.getSchema(), + SyncScope.ALL); + PacketOutputProxyFactory.getInstance().createProxy(c).writeArrayAsPacket(OkPacket.OK); + return true; + } } recordSql = false; diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/SelectColumnarFile.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/SelectColumnarFile.java new file mode 100644 index 000000000..3afaa13d3 --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/SelectColumnarFile.java @@ -0,0 +1,298 @@ +package com.alibaba.polardbx.server.response; + +import com.alibaba.polardbx.Fields; +import com.alibaba.polardbx.common.Engine; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.oss.ColumnarFileType; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.druid.sql.parser.ByteString; +import com.alibaba.polardbx.executor.chunk.Chunk; +import com.alibaba.polardbx.executor.columnar.DeletionFileReader; +import com.alibaba.polardbx.executor.columnar.SimpleCSVFileReader; +import com.alibaba.polardbx.executor.columnar.SimpleDeletionFileReader; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.gms.FileVersionStorage; +import com.alibaba.polardbx.gms.engine.FileSystemUtils; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.net.buffer.ByteBufferHolder; +import com.alibaba.polardbx.net.compress.IPacketOutputProxy; +import com.alibaba.polardbx.net.compress.PacketOutputProxyFactory; +import com.alibaba.polardbx.net.packet.EOFPacket; +import com.alibaba.polardbx.net.packet.FieldPacket; +import com.alibaba.polardbx.net.packet.MySQLPacket; +import com.alibaba.polardbx.net.packet.ResultSetHeaderPacket; +import com.alibaba.polardbx.net.packet.RowDataPacket; +import com.alibaba.polardbx.optimizer.config.table.ColumnMeta; +import com.alibaba.polardbx.optimizer.config.table.FileMeta; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.server.ServerConnection; +import com.alibaba.polardbx.server.util.PacketUtil; +import io.airlift.slice.Slice; +import org.roaringbitmap.RoaringBitmap; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SelectColumnarFile { + private static final String fileNameRegex = "SELECT\\s+COLUMNAR_FILE\\s*\\([\"'](.*)[\"']\\)"; + private static final Pattern fileNamePattern = Pattern.compile(fileNameRegex, Pattern.CASE_INSENSITIVE); + + public static boolean execute(ServerConnection c, boolean hasMore, ByteString stmt) { + String input = stmt.toString(); + Matcher matcher = fileNamePattern.matcher(input); + String fileName = null; + if (matcher.find()) { + try { + fileName = matcher.group(1); + } catch (IndexOutOfBoundsException e) { + // ignore + } + } + if (fileName == null) { + throw new TddlRuntimeException(ErrorCode.ERR_PARSER, + "Wrong format, example: select columnar_file('1.orc')"); + } + ColumnarFileType type = FileSystemUtils.getFileType(fileName); + if (type == null) { + throw new TddlRuntimeException(ErrorCode.ERR_PARSER, + "Unsupported columnar file suffix: " + fileName); + } + switch (type) { + case CSV: + return readCsvFile(c, hasMore, fileName); + case DEL: + return readDeleteBitmap(c, hasMore, fileName); + case ORC: + return readOrcFile(c, hasMore, fileName); + default: + throw new TddlRuntimeException(ErrorCode.ERR_PARSER, + "Unsupported columnar file type: " + type); + } + } + + private static IPacketOutputProxy buildHeader(IPacketOutputProxy proxy, List columnMetas) { + byte packetId = 0; + + ResultSetHeaderPacket header = PacketUtil.getHeader(columnMetas.size()); + header.packetId = ++packetId; + proxy = header.write(proxy); + + for (ColumnMeta columnMeta : columnMetas) { + FieldPacket field = + PacketUtil.getField(columnMeta.getFullName(), Fields.FIELD_TYPE_VAR_STRING); + field.packetId = ++packetId; + + proxy = field.write(proxy); + } + return proxy; + } + + private static IPacketOutputProxy buildDeleteBitmapHeader(IPacketOutputProxy proxy) { + byte packetId = 0; + FieldPacket field; + + ResultSetHeaderPacket header = PacketUtil.getHeader(3); + header.packetId = ++packetId; + proxy = header.write(proxy); + + field = PacketUtil.getField("TSO", Fields.FIELD_TYPE_VAR_STRING); + field.packetId = ++packetId; + proxy = field.write(proxy); + + field = PacketUtil.getField("File ID", Fields.FIELD_TYPE_VAR_STRING); + field.packetId = ++packetId; + proxy = field.write(proxy); + + field = PacketUtil.getField("Bitmap", Fields.FIELD_TYPE_VAR_STRING); + field.packetId = ++packetId; + proxy = field.write(proxy); + + return proxy; + } + + private static boolean readCsvFile(ServerConnection c, boolean hasMore, String fileName) { + FileMeta fileMeta = ColumnarManager.getInstance().fileMetaOf(fileName); + Engine engine = fileMeta.getEngine(); + List columnMetas = fileMeta.getColumnMetas(); + int filedCount = columnMetas.size(); + + ByteBufferHolder buffer = c.allocate(); + IPacketOutputProxy proxy = PacketOutputProxyFactory.getInstance().createProxy(c, buffer); + proxy.packetBegin(); + + proxy = buildHeader(proxy, columnMetas); + + // What if column size is more than 127? + byte tmpPacketId = (byte) (filedCount + 1); + // write eof + if (!c.isEofDeprecated()) { + EOFPacket eof = new EOFPacket(); + eof.packetId = ++tmpPacketId; + proxy = eof.write(proxy); + } + + long maxReadPosition; + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarAppendedFilesAccessor columnarAppendedFilesAccessor = new ColumnarAppendedFilesAccessor(); + columnarAppendedFilesAccessor.setConnection(connection); + ColumnarAppendedFilesRecord lastRecord = + columnarAppendedFilesAccessor.queryByFileNameAndMaxTso(fileName, + ColumnarManager.getInstance().latestTso()).get(0); + maxReadPosition = lastRecord.appendOffset + lastRecord.appendLength; + } catch (Throwable e) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, e, + String.format("Failed to query latest position of csv file: %s", fileName)); + } + + String charset = c.getResultSetCharset(); + try (SimpleCSVFileReader csvFileReader = new SimpleCSVFileReader()) { + csvFileReader.open(new ExecutionContext(), columnMetas, FileVersionStorage.CSV_CHUNK_LIMIT, engine, + fileName, 0, (int) maxReadPosition); + Chunk result; + while ((result = csvFileReader.nextUntilPosition(maxReadPosition)) != null) { + for (int pos = 0; pos < result.getPositionCount(); pos++) { + RowDataPacket row = new RowDataPacket(filedCount); + for (int field = 0; field < filedCount; field++) { + // This type conversion may be unexpected. + Object resultObject = result.getBlock(field).getObject(pos); + byte[] resultBytes; + if (resultObject == null) { + resultBytes = "NULL".getBytes(charset); + } else if (resultObject instanceof Slice) { + resultBytes = ((Slice) resultObject).toStringUtf8().getBytes(charset); + } else { + resultBytes = resultObject.toString().getBytes(charset); + } + row.add(resultBytes); + } + row.packetId = ++tmpPacketId; + proxy = row.write(proxy); + } + } + + } catch (Throwable t) { + throw new TddlRuntimeException(ErrorCode.ERR_LOAD_CSV_FILE, t, + String.format("Failed to read csv file, file name: %s, max position: %d", fileName, maxReadPosition)); + } + + EOFPacket lastEof = new EOFPacket(); + lastEof.packetId = ++tmpPacketId; + if (hasMore) { + lastEof.status |= MySQLPacket.SERVER_MORE_RESULTS_EXISTS; + } + proxy = lastEof.write(proxy); + + proxy.packetEnd(); + return true; + } + + private static boolean readOrcFile(ServerConnection c, boolean hasMore, String fileName) { + FileMeta fileMeta = ColumnarManager.getInstance().fileMetaOf(fileName); + Engine engine = fileMeta.getEngine(); + List columnMetas = fileMeta.getColumnMetas(); + int fieldCount = columnMetas.size(); + + ByteBufferHolder buffer = c.allocate(); + IPacketOutputProxy proxy = PacketOutputProxyFactory.getInstance().createProxy(c, buffer); + proxy.packetBegin(); + + proxy = buildHeader(proxy, columnMetas); + + byte tmpPacketId = (byte) (fieldCount + 1); + // write eof + if (!c.isEofDeprecated()) { + EOFPacket eof = new EOFPacket(); + eof.packetId = ++tmpPacketId; + proxy = eof.write(proxy); + } + + // TODO(siyun): raw read ORC file + EOFPacket lastEof = new EOFPacket(); + lastEof.packetId = ++tmpPacketId; + if (hasMore) { + lastEof.status |= MySQLPacket.SERVER_MORE_RESULTS_EXISTS; + } + proxy = lastEof.write(proxy); + + proxy.packetEnd(); + return true; + } + + private static boolean readDeleteBitmap(ServerConnection c, boolean hasMore, String fileName) { + ByteBufferHolder buffer = c.allocate(); + IPacketOutputProxy proxy = PacketOutputProxyFactory.getInstance().createProxy(c, buffer); + proxy.packetBegin(); + + proxy = buildDeleteBitmapHeader(proxy); + + byte tmpPacketId = (byte) (3 + 1); + // write eof + if (!c.isEofDeprecated()) { + EOFPacket eof = new EOFPacket(); + eof.packetId = ++tmpPacketId; + proxy = eof.write(proxy); + } + + long maxReadPosition; + Engine engine; + try (Connection connection = MetaDbUtil.getConnection()) { + ColumnarAppendedFilesAccessor columnarAppendedFilesAccessor = new ColumnarAppendedFilesAccessor(); + columnarAppendedFilesAccessor.setConnection(connection); + ColumnarAppendedFilesRecord lastRecord = + columnarAppendedFilesAccessor.queryByFileNameAndMaxTso(fileName, + ColumnarManager.getInstance().latestTso()).get(0); + maxReadPosition = lastRecord.appendOffset + lastRecord.appendLength; + engine = Engine.of(lastRecord.engine); + } catch (SQLException e) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, e, + String.format("Failed to query latest position of delete bitmap: %s", fileName)); + } + + try (SimpleDeletionFileReader fileReader = new SimpleDeletionFileReader()) { + try { + fileReader.open(engine, fileName, 0, (int) maxReadPosition); + } catch (IOException e) { + throw new TddlRuntimeException(ErrorCode.ERR_LOAD_DEL_FILE, e, + String.format("Failed to open delete bitmap file, filename: %s, offset: %d, length: %d", + fileName, 0, maxReadPosition)); + } + DeletionFileReader.DeletionEntry entry; + while (fileReader.position() < maxReadPosition && (entry = fileReader.next()) != null) { + final long delTso = entry.getTso(); + final int fileId = entry.getFileId(); + final RoaringBitmap bitmap = entry.getBitmap(); + if (bitmap != null) { + RowDataPacket row = new RowDataPacket(3); + row.add(String.valueOf(delTso).getBytes()); + row.add(String.valueOf(fileId).getBytes()); + row.add(bitmap.toString().getBytes()); + row.packetId = ++tmpPacketId; + proxy = row.write(proxy); + } + } + } catch (Throwable t) { + throw new TddlRuntimeException(ErrorCode.ERR_COLUMNAR_SNAPSHOT, t, + String.format("Failed to read delete bitmap, file name: %s, max position: %d", fileName, + maxReadPosition)); + } + + EOFPacket lastEof = new EOFPacket(); + lastEof.packetId = ++tmpPacketId; + if (hasMore) { + lastEof.status |= MySQLPacket.SERVER_MORE_RESULTS_EXISTS; + } + proxy = lastEof.write(proxy); + + proxy.packetEnd(); + return true; + } +} diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/SelectPolardbVersion.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/SelectPolardbVersion.java index 32a52854b..26d535f54 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/SelectPolardbVersion.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/SelectPolardbVersion.java @@ -17,6 +17,7 @@ package com.alibaba.polardbx.server.response; import com.alibaba.polardbx.Fields; +import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.common.utils.version.Version; @@ -35,6 +36,7 @@ import com.alibaba.polardbx.server.ServerConnection; import com.alibaba.polardbx.server.util.PacketUtil; import com.alibaba.polardbx.server.util.StringUtil; +import com.amazonaws.services.dynamodbv2.xspec.S; import org.apache.commons.lang3.StringUtils; /** @@ -108,7 +110,21 @@ private static byte addProduct(IPacketOutputProxy proxy, byte packetId, String c final String productReleaseDate = "Distributed Edition"; RowDataPacket row = new RowDataPacket(FIELD_COUNT); - addToRow(row, type, productVersion, productReleaseDate, charset); + + Pair cnReleaseInfo = extractReleaseInfo(Version.getVersion(), "CN"); + + Pair dnReleaseInfo = null; + try { + String dnVersion = ExecUtils.getDnPolardbVersion(); + if (dnVersion != null) { + dnReleaseInfo = extractReleaseInfo(dnVersion, "DN"); + } + } catch (Exception e) { + logger.warn("Failed to get DN version", e); + } + + String maxReleaseDate = getMaxVersion(); + addToRow(row, type, productVersion, productReleaseDate, charset, cnReleaseInfo, dnReleaseInfo, maxReleaseDate); row.packetId = packetId; row.write(proxy); @@ -199,11 +215,35 @@ private static byte addCnVersion(IPacketOutputProxy proxy, byte packetId, String return ++packetId; } - /** - * @param version format: {Version}-{ReleaseDate} - */ - static void addVersionWithReleaseDate(RowDataPacket row, String type, - String version, String charset) { + public static String getMaxVersion() { + String releaseDate = extractReleaseInfo(Version.getVersion(), "CN").getValue(); + try { + releaseDate = replaceWhenGreaterThan(releaseDate, ExecUtils.getDnPolardbVersion(), "DN"); + releaseDate = replaceWhenGreaterThan(releaseDate, CdcVersionUtil.getVersion(), "CDC"); + releaseDate = replaceWhenGreaterThan(releaseDate, MetaDbUtil.getGmsPolardbVersion(), "GMS"); + releaseDate = replaceWhenGreaterThan(releaseDate, ColumnarVersionUtil.getVersion(), "Columnar"); + } catch (Exception e) { + logger.warn("Failed to get version", e); + } + return releaseDate; + } + + public static String replaceWhenGreaterThan(String releaseDate, String replace, String type) { + if (replace == null) { + return releaseDate; + } + Pair replaceInfo = extractReleaseInfo(replace, type); + if (replaceInfo.getValue() == null) { + return releaseDate; + } + String replaceDate = replaceInfo.getValue(); + if (releaseDate == null || replaceDate.compareTo(releaseDate) > 0) { + return replaceDate; + } + return releaseDate; + } + + static Pair extractReleaseInfo(String version, String type) { String majorVersion = version; String releaseDate = null; boolean isLegalVersionFormat = false; @@ -230,17 +270,65 @@ static void addVersionWithReleaseDate(RowDataPacket row, String type, if (!isLegalVersionFormat) { logger.warn("Failed to parse " + type + " version: " + version); } - addToRowWithProductVersion(row, type, majorVersion, releaseDate, charset); + return new Pair<>(majorVersion, releaseDate); } - private static void addToRow(RowDataPacket row, String type, - String version, String releaseDate, - String charset) { + /** + * @param version format: {Version}-{ReleaseDate} + */ + static void addVersionWithReleaseDate(RowDataPacket row, String type, + String version, String charset) { + Pair ret = extractReleaseInfo(version, type); + addToRowWithProductVersion(row, type, ret.getKey(), ret.getValue(), charset); + } + + static void addToRow(RowDataPacket row, String type, + String version, String releaseDate, + String charset, + Pair cnReleaseInfo, + Pair dnReleaseInfo, + String maxReleaseDate) { row.add(StringUtil.encode(type, charset)); - row.add(StringUtil.encode(version, charset)); - row.add(StringUtil.encode(releaseDate, charset)); + + StringBuilder stringBuffer = new StringBuilder(); + stringBuffer.append(version); + stringBuffer.append("_").append(Version.PRODUCT_VERSION); + if (cnReleaseInfo != null) { + String cnVersion = cnReleaseInfo.getKey(); + String cnDate = cnReleaseInfo.getValue(); + if (cnVersion != null) { + stringBuffer.append("_"); + stringBuffer.append(cnVersion); + } + if (cnDate != null) { + stringBuffer.append("-"); + stringBuffer.append(cnDate); + } + } + + if (dnReleaseInfo != null) { + String dnVersion = dnReleaseInfo.getKey(); + String dnDate = dnReleaseInfo.getValue(); + if (dnVersion != null) { + stringBuffer.append("_"); + stringBuffer.append(dnVersion); + } + if (dnDate != null) { + stringBuffer.append("-"); + stringBuffer.append(dnDate); + } + } + + if (releaseDate != null) { + stringBuffer.append(" (").append(releaseDate).append(")"); + } + + row.add(StringUtil.encode(stringBuffer.toString(), charset)); + row.add(StringUtil.encode(maxReleaseDate, charset)); } + + private static void addToRowWithProductVersion(RowDataPacket row, String type, String version, String releaseDate, String charset) { diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowColumnarOffset.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowColumnarOffset.java index 41f4a1b4f..c5dea68b7 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowColumnarOffset.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowColumnarOffset.java @@ -24,6 +24,8 @@ import com.alibaba.polardbx.executor.gms.util.ColumnarTransactionUtils; import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPurgeHistoryAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPurgeHistoryRecord; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.net.buffer.ByteBufferHolder; import com.alibaba.polardbx.net.compress.IPacketOutputProxy; @@ -130,6 +132,7 @@ private static List buildBinlogOffset() { //先拿columnar位点,防止columnar位点 > polardbx List checkpointsList = new ArrayList<>(); List typeList = new ArrayList<>(); + Long columnarPurgeTso = null; try (Connection metaDbConn = MetaDbUtil.getConnection()) { ColumnarCheckpointsAccessor checkpointsAccessor = new ColumnarCheckpointsAccessor(); @@ -143,6 +146,14 @@ private static List buildBinlogOffset() { checkpointsList.add(columnarCheckpointsRecords.get(0)); typeList.add("COLUMNAR_LATENCY"); } + ColumnarPurgeHistoryAccessor columnarPurgeHistoryAccessor = new ColumnarPurgeHistoryAccessor(); + columnarPurgeHistoryAccessor.setConnection(metaDbConn); + + List records = columnarPurgeHistoryAccessor.queryLastPurgeTso(); + if (!records.isEmpty()) { + columnarPurgeTso = records.get(0).tso; + } + } catch (SQLException e) { throw new TddlRuntimeException(ErrorCode.ERR_GMS_GENERIC, "fail to fetch columnar checkpoint.", e); @@ -250,6 +261,24 @@ private static List buildBinlogOffset() { } + if (columnarPurgeTso != null) { + long columnarPurgeMs = columnarPurgeTso >>> 22; + long latency = cdcMs - columnarPurgeMs; + + Date cDate = new Date(columnarPurgeMs); + SimpleDateFormat cSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String cTime = cSdf.format(cDate); + byte[][] columnarResults = new byte[FIELD_COUNT][]; + int cPos = 0; + columnarResults[cPos++] = String.valueOf("COLUMNAR_PURGE").getBytes(); + columnarResults[cPos++] = String.valueOf("").getBytes(); + columnarResults[cPos++] = String.valueOf("").getBytes(); + columnarResults[cPos++] = String.valueOf(columnarPurgeTso).getBytes(); + columnarResults[cPos++] = String.valueOf(cTime).getBytes(); + columnarResults[cPos++] = String.valueOf(latency).getBytes(); + resultsList.add(columnarResults); + } + Channel channel = cdcServiceBlockingStub.getChannel(); if (channel instanceof ManagedChannel) { ((ManagedChannel) channel).shutdown(); diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowMpp.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowMpp.java index 513d4fb6c..5f00ecd9c 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowMpp.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowMpp.java @@ -21,6 +21,7 @@ import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; import com.alibaba.polardbx.gms.node.InternalNode; import com.alibaba.polardbx.gms.node.InternalNodeManager; +import com.alibaba.polardbx.gms.node.MppScope; import com.alibaba.polardbx.net.buffer.ByteBufferHolder; import com.alibaba.polardbx.net.compress.IPacketOutputProxy; import com.alibaba.polardbx.net.compress.PacketOutputProxyFactory; @@ -87,9 +88,21 @@ public static boolean executeInternal(IPacketOutputProxy proxy, String charset, proxy = eof.write(proxy); } - // write rows - for (InternalNode node : getNodes()) { - RowDataPacket row = getRow(charset, node); + // write master rows + for (InternalNode node : getNodes(MppScope.CURRENT)) { + RowDataPacket row = getRow(charset, node, MppScope.CURRENT); + row.packetId = ++tmpPacketId; + proxy = row.write(proxy); + } + + for (InternalNode node : getNodes(MppScope.SLAVE)) { + RowDataPacket row = getRow(charset, node, MppScope.SLAVE); + row.packetId = ++tmpPacketId; + proxy = row.write(proxy); + } + + for (InternalNode node : getNodes(MppScope.COLUMNAR)) { + RowDataPacket row = getRow(charset, node, MppScope.COLUMNAR); row.packetId = ++tmpPacketId; proxy = row.write(proxy); } @@ -104,20 +117,35 @@ public static boolean executeInternal(IPacketOutputProxy proxy, String charset, return true; } - private static RowDataPacket getRow(String charset, InternalNode node) { + protected static RowDataPacket getRow(String charset, InternalNode node, MppScope scope) { + String role = null; + + if (scope == MppScope.CURRENT) { + if (ConfigDataMode.isMasterMode()) { + role = "W"; + } else if (ConfigDataMode.isRowSlaveMode()) { + role = "R"; + } else { + role = "CR"; + } + } else if (scope == MppScope.SLAVE) { + role = "R"; + } else { + role = "CR"; + } + RowDataPacket row = new RowDataPacket(FIELD_COUNT); row.add(StringUtil.encode(node.getInstId(), charset)); row.add(StringUtil.encode(node.getHostPort(), charset)); - row.add(StringUtil.encode(ConfigDataMode.isMasterMode() ? "W" : "R", charset)); + row.add(StringUtil.encode(role, charset)); row.add(StringUtil.encode(node.isLeader() ? "Y" : "N", charset)); return row; } - private static Set getNodes() { + public static Set getNodes(MppScope scope) { InternalNodeManager manager = ServiceProvider.getInstance().getServer().getNodeManager(); Set allActiveNodes = new HashSet<>(); - allActiveNodes.addAll(manager.getAllNodes().getActiveNodes()); - allActiveNodes.addAll(manager.getAllNodes().getOtherActiveNodes()); + allActiveNodes.addAll(manager.getAllNodes().getAllWorkers(scope)); return allActiveNodes; } } diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowProcesslistSyncAction.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowProcesslistSyncAction.java index 446fa61d8..c6705c990 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowProcesslistSyncAction.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowProcesslistSyncAction.java @@ -126,7 +126,7 @@ public ResultCursor sync() { } for (Map.Entry conn : InnerConnectionManager.getActiveConnections().entrySet()) { - + addRowByInnerConnection(result, conn.getValue()); } return result; @@ -279,6 +279,7 @@ private void addRowByInnerConnection(ArrayResultCursor result, InnerConnection i String sqlType = null; boolean isStmtExecuting = innerConnection.isStatementExecuting(); if (isStmtExecuting) { + command = "Query"; if (this.isFull()) { info = innerConnection.getSqlSample(); @@ -292,8 +293,6 @@ private void addRowByInnerConnection(ArrayResultCursor result, InnerConnection i } ExecutionPlan plan = executionContext.getFinalPlan(); if (plan != null) { - //use the first plan. consider their ther PlanWithContext is similar when InsertSplitter is applied. - PlanCache.CacheKey cacheKey = plan.getCacheKey(); if (cacheKey != null) { sqlTid = cacheKey.getTemplateId(); diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowTransSyncAction.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowTransSyncAction.java index b8f552ba9..f678010b3 100644 --- a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowTransSyncAction.java +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/ShowTransSyncAction.java @@ -90,7 +90,10 @@ public ResultCursor sync() { if (transaction.isBegun() && !transaction.isClosed()) { final BaseTransaction tx = (BaseTransaction) transaction; final String transId = Long.toHexString(tx.getId()); - final String type = tx.getTransactionClass().toString(); + String type = tx.getClass().getSimpleName(); + if (null != type && type.endsWith("Transaction")) { + type = type.substring(0, type.length() - "Transaction".length()); + } final long duration = currentTimeMs - tx.getStartTimeInMs(); final String state = transaction.getState().toString(); final long processId; diff --git a/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/TtlScheduleViewSyncAction.java b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/TtlScheduleViewSyncAction.java new file mode 100644 index 000000000..77d9b6ebb --- /dev/null +++ b/polardbx-server/src/main/java/com/alibaba/polardbx/server/response/TtlScheduleViewSyncAction.java @@ -0,0 +1,109 @@ +package com.alibaba.polardbx.server.response; + +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.executor.ddl.job.task.ttl.scheduler.TtlScheduledJobStatManager; +import com.alibaba.polardbx.executor.handler.subhandler.InformationSchemaTtlScheduleHandler; +import com.alibaba.polardbx.executor.mpp.deploy.ServiceProvider; +import com.alibaba.polardbx.executor.scheduler.ScheduledJobsManager; +import com.alibaba.polardbx.executor.sync.ISyncAction; +import com.alibaba.polardbx.gms.node.InternalNodeManager; +import com.alibaba.polardbx.gms.node.Node; +import com.alibaba.polardbx.gms.scheduler.ScheduleDateTimeConverter; +import com.alibaba.polardbx.gms.scheduler.ScheduledJobExecutorType; +import com.alibaba.polardbx.gms.scheduler.ScheduledJobsRecord; +import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; + +import java.util.ArrayList; +import java.util.List; + +public class TtlScheduleViewSyncAction implements ISyncAction { + + protected String schema; + + public TtlScheduleViewSyncAction() { + } + + public TtlScheduleViewSyncAction(String schema) { + this.schema = schema; + } + + @Override + public ResultCursor sync() { + + ArrayResultCursor result = new ArrayResultCursor("TTL_SCHEDULE"); + result.addColumn("TABLE_SCHEMA", DataTypes.VarcharType); + result.addColumn("TABLE_NAME", DataTypes.VarcharType); + result.addColumn("METRIC_KEY", DataTypes.VarcharType); + result.addColumn("METRIC_VAL", DataTypes.VarcharType); + + result.initMeta(); + + InternalNodeManager nodeManager = ServiceProvider.getInstance().getServer().getNodeManager(); + Node node = nodeManager.getCurrentNode(); + if (!node.isLeader()) { + return result; + } + + List recordList = ScheduledJobsManager.queryScheduledJobsRecord(); + for (ScheduledJobsRecord rs : recordList) { + + if (!ScheduledJobExecutorType.TTL_JOB.name().equalsIgnoreCase(rs.getExecutorType())) { + continue; + } + + List> metricInfos = new ArrayList<>(); + metricInfos.add(new Pair<>("SCHEDULE_STATUS", String.valueOf(rs.getStatus()))); + metricInfos.add(new Pair<>("SCHEDULE_EXPR", String.valueOf(rs.getScheduleExpr()))); + metricInfos.add(new Pair<>("SCHEDULE_COMMENT", String.valueOf(rs.getScheduleComment()))); + metricInfos.add(new Pair<>("SCHEDULE_TIMEZONE", String.valueOf(rs.getTimeZone()))); + metricInfos.add(new Pair<>("SCHEDULE_LAST_FIRE_TIME", + ScheduleDateTimeConverter.secondToZonedDateTime(rs.getLastFireTime(), rs.getTimeZone()) + .toLocalDateTime().format(InformationSchemaTtlScheduleHandler.ISO_DATETIME_FORMATTER))); + metricInfos.add(new Pair<>("SCHEDULE_NEXT_FIRE_TIME", + ScheduleDateTimeConverter.secondToZonedDateTime(rs.getNextFireTime(), rs.getTimeZone()) + .toLocalDateTime().format(InformationSchemaTtlScheduleHandler.ISO_DATETIME_FORMATTER))); + + String dbName = rs.getTableSchema(); + String tbName = rs.getTableName(); + TtlScheduledJobStatManager.TtlJobStatInfo jobStatInfo = + TtlScheduledJobStatManager.getInstance().getTtlJobStatInfo(dbName, tbName); + if (jobStatInfo != null) { + metricInfos.addAll(jobStatInfo.toMetricInfo()); + } + + for (int i = 0; i < metricInfos.size(); i++) { + result.addRow(new Object[] { + dbName, + tbName, + metricInfos.get(i).getKey(), + metricInfos.get(i).getValue() + }); + } + } + + List> globalMetricInfos = + TtlScheduledJobStatManager.getInstance().getGlobalTtlJobStatInfo() + .toMetricInfo(); + String globalDbName = "global"; + String globalTbName = "global"; + for (int i = 0; i < globalMetricInfos.size(); i++) { + result.addRow(new Object[] { + globalDbName, + globalTbName, + globalMetricInfos.get(i).getKey(), + globalMetricInfos.get(i).getValue() + }); + } + return result; + } + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/CobarServerTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/CobarServerTest.java new file mode 100644 index 000000000..7486fb7d3 --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/CobarServerTest.java @@ -0,0 +1,61 @@ +package com.alibaba.polardbx; + +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.listener.impl.MetaDbConfigManager; +import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class CobarServerTest { + @Test + public void tryInitServerVariablesTest() throws SQLException { + ConfigDataMode.Mode mode = ConfigDataMode.getMode(); + ConfigDataMode.setMode(ConfigDataMode.Mode.MOCK); + Connection mockConnection = mock(Connection.class, RETURNS_DEEP_STUBS); + MetaDbDataSource mockMetaDbDataSource = mock(MetaDbDataSource.class); + when(mockMetaDbDataSource.getConnection()).thenReturn(mockConnection); + PreparedStatement prepareStatement = mock(PreparedStatement.class); + when(mockConnection.prepareStatement(Mockito.anyString())).thenReturn(prepareStatement); + doNothing().when(prepareStatement).setString(anyInt(), anyString()); + doNothing().when(prepareStatement).addBatch(); + when(prepareStatement.executeBatch()).thenReturn(new int[] {1, 1}); + MetaDbConfigManager configManager = mock(MetaDbConfigManager.class); + when(configManager.notify(anyString(), any())).thenReturn(1L); + + try (MockedStatic metaDbDataSourceMockedStatic = + Mockito.mockStatic(MetaDbDataSource.class); + MockedStatic metaDbConfigManagerMockedStatic = + Mockito.mockStatic(MetaDbConfigManager.class);) { + metaDbDataSourceMockedStatic.when(MetaDbDataSource::getInstance).thenReturn(mockMetaDbDataSource); + metaDbConfigManagerMockedStatic.when(MetaDbConfigManager::getInstance).thenReturn(configManager); + + Statement statement = mock(Statement.class); + when(mockConnection.createStatement()).thenReturn(statement); + ResultSet resultSet = mock(ResultSet.class); + when(statement.executeQuery(anyString())).thenReturn(resultSet); + when(resultSet.next()).thenReturn(true); + when(resultSet.getInt(1)).thenReturn(1); + + CobarServer.tryInitServerVariables(); + + when(prepareStatement.executeBatch()).thenThrow(new SQLException("test")); + CobarServer.tryInitServerVariables(); + } + ConfigDataMode.setMode(mode); + } +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/cdc/CdcDdlMarkSyncActionTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/cdc/CdcDdlMarkSyncActionTest.java new file mode 100644 index 000000000..77ab5c69a --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/cdc/CdcDdlMarkSyncActionTest.java @@ -0,0 +1,51 @@ +/* + * 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 com.alibaba.polardbx.cdc; + +import com.alibaba.polardbx.common.cdc.CdcDdlMarkVisibility; +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; +import java.util.Map; + +import static com.alibaba.polardbx.executor.utils.ExecUtils.resultSetToList; + +public class CdcDdlMarkSyncActionTest { + + @Test + public void testSyncOnLeaderNode() { + + CdcDdlMarkSyncAction action = new CdcDdlMarkSyncAction( + 10L, "CREATE_TABLE", "testSchema", "testTable", "CREATE TABLE test", "metaInfo", + CdcDdlMarkVisibility.Protected, "", true); + + ResultCursor resultCursor = action.buildReturnCursor(123456L); + + List> result = resultSetToList(resultCursor); + + Assert.assertEquals(1, resultCursor.getReturnColumns().size()); + Assert.assertEquals(1, result.size()); + + Assert.assertEquals(1, result.get(0).size()); + Assert.assertEquals(123456L, result.get(0).get("COMMIT_TSO")); + } + +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/cdc/MetaBuilderTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/cdc/MetaBuilderTest.java new file mode 100644 index 000000000..1b29745ce --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/cdc/MetaBuilderTest.java @@ -0,0 +1,53 @@ +package com.alibaba.polardbx.cdc; + +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.common.TopologyHandler; +import com.alibaba.polardbx.executor.spi.IGroupExecutor; +import com.alibaba.polardbx.group.jdbc.TGroupDataSource; +import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; +import lombok.SneakyThrows; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.sql.Connection; +import java.sql.SQLException; + +import static org.mockito.Mockito.when; + +public class MetaBuilderTest { + + @SneakyThrows + @Test + public void testGetPhyConnection() { + try (MockedStatic contextMockedStatic = Mockito.mockStatic(ExecutorContext.class)) { + ExecutorContext context = Mockito.mock(ExecutorContext.class); + TopologyHandler topologyHandler = Mockito.mock(TopologyHandler.class); + IGroupExecutor groupExecutor = Mockito.mock(IGroupExecutor.class); + TGroupDataSource dataSource = Mockito.mock(TGroupDataSource.class); + TGroupDirectConnection connection = new TGroupDirectConnection(dataSource, Mockito.mock(Connection.class)); + + contextMockedStatic.when(() -> ExecutorContext.getContext("test")).thenReturn(context); + when(context.getTopologyHandler()).thenReturn(topologyHandler); + when(topologyHandler.get(Mockito.anyString())).thenReturn(groupExecutor); + when(groupExecutor.getDataSource()).thenReturn(dataSource); + when(dataSource.getConnection()).thenReturn(connection); + when(dataSource.getDbGroupKey()).thenReturn("dgk"); + + MetaBuilder.getPhyConnection("test", "group"); + + Assert.assertEquals("", connection.getServerVariables().get("sql_mode")); + } + } + + @Test + public void testPreparePhyConnection() throws SQLException { + TGroupDataSource groupDataSource = Mockito.mock(TGroupDataSource.class); + when(groupDataSource.getDbGroupKey()).thenReturn("db_group_1"); + Connection connection = Mockito.mock(Connection.class); + TGroupDirectConnection groupDirectConnection = new TGroupDirectConnection(groupDataSource, connection); + MetaBuilder.preparePhyConnection(groupDirectConnection); + Assert.assertEquals("", groupDirectConnection.getServerVariables().get("sql_mode")); + } +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/cdc/SQLHelperTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/cdc/SQLHelperTest.java index 1a2bff3dc..fd4f95ab7 100644 --- a/polardbx-server/src/test/java/com/alibaba/polardbx/cdc/SQLHelperTest.java +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/cdc/SQLHelperTest.java @@ -155,10 +155,10 @@ public void testParseCreateTableGroupSql() { @Test public void testRewriteWithTableGroupImplicit() { - String sql = "alter table `t7` with tablegroup=single_tg468 implicit"; + String sql = "alter table `t``7` with tablegroup=single_tg468 implicit"; SQLStatement statement = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql, SQL_PARSE_FEATURES).parseStatementList().get(0); - Assert.assertEquals("ALTER TABLE `t7`\n" + Assert.assertEquals("ALTER TABLE `t``7`\n" + "\tSET tablegroup = single_tg468 IMPLICIT FORCE", statement.toString()); } @@ -199,7 +199,12 @@ public void testLocalPartitionBy() { + "\t`c_timestamp_6` timestamp(6) DEFAULT '2000-01-01 00:00:00',\n" + "\t`gmt_modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n" + "\tPRIMARY KEY (`id`, `gmt_modified`)\n" - + ") SINGLE"; + + ") SINGLE\n" + + "LOCAL PARTITION BY RANGE (gmt_modified)\n" + + " INTERVAL 1 MONTH\n" + + " EXPIRE AFTER 6\n" + + " PRE ALLOCATE 6\n" + + " PIVOTDATE NOW()"; Assert.assertEquals(expectSql, statement.toString()); } diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/matrix/config/MatrixConfigHolderTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/matrix/config/MatrixConfigHolderTest.java new file mode 100644 index 000000000..4fafe4014 --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/matrix/config/MatrixConfigHolderTest.java @@ -0,0 +1,83 @@ +/* + * 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 com.alibaba.polardbx.matrix.config; + +import com.alibaba.polardbx.executor.utils.SchemaMetaUtil; +import com.alibaba.polardbx.gms.listener.impl.MetaDbConfigManager; +import com.alibaba.polardbx.gms.listener.impl.MetaDbDataIdBuilder; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.sql.Connection; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; + +@RunWith(MockitoJUnitRunner.class) +public class MatrixConfigHolderTest { + + @Mock + private Connection metaDbConn; + + @InjectMocks + private SchemaMetaUtil.PolarDbXSchemaMetaCleaner polarDbXSchemaMetaCleaner = + new SchemaMetaUtil.PolarDbXSchemaMetaCleaner(); + + @Before + public void setUp() { + // Setup procedures if necessary + } + + @After + public void tearDown() { + // Cleanup resources or reset mocks +// mockReset(metaDbConn); + } + + @Test + public void testClearSchemaMetaInvokesCleanupSchemaMeta() throws Exception { + // Given + final String schemaName = "test_schema"; + final long versionId = 123L; + + MetaDbConfigManager metaDbConfigManager = Mockito.mock(MetaDbConfigManager.class); + doNothing().when(metaDbConfigManager).unregister(anyString(), any()); + try ( + MockedStatic mockMetaDbDataIdBuilder = Mockito.mockStatic(MetaDbDataIdBuilder.class)) { + try (MockedStatic mockMetaDbConfigManager = Mockito.mockStatic( + MetaDbConfigManager.class)) { + mockMetaDbDataIdBuilder.when(() -> MetaDbDataIdBuilder.getTableListDataId(anyString())) + .thenReturn("table"); + mockMetaDbConfigManager.when(() -> MetaDbConfigManager.getInstance()) + .thenAnswer(invocation -> metaDbConfigManager); + + polarDbXSchemaMetaCleaner.clearSchemaMeta(schemaName, metaDbConn, versionId); + } + } + } + +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/matrix/jdbc/TConnectionTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/matrix/jdbc/TConnectionTest.java index c620b66b5..deeded714 100644 --- a/polardbx-server/src/test/java/com/alibaba/polardbx/matrix/jdbc/TConnectionTest.java +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/matrix/jdbc/TConnectionTest.java @@ -18,10 +18,16 @@ package com.alibaba.polardbx.matrix.jdbc; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; import com.alibaba.polardbx.common.properties.ParamManager; import com.google.common.truth.Truth; import org.junit.Test; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + public class TConnectionTest { @Test public void newExecutionContextTest() { @@ -48,4 +54,69 @@ public void newExecutionContextTest() { .getBoolean(ConnectionParams.OUTPUT_MYSQL_ERROR_CODE)) .isTrue(); } + + /** + * Tests whether the method correctly sets the MASTER property when given a valid 'groupindex:0' hint. + */ + @Test + public void testTransformGroupIndexHintToMasterSlaveForMaster() { + Map extraCmd = new HashMap<>(); + String groupHint = "groupindex:0"; + + TConnection.transformGroupIndexHintToMasterSlave(groupHint, extraCmd); + + assertEquals(Boolean.TRUE, extraCmd.get(ConnectionProperties.MASTER)); + } + + /** + * Tests whether the method correctly sets the SLAVE property when given a valid 'groupindex:1' hint. + */ + @Test + public void testTransformGroupIndexHintToMasterSlaveForSlave() { + Map extraCmd = new HashMap<>(); + String groupHint = "groupindex:1"; + + TConnection.transformGroupIndexHintToMasterSlave(groupHint, extraCmd); + + assertEquals(Boolean.TRUE, extraCmd.get(ConnectionProperties.SLAVE)); + } + + /** + * Tests whether the method leaves the extraCmd unchanged when given an empty string as the groupHint. + */ + @Test + public void testTransformGroupIndexHintToMasterSlaveWithEmptyString() { + Map extraCmd = new HashMap<>(); + String groupHint = ""; + + TConnection.transformGroupIndexHintToMasterSlave(groupHint, extraCmd); + + assertEquals(0, extraCmd.size()); + } + + /** + * Tests whether the method leaves the extraCmd unchanged when given null as the groupHint. + */ + @Test + public void testTransformGroupIndexHintToMasterSlaveWithNull() { + Map extraCmd = new HashMap<>(); + String groupHint = null; + + TConnection.transformGroupIndexHintToMasterSlave(groupHint, extraCmd); + + assertEquals(0, extraCmd.size()); + } + + /** + * Tests whether the method leaves the extraCmd unchanged when given an invalid input as the groupHint. + */ + @Test + public void testTransformGroupIndexHintToMasterSlaveWithInvalidInput() { + Map extraCmd = new HashMap<>(); + String groupHint = "invalid_input"; + + TConnection.transformGroupIndexHintToMasterSlave(groupHint, extraCmd); + + assertEquals(0, extraCmd.size()); + } } diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/parser/SyncActionTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/parser/SyncActionTest.java index b6bf90dca..2526ff9b0 100644 --- a/polardbx-server/src/test/java/com/alibaba/polardbx/parser/SyncActionTest.java +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/parser/SyncActionTest.java @@ -19,23 +19,31 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.parser.ParserConfig; import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.polardbx.executor.sync.BaselineDeleteHotEvolvedSyncAction; +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.sync.BaselineDeleteSyncAction; import com.alibaba.polardbx.executor.sync.BaselineInvalidatePlanSyncAction; import com.alibaba.polardbx.executor.sync.BaselineInvalidateSchemaSyncAction; import com.alibaba.polardbx.executor.sync.BaselineUpdateSyncAction; import com.alibaba.polardbx.executor.sync.DeleteBaselineSyncAction; import com.alibaba.polardbx.executor.sync.FetchSPMSyncAction; +import com.alibaba.polardbx.executor.sync.MetricSyncAction; import com.alibaba.polardbx.executor.sync.RemoveColumnStatisticSyncAction; import com.alibaba.polardbx.executor.sync.RemoveTableStatisticSyncAction; import com.alibaba.polardbx.executor.sync.RenameStatisticSyncAction; import com.alibaba.polardbx.executor.sync.RenameTableSyncAction; import com.alibaba.polardbx.executor.sync.UpdateStatisticSyncAction; +import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; import com.alibaba.polardbx.optimizer.config.table.statistic.Histogram; +import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticFeedbackSyncAction; import com.alibaba.polardbx.optimizer.config.table.statistic.StatisticManager; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.planmanager.BaselineInfo; import com.alibaba.polardbx.optimizer.planmanager.PlanInfo; import com.alibaba.polardbx.server.response.ShowNodeSyncAction; import com.alibaba.polardbx.server.response.ShowSQLSlowSyncAction; +import com.alibaba.polardbx.stats.metric.FeatureStats; +import com.alibaba.polardbx.stats.metric.FeatureStatsItem; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.junit.Assert; @@ -46,6 +54,8 @@ import java.util.Map; import java.util.Random; +import static com.alibaba.polardbx.common.utils.Assert.assertTrue; + public class SyncActionTest { @Test @@ -82,6 +92,32 @@ public void testBaselineInvalidatePlanSyncAction() { Assert.assertEquals(action.isIsForce(), obj.isIsForce()); } + @Test + public void testDeleteBaselineSyncAction1() { + ParserConfig parserConfig = ParserConfig.getGlobalInstance(); + parserConfig.setAutoTypeSupport(true); + ParserConfig.getGlobalInstance() + .addAccept("com.alibaba.polardbx.executor.sync.BaselineDeleteSyncAction"); + int baselineId = 123; + int planId = 1234; + BaselineDeleteSyncAction action = new BaselineDeleteSyncAction("test1", baselineId); + + String data = JSON.toJSONString(action, SerializerFeature.WriteClassName); + BaselineDeleteSyncAction obj = (BaselineDeleteSyncAction) JSON.parse(data); + Assert.assertEquals(action.getSchemaName(), obj.getSchemaName()); + Assert.assertEquals(action.getBaselineId(), obj.getBaselineId()); + Assert.assertTrue(0 == obj.getPlanInfoId()); + + action.setBaselineId(baselineId); + action.setPlanInfoId(planId); + action.setSchemaName("test1"); + data = JSON.toJSONString(action, SerializerFeature.WriteClassName); + obj = (BaselineDeleteSyncAction) JSON.parse(data); + Assert.assertEquals(action.getSchemaName(), obj.getSchemaName()); + Assert.assertEquals(action.getBaselineId(), obj.getBaselineId()); + Assert.assertEquals(action.getPlanInfoId(), obj.getPlanInfoId()); + } + @Test public void testBaselineInvalidateSchemaSyncAction() { ParserConfig parserConfig = ParserConfig.getGlobalInstance(); @@ -109,6 +145,7 @@ public void testDeleteBaselineSyncAction() { DeleteBaselineSyncAction obj = (DeleteBaselineSyncAction) JSON.parse(data); Assert.assertEquals(action.getSchemaName(), obj.getSchemaName()); Assert.assertEquals(action.getParameterSql(), obj.getParameterSql()); + Assert.assertTrue(0 == obj.getPlanInfoId()); action = new DeleteBaselineSyncAction("test1", "test2", 123); data = JSON.toJSONString(action, SerializerFeature.WriteClassName); @@ -118,6 +155,20 @@ public void testDeleteBaselineSyncAction() { Assert.assertEquals(action.getPlanInfoId(), obj.getPlanInfoId()); } + @Test + public void testBaselineDeleteHotEvolvedSyncAction() { + ParserConfig parserConfig = ParserConfig.getGlobalInstance(); + parserConfig.setAutoTypeSupport(true); + ParserConfig.getGlobalInstance() + .addAccept("com.alibaba.polardbx.executor.sync.BaselineDeleteHotEvolvedSyncAction"); + + BaselineDeleteHotEvolvedSyncAction action = new BaselineDeleteHotEvolvedSyncAction("Test"); + + String data = JSON.toJSONString(action, SerializerFeature.WriteClassName); + BaselineDeleteHotEvolvedSyncAction obj = (BaselineDeleteHotEvolvedSyncAction) JSON.parse(data); + Assert.assertEquals(action.getSchema(), obj.getSchema()); + } + @Test public void testUpdateStatisticSyncAction() { ParserConfig parserConfig = ParserConfig.getGlobalInstance(); @@ -234,6 +285,55 @@ public void testBaselineUpdateSyncAction() { Assert.assertEquals(action.getBaselineMap(), obj.getBaselineMap()); } + @Test + public void testStatisticFeedbackSyncAction() { + ParserConfig parserConfig = ParserConfig.getGlobalInstance(); + parserConfig.setAutoTypeSupport(true); + ParserConfig.getGlobalInstance() + .addAccept("com.alibaba.polardbx.optimizer.config.table.statistic.StatisticFeedbackSyncAction"); + + StatisticFeedbackSyncAction action = new StatisticFeedbackSyncAction("test1", "test2"); + + String data = JSON.toJSONString(action, SerializerFeature.WriteClassName); + StatisticFeedbackSyncAction obj = (StatisticFeedbackSyncAction) JSON.parse(data); + Assert.assertEquals(action.getSchema(), obj.getSchema()); + Assert.assertEquals(action.getTable(), obj.getTable()); + } + + @Test + public void testMetricSyncAction() { + MetaDbInstConfigManager.setConfigFromMetaDb(false); + ParserConfig parserConfig = ParserConfig.getGlobalInstance(); + parserConfig.setAutoTypeSupport(true); + ParserConfig.getGlobalInstance() + .addAccept("com.alibaba.polardbx.executor.sync.MetricSyncAction"); + MetricSyncAction metricSyncAction = new MetricSyncAction(); + FeatureStats.getInstance().plus(FeatureStatsItem.FIX_PLAN_NUM, 99); + FeatureStats.getInstance().plus(FeatureStatsItem.NEW_BASELINE_NUM, 100); + FeatureStats.getInstance().plus(FeatureStatsItem.HOT_EVOLVE_PLAN_NUM, 105); + FeatureStats.getInstance().plus(FeatureStatsItem.HLL_TASK_SUCC, 101); + FeatureStats.getInstance().plus(FeatureStatsItem.HLL_TASK_FAIL, 102); + FeatureStats.getInstance().plus(FeatureStatsItem.SAMPLE_TASK_SUCC, 103); + FeatureStats.getInstance().plus(FeatureStatsItem.SAMPLE_TASK_FAIL, 104); + + FeatureStats.getInstance().increment(FeatureStatsItem.FIX_PLAN_NUM); + FeatureStats.getInstance().increment(FeatureStatsItem.NEW_BASELINE_NUM); + FeatureStats.getInstance().increment(FeatureStatsItem.HOT_EVOLVE_PLAN_NUM); + FeatureStats.getInstance().increment(FeatureStatsItem.HLL_TASK_SUCC); + FeatureStats.getInstance().increment(FeatureStatsItem.HLL_TASK_FAIL); + FeatureStats.getInstance().increment(FeatureStatsItem.SAMPLE_TASK_SUCC); + FeatureStats.getInstance().increment(FeatureStatsItem.SAMPLE_TASK_FAIL); + ResultCursor rc = metricSyncAction.sync(); + String line = rc.doNext().getString(0); + System.out.println(line); + assertTrue("{\"longStats\":[101,100,106,104,105,102,103],\"sign\":797014233}".equalsIgnoreCase(line)); + + FeatureStats fs = FeatureStats.deserialize(line); + System.out.println(fs.log()); + Assert.assertTrue(fs.log().equalsIgnoreCase( + "NEW_BASELINE_NUM:101,FIX_PLAN_NUM:100,HOT_EVOLVE_PLAN_NUM:106,SAMPLE_TASK_SUCC:104,SAMPLE_TASK_FAIL:105,HLL_TASK_SUCC:102,HLL_TASK_FAIL:103")); + } + @Test public void testBaselineQuerySyncAction() { ParserConfig parserConfig = ParserConfig.getGlobalInstance(); diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/ServerConnectionTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/ServerConnectionTest.java index 4c20fd788..ffa6ec335 100644 --- a/polardbx-server/src/test/java/com/alibaba/polardbx/server/ServerConnectionTest.java +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/ServerConnectionTest.java @@ -17,25 +17,38 @@ */ package com.alibaba.polardbx.server; +import com.alibaba.polardbx.CobarConfig; +import com.alibaba.polardbx.CobarServer; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.properties.ParamManager; import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.config.impl.MetaDbInstConfigManager; import com.alibaba.polardbx.matrix.jdbc.TConnection; +import com.alibaba.polardbx.net.compress.IPacketOutputProxy; +import com.alibaba.polardbx.net.compress.PacketOutputProxyFactory; +import com.alibaba.polardbx.net.packet.ErrorPacket; import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.server.util.PacketUtil; import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import java.io.EOFException; import java.io.IOException; import java.lang.reflect.Field; import java.nio.channels.ClosedChannelException; +import java.util.concurrent.atomic.AtomicInteger; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -44,8 +57,10 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.atMost; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockConstruction; import static org.mockito.Mockito.times; @@ -234,4 +249,59 @@ public void testHandleError() throws NoSuchFieldException, IllegalAccessExceptio verify(serverConnection).writeErrMessage(eq(1146), isNull(), anyString()); } } + + @Test + public void testSet() { + serverConnection.setUser("polardbx_root"); + Assert.assertTrue(serverConnection.isPolardbxRoot()); + } + + @Test + public void testLock() { + ConfigDataMode.Mode mode = ConfigDataMode.getMode(); + ConfigDataMode.setMode(ConfigDataMode.Mode.MOCK); + try (MockedStatic mockedStaticServer = Mockito.mockStatic(CobarServer.class); + MockedStatic mockedUtil = Mockito.mockStatic(PacketUtil.class); + MockedStatic mockedStaticPacketFactory = Mockito.mockStatic( + PacketOutputProxyFactory.class)) { + + CobarServer mockedServer = mock(CobarServer.class); + PacketOutputProxyFactory mockedPacketFactory = mock(PacketOutputProxyFactory.class); + CobarConfig mockedConfig = mock(CobarConfig.class); + + mockedStaticServer.when(CobarServer::getInstance).thenReturn(mockedServer); + mockedStaticPacketFactory.when(PacketOutputProxyFactory::getInstance).thenReturn(mockedPacketFactory); + when(mockedServer.getConfig()).thenReturn(mockedConfig); + IPacketOutputProxy proxy = mock(IPacketOutputProxy.class); + when(mockedConfig.isLock()).thenReturn(true); + + ErrorPacket mockedPacket = mock(ErrorPacket.class); + final AtomicInteger errCount = new AtomicInteger(0); + + doAnswer((invocation) -> { + errCount.incrementAndGet(); + return proxy; + }).when(mockedPacket).write(proxy); + mockedUtil.when(PacketUtil::getLock).thenReturn(mockedPacket); + + doReturn(true).when(serverConnection).isClosed(); + + serverConnection.setUser("testUser"); + Assert.assertFalse(serverConnection.isPolardbxRoot()); + + ServerQueryHandler queryHandler = new ServerQueryHandler(serverConnection); + serverConnection.setConnectionCharset("utf8"); + serverConnection.setQueryHandler(queryHandler); + + try { + serverConnection.query(new byte[] { + 33, 0, 0, 0, 3, 115, 101, 108, 101, 99, 116, 32, 64, 64, 118, 101, 114, 115, 105, + 111, 110, 95, 99, 111, 109, 109, 101, 110, 116, 32, 108, 105, 109, 105, 116, 32, 49}); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } finally { + ConfigDataMode.setMode(mode); + } + } } diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/conn/InnerConnectionTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/conn/InnerConnectionTest.java new file mode 100644 index 000000000..ad1698f11 --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/conn/InnerConnectionTest.java @@ -0,0 +1,65 @@ +package com.alibaba.polardbx.server.conn; + +import com.alibaba.polardbx.matrix.jdbc.TConnection; +import com.alibaba.polardbx.optimizer.utils.ITransaction; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class InnerConnectionTest { + @Test + public void testSetExtraServerVariables() { + TConnection connection = mock(TConnection.class); + InnerConnection mockConnection = new InnerConnection(connection); + Map map = new HashMap<>(); + when(connection.getExtraServerVariables()).thenReturn(map); + String key = "testKey"; + Object value = "testValue"; + mockConnection.setExtraServerVariables(key, value); + + Map extraServerVariables = mockConnection.getTConnection().getExtraServerVariables(); + assertEquals(value, extraServerVariables.get(key)); + + Object newValue = "newValue"; + mockConnection.setExtraServerVariables(key, newValue); + assertEquals(newValue, extraServerVariables.get(key)); + + final boolean[] first = {true}; + when(connection.getExtraServerVariables()).thenAnswer(i -> { + if (first[0]) { + first[0] = false; + return null; + } else { + return map; + } + }); + doNothing().when(connection).setExtraServerVariables(anyMap()); + newValue = "nnn"; + mockConnection.setExtraServerVariables(key, newValue); + assertEquals(newValue, extraServerVariables.get(key)); + + ITransaction trx = mock(ITransaction.class); + when(connection.getTrx()).thenReturn(trx); + Assert.assertEquals(trx, mockConnection.getTransaction()); + } + + @Test + public void commitTsoTest() throws Exception { + TConnection connection = mock(TConnection.class); + when(connection.getCommitTso()).thenReturn(123L); + doNothing().when(connection).commit(); + InnerConnection mockConnection = new InnerConnection(connection); + mockConnection.setRecordCommitTso(true); + mockConnection.commit(); + + assertEquals(123L, mockConnection.getCommitTso()); + } +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/SetHandlerTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/SetHandlerTest.java new file mode 100644 index 000000000..3c35fafdb --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/SetHandlerTest.java @@ -0,0 +1,121 @@ +package com.alibaba.polardbx.server.handler; + +import com.alibaba.polardbx.common.TddlConstants; +import com.alibaba.polardbx.common.cdc.ICdcManager; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.ParamManager; +import com.alibaba.polardbx.common.utils.InstanceRole; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.druid.sql.parser.ByteString; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.net.buffer.ByteBufferHolder; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.server.ServerConnection; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class SetHandlerTest { + @Test + public void test0() { + ServerConnection serverConnection = mock(ServerConnection.class); + Map map = new HashMap<>(); + map.put(ConnectionProperties.IGNORE_TRANSACTION_POLICY_NO_TRANSACTION, "true"); + when(serverConnection.getConnectionVariables()).thenReturn(map); + Assert.assertTrue(SetHandler.isIgnoreSettingNoTransaction(serverConnection)); + } + + @Test + public void test1() { + ServerConnection serverConnection = mock(ServerConnection.class); + Map map = new HashMap<>(); + when(serverConnection.getConnectionVariables()).thenReturn(map); + ExecutionContext ec = new ExecutionContext(); + when(serverConnection.getExecutionContext()).thenReturn(ec); + try (MockedStatic mockedStatic = mockStatic(InstConfUtil.class)) { + mockedStatic.when(() -> InstConfUtil.getBool(ConnectionParams.IGNORE_TRANSACTION_POLICY_NO_TRANSACTION)) + .thenReturn(true); + Assert.assertTrue(SetHandler.isIgnoreSettingNoTransaction(serverConnection)); + } + } + + @Test + public void test2() { + ServerConnection serverConnection = mock(ServerConnection.class); + Map map = new HashMap<>(); + when(serverConnection.getConnectionVariables()).thenReturn(map); + ExecutionContext ec = new ExecutionContext(); + when(serverConnection.getExecutionContext()).thenReturn(ec); + Map props = new HashMap<>(); + props.put(ConnectionProperties.IGNORE_TRANSACTION_POLICY_NO_TRANSACTION, "true"); + ParamManager paramManager = new ParamManager(props); + ec.setParamManager(paramManager); + Assert.assertTrue(SetHandler.isIgnoreSettingNoTransaction(serverConnection)); + } + + @Test + public void setSqlLogBinXTest() throws NoSuchFieldException, IllegalAccessException { + try { + ServerConnection serverConnection = mock(ServerConnection.class); + when(serverConnection.initOptimizerContext()).thenReturn(true); + ByteBuffer buffer = ByteBuffer.allocate(1024); + ByteBufferHolder holder = new ByteBufferHolder(buffer); + when(serverConnection.allocate()).thenReturn(holder); + when(serverConnection.checkWriteBuffer(holder, 1)).thenReturn(holder); + HashMap extraServerVariables = new HashMap<>(); + when(serverConnection.getExtraServerVariables()).thenReturn(extraServerVariables); + ByteString byteString = new ByteString("set sql_log_bin=off".getBytes(), Charset.defaultCharset()); + ConfigDataMode.setInstanceRole(InstanceRole.FAST_MOCK); + SetHandler.handleV2(byteString, serverConnection, 0, false); + Assert.assertEquals(false, serverConnection.getExtraServerVariables().get(ICdcManager.SQL_LOG_BIN)); + + byteString = new ByteString("set sql_log_bin=on".getBytes(), Charset.defaultCharset()); + ConfigDataMode.setInstanceRole(InstanceRole.FAST_MOCK); + SetHandler.handleV2(byteString, serverConnection, 0, false); + Assert.assertEquals(true, serverConnection.getExtraServerVariables().get(ICdcManager.SQL_LOG_BIN)); + } finally { + ConfigDataMode.setInstanceRole(InstanceRole.MASTER); + } + + } + + @Test + public void strictSetGlobalTest() { + + try (MockedStatic instUtilMockedStatic = Mockito.mockStatic(InstConfUtil.class)) { + + when(InstConfUtil.getValBool(TddlConstants.ENABLE_STRICT_SET_GLOBAL)).thenReturn(true); + ServerConnection serverConnection = mock(ServerConnection.class); + AtomicReference msgRef = new AtomicReference<>(null); + Mockito.doAnswer((invocation) -> { + String msg = invocation.getArgument(1, String.class); + msgRef.set(msg); + return null; + }).when(serverConnection).writeErrMessage(any(ErrorCode.class), anyString()); + + List list = new ArrayList(); + SetHandler.handleGlobalVariable(serverConnection, list, list, list); + + Assert.assertNotNull(msgRef.get()); + Assert.assertTrue(msgRef.get(), msgRef.get().contains("is not allowed")); + + } + } +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/SyncPointExecutorTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/SyncPointExecutorTest.java new file mode 100644 index 000000000..0d1742cc3 --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/SyncPointExecutorTest.java @@ -0,0 +1,302 @@ +package com.alibaba.polardbx.server.handler; + +import com.alibaba.polardbx.cdc.CdcTableUtil; +import com.alibaba.polardbx.common.jdbc.IConnection; +import com.alibaba.polardbx.common.jdbc.MasterSlave; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.utils.thread.ServerThreadPool; +import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.group.jdbc.TGroupDataSource; +import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; +import com.alibaba.polardbx.server.conn.InnerConnection; +import com.alibaba.polardbx.server.conn.InnerConnectionManager; +import com.alibaba.polardbx.transaction.TransactionExecutor; +import com.alibaba.polardbx.transaction.TransactionManager; +import com.alibaba.polardbx.transaction.trx.SyncPointTransaction; +import com.google.common.util.concurrent.Futures; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import static com.alibaba.polardbx.cdc.CdcTableUtil.CDC_TABLE_SCHEMA; +import static com.alibaba.polardbx.server.handler.SyncPointExecutor.SHOW_SYNC_POINT_VAR; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class SyncPointExecutorTest { + @Test + public void testExecute() throws SQLException { + try (MockedStatic innerConnectionManagerMockedStatic = + mockStatic(InnerConnectionManager.class); + MockedStatic execUtilsMockedStatic = mockStatic(ExecUtils.class); + MockedStatic transactionManagerMockedStatic = + mockStatic(TransactionManager.class); + MockedStatic metaDbUtil = mockStatic(MetaDbUtil.class);) { + Result result = + prepare(innerConnectionManagerMockedStatic, execUtilsMockedStatic, transactionManagerMockedStatic, + metaDbUtil); + List groupDataSources0; + + // Should success. + Assert.assertTrue(SyncPointExecutor.getInstance().execute()); + for (Map.Entry entry : result.extraServerVariables.entrySet()) { + if (ConnectionProperties.MARK_SYNC_POINT.equals(entry.getKey())) { + Assert.assertEquals("true", entry.getValue()); + } + } + Assert.assertTrue(result.inTrx.get()); + + // Empty group, should fail. + result.groupDataSources0.clear(); + Assert.assertFalse(SyncPointExecutor.getInstance().execute()); + + groupDataSources0 = new ArrayList<>(); + groupDataSources0.add(result.ds0); + when(result.showTablesRs.next()).thenReturn(false); + } + } + + @Test + public void testEmptyGroup() throws SQLException { + try (MockedStatic innerConnectionManagerMockedStatic = + mockStatic(InnerConnectionManager.class); + MockedStatic execUtilsMockedStatic = mockStatic(ExecUtils.class); + MockedStatic transactionManagerMockedStatic = + mockStatic(TransactionManager.class); + MockedStatic metaDbUtil = mockStatic(MetaDbUtil.class);) { + Result result = + prepare(innerConnectionManagerMockedStatic, execUtilsMockedStatic, transactionManagerMockedStatic, + metaDbUtil); + + // Empty group, should fail. + result.groupDataSources0.clear(); + Assert.assertFalse(SyncPointExecutor.getInstance().execute()); + } + } + + @Test + public void testNoPhyTable() throws SQLException { + try (MockedStatic innerConnectionManagerMockedStatic = + mockStatic(InnerConnectionManager.class); + MockedStatic execUtilsMockedStatic = mockStatic(ExecUtils.class); + MockedStatic transactionManagerMockedStatic = + mockStatic(TransactionManager.class); + MockedStatic metaDbUtil = mockStatic(MetaDbUtil.class);) { + Result result = + prepare(innerConnectionManagerMockedStatic, execUtilsMockedStatic, transactionManagerMockedStatic, + metaDbUtil); + when(result.showTablesRs.next()).thenReturn(false); + + // Should success. + Assert.assertTrue(SyncPointExecutor.getInstance().execute()); + for (Map.Entry entry : result.extraServerVariables.entrySet()) { + if (ConnectionProperties.MARK_SYNC_POINT.equals(entry.getKey())) { + Assert.assertEquals("true", entry.getValue()); + } + } + Assert.assertTrue(result.inTrx.get()); + } + } + + @Test + public void testDnVarOff() throws SQLException { + try (MockedStatic innerConnectionManagerMockedStatic = + mockStatic(InnerConnectionManager.class); + MockedStatic execUtilsMockedStatic = mockStatic(ExecUtils.class); + MockedStatic transactionManagerMockedStatic = + mockStatic(TransactionManager.class); + MockedStatic metaDbUtil = mockStatic(MetaDbUtil.class);) { + Result result = + prepare(innerConnectionManagerMockedStatic, execUtilsMockedStatic, transactionManagerMockedStatic, + metaDbUtil); + when(result.showSyncPointVarRs.getString(2)).thenReturn("OFF"); + Assert.assertFalse(SyncPointExecutor.getInstance().execute()); + + when(result.showSyncPointVarRs.next()).thenReturn(false); + Assert.assertFalse(SyncPointExecutor.getInstance().execute()); + } + } + + @Test + public void testTwoGroups() throws SQLException { + try (MockedStatic innerConnectionManagerMockedStatic = + mockStatic(InnerConnectionManager.class); + MockedStatic execUtilsMockedStatic = mockStatic(ExecUtils.class); + MockedStatic transactionManagerMockedStatic = + mockStatic(TransactionManager.class); + MockedStatic metaDbUtil = mockStatic(MetaDbUtil.class);) { + Result result = + prepare(innerConnectionManagerMockedStatic, execUtilsMockedStatic, transactionManagerMockedStatic, + metaDbUtil); + + TGroupDataSource ds1 = mock(TGroupDataSource.class); + String group1 = "group1"; + List groupDataSources1 = result.groups.get("group0"); + result.groups.put(group1, groupDataSources1); + + // Should success. + Assert.assertTrue(SyncPointExecutor.getInstance().execute()); + for (Map.Entry entry : result.extraServerVariables.entrySet()) { + if (ConnectionProperties.MARK_SYNC_POINT.equals(entry.getKey())) { + Assert.assertEquals("true", entry.getValue()); + } + } + Assert.assertTrue(result.inTrx.get()); + } + } + + @Test + public void testError() throws SQLException { + try (MockedStatic innerConnectionManagerMockedStatic = + mockStatic(InnerConnectionManager.class); + MockedStatic execUtilsMockedStatic = mockStatic(ExecUtils.class); + MockedStatic transactionManagerMockedStatic = + mockStatic(TransactionManager.class); + MockedStatic metaDbUtil = mockStatic(MetaDbUtil.class);) { + Result result = + prepare(innerConnectionManagerMockedStatic, execUtilsMockedStatic, transactionManagerMockedStatic, + metaDbUtil); + result.trxCount.getAndDecrement(); + + // Empty group, should fail. + Assert.assertFalse(SyncPointExecutor.getInstance().execute()); + } + } + + @NotNull + private static Result prepare(MockedStatic innerConnectionManagerMockedStatic, + MockedStatic execUtilsMockedStatic, + MockedStatic transactionManagerMockedStatic, + MockedStatic metaDbUtil) throws SQLException { + // Mock inner connection. + InnerConnectionManager manager = mock(InnerConnectionManager.class); + innerConnectionManagerMockedStatic.when(InnerConnectionManager::getInstance) + .thenReturn(manager); + InnerConnection mockInnerConnection = mock(InnerConnection.class); + when(manager.getConnection(any())).thenReturn(mockInnerConnection); + doNothing().when(mockInnerConnection).commit(); + + // Mock setting TConnection.extraServerVariables + Map extraServerVariables = new HashMap<>(); + doAnswer(invocation -> { + extraServerVariables.put(invocation.getArgument(0), invocation.getArgument(1)); + return null; + }).when(mockInnerConnection).setExtraServerVariables(any(), any()); + + // Mock get metadb connection + Connection metadbConnection = mock(Connection.class); + metaDbUtil.when(MetaDbUtil::getConnection).thenReturn(metadbConnection); + metaDbUtil.when(() -> MetaDbUtil.delete(any(), any())).thenReturn(1); + metaDbUtil.when(() -> MetaDbUtil.insert(any(), any(Map.class), any())).thenReturn(1); + + // Mock setting auto commit + AtomicBoolean inTrx = new AtomicBoolean(false); + doAnswer(invocation -> { + inTrx.set(true); + return null; + }).when(mockInnerConnection).setAutoCommit(false); + + // Mock db operations. + Statement mockStatement = mock(Statement.class); + when(mockInnerConnection.createStatement()).thenReturn(mockStatement); + when(mockStatement.executeQuery(CdcTableUtil.QUERY_CDC_DDL_RECORD_LIMIT_1)).thenReturn(null); + + // Mock sync point trx. + SyncPointTransaction trx = mock(SyncPointTransaction.class); + when(mockInnerConnection.getTransaction()).thenReturn(trx); + when(trx.getCommitTso()).thenReturn(1024L); + + // Mock getting all cdc groups. + TGroupDataSource ds0 = mock(TGroupDataSource.class); + String group0 = "group0"; + List groupDataSources0 = new ArrayList<>(); + groupDataSources0.add(ds0); + Map> groups = new HashMap<>(); + groups.put(group0, groupDataSources0); + execUtilsMockedStatic.when(() -> ExecUtils.getInstId2GroupList(CDC_TABLE_SCHEMA)) + .thenReturn(groups); + + // Mock transaction manager. + TransactionManager transactionManager = mock(TransactionManager.class); + transactionManagerMockedStatic.when((() -> TransactionManager.getInstance(any()))) + .thenReturn(transactionManager); + TransactionExecutor executor = mock(TransactionExecutor.class); + when(transactionManager.getTransactionExecutor()).thenReturn(executor); + ServerThreadPool threadPool = mock(ServerThreadPool.class); + when(executor.getExecutorService()).thenReturn(threadPool); + AtomicInteger trxCount = new AtomicInteger(); + doAnswer( + invocation -> { + trxCount.getAndIncrement(); + return Futures.immediateFuture(((Callable) invocation.getArgument(2)).call()); + } + ).when(threadPool).submit(any(), any(), any(Callable.class)); + doAnswer( + invocation -> trxCount.get() + 1 + ).when(trx).getNumberOfPartitions(); + + TGroupDirectConnection mockPhyConn = mock(TGroupDirectConnection.class); + when(ds0.getConnection(MasterSlave.MASTER_ONLY)).thenReturn(mockPhyConn); + Statement phyStatement = mock(Statement.class); + when(mockPhyConn.createStatement()).thenReturn(phyStatement); + ResultSet showTablesRs = mock(ResultSet.class); + when(phyStatement.executeQuery(any())).thenReturn(showTablesRs); + when(phyStatement.execute(any())).thenReturn(true); + when(showTablesRs.next()).thenReturn(true); + + IConnection trxConn = mock(IConnection.class); + when(trx.getConnection(any(), any(), any(), any())).thenReturn(trxConn); + Statement trxStmt = mock(Statement.class); + when(trxConn.createStatement()).thenReturn(trxStmt); + ResultSet showSyncPointVarRs = mock(ResultSet.class); + when(trxStmt.executeQuery(SHOW_SYNC_POINT_VAR)).thenReturn(showSyncPointVarRs); + when(showSyncPointVarRs.next()).thenReturn(true); + when(showSyncPointVarRs.getString(2)).thenReturn("ON"); + when(trxStmt.execute(any())).thenReturn(true); + return new Result(extraServerVariables, inTrx, ds0, groupDataSources0, showTablesRs, showSyncPointVarRs, + groups, trxCount); + } + + private static class Result { + public final Map extraServerVariables; + public final AtomicBoolean inTrx; + public final TGroupDataSource ds0; + public final List groupDataSources0; + public final ResultSet showTablesRs; + public final ResultSet showSyncPointVarRs; + public final Map> groups; + public final AtomicInteger trxCount; + + public Result(Map extraServerVariables, AtomicBoolean inTrx, TGroupDataSource ds0, + List groupDataSources0, ResultSet showTablesRs, + ResultSet showSyncPointVarRs, Map> groups, + AtomicInteger trxCount) { + this.extraServerVariables = extraServerVariables; + this.inTrx = inTrx; + this.ds0 = ds0; + this.groupDataSources0 = groupDataSources0; + this.showTablesRs = showTablesRs; + this.showSyncPointVarRs = showSyncPointVarRs; + this.groups = groups; + this.trxCount = trxCount; + } + } +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/CallSyncPointHandlerTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/CallSyncPointHandlerTest.java new file mode 100644 index 000000000..5b8f81620 --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/CallSyncPointHandlerTest.java @@ -0,0 +1,92 @@ +package com.alibaba.polardbx.server.handler.pl; + +import com.alibaba.polardbx.druid.sql.parser.ByteString; +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.matrix.jdbc.TResultSet; +import com.alibaba.polardbx.optimizer.core.row.ArrayRow; +import com.alibaba.polardbx.optimizer.core.row.Row; +import com.alibaba.polardbx.server.QueryResultHandler; +import com.alibaba.polardbx.server.ServerConnection; +import com.alibaba.polardbx.server.handler.SyncPointExecutor; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.sql.SQLException; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class CallSyncPointHandlerTest { + @Test + public void test() throws Exception { + try (MockedStatic mocked = mockStatic(SyncPointExecutor.class)) { + CallHandler handler = new CallHandler(); + SyncPointExecutor executor = mock(SyncPointExecutor.class); + mocked.when(SyncPointExecutor::getInstance).thenReturn(executor); + + // Mock server connection. + ServerConnection serverConnection = mock(ServerConnection.class); + QueryResultHandler queryResultHandler = mock(QueryResultHandler.class); + when(serverConnection.createResultHandler(false)).thenReturn(queryResultHandler); + AtomicInteger flag = new AtomicInteger(0); + doAnswer( + invocation -> { + TResultSet resultSet = invocation.getArgument(0); + ArrayResultCursor cursor = (ArrayResultCursor) resultSet.getResultCursor(); + List rows = cursor.getRows(); + ArrayRow row = (ArrayRow) rows.get(0); + String result = (String) row.getObject(0); + if ("OK".equals(result)) { + flag.set(1); + } else if ("FAIL".equals(result)) { + flag.set(-1); + } + return null; + } + ).when(queryResultHandler).sendSelectResult(any(), any(), anyLong()); + doNothing().when(queryResultHandler).sendPacketEnd(false); + + when(executor.execute()).thenReturn(false); + Assert.assertTrue( + handler.handle(ByteString.from("call polardbx.trigger_sync_point_trx()"), + serverConnection, false)); + Assert.assertEquals(-1, flag.get()); + + when(executor.execute()).thenReturn(true); + Assert.assertTrue( + handler.handle(ByteString.from("call polardbx.trigger_sync_point_trx()"), + serverConnection, false)); + Assert.assertEquals(1, flag.get()); + + AtomicBoolean error = new AtomicBoolean(false); + doAnswer( + invocation -> { + error.set(true); + return null; + } + ).when(serverConnection).writeErrMessage(any(), any()); + doThrow(new SQLException("test")).when(queryResultHandler).sendSelectResult(any(), any(), anyLong()); + Assert.assertTrue( + handler.handle(ByteString.from("call polardbx.trigger_sync_point_trx()"), + serverConnection, false)); + Assert.assertTrue(error.get()); + + error.set(false); + Assert.assertTrue( + handler.handle(ByteString.from("call polardbx.no_such_procedure()"), + serverConnection, false)); + Assert.assertTrue(error.get()); + } + } +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarBackupProcedureTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarBackupProcedureTest.java new file mode 100644 index 000000000..1b38c0e9d --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarBackupProcedureTest.java @@ -0,0 +1,107 @@ +/* + * 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 com.alibaba.polardbx.server.handler.pl; + +import com.alibaba.polardbx.common.cdc.CdcDDLContext; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.server.handler.pl.inner.ColumnarBackupProcedure; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; + +public class ColumnarBackupProcedureTest { + + @Test + public void callTest() { + try (MockedStatic cdcManagerHelperMockedStatic = mockStatic(CdcManagerHelper.class)) { + CdcManagerHelper cdcManagerHelper = mock(CdcManagerHelper.class); + cdcManagerHelperMockedStatic.when(CdcManagerHelper::getInstance).thenReturn(cdcManagerHelper); + doAnswer(invocation -> { + CdcDDLContext cdcDDLContext = invocation.getArgument(0); + cdcDDLContext.setCommitTso(100L); + return null; + }).when(cdcManagerHelper).notifyDdlWithContext(any()); + + ArrayResultCursor cursor = new ArrayResultCursor("columnar_backup"); + + ColumnarBackupProcedure procedure = new ColumnarBackupProcedure(); + // Execute inner procedure. + procedure.execute(null, null, cursor); + + Assert.assertEquals(1, cursor.getRows().size()); + Assert.assertEquals(100L, cursor.getRows().get(0).getObject(0)); + } + } + + @Test + public void callErrorTest() { + try (MockedStatic cdcManagerHelperMockedStatic = mockStatic(CdcManagerHelper.class)) { + CdcManagerHelper cdcManagerHelper = mock(CdcManagerHelper.class); + cdcManagerHelperMockedStatic.when(CdcManagerHelper::getInstance).thenReturn(cdcManagerHelper); + doAnswer(invocation -> { + CdcDDLContext cdcDDLContext = invocation.getArgument(0); + cdcDDLContext.setCommitTso(null); + return null; + }).when(cdcManagerHelper).notifyDdlWithContext(any()); + + ArrayResultCursor cursor = new ArrayResultCursor("columnar_backup"); + + ColumnarBackupProcedure procedure = new ColumnarBackupProcedure(); + // Execute inner procedure. + try { + procedure.execute(null, null, cursor); + Assert.fail("should throw exception"); + } catch (Exception ignored) { + + } + + doAnswer(invocation -> { + CdcDDLContext cdcDDLContext = invocation.getArgument(0); + cdcDDLContext.setCommitTso(0L); + return null; + }).when(cdcManagerHelper).notifyDdlWithContext(any()); + + try { + procedure.execute(null, null, cursor); + Assert.fail("should throw exception"); + } catch (Exception ignored) { + + } + + doAnswer(invocation -> { + CdcDDLContext cdcDDLContext = invocation.getArgument(0); + cdcDDLContext.setCommitTso(-1L); + return null; + }).when(cdcManagerHelper).notifyDdlWithContext(any()); + + try { + procedure.execute(null, null, cursor); + Assert.fail("should throw exception"); + } catch (Exception ignored) { + + } + } + } +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarFlushProcedureTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarFlushProcedureTest.java new file mode 100644 index 000000000..7cad9eb95 --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarFlushProcedureTest.java @@ -0,0 +1,310 @@ +/* + * 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 com.alibaba.polardbx.server.handler.pl; + +import com.alibaba.polardbx.common.cdc.CdcDDLContext; +import com.alibaba.polardbx.common.cdc.CdcManagerHelper; +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.druid.sql.parser.SQLParserFeature; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableStatus; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.parse.FastsqlUtils; +import com.alibaba.polardbx.server.handler.pl.inner.ColumnarFlushProcedure; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; + +public class ColumnarFlushProcedureTest { + + @Test + public void callTest() { + try (MockedStatic cdcManagerHelperMockedStatic = mockStatic(CdcManagerHelper.class)) { + CdcManagerHelper cdcManagerHelper = mock(CdcManagerHelper.class); + cdcManagerHelperMockedStatic.when(CdcManagerHelper::getInstance).thenReturn(cdcManagerHelper); + doAnswer(invocation -> { + CdcDDLContext cdcDDLContext = invocation.getArgument(0); + cdcDDLContext.setCommitTso(100L); + return null; + }).when(cdcManagerHelper).notifyDdlWithContext(any()); + + SQLCallStatement statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush()", + SQLParserFeature.IgnoreNameQuotes).get(0); + + ArrayResultCursor cursor = new ArrayResultCursor("columnar_flush"); + + ColumnarFlushProcedure procedure = new ColumnarFlushProcedure(); + // Execute inner procedure. + procedure.execute(null, statement, cursor); + + Assert.assertEquals(1, cursor.getRows().size()); + Assert.assertEquals(100L, cursor.getRows().get(0).getObject(0)); + } + } + + @Test + public void callParamsTest() { + try (MockedStatic cdcManagerHelperMockedStatic = mockStatic(CdcManagerHelper.class); + final MockedStatic metaDbUtilMockedStatic = mockStatic(MetaDbUtil.class)) { + CdcManagerHelper cdcManagerHelper = mock(CdcManagerHelper.class); + cdcManagerHelperMockedStatic.when(CdcManagerHelper::getInstance).thenReturn(cdcManagerHelper); + AtomicReference markSql = new AtomicReference<>(); + doAnswer(invocation -> { + CdcDDLContext cdcDDLContext = invocation.getArgument(0); + cdcDDLContext.setCommitTso(100L); + markSql.set(cdcDDLContext.getDdlSql()); + return null; + }).when(cdcManagerHelper).notifyDdlWithContext(any()); + + SQLCallStatement statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush()", + SQLParserFeature.IgnoreNameQuotes).get(0); + + List records = new ArrayList<>(); + + metaDbUtilMockedStatic.when(() -> MetaDbUtil.query(any(), any(), any(), any())).thenReturn(records); + + ArrayResultCursor cursor = new ArrayResultCursor("columnar_flush"); + + ColumnarFlushProcedure procedure = new ColumnarFlushProcedure(); + // Execute inner procedure. + procedure.execute(null, statement, cursor); + + Assert.assertEquals(1, cursor.getRows().size()); + Assert.assertEquals(100L, cursor.getRows().get(0).getObject(0)); + Assert.assertTrue(markSql.get().equalsIgnoreCase("call polardbx.columnar_flush()")); + + ColumnarTableMappingRecord record = new ColumnarTableMappingRecord(); + record.tableId = 11L; + record.status = ColumnarTableStatus.PUBLIC.name(); + records.add(record); + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush(11)", + SQLParserFeature.IgnoreNameQuotes).get(0); + + cursor = new ArrayResultCursor("columnar_flush"); + procedure.execute(null, statement, cursor); + + Assert.assertEquals(1, cursor.getRows().size()); + Assert.assertEquals(100L, cursor.getRows().get(0).getObject(0)); + Assert.assertTrue(markSql.get().equalsIgnoreCase("call polardbx.columnar_flush(11)")); + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush(\"a\", \"b\", \"c\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + + cursor = new ArrayResultCursor("columnar_flush"); + procedure.execute(null, statement, cursor); + + Assert.assertEquals(1, cursor.getRows().size()); + Assert.assertEquals(100L, cursor.getRows().get(0).getObject(0)); + Assert.assertTrue(markSql.get().equalsIgnoreCase("call polardbx.columnar_flush(11)")); + } + } + + @Test + public void callErrorTest() { + try (MockedStatic cdcManagerHelperMockedStatic = mockStatic(CdcManagerHelper.class)) { + CdcManagerHelper cdcManagerHelper = mock(CdcManagerHelper.class); + cdcManagerHelperMockedStatic.when(CdcManagerHelper::getInstance).thenReturn(cdcManagerHelper); + doAnswer(invocation -> { + CdcDDLContext cdcDDLContext = invocation.getArgument(0); + cdcDDLContext.setCommitTso(null); + return null; + }).when(cdcManagerHelper).notifyDdlWithContext(any()); + + SQLCallStatement statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush()", + SQLParserFeature.IgnoreNameQuotes).get(0); + + ArrayResultCursor cursor = new ArrayResultCursor("columnar_flush"); + + ColumnarFlushProcedure procedure = new ColumnarFlushProcedure(); + // Execute inner procedure. + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception ignored) { + + } + + doAnswer(invocation -> { + CdcDDLContext cdcDDLContext = invocation.getArgument(0); + cdcDDLContext.setCommitTso(0L); + return null; + }).when(cdcManagerHelper).notifyDdlWithContext(any()); + + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception ignored) { + + } + + doAnswer(invocation -> { + CdcDDLContext cdcDDLContext = invocation.getArgument(0); + cdcDDLContext.setCommitTso(-1L); + return null; + }).when(cdcManagerHelper).notifyDdlWithContext(any()); + + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception ignored) { + + } + } + + } + + @Test + public void callParamsErrorTest() { + try (MockedStatic cdcManagerHelperMockedStatic = mockStatic(CdcManagerHelper.class); + final MockedStatic metaDbUtilMockedStatic = mockStatic(MetaDbUtil.class)) { + CdcManagerHelper cdcManagerHelper = mock(CdcManagerHelper.class); + cdcManagerHelperMockedStatic.when(CdcManagerHelper::getInstance).thenReturn(cdcManagerHelper); + doAnswer(invocation -> { + CdcDDLContext cdcDDLContext = invocation.getArgument(0); + cdcDDLContext.setCommitTso(100L); + return null; + }).when(cdcManagerHelper).notifyDdlWithContext(any()); + + List records = new ArrayList<>(); + + metaDbUtilMockedStatic.when(() -> MetaDbUtil.query(any(), any(), any(), any())).thenReturn(records); + + ArrayResultCursor cursor = new ArrayResultCursor("columnar_flush"); + + ColumnarFlushProcedure procedure = new ColumnarFlushProcedure(); + // Execute inner procedure. + + SQLCallStatement statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush('b')", + SQLParserFeature.IgnoreNameQuotes).get(0); + + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush(\"b\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush(\"b\", \"c\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush(1.2)", + SQLParserFeature.IgnoreNameQuotes).get(0); + + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush(1,2)", + SQLParserFeature.IgnoreNameQuotes).get(0); + + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush(1)", + SQLParserFeature.IgnoreNameQuotes).get(0); + + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush(a,b,c)", + SQLParserFeature.IgnoreNameQuotes).get(0); + + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush('a','b','c')", + SQLParserFeature.IgnoreNameQuotes).get(0); + + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_flush(\"a\",\"b\",\"c\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + + try { + procedure.execute(null, statement, cursor); + Assert.fail("should throw exception"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + } + } +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarRollbackProcedureTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarRollbackProcedureTest.java new file mode 100644 index 000000000..94cf9c8be --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarRollbackProcedureTest.java @@ -0,0 +1,178 @@ +/* + * 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 com.alibaba.polardbx.server.handler.pl; + +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.druid.sql.parser.SQLParserFeature; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarPurgeHistoryRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.parse.FastsqlUtils; +import com.alibaba.polardbx.server.ServerConnection; +import com.alibaba.polardbx.server.handler.pl.inner.ColumnarRollbackProcedure; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class ColumnarRollbackProcedureTest { + + @Test + public void paramTest() { + ArrayResultCursor cursor = new ArrayResultCursor("test"); + ServerConnection connection = Mockito.mock(ServerConnection.class); + when(connection.getHost()).thenReturn("127.0.0.1"); + when(connection.getUser()).thenReturn("user_one"); + ColumnarRollbackProcedure procedure = new ColumnarRollbackProcedure(); + SQLCallStatement statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_rollback(10)", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(connection, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + when(connection.getUser()).thenReturn("polardbx_root"); + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_rollback()", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(connection, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_rollback(\"123\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(connection, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql( + "call polardbx.columnar_rollback(-120)", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(connection, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql( + "call polardbx.columnar_rollback(120.1)", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(connection, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql( + "call polardbx.columnar_rollback(120, 30)", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(connection, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + } + + @Test + public void executeTest() { + try (final MockedStatic metaDbUtilMockedStatic = mockStatic(MetaDbUtil.class)) { + ArrayResultCursor cursor = new ArrayResultCursor("test"); + ServerConnection connection = Mockito.mock(ServerConnection.class); + when(connection.getHost()).thenReturn("127.0.0.1"); + when(connection.getUser()).thenReturn("polardbx_root"); + ColumnarRollbackProcedure procedure = new ColumnarRollbackProcedure(); + SQLCallStatement statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_rollback(1234569)", + SQLParserFeature.IgnoreNameQuotes).get(0); + + metaDbUtilMockedStatic.when(() -> MetaDbUtil.query(Mockito.anyString(), Mockito.any(), + Mockito.eq(ColumnarCheckpointsRecord.class), Mockito.any())).thenReturn(new ArrayList<>()); + try { + procedure.execute(connection, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + List checkpointsRecords = new ArrayList<>(); + ColumnarCheckpointsRecord record = new ColumnarCheckpointsRecord(); + record.setCheckpointTso(1234569L); + checkpointsRecords.add(record); + metaDbUtilMockedStatic.when(() -> MetaDbUtil.query(Mockito.anyString(), Mockito.any(), + Mockito.eq(ColumnarCheckpointsRecord.class), Mockito.any())).thenReturn(checkpointsRecords); + + List purgeRecords = new ArrayList<>(); + ColumnarPurgeHistoryRecord record1 = new ColumnarPurgeHistoryRecord(); + record1.tso = 1234569L + 10; + purgeRecords.add(record1); + metaDbUtilMockedStatic.when(() -> MetaDbUtil.query(Mockito.anyString(), Mockito.any(), + Mockito.eq(ColumnarPurgeHistoryRecord.class), Mockito.any())).thenReturn(purgeRecords); + + try { + procedure.execute(connection, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + Connection connection2 = Mockito.mock(Connection.class); + metaDbUtilMockedStatic.when(MetaDbUtil::getConnection).thenReturn(connection2); + + metaDbUtilMockedStatic.when(() -> MetaDbUtil.query(Mockito.anyString(), Mockito.any(), + Mockito.eq(ColumnarPurgeHistoryRecord.class), Mockito.any())).thenReturn(new ArrayList<>()); + + metaDbUtilMockedStatic.when(() -> MetaDbUtil.insert(Mockito.anyString(), Mockito.anyMap(), + Mockito.any())).thenReturn(1); + + metaDbUtilMockedStatic.when(() -> MetaDbUtil.delete(Mockito.anyString(), Mockito.anyMap(), + Mockito.any())).thenReturn(1); + + metaDbUtilMockedStatic.when(() -> MetaDbUtil.update(Mockito.anyString(), Mockito.anyMap(), + Mockito.any())).thenReturn(1); + + procedure.execute(connection, statement, cursor); + } + + } +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarSetConfigProcedureTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarSetConfigProcedureTest.java new file mode 100644 index 000000000..f8cb62e63 --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarSetConfigProcedureTest.java @@ -0,0 +1,180 @@ +/* + * 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 com.alibaba.polardbx.server.handler.pl; + +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.druid.sql.parser.SQLParserFeature; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.parse.FastsqlUtils; +import com.alibaba.polardbx.server.handler.pl.inner.ColumnarSetConfigProcedure; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.Mockito.mockStatic; + +public class ColumnarSetConfigProcedureTest { + + @Test + public void paramTest() { + try (final MockedStatic metaDbUtilMockedStatic = mockStatic(MetaDbUtil.class)) { + metaDbUtilMockedStatic.when(MetaDbUtil::getConnection).thenReturn(null); + metaDbUtilMockedStatic.when(() -> MetaDbUtil.insert(any(), anyList(), any())).thenReturn(new int[] {1}); + + ColumnarSetConfigProcedure procedure = new ColumnarSetConfigProcedure(); + SQLCallStatement statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_set_config(aaa)", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(null, statement, null); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_set_config(123, \"aaa\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(null, statement, null); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_set_config(\"123\", \"ewc\", \"aaa\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(null, statement, null); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + metaDbUtilMockedStatic.when( + () -> MetaDbUtil.query(any(), anyMap(), any(), any())) + .thenReturn(new ArrayList()); + + statement = + (SQLCallStatement) FastsqlUtils.parseSql( + "call polardbx.columnar_set_config(\"aaa\", \"bbb\", \"ccc\", \"kk\", \"vv\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(null, statement, null); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + ColumnarTableMappingRecord record = new ColumnarTableMappingRecord(); + record.tableSchema = "aaa"; + record.tableName = "bbb"; + record.indexName = "ccc"; + record.tableId = 2; + List records = new ArrayList<>(); + records.add(record); + record = new ColumnarTableMappingRecord(); + record.tableSchema = "aaa"; + record.tableName = "bbb"; + record.indexName = "cccd"; + record.tableId = 4; + records.add(record); + metaDbUtilMockedStatic.when( + () -> MetaDbUtil.query(any(), anyMap(), any(), any())) + .thenReturn(records); + + try { + procedure.execute(null, statement, null); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + } + + } + + @Test + public void callTest() { + try (final MockedStatic metaDbUtilMockedStatic = mockStatic(MetaDbUtil.class)) { + metaDbUtilMockedStatic.when(MetaDbUtil::getConnection).thenReturn(null); + metaDbUtilMockedStatic.when(() -> MetaDbUtil.insert(any(), anyList(), any())).thenReturn(new int[] {1}); + + ColumnarTableMappingRecord record = new ColumnarTableMappingRecord(); + record.tableSchema = "aaa"; + record.tableName = "bbb"; + record.indexName = "ccc"; + record.tableId = 2; + List records = new ArrayList<>(); + records.add(record); + metaDbUtilMockedStatic.when( + () -> MetaDbUtil.query(any(), anyMap(), any(), any())) + .thenReturn(records); + + ColumnarSetConfigProcedure procedure = new ColumnarSetConfigProcedure(); + SQLCallStatement statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_set_config(\"aaa\", \"bbb\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + + ArrayResultCursor cursor = new ArrayResultCursor("test"); + procedure.execute(null, statement, cursor); + Assert.assertEquals(1, cursor.getRows().size()); + Assert.assertEquals(2, cursor.getReturnColumns().size()); + Assert.assertTrue("aaa".equalsIgnoreCase(cursor.getRows().get(0).getObject(0).toString())); + Assert.assertTrue("bbb".equalsIgnoreCase(cursor.getRows().get(0).getObject(1).toString())); + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_set_config(2, \"aaa\", \"bbb\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + cursor = new ArrayResultCursor("test"); + procedure.execute(null, statement, cursor); + Assert.assertEquals(1, cursor.getRows().size()); + Assert.assertEquals(3, cursor.getReturnColumns().size()); + Assert.assertEquals(2L, cursor.getRows().get(0).getObject(0)); + Assert.assertTrue("aaa".equalsIgnoreCase(cursor.getRows().get(0).getObject(1).toString())); + Assert.assertTrue("bbb".equalsIgnoreCase(cursor.getRows().get(0).getObject(2).toString())); + + statement = + (SQLCallStatement) FastsqlUtils.parseSql( + "call polardbx.columnar_set_config(\"aaa\", \"bbb\", \"ccc\", \"kk\", \"vv\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + cursor = new ArrayResultCursor("test"); + procedure.execute(null, statement, cursor); + Assert.assertEquals(1, cursor.getRows().size()); + Assert.assertEquals(6, cursor.getReturnColumns().size()); + Assert.assertTrue("aaa".equalsIgnoreCase(cursor.getRows().get(0).getObject(0).toString())); + Assert.assertTrue("bbb".equalsIgnoreCase(cursor.getRows().get(0).getObject(1).toString())); + Assert.assertTrue("ccc".equalsIgnoreCase(cursor.getRows().get(0).getObject(2).toString())); + Assert.assertEquals(2L, cursor.getRows().get(0).getObject(3)); + Assert.assertTrue("kk".equalsIgnoreCase(cursor.getRows().get(0).getObject(4).toString())); + Assert.assertTrue("vv".equalsIgnoreCase(cursor.getRows().get(0).getObject(5).toString())); + } + + } + +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarSnapshotFilesProcedureTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarSnapshotFilesProcedureTest.java new file mode 100644 index 000000000..8e1e2846d --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/handler/pl/ColumnarSnapshotFilesProcedureTest.java @@ -0,0 +1,137 @@ +/* + * 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 com.alibaba.polardbx.server.handler.pl; + +import com.alibaba.polardbx.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.polardbx.druid.sql.parser.SQLParserFeature; +import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarAppendedFilesRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarCheckpointsRecord; +import com.alibaba.polardbx.gms.metadb.table.FileInfoRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import com.alibaba.polardbx.optimizer.parse.FastsqlUtils; +import com.alibaba.polardbx.server.handler.pl.inner.ColumnarSnapshotFilesProcedure; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.mockStatic; + +public class ColumnarSnapshotFilesProcedureTest { + + @Test + public void paramTest() { + ArrayResultCursor cursor = new ArrayResultCursor("test"); + ColumnarSnapshotFilesProcedure procedure = new ColumnarSnapshotFilesProcedure(); + SQLCallStatement statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_snapshot_files()", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(null, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_snapshot_files(12.1)", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(null, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_snapshot_files(\"123\")", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(null, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql( + "call polardbx.columnar_snapshot_files(-120)", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(null, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + statement = + (SQLCallStatement) FastsqlUtils.parseSql( + "call polardbx.columnar_snapshot_files(120, 30)", + SQLParserFeature.IgnoreNameQuotes).get(0); + try { + procedure.execute(null, statement, cursor); + Assert.fail(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + } + + @Test + public void executeTest() { + try (final MockedStatic metaDbUtilMockedStatic = mockStatic(MetaDbUtil.class)) { + ArrayResultCursor cursor = new ArrayResultCursor("test"); + ColumnarSnapshotFilesProcedure procedure = new ColumnarSnapshotFilesProcedure(); + SQLCallStatement statement = + (SQLCallStatement) FastsqlUtils.parseSql("call polardbx.columnar_snapshot_files(77665544)", + SQLParserFeature.IgnoreNameQuotes).get(0); + + List records = new ArrayList<>(); + records.add(new ColumnarCheckpointsRecord()); + records.get(0).setBinlogTso(77665544L); + records.get(0).setCheckpointTso(77665544L); + metaDbUtilMockedStatic.when(() -> MetaDbUtil.query(Mockito.anyString(), Mockito.any(), + Mockito.eq(ColumnarCheckpointsRecord.class), Mockito.any())).thenReturn(records); + + List fileInfoRecords = new ArrayList<>(); + FileInfoRecord fileInfoRecord = new FileInfoRecord(); + fileInfoRecord.setFileName("a.orc"); + fileInfoRecord.setExtentSize(1024L); + fileInfoRecords.add(fileInfoRecord); + metaDbUtilMockedStatic.when(() -> MetaDbUtil.query(Mockito.anyString(), Mockito.any(), + Mockito.eq(FileInfoRecord.class), Mockito.any())).thenReturn(fileInfoRecords); + + List appendedFilesRecords = new ArrayList<>(); + ColumnarAppendedFilesRecord appendedFilesRecord = new ColumnarAppendedFilesRecord(); + appendedFilesRecord.setFileName("b.csv"); + appendedFilesRecord.setAppendOffset(2048L); + appendedFilesRecord.setAppendLength(4096L); + appendedFilesRecords.add(appendedFilesRecord); + metaDbUtilMockedStatic.when(() -> MetaDbUtil.query(Mockito.anyString(), Mockito.any(), + Mockito.eq(ColumnarAppendedFilesRecord.class), Mockito.any())).thenReturn(appendedFilesRecords); + + procedure.execute(null, statement, cursor); + System.out.println(cursor.getRows()); + } + } +} diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/response/SelectPolardbVersionTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/response/SelectPolardbVersionTest.java index c9633c5ee..ad7fbcfb7 100644 --- a/polardbx-server/src/test/java/com/alibaba/polardbx/server/response/SelectPolardbVersionTest.java +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/response/SelectPolardbVersionTest.java @@ -1,5 +1,9 @@ package com.alibaba.polardbx.server.response; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.common.utils.version.Version; +import com.alibaba.polardbx.executor.ddl.job.task.cdc.CdcVersionUtil; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.ColumnarVersionUtil; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.gms.topology.DbTopologyManager; import com.alibaba.polardbx.gms.util.MetaDbUtil; @@ -30,6 +34,71 @@ private static RowDataPacket generatePacket() { return row; } + @Test + public void testParseProductVersion() { + RowDataPacket packet = generatePacket(); + String type = "Product"; + final String productVersion = "PolarDB V2"; + final String productReleaseDate = "Distributed Edition"; + SelectPolardbVersion.addToRow(packet, type, + productVersion, productReleaseDate, CHARSET, + new Pair<>("5.4.20", "20241015"), + new Pair<>("8.4.20", "20241015"), + "20241015"); + + String typeInPacket = new String(packet.fieldValues.get(0)); + String versionInPacket = new String(packet.fieldValues.get(1)); + String releaseDateInPacket = new String(packet.fieldValues.get(2)); + Assert.assertEquals(type, typeInPacket); + Assert.assertEquals("PolarDB V2_2.5.0_5.4.20-20241015_8.4.20-20241015 (Distributed Edition)", versionInPacket); + Assert.assertEquals("20241015", releaseDateInPacket); + } + + @Test + public void testMaxVersion() throws Exception { + try (MockedStatic versionMockedStatic = Mockito.mockStatic(Version.class); + MockedStatic mockedStatic = Mockito.mockStatic(ExecUtils.class); + MockedStatic mockedCdcVersionUtil = Mockito.mockStatic(CdcVersionUtil.class); + MockedStatic mockedMetaDBUtil = Mockito.mockStatic(MetaDbUtil.class); + MockedStatic mockedColumnarVersionUtil = Mockito.mockStatic( + ColumnarVersionUtil.class)) { + + versionMockedStatic.when(Version::getVersion).thenReturn("5.4.20-20211015"); + mockedStatic.when(ExecUtils::getDnPolardbVersion).thenReturn("8.4.20-20241015"); + mockedCdcVersionUtil.when(CdcVersionUtil::getVersion).thenReturn("5.4.1-20241016"); + mockedMetaDBUtil.when(MetaDbUtil::getGmsPolardbVersion).thenReturn("5.4.2-20241017"); + mockedColumnarVersionUtil.when(ColumnarVersionUtil::getVersion).thenReturn("5.4.30-20251018"); + + Assert.assertEquals(SelectPolardbVersion.getMaxVersion(), "20251018"); + } + + try (MockedStatic versionMockedStatic = Mockito.mockStatic(Version.class); + MockedStatic mockedCdcVersionUtil = Mockito.mockStatic(CdcVersionUtil.class); + MockedStatic mockedMetaDBUtil = Mockito.mockStatic(MetaDbUtil.class); + MockedStatic mockedColumnarVersionUtil = Mockito.mockStatic( + ColumnarVersionUtil.class)) { + + versionMockedStatic.when(Version::getVersion).thenReturn("5.4.20-20211015"); + mockedCdcVersionUtil.when(CdcVersionUtil::getVersion).thenReturn("5.4.1-20241016"); + mockedMetaDBUtil.when(MetaDbUtil::getGmsPolardbVersion).thenReturn("5.4.2-20241017"); + mockedColumnarVersionUtil.when(ColumnarVersionUtil::getVersion).thenReturn("5.4.30-20251018"); + + Assert.assertEquals(SelectPolardbVersion.getMaxVersion(), "20211015"); + } + } + + @Test + public void testReplaceWhenGreaterThan() { + String releaseDate = "20240314"; + String type = "CN"; + Assert.assertEquals("20240315", + SelectPolardbVersion.replaceWhenGreaterThan(releaseDate, "5.4.19-20240315", type)); + Assert.assertEquals(releaseDate, + SelectPolardbVersion.replaceWhenGreaterThan(releaseDate, "5.4.19-20240313", type)); + Assert.assertEquals("20240313", SelectPolardbVersion.replaceWhenGreaterThan(null, "5.4.19-20240313", type)); + Assert.assertEquals(releaseDate, SelectPolardbVersion.replaceWhenGreaterThan(releaseDate, null, type)); + } + @Test public void testParseVersion() { RowDataPacket packet = generatePacket(); diff --git a/polardbx-server/src/test/java/com/alibaba/polardbx/server/response/ShowMppTest.java b/polardbx-server/src/test/java/com/alibaba/polardbx/server/response/ShowMppTest.java new file mode 100644 index 000000000..420f45d63 --- /dev/null +++ b/polardbx-server/src/test/java/com/alibaba/polardbx/server/response/ShowMppTest.java @@ -0,0 +1,37 @@ +package com.alibaba.polardbx.server.response; + +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.gms.node.InternalNode; +import com.alibaba.polardbx.gms.node.MppScope; +import com.alibaba.polardbx.net.packet.RowDataPacket; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +public class ShowMppTest { + @Test + public void testRole() { + try (MockedStatic configDataModeMockedStatic = Mockito.mockStatic(ConfigDataMode.class)) { + configDataModeMockedStatic.when(() -> ConfigDataMode.isMasterMode()).thenReturn(true); + configDataModeMockedStatic.when(() -> ConfigDataMode.isRowSlaveMode()).thenReturn(false); + + InternalNode node = Mockito.mock(InternalNode.class); + Mockito.when(node.isLeader()).thenReturn(true); + Mockito.when(node.getInstId()).thenReturn(""); + Mockito.when(node.getHostPort()).thenReturn(""); + RowDataPacket rowDataPacket = ShowMpp.getRow("utf8", node, MppScope.CURRENT); + String role = new String(rowDataPacket.fieldValues.get(2)); + Assert.assertEquals("W", role); + + rowDataPacket = ShowMpp.getRow("utf8", node, MppScope.SLAVE); + role = new String(rowDataPacket.fieldValues.get(2)); + Assert.assertEquals("R", role); + + rowDataPacket = ShowMpp.getRow("utf8", node, MppScope.COLUMNAR); + role = new String(rowDataPacket.fieldValues.get(2)); + Assert.assertEquals("CR", role); + } + + } +} diff --git a/polardbx-test/pom.xml b/polardbx-test/pom.xml index 62d67bb9f..579069a3a 100644 --- a/polardbx-test/pom.xml +++ b/polardbx-test/pom.xml @@ -15,8 +15,9 @@ polardbx-test - 5.1.49 + 5.1.40.12 8.0.26 + 1.4.0-SNAPSHOT none 24 10 @@ -26,17 +27,23 @@ 0.7.2 1.0.7 2.10.1 - - - + 1.0 + + + - pl.pragmatists - JUnitParams - ${jUnitParams.version} + net.jcip + jcip-annotations + ${jcip.version} + + + com.alibaba.external + test.junit.hamcrest + ${test.junit.hamcrest.version} test @@ -88,34 +95,33 @@ ${mysql_connector_v5} test - - com.google.truth - truth - ${truth.version} + com.aliyun + polardbx-java-connector + ${polardbx_connector} test + + + org.junit.jupiter + junit-jupiter + + - - org.springframework - spring-jdbc - ${spring_version} - test - - - org.hamcrest - hamcrest - test - - - net.jcip - jcip-annotations - ${jcip.version} + com.google.truth + truth + ${truth.version} test + + + + + + commons-cli commons-cli @@ -126,26 +132,6 @@ toml4j ${toml4j.version} - - com.aliyun - aliyun-encdb-mysql-jdbc - ${encjdbc.version} - - - io.grpc - grpc-core - - - mysql - mysql-connector-java - - - - - com.google.code.gson - gson - ${gson.version} - @@ -162,7 +148,7 @@ ${mvn_parallel} - + ${mvn_threadCount} ${mvn_threadCountClasses} ${mvn_threadCountSuites} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/BaseTestCase.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/BaseTestCase.java index f8b2bc0d9..917e055ee 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/BaseTestCase.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/BaseTestCase.java @@ -24,7 +24,9 @@ import com.alibaba.polardbx.druid.sql.parser.Token; import com.alibaba.polardbx.qatest.constant.ConfigConstant; import com.alibaba.polardbx.qatest.entity.ColumnEntity; +import com.alibaba.polardbx.qatest.util.ColumnarIndexNotInitedException; import com.alibaba.polardbx.qatest.util.ConnectionManager; +import com.alibaba.polardbx.qatest.util.FailFastTestWatcher; import com.alibaba.polardbx.qatest.util.JdbcUtil; import com.alibaba.polardbx.qatest.util.PropertiesUtil; import com.google.common.cache.Cache; @@ -37,6 +39,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.runner.RunWith; import javax.net.ssl.SSLException; @@ -51,15 +54,20 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import static com.alibaba.polardbx.qatest.util.PropertiesUtil.getConnectionProperties; import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentSameAssertWithDiffSql; +import static com.google.common.truth.Truth.assertWithMessage; @RunWith(CommonCaseRunner.class) public class BaseTestCase implements BaseTestMode { @@ -81,8 +89,11 @@ public class BaseTestCase implements BaseTestMode { private List metaDBConnections = new ArrayList<>(); protected String hint; + @Rule + public FailFastTestWatcher failFastTestWatcher = new FailFastTestWatcher(ColumnarIndexNotInitedException.class); + @Before - public void initializeFileStorage() { + public void initializeFileStorage() throws ColumnarIndexNotInitedException { boolean useFileStorageMode = PropertiesUtil.useFileStorage() && usingNewPartDb() && ClassHelper.getFileStorageTestCases().contains(getClass()); @@ -99,8 +110,12 @@ && usingNewPartDb() boolean skipColumnarIndex = PropertiesUtil.skipCreateColumnarIndex(); if (!skipColumnarIndex && columnarMode && !initedColumnar()) { - createColumnarIndex(); - prepareColumnarVars(); + try { + createColumnarIndex(); + prepareColumnarVars(); + } catch (Throwable t) { + throw new ColumnarIndexNotInitedException(t); + } } } @@ -138,6 +153,9 @@ private boolean checkInit() { private boolean initedColumnar() { String sourceDB1 = PropertiesUtil.polardbXAutoDBName1Innodb(); List tableNames = collectTableNames(sourceDB1); + if (tableNames.isEmpty()) { + return true; + } try (Connection conn = getPolardbxConnection(sourceDB1)) { Statement statement = conn.createStatement(); ResultSet rs = statement.executeQuery( @@ -249,8 +267,8 @@ private Object prepareArchivedData() { private void createColumnarIndex() { String sourceDB1 = PropertiesUtil.polardbXAutoDBName1Innodb(); String sourceDB2 = PropertiesUtil.polardbXAutoDBName2Innodb(); - createColumnarIndex(sourceDB1); - createColumnarIndex(sourceDB2); + createColumnarIndex(sourceDB1, 4); + createColumnarIndex(sourceDB2, 4); } private boolean hasPrimaryKey(String dbName, String tableName) { @@ -269,26 +287,55 @@ private boolean hasPrimaryKey(String dbName, String tableName) { return false; } - private void createColumnarIndex(String dbName) { + private void createColumnarIndex(String dbName, int parallelism) { List allTables = collectTableNames(dbName); List tableNames = allTables.stream().filter(t -> hasPrimaryKey(dbName, t)).collect(Collectors.toList()); List difference = new ArrayList<>(allTables); difference.removeAll(tableNames); log.error("no primary key table list: " + difference.stream().collect(Collectors.joining(","))); - List columnarCols = new ArrayList<>(tableNames.size()); + + // set logical ddl parallelism + try (Connection conn = getPolardbxConnection(dbName)) { + JdbcUtil.executeSuccess(conn, "set global logical_ddl_parallelism = " + parallelism); + } catch (Throwable t) { + throw new RuntimeException("Set logical ddl parallelism failed.", t); + } + + ExecutorService executorService = Executors.newFixedThreadPool(parallelism); + // List to hold runnable tasks + List> tasks = new ArrayList<>(); + + // Prepare the tasks for (String tableName : tableNames) { - columnarCols.add(getColumnForColumnar(dbName, tableName)); + String colName = getColumnForColumnar(dbName, tableName); + String sql = + String.format(CREATE_COLUMNAR_INDEX, "col_idx_" + colName, tableName, colName, colName, + RandomUtils.nextInt(9) + 1); + tasks.add(() -> { + try (Connection conn = getPolardbxConnection(dbName)) { + log.info(sql); + JdbcUtil.executeSuccess(conn, sql); + } catch (Throwable t) { + throw new RuntimeException("Create CCI failed.", t); + } + return null; + }); } - try (Connection conn = getPolardbxConnection(dbName)) { - for (int i = 0; i < tableNames.size(); ++i) { - String colName = columnarCols.get(i); - String sql = - String.format(CREATE_COLUMNAR_INDEX, "col_idx_" + colName, tableNames.get(i), colName, colName, - RandomUtils.nextInt(9) + 1); - JdbcUtil.executeSuccess(conn, sql); + + try { + List> futures = executorService.invokeAll(tasks); + for (Future future : futures) { + try { + future.get(); + } catch (Throwable t) { + throw new RuntimeException(t); + } } - } catch (Throwable t) { - throw new RuntimeException(t); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } finally { + executorService.shutdownNow(); } } @@ -682,11 +729,21 @@ public void afterBaseTestCase() { } } - public List> getTrace(Connection tddlConnection) { + public static List> getTrace(Connection tddlConnection) { final ResultSet rs = JdbcUtil.executeQuery("show trace", tddlConnection); return JdbcUtil.getStringResult(rs, false); } + public static void checkTraceRowCount(int rowCount, Connection conn) { + final List> traceUpdate = getTrace(conn); + assertWithMessage(Optional + .ofNullable(traceUpdate) + .map(tu -> tu.stream().map(r -> String.join(", ", r)).collect(Collectors.joining("\n"))) + .orElse("show trace result is null")) + .that(traceUpdate) + .hasSize(rowCount); + } + public void setSqlMode(String mode, Connection conn) { String sql = "SET session sql_mode = '" + mode + "'"; JdbcUtil.updateDataTddl(conn, sql, null); @@ -844,6 +901,24 @@ public static int getNodeNum(Connection conn) { return count; } + public List showTopology(Connection conn, String tbName) { + List phyTables = new ArrayList<>(); + String sql = "show topology " + tbName; + + ResultSet rs = JdbcUtil.executeQuerySuccess(conn, sql); + try { + while (rs.next()) { + String table = rs.getString("TABLE_NAME"); + phyTables.add(table); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + JdbcUtil.close(rs); + } + return phyTables; + } + public static void assertBroadcastTableSame(String tableName, Connection tddlConnection, Connection mysqlConnection) { ResultSet resultSet = diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ClassHelper.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ClassHelper.java index f7d8e6d82..7c0580d91 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ClassHelper.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ClassHelper.java @@ -17,6 +17,7 @@ package com.alibaba.polardbx.qatest; import com.alibaba.polardbx.common.utils.ClassFinder; +import com.alibaba.polardbx.qatest.ddl.auto.columnar.CreateCciTest; import com.google.common.collect.ImmutableList; import java.lang.reflect.Modifier; @@ -63,8 +64,11 @@ public static ImmutableList getColumnarTestCases() { synchronized (ClassHelper.class) { if (columnarTestCases == null) { columnarTestCases = ImmutableList.builder().addAll(fileStorageTestCases.stream() - .filter(klass -> klass.getAnnotation(TestFileStorage.class) == null).collect( - Collectors.toList())).addAll(getColumnarDqlCase()).build(); + .filter(klass -> klass.getAnnotation(TestFileStorage.class) == null) + .collect(Collectors.toList())) + .addAll(getColumnarDqlCase()) + .add(CreateCciTest.class) + .build(); } } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/DDLBaseNewDBTestCase.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/DDLBaseNewDBTestCase.java index 88ee80eff..06294b61d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/DDLBaseNewDBTestCase.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/DDLBaseNewDBTestCase.java @@ -33,6 +33,7 @@ import com.alibaba.polardbx.executor.gsi.GsiUtils; import com.alibaba.polardbx.executor.utils.failpoint.FailPointKey; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableStatus; import com.alibaba.polardbx.gms.metadb.table.IndexStatus; @@ -69,6 +70,8 @@ import org.apache.calcite.util.Litmus; import org.apache.calcite.util.Pair; import org.apache.commons.lang.StringUtils; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.junit.Assert; @@ -100,7 +103,9 @@ import java.util.function.Consumer; import java.util.stream.Collectors; +import static com.alibaba.polardbx.qatest.validator.DataOperator.executeOnMysqlAndTddl; import static com.alibaba.polardbx.qatest.validator.DataValidator.resultSetContentSameAssert; +import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentSameAssert; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -256,12 +261,25 @@ protected Connection createTddlDb(String db) { try { while (!dbName.equalsIgnoreCase(db) && retryCount > 0) { retryCount--; - if (!usingNewPartDb()) { - JdbcUtil.createDatabase(connection, db, DB_HINT); - } else { - JdbcUtil.createPartDatabase(connection, db); + try { + if (!usingNewPartDb()) { + JdbcUtil.createDatabase(connection, db, DB_HINT); + } else { + JdbcUtil.createPartDatabase(connection, db); + } + dbName = connection.getSchema(); + } catch (Throwable ex) { + if (ex.getMessage().toLowerCase().contains("not finished dropping")) { + try { + JdbcUtil.dropDatabase(connection, db); + } catch (Throwable e2) { + logger.warn(e2.getMessage()); + } + + } else { + throw ex; + } } - dbName = connection.getSchema(); } } catch (Exception e) { logger.error(e.getMessage()); @@ -839,6 +857,22 @@ public int getDataNumFromTable(Connection conn, String tableName) { return cnt; } + public List getAllDataNumFromTable(Connection conn, String tableName, String columnTobeSelect) { + String sql = String.format("select %s from %s order by %s asc", columnTobeSelect, tableName, columnTobeSelect); + List nums = new ArrayList<>(); + ResultSet rs = JdbcUtil.executeQuerySuccess(conn, sql); + try { + while (rs.next()) { + nums.add(rs.getInt(1)); + } + } catch (SQLException e) { + logger.error(e.getMessage(), e); + } finally { + JdbcUtil.close(rs); + } + return nums; + } + // drop 某个分库中得某个表,主要用于异常测试 public void dropOneDbInMysql(List physicalConnectionList, String tableName, int index) { String sql = "drop table if exists " + tableName; @@ -2356,6 +2390,28 @@ protected List queryDdlRecordByDdlSql(String schemaName, String ta return result; } + @NotNull + protected List queryDdlRecordByDdlSql(String schemaName, String ddlSql) + throws SQLException { + final List result = new ArrayList<>(); + + final String sql = String.format( + "select * from __cdc__.%s where schema_name = ? and ddl_sql like ?", + CdcTableUtil.CDC_DDL_RECORD_TABLE); + try (PreparedStatement ps = tddlConnection.prepareStatement(sql)) { + ps.setString(1, schemaName); + ps.setString(2, "%" + ddlSql + "%"); + + final ResultSet resultSet = ps.executeQuery(); + + while (resultSet.next()) { + result.add(CdcDdlRecord.fill(resultSet)); + } + } + + return result; + } + protected List queryLatestColumnarTableEvolutionRecordByDdlJobId(Long ddlJobId) throws SQLException { final List result; @@ -2392,6 +2448,21 @@ protected List queryColumnarTableMappingRecordByTabl return result; } + protected List queryDropColumnarTableMappingRecordByIndexName(String schemaName, + String tableName, + String indexName) + throws SQLException { + final List result; + try (final Connection metaConn = getMetaConnection()) { + final ColumnarTableMappingAccessor accessor = new ColumnarTableMappingAccessor(); + accessor.setConnection(metaConn); + result = accessor.queryBySchemaTableIndexLike(schemaName, tableName, indexName + "%", + ColumnarTableStatus.DROP.name()); + } + + return result; + } + protected void checkLatestColumnarSchemaEvolutionRecord(Long ddlJobId, String schemaName, String tableName, @@ -2451,6 +2522,29 @@ protected void checkLatestColumnarSchemaEvolutionRecordByDdlSql(String sqlDdl, .isEqualTo(columnarTableEvolutionRecords.get(0).versionId); } + protected void checkLatestColumnarMappingRecordByDropDbSql(String sqlDdl, + String schemaName, + String tableName, + String indexName, + DdlType ddlType, + ColumnarTableStatus cciTableStatus) + throws SQLException { + final List cdcDdlRecords = queryDdlRecordByDdlSql(schemaName, sqlDdl); + Truth + .assertWithMessage("No ddl record found for sql: %s ", sqlDdl) + .that(cdcDdlRecords) + .hasSize(1); + + final List columnarTableMappingRecords = + queryDropColumnarTableMappingRecordByIndexName(schemaName, tableName, indexName); + Truth.assertThat(columnarTableMappingRecords).hasSize(1); + Truth.assertThat(columnarTableMappingRecords.get(0).tableSchema).isEqualTo(schemaName); + Truth.assertThat(columnarTableMappingRecords.get(0).tableName).isEqualTo(tableName); + Truth.assertThat(columnarTableMappingRecords.get(0).indexName).startsWith(indexName); + Truth.assertThat(columnarTableMappingRecords.get(0).status).isEqualTo(cciTableStatus.name()); + Truth.assertThat(columnarTableMappingRecords.get(0).latestVersionId).isGreaterThan(-1); + } + protected void checkColumnarSchemaEvolutionRecordByDdlSql(String sqlDdl, String schemaName, String tableName, @@ -2656,4 +2750,138 @@ protected void executeDdlAndCheckCdcRecord(String sqlDdl, String expectedDdlSql, final DDLExtInfo ddlExtInfo = JSONObject.parseObject(ddlRecords.get(0).ext, DDLExtInfo.class); ddlExtInfoConsumer.accept(ddlExtInfo); } + + protected void checkTraceRowCount(int rowCount) { + checkTraceRowCount(rowCount, tddlConnection); + } + + protected List> checkTraceRowCountIs(int expectedTraceCount) { + return checkTraceRowCount(Matchers.is(expectedTraceCount)); + } + + protected List> checkTraceRowCount(Matcher matcher) { + final List> trace = getTrace(tddlConnection); + + Assert.assertThat("Unexpected trace count: \n" + Optional + .ofNullable(trace) + .map(tu -> tu.stream().map(r -> String.join(", ", r)).collect(Collectors.joining("\n"))) + .orElse("show trace result is null"), trace.size(), matcher); + + return trace; + } + + protected static @NotNull String buildSqlCheckData(List columnNames, String tableName) { + return "select " + String.join(",", columnNames) + " from " + tableName; + } + + protected void executeOnceThenCheckDataAndTraceResultAndRouteCorrectness(String hint, + String insert, + List columnNames, + String tableName, + Matcher traceCountMatcher) + throws SQLException { + final List> mysqlResult = executeOnceThenCheckDataAndTraceResult(hint, + insert, + buildSqlCheckData(columnNames, tableName), + traceCountMatcher); + + JdbcUtil.assertRouteCorrectness(hint, + tableName, + mysqlResult, + columnNames, + ImmutableList.of("c1"), + tddlConnection); + } + + protected @NotNull List> executeOnceThenCheckDataAndTraceResult(String hint, + String insert, + String sqlCheckData, + Matcher traceCountMatcher) { + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, true); + checkTraceRowCount(traceCountMatcher); + + return selectContentSameAssert(sqlCheckData, null, mysqlConnection, tddlConnection); + } + + protected void executeTwiceThenCheckDataAndTraceResult(String hint, + String insert, + String sqlCheckData, + Matcher traceCountMatcher) { + executeTwiceThenCheckDataAndTraceResult(hint, insert, sqlCheckData, false, traceCountMatcher); + } + + protected void executeTwiceThenCheckDataAndTraceResult(String hint, + String insert, + String sqlCheckData, + boolean compareAffectedRows, + Matcher traceCountMatcher) { + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); + + selectContentSameAssert(sqlCheckData, null, mysqlConnection, tddlConnection); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, + compareAffectedRows); + checkTraceRowCount(traceCountMatcher); + + selectContentSameAssert(sqlCheckData, null, mysqlConnection, tddlConnection); + } + + protected void executeTwiceThenCheckGsiDataAndTraceResult(String hint, + String insert, + String tableName, + String gsiName, + int traceCount) throws SQLException { + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); + + checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + + selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, true); + checkTraceRowCountIs(traceCount); + + selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + + checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + } + + protected void executeThriceThenCheckDataAndTraceResult(String hint, + String insert, + String sqlCheckData, + boolean compareAffectedRows, + Matcher traceCountMatcher) { + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); + + selectContentSameAssert(sqlCheckData, null, mysqlConnection, tddlConnection); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, + compareAffectedRows); + checkTraceRowCount(traceCountMatcher); + + selectContentSameAssert(sqlCheckData, null, mysqlConnection, tddlConnection); + } + + protected void executeThriceThenCheckGsiDataAndTraceResult(String hint, + String insert, + String tableName, + String gsiName, + boolean compareAffectedRows, + int traceCount) throws SQLException { + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); + + selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + + checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, + compareAffectedRows); + checkTraceRowCountIs(traceCount); + + selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + + checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/ColumnarPlancacheTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/ColumnarPlancacheTest.java new file mode 100644 index 000000000..6ba0d771c --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/ColumnarPlancacheTest.java @@ -0,0 +1,106 @@ +package com.alibaba.polardbx.qatest.NotThreadSafe; + +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.alibaba.polardbx.qatest.validator.DataValidator; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.SQLException; + +public class ColumnarPlancacheTest extends DDLBaseNewDBTestCase { + private static String TABLE_DEFINITION_FORMAT = "CREATE TABLE `%s` (\n" + + "\t`id` bigint(20) NOT NULL AUTO_INCREMENT,\n" + + "\t`a` int(32) UNSIGNED DEFAULT NULL,\n" + + "\t`b` int(32) UNSIGNED DEFAULT NULL,\n" + + "\t`c` int(32) UNSIGNED DEFAULT NULL,\n" + + "\tprimary key(id)\n" + + ") partition by key(id) partitions 8"; + + private static String CREATE_COL_IDX = SKIP_WAIT_CCI_CREATION_HINT + + "create clustered columnar index `%s` on %s(`%s`) partition by hash(`%s`) partitions 4"; + + private static String PUB_COL_IDX = + "/*+TDDL:CMD_EXTRA(ALTER_CCI_STATUS=true, ALTER_CCI_STATUS_BEFORE=CREATING, ALTER_CCI_STATUS_AFTER=PUBLIC)*/" + + "ALTER TABLE `%s` alter index `%s` VISIBLE;"; + + String tb1 = "tb1"; + + String colIdxA = "colIdx_a"; + + String colA = "a"; + + String EMPTY_HINT = "/*+TDDL:cmd_extra()*/"; + String ENABLE_COL_CACHE = "set global " + ConnectionProperties.ENABLE_COLUMNAR_PLAN_CACHE + " = true"; + String DISABLE_COL_CACHE = "set global " + ConnectionProperties.ENABLE_COLUMNAR_PLAN_CACHE + " = false"; + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Before + public void prepareTable() { + JdbcUtil.dropTable(getTddlConnection1(), tb1); + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(TABLE_DEFINITION_FORMAT, tb1)); + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(CREATE_COL_IDX, colIdxA, tb1, colA, colA)); + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(PUB_COL_IDX, tb1, colIdxA)); + } + + @After + public void afterDDLBaseNewDBTestCase() { + //cleanDataBase(); + } + + @Test + public void testExplain() throws SQLException, InterruptedException { + String sql1 = String.format("explain select id from %s where id < 1000+10", tb1); + String sql2 = String.format("explain select id from %s where id > 1000+10", tb1); + try (Connection conn1 = getPolardbxConnection(); + Connection conn2 = getPolardbxConnection()) { + JdbcUtil.executeQuery("set WORKLOAD_TYPE=AP", conn1); + JdbcUtil.executeQuery("set ENABLE_COLUMNAR_OPTIMIZER=true", conn1); + JdbcUtil.executeQuery("set ENABLE_COLUMNAR_OPTIMIZER=false", conn2); + + JdbcUtil.executeQuery(DISABLE_COL_CACHE, conn1); + Thread.sleep(3000L); + String explain = DataValidator.getExplainAllResult(sql1, null, conn1); + Assert.assertTrue(explain.contains("(`id` < 1010") && explain.contains("HitCache:false")); + explain = DataValidator.getExplainAllResult(sql1, null, conn1); + Assert.assertTrue(explain.contains("(`id` < 1010") && explain.contains("HitCache:false")); + explain = DataValidator.getExplainAllResult(sql2, null, conn2); + Assert.assertTrue(explain.contains("(`id` > (? + ?)") && explain.contains("HitCache:false")); + explain = DataValidator.getExplainAllResult(sql2, null, conn2); + Assert.assertTrue(explain.contains("(`id` > (? + ?)") && explain.contains("HitCache:true")); + + JdbcUtil.executeQuery(ENABLE_COL_CACHE, conn1); + Thread.sleep(3000L); + explain = DataValidator.getExplainAllResult(sql1, null, conn1); + Assert.assertTrue(explain.contains("(`id` < (? + ?)") && explain.contains("HitCache:false")); + explain = DataValidator.getExplainAllResult(sql1, null, conn1); + Assert.assertTrue(explain.contains("(`id` < (? + ?)") && explain.contains("HitCache:true")); + explain = DataValidator.getExplainAllResult(EMPTY_HINT + sql1, null, conn1); + Assert.assertTrue(explain.contains("(`id` < 1010") && explain.contains("HitCache:false")); + explain = DataValidator.getExplainAllResult(sql2, null, conn2); + Assert.assertTrue(explain.contains("(`id` > (? + ?)") && explain.contains("HitCache:true")); + + JdbcUtil.executeQuery(DISABLE_COL_CACHE, conn1); + Thread.sleep(3000L); + explain = DataValidator.getExplainAllResult(sql1, null, conn1); + Assert.assertTrue(explain.contains("(`id` < 1010") && explain.contains("HitCache:false")); + explain = DataValidator.getExplainAllResult(sql1, null, conn1); + Assert.assertTrue(explain.contains("(`id` < 1010") && explain.contains("HitCache:false")); + + explain = DataValidator.getExplainAllResult(sql2, null, conn2); + Assert.assertTrue(explain.contains("(`id` > (? + ?)") && explain.contains("HitCache:true")); + + } finally { + JdbcUtil.executeQuery(DISABLE_COL_CACHE, getTddlConnection1()); + } + + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/DeadlockAutoTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/DeadlockAutoTest.java index 0416b9f24..43e578e9a 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/DeadlockAutoTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/DeadlockAutoTest.java @@ -1,9 +1,7 @@ package com.alibaba.polardbx.qatest.NotThreadSafe; import com.alibaba.polardbx.common.utils.thread.NamedThreadFactory; -import com.alibaba.polardbx.qatest.CdcIgnore; import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; -import com.alibaba.polardbx.qatest.NotThreadSafe.DeadlockTest; import com.alibaba.polardbx.qatest.util.JdbcUtil; import net.jcip.annotations.NotThreadSafe; import org.apache.commons.lang.StringUtils; @@ -35,6 +33,7 @@ public boolean usingNewPartDb() { @Before public void before() { JdbcUtil.executeSuccess(tddlConnection, "set global ENABLE_DEADLOCK_DETECTION_80 = true"); + JdbcUtil.executeSuccess(tddlConnection, "set global MAX_KEEP_DEADLOCK_LOGS = 10000"); } @Test(timeout = 60000) @@ -58,9 +57,11 @@ private void testFramework(String tableName, boolean single) throws SQLException connections.add(getPolardbxConnection()); } try { + long before = queryInfoSchemaDeadlocks(); createTable(tableName, single); innerTest(tableName, connections); testShowDeadlocks(tableName, single); + ensureMoreDeadlocks(before); } finally { clear(connections, tableName); } @@ -178,7 +179,7 @@ private void createTable(String tableName, boolean single) { JdbcUtil.executeUpdateSuccess(tddlConnection, sql); // Create a partition table - sql = "create table " + tableName + " (id int primary key)" + (single ? "" : + sql = "create table " + tableName + " (id int primary key)" + (single ? " single " : " partition by hash(id) partitions 3"); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); } @@ -209,4 +210,26 @@ private void testShowDeadlocks(String tableName, boolean single) throws SQLExcep } Assert.assertTrue(flag); } + + public long queryInfoSchemaDeadlocks() throws SQLException { + final String sql = "SELECT count(0) FROM information_schema.deadlocks"; + final ResultSet rs2 = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + if (rs2.next()) { + return rs2.getLong(1); + } + return 0; + } + + private void ensureMoreDeadlocks(long before) throws SQLException { + int retry = 0; + while (queryInfoSchemaDeadlocks() - before < 1 && retry++ < 10) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + Assert.assertTrue("Not found more records in info_schema.deadlocks", retry < 10); + } + } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/FlashbackAreaTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/FlashbackAreaTest.java new file mode 100644 index 000000000..4e0139e93 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/FlashbackAreaTest.java @@ -0,0 +1,138 @@ +package com.alibaba.polardbx.qatest.NotThreadSafe; + +import com.alibaba.polardbx.qatest.CrudBasedLockTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runners.Parameterized; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class FlashbackAreaTest extends CrudBasedLockTestCase { + private final String isolation; + + @Override + public boolean usingNewPartDb() { + return true; + } + + @After + public void after() { + JdbcUtil.executeUpdateSuccess(tddlConnection, "rollback"); + } + + @Parameterized.Parameters(name = "isolation:{0}") + public static List prepare() { + return new ArrayList() { + { + add(new Object[] {"READ-COMMITTED"}); + add(new Object[] {"REPEATABLE-READ"}); + } + }; + } + + public FlashbackAreaTest(String isolation) { + this.isolation = isolation; + } + + @Test + public void testSimpleCase() throws SQLException { + if (!isMySQL80()) { + return; + } + JdbcUtil.executeUpdateSuccess(tddlConnection, "set TRANSACTION_ISOLATION = '" + isolation + "'"); + String tableName = "FlashbackAreaTest_tb"; + JdbcUtil.executeUpdateSuccess(tddlConnection, "drop table if exists " + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "set global opt_flashback_area = true"); + JdbcUtil.executeUpdateSuccess(tddlConnection, "set global innodb_txn_retention = 259200"); + String createTableSql = "create table if not exists " + tableName + " (\n" + + " id int primary key,\n" + + " a int,\n" + + " local index idx(a)\n" + + ") partition by key(id)"; + long beforeCreateTableTso = getTso(); + JdbcUtil.executeUpdateSuccess(tddlConnection, createTableSql); + JdbcUtil.executeUpdateSuccess(tddlConnection, "begin"); + JdbcUtil.executeUpdateSuccess(tddlConnection, "insert into " + tableName + " values(1,1)"); + JdbcUtil.executeUpdateSuccess(tddlConnection, "commit"); + long beforeInsert100TableTso = getTso(); + JdbcUtil.executeUpdateSuccess(tddlConnection, "begin"); + JdbcUtil.executeUpdateSuccess(tddlConnection, "insert into " + tableName + " values(100,100)"); + JdbcUtil.executeUpdateSuccess(tddlConnection, "commit"); + long beforeUpdate100TableTso = getTso(); + JdbcUtil.executeUpdateSuccess(tddlConnection, "begin"); + JdbcUtil.executeUpdateSuccess(tddlConnection, "update " + tableName + " set a = 200 where id = 100"); + JdbcUtil.executeUpdateSuccess(tddlConnection, "commit"); + long afterTso = getTso(); + + ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, + "select * from " + tableName + " as of tso " + beforeCreateTableTso); + Assert.assertFalse(rs.next()); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, + "select count(0) from " + tableName + " as of tso " + beforeInsert100TableTso); + Assert.assertTrue(rs.next()); + Assert.assertEquals(1, rs.getInt(1)); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, + "select * from " + tableName + " as of tso " + beforeUpdate100TableTso + " order by id"); + Assert.assertTrue(rs.next()); + Assert.assertEquals(1, rs.getInt("id")); + Assert.assertEquals(1, rs.getInt("a")); + Assert.assertTrue(rs.next()); + Assert.assertEquals(100, rs.getInt("id")); + Assert.assertEquals(100, rs.getInt("a")); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, + "select * from " + tableName + " as of tso " + afterTso + " order by id"); + Assert.assertTrue(rs.next()); + Assert.assertEquals(1, rs.getInt("id")); + Assert.assertEquals(1, rs.getInt("a")); + Assert.assertTrue(rs.next()); + Assert.assertEquals(100, rs.getInt("id")); + Assert.assertEquals(200, rs.getInt("a")); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, + "select * from " + tableName + " order by id"); + Assert.assertTrue(rs.next()); + Assert.assertEquals(1, rs.getInt("id")); + Assert.assertEquals(1, rs.getInt("a")); + Assert.assertTrue(rs.next()); + Assert.assertEquals(100, rs.getInt("id")); + Assert.assertEquals(200, rs.getInt("a")); + + JdbcUtil.executeUpdateSuccess(tddlConnection, "drop table if exists " + tableName); + } + + @Test + public void testSpm() throws SQLException { + if (!isMySQL80()) { + return; + } + String tableName = "FlashbackAreaTest_testSpm"; + JdbcUtil.executeUpdateSuccess(tddlConnection, "drop table if exists " + tableName); + String createTableSql = "create table if not exists " + tableName + " (\n" + + " id int primary key,\n" + + " a int,\n" + + " local index idx(a)\n" + + ") partition by key(id)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, createTableSql); + String sql = "insert into " + tableName + " values (0,0), (1,1)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + long tso = getTso(); + sql = + "select * from " + tableName + " as t1 as of tso " + tso + " join " + tableName + " as t2 as of tso " + tso + + " on t1.id=t2.id"; + JdbcUtil.executeQuerySuccess(tddlConnection, sql); + } + + private long getTso() throws SQLException { + ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, "select tso_timestamp()"); + Assert.assertTrue(rs.next()); + return rs.getLong(1); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/FwSessionHintTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/FwSessionHintTest.java deleted file mode 100644 index 690726fc4..000000000 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/FwSessionHintTest.java +++ /dev/null @@ -1,1017 +0,0 @@ -package com.alibaba.polardbx.qatest.NotThreadSafe; - -import com.alibaba.polardbx.common.utils.Assert; -import com.alibaba.polardbx.qatest.BaseTestCase; -import com.alibaba.polardbx.qatest.CdcIgnore; -import com.alibaba.polardbx.qatest.validator.DataOperator; -import com.alibaba.polardbx.qatest.validator.DataValidator; -import com.google.common.collect.Maps; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Ignore; -import org.junit.Test; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.Map; -import java.util.Objects; -import java.util.Random; - -/** - * Partition Hint test cases - * - * @author fangwu - */ -@CdcIgnore(ignoreReason = "session hints 暂时无法通过binlog透传给下游,该用例会触发下游报错,优先级不高,先忽略") -public class FwSessionHintTest extends BaseTestCase { - private static final Log log = LogFactory.getLog("ROOT"); - private static final String TBL_NAME = "session_hint_test"; - private static final String CREATE_TBL = "CREATE TABLE if not exists `session_hint_test` (\n" - + " `pk` bigint(11) NOT NULL,\n" - + " `integer_test` int(11) DEFAULT NULL,\n" - + " PRIMARY KEY (`pk`)\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8"; - - /** - * test if push hint working - * set partition_hint=xxx; - * trace select * from xxx; - * show trace && check if partition_hint work - */ - @Test - public void testSessionHintWithShardingTable() throws SQLException { - Connection c = null; - try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint=DRDS_POLARX1_QATEST_APP_000001_GROUP"); - c.createStatement().execute("trace select * from select_base_three_multi_db_one_tb"); - ResultSet rs = c.createStatement().executeQuery("show trace"); - - while (rs.next()) { - String groupName = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupName.equalsIgnoreCase("DRDS_POLARX1_QATEST_APP_000001_GROUP")); - } - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - log.info("session hint test end"); - } - } - - /** - * test if push hint working - * set partition_hint=xxx; - * trace select * from xxx; - * show trace && check if partition_hint work - */ - @Test - public void testSessionHintWithAutoTable() throws SQLException { - Connection c = null; - try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_part_qatest_app"); - - String tableName = "select_base_three_multi_db_multi_tb"; - ResultSet topologyRs = - c.createStatement().executeQuery("show topology from " + tableName); - Map partGroupMap = Maps.newHashMap(); - while (topologyRs.next()) { - String groupName = topologyRs.getString("GROUP_NAME"); - String partName = topologyRs.getString("partition_name"); - partGroupMap.put(partName, groupName); - } - - topologyRs.close(); - for (Map.Entry entry : partGroupMap.entrySet()) { - String partName = entry.getKey(); - String checkGroupName = entry.getValue(); - checkHintWork(c, TBL_NAME); - c.createStatement().execute("set partition_hint=" + partName); - ResultSet rs; - String joinSql = - "trace select * from " + tableName + " a join select_base_two_multi_db_multi_tb b on a.pk=b.pk"; - c.createStatement().executeQuery(joinSql); - rs = c.createStatement().executeQuery("show trace"); - - while (rs.next()) { - String groupName = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupName.equalsIgnoreCase(checkGroupName)); - } - } - - // broadcast table - try { - String sqlWithBroadcast = - "trace select * from select_base_two_multi_db_one_tb a join select_base_four_broadcast b on a.pk=b.pk;"; - c.createStatement().execute("set partition_hint=p3"); - c.createStatement().executeQuery(sqlWithBroadcast); - } catch (SQLException sqlException) { - sqlException.printStackTrace(); - log.info(sqlException.getMessage()); - Assert.fail( - "partition hint should ignore broadcast table partition and replace its physical table name"); - } - - // partition hint won't infect broadcast table - try { - String sqlWithBroadcast = "trace select * from select_base_four_broadcast b"; - c.createStatement().execute("set partition_hint=p3333"); - c.createStatement().executeQuery(sqlWithBroadcast); - ResultSet rs = c.createStatement().executeQuery("show trace"); - String groupName; - while (rs.next()) { - groupName = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupName.equalsIgnoreCase("DRDS_POLARX1_PART_QATEST_APP_P00000_GROUP")); - } - rs.close(); - } catch (SQLException sqlException) { - sqlException.printStackTrace(); - log.info(sqlException.getMessage()); - Assert.fail( - "partition hint should ignore broadcast table partition and replace its physical table name"); - } - - try { - String errorSql = - "trace select * from select_base_two_multi_db_one_tb a"; - c.createStatement().execute("set partition_hint=p1111"); - c.createStatement().executeQuery(errorSql); - Assert.fail(" error sql should product error msg"); - } catch (SQLException sqlException) { - sqlException.printStackTrace(); - log.info(sqlException.getMessage()); - Assert.assertTrue( - sqlException.getMessage().contains("Unsupported to use direct HINT ")); - } - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - log.info("session hint test end"); - } - } - - /** - * non-table statement like SELECT @@session.transaction_read_only - */ - @Test - public void testSessionHintWithNonTableStmt() throws SQLException { - Connection c = null; - try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_part_qatest_app"); - c.createStatement().execute("set partition_hint=p3"); - c.createStatement().execute("SELECT @@session.transaction_read_only"); - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(c).close(); - } - } - - @Test - public void testSessionHintWithTrans() throws SQLException { - Connection c1 = null; - Connection c2 = null; - Connection c3 = null; - ResultSet rs; - try { - c1 = getPolardbxConnection(); - c2 = getPolardbxConnection(); - c3 = getPolardbxConnection(); - c1.createStatement().execute("use drds_polarx1_part_qatest_app"); - c2.createStatement().execute("use drds_polarx1_part_qatest_app"); - c3.createStatement().execute("use drds_polarx1_part_qatest_app"); - - String tableName = "update_delete_base_date_one_multi_db_one_tb"; - // c1 using hint, truncate data - c1.createStatement().execute("truncate table " + tableName); - - // c2 begin and check no data - c2.setAutoCommit(false); - rs = c2.createStatement().executeQuery("select * from " + tableName); - Assert.assertTrue(!rs.next()); - rs.close(); - - // c3 check no data - rs = c3.createStatement().executeQuery("select * from " + tableName); - Assert.assertTrue(!rs.next()); - rs.close(); - - // c1 begin and insert - c1.setAutoCommit(false); - c1.createStatement().execute("insert into " + tableName - + " values(1,1,'a','a',null,1,1,1,1,1,1,1,1,1,now(), now(),now(),now(),now(),'a')"); - - // c2 check no data - rs = c2.createStatement().executeQuery("select * from " + tableName); - Assert.assertTrue(!rs.next()); - rs.close(); - - // c3 check no data - rs = c3.createStatement().executeQuery("select * from " + tableName); - Assert.assertTrue(!rs.next()); - rs.close(); - - // c1 commit - c1.commit(); - - // c3 check data - rs = c3.createStatement().executeQuery("select * from " + tableName); - Assert.assertTrue(rs.next()); - rs.close(); - - // c2 check no data - rs = c2.createStatement().executeQuery("select * from " + tableName); - Assert.assertTrue(!rs.next()); - rs.close(); - - } finally { - Objects.requireNonNull(c1).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(c1).close(); - Objects.requireNonNull(c2).close(); - Objects.requireNonNull(c3).close(); - log.info("session hint test end"); - } - } - - @Test - public void testSessionHintWithDdl() throws SQLException { - Connection connWithHint = null; - Connection connWithoutHint = null; - Random r = new Random(); - String tblName = "session_hint_ddl_test_tb_" + r.nextInt(10000); - try { - connWithoutHint = getPolardbxConnection(); - connWithoutHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - connWithHint = getPolardbxConnection(); - connWithHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - - connWithHint.createStatement().execute("set partition_hint=p3"); - - // test hint working - checkHintWork(connWithHint, "select_base_three_multi_db_one_tb"); - - // test create logical table - connWithHint.createStatement().execute("CREATE TABLE " + tblName + " (\n" - + "\t`id` bigint(20) NOT NULL,\n" - + "\t`ubigint_id` bigint(20) UNSIGNED DEFAULT NULL\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8"); - - // get partition name and group name - ResultSet rs = connWithHint.createStatement().executeQuery("show topology from " + tblName); - rs.next(); - String groupName = rs.getString("GROUP_NAME"); - String partitionName = rs.getString("PARTITION_NAME"); - - Assert.assertTrue(StringUtils.isNotEmpty(partitionName) && StringUtils.isNotEmpty(groupName)); - rs.close(); - - // check session hint working for new table - connWithHint.createStatement().execute("set partition_hint= " + partitionName); - connWithHint.createStatement().execute("trace select * from " + tblName); - rs = connWithHint.createStatement().executeQuery("show trace"); - while (rs.next()) { - String groupNameTmp = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupNameTmp.equalsIgnoreCase(groupName)); - } - rs.close(); - } finally { - Objects.requireNonNull(connWithHint).createStatement().execute("drop table if exists " + tblName); - Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(connWithHint).close(); - Objects.requireNonNull(connWithoutHint).close(); - log.info("session hint test end"); - } - } - - @Test - public void testSessionHintWithInformationSchema() throws SQLException { - Connection connWithHint = null; - Connection connWithoutHint = null; - try { - connWithoutHint = getPolardbxConnection(); - connWithoutHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - connWithHint = getPolardbxConnection(); - connWithHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - - connWithHint.createStatement().execute("set partition_hint=p3"); - - checkHintWork(connWithHint, TBL_NAME); - - // test normal hint won't interrupt partition hint - DataValidator.selectContentSameAssert("explain select * from information_schema.views", null, connWithHint, - connWithoutHint, true); - DataValidator.selectContentSameAssert("explain select * from information_schema.tables", null, connWithHint, - connWithoutHint); - DataValidator.selectContentSameAssert( - "explain select MODULE_NAME, host, schedule_jobs, views from information_schema.module", null, - connWithHint, - connWithoutHint); - DataValidator.selectContentSameAssert("explain select * from information_schema.column_statistics", null, - connWithHint, connWithoutHint); - - } finally { - Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(connWithHint).close(); - Objects.requireNonNull(connWithoutHint).close(); - log.info("session hint test end"); - } - } - - private void checkHintWork(Connection conn, String tblName) throws SQLException { - // prepare table - conn.createStatement().execute(CREATE_TBL); - - // get group name and partition name - ResultSet rs = conn.createStatement().executeQuery("show topology from " + tblName); - - String groupName = null; - String partitionName = null; - while (rs.next()) { - groupName = rs.getString("GROUP_NAME"); - partitionName = rs.getString("PARTITION_NAME"); - break; - } - rs.close(); - Assert.assertTrue(groupName != null && partitionName != null); - - // test partition hint working - conn.createStatement().execute("set partition_hint=" + partitionName); - conn.createStatement().execute("trace select * from " + tblName); - rs = conn.createStatement().executeQuery("show trace"); - - while (rs.next()) { - String groupNameTmp = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupNameTmp.equalsIgnoreCase(groupName)); - } - rs.close(); - conn.createStatement().execute("set partition_hint=''"); - } - - @Test - public void testSessionHintWithShowCommandAndDal() throws SQLException { - Connection connWithHint = null; - Connection connWithoutHint = null; - try { - connWithoutHint = getPolardbxConnection(); - connWithoutHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - connWithHint = getPolardbxConnection(); - connWithHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - - connWithHint.createStatement().execute("set partition_hint=p3"); - - // test hint working - checkHintWork(connWithHint, TBL_NAME); - - // test show command - connWithHint.createStatement().executeQuery("show tables"); - connWithHint.createStatement().executeQuery("show full tables"); - connWithHint.createStatement().executeQuery("show ddl"); - connWithHint.createStatement().executeQuery("show full ddl"); - connWithHint.createStatement().executeQuery("show ddl status"); - connWithHint.createStatement().executeQuery("show ddl result"); - connWithHint.createStatement().executeQuery("show rule from select_base_three_multi_db_multi_tb"); - connWithHint.createStatement().executeQuery("show full rule from select_base_three_multi_db_multi_tb"); - connWithHint.createStatement().executeQuery("show topology from select_base_three_multi_db_multi_tb"); - connWithHint.createStatement().executeQuery("show partitions from select_base_three_multi_db_multi_tb"); - // show datasources cannot make sure POOLING_COUNT same - DataValidator.selectConutAssert("show datasources", null, connWithHint, connWithoutHint); - DataOperator.executeOnMysqlAndTddl(connWithHint, connWithoutHint, "clear slow", null); - - // explain advisor/json_plan might cause different result in different cn node - connWithHint.createStatement().executeQuery( - "explain advisor select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); - connWithHint.createStatement().execute("analyze table select_base_three_multi_db_multi_tb"); - connWithHint.createStatement().executeQuery( - "explain STATISTICS select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); - connWithHint.createStatement().executeQuery( - "explain JSON_PLAN select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); - connWithoutHint.createStatement().executeQuery( - "explain JSON_PLAN select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); - - connWithHint.createStatement().executeQuery( - "explain EXECUTE select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); - connWithoutHint.createStatement().executeQuery( - "explain EXECUTE select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); - - connWithHint.createStatement().executeQuery( - "explain SHARDING select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); - connWithHint.createStatement().execute("create sequence session_hint_test_seq start with 100"); - connWithHint.createStatement().execute("alter sequence session_hint_test_seq start with 99"); - connWithHint.createStatement().execute("drop sequence session_hint_test_seq"); - - connWithHint.createStatement().execute("clear ccl_rules"); - connWithHint.createStatement().execute("clear ccl_triggers"); - - // thread running might be different - connWithHint.createStatement().executeQuery("show db status"); - connWithHint.createStatement().executeQuery("show full db status"); - - connWithHint.createStatement().executeQuery("show ds"); - connWithHint.createStatement().executeQuery("show trans"); - connWithHint.createStatement().executeQuery("show node"); - connWithHint.createStatement().executeQuery("show slow"); - connWithHint.createStatement().executeQuery("show full trans"); - connWithHint.createStatement().executeQuery("show ccl_rules"); - connWithHint.createStatement().executeQuery("show physical_slow"); - connWithHint.createStatement().executeQuery("show broadcasts"); - connWithHint.createStatement().executeQuery("show connection"); - connWithHint.createStatement().executeQuery("show rule"); - connWithHint.createStatement().executeQuery("check table select_base_four_multi_db_multi_tb"); - } finally { - Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(connWithHint).close(); - Objects.requireNonNull(connWithoutHint).close(); - log.info("session hint test end"); - } - } - - @Test - public void testSessionHintWithDirectHint() throws SQLException { - Connection connWithHint = null; - try { - connWithHint = getPolardbxConnection(); - connWithHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - - connWithHint.createStatement().execute("set partition_hint=p3"); - - // test partition hint working - checkHintWork(connWithHint, TBL_NAME); - ResultSet rs; - - // test normal hint won't interrupt partition hint - // get group name and partition name - rs = connWithHint.createStatement().executeQuery("show topology from " + TBL_NAME); - - String groupName = null; - String partitionName = null; - String tableName = null; - while (rs.next()) { - groupName = rs.getString("GROUP_NAME"); - partitionName = rs.getString("PARTITION_NAME"); - tableName = rs.getString("TABLE_NAME"); - break; - } - rs.close(); - Assert.assertTrue(groupName != null && partitionName != null); - - // test partition hint working - connWithHint.createStatement().execute("set partition_hint=" + partitionName); - - // test partition hint with non-direct hint - connWithHint.createStatement().execute("trace /*TDDL:slave()*/ select * from " + TBL_NAME); - - connWithHint.createStatement().execute("trace /*TDDL:a()*/ select * from " + TBL_NAME); - - connWithHint.createStatement() - .execute("trace /*TDDL:test_hint=true*/ select * from select_base_three_multi_db_one_tb"); - rs = connWithHint.createStatement().executeQuery("show trace"); - - while (rs.next()) { - String groupNameTmp = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupNameTmp.equalsIgnoreCase(groupName)); - } - rs.close(); - - // test node hint would interrupt partition hint - Assert.assertTrue(groupName != null); - Assert.assertTrue(tableName != null); - connWithHint.createStatement() - .execute("trace /*TDDL:node=" + groupName + "*/ select * from " + tableName); - - } finally { - Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(connWithHint).close(); - log.info("session hint test end"); - } - } - - /** - * test if push hint working on multi table - * set partition_hint=xxx; - * trace select * from xxx; - * show trace && check if partition_hint work - */ - @Test - public void testSessionHintWithShardingMultiTable() throws SQLException { - Connection c = null; - try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:00'"); - c.createStatement().execute("trace select * from select_base_three_multi_db_multi_tb"); - ResultSet rs = c.createStatement().executeQuery("show trace"); - - while (rs.next()) { - String groupName = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupName.equalsIgnoreCase("DRDS_POLARX1_QATEST_APP_000001_GROUP")); - } - - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:1'"); - c.createStatement().execute("trace select * from select_base_three_multi_db_multi_tb"); - rs = c.createStatement().executeQuery("show trace"); - - while (rs.next()) { - String groupName = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupName.equalsIgnoreCase("DRDS_POLARX1_QATEST_APP_000001_GROUP")); - } - - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:4'"); - try { - c.createStatement().execute("trace select * from select_base_three_multi_db_multi_tb"); - } catch (SQLException e) { - Assert.assertTrue(e.getMessage() - .contains("table index overflow in target group from direct HINT for sharding table")); - } - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - log.info("session hint test end"); - } - } - - @Test - public void testSessionHintWithJoin() throws SQLException { - // drds table with different sharding table num, report error - Connection c = null; - try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:00'"); - - try { - c.createStatement().execute( - "select * from select_base_three_multi_db_multi_tb a join select_base_three_multi_db_one_tb b on a.pk=b.pk"); - Assert.fail("should report error"); - } catch (SQLException e) { - Assert.assertTrue(e.getMessage() - .contains("different sharding table num in partition hint mode")); - } - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - log.info("session hint test end"); - } - - // auto table in different table group, report error - try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_part_qatest_app"); - c.createStatement().execute("set partition_hint='p1'"); - - // create table group - c.createStatement().execute("create tablegroup if not exists partition_hint_test_tg1"); - c.createStatement().execute("create tablegroup if not exists partition_hint_test_tg2"); - - // create table into table group partition_test_tg1 - c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_tbl1` (\n" - + " `a` datetime NOT NULL\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" - + "TABLEGROUP=partition_hint_test_tg1\n" - + "PARTITION BY RANGE(YEAR(a))\n" - + "(PARTITION p0 VALUES LESS THAN (1990) ENGINE = InnoDB,\n" - + " PARTITION p1 VALUES LESS THAN (2000) ENGINE = InnoDB,\n" - + " PARTITION p2 VALUES LESS THAN (2010) ENGINE = InnoDB,\n" - + " PARTITION p3 VALUES LESS THAN (2020) ENGINE = InnoDB);"); - - c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_tbl2` (\n" - + " `a` datetime NOT NULL\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" - + "TABLEGROUP=partition_hint_test_tg2\n" - + "PARTITION BY RANGE(YEAR(a))\n" - + "(PARTITION p0 VALUES LESS THAN (1990) ENGINE = InnoDB,\n" - + " PARTITION p1 VALUES LESS THAN (2000) ENGINE = InnoDB,\n" - + " PARTITION p2 VALUES LESS THAN (2010) ENGINE = InnoDB,\n" - + " PARTITION p3 VALUES LESS THAN (2020) ENGINE = InnoDB);"); - - // test different table group error report - try { - c.createStatement() - .execute("select * from partition_hint_test_tbl1 a join partition_hint_test_tbl2 b on a.a=b.a"); - Assert.fail("should report error"); - } catch (SQLException e) { - Assert.assertTrue(e.getMessage() - .contains("different table group in partition hint mode")); - } - - // change table group to same one:partition_hint_test_tbl1 - c.createStatement().execute("ALTER TABLE partition_hint_test_tbl2 set TABLEGROUP=partition_hint_test_tg1;"); - - // test if same table group work - c.createStatement() - .execute("select * from partition_hint_test_tbl1 a join partition_hint_test_tbl2 b on a.a=b.a"); - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(c).createStatement().execute("drop table if exists partition_hint_test_tbl1"); - Objects.requireNonNull(c).createStatement().execute("drop table if exists partition_hint_test_tbl2"); - Objects.requireNonNull(c).createStatement().execute("drop tablegroup if exists partition_hint_test_tg1"); - Objects.requireNonNull(c).createStatement().execute("drop tablegroup if exists partition_hint_test_tg2"); - log.info("session hint test end"); - } - - // test auto table join with broadcast table - try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_part_qatest_app"); - c.createStatement().execute("set partition_hint='p1'"); - - // create table group - c.createStatement().execute("create tablegroup if not exists partition_hint_test_tg1"); - - // create table into table group partition_test_tg1 - c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_tbl1` (\n" - + " `a` datetime NOT NULL\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" - + "TABLEGROUP=partition_hint_test_tg1\n" - + "PARTITION BY RANGE(YEAR(a))\n" - + "(PARTITION p0 VALUES LESS THAN (1990) ENGINE = InnoDB,\n" - + " PARTITION p1 VALUES LESS THAN (2000) ENGINE = InnoDB,\n" - + " PARTITION p2 VALUES LESS THAN (2010) ENGINE = InnoDB,\n" - + " PARTITION p3 VALUES LESS THAN (2020) ENGINE = InnoDB);"); - - c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_tbl2` (\n" - + " `a` datetime NOT NULL\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" - + "BROADCAST"); - - // test if table with broadcast table work - c.createStatement() - .execute("select * from partition_hint_test_tbl1 a join partition_hint_test_tbl2 b on a.a=b.a"); - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(c).createStatement().execute("drop table if exists partition_hint_test_tbl1"); - Objects.requireNonNull(c).createStatement().execute("drop table if exists partition_hint_test_tbl2"); - Objects.requireNonNull(c).createStatement().execute("drop tablegroup if exists partition_hint_test_tg1"); - log.info("session hint test end"); - } - } - - @Test - public void testSessionHintCrossSchema() throws SQLException { - Connection c = null; - try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:00'"); - - c.createStatement().execute("select * from drds_polarx1_qatest_app.select_base_three_multi_db_multi_tb"); - - try { - c.createStatement() - .execute("select * from drds_polarx1_part_qatest_app.select_base_three_multi_db_multi_tb"); - Assert.fail("should report error"); - } catch (SQLException e) { - log.info(e.getMessage()); - Assert.assertTrue( - e.getMessage().contains("partition hint visit table crossing schema")); - } - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - log.info("session hint test end"); - } - } - - /** - * partition hint with physical table name should cause table not exists error - * this condition should use direct node - */ - @Test - public void testSessionHintWithPhysicalTableName() throws SQLException { - Connection c = null; - - // drds table - try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:00'"); - - /* - * expected table topology - * | 0 | DRDS_POLARX1_QATEST_APP_000000_GROUP | select_base_three_multi_db_multi_tb_i9JV_00 | - | - * | 1 | DRDS_POLARX1_QATEST_APP_000000_GROUP | select_base_three_multi_db_multi_tb_i9JV_01 | - | - * | 2 | DRDS_POLARX1_QATEST_APP_000000_GROUP | select_base_three_multi_db_multi_tb_i9JV_02 | - | - * | 3 | DRDS_POLARX1_QATEST_APP_000000_GROUP | select_base_three_multi_db_multi_tb_i9JV_03 | - | - * | 4 | DRDS_POLARX1_QATEST_APP_000001_GROUP | select_base_three_multi_db_multi_tb_i9JV_04 | - | - * | 5 | DRDS_POLARX1_QATEST_APP_000001_GROUP | select_base_three_multi_db_multi_tb_i9JV_05 | - | - * | 6 | DRDS_POLARX1_QATEST_APP_000001_GROUP | select_base_three_multi_db_multi_tb_i9JV_06 | - | - * | 7 | DRDS_POLARX1_QATEST_APP_000001_GROUP | select_base_three_multi_db_multi_tb_i9JV_07 | - | - * ... ... - */ - c.createStatement().execute("select * from drds_polarx1_qatest_app.select_base_three_multi_db_multi_tb"); - - try { - c.createStatement() - .execute( - "select * from select_base_three_multi_db_multi_tb_i9JV_02 a join select_base_three_multi_db_one_tb b on a.pk=b.pk;"); - Assert.fail("should report error"); - } catch (SQLException e) { - log.info(e.getMessage()); - Assert.assertTrue(e.getMessage().contains("[PXC-4006][ERR_TABLE_NOT_EXIST]")); - } - try { - c.createStatement() - .execute( - "select * from select_base_three_multi_db_multi_tb_i9JV_06 a join select_base_three_multi_db_one_tb b on a.pk=b.pk;"); - } catch (SQLException e) { - log.info(e.getMessage()); - Assert.assertTrue(e.getMessage().contains("[PXC-4006][ERR_TABLE_NOT_EXIST]")); - } - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - log.info("session hint test end"); - } - - // auto table - try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_part_qatest_app"); - c.createStatement().execute("set partition_hint=p2"); - - /* - * expected topology - * | 0 | DRDS_POLARX1_PART_QATEST_APP_P00000_GROUP | select_base_three_multi_db_multi_tb_MvY5_00001 | p2 - * | 1 | DRDS_POLARX1_PART_QATEST_APP_P00001_GROUP | select_base_three_multi_db_multi_tb_MvY5_00000 | p1 - * | 2 | DRDS_POLARX1_PART_QATEST_APP_P00001_GROUP | select_base_three_multi_db_multi_tb_MvY5_00002 | p3 - * ... ... - */ - c.createStatement() - .execute("select * from drds_polarx1_part_qatest_app.select_base_three_multi_db_multi_tb"); - - try { - c.createStatement() - .execute( - "select * from select_base_three_multi_db_multi_tb_MvY5_00002 a join select_base_three_multi_db_one_tb b on a.pk=b.pk;"); - Assert.fail("should report error"); - } catch (SQLException e) { - log.info(e.getMessage()); - Assert.assertTrue(e.getMessage().contains("[PXC-4006][ERR_TABLE_NOT_EXIST]")); - } - try { - c.createStatement() - .execute( - "select * from select_base_three_multi_db_multi_tb_MvY5_00001 a join select_base_three_multi_db_one_tb b on a.pk=b.pk;"); - - } catch (SQLException e) { - log.info(e.getMessage()); - Assert.assertTrue(e.getMessage().contains("[PXC-4006][ERR_TABLE_NOT_EXIST]")); - } - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - log.info("session hint test end"); - } - } - - /** - * show full connection would output partition hint info. - */ - @Test - public void testShowFullConnection() throws SQLException { - Connection c = null; - try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:00'"); - - ResultSet rs = c.createStatement().executeQuery("show full connection"); - - boolean found = false; - while (rs.next()) { - String hint = rs.getString("PARTITION_HINT"); - if ("DRDS_POLARX1_QATEST_APP_000001_GROUP:00".equalsIgnoreCase(hint)) { - found = true; - } - } - Assert.assertTrue(found); - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - log.info("session hint test end"); - } - } - - /** - * partition hint with dml on table with gsi should report error. - */ - @Test - public void testDmlWithAutoGsi() throws SQLException { - Connection c = null; - try { - c = getPolardbxConnection(); - c.createStatement().execute("drop database if exists partition_hint_test"); - c.createStatement().execute("create database if not exists partition_hint_test mode=auto"); - c.createStatement().execute("use partition_hint_test"); - Random r = new Random(); - String tblName = "session_hint_dml_test_tb_order_" + r.nextInt(10000); - c.createStatement().execute( - "CREATE PARTITION TABLE " + tblName + "(\n" - + " `id` bigint(20) NOT NULL AUTO_INCREMENT,\n" - + " `bid` int(11) DEFAULT NULL,\n" - + " `name` varchar(30) DEFAULT NULL,\n" - + " PRIMARY KEY (`id`),\n" - + " GLOBAL INDEX /* idx_name_$a870 */ `idx_name` (`name`) PARTITION BY KEY (`name`, `id`) PARTITIONS 16,\n" - + " LOCAL KEY `_local_idx_name` (`name`)\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8\n" - + "PARTITION BY KEY(`id`)\n" - + "PARTITIONS 16"); - c.createStatement() - .execute("insert into " + tblName + "(id, bid, name) values(1, 11, 'a')"); - c.createStatement().execute("set partition_hint='P1'"); - - c.createStatement().execute("insert into " + tblName + "(id, bid, name) values(2, 12, 'a')"); - - Assert.fail("should report error"); - } catch (SQLException e) { - Assert.assertTrue( - e.getMessage().contains("[PXC-5311][ERR_GLOBAL_SECONDARY_INDEX_MODIFY_GSI_TABLE_DIRECTLY]")); - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - log.info("session hint test end"); - } - } - - /** - * partition hint with dml on table with gsi should report error. - */ - @Test - public void testDmlWithShardingGsi() throws SQLException { - Connection c = null; - try { - c = getPolardbxConnection(); - c.createStatement().execute("drop database if exists partition_hint_test"); - c.createStatement().execute("create database if not exists partition_hint_test mode=drds"); - c.createStatement().execute("use partition_hint_test"); - Random r = new Random(); - String tblName = "session_hint_dml_test_tb_order_" + r.nextInt(10000); - c.createStatement().execute( - "CREATE TABLE " + tblName + "(\n" - + " `id` bigint(20) NOT NULL AUTO_INCREMENT,\n" - + " `bid` int(11) DEFAULT NULL,\n" - + " `name` varchar(30) DEFAULT NULL,\n" - + " PRIMARY KEY (`id`),\n" - + " GLOBAL INDEX /* idx_name_$a870 */ `idx_name` (`name`) dbpartition by hash(`name`),\n" - + " LOCAL KEY `_local_idx_name` (`name`)\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8\n" - + "dbpartition by hash(name)"); - c.createStatement() - .execute("insert into " + tblName + "(id, bid, name) values(1, 11, 'a')"); - c.createStatement().execute("set partition_hint='PARTITION_HINT_TEST_000000_GROUP'"); - - c.createStatement().execute("insert into " + tblName + "(id, bid, name) values(2, 12, 'a')"); - - Assert.fail("should report error"); - } catch (SQLException e) { - Assert.assertTrue( - e.getMessage().contains("[PXC-5311][ERR_GLOBAL_SECONDARY_INDEX_MODIFY_GSI_TABLE_DIRECTLY]")); - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - log.info("session hint test end"); - } - } - - /** - * partition hint with dml on table with gsi should report error. - */ - @Test - public void testDmlWithShardingBroadcast() throws SQLException { - Connection c = null; - try { - c = getPolardbxConnection(); - c.createStatement().execute("drop database if exists partition_hint_test"); - c.createStatement().execute("create database if not exists partition_hint_test mode=drds"); - c.createStatement().execute("use partition_hint_test"); - Random r = new Random(); - String tblName = "session_hint_dml_test_tb_order_" + r.nextInt(10000); - c.createStatement().execute( - "CREATE TABLE " + tblName + "(\n" - + " `id` bigint(20) NOT NULL AUTO_INCREMENT,\n" - + " `bid` int(11) DEFAULT NULL,\n" - + " `name` varchar(30) DEFAULT NULL,\n" - + " PRIMARY KEY (`id`)\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8\n" - + "broadcast"); - c.createStatement() - .execute("insert into " + tblName + "(id, bid, name) values(1, 11, 'a')"); - c.createStatement().execute("set partition_hint='PARTITION_HINT_TEST_SINGLE_GROUP'"); - - c.createStatement().execute("insert into " + tblName + "(id, bid, name) values(2, 12, 'a')"); - - Assert.fail("should report error"); - } catch (SQLException e) { - e.printStackTrace(); - Assert.assertTrue( - e.getMessage().contains("[PXC-5325][ERR_MODIFY_BROADCAST_TABLE_BY_HINT_NOT_ALLOWED]")); - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - log.info("session hint test end"); - } - } - - /** - * test prepare path with partition hint - */ - @Test - public void testPrepareDml() throws SQLException { - Connection c = null; - try { - c = getPolardbxConnection(); - c.createStatement().execute("drop database if exists partition_hint_test"); - c.createStatement().execute("create database if not exists partition_hint_test mode=auto"); - c.createStatement().execute("use partition_hint_test"); - // create table into table group partition_test_tg1 - c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_tbl1` (\n" - + " `id` bigint NOT NULL,\n" - + " `name` varchar(25) NOT NULL,\n" - + " `c_time` datetime NOT NULL\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" - + "PARTITION BY RANGE(YEAR(c_time))\n" - + "(PARTITION p0 VALUES LESS THAN (1990) ENGINE = InnoDB,\n" - + " PARTITION p1 VALUES LESS THAN (2000) ENGINE = InnoDB,\n" - + " PARTITION p2 VALUES LESS THAN (2010) ENGINE = InnoDB,\n" - + " PARTITION p3 VALUES LESS THAN (2020) ENGINE = InnoDB);"); - - c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_tbl2` (\n" - + " `id` bigint NOT NULL,\n" - + " `name` varchar(25) NOT NULL,\n" - + " `c_time` datetime NOT NULL\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" - + "PARTITION BY RANGE(YEAR(c_time))\n" - + "(PARTITION p0 VALUES LESS THAN (1990) ENGINE = InnoDB,\n" - + " PARTITION p1 VALUES LESS THAN (2000) ENGINE = InnoDB,\n" - + " PARTITION p2 VALUES LESS THAN (2010) ENGINE = InnoDB,\n" - + " PARTITION p3 VALUES LESS THAN (2020) ENGINE = InnoDB);"); - - c.createStatement().executeQuery("set partition_hint='p1'"); - // test insert - PreparedStatement ps = - c.prepareStatement("insert into partition_hint_test_tbl1(id, name, c_time) values(?, ?, ?)"); - - ps.setInt(1, 5); - ps.setString(2, "a"); - ps.setTimestamp(3, new Timestamp(System.currentTimeMillis())); - - int affectRows = ps.executeUpdate(); - - Assert.assertTrue(affectRows == 1); - ps.close(); - - // test insert batch - c.createStatement().executeQuery("set partition_hint='p2'"); - ps = c.prepareStatement("insert into partition_hint_test_tbl1(id, name, c_time) values(?, ?, ?)"); - - ps.setInt(1, 5); - ps.setString(2, "a"); - ps.setTimestamp(3, new Timestamp(System.currentTimeMillis())); - - ps.addBatch(); - - ps.setInt(1, 6); - ps.setString(2, "b"); - ps.setTimestamp(3, new Timestamp(System.currentTimeMillis())); - - ps.addBatch(); - - ps.executeBatch(); - ps.close(); - - ResultSet rs = c.createStatement().executeQuery("select count(1) from partition_hint_test_tbl1"); - Assert.assertTrue(rs.next()); - Assert.assertTrue(2 == rs.getInt(1)); - - // test insert multi - c.createStatement().executeQuery("set partition_hint='p3'"); - ps = c.prepareStatement("insert into partition_hint_test_tbl1(id, name, c_time) values(?, ?, ?),(?, ?, ?)"); - - ps.setInt(1, 5); - ps.setString(2, "a"); - ps.setTimestamp(3, new Timestamp(System.currentTimeMillis())); - ps.setInt(4, 6); - ps.setString(5, "b"); - ps.setTimestamp(6, new Timestamp(System.currentTimeMillis())); - - affectRows = ps.executeUpdate(); - - Assert.assertTrue(affectRows == 2); - ps.close(); - - c.createStatement().executeQuery("set partition_hint=''"); - rs = c.createStatement().executeQuery("select count(1) from partition_hint_test_tbl1"); - Assert.assertTrue(rs.next()); - Assert.assertTrue(5 == rs.getInt(1)); - // test insert select - c.createStatement().executeQuery("set partition_hint='p3'"); - c.createStatement().execute("insert into partition_hint_test_tbl2 select * from partition_hint_test_tbl1"); - - rs = c.createStatement().executeQuery("select count(1) from partition_hint_test_tbl2"); - Assert.assertTrue(rs.next()); - Assert.assertTrue(2 == rs.getInt(1)); - - c.createStatement().executeQuery("set partition_hint='p2'"); - rs = c.createStatement().executeQuery("select count(1) from partition_hint_test_tbl2"); - Assert.assertTrue(rs.next()); - Assert.assertTrue(0 == rs.getInt(1)); - } finally { - Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(c).createStatement().execute("drop database if exists partition_hint_test"); - log.info("session hint test end"); - } - } -} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/HotEvolutionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/HotEvolutionTest.java new file mode 100644 index 000000000..7651214b0 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/HotEvolutionTest.java @@ -0,0 +1,327 @@ +package com.alibaba.polardbx.qatest.NotThreadSafe; + +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.optimizer.planmanager.PlanManager; +import com.alibaba.polardbx.qatest.BaseTestCase; +import com.alibaba.polardbx.qatest.util.ConnectionManager; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.google.common.collect.ImmutableList; +import com.google.common.truth.Truth; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.text.MessageFormat; +import java.util.List; + +public class HotEvolutionTest extends BaseTestCase { + private static final String DB = "hotEvolution"; + + private static final String EVO_TABLE = "full_table_big"; + + private static final String CREATE_TABLE_TEMPLATE = "CREATE TABLE {0} (\n" + + " `c_int_32` int(32) NOT NULL DEFAULT '0',\n" + + " `id` bigint(20) NOT NULL AUTO_INCREMENT,\n" + + " `c_bigint_64_un` bigint(64) UNSIGNED DEFAULT NULL,\n" + + " `c_bigint_1` bigint(1) DEFAULT NULL,\n" + + " `c_int_1` int(1) DEFAULT NULL,\n" + + " PRIMARY KEY (`id`),\n" + + " GLOBAL INDEX `c_bigint_1_idx` (`c_bigint_1`, `id`) PARTITION BY KEY(`c_bigint_1`, `id`) PARTITIONS 16,\n" + + " GLOBAL INDEX `c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`, `id`) PARTITION BY KEY(`c_bigint_64_un`, `c_int_1`, `id`) PARTITIONS 16,\n" + + " LOCAL KEY `_local_c_bigint_1_idx` (`c_bigint_1`),\n" + + " LOCAL KEY `_local_c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`)\n" + + ") ENGINE = InnoDB AUTO_INCREMENT = 9999976 DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS 16"; + + private static final String ENABLE_GLOBAL_HOT_GSI_EVOLUTION = + "set global " + ConnectionProperties.ENABLE_HOT_GSI_EVOLUTION + "= true"; + private static final String DISABLE_GLOBAL_HOT_GSI_EVOLUTION = + "set global " + ConnectionProperties.ENABLE_HOT_GSI_EVOLUTION + "= false"; + + private static final String SET_HOT_GSI_EVOLUTION_THRESHOLD = + "set " + ConnectionProperties.HOT_GSI_EVOLUTION_THRESHOLD + "= -1"; + + private static final String ANALYZE_TEMPLATE = "analyze table {0}"; + + private static final String SQL = "select * from {0} where c_bigint_1 = 12 and c_bigint_64_un = 14"; + + private static final String CLEAR_CACHE = "clear plancache"; + + private static final String SPM_CLEAR = "baseline delete_all"; + + private static final String SPM_HELP = "baseline help"; + + private static final String SPM_CLEAR_EVO = "baseline delete_evolved "; + + private static final String SPM_LIST = "baseline list "; + + private static final String INFO_SPM = "select * from information_schema.spm where baseline_id = '%s'"; + + @Override + public boolean usingNewPartDb() { + return true; + } + + @BeforeClass + public static void initDb() throws SQLException { + try (Connection tmpConnection = ConnectionManager.getInstance().getDruidPolardbxConnection()) { + JdbcUtil.createPartDatabase(tmpConnection, DB); + JdbcUtil.useDb(tmpConnection, DB); + JdbcUtil.dropTable(tmpConnection, EVO_TABLE); + JdbcUtil.executeUpdateSuccess(tmpConnection, + MessageFormat.format(CREATE_TABLE_TEMPLATE, EVO_TABLE)); + JdbcUtil.executeUpdateSuccess(tmpConnection, + MessageFormat.format(ANALYZE_TEMPLATE, EVO_TABLE)); + } + } + + @AfterClass + public static void deleteDb() throws SQLException { + try (Connection tmpConnection = ConnectionManager.getInstance().getDruidPolardbxConnection()) { + JdbcUtil.dropDatabase(tmpConnection, DB); + } + } + + @Test + public void testEvolution() { + System.out.println("testEvolution"); + String sql = MessageFormat.format(SQL, EVO_TABLE); + String baselineId; + try (Connection conn = getPolardbxConnection(DB)) { + JdbcUtil.executeSuccess(conn, CLEAR_CACHE); + JdbcUtil.executeSuccess(conn, SPM_CLEAR); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.PLAN_CACHE); + JdbcUtil.executeSuccess(conn, sql); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.PLAN_CACHE); + + // no evolution since plan is cached + JdbcUtil.executeSuccess(conn, SET_HOT_GSI_EVOLUTION_THRESHOLD); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.PLAN_CACHE); + + JdbcUtil.executeSuccess(conn, CLEAR_CACHE); + JdbcUtil.executeSuccess(conn, SPM_CLEAR); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.PLAN_CACHE); + + // wait for evolution + Thread.sleep(3000L); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.SPM_ACCEPT); + + baselineId = getBaselineId(conn, sql); + Truth.assertThat(baselineId).isNotEmpty(); + Truth.assertThat(getBaselineCount(conn, baselineId)).isEqualTo(3); + + // clear evolved + JdbcUtil.executeSuccess(conn, SPM_CLEAR_EVO); + Truth.assertThat(getBaselineCount(conn, baselineId)).isEqualTo(0); + + JdbcUtil.executeSuccess(conn, "baseline fix sql /*+TDDL:cmd_extra()*/ " + sql); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.SPM_FIX); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testEvolutionAndFix() { + System.out.println("testEvolutionAndFix"); + String sql = MessageFormat.format(SQL, EVO_TABLE); + String baselineId; + try (Connection conn = getPolardbxConnection(DB)) { + JdbcUtil.executeSuccess(conn, CLEAR_CACHE); + JdbcUtil.executeSuccess(conn, SPM_CLEAR); + JdbcUtil.executeSuccess(conn, SET_HOT_GSI_EVOLUTION_THRESHOLD); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.PLAN_CACHE); + // wait for evolution + Thread.sleep(3000L); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.SPM_ACCEPT); + + baselineId = getBaselineId(conn, sql); + Truth.assertThat(baselineId).isNotEmpty(); + Truth.assertThat(getBaselineCount(conn, baselineId)).isEqualTo(3); + + JdbcUtil.executeSuccess(conn, "baseline fix sql /*+TDDL:cmd_extra()*/ " + sql); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.SPM_FIX); + Truth.assertThat(getBaselineCount(conn, baselineId)).isEqualTo(3); + + // clear evolved + JdbcUtil.executeSuccess(conn, SPM_CLEAR_EVO); + Truth.assertThat(getBaselineCount(conn, baselineId)).isEqualTo(0); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testFixAndEvolution() { + String sql = MessageFormat.format(SQL, EVO_TABLE); + String baselineId; + System.out.println("testFixAndEvolution"); + try (Connection conn = getPolardbxConnection(DB)) { + JdbcUtil.executeSuccess(conn, CLEAR_CACHE); + JdbcUtil.executeSuccess(conn, SPM_CLEAR); + // baseline fix sql first + JdbcUtil.executeSuccess(conn, "baseline fix sql /*+TDDL:cmd_extra()*/ " + sql); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.SPM_FIX); + + // try evolve + JdbcUtil.executeSuccess(conn, SET_HOT_GSI_EVOLUTION_THRESHOLD); + JdbcUtil.executeSuccess(conn, CLEAR_CACHE); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.SPM_FIX); + JdbcUtil.executeSuccess(conn, sql); + Thread.sleep(3000L); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.SPM_FIX); + + // get baseline id + baselineId = getBaselineId(conn, sql); + Truth.assertThat(baselineId).isNotEmpty(); + + // should not evolve + Truth.assertThat(getBaselineCount(conn, baselineId)).isEqualTo(1); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testDisableEvolution() { + String sql = MessageFormat.format(SQL, EVO_TABLE); + String baselineId; + System.out.println("testDisableEvolution"); + try (Connection conn = getPolardbxConnection(DB)) { + JdbcUtil.executeSuccess(conn, CLEAR_CACHE); + JdbcUtil.executeSuccess(conn, SPM_CLEAR); + // try evolve + JdbcUtil.executeSuccess(conn, SET_HOT_GSI_EVOLUTION_THRESHOLD); + JdbcUtil.executeSuccess(conn, CLEAR_CACHE); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.PLAN_CACHE); + JdbcUtil.executeSuccess(conn, sql); + Thread.sleep(3000L); + + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.SPM_ACCEPT); + baselineId = getBaselineId(conn, sql); + Truth.assertThat(baselineId).isNotEmpty(); + Truth.assertThat(getBaselineCount(conn, baselineId)).isEqualTo(3); + // disable hot evolution + JdbcUtil.executeSuccess(conn, DISABLE_GLOBAL_HOT_GSI_EVOLUTION); + Thread.sleep(3000L); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.SPM_ACCEPT); + Truth.assertThat(getBaselineCount(conn, baselineId)).isEqualTo(3); + // clear cache + JdbcUtil.executeSuccess(conn, CLEAR_CACHE); + JdbcUtil.executeSuccess(conn, SPM_CLEAR); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.PLAN_CACHE); + JdbcUtil.executeSuccess(conn, sql); + Thread.sleep(3000L); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.PLAN_CACHE); + Truth.assertThat(getBaselineCount(conn, baselineId)).isEqualTo(0); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + try (Connection conn = getPolardbxConnection(DB)) { + JdbcUtil.executeSuccess(conn, ENABLE_GLOBAL_HOT_GSI_EVOLUTION); + Thread.sleep(3000L); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + @Test + public void testBaselineView() { + String sql = MessageFormat.format(SQL, EVO_TABLE); + String baselineId; + List> rows; + ResultSet rs; + System.out.println("testBaselineView"); + try (Connection conn = getPolardbxConnection(DB)) { + JdbcUtil.executeSuccess(conn, CLEAR_CACHE); + JdbcUtil.executeSuccess(conn, SPM_CLEAR); + JdbcUtil.executeSuccess(conn, SET_HOT_GSI_EVOLUTION_THRESHOLD); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.PLAN_CACHE); + // wait for evolution + Thread.sleep(3000L); + checkExplainSource(conn, sql, PlanManager.PLAN_SOURCE.SPM_ACCEPT); + + baselineId = getBaselineId(conn, sql); + Truth.assertThat(baselineId).isNotEmpty(); + + // check baseline help + boolean find = false; + rows = JdbcUtil.getAllStringResult(JdbcUtil.executeQuery(SPM_HELP, conn), false, ImmutableList.of()); + for (List row : rows) { + if (row.get(2).toLowerCase().contains(SPM_CLEAR_EVO.trim())) { + find = true; + break; + } + } + Truth.assertThat(find).isTrue(); + + // check hot evolved mark + rs = JdbcUtil.executeQuery(SPM_LIST + baselineId, conn); + while (rs.next()) { + Truth.assertThat(rs.getString("HOT_EVOLVED")).isEqualTo("true"); + } + rs.close(); + + // check hot evolved mark + rs = JdbcUtil.executeQuery(String.format(INFO_SPM, baselineId), conn); + while (rs.next()) { + Truth.assertThat(rs.getString("HOT_EVOLVED")).isEqualTo("true"); + } + rs.close(); + + JdbcUtil.executeSuccess(conn, SPM_CLEAR_EVO); + Truth.assertThat(getBaselineCount(conn, baselineId)).isEqualTo(0); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void checkExplainSource(Connection conn, String sql, PlanManager.PLAN_SOURCE expected) { + final List> res = + JdbcUtil.getAllStringResult(JdbcUtil.executeQuery("explain " + sql, conn), false, ImmutableList.of()); + String source = "SOURCE:"; + String result = ""; + for (List row : res) { + if (row.isEmpty()) { + continue; + } + System.out.println(row); + String value = row.get(0).toUpperCase(); + int sourceLoc = value.indexOf(source); + if (sourceLoc < 0) { + continue; + } + result = value.substring(sourceLoc + source.length()).trim(); + //break; + } + Truth.assertWithMessage("base explain " + sql).that(result).contains(expected.name().toUpperCase()); + } + + private String getBaselineId(Connection conn, String sql) { + final List> res = + JdbcUtil.getAllStringResult(JdbcUtil.executeQuery("explain " + sql, conn), false, ImmutableList.of()); + String source = "BaselineInfo Id:".toUpperCase(); + + for (List row : res) { + if (row.isEmpty()) { + continue; + } + String value = row.get(0).toUpperCase(); + int sourceLoc = value.indexOf(source); + if (sourceLoc < 0) { + continue; + } + return value.substring(sourceLoc + source.length()).trim(); + } + return ""; + } + + private int getBaselineCount(Connection conn, String baselineId) { + return JdbcUtil.getAllResult(JdbcUtil.executeQuery(SPM_LIST + baselineId, conn), false) + .size(); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/InformationSchemaTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/InformationSchemaTest.java index f4e7ba90b..f25b4bc6e 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/InformationSchemaTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/InformationSchemaTest.java @@ -16,20 +16,22 @@ package com.alibaba.polardbx.qatest.NotThreadSafe; -import com.alibaba.polardbx.common.utils.Assert; import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.qatest.AutoReadBaseTestCase; import com.alibaba.polardbx.qatest.CdcIgnore; import com.alibaba.polardbx.qatest.util.JdbcUtil; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.apache.commons.lang.StringUtils; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.sql.Connection; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; @@ -73,6 +75,9 @@ public class InformationSchemaTest extends AutoReadBaseTestCase { + "\tUNIQUE KEY (`char_test`, `integer_test`)\n" + ")"; + private static final String CREATE_VIEW_FORMAT = + "CREATE VIEW `%s` AS SELECT (`pk`) FROM `%s`"; + private static final String CREATE_TABLE_FORMAT_MIX_CASE = "CREATE TABLE `%s` (\n" + "\t`pk` bigint(11) NOT NULL,\n" + "\t`INTEGER_teST` int(11) DEFAULT NULL,\n" @@ -83,6 +88,11 @@ public class InformationSchemaTest extends AutoReadBaseTestCase { "select_base_one_multi_db_multi_tb", "select_base_two_multi_db_multi_tb"}; + private static final String[] mustContainViews = { + "select_base_one_multi_db_multi_tb_view", + "select_base_two_multi_db_multi_tb_view" + }; + private static final String[] mustContainTableColumns = { // select_base_two_multi_db_multi_tb "select_base_two_multi_db_multi_tb.pk", "select_base_two_multi_db_multi_tb.varchar_test", @@ -142,6 +152,8 @@ public class InformationSchemaTest extends AutoReadBaseTestCase { } } + private String[] unsupportedYet = {"GLOBAL_STATUS", "GLOBAL_VARIABLES", "SESSION_STATUS", "SESSION_VARIABLES"}; + @Before public void prepareDb() { JdbcUtil.dropDatabase(tddlConnection, INFORMATION_TEST_DB); @@ -152,6 +164,10 @@ public void prepareDb() { for (String table : mustContainTables) { JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(CREATE_TABLE_FORMAT, table)); } + for (int i = 0; i < mustContainViews.length; i++) { + JdbcUtil.executeUpdateSuccess(tddlConnection, + String.format(CREATE_VIEW_FORMAT, mustContainViews[i], mustContainTables[i])); + } //加入其它table JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(CREATE_TABLE_FORMAT, "select_base_three_multi_db_multi_tb")); @@ -170,7 +186,7 @@ public void clearDB() { } @Test - public void testTables() { + public void testTables() throws SQLException { String sql = String.format("select * from information_schema.tables where table_schema = '%s'", INFORMATION_TEST_DB); int size = assertContainsAllNames(sql, 1, 2, mustContainTablesSet); @@ -228,10 +244,37 @@ public void testTables() { INFORMATION_TEST_DB, "select_base_one_multi_db_multi_tb"); assertSizeEquals(sql, 1); + + sql = String.format( + "select table_schema,table_name,table_type from information_schema.tables where table_schema = '%s' and table_name='%s'", + INFORMATION_TEST_DB, + "select_base_one_multi_db_multi_tb_view" + ); + assertSizeEquals(sql, 1); + sql = String.format( + "select table_schema,table_name,table_type from information_schema.tables where table_schema = '%s' and table_name='%s'", + INFORMATION_TEST_DB, + "select_base_two_multi_db_multi_tb_view" + ); + assertSizeEquals(sql, 1); + + final String table = mustContainTables[0]; + sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = ? AND table_name = ?"; + PreparedStatement pstmt = + JdbcUtil.preparedStatementSet(sql, Lists.newArrayList(INFORMATION_TEST_DB, table), tddlConnection); + ResultSet resultSet = JdbcUtil.executeQuery(sql, pstmt); + Assert.assertTrue(resultSet.next()); + Assert.assertEquals(table, resultSet.getString(1)); + JdbcUtil.close(resultSet); } @Test - public void testColumns() { + public void TestTablesView() throws SQLException { + + } + + @Test + public void testColumns() throws SQLException { String sql = String.format("select * from information_schema.columns where table_schema = '%s'", INFORMATION_TEST_DB); int size = assertContainsAllTablesAndColumns(sql, 1, 2, 3, mustContainTableColumnsSet); @@ -286,10 +329,19 @@ public void testColumns() { INFORMATION_TEST_DB, "select_base_one_multi_db_multi_tb"); assertSizeEquals(sql, 20); + + final String table = mustContainTables[0]; + sql = "SELECT table_name FROM information_schema.columns WHERE table_schema = ? AND table_name = ?"; + PreparedStatement pstmt = + JdbcUtil.preparedStatementSet(sql, Lists.newArrayList(INFORMATION_TEST_DB, table), tddlConnection); + ResultSet resultSet = JdbcUtil.executeQuery(sql, pstmt); + Assert.assertTrue(resultSet.next()); + Assert.assertEquals(table, resultSet.getString(1)); + JdbcUtil.close(resultSet); } @Test - public void testStatistics() { + public void testStatistics() throws SQLException { String sql = String.format("select * from information_schema.statistics where table_schema = '%s'", INFORMATION_TEST_DB); @@ -340,6 +392,15 @@ public void testStatistics() { "select table_schema,table_name,index_name,column_name from information_schema.statistics where table_schema in ('%s') order by table_name,column_name limit 1,2", INFORMATION_TEST_DB); assertSizeEquals(sql, 2); + + final String table = mustContainTables[0]; + sql = "SELECT table_name FROM information_schema.statistics WHERE table_schema = ? AND table_name = ?"; + PreparedStatement pstmt = + JdbcUtil.preparedStatementSet(sql, Lists.newArrayList(INFORMATION_TEST_DB, table), tddlConnection); + ResultSet resultSet = JdbcUtil.executeQuery(sql, pstmt); + Assert.assertTrue(resultSet.next()); + Assert.assertEquals(table, resultSet.getString(1)); + JdbcUtil.close(resultSet); } @Test @@ -418,8 +479,6 @@ public void testSchemata() { assertCountResult(sql, size); } - private String[] unsupportedYet = {"GLOBAL_STATUS", "GLOBAL_VARIABLES", "SESSION_STATUS", "SESSION_VARIABLES"}; - @Test public void testPartitions() { @@ -624,7 +683,8 @@ public void testIn() { } @Test - @CdcIgnore(ignoreReason = "暂时未查到原因,可能是并行跑各种实验室导致。本地和实验室单独跑都无法复现,且对replica实验室无影响") + @CdcIgnore( + ignoreReason = "暂时未查到原因,可能是并行跑各种实验室导致。本地和实验室单独跑都无法复现,且对replica实验室无影响") public void testInformationPartitions() throws SQLException { try (Connection conn = getPolardbxConnection()) { // test INFORMATION_SCHEMA.PARTITIONS diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/OptimizerAlertScheduleJobTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/OptimizerAlertScheduleJobTest.java index 1c2ecf917..16bef06b6 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/OptimizerAlertScheduleJobTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/OptimizerAlertScheduleJobTest.java @@ -15,11 +15,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.AfterClass; -import org.junit.Ignore; import org.junit.Test; import java.sql.Connection; -import java.sql.Date; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -64,50 +62,6 @@ public class OptimizerAlertScheduleJobTest extends ReadBaseTestCase { public OptimizerAlertScheduleJobTest() { } - @Test - public void testXplanSlow() { - testShouldAlert(OptimizerAlertType.XPLAN_SLOW, () -> { - try (Connection conn = getPolardbxConnection(); - Statement statement = conn.createStatement()) { - String sql; - sql = "set ENABLE_ALERT_TEST=true"; - statement.execute(sql); - sql = - String.format( - "/*+TDDL:enable_mpp=false*/select * from select_base_four_%s where pk =10", - ExecuteTableName.ONE_DB_MUTIL_TB_SUFFIX); - statement.execute(sql); - return true; - } - }); - } - - @Test - public void testPlanCacheFull() { - testShouldAlert(OptimizerAlertType.PLAN_CACHE_FULL, () -> { - try (Connection conn = getPolardbxConnection(); - Statement statement = conn.createStatement()) { - String sql; - sql = "set global OPTIMIZER_ALERT_LOG_INTERVAL = 1000"; - statement.execute(sql); - sql = "set ENABLE_ALERT_TEST=true"; - statement.execute(sql); - Thread.sleep(2000L); - sql = "clear plancache"; - statement.execute(sql); - sql = "select * from select_base_four_" + ExecuteTableName.ONE_DB_MUTIL_TB_SUFFIX; - statement.execute(sql); - return true; - } finally { - try (Connection conn = getPolardbxConnection()) { - String sql = "set global OPTIMIZER_ALERT_LOG_INTERVAL = " + 600000; - JdbcUtil.executeSuccess(conn, sql); - JdbcUtil.executeSuccess(conn, ENABLE_DEFAULT_CHECK); - } - } - }); - } - @Test public void testBKATooMuch() { testShouldAlert(OptimizerAlertType.BKA_TOO_MUCH, () -> { @@ -211,42 +165,6 @@ public void testStatisticJobInterrupt() throws SQLException, InterruptedExceptio } } - @Test - @Ignore - public void testStatisticJobInconsistent() throws SQLException, InterruptedException { - try (Connection connection = getPolardbxConnection()) { - Statement statement = connection.createStatement(); - statement.execute("set global alert_statistic_inconsistent=true"); - statement.execute("set global alert_statistic_interrupt=false"); - statement.execute("set @fp_inject_ignore_interrupted_to_statistic_schedule_job='true'"); - statement.execute("analyze table select_base_four_" + ExecuteTableName.ONE_DB_MUTIL_TB_SUFFIX); - } - - // wait 5 sec - Thread.sleep(5 * 1000L); - - testShouldAlert(OptimizerAlertType.STATISTIC_INCONSISTENT, () -> { - try (Connection conn = getPolardbxConnection(); - Statement statement = conn.createStatement()) { - - ResultSet rs = statement.executeQuery( - "select schedule_id from metadb.scheduled_jobs where executor_type='statistic_sample_sketch'"); - rs.next(); - String scheduleId = rs.getString("schedule_id"); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String now = sdf.format(new Date(System.currentTimeMillis())); - statement.execute("fire schedule " + scheduleId); - return true; - } - }); - - try (Connection connection = getPolardbxConnection()) { - Statement statement = connection.createStatement(); - statement.execute("set @fp_inject_ignore_interrupted_to_statistic_schedule_job='false'"); - statement.execute("set global alert_statistic_inconsistent=false"); - } - } - protected void testShouldAlert(OptimizerAlertType targetAlert, Callable func) { try (Connection conn = getPolardbxConnection()) { JdbcUtil.executeSuccess(conn, DISABLE_DEFAULT_CHECK); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/SessionHintTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/SessionHintTest.java deleted file mode 100644 index 04c1d5a5d..000000000 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/SessionHintTest.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.alibaba.polardbx.qatest.NotThreadSafe; - -import com.alibaba.polardbx.common.utils.Assert; -import com.alibaba.polardbx.qatest.BaseTestCase; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Test; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Objects; - -public class SessionHintTest extends BaseTestCase { - private static final Log log = LogFactory.getLog("ROOT"); - private static final String TBL_NAME = "session_hint_test"; - private static final String CREATE_TBL = "CREATE TABLE if not exists `session_hint_test` (\n" - + " `pk` bigint(11) NOT NULL,\n" - + " `integer_test` int(11) DEFAULT NULL,\n" - + " PRIMARY KEY (`pk`)\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8"; - - private void checkHintWork(Connection conn, String tblName) throws SQLException { - // prepare table - conn.createStatement().execute(CREATE_TBL); - - // get group name and partition name - ResultSet rs = conn.createStatement().executeQuery("show topology from " + tblName); - - String groupName = null; - String partitionName = null; - while (rs.next()) { - groupName = rs.getString("GROUP_NAME"); - partitionName = rs.getString("PARTITION_NAME"); - break; - } - rs.close(); - Assert.assertTrue(groupName != null && partitionName != null); - - // test partition hint working - conn.createStatement().execute("set partition_hint=" + partitionName); - conn.createStatement().execute("trace select * from " + tblName); - rs = conn.createStatement().executeQuery("show trace"); - - while (rs.next()) { - String groupNameTmp = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupNameTmp.equalsIgnoreCase(groupName)); - } - rs.close(); - conn.createStatement().execute("set partition_hint=''"); - } - - @Test - public void testSessionHintWithFlashBack() throws SQLException, InterruptedException { - Connection connWithHint = null; - try { - connWithHint = getPolardbxConnection(); - connWithHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - - connWithHint.createStatement().execute("set partition_hint=p3"); - connWithHint.createStatement().execute("set global ENABLE_FORBID_PUSH_DML_WITH_HINT=false"); - Thread.sleep(2000); - // test partition hint working - checkHintWork(connWithHint, TBL_NAME); - ResultSet rs; - - // clear data - connWithHint.createStatement().execute("truncate table update_delete_base_autonic_multi_db_multi_tb"); - - // Ensure the as of timestamp is valid. - Thread.sleep(1000); - - // test insert into partition table - Calendar current = Calendar.getInstance(); - current.setTimeInMillis(current.getTimeInMillis() - 5000); - SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - connWithHint.setAutoCommit(false); - connWithHint.createStatement() - .execute( - "insert into update_delete_base_autonic_multi_db_multi_tb(varchar_test, timestamp_test) values('session hint test value', now())"); - connWithHint.commit(); - String sql = "select * from update_delete_base_autonic_multi_db_multi_tb as of timestamp '" + f.format( - current.getTime()) + "' where varchar_test='session hint test value'"; - System.out.println(sql); - rs = connWithHint.createStatement().executeQuery(sql); - while (rs.next()) { - Assert.fail("should not query any value by flashback"); - } - rs.close(); - } catch (Throwable t) { - if (isMySQL80() && t.getMessage().contains( - "The definition of the table required by the flashback query has changed")) { - return; - } - throw t; - } finally { - Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(connWithHint).close(); - log.info("session hint test end"); - } - } - - @Test - public void testSessionHintForbiddenByConfig() throws SQLException, InterruptedException { - Connection connWithHint = null; - try { - connWithHint = getPolardbxConnection(); - connWithHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - - connWithHint.createStatement().execute("set partition_hint=p3"); - connWithHint.createStatement().execute("set global ENABLE_FORBID_PUSH_DML_WITH_HINT=true"); - Thread.sleep(2000); - connWithHint.setAutoCommit(false); - - // test partition hint working - checkHintWork(connWithHint, TBL_NAME); - connWithHint.createStatement().execute("set partition_hint=p3"); - try { - connWithHint.createStatement() - .execute( - "insert into update_delete_base_autonic_multi_db_multi_tb(varchar_test, timestamp_test) values('session hint test value', now())"); - Assert.fail(" dml should be forbidden by ENABLE_FORBID_PUSH_DML_WITH_HINT=true"); - } catch (SQLException e) { - if (!e.getMessage().contains("Unsupported to push physical dml by hint ")) { - throw e; - } - } - - try { - connWithHint.createStatement() - .execute( - "update update_delete_base_autonic_multi_db_multi_tb set varchar_test='session hint test value'"); - Assert.fail(" dml should be forbidden by ENABLE_FORBID_PUSH_DML_WITH_HINT=true"); - } catch (SQLException e) { - if (!e.getMessage().contains("Unsupported to push physical dml by hint ")) { - throw e; - } - } - - try { - connWithHint.createStatement() - .execute( - "insert into update_delete_base_autonic_multi_db_multi_tb select * from update_delete_base_autonic_string_multi_db_multi_tb"); - Assert.fail(" dml should be forbidden by ENABLE_FORBID_PUSH_DML_WITH_HINT=true"); - } catch (SQLException e) { - if (!e.getMessage().contains("Unsupported to push physical dml by hint ")) { - throw e; - } - } - } finally { - Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(connWithHint).close(); - log.info("session hint test end"); - } - } - - @Test - public void testSessionHintWithDML() throws SQLException, InterruptedException { - Connection connWithHint = null; - try { - connWithHint = getPolardbxConnection(); - connWithHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - - connWithHint.createStatement().execute("set partition_hint=p3"); - connWithHint.createStatement().execute("set global ENABLE_FORBID_PUSH_DML_WITH_HINT=false"); - Thread.sleep(2000); - - // test partition hint working - checkHintWork(connWithHint, TBL_NAME); - connWithHint.createStatement().execute("set partition_hint=p3"); - - connWithHint.createStatement() - .execute( - "insert into update_delete_base_autonic_multi_db_multi_tb(varchar_test, timestamp_test) values('session hint test value', now())"); - - connWithHint.createStatement() - .execute( - "update update_delete_base_autonic_multi_db_multi_tb set varchar_test='session hint test value111'"); - connWithHint.createStatement() - .execute("truncate table update_delete_base_autonic_string_multi_db_multi_tb"); - connWithHint.createStatement() - .execute( - "insert into update_delete_base_autonic_string_multi_db_multi_tb(varchar_test, timestamp_test) " - + "select varchar_test, timestamp_test from update_delete_base_autonic_multi_db_multi_tb"); - } finally { - Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(connWithHint).close(); - log.info("session hint test end"); - } - } - -} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dal/set/SetInstanceReadOnlyTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/SetInstanceReadOnlyTest.java similarity index 99% rename from polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dal/set/SetInstanceReadOnlyTest.java rename to polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/SetInstanceReadOnlyTest.java index 84be7c923..169cc7093 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dal/set/SetInstanceReadOnlyTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/SetInstanceReadOnlyTest.java @@ -1,4 +1,4 @@ -package com.alibaba.polardbx.qatest.dal.set; +package com.alibaba.polardbx.qatest.NotThreadSafe; import com.alibaba.polardbx.qatest.DirectConnectionBaseTestCase; import com.alibaba.polardbx.qatest.constant.ConfigConstant; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/SpmChoosePlanTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/SpmChoosePlanTest.java new file mode 100644 index 000000000..faee0b30f --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/SpmChoosePlanTest.java @@ -0,0 +1,190 @@ +package com.alibaba.polardbx.qatest.NotThreadSafe; + +import com.alibaba.polardbx.qatest.BaseTestCase; +import com.alibaba.polardbx.qatest.util.ConnectionManager; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.google.common.collect.ImmutableList; +import com.google.common.truth.Truth; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.SQLException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.stream.IntStream; + +public class SpmChoosePlanTest extends BaseTestCase { + private static final String DB = "spmChoose"; + + private static final String SPM_TABLE = "full_table_big"; + + private static final String CREATE_TABLE_TEMPLATE = "CREATE TABLE {0} (\n" + + " `c_int_32` int(32) NOT NULL DEFAULT '0',\n" + + " `id` bigint(20) NOT NULL AUTO_INCREMENT,\n" + + " `c_bigint_64_un` bigint(64) UNSIGNED DEFAULT NULL,\n" + + " `c_bigint_1` bigint(1) DEFAULT NULL,\n" + + " `c_int_1` int(1) DEFAULT NULL,\n" + + " PRIMARY KEY (`id`),\n" + + " GLOBAL INDEX `c_bigint_1_idx` (`c_bigint_1`, `id`) PARTITION BY KEY(`c_bigint_1`, `id`) PARTITIONS 16,\n" + + " GLOBAL INDEX `c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`, `id`) PARTITION BY KEY(`c_bigint_64_un`, `c_int_1`, `id`) PARTITIONS 16,\n" + + " LOCAL KEY `_local_c_bigint_1_idx` (`c_bigint_1`),\n" + + " LOCAL KEY `_local_c_bigint_64_un_c_int_1_idx` (`c_bigint_64_un`, `c_int_1`)\n" + + ") ENGINE = InnoDB AUTO_INCREMENT = 9999976 DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS 16"; + + private static final String SQL = "select * from %s where c_bigint_1 in %s and c_bigint_64_un in %s"; + + private static final String INDEX1 = "c_bigint_1_idx"; + + private static final String INDEX2 = "c_bigint_64_un_c_int_1_idx"; + + private static final String INDEX_HINT1 = String.format("/*+TDDL:index(%s, %s)*/ ", SPM_TABLE, INDEX1); + + private static final String INDEX_HINT2 = String.format("/*+TDDL:index(%s, %s)*/", SPM_TABLE, INDEX2); + + private static final String CON_SHORT = "(1)"; + + private static final String CON_LONG = "(1, 2)"; + + private static final String CLEAR_CACHE = "clear plancache"; + + private static final String SPM_CLEAR = "baseline delete_all"; + + private static final String SPM_ADD = "baseline add sql "; + + private static final String SPM_LIST = "baseline list "; + + @Override + public boolean usingNewPartDb() { + return true; + } + + @BeforeClass + public static void initDb() throws SQLException { + try (Connection tmpConnection = ConnectionManager.getInstance().getDruidPolardbxConnection()) { + JdbcUtil.createPartDatabase(tmpConnection, DB); + JdbcUtil.useDb(tmpConnection, DB); + JdbcUtil.dropTable(tmpConnection, SPM_TABLE); + JdbcUtil.executeUpdateSuccess(tmpConnection, + MessageFormat.format(CREATE_TABLE_TEMPLATE, SPM_TABLE)); + } + } + + @AfterClass + public static void deleteDb() throws SQLException { + try (Connection tmpConnection = ConnectionManager.getInstance().getDruidPolardbxConnection()) { + JdbcUtil.dropDatabase(tmpConnection, DB); + } + } + + @Before + public void before() { + try (Connection conn = getPolardbxConnection(DB)) { + JdbcUtil.executeSuccess(conn, CLEAR_CACHE); + JdbcUtil.executeSuccess(conn, SPM_CLEAR); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testEvolution() { + String sql; + String baselineId; + ExecutorService executorService = Executors.newFixedThreadPool(10); + try (Connection conn = getPolardbxConnection(DB)) { + JdbcUtil.executeSuccess(conn, SPM_ADD + INDEX_HINT1 + String.format(SQL, SPM_TABLE, CON_SHORT, CON_SHORT)); + JdbcUtil.executeSuccess(conn, SPM_ADD + INDEX_HINT2 + String.format(SQL, SPM_TABLE, CON_SHORT, CON_SHORT)); + + sql = String.format(SQL, SPM_TABLE, CON_SHORT, CON_SHORT); + JdbcUtil.executeSuccess(conn, "explain " + sql); + + baselineId = getBaselineId(conn, sql); + Truth.assertThat(baselineId).isNotEmpty(); + Truth.assertThat(getBaselineCount(conn, baselineId)).isEqualTo(2); + + String[] sqls = { + String.format(SQL, SPM_TABLE, CON_SHORT, CON_LONG), String.format(SQL, SPM_TABLE, CON_LONG, CON_SHORT)}; + String[] indexes = {INDEX1, INDEX2}; + for (String testSql : sqls) { + Truth.assertWithMessage("base explain " + sql).that(getBaselineId(conn, testSql)).contains(baselineId); + } + + Callable task = + () -> { + try (Connection testConn = getPolardbxConnection(DB)) { + Random r1 = new Random(); + for (int i = 0; i < 15; i++) { + int loc = r1.nextInt(2); + checkGsi(testConn, sqls[loc], indexes[loc]); + } + return "success"; + } catch (SQLException e) { + e.printStackTrace(); + return (e.toString()); + } + }; + List> futures = new ArrayList<>(); + IntStream.range(0, 10).forEach( + i -> futures.add(executorService.submit(task))); + + for (Future future : futures) { + future.get(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + executorService.shutdown(); + } + } + + private void checkGsi(Connection conn, String sql, String index) { + final List> res = + JdbcUtil.getAllStringResult(JdbcUtil.executeQuery("explain " + sql, conn), false, ImmutableList.of()); + index = index.toUpperCase(); + String source = "IndexScan".toUpperCase(); + for (List row : res) { + if (row.isEmpty()) { + continue; + } + String value = row.get(0).toUpperCase(); + if (value.contains(source)) { + Truth.assertWithMessage("base explain " + sql).that(value).contains(index); + return; + } + } + Truth.assertWithMessage("base explain " + sql).that(true).isFalse(); + } + + private String getBaselineId(Connection conn, String sql) { + final List> res = + JdbcUtil.getAllStringResult(JdbcUtil.executeQuery("explain " + sql, conn), false, ImmutableList.of()); + String source = "BaselineInfo Id:".toUpperCase(); + + for (List row : res) { + if (row.isEmpty()) { + continue; + } + String value = row.get(0).toUpperCase(); + int sourceLoc = value.indexOf(source); + if (sourceLoc < 0) { + continue; + } + return value.substring(sourceLoc + source.length()).trim(); + } + return ""; + } + + private int getBaselineCount(Connection conn, String baselineId) { + return JdbcUtil.getAllResult(JdbcUtil.executeQuery(SPM_LIST + baselineId, conn), false) + .size(); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/XPlanFeedBackTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/XPlanFeedBackTest.java index 9354e28b1..d1e96b236 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/XPlanFeedBackTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/XPlanFeedBackTest.java @@ -40,6 +40,12 @@ public class XPlanFeedBackTest extends DDLBaseNewDBTestCase { "set " + ConnectionProperties.ENABLE_XPLAN_FEEDBACK + "= true"; private static final String DISABLE_XPLAN_FEEDBACK = "set " + ConnectionProperties.ENABLE_XPLAN_FEEDBACK + "= false"; + + private static final String DISABLE_DIRECT_PLAN = + "set " + ConnectionProperties.ENABLE_DIRECT_PLAN + "= false"; + private static final String DISABLE_POST_PLANNER = + "set " + ConnectionProperties.ENABLE_POST_PLANNER + "= false"; + private static final String ANALYZE_TEMPLATE = "analyze table {0}"; private static final String SK_SQL = "select * from {0} where x = 1"; @@ -183,6 +189,74 @@ public void testFeedBack() { } } + @Test + public void testFeedBackSpm() { + if (isMySQL80()) { + return; + } + JdbcUtil.executeSuccess(tddlConnection, CLEAR_CACHE); + JdbcUtil.executeSuccess(tddlConnection, CLEAR_SPM); + + // try feedback + try (Connection conn = getPolardbxConnection()) { + JdbcUtil.executeSuccess(conn, ENABLE_XPLAN_FEEDBACK); + JdbcUtil.executeSuccess(conn, DISABLE_DIRECT_PLAN); + JdbcUtil.executeSuccess(conn, DISABLE_POST_PLANNER); + JdbcUtil.executeSuccess(conn, + "baseline add sql /*+TDDL:cmd_extra()*/ " + MessageFormat.format(SK_SQL, XPLAN_TABLE)); + JdbcUtil.executeSuccess(conn, + "baseline add sql /*+TDDL:cmd_extra()*/ " + MessageFormat.format(PK_SQL, XPLAN_TABLE)); + JdbcUtil.executeSuccess(conn, + "baseline add sql /*+TDDL:cmd_extra()*/ " + MessageFormat.format(SK_PK_SQL, XPLAN_TABLE)); + assertExplainExecute(conn, MessageFormat.format(SK_SQL, XPLAN_TABLE), true); + assertExplainExecute(conn, MessageFormat.format(PK_SQL, XPLAN_TABLE), false); + assertExplainExecute(conn, MessageFormat.format(SK_PK_SQL, XPLAN_TABLE), true); + + // mock feedback + JdbcUtil.executeSuccess(conn, "set " + ConnectionProperties.XPLAN_MAX_SCAN_ROWS + "= 0"); + JdbcUtil.executeSuccess(conn, MessageFormat.format(SK_SQL, XPLAN_TABLE)); + JdbcUtil.executeSuccess(conn, MessageFormat.format(PK_SQL, XPLAN_TABLE)); + JdbcUtil.executeSuccess(conn, MessageFormat.format(SK_PK_SQL, XPLAN_TABLE)); + JdbcUtil.executeSuccess(conn, "set " + ConnectionProperties.XPLAN_MAX_SCAN_ROWS + "= 1000"); + + // xplan should be closed + assertExplainExecute(conn, MessageFormat.format(SK_SQL, XPLAN_TABLE), false); + assertExplainExecute(conn, MessageFormat.format(PK_SQL, XPLAN_TABLE), false); + assertExplainExecute(conn, MessageFormat.format(SK_PK_SQL, XPLAN_TABLE), false); + + // disable feedback + JdbcUtil.executeSuccess(conn, DISABLE_XPLAN_FEEDBACK); + assertExplainExecute(conn, MessageFormat.format(SK_SQL, XPLAN_TABLE), true); + assertExplainExecute(conn, MessageFormat.format(PK_SQL, XPLAN_TABLE), false); + assertExplainExecute(conn, MessageFormat.format(SK_PK_SQL, XPLAN_TABLE), true); + + // enable ENABLE_XPLAN_FEEDBACK again + JdbcUtil.executeSuccess(conn, ENABLE_XPLAN_FEEDBACK); + assertExplainExecute(conn, MessageFormat.format(SK_SQL, XPLAN_TABLE), false); + assertExplainExecute(conn, MessageFormat.format(PK_SQL, XPLAN_TABLE), false); + assertExplainExecute(conn, MessageFormat.format(SK_PK_SQL, XPLAN_TABLE), false); + + // clear plancache and execute sql again + JdbcUtil.executeSuccess(conn, CLEAR_CACHE); + assertExplainExecute(conn, MessageFormat.format(SK_SQL, XPLAN_TABLE), true); + assertExplainExecute(conn, MessageFormat.format(PK_SQL, XPLAN_TABLE), false); + assertExplainExecute(conn, MessageFormat.format(SK_PK_SQL, XPLAN_TABLE), true); + JdbcUtil.executeSuccess(conn, MessageFormat.format(SK_SQL, XPLAN_TABLE)); + JdbcUtil.executeSuccess(conn, MessageFormat.format(PK_SQL, XPLAN_TABLE)); + JdbcUtil.executeSuccess(conn, MessageFormat.format(SK_PK_SQL, XPLAN_TABLE)); + + // no feedback should happen + assertExplainExecute(conn, MessageFormat.format(SK_SQL, XPLAN_TABLE), true); + assertExplainExecute(conn, MessageFormat.format(PK_SQL, XPLAN_TABLE), false); + assertExplainExecute(conn, MessageFormat.format(SK_PK_SQL, XPLAN_TABLE), true); + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + JdbcUtil.executeSuccess(tddlConnection, CLEAR_CACHE); + JdbcUtil.executeSuccess(tddlConnection, CLEAR_SPM); + } + } + private boolean explainExecuteXplan(Connection conn, String sql) { final List> res = JdbcUtil.getAllStringResult(JdbcUtil.executeQuery("explain execute " + sql, conn), false, diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/failpoint/AlterTableGroupMovePartitionFailedTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/failpoint/AlterTableGroupMovePartitionFailedTest.java new file mode 100644 index 000000000..452a284d0 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/NotThreadSafe/failpoint/AlterTableGroupMovePartitionFailedTest.java @@ -0,0 +1,191 @@ +package com.alibaba.polardbx.qatest.NotThreadSafe.failpoint; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.alibaba.polardbx.qatest.util.RandomUtils; +import org.apache.commons.lang3.StringUtils; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class AlterTableGroupMovePartitionFailedTest extends DDLBaseNewDBTestCase { + static private final String DATABASE_NAME = "MovePartitionFailedTest"; + + private static final String SHOW_DS = "show ds where db='%s'"; + + private static final String SELECT_FROM_TABLE_DETAIL = + "select storage_inst_id,table_group_name from information_schema.table_detail where table_schema='%s' and table_name='%s' and partition_name='%s'"; + + private static final String CREATE_TABLE_SQL = + "create table `%s` (`a` int(11) primary key auto_increment, `b` int(11), `c` timestamp DEFAULT CURRENT_TIMESTAMP) PARTITION BY KEY(`a`) PARTITIONS 3"; + + private static final String INSERT_SQL = + "insert into `%s` (b, c) values (1, now()), (2, now()), (3, now()), (4, now())"; + + private static final String ALTER_TABLE_GROUP_SQL = "alter tablegroup %s move partitions %s to '%s'"; + + private static final String PARTITION_NAME = "p1"; + + @Before + public void before() { + doReCreateDatabase(); + } + + @Test + public void alterTableGroupWithFailPointTest() throws Exception { + List tableNames = new ArrayList<>(); + for (int i = 0; i < 4; ++i) { + String tableName = "t" + i + RandomUtils.getStringBetween(1, 5); + tableNames.add(tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(CREATE_TABLE_SQL, tableName)); + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(INSERT_SQL, tableName)); + } + + List commands = prepareCommands(tddlConnection, tableNames.get(0)); + + String failPointSql = String.format("set @FP_SPECIFIED_TABLE_DROP_PHY_EXCEPTION='%s'", tableNames.get(3)); + String failPointClearSql = "set @FP_SPECIFIED_TABLE_DROP_PHY_EXCEPTION=NULL"; + + for (String command : commands) { + System.out.printf("%s begin to execute command:[%s]%n", LocalTime.now().toString(), command); + + // 异常注入 + JdbcUtil.executeUpdateSuccess(tddlConnection, failPointSql); + + // 执行命令 + JdbcUtil.executeUpdateFailed(tddlConnection, command, "FP_SPECIFIED_TABLE_DROP_PHY_EXCEPTION"); + + System.out.printf("%s command:[%s] failed due to exception injection%n", LocalTime.now().toString(), + command); + + // 检查 + Assert.assertTrue(checkTables(tddlConnection, tableNames, 4L)); + + // 清除异常注入 + JdbcUtil.executeUpdateSuccess(tddlConnection, failPointClearSql); + + Long jobId = getDDLJobId(tddlConnection); + + // 回滚失败 + JdbcUtil.executeUpdateFailed(tddlConnection, String.format("ROLLBACK DDL %s", jobId), + "cannot be rolled back"); + + // 继续执行 + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format("CONTINUE DDL %s", jobId)); + + // 检查 + Assert.assertTrue(checkTables(tddlConnection, tableNames, 4L)); + + System.out.printf("%s command:[%s] finish%n", LocalTime.now().toString(), command); + } + } + + private static boolean checkTables(Connection connection, List tableNames, long rowCount) + throws SQLException { + String sql = "use " + DATABASE_NAME; + JdbcUtil.executeUpdate(connection, sql); + + for (String tableName : tableNames) { + // check table + sql = String.format("check table %s", tableName); + try (ResultSet rs = JdbcUtil.executeQuery(sql, connection)) { + while (rs.next()) { + String text = rs.getString("MSG_TEXT"); + if (!StringUtils.equalsIgnoreCase(text, "OK")) { + return false; + } + } + } + + // check row count + sql = String.format("select count(*) from %s", tableName); + try (ResultSet rs = JdbcUtil.executeQuery(sql, connection)) { + if (rs.next()) { + if (rs.getLong(1) != rowCount) { + return false; + } + } else { + return false; + } + } + } + return true; + } + + private static List prepareCommands(Connection connection, String tableName) throws SQLException { + List commands = new ArrayList<>(); + Set instIds = new HashSet<>(); + String curInstId; + String tableGroupName; + + String sql = "use " + DATABASE_NAME; + JdbcUtil.executeUpdate(connection, sql); + + sql = String.format(SELECT_FROM_TABLE_DETAIL, DATABASE_NAME, tableName, "p1"); + try (ResultSet rs = JdbcUtil.executeQuery(sql, connection)) { + if (rs.next()) { + curInstId = rs.getString("STORAGE_INST_ID"); + tableGroupName = rs.getString("TABLE_GROUP_NAME"); + } else { + throw new RuntimeException( + String.format("table %s.%s not found", DATABASE_NAME, tableName)); + } + } + + sql = String.format(SHOW_DS, DATABASE_NAME); + try (ResultSet rs = JdbcUtil.executeQuery(sql, connection)) { + while (rs.next()) { + if (!curInstId.equalsIgnoreCase(rs.getString("STORAGE_INST_ID"))) { + instIds.add(rs.getString("STORAGE_INST_ID")); + } + } + } + + Assert.assertTrue(!instIds.isEmpty()); + + for (String instId : instIds) { + // move partition p1 + commands.add(String.format(ALTER_TABLE_GROUP_SQL, tableGroupName, PARTITION_NAME, instId)); + } + return commands; + } + + private static Long getDDLJobId(Connection connection) throws SQLException { + long jobId = -1L; + String sql = "use " + DATABASE_NAME; + JdbcUtil.executeUpdate(connection, sql); + + sql = "show ddl"; + ResultSet rs = JdbcUtil.executeQuery(sql, connection); + if (rs.next()) { + jobId = rs.getLong("JOB_ID"); + } + rs.close(); + return jobId; + } + + void doReCreateDatabase() { + doClearDatabase(); + String sql = "use information_schema"; + JdbcUtil.executeUpdate(tddlConnection, sql); + sql = "create database " + DATABASE_NAME + " partition_mode = 'auto'"; + JdbcUtil.executeUpdate(tddlConnection, sql); + sql = "use " + DATABASE_NAME; + JdbcUtil.executeUpdate(tddlConnection, sql); + } + + void doClearDatabase() { + JdbcUtil.executeUpdate(getTddlConnection1(), "use information_schema"); + String sql = "drop database if exists " + DATABASE_NAME; + JdbcUtil.executeUpdate(getTddlConnection1(), sql); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/after/AfterTests.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/after/AfterTests.java index 88bfb6bc3..dfa5c1814 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/after/AfterTests.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/after/AfterTests.java @@ -7,10 +7,11 @@ import java.sql.Connection; import java.sql.ResultSet; +import java.sql.SQLException; public class AfterTests extends BaseTestCase { @Test - public void check() { + public void check() throws SQLException { try (Connection polarxConn = getPolardbxDirectConnection()) { // 检查复制中断 String sql = "show storage"; @@ -40,6 +41,7 @@ public void check() { Assert.assertTrue(cnt == 1, "more than 1 trx found"); } catch (Throwable t) { t.printStackTrace(); + throw t; } } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/Bank.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/Bank.java index 8543bd9aa..a646a8dc5 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/Bank.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/Bank.java @@ -16,8 +16,8 @@ package com.alibaba.polardbx.qatest.cdc; +import com.alibaba.polardbx.qatest.util.JdbcUtil; import lombok.extern.slf4j.Slf4j; -import org.springframework.jdbc.support.JdbcUtils; import javax.sql.DataSource; import java.sql.Connection; @@ -118,7 +118,7 @@ private void doTransfer(Transfer transfer) throws SQLException { } catch (Exception e) { conn.rollback(); } finally { - JdbcUtils.closeConnection(conn); + JdbcUtil.closeConnection(conn); } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/CdcCheckBeforeTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/CdcCheckBeforeTest.java index a15af377c..eec8bfb07 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/CdcCheckBeforeTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/CdcCheckBeforeTest.java @@ -16,13 +16,12 @@ package com.alibaba.polardbx.qatest.cdc; +import com.alibaba.polardbx.qatest.util.JdbcUtil; import lombok.extern.slf4j.Slf4j; import org.junit.Test; -import org.springframework.jdbc.support.JdbcUtils; import java.sql.Connection; import java.sql.SQLException; -import java.sql.Statement; import static com.alibaba.polardbx.qatest.cdc.Bank.ACCOUNT_COUNT; @@ -65,7 +64,7 @@ private void initAccounts(int accountCount) throws SQLException { log.error("Initial Accounts ERROR.", e); throw e; } finally { - JdbcUtils.closeConnection(conn); + JdbcUtil.closeConnection(conn); } log.info("accounts initialized success."); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/DataSourceUtil.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/DataSourceUtil.java index d927fa156..84dd833d5 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/DataSourceUtil.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/cdc/DataSourceUtil.java @@ -16,7 +16,7 @@ package com.alibaba.polardbx.qatest.cdc; -import org.springframework.jdbc.support.JdbcUtils; +import com.alibaba.polardbx.qatest.util.JdbcUtil; import java.sql.Connection; import java.sql.ResultSet; @@ -30,9 +30,9 @@ public class DataSourceUtil { private final static int QUERY_TIMEOUT = 7200; public static void closeQuery(ResultSet rs, Statement stmt, Connection conn) { - JdbcUtils.closeResultSet(rs); - JdbcUtils.closeStatement(stmt); - JdbcUtils.closeConnection(conn); + JdbcUtil.close(rs); + JdbcUtil.close(stmt); + JdbcUtil.closeConnection(conn); } public static ResultSet query(Connection conn, String sql, int fetchSize) diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/AnalyzeUseColumnarTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/AnalyzeUseColumnarTest.java new file mode 100644 index 000000000..b036decd5 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/AnalyzeUseColumnarTest.java @@ -0,0 +1,123 @@ +package com.alibaba.polardbx.qatest.columnar.dql; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.google.common.truth.Truth; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class AnalyzeUseColumnarTest extends DDLBaseNewDBTestCase { + private static String TABLE_DEFINITION_FORMAT = "CREATE TABLE `%s` (\n" + + "\t`id` bigint(20) NOT NULL AUTO_INCREMENT,\n" + + "\t`a` int(32) UNSIGNED DEFAULT NULL,\n" + + "\t`b` int(32) UNSIGNED DEFAULT NULL,\n" + + "\t`c` int(32) UNSIGNED DEFAULT NULL,\n" + + "\tprimary key(id),\n" + + "\tkey idx_a(a),\n" + + "\tkey idx_b(b),\n" + + "\tkey idx_c(c)\n" + + ") partition by key(id) partitions 8"; + + private static String CREATE_COL_IDX = SKIP_WAIT_CCI_CREATION_HINT + + "create clustered columnar index `%s` on %s(`%s`) partition by hash(`%s`) partitions 4"; + + String tableName = "tb1"; + String colIdxA = "colIdx_a"; + String colA = "a"; + + String ANALYZE = "analyze table " + tableName; + String ANALYZE_UPDATE = + "/*+TDDL:cmd_extra(" + ConnectionParams.ANALYZE_TEST_UPDATE + "=true)*/ analyze table " + tableName; + + String ANALYZE_UPDATE_ROW = "/*+TDDL:cmd_extra(" + + ConnectionParams.ANALYZE_TEST_UPDATE + "=true " + + ConnectionParams.ENABLE_MPP_NDV_USE_COLUMNAR + "=false " + + ")*/ analyze table " + tableName; + + String TIME = + "select max(UNIX_TIMESTAMP(gmt_modified)) from metadb.ndv_sketch_statistics where schema_name='%s' and table_name='%s'"; + + String LEN = + "select max(length(sketch_bytes)) from metadb.ndv_sketch_statistics where schema_name='%s' and table_name='%s'"; + + public boolean usingNewPartDb() { + return true; + } + + @After + public void dropTable() { + JdbcUtil.dropTable(getTddlConnection1(), tableName); + } + + @Before + public void prepareTable() { + JdbcUtil.dropTable(getTddlConnection1(), tableName); + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(TABLE_DEFINITION_FORMAT, tableName)); + JdbcUtil.executeSuccess(getTddlConnection1(), + String.format("insert into %s(a,b,c) values(1,2,3),(4,5,6)", tableName)); + ColumnarUtils.createColumnarIndex(getTddlConnection1(), colIdxA, tableName, colA, colA, 4); + } + + @Test + public void testAnalyze() throws SQLException, InterruptedException { + try (Connection conn = getPolardbxConnection(tddlDatabase1)) { + JdbcUtil.executeSuccess(conn, ANALYZE); + long time = getUpdateTime(); + Truth.assertThat(getByteLength()).isEqualTo(1L); + + JdbcUtil.executeSuccess(conn, ANALYZE_UPDATE); + Truth.assertThat(getUpdateTime()).isEqualTo(time); + Truth.assertThat(getByteLength()).isEqualTo(1L); + + JdbcUtil.executeSuccess(conn, "set global " + ConnectionProperties.STATISTIC_NDV_SKETCH_EXPIRE_TIME + "=1"); + Thread.sleep(3000L); + + JdbcUtil.executeSuccess(conn, ANALYZE_UPDATE); + Truth.assertThat(getUpdateTime()).isGreaterThan(time); + Truth.assertThat(getByteLength()).isEqualTo(1L); + time = getUpdateTime(); + + Thread.sleep(1000L); + JdbcUtil.executeSuccess(conn, ANALYZE_UPDATE_ROW); + Truth.assertThat(getUpdateTime()).isGreaterThan(time); + Truth.assertThat(getByteLength()).isGreaterThan(1L); + } finally { + JdbcUtil.executeSuccess(tddlConnection, "set global " + + ConnectionProperties.STATISTIC_NDV_SKETCH_EXPIRE_TIME + "=" + + ConnectionParams.STATISTIC_NDV_SKETCH_EXPIRE_TIME.getDefault()); + } + + } + + long getUpdateTime() { + try (ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, + String.format(TIME, tddlDatabase1, tableName))) { + if (rs.next()) { + return rs.getLong(1); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + return -1; + } + + long getByteLength() { + try ( + ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, String.format(LEN, tddlDatabase1, tableName))) { + if (rs.next()) { + return rs.getLong(1); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + return -1; + } + +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarCheckSnapshotTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarCheckSnapshotTest.java new file mode 100644 index 000000000..e93aef3c7 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarCheckSnapshotTest.java @@ -0,0 +1,112 @@ +package com.alibaba.polardbx.qatest.columnar.dql; + +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class ColumnarCheckSnapshotTest extends ColumnarReadBaseTestCase { + + private static final String TABLE_1 = "test_check_snapshot"; + private static final String CREATE_TABLE = + "create table %s (c1 int primary key, c2 varchar(255)) partition by hash(c1)"; + private static final String DROP_TABLE = "drop table if exists %s"; + private static final String INSERT_DATA = "insert into %s values (%s, '%s')"; + private static final String CHECK_SNAPSHOT = "check columnar snapshot %s"; + private static final int PART_COUNT = 4; + + @Before + public void prepareTable() throws SQLException { + dropTable(); + + try (Connection tddlConnection = getColumnarConnection()) { + String sql = String.format(CREATE_TABLE, TABLE_1); + JdbcUtil.executeSuccess(tddlConnection, sql); + for (int i = 0; i < 100; ++i) { + JdbcUtil.executeSuccess(tddlConnection, String.format(INSERT_DATA, TABLE_1, i, i)); + } + ColumnarUtils.createColumnarIndex(tddlConnection, "col_" + TABLE_1, TABLE_1, + "c1", "c1", PART_COUNT); + for (int i = 100; i < 200; ++i) { + JdbcUtil.executeSuccess(tddlConnection, String.format(INSERT_DATA, TABLE_1, i, i)); + } + } + } + + @After + public void dropTable() throws SQLException { + try (Connection tddlConnection = getColumnarConnection()) { + JdbcUtil.executeSuccess(tddlConnection, String.format(DROP_TABLE, TABLE_1)); + } + } + + @Test + public void testCheckSnapshot() throws SQLException { + try (Connection tddlConnection = getColumnarConnection()) { + String sql = String.format(CHECK_SNAPSHOT, TABLE_1); + try (ResultSet rs = JdbcUtil.executeQuery(sql, tddlConnection)) { + int rowCount = 0; + while (rs.next()) { + ++rowCount; + Assert.assertEquals("OK", rs.getString("Result")); + Assert.assertEquals("", rs.getString("Diff")); + Assert.assertEquals("NONE", rs.getString("Advice")); + } + Assert.assertEquals(PART_COUNT, rowCount); + } + + String tableId = null; + sql = "show columnar status"; + try (ResultSet rs = JdbcUtil.executeQuery(sql, tddlConnection)) { + while (rs.next()) { + String schemaName = rs.getString("SCHEMA_NAME"); + String tableName = rs.getString("TABLE_NAME"); + if (schemaName.equalsIgnoreCase(DB_NAME) && tableName.equalsIgnoreCase(TABLE_1)) { + tableId = rs.getString("ID"); + break; + } + } + } + + Assert.assertNotNull(tableId); + String partitionName = "p1"; + // inject failure + sql = String.format( + "update metadb.files set file_name = concat('fake_', file_name) where logical_schema_name='%s' and logical_table_name='%s' and file_type='TABLE_FILE' and partition_name='%s'", + DB_NAME, tableId, partitionName); + JdbcUtil.executeSuccess(tddlConnection, sql); + + sql = String.format(CHECK_SNAPSHOT, TABLE_1); + boolean partitionMatch = false; + try (ResultSet rs = JdbcUtil.executeQuery(sql, tddlConnection)) { + while (rs.next()) { + if (partitionName.equalsIgnoreCase(rs.getString("Partition_Name"))) { + partitionMatch = true; + if ("Found inconsistent snapshot".equalsIgnoreCase(rs.getString("Result"))) { + Assert.assertEquals("RELOAD COLUMNARMANAGER SNAPSHOT", rs.getString("Advice")); + String diff = rs.getString("Diff"); + Assert.assertTrue(diff.contains("expected but not present orc: [fake_")); + Assert.assertTrue(diff.contains("present but not expected orc: [" + DB_NAME)); + } + } + } + } + Assert.assertTrue(partitionMatch); + + // restore + sql = String.format( + "update metadb.files set file_name = SUBSTRING(file_name, 6) where logical_schema_name='%s' and logical_table_name='%s' and file_type='TABLE_FILE' and partition_name='%s'", + DB_NAME, tableId, partitionName); + JdbcUtil.executeSuccess(tddlConnection, sql); + JdbcUtil.executeSuccess(tddlConnection, "RELOAD COLUMNARMANAGER SNAPSHOT"); + sql = String.format(CHECK_SNAPSHOT, TABLE_1); + JdbcUtil.executeSuccess(tddlConnection, sql); + } + } + +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarFlashbackQueryTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarFlashbackQueryTest.java new file mode 100644 index 000000000..e95f0ad46 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarFlashbackQueryTest.java @@ -0,0 +1,145 @@ +package com.alibaba.polardbx.qatest.columnar.dql; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.qatest.constant.GsiConstant; +import com.alibaba.polardbx.qatest.data.ExecuteTableSelect; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.alibaba.polardbx.qatest.validator.DataValidator; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.stream.Collectors; + +import static com.alibaba.polardbx.qatest.columnar.dql.FullTypeTest.waitForSync; + +@RunWith(Parameterized.class) +public class ColumnarFlashbackQueryTest extends ColumnarReadBaseTestCase { + private final String sourceTable; + private final String cciName; + private final String targetName; + private static final long UPDATE_OFFSET = 1000000; + + // insert select ENUM 非法值导致报错的已知问题,先忽略 + private static final String NOT_SUPPORTED_ENUM = "(id,c_enum) values(null,'00');"; + + // bit(64) 类型的已知问题,先忽略 + private static final String NOT_SUPPORTED_C_BIT_64 = "(id,c_bit_64) values(null,18446744073709551615);"; + + private final String partDef; + private final int cciPartCount; + + @Parameterized.Parameters(name = "{index}:partDef={0},cciPartCount={1},number={2}") + public static Object[][] data() { + return new Object[][] { + {ExecuteTableSelect.DEFAULT_NEW_PARTITIONING_DEFINITION, 1, 0}, + {ExecuteTableSelect.DEFAULT_NEW_PARTITIONING_DEFINITION, 4, 1}, + {" single", 1, 2}, + {" single", 4, 3}, + }; + } + + public ColumnarFlashbackQueryTest(String partDef, int cciPartCount, int caseNumber) { + this.partDef = partDef; + this.cciPartCount = cciPartCount; + this.sourceTable = "insert_select_source_" + caseNumber; + this.cciName = sourceTable + "_cci"; + this.targetName = "insert_select_target_" + caseNumber; + } + + @Before + public void prepareTable() { + // prepare source table + JdbcUtil.dropTable(tddlConnection, sourceTable); + JdbcUtil.executeUpdateSuccess(tddlConnection, + ExecuteTableSelect.getFullTypeTableDef(sourceTable, partDef)); + + for (String sql : GsiConstant.buildGsiFullTypeTestInserts(sourceTable) + .values().stream().flatMap(List::stream).collect(Collectors.toList())) { + if (sql.contains(NOT_SUPPORTED_ENUM) || sql.contains(NOT_SUPPORTED_C_BIT_64)) { + continue; + } + JdbcUtil.executeUpdate(tddlConnection, sql, true, true); + } + + ColumnarUtils.createColumnarIndex(tddlConnection, + cciName, sourceTable, "id", "id", cciPartCount); + + // prepare target table + JdbcUtil.dropTable(tddlConnection, targetName); + JdbcUtil.executeUpdateSuccess(tddlConnection, + ExecuteTableSelect.getFullTypeTableDef(targetName, partDef)); + } + + @Test + public void testInsertSelect() throws InterruptedException, SQLException { + long oldTso = ColumnarUtils.columnarFlushAndGetTso(tddlConnection); + Assert.assertTrue(oldTso > 0, "Failed to flush columnar snapshot"); + JdbcUtil.executeUpdateSuccess(tddlConnection, + String.format("update %s set c_bigint_64 = id + %d", sourceTable, UPDATE_OFFSET)); + waitForSync(tddlConnection); + + checkFlashbackQueryOldResult(oldTso); + + // insert select from source table for old data + JdbcUtil.executeUpdateSuccess(tddlConnection, + String.format("insert into %s select * from %s as of tso %d force index(%s)", + targetName, sourceTable, oldTso, cciName)); + + DataValidator.selectContentSameAssertWithDiffSql( + String.format("select * from %s", targetName), + String.format("select * from %s as of tso %d force index(%s)", sourceTable, oldTso, cciName), + null, tddlConnection, tddlConnection, false, false, false + ); + } + + @Test + public void testReplaceSelect() throws InterruptedException, SQLException { + long oldTso = ColumnarUtils.columnarFlushAndGetTso(tddlConnection); + Assert.assertTrue(oldTso > 0, "Failed to flush columnar snapshot"); + JdbcUtil.executeUpdateSuccess(tddlConnection, + String.format("update %s set c_bigint_64 = id + %d", sourceTable, UPDATE_OFFSET)); + waitForSync(tddlConnection); + + checkFlashbackQueryOldResult(oldTso); + + // prepare target table for existed data + JdbcUtil.executeUpdateSuccess(tddlConnection, + String.format("insert into %s select * from %s", targetName, sourceTable)); + JdbcUtil.executeUpdateSuccess(tddlConnection, + String.format("update %s set c_bigint_64 = %d", targetName, UPDATE_OFFSET)); + + // insert select from source table for old data + JdbcUtil.executeUpdateSuccess(tddlConnection, + String.format("replace into %s select * from %s as of tso %d force index(%s)", + targetName, sourceTable, oldTso, cciName)); + + DataValidator.selectContentSameAssertWithDiffSql( + String.format("select * from %s", targetName), + String.format("select * from %s as of tso %d force index(%s)", sourceTable, oldTso, cciName), + null, tddlConnection, tddlConnection, false, false, false + ); + } + + @After + public void dropTable() { + JdbcUtil.dropTable(tddlConnection, sourceTable); + JdbcUtil.dropTable(tddlConnection, targetName); + } + + private void checkFlashbackQueryOldResult(long oldTso) throws SQLException { + ResultSet rs = JdbcUtil.executeQuery( + String.format("select c_bigint_64 from %s as of tso %d force index(%s)", sourceTable, oldTso, + cciName), + tddlConnection + ); + while (rs.next()) { + Assert.assertTrue(rs.getLong("c_bigint_64") < UPDATE_OFFSET); + } + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarReadBaseTestCase.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarReadBaseTestCase.java index dfffdface..43826ef0f 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarReadBaseTestCase.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarReadBaseTestCase.java @@ -22,7 +22,7 @@ public static void beforeClass() throws SQLException { } @Before - public void before() { + final public void before() { JdbcUtil.useDb(tddlConnection, DB_NAME); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarSnapshotTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarSnapshotTest.java new file mode 100644 index 000000000..b45eec1de --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarSnapshotTest.java @@ -0,0 +1,133 @@ +package com.alibaba.polardbx.qatest.columnar.dql; + +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class ColumnarSnapshotTest extends ColumnarReadBaseTestCase { + private static final String TABLE_NAME = "ColumnarSnapshotTest_t1"; + private static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS `" + TABLE_NAME + "` ( \n" + + "id int primary key,\n" + + "a int,\n" + + "gmt_created timestamp not null default current_timestamp,\n" + + "gmt_modified timestamp not null default current_timestamp on update current_timestamp\n" + + ") partition by key(id)"; + private static final String TMP_TABLE_NAME = TABLE_NAME + "_tmp"; + private static final String CREATE_TMP_TABLE = "create table if not exists " + TMP_TABLE_NAME + " (\n" + + " id int primary key,\n" + + " a int,\n" + + " gmt_created timestamp not null default current_timestamp,\n" + + " gmt_modified timestamp not null default current_timestamp on update current_timestamp\n" + + ") partition by key(id)"; + private static final String CALL_COLUMNAR_FLUSH = "CALL polardbx.columnar_flush('%s', '%s', '%s')"; + private static final String CALL_COLUMNAR_FLUSH_GLOBAL = "CALL polardbx.columnar_flush()"; + + @Before + public void setUp() { + JdbcUtil.dropTable(tddlConnection, TABLE_NAME); + JdbcUtil.dropTable(tddlConnection, TMP_TABLE_NAME); + JdbcUtil.executeUpdateSuccess(tddlConnection, CREATE_TABLE); + JdbcUtil.executeUpdateSuccess(tddlConnection, CREATE_TMP_TABLE); + JdbcUtil.executeUpdateSuccess(tddlConnection, + "delete from metadb.columnar_config where table_id = 0 and config_key = 'SNAPSHOT_RETENTION_DAYS'"); + JdbcUtil.executeUpdateSuccess(tddlConnection, + "delete from metadb.columnar_config where table_id = 0 and config_key = 'AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL'"); + } + + @After + public void tearDown() { + JdbcUtil.dropTable(tddlConnection, TABLE_NAME); + JdbcUtil.dropTable(tddlConnection, TMP_TABLE_NAME); + } + + @Test + public void testSimple() throws SQLException, InterruptedException { + String sql = "create clustered columnar index cci on " + TABLE_NAME + "(a) partition by key(id) " + + " engine='EXTERNAL_DISK' " + + " columnar_options='{" + + " \"type\":\"snapshot\", " + + " \"snapshot_retention_days\":\"7\"" + + " }'"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, "show full create table " + TABLE_NAME); + String tableDef = null; + if (rs.next()) { + tableDef = rs.getString(2); + } + System.out.println(tableDef); + Assert.assertNotNull(tableDef); + Assert.assertTrue(tableDef.contains("\"TYPE\":\"SNAPSHOT\"")); + Assert.assertTrue(tableDef.contains("\"SNAPSHOT_RETENTION_DAYS\":\"7\"")); + Assert.assertTrue(tableDef.contains("\"AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL\":\"-1\"")); + + sql = "INSERT INTO " + TABLE_NAME + " (id, a) values (0, 0), (1, 0)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, "set transaction_policy = TSO"); + JdbcUtil.executeUpdateSuccess(tddlConnection, "begin"); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + JdbcUtil.executeUpdateSuccess(tddlConnection, "commit"); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, + String.format(CALL_COLUMNAR_FLUSH, DB_NAME, TABLE_NAME, "cci")); + Assert.assertTrue(rs.next()); + long tso0 = rs.getLong(1); + waitColumnarFlush(tso0); + + sql = "UPDATE " + TABLE_NAME + " SET a = 100 where 1=1"; + JdbcUtil.executeUpdateSuccess(tddlConnection, "set transaction_policy = TSO"); + JdbcUtil.executeUpdateSuccess(tddlConnection, "begin"); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + JdbcUtil.executeUpdateSuccess(tddlConnection, "commit"); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, CALL_COLUMNAR_FLUSH_GLOBAL); + Assert.assertTrue(rs.next()); + long tso1 = rs.getLong(1); + waitColumnarFlush(tso1); + + sql = "UPDATE " + TABLE_NAME + " SET a = 200 where 1=1"; + JdbcUtil.executeUpdateSuccess(tddlConnection, "begin"); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + JdbcUtil.executeUpdateSuccess(tddlConnection, "commit"); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "select sum(a) from " + TABLE_NAME + + " as of tso " + tso0 + " force index(cci)"); + Assert.assertTrue(rs.next()); + Assert.assertEquals(0, rs.getLong(1)); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "select sum(a) from " + TABLE_NAME + + " as of tso " + tso1 + " force index(cci)"); + Assert.assertTrue(rs.next()); + Assert.assertEquals(200, rs.getLong(1)); + + sql = "INSERT INTO " + TMP_TABLE_NAME + " SELECT * FROM " + TABLE_NAME + + " AS OF TSO " + tso1 + " FORCE INDEX (cci)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT sum(a) FROM " + TMP_TABLE_NAME); + Assert.assertTrue(rs.next()); + Assert.assertEquals(200, rs.getLong(1)); + } + + private void waitColumnarFlush(long tso0) throws InterruptedException, SQLException { + ResultSet rs; + int retry = 10; + boolean succeed = false; + while (retry-- > 0) { + // Wait columnar to process flush. + Thread.sleep(1000); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, + "select tso from information_schema.columnar_snapshots where tso <= " + tso0 + + " order by tso desc limit 1"); + if (rs.next() && rs.getLong(1) == tso0) { + succeed = true; + break; + } + } + + Assert.assertTrue(succeed); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarSnapshotsTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarSnapshotsTest.java new file mode 100644 index 000000000..778c1ba64 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarSnapshotsTest.java @@ -0,0 +1,73 @@ +package com.alibaba.polardbx.qatest.columnar.dql; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Test; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class ColumnarSnapshotsTest extends ColumnarReadBaseTestCase { + private static final String TABLE_NAME = "test_columnar_snapshots_xxx"; + private static final String CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + + " id int primary key auto_increment, " + + " name varchar(255), " + + " CLUSTERED COLUMNAR INDEX `my_snapshot` (`id`) partition by key(`id`) engine='EXTERNAL_DISK' " + + " columnar_options='{\"type\":\"snapshot\", \"snapshot_retention_days\":\"7\", \"auto_gen_columnar_snapshot_interval\":\"3\"}'" + + ") partition by key (id)"; + private static final String DROP_TABLE_SQL = "DROP TABLE IF EXISTS " + TABLE_NAME; + + @Test + public void testColumnarSnapshots() throws InterruptedException, SQLException { + JdbcUtil.executeUpdateSuccess(tddlConnection, DROP_TABLE_SQL); + JdbcUtil.executeUpdateSuccess(tddlConnection, CREATE_TABLE_SQL); + String sql = "insert into " + TABLE_NAME + " (name) values ('Tom')"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + sql = "select name from " + TABLE_NAME + " force index(my_snapshot)"; + int retry = 0; + boolean found = false; + do { + ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + if (rs.next() && "Tom".equalsIgnoreCase(rs.getString(1))) { + found = true; + break; + } + Thread.sleep(1000); + } while (retry++ < 10); + Assert.assertTrue(found); + + sql = "select tso_timestamp()"; + ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + Assert.assertTrue(rs.next()); + long tso0 = rs.getLong(1); + + sql = "call polardbx.COLUMNAR_GENERATE_SNAPSHOTS()"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "select tso_timestamp()"; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + Assert.assertTrue(rs.next()); + long tso1 = rs.getLong(1); + + sql = "update " + TABLE_NAME + " set name = 'Jerry' where 1=1"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + retry = 0; + found = false; + do { + sql = "SELECT tso FROM INFORMATION_SCHEMA.COLUMNAR_SNAPSHOTS where TSO > " + tso0 + " and TSO < " + tso1; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + if (rs.next()) { + found = true; + break; + } + } while (retry++ < 10); + Assert.assertTrue(found); + long tso2 = rs.getLong(1); + + sql = "select name from " + TABLE_NAME + " as of tso " + tso2 + " force index(my_snapshot)"; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + Assert.assertTrue(rs.next()); + Assert.assertTrue("Tom".equalsIgnoreCase(rs.getString(1))); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarUtils.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarUtils.java index 5384ccdc3..7d694b75d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarUtils.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ColumnarUtils.java @@ -7,6 +7,7 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; public class ColumnarUtils { private static final String SHOW_COLUMNAR_OFFSET = "show columnar offset"; @@ -85,6 +86,36 @@ public static long getColumnarOffset(Connection tddlConnection) { throw new RuntimeException("get columnar offset failed"); } + public static long getColumnarTso(Connection tddlConnection) { + try (ResultSet rs = JdbcUtil.executeQuery(SHOW_COLUMNAR_OFFSET, tddlConnection)) { + while (rs.next()) { + String type = rs.getString("type"); + long tso = rs.getLong("tso"); + if (type.equalsIgnoreCase("COLUMNAR_LATENCY")) { + return tso; + } + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + throw new RuntimeException("get columnar offset failed"); + } + + static public long columnarFlushAndGetTso(Statement stmt) throws SQLException { + ResultSet rs = stmt.executeQuery("call polardbx.columnar_flush()"); + if (rs.next()) { + return rs.getLong(1); + } else { + return -1; + } + } + + static public long columnarFlushAndGetTso(Connection connection) throws SQLException { + try (Statement statement = connection.createStatement()) { + return columnarFlushAndGetTso(statement); + } + } + public static Pair getInnodbAndColumnarOffset(Connection tddlConnection) { long innodbOffset = 0, columnarOffset = -1; try (ResultSet rs = JdbcUtil.executeQuery(SHOW_COLUMNAR_OFFSET, tddlConnection)) { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ExchangePartitionPruningTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ExchangePartitionPruningTest.java index 7a95e2d45..8f2e411ab 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ExchangePartitionPruningTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ExchangePartitionPruningTest.java @@ -1,6 +1,7 @@ package com.alibaba.polardbx.qatest.columnar.dql; import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.qatest.ColumnarIgnore; import com.alibaba.polardbx.qatest.util.JdbcUtil; import org.junit.After; import org.junit.Before; @@ -9,6 +10,7 @@ import java.sql.ResultSet; import java.sql.SQLException; +@ColumnarIgnore // close #58321033 public class ExchangePartitionPruningTest extends ColumnarReadBaseTestCase { private static final String TABLE_1 = "test_exchange_prune_1"; private static final String TABLE_2 = "test_exchange_prune_2"; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ForceIndexTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ForceIndexTest.java new file mode 100644 index 000000000..5ade84852 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/ForceIndexTest.java @@ -0,0 +1,119 @@ +package com.alibaba.polardbx.qatest.columnar.dql; + +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class ForceIndexTest extends ColumnarReadBaseTestCase { + @Test + public void testSingleTable() throws SQLException, InterruptedException { + final String tableName = "force_index_test_single"; + final String indexName = "force_index_test_single_cci"; + final String createTable = "create table if not exists " + tableName + " (id int primary key, a int) single"; + JdbcUtil.dropTable(tddlConnection, tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, createTable); + String sql = "insert into " + tableName + " values (0, 0), (1, 1), (2, 2)"; + JdbcUtil.executeUpdateSuccessInTrx(tddlConnection, sql); + ColumnarUtils.createColumnarIndex(tddlConnection, indexName, tableName, "a", "a", 3); + sql = "insert into " + tableName + " values (10, 10), (11, 11), (12, 12)"; + JdbcUtil.executeUpdateSuccessInTrx(tddlConnection, sql); + + // simple select + sql = "select count(a) from %s force index (%s)"; + ResultSet rs; + boolean success = false; + int retry = 0; + do { + rs = JdbcUtil.executeQuerySuccess(tddlConnection, String.format(sql, tableName, indexName)); + Assert.assertTrue(rs.next()); + if (rs.getLong(1) == 6) { + success = true; + break; + } + Thread.sleep(1000); + } while (retry++ < 10); + Assert.assertTrue(success); + + // get tso 0 + sql = "select tso_timestamp()"; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + Assert.assertTrue(rs.next()); + long tso0 = rs.getLong(1); + + // insert more data + sql = "insert into " + tableName + " values (100, 100), (111, 111), (112, 112)"; + JdbcUtil.executeUpdateSuccessInTrx(tddlConnection, sql); + + sql = "select count(a) from %s force index (%s)"; + success = false; + retry = 0; + do { + rs = JdbcUtil.executeQuerySuccess(tddlConnection, String.format(sql, tableName, indexName)); + Assert.assertTrue(rs.next()); + if (rs.getLong(1) == 9) { + success = true; + break; + } + Thread.sleep(1000); + } while (retry++ < 10); + Assert.assertTrue(success); + + // get tso 1 + sql = "select tso_timestamp()"; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + Assert.assertTrue(rs.next()); + long tso1 = rs.getLong(1); + + // insert select + final String targetTable = "force_index_test_single_target"; + final String targetPartitionedTable = "force_index_test_single_target_partitioned"; + JdbcUtil.dropTable(tddlConnection, targetTable); + JdbcUtil.dropTable(tddlConnection, targetPartitionedTable); + sql = "create table if not exists " + targetTable + " (id int primary key, a int) single"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + sql = "create table if not exists " + targetPartitionedTable + + " (id int primary key, a int) partition by key(id)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + sql = "insert into %s select * from %s force index(%s)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, targetTable, tableName, indexName)); + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, targetPartitionedTable, tableName, indexName)); + sql = "select count(0) from " + targetTable; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + Assert.assertTrue(rs.next()); + Assert.assertEquals(9, rs.getLong(1)); + sql = "select count(0) from " + targetPartitionedTable; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + Assert.assertTrue(rs.next()); + Assert.assertEquals(9, rs.getLong(1)); + + // flashback + sql = "select count(a) from %s as of tso %s force index(%s)"; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, String.format(sql, tableName, tso0, indexName)); + Assert.assertTrue(rs.next()); + Assert.assertEquals(6, rs.getLong(1)); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, String.format(sql, tableName, tso1, indexName)); + Assert.assertTrue(rs.next()); + Assert.assertEquals(9, rs.getLong(1)); + + // replace select flashback + sql = "delete from " + targetTable; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + sql = "delete from " + targetPartitionedTable; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + sql = "replace into %s select * from %s as of tso %s force index(%s)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, targetTable, tableName, tso0, indexName)); + JdbcUtil.executeUpdateSuccess(tddlConnection, + String.format(sql, targetPartitionedTable, tableName, tso0, indexName)); + sql = "select count(0) from " + targetTable; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + Assert.assertTrue(rs.next()); + Assert.assertEquals(6, rs.getLong(1)); + sql = "select count(0) from " + targetPartitionedTable; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + Assert.assertTrue(rs.next()); + Assert.assertEquals(6, rs.getLong(1)); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/FullTypeTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/FullTypeTest.java index 336c29e98..abb6e4c83 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/FullTypeTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/FullTypeTest.java @@ -27,7 +27,7 @@ public class FullTypeTest extends ColumnarReadBaseTestCase { public static String COLUMNAR_INDEX_NAME = "full_type_index"; @Before - public void before() { + public void prepareTable() { JdbcUtil.dropTable(tddlConnection, PRIMARY_TABLE_NAME); JdbcUtil.executeUpdateSuccess(tddlConnection, ExecuteTableSelect.getFullTypeTableDef(PRIMARY_TABLE_NAME, diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/InformationSchemaColumnarIndexStatusTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/InformationSchemaColumnarIndexStatusTest.java index cdbf2d24c..546091afe 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/InformationSchemaColumnarIndexStatusTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/InformationSchemaColumnarIndexStatusTest.java @@ -6,6 +6,7 @@ import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import java.sql.Connection; @@ -16,6 +17,7 @@ import static com.alibaba.polardbx.qatest.columnar.dql.FullTypeTest.waitForSync; import static com.alibaba.polardbx.qatest.util.PropertiesUtil.polardbXAutoDBName1; +@Ignore public class InformationSchemaColumnarIndexStatusTest extends ReadBaseTestCase { private static final String TABLE_1 = "test_columnar_index_status_1"; private static final String TABLE_2 = "test_columnar_index_status_2"; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/SelectColumnarFileTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/SelectColumnarFileTest.java new file mode 100644 index 000000000..0803cad9d --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/SelectColumnarFileTest.java @@ -0,0 +1,130 @@ +package com.alibaba.polardbx.qatest.columnar.dql; + +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class SelectColumnarFileTest extends ColumnarReadBaseTestCase { + + private static final String TABLE_1 = "select_columnar_file_test"; + private static final String CREATE_TABLE = + "create table %s (c1 int primary key, c2 varchar(255)) partition by hash(c1)"; + private static final String DROP_TABLE = "drop table if exists %s"; + private static final String INSERT_DATA = "insert into %s values (%s, '%s')"; + private static final String DELETE_DATA = "delete from %s where c1 = %s"; + private static final int PART_COUNT = 4; + + @Before + public void prepareTable() throws SQLException { + dropTable(); + + try (Connection tddlConnection = getColumnarConnection()) { + String sql = String.format(CREATE_TABLE, TABLE_1); + JdbcUtil.executeSuccess(tddlConnection, sql); + for (int i = 0; i < 100; ++i) { + JdbcUtil.executeSuccess(tddlConnection, String.format(INSERT_DATA, TABLE_1, i, i)); + } + ColumnarUtils.createColumnarIndex(tddlConnection, "col_" + TABLE_1, TABLE_1, + "c1", "c1", PART_COUNT); + for (int i = 100; i < 200; ++i) { + JdbcUtil.executeSuccess(tddlConnection, String.format(INSERT_DATA, TABLE_1, i, i)); + } + for (int i = 0; i < 100; ++i) { + JdbcUtil.executeSuccess(tddlConnection, String.format(DELETE_DATA, TABLE_1, i)); + } + ColumnarUtils.waitColumnarOffset(tddlConnection); + } + } + + @After + public void dropTable() throws SQLException { + try (Connection tddlConnection = getColumnarConnection()) { + JdbcUtil.executeSuccess(tddlConnection, String.format(DROP_TABLE, TABLE_1)); + } + } + + @Test + public void test() throws SQLException { + String partitionName = "p1"; + String sql; + String tableId = null; + + String csvFileName = null; + String orcFileName = null; + String delFileName = null; + + try (Connection tddlConnection = getColumnarConnection()) { + sql = "show columnar status"; + try (ResultSet rs = JdbcUtil.executeQuery(sql, tddlConnection)) { + while (rs.next()) { + String schemaName = rs.getString("SCHEMA_NAME"); + String tableName = rs.getString("TABLE_NAME"); + if (schemaName.equalsIgnoreCase(DB_NAME) && tableName.equalsIgnoreCase(TABLE_1)) { + tableId = rs.getString("ID"); + break; + } + } + } + + JdbcUtil.executeSuccess(tddlConnection, "RELOAD COLUMNARMANAGER"); + JdbcUtil.executeSuccess(tddlConnection, "RELOAD COLUMNARMANAGER CACHE"); + JdbcUtil.executeSuccess(tddlConnection, "RELOAD COLUMNARMANAGER SNAPSHOT"); + JdbcUtil.executeSuccess(tddlConnection, "RELOAD COLUMNARMANAGER SCHEMA"); + + Assert.assertNotNull(tableId); + sql = String.format( + "select file_name from metadb.files where logical_schema_name='%s' and logical_table_name='%s' and file_type='TABLE_FILE' and partition_name='%s'", + DB_NAME, tableId, partitionName); + + try (ResultSet rs = JdbcUtil.executeQuery(sql, tddlConnection)) { + while (rs.next()) { + String fileName = rs.getString("file_name"); + if (fileName.endsWith(".csv")) { + csvFileName = fileName; + } else if (fileName.endsWith(".orc")) { + orcFileName = fileName; + } else if (fileName.endsWith(".del")) { + delFileName = fileName; + } + } + } + + Assert.assertNotNull(csvFileName); + Assert.assertNotNull(orcFileName); + Assert.assertNotNull(delFileName); + + // TODO(siyun): select orc file content + JdbcUtil.executeSuccess(tddlConnection, String.format("select columnar_file('%s')", orcFileName)); + + int lineCount = 0; + try (ResultSet rs = + JdbcUtil.executeQuery(String.format("select columnar_file('%s')", csvFileName), tddlConnection)) { + while (rs.next()) { + int position = Integer.parseInt(rs.getString(2)); + Assert.assertEquals(lineCount++, position); + Assert.assertEquals(rs.getString(3), rs.getString(4)); + } + } + Assert.assertTrue(lineCount > 0); + + lineCount = 0; + try (ResultSet rs = + JdbcUtil.executeQuery(String.format("select columnar_file('%s')", delFileName), tddlConnection)) { + while (rs.next()) { + String bitmapString = rs.getString(3); + for (String deletePos : bitmapString.substring(1, bitmapString.length() - 1).split(",")) { + Assert.assertEquals(lineCount++, Integer.parseInt(deletePos)); + } + } + } + Assert.assertTrue(lineCount > 0); + } + } + +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/SimpleColumnarCollationTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/SimpleColumnarCollationTest.java index cba501cb2..fbd1b9e5f 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/SimpleColumnarCollationTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/SimpleColumnarCollationTest.java @@ -155,6 +155,47 @@ public void useDb() { } @Test + public void testAll() { + List allExceptions = new ArrayList<>(); + try { + testFilter(); + } catch (Throwable t) { + allExceptions.add(t); + } + try { + testProject(); + } catch (Throwable t) { + allExceptions.add(t); + } + try { + testAgg(); + } catch (Throwable t) { + allExceptions.add(t); + } + try { + testJoin(); + } catch (Throwable t) { + allExceptions.add(t); + } + try { + testPairWiseJoin(); + } catch (Throwable t) { + allExceptions.add(t); + } + try { + testSort(); + } catch (Throwable t) { + allExceptions.add(t); + } + + if (!allExceptions.isEmpty()) { + for (Throwable t : allExceptions) { + t.printStackTrace(); + } + throw new RuntimeException(allExceptions.get(0)); + } + } + public void testFilter() { String sql = "select * from %s where c2 = 'nihaore'"; DataValidator.selectContentSameAssert(String.format(sql, table1), null, mysqlConnection, tddlConnection); @@ -162,7 +203,6 @@ public void testFilter() { DataValidator.selectContentSameAssert(String.format(sql, table3), null, mysqlConnection, tddlConnection); } - @Test public void testProject() { String sql = "select concat(c2, 'test') from %s where c2 = 'nihaore'"; DataValidator.selectContentSameAssert(String.format(sql, table1), null, mysqlConnection, tddlConnection); @@ -170,7 +210,6 @@ public void testProject() { DataValidator.selectContentSameAssert(String.format(sql, table3), null, mysqlConnection, tddlConnection); } - @Test public void testAgg() { String sql = "select count(*) from %s group by c2"; DataValidator.selectContentSameAssert(String.format(sql, table1), null, mysqlConnection, tddlConnection); @@ -178,7 +217,6 @@ public void testAgg() { DataValidator.selectContentSameAssert(String.format(sql, table3), null, mysqlConnection, tddlConnection); } - @Test public void testJoin() { String sql = "select * from %s %s join %s on %s.c2 = %s.c2"; DataValidator.selectContentSameAssert(String.format(sql, table1, "inner", table2, table1, table2), null, @@ -189,7 +227,6 @@ public void testJoin() { mysqlConnection, tddlConnection); } - @Test public void testPairWiseJoin() { String sql = "/*+TDDL:cmd_extra(ENABLE_BROADCAST_JOIN=false)*/ select * from %s %s join %s on %s.c2 = %s.c2"; checkPairWiseJoin(String.format(sql, table1, "inner", table3, table1, table3)); @@ -205,7 +242,6 @@ private void checkPairWiseJoin(String sql) { && StringUtils.countMatches(explain, "exchange") == 1, "but was " + explain); } - @Test public void testSort() throws SQLException { String sql = "select c2 from %s where c2 in ('a', 'b') order by c2 "; checkSortResult(tddlConnection, String.format(sql, table1)); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/TimestampWithTimeZoneTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/TimestampWithTimeZoneTest.java index 3cd746846..3817c126b 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/TimestampWithTimeZoneTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/TimestampWithTimeZoneTest.java @@ -14,7 +14,7 @@ public class TimestampWithTimeZoneTest extends ColumnarReadBaseTestCase { public static String COLUMNAR_INDEX_NAME = "time_cci"; @Before - public void before() { + public void prepareTable() { JdbcUtil.dropTable(tddlConnection, PRIMARY_TABLE_NAME); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/explain/ExplainAnalyzeTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/explain/ExplainAnalyzeTest.java index 7b551ad07..17c331a3a 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/explain/ExplainAnalyzeTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/dql/explain/ExplainAnalyzeTest.java @@ -2,6 +2,7 @@ import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.qatest.ColumnarIgnore; import com.alibaba.polardbx.qatest.columnar.dql.ColumnarReadBaseTestCase; import com.alibaba.polardbx.qatest.columnar.dql.ColumnarUtils; import com.alibaba.polardbx.qatest.data.ExecuteTableSelect; @@ -27,6 +28,7 @@ import java.util.Set; import java.util.regex.Pattern; +@ColumnarIgnore // close #58321033 public class ExplainAnalyzeTest extends ColumnarReadBaseTestCase { private static final List TABLES = new ArrayList<>(); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/prune/ColumnarTracerTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/prune/ColumnarTracerTest.java new file mode 100644 index 000000000..010a62a44 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/prune/ColumnarTracerTest.java @@ -0,0 +1,58 @@ +package com.alibaba.polardbx.qatest.columnar.prune; + +import com.alibaba.polardbx.qatest.AutoReadBaseTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runners.Parameterized; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +import static com.alibaba.polardbx.qatest.data.ExecuteTableSelect.selectBaseOneTable; + +public class ColumnarTracerTest extends AutoReadBaseTestCase { + + public ColumnarTracerTest(String baseOneTableName) { + this.baseOneTableName = baseOneTableName; + } + + @Parameterized.Parameters(name = "{index}:table0={0}") + public static List prepareData() { + return Arrays.asList(selectBaseOneTable()); + } + + @Test + public void testGlobalShowPruneTracer() throws SQLException { + final String MPP_HINT = + "enable_columnar_optimizer=true enable_master_mpp=true ENABLE_HTAP=true workload_type=ap"; + String traceHINT = String.format("trace /*+TDDL: %s */", MPP_HINT); + + String sqlSelect = "select * from select_base_one_one_db_one_tb " + + "where (varchar_test= \"feed32feed\" or varchar_test in (\"nihaore\")) and (integer_test= 2 or integer_test > 3)"; + + String sqlShow = "show prune tracer"; + + //execute select sql + ResultSet rs = JdbcUtil.executeQuery(traceHINT + sqlSelect, tddlConnection); + Assert.assertTrue(rs.getMetaData().getColumnCount() == 20); + int count = 0; + while (rs.next()) { + count++; + } + rs.close(); + Assert.assertTrue(count == 93); + + //execute show prune tracer + ResultSet rsShow = JdbcUtil.executeQuery(sqlShow, tddlConnection); + int showCount = 0; + while (rsShow.next()) { + showCount++; + } + rsShow.close(); + Assert.assertTrue(showCount > 0); + } + +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/role/ColumnarRoleTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/role/ColumnarRoleTest.java index 12453f7a2..df2cf0e32 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/role/ColumnarRoleTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/columnar/role/ColumnarRoleTest.java @@ -1,11 +1,17 @@ package com.alibaba.polardbx.qatest.columnar.role; +import com.alibaba.polardbx.common.utils.Assert; import com.alibaba.polardbx.qatest.AutoReadBaseTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; import com.alibaba.polardbx.qatest.util.PropertiesUtil; import org.junit.Before; import org.junit.Test; +import java.sql.Connection; +import java.sql.ResultSet; import java.sql.SQLException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static com.alibaba.polardbx.qatest.validator.DataValidator.explainResultMatchAssert; import static com.alibaba.polardbx.qatest.validator.DataValidator.explainResultStrictMatchAssert; @@ -38,7 +44,7 @@ public void showCreateTable1() throws SQLException { + "\t`primary` int(11),\n" + "\t`key` int(11)\n" + ") ENGINE = InnoDB DEFAULT CHARACTER SET = GBK DEFAULT COLLATE = gbk_chinese_ci", 2); - } catch (Exception e) { + } catch (Throwable e) { explainResultStrictMatchAssert( "show create table table_multi_db_multi_tb;", null, tddlConnection, "CREATE TABLE `table_multi_db_multi_tb` (\n" @@ -69,7 +75,7 @@ public void showCreateTable2() throws SQLException { + "\t`gmt_modified` date,\n" + "\tPRIMARY KEY (`id`)\n" + ") ENGINE = InnoDB DEFAULT CHARACTER SET = GBK DEFAULT COLLATE = gbk_chinese_ci", 2); - } catch (Exception e) { + } catch (Throwable e) { explainResultStrictMatchAssert( "show create table tddl_test;", null, tddlConnection, "CREATE TABLE `tddl_test` (\n" @@ -97,4 +103,18 @@ public void simpleTest() throws SQLException { "server error by don't support query the table without columnar index"); } + @Test + public void showCreateTableTest() throws SQLException { + String showResult = null; + try (Connection readOnlyConn = getPolardbxConnection(PropertiesUtil.polardbXDBName1(true))) { + JdbcUtil.useDb(readOnlyConn, "drds_polarx1_part_qatest_app"); + ResultSet result = JdbcUtil.executeQuerySuccess(readOnlyConn, + "show create table update_delete_base_autonic_two_multi_db_one_tb"); + while (result.next()) { + showResult = result.getString(2); + } + } + Assert.assertTrue(showResult != null); + } + } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dal/set/SetCmdAssignmentTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dal/set/SetCmdAssignmentTest.java index d0c568025..6632c3eca 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dal/set/SetCmdAssignmentTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dal/set/SetCmdAssignmentTest.java @@ -18,6 +18,7 @@ import com.alibaba.druid.util.JdbcUtils; import com.alibaba.polardbx.qatest.DirectConnectionBaseTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; import org.apache.commons.lang.StringUtils; import org.junit.Assert; import org.junit.Ignore; @@ -147,7 +148,9 @@ public void testAsyncDDLPureMode() throws SQLException { } @Ignore - public void testTransactionPolicy() throws SQLException { + public void testTransactionPolicy() throws SQLException, InterruptedException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET GLOBAL DISABLE_LEGACY_VARIABLE = FALSE"); + Thread.sleep(1000); String variable = "TRANSACTION POLICY"; @@ -157,7 +160,17 @@ public void testTransactionPolicy() throws SQLException { String selectSql = "select @savedValue"; String selectTmpSql = "select @tmp"; - int oldValue = getIntValue(showSql, 2); + int retry = 0; + int oldValue = -1; + while (retry < 10) { + retry++; + oldValue = getIntValue(showSql, 2); + if (oldValue != -1) { + break; + } + Thread.sleep(1000); + } + try { //保存初始值到 变量@savedValue 以及 oldValue中 setVar(setVarSql); @@ -187,13 +200,15 @@ public void testTransactionPolicy() throws SQLException { String setSql = "set @@`" + variable + "` = " + oldValue; setVar(setSql); Assert.assertEquals(getIntValue(showSql, 2), oldValue); + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET GLOBAL DISABLE_LEGACY_VARIABLE = TRUE"); this.tddlConnection.close(); } } @Test - public void testTransPolicy() throws SQLException { - + public void testTransPolicy() throws SQLException, InterruptedException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET GLOBAL DISABLE_LEGACY_VARIABLE = FALSE"); + Thread.sleep(1000); String variable = "TRANS.POLICY"; String showSql = "show variables like '" + variable + "'"; @@ -203,7 +218,17 @@ public void testTransPolicy() throws SQLException { String selectTmpSql = "select @tmp"; String commitSql = "commit"; - String oldValue = getStringValue(showSql, 2); + int retry = 0; + String oldValue = null; + while (retry < 10) { + retry++; + oldValue = getStringValue(showSql, 2); + if (oldValue != null) { + break; + } + Thread.sleep(1000); + } + try { //关闭autocommit String setSql = "set @@autocommit = 0"; @@ -242,6 +267,7 @@ public void testTransPolicy() throws SQLException { Assert.assertEquals(getStringValue(showSql, 2), oldValue); setSql = "set @@autocommit = 1"; setVar(setSql); + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET GLOBAL DISABLE_LEGACY_VARIABLE = TRUE"); this.tddlConnection.close(); } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/data/ExecuteTableSelect.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/data/ExecuteTableSelect.java index 8c6c96f05..c6f108ab3 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/data/ExecuteTableSelect.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/data/ExecuteTableSelect.java @@ -94,6 +94,18 @@ public static String[][] selectBaseOneTable() { } + /** + * 查询一张表,多库多表和广播表模式 + */ + public static String[][] selectBaseOneTableBradcastAndMutilDbMutilTb() { + + String[][] object = { + {"select_base_one_" + ExecuteTableName.MUlTI_DB_MUTIL_TB_SUFFIX}, + {"select_base_one_" + ExecuteTableName.BROADCAST_TB_SUFFIX}}; + return object; + + } + // where 条件限定了只能路由到一个分库,用于此类情况的测试 public static String[][] autoTableWithWhere() { String[][] object = { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/autoNewPartition/AutoPartitionCreateWithGSI.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/autoNewPartition/AutoPartitionCreateWithGSI.java index bf9d19748..441ca5791 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/autoNewPartition/AutoPartitionCreateWithGSI.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/autoNewPartition/AutoPartitionCreateWithGSI.java @@ -99,8 +99,7 @@ public void createWithUGSITest() { + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4", showCreateTable(tddlConnection, TABLE_NAME)); Assert.assertEquals("CREATE TABLE `i_auto_with_gsi_$` (\n" + "\t`seller_id` varchar(20) DEFAULT NULL,\n" - + "\tUNIQUE KEY `auto_shard_key_seller_id` USING BTREE (`seller_id`),\n" - + "\tKEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`)\n" + + "\tUNIQUE KEY `auto_shard_key_seller_id` USING BTREE (`seller_id`)\n" + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4\n" + "PARTITION BY KEY(`seller_id`)\n" + "PARTITIONS 3", diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/AlterTableWithCciForbidTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/AlterTableWithCciForbidTest.java index 0fe0d8e1a..266bfe6a4 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/AlterTableWithCciForbidTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/AlterTableWithCciForbidTest.java @@ -22,10 +22,15 @@ import com.alibaba.polardbx.qatest.util.JdbcUtil; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class AlterTableWithCciForbidTest extends DDLBaseNewDBTestCase { private static final String FORBID_DDL_WITH_CCI = "FORBID_DDL_WITH_CCI=TRUE"; @@ -33,6 +38,7 @@ public class AlterTableWithCciForbidTest extends DDLBaseNewDBTestCase { private static final String INDEX_NAME1 = "alter_table_ddl_with_cci_err_cci_pt_1"; private static final String PRIMARY_TABLE_NAME2 = "alter_table_ddl_with_cci_err_prim_pt_2"; private static final String INDEX_NAME2 = "alter_table_ddl_with_cci_err_cci_pt_2"; + private static final String BACK_FILL = "PHYSICAL_BACKFILL_ENABLE=false"; private static final String creatTableTmpl = "CREATE TABLE `%s` ( \n" + " `id` bigint(11) NOT NULL AUTO_INCREMENT BY GROUP, \n" @@ -322,6 +328,25 @@ public void testAlterColumnDefaultValue() { } } + @Ignore + @Test + public void testOmc() { + final String sql1 = + String.format( + "ALTER TABLE %s CHANGE COLUMN `order_snapshot` `order_snapshot_new` varchar(64), ALGORITHM=OMC", + PRIMARY_TABLE_NAME1); + final String sql2 = String.format("ALTER TABLE %s MODIFY COLUMN `order_snapshot` varchar(64), ALGORITHM=OMC", + PRIMARY_TABLE_NAME1); + try { + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, + "Do not support ALGORITHM=OMC on table with cci"); + JdbcUtil.executeUpdateFailed(tddlConnection, sql2, + "Do not support ALGORITHM=OMC on table with cci"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + @Test public void testRenameTable() { String hint = buildCmdExtra(FORBID_DDL_WITH_CCI); @@ -339,6 +364,7 @@ public void testRenameTable() { } } + @Ignore @Test public void testRenameIndex() { String hint = buildCmdExtra(FORBID_DDL_WITH_CCI); @@ -405,43 +431,43 @@ public void testModifyPartitions() { } } - @Test - public void testAddDropPartitions() { - String hint = buildCmdExtra(FORBID_DDL_WITH_CCI); - - String autoPartitionTable = "CREATE TABLE t_order (\n" - + " `id` bigint(11) NOT NULL AUTO_INCREMENT,\n" - + " `order_id` varchar(20) DEFAULT NULL,\n" - + " `buyer_id` varchar(20) DEFAULT NULL,\n" - + " `seller_id` varchar(20) DEFAULT NULL,\n" - + " `order_snapshot` longtext DEFAULT NULL,\n" - + " `order_detail` longtext DEFAULT NULL,\n" - + " PRIMARY KEY (`id`),\n" - + " KEY `l_i_order` (`order_id`)\n" - + ") PARTITION BY RANGE(id)\n" - + " (PARTITION p1 VALUES LESS THAN(20),\n" - + " PARTITION p2 VALUES LESS THAN(40))"; - JdbcUtil.executeUpdateSuccess(tddlConnection, autoPartitionTable); - final String createCciTmpl = - "ALTER TABLE t_order ADD CLUSTERED clustered columnar index %s(`buyer_id`) PARTITION BY RANGE(`ID`)(PARTITION p1 VALUES LESS THAN(20),\n" - + " PARTITION p2 VALUES LESS THAN(40))"; - final String sqlCreateCci1 = String.format(createCciTmpl, INDEX_NAME1); - createCciSuccess(sqlCreateCci1); - - final String sql1 = "ALTER TABLE t_order ADD PARTITION (PARTITION p3 VALUES LESS THAN(60),\n" - + " PARTITION p4 VALUES LESS THAN(80))"; - final String sql2 = "ALTER TABLE t_order DROP PARTITION p2"; - try { - JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql1, - "Do not support current ddl [ALTER_TABLEGROUP] with cci"); - JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql2, - "Do not support current ddl [ALTER_TABLEGROUP] with cci"); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - dropTableIfExists("t_order"); - } - } +// @Test +// public void testAddDropPartitions() { +// String hint = buildCmdExtra(FORBID_DDL_WITH_CCI); +// +// String autoPartitionTable = "CREATE TABLE t_order (\n" +// + " `id` bigint(11) NOT NULL AUTO_INCREMENT,\n" +// + " `order_id` varchar(20) DEFAULT NULL,\n" +// + " `buyer_id` varchar(20) DEFAULT NULL,\n" +// + " `seller_id` varchar(20) DEFAULT NULL,\n" +// + " `order_snapshot` longtext DEFAULT NULL,\n" +// + " `order_detail` longtext DEFAULT NULL,\n" +// + " PRIMARY KEY (`id`),\n" +// + " KEY `l_i_order` (`order_id`)\n" +// + ") PARTITION BY RANGE(id)\n" +// + " (PARTITION p1 VALUES LESS THAN(20),\n" +// + " PARTITION p2 VALUES LESS THAN(40))"; +// JdbcUtil.executeUpdateSuccess(tddlConnection, autoPartitionTable); +// final String createCciTmpl = +// "ALTER TABLE t_order ADD CLUSTERED clustered columnar index %s(`buyer_id`) PARTITION BY RANGE(`ID`)(PARTITION p1 VALUES LESS THAN(20),\n" +// + " PARTITION p2 VALUES LESS THAN(40))"; +// final String sqlCreateCci1 = String.format(createCciTmpl, INDEX_NAME1); +// createCciSuccess(sqlCreateCci1); +// +// final String sql1 = "ALTER TABLE t_order ADD PARTITION (PARTITION p3 VALUES LESS THAN(60),\n" +// + " PARTITION p4 VALUES LESS THAN(80))"; +// final String sql2 = "ALTER TABLE t_order DROP PARTITION p2"; +// try { +// JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql1, +// "Do not support current ddl [ADD_PARTITION] with cci"); +// JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql2, +// "Do not support current ddl [DROP_PARTITION] with cci"); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } finally { +// dropTableIfExists("t_order"); +// } +// } @Test public void testSplitPartition() { @@ -506,13 +532,13 @@ public void testSplitPartition() { try { JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql1, - "Do not support current ddl [ALTER_TABLEGROUP] with cci"); + "Do not support current ddl [SPLIT_PARTITION] with cci"); JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql2, - "Do not support current ddl [ALTER_TABLEGROUP] with cci"); + "Do not support current ddl [SPLIT_PARTITION] with cci"); JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql3, - "Do not support current ddl [ALTER_TABLEGROUP] with cci"); + "Do not support current ddl [SPLIT_PARTITION] with cci"); JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql4, - "Do not support current ddl [ALTER_TABLEGROUP] with cci"); + "Do not support current ddl [SPLIT_PARTITION] with cci"); } catch (Exception e) { throw new RuntimeException(e); } finally { @@ -578,18 +604,18 @@ public void testOtherPartitionOperations() { try { JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql1, - "Do not support current ddl [ALTER_TABLEGROUP] with cci"); + "Do not support current ddl [MERGE_PARTITION] with cci"); JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql2, - "Do not support current ddl [ALTER_TABLEGROUP] with cci"); + "Do not support current ddl [RENAME_PARTITION] with cci"); JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql3, - "Do not support current ddl [ALTER_TABLEGROUP] with cci"); + "not support"); JdbcUtil.executeUpdateFailed(tddlConnection, hint + sql4, - "Do not support current ddl [ALTER_TABLEGROUP] with cci"); + "Do not support current ddl [REORGANIZE_PARTITION] with cci"); } catch (Exception e) { throw new RuntimeException(e); } finally { dropTableIfExists("t_order_1"); - dropTableIfExists("t_order_2"); +// dropTableIfExists("t_order_2"); } } @@ -636,4 +662,59 @@ public void testTtlLocalPartitions() { dropTableIfExists("t_order"); } } + + private static final String SELECT_FROM_TABLE_DETAIL = + "select storage_inst_id,table_group_name from information_schema.table_detail where table_schema='%s' and table_name='%s' and partition_name='%s'"; + + @Test + public void testMovePartition() throws SQLException { + String hint = buildCmdExtra(FORBID_DDL_WITH_CCI, BACK_FILL); + + // RANGE + String rangePartitionTable = "CREATE TABLE t_order_1 (\n" + + " `id` bigint(11) NOT NULL AUTO_INCREMENT,\n" + + " `order_id` varchar(20) DEFAULT NULL,\n" + + " `buyer_id` varchar(20) DEFAULT NULL,\n" + + " `seller_id` varchar(20) DEFAULT NULL,\n" + + " `order_snapshot` longtext DEFAULT NULL,\n" + + " `order_detail` longtext DEFAULT NULL,\n" + + " PRIMARY KEY (`id`),\n" + + " KEY `l_i_order` (`order_id`)\n" + + ") PARTITION BY RANGE(id)\n" + + " (PARTITION p1 VALUES LESS THAN(20),\n" + + " PARTITION p2 VALUES LESS THAN(100))"; + JdbcUtil.executeUpdateSuccess(tddlConnection, rangePartitionTable); + String createCciTmpl = + "ALTER TABLE t_order_1 ADD CLUSTERED clustered columnar index %s(`buyer_id`) PARTITION BY RANGE(`ID`)(PARTITION p1 VALUES LESS THAN(20),\n" + + " PARTITION p2 VALUES LESS THAN(100))"; + String sqlCreateCci1 = String.format(createCciTmpl, INDEX_NAME1); + createCciSuccess(sqlCreateCci1); + + String curInstId; + Set instIds = new HashSet<>(); + String sql = String.format(SELECT_FROM_TABLE_DETAIL, tddlDatabase1, "t_order_1", "p1"); + + ResultSet rs = JdbcUtil.executeQuery(sql, tddlConnection); + if (rs.next()) { + curInstId = rs.getString("STORAGE_INST_ID"); + } else { + throw new RuntimeException( + String.format("not find database table %s.%s", tddlDatabase1, "t_order_1")); + } + rs.close(); + + sql = String.format("show ds where db='%s'", tddlDatabase1); + rs = JdbcUtil.executeQuery(sql, tddlConnection); + while (rs.next()) { + if (!curInstId.equalsIgnoreCase(rs.getString("STORAGE_INST_ID"))) { + instIds.add(rs.getString("STORAGE_INST_ID")); + } + } + rs.close(); + + if (!instIds.isEmpty()) { + JdbcUtil.executeUpdateSuccess(tddlConnection, + String.format("%s alter table t_order_1 move partitions p1 to '%s'", hint, instIds.iterator().next())); + } + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/AlterTableWithCciTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/AlterTableWithCciTest.java index d6afa22d6..46a3bed5c 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/AlterTableWithCciTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/AlterTableWithCciTest.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.TStringUtil; +import com.alibaba.polardbx.executor.ddl.job.task.columnar.CheckCciMetaTask; import com.alibaba.polardbx.gms.metadb.table.ColumnarColumnEvolutionRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableEvolutionRecord; import com.alibaba.polardbx.gms.metadb.table.ColumnarTableMappingAccessor; @@ -86,9 +87,9 @@ public void before() { @After public void after() { - dropTableIfExists(PRIMARY_TABLE_NAME1); - dropTableIfExists(PRIMARY_TABLE_NAME2); - dropTableIfExists(PRIMARY_TABLE_NAME3); +// dropTableIfExists(PRIMARY_TABLE_NAME1); +// dropTableIfExists(PRIMARY_TABLE_NAME2); +// dropTableIfExists(PRIMARY_TABLE_NAME3); } @Test @@ -112,18 +113,21 @@ public void testAddColumn() throws SQLException { compareColumnPositions(schemaName, tableName); compareColumnRecords(schemaName, tableName); checkAddIndexesRecords(schemaName, tableName, ImmutableList.of("c2")); + checkCciMeta(indexName); sql = "alter table %s add c3 int first"; JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); compareColumnPositions(schemaName, tableName); compareColumnRecords(schemaName, tableName); checkAddIndexesRecords(schemaName, tableName, ImmutableList.of("c3")); + checkCciMeta(indexName); sql = "alter table %s add c4 int after c3"; JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); compareColumnPositions(schemaName, tableName); compareColumnRecords(schemaName, tableName); checkAddIndexesRecords(schemaName, tableName, ImmutableList.of("c4")); + checkCciMeta(indexName); } @Test @@ -148,6 +152,16 @@ public void testDropColumn() throws SQLException { compareColumnPositions(schemaName, tableName); compareColumnRecords(schemaName, tableName); checkDropIndexesRecords(schemaName, tableName, ImmutableList.of("seller_id")); + checkCciMeta(indexName); + + // drop last column + sql = "alter table %s drop order_snapshot"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + + compareColumnPositions(schemaName, tableName); + compareColumnRecords(schemaName, tableName); + checkDropIndexesRecords(schemaName, tableName, ImmutableList.of("order_snapshot")); + checkCciMeta(indexName); } @Test @@ -170,16 +184,19 @@ public void testModifyColumn() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); compareColumnPositions(schemaName, tableName); compareColumnRecords(schemaName, tableName); + checkCciMeta(indexName); sql = "alter table %s modify column seller_id varchar(64) after id"; JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); compareColumnPositions(schemaName, tableName); compareColumnRecords(schemaName, tableName); + checkCciMeta(indexName); sql = "alter table %s modify column seller_id varchar(64) first"; JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); compareColumnPositions(schemaName, tableName); compareColumnRecords(schemaName, tableName); + checkCciMeta(indexName); } @Test @@ -204,6 +221,192 @@ public void testChangeColumn() throws SQLException { compareColumnPositions(schemaName, tableName); compareColumnRecords(schemaName, tableName); checkChangeIndexesRecords(schemaName, tableName, ImmutableList.of(new Pair<>("seller_id_1", "seller_id"))); + checkCciMeta(indexName); + } + + @Test + public void testMultiAlters() throws SQLException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET FORBID_DDL_WITH_CCI = false"); + + String schemaName = TStringUtil.isBlank(tddlDatabase2) ? tddlDatabase1 : tddlDatabase2; + String tableName = PRIMARY_TABLE_NAME1; + String indexName = INDEX_NAME1; + + final String sqlCreateTable1 = String.format( + creatTableTmpl, + tableName, + indexName); + + // Create table with cci + createCciSuccess(sqlCreateTable1); + + // DO NOT SUPPORT MIXED ALTERS ON CLUSTERED INDEX +// String sql = "alter table %s add column c2 int, add column c3 int first, add column c4 int after c3"; +// JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); +// compareColumnPositions(schemaName, tableName); +// compareColumnRecords(schemaName, tableName); +// checkAddIndexesRecords(schemaName, tableName, ImmutableList.of("c2, c3, c4")); + + String sql = "alter table %s add c2 int"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + sql = "alter table %s add c3 int first"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + sql = "alter table %s add c4 int after c3"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + + sql = "alter table %s modify column c2 bigint, modify column c3 int first, change column c4 c40 int after id"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + compareColumnPositions(schemaName, tableName); + compareColumnRecords(schemaName, tableName); + checkChangeIndexesRecords(schemaName, tableName, ImmutableList.of(new Pair<>("c40", "c4"))); + checkCciMeta(indexName); + + sql = "alter table %s change column c40 c4 int, drop column c2"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + compareColumnPositions(schemaName, tableName); + compareColumnRecords(schemaName, tableName); + checkCciMeta(indexName); + + sql = "alter table %s add c2 int"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + + sql = "alter table %s drop column c2, drop column c3"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + compareColumnPositions(schemaName, tableName); + compareColumnRecords(schemaName, tableName); + checkDropIndexesRecords(schemaName, tableName, ImmutableList.of("c2, c3")); + checkCciMeta(indexName); + } + + @Test + public void testRepartition() throws SQLException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET FORBID_DDL_WITH_CCI = false"); + + String schemaName = TStringUtil.isBlank(tddlDatabase2) ? tddlDatabase1 : tddlDatabase2; + String tableName = PRIMARY_TABLE_NAME1; + String indexName = INDEX_NAME1; + + final String sqlCreateTable1 = String.format( + creatTableTmpl, + tableName, + indexName); + + // Create table with cci + createCciSuccess(sqlCreateTable1); + String originCciName = fetchCciSysTable(schemaName, tableName, indexName); + + String sql = SKIP_WAIT_CCI_CREATION_HINT + "alter table %s single"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + String afterCciName = fetchCciSysTable(schemaName, tableName, indexName); + + Assert.assertTrue(originCciName.equals(afterCciName)); + + sql = SKIP_WAIT_CCI_CREATION_HINT + "alter table %s broadcast"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + afterCciName = fetchCciSysTable(schemaName, tableName, indexName); + Assert.assertTrue(originCciName.equals(afterCciName)); + checkCciMeta(indexName); + } + + @Test + public void testOMC() throws SQLException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET FORBID_DDL_WITH_CCI = false"); + + String schemaName = TStringUtil.isBlank(tddlDatabase2) ? tddlDatabase1 : tddlDatabase2; + String tableName = PRIMARY_TABLE_NAME1; + String indexName = INDEX_NAME1; + + final String sqlCreateTable1 = String.format( + creatTableTmpl, + tableName, + indexName); + + // Create table with cci + createCciSuccess(sqlCreateTable1); + + // SINGLE STATEMENT + String sql = "alter table %s modify column seller_id longtext, algorithm = 'omc'"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + compareColumnPositions(schemaName, tableName); + compareColumnRecords(schemaName, tableName); + checkCciMeta(indexName); + + sql = "alter table %s modify column seller_id varchar(64) after id, algorithm = 'omc'"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + compareColumnPositions(schemaName, tableName); + compareColumnRecords(schemaName, tableName); + checkCciMeta(indexName); + + sql = "alter table %s modify column seller_id longtext first, algorithm = 'omc'"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + compareColumnPositions(schemaName, tableName); + compareColumnRecords(schemaName, tableName); + checkCciMeta(indexName); + + sql = "alter table %s change column seller_id seller_id_1 varchar(64), algorithm = 'omc'"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + + compareColumnPositions(schemaName, tableName); + compareColumnRecords(schemaName, tableName); + checkChangeIndexesRecords(schemaName, tableName, ImmutableList.of(new Pair<>("seller_id_1", "seller_id"))); + checkCciMeta(indexName); + + // MULTI STATEMENTS + sql = + "alter table %s modify column seller_id_1 longtext, add column c2 int, add column c3 int first, add column c4 int, algorithm = 'omc'"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + compareColumnPositions(schemaName, tableName); + compareColumnRecords(schemaName, tableName); + checkCciMeta(indexName); + + sql = + "alter table %s modify column c2 bigint, modify column c3 int first, change column c4 c40 int after id, algorithm = 'omc'"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + compareColumnPositions(schemaName, tableName); + compareColumnRecords(schemaName, tableName); + checkChangeIndexesRecords(schemaName, tableName, ImmutableList.of(new Pair<>("c40", "c4"))); + checkCciMeta(indexName); + + sql = "alter table %s change column c40 c4 int, drop column c2, add column tmp int algorithm = 'omc'"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName)); + compareColumnPositions(schemaName, tableName); + compareColumnRecords(schemaName, tableName); + checkCciMeta(indexName); + } + + @Test + public void testRenameCci() throws SQLException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET FORBID_DDL_WITH_CCI = false"); + + String schemaName = TStringUtil.isBlank(tddlDatabase2) ? tddlDatabase1 : tddlDatabase2; + String tableName = PRIMARY_TABLE_NAME1; + String indexName = INDEX_NAME1; + String newIndexName = INDEX_NAME2; + + final String sqlCreateTable1 = String.format( + creatTableTmpl, + tableName, + indexName); + + // Create table with cci + createCciSuccess(sqlCreateTable1); + + String sql = "alter table %s rename index %s to %s"; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(sql, tableName, indexName, newIndexName)); + + // show primary table + String showCreateTableSql = String.format("show create table %s", tableName); + ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, showCreateTableSql); + Assert.assertTrue(rs.next()); + String createTableString = rs.getString(2); + Assert.assertTrue(createTableString.contains(newIndexName)); + + // show cci table + showCreateTableSql = String.format("show create table %s", newIndexName); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, showCreateTableSql); + Assert.assertTrue(rs.next()); + createTableString = rs.getString(2); + Assert.assertTrue(createTableString.contains(newIndexName)); } private void compareColumnPositions(String schemaName, String tableName) @@ -340,7 +543,7 @@ private void compareColumnRecords(List sysTableColumnRecords, for (int i = 0; i < sysTableColumnRecords.size(); i++) { ColumnsRecord sysRecord = sysTableColumnRecords.get(i); ColumnsRecord evolutionRecord = evolutionTableColumnRecords.get(i); - if (!sysRecord.equals(evolutionRecord)) { + if (!CheckCciMetaTask.equalsColumnRecord(sysRecord, evolutionRecord)) { Assert.fail("Different column records in '" + sysTableColumnRecords.get(i).columnName); } } @@ -420,5 +623,27 @@ private void checkChangeIndexesRecords(String schemaName, String tableName, List } } } + + private String fetchCciSysTable(String schemaName, String tableName, String columnarName) + throws SQLException { + String sql = "select index_name from columnar_table_mapping " + + "where table_schema='%s' and table_name='%s' and index_name like '%%%s%%' order by latest_version_id desc limit 1"; + try (Connection metaDbConn = getMetaConnection(); + Statement stmt = metaDbConn.createStatement(); + ResultSet rs = stmt.executeQuery(String.format(sql, schemaName, tableName, columnarName))) { + if (rs.next()) { + return rs.getString(1); + } + } + return ""; + } + + private void checkCciMeta(String indexName) throws SQLException { + String sql = String.format("check columnar index %s meta", indexName); + ResultSet resultSet = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + org.junit.Assert.assertTrue(resultSet.next()); + String detail = resultSet.getString("details"); + Assert.assertTrue(detail.startsWith("OK")); + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/DropCciTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/DropCciTest.java index 6984584f7..78b887175 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/DropCciTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/DropCciTest.java @@ -305,7 +305,7 @@ public void testDrop6_alter_table_drop_cci_check_cdc_mark() { createCciSuccess(sqlCreateTable1); // Drop cci - final String sqlDdl1 = String.format("drop index %s on %s", cciTestIndexName1, cciTestTableName1); + final String sqlDdl1 = String.format("drop index `%s` on `%s`", cciTestIndexName1, cciTestTableName1); executeDdlAndCheckCdcRecord(sqlDdl1, sqlDdl1, cciTestTableName1, true); checkLatestColumnarSchemaEvolutionRecordByDdlSql(sqlDdl1, getDdlSchema(), @@ -330,7 +330,8 @@ public void testDrop6_alter_table_drop_cci_check_cdc_mark() { // Alter table drop cci final String sqlDdl2 = String.format("ALTER TABLE %s\n" + "\tDROP INDEX %s", cciTestTableName2, cciTestIndexName2); - final String expectedSqlDdl2 = String.format("drop index %s on %s", cciTestIndexName2, cciTestTableName2); + final String expectedSqlDdl2 = + String.format("drop index `%s` on `%s`", cciTestIndexName2, cciTestTableName2); executeDdlAndCheckCdcRecord(sqlDdl2, expectedSqlDdl2, cciTestTableName2, true); checkLatestColumnarSchemaEvolutionRecordByDdlSql(expectedSqlDdl2, getDdlSchema(), diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/DropDbWithCciTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/DropDbWithCciTest.java new file mode 100644 index 000000000..1872b31c6 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/DropDbWithCciTest.java @@ -0,0 +1,77 @@ +/* + * 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 com.alibaba.polardbx.qatest.ddl.auto.columnar; + +import com.alibaba.polardbx.common.ddl.newengine.DdlType; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableStatus; +import com.alibaba.polardbx.qatest.ddl.auto.partition.PartitionTestBase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Test; + +import java.util.Formatter; +import java.util.Random; + +public class DropDbWithCciTest extends PartitionTestBase { + private static final String dataBaseNameBase = "test_db_drop_db_with_cci"; + private static final String PRIMARY_TABLE_NAME1 = "drop_table_prim"; + private static final String INDEX_NAME1 = "drop_table_cci"; + + @Test + public void testDrop_table_with_cci_check_cdc_mark() { + final Random random = new Random(); + final Formatter formatter = new Formatter(); + final String suffix = "__" + formatter.format("%04x", random.nextInt(0x10000)); + final String dataBaseName = dataBaseNameBase + suffix; + JdbcUtil.executeUpdateSuccess(tddlConnection, "CREATE DATABASE IF NOT EXISTS " + dataBaseName + " MODE = AUTO"); + JdbcUtil.executeUpdateSuccess(tddlConnection, "use " + dataBaseName); + + try { + final String creatTableTmpl = "CREATE TABLE `%s` ( \n" + + " `id` bigint(11) NOT NULL AUTO_INCREMENT BY GROUP, \n" + + " `order_id` varchar(20) DEFAULT NULL, \n" + + " `buyer_id` varchar(20) DEFAULT NULL, \n" + + " `order_snapshot` longtext, \n" + + " PRIMARY KEY (`id`), \n" + + " CLUSTERED COLUMNAR INDEX `%s`(`buyer_id`) PARTITION BY KEY(`id`)\n" + + ") ENGINE = InnoDB CHARSET = utf8 PARTITION BY KEY(`order_id`);\n"; + final String sqlCreateTable1 = String.format( + creatTableTmpl, + PRIMARY_TABLE_NAME1, + INDEX_NAME1); + + // Create table with cci + dropTableIfExists(PRIMARY_TABLE_NAME1); + createCciSuccess(sqlCreateTable1); + + // Drop database + final String sqlDdl1 = String.format("drop database if exists %s ", dataBaseName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sqlDdl1); + JdbcUtil.executeUpdateSuccess(tddlConnection, "use " + getDdlSchema()); + checkLatestColumnarMappingRecordByDropDbSql(sqlDdl1, + dataBaseName, + PRIMARY_TABLE_NAME1, + INDEX_NAME1, + DdlType.DROP_INDEX, + ColumnarTableStatus.DROP); + + } catch (Exception e) { + throw new RuntimeException("sql statement execution failed!", e); + } + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/TruncateTableWithCciTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/TruncateTableWithCciTest.java new file mode 100644 index 000000000..8749dc39d --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/TruncateTableWithCciTest.java @@ -0,0 +1,148 @@ +/* + * 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 com.alibaba.polardbx.qatest.ddl.auto.columnar; + +import com.alibaba.polardbx.common.ddl.newengine.DdlType; +import com.alibaba.polardbx.gms.metadb.table.ColumnarTableStatus; +import com.alibaba.polardbx.qatest.CdcIgnore; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.Formatter; +import java.util.Random; + +public class TruncateTableWithCciTest extends DDLBaseNewDBTestCase { + private static final String PRIMARY_TABLE_PREFIX = "truncate_table_prim"; + private static final String INDEX_PREFIX = "truncate_table_cci"; + private static final String PRIMARY_TABLE_NAME1 = PRIMARY_TABLE_PREFIX + "_1"; + private static final String INDEX_NAME1 = INDEX_PREFIX + "_1"; + private static final String PRIMARY_TABLE_NAME2 = PRIMARY_TABLE_PREFIX + "_2"; + private static final String INDEX_NAME2 = INDEX_PREFIX + "_2"; + private static final String PRIMARY_TABLE_NAME3 = PRIMARY_TABLE_PREFIX + "_3"; + private static final String INDEX_NAME3 = INDEX_PREFIX + "_2"; + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Before + public void before() { + dropTableIfExists(PRIMARY_TABLE_NAME1); + dropTableIfExists(PRIMARY_TABLE_NAME2); + dropTableIfExists(PRIMARY_TABLE_NAME3); + } + + @After + public void after() { + dropTableIfExists(PRIMARY_TABLE_NAME1); + dropTableIfExists(PRIMARY_TABLE_NAME2); + dropTableIfExists(PRIMARY_TABLE_NAME3); + } + + @Test + public void testTruncate_table_with_cci_check_cdc_mark() { + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET FORBID_DDL_WITH_CCI = false"); + + final Random random = new Random(); + final Formatter formatter = new Formatter(); + final String suffix = "__" + formatter.format("%04x", random.nextInt(0x10000)); + final String cciTestTableName1 = PRIMARY_TABLE_NAME1 + suffix; + final String cciTestIndexName1 = INDEX_NAME1 + suffix; + try { + final String creatTableTmpl = "CREATE TABLE `%s` ( \n" + + " `id` bigint(11) NOT NULL AUTO_INCREMENT BY GROUP, \n" + + " `order_id` varchar(20) DEFAULT NULL, \n" + + " `buyer_id` varchar(20) DEFAULT NULL, \n" + + " `order_snapshot` longtext, \n" + + " PRIMARY KEY (`id`), \n" + + " CLUSTERED COLUMNAR INDEX `%s`(`buyer_id`) PARTITION BY KEY(`id`)\n" + + ") ENGINE = InnoDB CHARSET = utf8 PARTITION BY KEY(`order_id`);\n"; + final String sqlCreateTable1 = String.format( + creatTableTmpl, + cciTestTableName1, + cciTestIndexName1); + + // Create table with cci + dropTableIfExists(cciTestTableName1); + createCciSuccess(sqlCreateTable1); + + // Drop table + final String sqlDdl1 = String.format("truncate table %s ", cciTestTableName1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sqlDdl1); + checkLatestColumnarSchemaEvolutionRecordByDdlSql(sqlDdl1, + getDdlSchema(), + cciTestTableName1, + cciTestIndexName1, + DdlType.TRUNCATE_TABLE, + ColumnarTableStatus.PUBLIC); + + } catch (Exception e) { + throw new RuntimeException("sql statement execution failed!", e); + } + } + + @CdcIgnore(ignoreReason = "cdc暂时未支持insert overwrite") + @Test + public void testInsertOverwrite_table_with_cci_check_cdc_mark() { + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET FORBID_DDL_WITH_CCI = false"); + + final Random random = new Random(); + final Formatter formatter = new Formatter(); + final String suffix = "__" + formatter.format("%04x", random.nextInt(0x10000)); + final String cciTestTableName1 = PRIMARY_TABLE_NAME1 + suffix; + final String cciTestIndexName1 = INDEX_NAME1 + suffix; + try { + final String creatTableTmpl = "CREATE TABLE `%s` ( \n" + + " `id` bigint(11) NOT NULL AUTO_INCREMENT BY GROUP, \n" + + " `order_id` varchar(20) DEFAULT NULL, \n" + + " `buyer_id` varchar(20) DEFAULT NULL, \n" + + " `order_snapshot` longtext, \n" + + " PRIMARY KEY (`id`), \n" + + " CLUSTERED COLUMNAR INDEX `%s`(`buyer_id`) PARTITION BY KEY(`id`)\n" + + ") ENGINE = InnoDB CHARSET = utf8 PARTITION BY KEY(`order_id`);\n"; + final String sqlCreateTable1 = String.format( + creatTableTmpl, + cciTestTableName1, + cciTestIndexName1); + + // Create table with cci + dropTableIfExists(cciTestTableName1); + createCciSuccess(sqlCreateTable1); + + // Drop table + final String sqlDdl1 = + String.format("insert overwrite table %s values (null,\"1\",\"1\",\"1\") ", cciTestTableName1); + final String sqlDdl2 = String.format("truncate table `%s`", cciTestTableName1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sqlDdl1); + checkLatestColumnarSchemaEvolutionRecordByDdlSql(sqlDdl2, + getDdlSchema(), + cciTestTableName1, + cciTestIndexName1, + DdlType.TRUNCATE_TABLE, + ColumnarTableStatus.PUBLIC); + + } catch (Exception e) { + throw new RuntimeException("sql statement execution failed!", e); + } + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciAddPartitionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciAddPartitionTest.java new file mode 100644 index 000000000..a92cc8ce1 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciAddPartitionTest.java @@ -0,0 +1,95 @@ +/* + * 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 com.alibaba.polardbx.qatest.ddl.auto.columnar.alterCciPartition; + +import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import net.jcip.annotations.NotThreadSafe; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@RunWith(Parameterized.class) +@NotThreadSafe +public class AlterCciAddPartitionTest extends AlterCciPartitionBaseTest { + static List partitionRuleInfos = new ArrayList<>(Arrays + .asList( + new PartitionRuleInfo(PartitionStrategy.RANGE, + 1, + PARTITION_BY_BIGINT_RANGE, + "alter table " + tableName + "." + cciName + " add partition (partition p9 values less than(100400))"), + new PartitionRuleInfo(PartitionStrategy.RANGE_COLUMNS, + 2, + PARTITION_BY_INT_BIGINT_RANGE_COL, + "alter table " + tableName + "." + cciName + + " add partition (partition p9 values less than(400, 100400))"), + new PartitionRuleInfo(PartitionStrategy.LIST, + 1, + PARTITION_BY_BIGINT_LIST, + "alter table " + tableName + "." + cciName + + " add partition (partition p9 values in (100300,100301,100302,100303,100304,100305))"), + new PartitionRuleInfo(PartitionStrategy.LIST_COLUMNS, + 4, + PARTITION_BY_INT_BIGINT_LIST, "alter table " + tableName + "." + cciName + + " add partition (partition p9 values in ((1,100300),(1,100301),(1,100302),(1,100303),(1,100304),(1,100305)))")) + ); + + private static PartitionRuleInfo partitionRuleInfo; + static boolean firstIn = true; + final static String logicalDatabase = "AlterCciAddPartition"; + + public AlterCciAddPartitionTest(PartitionRuleInfo partitionRuleInfo) { + super(logicalDatabase); + this.partitionRuleInfo = partitionRuleInfo; + firstIn = true; + } + + @Test + public void testDDLOnly() { + + } + + @Parameterized.Parameters(name = "{index}:partitionRuleInfo={0}") + public static List prepareData() { + List status = new ArrayList<>(); + partitionRuleInfos.stream().forEach(o -> { + PartitionRuleInfo pi = + new PartitionRuleInfo(o.strategy, o.initDataType, o.partitionRule, + o.alterCommand); + status.add(new PartitionRuleInfo[] {pi}); + }); + return status; + } + + @Before + public void setUpTables() { + if (firstIn) { + setUp(true, partitionRuleInfo, false); + firstIn = false; + } + partitionRuleInfo.connection = getTddlConnection1(); + String sql = "use " + logicalDatabase; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciDropPartitionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciDropPartitionTest.java new file mode 100644 index 000000000..31015e1bf --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciDropPartitionTest.java @@ -0,0 +1,88 @@ +/* + * 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 com.alibaba.polardbx.qatest.ddl.auto.columnar.alterCciPartition; + +import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import net.jcip.annotations.NotThreadSafe; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@RunWith(Parameterized.class) +@NotThreadSafe +public class AlterCciDropPartitionTest extends AlterCciPartitionBaseTest { + static List partitionRuleInfos = new ArrayList<>(Arrays + .asList(new PartitionRuleInfo(PartitionStrategy.RANGE, + 1, + PARTITION_BY_BIGINT_RANGE, "alter table " + tableName + "." + cciName + " drop partition p2"), + new PartitionRuleInfo(PartitionStrategy.RANGE_COLUMNS, + 2, + PARTITION_BY_INT_BIGINT_RANGE_COL, "alter table " + tableName + "." + cciName + " drop partition p2"), + new PartitionRuleInfo(PartitionStrategy.LIST, + 1, + PARTITION_BY_BIGINT_LIST, "alter table " + tableName + "." + cciName + " drop partition p2"), + new PartitionRuleInfo(PartitionStrategy.LIST_COLUMNS, + 4, + PARTITION_BY_INT_BIGINT_LIST, "alter table " + tableName + "." + cciName + " drop partition p2")) + ); + + private static PartitionRuleInfo partitionRuleInfo; + static boolean firstIn = true; + final static String logicalDatabase = "AlterCciAddPartition"; + + public AlterCciDropPartitionTest(PartitionRuleInfo partitionRuleInfo) { + super(logicalDatabase); + this.partitionRuleInfo = partitionRuleInfo; + firstIn = true; + } + + @Test + public void testDDLOnly() { + + } + + @Parameterized.Parameters(name = "{index}:partitionRuleInfo={0}") + public static List prepareData() { + List status = new ArrayList<>(); + partitionRuleInfos.stream().forEach(o -> { + PartitionRuleInfo pi = + new PartitionRuleInfo(o.strategy, o.initDataType, o.partitionRule, + o.alterCommand); + status.add(new PartitionRuleInfo[] {pi}); + }); + return status; + } + + @Before + public void setUpTables() { + if (firstIn) { + setUp(true, partitionRuleInfo, true); + firstIn = false; + } + partitionRuleInfo.connection = getTddlConnection1(); + String sql = "use " + logicalDatabase; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciMergePartitionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciMergePartitionTest.java new file mode 100644 index 000000000..7a1e7c94a --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciMergePartitionTest.java @@ -0,0 +1,110 @@ +/* + * 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 com.alibaba.polardbx.qatest.ddl.auto.columnar.alterCciPartition; + +import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Before; +import org.junit.Test; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class AlterCciMergePartitionTest extends AlterCciPartitionBaseTest { + final static String logicalDatabase = "AlterCciMergePartition"; + + static String reorgCommand = "alter table " + tableName + "." + cciName + " merge partitions p2,p3 to p23"; + + static String reorgCommandForList = "alter table " + tableName + "." + cciName + " merge partitions p2,p4 to p24"; + static boolean firstIn = true; + + static List partitionRuleInfos = new ArrayList<>(Arrays + .asList( + new PartitionRuleInfo(PartitionStrategy.KEY, + 1, + PARTITION_BY_BIGINT_KEY, reorgCommand), + new PartitionRuleInfo(PartitionStrategy.KEY, + 2, + PARTITION_BY_INT_KEY, reorgCommand), + new PartitionRuleInfo(PartitionStrategy.KEY, + 2, + PARTITION_BY_INT_BIGINT_KEY, reorgCommand), + new PartitionRuleInfo(PartitionStrategy.HASH, + 2, + PARTITION_BY_INT_BIGINT_HASH, reorgCommand), + new PartitionRuleInfo(PartitionStrategy.HASH, + 3, + PARTITION_BY_MONTH_HASH, reorgCommand), + new PartitionRuleInfo(PartitionStrategy.RANGE, + 1, + PARTITION_BY_BIGINT_RANGE, reorgCommand), + new PartitionRuleInfo(PartitionStrategy.RANGE_COLUMNS, + 2, + PARTITION_BY_INT_BIGINT_RANGE_COL, reorgCommand), + new PartitionRuleInfo(PartitionStrategy.LIST, + 1, + PARTITION_BY_BIGINT_LIST, reorgCommandForList), + new PartitionRuleInfo(PartitionStrategy.LIST_COLUMNS, + 4, + PARTITION_BY_INT_BIGINT_LIST, reorgCommandForList)) + ); + + private static PartitionRuleInfo partitionRuleInfo; + + public AlterCciMergePartitionTest(PartitionRuleInfo curPartitionRuleInfo) { + super(logicalDatabase); + if (this.partitionRuleInfo == null + || !(curPartitionRuleInfo.getTableStatus() == partitionRuleInfo.getTableStatus() + && curPartitionRuleInfo.getStrategy() == partitionRuleInfo.getStrategy() && curPartitionRuleInfo + .getPartitionRule().equalsIgnoreCase(partitionRuleInfo.getPartitionRule()))) { + firstIn = true; + this.partitionRuleInfo = curPartitionRuleInfo; + } + } + + @Test + public void testDDLOnly() { + + } + + @Parameterized.Parameters(name = "{index}:partitionRuleInfo={0}") + public static List prepareData() { + List status = new ArrayList<>(); + partitionRuleInfos.stream().forEach(o -> { + PartitionRuleInfo pi = + new PartitionRuleInfo(o.strategy, o.initDataType, o.partitionRule, + o.alterCommand); + status.add(new PartitionRuleInfo[] {pi}); + }); + return status; + } + + @Before + public void setUpTables() { + if (firstIn) { + setUp(true, partitionRuleInfo, false); + firstIn = false; + } + partitionRuleInfo.connection = getTddlConnection1(); + String sql = "use " + logicalDatabase; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciModifyPartitionAddValueTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciModifyPartitionAddValueTest.java new file mode 100644 index 000000000..91d4e431c --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciModifyPartitionAddValueTest.java @@ -0,0 +1,84 @@ +/* + * 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 com.alibaba.polardbx.qatest.ddl.auto.columnar.alterCciPartition; + +import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import net.jcip.annotations.NotThreadSafe; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@RunWith(Parameterized.class) +@NotThreadSafe +public class AlterCciModifyPartitionAddValueTest extends AlterCciPartitionBaseTest { + static List partitionRuleInfos = new ArrayList<>(Arrays + .asList(new PartitionRuleInfo(PartitionStrategy.LIST, + 1, + PARTITION_BY_BIGINT_LIST, + "alter table " + tableName + " modify partition p2 add values(10001, 10002)"), + new PartitionRuleInfo(PartitionStrategy.LIST_COLUMNS, + 4, + PARTITION_BY_INT_BIGINT_LIST, + "alter table " + tableName + " modify partition p2 add values((2,100011),(2,100011))")) + ); + + private static PartitionRuleInfo partitionRuleInfo; + private static boolean firstIn = true; + final static String logicalDatabase = "AlterCciAddValueTest"; + + public AlterCciModifyPartitionAddValueTest(PartitionRuleInfo partitionRuleInfo) { + super(logicalDatabase); + this.partitionRuleInfo = partitionRuleInfo; + firstIn = true; + } + + @Test + public void testDDLOnly() { + + } + + @Parameterized.Parameters(name = "{index}:partitionRuleInfo={0}") + public static List prepareData() { + List status = new ArrayList<>(); + partitionRuleInfos.stream().forEach(o -> { + PartitionRuleInfo pi = + new PartitionRuleInfo(o.strategy, o.initDataType, o.partitionRule, + o.alterCommand); + status.add(new PartitionRuleInfo[] {pi}); + }); + return status; + } + + @Before + public void setUpTables() { + if (firstIn) { + setUp(true, partitionRuleInfo, false); + firstIn = false; + } + partitionRuleInfo.connection = getTddlConnection1(); + String sql = "use " + logicalDatabase; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciModifyPartitionDropValueTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciModifyPartitionDropValueTest.java new file mode 100644 index 000000000..b9387aa0e --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciModifyPartitionDropValueTest.java @@ -0,0 +1,84 @@ +/* + * 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 com.alibaba.polardbx.qatest.ddl.auto.columnar.alterCciPartition; + +import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import net.jcip.annotations.NotThreadSafe; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@RunWith(Parameterized.class) +@NotThreadSafe +public class AlterCciModifyPartitionDropValueTest extends AlterCciPartitionBaseTest { + static List partitionRuleInfos = new ArrayList<>(Arrays + .asList(new PartitionRuleInfo(PartitionStrategy.LIST, + 1, + PARTITION_BY_BIGINT_LIST, + "alter table " + tableName + " modify partition p2 drop values(100010, 100011)"), + new PartitionRuleInfo(PartitionStrategy.LIST_COLUMNS, + 4, + PARTITION_BY_INT_BIGINT_LIST, + "alter table " + tableName + " modify partition p2 drop values((1,100011),(1,100012))")) + ); + + private static PartitionRuleInfo partitionRuleInfo; + private static boolean firstIn = true; + final static String logicalDatabase = "AlterCciAddValueTest"; + + public AlterCciModifyPartitionDropValueTest(PartitionRuleInfo partitionRuleInfo) { + super(logicalDatabase); + this.partitionRuleInfo = partitionRuleInfo; + firstIn = true; + } + + @Test + public void testDDLOnly() { + + } + + @Parameterized.Parameters(name = "{index}:partitionRuleInfo={0}") + public static List prepareData() { + List status = new ArrayList<>(); + partitionRuleInfos.stream().forEach(o -> { + PartitionRuleInfo pi = + new PartitionRuleInfo(o.strategy, o.initDataType, o.partitionRule, + o.alterCommand); + status.add(new PartitionRuleInfo[] {pi}); + }); + return status; + } + + @Before + public void setUpTables() { + if (firstIn) { + setUp(true, partitionRuleInfo, true); + firstIn = false; + } + partitionRuleInfo.connection = getTddlConnection1(); + String sql = "use " + logicalDatabase; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciPartitionBaseTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciPartitionBaseTest.java new file mode 100644 index 000000000..22ad4da03 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciPartitionBaseTest.java @@ -0,0 +1,286 @@ +/* + * 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 com.alibaba.polardbx.qatest.ddl.auto.columnar.alterCciPartition; + +import com.alibaba.polardbx.optimizer.config.table.ComplexTaskMetaManager; +import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.data.ExecuteTableSelect; +import com.alibaba.polardbx.qatest.util.ConnectionManager; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import lombok.Getter; +import org.junit.BeforeClass; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class AlterCciPartitionBaseTest extends DDLBaseNewDBTestCase { + + protected String logicalDatabase; + protected static List finalTableStatus; + protected static String originUseDbName; + protected static String originSqlMode; + protected static boolean needAutoDropDbAfterTest = true; + protected static boolean printExecutedSqlLog = false; + protected static String tableGroupName = "alter_cci_table_tg"; + protected static String tableName = "tT1"; + protected static String cciName = "cci_tT1"; + + protected static String pk = "id"; + + public static final String SKIP_REAL_ALTER_PARTITION_HINT = + "/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS=\"WaitColumnarTableAlterPartitionTask\")*/"; + + public static final String partitionMode = "mode='auto'"; + + public static final String createCci = + "CREATE COLUMNAR CLUSTERED INDEX `%s` ON `%s`(`id`) %s"; + + public static final String PARTITION_BY_BIGINT_KEY = + " partition by key(id) partitions 3"; + public static final String PARTITION_BY_INT_KEY = + " partition by key(c_int_32) partitions 3"; + public static final String PARTITION_BY_INT_BIGINT_KEY = + " partition by key(c_int_32, id) partitions 3"; + public static final String PARTITION_BY_INT_BIGINT_HASH = + " partition by hash(c_int_32, id) partitions 3"; + public static final String PARTITION_BY_MONTH_HASH = + " partition by hash(month(c_datetime)) partitions 3"; + public static final String PARTITION_BY_BIGINT_RANGE = + " partition by range(id) (partition p1 values less than(100040), " + + "partition p2 values less than(100080), " + + "partition p3 values less than(100120), " + + "partition p4 values less than(100160), " + + "partition p5 values less than(100200), " + + "partition p6 values less than(100240), " + + "partition p7 values less than(100280), " + + "partition p8 values less than(100320))"; + public static final String PARTITION_BY_INT_BIGINT_RANGE_COL = + " partition by range columns(c_int_32, id) (partition p1 values less than(10, 100040), " + + "partition p2 values less than(20, 100080), " + + "partition p3 values less than(30, 100120), " + + "partition p4 values less than(40, 100160), " + + "partition p5 values less than(50, 100200), " + + "partition p6 values less than(60, 100240), " + + "partition p7 values less than(70, 100280), " + + "partition p8 values less than(300, 100320))"; + + public static final String PARTITION_BY_BIGINT_LIST = + " partition by list(id) (" + + " partition p1 values in (100000,100001,100002,100003,100004,100005,100006,100007,100008,100009)," + + " partition p2 values in (100010,100011,100012,100013,100014,100015,100016,100017,100018,100019)," + + " partition p3 values in (100020,100021,100022,100023,100024,100025,100026,100027,100028,100029)," + + " partition p4 values in (100030,100031,100032,100033,100034,100035,100036,100037,100038,100039)," + + " partition p5 values in (100040,100041,100042,100043,100044,100045,100046,100047,100048,100049)," + + " partition p6 values in (100050,100051,100052,100053,100054,100055,100056,100057,100058,100059)," + + " partition p7 values in (100060,100061,100062,100063,100064,100065,100066,100067,100068,100069)," + + " partition p8 values in (100070,100071,100072,100073,100074,100075,100076,100077,100078,100079," + + "100080,100081,100082,100083,100084,100085,100086,100087,100088,100089," + + "100090,100091,100092,100093,100094,100095,100096,100097,100098,100099," + + "100100,100110,100120,100130,100140,100150,100160,100170,100180,100190," + + "100101,100111,100121,100131,100141,100151,100161,100171,100181,100191," + + "100102,100112,100122,100132,100142,100152,100162,100172,100182,100192," + + "100103,100113,100123,100133,100143,100153,100163,100173,100183,100193," + + "100104,100114,100124,100134,100144,100154,100164,100174,100184,100194," + + "100105,100115,100125,100135,100145,100155,100165,100175,100185,100195," + + "100106,100116,100126,100136,100146,100156,100166,100176,100186,100196," + + "100107,100117,100127,100137,100147,100157,100167,100177,100187,100197," + + "100108,100118,100128,100138,100148,100158,100168,100178,100188,100198," + + "100109,100119,100129,100139,100149,100159,100169,100179,100189,100199," + + "100200,100210,100220,100230,100240,100250,100260,100270,100280,100290," + + "100201,100211,100221,100231,100241,100251,100261,100271,100281,100291," + + "100202,100212,100222,100232,100242,100252,100262,100272,100282,100292," + + "100203,100213,100223,100233,100243,100253,100263,100273,100283,100293," + + "100204,100214,100224,100234,100244,100254,100264,100274,100284,100294," + + "100205,100215,100225,100235,100245,100255,100265,100275,100285,100295," + + "100206,100216,100226,100236,100246,100256,100266,100276,100286,100296," + + "100207,100217,100227,100237,100247,100257,100267,100277,100287,100297," + + "100208,100218,100228,100238,100248,100258,100268,100278,100288,100298," + + "100209,100219,100229,100239,100249,100259,100269,100279,100289,100299))"; + + public static final String PARTITION_BY_INT_BIGINT_LIST = + " partition by list columns(c_int_32, id) (" + + " partition p1 values in ((1,100000),(1,100001),(1,100002),(1,100003),(1,100004),(1,100005),(1,100006),(1,100007),(1,100008),(1,100009))," + + " partition p2 values in ((1,100010),(1,100011),(1,100012),(1,100013),(1,100014),(1,100015),(1,100016),(1,100017),(1,100018),(1,100019))," + + " partition p3 values in ((1,100020),(1,100021),(1,100022),(1,100023),(1,100024),(1,100025),(1,100026),(1,100027),(1,100028),(1,100029))," + + " partition p4 values in ((1,100030),(1,100031),(1,100032),(1,100033),(1,100034),(1,100035),(1,100036),(1,100037),(1,100038),(1,100039))," + + " partition p5 values in ((1,100040),(1,100041),(1,100042),(1,100043),(1,100044),(1,100045),(1,100046),(1,100047),(1,100048),(1,100049))," + + " partition p6 values in ((1,100050),(1,100051),(1,100052),(1,100053),(1,100054),(1,100055),(1,100056),(1,100057),(1,100058),(1,100059))," + + " partition p7 values in ((1,100060),(1,100061),(1,100062),(1,100063),(1,100064),(1,100065),(1,100066),(1,100067),(1,100068),(1,100069))," + + " partition p8 values in ((1,100070),(1,100071),(1,100072),(1,100073),(1,100074),(1,100075),(1,100076),(1,100077),(1,100078),(1,100079)," + + "(1,100080),(1,100081),(1,100082),(1,100083),(1,100084),(1,100085),(1,100086),(1,100087),(1,100088),(1,100089)," + + "(1,100090),(1,100091),(1,100092),(1,100093),(1,100094),(1,100095),(1,100096),(1,100097),(1,100098),(1,100099)," + + "(1,100100),(1,100110),(1,100120),(1,100130),(1,100140),(1,100150),(1,100160),(1,100170),(1,100180),(1,100190)," + + "(1,100101),(1,100111),(1,100121),(1,100131),(1,100141),(1,100151),(1,100161),(1,100171),(1,100181),(1,100191)," + + "(1,100102),(1,100112),(1,100122),(1,100132),(1,100142),(1,100152),(1,100162),(1,100172),(1,100182),(1,100192)," + + "(1,100103),(1,100113),(1,100123),(1,100133),(1,100143),(1,100153),(1,100163),(1,100173),(1,100183),(1,100193)," + + "(1,100104),(1,100114),(1,100124),(1,100134),(1,100144),(1,100154),(1,100164),(1,100174),(1,100184),(1,100194)," + + "(1,100105),(1,100115),(1,100125),(1,100135),(1,100145),(1,100155),(1,100165),(1,100175),(1,100185),(1,100195)," + + "(1,100106),(1,100116),(1,100126),(1,100136),(1,100146),(1,100156),(1,100166),(1,100176),(1,100186),(1,100196)," + + "(1,100107),(1,100117),(1,100127),(1,100137),(1,100147),(1,100157),(1,100167),(1,100177),(1,100187),(1,100197)," + + "(1,100108),(1,100118),(1,100128),(1,100138),(1,100148),(1,100158),(1,100168),(1,100178),(1,100188),(1,100198)," + + "(1,100109),(1,100119),(1,100129),(1,100139),(1,100149),(1,100159),(1,100169),(1,100179),(1,100189),(1,100199)," + + "(1,100200),(1,100210),(1,100220),(1,100230),(1,100240),(1,100250),(1,100260),(1,100270),(1,100280),(1,100290)," + + "(1,100201),(1,100211),(1,100221),(1,100231),(1,100241),(1,100251),(1,100261),(1,100271),(1,100281),(1,100291)," + + "(1,100202),(1,100212),(1,100222),(1,100232),(1,100242),(1,100252),(1,100262),(1,100272),(1,100282),(1,100292)," + + "(1,100203),(1,100213),(1,100223),(1,100233),(1,100243),(1,100253),(1,100263),(1,100273),(1,100283),(1,100293)," + + "(1,100204),(1,100214),(1,100224),(1,100234),(1,100244),(1,100254),(1,100264),(1,100274),(1,100284),(1,100294)," + + "(1,100205),(1,100215),(1,100225),(1,100235),(1,100245),(1,100255),(1,100265),(1,100275),(1,100285),(1,100295)," + + "(1,100206),(1,100216),(1,100226),(1,100236),(1,100246),(1,100256),(1,100266),(1,100276),(1,100286),(1,100296)," + + "(1,100207),(1,100217),(1,100227),(1,100237),(1,100247),(1,100257),(1,100267),(1,100277),(1,100287),(1,100297)," + + "(1,100208),(1,100218),(1,100228),(1,100238),(1,100248),(1,100258),(1,100268),(1,100278),(1,100288),(1,100298)," + + "(1,100209),(1,100219),(1,100229),(1,100239),(1,100249),(1,100259),(1,100269),(1,100279),(1,100289),(1,100299)))"; + + public AlterCciPartitionBaseTest(String logicalDatabase) { + this.logicalDatabase = logicalDatabase; + } + + @BeforeClass + public static void setUpTestCase() throws Exception { + try (Connection tddlConnection = ConnectionManager.getInstance().getDruidPolardbxConnection()) { + String tddlSql = "use polardbx"; + JdbcUtil.executeUpdate(tddlConnection, tddlSql); + + String sql = "select database(),@@sql_mode"; + PreparedStatement stmt = JdbcUtil.preparedStatement(sql, tddlConnection); + ResultSet rs = null; + try { + rs = stmt.executeQuery(); + if (rs.next()) { + originUseDbName = (String) rs.getObject(1); + originSqlMode = (String) rs.getObject(2); + } + rs.close(); + stmt.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + + public void setUp(boolean recreateDB, PartitionRuleInfo partitionRuleInfo, boolean isTruncateOrDrop) { + if (!usingNewPartDb()) { + return; + } + partitionRuleInfo.connection = getTddlConnection1(); + prepareDdlAndData(recreateDB, partitionRuleInfo); + executePartReorg(partitionRuleInfo.alterCommand, isTruncateOrDrop); + } + + protected void reCreateDatabase(Connection tddlConnection, String targetDbName) { + String tddlSql = "use information_schema"; + JdbcUtil.executeUpdateSuccess(tddlConnection, tddlSql); + tddlSql = "drop database if exists " + targetDbName; + JdbcUtil.executeUpdateSuccess(tddlConnection, tddlSql); + tddlSql = "use information_schema"; + JdbcUtil.executeUpdateSuccess(tddlConnection, tddlSql); + tddlSql = "create database " + targetDbName + " " + partitionMode; + JdbcUtil.executeUpdateSuccess(tddlConnection, tddlSql); + tddlSql = "use " + targetDbName; + JdbcUtil.executeUpdateSuccess(tddlConnection, tddlSql); + tddlSql = "create tablegroup " + tableGroupName; + JdbcUtil.executeUpdateSuccess(tddlConnection, tddlSql); + } + + protected void createTable(String logicalTableName, String partitionRule) { + String createTableSql = ExecuteTableSelect.getFullTypeTableDef(logicalTableName, partitionRule); + JdbcUtil.executeUpdateSuccess(tddlConnection, + createTableSql.replace("AUTO_INCREMENT=1", "AUTO_INCREMENT=100000")); + String alterTableSetTg = "alter table " + logicalTableName + " set tablegroup=" + tableGroupName + " force"; + JdbcUtil.executeUpdateSuccess(tddlConnection, alterTableSetTg); + } + + protected void createCci(String logicalTableName, String cciName, String partitionRule) { + String createCciSql = + SKIP_WAIT_CCI_CREATION_HINT + String.format(createCci, cciName, logicalTableName, partitionRule); + JdbcUtil.executeUpdateSuccess(tddlConnection, createCciSql); + } + + private void prepareDdlAndData(boolean recreateDB, PartitionRuleInfo partitionRuleInfo) { + if (recreateDB) { + reCreateDatabase(partitionRuleInfo.connection, this.logicalDatabase); + for (String tableName : partitionRuleInfo.getLogicalTableNames()) { + createTable(tableName, partitionRuleInfo.getPartitionRule()); + createCci(tableName, cciName, partitionRuleInfo.getPartitionRule()); + } + } + } + + private void executePartReorg(String command, boolean isDropOrTruncate) { + String sqlHint = "/*+TDDL({'extra':{'FORBID_DDL_WITH_CCI':'FALSE'}})*/"; + if (isDropOrTruncate) { + sqlHint = + "/*+TDDL({'extra':{'ENABLE_DROP_TRUNCATE_CCI_PARTITION':'TRUE','FORBID_DDL_WITH_CCI':'FALSE'}})*/"; + } + String ignoreErr = + "The DDL job has been paused or cancelled. Please use SHOW DDL"; + Set ignoreErrs = new HashSet<>(); + ignoreErrs.add(ignoreErr); + JdbcUtil.executeUpdateSuccessIgnoreErr(tddlConnection, sqlHint + command, ignoreErrs); + } + + @Getter + static class PartitionRuleInfo { + final PartitionStrategy strategy; + final String partitionRule; + String alterCommand; + ComplexTaskMetaManager.ComplexTaskStatus tableStatus; + List partCol = new ArrayList<>(); + List> partVals = new ArrayList<>(); + public Connection connection; + int initDataType; + List logicalTableNames = new ArrayList() {{ + add("tT1"); + }}; + + public PartitionRuleInfo(PartitionStrategy partitionStrategy, + int initDataType, String partitionRule, + String alterCommand) { + this.strategy = partitionStrategy; + this.partitionRule = partitionRule; + this.alterCommand = SKIP_REAL_ALTER_PARTITION_HINT + alterCommand; + this.initDataType = initDataType; + } + + @Override + public String toString() { + String partRule = partitionRule; + if (partitionRule.length() > 50) { + partRule = partitionRule.substring(0, 50) + "..."; + } + return "PartitionRuleInfo{" + + "strategy=" + strategy + + ", tableStatus=" + tableStatus + + ", partitionRule='" + partRule + '\'' + + ", alterTableGroupCommand='" + alterCommand + '\'' + + ", logicalTableNames=" + logicalTableNames + + '}'; + } + } + + public boolean usingNewPartDb() { + return true; + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciSplitPartitionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciSplitPartitionTest.java new file mode 100644 index 000000000..a474aab4e --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/columnar/alterCciPartition/AlterCciSplitPartitionTest.java @@ -0,0 +1,120 @@ +/* + * 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 com.alibaba.polardbx.qatest.ddl.auto.columnar.alterCciPartition; + +import com.alibaba.polardbx.optimizer.partition.common.PartitionStrategy; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import net.jcip.annotations.NotThreadSafe; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@RunWith(Parameterized.class) +@NotThreadSafe +public class AlterCciSplitPartitionTest extends AlterCciPartitionBaseTest { + + static List partitionRuleInfos = new ArrayList<>(Arrays + .asList( + new PartitionRuleInfo(PartitionStrategy.KEY, + 1, + PARTITION_BY_BIGINT_KEY, + "alter table " + tableName + "." + cciName + " split partition p2"), + new PartitionRuleInfo(PartitionStrategy.KEY, + 2, + PARTITION_BY_INT_KEY, "alter table " + tableName + "." + cciName + " split partition p2"), + new PartitionRuleInfo(PartitionStrategy.KEY, + 2, + PARTITION_BY_INT_BIGINT_KEY, "alter table " + tableName + "." + cciName + " split partition p2"), + // TODO(HASH SPLIT) +// new PartitionRuleInfo(PartitionStrategy.HASH, +// 2, +// PARTITION_BY_INT_BIGINT_HASH, "alter table " + tableName + "." + cciName + " split partition p2"), +// new PartitionRuleInfo(PartitionStrategy.HASH, +// 3, +// PARTITION_BY_MONTH_HASH, "alter table " + tableName + "." + cciName + " split partition p2"), + new PartitionRuleInfo(PartitionStrategy.RANGE, + 1, + PARTITION_BY_BIGINT_RANGE, "alter table " + tableName + "." + cciName + + " split partition p2 into (partition p20 values less than(100050)," + + "partition p21 values less than(100080))"), + new PartitionRuleInfo(PartitionStrategy.RANGE_COLUMNS, + 2, + PARTITION_BY_INT_BIGINT_RANGE_COL, "alter table " + tableName + "." + cciName + + " split partition p2 into (partition p20 values less than(15, 100040)," + + "partition p21 values less than(20, 100080))"), + new PartitionRuleInfo(PartitionStrategy.LIST, + 1, + PARTITION_BY_BIGINT_LIST, "alter table " + tableName + "." + cciName + + " split partition p2 into (partition p20 values in (100010,100011,100012,100016,100017)," + + "partition p21 values in (100013,100014,100015,100018,100019))"), + new PartitionRuleInfo(PartitionStrategy.LIST_COLUMNS, + 4, + PARTITION_BY_INT_BIGINT_LIST, "alter table " + tableName + "." + cciName + + " split partition p2 into (partition p20 values in ((1,100010),(1,100011),(1,100012),(1,100016),(1,100017))," + + "partition p21 values in ((1,100013),(1,100014),(1,100015),(1,100018),(1,100019)))")) + ); + + private static PartitionRuleInfo partitionRuleInfo; + private static boolean firstIn = true; + final static String logicalDatabase = "AlterTableSplitTest"; + + public AlterCciSplitPartitionTest(PartitionRuleInfo curPartitionRuleInfo) { + super(logicalDatabase); + if (this.partitionRuleInfo == null + || !(curPartitionRuleInfo.getTableStatus() == partitionRuleInfo.getTableStatus() + && curPartitionRuleInfo.getStrategy() == partitionRuleInfo.getStrategy() && curPartitionRuleInfo + .getPartitionRule().equalsIgnoreCase(partitionRuleInfo.getPartitionRule()))) { + firstIn = true; + this.partitionRuleInfo = curPartitionRuleInfo; + } + } + + @Test + public void testDDLOnly() { + + } + + @Parameterized.Parameters(name = "{index}:partitionRuleInfo={0}") + public static List prepareData() { + List status = new ArrayList<>(); + partitionRuleInfos.stream().forEach(o -> { + PartitionRuleInfo pi = + new PartitionRuleInfo(o.strategy, o.initDataType, o.partitionRule, + o.alterCommand); + status.add(new PartitionRuleInfo[] {pi}); + }); + return status; + } + + @Before + public void setUpTables() { + if (firstIn) { + setUp(true, partitionRuleInfo, false); + firstIn = false; + } + partitionRuleInfo.connection = getTddlConnection1(); + String sql = "use " + logicalDatabase; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/dag/FailPointFromHintWithKeyEnableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/dag/FailPointFromHintWithKeyEnableTest.java new file mode 100644 index 000000000..c3a5816d7 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/dag/FailPointFromHintWithKeyEnableTest.java @@ -0,0 +1,64 @@ +package com.alibaba.polardbx.qatest.ddl.auto.dag; + +import com.alibaba.polardbx.executor.utils.failpoint.FailPoint; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class FailPointFromHintWithKeyEnableTest { + + private ExecutionContext executionContext; + + @Before + public void before() { + this.executionContext = new ExecutionContext(); + Map hint = new HashMap<>(); + executionContext.setExtraCmds(hint); + } + + private void addHint(String key, String value) { + this.executionContext.getExtraCmds().put(key, value); + } + + private void clearHint() { + this.executionContext.getExtraCmds().clear(); + } + + @Test + public void testInjectExceptionFromHintWithKeyEnableCheck() { + String key = "key1"; + FailPoint.disable(key); + FailPoint.injectExceptionFromHintWithKeyEnableCheck(key, executionContext); + addHint(key, "123"); + FailPoint.injectExceptionFromHintWithKeyEnableCheck(key, executionContext); + } + + @Test(expected = RuntimeException.class) + public void testInjectExceptionFromHintWithKeyEnableCheck2() { + String key = "key1"; + addHint(key, "123"); + FailPoint.enable(key, "true"); + FailPoint.injectExceptionFromHintWithKeyEnableCheck(key, executionContext); + } + + @Test + public void testInjectExceptionWithTableName() { + String key = "key2"; + FailPoint.injectExceptionWithTableName("t1", key, executionContext); + addHint(key, "t2"); + FailPoint.injectExceptionWithTableName("t1", key, executionContext); + clearHint(); + } + + @Test(expected = RuntimeException.class) + public void testInjectExceptionWithTableName2() { + String key = "key2"; + FailPoint.injectExceptionWithTableName("t1", key, executionContext); + addHint(key, "t1"); + FailPoint.injectExceptionWithTableName("t1", key, executionContext); + clearHint(); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/dal/CheckTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/dal/CheckTableTest.java index 85ec1b2e8..5b9ed748a 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/dal/CheckTableTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/dal/CheckTableTest.java @@ -84,13 +84,13 @@ public ErrorInjection(String objectName, int index, ErrorType errorType) { } } - public Pair getFullObjectName(Connection connection, String tableName, String objectName, - int index) { + public static Pair getFullObjectName(Connection connection, String tableName, String objectName, + int index) { String fetchNameSql = String.format("show full create table %s", objectName); - ResultSet resultSet1 = JdbcUtil.executeQuery(fetchNameSql, tddlConnection); + ResultSet resultSet1 = JdbcUtil.executeQuery(fetchNameSql, connection); String fullTableName = JdbcUtil.getAllResult(resultSet1).get(0).get(0).toString(); String fetchTopology = String.format("show topology %s", fullTableName); - ResultSet resultSet2 = JdbcUtil.executeQuery(fetchTopology, tddlConnection); + ResultSet resultSet2 = JdbcUtil.executeQuery(fetchTopology, connection); List result = JdbcUtil.getAllResult(resultSet2).stream().filter(o -> o.get(2).toString().endsWith(String.valueOf(index))) .collect(Collectors.toList()).get(0); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/dal/TimeZoneRoutingTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/dal/TimeZoneRoutingTest.java new file mode 100644 index 000000000..3a9b5794a --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/dal/TimeZoneRoutingTest.java @@ -0,0 +1,23 @@ +package com.alibaba.polardbx.qatest.ddl.auto.dal; + +import com.alibaba.polardbx.qatest.ddl.auto.partition.PartitionAutoLoadSqlTestBase; +import net.jcip.annotations.NotThreadSafe; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.List; + +@RunWith(value = Parameterized.class) +@NotThreadSafe +public class TimeZoneRoutingTest extends PartitionAutoLoadSqlTestBase { + + public TimeZoneRoutingTest(AutoLoadSqlTestCaseParams parameter) { + super(parameter); + } + + @Parameterized.Parameters(name = "{index}: SubTestCase {0}") + public static List parameters() { + return getParameters(TimeZoneRoutingTest.class, 0, false); + } + +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/AlterTableRollbackTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/AlterTableRollbackTest.java index cae856e5e..03fbadbb7 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/AlterTableRollbackTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/AlterTableRollbackTest.java @@ -2,12 +2,14 @@ import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; import com.alibaba.polardbx.qatest.util.JdbcUtil; +import net.jcip.annotations.NotThreadSafe; import org.junit.Test; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; +@NotThreadSafe public class AlterTableRollbackTest extends DDLBaseNewDBTestCase { private String tableName = "wumu_test"; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/AnsiQuotesTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/AnsiQuotesTest.java new file mode 100644 index 000000000..b10ae1708 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/AnsiQuotesTest.java @@ -0,0 +1,41 @@ +package com.alibaba.polardbx.qatest.ddl.auto.ddl; + +import com.alibaba.polardbx.qatest.BaseTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.SQLException; + +public class AnsiQuotesTest extends BaseTestCase { + private static final String TABLE_NAME = "AnsiQuotesTest_tb"; + public static final String CREATE_GLOBAL_TX_TABLE_V2 = + "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "_0" + + " (\n" + + " `TXID` BIGINT UNSIGNED NOT NULL,\n" + + " `TRX_SEQ` BIGINT UNSIGNED NOT NULL DEFAULT 18446744073709551615 COMMENT 'DEFAULT INVALID_SEQUENCE_NUMBER',\n" + + " `N_PARTICIPANTS` INT UNSIGNED NOT NULL DEFAULT 0,\n" + + " PRIMARY KEY (`TXID`)\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"; + + public static final String CREATE_GLOBAL_TX_TABLE_V2_OLD = + "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "_1" + + " (\n" + + " `TXID` BIGINT UNSIGNED NOT NULL,\n" + + " `TRX_SEQ` BIGINT UNSIGNED NOT NULL DEFAULT 18446744073709551615 COMMENT \"DEFAULT INVALID_SEQUENCE_NUMBER\",\n" + + " `N_PARTICIPANTS` INT UNSIGNED NOT NULL DEFAULT 0,\n" + + " PRIMARY KEY (`TXID`)\n" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"; + + @Test + public void test() throws SQLException { + try (Connection connection = getMysqlConnection()) { + JdbcUtil.executeIgnoreErrors(connection, "drop table if exists " + TABLE_NAME + "_0"); + JdbcUtil.executeIgnoreErrors(connection, "drop table if exists " + TABLE_NAME + "_1"); + JdbcUtil.executeUpdateSuccess(connection, "set sql_mode='ansi_quotes'"); + JdbcUtil.executeUpdateSuccess(connection, CREATE_GLOBAL_TX_TABLE_V2); + JdbcUtil.executeUpdateFailed(connection, CREATE_GLOBAL_TX_TABLE_V2_OLD, + "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\"DEFAULT INVALID_SEQUENCE_NUMBER\","); + } + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/CreateDatabaseTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/CreateDatabaseTest.java new file mode 100644 index 000000000..eeaa2c43c --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/CreateDatabaseTest.java @@ -0,0 +1,25 @@ +package com.alibaba.polardbx.qatest.ddl.auto.ddl; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Test; + +public class CreateDatabaseTest extends DDLBaseNewDBTestCase { + @Test + public void testCreateDatabaseFailed() { + String sql = "create database polardbx"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql, ""); + + sql = "create database metadb"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql, ""); + + sql = "create database mysql"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql, ""); + + sql = "create database performance_schema"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql, ""); + + sql = "create database information_schema"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql, ""); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/CreateIndexTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/CreateIndexTest.java new file mode 100644 index 000000000..dc664234f --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/CreateIndexTest.java @@ -0,0 +1,92 @@ +package com.alibaba.polardbx.qatest.ddl.auto.ddl; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Test; + +public class CreateIndexTest extends DDLBaseNewDBTestCase { + + @Test + public void testCreateIndex() { + String sql1 = "drop table if exists t1"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = "create table t1(a int, b varchar(100))"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + sql1 = "alter table t1 add global index abc123(b) partition by key(b)"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + sql1 = "alter table t1 add global index abc123(b) partition by key(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "alter table t1 add global index Abc123(b) partition by key(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "alter table t1 add index abc123(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "alter table t1 add index Abc123(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create global index abc123(b) on t1(b) partition by key(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create global index Abc123(b) on t1(b) partition by key(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create index abc123(b) on t1(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create index Abc123(b) on t1(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "drop table if exists t1"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + } + + @Test + public void testCreateIndex2() { + String sql1 = "drop table if exists t1"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = "create table t1(a int, b varchar(100)) partition by key(a)"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + sql1 = "alter table t1 add index abc123(b)"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + sql1 = "alter table t1 add global index abc123(b) partition by key(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "alter table t1 add global index Abc123(b) partition by key(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "alter table t1 add index abc123(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "alter table t1 add index Abc123(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create global index abc123(b) on t1(b) partition by key(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create global index Abc123(b) on t1(b) partition by key(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create index abc123(b) on t1(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create index Abc123(b) on t1(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "drop table if exists t1"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + } + + @Override + public boolean usingNewPartDb() { + return true; + } +} + diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/DdlRollbackTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/DdlRollbackTest.java new file mode 100644 index 000000000..510937a47 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/DdlRollbackTest.java @@ -0,0 +1,354 @@ +package com.alibaba.polardbx.qatest.ddl.auto.ddl; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.apache.calcite.util.Pair; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.alibaba.polardbx.qatest.util.JdbcUtil.getTopology; + +public class DdlRollbackTest extends DDLBaseNewDBTestCase { + + private static final String tableSchema = "_rollbackDb_"; + private static final String hint = + "/*+TDDL:cmd_extra(TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG = 'READY_TO_PUBLIC')*/ "; + + @Test + public void testMoveTableRollback() throws SQLException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use " + tableSchema); + String tableName = generateRandomName(10); + int i = 0; + do { + i++; + String sql1 = String.format("drop table if exists %s", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = String.format("create table %s( a int) partition by key(a) partitions 2", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + //GROUP_NAME-TABLE_NAME-PARTITION_NAME-DN_ID + final List> result = getTopology(tddlConnection, tableName); + Assert.assertTrue(result.size() == 2); + Assert.assertTrue(result.get(0).size() == 4); + Assert.assertTrue(result.get(1).size() == 4); + + Assert.assertTrue(!result.get(0).get(3).equalsIgnoreCase(result.get(1).get(3))); + + sql1 = String.format("alter table %s move partitions %s to '%s'", tableName, result.get(0).get(2), + result.get(1).get(3)); + + String ignoreErr = + "The DDL job has been paused or cancelled. Please use SHOW DDL"; + Set ignoreErrs = new HashSet<>(); + ignoreErrs.add(ignoreErr); + JdbcUtil.executeUpdateSuccessIgnoreErr(tddlConnection, hint + sql1, + ignoreErrs); + Long jobId = getDDLJobId(tddlConnection); + String rollbackDdl = "rollback ddl " + jobId; + if (i == 1) { + JdbcUtil.executeUpdateSuccess(tddlConnection, rollbackDdl); + } else { + sql1 = String.format("/*+TDDL:node('%s')*/ drop table %s", result.get(0).get(0), result.get(0).get(1)); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + JdbcUtil.executeFailed(tddlConnection, rollbackDdl, "The DDL job has been paused or cancelled"); + } + } while (i <= 1); + } + + @Test + public void testMoveTableGroupRollback() throws SQLException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use " + tableSchema); + String tableName1 = generateRandomName(10); + String tableName2 = generateRandomName(10); + int i = 0; + do { + i++; + String sql1 = String.format("drop table if exists %s", tableName1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = String.format("create table %s( a int) partition by key(a) partitions 2", tableName1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + sql1 = String.format("drop table if exists %s", tableName2); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = String.format("create table %s( a int) partition by key(a) partitions 2", tableName2); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + //GROUP_NAME-TABLE_NAME-PARTITION_NAME-DN_ID + final List> result = getTopology(tddlConnection, tableName2); + Assert.assertTrue(result.size() == 2); + Assert.assertTrue(result.get(0).size() == 4); + Assert.assertTrue(result.get(1).size() == 4); + + Assert.assertTrue(!result.get(0).get(3).equalsIgnoreCase(result.get(1).get(3))); + + sql1 = String.format("alter tablegroup by table %s move partitions %s to '%s'", tableName1, + result.get(0).get(2), + result.get(1).get(3)); + + String ignoreErr = + "The DDL job has been paused or cancelled. Please use SHOW DDL"; + Set ignoreErrs = new HashSet<>(); + ignoreErrs.add(ignoreErr); + JdbcUtil.executeUpdateSuccessIgnoreErr(tddlConnection, hint + sql1, + ignoreErrs); + Long jobId = getDDLJobId(tddlConnection); + String rollbackDdl = "rollback ddl " + jobId; + if (i == 1) { + JdbcUtil.executeUpdateSuccess(tddlConnection, rollbackDdl); + } else { + sql1 = String.format("/*+TDDL:node('%s')*/ drop table %s", result.get(0).get(0), result.get(0).get(1)); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + JdbcUtil.executeFailed(tddlConnection, rollbackDdl, "The DDL job has been paused or cancelled"); + } + } while (i <= 1); + } + + @Test + public void testSplitTableRollback() throws SQLException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use " + tableSchema); + String tableName = generateRandomName(10); + int i = 0; + do { + i++; + String sql1 = String.format("drop table if exists %s", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = String.format("create table %s( a int) partition by key(a) partitions 2", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + //GROUP_NAME-TABLE_NAME-PARTITION_NAME-DN_ID + final List> result = getTopology(tddlConnection, tableName); + Assert.assertTrue(result.size() == 2); + Assert.assertTrue(result.get(0).size() == 4); + Assert.assertTrue(result.get(1).size() == 4); + + Assert.assertTrue(!result.get(0).get(3).equalsIgnoreCase(result.get(1).get(3))); + + sql1 = String.format("alter table %s split partition %s", tableName, result.get(0).get(2)); + + String ignoreErr = + "The DDL job has been paused or cancelled. Please use SHOW DDL"; + Set ignoreErrs = new HashSet<>(); + ignoreErrs.add(ignoreErr); + JdbcUtil.executeUpdateSuccessIgnoreErr(tddlConnection, hint + sql1, + ignoreErrs); + Long jobId = getDDLJobId(tddlConnection); + String rollbackDdl = "rollback ddl " + jobId; + if (i == 1) { + JdbcUtil.executeUpdateSuccess(tddlConnection, rollbackDdl); + } else { + sql1 = String.format("/*+TDDL:node('%s')*/ drop table %s", result.get(0).get(0), result.get(0).get(1)); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + JdbcUtil.executeFailed(tddlConnection, rollbackDdl, "The DDL job has been paused or cancelled"); + } + } while (i <= 1); + } + + @Test + public void testSplitTableGroupRollback() throws SQLException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use " + tableSchema); + String tableName1 = generateRandomName(10); + String tableName2 = generateRandomName(10); + int i = 0; + do { + i++; + String sql1 = String.format("drop table if exists %s", tableName1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = String.format("create table %s( a int) partition by key(a) partitions 2", tableName1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + sql1 = String.format("drop table if exists %s", tableName2); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = String.format("create table %s( a int) partition by key(a) partitions 2", tableName2); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + //GROUP_NAME-TABLE_NAME-PARTITION_NAME-DN_ID + final List> result = getTopology(tddlConnection, tableName2); + Assert.assertTrue(result.size() == 2); + Assert.assertTrue(result.get(0).size() == 4); + Assert.assertTrue(result.get(1).size() == 4); + + Assert.assertTrue(!result.get(0).get(3).equalsIgnoreCase(result.get(1).get(3))); + + sql1 = String.format("alter tablegroup by table %s split partition %s", tableName1, result.get(0).get(2)); + + String ignoreErr = + "The DDL job has been paused or cancelled. Please use SHOW DDL"; + Set ignoreErrs = new HashSet<>(); + ignoreErrs.add(ignoreErr); + JdbcUtil.executeUpdateSuccessIgnoreErr(tddlConnection, hint + sql1, + ignoreErrs); + Long jobId = getDDLJobId(tddlConnection); + String rollbackDdl = "rollback ddl " + jobId; + if (i == 1) { + JdbcUtil.executeUpdateSuccess(tddlConnection, rollbackDdl); + } else { + sql1 = String.format("/*+TDDL:node('%s')*/ drop table %s", result.get(0).get(0), result.get(0).get(1)); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + JdbcUtil.executeFailed(tddlConnection, rollbackDdl, "The DDL job has been paused or cancelled"); + } + } while (i <= 1); + } + + @Test + public void testMergeTableRollback() throws SQLException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use " + tableSchema); + String tableName = generateRandomName(10); + int i = 0; + do { + i++; + String sql1 = String.format("drop table if exists %s", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = String.format("create table %s( a int) partition by key(a) partitions 2", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + //GROUP_NAME-TABLE_NAME-PARTITION_NAME-DN_ID + final List> result = getTopology(tddlConnection, tableName); + Assert.assertTrue(result.size() == 2); + Assert.assertTrue(result.get(0).size() == 4); + Assert.assertTrue(result.get(1).size() == 4); + + Assert.assertTrue(!result.get(0).get(3).equalsIgnoreCase(result.get(1).get(3))); + + sql1 = String.format("alter table %s merge partitions %s, %s to %s", tableName, result.get(0).get(2), + result.get(1).get(2), "pp"); + + String ignoreErr = + "The DDL job has been paused or cancelled. Please use SHOW DDL"; + Set ignoreErrs = new HashSet<>(); + ignoreErrs.add(ignoreErr); + JdbcUtil.executeUpdateSuccessIgnoreErr(tddlConnection, hint + sql1, + ignoreErrs); + Long jobId = getDDLJobId(tddlConnection); + String rollbackDdl = "rollback ddl " + jobId; + if (i == 1) { + JdbcUtil.executeUpdateSuccess(tddlConnection, rollbackDdl); + } else { + sql1 = String.format("/*+TDDL:node('%s')*/ drop table %s", result.get(0).get(0), result.get(0).get(1)); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + JdbcUtil.executeFailed(tddlConnection, rollbackDdl, "The DDL job has been paused or cancelled"); + } + } while (i <= 1); + } + + @Test + public void testMergeTableGroupRollback() throws SQLException { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use " + tableSchema); + String tableName1 = generateRandomName(10); + String tableName2 = generateRandomName(10); + int i = 0; + do { + i++; + String sql1 = String.format("drop table if exists %s", tableName1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = String.format("create table %s( a int) partition by key(a) partitions 2", tableName1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + sql1 = String.format("drop table if exists %s", tableName2); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = String.format("create table %s( a int) partition by key(a) partitions 2", tableName2); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + //GROUP_NAME-TABLE_NAME-PARTITION_NAME-DN_ID + final List> result = getTopology(tddlConnection, tableName2); + Assert.assertTrue(result.size() == 2); + Assert.assertTrue(result.get(0).size() == 4); + Assert.assertTrue(result.get(1).size() == 4); + + Assert.assertTrue(!result.get(0).get(3).equalsIgnoreCase(result.get(1).get(3))); + + sql1 = + String.format("alter tablegroup by table %s merge partitions %s, %s to %s", tableName1, + result.get(0).get(2), + result.get(1).get(2), "pp"); + + String ignoreErr = + "The DDL job has been paused or cancelled. Please use SHOW DDL"; + Set ignoreErrs = new HashSet<>(); + ignoreErrs.add(ignoreErr); + JdbcUtil.executeUpdateSuccessIgnoreErr(tddlConnection, hint + sql1, + ignoreErrs); + Long jobId = getDDLJobId(tddlConnection); + String rollbackDdl = "rollback ddl " + jobId; + if (i == 1) { + JdbcUtil.executeUpdateSuccess(tddlConnection, rollbackDdl); + } else { + sql1 = String.format("/*+TDDL:node('%s')*/ drop table %s", result.get(0).get(0), result.get(0).get(1)); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + JdbcUtil.executeFailed(tddlConnection, rollbackDdl, "The DDL job has been paused or cancelled"); + } + } while (i <= 1); + } + + private static Long getDDLJobId(Connection connection) throws SQLException { + long jobId = -1L; + + String sql = "show ddl"; + ResultSet rs = JdbcUtil.executeQuery(sql, connection); + if (rs.next()) { + jobId = rs.getLong("JOB_ID"); + } + rs.close(); + return jobId; + } + + public boolean usingNewPartDb() { + return true; + } + + public static String generateRandomName(int len) { + String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + Random random = new Random(); + + return random.ints(len, 0, characters.length()) + .mapToObj(i -> characters.charAt(i)) + .map(Object::toString) + .collect(Collectors.joining()); + } + + @Before + public void setUp() { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use polardbx"); + String sql1 = String.format("drop database if exists %s", tableSchema); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = String.format("create database %s mode=auto", tableSchema); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + } + + @After + public void cleanUp() { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use polardbx"); + String sql1 = String.format("drop database if exists %s", tableSchema); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + } + + public static List> getTopology(Connection tddlConnection, String tableName) { + //GROUP_NAME-TABLE_NAME-PARTITION_NAME-DN_ID + final List> result = new ArrayList<>(); + try (ResultSet topology = JdbcUtil.executeQuery("SHOW TOPOLOGY FROM `" + tableName + "`", tddlConnection)) { + while (topology.next()) { + List row = new ArrayList<>(); + row.add(topology.getString(2)); + row.add(topology.getString(3)); + row.add(topology.getString(4)); + row.add(topology.getString(7)); + result.add(row); + } + } catch (SQLException e) { + throw new RuntimeException("Cannot get topology for " + tableName, e); + } + return result; + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/ForeignKeyDdlTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/ForeignKeyDdlTest.java index a402d1862..dbb01a9e6 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/ForeignKeyDdlTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/ForeignKeyDdlTest.java @@ -599,6 +599,10 @@ public void repartitionFkSameTableTest() throws SQLException { @Test public void CreateTableDifferentCharsetWithFkReferred() throws SQLException { + if (isMySQL80()) { + return; + } + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET ENABLE_FOREIGN_KEY = true"); dropTableIfExists("charset_c"); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/GsiCreateWithStatisticCollectTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/GsiCreateWithStatisticCollectTest.java index a26fc161a..6b99e10d5 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/GsiCreateWithStatisticCollectTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/GsiCreateWithStatisticCollectTest.java @@ -77,16 +77,6 @@ public void test() throws Exception { // create gsi c.createStatement().execute(String.format(ALTER_TABLE, TB_NAME)); - // assert table rowcount and update time - rs = c.createStatement().executeQuery(String.format(CHECK_TABLES, DB_NAME, TB_NAME)); - rs.next(); - rowCount = rs.getInt("TABLE_ROWS"); - Timestamp dateNew = rs.getTimestamp("UPDATE_TIME"); - - rs.close(); - assert rowCount > 0; - assert dateNew.after(date); - // assert statistics rs = c.createStatement().executeQuery(String.format(CHECK_STATISTIC, DB_NAME, TB_NAME)); rs.next(); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/InterruptAlterTableRollbackTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/InterruptAlterTableRollbackTest.java new file mode 100644 index 000000000..c54e8a658 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/InterruptAlterTableRollbackTest.java @@ -0,0 +1,76 @@ +package com.alibaba.polardbx.qatest.ddl.auto.ddl; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Test; + +public class InterruptAlterTableRollbackTest extends DDLBaseNewDBTestCase { + + @Test + public void testAlterTableInstanceConcurrent() { + String sql1 = "drop table if exists t1"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = "create table t1(a varchar(10)) partition by key(a) partitions 7"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + sql1 = + "/*+TDDL:cmd_extra(FP_PHYSICAL_DDL_INTERRUPTED=true,ENABLE_DRDS_MULTI_PHASE_DDL=false)*/ alter table t1 add column b int"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, "has been interrupted"); + + sql1 = "alter table t1 add column b int"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + } + + @Test + public void testAlterTableGroupConcurrent() { + String sql1 = "drop table if exists t2"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = "create table t2(a varchar(10)) partition by key(a) partitions 6"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + sql1 = + "/*+TDDL:cmd_extra(MERGE_CONCURRENT=true,ENABLE_DRDS_MULTI_PHASE_DDL=false,FP_PHYSICAL_DDL_INTERRUPTED=true)*/ alter table t2 add column b int"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, "has been interrupted"); + + sql1 = "/*+TDDL:cmd_extra(MERGE_CONCURRENT=true)*/alter table t2 add column b int"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + } + + @Test + public void testAlterTableConcurrent() { + String sql1 = "drop table if exists t3"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = "create table t3(a varchar(10)) partition by key(a) partitions 8"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + sql1 = + "/*+TDDL:cmd_extra(MERGE_CONCURRENT=true,MERGE_DDL_CONCURRENT=true,ENABLE_DRDS_MULTI_PHASE_DDL=false,FP_PHYSICAL_DDL_INTERRUPTED=true)*/ alter table t3 add column b int"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, "has been interrupted"); + + sql1 = "/*+TDDL:cmd_extra(MERGE_CONCURRENT=true,MERGE_DDL_CONCURRENT=true)*/alter table t3 add column b int"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + } + + @Test + public void testAlterTableSequential() { + String sql1 = "drop table if exists t4"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = "create table t4(a varchar(10)) partition by key(a) partitions 5"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + sql1 = + "/*+TDDL:cmd_extra(SEQUENTIAL_CONCURRENT_POLICY=true,ENABLE_DRDS_MULTI_PHASE_DDL=false,FP_PHYSICAL_DDL_INTERRUPTED=true)*/ alter table t4 add column b int"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, "has been interrupted"); + + sql1 = "/*+TDDL:cmd_extra(SEQUENTIAL_CONCURRENT_POLICY=true)*/alter table t4 add column b int"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + } + + public boolean usingNewPartDb() { + return true; + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/InterruptAlterTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/InterruptAlterTableTest.java index 6186f9825..0a9c2c65d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/InterruptAlterTableTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/InterruptAlterTableTest.java @@ -42,10 +42,12 @@ public void t01_normal_alter() throws SQLException { } @Test - public void t11_cancel_add_then_rollback() throws SQLException { + public void t11_cancel_add_then_rollback_legacy() throws SQLException { // Expected: ADD COLUMN can be rolled back regardless of whether the shards are done. String columnInfo = "c5 int(11)"; String sql = String.format(ALTER_TABLE, ADD_COLUMN, columnInfo); + String disableHint = "/*+TDDL:cmd_extra(ENABLE_DRDS_MULTI_PHASE_DDL=false)*/"; + sql = disableHint + sql; JobInfo job = executeAsyncDDL(sql, ALTER_PREFIX, false); cancelDDL(job); checkPhyProcess(job); @@ -144,10 +146,12 @@ public void t31_kill_logical_modify_then_recover_legacy() throws SQLException { } @Test - public void t32_kill_logical_add_then_rollback() throws SQLException { + public void t32_kill_logical_add_then_rollback_legacy() throws SQLException { // Expected: ADD COLUMN can be killed, then rolled back (equivalent to PAUSE DDL). String columnInfo = "c5 int(11)"; String sql = String.format(ALTER_TABLE, ADD_COLUMN, columnInfo); + String disableHint = "/*+TDDL:cmd_extra(ENABLE_DRDS_MULTI_PHASE_DDL=false)*/"; + sql = disableHint + sql; JobInfo job = executeSeparateDDL(sql, ALTER_PREFIX, false); killLogicalProcess(ALTER_PREFIX); waitForSeconds(2); @@ -335,6 +339,8 @@ private void all_failed_physical_alter(String failPointKey, String operation, St return; } String sql = String.format(ALTER_TABLE, operation, columnInfo); + String disableHint = "/*+TDDL:cmd_extra(ENABLE_DRDS_MULTI_PHASE_DDL=false)*/"; + sql = disableHint + sql; try { injectDDLException(failPointKey, true); JobInfo job = executeDDL(sql); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/OptimizeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/OptimizeTableTest.java index bc18c5de6..44d6341ab 100755 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/OptimizeTableTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/OptimizeTableTest.java @@ -16,27 +16,14 @@ package com.alibaba.polardbx.qatest.ddl.auto.ddl; -import com.alibaba.polardbx.gms.metadb.limit.Limits; import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; -import com.alibaba.polardbx.qatest.ddl.auto.locality.LocalityTestCaseUtils.LocalityTestUtils; import com.alibaba.polardbx.qatest.util.JdbcUtil; -import org.apache.commons.lang.StringUtils; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.sql.Connection; -import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; - -import static com.alibaba.polardbx.qatest.validator.DataOperator.executeOnMysqlAndTddl; -import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentSameAssert; -import static org.hamcrest.Matchers.is; - public class OptimizeTableTest extends DDLBaseNewDBTestCase { @@ -74,7 +61,9 @@ public void testOptimizeTable() { String sql2 = "create table " + tableName2 + "(id int, name varchar(20)) partition by hash(id) partitions 3"; JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); JdbcUtil.executeUpdateSuccess(tddlConnection, sql2); - String gsiSql = String.format("create global index %s on %s(id) partition by hash(id) partitions 3", gsiPrimaryTableName, tableName1); + String gsiSql = + String.format("create global index %s on %s(id) partition by hash(id) partitions 3", gsiPrimaryTableName, + tableName1); JdbcUtil.executeUpdateSuccess(tddlConnection, gsiSql); sql1 = "optimize table " + tableName1 + "," + tableName2; @@ -93,7 +82,9 @@ public void testOptimizeTable2() { String sql2 = "create table " + tableName2 + "(id int, name varchar(20)) partition by hash(id) partitions 3"; JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); JdbcUtil.executeUpdateSuccess(tddlConnection, sql2); - String gsiSql = String.format("create global index %s on %s(id) partition by hash(id) partitions 3", gsiPrimaryTableName, tableName1); + String gsiSql = + String.format("create global index %s on %s(id) partition by hash(id) partitions 3", gsiPrimaryTableName, + tableName1); JdbcUtil.executeUpdateSuccess(tddlConnection, gsiSql); sql1 = "/*+TDDL:cmd_extra(OPTIMIZE_TABLE_PARALLELISM=1)*/optimize table " + tableName1 + "," + tableName2; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/RemovePartitioningTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/RemovePartitioningTest.java new file mode 100644 index 000000000..2f46a9041 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/RemovePartitioningTest.java @@ -0,0 +1,38 @@ +package com.alibaba.polardbx.qatest.ddl.auto.ddl; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Test; + +import java.util.List; + +public class RemovePartitioningTest extends DDLBaseNewDBTestCase { + + @Test + public void testRemovePartitioning() { + String sql1 = "drop table if exists remove_partitioning_t1"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = + "create table remove_partitioning_t1(a int primary key, b varchar(100), index idxb(b)) partition by key(b)"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + sql1 = "trace alter table remove_partitioning_t1 remove partitioning"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + List> traceResult = getTrace(tddlConnection); + for (List row : traceResult) { + for (String col : row) { + if (col != null && col.toLowerCase().contains("CdcGsiDdlMarkTask".toLowerCase())) { + Assert.fail("CdcGsiDdlMarkTask should not be executed"); + } + } + } + } + + @Override + public boolean usingNewPartDb() { + return true; + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/RenameGsiWithAutoPartitionTableCdcTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/RenameGsiWithAutoPartitionTableCdcTest.java new file mode 100644 index 000000000..b3037a3ef --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/RenameGsiWithAutoPartitionTableCdcTest.java @@ -0,0 +1,63 @@ +package com.alibaba.polardbx.qatest.ddl.auto.ddl; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Test; + +public class RenameGsiWithAutoPartitionTableCdcTest extends DDLBaseNewDBTestCase { + + @Test + public void testRenamePhyTable() { + // 预期 cdc 实验室不报错 + String sql = "drop table if exists auto_table_rename_index"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "create table auto_table_rename_index(a int, b int)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "alter table auto_table_rename_index add index idx_a(a)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "alter table auto_table_rename_index add index idx_b(b)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "alter table auto_table_rename_index rename index idx_a to idx_a_new"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "alter table auto_table_rename_index rename index idx_b to idx_b_new"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "alter table auto_table_rename_index drop index idx_a_new"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "alter table auto_table_rename_index drop index idx_b_new"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } + + @Test + public void testRenamePhyTable2() { + // 预期 cdc 实验室不报错 + String sql = "drop table if exists auto_table_rename_index2"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "create table auto_table_rename_index2(a int, b int, index idx_a(a), index idx_b(b))"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "alter table auto_table_rename_index2 rename index idx_a to idx_a_new"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "alter table auto_table_rename_index2 rename index idx_b to idx_b_new"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "alter table auto_table_rename_index2 drop index idx_a_new"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "alter table auto_table_rename_index2 drop index idx_b_new"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } + + @Override + public boolean usingNewPartDb() { + return true; + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/TruncateTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/TruncateTableTest.java index 2125ba390..c987c77b3 100755 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/TruncateTableTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/TruncateTableTest.java @@ -20,6 +20,7 @@ import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; import com.alibaba.polardbx.qatest.ddl.auto.locality.LocalityTestCaseUtils.LocalityTestUtils; import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.google.common.collect.ImmutableList; import org.apache.commons.lang.StringUtils; import org.junit.Assert; import org.junit.Before; @@ -69,7 +70,7 @@ public void before() throws SQLException { public void testTruncateBroadCastTable() { String tableName = schemaPrefix + testTableName + "_1"; dropTableIfExists(tableName); - String sql = "create table " + tableName + "(id int, name varchar(20))broadcast"; + String sql = "create table " + tableName + "(id int primary key auto_increment, name varchar(20))broadcast"; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; @@ -80,9 +81,12 @@ public void testTruncateBroadCastTable() { // Assert.assertEquals(getNodeNum(tddlConnection), getExplainNum(sql)); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(0, getDataNumFromTable(tddlConnection, tableName)); - sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; + sql = "insert into " + tableName + " (id, name) values (null, \"tom\"), (null, \"simi\") "; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(2, getDataNumFromTable(tddlConnection, tableName)); + List nums = getAllDataNumFromTable(tddlConnection, tableName, "id"); + Assert.assertTrue(ImmutableList.of(1, 2).equals(nums)); + dropTableIfExists(tableName); } @@ -93,7 +97,7 @@ public void testTruncateBroadCastTable() { public void testTruncateSingleTable() { String tableName = schemaPrefix + testTableName + "_2"; dropTableIfExists(tableName); - String sql = "create table " + tableName + " (id int, name varchar(20))"; + String sql = "create table " + tableName + " (id int primary key auto_increment, name varchar(20))"; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; @@ -104,10 +108,13 @@ public void testTruncateSingleTable() { JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(0, getDataNumFromTable(tddlConnection, tableName)); - sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; + sql = "insert into " + tableName + " (id, name) values (null, \"tom\"), (null, \"simi\") "; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(2, getDataNumFromTable(tddlConnection, tableName)); + List nums = getAllDataNumFromTable(tddlConnection, tableName, "id"); + Assert.assertTrue(ImmutableList.of(1, 2).equals(nums)); + dropTableIfExists(tableName); } @@ -122,7 +129,8 @@ public void testTruncateShardDbTable() { JdbcUtil.executeUpdateSuccess(tddlConnection, sql); assertNotExistsTable(tableName, tddlConnection); - sql = "create table " + tableName + " (id int, name varchar(20)) partition by hash (id)"; + sql = "create table " + tableName + + " (id int primary key auto_increment, name varchar(20)) partition by hash (id)"; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; @@ -133,10 +141,13 @@ public void testTruncateShardDbTable() { JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(0, getDataNumFromTable(tddlConnection, tableName)); - sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; + sql = "insert into " + tableName + " (id, name) values (null, \"tom\"), (null, \"simi\") "; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(2, getDataNumFromTable(tddlConnection, tableName)); + List nums = getAllDataNumFromTable(tddlConnection, tableName, "id"); + Assert.assertTrue(ImmutableList.of(1, 2).equals(nums)); + dropTableIfExists(tableName); } @@ -186,7 +197,7 @@ public void testTruncateShardDbTableWithGsi() throws SQLException { dropTableIfExists(indexTableName4); String sql = "create table " + tableName - + " (id int primary key, " + + " (id int primary key auto_increment by new, " + "name varchar(20), " + "global index " + indexTableName1 + " (name) partition by hash(name)," + "global unique index " + indexTableName2 + " (name) partition by hash(name)," @@ -215,10 +226,13 @@ public void testTruncateShardDbTableWithGsi() throws SQLException { checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, indexTableName4)); sql = "insert into " + tableName - + " (id, name) values (1, \"a\"), (2, \"b\") , (3, \"c\"), (4, \"d\"), (5, \"e\"), (6, \"f\"), (7, \"g\"), (8, \"h\")"; + + " (id, name) values (null, \"a\"), (null, \"b\") , (null, \"c\"), (null, \"d\"), (null, \"e\"), (null, \"f\"), (null, \"g\"), (null, \"h\")"; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(8, getDataNumFromTable(tddlConnection, tableName)); + List nums = getAllDataNumFromTable(tddlConnection, tableName, "id"); + Assert.assertTrue(ImmutableList.of(1, 2, 3, 4, 5, 6, 7, 8).equals(nums)); + checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, indexTableName1)); checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, indexTableName2)); checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, indexTableName3)); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/TruncateTableWithGsiTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/TruncateTableWithGsiTest.java new file mode 100644 index 000000000..c1e8e0093 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/ddl/TruncateTableWithGsiTest.java @@ -0,0 +1,44 @@ +package com.alibaba.polardbx.qatest.ddl.auto.ddl; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Test; + +public class TruncateTableWithGsiTest extends DDLBaseNewDBTestCase { + + @Test + public void testTruncateTableWithUGsi() { + String tableName = "truncate_table_with_ugsi_1"; + String indexName = "ugsi_idx_1"; + String indexHint = "/*+TDDL:cmd_extra(UNIQUE_GSI_WITH_PRIMARY_KEY=false)*/"; + + String sql = + String.format("create table %s (id int, name varchar(10), col int, primary key(id)) partition by key(id)", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = indexHint + String.format("alter table %s add global unique index %s(name) partition by key(name)", + tableName, indexName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("insert into %s values(1, 'a', 1), (2, 'b', 2), (3, 'c', 3)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("update %s set name = 'b', col = 2 where name = 'b'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("truncate table %s", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("insert into %s values(1, 'a', 1), (2, 'b', 2), (3, 'c', 3)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("update %s set name = 'b', col = 2 where name = 'b'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } + + @Override + public boolean usingNewPartDb() { + return true; + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/DnGeneratedColumnTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/DnGeneratedColumnTest.java index 8863eecf5..e28547361 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/DnGeneratedColumnTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/DnGeneratedColumnTest.java @@ -646,6 +646,10 @@ public void testShowColumns() throws SQLException { @Test public void testAlterTableUniqueIndexFailed() throws SQLException { + if (isMySQL80()) { + return; + } + String tableName = "dn_gen_col_alter_unique_fail"; String createTable = String.format("create table %s (a int primary key, b int, c int as (a+b) stored, d int)", tableName); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/ExpressionIndex80Test.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/ExpressionIndex80Test.java new file mode 100644 index 000000000..0aefff967 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/ExpressionIndex80Test.java @@ -0,0 +1,57 @@ +package com.alibaba.polardbx.qatest.ddl.auto.gen; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ReplicaIgnore; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +@ReplicaIgnore(ignoreReason = "not support 80 expression index in replica") +public class ExpressionIndex80Test extends DDLBaseNewDBTestCase { + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testCreate() { + if (!isMySQL80()) { + return; + } + String tableName = "expr_create_80_test"; + String createSql = String.format( + "create table `%s` (a int primary key, b int, c int, d varchar(64), e varchar(64), index cc((b + c))) PARTITION BY KEY(`a`)", + tableName); + JdbcUtil.dropTable(tddlConnection, tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, createSql); + + JdbcUtil.dropTable(tddlConnection, tableName); + createSql = String.format( + "create table `%s` (a int primary key, b int, c int, d varchar(64), e varchar(64), f json DEFAULT NULL, " + + " index `idx_1` ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)))," + + " key `idx_2` ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)))," + + " unique index `idx_3` ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)))," + + " unique key `idx_4` ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)))) PARTITION BY KEY(`a`)", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, createSql); + + String alterSql = String.format( + "alter table `%s` add index `idx_5` ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)));", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, alterSql); + + String createIndexSql = + String.format("create index `idx_6` on %s ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)));", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, createIndexSql); + + String checkTableSql = String.format("check table %s", tableName); + List> checkTableResult = + JdbcUtil.getAllResult(JdbcUtil.executeQuery(checkTableSql, tddlConnection)); + + Assert.assertTrue(checkTableResult.stream().allMatch(o -> o.get(3).toString().equalsIgnoreCase("OK"))); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/ExpressionIndexTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/ExpressionIndexTest.java index c7f68b8c6..baf17d458 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/ExpressionIndexTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/ExpressionIndexTest.java @@ -32,6 +32,9 @@ public boolean usingNewPartDb() { @Test public void testCreateFailed() { + if (isMySQL80()) { + return; + } String tableName = "expr_create_fail_tbl"; String create = String.format( @@ -86,6 +89,9 @@ public void testCreateFailed() { @Test public void testCreateSucc() { + if (isMySQL80()) { + return; + } String tableName = "expr_index_create_tbl"; String indexName = tableName + "_idx"; String create = @@ -126,6 +132,9 @@ public void testCreateSucc() { @Test public void testSpecialIndexName() { + if (isMySQL80()) { + return; + } String tableName = "expr_special_index_tbl"; String create = String.format("create table %s (a int primary key, b int, c int, d varchar(64), e varchar(64))", tableName); @@ -147,6 +156,9 @@ public void testSpecialIndexName() { @Test public void testSpecialColumnName() { + if (isMySQL80()) { + return; + } String tableName = "expr_special_column_tbl"; String indexName = tableName + "_idx"; String create = String.format("create table %s (a int primary key, abs varchar(64))", tableName); @@ -217,6 +229,9 @@ private void checkGenCol(String tableName, String[] columnInfos) { @Test public void testAutoPartitionTable() { + if (isMySQL80()) { + return; + } String tableName = "expr_auto_part_tbl"; String create = String.format( @@ -252,6 +267,9 @@ private List generatedDdl(String tableName, String indexDef, String inde @Test public void testMultipleAlterTable() { + if (isMySQL80()) { + return; + } String tableName = "expr_index_multi_alter_tbl"; String create = String.format( "create table %s (a int primary key, b int, c varchar(20), d varchar(20)) partition by hash(a)", @@ -330,6 +348,9 @@ public void testMultipleAlterTable() { @Test public void testAlterTableAddColumnAndIndex() { + if (isMySQL80()) { + return; + } String tableName = "com_index_multi_alter_tbl"; String create = String.format( "create table %s (a int primary key, b int, c varchar(20), d varchar(20)) partition by hash(a)", diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/GeneratedColumnConcurrentDMLTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/GeneratedColumnConcurrentDMLTest.java index 197bc241d..4fb71c938 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/GeneratedColumnConcurrentDMLTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gen/GeneratedColumnConcurrentDMLTest.java @@ -29,6 +29,7 @@ import java.util.function.BiFunction; import java.util.function.Function; +import static com.alibaba.polardbx.common.properties.ConnectionProperties.DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN; import static org.junit.Assert.assertTrue; public class GeneratedColumnConcurrentDMLTest extends DDLBaseNewDBTestCase { @@ -38,6 +39,8 @@ public class GeneratedColumnConcurrentDMLTest extends DDLBaseNewDBTestCase { // Use logical execution since result may be different from pushdown execution private static final String USE_LOGICAL_EXECUTION = "DML_EXECUTION_STRATEGY=LOGICAL"; private static final String DISABLE_DML_RETURNING = "DML_USE_RETURNING=FALSE"; + private static final String ENABLE_LOCAL_UK_FULL_TABLE_SCAN = + DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN + "=TRUE"; private final boolean isRDS80 = StorageInfoManager.checkRDS80(ConnectionManager.getInstance().getMysqlDataSource()); @@ -426,7 +429,7 @@ public void genColWithReplace() throws Exception { final ExecutorService threadPool = Executors.newFixedThreadPool(2); final List> tasks = new ArrayList<>(); - String hint = buildCmdExtra(DISABLE_DML_RETURNING, USE_LOGICAL_EXECUTION); + String hint = buildCmdExtra(DISABLE_DML_RETURNING, USE_LOGICAL_EXECUTION, ENABLE_LOCAL_UK_FULL_TABLE_SCAN); String alterSql1 = "alter table %s add column c int as (a-b) logical first, add column d int as (a+b) logical first"; @@ -510,7 +513,7 @@ public void genColWithUpsert() throws Exception { final ExecutorService threadPool = Executors.newFixedThreadPool(2); final List> tasks = new ArrayList<>(); - String hint = buildCmdExtra(DISABLE_DML_RETURNING, USE_LOGICAL_EXECUTION); + String hint = buildCmdExtra(DISABLE_DML_RETURNING, USE_LOGICAL_EXECUTION, ENABLE_LOCAL_UK_FULL_TABLE_SCAN); String alterSql1 = "alter table %s add column c int not null as (a-b) logical first, add column d int as (a+b) logical first"; @@ -612,7 +615,7 @@ public void genColWithInsertIgnore() throws Exception { final ExecutorService threadPool = Executors.newFixedThreadPool(2); final List> tasks = new ArrayList<>(); - String hint = buildCmdExtra(DISABLE_DML_RETURNING, USE_LOGICAL_EXECUTION); + String hint = buildCmdExtra(DISABLE_DML_RETURNING, USE_LOGICAL_EXECUTION, ENABLE_LOCAL_UK_FULL_TABLE_SCAN); String alterSql1 = "alter table %s add column c int not null as (a-b) logical first, add column d int as (a+b) logical first"; @@ -773,7 +776,11 @@ public Void apply(AtomicBoolean shouldStop, AtomicInteger totalCount) { try { JdbcUtil.executeUpdateSuccess(connection, sql); } catch (AssertionError e) { - if (e.getMessage().contains("Lock wait timeout exceeded") || e.getMessage() + if (isRDS80 && e.getMessage().contains( + "The definition of the table required by the flashback query has changed ")) { + // ignore + totalCount.getAndDecrement(); + } else if (e.getMessage().contains("Lock wait timeout exceeded") || e.getMessage() .contains("Deadlock found")) { // ignore totalCount.getAndDecrement(); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/DeleteGsiReturningTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/DeleteGsiReturningTest.java new file mode 100644 index 000000000..586de79a8 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/DeleteGsiReturningTest.java @@ -0,0 +1,348 @@ +/* + * 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 com.alibaba.polardbx.qatest.ddl.auto.gsi; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.qatest.ddl.auto.autoNewPartition.BaseAutoPartitionNewPartition; +import com.alibaba.polardbx.qatest.validator.DataOperator; +import com.alibaba.polardbx.qatest.validator.DataValidator; +import org.junit.Before; +import org.junit.Test; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class DeleteGsiReturningTest extends BaseAutoPartitionNewPartition { + private static final String TABLE_NAME = "t_delete_gsi_returning_test"; + private static final String GSI_NAME = "gsi_delete_gsi_returning_test"; + private static final String LSI_NAME = "idx_delete_gsi_returning_test"; + + private static final String CREATE_TABLE_TMPL = "CREATE TABLE `%s` (\n" + + "`pk` BIGINT(11) NOT NULL AUTO_INCREMENT,\n" + + "`c1` BIGINT DEFAULT NULL,\n" + + "`c2` BIGINT DEFAULT NULL,\n" + + "`c3` BIGINT DEFAULT NULL,\n" + + "`c4` BIGINT DEFAULT NULL,\n" + + "`c5` VARCHAR(255) DEFAULT NULL,\n" + + "`c6` DATETIME DEFAULT NULL,\n" + + "`c7` TEXT DEFAULT NULL,\n" + + "`c8` TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,\n" + + "PRIMARY KEY (`pk`),\n" + + "%s" + + ") ENGINE=InnoDB DEFAULT CHARSET=UTF8 "; + private static final int SUBPARTITION_COUNT = 7; + private static final String GSI_DEF_TMPL = "GLOBAL INDEX `%s`(c3) COVERING(c5, c6) " + + "partition BY HASH(c3) subpartition by HASH(c3) subpartitions " + SUBPARTITION_COUNT + "\n"; + private static final String LSI_DEF_TMPL = "INDEX `%s`(c3)\n"; + private static final String TABLE_PARTITION_DEF = + "partition BY HASH(c1) subpartition by HASH(c1) subpartitions " + SUBPARTITION_COUNT + "\n"; + + private static final String OPTIMIZE_DELETE_BY_RETURNING_HINT = + "/*+TDDL:CMD_EXTRA(OPTIMIZE_DELETE_BY_RETURNING=true)*/"; + + // Group concurrent cursor. + private static final String OPTIMIZE_DELETE_BY_RETURNING_AND_ENABLE_GROUP_CONCURRENT_HINT = + "/*+TDDL:OPTIMIZE_DELETE_BY_RETURNING=true GSI_CONCURRENT_WRITE=true*/"; + + private static final String FULL_COLUMN_LIST = "c1, c2, c3, c4, c5, c6, c7, c8"; + private static final String SELECT_DEF = "select " + FULL_COLUMN_LIST + " from `%s` order by c8 desc"; + private static final String INSERT_DEF = + "insert into %s(" + FULL_COLUMN_LIST + + ") values(?, ?, ?, ?, ?, '2024-06-25 16:53:00', 'optimize logical delete by returning', '2024-06-25 16:52:47')"; + + private static final String DELETE_PRIMARY_SK_EQ_DEF = "delete from `%s` %s where c1 = 3"; + private static final String DELETE_PRIMARY_SK_RANGE_4_DEF = "delete from `%s` %s where c1 between 4 and 7"; + private static final String DELETE_PRIMARY_SK_LT_DEF = "delete from `%s` %s where c1 < 7"; + private static final String DELETE_PRIMARY_SK_LT_SORT_DEF = "delete from `%s` %s where c1 < 7 order by c1"; + + private static final String PARTITION_HINT_DEF = "partition(p1sp3)"; + private static final String DELETE_PRIMARY_PARTITION_HINT_LIMIT_1_DEF = + "delete from `%s` %s where c6 <= '2024-06-26 19:18:33' and c1 = 2 or c1 = 27149 ORDER BY c6,pk ASC LIMIT 5"; + + private static final String DELETE_PRIMARY_ORDER_BY_NO_LIMIT_8_DEF = + "delete from `%s` %s where c2 <= 5 ORDER BY c6,pk ASC"; + + // private static final Map + private final String hint; + private boolean supportReturning = false; + + @Parameterized.Parameters(name = "hint:{0}") + public static List prepare() { + return new ArrayList() { + { + add(new Object[] {OPTIMIZE_DELETE_BY_RETURNING_HINT}); + add(new Object[] {OPTIMIZE_DELETE_BY_RETURNING_AND_ENABLE_GROUP_CONCURRENT_HINT}); + } + }; + } + + public DeleteGsiReturningTest(String hint) { + this.hint = hint; + } + + @Before + public void before() { + this.supportReturning = useXproto() + && Optional.ofNullable(getStorageProperties(tddlConnection).get("supportsReturning")) + .map(Boolean::parseBoolean).orElse(false); + } + + @Test + public void prepareData() { + if (!supportReturning) { + return; + } + + final String tableName = TABLE_NAME; + final String gsiName = GSI_NAME; + + rebuildTable(TABLE_PARTITION_DEF, GSI_DEF_TMPL, tableName, gsiName); + // Init data + prepareData(tableName, 10); + } + + @Test + public void testDeleteWithSimpleConditionOnSk() { + if (!supportReturning) { + return; + } + + final String tableName = TABLE_NAME; + final String gsiName = GSI_NAME; + + rebuildTable(TABLE_PARTITION_DEF, GSI_DEF_TMPL, tableName, gsiName); + + final String realGsiName = getRealGsiName(tddlConnection, tableName, gsiName); + + final List primaryTopology = showTopology(tddlConnection, tableName); + final List gsiTopology = showTopology(tddlConnection, realGsiName); + final int primaryPartitionCount = primaryTopology.size() / SUBPARTITION_COUNT; + final int gsiTotalPartitionCount = gsiTopology.size(); + + int affectedRows = 0; + + // Delete primary and found nothing to remove + affectedRows = delete(DELETE_PRIMARY_SK_EQ_DEF, tableName); + checkTraceRowCount(1); + + affectedRows = delete(DELETE_PRIMARY_SK_RANGE_4_DEF, tableName); + checkTraceRowCount( + getAffectedPartitionCount(primaryPartitionCount, + SUBPARTITION_COUNT, + gsiTotalPartitionCount, + 4, + affectedRows)); + + affectedRows = delete(DELETE_PRIMARY_SK_LT_DEF, tableName); + checkTraceRowCount( + getAffectedPartitionCount(primaryPartitionCount, + SUBPARTITION_COUNT, + gsiTotalPartitionCount, + Integer.MAX_VALUE, + affectedRows)); + + affectedRows = delete(DELETE_PRIMARY_SK_LT_SORT_DEF, tableName); + checkTraceRowCount( + getAffectedPartitionCount(primaryPartitionCount, + SUBPARTITION_COUNT, + gsiTotalPartitionCount, + Integer.MAX_VALUE, + affectedRows)); + + // Init data + prepareData(tableName, 10); + + affectedRows = delete(DELETE_PRIMARY_SK_EQ_DEF, tableName); + /** + * with auto force index enabled, trace row count will be 3 + * with auto force index disabled, trace row count will be 2 + * not checkTraceRowCount temporary + */ + // checkTraceRowCount(2); + checkData(tableName); + + affectedRows = delete(DELETE_PRIMARY_SK_RANGE_4_DEF, tableName); + checkTraceRowCount( + getAffectedPartitionCount(primaryPartitionCount, + SUBPARTITION_COUNT, + gsiTotalPartitionCount, + 4, + affectedRows)); + checkData(tableName); + + affectedRows = delete(DELETE_PRIMARY_SK_LT_DEF, tableName); + checkTraceRowCount( + getAffectedPartitionCount(primaryPartitionCount, + SUBPARTITION_COUNT, + gsiTotalPartitionCount, + Integer.MAX_VALUE, + affectedRows)); + checkData(tableName); + + affectedRows = delete(DELETE_PRIMARY_SK_LT_SORT_DEF, tableName); + checkTraceRowCount( + getAffectedPartitionCount(primaryPartitionCount, + SUBPARTITION_COUNT, + gsiTotalPartitionCount, + Integer.MAX_VALUE, + affectedRows)); + checkData(tableName); + } + + @Test + public void testDeleteWithPartitionHint() { + if (!supportReturning) { + return; + } + + final String tableName = TABLE_NAME; + final String gsiName = GSI_NAME; + + rebuildTable(TABLE_PARTITION_DEF, GSI_DEF_TMPL, tableName, gsiName); + + final String realGsiName = getRealGsiName(tddlConnection, tableName, gsiName); + + final List primaryTopology = showTopology(tddlConnection, tableName); + final List gsiTopology = showTopology(tddlConnection, realGsiName); + final int primaryPartitionCount = primaryTopology.size() / SUBPARTITION_COUNT; + final int gsiTotalPartitionCount = gsiTopology.size(); + + int affectedRows = 0; + + // Delete primary and found nothing to remove + affectedRows = delete(DELETE_PRIMARY_PARTITION_HINT_LIMIT_1_DEF, tableName, PARTITION_HINT_DEF); + checkTraceRowCount(1); + + // Init data + prepareData(tableName, 10); + + affectedRows = delete(DELETE_PRIMARY_PARTITION_HINT_LIMIT_1_DEF, tableName, PARTITION_HINT_DEF); + checkTraceRowCount( + getAffectedPartitionCount(1, + 1, + gsiTotalPartitionCount, + 1, + affectedRows)); + checkData(tableName); + } + + @Test + public void testDeleteWithOrderBy() { + if (!supportReturning) { + return; + } + + final String tableName = TABLE_NAME; + final String gsiName = GSI_NAME; + + rebuildTable(TABLE_PARTITION_DEF, GSI_DEF_TMPL, tableName, gsiName); + + final String realGsiName = getRealGsiName(tddlConnection, tableName, gsiName); + + final List primaryTopology = showTopology(tddlConnection, tableName); + final List gsiTopology = showTopology(tddlConnection, realGsiName); + final int primaryPartitionCount = primaryTopology.size() / SUBPARTITION_COUNT; + final int gsiTotalPartitionCount = gsiTopology.size(); + + int affectedRows = 0; + + // Delete primary and found nothing to remove + affectedRows = delete(DELETE_PRIMARY_ORDER_BY_NO_LIMIT_8_DEF, tableName); + checkTraceRowCount(primaryTopology.size()); + + // Init data + prepareData(tableName, 10); + + affectedRows = delete(DELETE_PRIMARY_ORDER_BY_NO_LIMIT_8_DEF, tableName); + checkTraceRowCount( + getAffectedPartitionCount(primaryPartitionCount, + SUBPARTITION_COUNT, + gsiTotalPartitionCount, + Integer.MAX_VALUE, + affectedRows)); + checkData(tableName); + } + + private static int getAffectedPartitionCount(int primaryPartitionCount, + int primarySubpartitionCount, + int gsiTotalPartitionCount, + int conditionRows, + int affectedRows) { + return + // Send delete to all non-pruned partitions of primary table + Math.min(primaryPartitionCount, conditionRows) * Math.min(primarySubpartitionCount, conditionRows) + // Send delete to gsi partitions with data to be removed + + Math.min(gsiTotalPartitionCount, affectedRows); + } + + private void rebuildTable(String tablePartitionDef, String gsiDefTmpl, String tableName, String gsiName) { + final String gsiDef = String.format(gsiDefTmpl, gsiName); + final String lsiDef = String.format(LSI_DEF_TMPL, LSI_NAME); + final String polardbxCreateTable = String.format(CREATE_TABLE_TMPL, tableName, gsiDef) + tablePartitionDef; + final String mysqlCreateTable = String.format(CREATE_TABLE_TMPL, tableName, lsiDef); + + dropTableIfExists(tddlConnection, tableName); + dropTableIfExists(mysqlConnection, tableName); + + DataOperator.executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + mysqlCreateTable, + polardbxCreateTable, + null, + false); + } + + private int delete(String deleteTmpl, String tableName) { + return delete(deleteTmpl, tableName, ""); + } + + private int delete(String deleteTmpl, String tableName, String partitionHint) { + final String mysqlModify = String.format(deleteTmpl, tableName, ""); + final String polardbxModify = String.format(deleteTmpl, tableName, partitionHint); + System.out.println(polardbxModify); + return DataOperator.executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + mysqlModify, + "trace " + hint + polardbxModify, + null, + true); + } + + private void prepareData(String tableName, int rowCount) { + final String insert = String.format(INSERT_DEF, tableName); + final List> params = new ArrayList<>(); + for (int i = 0; i < rowCount; i++) { + List param = new ArrayList<>(); + param.add(i); + param.add(i); + param.add(i); + param.add(i); + param.add("a"); + params.add(param); + } + DataOperator.executeBatchOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, params); + } + + private void checkData(String tableName) { + final String select = String.format(SELECT_DEF, tableName); + DataValidator.selectContentSameAssert(select, null, tddlConnection, mysqlConnection); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/InsertIgnoreTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/InsertIgnoreTest.java index 33d9072c5..eac663a7b 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/InsertIgnoreTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/InsertIgnoreTest.java @@ -174,20 +174,27 @@ public void tableNoPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = buildCmdExtra(DML_EXECUTION_STRATEGY_LOGICAL, DISABLE_RETURNING); final String insert = hint + " insert ignore into " + tableName + "(id, c1, c5, c8) values(1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 'b', '2020-06-16 06:49:32'), (3, 3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), is(topology.size())); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size())); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.lessThanOrEqualTo(3)); } /** @@ -264,19 +271,26 @@ public void tableNoPkWithUk_defaultNull() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ insert ignore into " + tableName - + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), is(topology.size() + 3)); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ "; + final String insert = "insert ignore into " + tableName + + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -306,20 +320,26 @@ public void tableNoPkWithUk_amendUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ insert ignore into " + tableName - + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), is(topology.size())); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ "; + final String insert = "insert ignore into " + tableName + + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size())); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.is(1)); } /** @@ -515,24 +535,28 @@ public void tableWithPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = buildCmdExtra(DML_EXECUTION_STRATEGY_LOGICAL, DISABLE_SKIP_DUPLICATE_CHECK_FOR_PK, DISABLE_RETURNING); final String insert = hint + "insert ignore into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (null, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), is(topology.size() + 1)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + Matchers.is(topology.size() + 1)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + Matchers.lessThanOrEqualTo(3 + 1)); } /** @@ -715,7 +739,10 @@ public void tableWithPkWithMultiUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ insert ignore into " + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ "; + final String insert = "insert ignore into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, ignore @@ -723,20 +750,33 @@ public void tableWithPkWithMultiUk() { + "(1, 2, null, 'd', '2020-06-16 06:49:32')," // u_c1_c2 冲突, ignore + "(1, 2, 4, 'e', '2020-06-16 06:49:32')," // u_c1_c2 冲突,ignore + "(2, 2, 4, 'f', '2020-06-16 06:49:32')"; // u_c2_c3 上与上面一行冲突,但是上面一个行被 ignore,这行保留 - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); + final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.is(topology.size() + 1)); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); - Assert.assertThat(trace.size(), is(topology.size() + 1)); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + final String insert1 = "insert ignore into " + tableName + + "(c1, c2, c3, c5, c8) values" + + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + // 非全表扫描检测冲突时,下面这条会被插入, 导致与mysql不一致 + // + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, ignore + + "(1, null, 3, 'c', '2020-06-16 06:49:32'), " // 不冲突 + + "(1, 2, null, 'd', '2020-06-16 06:49:32')," // u_c1_c2 冲突, ignore + + "(1, 2, 4, 'e', '2020-06-16 06:49:32')," // u_c1_c2 冲突,ignore + + "(2, 2, 4, 'f', '2020-06-16 06:49:32')"; // u_c2_c3 上与上面一行冲突,但是上面一个行被 ignore,这行保留 - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert1, + buildSqlCheckData(columnNames, tableName), + Matchers.lessThanOrEqualTo(2 + 1)); } /* @@ -2953,14 +2993,9 @@ public void tableWithPkWithUkWithUgsi_writeOnly_usingGsi() throws SQLException { tddlConnection); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - final List> gsiTopology = - JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName1)); // primary (partition pruning: 3) + gsi(partition pruning: 1) + insert(primary + gsi: 2) - Assert.assertThat(trace.size(), is(3 + 1 + 2)); + checkTraceRowCount(is(3 + 1 + 2)); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, tddlConnection); @@ -3454,7 +3489,7 @@ public void checkHugeBatchInsertIgnoreTraceId() throws SQLException { @Test public void testLogicalInsertIgnore() throws SQLException { - String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE)*/"; + String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl", " partition by hash(id) PARTITIONS 3", false, @@ -3542,7 +3577,7 @@ private void testComplexDmlInternal(String op, String tableName, String partitio @Test public void testLogicalInsertIgnoreUsingIn() throws SQLException { String hint = - "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_USING_IN=TRUE)*/"; + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_USING_IN=TRUE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl", " partition by hash(id) PARTITIONS 3", false, true, true, REPLACE_PARAMS); @@ -3558,6 +3593,41 @@ public void testLogicalInsertIgnoreUsingIn() throws SQLException { false, REPLACE_PARAMS); } + private static final String[][] INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN = new String[][] { + new String[] { + "(id,a,b)", "values (0,1,1),(1,2,2),(2,3,3),(100,101,101),(101,102,102)", "(id,a,b)", + "values (0,1,1),(1,2,2),(2,3,3),(100,101,101),(101,102,102)"}, + new String[] {"(id)", "values (1)", "(id)", "values (1)"}, + new String[] {"(id,a,b)", "values (4,0+2,0+2)", "(id,a,b)", "values (4,2,2)"}, + new String[] {"(id,a,b)", "values (1,2,2),(2,3,3)", "(id,a,b)", "values (1,2,2),(2,3,3)"}, + new String[] { + "(id,a,b)", String.format("select * from %s where id=100", SOURCE_TABLE_NAME), "(id,a,b)", + "values (100,101,101)"}, + new String[] { + "(id,a,b)", String.format("select * from %s where id>100", SOURCE_TABLE_NAME), "(id,a,b)", + "values (101,102,102),(102,103,103)"} + }; + + @Test + public void testLogicalInsertIgnoreWithoutFullTableScan() throws SQLException { + String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=FALSE)*/"; + + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl", + " partition by hash(id) PARTITIONS 3", false, + true, true, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl_brd", " broadcast", false, true, + false, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl_single", " single", false, true, + false, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl", + " partition by hash(id) PARTITIONS 3", true, + true, true, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl_brd", " broadcast", true, true, + false, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl_single", " single", true, true, + false, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + } + @Test public void testCrossSchemaInsertIgnore() throws SQLException { final String dbName = "test_db_cross_schema_dml"; @@ -3603,6 +3673,9 @@ public void testCrossSchemaInsertIgnore() throws SQLException { @Test public void testInsertIgnoreUGSI_returning() throws SQLException { + if (!supportReturning) { + return; + } final String tableName = "insert_ignore_returing_ugsi_tbl"; final String indexName = tableName + "_gsi"; @@ -3638,6 +3711,9 @@ public void testInsertIgnoreUGSI_returning() throws SQLException { @Test public void testInsertIgnoreUGSI1_returning() throws SQLException { + if (!supportReturning) { + return; + } final String tableName = "insert_ignore_returing_ugsi1_tbl"; final String indexName = tableName + "_gsi"; @@ -3669,7 +3745,7 @@ public void testInsertIgnoreUGSI1_returning() throws SQLException { selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); final List> trace = getTrace(tddlConnection); - Assert.assertThat(trace.size(), is(4)); + Assert.assertThat(trace.size(), is(2)); checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, indexName)); } @@ -4474,4 +4550,43 @@ public void testUGsiMultiWrite() throws Exception { List> trace = getTrace(tddlConnection); Assert.assertFalse(trace.toString().toLowerCase().contains("ignore")); } + + @Test + public void testReturningPolicy() throws SQLException { + if (!supportReturning || useAffectedRows) { + return; + } + try (Connection connection = getPolardbxConnection()) { + final String createTable = "CREATE TABLE IF NOT EXISTS `testReturningPolicy` (\n" + + " `id` bigint(20) NOT NULL AUTO_INCREMENT,\n" + + " `order_id` bigint(20) NOT NULL,\n" + + " `push_success` tinyint(4) NOT NULL DEFAULT '0',\n" + + " `retry_times` int(11) NOT NULL DEFAULT '0',\n" + + " `del` tinyint(4) NOT NULL DEFAULT '0',\n" + + " PRIMARY KEY (`id`),\n" + + " GLOBAL INDEX `gsi_id` (`id`) COVERING (`order_id`)\n" + + " PARTITION BY KEY(`id`)\n" + + " PARTITIONS 16,\n" + + " UNIQUE KEY `uk_order_id` (`order_id`, `del`),\n" + + " KEY `idx_del_push` (`del`, `push_success`)\n" + + ")\n" + + "PARTITION BY KEY(`order_id`)\n" + + "PARTITIONS 16 "; + JdbcUtil.executeUpdateSuccess(connection, createTable); + final String insertSql = "insert ignore into `testReturningPolicy` " + + " (`id`,`order_id`,`push_success`,`retry_times`,`del`) values" + + " ('16599','19609','1','0','0')," + + " ('16600','19608','1','0','0')"; + final String deleteSql = "delete from `testReturningPolicy` where 1=1"; + JdbcUtil.executeUpdateSuccess(connection, "set SEQUENTIAL_CONCURRENT_POLICY = true"); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + JdbcUtil.executeUpdateSuccess(connection, deleteSql); + JdbcUtil.executeUpdateSuccess(connection, "set SEQUENTIAL_CONCURRENT_POLICY = false"); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + } + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/ReplaceTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/ReplaceTest.java index 572e5391c..fc0a07e7c 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/ReplaceTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/ReplaceTest.java @@ -164,13 +164,16 @@ public void tableNoPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ "; - final String insert = - "replace into " - + tableName + final String insert = "replace into " + tableName + "(id, c1, c5, c8) values(1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 'b', '2020-06-16 06:49:32'), (3, 3, 'c', '2020-06-16 06:49:32')"; + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + String hint1 = hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/ "; // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint1 + insert, null, true); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -178,13 +181,27 @@ public void tableNoPkWithUk() { // 已知问题,UK非拆分键,会导致replace没有检测到其他表的unique冲突,少replace executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, false); // 已知问题,replace 无 PK,会有隐式主键更新导致 affected rows 实在 delete+insert 多1 - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint1 + insert, null, false); - final List> trace = getTrace(tddlConnection); + checkTraceRowCount(Matchers.is(topology.size() + 3)); + selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + hint1 = hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=FALSE)*/ "; + // equal when first insert + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint1 + insert, null, true); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); + selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + + // 已知问题,replace 无 PK,会有隐式主键更新导致 affected rows 实在 delete+insert 多1 + // 已知问题,UK非拆分键,会导致replace没有检测到其他表的unique冲突,少replace + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, false); + // 已知问题,replace 无 PK,会有隐式主键更新导致 affected rows 实在 delete+insert 多1 + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint1 + insert, null, + false); + checkTraceRowCount(Matchers.is(3 + 3)); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); } @@ -216,19 +233,26 @@ public void tableNoPkWithUk_defaultNull() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ replace into " + tableName - + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ "; + final String insert = "replace into " + tableName + + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size() + 3)); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -258,23 +282,27 @@ public void tableNoPkWithUk_amendUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ replace into " - + tableName - + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ "; + final String insert = "replace into " + tableName + + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; // VALUES 中有重复,affected rows 可能会比 MySQL 返回的小 1 - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size() + 1)); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 1)); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.is(1 + 1)); } /** @@ -471,24 +499,27 @@ public void tableWithPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ replace into " - + tableName - + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (null, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ "; + final String insert = "replace into " + tableName + + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (null, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + Matchers.is(topology.size() + 3)); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -570,9 +601,10 @@ public void tableWithPkWithMultiUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ replace into " - + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ "; + final String insert = "replace into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, replace @@ -580,20 +612,23 @@ public void tableWithPkWithMultiUk() { + "(1, 2, null, 'd', '2020-06-16 06:49:32')," // u_c1_c2 与第一行冲突,但是第一行被 replace, 这行保留 + "(1, 2, 4, 'e', '2020-06-16 06:49:32')," // u_c1_c2 冲突,replace + "(2, 2, 4, 'f', '2020-06-16 06:49:32')"; // u_c2_c3 冲突,replace - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.lessThanOrEqualTo(topology.size() + 3)); - Assert.assertThat(trace.size(), Matchers.is(9)); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.lessThanOrEqualTo(3 + 3)); } /* @@ -998,7 +1033,7 @@ public void tableWithCompositedPkNoUkWithMultiGsi_partitionByPk() throws SQLExce /** * 有 PK 无 UK, 一个 UGSI * UGSI 中未包含主表拆分键, 主表上 REPLACE 转 SELECT + DELETE + INSERT - * UGSI 中包含全部唯一键,UGSI 上 REPLACE 转 SELECT + REPLACE + INSERT + * UGSI 中包含全部唯一键,UGSI 上 REPLACE 转 SELECT + REPLACE */ @Test public void tableWithPkNoUkWithUgsi_usingGsi() throws SQLException { @@ -1054,7 +1089,7 @@ public void tableWithPkNoUkWithUgsi_usingGsi() throws SQLException { final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - Assert.assertThat(trace.size(), Matchers.is(6)); + Assert.assertThat(trace.size(), Matchers.is(5)); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -1064,7 +1099,7 @@ public void tableWithPkNoUkWithUgsi_usingGsi() throws SQLException { /** * 有 PK 无 UK, 一个 UGSI * UGSI 中未包含主表拆分键, 主表上 REPLACE 转 SELECT + DELETE + INSERT - * UGSI 中包含全部唯一键,UGSI 上 REPLACE 转 SELECT + REPLACE + INSERT + * UGSI 中包含全部唯一键,UGSI 上 REPLACE 转 SELECT + REPLACE */ @Test public void tableWithPkNoUkWithUgsi() throws SQLException { @@ -1121,7 +1156,7 @@ public void tableWithPkNoUkWithUgsi() throws SQLException { final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(11)); + Assert.assertThat(trace.size(), Matchers.is(10)); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -1196,7 +1231,7 @@ public void tableWithPkNoUkWithUgsi_partitionByPk2() throws SQLException { * 有 PK 无 UK, 一个 UGSI, 主键拆分 * 每个唯一键中都包含全部拆分键,但只有索引表包含全部 UK * 主表 REPLACE 转 SELECT + DELETE + INSERT - * 主表 REPLACE 转 SELECT + REPLACE + INSERT + * 主表 REPLACE 转 SELECT + REPLACE */ @Test public void tableWithPkNoUkWithUgsi_partitionByPk3_usingGsi() throws SQLException { @@ -1257,7 +1292,7 @@ public void tableWithPkNoUkWithUgsi_partitionByPk3_usingGsi() throws SQLExceptio final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - Assert.assertThat(trace.size(), Matchers.is(7)); + Assert.assertThat(trace.size(), Matchers.is(6)); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -1268,7 +1303,7 @@ public void tableWithPkNoUkWithUgsi_partitionByPk3_usingGsi() throws SQLExceptio * 有 PK 无 UK, 一个 UGSI, 主键拆分 * 每个唯一键中都包含全部拆分键,但只有索引表包含全部 UK * 主表 REPLACE 转 SELECT + DELETE + INSERT - * 主表 REPLACE 转 SELECT + REPLACE + INSERT + * 主表 REPLACE 转 SELECT + REPLACE */ @Test public void tableWithPkNoUkWithUgsi_partitionByPk3() throws SQLException { @@ -1327,7 +1362,7 @@ public void tableWithPkNoUkWithUgsi_partitionByPk3() throws SQLException { final List> trace = getTrace(tddlConnection); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(5)); + Assert.assertThat(trace.size(), Matchers.is(4)); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -1397,7 +1432,7 @@ public void tableWithPkNoUkWithUgsi_partitionByPk32_usingGsi() throws SQLExcepti final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - Assert.assertThat(trace.size(), Matchers.is(7)); + Assert.assertThat(trace.size(), Matchers.is(6)); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -1408,7 +1443,7 @@ public void tableWithPkNoUkWithUgsi_partitionByPk32_usingGsi() throws SQLExcepti * 有 PK 无 UK, 一个 UGSI, 主键拆分 * 每个唯一键中都包含全部拆分键,但只有索引表包含全部 UK * 主表 REPLACE 转 SELECT + DELETE + INSERT - * 主表 REPLACE 转 SELECT + REPLACE + INSERT + * 主表 REPLACE 转 SELECT + REPLACE */ @Test public void tableWithPkNoUkWithUgsi_partitionByPk32() throws SQLException { @@ -1466,7 +1501,7 @@ public void tableWithPkNoUkWithUgsi_partitionByPk32() throws SQLException { final List> trace = getTrace(tddlConnection); // final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(5)); + Assert.assertThat(trace.size(), Matchers.is(4)); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -2973,7 +3008,8 @@ public void checkHugeBatchReplaceTraceId() throws SQLException { @Test public void testLogicalReplace() throws SQLException { - String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE)*/"; + String hint = + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint, "replace into", "replace_test_tbl", " partition by hash(id) PARTITIONS 3", false, true, true, @@ -3067,6 +3103,42 @@ private void testComplexDmlInternal(String hint, String op, String tableName, St } } + private static final String[][] REPLACE_PARAMS_1 = new String[][] { + new String[] { + "(id,a,b)", "values (0,1,1),(1,2,2),(2,3,3),(100,101,101),(101,102,102)", "(id,a,b)", + "values (0,1,1),(1,2,2),(2,3,3),(100,101,101),(101,102,102)"}, + new String[] {"(id)", "values (1)", "(id)", "values (1)"}, + new String[] {"(id,a,b)", "values (4,0+2,0+2)", "(id,a,b)", "values (4,2,2)"}, + new String[] {"(id,a,b)", "values (1,2,2),(2,3,3)", "(id,a,b)", "values (1,2,2),(2,3,3)"}, + new String[] { + "(id,a,b)", String.format("select * from %s where id=100", SOURCE_TABLE_NAME), "(id,a,b)", + "values (100,101,101)"}, + new String[] { + "(id,a,b)", String.format("select * from %s where id>100", SOURCE_TABLE_NAME), "(id,a,b)", + "values (101,102,102),(102,103,103)"} + }; + + @Test + public void testLogicalReplaceWithoutFullTableScan() throws SQLException { + String hint = + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=FALSE)*/"; + + testComplexDmlInternal(hint, "replace into", "replace_test_tbl", " partition by hash(id) PARTITIONS 3", false, + true, true, + REPLACE_PARAMS_1); + testComplexDmlInternal(hint, "replace into", "replace_test_tbl_brd", " broadcast", false, true, false, + REPLACE_PARAMS_1); + testComplexDmlInternal(hint, "replace into", "replace_test_tbl_single", " single", false, true, false, + REPLACE_PARAMS_1); + testComplexDmlInternal(hint, "replace into", "replace_test_tbl", " partition by hash(id) PARTITIONS 3", true, + true, true, + REPLACE_PARAMS_1); + testComplexDmlInternal(hint, "replace into", "replace_test_tbl_brd", " broadcast", true, true, false, + REPLACE_PARAMS_1); + testComplexDmlInternal(hint, "replace into", "replace_test_tbl_single", " single", true, true, false, + REPLACE_PARAMS_1); + } + /** * 检查使用 IN 代替 UNION 的 HINT 是否生效 */ @@ -3165,7 +3237,7 @@ public void testMaxInCount() throws SQLException { @Test public void testLogicalReplaceUsingIn() throws SQLException { String hint = - "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_USING_IN=TRUE)*/"; + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_USING_IN=TRUE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint, "replace into", "replace_test_tbl", " partition by hash(id) PARTITIONS 3", false, true, true, REPLACE_PARAMS); @@ -3231,7 +3303,7 @@ public void testReplaceUGSI() throws SQLException { + "(`b`) partition by range(`b`) (partition p0 values less than(0), partition p1 values less than(10), partition p2 values less than MAXVALUE)"; JdbcUtil.executeUpdateSuccess(tddlConnection, createIndex); - String insertSql = "insert into " + tableName + " values (3,3,5),(3,4,-5)"; + String insertSql = "insert into " + tableName + " values (2,3,5),(3,4,-5)"; JdbcUtil.executeUpdateSuccess(tddlConnection, insertSql); String replaceSql = "replace into " + tableName + " values (4,4,-5)"; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/UpdateTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/UpdateTest.java index b8a2adbc5..d28c9a2ec 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/UpdateTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/UpdateTest.java @@ -546,7 +546,7 @@ public void testUgsi() throws SQLException { gsiName, tableName); JdbcUtil.executeUpdateSuccess(tddlConnection, createGsiSql); - String sql = String.format("insert into %s values(1,null,-5),(1,null,5)", tableName); + String sql = String.format("insert into %s values(1,null,-5),(2,null,5)", tableName); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); sql = String.format("update %s set b=1 where c=-5", tableName); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); @@ -568,7 +568,7 @@ public void testUgsi1() throws SQLException { gsiName, tableName); JdbcUtil.executeUpdateSuccess(tddlConnection, createGsiSql); - String sql = String.format("insert into %s values(1,null,null),(1,null,5)", tableName); + String sql = String.format("insert into %s values(1,null,null),(2,null,5)", tableName); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); sql = String.format("update %s set b=1 where c is null", tableName); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); @@ -590,7 +590,7 @@ public void testUgsi2() throws SQLException { gsiName, tableName); JdbcUtil.executeUpdateSuccess(tddlConnection, createGsiSql); - String sql = String.format("insert into %s values(1,null,null),(1,null,5)", tableName); + String sql = String.format("insert into %s values(1,null,null),(2,null,5)", tableName); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); sql = String.format("update %s set c=-5 where c is null", tableName); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/UpsertTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/UpsertTest.java index 6fc912d20..caac1c1fd 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/UpsertTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/gsi/group3/UpsertTest.java @@ -23,7 +23,9 @@ import com.alibaba.polardbx.qatest.util.JdbcUtil; import com.google.common.collect.ImmutableList; import org.apache.calcite.util.Pair; +import org.hamcrest.Matcher; import org.hamcrest.Matchers; +import org.jetbrains.annotations.NotNull; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -128,19 +130,11 @@ public void tableNoPkNoUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ "; + final String insert = "insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - Assert.assertThat(trace.size(), Matchers.is(3)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + executeTwiceThenCheckDataAndTraceResult(hint, insert, "select * from " + tableName, Matchers.is(3)); } /** @@ -170,25 +164,31 @@ public void tableNoPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = "insert into " + tableName + "(id, c1, c5, c8) values(1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 'b', '2020-06-16 06:49:32'), (3, 3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c3 = c3 + 1"; // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, - !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeThriceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + !useAffectedRows, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeThriceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + !useAffectedRows, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -219,20 +219,29 @@ public void tableNoPkWithUk_defaultNull() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName - + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" - + "on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ "; + final String insert = "insert into " + tableName + + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + + "on duplicate key update c3 = c3 + 1"; + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeThriceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + !useAffectedRows, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeThriceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + !useAffectedRows, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -262,27 +271,31 @@ public void tableNoPkWithUk_amendUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = "insert into " + tableName + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c3 = c3 + 1"; // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - // VALUES 中有重复,affected rows 可能会比 MySQL 返回的小 1 - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, - !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeThriceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + !useAffectedRows, + Matchers.is(topology.size() + 1)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeThriceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + !useAffectedRows, + Matchers.is(1 + 1)); } /** @@ -313,27 +326,30 @@ public void tableNoPkWithUk_amendUk2() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ "; final String insert = "insert into " + tableName + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c3 = c3 + 1"; - // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - // VALUES 中有重复,affected rows 可能会比 MySQL 返回的小 1 - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, - !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size())); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeThriceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + !useAffectedRows, + Matchers.is(topology.size())); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeThriceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + !useAffectedRows, + Matchers.is(1)); } /** @@ -363,21 +379,13 @@ public void tableNoPkWithUk_partitionByUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName - + "(id, c1, c5, c8) values(1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 'b', '2020-06-16 06:49:32'), (1, 3, 'c', '2020-06-16 06:49:32')" - + "on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(2)); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; + final String insert = "insert into " + tableName + + "(id, c1, c5, c8) values(1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 'b', '2020-06-16 06:49:32'), (1, 3, 'c', '2020-06-16 06:49:32')" + + "on duplicate key update c3 = c3 + 1"; + executeTwiceThenCheckDataAndTraceResult(hint, insert, "select * from " + tableName, Matchers.is(2)); } /** @@ -409,19 +417,12 @@ public void tableNoPkWithMultiUk_partitionByUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = - "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName + "insert into " + tableName + "(id, c1, c5, c8) values(1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 'b', '2020-06-16 06:49:32'), (1, 3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - Assert.assertThat(trace.size(), Matchers.is(2)); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + executeTwiceThenCheckDataAndTraceResult(hint, insert, "select * from " + tableName, Matchers.is(2)); } /** @@ -451,20 +452,12 @@ public void tableWithPkNoUk_partitionByPk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = - "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName + "insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - Assert.assertThat(trace.size(), Matchers.is(3)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + executeTwiceThenCheckDataAndTraceResult(hint, insert, "select * from " + tableName, Matchers.is(3)); } /** @@ -494,22 +487,14 @@ public void tableWithPkNoUk_partitionByPk2() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = - "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName + "insert into " + tableName + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + executeTwiceThenCheckDataAndTraceResult(hint, insert, "select * from " + tableName, Matchers.is(1)); } /** @@ -541,29 +526,31 @@ public void tableWithPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; final String insert = "insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (null, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')on duplicate key update c3 = c3 + 1"; - // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, - !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeThriceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + !useAffectedRows, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeThriceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + !useAffectedRows, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -600,21 +587,11 @@ public void tableWithPkWithUk2() { "insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (null, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')on duplicate key update c3 = c3 + 1"; // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, true); - final List> trace = getTrace(tddlConnection); - -// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(3 + 3)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + executeThriceThenCheckDataAndTraceResult(hint, + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + true, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -647,7 +624,10 @@ public void tableWithPkWithMultiUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ "; + final String insert = "insert into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, update @@ -661,15 +641,22 @@ public void tableWithPkWithMultiUk() { // selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, // tddlConnection); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 2)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeOnceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.is(topology.size() + 2)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeOnceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.lessThanOrEqualTo(2 + 2)); } /** @@ -702,7 +689,10 @@ public void tableWithPkWithMultiUk1() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ "; + final String insert = "insert into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, update @@ -716,15 +706,22 @@ public void tableWithPkWithMultiUk1() { // selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, // tddlConnection); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 2)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeOnceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.is(topology.size() + 2)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeOnceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.lessThanOrEqualTo(2 + 2)); } /** @@ -758,6 +755,8 @@ public void tableWithPkWithMultiUk_modifyPartitionKey() throws Exception { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String insert = "insert into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " @@ -772,20 +771,24 @@ public void tableWithPkWithMultiUk_modifyPartitionKey() throws Exception { // selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, // tddlConnection); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7"); - final List> mysqlResult = - selectContentSameAssert("select " + String.join(",", columnNames) + " from " + tableName, null, - mysqlConnection, tddlConnection); - - JdbcUtil - .assertRouteCorrectness(hint, tableName, mysqlResult, columnNames, ImmutableList.of("c1"), tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeOnceThenCheckDataAndTraceResultAndRouteCorrectness( + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + columnNames, + tableName, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeOnceThenCheckDataAndTraceResultAndRouteCorrectness( + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + columnNames, + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -819,7 +822,10 @@ public void tableWithPkWithMultiUk_modifyPartitionKey1() throws Exception { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ "; + final String insert = "insert into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, update @@ -833,20 +839,24 @@ public void tableWithPkWithMultiUk_modifyPartitionKey1() throws Exception { // selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, // tddlConnection); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 2)); - final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7"); - final List> mysqlResult = - selectContentSameAssert("select " + String.join(",", columnNames) + " from " + tableName, null, - mysqlConnection, tddlConnection); - - JdbcUtil - .assertRouteCorrectness(hint, tableName, mysqlResult, columnNames, ImmutableList.of("c1"), tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeOnceThenCheckDataAndTraceResultAndRouteCorrectness( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + columnNames, + tableName, + Matchers.is(topology.size() + 2)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeOnceThenCheckDataAndTraceResultAndRouteCorrectness( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + columnNames, + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /* @@ -896,6 +906,8 @@ public void tableWithPkNoUkWithGsi() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; final String insert = "insert into " @@ -903,24 +915,7 @@ public void tableWithPkNoUkWithGsi() throws SQLException { + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, - !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(3 + 3 + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeThriceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, !useAffectedRows, 3 + 3 + 1); } /** @@ -970,25 +965,7 @@ public void tableWithPkNoUkWithGsi2() throws SQLException { final String insert = "insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; - // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, - !useAffectedRows); - final List> trace = getTrace(tddlConnection); - -// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(3 + 3 + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeThriceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, !useAffectedRows, 3 + 3 + 1); } /** @@ -1035,25 +1012,13 @@ public void tableWithPkNoUkWithGsi_partitionByPk() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/insert into " + tableName - + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" - + "on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(3)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; + final String insert = "insert into " + tableName + + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + + "on duplicate key update c5 = values(c5)"; + executeTwiceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, 3); } /** @@ -1100,25 +1065,12 @@ public void tableWithPkNoUkWithGsi_partitionByPk2() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); +// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String insert = "insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - -// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(3)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeTwiceThenCheckGsiDataAndTraceResult("", insert, tableName, gsiName, 3); } /** @@ -1167,6 +1119,8 @@ public void tableWithPkNoUkWithMultiGsi_partitionByPk() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; final String insert = "insert into " @@ -1184,11 +1138,7 @@ public void tableWithPkNoUkWithMultiGsi_partitionByPk() throws SQLException { executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(9)); + checkTraceRowCountIs(9); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -1242,6 +1192,8 @@ public void tableWithPkNoUkWithMultiGsi_partitionByPk2() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); +// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = "insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" @@ -1257,11 +1209,7 @@ public void tableWithPkNoUkWithMultiGsi_partitionByPk2() throws SQLException { executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, !useAffectedRows); - final List> trace = getTrace(tddlConnection); - -// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(9)); + checkTraceRowCountIs(9); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -1315,6 +1263,8 @@ public void tableWithCompositedPkNoUkWithMultiGsi_partitionByPk() throws SQLExce JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; final String insert = "insert into " @@ -1332,11 +1282,7 @@ public void tableWithCompositedPkNoUkWithMultiGsi_partitionByPk() throws SQLExce executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(8)); + checkTraceRowCountIs(8); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -1390,6 +1336,8 @@ public void tableWithCompositedPkNoUkWithMultiGsi_partitionByPk2() throws SQLExc JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); +// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = "insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" @@ -1405,11 +1353,7 @@ public void tableWithCompositedPkNoUkWithMultiGsi_partitionByPk2() throws SQLExc executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, !useAffectedRows); - final List> trace = getTrace(tddlConnection); - -// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(8)); + checkTraceRowCountIs(8); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -1463,26 +1407,15 @@ public void tableWithPkNoUkWithUgsi_usingGsi() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName - + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" - + "on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - // final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); // final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); // primary (partition pruning: 1) + gsi(partition pruning: 1) + update(primary + gsi: 2) - Assert.assertThat(trace.size(), Matchers.is(1 + 1 + 2)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; + final String insert = "insert into " + tableName + + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + + "on duplicate key update c5 = values(c5)"; + executeTwiceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, 1 + 1 + 2); } /** @@ -1528,29 +1461,16 @@ public void tableWithPkNoUkWithUgsi() throws SQLException { + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"; final String partitionDef = " partition by hash(`c1`) partitions 7"; - JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); - JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - - final String insert = - "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE, DML_GET_DUP_USING_GSI=FALSE)*/ insert into " + tableName - + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" - + "on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); + JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); + JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 1 + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE, DML_GET_DUP_USING_GSI=FALSE)*/ "; + final String insert = "insert into " + tableName + + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + + "on duplicate key update c5 = values(c5)"; + executeTwiceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, topology.size() + 1 + 1); } /** @@ -1597,27 +1517,15 @@ public void tableWithPkNoUkWithUgsi_partitionByPk2() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ insert into " + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = + "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; + final String insert = "insert into " + tableName + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(1 + 1 + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeTwiceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, 1 + 1 + 1); } /** @@ -1664,25 +1572,13 @@ public void tableWithPkNoUkWithUgsi_partitionByPk22() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName - + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" - + "on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - // final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(3)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; + final String insert = "insert into " + tableName + + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + + "on duplicate key update c5 = values(c5)"; + executeTwiceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, 3); } /** @@ -1731,32 +1627,20 @@ public void tableWithPkNoUkWithUgsi_partitionByPk3_usingGsi() throws SQLExceptio JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ insert into " + final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); + final List> gsiTopology = + JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + + final String hint = + "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; + final String insert = "insert into " + tableName + "(id, c1, c2, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(2, 2, 3, 'b', '2020-06-16 06:49:32'), " + "(1, 2, 3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - final List> gsiTopology = - JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - // primary (partition pruning: 1) + gsi(1 + 1) + update(primary + gsi: 2) - Assert.assertThat(trace.size(), Matchers.is(3 + 1 + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeTwiceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, 3 + 1 + 1); } /** @@ -1805,29 +1689,18 @@ public void tableWithPkNoUkWithUgsi_partitionByPk3() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE,DML_GET_DUP_USING_GSI=FALSE)*/ insert into " + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = + "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE,DML_GET_DUP_USING_GSI=FALSE)*/ "; + final String insert = "insert into " + tableName + "(id, c1, c2, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(2, 2, 3, 'b', '2020-06-16 06:49:32'), " + "(1, 2, 3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(1 + 1 + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeTwiceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, 1 + 1 + 1); } /** @@ -1876,29 +1749,17 @@ public void tableWithPkNoUkWithUgsi_partitionByPk32_usingGsi() throws SQLExcepti JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName + final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); + // final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; + final String insert = "insert into " + tableName + "(id, c1, c2, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(2, 2, 3, 'b', '2020-06-16 06:49:32'), " + "(1, 2, 3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - // final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - // primary (partition pruning: 3) + gsi(partition pruning: 1 + 1) - Assert.assertThat(trace.size(), Matchers.is(3 + 1 + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeTwiceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, 3 + 1 + 1); } /** @@ -1947,28 +1808,16 @@ public void tableWithPkNoUkWithUgsi_partitionByPk32() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_GET_DUP_USING_GSI=FALSE)*/ insert into " + tableName +// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_GET_DUP_USING_GSI=FALSE)*/ "; + final String insert = "insert into " + tableName + "(id, c1, c2, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(2, 2, 3, 'b', '2020-06-16 06:49:32'), " + "(1, 2, 3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - -// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(3)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeTwiceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, 3); } /** @@ -2017,6 +1866,9 @@ public void tableWithPkNoUkWithUgsi_partitionByPk4() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); + // final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); + // final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = "insert into " + tableName + "(id, c1, c2, c5, c8) values" @@ -2034,12 +1886,7 @@ public void tableWithPkNoUkWithUgsi_partitionByPk4() throws SQLException { executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - // final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - // final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - // primary (partition pruning: 3) + cgsi(partition pruning: 1) - Assert.assertThat(trace.size(), Matchers.is(3 + 1)); + checkTraceRowCountIs(3 + 1); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -2098,24 +1945,7 @@ public void tableWithPkWithUkWithGsi_partitionByPk() throws SQLException { + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, - !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(12)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeThriceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, !useAffectedRows, 12); } /** @@ -2164,31 +1994,15 @@ public void tableWithPkWithUkWithUgsi() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; final String insert = "insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; - // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, - !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(3 + 3 + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeThriceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, !useAffectedRows, 3 + 3 + 1); } /** @@ -2237,29 +2051,14 @@ public void tableWithPkWithUkWithUgsi2() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); +// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = "insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, - !useAffectedRows); - final List> trace = getTrace(tddlConnection); - -// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(3 + 3 + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeThriceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, !useAffectedRows, 3 + 3 + 1); } /** @@ -2310,6 +2109,11 @@ public void tableWithPkWithMultiUkWithUgsi_usingGsi() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); + final List> gsiTopology = + JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = "insert into " + tableName + "(c1, c2, c3, c5, c8) values" @@ -2332,15 +2136,7 @@ public void tableWithPkWithMultiUkWithUgsi_usingGsi() throws SQLException { executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - final List> gsiTopology = - JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - // primary (partition pruning: 3) + gsi(partition pruning: 1 + primary partition pruning: 2) + upsert(primary + gsi: 5) - Assert.assertThat(trace.size(), Matchers.is(3 + 1 + 2 + (1 + 2) * 2 - 1)); + checkTraceRowCountIs(3 + 1 + 2 + (1 + 2) * 2 - 1); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, tddlConnection); @@ -2396,6 +2192,8 @@ public void tableWithPkWithMultiUkWithUgsi() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_GET_DUP_USING_GSI=FALSE)*/ "; final String insert = "insert into " + tableName @@ -2419,11 +2217,7 @@ public void tableWithPkWithMultiUkWithUgsi() throws SQLException { executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + (1 + 2) * 2 - 1)); + checkTraceRowCountIs(topology.size() + (1 + 2) * 2 - 1); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, tddlConnection); @@ -2476,6 +2270,8 @@ public void tableWithPkNoUkWithGsi_deleteOnly() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:cmd_extra(GSI_DEBUG=\"GsiStatus1\",DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; final String insert = @@ -2493,11 +2289,7 @@ public void tableWithPkNoUkWithGsi_deleteOnly() throws SQLException { executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(3 + 3 + 1)); + checkTraceRowCountIs(3 + 3 + 1); selectContentSameAssert(checkSql, checkSql + " ignore index(" + gsiName + ")", null, mysqlConnection, tddlConnection); @@ -2555,6 +2347,8 @@ public void tableWithPkNoUkWithGsi_deleteOnly2() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); +// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL:cmd_extra(GSI_DEBUG=\"GsiStatus1\",DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = "insert into " + tableName @@ -2570,11 +2364,7 @@ public void tableWithPkNoUkWithGsi_deleteOnly2() throws SQLException { executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, !useAffectedRows); - final List> trace = getTrace(tddlConnection); - -// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(3 + 3 + 1)); + checkTraceRowCountIs(3 + 3 + 1); selectContentSameAssert(checkSql, checkSql + " ignore index(" + gsiName + ")", null, mysqlConnection, tddlConnection); @@ -2651,6 +2441,8 @@ public void tableWithPkWithUkWithUgsi_deleteOnly_usingGsi() { // no hint here, or bad affected rows when replace executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); + final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); + final String checkSql = "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName; selectContentSameAssert(checkSql, checkSql + " ignore index(" + gsiName + ")", null, mysqlConnection, tddlConnection); @@ -2662,10 +2454,7 @@ public void tableWithPkWithUkWithUgsi_deleteOnly_usingGsi() { JdbcUtil.executeUpdateSuccess(mysqlConnection, "alter table `" + tableName + "` drop index u_c2_c3_1"); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, false); - final List> trace = getTrace(tddlConnection); - - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(7)); + checkTraceRowCountIs(7); selectContentSameAssert(checkSql, checkSql + " ignore index(" + gsiName + ")", null, mysqlConnection, tddlConnection); @@ -2744,6 +2533,8 @@ public void tableWithPkWithUkWithUgsi_deleteOnly() { // no hint here, or bad affected rows when replace executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); + final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); + final String checkSql = "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName; selectContentSameAssert(checkSql, checkSql + " ignore index(" + gsiName + ")", null, mysqlConnection, tddlConnection); @@ -2756,11 +2547,7 @@ public void tableWithPkWithUkWithUgsi_deleteOnly() { JdbcUtil.executeUpdateSuccess(mysqlConnection, "alter table `" + tableName + "` drop index u_c2_c3_1"); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - // primary(partition pruning: 3) + update(primary + gsi: 5) - Assert.assertThat(trace.size(), Matchers.is(7)); + checkTraceRowCountIs(7); selectContentSameAssert(checkSql, checkSql + " ignore index(" + gsiName + ")", null, mysqlConnection, tddlConnection); @@ -2814,37 +2601,22 @@ public void tableWithPkNoUkWithGsi_writeOnly() throws SQLException { + " GLOBAL INDEX " + gsiName + "(`c2`) COVERING(`c5`) PARTITION BY HASH(`c2`) PARTITIONS 3\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"; - final String partitionDef = " partition by hash(`c1`) partitions 7"; - - JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); - JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - - final String hint = - "/*+TDDL: cmd_extra(GSI_DEBUG=\"GsiStatus2\",DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; - final String insert = - "insert into " - + tableName - + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" - + "on duplicate key update c5 = values(c5)"; - // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, - !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String partitionDef = " partition by hash(`c1`) partitions 7"; - Assert.assertThat(trace.size(), Matchers.is(3 + 3 + 1)); + JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); + JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + final String hint = + "/*+TDDL: cmd_extra(GSI_DEBUG=\"GsiStatus2\",DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; + final String insert = + "insert into " + + tableName + + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + + "on duplicate key update c5 = values(c5)"; + // equal when first insert + executeThriceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, !useAffectedRows, 3 + 3 + 1); } /** @@ -2892,30 +2664,15 @@ public void tableWithPkNoUkWithGsi_writeOnly2() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); +// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL: cmd_extra(GSI_DEBUG=\"GsiStatus2\",DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = "insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; // equal when first insert - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, - !useAffectedRows); - final List> trace = getTrace(tddlConnection); - -// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(3 + 3 + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + executeThriceThenCheckGsiDataAndTraceResult(hint, insert, tableName, gsiName, !useAffectedRows, 3 + 3 + 1); } /** @@ -3056,6 +2813,9 @@ public void tableWithPkWithUkWithUgsi_writeOnly_usingGsi() throws SQLException { // equal when first insert executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); + final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); + // final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, @@ -3064,12 +2824,7 @@ public void tableWithPkWithUkWithUgsi_writeOnly_usingGsi() throws SQLException { executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, !useAffectedRows); - final List> trace = getTrace(tddlConnection); - - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - // final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - // primary (3) + gsi(partition pruning: 1 + primary partition pruning: 2) + update(primary + gsi: 5) - Assert.assertThat(trace.size(), Matchers.is(3 + 1 + 2 + 5)); + checkTraceRowCountIs(3 + 1 + 2 + 5); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, tddlConnection); @@ -3124,6 +2879,8 @@ public void tableWithPkWithUkWithUgsi_writeOnly() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = "/*+TDDL: cmd_extra(GSI_DEBUG=\"GsiStatus2\",DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_GET_DUP_USING_GSI=FALSE)*/ "; final String insert = @@ -3148,11 +2905,7 @@ public void tableWithPkWithUkWithUgsi_writeOnly() throws SQLException { executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + (2 + 1) * 2 - 1)); + checkTraceRowCountIs(topology.size() + (2 + 1) * 2 - 1); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, tddlConnection); @@ -3208,6 +2961,9 @@ public void tableWithPkNoUkWithUgsi_multiDuplicateRow_usingGsi() throws SQLExcep JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); + final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); + // final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); + final String insert = "insert into " + tableName + "(id, c1, c2, c5, c8) values(1, 1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 2, 'b', '2020-06-16 06:49:32'), (3, 3, 3, 'c', '2020-06-16 06:49:32')"; executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); @@ -3216,16 +2972,12 @@ public void tableWithPkNoUkWithUgsi_multiDuplicateRow_usingGsi() throws SQLExcep selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - final String upsert = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE)*/"; + final String upsert = " insert into " + tableName + "(id, c1, c2, c5, c8) values(2, 1, 1, 'd', '2020-06-16 06:49:32') on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsert, "trace " + upsert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - // final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); - // primary (all primary gsi table) + gsi(partition pruning: 1 + primary partition pruning: 1) + update(primary + gsi: 2) - Assert.assertThat(trace.size(), Matchers.is(primaryTopology.size() + 1 + 1 + 2)); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsert, "trace " + hint + upsert, null, true); + checkTraceRowCountIs(primaryTopology.size() + 1 + 1 + 2); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -3280,6 +3032,8 @@ public void tableWithPkNoUkWithUgsi_multiDuplicateRow() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String insert = "insert into " + tableName + "(id, c1, c2, c5, c8) values(1, 1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 2, 'b', '2020-06-16 06:49:32'), (3, 3, 3, 'c', '2020-06-16 06:49:32')"; executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); @@ -3288,16 +3042,13 @@ public void tableWithPkNoUkWithUgsi_multiDuplicateRow() throws SQLException { selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_GET_DUP_USING_GSI=FALSE)*/ "; final String upsert = - "/*+TDDL:CMD_EXTRA(DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_GET_DUP_USING_GSI=FALSE)*/ insert into " + tableName + "insert into " + tableName + "(id, c1, c2, c5, c8) values(2, 1, 1, 'd', '2020-06-16 06:49:32') on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsert, "trace " + upsert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 2)); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsert, "trace " + hint + upsert, null, true); + checkTraceRowCountIs(topology.size() + 2); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -3430,28 +3181,26 @@ public void tableWithPkNoUkWithUgsi_multiDuplicateRow1() throws SQLException { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, mysqlCreatTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_USING_GSI=FALSE)*/ insert into " + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_USING_GSI=FALSE)*/ "; + final String insert = "insert into " + tableName + "(id, c1, c2, c5, c8) values(1, 1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 2, 'b', '2020-06-16 06:49:32'), (3, 3, 3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); checkGsi(tddlConnection, getRealGsiName(tddlConnection, tableName, gsiName)); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - final String upsert = - "/*+TDDL:CMD_EXTRA(DML_GET_DUP_USING_GSI=FALSE)*/ insert into " + tableName + "(id, c1, c2, c5, c8) values" + final String upsert = "insert into " + tableName + "(id, c1, c2, c5, c8) values" + "(4, 4, 4, 'e', '2020-06-16 06:49:32')," + "(2, 1, 1, 'f', '2020-06-16 06:49:32')," + "(5, 5, 5, 'g', '2020-06-16 06:49:32')," + "(3, 1, 4, 'h', '2020-06-16 06:49:32')" + "on duplicate key update c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsert, "trace " + upsert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 4 * 2)); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsert, "trace " + hint + upsert, null, true); + checkTraceRowCountIs(topology.size() + 4 * 2); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); @@ -3485,22 +3234,29 @@ public void tableWithPkNoUk_modifyPk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = - "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName + "insert into " + tableName + "(id, c1, c5, c8) values(4, 1, 'a', '2020-06-16 06:49:32'), (5, 2, 'b', '2020-06-16 06:49:32'), (6, 3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c1 = c1 + 3"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -3578,7 +3334,10 @@ public void tableWithPkWithMultiUk_modifyUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ "; + final String insert = "insert into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, update @@ -3588,15 +3347,22 @@ public void tableWithPkWithMultiUk_modifyUk() { + "(1, 2, 4, 'f', '2020-06-16 06:49:32')" // u_c1_c2 冲突,update + "on duplicate key update c2 = c2 + 1, c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 2)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeOnceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.is(topology.size() + 2)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeOnceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.lessThanOrEqualTo(2 + 2)); } @Test @@ -3612,17 +3378,18 @@ public void tableWithPkNoUk_broadcast() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ insert into " + tableName +// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ "; + final String insert = "insert into " + tableName + "(a,b) values(1+2-2,1) on duplicate key update b=b+20"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + hint + insert, null, true); final List> trace = getTrace(tddlConnection); -// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - final int nodeNum = getNodeNum(tddlConnection); Assert.assertThat(trace.size(), Matchers.is(nodeNum + 1)); @@ -3702,19 +3469,7 @@ public void tableWithPkNoUkWithGsi_pushdownUpsert() { + "( 20 , 'safdwe', 62, 'kisfe', 93, 0, 91, 57, 52, 250.4874, 1000000000, '2015-11-23', '12:12:12', '2013-02-05', '2013-02-05 12:27:32', '2005'), " + "( 22 , 'feed32feed', 13, 'abdfeed', 18, 0, 74, 85, 85, 21.258, 1000, '2013-02-05', '06:34:12', '2011-06-22', '2013-09-02 14:47:28', '2018')" + "ON DUPLICATE KEY UPDATE mediumint_test= double_test / 49"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - -// final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(10)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, - tddlConnection); + executeTwiceThenCheckDataAndTraceResult("", insert, "select * from " + tableName, Matchers.is(10)); } /** @@ -3745,22 +3500,15 @@ public void tableWithPkWithUk_upsertIgnore() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=TRUE)*/ "; final String insert = - "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=TRUE)*/ insert ignore into " + "insert ignore into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (null, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - Assert.assertThat(trace.size(), Matchers.is(3)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + executeTwiceThenCheckDataAndTraceResult(hint, + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + Matchers.is(3)); } /** @@ -3827,6 +3575,8 @@ public void tableWithPkWithMultiUk_modifyPartitionKey_testPhySqlId() throws Exce JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + JdbcUtil.executeUpdate(tddlConnection, "set polardbx_server_id = 27149"); final String insert = "insert into " + tableName @@ -3839,22 +3589,59 @@ public void tableWithPkWithMultiUk_modifyPartitionKey_testPhySqlId() throws Exce + "(1, 2, 4, 'f', '2020-06-16 06:49:32')" // u_c1_c2 冲突,update + "on duplicate key update c1 = c1 + 1, c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + insert, + "trace " + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ " + insert, + null, + true); + List> trace = getTrace(tddlConnection); checkPhySqlId(trace); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7"); - final List> mysqlResult = - selectContentSameAssert("select " + String.join(",", columnNames) + " from " + tableName, null, - mysqlConnection, tddlConnection); + List> mysqlResult = selectContentSameAssert(buildSqlCheckData(columnNames, tableName), + null, + mysqlConnection, + tddlConnection); + + JdbcUtil.assertRouteCorrectness(hint, + tableName, + mysqlResult, + columnNames, + ImmutableList.of("c1"), + tddlConnection); - JdbcUtil - .assertRouteCorrectness(hint, tableName, mysqlResult, columnNames, ImmutableList.of("c1"), tddlConnection); + // Clear data + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + insert, + "trace " + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ " + insert, + null, + true); + trace = getTrace(tddlConnection); + + checkPhySqlId(trace); + + Assert.assertThat(trace.size(), Matchers.lessThanOrEqualTo(3 + 3)); + + mysqlResult = selectContentSameAssert(buildSqlCheckData(columnNames, tableName), + null, + mysqlConnection, + tddlConnection); + + JdbcUtil.assertRouteCorrectness(hint, + tableName, + mysqlResult, + columnNames, + ImmutableList.of("c1"), + tddlConnection); } /** @@ -4281,7 +4068,8 @@ public void checkHugeBatchUpsertTraceId() throws SQLException { @Test public void testLogicalUpsert() throws SQLException { - String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/"; + String hint = + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint, "insert into", "upsert_test_tbl", " partition by hash(id) PARTITIONS 3", false, true, true, @@ -4389,7 +4177,8 @@ private void testComplexDmlInternal(String hint, String op, String tableName, St @Test public void testLogicalUpsertUsingIn() throws SQLException { - String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_GET_DUP_USING_IN=TRUE)*/"; + String hint = + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_GET_DUP_USING_IN=TRUE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint, "insert into", "upsert_test_tbl", " partition by hash(id) PARTITIONS 3", false, true, true, @@ -4407,6 +4196,51 @@ public void testLogicalUpsertUsingIn() throws SQLException { UPSERT_PARAMS); } + private static final String[][] UPSERT_PARAMS_1 = new String[][] { + new String[] { + "(id,a,b)", "values (1,2,2),(100,101,101),(101,102,102)", "(id,a,b)", + "values (1,2,2),(100,101,101),(101,102,102)"}, + new String[] { + "(id,a,b)", "values (1,5,5),(2,3,3) on duplicate key update a=id+2,b=id+2", "(id,a,b)", + "values (1,5,5),(2,3,3) on duplicate key update a=id+2,b=id+2"}, + new String[] { + "(id,a,b)", "values (1,5,5),(2,3,3) on duplicate key update a=values(a),b=values(a)", "(id,a,b)", + "values (1,5,5),(2,3,3) on duplicate key update a=values(a),b=values(a)"}, + new String[] { + "(id,a,b)", "values (1,5,5),(2,3,3) on duplicate key update id=id+10", "(id,a,b)", + "values (1,5,5),(2,3,3) on duplicate key update id=id+10"}, + new String[] { + "(id,a,b)", + String.format("select * from %s where id=100 ", SOURCE_TABLE_NAME) + "on duplicate key update id=id+10,a=a", + "(id,a,b)", "values (100,101,101) on duplicate key update id=id+10,a=a"}, + new String[] { + "(id,a,b)", + String.format("select * from %s where id>100 order by id ", SOURCE_TABLE_NAME) + + "on duplicate key update id=id+10,a=b", + "(id,a,b)", "values (101,102,102),(102,103,103) on duplicate key update id=id+10,a=b"} + }; + + @Test + public void testLogicalUpsertWithoutFullTableScan() throws SQLException { + String hint = + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=FALSE)*/"; + + testComplexDmlInternal(hint, "insert into", "upsert_test_tbl", " partition by hash(id) PARTITIONS 3", false, + true, true, + UPSERT_PARAMS_1); + testComplexDmlInternal(hint, "insert into", "upsert_test_tbl_brd", " broadcast", false, true, false, + UPSERT_PARAMS_1); + testComplexDmlInternal(hint, "insert into", "upsert_test_tbl_single", " single", false, true, false, + UPSERT_PARAMS_1); + testComplexDmlInternal(hint, "insert into", "upsert_test_tbl", " partition by hash(id) PARTITIONS 3", true, + true, true, + UPSERT_PARAMS_1); + testComplexDmlInternal(hint, "insert into", "upsert_test_tbl_brd", " broadcast", true, true, false, + UPSERT_PARAMS_1); + testComplexDmlInternal(hint, "insert into", "upsert_test_tbl_single", " single", true, true, false, + UPSERT_PARAMS_1); + } + @Test public void testUpsertUGSI() throws SQLException { final String tableName = "upsert_ugsi_tbl"; @@ -4426,7 +4260,7 @@ public void testUpsertUGSI() throws SQLException { + "(`b`) partition by range(`b`) (partition p0 values less than(0), partition p1 values less than(10), partition p2 values less than MAXVALUE)"; JdbcUtil.executeUpdateSuccess(tddlConnection, createIndex); - String insertSql = "insert into " + tableName + " values (3,3,5),(3,4,-5)"; + String insertSql = "insert into " + tableName + " values (2,3,5),(3,4,-5)"; JdbcUtil.executeUpdateSuccess(tddlConnection, insertSql); String upsertSql = "insert into " + tableName + " values (4,4,-5) on duplicate key update b=11"; @@ -4611,7 +4445,7 @@ private void testUpsertSingleShardInternal(String tableName, String upsertSql, S } @Test - public void testUpsertSingleShardMultiSk() { + public void testUpsertSingleShardMultiSk_fullTableScan() { String tableName = "test_upsert_single_shard_pk_tbl"; String createSql = String.format("create table %s (a int primary key, b int, c int)", tableName); String partDef = "partition by hash(a,b) partitions 3"; @@ -4621,65 +4455,232 @@ public void testUpsertSingleShardMultiSk() { JdbcUtil.executeUpdateSuccess(mysqlConnection, createSql); JdbcUtil.executeUpdateSuccess(tddlConnection, createSql + partDef); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + final String hint = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; + // all after value, pushdown String upsertSql = String.format("insert into %s values (1,2,3) on duplicate key update a=values(a),b=values(b),c=c", tableName); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsertSql, "trace " + upsertSql, null, true); - List> trace = getTrace(tddlConnection); - Assert.assertEquals(1, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=2", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(1)); // all before value, pushdown upsertSql = String.format("insert into %s values (1,2,4) on duplicate key update a=a,b=b,c=c", tableName); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsertSql, "trace " + upsertSql, null, true); - trace = getTrace(tddlConnection); - Assert.assertEquals(1, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=2", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(1)); // after value and before value, do not pushdown upsertSql = String.format("insert into %s values (1,2,5) on duplicate key update a=values(a),b=b,c=c", tableName); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsertSql, "trace " + upsertSql, null, true); - trace = getTrace(tddlConnection); - Assert.assertEquals(3, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=2", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(3)); + // after value with different column, do not pushdown upsertSql = String.format("insert into %s values (1,2,6) on duplicate key update a=values(a),b=values(a),c=c", tableName); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsertSql, "trace " + upsertSql, null, true); - trace = getTrace(tddlConnection); - Assert.assertEquals(5, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=1", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=1", + Matchers.is(3 + 2)); // before value with different column , do not pushdown upsertSql = String.format("insert into %s values (1,2,7) on duplicate key update a=a,b=a,c=c", tableName); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsertSql, "trace " + upsertSql, null, true); - trace = getTrace(tddlConnection); - Assert.assertEquals(3, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=1", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=1", + Matchers.is(3)); + + // part after value, can pushdown + // a is primary key, if duplicated happens, a.oldValue = a.newValue + // b is one of partition key, if duplicated happens, b.oldValue and b.newValue are at same partition, because we route upsert using b.newValue + upsertSql = String.format("insert into %s values (1,3,8) on duplicate key update b=values(b),c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(1)); // part after value, do not pushdown + upsertSql = String.format("insert into %s values (1,2,8) on duplicate key update a=values(a),c=c+1", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(3 + 1)); + + // part before value, pushdown + upsertSql = String.format("insert into %s values (1,2,10) on duplicate key update b=b,c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(1)); + } + + @Test + public void testUpsertSingleShardMultiSk() { + String tableName = "test_upsert_single_shard_pk_tbl"; + String createSql = String.format("create table %s (a int primary key, b int, c int)", tableName); + String partDef = "partition by hash(a,b) partitions 3"; + + dropTableIfExists(tableName); + dropTableIfExistsInMySql(tableName); + JdbcUtil.executeUpdateSuccess(mysqlConnection, createSql); + JdbcUtil.executeUpdateSuccess(tddlConnection, createSql + partDef); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + final String hint = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; + + // all after value, pushdown + String upsertSql = + String.format("insert into %s values (1,2,3) on duplicate key update a=values(a),b=values(b),c=c", + tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(1)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 2 | 3 || 1 | 2 | 3 | + * +-----------++-----------+ + */ + + // all before value, pushdown + upsertSql = String.format("insert into %s values (1,2,4) on duplicate key update a=a,b=b,c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(1)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 2 | 3 || 1 | 2 | 3 | + * +-----------++-----------+ + */ + + // after value and before value, do not pushdown + upsertSql = + String.format("insert into %s values (1,2,5) on duplicate key update a=values(a),b=b,c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(1)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 2 | 3 || 1 | 2 | 3 | + * +-----------++-----------+ + */ + + // after value with different column, do not pushdown + upsertSql = String.format("insert into %s values (1,2,6) on duplicate key update a=values(a),b=values(a),c=c", + tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=1", + Matchers.is(1 + 2)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 1 | 3 || 1 | 1 | 3 | + * +-----------++-----------+ + */ + + // before value with different column , do not pushdown + upsertSql = String.format("insert into %s values (1,2,7) on duplicate key update a=a,b=a,c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=1", + Matchers.is(1)); + + // partitioning results of "a=1 and b=1" and "a=1 and b=2" are same; + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 1 | 3 || 1 | 1 | 3 | + * +-----------++-----------+ + */ + + // part after value, can pushdown + // a is primary key, if duplicated happens, a.oldValue = a.newValue + // b is one of partition key, if duplicated happens, b.oldValue and b.newValue are at same partition, because we route upsert using b.newValue upsertSql = String.format("insert into %s values (1,3,8) on duplicate key update b=values(b),c=c", tableName); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsertSql, "trace " + upsertSql, null, true); - trace = getTrace(tddlConnection); - Assert.assertEquals(5, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=3", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(1)); + + // partitioning results of "a=1 and b=1" and "a=1 and b=3" are same; + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 3 | 3 || 1 | 3 | 3 | + * +-----------++-----------+ + */ + + // part after value, do not pushdown + upsertSql = String.format("insert into %s values (1,2,8) on duplicate key update a=values(a),c=c+1", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(1 + 1)); + + // partitioning results of "a=1 and b=3" and "a=1 and b=2" are same; + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 3 | 4 || 1 | 3 | 4 | + * +-----------++-----------+ + */ // part before value, pushdown - upsertSql = String.format("insert into %s values (1,2,9) on duplicate key update b=b,c=c", tableName); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsertSql, "trace " + upsertSql, null, true); - trace = getTrace(tddlConnection); - Assert.assertEquals(1, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=3", null, mysqlConnection, - tddlConnection); + upsertSql = String.format("insert into %s values (1,2,10) on duplicate key update b=b,c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(1)); + + // partitioning results of "a=1 and b=2" and "a=1 and b=3" are same; + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 3 | 4 || 1 | 3 | 4 | + * +-----------++-----------+ + */ } @Test @@ -4697,12 +4698,22 @@ public void testUpsertSingleShardMultiSk1() { String upsertSql = String.format("insert into %s values (1,2,3)", tableName); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsertSql, "trace " + upsertSql, null, true); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + String hint = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; upsertSql = String.format("insert into %s values (1,10,11) on duplicate key update b=values(b)", tableName); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsertSql, "trace " + upsertSql, null, true); - - List> trace = getTrace(tddlConnection); - Assert.assertEquals(4, trace.size()); - selectContentSameAssert("select * from " + tableName + " where b=10 and c=3", null, mysqlConnection, + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where b=10 and c=3", + Matchers.is(4)); + +// executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + hint = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; + upsertSql = String.format("insert into %s values (1,13,4) on duplicate key update b=values(b)", tableName); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, upsertSql, "trace " + hint + upsertSql, null, false); + checkTraceRowCount(Matchers.lessThanOrEqualTo(3)); + selectContentSameAssert("select * from " + tableName + " where b=13 and c=3", null, mysqlConnection, tddlConnection); } @@ -5498,11 +5509,13 @@ public void testBinaryFunc2() { selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); } + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + final String hint = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; for (int i = 0; i < binaryValues.length; i++) { String insert = String.format("insert into %s values (%d,%s) on duplicate key update a=a+10, b=%s", tableName, i + 10, binaryValues[i], binaryValues[i]); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, hint + insert, null, true); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); } @@ -5566,8 +5579,7 @@ public void testMultipleSKChecker1() { String.format("insert into %s values (1,3,7) on duplicate key update a=values(a),c=values(c)", tableName); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - Assert.assertThat(trace.size(), Matchers.is(6)); + checkTraceRowCountIs(6); } @Test @@ -5598,8 +5610,7 @@ public void testMultipleSKChecker2() { tableName); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - Assert.assertThat(trace.size(), Matchers.is(6)); + checkTraceRowCountIs(6); } @Test diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/locality/LocalityTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/locality/LocalityTest.java index 34aaf079c..bfc589c6f 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/locality/LocalityTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/locality/LocalityTest.java @@ -27,8 +27,11 @@ import org.junit.Test; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.TreeSet; +import java.util.stream.Collectors; @NotThreadSafe public class LocalityTest extends LocalityTestBase { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/locality/LocalityTestBase.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/locality/LocalityTestBase.java index 52d5b6df7..2cd36319d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/locality/LocalityTestBase.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/locality/LocalityTestBase.java @@ -25,12 +25,18 @@ import org.apache.commons.lang.BooleanUtils; import org.junit.Assert; import org.junit.Before; -import org.springframework.util.StringUtils; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; @@ -68,13 +74,17 @@ protected TableDetails queryTableDetails(String schema, String tableName) throws return queryTableDetails(schema, tableName, tddlConnection); } + public String quote(String str) { + return (str != null ? "\"" + str + "\"" : null); + } + /** * Query the approximate data length of the table */ protected TableDetails queryTableDetails(String schema, String tableName, Connection conn) throws SQLException { final String fromClause = " from information_schema.table_detail"; final String whereClause = - " where TABLE_SCHEMA = " + StringUtils.quote(schema) + " and table_name = " + StringUtils.quote(tableName); + " where TABLE_SCHEMA = " + quote(schema) + " and table_name = " + quote(tableName); final String summarySql = "select table_group_name, sum(data_length), sum(index_length), sum(table_rows) " + fromClause + whereClause; final String selectColumns = diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/movepartition/UGsiMovePartitionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/movepartition/UGsiMovePartitionTest.java new file mode 100644 index 000000000..ae8093309 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/movepartition/UGsiMovePartitionTest.java @@ -0,0 +1,115 @@ +package com.alibaba.polardbx.qatest.ddl.auto.movepartition; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashSet; +import java.util.Set; + +public class UGsiMovePartitionTest extends DDLBaseNewDBTestCase { + private static final String DROP_DB_HINT = "ALLOW_DROP_DATABASE_IN_SCALEOUT_PHASE=true"; + + static private final String DATABASE_NAME = "UGsiMovePartitionTest"; + private static final String TABLE_NAME = "tb1"; + private static final String MOVE_PARTITION_GROUPS = "p1"; + private static final String SHOW_DS = "show ds where db='%s'"; + private static final String MOVE_PARTITION_COMMAND = "alter tablegroup by table %s move partitions %s to '%s'"; + + private static final String SELECT_FROM_TABLE_DETAIL = + "select storage_inst_id,table_group_name from information_schema.table_detail where table_schema='%s' and table_name='%s' and partition_name='%s'"; + + private static final String CREATE_TABLE_SQL = + "create table `%s` (`a` int(11) primary key auto_increment, `b` int(11), `c` timestamp DEFAULT CURRENT_TIMESTAMP) "; + + private static final String CREATE_UGSI_SQL = "alter table `%s` add unique global index uk_b(b)"; + + private static final String DROP_TABLE_SQL = "drop table if exists `%s` "; + + private static String buildCmdExtra(String... params) { + if (0 == params.length) { + return ""; + } + return "/*+TDDL:CMD_EXTRA(" + String.join(",", params) + ")*/"; + } + + @Before + public void before() { + doReCreateDatabase(); + } + + @After + public void after() { + doClearDatabase(); + } + + @Test + public void testUGsiMovePartition() throws SQLException { + // create table + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(DROP_TABLE_SQL, TABLE_NAME)); + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(CREATE_TABLE_SQL, TABLE_NAME)); + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(CREATE_UGSI_SQL, TABLE_NAME)); + + // move partitions + String movePartitionsCommand = prepareAutoDbCommands(tddlConnection); + if (movePartitionsCommand == null) { + return; + } + + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(movePartitionsCommand, TABLE_NAME)); + } + + private static String prepareAutoDbCommands(Connection connection) throws SQLException { + Set instIds = new HashSet<>(); + String curInstId = null; + + String sql = "use " + DATABASE_NAME; + JdbcUtil.executeUpdate(connection, sql); + sql = String.format(SELECT_FROM_TABLE_DETAIL, DATABASE_NAME, TABLE_NAME, MOVE_PARTITION_GROUPS); + + ResultSet rs = JdbcUtil.executeQuery(sql, connection); + if (rs.next()) { + curInstId = rs.getString("STORAGE_INST_ID"); + } else { + throw new RuntimeException( + String.format("not find database table %s.%s", DATABASE_NAME, TABLE_NAME)); + } + rs.close(); + + sql = String.format(SHOW_DS, DATABASE_NAME); + rs = JdbcUtil.executeQuery(sql, connection); + while (rs.next()) { + if (!curInstId.equalsIgnoreCase(rs.getString("STORAGE_INST_ID"))) { + instIds.add(rs.getString("STORAGE_INST_ID")); + } + } + rs.close(); + + if (!instIds.isEmpty()) { + // move partition p1 + return String.format(MOVE_PARTITION_COMMAND, TABLE_NAME, MOVE_PARTITION_GROUPS, instIds.iterator().next()); + } + return null; + } + + void doReCreateDatabase() { + doClearDatabase(); + String tddlSql = "use information_schema"; + JdbcUtil.executeUpdate(tddlConnection, tddlSql); + tddlSql = "create database " + DATABASE_NAME + " partition_mode = 'auto'"; + JdbcUtil.executeUpdate(tddlConnection, tddlSql); + tddlSql = "use " + DATABASE_NAME; + JdbcUtil.executeUpdate(tddlConnection, tddlSql); + } + + void doClearDatabase() { + JdbcUtil.executeUpdate(getTddlConnection1(), "use information_schema"); + String tddlSql = buildCmdExtra(DROP_DB_HINT) + "drop database if exists " + DATABASE_NAME; + JdbcUtil.executeUpdate(getTddlConnection1(), tddlSql); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/base/PkRangeTestParam.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/base/PkRangeTestParam.java new file mode 100644 index 000000000..21be71369 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/base/PkRangeTestParam.java @@ -0,0 +1,386 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.base; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.executor.ddl.job.task.backfill.LogicalTableGsiPkRangeBackfillTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.ImportTableSpaceDdlTask; +import com.alibaba.polardbx.executor.ddl.job.task.basic.PhysicalBackfillTask; +import com.alibaba.polardbx.executor.ddl.job.task.gsi.SperateCheckGsiTask; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange.PkTest; +import com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DataManipulateUtil; +import com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import lombok.Data; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DataManipulateUtil.prepareData; + +@Data +public class PkRangeTestParam { + final static Log log = LogFactory.getLog(PkTest.class); + public static final String inspectDdlEngineStatusSql = + "select task_name, task_state, execution_time, node_ip from information_schema.ddl_scheduler where task_name != \"SubJobTask\" order by task_state;"; + + public static final String inspectFullDdlEngineStatusSql = + "show ddl engine status;"; + + public PkRangeTestParam(String schemaName, String originalTableName, String gsiTableName, + String createTableStmt, + String addGsiStmt, int partNum, int gsiPartNum, int eachPartRows, Boolean enablePkRange, + Boolean enableLocalIndexLater) { + this.schemaName = schemaName; + this.originalTableName = originalTableName; + this.gsiTableName = gsiTableName; + this.createTableStmt = createTableStmt; + this.addGsiStmt = addGsiStmt; + this.partNum = partNum; + this.eachPartRows = eachPartRows; + this.enablePkRange = enablePkRange; + this.gsiPartNum = gsiPartNum; + this.enableLocalIndexLater = enableLocalIndexLater; + this.expectedPkRangeNum = enablePkRange ? 1 : 0; + this.pkRangeSize = "2kB"; + this.taskRangeSize = "16kB"; + this.expectedLocalIndexConcurrency = -1; + this.expectedPkRange = enablePkRange; + this.expectedLocalIndexLater = enableLocalIndexLater; + this.mppTaskAllocationCheck = false; + } + + public String schemaName; + public String originalTableName; + public String gsiTableName; + public String createTableStmt; + public String addGsiStmt; + public int partNum; + public int gsiPartNum; + public int eachPartRows; + public Boolean enablePkRange; + public Boolean enableLocalIndexLater; + public Boolean expectedPkRange; + public Boolean expectedLocalIndexLater; + public long expectedPkRangeNum; + public String pkRangeSize; + public String taskRangeSize; + public int expectedLocalIndexConcurrency; + // for pause and continue test + public long sleepInterval; + public long checkInterval; + public Boolean mppTaskAllocationCheck; + + public static void baseTest(PkRangeTestParam pkRangeTestParam, Connection connection) + throws Exception { + String schemaName = pkRangeTestParam.schemaName; + String originalTableName = pkRangeTestParam.originalTableName; + String gsiName = pkRangeTestParam.gsiTableName; + String createTableStmt = pkRangeTestParam.createTableStmt; + int partNum = pkRangeTestParam.partNum; + int gsiPartNum = pkRangeTestParam.gsiPartNum; + int eachPartRows = pkRangeTestParam.eachPartRows; + Boolean enablePkRange = pkRangeTestParam.enablePkRange; + Boolean buildLocalIndexLater = pkRangeTestParam.enableLocalIndexLater; + String addGsiStmt = pkRangeTestParam.addGsiStmt; + String taskRangeSize = pkRangeTestParam.taskRangeSize; + String pkRangeSize = pkRangeTestParam.pkRangeSize; + long expectedPkRangeNum = pkRangeTestParam.expectedPkRangeNum; + int expectedLocalIndexConcurrency = pkRangeTestParam.expectedLocalIndexConcurrency; + Boolean expectedBuildLocalIndexLater = pkRangeTestParam.expectedLocalIndexLater; + Boolean expectedPkRange = pkRangeTestParam.expectedPkRange; + Boolean mppTaskAllocationCheck = pkRangeTestParam.mppTaskAllocationCheck; + String addGsiDdl = String.format(addGsiStmt, originalTableName, gsiName, gsiPartNum); + String addGsiHint = + String.format( + "/*+TDDL:CMD_EXTRA(PURE_ASYNC_DDL_MODE=true,GSI_BACKFILL_BY_PK_RANGE=%s,GSI_BUILD_LOCAL_INDEX_LATER=%s,BACKFILL_MAX_TASK_PK_RANGE_SIZE=%s,BACKFILL_MAX_PK_RANGE_SIZE=%s," + + "GSI_JOB_MAX_PARALLELISM=16,GSI_PK_RANGE_CPU_ACQUIRE=6,FORBID_REMOTE_DDL_TASK=%s)*/", + enablePkRange, buildLocalIndexLater, taskRangeSize, pkRangeSize, !mppTaskAllocationCheck); + + final Logger logger = LoggerFactory.getLogger(DdlStateCheckUtil.class); + if (!StringUtils.isEmpty(createTableStmt)) { + prepareData(connection, schemaName, originalTableName, eachPartRows, createTableStmt, + partNum, DataManipulateUtil.TABLE_TYPE.PARTITION_TABLE); + String analyzeTableSql = String.format("analyze table %s", originalTableName); + DdlStateCheckUtil.alterTableViaJdbc(connection, schemaName, originalTableName, analyzeTableSql); + } + DdlStateCheckUtil.alterTableViaJdbc(connection, schemaName, originalTableName, addGsiHint + addGsiDdl); + Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(connection, addGsiDdl); + String msg = + String.format("jobId: %d, table: %s, addGsiDdl: %s", jobId, originalTableName, addGsiHint + addGsiDdl); + logger.info(String.format("wait for ddl %d...", jobId)); + if (!DdlStateCheckUtil.waitTillDdlDone(connection, jobId, originalTableName, expectedLocalIndexConcurrency, + mppTaskAllocationCheck)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("wait addGsiDdl done timeout for %s", msg)); + } + logger.info(String.format("ddl %d finished...", jobId)); + if (!DdlStateCheckUtil.checkIfCompleteSuccessful(connection, jobId)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("this job failed for some unknown reason!!! %s", msg)); + } + List errMsg = new ArrayList<>(); + if (!DdlStateCheckUtil.checkIfExecuteByPkRangeAndBuildLocalIndexLater(connection, jobId, expectedPkRange, + expectedBuildLocalIndexLater, expectedPkRangeNum, errMsg)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format( + "this job success, but we don't expect that pkRange and localIndexLater behave in this way !!! %s, %s", + msg, errMsg.get(0))); + } + if (!DdlStateCheckUtil.checkIfBackfillSampleRowsArchived(connection, jobId, !expectedPkRange)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format( + "this job success, but we don't expect the sample rows archived failed! for %d", jobId)); + } + if (!StringUtils.isEmpty(createTableStmt) && !DdlStateCheckUtil.compareForLocalIndex(connection, schemaName, + jobId, originalTableName, createTableStmt, + addGsiStmt, gsiName, partNum, errMsg)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("this job success but local key is not right!! %s, %s", msg, errMsg.get(0))); + } + } + + public static void showDdlTest(PkRangeTestParam pkRangeTestParam, Connection connection, Boolean withSubjob) + throws Exception { + showDdlTest(pkRangeTestParam, connection, withSubjob, false, false); + } + + public static void showDdlTest(PkRangeTestParam pkRangeTestParam, Connection connection, Boolean withSubjob, + Boolean showDdlEngineTest, Boolean physicalBackfill) + throws Exception { + String schemaName = pkRangeTestParam.schemaName; + String originalTableName = pkRangeTestParam.originalTableName; + String gsiName = pkRangeTestParam.gsiTableName; + String createTableStmt = pkRangeTestParam.createTableStmt; + int partNum = pkRangeTestParam.partNum; + int gsiPartNum = pkRangeTestParam.gsiPartNum; + int eachPartRows = pkRangeTestParam.eachPartRows; + Boolean enablePkRange = pkRangeTestParam.enablePkRange; + Boolean buildLocalIndexLater = pkRangeTestParam.enableLocalIndexLater; + String taskRangeSize = pkRangeTestParam.taskRangeSize; + String pkRangeSize = pkRangeTestParam.pkRangeSize; + String addGsiStmt = pkRangeTestParam.addGsiStmt; + String addGsiDdl = String.format(addGsiStmt, originalTableName, gsiName, gsiPartNum); + String addGsiHint = + String.format( + "/*+TDDL:CMD_EXTRA(PURE_ASYNC_DDL_MODE=true,GSI_BACKFILL_BY_PK_RANGE=%s,GSI_BUILD_LOCAL_INDEX_LATER=%s,BACKFILL_MAX_TASK_PK_RANGE_SIZE=%s,PHYSICAL_BACKFILL_ENABLE=true,PHYSICAL_BACKFILL_MAX_SLAVE_LATENCY=4000000000,FORBID_REMOTE_DDL_TASK=%s)*/", + enablePkRange, buildLocalIndexLater, taskRangeSize, !physicalBackfill); + final Logger logger = LoggerFactory.getLogger(DdlStateCheckUtil.class); + prepareData(connection, schemaName, originalTableName, eachPartRows, createTableStmt, + partNum, DataManipulateUtil.TABLE_TYPE.PARTITION_TABLE); + DdlStateCheckUtil.alterTableViaJdbc(connection, schemaName, originalTableName, addGsiHint + addGsiDdl); + Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(connection, addGsiDdl); + String msg = + String.format("jobId: %d, table: %s, addGsiDdl: %s", jobId, originalTableName, addGsiHint + addGsiDdl); + List> showDdlResult = null; + List> showFullDdlResult = null; + List> showDdlEngineStatusResult = null; + int maxRecordNum = 0; + int maxTaskRecordNum = 0; + if (!showDdlEngineTest) { + for (int i = 0; i < 3; i++) { + showDdlResult = JdbcUtil.getAllResult(JdbcUtil.executeQuery("show ddl", connection)); + maxRecordNum = Math.max(maxRecordNum, showDdlResult.size()); + if(!physicalBackfill) { + if (showFullDdlResult != null) { + DdlStateCheckUtil.compareShowDdlResult(showFullDdlResult, showDdlResult); + } + showFullDdlResult = + JdbcUtil.getAllResult(JdbcUtil.executeQuery("show full ddl", connection)); + DdlStateCheckUtil.compareShowDdlResult(showDdlResult, showFullDdlResult); + } + showDdlEngineStatusResult = + JdbcUtil.getAllResult(JdbcUtil.executeQuery(inspectDdlEngineStatusSql, connection)); + maxTaskRecordNum = Math.max(maxTaskRecordNum, showDdlEngineStatusResult.size()); + Thread.sleep(1000L); + } + logger.info(String.format("wait for ddl %d ...", jobId)); + if (!DdlStateCheckUtil.waitTillDdlDone(connection, jobId, originalTableName)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("wait addGsiDdl done timeout for %s", msg)); + } + logger.info(String.format("ddl %d finished...", jobId)); +// if (maxTaskRecordNum < 1) { +// throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, +// String.format("expected record occur in show ddl engine status", msg)); +// } + } else { + int maxPkRangeBackfillTaskRecordNum = 0; + int maxCheckerTaskRecordNum = 0; + int maxPhysicalBackfillTaskRecordNum = 0; + int maxImportTableSpaceTaskRecordNum = 0; + while (!DdlStateCheckUtil.checkIfTerminate(connection, jobId)) { + logger.info(String.format("show ddl check...")); + showDdlResult = JdbcUtil.getAllResult(JdbcUtil.executeQuery("show ddl", connection)); + maxRecordNum = Math.max(maxRecordNum, showDdlResult.size()); + if(!physicalBackfill) { + if (showFullDdlResult != null) { + DdlStateCheckUtil.compareShowDdlResult(showFullDdlResult, showDdlResult); + } + showFullDdlResult = + JdbcUtil.getAllResult(JdbcUtil.executeQuery("show full ddl", connection)); + DdlStateCheckUtil.compareShowDdlResult(showDdlResult, showFullDdlResult); + } + showDdlEngineStatusResult = + JdbcUtil.getAllResult(JdbcUtil.executeQuery(inspectFullDdlEngineStatusSql, connection)); + logger.info(String.format("get ddl engine status...")); + maxTaskRecordNum = Math.max(maxTaskRecordNum, showDdlEngineStatusResult.size()); + maxPhysicalBackfillTaskRecordNum = + getMaxTaskRecordNum(showDdlEngineStatusResult, maxPhysicalBackfillTaskRecordNum, + PhysicalBackfillTask.class.getName()); + maxCheckerTaskRecordNum = getMaxTaskRecordNum(showDdlEngineStatusResult, maxCheckerTaskRecordNum, + SperateCheckGsiTask.class.getName()); + maxImportTableSpaceTaskRecordNum = + getMaxTaskRecordNum(showDdlEngineStatusResult, maxImportTableSpaceTaskRecordNum, + ImportTableSpaceDdlTask.class.getName()); + maxPkRangeBackfillTaskRecordNum = + getMaxTaskRecordNum(showDdlEngineStatusResult, maxPkRangeBackfillTaskRecordNum, + LogicalTableGsiPkRangeBackfillTask.class.getName()); + Thread.sleep(50L); + } + logger.info(String.format("ddl %d finished...", jobId)); + if (!DdlStateCheckUtil.waitTillDdlDone(connection, jobId, originalTableName)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("wait addGsiDdl done timeout for %s", msg)); + } + if (maxTaskRecordNum < 1) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("expected record occur in show ddl engine status", msg)); + } + if (physicalBackfill) { + if (maxImportTableSpaceTaskRecordNum < 0) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("expected import table space record occur in show ddl engine status", msg)); + } + if (maxPhysicalBackfillTaskRecordNum < 0) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("expected physical backfill record occur in show ddl engine status, but now only %d", maxPhysicalBackfillTaskRecordNum)); + } + } else { + if (maxPkRangeBackfillTaskRecordNum < 2) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("expected pk range record occur in show ddl engine status, but now only %d", maxPkRangeBackfillTaskRecordNum)); + } + if (maxCheckerTaskRecordNum < 0) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("expected checker record occur in show ddl engine status", msg)); + } + } + } + logger.info(String.format("check %d archived...", jobId)); + if (!DdlStateCheckUtil.checkIfBackfillSampleRowsArchived(connection, jobId, physicalBackfill || withSubjob)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format( + "this job success, but we don't expect the sample rows archived failed! for %d", jobId)); + } + } + + public static int getMaxTaskRecordNum(List> record, int n, String taskName) { + // task_name was 4th column +// result.addColumn("JOB_ID", DataTypes.LongType); +// result.addColumn("TASK_ID", DataTypes.LongType); +// result.addColumn("TASK_STATE", DataTypes.StringType); +// result.addColumn("TASK_NAME", DataTypes.StringType); +// result.addColumn("TASK_INFO", DataTypes.StringType); +// result.addColumn("EXECUTION_TIME", DataTypes.StringType); +// result.addColumn("NODE_IP", DataTypes.StringType); +// result.addColumn("RESOURCES", DataTypes.StringType); +// result.addColumn("EXTRA", DataTypes.StringType); +// result.addColumn("DDL_STMT", DataTypes.StringType); + long result = record.stream() + .filter(o -> taskName.endsWith(o.get(3).toString()) && o.get(2).toString().equalsIgnoreCase("ACTIVE")) + .count(); + return Math.max((int) result, n); + } + + public static void controlTest(final Log logger, PkRangeTestParam pkRangeTestParam, Connection connection) + throws Exception { + String schemaName = pkRangeTestParam.schemaName; + String originalTableName = pkRangeTestParam.originalTableName; + String gsiName = pkRangeTestParam.gsiTableName; + String createTableStmt = pkRangeTestParam.createTableStmt; + int partNum = pkRangeTestParam.partNum; + int gsiPartNum = pkRangeTestParam.gsiPartNum; + int eachPartRows = pkRangeTestParam.eachPartRows; + Boolean enablePkRange = pkRangeTestParam.enablePkRange; + Boolean buildLocalIndexLater = pkRangeTestParam.enableLocalIndexLater; + String addGsiStmt = pkRangeTestParam.addGsiStmt; + String taskRangeSize = pkRangeTestParam.taskRangeSize; + String pkRangeSize = pkRangeTestParam.pkRangeSize; + long expectedPkRangeNum = pkRangeTestParam.expectedPkRangeNum; + int expectedLocalIndexConcurrency = pkRangeTestParam.expectedLocalIndexConcurrency; + Boolean expectedBuildLocalIndexLater = pkRangeTestParam.expectedLocalIndexLater; + Boolean expectedPkRange = pkRangeTestParam.expectedPkRange; + long sleepInterval = pkRangeTestParam.sleepInterval; + long checkInterval = pkRangeTestParam.checkInterval; + String addGsiDdl = String.format(addGsiStmt, originalTableName, gsiName, gsiPartNum); + String addGsiHint = + String.format( + "/*+TDDL:CMD_EXTRA(PURE_ASYNC_DDL_MODE=true,GSI_BACKFILL_BY_PK_RANGE=%s,GSI_BUILD_LOCAL_INDEX_LATER=%s,BACKFILL_MAX_TASK_PK_RANGE_SIZE=%s,BACKFILL_MAX_PK_RANGE_SIZE=%s," + + "GSI_JOB_MAX_PARALLELISM=16,GSI_PK_RANGE_CPU_ACQUIRE=6)*/", + enablePkRange, buildLocalIndexLater, taskRangeSize, pkRangeSize); + if (!StringUtils.isEmpty(createTableStmt)) { + prepareData(connection, schemaName, originalTableName, eachPartRows, createTableStmt, + partNum, DataManipulateUtil.TABLE_TYPE.PARTITION_TABLE); + String analyzeTableSql = String.format("analyze table %s", originalTableName); + DdlStateCheckUtil.alterTableViaJdbc(connection, schemaName, originalTableName, analyzeTableSql); + } + DdlStateCheckUtil.alterTableViaJdbc(connection, schemaName, originalTableName, addGsiHint + addGsiDdl); + Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(connection, addGsiDdl); + String msg = + String.format("jobId: %d, table: %s, addGsiDdl: %s", jobId, originalTableName, addGsiHint + addGsiDdl); + + List errMsg = new ArrayList<>(); + for (int i = 0; i < 2; i++) { + Thread.sleep(sleepInterval); + DdlStateCheckUtil.pauseDdl(connection, jobId); + logger.info(String.format("pause ddl for %d time", i)); + Thread.sleep(sleepInterval); + try { + DdlStateCheckUtil.continueDdlAsync(connection, jobId); + } catch (Exception e) { + throw e; + } + logger.info(String.format("continue ddl for %d time", i)); + Thread.sleep(checkInterval); + if (!DdlStateCheckUtil.checkIfContinueValid(connection, jobId, errMsg)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("continue failed for %s, %s", msg, errMsg)); + } + } + logger.info(String.format("wait for ddl %d finish...", jobId)); + if (!DdlStateCheckUtil.waitTillDdlDone(logger, connection, jobId, originalTableName, expectedLocalIndexConcurrency, + false)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("wait addGsiDdl done timeout for %s", msg)); + } +// if (!DdlStateCheckUtil.checkBackfillObjectsValid(connection, jobId, errMsg)){ +// throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, +// String.format("check backfill objects failed %s", msg, errMsg.get(0))); +// } + logger.info(String.format("ddl %d finished...", jobId)); + if (!DdlStateCheckUtil.checkIfCompleteSuccessful(connection, jobId)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("this job failed for some unknown reason!!! %s", msg)); + } + if (!DdlStateCheckUtil.checkIfExecuteByPkRangeAndBuildLocalIndexLater(connection, jobId, expectedPkRange, + expectedBuildLocalIndexLater, expectedPkRangeNum, errMsg)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format( + "this job success, but we don't expect that pkRange and localIndexLater behave in this way !!! %s, %s", + msg, errMsg.get(0))); + } + if (!StringUtils.isEmpty(createTableStmt) && !DdlStateCheckUtil.compareForLocalIndex(connection, schemaName, + jobId, originalTableName, createTableStmt, + addGsiStmt, gsiName, partNum, errMsg)) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format("this job success but local key is not right!! %s, %s", msg, errMsg.get(0))); + } + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/base/PrivateDataGenerator.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/base/PrivateDataGenerator.java new file mode 100644 index 000000000..0d1bc8a4f --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/base/PrivateDataGenerator.java @@ -0,0 +1,184 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.base; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.qatest.util.JdbcUtil; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.stream.Collectors; + +public class PrivateDataGenerator { + +// public static void main(String[] args) { +// List columnNames = Arrays.asList("id", "partition", "name", "value"); +// List columnTypes = Arrays.asList("int", "varchar(32)", "varchar(32)", "float"); +// List pkColumnIndex = Arrays.asList(0); +// List partitionColumnIndex = Arrays.asList(1); +// int rows = 10; +// +// List> data = generateDuplicatePkData(columnNames, columnTypes, pkColumnIndex, partitionColumnIndex, rows); +// +// for (Map row : data) { +// System.out.println(row); +// } +// } + + public static List> generateDuplicatePkData(Connection connection, String schemaName, + String tableName, List columnNames, + List columnTypes, + Integer pkColumnIndex, + Integer partitionColumnIndex, int partNum, + int eachPartRows, int depth) { + if (depth > 3) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, " generate duplicate pk data failed!"); + } + Random random = new Random(); + + // 用于检查partition列对应数据的唯一性,确保PK列不同 + Map> partitionToPkMap = new HashMap<>(); + Map> partitionPkToRowMap = new HashMap<>(); + List> result = new ArrayList<>(); + String partitionKeyName = columnNames.get(partitionColumnIndex); + String pkColumnName = columnNames.get(pkColumnIndex); + Set partRoutes = new HashSet<>(); + Long generateKeyCount = 0L; + + for (int i = 0; i < partNum; i++) { + + // 构建partition key + String partitionValue; + String part; + do { + partitionValue = + generateRandomValue(columnTypes.get(partitionColumnIndex), random); + part = computePartRoute(connection, schemaName, tableName, partitionValue); + generateKeyCount += 1; + } while (partitionToPkMap.containsKey(partitionValue) || partRoutes.contains(part)); + partRoutes.add(part); + + for (int j = 0; j < eachPartRows; j++) { + Map row = new LinkedHashMap<>(); + // 确保partition列对应的PK列唯一 + Set usedPks = partitionToPkMap.computeIfAbsent(partitionValue, k -> new HashSet<>()); + String pk = ""; + for (int columnIndex = 0; columnIndex < columnNames.size(); columnIndex++) { + if (partitionColumnIndex == columnIndex) { + row.put(partitionKeyName, partitionValue); + continue; // partition列已经处理过 + } + + String value; + if (pkColumnIndex == columnIndex) { + // 对于PK列,需要确保唯一 + do { + value = generateRandomValue(columnTypes.get(columnIndex), random); + } while (usedPks.contains(value)); + pk = value; + usedPks.add(value); + } else { + value = generateRandomValue(columnTypes.get(columnIndex), random); + } + + row.put(columnNames.get(columnIndex), value); + } + partitionPkToRowMap.put(partitionValue + "_" + pk, row); + result.add(row); + } + } + + List partitionKeys = partitionToPkMap.keySet().stream().collect(Collectors.toList()); + Random random1 = new Random(); + Boolean successFlag = false; + for (int i = 0; i < 10; i++) { + int partitionKeyIndex = random1.nextInt(partitionKeys.size()); + String selectPartitionKey = partitionKeys.get(partitionKeyIndex); + Set pks = partitionToPkMap.get(selectPartitionKey); + String pk = randomSelectFromSet(pks); + Map selectRow = partitionPkToRowMap.get(selectPartitionKey + "_" + pk); + Map duplicateRow = new HashMap<>(selectRow); + for (int j = 0; j < 10; j++) { + int anotherPartitionKeyIndex = random1.nextInt(partitionKeys.size()); + if (anotherPartitionKeyIndex == partitionKeyIndex) { + continue; + } + String anotherPartitionKey = partitionKeys.get(anotherPartitionKeyIndex); + if (partitionToPkMap.get(anotherPartitionKey).contains(duplicateRow.get(pkColumnName))) { + continue; + } + duplicateRow.put(partitionKeyName, partitionKeys.get(anotherPartitionKeyIndex)); + result.add(duplicateRow); + successFlag = true; + break; + } + if (successFlag) { + break; + } + } + if (!successFlag) { + return generateDuplicatePkData(connection, schemaName, tableName, columnNames, columnTypes, pkColumnIndex, + partitionColumnIndex, partNum, + eachPartRows, depth + 1); + + } + + return result; + } + + private static String generateRandomValue(String type, Random random) { + switch (type.toLowerCase()) { + case "int": + return String.valueOf(random.nextInt(100000)); + case "bigint": + return String.valueOf(random.nextLong()); + case "float": + return String.valueOf(random.nextFloat()); + default: + if (type.startsWith("varchar")) { + int length = Integer.parseInt(type.replaceAll("[^0-9]", "")); + return randomString(length, random); + } + throw new IllegalArgumentException("Unsupported type: " + type); + } + } + + private static String randomString(int length, Random random) { + String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + StringBuilder result = new StringBuilder(length); + + for (int i = 0; i < length; i++) { + result.append(characters.charAt(random.nextInt(characters.length()))); + } + + return result.toString(); + } + + private static String randomSelectFromSet(Set set) { + int randomIndex = new Random().nextInt(set.size()); + Iterator iterator = set.iterator(); + int currentIndex = 0; + String result = ""; + while (iterator.hasNext()) { + result = iterator.next(); + currentIndex++; + if (currentIndex == randomIndex) { + break; + } + currentIndex++; + } + return result; + } + + static String computePartRoute(Connection connection, String schemaName, String tableName, String partitionValue) { + String sql = String.format("select part_route(\"%s\", \"%s\", \"%s\")", schemaName, tableName, partitionValue); + return JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(connection, sql)).get(0).get(0).toString(); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/OtherExceptionOnLargeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/OtherExceptionOnLargeTableTest.java new file mode 100644 index 000000000..76099d68c --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/OtherExceptionOnLargeTableTest.java @@ -0,0 +1,49 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.control; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange.PkTest; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class OtherExceptionOnLargeTableTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public OtherExceptionOnLargeTableTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testShowDdlStatus() throws SQLException { + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/PauseForExceptionOnLargeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/PauseForExceptionOnLargeTableTest.java new file mode 100644 index 000000000..e54704127 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/PauseForExceptionOnLargeTableTest.java @@ -0,0 +1,49 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.control; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange.PkTest; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class PauseForExceptionOnLargeTableTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public PauseForExceptionOnLargeTableTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testShowDdlStatus() throws SQLException { + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/SwitchLeaderOnLargeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/SwitchLeaderOnLargeTableTest.java new file mode 100644 index 000000000..3ce330527 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/SwitchLeaderOnLargeTableTest.java @@ -0,0 +1,49 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.control; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange.PkTest; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class SwitchLeaderOnLargeTableTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public SwitchLeaderOnLargeTableTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testShowDdlStatus() throws SQLException { + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/SyncExceptionOnLargeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/SyncExceptionOnLargeTableTest.java new file mode 100644 index 000000000..7dabb21dc --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/control/SyncExceptionOnLargeTableTest.java @@ -0,0 +1,49 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.control; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange.PkTest; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class SyncExceptionOnLargeTableTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public SyncExceptionOnLargeTableTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testShowDdlStatus() throws SQLException { + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mirrorcopy/PauseAndContinueOnLargeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mirrorcopy/PauseAndContinueOnLargeTableTest.java new file mode 100644 index 000000000..12596c278 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mirrorcopy/PauseAndContinueOnLargeTableTest.java @@ -0,0 +1,49 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.mirrorcopy; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange.PkTest; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class PauseAndContinueOnLargeTableTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public PauseAndContinueOnLargeTableTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testShowDdlStatus() throws SQLException { + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mirrorcopy/SyncFailTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mirrorcopy/SyncFailTest.java new file mode 100644 index 000000000..b18e0866c --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mirrorcopy/SyncFailTest.java @@ -0,0 +1,49 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.mirrorcopy; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange.PkTest; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class SyncFailTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public SyncFailTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testShowDdlStatus() throws SQLException { + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mirrorcopy/TaskPipelineQueueTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mirrorcopy/TaskPipelineQueueTest.java new file mode 100644 index 000000000..815b8d680 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mirrorcopy/TaskPipelineQueueTest.java @@ -0,0 +1,49 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.mirrorcopy; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange.PkTest; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class TaskPipelineQueueTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public TaskPipelineQueueTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testShowDdlStatus() throws SQLException { + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/monitor/PauseHandlyOnLargeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/monitor/PauseHandlyOnLargeTableTest.java new file mode 100644 index 000000000..c9331d7ee --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/monitor/PauseHandlyOnLargeTableTest.java @@ -0,0 +1,112 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.monitor; + +import com.alibaba.polardbx.optimizer.config.table.ScaleOutPlanUtil; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PkRangeTestParam; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange.PkTest; +import io.airlift.slice.DataSize; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class PauseHandlyOnLargeTableTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public PauseHandlyOnLargeTableTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testPauseAndContinueForLargeTable1() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "large_table_auto"; + String gsiName = randomTableName("gsi_large_", 8); + // prepare data + String createTableStmt = + "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 8; + int gsiPartNum = 8; + int eachPartRows = 200_000; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + String pkRangeSize = "32kB"; + String taskRangeSize = "8MB"; + String totalSize = "80MB"; + long expectedPkRangeNum = + DataSize.convertToByte(totalSize) / DataSize.convertToByte(taskRangeSize); + pkRangeTestParam.setExpectedPkRangeNum(expectedPkRangeNum / 2); + pkRangeTestParam.setTaskRangeSize(taskRangeSize); + pkRangeTestParam.setPkRangeSize(pkRangeSize); + pkRangeTestParam.setExpectedLocalIndexConcurrency(3); + pkRangeTestParam.setCheckInterval(2000L); + pkRangeTestParam.setSleepInterval(2000L); + PkRangeTestParam.controlTest(log, pkRangeTestParam, tddlConnection); + } + + @Test + public void testPauseAndContinueForLargeTable2() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "large_table_auto"; + String gsiName = randomTableName("gsi_large_", 8); + // prepare data + String createTableStmt = + "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 8; + int gsiPartNum = 8; + int eachPartRows = 400_000; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + String pkRangeSize = "128kB"; + String taskRangeSize = "16MB"; + String totalSize = "160MB"; + long expectedPkRangeNum = + DataSize.convertToByte(totalSize) / DataSize.convertToByte(taskRangeSize); + pkRangeTestParam.setExpectedPkRangeNum(expectedPkRangeNum / 2); + pkRangeTestParam.setTaskRangeSize(taskRangeSize); + pkRangeTestParam.setPkRangeSize(pkRangeSize); + pkRangeTestParam.setExpectedLocalIndexConcurrency(3); + pkRangeTestParam.setCheckInterval(2000L); + pkRangeTestParam.setSleepInterval(2000L); + PkRangeTestParam.controlTest(log, pkRangeTestParam, tddlConnection); + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/monitor/ShowDdlEngineStatusTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/monitor/ShowDdlEngineStatusTest.java new file mode 100644 index 000000000..a2f0c89d8 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/monitor/ShowDdlEngineStatusTest.java @@ -0,0 +1,97 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.monitor; + +import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PkRangeTestParam; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +import static com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PkRangeTestParam.showDdlTest; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class ShowDdlEngineStatusTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(ShowDdlEngineStatusTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public ShowDdlEngineStatusTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testShowDdlEngineForGsiBackfill() throws Exception { + String schemaName = "show_ddl_engine_test"; + String originalTableName = "multiple_pk_table1"; + String gsiName = randomTableName("gsi_multiple_pk1_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b char(16), c varchar(32), PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int eachPartRows = 102400; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + int gsiPartNum = 21; + String addGsiStmt = "alter table %s add global index %s(b) covering(c, a) partition by key(b, c) partitions %d"; + PkRangeTestParam + pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + showDdlTest(pkRangeTestParam, tddlConnection, true, true, false); + } + + @Test + public void testShowDdlEngineForMovePartition() throws Exception { + String schemaName = "show_ddl_engine_test"; + String originalTableName = "multiple_pk_table2"; + String gsiName = randomTableName("gsi_multiple_pk2_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b char(16), c varchar(32), PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 4; + int eachPartRows = 40960; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + int gsiPartNum = 21; +// String addGsiStmt = ""; + String addGsiStmt = "rebalance table %s shuffle_data_dist=1"; + PkRangeTestParam + pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + try { + showDdlTest(pkRangeTestParam, tddlConnection, true, true, true); + }catch (Exception e){ + logger.info(StringUtils.isEmpty(e.getMessage())?"bad exception catched":e.getMessage()); + throw e; + } + } +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/monitor/ShowDdlTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/monitor/ShowDdlTest.java new file mode 100644 index 000000000..bdfa1f049 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/monitor/ShowDdlTest.java @@ -0,0 +1,92 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.monitor; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PkRangeTestParam; +import com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +import static com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PkRangeTestParam.showDdlTest; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class ShowDdlTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(ShowDdlTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public ShowDdlTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testAddGsiForLargeTableGsi() throws Exception { + String schemaName = "show_ddl_test"; + String originalTableName = "multiple_pk_table1"; + String gsiName = randomTableName("gsi_multiple_pk1_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b char(16), c varchar(32), PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int eachPartRows = 4096; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c, a) partition by hash(b) partitions %d"; + PkRangeTestParam + pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, partNum, + eachPartRows, enablePkRange, enableLocalIndexLater); + showDdlTest(pkRangeTestParam, tddlConnection, false); + } + + @Test + public void testAddGsiForLargeTableGsiWithSubjob() throws Exception { + String schemaName = "show_ddl_test"; + String originalTableName = "multiple_pk_table2"; + String gsiName = randomTableName("gsi_multiple_pk2_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b char(16), c varchar(32), PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 64; + int eachPartRows = 10240; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + int gsiPartNum = 21; + String addGsiStmt = "alter table %s add global index %s(b) covering(c, a) partition by key(b, c) partitions %d"; + PkRangeTestParam + pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + showDdlTest(pkRangeTestParam, tddlConnection, true); + DdlStateCheckUtil.dropDbAndCheckArchived(schemaName, tddlConnection); + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mpp/MppMonitorOnLargeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mpp/MppMonitorOnLargeTableTest.java new file mode 100644 index 000000000..97e87e44c --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mpp/MppMonitorOnLargeTableTest.java @@ -0,0 +1,48 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.mpp; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange.PkTest; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class MppMonitorOnLargeTableTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public MppMonitorOnLargeTableTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testMonitorOnLargeTable() { + + } +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mpp/TaskAllocationOnLargeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mpp/TaskAllocationOnLargeTableTest.java new file mode 100644 index 000000000..7f9c18ad6 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/mpp/TaskAllocationOnLargeTableTest.java @@ -0,0 +1,77 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.mpp; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PkRangeTestParam; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange.PkTest; +import io.airlift.slice.DataSize; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class TaskAllocationOnLargeTableTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public TaskAllocationOnLargeTableTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testPauseAndContinueForLargeTable2() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "large_table_auto"; + String gsiName = randomTableName("gsi_large_", 8); + // prepare data + String createTableStmt = + "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 8; + int gsiPartNum = 8; + int eachPartRows = 400_000; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + String pkRangeSize = "128kB"; + String taskRangeSize = "1MB"; + String totalSize = "160MB"; + long expectedPkRangeNum = + DataSize.convertToByte(totalSize) / DataSize.convertToByte(taskRangeSize); + pkRangeTestParam.setExpectedPkRangeNum(expectedPkRangeNum / 2); + pkRangeTestParam.setTaskRangeSize(taskRangeSize); + pkRangeTestParam.setPkRangeSize(pkRangeSize); + pkRangeTestParam.setExpectedLocalIndexConcurrency(3); + pkRangeTestParam.setMppTaskAllocationCheck(true); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/BaseEmptyTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/BaseEmptyTableTest.java new file mode 100644 index 000000000..8c2aa1676 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/BaseEmptyTableTest.java @@ -0,0 +1,260 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PkRangeTestParam; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DataManipulateUtil.prepareData; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class BaseEmptyTableTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public BaseEmptyTableTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testLegacyAddGsiForEmptyTable() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "empty_table_for_simple"; + String gsiName = randomTableName("gsi_base_empty_", 8); + String createTableStmt = + "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = 16; + int eachPartRows = 0; + Boolean enablePkRange = false; + Boolean enableLocalIndexLater = false; + String addGsiStmt = "alter table %s add global index %s(b) covering(c) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testLegacyAddUGsiForEmptyTable() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "empty_table_for_simple_ugsi"; + String gsiName = randomTableName("gsi_base_unique_empty_", 8); + String createTableStmt = + "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = 16; + int eachPartRows = 0; + Boolean enablePkRange = false; + Boolean enableLocalIndexLater = false; + String addGsiStmt = + "alter table %s add global unique index %s(b) covering(c) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testLegacyAddUGsiForceDenyForEmptyTable() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "empty_table_for_simple_ugsi_force_deny"; + String gsiName = randomTableName("gsi_base_unique2_empty_", 8); + String createTableStmt = + "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = 16; + int eachPartRows = 0; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = + "alter table %s add global unique index %s(b) covering(c) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + pkRangeTestParam.setExpectedPkRangeNum(0); + pkRangeTestParam.setExpectedPkRange(false); + pkRangeTestParam.setExpectedLocalIndexLater(false); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testLegacyCreateEmptyTableWithGsi() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "empty_table_with_gsi"; + String gsiName = randomTableName("gsi_empty1_", 8); + String createTableWithGsiStmt = + "create table %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ", global index %s(b) partition by hash(b) partitions 16 " + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = 16; + int eachPartRows = 0; + Boolean enablePkRange = false; + Boolean enableLocalIndexLater = false; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, "", createTableWithGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testLegacyCreateEmptyTableWithGsiForceDeny() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "empty_table_with_gsi_force_deny"; + String gsiName = randomTableName("gsi_empty2_", 8); + String createTableWithGsiStmt = + "create table %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ", global index %s(b) partition by hash(b) partitions 16 " + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = 16; + int eachPartRows = 0; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, "", createTableWithGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + pkRangeTestParam.setExpectedPkRangeNum(0); + pkRangeTestParam.setExpectedPkRange(false); + pkRangeTestParam.setExpectedLocalIndexLater(false); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testAddGsiForEmptyTable() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "empty_table_empty_auto"; + String gsiName = randomTableName("gsi_empty_", 8); + // prepare data + String createTableStmt = + "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = 16; + int eachPartRows = 0; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testAddGsiForEmptyTableOnLocalIndex1() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "empty_table_local_index1"; + String gsiName = randomTableName("gsi_empty_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), d TIMESTAMP, PRIMARY KEY(a)," + + " local index i_c(c), local index i_bc(b, c), local index i_d(d)) PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = 16; + int eachPartRows = 0; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testAddGsiForEmptyTableOnLocalIndex2() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "empty_table_local_index2"; + String gsiName = randomTableName("gsi_empty_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), d TIMESTAMP, PRIMARY KEY(a)," + + " local index i_c(c), local unique index i_bc(b, c), local index i_d(d)) PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = 16; + int eachPartRows = 0; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b, c, d) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testAddClusteredGsiForEmptyTableOnLocalIndex1() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "empty_table_csi_local_index1"; + String gsiName = randomTableName("csi_empty_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), d TIMESTAMP, PRIMARY KEY(a)," + + " local index i_c(c), local index i_bc(b, c), local index i_d(d)) PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = 16; + int eachPartRows = 0; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add clustered index %s(b) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testAddClusteredGsiForEmptyTableOnLocalIndex2() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "empty_table_csi_local_index2"; + String gsiName = randomTableName("csi_empty_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), d TIMESTAMP, PRIMARY KEY(a)," + + " local index i_c(c), local unique index i_bc(b, c), local index i_d(d)) PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = 16; + int eachPartRows = 0; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add clustered index %s(b) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/LargeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/LargeTableTest.java new file mode 100644 index 000000000..ce74150b9 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/LargeTableTest.java @@ -0,0 +1,107 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange; + +import com.alibaba.polardbx.optimizer.config.table.ScaleOutPlanUtil; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PkRangeTestParam; +import io.airlift.slice.DataSize; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class LargeTableTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public LargeTableTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testAddGsiForLargeTable() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "large_table_auto"; + String gsiName = randomTableName("gsi_large_", 8); + // prepare data + String createTableStmt = + "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 8; + int gsiPartNum = 8; + int eachPartRows = 400_000; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + String pkRangeSize = "32kB"; + String taskRangeSize = "1MB"; + String totalSize = "160MB"; + long expectedPkRangeNum = + DataSize.convertToByte(totalSize) / DataSize.convertToByte(taskRangeSize); + pkRangeTestParam.setExpectedPkRangeNum(expectedPkRangeNum / 2); + pkRangeTestParam.setTaskRangeSize(taskRangeSize); + pkRangeTestParam.setPkRangeSize(pkRangeSize); + pkRangeTestParam.setExpectedLocalIndexConcurrency(3); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testAddGsiForLargeTableClusteredIndex() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "large_table_auto"; + String gsiName = randomTableName("gsi_large_", 8); + // prepare data + String createTableStmt = + "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 8; + int gsiPartNum = 8; + int eachPartRows = 400_000; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add clustered index %s(b) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + String pkRangeSize = "32kB"; + String taskRangeSize = "1MB"; + String totalSize = "160MB"; + long expectedPkRangeNum = + DataSize.convertToByte(totalSize) / DataSize.convertToByte(taskRangeSize); + pkRangeTestParam.setExpectedPkRangeNum(expectedPkRangeNum / 2); + pkRangeTestParam.setTaskRangeSize(taskRangeSize); + pkRangeTestParam.setPkRangeSize(pkRangeSize); + pkRangeTestParam.setExpectedLocalIndexConcurrency(3); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/OtherPkRangeTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/OtherPkRangeTest.java new file mode 100644 index 000000000..0d7ed9ad4 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/OtherPkRangeTest.java @@ -0,0 +1,17 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +public class OtherPkRangeTest { +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/PkTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/PkTest.java new file mode 100644 index 000000000..4625849c8 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/PkTest.java @@ -0,0 +1,255 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange; + +import com.alibaba.polardbx.qatest.BinlogIgnore; +import com.alibaba.polardbx.qatest.CdcIgnore; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PkRangeTestParam; +import com.alibaba.polardbx.qatest.ddl.balancer.datagenerator.DataLoader; +import com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DataManipulateUtil; +import com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.google.common.collect.Lists; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PkRangeTestParam.baseTest; +import static com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PrivateDataGenerator.generateDuplicatePkData; +import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DataManipulateUtil.prepareData; + +@NotThreadSafe +public class PkTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public PkTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testAddGsiForMultiplePkTable1() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "multiple_pk_table1"; + String gsiName = randomTableName("gsi_multiple_pk1_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b char(16), c varchar(32), PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int eachPartRows = 1024; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c, a) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, partNum, + eachPartRows, enablePkRange, enableLocalIndexLater); + baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testAddGsiForMultiplePkTable2() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "multiple_pk_table2"; + String gsiName = randomTableName("gsi_multiple_pk2_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b DATETIME not null default current_timestamp, c varchar(32), PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int eachPartRows = 1024; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c, a) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, partNum, + eachPartRows, enablePkRange, enableLocalIndexLater); + baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + @CdcIgnore(ignoreReason = "ignore handly insert duplicate key") + public void testAddGsiOnDuplicateKey() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "multiple_pk_table13"; + String gsiName = randomTableName("gsi_multiple_pk13_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(a int, b varchar(16), c varchar(32), d int, e int, PRIMARY KEY(a)" + + ") PARTITION BY HASH(b) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = partNum; + int eachPartRows = 1024; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(c) covering(b, a) partition by hash(c) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, partNum, + eachPartRows, enablePkRange, enableLocalIndexLater); + Boolean buildLocalIndexLater = pkRangeTestParam.enableLocalIndexLater; + String taskRangeSize = pkRangeTestParam.taskRangeSize; + String pkRangeSize = pkRangeTestParam.pkRangeSize; + long expectedPkRangeNum = pkRangeTestParam.expectedPkRangeNum; + int expectedLocalIndexConcurrency = pkRangeTestParam.expectedLocalIndexConcurrency; + Boolean expectedBuildLocalIndexLater = pkRangeTestParam.expectedLocalIndexLater; + Boolean expectedPkRange = pkRangeTestParam.expectedPkRange; + String addGsiDdl = String.format(addGsiStmt, originalTableName, gsiName, gsiPartNum); + Connection connection = tddlConnection; + String addGsiHint = + String.format( + "/*+TDDL:CMD_EXTRA(GSI_BACKFILL_BY_PK_RANGE=%s,GSI_BUILD_LOCAL_INDEX_LATER=%s,BACKFILL_MAX_TASK_PK_RANGE_SIZE=%s,BACKFILL_MAX_PK_RANGE_SIZE=%s," + + "GSI_JOB_MAX_PARALLELISM=16,GSI_PK_RANGE_CPU_ACQUIRE=6)*/", + enablePkRange, buildLocalIndexLater, taskRangeSize, pkRangeSize); + prepareData(connection, schemaName, originalTableName, eachPartRows, createTableStmt, + partNum, DataManipulateUtil.TABLE_TYPE.SELF_DEF_TABLE); + + List columnNames = Lists.newArrayList("a", "b", "c", "d", "e"); + List columnTypes = + Arrays.stream("int,varchar(16),varchar(32),int,int".split(",")).collect(Collectors.toList()); + int pkColumnIndex = 0; + int partitionColumnIndex = 1; + List> rows = + generateDuplicatePkData(tddlConnection, schemaName, originalTableName, columnNames, columnTypes, + pkColumnIndex, partitionColumnIndex, partNum, + eachPartRows, 0); + + String truncateTableSql = String.format("truncate table %s", originalTableName); + DdlStateCheckUtil.alterTableViaJdbc(connection, schemaName, originalTableName, truncateTableSql); + DataLoader dataLoader = + DataLoader.create(tddlConnection, originalTableName, rows); + dataLoader.batchInsertFromRow(rows.size(), true); + + String analyzeTableSql = String.format("analyze table %s", originalTableName); + DdlStateCheckUtil.alterTableViaJdbc(connection, schemaName, originalTableName, analyzeTableSql); + JdbcUtil.executeFailed(connection, addGsiHint + addGsiDdl, "Duplicated entry "); + } + + @Test + public void testAddGsiForMultiplePkTable4() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "multiple_pk_table4"; + String gsiName = randomTableName("gsi_multiple_pk4_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b TIMESTAMP not null, c varchar(32), PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 8; + int eachPartRows = 1024; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c, a) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, partNum, + eachPartRows, enablePkRange, enableLocalIndexLater); + baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testAddGsiForMultiplePkTable5() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "multiple_pk_table5"; + String gsiName = randomTableName("gsi_multiple_pk5_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b DATETIME not null default current_timestamp, c decimal(10, 3), PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 8; + int eachPartRows = 1024; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c, a) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, partNum, + eachPartRows, enablePkRange, enableLocalIndexLater); + baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testAddGsiForMultiplePkTable6() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "multiple_pk_table6"; + String gsiName = randomTableName("gsi_multiple_pk6_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b DATE not null, c time, PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 8; + int eachPartRows = 1024; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c, a) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, partNum, + eachPartRows, enablePkRange, enableLocalIndexLater); + baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testAddGsiForMultiplePkTable7() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "multiple_pk_table7"; + String gsiName = randomTableName("gsi_multiple_pk7_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b datetime, c year, PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 8; + int eachPartRows = 1024; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c, a) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, partNum, + eachPartRows, enablePkRange, enableLocalIndexLater); + baseTest(pkRangeTestParam, tddlConnection); + } + + @Test + public void testAddGsiForMultiplePkTable8() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "multiple_pk_table8"; + String gsiName = randomTableName("gsi_multiple_pk8_", 8); + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b binary(20), c timestamp, PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 8; + int eachPartRows = 1024; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(a) covering(c, b) partition by hash(a) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, partNum, + eachPartRows, enablePkRange, enableLocalIndexLater); + baseTest(pkRangeTestParam, tddlConnection); + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/SampleOnLargeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/SampleOnLargeTableTest.java new file mode 100644 index 000000000..6cc6dc363 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/SampleOnLargeTableTest.java @@ -0,0 +1,4 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange; + +public class SampleOnLargeTableTest { +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/SmallTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/SmallTableTest.java new file mode 100644 index 000000000..27526b211 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/pkrange/SmallTableTest.java @@ -0,0 +1,66 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.pkrange; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ddl.auto.mpp.base.PkRangeTestParam; +import net.jcip.annotations.NotThreadSafe; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +@NotThreadSafe +@RunWith(Parameterized.class) +public class SmallTableTest extends DDLBaseNewDBTestCase { + + final static Log log = LogFactory.getLog(PkTest.class); + private String tableName = ""; + private static final String createOption = " if not exists "; + + public SmallTableTest(boolean crossSchema) { + this.crossSchema = crossSchema; + } + + @Parameterized.Parameters(name = "{index}:crossSchema={0}") + public static List initParameters() { + return Arrays.asList(new Object[][] { + {false}}); + } + + @Before + public void init() { + this.tableName = schemaPrefix + randomTableName("empty_table", 4); + } + + @Override + public boolean usingNewPartDb() { + return true; + } + + @Test + public void testAddGsiForSmallTable() throws Exception { + String schemaName = "pk_range_test"; + String originalTableName = "small_table_auto"; + String gsiName = randomTableName("gsi_small_", 8); + // prepare data + String createTableStmt = + "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 16; + int gsiPartNum = 16; + int eachPartRows = 1024; + Boolean enablePkRange = true; + Boolean enableLocalIndexLater = true; + String addGsiStmt = "alter table %s add global index %s(b) covering(c) partition by hash(b) partitions %d"; + PkRangeTestParam pkRangeTestParam = + new PkRangeTestParam(schemaName, originalTableName, gsiName, createTableStmt, addGsiStmt, partNum, + gsiPartNum, eachPartRows, enablePkRange, enableLocalIndexLater); + PkRangeTestParam.baseTest(pkRangeTestParam, tddlConnection); + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/util/DrdsUnparameterizeSqlVisitorTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/util/DrdsUnparameterizeSqlVisitorTest.java new file mode 100644 index 000000000..e0eab34ea --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/util/DrdsUnparameterizeSqlVisitorTest.java @@ -0,0 +1,61 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.util; + +import com.alibaba.polardbx.common.jdbc.ParameterContext; +import com.alibaba.polardbx.common.jdbc.ParameterMethod; +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.druid.sql.ast.SQLStatement; +import com.alibaba.polardbx.druid.sql.parser.SQLStatementParser; +import com.alibaba.polardbx.druid.util.JdbcConstants; +import com.alibaba.polardbx.optimizer.parse.visitor.DrdsUnparameterizeSqlVisitor; +import junit.framework.TestCase; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static com.alibaba.polardbx.druid.sql.parser.SQLParserUtils.createSQLStatementParser; + +public class DrdsUnparameterizeSqlVisitorTest extends TestCase { + public void unparameterizeSqlCheck(String sql, List params) { + String out = DrdsUnparameterizeSqlVisitor.unparameterizeSql(sql, params); + SQLStatementParser statementParser = createSQLStatementParser(out, JdbcConstants.MYSQL); + SQLStatement sqlStatment = statementParser.parseStatement(); + String reParseOut = sqlStatment.toString(); + Assert.assertTrue(out.equals(reParseOut)); + } + + @Test + public void testUnparameterizeSqlInt() { + List params = new ArrayList<>(); + params.add(new ParameterContext(ParameterMethod.setLong, new Object[] {1, 1})); + String sql = "select id from t1 where a < ?"; + unparameterizeSqlCheck(sql, params); + } + + public void testUnparameterizeSql2() { + List params = new ArrayList<>(); + params.add(new ParameterContext(ParameterMethod.setLong, new Object[] {1, 1})); + params.add(new ParameterContext(ParameterMethod.setLong, new Object[] {2, 100})); + params.add(new ParameterContext(ParameterMethod.setFloat, new Object[] {3, 0.02})); + params.add(new ParameterContext(ParameterMethod.setLong, new Object[] {4, 24})); + String sql = "select id from t1 where a < ? and a > ? and rand() < ? order by a limit ?"; + unparameterizeSqlCheck(sql, params); + } + + public void testUnparameterizeSql3() { + List params = new ArrayList<>(); + params.add(new ParameterContext(ParameterMethod.setString, new Object[] {1, "t1"})); + String sql = "select id from ? where a < 3"; + unparameterizeSqlCheck(sql, params); + } + + public void testUnparameterizeSql4() { + List params = new ArrayList<>(); + params.add(new ParameterContext(ParameterMethod.setString, new Object[] {1, "1"})); + params.add(new ParameterContext(ParameterMethod.setString, new Object[] {2, "100"})); + params.add(new ParameterContext(ParameterMethod.setFloat, new Object[] {3, 0.02})); + params.add(new ParameterContext(ParameterMethod.setLong, new Object[] {4, 24})); + String sql = "select id from t1 where a < ? and a > ? and rand() < ? order by a limit ?"; + unparameterizeSqlCheck(sql, params); + } +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/util/ScaleOutPlanUtilTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/util/ScaleOutPlanUtilTest.java new file mode 100644 index 000000000..ec0ddf06f --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/mpp/util/ScaleOutPlanUtilTest.java @@ -0,0 +1,78 @@ +package com.alibaba.polardbx.qatest.ddl.auto.mpp.util; + +import com.alibaba.polardbx.optimizer.config.table.ScaleOutPlanUtil; +import io.airlift.slice.DataSize; +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +public class ScaleOutPlanUtilTest extends TestCase { + + @Test + public void testParseDataUnit() { + String dataUnit = "16MB"; + long dataSize = DataSize.convertToByte(dataUnit); + Assert.assertTrue(dataSize == 1024L * 16L * 1024L); + + dataUnit = "16kB"; + dataSize = DataSize.convertToByte(dataUnit); + Assert.assertTrue(dataSize == 1024L * 16L); + + dataUnit = "32kB"; + dataSize = DataSize.convertToByte(dataUnit); + Assert.assertTrue(dataSize == 1024L * 32L); + + dataUnit = "1024B"; + dataSize = DataSize.convertToByte(dataUnit); + Assert.assertTrue(dataSize == 1024L); + + dataUnit = "8GB"; + dataSize = DataSize.convertToByte(dataUnit); + Assert.assertTrue(dataSize == 1024L * 8L * 1024L * 1024L); + } + + @Test + public void testParseDataUnitError() { + String dataUnit = "8Gb"; + long dataSize; + String msg = ""; + try { + dataSize = DataSize.convertToByte(dataUnit); + } catch (Exception e) { + msg = e.getMessage(); + } + Assert.assertTrue(msg.contains("Unknown unit")); + + dataUnit = "8"; + try { + dataSize = DataSize.convertToByte(dataUnit); + } catch (Exception e) { + msg = e.getMessage(); + } + Assert.assertTrue(msg.contains("size is not a valid data size string")); + + dataUnit = "1024g"; + try { + dataSize = DataSize.convertToByte(dataUnit); + } catch (Exception e) { + msg = e.getMessage(); + } + Assert.assertTrue(msg.contains("Unknown unit")); + + dataUnit = "xg"; + try { + dataSize = DataSize.convertToByte(dataUnit); + } catch (Exception e) { + msg = e.getMessage(); + } + Assert.assertTrue(msg.contains("size is not a valid data size string")); + + dataUnit = "24xg"; + try { + dataSize = DataSize.convertToByte(dataUnit); + } catch (Exception e) { + msg = e.getMessage(); + } + Assert.assertTrue(msg.contains("Unknown unit")); + } +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ColumnOrdinalTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ColumnOrdinalTest.java index be8b4755a..157fa2d2e 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ColumnOrdinalTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ColumnOrdinalTest.java @@ -243,8 +243,8 @@ private void checkCdcDdlMark(String sql, String tableName, SchemaRepository repo private DDLExtInfo getDdlExtInfo(String sql) throws SQLException { try (Statement stmt = tddlConnection.createStatement()) { try (ResultSet resultSet = stmt.executeQuery( - "select ext from __cdc__." + CDC_DDL_RECORD_TABLE + " where ddl_sql = '" + sql - + "' order by id desc limit 1")) { + "select ext from __cdc__." + CDC_DDL_RECORD_TABLE + " where ddl_sql like '%" + sql + + "%' order by id desc limit 1")) { while (resultSet.next()) { String extStr = resultSet.getString(1); if (StringUtils.isNotBlank(extStr)) { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentDMLBaseTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentDMLBaseTest.java index 964ab3c82..a67850525 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentDMLBaseTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentDMLBaseTest.java @@ -20,6 +20,7 @@ import java.util.function.BiFunction; import java.util.function.Function; +import static com.alibaba.polardbx.common.properties.ConnectionProperties.DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -30,8 +31,10 @@ public class ConcurrentDMLBaseTest extends DDLBaseNewDBTestCase { // Use logical execution since result may be different from pushdown execution protected static final String USE_LOGICAL_EXECUTION = "DML_EXECUTION_STRATEGY=LOGICAL"; protected static final String DISABLE_DML_RETURNING = "DML_USE_RETURNING=FALSE"; - protected static final int FILL_COUNT = 2500; - protected static final int FILL_BATCH_SIZE = 2500; + protected static final String ENABLE_LOCAL_UK_FULL_TABLE_SCAN = + DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN + "=TRUE"; + protected static final int FILL_COUNT = 1500; + protected static final int FILL_BATCH_SIZE = 1500; protected static String buildCmdExtra(String... params) { if (0 == params.length) { @@ -72,14 +75,24 @@ public void concurrentTestInternal(String tableName, String colDef, String alter boolean fillData, boolean withGsi, int batchSize, boolean isModifyPartitionKey) throws Exception { concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, fillData, - withGsi, batchSize, isModifyPartitionKey, true); + withGsi, batchSize, isModifyPartitionKey, true, null); + } + + public void concurrentTestInternalWithCreateSql(String tableName, String colDef, String alterSql, String selectSql, + Function generator1, + Function generator2, + QuadFunction checker, + boolean fillData, boolean withGsi, + int batchSize, String createSql) throws Exception { + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, fillData, + withGsi, batchSize, false, true, createSql); } public void concurrentTestInternal(String tableName, String colDef, String alterSql, String selectSql, Function generator1, Function generator2, QuadFunction checker, - boolean fillData, boolean withGsi, - int batchSize, boolean isModifyPartitionKey, boolean isStrictMode) + boolean fillData, boolean withGsi, int batchSize, boolean isModifyPartitionKey, + boolean isStrictMode, String createTableSql) throws Exception { tableName = tableName + RandomUtils.getStringBetween(1, 5); dropTableIfExists(tableName); @@ -135,6 +148,9 @@ public void concurrentTestInternal(String tableName, String colDef, String alter + ") partition by hash(`a`) partitions 3", tableName, colDef); } + if (createTableSql != null) { + createSql = String.format(createTableSql, finalTableName); + } // Retry in case of table group not exist int retryCnt = 0; @@ -188,6 +204,7 @@ public Void apply(AtomicBoolean shouldStop, AtomicInteger totalCount) { if (e.getMessage().contains("Lock wait timeout exceeded") || e.getMessage() .contains("Deadlock found")) { // ignore + Thread.sleep(500); totalCount.getAndDecrement(); } else if ((e.getMessage().contains("Unknown target column") || e.getMessage() .contains("not found")) && !changed) { @@ -220,7 +237,8 @@ public Void apply(AtomicBoolean shouldStop, AtomicInteger totalCount) { } Thread.sleep(1000); String algorithm = isModifyPartitionKey ? "" : USE_OMC_ALGORITHM; - String sql = String.format(alterSql, finalTableName) + algorithm; + String batchHint = "/*+TDDL:cmd_extra(GSI_BACKFILL_BATCH_SIZE=50,CHANGE_SET_APPLY_BATCH=32)*/"; + String sql = batchHint + String.format(alterSql, finalTableName) + algorithm; try { execDdlWithRetry(tddlDatabase1, finalTableName, sql, connection); } finally { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertIgnoreTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertIgnoreTest.java index b497e64f6..3cc9a694d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertIgnoreTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertIgnoreTest.java @@ -32,8 +32,8 @@ public void modifyWithInsertIgnore1() throws Exception { + " alter table %s modify column b bigint"; String selectSql = "select * from %s order by a"; Function generator = (count) -> String.format( - buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) - + "insert ignore into %%s values(%d, %d + %d, 'a', 'b')", count, count, FILL_COUNT); + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING, ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + + "insert ignore into %%s values(%d, %d + %d, 'a', 'b')", count, count, FILL_COUNT); QuadFunction checker = (colA, colB, colC, colD) -> (Objects.equals(colA, colB)) && (colC.equalsIgnoreCase(colD)); concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, true, @@ -50,8 +50,8 @@ public void modifyWithInsertIgnore2() throws Exception { + " alter table %s modify column b bigint, modify column c char(10) after d"; String selectSql = "select * from %s order by a desc"; Function generator = (count) -> String.format( - buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) - + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING, ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); QuadFunction checker = (colA, colB, colC, colD) -> (Objects.equals(colA, colB)) && (colC.equalsIgnoreCase(colD)); concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, true, @@ -68,8 +68,8 @@ public void modifyWithInsertIgnore4PartitionKey() throws Exception { + " alter table %s modify column b bigint"; String selectSql = "select * from %s order by a desc"; Function generator = (count) -> String.format( - buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) - + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) + + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); QuadFunction checker = (colA, colB, colC, colD) -> (Objects.equals(colA, colB)) && (colC.equalsIgnoreCase(colD)); concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, true, @@ -86,8 +86,7 @@ public void changeWithInsertIgnore1() throws Exception { + " alter table %s change column b e bigint"; String selectSql = "select * from %s order by a"; Function generator = (count) -> String.format( - buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) - + "insert ignore into %%s values(%d, %d + %d, 'a', 'b')", count, count, FILL_COUNT); + "insert ignore into %%s values(%d, %d + %d, 'a', 'b')", count, count, FILL_COUNT); QuadFunction checker = (colA, colB, colC, colD) -> (Objects.equals(colA, colB)) && (colC.equalsIgnoreCase(colD)); concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, true, @@ -104,8 +103,8 @@ public void changeWithInsertIgnore2() throws Exception { + " alter table %s change column b e bigint"; String selectSql = "select * from %s order by a desc"; Function generator = (count) -> String.format( - buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) - + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING, ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); QuadFunction checker = (colA, colB, colC, colD) -> (Objects.equals(colA, colB)) && (colC.equalsIgnoreCase(colD)); concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, true, @@ -122,8 +121,8 @@ public void changeMultiWithInsertIgnore1() throws Exception { + " alter table %s change column b e bigint, change column c d char(10), change column d c varchar(20)"; String selectSql = "select * from %s order by a desc"; Function generator = (count) -> String.format( - buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) - + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING, ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); QuadFunction checker = (colA, colB, colC, colD) -> (Objects.equals(colA, colB)) && (colC.equalsIgnoreCase(colD)); concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, true, @@ -140,8 +139,8 @@ public void changeMultiWithInsertIgnore2() throws Exception { + " alter table %s change column b e bigint, drop column d, add column f char(10) default 'xyz'"; String selectSql = "select * from %s order by a desc"; Function generator = (count) -> String.format( - buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) - + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING, ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); QuadFunction checker = (colA, colB, colC, colD) -> (Objects.equals(colA, colB)) && (colC.equalsIgnoreCase(colD) || colD.equalsIgnoreCase("xyz")); @@ -150,4 +149,52 @@ public void changeMultiWithInsertIgnore2() throws Exception { concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, false, 1); } + + @Test + public void singleChangeMultiWithInsertIgnore() throws Exception { + String tableName = "omc_single_multi_with_insert_ignore"; + String colDef = "int unique key"; + String createSql = String.format( + "create table %%s (" + + "a int primary key, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") single", colDef); + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint, drop column d, add column f char(10) default 'xyz'"; + String selectSql = "select * from %s order by a desc"; + Function generator = (count) -> String.format( + buildCmdExtra(ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); + QuadFunction checker = + (colA, colB, colC, colD) -> (Objects.equals(colA, colB)) + && (colC.equalsIgnoreCase(colD) || colD.equalsIgnoreCase("xyz")); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator, generator, checker, + true, false, 1, createSql); + } + + @Test + public void broadcastChangeMultiWithInsertIgnore() throws Exception { + String tableName = "omc_single_multi_with_insert_ignore"; + String colDef = "int unique key"; + String createSql = String.format( + "create table %%s (" + + "a int primary key, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") broadcast", colDef); + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint, drop column d, add column f char(10) default 'xyz'"; + String selectSql = "select * from %s order by a desc"; + Function generator = (count) -> String.format( + buildCmdExtra(ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + + "insert ignore into %%s values(%d + %d, %d, 'a', 'b')", count, FILL_COUNT, count); + QuadFunction checker = + (colA, colB, colC, colD) -> (Objects.equals(colA, colB)) + && (colC.equalsIgnoreCase(colD) || colD.equalsIgnoreCase("xyz")); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator, generator, checker, + true, false, 1, createSql); + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertSelectTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertSelectTest.java index c763183d8..158ab5f40 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertSelectTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertSelectTest.java @@ -356,4 +356,76 @@ public void changeMultiWithInsertSelect() throws Exception { result.get(); } } + + @Test + public void singleBroadcastChangeMultiWithInsertSelect() throws Exception { + final ExecutorService threadPool = Executors.newFixedThreadPool(2); + final List> tasks = new ArrayList<>(); + + String selectTableName = "omc_sb_multi_with_is_src_tb"; + buildSelectTable(selectTableName); + + tasks.add(() -> { + String tableName = "omc_multi_with_insert_select_1"; + String colDef = "int"; + String createSql = String.format( + "create table %%s (" + + "a int primary key, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") single", colDef); + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint, change column c f text, change d g char(10)"; + String selectSql = "select * from %s"; + Function generator1 = + (count) -> String.format("insert into %%s(a,b,c,d) select %d,%d+1,%d,%d+1", count, count, count, count); + Function generator2 = + (count) -> String.format("insert into %%s(a,e,f,g) select %d,%d+1,%d,%d+1", count, count, count, count); + QuadFunction checker = + (colA, colB, colC, colD) -> (colA == colB - 1) + && (Float.parseFloat(colC) == Float.parseFloat(colD) - 1); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, + false, false, 1, createSql); + System.out.println("modifyMultiWithInsertSelect single"); + return null; + }); + + tasks.add(() -> { + String tableName = "omc_multi_with_insert_select_2"; + String colDef = "int"; + String createSql = String.format( + "create table %%s (" + + "a int primary key, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") broadcast", colDef); + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint, change column c d char(10), change column d c char(10)"; + String selectSql = "select * from %s"; + Function generator1 = + (count) -> String.format("insert into %%s(b,a,c,d) select c,d+1,e,f+1 from %s where c=%d", + selectTableName, count); + Function generator2 = + (count) -> String.format("insert into %%s(e,a,d,c) select c,d+1,e,f+1 from %s where c=%d", + selectTableName, count); + QuadFunction checker = + (colA, colB, colC, colD) -> (colA == colB + 1) + && (Float.parseFloat(colC) + 1 == Float.parseFloat(colD)); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, + false, false, 1, createSql); + System.out.println("modifyMultiWithInsertSelect broadcast"); + return null; + }); + + ArrayList> results = new ArrayList<>(); + for (Callable task : tasks) { + results.add(threadPool.submit(task)); + } + + for (Future result : results) { + result.get(); + } + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertTest.java index 49c4f5341..6423e1086 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentInsertTest.java @@ -1,6 +1,7 @@ package com.alibaba.polardbx.qatest.ddl.auto.omc; import com.alibaba.polardbx.executor.common.StorageInfoManager; +import com.alibaba.polardbx.qatest.CdcIgnore; import com.alibaba.polardbx.qatest.util.ConnectionManager; import org.junit.Before; import org.junit.Test; @@ -327,9 +328,9 @@ public void modifyMultiWithInsert3() throws Exception { QuadFunction checker = (colA, colB, colC, colD) -> (colA + 1 == colB && (colC.equals(colD) || colC.substring(0, 2).equals(colD))); concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, false, true, - 1, false, false); + 1, false, false, null); concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, false, false, - 1, false, false); + 1, false, false, null); } @Test @@ -579,4 +580,160 @@ public void changeMultiWithInsert3() throws Exception { concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, false, false, 2); } + + @Test + public void omcWithFloatPk() throws Exception { + String tableName = "omc_with_float_pk"; + String colDef = "float primary key"; + String createSql = String.format( + "create table %%s (" + + "a int, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") partition by hash(`a`) partitions 3", + colDef); + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s modify column c int," + USE_OMC_ALGORITHM; + String selectSql = "select * from %s"; + Function generator = + (count) -> String.format( + "insert into %%s(a,b,c,d) values (%d*2,%d*2+1,%d*2,%d*2+1),(%d*2+1,%d*2+2,%d*2,%d*2+1)", + count, count, count, count, count, count, count, count); + QuadFunction checker = (colA, colB, colC, colD) -> true; + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator, generator, checker, + false, false, 2, createSql); + } + + @Test + public void singleChangeMultiWithInsert1() throws Exception { + String tableName = "omc_singe_multi_with_insert_1"; + String colDef = "int"; + String createSql = String.format( + "create table %%s (" + + "a int, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") single", + colDef); + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint, change column c cc varchar(20) default 'new default', drop column d, add column f varchar(10) not null default 'new column'"; + String selectSql = "select * from %s"; + Function generator1 = + (count) -> String.format("insert into %%s(a,b) values (%d*2,%d*2+1),(%d*2+1,%d*2+2)", count, + count, count, count); + Function generator2 = + (count) -> String.format("insert into %%s(a,e) values (%d*2,%d*2+1),(%d*2+1,%d*2+2)", count, + count, count, count); + QuadFunction checker = + (colA, colB, colC, colD) -> (colA + 1 == colB && !(colC.equalsIgnoreCase("new default") + && colD.equalsIgnoreCase("abc"))); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, + false, false, 2, createSql); + } + + @Test + public void broadcastChangeMultiWithInsert1() throws Exception { + String tableName = "omc_broadcast_multi_with_insert_1"; + String colDef = "int"; + String createSql = String.format( + "create table %%s (" + + "a int, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") broadcast", + colDef); + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint, change column c cc varchar(20) default 'new default', drop column d, add column f varchar(10) not null default 'new column'"; + String selectSql = "select * from %s"; + Function generator1 = + (count) -> String.format("insert into %%s(a,b) values (%d*2,%d*2+1),(%d*2+1,%d*2+2)", count, + count, count, count); + Function generator2 = + (count) -> String.format("insert into %%s(a,e) values (%d*2,%d*2+1),(%d*2+1,%d*2+2)", count, + count, count, count); + QuadFunction checker = + (colA, colB, colC, colD) -> (colA + 1 == colB && !(colC.equalsIgnoreCase("new default") + && colD.equalsIgnoreCase("abc"))); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, + false, false, 2, createSql); + } + + @Test + @CdcIgnore(ignoreReason = "omc 精度变更导致cdc数据校验无法通过") + public void changeWithInsert9() throws Exception { + String tableName = "omc_with_insert_9"; + String colDef = "decimal(8,2)"; + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e decimal(9,3)"; + String selectSql = "select * from %s"; + Function generator1 = + (count) -> String.format("insert into %%s(a,b) values (%d,%f)", count, count / 7.0); + Function generator2 = + (count) -> String.format("insert into %%s(a,e) values (%d,%f)", count, count / 7.0); + QuadFunction checker = (colA, colB, colC, colD) -> true; + + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, false, true, + 1, false, false, null); + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, false, false, + 1, false, false, null); + } + + @Test + @CdcIgnore(ignoreReason = "omc 精度变更导致cdc数据校验无法通过") + public void changeWithInsert10() throws Exception { + String tableName = "omc_with_insert_10"; + String colDef = "decimal(8,2)"; + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s modify column b decimal(9,3)"; + String selectSql = "select * from %s"; + Function generator1 = + (count) -> String.format("insert into %%s(a,b) values (%d,%f)", count, count / 7.0); + QuadFunction checker = (colA, colB, colC, colD) -> true; + + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator1, checker, false, true, + 1, false, false, null); + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator1, checker, false, false, + 1, false, false, null); + } + + @Test + @CdcIgnore(ignoreReason = "omc 精度变更导致cdc数据校验无法通过") + public void changeWithInsert11() throws Exception { + String tableName = "omc_with_insert_11"; + String colDef = "float(8,2)"; + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e decimal(9,3)"; + String selectSql = "select * from %s"; + Function generator1 = + (count) -> String.format("insert into %%s(a,b) values (%d,%f)", count, count / 7.0); + Function generator2 = + (count) -> String.format("insert into %%s(a,e) values (%d,%f)", count, count / 7.0); + QuadFunction checker = (colA, colB, colC, colD) -> true; + + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, false, true, + 1, false, false, null); + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, false, false, + 1, false, false, null); + } + + @Test + @CdcIgnore(ignoreReason = "omc 精度变更导致cdc数据校验无法通过") + public void changeWithInsert12() throws Exception { + String tableName = "omc_with_insert_12"; + String colDef = "float(8,2)"; + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s modify column b decimal(9,3)"; + String selectSql = "select * from %s"; + Function generator1 = + (count) -> String.format("insert into %%s(a,b) values (%d,%f)", count, count / 7.0); + QuadFunction checker = (colA, colB, colC, colD) -> true; + + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator1, checker, false, true, + 1, false, false, null); + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator1, checker, false, false, + 1, false, false, null); + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentReplaceTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentReplaceTest.java index def7b8a8b..30fb2b423 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentReplaceTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentReplaceTest.java @@ -1,11 +1,11 @@ package com.alibaba.polardbx.qatest.ddl.auto.omc; import com.alibaba.polardbx.executor.common.StorageInfoManager; +import com.alibaba.polardbx.qatest.CdcIgnore; import com.alibaba.polardbx.qatest.util.ConnectionManager; import org.junit.Before; import org.junit.Test; -import java.util.function.BiFunction; import java.util.function.Function; public class ConcurrentReplaceTest extends ConcurrentDMLBaseTest { @@ -50,7 +50,7 @@ public void modifyWithReplace2() throws Exception { + " alter table %s modify column b bigint"; String selectSql = "select * from %s order by a desc"; Function generator = (count) -> String.format( - buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING, ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + "replace into %%s values(%d + %d, %d,null,null)", count, FILL_COUNT, count); QuadFunction checker = @@ -164,7 +164,7 @@ public void changeWithReplace2() throws Exception { + " alter table %s change column b e bigint"; String selectSql = "select * from %s order by a desc"; Function generator = (count) -> String.format( - buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING, ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + "replace into %%s values(%d + %d, %d,null,null)", count, FILL_COUNT, count); QuadFunction checker = @@ -220,7 +220,7 @@ public void changeMultiWithReplace2() throws Exception { + " alter table %s change column b e bigint, change column c cc char(10) character set utf8, drop column d, add column f varchar(10) default \"def d\""; String selectSql = "select * from %s order by a desc"; Function generator = (count) -> String.format( - buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING, ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + "replace into %%s values(%d + %d, %d, \"def c\", \"def d\")", count, FILL_COUNT, count); QuadFunction checker = @@ -249,4 +249,71 @@ public void changeMultiWithReplace3() throws Exception { concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, false, 1); } + + @Test + public void singleChangeMultiWithReplace() throws Exception { + String tableName = "omc_single_with_replace"; + String colDef = "int default 3"; + String createSql = String.format( + "create table %%s (" + + "a int primary key, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") single", + colDef); + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint default 4, change column c f char(10) character set utf8mb4 default 'wumu'"; + String selectSql = "select * from %s order by a"; + Function generator = (count) -> String.format( + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) + "replace into %%s(a) values(%d)", count); + QuadFunction checker = + (colA, colB, colC, colD) -> (colB == 3 || colB == 4) + && (colC.equalsIgnoreCase("abc") || colC.equalsIgnoreCase("wumu")); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, + false, 1, createSql); + } + + @Test + public void broadcastChangeMultiWithReplace() throws Exception { + String tableName = "omc_broadcast_with_replace"; + String colDef = "int default 3"; + String createSql = String.format( + "create table %%s (" + + "a int primary key, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") broadcast", + colDef); + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint default 4, change column c f char(10) character set utf8mb4 default 'wumu'"; + String selectSql = "select * from %s order by a"; + Function generator = (count) -> String.format( + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) + "replace into %%s(a) values(%d)", count); + QuadFunction checker = + (colA, colB, colC, colD) -> (colB == 3 || colB == 4) + && (colC.equalsIgnoreCase("abc") || colC.equalsIgnoreCase("wumu")); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, + false, 1, createSql); + } + + @Test + @CdcIgnore(ignoreReason = "omc 精度变更导致cdc数据校验无法通过") + public void changeWithReplace4() throws Exception { + String tableName = "omc_with_replace_4"; + String colDef = "float(8,2)"; + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s modify column b decimal(9,3)"; + String selectSql = "select * from %s"; + Function generator = (count) -> String.format( + buildCmdExtra(USE_LOGICAL_EXECUTION, DISABLE_DML_RETURNING) + + "replace into %%s values(%d, %f + %d,null,null)", count, count / 7.0, FILL_COUNT); + QuadFunction checker = (colA, colB, colC, colD) -> true; + + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, true, + 1, false, false, null); + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, false, + 1, false, false, null); + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentUpdateTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentUpdateTest.java index 351974649..c3a67e81c 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentUpdateTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentUpdateTest.java @@ -1,12 +1,12 @@ package com.alibaba.polardbx.qatest.ddl.auto.omc; import com.alibaba.polardbx.executor.common.StorageInfoManager; +import com.alibaba.polardbx.qatest.CdcIgnore; import com.alibaba.polardbx.qatest.util.ConnectionManager; import org.junit.Before; import org.junit.Test; import java.util.Objects; -import java.util.function.BiFunction; import java.util.function.Function; public class ConcurrentUpdateTest extends ConcurrentDMLBaseTest { @@ -417,4 +417,74 @@ public void modifyWithUpdateAndNothingChanged() throws Exception { concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator, generator, checker, true, false, 1); } + + @Test + public void singleChangeMultiWithUpdate() throws Exception { + String tableName = "omc_single_multi_with_update"; + String colDef = "int default 3"; + String createSql = String.format( + "create table %%s (" + + "a int primary key, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") single", + colDef); + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint default 4, change column c d char(10), change column d c char(10)"; + String selectSql = "select * from %s order by a"; + Function generator1 = + (count) -> String.format("update %%s set b=a+1,a=%d,b=a+1,b=b+1,c=a,d=b where a=%d", count, count); + Function generator2 = + (count) -> String.format("update %%s set e=a+1,a=%d,e=a+1,e=e+1,c=e,d=a where a=%d", count, count); + QuadFunction checker = + (colA, colB, colC, colD) -> (colB == colA + 2) && (Float.parseFloat(colD) == Float.parseFloat(colC) + 2); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, + true, false, 1, createSql); + } + + @Test + public void broadcastChangeMultiWithUpdate() throws Exception { + String tableName = "omc_single_multi_with_update"; + String colDef = "int default 3"; + String createSql = String.format( + "create table %%s (" + + "a int primary key, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") broadcast", + colDef); + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint default 4, change column c d char(10), change column d c char(10)"; + String selectSql = "select * from %s order by a"; + Function generator1 = + (count) -> String.format("update %%s set b=a+1,a=%d,b=a+1,b=b+1,c=a,d=b where a=%d", count, count); + Function generator2 = + (count) -> String.format("update %%s set e=a+1,a=%d,e=a+1,e=e+1,c=e,d=a where a=%d", count, count); + QuadFunction checker = + (colA, colB, colC, colD) -> (colB == colA + 2) && (Float.parseFloat(colD) == Float.parseFloat(colC) + 2); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, + true, false, 1, createSql); + } + + @Test + @CdcIgnore(ignoreReason = "双写对低精度数据做了四舍五入会导致切换前后表中的数据不一致, CDC忽略掉") + public void changeWithUpdate7() throws Exception { + String tableName = "omc_with_update_7"; + String colDef = "float(8,2)"; + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e decimal(9,3)"; + String selectSql = "select * from %s"; + Function generator1 = + (count) -> String.format("update %%s set b=%f where a=%d", count / 7.0, count); + Function generator2 = + (count) -> String.format("update %%s set e=%f where a=%d", count / 7.0, count); + QuadFunction checker = (colA, colB, colC, colD) -> true; + + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, true, true, + 1, false, false, null); + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, true, false, + 1, false, false, null); + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentUpsertTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentUpsertTest.java index fb05a4147..319a55542 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentUpsertTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/ConcurrentUpsertTest.java @@ -1,11 +1,11 @@ package com.alibaba.polardbx.qatest.ddl.auto.omc; import com.alibaba.polardbx.executor.common.StorageInfoManager; +import com.alibaba.polardbx.qatest.CdcIgnore; import com.alibaba.polardbx.qatest.util.ConnectionManager; import org.junit.Before; import org.junit.Test; -import java.util.function.BiFunction; import java.util.function.Function; public class ConcurrentUpsertTest extends ConcurrentDMLBaseTest { @@ -68,7 +68,8 @@ public void modifyWithUpsert3() throws Exception { + " alter table %s modify column b bigint"; String selectSql = "select * from %s order by a desc"; Function generator = - (count) -> String.format("insert into %%s values(%d + %d, %d,null,null) on duplicate key update a=a+%d", + (count) -> String.format(buildCmdExtra(ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + + "insert into %%s values(%d + %d, %d,null,null) on duplicate key update a=a+%d", count, FILL_COUNT, count, FILL_COUNT); QuadFunction checker = (colA, colB, colC, colD) -> colA - FILL_COUNT == colB; @@ -224,7 +225,8 @@ public void changeWithUpsert3() throws Exception { + " alter table %s change column b e bigint"; String selectSql = "select * from %s order by a desc"; Function generator1 = - (count) -> String.format("insert into %%s values(%d + %d, %d,null,null) on duplicate key update a=a+%d", + (count) -> String.format(buildCmdExtra(ENABLE_LOCAL_UK_FULL_TABLE_SCAN) + + "insert into %%s values(%d + %d, %d,null,null) on duplicate key update a=a+%d", count, FILL_COUNT, count, FILL_COUNT); Function generator2 = (count) -> String.format("insert into %%s values(%d + %d, %d,null,null) on duplicate key update a=a+%d", @@ -319,7 +321,7 @@ public void changeWithUpsert7() throws Exception { count, count, FILL_COUNT); Function generator2 = (count) -> String.format( - "insert into %%s values(%d, %d + %d,null,null) on duplicate key update e=default(e),f=default(g)", + "insert into %%s values(%d, %d + %d,null,default) on duplicate key update e=default(e),f=default(g)", count, count, FILL_COUNT); QuadFunction checker = (colA, colB, colC, colD) -> (colB == 3 || colB == 4) @@ -329,4 +331,86 @@ public void changeWithUpsert7() throws Exception { concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, true, false, 1); } + + @Test + public void singleChangeWithUpsert() throws Exception { + String tableName = "omc_single_with_upsert"; + String colDef = "int default 3"; + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint default 4, change column c f varchar(7) default 'aaa', drop column d, add column g char(10) not null default 'xyz'"; + String selectSql = "select * from %s order by a"; + String createSql = String.format( + "create table %%s (" + + "a int primary key, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") single", + colDef); + Function generator1 = + (count) -> String.format( + "insert into %%s values(%d, %d + %d,null,null) on duplicate key update b=default(b),c=default(d)", + count, count, FILL_COUNT); + Function generator2 = + (count) -> String.format( + "insert into %%s values(%d, %d + %d,null,default) on duplicate key update e=default(e),f=default(g)", + count, count, FILL_COUNT); + QuadFunction checker = + (colA, colB, colC, colD) -> (colB == 3 || colB == 4) + && (colC.equalsIgnoreCase("abc") || colC.equalsIgnoreCase("xyz")); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, + true, false, 1, createSql); + } + + @Test + public void broadcastChangeWithUpsert() throws Exception { + String tableName = "omc_broadcast_with_upsert"; + String colDef = "int default 3"; + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e bigint default 4, change column c f varchar(7) default 'aaa', drop column d, add column g char(10) not null default 'xyz'"; + String selectSql = "select * from %s order by a"; + String createSql = String.format( + "create table %%s (" + + "a int primary key, " + + "b %s, " + + "c varchar(10) default 'abc'," + + "d varchar(10) default 'abc'" + + ") single", + colDef); + Function generator1 = + (count) -> String.format( + "insert into %%s values(%d, %d + %d,null,null) on duplicate key update b=default(b),c=default(d)", + count, count, FILL_COUNT); + Function generator2 = + (count) -> String.format( + "insert into %%s values(%d, %d + %d,null,default) on duplicate key update e=default(e),f=default(g)", + count, count, FILL_COUNT); + QuadFunction checker = + (colA, colB, colC, colD) -> (colB == 3 || colB == 4) + && (colC.equalsIgnoreCase("abc") || colC.equalsIgnoreCase("xyz")); + concurrentTestInternalWithCreateSql(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, + true, false, 1, createSql); + } + + @Test + @CdcIgnore(ignoreReason = "omc 精度变更导致cdc数据校验无法通过") + public void changeWithUpsert8() throws Exception { + String tableName = "omc_with_update_8"; + String colDef = "float(8,2)"; + String alterSql = buildCmdExtra(OMC_FORCE_TYPE_CONVERSION) + + " alter table %s change column b e decimal(9,3)"; + String selectSql = "select * from %s order by a"; + Function generator1 = + (count) -> String.format("insert into %%s values(%d, %f,null,null) on duplicate key update a=a+%d", count, + count / 7.0, FILL_COUNT); + Function generator2 = + (count) -> String.format("insert into %%s values(%d, %f,null,null) on duplicate key update a=a+%d", count, + count / 7.0, FILL_COUNT); + QuadFunction checker = (colA, colB, colC, colD) -> true; + + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, true, true, + 1, false, false, null); + concurrentTestInternal(tableName, colDef, alterSql, selectSql, generator1, generator2, checker, true, false, + 1, false, false, null); + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/OMCMultiWriteTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/OMCMultiWriteTest.java index 1c4589fee..245b2b48e 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/OMCMultiWriteTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/OMCMultiWriteTest.java @@ -282,6 +282,63 @@ public void testStayAtWriteOnlyWithGsi() { assertTraceContains(trace, "DELETE", 2); } + @Test + public void testAfterOmc() { + String tableName = "after_omc_test_tb1" + RandomUtils.getStringBetween(1, 5); + dropTableIfExists(tableName); + String sql = String.format( + "create table %s (a varchar(11) primary key, b bigint, c bigint) partition by key(`a`) partitions 3", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("insert into table `%s` values('123', 1, 2), ('234', 2, 3)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("alter table `%s` modify b int, algorithm = omc", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("insert into table `%s` values('456', 4, 5)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + List> trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(1)); + + sql = String.format("UPDATE %s SET b = 2 WHERE a = '123'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + assertTraceContains(trace, "UPDATE", 1); + Assert.assertThat(trace.size(), is(1)); + + sql = String.format("DELETE FROM %s WHERE a = '234'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + assertTraceContains(trace, "DELETE", 1); + Assert.assertThat(trace.size(), is(1)); + + sql = String.format("INSERT IGNORE INTO %s VALUES ('567', 5, 6)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(1)); + + sql = String.format("INSERT INTO %s VALUES ('567', 5, 6) ON DUPLICATE KEY UPDATE a = '678'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + assertTraceContains(trace, "DELETE", 1); + assertTraceContains(trace, "INSERT", 1); + + sql = String.format("REPLACE INTO %s VALUES ('567', 5, 6)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(1)); + + sql = String.format("INSERT IGNORE INTO %s VALUES ('678', 6 ,7)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, dmlHintStr + sql); + sql = String.format("REPLACE INTO %s VALUES ('678', 7, 8)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(1)); + assertTraceContains(trace, "DELETE", 0); + } + @Test public void testStayAtDeleteOnlyWithChangeColumn() { String tableName = "modify_sk_test_tbl" + RandomUtils.getStringBetween(1, 5); @@ -344,6 +401,63 @@ public void testStayAtDeleteOnlyWithChangeColumn() { assertTraceContains(trace, "DELETE", 1); } + @Test + public void testAfterOmcWithChangeColumn() { + String tableName = "after_omc_test_tb2" + RandomUtils.getStringBetween(1, 5); + dropTableIfExists(tableName); + String sql = String.format( + "create table %s (a varchar(11) primary key, b bigint, c bigint) partition by key(`a`) partitions 3", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("insert into table `%s` values('123', 1, 2), ('234', 2, 3)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("alter table `%s` change column b d int, algorithm = omc", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("insert into table `%s` values('456', 4, 5)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + List> trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(1)); + + sql = String.format("UPDATE %s SET d = 2 WHERE a = '123'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + assertTraceContains(trace, "UPDATE", 1); + Assert.assertThat(trace.size(), is(1)); + + sql = String.format("DELETE FROM %s WHERE a = '234'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + assertTraceContains(trace, "DELETE", 1); + Assert.assertThat(trace.size(), is(1)); + + sql = String.format("INSERT IGNORE INTO %s VALUES ('567', 5, 6)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(1)); + + sql = String.format("INSERT INTO %s VALUES ('567', 5, 6) ON DUPLICATE KEY UPDATE a = '678'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + assertTraceContains(trace, "DELETE", 1); + assertTraceContains(trace, "INSERT", 1); + + sql = String.format("REPLACE INTO %s VALUES ('567', 5, 6)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(1)); + + sql = String.format("INSERT IGNORE INTO %s VALUES ('678', 6 ,7)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, dmlHintStr + sql); + sql = String.format("REPLACE INTO %s VALUES ('678', 7, 8)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(1)); + assertTraceContains(trace, "DELETE", 0); + } + @Test public void testStayAtWriteOnlyWithChangeColumn() { String tableName = "modify_sk_test_tbl2" + RandomUtils.getStringBetween(1, 5); @@ -405,6 +519,67 @@ public void testStayAtWriteOnlyWithChangeColumn() { assertTraceContains(trace, "DELETE", 1); } + @Test + public void testAfterOmcWithGsi() { + String tableName = "after_omc_gsi_test_tb1" + RandomUtils.getStringBetween(1, 5); + dropTableIfExists(tableName); + String sql = String.format( + "create table %s (a varchar(11) primary key, b bigint, c bigint) partition by key(`a`) partitions 3", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("insert into table `%s` values('123', 1, 2), ('234', 2, 3)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format( + "alter table `%s` add global index modify_sk_test_gsi(a, b, c) partition by key(`a`) partitions 3", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("alter table `%s` modify b int, algorithm = omc", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("insert into table `%s` values('456', 4, 5)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + List> trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(2)); + + sql = String.format("UPDATE %s SET b = 2 WHERE a = '123'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(3)); + + sql = String.format("DELETE FROM %s WHERE a = '234'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + assertTraceContains(trace, "DELETE", 2); + Assert.assertThat(trace.size(), is(3)); + + sql = String.format("INSERT IGNORE INTO %s VALUES ('567', 5, 6)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(2)); + + sql = String.format("INSERT INTO %s VALUES ('567', 5, 6) ON DUPLICATE KEY UPDATE a = '678'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + assertTraceContains(trace, "DELETE", 2); + assertTraceContains(trace, "INSERT", 2); + + sql = String.format("REPLACE INTO %s VALUES ('567', 5, 6)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(2)); + + sql = String.format("INSERT IGNORE INTO %s VALUES ('678', 6 ,7)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, dmlHintStr + sql); + sql = String.format("REPLACE INTO %s VALUES ('678', 7, 8)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(2)); + assertTraceContains(trace, "DELETE", 0); + } + @Test public void testStayAtDeleteOnlyWithGsiWithChangeColumn() { String tableName = "modify_sk_test_tbl3" + RandomUtils.getStringBetween(1, 5); @@ -538,6 +713,67 @@ public void testStayAtWriteOnlyWithGsiWithChangeColumn() { assertTraceContains(trace, "DELETE", 2); } + @Test + public void testAfterOmcChangeColumnWithGsi() { + String tableName = "after_omc_gsi_test_tb2" + RandomUtils.getStringBetween(1, 5); + dropTableIfExists(tableName); + String sql = String.format( + "create table %s (a varchar(11) primary key, b bigint, c bigint) partition by key(`a`) partitions 3", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("insert into table `%s` values('123', 1, 2), ('234', 2, 3)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format( + "alter table `%s` add global index modify_sk_test_gsi(a, b, c) partition by key(`a`) partitions 3", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("alter table `%s` change column b d int, algorithm = omc", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("insert into table `%s` values('456', 4, 5)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + List> trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(2)); + + sql = String.format("UPDATE %s SET d = 2 WHERE a = '123'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(3)); + + sql = String.format("DELETE FROM %s WHERE a = '234'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + assertTraceContains(trace, "DELETE", 2); + Assert.assertThat(trace.size(), is(3)); + + sql = String.format("INSERT IGNORE INTO %s VALUES ('567', 5, 6)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(2)); + + sql = String.format("INSERT INTO %s VALUES ('567', 5, 6) ON DUPLICATE KEY UPDATE a = '678'", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + assertTraceContains(trace, "DELETE", 2); + assertTraceContains(trace, "INSERT", 2); + + sql = String.format("REPLACE INTO %s VALUES ('567', 5, 6)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(2)); + + sql = String.format("INSERT IGNORE INTO %s VALUES ('678', 6 ,7)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, dmlHintStr + sql); + sql = String.format("REPLACE INTO %s VALUES ('678', 7, 8)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); + trace = getTrace(tddlConnection); + Assert.assertThat(trace.size(), is(2)); + assertTraceContains(trace, "DELETE", 0); + } + protected void assertTraceContains(List> trace, String targetStr, int count) { int c = 0; for (List item : trace) { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/OnlineModifyColumnTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/OnlineModifyColumnTest.java index 7f31602fa..12691bf4a 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/OnlineModifyColumnTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/omc/OnlineModifyColumnTest.java @@ -741,34 +741,34 @@ public void testExplainOMC() { JdbcUtil.executeUpdateSuccess(tddlConnection, sql); sql = String.format("explain alter table %s modify column b bigint," + USE_OMC_ALGORITHM, tableName); - checkExplainCount(sql, 5); + checkExplainCount(sql, 7); sql = String.format("explain alter table %s modify column b bigint not null," + USE_OMC_ALGORITHM, tableName); - checkExplainCount(sql, 5); + checkExplainCount(sql, 7); sql = String.format("explain alter table %s modify column b bigint not null default 123," + USE_OMC_ALGORITHM, tableName); - checkExplainCount(sql, 5); + checkExplainCount(sql, 7); sql = String.format("explain alter table %s modify column c bigint," + USE_OMC_ALGORITHM, tableName); - checkExplainCount(sql, 5); + checkExplainCount(sql, 7); sql = String.format("explain alter table %s modify column c bigint not null," + USE_OMC_ALGORITHM, tableName); - checkExplainCount(sql, 5); + checkExplainCount(sql, 7); sql = String.format("explain alter table %s modify column c bigint not null default 123," + USE_OMC_ALGORITHM, tableName); - checkExplainCount(sql, 5); + checkExplainCount(sql, 7); sql = String.format("explain alter table %s modify column d bigint," + USE_OMC_ALGORITHM, tableName); - checkExplainCount(sql, 5); + checkExplainCount(sql, 7); sql = String.format("explain alter table %s modify column d bigint not null," + USE_OMC_ALGORITHM, tableName); - checkExplainCount(sql, 5); + checkExplainCount(sql, 7); sql = String.format("explain alter table %s modify column d bigint not null default 123," + USE_OMC_ALGORITHM, tableName); - checkExplainCount(sql, 5); + checkExplainCount(sql, 7); } public void checkExplainCount(String sql, int expected) { @@ -832,4 +832,49 @@ public void testOnlineModifyColumnWithUGsi() { JdbcUtil.close(rs1); } } + + @Test + public void testOnlineModifyColumnWithAutoIncrement() { + String tableName = "omc_auto_increment" + RandomUtils.getStringBetween(1, 5); + dropTableIfExists(tableName); + String sql = + String.format("create table %s (a int primary key, b int ) partition by hash(a) partitions 3", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("alter table %s modify column a bigint auto_increment," + USE_OMC_ALGORITHM, tableName); + JdbcUtil.executeUpdateFailed(tddlConnection, sql, "Missing sequence"); + + sql = String.format("CREATE SEQUENCE `AUTO_SEQ_%s`", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("alter table %s modify column a bigint auto_increment," + USE_OMC_ALGORITHM, tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("insert into table %s(b) values (null),(null)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } + + @Test + public void testOnlineModifyColumnWithNullAble() { + String tableName = "omc_nullable" + RandomUtils.getStringBetween(1, 5); + dropTableIfExists(tableName); + String sql = + String.format( + "create table %s (a int primary key auto_increment, b varchar(10)) partition by hash(a) partitions 3", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + String sqlMode = JdbcUtil.getSqlMode(tddlConnection); + try { + setSqlMode("", tddlConnection); + + sql = String.format("insert into table %s(b) values (null),(null),(\"123\")", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = String.format("alter table %s modify column b varchar(10) not null," + USE_OMC_ALGORITHM, tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } finally { + setSqlMode(sqlMode, tddlConnection); + } + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/AlterTableDropPartitionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/AlterTableDropPartitionTest.java new file mode 100644 index 000000000..e8af8e368 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/AlterTableDropPartitionTest.java @@ -0,0 +1,21 @@ +package com.alibaba.polardbx.qatest.ddl.auto.partition; + +import org.junit.runners.Parameterized; + +import java.util.List; + +/** + * @author chenghui.lch + */ + +public class AlterTableDropPartitionTest extends PartitionAutoLoadSqlTestBase { + + public AlterTableDropPartitionTest(AutoLoadSqlTestCaseParams parameter) { + super(parameter); + } + + @Parameterized.Parameters(name = "{index}: SubTestCase {0}") + public static List parameters() { + return getParameters(AlterTableDropPartitionTest.class, 3, true); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/CreateTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/CreateTableTest.java index 025e5099a..a24738738 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/CreateTableTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/CreateTableTest.java @@ -639,6 +639,13 @@ public void testBug55930380() { JdbcUtil.executeUpdateSuccess(tddlConnection, sql); } + @Test + public void testBug58096294() { + String sql = + "create table testBug58096294(a int, b int, local index `auto_shard_key_a`(b)) partition by key(a) partitions 2 "; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } + private static final String EMPTY = ""; private String removeInvisibleChar(String sql) { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/ImplicitTableGroupTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/ImplicitTableGroupTest.java index 2f7ffb7de..3a9b0d500 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/ImplicitTableGroupTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/ImplicitTableGroupTest.java @@ -16,7 +16,7 @@ public ImplicitTableGroupTest(AutoLoadSqlTestCaseParams parameter) { @Parameterized.Parameters(name = "{index}: SubTestCase {0}") public static List parameters() { - return getParameters(ImplicitTableGroupTest.class, 0, false); + return getParameters(ImplicitTableGroupTest.class, 0, true); } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionAutoLoadSqlTestBase.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionAutoLoadSqlTestBase.java index 426eab413..c9c3cd17a 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionAutoLoadSqlTestBase.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionAutoLoadSqlTestBase.java @@ -174,6 +174,7 @@ protected void runOneTestCaseInner(AutoLoadSqlTestCaseParams params) { JdbcUtil.createPartDatabase(conn, dbName); } applyResourceFileIfExists(dbName, tcName.toLowerCase(), testClass); + JdbcUtil.disableAutoForceIndex(conn); testResult = runTestBySourceSql(tcName.toLowerCase(), supportAutoPart, testClass, dbName, conn, s -> applySubstitute(s)); JdbcUtil.dropDatabase(conn, dbName); @@ -204,6 +205,12 @@ protected void runOneTestCaseInner(AutoLoadSqlTestCaseParams params) { exceptedResult; exceptedResult = exceptedResult.replaceAll("part_mtr", params.testDbName); + // remove HitCache and ; + testResult = testResult.replaceAll(";\n", "\n"); + exceptedResult = exceptedResult.replaceAll(";\n", "\n"); + + String pattern = "HitCache.*\n?|"; + boolean mysql80 = isMySQL80(); if (mysql80) { String[] rsCmpArr = new String[2]; @@ -266,7 +273,13 @@ protected void runOneTestCaseInner(AutoLoadSqlTestCaseParams params) { } buildAndPrintTestInfo(testClassName, tcName, testResult, exceptedResult); - Assert.assertEquals(exceptedResult, testResult); + // The result of ShowDalTest is variable in different environment(e.g. show status) + // therefore we only guarantee the result do not contain ERROR + if ("ShowDalTest".equalsIgnoreCase(testClassName)) { + Assert.assertTrue(!testResult.startsWith("ERROR")); + } else { + Assert.assertEquals(exceptedResult, testResult); + } } catch (Throwable ex) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintWriter pw = new PrintWriter(baos); @@ -577,6 +590,9 @@ protected static String execSqlAndPrintResult(String sql, boolean needGetErrMsg, StringBuilder sb = new StringBuilder(""); try { + if (sql.toLowerCase().contains("explain ")) { + conn.createStatement().execute("clear plancache"); + } Statement stmt = conn.createStatement(); int updateCnt; boolean hasResultSet; @@ -593,7 +609,11 @@ protected static String execSqlAndPrintResult(String sql, boolean needGetErrMsg, } ResultSet rs = stmt.getResultSet(); List> rsInfo = JdbcUtil.getAllStringResultWithColumnNames(rs, ignoredException, null); - if (sql.toLowerCase().startsWith("explain")) { + + if (rsInfo != null && + rsInfo.size() >= 1 && + rsInfo.get(0).size() == 1 && + rsInfo.get(0).get(0).equalsIgnoreCase("Logical ExecutionPlan")) { rsInfo = ignoreTemplateIdInfoForExplainResults(rsInfo); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionIntraGroupParallel2Test.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionIntraGroupParallel2Test.java new file mode 100644 index 000000000..7fad7a5e4 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionIntraGroupParallel2Test.java @@ -0,0 +1,20 @@ +package com.alibaba.polardbx.qatest.ddl.auto.partition; + +import org.junit.runners.Parameterized; + +import java.util.List; + +/** + * @author chenghui.lch + */ +public class PartitionIntraGroupParallel2Test extends PartitionAutoLoadSqlTestBase { + + public PartitionIntraGroupParallel2Test(AutoLoadSqlTestCaseParams parameter) { + super(parameter); + } + + @Parameterized.Parameters(name = "{index}: SubTestCase {0}") + public static List parameters() { + return getParameters(PartitionIntraGroupParallel2Test.class, 0, false); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableBkaJoinTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableBkaJoinTest.java new file mode 100644 index 000000000..12022c026 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableBkaJoinTest.java @@ -0,0 +1,16 @@ +package com.alibaba.polardbx.qatest.ddl.auto.partition; + +import org.junit.runners.Parameterized; + +import java.util.List; + +public class PartitionTableBkaJoinTest extends PartitionAutoLoadSqlTestBase { + public PartitionTableBkaJoinTest(AutoLoadSqlTestCaseParams parameter) { + super(parameter); + } + + @Parameterized.Parameters(name = "{index}: SubTestCase {0}") + public static List parameters() { + return getParameters(PartitionTableBkaJoinTest.class, 0, false); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTablePruning4Test.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTablePruning4Test.java new file mode 100644 index 000000000..7053c90c9 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTablePruning4Test.java @@ -0,0 +1,23 @@ +package com.alibaba.polardbx.qatest.ddl.auto.partition; + +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.List; + +/** + * @author chenghui.lch + */ +@RunWith(value = Parameterized.class) +public class PartitionTablePruning4Test extends PartitionAutoLoadSqlTestBase { + + public PartitionTablePruning4Test(AutoLoadSqlTestCaseParams parameter) { + super(parameter); + } + + @Parameterized.Parameters(name = "{index}: SubTestCase {0}") + public static List parameters() { + return getParameters(PartitionTablePruning4Test.class, 0, false); + } + +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableRangeScanTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableRangeScanTest.java new file mode 100644 index 000000000..a8cce22c3 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableRangeScanTest.java @@ -0,0 +1,18 @@ +package com.alibaba.polardbx.qatest.ddl.auto.partition; + +import org.junit.runners.Parameterized; + +import java.util.List; + +public class PartitionTableRangeScanTest extends PartitionAutoLoadSqlTestBase { + + public PartitionTableRangeScanTest(AutoLoadSqlTestCaseParams parameter) { + super(parameter); + } + + @Parameterized.Parameters(name = "{index}: SubTestCase {0}") + public static List parameters() { + return getParameters(PartitionTableRangeScanTest.class, 0, false); + } + +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableSelectPartitionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableSelectPartitionTest.java index 79f7e822a..4dfaa5de0 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableSelectPartitionTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableSelectPartitionTest.java @@ -16,7 +16,6 @@ package com.alibaba.polardbx.qatest.ddl.auto.partition; -import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.List; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableTtlTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableTtlTest.java new file mode 100644 index 000000000..1a608101a --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partition/PartitionTableTtlTest.java @@ -0,0 +1,25 @@ +package com.alibaba.polardbx.qatest.ddl.auto.partition; + +import net.jcip.annotations.NotThreadSafe; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.List; + +/** + * @author luoyanxin + */ +@RunWith(value = Parameterized.class) +@NotThreadSafe +public class PartitionTableTtlTest extends PartitionAutoLoadSqlTestBase { + + public PartitionTableTtlTest(AutoLoadSqlTestCaseParams parameter) { + super(parameter); + } + + @Parameterized.Parameters(name = "{index}: SubTestCase {0}") + public static List parameters() { + return getParameters(PartitionTableTtlTest.class, 0, false); + } + +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partitionkey/ExplainValidateTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partitionkey/ExplainValidateTest.java index 7db3ea95e..237fb7422 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partitionkey/ExplainValidateTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/partitionkey/ExplainValidateTest.java @@ -33,6 +33,10 @@ public void testExplainModifyPartitionKey() { Assert.assertTrue(rs.next()); Assert.assertTrue(rs.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs.next()); + Assert.assertTrue(rs.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs.next()); + Assert.assertTrue(rs.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs.next()); Assert.assertTrue(rs.getString(1).contains("DROP_TABLE")); Assert.assertTrue(rs.next()); Assert.assertTrue(rs.getString(1).contains("EXCLUDE_RESOURCE")); @@ -63,6 +67,10 @@ public void testExplainModifyPartitionKey() { Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs3.next()); + Assert.assertTrue(rs3.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs3.next()); + Assert.assertTrue(rs3.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("DROP_TABLE")); Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("EXCLUDE_RESOURCE")); @@ -81,6 +89,10 @@ public void testExplainModifyPartitionKey() { Assert.assertTrue(rs4.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs4.getString(1).contains("CHARACTER SET gbk")); Assert.assertTrue(rs4.next()); + Assert.assertTrue(rs4.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs4.next()); + Assert.assertTrue(rs4.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs4.next()); Assert.assertTrue(rs4.getString(1).contains("DROP_TABLE")); Assert.assertTrue(rs4.next()); Assert.assertTrue(rs4.getString(1).contains("EXCLUDE_RESOURCE")); @@ -108,6 +120,10 @@ public void testExplainModifyPartitionKeyOMC() { Assert.assertTrue(rs.next()); Assert.assertTrue(rs.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs.next()); + Assert.assertTrue(rs.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs.next()); + Assert.assertTrue(rs.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs.next()); Assert.assertTrue(rs.getString(1).contains("DROP_TABLE")); Assert.assertTrue(rs.next()); Assert.assertTrue(rs.getString(1).contains("EXCLUDE_RESOURCE")); @@ -125,6 +141,10 @@ public void testExplainModifyPartitionKeyOMC() { Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs2.next()); + Assert.assertTrue(rs2.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs2.next()); + Assert.assertTrue(rs2.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("DROP_TABLE")); Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("EXCLUDE_RESOURCE")); @@ -172,6 +192,10 @@ public void testExplainModifyPartitionKeyWithGsi() { Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs2.next()); + Assert.assertTrue(rs2.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs2.next()); + Assert.assertTrue(rs2.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("DROP_TABLE")); @@ -193,6 +217,10 @@ public void testExplainModifyPartitionKeyWithGsi() { Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs3.next()); + Assert.assertTrue(rs3.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs3.next()); + Assert.assertTrue(rs3.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("DROP_TABLE")); @@ -214,6 +242,10 @@ public void testExplainModifyPartitionKeyWithGsi() { Assert.assertTrue(rs4.next()); Assert.assertTrue(rs4.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs4.next()); + Assert.assertTrue(rs4.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs4.next()); + Assert.assertTrue(rs4.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs4.next()); Assert.assertTrue(rs4.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs4.next()); Assert.assertTrue(rs4.getString(1).contains("DROP_TABLE")); @@ -235,6 +267,10 @@ public void testExplainModifyPartitionKeyWithGsi() { Assert.assertTrue(rs5.next()); Assert.assertTrue(rs5.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs5.next()); + Assert.assertTrue(rs5.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs5.next()); + Assert.assertTrue(rs5.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs5.next()); Assert.assertTrue(rs5.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs5.next()); Assert.assertTrue(rs5.getString(1).contains("DROP_TABLE")); @@ -256,6 +292,10 @@ public void testExplainModifyPartitionKeyWithGsi() { Assert.assertTrue(rs6.next()); Assert.assertTrue(rs6.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs6.next()); + Assert.assertTrue(rs6.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs6.next()); + Assert.assertTrue(rs6.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs6.next()); Assert.assertTrue(rs6.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs6.next()); Assert.assertTrue(rs6.getString(1).contains("DROP_TABLE")); @@ -292,6 +332,10 @@ public void testExplainModifyPartitionKeyWithGsi() { Assert.assertTrue(rs8.next()); Assert.assertTrue(rs8.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs8.next()); + Assert.assertTrue(rs8.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs8.next()); + Assert.assertTrue(rs8.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs8.next()); Assert.assertTrue(rs8.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs8.next()); Assert.assertTrue(rs8.getString(1).contains("DROP_TABLE")); @@ -343,6 +387,10 @@ public void testExplainModifyPartitionKeyWithGsi2() { Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs2.next()); + Assert.assertTrue(rs2.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs2.next()); + Assert.assertTrue(rs2.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("DROP_TABLE")); @@ -364,6 +412,10 @@ public void testExplainModifyPartitionKeyWithGsi2() { Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs3.next()); + Assert.assertTrue(rs3.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs3.next()); + Assert.assertTrue(rs3.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("DROP_TABLE")); @@ -385,6 +437,10 @@ public void testExplainModifyPartitionKeyWithGsi2() { Assert.assertTrue(rs4.next()); Assert.assertTrue(rs4.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs4.next()); + Assert.assertTrue(rs4.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs4.next()); + Assert.assertTrue(rs4.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs4.next()); Assert.assertTrue(rs4.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs4.next()); Assert.assertTrue(rs4.getString(1).contains("DROP_TABLE")); @@ -406,6 +462,10 @@ public void testExplainModifyPartitionKeyWithGsi2() { Assert.assertTrue(rs5.next()); Assert.assertTrue(rs5.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs5.next()); + Assert.assertTrue(rs5.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs5.next()); + Assert.assertTrue(rs5.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs5.next()); Assert.assertTrue(rs5.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs5.next()); Assert.assertTrue(rs5.getString(1).contains("DROP_TABLE")); @@ -427,6 +487,10 @@ public void testExplainModifyPartitionKeyWithGsi2() { Assert.assertTrue(rs6.next()); Assert.assertTrue(rs6.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs6.next()); + Assert.assertTrue(rs6.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs6.next()); + Assert.assertTrue(rs6.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs6.next()); Assert.assertTrue(rs6.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs6.next()); Assert.assertTrue(rs6.getString(1).contains("DROP_TABLE")); @@ -463,6 +527,10 @@ public void testExplainModifyPartitionKeyWithGsi2() { Assert.assertTrue(rs8.next()); Assert.assertTrue(rs8.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs8.next()); + Assert.assertTrue(rs8.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs8.next()); + Assert.assertTrue(rs8.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs8.next()); Assert.assertTrue(rs8.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs8.next()); Assert.assertTrue(rs8.getString(1).contains("DROP_TABLE")); @@ -514,6 +582,10 @@ public void testExplainChangePartitionKeyWithGsi() { Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs2.next()); + Assert.assertTrue(rs2.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs2.next()); + Assert.assertTrue(rs2.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs2.next()); Assert.assertTrue(rs2.getString(1).contains("DROP_TABLE")); @@ -535,6 +607,10 @@ public void testExplainChangePartitionKeyWithGsi() { Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs3.next()); + Assert.assertTrue(rs3.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs3.next()); + Assert.assertTrue(rs3.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs3.next()); Assert.assertTrue(rs3.getString(1).contains("DROP_TABLE")); @@ -556,6 +632,10 @@ public void testExplainChangePartitionKeyWithGsi() { Assert.assertTrue(rs4.next()); Assert.assertTrue(rs4.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs4.next()); + Assert.assertTrue(rs4.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs4.next()); + Assert.assertTrue(rs4.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs4.next()); Assert.assertTrue(rs4.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs4.next()); Assert.assertTrue(rs4.getString(1).contains("DROP_TABLE")); @@ -577,6 +657,10 @@ public void testExplainChangePartitionKeyWithGsi() { Assert.assertTrue(rs5.next()); Assert.assertTrue(rs5.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs5.next()); + Assert.assertTrue(rs5.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs5.next()); + Assert.assertTrue(rs5.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs5.next()); Assert.assertTrue(rs5.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs5.next()); Assert.assertTrue(rs5.getString(1).contains("DROP_TABLE")); @@ -598,6 +682,10 @@ public void testExplainChangePartitionKeyWithGsi() { Assert.assertTrue(rs6.next()); Assert.assertTrue(rs6.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs6.next()); + Assert.assertTrue(rs6.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs6.next()); + Assert.assertTrue(rs6.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs6.next()); Assert.assertTrue(rs6.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs6.next()); Assert.assertTrue(rs6.getString(1).contains("DROP_TABLE")); @@ -634,6 +722,10 @@ public void testExplainChangePartitionKeyWithGsi() { Assert.assertTrue(rs8.next()); Assert.assertTrue(rs8.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs8.next()); + Assert.assertTrue(rs8.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs8.next()); + Assert.assertTrue(rs8.getString(1).contains("ALTER_TABLE")); + Assert.assertTrue(rs8.next()); Assert.assertTrue(rs8.getString(1).contains("CREATE_TABLE")); Assert.assertTrue(rs8.next()); Assert.assertTrue(rs8.getString(1).contains("DROP_TABLE")); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/primarykey/DropAddPrimaryKeyMultiWriteTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/primarykey/DropAddPrimaryKeyMultiWriteTest.java index b9d505b4a..02023f296 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/primarykey/DropAddPrimaryKeyMultiWriteTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/primarykey/DropAddPrimaryKeyMultiWriteTest.java @@ -724,8 +724,7 @@ public void testStayAtWriteOnlyWithImplicitPkGsi() { JdbcUtil.executeUpdateSuccess(tddlConnection, dmlHintStr + sql); sql = String.format("REPLACE INTO %s VALUES ('678', 7, 8)", tableName); JdbcUtil.executeUpdateSuccess(tddlConnection, "trace" + dmlHintStr + sql); - trace = getTrace(tddlConnection); - Assert.assertThat(trace.size(), is(12)); + trace = checkTraceRowCount(is(12)); assertTraceContains(trace, "DELETE", 4); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/pushDownDdl/MultiPartDdlBigCaseTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/pushDownDdl/MultiPartDdlBigCaseTest.java new file mode 100644 index 000000000..a58031b36 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/pushDownDdl/MultiPartDdlBigCaseTest.java @@ -0,0 +1,22 @@ +package com.alibaba.polardbx.qatest.ddl.auto.pushDownDdl; + +import com.alibaba.polardbx.qatest.ddl.auto.partition.PartitionAutoLoadSqlTestBase; +import org.junit.runners.Parameterized; + +import java.util.List; + +/** + * Created by taokun. + * + * @author taokun + */ +public class MultiPartDdlBigCaseTest extends PartitionAutoLoadSqlTestBase { + public MultiPartDdlBigCaseTest(AutoLoadSqlTestCaseParams parameter) { + super(parameter); + } + + @Parameterized.Parameters(name = "{index}: SubTestCase {0}") + public static List parameters() { + return getParameters(MultiPartDdlBigCaseTest.class, 0, false); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/repartition/RepartitionFailedTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/repartition/RepartitionFailedTest.java index d84e11d63..a3b96ea33 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/repartition/RepartitionFailedTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/repartition/RepartitionFailedTest.java @@ -2,8 +2,12 @@ import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Assert; import org.junit.Test; +import java.sql.ResultSet; +import java.sql.SQLException; + public class RepartitionFailedTest extends DDLBaseNewDBTestCase { @Test @@ -36,7 +40,7 @@ public void testRepartitionFailed() { JdbcUtil.executeUpdateFailed(tddlConnection, sql, "does not support"); sql = "alter table tb123 remove partitioning CHARACTER SET = utf8mb4, COLLATE = utf8mb4_unicode_ci"; - JdbcUtil.executeUpdateFailed(tddlConnection, sql, "syntax error"); + JdbcUtil.executeUpdateFailed(tddlConnection, sql, "does not support"); sql = "alter table tb123 CHARACTER SET = utf8mb4, COLLATE = utf8mb4_unicode_ci partitions 1"; JdbcUtil.executeUpdateFailed(tddlConnection, sql, "does not support"); @@ -68,6 +72,33 @@ public void testRepartitionWithZeroAutoValue() { JdbcUtil.executeUpdateSuccess(tddlConnection, sql); } + @Test + public void testRepartitionExplain() { + String sql = "drop table if exists tb12345"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "create table tb12345 (a int primary key auto_increment, b int) partition by hash(a)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "explain alter table tb12345 partition by key(a, b)"; + checkExplainCount(sql, 2); + } + + public void checkExplainCount(String sql, int expected) { + ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + try { + int count = 0; + while (rs.next()) { + count++; + } + Assert.assertEquals(expected, count); + } catch (SQLException e) { + throw new RuntimeException("", e); + } finally { + JdbcUtil.close(rs); + } + } + @Override public boolean usingNewPartDb() { return true; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/tablegroup/AlterTableGroupRepartitionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/tablegroup/AlterTableGroupRepartitionTest.java new file mode 100644 index 000000000..44ef2b8fc --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/tablegroup/AlterTableGroupRepartitionTest.java @@ -0,0 +1,202 @@ +package com.alibaba.polardbx.qatest.ddl.auto.tablegroup; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runners.Parameterized; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created by luoyanxin. + * + * @author luoyanxin + */ +public class AlterTableGroupRepartitionTest extends DDLBaseNewDBTestCase { + + final static String CREATE_DB = "create database %s mode=auto"; + final static String DROP_DB = "drop database if exists %s"; + final static String TABLE_SCHEMA = "AlterTableGroupRepartitionTestDb"; + final static String CREATE_TABLE_GROUP = "create tablegroup %s"; + final static String CREATE_TABLE = "create table %s (a int, b int, unique key(b)) %s tablegroup=%s"; + + final static String PARTITION_BY_KEY_KEY = + "partition by key (a) subpartition by key(b) (partition p1 subpartitions 1)"; + final static String PARTITION_BY_KEY = "partition by key (a) partitions 1"; + final static String INSERT_DATA = + "insert into %s values(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10)"; + final static String INSERT_IGNORE_DATA = "insert ignore into %s select * from %s where a=%s"; + final static String UPDATE_DATA = "update %s set b=b+100 where a=%s"; + + final static String SOURCE_WRITE_ONLY_HINT = + "/*+TDDL:CMD_EXTRA(PHYSICAL_BACKFILL_ENABLE=false, TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG='SOURCE_WRITE_ONLY')*/"; + final static String SOURCE_DELETE_ONLY_HINT = + "/*+TDDL:CMD_EXTRA(PHYSICAL_BACKFILL_ENABLE=false, TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG='SOURCE_DELETE_ONLY')*/"; + + @Before + public void setUp() { + String sql = "use polardbx"; + JdbcUtil.executeUpdate(tddlConnection, sql); + JdbcUtil.executeUpdate(tddlConnection, String.format(DROP_DB, TABLE_SCHEMA)); + JdbcUtil.executeUpdate(tddlConnection, String.format(CREATE_DB, TABLE_SCHEMA)); + } + + private TestStrategy testStrategy; + + public AlterTableGroupRepartitionTest(TestStrategy testStrategy) { + this.testStrategy = testStrategy; + } + + @Test + public void testAlterTableGroupMovePartition() { + String sql = "use " + TABLE_SCHEMA; + JdbcUtil.executeUpdate(tddlConnection, sql); + String tgName = "move_tg1"; + + String tbName = "mpt2"; + boolean isSubPart = testStrategy.name().contains("SUBPARTITION"); + boolean isTbLvl = testStrategy.name().startsWith("TB_"); + boolean isMove = testStrategy.name().contains("_MOVE_"); + boolean isWriteOnlyHint = testStrategy.name().contains("WRITEONLY"); + + JdbcUtil.executeUpdate(tddlConnection, String.format(CREATE_TABLE_GROUP, tgName)); + JdbcUtil.executeUpdate(tddlConnection, + String.format(CREATE_TABLE, "mpt1", isSubPart ? PARTITION_BY_KEY_KEY : PARTITION_BY_KEY, tgName)); + JdbcUtil.executeUpdate(tddlConnection, + String.format(CREATE_TABLE, "mpt2", isSubPart ? PARTITION_BY_KEY_KEY : PARTITION_BY_KEY, tgName)); + JdbcUtil.executeUpdate(tddlConnection, + String.format(CREATE_TABLE, "mpt3", isSubPart ? PARTITION_BY_KEY_KEY : PARTITION_BY_KEY, tgName)); + JdbcUtil.executeUpdate(tddlConnection, String.format(INSERT_DATA, "mpt1")); + + String tarDn = ""; + String partName = isSubPart ? "p1sp1" : "p1"; + if (isMove) { + Map partDnMap = + getPartDnMap("mpt1", isSubPart, tddlConnection); + List storageInstIds = getStorageInstIds(TABLE_SCHEMA); + if (storageInstIds.size() <= 1) { + return; + } + String srcDn = partDnMap.get(partName); + for (int i = 0; i < storageInstIds.size(); i++) { + if (!storageInstIds.get(i).equalsIgnoreCase(srcDn)) { + tarDn = storageInstIds.get(i); + break; + } + } + } + + String ignoreErr = "Please use SHOW DDL"; + Set ignoreErrs = new HashSet<>(); + ignoreErrs.add(ignoreErr); + StringBuilder sb = new StringBuilder(); + if (isWriteOnlyHint) { + sb.append(SOURCE_WRITE_ONLY_HINT); + } else { + sb.append(SOURCE_DELETE_ONLY_HINT); + } + sb.append(" "); + if (isTbLvl) { + sb.append("alter table "); + sb.append(tbName); + } else { + sb.append("alter tablegroup "); + sb.append(tgName); + } + sb.append(" "); + if (isMove) { + sb.append("move "); + if (isSubPart) { + sb.append("subpartitions p1sp1 to '"); + } else { + sb.append("partitions p1 to '"); + } + sb.append(tarDn); + sb.append("'"); + } else { + sb.append("split "); + if (isSubPart) { + sb.append("subpartition p1sp1"); + } else { + sb.append("partition p1"); + } + } + + JdbcUtil.executeUpdateSuccessIgnoreErr(tddlConnection, sb.toString(), ignoreErrs); + JdbcUtil.executeUpdate(tddlConnection, String.format(INSERT_IGNORE_DATA, "mpt2", "mpt1", "1")); + JdbcUtil.executeUpdate(tddlConnection, String.format(UPDATE_DATA, "mpt2", "1")); + } + + private Map getPartDnMap(String tableName, boolean subPart, Connection conn) { + ResultSet resultSet = JdbcUtil.executeQuery("show topology from " + tableName, conn); + Map partDnMap = new HashMap<>(); + try { + while (resultSet.next()) { + partDnMap.put( + subPart ? resultSet.getString("SUBPARTITION_NAME") : resultSet.getString("PARTITION_NAME"), + resultSet.getString("DN_ID")); + } + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + return partDnMap; + } + + @After + public void tearDown() { + String sql = "use polardbx"; + JdbcUtil.executeUpdate(tddlConnection, sql); + JdbcUtil.executeUpdate(tddlConnection, String.format(DROP_DB, TABLE_SCHEMA)); + } + + @Parameterized.Parameters(name = "{index}:partitionRuleInfo={0}") + public static List prepareData() { + List status = new ArrayList<>(); + status.add(new TestStrategy[] {TestStrategy.TG_MOVE_WRITEONLY_PARTITION}); + status.add(new TestStrategy[] {TestStrategy.TG_MOVE_WRITEONLY_SUBPARTITION}); + status.add(new TestStrategy[] {TestStrategy.TG_MOVE_DELETEONLY_PARTITION}); + status.add(new TestStrategy[] {TestStrategy.TG_MOVE_DELETEONLY_SUBPARTITION}); + status.add(new TestStrategy[] {TestStrategy.TG_SPLIT_WRITEONLY_PARTITION}); + status.add(new TestStrategy[] {TestStrategy.TG_SPLIT_WRITEONLY_SUBPARTITION}); + status.add(new TestStrategy[] {TestStrategy.TG_SPLIT_DELETEONLY_PARTITION}); + status.add(new TestStrategy[] {TestStrategy.TG_SPLIT_DELETEONLY_SUBPARTITION}); + status.add(new TestStrategy[] {TestStrategy.TB_MOVE_WRITEONLY_PARTITION}); + status.add(new TestStrategy[] {TestStrategy.TB_MOVE_WRITEONLY_SUBPARTITION}); + status.add(new TestStrategy[] {TestStrategy.TB_MOVE_DELETEONLY_PARTITION}); + status.add(new TestStrategy[] {TestStrategy.TB_MOVE_DELETEONLY_SUBPARTITION}); + status.add(new TestStrategy[] {TestStrategy.TB_SPLIT_WRITEONLY_PARTITION}); + status.add(new TestStrategy[] {TestStrategy.TB_SPLIT_WRITEONLY_SUBPARTITION}); + status.add(new TestStrategy[] {TestStrategy.TB_SPLIT_DELETEONLY_PARTITION}); + status.add(new TestStrategy[] {TestStrategy.TB_SPLIT_DELETEONLY_SUBPARTITION}); + return status; + } + + enum TestStrategy { + TG_MOVE_WRITEONLY_PARTITION, + TG_MOVE_WRITEONLY_SUBPARTITION, + TG_MOVE_DELETEONLY_PARTITION, + TG_MOVE_DELETEONLY_SUBPARTITION, + TG_SPLIT_WRITEONLY_PARTITION, + TG_SPLIT_WRITEONLY_SUBPARTITION, + TG_SPLIT_DELETEONLY_PARTITION, + TG_SPLIT_DELETEONLY_SUBPARTITION, + TB_MOVE_WRITEONLY_PARTITION, + TB_MOVE_WRITEONLY_SUBPARTITION, + TB_MOVE_DELETEONLY_PARTITION, + TB_MOVE_DELETEONLY_SUBPARTITION, + TB_SPLIT_WRITEONLY_PARTITION, + TB_SPLIT_WRITEONLY_SUBPARTITION, + TB_SPLIT_DELETEONLY_PARTITION, + TB_SPLIT_DELETEONLY_SUBPARTITION + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/tablegroup/AlterTableGroupWithForeignKeyTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/tablegroup/AlterTableGroupWithForeignKeyTest.java index 832bca728..0730c4466 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/tablegroup/AlterTableGroupWithForeignKeyTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/tablegroup/AlterTableGroupWithForeignKeyTest.java @@ -28,7 +28,6 @@ public class AlterTableGroupWithForeignKeyTest extends MoveDatabaseBaseTest { static private final String dataBaseName = "TableGroupMovePartitionFkTest"; private String targetDnInstId = ""; - //delete hint SHARE_STORAGE_MODE=true,SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true because there are always 2 dn in k8s public String scaleOutHint = ""; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/tablereorg/AlterTableDropPartition2Test.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/tablereorg/AlterTableDropPartition2Test.java new file mode 100644 index 000000000..32e718740 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/auto/tablereorg/AlterTableDropPartition2Test.java @@ -0,0 +1,137 @@ +package com.alibaba.polardbx.qatest.ddl.auto.tablereorg; + +import com.alibaba.polardbx.common.utils.TStringUtil; +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.alibaba.polardbx.qatest.util.RandomUtils; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static com.alibaba.polardbx.qatest.util.JdbcUtil.showFullCreateTable; +import static org.hamcrest.Matchers.is; + +/** + * Created by luoyanxin. + * + * @author luoyanxin + */ +public class AlterTableDropPartition2Test extends DDLBaseNewDBTestCase { + + private static final String tableSchema = "_dropPartitionDb_"; + private static String CREATE_TABLE_PATTERN1 = "create table if not exists %s (\n" + + "a bigint unsigned not null,\n" + + "b bigint unsigned not null,\n" + + "c datetime NOT NULL,\n" + + "d varchar(16) NOT NULL,\n" + + "e varchar(16) NOT NULL\n" + + ")\n" + + "partition by range (to_days(c))\n" + + "subpartition by list (a)\n" + + "(\n" + + "partition p1 values less than ( to_days('2020-01-01') ) (\n" + + "subpartition p1sp1 values in ( 1000, 2000),\n" + + "subpartition p1sp2 values in ( default )\n" + + "),\n" + + "partition p2 values less than ( maxvalue ) (\n" + + "subpartition p2sp1 values in ( 1000, 2000),\n" + + "subpartition p2sp2 values in ( 3000, 4000),\n" + + "subpartition p2sp3 values in ( default )\n" + + ")\n" + + ");"; + private static String CREATE_TABLE_PATTERN2 = "create table if not exists %s (\n" + + "a bigint unsigned not null,\n" + + "b bigint unsigned not null,\n" + + "c datetime NOT NULL,\n" + + "d varchar(16) NOT NULL,\n" + + "e varchar(16) NOT NULL\n" + + ")\n" + + "partition by list (to_days(c))\n" + + "subpartition by range (a)\n" + + "(\n" + + "subpartition sp1 values less than ( 1000),\n" + + "subpartition sp2 values less than ( maxvalue )\n" + + ")\n" + + "(\n" + + "partition p1 values in ( to_days('2020-01-01') ),\n" + + "partition p2 values in ( default )\n" + + ");"; + + @Test + public void ntpSubpartitionTest() { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use " + tableSchema); + String dropTable = "drop table if exists %s"; + String tb1 = "tb" + RandomUtils.getStringBetween(5, 8); + String sql = String.format(dropTable, tb1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + sql = String.format(CREATE_TABLE_PATTERN1, tb1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "/*+TDDL:CMD_EXTRA(TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG='WRITE_REORG')*/alter table " + tb1 + + " drop subpartition p1sp1"; + String ignoreErr = + "The DDL job has been paused or cancelled. Please use SHOW DDL"; + Set ignoreErrs = new HashSet<>(); + ignoreErrs.add(ignoreErr); + JdbcUtil.executeUpdateSuccessIgnoreErr(tddlConnection, sql, + ignoreErrs); + + sql = "trace select * from " + tb1; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + List> trace = getTrace(tddlConnection); + Assert.assertThat(trace.toString(), trace.size(), is(4)); + + sql = "insert into " + tb1 + " values (1000,1000,'2019-01-01','a','b')"; + JdbcUtil.executeFailed(tddlConnection, sql, "Table has no partition for the values"); + } + + @Test + public void listTableTest() { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use " + tableSchema); + String dropTable = "drop table if exists %s"; + String tb1 = "tb" + RandomUtils.getStringBetween(5, 8); + String sql = String.format(dropTable, tb1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + sql = String.format(CREATE_TABLE_PATTERN2, tb1); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "/*+TDDL:CMD_EXTRA(TABLEGROUP_REORG_FINAL_TABLE_STATUS_DEBUG='WRITE_REORG')*/alter table " + tb1 + + " drop subpartition sp1"; + String ignoreErr = + "The DDL job has been paused or cancelled. Please use SHOW DDL"; + Set ignoreErrs = new HashSet<>(); + ignoreErrs.add(ignoreErr); + JdbcUtil.executeUpdateSuccessIgnoreErr(tddlConnection, sql, + ignoreErrs); + + sql = "trace select * from " + tb1; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + List> trace = getTrace(tddlConnection); + Assert.assertThat(trace.toString(), trace.size(), is(2)); + + sql = "insert into " + tb1 + " values (1,2,'2019-01-01','a','b')"; + JdbcUtil.executeFailed(tddlConnection, sql, "Table has no partition for the values"); + } + + @Before + public void setUp() { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use polardbx"); + String sql1 = String.format("drop database if exists %s", tableSchema); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = String.format("create database %s mode=auto", tableSchema); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + } + + @After + public void cleanUp() { + JdbcUtil.executeUpdateSuccess(tddlConnection, "use polardbx"); + String sql1 = String.format("drop database if exists %s", tableSchema); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/PartitionBalanceBaseTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/PartitionBalanceBaseTest.java index b4dbd5fbd..26f420b2e 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/PartitionBalanceBaseTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/PartitionBalanceBaseTest.java @@ -1,5 +1,7 @@ package com.alibaba.polardbx.qatest.ddl.balancer; +import com.alibaba.polardbx.common.utils.Pair; +import com.alibaba.polardbx.qatest.ddl.auto.dal.CheckTableTest; import com.alibaba.polardbx.qatest.ddl.auto.locality.LocalityTestCaseUtils.LocalityTestCaseBean; import com.alibaba.polardbx.qatest.ddl.balancer.datagenerator.DataLoader; import com.alibaba.polardbx.qatest.ddl.balancer.datagenerator.ManualHotSpotDataGenerator; @@ -23,6 +25,7 @@ import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; +import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; @@ -39,10 +42,10 @@ @NotThreadSafe public class PartitionBalanceBaseTest extends BalancerTestBase { - private int tableNum = 4; + private int tableNum = 2; private List tableNames = new ArrayList<>(); - private int tableRows = 100000; + private int tableRows = 500000; public static int maxWaitTime = 5000 * 200; @@ -170,8 +173,18 @@ public void test1_PartitionBalance() throws SQLException { String balanceDbSql = "rebalance database policy='partition_balance'"; try (ResultSet rs = JdbcUtil.executeQuery(balanceDbSql, tddlConnection);) { LOG.info("execute " + balanceDbSql); - Assert.assertEquals(Arrays.asList("job_id", "schema", "name", "action", "backfill_rows"), - JdbcUtil.getColumnNameListToLowerCase(rs)); + ResultSetMetaData rsmd = rs.getMetaData(); + if (rsmd.getColumnCount() == 5) { + //logical backfill + Assert.assertEquals(Arrays.asList("job_id", "schema", "name", "action", "backfill_rows"), + JdbcUtil.getColumnNameListToLowerCase(rs)); + } else { + //physical backfill + Assert.assertEquals( + Arrays.asList("job_id", "schema", "name", "action", "backfill_rows", "backfill_data_size", + "backfill_estimated_time"), + JdbcUtil.getColumnNameListToLowerCase(rs)); + } // Boolean emptyResult = JdbcUtil.getAllResult(rs).stream() // .noneMatch(o -> o.get(2).toString().equalsIgnoreCase("MovePartition")); // Assert.assertTrue("result should be empty", emptyResult); @@ -215,8 +228,16 @@ public void test1_PartitionBalance() throws SQLException { "rebalance database policy='auto_split_for_partition_balance' solve_level = 'hot_split'"; try (ResultSet rs = JdbcUtil.executeQuery(rebalanceAutoSplitDbSql, tddlConnection);) { LOG.info("execute " + rebalanceAutoSplitDbSql); - Assert.assertEquals(Arrays.asList("job_id", "schema", "name", "action", "backfill_rows"), - JdbcUtil.getColumnNameListToLowerCase(rs)); + ResultSetMetaData rsmd = rs.getMetaData(); + if (rsmd.getColumnCount() == 5) { + Assert.assertEquals(Arrays.asList("job_id", "schema", "name", "action", "backfill_rows"), + JdbcUtil.getColumnNameListToLowerCase(rs)); + } else { + Assert.assertEquals( + Arrays.asList("job_id", "schema", "name", "action", "backfill_rows", "backfill_data_size", + "backfill_estimated_time"), + JdbcUtil.getColumnNameListToLowerCase(rs)); + } Boolean emptyResult = JdbcUtil.getAllResult(rs).stream() .noneMatch(o -> o.get(2).toString().equalsIgnoreCase("SplitPartition")); Assert.assertFalse("result should not be empty", emptyResult); @@ -226,8 +247,16 @@ public void test1_PartitionBalance() throws SQLException { try (ResultSet rs = JdbcUtil.executeQuery(balanceDbSql, tddlConnection);) { LOG.info("execute " + balanceDbSql); - Assert.assertEquals(Arrays.asList("job_id", "schema", "name", "action", "backfill_rows"), - JdbcUtil.getColumnNameListToLowerCase(rs)); + ResultSetMetaData rsmd = rs.getMetaData(); + if (rsmd.getColumnCount() == 5) { + Assert.assertEquals(Arrays.asList("job_id", "schema", "name", "action", "backfill_rows"), + JdbcUtil.getColumnNameListToLowerCase(rs)); + } else { + Assert.assertEquals( + Arrays.asList("job_id", "schema", "name", "action", "backfill_rows", "backfill_data_size", + "backfill_estimated_time"), + JdbcUtil.getColumnNameListToLowerCase(rs)); + } // Boolean emptyResult = JdbcUtil.getAllResult(rs).stream().noneMatch(o->o.get(2).toString().equalsIgnoreCase("MovePartition")); // Assert.assertFalse("result should not be empty", emptyResult); } @@ -260,12 +289,27 @@ public void test2_ShowHotKey() throws SQLException { // ingest data String showHotKey = "show hotkey from %s partition(%s)"; - String showHotKeySql = String.format(showHotKey, tableNames.get(1), "p17"); + String tableName = tableNames.get(1); + String showHotKeySql = String.format(showHotKey, tableName, "p17"); + Pair phyDbNameTableName = + CheckTableTest.getFullObjectName(tddlConnection, tableName, tableName, 16); + String analyzeSql = String.format("analyze table %s", phyDbNameTableName.getValue()); +// String groupHint = String.format("/*+TDDL:node(%d)*/", phyDbNameTableName.getKey()); +// String sql = groupHint + analyzeSql; + Connection connection = getMysqlConnection(); + JdbcUtil.executeUpdateSuccess(connection, "use balancertestbase_p00000"); + for (int i = 0; i < 16; i++) { + JdbcUtil.executeUpdateSuccess(connection, analyzeSql); + } + String version = + JdbcUtil.getAllResult(JdbcUtil.executeQuery("select @@version", connection)).get(0).get(0).toString(); + Boolean is80Version = version.startsWith("8.0"); +// JdbcUtil.executeUpdateSuccess(tddlConnection, analyzeSql); try (ResultSet rs = JdbcUtil.executeQuery(showHotKeySql, tddlConnection);) { Assert.assertEquals(Arrays.asList("schema_name", "table_name", "part_name", "hotvalue", "estimate_rows", "estimate_percentage"), JdbcUtil.getColumnNameListToLowerCase(rs)); - Assert.assertFalse("result should not be empty", JdbcUtil.getAllResult(rs).isEmpty()); + Assert.assertFalse("result should not be empty", JdbcUtil.getAllResult(rs).isEmpty() && !is80Version); } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/SplitPartitionBaseTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/SplitPartitionBaseTest.java index cc2998e25..45b5d3480 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/SplitPartitionBaseTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/SplitPartitionBaseTest.java @@ -14,6 +14,7 @@ import org.junit.runners.MethodSorters; import java.sql.ResultSet; +import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.Arrays; import java.util.List; @@ -99,8 +100,16 @@ public void test2_ExplainRebalance() throws SQLException { String explainSplitSql = genSplitPartitionSql(tableName1, splitPartitionSize, 10); explainSplitSql += " explain=true"; try (ResultSet rs = JdbcUtil.executeQuery(explainSplitSql, tddlConnection)) { - Assert.assertEquals(Arrays.asList("job_id", "schema", "name", "action", "backfill_rows"), - JdbcUtil.getColumnNameListToLowerCase(rs)); + ResultSetMetaData rsmd = rs.getMetaData(); + if (rsmd.getColumnCount() == 5) { + Assert.assertEquals(Arrays.asList("job_id", "schema", "name", "action", "backfill_rows"), + JdbcUtil.getColumnNameListToLowerCase(rs)); + } else { + Assert.assertEquals( + Arrays.asList("job_id", "schema", "name", "action", "backfill_rows", "backfill_data_size", + "backfill_estimated_time"), + JdbcUtil.getColumnNameListToLowerCase(rs)); + } Assert.assertFalse("result should not be empty", JdbcUtil.getAllResult(rs).isEmpty()); } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/PauseRebalanceDrdsTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/PauseRebalanceDrdsTest.java index bbaf8fdc4..a09227c17 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/PauseRebalanceDrdsTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/PauseRebalanceDrdsTest.java @@ -22,7 +22,7 @@ public class PauseRebalanceDrdsTest extends DDLBaseNewDBTestCase { private static final String ENABLE_CHANGESET_HINT = "CN_ENABLE_CHANGESET=%s"; // 本地测试环境需要加该hint 或者 set global private static final String LOCAL_HINT = - "SHARE_STORAGE_MODE=true,SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true"; + "SHARE_STORAGE_MODE=true,PHYSICAL_BACKFILL_ENABLE=false,SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true"; private static final String DROP_DB_HINT = "ALLOW_DROP_DATABASE_IN_SCALEOUT_PHASE=true"; private static final int TABLE_COUNT = 4; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/SkipRebalanceSubjobDrdsTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/SkipRebalanceSubjobDrdsTest.java index fdc2b0ac5..94fdadb5f 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/SkipRebalanceSubjobDrdsTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/SkipRebalanceSubjobDrdsTest.java @@ -20,7 +20,7 @@ public class SkipRebalanceSubjobDrdsTest extends DDLBaseNewDBTestCase { private static final String ENABLE_CHANGESET_HINT = "CN_ENABLE_CHANGESET=%s"; // 本地测试环境需要加该hint 或者 set global private static final String LOCAL_HINT = - "SHARE_STORAGE_MODE=true,SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true"; + "SHARE_STORAGE_MODE=true,PHYSICAL_BACKFILL_ENABLE=false,SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true"; private static final String ENABLE_OPERATE_SUBJOB_HINT = "ENABLE_OPERATE_SUBJOB=true"; private static final String ASYNC_PAUSE_HINT = "ASYNC_PAUSE=false"; private static final String CHECK_RESPONSE_IN_MEM_HINT = "CHECK_RESPONSE_IN_MEM=false"; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/TerminateRebalanceAutoTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/TerminateRebalanceAutoTest.java index 39958cf0f..c617a83b6 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/TerminateRebalanceAutoTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/TerminateRebalanceAutoTest.java @@ -2,6 +2,7 @@ import com.alibaba.polardbx.common.utils.Assert; import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DataManipulateUtil; import com.alibaba.polardbx.qatest.util.JdbcUtil; import org.junit.After; import org.junit.Before; @@ -16,6 +17,8 @@ import java.util.List; import java.util.Set; +import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DataManipulateUtil.prepareData; + public class TerminateRebalanceAutoTest extends DDLBaseNewDBTestCase { private static final String SLOW_HINT = "GSI_DEBUG=\"slow\""; private static final String ASYNC_DDL_HINT = "ENABLE_ASYNC_DDL=true, PURE_ASYNC_DDL_MODE=true"; @@ -158,6 +161,147 @@ public void testTerminateRebalanceSchedule() throws SQLException, InterruptedExc Assert.assertTrue(getDDLPlanStats(tddlConnection, jobId).equalsIgnoreCase("SUCCESS")); } + @Test + public void testResumeRebalanceSchedule() throws SQLException, InterruptedException { + // create table + for (int i = 0; i < TABLE_COUNT; ++i) { + String tbName = TABLE_PREFIX + i; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(DROP_TABLE_SQL, tbName)); + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(CREATE_TABLE_SQL, tbName)); + } + + String command = prepareDrainNodeCommand(tddlConnection); + JdbcUtil.executeUpdateSuccess(tddlConnection, command + " async=false"); + + JdbcUtil.executeUpdateSuccess(tddlConnection, "schedule rebalance database"); + + // check + Thread.sleep(10500); + Long jobId = getDDLJobId(tddlConnection); + // Assert.assertTrue(checkRunningDDL(tddlConnection)); + if (!checkRunningDDL(tddlConnection)) { + return; + } + Assert.assertTrue(jobId != -1L); + + // RESUME REBALANCE + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format("RESUME REBALANCE %s", jobId)); + + // check + Assert.assertTrue(waitDDLJobFinish(tddlConnection)); + + Assert.assertTrue(getDDLPlanStats(tddlConnection, jobId).equalsIgnoreCase("EXECUTING")); + + // check + Thread.sleep(10500); + jobId = getDDLJobId(tddlConnection); + // Assert.assertTrue(checkRunningDDL(tddlConnection)); + if (!checkRunningDDL(tddlConnection)) { + return; + } + // rollback + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format("TERMINATE REBALANCE %s", jobId)); + + // check + Assert.assertTrue(waitDDLJobFinish(tddlConnection)); + + Assert.assertTrue(getDDLPlanStats(tddlConnection, jobId).equalsIgnoreCase("SUCCESS")); + } + + public void testResumeRebalanceWithDataSchedule() throws Exception { + // create table + for (int i = 0; i < TABLE_COUNT; ++i) { + String tbName = TABLE_PREFIX + i; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(DROP_TABLE_SQL, tbName)); + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(CREATE_TABLE_SQL, tbName)); + } + + String originalTableName = "multiple_pk_table3"; + // prepare data + String createTableStmt = "create table if not exists " + + " %s(d int, a int NOT NULL AUTO_INCREMENT,b char(16), c varchar(32), PRIMARY KEY(c, a, b)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + int partNum = 4; + int eachPartRows = 40960; + String rebalanceJob = "schedule rebalance table %s shuffle_data_dist=1"; + + prepareData(tddlConnection, DATABASE_NAME, originalTableName, eachPartRows, createTableStmt, + partNum, DataManipulateUtil.TABLE_TYPE.PARTITION_TABLE); + + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(rebalanceJob, originalTableName)); + + // check + Thread.sleep(10500); + Long jobId = getDDLJobId(tddlConnection); + // Assert.assertTrue(checkRunningDDL(tddlConnection)); + if (!checkRunningDDL(tddlConnection)) { + return; + } + Assert.assertTrue(jobId != -1L); + + // RESUME REBALANCE + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format("RESUME REBALANCE %s", jobId)); + + // check + Assert.assertTrue(waitDDLJobFinish(tddlConnection)); + + Assert.assertTrue(getDDLPlanStats(tddlConnection, jobId).equalsIgnoreCase("EXECUTING")); + + // check + Thread.sleep(10500); + jobId = getDDLJobId(tddlConnection); + // Assert.assertTrue(checkRunningDDL(tddlConnection)); + if (!checkRunningDDL(tddlConnection)) { + return; + } + // rollback + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format("TERMINATE REBALANCE %s", jobId)); + + // check + Assert.assertTrue(waitDDLJobFinish(tddlConnection)); + + Assert.assertTrue(getDDLPlanStats(tddlConnection, jobId).equalsIgnoreCase("SUCCESS")); + } + + @Test + public void testResumeRebalance() throws SQLException, InterruptedException { + // create table + for (int i = 0; i < TABLE_COUNT; ++i) { + String tbName = TABLE_PREFIX + i; + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(DROP_TABLE_SQL, tbName)); + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format(CREATE_TABLE_SQL, tbName)); + } + + String command = prepareDrainNodeCommand(tddlConnection); + JdbcUtil.executeUpdateSuccess(tddlConnection, command + " async=false"); + + JdbcUtil.executeUpdateSuccess(tddlConnection, "rebalance database"); + + Long jobId = getDDLJobId(tddlConnection); + // Assert.assertTrue(checkRunningDDL(tddlConnection)); + if (!checkRunningDDL(tddlConnection)) { + return; + } + Assert.assertTrue(jobId != -1L); + + // RESUME REBALANCE + JdbcUtil.executeUpdateSuccess(tddlConnection, String.format("RESUME REBALANCE %s", jobId)); + + // check + Assert.assertTrue(waitDDLJobFinish(tddlConnection)); + } + + @Test + public void testResumeRebalanceFail() throws SQLException, InterruptedException { + + String command = "resume rebalance all"; + String errorMsg = "Operation on multi ddl jobs is not allowed"; + JdbcUtil.executeUpdateFailed(tddlConnection, command, errorMsg); + + command = "resume rebalance 123,234"; + JdbcUtil.executeUpdateFailed(tddlConnection, command, errorMsg); + } + private static boolean checkRunningDDL(Connection connection) throws SQLException { String sql = "use " + DATABASE_NAME; JdbcUtil.executeUpdate(connection, sql); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/TerminateRebalanceDrdsTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/TerminateRebalanceDrdsTest.java index a5e48673b..b39b418bc 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/TerminateRebalanceDrdsTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/control/TerminateRebalanceDrdsTest.java @@ -20,7 +20,7 @@ public class TerminateRebalanceDrdsTest extends DDLBaseNewDBTestCase { private static final String ENABLE_CHANGESET_HINT = "CN_ENABLE_CHANGESET=%s"; // 本地测试环境需要加该hint 或者 set global private static final String LOCAL_HINT = - "SHARE_STORAGE_MODE=true,SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true"; + "SHARE_STORAGE_MODE=true,PHYSICAL_BACKFILL_ENABLE=false,SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true"; private static final String DROP_DB_HINT = "ALLOW_DROP_DATABASE_IN_SCALEOUT_PHASE=true"; private static final int TABLE_COUNT = 4; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/datagenerator/DataLoader.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/datagenerator/DataLoader.java index 426783b18..96a72e00e 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/datagenerator/DataLoader.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/datagenerator/DataLoader.java @@ -13,6 +13,7 @@ import java.sql.Types; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.StringJoiner; public class DataLoader { @@ -27,6 +28,7 @@ public class DataLoader { private List keys = new ArrayList<>(); private List defaults = new ArrayList<>(); private List extras = new ArrayList<>(); + public List> rows = new ArrayList<>(); private boolean autoPrimaryKey = true; @@ -46,6 +48,15 @@ public static DataLoader create(Connection connection, String tableName, DataGen return dataLoader; } + public static DataLoader create(Connection connection, String tableName, List> rows) { + DataLoader dataLoader = new DataLoader(); + dataLoader.connection = connection; + dataLoader.tableName = tableName; + dataLoader.rows = rows; + dataLoader.descTable(); + return dataLoader; + } + public void batchInsert(long count, Boolean fastMode) { String sql = batchInsertSql(fieldNames.size(), "?", fastMode); int batchSize = fastMode ? 4096 : 512; @@ -60,7 +71,7 @@ public void batchInsert(long count, Boolean fastMode) { preparedStatement.setNull(i, Types.INTEGER); } else if (fieldType.startsWith("int") || fieldType.startsWith("bigint")) { preparedStatement.setInt(i, (Integer) columnValue); - } else if (fieldType.startsWith("varchar")) { + } else if (fieldType.startsWith("varchar") || fieldType.startsWith("binary")) { preparedStatement.setString(i, (String) columnValue); } else { preparedStatement.setObject(i, columnValue); @@ -77,6 +88,37 @@ public void batchInsert(long count, Boolean fastMode) { preparedStatement.executeBatch(); // connection.commit(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + public void batchInsertFromRow(long count, Boolean fastMode) { + String sql = batchInsertSql(fieldNames.size(), "?", fastMode); + int batchSize = fastMode ? 4096 : 512; + try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) { + + for (long c = 0; c < count; c++) { +// List rowData = new ArrayList<>(); + int rowNum = (int) c; + for (int i = 1; i <= fieldTypes.size(); i++) { + String fieldType = fieldTypes.get(i - 1); + String columnName = fieldNames.get(i - 1); + Object columnValue = rows.get(rowNum).get(columnName); + preparedStatement.setObject(i, columnValue); +// rowData.add(columnValue); + } +// allData.add(rowData); + + preparedStatement.addBatch(); + if (c % batchSize == 0) { + preparedStatement.executeBatch(); + } + } + preparedStatement.executeBatch(); +// connection.commit(); + } catch (SQLException e) { e.printStackTrace(); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/datagenerator/UniformDistributionDataGenerator.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/datagenerator/UniformDistributionDataGenerator.java index 5d639004b..75b097067 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/datagenerator/UniformDistributionDataGenerator.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/balancer/datagenerator/UniformDistributionDataGenerator.java @@ -48,8 +48,17 @@ public Object generateData(String fieldType) throws SQLException { TimeStampGenerator.millisToZonedDateTime(timeStampGenerator.generateTs(1000 * 6000), ZoneId.systemDefault()).toLocalDateTime() ); - - } else { + } else if (StringUtils.containsIgnoreCase(fieldType, "decimal")) { + data = randomInt.uniformDistribution(100_0000, 0); + } else if (StringUtils.containsIgnoreCase(fieldType, "time")) { + data = Timestamp.valueOf( + TimeStampGenerator.millisToZonedDateTime(timeStampGenerator.generateTs(1000 * 6000), + ZoneId.systemDefault()).toLocalDateTime()); + } else if(StringUtils.containsIgnoreCase(fieldType, "year")) { + data = randomInt.uniformDistribution(50, 50); + } else if(StringUtils.containsIgnoreCase(fieldType, "binary")) { + data = String.valueOf(randomInt.uniformDistribution(100_0000, 0)); + } else{ throw new RuntimeException("not supported"); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcAlterTableSetTableGroupTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcAlterTableSetTableGroupTest.java index 1e083c4fb..b4e3d89a9 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcAlterTableSetTableGroupTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcAlterTableSetTableGroupTest.java @@ -144,6 +144,14 @@ private void testAlterTableSetTableGroup(Statement stmt, String schemaName) thro + " PARTITION p33 VALUES LESS THAN(200)\n" + ")"); + stmt.executeUpdate( + "CREATE TABLE tb9(a int) PARTITION BY RANGE(a)\n" + + " (\n" + + " PARTITION p11 VALUES LESS THAN(20),\n" + + " PARTITION p22 VALUES LESS THAN(100),\n" + + " PARTITION p33 VALUES LESS THAN(200)\n" + + ")"); + // 创建表组 executeAndCheck(schemaName, stmt, "create tablegroup mytg1", "mytg1", false, null, null); @@ -342,6 +350,9 @@ private void testAlterTableSetTableGroup(Statement stmt, String schemaName) thro item.listAfter1.get(1).getVisibility()); } ); + + executeAndCheck(schemaName, stmt, "alter table tb9 set tablegroup = ''", "tb9", false, + "ALTER_TABLE_SET_TABLEGROUP", null, true); } private void testAlterTableSetTableGroup_ForBroadcast(String schemaName) { @@ -871,7 +882,13 @@ private String getTableNameForGsi(String dbName, String tableName, String gsiNam private void executeAndCheck(String schemaName, Statement stmt, String sql, String tableName, boolean hasTopology, String sqlKind, - Consumer consumer) + Consumer consumer) throws SQLException { + executeAndCheck(schemaName, stmt, sql, tableName, hasTopology, sqlKind, consumer, false); + } + + private void executeAndCheck(String schemaName, Statement stmt, String sql, String tableName, boolean hasTopology, + String sqlKind, + Consumer consumer, boolean skipCheckSqlText) throws SQLException { int countBefore1 = getDdlRecordInfoList(schemaName, tableName).size(); int countBefore2 = getDdlRecordInfoList(schemaName, null).size(); @@ -892,7 +909,11 @@ private void executeAndCheck(String schemaName, Statement stmt, String sql, Stri } else { Assert.assertEquals(countBefore1 + 1, listAfter1.size()); Assert.assertEquals(countBefore2 + 1, listAfter2.size()); - Assert.assertEquals(sql, listAfter1.get(0).getDdlSql()); + if (!skipCheckSqlText) { + Assert.assertEquals(sql, listAfter1.get(0).getDdlSql()); + } else { + Assert.assertTrue(listAfter1.get(0).getDdlSql().toLowerCase().indexOf("implicit") != -1); + } if (StringUtils.isNotBlank(sqlKind)) { Assert.assertEquals(sqlKind, listAfter1.get(0).getSqlKind()); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcImplicitTableGroupTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcImplicitTableGroupTest.java index 260aef584..067c6e38e 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcImplicitTableGroupTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcImplicitTableGroupTest.java @@ -912,6 +912,48 @@ private void testModifyPartitionColumn(String schemaName, Statement stmt, List tgRemove1 = new HashSet<>(); + implicitTableGroupChecker.checkSql(schemaName, "t1", markSql, tgRemove1); + Assert.assertEquals(1, tgRemove1.size()); + replaySqlList.add(markSql); + + String alterTable4RemovePartition2 = "alter table t2 remove partitioning"; + stmt.execute(alterTable4RemovePartition2); + markSql = getMarkSqlForImplicitTableGroup(schemaName, "t2"); + Set tgRemove2 = new HashSet<>(); + implicitTableGroupChecker.checkSql(schemaName, "t2", markSql, tgRemove2); + Assert.assertEquals(2, tgRemove2.size()); + replaySqlList.add(markSql); + + String alterTable4RemovePartition3 = "alter table t3 remove partitioning"; + stmt.execute(alterTable4RemovePartition3); + markSql = getMarkSqlForImplicitTableGroup(schemaName, "t3"); + Set tgRemove3 = new HashSet<>(); + implicitTableGroupChecker.checkSql(schemaName, "t3", markSql, tgRemove3); + Assert.assertEquals(1, tgRemove3.size()); + replaySqlList.add(markSql); } private void executeAndCheckCreateIndexMulti(Statement stmt, String schemaName, String tableName1, diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcLocalPartitionTableDdlRecordTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcLocalPartitionTableDdlRecordTest.java index 2f3166036..6e1414558 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcLocalPartitionTableDdlRecordTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/cdc/CdcLocalPartitionTableDdlRecordTest.java @@ -81,13 +81,13 @@ private void doDDl(Statement stmt) startYear, StringUtils.leftPad(String.valueOf(Calendar.getInstance().get(Calendar.MONTH) + 1), 2, "0")); stmt.execute(sql); - Assert.assertEquals(0, getDdlRecordInfoListByToken(tokenHints).size()); + Assert.assertEquals(1, getDdlRecordInfoListByToken(tokenHints).size()); // Test Step tokenHints = buildTokenHints(); sql = tokenHints + "ALTER TABLE t_order EXPIRE LOCAL PARTITION"; stmt.execute(sql); - Assert.assertEquals(0, getDdlRecordInfoListByToken(tokenHints).size()); + Assert.assertEquals(1, getDdlRecordInfoListByToken(tokenHints).size()); // Test Step tokenHints = buildTokenHints(); @@ -110,7 +110,7 @@ private void doDDl(Statement stmt) + "PRE ALLOCATE 6\n" + "PIVOTDATE NOW()"; stmt.execute(sql); - Assert.assertEquals(0, getDdlRecordInfoListByToken(tokenHints).size()); + Assert.assertEquals(1, getDdlRecordInfoListByToken(tokenHints).size()); // Test Step tokenHints = buildTokenHints(); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/autoPartition/AutoPartitionCreateWithGSI.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/autoPartition/AutoPartitionCreateWithGSI.java index 035cbf9f8..5ba03206e 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/autoPartition/AutoPartitionCreateWithGSI.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/autoPartition/AutoPartitionCreateWithGSI.java @@ -21,6 +21,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import java.text.MessageFormat; @@ -206,6 +207,7 @@ public void testCreateIndexDoubleDrop0() { } @Test + @Ignore("忽略重复删除GSI的case,DDL引擎测试已有,删的过快情况下可能会导致偶发报错") public void testCreateIndexDoubleDrop1() { final String primaryTable = "t_idx_order"; final String indexTable = "g_i_idx_seller"; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/CreateIndexRepeatTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/CreateIndexRepeatTest.java new file mode 100644 index 000000000..1348eb97f --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/CreateIndexRepeatTest.java @@ -0,0 +1,53 @@ +package com.alibaba.polardbx.qatest.ddl.sharding.ddl; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Test; + +public class CreateIndexRepeatTest extends DDLBaseNewDBTestCase { + + @Test + public void testCreateIndex() { + String sql1 = "drop table if exists t1"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + + sql1 = "create table t1(a int, b varchar(100)) dbpartition by hash(a)"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + sql1 = "alter table t1 add global index abc123(b) dbpartition by hash(b)"; + JdbcUtil.executeSuccess(tddlConnection, sql1); + + sql1 = "alter table t1 add global index abc123(b) dbpartition by hash(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "alter table t1 add global index Abc123(b) dbpartition by hash(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "alter table t1 add index abc123(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "alter table t1 add index Abc123(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create global index abc123(b) on t1(b) dbpartition by hash(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create global index Abc123(b) on t1(b) dbpartition by hash(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create index abc123(b) on t1(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "create index Abc123(b) on t1(b)"; + JdbcUtil.executeUpdateFailed(tddlConnection, sql1, ""); + + sql1 = "drop table if exists t1"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql1); + } + + @Override + public boolean usingNewPartDb() { + return false; + } +} + diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/ForeignKeyDdlTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/ForeignKeyDdlTest.java index c6915dff0..0775d6718 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/ForeignKeyDdlTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/ForeignKeyDdlTest.java @@ -580,6 +580,10 @@ public void repartitionFkSameTableTest() throws SQLException { @Test public void CreateTableDifferentCharsetWithFkReferred() throws SQLException { + if (isMySQL80()) { + return; + } + JdbcUtil.executeUpdateSuccess(tddlConnection, "SET ENABLE_FOREIGN_KEY = true"); dropTableIfExists("charset_c"); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/OptimizeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/OptimizeTableTest.java index 30e32552f..c4bbba915 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/OptimizeTableTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/OptimizeTableTest.java @@ -169,8 +169,9 @@ public void testOneTable() { + " (id int, name varchar(20)) dbpartition by hash (id) tbpartition by hash(id) tbpartitions 2"; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); - String gsiSql = String.format("create global index %s on %s(id) dbpartition by hash (id) tbpartition by hash(id) tbpartitions 6", - tableName + "_gsi", tableName); + String gsiSql = String.format( + "create global index %s on %s(id) dbpartition by hash (id) tbpartition by hash(id) tbpartitions 6", + tableName + "_gsi", tableName); JdbcUtil.executeUpdateSuccess(tddlConnection, gsiSql); sql = "optimize table " + tableName; @@ -179,7 +180,8 @@ public void testOneTable() { while (resultSet.next()) { count++; } - Assert.assertTrue("unexpected result row count: " + count, count == 8 || count == 16|| count == 4); + Assert.assertTrue("unexpected result row count: " + count, + count == 8 || count == 16 || count == 4 || count == 2); } catch (SQLException e) { e.printStackTrace(); } @@ -213,7 +215,7 @@ public void testTwoTable() { while (resultSet.next()) { count++; } - Assert.assertTrue("unexpected result row count: " + count, count == 16 || count == 32 || count==4); + Assert.assertTrue("unexpected result row count: " + count, count == 16 || count == 32 || count == 4); } catch (SQLException e) { e.printStackTrace(); } @@ -301,7 +303,7 @@ public void testOneTableWithHint_3() { while (resultSet.next()) { count++; } - Assert.assertTrue("unexpected result row count: " + count, count == 8 || count == 16|| count == 2); + Assert.assertTrue("unexpected result row count: " + count, count == 8 || count == 16 || count == 2); } catch (SQLException e) { e.printStackTrace(); } @@ -336,7 +338,7 @@ public void testOneTableWithHint_4() { while (resultSet.next()) { count++; } - Assert.assertTrue("unexpected result row count: " + count, count == 16 || count == 32|| count == 4); + Assert.assertTrue("unexpected result row count: " + count, count == 16 || count == 32 || count == 4); } catch (SQLException e) { e.printStackTrace(); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/TruncateTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/TruncateTableTest.java index 5af2a3957..01cb7093d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/TruncateTableTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/ddl/TruncateTableTest.java @@ -24,13 +24,16 @@ import org.junit.Before; import org.junit.Test; import org.junit.runners.Parameterized; +import org.weakref.jmx.internal.guava.collect.ImmutableList; import java.sql.Connection; +import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; import static com.alibaba.polardbx.qatest.validator.DataOperator.executeOnMysqlAndTddl; import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentSameAssert; @@ -67,7 +70,7 @@ public void before() throws SQLException { public void testTruncateBroadCastTable() { String tableName = schemaPrefix + testTableName + "_1"; dropTableIfExists(tableName); - String sql = "create table " + tableName + "(id int, name varchar(20))broadcast"; + String sql = "create table " + tableName + "(id int primary key auto_increment, name varchar(20))broadcast"; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; @@ -78,9 +81,14 @@ public void testTruncateBroadCastTable() { // Assert.assertEquals(getNodeNum(tddlConnection), getExplainNum(sql)); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(0, getDataNumFromTable(tddlConnection, tableName)); - sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; + sql = "insert into " + tableName + " (id, name) values (null, \"tom\"), (null, \"simi\") "; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(2, getDataNumFromTable(tddlConnection, tableName)); + + List nums = getAllDataNumFromTable(tddlConnection, tableName, "id"); + nums = nums.stream().map(n -> n % 100).collect(Collectors.toList()); + Assert.assertTrue(ImmutableList.of(1, 2).equals(nums)); + dropTableIfExists(tableName); } @@ -91,7 +99,7 @@ public void testTruncateBroadCastTable() { public void testTruncateSingleTable() { String tableName = schemaPrefix + testTableName + "_2"; dropTableIfExists(tableName); - String sql = "create table " + tableName + " (id int, name varchar(20))"; + String sql = "create table " + tableName + " (id int primary key auto_increment by group, name varchar(20))"; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; @@ -102,10 +110,14 @@ public void testTruncateSingleTable() { JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(0, getDataNumFromTable(tddlConnection, tableName)); - sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; + sql = "insert into " + tableName + " (id, name) values (null, \"tom\"), (null, \"simi\") "; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(2, getDataNumFromTable(tddlConnection, tableName)); + List nums = getAllDataNumFromTable(tddlConnection, tableName, "id"); + nums = nums.stream().map(n -> n % 100).collect(Collectors.toList()); + Assert.assertTrue(ImmutableList.of(1, 2).equals(nums)); + dropTableIfExists(tableName); } @@ -117,7 +129,8 @@ public void testTruncateSingleTable() { public void testTruncateShardTbTable() { String tableName = schemaPrefix + testTableName + "_3"; dropTableIfExists(tableName); - String sql = "create table " + tableName + " (id int, name varchar(20)) tbpartition by hash(id) tbpartitions 2"; + String sql = "create table " + tableName + + " (id int primary key auto_increment, name varchar(20)) tbpartition by hash(id) tbpartitions 2"; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; @@ -129,10 +142,14 @@ public void testTruncateShardTbTable() { JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(0, getDataNumFromTable(tddlConnection, tableName)); - sql = "insert into " + tableName + " (id, name) values (1, \"tom\"), (2, \"simi\") "; + sql = "insert into " + tableName + " (id, name) values (null, \"tom\"), (null, \"simi\") "; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(2, getDataNumFromTable(tddlConnection, tableName)); + List nums = getAllDataNumFromTable(tddlConnection, tableName, "id"); + nums = nums.stream().map(n -> n % 100).collect(Collectors.toList()); + Assert.assertTrue(ImmutableList.of(1, 2).equals(nums)); + dropTableIfExists(tableName); } @@ -216,7 +233,7 @@ public void testTruncateShardDbTableWithGsi() throws SQLException { dropTableIfExists(indexTableName4); String sql = gsiDisableStorageCheckHint + "create table " + tableName - + " (id int primary key, " + + " (id int primary key auto_increment, " + "name varchar(20), " + "global index " + indexTableName1 + " (name) dbpartition by hash(name)," + "global unique index " + indexTableName2 + " (name) dbpartition by hash(name)," @@ -251,14 +268,19 @@ public void testTruncateShardDbTableWithGsi() throws SQLException { if (supportXA) { sql = "insert into " + tableName - + " (id, name) values (1, \"a\"), (2, \"b\") , (3, \"c\"), (4, \"d\"), (5, \"e\"), (6, \"f\"), (7, \"g\"), (8, \"h\")"; + + " (id, name) values (null, \"a\"), (null, \"b\") , (null, \"c\"), (null, \"d\"), (null, \"e\"), (null, \"f\"), (null, \"g\"), (null, \"h\")"; } else { sql = gsiDisableStorageCheckHint + "insert into " + tableName - + " (id, name) values (1, \"a\"), (2, \"b\") , (3, \"c\"), (4, \"d\"), (5, \"e\"), (6, \"f\"), (7, \"g\"), (8, \"h\")"; + + " (id, name) values (null, \"a\"), (null, \"b\") , (null, \"c\"), (null, \"d\"), (null, \"e\"), (null, \"f\"), (null, \"g\"), (null, \"h\")"; } JdbcUtil.executeUpdateSuccess(tddlConnection, sql); Assert.assertEquals(8, getDataNumFromTable(tddlConnection, tableName)); + + List nums = getAllDataNumFromTable(tddlConnection, tableName, "id"); + nums = nums.stream().map(n -> n % 100).collect(Collectors.toList()); + Assert.assertTrue(ImmutableList.of(1, 2, 3, 4, 5, 6, 7, 8).equals(nums)); + checkGsi(tddlConnection, indexTableName1); checkGsi(tddlConnection, indexTableName2); checkGsi(tddlConnection, indexTableName3); @@ -652,4 +674,92 @@ public void testTableWithGeneratedColumn() { JdbcUtil.executeUpdateSuccess(mysqlConnection, insert); selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); } + + @Test + public void testTableWithRecycleBin() { + if (crossSchema) { + return; + } + + String tableName = schemaPrefix + testTableName + "_13"; + String createTable = "create table " + tableName + + " (a int," + + " b int" + + ") dbpartition by hash(a)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, createTable); + + String insert = String.format("insert into %s(a,b) values (1,1)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, insert); + + assertSequenceStartValue(tableName); + + String truncate = String.format("/*+TDDL:cmd_extra(ENABLE_RECYCLEBIN=true)*/truncate table %s", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, truncate); + + insert = String.format("insert into %s(a,b) values (1,1)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, insert); + + assertSequenceStartValue(tableName); + + truncate = String.format("/*+TDDL:cmd_extra(ENABLE_RECYCLEBIN=true)*/truncate table %s", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, truncate); + + insert = String.format("insert into %s(a,b) values (1,1)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, insert); + + assertSequenceStartValue(tableName); + + truncate = String.format("/*+TDDL:cmd_extra(ENABLE_RECYCLEBIN=true)*/truncate table %s", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, truncate); + + insert = String.format("insert into %s(a,b) values (1,1)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, insert); + + assertSequenceStartValue(tableName); + } + + @Test + public void testTableWithRecycleBin2() { + if (crossSchema) { + return; + } + + String tableName = schemaPrefix + testTableName + "_14"; + String createTable = "create table " + tableName + + " (a int primary key," + + " b int" + + ") dbpartition by hash(a)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, createTable); + + String insert = String.format("insert into %s(a,b) values (1,1)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, insert); + + String truncate = String.format("/*+TDDL:cmd_extra(ENABLE_RECYCLEBIN=true)*/truncate table %s", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, truncate); + + insert = String.format("insert into %s(a,b) values (1,1)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, insert); + + truncate = String.format("/*+TDDL:cmd_extra(ENABLE_RECYCLEBIN=true)*/truncate table %s", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, truncate); + + insert = String.format("insert into %s(a,b) values (1,1)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, insert); + + truncate = String.format("/*+TDDL:cmd_extra(ENABLE_RECYCLEBIN=true)*/truncate table %s", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, truncate); + + insert = String.format("insert into %s(a,b) values (1,1)", tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, insert); + } + + void assertSequenceStartValue(String tableName) { + String select = String.format("select _drds_implicit_id_ from %s", tableName); + try (ResultSet rs = JdbcUtil.executeQuery(select, tddlConnection)) { + Assert.assertTrue(rs.next()); + Assert.assertEquals(rs.getLong(1), 100001L); + } catch (SQLException e) { + Assert.fail(); + } + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/fastchecker/FastCheckerWithScaleOutTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/fastchecker/FastCheckerWithScaleOutTest.java index 6494c2113..efb390ae2 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/fastchecker/FastCheckerWithScaleOutTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/fastchecker/FastCheckerWithScaleOutTest.java @@ -15,6 +15,7 @@ */ package com.alibaba.polardbx.qatest.ddl.sharding.fastchecker; + import com.alibaba.polardbx.qatest.util.JdbcUtil; import net.jcip.annotations.NotThreadSafe; import org.junit.*; @@ -28,17 +29,16 @@ /** * Created by zhuqiwei. - * - * @author: zhuqiwei */ @Ignore @NotThreadSafe public class FastCheckerWithScaleOutTest extends FastCheckerTestBase { private static String scaleOutTemplate = - "move database " + - "/*+TDDL: CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, SCALEOUT_CHECK_AFTER_BACKFILL={0})*/" + - "{1} to {2}"; + "move database " + + "/*+TDDL: CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, PHYSICAL_BACKFILL_ENABLE=false, SCALEOUT_CHECK_AFTER_BACKFILL={0})*/" + + + "{1} to {2}"; private static final String checkFinished = "show move database;"; @Before @@ -49,11 +49,11 @@ public void prepareData() { JdbcUtil.executeUpdateSuccess(tddlConnection, "use " + schemaName); JdbcUtil.executeUpdateSuccess(tddlConnection, MessageFormat - .format(srcTableTemplate, srcLogicTable, srcTbPartition)); + .format(srcTableTemplate, srcLogicTable, srcTbPartition)); for (int i = 1; i <= 500; i++) { JdbcUtil.executeUpdateSuccess(tddlConnection, MessageFormat - .format(fullColumnInsert, srcLogicTable, i, "uuid()", "uuid()", "FLOOR(Rand() * 1000)", "now()")); + .format(fullColumnInsert, srcLogicTable, i, "uuid()", "uuid()", "FLOOR(Rand() * 1000)", "now()")); } } @@ -67,16 +67,18 @@ private void executeScaleOut(boolean withFastChecker) { Set storages = new HashSet<>(); groupAndStorage.forEach((group, sids) -> { sids.forEach( - sid -> storages.add(sid) + sid -> storages.add(sid) ); }); Map> groupAndTables = getTableTopology(srcLogicTable); String srcGroup = groupAndTables.keySet().stream().findFirst().get(); - String srcStorageId = groupAndStorage.get(srcGroup).stream().filter(sid -> sid.contains("master")).findAny().get(); - String dstStorageId = storages.stream().filter(sid -> !sid.equals(srcStorageId) && sid.contains("master")).findAny().get(); + String srcStorageId = + groupAndStorage.get(srcGroup).stream().filter(sid -> sid.contains("master")).findAny().get(); + String dstStorageId = + storages.stream().filter(sid -> !sid.equals(srcStorageId) && sid.contains("master")).findAny().get(); String tddlSql = MessageFormat - .format(scaleOutTemplate, withFastChecker ? "true" : "false", srcGroup, "\'" + dstStorageId + "\'"); + .format(scaleOutTemplate, withFastChecker ? "true" : "false", srcGroup, "\'" + dstStorageId + "\'"); String jobId = null; JdbcUtil.executeUpdateSuccess(tddlConnection, tddlSql); waitUntilDdlJobSucceed(schemaName); @@ -90,7 +92,7 @@ private void waitUntilDdlJobSucceed(String schemaName) { try { while (rs.next()) { String db = rs.getString("SCHEMA"); - if(db == null || !db.equalsIgnoreCase(schemaName)) { + if (db == null || !db.equalsIgnoreCase(schemaName)) { continue; } String progress = rs.getString("PROGRESS"); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/DnGeneratedColumnTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/DnGeneratedColumnTest.java index 2a0e88d76..863449503 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/DnGeneratedColumnTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/DnGeneratedColumnTest.java @@ -250,7 +250,7 @@ public void testMoveDb() throws SQLException { .get(); String tddlSql = String.format( - "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, CN_ENABLE_CHANGESET=false)*/ %s to '%s'", + "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, PHYSICAL_BACKFILL_ENABLE=false, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, CN_ENABLE_CHANGESET=false)*/ %s to '%s'", srcGroup, dstStorageId); JdbcUtil.executeUpdateSuccess(conn, tddlSql); @@ -302,7 +302,7 @@ public void testMoveDbChangeset() throws SQLException { .get(); String tddlSql = String.format( - "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, CN_ENABLE_CHANGESET=true)*/ %s to '%s'", + "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, SPHYSICAL_BACKFILL_ENABLE=false, CALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, CN_ENABLE_CHANGESET=true)*/ %s to '%s'", srcGroup, dstStorageId); JdbcUtil.executeUpdateSuccess(conn, tddlSql); @@ -512,6 +512,9 @@ public void testShowColumns() throws SQLException { @Test public void testAlterTableUniqueIndexFailed() throws SQLException { + if (isMySQL80()) { + return; + } String tableName = "dn_gen_col_alter_unique_fail"; String createTable = String.format("create table %s (a int primary key, b int, c int as (a+b) stored, d int)", tableName); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/ExpressionIndex80Test.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/ExpressionIndex80Test.java new file mode 100644 index 000000000..bc17132cc --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/ExpressionIndex80Test.java @@ -0,0 +1,52 @@ +package com.alibaba.polardbx.qatest.ddl.sharding.gen; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.ReplicaIgnore; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +@ReplicaIgnore(ignoreReason = "not support 80 expression index in replica") +public class ExpressionIndex80Test extends DDLBaseNewDBTestCase { + + @Test + public void testCreate() { + if (!isMySQL80()) { + return; + } + String tableName = "expr_create_80_test"; + String createSql = String.format( + "create table `%s` (a int primary key, b int, c int, d varchar(64), e varchar(64), index cc((b + c))) DBPARTITION BY hash(`a`)", + tableName); + JdbcUtil.dropTable(tddlConnection, tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, createSql); + + JdbcUtil.dropTable(tddlConnection, tableName); + createSql = String.format( + "create table `%s` (a int primary key, b int, c int, d varchar(64), e varchar(64), f json DEFAULT NULL, " + + " index `idx_1` ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)))," + + " key `idx_2` ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)))," + + " unique index `idx_3` ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)))," + + " unique key `idx_4` ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)))) DBPARTITION BY hash(`a`)", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, createSql); + + String alterSql = String.format( + "alter table `%s` add index `idx_5` ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)));", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, alterSql); + + String createIndexSql = + String.format("create index `idx_6` on %s ((cast(json_extract(`f`,_utf8mb4'$[*]') as char(64) array)));", + tableName); + JdbcUtil.executeUpdateSuccess(tddlConnection, createIndexSql); + + String checkTableSql = String.format("check table %s", tableName); + List> checkTableResult = + JdbcUtil.getAllResult(JdbcUtil.executeQuery(checkTableSql, tddlConnection)); + + Assert.assertTrue(checkTableResult.stream().allMatch(o -> o.get(3).toString().equalsIgnoreCase("OK"))); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/ExpressionIndexTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/ExpressionIndexTest.java index 5246ab4c7..2501f7142 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/ExpressionIndexTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/ExpressionIndexTest.java @@ -27,6 +27,9 @@ private static String buildCmdExtra(String... params) { @Test public void testCreateFailed() { + if (isMySQL80()) { + return; + } String tableName = "expr_create_fail_tbl"; String create = String.format( @@ -81,6 +84,9 @@ public void testCreateFailed() { @Test public void testCreateSucc() { + if (isMySQL80()) { + return; + } String tableName = "expr_index_create_tbl"; String indexName = tableName + "_idx"; String create = @@ -121,6 +127,9 @@ public void testCreateSucc() { @Test public void testSpecialIndexName() { + if (isMySQL80()) { + return; + } String tableName = "expr_special_index_tbl"; String create = String.format("create table %s (a int primary key, b int, c int, d varchar(64), e varchar(64))", tableName); @@ -142,6 +151,9 @@ public void testSpecialIndexName() { @Test public void testSpecialColumnName() { + if (isMySQL80()) { + return; + } String tableName = "expr_special_column_tbl"; String indexName = tableName + "_idx"; String create = String.format("create table %s (a int primary key, abs varchar(64))", tableName); @@ -164,6 +176,9 @@ public void testSpecialColumnName() { @Test public void testMultiColumnIndex() { + if (isMySQL80()) { + return; + } String tableName = "expr_multi_column_tbl"; String indexName = tableName + "_idx"; String create = @@ -253,6 +268,9 @@ private List generatedDdl(String tableName, String indexDef, String inde @Test public void testMultipleAlterTable() { + if (isMySQL80()) { + return; + } String tableName = "expr_index_multi_alter_tbl"; String create = String.format( "create table %s (a int primary key, b int, c varchar(20), d varchar(20)) dbpartition by hash(a)", @@ -331,6 +349,9 @@ public void testMultipleAlterTable() { @Test public void testAlterTableAddColumnAndIndex() { + if (isMySQL80()) { + return; + } String tableName = "com_index_multi_alter_tbl"; String create = String.format( "create table %s (a int primary key, b int, c varchar(20), d varchar(20)) dbpartition by hash(a)", diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/GeneratedColumnConcurrentDMLTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/GeneratedColumnConcurrentDMLTest.java index 46a8095cd..1932a5953 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/GeneratedColumnConcurrentDMLTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/GeneratedColumnConcurrentDMLTest.java @@ -769,7 +769,11 @@ public Void apply(AtomicBoolean shouldStop, AtomicInteger totalCount) { try { JdbcUtil.executeUpdateSuccess(connection, sql); } catch (AssertionError e) { - if (e.getMessage().contains("Lock wait timeout exceeded") || e.getMessage() + if (isRDS80 && e.getMessage().contains( + "The definition of the table required by the flashback query has changed ")) { + // ignore + totalCount.getAndDecrement(); + } else if (e.getMessage().contains("Lock wait timeout exceeded") || e.getMessage() .contains("Deadlock found")) { // ignore totalCount.getAndDecrement(); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/GeneratedColumnTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/GeneratedColumnTest.java index 6a931e20b..4efd8b368 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/GeneratedColumnTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gen/GeneratedColumnTest.java @@ -667,7 +667,7 @@ public void testMoveDb() throws SQLException { .get(); String tddlSql = String.format( - "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, CN_ENABLE_CHANGESET=false)*/ %s to '%s'", + "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, PHYSICAL_BACKFILL_ENABLE=false, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, CN_ENABLE_CHANGESET=false)*/ %s to '%s'", srcGroup, dstStorageId); JdbcUtil.executeUpdateSuccess(conn, tddlSql); @@ -735,7 +735,7 @@ public void testMoveDbChangeset() throws SQLException { .get(); String tddlSql = String.format( - "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, CN_ENABLE_CHANGESET=true)*/ %s to '%s'", + "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, PHYSICAL_BACKFILL_ENABLE=false, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, CN_ENABLE_CHANGESET=true)*/ %s to '%s'", srcGroup, dstStorageId); JdbcUtil.executeUpdateSuccess(conn, tddlSql); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group1/CreateGsiTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group1/CreateGsiTest.java index c83219ddb..2c49f35ce 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group1/CreateGsiTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group1/CreateGsiTest.java @@ -38,7 +38,7 @@ import static com.alibaba.polardbx.qatest.validator.DataValidator.resultSetContentSameAssert; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.hamcrest.number.OrderingComparison.greaterThan; +import static org.hamcrest.number.OrderingComparisons.greaterThan; /** * @author chenmo.cm diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group2/GsiBackfillResumeTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group2/GsiBackfillResumeTest.java index 44df37f0c..f6f9ccdc7 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group2/GsiBackfillResumeTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group2/GsiBackfillResumeTest.java @@ -144,6 +144,7 @@ public void before() throws SQLException { } return new BackfillObjectRecord(-1, + -1, -1, tddlDatabase1, PRIMARY_TABLE_NAME, diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group2/GsiBackfillTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group2/GsiBackfillTest.java index b041733ef..56b4ee691 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group2/GsiBackfillTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group2/GsiBackfillTest.java @@ -277,12 +277,12 @@ public void singlePkCreateDropTest() { // ignore exception } - System.out.println("Start create GSI."); + logger.info("Start create GSI."); final String sqlCreateGsi = MessageFormat.format(CREATE_GSI_TMPL, INDEX_NAME, PRIMARY_TABLE_NAME); JdbcUtil.executeUpdateSuccess(tddlConnection, SLOW_HINT + sqlCreateGsi); - System.out.println("Create GSI done."); + logger.info("Create GSI done."); try { TimeUnit.SECONDS.sleep(1); @@ -290,7 +290,7 @@ public void singlePkCreateDropTest() { // ignore exception } - System.out.println("Start drop GSI."); + logger.info("Start drop GSI."); final String sqlDropGsi = MessageFormat.format(DROP_GSI_TMPL, INDEX_NAME, PRIMARY_TABLE_NAME); JdbcUtil.executeUpdateSuccess(tddlConnection, SLOW_HINT + sqlDropGsi); @@ -891,6 +891,8 @@ private Future launchDmlCheckThread(String sqlInsert, String sqlUpdate, Strin Supplier generateBatchSize) { return dmlPool.submit(new InsertRunner(stop, (conn) -> { // List> + logger.info(Thread.currentThread().getName() + " start to run DML and check."); + List> failedList = new ArrayList<>(); final ParameterContext skPc = Optional.ofNullable(generateSk.get()) @@ -926,6 +928,7 @@ private Future launchDmlCheckThread(String sqlInsert, String sqlUpdate, Strin } catch (Exception e) { if (!e.getMessage().contains("Deadlock found when trying to get lock") && !e.getMessage().contains("Lock wait timeout exceeded")) { + logger.info(Thread.currentThread().getName() + " find exception when insert " + e.getMessage()); throw GeneralUtil.nestedException(e); } try { @@ -941,6 +944,7 @@ private Future launchDmlCheckThread(String sqlInsert, String sqlUpdate, Strin lock.writeLock().unlock(); } + try (Statement stmt = conn.createStatement()) { try { lock.readLock().lock(); @@ -951,6 +955,7 @@ private Future launchDmlCheckThread(String sqlInsert, String sqlUpdate, Strin } catch (Exception e) { if (!e.getMessage().contains("Deadlock found when trying to get lock") && !e.getMessage().contains("Lock wait timeout exceeded")) { + logger.info(Thread.currentThread().getName() + " find exception when update " + e.getMessage()); throw GeneralUtil.nestedException(e); } try { @@ -976,6 +981,7 @@ private Future launchDmlCheckThread(String sqlInsert, String sqlUpdate, Strin } catch (Exception e) { if (!e.getMessage().contains("Deadlock found when trying to get lock") && !e.getMessage().contains("Lock wait timeout exceeded")) { + logger.info(Thread.currentThread().getName() + " find exception when delete " + e.getMessage()); throw GeneralUtil.nestedException(e); } try { @@ -991,7 +997,7 @@ private Future launchDmlCheckThread(String sqlInsert, String sqlUpdate, Strin lock.writeLock().unlock(); } - System.out.println(Thread.currentThread().getName() + " run DML and check."); + logger.info(Thread.currentThread().getName() + " run DML and check."); return inserted; }, throwException, 100)); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/InsertIgnoreTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/InsertIgnoreTest.java index 4474330d0..c225fcc37 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/InsertIgnoreTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/InsertIgnoreTest.java @@ -19,7 +19,9 @@ import com.alibaba.polardbx.qatest.CdcIgnore; import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.google.common.collect.ImmutableList; import org.apache.calcite.util.Pair; +import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; @@ -128,20 +130,27 @@ public void tableNoPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = buildCmdExtra(DML_EXECUTION_STRATEGY_LOGICAL, DISABLE_RETURNING); final String insert = hint + " insert ignore into " + tableName + "(id, c1, c5, c8) values(1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 'b', '2020-06-16 06:49:32'), (3, 3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), is(topology.size())); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size())); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.lessThanOrEqualTo(3)); } /** @@ -218,19 +227,26 @@ public void tableNoPkWithUk_defaultNull() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ insert ignore into " + tableName - + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), is(topology.size() + 3)); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ "; + final String insert = "insert ignore into " + tableName + + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -260,20 +276,26 @@ public void tableNoPkWithUk_amendUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ insert ignore into " + tableName - + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), is(topology.size())); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ "; + final String insert = "insert ignore into " + tableName + + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size())); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.is(1)); } /** @@ -469,24 +491,28 @@ public void tableWithPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String hint = buildCmdExtra(DML_EXECUTION_STRATEGY_LOGICAL, DISABLE_SKIP_DUPLICATE_CHECK_FOR_PK, DISABLE_RETURNING); final String insert = hint + "insert ignore into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (null, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), is(topology.size() + 1)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + Matchers.is(topology.size() + 1)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + Matchers.lessThanOrEqualTo(3 + 1)); } /** @@ -669,7 +695,10 @@ public void tableWithPkWithMultiUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ insert ignore into " + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ "; + final String insert = "insert ignore into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, ignore @@ -677,20 +706,32 @@ public void tableWithPkWithMultiUk() { + "(1, 2, null, 'd', '2020-06-16 06:49:32')," // u_c1_c2 冲突, ignore + "(1, 2, 4, 'e', '2020-06-16 06:49:32')," // u_c1_c2 冲突,ignore + "(2, 2, 4, 'f', '2020-06-16 06:49:32')"; // u_c2_c3 上与上面一行冲突,但是上面一个行被 ignore,这行保留 - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.is(topology.size() + 1)); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); - Assert.assertThat(trace.size(), is(topology.size() + 1)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + final String insert1 = "insert ignore into " + tableName + + "(c1, c2, c3, c5, c8) values" + + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + // 非全表扫描检测冲突时,下面这条会被插入, 导致与mysql不一致 + // + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, ignore + + "(1, null, 3, 'c', '2020-06-16 06:49:32'), " // 不冲突 + + "(1, 2, null, 'd', '2020-06-16 06:49:32')," // u_c1_c2 冲突, ignore + + "(1, 2, 4, 'e', '2020-06-16 06:49:32')," // u_c1_c2 冲突,ignore + + "(2, 2, 4, 'f', '2020-06-16 06:49:32')"; // u_c2_c3 上与上面一行冲突,但是上面一个行被 ignore,这行保留 + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert1, + buildSqlCheckData(columnNames, tableName), + Matchers.lessThanOrEqualTo(2 + 1)); } /* @@ -2115,12 +2156,11 @@ public void tableWithPkWithMultiUkWithUgsi_usingGsi() throws SQLException { tddlConnection); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); // final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); // final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, gsiName1); // gsi(partition pruning: 1) + insert(primary + gsi: 2) - Assert.assertThat(trace.size(), is(1 + 2)); + checkTraceRowCountIs(1 + 2); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, tddlConnection); @@ -2893,13 +2933,10 @@ public void tableWithPkWithUkWithUgsi_writeOnly_usingGsi() throws SQLException { tddlConnection); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, gsiName1); // primary (partition pruning: 3) + gsi(partition pruning: 1) + insert(primary + gsi: 2) - Assert.assertThat(trace.size(), is(3 + 1 + 2)); + // gsi(partition pruning: 1) + insert(primary + gsi: 2) + checkTraceRowCount(is(3 + 1 + 2)); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, tddlConnection); @@ -3391,7 +3428,7 @@ public void checkHugeBatchInsertIgnoreTraceId() throws SQLException { @Test public void testLogicalInsertIgnore() throws SQLException { - String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE)*/"; + String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl", " dbpartition by hash(id)", false, true, true, REPLACE_PARAMS); @@ -3475,7 +3512,7 @@ private void testComplexDmlInternal(String op, String tableName, String partitio @Test public void testLogicalInsertIgnoreUsingIn() throws SQLException { String hint = - "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_USING_IN=TRUE)*/"; + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_USING_IN=TRUE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl", " dbpartition by hash(id)", false, true, true, REPLACE_PARAMS); @@ -3491,6 +3528,39 @@ public void testLogicalInsertIgnoreUsingIn() throws SQLException { false, REPLACE_PARAMS); } + private static final String[][] INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN = new String[][] { + new String[] { + "(id,a,b)", "values (0,1,1),(1,2,2),(2,3,3),(100,101,101),(101,102,102)", "(id,a,b)", + "values (0,1,1),(1,2,2),(2,3,3),(100,101,101),(101,102,102)"}, + new String[] {"(id)", "values (1)", "(id)", "values (1)"}, + new String[] {"(id,a,b)", "values (3,0+2,0+2)", "(id,a,b)", "values (3,2,2)"}, + new String[] {"(id,a,b)", "values (1,2,2),(2,3,3)", "(id,a,b)", "values (1,2,2),(2,3,3)"}, + new String[] { + "(id,a,b)", String.format("select * from %s where id=100", SOURCE_TABLE_NAME), "(id,a,b)", + "values (100,101,101)"}, + new String[] { + "(id,a,b)", String.format("select * from %s where id>100", SOURCE_TABLE_NAME), "(id,a,b)", + "values (101,102,102),(102,103,103)"} + }; + + @Test + public void testLogicalInsertIgnoreWithoutFullTableScan() throws SQLException { + String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=FALSE)*/"; + + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl", " dbpartition by hash(id)", false, + true, true, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl_brd", " broadcast", false, true, + false, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl_single", " single", false, true, + false, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl", " dbpartition by hash(id)", true, + true, true, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl_brd", " broadcast", true, true, + false, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + testComplexDmlInternal(hint + "insert ignore into", "insert_ignore_test_tbl_single", " single", true, true, + false, INSERT_IGNORE_PARAMS_WITHOUT_FULL_TABLE_SCAN); + } + @Test public void testCrossSchemaInsertIgnore() throws SQLException { final String dbName = "test_db_cross_schema_dml"; @@ -3623,5 +3693,42 @@ public void insertIgnoreSelectSubqueryTest() throws Exception { checkGsi(tddlConnection, indexName1); } + + @Test + public void testReturningPolicy() throws SQLException { + if (!supportReturning) { + return; + } + try (Connection connection = getPolardbxConnection()) { + final String createTable = "CREATE TABLE IF NOT EXISTS `testReturningPolicy` (\n" + + " `id` bigint(20) NOT NULL AUTO_INCREMENT,\n" + + " `order_id` bigint(20) NOT NULL,\n" + + " `push_success` tinyint(4) NOT NULL DEFAULT '0',\n" + + " `retry_times` int(11) NOT NULL DEFAULT '0',\n" + + " `del` tinyint(4) NOT NULL DEFAULT '0',\n" + + " PRIMARY KEY (`id`),\n" + + " GLOBAL INDEX `gsi_id` (`id`) COVERING (`order_id`)\n" + + " DBPARTITION BY HASH(`id`),\n" + + " UNIQUE KEY `uk_order_id` (`order_id`, `del`),\n" + + " KEY `idx_del_push` (`del`, `push_success`)\n" + + ")\n" + + "DBPARTITION BY HASH(`order_id`)\n"; + JdbcUtil.executeUpdateSuccess(connection, createTable); + final String insertSql = "insert ignore into `testReturningPolicy` " + + " (`id`,`order_id`,`push_success`,`retry_times`,`del`) values" + + " ('16599','19609','1','0','0')," + + " ('16600','19608','1','0','0')"; + final String deleteSql = "delete from `testReturningPolicy` where 1=1"; + JdbcUtil.executeUpdateSuccess(connection, "set SEQUENTIAL_CONCURRENT_POLICY = true"); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + JdbcUtil.executeUpdateSuccess(connection, deleteSql); + JdbcUtil.executeUpdateSuccess(connection, "set SEQUENTIAL_CONCURRENT_POLICY = false"); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + JdbcUtil.executeUpdateSuccess(connection, insertSql); + } + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/ReplaceTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/ReplaceTest.java index 3f646c063..936aae9d4 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/ReplaceTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/ReplaceTest.java @@ -19,6 +19,7 @@ import com.alibaba.polardbx.qatest.CdcIgnore; import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.google.common.collect.ImmutableList; import org.apache.calcite.util.Pair; import org.hamcrest.Matchers; import org.junit.Assert; @@ -119,21 +120,29 @@ public void tableNoPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ replace into " - + tableName - + "(id, c1, c5, c8) values(1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 'b', '2020-06-16 06:49:32'), (3, 3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, false); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ "; + final String insert = "replace into " + tableName + + "(id, c1, c5, c8) values(1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 'b', '2020-06-16 06:49:32'), (3, 3, 'c', '2020-06-16 06:49:32')"; + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + false, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + false, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -164,19 +173,26 @@ public void tableNoPkWithUk_defaultNull() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ replace into " + tableName - + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/ "; + final String insert = "replace into " + tableName + + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -206,23 +222,27 @@ public void tableNoPkWithUk_amendUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ replace into " - + tableName - + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - // VALUES 中有重复,affected rows 可能会比 MySQL 返回的小 1 - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, false); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ "; + final String insert = "replace into " + tableName + + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; + // VALUES 中有重复,affected rows 可能会比 MySQL 返回的小 1 + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size() + 1)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.is(1 + 1)); } /** @@ -418,24 +438,27 @@ public void tableWithPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ replace into " - + tableName - + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (null, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ "; + final String insert = "replace into " + tableName + + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (null, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')"; - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -517,9 +540,10 @@ public void tableWithPkWithMultiUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ replace into " - + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_FORCE_PUSHDOWN_RC_REPLACE=TRUE)*/ "; + final String insert = "replace into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, replace @@ -527,20 +551,23 @@ public void tableWithPkWithMultiUk() { + "(1, 2, null, 'd', '2020-06-16 06:49:32')," // u_c1_c2 与第一行冲突,但是第一行被 replace, 这行保留 + "(1, 2, 4, 'e', '2020-06-16 06:49:32')," // u_c1_c2 冲突,replace + "(2, 2, 4, 'f', '2020-06-16 06:49:32')"; // u_c2_c3 冲突,replace - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.lessThanOrEqualTo(3 + 3)); } /* @@ -1684,12 +1711,9 @@ public void tableWithPkWithMultiUkWithUgsi_usingGsi() throws SQLException { tddlConnection); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, gsiName); // primary (partition pruning: 3) + gsi(partition pruning: 1 + primary partition pruning: 2) + replace(primary + gsi: 7) - Assert.assertThat(trace.size(), Matchers.is(3 + 1 + 2 + (2 * 2 + 1) + (1 + 1))); + // gsi(partition pruning: 1 + primary partition pruning: 3) + replace(primary + gsi: 7) + checkTraceRowCount(Matchers.is(1 + 3 + (2 * 2 + 1) + (1 + 1))); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, tddlConnection); @@ -2275,12 +2299,10 @@ public void tableWithPkWithUkWithUgsi_writeOnly_usingGsi() throws SQLException { tddlConnection); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, gsiName); // primary (partition pruning: 3) + gsi(partition pruning: 1 + primary partition pruning: 2) + replace(primary + gsi: 3 + 3 + 1) - Assert.assertThat(trace.size(), Matchers.is(3 + 1 + 2 + 7)); + // gsi(partition pruning: 1 + primary partition pruning: 3) + replace(primary + gsi: 3 + 3 + 1) + checkTraceRowCount(Matchers.is(3 + 3 + 7)); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, tddlConnection); @@ -2914,7 +2936,7 @@ public void checkHugeBatchReplaceTraceId() throws SQLException { @Test public void testLogicalReplace() throws SQLException { - String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE)*/"; + String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint + "replace into", "replace_test_tbl", " dbpartition by hash(id)", false, true, true, REPLACE_PARAMS); @@ -2995,6 +3017,40 @@ private void testComplexDmlInternal(String op, String tableName, String partitio } } + private static final String[][] REPLACE_PARAMS_1 = new String[][] { + new String[] { + "(id,a,b)", "values (0,1,1),(1,2,2),(2,3,3),(100,101,101),(101,102,102)", "(id,a,b)", + "values (0,1,1),(1,2,2),(2,3,3),(100,101,101),(101,102,102)"}, + new String[] {"(id)", "values (1)", "(id)", "values (1)"}, + new String[] {"(id,a,b)", "values (5,0+2,0+2)", "(id,a,b)", "values (5,2,2)"}, + new String[] {"(id,a,b)", "values (1,2,2),(2,3,3)", "(id,a,b)", "values (1,2,2),(2,3,3)"}, + new String[] { + "(id,a,b)", String.format("select * from %s where id=100", SOURCE_TABLE_NAME), "(id,a,b)", + "values (100,101,101)"}, + new String[] { + "(id,a,b)", String.format("select * from %s where id>100", SOURCE_TABLE_NAME), "(id,a,b)", + "values (101,102,102),(102,103,103)"} + }; + + @Test + public void testLogicalReplaceWithoutFullTableScan() throws SQLException { + String hint = + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=FALSE)*/"; + + testComplexDmlInternal(hint + "replace into", "replace_test_tbl", " dbpartition by hash(id)", false, true, true, + REPLACE_PARAMS_1); + testComplexDmlInternal(hint + "replace into", "replace_test_tbl_brd", " broadcast", false, true, false, + REPLACE_PARAMS_1); + testComplexDmlInternal(hint + "replace into", "replace_test_tbl_single", " single", false, true, false, + REPLACE_PARAMS_1); + testComplexDmlInternal(hint + "replace into", "replace_test_tbl", " dbpartition by hash(id)", true, true, true, + REPLACE_PARAMS_1); + testComplexDmlInternal(hint + "replace into", "replace_test_tbl_brd", " broadcast", true, true, false, + REPLACE_PARAMS_1); + testComplexDmlInternal(hint + "replace into", "replace_test_tbl_single", " single", true, true, false, + REPLACE_PARAMS_1); + } + /** * 检查使用 IN 代替 UNION 的 HINT 是否生效 */ @@ -3092,7 +3148,7 @@ public void testMaxInCount() throws SQLException { @Test public void testLogicalReplaceUsingIn() throws SQLException { String hint = - "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_USING_IN=TRUE)*/"; + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_USE_RETURNING=FALSE,DML_GET_DUP_USING_IN=TRUE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint + "replace into", "replace_test_tbl", " dbpartition by hash(id)", false, true, true, REPLACE_PARAMS); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/UpsertTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/UpsertTest.java index 34e7891f7..6586a6c78 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/UpsertTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/gsi/group3/UpsertTest.java @@ -127,21 +127,29 @@ public void tableNoPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; final String insert = - "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName + "insert into " + tableName + "(id, c1, c5, c8) values(1, 1, 'a', '2020-06-16 06:49:32'), (2, 2, 'b', '2020-06-16 06:49:32'), (3, 3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + // equal when first insert + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -172,20 +180,27 @@ public void tableNoPkWithUk_defaultNull() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ "; final String insert = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (2, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -215,23 +230,30 @@ public void tableNoPkWithUk_amendUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; + final String insert = "insert into " + tableName + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + "on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - + // equal when first insert // VALUES 中有重复,affected rows 可能会比 MySQL 返回的小 1 - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, false); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 1)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size() + 1)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.is(1 + 1)); } /** @@ -262,23 +284,27 @@ public void tableNoPkWithUk_amendUk2() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName - + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" - + "on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - // VALUES 中有重复,affected rows 可能会比 MySQL 返回的小 1 - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, false); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size())); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ "; + final String insert = "insert into " + tableName + + "(c1, c5, c8) values(3, 'a', '2020-06-16 06:49:32'), (3, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')" + + "on duplicate key update c3 = c3 + 1"; + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size())); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.is(1)); } /** @@ -486,24 +512,27 @@ public void tableWithPkWithUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ insert into " - + tableName - + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (null, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')on duplicate key update c3 = c3 + 1"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + final String hint = + "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE,DML_SKIP_DUPLICATE_CHECK_FOR_PK=FALSE)*/ "; + final String insert = "insert into " + tableName + + "(c1, c5, c8) values(1, 'a', '2020-06-16 06:49:32'), (null, 'b', '2020-06-16 06:49:32'), (3, 'c', '2020-06-16 06:49:32')on duplicate key update c3 = c3 + 1"; + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -584,7 +613,10 @@ public void tableWithPkWithMultiUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ "; + final String insert = "insert into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, update @@ -598,15 +630,22 @@ public void tableWithPkWithMultiUk() { // selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, // tddlConnection); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 2)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeOnceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.is(topology.size() + 2)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeOnceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.lessThanOrEqualTo(2 + 2)); } /** @@ -639,7 +678,10 @@ public void tableWithPkWithMultiUk1() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ "; + final String insert = "insert into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " + "(null, 2, 3, 'b', '2020-06-16 06:49:32'), " // u_c2_c3 冲突, update @@ -653,15 +695,22 @@ public void tableWithPkWithMultiUk1() { // selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, // tddlConnection); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 2)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeOnceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.is(topology.size() + 2)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeOnceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.lessThanOrEqualTo(2 + 2)); } /** @@ -695,6 +744,8 @@ public void tableWithPkWithMultiUk_modifyPartitionKey() throws Exception { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String insert = "insert into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " @@ -709,20 +760,24 @@ public void tableWithPkWithMultiUk_modifyPartitionKey() throws Exception { // selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, // tddlConnection); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7"); - final List> mysqlResult = - selectContentSameAssert("select " + String.join(",", columnNames) + " from " + tableName, null, - mysqlConnection, tddlConnection); - - JdbcUtil - .assertRouteCorrectness(hint, tableName, mysqlResult, columnNames, ImmutableList.of("c1"), tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeOnceThenCheckDataAndTraceResultAndRouteCorrectness( + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + columnNames, + tableName, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeOnceThenCheckDataAndTraceResultAndRouteCorrectness( + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + columnNames, + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -756,6 +811,8 @@ public void tableWithPkWithMultiUk_modifyPartitionKey1() throws Exception { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String insert = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " @@ -770,20 +827,24 @@ public void tableWithPkWithMultiUk_modifyPartitionKey1() throws Exception { // selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, // tddlConnection); - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 2)); - final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7"); - final List> mysqlResult = - selectContentSameAssert("select " + String.join(",", columnNames) + " from " + tableName, null, - mysqlConnection, tddlConnection); - - JdbcUtil - .assertRouteCorrectness(hint, tableName, mysqlResult, columnNames, ImmutableList.of("c1"), tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeOnceThenCheckDataAndTraceResultAndRouteCorrectness( + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + columnNames, + tableName, + Matchers.is(topology.size() + 2)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeOnceThenCheckDataAndTraceResultAndRouteCorrectness( + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + columnNames, + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /* @@ -2224,14 +2285,10 @@ public void tableWithPkWithMultiUkWithUgsi_usingGsi() throws SQLException { tddlConnection); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, gsiName); // primary (partition pruning: 3) + gsi(partition pruning: 1 + primary partition pruning: 2) + upsert(primary + gsi: 5) - Assert.assertThat(trace.size(), Matchers.is(3 + 1 + 2 + (1 + 2) * 2 - 1)); + // gsi(partition pruning: 1 + primary partition pruning: 4) + upsert(primary + gsi: 5) + checkTraceRowCount(Matchers.is(1 + 4 + (1 + 2) * 2 - 1)); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, tddlConnection); @@ -2906,12 +2963,9 @@ public void tableWithPkWithUkWithUgsi_writeOnly_usingGsi() throws SQLException { tddlConnection); executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> primaryTopology = JdbcUtil.getTopology(tddlConnection, tableName); - // final List> gsiTopology = JdbcUtil.getTopology(tddlConnection, gsiName); // primary (3) + gsi(partition pruning: 1 + primary partition pruning: 2) + update(primary + gsi: 5) - Assert.assertThat(trace.size(), Matchers.is(3 + 1 + 2 + 5)); + // gsi(partition pruning: 1 + primary partition pruning: 4) + update(primary + gsi: 5) + checkTraceRowCount(Matchers.is(3 + 1 + 2 + 5)); selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, tddlConnection); @@ -3322,22 +3376,27 @@ public void tableWithPkNoUk_modifyPk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); - final String insert = - "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ insert into " + tableName - + "(id, c1, c5, c8) values(4, 1, 'a', '2020-06-16 06:49:32'), (5, 2, 'b', '2020-06-16 06:49:32'), (6, 3, 'c', '2020-06-16 06:49:32')" - + "on duplicate key update c1 = c1 + 3"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, null, true); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); - - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); - - selectContentSameAssert("select * from " + tableName, null, mysqlConnection, tddlConnection); + final String hint = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE,DML_SKIP_TRIVIAL_UPDATE=FALSE)*/ "; + final String insert = "insert into " + tableName + + "(id, c1, c5, c8) values(4, 1, 'a', '2020-06-16 06:49:32'), (5, 2, 'b', '2020-06-16 06:49:32'), (6, 3, 'c', '2020-06-16 06:49:32')" + + "on duplicate key update c1 = c1 + 3"; + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + "select * from " + tableName, + Matchers.is(topology.size() + 3)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeTwiceThenCheckDataAndTraceResult( + hint + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + "select * from " + tableName, + Matchers.lessThanOrEqualTo(3 + 3)); } /** @@ -3415,6 +3474,8 @@ public void tableWithPkWithMultiUk_modifyUk() { JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + final String insert = "/*+TDDL:CMD_EXTRA(DML_PUSH_DUPLICATE_CHECK=FALSE)*/ insert into " + tableName + "(c1, c2, c3, c5, c8) values" + "(1, 2, 3, 'a', '2020-06-16 06:49:32'), " @@ -3425,15 +3486,22 @@ public void tableWithPkWithMultiUk_modifyUk() { + "(1, 2, 4, 'f', '2020-06-16 06:49:32')" // u_c1_c2 冲突,update + "on duplicate key update c2 = c2 + 1, c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); - - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 2)); - - selectContentSameAssert("select c1,c2,c3,c4,c5,c6,c7,c8 from " + tableName, null, mysqlConnection, - tddlConnection); + final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + executeOnceThenCheckDataAndTraceResult( + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.is(topology.size() + 2)); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + executeOnceThenCheckDataAndTraceResult( + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ ", + insert, + buildSqlCheckData(columnNames, tableName), + Matchers.lessThanOrEqualTo(2 + 2)); } @Test @@ -3664,6 +3732,8 @@ public void tableWithPkWithMultiUk_modifyPartitionKey_testPhySqlId() throws Exce JdbcUtil.executeUpdateSuccess(tddlConnection, createTable + partitionDef); JdbcUtil.executeUpdateSuccess(mysqlConnection, createTable); + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + JdbcUtil.executeUpdate(tddlConnection, "set polardbx_server_id = 27149"); final String insert = "insert into " + tableName @@ -3676,22 +3746,51 @@ public void tableWithPkWithMultiUk_modifyPartitionKey_testPhySqlId() throws Exce + "(1, 2, 4, 'f', '2020-06-16 06:49:32')" // u_c1_c2 冲突,update + "on duplicate key update c1 = c1 + 1, c5 = values(c5)"; - executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + insert, null, true); - final List> trace = getTrace(tddlConnection); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + String tmpHint = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + tmpHint + insert, null, true); + List> trace = getTrace(tddlConnection); checkPhySqlId(trace); - final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); - Assert.assertThat(trace.size(), Matchers.is(topology.size() + 3)); final List columnNames = ImmutableList.of("c1", "c2", "c3", "c4", "c5", "c6", "c7"); - final List> mysqlResult = - selectContentSameAssert("select " + String.join(",", columnNames) + " from " + tableName, null, - mysqlConnection, tddlConnection); + List> mysqlResult = selectContentSameAssert(buildSqlCheckData(columnNames, tableName), + null, + mysqlConnection, + tddlConnection); + + JdbcUtil.assertRouteCorrectness(hint, + tableName, + mysqlResult, + columnNames, + ImmutableList.of("c1"), + tddlConnection); + + // Clear data + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, "delete from " + tableName + " where 1=1", null, false); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + tmpHint = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, "trace " + tmpHint + insert, null, true); + trace = getTrace(tddlConnection); + + checkPhySqlId(trace); - JdbcUtil - .assertRouteCorrectness(hint, tableName, mysqlResult, columnNames, ImmutableList.of("c1"), tddlConnection); + Assert.assertThat(trace.size(), Matchers.lessThanOrEqualTo(3 + 3)); + + mysqlResult = selectContentSameAssert(buildSqlCheckData(columnNames, tableName), + null, + mysqlConnection, + tddlConnection); + + JdbcUtil.assertRouteCorrectness(hint, + tableName, + mysqlResult, + columnNames, + ImmutableList.of("c1"), + tddlConnection); } /** @@ -4108,7 +4207,8 @@ public void checkHugeBatchUpsertTraceId() throws SQLException { @Test public void testLogicalUpsert() throws SQLException { - String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL)*/"; + String hint = + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint + "insert into", "upsert_test_tbl", " dbpartition by hash(id)", false, true, true, UPSERT_PARAMS); @@ -4191,7 +4291,8 @@ private void testComplexDmlInternal(String op, String tableName, String partitio @Test public void testLogicalUpsertUsingIn() throws SQLException { - String hint = "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_GET_DUP_USING_IN=TRUE)*/"; + String hint = + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_GET_DUP_USING_IN=TRUE,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=TRUE)*/"; testComplexDmlInternal(hint + "insert into", "upsert_test_tbl", " dbpartition by hash(id)", false, true, true, UPSERT_PARAMS); @@ -4207,6 +4308,49 @@ public void testLogicalUpsertUsingIn() throws SQLException { UPSERT_PARAMS); } + private static final String[][] UPSERT_PARAMS_1 = new String[][] { + new String[] { + "(id,a,b)", "values (1,2,2),(100,101,101),(101,102,102)", "(id,a,b)", + "values (1,2,2),(100,101,101),(101,102,102)"}, + new String[] { + "(id,a,b)", "values (1,5,5),(2,3,3) on duplicate key update a=id+2,b=id+2", "(id,a,b)", + "values (1,5,5),(2,3,3) on duplicate key update a=id+2,b=id+2"}, + new String[] { + "(id,a,b)", "values (1,5,5),(2,3,3) on duplicate key update a=values(a),b=values(a)", "(id,a,b)", + "values (1,5,5),(2,3,3) on duplicate key update a=values(a),b=values(a)"}, + new String[] { + "(id,a,b)", "values (1,5,5),(2,3,3) on duplicate key update id=id+10", "(id,a,b)", + "values (1,5,5),(2,3,3) on duplicate key update id=id+10"}, + new String[] { + "(id,a,b)", + String.format("select * from %s where id=100 ", SOURCE_TABLE_NAME) + "on duplicate key update id=id+10,a=a", + "(id,a,b)", "values (100,101,101) on duplicate key update id=id+10,a=a"}, + new String[] { + "(id,a,b)", + String.format("select * from %s where id>100 order by id ", SOURCE_TABLE_NAME) + + "on duplicate key update id=id+10,a=b", + "(id,a,b)", "values (101,102,102),(102,103,103) on duplicate key update id=id+10,a=b"} + }; + + @Test + public void testLogicalUpsertWithoutFullTableScan() throws SQLException { + String hint = + "/*+TDDL:CMD_EXTRA(DML_EXECUTION_STRATEGY=LOGICAL,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=FALSE)*/"; + + testComplexDmlInternal(hint + "insert into", "upsert_test_tbl", " dbpartition by hash(id)", false, true, true, + UPSERT_PARAMS_1); + testComplexDmlInternal(hint + "insert into", "upsert_test_tbl_brd", " broadcast", false, true, false, + UPSERT_PARAMS_1); + testComplexDmlInternal(hint + "insert into", "upsert_test_tbl_single", " single", false, true, false, + UPSERT_PARAMS_1); + testComplexDmlInternal(hint + "insert into", "upsert_test_tbl", " dbpartition by hash(id)", true, true, true, + UPSERT_PARAMS_1); + testComplexDmlInternal(hint + "insert into", "upsert_test_tbl_brd", " broadcast", true, true, false, + UPSERT_PARAMS_1); + testComplexDmlInternal(hint + "insert into", "upsert_test_tbl_single", " single", true, true, false, + UPSERT_PARAMS_1); + } + @Test public void testUpsertModifyShardingKey() { String tableName = "upsert_test_modify_sk_tbl"; @@ -4379,8 +4523,8 @@ private void testUpsertSingleShardInternal(String tableName, String upsertSql, S } @Test - public void testUpsertSingleShardMultiSk() { - String tableName = "test_upsert_single_shard_pk_tbl"; + public void testUpsertSingleShardMultiSk_fullTableScan() { + String tableName = "test_upsert_single_shard_pk_tbl_fts"; String createSql = String.format("create table %s (a int primary key, b int, c int)", tableName); String partDef = "dbpartition by hash(a) tbpartition by hash(b) tbpartitions 2"; @@ -4389,72 +4533,229 @@ public void testUpsertSingleShardMultiSk() { List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = true + final String hint = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; + // all after value, pushdown String upsertSql = String.format("insert into %s values (1,2,3) on duplicate key update a=values(a),b=values(b),c=c", tableName); - JdbcUtil.executeUpdateSuccess(mysqlConnection, upsertSql); - JdbcUtil.executeUpdateSuccess(tddlConnection, "trace " + upsertSql); - List> trace = getTrace(tddlConnection); - Assert.assertEquals(1, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=2", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(1)); // all before value, pushdown upsertSql = String.format("insert into %s values (1,2,4) on duplicate key update a=a,b=b,c=c", tableName); - JdbcUtil.executeUpdateSuccess(mysqlConnection, upsertSql); - JdbcUtil.executeUpdateSuccess(tddlConnection, "trace " + upsertSql); - trace = getTrace(tddlConnection); - Assert.assertEquals(1, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=2", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(1)); // after value and before value, do not pushdown upsertSql = String.format("insert into %s values (1,2,5) on duplicate key update a=values(a),b=b,c=c", tableName); - JdbcUtil.executeUpdateSuccess(mysqlConnection, upsertSql); - JdbcUtil.executeUpdateSuccess(tddlConnection, "trace " + upsertSql); - trace = getTrace(tddlConnection); - Assert.assertEquals(topology.size(), trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=2", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(topology.size())); // after value with different column, do not pushdown upsertSql = String.format("insert into %s values (1,2,6) on duplicate key update a=values(a),b=values(a),c=c", tableName); - JdbcUtil.executeUpdateSuccess(mysqlConnection, upsertSql); - JdbcUtil.executeUpdateSuccess(tddlConnection, "trace " + upsertSql); - trace = getTrace(tddlConnection); - Assert.assertEquals(topology.size() + 2, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=1", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=1", + Matchers.is(topology.size() + 2)); // before value with different column , do not pushdown upsertSql = String.format("insert into %s values (1,2,7) on duplicate key update a=a,b=a,c=c", tableName); - JdbcUtil.executeUpdateSuccess(mysqlConnection, upsertSql); - JdbcUtil.executeUpdateSuccess(tddlConnection, "trace " + upsertSql); - trace = getTrace(tddlConnection); - Assert.assertEquals(topology.size(), trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=1", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=1", + Matchers.is(topology.size())); + + // part after value, can pushdown + // a is primary key, if duplicated happens, a.oldValue = a.newValue + // b is one of partition key, if duplicated happens, b.oldValue and b.newValue are at same partition, because we route upsert using b.newValue + upsertSql = String.format("insert into %s values (1,3,8) on duplicate key update b=values(b),c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(1)); // part after value, do not pushdown + upsertSql = String.format("insert into %s values (1,2,8) on duplicate key update a=values(a),c=c+1", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(topology.size() + 1)); + + // part before value, pushdown + upsertSql = String.format("insert into %s values (1,3,10) on duplicate key update b=b,c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(1)); + } + + @Test + public void testUpsertSingleShardMultiSk() { + String tableName = "test_upsert_single_shard_pk_tbl"; + String createSql = String.format("create table %s (a int primary key, b int, c int)", tableName); + String partDef = "dbpartition by hash(a) tbpartition by hash(b) tbpartitions 2"; + + JdbcUtil.executeUpdateSuccess(mysqlConnection, createSql); + JdbcUtil.executeUpdateSuccess(tddlConnection, createSql + partDef); + + // DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN = false + final String hint = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; + + // all after value, pushdown + String upsertSql = + String.format("insert into %s values (1,2,3) on duplicate key update a=values(a),b=values(b),c=c", + tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(1)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 2 | 3 || 1 | 2 | 3 | + * +-----------++-----------+ + */ + + // all before value, pushdown + upsertSql = String.format("insert into %s values (1,2,4) on duplicate key update a=a,b=b,c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(1)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 2 | 3 || 1 | 2 | 3 | + * +-----------++-----------+ + */ + + // after value and before value, do not pushdown + upsertSql = + String.format("insert into %s values (1,2,5) on duplicate key update a=values(a),b=b,c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=2", + Matchers.is(1)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 2 | 3 || 1 | 2 | 3 | + * +-----------++-----------+ + */ + + // after value with different column, do not pushdown + upsertSql = String.format("insert into %s values (1,2,6) on duplicate key update a=values(a),b=values(a),c=c", + tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=1", + Matchers.is(1 + 2)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 1 | 3 || 1 | 1 | 3 | + * +-----------++-----------+ + */ + + // before value with different column , do not pushdown + upsertSql = String.format("insert into %s values (1,2,7) on duplicate key update a=a,b=a,c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=1", + Matchers.is(1 + 1)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 1 | 3 || 1 | 1 | 3 | + * | 1 | 2 | 7 |+-----------+ + * +-----------+ + */ + + // part after value, can pushdown + // a is primary key, if duplicated happens, a.oldValue = a.newValue + // b is one of partition key, if duplicated happens, b.oldValue and b.newValue are at same partition, because we route upsert using b.newValue upsertSql = String.format("insert into %s values (1,3,8) on duplicate key update b=values(b),c=c", tableName); - JdbcUtil.executeUpdateSuccess(mysqlConnection, upsertSql); - JdbcUtil.executeUpdateSuccess(tddlConnection, "trace " + upsertSql); - trace = getTrace(tddlConnection); - Assert.assertEquals(topology.size() + 2, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=3", null, mysqlConnection, - tddlConnection); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(1)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 3 | 3 || 1 | 3 | 3 | + * | 1 | 2 | 7 |+-----------+ + * +-----------+ + */ + + // part after value, do not pushdown + upsertSql = String.format("insert into %s values (1,3,8) on duplicate key update a=values(a),c=c+1", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(1 + 1)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 3 | 4 || 1 | 3 | 4 | + * | 1 | 2 | 7 |+-----------+ + * +-----------+ + */ // part before value, pushdown - upsertSql = String.format("insert into %s values (1,2,9) on duplicate key update b=b,c=c", tableName); - JdbcUtil.executeUpdateSuccess(mysqlConnection, upsertSql); - JdbcUtil.executeUpdateSuccess(tddlConnection, "trace " + upsertSql); - trace = getTrace(tddlConnection); - Assert.assertEquals(1, trace.size()); - selectContentSameAssert("select * from " + tableName + " where a=1 and b=3", null, mysqlConnection, - tddlConnection); + upsertSql = String.format("insert into %s values (1,2,10) on duplicate key update b=b,c=c", tableName); + executeOnceThenCheckDataAndTraceResult(hint, + upsertSql, + "select * from " + tableName + " where a=1 and b=3", + Matchers.is(1)); + + /* + * +-----------++-----------+ + * | PolarDB-X || MySQL | + * |-----------||-----------| + * | a | b | c || a | b | c | + * |---|---|---||---|---|---| + * | 1 | 3 | 4 || 1 | 3 | 4 | + * | 1 | 2 | 7 |+-----------+ + * +-----------+ + */ } @Test diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ColumnOrdinalTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ColumnOrdinalTest.java index 1d20f7e4a..cfee997de 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ColumnOrdinalTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ColumnOrdinalTest.java @@ -235,8 +235,8 @@ private void checkCdcDdlMark(String sql, String tableName, SchemaRepository repo private DDLExtInfo getDdlExtInfo(String sql) throws SQLException { try (Statement stmt = tddlConnection.createStatement()) { try (ResultSet resultSet = stmt.executeQuery( - "select ext from __cdc__." + CDC_DDL_RECORD_TABLE + " where ddl_sql = '" + sql - + "' order by id desc limit 1")) { + "select ext from __cdc__." + CDC_DDL_RECORD_TABLE + " where ddl_sql like '%" + sql + + "%' order by id desc limit 1")) { while (resultSet.next()) { String extStr = resultSet.getString(1); if (StringUtils.isNotBlank(extStr)) { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ConcurrentDMLBaseTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ConcurrentDMLBaseTest.java index 3227b45d9..08b955d7e 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ConcurrentDMLBaseTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ConcurrentDMLBaseTest.java @@ -30,8 +30,8 @@ public class ConcurrentDMLBaseTest extends DDLBaseNewDBTestCase { // Use logical execution since result may be different from pushdown execution protected static final String USE_LOGICAL_EXECUTION = "DML_EXECUTION_STRATEGY=LOGICAL"; protected static final String DISABLE_DML_RETURNING = "DML_USE_RETURNING=FALSE"; - protected static final int FILL_COUNT = 2500; - protected static final int FILL_BATCH_SIZE = 2500; + protected static final int FILL_COUNT = 1500; + protected static final int FILL_BATCH_SIZE = 1500; protected static String buildCmdExtra(String... params) { if (0 == params.length) { @@ -138,6 +138,7 @@ public Void apply(AtomicBoolean shouldStop, AtomicInteger totalCount) { if (e.getMessage().contains("Lock wait timeout exceeded") || e.getMessage() .contains("Deadlock found")) { // ignore + Thread.sleep(500); totalCount.getAndDecrement(); } else if ((e.getMessage().contains("Unknown target column") || e.getMessage() .contains("not found")) && !changed) { @@ -169,7 +170,8 @@ public Void apply(AtomicBoolean shouldStop, AtomicInteger totalCount) { JdbcUtil.updateDataTddl(connection, sql, null); } Thread.sleep(1000); - String sql = String.format(alterSql, finalTableName) + USE_OMC_ALGORITHM; + String batchHint = "/*+TDDL:cmd_extra(GSI_BACKFILL_BATCH_SIZE=50,CHANGE_SET_APPLY_BATCH=32)*/"; + String sql = batchHint + String.format(alterSql, finalTableName) + USE_OMC_ALGORITHM; try { execDdlWithRetry(tddlDatabase1, finalTableName, sql, connection); } finally { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ConcurrentUpsertTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ConcurrentUpsertTest.java index a3ae10168..196927961 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ConcurrentUpsertTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/omc/ConcurrentUpsertTest.java @@ -281,7 +281,7 @@ public void changeWithUpsert7() throws Exception { count, count, FILL_COUNT); Function generator2 = (count) -> String.format( - "insert into %%s values(%d, %d + %d,null,null) on duplicate key update e=default(e),f=default(g)", + "insert into %%s values(%d, %d + %d,null,default) on duplicate key update e=default(e),f=default(g)", count, count, FILL_COUNT); QuadFunction checker = (colA, colB, colC, colD) -> (colB == 3 || colB == 4) diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/CdcScaleOutRecordTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/CdcScaleOutRecordTest.java index e540073af..0430fda91 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/CdcScaleOutRecordTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/CdcScaleOutRecordTest.java @@ -120,7 +120,8 @@ private String buildMoveDatabasesSql(String dbName) { e.printStackTrace(); } - String sql = "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true)*/ %s,%s to '%s'"; + String sql = + "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, PHYSICAL_BACKFILL_ENABLE=false)*/ %s,%s to '%s'"; if (storageGroupsInfo.size() > 1) { Map.Entry> first = null; Map.Entry> second = null; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutBaseTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutBaseTest.java index aac96370b..8d4eb3d66 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutBaseTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutBaseTest.java @@ -134,10 +134,10 @@ private void moveOneDb(List storageIDs) { if (StringUtils.isEmpty(finalTableStat) || ComplexTaskMetaManager.ComplexTaskStatus.PUBLIC.toString() .equalsIgnoreCase(finalTableStat)) { tddlSql = - "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true)*/ "; + "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, PHYSICAL_BACKFILL_ENABLE=false, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true)*/ "; } else { tddlSql = - "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, SCALE_OUT_FINAL_TABLE_STATUS_DEBUG=" + "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, PHYSICAL_BACKFILL_ENABLE=false, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, SCALE_OUT_FINAL_TABLE_STATUS_DEBUG=" + finalTableStat + ")*/ "; } @@ -164,10 +164,10 @@ private void moveMultiDbs(List storageIDs) { if (StringUtils.isEmpty(finalTableStat) || ComplexTaskMetaManager.ComplexTaskStatus.PUBLIC.toString() .equalsIgnoreCase(finalTableStat)) { tddlSql = - "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true)*/ "; + "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, PHYSICAL_BACKFILL_ENABLE=false, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true)*/ "; } else { tddlSql = - "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, SCALE_OUT_FINAL_TABLE_STATUS_DEBUG=" + "move database /*+TDDL:CMD_EXTRA(SCALE_OUT_DEBUG=true, SHARE_STORAGE_MODE=true, PHYSICAL_BACKFILL_ENABLE=false, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, SCALE_OUT_FINAL_TABLE_STATUS_DEBUG=" + finalTableStat + ")*/ "; } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutCompleteTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutCompleteTest.java index 24dcd48b6..bc8e679f7 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutCompleteTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutCompleteTest.java @@ -34,6 +34,7 @@ import org.yaml.snakeyaml.Yaml; import net.jcip.annotations.NotThreadSafe; + import java.io.InputStream; import java.sql.Connection; import java.sql.PreparedStatement; @@ -157,7 +158,7 @@ protected static class ScaleOutTaskContext { public long workloadTime = 0; public String scaleOutHint = String.format( - "/*+TDDL:CMD_EXTRA(SHARE_STORAGE_MODE=true, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, SCALE_OUT_DEBUG_WAIT_TIME_IN_WO=%s,SCALEOUT_BACKFILL_BATCH_SIZE=2, SCALEOUT_BACKFILL_SPEED_LIMITATION=32)*/", + "/*+TDDL:CMD_EXTRA(SHARE_STORAGE_MODE=true, PHYSICAL_BACKFILL_ENABLE=false, SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE=true, SCALE_OUT_DEBUG_WAIT_TIME_IN_WO=%s,SCALEOUT_BACKFILL_BATCH_SIZE=2, SCALEOUT_BACKFILL_SPEED_LIMITATION=32)*/", String.valueOf(waitTimeEachDb)); public ScaleOutTaskContext() { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutPlanTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutPlanTest.java index 72529bb9d..a02656b31 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutPlanTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutPlanTest.java @@ -42,13 +42,13 @@ public class ScaleOutPlanTest extends ScaleOutBaseTest { private static List moveTableStatus = - Stream.of( - ComplexTaskMetaManager.ComplexTaskStatus.CREATING, - ComplexTaskMetaManager.ComplexTaskStatus.DELETE_ONLY, - ComplexTaskMetaManager.ComplexTaskStatus.WRITE_ONLY, - ComplexTaskMetaManager.ComplexTaskStatus.WRITE_REORG, - ComplexTaskMetaManager.ComplexTaskStatus.READY_TO_PUBLIC, - ComplexTaskMetaManager.ComplexTaskStatus.PUBLIC).collect(Collectors.toList()); + Stream.of( + ComplexTaskMetaManager.ComplexTaskStatus.CREATING, + ComplexTaskMetaManager.ComplexTaskStatus.DELETE_ONLY, + ComplexTaskMetaManager.ComplexTaskStatus.WRITE_ONLY, + ComplexTaskMetaManager.ComplexTaskStatus.WRITE_REORG, + ComplexTaskMetaManager.ComplexTaskStatus.READY_TO_PUBLIC, + ComplexTaskMetaManager.ComplexTaskStatus.PUBLIC).collect(Collectors.toList()); final ComplexTaskMetaManager.ComplexTaskStatus finalTableStatus; static boolean firstIn = true; static ComplexTaskMetaManager.ComplexTaskStatus currentStatus = ComplexTaskMetaManager.ComplexTaskStatus.CREATING; @@ -57,7 +57,7 @@ public class ScaleOutPlanTest extends ScaleOutBaseTest { public ScaleOutPlanTest(StatusInfo tableStatus) { super("ScaleOutPlanTest", "polardbx_meta_db_polardbx", - ImmutableList.of(tableStatus.getMoveTableStatus().toString())); + ImmutableList.of(tableStatus.getMoveTableStatus().toString())); finalTableStatus = tableStatus.getMoveTableStatus(); isCache = tableStatus.isCache(); if (!currentStatus.equals(finalTableStatus)) { @@ -84,9 +84,9 @@ public void tearDown() { public static List prepareData() { List status = new ArrayList<>(); moveTableStatus.stream().forEach(c -> { - status.add(new StatusInfo[] {new StatusInfo(c, false)}); - status.add(new StatusInfo[] {new StatusInfo(c, true)}); - status.add(new StatusInfo[] {new StatusInfo(c, null)}); + status.add(new StatusInfo[]{new StatusInfo(c, false)}); + status.add(new StatusInfo[]{new StatusInfo(c, true)}); + status.add(new StatusInfo[]{new StatusInfo(c, null)}); }); return status; } @@ -109,10 +109,10 @@ public void insertIgnorePushDownOnNonScaleOutGroup() { // shard on scaleout-group sql = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; // shard on non-scale out-group, should be pushdown sql2 = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { @@ -154,10 +154,10 @@ public void replacePushDownOnNonScaleOutGroup() { // shard on scaleout-group sql = - "replace into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + "replace into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; // shard on non-scaleout-group, should be pushdown sql2 = - "replace into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + "replace into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { @@ -198,10 +198,10 @@ public void updatePushDownOnNonScaleOutGroup() { String sql2 = ""; executeDml(sql); String insert1 = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; executeDml(insert1); String insert2 = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; executeDml(insert2); // shard on scaleout-group @@ -245,10 +245,10 @@ public void deletePushDownOnNonScaleOutGroup() { String sql2 = ""; executeDml(sql); String insert1 = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; executeDml(insert1); String insert2 = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; executeDml(insert2); // shard on scaleout-group @@ -282,12 +282,12 @@ public void tablePkNoUkForInsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert ignore into " + tableName - + "(a,b) values(1,1), (2,2), ((1+2), (2+1)), (4,4), (5,5),(6,6)"; - String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; + + "(a,b) values(1,1), (2,2), ((1+2), (2+1)), (4,4), (5,5),(6,6)"; + String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; if (isCache == null) { - hintStr = ""; + hintStr = " /*+TDDL:cmd_extra(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; } else if (isCache.booleanValue()) { - hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true)*/ "; + hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; } executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -295,29 +295,53 @@ public void tablePkNoUkForInsert() { int basePhyInsert = 6; if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + } } else if (finalTableStatus.isDeleteOnly()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size())); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size())); + } } else { //push insert ignore Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert)); } for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b) values(1,1)"; + + "(a,b) values(1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i * 2; if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isDeleteOnly()) { basePhyInsert = i; - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else { Assert.assertThat(trace.toString(), trace.size(), is(1)); } @@ -335,12 +359,12 @@ public void tablePkNoUkForInsertSelect() { sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + sourceTableName + " where 1=1"; executeDml(sql); sql = "insert ignore into " + sourceTableName - + "(a,b) values(1,1), (2,2), (( 3),( 3)), (4,4), (5,5),(6,6)"; - String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; + + "(a,b) values(1,1), (2,2), (( 3),( 3)), (4,4), (5,5),(6,6)"; + String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false, DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; if (isCache == null) { - hintStr = " /*+TDDL:cmd_extra(MERGE_UNION=false)*/ "; + hintStr = " /*+TDDL:cmd_extra(MERGE_UNION=false,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; } else if (isCache.booleanValue()) { - hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true,MERGE_UNION=false)*/ "; + hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true,MERGE_UNION=false, DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; } executeDml(hintStr + sql); sql = "insert ignore into " + tableName + "(a,b) select a,b+100 from " + sourceTableName; @@ -350,32 +374,59 @@ public void tablePkNoUkForInsertSelect() { int basePhyInsert = 6; if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size() + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size() + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + } } else if (finalTableStatus.isDeleteOnly()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size())); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size())); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size())); + } } else { //select + push upsert Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size())); } for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b) select a,( 1+2-2) from " + sourceTableName + " where a = 1+1-1"; + + "(a,b) select a,( 1+2-2) from " + sourceTableName + " where a = 1"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i * 2; if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + if (isCache == null) { + //1:select_for_update, 3:Select, 2:insert 1*2 + Assert.assertThat(trace.toString(), trace.size(), is(1 + 3 + 2)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(3 + topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + if (isCache == null) { + //1:select_for_update, 3:Select, 2:insert 1*2 + Assert.assertThat(trace.toString(), trace.size(), is(1 + 3 + 2)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(3 + topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isDeleteOnly()) { basePhyInsert = i; - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + if (isCache == null) { + //1:select_for_update, 3:Select, 1:insert + Assert.assertThat(trace.toString(), trace.size(), is(1 + 3 + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(3 + topology.size() + basePhyInsert)); + } } else { //select + push upsert - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + 1)); + Assert.assertThat(trace.toString(), trace.size(), is(3 + 1)); } sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); @@ -388,7 +439,7 @@ public void tableWithPkAndUkForInsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert ignore into " + tableName - + "(a,b,c) values(1,1,1), (1+1,2,2), (3,1+1*2,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (1+1,2,2), (3,1+1*2,3), (4,4,4), (5,5,5),(6,6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -413,7 +464,7 @@ public void tableWithPkAndUkForInsert() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b,c) values(1,1,1)"; + + "(a,b,c) values(1,1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -449,10 +500,10 @@ public void tableWithPkAndUkForInsertSelect() { hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true,MERGE_UNION=false)*/ "; } sql = "insert ignore into " + sourceTableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; executeDml(sql); sql = "insert ignore into " + tableName - + "(a,b,c) select a+1-1,b,c from " + sourceTableName; + + "(a,b,c) select a+1-1,b,c from " + sourceTableName; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); List> trace = getTrace(tddlConnection); @@ -471,20 +522,20 @@ public void tableWithPkAndUkForInsertSelect() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b,c) select a,b+1-1,c from " + sourceTableName + " where a=(select 1) and b<>2+100"; + + "(a,b,c) select a,b+1-1,c from " + sourceTableName + " where a=(select 1) and b<>2+100"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i * 2; if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { Assert.assertThat(trace.toString(), trace.size(), - is(scanForDuplicateCheck + topology.size() + basePhyInsert)); + is(scanForDuplicateCheck + topology.size() + basePhyInsert)); } else if (finalTableStatus.isReadyToPublic()) { Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + 2)); } else if (finalTableStatus.isDeleteOnly()) { basePhyInsert = i; Assert.assertThat(trace.toString(), trace.size(), - is(scanForDuplicateCheck + topology.size() + basePhyInsert)); + is(scanForDuplicateCheck + topology.size() + basePhyInsert)); } else { Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + 1)); } @@ -499,7 +550,7 @@ public void brdTablePkNoUkForInsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert ignore into " + tableName - + "(a,b) values(1,1), (1+1,2), (3,3), (2+2,4), (5,5),(6,6)"; + + "(a,b) values(1,1), (1+1,2), (3,3), (2+2,4), (5,5),(6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -525,7 +576,7 @@ public void brdTablePkNoUkForInsert() { } for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b) values(1+1-1,1)"; + + "(a,b) values(1+1-1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -557,7 +608,7 @@ public void brdTablePkNoUkForInsertSelect() { executeDml(sql); sql = "insert ignore into " + sourceTableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -566,7 +617,7 @@ public void brdTablePkNoUkForInsertSelect() { } executeDml(hintStr + sql); sql = "insert ignore into " + tableName - + "(a,b) select a+1-1,b+20 from " + sourceTableName + " where a<> ( 1000)"; + + "(a,b) select a+1-1,b+20 from " + sourceTableName + " where a<> ( 1000)"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -588,7 +639,7 @@ public void brdTablePkNoUkForInsertSelect() { } for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b) select a+1-1,b+1 from " + sourceTableName + " where a=( 1)"; + + "(a,b) select a+1-1,b+1 from " + sourceTableName + " where a=( 1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -600,7 +651,7 @@ public void brdTablePkNoUkForInsertSelect() { } else if (finalTableStatus.isDeleteOnly()) { basePhyInsert = i > 0 ? i * physicalDbCount : 0; Assert - .assertThat(trace.toString(), trace.size(), is(topology.size() + topology.size() + basePhyInsert)); + .assertThat(trace.toString(), trace.size(), is(topology.size() + topology.size() + basePhyInsert)); } else if (finalTableStatus.isPublic()) { Assert.assertThat(trace.toString(), trace.size(), is(physicalDbCount + topology.size() + 1)); } else { @@ -618,7 +669,7 @@ public void brdTableWithPkAndUkForInsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert ignore into " + tableName - + "(a,b,c) values(1+1-1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,3+2+1-1+1)"; + + "(a,b,c) values(1+1-1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,3+2+1-1+1)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -644,7 +695,7 @@ public void brdTableWithPkAndUkForInsert() { } for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b,c) values(1,1,1)"; + + "(a,b,c) values(1,1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -675,7 +726,7 @@ public void brdTableWithPkAndUkForInsertSelect() { executeDml(sql); sql = "insert ignore into " + sourceTableName - + "(a,b,c) values( 1+1-1, 1, 1), (2,2,2), (3, 3,3), (4,4,4), (5,5,5),(3+6-3,6,6)"; + + "(a,b,c) values( 1+1-1, 1, 1), (2,2,2), (3, 3,3), (4,4,4), (5,5,5),(3+6-3,6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; if (isCache == null) { hintStr = " /*+TDDL:cmd_extra(MERGE_UNION=false)*/ "; @@ -685,7 +736,7 @@ public void brdTableWithPkAndUkForInsertSelect() { executeDml(hintStr + sql); sql = "insert ignore into " + tableName - + "(a,b,c) select a+1-1,b+1-1,c from " + sourceTableName + " where a<>2000 and b<1+2+2000"; + + "(a,b,c) select a+1-1,b+1-1,c from " + sourceTableName + " where a<>2000 and b<1+2+2000"; executeDml("trace " + hintStr + sql); int physicalDbCount = getDataSourceCount() - 1 - 1; //minus metaDb and scaleout target db final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -705,7 +756,7 @@ public void brdTableWithPkAndUkForInsertSelect() { } for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b,c) select a+1-1,b,c+1-1 from " + sourceTableName + " where a=1 and b<>1+9999+32"; + + "(a,b,c) select a+1-1,b,c+1-1 from " + sourceTableName + " where a=1 and b<>1+9999+32"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -716,7 +767,7 @@ public void brdTableWithPkAndUkForInsertSelect() { Assert.assertThat(trace.toString(), trace.size(), is(physicalDbCount + 1 + 1)); } else if (finalTableStatus.isDeleteOnly()) { Assert.assertThat(trace.toString(), trace.size(), - is(topology.size() * 2 + (i == 0 ? 0 : physicalDbCount))); + is(topology.size() * 2 + (i == 0 ? 0 : physicalDbCount))); } else if ((finalTableStatus.isPublic())) { Assert.assertThat(trace.toString(), trace.size(), is(physicalDbCount + 2)); } else { @@ -733,12 +784,12 @@ public void tablePkNoUkForReplace() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "replace into " + tableName - + "(a,b) values(1+1-1,1), (2,2), (3,3), (4,4), (5,5),(6,6+8-8)"; - String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; + + "(a,b) values(1+1-1,1), (2,2), (3,3), (4,4), (5,5),(6,6+8-8)"; + String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; if (isCache == null) { - hintStr = ""; + hintStr = " /*+TDDL:cmd_extra(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; } else if (isCache.booleanValue()) { - hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true)*/ "; + hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; } executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -746,30 +797,54 @@ public void tablePkNoUkForReplace() { int basePhyInsert = 6; if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + } } else if (finalTableStatus.isDeleteOnly()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size())); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size())); + } } else { //push replace Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert)); } for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b) values(1+1-1,1)"; + + "(a,b) values(1+1-1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 4 : 2); //4:(delete + insert) * 2 if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isReadyToPublic()) { basePhyInsert = 2; //(replace) * 2 or (insert) * 2 - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isDeleteOnly()) { basePhyInsert = (i == 0 ? 3 : 1); //3:(delete + insert) + delete - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else { //push replace Assert.assertThat(trace.toString(), trace.size(), is(1)); @@ -780,18 +855,30 @@ public void tablePkNoUkForReplace() { } } sql = "replace into " + tableName - + "(a,b) values(1,2)"; + + "(a,b) values(1,2)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = 4; //4:(delete + insert) * 2 if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(1 + 2)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(1 + 2)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isDeleteOnly()) { basePhyInsert = 3; //3:(delete + insert) + delete - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(1 + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else { //push replace Assert.assertThat(trace.toString(), trace.size(), is(1)); @@ -809,17 +896,17 @@ public void tablePkNoUkForReplaceSelect() { executeDml(sql); sql = "replace into " + sourceTableName - + "(a,b) values(1+1-1,1), (2,2+1-1), (3,3), (4,4), (5,5),(6,6+1-1)"; - String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; + + "(a,b) values(1+1-1,1), (2,2+1-1), (3,3), (4,4), (5,5),(6,6+1-1)"; + String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false, DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; if (isCache == null) { - hintStr = " /*+TDDL:cmd_extra(MERGE_UNION=false)*/ "; + hintStr = " /*+TDDL:cmd_extra(MERGE_UNION=false,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; } else if (isCache.booleanValue()) { - hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true,MERGE_UNION=false)*/ "; + hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true,MERGE_UNION=false, DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; } executeDml(hintStr + sql); sql = "replace into " + tableName - + "(a,b) select a,b+20 from " + sourceTableName + " where b<>( 200+321)"; + + "(a,b) select a,b+20 from " + sourceTableName + " where b<>( 200+321)"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -827,56 +914,73 @@ public void tablePkNoUkForReplaceSelect() { int basePhyInsert = 6; if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size() + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size() + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + } } else if (finalTableStatus.isDeleteOnly()) { //select + insert - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size())); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size())); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size())); + } } else { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size())); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size())); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size())); + } } for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b) select a+1-1,b from " + sourceTableName + " where a=1+1+2-3 and b<>( 1234+3456)"; + + "(a,b) select a+1-1,b from " + sourceTableName + " where a=1 and b<>( 1234+3456)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); - basePhyInsert = (i == 0 ? 4 : 2); //4:(delete + insert) * 2 + basePhyInsert = 2; //not delete if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + if (isCache == null) { + //1:select_for_update, 3:Select + Assert.assertThat(trace.toString(), trace.size(), is(1 + 3 + basePhyInsert)); + } else { + basePhyInsert = i == 0 ? 4 : 2; + Assert.assertThat(trace.toString(), trace.size(), is(3 + topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isReadyToPublic()) { //basePhyInsert = 2; //(replace) * 2 or (insert) * 2 - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + if (isCache == null) { + //1:select_for_update, 3:Select + Assert.assertThat(trace.toString(), trace.size(), is(1 + 3 + basePhyInsert)); + } else { + basePhyInsert = i == 0 ? 4 : 2; + Assert.assertThat(trace.toString(), trace.size(), is(3 + topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isDeleteOnly()) { basePhyInsert = (i == 0 ? 3 : 1); //3:(delete + insert) + delete - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + if (isCache == null) { + //1:select_for_update, 3:Select + basePhyInsert = 1;//not delete + Assert.assertThat(trace.toString(), trace.size(), is(1 + 3 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(3 + topology.size() + basePhyInsert)); + } } else { //push replace - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + 1)); + Assert.assertThat(trace.toString(), trace.size(), is(3 + 1)); } if (i == 0) { sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); } } - sql = "replace into " + tableName - + "(a,b) select a,b+1 from " + sourceTableName + " where a=1"; - executeDml("trace " + hintStr + sql); - trace = getTrace(tddlConnection); - - basePhyInsert = 4; //4:(delete + insert) * 2 - if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + topology.size() + basePhyInsert)); - } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + topology.size() + basePhyInsert)); - } else if (finalTableStatus.isDeleteOnly()) { - basePhyInsert = 3; //3:(delete + insert) + delete - Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + topology.size() + basePhyInsert)); - } else { - //select + replace - Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + 1)); - } } @Test @@ -885,7 +989,7 @@ public void tablePkAndUkForReplace() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "replace into " + tableName - + "(a,b,c) values(1+1-1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5+1-1),(6,6,6)"; + + "(a,b,c) values(1+1-1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5+1-1),(6,6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -910,7 +1014,7 @@ public void tablePkAndUkForReplace() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b,c) values(1+1-1,1,1)"; + + "(a,b,c) values(1+1-1,1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -932,7 +1036,7 @@ public void tablePkAndUkForReplace() { } } sql = "replace into " + tableName - + "(a,b,c) values(1,1,3)"; + + "(a,b,c) values(1,1,3)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -960,7 +1064,7 @@ public void tablePkAndUkForReplaceSelect() { executeDml(sql); sql = "replace into " + sourceTableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; if (isCache == null) { hintStr = " /*+TDDL:cmd_extra(MERGE_UNION=false)*/ "; @@ -970,8 +1074,8 @@ public void tablePkAndUkForReplaceSelect() { executeDml(hintStr + sql); sql = "replace into " + tableName - + "(a,b,c) select 3+a-3,b+1-1,c+2-2 from " + sourceTableName - + " where a<1000 and b<>( 1+3333+21-1*2)"; + + "(a,b,c) select 3+a-3,b+1-1,c+2-2 from " + sourceTableName + + " where a<1000 and b<>( 1+3333+21-1*2)"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -990,21 +1094,21 @@ public void tablePkAndUkForReplaceSelect() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b,c) select a+1*2-2,1+b-1,c+2-2 from " + sourceTableName + " where a=( 1)"; + + "(a,b,c) select a+1*2-2,1+b-1,c+2-2 from " + sourceTableName + " where a=( 1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 4 : 2); //4:(delete + insert) * 2 if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { Assert.assertThat(trace.toString(), trace.size(), - is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); + is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); } else if (finalTableStatus.isReadyToPublic()) { basePhyInsert = 2; //(replace) * 2 Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + basePhyInsert)); } else if (finalTableStatus.isDeleteOnly()) { basePhyInsert = (i == 0 ? 3 : 1); //3:(delete + insert) + delete Assert.assertThat(trace.toString(), trace.size(), - is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); + is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); } else { Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + 1)); } @@ -1014,21 +1118,21 @@ public void tablePkAndUkForReplaceSelect() { } } sql = "replace into " + tableName - + "(a,b,c) select a+1-1,b,c+2 from " + sourceTableName + " where a=(select 1) and c<>( 34567)"; + + "(a,b,c) select a+1-1,b,c+2 from " + sourceTableName + " where a=(select 1) and c<>( 34567)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = 4; //4:(delete + insert) * 2 if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { Assert.assertThat(trace.toString(), trace.size(), - is(topology.size() + scanForDuplicateCheck + basePhyInsert)); + is(topology.size() + scanForDuplicateCheck + basePhyInsert)); } else if (finalTableStatus.isReadyToPublic()) { //select + push replace Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + 1 + 1)); } else if (finalTableStatus.isDeleteOnly()) { basePhyInsert = 3; //3:(delete + insert) + delete Assert.assertThat(trace.toString(), trace.size(), - is(topology.size() + scanForDuplicateCheck + basePhyInsert)); + is(topology.size() + scanForDuplicateCheck + basePhyInsert)); } else { //select + push replace Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + 1)); @@ -1041,7 +1145,7 @@ public void brdTablePkNoUkForReplace() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "replace into " + tableName - + "(a,b) values(1,1), (2,2+1-1), (3,3), (4,4), (5,5),(6,6)"; + + "(a,b) values(1,1), (2,2+1-1), (3,3), (4,4), (5,5),(6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -1067,7 +1171,7 @@ public void brdTablePkNoUkForReplace() { } for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b) values(1,1)"; + + "(a,b) values(1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1090,7 +1194,7 @@ public void brdTablePkNoUkForReplace() { } } sql = "replace into " + tableName - + "(a,b) values(1+1-1,2)"; + + "(a,b) values(1+1-1,2)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1120,7 +1224,7 @@ public void brdTablePkNoUkForReplaceSelect() { executeDml(sql); sql = "replace into " + sourceTableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -1130,7 +1234,7 @@ public void brdTablePkNoUkForReplaceSelect() { executeDml(hintStr + sql); sql = "replace into " + tableName - + "(a,b) select a+1-1,b+1-1 from " + sourceTableName + " where 1=1 and a<>1+23456"; + + "(a,b) select a+1-1,b+1-1 from " + sourceTableName + " where 1=1 and a<>1+23456"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); List> trace = getTrace(tddlConnection); @@ -1150,7 +1254,7 @@ public void brdTablePkNoUkForReplaceSelect() { } for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b) select a,b from " + sourceTableName + " where 2=2 and a=1+1-1"; + + "(a,b) select a,b from " + sourceTableName + " where 2=2 and a=1+1-1"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1173,7 +1277,7 @@ public void brdTablePkNoUkForReplaceSelect() { } } sql = "replace into " + tableName - + "(a,b) select a,b+1 from " + sourceTableName + " where a=1 and 2=2"; + + "(a,b) select a,b+1 from " + sourceTableName + " where a=1 and 2=2"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1198,7 +1302,7 @@ public void brdTablePkAndUkForReplace() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/ delete from " + tableName + " where 1=1"; executeDml(sql); sql = "replace into " + tableName - + "(a,b,c) values(1,1,1+1-1), (2,2,2), (3,3+1-1,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1+1-1), (2,2,2), (3,3+1-1,3), (4,4,4), (5,5,5),(6,6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -1224,7 +1328,7 @@ public void brdTablePkAndUkForReplace() { } for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b,c) values(1+1-1,1,1)"; + + "(a,b,c) values(1+1-1,1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1247,7 +1351,7 @@ public void brdTablePkAndUkForReplace() { } } sql = "replace into " + tableName - + "(a,b,c) values(1,1+1-1,2)"; + + "(a,b,c) values(1,1+1-1,2)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1277,7 +1381,7 @@ public void brdTablePkAndUkForReplaceSelect() { executeDml(sql); sql = "replace into " + sourceTableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -1287,7 +1391,7 @@ public void brdTablePkAndUkForReplaceSelect() { executeDml("trace " + hintStr + sql); sql = "replace into " + tableName - + "(a,b,c) select a+1-1,b+1-1,c+2-2 from " + sourceTableName + " where a<>1 or 1=1"; + + "(a,b,c) select a+1-1,b+1-1,c+2-2 from " + sourceTableName + " where a<>1 or 1=1"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -1308,7 +1412,7 @@ public void brdTablePkAndUkForReplaceSelect() { } for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b,c) select a,b,c from " + sourceTableName + " where a=1 and 2+1=3"; + + "(a,b,c) select a,b,c from " + sourceTableName + " where a=1 and 2+1=3"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1331,7 +1435,7 @@ public void brdTablePkAndUkForReplaceSelect() { } } sql = "replace into " + tableName - + "(a,b,c) select a,b,c+1 from " + sourceTableName + " where a=1 and (2=1 or 2=2)"; + + "(a,b,c) select a,b,c+1 from " + sourceTableName + " where a=1 and (2=1 or 2=2)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1362,31 +1466,31 @@ public void tablePkNoUkForDelete() { } else if (isCache.booleanValue()) { hint = " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,PLAN_CACHE=true)*/ "; } - String[] sqlList = new String[] { - "delete from " + tableName + " where 1=1", - "delete from " + tableName + " where a < 300", - "delete from " + tableName + " where a = 1", - "delete from " + tableName + " where b=1", - "delete from " + tableName + " where a = 1 and b=1", - "delete from " + tableName + " where 1=1 order by a limit 6",}; + String[] sqlList = new String[]{ + "delete from " + tableName + " where 1=1", + "delete from " + tableName + " where a < 300", + "delete from " + tableName + " where a = 1", + "delete from " + tableName + " where b=1", + "delete from " + tableName + " where a = 1 and b=1", + "delete from " + tableName + " where 1=1 order by a limit 6",}; //{6, 2, 1, 1, 1, 1, 1} List> trace; final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); int dbCount = getDataSourceCount() - 1 - 1 - 1;//minus metadb+scaleoutdb + singledb - int[] scans = new int[] {dbCount, dbCount, 1, dbCount, 1, dbCount}; + int[] scans = new int[]{dbCount, dbCount, 1, dbCount, 1, dbCount}; int[] writablePhysicalOperations = - new int[] {6, 6, 1, 1, 1, 6}; + new int[]{6, 6, 1, 1, 1, 6}; int[] readyToPublishPhysicalOperations = - new int[] { - dbCount + 6 + 1, dbCount + 6 + 1, 1 + 1 + 1, dbCount + 1 + 1, 1 + 1 + 1, dbCount + 6 + 1}; + new int[]{ + dbCount + 6 + 1, dbCount + 6 + 1, 1 + 1 + 1, dbCount + 1 + 1, 1 + 1 + 1, dbCount + 6 + 1}; int[] otherPhysicalOperations = - new int[] {topology.size(), topology.size(), 1 * 3, dbCount, 1, dbCount + 6}; + new int[]{topology.size(), topology.size(), 1 * 3, dbCount, 1, dbCount + 6}; int[] publishPhysicalOperations = - new int[] {topology.size(), topology.size(), 1 * 3, dbCount + 1, 1, dbCount + 1 + 6}; + new int[]{topology.size(), topology.size(), 1 * 3, dbCount + 1, 1, dbCount + 1 + 6}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = writablePhysicalOperations[i]; @@ -1423,34 +1527,34 @@ public void tablePkAndUkForDelete() { } else if (isCache.booleanValue()) { hint = " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,PLAN_CACHE=true)*/ "; } - String[] sqlList = new String[] { - "delete from " + tableName + " where 1=1", - "delete from " + tableName + " where a < 300", - "delete from " + tableName + " where a = 1", - "delete from " + tableName + " where b=1", - "delete from " + tableName + " where c=1", - "delete from " + tableName + " where a = 1 and b=1", - "delete from " + tableName + " where a = 1 and b=1 and c=1", - "delete from " + tableName + " where 1=1 order by a limit 6",}; + String[] sqlList = new String[]{ + "delete from " + tableName + " where 1=1", + "delete from " + tableName + " where a < 300", + "delete from " + tableName + " where a = 1", + "delete from " + tableName + " where b=1", + "delete from " + tableName + " where c=1", + "delete from " + tableName + " where a = 1 and b=1", + "delete from " + tableName + " where a = 1 and b=1 and c=1", + "delete from " + tableName + " where 1=1 order by a limit 6",}; //{6, 2, 1, 1, 1, 1, 1} List> trace; final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); int dbCount = getDataSourceCount() - 1 - 1 - 1;//minus metadb+scaleoutdb + singledb - int[] scans = new int[] {dbCount, dbCount, 1, dbCount, dbCount, 1, 1, dbCount}; + int[] scans = new int[]{dbCount, dbCount, 1, dbCount, dbCount, 1, 1, dbCount}; int[] writablePhysicalOperations = - new int[] {6, 6, 1, 1, 1, 1, 1, 6}; + new int[]{6, 6, 1, 1, 1, 1, 1, 6}; int[] readyToPublishPhysicalOperations = - new int[] { - dbCount + 6 + 1, dbCount + 6 + 1, 1 + 1 + 1, dbCount + 1 + 1, dbCount + 1 + 1, - 1 + 1 + 1, 1 + 1 + 1, dbCount + 6 + 1}; + new int[]{ + dbCount + 6 + 1, dbCount + 6 + 1, 1 + 1 + 1, dbCount + 1 + 1, dbCount + 1 + 1, + 1 + 1 + 1, 1 + 1 + 1, dbCount + 6 + 1}; int[] otherPhysicalOperations = - new int[] {topology.size(), topology.size(), 1 * 3, dbCount, topology.size(), 1, 1, dbCount + 6}; + new int[]{topology.size(), topology.size(), 1 * 3, dbCount, topology.size(), 1, 1, dbCount + 6}; int[] publishPhysicalOperations = - new int[] {topology.size(), topology.size(), 1 * 3, dbCount + 1, topology.size(), 1, 1, dbCount + 1 + 6}; + new int[]{topology.size(), topology.size(), 1 * 3, dbCount + 1, topology.size(), 1, 1, dbCount + 1 + 6}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = writablePhysicalOperations[i]; @@ -1487,23 +1591,23 @@ public void brdTablePkNoUkForDelete() { } else if (isCache.booleanValue()) { hint = " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,PLAN_CACHE=true)*/ "; } - String[] sqlList = new String[] { - "delete from " + tableName + " where 1=1", - "delete from " + tableName + " where a < 300", - "delete from " + tableName + " where a = 2", - "delete from " + tableName + " where b=1", - "delete from " + tableName + " where a = 1 and b=1", - "delete from " + tableName + " where 1=1 order by a limit 6",}; + String[] sqlList = new String[]{ + "delete from " + tableName + " where 1=1", + "delete from " + tableName + " where a < 300", + "delete from " + tableName + " where a = 2", + "delete from " + tableName + " where b=1", + "delete from " + tableName + " where a = 1 and b=1", + "delete from " + tableName + " where 1=1 order by a limit 6",}; //{6, 2, 1, 1, 1, 1, 1} List> trace; int brdDbCount = getDataSourceCount() - 1 - 1;//minus metadb+scaleoutdb - int[] scans = new int[] {1, 1, 1, 1, 1, 1, 1}; + int[] scans = new int[]{1, 1, 1, 1, 1, 1, 1}; int[] physicalOperations = - new int[] {brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount}; + new int[]{brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = physicalOperations[i]; @@ -1538,25 +1642,25 @@ public void brdTablePkAndUkForDelete() { } else if (isCache.booleanValue()) { hint = " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,PLAN_CACHE=true)*/ "; } - String[] sqlList = new String[] { - "delete from " + tableName + " where 1=1", - "delete from " + tableName + " where a < 300", - "delete from " + tableName + " where a = 2", - "delete from " + tableName + " where b=1", - "delete from " + tableName + " where c=1", - "delete from " + tableName + " where a = 1 and b=1", - "delete from " + tableName + " where a = 1 and b=1 and c=1", - "delete from " + tableName + " where 1=1 order by a limit 6",}; + String[] sqlList = new String[]{ + "delete from " + tableName + " where 1=1", + "delete from " + tableName + " where a < 300", + "delete from " + tableName + " where a = 2", + "delete from " + tableName + " where b=1", + "delete from " + tableName + " where c=1", + "delete from " + tableName + " where a = 1 and b=1", + "delete from " + tableName + " where a = 1 and b=1 and c=1", + "delete from " + tableName + " where 1=1 order by a limit 6",}; //{6, 2, 1, 1, 1, 1, 1} List> trace; int brdDbCount = getDataSourceCount() - 1 - 1;//minus metadb+scaleoutdb - int[] scans = new int[] {1, 1, 1, 1, 1, 1, 1, 1}; + int[] scans = new int[]{1, 1, 1, 1, 1, 1, 1, 1}; int[] physicalOperations = - new int[] {brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount}; + new int[]{brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = physicalOperations[i]; @@ -1586,77 +1690,77 @@ public void tablePkNoUkForUpdate() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName; executeDml(sql); String hint = - "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; + "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; if (isCache == null) { hint = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE)*/ "; } else if (isCache.booleanValue()) { hint = - " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=true)*/ "; - } - - String[] sqlList = new String[] { - "update " + tableName + " set k=k+1", - "update " + tableName + " set k=k+1 where a=1", - "update " + tableName + " set k=k+1 where a=1 and b=1", - "update " + tableName + " set k=k+1 where b=1", - "update " + tableName + " set a=a-1 where a<100",//5 - "update " + tableName + " set b=b-1 where a<100", - "update " + tableName + " set b=b-1,a=a-1 where b<100", - "update " + tableName + " set a=a-1 where a=1", - "update " + tableName + " set b=b-1 where a=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 - "update " + tableName + " set a=a-1 where a=1 and b=1", - "update " + tableName + " set b=b-1 where a=1 and b=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", - "update " + tableName + " set a=a-1 where b=1", - "update " + tableName + " set b=b-1 where b=1",//15 - "update " + tableName + " set b=b-1,a=a-1 where b=1", - "update " + tableName + " set k=k+1 order by a limit 6", - "update " + tableName + " set a=a-1 where a<>3 order by a limit 6", - "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6",}; + " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=true)*/ "; + } + + String[] sqlList = new String[]{ + "update " + tableName + " set k=k+1", + "update " + tableName + " set k=k+1 where a=1", + "update " + tableName + " set k=k+1 where a=1 and b=1", + "update " + tableName + " set k=k+1 where b=1", + "update " + tableName + " set a=a-1 where a<100",//5 + "update " + tableName + " set b=b-1 where a<100", + "update " + tableName + " set b=b-1,a=a-1 where b<100", + "update " + tableName + " set a=a-1 where a=1", + "update " + tableName + " set b=b-1 where a=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 + "update " + tableName + " set a=a-1 where a=1 and b=1", + "update " + tableName + " set b=b-1 where a=1 and b=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", + "update " + tableName + " set a=a-1 where b=1", + "update " + tableName + " set b=b-1 where b=1",//15 + "update " + tableName + " set b=b-1,a=a-1 where b=1", + "update " + tableName + " set k=k+1 order by a limit 6", + "update " + tableName + " set a=a-1 where a<>3 order by a limit 6", + "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6",}; List> trace; final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); int dbCount = getDataSourceCount() - 1 - 1 - 1;//minus metadb+scaleoutdb + singledb int[] scans = - new int[] { - dbCount, 1, 1, dbCount, dbCount, - dbCount, dbCount, 1, 1, 1, - 1, 1, 1, dbCount, dbCount, - dbCount, dbCount, dbCount, 1}; + new int[]{ + dbCount, 1, 1, dbCount, dbCount, + dbCount, dbCount, 1, 1, 1, + 1, 1, 1, dbCount, dbCount, + dbCount, dbCount, dbCount, 1}; int[] writablePhysicalOperations = - new int[] { - 6 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + 1 + 1, - 6 * 2 + 1 + 1, 6 * 2 + 1 + 1, 1 * 2 + 1, 1 * 2 + 2, 1 * 2 + 1, - 1 * 2 + 1, 1 * 2 + 2, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 2, - 1 * 2 + 1, 6 + 1, 5 * 2 + 2, 1 + 1}; + new int[]{ + 6 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + 1 + 1, + 6 * 2 + 1 + 1, 6 * 2 + 1 + 1, 1 * 2 + 1, 1 * 2 + 2, 1 * 2 + 1, + 1 * 2 + 1, 1 * 2 + 2, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 2, + 1 * 2 + 1, 6 + 1, 5 * 2 + 2, 1 + 1}; int[] readyToPublishPhysicalOperations = - new int[] { - dbCount + 6 + 1, 1 + 1 + 1, 1 + 1 + 1, dbCount + 1 + 1, dbCount + 6 * 2 + 2, - dbCount + 6 * 2 + 2, dbCount + 6 * 2 + 2, 1 + 1 * 2 + 1, 1 + 1 * 2 + 2, 1 + 1 * 2 + 1, - 1 + 1 * 2 + 1, 1 + 1 * 2 + 2, 1 + 1 * 2 + 1, dbCount + 1 * 2 + 1, dbCount + 1 * 2 + 2, - dbCount + 1 * 2 + 1, dbCount + 6 + 1, dbCount + 5 * 2 + 2, 1 + 1 + 1}; + new int[]{ + dbCount + 6 + 1, 1 + 1 + 1, 1 + 1 + 1, dbCount + 1 + 1, dbCount + 6 * 2 + 2, + dbCount + 6 * 2 + 2, dbCount + 6 * 2 + 2, 1 + 1 * 2 + 1, 1 + 1 * 2 + 2, 1 + 1 * 2 + 1, + 1 + 1 * 2 + 1, 1 + 1 * 2 + 2, 1 + 1 * 2 + 1, dbCount + 1 * 2 + 1, dbCount + 1 * 2 + 2, + dbCount + 1 * 2 + 1, dbCount + 6 + 1, dbCount + 5 * 2 + 2, 1 + 1 + 1}; int[] otherPhysicalOperations = - new int[] { - topology.size(), 3, 1, dbCount, dbCount + 6 * 2, - dbCount + 6 * 2, dbCount + 6 * 2, 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, - 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, dbCount + 1 * 2, dbCount + 1 * 2, - dbCount + 1 * 2, dbCount + 6, dbCount + 5 * 2, 1}; + new int[]{ + topology.size(), 3, 1, dbCount, dbCount + 6 * 2, + dbCount + 6 * 2, dbCount + 6 * 2, 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, + 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, dbCount + 1 * 2, dbCount + 1 * 2, + dbCount + 1 * 2, dbCount + 6, dbCount + 5 * 2, 1}; int[] publishPhysicalOperations = - new int[] { - topology.size(), 3, 1, dbCount + 1, dbCount + 1 + 6 * 2, - dbCount + 1 + 6 * 2, dbCount + 1 + 6 * 2, 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, - 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, dbCount + 1 + 1 * 2, dbCount + 1 + 1 * 2, - dbCount + 1 + 1 * 2, dbCount + 1 + 6, dbCount + 1 + 5 * 2, 1}; + new int[]{ + topology.size(), 3, 1, dbCount + 1, dbCount + 1 + 6 * 2, + dbCount + 1 + 6 * 2, dbCount + 1 + 6 * 2, 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, + 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, dbCount + 1 + 1 * 2, dbCount + 1 + 1 * 2, + dbCount + 1 + 1 * 2, dbCount + 1 + 6, dbCount + 1 + 5 * 2, 1}; int[] deleteOnlyPhysicalOperations = - new int[] { - 6 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + 1, - 6 * 2 + 1, 6 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, - 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, - 1 * 2 + 1, 6 + 1, 5 * 2 + 1, 1 + 1}; + new int[]{ + 6 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + 1, + 6 * 2 + 1, 6 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, + 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, + 1 * 2 + 1, 6 + 1, 5 * 2 + 1, 1 + 1}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,k) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,k) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = writablePhysicalOperations[i]; @@ -1689,86 +1793,86 @@ public void tablePkAndUkForUpdate() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName; executeDml(sql); String hint = - "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; + "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; if (isCache == null) { hint = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE)*/ "; } else if (isCache.booleanValue()) { hint = - " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=true)*/ "; - } - String[] sqlList = new String[] { - "update " + tableName + " set k=k+1", - "update " + tableName + " set k=k+1 where a=1", - "update " + tableName + " set k=k+1 where a=1 and b=1", - "update " + tableName + " set k=k+1 where b=1", - "update " + tableName + " set a=a-1 where a<100",//5 - "update " + tableName + " set b=b-1 where a<100", - "update " + tableName + " set b=b-1,a=a-1 where b<100", - "update " + tableName + " set a=a-1 where a=1", - "update " + tableName + " set b=b-1 where a=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 - "update " + tableName + " set a=a-1 where a=1 and b=1", - "update " + tableName + " set b=b-1 where a=1 and b=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", - "update " + tableName + " set a=a-1 where b=1", - "update " + tableName + " set b=b-1 where b=1",//15 - "update " + tableName + " set b=b-1,a=a-1 where b=1", - "update " + tableName + " set k=k+1 order by a limit 6", - "update " + tableName + " set a=a-1 where a<>3 order by a limit 6", - "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6", - "update " + tableName + " set c=c-1 where b=1", - "update " + tableName + " set c=c-1 where a=1", + " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=true)*/ "; + } + String[] sqlList = new String[]{ + "update " + tableName + " set k=k+1", + "update " + tableName + " set k=k+1 where a=1", + "update " + tableName + " set k=k+1 where a=1 and b=1", + "update " + tableName + " set k=k+1 where b=1", + "update " + tableName + " set a=a-1 where a<100",//5 + "update " + tableName + " set b=b-1 where a<100", + "update " + tableName + " set b=b-1,a=a-1 where b<100", + "update " + tableName + " set a=a-1 where a=1", + "update " + tableName + " set b=b-1 where a=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 + "update " + tableName + " set a=a-1 where a=1 and b=1", + "update " + tableName + " set b=b-1 where a=1 and b=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", + "update " + tableName + " set a=a-1 where b=1", + "update " + tableName + " set b=b-1 where b=1",//15 + "update " + tableName + " set b=b-1,a=a-1 where b=1", + "update " + tableName + " set k=k+1 order by a limit 6", + "update " + tableName + " set a=a-1 where a<>3 order by a limit 6", + "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6", + "update " + tableName + " set c=c-1 where b=1", + "update " + tableName + " set c=c-1 where a=1", }; //{6, 2, 1, 1, 1, 1, 1} List> trace; final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); int dbCount = getDataSourceCount() - 1 - 1 - 1;//minus metadb+scaleoutdb + singledb int[] scans = - new int[] { - dbCount, 1, 1, dbCount, dbCount, - dbCount, dbCount, 1, 1, 1, - 1, 1, 1, dbCount, dbCount, - dbCount, dbCount, dbCount, 1, dbCount, - 1}; + new int[]{ + dbCount, 1, 1, dbCount, dbCount, + dbCount, dbCount, 1, 1, 1, + 1, 1, 1, dbCount, dbCount, + dbCount, dbCount, dbCount, 1, dbCount, + 1}; int[] writablePhysicalOperations = - new int[] { - 6 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + 1 + 1, - 6 * 2 + 1 + 1, 6 * 2 + 1 + 1, 1 * 2 + 1, 1 * 2 + 2, 1 * 2 + 1, - 1 * 2 + 1, 1 * 2 + 2, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 2, - 1 * 2 + 1, 6 + 1, 5 * 2 + 2, 1 + 1, 1 + 1, - 1 + 1}; + new int[]{ + 6 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + 1 + 1, + 6 * 2 + 1 + 1, 6 * 2 + 1 + 1, 1 * 2 + 1, 1 * 2 + 2, 1 * 2 + 1, + 1 * 2 + 1, 1 * 2 + 2, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 2, + 1 * 2 + 1, 6 + 1, 5 * 2 + 2, 1 + 1, 1 + 1, + 1 + 1}; int[] readyToPublishPhysicalOperations = - new int[] { - dbCount + 6 + 1, 1 + 1 + 1, 1 + 1 + 1, dbCount + 1 + 1, dbCount + 6 * 2 + 2, - dbCount + 6 * 2 + 2, dbCount + 6 * 2 + 2, 1 + 1 * 2 + 1, 1 + 1 * 2 + 2, 1 + 1 * 2 + 1, - 1 + 1 * 2 + 1, 1 + 1 * 2 + 2, 1 + 1 * 2 + 1, dbCount + 1 * 2 + 1, dbCount + 1 * 2 + 2, - dbCount + 1 * 2 + 1, dbCount + 6 + 1, dbCount + 5 * 2 + 2, 1 + 1 + 1, dbCount + 1 + 1, - 1 + 1 + 1}; + new int[]{ + dbCount + 6 + 1, 1 + 1 + 1, 1 + 1 + 1, dbCount + 1 + 1, dbCount + 6 * 2 + 2, + dbCount + 6 * 2 + 2, dbCount + 6 * 2 + 2, 1 + 1 * 2 + 1, 1 + 1 * 2 + 2, 1 + 1 * 2 + 1, + 1 + 1 * 2 + 1, 1 + 1 * 2 + 2, 1 + 1 * 2 + 1, dbCount + 1 * 2 + 1, dbCount + 1 * 2 + 2, + dbCount + 1 * 2 + 1, dbCount + 6 + 1, dbCount + 5 * 2 + 2, 1 + 1 + 1, dbCount + 1 + 1, + 1 + 1 + 1}; int[] otherPhysicalOperations = - new int[] { - topology.size(), 3, 1, dbCount, dbCount + 6 * 2, - dbCount + 6 * 2, dbCount + 6 * 2, 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, - 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, dbCount + 1 * 2, dbCount + 1 * 2, - dbCount + 1 * 2, dbCount + 6, dbCount + 5 * 2, 1, dbCount, - 3}; + new int[]{ + topology.size(), 3, 1, dbCount, dbCount + 6 * 2, + dbCount + 6 * 2, dbCount + 6 * 2, 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, + 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, dbCount + 1 * 2, dbCount + 1 * 2, + dbCount + 1 * 2, dbCount + 6, dbCount + 5 * 2, 1, dbCount, + 3}; int[] deleteOnlyPhysicalOperations = - new int[] { - 6 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + 1, - 6 * 2 + 1, 6 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, - 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, - 1 * 2 + 1, 6 + 1, 5 * 2 + 1, 1 + 1, 1 + 1, - 1 + 1}; + new int[]{ + 6 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + 1, + 6 * 2 + 1, 6 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, + 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, 1 * 2 + 1, + 1 * 2 + 1, 6 + 1, 5 * 2 + 1, 1 + 1, 1 + 1, + 1 + 1}; int[] publishPhysicalOperations = - new int[] { - topology.size(), 3, 1, dbCount + 1, dbCount + 1 + 6 * 2, - dbCount + 1 + 6 * 2, dbCount + 1 + 6 * 2, 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, - 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, dbCount + 1 + 1 * 2, dbCount + 1 + 1 * 2, - dbCount + 1 + 1 * 2, dbCount + 1 + 6, dbCount + 1 + 5 * 2, 1, dbCount + 1, - 3}; + new int[]{ + topology.size(), 3, 1, dbCount + 1, dbCount + 1 + 6 * 2, + dbCount + 1 + 6 * 2, dbCount + 1 + 6 * 2, 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, + 1 + 1 * 2, 1 + 1 * 2, 1 + 1 * 2, dbCount + 1 + 1 * 2, dbCount + 1 + 1 * 2, + dbCount + 1 + 1 * 2, dbCount + 1 + 6, dbCount + 1 + 5 * 2, 1, dbCount + 1, + 3}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,c,k) values(1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (5,5,5,5),(6,6,6,6)"; + + "(a,b,c,k) values(1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (5,5,5,5),(6,6,6,6)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = writablePhysicalOperations[i]; @@ -1801,74 +1905,74 @@ public void brdTablePkNoUkForUpdate() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName; executeDml(sql); String hint = - "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; + "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; if (isCache == null) { hint = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE)*/ "; } else if (isCache.booleanValue()) { hint = - " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=true)*/ "; - } - String[] sqlList = new String[] { - "update " + tableName + " set k=k+1", - "update " + tableName + " set k=k+1 where a=1", - "update " + tableName + " set k=k+1 where a=1 and b=1", - "update " + tableName + " set k=k+1 where b=1", - "update " + tableName + " set a=a-1 where a<100",//5 - "update " + tableName + " set b=b-1 where a<100", - "update " + tableName + " set b=b-1,a=a-1 where b<100", - "update " + tableName + " set a=a-1 where a=1", - "update " + tableName + " set b=b-1 where a=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 - "update " + tableName + " set a=a-1 where a=1 and b=1", - "update " + tableName + " set b=b-1 where a=1 and b=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", - "update " + tableName + " set a=a-1 where b=1", - "update " + tableName + " set b=b-1 where b=1",//15 - "update " + tableName + " set b=b-1,a=a-1 where b=1", - "update " + tableName + " set k=k+1 order by a limit 6", - "update " + tableName + " set a=a+10 where a<>3 order by a limit 6", - "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6",}; + " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=true)*/ "; + } + String[] sqlList = new String[]{ + "update " + tableName + " set k=k+1", + "update " + tableName + " set k=k+1 where a=1", + "update " + tableName + " set k=k+1 where a=1 and b=1", + "update " + tableName + " set k=k+1 where b=1", + "update " + tableName + " set a=a-1 where a<100",//5 + "update " + tableName + " set b=b-1 where a<100", + "update " + tableName + " set b=b-1,a=a-1 where b<100", + "update " + tableName + " set a=a-1 where a=1", + "update " + tableName + " set b=b-1 where a=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 + "update " + tableName + " set a=a-1 where a=1 and b=1", + "update " + tableName + " set b=b-1 where a=1 and b=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", + "update " + tableName + " set a=a-1 where b=1", + "update " + tableName + " set b=b-1 where b=1",//15 + "update " + tableName + " set b=b-1,a=a-1 where b=1", + "update " + tableName + " set k=k+1 order by a limit 6", + "update " + tableName + " set a=a+10 where a<>3 order by a limit 6", + "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6",}; //{6, 2, 1, 1, 1, 1, 1} List> trace; int brdDbCount = getDataSourceCount() - 1 - 1;//minus metadb+scaleoutdb int scan = 1; int[] writablePhysicalOperations = - new int[] { - scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, - scan + brdDbCount * 2 + 2, - scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, - scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, - scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount + 1}; + new int[]{ + scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, + scan + brdDbCount * 2 + 2, + scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, + scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, + scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount + 1}; int[] readyToPublishPhysicalOperations = - new int[] { - scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, - scan + brdDbCount * 2 + 2, - scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, - scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, - scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount + 1}; + new int[]{ + scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, + scan + brdDbCount * 2 + 2, + scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, + scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, + scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount + 1}; int[] otherPhysicalOperations = - new int[] { - brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, - brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, - brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, - brdDbCount, brdDbCount, brdDbCount, brdDbCount}; + new int[]{ + brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, + brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, + brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, + brdDbCount, brdDbCount, brdDbCount, brdDbCount}; int[] deleteOnlyPhysicalOperations = - new int[] { - scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, - scan + brdDbCount * 2 + 1, - scan + brdDbCount + 1, scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, - scan + brdDbCount + 1, scan + brdDbCount * 2 + 1, - scan + brdDbCount * 2 + 1, scan + brdDbCount + 1, scan + brdDbCount * 2 + 1, - scan + brdDbCount * 2 + 1, scan + brdDbCount + 1, - scan + brdDbCount * 2 + 1, scan + brdDbCount + 1, scan + brdDbCount * 2 + 1, scan + brdDbCount + 1}; + new int[]{ + scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, + scan + brdDbCount * 2 + 1, + scan + brdDbCount + 1, scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, + scan + brdDbCount + 1, scan + brdDbCount * 2 + 1, + scan + brdDbCount * 2 + 1, scan + brdDbCount + 1, scan + brdDbCount * 2 + 1, + scan + brdDbCount * 2 + 1, scan + brdDbCount + 1, + scan + brdDbCount * 2 + 1, scan + brdDbCount + 1, scan + brdDbCount * 2 + 1, scan + brdDbCount + 1}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,k) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,k) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = brdDbCount; @@ -1897,83 +2001,83 @@ public void brdTablePkAndUkForUpdate() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName; executeDml(sql); String hint = - "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; + "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; if (isCache == null) { hint = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE)*/ "; } else if (isCache.booleanValue()) { hint = - " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=true)*/ "; - } - String[] sqlList = new String[] { - "update " + tableName + " set k=k+1", - "update " + tableName + " set k=k+1 where a=1", - "update " + tableName + " set k=k+1 where a=1 and b=1", - "update " + tableName + " set k=k+1 where b=1", - "update " + tableName + " set a=a-1 where a<100",//5 - "update " + tableName + " set b=b-1 where a<100", - "update " + tableName + " set b=b-1,a=a-1 where b<100", - "update " + tableName + " set a=a-1 where a=1", - "update " + tableName + " set b=b-1 where a=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 - "update " + tableName + " set a=a-1 where a=1 and b=1", - "update " + tableName + " set b=b-1 where a=1 and b=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", - "update " + tableName + " set a=a-1 where b=1", - "update " + tableName + " set b=b-1 where b=1",//15 - "update " + tableName + " set b=b-1,a=a-1 where b=1", - "update " + tableName + " set k=k+1 order by a limit 6", - "update " + tableName + " set a=a+10 where a<>3 order by a limit 6", - "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6", - "update " + tableName + " set c=c-1 where b=1",//20 - "update " + tableName + " set c=c-1 where a=1", + " /*+TDDL:cmd_extra(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=true)*/ "; + } + String[] sqlList = new String[]{ + "update " + tableName + " set k=k+1", + "update " + tableName + " set k=k+1 where a=1", + "update " + tableName + " set k=k+1 where a=1 and b=1", + "update " + tableName + " set k=k+1 where b=1", + "update " + tableName + " set a=a-1 where a<100",//5 + "update " + tableName + " set b=b-1 where a<100", + "update " + tableName + " set b=b-1,a=a-1 where b<100", + "update " + tableName + " set a=a-1 where a=1", + "update " + tableName + " set b=b-1 where a=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 + "update " + tableName + " set a=a-1 where a=1 and b=1", + "update " + tableName + " set b=b-1 where a=1 and b=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", + "update " + tableName + " set a=a-1 where b=1", + "update " + tableName + " set b=b-1 where b=1",//15 + "update " + tableName + " set b=b-1,a=a-1 where b=1", + "update " + tableName + " set k=k+1 order by a limit 6", + "update " + tableName + " set a=a+10 where a<>3 order by a limit 6", + "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6", + "update " + tableName + " set c=c-1 where b=1",//20 + "update " + tableName + " set c=c-1 where a=1", }; List> trace; int brdDbCount = getDataSourceCount() - 1 - 1;//minus metadb+scaleoutdb int scan = 1; int[] writablePhysicalOperations = - new int[] { - scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, - scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, - scan + brdDbCount + 1, - scan + brdDbCount + 1}; + new int[]{ + scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, + scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, + scan + brdDbCount + 1, + scan + brdDbCount + 1}; int[] readyToPublishPhysicalOperations = - new int[] { - scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, - scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, - scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, - scan + brdDbCount + 1, - scan + brdDbCount + 1}; + new int[]{ + scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, + scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount * 2 + 2, + scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, scan + brdDbCount * 2 + 2, scan + brdDbCount + 1, + scan + brdDbCount + 1, + scan + brdDbCount + 1}; int[] otherPhysicalOperations = - new int[] { - brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, - brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, - brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, - brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, - brdDbCount}; + new int[]{ + brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, + brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, + brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, + brdDbCount, brdDbCount, brdDbCount, brdDbCount, brdDbCount, + brdDbCount}; int[] deleteOnlyPhysicalOperations = - new int[] { - scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, - scan + brdDbCount * 2 + 1, - scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, - scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, - scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, - scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, - scan + brdDbCount * 2 + 1, scan + brdDbCount + 1, scan + brdDbCount * 2 + 1, scan + brdDbCount + 1, - scan + brdDbCount + 1, - scan + brdDbCount + 1}; + new int[]{ + scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, scan + brdDbCount + 1, + scan + brdDbCount * 2 + 1, + scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, + scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, + scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, + scan + brdDbCount * 2 + 1, scan + brdDbCount * 2 + 1, + scan + brdDbCount * 2 + 1, scan + brdDbCount + 1, scan + brdDbCount * 2 + 1, scan + brdDbCount + 1, + scan + brdDbCount + 1, + scan + brdDbCount + 1}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,c,k) values(1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (5,5,5,5),(6,6,6,6)"; + + "(a,b,c,k) values(1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (5,5,5,5),(6,6,6,6)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = brdDbCount; @@ -2005,12 +2109,12 @@ public void tablePkNoUkForUpsert() { executeDml(sql); sql = "insert into " + tableName - + "(a,b) values(1,1), (2,2), (3,3), (4-2+2,4), (5,5),(9+6-9,6) on duplicate key update b=b+1+3"; - String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; + + "(a,b) values(1,1), (2,2), (3,3), (4-2+2,4), (5,5),(9+6-9,6) on duplicate key update b=b+1+3"; + String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; if (isCache == null) { - hintStr = ""; + hintStr = "/*+TDDL:cmd_extra(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/"; } else if (isCache.booleanValue()) { - hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true)*/ "; + hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; } executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -2019,32 +2123,69 @@ public void tablePkNoUkForUpsert() { int shrdDbCount = getDataSourceCount() - 1 - 1 - 1;//minus metadb+scaleoutdb+singledb int basePhyInsert = 6; if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 1)); + } + } else if (finalTableStatus.isDeleteOnly()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size())); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else { //select_for_duplicate + insert - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b) values(1,1+1-1) on duplicate key update b=b+1+3"; + + "(a,b) values(1,1+1-1) on duplicate key update b=b+1+3"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i == 0 ? 4 : 2; if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isDeleteOnly()) { - // 3:2*delete + insert; 1: insert - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + (i == 0 ? 3 : 1))); + if (isCache == null) { + // 3:2*delete + insert; 1: insert + Assert.assertThat(trace.toString(), trace.size(), is(1 + (i == 0 ? 3 : 1))); + } else { + // 3:2*delete + insert; 1: insert + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + (i == 0 ? 3 : 1))); + } + } else { //select_for_duplicate + insert - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + (i == 0 ? 2 : 1))); + if (isCache == null) { + // 3:2*delete + insert; 1: insert + Assert.assertThat(trace.toString(), trace.size(), is(1 + (i == 0 ? 2 : 1))); + } else { + // 3:2*delete + insert; 1: insert + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + (i == 0 ? 2 : 1))); + } } if (i == 0) { sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; @@ -2052,21 +2193,42 @@ public void tablePkNoUkForUpsert() { } } sql = "insert into " + tableName - + "(a,b) values(1+1-1,2) on duplicate key update a=a+" + String.valueOf(shrdDbCount) + "*20, b=b+2"; + + "(a,b) values(1+1-1,2) on duplicate key update a=a+" + String.valueOf(shrdDbCount) + "*20, b=b+2"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = 4; //4:(delete + insert) * 2 if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + basePhyInsert = 2; //insert + insert + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + basePhyInsert = 2; //insert + insert + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isDeleteOnly()) { basePhyInsert = 3; //3:(delete + insert) + delete - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + if (isCache == null) { + basePhyInsert = 1; //1: insert + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + } } else { //select_for_duplicate + delete + insert - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + 1 + 1)); + if (isCache == null) { + //select_for_duplicate + insert + Assert.assertThat(trace.toString(), trace.size(), is(1 + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + 1 + 1)); + } + } } @@ -2081,17 +2243,17 @@ public void tablePkNoUkForUpsertSelect() { executeDml(sql); sql = "insert into " + sourceTableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; - String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; + String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false, DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; if (isCache == null) { - hintStr = " /*+TDDL:cmd_extra(MERGE_UNION=false)*/ "; + hintStr = " /*+TDDL:cmd_extra(MERGE_UNION=false,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; } else if (isCache.booleanValue()) { - hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true,MERGE_UNION=false)*/ "; + hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=true,MERGE_UNION=false, DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ "; } executeDml(hintStr + sql); sql = "insert into " + tableName - + "(a,b) select a+1-1,b+1-1 from " + sourceTableName + " on duplicate key update b=b+1+3"; + + "(a,b) select a+1-1,b+1-1 from " + sourceTableName + " on duplicate key update b=b+1+3"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -2100,57 +2262,74 @@ public void tablePkNoUkForUpsertSelect() { int shrdDbCount = getDataSourceCount() - 1 - 1 - 1;//minus metadb+scaleoutdb+singledb int basePhyInsert = 6; if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size() + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size() + 1)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 1)); + } } else if (finalTableStatus.isDeleteOnly()) { - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size())); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size())); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size())); + } } else { //select + select_for_duplicate + insert - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size())); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size())); + } } for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b) select a+1-1,b from " + sourceTableName + " where a=1+1-1 on duplicate key update b=b+1+3"; + + "(a,b) select a+1-1,b from " + sourceTableName + " where a=1 on duplicate key update b=b+1+3"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i == 0 ? 4 : 2; if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + if (isCache == null) { + //1:select_for_update, 3:Select + Assert.assertThat(trace.toString(), trace.size(), is(1 + 3 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(3 + topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + if (isCache == null) { + //2:select_for_update, 3:Select + Assert.assertThat(trace.toString(), trace.size(), is(1 + 3 + basePhyInsert)); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(3 + topology.size() + basePhyInsert)); + } } else if (finalTableStatus.isDeleteOnly()) { // 3:2*delete + insert; 1: insert - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + (i == 0 ? 3 : 1))); + if (isCache == null) { + //2:select_for_update, 3:Select + Assert.assertThat(trace.toString(), trace.size(), is(1 + 3 + (i == 0 ? 3 : 1))); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(3 + topology.size() + (i == 0 ? 3 : 1))); + } } else { //0:select + select_for_duplicate + delete + insert //1:select + select_for_duplicate + insert - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + (i == 0 ? 2 : 1))); + if (isCache == null) { + Assert.assertThat(trace.toString(), trace.size(), is(3 + 1 + (i == 0 ? 2 : 1))); + } else { + Assert.assertThat(trace.toString(), trace.size(), is(3 + topology.size() + (i == 0 ? 2 : 1))); + } } if (i == 0) { sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); } } - sql = "insert into " + tableName - + "(a,b) select a,b+1 from " + sourceTableName + " where a=1 on duplicate key update a=a+" + String - .valueOf(shrdDbCount) + "*20, b=b+2"; - executeDml("trace " + hintStr + sql); - trace = getTrace(tddlConnection); - - basePhyInsert = 4; //4:(delete + insert) * 2 - if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + topology.size() + basePhyInsert)); - } else if (finalTableStatus.isReadyToPublic()) { - Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + topology.size() + basePhyInsert)); - } else if (finalTableStatus.isDeleteOnly()) { - basePhyInsert = 3; //3:(delete + insert) + delete - Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + topology.size() + basePhyInsert)); - } else { - //select + select_for_duplicate + delete + insert - Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + topology.size() + 1 + 1)); - } } @Test @@ -2160,7 +2339,7 @@ public void tablePkAndUkForUpsert() { executeDml(sql); sql = "insert into " + tableName - + "(a,b,c) values(1,1,1), (2,2+1-1,2), (3,3,3), (4,4,4), (5,5+2-2,5),(6,6,6) on duplicate key update a=a+1"; + + "(a,b,c) values(1,1,1), (2,2+1-1,2), (3,3,3), (4,4,4), (5,5+2-2,5),(6,6,6) on duplicate key update a=a+1"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -2187,7 +2366,7 @@ public void tablePkAndUkForUpsert() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b,c) values(1,1+1-1,1) on duplicate key update b=b+1"; + + "(a,b,c) values(1,1+1-1,1) on duplicate key update b=b+1"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -2210,7 +2389,7 @@ public void tablePkAndUkForUpsert() { } } sql = "insert into " + tableName - + "(a,b,c) values(1+1-1,1,3) on duplicate key update b=b+1"; + + "(a,b,c) values(1+1-1,1,3) on duplicate key update b=b+1"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -2239,7 +2418,7 @@ public void tablePkAndUkForUpsertSelect() { executeDml(sql); sql = "insert into " + sourceTableName - + "(a,b,c) values(1,1,1), (2,2,2+1-1), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (2,2,2+1-1), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; if (isCache == null) { hintStr = " /*+TDDL:cmd_extra(MERGE_UNION=false)*/ "; @@ -2249,7 +2428,7 @@ public void tablePkAndUkForUpsertSelect() { executeDml(hintStr + sql); sql = "insert into " + tableName - + "(a,b,c) select a+1-1,b,c from " + sourceTableName + " where a<>2+12324 on duplicate key update a=a+1"; + + "(a,b,c) select a+1-1,b,c from " + sourceTableName + " where a<>2+12324 on duplicate key update a=a+1"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); List> trace = getTrace(tddlConnection); @@ -2269,22 +2448,22 @@ public void tablePkAndUkForUpsertSelect() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b,c) select a,b+2-2,c from " + sourceTableName - + " where a=1 and 2=2 on duplicate key update b=b+2"; + + "(a,b,c) select a,b+2-2,c from " + sourceTableName + + " where a=1 and 2=2 on duplicate key update b=b+2"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 4 : 2); //4:(delete + insert) * 2 if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { Assert.assertThat(trace.toString(), trace.size(), - is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); + is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); } else if (finalTableStatus.isReadyToPublic()) { Assert.assertThat(trace.toString(), trace.size(), - is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); + is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); } else if (finalTableStatus.isDeleteOnly()) { basePhyInsert = (i == 0 ? 3 : 1); //3:(delete + insert) + delete Assert.assertThat(trace.toString(), trace.size(), - is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); + is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); } else { //0:select + select_for_duplicate + delete + insert //1:select + select_for_duplicate + insert @@ -2296,7 +2475,7 @@ public void tablePkAndUkForUpsertSelect() { } } sql = "insert into " + tableName - + "(a,b,c) select a,b,c+2 from " + sourceTableName + " where a=1 on duplicate key update b=b+20"; + + "(a,b,c) select a,b,c+2 from " + sourceTableName + " where a=1 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -2320,7 +2499,7 @@ public void brdTablePkNoUkForUpsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert into " + tableName - + "(a,b) values(1+1-1,1), (2,2+1-1), (3,3), (4,4), (5,5),(6,6) on duplicate key update b=b+20"; + + "(a,b) values(1+1-1,1), (2,2+1-1), (3,3), (4,4), (5,5),(6,6) on duplicate key update b=b+20"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -2348,7 +2527,7 @@ public void brdTablePkNoUkForUpsert() { } for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b) values(1+2-2,1) on duplicate key update b=b+20"; + + "(a,b) values(1+2-2,1) on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -2360,7 +2539,7 @@ public void brdTablePkNoUkForUpsert() { Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert)); } else if (finalTableStatus.isDeleteOnly()) { Assert.assertThat(trace.toString(), trace.size(), - is(topology.size() + (i == 0 ? basePhyInsert : physicalDbCount))); + is(topology.size() + (i == 0 ? basePhyInsert : physicalDbCount))); } else if (finalTableStatus.isPublic()) { Assert.assertThat(trace.toString(), trace.size(), is(physicalDbCount + 1)); } else { @@ -2373,7 +2552,7 @@ public void brdTablePkNoUkForUpsert() { } } sql = "insert into " + tableName - + "(a,b) values(1,2+1-1) on duplicate key update a=a+20"; + + "(a,b) values(1,2+1-1) on duplicate key update a=a+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -2403,7 +2582,7 @@ public void brdTablePkNoUkForUpsertSelect() { executeDml(sql); sql = "insert into " + sourceTableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -2413,8 +2592,8 @@ public void brdTablePkNoUkForUpsertSelect() { executeDml(hintStr + sql); sql = "insert into " + tableName - + "(a,b) select a,b+1-1 from " + sourceTableName - + " where 1=1 and a<>1+23456 on duplicate key update b=b+20"; + + "(a,b) select a,b+1-1 from " + sourceTableName + + " where 1=1 and a<>1+23456 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); List> trace = getTrace(tddlConnection); @@ -2436,8 +2615,8 @@ public void brdTablePkNoUkForUpsertSelect() { } for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b) select a+1-1,b from " + sourceTableName - + " where 2=2 and a=1+1-1 on duplicate key update b=b+20"; + + "(a,b) select a+1-1,b from " + sourceTableName + + " where 2=2 and a=1+1-1 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -2462,7 +2641,7 @@ public void brdTablePkNoUkForUpsertSelect() { } } sql = "insert into " + tableName - + "(a,b) select a,b+1 from " + sourceTableName + " where a=1 and 2=2 on duplicate key update b=b+20"; + + "(a,b) select a,b+1 from " + sourceTableName + " where a=1 and 2=2 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -2488,7 +2667,7 @@ public void brdTablePkAndUkForUpsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/ delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert into " + tableName - + "(a,b,c) values(1,1+1-1,1), (2+1-1,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6) on duplicate key update b=b+20"; + + "(a,b,c) values(1,1+1-1,1), (2+1-1,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6) on duplicate key update b=b+20"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -2516,16 +2695,16 @@ public void brdTablePkAndUkForUpsert() { } int scan = topology.size(); int[] writablePhysicalOperations = - new int[] {scan + physicalDbCount * 2 + 2, scan + physicalDbCount + 1}; + new int[]{scan + physicalDbCount * 2 + 2, scan + physicalDbCount + 1}; int[] readyToPublishPhysicalOperations = - new int[] {physicalDbCount + 1, physicalDbCount + 1}; + new int[]{physicalDbCount + 1, physicalDbCount + 1}; int[] otherPhysicalOperations = - new int[] {physicalDbCount, physicalDbCount}; + new int[]{physicalDbCount, physicalDbCount}; int[] deleteOnlyPhysicalOperations = - new int[] {scan + physicalDbCount * 2 + 1, scan + physicalDbCount}; + new int[]{scan + physicalDbCount * 2 + 1, scan + physicalDbCount}; for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b,c) values(1,1+1-1,1) on duplicate key update b=b+20"; + + "(a,b,c) values(1,1+1-1,1) on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -2547,7 +2726,7 @@ public void brdTablePkAndUkForUpsert() { } } sql = "insert into " + tableName - + "(a,b,c) values(1+1-1,1,2+1-1) on duplicate key update b=b+20"; + + "(a,b,c) values(1+1-1,1,2+1-1) on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -2577,7 +2756,7 @@ public void brdTablePkAndUkForUpsertSelect() { executeDml(sql); sql = "insert into " + sourceTableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; if (isCache == null) { hintStr = ""; @@ -2587,7 +2766,7 @@ public void brdTablePkAndUkForUpsertSelect() { executeDml("trace " + hintStr + sql); sql = "insert into " + tableName - + "(a,b,c) select a,b,c+1-1 from " + sourceTableName + " where a<>1 or 1=1 on duplicate key update b=b+20"; + + "(a,b,c) select a,b,c+1-1 from " + sourceTableName + " where a<>1 or 1=1 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -2610,17 +2789,17 @@ public void brdTablePkAndUkForUpsertSelect() { } int scan = topology.size(); int[] writablePhysicalOperations = - new int[] {scan + 1 + physicalDbCount * 2 + 2, scan + 1 + physicalDbCount + 1}; + new int[]{scan + 1 + physicalDbCount * 2 + 2, scan + 1 + physicalDbCount + 1}; int[] readyToPublishPhysicalOperations = - new int[] {scan + physicalDbCount + 1, scan + physicalDbCount + 1}; + new int[]{scan + physicalDbCount + 1, scan + physicalDbCount + 1}; int[] otherPhysicalOperations = - new int[] {1 + physicalDbCount, 1 + physicalDbCount}; + new int[]{1 + physicalDbCount, 1 + physicalDbCount}; int[] deleteOnlyPhysicalOperations = - new int[] {scan + 1 + physicalDbCount * 2 + 1, scan + 1 + physicalDbCount}; + new int[]{scan + 1 + physicalDbCount * 2 + 1, scan + 1 + physicalDbCount}; for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b,c) select a+1-1,b,c from " + sourceTableName - + " where a=1 and 2+1=3 on duplicate key update b=b+20"; + + "(a,b,c) select a+1-1,b,c from " + sourceTableName + + " where a=1 and 2+1=3 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); if (finalTableStatus.isWritable() && !finalTableStatus.isReadyToPublic()) { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutPlanWithMultiGroupMoveTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutPlanWithMultiGroupMoveTest.java index 1ff3920d3..e52d0610f 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutPlanWithMultiGroupMoveTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/sharding/scaleout/ScaleOutPlanWithMultiGroupMoveTest.java @@ -42,16 +42,16 @@ public class ScaleOutPlanWithMultiGroupMoveTest extends ScaleOutBaseTest { private static List moveTableStatus = - Stream.of( - ComplexTaskMetaManager.ComplexTaskStatus.DELETE_ONLY.toString(), - ComplexTaskMetaManager.ComplexTaskStatus.WRITE_ONLY.toString(), - ComplexTaskMetaManager.ComplexTaskStatus.READY_TO_PUBLIC.toString()).collect(Collectors.toList()); + Stream.of( + ComplexTaskMetaManager.ComplexTaskStatus.DELETE_ONLY.toString(), + ComplexTaskMetaManager.ComplexTaskStatus.WRITE_ONLY.toString(), + ComplexTaskMetaManager.ComplexTaskStatus.READY_TO_PUBLIC.toString()).collect(Collectors.toList()); final static int tbPartitions = 3; static boolean firstIn = true; public ScaleOutPlanWithMultiGroupMoveTest() { super("ScaleOutPlanMultiMoveTest", "polardbx_meta_db_polardbx", - moveTableStatus); + moveTableStatus); } @Before @@ -83,10 +83,10 @@ public void insertIgnorePushDownOnNonScaleOutGroup() { // shard on scaleout-group sql = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; // shard on non-scale out-group, should be pushdown sql2 = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123460+4*3, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123460+4*3, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; String hintStr = ""; @@ -118,10 +118,10 @@ public void replacePushDownOnNonScaleOutGroup() { // shard on scaleout-group sql = - "replace into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123460, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + "replace into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123460, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; // shard on non-scaleout-group, should be pushdown sql2 = - "replace into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123460+4*3, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + "replace into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123460+4*3, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; @@ -151,10 +151,10 @@ public void updatePushDownOnNonScaleOutGroup() { String sql2 = ""; executeDml(sql); String insert1 = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; executeDml(insert1); String insert2 = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123460+4*3, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123460+4*3, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; executeDml(insert2); // shard on scaleout-group @@ -189,10 +189,10 @@ public void deletePushDownOnNonScaleOutGroup() { String sql2 = ""; executeDml(sql); String insert1 = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123456+4, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; executeDml(insert1); String insert2 = - " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123460+4*3, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; + " insert ignore into `mdb_mtb_mk1` (pk, integer_test, varchar_test, datetime_test, timestamp_test) values (123460+4*3, 1, '1000', '2020-12-12 12:12:12', '2021-12-12 12:12:12');"; executeDml(insert2); // shard on scaleout-group @@ -221,8 +221,8 @@ public void tablePkNoUkForInsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert ignore into " + tableName - + "(a,b) values(1,1), (2,2), ((1+2), (2+1)), (4,4), (5,5),(6,6)"; - String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; + + "(a,b) values(1,1), (2,2), ((1+2), (2+1)), (4,4), (5,5),(6,6)"; + String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -231,16 +231,16 @@ public void tablePkNoUkForInsert() { int basePhyInsert = 6; //finalTableStatus.size() - 1(delete_only) = multiWrite Assert.assertThat(trace.toString(), trace.size(), - is(basePhyInsert + topology.size() + finalTableStatus.size() - 1)); + is(basePhyInsert * 2 + finalTableStatus.size() - 1)); for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b) values(0,0),(1,1),(2,2),(3,3)"; + + "(a,b) values(0,0),(1,1),(2,2),(3,3)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i * 1 + i * 2 + i * 2 + 1; - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + Assert.assertThat(trace.toString(), trace.size(), is(4 + basePhyInsert)); sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); @@ -256,8 +256,8 @@ public void tablePkNoUkForInsertSelect() { sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + sourceTableName + " where 1=1"; executeDml(sql); sql = "insert ignore into " + sourceTableName - + "(a,b) values(1,1), (2,2), (( 3),( 3)), (4,4), (5,5),(6,6)"; - String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; + + "(a,b) values(1,1), (2,2), (( 3),( 3)), (4,4), (5,5),(6,6)"; + String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; executeDml(hintStr + sql); sql = "insert ignore into " + tableName + "(a,b) select a,b+100 from " + sourceTableName; @@ -266,15 +266,15 @@ public void tablePkNoUkForInsertSelect() { List> trace = getTrace(tddlConnection); int basePhyInsert = 6; - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 0 + 1 + 1)); + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size() + 0 + 1 + 1)); for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b) select a,( 1+2-2) from " + sourceTableName + " where a = 1+1-1"; + + "(a,b) select a,( 1+2-2) from " + sourceTableName + " where a = 1+1-1"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); - basePhyInsert = i == 0 ? 0 : 2; - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + basePhyInsert = 2; + Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + 1 + basePhyInsert)); sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); } @@ -286,7 +286,7 @@ public void tableWithPkAndUkForInsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert ignore into " + tableName - + "(a,b,c) values(1,1,1), (1+1,2,2), (3,1+1*2,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (1+1,2,2), (3,1+1*2,3), (4,4,4), (5,5,5),(6,6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); @@ -299,7 +299,7 @@ public void tableWithPkAndUkForInsert() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b,c) values(1,1,1)"; + + "(a,b,c) values(1,1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -322,10 +322,10 @@ public void tableWithPkAndUkForInsertSelect() { String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; sql = "insert ignore into " + sourceTableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; executeDml(sql); sql = "insert ignore into " + tableName - + "(a,b,c) select a+1-1,b,c from " + sourceTableName; + + "(a,b,c) select a+1-1,b,c from " + sourceTableName; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); List> trace = getTrace(tddlConnection); @@ -337,13 +337,13 @@ public void tableWithPkAndUkForInsertSelect() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b,c) select a,b+1-1,c from " + sourceTableName + " where a=(select 1) and b<>2+100"; + + "(a,b,c) select a,b+1-1,c from " + sourceTableName + " where a=(select 1) and b<>2+100"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i * 2; Assert.assertThat(trace.toString(), trace.size(), - is(scanForDuplicateCheck + topology.size() + basePhyInsert)); + is(scanForDuplicateCheck + topology.size() + basePhyInsert)); sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); } @@ -355,7 +355,7 @@ public void brdTablePkNoUkForInsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert ignore into " + tableName - + "(a,b) values(1,1), (1+1,2), (3,3), (2+2,4), (5,5),(6,6)"; + + "(a,b) values(1,1), (1+1,2), (3,3), (2+2,4), (5,5),(6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); @@ -368,7 +368,7 @@ public void brdTablePkNoUkForInsert() { for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b) values(1+1-1,1)"; + + "(a,b) values(1+1-1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -390,12 +390,12 @@ public void brdTablePkNoUkForInsertSelect() { executeDml(sql); sql = "insert ignore into " + sourceTableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml(hintStr + sql); sql = "insert ignore into " + tableName - + "(a,b) select a+1-1,b+20 from " + sourceTableName + " where a<> ( 1000)"; + + "(a,b) select a+1-1,b+20 from " + sourceTableName + " where a<> ( 1000)"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -404,11 +404,11 @@ public void brdTablePkNoUkForInsertSelect() { int basePhyInsert = 6; int physicalDbCount = getDataSourceCount() - 1 - 3; //minus metaDb and scaleout target db Assert.assertThat(trace.toString(), trace.size(), - is(1/*scan*/ + physicalDbCount/*select*/ + topology.size()/*insert*/ + 0 + 1 + 1)); + is(1/*scan*/ + physicalDbCount/*select*/ + topology.size()/*insert*/ + 0 + 1 + 1)); for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b) select a+1-1,b+1 from " + sourceTableName + " where a=( 1)"; + + "(a,b) select a+1-1,b+1 from " + sourceTableName + " where a=( 1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -426,7 +426,7 @@ public void brdTableWithPkAndUkForInsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert ignore into " + tableName - + "(a,b,c) values(1+1-1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,3+2+1-1+1)"; + + "(a,b,c) values(1+1-1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,3+2+1-1+1)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); @@ -439,7 +439,7 @@ public void brdTableWithPkAndUkForInsert() { for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b,c) values(1,1,1),(2,2,2),(6,6,6)"; + + "(a,b,c) values(1,1,1),(2,2,2),(6,6,6)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -461,13 +461,13 @@ public void brdTableWithPkAndUkForInsertSelect() { executeDml(sql); sql = "insert ignore into " + sourceTableName - + "(a,b,c) values( 1+1-1, 1, 1), (2,2,2), (3, 3,3), (4,4,4), (5,5,5),(3+6-3,6,6)"; + + "(a,b,c) values( 1+1-1, 1, 1), (2,2,2), (3, 3,3), (4,4,4), (5,5,5),(3+6-3,6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; executeDml(hintStr + sql); sql = "insert ignore into " + tableName - + "(a,b,c) select a+1-1,b+1-1,c from " + sourceTableName + " where a<>2000 and b<1+2+2000"; + + "(a,b,c) select a+1-1,b+1-1,c from " + sourceTableName + " where a<>2000 and b<1+2+2000"; executeDml("trace " + hintStr + sql); int physicalDbCount = getDataSourceCount() - 1 - 3; //minus metaDb and scaleout target db final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -478,8 +478,8 @@ public void brdTableWithPkAndUkForInsertSelect() { for (int i = 0; i < 2; i++) { sql = "insert ignore into " + tableName - + "(a,b,c) select a+1-1,b,c+1-1 from " + sourceTableName - + " where (a=1 or a=2 or a=0) and b<>1+9999+32"; + + "(a,b,c) select a+1-1,b,c+1-1 from " + sourceTableName + + " where (a=1 or a=2 or a=0) and b<>1+9999+32"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -497,24 +497,24 @@ public void tablePkNoUkForReplace() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "replace into " + tableName - + "(a,b) values(1+1-1,1), (2,2), (3,3), (4,4), (5,5),(0,0+8-8)"; - String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; + + "(a,b) values(1+1-1,1), (2,2), (3,3), (4,4), (5,5),(0,0+8-8)"; + String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false,DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); List> trace = getTrace(tddlConnection); int basePhyInsert = 6; - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 0 + 1 + 1)); + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + 0 + 1 + 1)); for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b) values(1+1-1,1),(0+1-1,0),(2+1-1,2)"; + + "(a,b) values(1+1-1,1),(0+1-1,0),(2+1-1,2)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 4 + 4 + (2 + 1) : 3 + 0 + 1 + 1); //4:(delete + insert) * 2 - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + Assert.assertThat(trace.toString(), trace.size(), is(3 + basePhyInsert)); if (i == 0) { sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; @@ -522,11 +522,11 @@ public void tablePkNoUkForReplace() { } } sql = "replace into " + tableName - + "(a,b) values(5,5)"; + + "(a,b) values(5,5)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + 1)); + Assert.assertThat(trace.toString(), trace.size(), is(1 + 1)); } @Test @@ -540,29 +540,29 @@ public void tablePkNoUkForReplaceSelect() { executeDml(sql); sql = "replace into " + sourceTableName - + "(a,b) values(1+1-1,1), (2,2+1-1), (3,3), (4,4), (5,5),(6,6+1-1)"; - String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; + + "(a,b) values(1+1-1,1), (2,2+1-1), (3,3), (4,4), (5,5),(6,6+1-1)"; + String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false, DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; executeDml(hintStr + sql); sql = "replace into " + tableName - + "(a,b) select a,b+20 from " + sourceTableName + " where b<>( 200+321)"; + + "(a,b) select a,b+20 from " + sourceTableName + " where b<>( 200+321)"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); List> trace = getTrace(tddlConnection); int basePhyInsert = 6; - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 0 + 1 + 1)); + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size() + 0 + 1 + 1)); for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b) select a+1-1,b from " + sourceTableName + " where a=1+1+2-3 and b<>( 1234+3456)"; + + "(a,b) select a+1-1,b from " + sourceTableName + " where a=1+1+2-3 and b<>( 1234+3456)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); - basePhyInsert = (i == 0 ? 4 : 2); //4:(delete + insert) * 2 - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + basePhyInsert = 2; //4:(delete + insert) * 2 + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert + topology.size())); if (i == 0) { sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; @@ -570,12 +570,12 @@ public void tablePkNoUkForReplaceSelect() { } } sql = "replace into " + tableName - + "(a,b) select a,b+1 from " + sourceTableName + " where a=1"; + + "(a,b) select a,b+1 from " + sourceTableName + " where a=1"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); - basePhyInsert = 4; //4:(delete + insert) * 2 - Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + topology.size() + basePhyInsert)); + basePhyInsert = 2; //2:(insert) * 2 + Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + 1 + basePhyInsert)); } @@ -585,7 +585,7 @@ public void tablePkAndUkForReplace() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "replace into " + tableName - + "(a,b,c) values(1+1-1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5+1-1),(0,0,0)"; + + "(a,b,c) values(1+1-1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5+1-1),(0,0,0)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); @@ -599,7 +599,7 @@ public void tablePkAndUkForReplace() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b,c) values(1+1-1,1,1)"; + + "(a,b,c) values(1+1-1,1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -612,7 +612,7 @@ public void tablePkAndUkForReplace() { } } sql = "replace into " + tableName - + "(a,b,c) values(5,5,3)"; + + "(a,b,c) values(5,5,3)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -632,14 +632,14 @@ public void tablePkAndUkForReplaceSelect() { executeDml(sql); sql = "replace into " + sourceTableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(0,0,0)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(0,0,0)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; executeDml(hintStr + sql); sql = "replace into " + tableName - + "(a,b,c) select 3+a-3,b+1-1,c+2-2 from " + sourceTableName - + " where a<1000 and b<>( 1+3333+21-1*2)"; + + "(a,b,c) select 3+a-3,b+1-1,c+2-2 from " + sourceTableName + + " where a<1000 and b<>( 1+3333+21-1*2)"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -651,35 +651,35 @@ public void tablePkAndUkForReplaceSelect() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b,c) select a+1*2-2,1+b-1,c+2-2 from " + sourceTableName + " where a=( 1)"; + + "(a,b,c) select a+1*2-2,1+b-1,c+2-2 from " + sourceTableName + " where a=( 1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 4 : 2); //4:(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), - is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); + is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); sql = "replace into " + tableName - + "(a,b,c) select a+1*2-2,1+b-1,c+2-2 from " + sourceTableName + " where a=( 0)"; + + "(a,b,c) select a+1*2-2,1+b-1,c+2-2 from " + sourceTableName + " where a=( 0)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 3 : 1); //4:(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), - is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); + is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); if (i == 0) { sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); } } sql = "replace into " + tableName - + "(a,b,c) select a+1-1,b,c+2 from " + sourceTableName + " where a=(select 0) and c<>( 34567)"; + + "(a,b,c) select a+1-1,b,c+2 from " + sourceTableName + " where a=(select 0) and c<>( 34567)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = 3; //3:(delete + insert) + delete Assert.assertThat(trace.toString(), trace.size(), - is(topology.size() + scanForDuplicateCheck + basePhyInsert)); + is(topology.size() + scanForDuplicateCheck + basePhyInsert)); } @Test @@ -688,7 +688,7 @@ public void brdTablePkNoUkForReplace() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "replace into " + tableName - + "(a,b) values(1,1), (2,2+1-1), (3,3), (4,4), (5,5),(0,0)"; + + "(a,b) values(1,1), (2,2+1-1), (3,3), (4,4), (5,5),(0,0)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); @@ -701,12 +701,12 @@ public void brdTablePkNoUkForReplace() { for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b) values(1,1)"; + + "(a,b) values(1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 2 * physicalDbCount + (0 + 1) + (1 + 1) + (1 + 1) : - physicalDbCount + 0 + 1 + 1); //(delete + insert) * 2 + physicalDbCount + 0 + 1 + 1); //(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); if (i == 0) { @@ -715,13 +715,13 @@ public void brdTablePkNoUkForReplace() { } } sql = "replace into " + tableName - + "(a,b) values(1+1-1,2)"; + + "(a,b) values(1+1-1,2)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = physicalDbCount * 2; //(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), - is(topology.size() + basePhyInsert + (0 + 1) + (1 + 1) + (1 + 1))); + is(topology.size() + basePhyInsert + (0 + 1) + (1 + 1) + (1 + 1))); } @@ -736,13 +736,13 @@ public void brdTablePkNoUkForReplaceSelect() { executeDml(sql); sql = "replace into " + sourceTableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(0,0)"; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(0,0)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml(hintStr + sql); sql = "replace into " + tableName - + "(a,b) select a+1-1,b+1-1 from " + sourceTableName + " where 1=1 and a<>1+23456"; + + "(a,b) select a+1-1,b+1-1 from " + sourceTableName + " where 1=1 and a<>1+23456"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); List> trace = getTrace(tddlConnection); @@ -750,18 +750,18 @@ public void brdTablePkNoUkForReplaceSelect() { int basePhyInsert = 6; int physicalDbCount = getDataSourceCount() - 1 - 3; //minus metaDb and scaleout target db Assert.assertThat(trace.toString(), trace.size(), - is(topology.size()/*select from source*/ + topology.size()/*select from target*/ + physicalDbCount + 0 + 1 - + 1)); + is(topology.size()/*select from source*/ + topology.size()/*select from target*/ + physicalDbCount + 0 + 1 + + 1)); for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b) select a,b from " + sourceTableName + " where 2=2 and a=0"; + + "(a,b) select a,b from " + sourceTableName + " where 2=2 and a=0"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = - (i == 0 ? 2 * physicalDbCount + (0 + 1) + (1 + 1) + (1 + 1) : - physicalDbCount + 0 + 1 + 1); //delete + insert* 2 + (i == 0 ? 2 * physicalDbCount + (0 + 1) + (1 + 1) + (1 + 1) : + physicalDbCount + 0 + 1 + 1); //delete + insert* 2 Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); if (i == 0) { @@ -770,17 +770,17 @@ public void brdTablePkNoUkForReplaceSelect() { } } sql = "replace into " + tableName - + "(a,b) select a,b from " + sourceTableName + " where 2=2 and a=1"; + + "(a,b) select a,b from " + sourceTableName + " where 2=2 and a=1"; executeDml("trace " + hintStr + sql); sql = "replace into " + tableName - + "(a,b) select a,b+1 from " + sourceTableName + " where a=1 and 2=2"; + + "(a,b) select a,b+1 from " + sourceTableName + " where a=1 and 2=2"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = physicalDbCount * 2; //(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), - is(2 * topology.size() + basePhyInsert + (0 + 1) + (1 + 1) + (1 + 1))); + is(2 * topology.size() + basePhyInsert + (0 + 1) + (1 + 1) + (1 + 1))); } @@ -790,7 +790,7 @@ public void brdTablePkAndUkForReplace() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/ delete from " + tableName + " where 1=1"; executeDml(sql); sql = "replace into " + tableName - + "(a,b,c) values(1,1,1+1-1), (2,2,2), (3,3+1-1,3), (4,4,4), (5,5,5),(0,0,0)"; + + "(a,b,c) values(1,1,1+1-1), (2,2,2), (3,3+1-1,3), (4,4,4), (5,5,5),(0,0,0)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); @@ -803,21 +803,21 @@ public void brdTablePkAndUkForReplace() { for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b,c) values(1+1-1,1,1)"; + + "(a,b,c) values(1+1-1,1,1)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 2 * physicalDbCount + (1 + 0) + (1 + 1) + (1 + 1) : - physicalDbCount + 0 + 1 + 1); //(delete + insert) * 2 + physicalDbCount + 0 + 1 + 1); //(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); sql = "replace into " + tableName - + "(a,b,c) values(0,0,0)"; + + "(a,b,c) values(0,0,0)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 2 * physicalDbCount + (1 + 0) + (1 + 1) + (1 + 1) : - physicalDbCount + 0 + 1 + 1); //delete*2 + insert + physicalDbCount + 0 + 1 + 1); //delete*2 + insert Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); if (i == 0) { @@ -826,13 +826,13 @@ public void brdTablePkAndUkForReplace() { } } sql = "replace into " + tableName - + "(a,b,c) values(1,1+1-1,2)"; + + "(a,b,c) values(1,1+1-1,2)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = physicalDbCount * 2; //(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), - is(topology.size() + basePhyInsert + (1 + 0) + (1 + 1) + (1 + 1))); + is(topology.size() + basePhyInsert + (1 + 0) + (1 + 1) + (1 + 1))); } @@ -847,13 +847,13 @@ public void brdTablePkAndUkForReplaceSelect() { executeDml(sql); sql = "replace into " + sourceTableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(0,0,0)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(0,0,0)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); sql = "replace into " + tableName - + "(a,b,c) select a+1-1,b+1-1,c+2-2 from " + sourceTableName + " where a<>1 or 1=1"; + + "(a,b,c) select a+1-1,b+1-1,c+2-2 from " + sourceTableName + " where a<>1 or 1=1"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -865,21 +865,21 @@ public void brdTablePkAndUkForReplaceSelect() { for (int i = 0; i < 2; i++) { sql = "replace into " + tableName - + "(a,b,c) select a,b,c from " + sourceTableName + " where a=1 and 2+1=3"; + + "(a,b,c) select a,b,c from " + sourceTableName + " where a=1 and 2+1=3"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 2 * physicalDbCount + (0 + 1) + (1 + 1) + (1 + 1) : - physicalDbCount + 0 + 1 + 1); //(delete + insert) * 2 + physicalDbCount + 0 + 1 + 1); //(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); sql = "replace into " + tableName - + "(a,b,c) select a,b,c from " + sourceTableName + " where a=0 and 2+1=3"; + + "(a,b,c) select a,b,c from " + sourceTableName + " where a=0 and 2+1=3"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 2 * physicalDbCount + (0 + 1) + (1 + 1) + (1 + 1) : - physicalDbCount + 0 + 1 + 1); //delete*2 + insert + physicalDbCount + 0 + 1 + 1); //delete*2 + insert Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); if (i == 0) { @@ -888,13 +888,13 @@ public void brdTablePkAndUkForReplaceSelect() { } } sql = "replace into " + tableName - + "(a,b,c) select a,b,c+1 from " + sourceTableName + " where a=1 and (2=1 or 2=2)"; + + "(a,b,c) select a,b,c+1 from " + sourceTableName + " where a=1 and (2=1 or 2=2)"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = physicalDbCount * 2; //(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), - is(2 * topology.size() + basePhyInsert + (0 + 1) + (1 + 1) + (1 + 1))); + is(2 * topology.size() + basePhyInsert + (0 + 1) + (1 + 1) + (1 + 1))); } @@ -906,24 +906,24 @@ public void tablePkNoUkForDelete() { String hint = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,PLAN_CACHE=false)*/ "; - String[] sqlList = new String[] { - "delete from " + tableName + " where 1=1", - "delete from " + tableName + " where a < 300", - "delete from " + tableName + " where a = 1", - "delete from " + tableName + " where b=1", - "delete from " + tableName + " where a = 1 and b=1", - "delete from " + tableName + " where 1=1 order by a limit 6",}; + String[] sqlList = new String[]{ + "delete from " + tableName + " where 1=1", + "delete from " + tableName + " where a < 300", + "delete from " + tableName + " where a = 1", + "delete from " + tableName + " where b=1", + "delete from " + tableName + " where a = 1 and b=1", + "delete from " + tableName + " where 1=1 order by a limit 6",}; //{6, 2, 1, 1, 1, 1, 1} List> trace; final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); int dbCount = getDataSourceCount() - 1 - 1 - 3;//minus metadb+scaleoutdb + singledb - int[] scans = new int[] {dbCount, dbCount, 1, dbCount, 1, dbCount}; + int[] scans = new int[]{dbCount, dbCount, 1, dbCount, 1, dbCount}; int[] writablePhysicalOperations = - new int[] {6 + 1 + 1 + 1, 6 + 1 + 1 + 1, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, 6 + 1 + 1 + 1}; + new int[]{6 + 1 + 1 + 1, 6 + 1 + 1 + 1, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, 6 + 1 + 1 + 1}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(0,0)"; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(0,0)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = writablePhysicalOperations[i]; @@ -945,28 +945,28 @@ public void tablePkAndUkForDelete() { executeDml(sql); String hint = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,PLAN_CACHE=false)*/ "; - String[] sqlList = new String[] { - "delete from " + tableName + " where 1=1", - "delete from " + tableName + " where a < 300", - "delete from " + tableName + " where a = 1", - "delete from " + tableName + " where b=1", - "delete from " + tableName + " where c=1", - "delete from " + tableName + " where a = 1 and b=1", - "delete from " + tableName + " where a = 1 and b=1 and c=1", - "delete from " + tableName + " where 1=1 order by a limit 6",}; + String[] sqlList = new String[]{ + "delete from " + tableName + " where 1=1", + "delete from " + tableName + " where a < 300", + "delete from " + tableName + " where a = 1", + "delete from " + tableName + " where b=1", + "delete from " + tableName + " where c=1", + "delete from " + tableName + " where a = 1 and b=1", + "delete from " + tableName + " where a = 1 and b=1 and c=1", + "delete from " + tableName + " where 1=1 order by a limit 6",}; //{6, 2, 1, 1, 1, 1, 1} List> trace; final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); int dbCount = getDataSourceCount() - 1 - 1 - 3;//minus metadb+scaleoutdb + singledb - int[] scans = new int[] {dbCount, dbCount, 1, dbCount, dbCount, 1, 1, dbCount}; + int[] scans = new int[]{dbCount, dbCount, 1, dbCount, dbCount, 1, 1, dbCount}; int[] writablePhysicalOperations = - new int[] { - 6 + 1 + 1 + 1, 6 + 1 + 1 + 1, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, - 6 + 1 + 1 + 1}; + new int[]{ + 6 + 1 + 1 + 1, 6 + 1 + 1 + 1, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, 1 + 0 + 1 + 0, + 6 + 1 + 1 + 1}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(0,0,0)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(0,0,0)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = writablePhysicalOperations[i]; @@ -987,25 +987,25 @@ public void brdTablePkNoUkForDelete() { executeDml(sql); String hint = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,PLAN_CACHE=false)*/ "; - String[] sqlList = new String[] { - "delete from " + tableName + " where 1=1", - "delete from " + tableName + " where a < 300", - "delete from " + tableName + " where a = 2", - "delete from " + tableName + " where b=1", - "delete from " + tableName + " where a = 1 and b=1", - "delete from " + tableName + " where 1=1 order by a limit 6",}; + String[] sqlList = new String[]{ + "delete from " + tableName + " where 1=1", + "delete from " + tableName + " where a < 300", + "delete from " + tableName + " where a = 2", + "delete from " + tableName + " where b=1", + "delete from " + tableName + " where a = 1 and b=1", + "delete from " + tableName + " where 1=1 order by a limit 6",}; //{6, 2, 1, 1, 1, 1, 1} List> trace; int brdDbCount = getDataSourceCount() - 1 - 3;//minus metadb+scaleoutdb - int[] scans = new int[] {1, 1, 1, 1, 1, 1, 1}; + int[] scans = new int[]{1, 1, 1, 1, 1, 1, 1}; int[] physicalOperations = - new int[] { - brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, - brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1}; + new int[]{ + brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, + brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = physicalOperations[i]; @@ -1027,27 +1027,27 @@ public void brdTablePkAndUkForDelete() { executeDml(sql); String hint = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,PLAN_CACHE=false)*/ "; - String[] sqlList = new String[] { - "delete from " + tableName + " where 1=1", - "delete from " + tableName + " where a < 300", - "delete from " + tableName + " where a = 2", - "delete from " + tableName + " where b=1", - "delete from " + tableName + " where c=1", - "delete from " + tableName + " where a = 1 and b=1", - "delete from " + tableName + " where a = 1 and b=1 and c=1", - "delete from " + tableName + " where 1=1 order by a limit 6",}; + String[] sqlList = new String[]{ + "delete from " + tableName + " where 1=1", + "delete from " + tableName + " where a < 300", + "delete from " + tableName + " where a = 2", + "delete from " + tableName + " where b=1", + "delete from " + tableName + " where c=1", + "delete from " + tableName + " where a = 1 and b=1", + "delete from " + tableName + " where a = 1 and b=1 and c=1", + "delete from " + tableName + " where 1=1 order by a limit 6",}; //{6, 2, 1, 1, 1, 1, 1} List> trace; int brdDbCount = getDataSourceCount() - 1 - 3;//minus metadb+scaleoutdb - int[] scans = new int[] {1, 1, 1, 1, 1, 1, 1, 1}; + int[] scans = new int[]{1, 1, 1, 1, 1, 1, 1, 1}; int[] physicalOperations = - new int[] { - brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, - brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1}; + new int[]{ + brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, + brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1, brdDbCount + 1 + 1 + 1}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = physicalOperations[i]; @@ -1067,51 +1067,51 @@ public void tablePkNoUkForUpdate() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName; executeDml(sql); String hint = - "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; - - String[] sqlList = new String[] { - "update " + tableName + " set k=k+1", - "update " + tableName + " set k=k+1 where a=1", - "update " + tableName + " set k=k+1 where a=1 and b=1", - "update " + tableName + " set k=k+1 where b=1", - "update " + tableName + " set a=a+1 where a<100",//5 - "update " + tableName + " set b=b-1 where a<100", - "update " + tableName + " set b=b-1,a=a+1 where b<100", - "update " + tableName + " set a=a-1 where a=1", - "update " + tableName + " set b=b-1 where a=1", - "update " + tableName + " set b=b-1,a=a+1 where a=1",//10 - "update " + tableName + " set a=a+1 where a=1 and b=1", - "update " + tableName + " set b=b-1 where a=1 and b=1", - "update " + tableName + " set b=b-1,a=a+1 where a=1 and b=1", - "update " + tableName + " set a=a+1 where b=1", - "update " + tableName + " set b=b-1 where b=1",//15 - "update " + tableName + " set b=b-1,a=a+1 where b=1", - "update " + tableName + " set k=k+1 order by a limit 6", - "update " + tableName + " set a=a+1 where a<>3 order by a limit 6", - "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6",}; + "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; + + String[] sqlList = new String[]{ + "update " + tableName + " set k=k+1", + "update " + tableName + " set k=k+1 where a=1", + "update " + tableName + " set k=k+1 where a=1 and b=1", + "update " + tableName + " set k=k+1 where b=1", + "update " + tableName + " set a=a+1 where a<100",//5 + "update " + tableName + " set b=b-1 where a<100", + "update " + tableName + " set b=b-1,a=a+1 where b<100", + "update " + tableName + " set a=a-1 where a=1", + "update " + tableName + " set b=b-1 where a=1", + "update " + tableName + " set b=b-1,a=a+1 where a=1",//10 + "update " + tableName + " set a=a+1 where a=1 and b=1", + "update " + tableName + " set b=b-1 where a=1 and b=1", + "update " + tableName + " set b=b-1,a=a+1 where a=1 and b=1", + "update " + tableName + " set a=a+1 where b=1", + "update " + tableName + " set b=b-1 where b=1",//15 + "update " + tableName + " set b=b-1,a=a+1 where b=1", + "update " + tableName + " set k=k+1 order by a limit 6", + "update " + tableName + " set a=a+1 where a<>3 order by a limit 6", + "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6",}; List> trace; final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); int dbCount = getDataSourceCount() - 1 - 1 - 3;//minus metadb+scaleoutdb + singledb int[] scans = - new int[] { - dbCount, 1, 1, dbCount, dbCount, - dbCount, dbCount, 1, 1, 1, - 1, 1, 1, dbCount, dbCount, - dbCount, dbCount, dbCount, 1}; + new int[]{ + dbCount, 1, 1, dbCount, dbCount, + dbCount, dbCount, 1, 1, 1, + 1, 1, 1, dbCount, dbCount, + dbCount, dbCount, dbCount, 1}; //0 delete 0 + insert 1 //1 delete 1 + insert 2 //2 delete 2 + insert 3 int[] writablePhysicalOperations = - new int[] { - 6 + 1 + 1 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), - 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 1 * 2 + 1, 1 * 2 + 2, - 1 * 2 + 1 * 2, - 1 * 2 + 1 * 2, 1 * 2 + 2, 1 * 2 + 1 * 2, 1 * 2 + 1 * 2, 1 * 2 + 2, - 1 * 2 + 1 * 2, 6 + 1 + 1 + 1, 5 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 1 + 1}; + new int[]{ + 6 + 1 + 1 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), + 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 1 * 2 + 1, 1 * 2 + 2, + 1 * 2 + 1 * 2, + 1 * 2 + 1 * 2, 1 * 2 + 2, 1 * 2 + 1 * 2, 1 * 2 + 1 * 2, 1 * 2 + 2, + 1 * 2 + 1 * 2, 6 + 1 + 1 + 1, 5 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 1 + 1}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,k) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(0,0,0)"; + + "(a,b,k) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(0,0,0)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = writablePhysicalOperations[i]; @@ -1131,53 +1131,53 @@ public void tablePkAndUkForUpdate() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName; executeDml(sql); String hint = - "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; - - String[] sqlList = new String[] { - "update " + tableName + " set k=k+1", - "update " + tableName + " set k=k+1 where a=1", - "update " + tableName + " set k=k+1 where a=1 and b=1", - "update " + tableName + " set k=k+1 where b=1", - "update " + tableName + " set a=a+1 where a<100",//5 - "update " + tableName + " set b=b-1 where a<100", - "update " + tableName + " set b=b-1,a=a+1 where b<100", - "update " + tableName + " set a=a+1 where a=1", - "update " + tableName + " set b=b-1 where a=1", - "update " + tableName + " set b=b-1,a=a+1 where a=1",//10 - "update " + tableName + " set a=a+1 where a=1 and b=1", - "update " + tableName + " set b=b-1 where a=1 and b=1", - "update " + tableName + " set b=b-1,a=a+1 where a=1 and b=1", - "update " + tableName + " set a=a+1 where b=1", - "update " + tableName + " set b=b-1 where b=1",//15 - "update " + tableName + " set b=b-1,a=a+1 where b=1", - "update " + tableName + " set k=k+1 order by a limit 6", - "update " + tableName + " set a=a+1 where a<>3 order by a limit 6", - "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6", - "update " + tableName + " set c=c-1 where b=1", - "update " + tableName + " set c=c-1 where a=1", + "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; + + String[] sqlList = new String[]{ + "update " + tableName + " set k=k+1", + "update " + tableName + " set k=k+1 where a=1", + "update " + tableName + " set k=k+1 where a=1 and b=1", + "update " + tableName + " set k=k+1 where b=1", + "update " + tableName + " set a=a+1 where a<100",//5 + "update " + tableName + " set b=b-1 where a<100", + "update " + tableName + " set b=b-1,a=a+1 where b<100", + "update " + tableName + " set a=a+1 where a=1", + "update " + tableName + " set b=b-1 where a=1", + "update " + tableName + " set b=b-1,a=a+1 where a=1",//10 + "update " + tableName + " set a=a+1 where a=1 and b=1", + "update " + tableName + " set b=b-1 where a=1 and b=1", + "update " + tableName + " set b=b-1,a=a+1 where a=1 and b=1", + "update " + tableName + " set a=a+1 where b=1", + "update " + tableName + " set b=b-1 where b=1",//15 + "update " + tableName + " set b=b-1,a=a+1 where b=1", + "update " + tableName + " set k=k+1 order by a limit 6", + "update " + tableName + " set a=a+1 where a<>3 order by a limit 6", + "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6", + "update " + tableName + " set c=c-1 where b=1", + "update " + tableName + " set c=c-1 where a=1", }; //{6, 2, 1, 1, 1, 1, 1} List> trace; int dbCount = getDataSourceCount() - 1 - 1 - 3;//minus metadb+scaleoutdb + singledb int[] scans = - new int[] { - dbCount, 1, 1, dbCount, dbCount, - dbCount, dbCount, 1, 1, 1, - 1, 1, 1, dbCount, dbCount, - dbCount, dbCount, dbCount, 1, dbCount, - 1}; + new int[]{ + dbCount, 1, 1, dbCount, dbCount, + dbCount, dbCount, 1, 1, 1, + 1, 1, 1, dbCount, dbCount, + dbCount, dbCount, dbCount, 1, dbCount, + 1}; int[] writablePhysicalOperations = - new int[] { - 6 + 1 + 1 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), - 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 1 * 2 + 2, 1 * 2 + 2, - 1 * 2 + 2, - 1 * 2 + 2, 1 * 2 + 2, 1 * 2 + 2, 1 * 2 + 2, 1 * 2 + 2, - 1 * 2 + 2, 6 + 1 + 1 + 1, 5 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 1 + 1, 1 + 1, - 1 + 1}; + new int[]{ + 6 + 1 + 1 + 1, 1 + 1, 1 + 1, 1 + 1, 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), + 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 6 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 1 * 2 + 2, 1 * 2 + 2, + 1 * 2 + 2, + 1 * 2 + 2, 1 * 2 + 2, 1 * 2 + 2, 1 * 2 + 2, 1 * 2 + 2, + 1 * 2 + 2, 6 + 1 + 1 + 1, 5 * 2 + (1 + 0) + (1 + 1) + (1 + 1), 1 + 1, 1 + 1, + 1 + 1}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,c,k) values(1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (5,5,5,5),(0,0,0,0)"; + + "(a,b,c,k) values(1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (5,5,5,5),(0,0,0,0)"; executeDml(sql); sql = sqlList[i]; int physicalOperation = writablePhysicalOperations[i]; @@ -1198,49 +1198,49 @@ public void brdTablePkNoUkForUpdate() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName; executeDml(sql); String hint = - "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; - - String[] sqlList = new String[] { - "update " + tableName + " set k=k+1", - "update " + tableName + " set k=k+1 where a=1", - "update " + tableName + " set k=k+1 where a=1 and b=1", - "update " + tableName + " set k=k+1 where b=1", - "update " + tableName + " set a=a-1 where a<100",//5 - "update " + tableName + " set b=b-1 where a<100", - "update " + tableName + " set b=b-1,a=a-1 where b<100", - "update " + tableName + " set a=a-1 where a=1", - "update " + tableName + " set b=b-1 where a=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 - "update " + tableName + " set a=a-1 where a=1 and b=1", - "update " + tableName + " set b=b-1 where a=1 and b=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", - "update " + tableName + " set a=a-1 where b=1", - "update " + tableName + " set b=b-1 where b=1",//15 - "update " + tableName + " set b=b-1,a=a-1 where b=1", - "update " + tableName + " set k=k+1 order by a limit 6", - "update " + tableName + " set a=a+10 where a<>3 order by a limit 6", - "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6",}; + "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; + + String[] sqlList = new String[]{ + "update " + tableName + " set k=k+1", + "update " + tableName + " set k=k+1 where a=1", + "update " + tableName + " set k=k+1 where a=1 and b=1", + "update " + tableName + " set k=k+1 where b=1", + "update " + tableName + " set a=a-1 where a<100",//5 + "update " + tableName + " set b=b-1 where a<100", + "update " + tableName + " set b=b-1,a=a-1 where b<100", + "update " + tableName + " set a=a-1 where a=1", + "update " + tableName + " set b=b-1 where a=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 + "update " + tableName + " set a=a-1 where a=1 and b=1", + "update " + tableName + " set b=b-1 where a=1 and b=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", + "update " + tableName + " set a=a-1 where b=1", + "update " + tableName + " set b=b-1 where b=1",//15 + "update " + tableName + " set b=b-1,a=a-1 where b=1", + "update " + tableName + " set k=k+1 order by a limit 6", + "update " + tableName + " set a=a+10 where a<>3 order by a limit 6", + "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6",}; //{6, 2, 1, 1, 1, 1, 1} List> trace; int brdDbCount = getDataSourceCount() - 1 - 3;//minus metadb+scaleoutdb int scan = 1; int[] writablePhysicalOperations = - new int[] { - scan + brdDbCount + 1 + 1 + 1, scan + brdDbCount + 1 + 1 + 1, scan + brdDbCount + 1 + 1 + 1, - scan + brdDbCount + 1 + 1 + 1, - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount + 1 + 1 + 1, scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount + 1 + 1 + 1, scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 1 + 1 + 1, - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 1 + 1 + 1, - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 1 + 1 + 1, - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 1 + 1 + 1}; + new int[]{ + scan + brdDbCount + 1 + 1 + 1, scan + brdDbCount + 1 + 1 + 1, scan + brdDbCount + 1 + 1 + 1, + scan + brdDbCount + 1 + 1 + 1, + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount + 1 + 1 + 1, scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount + 1 + 1 + 1, scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 1 + 1 + 1, + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 1 + 1 + 1, + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 1 + 1 + 1, + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 1 + 1 + 1}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,k) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,k) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; executeDml(sql); sql = sqlList[i]; executeDml("trace " + hint + sql); @@ -1258,56 +1258,56 @@ public void brdTablePkAndUkForUpdate() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName; executeDml(sql); String hint = - "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; - - String[] sqlList = new String[] { - "update " + tableName + " set k=k+1", - "update " + tableName + " set k=k+1 where a=1", - "update " + tableName + " set k=k+1 where a=1 and b=1", - "update " + tableName + " set k=k+1 where b=1", - "update " + tableName + " set a=a-1 where a<100",//5 - "update " + tableName + " set b=b-1 where a<100", - "update " + tableName + " set b=b-1,a=a-1 where b<100", - "update " + tableName + " set a=a-1 where a=1", - "update " + tableName + " set b=b-1 where a=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 - "update " + tableName + " set a=a-1 where a=1 and b=1", - "update " + tableName + " set b=b-1 where a=1 and b=1", - "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", - "update " + tableName + " set a=a-1 where b=1", - "update " + tableName + " set b=b-1 where b=1",//15 - "update " + tableName + " set b=b-1,a=a-1 where b=1", - "update " + tableName + " set k=k+1 order by a limit 6", - "update " + tableName + " set a=a+10 where a<>3 order by a limit 6", - "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6", - "update " + tableName + " set c=c-1 where b=1",//20 - "update " + tableName + " set c=c-1 where a=1", + "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true,ENABLE_MODIFY_SHARDING_COLUMN=TRUE,PLAN_CACHE=false)*/ "; + + String[] sqlList = new String[]{ + "update " + tableName + " set k=k+1", + "update " + tableName + " set k=k+1 where a=1", + "update " + tableName + " set k=k+1 where a=1 and b=1", + "update " + tableName + " set k=k+1 where b=1", + "update " + tableName + " set a=a-1 where a<100",//5 + "update " + tableName + " set b=b-1 where a<100", + "update " + tableName + " set b=b-1,a=a-1 where b<100", + "update " + tableName + " set a=a-1 where a=1", + "update " + tableName + " set b=b-1 where a=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1",//10 + "update " + tableName + " set a=a-1 where a=1 and b=1", + "update " + tableName + " set b=b-1 where a=1 and b=1", + "update " + tableName + " set b=b-1,a=a-1 where a=1 and b=1", + "update " + tableName + " set a=a-1 where b=1", + "update " + tableName + " set b=b-1 where b=1",//15 + "update " + tableName + " set b=b-1,a=a-1 where b=1", + "update " + tableName + " set k=k+1 order by a limit 6", + "update " + tableName + " set a=a+10 where a<>3 order by a limit 6", + "update " + tableName + " set k=k-1 where a=1 and b=1 order by a limit 6", + "update " + tableName + " set c=c-1 where b=1",//20 + "update " + tableName + " set c=c-1 where a=1", }; List> trace; int brdDbCount = getDataSourceCount() - 1 - 3;//minus metadb+scaleoutdb int scan = 1; int[] writablePhysicalOperations = - new int[] { - scan + brdDbCount + 3, scan + brdDbCount + 3, scan + brdDbCount + 3, scan + brdDbCount + 3, - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 3, - scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 3, - scan + brdDbCount + 3, - scan + brdDbCount + 3}; + new int[]{ + scan + brdDbCount + 3, scan + brdDbCount + 3, scan + brdDbCount + 3, scan + brdDbCount + 3, + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 3, + scan + brdDbCount * 2 + (1 + 0) + (1 + 1) + (1 + 1), scan + brdDbCount + 3, + scan + brdDbCount + 3, + scan + brdDbCount + 3}; for (int i = 0; i < sqlList.length; i++) { sql = "insert into " + tableName - + "(a,b,c,k) values(1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (5,5,5,5),(6,6,6,6)"; + + "(a,b,c,k) values(1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (5,5,5,5),(6,6,6,6)"; executeDml(sql); sql = sqlList[i]; executeDml("trace " + hint + sql); @@ -1329,7 +1329,7 @@ public void tablePkNoUkForUpsert() { executeDml(sql); sql = "insert into " + tableName - + "(a,b) values(1,1), (2,2), (3,3), (4-2+2,4), (5,5),(9+0-9,0) on duplicate key update b=b+1+3"; + + "(a,b) values(1,1), (2,2), (3,3), (4-2+2,4), (5,5),(9+0-9,0) on duplicate key update b=b+1+3"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); @@ -1339,32 +1339,32 @@ public void tablePkNoUkForUpsert() { int shrdDbCount = getDataSourceCount() - 1 - 1 - 3;//minus metadb+scaleoutdb+singledb int basePhyInsert = 6; - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + topology.size() + 0 + 1 + 1)); + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + 0 + 1 + 1)); for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b) values(1,1+1-1) on duplicate key update b=b+1+3"; + + "(a,b) values(1,1+1-1) on duplicate key update b=b+1+3"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i == 0 ? 4 : 2; - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); sql = "insert into " + tableName - + "(a,b) values(0,0+1-1) on duplicate key update b=b+1+3"; + + "(a,b) values(0,0+1-1) on duplicate key update b=b+1+3"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i == 0 ? 3 : 1; - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); sql = "insert into " + tableName - + "(a,b) values(2,2+1-1) on duplicate key update b=b+1+3"; + + "(a,b) values(2,2+1-1) on duplicate key update b=b+1+3"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i == 0 ? 4 : 2; - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); if (i == 0) { sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; @@ -1372,12 +1372,12 @@ public void tablePkNoUkForUpsert() { } } sql = "insert into " + tableName - + "(a,b) values(1+1-1,2) on duplicate key update a=a+" + String.valueOf(shrdDbCount) + "*20, b=b+2"; + + "(a,b) values(1+1-1,2) on duplicate key update a=a+" + String.valueOf(shrdDbCount) + "*20, b=b+2"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); - basePhyInsert = 4; //4:(delete + insert) * 2 - Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); + basePhyInsert = 2; //2:(insert) * 2 + Assert.assertThat(trace.toString(), trace.size(), is(1 + basePhyInsert)); } @@ -1392,13 +1392,13 @@ public void tablePkNoUkForUpsertSelect() { executeDml(sql); sql = "insert into " + sourceTableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(0,0)"; - String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(0,0)"; + String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false, DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=false)*/ "; executeDml(hintStr + sql); sql = "insert into " + tableName - + "(a,b) select a+1-1,b+1-1 from " + sourceTableName + " on duplicate key update b=b+1+3"; + + "(a,b) select a+1-1,b+1-1 from " + sourceTableName + " on duplicate key update b=b+1+3"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -1406,32 +1406,32 @@ public void tablePkNoUkForUpsertSelect() { int shrdDbCount = getDataSourceCount() - 1 - 1 - 3;//minus metadb+scaleoutdb+singledb int basePhyInsert = 6; - Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert + 2 * topology.size() + 0 + 1 + 1)); + Assert.assertThat(trace.toString(), trace.size(), is(basePhyInsert * 2 + topology.size() + 0 + 1 + 1)); for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b) select a+1-1,b from " + sourceTableName + " where a=1+1-1 on duplicate key update b=b+1+3"; + + "(a,b) select a+1-1,b from " + sourceTableName + " where a=1+1-1 on duplicate key update b=b+1+3"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i == 0 ? 4 : 2; - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + Assert.assertThat(trace.toString(), trace.size(), is(1 + topology.size() + basePhyInsert)); sql = "insert into " + tableName - + "(a,b) select a+1-1,b from " + sourceTableName + " where a=0+1-1 on duplicate key update b=b+1+3"; + + "(a,b) select a+1-1,b from " + sourceTableName + " where a=0+1-1 on duplicate key update b=b+1+3"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i == 0 ? 3 : 1; - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + Assert.assertThat(trace.toString(), trace.size(), is(1 + topology.size() + basePhyInsert)); sql = "insert into " + tableName - + "(a,b) select a+1-1,b from " + sourceTableName + " where a=2+1-1 on duplicate key update b=b+1+3"; + + "(a,b) select a+1-1,b from " + sourceTableName + " where a=2+1-1 on duplicate key update b=b+1+3"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = i == 0 ? 4 : 2; - Assert.assertThat(trace.toString(), trace.size(), is(2 * topology.size() + basePhyInsert)); + Assert.assertThat(trace.toString(), trace.size(), is(1 + topology.size() + basePhyInsert)); if (i == 0) { sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; @@ -1439,13 +1439,13 @@ public void tablePkNoUkForUpsertSelect() { } } sql = "insert into " + tableName - + "(a,b) select a,b+1 from " + sourceTableName + " where a=1 on duplicate key update a=a+" + String - .valueOf(shrdDbCount) + "*20, b=b+2"; + + "(a,b) select a,b+1 from " + sourceTableName + " where a=1 on duplicate key update a=a+" + String + .valueOf(shrdDbCount) + "*20, b=b+2"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); - basePhyInsert = 4; //4:(delete + insert) * 2 - Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + topology.size() + basePhyInsert)); + basePhyInsert = 2; //2:(insert) * 2 + Assert.assertThat(trace.toString(), trace.size(), is(tbPartitions + 1 + basePhyInsert)); } @@ -1456,7 +1456,7 @@ public void tablePkAndUkForUpsert() { executeDml(sql); sql = "insert into " + tableName - + "(a,b,c) values(1,1,1), (2,2+1-1,2), (3,3,3), (4,4,4), (5,5+2-2,5),(0,0,0) on duplicate key update a=a+1"; + + "(a,b,c) values(1,1,1), (2,2+1-1,2), (3,3,3), (4,4,4), (5,5+2-2,5),(0,0,0) on duplicate key update a=a+1"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); @@ -1470,7 +1470,7 @@ public void tablePkAndUkForUpsert() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b,c) values(1,1+1-1,1) on duplicate key update b=b+1"; + + "(a,b,c) values(1,1+1-1,1) on duplicate key update b=b+1"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1478,7 +1478,7 @@ public void tablePkAndUkForUpsert() { Assert.assertThat(trace.toString(), trace.size(), is(scanForDuplicateCheck + basePhyInsert)); sql = "insert into " + tableName - + "(a,b,c) values(0,0+1-1,1) on duplicate key update b=b+1"; + + "(a,b,c) values(0,0+1-1,1) on duplicate key update b=b+1"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1486,7 +1486,7 @@ public void tablePkAndUkForUpsert() { Assert.assertThat(trace.toString(), trace.size(), is(scanForDuplicateCheck + basePhyInsert)); sql = "insert into " + tableName - + "(a,b,c) values(2,2+1-1,1) on duplicate key update b=b+1"; + + "(a,b,c) values(2,2+1-1,1) on duplicate key update b=b+1"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1511,13 +1511,13 @@ public void tablePkAndUkForUpsertSelect() { executeDml(sql); sql = "insert into " + sourceTableName - + "(a,b,c) values(1,1,1), (2,2,2+1-1), (3,3,3), (4,4,4), (5,5,5),(0,0,0)"; + + "(a,b,c) values(1,1,1), (2,2,2+1-1), (3,3,3), (4,4,4), (5,5,5),(0,0,0)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false, MERGE_UNION=false)*/ "; executeDml(hintStr + sql); sql = "insert into " + tableName - + "(a,b,c) select a+1-1,b,c from " + sourceTableName + " where a<>2+12324 on duplicate key update a=a+1"; + + "(a,b,c) select a+1-1,b,c from " + sourceTableName + " where a<>2+12324 on duplicate key update a=a+1"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); List> trace = getTrace(tddlConnection); @@ -1529,34 +1529,34 @@ public void tablePkAndUkForUpsertSelect() { int scanForDuplicateCheck = 1; for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b,c) select a,b+2-2,c from " + sourceTableName - + " where a=1 and 2=2 on duplicate key update b=b+2"; + + "(a,b,c) select a,b+2-2,c from " + sourceTableName + + " where a=1 and 2=2 on duplicate key update b=b+2"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 4 : 2); //4:(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), - is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); + is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); sql = "insert into " + tableName - + "(a,b,c) select a,b+2-2,c from " + sourceTableName - + " where a=0 and 2=2 on duplicate key update b=b+2"; + + "(a,b,c) select a,b+2-2,c from " + sourceTableName + + " where a=0 and 2=2 on duplicate key update b=b+2"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 3 : 1); //4:(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), - is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); + is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); sql = "insert into " + tableName - + "(a,b,c) select a,b+2-2,c from " + sourceTableName - + " where a=2 and 2=2 on duplicate key update b=b+2"; + + "(a,b,c) select a,b+2-2,c from " + sourceTableName + + " where a=2 and 2=2 on duplicate key update b=b+2"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); basePhyInsert = (i == 0 ? 4 : 2); //4:(delete + insert) * 2 Assert.assertThat(trace.toString(), trace.size(), - is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); + is(tbPartitions + scanForDuplicateCheck + basePhyInsert)); if (i == 0) { sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; @@ -1564,7 +1564,7 @@ public void tablePkAndUkForUpsertSelect() { } } sql = "insert into " + tableName - + "(a,b,c) select a,b,c+2 from " + sourceTableName + " where a=1 on duplicate key update b=b+20"; + + "(a,b,c) select a,b,c+2 from " + sourceTableName + " where a=1 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1579,7 +1579,7 @@ public void brdTablePkNoUkForUpsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert into " + tableName - + "(a,b) values(1+1-1,1), (2,2+1-1), (3,3), (4,4), (5,5),(0,0) on duplicate key update b=b+20"; + + "(a,b) values(1+1-1,1), (2,2+1-1), (3,3), (4,4), (5,5),(0,0) on duplicate key update b=b+20"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); @@ -1592,7 +1592,7 @@ public void brdTablePkNoUkForUpsert() { for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b) values(1+2-2,1) on duplicate key update b=b+20"; + + "(a,b) values(1+2-2,1) on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1600,7 +1600,7 @@ public void brdTablePkNoUkForUpsert() { Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); sql = "insert into " + tableName - + "(a,b) values(0+2-2,0) on duplicate key update b=b+20"; + + "(a,b) values(0+2-2,0) on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1608,7 +1608,7 @@ public void brdTablePkNoUkForUpsert() { Assert.assertThat(trace.toString(), trace.size(), is(topology.size() + basePhyInsert)); sql = "insert into " + tableName - + "(a,b) values(2+2-2,1) on duplicate key update b=b+20"; + + "(a,b) values(2+2-2,1) on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1621,12 +1621,12 @@ public void brdTablePkNoUkForUpsert() { } } sql = "insert into " + tableName - + "(a,b) values(1,2+1-1) on duplicate key update a=a+20"; + + "(a,b) values(1,2+1-1) on duplicate key update a=a+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); Assert.assertThat(trace.toString(), trace.size(), - is(topology.size() + physicalDbCount * 2 + (0 + 1) + (1 + 1) + (1 + 1))); + is(topology.size() + physicalDbCount * 2 + (0 + 1) + (1 + 1) + (1 + 1))); } @@ -1641,14 +1641,14 @@ public void brdTablePkNoUkForUpsertSelect() { executeDml(sql); sql = "insert into " + sourceTableName - + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; + + "(a,b) values(1,1), (2,2), (3,3), (4,4), (5,5),(6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml(hintStr + sql); sql = "insert into " + tableName - + "(a,b) select a,b+1-1 from " + sourceTableName - + " where 1=1 and a<>1+23456 on duplicate key update b=b+20"; + + "(a,b) select a,b+1-1 from " + sourceTableName + + " where 1=1 and a<>1+23456 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); List> trace = getTrace(tddlConnection); @@ -1659,8 +1659,8 @@ public void brdTablePkNoUkForUpsertSelect() { for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b) select a+1-1,b from " + sourceTableName - + " where 2=2 and a=1+1-1 on duplicate key update b=b+20"; + + "(a,b) select a+1-1,b from " + sourceTableName + + " where 2=2 and a=1+1-1 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1673,7 +1673,7 @@ public void brdTablePkNoUkForUpsertSelect() { } } sql = "insert into " + tableName - + "(a,b) select a,b+1 from " + sourceTableName + " where a=1 and 2=2 on duplicate key update b=b+20"; + + "(a,b) select a,b+1 from " + sourceTableName + " where a=1 and 2=2 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1688,7 +1688,7 @@ public void brdTablePkAndUkForUpsert() { String sql = "/*+TDDL:CMD_EXTRA(ENABLE_COMPLEX_DML_CROSS_DB=true)*/ delete from " + tableName + " where 1=1"; executeDml(sql); sql = "insert into " + tableName - + "(a,b,c) values(1,1+1-1,1), (2+1-1,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6) on duplicate key update b=b+20"; + + "(a,b,c) values(1,1+1-1,1), (2+1-1,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6) on duplicate key update b=b+20"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); @@ -1700,11 +1700,11 @@ public void brdTablePkAndUkForUpsert() { int scan = topology.size(); int[] writablePhysicalOperations = - new int[] {scan + physicalDbCount * 2 + (0 + 1) + (1 + 1) + (1 + 1), scan + physicalDbCount + 0 + 1 + 1}; + new int[]{scan + physicalDbCount * 2 + (0 + 1) + (1 + 1) + (1 + 1), scan + physicalDbCount + 0 + 1 + 1}; for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b,c) values(1,1+1-1,1) on duplicate key update b=b+20"; + + "(a,b,c) values(1,1+1-1,1) on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1716,7 +1716,7 @@ public void brdTablePkAndUkForUpsert() { } } sql = "insert into " + tableName - + "(a,b,c) values(1+1-1,1,2+1-1) on duplicate key update b=b+20"; + + "(a,b,c) values(1+1-1,1,2+1-1) on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); @@ -1736,13 +1736,13 @@ public void brdTablePkAndUkForUpsertSelect() { executeDml(sql); sql = "insert into " + sourceTableName - + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; + + "(a,b,c) values(1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5),(6,6,6)"; String hintStr = " /*+TDDL:cmd_extra(PLAN_CACHE=false)*/ "; executeDml("trace " + hintStr + sql); sql = "insert into " + tableName - + "(a,b,c) select a,b,c+1-1 from " + sourceTableName + " where a<>1 or 1=1 on duplicate key update b=b+20"; + + "(a,b,c) select a,b,c+1-1 from " + sourceTableName + " where a<>1 or 1=1 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); @@ -1754,13 +1754,13 @@ public void brdTablePkAndUkForUpsertSelect() { int scan = topology.size(); int[] writablePhysicalOperations = - new int[] { - scan + 1 + physicalDbCount * 2 + (0 + 1) + (1 + 1) + (1 + 1), scan + 1 + physicalDbCount + 0 + 1 + 1}; + new int[]{ + scan + 1 + physicalDbCount * 2 + (0 + 1) + (1 + 1) + (1 + 1), scan + 1 + physicalDbCount + 0 + 1 + 1}; for (int i = 0; i < 2; i++) { sql = "insert into " + tableName - + "(a,b,c) select a+1-1,b,c from " + sourceTableName - + " where a=1 and 2+1=3 on duplicate key update b=b+20"; + + "(a,b,c) select a+1-1,b,c from " + sourceTableName + + " where a=1 and 2+1=3 on duplicate key update b=b+20"; executeDml("trace " + hintStr + sql); trace = getTrace(tddlConnection); Assert.assertThat(trace.toString(), trace.size(), is(writablePhysicalOperations[i])); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/SqlToSqlPartitionByTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/SqlToSqlPartitionByTest.java new file mode 100644 index 000000000..2fe8c475f --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/SqlToSqlPartitionByTest.java @@ -0,0 +1,82 @@ +package com.alibaba.polardbx.qatest.ddl.ttl; + +import com.alibaba.polardbx.druid.sql.ast.SQLPartitionBy; +import com.alibaba.polardbx.druid.sql.dialect.mysql.parser.MySqlCreateTableParser; +import com.alibaba.polardbx.druid.sql.parser.ByteString; +import com.alibaba.polardbx.druid.sql.parser.SQLCreateTableParser; +import com.alibaba.polardbx.optimizer.PlannerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.planner.SqlConverter; +import com.alibaba.polardbx.optimizer.parse.visitor.ContextParameters; +import com.alibaba.polardbx.optimizer.parse.visitor.FastSqlToCalciteNodeVisitor; +import com.alibaba.polardbx.optimizer.partition.PartitionInfo; +import com.alibaba.polardbx.qatest.BaseTestCase; +import com.alibaba.polardbx.qatest.ReadBaseTestCase; +import org.apache.calcite.rel.ddl.CreateTable; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlPartitionBy; +import org.apache.calcite.sql.validate.SqlValidatorImpl; +import org.junit.Test; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static com.alibaba.polardbx.qatest.data.ExecuteTableSelect.selectBaseOneTable; +import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentSameAssert; + +/** + * @author bairui.lrj@alibaba-inc.com + * @since 5.4.9 + */ + +public class SqlToSqlPartitionByTest extends BaseTestCase { + private final String table; + + public SqlToSqlPartitionByTest(String table) { + this.table = table; + } + + @Parameterized.Parameters(name = "{index}:table={0}") + public static List generateParameters() { + return Arrays.asList(selectBaseOneTable()); + } + + @Test + public void testWithoutSchema() { + buildNewPartInfoForOssTable("d1", "t1"); +// selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + public static PartitionInfo buildNewPartInfoForOssTable(String ttlTblSchema, + String ttlTblName) { + + try { + ByteString byteString = ByteString.from("PARTITION BY KEY(id) PARTITIONS 8"); + SQLCreateTableParser createTableParser = new MySqlCreateTableParser(byteString); + + SQLPartitionBy fastSqlPartByAst = createTableParser.parsePartitionBy(); + + ExecutionContext ec = new ExecutionContext(); + FastSqlToCalciteNodeVisitor visitor = + new FastSqlToCalciteNodeVisitor(new ContextParameters(false), ec); + fastSqlPartByAst.accept(visitor); + SqlPartitionBy sqlPartByAst = (SqlPartitionBy) visitor.getSqlNode(); + +// SqlConverter sqlConverter = SqlConverter.getInstance(schemaName, ec); +// PlannerContext plannerContext = PlannerContext.getPlannerContext(createTable.getCluster()); +// Map partRexInfoCtx = sqlConverter.convertPartition(tableGroupSqlPartitionBy, plannerContext); +// ((CreateTable) (createTable)).getPartBoundExprInfo().putAll(partRexInfoCtx); + + System.out.println(sqlPartByAst.toString()); + } catch (Throwable ex) { + ex.printStackTrace(); + } + + return null; + } + +} + diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/TtlPartitionTable2Test.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/TtlPartitionTable2Test.java new file mode 100644 index 000000000..c7efb0626 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/TtlPartitionTable2Test.java @@ -0,0 +1,17 @@ +package com.alibaba.polardbx.qatest.ddl.ttl; + +import com.alibaba.polardbx.qatest.ddl.auto.partition.PartitionAutoLoadSqlTestBase; +import org.junit.runners.Parameterized; + +import java.util.List; + +public class TtlPartitionTable2Test extends PartitionAutoLoadSqlTestBase { + public TtlPartitionTable2Test(AutoLoadSqlTestCaseParams parameter) { + super(parameter); + } + + @Parameterized.Parameters(name = "{index}: SubTestCase {0}") + public static List parameters() { + return getParameters(TtlPartitionTable2Test.class, 0, false); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/TtlPartitionTable3Test.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/TtlPartitionTable3Test.java new file mode 100644 index 000000000..46804dbf3 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/TtlPartitionTable3Test.java @@ -0,0 +1,17 @@ +package com.alibaba.polardbx.qatest.ddl.ttl; + +import com.alibaba.polardbx.qatest.ddl.auto.partition.PartitionAutoLoadSqlTestBase; +import org.junit.runners.Parameterized; + +import java.util.List; + +public class TtlPartitionTable3Test extends PartitionAutoLoadSqlTestBase { + public TtlPartitionTable3Test(AutoLoadSqlTestCaseParams parameter) { + super(parameter); + } + + @Parameterized.Parameters(name = "{index}: SubTestCase {0}") + public static List parameters() { + return getParameters(TtlPartitionTable3Test.class, 0, false); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/TtlPartitionTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/TtlPartitionTableTest.java new file mode 100644 index 000000000..5cd5e67f9 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/ddl/ttl/TtlPartitionTableTest.java @@ -0,0 +1,17 @@ +package com.alibaba.polardbx.qatest.ddl.ttl; + +import com.alibaba.polardbx.qatest.ddl.auto.partition.PartitionAutoLoadSqlTestBase; +import org.junit.runners.Parameterized; + +import java.util.List; + +public class TtlPartitionTableTest extends PartitionAutoLoadSqlTestBase { + public TtlPartitionTableTest(AutoLoadSqlTestCaseParams parameter) { + super(parameter); + } + + @Parameterized.Parameters(name = "{index}: SubTestCase {0}") + public static List parameters() { + return getParameters(TtlPartitionTableTest.class, 0, false); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/DefaultAsExprValueTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/DefaultAsExprValueTest.java index e06f0a4ef..5403abd2d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/DefaultAsExprValueTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/DefaultAsExprValueTest.java @@ -30,6 +30,8 @@ public class DefaultAsExprValueTest extends AutoCrudBasedLockTestCase { + " `C11` DATE NOT NULL DEFAULT (CURRENT_DATE + INTERVAL 1 YEAR)," + " `C12` varchar(20) NOT NULL DEFAULT (LPAD(''string'', 5, ''0''))," + " `C13` tinyint(1) NOT NULL DEFAULT (TRUE)," + + " `C14` binary(16) NOT NULL DEFAULT (uuid_to_bin(''e7fe4fc5-11ef-1739-accb-0242ac110012''))," +// + " `C15` varchar(64) NOT NULL DEFAULT (bin_to_uuid(0xE7FE4FC511EF1739ACCB0242AC110012))," + " PRIMARY KEY (`pk`)" + ") {0} "; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/IgnoreNoTransactionJdbcTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/IgnoreNoTransactionJdbcTest.java new file mode 100644 index 000000000..0d60a27a5 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/IgnoreNoTransactionJdbcTest.java @@ -0,0 +1,58 @@ +package com.alibaba.polardbx.qatest.dml.auto.basecrud; + +import com.alibaba.polardbx.qatest.util.ConnectionManager; +import org.junit.Assert; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +public class IgnoreNoTransactionJdbcTest { + @Test + public void test() throws SQLException { + String testDb = "IgnoreNoTransactionJdbcTest_db"; + String testTb = "IgnoreNoTransactionJdbcTest_tb"; + try (Connection conn = ConnectionManager.getInstance().newPolarDBXConnection()) { + try (Statement stmt = conn.createStatement()) { + stmt.execute("create database if not exists " + testDb + " mode=auto "); + stmt.execute("use " + testDb); + stmt.execute("create table if not exists " + testTb + "(id int, a int) partition by key(id)"); + } + } + // Make sure it is the newly created JDBC connection. + try (Connection conn = ConnectionManager.getInstance().newPolarDBXConnection()) { + try (Statement stmt = conn.createStatement()) { + stmt.execute("use " + testDb); + } + conn.setAutoCommit(true); + try (Statement stmt = conn.createStatement()) { + stmt.execute("set transaction policy 4"); + stmt.execute("select * from " + testTb + " where 1 = 2"); + } + conn.setAutoCommit(false); + try (Statement stmt = conn.createStatement()) { + stmt.execute("replace into " + testTb + " values (101, 101)"); + ResultSet rs = stmt.executeQuery("show trans"); + Assert.assertTrue("Should start a explicit transaction", rs.next()); + System.out.println(rs.getString(2)); + } + conn.commit(); + + conn.setAutoCommit(true); + try (Statement stmt = conn.createStatement()) { + stmt.execute("replace into " + testTb + " values (101, 101)"); + } + + conn.setAutoCommit(false); + try (Statement stmt = conn.createStatement()) { + stmt.execute("replace into " + testTb + " values (101, 101)"); + ResultSet rs = stmt.executeQuery("show trans"); + Assert.assertTrue("Should start a explicit transaction", rs.next()); + System.out.println(rs.getString(2)); + } + conn.commit(); + } + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/InsertSelectTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/InsertSelectTest.java index 862328767..d8553ef42 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/InsertSelectTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/InsertSelectTest.java @@ -1039,4 +1039,35 @@ public void insertWithSubQueryTest() throws Exception { sql = "select * from " + baseTwoTableName; selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); } + + @Test + public void insertWithSelectAggTest() throws Exception { + String sql = "insert into " + baseTwoTableName + + " (varchar_test, integer_test, bigint_test) select varchar_test, min(integer_test), max(integer_test) from " + + baseOneTableName + + " group by varchar_test;"; + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, sql, null, true); + + sql = "select " + selectColumn + " from " + baseTwoTableName; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + @Test + public void insertWithSelectFuncTest() throws Exception { + String sql = "insert into " + baseTwoTableName + + " (varchar_test) select lower(uuid()) from " + baseOneTableName; + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, sql, null, true); + + sql = "select varchar_test from " + baseTwoTableName; + ResultSet rs = JdbcUtil.executeQuery(sql, tddlConnection); + String uuid = ""; + while (rs.next()) { + String uuidTemp = rs.getString(1); + Assert.assertNotEquals(uuidTemp, uuid); + uuid = uuidTemp; + } + } + } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/ModifyOnTopNTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/ModifyOnTopNTest.java new file mode 100644 index 000000000..4418e8648 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/ModifyOnTopNTest.java @@ -0,0 +1,378 @@ +/* + * 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 com.alibaba.polardbx.qatest.dml.auto.basecrud; + +import com.alibaba.polardbx.qatest.AutoCrudBasedLockTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.alibaba.polardbx.qatest.validator.DataOperator; +import com.alibaba.polardbx.qatest.validator.DataValidator; +import com.google.common.truth.Truth; +import org.junit.Before; +import org.junit.Test; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + +public class ModifyOnTopNTest extends AutoCrudBasedLockTestCase { + private static final String OPTIMIZE_MODIFY_TOP_N_BY_RETURNING_HINT = + "/*+TDDL:CMD_EXTRA(OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=TRUE)*/"; + private static final String COMPLEX_DML_WITH_TRX_HINT = "/*+TDDL:CMD_EXTRA(COMPLEX_DML_WITH_TRX=TRUE)*/"; + + private static final String TABLE_DEF = "CREATE TABLE `%s` (\n" + + " `id` varchar(32) NOT NULL,\n" + + " `c1` varchar(32) NOT NULL ,\n" + + " `c2` varchar(32) NOT NULL ,\n" + + " `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,\n" + + " PRIMARY KEY USING BTREE (`id`)\n" + + " ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4\n"; + private static final List CREATE_TIME = new ArrayList<>(); + + static { + CREATE_TIME.add("2024-03-10"); + CREATE_TIME.add("2024-03-20"); + CREATE_TIME.add("2024-03-30"); + CREATE_TIME.add("2024-04-10"); + CREATE_TIME.add("2024-04-20"); + CREATE_TIME.add("2024-04-30"); + } + + private static final String INSERT_DEF = "insert into `%s`(id, c1, c2, create_time) values(?, ?, ?, ?)"; + private static final String UPDATE_LIMIT_1_DEF = + "update `%s` set c2 = 'u1' where c1 = 3 and create_time <= '2024-04-10' order by create_time desc limit 1"; + private static final String UPDATE_LIMIT_2_DEF = + "update `%s` set c2 = 'u1' where c1 <= 3 and create_time <= '2024-04-10' order by create_time desc limit 2"; + private static final String UPDATE_EQUAL_LIMIT_2_DEF = + "update `%s` set c2 = 'u1' where c1 = 1 and create_time <= '2024-03-30' order by create_time desc limit 2"; + private static final String DELETE_LIMIT_1_DEF = + "delete from `%s` where c1 = 3 and create_time <= '2024-04-10' order by create_time desc limit 1"; + private static final String SELECT_DEF = "select * from `%s` order by create_time desc"; + + private static final String HASH_PARTITION_DEF = "PARTITION BY HASH(create_time) PARTITIONS 4"; + + private boolean supportReturning = false; + + @Before + public void before() { + this.supportReturning = useXproto(tddlConnection) + && Optional.ofNullable(getStorageProperties(tddlConnection).get("supportsReturning")) + .map(Boolean::parseBoolean).orElse(false); + } + + @Test + public void testHashPartition() { + final String tableName = "test_motn_hash_partition"; + + rebuildTable(tableName, TABLE_DEF, HASH_PARTITION_DEF); + + prepareData(tableName); + + final List topology = showTopology(tddlConnection, tableName); + + modifyTopN(UPDATE_LIMIT_1_DEF, tableName); + checkTraceRowCount(topology.size() + 1); + checkData(tableName); + + modifyTopN(UPDATE_LIMIT_2_DEF, tableName); + checkTraceRowCount(topology.size() + 2); + checkData(tableName); + + modifyTopN(DELETE_LIMIT_1_DEF, tableName); + checkTraceRowCount(topology.size() + 1); + checkData(tableName); + } + + private static final String RANGE_PARTITION_DEF = " PARTITION BY RANGE COLUMNS(create_time)\n" + + " (\n" + + " PARTITION p202403a VALUES LESS THAN('2024-03-11'),\n" + + " PARTITION p202403b VALUES LESS THAN('2024-03-21'),\n" + + " PARTITION p202403c VALUES LESS THAN('2024-04-01'),\n" + + " PARTITION p202404a VALUES LESS THAN('2024-04-11'),\n" + + " PARTITION p202404b VALUES LESS THAN('2024-04-21'),\n" + + " PARTITION p202404c VALUES LESS THAN('2024-05-01')\n" + + " );\n"; + + @Test + public void testRangePartition() { + final String tableName = "test_motn_range_partition"; + + rebuildTable(tableName, TABLE_DEF, RANGE_PARTITION_DEF); + + prepareData(tableName); + + modifyTopN(UPDATE_LIMIT_1_DEF, tableName); + if (supportReturning) { + checkTraceRowCount(1); + } else { + checkTraceRowCount(4 + 1); + } + checkData(tableName); + + modifyTopN(UPDATE_LIMIT_2_DEF, tableName); + if (supportReturning) { + checkTraceRowCount(2); + } else { + checkTraceRowCount(4 + 2); + } + checkData(tableName); + + modifyTopN(DELETE_LIMIT_1_DEF, tableName); + if (supportReturning) { + checkTraceRowCount(1); + } else { + checkTraceRowCount(4 + 1); + } + checkData(tableName); + } + + private static final int PARTITION_COUNT = 16; + private static final String RANGE_SUBPARTITION_DEF = " PARTITION BY KEY(c1)\n" + + " PARTITIONS " + PARTITION_COUNT + "\n" + + " SUBPARTITION BY RANGE COLUMNS(create_time)\n" + + " (\n" + + " SUBPARTITION sp202403a VALUES LESS THAN('2024-03-11'),\n" + + " SUBPARTITION sp202403b VALUES LESS THAN('2024-03-21'),\n" + + " SUBPARTITION sp202403c VALUES LESS THAN('2024-04-01'),\n" + + " SUBPARTITION sp202404a VALUES LESS THAN('2024-04-11'),\n" + + " SUBPARTITION sp202404b VALUES LESS THAN('2024-04-21'),\n" + + " SUBPARTITION sp202404c VALUES LESS THAN('2024-05-01')\n" + + " );"; + + @Test + public void testRangeSubpartition() { + final String tableName = "test_motn_range_subpartition"; + + rebuildTable(tableName, TABLE_DEF, RANGE_SUBPARTITION_DEF); + + prepareData(tableName); + + modifyTopN(UPDATE_LIMIT_1_DEF, tableName); + if (supportReturning) { + checkTraceRowCount(1); + } else { + checkTraceRowCount(4 + 1); + } + checkData(tableName); + + modifyTopN(UPDATE_LIMIT_2_DEF, tableName); + checkTrace((msg, traceResult) -> Truth.assertWithMessage(msg).that(traceResult.size()).isGreaterThan(3)); + checkData(tableName); + + modifyTopN(UPDATE_EQUAL_LIMIT_2_DEF, tableName); + if (supportReturning) { + checkTraceRowCount(3); + } else { + checkTraceRowCount(3 + 1); + } + checkData(tableName); + + modifyTopN(DELETE_LIMIT_1_DEF, tableName); + if (supportReturning) { + checkTraceRowCount(1); + } else { + checkTraceRowCount(4 + 1); + } + checkData(tableName); + } + + private static final String RANGE_SUBPARTITION_DEF_1 = " PARTITION BY RANGE COLUMNS(create_time)\n" + + " SUBPARTITION BY KEY(c1)\n" + + " SUBPARTITIONS " + PARTITION_COUNT + "\n" + + " (\n" + + " PARTITION sp202403a VALUES LESS THAN('2024-03-11'),\n" + + " PARTITION sp202403b VALUES LESS THAN('2024-03-21'),\n" + + " PARTITION sp202403c VALUES LESS THAN('2024-04-01'),\n" + + " PARTITION sp202404a VALUES LESS THAN('2024-04-11'),\n" + + " PARTITION sp202404b VALUES LESS THAN('2024-04-21'),\n" + + " PARTITION sp202404c VALUES LESS THAN('2024-05-01')\n" + + " )"; + + @Test + public void testRangeSubpartition1() { + final String tableName = "test_motn_range_subpartition1"; + + rebuildTable(tableName, TABLE_DEF, RANGE_SUBPARTITION_DEF_1); + + prepareData(tableName); + + modifyTopN(UPDATE_LIMIT_1_DEF, tableName); + if (supportReturning) { + checkTraceRowCount(1); + } else { + checkTraceRowCount(1 + 1); + } + checkData(tableName); + + modifyTopN(UPDATE_LIMIT_2_DEF, tableName); + checkTrace((msg, traceResult) -> Truth.assertWithMessage(msg).that(traceResult.size()).isGreaterThan(3)); + checkData(tableName); + + modifyTopN(UPDATE_EQUAL_LIMIT_2_DEF, tableName); + if (supportReturning) { + checkTraceRowCount(3); + } else { + checkTraceRowCount(1 + 1); + } + checkData(tableName); + + modifyTopN(DELETE_LIMIT_1_DEF, tableName); + if (supportReturning) { + checkTraceRowCount(1); + } else { + checkTraceRowCount(1 + 1); + } + checkData(tableName); + } + + private static final String UPDATE_FAILED_1ST_ROW_DEF = + "update `%s` set id = 9 where c1 <= 3 and create_time <= '2024-04-10' order by create_time desc limit 2"; + + private static final String UPDATE_FAILED_2ND_ROW_DEF = + "update `%s` set id = 8 where c1 <= 3 and create_time <= '2024-04-10' order by create_time desc limit 2"; + + @Test + public void testUpdateAutoSavepoint() { + final String tableName = "test_motn_update_auto_savepoint"; + + rebuildTable(tableName, TABLE_DEF, RANGE_PARTITION_DEF); + + prepareData(tableName, 12); + + modifyTopNWithTrxFailedThenCommit(UPDATE_FAILED_2ND_ROW_DEF, + tableName, + "Duplicate entry '8' for key", + false); + checkData(tableName); + + modifyTopNWithTrxFailedThenCommit(UPDATE_FAILED_1ST_ROW_DEF, + tableName, + "Duplicate entry '9' for key", + false); + checkData(tableName); + } + + @Test + public void testUpdateFailed() { + final String tableName = "test_motn_update_fail"; + + rebuildTable(tableName, TABLE_DEF, RANGE_PARTITION_DEF); + + prepareData(tableName, 12); + + modifyTopNWithTrxFailedThenCommit(COMPLEX_DML_WITH_TRX_HINT + UPDATE_FAILED_2ND_ROW_DEF, + tableName, + "Duplicate entry '8' for key", + true); + checkData(tableName); + + modifyTopNWithTrxFailedThenCommit(COMPLEX_DML_WITH_TRX_HINT + UPDATE_FAILED_1ST_ROW_DEF, + tableName, + "Duplicate entry '9' for key", + true); + checkData(tableName); + } + + private void modifyTopN(String sqlTmpl, String tableName) { + final String modify = String.format(sqlTmpl, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + modify, + "trace " + OPTIMIZE_MODIFY_TOP_N_BY_RETURNING_HINT + modify, + null, + true); + } + + private void modifyTopNWithTrxFailedThenCommit(String sqlTmpl, String tableName, String errMsg, + boolean singleStatementTrx) { + final String modify = String.format(sqlTmpl, tableName); + + if (singleStatementTrx) { + JdbcUtil.executeUpdateFailed(tddlConnection, + "trace " + OPTIMIZE_MODIFY_TOP_N_BY_RETURNING_HINT + modify, + errMsg); + } else { + try { + tddlConnection.setAutoCommit(false); + JdbcUtil.executeUpdateFailed(tddlConnection, + "trace " + OPTIMIZE_MODIFY_TOP_N_BY_RETURNING_HINT + modify, + errMsg); + tddlConnection.commit(); + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + try { + tddlConnection.setAutoCommit(true); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + } + } + + private void checkData(String tableName) { + final String select = String.format(SELECT_DEF, tableName); + DataValidator.selectContentSameAssert(select, null, tddlConnection, mysqlConnection); + } + + private void rebuildTable(String tableName, String tableDef, String partitionDef) { + final String dropTable = String.format(DROP_TABLE_SQL, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, dropTable, null); + + final String createTable = String.format(tableDef, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + createTable, + createTable + partitionDef, + null, + false); + } + + private void checkTrace(BiConsumer>> checker) { + final List> traceResult = getTrace(tddlConnection); + checker.accept(Optional + .ofNullable(traceResult) + .map(tu -> tu.stream().map(r -> String.join(", ", r)).collect(Collectors.joining("\n"))) + .orElse("show trace result is null"), + traceResult); + } + + private void checkTraceRowCount(int rowCount) { + checkTrace((msg, traceResult) -> Truth.assertWithMessage(msg).that(traceResult).hasSize(rowCount)); + } + + private void prepareData(String tableName) { + prepareData(tableName, 6); + } + + private void prepareData(String tableName, int rowCount) { + final String insert = String.format(INSERT_DEF, tableName); + final List> params = new ArrayList<>(); + for (int i = 0; i < rowCount; i++) { + List param = new ArrayList<>(); + param.add(i); + param.add(i); + param.add(i); + param.add(CREATE_TIME.get(i % CREATE_TIME.size())); + params.add(param); + } + DataOperator.executeBatchOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, params); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/MultiDBSingleTableDMLTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/MultiDBSingleTableDMLTest.java new file mode 100644 index 000000000..e3c90f41a --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/MultiDBSingleTableDMLTest.java @@ -0,0 +1,103 @@ +package com.alibaba.polardbx.qatest.dml.auto.basecrud; + +import com.alibaba.polardbx.qatest.AutoCrudBasedLockTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class MultiDBSingleTableDMLTest extends AutoCrudBasedLockTestCase { + String dbOneName = "multiDBTest1"; + String dbTwoName = "multiDBTest2"; + + String createTableSQL = "create table %s (id bigint primary key, a bigint, c int) single %s ;"; + String tableName = "single_table_one"; + + @Before + public void initData() throws Exception { + JdbcUtil.dropDatabase(tddlConnection, dbOneName); + JdbcUtil.dropDatabase(tddlConnection, dbTwoName); + JdbcUtil.createPartDatabase(tddlConnection, dbOneName); + JdbcUtil.createPartDatabase(tddlConnection, dbTwoName); + } + + @After + public void after() throws Exception { + JdbcUtil.useDb(tddlConnection, polardbxOneDB); + JdbcUtil.dropDatabase(tddlConnection, dbOneName); + JdbcUtil.dropDatabase(tddlConnection, dbTwoName); + } + + @Test + public void differentDnTest() { + List storageInfo = getStorageInfo(tddlConnection, dbOneName); + //需测试不同storage的情况 + if (storageInfo.size() < 2) { + System.out.println("skip test, because there is only one storage:" + storageInfo); + return; + } + + //通过locality创建不同dn的表 + JdbcUtil.useDb(tddlConnection, dbOneName); + JdbcUtil.dropTable(tddlConnection, tableName); + JdbcUtil.executeSuccess(tddlConnection, + String.format(createTableSQL, tableName, "locality = 'dn=" + storageInfo.get(0)) + "'"); + JdbcUtil.useDb(tddlConnection, dbTwoName); + JdbcUtil.dropTable(tddlConnection, tableName); + JdbcUtil.executeSuccess(tddlConnection, + String.format(createTableSQL, tableName, "locality = 'dn=" + storageInfo.get(1)) + "'"); + + JdbcUtil.useDb(tddlConnection, dbOneName); + JdbcUtil.executeSuccess(tddlConnection, "insert into " + tableName + " values(1,1,1),(2,2,2),(3,3,3),(4,4,4)"); + + String sql = String.format("insert into %s.%s select * from %s.%s", dbTwoName, tableName, dbOneName, tableName); + JdbcUtil.executeSuccess(tddlConnection, sql); + List rows = + JdbcUtil.executeQueryAndGetColumnResult("select count(*) from " + dbTwoName + '.' + tableName, + tddlConnection, 1); + Assert.assertEquals(4, Integer.parseInt(rows.get(0))); + + String updateSql = + String.format("update %s.%s ta, %s.%s tb set ta.a = 10 where ta.id = tb.id", dbOneName, tableName, + dbTwoName, tableName); + JdbcUtil.executeSuccess(tddlConnection, updateSql); + List aResult = + JdbcUtil.executeQueryAndGetColumnResult("select a from " + dbOneName + '.' + tableName, tddlConnection, 1); + Assert.assertEquals(4, aResult.size()); + Assert.assertEquals(10, Integer.parseInt(aResult.get(0))); + + String deleteSql = + String.format("delete ta from %s.%s ta, %s.%s tb where ta.id = tb.id", dbOneName, tableName, dbTwoName, + tableName); + JdbcUtil.executeSuccess(tddlConnection, deleteSql); + List rows2 = + JdbcUtil.executeQueryAndGetColumnResult("select count(*) from " + dbOneName + '.' + tableName, + tddlConnection, 1); + Assert.assertEquals(0, Integer.parseInt(rows2.get(0))); + + } + + private List getStorageInfo(Connection con, String dbName) { + final String sql = "show ds where db = '" + dbName + "'"; + Set storageList = new HashSet<>(); + try (ResultSet result = JdbcUtil.executeQuerySuccess(con, sql)) { + while (result.next()) { + String storageName = result.getString("STORAGE_INST_ID"); + storageList.add(storageName); + } + return new ArrayList<>(storageList); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + } +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/SessionHintTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/PartitionNameHintTest.java similarity index 57% rename from polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/SessionHintTest.java rename to polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/PartitionNameHintTest.java index 90990279d..37073148d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/SessionHintTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/PartitionNameHintTest.java @@ -2,12 +2,13 @@ import com.alibaba.polardbx.common.utils.Assert; import com.alibaba.polardbx.qatest.BaseTestCase; +import com.alibaba.polardbx.qatest.CdcIgnore; import com.alibaba.polardbx.qatest.validator.DataOperator; import com.alibaba.polardbx.qatest.validator.DataValidator; import com.google.common.collect.Maps; -import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.junit.BeforeClass; import org.junit.Test; import java.sql.Connection; @@ -17,23 +18,92 @@ import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.HashSet; import java.util.Map; import java.util.Objects; import java.util.Random; +import java.util.Set; /** * Partition Hint test cases * * @author fangwu */ -public class SessionHintTest extends BaseTestCase { +@CdcIgnore( + ignoreReason = "binlog 和 replica 未支持 partition hint") +public class PartitionNameHintTest extends BaseTestCase { private static final Log log = LogFactory.getLog("ROOT"); - private static final String TBL_NAME = "session_hint_test"; - private static final String CREATE_TBL = "CREATE TABLE if not exists `session_hint_test` (\n" - + " `pk` bigint(11) NOT NULL,\n" - + " `integer_test` int(11) DEFAULT NULL,\n" - + " PRIMARY KEY (`pk`)\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8"; + private static final String SHARD_DB_NAME = "partition_name_hint_test_shard"; + private static final String AUTO_DB_NAME = "partition_name_hint_test_auto"; + private static final String AUTO_TBL_NAME1 = "partition_name_hint_test1"; + private static final String AUTO_TBL_NAME2 = "partition_name_hint_test2"; + private static final String AUTO_TBL_NAME3 = "partition_name_hint_test3"; + private static final String AUTO_TBL_NAME4 = "partition_name_hint_test4"; + private static final String DRDS_TBL_NAME = "multi_db_multi_tbl"; + private static final String DRDS_TBL_NAME2 = "multi_db_multi_tbl2"; + + /** + * auto table + */ + private static final String AUTO_CREATE_TBL = "CREATE TABLE %s(\n" + + " id bigint not null auto_increment,\n" + + " bid int,\n" + + " name varchar(30),\n" + + " birthday datetime not null,\n" + + " primary key(id)\n" + + ")\n" + + "partition by hash(id)\n" + + "partitions 8;"; + + private static final String AUTO_CREATE_TBL2 = "CREATE TABLE %s(\n" + + " id bigint not null auto_increment,\n" + + " bid int,\n" + + " name varchar(30),\n" + + " birthday datetime not null,\n" + + " primary key(id)\n" + + ")\n" + + "partition by hash(id)\n" + + "partitions 5;"; + + private static final String AUTO_CREATE_BROADCAST_TBL = "CREATE TABLE %s(\n" + + " id bigint not null auto_increment, \n" + + " bid int, \n" + + " name varchar(30), \n" + + " primary key(id)\n" + + ") BROADCAST;"; + + private static final String DRDS_CREATE_TBL = "CREATE TABLE multi_db_multi_tbl(\n" + + " id bigint not null auto_increment, \n" + + " bid int, \n" + + " name varchar(30), \n" + + " primary key(id)\n" + + ") dbpartition by hash(id) tbpartition by hash(bid) tbpartitions 3"; + + private static final String DRDS_CREATE_TBL2 = "CREATE TABLE multi_db_multi_tbl2(\n" + + " id bigint not null auto_increment, \n" + + " bid int, \n" + + " name varchar(30), \n" + + " primary key(id)\n" + + ") dbpartition by hash(id) tbpartition by hash(bid) tbpartitions 5"; + + @BeforeClass + public static void setUp() throws SQLException { + try (Connection c = getPolardbxConnection0()) { + c.createStatement().execute("drop database if exists " + SHARD_DB_NAME); + c.createStatement().execute("create database if not exists " + SHARD_DB_NAME); + c.createStatement().execute("drop database if exists " + AUTO_DB_NAME); + c.createStatement().execute("create database if not exists " + AUTO_DB_NAME + " mode = auto"); + + c.createStatement().execute("use " + AUTO_DB_NAME); + c.createStatement().execute(String.format(AUTO_CREATE_TBL, AUTO_TBL_NAME1)); + c.createStatement().execute(String.format(AUTO_CREATE_TBL, AUTO_TBL_NAME2)); + c.createStatement().execute(String.format(AUTO_CREATE_BROADCAST_TBL, AUTO_TBL_NAME3)); + c.createStatement().execute(String.format(AUTO_CREATE_TBL2, AUTO_TBL_NAME4)); + c.createStatement().execute("use " + SHARD_DB_NAME); + c.createStatement().execute(DRDS_CREATE_TBL); + c.createStatement().execute(DRDS_CREATE_TBL2); + } + } /** * test if push hint working @@ -43,17 +113,15 @@ public class SessionHintTest extends BaseTestCase { */ @Test public void testSessionHintWithShardingTable() throws SQLException { - Connection c = null; + Connection c = getPolardbxConnection(SHARD_DB_NAME); try { - c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint=DRDS_POLARX1_QATEST_APP_000001_GROUP"); - c.createStatement().execute("trace select * from select_base_three_multi_db_one_tb"); + c.createStatement().execute("set partition_hint=PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP"); + c.createStatement().execute("trace select * from " + DRDS_TBL_NAME); ResultSet rs = c.createStatement().executeQuery("show trace"); while (rs.next()) { String groupName = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupName.equalsIgnoreCase("DRDS_POLARX1_QATEST_APP_000001_GROUP")); + Assert.assertTrue(groupName.equalsIgnoreCase("PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP")); } } finally { Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); @@ -72,11 +140,10 @@ public void testSessionHintWithAutoTable() throws SQLException { Connection c = null; try { c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_part_qatest_app"); + c.createStatement().execute("use " + AUTO_DB_NAME); - String tableName = "select_base_three_multi_db_multi_tb"; ResultSet topologyRs = - c.createStatement().executeQuery("show topology from " + tableName); + c.createStatement().executeQuery("show topology from " + AUTO_TBL_NAME1); Map partGroupMap = Maps.newHashMap(); while (topologyRs.next()) { String groupName = topologyRs.getString("GROUP_NAME"); @@ -88,11 +155,11 @@ public void testSessionHintWithAutoTable() throws SQLException { for (Map.Entry entry : partGroupMap.entrySet()) { String partName = entry.getKey(); String checkGroupName = entry.getValue(); - checkHintWork(c, TBL_NAME); + checkHintWork(c, AUTO_TBL_NAME1); c.createStatement().execute("set partition_hint=" + partName); ResultSet rs; String joinSql = - "trace select * from " + tableName + " a join select_base_two_multi_db_multi_tb b on a.pk=b.pk"; + "trace select * from " + AUTO_TBL_NAME1 + " a join " + AUTO_TBL_NAME2 + " b on a.id=b.id"; c.createStatement().executeQuery(joinSql); rs = c.createStatement().executeQuery("show trace"); @@ -105,7 +172,7 @@ public void testSessionHintWithAutoTable() throws SQLException { // broadcast table try { String sqlWithBroadcast = - "trace select * from select_base_two_multi_db_one_tb a join select_base_four_broadcast b on a.pk=b.pk;"; + "trace select * from " + AUTO_TBL_NAME1 + " a join " + AUTO_TBL_NAME3 + " b on a.id=b.bid;"; c.createStatement().execute("set partition_hint=p3"); c.createStatement().executeQuery(sqlWithBroadcast); } catch (SQLException sqlException) { @@ -117,14 +184,14 @@ public void testSessionHintWithAutoTable() throws SQLException { // partition hint won't infect broadcast table try { - String sqlWithBroadcast = "trace select * from select_base_four_broadcast b"; + String sqlWithBroadcast = "trace select * from " + AUTO_TBL_NAME3 + " b"; c.createStatement().execute("set partition_hint=p3333"); c.createStatement().executeQuery(sqlWithBroadcast); ResultSet rs = c.createStatement().executeQuery("show trace"); String groupName; while (rs.next()) { groupName = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupName.equalsIgnoreCase("DRDS_POLARX1_PART_QATEST_APP_P00000_GROUP")); + Assert.assertTrue(groupName.equalsIgnoreCase("PARTITION_NAME_HINT_TEST_AUTO_P00000_GROUP")); } rs.close(); } catch (SQLException sqlException) { @@ -135,8 +202,7 @@ public void testSessionHintWithAutoTable() throws SQLException { } try { - String errorSql = - "trace select * from select_base_two_multi_db_one_tb a"; + String errorSql = "trace select * from " + AUTO_TBL_NAME1 + " a"; c.createStatement().execute("set partition_hint=p1111"); c.createStatement().executeQuery(errorSql); Assert.fail(" error sql should product error msg"); @@ -144,7 +210,7 @@ public void testSessionHintWithAutoTable() throws SQLException { sqlException.printStackTrace(); log.info(sqlException.getMessage()); Assert.assertTrue( - sqlException.getMessage().contains("Unsupported to use direct HINT ")); + sqlException.getMessage().contains("Unsupported direct HINT for part table :p1111")); } } finally { Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); @@ -160,7 +226,7 @@ public void testSessionHintWithNonTableStmt() throws SQLException { Connection c = null; try { c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_part_qatest_app"); + c.createStatement().execute("use " + AUTO_DB_NAME); c.createStatement().execute("set partition_hint=p3"); c.createStatement().execute("SELECT @@session.transaction_read_only"); } finally { @@ -179,11 +245,11 @@ public void testSessionHintWithTrans() throws SQLException { c1 = getPolardbxConnection(); c2 = getPolardbxConnection(); c3 = getPolardbxConnection(); - c1.createStatement().execute("use drds_polarx1_part_qatest_app"); - c2.createStatement().execute("use drds_polarx1_part_qatest_app"); - c3.createStatement().execute("use drds_polarx1_part_qatest_app"); + c1.createStatement().execute("use " + AUTO_DB_NAME); + c2.createStatement().execute("use " + AUTO_DB_NAME); + c3.createStatement().execute("use " + AUTO_DB_NAME); - String tableName = "update_delete_base_date_one_multi_db_one_tb"; + String tableName = AUTO_TBL_NAME2; // c1 using hint, truncate data c1.createStatement().execute("truncate table " + tableName); @@ -200,8 +266,7 @@ public void testSessionHintWithTrans() throws SQLException { // c1 begin and insert c1.setAutoCommit(false); - c1.createStatement().execute("insert into " + tableName - + " values(1,1,'a','a',null,1,1,1,1,1,1,1,1,1,now(), now(),now(),now(),now(),'a')"); + c1.createStatement().execute("insert into " + tableName + " values(1,1,'a',now())"); // c2 check no data rs = c2.createStatement().executeQuery("select * from " + tableName); @@ -235,70 +300,18 @@ public void testSessionHintWithTrans() throws SQLException { } } - @Test - public void testSessionHintWithDdl() throws SQLException { - Connection connWithHint = null; - Connection connWithoutHint = null; - Random r = new Random(); - String tblName = "session_hint_ddl_test_tb_" + r.nextInt(10000); - try { - connWithoutHint = getPolardbxConnection(); - connWithoutHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - connWithHint = getPolardbxConnection(); - connWithHint.createStatement().execute("use drds_polarx1_part_qatest_app"); - - connWithHint.createStatement().execute("set partition_hint=p3"); - - // test hint working - checkHintWork(connWithHint, "select_base_three_multi_db_one_tb"); - - // test create logical table - connWithHint.createStatement().execute("CREATE TABLE " + tblName + " (\n" - + "\t`id` bigint(20) NOT NULL,\n" - + "\t`ubigint_id` bigint(20) UNSIGNED DEFAULT NULL\n" - + ") ENGINE = InnoDB DEFAULT CHARSET = utf8"); - - // get partition name and group name - ResultSet rs = connWithHint.createStatement().executeQuery("show topology from " + tblName); - rs.next(); - String groupName = rs.getString("GROUP_NAME"); - String partitionName = rs.getString("PARTITION_NAME"); - - Assert.assertTrue(StringUtils.isNotEmpty(partitionName) && StringUtils.isNotEmpty(groupName)); - rs.close(); - - // check session hint working for new table - connWithHint.createStatement().execute("set partition_hint= " + partitionName); - connWithHint.createStatement().execute("trace select * from " + tblName); - rs = connWithHint.createStatement().executeQuery("show trace"); - while (rs.next()) { - String groupNameTmp = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupNameTmp.equalsIgnoreCase(groupName)); - } - rs.close(); - } finally { - Objects.requireNonNull(connWithHint).createStatement().execute("drop table if exists " + tblName); - Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(connWithHint).close(); - Objects.requireNonNull(connWithoutHint).close(); - log.info("session hint test end"); - } - } - @Test public void testSessionHintWithInformationSchema() throws SQLException { Connection connWithHint = null; Connection connWithoutHint = null; try { connWithoutHint = getPolardbxConnection(); - connWithoutHint.createStatement().execute("use drds_polarx1_part_qatest_app"); + connWithoutHint.createStatement().execute("use " + AUTO_DB_NAME); connWithHint = getPolardbxConnection(); - connWithHint.createStatement().execute("use drds_polarx1_part_qatest_app"); + connWithHint.createStatement().execute("use " + AUTO_DB_NAME); connWithHint.createStatement().execute("set partition_hint=p3"); - checkHintWork(connWithHint, TBL_NAME); - // test normal hint won't interrupt partition hint DataValidator.selectContentSameAssert("explain select * from information_schema.views", null, connWithHint, connWithoutHint, true); @@ -320,9 +333,6 @@ public void testSessionHintWithInformationSchema() throws SQLException { } private void checkHintWork(Connection conn, String tblName) throws SQLException { - // prepare table - conn.createStatement().execute(CREATE_TBL); - // get group name and partition name ResultSet rs = conn.createStatement().executeQuery("show topology from " + tblName); @@ -355,15 +365,12 @@ public void testSessionHintWithShowCommandAndDal() throws SQLException { Connection connWithoutHint = null; try { connWithoutHint = getPolardbxConnection(); - connWithoutHint.createStatement().execute("use drds_polarx1_part_qatest_app"); + connWithoutHint.createStatement().execute("use " + AUTO_DB_NAME); connWithHint = getPolardbxConnection(); - connWithHint.createStatement().execute("use drds_polarx1_part_qatest_app"); + connWithHint.createStatement().execute("use " + AUTO_DB_NAME); connWithHint.createStatement().execute("set partition_hint=p3"); - // test hint working - checkHintWork(connWithHint, TBL_NAME); - // test show command connWithHint.createStatement().executeQuery("show tables"); connWithHint.createStatement().executeQuery("show full tables"); @@ -371,32 +378,32 @@ public void testSessionHintWithShowCommandAndDal() throws SQLException { connWithHint.createStatement().executeQuery("show full ddl"); connWithHint.createStatement().executeQuery("show ddl status"); connWithHint.createStatement().executeQuery("show ddl result"); - connWithHint.createStatement().executeQuery("show rule from select_base_three_multi_db_multi_tb"); - connWithHint.createStatement().executeQuery("show full rule from select_base_three_multi_db_multi_tb"); - connWithHint.createStatement().executeQuery("show topology from select_base_three_multi_db_multi_tb"); - connWithHint.createStatement().executeQuery("show partitions from select_base_three_multi_db_multi_tb"); + connWithHint.createStatement().executeQuery("show rule from " + AUTO_TBL_NAME1); + connWithHint.createStatement().executeQuery("show full rule from " + AUTO_TBL_NAME2); + connWithHint.createStatement().executeQuery("show topology from " + AUTO_TBL_NAME3); + connWithHint.createStatement().executeQuery("show partitions from " + AUTO_TBL_NAME1); // show datasources cannot make sure POOLING_COUNT same DataValidator.selectConutAssert("show datasources", null, connWithHint, connWithoutHint); DataOperator.executeOnMysqlAndTddl(connWithHint, connWithoutHint, "clear slow", null); // explain advisor/json_plan might cause different result in different cn node connWithHint.createStatement().executeQuery( - "explain advisor select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); - connWithHint.createStatement().execute("analyze table select_base_three_multi_db_multi_tb"); + "explain advisor select * from " + AUTO_TBL_NAME1 + " where name='12' order by id"); + connWithHint.createStatement().execute("analyze table " + AUTO_TBL_NAME1); connWithHint.createStatement().executeQuery( - "explain STATISTICS select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); + "explain STATISTICS select * from " + AUTO_TBL_NAME2 + " where name='12' order by id"); connWithHint.createStatement().executeQuery( - "explain JSON_PLAN select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); - connWithoutHint.createStatement().executeQuery( - "explain JSON_PLAN select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); + "explain JSON_PLAN select * from " + AUTO_TBL_NAME1 + " where name='12' order by id"); + connWithoutHint.createStatement() + .executeQuery("explain JSON_PLAN select * from " + AUTO_TBL_NAME3 + " where name='12' order by id"); connWithHint.createStatement().executeQuery( - "explain EXECUTE select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); + "explain EXECUTE select * from " + AUTO_TBL_NAME3 + " where name='12' order by id"); connWithoutHint.createStatement().executeQuery( - "explain EXECUTE select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); + "explain EXECUTE select * from " + AUTO_TBL_NAME3 + " where name='12' order by id"); connWithHint.createStatement().executeQuery( - "explain SHARDING select * from select_base_three_multi_db_multi_tb where varchar_test='12' order by pk"); + "explain SHARDING select * from " + AUTO_TBL_NAME3 + " where name='12' order by id"); connWithHint.createStatement().execute("create sequence session_hint_test_seq start with 100"); connWithHint.createStatement().execute("alter sequence session_hint_test_seq start with 99"); connWithHint.createStatement().execute("drop sequence session_hint_test_seq"); @@ -418,7 +425,7 @@ public void testSessionHintWithShowCommandAndDal() throws SQLException { connWithHint.createStatement().executeQuery("show broadcasts"); connWithHint.createStatement().executeQuery("show connection"); connWithHint.createStatement().executeQuery("show rule"); - connWithHint.createStatement().executeQuery("check table select_base_four_multi_db_multi_tb"); + connWithHint.createStatement().executeQuery("check table " + AUTO_TBL_NAME3); } finally { Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); Objects.requireNonNull(connWithHint).close(); @@ -432,17 +439,15 @@ public void testSessionHintWithDirectHint() throws SQLException { Connection connWithHint = null; try { connWithHint = getPolardbxConnection(); - connWithHint.createStatement().execute("use drds_polarx1_part_qatest_app"); + connWithHint.createStatement().execute("use " + AUTO_DB_NAME); connWithHint.createStatement().execute("set partition_hint=p3"); - // test partition hint working - checkHintWork(connWithHint, TBL_NAME); ResultSet rs; // test normal hint won't interrupt partition hint // get group name and partition name - rs = connWithHint.createStatement().executeQuery("show topology from " + TBL_NAME); + rs = connWithHint.createStatement().executeQuery("show topology from " + AUTO_TBL_NAME1); String groupName = null; String partitionName = null; @@ -460,12 +465,12 @@ public void testSessionHintWithDirectHint() throws SQLException { connWithHint.createStatement().execute("set partition_hint=" + partitionName); // test partition hint with non-direct hint - connWithHint.createStatement().execute("trace /*TDDL:slave()*/ select * from " + TBL_NAME); + connWithHint.createStatement().execute("trace /*TDDL:slave()*/ select * from " + AUTO_TBL_NAME1); - connWithHint.createStatement().execute("trace /*TDDL:a()*/ select * from " + TBL_NAME); + connWithHint.createStatement().execute("trace /*TDDL:a()*/ select * from " + AUTO_TBL_NAME2); connWithHint.createStatement() - .execute("trace /*TDDL:test_hint=true*/ select * from select_base_three_multi_db_one_tb"); + .execute("trace /*TDDL:test_hint=true*/ select * from " + AUTO_TBL_NAME1); rs = connWithHint.createStatement().executeQuery("show trace"); while (rs.next()) { @@ -498,34 +503,36 @@ public void testSessionHintWithShardingMultiTable() throws SQLException { Connection c = null; try { c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:00'"); - c.createStatement().execute("trace select * from select_base_three_multi_db_multi_tb"); + c.createStatement().execute("use " + SHARD_DB_NAME); + c.createStatement().execute("set partition_hint='PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP:00'"); + c.createStatement().execute("trace select * from " + DRDS_TBL_NAME); ResultSet rs = c.createStatement().executeQuery("show trace"); while (rs.next()) { String groupName = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupName.equalsIgnoreCase("DRDS_POLARX1_QATEST_APP_000001_GROUP")); + Assert.assertTrue(groupName.equalsIgnoreCase("PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP")); } - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:1'"); - c.createStatement().execute("trace select * from select_base_three_multi_db_multi_tb"); + c.createStatement().execute("set partition_hint='PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP:1'"); + c.createStatement().execute("trace select * from " + DRDS_TBL_NAME); rs = c.createStatement().executeQuery("show trace"); while (rs.next()) { String groupName = rs.getString("GROUP_NAME"); - Assert.assertTrue(groupName.equalsIgnoreCase("DRDS_POLARX1_QATEST_APP_000001_GROUP")); + Assert.assertTrue(groupName.equalsIgnoreCase("PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP")); } - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:4'"); + c.createStatement().execute("set partition_hint='PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP:4'"); try { - c.createStatement().execute("trace select * from select_base_three_multi_db_multi_tb"); + c.createStatement().execute("trace select * from " + DRDS_TBL_NAME); } catch (SQLException e) { Assert.assertTrue(e.getMessage() .contains("table index overflow in target group from direct HINT for sharding table")); } } finally { Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); + Objects.requireNonNull(c).close(); + log.info("session hint test end"); } } @@ -536,26 +543,28 @@ public void testSessionHintWithJoin() throws SQLException { Connection c = null; try { c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:00'"); + c.createStatement().execute("use " + SHARD_DB_NAME); + c.createStatement().execute("set partition_hint='PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP:00'"); try { - c.createStatement().execute( - "select * from select_base_three_multi_db_multi_tb a join select_base_three_multi_db_one_tb b on a.pk=b.pk"); + c.createStatement() + .execute("select * from " + DRDS_TBL_NAME + " a join " + DRDS_TBL_NAME2 + " b on a.id=b.id"); Assert.fail("should report error"); } catch (SQLException e) { + System.out.println(e.getMessage()); Assert.assertTrue(e.getMessage() .contains("different sharding table num in partition hint mode")); } } finally { Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); + Objects.requireNonNull(c).close(); log.info("session hint test end"); } // auto table in different table group, report error try { c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_part_qatest_app"); + c.createStatement().execute("use " + AUTO_DB_NAME); c.createStatement().execute("set partition_hint='p1'"); // create table group @@ -563,7 +572,7 @@ public void testSessionHintWithJoin() throws SQLException { c.createStatement().execute("create tablegroup if not exists partition_hint_test_tg2"); // create table into table group partition_test_tg1 - c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_tbl1` (\n" + c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_group_tbl1` (\n" + " `a` datetime NOT NULL\n" + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" + "TABLEGROUP=partition_hint_test_tg1\n" @@ -573,7 +582,7 @@ public void testSessionHintWithJoin() throws SQLException { + " PARTITION p2 VALUES LESS THAN (2010) ENGINE = InnoDB,\n" + " PARTITION p3 VALUES LESS THAN (2020) ENGINE = InnoDB);"); - c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_tbl2` (\n" + c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_group_tbl2` (\n" + " `a` datetime NOT NULL\n" + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" + "TABLEGROUP=partition_hint_test_tg2\n" @@ -586,7 +595,8 @@ public void testSessionHintWithJoin() throws SQLException { // test different table group error report try { c.createStatement() - .execute("select * from partition_hint_test_tbl1 a join partition_hint_test_tbl2 b on a.a=b.a"); + .execute( + "select * from partition_hint_test_group_tbl1 a join partition_hint_test_group_tbl2 b on a.a=b.a"); Assert.fail("should report error"); } catch (SQLException e) { Assert.assertTrue(e.getMessage() @@ -594,31 +604,34 @@ public void testSessionHintWithJoin() throws SQLException { } // change table group to same one:partition_hint_test_tbl1 - c.createStatement().execute("ALTER TABLE partition_hint_test_tbl2 set TABLEGROUP=partition_hint_test_tg1;"); + c.createStatement() + .execute("ALTER TABLE partition_hint_test_group_tbl2 set TABLEGROUP=partition_hint_test_tg1;"); // test if same table group work c.createStatement() - .execute("select * from partition_hint_test_tbl1 a join partition_hint_test_tbl2 b on a.a=b.a"); + .execute( + "select * from partition_hint_test_group_tbl1 a join partition_hint_test_group_tbl2 b on a.a=b.a"); } finally { Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(c).createStatement().execute("drop table if exists partition_hint_test_tbl1"); - Objects.requireNonNull(c).createStatement().execute("drop table if exists partition_hint_test_tbl2"); + Objects.requireNonNull(c).createStatement().execute("drop table if exists partition_hint_test_group_tbl1"); + Objects.requireNonNull(c).createStatement().execute("drop table if exists partition_hint_test_group_tbl2"); Objects.requireNonNull(c).createStatement().execute("drop tablegroup if exists partition_hint_test_tg1"); Objects.requireNonNull(c).createStatement().execute("drop tablegroup if exists partition_hint_test_tg2"); + Objects.requireNonNull(c).close(); log.info("session hint test end"); } // test auto table join with broadcast table try { c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_part_qatest_app"); + c.createStatement().execute("use " + AUTO_DB_NAME); c.createStatement().execute("set partition_hint='p1'"); // create table group c.createStatement().execute("create tablegroup if not exists partition_hint_test_tg1"); // create table into table group partition_test_tg1 - c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_tbl1` (\n" + c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_group_tbl1` (\n" + " `a` datetime NOT NULL\n" + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" + "TABLEGROUP=partition_hint_test_tg1\n" @@ -628,19 +641,23 @@ public void testSessionHintWithJoin() throws SQLException { + " PARTITION p2 VALUES LESS THAN (2010) ENGINE = InnoDB,\n" + " PARTITION p3 VALUES LESS THAN (2020) ENGINE = InnoDB);"); - c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_tbl2` (\n" + c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_broadcast_tbl2` (\n" + " `a` datetime NOT NULL\n" + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" + "BROADCAST"); // test if table with broadcast table work c.createStatement() - .execute("select * from partition_hint_test_tbl1 a join partition_hint_test_tbl2 b on a.a=b.a"); + .execute( + "select * from partition_hint_test_group_tbl1 a join partition_hint_test_broadcast_tbl2 b on a.a=b.a"); } finally { Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); - Objects.requireNonNull(c).createStatement().execute("drop table if exists partition_hint_test_tbl1"); - Objects.requireNonNull(c).createStatement().execute("drop table if exists partition_hint_test_tbl2"); + Objects.requireNonNull(c).createStatement().execute("drop table if exists partition_hint_test_group_tbl1"); + Objects.requireNonNull(c).createStatement() + .execute("drop table if exists partition_hint_test_broadcast_tbl2"); Objects.requireNonNull(c).createStatement().execute("drop tablegroup if exists partition_hint_test_tg1"); + Objects.requireNonNull(c).close(); + log.info("session hint test end"); } } @@ -650,14 +667,13 @@ public void testSessionHintCrossSchema() throws SQLException { Connection c = null; try { c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:00'"); + c.createStatement().execute("use " + SHARD_DB_NAME); + c.createStatement().execute("set partition_hint='PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP:00'"); - c.createStatement().execute("select * from drds_polarx1_qatest_app.select_base_three_multi_db_multi_tb"); + c.createStatement().execute("select * from " + SHARD_DB_NAME + "." + DRDS_TBL_NAME); try { - c.createStatement() - .execute("select * from drds_polarx1_part_qatest_app.select_base_three_multi_db_multi_tb"); + c.createStatement().execute("select * from " + AUTO_DB_NAME + "." + AUTO_TBL_NAME4); Assert.fail("should report error"); } catch (SQLException e) { log.info(e.getMessage()); @@ -666,6 +682,7 @@ public void testSessionHintCrossSchema() throws SQLException { } } finally { Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); + Objects.requireNonNull(c).close(); log.info("session hint test end"); } } @@ -681,27 +698,14 @@ public void testSessionHintWithPhysicalTableName() throws SQLException { // drds table try { c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:00'"); - - /* - * expected table topology - * | 0 | DRDS_POLARX1_QATEST_APP_000000_GROUP | select_base_three_multi_db_multi_tb_i9JV_00 | - | - * | 1 | DRDS_POLARX1_QATEST_APP_000000_GROUP | select_base_three_multi_db_multi_tb_i9JV_01 | - | - * | 2 | DRDS_POLARX1_QATEST_APP_000000_GROUP | select_base_three_multi_db_multi_tb_i9JV_02 | - | - * | 3 | DRDS_POLARX1_QATEST_APP_000000_GROUP | select_base_three_multi_db_multi_tb_i9JV_03 | - | - * | 4 | DRDS_POLARX1_QATEST_APP_000001_GROUP | select_base_three_multi_db_multi_tb_i9JV_04 | - | - * | 5 | DRDS_POLARX1_QATEST_APP_000001_GROUP | select_base_three_multi_db_multi_tb_i9JV_05 | - | - * | 6 | DRDS_POLARX1_QATEST_APP_000001_GROUP | select_base_three_multi_db_multi_tb_i9JV_06 | - | - * | 7 | DRDS_POLARX1_QATEST_APP_000001_GROUP | select_base_three_multi_db_multi_tb_i9JV_07 | - | - * ... ... - */ - c.createStatement().execute("select * from drds_polarx1_qatest_app.select_base_three_multi_db_multi_tb"); + c.createStatement().execute("use " + SHARD_DB_NAME); + c.createStatement().execute("set partition_hint='PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP:00'"); + c.createStatement().execute("select * from " + SHARD_DB_NAME + "." + DRDS_TBL_NAME); try { - c.createStatement() - .execute( - "select * from select_base_three_multi_db_multi_tb_i9JV_02 a join select_base_three_multi_db_one_tb b on a.pk=b.pk;"); + c.createStatement().execute( + "select * from select_base_three_multi_db_multi_tb_i9JV_02 a join " + DRDS_TBL_NAME + + " b on a.id=b.id"); Assert.fail("should report error"); } catch (SQLException e) { log.info(e.getMessage()); @@ -710,7 +714,8 @@ public void testSessionHintWithPhysicalTableName() throws SQLException { try { c.createStatement() .execute( - "select * from select_base_three_multi_db_multi_tb_i9JV_06 a join select_base_three_multi_db_one_tb b on a.pk=b.pk;"); + "select * from select_base_three_multi_db_multi_tb_i9JV_06 a join " + DRDS_TBL_NAME + + " b on a.id=b.id"); } catch (SQLException e) { log.info(e.getMessage()); Assert.assertTrue(e.getMessage().contains("[ERR_TABLE_NOT_EXIST]")); @@ -723,18 +728,9 @@ public void testSessionHintWithPhysicalTableName() throws SQLException { // auto table try { c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_part_qatest_app"); + c.createStatement().execute("use " + AUTO_DB_NAME); c.createStatement().execute("set partition_hint=p2"); - - /* - * expected topology - * | 0 | DRDS_POLARX1_PART_QATEST_APP_P00000_GROUP | select_base_three_multi_db_multi_tb_MvY5_00001 | p2 - * | 1 | DRDS_POLARX1_PART_QATEST_APP_P00001_GROUP | select_base_three_multi_db_multi_tb_MvY5_00000 | p1 - * | 2 | DRDS_POLARX1_PART_QATEST_APP_P00001_GROUP | select_base_three_multi_db_multi_tb_MvY5_00002 | p3 - * ... ... - */ - c.createStatement() - .execute("select * from drds_polarx1_part_qatest_app.select_base_three_multi_db_multi_tb"); + c.createStatement().execute("select * from " + AUTO_DB_NAME + "." + AUTO_TBL_NAME4); try { c.createStatement() @@ -756,6 +752,7 @@ public void testSessionHintWithPhysicalTableName() throws SQLException { } } finally { Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); + Objects.requireNonNull(c).close(); log.info("session hint test end"); } } @@ -768,15 +765,15 @@ public void testShowFullConnection() throws SQLException { Connection c = null; try { c = getPolardbxConnection(); - c.createStatement().execute("use drds_polarx1_qatest_app"); - c.createStatement().execute("set partition_hint='DRDS_POLARX1_QATEST_APP_000001_GROUP:00'"); + c.createStatement().execute("use " + SHARD_DB_NAME); + c.createStatement().execute("set partition_hint='PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP:00'"); ResultSet rs = c.createStatement().executeQuery("show full connection"); boolean found = false; while (rs.next()) { String hint = rs.getString("PARTITION_HINT"); - if ("DRDS_POLARX1_QATEST_APP_000001_GROUP:00".equalsIgnoreCase(hint)) { + if ("PARTITION_NAME_HINT_TEST_SHARD_000001_GROUP:00".equalsIgnoreCase(hint)) { found = true; } } @@ -795,9 +792,7 @@ public void testDmlWithAutoGsi() throws SQLException { Connection c = null; try { c = getPolardbxConnection(); - c.createStatement().execute("drop database if exists partition_hint_test"); - c.createStatement().execute("create database if not exists partition_hint_test mode=auto"); - c.createStatement().execute("use partition_hint_test"); + c.createStatement().execute("use " + AUTO_DB_NAME); Random r = new Random(); String tblName = "session_hint_dml_test_tb_order_" + r.nextInt(10000); c.createStatement().execute( @@ -823,6 +818,7 @@ public void testDmlWithAutoGsi() throws SQLException { e.getMessage().contains("[ERR_GLOBAL_SECONDARY_INDEX_MODIFY_GSI_TABLE_DIRECTLY]")); } finally { Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); + Objects.requireNonNull(c).close(); log.info("session hint test end"); } } @@ -835,9 +831,7 @@ public void testDmlWithShardingGsi() throws SQLException { Connection c = null; try { c = getPolardbxConnection(); - c.createStatement().execute("drop database if exists partition_hint_test"); - c.createStatement().execute("create database if not exists partition_hint_test mode=drds"); - c.createStatement().execute("use partition_hint_test"); + c.createStatement().execute("use " + SHARD_DB_NAME); Random r = new Random(); String tblName = "session_hint_dml_test_tb_order_" + r.nextInt(10000); c.createStatement().execute( @@ -850,9 +844,8 @@ public void testDmlWithShardingGsi() throws SQLException { + " LOCAL KEY `_local_idx_name` (`name`)\n" + ") ENGINE = InnoDB DEFAULT CHARSET = utf8\n" + "dbpartition by hash(name)"); - c.createStatement() - .execute("insert into " + tblName + "(id, bid, name) values(1, 11, 'a')"); - c.createStatement().execute("set partition_hint='PARTITION_HINT_TEST_000000_GROUP'"); + c.createStatement().execute("insert into " + tblName + "(id, bid, name) values(1, 11, 'a')"); + c.createStatement().execute("set partition_hint='PARTITION_NAME_HINT_TEST_SHARD_000000_GROUP'"); c.createStatement().execute("insert into " + tblName + "(id, bid, name) values(2, 12, 'a')"); @@ -862,6 +855,7 @@ public void testDmlWithShardingGsi() throws SQLException { e.getMessage().contains("[ERR_GLOBAL_SECONDARY_INDEX_MODIFY_GSI_TABLE_DIRECTLY]")); } finally { Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); + Objects.requireNonNull(c).close(); log.info("session hint test end"); } } @@ -874,9 +868,7 @@ public void testDmlWithShardingBroadcast() throws SQLException { Connection c = null; try { c = getPolardbxConnection(); - c.createStatement().execute("drop database if exists partition_hint_test"); - c.createStatement().execute("create database if not exists partition_hint_test mode=drds"); - c.createStatement().execute("use partition_hint_test"); + c.createStatement().execute("use " + SHARD_DB_NAME); Random r = new Random(); String tblName = "session_hint_dml_test_tb_order_" + r.nextInt(10000); c.createStatement().execute( @@ -887,9 +879,8 @@ public void testDmlWithShardingBroadcast() throws SQLException { + " PRIMARY KEY (`id`)\n" + ") ENGINE = InnoDB DEFAULT CHARSET = utf8\n" + "broadcast"); - c.createStatement() - .execute("insert into " + tblName + "(id, bid, name) values(1, 11, 'a')"); - c.createStatement().execute("set partition_hint='PARTITION_HINT_TEST_SINGLE_GROUP'"); + c.createStatement().execute("insert into " + tblName + "(id, bid, name) values(1, 11, 'a')"); + c.createStatement().execute("set partition_hint='PARTITION_NAME_HINT_TEST_SHARD_SINGLE_GROUP'"); c.createStatement().execute("insert into " + tblName + "(id, bid, name) values(2, 12, 'a')"); @@ -900,6 +891,7 @@ public void testDmlWithShardingBroadcast() throws SQLException { e.getMessage().contains("[ERR_MODIFY_BROADCAST_TABLE_BY_HINT_NOT_ALLOWED]")); } finally { Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); + Objects.requireNonNull(c).close(); log.info("session hint test end"); } } @@ -912,9 +904,7 @@ public void testPrepareDml() throws SQLException { Connection c = null; try { c = getPolardbxConnection(); - c.createStatement().execute("drop database if exists partition_hint_test"); - c.createStatement().execute("create database if not exists partition_hint_test mode=auto"); - c.createStatement().execute("use partition_hint_test"); + c.createStatement().execute("use " + AUTO_DB_NAME); // create table into table group partition_test_tg1 c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_tbl1` (\n" + " `id` bigint NOT NULL,\n" @@ -1013,4 +1003,390 @@ public void testPrepareDml() throws SQLException { log.info("session hint test end"); } } + + @Test + public void testDirectHint() throws SQLException { + Connection c = null; + try { + c = getPolardbxConnection(); + c.createStatement().execute("use " + AUTO_DB_NAME); + c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_direct_tbl1` (\n" + + " `id` bigint NOT NULL,\n" + + " `name` varchar(25) NOT NULL,\n" + + " `c_time` datetime NOT NULL\n" + + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" + + "PARTITION BY RANGE(YEAR(c_time))\n" + + "(PARTITION p0 VALUES LESS THAN (1990) ENGINE = InnoDB,\n" + + " PARTITION p1 VALUES LESS THAN (2000) ENGINE = InnoDB,\n" + + " PARTITION p2 VALUES LESS THAN (2010) ENGINE = InnoDB,\n" + + " PARTITION p3 VALUES LESS THAN (2020) ENGINE = InnoDB);"); + + c.createStatement().execute("CREATE TABLE if not exists `partition_hint_test_direct_tbl2` (\n" + + " `id` bigint NOT NULL,\n" + + " `name` varchar(25) NOT NULL,\n" + + " `c_time` datetime NOT NULL\n" + + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" + + "PARTITION BY RANGE(YEAR(c_time))\n" + + "(PARTITION p0 VALUES LESS THAN (1990) ENGINE = InnoDB,\n" + + " PARTITION p1 VALUES LESS THAN (2000) ENGINE = InnoDB,\n" + + " PARTITION p2 VALUES LESS THAN (2010) ENGINE = InnoDB,\n" + + " PARTITION p3 VALUES LESS THAN (2020) ENGINE = InnoDB);"); + + // test insert batch + ResultSet rs = c.createStatement().executeQuery( + "explain /*+TDDL({'type':'direct','dbid':'p0'})*/ select * from partition_hint_test_direct_tbl1"); + StringBuilder sb = new StringBuilder(); + while (rs.next()) { + sb.append(rs.getString(1)); + } + rs.close(); + + Assert.assertTrue(sb.toString().contains("PhyQuery")); + + rs = c.createStatement().executeQuery( + "explain /*+TDDL({'type':'direct','dbid':'p0, p3'})*/ select * from partition_hint_test_direct_tbl1"); + int count = 0; + while (rs.next()) { + if (rs.getString(1).contains("PhyQuery")) { + count++; + } + } + rs.close(); + + Assert.assertTrue(count == 2); + + rs = c.createStatement().executeQuery( + "explain select /*+TDDL({'type':'direct','dbid':'p0, p3'})*/ * from partition_hint_test_direct_tbl1"); + count = 0; + while (rs.next()) { + if (rs.getString(1).contains("PhyQuery")) { + count++; + } + } + rs.close(); + + Assert.assertTrue(count == 2); + + rs = c.createStatement().executeQuery( + "explain insert /*+TDDL({'type':'direct','dbid':'p0, p3'})*/ into partition_hint_test_direct_tbl1(id, name, c_time) values(1, 'a', now())"); + count = 0; + while (rs.next()) { + if (rs.getString(1).contains("PhyQuery")) { + count++; + } + } + rs.close(); + + Assert.assertTrue(count == 2); + + rs = c.createStatement() + .executeQuery("explain /*TDDL:NODE='p2'*/ select count(1) from partition_hint_test_direct_tbl1"); + count = 0; + while (rs.next()) { + if (rs.getString(1).contains("PhyQuery")) { + count++; + } + } + rs.close(); + + Assert.assertTrue(count == 1); + + rs = c.createStatement() + .executeQuery("explain /*TDDL:NODE(p3,p2)*/ select count(1) from partition_hint_test_direct_tbl2"); + count = 0; + while (rs.next()) { + if (rs.getString(1).contains("PhyQuery")) { + count++; + } + } + rs.close(); + + Assert.assertTrue(count == 2); + + // group hint + rs = c.createStatement() + .executeQuery( + "explain /*TDDL:node='p3, p2, p1'*/ select count(1) from partition_hint_test_direct_tbl2"); + count = 0; + while (rs.next()) { + if (rs.getString(1).contains("PhyQuery")) { + count++; + } + } + rs.close(); + + Assert.assertTrue(count == 3); + + } finally { + Objects.requireNonNull(c).createStatement().execute("set partition_hint=''"); + log.info("session hint test end"); + } + } + + @Test + public void testGroupHintSlaveHint() throws SQLException { + // make sure slave nodes exists + Set slaveNodes = new HashSet<>(); + try (Connection connection = getPolardbxConnection()) { + ResultSet rs = connection.createStatement().executeQuery("show datasources"); + while (rs.next()) { + String name = rs.getString("NAME"); + if (name.contains("slave")) { + slaveNodes.add(name); + } + } + + if (slaveNodes.size() == 0) { + log.warn("no slave nodes, skip test"); + return; + } + } + + // test group hint for drds table + try (Connection connection = getPolardbxConnection()) { + connection.createStatement().execute("drop database if exists group_hint_drds_test"); + connection.createStatement().execute("create database if not exists group_hint_drds_test"); + connection.createStatement().execute("use group_hint_drds_test"); + + // create table into table group partition_test_tg1 + connection.createStatement().execute("CREATE TABLE multi_db_multi_tbl(\n" + + " id bigint not null auto_increment, \n" + + " bid int, \n" + + " name varchar(30), \n" + + " primary key(id)\n" + + ") dbpartition by hash(id) tbpartition by hash(bid) tbpartitions 3;"); + + testGroupHint("/*+TDDL_GROUP({groupIndex:1})*/", connection, slaveNodes, true, "multi_db_multi_tbl"); + testGroupHint("/*+TDDL_GROUP({groupIndex:0})*/", connection, slaveNodes, false, "multi_db_multi_tbl"); + testGroupHint("/*+TDDL_GROUP({groupIndex:-2})*/", connection, slaveNodes, false, "multi_db_multi_tbl"); + testGroupHint("/*+TDDL:master()*/", connection, slaveNodes, false, "multi_db_multi_tbl"); + testGroupHint("/*+TDDL:slave()*/", connection, slaveNodes, true, "multi_db_multi_tbl"); + } + + // test group hint for auto table + try (Connection connection = getPolardbxConnection()) { + connection.createStatement().execute("drop database if exists group_hint_auto_test"); + connection.createStatement().execute("create database if not exists group_hint_auto_test mode=auto"); + connection.createStatement().execute("use group_hint_auto_test"); + + // create table into table group partition_test_tg1 + connection.createStatement().execute("CREATE TABLE if not exists `group_hint_tbl1` (\n" + + " `id` bigint NOT NULL,\n" + + " `name` varchar(25) NOT NULL,\n" + + " `c_time` datetime NOT NULL\n" + + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 \n" + + "PARTITION BY RANGE(YEAR(c_time))\n" + + "(PARTITION p0 VALUES LESS THAN (1990) ENGINE = InnoDB,\n" + + " PARTITION p1 VALUES LESS THAN (2000) ENGINE = InnoDB,\n" + + " PARTITION p2 VALUES LESS THAN (2010) ENGINE = InnoDB,\n" + + " PARTITION p3 VALUES LESS THAN (2020) ENGINE = InnoDB)"); + + testGroupHint("/*+TDDL_GROUP({groupIndex:1})*/", connection, slaveNodes, true, "group_hint_tbl1"); + testGroupHint("/*+TDDL_GROUP({groupIndex:0})*/", connection, slaveNodes, false, "group_hint_tbl1"); + testGroupHint("/*+TDDL_GROUP({groupIndex:-2})*/", connection, slaveNodes, false, "group_hint_tbl1"); + testGroupHint("/*+TDDL:master()*/", connection, slaveNodes, false, "group_hint_tbl1"); + testGroupHint("/*+TDDL:slave()*/", connection, slaveNodes, true, "group_hint_tbl1"); + } + + // test group hint + direct hint for auto table + try (Connection connection = getPolardbxConnection()) { + connection.createStatement().execute("use group_hint_auto_test"); + testGroupHint("/*+TDDL_GROUP({groupIndex:1})*//*+TDDL({\"dbid\":\"p2,p3\",\"type\":\"direct\"})*/", + connection, slaveNodes, true, "group_hint_tbl1"); + ResultSet rs = connection.createStatement().executeQuery("show trace"); + int count = 0; + while (rs.next()) { + if (rs.getString(1).contains("PhyQuery")) { + count++; + } + } + Assert.assertTrue(count == 2); + testGroupHint( + "/*+TDDL_GROUP({groupIndex:0})*//*+TDDL({\"dbindex\":true,\"dbid\":'p1, p0, p3',\"type\":\"direct\"})*/", + connection, slaveNodes, false, "group_hint_tbl1"); + rs = connection.createStatement().executeQuery("show trace"); + count = 0; + while (rs.next()) { + if (rs.getString(1).contains("PhyQuery")) { + count++; + } + } + Assert.assertTrue(count == 3); + } + } + + @Test + public void testSessionHintWithFlashBack() throws SQLException, InterruptedException { + Connection connWithHint = null; + try { + connWithHint = getPolardbxConnection(); + connWithHint.createStatement().execute("use " + AUTO_DB_NAME); + + connWithHint.createStatement().execute("set partition_hint=p3"); + connWithHint.createStatement().execute("set global ENABLE_FORBID_PUSH_DML_WITH_HINT=false"); + Thread.sleep(2000); + + ResultSet rs; + + // clear data + connWithHint.createStatement().execute("truncate table " + AUTO_TBL_NAME1); + + // Ensure the as of timestamp is valid. + Thread.sleep(1000); + + // test insert into partition table + Calendar current = Calendar.getInstance(); + current.setTimeInMillis(current.getTimeInMillis() - 5000); + SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + connWithHint.setAutoCommit(false); + connWithHint.createStatement() + .execute("insert into " + AUTO_TBL_NAME1 + "(bid, birthday) values(8, now())"); + connWithHint.commit(); + String sql = "select * from " + AUTO_TBL_NAME1 + " as of timestamp '" + f.format(current.getTime()) + + "' where bid=8"; + System.out.println(sql); + rs = connWithHint.createStatement().executeQuery(sql); + while (rs.next()) { + Assert.fail("should not query any value by flashback"); + } + rs.close(); + } catch (Throwable t) { + if (isMySQL80() && t.getMessage().contains( + "The definition of the table required by the flashback query has changed")) { + return; + } + throw t; + } finally { + Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); + Objects.requireNonNull(connWithHint).close(); + log.info("session hint test end"); + } + } + + @Test + public void testSessionHintForbiddenByConfig() throws SQLException, InterruptedException { + Connection connWithHint = null; + try { + connWithHint = getPolardbxConnection(); + connWithHint.createStatement().execute("use " + AUTO_DB_NAME); + + connWithHint.createStatement().execute("set partition_hint=p3"); + connWithHint.createStatement().execute("set global ENABLE_FORBID_PUSH_DML_WITH_HINT=true"); + Thread.sleep(2000); + connWithHint.setAutoCommit(false); + + connWithHint.createStatement().execute("set partition_hint=p3"); + try { + connWithHint.createStatement() + .execute("insert into " + AUTO_TBL_NAME1 + "(bid, birthday) values(18, now())"); + Assert.fail(" dml should be forbidden by ENABLE_FORBID_PUSH_DML_WITH_HINT=true"); + } catch (SQLException e) { + if (!e.getMessage().contains("Unsupported to push physical dml by hint ")) { + throw e; + } + } + + try { + connWithHint.createStatement().execute("update " + AUTO_TBL_NAME1 + " set bid=18"); + Assert.fail(" dml should be forbidden by ENABLE_FORBID_PUSH_DML_WITH_HINT=true"); + } catch (SQLException e) { + if (!e.getMessage().contains("Unsupported to push physical dml by hint ")) { + throw e; + } + } + + try { + connWithHint.createStatement() + .execute("insert into " + AUTO_TBL_NAME1 + " select * from " + AUTO_TBL_NAME2); + Assert.fail(" dml should be forbidden by ENABLE_FORBID_PUSH_DML_WITH_HINT=true"); + } catch (SQLException e) { + if (!e.getMessage().contains("Unsupported to push physical dml by hint ")) { + throw e; + } + } + } finally { + Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); + Objects.requireNonNull(connWithHint).close(); + log.info("session hint test end"); + } + } + + @Test + public void testSessionHintWithDML() throws SQLException, InterruptedException { + Connection connWithHint = null; + try { + connWithHint = getPolardbxConnection(); + connWithHint.createStatement().execute("use " + AUTO_DB_NAME); + + connWithHint.createStatement().execute("set partition_hint=p3"); + connWithHint.createStatement().execute("set global ENABLE_FORBID_PUSH_DML_WITH_HINT=false"); + Thread.sleep(2000); + + // test partition hint working + connWithHint.createStatement().execute("set partition_hint=p3"); + + connWithHint.createStatement() + .execute("insert into " + AUTO_TBL_NAME1 + "(bid, birthday) values(19, now())"); + + connWithHint.createStatement().execute("update " + AUTO_TBL_NAME1 + " set bid=19"); + connWithHint.createStatement().execute("truncate table " + AUTO_TBL_NAME1); + connWithHint.createStatement().execute( + "insert into " + AUTO_TBL_NAME2 + "(bid, birthday) " + "select bid, birthday from " + AUTO_TBL_NAME1); + } finally { + Objects.requireNonNull(connWithHint).createStatement().execute("set partition_hint=''"); + Objects.requireNonNull(connWithHint).close(); + log.info("session hint test end"); + } + } + + @Test + public void testTargetTableHint() throws SQLException { + + try (Connection connWithHint = getPolardbxConnection()) { + connWithHint.createStatement().execute("use " + AUTO_DB_NAME); + String groupName = null; + String tableName = null; + try (ResultSet rs = connWithHint.createStatement().executeQuery("show topology " + AUTO_TBL_NAME1)) { + if (rs.next()) { + groupName = rs.getString("GROUP_NAME"); + tableName = rs.getString("TABLE_NAME"); + } + } + String hint = + String.format("/*+TDDL: SCAN(\"%s\", REAL_TABLE=(\"%s\"), NODE=\"%s\") */", + AUTO_TBL_NAME1, tableName, groupName); + connWithHint.createStatement() + .execute("trace " + hint + " select * from " + AUTO_TBL_NAME1 + " where id in (1, 2, 3)"); + int traceResultCount = 0; + try (ResultSet rs = connWithHint.createStatement().executeQuery("show trace")) { + while (rs.next()) { + traceResultCount++; + String traceGroupName = rs.getString("GROUP_NAME"); + String params = rs.getString("PARAMS"); + Assert.assertTrue(traceGroupName.equalsIgnoreCase(groupName), "wrong group name by HINT"); + Assert.assertTrue(params.contains(tableName), "wrong table name by HINT"); + } + } + Assert.assertTrue(traceResultCount == 1, "should access exactly one partition"); + } + } + + private void testGroupHint(String hint, Connection connection, Set slaveNodes, boolean shouldContain, + String table) + throws SQLException { + connection.createStatement().executeQuery("trace " + hint + " select * from " + table); + ResultSet rs = connection.createStatement().executeQuery("show trace"); + + while (rs.next()) { + String dbkey = rs.getString("DBKEY_NAME"); + String dnKey = dbkey.split("#")[1]; + if (shouldContain) { + Assert.assertTrue(slaveNodes.contains(dnKey)); + } else { + Assert.assertTrue(!slaveNodes.contains(dnKey)); + } + } + rs.close(); + } + } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/RangeScanTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/RangeScanTest.java new file mode 100644 index 000000000..2d25561ac --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/RangeScanTest.java @@ -0,0 +1,217 @@ +/* + * 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 com.alibaba.polardbx.qatest.dml.auto.basecrud; + +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.qatest.AutoCrudBasedLockTestCase; +import com.alibaba.polardbx.qatest.validator.DataOperator; +import com.alibaba.polardbx.qatest.validator.DataValidator; +import org.junit.Test; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class RangeScanTest extends AutoCrudBasedLockTestCase { + boolean enableRangeScanForDml; + + @Parameterized.Parameters(name = "{index}:hint={0}") + public static List prepareData() { + return Arrays.asList(Boolean.TRUE, Boolean.FALSE); + } + + public RangeScanTest(Boolean enableRangeScanForDml) { + this.enableRangeScanForDml = enableRangeScanForDml; + } + + private static final String RANGE_SCAN_HINT = + "/*+TDDL:CMD_EXTRA(ENABLE_RANGE_SCAN_FOR_DML=%s OPTIMIZE_MODIFY_TOP_N_BY_RETURNING=FALSE)*/"; + + private static final String TABLE_DEF = "CREATE TABLE `%s` (\n" + + " `id` varchar(32) NOT NULL,\n" + + " `c1` varchar(32) NOT NULL ,\n" + + " `c2` varchar(32) NOT NULL ,\n" + + " `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,\n" + + " PRIMARY KEY USING BTREE (`id`)\n" + + " ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4\n"; + private static final String INSERT_DEF = "insert into `%s`(id, c1, c2, create_time) values(?, ?, ?, ?)"; + private static final String UPDATE_DEF = + "update `%s` set c2 = 'u1' where c1 = 3 and create_time <= '2024-04-10' order by create_time desc limit 1"; + private static final String DELETE_DEF = + "delete from `%s` where c1 = 3 and create_time <= '2024-04-10' order by create_time desc limit 1"; + private static final String SELECT_DEF = "select * from `%s` order by create_time desc"; + + private static final String PARTITION_DEF = " PARTITION BY RANGE COLUMNS(create_time)\n" + + " (\n" + + " PARTITION p202403a VALUES LESS THAN('2024-03-11'),\n" + + " PARTITION p202403b VALUES LESS THAN('2024-03-21'),\n" + + " PARTITION p202403c VALUES LESS THAN('2024-04-01'),\n" + + " PARTITION p202404a VALUES LESS THAN('2024-04-11'),\n" + + " PARTITION p202404b VALUES LESS THAN('2024-04-21'),\n" + + " PARTITION p202404c VALUES LESS THAN('2024-05-01')\n" + + " );\n"; + + @Test + public void testRangePartition() { + final String tableName = "test_dml_range_scan_partition"; + + rebuildTable(tableName, TABLE_DEF, PARTITION_DEF); + + prepareData(tableName); + + modifyTopN(UPDATE_DEF, tableName); + + checkTraceRowCount(2); + + checkData(tableName); + + modifyTopN(DELETE_DEF, tableName); + + checkTraceRowCount(2); + + checkData(tableName); + } + + private static final String SUBPARTITION_DEF = " PARTITION BY KEY(c1)\n" + + " PARTITIONS 16\n" + + " SUBPARTITION BY RANGE COLUMNS(create_time)\n" + + " (\n" + + " SUBPARTITION sp202403a VALUES LESS THAN('2024-03-11'),\n" + + " SUBPARTITION sp202403b VALUES LESS THAN('2024-03-21'),\n" + + " SUBPARTITION sp202403c VALUES LESS THAN('2024-04-01'),\n" + + " SUBPARTITION sp202404a VALUES LESS THAN('2024-04-11'),\n" + + " SUBPARTITION sp202404b VALUES LESS THAN('2024-04-21'),\n" + + " SUBPARTITION sp202404c VALUES LESS THAN('2024-05-01')\n" + + " );"; + + @Test + public void testRangeSubpartition() { + final String tableName = "test_dml_range_scan_subpartition"; + + rebuildTable(tableName, TABLE_DEF, SUBPARTITION_DEF); + + prepareData(tableName); + + modifyTopN(UPDATE_DEF, tableName); + + checkTraceRowCount(2); + + checkData(tableName); + + modifyTopN(DELETE_DEF, tableName); + + checkTraceRowCount(2); + + checkData(tableName); + } + + private static final String SUBPARTITION_DEF_1 = " PARTITION BY RANGE COLUMNS(create_time)\n" + + " SUBPARTITION BY KEY(c1)\n" + + " SUBPARTITIONS 16\n" + + " (\n" + + " PARTITION sp202403a VALUES LESS THAN('2024-03-11'),\n" + + " PARTITION sp202403b VALUES LESS THAN('2024-03-21'),\n" + + " PARTITION sp202403c VALUES LESS THAN('2024-04-01'),\n" + + " PARTITION sp202404a VALUES LESS THAN('2024-04-11'),\n" + + " PARTITION sp202404b VALUES LESS THAN('2024-04-21'),\n" + + " PARTITION sp202404c VALUES LESS THAN('2024-05-01')\n" + + " )"; + + @Test + public void testRangeSubpartition1() { + final String tableName = "test_dml_range_scan_subpartition1"; + + rebuildTable(tableName, TABLE_DEF, SUBPARTITION_DEF_1); + + prepareData(tableName); + + modifyTopN(UPDATE_DEF, tableName); + + checkTraceRowCount(2); + + checkData(tableName); + + modifyTopN(DELETE_DEF, tableName); + + checkTraceRowCount(2); + + checkData(tableName); + } + + private void modifyTopN(String sqlTmpl, String tableName) { + final String modify = String.format(sqlTmpl, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + modify, + "trace " + String.format(RANGE_SCAN_HINT, enableRangeScanForDml) + modify, + null, + true); + } + + private void checkData(String tableName) { + final String select = String.format(SELECT_DEF, tableName); + DataValidator.selectContentSameAssert(select, null, tddlConnection, mysqlConnection); + } + + private void rebuildTable(String tableName, String tableDef, String partitionDef) { + final String dropTable = String.format(DROP_TABLE_SQL, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, dropTable, null); + + final String createTable = String.format(TABLE_DEF, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + createTable, + createTable + PARTITION_DEF, + null, + false); + } + + private void checkTraceRowCount(int rowCount) { + final List> traceUpdate = getTrace(tddlConnection); + if (enableRangeScanForDml) { + Assert.assertTrue(traceUpdate.size() == rowCount, + String.format("count of physical sql expect %s, but was %s", rowCount, traceUpdate.size())); + } else { + Assert.assertTrue(traceUpdate.size() > rowCount, + String.format("count of physical sql should greater than %s, but was %s", rowCount, + traceUpdate.size())); + } + } + + private void prepareData(String tableName) { + final String insert = String.format(INSERT_DEF, tableName); + final List createTimes = new ArrayList<>(); + createTimes.add("2024-03-10"); + createTimes.add("2024-03-20"); + createTimes.add("2024-03-30"); + createTimes.add("2024-04-10"); + createTimes.add("2024-04-20"); + createTimes.add("2024-04-30"); + final List> params = new ArrayList<>(); + for (int i = 0; i < 6; i++) { + List param = new ArrayList<>(); + param.add(i); + param.add(i); + param.add(i); + param.add(createTimes.get(i)); + params.add(param); + } + DataOperator.executeBatchOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, params); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/ReplacePushDownTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/ReplacePushDownTest.java index d4cb9adcc..fcf8f4366 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/ReplacePushDownTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/ReplacePushDownTest.java @@ -94,13 +94,13 @@ public void testReplacePushDown() throws SQLException { shouldPushDown(tddlConnection, String.format(replaceSql, canPushDownTable0)); shouldPushDown(tddlConnection, String.format(replaceSql, canPushDownTable1)); shouldPushDown(tddlConnection, String.format(replaceSql, canNotPushDownTable0)); - shouldNotPushDown(tddlConnection, String.format(replaceSql, canNotPushDownTable1)); + // shouldNotPushDown(tddlConnection, String.format(replaceSql, canNotPushDownTable1)); JdbcUtil.executeSuccess(tddlConnection, "set transaction_isolation = 'READ-COMMITTED'"); shouldPushDown(tddlConnection, String.format(replaceSql, canPushDownTable0)); shouldPushDown(tddlConnection, String.format(replaceSql, canPushDownTable1)); shouldNotPushDown(tddlConnection, String.format(replaceSql, canNotPushDownTable0)); - shouldNotPushDown(tddlConnection, String.format(replaceSql, canNotPushDownTable1)); + // shouldNotPushDown(tddlConnection, String.format(replaceSql, canNotPushDownTable1)); } finally { clean(tddlConnection); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/SpecialUpsertTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/SpecialUpsertTest.java new file mode 100644 index 000000000..8b02f1fd2 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/SpecialUpsertTest.java @@ -0,0 +1,196 @@ +package com.alibaba.polardbx.qatest.dml.auto.basecrud; + +import com.alibaba.polardbx.qatest.AutoCrudBasedLockTestCase; +import com.alibaba.polardbx.qatest.data.ExecuteTableName; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.alibaba.polardbx.qatest.validator.DataOperator; +import com.google.common.truth.Truth; +import org.apache.calcite.util.Pair; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentSameAssert; + +public class SpecialUpsertTest extends AutoCrudBasedLockTestCase { + + private static final String TABLE_DEF = "CREATE TABLE `%s` (\n" + + " `ID` varchar(32) NOT NULL ,\n" + + " `XX_DATE` date NOT NULL,\n" + + " PRIMARY KEY (`ID`)\n" + + ") "; + + private static final String TABLE_DOUBLE_UK_DEF = "CREATE TABLE `%s` (\n" + + " `ID` varchar(32) NOT NULL ,\n" + + " `XX_DATE` date NOT NULL,\n" + + " PRIMARY KEY (`ID`),\n" + + " UNIQUE KEY (`XX_DATE`)\n" + + ") "; + + private static final String PARTITION_DEF = + "partition by UNI_HASH(`id`) subpartition by HASH(DAYOFMONTH(`xx_date`)) subpartitions 31;"; + + private static final List CREATE_TIME = new ArrayList<>(); + + static { + CREATE_TIME.add("2024-01-26 00:00:00.0"); + CREATE_TIME.add("2024-01-27 00:00:00.0"); + CREATE_TIME.add("2024-01-28 00:00:00.0"); + CREATE_TIME.add("2024-01-29 00:00:00.0"); + CREATE_TIME.add("2024-01-30 00:00:00.0"); + CREATE_TIME.add("2024-01-31 00:00:00.0"); + } + + private static final String INSERT_DEF = "insert into %s(ID, XX_DATE) VALUES(?, ?)"; + + public SpecialUpsertTest() { + this.baseOneTableName = ExecuteTableName.UPDATE_DELETE_BASE + ExecuteTableName.HASH_BY_VARCHAR + + ExecuteTableName.MUlTI_DB_MUTIL_TB_SUFFIX; + this.baseTwoTableName = ExecuteTableName.UPDATE_DELETE_BASE + ExecuteTableName.HASH_BY_VARCHAR + + ExecuteTableName.TWO + ExecuteTableName.MUlTI_DB_MUTIL_TB_SUFFIX; + } + + private static final String UPSERT_WITH_AFTER_VALUE_DEF = + "insert into %s(ID, XX_DATE) VALUES(1, '2024-02-27 00:00:00.0') " + + "on duplicate key update xx_date=values(xx_date);"; + + @Test + public void pushdownUpsertWithPartialAfterTest() { + final String tableName = "t1_pushdown_upsert11"; + + rebuildTable(tableName, TABLE_DEF, PARTITION_DEF); + + prepareData(tableName, 3); + + executeAndTraceUpsert(UPSERT_WITH_AFTER_VALUE_DEF, tableName); + + checkTraceRowCount(1); + + final String sql = String.format("select id, xx_date from %s order by id", tableName); + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + @Test + public void pushdownUpsertWithPartialAfterTest2() { + final String tableName = "t1_pushdown_upsert12"; + + rebuildTable(tableName, TABLE_DOUBLE_UK_DEF, PARTITION_DEF); + + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + prepareData(tableName, 3); + + executeAndTraceUpsert( + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ " + UPSERT_WITH_AFTER_VALUE_DEF, + tableName); + + checkTraceRowCount(topology.size() + 2); + + final String sql = String.format("select id, xx_date from %s order by id", tableName); + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + private static final String UPSERT_WITH_BEFORE_VALUE_DEF = + "insert into %s(ID, XX_DATE) VALUES(1, '2024-02-27 00:00:00.0') " + + "on duplicate key update xx_date=xx_date;"; + + @Test + public void pushdownUpsertWithPartialBeforeTest() { + final String tableName = "t1_pushdown_upsert21"; + + rebuildTable(tableName, TABLE_DEF, PARTITION_DEF); + + prepareData(tableName, 3); + + executeAndTraceUpsert(UPSERT_WITH_BEFORE_VALUE_DEF, tableName); + + checkTraceRowCount(1); + + final String sql = String.format("select id, xx_date from %s order by id", tableName); + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + @Test + public void pushdownUpsertWithPartialBeforeTest2() { + final String tableName = "t1_pushdown_upsert22"; + + rebuildTable(tableName, TABLE_DOUBLE_UK_DEF, PARTITION_DEF); + + prepareData(tableName, 3); + + executeAndTraceUpsert(UPSERT_WITH_BEFORE_VALUE_DEF, tableName); + + checkTraceRowCount(1); + + final String sql = String.format("select id, xx_date from %s order by id", tableName); + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + private static final String UPSERT_WITH_BEFORE_AND_AFTER_VALUE_DEF = + "insert into %s(ID, XX_DATE) VALUES(1, '2024-02-27 00:00:00.0') " + + "on duplicate key update id=id, xx_date=values(xx_date);"; + + @Test + public void pushdownUpsertWithBeforeAndAfterTest() { + final String tableName = "t1_pushdown_upsert31"; + + rebuildTable(tableName, TABLE_DEF, PARTITION_DEF); + + prepareData(tableName, 3); + + executeAndTraceUpsert(UPSERT_WITH_BEFORE_AND_AFTER_VALUE_DEF, tableName); + + checkTraceRowCount(1); + + final String sql = String.format("select id, xx_date from %s order by id", tableName); + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + private void executeAndTraceUpsert(String sqlTmpl, String tableName) { + final String upsertSql = String.format(sqlTmpl, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + upsertSql, + "trace " + upsertSql, + null, + true); + } + + private void rebuildTable(String tableName, String tableDef, String partitionDef) { + final String dropTable = String.format(DROP_TABLE_SQL, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, dropTable, null); + + final String createTable = String.format(tableDef, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + createTable, + createTable + partitionDef, + null, + false); + } + + private void prepareData(String tableName, int rowCount) { + final String insert = String.format(INSERT_DEF, tableName); + final List> params = new ArrayList<>(); + for (int i = 0; i < rowCount; i++) { + List param = new ArrayList<>(); + param.add(i); + param.add(CREATE_TIME.get(i % CREATE_TIME.size())); + params.add(param); + } + DataOperator.executeBatchOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, params); + } + + private void checkTraceRowCount(int rowCount) { + final List> traceUpdate = getTrace(tddlConnection); + Truth.assertWithMessage(Optional + .ofNullable(traceUpdate) + .map(tu -> tu.stream().map(r -> String.join(", ", r)).collect(Collectors.joining("\n"))) + .orElse("show trace result is null")) + .that(traceUpdate) + .hasSize(rowCount); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/UpdateTimestampTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/UpdateTimestampTest.java index 13698bb7e..59208c670 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/UpdateTimestampTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/basecrud/UpdateTimestampTest.java @@ -162,7 +162,8 @@ public void insertDuplicateTest() { } //设置精度为2 - insertSql = "insert into " + tableName + insertSql = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ " + + "insert into " + tableName + "(pk, sk) values(2, 3) ON DUPLICATE KEY UPDATE sk = 5, time = current_timestamp(2)"; i = 0; //重试多次,防止偶发真的为0 diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/broadcast/BroadcastWriteWithXATest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/broadcast/BroadcastWriteWithXATest.java index 1298b5cd1..f4ae52905 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/broadcast/BroadcastWriteWithXATest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/broadcast/BroadcastWriteWithXATest.java @@ -160,12 +160,12 @@ public void WriteBroadcastTable_autocommit_0_free() throws SQLException { sql = "DELETE FROM " + baseOneTableName + " WHERE pk = 6"; executeOnMysqlAndTddl(mysqlConnection, tddlConnection, sql, null); - assertVariable("drds_transaction_policy", "NO_TRANSACTION", tddlConnection, false); + assertVariable("transaction_policy", "NO_TRANSACTION", tddlConnection, false); sql = "COMMIT"; executeOnMysqlAndTddl(mysqlConnection, tddlConnection, sql, null); - assertVariable("drds_transaction_policy", "NO_TRANSACTION", tddlConnection, false); + assertVariable("transaction_policy", "NO_TRANSACTION", tddlConnection, false); sql = "SELECT * FROM " + baseOneTableName; selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); @@ -174,11 +174,11 @@ public void WriteBroadcastTable_autocommit_0_free() throws SQLException { @Test public void WriteBroadcastTable_autocommit_1_multi_statement() throws SQLException { String sql = "INSERT INTO " + baseOneTableName + "(pk, varchar_test, integer_test, timestamp_test) VALUES" - + "(1, 'something in broadcast table', 666, '2019-10-16 02:00:00'), (6, 'something in broadcast table', 777, '2019-10-16 02:00:00'); SHOW variables LIKE 'drds_transaction_policy'"; + + "(1, 'something in broadcast table', 666, '2019-10-16 02:00:00'), (6, 'something in broadcast table', 777, '2019-10-16 02:00:00'); SHOW variables LIKE 'transaction_policy'"; executeOnMysqlAndTddl(mysqlConnection, tddlConnection, sql, null); sql = "INSERT INTO " + baseOneTableName + "(pk, varchar_test, integer_test, timestamp_test) VALUES" - + "(3, 'something in broadcast table', 666, '2019-10-16 02:00:00'), (8, 'something in broadcast table', 777, '2019-10-16 02:00:00'); SHOW variables LIKE 'drds_transaction_policy'"; + + "(3, 'something in broadcast table', 666, '2019-10-16 02:00:00'), (8, 'something in broadcast table', 777, '2019-10-16 02:00:00'); SHOW variables LIKE 'transaction_policy'"; try (PreparedStatement ps = tddlConnection.prepareStatement(sql)) { boolean hasMoreResultSets = ps.execute(); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/delete/DeleteTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/delete/DeleteTest.java index a26a143b4..5f170ac8f 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/delete/DeleteTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/delete/DeleteTest.java @@ -30,6 +30,7 @@ import org.junit.Test; import org.junit.runners.Parameterized.Parameters; +import javax.xml.crypto.Data; import java.sql.ResultSet; import java.sql.Statement; import java.text.MessageFormat; @@ -1125,5 +1126,54 @@ public void deleteWithView() { executeErrorAssert(tddlConnection, sql, null, MessageFormat.format("{0}'' of the {1} is not updatable", viewName, "DELETE")); } + + // delete with force index + // delete t from t ... + // delete from t ... + @Test + public void deleteWithForceIndex1() throws Exception { + String tddlSql = String.format("delete from %s force index (primary) where pk = 5", baseOneTableName); + String mysqlSql = + String.format("delete %s from %s force index (primary) where pk = 5", baseOneTableName, baseOneTableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, mysqlSql, tddlSql, null, true); + String sql = String.format("select * from %s", baseOneTableName); + selectContentSameAssert(sql, null, mysqlConnection, + tddlConnection, true); + } + + // delete from t as t1 + @Test + public void deleteWithForceIndex2() throws Exception { + String tddlSql = String.format("delete from %s as t1 force index (primary) where t1.pk = 5", baseOneTableName); + String mysqlSql = + String.format("delete t1 from %s as t1 force index (primary) where t1.pk = 5", baseOneTableName, + baseOneTableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, mysqlSql, tddlSql, null, true); + String sql = String.format("select * from %s", baseOneTableName); + selectContentSameAssert(sql, null, mysqlConnection, + tddlConnection, true); + } + + // delete with force non-exist index should not throw exception + @Test + public void deleteWithForceIndex3() throws Exception { + String tddlSql = String.format("delete from %s force index (aaa) where pk = 5", baseOneTableName); + String mysqlSql = String.format("delete from %s where pk = 5", baseOneTableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, mysqlSql, tddlSql, null, true); + String sql = String.format("select * from %s", baseOneTableName); + selectContentSameAssert(sql, null, mysqlConnection, + tddlConnection, true); + } + + // delete with force multi index only use first + @Test + public void deleteWithForceIndex4() throws Exception { + String tddlSql = String.format("delete from %s force index (aaa,primary) where pk = 5", baseOneTableName); + String mysqlSql = String.format("delete from %s where pk = 5", baseOneTableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, mysqlSql, tddlSql, null, true); + String sql = String.format("select * from %s", baseOneTableName); + selectContentSameAssert(sql, null, mysqlConnection, + tddlConnection, true); + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/delete/DeleteWithThreeTableTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/delete/DeleteWithThreeTableTest.java index 6862877f6..bc2ff394e 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/delete/DeleteWithThreeTableTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/auto/delete/DeleteWithThreeTableTest.java @@ -243,4 +243,33 @@ public void assertBrocastTableSame(String tableName) { } } + @Test + public void deleteWithForceIndex() throws Exception { + String tddlSql = String + .format( + "delete from %s.*, %s.*, a.* using %s force index(xxx,primary), %s force index(primary,xxx), %s as a force index(primary) ", + baseOneTableName, baseTwoTableName, + baseOneTableName, baseTwoTableName, baseThreeTableName); + + String mysqlSql = String + .format("delete from %s.*, %s.*, a.* using %s, %s, %s as a ", baseOneTableName, baseTwoTableName, + baseOneTableName, baseTwoTableName, baseThreeTableName); + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, mysqlSql, tddlSql, null, true); + + String sql = "select * from " + baseOneTableName; + selectContentSameAssert(sql, null, mysqlConnection, + tddlConnection, true); + sql = "select * from " + baseTwoTableName; + selectContentSameAssert(sql, null, mysqlConnection, + tddlConnection, true); + sql = "select * from " + baseThreeTableName; + selectContentSameAssert(sql, null, mysqlConnection, + tddlConnection, true); + + assertBrocastTableSame(baseOneTableName); + assertBrocastTableSame(baseTwoTableName); + assertBrocastTableSame(baseThreeTableName); + } + } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/DefaultAsExprValueTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/DefaultAsExprValueTest.java index b21b9d1c2..dc22b6ee1 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/DefaultAsExprValueTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/DefaultAsExprValueTest.java @@ -30,6 +30,8 @@ public class DefaultAsExprValueTest extends CrudBasedLockTestCase { + " `C11` DATE NOT NULL DEFAULT (CURRENT_DATE + INTERVAL 1 YEAR)," + " `C12` varchar(20) NOT NULL DEFAULT (LPAD(''string'', 5, ''0''))," + " `C13` tinyint(1) NOT NULL DEFAULT (TRUE)," + + " `C14` binary(16) NOT NULL DEFAULT (uuid_to_bin(''e7fe4fc5-11ef-1739-accb-0242ac110012''))," +// + " `C15` varchar(64) NOT NULL DEFAULT (bin_to_uuid(0xE7FE4FC511EF1739ACCB0242AC110012))," + " PRIMARY KEY (`pk`)" + ") {0} "; private static final String SELECT_COLUMN = "c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13"; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/InsertSelectTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/InsertSelectTest.java index 45b22e3f7..bac1ee0b0 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/InsertSelectTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/InsertSelectTest.java @@ -1038,4 +1038,17 @@ public void insertWithSubQueryTest() throws Exception { sql = "select * from " + baseTwoTableName; selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); } + + @Test + public void insertWithSelectAggTest() throws Exception { + String sql = "insert into " + baseTwoTableName + + " (varchar_test, integer_test, bigint_test) select varchar_test, min(integer_test), max(integer_test) from " + + baseOneTableName + + " group by varchar_test;"; + + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, sql, null, true); + + sql = "select " + selectColumn + " from " + baseTwoTableName; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/MultiDBSingleTableDMLTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/MultiDBSingleTableDMLTest.java new file mode 100644 index 000000000..930119bdb --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/MultiDBSingleTableDMLTest.java @@ -0,0 +1,103 @@ +package com.alibaba.polardbx.qatest.dml.sharding.basecrud; + +import com.alibaba.polardbx.qatest.CrudBasedLockTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class MultiDBSingleTableDMLTest extends CrudBasedLockTestCase { + String dbOneName = "drdsMultiDBTest1"; + String dbTwoName = "drdsMultiDBTest2"; + + String createTableSQL = "create table %s (id bigint primary key, a bigint, c int) %s ;"; + String tableName = "single_table_one"; + + @Before + public void initData() throws Exception { + JdbcUtil.dropDatabase(tddlConnection, dbOneName); + JdbcUtil.dropDatabase(tddlConnection, dbTwoName); + JdbcUtil.createDatabase(tddlConnection, dbOneName, ""); + JdbcUtil.createDatabase(tddlConnection, dbTwoName, ""); + } + + @After + public void after() throws Exception { + JdbcUtil.useDb(tddlConnection, polardbxOneDB); + JdbcUtil.dropDatabase(tddlConnection, dbOneName); + JdbcUtil.dropDatabase(tddlConnection, dbTwoName); + } + + @Test + public void differentDnTest() { + List storageInfo = getStorageInfo(tddlConnection, dbOneName); + //需测试不同storage的情况 + if (storageInfo.size() < 2) { + System.out.println("skip test, because there is only one storage:" + storageInfo); + return; + } + + //通过locality创建不同dn的表 + JdbcUtil.useDb(tddlConnection, dbOneName); + JdbcUtil.dropTable(tddlConnection, tableName); + JdbcUtil.executeSuccess(tddlConnection, + String.format(createTableSQL, tableName, "locality = 'dn=" + storageInfo.get(0)) + "'"); + JdbcUtil.useDb(tddlConnection, dbTwoName); + JdbcUtil.dropTable(tddlConnection, tableName); + JdbcUtil.executeSuccess(tddlConnection, + String.format(createTableSQL, tableName, "locality = 'dn=" + storageInfo.get(1)) + "'"); + + JdbcUtil.useDb(tddlConnection, dbOneName); + JdbcUtil.executeSuccess(tddlConnection, "insert into " + tableName + " values(1,1,1),(2,2,2),(3,3,3),(4,4,4)"); + + String sql = String.format("insert into %s.%s select * from %s.%s", dbTwoName, tableName, dbOneName, tableName); + JdbcUtil.executeSuccess(tddlConnection, sql); + List rows = + JdbcUtil.executeQueryAndGetColumnResult("select count(*) from " + dbTwoName + '.' + tableName, + tddlConnection, 1); + Assert.assertEquals(4, Integer.parseInt(rows.get(0))); + + String updateSql = + String.format("update %s.%s ta, %s.%s tb set ta.a = 10 where ta.id = tb.id", dbOneName, tableName, + dbTwoName, tableName); + JdbcUtil.executeSuccess(tddlConnection, updateSql); + List aResult = + JdbcUtil.executeQueryAndGetColumnResult("select a from " + dbOneName + '.' + tableName, tddlConnection, 1); + Assert.assertEquals(4, aResult.size()); + Assert.assertEquals(10, Integer.parseInt(aResult.get(0))); + + String deleteSql = + String.format("delete ta from %s.%s ta, %s.%s tb where ta.id = tb.id", dbOneName, tableName, dbTwoName, + tableName); + JdbcUtil.executeSuccess(tddlConnection, deleteSql); + List rows2 = + JdbcUtil.executeQueryAndGetColumnResult("select count(*) from " + dbOneName + '.' + tableName, + tddlConnection, 1); + Assert.assertEquals(0, Integer.parseInt(rows2.get(0))); + + } + + private List getStorageInfo(Connection con, String dbName) { + final String sql = "show ds where db = '" + dbName + "'"; + Set storageList = new HashSet<>(); + try (ResultSet result = JdbcUtil.executeQuerySuccess(con, sql)) { + while (result.next()) { + String storageName = result.getString("STORAGE_INST_ID"); + storageList.add(storageName); + } + return new ArrayList<>(storageList); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + } +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/SpecialUpsertTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/SpecialUpsertTest.java new file mode 100644 index 000000000..ed126b0da --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/SpecialUpsertTest.java @@ -0,0 +1,196 @@ +package com.alibaba.polardbx.qatest.dml.sharding.basecrud; + +import com.alibaba.polardbx.qatest.CrudBasedLockTestCase; +import com.alibaba.polardbx.qatest.data.ExecuteTableName; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.alibaba.polardbx.qatest.validator.DataOperator; +import com.google.common.truth.Truth; +import org.apache.calcite.util.Pair; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentSameAssert; + +public class SpecialUpsertTest extends CrudBasedLockTestCase { + + private static final String TABLE_DEF = "CREATE TABLE `%s` (\n" + + " `ID` varchar(32) NOT NULL ,\n" + + " `XX_DATE` date NOT NULL,\n" + + " PRIMARY KEY (`ID`)\n" + + ") "; + + private static final String TABLE_DOUBLE_UK_DEF = "CREATE TABLE `%s` (\n" + + " `ID` varchar(32) NOT NULL ,\n" + + " `XX_DATE` date NOT NULL,\n" + + " PRIMARY KEY (`ID`),\n" + + " UNIQUE KEY (`XX_DATE`)\n" + + ") "; + + private static final String PARTITION_DEF = + "dbpartition by UNI_HASH(`id`) tbpartition by DD(`xx_date`) tbpartitions 31;"; + + private static final List CREATE_TIME = new ArrayList<>(); + + static { + CREATE_TIME.add("2024-01-26 00:00:00.0"); + CREATE_TIME.add("2024-01-27 00:00:00.0"); + CREATE_TIME.add("2024-01-28 00:00:00.0"); + CREATE_TIME.add("2024-01-29 00:00:00.0"); + CREATE_TIME.add("2024-01-30 00:00:00.0"); + CREATE_TIME.add("2024-01-31 00:00:00.0"); + } + + private static final String INSERT_DEF = "insert into %s(ID, XX_DATE) VALUES(?, ?)"; + + public SpecialUpsertTest() { + this.baseOneTableName = ExecuteTableName.UPDATE_DELETE_BASE + ExecuteTableName.HASH_BY_VARCHAR + + ExecuteTableName.MUlTI_DB_MUTIL_TB_SUFFIX; + this.baseTwoTableName = ExecuteTableName.UPDATE_DELETE_BASE + ExecuteTableName.HASH_BY_VARCHAR + + ExecuteTableName.TWO + ExecuteTableName.MUlTI_DB_MUTIL_TB_SUFFIX; + } + + private static final String UPSERT_WITH_AFTER_VALUE_DEF = + "insert into %s(ID, XX_DATE) VALUES(1, '2024-02-27 00:00:00.0') " + + "on duplicate key update xx_date=values(xx_date);"; + + @Test + public void pushdownUpsertWithPartialAfterTest() { + final String tableName = "t1_pushdown_upsert11"; + + rebuildTable(tableName, TABLE_DEF, PARTITION_DEF); + + prepareData(tableName, 3); + + executeAndTraceUpsert(UPSERT_WITH_AFTER_VALUE_DEF, tableName); + + checkTraceRowCount(1); + + final String sql = String.format("select id, xx_date from %s order by id", tableName); + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + @Test + public void pushdownUpsertWithPartialAfterTest2() { + final String tableName = "t1_pushdown_upsert12"; + + rebuildTable(tableName, TABLE_DOUBLE_UK_DEF, PARTITION_DEF); + + final List> topology = JdbcUtil.getTopology(tddlConnection, tableName); + + prepareData(tableName, 3); + + executeAndTraceUpsert( + "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ " + UPSERT_WITH_AFTER_VALUE_DEF, + tableName); + + checkTraceRowCount(topology.size() + 2); + + final String sql = String.format("select id, xx_date from %s order by id", tableName); + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + private static final String UPSERT_WITH_BEFORE_VALUE_DEF = + "insert into %s(ID, XX_DATE) VALUES(1, '2024-02-27 00:00:00.0') " + + "on duplicate key update xx_date=xx_date;"; + + @Test + public void pushdownUpsertWithPartialBeforeTest() { + final String tableName = "t1_pushdown_upsert21"; + + rebuildTable(tableName, TABLE_DEF, PARTITION_DEF); + + prepareData(tableName, 3); + + executeAndTraceUpsert(UPSERT_WITH_BEFORE_VALUE_DEF, tableName); + + checkTraceRowCount(1); + + final String sql = String.format("select id, xx_date from %s order by id", tableName); + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + @Test + public void pushdownUpsertWithPartialBeforeTest2() { + final String tableName = "t1_pushdown_upsert22"; + + rebuildTable(tableName, TABLE_DOUBLE_UK_DEF, PARTITION_DEF); + + prepareData(tableName, 3); + + executeAndTraceUpsert(UPSERT_WITH_BEFORE_VALUE_DEF, tableName); + + checkTraceRowCount(1); + + final String sql = String.format("select id, xx_date from %s order by id", tableName); + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + private static final String UPSERT_WITH_BEFORE_AND_AFTER_VALUE_DEF = + "insert into %s(ID, XX_DATE) VALUES(1, '2024-02-27 00:00:00.0') " + + "on duplicate key update id=id, xx_date=values(xx_date);"; + + @Test + public void pushdownUpsertWithBeforeAndAfterTest() { + final String tableName = "t1_pushdown_upsert31"; + + rebuildTable(tableName, TABLE_DEF, PARTITION_DEF); + + prepareData(tableName, 3); + + executeAndTraceUpsert(UPSERT_WITH_BEFORE_AND_AFTER_VALUE_DEF, tableName); + + checkTraceRowCount(1); + + final String sql = String.format("select id, xx_date from %s order by id", tableName); + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + + private void executeAndTraceUpsert(String sqlTmpl, String tableName) { + final String upsertSql = String.format(sqlTmpl, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + upsertSql, + "trace " + upsertSql, + null, + true); + } + + private void rebuildTable(String tableName, String tableDef, String partitionDef) { + final String dropTable = String.format(DROP_TABLE_SQL, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, dropTable, null); + + final String createTable = String.format(tableDef, tableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, + tddlConnection, + createTable, + createTable + partitionDef, + null, + false); + } + + private void prepareData(String tableName, int rowCount) { + final String insert = String.format(INSERT_DEF, tableName); + final List> params = new ArrayList<>(); + for (int i = 0; i < rowCount; i++) { + List param = new ArrayList<>(); + param.add(i); + param.add(CREATE_TIME.get(i % CREATE_TIME.size())); + params.add(param); + } + DataOperator.executeBatchOnMysqlAndTddl(mysqlConnection, tddlConnection, insert, params); + } + + private void checkTraceRowCount(int rowCount) { + final List> traceUpdate = getTrace(tddlConnection); + Truth.assertWithMessage(Optional + .ofNullable(traceUpdate) + .map(tu -> tu.stream().map(r -> String.join(", ", r)).collect(Collectors.joining("\n"))) + .orElse("show trace result is null")) + .that(traceUpdate) + .hasSize(rowCount); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/UpdateTimestampTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/UpdateTimestampTest.java index 254eb7d99..e539ed4d4 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/UpdateTimestampTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/basecrud/UpdateTimestampTest.java @@ -163,7 +163,8 @@ public void insertDuplicateTest() { } //设置精度为2 - insertSql = "insert into " + tableName + insertSql = "/*+TDDL:CMD_EXTRA(DML_GET_DUP_FOR_LOCAL_UK_WITH_FULL_TABLE_SCAN=true)*/ " + + "insert into " + tableName + "(pk, sk) values(2, 3) ON DUPLICATE KEY UPDATE sk = 5, time = current_timestamp(2)"; i = 0; //重试多次,防止偶发真的为0 diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/broadcast/BroadcastWriteWithXATest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/broadcast/BroadcastWriteWithXATest.java index d17eb62a3..9d7cf3f3a 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/broadcast/BroadcastWriteWithXATest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/broadcast/BroadcastWriteWithXATest.java @@ -1,19 +1,3 @@ -/* - * Copyright [2013-2021], Alibaba Group Holding Limited - * - * Licensed 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 com.alibaba.polardbx.qatest.dml.sharding.broadcast; import com.alibaba.polardbx.qatest.CrudBasedLockTestCase; @@ -24,6 +8,8 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import java.sql.PreparedStatement; @@ -160,12 +146,12 @@ public void WriteBroadcastTable_autocommit_0_free() throws SQLException { sql = "DELETE FROM " + baseOneTableName + " WHERE pk = 6"; executeOnMysqlAndTddl(mysqlConnection, tddlConnection, sql, null); - assertVariable("drds_transaction_policy", "NO_TRANSACTION", tddlConnection, false); + assertVariable("transaction_policy", "NO_TRANSACTION", tddlConnection, false); sql = "COMMIT"; executeOnMysqlAndTddl(mysqlConnection, tddlConnection, sql, null); - assertVariable("drds_transaction_policy", "NO_TRANSACTION", tddlConnection, false); + assertVariable("transaction_policy", "NO_TRANSACTION", tddlConnection, false); sql = "SELECT * FROM " + baseOneTableName; selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); @@ -174,11 +160,11 @@ public void WriteBroadcastTable_autocommit_0_free() throws SQLException { @Test public void WriteBroadcastTable_autocommit_1_multi_statement() throws SQLException { String sql = "INSERT INTO " + baseOneTableName + "(pk, varchar_test, integer_test, timestamp_test) VALUES" - + "(1, 'something in broadcast table', 666, '2019-10-16 02:00:00'), (6, 'something in broadcast table', 777, '2019-10-16 02:00:00'); SHOW variables LIKE 'drds_transaction_policy'"; + + "(1, 'something in broadcast table', 666, '2019-10-16 02:00:00'), (6, 'something in broadcast table', 777, '2019-10-16 02:00:00'); SHOW variables LIKE 'transaction_policy'"; executeOnMysqlAndTddl(mysqlConnection, tddlConnection, sql, null); sql = "INSERT INTO " + baseOneTableName + "(pk, varchar_test, integer_test, timestamp_test) VALUES" - + "(3, 'something in broadcast table', 666, '2019-10-16 02:00:00'), (8, 'something in broadcast table', 777, '2019-10-16 02:00:00'); SHOW variables LIKE 'drds_transaction_policy'"; + + "(3, 'something in broadcast table', 666, '2019-10-16 02:00:00'), (8, 'something in broadcast table', 777, '2019-10-16 02:00:00'); SHOW variables LIKE 'transaction_policy'"; try (PreparedStatement ps = tddlConnection.prepareStatement(sql)) { boolean hasMoreResultSets = ps.execute(); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/datatype/DataTypeShardingTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/datatype/DataTypeShardingTest.java index d90b3e8c4..f504b1c4d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/datatype/DataTypeShardingTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/datatype/DataTypeShardingTest.java @@ -21,6 +21,7 @@ import com.alibaba.polardbx.qatest.CrudBasedLockTestCase; import com.alibaba.polardbx.qatest.data.ExecuteTableName; import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.google.common.truth.Truth; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -30,11 +31,6 @@ import java.util.Arrays; import java.util.List; -import static com.alibaba.polardbx.qatest.validator.DataOperator.executeOnMysqlAndTddl; -import static com.alibaba.polardbx.qatest.validator.DataValidator.explainAllResultNotMatchAssert; -import static com.alibaba.polardbx.qatest.validator.DataValidator.explainResultMatchAssert; -import static com.alibaba.polardbx.qatest.validator.DataValidator.selectOrderByNotPrimaryKeyAssert; - /** * @author fangwu */ @@ -75,15 +71,31 @@ public void testDataTypeSharding() throws Exception { while (rs.next()) { groupName = rs.getString("GROUP_NAME"); } - + rs.close(); Assert.assertTrue(!StringUtils.isEmpty(groupName)); - String explainSql = "explain select 1 from " + tableName + " where c2=131313131331312"; - explainResultMatchAssert(explainSql, null, tddlConnection, "[\\s\\S]*" + groupName + "[\\s\\S]*"); - explainSql = "explain select 1 from " + tableName + " where c2 in(131313131331312)"; - explainResultMatchAssert(explainSql, null, tddlConnection, "[\\s\\S]*" + groupName + "[\\s\\S]*"); + String explainSql = "trace select 1 from " + tableName + " where c2=131313131331312"; + JdbcUtil.executeUpdateSuccess(tddlConnection, explainSql); + rs = JdbcUtil.executeQuery("show trace", tddlConnection); + while (rs.next()) { + Truth.assertWithMessage(explainSql).that(rs.getString("GROUP_NAME")).isEqualTo(groupName); + } + rs.close(); - explainSql = "explain select 1 from " + tableName + " where c2 in('131313131331312')"; - explainResultMatchAssert(explainSql, null, tddlConnection, "[\\s\\S]*" + groupName + "[\\s\\S]*"); + explainSql = "trace select 1 from " + tableName + " where c2 in(131313131331312)"; + JdbcUtil.executeUpdateSuccess(tddlConnection, explainSql); + rs = JdbcUtil.executeQuery("show trace", tddlConnection); + while (rs.next()) { + Truth.assertWithMessage(explainSql).that(rs.getString("GROUP_NAME")).isEqualTo(groupName); + } + rs.close(); + + explainSql = "trace select 1 from " + tableName + " where c2 in('131313131331312')"; + JdbcUtil.executeUpdateSuccess(tddlConnection, explainSql); + rs = JdbcUtil.executeQuery("show trace", tddlConnection); + while (rs.next()) { + Truth.assertWithMessage(explainSql).that(rs.getString("GROUP_NAME")).isEqualTo(groupName); + } + rs.close(); } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/delete/DeleteTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/delete/DeleteTest.java index 670fef769..8bcd7dd6d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/delete/DeleteTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/delete/DeleteTest.java @@ -1110,5 +1110,51 @@ public void deleteWithView() { executeErrorAssert(tddlConnection, sql, null, MessageFormat.format("{0}'' of the {1} is not updatable", viewName, "DELETE")); } + + @Test + public void deleteWithForceIndex() throws Exception { + String tddlSql = String.format("delete from %s force index (primary) where pk = 5", baseOneTableName); + String mysqlSql = + String.format("delete %s from %s force index (primary) where pk = 5", baseOneTableName, baseOneTableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, mysqlSql, tddlSql, null, true); + String sql = String.format("select * from %s", baseOneTableName); + selectContentSameAssert(sql, null, mysqlConnection, + tddlConnection, true); + } + + // delete from t as t1 + @Test + public void deleteWithForceIndex2() throws Exception { + String tddlSql = String.format("delete from %s as t1 force index (primary) where t1.pk = 5", baseOneTableName); + String mysqlSql = + String.format("delete t1 from %s as t1 force index (primary) where t1.pk = 5", baseOneTableName, + baseOneTableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, mysqlSql, tddlSql, null, true); + String sql = String.format("select * from %s", baseOneTableName); + selectContentSameAssert(sql, null, mysqlConnection, + tddlConnection, true); + } + + // delete with force non-exist index should not throw exception + @Test + public void deleteWithForceIndex3() throws Exception { + String tddlSql = String.format("delete from %s force index (aaa) where pk = 5", baseOneTableName); + String mysqlSql = String.format("delete %s from %s where pk = 5", baseOneTableName, baseOneTableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, mysqlSql, tddlSql, null, true); + String sql = String.format("select * from %s", baseOneTableName); + selectContentSameAssert(sql, null, mysqlConnection, + tddlConnection, true); + } + + // delete with force multi index only use first + @Test + public void deleteWithForceIndex4() throws Exception { + String tddlSql = String.format("delete from %s force index (aaa,primary) where pk = 5", baseOneTableName); + String mysqlSql = String.format("delete from %s where pk = 5", baseOneTableName); + DataOperator.executeOnMysqlAndTddl(mysqlConnection, tddlConnection, mysqlSql, tddlSql, null, true); + String sql = String.format("select * from %s", baseOneTableName); + selectContentSameAssert(sql, null, mysqlConnection, + tddlConnection, true); + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/DeleteGsiTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/DeleteGsiTest.java index 28e2b5765..54b7da2b8 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/DeleteGsiTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/DeleteGsiTest.java @@ -17,6 +17,7 @@ package com.alibaba.polardbx.qatest.dml.sharding.gsi; import com.alibaba.polardbx.common.utils.TStringUtil; +import com.alibaba.polardbx.optimizer.core.function.calc.scalar.math.Exp; import com.alibaba.polardbx.qatest.BinlogIgnore; import com.alibaba.polardbx.qatest.util.JdbcUtil; import org.junit.AfterClass; @@ -383,4 +384,38 @@ public void run() { assertRouteCorrectness(baseOneTableName); } + + // test force gsi , use table gsi_dml_global_unique_one_index_base + @Test + public void deleteTestWithForceGSI() throws Exception { + if (!baseOneTableName.endsWith("gsi_dml_global_unique_one_index_base")) { + return; + } + String sql = (HINT_STRESS_FLAG.equalsIgnoreCase(hint) ? hint + "insert " : "insert " + hint) + " into " + + baseOneTableName + + " (pk,integer_test,bigint_test,varchar_test,datetime_test,year_test,char_test)" + + " values (?,?,?,?,?,?,?)"; + List param = new ArrayList(); + param.add(100); + param.add(null); + param.add(null); + param.add("test100"); + param.add(columnDataGenerator.datetime_testValue); + param.add(2000); + param.add(columnDataGenerator.char_testValue); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, sql, param); + + String tddlSql = hint + "delete from " + baseOneTableName + " force index(" + baseOneTableName + + ".gsi_dml_global_unique_one_index_index1) where integer_test=null"; + String mysqlSql = hint + "delete from " + baseOneTableName + " where integer_test=null"; + param = new ArrayList<>(); + executeOnMysqlAndTddl(mysqlConnection, tddlConnection, mysqlSql, tddlSql, param, true); + + sql = hint + "select * from " + baseOneTableName; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + assertIndexSame(baseOneTableName); + + assertRouteCorrectness(baseOneTableName); + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/InsertGsiWithFuncTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/InsertGsiWithFuncTest.java index 9b574ed1e..27dde3876 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/InsertGsiWithFuncTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/InsertGsiWithFuncTest.java @@ -82,6 +82,13 @@ public static void afterDropTables() { UNSUPPORTED_FUNCTION.add("SESSION_USER"); UNSUPPORTED_FUNCTION.add("SYSTEM_USER"); UNSUPPORTED_FUNCTION.add("TSO_TIMESTAMP"); + + // locking functions + UNSUPPORTED_FUNCTION.add("GET_LOCK"); + UNSUPPORTED_FUNCTION.add("IS_FREE_LOCK"); + UNSUPPORTED_FUNCTION.add("IS_USED_LOCK"); + UNSUPPORTED_FUNCTION.add("RELEASE_ALL_LOCKS"); + UNSUPPORTED_FUNCTION.add("RELEASE_LOCK"); } @Parameterized.Parameters(name = "{index}:hint={0} table1={1} table2={2}") diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/SelectGsiTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/SelectGsiTest.java index e46974ca9..623bc749b 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/SelectGsiTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dml/sharding/gsi/SelectGsiTest.java @@ -304,8 +304,6 @@ public void indexSelectionWithHint12() { explainAllResultMatchAssert("EXPLAIN " + sql, null, tddlConnection, "[\\s\\S]*" + "IndexScan\\(" + "[\\s\\S]*"); - explainAllResultNotMatchAssert("EXPLAIN " + sql, null, tddlConnection, - "[\\s\\S]*" + "FORCE INDEX\\(" + "[\\s\\S]*"); explainAllResultMatchAssert("EXPLAIN " + sql, null, tddlConnection, "[\\s\\S]*" + "index1" + "[\\s\\S]*"); JdbcUtil.executeQuerySuccess(tddlConnection, sql); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/agg/PartialAggTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/agg/PartialAggTest.java index 832c8c39c..4bc2a1915 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/agg/PartialAggTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/agg/PartialAggTest.java @@ -25,7 +25,7 @@ public void prepare() { public void testPartialAgg(boolean enableLocalBuffer) { String sql = - "/*+TDDL:cmd_extra(PARTIAL_AGG_ONLY=true MPP_TASK_LOCAL_BUFFER_ENABLED = %s enable_master_mpp=false PARALLELISM=5 workload_type=ap enable_push_sort=false enable_push_agg=false enable_cbo_push_agg=false)*/ " + "/*+TDDL:cmd_extra(PREFER_PARTIAL_AGG=true MPP_TASK_LOCAL_BUFFER_ENABLED = %s enable_master_mpp=false PARALLELISM=5 workload_type=ap enable_push_sort=false enable_push_agg=false enable_cbo_push_agg=false)*/ " + " select count(*), c1 from %s group by c1"; JdbcUtil.executeSuccess(tddlConnection, "use " + DATABASE_1); checkPlanUsePartialAgg(String.format(sql, enableLocalBuffer, TABLE_NAME)); @@ -33,13 +33,13 @@ public void testPartialAgg(boolean enableLocalBuffer) { } @Test - @Ignore("wait for PARTIAL_AGG_ONLY work under row mode") + @Ignore("wait for PREFER_PARTIAL_AGG work under row mode") public void testDisableLocalBuffer() { testPartialAgg(false); } @Test - @Ignore("wait for PARTIAL_AGG_ONLY work under row mode") + @Ignore("wait for PREFER_PARTIAL_AGG work under row mode") public void testEnableLocalBuffer() { testPartialAgg(true); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/charset/CharsetTestBase.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/charset/CharsetTestBase.java index 94e31c9f9..10384f0cd 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/charset/CharsetTestBase.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/charset/CharsetTestBase.java @@ -1,11 +1,9 @@ package com.alibaba.polardbx.qatest.dql.auto.charset; -import com.alibaba.polardbx.common.utils.Assert; import com.alibaba.polardbx.qatest.AutoReadBaseTestCase; import com.alibaba.polardbx.qatest.columnar.dql.ColumnarUtils; import com.alibaba.polardbx.qatest.util.JdbcUtil; import com.alibaba.polardbx.qatest.util.PropertiesUtil; -import org.apache.commons.lang.StringUtils; import org.junit.After; import org.junit.Before; @@ -112,6 +110,8 @@ public class CharsetTestBase extends AutoReadBaseTestCase { protected static final String INSERT_SQL_FORMAT = "insert into %s (%s) values (?)"; + protected static final String INSERT_TWO_COL_SQL_FORMAT = "insert into %s (%s, %s) values (?, ?)"; + protected static final String ORDER_BY_SQL_FORMAT = "/*+TDDL:ENABLE_PUSH_SORT=false*/select hex(%s) from %s order by %s, hex(%s)"; @@ -158,6 +158,15 @@ protected void insertStrings(List bytesList, String col) { executeBatchOnMysqlAndTddl(mysqlConnection, tddlConnection, insertSql, params); } + protected void insertStrings(List bytesList, String col, String col2) { + final String insertSql = String.format(INSERT_TWO_COL_SQL_FORMAT, table, col, col2); + List params = bytesList.stream() + .map(bs -> new String(bs)) + .map(s -> Arrays.asList(s, s)) + .collect(Collectors.toList()); + executeBatchOnMysqlAndTddl(mysqlConnection, tddlConnection, insertSql, params); + } + protected void testOrderBy(List bytesList, String col) { insertStrings(bytesList, col); createColumnarIndexIfNeed(table, col); @@ -189,8 +198,9 @@ protected void testJoin(List bytesList, String col, String col2) { if (isMySQL80()) { return; // this test only for mysql57 } - insertStrings(bytesList, col); - insertStrings(bytesList, col2); + JdbcUtil.executeSuccess(mysqlConnection, String.format("truncate table %s", table)); + JdbcUtil.executeSuccess(tddlConnection, String.format("truncate table %s", table)); + insertStrings(bytesList, col, col2); createColumnarIndexIfNeed(table, col); String selectSql = String.format(JOIN_SQL_FORMAT, col, col2, table, table, col, col2); selectContentSameAssert(selectSql, null, mysqlConnection, tddlConnection); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/function/SelectJsonAggFunctionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/function/SelectJsonAggFunctionTest.java new file mode 100644 index 000000000..aecad3386 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/function/SelectJsonAggFunctionTest.java @@ -0,0 +1,237 @@ +package com.alibaba.polardbx.qatest.dql.auto.function; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.polardbx.qatest.AutoReadBaseTestCase; +import com.alibaba.polardbx.qatest.data.ExecuteTableSelect; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runners.Parameterized; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class SelectJsonAggFunctionTest extends AutoReadBaseTestCase { + + @Parameterized.Parameters(name = "{index}:table={0}") + public static List prepare() { + return Arrays.asList(ExecuteTableSelect.selectBaseOneTableBradcastAndMutilDbMutilTb()); + } + + public SelectJsonAggFunctionTest(String tableName) { + this.baseOneTableName = tableName; + } + + @Test + public void jsonObjectAggTest() throws Exception { + checkJsonObjectAggQuery("", "varchar_test", "integer_test", "char_test", baseOneTableName); + executeJsonObjectAggQuery("", "varchar_test", "double_test", "char_test", baseOneTableName, tddlConnection); + executeJsonObjectAggQuery("", "varchar_test", "float_test", "char_test", baseOneTableName, tddlConnection); + executeJsonObjectAggQuery("", "varchar_test", "double_test", "char_test", baseOneTableName, tddlConnection); + executeJsonObjectAggQuery("", "varchar_test", "decimal_test", "char_test", baseOneTableName, tddlConnection); + executeJsonObjectAggQuery("", "varchar_test", "date_test", "char_test", baseOneTableName, tddlConnection); + executeJsonObjectAggQuery("", "varchar_test", "time_test", "char_test", baseOneTableName, tddlConnection); + executeJsonObjectAggQuery("", "varchar_test", "datetime_test", "char_test", baseOneTableName, tddlConnection); + executeJsonObjectAggQuery("", "varchar_test", "datetime_test", "char_test", baseOneTableName, tddlConnection); + + //检验空表 + String tableName = "jsonObjectAggTest_tb"; + String createTable = "create table " + tableName + + "(id int primary key, name varchar(255), val int) partition by hash(id) partitions 3"; + JdbcUtil.dropTable(tddlConnection, tableName); + JdbcUtil.executeSuccess(tddlConnection, createTable); + ResultSet rs1 = + JdbcUtil.executeQuerySuccess(tddlConnection, "select json_objectagg(name, val) from " + tableName); + Assert.assertTrue(rs1.next()); + Assert.assertNull(rs1.getObject(1)); + + //检验空分区 + int id = 1; + String name = "name1"; + int val = 2; + String insertTable = String.format("insert into " + tableName + " values (%s,'%s',%s)", id, name, val); + JdbcUtil.executeSuccess(tddlConnection, insertTable); + String json = JdbcUtil.executeQueryAndGetFirstStringResult("select json_objectagg(name, val) from " + tableName, + tddlConnection); + JSONObject jsonObject = JSON.parseObject(json); + Assert.assertEquals(1, jsonObject.size()); + Assert.assertEquals(jsonObject.getIntValue(name), val); + + JdbcUtil.dropTable(tddlConnection, tableName); + } + + @Test + public void jsonArrayAggTest() throws Exception { + checkJsonArrayAggQuery("", "integer_test", "char_test", baseOneTableName); + checkJsonArrayAggQuery("", "varchar_test", "char_test", baseOneTableName); + executeJsonArrayAggQuery("", "double_test", "char_test", baseOneTableName, tddlConnection); + executeJsonArrayAggQuery("", "float_test", "char_test", baseOneTableName, tddlConnection); + executeJsonArrayAggQuery("", "double_test", "char_test", baseOneTableName, tddlConnection); + executeJsonArrayAggQuery("", "decimal_test", "char_test", baseOneTableName, tddlConnection); + executeJsonArrayAggQuery("", "date_test", "char_test", baseOneTableName, tddlConnection); + executeJsonArrayAggQuery("", "time_test", "char_test", baseOneTableName, tddlConnection); + executeJsonArrayAggQuery("", "datetime_test", "char_test", baseOneTableName, tddlConnection); + executeJsonArrayAggQuery("", "datetime_test", "char_test", baseOneTableName, tddlConnection); + + //检验空表 + String tableName = "jsonArrayAggTest_tb"; + String createTable = "create table " + tableName + + "(id int primary key, name varchar(255), val int) partition by hash(id) partitions 3"; + JdbcUtil.dropTable(tddlConnection, tableName); + JdbcUtil.executeSuccess(tddlConnection, createTable); + ResultSet rs1 = JdbcUtil.executeQuerySuccess(tddlConnection, "select json_arrayagg(val) from " + tableName); + Assert.assertTrue(rs1.next()); + Assert.assertNull(rs1.getObject(1)); + + //检验空分区 + int id = 1; + String name = "name1"; + int val = 2; + String insertTable = String.format("insert into " + tableName + " values (%s,'%s',%s)", id, name, val); + JdbcUtil.executeSuccess(tddlConnection, insertTable); + String json = + JdbcUtil.executeQueryAndGetFirstStringResult("select json_arrayagg(val) from " + tableName, tddlConnection); + JSONArray jsonArray = JSON.parseArray(json); + Assert.assertEquals(1, jsonArray.size()); + Assert.assertEquals(jsonArray.getIntValue(0), val); + + JdbcUtil.dropTable(tddlConnection, tableName); + + } + + @Test + public void unpushAggTest() throws Exception { + String hint = "/*+TDDL:enable_cbo_push_agg=false enable_push_agg=false executor_mode=ap_local*/"; + checkJsonObjectAggQuery(hint, "varchar_test", "integer_test", "char_test", baseOneTableName); + checkJsonArrayAggQuery(hint, "integer_test", "char_test", baseOneTableName); + checkJsonArrayAggQuery(hint, "varchar_test", "char_test", baseOneTableName); + } + + /** + * 需要注意values column的类型,由于jdbc类型转换的原因,Set#contains判断不一定准确 + */ + private void checkJsonObjectAggQuery(String hint, String keyColumn, String valueColumn, String groupColumn, + String tableName) + throws Exception { + + String sql1 = String.format("select %s,%s,%s from %s where %s is not null", + groupColumn, keyColumn, valueColumn, tableName, keyColumn, groupColumn); + ResultSet rs1 = JdbcUtil.executeQuery(sql1, tddlConnection); + List> res1 = getAllResult(rs1); + Map>> allValues = new HashMap<>(); + for (List values : res1) { + Object group = values.get(0); + String k = (String) values.get(1); + Object v = values.get(2); + allValues.putIfAbsent(group, new HashMap<>()); + allValues.get(group).putIfAbsent(k, new HashSet<>()); + allValues.get(group).get(k).add(v); + } + + List> res2 = + executeJsonObjectAggQuery(hint, keyColumn, valueColumn, groupColumn, tableName, tddlConnection); + for (List values : res2) { + Object group = values.get(0); + JSONObject json = JSON.parseObject((String) values.get(1)); + for (Map.Entry entry : json.entrySet()) { + Assert.assertNotNull(allValues.get(group)); + Assert.assertNotNull(allValues.get(group).get(entry.getKey())); + Assert.assertTrue(allValues.get(group).get(entry.getKey()).contains(entry.getValue())); + } + } + } + + private List> executeJsonObjectAggQuery(String hint, String keyColumn, String valueColumn, + String groupColumn, + String tableName, Connection connection) throws Exception { + String sql2 = String.format(hint + "select %s,json_objectagg(%s,%s) from %s where %s is not null group by %s", + groupColumn, keyColumn, valueColumn, tableName, keyColumn, groupColumn); + ResultSet rs2 = JdbcUtil.executeQuery(sql2, connection); + List> res2 = getAllResult(rs2); + return res2; + } + + /** + * 需要注意values column的类型,由于jdbc类型转换的原因,Set#contains判断不一定准确 + */ + private void checkJsonArrayAggQuery(String hint, String valueColumn, String groupColumn, String tableName) + throws Exception { + String sql1 = String.format("select %s,%s from %s ", + groupColumn, valueColumn, tableName); + ResultSet rs1 = JdbcUtil.executeQuery(sql1, tddlConnection); + List> res1 = getAllResult(rs1); + Map> allValues = new HashMap<>(); + for (List values : res1) { + Object group = values.get(0); + Object v = values.get(1); + allValues.putIfAbsent(group, new ArrayList<>()); + allValues.get(group).add(v); + } + + List> res2 = executeJsonArrayAggQuery(hint, valueColumn, groupColumn, tableName, tddlConnection); + for (List values : res2) { + Object group = values.get(0); + JSONArray json = JSON.parseArray((String) values.get(1)); + Object[] arr1 = json.toArray(); + Object[] arr2 = allValues.get(group).toArray(); + Arrays.sort(arr1, new NullableComparator()); + Arrays.sort(arr2, new NullableComparator()); + Assert.assertTrue(Arrays.deepEquals(arr1, arr2)); + } + } + + private List> executeJsonArrayAggQuery(String hint, String valueColumn, String groupColumn, + String tableName, + Connection connection) throws Exception { + String sql2 = String.format(hint + "select %s,json_arrayagg(%s) from %s group by %s", + groupColumn, valueColumn, tableName, groupColumn); + ResultSet rs2 = JdbcUtil.executeQuery(sql2, connection); + List> res2 = getAllResult(rs2); + return res2; + } + + public List> getAllResult(ResultSet rs) throws Exception { + List> allResults = new ArrayList>(); + ResultSetMetaData metaData = rs.getMetaData(); + int columnCount = metaData.getColumnCount(); + + while (rs.next()) { + List oneResult = new ArrayList(); + for (int i = 1; i < columnCount + 1; i++) { + oneResult.add(rs.getObject(i)); + } + allResults.add(oneResult); + } + return allResults; + } + + public static class NullableComparator implements Comparator { + @Override + public int compare(Object a, Object b) { + if (a == null && b == null) { + return 0; // 两个元素都是null,视为相等 + } + if (a == null) { + return -1; // a为null,应该排在前面 + } + if (b == null) { + return 1; // b为null,那么a应该排在后面 + } + return ((Comparable) a).compareTo(b); // 两者都非null,使用它们自然的顺序 + } + } + +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/function/SelectRowFunctionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/function/SelectRowFunctionTest.java index d0695dddf..3336fae92 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/function/SelectRowFunctionTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/function/SelectRowFunctionTest.java @@ -4,6 +4,7 @@ import com.alibaba.polardbx.qatest.util.JdbcUtil; import com.google.common.collect.Lists; import org.junit.Assert; +import com.google.common.collect.Lists; import org.junit.Test; import java.util.ArrayList; @@ -24,11 +25,9 @@ public class SelectRowFunctionTest extends AutoReadBaseTestCase { private String lessThanSql = "select %s <= %s"; private String greatSql = "select %s > %s"; private String greaterThanSql = "select %s >= %s"; - private String inSql = "select %s in (%s)"; - private String notInSql = "select %s not in (%s)"; private List templates = Lists.newArrayList( - equalSql, nullSafeEqualSql, lessSql, lessThanSql, greatSql, greaterThanSql, inSql, notInSql); + equalSql, nullSafeEqualSql, lessSql, lessThanSql, greatSql, greaterThanSql); @Test public void testSameRowLength() { @@ -42,57 +41,6 @@ public void testSameRowLength() { } } - @Test - public void testInNull() { - selectContentSameAssert("select (1,2,3,4) in ((null,2,3,4), (1,3,4,2))", new ArrayList<>(), mysqlConnection, - tddlConnection); - selectContentSameAssert("select (1,2,null,4) in ((1,2,null,4), (1,3,4,2))", new ArrayList<>(), mysqlConnection, - tddlConnection); - selectContentSameAssert("select (1,2,null,4) in ((1,2,3,4), (1,3,4,2))", new ArrayList<>(), mysqlConnection, - tddlConnection); - selectContentSameAssert("select (1,2,null,4) in ((1,null,3,4), (1,3,4,2))", new ArrayList<>(), mysqlConnection, - tddlConnection); - selectContentSameAssert("select (1,2,3,4) in ((1, null,3,null), (1,3,4,2))", new ArrayList<>(), mysqlConnection, - tddlConnection); - selectContentSameAssert("select (1,2,3,4) in ((1, null,3,null), (1,3,4,2), (1,2,3,4))", new ArrayList<>(), - mysqlConnection, tddlConnection); - selectContentSameAssert("select 1 in (2,null,3)", new ArrayList<>(), mysqlConnection, tddlConnection); - selectContentSameAssert("select (1,2,3,4) in ((null,2,3,4), (1,3,4,2))", new ArrayList<>(), mysqlConnection, - tddlConnection); - selectContentSameAssert("select null in (1,null,3)", new ArrayList<>(), mysqlConnection, tddlConnection); - } - - @Test - public void testInExprForEachType() { - selectContentSameAssert("select ('abc', 'def') in ((N'abc', N'def'))", new ArrayList<>(), mysqlConnection, - tddlConnection); - selectContentSameAssert("select ('abc', 'de') in ((N'abc', N'def'))", new ArrayList<>(), mysqlConnection, - tddlConnection); - - selectContentSameAssert("select (2, 1) in ((b'10', b'01'))", new ArrayList<>(), mysqlConnection, - tddlConnection); - selectContentSameAssert("select (1, 1) in ((b'10', b'01'))", new ArrayList<>(), mysqlConnection, - tddlConnection); - - selectContentSameAssert("select (true, false) in ((true, false))", new ArrayList<>(), mysqlConnection, - tddlConnection); - selectContentSameAssert("select (true, true) in ((true, false))", new ArrayList<>(), mysqlConnection, - tddlConnection); - - selectContentSameAssert("select (true, false) in ((true, false))", new ArrayList<>(), mysqlConnection, - tddlConnection); - selectContentSameAssert("select (true, true) in ((true, false))", new ArrayList<>(), mysqlConnection, - tddlConnection); - - // FIXME: wrong result for hex expression, this may fail: - // selectContentSameAssert("select b'0001001000110100' in (0x1234)", new ArrayList<>(), mysqlConnection, tddlConnection); - // selectContentSameAssert("select (0x1234, 0xabcc) in ((0x1234, 0xabcd))", new ArrayList<>(), mysqlConnection, tddlConnection); - selectContentSameAssert("select (0x1234, 0xabcd) in ((0x1234, 0xabcd))", new ArrayList<>(), mysqlConnection, - tddlConnection); - selectContentSameAssert("select (0x1233, 0xabcc) in ((0x1234, 0xabcd))", new ArrayList<>(), mysqlConnection, - tddlConnection); - } - @Test public void testDifferentRowLength() { String left = generateRandomStr(2); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/hint/HintTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/hint/HintTest.java index ef39b052f..b153f60a3 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/hint/HintTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/hint/HintTest.java @@ -70,33 +70,4 @@ public void testSampleHint() throws SQLException { String result = rs.getString("STATEMENT"); assert result.contains("+sample_percentage("); } - - @Test - public void testHintFlagInsideTran() throws SQLException { - String hint = "/*TDDL:a()*/ "; - String sql = "select * from " + baseOneTableName; - tddlConnection.createStatement().execute("clear plancache"); - try { - tddlConnection.createStatement().execute("begin"); - - // execute first and put it into plancache - tddlConnection.createStatement().execute(sql); - - // get explain, a cached plan should be returned - String result = getExplainResult(tddlConnection, sql); - Assert.assertTrue(result.contains("HitCache:true")); - - // get explain by hint, a new plan should be returned - result = getExplainResult(tddlConnection, hint + sql); - Assert.assertTrue(result.contains("HitCache:false")); - - // go back to no hint sql, a cached plan should be returned - result = getExplainResult(tddlConnection, sql); - Assert.assertTrue(result.contains("HitCache:true")); - } finally { - // clear trans - tddlConnection.createStatement().execute("rollback"); - } - - } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/infoschema/ColumnarSnapshotsTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/infoschema/ColumnarSnapshotsTest.java new file mode 100644 index 000000000..8ed5051c6 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/infoschema/ColumnarSnapshotsTest.java @@ -0,0 +1,242 @@ +package com.alibaba.polardbx.qatest.dql.auto.infoschema; + +import com.alibaba.polardbx.qatest.AutoReadBaseTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class ColumnarSnapshotsTest extends AutoReadBaseTestCase { + @Test + public void testColumnarSnapshot() throws SQLException, InterruptedException { + ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now())"); + Assert.assertTrue(rs.next()); + long tso0 = rs.getLong(1); + System.out.println(tso0); + Thread.sleep(1000); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now())"); + Assert.assertTrue(rs.next()); + long tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + + try { + JdbcUtil.executeUpdateSuccess(tddlConnection, "set time_zone = '+2:00'"); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now())"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + Thread.sleep(1000); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now())"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + + JdbcUtil.executeUpdateSuccess(tddlConnection, "set time_zone = '+2:00'"); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now())"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + Thread.sleep(1000); + JdbcUtil.executeUpdateSuccess(tddlConnection, "set time_zone = '+10:00'"); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now())"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + + JdbcUtil.executeUpdateSuccess(tddlConnection, "set time_zone = '+2:00'"); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now())"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + Thread.sleep(1000); + JdbcUtil.executeUpdateSuccess(tddlConnection, "set time_zone = '-10:00'"); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now())"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + + JdbcUtil.executeUpdateSuccess(tddlConnection, "set time_zone = '+2:00'"); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 14:00:00')"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 15:00:00')"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + + JdbcUtil.executeUpdateSuccess(tddlConnection, "set time_zone = '+2:00'"); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 14:00:00')"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + JdbcUtil.executeUpdateSuccess(tddlConnection, "set time_zone = '+10:00'"); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 15:00:00')"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 > tso1); + + JdbcUtil.executeUpdateSuccess(tddlConnection, "set time_zone = '+2:00'"); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 14:00:00')"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + JdbcUtil.executeUpdateSuccess(tddlConnection, "set time_zone = '-10:00'"); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 15:00:00')"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + + } finally { + JdbcUtil.executeUpdateSuccess(tddlConnection, "set time_zone = 'SYSTEM'"); + } + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now(), '+2:00')"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + Thread.sleep(1000); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now(), '+2:00')"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now(), '+2:00')"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + Thread.sleep(1000); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now(), '+10:00')"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 > tso1); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now(), '+2:00')"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + Thread.sleep(1000); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now(), '-10:00')"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 14:00:00', '+2:00')"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 15:00:00', '+2:00')"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 14:00:00', '+2:00')"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 15:00:00', '+10:00')"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 > tso1); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 14:00:00', '+2:00')"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 15:00:00', '-10:00')"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 14:00:00', 'SYSTEM')"); + Assert.assertTrue(rs.next()); + tso0 = rs.getLong(1); + System.out.println(tso0); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO('2024-01-01 15:00:00', 'SYSTEM')"); + Assert.assertTrue(rs.next()); + tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + } + + @Test + public void testInformationSchemaColumnarSnapshots() throws SQLException, InterruptedException { + ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now())"); + Assert.assertTrue(rs.next()); + long tso0 = rs.getLong(1); + System.out.println(tso0); + Thread.sleep(1000); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, "SELECT TIME_TO_TSO(now())"); + Assert.assertTrue(rs.next()); + long tso1 = rs.getLong(1); + System.out.println(tso1); + Assert.assertTrue(tso0 < tso1); + + final String schema = "testInformationSchemaColumnarSnapshots_schema"; + final String table = "testInformationSchemaColumnarSnapshots_table"; + final String index = "testInformationSchemaColumnarSnapshots_index"; + + try (Connection connection = getMetaConnection()) { + try { + String sql = "delete from columnar_table_mapping where table_schema = '" + schema + "'"; + JdbcUtil.executeUpdateSuccess(connection, sql); + sql = "delete from columnar_checkpoints where checkpoint_type = 'mock'"; + JdbcUtil.executeUpdateSuccess(connection, sql); + + sql = + "insert into columnar_table_mapping (table_schema, table_name, index_name, latest_version_id, status, type) " + + "values ('" + schema + "', '" + table + "', '" + index + "', 0, 'PUBLIC', 'snapshot')"; + JdbcUtil.executeUpdateSuccess(connection, sql); + rs = JdbcUtil.executeQuerySuccess(connection, "select table_id from columnar_table_mapping " + + "where table_schema = '" + schema + "' and table_name = '" + table + + "' and index_name = '" + index + "'"); + Assert.assertTrue(rs.next()); + long tableId = rs.getLong(1); + // index level + sql = + "insert into columnar_checkpoints (logical_schema, logical_table, checkpoint_tso, binlog_tso, info, offset, checkpoint_type) values " + + "('" + schema + "', '" + tableId + "', '" + tso0 + "', '" + tso0 + "', 'force', '{}', 'mock')"; + JdbcUtil.executeUpdateSuccess(connection, sql); + // global level + sql = "insert into columnar_checkpoints (logical_schema, checkpoint_tso, binlog_tso, info, offset, checkpoint_type) values " + + "('polardbx', '" + tso1 + "', '" + tso1 + "', 'force', '{}', 'mock')"; + JdbcUtil.executeUpdateSuccess(connection, sql); + + sql = "select * from information_schema.columnar_snapshots where schema_name = '" + schema + "'"; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + Assert.assertTrue(rs.next()); + Assert.assertTrue(schema.equalsIgnoreCase(rs.getString("SCHEMA_NAME"))); + Assert.assertTrue(table.equalsIgnoreCase(rs.getString("TABLE_NAME"))); + Assert.assertTrue(index.equalsIgnoreCase(rs.getString("INDEX_NAME"))); + Assert.assertEquals(tso0, rs.getLong("TSO")); + + sql = "select * from information_schema.columnar_snapshots where schema_name = 'polardbx' and tso = " + tso1; + rs = JdbcUtil.executeQuerySuccess(tddlConnection, sql); + Assert.assertTrue(rs.next()); + Assert.assertTrue("polardbx".equalsIgnoreCase(rs.getString("SCHEMA_NAME"))); + Assert.assertEquals(tso1, rs.getLong("TSO")); + } finally { + String sql = "delete from columnar_table_mapping where table_schema = '" + schema + "'"; + JdbcUtil.executeIgnoreErrors(connection, sql); + sql = "delete from columnar_checkpoints where checkpoint_type = 'mock'"; + JdbcUtil.executeIgnoreErrors(connection, sql); + } + } + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/join/BushyJoinTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/join/BushyJoinTest.java index 33e858630..43a6e16bc 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/join/BushyJoinTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/join/BushyJoinTest.java @@ -17,6 +17,8 @@ package com.alibaba.polardbx.qatest.dql.auto.join; import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.qatest.ColumnarIgnore; +import com.alibaba.polardbx.qatest.data.ExecuteTableSelect; import com.alibaba.polardbx.qatest.AutoReadBaseTestCase; import com.alibaba.polardbx.qatest.data.ExecuteTableSelect; import org.apache.commons.lang3.StringUtils; @@ -39,7 +41,7 @@ * @since 5.3.5 */ - +@ColumnarIgnore // close #58321033 public class BushyJoinTest extends AutoReadBaseTestCase { private static final Log log = LogFactory.getLog(BushyJoinTest.class); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/join/JoinWithDynamicValueTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/join/JoinWithDynamicValueTest.java index 6172e8f20..cabc1236f 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/join/JoinWithDynamicValueTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/join/JoinWithDynamicValueTest.java @@ -18,7 +18,8 @@ public class JoinWithDynamicValueTest extends BaseTestCase { private static final String TABLE_NAME = "test_dynamic_value"; - private static final String SQL = "/*+TDDL: cmd_extra()*/ select * from %s where c1 in (%s) and c2 = 5;"; + private static final String SQL = + "/*+TDDL: cmd_extra(IN_SUB_QUERY_THRESHOLD=5)*/ select * from %s where c1 in (%s) and c2 = 5;"; @Before public void init() throws SQLException { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/FlashbackQueryTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/FlashbackQueryTest.java index 5d168d0df..b8fb33c21 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/FlashbackQueryTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/FlashbackQueryTest.java @@ -98,36 +98,32 @@ public void testPartition() throws SQLException { "/*+TDDL:plancache=false enable_mpp=false*/ select * from FlashbackQueryTest as of timestamp '" + currentTime + "' as tt partition(p1)" ); + final List explainResult = ImmutableList.of( - "Gather(concurrent=true)\n" - + " LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF TIMESTAMP ? AS `FlashbackQueryTest`\")\n" + "LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF TIMESTAMP ? AS `FlashbackQueryTest`\")\n" + "HitCache:false\n" + "Source:null\n" + "TemplateId: NULL\n", - "Gather(concurrent=true)\n" - + " LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF TIMESTAMP ? AS `FlashbackQueryTest`\")\n" + "LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF TIMESTAMP ? AS `FlashbackQueryTest`\")\n" + "HitCache:false\n" + "Source:null\n" + "TemplateId: NULL\n", - "Gather(concurrent=true)\n" - + " LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF TIMESTAMP ? AS `FlashbackQueryTest`\")\n" + "LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF TIMESTAMP ? AS `FlashbackQueryTest`\")\n" + "HitCache:false\n" + "Source:null\n" + "TemplateId: NULL\n" ); + final List explainResult80 = ImmutableList.of( - "Gather(concurrent=true)\n" - + " LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF GCN ? AS `FlashbackQueryTest`\")\n" + "LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF GCN ? AS `FlashbackQueryTest`\")\n" + "HitCache:false\n" + "Source:null\n" + "TemplateId: NULL\n", - "Gather(concurrent=true)\n" - + " LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF GCN ? AS `FlashbackQueryTest`\")\n" + "LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF GCN ? AS `FlashbackQueryTest`\")\n" + "HitCache:false\n" + "Source:null\n" + "TemplateId: NULL\n", - "Gather(concurrent=true)\n" - + " LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF GCN ? AS `FlashbackQueryTest`\")\n" + "LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF GCN ? AS `FlashbackQueryTest`\")\n" + "HitCache:false\n" + "Source:null\n" + "TemplateId: NULL\n" @@ -182,7 +178,7 @@ public void test57Tso() { String sql = "/*+TDDL:plancache=false enable_mpp=false*/ select * from FlashbackQueryTest tt partition(p1) as of tso 10000"; String expect = - "Gather(concurrent=true) LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF TSO ? AS `FlashbackQueryTest`\")HitCache:falseSource:nullTemplateId: NULL"; + "LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF TSO ? AS `FlashbackQueryTest`\")HitCache:falseSource:nullTemplateId: NULL"; String explain = JdbcUtil.getExplainResult(tddlConnection, sql); Assert.assertEquals(expect, explain); } @@ -195,7 +191,7 @@ public void test80Tso() { String sql = "/*+TDDL:plancache=false enable_mpp=false*/ select * from FlashbackQueryTest tt partition(p1) as of tso 10000"; String expect = - "Gather(concurrent=true) LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF GCN ? AS `FlashbackQueryTest`\")HitCache:falseSource:nullTemplateId: NULL"; + "LogicalView(tables=\"FlashbackQueryTest[p1]\", sql=\"SELECT `a`, `b`, `c`, `d` FROM `FlashbackQueryTest` AS OF GCN ? AS `FlashbackQueryTest`\")HitCache:falseSource:nullTemplateId: NULL"; String explain = JdbcUtil.getExplainResult(tddlConnection, sql); Assert.assertEquals(expect, explain); } @@ -206,7 +202,21 @@ public void testTraceFunction() throws Exception { String createTable = MessageFormat.format(tableFormat, partition); JdbcUtil.dropTable(tddlConnection, tableName); - JdbcUtil.executeSuccess(tddlConnection, createTable); + + //创建单表可能会报table group: 65 not exist错误,重试几次 + int retry = 0; + while (retry++ < 5) { + try { + JdbcUtil.executeSuccess(tddlConnection, createTable); + break; + } catch (Exception e) { + Thread.sleep(2000); + } + } + + if (retry > 5) { + Assert.fail("create table failed:" + createTable); + } //等待5s,避免时间转tso:(UNIX_TIMESTAMP(now()) << 22) * 1000,报错:The definition of the table required by the flashback query has changed Thread.sleep(5000); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/SelectSubQueryTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/SelectSubQueryTest.java index e1c5c76a1..37f311710 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/SelectSubQueryTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/SelectSubQueryTest.java @@ -103,11 +103,6 @@ public void comparisonTest() { sql = "select * from " + baseOneTableName + " where integer_test >=(select pk from " + baseTwoTableName + " where varchar_test='" + columnDataGenerator.varchar_testValue + "' order by pk limit 1)"; selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); - - if (shardingAdvise.compareAndSet(false, true)) { - sql = "/*+TDDL:cmd_extra(SHARDING_ADVISOR_BROADCAST_THRESHOLD=100)*/shardingadvise"; - DataValidator.sqlMayErrorAssert(sql, tddlConnection, "ERR_TABLE_NOT_EXIST"); - } } /** diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/ViewTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/ViewTest.java index e27d8c610..cf3d45593 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/ViewTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/select/ViewTest.java @@ -62,7 +62,6 @@ public void testViewAlter() throws Exception { sb.append(rs.getString(1)); } assert sb.toString().contains("Source:PLAN_CACHE"); - assert sb.toString().contains("HitCache:true"); c.createStatement().execute("alter view view_test1 as select 1 from " + TB_NAME + " limit 1"); rs = c.createStatement().executeQuery("explain " + sql); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/spill/HybridBushyJoinTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/spill/HybridBushyJoinTest.java index 8d8cd9447..5b7290152 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/spill/HybridBushyJoinTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/spill/HybridBushyJoinTest.java @@ -16,6 +16,8 @@ package com.alibaba.polardbx.qatest.dql.auto.spill; +import com.alibaba.polardbx.qatest.ColumnarIgnore; +import com.alibaba.polardbx.qatest.data.ExecuteTableSelect; import com.alibaba.polardbx.qatest.AutoReadBaseTestCase; import com.alibaba.polardbx.qatest.data.ExecuteTableSelect; import org.apache.commons.logging.Log; @@ -31,7 +33,7 @@ import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentSameAssert; - +@ColumnarIgnore // close #58321033 public class HybridBushyJoinTest extends AutoReadBaseTestCase { private static final Log log = LogFactory.getLog(HybridBushyJoinTest.class); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/spm/PlanManagerUtilTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/spm/PlanManagerUtilTest.java deleted file mode 100644 index aa2977789..000000000 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/spm/PlanManagerUtilTest.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.alibaba.polardbx.qatest.dql.auto.spm; - -import com.alibaba.polardbx.common.utils.Pair; -import com.alibaba.polardbx.optimizer.parse.FastsqlParser; -import com.alibaba.polardbx.optimizer.planmanager.PlanManagerUtil; -import org.apache.calcite.sql.SqlNode; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashSet; -import java.util.Set; - -public class PlanManagerUtilTest { - - @Test - public void testGettingTableSetFromAst() { - String sql1 = "WITH tb AS (\n" - + " SELECT\n" - + " a.c1 x, b.c2 y\n" - + " FROM \n" - + " db1.t1 a\n" - + " JOIN db4.t2 b on a.name=b.name\n" - + ")\n" - + "\n" - + "SELECT \n" - + " (tb.x + 1),\n" - + " concat(tb.y, 'xx', a.name),\n" - + " (select max(salary) from db5.t3),\n" - + " b.salary\n" - + "FROM \n" - + " db2.t1 a \n" - + " JOIN db3.t2 b on a.id = b.id\n" - + " JOIN tb c on a.age = c.age\n" - + "WHERE\n" - + "\tb.val > (select avg(val) from db6.t1)\n" - + " AND NOT EXISTS ( SELECT 1 FROM t1 d WHERE d.id > 0);"; - SqlNode sqlNode1 = new FastsqlParser().parse(sql1).get(0); - Set> tableSet1 = PlanManagerUtil.getTableSetFromAst(sqlNode1); - Set> real1 = new HashSet<>(); - real1.add(Pair.of("db1", "t1")); - real1.add(Pair.of("db4", "t2")); - real1.add(Pair.of("db5", "t3")); - real1.add(Pair.of("db2", "t1")); - real1.add(Pair.of("db3", "t2")); - real1.add(Pair.of("db6", "t1")); - real1.add(Pair.of(null, "t1")); - Assert.assertTrue(tableSet1.size() == real1.size()); - for (Pair pair : tableSet1) { - if (!real1.contains(pair)) { - Assert.fail(); - } - } - - String sql2 = "Select * from b.t b join a.t a on a.id=b.id where a.id = 2"; - SqlNode sqlNode2 = new FastsqlParser().parse(sql2).get(0); - Set> tableSet2 = PlanManagerUtil.getTableSetFromAst(sqlNode2); - Set> real2 = new HashSet<>(); - real2.add(Pair.of("a", "t")); - real2.add(Pair.of("b", "t")); - Assert.assertTrue(tableSet2.size() == real2.size()); - for (Pair pair : tableSet2) { - if (!real2.contains(pair)) { - Assert.fail(); - } - } - - String sql3 = "select * from (select * from a.t1 a join b.t2 b on a.id = b.id)"; - SqlNode sqlNode3 = new FastsqlParser().parse(sql3).get(0); - Set> tableSet3 = PlanManagerUtil.getTableSetFromAst(sqlNode3); - Set> real3 = new HashSet<>(); - real3.add(Pair.of("a", "t1")); - real3.add(Pair.of("b", "t2")); - Assert.assertTrue(tableSet3.size() == real3.size()); - for (Pair pair : tableSet3) { - if (!real3.contains(pair)) { - Assert.fail(); - } - } - - } - -} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/spm/SpmTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/spm/SpmTest.java index 8a58b559e..bc8f2ea7d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/spm/SpmTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/auto/spm/SpmTest.java @@ -440,7 +440,7 @@ public void testSPMBaseLineSyncScheduledJob() throws Exception { /** * this test method should be the last one to be executed in this case */ - @Test + @Ignore("this case will drop database and affect other test cases") public void testDropDB() throws Exception { try (Connection c = getPolardbxConnection(DB_NAME)) { // drop database diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/JsonTypeTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/JsonTypeTest.java index 9a509ffb3..99b507ef5 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/JsonTypeTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/JsonTypeTest.java @@ -34,6 +34,7 @@ import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentIgnoreJsonFormatSameAssert; import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentSameAssert; +import static com.alibaba.polardbx.qatest.validator.DataValidator.selectErrorAssert; /** * @author wuheng.zxy 2016-4-17 上午10:45:30 @@ -324,6 +325,46 @@ public void testJsonContains() throws SQLException { String sql = "select JSON_CONTAINS('{\"a\": 1, \"b\": 2, \"c\": {\"d\": 4}}', '1', '$.a') from " + baseOneTableName; selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + //normal + sql = "select JSON_CONTAINS(CAST(1 AS JSON),CAST(2 AS JSON)),\n" + + " JSON_CONTAINS(CAST(1.2 AS JSON),CAST(2.1 AS JSON)),\n" + + " JSON_CONTAINS(CAST(FALSE AS JSON),CAST(TRUE AS JSON)),\n" + + " JSON_CONTAINS(CAST((2 - 1) AS JSON),CAST((1 + 2) AS JSON)),\n" + + " JSON_CONTAINS(CAST('null' AS JSON),CAST('null' AS JSON)),\n" + + " JSON_CONTAINS(CAST('{\\\"white\\\":2}' AS JSON), CAST('{\\\"black\\\":1}' AS JSON));"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + //quote + sql = "select JSON_CONTAINS(JSON_QUOTE('white'),JSON_QUOTE('black')),\n" + + " JSON_CONTAINS(JSON_QUOTE('white'),JSON_QUOTE('black')),\n" + + " JSON_CONTAINS(JSON_QUOTE('white'),JSON_QUOTE('black'));"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + //arrays + sql = "select JSON_CONTAINS(JSON_ARRAY(3,4),JSON_ARRAY(1,2)),\n" + + " JSON_CONTAINS(JSON_ARRAY(3,4), CAST('{\"3\": 4}' as JSON)),\n" + + " JSON_CONTAINS(JSON_ARRAY(3,4), JSON_ARRAY(3)),\n" + + " JSON_CONTAINS(JSON_ARRAY(3,4), JSON_ARRAY(3,4,5)),\n" + + " JSON_CONTAINS(JSON_ARRAY(3,FALSE,'white'),JSON_ARRAY(1,TRUE,'black')),\n" + + " JSON_CONTAINS(JSON_ARRAY(CAST('{\\\"white\\\":2}' AS JSON)), JSON_ARRAY(CAST('{\\\"black\\\":1}' AS JSON)));"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + //objects + sql = "select JSON_CONTAINS(JSON_OBJECT('second',2),JSON_OBJECT('first',1)),\n" + + " JSON_CONTAINS(JSON_OBJECT('second',2),JSON_OBJECT('second',1)),\n" + + " JSON_CONTAINS(JSON_OBJECT('second',2),JSON_OBJECT('second',2)),\n" + + " JSON_CONTAINS(CAST('{\"a\":1, \"b\": {\"c\": 3}}' as JSON), CAST('{\"c\":3}' as JSON)),\n" + + " JSON_CONTAINS(CAST('{\"a\":1, \"b\": {\"c\": 3}, \"c\": 3}' as JSON), CAST('{\"c\":3}' as JSON)),\n" + + " JSON_CONTAINS(JSON_OBJECT('second',CAST('{\\\"white\\\":2}' AS JSON)), JSON_OBJECT('first',CAST('{\\\"black\\\":1}' AS JSON)));"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + //funcions + sql = "select JSON_CONTAINS(json_quote(concat('foo','bar')),json_quote(concat('foo','bar'))),\n" + + " JSON_CONTAINS(CAST(2 AS JSON),CAST(1 AS JSON)),\n" + + " JSON_CONTAINS(JSON_QUOTE('bar'),JSON_QUOTE('foo')),\n" + + " JSON_CONTAINS(CAST('{\\\"white\\\":2}' AS JSON), CAST('{\\\"black\\\":1}' AS JSON));"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); } @Test @@ -333,6 +374,96 @@ public void testJsonContainsPath() throws SQLException { selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); } + @Test + public void testJsonOverlaps() throws SQLException { + if (isMySQL80()) { + //normal + String sql = "select JSON_OVERLAPS(CAST(1 AS JSON),CAST(2 AS JSON)),\n" + + " JSON_OVERLAPS(CAST(1.2 AS JSON),CAST(2.1 AS JSON)),\n" + + " JSON_OVERLAPS(CAST(FALSE AS JSON),CAST(TRUE AS JSON)),\n" + + " JSON_OVERLAPS(CAST((2 - 1) AS JSON),CAST((1 + 2) AS JSON)),\n" + + " JSON_OVERLAPS(CAST('null' AS JSON),CAST('null' AS JSON)),\n" + + " JSON_OVERLAPS(CAST('{\\\"white\\\":2}' AS JSON), CAST('{\\\"black\\\":1}' AS JSON));"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + //quote + sql = "select JSON_OVERLAPS(JSON_QUOTE('white'),JSON_QUOTE('black')),\n" + + " JSON_OVERLAPS(JSON_QUOTE('white'),JSON_QUOTE('black')),\n" + + " JSON_OVERLAPS(JSON_QUOTE('white'),JSON_QUOTE('black'));"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + //arrays + sql = "select JSON_OVERLAPS(JSON_ARRAY(3,4),JSON_ARRAY(1,2)),\n" + + " JSON_OVERLAPS(JSON_ARRAY(3,4), CAST('{\"3\": 4}' as JSON)),\n" + + " JSON_OVERLAPS(JSON_ARRAY(3,4), JSON_ARRAY(3)),\n" + + " JSON_OVERLAPS(JSON_ARRAY(3,4), JSON_ARRAY(3,4,5)),\n" + + " JSON_OVERLAPS(JSON_ARRAY(3,FALSE,'white'),JSON_ARRAY(1,TRUE,'black')),\n" + + " JSON_OVERLAPS(JSON_ARRAY(CAST('{\\\"white\\\":2}' AS JSON)), JSON_ARRAY(CAST('{\\\"black\\\":1}' AS JSON)));"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + //objects + sql = "select JSON_OVERLAPS(JSON_OBJECT('second',2),JSON_OBJECT('first',1)),\n" + + " JSON_OVERLAPS(JSON_OBJECT('second',2),JSON_OBJECT('second',1)),\n" + + " JSON_OVERLAPS(JSON_OBJECT('second',2),JSON_OBJECT('second',2)),\n" + + " JSON_OVERLAPS(CAST('{\"a\":1, \"b\": {\"c\": 3}}' as JSON), CAST('{\"c\":3}' as JSON)),\n" + + " JSON_OVERLAPS(CAST('{\"a\":1, \"b\": {\"c\": 3}, \"c\": 3}' as JSON), CAST('{\"c\":3}' as JSON)),\n" + + " JSON_OVERLAPS(CAST('{\"a\":1, \"b\": {\"c\": 3}, \"d\": 3}' as JSON), CAST('{\"b\": {\"c\": 2}}' as JSON)),\n" + + " JSON_OVERLAPS(JSON_OBJECT('second',CAST('{\\\"white\\\":2}' AS JSON)), JSON_OBJECT('first',CAST('{\\\"black\\\":1}' AS JSON)));"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + //funcions + sql = "select JSON_OVERLAPS(json_quote(concat('foo','bar')),json_quote(concat('foo','bar'))),\n" + + " JSON_OVERLAPS(CAST(2 AS JSON),CAST(1 AS JSON)),\n" + + " JSON_OVERLAPS(JSON_QUOTE('bar'),JSON_QUOTE('foo')),\n" + + " JSON_OVERLAPS(CAST('{\\\"white\\\":2}' AS JSON), CAST('{\\\"black\\\":1}' AS JSON));"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + //copy from mysql + sql = "select json_overlaps(cast('[1,2,3]' as json), cast('[3,4,5]' as json)),\n" + + " json_overlaps(cast('[1,2,3]' as json), cast('[4,4,5]' as json)),\n" + + " json_overlaps(cast('[1,2,3]' as json), cast('[4,5]' as json)),\n" + + " json_overlaps(cast('[1,2]' as json), cast('[3,4,5]' as json)),\n" + + " json_overlaps(cast('[1,2]' as json), cast('[2,4,5]' as json)),\n" + + " json_overlaps(cast('1' as json), cast('[3,4,5]' as json)),\n" + + " json_overlaps(cast('[3,4,5]' as json), cast('1' as json)),\n" + + " json_overlaps(cast('[3,4,{\"a\":5}]' as json), cast('{\"a\":5}' as json)),\n" + + " json_overlaps(cast('{\"a\":1, \"b\":2}' as json), cast('{\"a\":1,\"c\":3}' as json)),\n" + + " json_overlaps(cast('{\"a\":1, \"b\":2}' as json), cast('{\"a\":2,\"c\":3}' as json)),\n" + + " json_overlaps(cast('{\"a\":1, \"b\":null}' as json), cast('{\"a\":2,\"c\":3}' as json)),\n" + + " json_overlaps(cast('{\"a\":1, \"b\":2}' as json), cast('{\"a\":null, \"c\":3}' as json)),\n" + + " json_overlaps('null','[null]'),\n" + + " json_overlaps('1234',NULL);"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + sql = "select json_overlaps('2','[2,3,4]'),\n" + + " json_overlaps('null',NULL),\n" + + " json_overlaps('[{\"a\":1}]', '{\"a\":1}') as c1,\n" + + " json_overlaps('[{\"a\":1}]', '[{\"a\":1}]') as c2,\n" + + " json_overlaps('[{}]', '{}') as c1,\n" + + " json_overlaps('{}', '[{}]') as c1,\n" + + " json_overlaps('[{}]', '{\"a\":1, \"b\":2}') as c1,\n" + + " json_overlaps('[{}]', '1') as c1,\n" + + " json_overlaps(\"1\",\"1\") as c1,\n" + + " json_overlaps(\"true\",\"false\") as c1,\n" + + " json_overlaps(\"null\",\"null\") as c1,\n" + + " json_overlaps(\"123\",'{\"asd\":123}') as c1;"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + sql = "select json_overlaps('123',NULL);"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + sql = "select json_overlaps(NULL, '123');"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + + sql = "select json_overlaps('asdasd',NULL);"; + selectErrorAssert(sql, null, mysqlConnection, "Invalid JSON text"); + selectErrorAssert(sql, null, tddlConnection, "Invalid JSON text"); + + sql = "select json_overlaps(NULL, 'asdasd');"; + selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); + } + } + @Test public void testJsonInsert() throws SQLException { String sql = "select JSON_INSERT('{ \"a\": 1, \"b\": [2, 3]}', '$.a', 10, '$.c', '[true, false]') from " diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/functions/FunctionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/functions/FunctionTest.java index f19906f3d..7c15b21ea 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/functions/FunctionTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/functions/FunctionTest.java @@ -42,6 +42,7 @@ import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentLengthSameAssert; import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentSameAssert; import static com.alibaba.polardbx.qatest.validator.DataValidator.selectContentSameStringIgnoreCaseAssert; +import static com.alibaba.polardbx.qatest.validator.DataValidator.selectOrderAssert; /** * Created by chuanqin on 17/12/6. @@ -216,6 +217,13 @@ public void toBase64WithBinaryInputTest() { selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); } + @Test + public void toBase64BlobTest() { + String sql = String.format("/*+ TDDL: ENABLE_PUSH_PROJECT=false*/ " + + "select to_base64(blob_test) from %s order by pk;", baseOneTableName); + selectOrderAssert(sql, null, mysqlConnection, tddlConnection); + } + @Test @Ignore public void bitAndTest() throws Exception { @@ -366,7 +374,10 @@ public void strToDateTest() throws Exception { + " STR_TO_DATE('Mayy 1, 2013', '%M %d, %Y') d,\n" + " STR_TO_DATE('9', '%m'),\n" + " STR_TO_DATE('9', '%s') e,\n" - + " STR_TO_DATE('9/2001', '%i/%Y') f;\n"; + + " STR_TO_DATE('9/2001', '%i/%Y') f,\n" + + " STR_TO_DATE('2020-08-01 00:00:00','%Y-%m-%d %T') g,\n" + + " STR_TO_DATE('Monday 7th November 2022 13:45:30','%W %D %M %Y %T') h,\n" + + " STR_TO_DATE('01:02:03 PM', '%r') i;\n"; selectContentSameAssert(sql, null, mysqlConnection, tddlConnection); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/select/SubqueryUserCaseTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/select/SubqueryUserCaseTest.java index 5718c4cf6..19d5308fb 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/select/SubqueryUserCaseTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/select/SubqueryUserCaseTest.java @@ -49,6 +49,12 @@ public void testSubqueryWithBroadcastAndSingleTable() throws SQLException { + " OR jgdm.qxbm = xzqh.qhdm ))"; c.createStatement().execute("use " + testSchemaDrds); c.createStatement().executeQuery(testSql); + + testSql = + "select * from single_tbl a join single_tbl1 b on a.name=b.name and exists(select 1 from single_tbl2);"; + + c.createStatement().execute("use " + testSchemaAuto); + c.createStatement().executeQuery(testSql); } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/spm/BaselineCommandTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/spm/BaselineCommandTest.java index 84a833ebb..5a3d0effc 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/spm/BaselineCommandTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/spm/BaselineCommandTest.java @@ -2,11 +2,13 @@ import com.alibaba.polardbx.common.utils.Assert; import com.alibaba.polardbx.qatest.BaseTestCase; +import com.alibaba.polardbx.repo.mysql.handler.LogicalBaselineHandler; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.sql.Connection; +import java.sql.ResultSet; import java.sql.SQLException; /** @@ -15,6 +17,7 @@ public class BaselineCommandTest extends BaseTestCase { private static final String db = "BaselineCommandTest"; private static final String table = "BaselineCommandTest"; + private static final String table1 = "BaselineCommandTest1"; private static final String createTbl = "CREATE TABLE `%s` (\n" + "`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',\n" + "`creator` varchar(64) NOT NULL DEFAULT '' ,\n" @@ -22,6 +25,13 @@ public class BaselineCommandTest extends BaseTestCase { + "PRIMARY KEY (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 "; + private static final String createTbl1 = "CREATE TABLE `%s` (\n" + + "`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',\n" + + "`creator` varchar(64) NOT NULL DEFAULT '' ,\n" + + "`extend` varchar(128) NOT NULL DEFAULT '' ,\n" + + "PRIMARY KEY (`id`) " + + ") ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 dbpartition by hash(id) tbpartition by hash(id) tbpartitions 3;"; + private static final String testSqlTemp = "baseline add sql /*TDDL:a()*/ select * from %s "; @Before @@ -31,6 +41,7 @@ public void buildCatalog() throws SQLException { c.createStatement().execute("create database if not exists " + db + " mode='drds'"); c.createStatement().execute("use " + db); c.createStatement().execute(String.format(createTbl, table)); + c.createStatement().execute(String.format(createTbl1, table1)); } } @@ -42,15 +53,210 @@ public void clean() throws SQLException { } @Test - public void testAddPlanThatBaselineNotSupported() throws SQLException { + public void testAddPlanThatBaselineNotSupported() { try (Connection c = getPolardbxConnection(db)) { String testSql = String.format(testSqlTemp, table); // test plan in plan cache c.createStatement().execute(testSql); + Assert.fail(); } catch (SQLException e) { if (e.getErrorCode() != 7001) { Assert.fail("not expected baseline error"); } } } -} + + @Test + public void testBaselineHelp() throws SQLException { + String testSql = "baseline help"; + try (Connection c = getPolardbxConnection(db)) { + ResultSet rs = c.createStatement().executeQuery(testSql); + while (rs.next()) { + String statement = rs.getString("STATEMENT"); + String desc = rs.getString("DESCRIPTION"); + String example = rs.getString("EXAMPLE"); + LogicalBaselineHandler.BASELINE_OPERATION operation = + LogicalBaselineHandler.BASELINE_OPERATION.valueOf(statement); + Assert.assertTrue(desc.equalsIgnoreCase(operation.getDesc())); + Assert.assertTrue(example.equalsIgnoreCase(operation.getExample())); + } + } + } + + @Test + public void testBaselineAddListDelete() throws SQLException { + int baselineId1; + int baselineId2; + int baselineId3; + try (Connection c = getPolardbxConnection(db)) { + // add plan + String baselineAdd = "baseline add sql /*TDDL:a()*/ select * from %s t1 join %s t2 on t1.id = t2.id"; + ResultSet resultSet = c.createStatement().executeQuery(String.format(baselineAdd, table, table1)); + resultSet.next(); + baselineId1 = resultSet.getInt("BASELINE_ID"); + resultSet.close(); + + // fix plan + baselineAdd = "baseline fix sql /*TDDL:b()*/ select * from %s t1 join %s t2 on t1.id = t2.id limit 1"; + resultSet = c.createStatement().executeQuery(String.format(baselineAdd, table, table1)); + resultSet.next(); + baselineId2 = resultSet.getInt("BASELINE_ID"); + resultSet.close(); + + // hint bind + baselineAdd = + "baseline hint bind /*TDDL:c()*/ select * from %s t1 join %s t2 on t1.id = t2.id order by t1.creator limit 10"; + resultSet = c.createStatement().executeQuery(String.format(baselineAdd, table, table1)); + resultSet.next(); + baselineId3 = resultSet.getInt("BASELINE_ID"); + resultSet.close(); + } + + // check baseline list + try (Connection c1 = getPolardbxConnection(db)) { + ResultSet rs = c1.createStatement().executeQuery("baseline list"); + while (rs.next()) { + int testBaselineId = rs.getInt("BASELINE_ID"); + String fixed = rs.getString("FIXED"); + String hint = rs.getString("HINT"); + String rebuild = rs.getString("IS_REBUILD_AT_LOAD"); + if (testBaselineId == baselineId1) { + Assert.assertTrue(fixed.equalsIgnoreCase("0")); + Assert.assertTrue(hint.equalsIgnoreCase("/*TDDL:a()*/")); + Assert.assertTrue(rebuild.equalsIgnoreCase("false")); + } else if (testBaselineId == baselineId2) { + Assert.assertTrue(fixed.equalsIgnoreCase("1")); + Assert.assertTrue(hint.equalsIgnoreCase("/*TDDL:b()*/")); + Assert.assertTrue(rebuild.equalsIgnoreCase("false")); + } else if (testBaselineId == baselineId3) { + Assert.assertTrue(fixed.equalsIgnoreCase("1")); + Assert.assertTrue(hint.equalsIgnoreCase("/*TDDL:c()*/")); + Assert.assertTrue(rebuild.equalsIgnoreCase("true")); + } + } + } + + // test delete + try (Connection c2 = getPolardbxConnection(db)) { + c2.createStatement().execute(String.format("baseline delete %d", baselineId1)); + c2.createStatement().execute(String.format("baseline delete %d", baselineId2)); + c2.createStatement().execute(String.format("baseline delete %d", baselineId3)); + + try (Connection c3 = getPolardbxConnection(db)) { + ResultSet rs = c3.createStatement().executeQuery("baseline list"); + while (rs.next()) { + int testBaselineId = rs.getInt("BASELINE_ID"); + Assert.assertTrue(testBaselineId != baselineId1 && testBaselineId != baselineId2 + && testBaselineId != baselineId3); + } + } + } + } + + @Test + public void testDeleteAll() throws SQLException { + // add plan + try (Connection c = getPolardbxConnection(db)) { + // add plan + String baselineAdd = "baseline add sql /*TDDL:a()*/ select * from %s t1 join %s t2 on t1.id = t2.id"; + c.createStatement().executeQuery(String.format(baselineAdd, table, table1)); + + // fix plan + baselineAdd = "baseline fix sql /*TDDL:b()*/ select * from %s t1 join %s t2 on t1.id = t2.id limit 1"; + c.createStatement().executeQuery(String.format(baselineAdd, table, table1)); + + // hint bind + baselineAdd = + "baseline hint bind /*TDDL:c()*/ select * from %s t1 join %s t2 on t1.id = t2.id order by t1.creator limit 10"; + c.createStatement().executeQuery(String.format(baselineAdd, table, table1)); + } + // test delete + try (Connection c2 = getPolardbxConnection(db)) { + // delete all + c2.createStatement().execute("baseline delete_all"); + try (Connection c3 = getPolardbxConnection(db)) { + ResultSet rs = c3.createStatement().executeQuery("baseline list"); + while (rs.next()) { + Assert.fail(); + } + } + } + } + + @Test + public void testDeletePlan() throws SQLException { + int baselineId1; + int baselineId2; + int baselineId3; + int planId1; + int planId2; + Integer planId3; + try (Connection c = getPolardbxConnection(db)) { + // add plan + String baselineAdd = "baseline add sql /*TDDL:a()*/ select * from %s t1 join %s t2 on t1.id = t2.id"; + ResultSet resultSet = c.createStatement().executeQuery(String.format(baselineAdd, table, table1)); + resultSet.next(); + baselineId1 = resultSet.getInt("BASELINE_ID"); + planId1 = resultSet.getInt("PLAN_ID"); + resultSet.close(); + + // fix plan + baselineAdd = "baseline fix sql /*TDDL:b()*/ select * from %s t1 join %s t2 on t1.id = t2.id limit 1"; + resultSet = c.createStatement().executeQuery(String.format(baselineAdd, table, table1)); + resultSet.next(); + baselineId2 = resultSet.getInt("BASELINE_ID"); + planId2 = resultSet.getInt("PLAN_ID"); + resultSet.close(); + + // hint bind + baselineAdd = + "baseline hint bind /*TDDL:c()*/ select * from %s t1 join %s t2 on t1.id = t2.id order by t1.creator limit 10"; + resultSet = c.createStatement().executeQuery(String.format(baselineAdd, table, table1)); + resultSet.next(); + baselineId3 = resultSet.getInt("BASELINE_ID"); + planId3 = resultSet.getInt("PLAN_ID"); + Assert.assertTrue(planId3 == 0); + resultSet.close(); + } + + // check baseline list + try (Connection c1 = getPolardbxConnection(db)) { + ResultSet rs = c1.createStatement().executeQuery("baseline list"); + while (rs.next()) { + int testBaselineId = rs.getInt("BASELINE_ID"); + String fixed = rs.getString("FIXED"); + String hint = rs.getString("HINT"); + String rebuild = rs.getString("IS_REBUILD_AT_LOAD"); + if (testBaselineId == baselineId1) { + Assert.assertTrue(fixed.equalsIgnoreCase("0")); + Assert.assertTrue(hint.equalsIgnoreCase("/*TDDL:a()*/")); + Assert.assertTrue(rebuild.equalsIgnoreCase("false")); + } else if (testBaselineId == baselineId2) { + Assert.assertTrue(fixed.equalsIgnoreCase("1")); + Assert.assertTrue(hint.equalsIgnoreCase("/*TDDL:b()*/")); + Assert.assertTrue(rebuild.equalsIgnoreCase("false")); + } else if (testBaselineId == baselineId3) { + Assert.assertTrue(fixed.equalsIgnoreCase("1")); + Assert.assertTrue(hint.equalsIgnoreCase("/*TDDL:c()*/")); + Assert.assertTrue(rebuild.equalsIgnoreCase("true")); + } + } + } + + // test delete + try (Connection c2 = getPolardbxConnection(db)) { + c2.createStatement().execute(String.format("baseline delete_plan %d", planId1)); + c2.createStatement().execute(String.format("baseline delete_plan %d", planId2)); + c2.createStatement().execute(String.format("baseline delete %d", baselineId3)); + + try (Connection c3 = getPolardbxConnection(db)) { + ResultSet rs = c3.createStatement().executeQuery("baseline list"); + while (rs.next()) { + int testBaselineId = rs.getInt("BASELINE_ID"); + Assert.assertTrue(testBaselineId != baselineId1 && testBaselineId != baselineId2 + && testBaselineId != baselineId3); + } + } + } + } +} \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/spm/ChoosePlanByCostTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/spm/ChoosePlanByCostTest.java new file mode 100644 index 000000000..e33c70116 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/spm/ChoosePlanByCostTest.java @@ -0,0 +1,138 @@ +package com.alibaba.polardbx.qatest.dql.sharding.spm; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +import static com.alibaba.polardbx.common.utils.Assert.assertTrue; +import static com.alibaba.polardbx.qatest.BaseTestCase.getPolardbxConnection0; + +/** + * @author fangwu + */ +public class ChoosePlanByCostTest { + + private static final String DB = ChoosePlanByCostTest.class.getSimpleName(); + private static final String TB = "order"; + + private static final String CREATE_TABLE_FORMATTED = + "CREATE TABLE IF NOT EXISTS `%s` (\n" + + " `id` BIGINT(11) NOT NULL AUTO_INCREMENT,\n" + + " `order_id` VARCHAR(20) DEFAULT NULL,\n" + + " `buyer_id` VARCHAR(20) DEFAULT NULL,\n" + + " `seller_id` VARCHAR(20) DEFAULT NULL,\n" + + " `order_snapshot` LONGTEXT,\n" + + " `order_detail` LONGTEXT,\n" + + " `test` VARCHAR(20) DEFAULT NULL,\n" + + " PRIMARY KEY (`id`),\n" + + " GLOBAL INDEX `g_i_buyer` (`buyer_id`) COVERING (`order_id`)\n" + + " PARTITION BY KEY(`buyer_id`) PARTITIONS 16,\n" + + " GLOBAL INDEX `g_i_seller` (`seller_id`) COVERING (`order_id`)\n" + + " PARTITION BY KEY(`seller_id`) PARTITIONS 16,\n" + + " KEY `l_i_order` (`order_id`)\n" + + ") ENGINE = InnoDB DEFAULT CHARSET = utf8\n" + + "PARTITION BY KEY(`order_id`) PARTITIONS 16"; + + private static final String statisticCorrectionSql = "SET STATISTIC_CORRECTIONS='\n" + + "Catalog:ChoosePlanByCostTest,g_i_buyer_$4897,buyer_id,123\n" + + "Action:getFrequency\n" + + "StatisticValue:10000\n" + + "\n" + + "Catalog:ChoosePlanByCostTest,g_i_buyer_$4897\n" + + "Action:getRowCount\n" + + "StatisticValue:10000\n" + + "\n" + + "Catalog:ChoosePlanByCostTest,order,buyer_id,123\n" + + "Action:getFrequency\n" + + "StatisticValue:10000\n" + + "\n" + + "Catalog:chooseplanbycosttest,g_i_seller_$78a8,seller_id,1_null\n" + + "Action:getRangeCount\n" + + "StatisticValue:10000\n" + + "\n" + + "Catalog:chooseplanbycosttest,order,seller_id,1_null\n" + + "Action:getRangeCount\n" + + "StatisticValue:10000\n" + + "\n" + + "Catalog:ChoosePlanByCostTest,order\n" + + "Action:getRowCount\n" + + "StatisticValue:10000\n" + + "\n" + + "Catalog:ChoosePlanByCostTest,g_i_seller_$78a8\n" + + "Action:getRowCount\n" + + "StatisticValue:10000\n" + + "\n" + + "Catalog:ChoosePlanByCostTest,order,id\n" + + "Action:getCardinality\n" + + "StatisticValue:10000\n" + + "'"; + + @BeforeClass + public static void setUp() throws SQLException { + try (Connection c = getPolardbxConnection0()) { + c.createStatement().execute("drop database if exists " + DB); + c.createStatement().execute(String.format("create database if not exists %s mode='auto'", DB)); + c.createStatement().execute("use " + DB); + c.createStatement().execute(String.format(CREATE_TABLE_FORMATTED, TB)); + } + } + + @AfterClass + public static void cleanUp() throws SQLException { + try (Connection c = getPolardbxConnection0()) { + c.createStatement().execute("drop database if exists " + DB); + } + } + + @Test + public void testCostChooseGsiByDifferentEqualValue() throws SQLException { + String sql = "select * from %s where buyer_id='%s'"; + try (Connection c = getPolardbxConnection0(DB)) { + // set statistics + c.createStatement().execute(statisticCorrectionSql); + + // add baseline + c.createStatement().execute("baseline add sql /*TDDL:a()*/ " + String.format(sql, TB, "123")); + c.createStatement().execute("baseline add sql /*TDDL:a()*/ " + String.format(sql, TB, "1234")); + + String explain = explain(c, String.format(sql, TB, "123")); + assertTrue(!explain.contains("g_i_buyer")); + + explain = explain(c, String.format(sql, TB, "1234")); + assertTrue(explain.contains("g_i_buyer")); + } + } + + @Test + public void testCostChooseGsiByDifferentLimitValue() throws SQLException { + String sql = "select * from %s where buyer_id='123' limit %s"; + try (Connection c = getPolardbxConnection0(DB)) { + // set statistics + c.createStatement().execute(statisticCorrectionSql); + + // add baseline + c.createStatement().execute("baseline add sql /*TDDL:a()*/ " + String.format(sql, TB, "100")); + c.createStatement().execute("baseline add sql /*TDDL:a()*/ " + String.format(sql, TB, "1000")); + + String explain = explain(c, String.format(sql, TB, "1000")); + assertTrue(!explain.contains("g_i_buyer")); + + explain = explain(c, String.format(sql, TB, "100")); + assertTrue(explain.contains("g_i_buyer")); + } + } + + private String explain(Connection c, String sql) throws SQLException { + StringBuilder sb = new StringBuilder(); + try (ResultSet rs = c.createStatement().executeQuery("explain " + sql)) { + while (rs.next()) { + sb.append(rs.getString(1)).append("\n"); + } + return sb.toString(); + } + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/spm/ForceIndexTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/spm/ForceIndexTest.java new file mode 100644 index 000000000..b682bb84a --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/dql/sharding/spm/ForceIndexTest.java @@ -0,0 +1,351 @@ +package com.alibaba.polardbx.qatest.dql.sharding.spm; + +import com.alibaba.polardbx.qatest.BaseTestCase; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.SQLException; + +import static com.alibaba.polardbx.common.utils.Assert.assertTrue; + +/** + * @author fangwu + */ +public class ForceIndexTest extends BaseTestCase { + private static final String DB_NAME = "force_index_test"; + private static final String TBL_NAME1 = "t_order"; + private static final String TBL_NAME2 = "t_order1"; + private static final String TBL_NAME_SINGLE = "t_order_single"; + + private static final String CREATE_TABLE_FORMATTED = + "CREATE TABLE IF NOT EXISTS `%s` (\n" + + " `id` BIGINT(11) NOT NULL AUTO_INCREMENT,\n" + + " `order_id` VARCHAR(20) DEFAULT NULL,\n" + + " `buyer_id` VARCHAR(20) DEFAULT NULL,\n" + + " `seller_id` VARCHAR(20) DEFAULT NULL,\n" + + " `order_snapshot` LONGTEXT,\n" + + " `order_detail` LONGTEXT,\n" + + " `test` VARCHAR(20) DEFAULT NULL,\n" + + " PRIMARY KEY (`id`),\n" + + " GLOBAL INDEX `g_i_buyer` (`buyer_id`) COVERING (`order_id`)\n" + + " PARTITION BY KEY(`buyer_id`) PARTITIONS 16,\n" + + " GLOBAL INDEX `g_i_seller` (`seller_id`) COVERING (`order_id`)\n" + + " PARTITION BY KEY(`seller_id`) PARTITIONS 16,\n" + + " KEY `l_i_order` (`order_id`)\n" + + ") ENGINE = InnoDB DEFAULT CHARSET = utf8\n" + + "PARTITION BY KEY(`order_id`) PARTITIONS 16"; + + private static final String CREATE_SINGLE_TABLE_FORMATTED = + "CREATE TABLE IF NOT EXISTS `%s` (\n" + + " `id` BIGINT(11) NOT NULL AUTO_INCREMENT,\n" + + " `order_id` VARCHAR(20) DEFAULT NULL,\n" + + " `buyer_id` VARCHAR(20) DEFAULT NULL,\n" + + " `seller_id` VARCHAR(20) DEFAULT NULL,\n" + + " `order_snapshot` LONGTEXT,\n" + + " `order_detail` LONGTEXT,\n" + + " `test` VARCHAR(20) DEFAULT NULL,\n" + + " PRIMARY KEY (`id`),\n" + + " KEY `l_i_order` (`order_id`)\n" + + ") ENGINE = InnoDB DEFAULT CHARSET = utf8\n" + + "SINGLE"; + + @BeforeClass + public static void setUp() { + String createDbSql = "CREATE DATABASE IF NOT EXISTS " + DB_NAME + " mode='auto'"; + try { + // build db + Connection conn = getPolardbxConnection0(); + conn.createStatement().execute(createDbSql); + + // build table + conn.createStatement().execute("use " + DB_NAME); + conn.createStatement().execute(String.format(CREATE_TABLE_FORMATTED, TBL_NAME1)); + conn.createStatement().execute(String.format(CREATE_TABLE_FORMATTED, TBL_NAME2)); + conn.createStatement().execute(String.format(CREATE_SINGLE_TABLE_FORMATTED, TBL_NAME_SINGLE)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @AfterClass + public static void cleanUp() { + try { + // build db + getPolardbxConnection0().createStatement().execute("drop database " + DB_NAME); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testForceIndexSingleTable() throws SQLException { + try (Connection c = getPolardbxConnection0(DB_NAME)) { + String sql = "SELECT * FROM t_order_single force index(l_i_order) where buyer_id = '123456'"; + + // test explain + String explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("l_i_order")); + + sql = "/*TDDL:index(t_order_single, l_i_order)*/SELECT * FROM t_order_single where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("l_i_order")); + + sql = "/*TDDL:index(t_order_single, primary)*/SELECT * FROM t_order_single where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("force index(primary)")); + + sql = + "/*TDDL:index(t_order_single, primary, primary)*/SELECT * FROM t_order_single where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("force index(primary)")); + } + } + + @Test + public void testDNHint() throws SQLException { + try (Connection c = getPolardbxConnection0(DB_NAME)) { + String sql = + "/*TDDL:dn_hint='test hint'*/SELECT * FROM t_order_single force index(l_i_order) where buyer_id = '123456'"; + + // test explain + String explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("/*+test hint*/")); + + sql = + "/*TDDL:index(t_order_single, l_i_order) dn_hint='test hint' */SELECT * FROM t_order_single force index(g_i_buyer) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("/*+test hint*/")); + } + } + + @Test + public void testForceIndexGsi() { + try (Connection c = getPolardbxConnection0(DB_NAME)) { + String sql = "SELECT * FROM t_order force index(g_i_seller) where buyer_id = '123456'"; + + // test explain + String explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("g_i_seller")); + + sql = + "/*TDDL:index(t_order, g_i_seller) */SELECT * FROM t_order force index(g_i_buyer) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("g_i_seller")); + + sql = "SELECT * FROM t_order force index(g_i_buyer) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("g_i_buyer")); + + sql = + "/*TDDL:index(t_order, g_i_buyer) */SELECT * FROM t_order force index(primary) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("g_i_buyer")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testForceIndexLocalIndex() { + try (Connection c = getPolardbxConnection0(DB_NAME)) { + String sql = "SELECT * FROM t_order force index(l_i_order) where buyer_id = '123456'"; + + // test explain + String explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("g_i_seller")); + assertTrue(!explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(l_i_order)")); + + sql = + "/*TDDL:index(t_order, l_i_order)*/ SELECT * FROM t_order force index(g_i_seller) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("g_i_seller")); + assertTrue(!explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(l_i_order)")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testForceIndexPrimary() { + try (Connection c = getPolardbxConnection0(DB_NAME)) { + String sql = "SELECT * FROM t_order force index(primary) where buyer_id = '123456'"; + + // test explain + String explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("g_i_seller")); + assertTrue(!explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(primary)")); + + sql = + "/*TDDL:index(t_order, primary)*/SELECT * FROM t_order force index(g_i_buyer) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("g_i_seller")); + assertTrue(!explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(primary)")); + + sql = "SELECT * FROM t_order force index(primary.primary) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("g_i_seller")); + assertTrue(!explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(primary)")); + + sql = + "/*TDDL:index(t_order, primary, primary)*/SELECT * FROM t_order force index(g_i_buyer) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("g_i_seller")); + assertTrue(!explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(primary)")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testForceIndexGsiLocalIndex() { + try (Connection c = getPolardbxConnection0(DB_NAME)) { + String sql = "SELECT * FROM t_order force index(g_i_buyer.primary) where buyer_id = '123456'"; + + // test explain + String explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("g_i_seller")); + assertTrue(explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(primary)")); + + sql = + "/*TDDL:index(t_order, g_i_seller, primary)*/ SELECT * FROM t_order force index(g_i_buyer.primary) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("g_i_seller")); + assertTrue(!explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(primary)")); + + sql = "SELECT * FROM t_order force index(g_i_buyer.auto_shard_key_buyer_id) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("g_i_seller")); + assertTrue(explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(auto_shard_key_buyer_id)")); + + sql = + "/*TDDL:index(t_order, g_i_buyer, auto_shard_key_buyer_id)*/ SELECT * FROM t_order force index(g_i_seller.primary) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("g_i_seller")); + assertTrue(explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(auto_shard_key_buyer_id)")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testForceIndexGsiByForceLocalIndex() { + try (Connection c = getPolardbxConnection0(DB_NAME)) { + String sql = + "SELECT * FROM t_order force index(g_i_buyer.auto_shard_key_buyer_id) where buyer_id = '123456'"; + + // test explain + String explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("g_i_seller")); + assertTrue(explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(auto_shard_key_buyer_id)")); + + sql = + "/*TDDL:index(t_order, g_i_seller, auto_shard_key_seller_id)*/ SELECT * FROM t_order force index(g_i_buyer.primary) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("g_i_seller")); + assertTrue(!explain.contains("g_i_buyer")); + + sql = "SELECT * FROM t_order force index(auto_shard_key_buyer_id) where buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("g_i_seller")); + assertTrue(explain.contains("g_i_buyer")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testForceIndexUnPushJoin() { + try (Connection c = getPolardbxConnection0(DB_NAME)) { + String sql = + "SELECT * FROM t_order t1 force index(g_i_buyer.primary) join t_order1 t2 force index(primary) on t1.id=t2.id where t1.buyer_id = '123456'"; + + // test explain + String explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("indexscan(tables=\"g_i_seller_")); + assertTrue(explain.contains("indexscan(tables=\"g_i_buyer_")); + assertTrue(explain.contains("force index(primary)")); + + sql = "/*TDDL:index(t_order, g_i_buyer, primary) index(t_order1, g_i_seller, auto_shard_key_seller_id)*/" + + "SELECT * FROM t_order t1 force index(primary) join t_order1 t2 force index(primary) on t1.id=t2.id where t1.buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(explain.contains("g_i_seller")); + assertTrue(explain.contains("g_i_buyer")); + assertTrue(explain.contains("force index(auto_shard_key_seller_id)")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void testForceIndexPushedJoin() { + try (Connection c = getPolardbxConnection0(DB_NAME)) { + String sql = + "SELECT * FROM t_order t1 force index(g_i_buyer.primary) join t_order1 t2 force index(primary) on t1.order_id=t2.order_id where t1.buyer_id = '123456'"; + + // test explain + String explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("indexscan(tables=\"g_i_seller_")); + assertTrue(explain.contains("indexscan(tables=\"g_i_buyer_")); + assertTrue(explain.contains("force index(primary)")); + + sql = + "SELECT * FROM t_order t1 force index(l_i_order) join t_order1 t2 force index(primary) on t1.order_id=t2.order_id where t1.buyer_id = '123456'"; + + // test explain + explain = getExplainResult(c, sql).toLowerCase(); + assertTrue(!explain.contains("indexscan(tables=\"g_i_seller_")); + assertTrue(!explain.contains("indexscan(tables=\"g_i_buyer_")); + assertTrue(explain.contains("force index(primary)")); + assertTrue(explain.contains("force index(l_i_order)")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/oss/ColumnarDirectPlanTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/oss/ColumnarDirectPlanTest.java new file mode 100644 index 000000000..139157de9 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/oss/ColumnarDirectPlanTest.java @@ -0,0 +1,204 @@ +package com.alibaba.polardbx.qatest.oss; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.stream.Collectors; + +import static com.google.common.truth.Truth.assertWithMessage; + +public class ColumnarDirectPlanTest extends DDLBaseNewDBTestCase { + private static String TABLE_DEFINITION_FORMAT = "CREATE TABLE `%s` (\n" + + "\t`id` bigint(20) NOT NULL AUTO_INCREMENT,\n" + + "\t`a` int(32) UNSIGNED DEFAULT NULL,\n" + + "\t`b` int(32) UNSIGNED DEFAULT NULL,\n" + + "\t`c` int(32) UNSIGNED DEFAULT NULL,\n" + + "\tprimary key(id)\n" + + ") %s"; + + private static String CREATE_COL_IDX = SKIP_WAIT_CCI_CREATION_HINT + + "create clustered columnar index `%s` on %s(`%s`) partition by hash(`%s`) partitions 4"; + + private static String PUB_COL_IDX = + "/*+TDDL:CMD_EXTRA(ALTER_CCI_STATUS=true, ALTER_CCI_STATUS_BEFORE=CREATING, ALTER_CCI_STATUS_AFTER=PUBLIC)*/" + + "ALTER TABLE `%s` alter index `%s` VISIBLE;"; + + String tb1 = "tb1"; + String tb2 = "tb2"; + String tb3 = "tb3"; + String shard1 = "single"; + String shard2 = "single"; + String shard3 = "broadcast"; + + String colIdxA = "colIdx_a"; + String colIdxB = "colIdx_b"; + String colIdxC = "colIdx_c"; + + String colA = "a"; + String colB = "b"; + String colC = "c"; + + String COL_OPT = "/*+TDDL:cmd_extra(WORKLOAD_TYPE=TP ENABLE_COLUMNAR_OPTIMIZER=true)*/"; + String APHINT = "/*+TDDL:cmd_extra(WORKLOAD_TYPE=AP ENABLE_COLUMNAR_OPTIMIZER=true)*/"; + String AP_NOCOL_HINT = "/*+TDDL:cmd_extra(WORKLOAD_TYPE=AP ENABLE_COLUMNAR_OPTIMIZER=false)*/"; + + @Override + public boolean usingNewPartDb() { + return true; + } + + @After + public void dropTable() { + JdbcUtil.dropTable(getTddlConnection1(), tb1); + JdbcUtil.dropTable(getTddlConnection1(), tb2); + JdbcUtil.dropTable(getTddlConnection1(), tb3); + } + + @Before + public void prepareTable() { + JdbcUtil.dropTable(getTddlConnection1(), tb1); + JdbcUtil.dropTable(getTddlConnection1(), tb2); + JdbcUtil.dropTable(getTddlConnection1(), tb3); + + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(TABLE_DEFINITION_FORMAT, tb1, shard1)); + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(TABLE_DEFINITION_FORMAT, tb2, shard2)); + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(TABLE_DEFINITION_FORMAT, tb3, shard3)); + + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(CREATE_COL_IDX, colIdxA, tb1, colA, colA)); + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(PUB_COL_IDX, tb1, colIdxA)); + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(CREATE_COL_IDX, colIdxB, tb2, colB, colB)); + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(PUB_COL_IDX, tb2, colIdxB)); + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(CREATE_COL_IDX, colIdxC, tb3, colC, colC)); + JdbcUtil.executeSuccess(getTddlConnection1(), String.format(PUB_COL_IDX, tb3, colIdxC)); + } + + @Test + public void testExplain() throws SQLException { + String sql; + + sql = String.format("explain simple select * from %s", tb1); + checkNoOSSTableScan(sql); + sql = APHINT + String.format("explain simple select * from %s", tb1); + checkAllOSSTableScan(sql); + sql = COL_OPT + String.format("explain simple select * from %s", tb1); + checkNoOSSTableScan(sql); + sql = String.format("explain simple select * from %s force index(%s)", tb1, colIdxA); + checkAllOSSTableScan(sql); + sql = String.format("explain simple insert into %s select * from %s force index(%s)", tb2, tb1, colIdxA); + checkOSSTableScanAndLogicalInsert(sql); + sql = String.format("explain simple replace into %s select * from %s force index(%s)", tb2, tb1, colIdxA); + checkOSSTableScanAndLogicalInsert(sql); + + sql = String.format("explain simple select * from %s", tb3); + checkNoOSSTableScan(sql); + sql = APHINT + String.format("explain simple select * from %s", tb3); + checkAllOSSTableScan(sql); + sql = COL_OPT + String.format("explain simple select * from %s", tb3); + checkNoOSSTableScan(sql); + + // dml + sql = COL_OPT + String.format("explain simple delete from %s where a = 1", tb1); + checkNoOSSTableScan(sql); + sql = APHINT + String.format("explain simple update %s set b = 1 where a= 1", tb3); + checkNoOSSTableScan(sql); + sql = String.format("explain simple delete from %s force index(%s) where a = 1", tb1, colIdxA); + checkNoOSSTableScan(sql); + + // subquery + sql = String.format("explain simple select *,(select 1 from %s limit 1) from %s", tb1, tb2); + checkNoOSSTableScan(sql); + sql = APHINT + String.format("explain simple select *,(select 1 from %s limit 1) from %s", tb1, tb2); + checkNoOSSTableScan(sql); + sql = APHINT + String.format("explain simple select *,(select 1 from %s limit 1) from %s", tb1, tb3); + checkNoOSSTableScan(sql); + sql = COL_OPT + String.format("explain simple select *,(select 1 from %s limit 1) from %s", tb1, tb3); + checkNoOSSTableScan(sql); + + // force/ignore index + sql = String.format("explain simple select *,(select 1 from %s force index(%s) limit 1) from %s", tb1, colIdxA, + tb2); + checkOSSTableScanAndLogicalView(sql); + sql = + AP_NOCOL_HINT + String.format("explain simple select *,(select 1 from %s force index(%s) limit 1) from %s", + tb1, colIdxA, tb2); + checkOSSTableScanAndLogicalView(sql); + sql = APHINT + String.format("explain simple select *,(select 1 from %s force index(%s) limit 1) from %s", tb1, + colIdxA, tb2); + checkOSSTableScanAndLogicalView(sql); + sql = + COL_OPT + String.format("explain simple select *,(select 1 from %s force index(%s) limit 1) from %s", + tb1, colIdxA, tb2); + checkOSSTableScanAndLogicalView(sql); + + sql = + String.format("explain simple select *,(select 1 from %s force index(%s) limit 1) from %s force index(%s)", + tb1, colIdxA, tb2, colIdxB); + checkAllOSSTableScan(sql); + sql = AP_NOCOL_HINT + String.format( + "explain simple select *,(select 1 from %s force index(%s) limit 1) from %s force index(%s)", tb1, colIdxA, + tb2, colIdxB); + checkAllOSSTableScan(sql); + + sql = COL_OPT + String.format( + "explain simple select *,(select 1 from %s force index(%s) limit 1) from %s", tb1, + colIdxA, tb3); + checkOSSTableScanAndLogicalView(sql); + + sql = APHINT + String.format( + "explain simple select *,(select 1 from %s force index(%s) limit 1) from %s ignore index(%s)", tb1, colIdxA, + tb2, colIdxB); + checkOSSTableScanAndLogicalView(sql); + sql = COL_OPT + String.format( + "explain simple select *,(select 1 from %s force index(%s) limit 1) from %s ignore index(%s)", tb1, colIdxA, + tb2, colIdxB); + checkOSSTableScanAndLogicalView(sql); + sql = APHINT + String.format( + "explain simple select *,(select 1 from %s force index(%s) limit 1) from %s", tb1, + colIdxA, tb3); + checkOSSTableScanAndLogicalView(sql); + + sql = APHINT + String.format( + "explain simple select *,(select 1 from %s limit 1) from %s ignore index(idx_c)", tb1, tb2); + checkNoOSSTableScan(sql); + sql = APHINT + String.format( + "explain simple select *,(select 1 from %s ignore index(%s) limit 1) from %s ignore index(idx_c)", tb1, + colIdxA, tb2); + checkNoOSSTableScan(sql); + } + + void checkAllOSSTableScan(String sql) { + String explain = + JdbcUtil.getAllResult(JdbcUtil.executeQuery(sql, tddlConnection)) + .stream().flatMap(Collection::stream).map(Object::toString).collect(Collectors.joining("")); + assertWithMessage(sql).that(explain).contains("OSSTableScan"); + assertWithMessage(sql).that(explain).doesNotContain("LogicalView"); + } + + void checkNoOSSTableScan(String sql) { + String explain = + JdbcUtil.getAllResult(JdbcUtil.executeQuery(sql, tddlConnection)) + .stream().flatMap(Collection::stream).map(Object::toString).collect(Collectors.joining("")); + assertWithMessage(sql).that(explain).doesNotContain("OSSTableScan"); + } + + void checkOSSTableScanAndLogicalView(String sql) { + String explain = + JdbcUtil.getAllResult(JdbcUtil.executeQuery(sql, tddlConnection)) + .stream().flatMap(Collection::stream).map(Object::toString).collect(Collectors.joining("")); + assertWithMessage(sql).that(explain).contains("OSSTableScan"); + assertWithMessage(sql).that(explain).contains("LogicalView"); + } + + void checkOSSTableScanAndLogicalInsert(String sql) { + String explain = + JdbcUtil.getAllResult(JdbcUtil.executeQuery(sql, tddlConnection)) + .stream().flatMap(Collection::stream).map(Object::toString).collect(Collectors.joining("")); + assertWithMessage(sql).that(explain).contains("OSSTableScan"); + assertWithMessage(sql).that(explain).contains("LogicalInsert"); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/oss/ColumnarSelectionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/oss/ColumnarSelectionTest.java index 0861679bd..35bf3bcfe 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/oss/ColumnarSelectionTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/oss/ColumnarSelectionTest.java @@ -5,6 +5,7 @@ import com.alibaba.polardbx.qatest.oss.utils.FileStorageTestUtil; import com.alibaba.polardbx.qatest.util.JdbcUtil; import com.alibaba.polardbx.qatest.util.PropertiesUtil; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -61,6 +62,14 @@ public boolean usingNewPartDb() { return true; } + @After + public void dropTable() { + JdbcUtil.dropTable(getTddlConnection1(), tb1); + JdbcUtil.dropTable(getTddlConnection1(), tb2); + JdbcUtil.dropTable(getTddlConnection1(), tb3); + JdbcUtil.dropTable(getTddlConnection1(), tbOss); + } + @Before public void prepareTable() { JdbcUtil.dropTable(getTddlConnection1(), tb1); @@ -97,8 +106,8 @@ public void testExplain() throws SQLException { checkNoOSSTableScan(sql); sql = String.format("explain simple delete from %s force index(%s) where a = 1", tb1, colIdxA); checkNoOSSTableScan(sql); - sql = String.format("explain simple update %s force index(%s) set b = 1 where a= 1", tb1, colIdxA); - checkCantUse(sql); +// sql = String.format("explain simple update %s force index(%s) set b = 1 where a= 1", tb1, colIdxA); +// checkCantUse(sql); // sql = APHINT + String.format("explain simple select * from %s for update", tb1); // checkNoOSSTableScan(sql); // sql = APHINT + String.format("explain simple select * from %s force index(%s) for update", tb1, colA); @@ -108,7 +117,7 @@ public void testExplain() throws SQLException { sql = String.format("explain simple select *,(select 1 from %s limit 1) from %s", tb1, tb2); checkNoOSSTableScan(sql); sql = APHINT + String.format("explain simple select *,(select 1 from %s limit 1) from %s", tb1, tb2); - checkAllOSSTableScan(sql); + checkNoOSSTableScan(sql); // force/ignore index sql = String.format("explain simple select *,(select 1 from %s force index(%s) limit 1) from %s", tb1, colIdxA, @@ -120,7 +129,7 @@ public void testExplain() throws SQLException { checkOSSTableScanAndLogicalView(sql); sql = APHINT + String.format("explain simple select *,(select 1 from %s force index(%s) limit 1) from %s", tb1, colIdxA, tb2); - checkAllOSSTableScan(sql); + checkOSSTableScanAndLogicalView(sql); sql = String.format("explain simple select *,(select 1 from %s force index(%s) limit 1) from %s force index(%s)", @@ -147,11 +156,11 @@ public void testExplain() throws SQLException { sql = APHINT + String.format( "explain simple select *,(select 1 from %s force index(%s) limit 1) from %s ignore index(idx_c)", tb1, colIdxA, tb2); - checkAllOSSTableScan(sql); + checkOSSTableScanAndLogicalView(sql); sql = APHINT + String.format( "explain simple select *,(select 1 from %s limit 1) from %s ignore index(idx_c)", tb1, tb2); - checkAllOSSTableScan(sql); + checkNoOSSTableScan(sql); sql = APHINT + String.format( "explain simple select *,(select 1 from %s ignore index(%s) limit 1) from %s ignore index(idx_c)", tb1, colIdxA, tb2); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/sequence/SequenceNameTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/sequence/SequenceNameTest.java new file mode 100644 index 000000000..bfa16d792 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/sequence/SequenceNameTest.java @@ -0,0 +1,22 @@ +package com.alibaba.polardbx.qatest.sequence; + +import com.alibaba.polardbx.qatest.DDLBaseNewDBTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Test; + +public class SequenceNameTest extends DDLBaseNewDBTestCase { + + @Test + public void testCreateSequenceWithLongSeqName() { + String sql = + "create sequence aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggg2 start with 100"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = + "alter sequence aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggg2 start with 200"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + + sql = "drop sequence aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggg2"; + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/AccurateInformationSchemaTablesTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/AccurateInformationSchemaTablesTest.java new file mode 100644 index 000000000..355714fca --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/AccurateInformationSchemaTablesTest.java @@ -0,0 +1,195 @@ +package com.alibaba.polardbx.qatest.statistic; + +import com.alibaba.polardbx.qatest.BaseTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class AccurateInformationSchemaTablesTest extends BaseTestCase { + private final Connection polarxConnection = getPolardbxConnection(); + + @Test + public void testDrdsShardingTable() throws SQLException { + String db = "testDrdsShardingTable_db"; + String tb = "testDrdsShardingTable_tb"; + String gsi = "testDrdsShardingTable_gsi"; + try { + String createSql = "CREATE DATABASE IF NOT EXISTS " + db + ";\n" + + "USE " + db + ";\n" + + "CREATE TABLE IF NOT EXISTS " + db + "." + tb + "(\n" + + " id int auto_increment,\n" + + " name varchar(20),\n" + + " PRIMARY KEY (id),\n" + + " INDEX local_index(name),\n" + + " GLOBAL INDEX " + gsi + " (name) dbpartition by hash(name)\n" + + ") dbpartition by hash(id);\n"; + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + JdbcUtil.executeUpdateSuccess(polarxConnection, createSql); + prepareData(db, tb); + verify(db, tb, gsi); + } finally { + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + } + } + + @Test + public void testDrdsSingleTable() throws SQLException { + String db = "testDrdsSingleTable_db"; + String tb = "testDrdsSingleTable_tb"; + try { + String createSql = "CREATE DATABASE IF NOT EXISTS " + db + ";\n" + + "USE " + db + ";\n" + + "CREATE TABLE IF NOT EXISTS " + db + "." + tb + "(\n" + + " id int auto_increment,\n" + + " name varchar(20),\n" + + " PRIMARY KEY (id),\n" + + " INDEX local_index(name)\n" + + ");\n"; + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + JdbcUtil.executeUpdateSuccess(polarxConnection, createSql); + prepareData(db, tb); + verify(db, tb, null); + } finally { + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + } + } + + @Test + public void testDrdsBroadcastTable() throws SQLException { + String db = "testDrdsBroadcastTable_db"; + String tb = "testDrdsBroadcastTable_tb"; + try { + String createSql = "CREATE DATABASE IF NOT EXISTS " + db + ";\n" + + "USE " + db + ";\n" + + "CREATE TABLE IF NOT EXISTS " + db + "." + tb + "(\n" + + " id int auto_increment,\n" + + " name varchar(20),\n" + + " PRIMARY KEY (id),\n" + + " INDEX local_index(name)\n" + + ") BROADCAST;\n"; + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + JdbcUtil.executeUpdateSuccess(polarxConnection, createSql); + prepareData(db, tb); + verify(db, tb, null); + } finally { + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + } + } + + @Test + public void testAutoShardingTable() throws SQLException { + String db = "testAutoShardingTable_db"; + String tb = "testAutoShardingTable_tb"; + String gsi = "testAutoShardingTable_gsi"; + try { + String createSql = "CREATE DATABASE IF NOT EXISTS " + db + " mode = auto;\n" + + "USE " + db + ";\n" + + "CREATE TABLE IF NOT EXISTS " + db + "." + tb + "(\n" + + " id int auto_increment,\n" + + " name varchar(20),\n" + + " PRIMARY KEY (id),\n" + + " LOCAL INDEX local_index(name),\n" + + " GLOBAL INDEX " + gsi + " (name) partition by key(name)\n" + + ") partition by key(id);\n"; + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + JdbcUtil.executeUpdateSuccess(polarxConnection, createSql); + prepareData(db, tb); + verify(db, tb, gsi); + } finally { + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + } + } + + @Test + public void testAutoSingleTable() throws SQLException { + String db = "testAutoSingleTable_db"; + String tb = "testAutoSingleTable_tb"; + try { + String createSql = "CREATE DATABASE IF NOT EXISTS " + db + " mode = auto;\n" + + "USE " + db + ";\n" + + "CREATE TABLE IF NOT EXISTS " + db + "." + tb + "(\n" + + " id int auto_increment,\n" + + " name varchar(20),\n" + + " PRIMARY KEY (id),\n" + + " LOCAL INDEX local_index(name)\n" + + ") SINGLE;\n"; + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + JdbcUtil.executeUpdateSuccess(polarxConnection, createSql); + prepareData(db, tb); + verify(db, tb, null); + } finally { + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + } + } + + @Test + public void testAutoBroadcastTable() throws SQLException { + String db = "testAutoBroadcastTable_db"; + String tb = "testAutoBroadcastTable_tb"; + try { + String createSql = "CREATE DATABASE IF NOT EXISTS " + db + " mode = auto;\n" + + "USE " + db + ";\n" + + "CREATE TABLE IF NOT EXISTS " + db + "." + tb + "(\n" + + " id int auto_increment,\n" + + " name varchar(20),\n" + + " PRIMARY KEY (id),\n" + + " LOCAL INDEX local_index(name)\n" + + ") BROADCAST;\n"; + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + JdbcUtil.executeUpdateSuccess(polarxConnection, createSql); + prepareData(db, tb); + verify(db, tb, null); + } finally { + JdbcUtil.executeUpdateSuccess(polarxConnection, "DROP DATABASE IF EXISTS " + db); + } + } + + private void prepareData(String db, String tb) { + StringBuilder insertSql = new StringBuilder("INSERT INTO " + db + "." + tb + " VALUES "); + for (int i = 0; i < 63; i++) { + insertSql.append("(null, SUBSTRING(MD5(RAND()), 1, 10)),"); + } + insertSql.append("(null, SUBSTRING(MD5(RAND()), 1, 10))"); + for (int i = 0; i < 20; i++) { + JdbcUtil.executeSuccess(polarxConnection, insertSql.toString()); + } + } + + private void verify(String db, String tb, String gsi) throws SQLException { + JdbcUtil.executeUpdateSuccess(polarxConnection, "analyze table " + tb); + String polarxSql = "select table_rows, data_length, index_length, data_free from information_schema.tables " + + "where table_schema = '" + db + "' and table_name = '" + tb + "'"; + Stat primaryStat = new Stat(); + ResultSet rs = JdbcUtil.executeQuerySuccess(polarxConnection, polarxSql); + if (rs.next()) { + primaryStat.tableRows = rs.getLong(1); + primaryStat.dataLength = rs.getLong(2); + primaryStat.indexLength = rs.getLong(3); + primaryStat.dataFree = rs.getLong(4); + } + Assert.assertTrue(primaryStat.tableRows > 0); + Assert.assertTrue(primaryStat.dataLength > 0); + Assert.assertTrue(primaryStat.indexLength > 0); + + if (null != gsi) { + String gsiSql = "select SIZE_IN_MB from information_schema.global_indexes " + + "where schema = '" + db + "' and table = '" + tb + "' and key_name = '" + gsi + "'"; + rs = JdbcUtil.executeQuerySuccess(polarxConnection, gsiSql); + if (rs.next()) { + double gsiSize = rs.getDouble(1); + Assert.assertTrue(gsiSize > 0); + } + } + } + + private static class Stat { + public long tableRows = 0; + public long dataLength = 0; + public long indexLength = 0; + public long dataFree = 0; + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticCostModelTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticCostModelTest.java index d619f8b7f..5235ee3f3 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticCostModelTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticCostModelTest.java @@ -73,17 +73,27 @@ public void commonAfter() throws SQLException { } @Test - public void testCostModel() throws SQLException, IOException { + public void testCostModel() throws SQLException, IOException, InterruptedException { testInside(); } - public void testInside() throws SQLException, IOException { + public void testInside() throws SQLException, IOException, InterruptedException { if (checkStruct.sql.isEmpty()) { return; } log.info(checkStruct.sql); log.info("link: xx.xx(" + checkStruct.taskLineInfo() + ")"); try (Connection c = getPolardbxConnection()) { + // prepare global env + if (checkStruct.globalEnvSetCommands != null) { + for (String setCommand : checkStruct.globalEnvSetCommands) { + if (StringUtils.isNotEmpty(setCommand)) { + c.createStatement().execute(setCommand); + } + } + Thread.sleep(3000L); + } + // prepare catalog for (String buildCommand : checkStruct.catalogBuildCommands) { c.createStatement().execute(buildCommand); @@ -304,6 +314,7 @@ static class CheckStruct { String sql; Map statisticTraceMap; String plan; + String[] globalEnvSetCommands; String[] envSetCommands; String[] catalogBuildCommands; String detailPlan; @@ -326,6 +337,7 @@ public void decodeCatalog(String catalog) throws IOException { return; } + List globalSetCommands = Lists.newLinkedList(); List setCommands = Lists.newLinkedList(); List buildCommands = Lists.newLinkedList(); @@ -343,11 +355,14 @@ public void decodeCatalog(String catalog) throws IOException { } else if (line.startsWith("reload statistics")) { } else if (line.startsWith("set session ")) { setCommands.add(originLine); + } else if (line.startsWith("set global ")) { + globalSetCommands.add(originLine); } else { buildCommands.add(originLine); } } + globalEnvSetCommands = globalSetCommands.toArray(new String[0]); envSetCommands = setCommands.toArray(new String[0]); catalogBuildCommands = buildCommands.toArray(new String[0]); Assert.assertTrue(schema != null); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticsCostModelDumpIgnoreTraceTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticsCostModelDumpIgnoreTraceTest.java index ab7880b23..8f9c58bdc 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticsCostModelDumpIgnoreTraceTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticsCostModelDumpIgnoreTraceTest.java @@ -36,20 +36,24 @@ public StatisticsCostModelDumpIgnoreTraceTest(String filePath) { } @Test - public void testCostModel() throws SQLException, IOException { + public void testCostModel() throws SQLException, IOException, InterruptedException { Collection testStructs = buildCheckStructFromFile(filePath); for (CheckStruct testStruct : testStructs) { checkStruct = testStruct; - testInside(); - try (Connection c = getPolardbxConnection()) { - for (String schema : checkStruct.getSchemaList()) { - JdbcUtil.executeSuccess(c, "drop database if exists " + schema); - } + try { + testInside(); } finally { - log.info("env file test result sum:" + trs); + try (Connection c = getPolardbxConnection()) { + for (String schema : checkStruct.getSchemaList()) { + JdbcUtil.executeSuccess(c, "drop database if exists " + schema); + } + } finally { + log.info("env file test result sum:" + trs); + } } + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticsCostModelSpecialCaseTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticsCostModelSpecialCaseTest.java index 6c75d128f..e006a8bf8 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticsCostModelSpecialCaseTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/StatisticsCostModelSpecialCaseTest.java @@ -33,7 +33,7 @@ public StatisticsCostModelSpecialCaseTest(String filePath) { } @Test - public void testCostModel() throws SQLException, IOException { + public void testCostModel() throws SQLException, IOException, InterruptedException { Collection testStructs = buildCheckStructFromFile(filePath); for (CheckStruct testStruct : testStructs) { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/collect/AccuracyQuantifier.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/collect/AccuracyQuantifier.java index ba813a29c..9e16dd9c7 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/collect/AccuracyQuantifier.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/statistic/collect/AccuracyQuantifier.java @@ -149,9 +149,12 @@ public static String judgeAndReport(String upLimitName) throws IOException { error.append(qt.name() + " error:" + eMsg); } AccuracyReport ar = qt.accuracyReportMap.get(upLimitName); + if (ar == null) { + continue; + } sb.append(qt.name()).append(":").append(ar.report()).append("\n"); } - // basline skip error report + // baseline skip error report if (!AccuracyQuantifier.baselineMode && error.length() > 0) { sb.append(error); Assert.fail(sb.toString()); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/syncTests/SetVariablesTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/syncTests/SetVariablesTest.java index b0ebac90c..6407e481a 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/syncTests/SetVariablesTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/syncTests/SetVariablesTest.java @@ -345,7 +345,6 @@ public void setCnGlobalVariableTest() throws Exception { variableAssignmentList.add(new AssignmentItem("enable_scale_out_all_phy_dml_log", "false", true)); variableAssignmentList.add(new AssignmentItem("enable_scale_out_feature", "true", true)); variableAssignmentList.add(new AssignmentItem("enable_scale_out_group_phy_dml_log", "true", true)); - variableAssignmentList.add(new AssignmentItem("enable_select_into_outfile", "false", true)); variableAssignmentList.add(new AssignmentItem("enable_semi_bka_join", "true", true)); variableAssignmentList.add(new AssignmentItem("enable_semi_hash_join", "true", true)); variableAssignmentList.add(new AssignmentItem("enable_semi_join_reorder", "true", true)); @@ -469,7 +468,6 @@ public void setCnGlobalVariableTest() throws Exception { variableAssignmentList.add(new AssignmentItem("plan_cache", "true", true)); variableAssignmentList.add(new AssignmentItem("plan_externalize_test", "TRUE", true)); variableAssignmentList.add(new AssignmentItem("polardbx_parallelism", "-1", true)); - variableAssignmentList.add(new AssignmentItem("polardbx_slave_instance_first", "true", true)); variableAssignmentList.add(new AssignmentItem("prefetch_shards", "-1", true)); // variableAssignmentList.add(new AssignmentItem("pure_async_ddl_mode", "false", true)); variableAssignmentList.add(new AssignmentItem("purge_trans_before", "604801", true)); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/HandleTrxErrorTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/HandleTrxErrorTest.java index 270483fb7..295dd64ec 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/HandleTrxErrorTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/HandleTrxErrorTest.java @@ -158,6 +158,7 @@ private Future updateTableInOtherConn(String tableName, boolean enableA return threadPool.submit(() -> { final Connection conn2 = this.getPolardbxConnection(); JdbcUtil.executeUpdateSuccess(conn2, "set enable_auto_savepoint = " + enableAutoSp); + JdbcUtil.executeUpdateSuccess(conn2, "set ENABLE_DML_GROUP_CONCURRENT_IN_TRANSACTION = false"); try { conn2.setAutoCommit(false); JdbcUtil.executeUpdate(conn2, "update " + tableName + " set a = 100"); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/SyncPointTrxTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/SyncPointTrxTest.java new file mode 100644 index 000000000..c2014f99f --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/SyncPointTrxTest.java @@ -0,0 +1,45 @@ +package com.alibaba.polardbx.qatest.transaction; + +import com.alibaba.polardbx.qatest.CrudBasedLockTestCase; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class SyncPointTrxTest extends CrudBasedLockTestCase { + final private Connection metaDbConn = getMetaConnection(); + final private Connection polarxConn = getPolardbxConnection(); + final private static String QUERY_SYNC_POINT_META_COUNT = "select count(0) from cdc_sync_point_meta"; + + @Test + public void test() throws SQLException, InterruptedException { + if (isMySQL80()) { + return; + } + JdbcUtil.executeUpdateSuccess(tddlConnection, "set global enable_polarx_sync_point = true"); + Thread.sleep(1000); + ResultSet rs = JdbcUtil.executeQuerySuccess(metaDbConn, QUERY_SYNC_POINT_META_COUNT); + Assert.assertTrue("Not found count of sync point meta", rs.next()); + long before = rs.getLong(1); + rs.close(); + + triggerSyncPoint(); + triggerSyncPoint(); + + rs = JdbcUtil.executeQuerySuccess(metaDbConn, QUERY_SYNC_POINT_META_COUNT); + Assert.assertTrue("Not found count of sync point meta", rs.next()); + long after = rs.getLong(1); + Assert.assertTrue(after > before); + } + + private void triggerSyncPoint() throws SQLException { + ResultSet rs = JdbcUtil.executeQuerySuccess(polarxConn, + "call polardbx.trigger_sync_point_trx()"); + Assert.assertTrue("Not found result of sync point trigger", rs.next()); + String result = rs.getString(1); + Assert.assertEquals("OK", result); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/TransactionViewTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/TransactionViewTest.java new file mode 100644 index 000000000..fb542d3de --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/TransactionViewTest.java @@ -0,0 +1,89 @@ +package com.alibaba.polardbx.qatest.transaction; + +import com.alibaba.polardbx.qatest.ReadBaseTestCase; +import com.alibaba.polardbx.qatest.util.ConnectionManager; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class TransactionViewTest extends ReadBaseTestCase { + private static final String SCHEMA_NAME = "TransactionViewTest_db"; + private static final String CREATE_DB = "CREATE DATABASE if not exists " + SCHEMA_NAME + " mode=auto"; + private static final String DROP_DB = "DROP DATABASE if exists " + SCHEMA_NAME; + private static final String TABLE_NAME = "TransactionViewTest_tb"; + private static final String CREATE_TABLE = "create table if not exists " + TABLE_NAME + + "(id int primary key) partition by key(id)"; + private static final String INSERT_DATA = "insert into " + TABLE_NAME + " values (0), (1), (2)"; + private static final String SELECT_INNODB_TRX = + "select count(0) from information_schema.innodb_trx where trx_id = '%s'"; + private static final String SELECT_INNODB_LOCKS = + "select count(0) from information_schema.innodb_locks where lock_table like '%%%s%%'"; + private static final String SELECT_INNODB_LOCK_WAITS = + "select count(0) from information_schema.innodb_lock_waits where blocking_trx_id = '%s'"; + + @Before + public void before() { + JdbcUtil.executeUpdate(tddlConnection, CREATE_DB); + JdbcUtil.executeUpdate(tddlConnection, "use " + SCHEMA_NAME); + JdbcUtil.executeUpdate(tddlConnection, CREATE_TABLE); + JdbcUtil.executeUpdate(tddlConnection, INSERT_DATA); + } + + @After + public void after() { + JdbcUtil.executeUpdate(tddlConnection, DROP_DB); + } + + @Test + public void testSimple() throws SQLException, InterruptedException { + final String sql = "select * from " + TABLE_NAME + " where id = 0 for update"; + + JdbcUtil.executeUpdate(tddlConnection, "begin"); + JdbcUtil.executeQuerySuccess(tddlConnection, sql); + + String trxId; + ResultSet rs = JdbcUtil.executeQuerySuccess(tddlConnection, "select current_trans_id()"); + Assert.assertTrue(rs.next()); + trxId = rs.getString(1); + + rs = JdbcUtil.executeQuerySuccess(tddlConnection, String.format(SELECT_INNODB_TRX, trxId)); + Assert.assertTrue(rs.next()); + Assert.assertTrue(rs.getLong(1) > 0); + + new Thread(() -> { + try (Connection conn = ConnectionManager.newPolarDBXConnection0()) { + JdbcUtil.executeUpdate(conn, "use " + SCHEMA_NAME); + System.out.println("trx 2 starts."); + JdbcUtil.executeQuerySuccess(conn, sql); + JdbcUtil.executeUpdate(conn, "rollback"); + System.out.println("trx 2 ends."); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + }).start(); + + int retry = 0; + boolean success = false; + do { + Thread.sleep(1000); + rs = JdbcUtil.executeQuerySuccess(tddlConnection, String.format(SELECT_INNODB_LOCKS, TABLE_NAME)); + if (rs.next() && rs.getLong(1) > 0) { + rs = JdbcUtil.executeQuerySuccess(tddlConnection, String.format(SELECT_INNODB_LOCK_WAITS, trxId)); + Assert.assertTrue(rs.next()); + Assert.assertTrue(rs.getLong(1) > 0); + success = true; + break; + } + } while (retry++ < 10); + Assert.assertTrue(success); + + JdbcUtil.executeUpdate(tddlConnection, "rollback"); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATransactionFailureTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATransactionFailureTest.java index 7a74baae6..48216856e 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATransactionFailureTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATransactionFailureTest.java @@ -65,7 +65,7 @@ public static List prepare() throws SQLException { supportShareReadView = JdbcUtil.supportShareReadView(connection); } List ret = new ArrayList<>(); - String[] trxPolicy = {"XA", "TSO"}; + String[] trxPolicy = {"XA", "TSO", "ARCHIVE"}; String[] asyncCommit = {/*"TRUE",*/ "FALSE"}; for (String policy : trxPolicy) { for (String ac : asyncCommit) { @@ -140,11 +140,14 @@ public void testFailAfterPrimaryCommit() throws Throwable { } catch (Exception e) { Assert.fail(e.getMessage()); } + boolean exception = false; try { tddlConnection.commit(); } catch (Exception ex) { // ignore + exception = true; } + Assert.assertTrue(exception); mysqlConnection.commit(); tddlConnection.setAutoCommit(true); mysqlConnection.setAutoCommit(true); @@ -208,11 +211,14 @@ public void testFailDuringPrimaryCommit() throws Throwable { } catch (Exception e) { Assert.fail(e.getMessage()); } + boolean exception = false; try { tddlConnection.commit(); } catch (Exception ex) { // ignore + exception = true; } + Assert.assertTrue(exception); mysqlConnection.rollback(); // expect data to be rollbacked tddlConnection.setAutoCommit(true); mysqlConnection.setAutoCommit(true); @@ -271,11 +277,14 @@ public void testFailBeforePrimaryCommit() throws Throwable { } catch (Exception e) { Assert.fail(e.getMessage()); } + boolean exception = false; try { tddlConnection.commit(); } catch (Exception ex) { // ignore + exception = true; } + Assert.assertTrue(exception); mysqlConnection.rollback(); // expect data to be rollbacked tddlConnection.setAutoCommit(true); mysqlConnection.setAutoCommit(true); @@ -318,11 +327,15 @@ public void testDelayBeforeWriteCommitLog() throws Exception { } catch (Exception e) { Assert.fail(e.getMessage()); } + boolean exception = false; try { tddlConnection.commit(); } catch (Exception ex) { // ignore + exception = true; } + // Should not cause commit fail in this case! + Assert.assertFalse(exception); mysqlConnection.commit(); // expect data to be committed tddlConnection.setAutoCommit(true); mysqlConnection.setAutoCommit(true); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATransactionStressTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATransactionStressTest.java index ce016bf60..98cf4eace 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATransactionStressTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATransactionStressTest.java @@ -22,6 +22,7 @@ import com.alibaba.polardbx.qatest.util.JdbcUtil; import com.google.common.collect.ImmutableList; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import java.sql.Connection; @@ -40,6 +41,7 @@ import static com.alibaba.polardbx.qatest.validator.PrepareData.tableDataPrepare; +@Ignore("2024-08-08 之后update由串行改成group并发执行物理sql,此用例预期内会概率出现死锁,忽略") public class XATransactionStressTest extends CrudBasedLockTestCase { private static final int MAX_DATA_SIZE = 1000; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATsoTransactionTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATsoTransactionTest.java index e2c5e0ab7..89ff8be17 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATsoTransactionTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transaction/XATsoTransactionTest.java @@ -231,7 +231,7 @@ public void testSessionVariable() throws SQLException, InterruptedException { long connId = rs.getLong("PROCESS_ID"); if (connId == connectionId) { String type = rs.getString("TYPE"); - Assert.assertTrue(type.equalsIgnoreCase("XA_TSO")); + Assert.assertTrue(type.equalsIgnoreCase("XATSO")); } } // commit diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transfer/AllTypesTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transfer/AllTypesTest.java new file mode 100644 index 000000000..f8cf00633 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transfer/AllTypesTest.java @@ -0,0 +1,96 @@ +package com.alibaba.polardbx.qatest.transfer; + +import com.alibaba.polardbx.qatest.constant.ConfigConstant; +import com.alibaba.polardbx.qatest.util.ConnectionManager; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.alibaba.polardbx.qatest.util.PropertiesUtil; +import com.alibaba.polardbx.transfer.Runner; +import com.alibaba.polardbx.transfer.config.TomlConfig; +import com.alibaba.polardbx.transfer.plugin.BasePlugin; +import com.alibaba.polardbx.transfer.utils.Utils; +import com.moandjiezana.toml.TomlWriter; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.sql.Connection; + +public class AllTypesTest { + private final String path = ConfigConstant.RESOURCE_PATH + "all_types_test.toml"; + + @Test + public void allTypesTest() throws Exception { + prepareConfig(); + TomlConfig.getInstance().init(path); + try (Connection connection = ConnectionManager.newPolarDBXConnection0()) { + JdbcUtil.executeUpdate(connection, "drop database if exists all_types_test"); + JdbcUtil.executeUpdate(connection, "create database all_types_test mode=auto"); + } + // Prepare transfer table. + Utils.prepare(); + + // Run transfer test. + Runner.runAllPlugins(); + + if (BasePlugin.success()) { + System.out.println("All types test success."); + } else { + throw new RuntimeException("All types test failed."); + } + } + + private void prepareConfig() throws IOException { + // Delete old file if exists. + try { + Files.delete(Paths.get(path)); + } catch (NoSuchFileException ex) { + // ignore. + } + // Create new config file. + AllTypesConfig config = new AllTypesConfig(); + config.dsn = + PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_USER) + + ":" + + PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_PASSWORD) + + "@tcp(" + + PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_ADDRESS) + + ":" + + PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_PORT) + + ")/all_types_test"; + config.timeout = PropertiesUtil.transferTestTime * 60; + config.threads = PropertiesUtil.allTypesTestPrepareThreads; + config.big_column = PropertiesUtil.allTypesTestBigColumn; + config.row_count = PropertiesUtil.transferRowCount; + config.conn_properties = PropertiesUtil.getConnectionProperties(); + TomlWriter writer = new TomlWriter(); + writer.write(config, new File(path)); + } + + private static class AllTypesConfig { + String dsn; + String conn_properties; + String test_type = "all-types-test"; + String runmode = "local"; + long row_count = 10000; + String create_table_suffix = "PARTITION BY KEY(id) PARTITIONS 16"; + long report_interval = 5; + long timeout; + long threads = 16; + boolean big_column = false; + WriteOnly write_only = new WriteOnly(); + CheckColumnar check_columnar = new CheckColumnar(); + } + + private static class WriteOnly { + boolean enabled = true; + long threads = 5; + } + + private static class CheckColumnar { + boolean enabled = true; + long threads = 1; + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transfer/TransferTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transfer/TransferTest.java new file mode 100644 index 000000000..24bb74d9d --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/transfer/TransferTest.java @@ -0,0 +1,133 @@ +package com.alibaba.polardbx.qatest.transfer; + +import com.alibaba.polardbx.qatest.constant.ConfigConstant; +import com.alibaba.polardbx.qatest.util.ConnectionManager; +import com.alibaba.polardbx.qatest.util.JdbcUtil; +import com.alibaba.polardbx.qatest.util.PropertiesUtil; +import com.alibaba.polardbx.transfer.Runner; +import com.alibaba.polardbx.transfer.config.TomlConfig; +import com.alibaba.polardbx.transfer.plugin.BasePlugin; +import com.alibaba.polardbx.transfer.utils.Utils; +import com.moandjiezana.toml.TomlWriter; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.sql.Connection; + +public class TransferTest { + private final String path = ConfigConstant.RESOURCE_PATH + "transfer_test.toml"; + + @Test + public void transferTest() throws Exception { + try (Connection connection = ConnectionManager.newPolarDBXConnection0()) { + JdbcUtil.executeUpdate(connection, "drop database if exists transfer_test"); + JdbcUtil.executeUpdate(connection, "create database transfer_test mode=auto"); + } + prepareConfig(); + TomlConfig.getInstance().init(path); + + // Prepare transfer table. + Utils.prepare(); + + // Run transfer test. + Runner.runAllPlugins(); + + if (BasePlugin.success()) { + System.out.println("Transfer test success."); + } else { + throw new RuntimeException("Transfer test failed."); + } + } + + private void prepareConfig() throws IOException { + // Delete old file if exists. + try { + Files.delete(Paths.get(path)); + } catch (NoSuchFileException ex) { + // ignore. + } + // Create new config file. + TransferConfig config = new TransferConfig(); + config.dsn = + PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_USER) + + ":" + + PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_PASSWORD) + + "@tcp(" + + PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_ADDRESS) + + ":" + + PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_PORT) + + ")/transfer_test"; + config.timeout = PropertiesUtil.transferTestTime * 60; + config.replica_read.replica_dsn = config.dsn; + config.replica_flashback_query.replica_dsn = config.dsn; + config.row_count = PropertiesUtil.transferRowCount; + config.conn_properties = PropertiesUtil.getConnectionProperties(); + TomlWriter writer = new TomlWriter(); + writer.write(config, new File(path)); + } + + private static class TransferConfig { + String dsn; + String conn_properties; + String runmode = "local"; + long row_count = 100; + long initial_balance = 1000; + String create_table_suffix = "PARTITION BY KEY(id) PARTITIONS 16"; + long report_interval = 5; + long timeout; + TransferSimple transfer_simple = new TransferSimple(); + CheckBalance check_balance = new CheckBalance(); + ReplicaRead replica_read = new ReplicaRead(); + FlashbackQuery flashback_query = new FlashbackQuery(); + ReplicaFlashbackQuery replica_flashback_query = new ReplicaFlashbackQuery(); + CheckCdc check_cdc = new CheckCdc(); + } + + private static class TransferSimple { + boolean enabled = true; + long threads = 5; + boolean inject_commit_failure = false; + double inject_commit_failure_prob = 0.1; + } + + private static class CheckBalance { + boolean enabled = true; + long threads = 2; + String before_check_stmt = "set transaction_policy = TSO"; + } + + private static class ReplicaRead { + boolean enabled = false; + long threads = 2; + String replica_read_hint = "/*+TDDL:SLAVE()*/"; + String replica_dsn; + String session_var = ""; + boolean replica_strong_consistency = true; + } + + private static class FlashbackQuery { + boolean enabled = false; + long threads = 2; + long min_seconds = 10; + long max_seconds = 20; + } + + private static class ReplicaFlashbackQuery { + boolean enabled = false; + long threads = 2; + long min_seconds = 10; + long max_seconds = 20; + String replica_read_hint = "/*+TDDL:SLAVE()*/"; + String replica_dsn; + } + + private static class CheckCdc { + boolean enabled = false; + long threads = 2; + String replica_dsn; + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlConcurrentDdlTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlConcurrentDdlTest.java index e555aa118..92fd6e12d 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlConcurrentDdlTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlConcurrentDdlTest.java @@ -21,7 +21,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; -import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.alterTableViaTwoPhaseDdl; +import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.alterTableViaJdbc; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkIfExecuteTwoPhaseDdl; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkPhyDdlStatus; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkTableStatus; @@ -65,7 +65,7 @@ public boolean usingNewPartDb() { // two_phase_ddl_test1.online_ddl_pause_concurrent.{0..3}, 16 * 100W @Test - public void testConcurrentAlterTableAddDdlPauseBeforePrepare() throws SQLException, InterruptedException { + public void testConcurrentAlterTableAddDdlPauseBeforePrepare() throws Exception { String schemaName = "two_phase_ddl_test1"; List tableNames = new ArrayList<>(); List connections = new ArrayList<>(); @@ -111,7 +111,7 @@ public void testConcurrentAlterTableAddDdlPauseBeforePrepare() throws SQLExcepti // two_phase_ddl_test1.modify_column_pause_concurrent.{0..3}, 16 * 100W @Test - public void testConcurrentAlterTableModifyColumnDdlPauseBeforePrepare() throws SQLException, InterruptedException { + public void testConcurrentAlterTableModifyColumnDdlPauseBeforePrepare() throws Exception { String schemaName = "two_phase_ddl_test1"; List tableNames = new ArrayList<>(); List connections = new ArrayList<>(); @@ -131,7 +131,7 @@ public void testConcurrentAlterTableModifyColumnDdlPauseBeforePrepare() throws S for (int i = 0; i < concurrent; i++) { String table = tableNames.get(i); String recoverDdl = String.format("alter table %s modify column c varchar(32)", table); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, table, recoverDdl); + alterTableViaJdbc(tddlConnection, schemaName, table, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(16)", table); int finalI = i; futures.add( @@ -161,7 +161,7 @@ public void runTestCaseOnOneTable(Connection tddlConnection, String schemaName, String enableTwoPhaseDdlHint = String.format("/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,PURE_ASYNC_DDL_MODE=true)*/"); String msg = String.format("table: %s, ddl: %s", table, ddl); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, table, enableTwoPhaseDdlHint + ddl); + alterTableViaJdbc(tddlConnection, schemaName, table, enableTwoPhaseDdlHint + ddl); Long jobId = getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 4; Thread.sleep(sleepTime * 1000); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlDrdsOnlineDdlPauseTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlDrdsOnlineDdlPauseTest.java index 5770921bc..31be0447c 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlDrdsOnlineDdlPauseTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlDrdsOnlineDdlPauseTest.java @@ -16,7 +16,7 @@ import java.util.Arrays; import java.util.List; -import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.alterTableViaTwoPhaseDdl; +import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.alterTableViaJdbc; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkIfCompleteFully; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkIfExecuteTwoPhaseDdl; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkIfRollbackFully; @@ -77,7 +77,7 @@ public void testAlterTableAddDdlPauseBeforePrepare() throws SQLException, Interr String columName = randomTableName("column", 2); String ddl = String.format("alter table %s add column %s int, ALGORITHM=INPLACE", mytable, columName); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -130,7 +130,7 @@ public void testAlterTableAddDdlPauseThenRandomKillBeforePrepareToRollback() String columName = randomTableName("column", 3); String ddl = String.format("alter table %s add column %s int, ALGORITHM=INPLACE", mytable, columName); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -192,7 +192,7 @@ public void testAlterTableAddDdlPauseThenRollbackBeforePrepare() throws SQLExcep String columName = randomTableName("column", 4); String ddl = String.format("alter table %s add column %s int, ALGORITHM=INPLACE", mytable, columName); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -251,7 +251,7 @@ public void testAlterTableAddDdlPauseThenRandomKillBeforeCommitToContinueAndComp String columName = randomTableName("column", 3); String ddl = String.format("alter table %s add column %s int, ALGORITHM=INPLACE", mytable, columName); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlDrdsPauseModifyColumnTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlDrdsPauseModifyColumnTest.java index ce3a931dd..98aa6db23 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlDrdsPauseModifyColumnTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlDrdsPauseModifyColumnTest.java @@ -18,7 +18,7 @@ import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DataManipulateUtil.prepareData; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DataManipulateUtil.prepareDataForDrds; -import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.alterTableViaTwoPhaseDdl; +import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.alterTableViaJdbc; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkIfCompleteFully; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkIfExecuteTwoPhaseDdl; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkIfRollbackFully; @@ -76,10 +76,10 @@ public void testAlterTableModifyDdlPauseBeforePrepare() throws SQLException, Int String enableTwoPhaseDdlHint = String.format("/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,PURE_ASYNC_DDL_MODE=true)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(16)", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 500); @@ -133,10 +133,10 @@ public void testAlterTableModifyDdlPauseThenRandomKillBeforePrepareToRollback() String enableTwoPhaseDdlHint = String.format("/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,PURE_ASYNC_DDL_MODE=true)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(16)", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 500); @@ -202,10 +202,10 @@ public void testAlterTableModifyDdlPauseThenRollbackBeforePrepare() throws SQLEx String enableTwoPhaseDdlHint = String.format("/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,PURE_ASYNC_DDL_MODE=true)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(16)", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 500); @@ -266,10 +266,10 @@ public void testAlterTableModifyDdlPauseThenRandomKillBeforeCommitToContinueAndC String.format( "/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,PURE_ASYNC_DDL_MODE=true,MULTI_PHASE_COMMIT_DELAY=20)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(16)", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 500); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlOnlineLogApplyTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlOnlineLogApplyTest.java index deb61a9ed..952fee9c2 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlOnlineLogApplyTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlOnlineLogApplyTest.java @@ -71,10 +71,10 @@ public boolean usingNewPartDb() { // two_phase_ddl_test1.online_log_apply, 1 * 640W @Test - public void test01AlterTableAddColumn() throws SQLException, InterruptedException { + public void test01AlterTableAddColumn() throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "online_log_apply"; - // prepare data + /* prepare data */ prepareData(tddlConnection, schemaName, mytable, 64_000_00, DataManipulateUtil.TABLE_TYPE.SINGLE_TABLE); List beforeCheckSum = checkData(tddlConnection, schemaName, mytable); // @@ -84,7 +84,7 @@ public void test01AlterTableAddColumn() throws SQLException, InterruptedExceptio String columName = randomTableName("column", 2); String ddl = String.format("alter table %s add column %s int, ALGORITHM=INPLACE", mytable, columName); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); log.info("alter table stmt emmitted: " + enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 4; @@ -144,7 +144,7 @@ public void test01AlterTableAddColumn() throws SQLException, InterruptedExceptio // two_phase_ddl_test1.online_log_apply, 1 * 640W @Test - public void test11AlterTableAddIndex() throws SQLException, InterruptedException { + public void test11AlterTableAddIndex() throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "online_log_apply"; // prepare data @@ -157,7 +157,7 @@ public void test11AlterTableAddIndex() throws SQLException, InterruptedException String indexName = randomTableName("index", 4); String ddl = String.format("alter table %s add local index %s(a, b)", mytable, indexName); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); log.info("alter table stmt emmitted: " + enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 4; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseModifyColumnInplaceTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseModifyColumnInplaceTest.java index 591594b79..869a4a15f 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseModifyColumnInplaceTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseModifyColumnInplaceTest.java @@ -54,7 +54,7 @@ public boolean usingNewPartDb() { //two_phase_ddl_test1.modify_column_pause, 16 * 50W @Test - public void testAlterTableModifyInplacePauseBeforePrepare() throws SQLException, InterruptedException { + public void testAlterTableModifyInplacePauseBeforePrepare() throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "modify_column_pause"; // prepare data @@ -64,10 +64,10 @@ public void testAlterTableModifyInplacePauseBeforePrepare() throws SQLException, String.format( "/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,EMIT_PHY_DDL_DELAY=1,PURE_ASYNC_DDL_MODE=true)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(64)", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -112,7 +112,7 @@ public void testAlterTableModifyInplacePauseBeforePrepare() throws SQLException, //two_phase_ddl_test1.modify_column_pause, 16 * 50W @Test public void testAlterTableModifyInplacePauseThenRandomKillBeforePrepareToRollback() - throws SQLException, InterruptedException { + throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "modify_column_pause"; // prepare data @@ -122,10 +122,10 @@ public void testAlterTableModifyInplacePauseThenRandomKillBeforePrepareToRollbac String.format( "/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,EMIT_PHY_DDL_DELAY=1,PURE_ASYNC_DDL_MODE=true)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(64)", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -178,7 +178,7 @@ public void testAlterTableModifyInplacePauseThenRandomKillBeforePrepareToRollbac //two_phase_ddl_test1.modify_column_pause, 16 * 50W @Test - public void testAlterTableModifyInplacePauseThenRollbackBeforePrepare() throws SQLException, InterruptedException { + public void testAlterTableModifyInplacePauseThenRollbackBeforePrepare() throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "modify_column_pause"; // prepare data @@ -188,10 +188,10 @@ public void testAlterTableModifyInplacePauseThenRollbackBeforePrepare() throws S String.format( "/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,EMIT_PHY_DDL_DELAY=1,PURE_ASYNC_DDL_MODE=true)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(64)", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -242,7 +242,7 @@ public void testAlterTableModifyInplacePauseThenRollbackBeforePrepare() throws S //two_phase_ddl_test1.modify_column_pause, 16 * 50W @Test public void testAlterTableModifyInplacePauseThenRandomKillBeforeCommitToContinueAndCompensation() - throws SQLException, InterruptedException { + throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "modify_column_pause"; // prepare data @@ -252,10 +252,10 @@ public void testAlterTableModifyInplacePauseThenRandomKillBeforeCommitToContinue String.format( "/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,EMIT_PHY_DDL_DELAY=1,PURE_ASYNC_DDL_MODE=true,MULTI_PHASE_COMMIT_DELAY=20)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(64)", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseModifyColumnTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseModifyColumnTest.java index fa6c5e407..8a05edb66 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseModifyColumnTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseModifyColumnTest.java @@ -54,7 +54,7 @@ public boolean usingNewPartDb() { //two_phase_ddl_test1.modify_column_pause, 16 * 50W @Test - public void testAlterTableModifyDdlPauseBeforePrepare() throws SQLException, InterruptedException { + public void testAlterTableModifyDdlPauseBeforePrepare() throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "modify_column_pause"; // prepare data @@ -63,10 +63,10 @@ public void testAlterTableModifyDdlPauseBeforePrepare() throws SQLException, Int String enableTwoPhaseDdlHint = String.format("/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,PURE_ASYNC_DDL_MODE=true)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(16);", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -111,7 +111,7 @@ public void testAlterTableModifyDdlPauseBeforePrepare() throws SQLException, Int //two_phase_ddl_test1.modify_column_pause, 16 * 50W @Test public void testAlterTableModifyDdlPauseThenRandomKillBeforePrepareToRollback() - throws SQLException, InterruptedException { + throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "modify_column_pause"; // prepare data @@ -120,10 +120,10 @@ public void testAlterTableModifyDdlPauseThenRandomKillBeforePrepareToRollback() String enableTwoPhaseDdlHint = String.format("/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,PURE_ASYNC_DDL_MODE=true)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(16)", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -176,7 +176,7 @@ public void testAlterTableModifyDdlPauseThenRandomKillBeforePrepareToRollback() //two_phase_ddl_test1.modify_column_pause, 16 * 50W @Test - public void testAlterTableModifyDdlPauseThenRollbackBeforePrepare() throws SQLException, InterruptedException { + public void testAlterTableModifyDdlPauseThenRollbackBeforePrepare() throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "modify_column_pause"; // prepare data @@ -185,10 +185,10 @@ public void testAlterTableModifyDdlPauseThenRollbackBeforePrepare() throws SQLEx String enableTwoPhaseDdlHint = String.format("/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,PURE_ASYNC_DDL_MODE=true)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(16)", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -239,7 +239,7 @@ public void testAlterTableModifyDdlPauseThenRollbackBeforePrepare() throws SQLEx //two_phase_ddl_test1.modify_column_pause, 16 * 50W @Test public void testAlterTableModifyDdlPauseThenRandomKillBeforeCommitToContinueAndCompensation() - throws SQLException, InterruptedException { + throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "modify_column_pause"; // prepare data @@ -249,10 +249,10 @@ public void testAlterTableModifyDdlPauseThenRandomKillBeforeCommitToContinueAndC String.format( "/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,PURE_ASYNC_DDL_MODE=true,MULTI_PHASE_COMMIT_DELAY=20)*/"); String recoverDdl = String.format("alter table %s modify column c varchar(32)", mytable); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, recoverDdl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(16)", mytable); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseOnlineDdlTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseOnlineDdlTest.java index d3a935404..48c6d7f36 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseOnlineDdlTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlPauseOnlineDdlTest.java @@ -54,7 +54,7 @@ public boolean usingNewPartDb() { //two_phase_ddl_test1.online_ddl_pause, 16 * 50W @Test - public void testAlterTableAddDdlPauseBeforePrepare() throws SQLException, InterruptedException { + public void testAlterTableAddDdlPauseBeforePrepare() throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "online_ddl_pause"; // prepare data @@ -65,7 +65,7 @@ public void testAlterTableAddDdlPauseBeforePrepare() throws SQLException, Interr String columName = randomTableName("column", 2); String ddl = String.format("alter table %s add column %s int, ALGORITHM=INPLACE", mytable, columName); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -106,7 +106,7 @@ public void testAlterTableAddDdlPauseBeforePrepare() throws SQLException, Interr @Test public void testAlterTableAddDdlPauseThenRandomKillBeforePrepareToRollback() - throws SQLException, InterruptedException { + throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "online_ddl_pause"; // prepare data @@ -117,7 +117,7 @@ public void testAlterTableAddDdlPauseThenRandomKillBeforePrepareToRollback() String columName = randomTableName("column", 3); String ddl = String.format("alter table %s add column %s int, ALGORITHM=INPLACE", mytable, columName); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -166,7 +166,7 @@ public void testAlterTableAddDdlPauseThenRandomKillBeforePrepareToRollback() //two_phase_ddl_test1.online_ddl_pause, 16 * 50W @Test - public void testAlterTableAddDdlPauseThenRollbackBeforePrepare() throws SQLException, InterruptedException { + public void testAlterTableAddDdlPauseThenRollbackBeforePrepare() throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "online_ddl_pause"; // prepare data @@ -177,7 +177,7 @@ public void testAlterTableAddDdlPauseThenRollbackBeforePrepare() throws SQLExcep String columName = randomTableName("column", 4); String ddl = String.format("alter table %s add column %s int, ALGORITHM=INPLACE", mytable, columName); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); @@ -225,7 +225,7 @@ public void testAlterTableAddDdlPauseThenRollbackBeforePrepare() throws SQLExcep //two_phase_ddl_test1.online_ddl_pause, 16 * 50W @Test public void testAlterTableAddDdlPauseThenRandomKillBeforeCommitToContinueAndCompensation() - throws SQLException, InterruptedException { + throws Exception { String schemaName = "two_phase_ddl_test1"; String mytable = schemaPrefix + "online_ddl_pause"; // prepare data @@ -237,7 +237,7 @@ public void testAlterTableAddDdlPauseThenRandomKillBeforeCommitToContinueAndComp String columName = randomTableName("column", 3); String ddl = String.format("alter table %s add column %s int, ALGORITHM=INPLACE", mytable, columName); String msg = String.format("table: %s, ddl: %s", mytable, ddl); - DdlStateCheckUtil.alterTableViaTwoPhaseDdl(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); + DdlStateCheckUtil.alterTableViaJdbc(tddlConnection, schemaName, mytable, enableTwoPhaseDdlHint + ddl); Long jobId = DdlStateCheckUtil.getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlSecondaryPartitionDdlTest.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlSecondaryPartitionDdlTest.java index 9b09a1fd2..255c212c0 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlSecondaryPartitionDdlTest.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlSecondaryPartitionDdlTest.java @@ -23,7 +23,7 @@ import java.util.concurrent.Future; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DataManipulateUtil.prepareData; -import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.alterTableViaTwoPhaseDdl; +import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.alterTableViaJdbc; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkIfExecuteTwoPhaseDdl; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkPhyDdlStatus; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DdlStateCheckUtil.checkTableStatus; @@ -66,7 +66,7 @@ public boolean usingNewPartDb() { //two_phase_ddl_test1.online_ddl_pause_subpart, 16 * 50W @Test - public void testConcurrentAlterTableAddDdlPauseBeforePrepare() throws SQLException, InterruptedException { + public void testConcurrentAlterTableAddDdlPauseBeforePrepare() throws Exception { String schemaName = "two_phase_ddl_test1"; List tableNames = new ArrayList<>(); List connections = new ArrayList<>(); @@ -113,7 +113,7 @@ public void testConcurrentAlterTableAddDdlPauseBeforePrepare() throws SQLExcepti //two_phase_ddl_test1.modify_column_pause_subpart, 16 * 50W @Test - public void testConcurrentAlterTableModifyColumnDdlPauseBeforePrepare() throws SQLException, InterruptedException { + public void testConcurrentAlterTableModifyColumnDdlPauseBeforePrepare() throws Exception { String schemaName = "two_phase_ddl_test1"; List tableNames = new ArrayList<>(); List connections = new ArrayList<>(); @@ -134,7 +134,7 @@ public void testConcurrentAlterTableModifyColumnDdlPauseBeforePrepare() throws S for (int i = 0; i < concurrent; i++) { String table = tableNames.get(i); String recoverDdl = String.format("alter table %s modify column c varchar(32)", table); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, table, recoverDdl); + alterTableViaJdbc(tddlConnection, schemaName, table, recoverDdl); String ddl = String.format("alter table %s modify column c varchar(16)", table); int finalI = i; futures.add( @@ -164,7 +164,7 @@ public void runTestCaseOnOneTable(Connection tddlConnection, String schemaName, String enableTwoPhaseDdlHint = String.format("/*+TDDL:CMD_EXTRA(ENABLE_DRDS_MULTI_PHASE_DDL=true,PURE_ASYNC_DDL_MODE=true)*/"); String msg = String.format("table: %s, ddl: %s", table, ddl); - alterTableViaTwoPhaseDdl(tddlConnection, schemaName, table, enableTwoPhaseDdlHint + ddl); + alterTableViaJdbc(tddlConnection, schemaName, table, enableTwoPhaseDdlHint + ddl); Long jobId = getDdlJobIdFromPattern(tddlConnection, ddl); int sleepTime = 1; Thread.sleep(sleepTime * 1000); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DataCheckUtil.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DataCheckUtil.java index df212cef9..4d0ba2ed8 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DataCheckUtil.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DataCheckUtil.java @@ -47,7 +47,7 @@ public static List checkData(Connection tddlConnection, String schemaNa JdbcUtil.getAllResult(JdbcUtil.executeQuery(calCheckSumSql2, tddlConnection)).get(0).stream() .map(o -> Integer.valueOf(o.toString())) .collect(Collectors.toList()); - log.info("finsh check data"); + log.info("finish check data"); checkSum1.addAll(checkSum2); return checkSum1; } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DataManipulateUtil.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DataManipulateUtil.java index e66806794..3e4013ed0 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DataManipulateUtil.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DataManipulateUtil.java @@ -17,11 +17,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import static com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils.DataCheckUtil.checkData; +import static com.alibaba.polardbx.qatest.util.JdbcUtil.dropTable; import static com.alibaba.polardbx.qatest.util.JdbcUtil.useDb; public class DataManipulateUtil { @@ -32,7 +34,8 @@ public enum TABLE_TYPE { SECONDARY_PARTITION_TABLE, PARTITION_TABLE, SINGLE_TABLE, - BROADCAST_TABLE + BROADCAST_TABLE, + SELF_DEF_TABLE } public static synchronized Connection getPolardbxConnection(String db) { @@ -49,18 +52,23 @@ public static synchronized Connection getPolardbxConnection(String db) { } public static void batchInsert(String dbName, String tableName, int tableRows, int threadNum) - throws InterruptedException, SQLException { + throws Exception { Long start = new Date().getTime(); List threads = new ArrayList<>(); List connections = new ArrayList<>(); Boolean fastMode = true; + ConcurrentLinkedDeque exceptions = new ConcurrentLinkedDeque<>(); for (int i = 0; i < threadNum; i++) { Connection tddlConnection = getPolardbxConnection(dbName); connections.add(tddlConnection); Thread thread = new Thread(() -> { - DataLoader dataLoader = - DataLoader.create(tddlConnection, tableName, new UniformDistributionDataGenerator()); - dataLoader.batchInsert(tableRows, fastMode); + try { + DataLoader dataLoader = + DataLoader.create(tddlConnection, tableName, new UniformDistributionDataGenerator()); + dataLoader.batchInsert(tableRows, fastMode); + }catch (Exception e){ + exceptions.add(e); + } }); threads.add(thread); thread.start(); @@ -73,32 +81,44 @@ public static void batchInsert(String dbName, String tableName, int tableRows, i for (Connection connection : connections) { connection.close(); } + if(exceptions.size() > 0) { + throw exceptions.poll(); + } Long end = new Date().getTime(); log.info("data loader cost " + (end - start) + " ms"); } - public static void prepareData(Connection tddlConnection, String schemaName, String mytable) throws SQLException { + public static void prepareData(Connection tddlConnection, String schemaName, String mytable) throws Exception { prepareData(tddlConnection, schemaName, mytable, 2_000_000, TABLE_TYPE.PARTITION_TABLE); } public static void prepareData(Connection tddlConnection, String schemaName, String mytable, int eachPartRows) - throws SQLException { + throws Exception { prepareData(tddlConnection, schemaName, mytable, eachPartRows, TABLE_TYPE.PARTITION_TABLE); } public static void prepareData(Connection tddlConnection, String schemaName, String mytable, int eachPartRows, - TABLE_TYPE tableType) - throws SQLException { - int partNum = 16; + TABLE_TYPE tableType) throws Exception { + prepareData(tddlConnection, schemaName, mytable, eachPartRows, null, 0, TABLE_TYPE.PARTITION_TABLE); + } + + public static void prepareData(Connection tddlConnection, String schemaName, String mytable, int eachPartRows, + String createTableStmt, int partNum, TABLE_TYPE tableType) + throws Exception { + if (partNum == 0) { + partNum = 16; + } log.info("start to prepare data..."); Long now = System.currentTimeMillis(); String sql = String.format("create database if not exists %s mode = auto", schemaName); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); sql = String.format("use %s", schemaName); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); - String createTableStmt = - "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" - + ") PARTITION BY HASH(a) PARTITIONS %d"; + if (createTableStmt == null) { + createTableStmt = + "create table if not exists " + " %s(a int NOT NULL AUTO_INCREMENT,b int, c varchar(32), PRIMARY KEY(a)" + + ") PARTITION BY HASH(a) PARTITIONS %d"; + } sql = String.format(createTableStmt, mytable, partNum); if (tableType == TABLE_TYPE.SECONDARY_PARTITION_TABLE) { int subPartNum = 4; @@ -130,12 +150,14 @@ public static void prepareData(Connection tddlConnection, String schemaName, Str int residueRows = totalRows - currRows; int threadNum = 8; int tableRows = residueRows / threadNum; - if (residueRows > 0) { - try { - batchInsert(schemaName, mytable, tableRows, threadNum); - } catch (Exception e) { - log.info(e.getMessage()); - throw new RuntimeException("fail to insert data into logical table"); + if (tableType != TABLE_TYPE.SELF_DEF_TABLE) { + if (residueRows > 0) { + try { + batchInsert(schemaName, mytable, tableRows, threadNum); + } catch (Exception e) { + log.info(e.getMessage()); + throw e; + } } } Long cost = System.currentTimeMillis() - now; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DdlStateCheckUtil.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DdlStateCheckUtil.java index 8f9b32f13..00b8e5994 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DdlStateCheckUtil.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/twoPhaseDdl/TwoPhaseDdlTestUtils/DdlStateCheckUtil.java @@ -1,21 +1,34 @@ package com.alibaba.polardbx.qatest.twoPhaseDdl.TwoPhaseDdlTestUtils; +import com.alibaba.druid.util.JdbcUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.utils.Assert; +import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; -import com.alibaba.polardbx.qatest.ConnectionWrap; -import com.alibaba.polardbx.qatest.ddl.auto.locality.LocalityTestCaseUtils.LocalitySingleTaskCaseTask; -import com.alibaba.polardbx.qatest.ddl.balancer.datagenerator.DataLoader; -import com.alibaba.polardbx.qatest.ddl.balancer.datagenerator.UniformDistributionDataGenerator; -import com.alibaba.polardbx.qatest.util.ConnectionManager; +import com.alibaba.polardbx.druid.DbType; +import com.alibaba.polardbx.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; +import com.alibaba.polardbx.druid.sql.parser.SQLParserUtils; +import com.alibaba.polardbx.druid.sql.parser.SQLStatementParser; +import com.alibaba.polardbx.druid.util.StringUtils; +import com.alibaba.polardbx.executor.ddl.job.task.backfill.LogicalTableGsiPkRangeBackfillTask; +import com.alibaba.polardbx.executor.ddl.job.task.gsi.AlterGsiAddLocalIndexTask; +import com.alibaba.polardbx.executor.ddl.newengine.DdlEngineDagExecutor; +import com.alibaba.polardbx.executor.ddl.newengine.utils.DdlHelper; +import com.alibaba.polardbx.qatest.ddl.auto.dal.CheckTableTest; import com.alibaba.polardbx.qatest.util.JdbcUtil; -import com.alibaba.polardbx.statistics.SQLRecorderLogger; +import com.google.common.collect.Lists; +import io.grpc.netty.shaded.io.netty.util.internal.StringUtil; import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import java.sql.Connection; +import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Date; +import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -24,8 +37,6 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -import static com.alibaba.polardbx.qatest.util.JdbcUtil.useDb; - public class DdlStateCheckUtil { private final static Logger LOG = LoggerFactory.getLogger(DdlStateCheckUtil.class); @@ -97,18 +108,242 @@ public static Map parseStatusText(String statusText) { public static Boolean waitTillDdlDone(Connection tddlConnection, Long jobId, String tableName) throws InterruptedException { + return waitTillDdlDone(tddlConnection, jobId, tableName, -1, false); + } + + public static Map collectTimeOfBackfillIdExecuteTime(Connection connection, Long jobId) { + return new HashMap<>(); + } + + public static Boolean checkIfContinueValid(Connection connection, Long jobId, List errMsg) { + String fetchExecutionTimeSql = + String.format("select task_id, backfill_ids, extra from metadb.backfill_sample_rows where job_id = %d", + jobId); + List> results = + JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(connection, fetchExecutionTimeSql)); + List msg = new ArrayList<>(); + Boolean checkOk = true; + for (List result : results) { + Long taskId = Long.valueOf(result.get(0).toString()); + String fetchSuccessRowCountSql = + String.format("select job_id, success_row_count from metadb.backfill_objects where task_id = %d", + taskId); + List> successRowCount = + JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(connection, fetchSuccessRowCountSql)); + Map successRowCountMap = new HashMap<>(); + for (List row : successRowCount) { + successRowCountMap.put(Long.valueOf(row.get(0).toString()), Long.valueOf(row.get(1).toString())); + } + String backfillIds = (String) result.get(1); + String executionTime = (String) result.get(2); + if (!checkIfContinueValid(taskId, backfillIds, executionTime, successRowCountMap, msg)) { + checkOk = false; + } + } + errMsg.add(StringUtil.join(",", msg).toString()); + return checkOk; + } + + public static Map parseExecutionTime(String executionTime) { + String executionTimeMapString = DdlHelper.decompress(executionTime); + Map executionTimeMap = + JSON.parseObject(executionTimeMapString, new HashMap().getClass()); + return executionTimeMap; + } + + public static Long fromExecutionTime(String executionTime) { + String newExecutionTime = executionTime.replace(":i", ""); + Long result = Long.parseLong(newExecutionTime); + if (!newExecutionTime.equalsIgnoreCase(executionTime)) { + result = result * -1; + } + return result; + } + + public static Boolean checkIfContinueValid(Long taskId, String backfillIds, String executionTime, + Map successRowCountMap, + List errMsg) { + final int EXCEPTION_COUNT = 10; + String[] executionTimeSeqs = executionTime.split("\n"); + Boolean result = true; + if (executionTimeSeqs.length >= 2) { + List backfillIdList = + Arrays.stream(backfillIds.split(",")).map(o -> Long.valueOf(o)).collect(Collectors.toList()); + String lastExecutionTime = executionTimeSeqs[executionTimeSeqs.length - 2]; + String thisExecutionTime = executionTimeSeqs[executionTimeSeqs.length - 1]; + Map lastExecutionTimeMap = parseExecutionTime(lastExecutionTime); + Map thisExecutionTimeMap = parseExecutionTime(thisExecutionTime); + int pausedBackfillIdIndex = 0; + Long backfillId; + Long beforeTotalTime = 0L; + Long afterTotalTime = 0L; + Long beforeTime = 0L; + Long afterTime = 0L; + int flag = 0; + for (; pausedBackfillIdIndex < backfillIdList.size(); pausedBackfillIdIndex++) { + backfillId = backfillIdList.get(pausedBackfillIdIndex); + if (lastExecutionTimeMap.containsKey(backfillId) && thisExecutionTimeMap.containsKey(backfillId)) { + beforeTime = fromExecutionTime(lastExecutionTimeMap.get(backfillId).toString()); + afterTime = fromExecutionTime(thisExecutionTimeMap.get(backfillId).toString()); + beforeTotalTime += beforeTime; + afterTotalTime += Math.abs(afterTime); + if (afterTime >= 0) { + errMsg.add( + String.format(" the execution time not passed idempotent test %d, after:before = %d:%d", + taskId, + afterTime, beforeTime)); + flag++; + } + } + if (!lastExecutionTimeMap.containsKey(backfillId)) { + break; + } + } + if (flag == 1) { + errMsg.remove(errMsg.size() - 1); + flag = 0; + } else if (flag > 1) { + result = false; + } + if (afterTotalTime > beforeTotalTime * 0.7) { + errMsg.add(String.format(" the execution time too long for task %d, after:before = %d:%d", taskId, + afterTotalTime, beforeTotalTime)); + result = false; + } + Long totalBatchExecutionTime = 0L; + Long totalBatchRowCount = 0L; + int beginBackfillIdIndex = pausedBackfillIdIndex; + int totalBackfillIdNum = 0; + for (; beginBackfillIdIndex < backfillIdList.size(); beginBackfillIdIndex++) { + backfillId = backfillIdList.get(beginBackfillIdIndex); + if (thisExecutionTimeMap.containsKey(backfillId)) { + totalBatchExecutionTime += fromExecutionTime(thisExecutionTimeMap.get(backfillId).toString()); + totalBatchRowCount += Long.valueOf(successRowCountMap.get(backfillId).toString()); + totalBackfillIdNum++; + } + if (!thisExecutionTimeMap.containsKey(backfillId)) { + break; + } + } + long avgBatchExecutionTime = totalBatchExecutionTime / totalBackfillIdNum; + long avgBatchRowCount = totalBatchRowCount / totalBackfillIdNum; + if (thisExecutionTimeMap.containsKey(pausedBackfillIdIndex)) { + backfillId = backfillIdList.get(pausedBackfillIdIndex); + if (thisExecutionTimeMap.containsKey(backfillId)) { + if (fromExecutionTime(thisExecutionTimeMap.get(backfillId)) + > avgBatchExecutionTime * EXCEPTION_COUNT + || successRowCountMap.get(backfillId) > avgBatchRowCount * EXCEPTION_COUNT) { + errMsg.add(String.format( + " the execution time too long for task %d, backfill batch %d, time batch:avg=%s:%d, rows batch:avg=%d:%d", + taskId, + backfillId, thisExecutionTimeMap.get(backfillId), avgBatchExecutionTime, + successRowCountMap.get(backfillId), avgBatchRowCount)); + result = false; + } + } + } +// for(; beginBackfillIdIndex < pausedBackfillIdIndex; beginBackfillIdIndex++){ +// backfillId = backfillIdList.get(beginBackfillIdIndex); +// if(thisExecutionTimeMap.containsKey(backfillId)){ +// if(thisExecutionTimeMap.get(backfillId) > avgBatchExecutionTime * 10){ +// errMsg.add(String.format(" the execution time too long for task %d, backfill batch %d", taskId, backfillId)); +// return false; +// } +// } +// } + } + return result; + } + + public static Boolean checkIfBackfillObjectValid(Connection connection, Long jobId, List errMsg) { + return true; + } + + public static Boolean waitTillDdlDone(Connection tddlConnection, Long jobId, String tableName, + int expectedLocalIndexConcurrency, Boolean checkMppTaskAllocation) + throws InterruptedException { + return waitTillDdlDone(null, tddlConnection, jobId, tableName, expectedLocalIndexConcurrency, + checkMppTaskAllocation); + } + + public static Boolean waitTillDdlDone(Log logger, Connection tddlConnection, Long jobId, String tableName, + int expectedLocalIndexConcurrency, Boolean checkMppTaskAllocation) + throws InterruptedException { Boolean waitDone = false; - String sql = String.format("select state from metadb.ddl_engine where job_id = %d", jobId); + String showDdlSql = String.format("select state from metadb.ddl_engine where job_id = %d", jobId); + String showPhysicalDdlSql = "show physical processlist where info like '%alter table%'"; + String showDdlEngineStatusSql = String.format( + "select node_ip from information_schema.ddl_scheduler where job_id = %d and task_name = \"%s\" and task_state = \"ACTIVE\"" + , jobId, LogicalTableGsiPkRangeBackfillTask.class.getName()); + String showActiveTaskSql = String.format( + "select task_name, task_id, task_state, execution_time from information_schema.ddl_scheduler where job_id = %d and task_state = \"ACTIVE\"" + , jobId); + String showFullDdlSql = "show full ddl"; int i = 0; - while (i < 1000) { - List> results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, sql)); + int finalConcurrency = 0; + if (logger != null) { + logger.info(String.format(" loop start ")); + } + while (i < 10000) { + List> results = + JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, showDdlSql)); if (results.isEmpty()) { waitDone = true; break; } - Thread.sleep(2 * 1000); + if (i % 1000 == 0 && logger != null) { + results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, showFullDdlSql)); + logger.info(String.format(" loop %d, show full ddl is %s", i, results.toString())); + results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, showActiveTaskSql)); + logger.info(String.format(" loop %d, show ddl active task is %s", i, results.toString())); + } + if (expectedLocalIndexConcurrency > 0) { + results = + JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, showPhysicalDdlSql)).stream() + .map(o -> Lists.newArrayList(o.get(4), o.get(8))) + .collect(Collectors.toList()); + Map physicalConcurrency = new HashMap<>(); + for (List result : results) { + String phyDbName = result.get(0).toString(); + physicalConcurrency.put(phyDbName, physicalConcurrency.getOrDefault(phyDbName, 0) + 1); + } + if (!physicalConcurrency.isEmpty() && logger != null) { + logger.info(String.format(" loop %d, the physical concurrency is %s", i, physicalConcurrency)); + } + if (!physicalConcurrency.isEmpty()) { + int maxConcurreny = + physicalConcurrency.values().stream().max(Comparator.comparingInt(o -> o)).get(); + finalConcurrency = Math.max(maxConcurreny, finalConcurrency); + } + } + if (checkMppTaskAllocation) { + results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, showDdlEngineStatusSql)); + Map elementCounts = results.stream().map(o -> o.get(0).toString()) + .collect(Collectors.groupingBy(o -> o, Collectors.counting())); + int totalNum = results.size(); + if (elementCounts.size() > 0) { + int avgNum = totalNum / elementCounts.size(); + for (String nodeIp : elementCounts.keySet()) { + if (elementCounts.get(nodeIp) > avgNum + 1 || elementCounts.get(nodeIp) < avgNum - 1) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + String.format( + " check mpp task allocation error, expected %d active count, while get %d", + avgNum, elementCounts.get(nodeIp))); + } + } + } + + } + Thread.sleep(200); i++; } + if (logger != null) { + logger.info(String.format(" loop done for %d times ", i)); + } + if (finalConcurrency < expectedLocalIndexConcurrency) { + throw new TddlRuntimeException(ErrorCode.ERR_DDL_JOB_ERROR, + " expected concurrency:" + expectedLocalIndexConcurrency + " but got " + finalConcurrency); + } return waitDone; } @@ -199,10 +434,27 @@ public static Boolean checkPhyDdlStatus(String schemaName, Connection tddlConnec } - public static Long getDdlJobIdFromPattern(Connection tddlConnection, String originalDdl) { - String sql = "select job_id from metadb.ddl_engine where ddl_stmt like '%" + originalDdl + "%' limit 1"; + public static Long getDdlJobIdFromPattern(Connection tddlConnection, String originalDdl) + throws InterruptedException { + String sql1 = + "select job_id from metadb.ddl_engine where ddl_stmt like '%" + originalDdl + "%' order by id desc limit 1"; + String sql2 = "select name from metadb.ddl_engine_task where job_id = "; + List> results1 = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, sql1)); + while (results1.isEmpty()) { + Thread.sleep(100); + results1 = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, sql1)); + } Long jobId = Long.valueOf( - JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, sql)).get(0).get(0).toString()); + JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, sql1)).get(0).get(0).toString()); + LOG.info(String.format("fetch ddl job_id %d, %s", jobId, originalDdl)); + List> results2 = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, sql2 + jobId)); + while (results2.size() < 3) { + Thread.sleep(100); + jobId = Long.valueOf( + JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, sql1)).get(0).get(0) + .toString()); + results2 = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, sql2 + jobId)); + } return jobId; } @@ -226,13 +478,38 @@ public static void continueDdl(Connection tddlConnection, Long jobId) throws Int JdbcUtil.executeUpdateSuccess(tddlConnection, sql); } + public static void continueDdlAsync(Connection tddlConnection, Long jobId) throws InterruptedException { + String sql = String.format("select state from metadb.ddl_engine where job_id = %d", jobId); + String ddlState = + JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, sql)).get(0).get(0).toString(); + long time = 0; + while (!ddlState.equalsIgnoreCase("PAUSED") || time > 15L) { + ddlState = + JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, sql)).get(0).get(0).toString(); + time++; + Thread.sleep(500L); + } + sql = String.format("/*+TDDL:cmd_extra(PURE_ASYNC_DDL_MODE=true)*/continue ddl %d", jobId); + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } + public static void tryRollbackDdl(Connection tddlConnection, Long jobId) { String sql = String.format("rollback ddl %d", jobId); JdbcUtil.executeUpdateSuccess(tddlConnection, sql); } - public static void alterTableViaTwoPhaseDdl(Connection tddlConnection, String schemaName, String mytable, - String sql) throws SQLException { + public static void alterTableViaJdbc(Connection tddlConnection, String schemaName, String mytable, + String sql) throws SQLException { + if (sql.contains("rebalance")) { + JdbcUtil.executeQuerySuccess(tddlConnection, sql); + } else { + JdbcUtil.executeUpdateSuccess(tddlConnection, sql); + } + } + + public static void dropTableViaJdbc(Connection tddlConnection, String schemaName, String mytable) + throws SQLException { + String sql = "drop table if exists " + schemaName + "." + mytable; JdbcUtil.executeUpdateSuccess(tddlConnection, sql); } @@ -243,6 +520,64 @@ public static Boolean checkIfExecuteTwoPhaseDdl(Connection tddlConnection, Long return containsTwoPhaseDdlTasks; } + public static Boolean checkIfExecuteByPkRangeAndBuildLocalIndexLater(Connection tddlConnection, Long jobId, + Boolean pkRange, Boolean localIndexLater, + long expectedPkRangeNum, List errMsg) { + String fetchTaskSql = + String.format("select name from metadb.ddl_engine_task_archive where root_job_id = %d or job_id = %d", + jobId, jobId); + List> results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, fetchTaskSql)); + List names = results.stream().map(o -> o.get(0).toString()).collect(Collectors.toList()); + long pkRangeNum = + names.stream().filter(o -> LogicalTableGsiPkRangeBackfillTask.class.getName().contains(o.toString())) + .count(); + Boolean containsPkRange = (pkRangeNum >= 1); + Boolean enoughPkRange = (pkRangeNum >= expectedPkRangeNum); + Boolean containsLocalIndexLater = + names.stream().anyMatch(o -> AlterGsiAddLocalIndexTask.class.getName().contains(o.toString())); + Boolean result = (pkRange == containsPkRange) && (localIndexLater == containsLocalIndexLater) && enoughPkRange; + if (!result) { + String msg = String.format("pk range num is %d, local index later is %s", pkRangeNum, localIndexLater); + errMsg.add(msg); + } + return result; + } + + public static Boolean checkIfBackfillSampleRowsArchived(Connection tddlConnection, Long jobId, Boolean skipCheck) + throws InterruptedException { + if (skipCheck) { + return true; + } + int failedTime = 0; + Boolean result; + do { + result = true; + String fetchTaskSql = + String.format("select job_id from metadb.backfill_sample_rows where job_id = %d", jobId, + jobId); + List> results = + JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, fetchTaskSql)); + List jobIds = results.stream().map(o -> o.get(0).toString()).collect(Collectors.toList()); + if (!jobIds.isEmpty()) { + result = false; + } + fetchTaskSql = + String.format( + "select job_id from metadb.backfill_sample_rows_archive where job_id = %d", jobId, + jobId); + results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, fetchTaskSql)); + jobIds = results.stream().map(o -> o.get(0).toString()).collect(Collectors.toList()); + if (jobIds.isEmpty()) { + result = false; + } + if (!result) { + Thread.sleep(1000); + failedTime++; + } + } while (!result && failedTime < 15); + return result; + } + public static Boolean checkIfCompleteFully(Connection tddlConnection, Long jobId, String tableName) { String fetchJobSql = String.format("select state from metadb.ddl_engine_archive where job_id = %d", jobId); List> results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, fetchJobSql)); @@ -260,6 +595,72 @@ public static Boolean checkIfCompleteFully(Connection tddlConnection, Long jobId return jobCompleted && physicalDdlFinish; } + public static Boolean checkIfTerminate(Connection tddlConnection, Long jobId) { + String fetchJobSql = String.format("select state from metadb.ddl_engine where job_id = %d", jobId); + List> results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, fetchJobSql)); + List terminateStates = Lists.newArrayList("COMPLETED", "ROLLBACK_COMPLETED"); + if (results.isEmpty()) {// || terminateStates.contains(results.get(0).get(0).toString())) { + return true; + } else { + return false; + } + } + + public static Boolean checkIfCompleteSuccessful(Connection tddlConnection, Long jobId) { + String fetchJobSql = String.format("select state from metadb.ddl_engine_archive where job_id = %d", jobId); + List> results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, fetchJobSql)); + String state = results.get(0).get(0).toString(); + Boolean jobCompleted = state.equalsIgnoreCase("COMPLETED"); + return jobCompleted; + } + + public static Boolean compareForLocalIndex(Connection tddlConnection, String schemaName, Long jobId, + String originalTable, + String createTableStmt, String addGsiStmt, String gsiName, int partNum, + List errMsg) throws SQLException { + String compareOriginalTable = originalTable + "_compare"; + String compareGsiName = gsiName + "_compare"; + if (!StringUtils.isEmpty(createTableStmt)) { + String createCompareTable = String.format(createTableStmt, compareOriginalTable, partNum); + alterTableViaJdbc(tddlConnection, schemaName, originalTable, createCompareTable); + } + String addGsiForCompareTable = String.format(addGsiStmt, compareOriginalTable, compareGsiName, partNum); + String hint = + "/*+TDDL:CMD_EXTRA(PURE_ASYNC_DDL_MODE=false,GSI_BACKFILL_BY_PK_RANGE=false,GSI_BUILD_LOCAL_INDEX_LATER=false)*/"; + alterTableViaJdbc(tddlConnection, schemaName, originalTable, hint + addGsiForCompareTable); + String gsiCreateTableSql1 = getGsiCreateTable(tddlConnection, schemaName, originalTable, gsiName); + String gsiCreateTableSql2 = getGsiCreateTable(tddlConnection, schemaName, compareOriginalTable, compareGsiName); + SQLStatementParser mySqlCreateTableParser = + SQLParserUtils.createSQLStatementParser(gsiCreateTableSql1, DbType.mysql); + MySqlCreateTableStatement gsiCreateTableStmt = (MySqlCreateTableStatement) mySqlCreateTableParser.parseCreate(); + gsiCreateTableStmt.setTableName(gsiName); + SQLStatementParser mySqlCreateTableParser2 = + SQLParserUtils.createSQLStatementParser(gsiCreateTableSql2, DbType.mysql); + MySqlCreateTableStatement gsiCreateTableStmt2 = + (MySqlCreateTableStatement) mySqlCreateTableParser2.parseCreate(); + gsiCreateTableStmt2.setTableName(gsiName); + String s1 = gsiCreateTableStmt.toString(); + String s2 = gsiCreateTableStmt2.toString(); + if (s1.equalsIgnoreCase(s2)) { + return true; + } else { + String msg = String.format("the original is %s, the reference is %s", s1, s2); + errMsg.add(msg); + return false; + } + } + + public static String getGsiCreateTable(Connection tddlConnection, String schemaName, String originalTable, + String gsiName) { + Pair fullObjectName = CheckTableTest.getFullObjectName(tddlConnection, gsiName, gsiName, 0); + Integer groupIndex = fullObjectName.getKey(); + String gsiFullName = fullObjectName.getValue(); + String showCreateTableSql = String.format("/*+TDDL:node(%d)*/ show create table `%s`", groupIndex, gsiFullName); + ResultSet resultSet = JdbcUtil.executeQuerySuccess(tddlConnection, showCreateTableSql); + String createTableSql = JdbcUtil.getAllResult(resultSet).get(0).get(1).toString(); + return createTableSql; + } + public static Boolean checkIfRollbackFully(Connection tddlConnection, Long jobId, String tableName) { String fetchJobSql = String.format("select state from metadb.ddl_engine_archive where job_id = %d", jobId); List> results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, fetchJobSql)); @@ -287,4 +688,90 @@ public static Boolean checkIfExecuteTwoPhaseDdl(Connection tddlConnection, Strin Boolean containsTwoPhaseDdlTasks = results.stream().anyMatch(o -> o.toString().contains("TwoPhase")); return containsTwoPhaseDdlTasks; } + + public static Boolean compareShowDdlResult(List> showDdlResultBefore, + List> showDdlResultLater) { + // JOB_ID + // OBJECT_SCHEMA + // OBJECT_NAME + // ENGINE + // DDL_TYPE + // STATE + // TOTAL_BACKFILL_PROGRESS + // CURRENT_PHY_DDL_PROGRESS + // PROGRESS + // FASTCHECKER_TASK_NUM + // FASTCHECKER_TASK_FINISHED + // START_TIME + // END_TIME + // ELAPSED_TIME(MS) + // PHY_PROCESS + // CANCELABLE + int[] expectedTheSameColumns = new int[] { + 0, //JOB_ID + 1, //OBJECT_SCHEMA + 2, //OBJECT_NAME + 3, //ENGINE + 4, //DDL_TYPE + 11 //START_TIME + }; + if (showDdlResultLater.isEmpty() || showDdlResultBefore.isEmpty()) { + return true; + } + String msg = + String.format("show ddl and show full ddl result diffs: %s, %s", showDdlResultBefore, showDdlResultLater); + Assert.assertTrue(showDdlResultLater.size() >= showDdlResultBefore.size(), msg); + for (int i = 0; i < showDdlResultBefore.size(); i++) { + + List row = showDdlResultBefore.get(i); + List afterRow = showDdlResultLater.get(i); + for(int column: expectedTheSameColumns){ + if(!row.get(column).equals(afterRow.get(column))){ + Assert.assertTrue(false, String.format("row %d, column %s diff ", i, column) + msg); + } + + } + int progress = fetchProgress(row.get(8).toString()); + int afterProgress = fetchProgress(afterRow.get(8).toString()); + Assert.assertTrue(progress <= afterProgress || afterProgress <= progress * 0.5, String.format("row %d, progress diff ", i) + msg); + } + return true; + } + + public static int fetchProgress(String progess) { + return Integer.parseInt(progess.substring(0, progess.length() - 1)); + } + + public static Boolean checkIfBackfillSampleRowsDelete(Connection tddlConnection, String schemaName) + throws InterruptedException { + Thread.sleep(2000); + String fetchTaskSql = + String.format("select job_id from metadb.backfill_sample_rows where schema_name = '%s'", schemaName); + List> results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, fetchTaskSql)); + List jobIds = results.stream().map(o -> o.get(0).toString()).collect(Collectors.toList()); + Boolean result = true; + if (!jobIds.isEmpty()) { + result = false; + } + fetchTaskSql = + String.format( + "select job_id from metadb.backfill_sample_rows_archive where schema_name = '%s'", schemaName); + results = JdbcUtil.getAllResult(JdbcUtil.executeQuerySuccess(tddlConnection, fetchTaskSql)); + jobIds = results.stream().map(o -> o.get(0).toString()).collect(Collectors.toList()); + if (!jobIds.isEmpty()) { + result = false; + } + return result; + } + + public static void dropDbAndCheckArchived(String schemaName, Connection tddlConnection) + throws SQLException, InterruptedException { + alterTableViaJdbc(tddlConnection, null, null, "use polardbx"); + alterTableViaJdbc(tddlConnection, null, null, "drop database " + schemaName); + if (!checkIfBackfillSampleRowsDelete(tddlConnection, schemaName)) { + throw new RuntimeException("now we drop database and expect all the sample rows meta clean but not!"); + + } + + } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/ColumnarIndexNotInitedException.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/ColumnarIndexNotInitedException.java new file mode 100644 index 000000000..edfc24f81 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/ColumnarIndexNotInitedException.java @@ -0,0 +1,7 @@ +package com.alibaba.polardbx.qatest.util; + +public class ColumnarIndexNotInitedException extends Throwable { + public ColumnarIndexNotInitedException(Throwable throwable) { + super(throwable); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/ConnectionManager.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/ConnectionManager.java index b508e1357..aff214276 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/ConnectionManager.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/ConnectionManager.java @@ -21,7 +21,6 @@ import com.alibaba.polardbx.gms.util.JdbcUtil; import com.alibaba.polardbx.gms.util.PasswdUtil; import com.alibaba.polardbx.qatest.constant.ConfigConstant; -import com.alibaba.polardbx.qatest.privileges.encdb.EncdbTestBase; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Assert; @@ -29,7 +28,6 @@ import javax.sql.DataSource; import java.security.Security; import java.sql.Connection; -import java.sql.Driver; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -110,6 +108,9 @@ public static DruidDataSource getDruidDataSource(String server, String port, if (isMysql) { connProp = connProp.replace(POLARDBX_SERVER_ID_CONF, ""); } + if (PropertiesUtil.columnarMode()) { + connProp = connProp + "&socketTimeout=600000"; + } String url = String.format(ConfigConstant.URL_PATTERN_WITH_DB + connProp, server, port, db); return getDruidDataSource(url, user, password); @@ -209,9 +210,6 @@ private void init() { //ignore } - //remove encdb jdbc8 driver - EncdbTestBase.cleanJDBC8Driver(); - } catch (Throwable t) { log.error(this.toString(), t); throw new RuntimeException(t); @@ -296,6 +294,15 @@ public Connection newPolarDBXConnection() { return JdbcUtil.createConnection(url, polardbxUser, polardbxPassword); } + public static Connection newPolarDBXConnection0() { + String url = + String.format(ConfigConstant.URL_PATTERN + getConnectionProperties(), + PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_ADDRESS), + PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_PORT)); + return JdbcUtil.createConnection(url, PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_USER), + PropertiesUtil.configProp.getProperty(ConfigConstant.POLARDBX_PASSWORD)); + } + public Connection newPolarDBXConnectionWithUseAffectedRows() { String props = getConnectionProperties(); if (props.isEmpty()) { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/FailFastTestWatcher.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/FailFastTestWatcher.java new file mode 100644 index 000000000..cbd362306 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/FailFastTestWatcher.java @@ -0,0 +1,24 @@ +package com.alibaba.polardbx.qatest.util; + +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +public class FailFastTestWatcher extends TestWatcher { + + private final Class exceptionClass; + + public FailFastTestWatcher(Class exceptionClass) { + this.exceptionClass = exceptionClass; + } + + @Override + protected void failed(Throwable e, Description description) { + if (exceptionClass.isInstance(e)) { + System.out.println("Test failed: " + description.getDisplayName()); + System.out.println("Throwable: " + e.getMessage()); + System.out.println("StackTrace: "); + e.printStackTrace(); + System.exit(1); + } + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/JdbcUtil.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/JdbcUtil.java index 70a52f6dd..999f58131 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/JdbcUtil.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/JdbcUtil.java @@ -18,6 +18,7 @@ import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; +import com.alibaba.polardbx.common.properties.ConnectionProperties; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.TStringUtil; import com.alibaba.polardbx.matrix.jdbc.TConnection; @@ -378,6 +379,10 @@ public static void setGlobal(Connection tddlConn, String sql) { executeUpdate(tddlConn, "set enable_set_global=true;" + sql); } + public static void disableAutoForceIndex(Connection tddlConn) { + executeUpdate(tddlConn, "set " + ConnectionProperties.ENABLE_AUTO_FORCE_INDEX + " =false;"); + } + /** * 批量更新数据 */ @@ -1393,6 +1398,27 @@ public static void executeUpdateSuccess(Connection conn, String sql) { } + public static void executeUpdateSuccessInTrx(Connection conn, String sql) { + Statement stmt = null; + try { + stmt = conn.createStatement(); + stmt.execute("begin"); + stmt.execute(sql); + stmt.execute("commit"); + } catch (SQLException e) { + log.error(e.getMessage(), e); + assertWithMessage("语句并未按照预期执行成功:" + sql + e.getMessage()).fail(); + } finally { + try { + stmt.execute("rollback"); + } catch (SQLException e) { + e.printStackTrace(); + } + close(stmt); + } + + } + /** * 执行 update, 忽略指定异常 * diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/PropertiesUtil.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/PropertiesUtil.java index fe3418d09..bda22fec7 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/PropertiesUtil.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/util/PropertiesUtil.java @@ -201,4 +201,12 @@ public static boolean useSSL() { public static final Integer dnCount = Integer.valueOf(configProp.getProperty("dnCount", "1")); public static final Integer shardDbCountEachDn = Integer.valueOf(configProp.getProperty("shardDbCountEachDn", "4")); + + public static final Long transferTestTime = Long.valueOf(configProp.getProperty("transferTestTime", "1")); + public static final Long allTypesTestPrepareThreads = + Long.valueOf(configProp.getProperty("allTypesTestPrepareThreads", "16")); + public static final Boolean allTypesTestBigColumn = + Boolean.valueOf(configProp.getProperty("allTypesTestBigColumn", "false")); + public static final Long transferRowCount = + Long.valueOf(configProp.getProperty("transferRowCount", "100")); } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/validator/DataOperator.java b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/validator/DataOperator.java index aa32ef460..d9523a910 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/validator/DataOperator.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/qatest/validator/DataOperator.java @@ -133,9 +133,9 @@ public static void executeOnMysqlAndTddl(Connection mysqlConnection, Connection /** * mysql和tddl数据同时执行数据操作 isAssertCount 为是否校验返回条数是否一致 */ - public static void executeOnMysqlAndTddl(Connection mysqlConnection, Connection tddlConnection, - String mysqlSql, String tddlSql, - List param, boolean isAssertCount) { + public static int executeOnMysqlAndTddl(Connection mysqlConnection, Connection tddlConnection, + String mysqlSql, String tddlSql, + List param, boolean isAssertCount) { int mysqlEffectCount = JdbcUtil.updateData(mysqlConnection, mysqlSql, param); // int tddlEffectCount = JdbcUtil.updateDataTddl(tddlConnection, sql, int tddlEffectCount = JdbcUtil.updateData(tddlConnection, tddlSql, param); @@ -143,6 +143,7 @@ public static void executeOnMysqlAndTddl(Connection mysqlConnection, Connection Assert.assertEquals("sql 为 " + tddlSql + " 更新条数结果不一致", mysqlEffectCount, tddlEffectCount); } + return tddlEffectCount; } private static int updateDataGetEffectCount(Connection conn, String sql, List params) throws SQLException { @@ -275,7 +276,8 @@ public static void executeBatchOnMysqlAndTddl(Connection mysqlConnection, Connec } if (isAssertCount) { - assertWithMessage(" 顺序情况下:mysql 返回结果与tddl 返回结果不一致 \n sql 语句为:" + sql).that(mysqlEffectCount) + assertWithMessage(" 顺序情况下:mysql 返回结果与tddl 返回结果不一致 \n sql 语句为:" + sql).that( + mysqlEffectCount) .isEqualTo(tddlEffectCount); } @@ -331,7 +333,8 @@ public static void executeMutilValueOnMysqlAndTddl(Connection mysqlConnection, C } if (isAssertCount) { - assertWithMessage(" 顺序情况下:mysql 返回结果与tddl 返回结果不一致 \n sql 语句为:" + execSql).that(mysqlEffectCount) + assertWithMessage(" 顺序情况下:mysql 返回结果与tddl 返回结果不一致 \n sql 语句为:" + execSql).that( + mysqlEffectCount) .isEqualTo(tddlEffectCount); } } diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/Runner.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/Runner.java index 22f8a3a4b..58f30f896 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/Runner.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/Runner.java @@ -12,7 +12,6 @@ import org.slf4j.LoggerFactory; import java.lang.reflect.Constructor; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -33,6 +32,12 @@ public static void main(String[] args) throws Exception { return; } + runAllPlugins(); + + System.exit(BasePlugin.success() ? 0 : 1); + } + + public static void runAllPlugins() { List plugins = loadPlugins(); for (IPlugin plugin : plugins) { plugin.run(); @@ -41,7 +46,7 @@ public static void main(String[] args) throws Exception { Thread monitorThread = new Thread(() -> monitor(plugins), "Monitor"); monitorThread.start(); - long timeout = TomlConfig.getConfig().getLong("timeout"); + long timeout = TomlConfig.getConfig().getLong("timeout", 60L); try { BasePlugin.waitUtilTimeout(timeout * 1000); } catch (Throwable t) { @@ -58,16 +63,36 @@ public static void main(String[] args) throws Exception { private static boolean loadConfig(String[] args) { // Get config file path. - String configFilePath; + String configFilePath = "config.toml"; boolean prepare = false; - try { - CommandLineParser parser = new DefaultParser(); - CommandLine cmd = parser.parse(CmdOptions.getOptions(), args); - configFilePath = cmd.getOptionValue("config"); - prepare = "prepare".equalsIgnoreCase(cmd.getOptionValue("op", "run")); - } catch (Throwable t) { - logger.warn("Cant parse config file path in cmd line, use default config.toml ."); - configFilePath = "config.toml"; + + // Compatible with old version + boolean legacy = false; + if (args.length > 0) { + if ("prepare".equalsIgnoreCase(args[0])) { + prepare = true; + legacy = true; + } else if ("run".equalsIgnoreCase(args[0])) { + legacy = true; + } + if (legacy && args[1].startsWith("-config=")) { + configFilePath = args[1].substring("-config=".length()); + } else if (legacy && args[1].startsWith("--config ")) { + configFilePath = args[1].substring("--config ".length()).trim(); + } else if (legacy && args[1].startsWith("-config ")) { + configFilePath = args[1].substring("-config ".length()).trim(); + } + } + + if (!legacy) { + try { + CommandLineParser parser = new DefaultParser(); + CommandLine cmd = parser.parse(CmdOptions.getOptions(), args); + configFilePath = cmd.getOptionValue("config"); + prepare = "prepare".equalsIgnoreCase(cmd.getOptionValue("op", "run")); + } catch (Throwable t) { + logger.warn("Cant parse config file path in cmd line, use default config.toml ."); + } } // Read config from file. @@ -80,7 +105,7 @@ private static List loadPlugins() { String pluginPackage = "com.alibaba.polardbx.transfer.plugin"; ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); List classNames; - if ("local".equalsIgnoreCase(TomlConfig.getConfig().getString("runmode"))) { + if ("local".equalsIgnoreCase(TomlConfig.getConfig().getString("runmode", "docker"))) { classNames = Utils.getClassName(pluginPackage, classLoader); } else { classNames = Utils.getClassNameFromJar(pluginPackage); @@ -111,7 +136,7 @@ private static List loadPlugins() { } private static void monitor(Collection plugins) { - long reportInterval = TomlConfig.getConfig().getLong("report_interval"); + long reportInterval = TomlConfig.getConfig().getLong("report_interval", 5L); try { do { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/alltypes.toml b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/alltypes.toml index a014a7c12..6f8bd5b20 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/alltypes.toml +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/alltypes.toml @@ -9,9 +9,6 @@ runmode = 'local' # number of rows (the actual value will be slightly greater) row_count = 100 -# [Unused] just compatible to the framework -initial_balance = 1000 - # the following suffix will be appended to CREATE TABLE SQL create_table_suffix = 'PARTITION BY KEY(id) PARTITIONS 16' @@ -19,7 +16,7 @@ create_table_suffix = 'PARTITION BY KEY(id) PARTITIONS 16' report_interval = 5 # max test time, in seconds -timeout = 60 +timeout = 30 # prepare data threads threads = 4 @@ -28,4 +25,8 @@ big_column = false [write_only] enabled = true -threads = 2 +threads = 1 + +[check_columnar] +enabled = true +threads = 1 diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/config.toml b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/config.toml index 54bc1d680..7d76fe4d1 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/config.toml +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/config.toml @@ -1,5 +1,6 @@ # datasource name, format: '${user_name}:${password}@tcp(${ip}:${port})/${db_name}' dsn = 'polardbx_root:123456@tcp(127.0.0.1:8527)/transfer_test' +conn_properties='sessionVariables=polardbx_server_id=181818' # choices: local, docker runmode = 'local' @@ -90,3 +91,7 @@ session_var = '' enabled = false threads = 2 replica_dsn = 'root:root@tcp(127.0.0.1:37306)/db1' + +[check_rpl_sync_point] +enabled = false +replica_dsn = 'root:root@tcp(127.0.0.1:37306)/db1' diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/Dockerfile b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/Dockerfile index a6f28c523..1360838ed 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/Dockerfile +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.5-jdk-8 AS build +FROM pxc-registry.cn-shanghai.cr.aliyuncs.com/base/maven:3.5-jdk-8 AS build WORKDIR /root/workspace @@ -15,8 +15,9 @@ RUN mkdir -p polardbx-transfer/src/main/java/com/alibaba/polardbx/transfer && \ cd polardbx-transfer && \ mvn clean package -DskipTests -FROM openjdk:8-jre-alpine +FROM pxc-registry.cn-shanghai.cr.aliyuncs.com/base/openjdk:8-jre-alpine COPY --from=build /root/workspace/polardbx-transfer/target/transfer-test-1.0.0-jar-with-dependencies.jar transfer-test.jar COPY --from=build /root/workspace/docker/logback.xml logback.xml COPY --from=build /root/workspace/docker/config.toml config.toml +ENV TZ Asia/Shanghai ENTRYPOINT ["java", "-Dlogback.configurationFile=logback.xml", "-jar", "transfer-test.jar"] diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/README.md b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/README.md index 18b28b006..59e71aa99 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/README.md +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/README.md @@ -9,7 +9,7 @@ git checkout origin/xxx cd polardbx-test/src/test/java/com/alibaba/polardbx/transfer/ -docker build -t transfer-test:v1.0.0 . -f docker/Dockerfile +docker build --network host -t transfer-test:v1.0.0 . -f docker/Dockerfile ``` # 运行 diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/pom.xml b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/pom.xml index ef6b948e8..ce7761aaf 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/pom.xml +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/pom.xml @@ -14,16 +14,27 @@ + + ch.qos.logback + logback-classic + 1.2.3 + + + org.slf4j + jcl-over-slf4j + 1.7.21 + org.slf4j slf4j-api - 1.7.32 + 1.7.21 - ch.qos.logback - logback-classic - 1.2.6 + org.slf4j + log4j-over-slf4j + 1.7.21 + commons-cli commons-cli @@ -37,7 +48,7 @@ mysql mysql-connector-java - 5.1.40 + 8.0.30 com.google.guava diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/settings.xml b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/settings.xml deleted file mode 100644 index 3772859ff..000000000 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/docker/settings.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - aliyunmaven - central - 阿里云公共仓库 - https://maven.aliyun.com/repository/central - - - repo1 - central - central repo - http://repo1.maven.org/maven2/ - - - aliyunmaven - apache snapshots - 阿里云阿帕奇仓库 - https://maven.aliyun.com/repository/apache-snapshots - - - - - - - - - aliyunmaven - aliyunmaven - https://maven.aliyun.com/repository/public - default - - true - - - true - - - - MavenCentral - http://repo1.maven.org/maven2/ - - - aliyunmavenApache - https://maven.aliyun.com/repository/apache-snapshots - - - - - \ No newline at end of file diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/AllTypesCheckColumnarPlugin.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/AllTypesCheckColumnarPlugin.java new file mode 100644 index 000000000..b9d6ec221 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/AllTypesCheckColumnarPlugin.java @@ -0,0 +1,188 @@ +package com.alibaba.polardbx.transfer.plugin; + +import com.alibaba.polardbx.qatest.columnar.dql.ColumnarUtils; +import com.alibaba.polardbx.transfer.config.TomlConfig; +import com.alibaba.polardbx.transfer.utils.AllTypesTestUtils; +import com.moandjiezana.toml.Toml; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static com.alibaba.polardbx.transfer.utils.AllTypesTestUtils.COLUMNAR_INDEX_NAME; + +/** + * @author yaozhili + */ +public class AllTypesCheckColumnarPlugin extends BasePlugin { + private static final Logger logger = LoggerFactory.getLogger(AllTypesWriteOnlyPlugin.class); + + private final List allColumns = new ArrayList<>(); + private final Map lastTsoMap = new ConcurrentHashMap<>(); + + public AllTypesCheckColumnarPlugin() { + super(); + Toml config = TomlConfig.getConfig().getTable("check_columnar"); + if (null == config) { + enabled = false; + return; + } + enabled = config.getBoolean("enabled", false); + threads = Math.toIntExact(config.getLong("threads", 1L)); + boolean bigColumn = TomlConfig.getConfig().getBoolean("big_column", false); + allColumns.addAll(AllTypesTestUtils.getColumns()); + if (bigColumn) { + allColumns.addAll(AllTypesTestUtils.getBigColumns()); + } + if (enabled) { + getConnectionAndExecute(dsn, (conn, error) -> { + try (Statement stmt = conn.createStatement()) { + // Create columnar index. + String createSql = AllTypesTestUtils.FULL_TYPE_TABLE_COLUMNAR_INDEX; + stmt.execute(createSql); + } catch (Throwable t) { + if (t.getMessage().contains("Duplicate index name")) { + // ignore. + } else { + logger.error("create columnar index failed, skip AllTypesCheckColumnarPlugin.", t); + enabled = false; + } + } + }); + } + } + + @Override + protected void runInternal() { + long lastTso = lastTsoMap.getOrDefault(Thread.currentThread().getId(), -1L); + List checkResults = new ArrayList<>(); + // Cci fast checker. + getConnectionAndExecute(dsn, (conn, error) -> { + try (Statement stmt = conn.createStatement()) { + String checkSql = "/*+TDDL:ENABLE_CCI_FAST_CHECKER=true */ CHECK COLUMNAR INDEX " + + COLUMNAR_INDEX_NAME; + ResultSet rs = stmt.executeQuery(checkSql); + while (rs.next()) { + checkResults.add(rs.getString("DETAILS")); + } + stmt.execute("SELECT SLEEP(1)"); + } catch (SQLException e) { + logger.error("Write only error.", e); + error.set(e); + } + }); + if (checkResults.isEmpty() || !checkResults.get(0).startsWith("OK")) { + errorAllTypesTest1(checkResults, "Cci fast checker failed."); + } + + // Cci naive checker. + checkResults.clear(); + getConnectionAndExecute(dsn, (conn, error) -> { + try (Statement stmt = conn.createStatement()) { + String checkSql = "/*+TDDL:ENABLE_CCI_FAST_CHECKER=false */ CHECK COLUMNAR INDEX " + + COLUMNAR_INDEX_NAME; + ResultSet rs = stmt.executeQuery(checkSql); + while (rs.next()) { + checkResults.add(rs.getString("DETAILS")); + } + stmt.execute("SELECT SLEEP(1)"); + } catch (SQLException e) { + logger.error("Write only error.", e); + error.set(e); + } + }); + if (checkResults.isEmpty() || !checkResults.get(0).startsWith("OK")) { + errorAllTypesTest1(checkResults, "Cci naive checker failed."); + } + + // Cci increment checker. + if (lastTso > 0) { + checkResults.clear(); + getConnectionAndExecute(dsn, (conn, error) -> { + try (Statement stmt = conn.createStatement()) { + long currentTso = ColumnarUtils.columnarFlushAndGetTso(stmt); + if (currentTso > lastTso) { + lastTsoMap.put(Thread.currentThread().getId(), currentTso); + String checkSql = "CHECK COLUMNAR INDEX " + + COLUMNAR_INDEX_NAME + " INCREMENT " + lastTso + " " + currentTso + " " + currentTso; + ResultSet rs = stmt.executeQuery(checkSql); + while (rs.next()) { + checkResults.add(rs.getString("DETAILS")); + } + stmt.execute("SELECT SLEEP(1)"); + } else { + checkResults.add("Fail to get current tso."); + } + } catch (SQLException e) { + logger.error("Write only error.", e); + error.set(e); + } + }); + if (checkResults.isEmpty() || !checkResults.get(0).startsWith("OK")) { + errorAllTypesTest1(checkResults, "Cci increment checker failed."); + } + } + + // Cci snapshot fast checker. + if (lastTso > 0) { + checkResults.clear(); + getConnectionAndExecute(dsn, (conn, error) -> { + try (Statement stmt = conn.createStatement()) { + long currentTso = ColumnarUtils.columnarFlushAndGetTso(stmt); + if (currentTso > lastTso) { + lastTsoMap.put(Thread.currentThread().getId(), currentTso); + String checkSql = "/*+TDDL:ENABLE_CCI_FAST_CHECKER=true */ CHECK COLUMNAR INDEX " + + COLUMNAR_INDEX_NAME + " SNAPSHOT " + lastTso + " " + lastTso; + ResultSet rs = stmt.executeQuery(checkSql); + while (rs.next()) { + checkResults.add(rs.getString("DETAILS")); + } + stmt.execute("SELECT SLEEP(1)"); + } else { + checkResults.add("Fail to get current tso."); + } + } catch (SQLException e) { + logger.error("Write only error.", e); + error.set(e); + } + }); + if (checkResults.isEmpty() || !checkResults.get(0).startsWith("OK")) { + errorAllTypesTest1(checkResults, "Cci increment checker failed."); + } + } + + // Cci snapshot naive checker. + if (lastTso > 0) { + checkResults.clear(); + getConnectionAndExecute(dsn, (conn, error) -> { + try (Statement stmt = conn.createStatement()) { + long currentTso = ColumnarUtils.columnarFlushAndGetTso(stmt); + if (currentTso > lastTso) { + lastTsoMap.put(Thread.currentThread().getId(), currentTso); + String checkSql = "/*+TDDL:ENABLE_CCI_FAST_CHECKER=false */ CHECK COLUMNAR INDEX " + + COLUMNAR_INDEX_NAME + " SNAPSHOT " + lastTso + " " + lastTso; + ResultSet rs = stmt.executeQuery(checkSql); + while (rs.next()) { + checkResults.add(rs.getString("DETAILS")); + } + stmt.execute("SELECT SLEEP(1)"); + } else { + checkResults.add("Fail to get current tso."); + } + } catch (SQLException e) { + logger.error("Write only error.", e); + error.set(e); + } + }); + if (checkResults.isEmpty() || !checkResults.get(0).startsWith("OK")) { + errorAllTypesTest1(checkResults, "Cci increment checker failed."); + } + } + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/AllTypesWriteOnlyPlugin.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/AllTypesWriteOnlyPlugin.java index cba1ebd3c..28b9f1652 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/AllTypesWriteOnlyPlugin.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/AllTypesWriteOnlyPlugin.java @@ -12,11 +12,14 @@ import java.util.ArrayList; import java.util.List; +import static com.alibaba.polardbx.transfer.utils.AllTypesTestUtils.TABLE_NAME; + /** * @author yaozhili */ public class AllTypesWriteOnlyPlugin extends BasePlugin { private static final Logger logger = LoggerFactory.getLogger(AllTypesWriteOnlyPlugin.class); + private final boolean bigColumn; private final List allColumns = new ArrayList<>(); @@ -25,15 +28,14 @@ public AllTypesWriteOnlyPlugin() { Toml config = TomlConfig.getConfig().getTable("write_only"); if (null == config) { enabled = false; + bigColumn = false; return; } enabled = config.getBoolean("enabled", false); threads = Math.toIntExact(config.getLong("threads", 1L)); - boolean bigColumn = TomlConfig.getConfig().getBoolean("big_column", false); + bigColumn = TomlConfig.getConfig().getBoolean("big_column", false); allColumns.addAll(AllTypesTestUtils.getColumns()); - if (bigColumn) { - allColumns.addAll(AllTypesTestUtils.getBigColumns()); - } + allColumns.addAll(AllTypesTestUtils.getBigColumns()); } @Override @@ -46,21 +48,31 @@ protected void runInternal() { String sql = null; try { // Insert a new record. - sql = AllTypesTestUtils.buildInsertSql(1, allColumns); + sql = AllTypesTestUtils.buildInsertSql(1, allColumns, bigColumn); stmt.execute(sql); - // Update a random row. - sql = AllTypesTestUtils.buildSelectRandomSql(); + sql = "SELECT MIN(id), MAX(id) FROM " + TABLE_NAME; ResultSet rs = stmt.executeQuery(sql); + int min, max; + if (rs.next()) { + min = rs.getInt(1); + max = rs.getInt(2); + } else { + throw new RuntimeException("Can not find min/max id from " + TABLE_NAME); + } + + // Update a random row. + sql = AllTypesTestUtils.buildSelectRandomSql(min, max); + rs = stmt.executeQuery(sql); long id = 0; if (rs.next()) { id = rs.getLong(1); } - sql = AllTypesTestUtils.buildUpdateSql(id, allColumns); + sql = AllTypesTestUtils.buildUpdateSql(id, allColumns, bigColumn); stmt.execute(sql); // Delete a random row. - sql = AllTypesTestUtils.buildSelectRandomSql(); + sql = AllTypesTestUtils.buildSelectRandomSql(min, max); rs = stmt.executeQuery(sql); id = 0; if (rs.next()) { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/BasePlugin.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/BasePlugin.java index 0e2e24ff9..5531460a3 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/BasePlugin.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/BasePlugin.java @@ -40,6 +40,7 @@ public abstract class BasePlugin implements IPlugin { } protected final String dsn; + protected final String props; protected final int rowCount; protected final long initBalance; private final AtomicLong ops = new AtomicLong(0); @@ -51,11 +52,11 @@ public abstract class BasePlugin implements IPlugin { protected BasePlugin() { Toml config = TomlConfig.getConfig(); dsn = config.getString("dsn"); + props = config.getString("conn_properties"); rowCount = Math.toIntExact(config.getLong("row_count")); - initBalance = config.getLong("initial_balance"); + initBalance = config.getLong("initial_balance", 100L); assert dsn != null; assert rowCount > 0; - assert initBalance > 0; } public static void waitUtilTimeout(long timeout) throws InterruptedException { @@ -161,7 +162,7 @@ protected void getConnectionAndExecute(String dsn, } protected MyConnection getConnection(String dsn) throws SQLException { - ConnectionPool pool = connPoolMap.computeIfAbsent(dsn, ConnectionPool::new); + ConnectionPool pool = connPoolMap.computeIfAbsent(dsn, k -> new ConnectionPool(dsn, props)); return pool.get(); } @@ -170,6 +171,9 @@ protected void finishOp() { } protected void checkConsistency(List accounts, String hint) { + if (null == accounts) { + return; + } long expectTotal = rowCount * initBalance; long actualTotal = 0; for (Account account : accounts) { @@ -181,6 +185,9 @@ protected void checkConsistency(List accounts, String hint) { } protected void checkStrongConsistency(List masterAccounts, List slaveAccounts, String hint) { + if (null == masterAccounts || null == slaveAccounts) { + return; + } if (masterAccounts.size() != slaveAccounts.size()) { error2(masterAccounts, slaveAccounts, hint, "Master and slave size not matches, master: " + masterAccounts.size() + ", slave: " @@ -234,6 +241,23 @@ public void generateErrorMsg(List accounts, String hint) { logger.error(sb.toString()); } + protected void errorAllTypesTest1(List checkResults, String errorMsg) { + if (Thread.currentThread().isInterrupted()) { + // already interrupt + return; + } + StringBuilder sb = new StringBuilder("All types test failed: ").append("\n"); + for (String checkResult : checkResults) { + sb.append(checkResult).append("\n"); + } + fail(); + throw new RuntimeException(errorMsg); + } + + public static boolean success() { + return !FAIL.get(); + } + private static class Worker { private final ExecutorService executor; private final int threads; @@ -274,10 +298,12 @@ public Thread newThread(Runnable r) { private static class ConnectionPool { private final String dsn; + private final String props; ConcurrentLinkedQueue connections = new ConcurrentLinkedQueue<>(); - public ConnectionPool(String dsn) { + public ConnectionPool(String dsn, String props) { this.dsn = dsn; + this.props = props; } public void add(MyConnection conn) { @@ -288,7 +314,7 @@ public MyConnection get() throws SQLException { MyConnection conn; if (null == (conn = connections.poll())) { // poll is empty, create new connection - conn = new MyConnection(this, dsn); + conn = new MyConnection(this, dsn, props); } return conn; } @@ -312,10 +338,10 @@ public static class MyConnection implements Closeable { private final String dsn; private boolean discarded = false; - public MyConnection(ConnectionPool pool, String dsn) throws SQLException { + public MyConnection(ConnectionPool pool, String dsn, String props) throws SQLException { this.pool = pool; this.dsn = dsn; - this.conn = Utils.getConnection(dsn); + this.conn = Utils.getConnection(dsn, props); } @Override diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/CheckBalancePlugin.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/CheckBalancePlugin.java index 60288871d..200df3141 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/CheckBalancePlugin.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/CheckBalancePlugin.java @@ -71,6 +71,7 @@ private List getAccounts(MyConnection conn) throws SQLException { // rollback if necessary if (choice < 0.66) { conn.rollback(); + conn.setAutoCommit(true); } } return accounts; diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/CheckSyncPointPlugin.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/CheckSyncPointPlugin.java new file mode 100644 index 000000000..ff0d02c29 --- /dev/null +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/CheckSyncPointPlugin.java @@ -0,0 +1,90 @@ +package com.alibaba.polardbx.transfer.plugin; + +import com.alibaba.polardbx.transfer.config.TomlConfig; +import com.alibaba.polardbx.transfer.utils.Account; +import com.alibaba.polardbx.transfer.utils.Utils; +import com.moandjiezana.toml.Toml; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @author yudong + * @since 2024/6/13 17:37 + **/ +public class CheckSyncPointPlugin extends BasePlugin { + private static final Logger logger = LoggerFactory.getLogger(CheckSyncPointPlugin.class); + private static final String SELECT_SYNC_POINT_SQL = + "select * from information_schema.rpl_sync_point order by create_time desc limit 1"; + private static final String snapshotHint = "/*+TDDL:SNAPSHOT_TS=%s*/"; + private final String hint = "/*" + UUID.randomUUID() + "*/"; + private final String replicaDsn; + + public CheckSyncPointPlugin() { + super(); + Toml config = TomlConfig.getConfig().getTable("check_rpl_sync_point"); + if (null == config) { + enabled = false; + replicaDsn = null; + return; + } + enabled = config.getBoolean("enabled", false); + replicaDsn = config.getString("replica_dsn", dsn); + } + + @Override + public void runInternal() { + // get sync point + final AtomicReference primaryTso = new AtomicReference<>(); + final AtomicReference secondaryTso = new AtomicReference<>(); + getConnectionAndExecute(replicaDsn, (conn, error) -> { + try (Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(SELECT_SYNC_POINT_SQL)) { + if (rs.next()) { + primaryTso.set(rs.getString("PRIMARY_TSO")); + secondaryTso.set(rs.getString("SECONDARY_TSO")); + if (logger.isDebugEnabled()) { + logger.debug("primary tso: " + primaryTso.get() + ", secondary tso: " + secondaryTso.get()); + } + } else { + throw new SQLException("Cannot get sync point from metadb!"); + } + } catch (SQLException e) { + error.set(e); + logger.error("Get sync point error.", e); + } + }); + + // read master data first + String masterHint = String.format(snapshotHint, primaryTso.get()); + final AtomicReference> masterAccounts = new AtomicReference<>(); + getConnectionAndExecute(dsn, (conn, error) -> { + try (Statement stmt = conn.createStatement()) { + masterAccounts.set(Utils.getAccounts(masterHint, stmt)); + } catch (SQLException e) { + error.set(e); + logger.error("Get sync point error.", e); + } + }); + + // read slave data + String slaveHint = String.format(snapshotHint, secondaryTso.get()); + final AtomicReference> slaveAccounts = new AtomicReference<>(); + getConnectionAndExecute(replicaDsn, (conn, error) -> { + try (Statement stmt = conn.createStatement()) { + slaveAccounts.set(Utils.getAccounts(slaveHint, stmt)); + } catch (SQLException e) { + error.set(e); + logger.error("Get sync point error.", e); + } + }); + + checkStrongConsistency(masterAccounts.get(), slaveAccounts.get(), hint); + } +} diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/FlashbackQueryPlugin.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/FlashbackQueryPlugin.java index 4b0dfef0e..acc2b9784 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/FlashbackQueryPlugin.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/FlashbackQueryPlugin.java @@ -24,7 +24,7 @@ public class FlashbackQueryPlugin extends BasePlugin { private final int minTime; private final int maxTime; - private boolean firstTime = false; + private boolean firstTime = true; public FlashbackQueryPlugin() { super(); @@ -46,7 +46,7 @@ public void runInternal() { if (firstTime) { // wait until flashback timestamp is valid try { - Thread.sleep(minTime * 1000L); + Thread.sleep(maxTime * 1000L); firstTime = false; } catch (Throwable t) { // ignored diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaFlashbackPlugin.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaFlashbackPlugin.java index 7e66ab7d7..25b868970 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaFlashbackPlugin.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaFlashbackPlugin.java @@ -26,7 +26,7 @@ public class ReplicaFlashbackPlugin extends BasePlugin { private final String sessionVar; private final int minTime; private final int maxTime; - private boolean firstTime = false; + private boolean firstTime = true; public ReplicaFlashbackPlugin() { super(); @@ -54,7 +54,7 @@ public void runInternal() { if (firstTime) { // wait until flashback timestamp is valid try { - Thread.sleep(minTime * 1000L); + Thread.sleep(maxTime * 1000L); firstTime = false; } catch (Throwable t) { // ignored diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaReadPlugin.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaReadPlugin.java index f82fcb9ea..b9cf7f3b3 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaReadPlugin.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaReadPlugin.java @@ -67,6 +67,7 @@ public void runInternal() { // rollback if necessary if (choice < 0.66) { conn.rollback(); + conn.setAutoCommit(true); } } } catch (SQLException e) { @@ -95,6 +96,7 @@ public void runInternal() { // rollback if necessary if (choice < 0.66) { conn.rollback(); + conn.setAutoCommit(true); } } } catch (SQLException e) { diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaSHintPlugin.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaSHintPlugin.java index 73c4f1733..154533fe7 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaSHintPlugin.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/ReplicaSHintPlugin.java @@ -45,13 +45,15 @@ public ReplicaSHintPlugin() { replicaDsn = config.getString("replica_dsn", dsn); sessionVar = config.getString("session_var", null); strongConsistency = config.getBoolean("replica_strong_consistency", false); - // init session hint - try (MyConnection conn = getConnection(dsn); - Statement stmt = conn.createStatement()) { - Utils.initSessionHint(stmt, sessionHint); - logger.info("All partitions: " + String.join(",", sessionHint)); - } catch (Throwable t) { - logger.error("Init session hint failed.", t); + if (enabled) { + // init session hint + try (MyConnection conn = getConnection(dsn); + Statement stmt = conn.createStatement()) { + Utils.initSessionHint(stmt, sessionHint); + logger.info("All partitions: " + String.join(",", sessionHint)); + } catch (Throwable t) { + logger.error("Init session hint failed.", t); + } } } @@ -74,6 +76,7 @@ public void runInternal() { masterAccounts.set(Utils.getAccountsWithSessionHint(hint, stmt, sessionHint)); } finally { conn.rollback(); + conn.setAutoCommit(true); } } catch (SQLException e) { error.set(e); @@ -93,6 +96,7 @@ public void runInternal() { slaveAccounts.set(Utils.getAccountsWithSessionHint(slaveHint, stmt, sessionHint)); } finally { conn.rollback(); + conn.setAutoCommit(true); } } catch (SQLException e) { error.set(e); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/SessionHintPlugin.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/SessionHintPlugin.java index 34d342e76..d1ba3b2e9 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/SessionHintPlugin.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/plugin/SessionHintPlugin.java @@ -34,13 +34,15 @@ public SessionHintPlugin() { } enabled = config.getBoolean("enabled", false); threads = Math.toIntExact(config.getLong("threads", 1L)); - // init session hint - try (MyConnection conn = getConnection(dsn); - Statement stmt = conn.createStatement()) { - Utils.initSessionHint(stmt, sessionHint); - logger.info("All partitions: " + String.join(",", sessionHint)); - } catch (Throwable t) { - logger.error("Init session hint failed.", t); + if (enabled) { + // init session hint + try (MyConnection conn = getConnection(dsn); + Statement stmt = conn.createStatement()) { + Utils.initSessionHint(stmt, sessionHint); + logger.info("All partitions: " + String.join(",", sessionHint)); + } catch (Throwable t) { + logger.error("Init session hint failed.", t); + } } } @@ -61,6 +63,7 @@ public void runInternal() { accounts.set(Utils.getAccountsWithSessionHint(hint, stmt, sessionHint)); } finally { conn.rollback(); + conn.setAutoCommit(true); } } catch (SQLException e) { error.set(e); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/utils/AllTypesTestUtils.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/utils/AllTypesTestUtils.java index 68b41f62e..168e571c3 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/utils/AllTypesTestUtils.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/utils/AllTypesTestUtils.java @@ -22,7 +22,8 @@ public class AllTypesTestUtils { * Big columns values providers. */ private final static Map> BIG_COLUMNS_VALUES_PROVIDER; - private final static String TABLE_NAME = "`full_type`"; + public final static String TABLE_NAME = "`full_types`"; + public final static String COLUMNAR_INDEX_NAME = "`full_types_cci`"; public static Collection getColumns() { return VALUES_PROVIDER.keySet(); @@ -32,13 +33,13 @@ public static Collection getBigColumns() { return BIG_COLUMNS_VALUES_PROVIDER.keySet(); } - public static String buildInsertSql(int row, Collection columns) { + public static String buildInsertSql(int row, Collection columns, boolean useBigColumn) { Collection> values = new ArrayList<>(row); while (row-- > 0) { Collection oneRow = new ArrayList<>(); for (String column : columns) { - oneRow.add(getRandomValue(column)); + oneRow.add(getRandomValue(column, useBigColumn)); } values.add(oneRow); } @@ -85,10 +86,10 @@ public static String buildAllInsertSql() { return buildInsertSql(columns, values); } - public static String buildUpdateSql(long id, Collection columns) { + public static String buildUpdateSql(long id, Collection columns, boolean isBigColumn) { Collection values = new ArrayList<>(); for (String column : columns) { - values.add(getRandomValue(column)); + values.add(getRandomValue(column, isBigColumn)); } return buildUpdateSql(id, columns, values); } @@ -97,8 +98,11 @@ public static String buildDeleteSql(long id) { return "DELETE FROM " + TABLE_NAME + " WHERE id = " + id; } - public static String buildSelectRandomSql() throws SQLException { - return "SELECT id FROM " + TABLE_NAME + " ORDER BY RAND() LIMIT 1"; + public static String buildSelectRandomSql(int min, int max) throws SQLException { + long begin = new SecureRandom().nextInt(max - min) + min; + long end = Math.min(max, begin + 1000); + return "SELECT id FROM " + TABLE_NAME + " WHERE id BETWEEN " + begin + " AND " + end + + " ORDER BY RAND() LIMIT 1"; } /** @@ -155,10 +159,13 @@ private static String buildUpdateSql(long id, Collection columns, Collec return sb.toString(); } - private static String getRandomValue(String column) { + private static String getRandomValue(String column, boolean useBigColumn) { List possibleValues = BIG_COLUMNS_VALUES_PROVIDER.get(column); if (null == possibleValues) { possibleValues = VALUES_PROVIDER.get(column); + } else { + return possibleValues.get( + new SecureRandom().nextInt(useBigColumn ? possibleValues.size() : possibleValues.size() - 1)); } if (null == possibleValues) { throw new IllegalArgumentException("Invalid column name"); @@ -166,6 +173,9 @@ private static String getRandomValue(String column) { return possibleValues.get(new SecureRandom().nextInt(possibleValues.size())); } + public static final String FULL_TYPE_TABLE_COLUMNAR_INDEX = "ALTER TABLE " + TABLE_NAME + + " ADD CLUSTERED COLUMNAR INDEX " + COLUMNAR_INDEX_NAME + "(`id`)"; + public static final String FULL_TYPE_TABLE_TEMPLATE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (\n" + " `id` bigint(20) NOT NULL AUTO_INCREMENT,\n" + " `c_bit_1` bit(1) DEFAULT NULL,\n" @@ -333,6 +343,10 @@ private static String getRandomValue(String column) { BIG_COLUMNS_VALUES_PROVIDER = builder1.build(); } + private boolean isBigColumn(String column) { + return BIG_COLUMNS_VALUES_PROVIDER.containsKey(column); + } + /** * Corner cases included. * @@ -809,6 +823,7 @@ private static ImmutableMap> buildFullTypeTestValues() { "'a中国a'", "x'313233616263'", "x'0A08080E10011894AB0E'", + "RANDOM_BYTES(FLOOR(1 + (RAND() * 255)))", /* from 64B to 64KB */ "REPEAT(RANDOM_BYTES(FLOOR(1 + (RAND() * 1024))), 64)" )); @@ -819,6 +834,7 @@ private static ImmutableMap> buildFullTypeTestValues() { "'a中国a'", "x'313233616263'", "x'0A08080E10011894AB0E'", + "RANDOM_BYTES(FLOOR(1 + (RAND() * 255)))", /* from 16KB to 16MB */ "REPEAT(RANDOM_BYTES(FLOOR(1 + (RAND() * 1024))), 16384)" )); @@ -829,6 +845,7 @@ private static ImmutableMap> buildFullTypeTestValues() { "'a中国a'", "x'313233616263'", "x'0A08080E10011894AB0E'", + "RANDOM_BYTES(FLOOR(1 + (RAND() * 255)))", /* from 128KB to 128MB */ "REPEAT(RANDOM_BYTES(FLOOR(1 + (RAND() * 1024))), 131072)" )); @@ -846,6 +863,7 @@ private static ImmutableMap> buildFullTypeTestValues() { "'99'", "'a中国a'", "x'313233616263'", + "SUBSTRING(MD5(RAND()), 1, 10)", "REPEAT(SUBSTRING(MD5(RAND()), 1, 10), 100)" )); @@ -854,6 +872,7 @@ private static ImmutableMap> buildFullTypeTestValues() { "'99'", "'a中国a'", "x'313233616263'", + "SUBSTRING(MD5(RAND()), 1, 10)", "REPEAT(SUBSTRING(MD5(RAND()), 1, 10), 10000)" )); @@ -862,6 +881,7 @@ private static ImmutableMap> buildFullTypeTestValues() { "'99'", "'a中国a'", "x'313233616263'", + "SUBSTRING(MD5(RAND()), 1, 10)", "REPEAT(SUBSTRING(MD5(RAND()), 1, 10), 1000000)" )); diff --git a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/utils/Utils.java b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/utils/Utils.java index 9edaadd6c..411ac6f35 100644 --- a/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/utils/Utils.java +++ b/polardbx-test/src/test/java/com/alibaba/polardbx/transfer/utils/Utils.java @@ -39,7 +39,7 @@ public class Utils { // '${user_name}:${password}@tcp(${ip}:${port})/${db_name}' private static final String PATTERN = "(.*):(.*)@tcp\\((.*):(\\d+)\\)/(.*)"; - public static Connection getConnection(String dsn) throws SQLException { + public static Connection getConnection(String dsn, String props) throws SQLException { Pattern regex = Pattern.compile(PATTERN); Matcher matcher = regex.matcher(dsn); if (matcher.find()) { @@ -49,6 +49,9 @@ public static Connection getConnection(String dsn) throws SQLException { String port = matcher.group(4); String dbname = matcher.group(5); String url = "jdbc:mysql://" + host + ":" + port + "/" + dbname; + if (null != props) { + url += "?" + props; + } return DriverManager.getConnection(url, username, password); } throw new RuntimeException("Invalid dsn format, " + @@ -69,6 +72,7 @@ public static void prepare() throws Exception { private static void prepareTransferTest(Toml config) throws SQLException { String dsn = config.getString("dsn"); + String props = config.getString("conn_properties"); int rowCount = Math.toIntExact(config.getLong("row_count")); long initBalance = config.getLong("initial_balance"); assert dsn != null; @@ -76,7 +80,7 @@ private static void prepareTransferTest(Toml config) throws SQLException { assert initBalance > 0; String suffix = config.getString("create_table_suffix", ""); - try (Connection conn = getConnection(dsn); + try (Connection conn = getConnection(dsn, props); Statement stmt = conn.createStatement()) { // create table String createSql = "CREATE TABLE IF NOT EXISTS accounts (" @@ -124,16 +128,14 @@ private static void prepareTransferTest(Toml config) throws SQLException { private static void prepareAllTypesTest(Toml config) throws Exception { String dsn = config.getString("dsn"); + String props = config.getString("conn_properties"); int rowCount = Math.toIntExact(config.getLong("row_count")); long threads = config.getLong("threads", 1L); - boolean bigColumn = config.getBoolean("big_column", false); final List allColumns = new ArrayList<>(AllTypesTestUtils.getColumns()); - if (bigColumn) { - allColumns.addAll(AllTypesTestUtils.getBigColumns()); - } + allColumns.addAll(AllTypesTestUtils.getBigColumns()); String suffix = config.getString("create_table_suffix", ""); - try (Connection conn = getConnection(dsn); + try (Connection conn = getConnection(dsn, props); Statement stmt = conn.createStatement()) { // Create table. String createSql = AllTypesTestUtils.FULL_TYPE_TABLE_TEMPLATE + suffix; @@ -150,12 +152,12 @@ private static void prepareAllTypesTest(Toml config) throws Exception { Callable batchInsert = () -> { long rows = Thread.currentThread().getId() == threadId ? rowsLastThread : rowsEachThread; String sql = null; - try (Connection conn = getConnection(dsn); + try (Connection conn = getConnection(dsn, props); Statement stmt = conn.createStatement()) { stmt.execute("set sql_mode=''"); while (rows > 0) { int currentBatch = (int) Math.min(batch, rows); - sql = AllTypesTestUtils.buildInsertSql(currentBatch, allColumns); + sql = AllTypesTestUtils.buildInsertSql(currentBatch, allColumns, false); stmt.execute(sql); rows -= currentBatch; } @@ -316,12 +318,13 @@ public static List getAccountsWithFlashbackQuery(String hint, Statement return accounts; } - public static void findIncorrectColumns(Toml config) throws Exception { - String dsn = config.getString("dsn"); - try (Connection conn = getConnection(dsn); + public static void findIncorrectColumns() throws Exception { + String dsn = ""; + String props = ""; + try (Connection conn = getConnection(dsn, props); Statement stmt = conn.createStatement()) { Collection columns = AllTypesTestUtils.getColumns(); - String sql = "select check_sum_v2(%s) from full_type"; + String sql = "select check_sum_v2(%s) from full_types"; String hint = "/*+TDDL:WORKLOAD_TYPE=AP ENABLE_MPP=true ENABLE_MASTER_MPP=true ENABLE_COLUMNAR_OPTIMIZER=true OPTIMIZER_TYPE='columnar' ENABLE_HTAP=true */"; for (String column : columns) { @@ -342,4 +345,8 @@ public static void findIncorrectColumns(Toml config) throws Exception { } } } + + public static void main(String[] args) throws Exception { + findIncorrectColumns(); + } } diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci.result b/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci.result index 3020dc973..5a6bcf5a4 100644 --- a/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci.result +++ b/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci.result @@ -100,7 +100,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -130,7 +130,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -160,7 +160,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -190,7 +190,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -220,7 +220,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 9 + PARTITIONS 9 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -251,7 +251,7 @@ t_order_1,CREATE PARTITION TABLE `t_order_1` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`_drds_implicit_id_`) PARTITIONS #@# @@ -281,7 +281,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -311,7 +311,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -341,7 +341,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -370,7 +370,7 @@ t_order_single,CREATE TABLE `t_order_single` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 9 + PARTITIONS 9 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -399,7 +399,7 @@ t_order_single,CREATE TABLE `t_order_single` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -428,7 +428,7 @@ t_order_single,CREATE TABLE `t_order_single` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -457,7 +457,7 @@ t_order_single,CREATE TABLE `t_order_single` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -486,7 +486,7 @@ t_order_single,CREATE TABLE `t_order_single` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -516,7 +516,7 @@ t_order_single_1,CREATE TABLE `t_order_single_1` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -545,7 +545,7 @@ t_order_broadcast,CREATE TABLE `t_order_broadcast` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 9 + PARTITIONS 9 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -574,7 +574,7 @@ t_order_broadcast,CREATE TABLE `t_order_broadcast` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -603,7 +603,7 @@ t_order_broadcast,CREATE TABLE `t_order_broadcast` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -632,7 +632,7 @@ t_order_broadcast,CREATE TABLE `t_order_broadcast` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -661,7 +661,7 @@ t_order_broadcast_1,CREATE TABLE `t_order_broadcast_1` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -681,7 +681,7 @@ heavy_qps_table,CREATE TABLE `heavy_qps_table` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* heavy_qps_table_cci_$ */ `heavy_qps_table_cci` (`id`) PARTITION BY HASH(`id`) - PARTITIONS 4 + PARTITIONS 4 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_hash.result b/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_hash.result index 8b94c7012..22de72a44 100644 --- a/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_hash.result +++ b/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_hash.result @@ -38,7 +38,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_0_$ */ `cci_0` (`seller_id`) PARTITION BY KEY(`seller_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -70,7 +70,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_1_$ */ `cci_1` (`seller_id`) PARTITION BY KEY(`buyer_id`,`order_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -102,7 +102,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_2_$ */ `cci_2` (`seller_id`) PARTITION BY HASH(`seller_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -134,7 +134,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_3_$ */ `cci_3` (`seller_id`) PARTITION BY HASH(`buyer_id`,`order_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -166,7 +166,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_4_$ */ `cci_4` (`seller_id`) PARTITION BY HASH(YEAR(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -198,7 +198,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_5_$ */ `cci_5` (`seller_id`) PARTITION BY HASH(MONTH(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -230,7 +230,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_6_$ */ `cci_6` (`seller_id`) PARTITION BY HASH(DAYOFMONTH(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -262,7 +262,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_7_$ */ `cci_7` (`seller_id`) PARTITION BY HASH(DAYOFWEEK(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -294,7 +294,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_8_$ */ `cci_8` (`seller_id`) PARTITION BY HASH(DAYOFYEAR(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -326,7 +326,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_9_$ */ `cci_9` (`seller_id`) PARTITION BY HASH(TO_DAYS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -358,7 +358,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_10_$ */ `cci_10` (`seller_id`) PARTITION BY HASH(TO_MONTHS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -390,7 +390,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_11_$ */ `cci_11` (`seller_id`) PARTITION BY HASH(TO_WEEKS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -422,7 +422,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_12_$ */ `cci_12` (`seller_id`) PARTITION BY HASH(TO_SECONDS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -454,7 +454,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_13_$ */ `cci_13` (`seller_id`) PARTITION BY HASH(UNIX_TIMESTAMP(`gmt_modified`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -486,7 +486,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_14_$ */ `cci_14` (`seller_id`) PARTITION BY HASH(SUBSTR(`seller_id`,1,4)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -518,7 +518,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_15_$ */ `cci_15` (`seller_id`) PARTITION BY KEY(`seller_id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -550,7 +550,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_16_$ */ `cci_16` (`seller_id`) PARTITION BY HASH(`seller_id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -582,7 +582,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_17_$ */ `cci_17` (`seller_id`) PARTITION BY HASH(SUBSTR(`seller_id`,1,4)) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -614,7 +614,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_18_$ */ `cci_18` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_list.result b/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_list.result index e6841d0cf..135d0d183 100644 --- a/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_list.result +++ b/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_list.result @@ -49,7 +49,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PARTITION BY LIST COLUMNS(`country`,`city`) (PARTITION p1 VALUES IN (('China','Beijing'),('China','Hangzhou')) ENGINE = Columnar, PARTITION p3 VALUES IN (('Russian','Moscow')) ENGINE = Columnar, - PARTITION p2 VALUES IN (('United States','Chicago'),('United States','NewYork')) ENGINE = Columnar) + PARTITION p2 VALUES IN (('United States','Chicago'),('United States','NewYork')) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -91,7 +91,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PARTITION BY LIST(YEAR(`order_datetime`)) (PARTITION p1 VALUES IN (1990,1991,1992,1993,1994,1995,1996,1997,1998,1999) ENGINE = Columnar, PARTITION p2 VALUES IN (2000,2001,2002,2003,2004,2005,2006,2007,2008,2009) ENGINE = Columnar, - PARTITION p3 VALUES IN (2010,2011,2012,2013,2014,2015,2016,2017,2018,2019) ENGINE = Columnar) + PARTITION p3 VALUES IN (2010,2011,2012,2013,2014,2015,2016,2017,2018,2019) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_range.result b/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_range.result index e3918b92e..0b1108eaf 100644 --- a/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_range.result +++ b/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_partition_by_range.result @@ -57,7 +57,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PARTITION p3 VALUES LESS THAN ('30000','2021-01-01 00:00:00') ENGINE = Columnar, PARTITION p4 VALUES LESS THAN ('40000','2021-01-01 00:00:00') ENGINE = Columnar, PARTITION p5 VALUES LESS THAN ('50000','2021-01-01 00:00:00') ENGINE = Columnar, - PARTITION p6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = Columnar) + PARTITION p6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -108,7 +108,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PARTITION p3 VALUES LESS THAN (738337) ENGINE = Columnar, PARTITION p4 VALUES LESS THAN (738429) ENGINE = Columnar, PARTITION p5 VALUES LESS THAN (738521) ENGINE = Columnar, - PARTITION p6 VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) + PARTITION p6 VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_random_suffix.result b/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_random_suffix.result index 5ba851ed7..95e38a469 100644 --- a/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_random_suffix.result +++ b/polardbx-test/src/test/resources/partition/env/AlterTableAddCciTest/test_alter_table_add_cci_random_suffix.result @@ -28,7 +28,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`x`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`x`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`) PARTITIONS #@# @@ -49,7 +49,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`x`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY KEY(`seller_id`) - PARTITIONS 2 + PARTITIONS 2 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`) PARTITIONS #@# @@ -70,7 +70,7 @@ t_order_1,CREATE PARTITION TABLE `t_order_1` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`_drds_implicit_id_`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_ntp.result b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_ntp.result new file mode 100644 index 000000000..48c61e431 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_ntp.result @@ -0,0 +1,413 @@ +## DISABLE_FAST_SQL_PARSER +## h_r_ntp +drop table if exists h_r_ntp1; +drop table if exists h_r_ntp2; +drop table if exists h_r_ntp3; +create table if not exists h_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); +create table if not exists h_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); +create table if not exists h_r_ntp3 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); +alter table h_r_ntp1 drop subpartition p1sp1; +alter table h_r_ntp1 drop subpartition p2sp1,p2sp3; +alter table h_r_ntp2 drop subpartition p1sp1; +alter table h_r_ntp2 drop subpartition p2sp1,p2sp3; +alter table h_r_ntp3 drop subpartition p1sp1; +alter table h_r_ntp3 drop subpartition p2sp1,p2sp3; +show full create table h_r_ntp1; +Table,Create Table +h_r_ntp1,CREATE TABLE `h_r_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +SUBPARTITION BY RANGE(TO_DAYS(`c`)) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES LESS THAN (738156) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table h_r_ntp2; +Table,Create Table +h_r_ntp2,CREATE TABLE `h_r_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +SUBPARTITION BY RANGE(TO_DAYS(`c`)) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES LESS THAN (738156) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table h_r_ntp3; +Table,Create Table +h_r_ntp3,CREATE TABLE `h_r_ntp3` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +SUBPARTITION BY RANGE(TO_DAYS(`c`)) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES LESS THAN (738156) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## h_rc_ntp +drop table if exists h_rc_ntp1; +drop table if exists h_rc_ntp2; +create table if not exists h_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range columns (c,d) +( +partition p1 +( +subpartition p1sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p2sp2 values less than ( '2021-01-01', 'abc' ), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists h_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range columns (c,d) +( +partition p1 +( +subpartition p1sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p2sp2 values less than ( '2021-01-01', 'abc' ), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +alter table h_rc_ntp1 drop subpartition p1sp1; +alter table h_rc_ntp1 drop subpartition p2sp1,p2sp3; +alter table h_rc_ntp2 drop subpartition p1sp1; +alter table h_rc_ntp2 drop subpartition p2sp1,p2sp3; +## error_msg: $# Don't allow to drop all the subpartitions for #$ +alter table h_rc_ntp2 drop subpartition p2sp2; +Don't allow to drop all the subpartitions for +show full create table h_rc_ntp1; +Table,Create Table +h_rc_ntp1,CREATE TABLE `h_rc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +SUBPARTITION BY RANGE COLUMNS(`c`,`d`) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table h_rc_ntp2; +Table,Create Table +h_rc_ntp2,CREATE TABLE `h_rc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +SUBPARTITION BY RANGE COLUMNS(`c`,`d`) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## h_l_ntp +drop table if exists h_l_ntp1; +drop table if exists h_l_ntp2; +create table if not exists h_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by list (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values in ( to_days('2020-01-01') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( to_days('2020-01-01') ), +subpartition p2sp2 values in ( to_days('2021-01-01') ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists h_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by list (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values in ( to_days('2020-01-01') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( to_days('2020-01-01') ), +subpartition p2sp2 values in ( to_days('2021-01-01') ), +subpartition p2sp3 values in ( default ) +) +); +alter table h_l_ntp1 drop subpartition p1sp1; +alter table h_l_ntp1 drop subpartition p2sp1,p2sp3; +alter table h_l_ntp2 drop subpartition p1sp1; +alter table h_l_ntp2 drop subpartition p2sp1,p2sp3; +show full create table h_l_ntp1; +Table,Create Table +h_l_ntp1,CREATE TABLE `h_l_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +SUBPARTITION BY LIST(TO_DAYS(`c`)) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES IN (738156) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table h_l_ntp2; +Table,Create Table +h_l_ntp2,CREATE TABLE `h_l_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +SUBPARTITION BY LIST(TO_DAYS(`c`)) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES IN (738156) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## h_lc_tp +drop table if exists h_lc_ntp1; +drop table if exists h_lc_ntp2; +create table if not exists h_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by list columns (c,d) +( +partition p1 +( +subpartition p1sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p2sp2 values in ( ('2021-01-01', 'abc') ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists h_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by list columns (c,d) +( +partition p1 +( +subpartition p1sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p2sp2 values in ( ('2021-01-01', 'abc') ), +subpartition p2sp3 values in ( default ) +) +); +alter table h_lc_ntp1 drop subpartition p1sp1; +alter table h_lc_ntp1 drop subpartition p2sp1,p2sp3; +alter table h_lc_ntp2 drop subpartition p1sp1; +alter table h_lc_ntp2 drop subpartition p2sp1,p2sp3; +show full create table h_lc_ntp1; +Table,Create Table +h_lc_ntp1,CREATE TABLE `h_lc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +SUBPARTITION BY LIST COLUMNS(`c`,`d`) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table h_lc_ntp2; +Table,Create Table +h_lc_ntp2,CREATE TABLE `h_lc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +SUBPARTITION BY LIST COLUMNS(`c`,`d`) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB)) +/* tablegroup = `tg` */ \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_ntp.test.yml b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_ntp.test.yml new file mode 100644 index 000000000..4415b9622 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_ntp.test.yml @@ -0,0 +1,247 @@ +## DISABLE_FAST_SQL_PARSER +## h_r_ntp +drop table if exists h_r_ntp1; +drop table if exists h_r_ntp2; +drop table if exists h_r_ntp3; +create table if not exists h_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); + +create table if not exists h_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); + +create table if not exists h_r_ntp3 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); + +alter table h_r_ntp1 drop subpartition p1sp1; +alter table h_r_ntp1 drop subpartition p2sp1,p2sp3; +alter table h_r_ntp2 drop subpartition p1sp1; +alter table h_r_ntp2 drop subpartition p2sp1,p2sp3; +alter table h_r_ntp3 drop subpartition p1sp1; +alter table h_r_ntp3 drop subpartition p2sp1,p2sp3; +show full create table h_r_ntp1; +show full create table h_r_ntp2; +show full create table h_r_ntp3; + +## h_rc_ntp +drop table if exists h_rc_ntp1; +drop table if exists h_rc_ntp2; +create table if not exists h_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range columns (c,d) +( +partition p1 +( +subpartition p1sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p2sp2 values less than ( '2021-01-01', 'abc' ), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists h_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range columns (c,d) +( +partition p1 +( +subpartition p1sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p2sp2 values less than ( '2021-01-01', 'abc' ), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); + +alter table h_rc_ntp1 drop subpartition p1sp1; +alter table h_rc_ntp1 drop subpartition p2sp1,p2sp3; +alter table h_rc_ntp2 drop subpartition p1sp1; +alter table h_rc_ntp2 drop subpartition p2sp1,p2sp3; +## error_msg: $# Don't allow to drop all the subpartitions for #$ +alter table h_rc_ntp2 drop subpartition p2sp2; +show full create table h_rc_ntp1; +show full create table h_rc_ntp2; + +## h_l_ntp +drop table if exists h_l_ntp1; +drop table if exists h_l_ntp2; +create table if not exists h_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by list (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values in ( to_days('2020-01-01') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( to_days('2020-01-01') ), +subpartition p2sp2 values in ( to_days('2021-01-01') ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists h_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by list (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values in ( to_days('2020-01-01') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( to_days('2020-01-01') ), +subpartition p2sp2 values in ( to_days('2021-01-01') ), +subpartition p2sp3 values in ( default ) +) +); +alter table h_l_ntp1 drop subpartition p1sp1; +alter table h_l_ntp1 drop subpartition p2sp1,p2sp3; +alter table h_l_ntp2 drop subpartition p1sp1; +alter table h_l_ntp2 drop subpartition p2sp1,p2sp3; +show full create table h_l_ntp1; +show full create table h_l_ntp2; +## h_lc_tp +drop table if exists h_lc_ntp1; +drop table if exists h_lc_ntp2; +create table if not exists h_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by list columns (c,d) +( +partition p1 +( +subpartition p1sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p2sp2 values in ( ('2021-01-01', 'abc') ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists h_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by list columns (c,d) +( +partition p1 +( +subpartition p1sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p2sp2 values in ( ('2021-01-01', 'abc') ), +subpartition p2sp3 values in ( default ) +) +); +alter table h_lc_ntp1 drop subpartition p1sp1; +alter table h_lc_ntp1 drop subpartition p2sp1,p2sp3; +alter table h_lc_ntp2 drop subpartition p1sp1; +alter table h_lc_ntp2 drop subpartition p2sp1,p2sp3; +show full create table h_lc_ntp1; +show full create table h_lc_ntp2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_tp.result b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_tp.result new file mode 100644 index 000000000..baabe931a --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_tp.result @@ -0,0 +1,521 @@ +## DISABLE_FAST_SQL_PARSER + ## h_r_tp +drop table if exists h_r_tp1; +drop table if exists h_r_tp2; +create table if not exists h_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by range (to_days(c)) ( + subpartition sp1 values less than ( to_days('2020-01-01') ), + subpartition sp2 values less than ( maxvalue ) +); +create table if not exists h_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by range (to_days(c)) ( +subpartition sp1 values less than ( to_days('2020-01-01') ), +subpartition sp2 values less than ( maxvalue ) +); +alter table h_r_tp1 drop subpartition sp1; +alter table h_r_tp2 drop subpartition sp1; +show full create table h_r_tp1; +Table,Create Table +h_r_tp1,CREATE TABLE `h_r_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY RANGE(TO_DAYS(`c`)) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +show full create table h_r_tp2; +Table,Create Table +h_r_tp2,CREATE TABLE `h_r_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY RANGE(TO_DAYS(`c`)) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +## h_rc_tp +drop table if exists h_rc_tp1; +drop table if exists h_rc_tp2; +create table if not exists h_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by range columns (c,d) ( +subpartition sp1 values less than ( '2020-01-01', 'abc' ), +subpartition sp2 values less than ( maxvalue, maxvalue ) +); +create table if not exists h_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by range columns (c,d) ( +subpartition sp1 values less than ( '2020-01-01', 'abc' ), +subpartition sp2 values less than ( maxvalue, maxvalue ) +); +alter table h_rc_tp1 drop subpartition sp1; +alter table h_rc_tp2 drop subpartition sp2; +show full create table h_rc_tp1; +Table,Create Table +h_rc_tp1,CREATE TABLE `h_rc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY RANGE COLUMNS(`c`,`d`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +show full create table h_rc_tp2; +Table,Create Table +h_rc_tp2,CREATE TABLE `h_rc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY RANGE COLUMNS(`c`,`d`) +(SUBPARTITION sp1 VALUES LESS THAN ('2020-01-01 00:00:00','abc')) +/* tablegroup = `tg` */ +## h_l_tp +drop table if exists h_l_tp1; +drop table if exists h_l_tp2; +create table if not exists h_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by list (to_days(c)) ( +subpartition sp1 values in ( to_days('2020-01-01') ), +subpartition sp2 values in ( default ) +); +create table if not exists h_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by list (to_days(c)) ( +subpartition sp1 values in ( to_days('2020-01-01') ), +subpartition sp2 values in ( default ) +); +alter table h_l_tp1 drop subpartition sp1; +alter table h_l_tp2 drop subpartition sp1; +show full create table h_l_tp1; +Table,Create Table +h_l_tp1,CREATE TABLE `h_l_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY LIST(TO_DAYS(`c`)) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table h_l_tp2; +Table,Create Table +h_l_tp2,CREATE TABLE `h_l_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY LIST(TO_DAYS(`c`)) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +## h_lc_tp +drop table if exists h_lc_tp1; +drop table if exists h_lc_tp2; +create table if not exists h_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by list columns (c,d) ( +subpartition sp1 values in ( ('2020-01-01','abc') ), +subpartition sp2 values in ( default ) +); +create table if not exists h_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by list columns (c,d) ( +subpartition sp1 values in ( ('2020-01-01','abc') ), +subpartition sp2 values in ( default ) +); +alter table h_lc_tp1 drop subpartition sp1; +alter table h_lc_tp2 drop subpartition sp2; +show full create table h_lc_tp1; +Table,Create Table +h_lc_tp1,CREATE TABLE `h_lc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY LIST COLUMNS(`c`,`d`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table h_lc_tp2; +Table,Create Table +h_lc_tp2,CREATE TABLE `h_lc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY LIST COLUMNS(`c`,`d`) +(SUBPARTITION sp1 VALUES IN (('2020-01-01 00:00:00','abc'))) +/* tablegroup = `tg` */ +## k_r_tp +drop table if exists k_r_tp1; +drop table if exists k_r_tp2; +create table if not exists k_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by range (to_days(c)) ( +subpartition sp1 values less than ( to_days('2020-01-01') ), +subpartition sp2 values less than ( maxvalue ) +); +create table if not exists k_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by range (to_days(c)) ( +subpartition sp1 values less than ( to_days('2020-01-01') ), +subpartition sp2 values less than ( maxvalue ) +); +alter table k_r_tp1 drop subpartition sp1; +alter table k_r_tp2 drop subpartition sp2; +show full create table k_r_tp1; +Table,Create Table +k_r_tp1,CREATE TABLE `k_r_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY RANGE(TO_DAYS(`c`)) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +show full create table k_r_tp2; +Table,Create Table +k_r_tp2,CREATE TABLE `k_r_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY RANGE(TO_DAYS(`c`)) +(SUBPARTITION sp1 VALUES LESS THAN (737790)) +/* tablegroup = `tg` */ +## k_rc_tp +drop table if exists k_rc_tp1; +drop table if exists k_rc_tp2; +create table if not exists k_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by range columns (c,d) ( +subpartition sp1 values less than ( '2020-01-01', 'abc' ), +subpartition sp2 values less than ( maxvalue, maxvalue ) +); +create table if not exists k_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by range columns (c,d) ( +subpartition sp1 values less than ( '2020-01-01', 'abc' ), +subpartition sp2 values less than ( maxvalue, maxvalue ) +); +alter table k_rc_tp1 drop subpartition sp1; +alter table k_rc_tp2 drop subpartition sp1; +show full create table k_rc_tp1; +Table,Create Table +k_rc_tp1,CREATE TABLE `k_rc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY RANGE COLUMNS(`c`,`d`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +show full create table k_rc_tp2; +Table,Create Table +k_rc_tp2,CREATE TABLE `k_rc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY RANGE COLUMNS(`c`,`d`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +## k_l_tp +drop table if exists k_l_tp1; +drop table if exists k_l_tp2; +create table if not exists k_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by list (to_days(c)) ( +subpartition sp1 values in ( to_days('2020-01-01') ), +subpartition sp2 values in ( default ) +); +create table if not exists k_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by list (to_days(c)) ( +subpartition sp1 values in ( to_days('2020-01-01') ), +subpartition sp2 values in ( default ) +); +alter table k_l_tp1 drop subpartition sp1; +alter table k_l_tp2 drop subpartition sp2; +show full create table k_l_tp1; +Table,Create Table +k_l_tp1,CREATE TABLE `k_l_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY LIST(TO_DAYS(`c`)) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table k_l_tp2; +Table,Create Table +k_l_tp2,CREATE TABLE `k_l_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY LIST(TO_DAYS(`c`)) +(SUBPARTITION sp1 VALUES IN (737790)) +/* tablegroup = `tg` */ +## k_lc_tp +drop table if exists k_lc_tp1; +drop table if exists k_lc_tp2; +create table if not exists k_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by list columns (c,d) ( +subpartition sp1 values in ( ('2020-01-01','abc') ), +subpartition sp2 values in ( default ) +); +create table if not exists k_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by list columns (c,d) ( +subpartition sp1 values in ( ('2020-01-01','abc') ), +subpartition sp2 values in ( default ) +); +alter table k_lc_tp1 drop subpartition sp1; +alter table k_lc_tp2 drop subpartition sp2; +show full create table k_lc_tp1; +Table,Create Table +k_lc_tp1,CREATE TABLE `k_lc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY LIST COLUMNS(`c`,`d`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table k_lc_tp2; +Table,Create Table +k_lc_tp2,CREATE TABLE `k_lc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY LIST COLUMNS(`c`,`d`) +(SUBPARTITION sp1 VALUES IN (('2020-01-01 00:00:00','abc'))) +/* tablegroup = `tg` */ \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_tp.test.yml b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_tp.test.yml new file mode 100644 index 000000000..27687f092 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_hash_tp.test.yml @@ -0,0 +1,258 @@ +## DISABLE_FAST_SQL_PARSER + + ## h_r_tp +drop table if exists h_r_tp1; +drop table if exists h_r_tp2; +create table if not exists h_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by range (to_days(c)) ( + subpartition sp1 values less than ( to_days('2020-01-01') ), + subpartition sp2 values less than ( maxvalue ) +); +create table if not exists h_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by range (to_days(c)) ( +subpartition sp1 values less than ( to_days('2020-01-01') ), +subpartition sp2 values less than ( maxvalue ) +); + +alter table h_r_tp1 drop subpartition sp1; +alter table h_r_tp2 drop subpartition sp1; +show full create table h_r_tp1; +show full create table h_r_tp2; + + ## h_rc_tp +drop table if exists h_rc_tp1; +drop table if exists h_rc_tp2; +create table if not exists h_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by range columns (c,d) ( +subpartition sp1 values less than ( '2020-01-01', 'abc' ), +subpartition sp2 values less than ( maxvalue, maxvalue ) +); +create table if not exists h_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by range columns (c,d) ( +subpartition sp1 values less than ( '2020-01-01', 'abc' ), +subpartition sp2 values less than ( maxvalue, maxvalue ) +); +alter table h_rc_tp1 drop subpartition sp1; +alter table h_rc_tp2 drop subpartition sp2; +show full create table h_rc_tp1; +show full create table h_rc_tp2; + + ## h_l_tp +drop table if exists h_l_tp1; +drop table if exists h_l_tp2; +create table if not exists h_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by list (to_days(c)) ( +subpartition sp1 values in ( to_days('2020-01-01') ), +subpartition sp2 values in ( default ) +); +create table if not exists h_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by list (to_days(c)) ( +subpartition sp1 values in ( to_days('2020-01-01') ), +subpartition sp2 values in ( default ) +); +alter table h_l_tp1 drop subpartition sp1; +alter table h_l_tp2 drop subpartition sp1; +show full create table h_l_tp1; +show full create table h_l_tp2; + + ## h_lc_tp +drop table if exists h_lc_tp1; +drop table if exists h_lc_tp2; +create table if not exists h_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by list columns (c,d) ( +subpartition sp1 values in ( ('2020-01-01','abc') ), +subpartition sp2 values in ( default ) +); +create table if not exists h_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by list columns (c,d) ( +subpartition sp1 values in ( ('2020-01-01','abc') ), +subpartition sp2 values in ( default ) +); +alter table h_lc_tp1 drop subpartition sp1; +alter table h_lc_tp2 drop subpartition sp2; +show full create table h_lc_tp1; +show full create table h_lc_tp2; + + ## k_r_tp +drop table if exists k_r_tp1; +drop table if exists k_r_tp2; +create table if not exists k_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by range (to_days(c)) ( +subpartition sp1 values less than ( to_days('2020-01-01') ), +subpartition sp2 values less than ( maxvalue ) +); +create table if not exists k_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by range (to_days(c)) ( +subpartition sp1 values less than ( to_days('2020-01-01') ), +subpartition sp2 values less than ( maxvalue ) +); +alter table k_r_tp1 drop subpartition sp1; +alter table k_r_tp2 drop subpartition sp2; +show full create table k_r_tp1; +show full create table k_r_tp2; + + ## k_rc_tp +drop table if exists k_rc_tp1; +drop table if exists k_rc_tp2; +create table if not exists k_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by range columns (c,d) ( +subpartition sp1 values less than ( '2020-01-01', 'abc' ), +subpartition sp2 values less than ( maxvalue, maxvalue ) +); +create table if not exists k_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by range columns (c,d) ( +subpartition sp1 values less than ( '2020-01-01', 'abc' ), +subpartition sp2 values less than ( maxvalue, maxvalue ) +); +alter table k_rc_tp1 drop subpartition sp1; +alter table k_rc_tp2 drop subpartition sp1; +show full create table k_rc_tp1; +show full create table k_rc_tp2; + + ## k_l_tp +drop table if exists k_l_tp1; +drop table if exists k_l_tp2; +create table if not exists k_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by list (to_days(c)) ( +subpartition sp1 values in ( to_days('2020-01-01') ), +subpartition sp2 values in ( default ) +); +create table if not exists k_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by list (to_days(c)) ( +subpartition sp1 values in ( to_days('2020-01-01') ), +subpartition sp2 values in ( default ) +); +alter table k_l_tp1 drop subpartition sp1; +alter table k_l_tp2 drop subpartition sp2; +show full create table k_l_tp1; +show full create table k_l_tp2; + + ## k_lc_tp +drop table if exists k_lc_tp1; +drop table if exists k_lc_tp2; +create table if not exists k_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by list columns (c,d) ( +subpartition sp1 values in ( ('2020-01-01','abc') ), +subpartition sp2 values in ( default ) +); +create table if not exists k_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 4 +subpartition by list columns (c,d) ( +subpartition sp1 values in ( ('2020-01-01','abc') ), +subpartition sp2 values in ( default ) +); +alter table k_lc_tp1 drop subpartition sp1; +alter table k_lc_tp2 drop subpartition sp2; +show full create table k_lc_tp1; +show full create table k_lc_tp2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_key_ntp.result b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_key_ntp.result new file mode 100644 index 000000000..20d6cef85 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_key_ntp.result @@ -0,0 +1,368 @@ +## DISABLE_FAST_SQL_PARSER +## k_r_ntp +drop table if exists k_r_ntp1; +drop table if exists k_r_ntp1; +create table if not exists k_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); +create table if not exists k_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); +alter table k_r_ntp1 drop subpartition p1sp1; +alter table k_r_ntp1 drop subpartition p2sp1,p2sp3; +alter table k_r_ntp2 drop subpartition p1sp1; +alter table k_r_ntp2 drop subpartition p2sp1,p2sp3; +show full create table k_r_ntp1; +Table,Create Table +k_r_ntp1,CREATE TABLE `k_r_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +SUBPARTITION BY RANGE(TO_DAYS(`c`)) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES LESS THAN (738156) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table k_r_ntp2; +Table,Create Table +k_r_ntp2,CREATE TABLE `k_r_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +SUBPARTITION BY RANGE(TO_DAYS(`c`)) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES LESS THAN (738156) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## k_rc_ntp +drop table if exists k_rc_ntp1; +drop table if exists k_rc_ntp2; +create table if not exists k_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by range columns (c,d) +( +partition p1 +( +subpartition p1sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p2sp2 values less than ( '2021-01-01', 'abc' ), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists k_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by range columns (c,d) +( +partition p1 +( +subpartition p1sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p2sp2 values less than ( '2021-01-01', 'abc' ), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +alter table k_rc_ntp1 drop subpartition p1sp1; +alter table k_rc_ntp1 drop subpartition p2sp1,p2sp3; +alter table k_rc_ntp2 drop subpartition p1sp1; +alter table k_rc_ntp2 drop subpartition p2sp1,p2sp3; +show full create table k_rc_ntp1; +Table,Create Table +k_rc_ntp1,CREATE TABLE `k_rc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +SUBPARTITION BY RANGE COLUMNS(`c`,`d`) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table k_rc_ntp2; +Table,Create Table +k_rc_ntp2,CREATE TABLE `k_rc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +SUBPARTITION BY RANGE COLUMNS(`c`,`d`) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## k_l_ntp +drop table if exists k_l_ntp1; +drop table if exists k_l_ntp2; +create table if not exists k_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by list (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values in ( to_days('2020-01-01') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( to_days('2020-01-01') ), +subpartition p2sp2 values in ( to_days('2021-01-01') ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists k_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by list (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values in ( to_days('2020-01-01') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( to_days('2020-01-01') ), +subpartition p2sp2 values in ( to_days('2021-01-01') ), +subpartition p2sp3 values in ( default ) +) +); +alter table k_l_ntp1 drop subpartition p1sp1; +alter table k_l_ntp1 drop subpartition p2sp1,p2sp3; +alter table k_l_ntp2 drop subpartition p1sp1; +alter table k_l_ntp2 drop subpartition p2sp1,p2sp3; +show full create table k_l_ntp1; +Table,Create Table +k_l_ntp1,CREATE TABLE `k_l_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +SUBPARTITION BY LIST(TO_DAYS(`c`)) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES IN (738156) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table k_l_ntp2; +Table,Create Table +k_l_ntp2,CREATE TABLE `k_l_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +SUBPARTITION BY LIST(TO_DAYS(`c`)) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES IN (738156) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## k_lc_tp +drop table if exists k_lc_ntp1; +drop table if exists k_lc_ntp2; +create table if not exists k_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by list columns (c,d) +( +partition p1 +( +subpartition p1sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p2sp2 values in ( ('2021-01-01', 'abc') ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists k_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by list columns (c,d) +( +partition p1 +( +subpartition p1sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p2sp2 values in ( ('2021-01-01', 'abc') ), +subpartition p2sp3 values in ( default ) +) +); +alter table k_lc_ntp1 drop subpartition p1sp1; +alter table k_lc_ntp1 drop subpartition p2sp1,p2sp3; +alter table k_lc_ntp2 drop subpartition p1sp1; +alter table k_lc_ntp2 drop subpartition p2sp1,p2sp3; +## error_msg: $# Don't allow to drop all the subpartitions for #$ +alter table k_lc_ntp2 drop subpartition p2sp2; +Don't allow to drop all the subpartitions for +show full create table k_lc_ntp1; +Table,Create Table +k_lc_ntp1,CREATE TABLE `k_lc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +SUBPARTITION BY LIST COLUMNS(`c`,`d`) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table k_lc_ntp2; +Table,Create Table +k_lc_ntp2,CREATE TABLE `k_lc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +SUBPARTITION BY LIST COLUMNS(`c`,`d`) +(PARTITION p1 + (SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB)) +/* tablegroup = `tg` */ \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_key_ntp.test.yml b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_key_ntp.test.yml new file mode 100644 index 000000000..687f78044 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_key_ntp.test.yml @@ -0,0 +1,218 @@ +## DISABLE_FAST_SQL_PARSER +## k_r_ntp +drop table if exists k_r_ntp1; +drop table if exists k_r_ntp1; +create table if not exists k_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); +create table if not exists k_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); +alter table k_r_ntp1 drop subpartition p1sp1; +alter table k_r_ntp1 drop subpartition p2sp1,p2sp3; +alter table k_r_ntp2 drop subpartition p1sp1; +alter table k_r_ntp2 drop subpartition p2sp1,p2sp3; +show full create table k_r_ntp1; +show full create table k_r_ntp2; +## k_rc_ntp +drop table if exists k_rc_ntp1; +drop table if exists k_rc_ntp2; +create table if not exists k_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by range columns (c,d) +( +partition p1 +( +subpartition p1sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p2sp2 values less than ( '2021-01-01', 'abc' ), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists k_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by range columns (c,d) +( +partition p1 +( +subpartition p1sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( '2020-01-01', 'abc' ), +subpartition p2sp2 values less than ( '2021-01-01', 'abc' ), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +alter table k_rc_ntp1 drop subpartition p1sp1; +alter table k_rc_ntp1 drop subpartition p2sp1,p2sp3; +alter table k_rc_ntp2 drop subpartition p1sp1; +alter table k_rc_ntp2 drop subpartition p2sp1,p2sp3; +show full create table k_rc_ntp1; +show full create table k_rc_ntp2; + +## k_l_ntp +drop table if exists k_l_ntp1; +drop table if exists k_l_ntp2; +create table if not exists k_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by list (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values in ( to_days('2020-01-01') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( to_days('2020-01-01') ), +subpartition p2sp2 values in ( to_days('2021-01-01') ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists k_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by list (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values in ( to_days('2020-01-01') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( to_days('2020-01-01') ), +subpartition p2sp2 values in ( to_days('2021-01-01') ), +subpartition p2sp3 values in ( default ) +) +); +alter table k_l_ntp1 drop subpartition p1sp1; +alter table k_l_ntp1 drop subpartition p2sp1,p2sp3; +alter table k_l_ntp2 drop subpartition p1sp1; +alter table k_l_ntp2 drop subpartition p2sp1,p2sp3; +show full create table k_l_ntp1; +show full create table k_l_ntp2; + +## k_lc_tp +drop table if exists k_lc_ntp1; +drop table if exists k_lc_ntp2; +create table if not exists k_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by list columns (c,d) +( +partition p1 +( +subpartition p1sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p2sp2 values in ( ('2021-01-01', 'abc') ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists k_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by key (a,b) partitions 2 +subpartition by list columns (c,d) +( +partition p1 +( +subpartition p1sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p1sp2 values in ( default ) +), +partition p2 +( +subpartition p2sp1 values in ( ('2020-01-01', 'abc') ), +subpartition p2sp2 values in ( ('2021-01-01', 'abc') ), +subpartition p2sp3 values in ( default ) +) +); + +alter table k_lc_ntp1 drop subpartition p1sp1; +alter table k_lc_ntp1 drop subpartition p2sp1,p2sp3; +alter table k_lc_ntp2 drop subpartition p1sp1; +alter table k_lc_ntp2 drop subpartition p2sp1,p2sp3; +## error_msg: $# Don't allow to drop all the subpartitions for #$ +alter table k_lc_ntp2 drop subpartition p2sp2; +show full create table k_lc_ntp1; +show full create table k_lc_ntp2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_ntp.result b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_ntp.result new file mode 100644 index 000000000..328bc9e82 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_ntp.result @@ -0,0 +1,1005 @@ +## DISABLE_FAST_SQL_PARSER +######### + ## l_h_ntp +drop table if exists l_h_ntp1; +drop table if exists l_h_ntp2; +create table if not exists l_h_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by hash (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values in ( to_days('2021-11-01') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3 +); +create table if not exists l_h_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by hash (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values in ( to_days('2021-11-01') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3); +alter table l_h_ntp1 drop partition p1; +alter table l_h_ntp1 drop partition p3; +alter table l_h_ntp2 drop partition p1,p3; +show full create table l_h_ntp1; +Table,Create Table +l_h_ntp1,CREATE TABLE `l_h_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY HASH(`a`,`b`) +(PARTITION p2 VALUES IN (738460) + (SUBPARTITION p2sp1 ENGINE = InnoDB, + SUBPARTITION p2sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table l_h_ntp2; +Table,Create Table +l_h_ntp2,CREATE TABLE `l_h_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY HASH(`a`,`b`) +(PARTITION p2 VALUES IN (738460) + (SUBPARTITION p2sp1 ENGINE = InnoDB, + SUBPARTITION p2sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## l_k_ntp +drop table if exists l_k_ntp1; +drop table if exists l_k_ntp2; +create table if not exists l_k_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by key (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values in ( to_days('2021-11-01') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3); +create table if not exists l_k_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by key (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values in ( to_days('2021-11-01') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3); +alter table l_k_ntp1 drop partition p1; +alter table l_k_ntp1 drop partition p3; +alter table l_k_ntp2 drop partition p1,p3; +show full create table l_k_ntp1; +Table,Create Table +l_k_ntp1,CREATE TABLE `l_k_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY KEY(`a`,`b`) +(PARTITION p2 VALUES IN (738460) + (SUBPARTITION p2sp1 ENGINE = InnoDB, + SUBPARTITION p2sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table l_k_ntp2; +Table,Create Table +l_k_ntp2,CREATE TABLE `l_k_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY KEY(`a`,`b`) +(PARTITION p2 VALUES IN (738460) + (SUBPARTITION p2sp1 ENGINE = InnoDB, + SUBPARTITION p2sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## l_r_ntp +drop table if exists l_r_ntp1; +drop table if exists l_r_ntp2; +create table if not exists l_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range (a) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values in ( to_days('2023-01-01') ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000), +subpartition p3sp2 values less than ( 2000), +subpartition p3sp3 values less than ( maxvalue ) +) +); +create table if not exists l_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range (a) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values in ( to_days('2023-01-01') ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000), +subpartition p3sp2 values less than ( 2000), +subpartition p3sp3 values less than ( maxvalue ) +) +); +alter table l_r_ntp1 drop subpartition p1sp1,p1sp2; +alter table l_r_ntp1 drop subpartition p2sp1,p3sp2; +alter table l_r_ntp1 drop partition p3; +alter table l_r_ntp2 drop subpartition p1sp1,p1sp2; +alter table l_r_ntp2 drop subpartition p2sp1,p3sp2; +alter table l_r_ntp2 drop partition p3; +show full create table l_r_ntp1; +Table,Create Table +l_r_ntp1,CREATE TABLE `l_r_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY RANGE(`a`) +(PARTITION p2 VALUES IN (738886) + (SUBPARTITION p2sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table l_r_ntp2; +Table,Create Table +l_r_ntp2,CREATE TABLE `l_r_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY RANGE(`a`) +(PARTITION p2 VALUES IN (738886) + (SUBPARTITION p2sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## l_rc_ntp +drop table if exists l_rc_ntp1; +drop table if exists l_rc_ntp2; +create table if not exists l_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range columns (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values in ( to_days('2024-01-01') ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( maxvalue, maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000, 10000), +subpartition p3sp2 values less than ( 2000, 10000), +subpartition p3sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists l_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range columns (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values in ( to_days('2024-01-01') ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( maxvalue, maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000, 10000), +subpartition p3sp2 values less than ( 2000, 10000), +subpartition p3sp3 values less than ( maxvalue, maxvalue ) +) +); +alter table l_rc_ntp1 drop subpartition p1sp1,p1sp2; +alter table l_rc_ntp1 drop subpartition p2sp1,p3sp2; +alter table l_rc_ntp1 drop partition p3; +alter table l_rc_ntp2 drop subpartition p1sp1,p1sp2; +alter table l_rc_ntp2 drop subpartition p2sp1,p3sp2; +alter table l_rc_ntp2 drop partition p3; +show full create table l_rc_ntp1; +Table,Create Table +l_rc_ntp1,CREATE TABLE `l_rc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p2 VALUES IN (739251) + (SUBPARTITION p2sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table l_rc_ntp2; +Table,Create Table +l_rc_ntp2,CREATE TABLE `l_rc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p2 VALUES IN (739251) + (SUBPARTITION p2sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## l_l_ntp +drop table if exists l_l_ntp1; +drop table if exists l_l_ntp2; +create table if not exists l_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list (a) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( to_days('2023-11-01') ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( default ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values in ( 1000, 2000), +subpartition p3sp2 values in ( 3000, 4000), +subpartition p3sp3 values in ( default ) +) +); +create table if not exists l_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list (a) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( to_days('2023-11-01') ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( default ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values in ( 1000, 2000), +subpartition p3sp2 values in ( 3000, 4000), +subpartition p3sp3 values in ( default ) +) +); +alter table l_l_ntp1 drop subpartition p1sp1,p1sp2,p2sp1; +alter table l_l_ntp1 drop partition p3; +alter table l_l_ntp2 drop subpartition p1sp1,p1sp2,p2sp1; +alter table l_l_ntp2 drop subpartition p3sp1; +show full create table l_l_ntp1; +Table,Create Table +l_l_ntp1,CREATE TABLE `l_l_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY LIST(`a`) +(PARTITION p2 VALUES IN (739190) + (SUBPARTITION p2sp2 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table l_l_ntp2; +Table,Create Table +l_l_ntp2,CREATE TABLE `l_l_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY LIST(`a`) +(PARTITION p2 VALUES IN (739190) + (SUBPARTITION p2sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p3 VALUES IN (DEFAULT) + (SUBPARTITION p3sp2 VALUES IN (3000,4000) ENGINE = InnoDB, + SUBPARTITION p3sp3 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## l_lc_ntp +drop table if exists l_lc_ntp1; +drop table if exists l_lc_ntp2; +create table if not exists l_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list columns (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( to_days('2022-01-01') ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( default ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values in ( (1000, 2000) ), +subpartition p3sp2 values in ( (2000, 2000) ), +subpartition p3sp3 values in ( default ) +) +); +create table if not exists l_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list columns (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( to_days('2022-01-01') ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( default ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values in ( (1000, 2000) ), +subpartition p3sp2 values in ( (2000, 2000) ), +subpartition p3sp3 values in ( default ) +) +); +alter table l_lc_ntp1 drop subpartition p1sp1,p1sp2,p2sp1; +alter table l_lc_ntp1 drop partition p3; +alter table l_lc_ntp2 drop subpartition p1sp1,p1sp2,p2sp1; +alter table l_lc_ntp2 drop subpartition p3sp1; +show full create table l_lc_ntp1; +Table,Create Table +l_lc_ntp1,CREATE TABLE `l_lc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p2 VALUES IN (738521) + (SUBPARTITION p2sp2 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table l_lc_ntp2; +Table,Create Table +l_lc_ntp2,CREATE TABLE `l_lc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p2 VALUES IN (738521) + (SUBPARTITION p2sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p3 VALUES IN (DEFAULT) + (SUBPARTITION p3sp2 VALUES IN ((2000,2000)) ENGINE = InnoDB, + SUBPARTITION p3sp3 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## lc_h_ntp +drop table if exists lc_h_ntp1; +drop table if exists lc_h_ntp2; +create table if not exists lc_h_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by hash (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) subpartitions 2, +partition p2 values in ( ('2022-01-01', 'abc') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3 +); +create table if not exists lc_h_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by hash (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) subpartitions 2, +partition p2 values in ( ('2022-01-01', 'abc') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3 +); +alter table lc_h_ntp1 drop partition p1; +alter table lc_h_ntp1 drop partition p3; +alter table lc_h_ntp2 drop partition p1,p3; +show full create table lc_h_ntp1; +Table,Create Table +lc_h_ntp1,CREATE TABLE `lc_h_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY HASH(`a`,`b`) +(PARTITION p2 VALUES IN (('2022-01-01 00:00:00','abc')) + (SUBPARTITION p2sp1 ENGINE = InnoDB, + SUBPARTITION p2sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table lc_h_ntp2; +Table,Create Table +lc_h_ntp2,CREATE TABLE `lc_h_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY HASH(`a`,`b`) +(PARTITION p2 VALUES IN (('2022-01-01 00:00:00','abc')) + (SUBPARTITION p2sp1 ENGINE = InnoDB, + SUBPARTITION p2sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## lc_k_ntp +drop table if exists lc_k_ntp1; +drop table if exists lc_k_ntp2; +create table if not exists lc_k_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by key (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) subpartitions 2, +partition p2 values in ( ('2022-01-01', 'abc') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3 +); +create table if not exists lc_k_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by key (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) subpartitions 2, +partition p2 values in ( ('2022-01-01', 'abc') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3 +); +alter table lc_k_ntp1 drop partition p1; +alter table lc_k_ntp1 drop partition p3; +alter table lc_k_ntp2 drop partition p1,p3; +show full create table lc_k_ntp1; +Table,Create Table +lc_k_ntp1,CREATE TABLE `lc_k_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY KEY(`a`,`b`) +(PARTITION p2 VALUES IN (('2022-01-01 00:00:00','abc')) + (SUBPARTITION p2sp1 ENGINE = InnoDB, + SUBPARTITION p2sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table lc_k_ntp2; +Table,Create Table +lc_k_ntp2,CREATE TABLE `lc_k_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY KEY(`a`,`b`) +(PARTITION p2 VALUES IN (('2022-01-01 00:00:00','abc')) + (SUBPARTITION p2sp1 ENGINE = InnoDB, + SUBPARTITION p2sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## lc_r_ntp +drop table if exists lc_r_ntp1; +drop table if exists lc_r_ntp2; +create table if not exists lc_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range (a) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values in ( ('2022-01-01', 'abc') ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000), +subpartition p3sp2 values less than ( 2000), +subpartition p3sp3 values less than ( maxvalue ) +) +); +create table if not exists lc_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range (a) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values in ( ('2022-01-01', 'abc') ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000), +subpartition p3sp2 values less than ( 2000), +subpartition p3sp3 values less than ( maxvalue ) +) +); +alter table lc_r_ntp1 drop subpartition p1sp1,p1sp2; +alter table lc_r_ntp1 drop subpartition p2sp1,p3sp2; +alter table lc_r_ntp1 drop partition p3; +alter table lc_r_ntp2 drop subpartition p1sp1,p1sp2; +alter table lc_r_ntp2 drop subpartition p2sp1,p3sp2; +alter table lc_r_ntp2 drop partition p3; +show full create table lc_r_ntp1; +Table,Create Table +lc_r_ntp1,CREATE TABLE `lc_r_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE(`a`) +(PARTITION p2 VALUES IN (('2022-01-01 00:00:00','abc')) + (SUBPARTITION p2sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table lc_r_ntp2; +Table,Create Table +lc_r_ntp2,CREATE TABLE `lc_r_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE(`a`) +(PARTITION p2 VALUES IN (('2022-01-01 00:00:00','abc')) + (SUBPARTITION p2sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## lc_rc_ntp +drop table if exists lc_rc_ntp1; +drop table if exists lc_rc_ntp2; +create table if not exists lc_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range columns (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( 2000, 10000), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists lc_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range columns (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( 2000, 10000), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +alter table lc_rc_ntp1 drop subpartition p1sp1,p1sp2; +alter table lc_rc_ntp2 drop subpartition p1sp1,p2sp2; +alter table lc_rc_ntp2 drop partition p2; +show full create table lc_rc_ntp1; +Table,Create Table +lc_rc_ntp1,CREATE TABLE `lc_rc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p2 VALUES IN (DEFAULT) + (SUBPARTITION p2sp1 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, + SUBPARTITION p2sp2 VALUES LESS THAN (2000,10000) ENGINE = InnoDB, + SUBPARTITION p2sp3 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table lc_rc_ntp2; +Table,Create Table +lc_rc_ntp2,CREATE TABLE `lc_rc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p1 VALUES IN (('2020-01-01 00:00:00','abc')) + (SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## lc_l_tp +drop table if exists lc_l_ntp1; +drop table if exists lc_l_ntp2; +create table if not exists lc_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list (a) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists lc_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list (a) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +alter table lc_l_ntp1 drop subpartition p1sp1,p1sp2; +alter table lc_l_ntp2 drop subpartition p1sp1,p2sp2; +alter table lc_l_ntp2 drop partition p2; +show full create table lc_l_ntp1; +Table,Create Table +lc_l_ntp1,CREATE TABLE `lc_l_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY LIST(`a`) +(PARTITION p2 VALUES IN (DEFAULT) + (SUBPARTITION p2sp1 VALUES IN (1000,2000) ENGINE = InnoDB, + SUBPARTITION p2sp2 VALUES IN (3000,4000) ENGINE = InnoDB, + SUBPARTITION p2sp3 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table lc_l_ntp2; +Table,Create Table +lc_l_ntp2,CREATE TABLE `lc_l_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY LIST(`a`) +(PARTITION p1 VALUES IN (('2020-01-01 00:00:00','abc')) + (SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## lc_lc_ntp +drop table if exists lc_lc_ntp1; +drop table if exists lc_lc_ntp2; +create table if not exists lc_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list columns (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( (2000, 2000) ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists lc_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list columns (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( (2000, 2000) ), +subpartition p2sp3 values in ( default ) +) +); +alter table lc_lc_ntp1 drop partition p1; +alter table lc_lc_ntp1 drop subpartition p2sp1,p2sp3; +alter table lc_lc_ntp2 drop subpartition p2sp1,p2sp2,p2sp3; +show full create table lc_lc_ntp1; +Table,Create Table +lc_lc_ntp1,CREATE TABLE `lc_lc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p2 VALUES IN (DEFAULT) + (SUBPARTITION p2sp2 VALUES IN ((2000,2000)) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table lc_lc_ntp2; +Table,Create Table +lc_lc_ntp2,CREATE TABLE `lc_lc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p1 VALUES IN (('2020-01-01 00:00:00','abc')) + (SUBPARTITION p1sp1 VALUES IN ((1000,2000)) ENGINE = InnoDB, + SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_ntp.test.yml b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_ntp.test.yml new file mode 100644 index 000000000..be4110acf --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_ntp.test.yml @@ -0,0 +1,592 @@ +## DISABLE_FAST_SQL_PARSER +######### + ## l_h_ntp +drop table if exists l_h_ntp1; +drop table if exists l_h_ntp2; +create table if not exists l_h_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by hash (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values in ( to_days('2021-11-01') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3 +); +create table if not exists l_h_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by hash (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values in ( to_days('2021-11-01') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3); + +alter table l_h_ntp1 drop partition p1; +alter table l_h_ntp1 drop partition p3; +alter table l_h_ntp2 drop partition p1,p3; +show full create table l_h_ntp1; +show full create table l_h_ntp2; + +## l_k_ntp +drop table if exists l_k_ntp1; +drop table if exists l_k_ntp2; +create table if not exists l_k_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by key (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values in ( to_days('2021-11-01') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3); + +create table if not exists l_k_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by key (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values in ( to_days('2021-11-01') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3); + +alter table l_k_ntp1 drop partition p1; +alter table l_k_ntp1 drop partition p3; +alter table l_k_ntp2 drop partition p1,p3; +show full create table l_k_ntp1; +show full create table l_k_ntp2; + +## l_r_ntp +drop table if exists l_r_ntp1; +drop table if exists l_r_ntp2; +create table if not exists l_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range (a) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values in ( to_days('2023-01-01') ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000), +subpartition p3sp2 values less than ( 2000), +subpartition p3sp3 values less than ( maxvalue ) +) +); +create table if not exists l_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range (a) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values in ( to_days('2023-01-01') ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000), +subpartition p3sp2 values less than ( 2000), +subpartition p3sp3 values less than ( maxvalue ) +) +); +alter table l_r_ntp1 drop subpartition p1sp1,p1sp2; +alter table l_r_ntp1 drop subpartition p2sp1,p3sp2; +alter table l_r_ntp1 drop partition p3; +alter table l_r_ntp2 drop subpartition p1sp1,p1sp2; +alter table l_r_ntp2 drop subpartition p2sp1,p3sp2; +alter table l_r_ntp2 drop partition p3; +show full create table l_r_ntp1; +show full create table l_r_ntp2; + +## l_rc_ntp +drop table if exists l_rc_ntp1; +drop table if exists l_rc_ntp2; +create table if not exists l_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range columns (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values in ( to_days('2024-01-01') ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( maxvalue, maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000, 10000), +subpartition p3sp2 values less than ( 2000, 10000), +subpartition p3sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists l_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range columns (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values in ( to_days('2024-01-01') ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( maxvalue, maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000, 10000), +subpartition p3sp2 values less than ( 2000, 10000), +subpartition p3sp3 values less than ( maxvalue, maxvalue ) +) +); +alter table l_rc_ntp1 drop subpartition p1sp1,p1sp2; +alter table l_rc_ntp1 drop subpartition p2sp1,p3sp2; +alter table l_rc_ntp1 drop partition p3; +alter table l_rc_ntp2 drop subpartition p1sp1,p1sp2; +alter table l_rc_ntp2 drop subpartition p2sp1,p3sp2; +alter table l_rc_ntp2 drop partition p3; +show full create table l_rc_ntp1; +show full create table l_rc_ntp2; + +## l_l_ntp +drop table if exists l_l_ntp1; +drop table if exists l_l_ntp2; +create table if not exists l_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list (a) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( to_days('2023-11-01') ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( default ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values in ( 1000, 2000), +subpartition p3sp2 values in ( 3000, 4000), +subpartition p3sp3 values in ( default ) +) +); +create table if not exists l_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list (a) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( to_days('2023-11-01') ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( default ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values in ( 1000, 2000), +subpartition p3sp2 values in ( 3000, 4000), +subpartition p3sp3 values in ( default ) +) +); +alter table l_l_ntp1 drop subpartition p1sp1,p1sp2,p2sp1; +alter table l_l_ntp1 drop partition p3; +alter table l_l_ntp2 drop subpartition p1sp1,p1sp2,p2sp1; +alter table l_l_ntp2 drop subpartition p3sp1; +show full create table l_l_ntp1; +show full create table l_l_ntp2; + +## l_lc_ntp +drop table if exists l_lc_ntp1; +drop table if exists l_lc_ntp2; +create table if not exists l_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list columns (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( to_days('2022-01-01') ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( default ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values in ( (1000, 2000) ), +subpartition p3sp2 values in ( (2000, 2000) ), +subpartition p3sp3 values in ( default ) +) +); +create table if not exists l_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list columns (a,b) +( +partition p1 values in ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( to_days('2022-01-01') ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( default ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values in ( (1000, 2000) ), +subpartition p3sp2 values in ( (2000, 2000) ), +subpartition p3sp3 values in ( default ) +) +); +alter table l_lc_ntp1 drop subpartition p1sp1,p1sp2,p2sp1; +alter table l_lc_ntp1 drop partition p3; +alter table l_lc_ntp2 drop subpartition p1sp1,p1sp2,p2sp1; +alter table l_lc_ntp2 drop subpartition p3sp1; +show full create table l_lc_ntp1; +show full create table l_lc_ntp2; + +## lc_h_ntp +drop table if exists lc_h_ntp1; +drop table if exists lc_h_ntp2; +create table if not exists lc_h_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by hash (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) subpartitions 2, +partition p2 values in ( ('2022-01-01', 'abc') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3 +); +create table if not exists lc_h_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by hash (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) subpartitions 2, +partition p2 values in ( ('2022-01-01', 'abc') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3 +); +alter table lc_h_ntp1 drop partition p1; +alter table lc_h_ntp1 drop partition p3; +alter table lc_h_ntp2 drop partition p1,p3; +show full create table lc_h_ntp1; +show full create table lc_h_ntp2; + +## lc_k_ntp +drop table if exists lc_k_ntp1; +drop table if exists lc_k_ntp2; +create table if not exists lc_k_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by key (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) subpartitions 2, +partition p2 values in ( ('2022-01-01', 'abc') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3 +); +create table if not exists lc_k_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by key (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) subpartitions 2, +partition p2 values in ( ('2022-01-01', 'abc') ) subpartitions 2, +partition p3 values in ( default ) subpartitions 3 +); +alter table lc_k_ntp1 drop partition p1; +alter table lc_k_ntp1 drop partition p3; +alter table lc_k_ntp2 drop partition p1,p3; +show full create table lc_k_ntp1; +show full create table lc_k_ntp2; + +## lc_r_ntp +drop table if exists lc_r_ntp1; +drop table if exists lc_r_ntp2; +create table if not exists lc_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range (a) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values in ( ('2022-01-01', 'abc') ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000), +subpartition p3sp2 values less than ( 2000), +subpartition p3sp3 values less than ( maxvalue ) +) +); +create table if not exists lc_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range (a) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values in ( ('2022-01-01', 'abc') ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values in ( default ) ( +subpartition p3sp1 values less than ( 1000), +subpartition p3sp2 values less than ( 2000), +subpartition p3sp3 values less than ( maxvalue ) +) +); +alter table lc_r_ntp1 drop subpartition p1sp1,p1sp2; +alter table lc_r_ntp1 drop subpartition p2sp1,p3sp2; +alter table lc_r_ntp1 drop partition p3; +alter table lc_r_ntp2 drop subpartition p1sp1,p1sp2; +alter table lc_r_ntp2 drop subpartition p2sp1,p3sp2; +alter table lc_r_ntp2 drop partition p3; +show full create table lc_r_ntp1; +show full create table lc_r_ntp2; + +## lc_rc_ntp +drop table if exists lc_rc_ntp1; +drop table if exists lc_rc_ntp2; +create table if not exists lc_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range columns (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( 2000, 10000), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists lc_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range columns (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( 2000, 10000), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +alter table lc_rc_ntp1 drop subpartition p1sp1,p1sp2; +alter table lc_rc_ntp2 drop subpartition p1sp1,p2sp2; +alter table lc_rc_ntp2 drop partition p2; +show full create table lc_rc_ntp1; +show full create table lc_rc_ntp2; + +## lc_l_tp +drop table if exists lc_l_ntp1; +drop table if exists lc_l_ntp2; +create table if not exists lc_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list (a) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists lc_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list (a) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +alter table lc_l_ntp1 drop subpartition p1sp1,p1sp2; +alter table lc_l_ntp2 drop subpartition p1sp1,p2sp2; +alter table lc_l_ntp2 drop partition p2; +show full create table lc_l_ntp1; +show full create table lc_l_ntp2; + +## lc_lc_ntp +drop table if exists lc_lc_ntp1; +drop table if exists lc_lc_ntp2; +create table if not exists lc_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list columns (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( (2000, 2000) ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists lc_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list columns (a,b) +( +partition p1 values in ( ('2020-01-01', 'abc') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values in ( default ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( (2000, 2000) ), +subpartition p2sp3 values in ( default ) +) +); +alter table lc_lc_ntp1 drop partition p1; +alter table lc_lc_ntp1 drop subpartition p2sp1,p2sp3; +alter table lc_lc_ntp2 drop subpartition p2sp1,p2sp2,p2sp3; +show full create table lc_lc_ntp1; +show full create table lc_lc_ntp2; diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_tp.result b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_tp.result new file mode 100644 index 000000000..30a1e4943 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_tp.result @@ -0,0 +1,885 @@ +## DISABLE_FAST_SQL_PARSER + ## l_h_tp +drop table if exists l_h_tp1; +drop table if exists l_h_tp2; +create table if not exists l_h_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_h_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_h_tp1 drop partition p1; +alter table l_h_tp2 drop partition p1; +show full create table l_h_tp1; +Table,Create Table +l_h_tp1,CREATE TABLE `l_h_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY HASH(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table l_h_tp2; +Table,Create Table +l_h_tp2,CREATE TABLE `l_h_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY HASH(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +## l_k_tp +drop table if exists l_k_tp1; +drop table if exists l_k_tp2; +create table if not exists l_k_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_k_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_k_tp1 drop partition p1; +alter table l_k_tp2 drop partition p2; +show full create table l_k_tp1; +Table,Create Table +l_k_tp1,CREATE TABLE `l_k_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY KEY(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table l_k_tp2; +Table,Create Table +l_k_tp2,CREATE TABLE `l_k_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY KEY(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p1 VALUES IN (737790)) +/* tablegroup = `tg` */ +## l_r_tp +drop table if exists l_r_tp1; +drop table if exists l_r_tp2; +create table if not exists l_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_r_tp1 drop partition p1; +alter table l_r_tp1 drop subpartition sp1; +alter table l_r_tp2 drop subpartition sp2; +alter table l_r_tp2 drop partition p2; +show full create table l_r_tp1; +Table,Create Table +l_r_tp1,CREATE TABLE `l_r_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY RANGE(`a`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table l_r_tp2; +Table,Create Table +l_r_tp2,CREATE TABLE `l_r_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY RANGE(`a`) +(SUBPARTITION sp1 VALUES LESS THAN (1000)) +(PARTITION p1 VALUES IN (737790)) +/* tablegroup = `tg` */ +## l_rc_tp +drop table if exists l_rc_tp1; +drop table if exists l_rc_tp2; +create table if not exists l_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_rc_tp1 drop partition p1; +alter table l_rc_tp1 drop subpartition sp1; +alter table l_rc_tp2 drop subpartition sp1; +alter table l_rc_tp2 drop partition p1; +show full create table l_rc_tp1; +Table,Create Table +l_rc_tp1,CREATE TABLE `l_rc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table l_rc_tp2; +Table,Create Table +l_rc_tp2,CREATE TABLE `l_rc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +## l_l_tp +drop table if exists l_l_tp1; +drop table if exists l_l_tp2; +create table if not exists l_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_l_tp1 drop partition p1; +alter table l_l_tp1 drop subpartition sp1; +alter table l_l_tp2 drop subpartition sp1; +alter table l_l_tp2 drop partition p1; +show full create table l_l_tp1; +Table,Create Table +l_l_tp1,CREATE TABLE `l_l_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY LIST(`a`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table l_l_tp2; +Table,Create Table +l_l_tp2,CREATE TABLE `l_l_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY LIST(`a`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +## l_lc_tp +drop table if exists l_lc_tp1; +drop table if exists l_lc_tp2; +create table if not exists l_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_lc_tp1 drop partition p1; +alter table l_lc_tp1 drop subpartition sp1; +alter table l_lc_tp2 drop subpartition sp1; +alter table l_lc_tp2 drop partition p1; +show full create table l_lc_tp1; +Table,Create Table +l_lc_tp1,CREATE TABLE `l_lc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table l_lc_tp2; +Table,Create Table +l_lc_tp2,CREATE TABLE `l_lc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(TO_DAYS(`c`)) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +## lc_h_tp +drop table if exists lc_h_tp1; +drop table if exists lc_h_tp2; +create table if not exists lc_h_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_h_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_h_tp1 drop partition p1; +alter table lc_h_tp2 drop partition p1; +show full create table lc_h_tp1; +Table,Create Table +lc_h_tp1,CREATE TABLE `lc_h_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY HASH(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table lc_h_tp2; +Table,Create Table +lc_h_tp2,CREATE TABLE `lc_h_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY HASH(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +## lc_k_tp +drop table if exists lc_k_tp1; +drop table if exists lc_k_tp2; +create table if not exists lc_k_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_k_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_k_tp1 drop partition p1; +alter table lc_k_tp2 drop partition p2; +show full create table lc_k_tp1; +Table,Create Table +lc_k_tp1,CREATE TABLE `lc_k_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY KEY(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table lc_k_tp2; +Table,Create Table +lc_k_tp2,CREATE TABLE `lc_k_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY KEY(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p1 VALUES IN (('2020-01-01 00:00:00','abc'))) +/* tablegroup = `tg` */ +## lc_r_tp +drop table if exists lc_r_tp1; +drop table if exists lc_r_tp2; +create table if not exists lc_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_r_tp1 drop partition p1; +alter table lc_r_tp1 drop subpartition sp1; +alter table lc_r_tp2 drop subpartition sp1; +alter table lc_r_tp2 drop partition p1; +show full create table lc_r_tp1; +Table,Create Table +lc_r_tp1,CREATE TABLE `lc_r_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE(`a`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table lc_r_tp2; +Table,Create Table +lc_r_tp2,CREATE TABLE `lc_r_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE(`a`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +## lc_rc_tp +drop table if exists lc_rc_tp1; +drop table if exists lc_rc_tp2; +create table if not exists lc_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_rc_tp1 drop partition p1; +alter table lc_rc_tp1 drop subpartition sp1; +alter table lc_rc_tp2 drop subpartition sp2; +alter table lc_rc_tp2 drop partition p1; +show full create table lc_rc_tp1; +Table,Create Table +lc_rc_tp1,CREATE TABLE `lc_rc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table lc_rc_tp2; +Table,Create Table +lc_rc_tp2,CREATE TABLE `lc_rc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(SUBPARTITION sp1 VALUES LESS THAN (1000,10000)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +## lc_l_tp +drop table if exists lc_l_tp1; +drop table if exists lc_l_tp2; +create table if not exists lc_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_l_tp1 drop partition p1; +alter table lc_l_tp1 drop subpartition sp1; +alter table lc_l_tp2 drop subpartition sp1; +alter table lc_l_tp2 drop partition p1; +show full create table lc_l_tp1; +Table,Create Table +lc_l_tp1,CREATE TABLE `lc_l_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY LIST(`a`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table lc_l_tp2; +Table,Create Table +lc_l_tp2,CREATE TABLE `lc_l_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY LIST(`a`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +## lc_lc_tp +drop table if exists lc_lc_tp1; +drop table if exists lc_lc_tp2; +create table if not exists lc_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_lc_tp1 drop partition p1; +alter table lc_lc_tp1 drop subpartition sp1; +alter table lc_lc_tp2 drop subpartition sp1; +alter table lc_lc_tp2 drop partition p1; +show full create table lc_lc_tp1; +Table,Create Table +lc_lc_tp1,CREATE TABLE `lc_lc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ +show full create table lc_lc_tp2; +Table,Create Table +lc_lc_tp2,CREATE TABLE `lc_lc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`c`,`d`) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES IN (DEFAULT)) +/* tablegroup = `tg` */ \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_tp.test.yml b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_tp.test.yml new file mode 100644 index 000000000..b99f5764d --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_list_tp.test.yml @@ -0,0 +1,488 @@ +## DISABLE_FAST_SQL_PARSER + ## l_h_tp +drop table if exists l_h_tp1; +drop table if exists l_h_tp2; +create table if not exists l_h_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_h_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_h_tp1 drop partition p1; +alter table l_h_tp2 drop partition p1; +show full create table l_h_tp1; +show full create table l_h_tp2; + + ## l_k_tp +drop table if exists l_k_tp1; +drop table if exists l_k_tp2; +create table if not exists l_k_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_k_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_k_tp1 drop partition p1; +alter table l_k_tp2 drop partition p2; +show full create table l_k_tp1; +show full create table l_k_tp2; + + ## l_r_tp +drop table if exists l_r_tp1; +drop table if exists l_r_tp2; +create table if not exists l_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_r_tp1 drop partition p1; +alter table l_r_tp1 drop subpartition sp1; +alter table l_r_tp2 drop subpartition sp2; +alter table l_r_tp2 drop partition p2; +show full create table l_r_tp1; +show full create table l_r_tp2; + + ## l_rc_tp +drop table if exists l_rc_tp1; +drop table if exists l_rc_tp2; +create table if not exists l_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_rc_tp1 drop partition p1; +alter table l_rc_tp1 drop subpartition sp1; +alter table l_rc_tp2 drop subpartition sp1; +alter table l_rc_tp2 drop partition p1; +show full create table l_rc_tp1; +show full create table l_rc_tp2; + + ## l_l_tp +drop table if exists l_l_tp1; +drop table if exists l_l_tp2; +create table if not exists l_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_l_tp1 drop partition p1; +alter table l_l_tp1 drop subpartition sp1; +alter table l_l_tp2 drop subpartition sp1; +alter table l_l_tp2 drop partition p1; +show full create table l_l_tp1; +show full create table l_l_tp2; + + ## l_lc_tp +drop table if exists l_lc_tp1; +drop table if exists l_lc_tp2; +create table if not exists l_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +create table if not exists l_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list (to_days(c)) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( to_days('2020-01-01') ), +partition p2 values in ( default ) +); +alter table l_lc_tp1 drop partition p1; +alter table l_lc_tp1 drop subpartition sp1; +alter table l_lc_tp2 drop subpartition sp1; +alter table l_lc_tp2 drop partition p1; +show full create table l_lc_tp1; +show full create table l_lc_tp2; + + ## lc_h_tp +drop table if exists lc_h_tp1; +drop table if exists lc_h_tp2; +create table if not exists lc_h_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_h_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_h_tp1 drop partition p1; +alter table lc_h_tp2 drop partition p1; +show full create table lc_h_tp1; +show full create table lc_h_tp2; + + ## lc_k_tp +drop table if exists lc_k_tp1; +drop table if exists lc_k_tp2; +create table if not exists lc_k_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_k_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_k_tp1 drop partition p1; +alter table lc_k_tp2 drop partition p2; +show full create table lc_k_tp1; +show full create table lc_k_tp2; + + ## lc_r_tp +drop table if exists lc_r_tp1; +drop table if exists lc_r_tp2; +create table if not exists lc_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_r_tp1 drop partition p1; +alter table lc_r_tp1 drop subpartition sp1; +alter table lc_r_tp2 drop subpartition sp1; +alter table lc_r_tp2 drop partition p1; +show full create table lc_r_tp1; +show full create table lc_r_tp2; + + ## lc_rc_tp +drop table if exists lc_rc_tp1; +drop table if exists lc_rc_tp2; +create table if not exists lc_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_rc_tp1 drop partition p1; +alter table lc_rc_tp1 drop subpartition sp1; +alter table lc_rc_tp2 drop subpartition sp2; +alter table lc_rc_tp2 drop partition p1; +show full create table lc_rc_tp1; +show full create table lc_rc_tp2; + + ## lc_l_tp +drop table if exists lc_l_tp1; +drop table if exists lc_l_tp2; +create table if not exists lc_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_l_tp1 drop partition p1; +alter table lc_l_tp1 drop subpartition sp1; +alter table lc_l_tp2 drop subpartition sp1; +alter table lc_l_tp2 drop partition p1; +show full create table lc_l_tp1; +show full create table lc_l_tp2; + + ## lc_lc_tp +drop table if exists lc_lc_tp1; +drop table if exists lc_lc_tp2; +create table if not exists lc_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +create table if not exists lc_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by list columns (c,d) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values in ( ('2020-01-01', 'abc') ), +partition p2 values in ( default ) +); +alter table lc_lc_tp1 drop partition p1; +alter table lc_lc_tp1 drop subpartition sp1; +alter table lc_lc_tp2 drop subpartition sp1; +alter table lc_lc_tp2 drop partition p1; +show full create table lc_lc_tp1; +show full create table lc_lc_tp2; diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition.result b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition.result new file mode 100644 index 000000000..c296f4d3a --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition.result @@ -0,0 +1,319 @@ +DROP TABLE IF EXISTS tbl_rng; +DROP TABLE IF EXISTS tbl_rng1; +DROP TABLE IF EXISTS tbl_rng2; +CREATE TABLE IF NOT EXISTS tbl_rng ( + a int NOT NULL, + PRIMARY KEY (`a`) +) +PARTITION BY RANGE (a) ( + PARTITION p1 VALUES LESS THAN (100), + PARTITION p2 VALUES LESS THAN (200), + PARTITION p3 VALUES LESS THAN (300), + PARTITION p4 VALUES LESS THAN MAXVALUE +); +CREATE TABLE IF NOT EXISTS tbl_rng1 ( + a int NOT NULL, + PRIMARY KEY (`a`) +) +PARTITION BY RANGE (a) ( + PARTITION p1 VALUES LESS THAN (100), + PARTITION p2 VALUES LESS THAN (200), + PARTITION p3 VALUES LESS THAN (300), + PARTITION p4 VALUES LESS THAN MAXVALUE +); +CREATE TABLE IF NOT EXISTS tbl_rng2 ( + a int NOT NULL, + PRIMARY KEY (`a`) +) +PARTITION BY RANGE (a) ( + PARTITION p1 VALUES LESS THAN (100), + PARTITION p2 VALUES LESS THAN (200), + PARTITION p3 VALUES LESS THAN (300), + PARTITION p40 VALUES LESS THAN MAXVALUE +); +SHOW CREATE TABLE tbl_rng; +Table,Create Table +tbl_rng,CREATE TABLE `tbl_rng` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(`a`) +(PARTITION p1 VALUES LESS THAN (100) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (200) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (300) ENGINE = InnoDB, + PARTITION p4 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) +ALTER TABLE tbl_rng + DROP PARTITION p2; +ALTER TABLE tbl_rng1 + DROP PARTITION p2; +SHOW CREATE TABLE tbl_rng; +Table,Create Table +tbl_rng,CREATE TABLE `tbl_rng` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(`a`) +(PARTITION p1 VALUES LESS THAN (100) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (300) ENGINE = InnoDB, + PARTITION p4 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) +ALTER TABLE tbl_rng + DROP PARTITION p4; +ALTER TABLE tbl_rng1 + DROP PARTITION p4; +ALTER TABLE tbl_rng2 + DROP PARTITION p40; +SHOW CREATE TABLE tbl_rng; +Table,Create Table +tbl_rng,CREATE TABLE `tbl_rng` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(`a`) +(PARTITION p1 VALUES LESS THAN (100) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (300) ENGINE = InnoDB) +SHOW CREATE TABLE tbl_rng1; +Table,Create Table +tbl_rng1,CREATE TABLE `tbl_rng1` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(`a`) +(PARTITION p1 VALUES LESS THAN (100) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (300) ENGINE = InnoDB) +SHOW CREATE TABLE tbl_rng2; +Table,Create Table +tbl_rng2,CREATE TABLE `tbl_rng2` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(`a`) +(PARTITION p1 VALUES LESS THAN (100) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (200) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (300) ENGINE = InnoDB) +DROP TABLE IF EXISTS tbl_rng_col; +DROP TABLE IF EXISTS tbl_rng_col1; +CREATE TABLE IF NOT EXISTS tbl_rng_col ( + a varchar(20) NOT NULL, + b int, + PRIMARY KEY (`a`) +) +PARTITION BY RANGE COLUMNS (a, b) ( + PARTITION p1 VALUES LESS THAN ('100', 20), + PARTITION p2 VALUES LESS THAN ('200', 20), + PARTITION p3 VALUES LESS THAN ('300', 20), + PARTITION p4 VALUES LESS THAN (maxvalue, maxvalue) +); +CREATE TABLE IF NOT EXISTS tbl_rng_col1 ( + a varchar(20) NOT NULL, + b int, + PRIMARY KEY (`a`) +) +PARTITION BY RANGE COLUMNS (a, b) ( + PARTITION p1 VALUES LESS THAN ('100', 20), + PARTITION p2 VALUES LESS THAN ('200', 20), + PARTITION p3 VALUES LESS THAN ('300', 20), + PARTITION p4 VALUES LESS THAN (maxvalue, maxvalue) +); +SHOW CREATE TABLE tbl_rng_col; +Table,Create Table +tbl_rng_col,CREATE TABLE `tbl_rng_col` ( + `a` varchar(20) NOT NULL, + `b` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p1 VALUES LESS THAN ('100',20) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN ('200',20) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN ('300',20) ENGINE = InnoDB, + PARTITION p4 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB) +ALTER TABLE tbl_rng_col + DROP PARTITION p2; +ALTER TABLE tbl_rng_col1 + DROP PARTITION p2; +SHOW CREATE TABLE tbl_rng_col; +Table,Create Table +tbl_rng_col,CREATE TABLE `tbl_rng_col` ( + `a` varchar(20) NOT NULL, + `b` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p1 VALUES LESS THAN ('100',20) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN ('300',20) ENGINE = InnoDB, + PARTITION p4 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB) +ALTER TABLE tbl_rng_col + DROP PARTITION p4; +ALTER TABLE tbl_rng_col1 + DROP PARTITION p4; +SHOW CREATE TABLE tbl_rng_col; +Table,Create Table +tbl_rng_col,CREATE TABLE `tbl_rng_col` ( + `a` varchar(20) NOT NULL, + `b` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p1 VALUES LESS THAN ('100',20) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN ('300',20) ENGINE = InnoDB) +SHOW CREATE TABLE tbl_rng_col1; +Table,Create Table +tbl_rng_col1,CREATE TABLE `tbl_rng_col1` ( + `a` varchar(20) NOT NULL, + `b` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p1 VALUES LESS THAN ('100',20) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN ('300',20) ENGINE = InnoDB) +DROP TABLE IF EXISTS tbl_list; +DROP TABLE IF EXISTS tbl_list1; +CREATE TABLE IF NOT EXISTS tbl_list ( + a int NOT NULL, + PRIMARY KEY (`a`) +) +PARTITION BY LIST (a) ( + PARTITION p1 VALUES IN (10, 11), + PARTITION p2 VALUES IN (100, 101), + PARTITION p3 VALUES IN (200, 201), + PARTITION p4 VALUES IN (DEFAULT) +); +CREATE TABLE IF NOT EXISTS tbl_list1 ( + a int NOT NULL, + PRIMARY KEY (`a`) +) +PARTITION BY LIST (a) ( + PARTITION p1 VALUES IN (10, 11), + PARTITION p2 VALUES IN (100, 101), + PARTITION p3 VALUES IN (200, 201), + PARTITION p4 VALUES IN (DEFAULT) +); +SHOW CREATE TABLE tbl_list; +Table,Create Table +tbl_list,CREATE TABLE `tbl_list` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(`a`) +(PARTITION p1 VALUES IN (10,11) ENGINE = InnoDB, + PARTITION p2 VALUES IN (100,101) ENGINE = InnoDB, + PARTITION p3 VALUES IN (200,201) ENGINE = InnoDB, + PARTITION p4 VALUES IN (DEFAULT) ENGINE = InnoDB) +ALTER TABLE tbl_list + DROP PARTITION p2; +ALTER TABLE tbl_list1 + DROP PARTITION p2; +SHOW CREATE TABLE tbl_list; +Table,Create Table +tbl_list,CREATE TABLE `tbl_list` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(`a`) +(PARTITION p1 VALUES IN (10,11) ENGINE = InnoDB, + PARTITION p3 VALUES IN (200,201) ENGINE = InnoDB, + PARTITION p4 VALUES IN (DEFAULT) ENGINE = InnoDB) +ALTER TABLE tbl_list + DROP PARTITION p4; +ALTER TABLE tbl_list1 + DROP PARTITION p4; +SHOW CREATE TABLE tbl_list; +Table,Create Table +tbl_list,CREATE TABLE `tbl_list` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(`a`) +(PARTITION p1 VALUES IN (10,11) ENGINE = InnoDB, + PARTITION p3 VALUES IN (200,201) ENGINE = InnoDB) +SHOW CREATE TABLE tbl_list1; +Table,Create Table +tbl_list1,CREATE TABLE `tbl_list1` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(`a`) +(PARTITION p1 VALUES IN (10,11) ENGINE = InnoDB, + PARTITION p3 VALUES IN (200,201) ENGINE = InnoDB) +DROP TABLE IF EXISTS tbl_list_col; +DROP TABLE IF EXISTS tbl_list_col1; +CREATE TABLE IF NOT EXISTS tbl_list_col ( + a int NOT NULL, + b int, + PRIMARY KEY (`a`) +) +PARTITION BY LIST COLUMNS (a, b) ( + PARTITION p1 VALUES IN ((10, 11), (12, 13)), + PARTITION p2 VALUES IN ((100, 101), (100, 103)), + PARTITION p3 VALUES IN ((200, 201), (100, 1321)), + PARTITION p4 VALUES IN (DEFAULT) +); +CREATE TABLE IF NOT EXISTS tbl_list_col1 ( + a int NOT NULL, + b int, + PRIMARY KEY (`a`) +) +PARTITION BY LIST COLUMNS (a, b) ( + PARTITION p1 VALUES IN ((10, 11), (12, 13)), + PARTITION p2 VALUES IN ((100, 101), (100, 103)), + PARTITION p3 VALUES IN ((200, 201), (100, 1321)), + PARTITION p4 VALUES IN (DEFAULT) +); +SHOW CREATE TABLE tbl_list_col; +Table,Create Table +tbl_list_col,CREATE TABLE `tbl_list_col` ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p1 VALUES IN ((10,11),(12,13)) ENGINE = InnoDB, + PARTITION p2 VALUES IN ((100,101),(100,103)) ENGINE = InnoDB, + PARTITION p3 VALUES IN ((100,1321),(200,201)) ENGINE = InnoDB, + PARTITION p4 VALUES IN (DEFAULT) ENGINE = InnoDB) +ALTER TABLE tbl_list_col + DROP PARTITION p2; +ALTER TABLE tbl_list_col1 + DROP PARTITION p2; +SHOW CREATE TABLE tbl_list_col; +Table,Create Table +tbl_list_col,CREATE TABLE `tbl_list_col` ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p1 VALUES IN ((10,11),(12,13)) ENGINE = InnoDB, + PARTITION p3 VALUES IN ((100,1321),(200,201)) ENGINE = InnoDB, + PARTITION p4 VALUES IN (DEFAULT) ENGINE = InnoDB) +ALTER TABLE tbl_list_col + DROP PARTITION p4; +ALTER TABLE tbl_list_col1 + DROP PARTITION p4; +SHOW CREATE TABLE tbl_list_col; +Table,Create Table +tbl_list_col,CREATE TABLE `tbl_list_col` ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p1 VALUES IN ((10,11),(12,13)) ENGINE = InnoDB, + PARTITION p3 VALUES IN ((100,1321),(200,201)) ENGINE = InnoDB) +SHOW CREATE TABLE tbl_list_col1; +Table,Create Table +tbl_list_col1,CREATE TABLE `tbl_list_col1` ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p1 VALUES IN ((10,11),(12,13)) ENGINE = InnoDB, + PARTITION p3 VALUES IN ((100,1321),(200,201)) ENGINE = InnoDB) \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition.test.yml b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition.test.yml new file mode 100644 index 000000000..dce5e9795 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition.test.yml @@ -0,0 +1,113 @@ +## test hash/one col/int + +## test drop partition for range +drop table if exists tbl_rng; +drop table if exists tbl_rng1; +drop table if exists tbl_rng2; +create table if not exists tbl_rng (a int not null,primary key (`a`)) +partition by range(a) +( partition p1 values less than (100), +partition p2 values less than (200), +partition p3 values less than (300), +partition p4 values less than (maxvalue) +); +create table if not exists tbl_rng1 (a int not null,primary key (`a`)) +partition by range(a) +( partition p1 values less than (100), +partition p2 values less than (200), +partition p3 values less than (300), +partition p4 values less than (maxvalue) +); +create table if not exists tbl_rng2 (a int not null,primary key (`a`)) +partition by range(a) +( partition p1 values less than (100), +partition p2 values less than (200), +partition p3 values less than (300), +partition p40 values less than (maxvalue) +); +show create table tbl_rng; +alter table tbl_rng drop partition p2; +alter table tbl_rng1 drop partition p2; +show create table tbl_rng; +alter table tbl_rng drop partition p4; +alter table tbl_rng1 drop partition p4; +alter table tbl_rng2 drop partition p40; +show create table tbl_rng; +show create table tbl_rng1; +show create table tbl_rng2; + +drop table if exists tbl_rng_col; +drop table if exists tbl_rng_col1; +create table if not exists tbl_rng_col (a varchar(20) not null,b int, primary key (`a`)) +partition by range columns(a, b) +( partition p1 values less than ('100',20), +partition p2 values less than ('200',20), +partition p3 values less than ('300',20), +partition p4 values less than (maxvalue,maxvalue) +); +create table if not exists tbl_rng_col1 (a varchar(20) not null,b int, primary key (`a`)) +partition by range columns(a, b) +( partition p1 values less than ('100',20), +partition p2 values less than ('200',20), +partition p3 values less than ('300',20), +partition p4 values less than (maxvalue,maxvalue) +); +show create table tbl_rng_col; +alter table tbl_rng_col drop partition p2; +alter table tbl_rng_col1 drop partition p2; +show create table tbl_rng_col; +alter table tbl_rng_col drop partition p4; +alter table tbl_rng_col1 drop partition p4; +show create table tbl_rng_col; +show create table tbl_rng_col1; + +drop table if exists tbl_list; +drop table if exists tbl_list1; +create table if not exists tbl_list (a int not null,primary key (`a`)) +partition by list(a) +( partition p1 values in (10,11), +partition p2 values in (100,101), +partition p3 values in (200,201), +partition p4 values in (default) +); +create table if not exists tbl_list1 (a int not null,primary key (`a`)) +partition by list(a) +( partition p1 values in (10,11), +partition p2 values in (100,101), +partition p3 values in (200,201), +partition p4 values in (default) +); +show create table tbl_list; +alter table tbl_list drop partition p2; +alter table tbl_list1 drop partition p2; +show create table tbl_list; +alter table tbl_list drop partition p4; +alter table tbl_list1 drop partition p4; +show create table tbl_list; +show create table tbl_list1; + +drop table if exists tbl_list_col; +drop table if exists tbl_list_col1; +create table if not exists tbl_list_col (a int not null, b int, primary key (`a`)) +partition by list columns(a, b) +( partition p1 values in ((10,11),(12,13)), +partition p2 values in ((100,101),(100,103)), +partition p3 values in ((200,201),(100,1321)), +partition p4 values in (default) +); +create table if not exists tbl_list_col1 (a int not null, b int, primary key (`a`)) +partition by list columns(a, b) +( partition p1 values in ((10,11),(12,13)), +partition p2 values in ((100,101),(100,103)), +partition p3 values in ((200,201),(100,1321)), +partition p4 values in (default) +); +show create table tbl_list_col; +alter table tbl_list_col drop partition p2; +alter table tbl_list_col1 drop partition p2; +show create table tbl_list_col; +alter table tbl_list_col drop partition p4; +alter table tbl_list_col1 drop partition p4; +show create table tbl_list_col; +show create table tbl_list_col1; + diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition_group.result b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition_group.result new file mode 100644 index 000000000..bca02e2de --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition_group.result @@ -0,0 +1,419 @@ +DROP TABLE IF EXISTS tbl_rng10; +DROP TABLE IF EXISTS tbl_rng20; +DROP TABLEGROUP IF EXISTS rg_tg1; +CREATE TABLEGROUP rg_tg1; +CREATE TABLE IF NOT EXISTS tbl_rng10 ( + a int NOT NULL, + PRIMARY KEY (`a`) +) +PARTITION BY RANGE (a) ( + PARTITION p1 VALUES LESS THAN (100), + PARTITION p2 VALUES LESS THAN (200), + PARTITION p3 VALUES LESS THAN (300), + PARTITION p4 VALUES LESS THAN MAXVALUE +); +CREATE TABLE IF NOT EXISTS tbl_rng20 ( + a int NOT NULL, + PRIMARY KEY (`a`) +) +PARTITION BY RANGE (a) ( + PARTITION p1 VALUES LESS THAN (100), + PARTITION p2 VALUES LESS THAN (200), + PARTITION p3 VALUES LESS THAN (300), + PARTITION p4 VALUES LESS THAN MAXVALUE +); +ALTER TABLE tbl_rng10 + SET tablegroup = rg_tg1; +ALTER TABLE tbl_rng20 + SET tablegroup = rg_tg1; +ALTER TABLEGROUP rg_tg1 DROP PARTITION p2 ; +ALTER TABLEGROUP rg_tg1 DROP PARTITION p4 ; +SHOW CREATE TABLE tbl_rng10; +Table,Create Table +tbl_rng10,CREATE TABLE `tbl_rng10` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(`a`) +(PARTITION p1 VALUES LESS THAN (100) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (300) ENGINE = InnoDB) +tablegroup = `rg_tg1` +SHOW CREATE TABLE tbl_rng20; +Table,Create Table +tbl_rng20,CREATE TABLE `tbl_rng20` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(`a`) +(PARTITION p1 VALUES LESS THAN (100) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (300) ENGINE = InnoDB) +tablegroup = `rg_tg1` +DROP TABLE IF EXISTS tbl_list10; +DROP TABLE IF EXISTS tbl_list20; +DROP TABLEGROUP IF EXISTS ls_tg1; +CREATE TABLEGROUP ls_tg1; +CREATE TABLE IF NOT EXISTS tbl_list10 ( + a int NOT NULL, + PRIMARY KEY (`a`) +) +PARTITION BY LIST (a) ( + PARTITION p1 VALUES IN (10, 11), + PARTITION p2 VALUES IN (100, 101), + PARTITION p3 VALUES IN (200, 201), + PARTITION p4 VALUES IN (DEFAULT) +); +CREATE TABLE IF NOT EXISTS tbl_list20 ( + a int NOT NULL, + PRIMARY KEY (`a`) +) +PARTITION BY LIST (a) ( + PARTITION p1 VALUES IN (10, 11), + PARTITION p2 VALUES IN (100, 101), + PARTITION p3 VALUES IN (200, 201), + PARTITION p4 VALUES IN (DEFAULT) +); +ALTER TABLE tbl_list10 + SET tablegroup = ls_tg1; +ALTER TABLE tbl_list20 + SET tablegroup = ls_tg1; +ALTER TABLEGROUP ls_tg1 DROP PARTITION p2 ; +ALTER TABLEGROUP ls_tg1 DROP PARTITION p4 ; +SHOW CREATE TABLE tbl_list10; +Table,Create Table +tbl_list10,CREATE TABLE `tbl_list10` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(`a`) +(PARTITION p1 VALUES IN (10,11) ENGINE = InnoDB, + PARTITION p3 VALUES IN (200,201) ENGINE = InnoDB) +tablegroup = `ls_tg1` +SHOW CREATE TABLE tbl_list20; +Table,Create Table +tbl_list20,CREATE TABLE `tbl_list20` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY LIST(`a`) +(PARTITION p1 VALUES IN (10,11) ENGINE = InnoDB, + PARTITION p3 VALUES IN (200,201) ENGINE = InnoDB) +tablegroup = `ls_tg1` +DROP TABLE IF EXISTS h_r_ntp10; +DROP TABLE IF EXISTS h_r_ntp20; +DROP TABLEGROUP IF EXISTS hr_tg1; +CREATE TABLEGROUP hr_tg1; +CREATE TABLE IF NOT EXISTS h_r_ntp10 ( + a bigint UNSIGNED NOT NULL, + b bigint UNSIGNED NOT NULL, + c datetime NOT NULL, + d varchar(16) NOT NULL, + e varchar(16) NOT NULL +) +PARTITION BY HASH (a, b) PARTITIONS 2 +SUBPARTITION BY RANGE (to_days(c)) ( + PARTITION p1 ( + SUBPARTITION p1sp1 VALUES LESS THAN (to_days('2020-01-01')), + SUBPARTITION p1sp2 VALUES LESS THAN MAXVALUE + ), + PARTITION p2 ( + SUBPARTITION p2sp1 VALUES LESS THAN (to_days('2020-01-01')), + SUBPARTITION p2sp2 VALUES LESS THAN (to_days('2021-01-01')), + SUBPARTITION p2sp3 VALUES LESS THAN MAXVALUE + ) +); +CREATE TABLE IF NOT EXISTS h_r_ntp20 ( + a bigint UNSIGNED NOT NULL, + b bigint UNSIGNED NOT NULL, + c datetime NOT NULL, + d varchar(16) NOT NULL, + e varchar(16) NOT NULL +) +PARTITION BY HASH (a, b) PARTITIONS 2 +SUBPARTITION BY RANGE (to_days(c)) ( + PARTITION p1 ( + SUBPARTITION p1sp1 VALUES LESS THAN (to_days('2020-01-01')), + SUBPARTITION p1sp2 VALUES LESS THAN MAXVALUE + ), + PARTITION p2 ( + SUBPARTITION p2sp1 VALUES LESS THAN (to_days('2020-01-01')), + SUBPARTITION p2sp2 VALUES LESS THAN (to_days('2021-01-01')), + SUBPARTITION p2sp3 VALUES LESS THAN MAXVALUE + ) +); +ALTER TABLE h_r_ntp10 + SET tablegroup = hr_tg1; +ALTER TABLE h_r_ntp20 + SET tablegroup = hr_tg1; +ALTER TABLEGROUP hr_tg1 DROP SUBPARTITION p2sp1 ; +ALTER TABLEGROUP hr_tg1 DROP SUBPARTITION p1sp2 ; +ALTER TABLEGROUP hr_tg1 DROP SUBPARTITION p2sp3 ; +SHOW FULL CREATE TABLE h_r_ntp10; +Table,Create Table +h_r_ntp10,CREATE TABLE `h_r_ntp10` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +SUBPARTITION BY RANGE(TO_DAYS(`c`)) +(PARTITION p1 + (SUBPARTITION p1sp1 VALUES LESS THAN (737790) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES LESS THAN (738156) ENGINE = InnoDB)) +tablegroup = `hr_tg1` +SHOW FULL CREATE TABLE h_r_ntp20; +Table,Create Table +h_r_ntp20,CREATE TABLE `h_r_ntp20` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +SUBPARTITION BY RANGE(TO_DAYS(`c`)) +(PARTITION p1 + (SUBPARTITION p1sp1 VALUES LESS THAN (737790) ENGINE = InnoDB), + PARTITION p2 + (SUBPARTITION p2sp2 VALUES LESS THAN (738156) ENGINE = InnoDB)) +tablegroup = `hr_tg1` +DROP TABLE IF EXISTS h_l_tp10; +DROP TABLE IF EXISTS h_l_tp20; +DROP TABLEGROUP IF EXISTS hl_tg1; +CREATE TABLEGROUP hl_tg1; +CREATE TABLE IF NOT EXISTS h_l_tp10 ( + a bigint UNSIGNED NOT NULL, + b bigint UNSIGNED NOT NULL, + c datetime NOT NULL, + d varchar(16) NOT NULL, + e varchar(16) NOT NULL +) +PARTITION BY HASH (a, b) PARTITIONS 4 +SUBPARTITION BY LIST (to_days(c)) ( + SUBPARTITION sp1 VALUES IN (to_days('2020-01-01')), + SUBPARTITION sp2 VALUES IN (DEFAULT) +); +CREATE TABLE IF NOT EXISTS h_l_tp20 ( + a bigint UNSIGNED NOT NULL, + b bigint UNSIGNED NOT NULL, + c datetime NOT NULL, + d varchar(16) NOT NULL, + e varchar(16) NOT NULL +) +PARTITION BY HASH (a, b) PARTITIONS 4 +SUBPARTITION BY LIST (to_days(c)) ( + SUBPARTITION sp1 VALUES IN (to_days('2020-01-01')), + SUBPARTITION sp2 VALUES IN (DEFAULT) +); +ALTER TABLE h_l_tp10 + SET tablegroup = hl_tg1; +ALTER TABLE h_l_tp20 + SET tablegroup = hl_tg1; +ALTER TABLEGROUP hl_tg1 DROP SUBPARTITION sp1 ; +SHOW FULL CREATE TABLE h_l_tp10; +Table,Create Table +h_l_tp10,CREATE TABLE `h_l_tp10` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY LIST(TO_DAYS(`c`)) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +tablegroup = `hl_tg1` +SHOW FULL CREATE TABLE h_l_tp20; +Table,Create Table +h_l_tp20,CREATE TABLE `h_l_tp20` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY HASH(`a`,`b`) +PARTITIONS 4 +SUBPARTITION BY LIST(TO_DAYS(`c`)) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +tablegroup = `hl_tg1` +DROP TABLE IF EXISTS r_l_ntp10; +DROP TABLE IF EXISTS r_l_ntp20; +DROP TABLEGROUP IF EXISTS rl_tg1; +CREATE TABLEGROUP rl_tg1; +CREATE TABLE IF NOT EXISTS r_l_ntp10 ( + a bigint UNSIGNED NOT NULL, + b bigint UNSIGNED NOT NULL, + c datetime NOT NULL, + d varchar(16) NOT NULL, + e varchar(16) NOT NULL +) +PARTITION BY RANGE (to_days(c)) +SUBPARTITION BY LIST (a) ( + PARTITION p1 VALUES LESS THAN (to_days('2020-01-01')) ( + SUBPARTITION p1sp1 VALUES IN (1000, 2000), + SUBPARTITION p1sp2 VALUES IN (DEFAULT) + ), + PARTITION p2 VALUES LESS THAN MAXVALUE ( + SUBPARTITION p2sp1 VALUES IN (1000, 2000), + SUBPARTITION p2sp2 VALUES IN (3000, 4000), + SUBPARTITION p2sp3 VALUES IN (DEFAULT) + ) +); +CREATE TABLE IF NOT EXISTS r_l_ntp20 ( + a bigint UNSIGNED NOT NULL, + b bigint UNSIGNED NOT NULL, + c datetime NOT NULL, + d varchar(16) NOT NULL, + e varchar(16) NOT NULL +) +PARTITION BY RANGE (to_days(c)) +SUBPARTITION BY LIST (a) ( + PARTITION p1 VALUES LESS THAN (to_days('2020-01-01')) ( + SUBPARTITION p1sp1 VALUES IN (1000, 2000), + SUBPARTITION p1sp2 VALUES IN (DEFAULT) + ), + PARTITION p2 VALUES LESS THAN MAXVALUE ( + SUBPARTITION p2sp1 VALUES IN (1000, 2000), + SUBPARTITION p2sp2 VALUES IN (3000, 4000), + SUBPARTITION p2sp3 VALUES IN (DEFAULT) + ) +); +ALTER TABLE r_l_ntp10 + SET tablegroup = rl_tg1; +ALTER TABLE r_l_ntp20 + SET tablegroup = rl_tg1; +ALTER TABLEGROUP rl_tg1 DROP SUBPARTITION p1sp1, p1sp2 ; +ALTER TABLEGROUP rl_tg1 DROP SUBPARTITION p2sp1, p2sp2 ; +SHOW FULL CREATE TABLE r_l_ntp10; +Table,Create Table +r_l_ntp10,CREATE TABLE `r_l_ntp10` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY LIST(`a`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE) + (SUBPARTITION p2sp3 VALUES IN (DEFAULT) ENGINE = InnoDB)) +tablegroup = `rl_tg1` +SHOW FULL CREATE TABLE r_l_ntp20; +Table,Create Table +r_l_ntp20,CREATE TABLE `r_l_ntp20` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY LIST(`a`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE) + (SUBPARTITION p2sp3 VALUES IN (DEFAULT) ENGINE = InnoDB)) +tablegroup = `rl_tg1` +DROP TABLE IF EXISTS rc_lc_tp10; +DROP TABLE IF EXISTS rc_lc_tp20; +DROP TABLEGROUP IF EXISTS rclc_tg1; +CREATE TABLEGROUP rclc_tg1; +CREATE TABLE IF NOT EXISTS rc_lc_tp10 ( + a bigint UNSIGNED NOT NULL, + b bigint UNSIGNED NOT NULL, + c datetime NOT NULL, + d varchar(16) NOT NULL, + e varchar(16) NOT NULL +) +PARTITION BY RANGE COLUMNS (c, d) +SUBPARTITION BY LIST COLUMNS (a, b) ( + SUBPARTITION sp1 VALUES IN ((1000, 2000)), + SUBPARTITION sp2 VALUES IN (DEFAULT) +) ( + PARTITION p1 VALUES LESS THAN ('2020-01-01', 'abc'), + PARTITION p2 VALUES LESS THAN (maxvalue, maxvalue) +); +CREATE TABLE IF NOT EXISTS rc_lc_tp20 ( + a bigint UNSIGNED NOT NULL, + b bigint UNSIGNED NOT NULL, + c datetime NOT NULL, + d varchar(16) NOT NULL, + e varchar(16) NOT NULL +) +PARTITION BY RANGE COLUMNS (c, d) +SUBPARTITION BY LIST COLUMNS (a, b) ( + SUBPARTITION sp1 VALUES IN ((1000, 2000)), + SUBPARTITION sp2 VALUES IN (DEFAULT) +) ( + PARTITION p1 VALUES LESS THAN ('2020-01-01', 'abc'), + PARTITION p2 VALUES LESS THAN (maxvalue, maxvalue) +); +ALTER TABLE rc_lc_tp10 + SET tablegroup = rclc_tg1; +ALTER TABLE rc_lc_tp20 + SET tablegroup = rclc_tg1; +ALTER TABLEGROUP rclc_tg1 DROP SUBPARTITION sp1 ; +SHOW FULL CREATE TABLE rc_lc_tp10; +Table,Create Table +rc_lc_tp10,CREATE TABLE `rc_lc_tp10` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p1 VALUES LESS THAN ('2020-01-01 00:00:00','abc'), + PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +tablegroup = `rclc_tg1` +SHOW FULL CREATE TABLE rc_lc_tp20; +Table,Create Table +rc_lc_tp20,CREATE TABLE `rc_lc_tp20` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p1 VALUES LESS THAN ('2020-01-01 00:00:00','abc'), + PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +tablegroup = `rclc_tg1` \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition_group.test.yml b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition_group.test.yml new file mode 100644 index 000000000..15106643e --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_partition_group.test.yml @@ -0,0 +1,241 @@ +## test hash/one col/int + +## test drop partition for range +drop table if exists tbl_rng10; +drop table if exists tbl_rng20; +drop tablegroup if exists rg_tg1; +create tablegroup rg_tg1; +create table if not exists tbl_rng10 (a int not null,primary key (`a`)) +partition by range(a) +( partition p1 values less than (100), +partition p2 values less than (200), +partition p3 values less than (300), +partition p4 values less than (maxvalue) +); +create table if not exists tbl_rng20 (a int not null,primary key (`a`)) +partition by range(a) +( partition p1 values less than (100), +partition p2 values less than (200), +partition p3 values less than (300), +partition p4 values less than (maxvalue) +); +alter table tbl_rng10 set tablegroup=rg_tg1; +alter table tbl_rng20 set tablegroup=rg_tg1; + +alter tablegroup rg_tg1 drop partition p2; +alter tablegroup rg_tg1 drop partition p4; +show create table tbl_rng10; +show create table tbl_rng20; + +drop table if exists tbl_list10; +drop table if exists tbl_list20; +drop tablegroup if exists ls_tg1; +create tablegroup ls_tg1; +create table if not exists tbl_list10 (a int not null,primary key (`a`)) +partition by list(a) +( partition p1 values in (10,11), +partition p2 values in (100,101), +partition p3 values in (200,201), +partition p4 values in (default) +); +create table if not exists tbl_list20 (a int not null,primary key (`a`)) +partition by list(a) +( partition p1 values in (10,11), +partition p2 values in (100,101), +partition p3 values in (200,201), +partition p4 values in (default) +); +alter table tbl_list10 set tablegroup=ls_tg1; +alter table tbl_list20 set tablegroup=ls_tg1; +alter tablegroup ls_tg1 drop partition p2; +alter tablegroup ls_tg1 drop partition p4; +show create table tbl_list10; +show create table tbl_list20; + +drop table if exists h_r_ntp10; +drop table if exists h_r_ntp20; +drop tablegroup if exists hr_tg1; +create tablegroup hr_tg1; +create table if not exists h_r_ntp10 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); + +create table if not exists h_r_ntp20 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 2 +subpartition by range (to_days(c)) +( +partition p1 +( +subpartition p1sp1 values less than ( to_days('2020-01-01') ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 +( +subpartition p2sp1 values less than ( to_days('2020-01-01') ), +subpartition p2sp2 values less than ( to_days('2021-01-01') ), +subpartition p2sp3 values less than ( maxvalue ) +) +); + +alter table h_r_ntp10 set tablegroup=hr_tg1; +alter table h_r_ntp20 set tablegroup=hr_tg1; + +alter tablegroup hr_tg1 drop subpartition p2sp1; +alter tablegroup hr_tg1 drop subpartition p1sp2; +alter tablegroup hr_tg1 drop subpartition p2sp3; +show full create table h_r_ntp10; +show full create table h_r_ntp20; + +drop table if exists h_l_tp10; +drop table if exists h_l_tp20; +drop tablegroup if exists hl_tg1; +create tablegroup hl_tg1; +create table if not exists h_l_tp10 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by list (to_days(c)) ( +subpartition sp1 values in ( to_days('2020-01-01') ), +subpartition sp2 values in ( default ) +); +create table if not exists h_l_tp20 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by hash (a,b) partitions 4 +subpartition by list (to_days(c)) ( +subpartition sp1 values in ( to_days('2020-01-01') ), +subpartition sp2 values in ( default ) +); +alter table h_l_tp10 set tablegroup=hl_tg1; +alter table h_l_tp20 set tablegroup=hl_tg1; +alter tablegroup hl_tg1 drop subpartition sp1; +show full create table h_l_tp10; +show full create table h_l_tp20; + +drop table if exists r_l_ntp10; +drop table if exists r_l_ntp20; +drop tablegroup if exists rl_tg1; +create tablegroup rl_tg1; +create table if not exists r_l_ntp10 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list (a) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists r_l_ntp20 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list (a) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +alter table r_l_ntp10 set tablegroup=rl_tg1; +alter table r_l_ntp20 set tablegroup=rl_tg1; +alter tablegroup rl_tg1 drop subpartition p1sp1,p1sp2; +alter tablegroup rl_tg1 drop subpartition p2sp1,p2sp2; +show full create table r_l_ntp10; +show full create table r_l_ntp20; + +drop table if exists rc_lc_tp10; +drop table if exists rc_lc_tp20; +drop tablegroup if exists rclc_tg1; +create tablegroup rclc_tg1; +create table if not exists rc_lc_tp10 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000)), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_lc_tp20 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000)), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_lc_tp10 set tablegroup=rclc_tg1; +alter table rc_lc_tp20 set tablegroup=rclc_tg1; +alter tablegroup rclc_tg1 drop subpartition sp1; +show full create table rc_lc_tp10; +show full create table rc_lc_tp20; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_ntp.result b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_ntp.result new file mode 100644 index 000000000..f080aeea6 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_ntp.result @@ -0,0 +1,948 @@ +## DISABLE_FAST_SQL_PARSER +## r_h_ntp +drop table if exists r_h_ntp1; +drop table if exists r_h_ntp2; +create table if not exists r_h_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by hash (a,b) +( + partition p1 values less than ( to_days('2020-01-01') ) subpartitions 2, + partition p2 values less than ( maxvalue ) subpartitions 3 +); +create table if not exists r_h_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by hash (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values less than ( maxvalue ) subpartitions 3 +); +alter table r_h_ntp1 drop partition p1; +alter table r_h_ntp2 drop partition p2; +show full create table r_h_ntp1; +Table,Create Table +r_h_ntp1,CREATE TABLE `r_h_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY HASH(`a`,`b`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE) + (SUBPARTITION p2sp1 ENGINE = InnoDB, + SUBPARTITION p2sp2 ENGINE = InnoDB, + SUBPARTITION p2sp3 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table r_h_ntp2; +Table,Create Table +r_h_ntp2,CREATE TABLE `r_h_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY HASH(`a`,`b`) +(PARTITION p1 VALUES LESS THAN (737790) + (SUBPARTITION p1sp1 ENGINE = InnoDB, + SUBPARTITION p1sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## r_k_ntp +drop table if exists r_k_ntp1; +drop table if exists r_k_ntp2; +create table if not exists r_k_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by key (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values less than ( maxvalue ) subpartitions 3 +); +create table if not exists r_k_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by key (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values less than ( maxvalue ) subpartitions 3 +); +alter table r_k_ntp1 drop partition p2; +alter table r_k_ntp2 drop partition p2; +show full create table r_k_ntp1; +Table,Create Table +r_k_ntp1,CREATE TABLE `r_k_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY KEY(`a`,`b`) +(PARTITION p1 VALUES LESS THAN (737790) + (SUBPARTITION p1sp1 ENGINE = InnoDB, + SUBPARTITION p1sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table r_k_ntp2; +Table,Create Table +r_k_ntp2,CREATE TABLE `r_k_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY KEY(`a`,`b`) +(PARTITION p1 VALUES LESS THAN (737790) + (SUBPARTITION p1sp1 ENGINE = InnoDB, + SUBPARTITION p1sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## r_r_ntp +drop table if exists r_r_ntp1; +drop table if exists r_r_ntp2; +create table if not exists r_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range (a) +( +partition p1 values less than ( to_days('2020-01-01') ) +( +subpartition p1sp1 values less than ( 1000 ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values less than ( to_days('2022-01-01') ) +( +subpartition p2sp1 values less than ( 1000 ), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values less than ( maxvalue ) +( +subpartition p3sp1 values less than ( 1000 ), +subpartition p3sp2 values less than ( 2000 ), +subpartition p3sp3 values less than ( maxvalue ) +) +); +create table if not exists r_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range (a) +( +partition p1 values less than ( to_days('2020-01-01') ) +( +subpartition p1sp1 values less than ( 1000 ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values less than ( to_days('2022-01-01') ) +( +subpartition p2sp1 values less than ( 1000 ), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values less than ( maxvalue ) +( +subpartition p3sp1 values less than ( 1000 ), +subpartition p3sp2 values less than ( 2000 ), +subpartition p3sp3 values less than ( maxvalue ) +) +); +alter table r_r_ntp1 drop subpartition p1sp1,p1sp2; +alter table r_r_ntp1 drop subpartition p2sp1,p3sp2; +alter table r_r_ntp1 drop partition p3; +alter table r_r_ntp2 drop subpartition p1sp1,p1sp2; +alter table r_r_ntp2 drop subpartition p2sp1,p3sp2; +alter table r_r_ntp2 drop partition p3; +show full create table r_r_ntp1; +Table,Create Table +r_r_ntp1,CREATE TABLE `r_r_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY RANGE(`a`) +(PARTITION p2 VALUES LESS THAN (738521) + (SUBPARTITION p2sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table r_r_ntp2; +Table,Create Table +r_r_ntp2,CREATE TABLE `r_r_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY RANGE(`a`) +(PARTITION p2 VALUES LESS THAN (738521) + (SUBPARTITION p2sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## r_rc_ntp +drop table if exists r_rc_ntp1; +drop table if exists r_rc_ntp2; +create table if not exists r_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range columns (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values less than ( to_days('2022-01-01') ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( maxvalue, maxvalue ) +), +partition p3 values less than ( maxvalue ) ( +subpartition p3sp1 values less than ( 1000, 10000), +subpartition p3sp2 values less than ( 2000, 10000), +subpartition p3sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists r_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range columns (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values less than ( to_days('2022-01-01') ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( maxvalue, maxvalue ) +), +partition p3 values less than ( maxvalue ) ( +subpartition p3sp1 values less than ( 1000, 10000), +subpartition p3sp2 values less than ( 2000, 10000), +subpartition p3sp3 values less than ( maxvalue, maxvalue ) +) +); +alter table r_rc_ntp1 drop subpartition p1sp1,p1sp2; +alter table r_rc_ntp1 drop subpartition p2sp1,p3sp2; +alter table r_rc_ntp1 drop partition p3; +alter table r_rc_ntp2 drop subpartition p1sp1,p1sp2; +alter table r_rc_ntp2 drop subpartition p2sp1,p3sp2; +alter table r_rc_ntp2 drop partition p3; +show full create table r_rc_ntp1; +Table,Create Table +r_rc_ntp1,CREATE TABLE `r_rc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p2 VALUES LESS THAN (738521) + (SUBPARTITION p2sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table r_rc_ntp2; +Table,Create Table +r_rc_ntp2,CREATE TABLE `r_rc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p2 VALUES LESS THAN (738521) + (SUBPARTITION p2sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## r_l_ntp +drop table if exists r_l_ntp1; +drop table if exists r_l_ntp2; +create table if not exists r_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list (a) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists r_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list (a) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +alter table r_l_ntp1 drop subpartition p1sp1,p1sp2; +alter table r_l_ntp2 drop subpartition p2sp1,p2sp3; +alter table r_l_ntp2 drop partition p2; +show full create table r_l_ntp1; +Table,Create Table +r_l_ntp1,CREATE TABLE `r_l_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY LIST(`a`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE) + (SUBPARTITION p2sp1 VALUES IN (1000,2000) ENGINE = InnoDB, + SUBPARTITION p2sp2 VALUES IN (3000,4000) ENGINE = InnoDB, + SUBPARTITION p2sp3 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table r_l_ntp2; +Table,Create Table +r_l_ntp2,CREATE TABLE `r_l_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY LIST(`a`) +(PARTITION p1 VALUES LESS THAN (737790) + (SUBPARTITION p1sp1 VALUES IN (1000,2000) ENGINE = InnoDB, + SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## r_lc_ntp +drop table if exists r_lc_ntp1; +drop table if exists r_lc_ntp2; +create table if not exists r_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list columns (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( (4000, 3000) ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists r_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list columns (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( (4000, 3000) ), +subpartition p2sp3 values in ( default ) +) +); +alter table r_lc_ntp1 drop subpartition p1sp1,p1sp2; +alter table r_lc_ntp2 drop subpartition p2sp1,p2sp3; +alter table r_lc_ntp2 drop partition p2; +show full create table r_lc_ntp1; +Table,Create Table +r_lc_ntp1,CREATE TABLE `r_lc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE) + (SUBPARTITION p2sp1 VALUES IN ((1000,2000)) ENGINE = InnoDB, + SUBPARTITION p2sp2 VALUES IN ((4000,3000)) ENGINE = InnoDB, + SUBPARTITION p2sp3 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table r_lc_ntp2; +Table,Create Table +r_lc_ntp2,CREATE TABLE `r_lc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p1 VALUES LESS THAN (737790) + (SUBPARTITION p1sp1 VALUES IN ((1000,2000)) ENGINE = InnoDB, + SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +######### + ## rc_h_ntp +drop table if exists rc_h_ntp1; +drop table if exists rc_h_ntp2; +create table if not exists rc_h_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by hash (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) subpartitions 2, +partition p2 values less than ( maxvalue, maxvalue ) subpartitions 3 +); +create table if not exists rc_h_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by hash (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) subpartitions 2, +partition p2 values less than ( maxvalue, maxvalue ) subpartitions 3 +); +alter table rc_h_ntp1 drop partition p1; +alter table rc_h_ntp2 drop partition p2; +show full create table rc_h_ntp1; +Table,Create Table +rc_h_ntp1,CREATE TABLE `rc_h_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY HASH(`a`,`b`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE) + (SUBPARTITION p2sp1 ENGINE = InnoDB, + SUBPARTITION p2sp2 ENGINE = InnoDB, + SUBPARTITION p2sp3 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table rc_h_ntp2; +Table,Create Table +rc_h_ntp2,CREATE TABLE `rc_h_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY HASH(`a`,`b`) +(PARTITION p1 VALUES LESS THAN ('2020-01-01 00:00:00','abc') + (SUBPARTITION p1sp1 ENGINE = InnoDB, + SUBPARTITION p1sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## rc_k_ntp +drop table if exists rc_k_ntp1; +create table if not exists rc_k_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by key (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) subpartitions 2, +partition p2 values less than ( maxvalue, maxvalue ) subpartitions 3 +); +alter table rc_k_ntp1 drop partition p2; +show full create table rc_k_ntp1; +Table,Create Table +rc_k_ntp1,CREATE TABLE `rc_k_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY KEY(`a`,`b`) +(PARTITION p1 VALUES LESS THAN ('2020-01-01 00:00:00','abc') + (SUBPARTITION p1sp1 ENGINE = InnoDB, + SUBPARTITION p1sp2 ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## rc_r_ntp +drop table if exists rc_r_ntp1; +drop table if exists rc_r_ntp2; +create table if not exists rc_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range (a) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( 2000), +subpartition p2sp3 values less than ( maxvalue ) +) +); +create table if not exists rc_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range (a) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( 2000), +subpartition p2sp3 values less than ( maxvalue ) +) +); +alter table rc_r_ntp1 drop subpartition p2sp1; +alter table rc_r_ntp1 drop subpartition p1sp1,p1sp2; +alter table rc_r_ntp2 drop subpartition p2sp3; +alter table rc_r_ntp2 drop subpartition p1sp1,p1sp2; +show full create table rc_r_ntp1; +Table,Create Table +rc_r_ntp1,CREATE TABLE `rc_r_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE(`a`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE) + (SUBPARTITION p2sp2 VALUES LESS THAN (2000) ENGINE = InnoDB, + SUBPARTITION p2sp3 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table rc_r_ntp2; +Table,Create Table +rc_r_ntp2,CREATE TABLE `rc_r_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE(`a`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE) + (SUBPARTITION p2sp1 VALUES LESS THAN (1000) ENGINE = InnoDB, + SUBPARTITION p2sp2 VALUES LESS THAN (2000) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## rc_rc_ntp +drop table if exists rc_rc_ntp1; +drop table if exists rc_rc_ntp2; +create table if not exists rc_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range columns (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values less than ( 1000, 2000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values less than ( 1000, 2000), +subpartition p2sp2 values less than ( 2000, 2000), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists rc_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range columns (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values less than ( 1000, 2000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values less than ( 1000, 2000), +subpartition p2sp2 values less than ( 2000, 2000), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +alter table rc_rc_ntp1 drop subpartition p2sp1; +alter table rc_rc_ntp1 drop subpartition p1sp1,p1sp2; +alter table rc_rc_ntp2 drop subpartition p2sp3; +alter table rc_rc_ntp2 drop subpartition p1sp1,p1sp2; +show full create table rc_rc_ntp1; +Table,Create Table +rc_rc_ntp1,CREATE TABLE `rc_rc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE) + (SUBPARTITION p2sp2 VALUES LESS THAN (2000,2000) ENGINE = InnoDB, + SUBPARTITION p2sp3 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table rc_rc_ntp2; +Table,Create Table +rc_rc_ntp2,CREATE TABLE `rc_rc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE) + (SUBPARTITION p2sp1 VALUES LESS THAN (1000,2000) ENGINE = InnoDB, + SUBPARTITION p2sp2 VALUES LESS THAN (2000,2000) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## rc_l_ntp +drop table if exists rc_l_ntp1; +drop table if exists rc_l_ntp2; +create table if not exists rc_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list (a) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists rc_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list (a) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +alter table rc_l_ntp1 drop subpartition p2sp1; +alter table rc_l_ntp1 drop subpartition p1sp1,p1sp2; +alter table rc_l_ntp2 drop subpartition p2sp3; +alter table rc_l_ntp2 drop subpartition p1sp1,p1sp2; +show full create table rc_l_ntp1; +Table,Create Table +rc_l_ntp1,CREATE TABLE `rc_l_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY LIST(`a`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE) + (SUBPARTITION p2sp2 VALUES IN (3000,4000) ENGINE = InnoDB, + SUBPARTITION p2sp3 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table rc_l_ntp2; +Table,Create Table +rc_l_ntp2,CREATE TABLE `rc_l_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY LIST(`a`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE) + (SUBPARTITION p2sp1 VALUES IN (1000,2000) ENGINE = InnoDB, + SUBPARTITION p2sp2 VALUES IN (3000,4000) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +## rc_lc_ntp +drop table if exists rc_lc_ntp1; +drop table if exists rc_lc_ntp2; +create table if not exists rc_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list columns (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values in ( (1000, 2000)), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values in ( (1000, 2000)), +subpartition p2sp2 values in ( (2000, 2000)), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists rc_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list columns (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values in ( (1000, 2000)), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values in ( (1000, 2000)), +subpartition p2sp2 values in ( (2000, 2000)), +subpartition p2sp3 values in ( default ) +) +); +alter table rc_lc_ntp1 drop subpartition p2sp1; +alter table rc_lc_ntp1 drop subpartition p1sp1,p1sp2; +alter table rc_lc_ntp2 drop subpartition p2sp3; +alter table rc_lc_ntp2 drop subpartition p1sp1,p1sp2; +show full create table rc_lc_ntp1; +Table,Create Table +rc_lc_ntp1,CREATE TABLE `rc_lc_ntp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE) + (SUBPARTITION p2sp2 VALUES IN ((2000,2000)) ENGINE = InnoDB, + SUBPARTITION p2sp3 VALUES IN (DEFAULT) ENGINE = InnoDB)) +/* tablegroup = `tg` */ +show full create table rc_lc_ntp2; +Table,Create Table +rc_lc_ntp2,CREATE TABLE `rc_lc_ntp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE) + (SUBPARTITION p2sp1 VALUES IN ((1000,2000)) ENGINE = InnoDB, + SUBPARTITION p2sp2 VALUES IN ((2000,2000)) ENGINE = InnoDB)) +/* tablegroup = `tg` */ \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_ntp.test.yml b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_ntp.test.yml new file mode 100644 index 000000000..6e6f01020 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_ntp.test.yml @@ -0,0 +1,547 @@ +## DISABLE_FAST_SQL_PARSER +## r_h_ntp +drop table if exists r_h_ntp1; +drop table if exists r_h_ntp2; +create table if not exists r_h_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by hash (a,b) +( + partition p1 values less than ( to_days('2020-01-01') ) subpartitions 2, + partition p2 values less than ( maxvalue ) subpartitions 3 +); +create table if not exists r_h_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by hash (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values less than ( maxvalue ) subpartitions 3 +); + +alter table r_h_ntp1 drop partition p1; +alter table r_h_ntp2 drop partition p2; +show full create table r_h_ntp1; +show full create table r_h_ntp2; + + +## r_k_ntp +drop table if exists r_k_ntp1; +drop table if exists r_k_ntp2; +create table if not exists r_k_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by key (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values less than ( maxvalue ) subpartitions 3 +); +create table if not exists r_k_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by key (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) subpartitions 2, +partition p2 values less than ( maxvalue ) subpartitions 3 +); +alter table r_k_ntp1 drop partition p2; +alter table r_k_ntp2 drop partition p2; +show full create table r_k_ntp1; +show full create table r_k_ntp2; + +## r_r_ntp +drop table if exists r_r_ntp1; +drop table if exists r_r_ntp2; +create table if not exists r_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range (a) +( +partition p1 values less than ( to_days('2020-01-01') ) +( +subpartition p1sp1 values less than ( 1000 ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values less than ( to_days('2022-01-01') ) +( +subpartition p2sp1 values less than ( 1000 ), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values less than ( maxvalue ) +( +subpartition p3sp1 values less than ( 1000 ), +subpartition p3sp2 values less than ( 2000 ), +subpartition p3sp3 values less than ( maxvalue ) +) +); +create table if not exists r_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range (a) +( +partition p1 values less than ( to_days('2020-01-01') ) +( +subpartition p1sp1 values less than ( 1000 ), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values less than ( to_days('2022-01-01') ) +( +subpartition p2sp1 values less than ( 1000 ), +subpartition p2sp2 values less than ( maxvalue ) +), +partition p3 values less than ( maxvalue ) +( +subpartition p3sp1 values less than ( 1000 ), +subpartition p3sp2 values less than ( 2000 ), +subpartition p3sp3 values less than ( maxvalue ) +) +); +alter table r_r_ntp1 drop subpartition p1sp1,p1sp2; +alter table r_r_ntp1 drop subpartition p2sp1,p3sp2; +alter table r_r_ntp1 drop partition p3; +alter table r_r_ntp2 drop subpartition p1sp1,p1sp2; +alter table r_r_ntp2 drop subpartition p2sp1,p3sp2; +alter table r_r_ntp2 drop partition p3; +show full create table r_r_ntp1; +show full create table r_r_ntp2; + +## r_rc_ntp +drop table if exists r_rc_ntp1; +drop table if exists r_rc_ntp2; +create table if not exists r_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range columns (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values less than ( to_days('2022-01-01') ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( maxvalue, maxvalue ) +), +partition p3 values less than ( maxvalue ) ( +subpartition p3sp1 values less than ( 1000, 10000), +subpartition p3sp2 values less than ( 2000, 10000), +subpartition p3sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists r_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range columns (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values less than ( 1000, 10000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values less than ( to_days('2022-01-01') ) ( +subpartition p2sp1 values less than ( 1000, 10000), +subpartition p2sp2 values less than ( maxvalue, maxvalue ) +), +partition p3 values less than ( maxvalue ) ( +subpartition p3sp1 values less than ( 1000, 10000), +subpartition p3sp2 values less than ( 2000, 10000), +subpartition p3sp3 values less than ( maxvalue, maxvalue ) +) +); +alter table r_rc_ntp1 drop subpartition p1sp1,p1sp2; +alter table r_rc_ntp1 drop subpartition p2sp1,p3sp2; +alter table r_rc_ntp1 drop partition p3; +alter table r_rc_ntp2 drop subpartition p1sp1,p1sp2; +alter table r_rc_ntp2 drop subpartition p2sp1,p3sp2; +alter table r_rc_ntp2 drop partition p3; +show full create table r_rc_ntp1; +show full create table r_rc_ntp2; + +## r_l_ntp +drop table if exists r_l_ntp1; +drop table if exists r_l_ntp2; +create table if not exists r_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list (a) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists r_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list (a) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +alter table r_l_ntp1 drop subpartition p1sp1,p1sp2; +alter table r_l_ntp2 drop subpartition p2sp1,p2sp3; +alter table r_l_ntp2 drop partition p2; +show full create table r_l_ntp1; +show full create table r_l_ntp2; + +## r_lc_ntp +drop table if exists r_lc_ntp1; +drop table if exists r_lc_ntp2; +create table if not exists r_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list columns (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( (4000, 3000) ), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists r_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list columns (a,b) +( +partition p1 values less than ( to_days('2020-01-01') ) ( +subpartition p1sp1 values in ( (1000, 2000) ), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue ) ( +subpartition p2sp1 values in ( (1000, 2000) ), +subpartition p2sp2 values in ( (4000, 3000) ), +subpartition p2sp3 values in ( default ) +) +); +alter table r_lc_ntp1 drop subpartition p1sp1,p1sp2; +alter table r_lc_ntp2 drop subpartition p2sp1,p2sp3; +alter table r_lc_ntp2 drop partition p2; +show full create table r_lc_ntp1; +show full create table r_lc_ntp2; + +######### + ## rc_h_ntp +drop table if exists rc_h_ntp1; +drop table if exists rc_h_ntp2; +create table if not exists rc_h_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by hash (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) subpartitions 2, +partition p2 values less than ( maxvalue, maxvalue ) subpartitions 3 +); +create table if not exists rc_h_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by hash (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) subpartitions 2, +partition p2 values less than ( maxvalue, maxvalue ) subpartitions 3 +); +alter table rc_h_ntp1 drop partition p1; +alter table rc_h_ntp2 drop partition p2; +show full create table rc_h_ntp1; +show full create table rc_h_ntp2; + +## rc_k_ntp +drop table if exists rc_k_ntp1; +create table if not exists rc_k_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by key (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) subpartitions 2, +partition p2 values less than ( maxvalue, maxvalue ) subpartitions 3 +); +alter table rc_k_ntp1 drop partition p2; +show full create table rc_k_ntp1; + +## rc_r_ntp +drop table if exists rc_r_ntp1; +drop table if exists rc_r_ntp2; +create table if not exists rc_r_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range (a) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( 2000), +subpartition p2sp3 values less than ( maxvalue ) +) +); +create table if not exists rc_r_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range (a) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values less than ( 1000), +subpartition p1sp2 values less than ( maxvalue ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values less than ( 1000), +subpartition p2sp2 values less than ( 2000), +subpartition p2sp3 values less than ( maxvalue ) +) +); +alter table rc_r_ntp1 drop subpartition p2sp1; +alter table rc_r_ntp1 drop subpartition p1sp1,p1sp2; +alter table rc_r_ntp2 drop subpartition p2sp3; +alter table rc_r_ntp2 drop subpartition p1sp1,p1sp2; +show full create table rc_r_ntp1; +show full create table rc_r_ntp2; + +## rc_rc_ntp +drop table if exists rc_rc_ntp1; +drop table if exists rc_rc_ntp2; +create table if not exists rc_rc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range columns (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values less than ( 1000, 2000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values less than ( 1000, 2000), +subpartition p2sp2 values less than ( 2000, 2000), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +create table if not exists rc_rc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range columns (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values less than ( 1000, 2000), +subpartition p1sp2 values less than ( maxvalue, maxvalue ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values less than ( 1000, 2000), +subpartition p2sp2 values less than ( 2000, 2000), +subpartition p2sp3 values less than ( maxvalue, maxvalue ) +) +); +alter table rc_rc_ntp1 drop subpartition p2sp1; +alter table rc_rc_ntp1 drop subpartition p1sp1,p1sp2; +alter table rc_rc_ntp2 drop subpartition p2sp3; +alter table rc_rc_ntp2 drop subpartition p1sp1,p1sp2; +show full create table rc_rc_ntp1; +show full create table rc_rc_ntp2; + +## rc_l_ntp +drop table if exists rc_l_ntp1; +drop table if exists rc_l_ntp2; +create table if not exists rc_l_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list (a) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists rc_l_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list (a) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values in ( 1000, 2000), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values in ( 1000, 2000), +subpartition p2sp2 values in ( 3000, 4000), +subpartition p2sp3 values in ( default ) +) +); +alter table rc_l_ntp1 drop subpartition p2sp1; +alter table rc_l_ntp1 drop subpartition p1sp1,p1sp2; +alter table rc_l_ntp2 drop subpartition p2sp3; +alter table rc_l_ntp2 drop subpartition p1sp1,p1sp2; +show full create table rc_l_ntp1; +show full create table rc_l_ntp2; + +## rc_lc_ntp +drop table if exists rc_lc_ntp1; +drop table if exists rc_lc_ntp2; +create table if not exists rc_lc_ntp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list columns (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values in ( (1000, 2000)), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values in ( (1000, 2000)), +subpartition p2sp2 values in ( (2000, 2000)), +subpartition p2sp3 values in ( default ) +) +); +create table if not exists rc_lc_ntp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list columns (a,b) +( +partition p1 values less than ( '2020-01-01','abc' ) ( +subpartition p1sp1 values in ( (1000, 2000)), +subpartition p1sp2 values in ( default ) +), +partition p2 values less than ( maxvalue, maxvalue ) ( +subpartition p2sp1 values in ( (1000, 2000)), +subpartition p2sp2 values in ( (2000, 2000)), +subpartition p2sp3 values in ( default ) +) +); +alter table rc_lc_ntp1 drop subpartition p2sp1; +alter table rc_lc_ntp1 drop subpartition p1sp1,p1sp2; +alter table rc_lc_ntp2 drop subpartition p2sp3; +alter table rc_lc_ntp2 drop subpartition p1sp1,p1sp2; +show full create table rc_lc_ntp1; +show full create table rc_lc_ntp2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_tp.result b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_tp.result new file mode 100644 index 000000000..b4ca366f4 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_tp.result @@ -0,0 +1,886 @@ +## DISABLE_FAST_SQL_PARSER + ## r_h_tp +drop table if exists r_h_tp1; +drop table if exists r_h_tp2; +create table if not exists r_h_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by hash (a,b) subpartitions 4 +( + partition p1 values less than ( to_days('2020-01-01') ), + partition p2 values less than ( maxvalue ) +); +create table if not exists r_h_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_h_tp1 drop partition p1; +alter table r_h_tp2 drop partition p1; +show full create table r_h_tp1; +Table,Create Table +r_h_tp1,CREATE TABLE `r_h_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY HASH(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +show full create table r_h_tp2; +Table,Create Table +r_h_tp2,CREATE TABLE `r_h_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY HASH(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +## r_k_tp +drop table if exists r_k_tp1; +drop table if exists r_k_tp2; +create table if not exists r_k_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +create table if not exists r_k_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_k_tp1 drop partition p1; +alter table r_k_tp2 drop partition p2; +show full create table r_k_tp1; +Table,Create Table +r_k_tp1,CREATE TABLE `r_k_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY KEY(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +show full create table r_k_tp2; +Table,Create Table +r_k_tp2,CREATE TABLE `r_k_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY KEY(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p1 VALUES LESS THAN (737790)) +/* tablegroup = `tg` */ +## r_r_tp +drop table if exists r_r_tp1; +drop table if exists r_r_tp2; +create table if not exists r_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range (a) +( + subpartition sp1 values less than ( 1000), + subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +create table if not exists r_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_r_tp1 drop partition p1; +alter table r_r_tp1 drop subpartition sp1; +alter table r_r_tp2 drop partition p2; +alter table r_r_tp2 drop subpartition sp2; +show full create table r_r_tp1; +Table,Create Table +r_r_tp1,CREATE TABLE `r_r_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY RANGE(`a`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE)) +(PARTITION p2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +show full create table r_r_tp2; +Table,Create Table +r_r_tp2,CREATE TABLE `r_r_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY RANGE(`a`) +(SUBPARTITION sp1 VALUES LESS THAN (1000)) +(PARTITION p1 VALUES LESS THAN (737790)) +/* tablegroup = `tg` */ +## r_rc_tp +drop table if exists r_rc_tp1; +drop table if exists r_rc_tp2; +create table if not exists r_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +create table if not exists r_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_rc_tp1 drop partition p1; +alter table r_rc_tp1 drop subpartition sp2; +alter table r_rc_tp2 drop partition p1; +alter table r_rc_tp2 drop subpartition sp2; +show full create table r_rc_tp1; +Table,Create Table +r_rc_tp1,CREATE TABLE `r_rc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(SUBPARTITION sp1 VALUES LESS THAN (1000,10000)) +(PARTITION p2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +show full create table r_rc_tp2; +Table,Create Table +r_rc_tp2,CREATE TABLE `r_rc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(SUBPARTITION sp1 VALUES LESS THAN (1000,10000)) +(PARTITION p2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +## r_l_tp +drop table if exists r_l_tp1; +drop table if exists r_l_tp2; +create table if not exists r_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +create table if not exists r_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_l_tp1 drop partition p1; +alter table r_l_tp1 drop subpartition sp1; +alter table r_l_tp2 drop partition p2; +alter table r_l_tp2 drop subpartition sp1; +show full create table r_l_tp1; +Table,Create Table +r_l_tp1,CREATE TABLE `r_l_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY LIST(`a`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +show full create table r_l_tp2; +Table,Create Table +r_l_tp2,CREATE TABLE `r_l_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY LIST(`a`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p1 VALUES LESS THAN (737790)) +/* tablegroup = `tg` */ +## r_lc_tp +drop table if exists r_lc_tp1; +drop table if exists r_lc_tp2; +create table if not exists r_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +create table if not exists r_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_lc_tp1 drop partition p1; +alter table r_lc_tp1 drop subpartition sp2; +alter table r_lc_tp2 drop partition p1; +alter table r_lc_tp2 drop subpartition sp2; +show full create table r_lc_tp1; +Table,Create Table +r_lc_tp1,CREATE TABLE `r_lc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(SUBPARTITION sp1 VALUES IN ((1000,2000))) +(PARTITION p2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +show full create table r_lc_tp2; +Table,Create Table +r_lc_tp2,CREATE TABLE `r_lc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c` USING BTREE (`c`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(TO_DAYS(`c`)) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(SUBPARTITION sp1 VALUES IN ((1000,2000))) +(PARTITION p2 VALUES LESS THAN (MAXVALUE)) +/* tablegroup = `tg` */ +######### + ## rc_h_tp +drop table if exists rc_h_tp1; +drop table if exists rc_h_tp2; +create table if not exists rc_h_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_h_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_h_tp1 drop partition p1; +alter table rc_h_tp2 drop partition p1; +show full create table rc_h_tp1; +Table,Create Table +rc_h_tp1,CREATE TABLE `rc_h_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY HASH(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +show full create table rc_h_tp2; +Table,Create Table +rc_h_tp2,CREATE TABLE `rc_h_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY HASH(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +## rc_k_tp +drop table if exists rc_k_tp1; +drop table if exists rc_k_tp2; +create table if not exists rc_k_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_k_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_k_tp1 drop partition p1; +alter table rc_k_tp2 drop partition p2; +show full create table rc_k_tp1; +Table,Create Table +rc_k_tp1,CREATE TABLE `rc_k_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY KEY(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +show full create table rc_k_tp2; +Table,Create Table +rc_k_tp2,CREATE TABLE `rc_k_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY KEY(`a`,`b`) +SUBPARTITIONS 4 +(PARTITION p1 VALUES LESS THAN ('2020-01-01 00:00:00','abc')) +/* tablegroup = `tg` */ +## rc_r_tp +drop table if exists rc_r_tp1; +drop table if exists rc_r_tp2; +create table if not exists rc_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_r_tp1 drop partition p1; +alter table rc_r_tp1 drop subpartition sp1; +alter table rc_r_tp2 drop partition p1; +alter table rc_r_tp2 drop subpartition sp1; +show full create table rc_r_tp1; +Table,Create Table +rc_r_tp1,CREATE TABLE `rc_r_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE(`a`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE)) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +show full create table rc_r_tp2; +Table,Create Table +rc_r_tp2,CREATE TABLE `rc_r_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE(`a`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE)) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +## rc_rc_tp +drop table if exists rc_rc_tp1; +drop table if exists rc_rc_tp2; +create table if not exists rc_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 2000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 2000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_rc_tp1 drop partition p1; +alter table rc_rc_tp1 drop subpartition sp1; +alter table rc_rc_tp2 drop subpartition sp2; +alter table rc_rc_tp2 drop partition p1; +show full create table rc_rc_tp1; +Table,Create Table +rc_rc_tp1,CREATE TABLE `rc_rc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +show full create table rc_rc_tp2; +Table,Create Table +rc_rc_tp2,CREATE TABLE `rc_rc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY RANGE COLUMNS(`a`,`b`) +(SUBPARTITION sp1 VALUES LESS THAN (1000,2000)) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +## rc_l_tp +drop table if exists rc_l_tp1; +drop table if exists rc_l_tp2; +create table if not exists rc_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_l_tp1 drop partition p1; +alter table rc_l_tp1 drop subpartition sp1; +alter table rc_l_tp2 drop partition p1; +alter table rc_l_tp2 drop subpartition sp1; +show full create table rc_l_tp1; +Table,Create Table +rc_l_tp1,CREATE TABLE `rc_l_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY LIST(`a`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +show full create table rc_l_tp2; +Table,Create Table +rc_l_tp2,CREATE TABLE `rc_l_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY LIST(`a`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +## rc_lc_tp +drop table if exists rc_lc_tp1; +drop table if exists rc_lc_tp2; +create table if not exists rc_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000)), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000)), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_lc_tp1 drop partition p1; +alter table rc_lc_tp1 drop subpartition sp1; +alter table rc_lc_tp2 drop partition p2; +alter table rc_lc_tp2 drop subpartition sp1; +show full create table rc_lc_tp1; +Table,Create Table +rc_lc_tp1,CREATE TABLE `rc_lc_tp1` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p2 VALUES LESS THAN (MAXVALUE,MAXVALUE)) +/* tablegroup = `tg` */ +show full create table rc_lc_tp2; +Table,Create Table +rc_lc_tp2,CREATE TABLE `rc_lc_tp2` ( + `a` bigint(20) UNSIGNED NOT NULL, + `b` bigint(20) UNSIGNED NOT NULL, + `c` datetime NOT NULL, + `d` varchar(16) NOT NULL, + `e` varchar(16) NOT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), + LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`c`,`d`) +SUBPARTITION BY LIST COLUMNS(`a`,`b`) +(SUBPARTITION sp2 VALUES IN (DEFAULT)) +(PARTITION p1 VALUES LESS THAN ('2020-01-01 00:00:00','abc')) +/* tablegroup = `tg` */ \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_tp.test.yml b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_tp.test.yml new file mode 100644 index 000000000..df7d82377 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/test_drop_range_tp.test.yml @@ -0,0 +1,490 @@ +## DISABLE_FAST_SQL_PARSER + ## r_h_tp +drop table if exists r_h_tp1; +drop table if exists r_h_tp2; +create table if not exists r_h_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by hash (a,b) subpartitions 4 +( + partition p1 values less than ( to_days('2020-01-01') ), + partition p2 values less than ( maxvalue ) +); +create table if not exists r_h_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_h_tp1 drop partition p1; +alter table r_h_tp2 drop partition p1; +show full create table r_h_tp1; +show full create table r_h_tp2; + + ## r_k_tp +drop table if exists r_k_tp1; +drop table if exists r_k_tp2; +create table if not exists r_k_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +create table if not exists r_k_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_k_tp1 drop partition p1; +alter table r_k_tp2 drop partition p2; +show full create table r_k_tp1; +show full create table r_k_tp2; + + ## r_r_tp +drop table if exists r_r_tp1; +drop table if exists r_r_tp2; +create table if not exists r_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range (a) +( + subpartition sp1 values less than ( 1000), + subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +create table if not exists r_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_r_tp1 drop partition p1; +alter table r_r_tp1 drop subpartition sp1; +alter table r_r_tp2 drop partition p2; +alter table r_r_tp2 drop subpartition sp2; +show full create table r_r_tp1; +show full create table r_r_tp2; + + ## r_rc_tp +drop table if exists r_rc_tp1; +drop table if exists r_rc_tp2; +create table if not exists r_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +create table if not exists r_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 10000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_rc_tp1 drop partition p1; +alter table r_rc_tp1 drop subpartition sp2; +alter table r_rc_tp2 drop partition p1; +alter table r_rc_tp2 drop subpartition sp2; +show full create table r_rc_tp1; +show full create table r_rc_tp2; + + ## r_l_tp +drop table if exists r_l_tp1; +drop table if exists r_l_tp2; +create table if not exists r_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +create table if not exists r_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_l_tp1 drop partition p1; +alter table r_l_tp1 drop subpartition sp1; +alter table r_l_tp2 drop partition p2; +alter table r_l_tp2 drop subpartition sp1; +show full create table r_l_tp1; +show full create table r_l_tp2; + + ## r_lc_tp +drop table if exists r_lc_tp1; +drop table if exists r_lc_tp2; +create table if not exists r_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +create table if not exists r_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range (to_days(c)) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000) ), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( to_days('2020-01-01') ), +partition p2 values less than ( maxvalue ) +); +alter table r_lc_tp1 drop partition p1; +alter table r_lc_tp1 drop subpartition sp2; +alter table r_lc_tp2 drop partition p1; +alter table r_lc_tp2 drop subpartition sp2; +show full create table r_lc_tp1; +show full create table r_lc_tp2; + +######### + + ## rc_h_tp +drop table if exists rc_h_tp1; +drop table if exists rc_h_tp2; +create table if not exists rc_h_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_h_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by hash (a,b) subpartitions 4 +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_h_tp1 drop partition p1; +alter table rc_h_tp2 drop partition p1; +show full create table rc_h_tp1; +show full create table rc_h_tp2; + + ## rc_k_tp +drop table if exists rc_k_tp1; +drop table if exists rc_k_tp2; +create table if not exists rc_k_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_k_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by key (a,b) subpartitions 4 +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_k_tp1 drop partition p1; +alter table rc_k_tp2 drop partition p2; +show full create table rc_k_tp1; +show full create table rc_k_tp2; + + ## rc_r_tp +drop table if exists rc_r_tp1; +drop table if exists rc_r_tp2; +create table if not exists rc_r_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_r_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range (a) +( +subpartition sp1 values less than ( 1000), +subpartition sp2 values less than ( maxvalue ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_r_tp1 drop partition p1; +alter table rc_r_tp1 drop subpartition sp1; +alter table rc_r_tp2 drop partition p1; +alter table rc_r_tp2 drop subpartition sp1; +show full create table rc_r_tp1; +show full create table rc_r_tp2; + + ## rc_rc_tp +drop table if exists rc_rc_tp1; +drop table if exists rc_rc_tp2; +create table if not exists rc_rc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 2000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_rc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by range columns (a,b) +( +subpartition sp1 values less than ( 1000, 2000), +subpartition sp2 values less than ( maxvalue, maxvalue ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_rc_tp1 drop partition p1; +alter table rc_rc_tp1 drop subpartition sp1; +alter table rc_rc_tp2 drop subpartition sp2; +alter table rc_rc_tp2 drop partition p1; +show full create table rc_rc_tp1; +show full create table rc_rc_tp2; + + ## rc_l_tp +drop table if exists rc_l_tp1; +drop table if exists rc_l_tp2; +create table if not exists rc_l_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_l_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list (a) +( +subpartition sp1 values in ( 1000, 2000), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_l_tp1 drop partition p1; +alter table rc_l_tp1 drop subpartition sp1; +alter table rc_l_tp2 drop partition p1; +alter table rc_l_tp2 drop subpartition sp1; +show full create table rc_l_tp1; +show full create table rc_l_tp2; + + ## rc_lc_tp +drop table if exists rc_lc_tp1; +drop table if exists rc_lc_tp2; +create table if not exists rc_lc_tp1 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000)), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +create table if not exists rc_lc_tp2 ( +a bigint unsigned not null, +b bigint unsigned not null, +c datetime NOT NULL, +d varchar(16) NOT NULL, +e varchar(16) NOT NULL +) +partition by range columns (c,d) +subpartition by list columns (a,b) +( +subpartition sp1 values in ( (1000, 2000)), +subpartition sp2 values in ( default ) +) +( +partition p1 values less than ( '2020-01-01','abc' ), +partition p2 values less than ( maxvalue, maxvalue ) +); +alter table rc_lc_tp1 drop partition p1; +alter table rc_lc_tp1 drop subpartition sp1; +alter table rc_lc_tp2 drop partition p2; +alter table rc_lc_tp2 drop subpartition sp1; +show full create table rc_lc_tp1; +show full create table rc_lc_tp2; diff --git a/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/testcase.config.yml new file mode 100644 index 000000000..691de9710 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AlterTableDropPartitionTest/testcase.config.yml @@ -0,0 +1,9 @@ +test_drop_hash_ntp +test_drop_hash_tp +test_drop_key_ntp +test_drop_list_ntp +test_drop_list_tp +test_drop_partition +test_drop_partition_group +test_drop_range_ntp +test_drop_range_tp \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_add_index.result b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_add_index.result index 3bc16ff31..069e02653 100644 --- a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_add_index.result +++ b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_add_index.result @@ -113,8 +113,8 @@ agsi_1_$,CREATE TABLE `agsi_1_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`seller_id`) PARTITIONS #@# @@ -135,8 +135,8 @@ Table,Create Table agsi_3_$,CREATE TABLE `agsi_3_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -146,8 +146,8 @@ Table,Create Table agsi_4_$,CREATE TABLE `agsi_4_$` ( `order_id` varchar(20) DEFAULT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -169,8 +169,8 @@ agsi_6_$,CREATE TABLE `agsi_6_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`seller_id`) PARTITIONS #@# @@ -191,8 +191,8 @@ Table,Create Table agsi_8_$,CREATE TABLE `agsi_8_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -202,8 +202,8 @@ Table,Create Table agsi_9_$,CREATE TABLE `agsi_9_$` ( `order_id` varchar(20) DEFAULT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -225,8 +225,8 @@ agsi_1b_$,CREATE TABLE `agsi_1b_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`seller_id`) PARTITIONS #@# @@ -247,8 +247,8 @@ Table,Create Table agsi_3b_$,CREATE TABLE `agsi_3b_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -258,8 +258,8 @@ Table,Create Table agsi_4b_$,CREATE TABLE `agsi_4b_$` ( `order_id` varchar(20) DEFAULT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -281,8 +281,8 @@ agsi_6b_$,CREATE TABLE `agsi_6b_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`seller_id`) PARTITIONS #@# @@ -303,8 +303,8 @@ Table,Create Table agsi_8b_$,CREATE TABLE `agsi_8b_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -314,8 +314,8 @@ Table,Create Table agsi_9b_$,CREATE TABLE `agsi_9b_$` ( `order_id` varchar(20) DEFAULT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 diff --git a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_add_ugsi.result b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_add_ugsi.result new file mode 100644 index 000000000..3399e6552 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_add_ugsi.result @@ -0,0 +1,239 @@ +DROP TABLE IF EXISTS `tb1`; +DROP TABLE IF EXISTS `tb2`; +CREATE TABLE `tb1` ( + a int, + b int, + c int +); +CREATE TABLE `tb2` ( + a int, + b int, + c int, + d int, + PRIMARY KEY (a, b) +); +/*+TDDL:cmd_extra(UNIQUE_GSI_WITH_PRIMARY_KEY=false)*/ALTER TABLE tb1 + ADD UNIQUE KEY u1 (a, b); +SHOW CREATE TABLE u1; +Table,Create Table +u1_$,CREATE TABLE `u1_$` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + UNIQUE KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 3 +SHOW FULL CREATE TABLE u1; +Table,Create Table +u1_$,CREATE TABLE `u1_$` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL, + UNIQUE LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 3 +/* tablegroup = `tg` */ +/*+TDDL:cmd_extra(UNIQUE_GSI_WITH_PRIMARY_KEY=true)*/ALTER TABLE tb1 + ADD UNIQUE KEY u2 (b, c); +SHOW CREATE TABLE u2; +Table,Create Table +u2_$,CREATE TABLE `u2_$` ( + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + UNIQUE KEY `auto_shard_key_b_c` USING BTREE (`b`, `c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`b`,`c`) +PARTITIONS 3 +SHOW FULL CREATE TABLE u2; +Table,Create Table +u2_$,CREATE TABLE `u2_$` ( + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL, + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_b_c` USING BTREE (`b`, `c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`b`,`c`) +PARTITIONS 3 +/* tablegroup = `tg` */ +SHOW FULL CREATE TABLE tb1; +Table,Create Table +tb1,CREATE PARTITION TABLE `tb1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE GLOBAL INDEX /* u1_$ */ `u1` (`a`, `b`) + PARTITION BY KEY(`a`,`b`) + PARTITIONS 3, + UNIQUE GLOBAL INDEX /* u2_$ */ `u2` (`b`, `c`) + PARTITION BY KEY(`b`,`c`) + PARTITIONS 3, + UNIQUE LOCAL KEY `_local_u1` (`a`, `b`), + UNIQUE LOCAL KEY `_local_u2` (`b`, `c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`_drds_implicit_id_`) +PARTITIONS 3 +/* tablegroup = `tg` */ +ALTER TABLE tb1 + MODIFY COLUMN a bigint; +SHOW FULL CREATE TABLE u1; +Table,Create Table +u1_$,CREATE TABLE `u1_$` ( + `a` bigint(20) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL, + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 3 +/* tablegroup = `tg` */ +SHOW FULL CREATE TABLE u2; +Table,Create Table +u2_$,CREATE TABLE `u2_$` ( + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL, + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_b_c` USING BTREE (`b`, `c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`b`,`c`) +PARTITIONS 3 +/* tablegroup = `tg` */ +SHOW FULL CREATE TABLE tb1; +Table,Create Table +tb1,CREATE PARTITION TABLE `tb1` ( + `a` bigint(20) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE GLOBAL INDEX /* u1_$ */ `u1` (`a`, `b`) + PARTITION BY KEY(`a`,`b`) + PARTITIONS 3, + UNIQUE GLOBAL INDEX /* u2_$ */ `u2` (`b`, `c`) + PARTITION BY KEY(`b`,`c`) + PARTITIONS 3, + UNIQUE LOCAL KEY `_local_u1` (`a`, `b`), + UNIQUE LOCAL KEY `_local_u2` (`b`, `c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`_drds_implicit_id_`) +PARTITIONS 3 +/* tablegroup = `tg` */ +/*+TDDL:cmd_extra(UNIQUE_GSI_WITH_PRIMARY_KEY=false)*/ALTER TABLE tb2 + ADD UNIQUE KEY u3 (a, b); +SHOW CREATE TABLE u3; +Table,Create Table +u3_$,CREATE TABLE `u3_$` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + UNIQUE KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + KEY `_gsi_pk_idx_` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 3 +SHOW FULL CREATE TABLE u3; +Table,Create Table +u3_$,CREATE TABLE `u3_$` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + UNIQUE LOCAL KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`), + LOCAL KEY `_gsi_pk_idx_` USING BTREE (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 3 +/* tablegroup = `tg` */ +/*+TDDL:cmd_extra(UNIQUE_GSI_WITH_PRIMARY_KEY=true)*/ALTER TABLE tb2 + ADD UNIQUE KEY u4 (b, c); +SHOW CREATE TABLE u4; +Table,Create Table +u4_$,CREATE TABLE `u4_$` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) DEFAULT NULL, + PRIMARY KEY (`a`, `b`), + UNIQUE KEY `auto_shard_key_b_c` USING BTREE (`b`, `c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`b`,`c`) +PARTITIONS 3 +SHOW FULL CREATE TABLE u4; +Table,Create Table +u4_$,CREATE TABLE `u4_$` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) DEFAULT NULL, + PRIMARY KEY (`a`, `b`), + UNIQUE LOCAL KEY `auto_shard_key_b_c` USING BTREE (`b`, `c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`b`,`c`) +PARTITIONS 3 +/* tablegroup = `tg` */ +SHOW FULL CREATE TABLE tb2; +Table,Create Table +tb2,CREATE PARTITION TABLE `tb2` ( + `a` int(11) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) DEFAULT NULL, + `d` int(11) DEFAULT NULL, + PRIMARY KEY (`a`, `b`), + UNIQUE GLOBAL INDEX /* u3_$ */ `u3` (`a`, `b`) + PARTITION BY KEY(`a`,`b`) + PARTITIONS 3, + UNIQUE GLOBAL INDEX /* u4_$ */ `u4` (`b`, `c`) + PARTITION BY KEY(`b`,`c`) + PARTITIONS 3, + UNIQUE LOCAL KEY `_local_u3` (`a`, `b`), + UNIQUE LOCAL KEY `_local_u4` (`b`, `c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 3 +/* tablegroup = `tg` */ +ALTER TABLE tb2 + MODIFY COLUMN a bigint; +SHOW FULL CREATE TABLE u3; +Table,Create Table +u3_$,CREATE TABLE `u3_$` ( + `a` bigint(20) NOT NULL, + `b` int(11) NOT NULL, + PRIMARY KEY (`a`, `b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 3 +/* tablegroup = `tg` */ +SHOW FULL CREATE TABLE u4; +Table,Create Table +u4_$,CREATE TABLE `u4_$` ( + `a` bigint(20) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) DEFAULT NULL, + PRIMARY KEY (`a`, `b`), + UNIQUE LOCAL KEY `auto_shard_key_b_c` USING BTREE (`b`, `c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`b`,`c`) +PARTITIONS 3 +/* tablegroup = `tg` */ +SHOW FULL CREATE TABLE tb2; +Table,Create Table +tb2,CREATE PARTITION TABLE `tb2` ( + `a` bigint(20) NOT NULL, + `b` int(11) NOT NULL, + `c` int(11) DEFAULT NULL, + `d` int(11) DEFAULT NULL, + PRIMARY KEY (`a`, `b`), + UNIQUE GLOBAL INDEX /* u3_$ */ `u3` (`a`, `b`) + PARTITION BY KEY(`a`,`b`) + PARTITIONS 3, + UNIQUE GLOBAL INDEX /* u4_$ */ `u4` (`b`, `c`) + PARTITION BY KEY(`b`,`c`) + PARTITIONS 3, + UNIQUE LOCAL KEY `_local_u3` (`a`, `b`), + UNIQUE LOCAL KEY `_local_u4` (`b`, `c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`,`b`) +PARTITIONS 3 +/* tablegroup = `tg` */ \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_add_ugsi.test.yml b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_add_ugsi.test.yml new file mode 100644 index 000000000..c8c7c6b9a --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_add_ugsi.test.yml @@ -0,0 +1,60 @@ +drop table if exists `tb1`; +drop table if exists `tb2`; + +create table `tb1` ( + a int, + b int, + c int +); + +create table `tb2` ( + a int, + b int, + c int, + d int, + primary key(a,b) +); + +/*+TDDL:cmd_extra(UNIQUE_GSI_WITH_PRIMARY_KEY=false)*/alter table tb1 add unique key u1(a,b); + +show create table u1; + +show full create table u1; + +/*+TDDL:cmd_extra(UNIQUE_GSI_WITH_PRIMARY_KEY=true)*/alter table tb1 add unique key u2(b,c); + +show create table u2; + +show full create table u2; + +show full create table tb1; + +alter table tb1 modify column a bigint; + +show full create table u1; + +show full create table u2; + +show full create table tb1; + +/*+TDDL:cmd_extra(UNIQUE_GSI_WITH_PRIMARY_KEY=false)*/alter table tb2 add unique key u3(a,b); + +show create table u3; + +show full create table u3; + +/*+TDDL:cmd_extra(UNIQUE_GSI_WITH_PRIMARY_KEY=true)*/alter table tb2 add unique key u4(b,c); + +show create table u4; + +show full create table u4; + +show full create table tb2; + +alter table tb2 modify column a bigint; + +show full create table u3; + +show full create table u4; + +show full create table tb2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_alter_partitions.result b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_alter_partitions.result index 65cffd811..3c5a9f28b 100644 --- a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_alter_partitions.result +++ b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_alter_partitions.result @@ -72,8 +72,8 @@ ugidx_$,CREATE TABLE `ugidx_$` ( `a` int(11) NOT NULL, `c` int(11) NOT NULL, `d` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`), + UNIQUE KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`c`,`d`) PARTITIONS #@# @@ -126,8 +126,8 @@ ugidx_$,CREATE TABLE `ugidx_$` ( `a` int(11) NOT NULL, `c` int(11) NOT NULL, `d` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`), + UNIQUE KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`c`,`d`) PARTITIONS 4 diff --git a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_composite_index.result b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_composite_index.result index 4683bd4fe..0ec44c136 100644 --- a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_composite_index.result +++ b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_composite_index.result @@ -198,8 +198,8 @@ agsi_1_$,CREATE TABLE `agsi_1_$` ( `y` int(11) NOT NULL, `z` int(11) NOT NULL, `d` float NOT NULL, - UNIQUE KEY `auto_shard_key_y_z_d` USING BTREE (`y`, `z`, `d`), - KEY `_gsi_pk_idx_` USING BTREE (`x`, `y`) + PRIMARY KEY (`x`, `y`), + UNIQUE KEY `auto_shard_key_y_z_d` USING BTREE (`y`, `z`, `d`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`y`,`z`) PARTITIONS 3 @@ -250,8 +250,8 @@ agsi_3_$,CREATE TABLE `agsi_3_$` ( `c` int(11) NOT NULL, `e` int(11) NOT NULL, `f` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_x_y_z_c_e_f` USING BTREE (`x`, `y`, `z`, `c`, `e`, `f`), - KEY `_gsi_pk_idx_` USING BTREE (`x`, `y`) + PRIMARY KEY (`x`, `y`), + UNIQUE KEY `auto_shard_key_x_y_z_c_e_f` USING BTREE (`x`, `y`, `z`, `c`, `e`, `f`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`,`y`,`z`,`c`,`e`) PARTITIONS 3 @@ -264,8 +264,8 @@ agsi_3_$,CREATE TABLE `agsi_3_$` ( `c` int(11) NOT NULL, `e` int(11) NOT NULL, `f` int(11) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_x_y_z_c_e_f` USING BTREE (`x`, `y`, `z`, `c`, `e`, `f`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`, `y`) + PRIMARY KEY (`x`, `y`), + UNIQUE LOCAL KEY `auto_shard_key_x_y_z_c_e_f` USING BTREE (`x`, `y`, `z`, `c`, `e`, `f`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`,`y`,`z`,`c`,`e`) PARTITIONS 3 diff --git a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_create_with_ugsi.result b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_create_with_ugsi.result index c74776c4f..5466cd4ba 100644 --- a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_create_with_ugsi.result +++ b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_create_with_ugsi.result @@ -24,8 +24,8 @@ Table,Create Table ugsi_b_$,CREATE TABLE `ugsi_b_$` ( `b` int(11) NOT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_b` USING BTREE (`b`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_b` USING BTREE (`b`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`b`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_drop_add_primary_key.result b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_drop_add_primary_key.result index 553af55d4..8939364c0 100644 --- a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_drop_add_primary_key.result +++ b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_drop_add_primary_key.result @@ -108,8 +108,8 @@ idx_order_$,CREATE TABLE `idx_order_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, `gmt_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`, `gmt_modified`) + PRIMARY KEY (`x`, `gmt_modified`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# @@ -146,8 +146,8 @@ Table,Create Table idx_order2_$,CREATE TABLE `idx_order2_$` ( `order_id` varchar(20) DEFAULT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# @@ -191,8 +191,8 @@ Table,Create Table idx_order2_$,CREATE TABLE `idx_order2_$` ( `order_id` varchar(20) DEFAULT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_index_replaced.result b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_index_replaced.result index 40a256d00..03533ea2e 100644 --- a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_index_replaced.result +++ b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_index_replaced.result @@ -52,8 +52,8 @@ bmsql_oorder_idx1_$,CREATE TABLE `bmsql_oorder_idx1_$` ( `o_d_id` int(11) NOT NULL, `o_id` int(11) NOT NULL, `o_carrier_id` int(11) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_o_w_id_o_d_id_o_carrier_id_o_id` USING BTREE (`o_w_id`, `o_d_id`, `o_carrier_id`, `o_id`), - KEY `_gsi_pk_idx_` USING BTREE (`o_w_id`, `o_d_id`, `o_id`) + PRIMARY KEY (`o_w_id`, `o_d_id`, `o_id`), + UNIQUE KEY `auto_shard_key_o_w_id_o_d_id_o_carrier_id_o_id` USING BTREE (`o_w_id`, `o_d_id`, `o_carrier_id`, `o_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`o_w_id`,`o_d_id`,`o_carrier_id`,`o_id`) PARTITIONS #@# @@ -64,8 +64,8 @@ bmsql_oorder_idx1_$,CREATE TABLE `bmsql_oorder_idx1_$` ( `o_d_id` int(11) NOT NULL, `o_id` int(11) NOT NULL, `o_carrier_id` int(11) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_o_w_id_o_d_id_o_carrier_id_o_id` USING BTREE (`o_w_id`, `o_d_id`, `o_carrier_id`, `o_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`o_w_id`, `o_d_id`, `o_id`) + PRIMARY KEY (`o_w_id`, `o_d_id`, `o_id`), + UNIQUE LOCAL KEY `auto_shard_key_o_w_id_o_d_id_o_carrier_id_o_id` USING BTREE (`o_w_id`, `o_d_id`, `o_carrier_id`, `o_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`o_w_id`,`o_d_id`,`o_carrier_id`,`o_id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_missing_implicit_pk_bug.result b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_missing_implicit_pk_bug.result index 3025f3b31..2953b044f 100644 --- a/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_missing_implicit_pk_bug.result +++ b/polardbx-test/src/test/resources/partition/env/AutoPartitionTest/test_missing_implicit_pk_bug.result @@ -29,18 +29,18 @@ PARTITIONS #@# SHOW CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_id` USING BTREE (`id`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + `id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_id` USING BTREE (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS #@# SHOW FULL CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_id` USING BTREE (`id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`id`) + `id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE LOCAL KEY `auto_shard_key_id` USING BTREE (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -79,20 +79,20 @@ PARTITIONS #@# SHOW CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, + `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_a` USING BTREE (`a`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_a` USING BTREE (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`a`) PARTITIONS #@# SHOW FULL CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, + `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_a` USING BTREE (`a`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`a`) PARTITIONS #@# @@ -131,20 +131,20 @@ PARTITIONS #@# SHOW CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, + `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_a` USING BTREE (`a`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_a` USING BTREE (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`a`) PARTITIONS #@# SHOW FULL CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, + `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_a` USING BTREE (`a`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`a`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/CoHashTest/test_co_hash_dml.result b/polardbx-test/src/test/resources/partition/env/CoHashTest/test_co_hash_dml.result index 13ad0ff54..7dda9b566 100644 --- a/polardbx-test/src/test/resources/partition/env/CoHashTest/test_co_hash_dml.result +++ b/polardbx-test/src/test/resources/partition/env/CoHashTest/test_co_hash_dml.result @@ -23,15 +23,13 @@ PARTITIONS 16; explain select * from ch_t1_f_f where user_id='12345678'; Logical ExecutionPlan PhyTableOperation(tables="ch_t1_f_f[p14]", sql="SELECT `ch_t1_f_f`.`id`, `ch_t1_f_f`.`sid`, `ch_t1_f_f`.`user_id`, `ch_t1_f_f`.`order_id`, `ch_t1_f_f`.`order_time` FROM ? AS `ch_t1_f_f` WHERE (`ch_t1_f_f`.`user_id` = ?)", params="12345678") -HitCache:false -Source:PLAN_CACHE -TemplateId: 2f8b99db explain select * from ch_t1_f_f where order_id='abcdefg12345678'; Logical ExecutionPlan PhyTableOperation(tables="ch_t1_f_f[p14]", sql="SELECT `ch_t1_f_f`.`id`, `ch_t1_f_f`.`sid`, `ch_t1_f_f`.`user_id`, `ch_t1_f_f`.`order_id`, `ch_t1_f_f`.`order_time` FROM ? AS `ch_t1_f_f` WHERE (`ch_t1_f_f`.`order_id` = ?)", params="abcdefg12345678") explain select * from ch_t1_f_f where order_id='abcdefg12345678' or user_id='12345678'; Logical ExecutionPlan -PhyTableOperation(tables="ch_t1_f_f[p14]", sql="SELECT `ch_t1_f_f`.`id`, `ch_t1_f_f`.`sid`, `ch_t1_f_f`.`user_id`, `ch_t1_f_f`.`order_id`, `ch_t1_f_f`.`order_time` FROM ? AS `ch_t1_f_f` WHERE ((`ch_t1_f_f`.`order_id` = ?) OR (`ch_t1_f_f`.`user_id` = ?))", params="12345678,abcdefg12345678") +Gather(concurrent=true) + LogicalView(tables="ch_t1_f_f[p14]", sql="SELECT `id`, `sid`, `user_id`, `order_id`, `order_time` FROM `ch_t1_f_f` AS `ch_t1_f_f` WHERE ((`order_id` = ?) OR (`user_id` = ?))") explain select * from ch_t1_f_f where order_id='abcdefg12345678' and user_id='12345678'; Logical ExecutionPlan PhyTableOperation(tables="ch_t1_f_f[p14]", sql="SELECT `ch_t1_f_f`.`id`, `ch_t1_f_f`.`sid`, `ch_t1_f_f`.`user_id`, `ch_t1_f_f`.`order_id`, `ch_t1_f_f`.`order_time` FROM ? AS `ch_t1_f_f` WHERE ((`ch_t1_f_f`.`order_id` = ?) AND (`ch_t1_f_f`.`user_id` = ?))", params="12345678,abcdefg12345678") @@ -40,17 +38,16 @@ Logical ExecutionPlan PhyTableOperation(tables="ch_t1_f_f[p14]", sql="SELECT `ch_t1_f_f`.`id`, `ch_t1_f_f`.`sid`, `ch_t1_f_f`.`user_id`, `ch_t1_f_f`.`order_id`, `ch_t1_f_f`.`order_time` FROM ? AS `ch_t1_f_f` WHERE ((`ch_t1_f_f`.`order_id`, `ch_t1_f_f`.`user_id`) =(?, ?))", params="12345678,abcdefg12345678") explain select * from ch_t1_f_f where order_id in ('abcdefg12345678') and user_id in ('12345678'); Logical ExecutionPlan -PhyTableOperation(tables="ch_t1_f_f[p14]", sql="SELECT `ch_t1_f_f`.`id`, `ch_t1_f_f`.`sid`, `ch_t1_f_f`.`user_id`, `ch_t1_f_f`.`order_id`, `ch_t1_f_f`.`order_time` FROM ? AS `ch_t1_f_f` WHERE ((`ch_t1_f_f`.`order_id` IN (?)) AND (`ch_t1_f_f`.`user_id` IN (?)))", params="Raw('12345678'),Raw('abcdefg12345678')") +Gather(concurrent=true) + LogicalView(tables="ch_t1_f_f[p14]", sql="SELECT `id`, `sid`, `user_id`, `order_id`, `order_time` FROM `ch_t1_f_f` AS `ch_t1_f_f` WHERE ((`order_id` IN(?)) AND (`user_id` IN(?)))") explain select * from ch_t1_f_f where (order_id,user_id) in (('abcdefg12345678','12345678')); Logical ExecutionPlan -PhyTableOperation(tables="ch_t1_f_f[p14]", sql="SELECT `ch_t1_f_f`.`id`, `ch_t1_f_f`.`sid`, `ch_t1_f_f`.`user_id`, `ch_t1_f_f`.`order_id`, `ch_t1_f_f`.`order_time` FROM ? AS `ch_t1_f_f` WHERE (((`ch_t1_f_f`.`order_id`, `ch_t1_f_f`.`user_id`)) IN (?))", params="Raw(('abcdefg12345678','12345678'))") +Gather(concurrent=true) + LogicalView(tables="ch_t1_f_f[p14]", sql="SELECT `id`, `sid`, `user_id`, `order_id`, `order_time` FROM `ch_t1_f_f` AS `ch_t1_f_f` WHERE (((`order_id`, `user_id`)) IN(?))") ## point-select2 explain select * from ch_t1_f_f where user_id='12345679'; Logical ExecutionPlan PhyTableOperation(tables="ch_t1_f_f[p7]", sql="SELECT `ch_t1_f_f`.`id`, `ch_t1_f_f`.`sid`, `ch_t1_f_f`.`user_id`, `ch_t1_f_f`.`order_id`, `ch_t1_f_f`.`order_time` FROM ? AS `ch_t1_f_f` WHERE (`ch_t1_f_f`.`user_id` = ?)", params="12345679") -HitCache:true -Source:PLAN_CACHE -TemplateId: 2f8b99db explain select * from ch_t1_f_f where order_id='abcdefg12345678'; Logical ExecutionPlan PhyTableOperation(tables="ch_t1_f_f[p14]", sql="SELECT `ch_t1_f_f`.`id`, `ch_t1_f_f`.`sid`, `ch_t1_f_f`.`user_id`, `ch_t1_f_f`.`order_id`, `ch_t1_f_f`.`order_time` FROM ? AS `ch_t1_f_f` WHERE (`ch_t1_f_f`.`order_id` = ?)", params="abcdefg12345678") @@ -77,9 +74,6 @@ explain select * from ch_t1_f_f where user_id>='12345678'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="ch_t1_f_f[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `id`, `sid`, `user_id`, `order_id`, `order_time` FROM `ch_t1_f_f` AS `ch_t1_f_f` WHERE (`user_id` >= ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: c1e87f3f explain select * from ch_t1_f_f where order_id<='abcdefg12345678'; Logical ExecutionPlan Gather(concurrent=true) diff --git a/polardbx-test/src/test/resources/partition/env/CoHashTest/test_co_hash_subquery.result b/polardbx-test/src/test/resources/partition/env/CoHashTest/test_co_hash_subquery.result index 00e8c34ad..c6d4e9d10 100644 --- a/polardbx-test/src/test/resources/partition/env/CoHashTest/test_co_hash_subquery.result +++ b/polardbx-test/src/test/resources/partition/env/CoHashTest/test_co_hash_subquery.result @@ -95,10 +95,8 @@ Project(id="id", sid="sid") ## route: p8 explain select id from ch_t1_u_o where order_id in (111234); Logical ExecutionPlan -PhyTableOperation(tables="ch_t1_u_o[p8]", sql="SELECT `ch_t1_u_o`.`id` AS `id` FROM ? AS `ch_t1_u_o` WHERE (`ch_t1_u_o`.`order_id` IN (?))", params="Raw(111234)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 9df7bc31 +Gather(concurrent=true) + LogicalView(tables="ch_t1_u_o[p8]", sql="SELECT `id` FROM `ch_t1_u_o` AS `ch_t1_u_o` WHERE (`order_id` IN(?))") ## route: p3,p5,p7 select user_id from ch_t2_u_o where user_id in (123456, 123458, 123459) order by user_id; user_id diff --git a/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_dd.result b/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_dd.result index 911cb899f..883f6dbdc 100644 --- a/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_dd.result +++ b/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_dd.result @@ -63,6 +63,7 @@ unique global index `tb6_k4` (`col5`) dbpartition by yyyydd(`col5`), unique global index `tb6_k5` (`col6`, `col7`) covering (`col8`) dbpartition by yyyydd(`col6`) tbpartition by dd(`col7`) tbpartitions 4, global index `tb6_k6` (`col8`) covering (`col9`) dbpartition by yyyymm(`col8`) ) dbpartition by yyyydd(`col1`) tbpartition by dd(`col2`) tbpartitions 4; +create view v1 as select * from tb6; ## dry run create database testConvertDbAuto2 like testConvertDrdsDb mode=auto dry_run=true; TABLE,CREATE_TABLE_DRDS,CREATE_TABLE_AUTO diff --git a/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_dd.test.yml b/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_dd.test.yml index 5e391ebe4..e561c18ff 100644 --- a/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_dd.test.yml +++ b/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_dd.test.yml @@ -69,7 +69,8 @@ unique global index `tb6_k4` (`col5`) dbpartition by yyyydd(`col5`), unique global index `tb6_k5` (`col6`, `col7`) covering (`col8`) dbpartition by yyyydd(`col6`) tbpartition by dd(`col7`) tbpartitions 4, global index `tb6_k6` (`col8`) covering (`col9`) dbpartition by yyyymm(`col8`) ) dbpartition by yyyydd(`col1`) tbpartition by dd(`col2`) tbpartitions 4; - + +create view v1 as select * from tb6; ## dry run create database testConvertDbAuto2 like testConvertDrdsDb mode=auto dry_run=true; diff --git a/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_mm.result b/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_mm.result index b23985515..f6f98043b 100644 --- a/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_mm.result +++ b/polardbx-test/src/test/resources/partition/env/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_mm.result @@ -121,6 +121,7 @@ SUBPARTITION BY RANGE (MONTH(`col11`)) ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ) tb2,CREATE TABLE `tb2` ( @@ -148,6 +149,7 @@ SUBPARTITION BY RANGE (MONTH(`col3`)) ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ) tb4,CREATE TABLE `tb4` ( @@ -226,6 +228,7 @@ tb6,CREATE TABLE `tb6` ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ), CLUSTERED INDEX `tb6_k3`(`col4`) PARTITION BY HASH (TO_DAYS(`col4`)) PARTITIONS 16, @@ -242,6 +245,7 @@ tb6,CREATE TABLE `tb6` ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ), GLOBAL INDEX `tb6_k6`(`col8`) COVERING (`col0`, `col1`, `col2`, `col9`) PARTITION BY HASH (TO_DAYS(`col8`)) PARTITIONS 16 @@ -258,6 +262,7 @@ SUBPARTITION BY RANGE (MONTH(`col2`)) ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ) use polardbx; diff --git a/polardbx-test/src/test/resources/partition/env/ConvertDrdsTableModeTest/test_subpartition.result b/polardbx-test/src/test/resources/partition/env/ConvertDrdsTableModeTest/test_subpartition.result index ae49a00c3..31f43cb71 100644 --- a/polardbx-test/src/test/resources/partition/env/ConvertDrdsTableModeTest/test_subpartition.result +++ b/polardbx-test/src/test/resources/partition/env/ConvertDrdsTableModeTest/test_subpartition.result @@ -278,6 +278,7 @@ True,CREATE TABLE `tb3` ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ), CLUSTERED INDEX `tb3_k2`(`col4`, `col3`) PARTITION BY KEY (`col4`) PARTITIONS 16 @@ -292,6 +293,7 @@ True,CREATE TABLE `tb3` ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ), UNIQUE GLOBAL INDEX `tb3_k3` (`col6`, `col5`) PARTITION BY HASH (TO_DAYS(`col5`)) PARTITIONS 16 @@ -306,6 +308,7 @@ True,CREATE TABLE `tb3` ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ), GLOBAL INDEX `tb3_k4`(`col6`, `col7`) COVERING (`col8`) PARTITION BY HASH (TO_DAYS(`col6`)) PARTITIONS 16 @@ -320,6 +323,7 @@ True,CREATE TABLE `tb3` ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ) ) @@ -335,6 +339,7 @@ SUBPARTITION BY RANGE (MONTH(`col2`)) ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ),null ## test mmdd diff --git a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci.result b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci.result index fe4121eac..fd9cfdb4c 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci.result +++ b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci.result @@ -109,7 +109,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -138,7 +138,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -167,7 +167,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -196,7 +196,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -225,7 +225,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 9 + PARTITIONS 9 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -255,7 +255,7 @@ t_order_1,CREATE PARTITION TABLE `t_order_1` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`_drds_implicit_id_`) PARTITIONS #@# @@ -284,7 +284,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -313,7 +313,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -342,7 +342,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -370,7 +370,7 @@ t_order_single,CREATE TABLE `t_order_single` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 9 + PARTITIONS 9 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -398,7 +398,7 @@ t_order_single,CREATE TABLE `t_order_single` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -426,7 +426,7 @@ t_order_single,CREATE TABLE `t_order_single` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -454,7 +454,7 @@ t_order_single,CREATE TABLE `t_order_single` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -482,7 +482,7 @@ t_order_single,CREATE TABLE `t_order_single` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -511,7 +511,7 @@ t_order_single_1,CREATE TABLE `t_order_single_1` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -539,7 +539,7 @@ t_order_broadcast,CREATE TABLE `t_order_broadcast` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 9 + PARTITIONS 9 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -567,7 +567,7 @@ t_order_broadcast,CREATE TABLE `t_order_broadcast` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -595,7 +595,7 @@ t_order_broadcast,CREATE TABLE `t_order_broadcast` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -623,7 +623,7 @@ t_order_broadcast,CREATE TABLE `t_order_broadcast` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -651,7 +651,7 @@ t_order_broadcast_1,CREATE TABLE `t_order_broadcast_1` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -670,7 +670,7 @@ heavy_qps_table,CREATE TABLE `heavy_qps_table` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* heavy_qps_table_cci_$ */ `heavy_qps_table_cci` (`id`) PARTITION BY HASH(`id`) - PARTITIONS 4 + PARTITIONS 4 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -682,7 +682,10 @@ CCI,error_type,status,primary_key,details DROP INDEX `heavy_qps_table_cci` ON `heavy_qps_table`; # create cci on partition table with dictionary columns -/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/CREATE CLUSTERED COLUMNAR INDEX `nation_col_index` ON `nation` (`n_nationkey`) PARTITION BY HASH (`n_nationkey`) PARTITIONS 1 DICTIONARY_COLUMNS = 'n_name,n_comment'; +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/CREATE CLUSTERED COLUMNAR INDEX `nation_col_index` ON `nation` (`n_nationkey`) PARTITION BY HASH (`n_nationkey`) PARTITIONS 1 DICTIONARY_COLUMNS = 'n_name,n_comment' +COLUMNAR_OPTIONS='{ + "DICTIONARY_COLUMNS":"N_NAME,N_COMMENT", +}'; SHOW CREATE TABLE `nation`; Table,Create Table nation,CREATE TABLE `nation` ( @@ -707,7 +710,10 @@ nation,CREATE TABLE `nation` ( PRIMARY KEY (`n_nationkey`), CLUSTERED COLUMNAR INDEX /* nation_col_index_$ */ `nation_col_index` (`n_nationkey`) PARTITION BY HASH(`n_nationkey`) - PARTITIONS 1 DICTIONARY_COLUMNS = '`n_name`,`n_comment`' + PARTITIONS 1 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "DICTIONARY_COLUMNS":"`N_NAME`,`N_COMMENT`", + }' ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY(`n_nationkey`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_hash.result b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_hash.result index 70e9ff62e..4d660c930 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_hash.result +++ b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_hash.result @@ -37,7 +37,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_0_$ */ `cci_0` (`seller_id`) PARTITION BY KEY(`seller_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -68,7 +68,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_1_$ */ `cci_1` (`seller_id`) PARTITION BY KEY(`buyer_id`,`order_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -99,7 +99,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_2_$ */ `cci_2` (`seller_id`) PARTITION BY HASH(`seller_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -130,7 +130,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_3_$ */ `cci_3` (`seller_id`) PARTITION BY HASH(`buyer_id`,`order_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -161,7 +161,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_4_$ */ `cci_4` (`seller_id`) PARTITION BY HASH(YEAR(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -192,7 +192,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_5_$ */ `cci_5` (`seller_id`) PARTITION BY HASH(MONTH(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -223,7 +223,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_6_$ */ `cci_6` (`seller_id`) PARTITION BY HASH(DAYOFMONTH(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -254,7 +254,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_7_$ */ `cci_7` (`seller_id`) PARTITION BY HASH(DAYOFWEEK(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -285,7 +285,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_8_$ */ `cci_8` (`seller_id`) PARTITION BY HASH(DAYOFYEAR(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -316,7 +316,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_9_$ */ `cci_9` (`seller_id`) PARTITION BY HASH(TO_DAYS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -347,7 +347,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_10_$ */ `cci_10` (`seller_id`) PARTITION BY HASH(TO_MONTHS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -378,7 +378,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_11_$ */ `cci_11` (`seller_id`) PARTITION BY HASH(TO_WEEKS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -409,7 +409,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_12_$ */ `cci_12` (`seller_id`) PARTITION BY HASH(TO_SECONDS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -440,7 +440,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_13_$ */ `cci_13` (`seller_id`) PARTITION BY HASH(UNIX_TIMESTAMP(`gmt_modified`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -471,7 +471,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_14_$ */ `cci_14` (`seller_id`) PARTITION BY HASH(SUBSTR(`seller_id`,1,4)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -502,7 +502,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_15_$ */ `cci_15` (`seller_id`) PARTITION BY KEY(`seller_id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -533,7 +533,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_16_$ */ `cci_16` (`seller_id`) PARTITION BY HASH(`seller_id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -564,7 +564,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_17_$ */ `cci_17` (`seller_id`) PARTITION BY HASH(SUBSTR(`seller_id`,1,4)) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -595,7 +595,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_18_$ */ `cci_18` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_list.result b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_list.result index 0e73178c8..f4df288fa 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_list.result +++ b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_list.result @@ -48,7 +48,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PARTITION BY LIST COLUMNS(`country`,`city`) (PARTITION p1 VALUES IN (('China','Beijing'),('China','Hangzhou')) ENGINE = Columnar, PARTITION p3 VALUES IN (('Russian','Moscow')) ENGINE = Columnar, - PARTITION p2 VALUES IN (('United States','Chicago'),('United States','NewYork')) ENGINE = Columnar) + PARTITION p2 VALUES IN (('United States','Chicago'),('United States','NewYork')) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -89,7 +89,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PARTITION BY LIST(YEAR(`order_datetime`)) (PARTITION p1 VALUES IN (1990,1991,1992,1993,1994,1995,1996,1997,1998,1999) ENGINE = Columnar, PARTITION p2 VALUES IN (2000,2001,2002,2003,2004,2005,2006,2007,2008,2009) ENGINE = Columnar, - PARTITION p3 VALUES IN (2010,2011,2012,2013,2014,2015,2016,2017,2018,2019) ENGINE = Columnar) + PARTITION p3 VALUES IN (2010,2011,2012,2013,2014,2015,2016,2017,2018,2019) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_range.result b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_range.result index 0f0aa7864..1553d6a54 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_range.result +++ b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_partition_by_range.result @@ -56,7 +56,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PARTITION p3 VALUES LESS THAN ('30000','2021-01-01 00:00:00') ENGINE = Columnar, PARTITION p4 VALUES LESS THAN ('40000','2021-01-01 00:00:00') ENGINE = Columnar, PARTITION p5 VALUES LESS THAN ('50000','2021-01-01 00:00:00') ENGINE = Columnar, - PARTITION p6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = Columnar) + PARTITION p6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -106,7 +106,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PARTITION p3 VALUES LESS THAN (738337) ENGINE = Columnar, PARTITION p4 VALUES LESS THAN (738429) ENGINE = Columnar, PARTITION p5 VALUES LESS THAN (738521) ENGINE = Columnar, - PARTITION p6 VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) + PARTITION p6 VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_random_suffix.result b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_random_suffix.result index 9f98a32f9..02d5121c4 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_random_suffix.result +++ b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_random_suffix.result @@ -27,7 +27,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`x`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`x`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`) PARTITIONS #@# @@ -47,7 +47,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`x`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY KEY(`seller_id`) - PARTITIONS 2 + PARTITIONS 2 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`) PARTITIONS #@# @@ -67,7 +67,7 @@ t_order_1,CREATE PARTITION TABLE `t_order_1` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* cci_seller_id_$ */ `cci_seller_id` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`_drds_implicit_id_`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_with_options.result b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_with_options.result new file mode 100644 index 000000000..472c56112 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_with_options.result @@ -0,0 +1,505 @@ +## DISABLE_FAST_SQL_PARSER +drop table if exists t_order +delete from metadb.columnar_config where table_id = 0 and config_key = 'SNAPSHOT_RETENTION_DAYS' +delete from metadb.columnar_config where table_id = 0 and config_key = 'AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL' +CREATE TABLE t_order ( +`id` bigint(11) NOT NULL AUTO_INCREMENT, +`order_id` varchar(20) DEFAULT NULL, +`buyer_id` varchar(20) DEFAULT NULL, +`seller_id` varchar(20) DEFAULT NULL, +`order_snapshot` longtext DEFAULT NULL, +`order_detail` longtext DEFAULT NULL, +PRIMARY KEY (`id`), +KEY `l_i_order` (`order_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`order_id`) partitions 16 +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +CREATE CLUSTERED COLUMNAR INDEX `seller_snapshot` ON t_order (`seller_id`) +partition by hash(`order_id`) partitions 16 +COLUMNAR_OPTIONS='{ + "TYPE":"snapshot", + "snapshot_retention_days":"15", + "auto_gen_columnar_snapshot_interval":"10" + }' +SHOW FULL CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX /* seller_snapshot_$ */ `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`order_id`) + PARTITIONS 16 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL":"10", + "SNAPSHOT_RETENTION_DAYS":"15", + }', + LOCAL KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +/* tablegroup = `tg` */ +SHOW CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`order_id`) + PARTITIONS 16, + KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +ALTER TABLE t_order DROP INDEX seller_snapshot +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +CREATE CLUSTERED COLUMNAR INDEX `seller_snapshot` ON t_order (`seller_id`) +partition by hash(`order_id`) +COLUMNAR_OPTIONS='{ + "type":"SNAPSHOT", + "SNAPSHOT_RETENTION_DAYS":"15", + }' +SHOW FULL CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX /* seller_snapshot_$ */ `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`order_id`) + PARTITIONS 16 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL":"-1", + "SNAPSHOT_RETENTION_DAYS":"15", + }', + LOCAL KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +/* tablegroup = `tg` */ +SHOW CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`order_id`) + PARTITIONS 16, + KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +ALTER TABLE t_order DROP INDEX seller_snapshot +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +CREATE CLUSTERED COLUMNAR INDEX `seller_snapshot` ON t_order (`seller_id`) +COLUMNAR_OPTIONS='{ + "type":"SNAPSHOT" + }' +SHOW FULL CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX /* seller_snapshot_$ */ `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`id`) + PARTITIONS 16 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL":"-1", + "SNAPSHOT_RETENTION_DAYS":"7", + }', + LOCAL KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +/* tablegroup = `tg` */ +SHOW CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`id`) + PARTITIONS 16, + KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +ALTER TABLE t_order DROP INDEX seller_snapshot +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +partition by hash(`order_id`) partitions 16 +COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "snapshot_retention_days":"15", + "auto_gen_columnar_snapshot_interval":"10" + }' +SHOW FULL CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX /* seller_snapshot_$ */ `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`order_id`) + PARTITIONS 16 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL":"10", + "SNAPSHOT_RETENTION_DAYS":"15", + }', + LOCAL KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +/* tablegroup = `tg` */ +SHOW CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`order_id`) + PARTITIONS 16, + KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +ALTER TABLE t_order DROP INDEX seller_snapshot +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +partition by hash(`order_id`) +COLUMNAR_OPTIONS='{ + "type":"snapshot", + "SNAPSHOT_RETENTION_DAYS":"15", + }' +SHOW FULL CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX /* seller_snapshot_$ */ `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`order_id`) + PARTITIONS 16 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL":"-1", + "SNAPSHOT_RETENTION_DAYS":"15", + }', + LOCAL KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +/* tablegroup = `tg` */ +SHOW CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`order_id`) + PARTITIONS 16, + KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +ALTER TABLE t_order DROP INDEX seller_snapshot +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +COLUMNAR_OPTIONS='{ + "type":"snapshot" + }' +SHOW FULL CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX /* seller_snapshot_$ */ `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`id`) + PARTITIONS 16 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL":"-1", + "SNAPSHOT_RETENTION_DAYS":"7", + }', + LOCAL KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +/* tablegroup = `tg` */ +SHOW CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`id`) + PARTITIONS 16, + KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +ALTER TABLE t_order DROP INDEX seller_snapshot +DROP TABLE IF EXISTS t_order +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +CREATE TABLE t_order ( +`id` bigint(11) NOT NULL AUTO_INCREMENT, +`order_id` varchar(20) DEFAULT NULL, +`buyer_id` varchar(20) DEFAULT NULL, +`seller_id` varchar(20) DEFAULT NULL, +`order_snapshot` longtext DEFAULT NULL, +`order_detail` longtext DEFAULT NULL, +PRIMARY KEY (`id`), +KEY `l_i_order` (`order_id`), +CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +partition by hash(`order_id`) partitions 16 +COLUMNAR_OPTIONS='{ + "type":"snapshot", + "snapshot_retention_days":"15" + }' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`order_id`) partitions 16 +SHOW FULL CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX /* seller_snapshot_$ */ `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`order_id`) + PARTITIONS 16 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL":"-1", + "SNAPSHOT_RETENTION_DAYS":"15", + }', + LOCAL KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +/* tablegroup = `tg` */ +SHOW CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`order_id`) + PARTITIONS 16, + KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +ALTER TABLE t_order DROP INDEX seller_snapshot +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +COLUMNAR_OPTIONS='{ + "type":"snapshot", + "DICTIONARY_COLUMNS":"order_snapshot,order_detail" + }' +SHOW FULL CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX /* seller_snapshot_$ */ `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`id`) + PARTITIONS 16 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL":"-1", + "DICTIONARY_COLUMNS":"`ORDER_SNAPSHOT`,`ORDER_DETAIL`", + "SNAPSHOT_RETENTION_DAYS":"7", + }', + LOCAL KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +/* tablegroup = `tg` */ +SHOW CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`id`) + PARTITIONS 16, + KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +ALTER TABLE t_order DROP INDEX seller_snapshot +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +DICTIONARY_COLUMNS='order_snapshot,order_detail' +COLUMNAR_OPTIONS='{ + "type":"snapshot" + }' +SHOW FULL CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX /* seller_snapshot_$ */ `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`id`) + PARTITIONS 16 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL":"-1", + "DICTIONARY_COLUMNS":"`ORDER_SNAPSHOT`,`ORDER_DETAIL`", + "SNAPSHOT_RETENTION_DAYS":"7", + }', + LOCAL KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +/* tablegroup = `tg` */ +SHOW CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`id`) + PARTITIONS 16, + KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +ALTER TABLE t_order DROP INDEX seller_snapshot +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +COLUMNAR_OPTIONS='{ + "type":"snapshot", + "DICTIONARY_COLUMNS":"order_snapshot,order_detail", + "snapshot_retention_days":"15", + }' +SHOW FULL CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX /* seller_snapshot_$ */ `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`id`) + PARTITIONS 16 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL":"-1", + "DICTIONARY_COLUMNS":"`ORDER_SNAPSHOT`,`ORDER_DETAIL`", + "SNAPSHOT_RETENTION_DAYS":"15", + }', + LOCAL KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +/* tablegroup = `tg` */ +SHOW CREATE TABLE t_order +Table,Create Table +t_order,CREATE TABLE `t_order` ( + `id` bigint(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(20) DEFAULT NULL, + `buyer_id` varchar(20) DEFAULT NULL, + `seller_id` varchar(20) DEFAULT NULL, + `order_snapshot` longtext, + `order_detail` longtext, + PRIMARY KEY (`id`), + CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) + PARTITION BY HASH(`id`) + PARTITIONS 16, + KEY `l_i_order` (`order_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`order_id`) +PARTITIONS 16 +ALTER TABLE t_order DROP INDEX seller_snapshot +DROP TABLE IF EXISTS t_order; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_with_options.test.yml b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_with_options.test.yml new file mode 100644 index 000000000..4341c490c --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/CreateCciTest/test_create_cci_with_options.test.yml @@ -0,0 +1,136 @@ +## DISABLE_FAST_SQL_PARSER +drop table if exists t_order; + +delete from metadb.columnar_config where table_id = 0 and config_key = 'SNAPSHOT_RETENTION_DAYS'; +delete from metadb.columnar_config where table_id = 0 and config_key = 'AUTO_GEN_COLUMNAR_SNAPSHOT_INTERVAL'; + +CREATE TABLE t_order ( +`id` bigint(11) NOT NULL AUTO_INCREMENT, +`order_id` varchar(20) DEFAULT NULL, +`buyer_id` varchar(20) DEFAULT NULL, +`seller_id` varchar(20) DEFAULT NULL, +`order_snapshot` longtext DEFAULT NULL, +`order_detail` longtext DEFAULT NULL, +PRIMARY KEY (`id`), +KEY `l_i_order` (`order_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`order_id`) partitions 16; + +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +CREATE CLUSTERED COLUMNAR INDEX `seller_snapshot` ON t_order (`seller_id`) +partition by hash(`order_id`) partitions 16 +COLUMNAR_OPTIONS='{ + "TYPE":"snapshot", + "snapshot_retention_days":"15", + "auto_gen_columnar_snapshot_interval":"10" + }'; +SHOW FULL CREATE TABLE t_order; +SHOW CREATE TABLE t_order; +ALTER TABLE t_order DROP INDEX seller_snapshot; + +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +CREATE CLUSTERED COLUMNAR INDEX `seller_snapshot` ON t_order (`seller_id`) +partition by hash(`order_id`) +COLUMNAR_OPTIONS='{ + "type":"SNAPSHOT", + "SNAPSHOT_RETENTION_DAYS":"15", + }'; +SHOW FULL CREATE TABLE t_order; +SHOW CREATE TABLE t_order; +ALTER TABLE t_order DROP INDEX seller_snapshot; + +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +CREATE CLUSTERED COLUMNAR INDEX `seller_snapshot` ON t_order (`seller_id`) +COLUMNAR_OPTIONS='{ + "type":"SNAPSHOT" + }'; +SHOW FULL CREATE TABLE t_order; +SHOW CREATE TABLE t_order; +ALTER TABLE t_order DROP INDEX seller_snapshot; + +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +partition by hash(`order_id`) partitions 16 +COLUMNAR_OPTIONS='{ + "TYPE":"SNAPSHOT", + "snapshot_retention_days":"15", + "auto_gen_columnar_snapshot_interval":"10" + }'; +SHOW FULL CREATE TABLE t_order; +SHOW CREATE TABLE t_order; +ALTER TABLE t_order DROP INDEX seller_snapshot; + +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +partition by hash(`order_id`) +COLUMNAR_OPTIONS='{ + "type":"snapshot", + "SNAPSHOT_RETENTION_DAYS":"15", + }'; +SHOW FULL CREATE TABLE t_order; +SHOW CREATE TABLE t_order; +ALTER TABLE t_order DROP INDEX seller_snapshot; + +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +COLUMNAR_OPTIONS='{ + "type":"snapshot" + }'; +SHOW FULL CREATE TABLE t_order; +SHOW CREATE TABLE t_order; +ALTER TABLE t_order DROP INDEX seller_snapshot; + +DROP TABLE IF EXISTS t_order; + +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +CREATE TABLE t_order ( +`id` bigint(11) NOT NULL AUTO_INCREMENT, +`order_id` varchar(20) DEFAULT NULL, +`buyer_id` varchar(20) DEFAULT NULL, +`seller_id` varchar(20) DEFAULT NULL, +`order_snapshot` longtext DEFAULT NULL, +`order_detail` longtext DEFAULT NULL, +PRIMARY KEY (`id`), +KEY `l_i_order` (`order_id`), +CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +partition by hash(`order_id`) partitions 16 +COLUMNAR_OPTIONS='{ + "type":"snapshot", + "snapshot_retention_days":"15" + }' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`order_id`) partitions 16; +SHOW FULL CREATE TABLE t_order; +SHOW CREATE TABLE t_order; +ALTER TABLE t_order DROP INDEX seller_snapshot; + +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +COLUMNAR_OPTIONS='{ + "type":"snapshot", + "DICTIONARY_COLUMNS":"order_snapshot,order_detail" + }'; +SHOW FULL CREATE TABLE t_order; +SHOW CREATE TABLE t_order; +ALTER TABLE t_order DROP INDEX seller_snapshot; + +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +DICTIONARY_COLUMNS='order_snapshot,order_detail' +COLUMNAR_OPTIONS='{ + "type":"snapshot" + }'; +SHOW FULL CREATE TABLE t_order; +SHOW CREATE TABLE t_order; +ALTER TABLE t_order DROP INDEX seller_snapshot; + +/*+TDDL:CMD_EXTRA(SKIP_DDL_TASKS="WaitColumnarTableCreationTask")*/ +ALTER TABLE t_order ADD CLUSTERED COLUMNAR INDEX `seller_snapshot` (`seller_id`) +COLUMNAR_OPTIONS='{ + "type":"snapshot", + "DICTIONARY_COLUMNS":"order_snapshot,order_detail", + "snapshot_retention_days":"15", + }'; +SHOW FULL CREATE TABLE t_order; +SHOW CREATE TABLE t_order; +ALTER TABLE t_order DROP INDEX seller_snapshot; + +DROP TABLE IF EXISTS t_order; diff --git a/polardbx-test/src/test/resources/partition/env/CreateCciTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/CreateCciTest/testcase.config.yml index 834a48f62..ae878f185 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateCciTest/testcase.config.yml +++ b/polardbx-test/src/test/resources/partition/env/CreateCciTest/testcase.config.yml @@ -4,3 +4,4 @@ test_create_cci_random_suffix test_create_cci_partition_by_hash test_create_cci_partition_by_list test_create_cci_partition_by_range +test_create_cci_with_options diff --git a/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_64len.result b/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_64len.result index a112dd850..6f8d544c0 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_64len.result +++ b/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_64len.result @@ -33,8 +33,4 @@ INDEX `k_1` (`k`) insert into `Auto012345678901234567890123456789012345678901234567890123456789`.`t1` (k) values(2); select k from `Auto012345678901234567890123456789012345678901234567890123456789`.t1; k -2 -select table_schema,table_name,part_name,phy_group,phy_db from information_schema.partitions_meta where table_schema='Auto012345678901234567890123456789012345678901234567890123456789' and table_name='t1' order by part_name; -table_schema,table_name,part_name,phy_group,phy_db -auto012345678901234567890123456789012345678901234567890123456789,t1,p1,AUTO01234567890123456789012345678901_13428F39_P00000_GROUP,auto01234567890123456789012345678901_13428f39_p00000 -auto012345678901234567890123456789012345678901234567890123456789,t1,p2,AUTO01234567890123456789012345678901_13428F39_P00001_GROUP,auto01234567890123456789012345678901_13428f39_p00001 +2 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_64len.test.yml b/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_64len.test.yml index f71e65cbb..a778a9c9d 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_64len.test.yml +++ b/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_64len.test.yml @@ -27,4 +27,3 @@ INDEX `k_1` (`k`) ) broadcast; insert into `Auto012345678901234567890123456789012345678901234567890123456789`.`t1` (k) values(2); select k from `Auto012345678901234567890123456789012345678901234567890123456789`.t1; -select table_schema,table_name,part_name,phy_group,phy_db from information_schema.partitions_meta where table_schema='Auto012345678901234567890123456789012345678901234567890123456789' and table_name='t1' order by part_name \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_invalid_dbname.result b/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_invalid_dbname.result new file mode 100644 index 000000000..fb6eefeb4 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_invalid_dbname.result @@ -0,0 +1,25 @@ +## DISABLE_FAST_SQL_PARSER +## error_msg: $# forbidden #$ +create database `mysql`; +forbidden +## error_msg: $# forbidden #$ +create database if not exists `mysql`; +forbidden +## error_msg: $# forbidden #$ +create database `performance_schema` mode='auto'; +forbidden +## error_msg: $# forbidden #$ +create database if not exists `performance_schema` mode='auto'; +forbidden +## error_msg: $# forbidden #$ +create database `__cdc__` mode='auto'; +forbidden +## error_msg: $# forbidden #$ +create database if not exists `__cdc__` mode='auto'; +forbidden +## error_msg: $# forbidden #$ +create database `metadb` mode='auto'; +forbidden +## error_msg: $# forbidden #$ +create database if not exists `metadb` mode='auto'; +forbidden \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_invalid_dbname.test.yml b/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_invalid_dbname.test.yml new file mode 100644 index 000000000..b42e86051 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/test_createdb_invalid_dbname.test.yml @@ -0,0 +1,25 @@ +## DISABLE_FAST_SQL_PARSER + +## error_msg: $# forbidden #$ +create database `mysql`; + +## error_msg: $# forbidden #$ +create database if not exists `mysql`; + +## error_msg: $# forbidden #$ +create database `performance_schema` mode='auto'; + +## error_msg: $# forbidden #$ +create database if not exists `performance_schema` mode='auto'; + +## error_msg: $# forbidden #$ +create database `__cdc__` mode='auto'; + +## error_msg: $# forbidden #$ +create database if not exists `__cdc__` mode='auto'; + +## error_msg: $# forbidden #$ +create database `metadb` mode='auto'; + +## error_msg: $# forbidden #$ +create database if not exists `metadb` mode='auto'; diff --git a/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/testcase.config.yml index 6c88c4f75..c892d50ab 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/testcase.config.yml +++ b/polardbx-test/src/test/resources/partition/env/CreateDatabaseTest/testcase.config.yml @@ -1,2 +1,3 @@ test_createdb_64len -test_createdb_64len_2 \ No newline at end of file +test_createdb_64len_2 +test_createdb_invalid_dbname \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci.result b/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci.result index d700db2a8..2f562e45e 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci.result +++ b/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci.result @@ -49,7 +49,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -85,7 +85,7 @@ t_order_1,CREATE PARTITION TABLE `t_order_1` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -121,7 +121,7 @@ t_order_2,CREATE PARTITION TABLE `t_order_2` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -157,7 +157,7 @@ t_order_3,CREATE PARTITION TABLE `t_order_3` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -194,7 +194,7 @@ t_order_4,CREATE TABLE `t_order_4` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -230,7 +230,7 @@ t_order_5,CREATE PARTITION TABLE `t_order_5` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`_drds_implicit_id_`) PARTITIONS #@# @@ -267,7 +267,7 @@ t_order_6,CREATE TABLE `t_order_6` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -304,7 +304,7 @@ t_order_7,CREATE TABLE `t_order_7` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -341,7 +341,7 @@ t_order_8,CREATE TABLE `t_order_8` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 3 @@ -377,7 +377,7 @@ t_order_single,CREATE TABLE `t_order_single` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -412,7 +412,7 @@ t_order_single_1,CREATE TABLE `t_order_single_1` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -447,7 +447,7 @@ t_order_single_2,CREATE TABLE `t_order_single_2` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -482,7 +482,7 @@ t_order_single_3,CREATE TABLE `t_order_single_3` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -517,7 +517,7 @@ t_order_single_4,CREATE TABLE `t_order_single_4` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -552,7 +552,7 @@ t_order_single_5,CREATE TABLE `t_order_single_5` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 SINGLE /* tablegroup = `single_tg` */ @@ -587,7 +587,7 @@ t_order_broadcast,CREATE TABLE `t_order_broadcast` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -622,7 +622,7 @@ t_order_broadcast_1,CREATE TABLE `t_order_broadcast_1` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -657,7 +657,7 @@ t_order_broadcast_2,CREATE TABLE `t_order_broadcast_2` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -692,7 +692,7 @@ t_order_broadcast_3,CREATE TABLE `t_order_broadcast_3` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -727,7 +727,7 @@ t_order_broadcast_4,CREATE TABLE `t_order_broadcast_4` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 20 + PARTITIONS 20 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -762,7 +762,7 @@ t_order_broadcast_5,CREATE TABLE `t_order_broadcast_5` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 BROADCAST /* tablegroup = `broadcast_tg` */ @@ -784,7 +784,7 @@ heavy_qps_table,CREATE TABLE `heavy_qps_table` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* heavy_qps_table_cci_$ */ `heavy_qps_table_cci` (`id`) PARTITION BY HASH(`id`) - PARTITIONS 4 + PARTITIONS 4 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -824,7 +824,10 @@ region,CREATE TABLE `region` ( PRIMARY KEY (`r_regionkey`), CLUSTERED COLUMNAR INDEX /* region_col_index_$ */ `region_col_index` (`r_regionkey`) PARTITION BY HASH(`r_regionkey`) - PARTITIONS 1 DICTIONARY_COLUMNS = '`r_name`' + PARTITIONS 1 ENGINE=OSS + COLUMNAR_OPTIONS='{ + "DICTIONARY_COLUMNS":"`R_NAME`", + }' ) ENGINE = InnoDB DEFAULT CHARSET = latin1 PARTITION BY KEY(`r_regionkey`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_hash.result b/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_hash.result index b99c7b098..d276c14cc 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_hash.result +++ b/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_hash.result @@ -48,7 +48,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_0_$ */ `cci_0` (`seller_id`) PARTITION BY KEY(`seller_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -86,7 +86,7 @@ t_order_1,CREATE PARTITION TABLE `t_order_1` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_1_$ */ `cci_1` (`seller_id`) PARTITION BY KEY(`buyer_id`,`order_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -124,7 +124,7 @@ t_order_2,CREATE PARTITION TABLE `t_order_2` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_2_$ */ `cci_2` (`seller_id`) PARTITION BY HASH(`seller_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -162,7 +162,7 @@ t_order_3,CREATE PARTITION TABLE `t_order_3` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_3_$ */ `cci_3` (`seller_id`) PARTITION BY HASH(`buyer_id`,`order_id`) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -200,7 +200,7 @@ t_order_4,CREATE PARTITION TABLE `t_order_4` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_4_$ */ `cci_4` (`seller_id`) PARTITION BY HASH(YEAR(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -238,7 +238,7 @@ t_order_5,CREATE PARTITION TABLE `t_order_5` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_5_$ */ `cci_5` (`seller_id`) PARTITION BY HASH(MONTH(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -276,7 +276,7 @@ t_order_6,CREATE PARTITION TABLE `t_order_6` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_6_$ */ `cci_6` (`seller_id`) PARTITION BY HASH(DAYOFMONTH(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -314,7 +314,7 @@ t_order_7,CREATE PARTITION TABLE `t_order_7` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_7_$ */ `cci_7` (`seller_id`) PARTITION BY HASH(DAYOFWEEK(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -352,7 +352,7 @@ t_order_8,CREATE PARTITION TABLE `t_order_8` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_8_$ */ `cci_8` (`seller_id`) PARTITION BY HASH(DAYOFYEAR(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -390,7 +390,7 @@ t_order_9,CREATE PARTITION TABLE `t_order_9` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_9_$ */ `cci_9` (`seller_id`) PARTITION BY HASH(TO_DAYS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -428,7 +428,7 @@ t_order_10,CREATE PARTITION TABLE `t_order_10` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_10_$ */ `cci_10` (`seller_id`) PARTITION BY HASH(TO_MONTHS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -466,7 +466,7 @@ t_order_11,CREATE PARTITION TABLE `t_order_11` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_11_$ */ `cci_11` (`seller_id`) PARTITION BY HASH(TO_WEEKS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -504,7 +504,7 @@ t_order_12,CREATE PARTITION TABLE `t_order_12` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_12_$ */ `cci_12` (`seller_id`) PARTITION BY HASH(TO_SECONDS(`order_datetime`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -542,7 +542,7 @@ t_order_13,CREATE PARTITION TABLE `t_order_13` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_13_$ */ `cci_13` (`seller_id`) PARTITION BY HASH(UNIX_TIMESTAMP(`gmt_modified`)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -580,7 +580,7 @@ t_order_14,CREATE PARTITION TABLE `t_order_14` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_14_$ */ `cci_14` (`seller_id`) PARTITION BY HASH(SUBSTR(`seller_id`,1,4)) - PARTITIONS 3 + PARTITIONS 3 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -618,7 +618,7 @@ t_order_15,CREATE PARTITION TABLE `t_order_15` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_15_$ */ `cci_15` (`seller_id`) PARTITION BY KEY(`seller_id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -656,7 +656,7 @@ t_order_16,CREATE PARTITION TABLE `t_order_16` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_16_$ */ `cci_16` (`seller_id`) PARTITION BY HASH(`seller_id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -694,7 +694,7 @@ t_order_17,CREATE PARTITION TABLE `t_order_17` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_17_$ */ `cci_17` (`seller_id`) PARTITION BY HASH(SUBSTR(`seller_id`,1,4)) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -732,7 +732,7 @@ t_order_18,CREATE PARTITION TABLE `t_order_18` ( PRIMARY KEY (`id`), CLUSTERED COLUMNAR INDEX /* cci_18_$ */ `cci_18` (`seller_id`) PARTITION BY HASH(`id`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_list.result b/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_list.result index 104823ece..e9fd2b7cb 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_list.result +++ b/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_list.result @@ -47,7 +47,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PARTITION BY LIST COLUMNS(`country`,`city`) (PARTITION p1 VALUES IN (('China','Beijing'),('China','Hangzhou')) ENGINE = Columnar, PARTITION p3 VALUES IN (('Russian','Moscow')) ENGINE = Columnar, - PARTITION p2 VALUES IN (('United States','Chicago'),('United States','NewYork')) ENGINE = Columnar) + PARTITION p2 VALUES IN (('United States','Chicago'),('United States','NewYork')) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -99,7 +99,7 @@ t_order_1,CREATE PARTITION TABLE `t_order_1` ( PARTITION BY LIST(YEAR(`order_datetime`)) (PARTITION p1 VALUES IN (1990,1991,1992,1993,1994,1995,1996,1997,1998,1999) ENGINE = Columnar, PARTITION p2 VALUES IN (2000,2001,2002,2003,2004,2005,2006,2007,2008,2009) ENGINE = Columnar, - PARTITION p3 VALUES IN (2010,2011,2012,2013,2014,2015,2016,2017,2018,2019) ENGINE = Columnar) + PARTITION p3 VALUES IN (2010,2011,2012,2013,2014,2015,2016,2017,2018,2019) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_range.result b/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_range.result index 8d48eefc0..d59ef3e1c 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_range.result +++ b/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_partition_by_range.result @@ -50,7 +50,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PARTITION p3 VALUES LESS THAN ('30000','2021-01-01 00:00:00') ENGINE = Columnar, PARTITION p4 VALUES LESS THAN ('40000','2021-01-01 00:00:00') ENGINE = Columnar, PARTITION p5 VALUES LESS THAN ('50000','2021-01-01 00:00:00') ENGINE = Columnar, - PARTITION p6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = Columnar) + PARTITION p6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -100,14 +100,14 @@ t_order_1,CREATE PARTITION TABLE `t_order_1` ( `gmt_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `rint` double(10, 2) DEFAULT NULL, PRIMARY KEY (`id`), - CLUSTERED COLUMNAR INDEX /* cci_1_$ */ `cci_1` (`seller_id`) + CLUSTERED COLUMNAR INDEX /* cci_1_$ */ `cci_1` (`seller_id`) PARTITION BY RANGE(TO_DAYS(`order_datetime`)) (PARTITION p1 VALUES LESS THAN (738156) ENGINE = Columnar, PARTITION p2 VALUES LESS THAN (738246) ENGINE = Columnar, PARTITION p3 VALUES LESS THAN (738337) ENGINE = Columnar, PARTITION p4 VALUES LESS THAN (738429) ENGINE = Columnar, PARTITION p5 VALUES LESS THAN (738521) ENGINE = Columnar, - PARTITION p6 VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) + PARTITION p6 VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_random_suffix.result b/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_random_suffix.result index 1a33c3830..8c752512e 100644 --- a/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_random_suffix.result +++ b/polardbx-test/src/test/resources/partition/env/CreateTableWithCciTest/test_create_table_with_cci_random_suffix.result @@ -19,7 +19,7 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( PRIMARY KEY (`x`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY HASH(`x`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`) PARTITIONS #@# @@ -40,7 +40,7 @@ t_order_1,CREATE PARTITION TABLE `t_order_1` ( PRIMARY KEY (`x`), CLUSTERED COLUMNAR INDEX /* seller_id_$ */ `seller_id` (`seller_id`) PARTITION BY KEY(`seller_id`) - PARTITIONS 2 + PARTITIONS 2 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`) PARTITIONS #@# @@ -62,7 +62,7 @@ t_order_2,CREATE PARTITION TABLE `t_order_2` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* i_0_$ */ `i_0` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`_drds_implicit_id_`) PARTITIONS #@# @@ -84,7 +84,7 @@ t_order_3,CREATE PARTITION TABLE `t_order_3` ( PRIMARY KEY (`_drds_implicit_id_`), CLUSTERED COLUMNAR INDEX /* i_0_$ */ `i_0` (`seller_id`) PARTITION BY HASH(`_drds_implicit_id_`) - PARTITIONS 16 + PARTITIONS 16 ENGINE=OSS ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`_drds_implicit_id_`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/ImplicitTableGroupTest/alter_table_remove_partitioning.result b/polardbx-test/src/test/resources/partition/env/ImplicitTableGroupTest/alter_table_remove_partitioning.result new file mode 100644 index 000000000..37227e838 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/ImplicitTableGroupTest/alter_table_remove_partitioning.result @@ -0,0 +1,117 @@ +## DISABLE_FAST_SQL_PARSER +create table t1(a int, b bigint, c int, index i1(b)) partition by key(a) partitions 2 +create table t2(a int, b bigint, c int, index i1(a)) partition by key(a) partitions 2 +create table t3(a int, b bigint, c int, index i1(a), primary key(a)) partition by key(a) partitions 2 +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t1 +Table,Create Table +t1,CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` bigint(20) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `i1` (`b`), + LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 2 +(PARTITION p1 VALUES LESS THAN (1) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB) +/* tablegroup = `tg` */ +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t2 +Table,Create Table +t2,CREATE TABLE `t2` ( + `a` int(11) DEFAULT NULL, + `b` bigint(20) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + LOCAL KEY `i1` (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 2 +(PARTITION p1 VALUES LESS THAN (1) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB) +/* tablegroup = `tg` */ +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t3 +Table,Create Table +t3,CREATE TABLE `t3` ( + `a` int(11) NOT NULL, + `b` bigint(20) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + LOCAL KEY `i1` (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 2 +(PARTITION p1 VALUES LESS THAN (1) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB) +/* tablegroup = `tg` */ +alter table t1 remove partitioning with tablegroup=tgi1 implicit, index i1 with tablegroup=tgi2 implicit +alter table t2 remove partitioning with tablegroup=tgi1 implicit, index i1 with tablegroup=tgi3 implicit +alter table t3 remove partitioning with tablegroup=tgi3 implicit, index i1 with tablegroup=tgi3 implicit +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t1 +Table,Create Table +t1,CREATE PARTITION TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` bigint(20) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + GLOBAL INDEX /* i1_$ */ `i1` (`b`) + PARTITION BY KEY(`b`,`_drds_implicit_id_`) + PARTITIONS 3 + (PARTITION p1 VALUES LESS THAN (-3074457345618258601,9223372036854775807) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (3074457345618258603,9223372036854775807) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + LOCAL KEY `_local_i1` (`b`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`_drds_implicit_id_`) +PARTITIONS 3 +(PARTITION p1 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB) +/* tablegroup = `tgi1` */ +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t2 +Table,Create Table +t2,CREATE PARTITION TABLE `t2` ( + `a` int(11) DEFAULT NULL, + `b` bigint(20) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`_drds_implicit_id_`), + GLOBAL INDEX /* i1_$ */ `i1` (`a`) + PARTITION BY KEY(`a`,`_drds_implicit_id_`) + PARTITIONS 3 + (PARTITION p1 VALUES LESS THAN (-3074457345618258601,9223372036854775807) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (3074457345618258603,9223372036854775807) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + LOCAL KEY `_local_i1` (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`_drds_implicit_id_`) +PARTITIONS 3 +(PARTITION p1 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB) +/* tablegroup = `tgi1` */ +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t3 +Table,Create Table +t3,CREATE PARTITION TABLE `t3` ( + `a` int(11) NOT NULL, + `b` bigint(20) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + GLOBAL INDEX /* i1_$ */ `i1` (`a`) + PARTITION BY KEY(`a`) + PARTITIONS 3 + (PARTITION p1 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + LOCAL KEY `_local_i1` (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 3 +(PARTITION p1 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, + PARTITION p3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB) +/* tablegroup = `tgi3` */ \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/ImplicitTableGroupTest/alter_table_remove_partitioning.test.yml b/polardbx-test/src/test/resources/partition/env/ImplicitTableGroupTest/alter_table_remove_partitioning.test.yml new file mode 100644 index 000000000..f2cf7105d --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/ImplicitTableGroupTest/alter_table_remove_partitioning.test.yml @@ -0,0 +1,14 @@ +## DISABLE_FAST_SQL_PARSER +create table t1(a int, b bigint, c int, index i1(b)) partition by key(a) partitions 2; +create table t2(a int, b bigint, c int, index i1(a)) partition by key(a) partitions 2; +create table t3(a int, b bigint, c int, index i1(a), primary key(a)) partition by key(a) partitions 2; +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t1; +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t2; +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t3; + +alter table t1 remove partitioning with tablegroup=tgi1 implicit, index i1 with tablegroup=tgi2 implicit; +alter table t2 remove partitioning with tablegroup=tgi1 implicit, index i1 with tablegroup=tgi3 implicit; +alter table t3 remove partitioning with tablegroup=tgi3 implicit, index i1 with tablegroup=tgi3 implicit; +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t1; +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t2; +/*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table t3; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/ImplicitTableGroupTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/ImplicitTableGroupTest/testcase.config.yml index 7811f7b3c..58a51b1ef 100644 --- a/polardbx-test/src/test/resources/partition/env/ImplicitTableGroupTest/testcase.config.yml +++ b/polardbx-test/src/test/resources/partition/env/ImplicitTableGroupTest/testcase.config.yml @@ -1,2 +1,3 @@ alter_table_modify_column -create_table_with_implicit_tg \ No newline at end of file +create_table_with_implicit_tg +alter_table_remove_partitioning \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/InvisibleGsiDdlTest/test_ddl_in_auto.result b/polardbx-test/src/test/resources/partition/env/InvisibleGsiDdlTest/test_ddl_in_auto.result index 6bd4abd40..9863a236f 100644 --- a/polardbx-test/src/test/resources/partition/env/InvisibleGsiDdlTest/test_ddl_in_auto.result +++ b/polardbx-test/src/test/resources/partition/env/InvisibleGsiDdlTest/test_ddl_in_auto.result @@ -51,8 +51,8 @@ Table,Create Table g2_$,CREATE TABLE `g2_$` ( `id` int(11) NOT NULL, `name` varchar(20) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`name`) PARTITIONS 3 @@ -306,8 +306,8 @@ Table,Create Table g2_$,CREATE TABLE `g2_$` ( `id` int(11) NOT NULL, `name` varchar(20) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`name`) PARTITIONS 3 @@ -579,8 +579,8 @@ g2_$,CREATE TABLE `g2_$` ( `id` int(11) NOT NULL, `name` varchar(20) DEFAULT NULL, `addr3` varchar(10) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`name`) PARTITIONS 3 diff --git a/polardbx-test/src/test/resources/partition/env/MultiDBSingleTableTest/test_multi_db_single_table.result b/polardbx-test/src/test/resources/partition/env/MultiDBSingleTableTest/test_multi_db_single_table.result index 09feab14f..b46a271bc 100644 --- a/polardbx-test/src/test/resources/partition/env/MultiDBSingleTableTest/test_multi_db_single_table.result +++ b/polardbx-test/src/test/resources/partition/env/MultiDBSingleTableTest/test_multi_db_single_table.result @@ -96,13 +96,22 @@ Logical ExecutionPlan LogicalView(tables=[single_t1.single_t1_s1, single_t2.single_t2_s1], sql="") explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert single_t3.single_t3_s1(a3, b3) select * from single_t1.single_t1_s1; Logical ExecutionPlan -LogicalView(tables=[single_t3.single_t3_s1, single_t1.single_t1_s1], sql="") +LogicalInsert(table="single_t3_s1", columns=RecordType(BIGINT_UNSIGNED a3, BIGINT_UNSIGNED b3, BIGINT _drds_implicit_id_), mode=MULTI) + LogicalView(tables="single_t1_s1[p1]", sql="SELECT `a1` AS `a3`, `b1` AS `b3`, NULL AS `_drds_implicit_id_` FROM `single_t1_s1` AS `single_t1_s1`") begin; explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert single_t3.single_t3_s1(a3, b3) select * from single_t1.single_t1_s1; Logical ExecutionPlan LogicalInsert(table="single_t3_s1", columns=RecordType(BIGINT_UNSIGNED a3, BIGINT_UNSIGNED b3, BIGINT _drds_implicit_id_), mode=MULTI) LogicalView(tables="single_t1_s1[p1]", sql="SELECT `a1` AS `a3`, `b1` AS `b3`, NULL AS `_drds_implicit_id_` FROM `single_t1_s1` AS `single_t1_s1`") commit; +explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert drds_single_t4.single_t4_s1(a3, b3) select * from single_t1.single_t1_s1; +Logical ExecutionPlan +LogicalInsert(table="single_t4_s1", columns=RecordType(BIGINT_UNSIGNED a3, BIGINT_UNSIGNED b3, BIGINT _drds_implicit_id_), mode=MULTI) + LogicalView(tables="single_t1_s1[p1]", sql="SELECT `a1` AS `a3`, `b1` AS `b3`, NULL AS `_drds_implicit_id_` FROM `single_t1_s1` AS `single_t1_s1`") +explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert single_t1.single_t1_s1(a1, b1) select * from drds_single_t4.single_t4_s1; +Logical ExecutionPlan +LogicalInsert(table="single_t1_s1", columns=RecordType(BIGINT_UNSIGNED a1, BIGINT_UNSIGNED b1, BIGINT _drds_implicit_id_), mode=MULTI) + LogicalView(tables="DRDS_SINGLE_T4_000000_GROUP.single_t4_s1", sql="SELECT `a3` AS `a1`, `b3` AS `b1`, NULL AS `_drds_implicit_id_` FROM `single_t4_s1` AS `single_t4_s1`") insert single_t3.single_t3_s1(a3, b3) select * from single_t1.single_t1_s1; select * from single_t3.single_t3_s1; a3,b3 @@ -127,5 +136,4 @@ explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/select * from single_t2.s Logical ExecutionPlan HashJoin(condition="a2 = a3", type="inner") LogicalView(tables="single_t2_s1[p1]", sql="SELECT `a2`, `b2` FROM `single_t2_s1` AS `single_t2_s1`") - Gather(concurrent=true) - LogicalView(tables="single_t3_s2", shardCount=0, sql="SELECT `a3`, `b3` FROM `single_t3_s2` AS `single_t3_s2`") \ No newline at end of file + LogicalView(tables="single_t3_s2", shardCount=0, sql="SELECT `a3`, `b3` FROM `single_t3_s2` AS `single_t3_s2`") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/MultiDBSingleTableTest/test_multi_db_single_table.test.yml b/polardbx-test/src/test/resources/partition/env/MultiDBSingleTableTest/test_multi_db_single_table.test.yml index 59f4bc716..9cc940361 100644 --- a/polardbx-test/src/test/resources/partition/env/MultiDBSingleTableTest/test_multi_db_single_table.test.yml +++ b/polardbx-test/src/test/resources/partition/env/MultiDBSingleTableTest/test_multi_db_single_table.test.yml @@ -104,6 +104,10 @@ explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert single_t3.single_t commit; +explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert drds_single_t4.single_t4_s1(a3, b3) select * from single_t1.single_t1_s1; + +explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert single_t1.single_t1_s1(a1, b1) select * from drds_single_t4.single_t4_s1; + insert single_t3.single_t3_s1(a3, b3) select * from single_t1.single_t1_s1; select * from single_t3.single_t3_s1; diff --git a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_many_random_multi_ddl.result b/polardbx-test/src/test/resources/partition/env/MultiPartDdlBigCaseTest/test_many_random_multi_ddl.result similarity index 99% rename from polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_many_random_multi_ddl.result rename to polardbx-test/src/test/resources/partition/env/MultiPartDdlBigCaseTest/test_many_random_multi_ddl.result index ff95ef92a..2c128479c 100644 --- a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_many_random_multi_ddl.result +++ b/polardbx-test/src/test/resources/partition/env/MultiPartDdlBigCaseTest/test_many_random_multi_ddl.result @@ -1,6 +1,6 @@ -DROP DATABASE IF EXISTS d_multi_part_ddl; -CREATE DATABASE d_multi_part_ddl MODE 'auto'; -USE d_multi_part_ddl; +DROP DATABASE IF EXISTS d_multi_part_ddl_random; +CREATE DATABASE d_multi_part_ddl_random MODE 'auto'; +USE d_multi_part_ddl_random; DROP TABLE IF EXISTS `alter_table_test_20bt`; CREATE TABLE `alter_table_test_20bt` ( `id` int(11) DEFAULT NULL, @@ -13262,11 +13262,11 @@ ALTER TABLE alter_table_test_20bt DROP INDEX `i_5743`; /*+TDDL:CMD_EXTRA(CHECK_LOGICAL_COLUMN_ORDER=true)*/CHECK TABLE `alter_table_test_20bt`; Table,Op,Msg_type,Msg_text -d_multi_part_ddl.alter_table_test_20bt:Topology,check,status,OK -d_multi_part_ddl.alter_table_test_20bt:Columns,check,status,OK +d_multi_part_ddl_random.alter_table_test_20bt:Topology,check,status,OK +d_multi_part_ddl_random.alter_table_test_20bt:Columns,check,status,OK alter_table_test_20bt.i_5744:Local Index,check,status,OK alter_table_test_20bt.i_5745:Local Index,check,status,OK alter_table_test_20bt.i_5746:Local Index,check,status,OK alter_table_test_20bt.i_5747:Local Index,check,status,OK USE polardbx; -DROP DATABASE IF EXISTS d_multi_part_ddl; +DROP DATABASE IF EXISTS d_multi_part_ddl_random; diff --git a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_many_random_multi_ddl.test.yml b/polardbx-test/src/test/resources/partition/env/MultiPartDdlBigCaseTest/test_many_random_multi_ddl.test.yml similarity index 99% rename from polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_many_random_multi_ddl.test.yml rename to polardbx-test/src/test/resources/partition/env/MultiPartDdlBigCaseTest/test_many_random_multi_ddl.test.yml index 8ec7fb978..bbf7de664 100644 --- a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_many_random_multi_ddl.test.yml +++ b/polardbx-test/src/test/resources/partition/env/MultiPartDdlBigCaseTest/test_many_random_multi_ddl.test.yml @@ -1,8 +1,8 @@ -drop database if exists d_multi_part_ddl; +drop database if exists d_multi_part_ddl_random; -create database d_multi_part_ddl mode = "auto"; +create database d_multi_part_ddl_random mode = "auto"; -use d_multi_part_ddl; +use d_multi_part_ddl_random; drop table if exists `alter_table_test_20bt` ; @@ -1412,4 +1412,4 @@ ALTER TABLE alter_table_test_20bt ADD COLUMN c4799 int FIRST,ADD COLUMN c4798 va use polardbx; -drop database if exists d_multi_part_ddl; \ No newline at end of file +drop database if exists d_multi_part_ddl_random; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/MultiPartDdlBigCaseTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/MultiPartDdlBigCaseTest/testcase.config.yml new file mode 100644 index 000000000..65529bdf7 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/MultiPartDdlBigCaseTest/testcase.config.yml @@ -0,0 +1 @@ +test_many_random_multi_ddl \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column.result b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column.result new file mode 100644 index 000000000..d23bc2237 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column.result @@ -0,0 +1,62 @@ +DROP DATABASE IF EXISTS d_multi_part_ddl; +CREATE DATABASE d_multi_part_ddl MODE 'auto'; +USE d_multi_part_ddl; +DROP TABLE IF EXISTS test_multi_change_column1; +CREATE TABLE test_multi_change_column1 ( + c1 int, + c2 double, + c3 varchar(10), + c4 varchar(40) +); +ALTER TABLE test_multi_change_column1 + ADD LOCAL INDEX i_c1c2 (c1, c2), + ADD LOCAL INDEX i_c2c3 (c2, c3), + ADD LOCAL INDEX i_c3c4 (c3, c4); +ALTER TABLE test_multi_change_column1 + CHANGE COLUMN c1 C2 int AFTER C1, + CHANGE COLUMN c2 C1 double; +/*+TDDL:CMD_EXTRA(CHECK_LOGICAL_COLUMN_ORDER=true)*/CHECK TABLE test_multi_change_column1; +Table,Op,Msg_type,Msg_text +d_multi_part_ddl.test_multi_change_column1:Topology,check,status,OK +d_multi_part_ddl.test_multi_change_column1:Columns,check,status,OK +test_multi_change_column1.i_c1c2:Local Index,check,status,OK +test_multi_change_column1.i_c2c3:Local Index,check,status,OK +test_multi_change_column1.i_c3c4:Local Index,check,status,OK +ALTER TABLE test_multi_change_column1 + CHANGE COLUMN c1 C3 int AFTER C4, + CHANGE COLUMN C3 c1 varchar(30) AFTER c2, + ADD COLUMN c5 varchar(50); +/*+TDDL:CMD_EXTRA(CHECK_LOGICAL_COLUMN_ORDER=true)*/CHECK TABLE test_multi_change_column1; +Table,Op,Msg_type,Msg_text +d_multi_part_ddl.test_multi_change_column1:Topology,check,status,OK +d_multi_part_ddl.test_multi_change_column1:Columns,check,status,OK +test_multi_change_column1.i_c1c2:Local Index,check,status,OK +test_multi_change_column1.i_c2c3:Local Index,check,status,OK +test_multi_change_column1.i_c3c4:Local Index,check,status,OK +ALTER TABLE `test_multi_change_column1` + MODIFY COLUMN `C2` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL FIRST, + MODIFY COLUMN `c3` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c2`, + MODIFY COLUMN `C4` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c3`, + MODIFY COLUMN `c1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c4`; +/*+TDDL:CMD_EXTRA(CHECK_LOGICAL_COLUMN_ORDER=true)*/CHECK TABLE test_multi_change_column1; +Table,Op,Msg_type,Msg_text +d_multi_part_ddl.test_multi_change_column1:Topology,check,status,OK +d_multi_part_ddl.test_multi_change_column1:Columns,check,status,OK +test_multi_change_column1.i_c1c2:Local Index,check,status,OK +test_multi_change_column1.i_c2c3:Local Index,check,status,OK +test_multi_change_column1.i_c3c4:Local Index,check,status,OK +ALTER TABLE `test_multi_change_column1` + CHANGE COLUMN `c3` `C8` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL FIRST, + CHANGE COLUMN `c5` `c2` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c8`, + CHANGE COLUMN `C2` `c5` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c2`, + CHANGE COLUMN `c4` `c3` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c5`, + MODIFY COLUMN `C1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c3` +/*+TDDL:CMD_EXTRA(CHECK_LOGICAL_COLUMN_ORDER=true)*/CHECK TABLE test_multi_change_column1; +Table,Op,Msg_type,Msg_text +d_multi_part_ddl.test_multi_change_column1:Topology,check,status,OK +d_multi_part_ddl.test_multi_change_column1:Columns,check,status,OK +test_multi_change_column1.i_c1c2:Local Index,check,status,OK +test_multi_change_column1.i_c2c3:Local Index,check,status,OK +test_multi_change_column1.i_c3c4:Local Index,check,status,OK +USE polardbx; +DROP DATABASE IF EXISTS d_multi_part_ddl; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column.test.yml b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column.test.yml new file mode 100644 index 000000000..3fb04e2cf --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column.test.yml @@ -0,0 +1,42 @@ +DROP DATABASE IF EXISTS d_multi_part_ddl; +CREATE DATABASE d_multi_part_ddl MODE 'auto'; +USE d_multi_part_ddl; +DROP TABLE IF EXISTS test_multi_change_column1; +CREATE TABLE test_multi_change_column1 ( +c1 int, +c2 double, +c3 varchar(10), +c4 varchar(40) +); +ALTER TABLE test_multi_change_column1 +ADD LOCAL INDEX i_c1c2 (c1, c2), +ADD LOCAL INDEX i_c2c3 (c2, c3), +ADD LOCAL INDEX i_c3c4 (c3, c4); +ALTER TABLE test_multi_change_column1 +CHANGE COLUMN c1 C2 int AFTER C1, +CHANGE COLUMN c2 C1 double; +/*+TDDL:CMD_EXTRA(CHECK_LOGICAL_COLUMN_ORDER=true)*/CHECK TABLE test_multi_change_column1; + +ALTER TABLE test_multi_change_column1 +CHANGE COLUMN c1 C3 int AFTER C4, +CHANGE COLUMN C3 c1 varchar(30) AFTER c2, +ADD COLUMN c5 varchar(50); +/*+TDDL:CMD_EXTRA(CHECK_LOGICAL_COLUMN_ORDER=true)*/CHECK TABLE test_multi_change_column1; + +ALTER TABLE `test_multi_change_column1` +MODIFY COLUMN `C2` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL FIRST, +MODIFY COLUMN `c3` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c2`, +MODIFY COLUMN `C4` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c3`, +MODIFY COLUMN `c1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c4`; +/*+TDDL:CMD_EXTRA(CHECK_LOGICAL_COLUMN_ORDER=true)*/CHECK TABLE test_multi_change_column1; + +ALTER TABLE `test_multi_change_column1` +CHANGE COLUMN `c3` `C8` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL FIRST, +CHANGE COLUMN `c5` `c2` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c8`, +CHANGE COLUMN `C2` `c5` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c2`, +CHANGE COLUMN `c4` `c3` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c5`, +MODIFY COLUMN `C1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c3` +/*+TDDL:CMD_EXTRA(CHECK_LOGICAL_COLUMN_ORDER=true)*/CHECK TABLE test_multi_change_column1; + +USE polardbx; +DROP DATABASE IF EXISTS d_multi_part_ddl; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column_rename_index.result b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column_rename_index.result new file mode 100644 index 000000000..183f84b54 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column_rename_index.result @@ -0,0 +1,73 @@ +DROP DATABASE IF EXISTS d_multi_part_ddl; +CREATE DATABASE d_multi_part_ddl MODE 'auto'; +USE d_multi_part_ddl; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( + c1 varchar(10), + c2 varchar(20), + C3 varchar(30), + c4 varchar(40), + C5 varchar(50), + c6 varchar(60) +); +ALTER TABLE `t1` + ADD LOCAL INDEX `i_ab` (c3, c4); +ALTER TABLE `t1` + ADD LOCAL INDEX `i_cd` (c3, C5); +ALTER TABLE `t1` + ADD LOCAL INDEX `i_fn` (c2, c4); +ALTER TABLE `t1` + ADD LOCAL INDEX `i_ch` (c1, C6); +ALTER TABLE `t1` + ADD LOCAL INDEX `i_mn` (c1, c5); +ALTER TABLE `t1` + MODIFY COLUMN `c3` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL FIRST, + MODIFY COLUMN `C4` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c3`, + CHANGE COLUMN `c2` `C5` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c4`, + CHANGE COLUMN `c6` `c2` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `C5`, + CHANGE COLUMN `c1` `C7` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `C2`, + CHANGE COLUMN `c5` `c1` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c7`; +/*+TDDL:CMD_EXTRA(LOGICAL_CHECK_COLUMN_ORDER=true)*/CHECK TABLE t1; +Table,Op,Msg_type,Msg_text +d_multi_part_ddl.t1:Topology,check,status,OK +d_multi_part_ddl.t1:Columns,check,status,OK +t1.i_ab:Local Index,check,status,OK +t1.i_cd:Local Index,check,status,OK +t1.i_ch:Local Index,check,status,OK +t1.i_fn:Local Index,check,status,OK +t1.i_mn:Local Index,check,status,OK +ALTER TABLE `t1` + DROP COLUMN `c5`, + DROP COLUMN `c2`, + MODIFY COLUMN `c4` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL FIRST, + MODIFY COLUMN `c3` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c4`, + MODIFY COLUMN `c7` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL AFTER `c3`, + RENAME INDEX `I_ab` TO `i_Mn`, + RENAME INDEX `i_cd` TO `i_ch`, + RENAME INDEX `i_ch` TO `i_Ab`, + RENAME INDEX `i_Mn` TO `i_fn`, + RENAME INDEX `i_fn` TO `i_cd`, + CHARACTER SET = utf8; +/*+TDDL:CMD_EXTRA(LOGICAL_CHECK_COLUMN_ORDER=true)*/CHECK TABLE t1; +Table,Op,Msg_type,Msg_text +d_multi_part_ddl.t1:Topology,check,status,OK +d_multi_part_ddl.t1:Columns,check,status,OK +t1.i_Ab:Local Index,check,status,OK +t1.i_cd:Local Index,check,status,OK +t1.i_ch:Local Index,check,status,OK +t1.i_fn:Local Index,check,status,OK +t1.i_Mn:Local Index,check,status,OK +ALTER TABLE `t1` + RENAME INDEX `i_cD` TO `i_pq`, + CHARACTER SET = utf8; +/*+TDDL:CMD_EXTRA(LOGICAL_CHECK_COLUMN_ORDER=true)*/CHECK TABLE t1; +Table,Op,Msg_type,Msg_text +d_multi_part_ddl.t1:Topology,check,status,OK +d_multi_part_ddl.t1:Columns,check,status,OK +t1.i_Ab:Local Index,check,status,OK +t1.i_ch:Local Index,check,status,OK +t1.i_fn:Local Index,check,status,OK +t1.i_Mn:Local Index,check,status,OK +t1.i_pq:Local Index,check,status,OK +USE polardbx; +DROP DATABASE IF EXISTS d_multi_part_ddl; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column_rename_index.test.yml b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column_rename_index.test.yml new file mode 100644 index 000000000..8b342f299 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_multi_case_inconsist_change_column_rename_index.test.yml @@ -0,0 +1,52 @@ +DROP DATABASE IF EXISTS d_multi_part_ddl; +CREATE DATABASE d_multi_part_ddl MODE 'auto'; +USE d_multi_part_ddl; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( + c1 varchar(10), + c2 varchar(20), + C3 varchar(30), + c4 varchar(40), + C5 varchar(50), + c6 varchar(60) +); +ALTER TABLE `t1` + ADD LOCAL INDEX `i_ab` (c3, c4); +ALTER TABLE `t1` + ADD LOCAL INDEX `i_cd` (c3, C5); +ALTER TABLE `t1` + ADD LOCAL INDEX `i_fn` (c2, c4); +ALTER TABLE `t1` + ADD LOCAL INDEX `i_ch` (c1, C6); +ALTER TABLE `t1` + ADD LOCAL INDEX `i_mn` (c1, c5); +ALTER TABLE `t1` + MODIFY COLUMN `c3` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL FIRST, + MODIFY COLUMN `C4` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c3`, + CHANGE COLUMN `c2` `C5` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c4`, + CHANGE COLUMN `c6` `c2` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `C5`, + CHANGE COLUMN `c1` `C7` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `C2`, + CHANGE COLUMN `c5` `c1` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c7`; +/*+TDDL:CMD_EXTRA(LOGICAL_CHECK_COLUMN_ORDER=true)*/CHECK TABLE t1; + +ALTER TABLE `t1` + DROP COLUMN `c5`, + DROP COLUMN `c2`, + MODIFY COLUMN `c4` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL FIRST, + MODIFY COLUMN `c3` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL AFTER `c4`, + MODIFY COLUMN `c7` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL AFTER `c3`, + RENAME INDEX `I_ab` TO `i_Mn`, + RENAME INDEX `i_cd` TO `i_ch`, + RENAME INDEX `i_ch` TO `i_Ab`, + RENAME INDEX `i_Mn` TO `i_fn`, + RENAME INDEX `i_fn` TO `i_cd`, + CHARACTER SET = utf8; +/*+TDDL:CMD_EXTRA(LOGICAL_CHECK_COLUMN_ORDER=true)*/CHECK TABLE t1; + +ALTER TABLE `t1` + RENAME INDEX `i_cD` TO `i_pq`, + CHARACTER SET = utf8; +/*+TDDL:CMD_EXTRA(LOGICAL_CHECK_COLUMN_ORDER=true)*/CHECK TABLE t1; + +USE polardbx; +DROP DATABASE IF EXISTS d_multi_part_ddl; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_single_case_inconsist_change_column.result b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_single_case_inconsist_change_column.result new file mode 100644 index 000000000..b71d8e9a4 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_single_case_inconsist_change_column.result @@ -0,0 +1,25 @@ +DROP DATABASE IF EXISTS d_single_part_ddl; +CREATE DATABASE d_single_part_ddl MODE 'auto'; +USE d_single_part_ddl; +DROP TABLE IF EXISTS test_single_change_column1; +CREATE TABLE test_single_change_column1 ( + c1 int, + c2 double, + c3 varchar(10), + c4 varchar(40) +); +ALTER TABLE test_single_change_column1 + ADD LOCAL INDEX i_c1c2 (c1, C2); +ALTER TABLE test_single_change_column1 + CHANGE COLUMN c1 C7 int AFTER C3; +ALTER TABLE test_single_change_column1 + MODIFY COLUMN C4 varchar(60); +ALTER TABLE test_single_change_column1 + ADD COLUMN C5 varchar(60) AFTER C2; +ALTER TABLE test_single_change_column1 + RENAME INDEX i_C1c2 TO i_c1c5; +/*+TDDL:CMD_EXTRA(CHECK_LOGICAL_COLUMN_ORDER=true)*/CHECK TABLE test_single_change_column1; +Table,Op,Msg_type,Msg_text +d_single_part_ddl.test_single_change_column1:Topology,check,status,OK +d_single_part_ddl.test_single_change_column1:Columns,check,status,OK +test_single_change_column1.i_c1c5:Local Index,check,status,OK \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_single_case_inconsist_change_column.test.yml b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_single_case_inconsist_change_column.test.yml new file mode 100644 index 000000000..f9356ddf6 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/test_single_case_inconsist_change_column.test.yml @@ -0,0 +1,21 @@ +DROP DATABASE IF EXISTS d_single_part_ddl; +CREATE DATABASE d_single_part_ddl MODE 'auto'; +USE d_single_part_ddl; +DROP TABLE IF EXISTS test_single_change_column1; +CREATE TABLE test_single_change_column1 ( + c1 int, + c2 double, + c3 varchar(10), + c4 varchar(40) +); +ALTER TABLE test_single_change_column1 + ADD LOCAL INDEX i_c1c2 (c1, C2); +ALTER TABLE test_single_change_column1 + CHANGE COLUMN c1 C7 int AFTER C3; +ALTER TABLE test_single_change_column1 + MODIFY COLUMN C4 varchar(60); +ALTER TABLE test_single_change_column1 + ADD COLUMN C5 varchar(60) after C2; +ALTER TABLE test_single_change_column1 + RENAME INDEX i_C1c2 to i_c1c5; +/*+TDDL:CMD_EXTRA(CHECK_LOGICAL_COLUMN_ORDER=true)*/CHECK TABLE test_single_change_column1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/testcase.config.yml index eea624296..a55cf426a 100644 --- a/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/testcase.config.yml +++ b/polardbx-test/src/test/resources/partition/env/MultiPartDdlTest/testcase.config.yml @@ -1,4 +1,6 @@ test_multi_change_column test_multi_change_column_default test_multi_change_column_rename_index -test_many_random_multi_ddl +test_multi_case_inconsist_change_column +test_multi_case_inconsist_change_column_rename_index +test_single_case_inconsist_change_column diff --git a/polardbx-test/src/test/resources/partition/env/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.result b/polardbx-test/src/test/resources/partition/env/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.result new file mode 100644 index 000000000..3c733d9b8 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.result @@ -0,0 +1,51 @@ +## DISABLE_FAST_SQL_PARSER +CREATE TABLE `my_bro_t1` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB AUTO_INCREMENT = 400021 DEFAULT CHARSET = utf8mb4 +BROADCAST; +CREATE TABLE `my_hash_t1` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 8; +CREATE TABLE `my_hash_t2` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 8; +explain insert into my_hash_t2 select t1.a, t1.b from my_hash_t1 t1 join my_bro_t1 t2 on t1.b=t2.b; +Logical ExecutionPlan +LogicalInsert(table="my_hash_t2", columns=RecordType(BIGINT_UNSIGNED a, BIGINT_UNSIGNED b), mode=MULTI) + Gather(concurrent=true) + LogicalView(tables="my_hash_t1[p1,p2,p3,p4,p5,p6,p7,p8],my_bro_t1", shardCount=8, sql="SELECT `my_hash_t1`.`a`, `my_hash_t1`.`b` FROM `my_hash_t1` AS `my_hash_t1` INNER JOIN `my_bro_t1` AS `my_bro_t1` ON (`my_hash_t1`.`b` = `my_bro_t1`.`b`)") +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b; +Logical ExecutionPlan +Gather(concurrent=true) + LogicalView(tables="my_hash_t1[p1,p2,p3,p4,p5,p6,p7,p8],my_bro_t1", shardCount=8, sql="SELECT `my_bro_t1`.`a` AS `a0`, `my_bro_t1`.`b` AS `b0`, `my_hash_t1`.`a`, `my_hash_t1`.`b` FROM `my_hash_t1` AS `my_hash_t1` INNER JOIN `my_bro_t1` AS `my_bro_t1` ON (`my_hash_t1`.`b` = `my_bro_t1`.`b`)") +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; +Logical ExecutionPlan +BKAJoin(condition="b = b", type="inner") + LogicalView(tables="my_bro_t1", shardCount=0, sql="SELECT `a`, `b` FROM `my_bro_t1` AS `my_bro_t1` FOR UPDATE") + Gather(concurrent=true) + LogicalView(tables="my_hash_t1[p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=8, sql="SELECT `a`, `b` FROM `my_hash_t1` AS `my_hash_t1` WHERE (`b` IN (...)) FOR UPDATE") +set autocommit=false; +select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; +a,b,a,b +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; +Logical ExecutionPlan +BKAJoin(condition="b = b", type="inner") + LogicalView(tables="my_bro_t1", shardCount=0, sql="SELECT `a`, `b` FROM `my_bro_t1` AS `my_bro_t1` FOR UPDATE") + Gather(concurrent=true) + LogicalView(tables="my_hash_t1[p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=8, sql="SELECT `a`, `b` FROM `my_hash_t1` AS `my_hash_t1` WHERE (`b` IN (...)) FOR UPDATE") +explain insert into my_hash_t2 select t1.a, t1.b from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b; +Logical ExecutionPlan +LogicalInsert(table="my_hash_t2", columns=RecordType(BIGINT_UNSIGNED a, BIGINT_UNSIGNED b), mode=MULTI) + Project(a="a", b="b") + BKAJoin(condition="b = b", type="inner") + LogicalView(tables="my_bro_t1", shardCount=0, sql="SELECT `a`, `b` FROM `my_bro_t1` AS `my_bro_t1`") + Gather(concurrent=true) + LogicalView(tables="my_hash_t1[p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=8, sql="SELECT `b` FROM `my_hash_t1` AS `my_hash_t1` WHERE (`b` IN (...))") +rollback; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.test.yml new file mode 100644 index 000000000..5bdd908ee --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.test.yml @@ -0,0 +1,32 @@ +## DISABLE_FAST_SQL_PARSER + +CREATE TABLE `my_bro_t1` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB AUTO_INCREMENT = 400021 DEFAULT CHARSET = utf8mb4 +BROADCAST; + +CREATE TABLE `my_hash_t1` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 8; + +CREATE TABLE `my_hash_t2` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 8; + +explain insert into my_hash_t2 select t1.a, t1.b from my_hash_t1 t1 join my_bro_t1 t2 on t1.b=t2.b; +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b; +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; + +set autocommit=false; +select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; +explain insert into my_hash_t2 select t1.a, t1.b from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b; +rollback; + diff --git a/polardbx-test/src/test/resources/partition/env/PartitionIntraGroupParallel2Test/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/PartitionIntraGroupParallel2Test/testcase.config.yml new file mode 100644 index 000000000..971b3427f --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionIntraGroupParallel2Test/testcase.config.yml @@ -0,0 +1 @@ +test_dml_bro_join_pushdown \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_create_db2.result b/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_create_db2.result index b1699679a..6c2585811 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_create_db2.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_create_db2.result @@ -1,5 +1,6 @@ ## DISABLE_FAST_SQL_PARSER -## test show createdb without extras of default_single -show create database drds_polarx2_part_qatest_app; -Database,Create Database -drds_polarx2_part_qatest_app,CREATE DATABASE `drds_polarx2_part_qatest_app` CHARSET = `utf8mb4` MODE = 'auto' \ No newline at end of file +create database mynew_db1 mode='auto' +use mynew_db1 +create table mynew_t1(a int ,b int) partition by key(a) partitions 16 +use polardbx +drop database mynew_db1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_create_db2.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_create_db2.test.yml index 97dd1cefc..62202b934 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_create_db2.test.yml +++ b/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_create_db2.test.yml @@ -1,4 +1,8 @@ ## DISABLE_FAST_SQL_PARSER -## test show createdb without extras of default_single -show create database drds_polarx2_part_qatest_app; + +create database mynew_db1 mode='auto'; +use mynew_db1; +create table mynew_t1(a int ,b int) partition by key(a) partitions 16; +use polardbx; +drop database mynew_db1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_desc_partitions.result b/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_desc_partitions.result index 01d31aa2f..7e50ebcff 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_desc_partitions.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionModeTest/test_desc_partitions.result @@ -75,6 +75,7 @@ PART_EXPR,varchar,YES,,NULL, PART_NAME,varchar,YES,,NULL, PART_POSI,bigint,YES,,NULL, PART_DESC,varchar,YES,,NULL, +PART_ARC_STATE,varchar,YES,,NULL, SUBPART_METHOD,varchar,YES,,NULL, SUBPART_COL,varchar,YES,,NULL, SUBPART_COL_TYPE,varchar,YES,,NULL, @@ -83,6 +84,7 @@ SUBPART_NAME,varchar,YES,,NULL, SUBPART_TEMP_NAME,varchar,YES,,NULL, SUBPART_POSI,bigint,YES,,NULL, SUBPART_DESC,varchar,YES,,NULL, +SUBPART_ARC_STATE,varchar,YES,,NULL, PG_NAME,varchar,YES,,NULL, PHY_GROUP,varchar,YES,,NULL, PHY_DB,varchar,YES,,NULL, @@ -104,6 +106,7 @@ PART_EXPR,varchar,YES,,NULL, PART_NAME,varchar,YES,,NULL, PART_POSI,bigint,YES,,NULL, PART_DESC,varchar,YES,,NULL, +PART_ARC_STATE,varchar,YES,,NULL, SUBPART_METHOD,varchar,YES,,NULL, SUBPART_COL,varchar,YES,,NULL, SUBPART_COL_TYPE,varchar,YES,,NULL, @@ -112,6 +115,7 @@ SUBPART_NAME,varchar,YES,,NULL, SUBPART_TEMP_NAME,varchar,YES,,NULL, SUBPART_POSI,bigint,YES,,NULL, SUBPART_DESC,varchar,YES,,NULL, +SUBPART_ARC_STATE,varchar,YES,,NULL, PG_NAME,varchar,YES,,NULL, PHY_GROUP,varchar,YES,,NULL, PHY_DB,varchar,YES,,NULL, diff --git a/polardbx-test/src/test/resources/partition/env/PartitionModeTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/PartitionModeTest/testcase.config.yml index d5909e564..354cbebec 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionModeTest/testcase.config.yml +++ b/polardbx-test/src/test/resources/partition/env/PartitionModeTest/testcase.config.yml @@ -1,7 +1,7 @@ test_create_db -#test_create_db2 +test_create_db2 test_create_auto test_part_mode #test_desc_partitions test_part_show_rule -test_createdb_charset \ No newline at end of file +test_createdb_charset diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableBkaJoinTest/empty_split.result b/polardbx-test/src/test/resources/partition/env/PartitionTableBkaJoinTest/empty_split.result new file mode 100644 index 000000000..fb6023594 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableBkaJoinTest/empty_split.result @@ -0,0 +1,21 @@ +## DISABLE_FAST_SQL_PARSER +CREATE PARTITION TABLE `t1` ( +`c1` int(11) NOT NULL, +`c2` int(11) DEFAULT NULL, +PRIMARY KEY (`c1`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`c1`); +CREATE TABLE `t2` ( +`c1` int(11) DEFAULT NULL, +`c2` int(11) DEFAULT NULL, +`_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, +PRIMARY KEY (`_drds_implicit_id_`), +LOCAL KEY `auto_shard_key_c2` USING BTREE (`c2`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(`c2`) +(PARTITION p0 VALUES LESS THAN (100) ENGINE = InnoDB, +PARTITION p1 VALUES LESS THAN (200) ENGINE = InnoDB); +/*+TDDL: bka_join(t1,t2) enable_master_mpp=false parallelism=4 workload_type=ap*/ select count(*) from t1 join t2 on t1.c1 = t2.c1 where t2.c2 = 233 group by t1.c1; +count(*) +/*+TDDL: bka_join(t1,t2) enable_master_mpp=true parallelism=4 workload_type=ap*/ select count(*) from t1 join t2 on t1.c1 = t2.c1 where t2.c2 = 233 group by t1.c1; +count(*) \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableBkaJoinTest/empty_split.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableBkaJoinTest/empty_split.test.yml new file mode 100644 index 000000000..6c127cd33 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableBkaJoinTest/empty_split.test.yml @@ -0,0 +1,20 @@ +## DISABLE_FAST_SQL_PARSER + +CREATE PARTITION TABLE `t1` ( +`c1` int(11) NOT NULL, +`c2` int(11) DEFAULT NULL, +PRIMARY KEY (`c1`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`c1`); +CREATE TABLE `t2` ( +`c1` int(11) DEFAULT NULL, +`c2` int(11) DEFAULT NULL, +`_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, +PRIMARY KEY (`_drds_implicit_id_`), +LOCAL KEY `auto_shard_key_c2` USING BTREE (`c2`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(`c2`) +(PARTITION `p0` VALUES LESS THAN (100) ENGINE = InnoDB, +PARTITION `p1` VALUES LESS THAN (200) ENGINE = InnoDB); +/*+TDDL: bka_join(t1,t2) enable_master_mpp=false parallelism=4 workload_type=ap*/ select count(*) from t1 join t2 on t1.c1 = t2.c1 where t2.c2 = 233 group by t1.c1; +/*+TDDL: bka_join(t1,t2) enable_master_mpp=true parallelism=4 workload_type=ap*/ select count(*) from t1 join t2 on t1.c1 = t2.c1 where t2.c2 = 233 group by t1.c1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableBkaJoinTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableBkaJoinTest/testcase.config.yml new file mode 100644 index 000000000..a882deb30 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableBkaJoinTest/testcase.config.yml @@ -0,0 +1 @@ +empty_split \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_alter_repartition_with_ugsi.result b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_alter_repartition_with_ugsi.result index 57e909aa5..9c44e5de4 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_alter_repartition_with_ugsi.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_alter_repartition_with_ugsi.result @@ -27,10 +27,9 @@ PARTITIONS 3 SHOW CREATE TABLE g1; Table,Create Table g1_$,CREATE TABLE `g1_$` ( - `id` varchar(20) DEFAULT NULL, + `id` varchar(20) NOT NULL, `name` varchar(20) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_id` USING BTREE (`id`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS 3 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_compressed_table.result b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_compressed_table.result index a52964e22..deaac12eb 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_compressed_table.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_compressed_table.result @@ -49,8 +49,8 @@ Table,Create Table gu_compressed_c_$,CREATE TABLE `gu_compressed_c_$` ( `a` int(11) NOT NULL, `c` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`), - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`), + UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8 PARTITION BY KEY(`c`) PARTITIONS 3 @@ -88,8 +88,8 @@ Table,Create Table gu_compressed_c_$,CREATE TABLE `gu_compressed_c_$` ( `a` int(11) NOT NULL, `c` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) KEY_BLOCK_SIZE = 8, - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`) KEY_BLOCK_SIZE = 8, + UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) KEY_BLOCK_SIZE = 8 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 16 PARTITION BY KEY(`c`) PARTITIONS 3 @@ -99,7 +99,7 @@ g_compressed_b_$,CREATE TABLE `g_compressed_b_$` ( `a` int(11) NOT NULL, `b` int(11) NOT NULL, PRIMARY KEY (`a`) KEY_BLOCK_SIZE = 8, - KEY `i_a_b` USING BTREE (`a`, `b`) + KEY `i_a_b` USING BTREE (`a`, `b`) KEY_BLOCK_SIZE = 8 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 16 PARTITION BY KEY(`a`,`b`) PARTITIONS 3 @@ -139,8 +139,8 @@ gu_compressed_c_$,CREATE TABLE `gu_compressed_c_$` ( `a` int(11) NOT NULL, `c` int(11) NOT NULL, `b` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) KEY_BLOCK_SIZE = 8, - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`) KEY_BLOCK_SIZE = 8, + UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) KEY_BLOCK_SIZE = 8 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 16 PARTITION BY KEY(`c`) PARTITIONS 3 @@ -150,7 +150,7 @@ g_compressed_b_$,CREATE TABLE `g_compressed_b_$` ( `a` int(11) NOT NULL, `b` int(11) NOT NULL, PRIMARY KEY (`a`) KEY_BLOCK_SIZE = 8, - KEY `i_a_b` USING BTREE (`a`, `b`) + KEY `i_a_b` USING BTREE (`a`, `b`) KEY_BLOCK_SIZE = 8 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 16 PARTITION BY KEY(`a`,`b`) PARTITIONS 3 @@ -180,7 +180,7 @@ t1,CREATE TABLE `t1` ( GLOBAL INDEX `g_compressed_b` (`a`, `b`) PARTITION BY KEY(`a`,`b`) PARTITIONS 3, - KEY `auto_shard_key_b` USING BTREE (`b`) + KEY `auto_shard_key_b` USING BTREE (`b`) KEY_BLOCK_SIZE = 16 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8 PARTITION BY KEY(`b`) PARTITIONS 3 @@ -190,8 +190,8 @@ gu_compressed_c_$,CREATE TABLE `gu_compressed_c_$` ( `a` int(11) NOT NULL, `c` int(11) NOT NULL, `b` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`), - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`), + UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8 PARTITION BY KEY(`c`) PARTITIONS 3 @@ -239,11 +239,11 @@ PARTITIONS 3 SHOW CREATE TABLE gu_compressed_c; Table,Create Table gu_compressed_c_$,CREATE TABLE `gu_compressed_c_$` ( - `a` bigint(20) DEFAULT NULL, + `a` bigint(20) NOT NULL, `b` int(11) NOT NULL, `c` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`), - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`), + UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8 PARTITION BY KEY(`c`) PARTITIONS 3 @@ -290,11 +290,11 @@ PARTITIONS 2 SHOW CREATE TABLE gu_compressed_c; Table,Create Table gu_compressed_c_$,CREATE TABLE `gu_compressed_c_$` ( - `a` bigint(20) DEFAULT NULL, + `a` bigint(20) NOT NULL, `b` int(11) NOT NULL, `c` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`), - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`), + UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8 PARTITION BY KEY(`c`) PARTITIONS 3 @@ -334,18 +334,18 @@ t1,CREATE TABLE `t1` ( GLOBAL INDEX `g_compressed_b` (`a`, `b`) PARTITION BY KEY(`a`,`b`) PARTITIONS 3, - KEY `auto_shard_key_b` USING BTREE (`b`) + KEY `auto_shard_key_b` USING BTREE (`b`) KEY_BLOCK_SIZE = 8 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED PARTITION BY KEY(`b`) PARTITIONS 2 SHOW CREATE TABLE gu_compressed_c; Table,Create Table gu_compressed_c_$,CREATE TABLE `gu_compressed_c_$` ( - `a` bigint(20) DEFAULT NULL, + `a` bigint(20) NOT NULL, `b` int(11) NOT NULL, `c` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) KEY_BLOCK_SIZE = 8, - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`) KEY_BLOCK_SIZE = 8, + UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) KEY_BLOCK_SIZE = 8 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED PARTITION BY KEY(`c`) PARTITIONS 3 @@ -355,7 +355,7 @@ g_compressed_b_$,CREATE TABLE `g_compressed_b_$` ( `a` bigint(20) NOT NULL, `b` int(11) NOT NULL, PRIMARY KEY (`a`) KEY_BLOCK_SIZE = 8, - KEY `i_a_b` USING BTREE (`a`, `b`) + KEY `i_a_b` USING BTREE (`a`, `b`) KEY_BLOCK_SIZE = 8 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED PARTITION BY KEY(`a`,`b`) PARTITIONS 3 @@ -385,18 +385,18 @@ t1,CREATE TABLE `t1` ( GLOBAL INDEX `g_compressed_b` (`a`, `b`) PARTITION BY KEY(`a`,`b`) PARTITIONS 3, - KEY `auto_shard_key_b` USING BTREE (`b`) + KEY `auto_shard_key_b` USING BTREE (`b`) KEY_BLOCK_SIZE = 8 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC PARTITION BY KEY(`b`) PARTITIONS 2 SHOW CREATE TABLE gu_compressed_c; Table,Create Table gu_compressed_c_$,CREATE TABLE `gu_compressed_c_$` ( - `a` bigint(20) DEFAULT NULL, + `a` bigint(20) NOT NULL, `b` int(11) NOT NULL, `c` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) KEY_BLOCK_SIZE = 8, - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`) KEY_BLOCK_SIZE = 8, + UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) KEY_BLOCK_SIZE = 8 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC PARTITION BY KEY(`c`) PARTITIONS 3 @@ -406,7 +406,7 @@ g_compressed_b_$,CREATE TABLE `g_compressed_b_$` ( `a` bigint(20) NOT NULL, `b` int(11) NOT NULL, PRIMARY KEY (`a`) KEY_BLOCK_SIZE = 8, - KEY `i_a_b` USING BTREE (`a`, `b`) + KEY `i_a_b` USING BTREE (`a`, `b`) KEY_BLOCK_SIZE = 8 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC PARTITION BY KEY(`a`,`b`) PARTITIONS 3 @@ -443,11 +443,11 @@ PARTITIONS 2 SHOW CREATE TABLE gu_compressed_c; Table,Create Table gu_compressed_c_$,CREATE TABLE `gu_compressed_c_$` ( - `a` bigint(20) DEFAULT NULL, + `a` bigint(20) NOT NULL, `b` int(11) NOT NULL, `c` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`), - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`), + UNIQUE KEY `auto_shard_key_c` USING BTREE (`c`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8 PARTITION BY KEY(`c`) PARTITIONS 3 diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_drop_add_primary_key.result b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_drop_add_primary_key.result index 3afb2280e..5e5f3c5fa 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_drop_add_primary_key.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_drop_add_primary_key.result @@ -106,8 +106,8 @@ idx_order_$,CREATE TABLE `idx_order_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, `gmt_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`, `gmt_modified`) + PRIMARY KEY (`x`, `gmt_modified`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# @@ -146,15 +146,15 @@ idx_seller2_$,CREATE TABLE `idx_seller2_$` ( LOCAL KEY `auto_shard_key_seller_id` USING BTREE (`seller_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`seller_id`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ SHOW FULL CREATE TABLE idx_order2; Table,Create Table idx_order2_$,CREATE TABLE `idx_order2_$` ( `order_id` varchar(20) DEFAULT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# @@ -194,8 +194,8 @@ Table,Create Table idx_order2_$,CREATE TABLE `idx_order2_$` ( `order_id` varchar(20) NOT NULL, `seller_id` varchar(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`order_id`, `seller_id`) + PRIMARY KEY (`order_id`, `seller_id`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_fulltext_with_parser.result b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_fulltext_with_parser.result new file mode 100644 index 000000000..0f9246bfa --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_fulltext_with_parser.result @@ -0,0 +1,125 @@ +DROP TABLE IF EXISTS tb1 +CREATE TABLE tb1 ( + a int PRIMARY KEY, + b text, + c text, + d text, + e text, + FULLTEXT KEY `test_idx1` (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, + FULLTEXT INDEX `test_idx2`(`b`) COMMENT '234' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx3` (`d`) WITH PARSER ngram, + FULLTEXT INDEX `test_idx4`(`e`) WITH PARSER ngram +) +PARTITION BY KEY (a) +SHOW CREATE TABLE tb1 +Table,Create Table +tb1,CREATE TABLE `tb1` ( + `a` int(11) NOT NULL, + `b` text, + `c` text, + `d` text, + `e` text, + PRIMARY KEY (`a`), + FULLTEXT KEY `test_idx1` (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx2` (`b`) COMMENT '234' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx3` (`d`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx4` (`e`) /*!50100 WITH PARSER `ngram` */ +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 3 +ALTER TABLE tb1 + ADD FULLTEXT KEY `test_idx5` (`c`) COMMENT '456' /*!50100 WITH PARSER `ngram` */ +ALTER TABLE tb1 + ADD FULLTEXT INDEX `test_idx6` (`c`) COMMENT '789' /*!50100 WITH PARSER `ngram` */ +SHOW CREATE TABLE tb1 +Table,Create Table +tb1,CREATE TABLE `tb1` ( + `a` int(11) NOT NULL, + `b` text, + `c` text, + `d` text, + `e` text, + PRIMARY KEY (`a`), + FULLTEXT KEY `test_idx1` (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx2` (`b`) COMMENT '234' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx3` (`d`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx4` (`e`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx5` (`c`) COMMENT '456' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx6` (`c`) COMMENT '789' /*!50100 WITH PARSER `ngram` */ +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 3 +CREATE FULLTEXT INDEX `test_idx7` ON tb1 (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */ +CREATE FULLTEXT INDEX `test_idx8` ON tb1 (`c`) COMMENT '123' /*!50100 WITH PARSER `ngram` */ +SHOW CREATE TABLE tb1 +Table,Create Table +tb1,CREATE TABLE `tb1` ( + `a` int(11) NOT NULL, + `b` text, + `c` text, + `d` text, + `e` text, + PRIMARY KEY (`a`), + FULLTEXT KEY `test_idx1` (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx2` (`b`) COMMENT '234' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx3` (`d`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx4` (`e`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx5` (`c`) COMMENT '456' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx6` (`c`) COMMENT '789' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx7` (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx8` (`c`) COMMENT '123' /*!50100 WITH PARSER `ngram` */ +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 3 +ALTER TABLE tb1 + ADD FULLTEXT KEY `test_idx9` (`c`) WITH PARSER ngram +ALTER TABLE tb1 + ADD FULLTEXT INDEX `test_idx10` (`c`) WITH PARSER ngram +SHOW CREATE TABLE tb1 +Table,Create Table +tb1,CREATE TABLE `tb1` ( + `a` int(11) NOT NULL, + `b` text, + `c` text, + `d` text, + `e` text, + PRIMARY KEY (`a`), + FULLTEXT KEY `test_idx1` (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx2` (`b`) COMMENT '234' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx3` (`d`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx4` (`e`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx5` (`c`) COMMENT '456' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx6` (`c`) COMMENT '789' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx7` (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx8` (`c`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx9` (`c`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx10` (`c`) /*!50100 WITH PARSER `ngram` */ +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 3 +CREATE FULLTEXT INDEX `test_idx11` ON tb1 (`b`) WITH PARSER ngram +CREATE FULLTEXT INDEX `test_idx12` ON tb1 (`c`) WITH PARSER ngram +SHOW CREATE TABLE tb1 +Table,Create Table +tb1,CREATE TABLE `tb1` ( + `a` int(11) NOT NULL, + `b` text, + `c` text, + `d` text, + `e` text, + PRIMARY KEY (`a`), + FULLTEXT KEY `test_idx1` (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx2` (`b`) COMMENT '234' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx3` (`d`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx4` (`e`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx5` (`c`) COMMENT '456' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx6` (`c`) COMMENT '789' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx7` (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx8` (`c`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx9` (`c`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx10` (`c`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx11` (`b`) /*!50100 WITH PARSER `ngram` */, + FULLTEXT KEY `test_idx12` (`c`) /*!50100 WITH PARSER `ngram` */ +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 3 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_fulltext_with_parser.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_fulltext_with_parser.test.yml new file mode 100644 index 000000000..6a240a858 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_fulltext_with_parser.test.yml @@ -0,0 +1,40 @@ +drop table if exists tb1; + +create table tb1 ( +a int primary key, +b text, +c text, +d text, +e text, +FULLTEXT KEY `test_idx1` (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */, +FULLTEXT INDEX `test_idx2` (`b`) COMMENT '234' /*!50100 WITH PARSER `ngram` */, +FULLTEXT KEY `test_idx3` (`d`) WITH PARSER ngram, +FULLTEXT INDEX `test_idx4` (`e`) WITH PARSER ngram +) +partition by key(a); + +show create table tb1; + +alter table tb1 add fulltext key `test_idx5` (`c`) COMMENT '456' /*!50100 WITH PARSER `ngram` */; + +alter table tb1 add fulltext index `test_idx6` (`c`) COMMENT '789' /*!50100 WITH PARSER `ngram` */; + +show create table tb1; + +create fulltext index `test_idx7` on tb1 (`b`) COMMENT '123' /*!50100 WITH PARSER `ngram` */; + +create fulltext index `test_idx8` on tb1 (`c`) COMMENT '123' /*!50100 WITH PARSER `ngram` */; + +show create table tb1; + +alter table tb1 add fulltext key `test_idx9` (`c`) WITH PARSER ngram; + +alter table tb1 add fulltext index `test_idx10` (`c`) WITH PARSER ngram; + +show create table tb1; + +create fulltext index `test_idx11` on tb1 (`b`) WITH PARSER ngram; + +create fulltext index `test_idx12` on tb1 (`c`) WITH PARSER ngram; + +show create table tb1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_identifier_with_special_character.result b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_identifier_with_special_character.result new file mode 100644 index 000000000..de71d6367 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_identifier_with_special_character.result @@ -0,0 +1,136 @@ +DROP TABLE IF EXISTS `t``1`; +CREATE TABLE `t``1` ( + `a``a` int(11) NOT NULL, + `b``b` int(11) DEFAULT NULL, + PRIMARY KEY (`a``a`) +); +ALTER TABLE `t``1` + ADD CLUSTERED INDEX cgsi (`a``a`); +SHOW CREATE TABLE `t``1`; +Table,Create Table +t`1,CREATE TABLE `t``1` ( + `a``a` int(11) NOT NULL, + `b``b` int(11) DEFAULT NULL, + PRIMARY KEY (`a``a`), + CLUSTERED INDEX `cgsi` (`a``a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +SHOW FULL CREATE TABLE `t``1`; +Table,Create Table +t`1,CREATE PARTITION TABLE `t``1` ( + `a``a` int(11) NOT NULL, + `b``b` int(11) DEFAULT NULL, + PRIMARY KEY (`a``a`), + CLUSTERED INDEX /* cgsi_$ */ `cgsi` (`a``a`) + PARTITION BY KEY(`a``a`) + PARTITIONS 3, + LOCAL KEY `_local_cgsi` (`a``a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a``a`) +PARTITIONS 3 +/* tablegroup = `tg` */ +ALTER TABLE `t``1` + RENAME INDEX cgsi TO `c``gsi`; +SHOW CREATE TABLE `t``1`; +Table,Create Table +t`1,CREATE TABLE `t``1` ( + `a``a` int(11) NOT NULL, + `b``b` int(11) DEFAULT NULL, + PRIMARY KEY (`a``a`), + CLUSTERED INDEX `c``gsi` (`a``a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +SHOW FULL CREATE TABLE `t``1`; +Table,Create Table +t`1,CREATE PARTITION TABLE `t``1` ( + `a``a` int(11) NOT NULL, + `b``b` int(11) DEFAULT NULL, + PRIMARY KEY (`a``a`), + CLUSTERED INDEX /* c`gsi_$ */ `c``gsi` (`a``a`) + PARTITION BY KEY(`a``a`) + PARTITIONS 3, + LOCAL KEY `_local_c``gsi` (`a``a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a``a`) +PARTITIONS 3 +/* tablegroup = `tg` */ +ALTER TABLE `t``1` + ADD INDEX idxa (`a``a`); +ALTER TABLE `t``1` + ADD COLUMN `c``c` int; +INSERT INTO `t``1` +VALUES (1, 2, 3), + (4, 5, 6), + (7, 8, 9); +ALTER TABLE `t``1` +PARTITION BY KEY (`c``c`); +SHOW CREATE TABLE `t``1`; +Table,Create Table +t`1,CREATE TABLE `t``1` ( + `a``a` int(11) NOT NULL, + `b``b` int(11) DEFAULT NULL, + `c``c` int(11) DEFAULT NULL, + PRIMARY KEY (`a``a`), + KEY `c``gsi` USING BTREE (`a``a`), + KEY `idxa` USING BTREE (`a``a`), + KEY `auto_shard_key_c``c` USING BTREE (`c``c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`c``c`) +PARTITIONS 3 +SHOW FULL CREATE TABLE `t``1`; +Table,Create Table +t`1,CREATE TABLE `t``1` ( + `a``a` int(11) NOT NULL, + `b``b` int(11) DEFAULT NULL, + `c``c` int(11) DEFAULT NULL, + PRIMARY KEY (`a``a`), + LOCAL KEY `c``gsi` USING BTREE (`a``a`), + LOCAL KEY `idxa` USING BTREE (`a``a`), + LOCAL KEY `auto_shard_key_c``c` USING BTREE (`c``c`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`c``c`) +PARTITIONS 3 +/* tablegroup = `tg` */ +SELECT * +FROM `t``1` +ORDER BY `a``a`; +a`a,b`b,c`c +1,2,3 +4,5,6 +7,8,9 +ALTER TABLE `t``1` + REMOVE PARTITIONING; +SHOW CREATE TABLE `t``1`; +Table,Create Table +t`1,CREATE TABLE `t``1` ( + `a``a` int(11) NOT NULL, + `b``b` int(11) DEFAULT NULL, + `c``c` int(11) DEFAULT NULL, + PRIMARY KEY (`a``a`), + INDEX `c``gsi` (`a``a`), + INDEX `idxa` (`a``a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +SHOW FULL CREATE TABLE `t``1`; +Table,Create Table +t`1,CREATE PARTITION TABLE `t``1` ( + `a``a` int(11) NOT NULL, + `b``b` int(11) DEFAULT NULL, + `c``c` int(11) DEFAULT NULL, + PRIMARY KEY (`a``a`), + GLOBAL INDEX /* c`gsi_$ */ `c``gsi` (`a``a`) + PARTITION BY KEY(`a``a`) + PARTITIONS 3, + GLOBAL INDEX /* idxa_$ */ `idxa` (`a``a`) + PARTITION BY KEY(`a``a`) + PARTITIONS 3, + LOCAL KEY `_local_c``gsi` USING BTREE (`a``a`), + LOCAL KEY `_local_idxa` USING BTREE (`a``a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a``a`) +PARTITIONS 3 +/* tablegroup = `tg` */ +SELECT * +FROM `t``1` +ORDER BY `a``a`; +a`a,b`b,c`c +1,2,3 +4,5,6 +7,8,9 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_identifier_with_special_character.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_identifier_with_special_character.test.yml new file mode 100644 index 000000000..5f865b817 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/test_identifier_with_special_character.test.yml @@ -0,0 +1,41 @@ +drop table if exists `t``1`; + +CREATE TABLE `t``1` ( +`a``a` int(11) NOT NULL, +`b``b` int(11) DEFAULT NULL, +PRIMARY KEY (`a``a`) +); + +alter table `t``1` add clustered index cgsi(`a``a`); + +show create table `t``1`; + +show full create table `t``1`; + +alter table `t``1` rename index cgsi to `c``gsi`; + +show create table `t``1`; + +show full create table `t``1`; + +alter table `t``1` add index idxa(`a``a`); + +alter table `t``1` add column `c``c` int; + +insert into `t``1` values(1,2,3),(4,5,6),(7,8,9); + +alter table `t``1` partition by key(`c``c`); + +show create table `t``1`; + +show full create table `t``1`; + +select * from `t``1` order by `a``a`; + +alter table `t``1` remove partitioning; + +show create table `t``1`; + +show full create table `t``1`; + +select * from `t``1` order by `a``a`; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/testcase.config.yml index a247050cb..2a375c068 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/testcase.config.yml +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableDdlTest/testcase.config.yml @@ -33,4 +33,6 @@ test_modify_column test_online_modify_column test_online_modify_column_gsi test_compressed_table -test_create_table_with_blank \ No newline at end of file +test_create_table_with_blank +test_identifier_with_special_character +test_fulltext_with_parser diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal.result index 6c75d44fa..a6d121179 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal.result @@ -185,24 +185,16 @@ explain select * from rng_decimal_2400 where c1 between '16777215' and '42949672 Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rng_decimal_2400[p7,p8,p9]", shardCount=3, sql="SELECT `c1` FROM `rng_decimal_2400` AS `rng_decimal_2400` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: cdf3b018 ## p10,pm explain select * from rng_decimal_2400 where c1 between '123456789012345678809999' and '123456789012345679909999'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rng_decimal_2400[p10,pm]", shardCount=2, sql="SELECT `c1` FROM `rng_decimal_2400` AS `rng_decimal_2400` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: cdf3b018 ## pm explain select * from rng_decimal_2400 where c1 between '123456789012345678909999' and '123456789012345678919999'; Logical ExecutionPlan -PhyTableOperation(tables="rng_decimal_2400[pm]", sql="SELECT `rng_decimal_2400`.`c1` FROM ? AS `rng_decimal_2400` WHERE (`rng_decimal_2400`.`c1` BETWEEN ? AND ?)", params="123456789012345678919999,123456789012345678909999") -HitCache:true -Source:PLAN_CACHE -TemplateId: cdf3b018 +Gather(concurrent=true) + LogicalView(tables="rng_decimal_2400[pm]", sql="SELECT `c1` FROM `rng_decimal_2400` AS `rng_decimal_2400` WHERE (`c1` BETWEEN ? AND ?)") ####------- case 7 test rng route with biggest int------ drop table if exists rng_decimal_6500; set sql_mode=''; @@ -231,7 +223,8 @@ Logical ExecutionPlan PhyTableOperation(tables="rng_decimal_6500[pmax]", sql="SELECT `rng_decimal_6500`.`c1` FROM ? AS `rng_decimal_6500` WHERE (`rng_decimal_6500`.`c1` = ?)", params="99999999999999999999999999999999999999999999999999999999999999999") explain select * from rng_decimal_6500 where c1>'99999999999999999999999999999999999999999999999999999999999999999'; Logical ExecutionPlan -PhyTableOperation(tables="rng_decimal_6500[pmax]", sql="SELECT `rng_decimal_6500`.`c1` FROM ? AS `rng_decimal_6500` WHERE (`rng_decimal_6500`.`c1` > ?)", params="99999999999999999999999999999999999999999999999999999999999999999") +Gather(concurrent=true) + LogicalView(tables="rng_decimal_6500[pmax]", sql="SELECT `c1` FROM `rng_decimal_6500` AS `rng_decimal_6500` WHERE (`c1` > ?)") select part_route('','key_decimal_6500',-1234567890123456789012340); part_route('', 'key_decimal_6500', -1234567890123456789012340) p1 @@ -258,29 +251,18 @@ explain select * from list_decimal_2400 where c1 between '16777215' and '4294967 Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="list_decimal_2400[p2,p3,pm]", shardCount=3, sql="SELECT `c1` FROM `list_decimal_2400` AS `list_decimal_2400` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 5747dcef ## p10,pm explain select * from list_decimal_2400 where c1 between '123456789012345678809999' and '123456789012345679909999'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="list_decimal_2400[p5,pm]", shardCount=2, sql="SELECT `c1` FROM `list_decimal_2400` AS `list_decimal_2400` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 5747dcef ## zero explain select * from list_decimal_2400 where c1 >= '123456789012345688909999' and c1 <= '123456789012345678919999'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="list_decimal_2400[]", shardCount=0, sql="SELECT `c1` FROM `list_decimal_2400` AS `list_decimal_2400` WHERE ((`c1` >= ?) AND (`c1` <= ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: 3070605e ## pm explain select * from list_decimal_2400 where c1 <= '123456789012345688909999' and c1 >= '123456789012345678919999'; Logical ExecutionPlan -PhyTableOperation(tables="list_decimal_2400[pm]", sql="SELECT `list_decimal_2400`.`c1` FROM ? AS `list_decimal_2400` WHERE ((`list_decimal_2400`.`c1` <= ?) AND (`list_decimal_2400`.`c1` >= ?))", params="123456789012345678919999,123456789012345688909999") -HitCache:false -Source:PLAN_CACHE -TemplateId: 8f1d8d1a \ No newline at end of file +Gather(concurrent=true) + LogicalView(tables="list_decimal_2400[pm]", sql="SELECT `c1` FROM `list_decimal_2400` AS `list_decimal_2400` WHERE ((`c1` <= ?) AND (`c1` >= ?))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal2.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal2.result index b53c158eb..0fa480c8f 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal2.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal2.result @@ -97,16 +97,10 @@ explain select * from tb_decimal_6530 Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_6530[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `id` FROM `tb_decimal_6530` AS `tb_decimal_6530` WHERE ((`id` >= ?) AND (`id` <= ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: cc7827b4 ## should scan no partitions explain select * from tb_decimal_6530 where id <= '12345678901234567890123456789012345.123456789012345678900123456789' and id >= '12345678901234567890123456789012345.123456789012345678900123456795'; Logical ExecutionPlan Gather(concurrent=true) - LogicalView(tables="tb_decimal_6530[]", shardCount=0, sql="SELECT `id` FROM `tb_decimal_6530` AS `tb_decimal_6530` WHERE ((`id` <= ?) AND (`id` >= ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: 2b255470 \ No newline at end of file + LogicalView(tables="tb_decimal_6530[]", shardCount=0, sql="SELECT `id` FROM `tb_decimal_6530` AS `tb_decimal_6530` WHERE ((`id` <= ?) AND (`id` >= ?))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal_endpoints.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal_endpoints.result index 657c5f7d1..e09ddc8b1 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal_endpoints.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal_endpoints.result @@ -19,9 +19,6 @@ explain select * from rc4_decimal_2400 where c1 > '123456789012345678901236.2'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p7,p8,pm]", shardCount=3, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` > ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: e14ba130 explain select * from rc4_decimal_2400 where '123456789012345678901236.2' < c1; Logical ExecutionPlan Gather(concurrent=true) @@ -31,9 +28,6 @@ explain select * from rc4_decimal_2400 where c1 > '123456789012345678901236.8'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p8,pm]", shardCount=2, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` > ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: e14ba130 explain select * from rc4_decimal_2400 where '123456789012345678901236.8' < c1; Logical ExecutionPlan Gather(concurrent=true) @@ -43,9 +37,6 @@ explain select * from rc4_decimal_2400 where c1 >= '123456789012345678901236.2'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p7,p8,pm]", shardCount=3, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` >= ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 4828ee2b explain select * from rc4_decimal_2400 where '123456789012345678901236.2' <= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -55,9 +46,6 @@ explain select * from rc4_decimal_2400 where c1 >= '123456789012345678901236.8'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p8,pm]", shardCount=2, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` >= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 4828ee2b explain select * from rc4_decimal_2400 where '123456789012345678901236.8' <= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -67,9 +55,6 @@ explain select * from rc4_decimal_2400 where c1 < '123456789012345678901236.2'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3,p4,p5,p6,p7]", shardCount=8, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` < ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: e14b99ae explain select * from rc4_decimal_2400 where '123456789012345678901236.2' > c1; Logical ExecutionPlan Gather(concurrent=true) @@ -79,9 +64,6 @@ explain select * from rc4_decimal_2400 where c1 < '123456789012345678901236.8'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=9, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` < ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: e14b99ae explain select * from rc4_decimal_2400 where '123456789012345678901236.8' > c1; Logical ExecutionPlan Gather(concurrent=true) @@ -91,9 +73,6 @@ explain select * from rc4_decimal_2400 where c1 <= '123456789012345678901236.2'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3,p4,p5,p6,p7]", shardCount=8, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` <= ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 4828056d explain select * from rc4_decimal_2400 where '123456789012345678901236.2' >= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -103,9 +82,6 @@ explain select * from rc4_decimal_2400 where c1 <= '123456789012345678901236.8'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=9, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` <= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 4828056d explain select * from rc4_decimal_2400 where '123456789012345678901236.8' >= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -116,9 +92,6 @@ explain select * from rc4_decimal_2400 where c1 < '-123456789012345678901232.2'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3]", shardCount=4, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` < ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: e14b99ae explain select * from rc4_decimal_2400 where '-123456789012345678901232.2' > c1; Logical ExecutionPlan Gather(concurrent=true) @@ -128,9 +101,6 @@ explain select * from rc4_decimal_2400 where c1 > '-123456789012345678901232.8'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=8, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` > ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: e14ba130 explain select * from rc4_decimal_2400 where '-123456789012345678901232.8' < c1; Logical ExecutionPlan Gather(concurrent=true) @@ -140,9 +110,6 @@ explain select * from rc4_decimal_2400 where c1 <= '-123456789012345678901232.2' Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3]", shardCount=4, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` <= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 4828056d explain select * from rc4_decimal_2400 where '-123456789012345678901232.2' >= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -152,9 +119,6 @@ explain select * from rc4_decimal_2400 where c1 >= '-123456789012345678901232.8' Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=8, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` >= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 4828ee2b explain select * from rc4_decimal_2400 where '-123456789012345678901232.8' <= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -178,128 +142,82 @@ explain select * from rc5_bigint where c1 > 9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p8,pm]", shardCount=2, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` > ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 0c573392 ## c1 > 9999.1 ==> c1 >= 9999: p8,pm explain select * from rc5_bigint where c1 >= 9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p8,pm]", shardCount=2, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` >= ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 7e8fa809 ## c1 > 9999.8 ==> c1 >= 10000: pm explain select * from rc5_bigint where c1 > 9999.8; Logical ExecutionPlan -PhyTableOperation(tables="rc5_bigint[pm]", sql="SELECT `rc5_bigint`.`c1` FROM ? AS `rc5_bigint` WHERE (`rc5_bigint`.`c1` > ?)", params="9999.8") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c573392 +Gather(concurrent=true) + LogicalView(tables="rc5_bigint[pm]", sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` > ?)") ## c1 > 9999.8 ==> c1 >= 10000: pm explain select * from rc5_bigint where c1 >= 9999.8; Logical ExecutionPlan -PhyTableOperation(tables="rc5_bigint[pm]", sql="SELECT `rc5_bigint`.`c1` FROM ? AS `rc5_bigint` WHERE (`rc5_bigint`.`c1` >= ?)", params="9999.8") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8fa809 +Gather(concurrent=true) + LogicalView(tables="rc5_bigint[pm]", sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` >= ?)") ## c1 < 9999.1 ==> c1 <= 9999: p0~p8 explain select * from rc5_bigint where c1 < 9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=9, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` < ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 0c572c10 ## c1 <= 9999.1 ==> c1 <= 9999: p0~p8 explain select * from rc5_bigint where c1 <= 9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=9, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` <= ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 7e8ebf4b ## c1 < 9999.8 ==> c1 <= 10000: p0~0m explain select * from rc5_bigint where c1 < 9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=10, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` < ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c572c10 ## c1 < 9999.8 ==> c1 <= 10000: p0~0m explain select * from rc5_bigint where c1 <= 9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=10, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` <= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8ebf4b ##---- negative ---- ## c1 > -9999.1 ==> c1 >= -9999: p3~pm explain select * from rc5_bigint where c1 > -9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p3,p4,p5,p6,p7,p8,pm]", shardCount=7, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` > ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c573392 ## c1 > -9999.1 ==> c1 >= 9999: p3~pm explain select * from rc5_bigint where c1 >= -9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p3,p4,p5,p6,p7,p8,pm]", shardCount=7, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` >= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8fa809 ## c1 > -9999.8 ==> c1 >= -10000: p2~pm explain select * from rc5_bigint where c1 > -9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=8, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` > ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c573392 ## c1 > -9999.8 ==> c1 >= -10000: p2~pm explain select * from rc5_bigint where c1 >= -9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=8, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` >= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8fa809 ## c1 < -9999.1 ==> c1 <= -9999: p0,p1,p2,p3 explain select * from rc5_bigint where c1 < -9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3]", shardCount=4, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` < ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c572c10 ## c1 <= 9999.1 ==> c1 <= 9999: p0,p1,p2,p3 explain select * from rc5_bigint where c1 <= -9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3]", shardCount=4, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` <= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8ebf4b ## c1 < 9999.8 ==> c1 <= 10000: p0,p1,p2 explain select * from rc5_bigint where c1 < -9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2]", shardCount=3, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` < ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c572c10 ## c1 < 9999.8 ==> c1 <= 10000: p0,p1,p2 explain select * from rc5_bigint where c1 <= -9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2]", shardCount=3, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` <= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8ebf4b create table if not exists rc3_decimal_2400 (c1 decimal(24,0) default null ) partition by range columns(c1) ( partition p0 values less than ('-999999999999999999999999'), @@ -340,7 +258,8 @@ c1 123456789012345678901234 explain select * from rc3_decimal_2400 where c1 >= '123456789012345678901233.8' and c1<='123456789012345678901234.5'; Logical ExecutionPlan -PhyTableOperation(tables="rc3_decimal_2400[p26]", sql="SELECT `rc3_decimal_2400`.`c1` FROM ? AS `rc3_decimal_2400` WHERE ((`rc3_decimal_2400`.`c1` >= ?) AND (`rc3_decimal_2400`.`c1` <= ?))", params="123456789012345678901234.5,123456789012345678901233.8") +Gather(concurrent=true) + LogicalView(tables="rc3_decimal_2400[p26]", sql="SELECT `c1` FROM `rc3_decimal_2400` AS `rc3_decimal_2400` WHERE ((`c1` >= ?) AND (`c1` <= ?))") explain select * from rc3_decimal_2400 where c1 <= '123456789012345678901233.8' and c1>='123456789012345678901234.5'; Logical ExecutionPlan Gather(concurrent=true) diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal_sp.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal_sp.result index 0b658b240..f6bf7e36d 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal_sp.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_decimal_sp.result @@ -103,9 +103,6 @@ explain select * from tb_decimal_sp_6530_6500 Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6530_6500[p1sp1,p1sp2,p1sp3,...p4spd]", shardCount=24, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6530_6500` AS `tb_decimal_sp_6530_6500` WHERE ((`id` >= ?) AND (`id` <= ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: ca3d48f0 ## empty explain select * from tb_decimal_sp_6530_6500 where id <= '12345678901234567890123456789012345.123456789012345678900123456789' @@ -113,18 +110,12 @@ and id >= '12345678901234567890123456789012345.123456789012345678900123456795'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6530_6500[]", shardCount=0, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6530_6500` AS `tb_decimal_sp_6530_6500` WHERE ((`id` <= ?) AND (`id` >= ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: 28ea75ac ## p1~p4 , sp: sp4,spd explain select * from tb_decimal_sp_6530_6500 where c1 between 9223372036854775806 and 9223372036854775808; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6530_6500[p1sp4,p1spd,p2sp4,p2spd,p3sp4,p3spd,p4sp4,p4spd]", shardCount=8, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6530_6500` AS `tb_decimal_sp_6530_6500` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 284b7f21 ## p1~p4, sp: sp4,spd explain select * from tb_decimal_sp_6530_6500 where id >= '12345678901234567890123456789012345.123456789012345678900123456789' @@ -133,9 +124,6 @@ and c1 between 9223372036854775806 and 9223372036854775808; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6530_6500[p1sp4,p1spd,p2sp4,p2spd,p3sp4,p3spd,p4sp4,p4spd]", shardCount=8, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6530_6500` AS `tb_decimal_sp_6530_6500` WHERE ((`id` >= ?) AND (`id` <= ?) AND (`c1` BETWEEN ? AND ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: 491ebac3 CREATE TABLE `tb_decimal_sp_6500_6530` ( `id` decimal(65,30) NOT NULL, `c1` decimal(65,0) NOT NULL @@ -174,9 +162,6 @@ where c1 between 9223372036854775806 and 9223372036854775808; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6500_6530[p4sp1,p4sp2,p4sp3,p4sp4,pdsp1,pdsp2,pdsp3,pdsp4]", shardCount=8, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6500_6530` AS `tb_decimal_sp_6500_6530` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 3badf1c7 ## p: p4,pd ## sp: sp1~sp4 explain select * from tb_decimal_sp_6500_6530 @@ -186,9 +171,6 @@ and c1 between 9223372036854775806 and 9223372036854775808; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6500_6530[p4sp1,p4sp2,p4sp3,p4sp4,pdsp1,pdsp2,pdsp3,pdsp4]", shardCount=8, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6500_6530` AS `tb_decimal_sp_6500_6530` WHERE ((`id` >= ?) AND (`id` <= ?) AND (`c1` BETWEEN ? AND ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: 4a0789e9 ## p:p4,pd, ## sp: sp3 explain select * from tb_decimal_sp_6500_6530 @@ -197,7 +179,4 @@ and id <= '12345678901234567890123456789012345.123456789012345678900123456789' and c1 between 9223372036854775806 and 9223372036854775808; Logical ExecutionPlan Gather(concurrent=true) - LogicalView(tables="tb_decimal_sp_6500_6530[p4sp3,pdsp3]", shardCount=2, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6500_6530` AS `tb_decimal_sp_6500_6530` WHERE ((`id` >= ?) AND (`id` <= ?) AND (`c1` BETWEEN ? AND ?))") -HitCache:true -Source:PLAN_CACHE -TemplateId: 4a0789e9 \ No newline at end of file + LogicalView(tables="tb_decimal_sp_6500_6530[p4sp3,pdsp3]", shardCount=2, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6500_6530` AS `tb_decimal_sp_6500_6530` WHERE ((`id` >= ?) AND (`id` <= ?) AND (`c1` BETWEEN ? AND ?))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_list_part_posi.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_list_part_posi.result index a43f9c509..079fcad84 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_list_part_posi.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning3Test/test_list_part_posi.result @@ -77,5 +77,6 @@ a,b,a,b 2,2,2,1 explain select * from list_t2 t2 join list_t1 t1 on t2.a=t1.a and t2.a=2 for update; Logical ExecutionPlan -PhyTableOperation(tables="list_t2[p2],list_t1[p2]", sql="SELECT `t2`.`a`, `t2`.`b`, `t1`.`a`, `t1`.`b` FROM ? AS `t2` INNER JOIN ? AS `t1` ON ((`t2`.`a` = `t1`.`a`) AND (`t2`.`a` = ?)) FOR UPDATE", params="2") +Gather(concurrent=true) + LogicalView(tables="list_t2[p2],list_t1[p2]", sql="SELECT `list_t2`.`a`, `list_t2`.`b`, `list_t1`.`a` AS `a0`, `list_t1`.`b` AS `b0` FROM `list_t2` AS `list_t2` INNER JOIN `list_t1` AS `list_t1` ON ((`list_t2`.`a` = ?) AND (`list_t1`.`a` = ?) AND (`list_t2`.`a` = `list_t1`.`a`)) FOR UPDATE") commit; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning4Test/test_sp_partfunc_month.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning4Test/test_sp_partfunc_month.result new file mode 100644 index 000000000..a185cf8b4 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning4Test/test_sp_partfunc_month.result @@ -0,0 +1,66 @@ +## DISABLE_FAST_SQL_PARSER +CREATE TABLE `sp_k_r_month` ( +`id` bigint(18) NOT NULL AUTO_INCREMENT, +`snap_time` datetime NOT NULL, +`school_id` bigint(18) DEFAULT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 1684206033 DEFAULT CHARSET = utf8 +PARTITION BY KEY(`school_id`,`id`) +PARTITIONS 2 +SUBPARTITION BY RANGE(MONTH(`snap_time`)) +(SUBPARTITION sp1 VALUES LESS THAN (2), +SUBPARTITION sp2 VALUES LESS THAN (3), +SUBPARTITION sp3 VALUES LESS THAN (4), +SUBPARTITION sp4 VALUES LESS THAN (5), +SUBPARTITION sp5 VALUES LESS THAN (6), +SUBPARTITION sp6 VALUES LESS THAN (7), +SUBPARTITION sp7 VALUES LESS THAN (8), +SUBPARTITION sp8 VALUES LESS THAN (9), +SUBPARTITION sp9 VALUES LESS THAN (10), +SUBPARTITION sp10 VALUES LESS THAN (11), +SUBPARTITION sp11 VALUES LESS THAN (12), +SUBPARTITION sp12 VALUES LESS THAN (13) +); +show create table sp_k_r_month; +Table,Create Table +sp_k_r_month,CREATE TABLE `sp_k_r_month` ( + `id` bigint(18) NOT NULL AUTO_INCREMENT, + `snap_time` datetime NOT NULL, + `school_id` bigint(18) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `auto_shard_key_school_id_id` USING BTREE (`school_id`, `id`), + KEY `auto_shard_key_snap_time` USING BTREE (`snap_time`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 +PARTITION BY KEY(`school_id`,`id`) +PARTITIONS 2 +SUBPARTITION BY RANGE(MONTH(`snap_time`)) +(SUBPARTITION sp1 VALUES LESS THAN (2), + SUBPARTITION sp2 VALUES LESS THAN (3), + SUBPARTITION sp3 VALUES LESS THAN (4), + SUBPARTITION sp4 VALUES LESS THAN (5), + SUBPARTITION sp5 VALUES LESS THAN (6), + SUBPARTITION sp6 VALUES LESS THAN (7), + SUBPARTITION sp7 VALUES LESS THAN (8), + SUBPARTITION sp8 VALUES LESS THAN (9), + SUBPARTITION sp9 VALUES LESS THAN (10), + SUBPARTITION sp10 VALUES LESS THAN (11), + SUBPARTITION sp11 VALUES LESS THAN (12), + SUBPARTITION sp12 VALUES LESS THAN (13)) +explain select `snap_time` from `sp_k_r_month` t where t.snap_time >= '2024-05-21 17:30:27' and t.snap_time <= '2024-05-21 17:30:40' order by t.snap_time limit 10; +Logical ExecutionPlan +MergeSort(sort="snap_time ASC", offset=0, fetch=?2) + LogicalView(tables="sp_k_r_month[p1sp5,p2sp5]", shardCount=2, sql="SELECT `snap_time` FROM `sp_k_r_month` AS `sp_k_r_month` WHERE ((`snap_time` >= ?) AND (`snap_time` <= ?)) ORDER BY `snap_time` LIMIT (? + 0)") +explain select `snap_time` from `sp_k_r_month` t where t.snap_time >= '2024-05-21 17:30:27' and t.snap_time <= '2024-06-21 17:30:40' order by t.snap_time limit 10; +Logical ExecutionPlan +MergeSort(sort="snap_time ASC", offset=0, fetch=?2) + LogicalView(tables="sp_k_r_month[p1sp5,p1sp6,p2sp5,p2sp6]", shardCount=4, sql="SELECT `snap_time` FROM `sp_k_r_month` AS `sp_k_r_month` WHERE ((`snap_time` >= ?) AND (`snap_time` <= ?)) ORDER BY `snap_time` LIMIT (? + 0)") +explain select `snap_time` from `sp_k_r_month` t where t.snap_time >= '2024-05-21 17:30:27' and t.snap_time <= '2024-07-21 17:30:40' order by t.snap_time limit 10; +Logical ExecutionPlan +MergeSort(sort="snap_time ASC", offset=0, fetch=?2) + LogicalView(tables="sp_k_r_month[p1sp5,p1sp6,p1sp7,p2sp5,p2sp6,p2sp7]", shardCount=6, sql="SELECT `snap_time` FROM `sp_k_r_month` AS `sp_k_r_month` WHERE ((`snap_time` >= ?) AND (`snap_time` <= ?)) ORDER BY `snap_time` LIMIT (? + 0)") +insert into sp_k_r_month values (null, '2024-01-22 00:00:00', 0); +insert into sp_k_r_month values (null, '2024-05-21 17:30:33', 0); +insert into sp_k_r_month values (null, '2024-06-22 00:00:00', 0); +select `snap_time` from `sp_k_r_month` t where t.snap_time >= '2024-05-21 17:30:27' and t.snap_time <= '2024-05-21 17:30:40' order by t.snap_time limit 10; +snap_time +2024-05-21 17:30:33.0 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning4Test/test_sp_partfunc_month.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning4Test/test_sp_partfunc_month.test.yml new file mode 100644 index 000000000..49450b1d0 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning4Test/test_sp_partfunc_month.test.yml @@ -0,0 +1,36 @@ +## DISABLE_FAST_SQL_PARSER + +CREATE TABLE `sp_k_r_month` ( +`id` bigint(18) NOT NULL AUTO_INCREMENT, +`snap_time` datetime NOT NULL, +`school_id` bigint(18) DEFAULT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 1684206033 DEFAULT CHARSET = utf8 +PARTITION BY KEY(`school_id`,`id`) +PARTITIONS 2 +SUBPARTITION BY RANGE(MONTH(`snap_time`)) +(SUBPARTITION `sp1` VALUES LESS THAN (2), +SUBPARTITION `sp2` VALUES LESS THAN (3), +SUBPARTITION `sp3` VALUES LESS THAN (4), +SUBPARTITION `sp4` VALUES LESS THAN (5), +SUBPARTITION `sp5` VALUES LESS THAN (6), +SUBPARTITION `sp6` VALUES LESS THAN (7), +SUBPARTITION `sp7` VALUES LESS THAN (8), +SUBPARTITION `sp8` VALUES LESS THAN (9), +SUBPARTITION `sp9` VALUES LESS THAN (10), +SUBPARTITION `sp10` VALUES LESS THAN (11), +SUBPARTITION `sp11` VALUES LESS THAN (12), +SUBPARTITION `sp12` VALUES LESS THAN (13) +); + +show create table sp_k_r_month; +explain select `snap_time` from `sp_k_r_month` t where t.snap_time >= '2024-05-21 17:30:27' and t.snap_time <= '2024-05-21 17:30:40' order by t.snap_time limit 10; +explain select `snap_time` from `sp_k_r_month` t where t.snap_time >= '2024-05-21 17:30:27' and t.snap_time <= '2024-06-21 17:30:40' order by t.snap_time limit 10; +explain select `snap_time` from `sp_k_r_month` t where t.snap_time >= '2024-05-21 17:30:27' and t.snap_time <= '2024-07-21 17:30:40' order by t.snap_time limit 10; +insert into sp_k_r_month values (null, '2024-01-22 00:00:00', 0); +insert into sp_k_r_month values (null, '2024-05-21 17:30:33', 0); +insert into sp_k_r_month values (null, '2024-06-22 00:00:00', 0); +select `snap_time` from `sp_k_r_month` t where t.snap_time >= '2024-05-21 17:30:27' and t.snap_time <= '2024-05-21 17:30:40' order by t.snap_time limit 10; + + + diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruning4Test/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning4Test/testcase.config.yml new file mode 100644 index 000000000..85719e6bb --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruning4Test/testcase.config.yml @@ -0,0 +1 @@ +test_sp_partfunc_month \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_hash_enum.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_hash_enum.result index d8832b3fb..384150500 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_hash_enum.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_hash_enum.result @@ -39,7 +39,8 @@ EXPLAIN SELECT * FROM t_ubigint WHERE a BETWEEN 9223372036854775809 AND 9223372036854775809; Logical ExecutionPlan -PhyTableOperation(tables="t_ubigint[p1]", sql="SELECT `t_ubigint`.`a` FROM ? AS `t_ubigint` WHERE (`t_ubigint`.`a` BETWEEN ? AND ?)", params="9223372036854775809,9223372036854775809") +Gather(concurrent=true) + LogicalView(tables="t_ubigint[p1]", sql="SELECT `a` FROM `t_ubigint` AS `t_ubigint` WHERE (`a` BETWEEN ? AND ?)") EXPLAIN SELECT * FROM t_ubigint WHERE a = 9223372036854775809; diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_between.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_between.result index 17216f8fd..983a02355 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_between.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_between.result @@ -15,7 +15,8 @@ FROM tbl_bt WHERE b BETWEEN 2000 AND 3000 AND a = 100; Logical ExecutionPlan -PhyTableOperation(tables="tbl_bt[p2]", sql="SELECT `tbl_bt`.`a` AS `a` FROM ? AS `tbl_bt` WHERE ((`tbl_bt`.`b` BETWEEN ? AND ?) AND (`tbl_bt`.`a` = ?))", params="3000,2000,100") +Gather(concurrent=true) + LogicalView(tables="tbl_bt[p2]", sql="SELECT `a` FROM `tbl_bt` AS `tbl_bt` WHERE ((`b` BETWEEN ? AND ?) AND (`a` = ?))") EXPLAIN SELECT a FROM tbl_bt WHERE a BETWEEN 200 AND 300 diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_null2.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_null2.result index 0d0157493..f97bed682 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_null2.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_null2.result @@ -34,7 +34,8 @@ EXPLAIN SELECT a FROM tbl_rng_col WHERE b <= NULL; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col[p1]", sql="SELECT `tbl_rng_col`.`a` AS `a` FROM ? AS `tbl_rng_col` WHERE (`tbl_rng_col`.`b` <= NULL)") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col[p1]", sql="SELECT `a` FROM `tbl_rng_col` AS `tbl_rng_col` WHERE (`b` <= NULL)") EXPLAIN SELECT a FROM tbl_rng_col WHERE b = NULL; @@ -50,7 +51,8 @@ EXPLAIN SELECT a FROM tbl_rng_col WHERE b < NULL; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col[p1]", sql="SELECT `tbl_rng_col`.`a` AS `a` FROM ? AS `tbl_rng_col` WHERE (`tbl_rng_col`.`b` < NULL)") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col[p1]", sql="SELECT `a` FROM `tbl_rng_col` AS `tbl_rng_col` WHERE (`b` < NULL)") CREATE TABLE `tbl_rng_col2` ( `a` bigint(20) DEFAULT NULL, `b` bigint(20) DEFAULT NULL, @@ -92,12 +94,14 @@ EXPLAIN SELECT a FROM tbl_rng_col2 WHERE b <= NULL; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col2[p1]", sql="SELECT `tbl_rng_col2`.`a` AS `a` FROM ? AS `tbl_rng_col2` WHERE (`tbl_rng_col2`.`b` <= NULL)") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col2[p1]", sql="SELECT `a` FROM `tbl_rng_col2` AS `tbl_rng_col2` WHERE (`b` <= NULL)") EXPLAIN SELECT a FROM tbl_rng_col2 WHERE b = NULL; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col2[p1]", sql="SELECT `tbl_rng_col2`.`a` AS `a` FROM ? AS `tbl_rng_col2` WHERE (`tbl_rng_col2`.`b` = ?)", params="NULL") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col2[p1]", sql="SELECT `a` FROM `tbl_rng_col2` AS `tbl_rng_col2` WHERE (`b` = ?)") EXPLAIN SELECT a FROM tbl_rng_col2 WHERE b > NULL; @@ -108,7 +112,8 @@ EXPLAIN SELECT a FROM tbl_rng_col2 WHERE b < NULL; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col2[p1]", sql="SELECT `tbl_rng_col2`.`a` AS `a` FROM ? AS `tbl_rng_col2` WHERE (`tbl_rng_col2`.`b` < NULL)") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col2[p1]", sql="SELECT `a` FROM `tbl_rng_col2` AS `tbl_rng_col2` WHERE (`b` < NULL)") SELECT a FROM tbl_rng_col2 WHERE (b, c) = (1001, NULL); diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_row_expr.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_row_expr.result index 461625b07..287631194 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_row_expr.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_pruning_row_expr.result @@ -157,7 +157,8 @@ EXPLAIN SELECT * FROM tbl_rng_col2 WHERE (b, c, a) >= (2001, 1999, 10000); Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col2[p3]", sql="SELECT `tbl_rng_col2`.`a`, `tbl_rng_col2`.`b`, `tbl_rng_col2`.`c`, `tbl_rng_col2`.`d`, `tbl_rng_col2`.`e` FROM ? AS `tbl_rng_col2` WHERE ((`tbl_rng_col2`.`b`, `tbl_rng_col2`.`c`, `tbl_rng_col2`.`a`) >=(?, ?, ?))", params="1999,2001,10000") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col2[p3]", sql="SELECT `a`, `b`, `c`, `d`, `e` FROM `tbl_rng_col2` AS `tbl_rng_col2` WHERE ((`b`, `c`, `a`) >=(?, ?, ?))") EXPLAIN SELECT * FROM tbl_rng_col2 WHERE (b, c, a) = (2001, 1999, 10000); diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_timezone.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_timezone.result index c7bb1621f..c527b8c3a 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_timezone.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_part_timezone.result @@ -120,7 +120,8 @@ a 1998-12-31 17:00:00.0 explain /*TDDL:cmd_extra(IN_SUB_QUERY_THRESHOLD=8)*/select * from tbl_rng_ts2 where a='1998-12-31 15:00:00' or a='1998-12-31 17:00:00'; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_ts2[p0]", sql="SELECT `tbl_rng_ts2`.`a` FROM ? AS `tbl_rng_ts2` WHERE (`tbl_rng_ts2`.`a` IN (?, ?))", params="1998-12-31 17:00:00,1998-12-31 15:00:00") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_ts2[p0]", sql="SELECT `a` FROM `tbl_rng_ts2` AS `tbl_rng_ts2` WHERE (`a` IN(?, ?))") set time_zone="+08:00"; ## both '1998-12-31 23:00:00' and '1999-01-01 01:00:00' should be route to p0 select * from tbl_rng_ts2 where a ='1998-12-31 23:00:00' or a='1999-01-01 01:00:00'; @@ -129,4 +130,5 @@ a 1999-01-01 01:00:00.0 explain /*TDDL:cmd_extra(IN_SUB_QUERY_THRESHOLD=8)*/select * from tbl_rng_ts2 where a ='1998-12-31 23:00:00' or a='1999-01-01 01:00:00'; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_ts2[p0]", sql="SELECT `tbl_rng_ts2`.`a` FROM ? AS `tbl_rng_ts2` WHERE (`tbl_rng_ts2`.`a` IN (?, ?))", params="1999-01-01 01:00:00,1998-12-31 23:00:00") \ No newline at end of file +Gather(concurrent=true) + LogicalView(tables="tbl_rng_ts2[p0]", sql="SELECT `a` FROM `tbl_rng_ts2` AS `tbl_rng_ts2` WHERE (`a` IN(?, ?))") diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_range_hex.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_range_hex.result index 12d8c9400..9781edc11 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_range_hex.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_range_hex.result @@ -13,7 +13,8 @@ EXPLAIN SELECT * FROM rc_char16_gbk_utf8 WHERE c1 = 0xE4B896E7958C; Logical ExecutionPlan -PhyTableOperation(tables="rc_char16_gbk_utf8[p0]", sql="SELECT `rc_char16_gbk_utf8`.`c1`, `rc_char16_gbk_utf8`.`c2` FROM ? AS `rc_char16_gbk_utf8` WHERE (`rc_char16_gbk_utf8`.`c1` = CONVERT(? USING 'GBK'))", params="0xE4B896E7958C") +Gather(concurrent=true) + LogicalView(tables="rc_char16_gbk_utf8[p0]", sql="SELECT `c1`, `c2` FROM `rc_char16_gbk_utf8` AS `rc_char16_gbk_utf8` WHERE (`c1` = CONVERT(? USING 'GBK'))") DROP TABLE IF EXISTS rc_varchar16_gbk_utf8; CREATE TABLE IF NOT EXISTS rc_varchar16_gbk_utf8 ( c1 varchar(16) CHARACTER SET gbk DEFAULT NULL, @@ -29,4 +30,5 @@ EXPLAIN SELECT * FROM rc_varchar16_gbk_utf8 WHERE c1 = 0xE4B896E7958C; Logical ExecutionPlan -PhyTableOperation(tables="rc_varchar16_gbk_utf8[p0]", sql="SELECT `rc_varchar16_gbk_utf8`.`c1`, `rc_varchar16_gbk_utf8`.`c2` FROM ? AS `rc_varchar16_gbk_utf8` WHERE (`rc_varchar16_gbk_utf8`.`c1` = CONVERT(? USING 'GBK'))", params="0xE4B896E7958C") +Gather(concurrent=true) + LogicalView(tables="rc_varchar16_gbk_utf8[p0]", sql="SELECT `c1`, `c2` FROM `rc_varchar16_gbk_utf8` AS `rc_varchar16_gbk_utf8` WHERE (`c1` = CONVERT(? USING 'GBK'))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_select_partitions.result b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_select_partitions.result index 543c53532..58f07bf02 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_select_partitions.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTablePruningTest/test_select_partitions.result @@ -22,18 +22,14 @@ PARTITION BY RANGE (a) ( explain select * from t1 partition (p1) join t2 partition (p1) on t1.id=t2.id; Logical ExecutionPlan BKAJoin(condition="id = id", type="inner") - Gather(concurrent=true) - LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") - Gather(concurrent=true) - LogicalView(tables="t2[p1]", sql="SELECT `id`, `a` FROM `t2` AS `t2` WHERE (`id` IN (...))") + LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") + LogicalView(tables="t2[p1]", sql="SELECT `id`, `a` FROM `t2` AS `t2` WHERE (`id` IN (...))") explain select * from t1 partition (p1); Logical ExecutionPlan -Gather(concurrent=true) - LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") +LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") explain select * from t2 partition (p1); Logical ExecutionPlan -Gather(concurrent=true) - LogicalView(tables="t2[p1]", sql="SELECT `id`, `a` FROM `t2` AS `t2`") +LogicalView(tables="t2[p1]", sql="SELECT `id`, `a` FROM `t2` AS `t2`") explain select * from t1 partition (p1) join t2 partition (p1) on t1.a=t2.a; Logical ExecutionPlan Gather(concurrent=true) @@ -41,7 +37,5 @@ Gather(concurrent=true) explain select * from t1 partition (p1) join t2 partition (p2) on t1.a=t2.a; Logical ExecutionPlan BKAJoin(condition="a = a", type="inner") - Gather(concurrent=true) - LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") - Gather(concurrent=true) - LogicalView(tables="t2[p2]", sql="SELECT `id`, `a` FROM `t2` AS `t2` WHERE (`a` IN (...))") \ No newline at end of file + LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") + LogicalView(tables="t2[p2]", sql="SELECT `id`, `a` FROM `t2` AS `t2` WHERE (`a` IN (...))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan.result b/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan.result new file mode 100644 index 000000000..65ce4b713 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan.result @@ -0,0 +1,75 @@ +## DISABLE_FAST_SQL_PARSER +CREATE TABLE `sbtest1` ( +`id` int(11) NOT NULL, +`k` int(11) NOT NULL DEFAULT '0', +`create_time` char(120) NOT NULL DEFAULT '', +`pad` char(60) NOT NULL DEFAULT '', +KEY `auto_shard_key_id` USING BTREE (`id`), +KEY `auto_shard_key_create_time` USING BTREE (`create_time`), +KEY `k_1` (`k`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 8 +SUBPARTITION BY RANGE COLUMNS(`create_time`) +(SUBPARTITION sp202305 VALUES LESS THAN ('2023-06-01 00:00:00'), +SUBPARTITION sp202306 VALUES LESS THAN ('2023-07-01 00:00:00'), +SUBPARTITION sp202307 VALUES LESS THAN ('2023-08-01 00:00:00'), +SUBPARTITION sp202308 VALUES LESS THAN ('2023-09-01 00:00:00'), +SUBPARTITION sp202309 VALUES LESS THAN ('2023-10-01 00:00:00'), +SUBPARTITION sp202310 VALUES LESS THAN ('2023-11-01 00:00:00'), +SUBPARTITION sp202311 VALUES LESS THAN ('2023-12-01 00:00:00'), +SUBPARTITION sp202312 VALUES LESS THAN ('2024-01-01 00:00:00'), +SUBPARTITION sp202401 VALUES LESS THAN ('2024-02-01 00:00:00'), +SUBPARTITION sp202402 VALUES LESS THAN ('2024-03-01 00:00:00'), +SUBPARTITION sp202403 VALUES LESS THAN ('2024-04-01 00:00:00'), +SUBPARTITION sp202404 VALUES LESS THAN ('2024-05-01 00:00:00')); +insert into sbtest1 values +(1, 1, '2024-04-11 00:00:00', 'pad'), (1, 2, '2024-04-10 00:00:00', 'pad'), (1, 3, '2024-04-10 00:00:00', 'pad'), +(1, 10, '2024-03-11 00:00:00', 'pad'), (1, 12, '2024-03-10 00:00:00', 'pad'), (1, 13, '2024-03-10 00:00:00', 'pad'), +(1, 100, '2024-01-11 00:00:00', 'pad'), (1, 120, '2024-01-10 00:00:00', 'pad'), (1, 130, '2024-01-10 00:00:00', 'pad'), +(2, 1, '2024-04-11 00:00:00', 'pad'), (2, 2, '2024-04-10 00:00:00', 'pad'), (2, 3, '2024-04-10 00:00:00', 'pad'), +(2, 10, '2024-03-11 00:00:00', 'pad'), (2, 12, '2024-03-10 00:00:00', 'pad'), (2, 13, '2024-03-10 00:00:00', 'pad'), +(3, 100, '2024-01-11 00:00:00', 'pad'), (3, 120, '2024-01-10 00:00:00', 'pad'), (3, 130, '2024-01-10 00:00:00', 'pad'); +/*+TDDL: ENABLE_RANGE_SCAN=FALSE*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE=''*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='SERIALIZE'*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='NORMAL'*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE'*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='' */ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='CONSTANT' */ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='EXPONENT' */ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='EXPONENT ' */ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_SERIALIZE_LIMIT=2*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 10; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_SERIALIZE_LIMIT=20*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 10; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest1 where id = 1 and k = 4 order by create_time limit 1; +id,k,create_time,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest1 where id = 4 and k = 4 order by create_time limit 1; +id,k,create_time,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest1 where id = 2 and k = 12 order by create_time limit 1; +id,k,create_time,pad +2,12,2024-03-10 00:00:00,pad \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan.test.yml new file mode 100644 index 000000000..086e9a647 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan.test.yml @@ -0,0 +1,47 @@ +## DISABLE_FAST_SQL_PARSER +CREATE TABLE `sbtest1` ( +`id` int(11) NOT NULL, +`k` int(11) NOT NULL DEFAULT '0', +`create_time` char(120) NOT NULL DEFAULT '', +`pad` char(60) NOT NULL DEFAULT '', +KEY `auto_shard_key_id` USING BTREE (`id`), +KEY `auto_shard_key_create_time` USING BTREE (`create_time`), +KEY `k_1` (`k`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 8 +SUBPARTITION BY RANGE COLUMNS(`create_time`) +(SUBPARTITION `sp202305` VALUES LESS THAN ('2023-06-01 00:00:00'), +SUBPARTITION `sp202306` VALUES LESS THAN ('2023-07-01 00:00:00'), +SUBPARTITION `sp202307` VALUES LESS THAN ('2023-08-01 00:00:00'), +SUBPARTITION `sp202308` VALUES LESS THAN ('2023-09-01 00:00:00'), +SUBPARTITION `sp202309` VALUES LESS THAN ('2023-10-01 00:00:00'), +SUBPARTITION `sp202310` VALUES LESS THAN ('2023-11-01 00:00:00'), +SUBPARTITION `sp202311` VALUES LESS THAN ('2023-12-01 00:00:00'), +SUBPARTITION `sp202312` VALUES LESS THAN ('2024-01-01 00:00:00'), +SUBPARTITION `sp202401` VALUES LESS THAN ('2024-02-01 00:00:00'), +SUBPARTITION `sp202402` VALUES LESS THAN ('2024-03-01 00:00:00'), +SUBPARTITION `sp202403` VALUES LESS THAN ('2024-04-01 00:00:00'), +SUBPARTITION `sp202404` VALUES LESS THAN ('2024-05-01 00:00:00')); +insert into sbtest1 values +(1, 1, '2024-04-11 00:00:00', 'pad'), (1, 2, '2024-04-10 00:00:00', 'pad'), (1, 3, '2024-04-10 00:00:00', 'pad'), +(1, 10, '2024-03-11 00:00:00', 'pad'), (1, 12, '2024-03-10 00:00:00', 'pad'), (1, 13, '2024-03-10 00:00:00', 'pad'), +(1, 100, '2024-01-11 00:00:00', 'pad'), (1, 120, '2024-01-10 00:00:00', 'pad'), (1, 130, '2024-01-10 00:00:00', 'pad'), +(2, 1, '2024-04-11 00:00:00', 'pad'), (2, 2, '2024-04-10 00:00:00', 'pad'), (2, 3, '2024-04-10 00:00:00', 'pad'), +(2, 10, '2024-03-11 00:00:00', 'pad'), (2, 12, '2024-03-10 00:00:00', 'pad'), (2, 13, '2024-03-10 00:00:00', 'pad'), +(3, 100, '2024-01-11 00:00:00', 'pad'), (3, 120, '2024-01-10 00:00:00', 'pad'), (3, 130, '2024-01-10 00:00:00', 'pad'); +/*+TDDL: ENABLE_RANGE_SCAN=FALSE*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE=''*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='SERIALIZE'*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='NORMAL'*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE'*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='' */ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='CONSTANT' */ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='EXPONENT' */ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='EXPONENT ' */ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_SERIALIZE_LIMIT=2*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 10; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_SERIALIZE_LIMIT=20*/ select * from sbtest1 where id = 1 and k = 2 order by create_time limit 10; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest1 where id = 1 and k = 4 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest1 where id = 4 and k = 4 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest1 where id = 2 and k = 12 order by create_time limit 1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan_2.result b/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan_2.result new file mode 100644 index 000000000..86dbb8306 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan_2.result @@ -0,0 +1,73 @@ +## DISABLE_FAST_SQL_PARSER + CREATE TABLE `sbtest2` ( + `id` int(11) NOT NULL, + `k` int(11) NOT NULL DEFAULT '0', + `create_time` char(120) NOT NULL DEFAULT '', + `pad` char(60) NOT NULL DEFAULT '', + KEY `auto_shard_key_id` USING BTREE (`id`), + KEY `auto_shard_key_create_time` USING BTREE (`create_time`), + KEY `k_1` (`k`) + ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 + PARTITION BY RANGE COLUMNS(`create_time`) + (SUBPARTITION sp202305 VALUES LESS THAN ('2023-06-01 00:00:00'), + SUBPARTITION sp202306 VALUES LESS THAN ('2023-07-01 00:00:00'), + SUBPARTITION sp202307 VALUES LESS THAN ('2023-08-01 00:00:00'), + SUBPARTITION sp202308 VALUES LESS THAN ('2023-09-01 00:00:00'), + SUBPARTITION sp202309 VALUES LESS THAN ('2023-10-01 00:00:00'), + SUBPARTITION sp202310 VALUES LESS THAN ('2023-11-01 00:00:00'), + SUBPARTITION sp202311 VALUES LESS THAN ('2023-12-01 00:00:00'), + SUBPARTITION sp202312 VALUES LESS THAN ('2024-01-01 00:00:00'), + SUBPARTITION sp202401 VALUES LESS THAN ('2024-02-01 00:00:00'), + SUBPARTITION sp202402 VALUES LESS THAN ('2024-03-01 00:00:00'), + SUBPARTITION sp202403 VALUES LESS THAN ('2024-04-01 00:00:00'), + SUBPARTITION sp202404 VALUES LESS THAN ('2024-05-01 00:00:00')); +insert into sbtest2 values + (1, 1, '2024-04-11 00:00:00', 'pad'), (1, 2, '2024-04-10 00:00:00', 'pad'), (1, 3, '2024-04-10 00:00:00', 'pad'), + (1, 10, '2024-03-11 00:00:00', 'pad'), (1, 12, '2024-03-10 00:00:00', 'pad'), (1, 13, '2024-03-10 00:00:00', 'pad'), + (1, 100, '2024-01-11 00:00:00', 'pad'), (1, 120, '2024-01-10 00:00:00', 'pad'), (1, 130, '2024-01-10 00:00:00', 'pad'), + (2, 1, '2024-04-11 00:00:00', 'pad'), (2, 2, '2024-04-10 00:00:00', 'pad'), (2, 3, '2024-04-10 00:00:00', 'pad'), + (2, 10, '2024-03-11 00:00:00', 'pad'), (2, 12, '2024-03-10 00:00:00', 'pad'), (2, 13, '2024-03-10 00:00:00', 'pad'), + (3, 100, '2024-01-11 00:00:00', 'pad'), (3, 120, '2024-01-10 00:00:00', 'pad'), (3, 130, '2024-01-10 00:00:00', 'pad'); +/*+TDDL: ENABLE_RANGE_SCAN=FALSE*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE=''*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='SERIALIZE'*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='NORMAL'*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE'*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='' */ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='CONSTANT' */ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='EXPONENT' */ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='EXPONENT ' */ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_SERIALIZE_LIMIT=2*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 10; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_SERIALIZE_LIMIT=20*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 10; +id,k,create_time,pad +1,2,2024-04-10 00:00:00,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest2 where id = 1 and k = 4 order by create_time limit 1; +id,k,create_time,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest2 where id = 4 and k = 4 order by create_time limit 1; +id,k,create_time,pad +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest2 where id = 2 and k = 12 order by create_time limit 1; +id,k,create_time,pad +2,12,2024-03-10 00:00:00,pad \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan_2.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan_2.test.yml new file mode 100644 index 000000000..ef2870d82 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/test_range_scan_2.test.yml @@ -0,0 +1,45 @@ +## DISABLE_FAST_SQL_PARSER + CREATE TABLE `sbtest2` ( + `id` int(11) NOT NULL, + `k` int(11) NOT NULL DEFAULT '0', + `create_time` char(120) NOT NULL DEFAULT '', + `pad` char(60) NOT NULL DEFAULT '', + KEY `auto_shard_key_id` USING BTREE (`id`), + KEY `auto_shard_key_create_time` USING BTREE (`create_time`), + KEY `k_1` (`k`) + ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 + PARTITION BY RANGE COLUMNS(`create_time`) + (SUBPARTITION `sp202305` VALUES LESS THAN ('2023-06-01 00:00:00'), + SUBPARTITION `sp202306` VALUES LESS THAN ('2023-07-01 00:00:00'), + SUBPARTITION `sp202307` VALUES LESS THAN ('2023-08-01 00:00:00'), + SUBPARTITION `sp202308` VALUES LESS THAN ('2023-09-01 00:00:00'), + SUBPARTITION `sp202309` VALUES LESS THAN ('2023-10-01 00:00:00'), + SUBPARTITION `sp202310` VALUES LESS THAN ('2023-11-01 00:00:00'), + SUBPARTITION `sp202311` VALUES LESS THAN ('2023-12-01 00:00:00'), + SUBPARTITION `sp202312` VALUES LESS THAN ('2024-01-01 00:00:00'), + SUBPARTITION `sp202401` VALUES LESS THAN ('2024-02-01 00:00:00'), + SUBPARTITION `sp202402` VALUES LESS THAN ('2024-03-01 00:00:00'), + SUBPARTITION `sp202403` VALUES LESS THAN ('2024-04-01 00:00:00'), + SUBPARTITION `sp202404` VALUES LESS THAN ('2024-05-01 00:00:00')); + insert into sbtest2 values + (1, 1, '2024-04-11 00:00:00', 'pad'), (1, 2, '2024-04-10 00:00:00', 'pad'), (1, 3, '2024-04-10 00:00:00', 'pad'), + (1, 10, '2024-03-11 00:00:00', 'pad'), (1, 12, '2024-03-10 00:00:00', 'pad'), (1, 13, '2024-03-10 00:00:00', 'pad'), + (1, 100, '2024-01-11 00:00:00', 'pad'), (1, 120, '2024-01-10 00:00:00', 'pad'), (1, 130, '2024-01-10 00:00:00', 'pad'), + (2, 1, '2024-04-11 00:00:00', 'pad'), (2, 2, '2024-04-10 00:00:00', 'pad'), (2, 3, '2024-04-10 00:00:00', 'pad'), + (2, 10, '2024-03-11 00:00:00', 'pad'), (2, 12, '2024-03-10 00:00:00', 'pad'), (2, 13, '2024-03-10 00:00:00', 'pad'), + (3, 100, '2024-01-11 00:00:00', 'pad'), (3, 120, '2024-01-10 00:00:00', 'pad'), (3, 130, '2024-01-10 00:00:00', 'pad'); +/*+TDDL: ENABLE_RANGE_SCAN=FALSE*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE=''*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='SERIALIZE'*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='NORMAL'*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE'*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='' */ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='CONSTANT' */ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='EXPONENT' */ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_MODE='ADAPTIVE' RANGE_SCAN_ADAPTIVE_POLICY='EXPONENT ' */ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_SERIALIZE_LIMIT=2*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 10; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE RANGE_SCAN_SERIALIZE_LIMIT=20*/ select * from sbtest2 where id = 1 and k = 2 order by create_time limit 10; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest2 where id = 1 and k = 4 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest2 where id = 4 and k = 4 order by create_time limit 1; +/*+TDDL: ENABLE_RANGE_SCAN=TRUE*/ select * from sbtest2 where id = 2 and k = 12 order by create_time limit 1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/testcase.config.yml new file mode 100644 index 000000000..af816f1ac --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableRangeScanTest/testcase.config.yml @@ -0,0 +1,2 @@ +test_range_scan +test_range_scan_2 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableSelectPartitionTest/test_select_partition_in_dml.result b/polardbx-test/src/test/resources/partition/env/PartitionTableSelectPartitionTest/test_select_partition_in_dml.result index b37893ad1..d8d2fba21 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableSelectPartitionTest/test_select_partition_in_dml.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableSelectPartitionTest/test_select_partition_in_dml.result @@ -85,12 +85,12 @@ a,b begin; explain select * from tbl_with_gsi1 partition(p2) where a=21; Logical ExecutionPlan -LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d` FROM `tbl_with_gsi1` AS `tbl_with_gsi1` WHERE (`a` = ?)") +PhyTableOperation(tables="tbl_with_gsi1[p3]", sql="SELECT `tbl_with_gsi1`.`a`, `tbl_with_gsi1`.`b`, `tbl_with_gsi1`.`c`, `tbl_with_gsi1`.`d` FROM ? AS `tbl_with_gsi1` WHERE (`tbl_with_gsi1`.`a` = ?)", params="21") select * from tbl_with_gsi1 partition(p2) where a=21; a,b,c,d explain select * from tbl_with_gsi1 partition(p2) where a=11; Logical ExecutionPlan -LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d` FROM `tbl_with_gsi1` AS `tbl_with_gsi1` WHERE (`a` = ?)") +PhyTableOperation(tables="tbl_with_gsi1[p2]", sql="SELECT `tbl_with_gsi1`.`a`, `tbl_with_gsi1`.`b`, `tbl_with_gsi1`.`c`, `tbl_with_gsi1`.`d` FROM ? AS `tbl_with_gsi1` WHERE (`tbl_with_gsi1`.`a` = ?)", params="11") select * from tbl_with_gsi1 partition(p2) where a=11; a,b,c,d rollback; @@ -98,7 +98,8 @@ rollback; begin; explain select * from tbl_with_gsi1 partition(p2) t1 inner join tbl_with_gsi2 partition(p2) t2 on t1.a=t2.a where t1.a=11; Logical ExecutionPlan -PhyTableOperation(tables="tbl_with_gsi1[p2],tbl_with_gsi2[p2]", sql="SELECT `t1`.`a`, `t1`.`b`, `t1`.`c`, `t1`.`d`, `t2`.`a`, `t2`.`b`, `t2`.`c`, `t2`.`d` FROM ? AS `t1` INNER JOIN ? AS `t2` ON (`t1`.`a` = `t2`.`a`) WHERE (`t1`.`a` = ?)", params="11") +Gather(concurrent=true) + LogicalView(tables="tbl_with_gsi1[p2],tbl_with_gsi2[p2]", sql="SELECT `tbl_with_gsi1`.`a`, `tbl_with_gsi1`.`b`, `tbl_with_gsi1`.`c`, `tbl_with_gsi1`.`d`, `tbl_with_gsi2`.`a` AS `a0`, `tbl_with_gsi2`.`b` AS `b0`, `tbl_with_gsi2`.`c` AS `c0`, `tbl_with_gsi2`.`d` AS `d0` FROM `tbl_with_gsi1` AS `tbl_with_gsi1` INNER JOIN `tbl_with_gsi2` AS `tbl_with_gsi2` ON ((`tbl_with_gsi2`.`a` = ?) AND (`tbl_with_gsi1`.`a` = `tbl_with_gsi2`.`a`) AND (`tbl_with_gsi1`.`a` = ?))") select * from tbl_with_gsi1 partition(p2) t1 inner join tbl_with_gsi2 partition(p2) t2 on t1.a=t2.a where t1.a=11; a,b,c,d,a,b,c,d explain select * from tbl_with_gsi1 partition(p4,p2,p3) t1 inner join tbl_with_gsi2 partition(p2,p3,p3) t2 on t1.a=t2.a where t1.a=11; @@ -133,10 +134,8 @@ a,b,c,d explain select * from tbl_with_gsi1 partition(p2) where exists (select a from tbl_with_gsi2 partition(p2)); Logical ExecutionPlan SemiNLJoin(condition="true", type="semi") - Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d` FROM `tbl_with_gsi1` AS `tbl_with_gsi1`") - Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi2[p2]", sql="SELECT `a` FROM `tbl_with_gsi2` AS `tbl_with_gsi2`") + LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d` FROM `tbl_with_gsi1` AS `tbl_with_gsi1`") + LogicalView(tables="tbl_with_gsi2[p2]", sql="SELECT `a` FROM `tbl_with_gsi2` AS `tbl_with_gsi2`") select * from tbl_with_gsi1 partition(p2) where exists (select a from tbl_with_gsi2 partition(p2)); a,b,c,d rollback; @@ -147,18 +146,16 @@ Logical ExecutionPlan Project(a="a", b="b", c="c", d="d") Filter(condition="APPLY_BOOLEAN") CorrelateApply(cor=$cor0, leftConditions=[$0], opKind=EQUALS, type=SEMI) - Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d` FROM `tbl_with_gsi1` AS `tbl_with_gsi1`") + LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d` FROM `tbl_with_gsi1` AS `tbl_with_gsi1`") TopN(sort="$f0 ASC", offset=0, fetch=?0) Project($f0="a") Filter(condition="$cor0.b = b") - Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi2[p2]", sql="SELECT `a`, `b` FROM `tbl_with_gsi2` AS `tbl_with_gsi2`") + LogicalView(tables="tbl_with_gsi2[p2]", sql="SELECT `a`, `b` FROM `tbl_with_gsi2` AS `tbl_with_gsi2`") HitCache:false Source:PLAN_CACHE cache node: -Gather.DRDS.[].single(input=LogicalView#distribution=single) -Gather.DRDS.[].single(input=LogicalView#distribution=single) +LogicalView.DRDS.[].any.[](table=[test_select_part_439576952, tbl_with_gsi1],tableNames=[tbl_with_gsi1],pushDownOpt=com.alibaba.polardbx.optimizer.core.rel.PushDownOpt@3983ad9,schemaName=test_select_part_439576952,partitions=[p2],flashback=null) +LogicalView.DRDS.[].any.[](table=[test_select_part_439576952, tbl_with_gsi2],tableNames=[tbl_with_gsi2],pushDownOpt=com.alibaba.polardbx.optimizer.core.rel.PushDownOpt@4dc9b00b,schemaName=test_select_part_439576952,partitions=[p2],flashback=null) select * from tbl_with_gsi1 partition(p2) where a in (select a from tbl_with_gsi2 partition(p2) where tbl_with_gsi1.b=tbl_with_gsi2.b order by a limit 5); a,b,c,d explain select * from tbl_with_gsi1 partition(p2) where a in (select a from tbl_with_gsi2 partition(p2,p4) where tbl_with_gsi1.b=tbl_with_gsi2.b order by a limit 5); @@ -166,8 +163,7 @@ Logical ExecutionPlan Project(a="a", b="b", c="c", d="d") Filter(condition="APPLY_BOOLEAN") CorrelateApply(cor=$cor0, leftConditions=[$0], opKind=EQUALS, type=SEMI) - Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d` FROM `tbl_with_gsi1` AS `tbl_with_gsi1`") + LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d` FROM `tbl_with_gsi1` AS `tbl_with_gsi1`") TopN(sort="$f0 ASC", offset=0, fetch=?0) Project($f0="a") Filter(condition="$cor0.b = b") @@ -176,8 +172,8 @@ Project(a="a", b="b", c="c", d="d") HitCache:false Source:PLAN_CACHE cache node: -Gather.DRDS.[].single(input=LogicalView#distribution=single) -Gather.DRDS.[].single(input=LogicalView#distribution=single) +LogicalView.DRDS.[].any.[](table=[test_select_part_439576952, tbl_with_gsi1],tableNames=[tbl_with_gsi1],pushDownOpt=com.alibaba.polardbx.optimizer.core.rel.PushDownOpt@6d2f4d0c,schemaName=test_select_part_439576952,partitions=[p2],flashback=null) +Gather.DRDS.[].single.[](input=LogicalView#distribution=single) select * from tbl_with_gsi1 partition(p2) where a in (select a from tbl_with_gsi2 partition(p2,p4) where tbl_with_gsi1.b=tbl_with_gsi2.b order by a limit 5); a,b,c,d rollback; @@ -204,16 +200,14 @@ a,b,c,d explain update tbl_with_gsi1 partition(p2) set d=999; Logical ExecutionPlan LogicalRelocate(TYPE=UPDATE, SET="tbl_with_gsi1.d=?0", RELOCATE="idxd_$", UPDATE="tbl_with_gsi1") - Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_`, ? FROM `tbl_with_gsi1` AS `tbl_with_gsi1` FOR UPDATE") + LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_`, ? FROM `tbl_with_gsi1` AS `tbl_with_gsi1` FOR UPDATE") update tbl_with_gsi1 partition(p2) set d=999; select * from tbl_with_gsi1 order by a; a,b,c,d explain update tbl_with_gsi1 partition(p2) set b=100, d=999; Logical ExecutionPlan LogicalRelocate(TYPE=UPDATE, SET="tbl_with_gsi1.b=?0, tbl_with_gsi1.d=?1", RELOCATE="idxb_$, idxd_$", UPDATE="tbl_with_gsi1") - Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_`, ?, ? AS `GEN$1` FROM `tbl_with_gsi1` AS `tbl_with_gsi1` FOR UPDATE") + LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_`, ?, ? AS `GEN$1` FROM `tbl_with_gsi1` AS `tbl_with_gsi1` FOR UPDATE") select * from tbl_with_gsi1 order by a; a,b,c,d rollback; @@ -304,12 +298,11 @@ a,b,c,d explain update tbl_with_gsi1 partition(p2),tbl_with_gsi2 partition(p2,p3) set tbl_with_gsi1.d=9999, tbl_with_gsi2.d=999 where tbl_with_gsi1.a=tbl_with_gsi2.a; Logical ExecutionPlan LogicalRelocate(TYPE=UPDATE, SET="tbl_with_gsi1.d=?0, tbl_with_gsi2.d=?1", RELOCATE="idxd_$, idxd_$", UPDATE="tbl_with_gsi1, tbl_with_gsi2") - Project(a="a", b="b", c="c", d="d", _drds_implicit_id_="_drds_implicit_id_", a0="a0", b0="b0", c0="c0", d0="d0", _drds_implicit_id_0="_drds_implicit_id_0", GEN$0="?0", GEN$1="?1") + Project(a="a0", b="b0", c="c0", d="d0", _drds_implicit_id_="_drds_implicit_id_0", a0="a", b0="b", c0="c", d0="d", _drds_implicit_id_0="_drds_implicit_id_", GEN$0="?0", GEN$1="?1") BKAJoin(condition="a = a", type="inner") Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_` FROM `tbl_with_gsi1` AS `tbl_with_gsi1` FOR UPDATE") - Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi2[p2,p3]", shardCount=2, sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_` FROM `tbl_with_gsi2` AS `tbl_with_gsi2` WHERE (`a` IN (...)) FOR UPDATE") + LogicalView(tables="tbl_with_gsi2[p2,p3]", shardCount=2, sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_` FROM `tbl_with_gsi2` AS `tbl_with_gsi2` FOR UPDATE") + LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_` FROM `tbl_with_gsi1` AS `tbl_with_gsi1` WHERE (`a` IN (...)) FOR UPDATE") update tbl_with_gsi1 partition(p2),tbl_with_gsi2 partition(p2,p3) set tbl_with_gsi1.d=999, tbl_with_gsi2.d=999 where tbl_with_gsi1.a=tbl_with_gsi2.a; select * from tbl_with_gsi1 order by a; a,b,c,d @@ -339,15 +332,14 @@ a,b,c,d explain update tbl_with_gsi1 partition(p2),tbl_with_gsi2 partition(p2,p3),tbl_with_gsi3 partition(p3,p3,p4,p2) set tbl_with_gsi1.d=9999, tbl_with_gsi2.d=9999,tbl_with_gsi3.d=9999 where tbl_with_gsi1.a=tbl_with_gsi2.a and tbl_with_gsi2.a=tbl_with_gsi3.a; Logical ExecutionPlan LogicalRelocate(TYPE=UPDATE, SET="tbl_with_gsi1.d=?0, tbl_with_gsi2.d=?1, tbl_with_gsi3.d=?2", RELOCATE="idxd_$, idxd_$, idxd_$", UPDATE="tbl_with_gsi1, tbl_with_gsi2, tbl_with_gsi3") - Project(a="a", b="b", c="c", d="d", _drds_implicit_id_="_drds_implicit_id_", a0="a0", b0="b0", c0="c0", d0="d0", _drds_implicit_id_0="_drds_implicit_id_0", a1="a1", b1="b1", c1="c1", d1="d1", _drds_implicit_id_1="_drds_implicit_id_1", GEN$0="?0", GEN$1="?1", GEN$2="?2") + Project(a="a1", b="b1", c="c1", d="d1", _drds_implicit_id_="_drds_implicit_id_1", a0="a", b0="b", c0="c", d0="d", _drds_implicit_id_0="_drds_implicit_id_", a1="a0", b1="b0", c1="c0", d1="d0", _drds_implicit_id_1="_drds_implicit_id_0", GEN$0="?0", GEN$1="?1", GEN$2="?2") BKAJoin(condition="a0 = a AND a = a", type="inner") BKAJoin(condition="a = a", type="inner") Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_` FROM `tbl_with_gsi1` AS `tbl_with_gsi1` FOR UPDATE") + LogicalView(tables="tbl_with_gsi2[p2,p3]", shardCount=2, sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_` FROM `tbl_with_gsi2` AS `tbl_with_gsi2` FOR UPDATE") Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi2[p2,p3]", shardCount=2, sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_` FROM `tbl_with_gsi2` AS `tbl_with_gsi2` WHERE (`a` IN (...)) FOR UPDATE") - Gather(concurrent=true) - LogicalView(tables="tbl_with_gsi3[p2,p3,p4]", shardCount=3, sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_` FROM `tbl_with_gsi3` AS `tbl_with_gsi3` WHERE (`a` IN (...)) FOR UPDATE") + LogicalView(tables="tbl_with_gsi3[p2,p3,p4]", shardCount=3, sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_` FROM `tbl_with_gsi3` AS `tbl_with_gsi3` WHERE (`a` IN (...)) FOR UPDATE") + LogicalView(tables="tbl_with_gsi1[p2]", sql="SELECT `a`, `b`, `c`, `d`, `_drds_implicit_id_` FROM `tbl_with_gsi1` AS `tbl_with_gsi1` WHERE (`a` IN (...)) FOR UPDATE") update tbl_with_gsi1 partition(p2),tbl_with_gsi2 partition(p2,p3),tbl_with_gsi3 partition(p3,p3,p4,p2) set tbl_with_gsi1.d=9999, tbl_with_gsi2.d=9999,tbl_with_gsi3.d=9999 where tbl_with_gsi1.a=tbl_with_gsi2.a and tbl_with_gsi2.a=tbl_with_gsi3.a; select * from tbl_with_gsi1 order by a; a,b,c,d diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableSelectPartitionTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableSelectPartitionTest/testcase.config.yml index 21aa64669..fe527a95f 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableSelectPartitionTest/testcase.config.yml +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableSelectPartitionTest/testcase.config.yml @@ -1,2 +1,5 @@ test_select_bka_partition -test_select_metadb \ No newline at end of file +test_select_metadb +#test_select_partition +#test_select_partition_broadcast +#test_select_partition_in_dml diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_list.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_list.result index f34fbcda5..affab2377 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_list.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_list.result @@ -37,7 +37,8 @@ EXPLAIN SELECT * FROM tbl WHERE a < 5; Logical ExecutionPlan -PhyTableOperation(tables="tbl[p0]", sql="SELECT `tbl`.`a` FROM ? AS `tbl` WHERE (`tbl`.`a` < ?)", params="5") +Gather(concurrent=true) + LogicalView(tables="tbl[p0]", sql="SELECT `a` FROM `tbl` AS `tbl` WHERE (`a` < ?)") DROP TABLE IF EXISTS tbl; CREATE TABLE IF NOT EXISTS tbl ( a datetime NOT NULL diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofmonth.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofmonth.result index 278c98b28..2186fd45d 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofmonth.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofmonth.result @@ -37,9 +37,6 @@ d explain select * from d1 where d = '2022-07-18' order by d; Logical ExecutionPlan PhyTableOperation(tables="d1[p11]", sql="SELECT `d1`.`d` FROM ? AS `d1` WHERE (`d1`.`d` = ?) ORDER BY `d`", params="2022-07-18") -HitCache:false -Source:PLAN_CACHE -TemplateId: 024aaf5b explain select * from d1 where d = '2022-06-18' order by d; Logical ExecutionPlan PhyTableOperation(tables="d1[p11]", sql="SELECT `d1`.`d` FROM ? AS `d1` WHERE (`d1`.`d` = ?) ORDER BY `d`", params="2022-06-18") @@ -178,9 +175,6 @@ d explain select * from d3 where d = '2022-07-01'; Logical ExecutionPlan PhyTableOperation(tables="d3[p0]", sql="SELECT `d3`.`d` FROM ? AS `d3` WHERE (`d3`.`d` = ?)", params="2022-07-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: 2fdcbc3e explain select * from d3 where d = '2022-07-07'; Logical ExecutionPlan PhyTableOperation(tables="d3[p1]", sql="SELECT `d3`.`d` FROM ? AS `d3` WHERE (`d3`.`d` = ?)", params="2022-07-07") @@ -264,9 +258,6 @@ dt explain select * from d4 where dt = '2022-07-01 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="d4[p0]", sql="SELECT `d4`.`dt` FROM ? AS `d4` WHERE (`d4`.`dt` = ?)", params="2022-07-01 00:00:00") -HitCache:false -Source:PLAN_CACHE -TemplateId: b22b860d explain select * from d4 where dt = '2022-07-07 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="d4[p1]", sql="SELECT `d4`.`dt` FROM ? AS `d4` WHERE (`d4`.`dt` = ?)", params="2022-07-07 00:00:00") @@ -350,9 +341,6 @@ d explain select * from d5 where d = '2022-07-07'; Logical ExecutionPlan PhyTableOperation(tables="d5[p0]", sql="SELECT `d5`.`d` FROM ? AS `d5` WHERE (`d5`.`d` = ?)", params="2022-07-07") -HitCache:false -Source:PLAN_CACHE -TemplateId: 0ce2c940 explain select * from d5 where d = '2022-07-14'; Logical ExecutionPlan PhyTableOperation(tables="d5[p1]", sql="SELECT `d5`.`d` FROM ? AS `d5` WHERE (`d5`.`d` = ?)", params="2022-07-14") diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofmonth2.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofmonth2.result index 072762c71..22c9b2e11 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofmonth2.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofmonth2.result @@ -26,7 +26,8 @@ part_route('', 'hash_dayofmonth', '2025-01-01 00:00:00.000') p1 explain select d from hash_dayofmonth where d between '2022-02-28' and '2022-03-01'; Logical ExecutionPlan -PhyTableOperation(tables="hash_dayofmonth[p1]", sql="SELECT `hash_dayofmonth`.`d` AS `d` FROM ? AS `hash_dayofmonth` WHERE (`hash_dayofmonth`.`d` BETWEEN ? AND ?)", params="2022-03-01,2022-02-28") +Gather(concurrent=true) + LogicalView(tables="hash_dayofmonth[p1]", sql="SELECT `d` FROM `hash_dayofmonth` AS `hash_dayofmonth` WHERE (`d` BETWEEN ? AND ?)") explain select d from hash_dayofmonth where d between '2024-02-28' and '2024-03-01'; Logical ExecutionPlan Gather(concurrent=true) diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofweek.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofweek.result index 4d26b259f..c29f8811a 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofweek.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofweek.result @@ -32,9 +32,6 @@ d explain select * from w1 where d = '2022-07-17'; Logical ExecutionPlan PhyTableOperation(tables="w1[p1]", sql="SELECT `w1`.`d` FROM ? AS `w1` WHERE (`w1`.`d` = ?)", params="2022-07-17") -HitCache:false -Source:PLAN_CACHE -TemplateId: 164ca609 explain select * from w1 where d = '2022-07-18'; Logical ExecutionPlan PhyTableOperation(tables="w1[p6]", sql="SELECT `w1`.`d` FROM ? AS `w1` WHERE (`w1`.`d` = ?)", params="2022-07-18") @@ -109,9 +106,6 @@ dt explain select * from w2 where dt = '2022-07-17 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="w2[p1]", sql="SELECT `w2`.`dt` FROM ? AS `w2` WHERE (`w2`.`dt` = ?)", params="2022-07-17 00:00:00") -HitCache:false -Source:PLAN_CACHE -TemplateId: 99b8d5a2 explain select * from w2 where dt = '2022-07-18 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="w2[p6]", sql="SELECT `w2`.`dt` FROM ? AS `w2` WHERE (`w2`.`dt` = ?)", params="2022-07-18 00:00:00") @@ -218,9 +212,6 @@ d explain select * from w3 where d = '2022-07-17'; Logical ExecutionPlan PhyTableOperation(tables="w3[p2]", sql="SELECT `w3`.`d` FROM ? AS `w3` WHERE (`w3`.`d` = ?)", params="2022-07-17") -HitCache:false -Source:PLAN_CACHE -TemplateId: f352b30b explain select * from w3 where d = '2022-07-18'; Logical ExecutionPlan PhyTableOperation(tables="w3[p3]", sql="SELECT `w3`.`d` FROM ? AS `w3` WHERE (`w3`.`d` = ?)", params="2022-07-18") @@ -350,9 +341,6 @@ d explain select * from w4 where d = '2022-07-17'; Logical ExecutionPlan PhyTableOperation(tables="w4[p1]", sql="SELECT `w4`.`d` FROM ? AS `w4` WHERE (`w4`.`d` = ?)", params="2022-07-17") -HitCache:false -Source:PLAN_CACHE -TemplateId: e1d5b98c explain select * from w4 where d = '2022-07-18'; Logical ExecutionPlan PhyTableOperation(tables="w4[p2]", sql="SELECT `w4`.`d` FROM ? AS `w4` WHERE (`w4`.`d` = ?)", params="2022-07-18") diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofyear.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofyear.result index 9691a2439..4e48f24cb 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofyear.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_dayofyear.result @@ -32,9 +32,6 @@ d explain select * from y1 where d = '2021-07-01'; Logical ExecutionPlan PhyTableOperation(tables="y1[p5]", sql="SELECT `y1`.`d` FROM ? AS `y1` WHERE (`y1`.`d` = ?)", params="2021-07-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: da083947 explain select * from y1 where d = '2022-01-01'; Logical ExecutionPlan PhyTableOperation(tables="y1[p1]", sql="SELECT `y1`.`d` FROM ? AS `y1` WHERE (`y1`.`d` = ?)", params="2022-01-01") @@ -108,9 +105,6 @@ dt explain select * from y2 where dt = '2021-07-01 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="y2[p5]", sql="SELECT `y2`.`dt` FROM ? AS `y2` WHERE (`y2`.`dt` = ?)", params="2021-07-01 00:00:00") -HitCache:false -Source:PLAN_CACHE -TemplateId: 4d6faa24 explain select * from y2 where dt = '2022-01-01 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="y2[p1]", sql="SELECT `y2`.`dt` FROM ? AS `y2` WHERE (`y2`.`dt` = ?)", params="2022-01-01 00:00:00") @@ -190,9 +184,6 @@ d explain select * from y3 where d = '2022-01-01'; Logical ExecutionPlan PhyTableOperation(tables="y3[p0]", sql="SELECT `y3`.`d` FROM ? AS `y3` WHERE (`y3`.`d` = ?)", params="2022-01-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: b70e4649 explain select * from y3 where d = '2021-01-10'; Logical ExecutionPlan PhyTableOperation(tables="y3[p1]", sql="SELECT `y3`.`d` FROM ? AS `y3` WHERE (`y3`.`d` = ?)", params="2021-01-10") @@ -273,9 +264,6 @@ d explain select * from y4 where d = '2021-01-01'; Logical ExecutionPlan PhyTableOperation(tables="y4[p0]", sql="SELECT `y4`.`d` FROM ? AS `y4` WHERE (`y4`.`d` = ?)", params="2021-01-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: a5914cca explain select * from y4 where d = '2020-01-10'; Logical ExecutionPlan PhyTableOperation(tables="y4[p1]", sql="SELECT `y4`.`d` FROM ? AS `y4` WHERE (`y4`.`d` = ?)", params="2020-01-10") @@ -349,9 +337,6 @@ explain select * from y5 where d >= '2020-02-28' and d < '2020-03-02' order by d Logical ExecutionPlan MergeSort(sort="d ASC") LogicalView(tables="y5[p28,p268,p304,p350]", shardCount=4, sql="SELECT `d` FROM `y5` AS `y5` WHERE ((`d` >= ?) AND (`d` < ?)) ORDER BY `d`") -HitCache:false -Source:PLAN_CACHE -TemplateId: b3ce44af explain select * from y5 where d > '2020-02-28' and d < '2020-03-01' order by d; Logical ExecutionPlan MergeSort(sort="d ASC") diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_substr.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_substr.result index 03396513a..292d78282 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_substr.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_substr.result @@ -36,12 +36,14 @@ EXPLAIN SELECT id FROM s3 WHERE id IN ('12abc'); Logical ExecutionPlan -PhyTableOperation(tables="s3[p5]", sql="SELECT `s3`.`id` AS `id` FROM ? AS `s3` WHERE (`s3`.`id` IN (?))", params="Raw('12abc')") +Gather(concurrent=true) + LogicalView(tables="s3[p5]", sql="SELECT `id` FROM `s3` AS `s3` WHERE (`id` IN(?))") EXPLAIN SELECT id FROM s3 WHERE id IN ('34abc'); Logical ExecutionPlan -PhyTableOperation(tables="s3[p5]", sql="SELECT `s3`.`id` AS `id` FROM ? AS `s3` WHERE (`s3`.`id` IN (?))", params="Raw('34abc')") +Gather(concurrent=true) + LogicalView(tables="s3[p5]", sql="SELECT `id` FROM `s3` AS `s3` WHERE (`id` IN(?))") EXPLAIN SELECT id FROM s3 WHERE id > '12abc'; diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_todays.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_todays.result index 7f9e94942..ce7ca68ed 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_todays.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_todays.result @@ -46,17 +46,11 @@ a explain select * from tbl where a='1989-01-01' order by a; Logical ExecutionPlan PhyTableOperation(tables="tbl[p0]", sql="SELECT `tbl`.`a` FROM ? AS `tbl` WHERE (`tbl`.`a` = ?) ORDER BY `a`", params="1989-01-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: 48dfdf4e ## explain range select explain select * from tbl where (a<'2019-01-02' and a>='2009-12-31') or a between '1989-01-01' and '1989-11-01' order by a; Logical ExecutionPlan MergeSort(sort="a ASC") LogicalView(tables="tbl[p0,p2,p3]", shardCount=3, sql="SELECT `a` FROM `tbl` AS `tbl` WHERE (((`a` < ?) AND (`a` >= ?)) OR (`a` BETWEEN ? AND ?)) ORDER BY `a`") -HitCache:false -Source:PLAN_CACHE -TemplateId: d85eb230 ## test hash CREATE TABLE `tod1` ( `d` date DEFAULT NULL diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_tomonths.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_tomonths.result index b051ae44e..3aa01c5a9 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_tomonths.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_tomonths.result @@ -32,9 +32,6 @@ d explain select * from m1 where d = '0000-01-01'; Logical ExecutionPlan PhyTableOperation(tables="m1[p1]", sql="SELECT `m1`.`d` FROM ? AS `m1` WHERE (`m1`.`d` = ?)", params="0000-01-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: 43a2c5d3 explain select * from m1 where d = '0000-03-01'; Logical ExecutionPlan PhyTableOperation(tables="m1[p14]", sql="SELECT `m1`.`d` FROM ? AS `m1` WHERE (`m1`.`d` = ?)", params="0000-03-01") @@ -163,9 +160,6 @@ explain select * from m4 where dt > '2021-12-31' order by dt; Logical ExecutionPlan MergeSort(sort="dt ASC") LogicalView(tables="m4[p1,p2,p3,...p128]", shardCount=128, sql="SELECT `dt` FROM `m4` AS `m4` WHERE (`dt` > ?) ORDER BY `dt`") -HitCache:false -Source:PLAN_CACHE -TemplateId: e67c62d4 explain select * from m4 where dt >= '2021-12-30' and dt < '2023-01-01' order by dt; Logical ExecutionPlan MergeSort(sort="dt ASC") diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_toweeks.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_toweeks.result index 23c194279..111f8dd90 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_toweeks.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_toweeks.result @@ -32,9 +32,6 @@ d explain select * from w1 where d = '0000-01-01'; Logical ExecutionPlan PhyTableOperation(tables="w1[p9]", sql="SELECT `w1`.`d` FROM ? AS `w1` WHERE (`w1`.`d` = ?)", params="0000-01-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: 164ca609 explain select * from w1 where d = '0000-01-02'; Logical ExecutionPlan PhyTableOperation(tables="w1[p9]", sql="SELECT `w1`.`d` FROM ? AS `w1` WHERE (`w1`.`d` = ?)", params="0000-01-02") @@ -155,9 +152,6 @@ explain select * from w4 where dt > '2021-12-31' order by dt; Logical ExecutionPlan MergeSort(sort="dt ASC") LogicalView(tables="w4[p1,p2,p3,...p128]", shardCount=128, sql="SELECT `dt` FROM `w4` AS `w4` WHERE (`dt` > ?) ORDER BY `dt`") -HitCache:false -Source:PLAN_CACHE -TemplateId: 23a70a5e explain select * from w4 where dt >= '2021-12-30' and dt < '2022-01-01' order by dt; Logical ExecutionPlan PhyTableOperation(tables="w4[p53]", sql="SELECT `w4`.`dt` FROM ? AS `w4` WHERE ((`w4`.`dt` >= ?) AND (`w4`.`dt` < ?)) ORDER BY `dt`", params="2022-01-01,2021-12-30") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_toweeks2.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_toweeks2.result index 526e18f2f..7305a15c3 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_toweeks2.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTest/test_part_func_toweeks2.result @@ -9,16 +9,10 @@ partitions 8; explain select dt from hash_to_weeks where dt = '2021-12-25'; Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p8]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2021-12-25") -HitCache:false -Source:PLAN_CACHE -TemplateId: 10895681 ## two-week explain select dt from hash_to_weeks where dt = '2021-12-26'; Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p4]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2021-12-26") -HitCache:true -Source:PLAN_CACHE -TemplateId: 10895681 explain select dt from hash_to_weeks where dt = '2021-12-27'; Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p4]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2021-12-27") @@ -32,9 +26,6 @@ PhyTableOperation(tables="hash_to_weeks[p4]", sql="SELECT `hash_to_weeks`.`dt` A explain select dt from hash_to_weeks where dt = '2022-01-02'; Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p7]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2022-01-02") -HitCache:true -Source:PLAN_CACHE -TemplateId: 10895681 explain select dt from hash_to_weeks where dt = '2022-01-03'; Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p7]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2022-01-03") @@ -43,7 +34,8 @@ Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p7]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2022-01-08") explain select dt from hash_to_weeks where dt between '2022-01-02' and '2022-01-08'; Logical ExecutionPlan -PhyTableOperation(tables="hash_to_weeks[p7]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` BETWEEN ? AND ?)", params="2022-01-08,2022-01-02") +Gather(concurrent=true) + LogicalView(tables="hash_to_weeks[p7]", sql="SELECT `dt` FROM `hash_to_weeks` AS `hash_to_weeks` WHERE (`dt` BETWEEN ? AND ?)") explain select dt from hash_to_weeks where dt between '2022-01-01' and '2022-01-08'; Logical ExecutionPlan Gather(concurrent=true) diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_local_part_ttl_tbl.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_local_part_ttl_tbl.result new file mode 100644 index 000000000..cba6f92f3 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_local_part_ttl_tbl.result @@ -0,0 +1 @@ +toBeAdd \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_local_part_ttl_tbl.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_local_part_ttl_tbl.test.yml new file mode 100644 index 000000000..bd0179f31 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_local_part_ttl_tbl.test.yml @@ -0,0 +1,20 @@ +## DISABLE_FAST_SQL_PARSER + +create table t_order +( + id int, + gmt_created datetime not null, + order_id int not null, + primary key(id, gmt_created) +) +partition by key(order_id) partitions 2; + +ALTER TABLE t_order +LOCAL PARTITION BY RANGE (gmt_created) +STARTWITH '2023-01-01' +INTERVAL 1 MONTH +EXPIRE AFTER 6 +PRE ALLOCATE 3; + +CREATE TABLE t_order_oss + LIKE t_order ENGINE = 'local_disk' ARCHIVE_MODE = 'TTL'; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_part_ttl_tbl.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_part_ttl_tbl.result new file mode 100644 index 000000000..cba6f92f3 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_part_ttl_tbl.result @@ -0,0 +1 @@ +toBeAdd \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_part_ttl_tbl.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_part_ttl_tbl.test.yml new file mode 100644 index 000000000..fa32eb1b5 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_part_ttl_tbl.test.yml @@ -0,0 +1,182 @@ +## DISABLE_FAST_SQL_PARSER + +## orginal +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +partition by key(a) partitions 8 +local partition by range(b) +STARTWITH '2021-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 12 +PRE ALLOCATE 6; + + +# -- 语法 +# (SUB)PARTITION BY RANGE COLUMNS (gmt_modified) -- 分区列 +# [STARTWITH $startWithDate] -- 分区初始时间 +# INTERVAL $intervalCount $intervalUnit -- 分区间隔 +# [EXPIRE AFTER $expireAfterCount] -- expireAfterCount个间隔后失效 +# [PRE ALLOCATE $preAllocateCount] -- 提前preAllocateCount个间隔创建分区 +# [PIVOTDATE $pivotDate] -- 基准时间,默认为NOW() +# ; + +## new +create table ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +partition by key(a) partitions 8 +subpartition by range columns(b) +STARTWITH '2021-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 12 +PRE ALLOCATE 6 +PIVOTDATE NOW(); + + +create table pttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +subpartition by range columns(b) +STARTWITH '2022-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 12 +PRE ALLOCATE 6 +PIVOTDATE NOW(); + +#CREATE TABLE `pttl_t1` ( +#`a` int(11) NOT NULL AUTO_INCREMENT, +#`b` datetime DEFAULT CURRENT_TIMESTAMP, +#PRIMARY KEY (`a`), +#KEY `auto_shard_key_b` USING BTREE (`b`) +#) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +#PARTITION BY KEY(`a`) +#PARTITIONS 2 +#SUBPARTITION BY RANGE COLUMNS(`b`) +#(SUBPARTITION `sp20220101` VALUES LESS THAN ('2022-01-01 00:00:00'), +#SUBPARTITION `sp20220701` VALUES LESS THAN ('2022-07-01 00:00:00'), +#SUBPARTITION `sp20230101` VALUES LESS THAN ('2023-01-01 00:00:00'), +#SUBPARTITION `sp20230701` VALUES LESS THAN ('2023-07-01 00:00:00'), +#SUBPARTITION `sp20240101` VALUES LESS THAN ('2024-01-01 00:00:00'), +#SUBPARTITION `sp20240701` VALUES LESS THAN ('2024-07-01 00:00:00'), +#SUBPARTITION `sp20250101` VALUES LESS THAN ('2025-01-01 00:00:00'), +#SUBPARTITION `sp20250701` VALUES LESS THAN ('2025-07-01 00:00:00'), +#SUBPARTITION `sp20260101` VALUES LESS THAN ('2026-01-01 00:00:00'), +#SUBPARTITION `sp20260701` VALUES LESS THAN ('2026-07-01 00:00:00'), +#SUBPARTITION `spmax` VALUES LESS THAN (MAXVALUE)) + +alter table pttl_t1 split subpartition spmax into ( +SUBPARTITION `sp20270101` VALUES LESS THAN ('2027-01-01 00:00:00'), +SUBPARTITION `spmax` VALUES LESS THAN (maxvalue) +); + + +create table ttl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_EXPR = '`b` | EXPIRE AFTER 5 MINUTE | TIMEZONE=+08:00' +partition by key(a) partitions 2; + +create table ttl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_LEVEL = 'ROW' +TTL_EXPR = `b` EXPIRE AFTER 5 MINUTE TIMEZONE '+08:00' +TTL_JOB = CRON '* */2 * * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + + +create table rl_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_LEVEL = 'ROW' +TTL_EXPR = `b` EXPIRE AFTER 5 MINUTE TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + + +insert into rl_ttl_t1(a, b) values (null, now()); +insert into rl_ttl_t1(a, b) select null, date_format( b, b - interval '5' DAY) from rl_ttl_t1 limit 10000; + +select b - interval '5' DAY ; + + +create table nottl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + + +## +## TTL_ENABLE = {'ON'|'OFF'|} +## TTL_LEVEL = {'ROW'|'PART'|'SUBPART'|'LOCAL'} +## TTL_EXPR = '`column` INTERVAL 6 MONTH' +## + + +create table ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +ENA +partition by key(a) partitions 3; + + + + + + +insert into bmsql_history +(hist_id, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, h_date,h_amount, h_data ) + +select +null, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, date_format( h_date, h_date - interval minute(h_date) * 60 + second(h_date) HOUR),h_amount, h_data +from +bmsql_history; + + +date_format( b, b - interval '5' DAY) +date_format( h_date, h_date - interval minute(h_date) * 60 + second(h_date) HOUR) + + + +insert into bmsql_history (hist_id, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, h_date,h_amount, h_data ) select null, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, date_format( h_date, h_date - interval minute(h_date) * 60 + second(h_date) HOUR),h_amount, h_data from bmsql_history order by h_date limit 50000; + + + + +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 6 MONTH TIMEZONE '+08:00' +partition by key(a) partitions 2; + + +CREATE TABLE oss_t1 +LIKE ttl_t1 ENGINE = 'local_disk' ARCHIVE_MODE = 'TTL'; + + + + diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_part_ttl_tbl2.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_part_ttl_tbl2.test.yml new file mode 100644 index 000000000..e64a864a0 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/create_part_ttl_tbl2.test.yml @@ -0,0 +1,19 @@ +## DISABLE_FAST_SQL_PARSER + +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 6 MONTH TIMEZONE '+08:00' +partition by key(a) partitions 2; + + +CREATE TABLE oss_t1 +LIKE ttl_t1 ENGINE = 'local_disk' ARCHIVE_MODE = 'TTL'; + + + +## 手动触发行级ttl清理数据的命令 +alter Table ttl_t1 cleanup expaired data; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/testcase.config.yml new file mode 100644 index 000000000..ddebf8e38 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTtlTest/testcase.config.yml @@ -0,0 +1 @@ +show_full_grp \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test1.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test1.result index 97f018387..1117d23e2 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test1.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test1.result @@ -11,7 +11,7 @@ CREATE TABLE `nation` ( ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`N_NATIONKEY`) PARTITIONS 8; -explain /*+TDDL:IN_SUB_QUERY_THRESHOLD=8*/ SELECT +explain /*TDDL:IN_SUB_QUERY_THRESHOLD=10000*/ SELECT nation.n_nationkey, nation.n_regionkey, nation.n_comment, @@ -32,4 +32,5 @@ WHERE AND nation.n_nationkey IS NOT NULL AND nation.n_nationkey BETWEEN 3.805471129478495 AND 4.758352957397205; Logical ExecutionPlan -PhyTableOperation(tables="nation[p8]", sql="SELECT `nation`.`N_NATIONKEY` AS `n_nationkey`, `nation`.`N_REGIONKEY` AS `n_regionkey`, `nation`.`N_COMMENT` AS `n_comment`, `nation`.`N_NAME` AS `n_name` FROM ? AS `nation` WHERE ((`nation`.`N_NATIONKEY` IN (?)) AND (`nation`.`N_NATIONKEY` IN (?)) AND ((`nation`.`N_NATIONKEY` + ?) <= ?) AND (`nation`.`N_NATIONKEY` IN (?)) AND (`nation`.`N_NATIONKEY` IS NOT NULL) AND (`nation`.`N_NATIONKEY` BETWEEN ? AND ?))", params="Raw(4,1.9768277360857997E9),3.805471129478495,5.27214097707928,Raw(4,4.472058352208863E8,1.333687324233481E9,4.1576415757607274E7),1,4.758352957397205,Raw(4,8.81152213174817E8,3.389451686261133E8,1.6448133002964172E9)") \ No newline at end of file +Gather(concurrent=true) + LogicalView(tables="nation[p8]", sql="SELECT `N_NATIONKEY` AS `n_nationkey`, `N_REGIONKEY` AS `n_regionkey`, `N_COMMENT` AS `n_comment`, `N_NAME` AS `n_name` FROM `nation` AS `nation` WHERE (((`N_NATIONKEY` + ?) <= ?) AND (`N_NATIONKEY` IN(?)) AND (`N_NATIONKEY` IN(?)) AND (`N_NATIONKEY` IN(?)) AND (`N_NATIONKEY` BETWEEN ? AND ?) AND (`N_NATIONKEY` IS NOT NULL))", pruningInfo="all size:10*1(part), pruning size:7") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test1.test.yml b/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test1.test.yml index 0f6e2ef82..dbadb7cfc 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test1.test.yml +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test1.test.yml @@ -13,7 +13,7 @@ CREATE TABLE `nation` ( PARTITION BY KEY(`N_NATIONKEY`) PARTITIONS 8; -explain /*+TDDL:IN_SUB_QUERY_THRESHOLD=8*/ SELECT +explain /*TDDL:IN_SUB_QUERY_THRESHOLD=10000*/ SELECT nation.n_nationkey, nation.n_regionkey, nation.n_comment, diff --git a/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test3.result b/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test3.result index de5cdeb0b..6d4ea3838 100644 --- a/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test3.result +++ b/polardbx-test/src/test/resources/partition/env/PartitionTableTypeCastTest/test3.result @@ -22,11 +22,13 @@ FROM nation WHERE N_NATIONKEY = 100 AND N_NATIONKEY < 100.5; Logical ExecutionPlan -PhyTableOperation(tables="nation[p2]", sql="SELECT `nation`.`N_NATIONKEY`, `nation`.`N_NAME`, `nation`.`N_REGIONKEY`, `nation`.`N_COMMENT` FROM ? AS `nation` WHERE ((`nation`.`N_NATIONKEY` = ?) AND (`nation`.`N_NATIONKEY` < ?))", params="100.5,100") +Gather(concurrent=true) + LogicalView(tables="nation[p2]", sql="SELECT `N_NATIONKEY`, `N_NAME`, `N_REGIONKEY`, `N_COMMENT` FROM `nation` AS `nation` WHERE ((`N_NATIONKEY` = ?) AND (`N_NATIONKEY` < ?))") EXPLAIN SELECT * FROM nation WHERE N_NATIONKEY = 100 AND N_NATIONKEY < 100.5 AND N_NATIONKEY > 99.12; Logical ExecutionPlan -PhyTableOperation(tables="nation[p2]", sql="SELECT `nation`.`N_NATIONKEY`, `nation`.`N_NAME`, `nation`.`N_REGIONKEY`, `nation`.`N_COMMENT` FROM ? AS `nation` WHERE ((`nation`.`N_NATIONKEY` = ?) AND (`nation`.`N_NATIONKEY` < ?) AND (`nation`.`N_NATIONKEY` > ?))", params="100.5,100,99.12") \ No newline at end of file +Gather(concurrent=true) + LogicalView(tables="nation[p2]", sql="SELECT `N_NATIONKEY`, `N_NAME`, `N_REGIONKEY`, `N_COMMENT` FROM `nation` AS `nation` WHERE ((`N_NATIONKEY` = ?) AND (`N_NATIONKEY` < ?) AND (`N_NATIONKEY` > ?))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/ShowDalTest/show_dal_columnar_test.result b/polardbx-test/src/test/resources/partition/env/ShowDalTest/show_dal_columnar_test.result new file mode 100644 index 000000000..0057cef7c --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/ShowDalTest/show_dal_columnar_test.result @@ -0,0 +1,129 @@ +DROP TABLE IF EXISTS `triangle`; +CREATE TABLE `triangle` ( + `sidea` DOUBLE, + `sideb` DOUBLE, + `sidec` DOUBLE GENERATED ALWAYS AS (SQRT(sidea * sidea + sideb * sideb)) +) ENGINE = InnoDB DEFAULT CHARSET = utf8; +SHOW INDEX FROM triangle; +Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation,Cardinality,Sub_part,Packed,Null,Index_type,Comment,Index_comment +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/SHOW INDEX FROM triangle; +Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation,Cardinality,Sub_part,Packed,Null,Index_type,Comment,Index_comment +SHOW COLUMNS FROM triangle; +Field,Type,Null,Key,Default,Extra +sidea,double,YES,,null, +sideb,double,YES,,null, +sidec,double,YES,,null,VIRTUAL GENERATED +/*+TDDL:ENABLE_LOGICAL_TABLE_META=ture*/SHOW COLUMNS FROM triangle; +Field,Type,Null,Key,Default,Extra +sidea,double,YES,,null, +sideb,double,YES,,null, +sidec,double,YES,,null,VIRTUAL GENERATED +DROP TABLE IF EXISTS `triangle`; +DROP TABLE IF EXISTS fi3; +CREATE TABLE fi3 ( + id INT PRIMARY KEY, + col1 INT, + col2 INT, + col3 CHAR(16) +); +/*+TDDL:CMD_EXTRA(ENABLE_CREATE_EXPRESSION_INDEX=TRUE,ENABLE_UNIQUE_KEY_ON_GEN_COL=TRUE)*/ALTER TABLE fi3 + ADD UNIQUE LOCAL INDEX func_index (SUBSTRING(col3, 1, 2)); +SHOW INDEX FROM fi3; +Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation,Cardinality,Sub_part,Packed,Null,Index_type,Comment,Index_comment +fi3,0,PRIMARY,1,id,A,0,null,null,,BTREE,, +fi3,0,func_index,1,func_index$0,A,0,null,null,YES,BTREE,, +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/SHOW INDEX FROM fi3; +Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation,Cardinality,Sub_part,Packed,Null,Index_type,Comment,Index_comment +fi3,0,func_index,1,func_index$0,A,0,0,null,YES,BTREE,, +fi3,0,PRIMARY,1,id,A,0,0,null,,BTREE,, +SHOW COLUMNS FROM fi3; +Field,Type,Null,Key,Default,Extra +id,int(11),NO,PRI,null, +col1,int(11),YES,,null, +col2,int(11),YES,,null, +col3,char(16),YES,,null, +func_index$0,char(16),YES,UNI,null,VIRTUAL GENERATED +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/SHOW COLUMNS FROM fi3; +Field,Type,Null,Key,Default,Extra +col1,int(11),YES,,null, +col2,int(11),YES,,null, +col3,char(16),YES,,null, +func_index$0,char(16),YES,UNI,(SUBSTRING(`col3` FROM 1 FOR 2)),VIRTUAL GENERATED +id,int(11),NO,PRI,null, +DROP TABLE IF EXISTS fi3; +DROP TABLE IF EXISTS sp_tbl_list_key_tp; +CREATE TABLE sp_tbl_list_key_tp ( + id int, + country varchar(64), + city varchar(64), + order_time datetime NOT NULL, + PRIMARY KEY (id) +) +PARTITION BY LIST COLUMNS (country, city) +SUBPARTITION BY KEY (id) SUBPARTITIONS 4 ( + PARTITION p1 VALUES IN (('China', 'Hangzhou')), + PARTITION p2 VALUES IN (('Russian', 'Moscow')), + PARTITION pd VALUES IN (DEFAULT) +); +SHOW INDEX FROM sp_tbl_list_key_tp; +Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation,Cardinality,Sub_part,Packed,Null,Index_type,Comment,Index_comment +sp_tbl_list_key_tp,0,PRIMARY,1,id,A,0,null,null,,BTREE,, +sp_tbl_list_key_tp,1,auto_shard_key_country_city,1,country,A,0,null,null,YES,BTREE,, +sp_tbl_list_key_tp,1,auto_shard_key_country_city,2,city,A,0,null,null,YES,BTREE,, +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/SHOW INDEX FROM sp_tbl_list_key_tp; +Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation,Cardinality,Sub_part,Packed,Null,Index_type,Comment,Index_comment +sp_tbl_list_key_tp,1,auto_shard_key_country_city,2,city,A,0,0,null,YES,BTREE,, +sp_tbl_list_key_tp,1,auto_shard_key_country_city,1,country,A,0,0,null,YES,BTREE,, +sp_tbl_list_key_tp,0,PRIMARY,1,id,A,0,0,null,,BTREE,, +SHOW COLUMNS FROM sp_tbl_list_key_tp; +Field,Type,Null,Key,Default,Extra +id,int(11),NO,PRI,null, +country,varchar(64),YES,MUL,null, +city,varchar(64),YES,,null, +order_time,datetime,NO,,null, +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/SHOW COLUMNS FROM sp_tbl_list_key_tp; +Field,Type,Null,Key,Default,Extra +city,varchar(64),YES,,null, +country,varchar(64),YES,MUL,null, +id,int(11),NO,PRI,null, +order_time,datetime,NO,,null, +DROP TABLE IF EXISTS sp_tbl_list_key_tp; +DROP TABLE IF EXISTS user; +CREATE TABLE user ( + user_id bigint, + name varchar(10), + addr varchar(30), + GLOBAL INDEX `g_i_name`(name) PARTITION BY HASH (name), + PRIMARY KEY (user_id) +) +PARTITION BY KEY (user_id); +SHOW INDEX FROM user; +Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation,Cardinality,Sub_part,Packed,Null,Index_type,Comment,Index_comment +user,0,PRIMARY,1,user_id,A,0,null,null,,BTREE,, +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/SHOW INDEX FROM user; +Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation,Cardinality,Sub_part,Packed,Null,Index_type,Comment,Index_comment +user,0,PRIMARY,1,user_id,A,0,0,null,,BTREE,, +SHOW COLUMNS FROM user; +Field,Type,Null,Key,Default,Extra +user_id,bigint(20),NO,PRI,null, +name,varchar(10),YES,,null, +addr,varchar(30),YES,,null, +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/SHOW COLUMNS FROM user; +Field,Type,Null,Key,Default,Extra +addr,varchar(30),YES,,null, +name,varchar(10),YES,,null, +user_id,bigint(20),NO,PRI,null, +DROP INDEX `g_i_name` ON user; +DROP TABLE IF EXISTS user; +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/SHOW ENGINES +Engine,Support,Comment,Transaction,XA,Savepoints +CSV,YES,CSV storage engine,NO,NO,NO +MRG_MYISAM,YES,Collection of identical MyISAM tables,NO,NO,NO +PERFORMANCE_SCHEMA,YES,Performance Schema,NO,NO,NO +BLACKHOLE,YES,/dev/null storage engine (anything you write to it disappears),NO,NO,NO +MyISAM,YES,MyISAM storage engine,NO,NO,NO +MEMORY,YES,Hash based, stored in memory, useful for temporary tables,NO,NO,NO +ARCHIVE,YES,Archive storage engine,NO,NO,NO +InnoDB,DEFAULT,Supports transactions, row-level locking, and foreign keys,YES,YES,YES +FEDERATED,NO,Federated MySQL storage engine,null,null,null +Sequence,YES,Sequence Storage Engine Helper,NO,NO,NO \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/ShowDalTest/show_dal_columnar_test.test.yml b/polardbx-test/src/test/resources/partition/env/ShowDalTest/show_dal_columnar_test.test.yml new file mode 100644 index 000000000..607711ffe --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/ShowDalTest/show_dal_columnar_test.test.yml @@ -0,0 +1,73 @@ +#test show dal with generated column +DROP TABLE IF EXISTS `triangle`; +CREATE TABLE `triangle` ( +`sidea` DOUBLE, +`sideb` DOUBLE, +`sidec` DOUBLE AS (SQRT(sidea * sidea + sideb * sideb)) +) ENGINE = InnoDB DEFAULT CHARSET = utf8; +SHOW INDEX FROM triangle; +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/ SHOW INDEX FROM triangle; +SHOW COLUMNS FROM triangle; +/*+TDDL:ENABLE_LOGICAL_TABLE_META=ture*/ SHOW COLUMNS FROM triangle; +DROP TABLE IF EXISTS `triangle`; + +#test show dal with function index +DROP TABLE IF EXISTS fi3; +CREATE TABLE fi3 ( +id INT primary key, +col1 INT, +col2 INT, +col3 CHAR(16) +); +/*+TDDL:CMD_EXTRA(ENABLE_CREATE_EXPRESSION_INDEX=TRUE,ENABLE_UNIQUE_KEY_ON_GEN_COL=TRUE)*/ +alter table fi3 add local unique index func_index(SUBSTRING(col3, 1, 2)); + +SHOW INDEX FROM fi3; +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/ SHOW INDEX FROM fi3; +SHOW COLUMNS FROM fi3; +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/ SHOW COLUMNS FROM fi3; +DROP TABLE IF EXISTS fi3; + +#test show dal with two level partitions +DROP TABLE IF EXISTS sp_tbl_list_key_tp; +CREATE TABLE sp_tbl_list_key_tp( +id int, +country varchar(64), +city varchar(64), +order_time datetime not null, +PRIMARY KEY(id) +) +PARTITION BY LIST COLUMNS(country,city) +SUBPARTITION BY KEY(id) SUBPARTITIONS 4 +( +PARTITION p1 VALUES IN (('China','Hangzhou')), +PARTITION p2 VALUES IN (('Russian','Moscow')), +PARTITION pd VALUES IN (DEFAULT) +); + +SHOW INDEX FROM sp_tbl_list_key_tp; +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/ SHOW INDEX FROM sp_tbl_list_key_tp; +SHOW COLUMNS FROM sp_tbl_list_key_tp; +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/ SHOW COLUMNS FROM sp_tbl_list_key_tp; +DROP TABLE IF EXISTS sp_tbl_list_key_tp; + +#test show dal with global index +DROP TABLE IF EXISTS user; +CREATE TABLE user( +user_id bigint, +name varchar(10), +addr varchar(30), +GLOBAL INDEX `g_i_name` (name) PARTITION BY HASH(name), +PRIMARY KEY(user_id) +) PARTITION BY KEY(user_id); + +SHOW INDEX FROM user; +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/ SHOW INDEX FROM user; +SHOW COLUMNS FROM user; +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/ SHOW COLUMNS FROM user; +DROP INDEX `g_i_name` on user; +DROP TABLE IF EXISTS user; + +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/ SHOW ENGINES; +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/ SHOW STATUS; +/*+TDDL:ENABLE_LOGICAL_TABLE_META=true*/ SHOW VARIABLES; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/ShowDalTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/ShowDalTest/testcase.config.yml index c5fa448d6..5d9e7947b 100644 --- a/polardbx-test/src/test/resources/partition/env/ShowDalTest/testcase.config.yml +++ b/polardbx-test/src/test/resources/partition/env/ShowDalTest/testcase.config.yml @@ -1,3 +1,4 @@ test_show_profiles test_query_tables -select_db \ No newline at end of file +select_db +show_dal_columnar_test \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_hash.result b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_hash.result new file mode 100644 index 000000000..6487d96ba --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_hash.result @@ -0,0 +1,97 @@ +## DISABLE_FAST_SQL_PARSER +CREATE TABLE part_ts_hash ( +a INT, +b varchar(32), +ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (a) +) +partition by hash( unix_timestamp(ts) ) +partitions 8; +set time_zone='+08:00'; +insert into part_ts_hash values (1, '+08:00/shanghai', '2024-10-01 12:00:00'); +set time_zone='+09:00'; +insert into part_ts_hash values (2, '+09:00/tokyo', '2024-10-01 12:00:00'); +set time_zone='-05:00'; +insert into part_ts_hash values (3, '-05:00/chicago', '2024-10-01 12:00:00'); +set time_zone='+08:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +1,+08:00/shanghai,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p2]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +select * from part_ts_hash where ts = '2024-10-01 11:00:00'; +a,b,ts +2,+09:00/tokyo,2024-10-01 11:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 11:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p1]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 11:00:00") +select * from part_ts_hash where ts = '2024-10-02 01:00:00'; +a,b,ts +3,-05:00/chicago,2024-10-02 01:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-02 01:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p6]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-02 01:00:00") +set time_zone='+09:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +2,+09:00/tokyo,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p1]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='-05:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +3,-05:00/chicago,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p6]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +########## +set time_zone='Asia/Shanghai'; +insert into part_ts_hash values (4, '+08:00/shanghai', '2024-10-01 12:00:00'); +set time_zone='Asia/Tokyo'; +insert into part_ts_hash values (5, '+09:00/tokyo', '2024-10-01 12:00:00'); +set time_zone='America/Chicago'; +insert into part_ts_hash values (6, '-05:00/chicago', '2024-10-01 12:00:00'); +set time_zone='Asia/Shanghai'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +1,+08:00/shanghai,2024-10-01 12:00:00.0 +4,+08:00/shanghai,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p2]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='Asia/Tokyo'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +2,+09:00/tokyo,2024-10-01 12:00:00.0 +5,+09:00/tokyo,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p1]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='America/Chicago'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +3,-05:00/chicago,2024-10-01 12:00:00.0 +6,-05:00/chicago,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p6]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +## set time_zone='+09:00' +set time_zone='Asia/Tokyo'; +## shanghai time: "2024-10-01 11:00:00" +select unix_timestamp('2024-10-01 12:00:00'); +unix_timestamp('2024-10-01 12:00:00') +1727751600 +select CONVERT_TZ(FROM_UNIXTIME( unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'),'Asia/Tokyo','Asia/Shanghai'); +CONVERT_TZ(FROM_UNIXTIME(unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'), 'Asia/Tokyo', 'Asia/Shanghai') +2024-10-01 11:00:00.0 +## CST : set time_zone='-05:00' / set time_zone='EST' +set time_zone='America/Chicago'; +## shanghai time: "2024-10-02 01:00:00" +select unix_timestamp('2024-10-01 12:00:00'); +unix_timestamp('2024-10-01 12:00:00') +1727802000 +select CONVERT_TZ(FROM_UNIXTIME( unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'),'America/Chicago','Asia/Shanghai'); +CONVERT_TZ(FROM_UNIXTIME(unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'), 'America/Chicago', 'Asia/Shanghai') +2024-10-02 01:00:00.0 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_hash.test.yml b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_hash.test.yml new file mode 100644 index 000000000..44837c62c --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_hash.test.yml @@ -0,0 +1,73 @@ +## DISABLE_FAST_SQL_PARSER + +CREATE TABLE part_ts_hash ( +a INT, +b varchar(32), +ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (a) +) +partition by hash( unix_timestamp(ts) ) +partitions 8; + +set time_zone='+08:00'; +insert into part_ts_hash values (1, '+08:00/shanghai', '2024-10-01 12:00:00'); + +set time_zone='+09:00'; +insert into part_ts_hash values (2, '+09:00/tokyo', '2024-10-01 12:00:00'); + +set time_zone='-05:00'; +insert into part_ts_hash values (3, '-05:00/chicago', '2024-10-01 12:00:00'); + +set time_zone='+08:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +select * from part_ts_hash where ts = '2024-10-01 11:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 11:00:00'; +select * from part_ts_hash where ts = '2024-10-02 01:00:00'; +explain select * from part_ts_hash where ts = '2024-10-02 01:00:00'; + +set time_zone='+09:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; + +set time_zone='-05:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; + + +########## + +set time_zone='Asia/Shanghai'; +insert into part_ts_hash values (4, '+08:00/shanghai', '2024-10-01 12:00:00'); + +set time_zone='Asia/Tokyo'; +insert into part_ts_hash values (5, '+09:00/tokyo', '2024-10-01 12:00:00'); + +set time_zone='America/Chicago'; +insert into part_ts_hash values (6, '-05:00/chicago', '2024-10-01 12:00:00'); + +set time_zone='Asia/Shanghai'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; + +set time_zone='Asia/Tokyo'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; + +set time_zone='America/Chicago'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; + + + ## set time_zone='+09:00' +set time_zone='Asia/Tokyo'; + ## shanghai time: "2024-10-01 11:00:00" +select unix_timestamp('2024-10-01 12:00:00'); +select CONVERT_TZ(FROM_UNIXTIME( unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'),'Asia/Tokyo','Asia/Shanghai'); + + ## CST : set time_zone='-05:00' / set time_zone='EST' +set time_zone='America/Chicago'; + ## shanghai time: "2024-10-02 01:00:00" +select unix_timestamp('2024-10-01 12:00:00'); +select CONVERT_TZ(FROM_UNIXTIME( unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'),'America/Chicago','Asia/Shanghai'); + diff --git a/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_rng.result b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_rng.result new file mode 100644 index 000000000..cd5fc18f4 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_rng.result @@ -0,0 +1,78 @@ +## DISABLE_FAST_SQL_PARSER +set LOGICAL_DB_TIME_ZONE='Asia/Shanghai'; +set time_zone='+08:00'; +drop table if exists part_ts; +CREATE TABLE if not exists part_ts ( +a INT, +b varchar(32), +ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (a) +) +partition by range( unix_timestamp(ts) ) +( + partition p1 values less than (unix_timestamp('2024-09-30 00:00:00')), + partition p2 values less than (unix_timestamp('2024-10-01 12:00:00')), + partition p3 values less than (unix_timestamp('2024-10-01 12:30:00')), + partition p4 values less than (unix_timestamp('2024-10-02 01:00:00')), + partition p5 values less than (unix_timestamp('2024-10-02 01:30:00')), + partition p6 values less than (unix_timestamp('2024-10-03 00:00:00')), + partition p7 values less than (maxvalue) +); +set time_zone='+08:00'; +insert into part_ts values (1, '+08:00/shanghai', '2024-10-01 12:00:00'); +set time_zone='+09:00'; +insert into part_ts values (2, '+09:00/tokyo', '2024-10-01 12:00:00'); +set time_zone='-05:00'; +insert into part_ts values (3, '-05:00/chicago', '2024-10-01 12:00:00'); +set time_zone='+08:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +1,+08:00/shanghai,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p3]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='+09:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +2,+09:00/tokyo,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p2]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='-05:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +3,-05:00/chicago,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p5]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") +########## +set time_zone='Asia/Shanghai'; +insert into part_ts values (4, '+08:00/shanghai', '2024-10-01 12:00:00'); +set time_zone='Asia/Tokyo'; +insert into part_ts values (5, '+09:00/tokyo', '2024-10-01 12:00:00'); +set time_zone='America/Chicago'; +insert into part_ts values (6, '-05:00/chicago', '2024-10-01 12:00:00'); +set time_zone='Asia/Shanghai'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +1,+08:00/shanghai,2024-10-01 12:00:00.0 +4,+08:00/shanghai,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p3]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='Asia/Tokyo'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +2,+09:00/tokyo,2024-10-01 12:00:00.0 +5,+09:00/tokyo,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p2]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='America/Chicago'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +3,-05:00/chicago,2024-10-01 12:00:00.0 +6,-05:00/chicago,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p5]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_rng.test.yml b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_rng.test.yml new file mode 100644 index 000000000..e46a8764d --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_rng.test.yml @@ -0,0 +1,69 @@ +## DISABLE_FAST_SQL_PARSER + +set LOGICAL_DB_TIME_ZONE='Asia/Shanghai'; + +set time_zone='+08:00'; +drop table if exists part_ts; +CREATE TABLE if not exists part_ts ( +a INT, +b varchar(32), +ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (a) +) +partition by range( unix_timestamp(ts) ) +( + partition p1 values less than (unix_timestamp('2024-09-30 00:00:00')), + partition p2 values less than (unix_timestamp('2024-10-01 12:00:00')), + partition p3 values less than (unix_timestamp('2024-10-01 12:30:00')), + partition p4 values less than (unix_timestamp('2024-10-02 01:00:00')), + partition p5 values less than (unix_timestamp('2024-10-02 01:30:00')), + partition p6 values less than (unix_timestamp('2024-10-03 00:00:00')), + partition p7 values less than (maxvalue) +); + +set time_zone='+08:00'; +insert into part_ts values (1, '+08:00/shanghai', '2024-10-01 12:00:00'); + +set time_zone='+09:00'; +insert into part_ts values (2, '+09:00/tokyo', '2024-10-01 12:00:00'); + +set time_zone='-05:00'; +insert into part_ts values (3, '-05:00/chicago', '2024-10-01 12:00:00'); + +set time_zone='+08:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='+09:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='-05:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + + +########## + + +set time_zone='Asia/Shanghai'; +insert into part_ts values (4, '+08:00/shanghai', '2024-10-01 12:00:00'); + +set time_zone='Asia/Tokyo'; +insert into part_ts values (5, '+09:00/tokyo', '2024-10-01 12:00:00'); + +set time_zone='America/Chicago'; +insert into part_ts values (6, '-05:00/chicago', '2024-10-01 12:00:00'); + +set time_zone='Asia/Shanghai'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='Asia/Tokyo'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='America/Chicago'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + diff --git a/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_tmp.test.yml b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_tmp.test.yml new file mode 100644 index 000000000..9d1872f24 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/test_set_tz_tmp.test.yml @@ -0,0 +1,99 @@ +## DISABLE_FAST_SQL_PARSER + +set LOGICAL_DB_TIME_ZONE='Asia/Shanghai'; + +set time_zone='+08:00'; +CREATE TABLE part_ts ( +a INT, +b varchar(32), +ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (ts) +) +partition by range( unix_timestamp(ts) ) +( + partition p1 values less than (unix_timestamp('2024-09-30 00:00:00')), + partition p2 values less than (unix_timestamp('2024-10-01 12:00:00')), + partition p3 values less than (unix_timestamp('2024-10-01 12:30:00')), + partition p4 values less than (unix_timestamp('2024-10-02 01:00:00')), + partition p5 values less than (unix_timestamp('2024-10-02 01:30:00')), + partition p6 values less than (unix_timestamp('2024-10-03 00:00:00')), + partition p7 values less than (maxvalue) +); + +set time_zone='UTC'; + + +set time_zone='+08:00'; +insert into part_ts values (1, '+08:00/shanghai', '2024-10-01 12:00:00'); + +set time_zone='+09:00'; +insert into part_ts values (2, '+09:00/tokyo', '2024-10-01 12:00:00'); + +set time_zone='-05:00'; +insert into part_ts values (3, '-05:00/chicago', '2024-10-01 12:00:00'); + +set time_zone='+08:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='+09:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='-05:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + + +########## + + +set time_zone='Asia/Shanghai'; +insert into part_ts values (1, '+08:00/shanghai', '2024-10-01 12:00:00'); + +set time_zone='Asia/Tokyo'; +insert into part_ts values (2, '+09:00/tokyo', '2024-10-01 12:00:00'); + +set time_zone='America/Chicago'; +insert into part_ts values (3, '-05:00/chicago', '2024-10-01 12:00:00'); + +set time_zone='Asia/Shanghai'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='Asia/Tokyo'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='America/Chicago'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +############## + +set time_zone='Asia/Tokyo'; +insert into part_ts values (5, '2008-12-31 23:59:00'); + +set time_zone='Asia/Shanghai'; +explain select * from part_ts where ts='2008-12-31 23:59:00'; +set time_zone='America/Chicago'; +explain select * from part_ts where ts='2008-12-31 23:59:00'; + +# CTT : set time_zone='+08:00' +set time_zone='Asia/Shanghai'; +## shanghai time: "2024-10-01 12:00:00" +select unix_timestamp('2024-10-01 12:00:00'); +select CONVERT_TZ('2024-10-01 12:00:00','America/Chicago','+08:00'); + +## set time_zone='+09:00' +set time_zone='Asia/Tokyo'; +## shanghai time: "2024-10-01 11:00:00" +select unix_timestamp('2024-10-01 12:00:00'); + +select CONVERT_TZ(FROM_UNIXTIME( unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'),'Asia/Tokyo','Asia/Shanghai'); + +# CST : set time_zone='-05:00' / set time_zone='EST' +set time_zone='America/Chicago'; +## shanghai time: "2024-10-02 01:00:00" +select unix_timestamp('2024-10-01 12:00:00'); +select CONVERT_TZ(FROM_UNIXTIME( unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'),'America/Chicago','Asia/Shanghai'); diff --git a/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/testcase.config.yml new file mode 100644 index 000000000..a022131bc --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TimeZoneRoutingTest/testcase.config.yml @@ -0,0 +1,2 @@ +test_set_tz_rng +test_set_tz_hash \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_d.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_d.result new file mode 100644 index 000000000..5e8d416eb --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_d.result @@ -0,0 +1,81 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set sql_mode='' +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +CREATE TABLE `ttl_t1_d_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +CREATE TABLE `ttl_t2_d_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +insert into ttl_t2_d_null values (1, null) +CREATE TABLE `ttl_t3_d_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +insert into ttl_t3_d_zero values (1, '0000-00-00 00:00:00') +CREATE TABLE `ttl_t4_d_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +insert into ttl_t4_d_both values (1, null) +insert into ttl_t4_d_both values (2, '0000-00-00 00:00:00') +insert into ttl_t4_d_both values (3, '9999-00-00 00:00:00') +insert into ttl_t4_d_both values (4, '9999-01-01 00:00:00') +insert into ttl_t4_d_both values (5, '2024-05-05 00:00:00') +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_d_empty order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_d_null order by a +a,b_val +1,null +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_d_zero order by a +a,b_val +1,0000-00-00 00:00:00 +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_d_both order by a +a,b_val +1,null +2,0000-00-00 00:00:00 +3,9999-00-00 00:00:00 +4,9999-01-01 00:00:00 +5,2024-05-05 00:00:00 +create table ttl_t1_d_empty_arc like ttl_t1_d_empty engine='columnar' archive_mode='ttl' +create table ttl_t2_d_null_arc like ttl_t2_d_null engine='columnar' archive_mode='ttl' +create table ttl_t3_d_zero_arc like ttl_t3_d_zero engine='columnar' archive_mode='ttl' +create table ttl_t4_d_both_arc like ttl_t4_d_both engine='columnar' archive_mode='ttl' +alter table ttl_t1_d_empty cleanup expired data +alter table ttl_t2_d_null cleanup expired data +alter table ttl_t3_d_zero cleanup expired data +alter table ttl_t4_d_both cleanup expired data +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_d_empty order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_d_null order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_d_zero order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_d_both order by a +a,b_val +3,9999-00-00 00:00:00 +4,9999-01-01 00:00:00 +5,2024-05-05 00:00:00 +drop table ttl_t1_d_empty +drop table ttl_t2_d_null +drop table ttl_t3_d_zero +drop table ttl_t4_d_both; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_d.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_d.test.yml new file mode 100644 index 000000000..57820b43a --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_d.test.yml @@ -0,0 +1,79 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set sql_mode=''; +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; + +CREATE TABLE `ttl_t1_d_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +CREATE TABLE `ttl_t2_d_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t2_d_null values (1, null); + +CREATE TABLE `ttl_t3_d_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t3_d_zero values (1, '0000-00-00 00:00:00'); + +CREATE TABLE `ttl_t4_d_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t4_d_both values (1, null); +insert into ttl_t4_d_both values (2, '0000-00-00 00:00:00'); +insert into ttl_t4_d_both values (3, '9999-00-00 00:00:00'); +insert into ttl_t4_d_both values (4, '9999-01-01 00:00:00'); +insert into ttl_t4_d_both values (5, '2024-05-05 00:00:00'); + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_d_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_d_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_d_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_d_both order by a; + +create table ttl_t1_d_empty_arc like ttl_t1_d_empty engine='columnar' archive_mode='ttl'; +create table ttl_t2_d_null_arc like ttl_t2_d_null engine='columnar' archive_mode='ttl'; +create table ttl_t3_d_zero_arc like ttl_t3_d_zero engine='columnar' archive_mode='ttl'; +create table ttl_t4_d_both_arc like ttl_t4_d_both engine='columnar' archive_mode='ttl'; + +alter table ttl_t1_d_empty cleanup expired data; +alter table ttl_t2_d_null cleanup expired data; +alter table ttl_t3_d_zero cleanup expired data; +alter table ttl_t4_d_both cleanup expired data; + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_d_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_d_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_d_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_d_both order by a; + +drop table ttl_t1_d_empty; +drop table ttl_t2_d_null; +drop table ttl_t3_d_zero; +drop table ttl_t4_d_both; + + + + + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_dt.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_dt.result new file mode 100644 index 000000000..325b81d13 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_dt.result @@ -0,0 +1,81 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set sql_mode='' +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +CREATE TABLE `ttl_t1_dt_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +CREATE TABLE `ttl_t2_dt_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +insert into ttl_t2_dt_null values (1, null) +CREATE TABLE `ttl_t3_dt_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +insert into ttl_t3_dt_zero values (1, '0000-00-00 00:00:00') +CREATE TABLE `ttl_t4_dt_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +insert into ttl_t4_dt_both values (1, null) +insert into ttl_t4_dt_both values (2, '0000-00-00 00:00:00') +insert into ttl_t4_dt_both values (3, '9999-00-00 00:00:00') +insert into ttl_t4_dt_both values (4, '9999-01-01 00:00:00') +insert into ttl_t4_dt_both values (5, '2024-05-05 00:00:00') +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_dt_empty order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_dt_null order by a +a,b_val +1,null +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_dt_zero order by a +a,b_val +1,0000-00-00 00:00:00 +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_dt_both order by a +a,b_val +1,null +2,0000-00-00 00:00:00 +3,9999-00-00 00:00:00 +4,9999-01-01 00:00:00 +5,2024-05-05 00:00:00 +create table ttl_t1_dt_empty_arc like ttl_t1_dt_empty engine='columnar' archive_mode='ttl' +create table ttl_t2_dt_null_arc like ttl_t2_dt_null engine='columnar' archive_mode='ttl' +create table ttl_t3_dt_zero_arc like ttl_t3_dt_zero engine='columnar' archive_mode='ttl' +create table ttl_t4_dt_both_arc like ttl_t4_dt_both engine='columnar' archive_mode='ttl' +alter table ttl_t1_dt_empty cleanup expired data +alter table ttl_t2_dt_null cleanup expired data +alter table ttl_t3_dt_zero cleanup expired data +alter table ttl_t4_dt_both cleanup expired data +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_dt_empty order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_dt_null order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_dt_zero order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_dt_both order by a +a,b_val +3,9999-00-00 00:00:00 +4,9999-01-01 00:00:00 +5,2024-05-05 00:00:00 +drop table ttl_t1_dt_empty +drop table ttl_t2_dt_null +drop table ttl_t3_dt_zero +drop table ttl_t4_dt_both; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_dt.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_dt.test.yml new file mode 100644 index 000000000..595a250c1 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_dt.test.yml @@ -0,0 +1,79 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set sql_mode=''; +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; + +CREATE TABLE `ttl_t1_dt_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +CREATE TABLE `ttl_t2_dt_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t2_dt_null values (1, null); + +CREATE TABLE `ttl_t3_dt_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t3_dt_zero values (1, '0000-00-00 00:00:00'); + +CREATE TABLE `ttl_t4_dt_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t4_dt_both values (1, null); +insert into ttl_t4_dt_both values (2, '0000-00-00 00:00:00'); +insert into ttl_t4_dt_both values (3, '9999-00-00 00:00:00'); +insert into ttl_t4_dt_both values (4, '9999-01-01 00:00:00'); +insert into ttl_t4_dt_both values (5, '2024-05-05 00:00:00'); + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_dt_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_dt_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_dt_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_dt_both order by a; + +create table ttl_t1_dt_empty_arc like ttl_t1_dt_empty engine='columnar' archive_mode='ttl'; +create table ttl_t2_dt_null_arc like ttl_t2_dt_null engine='columnar' archive_mode='ttl'; +create table ttl_t3_dt_zero_arc like ttl_t3_dt_zero engine='columnar' archive_mode='ttl'; +create table ttl_t4_dt_both_arc like ttl_t4_dt_both engine='columnar' archive_mode='ttl'; + +alter table ttl_t1_dt_empty cleanup expired data; +alter table ttl_t2_dt_null cleanup expired data; +alter table ttl_t3_dt_zero cleanup expired data; +alter table ttl_t4_dt_both cleanup expired data; + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_dt_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_dt_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_dt_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_dt_both order by a; + +drop table ttl_t1_dt_empty; +drop table ttl_t2_dt_null; +drop table ttl_t3_dt_zero; +drop table ttl_t4_dt_both; + + + + + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_ts.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_ts.result new file mode 100644 index 000000000..328206817 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_ts.result @@ -0,0 +1,79 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set sql_mode='' +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +CREATE TABLE `ttl_t1_ts_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +CREATE TABLE `ttl_t2_ts_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +insert into ttl_t2_ts_null values (1, 0) +CREATE TABLE `ttl_t3_ts_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +insert into ttl_t3_ts_zero values (1, '0000-00-00 00:00:00') +CREATE TABLE `ttl_t4_ts_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +insert into ttl_t4_ts_both values (1, 0) +insert into ttl_t4_ts_both values (2, 9999999999999) +insert into ttl_t4_ts_both values (3, '0000-00-00 00:00:00') +insert into ttl_t4_ts_both values (4, '1970-01-01 00:00:00') +insert into ttl_t4_ts_both values (5, '2024-05-05 00:00:00') +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_ts_empty order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_ts_null order by a +a,b_val +1,0000-00-00 00:00:00 +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_ts_zero order by a +a,b_val +1,0000-00-00 00:00:00 +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_ts_both order by a +a,b_val +1,0000-00-00 00:00:00 +2,0000-00-00 00:00:00 +3,0000-00-00 00:00:00 +4,0000-00-00 00:00:00 +5,2024-05-05 00:00:00 +create table ttl_t1_ts_empty_arc like ttl_t1_ts_empty engine='columnar' archive_mode='ttl' +create table ttl_t2_ts_null_arc like ttl_t2_ts_null engine='columnar' archive_mode='ttl' +create table ttl_t3_ts_zero_arc like ttl_t3_ts_zero engine='columnar' archive_mode='ttl' +create table ttl_t4_ts_both_arc like ttl_t4_ts_both engine='columnar' archive_mode='ttl' +alter table ttl_t1_ts_empty cleanup expired data +alter table ttl_t2_ts_null cleanup expired data +alter table ttl_t3_ts_zero cleanup expired data +alter table ttl_t4_ts_both cleanup expired data +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_ts_empty order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_ts_null order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_ts_zero order by a +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_ts_both order by a +a,b_val +5,2024-05-05 00:00:00 +drop table ttl_t1_ts_empty +drop table ttl_t2_ts_null +drop table ttl_t3_ts_zero +drop table ttl_t4_ts_both; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_ts.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_ts.test.yml new file mode 100644 index 000000000..5d8bba145 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/test_ttl_special_val_ts.test.yml @@ -0,0 +1,74 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set sql_mode=''; +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; + +CREATE TABLE `ttl_t1_ts_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +CREATE TABLE `ttl_t2_ts_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t2_ts_null values (1, 0); + +CREATE TABLE `ttl_t3_ts_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t3_ts_zero values (1, '0000-00-00 00:00:00'); + +CREATE TABLE `ttl_t4_ts_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t4_ts_both values (1, 0); +insert into ttl_t4_ts_both values (2, 9999999999999); +insert into ttl_t4_ts_both values (3, '0000-00-00 00:00:00'); +insert into ttl_t4_ts_both values (4, '1970-01-01 00:00:00'); +insert into ttl_t4_ts_both values (5, '2024-05-05 00:00:00'); + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_ts_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_ts_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_ts_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_ts_both order by a; + +create table ttl_t1_ts_empty_arc like ttl_t1_ts_empty engine='columnar' archive_mode='ttl'; +create table ttl_t2_ts_null_arc like ttl_t2_ts_null engine='columnar' archive_mode='ttl'; +create table ttl_t3_ts_zero_arc like ttl_t3_ts_zero engine='columnar' archive_mode='ttl'; +create table ttl_t4_ts_both_arc like ttl_t4_ts_both engine='columnar' archive_mode='ttl'; + +alter table ttl_t1_ts_empty cleanup expired data; +alter table ttl_t2_ts_null cleanup expired data; +alter table ttl_t3_ts_zero cleanup expired data; +alter table ttl_t4_ts_both cleanup expired data; + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_ts_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_ts_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_ts_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_ts_both order by a; + +drop table ttl_t1_ts_empty; +drop table ttl_t2_ts_null; +drop table ttl_t3_ts_zero; +drop table ttl_t4_ts_both; + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/testcase.config.yml new file mode 100644 index 000000000..23af37abd --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable2Test/testcase.config.yml @@ -0,0 +1,3 @@ +test_ttl_special_val_dt +test_ttl_special_val_d +test_ttl_special_val_ts \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.result new file mode 100644 index 000000000..0fb67058b --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.result @@ -0,0 +1,63 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set sql_mode='' +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true +set FORBID_DDL_WITH_CCI=false +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI=false +CREATE TABLE `coupon` ( +`Id` varchar(32) NOT NULL COMMENT '主键', +`UserId` varchar(32) NOT NULL COMMENT '用户ID', +`CouponCode` varchar(32) NOT NULL COMMENT '优惠卷编号', +`BeginValidityPeriod` datetime NOT NULL COMMENT '有效期始', +`EndValidityPeriod` datetime NOT NULL COMMENT '有效期止', +`RuleType` tinyint(4) NOT NULL COMMENT '1定额 2折扣 3时长 4免费停车 5定额停车 6免单停车券 7商户免单券', +`FaceAmount` decimal(18, 2) NOT NULL COMMENT '面额', +`RestrictAmount` decimal(18, 2) NOT NULL COMMENT '使用限额', +`RegionId` varchar(32) NOT NULL COMMENT '地区Id', +`ScopeType` tinyint(4) NOT NULL COMMENT '限制类型0 无限制 1地区 2 停车场', +`CouponStatus` tinyint(4) NOT NULL COMMENT '状态 1正常 、未使用 2 已使用 3已过期', +`CouponPublishRuleId` varchar(32) NOT NULL COMMENT '发行规则表Id', +`CouponPublishRuleDetailId` varchar(32) NOT NULL COMMENT '规则明细表Id', +`CouponEventId` varchar(32) NOT NULL COMMENT '事件表Id', +`PaySettleAccountId` varchar(32) NOT NULL COMMENT '发行结算方Id', +`CouponType` tinyint(4) NOT NULL COMMENT '优惠券类型 0通用 1停车券 2洗车券', +`CreateTime` datetime NOT NULL COMMENT '创建时间', +`UpdateTime` datetime NOT NULL COMMENT '修改时间', +`ExtendInfo` varchar(4000) NOT NULL COMMENT '扩展信息', +`IsDelete` tinyint(4) NOT NULL COMMENT '是否删除(0否,1是)', +`Status` tinyint(4) NOT NULL COMMENT '状态(0正常)', +`IsNeedSettle` tinyint(4) NOT NULL, +`ComeFrom` tinyint(4) DEFAULT NULL COMMENT '优惠券来源 0 客服送券,1 发行规则 2 直接插入表的接口3来自无效订单回滚4.商户赠送 5.结算方送商户,商户送用户6.商户赠送(通联)7.团队发券 8.商户赠送(银联) 9.松立山东', +`DirectKey` varchar(32) DEFAULT NULL COMMENT '车辆ID', +`ObjectId` varchar(32) DEFAULT NULL, +`MerchantId` varchar(32) DEFAULT NULL COMMENT '商户id(comefrom为4,5,6时,此字段有值)', +`CreateBy` varchar(32) DEFAULT '' COMMENT '操作人', +`Remarks` varchar(512) DEFAULT '' COMMENT '备注', +`ProjectId` int(4) DEFAULT '0' COMMENT '项目ID', +`PromoterId` varchar(32) DEFAULT NULL COMMENT '推广人Id', +`CouponFlag` tinyint(2) NOT NULL DEFAULT '0' COMMENT '叠加券标识 0:普通券 1”叠加券', +PRIMARY KEY (`Id`, `EndValidityPeriod`), +GLOBAL INDEX `g_i_directkey` (`directkey`) +PARTITION BY KEY(`DirectKey`) +PARTITIONS 8, +KEY `IDX_code` USING BTREE (`CouponCode`), +KEY `IDX_CISB` (`CouponStatus`, `IsDelete`, `Status`, `BeginValidityPeriod`), +KEY `IDX_RU` (`CouponPublishRuleId`), +KEY `idx_dciseb` (`DirectKey`, `CouponStatus`, `IsDelete`, `Status`, `EndValidityPeriod`, `BeginValidityPeriod`), +KEY `idx_uciseb` (`UserId`, `CouponStatus`, `IsDelete`, `Status`, `EndValidityPeriod`, `BeginValidityPeriod`), +KEY `idx_CouponPublishRuleDetailId` (`CouponPublishRuleDetailId`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT '优惠劵' +PARTITION BY KEY(`Id`) +PARTITIONS 8 +alter table coupon modify ttl set ttl_expr = `EndValidityPeriod` expire after 2 month timezone '+08:00' +create table coupon_bak like coupon engine='columnar' archive_mode='ttl' +ALTER TABLE `coupon` ADD COLUMN `update_by` varchar(32) NULL DEFAULT '' COMMENT '更新人' AFTER `CouponFlag` +show create table coupon_bak +View,Create View,character_set_client,collation_connection +coupon_bak,CREATE VIEW `coupon_bak` AS SELECT `coupon`.`Id`, `coupon`.`UserId`, `coupon`.`CouponCode`, `coupon`.`BeginValidityPeriod`, `coupon`.`EndValidityPeriod`, `coupon`.`RuleType`, `coupon`.`FaceAmount`, `coupon`.`RestrictAmount`, `coupon`.`RegionId`, `coupon`.`ScopeType`, `coupon`.`CouponStatus`, `coupon`.`CouponPublishRuleId`, `coupon`.`CouponPublishRuleDetailId`, `coupon`.`CouponEventId`, `coupon`.`PaySettleAccountId`, `coupon`.`CouponType`, `coupon`.`CreateTime`, `coupon`.`UpdateTime`, `coupon`.`ExtendInfo`, `coupon`.`IsDelete`, `coupon`.`Status`, `coupon`.`IsNeedSettle`, `coupon`.`ComeFrom`, `coupon`.`DirectKey`, `coupon`.`ObjectId`, `coupon`.`MerchantId`, `coupon`.`CreateBy`, `coupon`.`Remarks`, `coupon`.`ProjectId`, `coupon`.`PromoterId`, `coupon`.`CouponFlag`, `coupon`.`update_by` +FROM `test_add_col_on__910534051`.`coupon` FORCE INDEX(`ARCTMP_COUPON_BAK`),utf8,utf8_general_ci +drop table coupon_bak +drop table coupon; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.test.yml new file mode 100644 index 000000000..800d3a8ca --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.test.yml @@ -0,0 +1,63 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set sql_mode=''; +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true; +set FORBID_DDL_WITH_CCI=false; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI=false; +CREATE TABLE `coupon` ( +`Id` varchar(32) NOT NULL COMMENT '主键', +`UserId` varchar(32) NOT NULL COMMENT '用户ID', +`CouponCode` varchar(32) NOT NULL COMMENT '优惠卷编号', +`BeginValidityPeriod` datetime NOT NULL COMMENT '有效期始', +`EndValidityPeriod` datetime NOT NULL COMMENT '有效期止', +`RuleType` tinyint(4) NOT NULL COMMENT '1定额 2折扣 3时长 4免费停车 5定额停车 6免单停车券 7商户免单券', +`FaceAmount` decimal(18, 2) NOT NULL COMMENT '面额', +`RestrictAmount` decimal(18, 2) NOT NULL COMMENT '使用限额', +`RegionId` varchar(32) NOT NULL COMMENT '地区Id', +`ScopeType` tinyint(4) NOT NULL COMMENT '限制类型0 无限制 1地区 2 停车场', +`CouponStatus` tinyint(4) NOT NULL COMMENT '状态 1正常 、未使用 2 已使用 3已过期', +`CouponPublishRuleId` varchar(32) NOT NULL COMMENT '发行规则表Id', +`CouponPublishRuleDetailId` varchar(32) NOT NULL COMMENT '规则明细表Id', +`CouponEventId` varchar(32) NOT NULL COMMENT '事件表Id', +`PaySettleAccountId` varchar(32) NOT NULL COMMENT '发行结算方Id', +`CouponType` tinyint(4) NOT NULL COMMENT '优惠券类型 0通用 1停车券 2洗车券', +`CreateTime` datetime NOT NULL COMMENT '创建时间', +`UpdateTime` datetime NOT NULL COMMENT '修改时间', +`ExtendInfo` varchar(4000) NOT NULL COMMENT '扩展信息', +`IsDelete` tinyint(4) NOT NULL COMMENT '是否删除(0否,1是)', +`Status` tinyint(4) NOT NULL COMMENT '状态(0正常)', +`IsNeedSettle` tinyint(4) NOT NULL, +`ComeFrom` tinyint(4) DEFAULT NULL COMMENT '优惠券来源 0 客服送券,1 发行规则 2 直接插入表的接口3来自无效订单回滚4.商户赠送 5.结算方送商户,商户送用户6.商户赠送(通联)7.团队发券 8.商户赠送(银联) 9.松立山东', +`DirectKey` varchar(32) DEFAULT NULL COMMENT '车辆ID', +`ObjectId` varchar(32) DEFAULT NULL, +`MerchantId` varchar(32) DEFAULT NULL COMMENT '商户id(comefrom为4,5,6时,此字段有值)', +`CreateBy` varchar(32) DEFAULT '' COMMENT '操作人', +`Remarks` varchar(512) DEFAULT '' COMMENT '备注', +`ProjectId` int(4) DEFAULT '0' COMMENT '项目ID', +`PromoterId` varchar(32) DEFAULT NULL COMMENT '推广人Id', +`CouponFlag` tinyint(2) NOT NULL DEFAULT '0' COMMENT '叠加券标识 0:普通券 1”叠加券', +PRIMARY KEY (`Id`, `EndValidityPeriod`), +GLOBAL INDEX `g_i_directkey` (`directkey`) +PARTITION BY KEY(`DirectKey`) +PARTITIONS 8, +KEY `IDX_code` USING BTREE (`CouponCode`), +KEY `IDX_CISB` (`CouponStatus`, `IsDelete`, `Status`, `BeginValidityPeriod`), +KEY `IDX_RU` (`CouponPublishRuleId`), +KEY `idx_dciseb` (`DirectKey`, `CouponStatus`, `IsDelete`, `Status`, `EndValidityPeriod`, `BeginValidityPeriod`), +KEY `idx_uciseb` (`UserId`, `CouponStatus`, `IsDelete`, `Status`, `EndValidityPeriod`, `BeginValidityPeriod`), +KEY `idx_CouponPublishRuleDetailId` (`CouponPublishRuleDetailId`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT '优惠劵' +PARTITION BY KEY(`Id`) +PARTITIONS 8; +alter table coupon modify ttl set ttl_expr = `EndValidityPeriod` expire after 2 month timezone '+08:00'; +create table coupon_bak like coupon engine='columnar' archive_mode='ttl'; +ALTER TABLE `coupon` ADD COLUMN `update_by` varchar(32) NULL DEFAULT '' COMMENT '更新人' AFTER `CouponFlag`; +show create table coupon_bak; +drop table coupon_bak; +drop table coupon; + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_auto_split_cci_part.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_auto_split_cci_part.result new file mode 100644 index 000000000..ebf7a4960 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_auto_split_cci_part.result @@ -0,0 +1,64 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +create table test_cci_split( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +show create table test_cci_split +Table,Create Table +test_cci_split,CREATE TABLE `test_cci_split` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table test_cci_split_bk like test_cci_split engine='columnar' archive_mode='ttl' +show create table test_cci_split +Table,Create Table +test_cci_split,CREATE TABLE `test_cci_split` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_test_cci_split_bk` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'test_cci_split_bk', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table test_cci_split modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE=4 +alter table test_cci_split cleanup expired data +show create table test_cci_split +Table,Create Table +test_cci_split,CREATE TABLE `test_cci_split` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_test_cci_split_bk` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = Columnar, + PARTITION p202410 VALUES LESS THAN ('2024-11-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'test_cci_split_bk', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI=false +drop table test_cci_split; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_auto_split_cci_part.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_auto_split_cci_part.test.yml new file mode 100644 index 000000000..7c19c1ace --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_auto_split_cci_part.test.yml @@ -0,0 +1,25 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; + +create table test_cci_split( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; +show create table test_cci_split; +create table test_cci_split_bk like test_cci_split engine='columnar' archive_mode='ttl'; +show create table test_cci_split; + +alter table test_cci_split modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE=4; +alter table test_cci_split cleanup expired data; +show create table test_cci_split; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI=false; +drop table test_cci_split; + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl.result new file mode 100644 index 000000000..46d57281d --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl.result @@ -0,0 +1,109 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +create table nottl_tbl( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +create table ttl_tbl_without_arc( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +create table ttl_tbl_with_arc( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +create table ttl_tbl_with_arc_bak like ttl_tbl_with_arc engine='columnar' archive_mode='ttl' +show create table nottl_tbl +Table,Create Table +nottl_tbl,CREATE TABLE `nottl_tbl` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 2 +show create table ttl_tbl_without_arc +Table,Create Table +ttl_tbl_without_arc,CREATE TABLE `ttl_tbl_without_arc` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +show create table ttl_tbl_with_arc +Table,Create Table +ttl_tbl_with_arc,CREATE TABLE `ttl_tbl_with_arc` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_arc_bak` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_arc_bak', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +## error_msg: $# not a ttl-defined #$ +create table like_t1 like nottl_tbl engine='columnar' archive_mode='ttl' +not a ttl-defined +## error_msg: $# not a ttl-defined #$ +create table like_t1 like nottl_tbl engine='columnar' +not a ttl-defined +## error_msg: $# cannot create #$ +create table like_t1 like nottl_tbl archive_mode='ttl' +cannot create +## error_msg: $# without specifying both #$ +create table like_t1 like ttl_tbl_without_arc archive_mode='ttl' +without specifying both +## error_msg: $# without specifying both #$ +create table like_t1 like ttl_tbl_without_arc engine='columnar' +without specifying both +create table like_t1 like ttl_tbl_without_arc +show create table like_t1 +Table,Create Table +like_t1,CREATE TABLE `like_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +## error_msg: $#cannot create #$ +create table like_t2 like ttl_tbl_with_arc +cannot create +set ALLOW_CREATE_TABLE_LIKE_IGNORE_ARCHIVE_CCI=true +create table like_t2 like ttl_tbl_with_arc +create table like_t3 like nottl_tbl +show create table like_t3 +Table,Create Table +like_t3,CREATE TABLE `like_t3` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 2 +drop table if exists nottl_tbl +drop table if exists ttl_tbl_without_arc +drop table if exists ttl_tbl_with_arc +drop table if exists like_t1 +drop table if exists like_t2 +drop table if exists like_t3; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl.test.yml new file mode 100644 index 000000000..5dd30bc02 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl.test.yml @@ -0,0 +1,69 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; + +create table nottl_tbl( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +create table ttl_tbl_without_arc( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; + +create table ttl_tbl_with_arc( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; +create table ttl_tbl_with_arc_bak like ttl_tbl_with_arc engine='columnar' archive_mode='ttl'; + +show create table nottl_tbl; +show create table ttl_tbl_without_arc; +show create table ttl_tbl_with_arc; + +## error_msg: $# not a ttl-defined #$ +create table like_t1 like nottl_tbl engine='columnar' archive_mode='ttl'; +## error_msg: $# not a ttl-defined #$ +create table like_t1 like nottl_tbl engine='columnar'; +## error_msg: $# cannot create #$ +create table like_t1 like nottl_tbl archive_mode='ttl'; + +## error_msg: $# without specifying both #$ +create table like_t1 like ttl_tbl_without_arc archive_mode='ttl'; +## error_msg: $# without specifying both #$ +create table like_t1 like ttl_tbl_without_arc engine='columnar'; + +create table like_t1 like ttl_tbl_without_arc; +show create table like_t1; + +## error_msg: $#cannot create #$ +create table like_t2 like ttl_tbl_with_arc; +set ALLOW_CREATE_TABLE_LIKE_IGNORE_ARCHIVE_CCI=true; +create table like_t2 like ttl_tbl_with_arc; + +create table like_t3 like nottl_tbl; +show create table like_t3; + +drop table if exists nottl_tbl; +drop table if exists ttl_tbl_without_arc; +drop table if exists ttl_tbl_with_arc; +drop table if exists like_t1; +drop table if exists like_t2; +drop table if exists like_t3; + + + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl2.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl2.result new file mode 100644 index 000000000..f03bb1c3d --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl2.result @@ -0,0 +1,119 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +create table ttl_tbl_with_cci( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci engine='columnar' archive_mode='ttl' +create table ttl_tbl_with_cci2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +## error_msg: $# has bound the archive table #$ +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci engine='columnar' archive_mode='ttl' +has bound the archive table +## error_msg: $# already exists #$ +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci2 engine='columnar' archive_mode='ttl' +already exists +create table ttl_tbl_with_cci_bak2 like ttl_tbl_with_cci2 engine='columnar' archive_mode='ttl' +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci_bak` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci_bak', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +already exists +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +already exists +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +already exists +## error_msg: $# not the same #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_xxx` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_yyy', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +not the same +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_xxx` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_xxx', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +drop table if exists ttl_tbl_with_cci +drop table if exists ttl_tbl_with_cci2 +drop table if exists ttl_tbl_with_cci3; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl2.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl2.test.yml new file mode 100644 index 000000000..151df8053 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_create_like_ttl_tbl2.test.yml @@ -0,0 +1,131 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; + +create table ttl_tbl_with_cci( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci engine='columnar' archive_mode='ttl'; + +create table ttl_tbl_with_cci2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; + +## error_msg: $# has bound the archive table #$ +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci engine='columnar' archive_mode='ttl'; + +## error_msg: $# already exists #$ +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci2 engine='columnar' archive_mode='ttl'; + +create table ttl_tbl_with_cci_bak2 like ttl_tbl_with_cci2 engine='columnar' archive_mode='ttl'; + +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci_bak` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION `pmax` VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci_bak', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION `pmax` VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION `pmax` VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +## error_msg: $# not the same #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_xxx` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION `pmax` VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_yyy', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_xxx` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION `pmax` VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_xxx', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +drop table if exists ttl_tbl_with_cci; +drop table if exists ttl_tbl_with_cci2; +drop table if exists ttl_tbl_with_cci3; + + + + + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_drop_ttl_tbl.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_drop_ttl_tbl.result new file mode 100644 index 000000000..1f7bd1e67 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_drop_ttl_tbl.result @@ -0,0 +1,31 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +create table test_drop_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +show create table test_drop_ttl_t1 +Table,Create Table +test_drop_ttl_t1,CREATE TABLE `test_drop_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table test_drop_ttl_t1_bk like test_drop_ttl_t1 engine='columnar' archive_mode='ttl' +## error_msg: $# Forbid to drop #$ +drop table test_drop_ttl_t1_bk +Forbid to drop +## error_msg: $# Forbid to drop #$ +drop table test_drop_ttl_t1 +Forbid to drop +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +drop table test_drop_ttl_t1_bk +drop table test_drop_ttl_t1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_drop_ttl_tbl.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_drop_ttl_tbl.test.yml new file mode 100644 index 000000000..79a778c54 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_drop_ttl_tbl.test.yml @@ -0,0 +1,27 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table test_drop_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; +show create table test_drop_ttl_t1; +create table test_drop_ttl_t1_bk like test_drop_ttl_t1 engine='columnar' archive_mode='ttl'; + +## error_msg: $# Forbid to drop #$ +drop table test_drop_ttl_t1_bk; + +## error_msg: $# Forbid to drop #$ +drop table test_drop_ttl_t1; + + +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; +drop table test_drop_ttl_t1_bk; +drop table test_drop_ttl_t1; diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_rename_ttl_tbl.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_rename_ttl_tbl.result new file mode 100644 index 000000000..1c989b38e --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_rename_ttl_tbl.result @@ -0,0 +1,28 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +create table test_drop_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +show create table test_drop_ttl_t1 +Table,Create Table +test_drop_ttl_t1,CREATE TABLE `test_drop_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table test_drop_ttl_t1_bk like test_drop_ttl_t1 engine='columnar' archive_mode='ttl' +set FORBID_DDL_WITH_CCI=true +## error_msg: $# not support #$ +rename table test_drop_ttl_t1 to test_drop_ttl_t2 +not support +set FORBID_DDL_WITH_CCI=false +rename table test_drop_ttl_t1 to test_drop_ttl_t2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_rename_ttl_tbl.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_rename_ttl_tbl.test.yml new file mode 100644 index 000000000..ae9f0e1ee --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/test_rename_ttl_tbl.test.yml @@ -0,0 +1,26 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + + +create table test_drop_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; +show create table test_drop_ttl_t1; +create table test_drop_ttl_t1_bk like test_drop_ttl_t1 engine='columnar' archive_mode='ttl'; + +set FORBID_DDL_WITH_CCI=true; +## error_msg: $# not support #$ +rename table test_drop_ttl_t1 to test_drop_ttl_t2; +set FORBID_DDL_WITH_CCI=false; +rename table test_drop_ttl_t1 to test_drop_ttl_t2; + + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/testcase.config.yml new file mode 100644 index 000000000..a439225fa --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTable3Test/testcase.config.yml @@ -0,0 +1,6 @@ +test_drop_ttl_tbl +test_rename_ttl_tbl +test_add_col_on_ttl_tbl +test_auto_split_cci_part +test_create_like_ttl_tbl +test_create_like_ttl_tbl2 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/alter_tbl_modify_ttl.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/alter_tbl_modify_ttl.test.yml new file mode 100644 index 000000000..874f87d5c --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/alter_tbl_modify_ttl.test.yml @@ -0,0 +1,90 @@ +## DISABLE_FAST_SQL_PARSER + + + +create table modify_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_LEVEL = 'ROW' +TTL_EXPR = '`b` | EXPIRE AFTER 5 MINUTE | TIMEZONE=+08:00' +TTL_JOB = CRON '* */2 * * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + + +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +alter table ttl_t1 modify ttl +set +TTL_ENABLE = 'OFF' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+00:00'; + +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'OFF' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + +alter table modify_ttl_t1 +modify ttl +set +TTL_EXPR = '`b` EXPIRE AFTER 5 MONTH TIMEZONE=+08:00' +TTL_PRE_ALLOCATE = 12 +TTL_POST_ALLOCATE = 24; + +create table arc_t1 like ttl_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; +alter table ttl_t1 modify ttl set ARC_PRE_ALLOCATE = 3; +select * from information_schema.ttl_info where table_schema='ttldb2' and table_name='ttl_t1'; + +alter table ttl_t1 cleanup expired data; + +alter table ttl_t1 +modify ttl +set +TTL_ENABLE = 'OFF' +TTL_EXPR = `b` EXPIRE AFTER 5 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+00:00' +ARCHIVE_TABLE_SCHEMA = '' +ARCHIVE_TABLE_NAME = '' +ARC_PRE_ALLOCATE = 1 +ARC_POST_ALLOCATE = 6; + +alter table ttl_t1 +modify ttl +set +TTL_ENABLE = 'OFF' +TTL_EXPR = `b` EXPIRE AFTER 5 DAY TIMEZONE '+08:00' +TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+00:00' +ARCHIVE_TABLE_SCHEMA = '' +ARCHIVE_TABLE_NAME = '' +ARC_PRE_ALLOCATE = 1 +ARC_POST_ALLOCATE = 6; + + +alter table ttl_t2 modify ttl set ARC_PRE_ALLOCATE = 5 ARC_POST_ALLOCATE = 5; + +alter table ttl_t1 modify ttl set TTL_EXPR = `b` EXPIRE AFTER 180 DAY TIMEZONE '+08:00'; + +create table arc_t2 like ttl_t2 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; + +select * from information_schema.ttl_info where table_schema='ttldb4'; + +CREATE TABLE `ttl_t2` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' +PARTITION BY KEY(`a`) +PARTITIONS 2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/alter_tbl_modify_ttl2.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/alter_tbl_modify_ttl2.test.yml new file mode 100644 index 000000000..4858a81ca --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/alter_tbl_modify_ttl2.test.yml @@ -0,0 +1,102 @@ +## DISABLE_FAST_SQL_PARSER + + + +create table modify_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_LEVEL = 'ROW' +TTL_EXPR = '`b` | EXPIRE AFTER 5 MINUTE | TIMEZONE=+08:00' +TTL_JOB = CRON '* */2 * * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + + +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +alter table ttl_t1 modify ttl +set +TTL_ENABLE = 'OFF' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+00:00'; + +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'OFF' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + +alter table modify_ttl_t1 +modify ttl +set +TTL_EXPR = '`b` EXPIRE AFTER 5 MONTH TIMEZONE=+08:00' +TTL_PRE_ALLOCATE = 12 +TTL_POST_ALLOCATE = 24; + +create table arc_t1 like ttl_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; +alter table ttl_t1 modify ttl set ARC_PRE_ALLOCATE = 3; +select * from information_schema.ttl_info where table_schema='ttldb2' and table_name='ttl_t1'; + +alter table ttl_t1 cleanup expired data; + +alter table ttl_t1 +modify ttl +set +TTL_ENABLE = 'OFF' +TTL_EXPR = `b` EXPIRE AFTER 5 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+00:00' +ARCHIVE_TABLE_SCHEMA = '' +ARCHIVE_TABLE_NAME = '' +ARC_PRE_ALLOCATE = 1 +ARC_POST_ALLOCATE = 6; + +alter table ttl_t1 +modify ttl +set +TTL_ENABLE = 'OFF' +TTL_EXPR = `b` EXPIRE AFTER 5 DAY TIMEZONE '+08:00' +TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+00:00' +ARCHIVE_TABLE_SCHEMA = '' +ARCHIVE_TABLE_NAME = '' +ARC_PRE_ALLOCATE = 1 +ARC_POST_ALLOCATE = 6; + + +alter table ttl_t1 modify ttl set ARC_PRE_ALLOCATE = 3 ARC_POST_ALLOCATE = 5; + +alter table ttl_t1 modify ttl set TTL_EXPR = `b` EXPIRE AFTER 180 DAY TIMEZONE '+08:00'; + +create table arc_t2 like ttl_t2 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; + +CREATE TABLE `ttl_t2` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' +PARTITION BY KEY(`a`) +PARTITIONS 2; + + +create table ttl_ts_t1( +a int not null auto_increment, +b timestamp default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'OFF' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+10:00' +TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+10:00' +partition by key(a) partitions 2; + +alter table ttl_ts_t1 modify ttl set ARC_PRE_ALLOCATE = 1 ARC_POST_ALLOCATE = 3; +create table arc_ts_t1 like ttl_ts_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl.test.yml new file mode 100644 index 000000000..1933269a9 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl.test.yml @@ -0,0 +1,415 @@ +## DISABLE_FAST_SQL_PARSER + +## orginal +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +partition by key(a) partitions 8 +local partition by range(b) +STARTWITH '2021-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 12 +PRE ALLOCATE 6; + + +# -- 语法 +# (SUB)PARTITION BY RANGE COLUMNS (gmt_modified) -- 分区列 +# [STARTWITH $startWithDate] -- 分区初始时间 +# INTERVAL $intervalCount $intervalUnit -- 分区间隔 +# [EXPIRE AFTER $expireAfterCount] -- expireAfterCount个间隔后失效 +# [PRE ALLOCATE $preAllocateCount] -- 提前preAllocateCount个间隔创建分区 +# [PIVOTDATE $pivotDate] -- 基准时间,默认为NOW() +# ; + +## new +create table ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +partition by key(a) partitions 8 +subpartition by range columns(b) +STARTWITH '2021-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 12 +PRE ALLOCATE 6 +PIVOTDATE NOW(); + + +create table pttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +subpartition by range columns(b) +STARTWITH '2022-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 12 +PRE ALLOCATE 6 +PIVOTDATE NOW(); + +#CREATE TABLE `pttl_t1` ( +#`a` int(11) NOT NULL AUTO_INCREMENT, +#`b` datetime DEFAULT CURRENT_TIMESTAMP, +#PRIMARY KEY (`a`), +#KEY `auto_shard_key_b` USING BTREE (`b`) +#) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +#PARTITION BY KEY(`a`) +#PARTITIONS 2 +#SUBPARTITION BY RANGE COLUMNS(`b`) +#(SUBPARTITION `sp20220101` VALUES LESS THAN ('2022-01-01 00:00:00'), +#SUBPARTITION `sp20220701` VALUES LESS THAN ('2022-07-01 00:00:00'), +#SUBPARTITION `sp20230101` VALUES LESS THAN ('2023-01-01 00:00:00'), +#SUBPARTITION `sp20230701` VALUES LESS THAN ('2023-07-01 00:00:00'), +#SUBPARTITION `sp20240101` VALUES LESS THAN ('2024-01-01 00:00:00'), +#SUBPARTITION `sp20240701` VALUES LESS THAN ('2024-07-01 00:00:00'), +#SUBPARTITION `sp20250101` VALUES LESS THAN ('2025-01-01 00:00:00'), +#SUBPARTITION `sp20250701` VALUES LESS THAN ('2025-07-01 00:00:00'), +#SUBPARTITION `sp20260101` VALUES LESS THAN ('2026-01-01 00:00:00'), +#SUBPARTITION `sp20260701` VALUES LESS THAN ('2026-07-01 00:00:00'), +#SUBPARTITION `spmax` VALUES LESS THAN (MAXVALUE)) + +alter table pttl_t1 split subpartition spmax into ( +SUBPARTITION `sp20270101` VALUES LESS THAN ('2027-01-01 00:00:00'), +SUBPARTITION `spmax` VALUES LESS THAN (maxvalue) +); + + +create table ttl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_LEVEL = 'ROW' +TTL_EXPR = '`b` | EXPIRE AFTER 5 MINUTE | TIMEZONE=+08:00' +TTL_JOB = CRON '* */2 * * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + +create table ttl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_LEVEL = 'ROW' +TTL_EXPR = `b` EXPIRE AFTER 5 MINUTE TIMEZONE '+08:00' +TTL_JOB = CRON '* */2 * * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + + +create table rl_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_LEVEL = 'ROW' +TTL_EXPR = `b` EXPIRE AFTER 5 MINUTE TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + + +insert into rl_ttl_t1(a, b) values (null, now()); +insert into rl_ttl_t1(a, b) select null, date_format( b, b - interval '5' DAY) from rl_ttl_t1 limit 10000; + +select b - interval '5' DAY ; + + +create table nottl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + + +## +## TTL_ENABLE = {'ON'|'OFF'|} +## TTL_LEVEL = {'ROW'|'PART'|'SUBPART'|'LOCAL'} +## TTL_EXPR = '`column` INTERVAL 6 MONTH' +## + + +create table ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +ENA +partition by key(a) partitions 3; + + + + + + +insert into bmsql_history +(hist_id, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, h_date,h_amount, h_data ) + +select +null, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, date_format( h_date, h_date - interval minute(h_date) * 60 + second(h_date) HOUR),h_amount, h_data +from +bmsql_history; + + +date_format( b, b - interval '5' DAY) +date_format( h_date, h_date - interval minute(h_date) * 60 + second(h_date) HOUR) + + + +insert into bmsql_history (hist_id, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, h_date,h_amount, h_data ) select null, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, date_format( h_date, h_date - interval minute(h_date) * 60 + second(h_date) HOUR),h_amount, h_data from bmsql_history order by h_date limit 50000; + + +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a), +global index g_b (b) partition by key(b) partitions 16 +) +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 5 MINUTE TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 16; + + +create table oss_t1 +like ttl_t1 engine = 'local_disk' +archive_mode = 'ttl'; + +alter table ttl_t1 cleanup expired data; + +alter table _ttl_tmp_ttl_t1 add partition ( + PARTITION `p2` VALUES LESS THAN ('2023-02-01 00:00:00'), + PARTITION `p3` VALUES LESS THAN ('2023-03-01 00:00:00') +); + +insert into ttl_t1 values +(null, '2023-01-01'), +(null, '2023-01-02'), +(null, '2023-01-03'), +(null, '2023-01-04'), +(null, '2023-01-11'), +(null, '2023-01-12') +; + +insert into ttl_t1 (a, b) select null, b from ttl_t1; + + +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a), +global index g_b (b) partition by key(b) partitions 16 +) +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 16; + +create table oss_t1 +like ttl_t1 engine = 'local_disk' +archive_mode = 'ttl'; + + +create table no_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a), + +global index g_b (b) partition by key(b) partitions 16 +) +partition by key(a) partitions 16; + + +; +alter table no_t1 +set +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00'; + +insert into ttl_t1 values +(null, '2023-01-01'), +(null, '2023-07-05'), +(null, '2023-08-02'), +(null, '2023-09-03'), +(null, '2023-10-04'), +(null, '2023-11-11'), +(null, '2023-12-11'), +(null, '2024-03-12') +; + +insert into ttl_bk values +(null, '2023-01-01'), +(null, '2023-07-05'), +(null, '2023-08-02'), +(null, '2023-09-03'), +(null, '2023-10-04'), +(null, '2023-11-11'), +(null, '2023-12-11'), +(null, '2024-03-12') +; + +insert into ttl_bk select null,b from ttl_bk; + +insert into ttl_t1 select null,b from ttl_bk; + +insert into ttl_t1 values +(null, '2023-01-01', c_seq.nextval), +(null, '2023-07-05', c_seq.nextval), +(null, '2023-08-02', c_seq.nextval), +(null, '2023-09-03', c_seq.nextval), +(null, '2023-10-04', c_seq.nextval), +(null, '2023-11-11', c_seq.nextval), +(null, '2023-12-11', c_seq.nextval), +(null, '2024-03-12', c_seq.nextval) +; + + +CREATE TABLE `_ttl_tmp_ttl_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`) +) +ENGINE = InnoDB +DEFAULT CHARSET = utf8mb4 +TTL_TEMPORARY= 'Y' +PARTITION BY RANGE COLUMNS(`b`) +SUBPARTITION BY KEY(`a`) +SUBPARTITIONS 8 +( + PARTITION `pstart` VALUES LESS THAN ('1970-01-01 00:00:00') +); + +alter table _ttl_tmp_ttl_t1 add partition ( +PARTITION `p202308` VALUES LESS THAN ('2023-09-01 00:00:00'), +PARTITION `p202309` VALUES LESS THAN ('2023-10-01 00:00:00'), +PARTITION `p202310` VALUES LESS THAN ('2023-11-01 00:00:00'), +PARTITION `p202311` VALUES LESS THAN ('2023-12-01 00:00:00'), +PARTITION `p202312` VALUES LESS THAN ('2024-01-01 00:00:00'), +PARTITION `p202301` VALUES LESS THAN ('2024-02-01 00:00:00'), +PARTITION `p202302` VALUES LESS THAN ('2024-03-01 00:00:00'), +PARTITION `p202403` VALUES LESS THAN ('2024-04-01 00:00:00') +); + +alter table _ttl_tmp_ttl_t1 drop partition +p202310,p202311,p202312,p202401,p202402 + + +insert into ttl_t1 select null,b from ttl_t1; + +alter table ttl_t1 cleanup expired data; + +insert into ttl_t2 (a, b) select null, b from ttl_t2; + + +ALTER TABLE no_t1 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00'; + + + +CREATE TABLE ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +c varchar(32) not null, +PRIMARY KEY(a), +UNIQUE INDEX ui_c(c) +) +PARTITION BY KEY(a) PARTITIONS 16; + +CREATE TABLE ttl_bk( +a int not null auto_increment, +b datetime default current_timestamp, +PRIMARY KEY(a) +) +PARTITION BY KEY(a) PARTITIONS 16; + +insert into ttl_t1 values +(null, '2023-01-01', c_seq.nextval), +(null, '2023-07-05', c_seq.nextval), +(null, '2023-08-02', c_seq.nextval), +(null, '2023-09-03', c_seq.nextval), +(null, '2023-10-04', c_seq.nextval), +(null, '2023-11-11', c_seq.nextval), +(null, '2023-12-11', c_seq.nextval), +(null, '2024-03-12', c_seq.nextval) +; + +insert into ttl_t1 select null,b,c_seq.nextval from ttl_t1; + +create table oss_t1 +like ttl_t1 engine = 'oss' +archive_mode = 'ttl'; + + +select sum(data_length) len from information_schema.tables +where table_name='ttl_t1' and table_schema='ttldb'; + + +insert into ttl_bk values +(null, '2022-01-02'), +(null, '2022-02-05'), +(null, '2022-03-02'), +(null, '2022-04-02'), +(null, '2022-05-03'), +(null, '2022-06-04'), +(null, '2022-07-11'), +(null, '2022-08-11'), +(null, '2022-09-12'), +(null, '2022-10-12'), +(null, '2022-11-02'), +(null, '2022-12-05'), +(null, '2023-01-02'), +(null, '2023-02-05'), +(null, '2023-03-02'), +(null, '2023-04-02'), +(null, '2023-05-03'), +(null, '2023-06-04'), +(null, '2023-07-11'), +(null, '2023-08-11'), +(null, '2024-09-12'), +(null, '2023-10-02'), +(null, '2023-11-05'), +(null, '2023-12-02'), +(null, '2024-01-02'), +(null, '2024-02-03'), +(null, '2024-03-04'), +(null, '2024-04-08') +; + +insert into ttl_bk(a, b) select null, b from ttl_bk; + +insert into ttl_t1(a, b) select a, b from ttl_bk; + + +create table oss_t1 +like ttl_t1 engine = 'local_disk' +archive_mode = 'ttl'; + +alter table ttl_t1 cleanup expired data; + + +select distinct table_schema,table_name, part_name, part_arc_state from information_schema.partitions_meta where table_schema='ttldb' and table_name='_ttl_tmp_ttl_t1'; + +select sum(data_length + index_length) len from information_schema.tables where table_schema like 'ttldb%' and table_name like '_ttl_tmp_ttl_t1%'; + +select table_schema, table_name, data_length + index_length len from information_schema.tables where table_schema like 'ttldb%' and table_name like '_ttl_tmp_ttl_t1%'; + + +select count(1),b from ttl_t1 group by b order by b asc; +select count(1),b from _ttl_tmp_ttl_t1 group by b order by b asc; +select count(1),b from oss_t1 group by b order by b asc; + + +insert into ttl_t1 (a,b) select null, '2022-05-02' from ttl_bk limit 5000; + + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl.test2.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl.test2.yml new file mode 100644 index 000000000..025aeb5ff --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl.test2.yml @@ -0,0 +1,38 @@ + +## create table +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a), +global index g_b (b) partition by key(b) partitions 16 +) +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 5 MINUTE TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 16; + +create table oss_t1 +like ttl_t1 engine = 'local_disk' +archive_mode = 'ttl'; + +## prepare data +insert into ttl_t1 values +(null, '2023-01-01'), +(null, '2023-01-02'), +(null, '2023-01-03'), +(null, '2023-01-04'), +(null, '2023-01-11'), +(null, '2023-01-12') +; +insert into ttl_t1 (a, b) select null, b from ttl_t1; + +## prepare new part for the exparied data to be archived +alter table _ttl_tmp_ttl_t1 add partition ( +PARTITION `p2` VALUES LESS THAN ('2023-02-01 00:00:00'), +PARTITION `p3` VALUES LESS THAN ('2023-03-01 00:00:00') +); + +## do data cleaning, ( clean the data of time <= '2023-02-2' , mock) +alter table ttl_t1 cleanup expired data; + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl.test3.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl.test3.yml new file mode 100644 index 000000000..025aeb5ff --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl.test3.yml @@ -0,0 +1,38 @@ + +## create table +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a), +global index g_b (b) partition by key(b) partitions 16 +) +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 5 MINUTE TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 16; + +create table oss_t1 +like ttl_t1 engine = 'local_disk' +archive_mode = 'ttl'; + +## prepare data +insert into ttl_t1 values +(null, '2023-01-01'), +(null, '2023-01-02'), +(null, '2023-01-03'), +(null, '2023-01-04'), +(null, '2023-01-11'), +(null, '2023-01-12') +; +insert into ttl_t1 (a, b) select null, b from ttl_t1; + +## prepare new part for the exparied data to be archived +alter table _ttl_tmp_ttl_t1 add partition ( +PARTITION `p2` VALUES LESS THAN ('2023-02-01 00:00:00'), +PARTITION `p3` VALUES LESS THAN ('2023-03-01 00:00:00') +); + +## do data cleaning, ( clean the data of time <= '2023-02-2' , mock) +alter table ttl_t1 cleanup expired data; + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl2.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl2.result new file mode 100644 index 000000000..cba6f92f3 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl2.result @@ -0,0 +1 @@ +toBeAdd \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl3.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl3.result new file mode 100644 index 000000000..cba6f92f3 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl3.result @@ -0,0 +1 @@ +toBeAdd \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl_on_columnar.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl_on_columnar.test.yml new file mode 100644 index 000000000..e0e862eb7 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/create_part_ttl_tbl_on_columnar.test.yml @@ -0,0 +1,429 @@ +## DISABLE_FAST_SQL_PARSER + +## orginal +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +partition by key(a) partitions 8 +local partition by range(b) +STARTWITH '2021-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 12 +PRE ALLOCATE 6; + +# -- 语法 +# (SUB)PARTITION BY RANGE COLUMNS (gmt_modified) -- 分区列 +# [STARTWITH $startWithDate] -- 分区初始时间 +# INTERVAL $intervalCount $intervalUnit -- 分区间隔 +# [EXPIRE AFTER $expireAfterCount] -- expireAfterCount个间隔后失效 +# [PRE ALLOCATE $preAllocateCount] -- 提前preAllocateCount个间隔创建分区 +# [PIVOTDATE $pivotDate] -- 基准时间,默认为NOW() +# ; + +## new +create table ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +partition by key(a) partitions 8 +subpartition by range columns(b) +STARTWITH '2021-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 12 +PRE ALLOCATE 6 +PIVOTDATE NOW(); + + +create table pttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +subpartition by range columns(b) +STARTWITH '2022-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 12 +PRE ALLOCATE 6 +PIVOTDATE NOW(); + +#CREATE TABLE `pttl_t1` ( +#`a` int(11) NOT NULL AUTO_INCREMENT, +#`b` datetime DEFAULT CURRENT_TIMESTAMP, +#PRIMARY KEY (`a`), +#KEY `auto_shard_key_b` USING BTREE (`b`) +#) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +#PARTITION BY KEY(`a`) +#PARTITIONS 2 +#SUBPARTITION BY RANGE COLUMNS(`b`) +#(SUBPARTITION `sp20220101` VALUES LESS THAN ('2022-01-01 00:00:00'), +#SUBPARTITION `sp20220701` VALUES LESS THAN ('2022-07-01 00:00:00'), +#SUBPARTITION `sp20230101` VALUES LESS THAN ('2023-01-01 00:00:00'), +#SUBPARTITION `sp20230701` VALUES LESS THAN ('2023-07-01 00:00:00'), +#SUBPARTITION `sp20240101` VALUES LESS THAN ('2024-01-01 00:00:00'), +#SUBPARTITION `sp20240701` VALUES LESS THAN ('2024-07-01 00:00:00'), +#SUBPARTITION `sp20250101` VALUES LESS THAN ('2025-01-01 00:00:00'), +#SUBPARTITION `sp20250701` VALUES LESS THAN ('2025-07-01 00:00:00'), +#SUBPARTITION `sp20260101` VALUES LESS THAN ('2026-01-01 00:00:00'), +#SUBPARTITION `sp20260701` VALUES LESS THAN ('2026-07-01 00:00:00'), +#SUBPARTITION `spmax` VALUES LESS THAN (MAXVALUE)) + +alter table pttl_t1 split subpartition spmax into ( +SUBPARTITION `sp20270101` VALUES LESS THAN ('2027-01-01 00:00:00'), +SUBPARTITION `spmax` VALUES LESS THAN (maxvalue) +); + + +create table ttl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_LEVEL = 'ROW' +TTL_EXPR = '`b` | EXPIRE AFTER 5 MINUTE | TIMEZONE=+08:00' +TTL_JOB = CRON '* */2 * * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + +create table ttl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_LEVEL = 'ROW' +TTL_EXPR = `b` EXPIRE AFTER 5 MINUTE TIMEZONE '+08:00' +TTL_JOB = CRON '* */2 * * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + + +create table rl_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL_ENABLE = 'ON' +TTL_LEVEL = 'ROW' +TTL_EXPR = `b` EXPIRE AFTER 5 MINUTE TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 2; + + +insert into rl_ttl_t1(a, b) values (null, now()); +insert into rl_ttl_t1(a, b) select null, date_format( b, b - interval '5' DAY) from rl_ttl_t1 limit 10000; + +select b - interval '5' DAY ; + + +create table nottl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + + +## +## TTL_ENABLE = {'ON'|'OFF'|} +## TTL_LEVEL = {'ROW'|'PART'|'SUBPART'|'LOCAL'} +## TTL_EXPR = '`column` INTERVAL 6 MONTH' +## + + +create table ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +ENA +partition by key(a) partitions 3; + + + + + + +insert into bmsql_history +(hist_id, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, h_date,h_amount, h_data ) + +select +null, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, date_format( h_date, h_date - interval minute(h_date) * 60 + second(h_date) HOUR),h_amount, h_data +from +bmsql_history; + + +date_format( b, b - interval '5' DAY) +date_format( h_date, h_date - interval minute(h_date) * 60 + second(h_date) HOUR) + + + +insert into bmsql_history (hist_id, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, h_date,h_amount, h_data ) select null, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, date_format( h_date, h_date - interval minute(h_date) * 60 + second(h_date) HOUR),h_amount, h_data from bmsql_history order by h_date limit 50000; + + +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a), +global index g_b (b) partition by key(b) partitions 16 +) +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 5 MINUTE TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 16; + + +create table oss_t1 +like ttl_t1 engine = 'local_disk' +archive_mode = 'ttl'; + +alter table ttl_t1 cleanup expired data; + +alter table _ttl_tmp_ttl_t1 add partition ( + PARTITION `p2` VALUES LESS THAN ('2023-02-01 00:00:00'), + PARTITION `p3` VALUES LESS THAN ('2023-03-01 00:00:00') +); + +insert into ttl_t1 values +(null, '2023-01-01'), +(null, '2023-01-02'), +(null, '2023-01-03'), +(null, '2023-01-04'), +(null, '2023-01-11'), +(null, '2023-01-12') +; + +insert into ttl_t1 (a, b) select null, b from ttl_t1; + + +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a), +global index g_b (b) partition by key(b) partitions 16 +) +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 16; + +create table oss_t1 +like ttl_t1 engine = 'local_disk' +archive_mode = 'ttl'; + + +create table no_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a), + +global index g_b (b) partition by key(b) partitions 16 +) +partition by key(a) partitions 16; + + +; +alter table no_t1 +set +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00'; + +insert into ttl_t1 values +(null, '2023-01-01'), +(null, '2023-07-05'), +(null, '2023-08-02'), +(null, '2023-09-03'), +(null, '2023-10-04'), +(null, '2023-11-11'), +(null, '2023-12-11'), +(null, '2024-03-12') +; + +insert into ttl_bk values +(null, '2023-01-01'), +(null, '2023-07-05'), +(null, '2023-08-02'), +(null, '2023-09-03'), +(null, '2023-10-04'), +(null, '2023-11-11'), +(null, '2023-12-11'), +(null, '2024-03-12') +; + +insert into ttl_bk select null,b from ttl_bk; + +insert into ttl_t1 select null,b from ttl_bk; + +insert into ttl_t1 values +(null, '2023-01-01', c_seq.nextval), +(null, '2023-07-05', c_seq.nextval), +(null, '2023-08-02', c_seq.nextval), +(null, '2023-09-03', c_seq.nextval), +(null, '2023-10-04', c_seq.nextval), +(null, '2023-11-11', c_seq.nextval), +(null, '2023-12-11', c_seq.nextval), +(null, '2024-03-12', c_seq.nextval) +; + + +CREATE TABLE `_ttl_tmp_ttl_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`) +) +ENGINE = InnoDB +DEFAULT CHARSET = utf8mb4 +TTL_TEMPORARY= 'Y' +PARTITION BY RANGE COLUMNS(`b`) +SUBPARTITION BY KEY(`a`) +SUBPARTITIONS 8 +( + PARTITION `pstart` VALUES LESS THAN ('1970-01-01 00:00:00') +); + +alter table _ttl_tmp_ttl_t1 add partition ( +PARTITION `p202308` VALUES LESS THAN ('2023-09-01 00:00:00'), +PARTITION `p202309` VALUES LESS THAN ('2023-10-01 00:00:00'), +PARTITION `p202310` VALUES LESS THAN ('2023-11-01 00:00:00'), +PARTITION `p202311` VALUES LESS THAN ('2023-12-01 00:00:00'), +PARTITION `p202312` VALUES LESS THAN ('2024-01-01 00:00:00'), +PARTITION `p202301` VALUES LESS THAN ('2024-02-01 00:00:00'), +PARTITION `p202302` VALUES LESS THAN ('2024-03-01 00:00:00'), +PARTITION `p202403` VALUES LESS THAN ('2024-04-01 00:00:00') +); + +alter table _ttl_tmp_ttl_t1 drop partition +p202310,p202311,p202312,p202401,p202402 + + +insert into ttl_t1 select null,b from ttl_t1; + +alter table ttl_t1 cleanup expired data; + +insert into ttl_t2 (a, b) select null, b from ttl_t2; + + +ALTER TABLE no_t1 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00'; + + + +CREATE TABLE ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +c varchar(32) not null, +PRIMARY KEY(a), +UNIQUE INDEX ui_c(c) +) +PARTITION BY KEY(a) PARTITIONS 16; + +CREATE TABLE ttl_bk( +a int not null auto_increment, +b datetime default current_timestamp, +PRIMARY KEY(a) +) +PARTITION BY KEY(a) PARTITIONS 16; + +insert into ttl_t1 values +(null, '2023-01-01', c_seq.nextval), +(null, '2023-07-05', c_seq.nextval), +(null, '2023-08-02', c_seq.nextval), +(null, '2023-09-03', c_seq.nextval), +(null, '2023-10-04', c_seq.nextval), +(null, '2023-11-11', c_seq.nextval), +(null, '2023-12-11', c_seq.nextval), +(null, '2024-03-12', c_seq.nextval) +; + +insert into ttl_t1 select null,b,c_seq.nextval from ttl_t1; + +create table oss_t1 +like ttl_t1 engine = 'oss' +archive_mode = 'ttl'; + + +select sum(data_length) len from information_schema.tables +where table_name='ttl_t1' and table_schema='ttldb'; + + +insert into ttl_bk values +(null, '2022-01-02'), +(null, '2022-02-05'), +(null, '2022-03-02'), +(null, '2022-04-02'), +(null, '2022-05-03'), +(null, '2022-06-04'), +(null, '2022-07-11'), +(null, '2022-08-11'), +(null, '2022-09-12'), +(null, '2022-10-12'), +(null, '2022-11-02'), +(null, '2022-12-05'), +(null, '2023-01-02'), +(null, '2023-02-05'), +(null, '2023-03-02'), +(null, '2023-04-02'), +(null, '2023-05-03'), +(null, '2023-06-04'), +(null, '2023-07-11'), +(null, '2023-08-11'), +(null, '2024-09-12'), +(null, '2023-10-02'), +(null, '2023-11-05'), +(null, '2023-12-02'), +(null, '2024-01-02'), +(null, '2024-02-03'), +(null, '2024-03-04'), +(null, '2024-04-08') +; + +insert into ttl_bk(a, b) select null, b from ttl_bk; + +insert into ttl_t1(a, b) select a, b from ttl_bk; + + +create table oss_t1 +like ttl_t1 engine = 'local_disk' +archive_mode = 'ttl'; + +alter table ttl_t1 cleanup expired data; + + +select distinct table_schema,table_name, part_name, part_arc_state from information_schema.partitions_meta where table_schema='ttldb' and table_name='_ttl_tmp_ttl_t1'; + +select sum(data_length + index_length) len from information_schema.tables where table_schema like 'ttldb%' and table_name like '_ttl_tmp_ttl_t1%'; + +select table_schema, table_name, data_length + index_length len from information_schema.tables where table_schema like 'ttldb%' and table_name like '_ttl_tmp_ttl_t1%'; + + +select count(1),b from ttl_t1 group by b order by b asc; +select count(1),b from _ttl_tmp_ttl_t1 group by b order by b asc; +select count(1),b from oss_t1 group by b order by b asc; + + +insert into ttl_t1 (a,b) select null, '2022-05-02' from ttl_bk limit 5000; + + +create table ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a), +global index g_b (b) partition by key(b) partitions 16 +) +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '* * */1 * * ?' TIMEZONE '+00:00' +partition by key(a) partitions 16; + + +create table yyy_db.arc_tbl like ttl_tbl; +CREATE TABLE arc_t1 LIKE ttl_t1 ENGINE = 'columnar' ARCHIVE_MODE = 'ttl'; + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/multi_ttl_cleanup.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/multi_ttl_cleanup.result new file mode 100644 index 000000000..cba6f92f3 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/multi_ttl_cleanup.result @@ -0,0 +1 @@ +toBeAdd \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/multi_ttl_cleanup.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/multi_ttl_cleanup.test.yml new file mode 100644 index 000000000..1f653cc78 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/multi_ttl_cleanup.test.yml @@ -0,0 +1,241 @@ +## DISABLE_FAST_SQL_PARSER + +CREATE TABLE IF NOT EXISTS `my_t0` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT, +`text_field` varchar(2048) NOT NULL, +`text_field1` varchar(32) NOT NULL, +`text_field2` varchar(32) NOT NULL, +`text_field3` varchar(32) NOT NULL, +`text_field4` varchar(32) NOT NULL, +`text_field5` varchar(32) NOT NULL, +`int_field` int(11) NOT NULL, +`date_field` datetime NOT NULL, +`float_field` float NOT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 5000001 DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 48; + + +CREATE TABLE IF NOT EXISTS `my_t1` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT, +`text_field` varchar(2048) NOT NULL, +`text_field1` varchar(32) NOT NULL, +`text_field2` varchar(32) NOT NULL, +`text_field3` varchar(32) NOT NULL, +`text_field4` varchar(32) NOT NULL, +`text_field5` varchar(32) NOT NULL, +`int_field` int(11) NOT NULL, +`date_field` datetime NOT NULL, +`float_field` float NOT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 5000001 DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 48; + + +CREATE TABLE IF NOT EXISTS `my_t2` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT, +`text_field` varchar(2048) NOT NULL, +`text_field1` varchar(32) NOT NULL, +`text_field2` varchar(32) NOT NULL, +`text_field3` varchar(32) NOT NULL, +`text_field4` varchar(32) NOT NULL, +`text_field5` varchar(32) NOT NULL, +`int_field` int(11) NOT NULL, +`date_field` datetime NOT NULL, +`float_field` float NOT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 5000001 DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 48; + + +CREATE TABLE IF NOT EXISTS `my_t3` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT, +`text_field` varchar(2048) NOT NULL, +`text_field1` varchar(32) NOT NULL, +`text_field2` varchar(32) NOT NULL, +`text_field3` varchar(32) NOT NULL, +`text_field4` varchar(32) NOT NULL, +`text_field5` varchar(32) NOT NULL, +`int_field` int(11) NOT NULL, +`date_field` datetime NOT NULL, +`float_field` float NOT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 5000001 DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 48; + + +CREATE TABLE IF NOT EXISTS `my_t4` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT, +`text_field` varchar(2048) NOT NULL, +`text_field1` varchar(32) NOT NULL, +`text_field2` varchar(32) NOT NULL, +`text_field3` varchar(32) NOT NULL, +`text_field4` varchar(32) NOT NULL, +`text_field5` varchar(32) NOT NULL, +`int_field` int(11) NOT NULL, +`date_field` datetime NOT NULL, +`float_field` float NOT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 5000001 DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 48; + + +CREATE TABLE IF NOT EXISTS `my_t5` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT, +`text_field` varchar(2048) NOT NULL, +`text_field1` varchar(32) NOT NULL, +`text_field2` varchar(32) NOT NULL, +`text_field3` varchar(32) NOT NULL, +`text_field4` varchar(32) NOT NULL, +`text_field5` varchar(32) NOT NULL, +`int_field` int(11) NOT NULL, +`date_field` datetime NOT NULL, +`float_field` float NOT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 5000001 DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 48; + + +CREATE TABLE IF NOT EXISTS `my_t6` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT, +`text_field` varchar(2048) NOT NULL, +`text_field1` varchar(32) NOT NULL, +`text_field2` varchar(32) NOT NULL, +`text_field3` varchar(32) NOT NULL, +`text_field4` varchar(32) NOT NULL, +`text_field5` varchar(32) NOT NULL, +`int_field` int(11) NOT NULL, +`date_field` datetime NOT NULL, +`float_field` float NOT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 5000001 DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 48; + + +CREATE TABLE IF NOT EXISTS `my_t7` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT, +`text_field` varchar(2048) NOT NULL, +`text_field1` varchar(32) NOT NULL, +`text_field2` varchar(32) NOT NULL, +`text_field3` varchar(32) NOT NULL, +`text_field4` varchar(32) NOT NULL, +`text_field5` varchar(32) NOT NULL, +`int_field` int(11) NOT NULL, +`date_field` datetime NOT NULL, +`float_field` float NOT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 5000001 DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 48; + +CREATE TABLE IF NOT EXISTS `my_t8` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT, +`text_field` varchar(2048) NOT NULL, +`text_field1` varchar(32) NOT NULL, +`text_field2` varchar(32) NOT NULL, +`text_field3` varchar(32) NOT NULL, +`text_field4` varchar(32) NOT NULL, +`text_field5` varchar(32) NOT NULL, +`int_field` int(11) NOT NULL, +`date_field` datetime NOT NULL, +`float_field` float NOT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 5000001 DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 48; + +CREATE TABLE IF NOT EXISTS `my_t9` ( +`id` bigint(20) NOT NULL AUTO_INCREMENT, +`text_field` varchar(2048) NOT NULL, +`text_field1` varchar(32) NOT NULL, +`text_field2` varchar(32) NOT NULL, +`text_field3` varchar(32) NOT NULL, +`text_field4` varchar(32) NOT NULL, +`text_field5` varchar(32) NOT NULL, +`int_field` int(11) NOT NULL, +`date_field` datetime NOT NULL, +`float_field` float NOT NULL, +PRIMARY KEY (`id`) +) ENGINE = InnoDB AUTO_INCREMENT = 5000001 DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`id`) +PARTITIONS 48; + +ALTER TABLE my_t0 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '*/5 * * * * ?' TIMEZONE '+00:00'; + +ALTER TABLE my_t1 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '*/5 * * * * ?' TIMEZONE '+00:00'; + +ALTER TABLE my_t2 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '*/5 * * * * ?' TIMEZONE '+00:00'; + +ALTER TABLE my_t3 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '*/5 * * * * ?' TIMEZONE '+00:00'; + +ALTER TABLE my_t4 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '*/5 * * * * ?' TIMEZONE '+00:00'; + +ALTER TABLE my_t5 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '*/5 * * * * ?' TIMEZONE '+00:00'; + +ALTER TABLE my_t6 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '*/5 * * * * ?' TIMEZONE '+00:00'; + +ALTER TABLE my_t7 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '*/5 * * * * ?' TIMEZONE '+00:00'; + +ALTER TABLE my_t8 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '*/5 * * * * ?' TIMEZONE '+00:00'; + +ALTER TABLE my_t9 +MODIFY TTL +SET +TTL_ENABLE = 'ON' +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' +TTL_JOB = CRON '*/5 * * * * ?' TIMEZONE '+00:00'; + + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/oss_tbl_alter.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/oss_tbl_alter.result new file mode 100644 index 000000000..cba6f92f3 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/oss_tbl_alter.result @@ -0,0 +1 @@ +toBeAdd \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/oss_tbl_alter.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/oss_tbl_alter.test.yml new file mode 100644 index 000000000..9b39cf785 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/oss_tbl_alter.test.yml @@ -0,0 +1,23 @@ +## DISABLE_FAST_SQL_PARSER + + +create table myttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +partition by key(a) partitions 8 +local partition by range(b) +STARTWITH '2021-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 12 +PRE ALLOCATE 6; + + +create table myoss_t1 +like myttl_t1 engine = 'local_disk' +archive_mode = 'ttl'; + +show create table myttl_t1; + +alter table myttl_t1 add column c int not null; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl.result new file mode 100644 index 000000000..b829cfd64 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl.result @@ -0,0 +1,65 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +create table my_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +alter table my_ttl_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 12 ARCHIVE_TABLE_POST_ALLOCATE = 48 +select TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE from information_schema.ttl_info where table_name='my_ttl_t1' limit 1 +TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE +my_ttl_t1,OFF,b,`b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00',* * */2 * * ?,null,null,12,48 +alter table my_ttl_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 3 ARCHIVE_TABLE_POST_ALLOCATE = 3 +select TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE from information_schema.ttl_info where table_name='my_ttl_t1' limit 1 +TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE +my_ttl_t1,OFF,b,`b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00',* * */2 * * ?,null,null,3,3 +create table my_arc_t1 like my_ttl_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL' +show create table my_ttl_t1 +Table,Create Table +my_ttl_t1,CREATE TABLE `my_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3 +alter table my_ttl_t1 cleanup expired data +show create table my_ttl_t1 +Table,Create Table +my_ttl_t1,CREATE TABLE `my_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = Columnar, + PARTITION p202410 VALUES LESS THAN ('2024-11-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl.test.yml new file mode 100644 index 000000000..b4b94054d --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl.test.yml @@ -0,0 +1,26 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; + +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create table my_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 12 ARCHIVE_TABLE_POST_ALLOCATE = 48; +select TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE from information_schema.ttl_info where table_name='my_ttl_t1' limit 1; +alter table my_ttl_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 3 ARCHIVE_TABLE_POST_ALLOCATE = 3; +select TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE from information_schema.ttl_info where table_name='my_ttl_t1' limit 1; +create table my_arc_t1 like my_ttl_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; +show create table my_ttl_t1; +alter table my_ttl_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +alter table my_ttl_t1 cleanup expired data; +show create table my_ttl_t1; + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl_ts.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl_ts.result new file mode 100644 index 000000000..613593a36 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl_ts.result @@ -0,0 +1,159 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +set time_zone='+08:00' +create table my_ttl_ts_t1( +a int not null auto_increment, +b timestamp default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +alter table my_ttl_ts_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE=5, ARCHIVE_TABLE_POST_ALLOCATE=3 +show create table my_ttl_ts_t1 +Table,Create Table +my_ttl_ts_t1,CREATE TABLE `my_ttl_ts_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 5, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_ts_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 3 ARCHIVE_TABLE_POST_ALLOCATE = 3 +show create table my_ttl_ts_t1 +Table,Create Table +my_ttl_ts_t1,CREATE TABLE `my_ttl_ts_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table my_arc_ts_t1 like my_ttl_ts_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL' +show create table my_ttl_ts_t1 +Table,Create Table +my_ttl_ts_t1,CREATE TABLE `my_ttl_ts_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_ts_t1` (`b`) + PARTITION BY RANGE(UNIX_TIMESTAMP(`b`)) + (PARTITION pstart VALUES LESS THAN (57600) ENGINE = Columnar, + PARTITION p202403 VALUES LESS THAN (1711900800) ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN (1714492800) ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN (1717171200) ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN (1719763200) ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN (1722441600) ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN (1725120000) ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN (1727712000) ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_ts_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_ts_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3 +alter table my_ttl_ts_t1 cleanup expired data +show create table my_ttl_ts_t1 +Table,Create Table +my_ttl_ts_t1,CREATE TABLE `my_ttl_ts_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_ts_t1` (`b`) + PARTITION BY RANGE(UNIX_TIMESTAMP(`b`)) + (PARTITION pstart VALUES LESS THAN (57600) ENGINE = Columnar, + PARTITION p202403 VALUES LESS THAN (1711900800) ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN (1714492800) ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN (1717171200) ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN (1719763200) ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN (1722441600) ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN (1725120000) ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN (1727712000) ENGINE = Columnar, + PARTITION p202410 VALUES LESS THAN (1730390400) ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_ts_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +set time_zone='+08:00' +create table rng_dt (dt datetime) +PARTITION BY RANGE COLUMNS(`dt`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +show create table rng_dt +Table,Create Table +rng_dt,CREATE TABLE `rng_dt` ( + `dt` datetime DEFAULT NULL, + KEY `auto_shard_key_dt` USING BTREE (`dt`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`dt`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +create table rng_ts (ts timestamp default current_timestamp) +PARTITION BY RANGE(UNIX_TIMESTAMP(`ts`)) +(PARTITION pstart VALUES LESS THAN (UNIX_TIMESTAMP('1970-01-02 00:00:00')) ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN (UNIX_TIMESTAMP('2024-04-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN (UNIX_TIMESTAMP('2024-05-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN (UNIX_TIMESTAMP('2024-06-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN (UNIX_TIMESTAMP('2024-07-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN (UNIX_TIMESTAMP('2024-08-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN (UNIX_TIMESTAMP('2024-09-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN (UNIX_TIMESTAMP('2024-10-01 00:00:00')) ENGINE = InnoDB) +show create table rng_ts +Table,Create Table +rng_ts,CREATE TABLE `rng_ts` ( + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + KEY `auto_shard_key_ts` USING BTREE (`ts`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(UNIX_TIMESTAMP(`ts`)) +(PARTITION pstart VALUES LESS THAN (57600) ENGINE = InnoDB, + PARTITION p202403 VALUES LESS THAN (1711900800) ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN (1714492800) ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN (1717171200) ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN (1719763200) ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN (1722441600) ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN (1725120000) ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN (1727712000) ENGINE = InnoDB) +set time_zone='+08:00' +select UNIX_TIMESTAMP('1970-01-02 00:00:00'), FROM_UNIXTIME(57600) +UNIX_TIMESTAMP('1970-01-02 00:00:00'),FROM_UNIXTIME(57600) +57600.0,1970-01-02 00:00:00.0 +select UNIX_TIMESTAMP('2024-04-01 00:00:00'), FROM_UNIXTIME(1711900800) +UNIX_TIMESTAMP('2024-04-01 00:00:00'),FROM_UNIXTIME(1711900800) +1711900800,2024-04-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-05-01 00:00:00'), FROM_UNIXTIME(1714492800) +UNIX_TIMESTAMP('2024-05-01 00:00:00'),FROM_UNIXTIME(1714492800) +1714492800,2024-05-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-06-01 00:00:00'), FROM_UNIXTIME(1717171200) +UNIX_TIMESTAMP('2024-06-01 00:00:00'),FROM_UNIXTIME(1717171200) +1717171200,2024-06-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-07-01 00:00:00'), FROM_UNIXTIME(1719763200) +UNIX_TIMESTAMP('2024-07-01 00:00:00'),FROM_UNIXTIME(1719763200) +1719763200,2024-07-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-08-01 00:00:00'), FROM_UNIXTIME(1722441600) +UNIX_TIMESTAMP('2024-08-01 00:00:00'),FROM_UNIXTIME(1722441600) +1722441600,2024-08-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-09-01 00:00:00'), FROM_UNIXTIME(1725120000) +UNIX_TIMESTAMP('2024-09-01 00:00:00'),FROM_UNIXTIME(1725120000) +1725120000,2024-09-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-10-01 00:00:00'), FROM_UNIXTIME(1727712000) +UNIX_TIMESTAMP('2024-10-01 00:00:00'),FROM_UNIXTIME(1727712000) +1727712000,2024-10-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-11-01 00:00:00'), FROM_UNIXTIME(1730390400) +UNIX_TIMESTAMP('2024-11-01 00:00:00'),FROM_UNIXTIME(1730390400) +1730390400,2024-11-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-12-01 00:00:00'), FROM_UNIXTIME(1732982400) +UNIX_TIMESTAMP('2024-12-01 00:00:00'),FROM_UNIXTIME(1732982400) +1732982400,2024-12-01 00:00:00.0 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl_ts.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl_ts.test.yml new file mode 100644 index 000000000..4f168fc16 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl_ts.test.yml @@ -0,0 +1,61 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; +set time_zone='+08:00'; + +create table my_ttl_ts_t1( +a int not null auto_increment, +b timestamp default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_ts_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE=5, ARCHIVE_TABLE_POST_ALLOCATE=3; +show create table my_ttl_ts_t1; +alter table my_ttl_ts_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 3 ARCHIVE_TABLE_POST_ALLOCATE = 3; +show create table my_ttl_ts_t1; +create table my_arc_ts_t1 like my_ttl_ts_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; +show create table my_ttl_ts_t1; +alter table my_ttl_ts_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +alter table my_ttl_ts_t1 cleanup expired data; +show create table my_ttl_ts_t1; + +set time_zone='+08:00'; +create table rng_dt (dt datetime) +PARTITION BY RANGE COLUMNS(`dt`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB); +show create table rng_dt; + +create table rng_ts (ts timestamp default current_timestamp) +PARTITION BY RANGE(UNIX_TIMESTAMP(`ts`)) +(PARTITION pstart VALUES LESS THAN (UNIX_TIMESTAMP('1970-01-02 00:00:00')) ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN (UNIX_TIMESTAMP('2024-04-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN (UNIX_TIMESTAMP('2024-05-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN (UNIX_TIMESTAMP('2024-06-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN (UNIX_TIMESTAMP('2024-07-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN (UNIX_TIMESTAMP('2024-08-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN (UNIX_TIMESTAMP('2024-09-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN (UNIX_TIMESTAMP('2024-10-01 00:00:00')) ENGINE = InnoDB); +show create table rng_ts; + +set time_zone='+08:00'; +select UNIX_TIMESTAMP('1970-01-02 00:00:00'), FROM_UNIXTIME(57600); +select UNIX_TIMESTAMP('2024-04-01 00:00:00'), FROM_UNIXTIME(1711900800); +select UNIX_TIMESTAMP('2024-05-01 00:00:00'), FROM_UNIXTIME(1714492800); +select UNIX_TIMESTAMP('2024-06-01 00:00:00'), FROM_UNIXTIME(1717171200); +select UNIX_TIMESTAMP('2024-07-01 00:00:00'), FROM_UNIXTIME(1719763200); +select UNIX_TIMESTAMP('2024-08-01 00:00:00'), FROM_UNIXTIME(1722441600); +select UNIX_TIMESTAMP('2024-09-01 00:00:00'), FROM_UNIXTIME(1725120000); +select UNIX_TIMESTAMP('2024-10-01 00:00:00'), FROM_UNIXTIME(1727712000); +select UNIX_TIMESTAMP('2024-11-01 00:00:00'), FROM_UNIXTIME(1730390400); +select UNIX_TIMESTAMP('2024-12-01 00:00:00'), FROM_UNIXTIME(1732982400); diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl_with_gsi.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl_with_gsi.test.yml new file mode 100644 index 000000000..45184ee69 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_ttl_with_gsi.test.yml @@ -0,0 +1,37 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table my_ttl_with_cci_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_with_cci_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 3 ARCHIVE_TABLE_POST_ALLOCATE = 3; + + +create table my_arc_with_cci_t1 like my_ttl_with_cci_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; + + +CREATE TABLE `my_ttl_with_gsi_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED INDEX `gsi_b` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION `p202403` VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202409` VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 + TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TYPE = '', ARCHIVE_TABLE_SCHEMA = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_with_cci_ttl.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_with_cci_ttl.result new file mode 100644 index 000000000..ddd360071 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_with_cci_ttl.result @@ -0,0 +1,84 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +set time_zone='+08:00' +## error_msg: $# not the same #$ +CREATE TABLE `my_ttl_with_cci_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_my_arc_with_cci_t1` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_SCHEMA = 'ttldb3', ARCHIVE_TABLE_SCHEMA='unknown_db', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) PARTITION BY KEY(`a`) PARTITIONS 2 +not the same +CREATE TABLE `my_ttl_with_cci_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_my_arc_with_cci_t1` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) PARTITION BY KEY(`a`) PARTITIONS 2 +show create table my_ttl_with_cci_t1 +Table,Create Table +my_ttl_with_cci_t1,CREATE TABLE `my_ttl_with_cci_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_with_cci_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +show create table my_arc_with_cci_t1 +View,Create View,character_set_client,collation_connection +my_arc_with_cci_t1,CREATE VIEW `my_arc_with_cci_t1` AS select `my_ttl_with_cci_t1`.`a`,`my_ttl_with_cci_t1`.`b` from `test_create_with_1204881928`.`my_ttl_with_cci_t1` force index (`arctmp_my_arc_with_cci_t1`);,utf8,utf8_general_ci +alter table my_ttl_with_cci_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 +alter table my_ttl_with_cci_t1 cleanup expired data +show create table my_ttl_with_cci_t1 +Table,Create Table +my_ttl_with_cci_t1,CREATE TABLE `my_ttl_with_cci_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_with_cci_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = Columnar, + PARTITION p202410 VALUES LESS THAN ('2024-11-01 00:00:00') ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +drop table my_ttl_with_cci_t1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_with_cci_ttl.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_with_cci_ttl.test.yml new file mode 100644 index 000000000..6dade6afb --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_create_with_cci_ttl.test.yml @@ -0,0 +1,51 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; +set time_zone='+08:00'; + +## error_msg: $# not the same #$ +CREATE TABLE `my_ttl_with_cci_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_my_arc_with_cci_t1` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION `p202403` VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202409` VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_SCHEMA = 'ttldb3', ARCHIVE_TABLE_SCHEMA='unknown_db', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) PARTITION BY KEY(`a`) PARTITIONS 2; + + +CREATE TABLE `my_ttl_with_cci_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_my_arc_with_cci_t1` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION `p202403` VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202409` VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) PARTITION BY KEY(`a`) PARTITIONS 2; +show create table my_ttl_with_cci_t1; +show create table my_arc_with_cci_t1; +alter table my_ttl_with_cci_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4; +alter table my_ttl_with_cci_t1 cleanup expired data; +show create table my_ttl_with_cci_t1; +drop table my_ttl_with_cci_t1; + + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage.result new file mode 100644 index 000000000..b627272fd --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage.result @@ -0,0 +1,77 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +set FORBID_DDL_WITH_CCI=false +set time_zone='+08:00' +create table my_ttl_t4( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `a` expire after 2 month timezone '+08:00' +not supported +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 second timezone '+08:00' +not supported +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 minute timezone '+08:00' +not supported +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 hour timezone '+08:00' +not supported +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 hour timezone '+08:00' +not supported +## error_msg: $# ttl_expr is not defined #$ +alter table my_ttl_t4 modify ttl set ttl_job = CRON '* * */2 * * * * ?' TIMEZONE '+08:00' +ttl_expr is not defined +## error_msg: $# invalid #$ +alter table my_ttl_t4 modify ttl set ttl_job = CRON '* * */2 * * * * ?' TIMEZONE '+08:00' +invalid +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00' +alter table my_ttl_t4 modify ttl set archive_table_pre_allocate = 3 archive_table_post_allocate = 3 +create table my_arc_t4 like my_ttl_t4 engine='columnar' archive_mode='ttl' +show create table my_ttl_t4 +Table,Create Table +my_ttl_t4,CREATE TABLE `my_ttl_t4` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_t4` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 month TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_t4', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +desc my_arc_t4 +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +## error_msg: $# not allowed #$ +drop view my_arc_t4 +not allowed +## error_msg: $# not allowed #$ +alter table my_ttl_t4 drop index arctmp_my_arc_t4 +not allowed +alter table my_ttl_t4 add column c datetime default null +## error_msg: $# change ttl column #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `c` expire after 2 month timezone '+08:00' +change ttl column +## error_msg: $# archive table #$ +create table my_arc_t5 like my_ttl_t4 engine='columnar' archive_mode='ttl' +archive table +drop table my_arc_t4 +drop table my_ttl_t4; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage.test.yml new file mode 100644 index 000000000..3cdf0a0b5 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage.test.yml @@ -0,0 +1,60 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; +set FORBID_DDL_WITH_CCI=false; +set time_zone='+08:00'; + +create table my_ttl_t4( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `a` expire after 2 month timezone '+08:00'; + +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 second timezone '+08:00'; + +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 minute timezone '+08:00'; + +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 hour timezone '+08:00'; + +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 hour timezone '+08:00'; + +## error_msg: $# ttl_expr is not defined #$ +alter table my_ttl_t4 modify ttl set ttl_job = CRON '* * */2 * * * * ?' TIMEZONE '+08:00'; + +## error_msg: $# invalid #$ +alter table my_ttl_t4 modify ttl set ttl_job = CRON '* * */2 * * * * ?' TIMEZONE '+08:00'; + +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; +alter table my_ttl_t4 modify ttl set archive_table_pre_allocate = 3 archive_table_post_allocate = 3; +create table my_arc_t4 like my_ttl_t4 engine='columnar' archive_mode='ttl'; +show create table my_ttl_t4; +desc my_arc_t4; + +## error_msg: $# not allowed #$ +drop view my_arc_t4; + +## error_msg: $# not allowed #$ +alter table my_ttl_t4 drop index arctmp_my_arc_t4; + +alter table my_ttl_t4 add column c datetime default null; + +## error_msg: $# change ttl column #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `c` expire after 2 month timezone '+08:00'; + +## error_msg: $# archive table #$ +create table my_arc_t5 like my_ttl_t4 engine='columnar' archive_mode='ttl'; + +drop table my_arc_t4; +drop table my_ttl_t4; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage2.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage2.result new file mode 100644 index 000000000..f24d4fc21 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage2.result @@ -0,0 +1,47 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create database ttl_test_drds_db2 mode = 'drds'; +create table my_bro_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +broadcast; +create table my_sin_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +single; +create table ttl_test_drds_db2.my_dbpart_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +dbpartition by hash(a); +create table my_locpart_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +partition by key(a) partitions 8 +local partition by range(b) +STARTWITH '2021-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 1 +PRE ALLOCATE 6; +## error_msg: $# not allowed #$ +alter table my_locpart_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; +not allowed +## error_msg: $# not allowed #$ +alter table my_bro_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; +not allowed +## error_msg: $# not allowed #$ +alter table my_sin_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; +not allowed +## error_msg: $# not allowed #$ +alter table ttl_test_drds_db2.my_dbpart_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; +not allowed +drop database if exists ttl_test_drds_db2; +drop table my_locpart_t1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage2.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage2.test.yml new file mode 100644 index 000000000..6f0b1d149 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_invalid_usage2.test.yml @@ -0,0 +1,54 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create database ttl_test_drds_db2 mode = 'drds'; + +create table my_bro_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +broadcast; + +create table my_sin_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +single; + +create table ttl_test_drds_db2.my_dbpart_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +dbpartition by hash(a); + +create table my_locpart_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +partition by key(a) partitions 8 +local partition by range(b) +STARTWITH '2021-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 1 +PRE ALLOCATE 6; + +## error_msg: $# not allowed #$ +alter table my_locpart_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; + +## error_msg: $# not allowed #$ +alter table my_bro_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; + +## error_msg: $# not allowed #$ +alter table my_sin_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; + +## error_msg: $# not allowed #$ +alter table ttl_test_drds_db2.my_dbpart_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; + +drop database if exists ttl_test_drds_db2; +drop table my_locpart_t1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl.result new file mode 100644 index 000000000..3c3129ccc --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl.result @@ -0,0 +1,21 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create table my_ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00'; +alter table my_ttl_t2 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +show create table my_ttl_t2; +Table,Create Table +my_ttl_t2,CREATE TABLE `my_ttl_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_t2 modify ttl set TTL_EXPR = `b` EXPIRE AFTER 30 DAY TIMEZONE '+08:00' TTL_JOB = CRON '* * */4 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 6; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl.test.yml new file mode 100644 index 000000000..bc0c93a2c --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl.test.yml @@ -0,0 +1,22 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table my_ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00'; +alter table my_ttl_t2 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +show create table my_ttl_t2; +alter table my_ttl_t2 modify ttl set TTL_EXPR = `b` EXPIRE AFTER 30 DAY TIMEZONE '+08:00' TTL_JOB = CRON '* * */4 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 6; + + + + + + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl2.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl2.result new file mode 100644 index 000000000..23027170a --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl2.result @@ -0,0 +1,102 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +set time_zone='+08:00' +create table my_modify_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL = TTL_DEFINITION ( +TTL_ENABLE = 'OFF', +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', +TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', +ARCHIVE_TYPE = '' ARCHIVE_TABLE_SCHEMA = '', +ARCHIVE_TABLE_NAME = '', +ARCHIVE_TABLE_PRE_ALLOCATE = 3, +ARCHIVE_TABLE_POST_ALLOCATE = 4 +) +partition by key(a) partitions 2 +show create table my_modify_ttl_t1 +Table,Create Table +my_modify_ttl_t1,CREATE TABLE `my_modify_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 4 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_modify_ttl_t1 modify ttl +set +TTL_ENABLE = 'OFF', +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', +TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', +ARCHIVE_TYPE = '' ARCHIVE_TABLE_SCHEMA = '', +ARCHIVE_TABLE_NAME = '', +ARCHIVE_TABLE_PRE_ALLOCATE = 1, +ARCHIVE_TABLE_POST_ALLOCATE = 1 +show create table my_modify_ttl_t1 +Table,Create Table +my_modify_ttl_t1,CREATE TABLE `my_modify_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 1, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table my_modify_arc_t1 like my_modify_ttl_t1 engine='columnar' archive_mode='ttl' +show create table my_modify_ttl_t1 +Table,Create Table +my_modify_ttl_t1,CREATE TABLE `my_modify_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_modify_arc_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_modify_arc_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 1, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_modify_ttl_t1 modify ttl set archive_table_pre_allocate = 2, archive_table_post_allocate = 1 +show create table my_modify_ttl_t1 +Table,Create Table +my_modify_ttl_t1,CREATE TABLE `my_modify_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_modify_arc_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_modify_arc_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_modify_ttl_t1 cleanup expired data +show create table my_modify_ttl_t1 +Table,Create Table +my_modify_ttl_t1,CREATE TABLE `my_modify_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_modify_arc_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_modify_arc_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +drop table my_modify_ttl_t1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl2.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl2.test.yml new file mode 100644 index 000000000..5e7f41bd1 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_modify_ttl2.test.yml @@ -0,0 +1,52 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; +set time_zone='+08:00'; + +create table my_modify_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL = TTL_DEFINITION ( +TTL_ENABLE = 'OFF', +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', +TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', +ARCHIVE_TYPE = '' ARCHIVE_TABLE_SCHEMA = '', +ARCHIVE_TABLE_NAME = '', +ARCHIVE_TABLE_PRE_ALLOCATE = 3, +ARCHIVE_TABLE_POST_ALLOCATE = 4 +) +partition by key(a) partitions 2; + +show create table my_modify_ttl_t1; + +alter table my_modify_ttl_t1 modify ttl +set +TTL_ENABLE = 'OFF', +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', +TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', +ARCHIVE_TYPE = '' ARCHIVE_TABLE_SCHEMA = '', +ARCHIVE_TABLE_NAME = '', +ARCHIVE_TABLE_PRE_ALLOCATE = 1, +ARCHIVE_TABLE_POST_ALLOCATE = 1 +; + +show create table my_modify_ttl_t1; + +create table my_modify_arc_t1 like my_modify_ttl_t1 engine='columnar' archive_mode='ttl'; +show create table my_modify_ttl_t1; + +alter table my_modify_ttl_t1 modify ttl set archive_table_pre_allocate = 2, archive_table_post_allocate = 1; +show create table my_modify_ttl_t1; + +alter table my_modify_ttl_t1 cleanup expired data; +show create table my_modify_ttl_t1; + +drop table my_modify_ttl_t1; + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_remove_ttl.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_remove_ttl.result new file mode 100644 index 000000000..8b6ce232f --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_remove_ttl.result @@ -0,0 +1,65 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +set time_zone='+08:00' +create table my_rm_ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +alter table my_rm_ttl_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2 +show create table my_rm_ttl_t2 +Table,Create Table +my_rm_ttl_t2,CREATE TABLE `my_rm_ttl_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table my_rm_arc_t2 like my_rm_ttl_t2 engine='columnar' archive_mode='ttl' +show create table my_rm_ttl_t2 +Table,Create Table +my_rm_ttl_t2,CREATE TABLE `my_rm_ttl_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_rm_arc_t2` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_rm_arc_t2', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +## error_msg: $# has bound #$ +alter table my_rm_ttl_t2 remove ttl +has bound +drop table my_rm_arc_t2 +show create table my_rm_ttl_t2 +Table,Create Table +my_rm_ttl_t2,CREATE TABLE `my_rm_ttl_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_rm_ttl_t2 remove ttl +show create table my_rm_ttl_t2 +Table,Create Table +my_rm_ttl_t2,CREATE TABLE `my_rm_ttl_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 2 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_remove_ttl.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_remove_ttl.test.yml new file mode 100644 index 000000000..7b1c7619f --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_remove_ttl.test.yml @@ -0,0 +1,30 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; +set time_zone='+08:00'; + +create table my_rm_ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_rm_ttl_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2; +show create table my_rm_ttl_t2; +create table my_rm_arc_t2 like my_rm_ttl_t2 engine='columnar' archive_mode='ttl'; +show create table my_rm_ttl_t2; +## error_msg: $# has bound #$ +alter table my_rm_ttl_t2 remove ttl; +drop table my_rm_arc_t2; +show create table my_rm_ttl_t2; +alter table my_rm_ttl_t2 remove ttl; +show create table my_rm_ttl_t2; + + + + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_alter_col.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_alter_col.result new file mode 100644 index 000000000..f847e67db --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_alter_col.result @@ -0,0 +1,54 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +set FORBID_DDL_WITH_CCI=false +create table my_ttl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +alter table my_ttl_t3 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' +alter table my_ttl_t3 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3 +show create table my_ttl_t3 +Table,Create Table +my_ttl_t3,CREATE TABLE `my_ttl_t3` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table my_arc_t3 like my_ttl_t3 engine='columnar' archive_mode='ttl' +desc my_arc_t3 +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +alter table my_ttl_t3 add column c datetime default null +desc my_arc_t3 +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +c,datetime(0),YES,,NULL, +alter table my_ttl_t3 add column d datetime default null +desc my_arc_t3 +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +c,datetime(0),YES,,NULL, +d,datetime(0),YES,,NULL, +alter table my_ttl_t3 drop column d +desc my_arc_t3 +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +c,datetime(0),YES,,NULL, +alter table my_ttl_t3 change column c d datetime default null +desc my_arc_t3 +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +d,datetime(0),YES,,NULL, \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_alter_col.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_alter_col.test.yml new file mode 100644 index 000000000..21a4b90c0 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_alter_col.test.yml @@ -0,0 +1,28 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; +set FORBID_DDL_WITH_CCI=false; + +create table my_ttl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_t3 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00'; +alter table my_ttl_t3 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +show create table my_ttl_t3; +create table my_arc_t3 like my_ttl_t3 engine='columnar' archive_mode='ttl'; +desc my_arc_t3; +alter table my_ttl_t3 add column c datetime default null; +desc my_arc_t3; +alter table my_ttl_t3 add column d datetime default null; +desc my_arc_t3; +alter table my_ttl_t3 drop column d; +desc my_arc_t3; +alter table my_ttl_t3 change column c d datetime default null; +desc my_arc_t3; diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg.result new file mode 100644 index 000000000..b2db819a5 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg.result @@ -0,0 +1,66 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +create table my_ttl_tg_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +alter table my_ttl_tg_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2 +create table my_arc_tg_t1 like my_ttl_tg_t1 engine='columnar' archive_mode='ttl' +create table my_ttl_tg_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +alter table my_ttl_tg_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2 +create table my_arc_tg_t2 like my_ttl_tg_t2 engine='columnar' archive_mode='ttl' +alter table my_ttl_tg_t1 cleanup expired data +alter table my_ttl_tg_t2 cleanup expired data +alter table my_ttl_tg_t2 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 4 +alter table my_ttl_tg_t2 cleanup expired data +show create table my_ttl_tg_t1 +Table,Create Table +my_ttl_tg_t1,CREATE TABLE `my_ttl_tg_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tg_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tg_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +show create table my_ttl_tg_t2 +Table,Create Table +my_ttl_tg_t2,CREATE TABLE `my_ttl_tg_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tg_t2` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = Columnar, + PARTITION p202410 VALUES LESS THAN ('2024-11-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tg_t2', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 4 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +drop table my_ttl_tg_t1 +drop table my_ttl_tg_t2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg.test.yml new file mode 100644 index 000000000..180946832 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg.test.yml @@ -0,0 +1,37 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; + +create table my_ttl_tg_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_tg_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2; +create table my_arc_tg_t1 like my_ttl_tg_t1 engine='columnar' archive_mode='ttl'; + +create table my_ttl_tg_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_tg_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2; +create table my_arc_tg_t2 like my_ttl_tg_t2 engine='columnar' archive_mode='ttl'; + +alter table my_ttl_tg_t1 cleanup expired data; +alter table my_ttl_tg_t2 cleanup expired data; + +alter table my_ttl_tg_t2 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 4; +alter table my_ttl_tg_t2 cleanup expired data; + +show create table my_ttl_tg_t1; +show create table my_ttl_tg_t2; + +drop table my_ttl_tg_t1; +drop table my_ttl_tg_t2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg2.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg2.result new file mode 100644 index 000000000..aa8621db7 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg2.result @@ -0,0 +1,63 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +create table my_ttl_tg_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +alter table my_ttl_tg_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2 +create table my_arc_tg_t1 like my_ttl_tg_t1 engine='columnar' archive_mode='ttl' +create table my_ttl_tg_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +alter table my_ttl_tg_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2 +create table my_arc_tg_t2 like my_ttl_tg_t2 engine='columnar' archive_mode='ttl' +alter table my_ttl_tg_t1 cleanup expired data +alter table my_ttl_tg_t2 cleanup expired data +alter table my_ttl_tg_t2 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 4 +alter table my_ttl_tg_t2 cleanup expired data +show create table my_ttl_tg_t1 +Table,Create Table +my_ttl_tg_t1,CREATE TABLE `my_ttl_tg_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tg_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tg_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +show create table my_ttl_tg_t2 +Table,Create Table +my_ttl_tg_t2,CREATE TABLE `my_ttl_tg_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tg_t2` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = Columnar, + PARTITION p202410 VALUES LESS THAN ('2024-11-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tg_t2', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 4 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg2.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg2.test.yml new file mode 100644 index 000000000..3bc596d27 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_cci_tg2.test.yml @@ -0,0 +1,33 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table my_ttl_tg_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_tg_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2; +create table my_arc_tg_t1 like my_ttl_tg_t1 engine='columnar' archive_mode='ttl'; + +create table my_ttl_tg_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_tg_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2; +create table my_arc_tg_t2 like my_ttl_tg_t2 engine='columnar' archive_mode='ttl'; + +alter table my_ttl_tg_t1 cleanup expired data; +alter table my_ttl_tg_t2 cleanup expired data; + +alter table my_ttl_tg_t2 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 4; +alter table my_ttl_tg_t2 cleanup expired data; + +show create table my_ttl_tg_t1; +show create table my_ttl_tg_t2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_info_view.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_info_view.result new file mode 100644 index 000000000..cf0516a18 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_info_view.result @@ -0,0 +1,20 @@ +## DISABLE_FAST_SQL_PARSER +desc information_schema.ttl_info; +Field,Type,Null,Key,Default,Extra +TABLE_SCHEMA,varchar,YES,,NULL, +TABLE_NAME,varchar,YES,,NULL, +TTL_ENABLE,varchar,YES,,NULL, +TTL_COL,varchar,YES,,NULL, +TTL_EXPR,varchar,YES,,NULL, +TTL_CRON,varchar,YES,,NULL, +ARCHIVE_TYPE,varchar,YES,,NULL, +ARCHIVE_TABLE_SCHEMA,varchar,YES,,NULL, +ARCHIVE_TABLE_NAME,varchar,YES,,NULL, +ARCHIVE_TABLE_PRE_ALLOCATE,varchar,YES,,NULL, +ARCHIVE_TABLE_POST_ALLOCATE,varchar,YES,,NULL, +desc information_schema.ttl_schedule; +Field,Type,Null,Key,Default,Extra +TABLE_SCHEMA,varchar,YES,,NULL, +TABLE_NAME,varchar,YES,,NULL, +METRIC_KEY,varchar,YES,,NULL, +METRIC_VAL,varchar,YES,,NULL, \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_info_view.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_info_view.test.yml new file mode 100644 index 000000000..0d622b762 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_info_view.test.yml @@ -0,0 +1,5 @@ +## DISABLE_FAST_SQL_PARSER + +desc information_schema.ttl_info; + +desc information_schema.ttl_schedule; diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_unit.result b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_unit.result new file mode 100644 index 000000000..835140d27 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_unit.result @@ -0,0 +1,199 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +set time_zone='+08:00' +create table my_ttl_tb_day( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +create table my_ttl_tb_month( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +create table my_ttl_tb_year( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +alter table my_ttl_tb_day modify ttl set ttl_expr = `b` expire after 7 day timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1 +create table my_arc_tb_day like my_ttl_tb_day engine='columnar' archive_mode='ttl' +show create table my_ttl_tb_day +Table,Create Table +my_ttl_tb_day,CREATE TABLE `my_ttl_tb_day` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p20240626 VALUES LESS THAN ('2024-06-27 00:00:00') ENGINE = Columnar, + PARTITION p20240627 VALUES LESS THAN ('2024-06-28 00:00:00') ENGINE = Columnar, + PARTITION p20240628 VALUES LESS THAN ('2024-06-29 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 7 day TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 1, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_day modify ttl set archive_table_pre_allocate = 2 +alter table my_ttl_tb_day cleanup expired data +show create table my_ttl_tb_day +Table,Create Table +my_ttl_tb_day,CREATE TABLE `my_ttl_tb_day` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p20240626 VALUES LESS THAN ('2024-06-27 00:00:00') ENGINE = Columnar, + PARTITION p20240627 VALUES LESS THAN ('2024-06-28 00:00:00') ENGINE = Columnar, + PARTITION p20240628 VALUES LESS THAN ('2024-06-29 00:00:00') ENGINE = Columnar, + PARTITION p20240629 VALUES LESS THAN ('2024-06-30 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 7 day TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_day modify ttl set archive_table_pre_allocate = 3 +alter table my_ttl_tb_day cleanup expired data +show create table my_ttl_tb_day +Table,Create Table +my_ttl_tb_day,CREATE TABLE `my_ttl_tb_day` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p20240626 VALUES LESS THAN ('2024-06-27 00:00:00') ENGINE = Columnar, + PARTITION p20240627 VALUES LESS THAN ('2024-06-28 00:00:00') ENGINE = Columnar, + PARTITION p20240628 VALUES LESS THAN ('2024-06-29 00:00:00') ENGINE = Columnar, + PARTITION p20240629 VALUES LESS THAN ('2024-06-30 00:00:00') ENGINE = Columnar, + PARTITION p20240630 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 7 day TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_month modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1 +create table my_arc_tb_month like my_ttl_tb_month engine='columnar' archive_mode='ttl' +show create table my_ttl_tb_month +Table,Create Table +my_ttl_tb_month,CREATE TABLE `my_ttl_tb_month` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tb_month` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 month TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_month', ARCHIVE_TABLE_PRE_ALLOCATE = 1, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_month modify ttl set archive_table_pre_allocate = 2 +alter table my_ttl_tb_month cleanup expired data +show create table my_ttl_tb_month +Table,Create Table +my_ttl_tb_month,CREATE TABLE `my_ttl_tb_month` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tb_month` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 month TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_month', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_month modify ttl set archive_table_pre_allocate = 3 +alter table my_ttl_tb_month cleanup expired data +show create table my_ttl_tb_month +Table,Create Table +my_ttl_tb_month,CREATE TABLE `my_ttl_tb_month` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tb_month` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 month TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_month', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_year modify ttl set ttl_expr = `b` expire after 2 year timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1 +create table my_arc_tb_year like my_ttl_tb_year engine='columnar' archive_mode='ttl' +show create table my_ttl_tb_year +Table,Create Table +my_ttl_tb_year,CREATE TABLE `my_ttl_tb_year` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tb_year` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p2023 VALUES LESS THAN ('2024-01-01 00:00:00') ENGINE = Columnar, + PARTITION p2024 VALUES LESS THAN ('2025-01-01 00:00:00') ENGINE = Columnar, + PARTITION p2025 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 year TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_year', ARCHIVE_TABLE_PRE_ALLOCATE = 1, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_year modify ttl set archive_table_pre_allocate = 2 +alter table my_ttl_tb_year cleanup expired data +show create table my_ttl_tb_year +Table,Create Table +my_ttl_tb_year,CREATE TABLE `my_ttl_tb_year` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tb_year` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p2023 VALUES LESS THAN ('2024-01-01 00:00:00') ENGINE = Columnar, + PARTITION p2024 VALUES LESS THAN ('2025-01-01 00:00:00') ENGINE = Columnar, + PARTITION p2025 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = Columnar, + PARTITION p2026 VALUES LESS THAN ('2027-01-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 year TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_year', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_year modify ttl set archive_table_pre_allocate = 3 +alter table my_ttl_tb_year cleanup expired data +show create table my_ttl_tb_year +Table,Create Table +my_ttl_tb_year,CREATE TABLE `my_ttl_tb_year` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_my_arc_tb_year` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p2023 VALUES LESS THAN ('2024-01-01 00:00:00') ENGINE = Columnar, + PARTITION p2024 VALUES LESS THAN ('2025-01-01 00:00:00') ENGINE = Columnar, + PARTITION p2025 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = Columnar, + PARTITION p2026 VALUES LESS THAN ('2027-01-01 00:00:00') ENGINE = Columnar, + PARTITION p2027 VALUES LESS THAN ('2028-01-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 year TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_year', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +drop table my_ttl_tb_day +drop table my_ttl_tb_month +drop table my_ttl_tb_year; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_unit.test.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_unit.test.yml new file mode 100644 index 000000000..326155865 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/test_ttl_unit.test.yml @@ -0,0 +1,69 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; +set time_zone='+08:00'; + +create table my_ttl_tb_day( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +create table my_ttl_tb_month( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +create table my_ttl_tb_year( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +alter table my_ttl_tb_day modify ttl set ttl_expr = `b` expire after 7 day timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1; +create table my_arc_tb_day like my_ttl_tb_day engine='columnar' archive_mode='ttl'; +show create table my_ttl_tb_day; +alter table my_ttl_tb_day modify ttl set archive_table_pre_allocate = 2; +alter table my_ttl_tb_day cleanup expired data; +show create table my_ttl_tb_day; +alter table my_ttl_tb_day modify ttl set archive_table_pre_allocate = 3; +alter table my_ttl_tb_day cleanup expired data; +show create table my_ttl_tb_day; + +alter table my_ttl_tb_month modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1; +create table my_arc_tb_month like my_ttl_tb_month engine='columnar' archive_mode='ttl'; +show create table my_ttl_tb_month; +alter table my_ttl_tb_month modify ttl set archive_table_pre_allocate = 2; +alter table my_ttl_tb_month cleanup expired data; +show create table my_ttl_tb_month; +alter table my_ttl_tb_month modify ttl set archive_table_pre_allocate = 3; +alter table my_ttl_tb_month cleanup expired data; +show create table my_ttl_tb_month; + +alter table my_ttl_tb_year modify ttl set ttl_expr = `b` expire after 2 year timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1; +create table my_arc_tb_year like my_ttl_tb_year engine='columnar' archive_mode='ttl'; +show create table my_ttl_tb_year; +alter table my_ttl_tb_year modify ttl set archive_table_pre_allocate = 2; +alter table my_ttl_tb_year cleanup expired data; +show create table my_ttl_tb_year; +alter table my_ttl_tb_year modify ttl set archive_table_pre_allocate = 3; +alter table my_ttl_tb_year cleanup expired data; +show create table my_ttl_tb_year; + +drop table my_ttl_tb_day; +drop table my_ttl_tb_month; +drop table my_ttl_tb_year; + + + + + + diff --git a/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/testcase.config.yml new file mode 100644 index 000000000..931dcaa28 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env/TtlPartitionTableTest/testcase.config.yml @@ -0,0 +1,13 @@ +test_create_ttl +test_modify_ttl +test_ttl_alter_col +test_create_ttl_ts +test_invalid_usage +test_invalid_usage2 +test_ttl_unit +test_modify_ttl2 +test_remove_ttl +test_create_with_cci_ttl +test_ttl_info_view +test_ttl_cci_tg +test_ttl_cci_tg2 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_add_index.result b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_add_index.result index 3bc16ff31..578bb38de 100644 --- a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_add_index.result +++ b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_add_index.result @@ -11,7 +11,7 @@ PRIMARY KEY (x) show create table `t_order_0`; Table,Create Table t_order_0,CREATE TABLE `t_order_0` ( - `x` int(11) NOT NULL AUTO_INCREMENT, + `x` int NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`) @@ -19,13 +19,13 @@ t_order_0,CREATE TABLE `t_order_0` ( show full create table `t_order_0`; Table,Create Table t_order_0,CREATE PARTITION TABLE `t_order_0` ( - `x` int(11) NOT NULL AUTO_INCREMENT, + `x` int NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ CREATE TABLE `t_order_1` ( `x` int NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -35,7 +35,7 @@ CREATE TABLE `t_order_1` ( show create table `t_order_1`; Table,Create Table t_order_1,CREATE TABLE `t_order_1` ( - `x` int(11) NOT NULL AUTO_INCREMENT, + `x` int NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`) @@ -43,13 +43,13 @@ t_order_1,CREATE TABLE `t_order_1` ( show full create table `t_order_1`; Table,Create Table t_order_1,CREATE PARTITION TABLE `t_order_1` ( - `x` int(11) NOT NULL AUTO_INCREMENT, + `x` int NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ CREATE TABLE `t_order_2` ( `x` int NOT NULL, @@ -59,21 +59,21 @@ CREATE TABLE `t_order_2` ( show create table `t_order_2`; Table,Create Table t_order_2,CREATE TABLE `t_order_2` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 show full create table `t_order_2`; Table,Create Table t_order_2,CREATE PARTITION TABLE `t_order_2` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, - `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + `_drds_implicit_id_` bigint NOT NULL AUTO_INCREMENT, PRIMARY KEY (`_drds_implicit_id_`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`_drds_implicit_id_`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ # now generated three types of base table. create index `agsi_0` on `t_order_0`(`order_id`); @@ -99,30 +99,30 @@ alter table `t_order_2` add global unique index `agsi_9b` using btree (`order_id show full create table agsi_0; Table,Create Table agsi_0_$,CREATE TABLE `agsi_0_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`), LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`x`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ show full create table agsi_1; Table,Create Table agsi_1_$,CREATE TABLE `agsi_1_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`seller_id`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ show full create table agsi_2; Table,Create Table agsi_2_$,CREATE TABLE `agsi_2_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`), LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) @@ -133,10 +133,10 @@ PARTITIONS 2 show full create table agsi_3; Table,Create Table agsi_3_$,CREATE TABLE `agsi_3_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -145,9 +145,9 @@ show full create table agsi_4; Table,Create Table agsi_4_$,CREATE TABLE `agsi_4_$` ( `order_id` varchar(20) DEFAULT NULL, - `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + `_drds_implicit_id_` bigint NOT NULL, + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -155,30 +155,30 @@ PARTITIONS 2 show full create table agsi_5; Table,Create Table agsi_5_$,CREATE TABLE `agsi_5_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`), LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`x`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ show full create table agsi_6; Table,Create Table agsi_6_$,CREATE TABLE `agsi_6_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`seller_id`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ show full create table agsi_7; Table,Create Table agsi_7_$,CREATE TABLE `agsi_7_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`), LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) @@ -189,10 +189,10 @@ PARTITIONS 2 show full create table agsi_8; Table,Create Table agsi_8_$,CREATE TABLE `agsi_8_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -201,9 +201,9 @@ show full create table agsi_9; Table,Create Table agsi_9_$,CREATE TABLE `agsi_9_$` ( `order_id` varchar(20) DEFAULT NULL, - `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + `_drds_implicit_id_` bigint NOT NULL, + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -211,30 +211,30 @@ PARTITIONS 2 show full create table agsi_0b; Table,Create Table agsi_0b_$,CREATE TABLE `agsi_0b_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`), LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`x`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ show full create table agsi_1b; Table,Create Table agsi_1b_$,CREATE TABLE `agsi_1b_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`seller_id`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ show full create table agsi_2b; Table,Create Table agsi_2b_$,CREATE TABLE `agsi_2b_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`), LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) @@ -245,10 +245,10 @@ PARTITIONS 2 show full create table agsi_3b; Table,Create Table agsi_3b_$,CREATE TABLE `agsi_3b_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -257,9 +257,9 @@ show full create table agsi_4b; Table,Create Table agsi_4b_$,CREATE TABLE `agsi_4b_$` ( `order_id` varchar(20) DEFAULT NULL, - `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + `_drds_implicit_id_` bigint NOT NULL, + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -267,30 +267,30 @@ PARTITIONS 2 show full create table agsi_5b; Table,Create Table agsi_5b_$,CREATE TABLE `agsi_5b_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`), LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`x`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ show full create table agsi_6b; Table,Create Table agsi_6b_$,CREATE TABLE `agsi_6b_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id_seller_id` USING BTREE (`order_id`, `seller_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`,`seller_id`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ show full create table agsi_7b; Table,Create Table agsi_7b_$,CREATE TABLE `agsi_7b_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`), LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) @@ -301,10 +301,10 @@ PARTITIONS 2 show full create table agsi_8b; Table,Create Table agsi_8b_$,CREATE TABLE `agsi_8b_$` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`) + PRIMARY KEY (`x`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -313,9 +313,9 @@ show full create table agsi_9b; Table,Create Table agsi_9b_$,CREATE TABLE `agsi_9b_$` ( `order_id` varchar(20) DEFAULT NULL, - `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + `_drds_implicit_id_` bigint NOT NULL, + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS 2 @@ -328,34 +328,34 @@ Table 'agsi_0' not found and multiple GSI table found show full create table `t_order_0`; Table,Create Table t_order_0,CREATE PARTITION TABLE `t_order_0` ( - `x` int(11) NOT NULL AUTO_INCREMENT, + `x` int NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`), GLOBAL INDEX /* agsi_0b_$ */ `agsi_0b` USING BTREE (`order_id`) PARTITION BY KEY(`order_id`,`x`) - PARTITIONS #@#, + PARTITIONS 3, GLOBAL INDEX /* agsi_0_$ */ `agsi_0` (`order_id`) PARTITION BY KEY(`order_id`,`x`) - PARTITIONS #@#, + PARTITIONS 3, UNIQUE GLOBAL INDEX /* agsi_1b_$ */ `agsi_1b` USING BTREE (`order_id`, `seller_id`) PARTITION BY KEY(`order_id`,`seller_id`) - PARTITIONS #@#, + PARTITIONS 3, UNIQUE GLOBAL INDEX /* agsi_1_$ */ `agsi_1` (`order_id`, `seller_id`) PARTITION BY KEY(`order_id`,`seller_id`) - PARTITIONS #@#, + PARTITIONS 3, GLOBAL INDEX /* agsi_5b_$ */ `agsi_5b` USING BTREE (`order_id`) PARTITION BY KEY(`order_id`,`x`) - PARTITIONS #@#, + PARTITIONS 3, GLOBAL INDEX /* agsi_5_$ */ `agsi_5` (`order_id`) PARTITION BY KEY(`order_id`,`x`) - PARTITIONS #@#, + PARTITIONS 3, UNIQUE GLOBAL INDEX /* agsi_6b_$ */ `agsi_6b` USING BTREE (`order_id`, `seller_id`) PARTITION BY KEY(`order_id`,`seller_id`) - PARTITIONS #@#, + PARTITIONS 3, UNIQUE GLOBAL INDEX /* agsi_6_$ */ `agsi_6` (`order_id`, `seller_id`) PARTITION BY KEY(`order_id`,`seller_id`) - PARTITIONS #@#, + PARTITIONS 3, UNIQUE LOCAL KEY `_local_agsi_1` (`order_id`, `seller_id`), UNIQUE LOCAL KEY `_local_agsi_1b` USING BTREE (`order_id`, `seller_id`), UNIQUE LOCAL KEY `_local_agsi_6` (`order_id`, `seller_id`), @@ -366,12 +366,12 @@ t_order_0,CREATE PARTITION TABLE `t_order_0` ( LOCAL KEY `_local_agsi_5b` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ show full create table `t_order_1`; Table,Create Table t_order_1,CREATE PARTITION TABLE `t_order_1` ( - `x` int(11) NOT NULL AUTO_INCREMENT, + `x` int NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`x`), @@ -409,19 +409,19 @@ t_order_1,CREATE PARTITION TABLE `t_order_1` ( LOCAL KEY `_local_agsi_7b` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ show full create table `t_order_2`; Table,Create Table t_order_2,CREATE PARTITION TABLE `t_order_2` ( - `x` int(11) NOT NULL, + `x` int NOT NULL, `order_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, - `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT, + `_drds_implicit_id_` bigint NOT NULL AUTO_INCREMENT, PRIMARY KEY (`_drds_implicit_id_`), GLOBAL INDEX /* agsi_0_$ */ `agsi_0` (`order_id`) PARTITION BY KEY(`order_id`,`_drds_implicit_id_`) - PARTITIONS #@#, + PARTITIONS 3, UNIQUE GLOBAL INDEX /* agsi_4b_$ */ `agsi_4b` USING BTREE (`order_id`) PARTITION BY KEY(`order_id`) PARTITIONS 2, @@ -441,7 +441,7 @@ t_order_2,CREATE PARTITION TABLE `t_order_2` ( LOCAL KEY `_local_agsi_0` (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`_drds_implicit_id_`) -PARTITIONS #@# +PARTITIONS 3 /* tablegroup = `tg` */ drop table if exists `t_order_0`; drop table if exists `t_order_1`; diff --git a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_alter_partitions.result b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_alter_partitions.result index 65cffd811..3c5a9f28b 100644 --- a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_alter_partitions.result +++ b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_alter_partitions.result @@ -72,8 +72,8 @@ ugidx_$,CREATE TABLE `ugidx_$` ( `a` int(11) NOT NULL, `c` int(11) NOT NULL, `d` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`), + UNIQUE KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`c`,`d`) PARTITIONS #@# @@ -126,8 +126,8 @@ ugidx_$,CREATE TABLE `ugidx_$` ( `a` int(11) NOT NULL, `c` int(11) NOT NULL, `d` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`), - KEY `_gsi_pk_idx_` USING BTREE (`a`) + PRIMARY KEY (`a`), + UNIQUE KEY `auto_shard_key_c_d` USING BTREE (`c`, `d`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`c`,`d`) PARTITIONS 4 diff --git a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_composite_index.result b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_composite_index.result index 4683bd4fe..0ec44c136 100644 --- a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_composite_index.result +++ b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_composite_index.result @@ -198,8 +198,8 @@ agsi_1_$,CREATE TABLE `agsi_1_$` ( `y` int(11) NOT NULL, `z` int(11) NOT NULL, `d` float NOT NULL, - UNIQUE KEY `auto_shard_key_y_z_d` USING BTREE (`y`, `z`, `d`), - KEY `_gsi_pk_idx_` USING BTREE (`x`, `y`) + PRIMARY KEY (`x`, `y`), + UNIQUE KEY `auto_shard_key_y_z_d` USING BTREE (`y`, `z`, `d`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`y`,`z`) PARTITIONS 3 @@ -250,8 +250,8 @@ agsi_3_$,CREATE TABLE `agsi_3_$` ( `c` int(11) NOT NULL, `e` int(11) NOT NULL, `f` int(11) NOT NULL, - UNIQUE KEY `auto_shard_key_x_y_z_c_e_f` USING BTREE (`x`, `y`, `z`, `c`, `e`, `f`), - KEY `_gsi_pk_idx_` USING BTREE (`x`, `y`) + PRIMARY KEY (`x`, `y`), + UNIQUE KEY `auto_shard_key_x_y_z_c_e_f` USING BTREE (`x`, `y`, `z`, `c`, `e`, `f`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`,`y`,`z`,`c`,`e`) PARTITIONS 3 @@ -264,8 +264,8 @@ agsi_3_$,CREATE TABLE `agsi_3_$` ( `c` int(11) NOT NULL, `e` int(11) NOT NULL, `f` int(11) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_x_y_z_c_e_f` USING BTREE (`x`, `y`, `z`, `c`, `e`, `f`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`, `y`) + PRIMARY KEY (`x`, `y`), + UNIQUE LOCAL KEY `auto_shard_key_x_y_z_c_e_f` USING BTREE (`x`, `y`, `z`, `c`, `e`, `f`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`x`,`y`,`z`,`c`,`e`) PARTITIONS 3 diff --git a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_create_with_ugsi.result b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_create_with_ugsi.result index c74776c4f..5466cd4ba 100644 --- a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_create_with_ugsi.result +++ b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_create_with_ugsi.result @@ -24,8 +24,8 @@ Table,Create Table ugsi_b_$,CREATE TABLE `ugsi_b_$` ( `b` int(11) NOT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_b` USING BTREE (`b`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_b` USING BTREE (`b`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`b`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_drop_add_primary_key.result b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_drop_add_primary_key.result index 553af55d4..8939364c0 100644 --- a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_drop_add_primary_key.result +++ b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_drop_add_primary_key.result @@ -108,8 +108,8 @@ idx_order_$,CREATE TABLE `idx_order_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, `gmt_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`, `gmt_modified`) + PRIMARY KEY (`x`, `gmt_modified`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# @@ -146,8 +146,8 @@ Table,Create Table idx_order2_$,CREATE TABLE `idx_order2_$` ( `order_id` varchar(20) DEFAULT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# @@ -191,8 +191,8 @@ Table,Create Table idx_order2_$,CREATE TABLE `idx_order2_$` ( `order_id` varchar(20) DEFAULT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_index_replaced.result b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_index_replaced.result index 40a256d00..03533ea2e 100644 --- a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_index_replaced.result +++ b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_index_replaced.result @@ -52,8 +52,8 @@ bmsql_oorder_idx1_$,CREATE TABLE `bmsql_oorder_idx1_$` ( `o_d_id` int(11) NOT NULL, `o_id` int(11) NOT NULL, `o_carrier_id` int(11) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_o_w_id_o_d_id_o_carrier_id_o_id` USING BTREE (`o_w_id`, `o_d_id`, `o_carrier_id`, `o_id`), - KEY `_gsi_pk_idx_` USING BTREE (`o_w_id`, `o_d_id`, `o_id`) + PRIMARY KEY (`o_w_id`, `o_d_id`, `o_id`), + UNIQUE KEY `auto_shard_key_o_w_id_o_d_id_o_carrier_id_o_id` USING BTREE (`o_w_id`, `o_d_id`, `o_carrier_id`, `o_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`o_w_id`,`o_d_id`,`o_carrier_id`,`o_id`) PARTITIONS #@# @@ -64,8 +64,8 @@ bmsql_oorder_idx1_$,CREATE TABLE `bmsql_oorder_idx1_$` ( `o_d_id` int(11) NOT NULL, `o_id` int(11) NOT NULL, `o_carrier_id` int(11) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_o_w_id_o_d_id_o_carrier_id_o_id` USING BTREE (`o_w_id`, `o_d_id`, `o_carrier_id`, `o_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`o_w_id`, `o_d_id`, `o_id`) + PRIMARY KEY (`o_w_id`, `o_d_id`, `o_id`), + UNIQUE LOCAL KEY `auto_shard_key_o_w_id_o_d_id_o_carrier_id_o_id` USING BTREE (`o_w_id`, `o_d_id`, `o_carrier_id`, `o_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`o_w_id`,`o_d_id`,`o_carrier_id`,`o_id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_missing_implicit_pk_bug.result b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_missing_implicit_pk_bug.result index 3025f3b31..2953b044f 100644 --- a/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_missing_implicit_pk_bug.result +++ b/polardbx-test/src/test/resources/partition/env80/AutoPartitionTest/test_missing_implicit_pk_bug.result @@ -29,18 +29,18 @@ PARTITIONS #@# SHOW CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_id` USING BTREE (`id`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + `id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_id` USING BTREE (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS #@# SHOW FULL CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_id` USING BTREE (`id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`id`) + `id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE LOCAL KEY `auto_shard_key_id` USING BTREE (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS #@# @@ -79,20 +79,20 @@ PARTITIONS #@# SHOW CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, + `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_a` USING BTREE (`a`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_a` USING BTREE (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`a`) PARTITIONS #@# SHOW FULL CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, + `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_a` USING BTREE (`a`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`a`) PARTITIONS #@# @@ -131,20 +131,20 @@ PARTITIONS #@# SHOW CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, + `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_a` USING BTREE (`a`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_a` USING BTREE (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`a`) PARTITIONS #@# SHOW FULL CREATE TABLE `id_index`; Table,Create Table id_index_$,CREATE TABLE `id_index_$` ( - `id` int(11) DEFAULT NULL, + `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, - UNIQUE LOCAL KEY `auto_shard_key_a` USING BTREE (`a`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE LOCAL KEY `auto_shard_key_a` USING BTREE (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`a`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env80/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_mm.result b/polardbx-test/src/test/resources/partition/env80/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_mm.result index 257b6ffe9..ff69d1508 100644 --- a/polardbx-test/src/test/resources/partition/env80/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_mm.result +++ b/polardbx-test/src/test/resources/partition/env80/ConvertDrdsCreateTableSqlToAutoTest/test_convert_drds_mm.result @@ -130,6 +130,7 @@ SUBPARTITION BY RANGE (MONTH(`col11`)) ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ) tb2,CREATE TABLE `tb2` ( @@ -157,6 +158,7 @@ SUBPARTITION BY RANGE (MONTH(`col3`)) ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ) tb4,CREATE TABLE `tb4` ( @@ -235,6 +237,7 @@ tb6,CREATE TABLE `tb6` ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ), CLUSTERED INDEX `tb6_k3`(`col4`) PARTITION BY HASH (TO_DAYS(`col4`)) PARTITIONS 16, @@ -251,6 +254,7 @@ tb6,CREATE TABLE `tb6` ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ), GLOBAL INDEX `tb6_k6`(`col8`) COVERING (`col0`, `col1`, `col2`, `col9`) PARTITION BY HASH (TO_DAYS(`col8`)) PARTITIONS 16 @@ -267,6 +271,7 @@ SUBPARTITION BY RANGE (MONTH(`col2`)) ( SUBPARTITION sp9 VALUES LESS THAN (9), SUBPARTITION sp10 VALUES LESS THAN (10), SUBPARTITION sp11 VALUES LESS THAN (11), + SUBPARTITION sp12 VALUES LESS THAN (12), SUBPARTITION spd VALUES LESS THAN MAXVALUE ) use polardbx; diff --git a/polardbx-test/src/test/resources/partition/env80/InvisibleGsiDdlTest/test_ddl_in_auto.result b/polardbx-test/src/test/resources/partition/env80/InvisibleGsiDdlTest/test_ddl_in_auto.result index 6bd4abd40..9863a236f 100644 --- a/polardbx-test/src/test/resources/partition/env80/InvisibleGsiDdlTest/test_ddl_in_auto.result +++ b/polardbx-test/src/test/resources/partition/env80/InvisibleGsiDdlTest/test_ddl_in_auto.result @@ -51,8 +51,8 @@ Table,Create Table g2_$,CREATE TABLE `g2_$` ( `id` int(11) NOT NULL, `name` varchar(20) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`name`) PARTITIONS 3 @@ -306,8 +306,8 @@ Table,Create Table g2_$,CREATE TABLE `g2_$` ( `id` int(11) NOT NULL, `name` varchar(20) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`name`) PARTITIONS 3 @@ -579,8 +579,8 @@ g2_$,CREATE TABLE `g2_$` ( `id` int(11) NOT NULL, `name` varchar(20) DEFAULT NULL, `addr3` varchar(10) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `auto_shard_key_name` USING BTREE (`name`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`name`) PARTITIONS 3 diff --git a/polardbx-test/src/test/resources/partition/env80/ListDefaultAdditionalTest/test_extract_subpartition_tb.result b/polardbx-test/src/test/resources/partition/env80/ListDefaultAdditionalTest/test_extract_subpartition_tb.result index 7f4f87235..f9bf9c76d 100644 --- a/polardbx-test/src/test/resources/partition/env80/ListDefaultAdditionalTest/test_extract_subpartition_tb.result +++ b/polardbx-test/src/test/resources/partition/env80/ListDefaultAdditionalTest/test_extract_subpartition_tb.result @@ -68,7 +68,7 @@ b show create table tb1; Table,Create Table tb1,CREATE TABLE `tb1` ( - `a` int(11) DEFAULT NULL, + `a` int DEFAULT NULL, `b` varchar(20) DEFAULT NULL, KEY `auto_shard_key_a` USING BTREE (`a`), KEY `auto_shard_key_b` USING BTREE (`b`) @@ -141,9 +141,9 @@ b show create table tb2; Table,Create Table tb2,CREATE TABLE `tb2` ( - `a` int(11) DEFAULT NULL, + `a` int DEFAULT NULL, `b` varchar(20) DEFAULT NULL, - `c` int(11) DEFAULT NULL, + `c` int DEFAULT NULL, KEY `auto_shard_key_c` USING BTREE (`c`), KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 @@ -225,7 +225,7 @@ b show create table tb3; Table,Create Table tb3,CREATE TABLE `tb3` ( - `a` int(11) DEFAULT NULL, + `a` int DEFAULT NULL, `b` varchar(20) DEFAULT NULL, KEY `auto_shard_key_a` USING BTREE (`a`), KEY `auto_shard_key_b` USING BTREE (`b`) @@ -292,7 +292,7 @@ b show create table tb4; Table,Create Table tb4,CREATE TABLE `tb4` ( - `a` int(11) DEFAULT NULL, + `a` int DEFAULT NULL, `b` varchar(20) DEFAULT NULL, KEY `auto_shard_key_a` USING BTREE (`a`), KEY `auto_shard_key_b` USING BTREE (`b`) @@ -361,9 +361,9 @@ b show create table tb5; Table,Create Table tb5,CREATE TABLE `tb5` ( - `a` int(11) DEFAULT NULL, + `a` int DEFAULT NULL, `b` varchar(20) DEFAULT NULL, - `c` int(11) DEFAULT NULL, + `c` int DEFAULT NULL, KEY `auto_shard_key_c` USING BTREE (`c`), KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 @@ -431,7 +431,7 @@ b show create table tb6; Table,Create Table tb6,CREATE TABLE `tb6` ( - `a` int(11) DEFAULT NULL, + `a` int DEFAULT NULL, `b` varchar(20) DEFAULT NULL, KEY `auto_shard_key_a` USING BTREE (`a`), KEY `auto_shard_key_b` USING BTREE (`b`) @@ -532,7 +532,7 @@ b show create table tb7; Table,Create Table tb7,CREATE TABLE `tb7` ( - `a` int(11) DEFAULT NULL, + `a` int DEFAULT NULL, `b` varchar(20) DEFAULT NULL, KEY `auto_shard_key_a` USING BTREE (`a`), KEY `auto_shard_key_b` USING BTREE (`b`) @@ -587,9 +587,9 @@ b show create table tb8; Table,Create Table tb8,CREATE TABLE `tb8` ( - `a` int(11) DEFAULT NULL, + `a` int DEFAULT NULL, `b` varchar(20) DEFAULT NULL, - `c` int(11) DEFAULT NULL, + `c` int DEFAULT NULL, KEY `auto_shard_key_c` USING BTREE (`c`), KEY `auto_shard_key_a_b` USING BTREE (`a`, `b`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 @@ -604,13 +604,13 @@ SUBPARTITION BY LIST COLUMNS(`a`,`b`) SUBPARTITION p2sp2 VALUES IN ((3,'3'),(4,'4')) ENGINE = InnoDB, SUBPARTITION p2spd VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p3 VALUES IN (3) - (SUBPARTITION sp3 VALUES IN ((1,'1'),(2,'2')) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES IN ((3,'3'),(4,'4')) ENGINE = InnoDB, - SUBPARTITION sp5 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p3sp3 VALUES IN ((1,'1'),(2,'2')) ENGINE = InnoDB, + SUBPARTITION p3sp4 VALUES IN ((3,'3'),(4,'4')) ENGINE = InnoDB, + SUBPARTITION p3sp5 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION pd VALUES IN (DEFAULT) - (SUBPARTITION sp6 VALUES IN ((1,'1'),(2,'2')) ENGINE = InnoDB, - SUBPARTITION sp7 VALUES IN ((3,'3'),(4,'4')) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES IN (DEFAULT) ENGINE = InnoDB)) + (SUBPARTITION pdsp6 VALUES IN ((1,'1'),(2,'2')) ENGINE = InnoDB, + SUBPARTITION pdsp7 VALUES IN ((3,'3'),(4,'4')) ENGINE = InnoDB, + SUBPARTITION pdsp8 VALUES IN (DEFAULT) ENGINE = InnoDB)) # test hash partition # template create table tb9( @@ -635,9 +635,9 @@ a /*+TDDL:CMD_EXTRA(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show create table tb9; Table,Create Table tb9,CREATE TABLE `tb9` ( - `a` int(11) DEFAULT NULL, - `b` int(11) DEFAULT NULL, - `c` int(11) DEFAULT NULL, + `a` int DEFAULT NULL, + `b` int DEFAULT NULL, + `c` int DEFAULT NULL, KEY `auto_shard_key_a` USING BTREE (`a`), KEY `auto_shard_key_b_c` USING BTREE (`b`, `c`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 @@ -682,9 +682,9 @@ a /*+TDDL:CMD_EXTRA(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show create table tb10; Table,Create Table tb10,CREATE TABLE `tb10` ( - `a` int(11) DEFAULT NULL, - `b` int(11) DEFAULT NULL, - `c` int(11) DEFAULT NULL, + `a` int DEFAULT NULL, + `b` int DEFAULT NULL, + `c` int DEFAULT NULL, KEY `auto_shard_key_a` USING BTREE (`a`), KEY `auto_shard_key_b_c` USING BTREE (`b`, `c`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 @@ -726,9 +726,9 @@ a /*+TDDL:CMD_EXTRA(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show create table tb11; Table,Create Table tb11,CREATE TABLE `tb11` ( - `a` int(11) DEFAULT NULL, - `b` int(11) DEFAULT NULL, - `c` int(11) DEFAULT NULL, + `a` int DEFAULT NULL, + `b` int DEFAULT NULL, + `c` int DEFAULT NULL, KEY `auto_shard_key_a` USING BTREE (`a`), KEY `auto_shard_key_b_c` USING BTREE (`b`, `c`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 diff --git a/polardbx-test/src/test/resources/partition/env80/MultiDBSingleTableTest/test_multi_db_single_table.result b/polardbx-test/src/test/resources/partition/env80/MultiDBSingleTableTest/test_multi_db_single_table.result index 09feab14f..b46a271bc 100644 --- a/polardbx-test/src/test/resources/partition/env80/MultiDBSingleTableTest/test_multi_db_single_table.result +++ b/polardbx-test/src/test/resources/partition/env80/MultiDBSingleTableTest/test_multi_db_single_table.result @@ -96,13 +96,22 @@ Logical ExecutionPlan LogicalView(tables=[single_t1.single_t1_s1, single_t2.single_t2_s1], sql="") explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert single_t3.single_t3_s1(a3, b3) select * from single_t1.single_t1_s1; Logical ExecutionPlan -LogicalView(tables=[single_t3.single_t3_s1, single_t1.single_t1_s1], sql="") +LogicalInsert(table="single_t3_s1", columns=RecordType(BIGINT_UNSIGNED a3, BIGINT_UNSIGNED b3, BIGINT _drds_implicit_id_), mode=MULTI) + LogicalView(tables="single_t1_s1[p1]", sql="SELECT `a1` AS `a3`, `b1` AS `b3`, NULL AS `_drds_implicit_id_` FROM `single_t1_s1` AS `single_t1_s1`") begin; explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert single_t3.single_t3_s1(a3, b3) select * from single_t1.single_t1_s1; Logical ExecutionPlan LogicalInsert(table="single_t3_s1", columns=RecordType(BIGINT_UNSIGNED a3, BIGINT_UNSIGNED b3, BIGINT _drds_implicit_id_), mode=MULTI) LogicalView(tables="single_t1_s1[p1]", sql="SELECT `a1` AS `a3`, `b1` AS `b3`, NULL AS `_drds_implicit_id_` FROM `single_t1_s1` AS `single_t1_s1`") commit; +explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert drds_single_t4.single_t4_s1(a3, b3) select * from single_t1.single_t1_s1; +Logical ExecutionPlan +LogicalInsert(table="single_t4_s1", columns=RecordType(BIGINT_UNSIGNED a3, BIGINT_UNSIGNED b3, BIGINT _drds_implicit_id_), mode=MULTI) + LogicalView(tables="single_t1_s1[p1]", sql="SELECT `a1` AS `a3`, `b1` AS `b3`, NULL AS `_drds_implicit_id_` FROM `single_t1_s1` AS `single_t1_s1`") +explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert single_t1.single_t1_s1(a1, b1) select * from drds_single_t4.single_t4_s1; +Logical ExecutionPlan +LogicalInsert(table="single_t1_s1", columns=RecordType(BIGINT_UNSIGNED a1, BIGINT_UNSIGNED b1, BIGINT _drds_implicit_id_), mode=MULTI) + LogicalView(tables="DRDS_SINGLE_T4_000000_GROUP.single_t4_s1", sql="SELECT `a3` AS `a1`, `b3` AS `b1`, NULL AS `_drds_implicit_id_` FROM `single_t4_s1` AS `single_t4_s1`") insert single_t3.single_t3_s1(a3, b3) select * from single_t1.single_t1_s1; select * from single_t3.single_t3_s1; a3,b3 @@ -127,5 +136,4 @@ explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/select * from single_t2.s Logical ExecutionPlan HashJoin(condition="a2 = a3", type="inner") LogicalView(tables="single_t2_s1[p1]", sql="SELECT `a2`, `b2` FROM `single_t2_s1` AS `single_t2_s1`") - Gather(concurrent=true) - LogicalView(tables="single_t3_s2", shardCount=0, sql="SELECT `a3`, `b3` FROM `single_t3_s2` AS `single_t3_s2`") \ No newline at end of file + LogicalView(tables="single_t3_s2", shardCount=0, sql="SELECT `a3`, `b3` FROM `single_t3_s2` AS `single_t3_s2`") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/MultiDBSingleTableTest/test_multi_db_single_table.test.yml b/polardbx-test/src/test/resources/partition/env80/MultiDBSingleTableTest/test_multi_db_single_table.test.yml index 59f4bc716..9ec051974 100644 --- a/polardbx-test/src/test/resources/partition/env80/MultiDBSingleTableTest/test_multi_db_single_table.test.yml +++ b/polardbx-test/src/test/resources/partition/env80/MultiDBSingleTableTest/test_multi_db_single_table.test.yml @@ -95,7 +95,6 @@ commit; explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/select * from single_t1.single_t1_s1 as t1 inner join single_t2.single_t2_s1 t2 on t1.a1=t2.a2; - explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert single_t3.single_t3_s1(a3, b3) select * from single_t1.single_t1_s1; begin; @@ -104,6 +103,10 @@ explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert single_t3.single_t commit; +explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert drds_single_t4.single_t4_s1(a3, b3) select * from single_t1.single_t1_s1; + +explain /*+TDDL:SIMPLIFY_MULTI_DB_SINGLE_TB_PLAN=true*/insert single_t1.single_t1_s1(a1, b1) select * from drds_single_t4.single_t4_s1; + insert single_t3.single_t3_s1(a3, b3) select * from single_t1.single_t1_s1; select * from single_t3.single_t3_s1; diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.result b/polardbx-test/src/test/resources/partition/env80/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.result new file mode 100644 index 000000000..3c733d9b8 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.result @@ -0,0 +1,51 @@ +## DISABLE_FAST_SQL_PARSER +CREATE TABLE `my_bro_t1` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB AUTO_INCREMENT = 400021 DEFAULT CHARSET = utf8mb4 +BROADCAST; +CREATE TABLE `my_hash_t1` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 8; +CREATE TABLE `my_hash_t2` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 8; +explain insert into my_hash_t2 select t1.a, t1.b from my_hash_t1 t1 join my_bro_t1 t2 on t1.b=t2.b; +Logical ExecutionPlan +LogicalInsert(table="my_hash_t2", columns=RecordType(BIGINT_UNSIGNED a, BIGINT_UNSIGNED b), mode=MULTI) + Gather(concurrent=true) + LogicalView(tables="my_hash_t1[p1,p2,p3,p4,p5,p6,p7,p8],my_bro_t1", shardCount=8, sql="SELECT `my_hash_t1`.`a`, `my_hash_t1`.`b` FROM `my_hash_t1` AS `my_hash_t1` INNER JOIN `my_bro_t1` AS `my_bro_t1` ON (`my_hash_t1`.`b` = `my_bro_t1`.`b`)") +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b; +Logical ExecutionPlan +Gather(concurrent=true) + LogicalView(tables="my_hash_t1[p1,p2,p3,p4,p5,p6,p7,p8],my_bro_t1", shardCount=8, sql="SELECT `my_bro_t1`.`a` AS `a0`, `my_bro_t1`.`b` AS `b0`, `my_hash_t1`.`a`, `my_hash_t1`.`b` FROM `my_hash_t1` AS `my_hash_t1` INNER JOIN `my_bro_t1` AS `my_bro_t1` ON (`my_hash_t1`.`b` = `my_bro_t1`.`b`)") +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; +Logical ExecutionPlan +BKAJoin(condition="b = b", type="inner") + LogicalView(tables="my_bro_t1", shardCount=0, sql="SELECT `a`, `b` FROM `my_bro_t1` AS `my_bro_t1` FOR UPDATE") + Gather(concurrent=true) + LogicalView(tables="my_hash_t1[p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=8, sql="SELECT `a`, `b` FROM `my_hash_t1` AS `my_hash_t1` WHERE (`b` IN (...)) FOR UPDATE") +set autocommit=false; +select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; +a,b,a,b +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; +Logical ExecutionPlan +BKAJoin(condition="b = b", type="inner") + LogicalView(tables="my_bro_t1", shardCount=0, sql="SELECT `a`, `b` FROM `my_bro_t1` AS `my_bro_t1` FOR UPDATE") + Gather(concurrent=true) + LogicalView(tables="my_hash_t1[p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=8, sql="SELECT `a`, `b` FROM `my_hash_t1` AS `my_hash_t1` WHERE (`b` IN (...)) FOR UPDATE") +explain insert into my_hash_t2 select t1.a, t1.b from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b; +Logical ExecutionPlan +LogicalInsert(table="my_hash_t2", columns=RecordType(BIGINT_UNSIGNED a, BIGINT_UNSIGNED b), mode=MULTI) + Project(a="a", b="b") + BKAJoin(condition="b = b", type="inner") + LogicalView(tables="my_bro_t1", shardCount=0, sql="SELECT `a`, `b` FROM `my_bro_t1` AS `my_bro_t1`") + Gather(concurrent=true) + LogicalView(tables="my_hash_t1[p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=8, sql="SELECT `b` FROM `my_hash_t1` AS `my_hash_t1` WHERE (`b` IN (...))") +rollback; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.test.yml b/polardbx-test/src/test/resources/partition/env80/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.test.yml new file mode 100644 index 000000000..5bdd908ee --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/PartitionIntraGroupParallel2Test/test_dml_bro_join_pushdown.test.yml @@ -0,0 +1,32 @@ +## DISABLE_FAST_SQL_PARSER + +CREATE TABLE `my_bro_t1` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB AUTO_INCREMENT = 400021 DEFAULT CHARSET = utf8mb4 +BROADCAST; + +CREATE TABLE `my_hash_t1` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 8; + +CREATE TABLE `my_hash_t2` ( +`a` bigint(20) UNSIGNED NOT NULL PRIMARY KEY, +`b` bigint(20) UNSIGNED NOT NULL +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 8; + +explain insert into my_hash_t2 select t1.a, t1.b from my_hash_t1 t1 join my_bro_t1 t2 on t1.b=t2.b; +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b; +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; + +set autocommit=false; +select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; +explain select * from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b for update; +explain insert into my_hash_t2 select t1.a, t1.b from my_bro_t1 t1 join my_hash_t1 t2 on t1.b=t2.b; +rollback; + diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionIntraGroupParallel2Test/testcase.config.yml b/polardbx-test/src/test/resources/partition/env80/PartitionIntraGroupParallel2Test/testcase.config.yml new file mode 100644 index 000000000..347026527 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/PartitionIntraGroupParallel2Test/testcase.config.yml @@ -0,0 +1 @@ +#test_dml_bro_join_pushdown \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableDdlTest/test_alter_repartition_with_ugsi.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableDdlTest/test_alter_repartition_with_ugsi.result index 57e909aa5..9c44e5de4 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableDdlTest/test_alter_repartition_with_ugsi.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableDdlTest/test_alter_repartition_with_ugsi.result @@ -27,10 +27,9 @@ PARTITIONS 3 SHOW CREATE TABLE g1; Table,Create Table g1_$,CREATE TABLE `g1_$` ( - `id` varchar(20) DEFAULT NULL, + `id` varchar(20) NOT NULL, `name` varchar(20) DEFAULT NULL, - UNIQUE KEY `auto_shard_key_id` USING BTREE (`id`), - KEY `_gsi_pk_idx_` USING BTREE (`id`) + PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`id`) PARTITIONS 3 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableDdlTest/test_drop_add_primary_key.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableDdlTest/test_drop_add_primary_key.result index 3afb2280e..4720dec88 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableDdlTest/test_drop_add_primary_key.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableDdlTest/test_drop_add_primary_key.result @@ -106,8 +106,8 @@ idx_order_$,CREATE TABLE `idx_order_$` ( `x` int(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, `gmt_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`x`, `gmt_modified`) + PRIMARY KEY (`x`, `gmt_modified`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# @@ -153,8 +153,8 @@ Table,Create Table idx_order2_$,CREATE TABLE `idx_order2_$` ( `order_id` varchar(20) DEFAULT NULL, `_drds_implicit_id_` bigint(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`_drds_implicit_id_`) + PRIMARY KEY (`_drds_implicit_id_`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# @@ -194,8 +194,8 @@ Table,Create Table idx_order2_$,CREATE TABLE `idx_order2_$` ( `order_id` varchar(20) NOT NULL, `seller_id` varchar(20) NOT NULL, - UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`), - LOCAL KEY `_gsi_pk_idx_` USING BTREE (`order_id`, `seller_id`) + PRIMARY KEY (`order_id`, `seller_id`), + UNIQUE LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY(`order_id`) PARTITIONS #@# diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal.result b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal.result index 00861a85f..75357b72d 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal.result @@ -185,24 +185,16 @@ explain select * from rng_decimal_2400 where c1 between '16777215' and '42949672 Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rng_decimal_2400[p7,p8,p9]", shardCount=3, sql="SELECT `c1` FROM `rng_decimal_2400` AS `rng_decimal_2400` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: cdf3b018 ## p10,pm explain select * from rng_decimal_2400 where c1 between '123456789012345678809999' and '123456789012345679909999'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rng_decimal_2400[p10,pm]", shardCount=2, sql="SELECT `c1` FROM `rng_decimal_2400` AS `rng_decimal_2400` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: cdf3b018 ## pm explain select * from rng_decimal_2400 where c1 between '123456789012345678909999' and '123456789012345678919999'; Logical ExecutionPlan -PhyTableOperation(tables="rng_decimal_2400[pm]", sql="SELECT `rng_decimal_2400`.`c1` FROM ? AS `rng_decimal_2400` WHERE (`rng_decimal_2400`.`c1` BETWEEN ? AND ?)", params="123456789012345678919999,123456789012345678909999") -HitCache:true -Source:PLAN_CACHE -TemplateId: cdf3b018 +Gather(concurrent=true) + LogicalView(tables="rng_decimal_2400[pm]", sql="SELECT `c1` FROM `rng_decimal_2400` AS `rng_decimal_2400` WHERE (`c1` BETWEEN ? AND ?)") ####------- case 7 test rng route with biggest int------ drop table if exists rng_decimal_6500; set sql_mode=''; @@ -231,7 +223,8 @@ Logical ExecutionPlan PhyTableOperation(tables="rng_decimal_6500[pmax]", sql="SELECT `rng_decimal_6500`.`c1` FROM ? AS `rng_decimal_6500` WHERE (`rng_decimal_6500`.`c1` = ?)", params="99999999999999999999999999999999999999999999999999999999999999999") explain select * from rng_decimal_6500 where c1>'99999999999999999999999999999999999999999999999999999999999999999'; Logical ExecutionPlan -PhyTableOperation(tables="rng_decimal_6500[pmax]", sql="SELECT `rng_decimal_6500`.`c1` FROM ? AS `rng_decimal_6500` WHERE (`rng_decimal_6500`.`c1` > ?)", params="99999999999999999999999999999999999999999999999999999999999999999") +Gather(concurrent=true) + LogicalView(tables="rng_decimal_6500[pmax]", sql="SELECT `c1` FROM `rng_decimal_6500` AS `rng_decimal_6500` WHERE (`c1` > ?)") select part_route('','key_decimal_6500',-1234567890123456789012340); part_route('', 'key_decimal_6500', -1234567890123456789012340) p1 @@ -258,29 +251,18 @@ explain select * from list_decimal_2400 where c1 between '16777215' and '4294967 Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="list_decimal_2400[p2,p3,pm]", shardCount=3, sql="SELECT `c1` FROM `list_decimal_2400` AS `list_decimal_2400` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 5747dcef ## p10,pm explain select * from list_decimal_2400 where c1 between '123456789012345678809999' and '123456789012345679909999'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="list_decimal_2400[p5,pm]", shardCount=2, sql="SELECT `c1` FROM `list_decimal_2400` AS `list_decimal_2400` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 5747dcef ## zero explain select * from list_decimal_2400 where c1 >= '123456789012345688909999' and c1 <= '123456789012345678919999'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="list_decimal_2400[]", shardCount=0, sql="SELECT `c1` FROM `list_decimal_2400` AS `list_decimal_2400` WHERE ((`c1` >= ?) AND (`c1` <= ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: 3070605e ## pm explain select * from list_decimal_2400 where c1 <= '123456789012345688909999' and c1 >= '123456789012345678919999'; Logical ExecutionPlan -PhyTableOperation(tables="list_decimal_2400[pm]", sql="SELECT `list_decimal_2400`.`c1` FROM ? AS `list_decimal_2400` WHERE ((`list_decimal_2400`.`c1` <= ?) AND (`list_decimal_2400`.`c1` >= ?))", params="123456789012345678919999,123456789012345688909999") -HitCache:false -Source:PLAN_CACHE -TemplateId: 8f1d8d1a \ No newline at end of file +Gather(concurrent=true) + LogicalView(tables="list_decimal_2400[pm]", sql="SELECT `c1` FROM `list_decimal_2400` AS `list_decimal_2400` WHERE ((`c1` <= ?) AND (`c1` >= ?))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal2.result b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal2.result index af5c241e8..99db9c3c7 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal2.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal2.result @@ -97,16 +97,10 @@ explain select * from tb_decimal_6530 Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_6530[p1,p2,p3,...p16]", shardCount=16, sql="SELECT `id` FROM `tb_decimal_6530` AS `tb_decimal_6530` WHERE ((`id` >= ?) AND (`id` <= ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: cc7827b4 ## should scan no partitions explain select * from tb_decimal_6530 where id <= '12345678901234567890123456789012345.123456789012345678900123456789' and id >= '12345678901234567890123456789012345.123456789012345678900123456795'; Logical ExecutionPlan Gather(concurrent=true) - LogicalView(tables="tb_decimal_6530[]", shardCount=0, sql="SELECT `id` FROM `tb_decimal_6530` AS `tb_decimal_6530` WHERE ((`id` <= ?) AND (`id` >= ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: 2b255470 \ No newline at end of file + LogicalView(tables="tb_decimal_6530[]", shardCount=0, sql="SELECT `id` FROM `tb_decimal_6530` AS `tb_decimal_6530` WHERE ((`id` <= ?) AND (`id` >= ?))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal_endpoints.result b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal_endpoints.result index 657c5f7d1..e09ddc8b1 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal_endpoints.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal_endpoints.result @@ -19,9 +19,6 @@ explain select * from rc4_decimal_2400 where c1 > '123456789012345678901236.2'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p7,p8,pm]", shardCount=3, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` > ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: e14ba130 explain select * from rc4_decimal_2400 where '123456789012345678901236.2' < c1; Logical ExecutionPlan Gather(concurrent=true) @@ -31,9 +28,6 @@ explain select * from rc4_decimal_2400 where c1 > '123456789012345678901236.8'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p8,pm]", shardCount=2, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` > ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: e14ba130 explain select * from rc4_decimal_2400 where '123456789012345678901236.8' < c1; Logical ExecutionPlan Gather(concurrent=true) @@ -43,9 +37,6 @@ explain select * from rc4_decimal_2400 where c1 >= '123456789012345678901236.2'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p7,p8,pm]", shardCount=3, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` >= ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 4828ee2b explain select * from rc4_decimal_2400 where '123456789012345678901236.2' <= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -55,9 +46,6 @@ explain select * from rc4_decimal_2400 where c1 >= '123456789012345678901236.8'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p8,pm]", shardCount=2, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` >= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 4828ee2b explain select * from rc4_decimal_2400 where '123456789012345678901236.8' <= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -67,9 +55,6 @@ explain select * from rc4_decimal_2400 where c1 < '123456789012345678901236.2'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3,p4,p5,p6,p7]", shardCount=8, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` < ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: e14b99ae explain select * from rc4_decimal_2400 where '123456789012345678901236.2' > c1; Logical ExecutionPlan Gather(concurrent=true) @@ -79,9 +64,6 @@ explain select * from rc4_decimal_2400 where c1 < '123456789012345678901236.8'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=9, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` < ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: e14b99ae explain select * from rc4_decimal_2400 where '123456789012345678901236.8' > c1; Logical ExecutionPlan Gather(concurrent=true) @@ -91,9 +73,6 @@ explain select * from rc4_decimal_2400 where c1 <= '123456789012345678901236.2'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3,p4,p5,p6,p7]", shardCount=8, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` <= ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 4828056d explain select * from rc4_decimal_2400 where '123456789012345678901236.2' >= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -103,9 +82,6 @@ explain select * from rc4_decimal_2400 where c1 <= '123456789012345678901236.8'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=9, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` <= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 4828056d explain select * from rc4_decimal_2400 where '123456789012345678901236.8' >= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -116,9 +92,6 @@ explain select * from rc4_decimal_2400 where c1 < '-123456789012345678901232.2'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3]", shardCount=4, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` < ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: e14b99ae explain select * from rc4_decimal_2400 where '-123456789012345678901232.2' > c1; Logical ExecutionPlan Gather(concurrent=true) @@ -128,9 +101,6 @@ explain select * from rc4_decimal_2400 where c1 > '-123456789012345678901232.8'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=8, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` > ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: e14ba130 explain select * from rc4_decimal_2400 where '-123456789012345678901232.8' < c1; Logical ExecutionPlan Gather(concurrent=true) @@ -140,9 +110,6 @@ explain select * from rc4_decimal_2400 where c1 <= '-123456789012345678901232.2' Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p0,p1,p2,p3]", shardCount=4, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` <= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 4828056d explain select * from rc4_decimal_2400 where '-123456789012345678901232.2' >= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -152,9 +119,6 @@ explain select * from rc4_decimal_2400 where c1 >= '-123456789012345678901232.8' Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc4_decimal_2400[p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=8, sql="SELECT `c1` FROM `rc4_decimal_2400` AS `rc4_decimal_2400` WHERE (`c1` >= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 4828ee2b explain select * from rc4_decimal_2400 where '-123456789012345678901232.8' <= c1; Logical ExecutionPlan Gather(concurrent=true) @@ -178,128 +142,82 @@ explain select * from rc5_bigint where c1 > 9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p8,pm]", shardCount=2, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` > ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 0c573392 ## c1 > 9999.1 ==> c1 >= 9999: p8,pm explain select * from rc5_bigint where c1 >= 9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p8,pm]", shardCount=2, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` >= ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 7e8fa809 ## c1 > 9999.8 ==> c1 >= 10000: pm explain select * from rc5_bigint where c1 > 9999.8; Logical ExecutionPlan -PhyTableOperation(tables="rc5_bigint[pm]", sql="SELECT `rc5_bigint`.`c1` FROM ? AS `rc5_bigint` WHERE (`rc5_bigint`.`c1` > ?)", params="9999.8") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c573392 +Gather(concurrent=true) + LogicalView(tables="rc5_bigint[pm]", sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` > ?)") ## c1 > 9999.8 ==> c1 >= 10000: pm explain select * from rc5_bigint where c1 >= 9999.8; Logical ExecutionPlan -PhyTableOperation(tables="rc5_bigint[pm]", sql="SELECT `rc5_bigint`.`c1` FROM ? AS `rc5_bigint` WHERE (`rc5_bigint`.`c1` >= ?)", params="9999.8") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8fa809 +Gather(concurrent=true) + LogicalView(tables="rc5_bigint[pm]", sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` >= ?)") ## c1 < 9999.1 ==> c1 <= 9999: p0~p8 explain select * from rc5_bigint where c1 < 9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=9, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` < ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 0c572c10 ## c1 <= 9999.1 ==> c1 <= 9999: p0~p8 explain select * from rc5_bigint where c1 <= 9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3,p4,p5,p6,p7,p8]", shardCount=9, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` <= ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 7e8ebf4b ## c1 < 9999.8 ==> c1 <= 10000: p0~0m explain select * from rc5_bigint where c1 < 9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=10, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` < ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c572c10 ## c1 < 9999.8 ==> c1 <= 10000: p0~0m explain select * from rc5_bigint where c1 <= 9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=10, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` <= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8ebf4b ##---- negative ---- ## c1 > -9999.1 ==> c1 >= -9999: p3~pm explain select * from rc5_bigint where c1 > -9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p3,p4,p5,p6,p7,p8,pm]", shardCount=7, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` > ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c573392 ## c1 > -9999.1 ==> c1 >= 9999: p3~pm explain select * from rc5_bigint where c1 >= -9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p3,p4,p5,p6,p7,p8,pm]", shardCount=7, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` >= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8fa809 ## c1 > -9999.8 ==> c1 >= -10000: p2~pm explain select * from rc5_bigint where c1 > -9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=8, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` > ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c573392 ## c1 > -9999.8 ==> c1 >= -10000: p2~pm explain select * from rc5_bigint where c1 >= -9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p2,p3,p4,p5,p6,p7,p8,pm]", shardCount=8, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` >= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8fa809 ## c1 < -9999.1 ==> c1 <= -9999: p0,p1,p2,p3 explain select * from rc5_bigint where c1 < -9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3]", shardCount=4, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` < ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c572c10 ## c1 <= 9999.1 ==> c1 <= 9999: p0,p1,p2,p3 explain select * from rc5_bigint where c1 <= -9999.1; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2,p3]", shardCount=4, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` <= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8ebf4b ## c1 < 9999.8 ==> c1 <= 10000: p0,p1,p2 explain select * from rc5_bigint where c1 < -9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2]", shardCount=3, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` < ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 0c572c10 ## c1 < 9999.8 ==> c1 <= 10000: p0,p1,p2 explain select * from rc5_bigint where c1 <= -9999.8; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="rc5_bigint[p0,p1,p2]", shardCount=3, sql="SELECT `c1` FROM `rc5_bigint` AS `rc5_bigint` WHERE (`c1` <= ?)") -HitCache:true -Source:PLAN_CACHE -TemplateId: 7e8ebf4b create table if not exists rc3_decimal_2400 (c1 decimal(24,0) default null ) partition by range columns(c1) ( partition p0 values less than ('-999999999999999999999999'), @@ -340,7 +258,8 @@ c1 123456789012345678901234 explain select * from rc3_decimal_2400 where c1 >= '123456789012345678901233.8' and c1<='123456789012345678901234.5'; Logical ExecutionPlan -PhyTableOperation(tables="rc3_decimal_2400[p26]", sql="SELECT `rc3_decimal_2400`.`c1` FROM ? AS `rc3_decimal_2400` WHERE ((`rc3_decimal_2400`.`c1` >= ?) AND (`rc3_decimal_2400`.`c1` <= ?))", params="123456789012345678901234.5,123456789012345678901233.8") +Gather(concurrent=true) + LogicalView(tables="rc3_decimal_2400[p26]", sql="SELECT `c1` FROM `rc3_decimal_2400` AS `rc3_decimal_2400` WHERE ((`c1` >= ?) AND (`c1` <= ?))") explain select * from rc3_decimal_2400 where c1 <= '123456789012345678901233.8' and c1>='123456789012345678901234.5'; Logical ExecutionPlan Gather(concurrent=true) diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal_sp.result b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal_sp.result index 79fe516d8..b86fd3a41 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal_sp.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_decimal_sp.result @@ -103,9 +103,6 @@ explain select * from tb_decimal_sp_6530_6500 Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6530_6500[p1sp1,p1sp2,p1sp3,...p4spd]", shardCount=24, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6530_6500` AS `tb_decimal_sp_6530_6500` WHERE ((`id` >= ?) AND (`id` <= ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: ca3d48f0 ## empty explain select * from tb_decimal_sp_6530_6500 where id <= '12345678901234567890123456789012345.123456789012345678900123456789' @@ -113,18 +110,12 @@ and id >= '12345678901234567890123456789012345.123456789012345678900123456795'; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6530_6500[]", shardCount=0, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6530_6500` AS `tb_decimal_sp_6530_6500` WHERE ((`id` <= ?) AND (`id` >= ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: 28ea75ac ## p1~p4 , sp: sp4,spd explain select * from tb_decimal_sp_6530_6500 where c1 between 9223372036854775806 and 9223372036854775808; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6530_6500[p1sp4,p1spd,p2sp4,p2spd,p3sp4,p3spd,p4sp4,p4spd]", shardCount=8, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6530_6500` AS `tb_decimal_sp_6530_6500` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 284b7f21 ## p1~p4, sp: sp4,spd explain select * from tb_decimal_sp_6530_6500 where id >= '12345678901234567890123456789012345.123456789012345678900123456789' @@ -133,9 +124,6 @@ and c1 between 9223372036854775806 and 9223372036854775808; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6530_6500[p1sp4,p1spd,p2sp4,p2spd,p3sp4,p3spd,p4sp4,p4spd]", shardCount=8, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6530_6500` AS `tb_decimal_sp_6530_6500` WHERE ((`id` >= ?) AND (`id` <= ?) AND (`c1` BETWEEN ? AND ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: 491ebac3 CREATE TABLE `tb_decimal_sp_6500_6530` ( `id` decimal(65,30) NOT NULL, `c1` decimal(65,0) NOT NULL @@ -174,9 +162,6 @@ where c1 between 9223372036854775806 and 9223372036854775808; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6500_6530[p4sp1,p4sp2,p4sp3,p4sp4,pdsp1,pdsp2,pdsp3,pdsp4]", shardCount=8, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6500_6530` AS `tb_decimal_sp_6500_6530` WHERE (`c1` BETWEEN ? AND ?)") -HitCache:false -Source:PLAN_CACHE -TemplateId: 3badf1c7 ## p: p4,pd ## sp: sp1~sp4 explain select * from tb_decimal_sp_6500_6530 @@ -186,9 +171,6 @@ and c1 between 9223372036854775806 and 9223372036854775808; Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="tb_decimal_sp_6500_6530[p4sp1,p4sp2,p4sp3,p4sp4,pdsp1,pdsp2,pdsp3,pdsp4]", shardCount=8, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6500_6530` AS `tb_decimal_sp_6500_6530` WHERE ((`id` >= ?) AND (`id` <= ?) AND (`c1` BETWEEN ? AND ?))") -HitCache:false -Source:PLAN_CACHE -TemplateId: 4a0789e9 ## p:p4,pd, ## sp: sp3 explain select * from tb_decimal_sp_6500_6530 @@ -197,7 +179,4 @@ and id <= '12345678901234567890123456789012345.123456789012345678900123456789' and c1 between 9223372036854775806 and 9223372036854775808; Logical ExecutionPlan Gather(concurrent=true) - LogicalView(tables="tb_decimal_sp_6500_6530[p4sp3,pdsp3]", shardCount=2, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6500_6530` AS `tb_decimal_sp_6500_6530` WHERE ((`id` >= ?) AND (`id` <= ?) AND (`c1` BETWEEN ? AND ?))") -HitCache:true -Source:PLAN_CACHE -TemplateId: 4a0789e9 \ No newline at end of file + LogicalView(tables="tb_decimal_sp_6500_6530[p4sp3,pdsp3]", shardCount=2, sql="SELECT `id`, `c1` FROM `tb_decimal_sp_6500_6530` AS `tb_decimal_sp_6500_6530` WHERE ((`id` >= ?) AND (`id` <= ?) AND (`c1` BETWEEN ? AND ?))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_list_part_posi.result b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_list_part_posi.result index a43f9c509..011389fc8 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_list_part_posi.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruning3Test/test_list_part_posi.result @@ -1,7 +1,7 @@ ## DISABLE_FAST_SQL_PARSER CREATE TABLE `list_t1` ( -`a` int(11) NOT NULL primary key, -`b` int(11) DEFAULT NULL +`a` int NOT NULL primary key, +`b` int DEFAULT NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 partition by list(a) ( @@ -15,8 +15,8 @@ partition p7 values in (7,77), partition pd values in (default) ); CREATE TABLE `list_t2` ( -`a` int(11) NOT NULL primary key, -`b` int(11) DEFAULT NULL +`a` int NOT NULL primary key, +`b` int DEFAULT NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 partition by list(a) ( @@ -32,8 +32,8 @@ partition pd values in (default) show create table list_t1; Table,Create Table list_t1,CREATE TABLE `list_t1` ( - `a` int(11) NOT NULL, - `b` int(11) DEFAULT NULL, + `a` int NOT NULL, + `b` int DEFAULT NULL, PRIMARY KEY (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY LIST(`a`) @@ -48,8 +48,8 @@ PARTITION BY LIST(`a`) show create table list_t2; Table,Create Table list_t2,CREATE TABLE `list_t2` ( - `a` int(11) NOT NULL, - `b` int(11) DEFAULT NULL, + `a` int NOT NULL, + `b` int DEFAULT NULL, PRIMARY KEY (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY LIST(`a`) @@ -77,5 +77,6 @@ a,b,a,b 2,2,2,1 explain select * from list_t2 t2 join list_t1 t1 on t2.a=t1.a and t2.a=2 for update; Logical ExecutionPlan -PhyTableOperation(tables="list_t2[p2],list_t1[p2]", sql="SELECT `t2`.`a`, `t2`.`b`, `t1`.`a`, `t1`.`b` FROM ? AS `t2` INNER JOIN ? AS `t1` ON ((`t2`.`a` = `t1`.`a`) AND (`t2`.`a` = ?)) FOR UPDATE", params="2") +Gather(concurrent=true) + LogicalView(tables="list_t2[p2],list_t1[p2]", sql="SELECT `list_t2`.`a`, `list_t2`.`b`, `list_t1`.`a` AS `a0`, `list_t1`.`b` AS `b0` FROM `list_t2` AS `list_t2` INNER JOIN `list_t1` AS `list_t1` ON ((`list_t2`.`a` = ?) AND (`list_t1`.`a` = ?) AND (`list_t2`.`a` = `list_t1`.`a`)) FOR UPDATE") commit; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_hash_enum.result b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_hash_enum.result index d8832b3fb..1bfb0c33c 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_hash_enum.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_hash_enum.result @@ -1,8 +1,8 @@ DROP TABLE IF EXISTS hsh_key; CREATE TABLE `hsh_key` ( - `a` bigint(20) NOT NULL, - `b` bigint(20) NOT NULL, - `c` bigint(20) NOT NULL + `a` bigint NOT NULL, + `b` bigint NOT NULL, + `c` bigint NOT NULL ) ENGINE = InnoDB AUTO_INCREMENT = 400002 DEFAULT CHARSET = utf8mb4 PARTITION BY KEY (a) PARTITIONS 32; EXPLAIN SELECT * @@ -31,7 +31,7 @@ Logical ExecutionPlan Gather(concurrent=true) LogicalView(tables="hsh_key[p2,p11,p14,p28]", shardCount=4, sql="SELECT `a`, `b`, `c` FROM `hsh_key` AS `hsh_key` WHERE (((`a` > ?) AND (`a` < ?)) OR ((`a` >= ?) AND (`a` < ?)))") CREATE TABLE `t_ubigint` ( - `a` bigint(20) UNSIGNED DEFAULT NULL, + `a` bigint UNSIGNED DEFAULT NULL, KEY `auto_shard_key_a` USING BTREE (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY HASH (a) PARTITIONS 8; @@ -39,7 +39,8 @@ EXPLAIN SELECT * FROM t_ubigint WHERE a BETWEEN 9223372036854775809 AND 9223372036854775809; Logical ExecutionPlan -PhyTableOperation(tables="t_ubigint[p1]", sql="SELECT `t_ubigint`.`a` FROM ? AS `t_ubigint` WHERE (`t_ubigint`.`a` BETWEEN ? AND ?)", params="9223372036854775809,9223372036854775809") +Gather(concurrent=true) + LogicalView(tables="t_ubigint[p1]", sql="SELECT `a` FROM `t_ubigint` AS `t_ubigint` WHERE (`a` BETWEEN ? AND ?)") EXPLAIN SELECT * FROM t_ubigint WHERE a = 9223372036854775809; diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_between.result b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_between.result index 17216f8fd..71ee9071b 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_between.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_between.result @@ -15,11 +15,12 @@ FROM tbl_bt WHERE b BETWEEN 2000 AND 3000 AND a = 100; Logical ExecutionPlan -PhyTableOperation(tables="tbl_bt[p2]", sql="SELECT `tbl_bt`.`a` AS `a` FROM ? AS `tbl_bt` WHERE ((`tbl_bt`.`b` BETWEEN ? AND ?) AND (`tbl_bt`.`a` = ?))", params="3000,2000,100") +Gather(concurrent=true) + LogicalView(tables="tbl_bt[p2]", sql="SELECT `a` FROM `tbl_bt` AS `tbl_bt` WHERE ((`b` BETWEEN ? AND ?) AND (`a` = ?))") EXPLAIN SELECT a FROM tbl_bt WHERE a BETWEEN 200 AND 300 AND b = 1250; Logical ExecutionPlan Gather(concurrent=true) - LogicalView(tables="tbl_bt[p2,p4]", shardCount=2, sql="SELECT `a` FROM `tbl_bt` AS `tbl_bt` WHERE ((`a` BETWEEN ? AND ?) AND (`b` = ?))") + LogicalView(tables="tbl_bt[p2,p4]", shardCount=2, sql="SELECT `a` FROM `tbl_bt` AS `tbl_bt` WHERE ((`a` BETWEEN ? AND ?) AND (`b` = ?))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_null2.result b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_null2.result index 0d0157493..59b3e3719 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_null2.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_null2.result @@ -1,10 +1,10 @@ DROP TABLE IF EXISTS tbl_rng_col; CREATE TABLE `tbl_rng_col` ( - `a` bigint(20) DEFAULT NULL, - `b` bigint(20) DEFAULT NULL, - `c` bigint(20) DEFAULT NULL, - `d` bigint(20) DEFAULT NULL, - `e` bigint(20) DEFAULT NULL + `a` bigint DEFAULT NULL, + `b` bigint DEFAULT NULL, + `c` bigint DEFAULT NULL, + `d` bigint DEFAULT NULL, + `e` bigint DEFAULT NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY RANGE COLUMNS (b) ( PARTITION p1 VALUES LESS THAN (1000) @@ -34,7 +34,8 @@ EXPLAIN SELECT a FROM tbl_rng_col WHERE b <= NULL; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col[p1]", sql="SELECT `tbl_rng_col`.`a` AS `a` FROM ? AS `tbl_rng_col` WHERE (`tbl_rng_col`.`b` <= NULL)") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col[p1]", sql="SELECT `a` FROM `tbl_rng_col` AS `tbl_rng_col` WHERE (`b` <= NULL)") EXPLAIN SELECT a FROM tbl_rng_col WHERE b = NULL; @@ -50,13 +51,14 @@ EXPLAIN SELECT a FROM tbl_rng_col WHERE b < NULL; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col[p1]", sql="SELECT `tbl_rng_col`.`a` AS `a` FROM ? AS `tbl_rng_col` WHERE (`tbl_rng_col`.`b` < NULL)") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col[p1]", sql="SELECT `a` FROM `tbl_rng_col` AS `tbl_rng_col` WHERE (`b` < NULL)") CREATE TABLE `tbl_rng_col2` ( - `a` bigint(20) DEFAULT NULL, - `b` bigint(20) DEFAULT NULL, - `c` bigint(20) DEFAULT NULL, - `d` bigint(20) DEFAULT NULL, - `e` bigint(20) DEFAULT NULL + `a` bigint DEFAULT NULL, + `b` bigint DEFAULT NULL, + `c` bigint DEFAULT NULL, + `d` bigint DEFAULT NULL, + `e` bigint DEFAULT NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY RANGE COLUMNS (b, c) ( PARTITION p1 VALUES LESS THAN (1000, 10000) @@ -92,12 +94,14 @@ EXPLAIN SELECT a FROM tbl_rng_col2 WHERE b <= NULL; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col2[p1]", sql="SELECT `tbl_rng_col2`.`a` AS `a` FROM ? AS `tbl_rng_col2` WHERE (`tbl_rng_col2`.`b` <= NULL)") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col2[p1]", sql="SELECT `a` FROM `tbl_rng_col2` AS `tbl_rng_col2` WHERE (`b` <= NULL)") EXPLAIN SELECT a FROM tbl_rng_col2 WHERE b = NULL; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col2[p1]", sql="SELECT `tbl_rng_col2`.`a` AS `a` FROM ? AS `tbl_rng_col2` WHERE (`tbl_rng_col2`.`b` = ?)", params="NULL") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col2[p1]", sql="SELECT `a` FROM `tbl_rng_col2` AS `tbl_rng_col2` WHERE (`b` = ?)") EXPLAIN SELECT a FROM tbl_rng_col2 WHERE b > NULL; @@ -108,7 +112,8 @@ EXPLAIN SELECT a FROM tbl_rng_col2 WHERE b < NULL; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col2[p1]", sql="SELECT `tbl_rng_col2`.`a` AS `a` FROM ? AS `tbl_rng_col2` WHERE (`tbl_rng_col2`.`b` < NULL)") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col2[p1]", sql="SELECT `a` FROM `tbl_rng_col2` AS `tbl_rng_col2` WHERE (`b` < NULL)") SELECT a FROM tbl_rng_col2 WHERE (b, c) = (1001, NULL); diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_row_expr.result b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_row_expr.result index 461625b07..2656d126e 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_row_expr.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_pruning_row_expr.result @@ -1,10 +1,10 @@ DROP TABLE IF EXISTS tbl_rng_col; CREATE TABLE `tbl_rng_col` ( - `a` bigint(20) DEFAULT NULL, - `b` bigint(20) DEFAULT NULL, - `c` bigint(20) DEFAULT NULL, - `d` bigint(20) DEFAULT NULL, - `e` bigint(20) DEFAULT NULL + `a` bigint DEFAULT NULL, + `b` bigint DEFAULT NULL, + `c` bigint DEFAULT NULL, + `d` bigint DEFAULT NULL, + `e` bigint DEFAULT NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY RANGE COLUMNS (b) ( PARTITION p1 VALUES LESS THAN (1000) @@ -60,11 +60,11 @@ a,b,c,d,e 2001,2001,1,1,1 2002,null,1,1,1 CREATE TABLE `tbl_rng_col2` ( - `a` bigint(20) DEFAULT NULL, - `b` bigint(20) DEFAULT NULL, - `c` bigint(20) DEFAULT NULL, - `d` bigint(20) DEFAULT NULL, - `e` bigint(20) DEFAULT NULL + `a` bigint DEFAULT NULL, + `b` bigint DEFAULT NULL, + `c` bigint DEFAULT NULL, + `d` bigint DEFAULT NULL, + `e` bigint DEFAULT NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY RANGE COLUMNS (b, c) ( PARTITION p1 VALUES LESS THAN (1000, 10000) @@ -157,7 +157,8 @@ EXPLAIN SELECT * FROM tbl_rng_col2 WHERE (b, c, a) >= (2001, 1999, 10000); Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_col2[p3]", sql="SELECT `tbl_rng_col2`.`a`, `tbl_rng_col2`.`b`, `tbl_rng_col2`.`c`, `tbl_rng_col2`.`d`, `tbl_rng_col2`.`e` FROM ? AS `tbl_rng_col2` WHERE ((`tbl_rng_col2`.`b`, `tbl_rng_col2`.`c`, `tbl_rng_col2`.`a`) >=(?, ?, ?))", params="1999,2001,10000") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_col2[p3]", sql="SELECT `a`, `b`, `c`, `d`, `e` FROM `tbl_rng_col2` AS `tbl_rng_col2` WHERE ((`b`, `c`, `a`) >=(?, ?, ?))") EXPLAIN SELECT * FROM tbl_rng_col2 WHERE (b, c, a) = (2001, 1999, 10000); diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_timezone.result b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_timezone.result index 9e0616736..e8d06fed6 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_timezone.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_part_timezone.result @@ -120,7 +120,8 @@ a 1998-12-31 17:00:00.0 explain /*TDDL:cmd_extra(IN_SUB_QUERY_THRESHOLD=8)*/select * from tbl_rng_ts2 where a='1998-12-31 15:00:00' or a='1998-12-31 17:00:00'; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_ts2[p0]", sql="SELECT `tbl_rng_ts2`.`a` FROM ? AS `tbl_rng_ts2` WHERE (`tbl_rng_ts2`.`a` IN (?, ?))", params="1998-12-31 17:00:00,1998-12-31 15:00:00") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_ts2[p0]", sql="SELECT `a` FROM `tbl_rng_ts2` AS `tbl_rng_ts2` WHERE (`a` IN(?, ?))") set time_zone="+08:00"; ## both '1998-12-31 23:00:00' and '1999-01-01 01:00:00' should be route to p0 select * from tbl_rng_ts2 where a ='1998-12-31 23:00:00' or a='1999-01-01 01:00:00'; @@ -129,4 +130,5 @@ a 1999-01-01 01:00:00.0 explain /*TDDL:cmd_extra(IN_SUB_QUERY_THRESHOLD=8)*/select * from tbl_rng_ts2 where a ='1998-12-31 23:00:00' or a='1999-01-01 01:00:00'; Logical ExecutionPlan -PhyTableOperation(tables="tbl_rng_ts2[p0]", sql="SELECT `tbl_rng_ts2`.`a` FROM ? AS `tbl_rng_ts2` WHERE (`tbl_rng_ts2`.`a` IN (?, ?))", params="1999-01-01 01:00:00,1998-12-31 23:00:00") +Gather(concurrent=true) + LogicalView(tables="tbl_rng_ts2[p0]", sql="SELECT `a` FROM `tbl_rng_ts2` AS `tbl_rng_ts2` WHERE (`a` IN(?, ?))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_select_partitions.result b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_select_partitions.result index 543c53532..bc8914dba 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_select_partitions.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTablePruningTest/test_select_partitions.result @@ -1,6 +1,6 @@ ## DISABLE_FAST_SQL_PARSER CREATE TABLE t1 ( - id bigint(20) NOT NULL AUTO_INCREMENT, + id bigint NOT NULL AUTO_INCREMENT, a int, primary key(id) ) @@ -10,7 +10,7 @@ PARTITION BY RANGE (a) ( PARTITION p2 VALUES LESS THAN (300) ); CREATE TABLE t2 ( - id bigint(20) NOT NULL AUTO_INCREMENT, + id bigint NOT NULL AUTO_INCREMENT, a int, primary key(id) ) @@ -22,18 +22,14 @@ PARTITION BY RANGE (a) ( explain select * from t1 partition (p1) join t2 partition (p1) on t1.id=t2.id; Logical ExecutionPlan BKAJoin(condition="id = id", type="inner") - Gather(concurrent=true) - LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") - Gather(concurrent=true) - LogicalView(tables="t2[p1]", sql="SELECT `id`, `a` FROM `t2` AS `t2` WHERE (`id` IN (...))") + LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") + LogicalView(tables="t2[p1]", sql="SELECT `id`, `a` FROM `t2` AS `t2` WHERE (`id` IN (...))") explain select * from t1 partition (p1); Logical ExecutionPlan -Gather(concurrent=true) - LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") +LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") explain select * from t2 partition (p1); Logical ExecutionPlan -Gather(concurrent=true) - LogicalView(tables="t2[p1]", sql="SELECT `id`, `a` FROM `t2` AS `t2`") +LogicalView(tables="t2[p1]", sql="SELECT `id`, `a` FROM `t2` AS `t2`") explain select * from t1 partition (p1) join t2 partition (p1) on t1.a=t2.a; Logical ExecutionPlan Gather(concurrent=true) @@ -41,7 +37,5 @@ Gather(concurrent=true) explain select * from t1 partition (p1) join t2 partition (p2) on t1.a=t2.a; Logical ExecutionPlan BKAJoin(condition="a = a", type="inner") - Gather(concurrent=true) - LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") - Gather(concurrent=true) - LogicalView(tables="t2[p2]", sql="SELECT `id`, `a` FROM `t2` AS `t2` WHERE (`a` IN (...))") \ No newline at end of file + LogicalView(tables="t1[p1]", sql="SELECT `id`, `a` FROM `t1` AS `t1`") + LogicalView(tables="t2[p2]", sql="SELECT `id`, `a` FROM `t2` AS `t2` WHERE (`a` IN (...))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_list.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_list.result index f34fbcda5..5f9b1a282 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_list.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_list.result @@ -9,7 +9,7 @@ PARTITION BY LIST (a) ( SHOW CREATE TABLE tbl; Table,Create Table tbl,CREATE TABLE `tbl` ( - `a` int(11) NOT NULL, + `a` int NOT NULL, KEY `auto_shard_key_a` USING BTREE (`a`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY LIST(`a`) @@ -37,7 +37,8 @@ EXPLAIN SELECT * FROM tbl WHERE a < 5; Logical ExecutionPlan -PhyTableOperation(tables="tbl[p0]", sql="SELECT `tbl`.`a` FROM ? AS `tbl` WHERE (`tbl`.`a` < ?)", params="5") +Gather(concurrent=true) + LogicalView(tables="tbl[p0]", sql="SELECT `a` FROM `tbl` AS `tbl` WHERE (`a` < ?)") DROP TABLE IF EXISTS tbl; CREATE TABLE IF NOT EXISTS tbl ( a datetime NOT NULL diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofmonth.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofmonth.result index 278c98b28..2186fd45d 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofmonth.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofmonth.result @@ -37,9 +37,6 @@ d explain select * from d1 where d = '2022-07-18' order by d; Logical ExecutionPlan PhyTableOperation(tables="d1[p11]", sql="SELECT `d1`.`d` FROM ? AS `d1` WHERE (`d1`.`d` = ?) ORDER BY `d`", params="2022-07-18") -HitCache:false -Source:PLAN_CACHE -TemplateId: 024aaf5b explain select * from d1 where d = '2022-06-18' order by d; Logical ExecutionPlan PhyTableOperation(tables="d1[p11]", sql="SELECT `d1`.`d` FROM ? AS `d1` WHERE (`d1`.`d` = ?) ORDER BY `d`", params="2022-06-18") @@ -178,9 +175,6 @@ d explain select * from d3 where d = '2022-07-01'; Logical ExecutionPlan PhyTableOperation(tables="d3[p0]", sql="SELECT `d3`.`d` FROM ? AS `d3` WHERE (`d3`.`d` = ?)", params="2022-07-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: 2fdcbc3e explain select * from d3 where d = '2022-07-07'; Logical ExecutionPlan PhyTableOperation(tables="d3[p1]", sql="SELECT `d3`.`d` FROM ? AS `d3` WHERE (`d3`.`d` = ?)", params="2022-07-07") @@ -264,9 +258,6 @@ dt explain select * from d4 where dt = '2022-07-01 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="d4[p0]", sql="SELECT `d4`.`dt` FROM ? AS `d4` WHERE (`d4`.`dt` = ?)", params="2022-07-01 00:00:00") -HitCache:false -Source:PLAN_CACHE -TemplateId: b22b860d explain select * from d4 where dt = '2022-07-07 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="d4[p1]", sql="SELECT `d4`.`dt` FROM ? AS `d4` WHERE (`d4`.`dt` = ?)", params="2022-07-07 00:00:00") @@ -350,9 +341,6 @@ d explain select * from d5 where d = '2022-07-07'; Logical ExecutionPlan PhyTableOperation(tables="d5[p0]", sql="SELECT `d5`.`d` FROM ? AS `d5` WHERE (`d5`.`d` = ?)", params="2022-07-07") -HitCache:false -Source:PLAN_CACHE -TemplateId: 0ce2c940 explain select * from d5 where d = '2022-07-14'; Logical ExecutionPlan PhyTableOperation(tables="d5[p1]", sql="SELECT `d5`.`d` FROM ? AS `d5` WHERE (`d5`.`d` = ?)", params="2022-07-14") diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofmonth2.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofmonth2.result index 072762c71..1860b907e 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofmonth2.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofmonth2.result @@ -26,8 +26,9 @@ part_route('', 'hash_dayofmonth', '2025-01-01 00:00:00.000') p1 explain select d from hash_dayofmonth where d between '2022-02-28' and '2022-03-01'; Logical ExecutionPlan -PhyTableOperation(tables="hash_dayofmonth[p1]", sql="SELECT `hash_dayofmonth`.`d` AS `d` FROM ? AS `hash_dayofmonth` WHERE (`hash_dayofmonth`.`d` BETWEEN ? AND ?)", params="2022-03-01,2022-02-28") +Gather(concurrent=true) + LogicalView(tables="hash_dayofmonth[p1]", sql="SELECT `d` FROM `hash_dayofmonth` AS `hash_dayofmonth` WHERE (`d` BETWEEN ? AND ?)") explain select d from hash_dayofmonth where d between '2024-02-28' and '2024-03-01'; Logical ExecutionPlan Gather(concurrent=true) - LogicalView(tables="hash_dayofmonth[p1,p7]", shardCount=2, sql="SELECT `d` FROM `hash_dayofmonth` AS `hash_dayofmonth` WHERE (`d` BETWEEN ? AND ?)") \ No newline at end of file + LogicalView(tables="hash_dayofmonth[p1,p7]", shardCount=2, sql="SELECT `d` FROM `hash_dayofmonth` AS `hash_dayofmonth` WHERE (`d` BETWEEN ? AND ?)") diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofweek.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofweek.result index 4d26b259f..c29f8811a 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofweek.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofweek.result @@ -32,9 +32,6 @@ d explain select * from w1 where d = '2022-07-17'; Logical ExecutionPlan PhyTableOperation(tables="w1[p1]", sql="SELECT `w1`.`d` FROM ? AS `w1` WHERE (`w1`.`d` = ?)", params="2022-07-17") -HitCache:false -Source:PLAN_CACHE -TemplateId: 164ca609 explain select * from w1 where d = '2022-07-18'; Logical ExecutionPlan PhyTableOperation(tables="w1[p6]", sql="SELECT `w1`.`d` FROM ? AS `w1` WHERE (`w1`.`d` = ?)", params="2022-07-18") @@ -109,9 +106,6 @@ dt explain select * from w2 where dt = '2022-07-17 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="w2[p1]", sql="SELECT `w2`.`dt` FROM ? AS `w2` WHERE (`w2`.`dt` = ?)", params="2022-07-17 00:00:00") -HitCache:false -Source:PLAN_CACHE -TemplateId: 99b8d5a2 explain select * from w2 where dt = '2022-07-18 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="w2[p6]", sql="SELECT `w2`.`dt` FROM ? AS `w2` WHERE (`w2`.`dt` = ?)", params="2022-07-18 00:00:00") @@ -218,9 +212,6 @@ d explain select * from w3 where d = '2022-07-17'; Logical ExecutionPlan PhyTableOperation(tables="w3[p2]", sql="SELECT `w3`.`d` FROM ? AS `w3` WHERE (`w3`.`d` = ?)", params="2022-07-17") -HitCache:false -Source:PLAN_CACHE -TemplateId: f352b30b explain select * from w3 where d = '2022-07-18'; Logical ExecutionPlan PhyTableOperation(tables="w3[p3]", sql="SELECT `w3`.`d` FROM ? AS `w3` WHERE (`w3`.`d` = ?)", params="2022-07-18") @@ -350,9 +341,6 @@ d explain select * from w4 where d = '2022-07-17'; Logical ExecutionPlan PhyTableOperation(tables="w4[p1]", sql="SELECT `w4`.`d` FROM ? AS `w4` WHERE (`w4`.`d` = ?)", params="2022-07-17") -HitCache:false -Source:PLAN_CACHE -TemplateId: e1d5b98c explain select * from w4 where d = '2022-07-18'; Logical ExecutionPlan PhyTableOperation(tables="w4[p2]", sql="SELECT `w4`.`d` FROM ? AS `w4` WHERE (`w4`.`d` = ?)", params="2022-07-18") diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofyear.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofyear.result index 9691a2439..4e48f24cb 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofyear.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_dayofyear.result @@ -32,9 +32,6 @@ d explain select * from y1 where d = '2021-07-01'; Logical ExecutionPlan PhyTableOperation(tables="y1[p5]", sql="SELECT `y1`.`d` FROM ? AS `y1` WHERE (`y1`.`d` = ?)", params="2021-07-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: da083947 explain select * from y1 where d = '2022-01-01'; Logical ExecutionPlan PhyTableOperation(tables="y1[p1]", sql="SELECT `y1`.`d` FROM ? AS `y1` WHERE (`y1`.`d` = ?)", params="2022-01-01") @@ -108,9 +105,6 @@ dt explain select * from y2 where dt = '2021-07-01 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="y2[p5]", sql="SELECT `y2`.`dt` FROM ? AS `y2` WHERE (`y2`.`dt` = ?)", params="2021-07-01 00:00:00") -HitCache:false -Source:PLAN_CACHE -TemplateId: 4d6faa24 explain select * from y2 where dt = '2022-01-01 00:00:00'; Logical ExecutionPlan PhyTableOperation(tables="y2[p1]", sql="SELECT `y2`.`dt` FROM ? AS `y2` WHERE (`y2`.`dt` = ?)", params="2022-01-01 00:00:00") @@ -190,9 +184,6 @@ d explain select * from y3 where d = '2022-01-01'; Logical ExecutionPlan PhyTableOperation(tables="y3[p0]", sql="SELECT `y3`.`d` FROM ? AS `y3` WHERE (`y3`.`d` = ?)", params="2022-01-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: b70e4649 explain select * from y3 where d = '2021-01-10'; Logical ExecutionPlan PhyTableOperation(tables="y3[p1]", sql="SELECT `y3`.`d` FROM ? AS `y3` WHERE (`y3`.`d` = ?)", params="2021-01-10") @@ -273,9 +264,6 @@ d explain select * from y4 where d = '2021-01-01'; Logical ExecutionPlan PhyTableOperation(tables="y4[p0]", sql="SELECT `y4`.`d` FROM ? AS `y4` WHERE (`y4`.`d` = ?)", params="2021-01-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: a5914cca explain select * from y4 where d = '2020-01-10'; Logical ExecutionPlan PhyTableOperation(tables="y4[p1]", sql="SELECT `y4`.`d` FROM ? AS `y4` WHERE (`y4`.`d` = ?)", params="2020-01-10") @@ -349,9 +337,6 @@ explain select * from y5 where d >= '2020-02-28' and d < '2020-03-02' order by d Logical ExecutionPlan MergeSort(sort="d ASC") LogicalView(tables="y5[p28,p268,p304,p350]", shardCount=4, sql="SELECT `d` FROM `y5` AS `y5` WHERE ((`d` >= ?) AND (`d` < ?)) ORDER BY `d`") -HitCache:false -Source:PLAN_CACHE -TemplateId: b3ce44af explain select * from y5 where d > '2020-02-28' and d < '2020-03-01' order by d; Logical ExecutionPlan MergeSort(sort="d ASC") diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_substr.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_substr.result index 7bb499dc1..6a55b188e 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_substr.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_substr.result @@ -36,12 +36,14 @@ EXPLAIN SELECT id FROM s3 WHERE id IN ('12abc'); Logical ExecutionPlan -PhyTableOperation(tables="s3[p5]", sql="SELECT `s3`.`id` AS `id` FROM ? AS `s3` WHERE (`s3`.`id` IN (?))", params="Raw('12abc')") +Gather(concurrent=true) + LogicalView(tables="s3[p5]", sql="SELECT `id` FROM `s3` AS `s3` WHERE (`id` IN(?))") EXPLAIN SELECT id FROM s3 WHERE id IN ('34abc'); Logical ExecutionPlan -PhyTableOperation(tables="s3[p5]", sql="SELECT `s3`.`id` AS `id` FROM ? AS `s3` WHERE (`s3`.`id` IN (?))", params="Raw('34abc')") +Gather(concurrent=true) + LogicalView(tables="s3[p5]", sql="SELECT `id` FROM `s3` AS `s3` WHERE (`id` IN(?))") EXPLAIN SELECT id FROM s3 WHERE id > '12abc'; @@ -421,4 +423,4 @@ lstr_f3,CREATE TABLE `lstr_f3` ( ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3 PARTITION BY LIST(SUBSTRING(`id`,3)) (PARTITION p2 VALUES IN ('123','456') ENGINE = InnoDB, - PARTITION p1 VALUES IN ('abc','efg') ENGINE = InnoDB) + PARTITION p1 VALUES IN ('abc','efg') ENGINE = InnoDB) \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_todays.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_todays.result index 7f9e94942..ce7ca68ed 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_todays.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_todays.result @@ -46,17 +46,11 @@ a explain select * from tbl where a='1989-01-01' order by a; Logical ExecutionPlan PhyTableOperation(tables="tbl[p0]", sql="SELECT `tbl`.`a` FROM ? AS `tbl` WHERE (`tbl`.`a` = ?) ORDER BY `a`", params="1989-01-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: 48dfdf4e ## explain range select explain select * from tbl where (a<'2019-01-02' and a>='2009-12-31') or a between '1989-01-01' and '1989-11-01' order by a; Logical ExecutionPlan MergeSort(sort="a ASC") LogicalView(tables="tbl[p0,p2,p3]", shardCount=3, sql="SELECT `a` FROM `tbl` AS `tbl` WHERE (((`a` < ?) AND (`a` >= ?)) OR (`a` BETWEEN ? AND ?)) ORDER BY `a`") -HitCache:false -Source:PLAN_CACHE -TemplateId: d85eb230 ## test hash CREATE TABLE `tod1` ( `d` date DEFAULT NULL diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_tomonths.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_tomonths.result index b051ae44e..3aa01c5a9 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_tomonths.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_tomonths.result @@ -32,9 +32,6 @@ d explain select * from m1 where d = '0000-01-01'; Logical ExecutionPlan PhyTableOperation(tables="m1[p1]", sql="SELECT `m1`.`d` FROM ? AS `m1` WHERE (`m1`.`d` = ?)", params="0000-01-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: 43a2c5d3 explain select * from m1 where d = '0000-03-01'; Logical ExecutionPlan PhyTableOperation(tables="m1[p14]", sql="SELECT `m1`.`d` FROM ? AS `m1` WHERE (`m1`.`d` = ?)", params="0000-03-01") @@ -163,9 +160,6 @@ explain select * from m4 where dt > '2021-12-31' order by dt; Logical ExecutionPlan MergeSort(sort="dt ASC") LogicalView(tables="m4[p1,p2,p3,...p128]", shardCount=128, sql="SELECT `dt` FROM `m4` AS `m4` WHERE (`dt` > ?) ORDER BY `dt`") -HitCache:false -Source:PLAN_CACHE -TemplateId: e67c62d4 explain select * from m4 where dt >= '2021-12-30' and dt < '2023-01-01' order by dt; Logical ExecutionPlan MergeSort(sort="dt ASC") diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_toweeks.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_toweeks.result index 23c194279..111f8dd90 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_toweeks.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_toweeks.result @@ -32,9 +32,6 @@ d explain select * from w1 where d = '0000-01-01'; Logical ExecutionPlan PhyTableOperation(tables="w1[p9]", sql="SELECT `w1`.`d` FROM ? AS `w1` WHERE (`w1`.`d` = ?)", params="0000-01-01") -HitCache:false -Source:PLAN_CACHE -TemplateId: 164ca609 explain select * from w1 where d = '0000-01-02'; Logical ExecutionPlan PhyTableOperation(tables="w1[p9]", sql="SELECT `w1`.`d` FROM ? AS `w1` WHERE (`w1`.`d` = ?)", params="0000-01-02") @@ -155,9 +152,6 @@ explain select * from w4 where dt > '2021-12-31' order by dt; Logical ExecutionPlan MergeSort(sort="dt ASC") LogicalView(tables="w4[p1,p2,p3,...p128]", shardCount=128, sql="SELECT `dt` FROM `w4` AS `w4` WHERE (`dt` > ?) ORDER BY `dt`") -HitCache:false -Source:PLAN_CACHE -TemplateId: 23a70a5e explain select * from w4 where dt >= '2021-12-30' and dt < '2022-01-01' order by dt; Logical ExecutionPlan PhyTableOperation(tables="w4[p53]", sql="SELECT `w4`.`dt` FROM ? AS `w4` WHERE ((`w4`.`dt` >= ?) AND (`w4`.`dt` < ?)) ORDER BY `dt`", params="2022-01-01,2021-12-30") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_toweeks2.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_toweeks2.result index 28be9d292..e3fae5448 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_toweeks2.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTest/test_part_func_toweeks2.result @@ -9,16 +9,10 @@ partitions 8; explain select dt from hash_to_weeks where dt = '2021-12-25'; Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p8]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2021-12-25") -HitCache:false -Source:PLAN_CACHE -TemplateId: 10895681 ## two-week explain select dt from hash_to_weeks where dt = '2021-12-26'; Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p4]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2021-12-26") -HitCache:true -Source:PLAN_CACHE -TemplateId: 10895681 explain select dt from hash_to_weeks where dt = '2021-12-27'; Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p4]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2021-12-27") @@ -32,9 +26,6 @@ PhyTableOperation(tables="hash_to_weeks[p4]", sql="SELECT `hash_to_weeks`.`dt` A explain select dt from hash_to_weeks where dt = '2022-01-02'; Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p7]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2022-01-02") -HitCache:true -Source:PLAN_CACHE -TemplateId: 10895681 explain select dt from hash_to_weeks where dt = '2022-01-03'; Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p7]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2022-01-03") @@ -43,7 +34,8 @@ Logical ExecutionPlan PhyTableOperation(tables="hash_to_weeks[p7]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` = ?)", params="2022-01-08") explain select dt from hash_to_weeks where dt between '2022-01-02' and '2022-01-08'; Logical ExecutionPlan -PhyTableOperation(tables="hash_to_weeks[p7]", sql="SELECT `hash_to_weeks`.`dt` AS `dt` FROM ? AS `hash_to_weeks` WHERE (`hash_to_weeks`.`dt` BETWEEN ? AND ?)", params="2022-01-08,2022-01-02") +Gather(concurrent=true) + LogicalView(tables="hash_to_weeks[p7]", sql="SELECT `dt` FROM `hash_to_weeks` AS `hash_to_weeks` WHERE (`dt` BETWEEN ? AND ?)") explain select dt from hash_to_weeks where dt between '2022-01-01' and '2022-01-08'; Logical ExecutionPlan Gather(concurrent=true) diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test1.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test1.result index df4cbaebd..3b5d3c6ad 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test1.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test1.result @@ -3,15 +3,15 @@ ## test hash tbl drop table if exists nation; CREATE TABLE `nation` ( - `N_NATIONKEY` int(11) NOT NULL, + `N_NATIONKEY` int NOT NULL, `N_NAME` char(255) DEFAULT NULL, - `N_REGIONKEY` int(11) DEFAULT NULL, + `N_REGIONKEY` int DEFAULT NULL, `N_COMMENT` varchar(255) DEFAULT NULL, PRIMARY KEY (`N_NATIONKEY`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`N_NATIONKEY`) PARTITIONS 8; -explain SELECT +explain /*TDDL:IN_SUB_QUERY_THRESHOLD=10000*/ SELECT nation.n_nationkey, nation.n_regionkey, nation.n_comment, @@ -32,4 +32,5 @@ WHERE AND nation.n_nationkey IS NOT NULL AND nation.n_nationkey BETWEEN 3.805471129478495 AND 4.758352957397205; Logical ExecutionPlan -PhyTableOperation(tables="nation[p8]", sql="SELECT `nation`.`N_NATIONKEY` AS `n_nationkey`, `nation`.`N_REGIONKEY` AS `n_regionkey`, `nation`.`N_COMMENT` AS `n_comment`, `nation`.`N_NAME` AS `n_name` FROM ? AS `nation` WHERE ((`nation`.`N_NATIONKEY` IN (?)) AND (`nation`.`N_NATIONKEY` IN (?)) AND ((`nation`.`N_NATIONKEY` + ?) <= ?) AND (`nation`.`N_NATIONKEY` IN (?)) AND (`nation`.`N_NATIONKEY` IS NOT NULL) AND (`nation`.`N_NATIONKEY` BETWEEN ? AND ?))", params="Raw(4,1.9768277360857997E9),3.805471129478495,5.27214097707928,Raw(4,4.472058352208863E8,1.333687324233481E9,4.1576415757607274E7),1,4.758352957397205,Raw(4,8.81152213174817E8,3.389451686261133E8,1.6448133002964172E9)") \ No newline at end of file +Gather(concurrent=true) + LogicalView(tables="nation[p8]", sql="SELECT `N_NATIONKEY` AS `n_nationkey`, `N_REGIONKEY` AS `n_regionkey`, `N_COMMENT` AS `n_comment`, `N_NAME` AS `n_name` FROM `nation` AS `nation` WHERE (((`N_NATIONKEY` + ?) <= ?) AND (`N_NATIONKEY` IN(?)) AND (`N_NATIONKEY` IN(?)) AND (`N_NATIONKEY` IN(?)) AND (`N_NATIONKEY` BETWEEN ? AND ?) AND (`N_NATIONKEY` IS NOT NULL))", pruningInfo="all size:10*1(part), pruning size:7") diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test1.test.yml b/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test1.test.yml index 0c14b77a5..dbadb7cfc 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test1.test.yml +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test1.test.yml @@ -13,7 +13,7 @@ CREATE TABLE `nation` ( PARTITION BY KEY(`N_NATIONKEY`) PARTITIONS 8; -explain SELECT +explain /*TDDL:IN_SUB_QUERY_THRESHOLD=10000*/ SELECT nation.n_nationkey, nation.n_regionkey, nation.n_comment, diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test2.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test2.result index 97908801f..1f347dd47 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test2.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test2.result @@ -2,9 +2,9 @@ ## test hash tbl drop table if exists nation; CREATE TABLE `nation` ( - `N_NATIONKEY` int(11) NOT NULL, + `N_NATIONKEY` int NOT NULL, `N_NAME` char(255) DEFAULT NULL, - `N_REGIONKEY` int(11) DEFAULT NULL, + `N_REGIONKEY` int DEFAULT NULL, `N_COMMENT` varchar(255) DEFAULT NULL, PRIMARY KEY (`N_NATIONKEY`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8 @@ -13,7 +13,7 @@ PARTITIONS 8; explain /*TDDL:cmd_extra(USE_FAST_SINGLE_POINT_INTERVAL_MERGING=TRUE)*/SELECT nation.n_nationkey, nation.n_regionkey, nation.n_comment, nation.n_name FROM nation WHERE nation.n_name <= 'FEGYPT' AND nation.n_nationkey = 4 AND nation.n_regionkey * 1.125 <= 4.597964841150929 AND nation.n_regionkey <= 4.603817292328983 AND nation.n_nationkey IN (4, 6.571142182969552E7, 1.0225007368253655E9, 1.3282392195771594E9) AND nation.n_comment IS NOT NULL AND nation.n_regionkey - 5 > -1.2458977715312591 AND nation.n_name != 'eD^)&oW4*F' AND nation.n_comment != 'F!fd)e' AND nation.n_name > 'DEGYPT' GROUP BY nation.n_nationkey, nation.n_regionkey, nation.n_comment, nation.n_name ORDER BY nation.n_nationkey, nation.n_regionkey, nation.n_comment, nation.n_name; Logical ExecutionPlan MergeSort(sort="n_nationkey ASC,n_regionkey ASC,n_comment ASC,n_name ASC") - LogicalView(tables="nation[p4,p6,p8]", shardCount=3, sql="SELECT `N_NATIONKEY` AS `n_nationkey`, `N_REGIONKEY` AS `n_regionkey`, `N_COMMENT` AS `n_comment`, `N_NAME` AS `n_name` FROM `nation` AS `nation` WHERE ((`N_NATIONKEY` = ?) AND ((`N_REGIONKEY` * ?) <= ?) AND ((`N_REGIONKEY` - ?) > ?) AND (`N_NATIONKEY` IN(?)) AND (`N_NAME` <= ?) AND (`N_REGIONKEY` <= ?) AND (`N_NAME` > ?) AND (`N_COMMENT` IS NOT NULL) AND (`N_NAME` <> ?) AND (`N_COMMENT` <> ?)) ORDER BY `N_NATIONKEY`, `N_REGIONKEY`, `N_COMMENT`, `N_NAME`", isDynamicParam="true") + LogicalView(tables="nation[p4,p6,p8]", shardCount=3, sql="SELECT `N_NATIONKEY` AS `n_nationkey`, `N_REGIONKEY` AS `n_regionkey`, `N_COMMENT` AS `n_comment`, `N_NAME` AS `n_name` FROM `nation` AS `nation` WHERE ((`N_NATIONKEY` = ?) AND ((`N_REGIONKEY` * ?) <= ?) AND ((`N_REGIONKEY` - ?) > ?) AND (`N_NATIONKEY` IN(?)) AND (`N_NAME` <= ?) AND (`N_REGIONKEY` <= ?) AND (`N_NAME` > ?) AND (`N_COMMENT` IS NOT NULL) AND (`N_NAME` <> ?) AND (`N_COMMENT` <> ?)) ORDER BY `N_NATIONKEY`, `N_REGIONKEY`, `N_COMMENT`, `N_NAME`", pruningInfo="all size:4*3(part), pruning size:8") explain /*TDDL:cmd_extra(USE_FAST_SINGLE_POINT_INTERVAL_MERGING=FALSE)*/SELECT nation.n_nationkey, nation.n_regionkey, nation.n_comment, nation.n_name FROM nation WHERE nation.n_name <= 'FEGYPT' AND nation.n_nationkey = 4 AND nation.n_regionkey * 1.125 <= 4.597964841150929 AND nation.n_regionkey <= 4.603817292328983 AND nation.n_nationkey IN (4, 6.571142182969552E7, 1.0225007368253655E9, 1.3282392195771594E9) AND nation.n_comment IS NOT NULL AND nation.n_regionkey - 5 > -1.2458977715312591 AND nation.n_name != 'eD^)&oW4*F' AND nation.n_comment != 'F!fd)e' AND nation.n_name > 'DEGYPT' GROUP BY nation.n_nationkey, nation.n_regionkey, nation.n_comment, nation.n_name ORDER BY nation.n_nationkey, nation.n_regionkey, nation.n_comment, nation.n_name; Logical ExecutionPlan PhyTableOperation(tables="nation[p8]", sql="SELECT `nation`.`N_NATIONKEY` AS `n_nationkey`, `nation`.`N_REGIONKEY` AS `n_regionkey`, `nation`.`N_COMMENT` AS `n_comment`, `nation`.`N_NAME` AS `n_name` FROM ? AS `nation` WHERE ((`nation`.`N_NAME` <= ?) AND (`nation`.`N_NATIONKEY` = ?) AND ((`nation`.`N_REGIONKEY` * ?) <= ?) AND (`nation`.`N_REGIONKEY` <= ?) AND (`nation`.`N_NATIONKEY` IN (?)) AND (`nation`.`N_COMMENT` IS NOT NULL) AND ((`nation`.`N_REGIONKEY` - ?) > ?) AND (`nation`.`N_NAME` <> ?) AND (`nation`.`N_COMMENT` <> ?) AND (`nation`.`N_NAME` > ?)) GROUP BY `nation`.`N_NATIONKEY`, `nation`.`N_REGIONKEY`, `nation`.`N_COMMENT`, `nation`.`N_NAME` ORDER BY `nation`.`N_NATIONKEY`, `nation`.`N_REGIONKEY`, `nation`.`N_COMMENT`, `nation`.`N_NAME`", params="4,Raw(4,6.571142182969552E7,1.0225007368253655E9,1.3282392195771594E9),4.597964841150929,-1.2458977715312591,eD^)&oW4*F,DEGYPT,F!fd)e,FEGYPT,1.125,5,4.603817292328983") diff --git a/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test3.result b/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test3.result index de5cdeb0b..68e37aa8e 100644 --- a/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test3.result +++ b/polardbx-test/src/test/resources/partition/env80/PartitionTableTypeCastTest/test3.result @@ -1,8 +1,8 @@ DROP TABLE IF EXISTS nation; CREATE TABLE `nation` ( - `N_NATIONKEY` int(11) NOT NULL, + `N_NATIONKEY` int NOT NULL, `N_NAME` char(255) DEFAULT NULL, - `N_REGIONKEY` int(11) DEFAULT NULL, + `N_REGIONKEY` int DEFAULT NULL, `N_COMMENT` varchar(255) DEFAULT NULL, PRIMARY KEY (`N_NATIONKEY`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8 @@ -22,11 +22,13 @@ FROM nation WHERE N_NATIONKEY = 100 AND N_NATIONKEY < 100.5; Logical ExecutionPlan -PhyTableOperation(tables="nation[p2]", sql="SELECT `nation`.`N_NATIONKEY`, `nation`.`N_NAME`, `nation`.`N_REGIONKEY`, `nation`.`N_COMMENT` FROM ? AS `nation` WHERE ((`nation`.`N_NATIONKEY` = ?) AND (`nation`.`N_NATIONKEY` < ?))", params="100.5,100") +Gather(concurrent=true) + LogicalView(tables="nation[p2]", sql="SELECT `N_NATIONKEY`, `N_NAME`, `N_REGIONKEY`, `N_COMMENT` FROM `nation` AS `nation` WHERE ((`N_NATIONKEY` = ?) AND (`N_NATIONKEY` < ?))") EXPLAIN SELECT * FROM nation WHERE N_NATIONKEY = 100 AND N_NATIONKEY < 100.5 AND N_NATIONKEY > 99.12; Logical ExecutionPlan -PhyTableOperation(tables="nation[p2]", sql="SELECT `nation`.`N_NATIONKEY`, `nation`.`N_NAME`, `nation`.`N_REGIONKEY`, `nation`.`N_COMMENT` FROM ? AS `nation` WHERE ((`nation`.`N_NATIONKEY` = ?) AND (`nation`.`N_NATIONKEY` < ?) AND (`nation`.`N_NATIONKEY` > ?))", params="100.5,100,99.12") \ No newline at end of file +Gather(concurrent=true) + LogicalView(tables="nation[p2]", sql="SELECT `N_NATIONKEY`, `N_NAME`, `N_REGIONKEY`, `N_COMMENT` FROM `nation` AS `nation` WHERE ((`N_NATIONKEY` = ?) AND (`N_NATIONKEY` < ?) AND (`N_NATIONKEY` > ?))") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/SubPartitionTableAlterTest/test_all_ntp_subpart_split_merge.result b/polardbx-test/src/test/resources/partition/env80/SubPartitionTableAlterTest/test_all_ntp_subpart_split_merge.result index 579214dae..7d9fc9096 100644 --- a/polardbx-test/src/test/resources/partition/env80/SubPartitionTableAlterTest/test_all_ntp_subpart_split_merge.result +++ b/polardbx-test/src/test/resources/partition/env80/SubPartitionTableAlterTest/test_all_ntp_subpart_split_merge.result @@ -61,20 +61,20 @@ h_h_ntp1,CREATE TABLE `h_h_ntp1` ( PARTITION BY HASH(`c`,`d`) SUBPARTITION BY HASH(`a`,`b`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p1 VALUES LESS THAN (3) - (SUBPARTITION sp1 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p1sp1 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p2 VALUES LESS THAN (4611686018427387905) - (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p2sp2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p3sp3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table h_h_ntp2; Table,Create Table @@ -92,20 +92,20 @@ h_h_ntp2,CREATE TABLE `h_h_ntp2` ( PARTITION BY HASH(`c`,`d`) SUBPARTITION BY HASH(`a`,`b`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p1 VALUES LESS THAN (3) - (SUBPARTITION sp1 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p1sp1 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p2 VALUES LESS THAN (4611686018427387905) - (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p2sp2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p3sp3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table h_h_ntp1; drop table h_h_ntp2; @@ -170,20 +170,20 @@ h_k_ntp1,CREATE TABLE `h_k_ntp1` ( PARTITION BY HASH(`c`,`d`) SUBPARTITION BY KEY(`a`,`b`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p1 VALUES LESS THAN (3) - (SUBPARTITION sp1 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p1sp1 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p2 VALUES LESS THAN (4611686018427387905) - (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p2sp2 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p3sp3 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table h_k_ntp2; Table,Create Table @@ -201,20 +201,20 @@ h_k_ntp2,CREATE TABLE `h_k_ntp2` ( PARTITION BY HASH(`c`,`d`) SUBPARTITION BY KEY(`a`,`b`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p1 VALUES LESS THAN (3) - (SUBPARTITION sp1 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p1sp1 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p2 VALUES LESS THAN (4611686018427387905) - (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p2sp2 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p3sp3 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table h_k_ntp1; drop table h_k_ntp2; @@ -314,29 +314,29 @@ h_r_ntp1,CREATE TABLE `h_r_ntp1` ( PARTITION BY HASH(`a`,`b`) SUBPARTITION BY RANGE(TO_DAYS(`c`)) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px1 VALUES LESS THAN (-3074457345618258599) - (SUBPARTITION sp3 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px1sp3 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px1sp4 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px1sp11 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px1sp12 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px2 VALUES LESS THAN (-1537228672809129299) - (SUBPARTITION sp13 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px2sp13 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px2sp14 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px2sp15 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px2sp16 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px3 VALUES LESS THAN (3) - (SUBPARTITION sp17 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp19 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px3sp17 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px3sp18 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px3sp19 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px3sp20 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807) (SUBPARTITION sp1 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -356,29 +356,29 @@ h_r_ntp2,CREATE TABLE `h_r_ntp2` ( PARTITION BY HASH(`a`,`b`) SUBPARTITION BY RANGE(TO_DAYS(`c`)) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px1 VALUES LESS THAN (-3074457345618258599) - (SUBPARTITION sp3 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px1sp3 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px1sp4 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px1sp11 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px1sp12 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px2 VALUES LESS THAN (-1537228672809129299) - (SUBPARTITION sp13 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px2sp13 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px2sp14 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px2sp15 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px2sp16 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px3 VALUES LESS THAN (3) - (SUBPARTITION sp17 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp19 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px3sp17 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px3sp18 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px3sp19 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px3sp20 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807) (SUBPARTITION sp1 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -480,29 +480,29 @@ h_rc_ntp1,CREATE TABLE `h_rc_ntp1` ( PARTITION BY HASH(`a`,`b`) SUBPARTITION BY RANGE COLUMNS(`c`,`d`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px1 VALUES LESS THAN (-3074457345618258599) - (SUBPARTITION sp3 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp4 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp12 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px1sp3 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp4 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp11 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp12 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px2 VALUES LESS THAN (-1537228672809129299) - (SUBPARTITION sp13 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp16 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px2sp13 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp14 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp15 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp16 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px3 VALUES LESS THAN (3) - (SUBPARTITION sp17 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp18 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp19 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp20 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px3sp17 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp18 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp19 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp20 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807) (SUBPARTITION sp1 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -522,29 +522,29 @@ h_rc_ntp2,CREATE TABLE `h_rc_ntp2` ( PARTITION BY HASH(`a`,`b`) SUBPARTITION BY RANGE COLUMNS(`c`,`d`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px1 VALUES LESS THAN (-3074457345618258599) - (SUBPARTITION sp3 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp4 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp12 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px1sp3 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp4 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp11 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp12 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px2 VALUES LESS THAN (-1537228672809129299) - (SUBPARTITION sp13 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp16 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px2sp13 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp14 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp15 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp16 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px3 VALUES LESS THAN (3) - (SUBPARTITION sp17 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp18 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp19 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp20 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px3sp17 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp18 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp19 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp20 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807) (SUBPARTITION sp1 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -644,32 +644,32 @@ h_l_ntp1,CREATE TABLE `h_l_ntp1` ( PARTITION BY HASH(`a`,`b`) SUBPARTITION BY LIST(TO_DAYS(`c`)) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (-3074457345618258599) - (SUBPARTITION sp3 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p3sp3 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p3sp4 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p3sp11 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p3sp12 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p3sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p4 VALUES LESS THAN (-1537228672809129299) - (SUBPARTITION sp14 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp17 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), - PARTITION p11 VALUES LESS THAN (3) - (SUBPARTITION sp19 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp21 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp22 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p4sp14 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p4sp15 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p4sp16 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p4sp17 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p4sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p8 VALUES LESS THAN (3) + (SUBPARTITION p8sp19 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p8sp20 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p8sp21 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p8sp22 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p8sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807) (SUBPARTITION sp1 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -689,32 +689,32 @@ h_l_ntp2,CREATE TABLE `h_l_ntp2` ( PARTITION BY HASH(`a`,`b`) SUBPARTITION BY LIST(TO_DAYS(`c`)) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (-3074457345618258599) - (SUBPARTITION sp3 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p3sp3 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p3sp4 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p3sp11 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p3sp12 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p3sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p4 VALUES LESS THAN (-1537228672809129299) - (SUBPARTITION sp14 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp17 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), - PARTITION p11 VALUES LESS THAN (3) - (SUBPARTITION sp19 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp21 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp22 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p4sp14 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p4sp15 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p4sp16 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p4sp17 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p4sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p8 VALUES LESS THAN (3) + (SUBPARTITION p8sp19 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p8sp20 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p8sp21 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p8sp22 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p8sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807) (SUBPARTITION sp1 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -814,32 +814,32 @@ h_lc_ntp1,CREATE TABLE `h_lc_ntp1` ( PARTITION BY HASH(`a`,`b`) SUBPARTITION BY LIST COLUMNS(`c`,`d`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (-3074457345618258599) - (SUBPARTITION sp3 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p3sp3 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp4 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp11 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp12 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p3sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p4 VALUES LESS THAN (-1537228672809129299) - (SUBPARTITION sp14 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp17 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), - PARTITION p11 VALUES LESS THAN (3) - (SUBPARTITION sp19 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp21 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp22 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p4sp14 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp15 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp16 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp17 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p4sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p8 VALUES LESS THAN (3) + (SUBPARTITION p8sp19 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp20 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp21 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp22 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p8sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807) (SUBPARTITION sp1 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -859,32 +859,32 @@ h_lc_ntp2,CREATE TABLE `h_lc_ntp2` ( PARTITION BY HASH(`a`,`b`) SUBPARTITION BY LIST COLUMNS(`c`,`d`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505) - (SUBPARTITION sp5 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202) - (SUBPARTITION sp7 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899) - (SUBPARTITION sp9 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (-3074457345618258599) - (SUBPARTITION sp3 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p3sp3 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp4 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp11 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp12 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p3sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p4 VALUES LESS THAN (-1537228672809129299) - (SUBPARTITION sp14 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp17 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), - PARTITION p11 VALUES LESS THAN (3) - (SUBPARTITION sp19 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp21 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp22 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p4sp14 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp15 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp16 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp17 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p4sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p8 VALUES LESS THAN (3) + (SUBPARTITION p8sp19 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp20 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp21 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp22 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p8sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807) (SUBPARTITION sp1 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -952,20 +952,20 @@ k_h_ntp1,CREATE TABLE `k_h_ntp1` ( PARTITION BY KEY(`c`,`d`) SUBPARTITION BY HASH(`a`,`b`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p1 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp1 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p1sp1 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p2 VALUES LESS THAN (6148914691236517205,9223372036854775807) - (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p2sp2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (9223372036854775807,9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p3sp3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table k_h_ntp2; Table,Create Table @@ -983,20 +983,20 @@ k_h_ntp2,CREATE TABLE `k_h_ntp2` ( PARTITION BY KEY(`c`,`d`) SUBPARTITION BY HASH(`a`,`b`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES LESS THAN (1) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (1) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p1 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp1 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p1sp1 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p2 VALUES LESS THAN (6148914691236517205,9223372036854775807) - (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p2sp2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (9223372036854775807,9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p3sp3 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table k_h_ntp1; drop table k_h_ntp2; @@ -1061,20 +1061,20 @@ k_k_ntp1,CREATE TABLE `k_k_ntp1` ( PARTITION BY KEY(`c`,`d`) SUBPARTITION BY KEY(`a`,`b`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p1 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp1 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p1sp1 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p2 VALUES LESS THAN (6148914691236517205,9223372036854775807) - (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p2sp2 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (9223372036854775807,9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p3sp3 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table k_k_ntp2; Table,Create Table @@ -1092,20 +1092,20 @@ k_k_ntp2,CREATE TABLE `k_k_ntp2` ( PARTITION BY KEY(`c`,`d`) SUBPARTITION BY KEY(`a`,`b`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (1,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p1 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp1 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p1sp1 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p2 VALUES LESS THAN (6148914691236517205,9223372036854775807) - (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), + (SUBPARTITION p2sp2 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (9223372036854775807,9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p3sp3 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table k_k_ntp1; drop table k_k_ntp2; @@ -1205,29 +1205,29 @@ k_r_ntp1,CREATE TABLE `k_r_ntp1` ( PARTITION BY KEY(`a`,`b`) SUBPARTITION BY RANGE(TO_DAYS(`c`)) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px1 VALUES LESS THAN (-3074457345618258599,9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px1sp3 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px1sp4 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px1sp11 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px1sp12 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px2 VALUES LESS THAN (-1024819115206086199,9223372036854775807) - (SUBPARTITION sp13 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px2sp13 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px2sp14 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px2sp15 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px2sp16 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px3 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp17 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp19 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px3sp17 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px3sp18 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px3sp19 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px3sp20 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807,9223372036854775807) (SUBPARTITION sp1 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -1247,29 +1247,29 @@ k_r_ntp2,CREATE TABLE `k_r_ntp2` ( PARTITION BY KEY(`a`,`b`) SUBPARTITION BY RANGE(TO_DAYS(`c`)) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px1 VALUES LESS THAN (-3074457345618258599,9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px1sp3 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px1sp4 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px1sp11 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px1sp12 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px2 VALUES LESS THAN (-1024819115206086199,9223372036854775807) - (SUBPARTITION sp13 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px2sp13 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px2sp14 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px2sp15 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px2sp16 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION px3 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp17 VALUES LESS THAN (737790) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES LESS THAN (738156) ENGINE = InnoDB, - SUBPARTITION sp19 VALUES LESS THAN (738521) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px3sp17 VALUES LESS THAN (737790) ENGINE = InnoDB, + SUBPARTITION px3sp18 VALUES LESS THAN (738156) ENGINE = InnoDB, + SUBPARTITION px3sp19 VALUES LESS THAN (738521) ENGINE = InnoDB, + SUBPARTITION px3sp20 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807,9223372036854775807) (SUBPARTITION sp1 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -1371,29 +1371,29 @@ k_rc_ntp1,CREATE TABLE `k_rc_ntp1` ( PARTITION BY KEY(`a`,`b`) SUBPARTITION BY RANGE COLUMNS(`c`,`d`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px1 VALUES LESS THAN (-3074457345618258599,9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp4 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp12 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px1sp3 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp4 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp11 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp12 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px2 VALUES LESS THAN (-1024819115206086199,9223372036854775807) - (SUBPARTITION sp13 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp16 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px2sp13 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp14 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp15 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp16 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px3 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp17 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp18 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp19 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp20 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px3sp17 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp18 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp19 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp20 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807,9223372036854775807) (SUBPARTITION sp1 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -1413,29 +1413,29 @@ k_rc_ntp2,CREATE TABLE `k_rc_ntp2` ( PARTITION BY KEY(`a`,`b`) SUBPARTITION BY RANGE COLUMNS(`c`,`d`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp8 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px1 VALUES LESS THAN (-3074457345618258599,9223372036854775807) - (SUBPARTITION sp3 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp4 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp12 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px1sp3 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp4 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp11 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px1sp12 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px2 VALUES LESS THAN (-1024819115206086199,9223372036854775807) - (SUBPARTITION sp13 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp16 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px2sp13 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp14 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp15 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px2sp16 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION px3 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp17 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp18 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp19 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, - SUBPARTITION sp20 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), + (SUBPARTITION px3sp17 VALUES LESS THAN ('2020-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp18 VALUES LESS THAN ('2021-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp19 VALUES LESS THAN ('2022-01-01 00:00:00','abc') ENGINE = InnoDB, + SUBPARTITION px3sp20 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807,9223372036854775807) (SUBPARTITION sp1 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -1535,32 +1535,32 @@ k_l_ntp1,CREATE TABLE `k_l_ntp1` ( PARTITION BY KEY(`a`,`b`) SUBPARTITION BY LIST(TO_DAYS(`c`)) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (-3074457345618258599,9223372036854775807) - (SUBPARTITION sp3 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p3sp3 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p3sp4 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p3sp11 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p3sp12 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p3sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p4 VALUES LESS THAN (-1024819115206086199,9223372036854775807) - (SUBPARTITION sp14 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp17 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), - PARTITION p11 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp19 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp21 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp22 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p4sp14 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p4sp15 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p4sp16 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p4sp17 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p4sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p8 VALUES LESS THAN (3,9223372036854775807) + (SUBPARTITION p8sp19 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p8sp20 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p8sp21 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p8sp22 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p8sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807,9223372036854775807) (SUBPARTITION sp1 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -1580,32 +1580,32 @@ k_l_ntp2,CREATE TABLE `k_l_ntp2` ( PARTITION BY KEY(`a`,`b`) SUBPARTITION BY LIST(TO_DAYS(`c`)) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (-3074457345618258599,9223372036854775807) - (SUBPARTITION sp3 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p3sp3 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p3sp4 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p3sp11 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p3sp12 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p3sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p4 VALUES LESS THAN (-1024819115206086199,9223372036854775807) - (SUBPARTITION sp14 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp17 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), - PARTITION p11 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp19 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES IN (10,11,12,13) ENGINE = InnoDB, - SUBPARTITION sp21 VALUES IN (737790) ENGINE = InnoDB, - SUBPARTITION sp22 VALUES IN (738156) ENGINE = InnoDB, - SUBPARTITION sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p4sp14 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p4sp15 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p4sp16 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p4sp17 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p4sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p8 VALUES LESS THAN (3,9223372036854775807) + (SUBPARTITION p8sp19 VALUES IN (1,2,3,4,5,6) ENGINE = InnoDB, + SUBPARTITION p8sp20 VALUES IN (10,11,12,13) ENGINE = InnoDB, + SUBPARTITION p8sp21 VALUES IN (737790) ENGINE = InnoDB, + SUBPARTITION p8sp22 VALUES IN (738156) ENGINE = InnoDB, + SUBPARTITION p8sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807,9223372036854775807) (SUBPARTITION sp1 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -1705,32 +1705,32 @@ k_lc_ntp1,CREATE TABLE `k_lc_ntp1` ( PARTITION BY KEY(`a`,`b`) SUBPARTITION BY LIST COLUMNS(`c`,`d`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (-3074457345618258599,9223372036854775807) - (SUBPARTITION sp3 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p3sp3 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp4 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp11 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp12 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p3sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p4 VALUES LESS THAN (-1024819115206086199,9223372036854775807) - (SUBPARTITION sp14 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp17 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), - PARTITION p11 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp19 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp21 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp22 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p4sp14 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp15 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp16 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp17 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p4sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p8 VALUES LESS THAN (3,9223372036854775807) + (SUBPARTITION p8sp19 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp20 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp21 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp22 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p8sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807,9223372036854775807) (SUBPARTITION sp1 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -1750,32 +1750,32 @@ k_lc_ntp2,CREATE TABLE `k_lc_ntp2` ( PARTITION BY KEY(`a`,`b`) SUBPARTITION BY LIST COLUMNS(`c`,`d`) (PARTITION p5 VALUES LESS THAN (-7686143364045646505,9223372036854775807) - (SUBPARTITION sp5 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p5sp5 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p5sp6 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p6 VALUES LESS THAN (-6148914691236517202,9223372036854775807) - (SUBPARTITION sp7 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p6sp7 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p6sp8 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p7 VALUES LESS THAN (-4611686018427387899,9223372036854775807) - (SUBPARTITION sp9 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p7sp9 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p7sp10 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p3 VALUES LESS THAN (-3074457345618258599,9223372036854775807) - (SUBPARTITION sp3 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp4 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp12 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p3sp3 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp4 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp11 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p3sp12 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p3sp13 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p4 VALUES LESS THAN (-1024819115206086199,9223372036854775807) - (SUBPARTITION sp14 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp16 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp17 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), - PARTITION p11 VALUES LESS THAN (3,9223372036854775807) - (SUBPARTITION sp19 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp20 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp21 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, - SUBPARTITION sp22 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, - SUBPARTITION sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), + (SUBPARTITION p4sp14 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp15 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp16 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p4sp17 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p4sp18 VALUES IN (DEFAULT) ENGINE = InnoDB), + PARTITION p8 VALUES LESS THAN (3,9223372036854775807) + (SUBPARTITION p8sp19 VALUES IN (('2020-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp20 VALUES IN (('2021-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp21 VALUES IN (('2021-01-01 00:00:00','bc'),('2021-01-02 00:00:00','abc'),('2022-01-01 00:00:00','abc')) ENGINE = InnoDB, + SUBPARTITION p8sp22 VALUES IN (('2021-11-01 00:00:00','abc'),('2022-10-01 00:00:00','abc'),('2022-10-01 00:00:00','abce')) ENGINE = InnoDB, + SUBPARTITION p8sp23 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p34 VALUES LESS THAN (9223372036854775807,9223372036854775807) (SUBPARTITION sp1 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` @@ -3090,9 +3090,9 @@ SUBPARTITION BY HASH(`a`,`b`) SUBPARTITION pxx4 VALUES LESS THAN (-4611686018427387899) ENGINE = InnoDB, SUBPARTITION p2sp234 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p32 VALUES IN (DEFAULT) - (SUBPARTITION sp13 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p32sp13 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, + SUBPARTITION p32sp14 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, + SUBPARTITION p32sp15 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table l_h_ntp2; Table,Create Table @@ -3123,9 +3123,9 @@ SUBPARTITION BY HASH(`a`,`b`) SUBPARTITION pxx4 VALUES LESS THAN (-4611686018427387899) ENGINE = InnoDB, SUBPARTITION p2sp234 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p32 VALUES IN (DEFAULT) - (SUBPARTITION sp13 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p32sp13 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, + SUBPARTITION p32sp14 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, + SUBPARTITION p32sp15 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table l_h_ntp1; drop table l_h_ntp2; @@ -3201,9 +3201,9 @@ SUBPARTITION BY KEY(`a`,`b`) SUBPARTITION pxx4 VALUES LESS THAN (-4611686018427387899,9223372036854775807) ENGINE = InnoDB, SUBPARTITION p2sp234 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p32 VALUES IN (DEFAULT) - (SUBPARTITION sp13 VALUES LESS THAN (-3074457345618258601,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (3074457345618258603,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p32sp13 VALUES LESS THAN (-3074457345618258601,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p32sp14 VALUES LESS THAN (3074457345618258603,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p32sp15 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table l_k_ntp2; Table,Create Table @@ -3234,9 +3234,9 @@ SUBPARTITION BY KEY(`a`,`b`) SUBPARTITION pxx4 VALUES LESS THAN (-4611686018427387899,9223372036854775807) ENGINE = InnoDB, SUBPARTITION p2sp234 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p32 VALUES IN (DEFAULT) - (SUBPARTITION sp13 VALUES LESS THAN (-3074457345618258601,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (3074457345618258603,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp15 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p32sp13 VALUES LESS THAN (-3074457345618258601,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p32sp14 VALUES LESS THAN (3074457345618258603,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p32sp15 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table l_k_ntp1; drop table l_k_ntp2; @@ -3316,9 +3316,9 @@ SUBPARTITION BY RANGE(`a`) PARTITION p2 VALUES IN (1000000,3000000) (SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES LESS THAN (1000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (2000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES LESS THAN (1000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES LESS THAN (2000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table l_r_ntp2; Table,Create Table @@ -3341,9 +3341,9 @@ SUBPARTITION BY RANGE(`a`) PARTITION p2 VALUES IN (1000000,3000000) (SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES LESS THAN (1000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (2000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES LESS THAN (1000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES LESS THAN (2000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table l_r_ntp1; drop table l_r_ntp2; @@ -3423,9 +3423,9 @@ SUBPARTITION BY RANGE COLUMNS(`a`,`b`) (SUBPARTITION p1sp1 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (2000,10000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES LESS THAN (2000,10000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table l_rc_ntp2; Table,Create Table @@ -3448,9 +3448,9 @@ SUBPARTITION BY RANGE COLUMNS(`a`,`b`) (SUBPARTITION p1sp1 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (2000,10000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES LESS THAN (2000,10000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table l_rc_ntp1; drop table l_rc_ntp2; @@ -3530,9 +3530,9 @@ SUBPARTITION BY LIST(`a`) (SUBPARTITION p1sp1 VALUES IN (1000,2000) ENGINE = InnoDB, SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES IN (1000,2000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (3000,4000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES IN (1000,2000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES IN (3000,4000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table l_l_ntp2; Table,Create Table @@ -3555,9 +3555,9 @@ SUBPARTITION BY LIST(`a`) (SUBPARTITION p1sp1 VALUES IN (1000,2000) ENGINE = InnoDB, SUBPARTITION p1sp2 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES IN (1000,2000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (3000,4000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES IN (1000,2000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES IN (3000,4000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table l_l_ntp1; drop table l_l_ntp2; @@ -3638,9 +3638,9 @@ SUBPARTITION BY LIST COLUMNS(`a`,`b`) SUBPARTITION p1sp2 VALUES IN ((1000,4000),(1000,5000)) ENGINE = InnoDB, SUBPARTITION p1sp22 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES IN ((1000,2000)) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN ((2000,2000)) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES IN ((1000,2000)) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES IN ((2000,2000)) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table l_lc_ntp2; Table,Create Table @@ -3664,9 +3664,9 @@ SUBPARTITION BY LIST COLUMNS(`a`,`b`) SUBPARTITION p1sp2 VALUES IN ((1000,4000),(1000,5000)) ENGINE = InnoDB, SUBPARTITION p1sp22 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES IN ((1000,2000)) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN ((2000,2000)) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES IN ((1000,2000)) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES IN ((2000,2000)) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table l_lc_ntp1; drop table l_lc_ntp2; @@ -3736,9 +3736,9 @@ SUBPARTITION BY HASH(`a`,`b`) PARTITION p2 VALUES IN (('2020-01-01 00:00:00','abcd'),('2020-01-01 00:00:00','abce'),('2020-01-01 00:00:00','abcf'),('2020-01-02 00:00:00','abcg')) (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp12 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p22sp12 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, + SUBPARTITION p22sp13 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, + SUBPARTITION p22sp14 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table lc_h_ntp2; Table,Create Table @@ -3765,9 +3765,9 @@ SUBPARTITION BY HASH(`a`,`b`) PARTITION p2 VALUES IN (('2020-01-01 00:00:00','abcd'),('2020-01-01 00:00:00','abce'),('2020-01-01 00:00:00','abcf'),('2020-01-02 00:00:00','abcg')) (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp12 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p22sp12 VALUES LESS THAN (-3074457345618258601) ENGINE = InnoDB, + SUBPARTITION p22sp13 VALUES LESS THAN (3074457345618258603) ENGINE = InnoDB, + SUBPARTITION p22sp14 VALUES LESS THAN (9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table lc_h_ntp1; drop table lc_h_ntp2; @@ -3836,9 +3836,9 @@ SUBPARTITION BY KEY(`a`,`b`) PARTITION p2 VALUES IN (('2020-01-01 00:00:00','abcd'),('2020-01-01 00:00:00','abce'),('2020-01-01 00:00:00','abcf'),('2020-01-02 00:00:00','abcg')) (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp12 VALUES LESS THAN (-3074457345618258601,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES LESS THAN (3074457345618258603,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p22sp12 VALUES LESS THAN (-3074457345618258601,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p22sp13 VALUES LESS THAN (3074457345618258603,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p22sp14 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table lc_k_ntp2; Table,Create Table @@ -3865,9 +3865,9 @@ SUBPARTITION BY KEY(`a`,`b`) PARTITION p2 VALUES IN (('2020-01-01 00:00:00','abcd'),('2020-01-01 00:00:00','abce'),('2020-01-01 00:00:00','abcf'),('2020-01-02 00:00:00','abcg')) (SUBPARTITION sp2 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp12 VALUES LESS THAN (-3074457345618258601,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp13 VALUES LESS THAN (3074457345618258603,9223372036854775807) ENGINE = InnoDB, - SUBPARTITION sp14 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) + (SUBPARTITION p22sp12 VALUES LESS THAN (-3074457345618258601,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p22sp13 VALUES LESS THAN (3074457345618258603,9223372036854775807) ENGINE = InnoDB, + SUBPARTITION p22sp14 VALUES LESS THAN (9223372036854775807,9223372036854775807) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table lc_k_ntp1; drop table lc_k_ntp2; @@ -3947,9 +3947,9 @@ SUBPARTITION BY RANGE(`a`) (SUBPARTITION p1sp1 VALUES LESS THAN (1000) ENGINE = InnoDB, SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES LESS THAN (1000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (2000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES LESS THAN (1000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES LESS THAN (2000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table lc_r_ntp2; Table,Create Table @@ -3972,9 +3972,9 @@ SUBPARTITION BY RANGE(`a`) (SUBPARTITION p1sp1 VALUES LESS THAN (1000) ENGINE = InnoDB, SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES LESS THAN (1000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (2000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES LESS THAN (1000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES LESS THAN (2000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table lc_r_ntp1; drop table lc_r_ntp2; @@ -4054,9 +4054,9 @@ SUBPARTITION BY RANGE COLUMNS(`a`,`b`) (SUBPARTITION p1sp1 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (2000,10000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES LESS THAN (2000,10000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table lc_rc_ntp2; Table,Create Table @@ -4079,9 +4079,9 @@ SUBPARTITION BY RANGE COLUMNS(`a`,`b`) (SUBPARTITION p1sp1 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, SUBPARTITION p1sp2 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES LESS THAN (2000,10000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES LESS THAN (1000,10000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES LESS THAN (2000,10000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES LESS THAN (MAXVALUE,MAXVALUE) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table lc_rc_ntp1; drop table lc_rc_ntp2; @@ -4162,9 +4162,9 @@ SUBPARTITION BY LIST(`a`) SUBPARTITION p1sp2 VALUES IN (8000,9000) ENGINE = InnoDB, SUBPARTITION p1sp22 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES IN (1000,2000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (3000,4000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES IN (1000,2000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES IN (3000,4000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table lc_l_ntp2; Table,Create Table @@ -4188,9 +4188,9 @@ SUBPARTITION BY LIST(`a`) SUBPARTITION p1sp2 VALUES IN (8000,9000) ENGINE = InnoDB, SUBPARTITION p1sp22 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES IN (1000,2000) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN (3000,4000) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES IN (1000,2000) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES IN (3000,4000) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table lc_l_ntp1; drop table lc_l_ntp2; @@ -4271,9 +4271,9 @@ SUBPARTITION BY LIST COLUMNS(`a`,`b`) SUBPARTITION p1sp1 VALUES IN ((1000,2000)) ENGINE = InnoDB, SUBPARTITION p1sp22 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES IN ((1000,2000)) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN ((2000,2000)) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES IN ((1000,2000)) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES IN ((2000,2000)) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` /*+TDDL:cmd_extra(SHOW_HASH_PARTITIONS_BY_RANGE=TRUE)*/show full create table lc_lc_ntp2; Table,Create Table @@ -4297,9 +4297,9 @@ SUBPARTITION BY LIST COLUMNS(`a`,`b`) SUBPARTITION p1sp1 VALUES IN ((1000,2000)) ENGINE = InnoDB, SUBPARTITION p1sp22 VALUES IN (DEFAULT) ENGINE = InnoDB), PARTITION p22 VALUES IN (DEFAULT) - (SUBPARTITION sp9 VALUES IN ((1000,2000)) ENGINE = InnoDB, - SUBPARTITION sp10 VALUES IN ((2000,2000)) ENGINE = InnoDB, - SUBPARTITION sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) + (SUBPARTITION p22sp9 VALUES IN ((1000,2000)) ENGINE = InnoDB, + SUBPARTITION p22sp10 VALUES IN ((2000,2000)) ENGINE = InnoDB, + SUBPARTITION p22sp11 VALUES IN (DEFAULT) ENGINE = InnoDB)) tablegroup = `my_ntp_tg_1` drop table lc_lc_ntp1; drop table lc_lc_ntp2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_hash.result b/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_hash.result new file mode 100644 index 000000000..6487d96ba --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_hash.result @@ -0,0 +1,97 @@ +## DISABLE_FAST_SQL_PARSER +CREATE TABLE part_ts_hash ( +a INT, +b varchar(32), +ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (a) +) +partition by hash( unix_timestamp(ts) ) +partitions 8; +set time_zone='+08:00'; +insert into part_ts_hash values (1, '+08:00/shanghai', '2024-10-01 12:00:00'); +set time_zone='+09:00'; +insert into part_ts_hash values (2, '+09:00/tokyo', '2024-10-01 12:00:00'); +set time_zone='-05:00'; +insert into part_ts_hash values (3, '-05:00/chicago', '2024-10-01 12:00:00'); +set time_zone='+08:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +1,+08:00/shanghai,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p2]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +select * from part_ts_hash where ts = '2024-10-01 11:00:00'; +a,b,ts +2,+09:00/tokyo,2024-10-01 11:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 11:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p1]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 11:00:00") +select * from part_ts_hash where ts = '2024-10-02 01:00:00'; +a,b,ts +3,-05:00/chicago,2024-10-02 01:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-02 01:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p6]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-02 01:00:00") +set time_zone='+09:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +2,+09:00/tokyo,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p1]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='-05:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +3,-05:00/chicago,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p6]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +########## +set time_zone='Asia/Shanghai'; +insert into part_ts_hash values (4, '+08:00/shanghai', '2024-10-01 12:00:00'); +set time_zone='Asia/Tokyo'; +insert into part_ts_hash values (5, '+09:00/tokyo', '2024-10-01 12:00:00'); +set time_zone='America/Chicago'; +insert into part_ts_hash values (6, '-05:00/chicago', '2024-10-01 12:00:00'); +set time_zone='Asia/Shanghai'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +1,+08:00/shanghai,2024-10-01 12:00:00.0 +4,+08:00/shanghai,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p2]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='Asia/Tokyo'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +2,+09:00/tokyo,2024-10-01 12:00:00.0 +5,+09:00/tokyo,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p1]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='America/Chicago'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +a,b,ts +3,-05:00/chicago,2024-10-01 12:00:00.0 +6,-05:00/chicago,2024-10-01 12:00:00.0 +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts_hash[p6]", sql="SELECT `part_ts_hash`.`a`, `part_ts_hash`.`b`, `part_ts_hash`.`ts` FROM ? AS `part_ts_hash` WHERE (`part_ts_hash`.`ts` = ?)", params="2024-10-01 12:00:00") +## set time_zone='+09:00' +set time_zone='Asia/Tokyo'; +## shanghai time: "2024-10-01 11:00:00" +select unix_timestamp('2024-10-01 12:00:00'); +unix_timestamp('2024-10-01 12:00:00') +1727751600 +select CONVERT_TZ(FROM_UNIXTIME( unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'),'Asia/Tokyo','Asia/Shanghai'); +CONVERT_TZ(FROM_UNIXTIME(unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'), 'Asia/Tokyo', 'Asia/Shanghai') +2024-10-01 11:00:00.0 +## CST : set time_zone='-05:00' / set time_zone='EST' +set time_zone='America/Chicago'; +## shanghai time: "2024-10-02 01:00:00" +select unix_timestamp('2024-10-01 12:00:00'); +unix_timestamp('2024-10-01 12:00:00') +1727802000 +select CONVERT_TZ(FROM_UNIXTIME( unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'),'America/Chicago','Asia/Shanghai'); +CONVERT_TZ(FROM_UNIXTIME(unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'), 'America/Chicago', 'Asia/Shanghai') +2024-10-02 01:00:00.0 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_hash.test.yml b/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_hash.test.yml new file mode 100644 index 000000000..44837c62c --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_hash.test.yml @@ -0,0 +1,73 @@ +## DISABLE_FAST_SQL_PARSER + +CREATE TABLE part_ts_hash ( +a INT, +b varchar(32), +ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (a) +) +partition by hash( unix_timestamp(ts) ) +partitions 8; + +set time_zone='+08:00'; +insert into part_ts_hash values (1, '+08:00/shanghai', '2024-10-01 12:00:00'); + +set time_zone='+09:00'; +insert into part_ts_hash values (2, '+09:00/tokyo', '2024-10-01 12:00:00'); + +set time_zone='-05:00'; +insert into part_ts_hash values (3, '-05:00/chicago', '2024-10-01 12:00:00'); + +set time_zone='+08:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +select * from part_ts_hash where ts = '2024-10-01 11:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 11:00:00'; +select * from part_ts_hash where ts = '2024-10-02 01:00:00'; +explain select * from part_ts_hash where ts = '2024-10-02 01:00:00'; + +set time_zone='+09:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; + +set time_zone='-05:00'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; + + +########## + +set time_zone='Asia/Shanghai'; +insert into part_ts_hash values (4, '+08:00/shanghai', '2024-10-01 12:00:00'); + +set time_zone='Asia/Tokyo'; +insert into part_ts_hash values (5, '+09:00/tokyo', '2024-10-01 12:00:00'); + +set time_zone='America/Chicago'; +insert into part_ts_hash values (6, '-05:00/chicago', '2024-10-01 12:00:00'); + +set time_zone='Asia/Shanghai'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; + +set time_zone='Asia/Tokyo'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; + +set time_zone='America/Chicago'; +select * from part_ts_hash where ts = '2024-10-01 12:00:00'; +explain select * from part_ts_hash where ts = '2024-10-01 12:00:00'; + + + ## set time_zone='+09:00' +set time_zone='Asia/Tokyo'; + ## shanghai time: "2024-10-01 11:00:00" +select unix_timestamp('2024-10-01 12:00:00'); +select CONVERT_TZ(FROM_UNIXTIME( unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'),'Asia/Tokyo','Asia/Shanghai'); + + ## CST : set time_zone='-05:00' / set time_zone='EST' +set time_zone='America/Chicago'; + ## shanghai time: "2024-10-02 01:00:00" +select unix_timestamp('2024-10-01 12:00:00'); +select CONVERT_TZ(FROM_UNIXTIME( unix_timestamp('2024-10-01 12:00:00'), '%Y-%m-%d %H:%i:%s'),'America/Chicago','Asia/Shanghai'); + diff --git a/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_rng.result b/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_rng.result new file mode 100644 index 000000000..cd5fc18f4 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_rng.result @@ -0,0 +1,78 @@ +## DISABLE_FAST_SQL_PARSER +set LOGICAL_DB_TIME_ZONE='Asia/Shanghai'; +set time_zone='+08:00'; +drop table if exists part_ts; +CREATE TABLE if not exists part_ts ( +a INT, +b varchar(32), +ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (a) +) +partition by range( unix_timestamp(ts) ) +( + partition p1 values less than (unix_timestamp('2024-09-30 00:00:00')), + partition p2 values less than (unix_timestamp('2024-10-01 12:00:00')), + partition p3 values less than (unix_timestamp('2024-10-01 12:30:00')), + partition p4 values less than (unix_timestamp('2024-10-02 01:00:00')), + partition p5 values less than (unix_timestamp('2024-10-02 01:30:00')), + partition p6 values less than (unix_timestamp('2024-10-03 00:00:00')), + partition p7 values less than (maxvalue) +); +set time_zone='+08:00'; +insert into part_ts values (1, '+08:00/shanghai', '2024-10-01 12:00:00'); +set time_zone='+09:00'; +insert into part_ts values (2, '+09:00/tokyo', '2024-10-01 12:00:00'); +set time_zone='-05:00'; +insert into part_ts values (3, '-05:00/chicago', '2024-10-01 12:00:00'); +set time_zone='+08:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +1,+08:00/shanghai,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p3]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='+09:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +2,+09:00/tokyo,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p2]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='-05:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +3,-05:00/chicago,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p5]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") +########## +set time_zone='Asia/Shanghai'; +insert into part_ts values (4, '+08:00/shanghai', '2024-10-01 12:00:00'); +set time_zone='Asia/Tokyo'; +insert into part_ts values (5, '+09:00/tokyo', '2024-10-01 12:00:00'); +set time_zone='America/Chicago'; +insert into part_ts values (6, '-05:00/chicago', '2024-10-01 12:00:00'); +set time_zone='Asia/Shanghai'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +1,+08:00/shanghai,2024-10-01 12:00:00.0 +4,+08:00/shanghai,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p3]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='Asia/Tokyo'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +2,+09:00/tokyo,2024-10-01 12:00:00.0 +5,+09:00/tokyo,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p2]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") +set time_zone='America/Chicago'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +a,b,ts +3,-05:00/chicago,2024-10-01 12:00:00.0 +6,-05:00/chicago,2024-10-01 12:00:00.0 +explain select * from part_ts where ts = '2024-10-01 12:00:00'; +Logical ExecutionPlan +PhyTableOperation(tables="part_ts[p5]", sql="SELECT `part_ts`.`a`, `part_ts`.`b`, `part_ts`.`ts` FROM ? AS `part_ts` WHERE (`part_ts`.`ts` = ?)", params="2024-10-01 12:00:00") \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_rng.test.yml b/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_rng.test.yml new file mode 100644 index 000000000..e46a8764d --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/test_set_tz_rng.test.yml @@ -0,0 +1,69 @@ +## DISABLE_FAST_SQL_PARSER + +set LOGICAL_DB_TIME_ZONE='Asia/Shanghai'; + +set time_zone='+08:00'; +drop table if exists part_ts; +CREATE TABLE if not exists part_ts ( +a INT, +b varchar(32), +ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (a) +) +partition by range( unix_timestamp(ts) ) +( + partition p1 values less than (unix_timestamp('2024-09-30 00:00:00')), + partition p2 values less than (unix_timestamp('2024-10-01 12:00:00')), + partition p3 values less than (unix_timestamp('2024-10-01 12:30:00')), + partition p4 values less than (unix_timestamp('2024-10-02 01:00:00')), + partition p5 values less than (unix_timestamp('2024-10-02 01:30:00')), + partition p6 values less than (unix_timestamp('2024-10-03 00:00:00')), + partition p7 values less than (maxvalue) +); + +set time_zone='+08:00'; +insert into part_ts values (1, '+08:00/shanghai', '2024-10-01 12:00:00'); + +set time_zone='+09:00'; +insert into part_ts values (2, '+09:00/tokyo', '2024-10-01 12:00:00'); + +set time_zone='-05:00'; +insert into part_ts values (3, '-05:00/chicago', '2024-10-01 12:00:00'); + +set time_zone='+08:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='+09:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='-05:00'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + + +########## + + +set time_zone='Asia/Shanghai'; +insert into part_ts values (4, '+08:00/shanghai', '2024-10-01 12:00:00'); + +set time_zone='Asia/Tokyo'; +insert into part_ts values (5, '+09:00/tokyo', '2024-10-01 12:00:00'); + +set time_zone='America/Chicago'; +insert into part_ts values (6, '-05:00/chicago', '2024-10-01 12:00:00'); + +set time_zone='Asia/Shanghai'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='Asia/Tokyo'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + +set time_zone='America/Chicago'; +select * from part_ts where ts = '2024-10-01 12:00:00'; +explain select * from part_ts where ts = '2024-10-01 12:00:00'; + diff --git a/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/testcase.config.yml new file mode 100644 index 000000000..a022131bc --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TimeZoneRoutingTest/testcase.config.yml @@ -0,0 +1,2 @@ +test_set_tz_rng +test_set_tz_hash \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_d.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_d.result new file mode 100644 index 000000000..531197f92 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_d.result @@ -0,0 +1,78 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set sql_mode=''; +CREATE TABLE `ttl_t1_d_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +CREATE TABLE `ttl_t2_d_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t2_d_null values (1, null); +CREATE TABLE `ttl_t3_d_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t3_d_zero values (1, '0000-00-00 00:00:00'); +CREATE TABLE `ttl_t4_d_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t4_d_both values (1, null); +insert into ttl_t4_d_both values (2, '0000-00-00 00:00:00'); +insert into ttl_t4_d_both values (3, '9999-00-00 00:00:00'); +insert into ttl_t4_d_both values (4, '9999-01-01 00:00:00'); +insert into ttl_t4_d_both values (5, '2024-05-05 00:00:00'); +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_d_empty order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_d_null order by a; +a,b_val +1,null +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_d_zero order by a; +a,b_val +1,0000-00-00 00:00:00 +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_d_both order by a; +a,b_val +1,null +2,0000-00-00 00:00:00 +3,9999-00-00 00:00:00 +4,9999-01-01 00:00:00 +5,2024-05-05 00:00:00 +create table ttl_t1_d_empty_arc like ttl_t1_d_empty engine='columnar' archive_mode='ttl'; +create table ttl_t2_d_null_arc like ttl_t2_d_null engine='columnar' archive_mode='ttl'; +create table ttl_t3_d_zero_arc like ttl_t3_d_zero engine='columnar' archive_mode='ttl'; +create table ttl_t4_d_both_arc like ttl_t4_d_both engine='columnar' archive_mode='ttl'; +alter table ttl_t1_d_empty cleanup expired data; +alter table ttl_t2_d_null cleanup expired data; +alter table ttl_t3_d_zero cleanup expired data; +alter table ttl_t4_d_both cleanup expired data; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_d_empty order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_d_null order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_d_zero order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_d_both order by a; +a,b_val +3,9999-00-00 00:00:00 +4,9999-01-01 00:00:00 +5,2024-05-05 00:00:00 +drop table ttl_t1_d_empty; +drop table ttl_t2_d_null; +drop table ttl_t3_d_zero; +drop table ttl_t4_d_both; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_d.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_d.test.yml new file mode 100644 index 000000000..c98f568de --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_d.test.yml @@ -0,0 +1,77 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set sql_mode=''; +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true; + +CREATE TABLE `ttl_t1_d_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +CREATE TABLE `ttl_t2_d_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t2_d_null values (1, null); + +CREATE TABLE `ttl_t3_d_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t3_d_zero values (1, '0000-00-00 00:00:00'); + +CREATE TABLE `ttl_t4_d_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` date DEFAULT NULl, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t4_d_both values (1, null); +insert into ttl_t4_d_both values (2, '0000-00-00 00:00:00'); +insert into ttl_t4_d_both values (3, '9999-00-00 00:00:00'); +insert into ttl_t4_d_both values (4, '9999-01-01 00:00:00'); +insert into ttl_t4_d_both values (5, '2024-05-05 00:00:00'); + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_d_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_d_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_d_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_d_both order by a; + +create table ttl_t1_d_empty_arc like ttl_t1_d_empty engine='columnar' archive_mode='ttl'; +create table ttl_t2_d_null_arc like ttl_t2_d_null engine='columnar' archive_mode='ttl'; +create table ttl_t3_d_zero_arc like ttl_t3_d_zero engine='columnar' archive_mode='ttl'; +create table ttl_t4_d_both_arc like ttl_t4_d_both engine='columnar' archive_mode='ttl'; + +alter table ttl_t1_d_empty cleanup expired data; +alter table ttl_t2_d_null cleanup expired data; +alter table ttl_t3_d_zero cleanup expired data; +alter table ttl_t4_d_both cleanup expired data; + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_d_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_d_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_d_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_d_both order by a; + +drop table ttl_t1_d_empty; +drop table ttl_t2_d_null; +drop table ttl_t3_d_zero; +drop table ttl_t4_d_both; + + + + + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_dt.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_dt.result new file mode 100644 index 000000000..acb2cb178 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_dt.result @@ -0,0 +1,78 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set sql_mode=''; +CREATE TABLE `ttl_t1_dt_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +CREATE TABLE `ttl_t2_dt_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t2_dt_null values (1, null); +CREATE TABLE `ttl_t3_dt_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t3_dt_zero values (1, '0000-00-00 00:00:00'); +CREATE TABLE `ttl_t4_dt_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t4_dt_both values (1, null); +insert into ttl_t4_dt_both values (2, '0000-00-00 00:00:00'); +insert into ttl_t4_dt_both values (3, '9999-00-00 00:00:00'); +insert into ttl_t4_dt_both values (4, '9999-01-01 00:00:00'); +insert into ttl_t4_dt_both values (5, '2024-05-05 00:00:00'); +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_dt_empty order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_dt_null order by a; +a,b_val +1,null +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_dt_zero order by a; +a,b_val +1,0000-00-00 00:00:00 +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_dt_both order by a; +a,b_val +1,null +2,0000-00-00 00:00:00 +3,9999-00-00 00:00:00 +4,9999-01-01 00:00:00 +5,2024-05-05 00:00:00 +create table ttl_t1_dt_empty_arc like ttl_t1_dt_empty engine='columnar' archive_mode='ttl'; +create table ttl_t2_dt_null_arc like ttl_t2_dt_null engine='columnar' archive_mode='ttl'; +create table ttl_t3_dt_zero_arc like ttl_t3_dt_zero engine='columnar' archive_mode='ttl'; +create table ttl_t4_dt_both_arc like ttl_t4_dt_both engine='columnar' archive_mode='ttl'; +alter table ttl_t1_dt_empty cleanup expired data; +alter table ttl_t2_dt_null cleanup expired data; +alter table ttl_t3_dt_zero cleanup expired data; +alter table ttl_t4_dt_both cleanup expired data; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_dt_empty order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_dt_null order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_dt_zero order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_dt_both order by a; +a,b_val +3,9999-00-00 00:00:00 +4,9999-01-01 00:00:00 +5,2024-05-05 00:00:00 +drop table ttl_t1_dt_empty; +drop table ttl_t2_dt_null; +drop table ttl_t3_dt_zero; +drop table ttl_t4_dt_both; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_dt.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_dt.test.yml new file mode 100644 index 000000000..3f78cf6dc --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_dt.test.yml @@ -0,0 +1,77 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set sql_mode=''; +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true; + +CREATE TABLE `ttl_t1_dt_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +CREATE TABLE `ttl_t2_dt_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t2_dt_null values (1, null); + +CREATE TABLE `ttl_t3_dt_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t3_dt_zero values (1, '0000-00-00 00:00:00'); + +CREATE TABLE `ttl_t4_dt_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t4_dt_both values (1, null); +insert into ttl_t4_dt_both values (2, '0000-00-00 00:00:00'); +insert into ttl_t4_dt_both values (3, '9999-00-00 00:00:00'); +insert into ttl_t4_dt_both values (4, '9999-01-01 00:00:00'); +insert into ttl_t4_dt_both values (5, '2024-05-05 00:00:00'); + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_dt_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_dt_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_dt_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_dt_both order by a; + +create table ttl_t1_dt_empty_arc like ttl_t1_dt_empty engine='columnar' archive_mode='ttl'; +create table ttl_t2_dt_null_arc like ttl_t2_dt_null engine='columnar' archive_mode='ttl'; +create table ttl_t3_dt_zero_arc like ttl_t3_dt_zero engine='columnar' archive_mode='ttl'; +create table ttl_t4_dt_both_arc like ttl_t4_dt_both engine='columnar' archive_mode='ttl'; + +alter table ttl_t1_dt_empty cleanup expired data; +alter table ttl_t2_dt_null cleanup expired data; +alter table ttl_t3_dt_zero cleanup expired data; +alter table ttl_t4_dt_both cleanup expired data; + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_dt_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_dt_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_dt_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_dt_both order by a; + +drop table ttl_t1_dt_empty; +drop table ttl_t2_dt_null; +drop table ttl_t3_dt_zero; +drop table ttl_t4_dt_both; + + + + + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_ts.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_ts.result new file mode 100644 index 000000000..0a4a96fd5 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_ts.result @@ -0,0 +1,76 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set sql_mode=''; +CREATE TABLE `ttl_t1_ts_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +CREATE TABLE `ttl_t2_ts_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t2_ts_null values (1, 0); +CREATE TABLE `ttl_t3_ts_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t3_ts_zero values (1, '0000-00-00 00:00:00'); +CREATE TABLE `ttl_t4_ts_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t4_ts_both values (1, 0); +insert into ttl_t4_ts_both values (2, 9999999999999); +insert into ttl_t4_ts_both values (3, '0000-00-00 00:00:00'); +insert into ttl_t4_ts_both values (4, '1970-01-01 00:00:00'); +insert into ttl_t4_ts_both values (5, '2024-05-05 00:00:00'); +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_ts_empty order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_ts_null order by a; +a,b_val +1,0000-00-00 00:00:00 +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_ts_zero order by a; +a,b_val +1,0000-00-00 00:00:00 +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_ts_both order by a; +a,b_val +1,0000-00-00 00:00:00 +2,0000-00-00 00:00:00 +3,0000-00-00 00:00:00 +4,0000-00-00 00:00:00 +5,2024-05-05 00:00:00 +create table ttl_t1_ts_empty_arc like ttl_t1_ts_empty engine='columnar' archive_mode='ttl'; +create table ttl_t2_ts_null_arc like ttl_t2_ts_null engine='columnar' archive_mode='ttl'; +create table ttl_t3_ts_zero_arc like ttl_t3_ts_zero engine='columnar' archive_mode='ttl'; +create table ttl_t4_ts_both_arc like ttl_t4_ts_both engine='columnar' archive_mode='ttl'; +alter table ttl_t1_ts_empty cleanup expired data; +alter table ttl_t2_ts_null cleanup expired data; +alter table ttl_t3_ts_zero cleanup expired data; +alter table ttl_t4_ts_both cleanup expired data; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_ts_empty order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_ts_null order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_ts_zero order by a; +a,b_val +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_ts_both order by a; +a,b_val +5,2024-05-05 00:00:00 +drop table ttl_t1_ts_empty; +drop table ttl_t2_ts_null; +drop table ttl_t3_ts_zero; +drop table ttl_t4_ts_both; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_ts.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_ts.test.yml new file mode 100644 index 000000000..f958cd3f8 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/test_ttl_special_val_ts.test.yml @@ -0,0 +1,72 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set sql_mode=''; +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true; + +CREATE TABLE `ttl_t1_ts_empty` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +CREATE TABLE `ttl_t2_ts_null` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t2_ts_null values (1, 0); + +CREATE TABLE `ttl_t3_ts_zero` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t3_ts_zero values (1, '0000-00-00 00:00:00'); + +CREATE TABLE `ttl_t4_ts_both` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` timestamp, +PRIMARY KEY(a) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 DAY TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; +insert into ttl_t4_ts_both values (1, 0); +insert into ttl_t4_ts_both values (2, 9999999999999); +insert into ttl_t4_ts_both values (3, '0000-00-00 00:00:00'); +insert into ttl_t4_ts_both values (4, '1970-01-01 00:00:00'); +insert into ttl_t4_ts_both values (5, '2024-05-05 00:00:00'); + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_ts_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_ts_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_ts_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_ts_both order by a; + +create table ttl_t1_ts_empty_arc like ttl_t1_ts_empty engine='columnar' archive_mode='ttl'; +create table ttl_t2_ts_null_arc like ttl_t2_ts_null engine='columnar' archive_mode='ttl'; +create table ttl_t3_ts_zero_arc like ttl_t3_ts_zero engine='columnar' archive_mode='ttl'; +create table ttl_t4_ts_both_arc like ttl_t4_ts_both engine='columnar' archive_mode='ttl'; + +alter table ttl_t1_ts_empty cleanup expired data; +alter table ttl_t2_ts_null cleanup expired data; +alter table ttl_t3_ts_zero cleanup expired data; +alter table ttl_t4_ts_both cleanup expired data; + +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t1_ts_empty order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t2_ts_null order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t3_ts_zero order by a; +select a, date_format(b, '%Y-%m-%d %H:%i:%s') b_val from ttl_t4_ts_both order by a; + +drop table ttl_t1_ts_empty; +drop table ttl_t2_ts_null; +drop table ttl_t3_ts_zero; +drop table ttl_t4_ts_both; + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/testcase.config.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/testcase.config.yml new file mode 100644 index 000000000..a7cfc390c --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable2Test/testcase.config.yml @@ -0,0 +1,3 @@ +#test_ttl_special_val_dt +#test_ttl_special_val_d +#test_ttl_special_val_ts \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.result new file mode 100644 index 000000000..0fb67058b --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.result @@ -0,0 +1,63 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set sql_mode='' +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true +set FORBID_DDL_WITH_CCI=false +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI=false +CREATE TABLE `coupon` ( +`Id` varchar(32) NOT NULL COMMENT '主键', +`UserId` varchar(32) NOT NULL COMMENT '用户ID', +`CouponCode` varchar(32) NOT NULL COMMENT '优惠卷编号', +`BeginValidityPeriod` datetime NOT NULL COMMENT '有效期始', +`EndValidityPeriod` datetime NOT NULL COMMENT '有效期止', +`RuleType` tinyint(4) NOT NULL COMMENT '1定额 2折扣 3时长 4免费停车 5定额停车 6免单停车券 7商户免单券', +`FaceAmount` decimal(18, 2) NOT NULL COMMENT '面额', +`RestrictAmount` decimal(18, 2) NOT NULL COMMENT '使用限额', +`RegionId` varchar(32) NOT NULL COMMENT '地区Id', +`ScopeType` tinyint(4) NOT NULL COMMENT '限制类型0 无限制 1地区 2 停车场', +`CouponStatus` tinyint(4) NOT NULL COMMENT '状态 1正常 、未使用 2 已使用 3已过期', +`CouponPublishRuleId` varchar(32) NOT NULL COMMENT '发行规则表Id', +`CouponPublishRuleDetailId` varchar(32) NOT NULL COMMENT '规则明细表Id', +`CouponEventId` varchar(32) NOT NULL COMMENT '事件表Id', +`PaySettleAccountId` varchar(32) NOT NULL COMMENT '发行结算方Id', +`CouponType` tinyint(4) NOT NULL COMMENT '优惠券类型 0通用 1停车券 2洗车券', +`CreateTime` datetime NOT NULL COMMENT '创建时间', +`UpdateTime` datetime NOT NULL COMMENT '修改时间', +`ExtendInfo` varchar(4000) NOT NULL COMMENT '扩展信息', +`IsDelete` tinyint(4) NOT NULL COMMENT '是否删除(0否,1是)', +`Status` tinyint(4) NOT NULL COMMENT '状态(0正常)', +`IsNeedSettle` tinyint(4) NOT NULL, +`ComeFrom` tinyint(4) DEFAULT NULL COMMENT '优惠券来源 0 客服送券,1 发行规则 2 直接插入表的接口3来自无效订单回滚4.商户赠送 5.结算方送商户,商户送用户6.商户赠送(通联)7.团队发券 8.商户赠送(银联) 9.松立山东', +`DirectKey` varchar(32) DEFAULT NULL COMMENT '车辆ID', +`ObjectId` varchar(32) DEFAULT NULL, +`MerchantId` varchar(32) DEFAULT NULL COMMENT '商户id(comefrom为4,5,6时,此字段有值)', +`CreateBy` varchar(32) DEFAULT '' COMMENT '操作人', +`Remarks` varchar(512) DEFAULT '' COMMENT '备注', +`ProjectId` int(4) DEFAULT '0' COMMENT '项目ID', +`PromoterId` varchar(32) DEFAULT NULL COMMENT '推广人Id', +`CouponFlag` tinyint(2) NOT NULL DEFAULT '0' COMMENT '叠加券标识 0:普通券 1”叠加券', +PRIMARY KEY (`Id`, `EndValidityPeriod`), +GLOBAL INDEX `g_i_directkey` (`directkey`) +PARTITION BY KEY(`DirectKey`) +PARTITIONS 8, +KEY `IDX_code` USING BTREE (`CouponCode`), +KEY `IDX_CISB` (`CouponStatus`, `IsDelete`, `Status`, `BeginValidityPeriod`), +KEY `IDX_RU` (`CouponPublishRuleId`), +KEY `idx_dciseb` (`DirectKey`, `CouponStatus`, `IsDelete`, `Status`, `EndValidityPeriod`, `BeginValidityPeriod`), +KEY `idx_uciseb` (`UserId`, `CouponStatus`, `IsDelete`, `Status`, `EndValidityPeriod`, `BeginValidityPeriod`), +KEY `idx_CouponPublishRuleDetailId` (`CouponPublishRuleDetailId`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT '优惠劵' +PARTITION BY KEY(`Id`) +PARTITIONS 8 +alter table coupon modify ttl set ttl_expr = `EndValidityPeriod` expire after 2 month timezone '+08:00' +create table coupon_bak like coupon engine='columnar' archive_mode='ttl' +ALTER TABLE `coupon` ADD COLUMN `update_by` varchar(32) NULL DEFAULT '' COMMENT '更新人' AFTER `CouponFlag` +show create table coupon_bak +View,Create View,character_set_client,collation_connection +coupon_bak,CREATE VIEW `coupon_bak` AS SELECT `coupon`.`Id`, `coupon`.`UserId`, `coupon`.`CouponCode`, `coupon`.`BeginValidityPeriod`, `coupon`.`EndValidityPeriod`, `coupon`.`RuleType`, `coupon`.`FaceAmount`, `coupon`.`RestrictAmount`, `coupon`.`RegionId`, `coupon`.`ScopeType`, `coupon`.`CouponStatus`, `coupon`.`CouponPublishRuleId`, `coupon`.`CouponPublishRuleDetailId`, `coupon`.`CouponEventId`, `coupon`.`PaySettleAccountId`, `coupon`.`CouponType`, `coupon`.`CreateTime`, `coupon`.`UpdateTime`, `coupon`.`ExtendInfo`, `coupon`.`IsDelete`, `coupon`.`Status`, `coupon`.`IsNeedSettle`, `coupon`.`ComeFrom`, `coupon`.`DirectKey`, `coupon`.`ObjectId`, `coupon`.`MerchantId`, `coupon`.`CreateBy`, `coupon`.`Remarks`, `coupon`.`ProjectId`, `coupon`.`PromoterId`, `coupon`.`CouponFlag`, `coupon`.`update_by` +FROM `test_add_col_on__910534051`.`coupon` FORCE INDEX(`ARCTMP_COUPON_BAK`),utf8,utf8_general_ci +drop table coupon_bak +drop table coupon; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.test.yml new file mode 100644 index 000000000..800d3a8ca --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_add_col_on_ttl_tbl.test.yml @@ -0,0 +1,63 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set sql_mode=''; +set TTL_ADD_MAXVAL_PART_ON_CCI_CREATING=true; +set FORBID_DDL_WITH_CCI=false; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI=false; +CREATE TABLE `coupon` ( +`Id` varchar(32) NOT NULL COMMENT '主键', +`UserId` varchar(32) NOT NULL COMMENT '用户ID', +`CouponCode` varchar(32) NOT NULL COMMENT '优惠卷编号', +`BeginValidityPeriod` datetime NOT NULL COMMENT '有效期始', +`EndValidityPeriod` datetime NOT NULL COMMENT '有效期止', +`RuleType` tinyint(4) NOT NULL COMMENT '1定额 2折扣 3时长 4免费停车 5定额停车 6免单停车券 7商户免单券', +`FaceAmount` decimal(18, 2) NOT NULL COMMENT '面额', +`RestrictAmount` decimal(18, 2) NOT NULL COMMENT '使用限额', +`RegionId` varchar(32) NOT NULL COMMENT '地区Id', +`ScopeType` tinyint(4) NOT NULL COMMENT '限制类型0 无限制 1地区 2 停车场', +`CouponStatus` tinyint(4) NOT NULL COMMENT '状态 1正常 、未使用 2 已使用 3已过期', +`CouponPublishRuleId` varchar(32) NOT NULL COMMENT '发行规则表Id', +`CouponPublishRuleDetailId` varchar(32) NOT NULL COMMENT '规则明细表Id', +`CouponEventId` varchar(32) NOT NULL COMMENT '事件表Id', +`PaySettleAccountId` varchar(32) NOT NULL COMMENT '发行结算方Id', +`CouponType` tinyint(4) NOT NULL COMMENT '优惠券类型 0通用 1停车券 2洗车券', +`CreateTime` datetime NOT NULL COMMENT '创建时间', +`UpdateTime` datetime NOT NULL COMMENT '修改时间', +`ExtendInfo` varchar(4000) NOT NULL COMMENT '扩展信息', +`IsDelete` tinyint(4) NOT NULL COMMENT '是否删除(0否,1是)', +`Status` tinyint(4) NOT NULL COMMENT '状态(0正常)', +`IsNeedSettle` tinyint(4) NOT NULL, +`ComeFrom` tinyint(4) DEFAULT NULL COMMENT '优惠券来源 0 客服送券,1 发行规则 2 直接插入表的接口3来自无效订单回滚4.商户赠送 5.结算方送商户,商户送用户6.商户赠送(通联)7.团队发券 8.商户赠送(银联) 9.松立山东', +`DirectKey` varchar(32) DEFAULT NULL COMMENT '车辆ID', +`ObjectId` varchar(32) DEFAULT NULL, +`MerchantId` varchar(32) DEFAULT NULL COMMENT '商户id(comefrom为4,5,6时,此字段有值)', +`CreateBy` varchar(32) DEFAULT '' COMMENT '操作人', +`Remarks` varchar(512) DEFAULT '' COMMENT '备注', +`ProjectId` int(4) DEFAULT '0' COMMENT '项目ID', +`PromoterId` varchar(32) DEFAULT NULL COMMENT '推广人Id', +`CouponFlag` tinyint(2) NOT NULL DEFAULT '0' COMMENT '叠加券标识 0:普通券 1”叠加券', +PRIMARY KEY (`Id`, `EndValidityPeriod`), +GLOBAL INDEX `g_i_directkey` (`directkey`) +PARTITION BY KEY(`DirectKey`) +PARTITIONS 8, +KEY `IDX_code` USING BTREE (`CouponCode`), +KEY `IDX_CISB` (`CouponStatus`, `IsDelete`, `Status`, `BeginValidityPeriod`), +KEY `IDX_RU` (`CouponPublishRuleId`), +KEY `idx_dciseb` (`DirectKey`, `CouponStatus`, `IsDelete`, `Status`, `EndValidityPeriod`, `BeginValidityPeriod`), +KEY `idx_uciseb` (`UserId`, `CouponStatus`, `IsDelete`, `Status`, `EndValidityPeriod`, `BeginValidityPeriod`), +KEY `idx_CouponPublishRuleDetailId` (`CouponPublishRuleDetailId`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT '优惠劵' +PARTITION BY KEY(`Id`) +PARTITIONS 8; +alter table coupon modify ttl set ttl_expr = `EndValidityPeriod` expire after 2 month timezone '+08:00'; +create table coupon_bak like coupon engine='columnar' archive_mode='ttl'; +ALTER TABLE `coupon` ADD COLUMN `update_by` varchar(32) NULL DEFAULT '' COMMENT '更新人' AFTER `CouponFlag`; +show create table coupon_bak; +drop table coupon_bak; +drop table coupon; + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_auto_split_cci_part.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_auto_split_cci_part.result new file mode 100644 index 000000000..ebf7a4960 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_auto_split_cci_part.result @@ -0,0 +1,64 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +create table test_cci_split( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +show create table test_cci_split +Table,Create Table +test_cci_split,CREATE TABLE `test_cci_split` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table test_cci_split_bk like test_cci_split engine='columnar' archive_mode='ttl' +show create table test_cci_split +Table,Create Table +test_cci_split,CREATE TABLE `test_cci_split` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_test_cci_split_bk` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'test_cci_split_bk', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table test_cci_split modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE=4 +alter table test_cci_split cleanup expired data +show create table test_cci_split +Table,Create Table +test_cci_split,CREATE TABLE `test_cci_split` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_test_cci_split_bk` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = Columnar, + PARTITION p202410 VALUES LESS THAN ('2024-11-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'test_cci_split_bk', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI=false +drop table test_cci_split; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_auto_split_cci_part.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_auto_split_cci_part.test.yml new file mode 100644 index 000000000..7c19c1ace --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_auto_split_cci_part.test.yml @@ -0,0 +1,25 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; + +create table test_cci_split( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; +show create table test_cci_split; +create table test_cci_split_bk like test_cci_split engine='columnar' archive_mode='ttl'; +show create table test_cci_split; + +alter table test_cci_split modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE=4; +alter table test_cci_split cleanup expired data; +show create table test_cci_split; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI=false; +drop table test_cci_split; + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl.result new file mode 100644 index 000000000..46d57281d --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl.result @@ -0,0 +1,109 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +create table nottl_tbl( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2 +create table ttl_tbl_without_arc( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +create table ttl_tbl_with_arc( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +create table ttl_tbl_with_arc_bak like ttl_tbl_with_arc engine='columnar' archive_mode='ttl' +show create table nottl_tbl +Table,Create Table +nottl_tbl,CREATE TABLE `nottl_tbl` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 2 +show create table ttl_tbl_without_arc +Table,Create Table +ttl_tbl_without_arc,CREATE TABLE `ttl_tbl_without_arc` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +show create table ttl_tbl_with_arc +Table,Create Table +ttl_tbl_with_arc,CREATE TABLE `ttl_tbl_with_arc` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_arc_bak` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, + PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_arc_bak', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +## error_msg: $# not a ttl-defined #$ +create table like_t1 like nottl_tbl engine='columnar' archive_mode='ttl' +not a ttl-defined +## error_msg: $# not a ttl-defined #$ +create table like_t1 like nottl_tbl engine='columnar' +not a ttl-defined +## error_msg: $# cannot create #$ +create table like_t1 like nottl_tbl archive_mode='ttl' +cannot create +## error_msg: $# without specifying both #$ +create table like_t1 like ttl_tbl_without_arc archive_mode='ttl' +without specifying both +## error_msg: $# without specifying both #$ +create table like_t1 like ttl_tbl_without_arc engine='columnar' +without specifying both +create table like_t1 like ttl_tbl_without_arc +show create table like_t1 +Table,Create Table +like_t1,CREATE TABLE `like_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +## error_msg: $#cannot create #$ +create table like_t2 like ttl_tbl_with_arc +cannot create +set ALLOW_CREATE_TABLE_LIKE_IGNORE_ARCHIVE_CCI=true +create table like_t2 like ttl_tbl_with_arc +create table like_t3 like nottl_tbl +show create table like_t3 +Table,Create Table +like_t3,CREATE TABLE `like_t3` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 2 +drop table if exists nottl_tbl +drop table if exists ttl_tbl_without_arc +drop table if exists ttl_tbl_with_arc +drop table if exists like_t1 +drop table if exists like_t2 +drop table if exists like_t3; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl.test.yml new file mode 100644 index 000000000..5dd30bc02 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl.test.yml @@ -0,0 +1,69 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; + +create table nottl_tbl( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +create table ttl_tbl_without_arc( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; + +create table ttl_tbl_with_arc( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; +create table ttl_tbl_with_arc_bak like ttl_tbl_with_arc engine='columnar' archive_mode='ttl'; + +show create table nottl_tbl; +show create table ttl_tbl_without_arc; +show create table ttl_tbl_with_arc; + +## error_msg: $# not a ttl-defined #$ +create table like_t1 like nottl_tbl engine='columnar' archive_mode='ttl'; +## error_msg: $# not a ttl-defined #$ +create table like_t1 like nottl_tbl engine='columnar'; +## error_msg: $# cannot create #$ +create table like_t1 like nottl_tbl archive_mode='ttl'; + +## error_msg: $# without specifying both #$ +create table like_t1 like ttl_tbl_without_arc archive_mode='ttl'; +## error_msg: $# without specifying both #$ +create table like_t1 like ttl_tbl_without_arc engine='columnar'; + +create table like_t1 like ttl_tbl_without_arc; +show create table like_t1; + +## error_msg: $#cannot create #$ +create table like_t2 like ttl_tbl_with_arc; +set ALLOW_CREATE_TABLE_LIKE_IGNORE_ARCHIVE_CCI=true; +create table like_t2 like ttl_tbl_with_arc; + +create table like_t3 like nottl_tbl; +show create table like_t3; + +drop table if exists nottl_tbl; +drop table if exists ttl_tbl_without_arc; +drop table if exists ttl_tbl_with_arc; +drop table if exists like_t1; +drop table if exists like_t2; +drop table if exists like_t3; + + + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl2.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl2.result new file mode 100644 index 000000000..f03bb1c3d --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl2.result @@ -0,0 +1,119 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +create table ttl_tbl_with_cci( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci engine='columnar' archive_mode='ttl' +create table ttl_tbl_with_cci2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +## error_msg: $# has bound the archive table #$ +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci engine='columnar' archive_mode='ttl' +has bound the archive table +## error_msg: $# already exists #$ +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci2 engine='columnar' archive_mode='ttl' +already exists +create table ttl_tbl_with_cci_bak2 like ttl_tbl_with_cci2 engine='columnar' archive_mode='ttl' +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci_bak` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci_bak', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +already exists +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +already exists +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +already exists +## error_msg: $# not the same #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_xxx` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_yyy', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +not the same +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_xxx` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION pmax VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_xxx', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +drop table if exists ttl_tbl_with_cci +drop table if exists ttl_tbl_with_cci2 +drop table if exists ttl_tbl_with_cci3; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl2.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl2.test.yml new file mode 100644 index 000000000..151df8053 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_create_like_ttl_tbl2.test.yml @@ -0,0 +1,131 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; + +create table ttl_tbl_with_cci( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci engine='columnar' archive_mode='ttl'; + +create table ttl_tbl_with_cci2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; + +## error_msg: $# has bound the archive table #$ +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci engine='columnar' archive_mode='ttl'; + +## error_msg: $# already exists #$ +create table ttl_tbl_with_cci_bak like ttl_tbl_with_cci2 engine='columnar' archive_mode='ttl'; + +create table ttl_tbl_with_cci_bak2 like ttl_tbl_with_cci2 engine='columnar' archive_mode='ttl'; + +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci_bak` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION `pmax` VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci_bak', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION `pmax` VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +## error_msg: $# already exists #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_cci` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION `pmax` VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_cci', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +## error_msg: $# not the same #$ +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_xxx` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION `pmax` VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_yyy', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +CREATE TABLE `ttl_tbl_with_cci3` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED COLUMNAR INDEX `arctmp_ttl_tbl_with_xxx` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = Columnar, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = Columnar, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = Columnar, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = Columnar, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = Columnar, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = Columnar, +PARTITION `pmax` VALUES LESS THAN (MAXVALUE) ENGINE = Columnar) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'ttl_tbl_with_xxx', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + +drop table if exists ttl_tbl_with_cci; +drop table if exists ttl_tbl_with_cci2; +drop table if exists ttl_tbl_with_cci3; + + + + + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_drop_ttl_tbl.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_drop_ttl_tbl.result new file mode 100644 index 000000000..1f7bd1e67 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_drop_ttl_tbl.result @@ -0,0 +1,31 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +create table test_drop_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +show create table test_drop_ttl_t1 +Table,Create Table +test_drop_ttl_t1,CREATE TABLE `test_drop_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table test_drop_ttl_t1_bk like test_drop_ttl_t1 engine='columnar' archive_mode='ttl' +## error_msg: $# Forbid to drop #$ +drop table test_drop_ttl_t1_bk +Forbid to drop +## error_msg: $# Forbid to drop #$ +drop table test_drop_ttl_t1 +Forbid to drop +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false +drop table test_drop_ttl_t1_bk +drop table test_drop_ttl_t1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_drop_ttl_tbl.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_drop_ttl_tbl.test.yml new file mode 100644 index 000000000..79a778c54 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_drop_ttl_tbl.test.yml @@ -0,0 +1,27 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table test_drop_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; +show create table test_drop_ttl_t1; +create table test_drop_ttl_t1_bk like test_drop_ttl_t1 engine='columnar' archive_mode='ttl'; + +## error_msg: $# Forbid to drop #$ +drop table test_drop_ttl_t1_bk; + +## error_msg: $# Forbid to drop #$ +drop table test_drop_ttl_t1; + + +set TTL_FORBID_DROP_TTL_TBL_WITH_ARC_CCI = false; +drop table test_drop_ttl_t1_bk; +drop table test_drop_ttl_t1; diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_rename_ttl_tbl.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_rename_ttl_tbl.result new file mode 100644 index 000000000..c61253743 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_rename_ttl_tbl.result @@ -0,0 +1,27 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask" +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00' +create table test_drop_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2 +show create table test_drop_ttl_t1 +Table,Create Table +test_drop_ttl_t1,CREATE TABLE `test_drop_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table test_drop_ttl_t1_bk like test_drop_ttl_t1 engine='columnar' archive_mode='ttl' +## error_msg: $# not support #$ +rename table test_drop_ttl_t1 to test_drop_ttl_t2 +not support +set FORBID_DDL_WITH_CCI=false +rename table test_drop_ttl_t1 to test_drop_ttl_t2; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_rename_ttl_tbl.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_rename_ttl_tbl.test.yml new file mode 100644 index 000000000..3ffd2c59d --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/test_rename_ttl_tbl.test.yml @@ -0,0 +1,25 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = false; +set TTL_DEBUG_CCI_SKIP_DDL_TASKS = "WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set SKIP_DDL_TASKS="WaitColumnarTableAlterPartitionTask,WaitColumnarTableCreationTask"; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + + +create table test_drop_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +ttl = ttl_definition( TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '0 0 1 */2 * ? *' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 2 ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +partition by key(a) partitions 2; +show create table test_drop_ttl_t1; +create table test_drop_ttl_t1_bk like test_drop_ttl_t1 engine='columnar' archive_mode='ttl'; + +## error_msg: $# not support #$ +rename table test_drop_ttl_t1 to test_drop_ttl_t2; +set FORBID_DDL_WITH_CCI=false; +rename table test_drop_ttl_t1 to test_drop_ttl_t2; + + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/testcase.config.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/testcase.config.yml new file mode 100644 index 000000000..a8428514c --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTable3Test/testcase.config.yml @@ -0,0 +1,6 @@ +#test_drop_ttl_tbl +#test_rename_ttl_tbl +#test_add_col_on_ttl_tbl +#test_auto_split_cci_part +#test_create_like_ttl_tbl +#test_create_like_ttl_tbl2 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl.result new file mode 100644 index 000000000..91d59b8af --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl.result @@ -0,0 +1,59 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create table my_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00'; +select TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE from information_schema.ttl_info where table_name='my_ttl_t1' limit 1; +TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE +my_ttl_t1,OFF,b,`b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00',* * */2 * * ?,null,null,12,64 +alter table my_ttl_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 3 ARCHIVE_TABLE_POST_ALLOCATE = 3; +select TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE from information_schema.ttl_info where table_name='my_ttl_t1' limit 1; +TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE +my_ttl_t1,OFF,b,`b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00',* * */2 * * ?,null,null,3,3 +create table my_arc_t1 like my_ttl_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; +show create table my_ttl_t1; +Table,Create Table +my_ttl_t1,CREATE TABLE `my_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +alter table my_ttl_t1 cleanup expired data; +show create table my_ttl_t1; +Table,Create Table +my_ttl_t1,CREATE TABLE `my_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB, + PARTITION p202410 VALUES LESS THAN ('2024-11-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl.test.yml new file mode 100644 index 000000000..b25692844 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl.test.yml @@ -0,0 +1,21 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create table my_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00'; +select TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE from information_schema.ttl_info where table_name='my_ttl_t1' limit 1; +alter table my_ttl_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 3 ARCHIVE_TABLE_POST_ALLOCATE = 3; +select TABLE_NAME,TTL_ENABLE,TTL_COL,TTL_EXPR,TTL_CRON,ARCHIVE_TABLE_SCHEMA,ARCHIVE_TABLE_NAME,ARCHIVE_TABLE_PRE_ALLOCATE,ARCHIVE_TABLE_POST_ALLOCATE from information_schema.ttl_info where table_name='my_ttl_t1' limit 1; +create table my_arc_t1 like my_ttl_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; +show create table my_ttl_t1; +alter table my_ttl_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +alter table my_ttl_t1 cleanup expired data; +show create table my_ttl_t1; + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl_ts.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl_ts.result new file mode 100644 index 000000000..182bc66bd --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl_ts.result @@ -0,0 +1,154 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set time_zone='+08:00'; +create table my_ttl_ts_t1( +a int not null auto_increment, +b timestamp default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_ts_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE=5, ARCHIVE_TABLE_POST_ALLOCATE=3; +show create table my_ttl_ts_t1; +Table,Create Table +my_ttl_ts_t1,CREATE TABLE `my_ttl_ts_t1` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 5, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_ts_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 3 ARCHIVE_TABLE_POST_ALLOCATE = 3; +show create table my_ttl_ts_t1; +Table,Create Table +my_ttl_ts_t1,CREATE TABLE `my_ttl_ts_t1` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table my_arc_ts_t1 like my_ttl_ts_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; +show create table my_ttl_ts_t1; +Table,Create Table +my_ttl_ts_t1,CREATE TABLE `my_ttl_ts_t1` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_ts_t1` (`b`) + PARTITION BY RANGE(UNIX_TIMESTAMP(`b`)) + (PARTITION pstart VALUES LESS THAN (57600) ENGINE = InnoDB, + PARTITION p202403 VALUES LESS THAN (1711900800) ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN (1714492800) ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN (1717171200) ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN (1719763200) ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN (1722441600) ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN (1725120000) ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN (1727712000) ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_ts_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_ts_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +alter table my_ttl_ts_t1 cleanup expired data; +show create table my_ttl_ts_t1; +Table,Create Table +my_ttl_ts_t1,CREATE TABLE `my_ttl_ts_t1` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_ts_t1` (`b`) + PARTITION BY RANGE(UNIX_TIMESTAMP(`b`)) + (PARTITION pstart VALUES LESS THAN (57600) ENGINE = InnoDB, + PARTITION p202403 VALUES LESS THAN (1711900800) ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN (1714492800) ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN (1717171200) ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN (1719763200) ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN (1722441600) ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN (1725120000) ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN (1727712000) ENGINE = InnoDB, + PARTITION p202410 VALUES LESS THAN (1730390400) ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_ts_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +set time_zone='+08:00'; +create table rng_dt (dt datetime) +PARTITION BY RANGE COLUMNS(`dt`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB); +show create table rng_dt; +Table,Create Table +rng_dt,CREATE TABLE `rng_dt` ( + `dt` datetime DEFAULT NULL, + KEY `auto_shard_key_dt` USING BTREE (`dt`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE COLUMNS(`dt`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +create table rng_ts (ts timestamp default current_timestamp) +PARTITION BY RANGE(UNIX_TIMESTAMP(`ts`)) +(PARTITION pstart VALUES LESS THAN (UNIX_TIMESTAMP('1970-01-02 00:00:00')) ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN (UNIX_TIMESTAMP('2024-04-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN (UNIX_TIMESTAMP('2024-05-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN (UNIX_TIMESTAMP('2024-06-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN (UNIX_TIMESTAMP('2024-07-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN (UNIX_TIMESTAMP('2024-08-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN (UNIX_TIMESTAMP('2024-09-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN (UNIX_TIMESTAMP('2024-10-01 00:00:00')) ENGINE = InnoDB); +show create table rng_ts; +Table,Create Table +rng_ts,CREATE TABLE `rng_ts` ( + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + KEY `auto_shard_key_ts` USING BTREE (`ts`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY RANGE(UNIX_TIMESTAMP(`ts`)) +(PARTITION pstart VALUES LESS THAN (57600) ENGINE = InnoDB, + PARTITION p202403 VALUES LESS THAN (1711900800) ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN (1714492800) ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN (1717171200) ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN (1719763200) ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN (1722441600) ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN (1725120000) ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN (1727712000) ENGINE = InnoDB) +set time_zone='+08:00'; +select UNIX_TIMESTAMP('1970-01-02 00:00:00'), FROM_UNIXTIME(57600); +UNIX_TIMESTAMP('1970-01-02 00:00:00'),FROM_UNIXTIME(57600) +57600.0,1970-01-02 00:00:00.0 +select UNIX_TIMESTAMP('2024-04-01 00:00:00'), FROM_UNIXTIME(1711900800); +UNIX_TIMESTAMP('2024-04-01 00:00:00'),FROM_UNIXTIME(1711900800) +1711900800,2024-04-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-05-01 00:00:00'), FROM_UNIXTIME(1714492800); +UNIX_TIMESTAMP('2024-05-01 00:00:00'),FROM_UNIXTIME(1714492800) +1714492800,2024-05-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-06-01 00:00:00'), FROM_UNIXTIME(1717171200); +UNIX_TIMESTAMP('2024-06-01 00:00:00'),FROM_UNIXTIME(1717171200) +1717171200,2024-06-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-07-01 00:00:00'), FROM_UNIXTIME(1719763200); +UNIX_TIMESTAMP('2024-07-01 00:00:00'),FROM_UNIXTIME(1719763200) +1719763200,2024-07-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-08-01 00:00:00'), FROM_UNIXTIME(1722441600); +UNIX_TIMESTAMP('2024-08-01 00:00:00'),FROM_UNIXTIME(1722441600) +1722441600,2024-08-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-09-01 00:00:00'), FROM_UNIXTIME(1725120000); +UNIX_TIMESTAMP('2024-09-01 00:00:00'),FROM_UNIXTIME(1725120000) +1725120000,2024-09-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-10-01 00:00:00'), FROM_UNIXTIME(1727712000); +UNIX_TIMESTAMP('2024-10-01 00:00:00'),FROM_UNIXTIME(1727712000) +1727712000,2024-10-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-11-01 00:00:00'), FROM_UNIXTIME(1730390400); +UNIX_TIMESTAMP('2024-11-01 00:00:00'),FROM_UNIXTIME(1730390400) +1730390400,2024-11-01 00:00:00.0 +select UNIX_TIMESTAMP('2024-12-01 00:00:00'), FROM_UNIXTIME(1732982400); +UNIX_TIMESTAMP('2024-12-01 00:00:00'),FROM_UNIXTIME(1732982400) +1732982400,2024-12-01 00:00:00.0 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl_ts.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl_ts.test.yml new file mode 100644 index 000000000..2c1669113 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl_ts.test.yml @@ -0,0 +1,57 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +set time_zone='+08:00'; +create table my_ttl_ts_t1( +a int not null auto_increment, +b timestamp default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_ts_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE=5, ARCHIVE_TABLE_POST_ALLOCATE=3; +show create table my_ttl_ts_t1; +alter table my_ttl_ts_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 3 ARCHIVE_TABLE_POST_ALLOCATE = 3; +show create table my_ttl_ts_t1; +create table my_arc_ts_t1 like my_ttl_ts_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; +show create table my_ttl_ts_t1; +alter table my_ttl_ts_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +alter table my_ttl_ts_t1 cleanup expired data; +show create table my_ttl_ts_t1; + +set time_zone='+08:00'; +create table rng_dt (dt datetime) +PARTITION BY RANGE COLUMNS(`dt`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB); +show create table rng_dt; + +create table rng_ts (ts timestamp default current_timestamp) +PARTITION BY RANGE(UNIX_TIMESTAMP(`ts`)) +(PARTITION pstart VALUES LESS THAN (UNIX_TIMESTAMP('1970-01-02 00:00:00')) ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN (UNIX_TIMESTAMP('2024-04-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN (UNIX_TIMESTAMP('2024-05-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN (UNIX_TIMESTAMP('2024-06-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN (UNIX_TIMESTAMP('2024-07-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN (UNIX_TIMESTAMP('2024-08-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN (UNIX_TIMESTAMP('2024-09-01 00:00:00')) ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN (UNIX_TIMESTAMP('2024-10-01 00:00:00')) ENGINE = InnoDB); +show create table rng_ts; + +set time_zone='+08:00'; +select UNIX_TIMESTAMP('1970-01-02 00:00:00'), FROM_UNIXTIME(57600); +select UNIX_TIMESTAMP('2024-04-01 00:00:00'), FROM_UNIXTIME(1711900800); +select UNIX_TIMESTAMP('2024-05-01 00:00:00'), FROM_UNIXTIME(1714492800); +select UNIX_TIMESTAMP('2024-06-01 00:00:00'), FROM_UNIXTIME(1717171200); +select UNIX_TIMESTAMP('2024-07-01 00:00:00'), FROM_UNIXTIME(1719763200); +select UNIX_TIMESTAMP('2024-08-01 00:00:00'), FROM_UNIXTIME(1722441600); +select UNIX_TIMESTAMP('2024-09-01 00:00:00'), FROM_UNIXTIME(1725120000); +select UNIX_TIMESTAMP('2024-10-01 00:00:00'), FROM_UNIXTIME(1727712000); +select UNIX_TIMESTAMP('2024-11-01 00:00:00'), FROM_UNIXTIME(1730390400); +select UNIX_TIMESTAMP('2024-12-01 00:00:00'), FROM_UNIXTIME(1732982400); diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl_with_gsi.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl_with_gsi.test.yml new file mode 100644 index 000000000..45184ee69 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_ttl_with_gsi.test.yml @@ -0,0 +1,37 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table my_ttl_with_cci_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_with_cci_t1 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 3 ARCHIVE_TABLE_POST_ALLOCATE = 3; + + +create table my_arc_with_cci_t1 like my_ttl_with_cci_t1 ENGINE='COLUMNAR' ARCHIVE_MODE='TTL'; + + +CREATE TABLE `my_ttl_with_gsi_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED INDEX `gsi_b` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION `p202403` VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202409` VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 + TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TYPE = '', ARCHIVE_TABLE_SCHEMA = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2; + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_with_cci_ttl.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_with_cci_ttl.result new file mode 100644 index 000000000..97369b60e --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_with_cci_ttl.result @@ -0,0 +1,80 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +## error_msg: $# not the same #$ +CREATE TABLE `my_ttl_with_cci_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED INDEX `arctmp_my_arc_with_cci_t1` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_SCHEMA = 'ttldb3', ARCHIVE_TABLE_SCHEMA='unknown_db', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) PARTITION BY KEY(`a`) PARTITIONS 2; +not the same +CREATE TABLE `my_ttl_with_cci_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED INDEX `arctmp_my_arc_with_cci_t1` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) PARTITION BY KEY(`a`) PARTITIONS 2; +show create table my_ttl_with_cci_t1; +Table,Create Table +my_ttl_with_cci_t1,CREATE TABLE `my_ttl_with_cci_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_with_cci_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +show create table my_arc_with_cci_t1; +View,Create View,character_set_client,collation_connection +my_arc_with_cci_t1,CREATE VIEW `my_arc_with_cci_t1` AS select `my_ttl_with_cci_t1`.`a`,`my_ttl_with_cci_t1`.`b` from `test_create_with_1204881928`.`my_ttl_with_cci_t1` force index (`arctmp_my_arc_with_cci_t1`);,utf8,utf8_general_ci +alter table my_ttl_with_cci_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4; +alter table my_ttl_with_cci_t1 cleanup expired data; +show create table my_ttl_with_cci_t1; +Table,Create Table +my_ttl_with_cci_t1,CREATE TABLE `my_ttl_with_cci_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_with_cci_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB, + PARTITION p202410 VALUES LESS THAN ('2024-11-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +drop table my_ttl_with_cci_t1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_with_cci_ttl.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_with_cci_ttl.test.yml new file mode 100644 index 000000000..8e9d39f1a --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_create_with_cci_ttl.test.yml @@ -0,0 +1,47 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +## error_msg: $# not the same #$ +CREATE TABLE `my_ttl_with_cci_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED INDEX `arctmp_my_arc_with_cci_t1` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION `p202403` VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202409` VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_SCHEMA = 'ttldb3', ARCHIVE_TABLE_SCHEMA='unknown_db', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) PARTITION BY KEY(`a`) PARTITIONS 2; + + +CREATE TABLE `my_ttl_with_cci_t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT CURRENT_TIMESTAMP, +PRIMARY KEY (`a`), +CLUSTERED INDEX `arctmp_my_arc_with_cci_t1` (`b`) +PARTITION BY RANGE COLUMNS(`b`) +(PARTITION `pstart` VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, +PARTITION `p202403` VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202404` VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202405` VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202406` VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202407` VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202408` VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, +PARTITION `p202409` VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_with_cci_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) PARTITION BY KEY(`a`) PARTITIONS 2; +show create table my_ttl_with_cci_t1; +show create table my_arc_with_cci_t1; +alter table my_ttl_with_cci_t1 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4; +alter table my_ttl_with_cci_t1 cleanup expired data; +show create table my_ttl_with_cci_t1; +drop table my_ttl_with_cci_t1; + + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage.result new file mode 100644 index 000000000..1861363e6 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage.result @@ -0,0 +1,71 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create table my_ttl_t4( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `a` expire after 2 month timezone '+08:00'; +not supported +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 second timezone '+08:00'; +not supported +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 minute timezone '+08:00'; +not supported +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 hour timezone '+08:00'; +not supported +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 hour timezone '+08:00'; +not supported +## error_msg: $# ttl_expr is not defined #$ +alter table my_ttl_t4 modify ttl set ttl_job = CRON '* * */2 * * * * ?' TIMEZONE '+08:00'; +ttl_expr is not defined +## error_msg: $# invalid #$ +alter table my_ttl_t4 modify ttl set ttl_job = CRON '* * */2 * * * * ?' TIMEZONE '+08:00'; +invalid +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; +alter table my_ttl_t4 modify ttl set archive_table_pre_allocate = 3 archive_table_post_allocate = 3; +create table my_arc_t4 like my_ttl_t4 engine='columnar' archive_mode='ttl'; +show create table my_ttl_t4; +Table,Create Table +my_ttl_t4,CREATE TABLE `my_ttl_t4` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_t4` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202403 VALUES LESS THAN ('2024-04-01 00:00:00') ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 month TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_t4', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +desc my_arc_t4; +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +## error_msg: $# not allowed #$ +drop view my_arc_t4; +not allowed +## error_msg: $# not allowed #$ +alter table my_ttl_t4 drop index arctmp_my_arc_t4; +not allowed +alter table my_ttl_t4 add column c datetime default null; +## error_msg: $# change ttl column #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `c` expire after 2 month timezone '+08:00'; +change ttl column +## error_msg: $# archive table #$ +create table my_arc_t5 like my_ttl_t4 engine='columnar' archive_mode='ttl'; +archive table +drop table my_arc_t4; +drop table my_ttl_t4; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage.test.yml new file mode 100644 index 000000000..b281c1514 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage.test.yml @@ -0,0 +1,55 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table my_ttl_t4( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `a` expire after 2 month timezone '+08:00'; + +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 second timezone '+08:00'; + +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 minute timezone '+08:00'; + +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 hour timezone '+08:00'; + +## error_msg: $# not supported #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 hour timezone '+08:00'; + +## error_msg: $# ttl_expr is not defined #$ +alter table my_ttl_t4 modify ttl set ttl_job = CRON '* * */2 * * * * ?' TIMEZONE '+08:00'; + +## error_msg: $# invalid #$ +alter table my_ttl_t4 modify ttl set ttl_job = CRON '* * */2 * * * * ?' TIMEZONE '+08:00'; + +alter table my_ttl_t4 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; +alter table my_ttl_t4 modify ttl set archive_table_pre_allocate = 3 archive_table_post_allocate = 3; +create table my_arc_t4 like my_ttl_t4 engine='columnar' archive_mode='ttl'; +show create table my_ttl_t4; +desc my_arc_t4; + +## error_msg: $# not allowed #$ +drop view my_arc_t4; + +## error_msg: $# not allowed #$ +alter table my_ttl_t4 drop index arctmp_my_arc_t4; + +alter table my_ttl_t4 add column c datetime default null; + +## error_msg: $# change ttl column #$ +alter table my_ttl_t4 modify ttl set ttl_expr = `c` expire after 2 month timezone '+08:00'; + +## error_msg: $# archive table #$ +create table my_arc_t5 like my_ttl_t4 engine='columnar' archive_mode='ttl'; + +drop table my_arc_t4; +drop table my_ttl_t4; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage2.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage2.result new file mode 100644 index 000000000..f24d4fc21 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage2.result @@ -0,0 +1,47 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create database ttl_test_drds_db2 mode = 'drds'; +create table my_bro_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +broadcast; +create table my_sin_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +single; +create table ttl_test_drds_db2.my_dbpart_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +dbpartition by hash(a); +create table my_locpart_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +partition by key(a) partitions 8 +local partition by range(b) +STARTWITH '2021-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 1 +PRE ALLOCATE 6; +## error_msg: $# not allowed #$ +alter table my_locpart_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; +not allowed +## error_msg: $# not allowed #$ +alter table my_bro_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; +not allowed +## error_msg: $# not allowed #$ +alter table my_sin_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; +not allowed +## error_msg: $# not allowed #$ +alter table ttl_test_drds_db2.my_dbpart_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; +not allowed +drop database if exists ttl_test_drds_db2; +drop table my_locpart_t1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage2.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage2.test.yml new file mode 100644 index 000000000..6f0b1d149 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_invalid_usage2.test.yml @@ -0,0 +1,54 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create database ttl_test_drds_db2 mode = 'drds'; + +create table my_bro_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +broadcast; + +create table my_sin_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +single; + +create table ttl_test_drds_db2.my_dbpart_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +dbpartition by hash(a); + +create table my_locpart_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a,b) +) +partition by key(a) partitions 8 +local partition by range(b) +STARTWITH '2021-01-01' +INTERVAL 6 MONTH +EXPIRE AFTER 1 +PRE ALLOCATE 6; + +## error_msg: $# not allowed #$ +alter table my_locpart_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; + +## error_msg: $# not allowed #$ +alter table my_bro_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; + +## error_msg: $# not allowed #$ +alter table my_sin_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; + +## error_msg: $# not allowed #$ +alter table ttl_test_drds_db2.my_dbpart_t1 modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00'; + +drop database if exists ttl_test_drds_db2; +drop table my_locpart_t1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl.result new file mode 100644 index 000000000..3c3129ccc --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl.result @@ -0,0 +1,21 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create table my_ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00'; +alter table my_ttl_t2 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +show create table my_ttl_t2; +Table,Create Table +my_ttl_t2,CREATE TABLE `my_ttl_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_t2 modify ttl set TTL_EXPR = `b` EXPIRE AFTER 30 DAY TIMEZONE '+08:00' TTL_JOB = CRON '* * */4 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 6; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl.test.yml new file mode 100644 index 000000000..bc0c93a2c --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl.test.yml @@ -0,0 +1,22 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table my_ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00'; +alter table my_ttl_t2 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +show create table my_ttl_t2; +alter table my_ttl_t2 modify ttl set TTL_EXPR = `b` EXPIRE AFTER 30 DAY TIMEZONE '+08:00' TTL_JOB = CRON '* * */4 * * ?' TIMEZONE '+08:00' ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 6; + + + + + + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl2.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl2.result new file mode 100644 index 000000000..b80623398 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl2.result @@ -0,0 +1,95 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create table my_modify_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL = TTL_DEFINITION ( +TTL_ENABLE = 'OFF', +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', +TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', +ARCHIVE_TYPE = '' ARCHIVE_TABLE_SCHEMA = '', +ARCHIVE_TABLE_NAME = '', +ARCHIVE_TABLE_PRE_ALLOCATE = 3, +ARCHIVE_TABLE_POST_ALLOCATE = 4 +) +partition by key(a) partitions 2; +show create table my_modify_ttl_t1; +Table,Create Table +my_modify_ttl_t1,CREATE TABLE `my_modify_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 4 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_modify_ttl_t1 modify ttl +set +TTL_ENABLE = 'OFF', +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', +TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', +ARCHIVE_TYPE = '' ARCHIVE_TABLE_SCHEMA = '', +ARCHIVE_TABLE_NAME = '', +ARCHIVE_TABLE_PRE_ALLOCATE = 1, +ARCHIVE_TABLE_POST_ALLOCATE = 1; +show create table my_modify_ttl_t1; +Table,Create Table +my_modify_ttl_t1,CREATE TABLE `my_modify_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 1, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table my_modify_arc_t1 like my_modify_ttl_t1 engine='columnar' archive_mode='ttl'; +show create table my_modify_ttl_t1; +Table,Create Table +my_modify_ttl_t1,CREATE TABLE `my_modify_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_modify_arc_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_modify_arc_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 1, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_modify_ttl_t1 modify ttl set archive_table_pre_allocate = 2, archive_table_post_allocate = 1; +show create table my_modify_ttl_t1; +Table,Create Table +my_modify_ttl_t1,CREATE TABLE `my_modify_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_modify_arc_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_modify_arc_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_modify_ttl_t1 cleanup expired data; +show create table my_modify_ttl_t1; +Table,Create Table +my_modify_ttl_t1,CREATE TABLE `my_modify_ttl_t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_modify_arc_t1` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_modify_arc_t1', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +drop table my_modify_ttl_t1; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl2.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl2.test.yml new file mode 100644 index 000000000..211008be1 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_modify_ttl2.test.yml @@ -0,0 +1,48 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table my_modify_ttl_t1( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +TTL = TTL_DEFINITION ( +TTL_ENABLE = 'OFF', +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', +TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', +ARCHIVE_TYPE = '' ARCHIVE_TABLE_SCHEMA = '', +ARCHIVE_TABLE_NAME = '', +ARCHIVE_TABLE_PRE_ALLOCATE = 3, +ARCHIVE_TABLE_POST_ALLOCATE = 4 +) +partition by key(a) partitions 2; + +show create table my_modify_ttl_t1; + +alter table my_modify_ttl_t1 modify ttl +set +TTL_ENABLE = 'OFF', +TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', +TTL_JOB = CRON '*/1 * * * * ?' TIMEZONE '+08:00', +ARCHIVE_TYPE = '' ARCHIVE_TABLE_SCHEMA = '', +ARCHIVE_TABLE_NAME = '', +ARCHIVE_TABLE_PRE_ALLOCATE = 1, +ARCHIVE_TABLE_POST_ALLOCATE = 1 +; + +show create table my_modify_ttl_t1; + +create table my_modify_arc_t1 like my_modify_ttl_t1 engine='columnar' archive_mode='ttl'; +show create table my_modify_ttl_t1; + +alter table my_modify_ttl_t1 modify ttl set archive_table_pre_allocate = 2, archive_table_post_allocate = 1; +show create table my_modify_ttl_t1; + +alter table my_modify_ttl_t1 cleanup expired data; +show create table my_modify_ttl_t1; + +drop table my_modify_ttl_t1; + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_remove_ttl.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_remove_ttl.result new file mode 100644 index 000000000..8e0cf03c4 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_remove_ttl.result @@ -0,0 +1,60 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create table my_rm_ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_rm_ttl_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2; +show create table my_rm_ttl_t2; +Table,Create Table +my_rm_ttl_t2,CREATE TABLE `my_rm_ttl_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table my_rm_arc_t2 like my_rm_ttl_t2 engine='columnar' archive_mode='ttl'; +show create table my_rm_ttl_t2; +Table,Create Table +my_rm_ttl_t2,CREATE TABLE `my_rm_ttl_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_rm_arc_t2` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202404 VALUES LESS THAN ('2024-05-01 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_rm_arc_t2', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +## error_msg: $# has bound #$ +alter table my_rm_ttl_t2 remove ttl; +has bound +drop table my_rm_arc_t2; +show create table my_rm_ttl_t2; +Table,Create Table +my_rm_ttl_t2,CREATE TABLE `my_rm_ttl_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 2 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_rm_ttl_t2 remove ttl; +show create table my_rm_ttl_t2; +Table,Create Table +my_rm_ttl_t2,CREATE TABLE `my_rm_ttl_t2` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 +PARTITION BY KEY(`a`) +PARTITIONS 2 \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_remove_ttl.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_remove_ttl.test.yml new file mode 100644 index 000000000..f1d6337af --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_remove_ttl.test.yml @@ -0,0 +1,26 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table my_rm_ttl_t2( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_rm_ttl_t2 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00' archive_table_pre_allocate = 2 archive_table_post_allocate = 2; +show create table my_rm_ttl_t2; +create table my_rm_arc_t2 like my_rm_ttl_t2 engine='columnar' archive_mode='ttl'; +show create table my_rm_ttl_t2; +## error_msg: $# has bound #$ +alter table my_rm_ttl_t2 remove ttl; +drop table my_rm_arc_t2; +show create table my_rm_ttl_t2; +alter table my_rm_ttl_t2 remove ttl; +show create table my_rm_ttl_t2; + + + + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_alter_col.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_alter_col.result new file mode 100644 index 000000000..56827b4f6 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_alter_col.result @@ -0,0 +1,50 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create table my_ttl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_t3 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00'; +alter table my_ttl_t3 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +show create table my_ttl_t3; +Table,Create Table +my_ttl_t3,CREATE TABLE `my_ttl_t3` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00', TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00', ARCHIVE_TYPE = '', ARCHIVE_TABLE_NAME = '', ARCHIVE_TABLE_PRE_ALLOCATE = 4, ARCHIVE_TABLE_POST_ALLOCATE = 3 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +create table my_arc_t3 like my_ttl_t3 engine='columnar' archive_mode='ttl'; +desc my_arc_t3; +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +alter table my_ttl_t3 add column c datetime default null; +desc my_arc_t3; +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +c,datetime(0),YES,,NULL, +alter table my_ttl_t3 add column d datetime default null; +desc my_arc_t3; +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +c,datetime(0),YES,,NULL, +d,datetime(0),YES,,NULL, +alter table my_ttl_t3 drop column d; +desc my_arc_t3; +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +c,datetime(0),YES,,NULL, +alter table my_ttl_t3 change column c d datetime default null; +desc my_arc_t3; +Field,Type,Null,Key,Default,Extra +a,integer,YES,,NULL, +b,datetime(0),YES,,NULL, +d,datetime(0),YES,,NULL, \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_alter_col.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_alter_col.test.yml new file mode 100644 index 000000000..d96b292e7 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_alter_col.test.yml @@ -0,0 +1,24 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table my_ttl_t3( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_t3 modify ttl set TTL_ENABLE = 'OFF' TTL_EXPR = `b` EXPIRE AFTER 2 MONTH TIMEZONE '+08:00' TTL_JOB = CRON '* * */2 * * ?' TIMEZONE '+08:00'; +alter table my_ttl_t3 modify ttl set ARCHIVE_TABLE_PRE_ALLOCATE = 4 ARCHIVE_TABLE_POST_ALLOCATE = 3; +show create table my_ttl_t3; +create table my_arc_t3 like my_ttl_t3 engine='columnar' archive_mode='ttl'; +desc my_arc_t3; +alter table my_ttl_t3 add column c datetime default null; +desc my_arc_t3; +alter table my_ttl_t3 add column d datetime default null; +desc my_arc_t3; +alter table my_ttl_t3 drop column d; +desc my_arc_t3; +alter table my_ttl_t3 change column c d datetime default null; +desc my_arc_t3; diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_info_view.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_info_view.result new file mode 100644 index 000000000..cba6f92f3 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_info_view.result @@ -0,0 +1 @@ +toBeAdd \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_info_view.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_info_view.test.yml new file mode 100644 index 000000000..d7d912b5a --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_info_view.test.yml @@ -0,0 +1,2 @@ +## DISABLE_FAST_SQL_PARSER + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_unit.result b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_unit.result new file mode 100644 index 000000000..c3a1fe465 --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_unit.result @@ -0,0 +1,186 @@ +## DISABLE_FAST_SQL_PARSER +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; +create table my_ttl_tb_day( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +create table my_ttl_tb_month( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +create table my_ttl_tb_year( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; +alter table my_ttl_tb_day modify ttl set ttl_expr = `b` expire after 7 day timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1; +create table my_arc_tb_day like my_ttl_tb_day engine='columnar' archive_mode='ttl'; +show create table my_ttl_tb_day; +Table,Create Table +my_ttl_tb_day,CREATE TABLE `my_ttl_tb_day` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p20240626 VALUES LESS THAN ('2024-06-27 00:00:00') ENGINE = InnoDB, + PARTITION p20240627 VALUES LESS THAN ('2024-06-28 00:00:00') ENGINE = InnoDB, + PARTITION p20240628 VALUES LESS THAN ('2024-06-29 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 7 day TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 1, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_day modify ttl set archive_table_pre_allocate = 2; +alter table my_ttl_tb_day cleanup expired data; +show create table my_ttl_tb_day; +Table,Create Table +my_ttl_tb_day,CREATE TABLE `my_ttl_tb_day` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p20240626 VALUES LESS THAN ('2024-06-27 00:00:00') ENGINE = InnoDB, + PARTITION p20240627 VALUES LESS THAN ('2024-06-28 00:00:00') ENGINE = InnoDB, + PARTITION p20240628 VALUES LESS THAN ('2024-06-29 00:00:00') ENGINE = InnoDB, + PARTITION p20240629 VALUES LESS THAN ('2024-06-30 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 7 day TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_day modify ttl set archive_table_pre_allocate = 3; +alter table my_ttl_tb_day cleanup expired data; +show create table my_ttl_tb_day; +Table,Create Table +my_ttl_tb_day,CREATE TABLE `my_ttl_tb_day` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p20240626 VALUES LESS THAN ('2024-06-27 00:00:00') ENGINE = InnoDB, + PARTITION p20240627 VALUES LESS THAN ('2024-06-28 00:00:00') ENGINE = InnoDB, + PARTITION p20240628 VALUES LESS THAN ('2024-06-29 00:00:00') ENGINE = InnoDB, + PARTITION p20240629 VALUES LESS THAN ('2024-06-30 00:00:00') ENGINE = InnoDB, + PARTITION p20240630 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 7 day TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_month modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1; +create table my_arc_tb_day like my_ttl_tb_month engine='columnar' archive_mode='ttl'; +show create table my_ttl_tb_month; +Table,Create Table +my_ttl_tb_month,CREATE TABLE `my_ttl_tb_month` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 month TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 1, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_month modify ttl set archive_table_pre_allocate = 2; +alter table my_ttl_tb_month cleanup expired data; +show create table my_ttl_tb_month; +Table,Create Table +my_ttl_tb_month,CREATE TABLE `my_ttl_tb_month` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 month TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_month modify ttl set archive_table_pre_allocate = 3; +alter table my_ttl_tb_month cleanup expired data; +show create table my_ttl_tb_month; +Table,Create Table +my_ttl_tb_month,CREATE TABLE `my_ttl_tb_month` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p202405 VALUES LESS THAN ('2024-06-01 00:00:00') ENGINE = InnoDB, + PARTITION p202406 VALUES LESS THAN ('2024-07-01 00:00:00') ENGINE = InnoDB, + PARTITION p202407 VALUES LESS THAN ('2024-08-01 00:00:00') ENGINE = InnoDB, + PARTITION p202408 VALUES LESS THAN ('2024-09-01 00:00:00') ENGINE = InnoDB, + PARTITION p202409 VALUES LESS THAN ('2024-10-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 month TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_year modify ttl set ttl_expr = `b` expire after 2 year timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1; +create table my_arc_tb_day like my_ttl_tb_year engine='columnar' archive_mode='ttl'; +show create table my_ttl_tb_year; +Table,Create Table +my_ttl_tb_year,CREATE TABLE `my_ttl_tb_year` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p2023 VALUES LESS THAN ('2024-01-01 00:00:00') ENGINE = InnoDB, + PARTITION p2024 VALUES LESS THAN ('2025-01-01 00:00:00') ENGINE = InnoDB, + PARTITION p2025 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 year TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 1, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_year modify ttl set archive_table_pre_allocate = 2; +alter table my_ttl_tb_year cleanup expired data; +show create table my_ttl_tb_year; +Table,Create Table +my_ttl_tb_year,CREATE TABLE `my_ttl_tb_year` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p2023 VALUES LESS THAN ('2024-01-01 00:00:00') ENGINE = InnoDB, + PARTITION p2024 VALUES LESS THAN ('2025-01-01 00:00:00') ENGINE = InnoDB, + PARTITION p2025 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = InnoDB, + PARTITION p2026 VALUES LESS THAN ('2027-01-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 year TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 2, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +alter table my_ttl_tb_year modify ttl set archive_table_pre_allocate = 3; +alter table my_ttl_tb_year cleanup expired data; +show create table my_ttl_tb_year; +Table,Create Table +my_ttl_tb_year,CREATE TABLE `my_ttl_tb_year` ( + `a` int NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`a`), + CLUSTERED INDEX `arctmp_my_arc_tb_day` (`b`) + PARTITION BY RANGE COLUMNS(`b`) + (PARTITION pstart VALUES LESS THAN ('1970-01-02 00:00:00') ENGINE = InnoDB, + PARTITION p2023 VALUES LESS THAN ('2024-01-01 00:00:00') ENGINE = InnoDB, + PARTITION p2024 VALUES LESS THAN ('2025-01-01 00:00:00') ENGINE = InnoDB, + PARTITION p2025 VALUES LESS THAN ('2026-01-01 00:00:00') ENGINE = InnoDB, + PARTITION p2026 VALUES LESS THAN ('2027-01-01 00:00:00') ENGINE = InnoDB, + PARTITION p2027 VALUES LESS THAN ('2028-01-01 00:00:00') ENGINE = InnoDB) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 TTL = TTL_DEFINITION( TTL_ENABLE = 'OFF', TTL_EXPR = `b` EXPIRE AFTER 2 year TIMEZONE '+08:00', TTL_JOB = CRON '0 0 1 * * ? *' TIMEZONE '+08:00', ARCHIVE_TYPE = 'COLUMNAR', ARCHIVE_TABLE_NAME = 'my_arc_tb_day', ARCHIVE_TABLE_PRE_ALLOCATE = 3, ARCHIVE_TABLE_POST_ALLOCATE = 1 ) +PARTITION BY KEY(`a`) +PARTITIONS 2 +drop table my_ttl_tb_day; +drop table my_ttl_tb_month; +drop table my_ttl_tb_year; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_unit.test.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_unit.test.yml new file mode 100644 index 000000000..07b990d1e --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/test_ttl_unit.test.yml @@ -0,0 +1,65 @@ +## DISABLE_FAST_SQL_PARSER + +set TTL_DEBUG_USE_GSI_FOR_COLUMNAR_ARC_TBL = true; +set TTL_DEBUG_CURRENT_DATETIME='2024-06-27 00:00:00'; + +create table my_ttl_tb_day( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +create table my_ttl_tb_month( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +create table my_ttl_tb_year( +a int not null auto_increment, +b datetime default current_timestamp, +primary key(a) +) +partition by key(a) partitions 2; + +alter table my_ttl_tb_day modify ttl set ttl_expr = `b` expire after 7 day timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1; +create table my_arc_tb_day like my_ttl_tb_day engine='columnar' archive_mode='ttl'; +show create table my_ttl_tb_day; +alter table my_ttl_tb_day modify ttl set archive_table_pre_allocate = 2; +alter table my_ttl_tb_day cleanup expired data; +show create table my_ttl_tb_day; +alter table my_ttl_tb_day modify ttl set archive_table_pre_allocate = 3; +alter table my_ttl_tb_day cleanup expired data; +show create table my_ttl_tb_day; + +alter table my_ttl_tb_month modify ttl set ttl_expr = `b` expire after 2 month timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1; +create table my_arc_tb_day like my_ttl_tb_month engine='columnar' archive_mode='ttl'; +show create table my_ttl_tb_month; +alter table my_ttl_tb_month modify ttl set archive_table_pre_allocate = 2; +alter table my_ttl_tb_month cleanup expired data; +show create table my_ttl_tb_month; +alter table my_ttl_tb_month modify ttl set archive_table_pre_allocate = 3; +alter table my_ttl_tb_month cleanup expired data; +show create table my_ttl_tb_month; + +alter table my_ttl_tb_year modify ttl set ttl_expr = `b` expire after 2 year timezone '+08:00' archive_table_pre_allocate = 1 archive_table_post_allocate = 1; +create table my_arc_tb_day like my_ttl_tb_year engine='columnar' archive_mode='ttl'; +show create table my_ttl_tb_year; +alter table my_ttl_tb_year modify ttl set archive_table_pre_allocate = 2; +alter table my_ttl_tb_year cleanup expired data; +show create table my_ttl_tb_year; +alter table my_ttl_tb_year modify ttl set archive_table_pre_allocate = 3; +alter table my_ttl_tb_year cleanup expired data; +show create table my_ttl_tb_year; + +drop table my_ttl_tb_day; +drop table my_ttl_tb_month; +drop table my_ttl_tb_year; + + + + + + diff --git a/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/testcase.config.yml b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/testcase.config.yml new file mode 100644 index 000000000..d69e95feb --- /dev/null +++ b/polardbx-test/src/test/resources/partition/env80/TtlPartitionTableTest/testcase.config.yml @@ -0,0 +1,10 @@ +#test_create_ttl +#test_modify_ttl +#test_ttl_alter_col +#test_create_ttl_ts +#test_invalid_usage +#test_invalid_usage2 +#test_ttl_unit +#test_modify_ttl2 +#test_remove_ttl +#test_create_with_cci_ttl diff --git a/polardbx-test/src/test/resources/statistics/dump/coveringindex.yml b/polardbx-test/src/test/resources/statistics/dump/coveringindex.yml index 7f5b3e143..cedbd9201 100644 --- a/polardbx-test/src/test/resources/statistics/dump/coveringindex.yml +++ b/polardbx-test/src/test/resources/statistics/dump/coveringindex.yml @@ -22,8 +22,8 @@ LogicalView(tableNames=[[t_contacts_person]]) PhysicalProject HashAgg - PhysicalProject - MppExchange + MppExchange + PhysicalProject BKAJoin LogicalIndexScan(tableNames=[[MAIN_USER_ID_$ca99]]) LogicalView(tableNames=[[t_contacts_person]]) diff --git a/polardbx-test/src/test/resources/statistics/dump/pushDownFilter.yml b/polardbx-test/src/test/resources/statistics/dump/pushDownFilter.yml deleted file mode 100644 index 16491b7a3..000000000 --- a/polardbx-test/src/test/resources/statistics/dump/pushDownFilter.yml +++ /dev/null @@ -1,208 +0,0 @@ -- - SQL: | - SELECT 1 from shipping_container_detail sil ignore index(idx3) - LEFT JOIN shipment_header sr - ON sr.id=sil.shipmentId - LEFT - JOIN - (SELECT DISTINCT itemcode, - shipmentId , - warehouseCode, - itemListPrice, - id - FROM shipment_detail - WHERE shipmentId in('7545055') ) shl - ON shl.shipmentId=sil.shipmentId - AND shl.itemcode=sil.itemcode - AND shl.id=sil.shipmentDetailId - LEFT JOIN item_packing_detail i - ON i.itemCode =sil.itemCode - AND i.warehouseCode =sil.warehouseCode - AND i.companyCode =sil.companyCode - LEFT JOIN item it - ON it.code = sil.itemCode - AND it.companyCode =sr.companyCode - AND it.warehouseCode = sr.warehouseCode - LEFT JOIN shipping_container_header ignore index(idx1) shr - ON shr.warehouseCode = sil.warehouseCode - AND shr.code=sil.containerCode - INNER JOIN warehouse w - ON w.code = sr.warehouseCode - LEFT JOIN ttx_user tr - ON tr.code=sr.createdBy - LEFT JOIN - (SELECT referenceContId, - warehouseCode, - companyCode, - taskCode - FROM task_detail td - WHERE referenceId IN ('7545055') - AND warehouseCode='SH01' - GROUP BY referenceContId ) st - ON st.warehouseCode =sil.warehouseCode - AND st.companyCode =sil.companyCode - AND st.referenceContId =sil.containerId - WHERE sr.processType <> 'CANCEL' - AND sr.leadingSts>300 - AND i.unitcode ='CS' - AND sr.id IN ('7545055') - GROUP BY sr.warehouseCode,sr.companyCode ,shr.code,sil.itemCode,sil.batch,shl.itemListPrice - ORDER BY shr.Code, sil.itemCode - PLAN: | - PhysicalProject - MppExchange - MemSort - PhysicalProject - HashAgg - HashJoin - HashJoin - PhysicalProject - HashJoin - HashJoin - MppExchange - PhysicalProject - BKAJoin - BKAJoin - BKAJoin - BKAJoin - LogicalView(tableNames=[[shipping_container_detail]]) - LogicalView(tableNames=[[shipment_header]]) - LogicalView(tableNames=[[shipment_detail]]) - LogicalView(tableNames=[[item]]) - LogicalView(tableNames=[[item_packing_detail]]) - MppExchange - LogicalView(tableNames=[[shipping_container_header]]) - MppExchange - LogicalView(tableNames=[[warehouse]]) - MppExchange - LogicalView(tableNames=[[ttx_user]]) - MppExchange - PhysicalProject - HashAgg - MppExchange - LogicalView(tableNames=[[task_detail]]) - - CATALOG: | - set global AUTO_PARTITION_PARTITIONS = '32'; - CREATE DATABASE IF NOT EXISTS `jala_wms_prod` CHARACTER SET `utf8mb4` COLLATE `utf8mb4_general_ci` MODE = 'auto'; - use jala_wms_prod; - CREATE TABLEGROUP IF NOT EXISTS `newtg7643`; - CREATE TABLE IF NOT EXISTS `ttx_user` ( `code` varchar(50) NOT NULL, `name` varchar(50) NOT NULL, `orgCode` varchar(50) DEFAULT NULL, `department` varchar(50) DEFAULT NULL, `portal` varchar(16) DEFAULT NULL, `phone` varchar(20) DEFAULT '', `email` varchar(50) DEFAULT '', `portraitUrl` varchar(200) DEFAULT NULL, `taobaoUserNick` varchar(100) DEFAULT NULL, `type` varchar(50) DEFAULT 'USER', `lastLoginIn` datetime DEFAULT NULL, `wxAvatarUrl` varchar(255) DEFAULT '', `wxNickName` varchar(255) DEFAULT '', `wxSessionKey` varchar(255) DEFAULT '', `wxOpenid` varchar(255) DEFAULT '', `gAuthEnabled` int(11) DEFAULT '0', `gAuthSecretKey` char(64) DEFAULT NULL, `status` int(11) NOT NULL DEFAULT '1', `authType` varchar(50) DEFAULT NULL, `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `createdBy` varchar(255) DEFAULT NULL, `lastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `lastUpdatedBy` varchar(255) DEFAULT NULL, `version` int(11) DEFAULT '0', `userDef1` varchar(50) DEFAULT NULL, `userDef2` varchar(50) DEFAULT NULL, `userDef3` varchar(50) DEFAULT NULL, `userDef4` varchar(50) DEFAULT NULL, `userDef5` varchar(50) DEFAULT NULL, `userDef6` varchar(50) DEFAULT NULL, `userDef7` varchar(50) DEFAULT NULL, `userDef8` varchar(50) DEFAULT NULL, `isDeveloper` int(1) DEFAULT '0', `inited` int(1) DEFAULT '0', PRIMARY KEY USING BTREE (`code`) ) SINGLE ENGINE = InnoDB DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC; - CREATE TABLE IF NOT EXISTS `task_detail` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `taskId` bigint(20) DEFAULT NULL, `taskCode` varchar(50) NOT NULL, `taskType` varchar(50) DEFAULT NULL, `warehouseCode` varchar(50) DEFAULT NULL, `companyCode` varchar(50) DEFAULT NULL, `itemCode` varchar(50) DEFAULT NULL, `itemName` varchar(500) DEFAULT NULL, `totalQty` bigint(20) DEFAULT '0', `fromQty` bigint(20) DEFAULT '0', `toQty` bigint(20) DEFAULT '0', `fromLoc` varchar(50) DEFAULT NULL, `toLoc` varchar(50) DEFAULT NULL, `fromLPN` varchar(50) DEFAULT NULL, `toLPN` varchar(50) DEFAULT NULL, `fromZone` varchar(50) DEFAULT NULL, `toZone` varchar(50) DEFAULT NULL, `currentLoc` varchar(50) DEFAULT NULL, `currentLPN` varchar(50) DEFAULT NULL, `attributeId` bigint(20) DEFAULT NULL, `status` int(11) DEFAULT NULL, `referenceCode` varchar(50) DEFAULT NULL, `referenceId` bigint(20) DEFAULT NULL, `referenceLineId` bigint(20) DEFAULT NULL, `referenceContCode` varchar(50) DEFAULT NULL, `referenceContId` bigint(20) DEFAULT NULL, `referenceOrderType` varchar(50) DEFAULT NULL, `assignedUser` varchar(50) DEFAULT NULL, `internalTaskType` varchar(50) DEFAULT NULL, `attribute1` varchar(50) DEFAULT NULL, `attribute2` varchar(50) DEFAULT NULL, `attribute3` varchar(50) DEFAULT NULL, `attribute4` varchar(50) DEFAULT NULL, `attribute5` varchar(50) DEFAULT NULL, `attribute6` varchar(50) DEFAULT NULL, `attribute7` varchar(50) DEFAULT NULL, `attribute8` varchar(50) DEFAULT NULL, `batch` varchar(50) DEFAULT NULL, `lot` varchar(50) DEFAULT NULL, `manufactureDate` date DEFAULT NULL, `expirationDate` date DEFAULT NULL, `agingDate` date DEFAULT NULL, `inventorySts` varchar(50) DEFAULT NULL, `shelfLifeSts` varchar(50) DEFAULT NULL, `packingCode` varchar(50) DEFAULT NULL, `convertedQty` bigint(20) DEFAULT '0', `convertedQtyUm` varchar(50) DEFAULT NULL, `unitQty` bigint(20) DEFAULT '0', `waveId` bigint(20) DEFAULT NULL, `referenceReqId` bigint(20) DEFAULT NULL, `fromInventoryId` bigint(20) DEFAULT NULL, `toInventoryId` bigint(20) DEFAULT NULL, `relayBy` varchar(50) DEFAULT NULL, `relayAt` datetime DEFAULT NULL, `confirmedBy` varchar(50) DEFAULT NULL, `confirmedAt` datetime DEFAULT NULL, `pickingCartCode` varchar(50) DEFAULT NULL, `transContCode` varchar(50) DEFAULT NULL, `pickingCartPos` varchar(50) DEFAULT NULL, `pickDropLoc` varchar(50) DEFAULT NULL, `rebinShortQty` bigint(20) DEFAULT '0', `groupNum` int(11) DEFAULT NULL, `groupIndex` int(11) DEFAULT NULL, `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `createdBy` varchar(50) DEFAULT NULL, `lastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `lastUpdatedBy` varchar(50) DEFAULT NULL, `version` int(11) DEFAULT '0', `userDef1` varchar(50) DEFAULT NULL, `userDef2` varchar(50) DEFAULT NULL, `userDef3` varchar(50) DEFAULT NULL, `userDef4` varchar(50) DEFAULT NULL, `userDef5` varchar(50) DEFAULT NULL, `userDef6` varchar(50) DEFAULT NULL, `userDef7` varchar(50) DEFAULT NULL, `userDef8` varchar(50) DEFAULT NULL, `processStamp` varchar(50) DEFAULT NULL, `csQty` bigint(20) DEFAULT '0', `plQty` bigint(20) DEFAULT '0', `qtyRatio` int(11) DEFAULT '0', `umQtyRatio` int(11) DEFAULT '0', `unitQtyRatio` int(11) DEFAULT '0', `inTransitLocked` int(11) DEFAULT '0', `finishRebatch` int(11) DEFAULT '0', `coverReson` varchar(50) DEFAULT NULL, PRIMARY KEY USING BTREE (`id`), KEY `idx11` USING BTREE (`currentLoc`, `status`, `warehouseCode`), KEY `idx1` USING BTREE (`taskId`), KEY `idx2` USING BTREE (`taskCode`, `warehouseCode`, `internalTaskType`), KEY `idx3` USING BTREE (`waveId`), KEY `idx4` USING BTREE (`referenceId`, `internalTaskType`, `itemCode`), KEY `idx5` USING BTREE (`referenceContId`, `internalTaskType`, `warehouseCode`), KEY `idx6` USING BTREE (`referenceCode`, `warehouseCode`, `internalTaskType`), KEY `idx7` USING BTREE (`fromInventoryId`, `status`), KEY `idx8` USING BTREE (`confirmedAt`), KEY `idx9` USING BTREE (`pickingCartCode`, `status`, `warehouseCode`), KEY `idx_referenceLineId` (`referenceLineId`), KEY `auto_shard_key_warehousecode` USING BTREE (`warehouseCode`) ) ENGINE = InnoDB AUTO_INCREMENT = 17666343 DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC PARTITION BY LIST COLUMNS (`warehouseCode`) SUBPARTITION BY KEY (`id`) ( PARTITION `p1` VALUES IN ('021DC1') ( SUBPARTITION `p1sp1`, SUBPARTITION `p1sp2`, SUBPARTITION `p1sp3`, SUBPARTITION `p1sp4` ), PARTITION `p2` VALUES IN ('022DC') ( SUBPARTITION `p2sp1`, SUBPARTITION `p2sp2`, SUBPARTITION `p2sp3`, SUBPARTITION `p2sp4` ), PARTITION `p3` VALUES IN ('027DC') ( SUBPARTITION `p3sp1`, SUBPARTITION `p3sp2`, SUBPARTITION `p3sp3`, SUBPARTITION `p3sp4` ), PARTITION `p4` VALUES IN ('028DC') ( SUBPARTITION `p4sp1`, SUBPARTITION `p4sp2`, SUBPARTITION `p4sp3`, SUBPARTITION `p4sp4` ), PARTITION `p5` VALUES IN ('573DC') ( SUBPARTITION `p5sp1`, SUBPARTITION `p5sp2`, SUBPARTITION `p5sp3`, SUBPARTITION `p5sp4` ), PARTITION `p6` VALUES IN ('763DC') ( SUBPARTITION `p6sp1`, SUBPARTITION `p6sp2`, SUBPARTITION `p6sp3`, SUBPARTITION `p6sp4` ), PARTITION `p7` VALUES IN ('763DCA') ( SUBPARTITION `p7sp1`, SUBPARTITION `p7sp2`, SUBPARTITION `p7sp3`, SUBPARTITION `p7sp4` ), PARTITION `p8` VALUES IN ('SH01') ( SUBPARTITION `p8sp1`, SUBPARTITION `p8sp2`, SUBPARTITION `p8sp3`, SUBPARTITION `p8sp4` ), PARTITION `p9` VALUES IN ('SH02') ( SUBPARTITION `p9sp1`, SUBPARTITION `p9sp2`, SUBPARTITION `p9sp3`, SUBPARTITION `p9sp4` ), PARTITION `p10` VALUES IN ('SH03') ( SUBPARTITION `p10sp1`, SUBPARTITION `p10sp2`, SUBPARTITION `p10sp3`, SUBPARTITION `p10sp4` ), PARTITION `p11` VALUES IN ('TEST01') ( SUBPARTITION `p11sp1`, SUBPARTITION `p11sp2`, SUBPARTITION `p11sp3`, SUBPARTITION `p11sp4` ), PARTITION `p12` VALUES IN (DEFAULT) ( SUBPARTITION `p12sp1`, SUBPARTITION `p12sp2`, SUBPARTITION `p12sp3`, SUBPARTITION `p12sp4` ) ); - CREATE TABLE IF NOT EXISTS `shipment_detail` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `shipmentId` bigint(20) NOT NULL, `warehouseCode` varchar(50) NOT NULL, `companyCode` varchar(50) NOT NULL, `shipmentCode` varchar(50) NOT NULL, `erpOrderCode` varchar(50) DEFAULT NULL, `erpOrderId` bigint(20) DEFAULT NULL, `erpOrderLineNum` varchar(50) DEFAULT NULL, `sourceOrderCode` varchar(1500) DEFAULT NULL, `itemCode` varchar(50) NOT NULL, `itemName` varchar(500) DEFAULT NULL, `shipQty` bigint(20) DEFAULT '0', `requestQty` bigint(20) DEFAULT '0', `allocationRule` varchar(50) DEFAULT NULL, `replenishmentRule` varchar(50) DEFAULT NULL, `pickLocs` varchar(100) DEFAULT NULL, `attribute1` varchar(50) DEFAULT NULL, `attribute2` varchar(50) DEFAULT NULL, `attribute3` varchar(50) DEFAULT NULL, `attribute4` varchar(50) DEFAULT NULL, `attribute5` varchar(50) DEFAULT NULL, `attribute6` varchar(50) DEFAULT NULL, `attribute7` varchar(50) DEFAULT NULL, `attribute8` varchar(50) DEFAULT NULL, `batch` varchar(50) DEFAULT NULL, `lot` varchar(50) DEFAULT NULL, `manufactureDate` date DEFAULT NULL, `expirationDate` date DEFAULT NULL, `agingDate` date DEFAULT NULL, `inventorySts` varchar(50) DEFAULT NULL, `shelfLifeSts` varchar(50) DEFAULT NULL, `packingCode` varchar(50) DEFAULT NULL, `dockLoc` varchar(50) DEFAULT NULL, `packingClass` varchar(50) DEFAULT NULL, `status` int(11) DEFAULT NULL, `waveId` bigint(20) DEFAULT NULL, `totalWeight` decimal(15, 4) DEFAULT NULL, `totalVolume` decimal(15, 4) DEFAULT NULL, `backOrderLineNum` bigint(20) DEFAULT NULL, `itemListPrice` decimal(15, 4) DEFAULT NULL, `itemNetPrice` decimal(15, 4) DEFAULT NULL, `originalShipmentCode` varchar(100) DEFAULT NULL, `hostItemCode` varchar(100) DEFAULT NULL, `uploadRequired` varchar(100) DEFAULT NULL, `pickLPN` varchar(100) DEFAULT NULL, `pickParentLPN` varchar(100) DEFAULT NULL, `bomItemCode` varchar(50) DEFAULT NULL, `isVirtualBom` int(11) DEFAULT '0', `samplesize` double DEFAULT NULL, `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `createdBy` varchar(50) DEFAULT NULL, `lastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `lastUpdatedBy` varchar(50) DEFAULT NULL, `version` int(11) DEFAULT '0', `userDef1` varchar(50) DEFAULT NULL, `userDef2` varchar(50) DEFAULT NULL, `userDef3` varchar(50) DEFAULT NULL, `userDef4` varchar(50) DEFAULT NULL, `userDef5` varchar(50) DEFAULT NULL, `userDef6` varchar(50) DEFAULT NULL, `userDef7` varchar(50) DEFAULT NULL, `userDef8` varchar(50) DEFAULT NULL, `processStamp` varchar(50) DEFAULT NULL, `csQty` bigint(20) DEFAULT '0', `plQty` bigint(20) DEFAULT '0', `qtyRatio` int(11) DEFAULT '0', `umQtyRatio` int(11) DEFAULT '0', `unitQtyRatio` int(11) DEFAULT '0', `isGift` int(11) DEFAULT '0', `processType` varchar(50) DEFAULT NULL, `quantityUm` varchar(50) DEFAULT NULL, `unitQty` bigint(20) DEFAULT '0', `quantity` bigint(20) DEFAULT '0', `requestCancelQty` bigint(20) DEFAULT '0', `canceledQty` bigint(20) DEFAULT '0', `originalOrderLineNum` bigint(20) DEFAULT '0', `shortAllocQty` bigint(20) DEFAULT '0', `shortPickQty` bigint(20) DEFAULT '0', `shortPackingQty` bigint(20) DEFAULT '0', `warehouseTransferDtlId` bigint(20) DEFAULT '0', `maxBatches` int(11) NOT NULL DEFAULT '0', `aItem` int(11) DEFAULT '0', `referenceCrossDockCode` varchar(50) DEFAULT NULL, `returnQty` int(11) DEFAULT NULL, `movereason` varchar(50) DEFAULT NULL, `manufacturer` varchar(50) DEFAULT NULL, `purchaseOrderCode` varchar(50) DEFAULT NULL, `splitQty` bigint(20) DEFAULT '0', `deletedimension` int(11) DEFAULT '0', `pickupquantity` int(11) DEFAULT NULL, `fromwarehouseCode` varchar(50) DEFAULT NULL, PRIMARY KEY USING BTREE (`id`), KEY `idx1` USING BTREE (`shipmentId`), KEY `idx2` USING BTREE (`shipmentCode`, `warehouseCode`), KEY `idx5` (`waveId`, `warehouseCode`), KEY `idx3` (`waveId`), KEY `idx4` (`warehouseTransferDtlId`), KEY `auto_shard_key_warehousecode` USING BTREE (`warehouseCode`) ) ENGINE = InnoDB AUTO_INCREMENT = 21374797 DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC PARTITION BY LIST COLUMNS (`warehouseCode`) SUBPARTITION BY KEY (`shipmentId`) ( PARTITION `p1` VALUES IN ('021DC1') ( SUBPARTITION `p1sp1`, SUBPARTITION `p1sp2`, SUBPARTITION `p1sp3`, SUBPARTITION `p1sp4` ), PARTITION `p2` VALUES IN ('022DC') ( SUBPARTITION `p2sp1`, SUBPARTITION `p2sp2`, SUBPARTITION `p2sp3`, SUBPARTITION `p2sp4` ), PARTITION `p3` VALUES IN ('027DC') ( SUBPARTITION `p3sp1`, SUBPARTITION `p3sp2`, SUBPARTITION `p3sp3`, SUBPARTITION `p3sp4` ), PARTITION `p4` VALUES IN ('028DC') ( SUBPARTITION `p4sp1`, SUBPARTITION `p4sp2`, SUBPARTITION `p4sp3`, SUBPARTITION `p4sp4` ), PARTITION `p5` VALUES IN ('573DC') ( SUBPARTITION `p5sp1`, SUBPARTITION `p5sp2`, SUBPARTITION `p5sp3`, SUBPARTITION `p5sp4` ), PARTITION `p6` VALUES IN ('763DC') ( SUBPARTITION `p6sp1`, SUBPARTITION `p6sp2`, SUBPARTITION `p6sp3`, SUBPARTITION `p6sp4` ), PARTITION `p7` VALUES IN ('763DCA') ( SUBPARTITION `p7sp1`, SUBPARTITION `p7sp2`, SUBPARTITION `p7sp3`, SUBPARTITION `p7sp4` ), PARTITION `p8` VALUES IN ('SH01') ( SUBPARTITION `p8sp1`, SUBPARTITION `p8sp2`, SUBPARTITION `p8sp3`, SUBPARTITION `p8sp4` ), PARTITION `p9` VALUES IN ('SH02') ( SUBPARTITION `p9sp1`, SUBPARTITION `p9sp2`, SUBPARTITION `p9sp3`, SUBPARTITION `p9sp4` ), PARTITION `p10` VALUES IN ('SH03') ( SUBPARTITION `p10sp1`, SUBPARTITION `p10sp2`, SUBPARTITION `p10sp3`, SUBPARTITION `p10sp4` ), PARTITION `p11` VALUES IN ('TEST01') ( SUBPARTITION `p11sp1`, SUBPARTITION `p11sp2`, SUBPARTITION `p11sp3`, SUBPARTITION `p11sp4` ), PARTITION `p12` VALUES IN (DEFAULT) ( SUBPARTITION `p12sp1`, SUBPARTITION `p12sp2`, SUBPARTITION `p12sp3`, SUBPARTITION `p12sp4` ) ); - CREATE TABLE IF NOT EXISTS `item` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `code` varchar(50) NOT NULL, `companyCode` varchar(50) NOT NULL, `warehouseCode` varchar(50) DEFAULT NULL, `name` varchar(500) DEFAULT NULL, `nameEn` varchar(500) DEFAULT NULL, `parentCode` varchar(50) DEFAULT NULL, `packingClass` varchar(50) DEFAULT NULL, `movementClass` varchar(50) DEFAULT NULL, `abcClass` varchar(50) DEFAULT NULL, `yearsToExpire` int(11) DEFAULT '0', `monthsToExpire` int(11) DEFAULT '0', `daysToExpire` int(11) DEFAULT '0', `locatingRule` varchar(50) DEFAULT NULL, `allocationRule` varchar(50) DEFAULT NULL, `replenishmentRule` varchar(50) DEFAULT NULL, `emptyLocRule` varchar(50) DEFAULT NULL, `itemCategory1` varchar(50) DEFAULT NULL, `itemCategory2` varchar(50) DEFAULT NULL, `itemCategory3` varchar(50) DEFAULT NULL, `itemCategory4` varchar(50) DEFAULT NULL, `class01` varchar(50) DEFAULT NULL, `class02` varchar(50) DEFAULT NULL, `class03` varchar(50) DEFAULT NULL, `attributeTemplateCode` varchar(50) DEFAULT NULL, `trackSerialNum` int(11) DEFAULT '0', `autoGenSerialNum` int(11) DEFAULT '0', `autoGenSerialNumFormat` varchar(50) DEFAULT NULL, `snTemplateCode` varchar(50) DEFAULT NULL, `brand` varchar(50) DEFAULT NULL, `division` varchar(50) DEFAULT NULL, `department` varchar(50) DEFAULT NULL, `itemSize` varchar(50) DEFAULT NULL, `itemColor` varchar(50) DEFAULT NULL, `itemStyle` varchar(50) DEFAULT NULL, `costPrice` decimal(15, 4) DEFAULT NULL, `listPrice` decimal(15, 4) DEFAULT NULL, `netPrice` decimal(15, 4) DEFAULT NULL, `placeOfOrigin` varchar(50) DEFAULT NULL, `itemAttributeTemplateCode` varchar(50) DEFAULT NULL, `itemAttribute1` varchar(50) DEFAULT NULL, `itemAttribute2` varchar(50) DEFAULT NULL, `itemAttribute3` varchar(50) DEFAULT NULL, `itemAttribute4` varchar(50) DEFAULT NULL, `itemAttribute5` varchar(50) DEFAULT NULL, `itemAttribute6` varchar(50) DEFAULT NULL, `itemAttribute7` varchar(50) DEFAULT NULL, `itemAttribute8` varchar(50) DEFAULT NULL, `maintainSts` int(11) DEFAULT '0', `trackBatch` int(11) DEFAULT '0', `trackLot` int(11) DEFAULT NULL, `trackManufactureDate` int(11) DEFAULT NULL, `trackExpirationDate` int(11) DEFAULT NULL, `trackAgingDate` int(11) DEFAULT NULL, `warnShelfLife` int(11) DEFAULT '0', `goodShelfLife` int(11) DEFAULT '0', `unitQty` bigint(20) DEFAULT '0', `unitDesc` varchar(50) DEFAULT '?', `unitLength` decimal(15, 4) DEFAULT '0.0000', `unitWidth` decimal(15, 4) DEFAULT '0.0000', `unitHeight` decimal(15, 4) DEFAULT '0.0000', `unitWeight` decimal(15, 4) DEFAULT '0.0000', `unitVolume` decimal(15, 4) DEFAULT '0.0000', `eaAsLooseInbound` int(11) DEFAULT '1', `eaAsLooseOutbound` int(11) DEFAULT '1', `csQty` bigint(20) DEFAULT '0', `csDesc` varchar(50) DEFAULT '?', `csLength` decimal(15, 4) DEFAULT '0.0000', `csWidth` decimal(15, 4) DEFAULT '0.0000', `csHeight` decimal(15, 4) DEFAULT '0.0000', `csWeight` decimal(15, 4) DEFAULT '0.0000', `csVolume` decimal(15, 4) DEFAULT '0.0000', `csAsLooseInbound` int(11) DEFAULT '1', `csAsLooseOutbound` int(11) DEFAULT '1', `plQty` bigint(20) DEFAULT '0', `plDesc` varchar(50) DEFAULT '?', `plLength` decimal(15, 4) DEFAULT '0.0000', `plWidth` decimal(15, 4) DEFAULT '0.0000', `plHeight` decimal(15, 4) DEFAULT '0.0000', `plWeight` decimal(15, 4) DEFAULT '0.0000', `plVolume` decimal(15, 4) DEFAULT '0.0000', `tiHi` varchar(50) DEFAULT NULL, `status` int(11) DEFAULT '1', `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `createdBy` varchar(50) DEFAULT NULL, `lastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `lastUpdatedBy` varchar(50) DEFAULT NULL, `version` int(11) DEFAULT '0', `userDef1` varchar(500) DEFAULT NULL, `userDef2` varchar(50) DEFAULT NULL, `userDef3` varchar(50) DEFAULT NULL, `userDef4` varchar(50) DEFAULT NULL, `userDef5` varchar(50) DEFAULT NULL, `userDef6` varchar(50) DEFAULT NULL, `userDef7` varchar(50) DEFAULT NULL, `userDef8` varchar(50) DEFAULT NULL, `sourceErp` varchar(50) DEFAULT NULL, `turnOverRate` decimal(15, 4) DEFAULT '0.0000', `isGift` int(11) DEFAULT '0', `minShelfLife` int(11) DEFAULT '0', `minShelfLifeSts` varchar(50) DEFAULT NULL, `warnShelfLifeSts` varchar(50) DEFAULT NULL, `overShelfLifeSts` varchar(50) DEFAULT NULL, `inShelfLifeSts` varchar(50) DEFAULT NULL, `minShelfLifeDays` int(11) DEFAULT NULL, `expiringDays` int(11) DEFAULT NULL, `lastCycleCountDate` datetime DEFAULT NULL, `imageId` varchar(50) DEFAULT NULL, `thumbImageId` varchar(50) DEFAULT NULL, `minOrderQty` bigint(20) DEFAULT '0', `inboundFrozenDays` int(11) DEFAULT '0', `preImportSerialNum` int(11) DEFAULT '0', `serialNumType` int(11) DEFAULT '1', `allowRotate` int(11) DEFAULT '0', `allowDown` int(11) DEFAULT '0', `collectCsQty` int(11) DEFAULT '0', `collectDatetime` datetime DEFAULT NULL, `collectedBy` varchar(50) DEFAULT NULL, `qtyRatio` int(11) DEFAULT '0', `trackInv` int(11) DEFAULT '1', `overlapRate` decimal(15, 4) DEFAULT '0.0000', `tempLevel` varchar(50) DEFAULT NULL, `manufacturer` varchar(50) DEFAULT NULL, `imported` int(11) DEFAULT '0', `dosageForms` varchar(50) DEFAULT NULL, `interOrExter` varchar(50) DEFAULT NULL, `approvalNumber` varchar(50) DEFAULT NULL, `specialDrugs` int(11) DEFAULT '0', `specialManagementDrugs` int(11) DEFAULT '0', `iqcMethod` int(11) DEFAULT NULL, `acceptanceMethod` int(11) DEFAULT NULL, `checkingMethod` int(11) DEFAULT NULL, `maintained` int(11) DEFAULT '0', `maintainPeriod` int(11) DEFAULT '0', `productLine` varchar(50) DEFAULT NULL, `pos` varchar(50) DEFAULT NULL, `threeLevelClass` varchar(50) DEFAULT NULL, `gs1Code` varchar(50) DEFAULT NULL, `auditCode` varchar(50) DEFAULT NULL, `collectDrugTest` int(11) DEFAULT '0', `needAudited` int(11) DEFAULT '0', `cycleCount` int(11) DEFAULT '0', `countPeriod` int(11) DEFAULT '0', `needIqc` int(11) DEFAULT '0', `iqcRuleCode` varchar(50) DEFAULT NULL, `trackLPN` int(11) DEFAULT '1', `manufacturerdeletion` int(11) DEFAULT '0', `purchasestoragelocation` varchar(50) DEFAULT NULL, `productionstoragelocation` varchar(50) DEFAULT NULL, `snmanagement` varchar(11) DEFAULT NULL, `productioniqc` int(11) DEFAULT '0', `purchaseiqc` int(11) DEFAULT '0', `unitName` varchar(50) DEFAULT NULL, `unitName1` varchar(50) DEFAULT NULL, `unitName2` varchar(50) DEFAULT NULL, `unitName3` varchar(50) DEFAULT NULL, `text` varchar(255) DEFAULT NULL, `groupleveldeletion` varchar(50) DEFAULT NULL, `grossweight` double DEFAULT NULL, `snmangement` varchar(50) DEFAULT NULL, `storageTempLevel` varchar(50) DEFAULT NULL, `itemGroup` varchar(50) DEFAULT NULL, `packageStyle` varchar(50) DEFAULT NULL, `itemExpirationDate` date DEFAULT NULL, PRIMARY KEY USING BTREE (`id`), UNIQUE KEY `idx1` USING BTREE (`code`, `companyCode`, `warehouseCode`), KEY `idx2` USING BTREE (`collectDatetime`) ) BROADCAST ENGINE = InnoDB AUTO_INCREMENT = 2457346 DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC; - CREATE TABLE IF NOT EXISTS `shipping_container_header` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `code` varchar(50) NOT NULL, `warehouseCode` varchar(50) NOT NULL, `containerType` varchar(50) DEFAULT NULL, `shipContMasterCode` varchar(50) DEFAULT NULL, `status` int(11) DEFAULT '300', `parent` int(11) DEFAULT '0', `totalWeight` decimal(15, 4) DEFAULT '0.0000', `totalVolume` decimal(15, 4) DEFAULT '0.0000', `length` decimal(15, 4) DEFAULT '0.0000', `width` decimal(15, 4) DEFAULT '0.0000', `height` decimal(15, 4) DEFAULT '0.0000', `totalValue` decimal(15, 4) DEFAULT '0.0000', `zxQty` int(15) DEFAULT NULL, `hxQty` int(15) DEFAULT NULL, `totalconQty` int(15) DEFAULT NULL, `shipmentId` bigint(20) DEFAULT '0', `companyCode` varchar(50) DEFAULT NULL, `qtyRatio` int(11) DEFAULT '0', `totalQty` bigint(20) DEFAULT '0', `waybillCode` varchar(50) DEFAULT NULL, `groupNum` int(11) DEFAULT '0', `groupIndex` int(11) DEFAULT '0', `waveId` bigint(20) DEFAULT '0', `countIndex` int(11) DEFAULT '0', `countTotal` int(11) DEFAULT '1', `taskCreated` int(11) DEFAULT '0', `shipmentCode` varchar(50) DEFAULT NULL, `transContCode` varchar(50) DEFAULT NULL, `oqcBench` varchar(50) DEFAULT NULL, `oqcBy` varchar(50) DEFAULT NULL, `oqcStartAt` datetime DEFAULT NULL, `oqcEndAt` datetime DEFAULT NULL, `loadId` bigint(20) DEFAULT '0', `cageId` bigint(20) DEFAULT '0', `cageCode` varchar(50) DEFAULT NULL, `stagedAt` datetime DEFAULT NULL, `stagedBy` varchar(50) DEFAULT NULL, `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `createdBy` varchar(50) DEFAULT NULL, `lastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `lastUpdatedBy` varchar(50) DEFAULT NULL, `version` int(11) DEFAULT '0', `userDef1` varchar(50) DEFAULT NULL, `userDef2` varchar(50) DEFAULT NULL, `userDef3` varchar(50) DEFAULT NULL, `userDef4` varchar(50) DEFAULT NULL, `userDef5` varchar(50) DEFAULT NULL, `userDef6` varchar(50) DEFAULT NULL, `userDef7` varchar(50) DEFAULT NULL, `userDef8` varchar(50) DEFAULT NULL, `processStamp` varchar(50) DEFAULT NULL, `uploadBatch` varchar(200) DEFAULT NULL, `carrierCode` varchar(50) DEFAULT NULL, `scaledBy` varchar(50) DEFAULT NULL, `scaledAt` datetime DEFAULT NULL, `storeCode` varchar(50) DEFAULT NULL, `picUrls` varchar(50) DEFAULT NULL, `pidIds` varchar(255) DEFAULT NULL, `actualShipDateTime` datetime DEFAULT NULL, `systemCreated` int(11) DEFAULT '1', `stopSeq` int(11) DEFAULT '0', `checkedType` int(11) NOT NULL DEFAULT '0', `multiPacking` int(11) NOT NULL DEFAULT '0', `stageLoc` varchar(50) DEFAULT NULL, `scannedSerialNum` text, `pickCompletedAt` datetime DEFAULT NULL, `carrierService` varchar(50) DEFAULT NULL, `printDataId` varchar(100) DEFAULT NULL, `packedBy` varchar(50) DEFAULT NULL, `packedAt` datetime DEFAULT NULL, `handoverAt` datetime DEFAULT NULL, `handoverBy` varchar(50) DEFAULT NULL, `videoFileName` varchar(200) DEFAULT NULL, `statusFlow` varchar(50) DEFAULT NULL, `sourceErp` varchar(50) DEFAULT NULL, `erpOrderType` varchar(50) DEFAULT NULL, `secondOqcBench` varchar(50) DEFAULT NULL, `doubleOqcBy` varchar(50) DEFAULT NULL, `secondOqcBy` varchar(50) DEFAULT NULL, `secondOqcStartAt` datetime DEFAULT NULL, `secondOqcEndAt` datetime DEFAULT NULL, `checkAt` datetime DEFAULT NULL, `checkBy` varchar(50) DEFAULT NULL, `actualContainerType` varchar(255) DEFAULT NULL, `isSubscribe` int(2) DEFAULT '0', `actualWeight` decimal(15, 4) DEFAULT NULL, `handoverConfirmAt` datetime DEFAULT NULL, `handoverConfirmBy` varchar(50) DEFAULT NULL, `actProcessStamp` varchar(50) DEFAULT NULL, `sfRegisterRoute` int(11) NOT NULL DEFAULT '0', `ztoRegisterRoute` int(11) NOT NULL DEFAULT '0', `packageCollection` varchar(50) DEFAULT NULL, `packageTransfer` varchar(50) DEFAULT NULL, `Packagedelivery` varchar(50) DEFAULT NULL, `PackageReceipt` varchar(50) DEFAULT NULL, PRIMARY KEY USING BTREE (`id`), UNIQUE KEY `idx1` USING BTREE (`code`, `warehouseCode`), KEY `idx14` USING BTREE (`warehouseCode`, `status`, `companyCode`), KEY `idx15` USING BTREE (`transContCode`, `warehouseCode`, `status`), KEY `idx16` USING BTREE (`cageCode`, `warehouseCode`, `status`), KEY `idx2` USING BTREE (`shipmentId`), KEY `idx3` USING BTREE (`shipmentCode`, `warehouseCode`), KEY `idx4` USING BTREE (`waveId`), KEY `idx5` USING BTREE (`waybillCode`, `warehouseCode`), KEY `idx6` USING BTREE (`loadId`), KEY `idx7` USING BTREE (`cageId`), KEY `idx9` USING BTREE (`stageLoc`, `warehouseCode`, `status`), KEY `_local_idx8` USING BTREE (`actualShipDateTime`), KEY `_local_idx10` USING BTREE (`pickCompletedAt`), KEY `_local_idx11` USING BTREE (`oqcEndAt`), KEY `_local_idx12` USING BTREE (`scaledAt`), KEY `_local_idx13` USING BTREE (`stagedAt`), KEY `idx_lastUpdated` (`lastUpdated`) ) SINGLE ENGINE = InnoDB AUTO_INCREMENT = 5866868 DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC TABLEGROUP = `newtg7643`; - CREATE TABLE IF NOT EXISTS `item_packing_detail` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `headerId` bigint(20) NOT NULL DEFAULT '0', `warehouseCode` varchar(50) NOT NULL, `companyCode` varchar(50) NOT NULL, `itemCode` varchar(50) NOT NULL, `packingCode` varchar(50) NOT NULL, `sequence` int(10) NOT NULL DEFAULT '0', `unitCode` varchar(50) NOT NULL, `unitName` varchar(50) NOT NULL, `displayName` varchar(100) NOT NULL, `qtyRatio` int(11) DEFAULT '0', `unitQty` bigint(20) DEFAULT '0', `unitLength` decimal(15, 4) DEFAULT '0.0000', `unitWidth` decimal(15, 4) DEFAULT '0.0000', `unitHeight` decimal(15, 4) DEFAULT '0.0000', `unitWeight` decimal(15, 4) DEFAULT '0.0000', `unitVolume` decimal(15, 4) DEFAULT '0.0000', `ti` int(10) NOT NULL DEFAULT '0', `hi` int(10) NOT NULL DEFAULT '0', `unitAsLooseInbound` int(1) NOT NULL DEFAULT '0', `unitAsLooseOutbound` int(1) NOT NULL DEFAULT '0', `syncGlobal` int(11) DEFAULT '0', `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `createdBy` varchar(50) DEFAULT NULL, `lastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `lastUpdatedBy` varchar(50) DEFAULT NULL, `version` int(11) DEFAULT '0', `userDef1` varchar(50) DEFAULT NULL, `userDef2` varchar(50) DEFAULT NULL, `userDef3` varchar(50) DEFAULT NULL, `userDef4` varchar(50) DEFAULT NULL, `userDef5` varchar(50) DEFAULT NULL, `userDef6` varchar(50) DEFAULT NULL, `userDef7` varchar(50) DEFAULT NULL, `userDef8` varchar(50) DEFAULT NULL, `processStamp` varchar(50) DEFAULT NULL, `denominator` int(11) DEFAULT '0', `molecule` int(11) DEFAULT '0', PRIMARY KEY USING BTREE (`id`), UNIQUE KEY `idx2` USING BTREE (`itemCode`, `companyCode`, `warehouseCode`, `packingCode`, `unitCode`), KEY `idx1` USING BTREE (`headerId`) ) SINGLE ENGINE = InnoDB AUTO_INCREMENT = 13384955 DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC; - CREATE TABLE IF NOT EXISTS `warehouse` ( `code` varchar(50) NOT NULL DEFAULT '', `address1` varchar(200) DEFAULT NULL, `address2` varchar(200) DEFAULT NULL, `city` varchar(50) DEFAULT NULL, `state` varchar(50) DEFAULT NULL, `district` varchar(50) DEFAULT NULL, `town` varchar(50) DEFAULT NULL, `country` varchar(50) DEFAULT NULL, `countryCode` varchar(50) DEFAULT NULL, `stateCode` varchar(50) DEFAULT NULL, `cityCode` varchar(50) DEFAULT NULL, `districtCode` varchar(50) DEFAULT NULL, `townCode` varchar(50) DEFAULT NULL, `postalCode` varchar(50) DEFAULT NULL, `attentionTo` varchar(50) DEFAULT NULL, `phoneNum` varchar(50) DEFAULT NULL, `mobile` varchar(50) DEFAULT NULL, `faxNum` varchar(50) DEFAULT NULL, `email` varchar(50) DEFAULT NULL, `hostCode` varchar(200) DEFAULT NULL, `name` varchar(50) NOT NULL, `status` int(11) DEFAULT '1', `orgCode` varchar(50) DEFAULT NULL, `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `createdBy` varchar(50) DEFAULT NULL, `lastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `lastUpdatedBy` varchar(50) DEFAULT NULL, `version` int(11) DEFAULT '0', `userDef1` varchar(50) DEFAULT NULL, `userDef2` varchar(50) DEFAULT NULL, `userDef3` varchar(50) DEFAULT NULL, `userDef4` varchar(50) DEFAULT NULL, `userDef5` varchar(50) DEFAULT NULL, `userDef6` varchar(50) DEFAULT NULL, `userDef7` varchar(50) DEFAULT NULL, `userDef8` varchar(50) DEFAULT NULL, `tenantId` varchar(50) DEFAULT NULL, `acctCode` varchar(50) DEFAULT NULL, `authOrigin` varchar(50) DEFAULT NULL, `tenantMobile` varchar(50) DEFAULT NULL, `tenantNickName` varchar(50) DEFAULT NULL, `lat` double DEFAULT NULL, `lng` double DEFAULT NULL, `qrcode` varchar(100) DEFAULT NULL, PRIMARY KEY USING BTREE (`code`) ) BROADCAST ENGINE = InnoDB DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC; - CREATE TABLE IF NOT EXISTS `shipment_header` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `warehouseCode` varchar(50) NOT NULL, `companyCode` varchar(50) NOT NULL, `loadId` bigint(20) DEFAULT '0', `code` varchar(50) NOT NULL, `erpOrderCode` varchar(50) DEFAULT NULL, `erpOrderType` varchar(50) DEFAULT NULL, `erpOrderId` bigint(20) DEFAULT NULL, `leadingSts` int(11) NOT NULL DEFAULT '100', `trailingSts` int(11) NOT NULL DEFAULT '100', `shipmentType` varchar(50) NOT NULL, `route` varchar(50) DEFAULT NULL, `sourcePlatform` varchar(50) DEFAULT NULL, `sourceOrderCode` varchar(1500) DEFAULT NULL, `sourceErp` varchar(50) DEFAULT NULL, `shipTo` varchar(50) DEFAULT NULL, `sellerTo` varchar(50) DEFAULT NULL, `shipToName` varchar(50) DEFAULT NULL, `shipToID` varchar(300) DEFAULT NULL, `shipToCAID` varchar(300) DEFAULT NULL, `shipToAddress1` varchar(1500) DEFAULT NULL, `shipToAddress2` varchar(1500) DEFAULT NULL, `shipToDistrict` varchar(500) DEFAULT NULL, `shipToTown` varchar(500) DEFAULT NULL, `shipToCity` varchar(500) DEFAULT NULL, `shipToState` varchar(500) DEFAULT NULL, `shipToCountry` varchar(500) DEFAULT NULL, `shipToCountryCode` varchar(50) DEFAULT NULL, `shipToStateCode` varchar(50) DEFAULT NULL, `shipToCityCode` varchar(50) DEFAULT NULL, `shipToDistrictCode` varchar(50) DEFAULT NULL, `shipToTownCode` varchar(50) DEFAULT NULL, `shipToPostalCode` varchar(50) DEFAULT NULL, `shipToAttentionTo` varchar(1500) DEFAULT NULL, `shipToPhoneNum` varchar(500) DEFAULT NULL, `shipToMobile` varchar(1500) DEFAULT NULL, `shipToFaxNum` varchar(50) DEFAULT NULL, `shipToEmailAddress` varchar(500) DEFAULT NULL, `priority` int(11) DEFAULT NULL, `requestedDeliveryDate` date DEFAULT NULL, `requestedDeliveryType` varchar(20) DEFAULT NULL, `scheduledShipDate` date DEFAULT NULL, `actualShipDateTime` datetime DEFAULT NULL, `actualDeliveryDate` date DEFAULT NULL, `deliveryNote` varchar(200) DEFAULT NULL, `rejectionNote` varchar(500) DEFAULT NULL, `waveId` bigint(20) DEFAULT NULL, `shipDock` varchar(50) DEFAULT NULL, `allocateComplete` int(11) DEFAULT NULL, `totalWeight` decimal(15, 4) DEFAULT NULL, `qtyRatio` int(11) DEFAULT '0', `totalQty` bigint(20) DEFAULT '0', `totalVolume` decimal(15, 4) DEFAULT NULL, `totalLines` int(11) DEFAULT NULL, `totalContainers` int(11) DEFAULT NULL, `totalCases` int(11) DEFAULT NULL, `totalGroupConts` int(11) DEFAULT '0', `totalValue` decimal(15, 4) DEFAULT NULL, `carrierCode` varchar(50) DEFAULT NULL, `carrierService` varchar(50) DEFAULT NULL, `backOrderId` bigint(20) DEFAULT NULL, `processType` varchar(50) DEFAULT NULL, `lastWaveId` bigint(20) DEFAULT NULL, `groupNum` int(11) DEFAULT NULL, `groupIndex` int(11) DEFAULT NULL, `signValue` text, `shipmentSubType` varchar(50) DEFAULT NULL, `shipmentCategory1` varchar(50) DEFAULT NULL, `shipmentCategory2` varchar(50) DEFAULT NULL, `shipmentCategory3` varchar(50) DEFAULT NULL, `shipmentCategory4` varchar(50) DEFAULT NULL, `shipmentCategory5` varchar(50) DEFAULT NULL, `shipmentCategory6` varchar(50) DEFAULT NULL, `shipmentCategory7` varchar(50) DEFAULT NULL, `shipmentCategory8` varchar(50) DEFAULT NULL, `shipmentNote` varchar(500) DEFAULT NULL, `stopSeq` int(11) DEFAULT NULL, `codRequired` int(11) DEFAULT NULL, `codValue` decimal(15, 4) DEFAULT NULL, `deiveryWindow` varchar(100) DEFAULT NULL, `allowConsolidate` int(11) DEFAULT NULL, `consolidated` int(11) DEFAULT NULL, `invoiceRequired` int(11) DEFAULT NULL, `invoiceType` varchar(100) DEFAULT NULL, `invoiceHeader` varchar(100) DEFAULT NULL, `invoiceContent` varchar(200) DEFAULT NULL, `hostCompanyCode` varchar(50) DEFAULT NULL, `uploadRequired` int(11) DEFAULT '0', `uploadBatch` varchar(200) DEFAULT NULL, `statusFlow` varchar(50) DEFAULT NULL, `storeCode` varchar(50) DEFAULT NULL, `storeName` varchar(50) DEFAULT NULL, `primaryWaybillCode` varchar(50) DEFAULT NULL, `secondWaybillCodes` varchar(200) DEFAULT NULL, `routeCode` varchar(50) DEFAULT NULL, `shortAddress` varchar(50) DEFAULT NULL, `podStatus` varchar(50) DEFAULT NULL, `podDatetime` datetime DEFAULT NULL, `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `finalshipment` varchar(255) DEFAULT NULL, `bulkmaterials` varchar(255) DEFAULT NULL, `componentscraprate` varchar(255) DEFAULT NULL, `text` varchar(255) DEFAULT NULL, `reserveNo` int(11) DEFAULT NULL, `createdBy` varchar(50) DEFAULT NULL, `lastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `lastUpdatedBy` varchar(50) DEFAULT NULL, `version` int(11) DEFAULT '0', `userDef1` varchar(50) DEFAULT NULL, `userDef2` varchar(50) DEFAULT NULL, `userDef3` varchar(50) DEFAULT NULL, `userDef4` varchar(50) DEFAULT NULL, `userDef5` varchar(50) DEFAULT NULL, `userDef6` varchar(500) DEFAULT NULL, `userDef7` varchar(50) DEFAULT NULL, `userDef8` varchar(50) DEFAULT NULL, `processStamp` varchar(50) DEFAULT NULL, `payTime` datetime DEFAULT NULL, `payNo` varchar(800) DEFAULT NULL, `lockCode` varchar(50) DEFAULT NULL, `shipToAddressLng` varchar(50) DEFAULT NULL, `shipToAddressLat` varchar(50) DEFAULT NULL, `shortPick` int(11) DEFAULT '0', `shortAlloc` int(11) DEFAULT '0', `portCode` varchar(50) DEFAULT NULL, `packageCenterCode` varchar(50) DEFAULT NULL, `packageCenterName` varchar(50) DEFAULT NULL, `stamp` varchar(50) DEFAULT NULL, `stampIndex` varchar(50) DEFAULT NULL, `thruReceiptCode` varchar(50) DEFAULT NULL, `stageLoc` varchar(50) DEFAULT NULL, `insureRequired` int(11) DEFAULT '0', `originalOrderId` bigint(20) DEFAULT '0', `shortPacking` int(11) DEFAULT '0', `printDataId` varchar(100) DEFAULT NULL, `disabledCarrierCodes` varchar(100) DEFAULT NULL, `realUserId` varchar(100) DEFAULT NULL, `logisticsServices` varchar(100) DEFAULT NULL, `trackingType` int(11) DEFAULT '0', `shortAddressCode` varchar(50) DEFAULT NULL, `secondSectionCode` varchar(50) DEFAULT NULL, `thirdSectionCode` varchar(50) DEFAULT NULL, `servicemode` varchar(50) DEFAULT NULL, `payType` varchar(50) DEFAULT NULL, `receipcompany` varchar(50) DEFAULT NULL, `vipshopCode` varchar(50) DEFAULT NULL, `payStatus` int(11) DEFAULT '0', `warehouseTransferId` bigint(20) DEFAULT '0', `warehouseTransferCode` varchar(50) DEFAULT NULL, `shipObjType` varchar(50) DEFAULT NULL, `auditStatus` int(11) DEFAULT '-2', `auditedBy` varchar(50) DEFAULT NULL, `auditedAt` datetime DEFAULT NULL, `auditOpinion` varchar(200) DEFAULT NULL, `tempLevel` varchar(50) DEFAULT NULL, `checkBusinessScope` int(11) DEFAULT '0', `twoVoteSystem` int(11) DEFAULT '0', `materialdocumentyear` varchar(50) DEFAULT NULL, `itemCode` varchar(50) DEFAULT NULL, `confirmedAt` varchar(50) DEFAULT NULL, `postReceiptOn` varchar(50) DEFAULT NULL, `manufacturer` varchar(50) DEFAULT NULL, `towarehouseCode` varchar(50) DEFAULT NULL, `fromwarehouseCode` varchar(50) DEFAULT NULL, `orderDate` varchar(50) DEFAULT NULL, `purchaseOrderCode` varchar(50) DEFAULT NULL, `zxQty` int(11) DEFAULT NULL, `hxQty` int(11) DEFAULT NULL, `totalconQty` int(11) DEFAULT NULL, `deletedimension` varchar(255) DEFAULT NULL, `sourceErpCode` varchar(50) DEFAULT NULL, `uploadture` int(11) DEFAULT NULL, `updatereason` varchar(200) DEFAULT NULL, `closeShipment` int(2) DEFAULT NULL, `splitOrderIdentification` varchar(50) DEFAULT NULL, `temperatureControl` int(2) DEFAULT NULL, `newOrderDate` date DEFAULT NULL, `sfWeightProcess` varchar(5) DEFAULT NULL, `companyType` varchar(50) DEFAULT NULL, `agentCode` varchar(50) DEFAULT NULL, `actualTotalWeight` decimal(15, 6) DEFAULT NULL, PRIMARY KEY USING BTREE (`id`), UNIQUE KEY `idx1` USING BTREE (`code`, `warehouseCode`, `companyCode`), KEY `idx2` USING BTREE (`waveId`), KEY `idx3` USING BTREE (`loadId`), KEY `idx4` USING BTREE (`erpOrderCode`, `warehouseCode`), KEY `idx6` USING BTREE (`primaryWaybillCode`, `warehouseCode`), KEY `idx_splitOrderIdentification` (`splitOrderIdentification`), KEY `__advise_index_shipment_header_list_carriercode` (`carrierCode`, `warehouseCode`), KEY `_local_idx10` USING BTREE (`warehouseTransferId`), KEY `_local_idx11` USING BTREE (`warehouseTransferCode`, `warehouseCode`, `companyCode`), KEY `_local_idx8` USING BTREE (`stamp`, `warehouseCode`), KEY `idxCreaedWarehouseCode` (`created`, `warehouseCode`), KEY `idexLeadTrailSts` (`leadingSts`, `trailingSts`), KEY `local_idx_primaryWaybillCode` (`primaryWaybillCode`, `secondWaybillCodes`, `trailingSts`), KEY `local_idx_trailingSts` (`trailingSts`, `created`), KEY `auto_shard_key_warehousecode` USING BTREE (`warehouseCode`) ) ENGINE = InnoDB AUTO_INCREMENT = 8853934 DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC PARTITION BY LIST COLUMNS (`warehouseCode`) SUBPARTITION BY KEY (`id`) ( PARTITION `p1` VALUES IN ('021DC1') ( SUBPARTITION `p1sp1`, SUBPARTITION `p1sp2`, SUBPARTITION `p1sp3`, SUBPARTITION `p1sp4` ), PARTITION `p2` VALUES IN ('022DC') ( SUBPARTITION `p2sp1`, SUBPARTITION `p2sp2`, SUBPARTITION `p2sp3`, SUBPARTITION `p2sp4` ), PARTITION `p3` VALUES IN ('027DC') ( SUBPARTITION `p3sp1`, SUBPARTITION `p3sp2`, SUBPARTITION `p3sp3`, SUBPARTITION `p3sp4` ), PARTITION `p4` VALUES IN ('028DC') ( SUBPARTITION `p4sp1`, SUBPARTITION `p4sp2`, SUBPARTITION `p4sp3`, SUBPARTITION `p4sp4` ), PARTITION `p5` VALUES IN ('573DC') ( SUBPARTITION `p5sp1`, SUBPARTITION `p5sp2`, SUBPARTITION `p5sp3`, SUBPARTITION `p5sp4` ), PARTITION `p6` VALUES IN ('763DC') ( SUBPARTITION `p6sp1`, SUBPARTITION `p6sp2`, SUBPARTITION `p6sp3`, SUBPARTITION `p6sp4` ), PARTITION `p7` VALUES IN ('763DCA') ( SUBPARTITION `p7sp1`, SUBPARTITION `p7sp2`, SUBPARTITION `p7sp3`, SUBPARTITION `p7sp4` ), PARTITION `p8` VALUES IN ('SH01') ( SUBPARTITION `p8sp1`, SUBPARTITION `p8sp2`, SUBPARTITION `p8sp3`, SUBPARTITION `p8sp4` ), PARTITION `p9` VALUES IN ('SH02') ( SUBPARTITION `p9sp1`, SUBPARTITION `p9sp2`, SUBPARTITION `p9sp3`, SUBPARTITION `p9sp4` ), PARTITION `p10` VALUES IN ('SH03') ( SUBPARTITION `p10sp1`, SUBPARTITION `p10sp2`, SUBPARTITION `p10sp3`, SUBPARTITION `p10sp4` ), PARTITION `p11` VALUES IN ('TEST01') ( SUBPARTITION `p11sp1`, SUBPARTITION `p11sp2`, SUBPARTITION `p11sp3`, SUBPARTITION `p11sp4` ), PARTITION `p12` VALUES IN (DEFAULT) ( SUBPARTITION `p12sp1`, SUBPARTITION `p12sp2`, SUBPARTITION `p12sp3`, SUBPARTITION `p12sp4` ) ); - CREATE TABLE IF NOT EXISTS `shipping_container_detail` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `containerCode` varchar(50) NOT NULL, `containerId` bigint(20) NOT NULL, `shipmentCode` varchar(50) NOT NULL, `warehouseCode` varchar(50) NOT NULL, `shipmentId` bigint(20) NOT NULL, `shipmentDetailId` bigint(20) NOT NULL, `companyCode` varchar(50) NOT NULL, `itemCode` varchar(50) NOT NULL, `itemName` varchar(500) DEFAULT NULL, `status` int(11) DEFAULT '300', `itemWeight` decimal(15, 4) DEFAULT '0.0000', `itemVolume` decimal(15, 4) DEFAULT '0.0000', `itemLength` decimal(15, 4) DEFAULT '0.0000', `itemWidth` decimal(15, 4) DEFAULT '0.0000', `itemHeight` decimal(15, 4) DEFAULT '0.0000', `itemValue` decimal(15, 4) DEFAULT '0.0000', `quantity` bigint(20) DEFAULT '0', `waveId` bigint(20) DEFAULT '0', `shipmentAllocId` bigint(20) DEFAULT '0', `taskCreated` int(11) DEFAULT '0', `attributeId` bigint(20) DEFAULT '0', `originalPickLoc` varchar(50) DEFAULT NULL, `lpn` varchar(50) DEFAULT NULL, `attribute1` varchar(50) DEFAULT NULL, `attribute2` varchar(50) DEFAULT NULL, `attribute3` varchar(50) DEFAULT NULL, `attribute4` varchar(50) DEFAULT NULL, `attribute5` varchar(50) DEFAULT NULL, `attribute6` varchar(50) DEFAULT NULL, `attribute7` varchar(50) DEFAULT NULL, `attribute8` varchar(50) DEFAULT NULL, `batch` varchar(50) DEFAULT NULL, `lot` varchar(50) DEFAULT NULL, `manufactureDate` date DEFAULT NULL, `expirationDate` date DEFAULT NULL, `agingDate` date DEFAULT NULL, `inventorySts` varchar(50) DEFAULT NULL, `shelfLifeSts` varchar(50) DEFAULT NULL, `packingCode` varchar(50) DEFAULT NULL, `convertedQty` bigint(20) DEFAULT '0', `convertedQtyUm` varchar(50) DEFAULT NULL, `unitQty` bigint(20) DEFAULT '0', `packingClass` varchar(50) DEFAULT NULL, `transContCode` varchar(50) DEFAULT NULL, `scannedQty` bigint(20) DEFAULT '0', `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `createdBy` varchar(50) DEFAULT NULL, `lastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `lastUpdatedBy` varchar(50) DEFAULT NULL, `version` int(11) DEFAULT '0', `userDef1` varchar(50) DEFAULT NULL, `userDef2` varchar(50) DEFAULT NULL, `userDef3` varchar(50) DEFAULT NULL, `userDef4` varchar(50) DEFAULT NULL, `userDef5` varchar(50) DEFAULT NULL, `userDef6` varchar(50) DEFAULT NULL, `userDef7` varchar(50) DEFAULT NULL, `userDef8` varchar(50) DEFAULT NULL, `processStamp` varchar(50) DEFAULT NULL, `csQty` bigint(20) DEFAULT '0', `plQty` bigint(20) DEFAULT '0', `qtyRatio` int(11) DEFAULT '0', `umQtyRatio` int(11) DEFAULT '0', `unitQtyRatio` int(11) DEFAULT '0', `isGift` int(11) DEFAULT '0', `actualBarcode` varchar(50) DEFAULT NULL, `checkingMethod` int(11) DEFAULT NULL, `twiceCheckingStatus` int(11) DEFAULT NULL, `crossDockMode` int(1) DEFAULT '0', `receiptCode` varchar(50) DEFAULT NULL, `receiptId` bigint(20) DEFAULT NULL, `receiptDetailId` bigint(20) DEFAULT NULL, PRIMARY KEY USING BTREE (`id`), KEY `idx1` USING BTREE (`containerId`), KEY `idx2` USING BTREE (`containerCode`, `warehouseCode`), KEY `idx3` USING BTREE (`shipmentId`), KEY `idx4` USING BTREE (`shipmentCode`, `warehouseCode`), KEY `idx5` USING BTREE (`waveId`), KEY `idx6` USING BTREE (`shipmentDetailId`), KEY `idx7` USING BTREE (`shipmentAllocId`), KEY `auto_shard_key_warehousecode` USING BTREE (`warehouseCode`) ) ENGINE = InnoDB AUTO_INCREMENT = 18848143 DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC PARTITION BY LIST COLUMNS (`warehouseCode`) SUBPARTITION BY KEY (`id`) ( PARTITION `p1` VALUES IN ('021DC1') ( SUBPARTITION `p1sp1`, SUBPARTITION `p1sp2`, SUBPARTITION `p1sp3`, SUBPARTITION `p1sp4` ), PARTITION `p2` VALUES IN ('022DC') ( SUBPARTITION `p2sp1`, SUBPARTITION `p2sp2`, SUBPARTITION `p2sp3`, SUBPARTITION `p2sp4` ), PARTITION `p3` VALUES IN ('027DC') ( SUBPARTITION `p3sp1`, SUBPARTITION `p3sp2`, SUBPARTITION `p3sp3`, SUBPARTITION `p3sp4` ), PARTITION `p4` VALUES IN ('028DC') ( SUBPARTITION `p4sp1`, SUBPARTITION `p4sp2`, SUBPARTITION `p4sp3`, SUBPARTITION `p4sp4` ), PARTITION `p5` VALUES IN ('573DC') ( SUBPARTITION `p5sp1`, SUBPARTITION `p5sp2`, SUBPARTITION `p5sp3`, SUBPARTITION `p5sp4` ), PARTITION `p6` VALUES IN ('763DC') ( SUBPARTITION `p6sp1`, SUBPARTITION `p6sp2`, SUBPARTITION `p6sp3`, SUBPARTITION `p6sp4` ), PARTITION `p7` VALUES IN ('763DCA') ( SUBPARTITION `p7sp1`, SUBPARTITION `p7sp2`, SUBPARTITION `p7sp3`, SUBPARTITION `p7sp4` ), PARTITION `p8` VALUES IN ('SH01') ( SUBPARTITION `p8sp1`, SUBPARTITION `p8sp2`, SUBPARTITION `p8sp3`, SUBPARTITION `p8sp4` ), PARTITION `p9` VALUES IN ('SH02') ( SUBPARTITION `p9sp1`, SUBPARTITION `p9sp2`, SUBPARTITION `p9sp3`, SUBPARTITION `p9sp4` ), PARTITION `p10` VALUES IN ('SH03') ( SUBPARTITION `p10sp1`, SUBPARTITION `p10sp2`, SUBPARTITION `p10sp3`, SUBPARTITION `p10sp4` ), PARTITION `p11` VALUES IN ('TEST01') ( SUBPARTITION `p11sp1`, SUBPARTITION `p11sp2`, SUBPARTITION `p11sp3`, SUBPARTITION `p11sp4` ), PARTITION `p12` VALUES IN (DEFAULT) ( SUBPARTITION `p12sp1`, SUBPARTITION `p12sp2`, SUBPARTITION `p12sp3`, SUBPARTITION `p12sp4` ) ); - DELETE FROM metadb.table_statistics WHERE `SCHEMA_NAME` = 'jala_wms_prod' AND `TABLE_NAME` in ('ttx_user','task_detail','shipment_detail','item','shipping_container_header','item_packing_detail','warehouse','shipment_header','shipping_container_detail'); - INSERT INTO metadb.table_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `ROW_COUNT`) VALUES ('jala_wms_prod','item',805309),('jala_wms_prod','item_packing_detail',4028798),('jala_wms_prod','shipment_detail',9835232),('jala_wms_prod','shipment_header',4236337),('jala_wms_prod','shipping_container_detail',12538591),('jala_wms_prod','shipping_container_header',3285881),('jala_wms_prod','task_detail',13993072),('jala_wms_prod','ttx_user',1630),('jala_wms_prod','warehouse',12); - DELETE FROM metadb.column_statistics WHERE `SCHEMA_NAME` = 'jala_wms_prod' AND `TABLE_NAME` in ('ttx_user','task_detail','shipment_detail','item','shipping_container_header','item_packing_detail','warehouse','shipment_header','shipping_container_detail'); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('jala_wms_prod','item','abcclass',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[42],"valueArr":[""],"type":"String","sampleRate":1.0}',93097,0.11565614),('jala_wms_prod','item','acceptancemethod',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','allocationrule',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"2B按单拣货波次规则","lower":"2B按单拣货波次规则","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[41],"valueArr":[""],"type":"String","sampleRate":1.0}',93097,0.11565614),('jala_wms_prod','item','allowdown',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','allowrotate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','approvalnumber',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[96],"valueArr":[""],"type":"String","sampleRate":1.0}',93043,0.11565614),('jala_wms_prod','item','attributetemplatecode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[52,88060,5026],"valueArr":["","批次+生产日期+失效日期+入库日期","批次+生产日期+失效日期+入库日期+属性1"],"type":"String","sampleRate":1.0}',1,0.11565614),('jala_wms_prod','item','auditcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[96],"valueArr":[""],"type":"String","sampleRate":1.0}',93043,0.11565614),('jala_wms_prod','item','autogenserialnum',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','autogenserialnumformat',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[96],"valueArr":[""],"type":"String","sampleRate":1.0}',93043,0.11565614),('jala_wms_prod','item','brand',22,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"09J9","lower":"09J9","count":45,"preSum":0},{"ndv":1,"upper":"13JALA","lower":"13JALA","count":27,"preSum":45},{"ndv":1,"upper":"医婷","lower":"医婷","count":2,"preSum":72},{"ndv":2,"upper":"莎辛那","lower":"珀芙研","count":13,"preSum":74}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[11962,13939,48336,4652,5803,1551,456,92,1744,1674,212,63,188,148],"valueArr":["","01美素","02自然堂","03植物智慧","05春夏","06COMO","07ASSASSINA莎辛那","10己出","12珀芙研","ZZ通用","春夏","植物智慧","美素","自然堂"],"type":"String","sampleRate":1.0}',2232,0.11565614),('jala_wms_prod','item','checkingmethod',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','class01',151,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"","lower":"","count":1074,"preSum":0},{"ndv":1,"upper":"10101","lower":"10101","count":1332,"preSum":1074},{"ndv":2,"upper":"10103","lower":"10102","count":735,"preSum":2406},{"ndv":3,"upper":"10107","lower":"10104","count":1062,"preSum":3141},{"ndv":3,"upper":"10111","lower":"10108","count":503,"preSum":4203},{"ndv":1,"upper":"10112","lower":"10112","count":1069,"preSum":4706},{"ndv":3,"upper":"10115","lower":"10113","count":990,"preSum":5775},{"ndv":6,"upper":"10121","lower":"10116","count":516,"preSum":6765},{"ndv":1,"upper":"10122","lower":"10122","count":1371,"preSum":7281},{"ndv":2,"upper":"10124","lower":"10123","count":1411,"preSum":8652},{"ndv":11,"upper":"10204","lower":"10125","count":676,"preSum":10063},{"ndv":6,"upper":"10405","lower":"10205","count":1465,"preSum":10739},{"ndv":3,"upper":"10408","lower":"10406","count":509,"preSum":12204},{"ndv":1,"upper":"10409","lower":"10409","count":804,"preSum":12713},{"ndv":1,"upper":"10410","lower":"10410","count":530,"preSum":13517},{"ndv":5,"upper":"10602","lower":"10501","count":1383,"preSum":14047},{"ndv":1,"upper":"19999","lower":"19999","count":1278,"preSum":15430},{"ndv":2,"upper":"20103","lower":"20102","count":591,"preSum":16708},{"ndv":1,"upper":"20201","lower":"20201","count":619,"preSum":17299},{"ndv":2,"upper":"20203","lower":"20202","count":546,"preSum":17918},{"ndv":4,"upper":"20302","lower":"20204","count":574,"preSum":18464},{"ndv":6,"upper":"20402","lower":"20303","count":994,"preSum":19038},{"ndv":3,"upper":"20501","lower":"20403","count":541,"preSum":20032},{"ndv":4,"upper":"304","lower":"20502","count":1344,"preSum":20573},{"ndv":7,"upper":"499","lower":"305","count":1427,"preSum":21917},{"ndv":1,"upper":"502","lower":"502","count":752,"preSum":23344},{"ndv":2,"upper":"506","lower":"504","count":846,"preSum":24096},{"ndv":4,"upper":"60103","lower":"6","count":600,"preSum":24942},{"ndv":5,"upper":"60108","lower":"60104","count":557,"preSum":25542},{"ndv":5,"upper":"60202","lower":"60110","count":1159,"preSum":26099},{"ndv":3,"upper":"60206","lower":"60204","count":841,"preSum":27258},{"ndv":5,"upper":"60211","lower":"60207","count":508,"preSum":28099},{"ndv":1,"upper":"60213","lower":"60213","count":605,"preSum":28607},{"ndv":3,"upper":"60303","lower":"60214","count":514,"preSum":29212},{"ndv":3,"upper":"60401","lower":"60304","count":825,"preSum":29726},{"ndv":7,"upper":"80102","lower":"60402","count":519,"preSum":30551},{"ndv":9,"upper":"80301","lower":"80103","count":547,"preSum":31070},{"ndv":5,"upper":"ZB16","lower":"80302","count":146,"preSum":31617}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[7197,2979,3758,4569,2982,3608,2293,3010,11961,3090,3074,4684,3431,1436],"valueArr":["10402","10403","10404","10601","20101","301","302","4","501","503","505","60203","60305","69999"],"type":"String","sampleRate":1.0}',3304,0.11565614),('jala_wms_prod','item','class02',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[726],"valueArr":[""],"type":"String","sampleRate":1.0}',92413,0.11565614),('jala_wms_prod','item','class03',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[726],"valueArr":[""],"type":"String","sampleRate":1.0}',92413,0.11565614),('jala_wms_prod','item','code',79981,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":689,"upper":"1103096400","lower":"1101003500","count":1455,"preSum":0},{"ndv":633,"upper":"1115027100","lower":"1103096500","count":1457,"preSum":1455},{"ndv":694,"upper":"1201107000","lower":"1115027200","count":1458,"preSum":2912},{"ndv":642,"upper":"1201205600","lower":"1201107100","count":1454,"preSum":4370},{"ndv":680,"upper":"1203015601","lower":"1201205700","count":1455,"preSum":5824},{"ndv":717,"upper":"1213029500","lower":"1203015900","count":1457,"preSum":7279},{"ndv":674,"upper":"1216189300","lower":"1213029502","count":1454,"preSum":8736},{"ndv":638,"upper":"1300051400","lower":"1216189500","count":1456,"preSum":10190},{"ndv":662,"upper":"1300114400","lower":"1300051500","count":1457,"preSum":11646},{"ndv":655,"upper":"1300176100","lower":"1300114500","count":1454,"preSum":13103},{"ndv":722,"upper":"1300245400","lower":"1300176200","count":1454,"preSum":14557},{"ndv":665,"upper":"1300311300","lower":"1300245500","count":1455,"preSum":16011},{"ndv":730,"upper":"1300395500","lower":"1300311400","count":1455,"preSum":17466},{"ndv":673,"upper":"1300462000","lower":"1300395600","count":1456,"preSum":18921},{"ndv":669,"upper":"1300532000","lower":"1300462100","count":1455,"preSum":20377},{"ndv":703,"upper":"1300607700","lower":"1300532200","count":1455,"preSum":21832},{"ndv":630,"upper":"1300676502","lower":"1300607701","count":1456,"preSum":23287},{"ndv":662,"upper":"1300748700","lower":"1300676600","count":1455,"preSum":24743},{"ndv":666,"upper":"1300820900","lower":"1300748800","count":1454,"preSum":26198},{"ndv":648,"upper":"1300887900","lower":"1300821000","count":1455,"preSum":27652},{"ndv":652,"upper":"1300958601","lower":"1300888000","count":1454,"preSum":29107},{"ndv":615,"upper":"1301022200","lower":"1300958700","count":1455,"preSum":30561},{"ndv":627,"upper":"1301093300","lower":"1301022300","count":1454,"preSum":32016},{"ndv":591,"upper":"1301169300","lower":"1301093400","count":1455,"preSum":33470},{"ndv":554,"upper":"20543","lower":"1301169400","count":1456,"preSum":34925},{"ndv":636,"upper":"21476","lower":"20544","count":1454,"preSum":36381},{"ndv":673,"upper":"22399","lower":"21477","count":1455,"preSum":37835},{"ndv":731,"upper":"28112","lower":"22400","count":1454,"preSum":39290},{"ndv":658,"upper":"28949","lower":"28113","count":1455,"preSum":40744},{"ndv":601,"upper":"30164900","lower":"28950","count":1454,"preSum":42199},{"ndv":603,"upper":"30218503","lower":"30164901","count":1455,"preSum":43653},{"ndv":613,"upper":"30265900","lower":"30218504","count":1454,"preSum":45108},{"ndv":603,"upper":"30320000","lower":"30266101","count":1454,"preSum":46562},{"ndv":596,"upper":"30700600","lower":"30500100","count":1454,"preSum":48016},{"ndv":670,"upper":"402201911","lower":"30700700","count":1455,"preSum":49470},{"ndv":661,"upper":"402575902","lower":"402201912","count":1456,"preSum":50925},{"ndv":616,"upper":"403222600","lower":"402576001","count":1457,"preSum":52381},{"ndv":679,"upper":"501477500","lower":"403222601","count":1454,"preSum":53838},{"ndv":690,"upper":"501953252","lower":"501477600","count":1454,"preSum":55292},{"ndv":676,"upper":"502191363","lower":"501953260","count":1455,"preSum":56746},{"ndv":676,"upper":"502477400","lower":"502191380","count":1456,"preSum":58201},{"ndv":631,"upper":"502521402","lower":"502477401","count":1456,"preSum":59657},{"ndv":650,"upper":"502559901","lower":"502521403","count":1456,"preSum":61113},{"ndv":655,"upper":"502591300","lower":"502559902","count":1454,"preSum":62569},{"ndv":664,"upper":"502646901","lower":"502591400","count":1454,"preSum":64023},{"ndv":655,"upper":"502700701","lower":"502647000","count":1455,"preSum":65477},{"ndv":630,"upper":"502762100","lower":"502700702","count":1454,"preSum":66932},{"ndv":622,"upper":"502974270","lower":"502762102","count":1455,"preSum":68386},{"ndv":727,"upper":"503134600","lower":"502974270[1801]","count":1455,"preSum":69841},{"ndv":653,"upper":"505005300[2007]","lower":"503134700","count":1456,"preSum":71296},{"ndv":666,"upper":"506020100","lower":"505005301","count":1455,"preSum":72752},{"ndv":680,"upper":"512020700","lower":"506020200","count":1455,"preSum":74207},{"ndv":708,"upper":"6011108","lower":"512020800","count":1454,"preSum":75662},{"ndv":694,"upper":"6022871","lower":"6011111","count":1454,"preSum":77116},{"ndv":668,"upper":"6120148","lower":"6022872","count":1454,"preSum":78570},{"ndv":654,"upper":"6160282","lower":"6120149","count":1454,"preSum":80024},{"ndv":666,"upper":"6161126","lower":"6160285","count":1454,"preSum":81478},{"ndv":653,"upper":"6161951","lower":"6161127","count":1457,"preSum":82932},{"ndv":689,"upper":"6162825","lower":"6161953","count":1454,"preSum":84389},{"ndv":651,"upper":"6163630","lower":"6162826","count":1455,"preSum":85843},{"ndv":678,"upper":"6164500","lower":"6163631","count":1454,"preSum":87298},{"ndv":669,"upper":"6165376","lower":"6164501","count":1456,"preSum":88752},{"ndv":606,"upper":"80106","lower":"6165378","count":1454,"preSum":90208},{"ndv":745,"upper":"YD001500","lower":"80107","count":1348,"preSum":91662}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[16,13,12,13,13,12,12,13,13,12],"valueArr":["1300477502","1300814301","1300970201","1301189100","1301191900","1301193800","502912300","510005100","6165617","6165697"],"type":"String","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','collectcsqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','collectdatetime',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','collectdrugtest',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','collectedby',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','companycode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[53255,5032,34852],"valueArr":["JALA01","JALA02","JALA11"],"type":"String","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','costprice',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','countperiod',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','created',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','createdby',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[8865,32529,4293,37866,9586],"valueArr":["TTXLHJ","XCY","XCY1","api","jx"],"type":"String","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','csaslooseinbound',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','csaslooseoutbound',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','csdesc',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93139],"valueArr":["箱"],"type":"String","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','csheight',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','cslength',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','csqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','csvolume',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','csweight',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','cswidth',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','cyclecount',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','daystoexpire',37,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":3,"lower":3,"count":14,"preSum":0},{"ndv":2,"upper":60,"lower":14,"count":31,"preSum":14},{"ndv":2,"upper":270,"lower":100,"count":4,"preSum":45},{"ndv":1,"upper":360,"lower":360,"count":6,"preSum":49},{"ndv":2,"upper":540,"lower":455,"count":25,"preSum":55},{"ndv":1,"upper":605,"lower":605,"count":7,"preSum":80},{"ndv":2,"upper":750,"lower":719,"count":6,"preSum":87},{"ndv":1,"upper":910,"lower":910,"count":34,"preSum":93},{"ndv":1,"upper":1000,"lower":1000,"count":4,"preSum":127},{"ndv":1,"upper":1046,"lower":1046,"count":57,"preSum":131},{"ndv":1,"upper":1080,"lower":1080,"count":8,"preSum":188},{"ndv":2,"upper":1800,"lower":1275,"count":4,"preSum":196},{"ndv":1,"upper":2190,"lower":2190,"count":30,"preSum":200},{"ndv":1,"upper":2555,"lower":2555,"count":3,"preSum":230}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[16200,70,288,98,1188,5361,156,2293,305,31634,23772,10932,408,201],"valueArr":[0,1,2,7,30,90,180,365,545,730,1095,1460,1825,3650],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','department',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[91787,78],"valueArr":["","230"],"type":"String","sampleRate":1.0}',1274,0.11565614),('jala_wms_prod','item','division',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[96],"valueArr":[""],"type":"String","sampleRate":1.0}',93043,0.11565614),('jala_wms_prod','item','dosageforms',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93],"valueArr":[""],"type":"String","sampleRate":1.0}',93046,0.11565614),('jala_wms_prod','item','eaaslooseinbound',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[1],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','eaaslooseoutbound',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[1],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','emptylocrule',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[42],"valueArr":[""],"type":"String","sampleRate":1.0}',93097,0.11565614),('jala_wms_prod','item','expiringdays',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','goodshelflife',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','grossweight',3569,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":84,"upper":3.0,"lower":0.022,"count":254,"preSum":0},{"ndv":63,"upper":4.643,"lower":3.016,"count":248,"preSum":254},{"ndv":54,"upper":6.0,"lower":4.667,"count":246,"preSum":502},{"ndv":64,"upper":8.55,"lower":6.037,"count":245,"preSum":748},{"ndv":43,"upper":11.0,"lower":8.65,"count":250,"preSum":993},{"ndv":51,"upper":14.091,"lower":11.111,"count":244,"preSum":1243},{"ndv":51,"upper":16.68,"lower":14.1,"count":244,"preSum":1487},{"ndv":51,"upper":20.0,"lower":16.7,"count":249,"preSum":1731},{"ndv":38,"upper":22.78,"lower":20.05,"count":263,"preSum":1980},{"ndv":36,"upper":26.0,"lower":22.8,"count":244,"preSum":2243},{"ndv":33,"upper":29.167,"lower":26.042,"count":256,"preSum":2487},{"ndv":44,"upper":33.75,"lower":29.2,"count":248,"preSum":2743},{"ndv":43,"upper":36.667,"lower":33.792,"count":278,"preSum":2991},{"ndv":29,"upper":39.444,"lower":36.806,"count":282,"preSum":3269},{"ndv":32,"upper":42.75,"lower":39.5,"count":246,"preSum":3551},{"ndv":32,"upper":47.222,"lower":42.778,"count":245,"preSum":3797},{"ndv":42,"upper":53.65,"lower":47.25,"count":244,"preSum":4042},{"ndv":50,"upper":60.87,"lower":53.66,"count":245,"preSum":4286},{"ndv":42,"upper":67.708,"lower":60.937,"count":247,"preSum":4531},{"ndv":34,"upper":72.916,"lower":67.777,"count":247,"preSum":4778},{"ndv":40,"upper":80.417,"lower":72.917,"count":244,"preSum":5025},{"ndv":41,"upper":89.583,"lower":80.5,"count":274,"preSum":5269},{"ndv":36,"upper":97.917,"lower":90.0,"count":248,"preSum":5543},{"ndv":35,"upper":106.25,"lower":98.0,"count":267,"preSum":5791},{"ndv":43,"upper":118.75,"lower":106.416,"count":252,"preSum":6058},{"ndv":31,"upper":128.125,"lower":119.444,"count":245,"preSum":6310},{"ndv":21,"upper":137.5,"lower":128.75,"count":261,"preSum":6555},{"ndv":26,"upper":147.917,"lower":138.194,"count":253,"preSum":6816},{"ndv":30,"upper":160.417,"lower":147.92,"count":246,"preSum":7069},{"ndv":31,"upper":170.833,"lower":161.458,"count":247,"preSum":7315},{"ndv":28,"upper":182.5,"lower":171.875,"count":246,"preSum":7562},{"ndv":24,"upper":191.666,"lower":182.589,"count":250,"preSum":7808},{"ndv":16,"upper":200.0,"lower":191.667,"count":272,"preSum":8058},{"ndv":32,"upper":215.625,"lower":200.556,"count":245,"preSum":8330},{"ndv":19,"upper":223.333,"lower":216.5,"count":247,"preSum":8575},{"ndv":21,"upper":233.33,"lower":223.958,"count":250,"preSum":8822},{"ndv":17,"upper":241.666,"lower":233.333,"count":279,"preSum":9072},{"ndv":32,"upper":258.333,"lower":241.667,"count":279,"preSum":9351},{"ndv":27,"upper":275.0,"lower":259.375,"count":272,"preSum":9630},{"ndv":32,"upper":291.667,"lower":275.63,"count":259,"preSum":9902},{"ndv":37,"upper":315.625,"lower":292.31,"count":244,"preSum":10161},{"ndv":42,"upper":345.0,"lower":316.667,"count":250,"preSum":10405},{"ndv":22,"upper":363.636,"lower":345.833,"count":244,"preSum":10655},{"ndv":45,"upper":395.833,"lower":364.58,"count":250,"preSum":10899},{"ndv":34,"upper":420.0,"lower":396.429,"count":248,"preSum":11149},{"ndv":63,"upper":500.0,"lower":420.417,"count":288,"preSum":11397},{"ndv":52,"upper":600.0,"lower":503.333,"count":292,"preSum":11685},{"ndv":41,"upper":675.0,"lower":602.78,"count":255,"preSum":11977},{"ndv":55,"upper":800.0,"lower":679.167,"count":261,"preSum":12232},{"ndv":42,"upper":910.0,"lower":805.0,"count":247,"preSum":12493},{"ndv":45,"upper":1033.333,"lower":915.0,"count":246,"preSum":12740},{"ndv":34,"upper":1130.0,"lower":1035.0,"count":244,"preSum":12986},{"ndv":37,"upper":1216.667,"lower":1132.5,"count":257,"preSum":13230},{"ndv":35,"upper":1320.0,"lower":1220.0,"count":245,"preSum":13487},{"ndv":35,"upper":1425.0,"lower":1321.67,"count":246,"preSum":13732},{"ndv":46,"upper":1600.0,"lower":1430.0,"count":253,"preSum":13978},{"ndv":53,"upper":1900.0,"lower":1608.333,"count":253,"preSum":14231},{"ndv":54,"upper":2750.0,"lower":1916.667,"count":250,"preSum":14484},{"ndv":40,"upper":3840.0,"lower":2756.25,"count":248,"preSum":14734},{"ndv":42,"upper":6310.0,"lower":3850.0,"count":244,"preSum":14982},{"ndv":78,"upper":14300.0,"lower":6380.0,"count":245,"preSum":15226},{"ndv":35,"upper":100000.0,"lower":14450.0,"count":84,"preSum":15471}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[61760,247,14433,71,79,208,99,79,133,77,82,140,106,70],"valueArr":[0.0,0.1,1.0,27.0,40.625,41.667,45.833,143.75,152.083,162.5,175.0,229.167,250.0,350.0],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','groupleveldeletion',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[90906,950],"valueArr":["0","1"],"type":"String","sampleRate":1.0}',1283,0.11565614),('jala_wms_prod','item','gs1code',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[96],"valueArr":[""],"type":"String","sampleRate":1.0}',93043,0.11565614),('jala_wms_prod','item','id',854809,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1456,"upper":1252690,"lower":1224862,"count":1456,"preSum":0},{"ndv":1456,"upper":1267504,"lower":1252693,"count":1456,"preSum":1456},{"ndv":1456,"upper":1284683,"lower":1267505,"count":1456,"preSum":2912},{"ndv":1456,"upper":1297514,"lower":1284686,"count":1456,"preSum":4368},{"ndv":1456,"upper":1314962,"lower":1297516,"count":1456,"preSum":5824},{"ndv":1456,"upper":1330674,"lower":1314963,"count":1456,"preSum":7280},{"ndv":1456,"upper":1342750,"lower":1330675,"count":1456,"preSum":8736},{"ndv":1456,"upper":1356411,"lower":1342751,"count":1456,"preSum":10192},{"ndv":1456,"upper":1371382,"lower":1356412,"count":1456,"preSum":11648},{"ndv":1456,"upper":1385716,"lower":1371383,"count":1456,"preSum":13104},{"ndv":1456,"upper":1403558,"lower":1385717,"count":1456,"preSum":14560},{"ndv":1456,"upper":1419965,"lower":1403559,"count":1456,"preSum":16016},{"ndv":1456,"upper":1434761,"lower":1419966,"count":1456,"preSum":17472},{"ndv":1456,"upper":1450174,"lower":1434763,"count":1456,"preSum":18928},{"ndv":1456,"upper":1466685,"lower":1450175,"count":1456,"preSum":20384},{"ndv":1456,"upper":1482496,"lower":1466686,"count":1456,"preSum":21840},{"ndv":1456,"upper":1498128,"lower":1482497,"count":1456,"preSum":23296},{"ndv":1456,"upper":1513440,"lower":1498129,"count":1456,"preSum":24752},{"ndv":1456,"upper":1531458,"lower":1513441,"count":1456,"preSum":26208},{"ndv":1456,"upper":1546068,"lower":1531460,"count":1456,"preSum":27664},{"ndv":1456,"upper":1563642,"lower":1546069,"count":1456,"preSum":29120},{"ndv":1456,"upper":1580627,"lower":1563643,"count":1456,"preSum":30576},{"ndv":1456,"upper":1598500,"lower":1580628,"count":1456,"preSum":32032},{"ndv":1456,"upper":1615106,"lower":1598502,"count":1456,"preSum":33488},{"ndv":1456,"upper":1657426,"lower":1615108,"count":1456,"preSum":34944},{"ndv":1456,"upper":1674443,"lower":1657427,"count":1456,"preSum":36400},{"ndv":1456,"upper":1691205,"lower":1674448,"count":1456,"preSum":37856},{"ndv":1456,"upper":1709915,"lower":1691206,"count":1456,"preSum":39312},{"ndv":1456,"upper":1727340,"lower":1709916,"count":1456,"preSum":40768},{"ndv":1456,"upper":1746149,"lower":1727341,"count":1456,"preSum":42224},{"ndv":1456,"upper":1763074,"lower":1746150,"count":1456,"preSum":43680},{"ndv":1456,"upper":1778626,"lower":1763075,"count":1456,"preSum":45136},{"ndv":1456,"upper":1793008,"lower":1778627,"count":1456,"preSum":46592},{"ndv":1456,"upper":1811039,"lower":1793009,"count":1456,"preSum":48048},{"ndv":1456,"upper":1828246,"lower":1811040,"count":1456,"preSum":49504},{"ndv":1456,"upper":1844287,"lower":1828247,"count":1456,"preSum":50960},{"ndv":1456,"upper":1860839,"lower":1844288,"count":1456,"preSum":52416},{"ndv":1456,"upper":1879377,"lower":1860840,"count":1456,"preSum":53872},{"ndv":1456,"upper":1894306,"lower":1879378,"count":1456,"preSum":55328},{"ndv":1456,"upper":1910663,"lower":1894307,"count":1456,"preSum":56784},{"ndv":1456,"upper":1926904,"lower":1910664,"count":1456,"preSum":58240},{"ndv":1456,"upper":1944096,"lower":1926905,"count":1456,"preSum":59696},{"ndv":1456,"upper":1960483,"lower":1944097,"count":1456,"preSum":61152},{"ndv":1456,"upper":1976464,"lower":1960484,"count":1456,"preSum":62608},{"ndv":1456,"upper":1996513,"lower":1976465,"count":1456,"preSum":64064},{"ndv":1456,"upper":2016620,"lower":1996514,"count":1456,"preSum":65520},{"ndv":1456,"upper":2036351,"lower":2016621,"count":1456,"preSum":66976},{"ndv":1456,"upper":2049698,"lower":2036352,"count":1456,"preSum":68432},{"ndv":1456,"upper":2065539,"lower":2049699,"count":1456,"preSum":69888},{"ndv":1456,"upper":2083841,"lower":2065540,"count":1456,"preSum":71344},{"ndv":1456,"upper":2098634,"lower":2083842,"count":1456,"preSum":72800},{"ndv":1456,"upper":2114271,"lower":2098635,"count":1456,"preSum":74256},{"ndv":1456,"upper":2131621,"lower":2114272,"count":1456,"preSum":75712},{"ndv":1456,"upper":2147909,"lower":2131622,"count":1456,"preSum":77168},{"ndv":1456,"upper":2164402,"lower":2148111,"count":1456,"preSum":78624},{"ndv":1456,"upper":2179171,"lower":2164404,"count":1456,"preSum":80080},{"ndv":1456,"upper":2196852,"lower":2179172,"count":1456,"preSum":81536},{"ndv":1456,"upper":2210263,"lower":2196854,"count":1456,"preSum":82992},{"ndv":1456,"upper":2226144,"lower":2210264,"count":1456,"preSum":84448},{"ndv":1456,"upper":2242738,"lower":2226145,"count":1456,"preSum":85904},{"ndv":1456,"upper":2257641,"lower":2242740,"count":1456,"preSum":87360},{"ndv":1456,"upper":2276328,"lower":2257642,"count":1456,"preSum":88816},{"ndv":1456,"upper":2293673,"lower":2276329,"count":1456,"preSum":90272},{"ndv":1411,"upper":2456791,"lower":2293674,"count":1411,"preSum":91728}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,0,0.11565614),('jala_wms_prod','item','imageid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[96],"valueArr":[""],"type":"String","sampleRate":1.0}',93043,0.11565614),('jala_wms_prod','item','imported',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','inboundfrozendays',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','inshelflifests',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93],"valueArr":[""],"type":"String","sampleRate":1.0}',93046,0.11565614),('jala_wms_prod','item','interorexter',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93],"valueArr":[""],"type":"String","sampleRate":1.0}',93046,0.11565614),('jala_wms_prod','item','iqcmethod',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','iqcrulecode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[42],"valueArr":[""],"type":"String","sampleRate":1.0}',93097,0.11565614),('jala_wms_prod','item','isgift',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','itemattribute1',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemattribute2',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemattribute3',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemattribute4',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemattribute5',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemattribute6',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemattribute7',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemattribute8',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemattributetemplatecode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemcategory1',8,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[35514,7126,7163,4598,20661,15733,35,1025],"valueArr":["Z001","Z002","Z003","Z004","Z005","Z006","Z007","Z008"],"type":"String","sampleRate":1.0}',1284,0.11565614),('jala_wms_prod','item','itemcategory2',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemcategory3',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemcategory4',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','itemcolor',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[729],"valueArr":[""],"type":"String","sampleRate":1.0}',92410,0.11565614),('jala_wms_prod','item','itemexpirationdate',8,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"1851045417546940416","lower":"1851045417546940416","count":2,"preSum":0}],"maxBucketSize":64,"type":"Date","sampleRate":1.0}','{"countArr":[92944,12,40,128,3,5,5],"valueArr":[-1,1851067407779495936,1851115786291118080,1851186155035295744,1851397261267828736,1851537998756184064,1851540197779439616],"type":"Date","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','itemgroup',155,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"10101","lower":"","count":1255,"preSum":0},{"ndv":2,"upper":"10103","lower":"10102","count":740,"preSum":1255},{"ndv":3,"upper":"10107","lower":"10104","count":1016,"preSum":1995},{"ndv":3,"upper":"10111","lower":"10108","count":493,"preSum":3011},{"ndv":1,"upper":"10112","lower":"10112","count":1103,"preSum":3504},{"ndv":3,"upper":"10115","lower":"10113","count":950,"preSum":4607},{"ndv":6,"upper":"10121","lower":"10116","count":494,"preSum":5557},{"ndv":1,"upper":"10122","lower":"10122","count":1323,"preSum":6051},{"ndv":2,"upper":"10124","lower":"10123","count":1388,"preSum":7374},{"ndv":11,"upper":"10202","lower":"10125","count":466,"preSum":8762},{"ndv":7,"upper":"10401","lower":"10203","count":577,"preSum":9228},{"ndv":1,"upper":"10405","lower":"10405","count":1029,"preSum":9805},{"ndv":3,"upper":"10408","lower":"10406","count":481,"preSum":10834},{"ndv":1,"upper":"10409","lower":"10409","count":732,"preSum":11315},{"ndv":1,"upper":"10410","lower":"10410","count":498,"preSum":12047},{"ndv":5,"upper":"10602","lower":"10501","count":1299,"preSum":12545},{"ndv":1,"upper":"19999","lower":"19999","count":1127,"preSum":13844},{"ndv":1,"upper":"20102","lower":"20102","count":458,"preSum":14971},{"ndv":2,"upper":"20201","lower":"20103","count":588,"preSum":15429},{"ndv":2,"upper":"20203","lower":"20202","count":483,"preSum":16017},{"ndv":4,"upper":"20302","lower":"20204","count":526,"preSum":16500},{"ndv":6,"upper":"20402","lower":"20303","count":910,"preSum":17026},{"ndv":3,"upper":"20501","lower":"20403","count":460,"preSum":17936},{"ndv":4,"upper":"304","lower":"20502","count":1140,"preSum":18396},{"ndv":7,"upper":"499","lower":"305","count":1265,"preSum":19536},{"ndv":1,"upper":"502","lower":"502","count":747,"preSum":20801},{"ndv":2,"upper":"506","lower":"504","count":914,"preSum":21548},{"ndv":4,"upper":"60103","lower":"6","count":588,"preSum":22462},{"ndv":5,"upper":"60108","lower":"60104","count":557,"preSum":23050},{"ndv":4,"upper":"60201","lower":"60110","count":478,"preSum":23607},{"ndv":1,"upper":"60202","lower":"60202","count":673,"preSum":24085},{"ndv":3,"upper":"60206","lower":"60204","count":817,"preSum":24758},{"ndv":5,"upper":"60211","lower":"60207","count":501,"preSum":25575},{"ndv":1,"upper":"60213","lower":"60213","count":649,"preSum":26076},{"ndv":5,"upper":"60303","lower":"60214","count":521,"preSum":26725},{"ndv":3,"upper":"60401","lower":"60304","count":841,"preSum":27246},{"ndv":7,"upper":"80102","lower":"60402","count":476,"preSum":28087},{"ndv":9,"upper":"80301","lower":"80103","count":508,"preSum":28563},{"ndv":5,"upper":"ZB16","lower":"80302","count":142,"preSum":29071}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[6730,2800,3488,4250,2652,3039,1859,2810,12342,3081,3391,4739,3445,1430],"valueArr":["10402","10403","10404","10601","20101","301","302","4","501","503","505","60203","60305","69999"],"type":"String","sampleRate":1.0}',7870,0.11565614),('jala_wms_prod','item','itemsize',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[729],"valueArr":[""],"type":"String","sampleRate":1.0}',92410,0.11565614),('jala_wms_prod','item','itemstyle',1074,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":23,"upper":"1.5mL","lower":"(1.5mL+26mL)*6片","count":439,"preSum":0},{"ndv":13,"upper":"100mL","lower":"1.5mL*1片","count":292,"preSum":439},{"ndv":6,"upper":"10片","lower":"100件套","count":310,"preSum":731},{"ndv":9,"upper":"120mL","lower":"110G","count":414,"preSum":1041},{"ndv":16,"upper":"14g","lower":"120ML+40ML+60MLML","count":326,"preSum":1455},{"ndv":11,"upper":"15mL","lower":"14mL","count":312,"preSum":1781},{"ndv":14,"upper":"180mL","lower":"15件套","count":277,"preSum":2093},{"ndv":23,"upper":"1:108:48","lower":"18g","count":290,"preSum":2370},{"ndv":18,"upper":"1:120:30:6","lower":"1:108:4:12","count":277,"preSum":2660},{"ndv":12,"upper":"1:126:20","lower":"1:120:48","count":319,"preSum":2937},{"ndv":18,"upper":"1:130:8:6","lower":"1:126:48","count":296,"preSum":3256},{"ndv":24,"upper":"1:144:4:6","lower":"1:132:12","count":301,"preSum":3552},{"ndv":34,"upper":"1:180:20","lower":"1:144:6","count":288,"preSum":3853},{"ndv":17,"upper":"1:20:12","lower":"1:180:30:6","count":279,"preSum":4141},{"ndv":26,"upper":"1:260:8:6","lower":"1:20:30","count":337,"preSum":4420},{"ndv":19,"upper":"1:30:20","lower":"1:280:4:12","count":297,"preSum":4757},{"ndv":11,"upper":"1:32:12","lower":"1:30:20:10","count":277,"preSum":5054},{"ndv":19,"upper":"1:35:6","lower":"1:32:24","count":303,"preSum":5331},{"ndv":18,"upper":"1:36:8:6","lower":"1:35:8","count":313,"preSum":5634},{"ndv":12,"upper":"1:40:60","lower":"1:40:10","count":285,"preSum":5947},{"ndv":10,"upper":"1:42:18","lower":"1:40:8","count":304,"preSum":6232},{"ndv":11,"upper":"1:42:8","lower":"1:42:20","count":280,"preSum":6536},{"ndv":15,"upper":"1:48:10","lower":"1:42:8:6","count":281,"preSum":6816},{"ndv":7,"upper":"1:48:48","lower":"1:48:12","count":288,"preSum":7097},{"ndv":10,"upper":"1:49:25","lower":"1:48:4:12","count":280,"preSum":7385},{"ndv":15,"upper":"1:50:60","lower":"1:49:32","count":383,"preSum":7665},{"ndv":16,"upper":"1:56:12","lower":"1:50:95","count":277,"preSum":8048},{"ndv":11,"upper":"1:56:6","lower":"1:56:18","count":397,"preSum":8325},{"ndv":12,"upper":"1:60:6","lower":"1:56:8","count":297,"preSum":8722},{"ndv":8,"upper":"1:63:48","lower":"1:60:6:4","count":341,"preSum":9019},{"ndv":13,"upper":"1:64:48","lower":"1:63:4:12","count":339,"preSum":9360},{"ndv":16,"upper":"1:70:48","lower":"1:64:4:12","count":280,"preSum":9699},{"ndv":12,"upper":"1:72:24","lower":"1:70:4:12","count":277,"preSum":9979},{"ndv":6,"upper":"1:72:4:12","lower":"1:72:280","count":291,"preSum":10256},{"ndv":19,"upper":"1:80:24","lower":"1:72:4:6","count":290,"preSum":10547},{"ndv":6,"upper":"1:80:8","lower":"1:80:30:6","count":283,"preSum":10837},{"ndv":11,"upper":"1:84:30:6","lower":"1:80:8:6","count":373,"preSum":11120},{"ndv":18,"upper":"1:90:48","lower":"1:84:48","count":319,"preSum":11493},{"ndv":12,"upper":"1:96:20","lower":"1:90:4:12","count":290,"preSum":11812},{"ndv":18,"upper":"1mL","lower":"1:96:24","count":291,"preSum":12102},{"ndv":19,"upper":"200mL","lower":"1PCS","count":298,"preSum":12393},{"ndv":5,"upper":"20片","lower":"20g","count":277,"preSum":12691},{"ndv":29,"upper":"28mL","lower":"21件套","count":323,"preSum":12968},{"ndv":16,"upper":"2件套","lower":"28mL*1","count":387,"preSum":13291},{"ndv":9,"upper":"300mL","lower":"2支","count":447,"preSum":13678},{"ndv":14,"upper":"33ml*1片","lower":"30g","count":310,"preSum":14125},{"ndv":14,"upper":"3PCS","lower":"33ml*5片","count":281,"preSum":14435},{"ndv":9,"upper":"40mL","lower":"3支","count":361,"preSum":14716},{"ndv":17,"upper":"4件套","lower":"40片","count":353,"preSum":15077},{"ndv":23,"upper":"5g","lower":"4支","count":455,"preSum":15430},{"ndv":6,"upper":"5件套","lower":"5mL","count":295,"preSum":15885},{"ndv":13,"upper":"6g","lower":"5支","count":387,"preSum":16180},{"ndv":7,"upper":"7.5mL","lower":"6g*1片","count":286,"preSum":16567},{"ndv":18,"upper":"8g","lower":"7.93981481481481E-","count":292,"preSum":16853},{"ndv":2,"upper":"8件套","lower":"8mL","count":310,"preSum":17145},{"ndv":20,"upper":"(5mL+0.14g)*1支","lower":"8片","count":211,"preSum":17455}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[68769,1427,302,286,1188,222,253,308,474,518,302,408,230,346],"valueArr":["","0","15g","1:1000:480","1:1000:500","1:42:48","1:56:48","1片","3.2g","30mL","3件套","50g","50mL","5片"],"type":"String","sampleRate":1.0}',440,0.11565614),('jala_wms_prod','item','lastcyclecountdate',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','lastupdated',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','lastupdatedby',16,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"gth","lower":"gth","count":1,"preSum":0},{"ndv":1,"upper":"HQP","lower":"HQP","count":1,"preSum":1},{"ndv":1,"upper":"zhixilong","lower":"zhixilong","count":2,"preSum":2}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[4564,4007,34,11,13,83234,1262,3,7],"valueArr":["TTXLHJ","XCY","XCY1","ZXL","ZY","api","jx","lhj","lyg"],"type":"String","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','listprice',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','locatingrule',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[42],"valueArr":[""],"type":"String","sampleRate":1.0}',93097,0.11565614),('jala_wms_prod','item','maintained',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','maintainperiod',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','maintainsts',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','manufacturer',6,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[85711,6099,10,31,6,8],"valueArr":["","1000","2010","2020","2030","2050"],"type":"String","sampleRate":1.0}',1274,0.11565614),('jala_wms_prod','item','manufacturerdeletion',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[91856],"valueArr":[0],"type":"Int","sampleRate":1.0}',1283,0.11565614),('jala_wms_prod','item','minorderqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','minshelflife',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','minshelflifedays',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','minshelflifests',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93],"valueArr":[""],"type":"String","sampleRate":1.0}',93046,0.11565614),('jala_wms_prod','item','monthstoexpire',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','movementclass',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[96],"valueArr":[""],"type":"String","sampleRate":1.0}',93043,0.11565614),('jala_wms_prod','item','name',74858,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":667,"upper":"2014美素春季POP插页","lower":"\\tEMOSMART L19","count":1451,"preSum":0},{"ndv":676,"upper":"202#外箱","lower":"2014美素春季促销海报","count":1451,"preSum":1451},{"ndv":602,"upper":"21257","lower":"202#格档","count":1455,"preSum":2902},{"ndv":679,"upper":"22392","lower":"21263","count":1450,"preSum":4357},{"ndv":750,"upper":"28296","lower":"22393","count":1450,"preSum":5807},{"ndv":624,"upper":"29090","lower":"28297","count":1450,"preSum":7257},{"ndv":664,"upper":"COMO任我闪耀多用彩妆蜜中包","lower":"29091","count":1450,"preSum":8707},{"ndv":605,"upper":"COMO经典刻印腮红#03午夜私语裸桃半成品","lower":"COMO任我闪耀多用彩妆蜜内塞","count":1451,"preSum":10157},{"ndv":655,"upper":"TRIETHANOLAMINE, 99%(三乙醇胺)","lower":"COMO经典刻印腮红#03午夜私语裸桃容器底标","count":1453,"preSum":11608},{"ndv":687,"upper":"伽蓝快递箱04#","lower":"TWEEN-80-LQ-SG","count":1453,"preSum":13061},{"ndv":685,"upper":"刮刮卡-自然堂无瑕持妆冰肌粉底液(滋润型)#02柔粉色30mL","lower":"伽蓝快递箱05#","count":1450,"preSum":14514},{"ndv":651,"upper":"小玫瑰娇嫩滋养三件礼盒装下盖(2016版)","lower":"刮刮卡-自然堂无瑕持妆冰肌粉底液(滋润型)#03米白色30mL","count":1453,"preSum":15964},{"ndv":618,"upper":"春夏201903张艺兴明信片(工厂版)","lower":"小玫瑰娇嫩滋养三件礼盒装吸塑托(2016版)","count":1451,"preSum":17417},{"ndv":638,"upper":"春夏南非复活草恒润保湿乳110mL(新法规)裸装品","lower":"春夏201903版CS渠道防晒二点陈列架","count":1451,"preSum":18868},{"ndv":641,"upper":"春夏巴西红樱桃亮采补水面膜26mL铝箔袋","lower":"春夏南非复活草恒润保湿乳110mL(过渡版)裸装品","count":1453,"preSum":20319},{"ndv":604,"upper":"春夏玻尿酸高保湿三步曲挚爱套装吸塑托","lower":"春夏巴西红樱桃亮采补水面膜26mL铝箔袋-02代","count":1451,"preSum":21772},{"ndv":572,"upper":"春夏防晒套盒(MT专供)吸塑托","lower":"春夏玻尿酸高保湿三步曲挚爱套装花盒","count":1454,"preSum":23223},{"ndv":610,"upper":"植物智慧环保购物纸袋(201808版)","lower":"春夏防晒小花伞礼盒SPF30PA+++(MT专供/屈臣氏版本)","count":1451,"preSum":24677},{"ndv":615,"upper":"植物智慧舒缓美白水漾面膜26mL铝箔袋","lower":"植物智慧甜扁桃保湿肌底面膜28mL×5片装","count":1450,"preSum":26128},{"ndv":636,"upper":"活泉补水控油洁面膏(泡沫型)柜台试用品简装盒(201506)","lower":"植物智慧舒缓美白水漾面膜26mL铝箔袋(2023版)","count":1451,"preSum":27578},{"ndv":688,"upper":"珀芙研壳聚糖屏障修复面膜半成品","lower":"活泉补水控油洁面膏(泡沫型)柜台陈列假样简装盒","count":1450,"preSum":29029},{"ndv":646,"upper":"瑰蜜凝颜三件礼盒装说明书","lower":"珀芙研壳聚糖敷料 1片装","count":1450,"preSum":30479},{"ndv":627,"upper":"纯粹滋润冰肌水(凝润型)160ml瓶身(201309)","lower":"瑰蜜凝颜三件礼盒装说明书(第三版)","count":1452,"preSum":31929},{"ndv":657,"upper":"美素7ml/8.5ml装精华瓶金色盖","lower":"纯粹滋润冰肌水(凝润型)160ml花盒(201312)","count":1451,"preSum":33381},{"ndv":650,"upper":"美素初颜弹力精华液40mL","lower":"美素7ml/8.5ml装精华瓶银色盖","count":1450,"preSum":34832},{"ndv":653,"upper":"美素小玫瑰蜜养淡纹乳液120mL玻璃瓶","lower":"美素初颜弹力精华液40mL假样","count":1452,"preSum":36282},{"ndv":638,"upper":"美素沉鱼落雁闭月羞花芊芊玉手礼盒内衬-第03代","lower":"美素小玫瑰蜜养淡纹乳液120mL花盒","count":1450,"preSum":37734},{"ndv":607,"upper":"美素瑰蜜凝颜娇嫩滋养精华霜1.5g袋装裸装品","lower":"美素沉鱼落雁闭月羞花芊芊玉手礼盒吸塑托","count":1451,"preSum":39184},{"ndv":662,"upper":"美素腮红&眼影#18试用装(暂定名)","lower":"美素瑰蜜凝颜娇嫩滋养精华霜15g(网络专供)中小样裸装品","count":1451,"preSum":40635},{"ndv":673,"upper":"美素铂金抚纹冻干精华液(精华水)半成品","lower":"美素腮红&眼影#19(暂定名)","count":1450,"preSum":42086},{"ndv":655,"upper":"自然堂2012版沃尔玛杆子灯","lower":"美素铂金紧肤抗皱精华油(新法规)30mL","count":1450,"preSum":43536},{"ndv":664,"upper":"自然堂2019水散粉重点品陈列道具(百货1.6米通用)","lower":"自然堂2013年9月商场1.5M护肤陈列架","count":1450,"preSum":44986},{"ndv":670,"upper":"自然堂2022中文LOGO牌(黑字)","lower":"自然堂2019水散粉面板(彩妆背柜通用)","count":1451,"preSum":46436},{"ndv":603,"upper":"自然堂euspa闻花听雨护发素300mL透明后标贴+黑色圆瓶","lower":"自然堂2022亚克力LOGO立牌(600mm)","count":1450,"preSum":47887},{"ndv":620,"upper":"自然堂会员俱乐部单页(201811版大)","lower":"自然堂euspa闻花听雨护发素30mL圆点软管+盖","count":1451,"preSum":49337},{"ndv":607,"upper":"自然堂凝时精华鲜注面膜铝箔袋-02代","lower":"自然堂会员俱乐部单页(201811版小)","count":1450,"preSum":50788},{"ndv":606,"upper":"自然堂凝时鲜颜肌活修护三件套","lower":"自然堂凝时系列DM卡(2023)","count":1450,"preSum":52238},{"ndv":643,"upper":"自然堂凝时鲜颜肌活眼部精华乳(新装箱)4mL中小样","lower":"自然堂凝时鲜颜肌活修护三件套(201707霜版)中小样","count":1450,"preSum":53688},{"ndv":619,"upper":"自然堂喜雪微精华高保湿体验装三件套(乳版)贴纸","lower":"自然堂凝时鲜颜肌活眼部精华乳18mL","count":1451,"preSum":55138},{"ndv":632,"upper":"自然堂头皮护理控油舒爽去屑洗发露550mL塑料瓶身(经销商大会版)","lower":"自然堂喜雪微精华高保湿体验装三件套(霜版)-背卡","count":1451,"preSum":56589},{"ndv":570,"upper":"自然堂定制双管控油抑痘精华液(油性痘痘肌)O5瓶贴","lower":"自然堂头皮护理控油舒爽去屑洗发露550mL泵头","count":1451,"preSum":58040},{"ndv":629,"upper":"自然堂弹嫩精华油L形产品小立牌","lower":"自然堂定制双管控油抑痘精华液(油性痘痘肌)O6 28mL+8mL","count":1451,"preSum":59491},{"ndv":539,"upper":"自然堂微精华喜雪高保湿水(2023版)150mL","lower":"自然堂弹嫩精华面膜(新规版)30mL 1片装","count":1451,"preSum":60942},{"ndv":600,"upper":"自然堂新彩妆千禧粉乐园路演冰肌粉底液模型(小)","lower":"自然堂微精华喜雪高保湿水(售卖版)20mL","count":1450,"preSum":62393},{"ndv":643,"upper":"自然堂气垫BB堆头插卡-美妆店渠道","lower":"自然堂新彩妆千禧粉乐园路演化妆箱","count":1450,"preSum":63843},{"ndv":587,"upper":"自然堂活泉深层补水按摩乳半成品","lower":"自然堂气垫BB蜂窝板纸质落地架-全渠道","count":1451,"preSum":65293},{"ndv":613,"upper":"自然堂炫彩盈润高显色唇膏#01茶花粉3.2g条形码标贴","lower":"自然堂活泉深层补水调理精华液(201209)裸装品","count":1451,"preSum":66744},{"ndv":603,"upper":"自然堂烈日防水防汗防晒乳钜惠装2+5","lower":"自然堂炫彩盈润高显色唇膏#01茶花粉3.2g裸装品","count":1452,"preSum":68195},{"ndv":598,"upper":"自然堂男士保湿精华眼霜瓶身(201412)","lower":"自然堂烈日防水防汗防晒乳钜惠装2+5花盒","count":1452,"preSum":69647},{"ndv":612,"upper":"自然堂男士喜马拉雅绿泥控油洁面膏50g(201801)中小样","lower":"自然堂男士保湿精华眼霜瓶身(201611)","count":1450,"preSum":71099},{"ndv":642,"upper":"自然堂百货渠道16版2.7米护+彩陈列架--嘀嗒唇膏笔面板(2018)","lower":"自然堂男士喜马拉雅绿泥控油洁面膏50g(201801)中小样裸装品","count":1450,"preSum":72549},{"ndv":607,"upper":"自然堂纯粹滋润冰肌水(凝润型)(升级版)20mL中小样","lower":"自然堂百货渠道16版2.7米护+彩陈列架--底妆面板(2018)","count":1450,"preSum":73999},{"ndv":637,"upper":"自然堂花萃漾泽养护唇膏#01色3.5g试用装","lower":"自然堂纯粹滋润冰肌水(凝润型)(升级版)60mL中小样","count":1450,"preSum":75449},{"ndv":614,"upper":"自然堂酵母原液修护安瓶精华液背卡","lower":"自然堂花萃漾泽养护唇膏#01色3.5g非卖商品","count":1451,"preSum":76899},{"ndv":634,"upper":"自然堂雪域澎湃保湿钜惠限定装(印尼版)","lower":"自然堂酵母原液修护安瓶精华液陈列假样","count":1451,"preSum":78350},{"ndv":619,"upper":"自然堂雪域精粹纯粹滋润乳液90mL","lower":"自然堂雪域澎湃保湿钜惠限定装(国际版))花盒标贴","count":1454,"preSum":79801},{"ndv":602,"upper":"自然堂雪松精油御龄大礼包花盒","lower":"自然堂雪域精粹纯粹滋润乳液90ml&120ml外罩","count":1451,"preSum":81255},{"ndv":561,"upper":"自然堂雪润晶采裸透气垫霜15g(05自然粉)底贴","lower":"自然堂雪松精油御龄精华优享装(2020)吸塑托","count":1450,"preSum":82706},{"ndv":611,"upper":"自然堂雪润皙白晶采霜(滋润型)(201610)花盒-第02代","lower":"自然堂雪润晶采裸透气垫霜15g(04#/05#)海绵 ","count":1450,"preSum":84156},{"ndv":595,"upper":"自然堂黑晶亮采眼贴膜半成品","lower":"自然堂雪润皙白晶采霜(滋润型)(201610)花盒-第03代","count":1453,"preSum":85606},{"ndv":677,"upper":"资材Z-T-1027#专用格挡","lower":"自然堂黑晶亮采眼贴膜水半成品","count":1450,"preSum":87059},{"ndv":622,"upper":"资材Z-T-833#通用纸箱","lower":"资材Z-T-1027#通用纸箱","count":1451,"preSum":88509},{"ndv":662,"upper":"雪域精粹纯粹滋润精华液瓶身","lower":"资材Z-T-835#通用纸箱","count":1450,"preSum":89960},{"ndv":636,"upper":"龙胆提取物","lower":"雪域精粹纯粹滋润精华液瓶身(201312)","count":1357,"preSum":91410}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[194,18,18,25,19,17,25,17,18,21],"valueArr":["待分配","春夏芬兰海莓果滋润倍护乳110mL","自然堂冰川水水光面膜28mL 1片装","自然堂凝时鲜颜肌活乳液半成品","自然堂凝润滋养护手霜半成品","自然堂抗皱两步曲面膜半成品","自然堂男士喜马拉雅矿岩控油露半成品","自然堂雪域百合补水面膜26mL 1片装","自然堂雪松精油活颜御龄明眸眼霜15g试用装","自然堂雪茶平衡保湿面膜26mL 1片装"],"type":"String","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','nameen',10,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"5027004.01","lower":"5027004.01","count":1,"preSum":0},{"ndv":1,"upper":"5027291.01","lower":"5027291.01","count":1,"preSum":1}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[91863],"valueArr":[""],"type":"String","sampleRate":1.0}',1274,0.11565614),('jala_wms_prod','item','needaudited',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','neediqc',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','netprice',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','overlaprate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','overshelflifests',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93],"valueArr":[""],"type":"String","sampleRate":1.0}',93046,0.11565614),('jala_wms_prod','item','packagestyle',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[3115],"valueArr":[""],"type":"String","sampleRate":1.0}',90024,0.11565614),('jala_wms_prod','item','packingclass',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[726,33],"valueArr":["","CS"],"type":"String","sampleRate":1.0}',92380,0.11565614),('jala_wms_prod','item','parentcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('jala_wms_prod','item','placeoforigin',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[96],"valueArr":[""],"type":"String","sampleRate":1.0}',93043,0.11565614),('jala_wms_prod','item','pldesc',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93139],"valueArr":["托"],"type":"String","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','plheight',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','pllength',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','plqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','plvolume',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','plweight',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','plwidth',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','pos',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[96],"valueArr":[""],"type":"String","sampleRate":1.0}',93043,0.11565614),('jala_wms_prod','item','preimportserialnum',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','productioniqc',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','productionstoragelocation',10,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[85793,3308,327,457,32,687,473,649,78,52],"valueArr":["","2101","3101","3102","4101","D001","D002","D003","D017","W007"],"type":"String","sampleRate":1.0}',1283,0.11565614),('jala_wms_prod','item','productline',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[96],"valueArr":[""],"type":"String","sampleRate":1.0}',93043,0.11565614),('jala_wms_prod','item','purchaseiqc',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','purchasestoragelocation',10,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[85793,32,3308,327,457,687,473,649,78,52],"valueArr":["","1101","2101","3101","3102","D001","D002","D003","D017","W007"],"type":"String","sampleRate":1.0}',1283,0.11565614),('jala_wms_prod','item','qtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','replenishmentrule',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[42],"valueArr":[""],"type":"String","sampleRate":1.0}',93097,0.11565614),('jala_wms_prod','item','serialnumtype',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[1],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','snmanagement',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[85221,6635],"valueArr":["0","1"],"type":"String","sampleRate":1.0}',1283,0.11565614),('jala_wms_prod','item','snmangement',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','sntemplatecode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93],"valueArr":[""],"type":"String","sampleRate":1.0}',93046,0.11565614),('jala_wms_prod','item','sourceerp',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','specialdrugs',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','specialmanagementdrugs',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','status',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[1],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','storagetemplevel',7,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[87094,252,111,55,1816,409,125],"valueArr":["","0-30℃运输","0-35℃运输","null","无","避免零下运输","限量运输(香水、气雾罐、酒精凝胶类)"],"type":"String","sampleRate":1.0}',3277,0.11565614),('jala_wms_prod','item','templevel',7,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"避免零下存储","lower":"避免零下存储","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[89033,331,54,1858,125,407],"valueArr":["","0-30℃储存","null","无","甲类仓库或限量储存(香水、气雾罐、酒精凝胶类)","避免零下储存"],"type":"String","sampleRate":1.0}',1329,0.11565614),('jala_wms_prod','item','text',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[91856],"valueArr":[""],"type":"String","sampleRate":1.0}',1283,0.11565614),('jala_wms_prod','item','threelevelclass',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93],"valueArr":[""],"type":"String","sampleRate":1.0}',93046,0.11565614),('jala_wms_prod','item','thumbimageid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[96],"valueArr":[""],"type":"String","sampleRate":1.0}',93043,0.11565614),('jala_wms_prod','item','tihi',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','trackagingdate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','trackbatch',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[86985,6154],"valueArr":[0,1],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','trackexpirationdate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','trackinv',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[1],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','tracklot',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','tracklpn',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":0,"lower":0,"count":1,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93138],"valueArr":[1],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','trackmanufacturedate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','trackserialnum',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[85225,4853,3061],"valueArr":[0,2,3],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','turnoverrate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','unitdesc',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93139],"valueArr":["个"],"type":"String","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','unitheight',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','unitlength',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','unitname',17,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"G","lower":"G","count":1,"preSum":0},{"ndv":1,"upper":"HE","lower":"HE","count":1,"preSum":1},{"ndv":1,"upper":"PC","lower":"PC","count":1,"preSum":2}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[47,15162,215,233,16,70881,5299],"valueArr":["GON","KG","M","M2","PAC","PCS","TAO"],"type":"String","sampleRate":1.0}',1283,0.11565614),('jala_wms_prod','item','unitname1',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"ST2","lower":"ST2","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[91855],"valueArr":[""],"type":"String","sampleRate":1.0}',1283,0.11565614),('jala_wms_prod','item','unitname2',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[91856],"valueArr":[""],"type":"String","sampleRate":1.0}',1283,0.11565614),('jala_wms_prod','item','unitname3',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[91856],"valueArr":[""],"type":"String","sampleRate":1.0}',1283,0.11565614),('jala_wms_prod','item','unitqty',17,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":15,"lower":15,"count":1,"preSum":0},{"ndv":1,"upper":20,"lower":20,"count":1,"preSum":1},{"ndv":1,"upper":50,"lower":50,"count":1,"preSum":2}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[344,92719,31,8,8,7,7,12],"valueArr":[0,1,3,6,10,12,24,30],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','unitvolume',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','unitweight',3631,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":85,"upper":3.0000,"lower":0.0220,"count":254,"preSum":0},{"ndv":63,"upper":4.6430,"lower":3.0160,"count":251,"preSum":254},{"ndv":54,"upper":6.0000,"lower":4.6670,"count":248,"preSum":505},{"ndv":64,"upper":8.5500,"lower":6.0370,"count":245,"preSum":753},{"ndv":43,"upper":11.0000,"lower":8.6500,"count":251,"preSum":998},{"ndv":51,"upper":14.0000,"lower":11.1110,"count":246,"preSum":1249},{"ndv":52,"upper":16.6670,"lower":14.0910,"count":244,"preSum":1495},{"ndv":52,"upper":19.9500,"lower":16.6790,"count":244,"preSum":1739},{"ndv":40,"upper":22.7800,"lower":19.9540,"count":268,"preSum":1983},{"ndv":36,"upper":26.0000,"lower":22.8000,"count":244,"preSum":2251},{"ndv":36,"upper":29.1670,"lower":26.0420,"count":260,"preSum":2495},{"ndv":43,"upper":33.7500,"lower":29.2000,"count":249,"preSum":2755},{"ndv":42,"upper":36.6670,"lower":33.7920,"count":272,"preSum":3004},{"ndv":30,"upper":39.4440,"lower":36.8060,"count":283,"preSum":3276},{"ndv":31,"upper":42.7500,"lower":39.5000,"count":244,"preSum":3559},{"ndv":32,"upper":47.2220,"lower":42.7780,"count":249,"preSum":3803},{"ndv":43,"upper":53.6250,"lower":47.2500,"count":244,"preSum":4052},{"ndv":52,"upper":60.7500,"lower":53.6500,"count":248,"preSum":4296},{"ndv":43,"upper":67.7770,"lower":60.8700,"count":246,"preSum":4544},{"ndv":34,"upper":72.9160,"lower":67.8570,"count":252,"preSum":4790},{"ndv":41,"upper":80.5000,"lower":72.9170,"count":246,"preSum":5042},{"ndv":40,"upper":89.5830,"lower":80.6250,"count":271,"preSum":5288},{"ndv":37,"upper":97.9170,"lower":90.0000,"count":249,"preSum":5559},{"ndv":34,"upper":106.2500,"lower":98.0000,"count":263,"preSum":5808},{"ndv":45,"upper":118.7500,"lower":106.4160,"count":253,"preSum":6071},{"ndv":33,"upper":129.0000,"lower":119.4440,"count":246,"preSum":6324},{"ndv":19,"upper":137.5000,"lower":129.1660,"count":256,"preSum":6570},{"ndv":27,"upper":147.9170,"lower":138.1940,"count":254,"preSum":6826},{"ndv":31,"upper":160.4170,"lower":147.9200,"count":254,"preSum":7080},{"ndv":34,"upper":170.6670,"lower":160.5000,"count":245,"preSum":7334},{"ndv":30,"upper":181.2500,"lower":170.8000,"count":260,"preSum":7579},{"ndv":26,"upper":190.0000,"lower":182.2920,"count":246,"preSum":7839},{"ndv":18,"upper":200.0000,"lower":190.6250,"count":272,"preSum":8085},{"ndv":30,"upper":214.5830,"lower":200.5560,"count":249,"preSum":8357},{"ndv":21,"upper":223.0000,"lower":214.6670,"count":244,"preSum":8606},{"ndv":22,"upper":233.1250,"lower":223.3000,"count":244,"preSum":8850},{"ndv":17,"upper":240.6250,"lower":233.3300,"count":247,"preSum":9094},{"ndv":26,"upper":254.1660,"lower":241.1660,"count":265,"preSum":9341},{"ndv":30,"upper":270.8330,"lower":254.1670,"count":272,"preSum":9606},{"ndv":32,"upper":287.5000,"lower":271.8750,"count":273,"preSum":9878},{"ndv":37,"upper":309.3750,"lower":288.8890,"count":246,"preSum":10151},{"ndv":39,"upper":336.2500,"lower":310.0000,"count":250,"preSum":10397},{"ndv":33,"upper":362.5000,"lower":337.5000,"count":278,"preSum":10647},{"ndv":46,"upper":393.7500,"lower":363.5420,"count":244,"preSum":10925},{"ndv":37,"upper":420.0000,"lower":394.4400,"count":258,"preSum":11169},{"ndv":63,"upper":500.0000,"lower":420.4170,"count":290,"preSum":11427},{"ndv":51,"upper":600.0000,"lower":503.3330,"count":290,"preSum":11717},{"ndv":41,"upper":675.0000,"lower":602.7800,"count":255,"preSum":12007},{"ndv":51,"upper":785.0000,"lower":679.1670,"count":245,"preSum":12262},{"ndv":43,"upper":895.0000,"lower":788.8890,"count":247,"preSum":12507},{"ndv":42,"upper":1016.6670,"lower":898.0000,"count":250,"preSum":12754},{"ndv":34,"upper":1116.6660,"lower":1018.0000,"count":247,"preSum":13004},{"ndv":34,"upper":1200.0000,"lower":1116.6670,"count":252,"preSum":13251},{"ndv":39,"upper":1300.0000,"lower":1201.6670,"count":248,"preSum":13503},{"ndv":37,"upper":1416.6660,"lower":1310.0000,"count":253,"preSum":13751},{"ndv":47,"upper":1583.3330,"lower":1416.6670,"count":246,"preSum":14004},{"ndv":49,"upper":1860.0000,"lower":1593.7500,"count":244,"preSum":14250},{"ndv":52,"upper":2580.0000,"lower":1866.6670,"count":247,"preSum":14494},{"ndv":40,"upper":3500.0000,"lower":2585.0000,"count":256,"preSum":14741},{"ndv":42,"upper":5800.0000,"lower":3550.0000,"count":246,"preSum":14997},{"ndv":75,"upper":13000.0000,"lower":5850.0000,"count":246,"preSum":15243},{"ndv":46,"upper":100000.0000,"lower":13200.0000,"count":112,"preSum":15489}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[61727,247,14433,71,79,208,99,79,133,77,72,140,103,70],"valueArr":[0.0000,0.1000,1.0000,27.0000,40.6250,41.6670,45.8330,143.7500,152.0830,162.5000,175.0000,229.1670,250.0000,350.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','unitwidth',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[93139],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','userdef1',1507,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":28,"upper":"国妆特字G20152356","lower":" 国妆特字G20130898","count":141,"preSum":0},{"ndv":11,"upper":"国妆特字G20160748","lower":"国妆特字G20152426","count":141,"preSum":141},{"ndv":10,"upper":"国妆特字G20170298","lower":"国妆特字G20160749","count":139,"preSum":282},{"ndv":20,"upper":"国妆特字G20190547","lower":"国妆特字G20170557","count":149,"preSum":421},{"ndv":24,"upper":"国妆特字G20212184","lower":"国妆特字G20191304","count":134,"preSum":570},{"ndv":25,"upper":"沪G妆网备字2014004041","lower":"国妆特字G20213383","count":134,"preSum":704},{"ndv":39,"upper":"沪G妆网备字2016017463","lower":"沪G妆网备字2014004050","count":134,"preSum":838},{"ndv":29,"upper":"沪G妆网备字2017010257","lower":"沪G妆网备字2016019434","count":142,"preSum":972},{"ndv":13,"upper":"沪G妆网备字2017016687","lower":"沪G妆网备字2017010259","count":143,"preSum":1114},{"ndv":17,"upper":"沪G妆网备字2017021453","lower":"沪G妆网备字2017016738","count":136,"preSum":1257},{"ndv":20,"upper":"沪G妆网备字2017025054","lower":"沪G妆网备字2017021454","count":143,"preSum":1393},{"ndv":18,"upper":"沪G妆网备字2017028111","lower":"沪G妆网备字2017025056","count":136,"preSum":1536},{"ndv":42,"upper":"沪G妆网备字2017031291","lower":"沪G妆网备字2017028681","count":139,"preSum":1672},{"ndv":20,"upper":"沪G妆网备字2018002219","lower":"沪G妆网备字2017032695","count":139,"preSum":1811},{"ndv":12,"upper":"沪G妆网备字2018004001","lower":"沪G妆网备字2018002634","count":146,"preSum":1950},{"ndv":13,"upper":"沪G妆网备字2018007699","lower":"沪G妆网备字2018004121","count":142,"preSum":2096},{"ndv":11,"upper":"沪G妆网备字2018007860","lower":"沪G妆网备字2018007734","count":136,"preSum":2238},{"ndv":17,"upper":"沪G妆网备字2018010991","lower":"沪G妆网备字2018009479","count":137,"preSum":2374},{"ndv":28,"upper":"沪G妆网备字2018011893","lower":"沪G妆网备字2018010992","count":149,"preSum":2511},{"ndv":18,"upper":"沪G妆网备字2018012725","lower":"沪G妆网备字2018011922","count":138,"preSum":2660},{"ndv":16,"upper":"沪G妆网备字2018015104","lower":"沪G妆网备字2018012728","count":144,"preSum":2798},{"ndv":18,"upper":"沪G妆网备字2018021148","lower":"沪G妆网备字2018015105","count":137,"preSum":2942},{"ndv":17,"upper":"沪G妆网备字2018030159","lower":"沪G妆网备字2018022109","count":141,"preSum":3079},{"ndv":23,"upper":"沪G妆网备字2019003913","lower":"沪G妆网备字2018032047","count":136,"preSum":3220},{"ndv":25,"upper":"沪G妆网备字2019011782","lower":"沪G妆网备字2019004071","count":134,"preSum":3356},{"ndv":21,"upper":"沪G妆网备字2019020713","lower":"沪G妆网备字2019011810","count":141,"preSum":3490},{"ndv":29,"upper":"沪G妆网备字2019022133","lower":"沪G妆网备字2019020731","count":134,"preSum":3631},{"ndv":17,"upper":"沪G妆网备字2019022777","lower":"沪G妆网备字2019022158","count":134,"preSum":3765},{"ndv":12,"upper":"沪G妆网备字2019024130","lower":"沪G妆网备字2019022783","count":144,"preSum":3899},{"ndv":13,"upper":"沪G妆网备字2019025897","lower":"沪G妆网备字2019024172","count":136,"preSum":4043},{"ndv":21,"upper":"沪G妆网备字2019027099","lower":"沪G妆网备字2019025948","count":140,"preSum":4179},{"ndv":20,"upper":"沪G妆网备字2020000289","lower":"沪G妆网备字2019027730","count":140,"preSum":4319},{"ndv":29,"upper":"沪G妆网备字2020002363","lower":"沪G妆网备字2020000293","count":137,"preSum":4459},{"ndv":20,"upper":"沪G妆网备字2020004467","lower":"沪G妆网备字2020002364","count":134,"preSum":4596},{"ndv":9,"upper":"沪G妆网备字2020006078","lower":"沪G妆网备字2020004481","count":134,"preSum":4730},{"ndv":21,"upper":"沪G妆网备字2020009874","lower":"沪G妆网备字2020007048","count":135,"preSum":4864},{"ndv":20,"upper":"沪G妆网备字2020012569","lower":"沪G妆网备字2020009875","count":154,"preSum":4999},{"ndv":15,"upper":"沪G妆网备字2020015103","lower":"沪G妆网备字2020012639","count":141,"preSum":5153},{"ndv":17,"upper":"沪G妆网备字2020017132","lower":"沪G妆网备字2020015198","count":140,"preSum":5294},{"ndv":25,"upper":"沪G妆网备字2020021095","lower":"沪G妆网备字2020017134","count":140,"preSum":5434},{"ndv":13,"upper":"沪G妆网备字2020024075","lower":"沪G妆网备字2020021116","count":135,"preSum":5574},{"ndv":10,"upper":"沪G妆网备字2020027609","lower":"沪G妆网备字2020025156","count":136,"preSum":5709},{"ndv":17,"upper":"沪G妆网备字2020029583","lower":"沪G妆网备字2020028345","count":139,"preSum":5845},{"ndv":10,"upper":"沪G妆网备字2020029614","lower":"沪G妆网备字2020029591","count":141,"preSum":5984},{"ndv":7,"upper":"沪G妆网备字2020029630","lower":"沪G妆网备字2020029615","count":144,"preSum":6125},{"ndv":14,"upper":"沪G妆网备字2021000140","lower":"沪G妆网备字2020030090","count":138,"preSum":6269},{"ndv":10,"upper":"沪G妆网备字2021003477","lower":"沪G妆网备字2021000203","count":137,"preSum":6407},{"ndv":17,"upper":"沪G妆网备字2021009338","lower":"沪G妆网备字2021004074","count":134,"preSum":6544},{"ndv":19,"upper":"沪G妆网备字2021009450","lower":"沪G妆网备字2021009342","count":144,"preSum":6678},{"ndv":20,"upper":"沪G妆网备字2021010617","lower":"沪G妆网备字2021009465","count":136,"preSum":6822},{"ndv":17,"upper":"沪G妆网备字2021506351","lower":"沪G妆网备字2021500076","count":139,"preSum":6958},{"ndv":19,"upper":"沪G妆网备字2021513468","lower":"沪G妆网备字2021506352","count":141,"preSum":7097},{"ndv":21,"upper":"沪G妆网备字2021514376","lower":"沪G妆网备字2021513547","count":144,"preSum":7238},{"ndv":23,"upper":"沪G妆网备字2022003111","lower":"沪G妆网备字2021514381","count":135,"preSum":7382},{"ndv":25,"upper":"沪G妆网备字2022006688","lower":"沪G妆网备字2022003112","count":138,"preSum":7517},{"ndv":21,"upper":"沪G妆网备字2022008989","lower":"沪G妆网备字2022006971","count":142,"preSum":7655},{"ndv":22,"upper":"沪G妆网备字2022010621","lower":"沪G妆网备字2022009151","count":134,"preSum":7797},{"ndv":24,"upper":"沪G妆网备字2022014173","lower":"沪G妆网备字2022010622","count":134,"preSum":7931},{"ndv":21,"upper":"沪G妆网备字2022016039","lower":"沪G妆网备字2022015896","count":134,"preSum":8065},{"ndv":29,"upper":"沪G妆网备字2023000741","lower":"沪G妆网备字2022016040","count":143,"preSum":8199},{"ndv":26,"upper":"沪G妆网备字2023003554","lower":"沪G妆网备字2023000771","count":135,"preSum":8342},{"ndv":10,"upper":"黑械注准20212140027","lower":"沪G妆网备字2023003600","count":39,"preSum":8477}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[82655,39,63,43,44,78,39,42,43,52,52,42,45,93],"valueArr":["","沪G妆网备字2017017819","沪G妆网备字2019024105","沪G妆网备字2019026142","沪G妆网备字2020004852","沪G妆网备字2020007844","沪G妆网备字2020029618","沪G妆网备字2021004877","沪G妆网备字2021501304","沪G妆网备字2021501306","沪G妆网备字2021501766","沪G妆网备字2022000191","沪G妆网备字2023000718","略"],"type":"String","sampleRate":1.0}',1293,0.11565614),('jala_wms_prod','item','userdef2',7,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"10.0","lower":"10.0","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[91809,7,38],"valueArr":["0.0","1.0","5.0"],"type":"String","sampleRate":1.0}',1284,0.11565614),('jala_wms_prod','item','userdef3',7,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"10.0","lower":"10.0","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[91270,141,443],"valueArr":["0.0","2.0","5.0"],"type":"String","sampleRate":1.0}',1284,0.11565614),('jala_wms_prod','item','userdef4',6,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"C3","lower":"C3","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[44466,23607,5061,1602,15488],"valueArr":["","C1","C7","C9","CL"],"type":"String","sampleRate":1.0}',2913,0.11565614),('jala_wms_prod','item','userdef5',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[1682],"valueArr":[""],"type":"String","sampleRate":1.0}',91457,0.11565614),('jala_wms_prod','item','userdef6',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','userdef7',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','userdef8',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93139,0.11565614),('jala_wms_prod','item','version',935,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":7,"lower":7,"count":761,"preSum":0},{"ndv":2,"upper":10,"lower":9,"count":1709,"preSum":761},{"ndv":2,"upper":13,"lower":11,"count":1618,"preSum":2470},{"ndv":2,"upper":15,"lower":14,"count":1004,"preSum":4088},{"ndv":1,"upper":16,"lower":16,"count":920,"preSum":5092},{"ndv":3,"upper":21,"lower":17,"count":836,"preSum":6012},{"ndv":1,"upper":22,"lower":22,"count":822,"preSum":6848},{"ndv":2,"upper":24,"lower":23,"count":704,"preSum":7670},{"ndv":2,"upper":26,"lower":25,"count":622,"preSum":8374},{"ndv":2,"upper":29,"lower":27,"count":721,"preSum":8996},{"ndv":2,"upper":32,"lower":31,"count":1158,"preSum":9717},{"ndv":2,"upper":34,"lower":33,"count":1625,"preSum":10875},{"ndv":1,"upper":35,"lower":35,"count":1222,"preSum":12500},{"ndv":3,"upper":38,"lower":36,"count":699,"preSum":13722},{"ndv":2,"upper":40,"lower":39,"count":724,"preSum":14421},{"ndv":4,"upper":44,"lower":41,"count":1033,"preSum":15145},{"ndv":2,"upper":46,"lower":45,"count":1523,"preSum":16178},{"ndv":2,"upper":48,"lower":47,"count":726,"preSum":17701},{"ndv":3,"upper":51,"lower":49,"count":677,"preSum":18427},{"ndv":4,"upper":55,"lower":52,"count":829,"preSum":19104},{"ndv":3,"upper":58,"lower":56,"count":1176,"preSum":19933},{"ndv":2,"upper":60,"lower":59,"count":1125,"preSum":21109},{"ndv":3,"upper":63,"lower":61,"count":753,"preSum":22234},{"ndv":4,"upper":67,"lower":64,"count":685,"preSum":22987},{"ndv":4,"upper":71,"lower":68,"count":591,"preSum":23672},{"ndv":5,"upper":77,"lower":72,"count":1611,"preSum":24263},{"ndv":2,"upper":79,"lower":78,"count":737,"preSum":25874},{"ndv":1,"upper":80,"lower":80,"count":1054,"preSum":26611},{"ndv":4,"upper":84,"lower":81,"count":942,"preSum":27665},{"ndv":3,"upper":87,"lower":85,"count":633,"preSum":28607},{"ndv":3,"upper":90,"lower":88,"count":672,"preSum":29240},{"ndv":4,"upper":94,"lower":91,"count":625,"preSum":29912},{"ndv":7,"upper":101,"lower":95,"count":597,"preSum":30537},{"ndv":7,"upper":108,"lower":102,"count":633,"preSum":31134},{"ndv":6,"upper":114,"lower":109,"count":770,"preSum":31767},{"ndv":10,"upper":124,"lower":115,"count":595,"preSum":32537},{"ndv":15,"upper":139,"lower":125,"count":606,"preSum":33132},{"ndv":13,"upper":152,"lower":140,"count":612,"preSum":33738},{"ndv":42,"upper":194,"lower":153,"count":621,"preSum":34350},{"ndv":21,"upper":215,"lower":195,"count":664,"preSum":34971},{"ndv":22,"upper":237,"lower":216,"count":591,"preSum":35635},{"ndv":59,"upper":298,"lower":238,"count":593,"preSum":36226},{"ndv":173,"upper":740,"lower":299,"count":598,"preSum":36819},{"ndv":171,"upper":2013,"lower":741,"count":406,"preSum":37417}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[11427,5789,6985,2808,8701,1947,2247,3707,1474,2235,2793,1514,1695,1994],"valueArr":[0,1,2,3,4,5,6,8,12,19,20,28,30,76],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','warehousecode',13,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[15105,9731,9666,4158,9776,1558,9544,4819,4995,4983,5025,9021,4758],"valueArr":["021DC1","022DC","027DC","028DC","573DC","573DJX","763DC","763DCA","SH01","SH02","SH03","TEST01","TEST02"],"type":"String","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','warnshelflife',8,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":1095,"lower":1095,"count":1,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[87357,16,893,4341,531],"valueArr":[0,30,180,365,548],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item','warnshelflifests',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93],"valueArr":[""],"type":"String","sampleRate":1.0}',93046,0.11565614),('jala_wms_prod','item','yearstoexpire',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93100,11,28],"valueArr":[0,3,4],"type":"Int","sampleRate":1.0}',0,0.11565614),('jala_wms_prod','item_packing_detail','companycode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}','{"countArr":[58455,5209,36337],"valueArr":["JALA01","JALA02","JALA11"],"type":"String","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','created',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9553658}',null,100001,0.025981193),('jala_wms_prod','item_packing_detail','createdby',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}','{"countArr":[9993,36088,4289,40567,9064],"valueArr":["TTXLHJ","XCY","XCY1","api","jx"],"type":"String","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','denominator',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','displayname',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}','{"countArr":[20000,20003,19933,19882,20183],"valueArr":["个","中包","小包","托","箱"],"type":"String","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','headerid',236404,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":516,"upper":1583018,"lower":1554937,"count":1564,"preSum":0},{"ndv":526,"upper":1602664,"lower":1583019,"count":1563,"preSum":1564},{"ndv":487,"upper":1613645,"lower":1602666,"count":1563,"preSum":3127},{"ndv":500,"upper":1625915,"lower":1613647,"count":1564,"preSum":4690},{"ndv":521,"upper":1643799,"lower":1625916,"count":1563,"preSum":6254},{"ndv":497,"upper":1662023,"lower":1643800,"count":1566,"preSum":7817},{"ndv":458,"upper":1676871,"lower":1662024,"count":1564,"preSum":9383},{"ndv":451,"upper":1691130,"lower":1676872,"count":1565,"preSum":10947},{"ndv":465,"upper":1708584,"lower":1691131,"count":1563,"preSum":12512},{"ndv":461,"upper":1721766,"lower":1708624,"count":1563,"preSum":14075},{"ndv":451,"upper":1733927,"lower":1721767,"count":1567,"preSum":15638},{"ndv":444,"upper":1750671,"lower":1733928,"count":1563,"preSum":17205},{"ndv":439,"upper":1765216,"lower":1750672,"count":1563,"preSum":18768},{"ndv":442,"upper":1779937,"lower":1765217,"count":1565,"preSum":20331},{"ndv":439,"upper":1793602,"lower":1779938,"count":1565,"preSum":21896},{"ndv":446,"upper":1809973,"lower":1793903,"count":1564,"preSum":23461},{"ndv":439,"upper":1826554,"lower":1809974,"count":1563,"preSum":25025},{"ndv":436,"upper":1840102,"lower":1826555,"count":1563,"preSum":26588},{"ndv":433,"upper":1857633,"lower":1840103,"count":1563,"preSum":28151},{"ndv":472,"upper":1872802,"lower":1857634,"count":1567,"preSum":29714},{"ndv":461,"upper":1893030,"lower":1872803,"count":1565,"preSum":31281},{"ndv":472,"upper":1906799,"lower":1893031,"count":1565,"preSum":32846},{"ndv":472,"upper":1925515,"lower":1906800,"count":1566,"preSum":34411},{"ndv":466,"upper":1940173,"lower":1925516,"count":1565,"preSum":35977},{"ndv":626,"upper":2050724,"lower":1940174,"count":1563,"preSum":37542},{"ndv":964,"upper":2070308,"lower":2050725,"count":1563,"preSum":39105},{"ndv":993,"upper":2083709,"lower":2070309,"count":1564,"preSum":40668},{"ndv":938,"upper":2104542,"lower":2083710,"count":1563,"preSum":42232},{"ndv":965,"upper":2120015,"lower":2104543,"count":1563,"preSum":43795},{"ndv":967,"upper":2138693,"lower":2120017,"count":1564,"preSum":45358},{"ndv":851,"upper":2153224,"lower":2138694,"count":1563,"preSum":46922},{"ndv":880,"upper":2168014,"lower":2153225,"count":1564,"preSum":48485},{"ndv":1009,"upper":2181665,"lower":2168016,"count":1563,"preSum":50049},{"ndv":940,"upper":2193204,"lower":2181666,"count":1563,"preSum":51612},{"ndv":880,"upper":2207084,"lower":2193205,"count":1563,"preSum":53175},{"ndv":946,"upper":2224897,"lower":2207452,"count":1564,"preSum":54738},{"ndv":935,"upper":2243280,"lower":2224898,"count":1563,"preSum":56302},{"ndv":933,"upper":2263635,"lower":2243282,"count":1564,"preSum":57865},{"ndv":1114,"upper":2280768,"lower":2263680,"count":1563,"preSum":59429},{"ndv":1132,"upper":2297441,"lower":2280771,"count":1565,"preSum":60992},{"ndv":1158,"upper":2316690,"lower":2297445,"count":1563,"preSum":62557},{"ndv":805,"upper":2332143,"lower":2316691,"count":1564,"preSum":64120},{"ndv":922,"upper":2352931,"lower":2332144,"count":1563,"preSum":65684},{"ndv":1005,"upper":2366302,"lower":2352932,"count":1563,"preSum":67247},{"ndv":1088,"upper":2381003,"lower":2366304,"count":1563,"preSum":68810},{"ndv":1041,"upper":2389431,"lower":2381009,"count":1563,"preSum":70373},{"ndv":1138,"upper":2408807,"lower":2389432,"count":1563,"preSum":71936},{"ndv":1158,"upper":2426893,"lower":2408808,"count":1563,"preSum":73499},{"ndv":1191,"upper":2444519,"lower":2426908,"count":1563,"preSum":75062},{"ndv":1185,"upper":2463456,"lower":2444521,"count":1563,"preSum":76625},{"ndv":1024,"upper":2479113,"lower":2463460,"count":1563,"preSum":78188},{"ndv":871,"upper":2493758,"lower":2479120,"count":1563,"preSum":79751},{"ndv":900,"upper":2517238,"lower":2493759,"count":1564,"preSum":81314},{"ndv":1000,"upper":2531882,"lower":2517239,"count":1563,"preSum":82878},{"ndv":1016,"upper":2554053,"lower":2531887,"count":1564,"preSum":84441},{"ndv":1124,"upper":2571290,"lower":2554054,"count":1564,"preSum":86005},{"ndv":1017,"upper":2588218,"lower":2571291,"count":1565,"preSum":87569},{"ndv":941,"upper":2606483,"lower":2588219,"count":1564,"preSum":89134},{"ndv":1005,"upper":2620429,"lower":2606484,"count":1563,"preSum":90698},{"ndv":1088,"upper":2637032,"lower":2620703,"count":1563,"preSum":92261},{"ndv":1047,"upper":2652371,"lower":2637034,"count":1563,"preSum":93824},{"ndv":1106,"upper":2674705,"lower":2652373,"count":1563,"preSum":95387},{"ndv":1117,"upper":2693382,"lower":2674708,"count":1563,"preSum":96950},{"ndv":825,"upper":2856124,"lower":2693383,"count":1488,"preSum":98513}],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[],"valueArr":[],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','hi',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','id',3802078,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1563,"upper":7925692,"lower":7785277,"count":1563,"preSum":0},{"ndv":1563,"upper":8023940,"lower":7925694,"count":1563,"preSum":1563},{"ndv":1563,"upper":8078826,"lower":8023942,"count":1563,"preSum":3126},{"ndv":1563,"upper":8140178,"lower":8078827,"count":1563,"preSum":4689},{"ndv":1563,"upper":8229589,"lower":8140179,"count":1563,"preSum":6252},{"ndv":1563,"upper":8320714,"lower":8229590,"count":1563,"preSum":7815},{"ndv":1563,"upper":8394953,"lower":8320715,"count":1563,"preSum":9378},{"ndv":1563,"upper":8466246,"lower":8394954,"count":1563,"preSum":10941},{"ndv":1563,"upper":8553517,"lower":8466247,"count":1563,"preSum":12504},{"ndv":1563,"upper":8618481,"lower":8553518,"count":1563,"preSum":14067},{"ndv":1563,"upper":8680231,"lower":8619288,"count":1563,"preSum":15630},{"ndv":1563,"upper":8763956,"lower":8680233,"count":1563,"preSum":17193},{"ndv":1563,"upper":8833338,"lower":8763957,"count":1563,"preSum":18756},{"ndv":1563,"upper":8910597,"lower":8833339,"count":1563,"preSum":20319},{"ndv":1563,"upper":8978957,"lower":8910598,"count":1563,"preSum":21882},{"ndv":1563,"upper":9060807,"lower":8978958,"count":1563,"preSum":23445},{"ndv":1563,"upper":9143737,"lower":9060808,"count":1563,"preSum":25008},{"ndv":1563,"upper":9211488,"lower":9143740,"count":1563,"preSum":26571},{"ndv":1563,"upper":9299725,"lower":9211489,"count":1563,"preSum":28134},{"ndv":1563,"upper":9373817,"lower":9299726,"count":1563,"preSum":29697},{"ndv":1563,"upper":9476741,"lower":9373818,"count":1563,"preSum":31260},{"ndv":1563,"upper":9544674,"lower":9476742,"count":1563,"preSum":32823},{"ndv":1563,"upper":9636671,"lower":9544675,"count":1563,"preSum":34386},{"ndv":1563,"upper":9712532,"lower":9636672,"count":1563,"preSum":35949},{"ndv":1563,"upper":9853012,"lower":9712533,"count":1563,"preSum":37512},{"ndv":1563,"upper":9944494,"lower":9853015,"count":1563,"preSum":39075},{"ndv":1563,"upper":10017185,"lower":9944495,"count":1563,"preSum":40638},{"ndv":1563,"upper":10122053,"lower":10017187,"count":1563,"preSum":42201},{"ndv":1563,"upper":10197602,"lower":10122054,"count":1563,"preSum":43764},{"ndv":1563,"upper":10285478,"lower":10197603,"count":1563,"preSum":45327},{"ndv":1563,"upper":10364622,"lower":10285480,"count":1563,"preSum":46890},{"ndv":1563,"upper":10438029,"lower":10364623,"count":1563,"preSum":48453},{"ndv":1563,"upper":10505349,"lower":10438032,"count":1563,"preSum":50016},{"ndv":1563,"upper":10565457,"lower":10505351,"count":1563,"preSum":51579},{"ndv":1563,"upper":10636060,"lower":10565459,"count":1563,"preSum":53142},{"ndv":1563,"upper":10725186,"lower":10636061,"count":1563,"preSum":54705},{"ndv":1563,"upper":10808294,"lower":10725187,"count":1563,"preSum":56268},{"ndv":1563,"upper":10938603,"lower":10808295,"count":1563,"preSum":57831},{"ndv":1563,"upper":11027160,"lower":10938604,"count":1563,"preSum":59394},{"ndv":1563,"upper":11110905,"lower":11027161,"count":1563,"preSum":60957},{"ndv":1563,"upper":11204473,"lower":11110906,"count":1563,"preSum":62520},{"ndv":1563,"upper":11289763,"lower":11204474,"count":1563,"preSum":64083},{"ndv":1563,"upper":11393702,"lower":11289765,"count":1563,"preSum":65646},{"ndv":1563,"upper":11459326,"lower":11393703,"count":1563,"preSum":67209},{"ndv":1563,"upper":11531891,"lower":11459327,"count":1563,"preSum":68772},{"ndv":1563,"upper":11576233,"lower":11531892,"count":1563,"preSum":70335},{"ndv":1563,"upper":11673027,"lower":11576234,"count":1563,"preSum":71898},{"ndv":1563,"upper":11763316,"lower":11673028,"count":1563,"preSum":73461},{"ndv":1563,"upper":11849917,"lower":11763317,"count":1563,"preSum":75024},{"ndv":1563,"upper":11944274,"lower":11849918,"count":1563,"preSum":76587},{"ndv":1563,"upper":12029555,"lower":11944276,"count":1563,"preSum":78150},{"ndv":1563,"upper":12102634,"lower":12029557,"count":1563,"preSum":79713},{"ndv":1563,"upper":12212811,"lower":12102635,"count":1563,"preSum":81276},{"ndv":1563,"upper":12292329,"lower":12220348,"count":1563,"preSum":82839},{"ndv":1563,"upper":12404397,"lower":12292330,"count":1563,"preSum":84402},{"ndv":1563,"upper":12490627,"lower":12404398,"count":1563,"preSum":85965},{"ndv":1563,"upper":12570183,"lower":12490628,"count":1563,"preSum":87528},{"ndv":1563,"upper":12661367,"lower":12570185,"count":1563,"preSum":89091},{"ndv":1563,"upper":12735863,"lower":12661368,"count":1563,"preSum":90654},{"ndv":1563,"upper":12813227,"lower":12735865,"count":1563,"preSum":92217},{"ndv":1563,"upper":12893702,"lower":12813228,"count":1563,"preSum":93780},{"ndv":1563,"upper":12997394,"lower":12893703,"count":1563,"preSum":95343},{"ndv":1563,"upper":13111947,"lower":12997395,"count":1563,"preSum":96906},{"ndv":1532,"upper":13379820,"lower":13111948,"count":1532,"preSum":98469}],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}',null,0,0.025981193),('jala_wms_prod','item_packing_detail','itemcode',88097,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":477,"upper":"1103090400","lower":"1101013500","count":1563,"preSum":0},{"ndv":522,"upper":"1112010500","lower":"1103090600","count":1557,"preSum":1563},{"ndv":517,"upper":"1201105300","lower":"1112010600","count":1558,"preSum":3120},{"ndv":470,"upper":"1201204000","lower":"1201105400","count":1557,"preSum":4678},{"ndv":533,"upper":"1206000600","lower":"1201204100","count":1558,"preSum":6235},{"ndv":479,"upper":"1210036200","lower":"1206000601","count":1560,"preSum":7793},{"ndv":511,"upper":"1216179400","lower":"1210036300","count":1560,"preSum":9353},{"ndv":519,"upper":"1300047101","lower":"1216179800","count":1564,"preSum":10913},{"ndv":453,"upper":"1300104400","lower":"1300047200","count":1560,"preSum":12477},{"ndv":448,"upper":"1300159200","lower":"1300104500","count":1563,"preSum":14037},{"ndv":508,"upper":"1300221000","lower":"1300159201","count":1558,"preSum":15600},{"ndv":528,"upper":"1300298100","lower":"1300221001","count":1558,"preSum":17158},{"ndv":497,"upper":"1300376300","lower":"1300298300","count":1557,"preSum":18716},{"ndv":483,"upper":"1300444400","lower":"1300376400","count":1573,"preSum":20273},{"ndv":473,"upper":"1300505501","lower":"1300444700","count":1562,"preSum":21846},{"ndv":489,"upper":"1300576400","lower":"1300505600","count":1565,"preSum":23408},{"ndv":515,"upper":"1300646300","lower":"1300576500","count":1563,"preSum":24973},{"ndv":510,"upper":"1300721700","lower":"1300646301","count":1563,"preSum":26536},{"ndv":514,"upper":"1300798500","lower":"1300722100","count":1557,"preSum":28099},{"ndv":501,"upper":"1300872300","lower":"1300798600","count":1557,"preSum":29656},{"ndv":526,"upper":"1300941701","lower":"1300872600","count":1558,"preSum":31213},{"ndv":516,"upper":"1301007500","lower":"1300941800","count":1557,"preSum":32771},{"ndv":483,"upper":"1301072300","lower":"1301007700","count":1559,"preSum":34328},{"ndv":507,"upper":"1301167000","lower":"1301072500","count":1558,"preSum":35887},{"ndv":360,"upper":"20325","lower":"1301167400","count":1568,"preSum":37445},{"ndv":459,"upper":"21013","lower":"20326","count":1562,"preSum":39013},{"ndv":482,"upper":"21999","lower":"21014","count":1557,"preSum":40575},{"ndv":536,"upper":"22892","lower":"22000","count":1558,"preSum":42132},{"ndv":519,"upper":"28478","lower":"22894","count":1557,"preSum":43690},{"ndv":497,"upper":"30122200","lower":"28479","count":1558,"preSum":45247},{"ndv":406,"upper":"302026400","lower":"30122400","count":1558,"preSum":46805},{"ndv":421,"upper":"30232404","lower":"302026500","count":1558,"preSum":48363},{"ndv":440,"upper":"30285600","lower":"30232500","count":1557,"preSum":49921},{"ndv":441,"upper":"30514600","lower":"30285700","count":1562,"preSum":51478},{"ndv":506,"upper":"401459300","lower":"30514701","count":1562,"preSum":53040},{"ndv":519,"upper":"402476200","lower":"401459400","count":1557,"preSum":54602},{"ndv":495,"upper":"402754600","lower":"402476300","count":1564,"preSum":56159},{"ndv":495,"upper":"501280100","lower":"402754601","count":1557,"preSum":57723},{"ndv":423,"upper":"501515302","lower":"501280200[1801]","count":1570,"preSum":59280},{"ndv":470,"upper":"502101100","lower":"501515500","count":1560,"preSum":60850},{"ndv":561,"upper":"502313104","lower":"502110400","count":1557,"preSum":62410},{"ndv":503,"upper":"502505700","lower":"502313107","count":1558,"preSum":63967},{"ndv":521,"upper":"502547600S","lower":"502506100","count":1570,"preSum":65525},{"ndv":491,"upper":"502584800","lower":"502547600T","count":1561,"preSum":67095},{"ndv":486,"upper":"502630900","lower":"502584900","count":1559,"preSum":68656},{"ndv":479,"upper":"502691700","lower":"502631200","count":1557,"preSum":70215},{"ndv":506,"upper":"502751800","lower":"502691800","count":1559,"preSum":71772},{"ndv":432,"upper":"502952961","lower":"502751900","count":1560,"preSum":73331},{"ndv":484,"upper":"502985460","lower":"502952970","count":1557,"preSum":74891},{"ndv":493,"upper":"505000402.1","lower":"502985461","count":1563,"preSum":76448},{"ndv":504,"upper":"505027803","lower":"505000403","count":1558,"preSum":78011},{"ndv":511,"upper":"512003902","lower":"505028000","count":1565,"preSum":79569},{"ndv":430,"upper":"6010778","lower":"512004000","count":1557,"preSum":81134},{"ndv":518,"upper":"6022298","lower":"6010780","count":1563,"preSum":82691},{"ndv":506,"upper":"6023647","lower":"6022299","count":1559,"preSum":84254},{"ndv":543,"upper":"6160098","lower":"6023657","count":1569,"preSum":85813},{"ndv":520,"upper":"6160972","lower":"6160099","count":1557,"preSum":87382},{"ndv":544,"upper":"6161910","lower":"6160973","count":1561,"preSum":88939},{"ndv":506,"upper":"6162807","lower":"6161911","count":1557,"preSum":90500},{"ndv":519,"upper":"6163727","lower":"6162808","count":1557,"preSum":92057},{"ndv":471,"upper":"6164524","lower":"6163728","count":1560,"preSum":93614},{"ndv":492,"upper":"6165366","lower":"6164525","count":1557,"preSum":95174},{"ndv":501,"upper":"80242","lower":"6165368","count":1557,"preSum":96731},{"ndv":479,"upper":"test001","lower":"80243","count":1302,"preSum":98288}],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}','{"countArr":[30,25,29,45,38,25,32,27,34,29,41,27,29],"valueArr":["1300538004","1300545502","1301130800","1301167200","1301167300","20259","30271100","30524100","31000200","502799301","502900900","6163655","6165592"],"type":"String","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','lastupdated',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9553658}',null,100001,0.025981193),('jala_wms_prod','item_packing_detail','lastupdatedby',51,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"0220005","lower":"0220005","count":1,"preSum":0},{"ndv":1,"upper":"02700003","lower":"02700003","count":1,"preSum":1},{"ndv":1,"upper":"02700004","lower":"02700004","count":1,"preSum":2},{"ndv":1,"upper":"02700006","lower":"02700006","count":1,"preSum":3},{"ndv":1,"upper":"41091430","lower":"41091430","count":1,"preSum":4},{"ndv":1,"upper":"41163094","lower":"41163094","count":2,"preSum":5},{"ndv":1,"upper":"CFM","lower":"CFM","count":2,"preSum":7},{"ndv":1,"upper":"gth","lower":"gth","count":1,"preSum":9},{"ndv":1,"upper":"zhaolingling","lower":"zhaolingling","count":2,"preSum":10}],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}','{"countArr":[8045,27966,3232,53016,7730],"valueArr":["TTXLHJ","XCY","XCY1","api","jx"],"type":"String","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','molecule',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','packingcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}','{"countArr":[100001],"valueArr":["STD"],"type":"String","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','processstamp',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}',null,100001,0.025981193),('jala_wms_prod','item_packing_detail','qtyratio',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":1000,"lower":1000,"count":2,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[99999],"valueArr":[0],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','sequence',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[20000,19933,20003,20183,19882],"valueArr":[10,20,30,40,50],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','syncglobal',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[12,99989],"valueArr":[0,1],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','ti',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','unitaslooseinbound',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[28783,71218],"valueArr":[0,1],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','unitaslooseoutbound',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[28783,71218],"valueArr":[0,1],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','unitcode',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}','{"countArr":[20183,20000,20003,19882,19933],"valueArr":["CS","EA","MP","PL","SP"],"type":"String","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','unitheight',617,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":4.0000,"lower":1.5000,"count":10,"preSum":0},{"ndv":5,"upper":15.0000,"lower":6.0000,"count":11,"preSum":10},{"ndv":4,"upper":17.0000,"lower":15.8000,"count":9,"preSum":21},{"ndv":4,"upper":18.7800,"lower":18.0000,"count":10,"preSum":30},{"ndv":3,"upper":19.2000,"lower":18.9000,"count":9,"preSum":40},{"ndv":3,"upper":21.0000,"lower":19.2600,"count":14,"preSum":49},{"ndv":4,"upper":24.0000,"lower":21.8000,"count":9,"preSum":63},{"ndv":2,"upper":26.0000,"lower":25.0000,"count":9,"preSum":72},{"ndv":3,"upper":29.5000,"lower":27.0000,"count":9,"preSum":81},{"ndv":2,"upper":30.1000,"lower":30.0000,"count":9,"preSum":90},{"ndv":8,"upper":34.0000,"lower":30.5700,"count":10,"preSum":99},{"ndv":4,"upper":38.0000,"lower":35.0000,"count":9,"preSum":109},{"ndv":3,"upper":39.8000,"lower":39.0000,"count":9,"preSum":118},{"ndv":1,"upper":40.0000,"lower":40.0000,"count":9,"preSum":127},{"ndv":6,"upper":45.0000,"lower":40.5000,"count":9,"preSum":136},{"ndv":3,"upper":49.0000,"lower":46.0000,"count":10,"preSum":145},{"ndv":5,"upper":54.0000,"lower":49.5000,"count":9,"preSum":155},{"ndv":3,"upper":56.0000,"lower":55.0000,"count":10,"preSum":164},{"ndv":2,"upper":56.9300,"lower":56.9000,"count":9,"preSum":174},{"ndv":4,"upper":61.0000,"lower":57.0000,"count":9,"preSum":183},{"ndv":4,"upper":64.0000,"lower":61.5000,"count":9,"preSum":192},{"ndv":6,"upper":69.0000,"lower":65.0000,"count":16,"preSum":201},{"ndv":2,"upper":72.0000,"lower":70.0000,"count":9,"preSum":217},{"ndv":4,"upper":77.5000,"lower":73.5800,"count":12,"preSum":226},{"ndv":5,"upper":81.9000,"lower":78.0000,"count":15,"preSum":238},{"ndv":4,"upper":84.5000,"lower":81.9400,"count":10,"preSum":253},{"ndv":3,"upper":87.0000,"lower":84.8000,"count":13,"preSum":263},{"ndv":5,"upper":93.0000,"lower":88.0000,"count":9,"preSum":276},{"ndv":3,"upper":105.0000,"lower":97.0000,"count":13,"preSum":285},{"ndv":7,"upper":112.0000,"lower":106.0000,"count":16,"preSum":298},{"ndv":5,"upper":123.0000,"lower":114.0000,"count":9,"preSum":314},{"ndv":3,"upper":129.0000,"lower":125.0000,"count":14,"preSum":323},{"ndv":3,"upper":133.0000,"lower":130.0000,"count":10,"preSum":337},{"ndv":2,"upper":136.8300,"lower":135.0000,"count":9,"preSum":347},{"ndv":2,"upper":137.2200,"lower":137.0000,"count":10,"preSum":356},{"ndv":4,"upper":147.0000,"lower":140.0000,"count":11,"preSum":366},{"ndv":2,"upper":149.0000,"lower":148.0000,"count":9,"preSum":377},{"ndv":2,"upper":151.0000,"lower":150.0000,"count":13,"preSum":386},{"ndv":5,"upper":161.0000,"lower":151.5000,"count":9,"preSum":399},{"ndv":4,"upper":168.7200,"lower":163.0000,"count":10,"preSum":408},{"ndv":2,"upper":171.0000,"lower":169.0000,"count":10,"preSum":418},{"ndv":3,"upper":174.0000,"lower":172.0000,"count":9,"preSum":428},{"ndv":2,"upper":176.0000,"lower":175.9000,"count":9,"preSum":437},{"ndv":4,"upper":179.0200,"lower":176.5300,"count":10,"preSum":446},{"ndv":2,"upper":181.0000,"lower":180.0000,"count":9,"preSum":456},{"ndv":2,"upper":182.5000,"lower":182.0000,"count":16,"preSum":465},{"ndv":3,"upper":186.0000,"lower":183.4000,"count":9,"preSum":481},{"ndv":2,"upper":193.0000,"lower":188.0000,"count":9,"preSum":490},{"ndv":3,"upper":203.5000,"lower":195.0000,"count":10,"preSum":499},{"ndv":8,"upper":243.0000,"lower":208.0000,"count":9,"preSum":509},{"ndv":1,"upper":640.0000,"lower":640.0000,"count":1,"preSum":518}],"maxBucketSize":64,"type":"Double","sampleRate":0.9553658}','{"countArr":[99296,16,10,13,24,23,13,14,21,12,17,13,10],"valueArr":[0.0000,22.0000,60.0000,81.0000,90.0000,120.0000,122.0000,139.0000,167.0000,170.0000,175.0000,175.4700,198.0000],"type":"Double","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','unitlength',672,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":4,"upper":17.0400,"lower":9.0500,"count":8,"preSum":0},{"ndv":3,"upper":19.5500,"lower":17.9200,"count":10,"preSum":8},{"ndv":3,"upper":22.0000,"lower":19.6000,"count":16,"preSum":18},{"ndv":6,"upper":25.5000,"lower":23.3000,"count":19,"preSum":34},{"ndv":4,"upper":28.5000,"lower":25.5200,"count":10,"preSum":53},{"ndv":6,"upper":34.0000,"lower":30.0000,"count":12,"preSum":63},{"ndv":5,"upper":36.0000,"lower":35.0000,"count":10,"preSum":75},{"ndv":4,"upper":37.0700,"lower":36.6000,"count":8,"preSum":85},{"ndv":4,"upper":40.0000,"lower":38.3000,"count":10,"preSum":93},{"ndv":3,"upper":42.0000,"lower":41.0000,"count":10,"preSum":103},{"ndv":3,"upper":44.0000,"lower":42.5000,"count":8,"preSum":113},{"ndv":2,"upper":46.5000,"lower":45.5000,"count":12,"preSum":121},{"ndv":5,"upper":53.0000,"lower":48.0000,"count":9,"preSum":133},{"ndv":1,"upper":54.0000,"lower":54.0000,"count":10,"preSum":142},{"ndv":2,"upper":57.0000,"lower":55.0000,"count":10,"preSum":152},{"ndv":4,"upper":60.0000,"lower":58.0000,"count":9,"preSum":162},{"ndv":5,"upper":63.4100,"lower":60.5900,"count":9,"preSum":171},{"ndv":2,"upper":65.0000,"lower":63.9900,"count":12,"preSum":180},{"ndv":2,"upper":67.0000,"lower":66.0000,"count":10,"preSum":192},{"ndv":3,"upper":69.0000,"lower":67.4500,"count":8,"preSum":202},{"ndv":3,"upper":72.0000,"lower":70.0000,"count":12,"preSum":210},{"ndv":1,"upper":74.0000,"lower":74.0000,"count":10,"preSum":222},{"ndv":2,"upper":77.0000,"lower":75.0000,"count":9,"preSum":232},{"ndv":3,"upper":79.0000,"lower":78.0000,"count":8,"preSum":241},{"ndv":1,"upper":80.0000,"lower":80.0000,"count":8,"preSum":249},{"ndv":3,"upper":86.0000,"lower":81.0000,"count":8,"preSum":257},{"ndv":2,"upper":91.0000,"lower":90.0000,"count":9,"preSum":265},{"ndv":5,"upper":96.0000,"lower":92.0000,"count":8,"preSum":274},{"ndv":5,"upper":101.3500,"lower":99.0000,"count":8,"preSum":282},{"ndv":3,"upper":110.1100,"lower":102.0000,"count":8,"preSum":290},{"ndv":3,"upper":112.9700,"lower":110.1800,"count":11,"preSum":298},{"ndv":3,"upper":119.0000,"lower":114.0000,"count":10,"preSum":309},{"ndv":1,"upper":122.0000,"lower":122.0000,"count":8,"preSum":319},{"ndv":1,"upper":123.0000,"lower":123.0000,"count":12,"preSum":327},{"ndv":7,"upper":129.0000,"lower":123.0900,"count":9,"preSum":339},{"ndv":2,"upper":130.0000,"lower":129.6100,"count":14,"preSum":348},{"ndv":2,"upper":134.0000,"lower":132.0000,"count":11,"preSum":362},{"ndv":3,"upper":138.0000,"lower":136.0000,"count":8,"preSum":373},{"ndv":4,"upper":150.0000,"lower":140.0000,"count":14,"preSum":381},{"ndv":4,"upper":156.5000,"lower":154.4800,"count":8,"preSum":395},{"ndv":6,"upper":165.0000,"lower":157.0000,"count":8,"preSum":403},{"ndv":3,"upper":177.0000,"lower":166.0000,"count":8,"preSum":411},{"ndv":4,"upper":187.0000,"lower":178.0000,"count":9,"preSum":419},{"ndv":3,"upper":195.0000,"lower":190.0000,"count":8,"preSum":428},{"ndv":5,"upper":210.0000,"lower":200.0000,"count":13,"preSum":436},{"ndv":5,"upper":240.0000,"lower":211.0000,"count":8,"preSum":449},{"ndv":5,"upper":261.0000,"lower":245.0000,"count":8,"preSum":457},{"ndv":7,"upper":297.0000,"lower":276.0000,"count":11,"preSum":465},{"ndv":7,"upper":332.0000,"lower":306.0000,"count":8,"preSum":476},{"ndv":3,"upper":435.0000,"lower":339.5000,"count":3,"preSum":484}],"maxBucketSize":64,"type":"Double","sampleRate":0.9553658}','{"countArr":[99285,27,14,13,33,15,19,26,17,22,15,13,15],"valueArr":[0.0000,23.0000,38.0000,43.0000,45.0000,46.0000,47.0000,50.0000,56.0000,59.0000,120.0000,124.7100,133.0000],"type":"Double","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','unitname',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}','{"countArr":[20000,20003,19933,19882,20183],"valueArr":["个","中包","小包","托","箱"],"type":"String","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','unitqty',962,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":3,"lower":2,"count":101,"preSum":0},{"ndv":3,"upper":8,"lower":4,"count":133,"preSum":101},{"ndv":1,"upper":12,"lower":12,"count":122,"preSum":234},{"ndv":10,"upper":25,"lower":13,"count":95,"preSum":356},{"ndv":3,"upper":30,"lower":26,"count":118,"preSum":451},{"ndv":5,"upper":40,"lower":32,"count":89,"preSum":569},{"ndv":4,"upper":50,"lower":41,"count":117,"preSum":658},{"ndv":6,"upper":64,"lower":54,"count":68,"preSum":775},{"ndv":3,"upper":72,"lower":66,"count":95,"preSum":843},{"ndv":5,"upper":88,"lower":77,"count":68,"preSum":938},{"ndv":6,"upper":105,"lower":90,"count":78,"preSum":1006},{"ndv":6,"upper":120,"lower":108,"count":83,"preSum":1084},{"ndv":8,"upper":142,"lower":125,"count":71,"preSum":1167},{"ndv":3,"upper":154,"lower":144,"count":68,"preSum":1238},{"ndv":8,"upper":175,"lower":160,"count":70,"preSum":1306},{"ndv":9,"upper":216,"lower":176,"count":79,"preSum":1376},{"ndv":7,"upper":240,"lower":220,"count":79,"preSum":1455},{"ndv":7,"upper":270,"lower":242,"count":110,"preSum":1534},{"ndv":4,"upper":288,"lower":280,"count":108,"preSum":1644},{"ndv":8,"upper":320,"lower":294,"count":71,"preSum":1752},{"ndv":7,"upper":350,"lower":324,"count":82,"preSum":1823},{"ndv":10,"upper":396,"lower":351,"count":70,"preSum":1905},{"ndv":1,"upper":400,"lower":400,"count":136,"preSum":1975},{"ndv":11,"upper":456,"lower":405,"count":68,"preSum":2111},{"ndv":7,"upper":504,"lower":462,"count":68,"preSum":2179},{"ndv":12,"upper":600,"lower":532,"count":201,"preSum":2247},{"ndv":19,"upper":700,"lower":603,"count":214,"preSum":2448},{"ndv":6,"upper":756,"lower":704,"count":69,"preSum":2662},{"ndv":16,"upper":900,"lower":760,"count":151,"preSum":2731},{"ndv":11,"upper":1008,"lower":912,"count":70,"preSum":2882},{"ndv":9,"upper":1134,"lower":1020,"count":68,"preSum":2952},{"ndv":8,"upper":1200,"lower":1140,"count":83,"preSum":3020},{"ndv":13,"upper":1400,"lower":1232,"count":77,"preSum":3103},{"ndv":10,"upper":1600,"lower":1407,"count":103,"preSum":3180},{"ndv":11,"upper":1824,"lower":1620,"count":68,"preSum":3283},{"ndv":6,"upper":2000,"lower":1872,"count":68,"preSum":3351},{"ndv":11,"upper":2235,"lower":2046,"count":68,"preSum":3419},{"ndv":8,"upper":2400,"lower":2240,"count":69,"preSum":3487},{"ndv":16,"upper":3000,"lower":2420,"count":100,"preSum":3556},{"ndv":6,"upper":3400,"lower":3100,"count":90,"preSum":3656},{"ndv":9,"upper":4200,"lower":3500,"count":75,"preSum":3746},{"ndv":7,"upper":5000,"lower":4320,"count":131,"preSum":3821},{"ndv":10,"upper":6000,"lower":5084,"count":92,"preSum":3952},{"ndv":18,"upper":10000,"lower":6200,"count":170,"preSum":4044},{"ndv":26,"upper":25000,"lower":10080,"count":69,"preSum":4214},{"ndv":16,"upper":64000,"lower":26000,"count":38,"preSum":4283}],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[70120,20642,351,985,153,282,1285,241,252,290,341,163,159,416],"valueArr":[0,1,6,10,20,24,48,100,180,200,300,500,800,1000],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','unitvolume',12609,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":36,"upper":6.0900,"lower":0.0170,"count":72,"preSum":0},{"ndv":32,"upper":11.3850,"lower":6.3000,"count":74,"preSum":72},{"ndv":45,"upper":21.5300,"lower":11.5010,"count":71,"preSum":146},{"ndv":42,"upper":28.4810,"lower":21.5640,"count":71,"preSum":217},{"ndv":40,"upper":38.4540,"lower":28.5240,"count":71,"preSum":288},{"ndv":32,"upper":47.3850,"lower":38.4750,"count":71,"preSum":359},{"ndv":35,"upper":55.1760,"lower":47.5000,"count":73,"preSum":430},{"ndv":29,"upper":65.9760,"lower":55.3700,"count":72,"preSum":503},{"ndv":34,"upper":75.9540,"lower":66.0230,"count":71,"preSum":575},{"ndv":14,"upper":81.0470,"lower":76.7810,"count":74,"preSum":646},{"ndv":30,"upper":91.0000,"lower":81.6000,"count":71,"preSum":720},{"ndv":26,"upper":102.0000,"lower":91.0800,"count":71,"preSum":791},{"ndv":29,"upper":110.3880,"lower":102.3750,"count":71,"preSum":862},{"ndv":35,"upper":119.7970,"lower":110.6660,"count":71,"preSum":933},{"ndv":28,"upper":129.9380,"lower":120.0000,"count":71,"preSum":1004},{"ndv":29,"upper":141.7500,"lower":130.6800,"count":71,"preSum":1075},{"ndv":27,"upper":161.9200,"lower":142.1520,"count":74,"preSum":1146},{"ndv":41,"upper":192.0000,"lower":164.2080,"count":71,"preSum":1220},{"ndv":36,"upper":221.0000,"lower":193.0500,"count":71,"preSum":1291},{"ndv":37,"upper":239.7780,"lower":221.4520,"count":75,"preSum":1362},{"ndv":31,"upper":255.9070,"lower":240.1960,"count":71,"preSum":1437},{"ndv":30,"upper":273.2400,"lower":255.9380,"count":78,"preSum":1508},{"ndv":32,"upper":289.7750,"lower":273.3250,"count":75,"preSum":1586},{"ndv":36,"upper":313.4380,"lower":290.7550,"count":73,"preSum":1661},{"ndv":36,"upper":330.0000,"lower":314.5830,"count":74,"preSum":1734},{"ndv":35,"upper":350.3960,"lower":330.2500,"count":71,"preSum":1808},{"ndv":39,"upper":376.1330,"lower":350.7680,"count":71,"preSum":1879},{"ndv":38,"upper":405.5590,"lower":376.5850,"count":71,"preSum":1950},{"ndv":30,"upper":425.2160,"lower":408.3330,"count":71,"preSum":2021},{"ndv":37,"upper":448.8750,"lower":425.2500,"count":73,"preSum":2092},{"ndv":33,"upper":472.5000,"lower":450.3960,"count":72,"preSum":2165},{"ndv":38,"upper":501.0890,"lower":474.2920,"count":71,"preSum":2237},{"ndv":44,"upper":537.3200,"lower":504.3760,"count":72,"preSum":2308},{"ndv":35,"upper":561.0000,"lower":537.3960,"count":73,"preSum":2380},{"ndv":27,"upper":583.1460,"lower":561.0800,"count":71,"preSum":2453},{"ndv":23,"upper":599.1560,"lower":583.3330,"count":71,"preSum":2524},{"ndv":27,"upper":617.5000,"lower":599.5160,"count":72,"preSum":2595},{"ndv":32,"upper":649.0420,"lower":619.6670,"count":71,"preSum":2667},{"ndv":31,"upper":681.3100,"lower":649.3670,"count":71,"preSum":2738},{"ndv":26,"upper":710.9160,"lower":683.7890,"count":80,"preSum":2809},{"ndv":39,"upper":770.0000,"lower":711.1030,"count":72,"preSum":2889},{"ndv":30,"upper":831.2500,"lower":772.2000,"count":71,"preSum":2961},{"ndv":31,"upper":915.9000,"lower":835.4060,"count":72,"preSum":3032},{"ndv":41,"upper":1074.9340,"lower":917.3330,"count":75,"preSum":3104},{"ndv":41,"upper":1286.4720,"lower":1077.7400,"count":71,"preSum":3179},{"ndv":40,"upper":1525.6320,"lower":1286.6800,"count":71,"preSum":3250},{"ndv":43,"upper":1998.0000,"lower":1529.7100,"count":71,"preSum":3321},{"ndv":52,"upper":2592.0000,"lower":2008.1300,"count":72,"preSum":3392},{"ndv":45,"upper":3172.0500,"lower":2614.3330,"count":72,"preSum":3464},{"ndv":47,"upper":4136.0630,"lower":3180.1000,"count":71,"preSum":3536},{"ndv":48,"upper":4814.1700,"lower":4142.7540,"count":72,"preSum":3607},{"ndv":42,"upper":5550.0000,"lower":4859.8000,"count":71,"preSum":3679},{"ndv":34,"upper":6192.5310,"lower":5553.3330,"count":82,"preSum":3750},{"ndv":37,"upper":6692.4000,"lower":6208.3120,"count":73,"preSum":3832},{"ndv":41,"upper":7618.7500,"lower":6703.1250,"count":71,"preSum":3905},{"ndv":46,"upper":8911.8330,"lower":7686.0000,"count":71,"preSum":3976},{"ndv":40,"upper":10914.7500,"lower":8950.3780,"count":72,"preSum":4047},{"ndv":41,"upper":14280.0000,"lower":10972.5000,"count":71,"preSum":4119},{"ndv":45,"upper":18304.0000,"lower":14300.0000,"count":71,"preSum":4190},{"ndv":43,"upper":25480.0000,"lower":18468.0000,"count":71,"preSum":4261},{"ndv":37,"upper":36160.8000,"lower":25627.5000,"count":73,"preSum":4332},{"ndv":54,"upper":113322.0000,"lower":36570.0000,"count":71,"preSum":4405},{"ndv":23,"upper":1503480.0000,"lower":121451.0000,"count":32,"preSum":4476}],"maxBucketSize":64,"type":"Double","sampleRate":0.9553658}','{"countArr":[92215,40,3024,17,23,19,20,38,28,18,28,23],"valueArr":[0.0000,0.2000,1.0000,43.9370,54.0120,79.1200,90.4880,98.4050,157.4480,352.2440,581.8750,617.6290],"type":"Double","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','unitweight',6200,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":38,"upper":3.0000,"lower":0.0220,"count":66,"preSum":0},{"ndv":34,"upper":4.6430,"lower":3.0500,"count":68,"preSum":66},{"ndv":30,"upper":6.0790,"lower":4.7190,"count":72,"preSum":134},{"ndv":29,"upper":8.1110,"lower":6.1400,"count":66,"preSum":206},{"ndv":30,"upper":11.0000,"lower":8.4440,"count":67,"preSum":272},{"ndv":31,"upper":14.6880,"lower":11.1000,"count":66,"preSum":339},{"ndv":32,"upper":17.0000,"lower":14.7900,"count":69,"preSum":405},{"ndv":34,"upper":20.0000,"lower":17.0130,"count":70,"preSum":474},{"ndv":23,"upper":23.5000,"lower":20.0500,"count":72,"preSum":544},{"ndv":19,"upper":26.3890,"lower":23.6110,"count":66,"preSum":616},{"ndv":16,"upper":29.1670,"lower":26.6670,"count":71,"preSum":682},{"ndv":31,"upper":34.0000,"lower":29.2500,"count":68,"preSum":753},{"ndv":23,"upper":36.6670,"lower":34.2200,"count":72,"preSum":821},{"ndv":23,"upper":39.4440,"lower":36.7500,"count":69,"preSum":893},{"ndv":17,"upper":42.0830,"lower":39.5000,"count":66,"preSum":962},{"ndv":26,"upper":48.3330,"lower":42.5000,"count":68,"preSum":1028},{"ndv":27,"upper":55.5550,"lower":48.8890,"count":66,"preSum":1096},{"ndv":31,"upper":62.5000,"lower":56.0000,"count":67,"preSum":1162},{"ndv":23,"upper":69.0000,"lower":63.0000,"count":67,"preSum":1229},{"ndv":26,"upper":75.0000,"lower":69.1700,"count":70,"preSum":1296},{"ndv":18,"upper":81.0420,"lower":76.0000,"count":66,"preSum":1366},{"ndv":23,"upper":89.5830,"lower":81.2500,"count":70,"preSum":1432},{"ndv":24,"upper":97.9170,"lower":90.0000,"count":67,"preSum":1502},{"ndv":20,"upper":105.0000,"lower":98.0000,"count":67,"preSum":1569},{"ndv":25,"upper":115.6250,"lower":106.2500,"count":70,"preSum":1636},{"ndv":30,"upper":129.0000,"lower":115.6300,"count":66,"preSum":1706},{"ndv":20,"upper":137.5000,"lower":129.1670,"count":68,"preSum":1772},{"ndv":17,"upper":145.0000,"lower":138.0000,"count":66,"preSum":1840},{"ndv":19,"upper":157.2920,"lower":145.8330,"count":66,"preSum":1906},{"ndv":24,"upper":167.0000,"lower":158.3330,"count":66,"preSum":1972},{"ndv":19,"upper":177.0830,"lower":167.5000,"count":71,"preSum":2038},{"ndv":20,"upper":185.4170,"lower":178.0000,"count":73,"preSum":2109},{"ndv":15,"upper":194.0000,"lower":185.4200,"count":66,"preSum":2182},{"ndv":22,"upper":207.9160,"lower":194.7920,"count":68,"preSum":2248},{"ndv":19,"upper":218.7500,"lower":208.0000,"count":78,"preSum":2316},{"ndv":14,"upper":227.5000,"lower":219.3880,"count":66,"preSum":2394},{"ndv":14,"upper":235.4160,"lower":227.6320,"count":70,"preSum":2460},{"ndv":19,"upper":243.7500,"lower":235.4170,"count":70,"preSum":2530},{"ndv":23,"upper":264.5830,"lower":244.0000,"count":74,"preSum":2600},{"ndv":21,"upper":279.1670,"lower":265.6250,"count":73,"preSum":2674},{"ndv":20,"upper":292.7080,"lower":280.0000,"count":66,"preSum":2747},{"ndv":18,"upper":309.3750,"lower":293.3300,"count":66,"preSum":2813},{"ndv":28,"upper":333.3330,"lower":309.3800,"count":67,"preSum":2879},{"ndv":31,"upper":360.8330,"lower":333.7210,"count":66,"preSum":2946},{"ndv":24,"upper":391.6670,"lower":361.4580,"count":71,"preSum":3012},{"ndv":23,"upper":416.6670,"lower":392.5000,"count":67,"preSum":3083},{"ndv":36,"upper":500.0000,"lower":417.8570,"count":67,"preSum":3150},{"ndv":31,"upper":600.0000,"lower":508.3330,"count":79,"preSum":3217},{"ndv":27,"upper":675.0000,"lower":604.1670,"count":66,"preSum":3296},{"ndv":32,"upper":800.0000,"lower":680.0000,"count":74,"preSum":3362},{"ndv":31,"upper":991.2500,"lower":808.3330,"count":67,"preSum":3436},{"ndv":23,"upper":1063.0000,"lower":1000.0000,"count":66,"preSum":3503},{"ndv":27,"upper":1158.3330,"lower":1066.6670,"count":67,"preSum":3569},{"ndv":21,"upper":1250.0000,"lower":1166.6660,"count":69,"preSum":3636},{"ndv":23,"upper":1383.3330,"lower":1258.3330,"count":72,"preSum":3705},{"ndv":27,"upper":1518.0000,"lower":1385.0000,"count":67,"preSum":3777},{"ndv":36,"upper":1805.0000,"lower":1524.0000,"count":66,"preSum":3844},{"ndv":30,"upper":2300.0000,"lower":1806.2500,"count":66,"preSum":3910},{"ndv":24,"upper":3340.0000,"lower":2312.5000,"count":66,"preSum":3976},{"ndv":26,"upper":4800.0000,"lower":3350.0000,"count":67,"preSum":4042},{"ndv":36,"upper":11030.0000,"lower":4850.0000,"count":66,"preSum":4109},{"ndv":22,"upper":98000.0000,"lower":11850.0000,"count":33,"preSum":4175}],"maxBucketSize":64,"type":"Double","sampleRate":0.9553658}','{"countArr":[92438,49,3023,40,23,43,25,23,36,23,23,24,23],"valueArr":[0.0000,0.1000,1.0000,24.0200,32.5000,41.6670,45.8330,125.0000,152.0830,193.7500,221.8750,250.0000,362.5000],"type":"Double","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','unitwidth',461,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":3.1900,"lower":2.7800,"count":8,"preSum":0},{"ndv":2,"upper":9.0500,"lower":6.0000,"count":7,"preSum":8},{"ndv":4,"upper":15.0000,"lower":10.3400,"count":8,"preSum":15},{"ndv":5,"upper":17.8000,"lower":15.1100,"count":8,"preSum":23},{"ndv":4,"upper":19.5500,"lower":17.9200,"count":11,"preSum":31},{"ndv":3,"upper":21.0000,"lower":19.6000,"count":8,"preSum":42},{"ndv":4,"upper":24.0000,"lower":21.8000,"count":9,"preSum":50},{"ndv":5,"upper":25.2000,"lower":24.2000,"count":17,"preSum":59},{"ndv":2,"upper":26.0000,"lower":25.5200,"count":7,"preSum":76},{"ndv":3,"upper":28.0000,"lower":26.2900,"count":10,"preSum":83},{"ndv":3,"upper":28.8500,"lower":28.3400,"count":10,"preSum":93},{"ndv":4,"upper":29.8000,"lower":28.8800,"count":8,"preSum":103},{"ndv":3,"upper":31.0000,"lower":30.5000,"count":11,"preSum":111},{"ndv":2,"upper":32.0000,"lower":31.5000,"count":10,"preSum":122},{"ndv":2,"upper":34.0000,"lower":33.0000,"count":7,"preSum":132},{"ndv":4,"upper":36.0000,"lower":34.2000,"count":8,"preSum":139},{"ndv":3,"upper":37.0000,"lower":36.6000,"count":7,"preSum":147},{"ndv":2,"upper":37.5000,"lower":37.0700,"count":7,"preSum":154},{"ndv":2,"upper":38.0000,"lower":37.7900,"count":11,"preSum":161},{"ndv":3,"upper":41.0000,"lower":38.3000,"count":7,"preSum":172},{"ndv":1,"upper":42.0000,"lower":42.0000,"count":10,"preSum":179},{"ndv":1,"upper":43.0000,"lower":43.0000,"count":11,"preSum":189},{"ndv":4,"upper":47.5000,"lower":43.5000,"count":14,"preSum":200},{"ndv":3,"upper":51.0000,"lower":49.0000,"count":12,"preSum":214},{"ndv":1,"upper":52.0000,"lower":52.0000,"count":7,"preSum":226},{"ndv":3,"upper":55.0000,"lower":54.0000,"count":10,"preSum":233},{"ndv":4,"upper":58.5000,"lower":56.5000,"count":8,"preSum":243},{"ndv":2,"upper":61.0000,"lower":60.0000,"count":7,"preSum":251},{"ndv":4,"upper":63.4100,"lower":61.9000,"count":8,"preSum":258},{"ndv":2,"upper":65.0000,"lower":63.9900,"count":7,"preSum":266},{"ndv":1,"upper":66.0000,"lower":66.0000,"count":8,"preSum":273},{"ndv":4,"upper":70.0000,"lower":67.0000,"count":7,"preSum":281},{"ndv":1,"upper":70.2800,"lower":70.2800,"count":7,"preSum":288},{"ndv":3,"upper":71.5000,"lower":70.5000,"count":7,"preSum":295},{"ndv":1,"upper":72.0000,"lower":72.0000,"count":8,"preSum":302},{"ndv":1,"upper":74.0000,"lower":74.0000,"count":8,"preSum":310},{"ndv":1,"upper":75.0000,"lower":75.0000,"count":8,"preSum":318},{"ndv":2,"upper":77.0000,"lower":76.0000,"count":13,"preSum":326},{"ndv":2,"upper":80.0000,"lower":78.0000,"count":8,"preSum":339},{"ndv":3,"upper":90.0000,"lower":85.0000,"count":12,"preSum":347},{"ndv":2,"upper":94.0000,"lower":92.0000,"count":7,"preSum":359},{"ndv":5,"upper":110.0000,"lower":95.0000,"count":7,"preSum":366},{"ndv":5,"upper":136.0000,"lower":120.0000,"count":9,"preSum":373},{"ndv":3,"upper":150.0000,"lower":140.0000,"count":8,"preSum":382},{"ndv":3,"upper":160.0000,"lower":153.0000,"count":7,"preSum":390},{"ndv":3,"upper":190.0000,"lower":162.0000,"count":7,"preSum":397},{"ndv":4,"upper":200.0000,"lower":194.0000,"count":12,"preSum":404},{"ndv":4,"upper":210.0000,"lower":202.0000,"count":7,"preSum":416},{"ndv":6,"upper":227.0000,"lower":214.0000,"count":7,"preSum":423},{"ndv":4,"upper":250.6000,"lower":230.0000,"count":7,"preSum":430},{"ndv":1,"upper":282.5000,"lower":282.5000,"count":1,"preSum":437}],"maxBucketSize":64,"type":"Double","sampleRate":0.9553658}','{"countArr":[99285,16,41,26,12,23,29,24,23,30,13,12,16,13],"valueArr":[0.0000,3.5900,22.0000,25.0000,25.5000,30.0000,35.0000,40.0000,44.0000,45.0000,47.0000,48.0000,50.0000,56.0000],"type":"Double","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','userdef1',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}',null,100001,0.025981193),('jala_wms_prod','item_packing_detail','userdef2',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}',null,100001,0.025981193),('jala_wms_prod','item_packing_detail','userdef3',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}',null,100001,0.025981193),('jala_wms_prod','item_packing_detail','userdef4',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}',null,100001,0.025981193),('jala_wms_prod','item_packing_detail','userdef5',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}',null,100001,0.025981193),('jala_wms_prod','item_packing_detail','userdef6',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}',null,100001,0.025981193),('jala_wms_prod','item_packing_detail','userdef7',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}',null,100001,0.025981193),('jala_wms_prod','item_packing_detail','userdef8',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}',null,100001,0.025981193); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('jala_wms_prod','item_packing_detail','version',542,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":7,"lower":7,"count":446,"preSum":0},{"ndv":2,"upper":10,"lower":9,"count":515,"preSum":446},{"ndv":2,"upper":12,"lower":11,"count":620,"preSum":961},{"ndv":2,"upper":14,"lower":13,"count":366,"preSum":1581},{"ndv":1,"upper":16,"lower":16,"count":408,"preSum":1947},{"ndv":2,"upper":18,"lower":17,"count":276,"preSum":2355},{"ndv":1,"upper":19,"lower":19,"count":241,"preSum":2631},{"ndv":3,"upper":23,"lower":21,"count":370,"preSum":2872},{"ndv":1,"upper":24,"lower":24,"count":363,"preSum":3242},{"ndv":2,"upper":28,"lower":25,"count":517,"preSum":3605},{"ndv":2,"upper":32,"lower":30,"count":238,"preSum":4122},{"ndv":2,"upper":34,"lower":33,"count":389,"preSum":4360},{"ndv":1,"upper":35,"lower":35,"count":323,"preSum":4749},{"ndv":2,"upper":37,"lower":36,"count":384,"preSum":5072},{"ndv":1,"upper":38,"lower":38,"count":265,"preSum":5456},{"ndv":2,"upper":40,"lower":39,"count":344,"preSum":5721},{"ndv":2,"upper":42,"lower":41,"count":257,"preSum":6065},{"ndv":3,"upper":45,"lower":43,"count":420,"preSum":6322},{"ndv":3,"upper":48,"lower":46,"count":300,"preSum":6742},{"ndv":3,"upper":51,"lower":49,"count":284,"preSum":7042},{"ndv":2,"upper":53,"lower":52,"count":263,"preSum":7326},{"ndv":2,"upper":55,"lower":54,"count":282,"preSum":7589},{"ndv":2,"upper":57,"lower":56,"count":283,"preSum":7871},{"ndv":3,"upper":60,"lower":58,"count":442,"preSum":8154},{"ndv":2,"upper":62,"lower":61,"count":319,"preSum":8596},{"ndv":1,"upper":63,"lower":63,"count":279,"preSum":8915},{"ndv":1,"upper":64,"lower":64,"count":246,"preSum":9194},{"ndv":2,"upper":66,"lower":65,"count":266,"preSum":9440},{"ndv":2,"upper":68,"lower":67,"count":267,"preSum":9706},{"ndv":2,"upper":70,"lower":69,"count":248,"preSum":9973},{"ndv":3,"upper":73,"lower":71,"count":296,"preSum":10221},{"ndv":2,"upper":75,"lower":74,"count":249,"preSum":10517},{"ndv":3,"upper":78,"lower":76,"count":233,"preSum":10766},{"ndv":3,"upper":81,"lower":79,"count":333,"preSum":10999},{"ndv":3,"upper":84,"lower":82,"count":288,"preSum":11332},{"ndv":4,"upper":88,"lower":85,"count":241,"preSum":11620},{"ndv":4,"upper":92,"lower":89,"count":240,"preSum":11861},{"ndv":4,"upper":96,"lower":93,"count":287,"preSum":12101},{"ndv":5,"upper":101,"lower":97,"count":256,"preSum":12388},{"ndv":5,"upper":106,"lower":102,"count":281,"preSum":12644},{"ndv":6,"upper":112,"lower":107,"count":294,"preSum":12925},{"ndv":7,"upper":119,"lower":113,"count":245,"preSum":13219},{"ndv":8,"upper":127,"lower":120,"count":250,"preSum":13464},{"ndv":14,"upper":141,"lower":128,"count":239,"preSum":13714},{"ndv":15,"upper":156,"lower":142,"count":237,"preSum":13953},{"ndv":24,"upper":180,"lower":157,"count":253,"preSum":14190},{"ndv":55,"upper":243,"lower":181,"count":233,"preSum":14443},{"ndv":64,"upper":588,"lower":244,"count":122,"preSum":14676}],"maxBucketSize":64,"type":"Int","sampleRate":0.9553658}','{"countArr":[77074,850,553,547,672,838,511,555,487,530,520,912,532,622],"valueArr":[0,1,2,3,4,5,6,8,15,20,26,27,29,31],"type":"Int","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','item_packing_detail','warehousecode',13,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9553658}','{"countArr":[16075,9740,9653,5984,9334,1624,10605,4879,5409,5621,5376,9387,6314],"valueArr":["021DC1","022DC","027DC","028DC","573DC","573DJX","763DC","763DCA","SH01","SH02","SH03","TEST01","TEST02"],"type":"String","sampleRate":0.9553657581229161}',0,0.025981193),('jala_wms_prod','shipment_detail','agingdate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Date","sampleRate":1.0}','{"countArr":[88574],"valueArr":[-1],"type":"Date","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','aitem',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','allocationrule',72,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"D001中外运拣货","lower":"","count":50,"preSum":0},{"ndv":2,"upper":"D001拣货区拣货波次规则","lower":"D001借货暂放区拣货规则","count":91,"preSum":50},{"ndv":1,"upper":"D002拣货分配规则","lower":"D002拣货分配规则","count":91,"preSum":141},{"ndv":1,"upper":"D002拣货分配规则(新)","lower":"D002拣货分配规则(新)","count":84,"preSum":232},{"ndv":1,"upper":"D002拣货区拣货波次","lower":"D002拣货区拣货波次","count":27,"preSum":316},{"ndv":1,"upper":"D002整托散零分配规则","lower":"D002整托散零分配规则","count":26,"preSum":343},{"ndv":1,"upper":"D003存储分配规则","lower":"D003存储分配规则","count":81,"preSum":369},{"ndv":3,"upper":"D011拣货分配规则","lower":"D003整存区拣货波次","count":81,"preSum":450},{"ndv":1,"upper":"D011拣货分配规则(新)","lower":"D011拣货分配规则(新)","count":97,"preSum":531},{"ndv":1,"upper":"D011拣货区拣货波次","lower":"D011拣货区拣货波次","count":42,"preSum":628},{"ndv":2,"upper":"S116拣货规则","lower":"LOST18指定货位拣货规则","count":26,"preSum":670},{"ndv":1,"upper":"TEST","lower":"TEST","count":53,"preSum":696},{"ndv":2,"upper":"W007拣货规则1","lower":"W007拣货规则","count":52,"preSum":749},{"ndv":2,"upper":"W028拣货规则","lower":"W009拣货规则","count":95,"preSum":801},{"ndv":2,"upper":"京东拣货规则","lower":"京东小于36支","count":49,"preSum":896},{"ndv":2,"upper":"屈臣氏1效期拣货规则(2023222)","lower":"仓内货主B-C互转波次","count":28,"preSum":945},{"ndv":1,"upper":"屈臣氏2效期拣货规则","lower":"屈臣氏2效期拣货规则","count":19,"preSum":973},{"ndv":2,"upper":"屈臣氏单效期拣货规则","lower":"屈臣氏D011拣货区拣货波次","count":44,"preSum":992},{"ndv":1,"upper":"屈臣氏单效期拣货规则(202322)","lower":"屈臣氏单效期拣货规则(202322)","count":40,"preSum":1036},{"ndv":1,"upper":"屈臣氏单效期拣货规则(新)","lower":"屈臣氏单效期拣货规则(新)","count":40,"preSum":1076},{"ndv":1,"upper":"平台效期波次(19、27、35)","lower":"平台效期波次(19、27、35)","count":41,"preSum":1116},{"ndv":2,"upper":"新托+箱+支 /存储区拣货","lower":"按批次分配规则","count":52,"preSum":1157}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[2070,1255,1010,5205,2629,17464,42204,257,5498,110,338,655,1139,1780],"valueArr":["2B按单拣货波次规则","2B按单拣货波次规则-不补货","2B正常零拣波次拣货规则","2C提总单波次规则","2C提总单波次规则-存储区出库","2C散单波次规则","2C正常波次拣货规则","2C预包单提总单波次","2C预售已付尾款指定货位拣货规则","D011整托散零分配规则","W013拣货规则","新托+箱+支 /存储区不拣货","货主1000区域","货主1001区域"],"type":"String","sampleRate":1.0}',5751,0.009150696),('jala_wms_prod','shipment_detail','attribute1',25,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"分仓","lower":"分仓","count":1,"preSum":0},{"ndv":1,"upper":"总仓","lower":"总仓","count":2,"preSum":1},{"ndv":1,"upper":"质量召回","lower":"质量召回","count":2,"preSum":3}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36,3,3,8,368,7,14,4],"valueArr":["","0","W028调入","商超渠道","电商渠道","美妆店渠道","美妆渠道","货架渠道"],"type":"String","sampleRate":1.0}',88126,0.009150696),('jala_wms_prod','shipment_detail','attribute2',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','attribute3',126912,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":420,"upper":"PJX2303762215210616","lower":"CK0001537175","count":1151,"preSum":0},{"ndv":407,"upper":"PJX2304779971271222","lower":"PJX2303762215280616","count":1151,"preSum":1151},{"ndv":393,"upper":"PJX2304786709082616","lower":"PJX2304779971551222","count":1155,"preSum":2302},{"ndv":345,"upper":"PJX2305791609340320","lower":"PJX2304786709182616","count":1151,"preSum":3457},{"ndv":326,"upper":"PJX2305795400331015","lower":"PJX2305791609350320","count":1151,"preSum":4608},{"ndv":373,"upper":"PJX2305798104271513","lower":"PJX2305795400821015","count":1155,"preSum":5759},{"ndv":349,"upper":"PJX2305800989042014","lower":"PJX2305798104381513","count":1153,"preSum":6914},{"ndv":415,"upper":"PJX2305806378912715","lower":"PJX2305800989082014","count":1155,"preSum":8067},{"ndv":398,"upper":"PJX2306812524310200","lower":"PJX2305806383692715","count":1153,"preSum":9222},{"ndv":378,"upper":"POD2305794152410810","lower":"PJX2306812524430200","count":1155,"preSum":10375},{"ndv":338,"upper":"POD2305808463062910","lower":"POD2305794152430810","count":1152,"preSum":11530},{"ndv":327,"upper":"PSD2304784277792114","lower":"POD2305808464852910","count":1159,"preSum":12682},{"ndv":273,"upper":"PSD2304784917602222","lower":"PSD2304784283992114","count":1152,"preSum":13841},{"ndv":339,"upper":"PSD2304786000062510","lower":"PSD2304784917642222","count":1154,"preSum":14993},{"ndv":269,"upper":"PSD2304786976162710","lower":"PSD2304786008382510","count":1153,"preSum":16147},{"ndv":338,"upper":"PSD2304788116642911","lower":"PSD2304786994322711","count":1155,"preSum":17300},{"ndv":329,"upper":"PSD2305789076120110","lower":"PSD2304788116682911","count":1153,"preSum":18455},{"ndv":277,"upper":"PSD2305790169210222","lower":"PSD2305789076140110","count":1152,"preSum":19608},{"ndv":292,"upper":"PSD2305792499740501","lower":"PSD2305790169660222","count":1156,"preSum":20760},{"ndv":329,"upper":"PSD2305793329710614","lower":"PSD2305792499750501","count":1152,"preSum":21916},{"ndv":325,"upper":"PSD2305794173180810","lower":"PSD2305793329760614","count":1151,"preSum":23068},{"ndv":350,"upper":"PSD2305795251241010","lower":"PSD2305794173190810","count":1154,"preSum":24219},{"ndv":314,"upper":"PSD2305796347701209","lower":"PSD2305795256991010","count":1151,"preSum":25373},{"ndv":291,"upper":"PSD2305797297521401","lower":"PSD2305796352581209","count":1154,"preSum":26524},{"ndv":306,"upper":"PSD2305798041331511","lower":"PSD2305797297631401","count":1162,"preSum":27678},{"ndv":330,"upper":"PSD2305799721591723","lower":"PSD2305798041631511","count":1157,"preSum":28840},{"ndv":286,"upper":"PSD2305800484451913","lower":"PSD2305799722621723","count":1157,"preSum":29997},{"ndv":266,"upper":"PSD2305801246062023","lower":"PSD2305800511591915","count":1151,"preSum":31154},{"ndv":238,"upper":"PSD2305801731962120","lower":"PSD2305801249262023","count":1152,"preSum":32305},{"ndv":283,"upper":"PSD2305802660522320","lower":"PSD2305801731972120","count":1156,"preSum":33457},{"ndv":383,"upper":"PSD2305803795462610","lower":"PSD2305802660562320","count":1161,"preSum":34613},{"ndv":314,"upper":"PSD2305807533542815","lower":"PSD2305803804372610","count":1151,"preSum":35774},{"ndv":317,"upper":"PSD2305808978942923","lower":"PSD2305807533552815","count":1156,"preSum":36925},{"ndv":394,"upper":"PSD2305810874863121","lower":"PSD2305808979012923","count":1151,"preSum":38081},{"ndv":307,"upper":"PSD2306812839160212","lower":"PSD2305810875013121","count":1151,"preSum":39232},{"ndv":477,"upper":"PTB2303767495601400","lower":"PSD2306812842740212","count":1151,"preSum":40383},{"ndv":527,"upper":"PTB2304777985950819","lower":"PTB2303767496461400","count":1152,"preSum":41534},{"ndv":562,"upper":"PTB2304783230091907","lower":"PTB2304777986200819","count":1151,"preSum":42686},{"ndv":512,"upper":"PTB2304785718032421","lower":"PTB2304783263741909","count":1154,"preSum":43837},{"ndv":435,"upper":"PTB2304787067422713","lower":"PTB2304785781522421","count":1155,"preSum":44991},{"ndv":478,"upper":"PTB2305788700190106","lower":"PTB2304787067452713","count":1151,"preSum":46146},{"ndv":498,"upper":"PTB2305789837040217","lower":"PTB2305788700290106","count":1151,"preSum":47297},{"ndv":438,"upper":"PTB2305790763570310","lower":"PTB2305789838130217","count":1153,"preSum":48448},{"ndv":411,"upper":"PTB2305791293640311","lower":"PTB2305790763600310","count":1152,"preSum":49601},{"ndv":381,"upper":"PTB2305791964910409","lower":"PTB2305791293670311","count":1153,"preSum":50753},{"ndv":428,"upper":"PTB2305793839510716","lower":"PTB2305791964970409","count":1151,"preSum":51906},{"ndv":464,"upper":"PTB2305795782241109","lower":"PTB2305793840300716","count":1151,"preSum":53057},{"ndv":453,"upper":"PTB2305797295291401","lower":"PTB2305795782621109","count":1151,"preSum":54208},{"ndv":552,"upper":"PTB2305799360001711","lower":"PTB2305797295421401","count":1152,"preSum":55359},{"ndv":490,"upper":"PTB2305800948752013","lower":"PTB2305799367661711","count":1156,"preSum":56511},{"ndv":573,"upper":"PTB2305802839042408","lower":"PTB2305800950052013","count":1151,"preSum":57667},{"ndv":497,"upper":"PTB2305804482542710","lower":"PTB2305802839402408","count":1152,"preSum":58818},{"ndv":449,"upper":"PTB2305804972222711","lower":"PTB2305804482952710","count":1154,"preSum":59970},{"ndv":442,"upper":"PTB2305805477602711","lower":"PTB2305804972262711","count":1152,"preSum":61124},{"ndv":461,"upper":"PTB2305805998112713","lower":"PTB2305805477832711","count":1151,"preSum":62276},{"ndv":548,"upper":"PTB2305806724072717","lower":"PTB2305805998292713","count":1153,"preSum":63427},{"ndv":428,"upper":"PTB2305807520602815","lower":"PTB2305806727782717","count":1151,"preSum":64580},{"ndv":469,"upper":"PTB2305808127612820","lower":"PTB2305807520662815","count":1151,"preSum":65731},{"ndv":433,"upper":"PTB2305809088543009","lower":"PTB2305808129122820","count":1151,"preSum":66882},{"ndv":475,"upper":"PTB2305810021743112","lower":"PTB2305809088643009","count":1152,"preSum":68033},{"ndv":452,"upper":"PTB2305810687753121","lower":"PTB2305810021813112","count":1153,"preSum":69185},{"ndv":451,"upper":"PTB2306811299330100","lower":"PTB2305810687933121","count":1151,"preSum":70338},{"ndv":420,"upper":"PTB2306812039240115","lower":"PTB2306811299410100","count":1153,"preSum":71489},{"ndv":448,"upper":"PTB2306813092880218","lower":"PTB2306812039260115","count":1016,"preSum":72642}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36,17,18,17,21,18,17],"valueArr":["","PJX2306812180750117","POD2305799555691717","PSD2305802684802321","PTB2304788415812923","PTB2305795838041110","PTB2306811706960110"],"type":"String","sampleRate":1.0}',14772,0.009150696),('jala_wms_prod','shipment_detail','attribute4',443,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"2082629","lower":"2049369","count":8,"preSum":0},{"ndv":1,"upper":"2138480","lower":"2138480","count":8,"preSum":8},{"ndv":1,"upper":"CK0001295330","lower":"CK0001295330","count":5,"preSum":16},{"ndv":2,"upper":"CK0001333859","lower":"CK0001295360","count":11,"preSum":21},{"ndv":3,"upper":"CK0001351805","lower":"CK0001333866","count":6,"preSum":32},{"ndv":2,"upper":"CK0001351821","lower":"CK0001351810","count":7,"preSum":38},{"ndv":3,"upper":"CK0001351842","lower":"CK0001351822","count":5,"preSum":45},{"ndv":3,"upper":"CK0001351951","lower":"CK0001351843","count":9,"preSum":50},{"ndv":2,"upper":"CK0001382537","lower":"CK0001351967","count":7,"preSum":59},{"ndv":1,"upper":"CK0001382576","lower":"CK0001382576","count":7,"preSum":66},{"ndv":3,"upper":"CK0001404769","lower":"CK0001382631","count":10,"preSum":73},{"ndv":3,"upper":"CK0001413429","lower":"CK0001408648","count":5,"preSum":83},{"ndv":2,"upper":"CK0001416730","lower":"CK0001416725-1","count":6,"preSum":88},{"ndv":1,"upper":"CK0001416732","lower":"CK0001416732","count":5,"preSum":94},{"ndv":2,"upper":"CK0001417558","lower":"CK0001416909","count":8,"preSum":99},{"ndv":5,"upper":"CK0001424743","lower":"CK0001417578","count":5,"preSum":107},{"ndv":2,"upper":"CK0001425929","lower":"CK0001424859","count":5,"preSum":112},{"ndv":2,"upper":"CK0001426894","lower":"CK0001426110","count":7,"preSum":117},{"ndv":1,"upper":"CK0001426896","lower":"CK0001426896","count":5,"preSum":124},{"ndv":1,"upper":"CK0001426919","lower":"CK0001426919","count":6,"preSum":129},{"ndv":4,"upper":"CK0001432691","lower":"CK0001426946","count":7,"preSum":135},{"ndv":3,"upper":"CK0001449640","lower":"CK0001434141","count":10,"preSum":142},{"ndv":1,"upper":"CK0001449660","lower":"CK0001449660","count":6,"preSum":152},{"ndv":4,"upper":"CK0001459744","lower":"CK0001450250","count":9,"preSum":158},{"ndv":4,"upper":"CK0001460501","lower":"CK0001459969","count":7,"preSum":167},{"ndv":3,"upper":"CK0001460559","lower":"CK0001460534","count":6,"preSum":174},{"ndv":2,"upper":"CK0001481741","lower":"CK0001472788","count":11,"preSum":180},{"ndv":2,"upper":"CK0001481834","lower":"CK0001481831","count":6,"preSum":191},{"ndv":1,"upper":"CK0001481836","lower":"CK0001481836","count":7,"preSum":197},{"ndv":1,"upper":"CK0001481839","lower":"CK0001481839","count":8,"preSum":204},{"ndv":1,"upper":"CK0001492668","lower":"CK0001492668","count":5,"preSum":212},{"ndv":1,"upper":"CK0001497744","lower":"CK0001497744","count":6,"preSum":217},{"ndv":2,"upper":"CK0001497811","lower":"CK0001497782","count":5,"preSum":223},{"ndv":5,"upper":"CK0001498207","lower":"CK0001497899","count":5,"preSum":228},{"ndv":1,"upper":"CK0001498239","lower":"CK0001498239","count":5,"preSum":233},{"ndv":1,"upper":"CK0001507940","lower":"CK0001507940","count":6,"preSum":238},{"ndv":1,"upper":"CK0001518880","lower":"CK0001518880","count":7,"preSum":244},{"ndv":2,"upper":"CK0001537587","lower":"CK0001518982","count":8,"preSum":251}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36,12,27,11,13,16,13,30,21,19,9,12,10],"valueArr":["","CK0001400614","CK0001408649","CK0001411031","CK0001416902","CK0001432545","CK0001434811","CK0001456539","CK0001513286","CK0001518126","CK0001519017","CK0001519088","CK0001535906"],"type":"String","sampleRate":1.0}',88086,0.009150696),('jala_wms_prod','shipment_detail','attribute5',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','attribute6',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','attribute7',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','attribute8',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','backorderlinenum',528,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":3055182,"lower":3055182,"count":1,"preSum":0},{"ndv":1,"upper":3220190,"lower":3220190,"count":1,"preSum":1},{"ndv":1,"upper":3232657,"lower":3232657,"count":1,"preSum":2},{"ndv":1,"upper":3328016,"lower":3328016,"count":1,"preSum":3},{"ndv":1,"upper":3471907,"lower":3471907,"count":1,"preSum":4},{"ndv":1,"upper":5376704,"lower":5376704,"count":1,"preSum":5},{"ndv":1,"upper":5376829,"lower":5376829,"count":1,"preSum":6},{"ndv":1,"upper":5430331,"lower":5430331,"count":1,"preSum":7},{"ndv":1,"upper":5808895,"lower":5808895,"count":1,"preSum":8},{"ndv":1,"upper":5815452,"lower":5815452,"count":1,"preSum":9},{"ndv":1,"upper":6101651,"lower":6101651,"count":1,"preSum":10},{"ndv":1,"upper":6101806,"lower":6101806,"count":1,"preSum":11},{"ndv":1,"upper":6101925,"lower":6101925,"count":1,"preSum":12},{"ndv":1,"upper":6102080,"lower":6102080,"count":1,"preSum":13},{"ndv":1,"upper":6102089,"lower":6102089,"count":1,"preSum":14},{"ndv":1,"upper":6102201,"lower":6102201,"count":1,"preSum":15},{"ndv":1,"upper":6102342,"lower":6102342,"count":1,"preSum":16},{"ndv":1,"upper":6102736,"lower":6102736,"count":1,"preSum":17},{"ndv":1,"upper":6103271,"lower":6103271,"count":1,"preSum":18},{"ndv":1,"upper":6103555,"lower":6103555,"count":1,"preSum":19},{"ndv":1,"upper":6104014,"lower":6104014,"count":1,"preSum":20},{"ndv":1,"upper":6104056,"lower":6104056,"count":1,"preSum":21},{"ndv":1,"upper":6104159,"lower":6104159,"count":1,"preSum":22},{"ndv":1,"upper":6123262,"lower":6123262,"count":1,"preSum":23},{"ndv":1,"upper":6123302,"lower":6123302,"count":1,"preSum":24},{"ndv":1,"upper":6407234,"lower":6407234,"count":1,"preSum":25},{"ndv":1,"upper":6447014,"lower":6447014,"count":1,"preSum":26},{"ndv":1,"upper":6447095,"lower":6447095,"count":1,"preSum":27},{"ndv":1,"upper":6447283,"lower":6447283,"count":1,"preSum":28}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88545],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','batch',17205,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":35,"upper":"0ZU22","lower":"000","count":112,"preSum":0},{"ndv":37,"upper":"15L22","lower":"111E1A411","count":112,"preSum":112},{"ndv":50,"upper":"172F22731","lower":"15T27","count":112,"preSum":224},{"ndv":34,"upper":"173F21511","lower":"172F23641","count":113,"preSum":336},{"ndv":58,"upper":"182F26051","lower":"173S30011","count":117,"preSum":449},{"ndv":29,"upper":"183F21121","lower":"182F26121","count":112,"preSum":566},{"ndv":50,"upper":"192F14861","lower":"183F21201","count":115,"preSum":678},{"ndv":29,"upper":"193F11461","lower":"192F14872","count":112,"preSum":793},{"ndv":51,"upper":"1YW09","lower":"193F11472","count":113,"preSum":905},{"ndv":49,"upper":"2206","lower":"1Z109","count":115,"preSum":1018},{"ndv":76,"upper":"221220060M","lower":"2206150701","count":112,"preSum":1133},{"ndv":32,"upper":"230131400A","lower":"222204301","count":112,"preSum":1245},{"ndv":51,"upper":"25521","lower":"2302","count":117,"preSum":1357},{"ndv":56,"upper":"26H08","lower":"25606","count":112,"preSum":1474},{"ndv":47,"upper":"26W06","lower":"26H09","count":115,"preSum":1586},{"ndv":28,"upper":"27830","lower":"26W09","count":113,"preSum":1701},{"ndv":41,"upper":"27U06","lower":"27922","count":114,"preSum":1814},{"ndv":37,"upper":"28F08","lower":"27U22","count":112,"preSum":1928},{"ndv":30,"upper":"29310","lower":"28G02","count":116,"preSum":2040},{"ndv":35,"upper":"29F29","lower":"29327","count":116,"preSum":2156},{"ndv":24,"upper":"29M22","lower":"29G02","count":118,"preSum":2272},{"ndv":26,"upper":"29W29","lower":"29M27","count":112,"preSum":2390},{"ndv":50,"upper":"2X801","lower":"2CS026","count":116,"preSum":2502},{"ndv":29,"upper":"2XD07","lower":"2X804","count":120,"preSum":2618},{"ndv":24,"upper":"2XJ48","lower":"2XD10","count":112,"preSum":2738},{"ndv":29,"upper":"2XP02","lower":"2XJL4","count":114,"preSum":2850},{"ndv":35,"upper":"2XUL4","lower":"2XP06","count":114,"preSum":2964},{"ndv":26,"upper":"2Y2L0","lower":"2XV01","count":113,"preSum":3078},{"ndv":31,"upper":"2Y729","lower":"2Y306","count":113,"preSum":3191},{"ndv":32,"upper":"2YC31","lower":"2Y730","count":119,"preSum":3304},{"ndv":31,"upper":"2YL21","lower":"2YE02","count":115,"preSum":3423},{"ndv":31,"upper":"2YR27","lower":"2YL26","count":114,"preSum":3538},{"ndv":22,"upper":"2YU63","lower":"2YR29","count":118,"preSum":3652},{"ndv":17,"upper":"2YW61","lower":"2YV01","count":113,"preSum":3770},{"ndv":21,"upper":"2Z624","lower":"2Z101","count":112,"preSum":3883},{"ndv":29,"upper":"2ZH23","lower":"2Z661","count":113,"preSum":3995},{"ndv":21,"upper":"31510","lower":"2ZJ01","count":113,"preSum":4108},{"ndv":31,"upper":"32120","lower":"31521","count":119,"preSum":4221},{"ndv":37,"upper":"32F30","lower":"32131","count":116,"preSum":4340},{"ndv":17,"upper":"32U27","lower":"32G08","count":112,"preSum":4456},{"ndv":19,"upper":"33601","lower":"33101","count":120,"preSum":4568},{"ndv":19,"upper":"33B01","lower":"33625","count":117,"preSum":4688},{"ndv":15,"upper":"33E06","lower":"33B06","count":124,"preSum":4805},{"ndv":20,"upper":"33J04","lower":"33E07","count":116,"preSum":4929},{"ndv":27,"upper":"33Q27","lower":"33J09","count":115,"preSum":5045},{"ndv":20,"upper":"34321","lower":"33Q73","count":114,"preSum":5160},{"ndv":27,"upper":"34908","lower":"34363","count":116,"preSum":5274},{"ndv":32,"upper":"34K21","lower":"34922","count":113,"preSum":5390},{"ndv":54,"upper":"372210151","lower":"34M02","count":113,"preSum":5503},{"ndv":71,"upper":"512110261","lower":"372210231","count":115,"preSum":5616},{"ndv":35,"upper":"552301061","lower":"512111101","count":116,"preSum":5731},{"ndv":62,"upper":"752210061","lower":"552301071","count":116,"preSum":5847},{"ndv":36,"upper":"752304101","lower":"752210082","count":112,"preSum":5963},{"ndv":38,"upper":"772212041","lower":"752304112","count":115,"preSum":6075},{"ndv":31,"upper":"772304101","lower":"772212042","count":113,"preSum":6190},{"ndv":51,"upper":"792212071","lower":"772304111","count":113,"preSum":6303},{"ndv":24,"upper":"792303141","lower":"792212091","count":112,"preSum":6416},{"ndv":41,"upper":"9YJ22","lower":"792303151","count":125,"preSum":6528},{"ndv":74,"upper":"CS3990011","lower":"9YV081217","count":122,"preSum":6653},{"ndv":95,"upper":"J02111121","lower":"CS3990012","count":112,"preSum":6775},{"ndv":39,"upper":"L82303151","lower":"J02111151","count":116,"preSum":6887},{"ndv":53,"upper":"V32209231","lower":"L82303251","count":113,"preSum":7003},{"ndv":7,"upper":"YPHP","lower":"V32209271","count":17,"preSum":7116}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[80033,29,65,65,36,29,99,54,32,31,27,314,249],"valueArr":["","082211061","2208","2209","2212","2301","230105","230106","29L22","33A05","33X27","JALA","N12012"],"type":"String","sampleRate":1.0}',378,0.009150696),('jala_wms_prod','shipment_detail','bomitemcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','canceledqty',34,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":450,"lower":450,"count":1,"preSum":0},{"ndv":1,"upper":480,"lower":480,"count":1,"preSum":1}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88572],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','companycode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[8415,1804,78355],"valueArr":["JALA01","JALA02","JALA11"],"type":"String","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','created',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','createdby',7,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"HLL","lower":"HLL","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[407,34,5,88014,107,5],"valueArr":["LL","XCY1","YBJ","api","lhj","yj"],"type":"String","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','csqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','deletedimension',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88567],"valueArr":[0],"type":"Int","sampleRate":1.0}',7,0.009150696),('jala_wms_prod','shipment_detail','dockloc',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','erpordercode',16432,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":207,"upper":"1679266","lower":"0001622095","count":239,"preSum":0},{"ndv":70,"upper":"23041986760486","lower":"1703161","count":236,"preSum":239},{"ndv":77,"upper":"23042300137917","lower":"23042000471306","count":235,"preSum":475},{"ndv":78,"upper":"23042553039724","lower":"23042300277358","count":237,"preSum":710},{"ndv":64,"upper":"23042658732869","lower":"23042553053124","count":235,"preSum":947},{"ndv":74,"upper":"23042852027159","lower":"23042658793369","count":235,"preSum":1182},{"ndv":83,"upper":"23050149668532","lower":"23042852623759","count":240,"preSum":1417},{"ndv":71,"upper":"23050278958753","lower":"23050157163315","count":235,"preSum":1657},{"ndv":79,"upper":"23050470165987","lower":"23050281087986","count":238,"preSum":1892},{"ndv":67,"upper":"23050648277343","lower":"23050470179187","count":235,"preSum":2130},{"ndv":73,"upper":"23050852132867","lower":"23050649441506","count":236,"preSum":2365},{"ndv":79,"upper":"23051069987975","lower":"23050853767356","count":237,"preSum":2601},{"ndv":71,"upper":"23051202885680","lower":"23051070107875","count":235,"preSum":2838},{"ndv":67,"upper":"23051323810382","lower":"23051204476580","count":240,"preSum":3073},{"ndv":82,"upper":"23051459605988","lower":"23051325422676","count":235,"preSum":3313},{"ndv":86,"upper":"23051602134948","lower":"23051461912244","count":239,"preSum":3548},{"ndv":86,"upper":"23051805347356","lower":"23051602360348","count":236,"preSum":3787},{"ndv":76,"upper":"23051971115382","lower":"23051808535915","count":235,"preSum":4023},{"ndv":75,"upper":"23052120366519","lower":"23051971745737","count":247,"preSum":4258},{"ndv":69,"upper":"23052368705472","lower":"23052122747719","count":236,"preSum":4505},{"ndv":85,"upper":"23052514094843","lower":"23052371356609","count":236,"preSum":4741},{"ndv":77,"upper":"23052695115653","lower":"23052514159343","count":239,"preSum":4977},{"ndv":86,"upper":"23052920585556","lower":"23052705303463","count":235,"preSum":5216},{"ndv":82,"upper":"23053096784684","lower":"23052921001083","count":236,"preSum":5451},{"ndv":89,"upper":"23060197473975","lower":"23053096896984","count":236,"preSum":5687},{"ndv":222,"upper":"40000232722","lower":"23060197557675","count":235,"preSum":5923},{"ndv":68,"upper":"CK0001181811","lower":"40000232728","count":251,"preSum":6158},{"ndv":75,"upper":"CK0001191184","lower":"CK0001181844","count":235,"preSum":6409},{"ndv":40,"upper":"CK0001209664","lower":"CK0001191498","count":239,"preSum":6644},{"ndv":31,"upper":"CK0001224392","lower":"CK0001209665","count":238,"preSum":6883},{"ndv":57,"upper":"CK0001250110","lower":"CK0001224401","count":236,"preSum":7121},{"ndv":50,"upper":"CK0001285869","lower":"CK0001250510","count":247,"preSum":7357},{"ndv":29,"upper":"CK0001290562","lower":"CK0001285871","count":253,"preSum":7604},{"ndv":26,"upper":"CK0001303182","lower":"CK0001290580","count":240,"preSum":7857},{"ndv":35,"upper":"CK0001330512","lower":"CK0001303590","count":238,"preSum":8097},{"ndv":50,"upper":"CK0001361268","lower":"CK0001332591","count":244,"preSum":8335},{"ndv":26,"upper":"CK0001367390","lower":"CK0001362035","count":242,"preSum":8579},{"ndv":29,"upper":"CK0001392093","lower":"CK0001367429","count":235,"preSum":8821},{"ndv":29,"upper":"CK0001408649","lower":"CK0001392199","count":249,"preSum":9056},{"ndv":70,"upper":"CK0001429465","lower":"CK0001409580","count":240,"preSum":9305},{"ndv":25,"upper":"CK0001436384","lower":"CK0001429977","count":235,"preSum":9545},{"ndv":57,"upper":"CK0001454553","lower":"CK0001437332","count":237,"preSum":9780},{"ndv":57,"upper":"CK0001464074","lower":"CK0001454636","count":235,"preSum":10017},{"ndv":55,"upper":"CK0001471942","lower":"CK0001464586","count":243,"preSum":10252},{"ndv":46,"upper":"CK0001475852","lower":"CK0001472030","count":235,"preSum":10495},{"ndv":22,"upper":"CK0001478672","lower":"CK0001475857","count":235,"preSum":10730},{"ndv":27,"upper":"CK0001482473","lower":"CK0001478864","count":238,"preSum":10965},{"ndv":29,"upper":"CK0001486748","lower":"CK0001482608","count":245,"preSum":11203},{"ndv":39,"upper":"CK0001492092","lower":"CK0001486828","count":245,"preSum":11448},{"ndv":34,"upper":"CK0001496288","lower":"CK0001492096","count":237,"preSum":11693},{"ndv":39,"upper":"CK0001499301","lower":"CK0001496400","count":235,"preSum":11930},{"ndv":29,"upper":"CK0001507803","lower":"CK0001499377","count":240,"preSum":12165},{"ndv":28,"upper":"CK0001513170","lower":"CK0001507940","count":237,"preSum":12405},{"ndv":39,"upper":"CK0001521919","lower":"CK0001513281","count":242,"preSum":12642},{"ndv":36,"upper":"CK0001526351","lower":"CK0001521920","count":236,"preSum":12884},{"ndv":27,"upper":"CK0001530629","lower":"CK0001526684","count":253,"preSum":13120},{"ndv":38,"upper":"CK0001534271","lower":"CK0001530707","count":235,"preSum":13373},{"ndv":25,"upper":"CK0001538232","lower":"CK0001534521","count":237,"preSum":13608},{"ndv":32,"upper":"CKH00000005180","lower":"CK0001538842","count":256,"preSum":13845},{"ndv":24,"upper":"CKH00000007343","lower":"CKH00000005184","count":250,"preSum":14101},{"ndv":26,"upper":"CKH00000009046","lower":"CKH00000007484","count":249,"preSum":14351},{"ndv":24,"upper":"CKH00000010157","lower":"CKH00000009292","count":238,"preSum":14600},{"ndv":16,"upper":"CKH00000011600","lower":"CKH00000010351","count":159,"preSum":14838}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[72778,30,30,30,30,30,31,30,30],"valueArr":["","CK0001359709","CK0001443350","CK0001456539","CK0001513362","CK0001532063","CKH00000005209","CKH00000006452","CKH00000008816"],"type":"String","sampleRate":1.0}',558,0.009150696),('jala_wms_prod','shipment_detail','erporderid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','erporderlinenum',2440126,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":15,"upper":"22","lower":"","count":1271,"preSum":0},{"ndv":751,"upper":"290439516","lower":"23","count":1264,"preSum":1271},{"ndv":1264,"upper":"293148248","lower":"290439524","count":1264,"preSum":2535},{"ndv":1264,"upper":"295555346","lower":"293148251","count":1264,"preSum":3799},{"ndv":1264,"upper":"297903405","lower":"295555357","count":1264,"preSum":5063},{"ndv":1264,"upper":"298888510","lower":"297903534","count":1264,"preSum":6327},{"ndv":1263,"upper":"299786452","lower":"298888880","count":1264,"preSum":7591},{"ndv":1216,"upper":"300002255","lower":"299786453","count":1264,"preSum":8855},{"ndv":1264,"upper":"300215345","lower":"300002271","count":1264,"preSum":10119},{"ndv":1264,"upper":"300478081","lower":"300215346","count":1264,"preSum":11383},{"ndv":1264,"upper":"300670022","lower":"300478083","count":1264,"preSum":12647},{"ndv":1261,"upper":"300828977","lower":"300670025","count":1264,"preSum":13911},{"ndv":1264,"upper":"301015794","lower":"300828978","count":1264,"preSum":15175},{"ndv":1264,"upper":"301229153","lower":"301015816","count":1264,"preSum":16439},{"ndv":1264,"upper":"301467851","lower":"301229155","count":1264,"preSum":17703},{"ndv":1264,"upper":"301651287","lower":"301467859","count":1264,"preSum":18967},{"ndv":1264,"upper":"301808610","lower":"301651288","count":1264,"preSum":20231},{"ndv":1264,"upper":"302004154","lower":"301808622","count":1264,"preSum":21495},{"ndv":1264,"upper":"302174161","lower":"302004185","count":1264,"preSum":22759},{"ndv":1261,"upper":"302465478","lower":"302174190","count":1264,"preSum":24023},{"ndv":1264,"upper":"302705315","lower":"302465479","count":1264,"preSum":25287},{"ndv":1264,"upper":"302846775","lower":"302705328","count":1264,"preSum":26551},{"ndv":1264,"upper":"303040832","lower":"302846802","count":1264,"preSum":27815},{"ndv":1264,"upper":"303243684","lower":"303040839","count":1264,"preSum":29079},{"ndv":1264,"upper":"303450007","lower":"303243739","count":1264,"preSum":30343},{"ndv":1264,"upper":"303662587","lower":"303450008","count":1264,"preSum":31607},{"ndv":1264,"upper":"303885913","lower":"303662588","count":1264,"preSum":32871},{"ndv":1264,"upper":"304068989","lower":"303885915","count":1264,"preSum":34135},{"ndv":1264,"upper":"304267328","lower":"304068997","count":1264,"preSum":35399},{"ndv":1264,"upper":"304460610","lower":"304267336","count":1264,"preSum":36663},{"ndv":1264,"upper":"304676337","lower":"304460611","count":1264,"preSum":37927},{"ndv":1264,"upper":"304888252","lower":"304676358","count":1264,"preSum":39191},{"ndv":1264,"upper":"305090891","lower":"304888257","count":1264,"preSum":40455},{"ndv":1264,"upper":"305250338","lower":"305090903","count":1264,"preSum":41719},{"ndv":1264,"upper":"305433900","lower":"305250573","count":1264,"preSum":42983},{"ndv":1264,"upper":"305705239","lower":"305433906","count":1264,"preSum":44247},{"ndv":1264,"upper":"305907185","lower":"305705247","count":1264,"preSum":45511},{"ndv":1264,"upper":"306094287","lower":"305907189","count":1264,"preSum":46775},{"ndv":1264,"upper":"306267634","lower":"306097285","count":1264,"preSum":48039},{"ndv":1264,"upper":"306435971","lower":"306267640","count":1264,"preSum":49303},{"ndv":1264,"upper":"306584812","lower":"306435975","count":1264,"preSum":50567},{"ndv":1264,"upper":"306754541","lower":"306584832","count":1264,"preSum":51831},{"ndv":1264,"upper":"306910869","lower":"306754549","count":1264,"preSum":53095},{"ndv":1264,"upper":"307144514","lower":"306910870","count":1264,"preSum":54359},{"ndv":1264,"upper":"307383085","lower":"307144521","count":1264,"preSum":55623},{"ndv":1264,"upper":"307566711","lower":"307383679","count":1264,"preSum":56887},{"ndv":1264,"upper":"307708198","lower":"307566723","count":1264,"preSum":58151},{"ndv":1264,"upper":"307853998","lower":"307708204","count":1264,"preSum":59415},{"ndv":1264,"upper":"307980638","lower":"307854016","count":1264,"preSum":60679},{"ndv":1260,"upper":"308087933","lower":"307980647","count":1264,"preSum":61943},{"ndv":1255,"upper":"308218662","lower":"308087980","count":1264,"preSum":63207},{"ndv":1264,"upper":"308351592","lower":"308218686","count":1264,"preSum":64471},{"ndv":1261,"upper":"308482971","lower":"308351603","count":1264,"preSum":65735},{"ndv":1264,"upper":"308624609","lower":"308483057","count":1264,"preSum":66999},{"ndv":1264,"upper":"308783317","lower":"308624840","count":1264,"preSum":68263},{"ndv":1264,"upper":"308965494","lower":"308784025","count":1264,"preSum":69527},{"ndv":1264,"upper":"309144034","lower":"308965495","count":1264,"preSum":70791},{"ndv":1264,"upper":"309318126","lower":"309144035","count":1264,"preSum":72055},{"ndv":1264,"upper":"309473811","lower":"309318143","count":1264,"preSum":73319},{"ndv":1264,"upper":"309668232","lower":"309473820","count":1264,"preSum":74583},{"ndv":1264,"upper":"309879381","lower":"309668245","count":1264,"preSum":75847},{"ndv":1213,"upper":"310033833","lower":"309879396","count":1264,"preSum":77111},{"ndv":1264,"upper":"310243136","lower":"310033898","count":1264,"preSum":78375},{"ndv":654,"upper":"74","lower":"310243147","count":1194,"preSum":79639}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[996,345,315,299,279,255,728,632,560,522,471,443,408,371],"valueArr":["1","10","11","12","13","14","2","3","4","5","6","7","8","9"],"type":"String","sampleRate":1.0}',1117,0.009150696),('jala_wms_prod','shipment_detail','expirationdate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Date","sampleRate":1.0}','{"countArr":[88574],"valueArr":[-1],"type":"Date","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','fromwarehousecode',7,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[65,59,19,13,3,13,51],"valueArr":["D001","D002","D003","D011","W002","W005","W028"],"type":"String","sampleRate":1.0}',88351,0.009150696),('jala_wms_prod','shipment_detail','hostitemcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','id',6229805,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1384,"upper":3265249,"lower":3031495,"count":1384,"preSum":0},{"ndv":1384,"upper":4204916,"lower":3265250,"count":1384,"preSum":1384},{"ndv":1384,"upper":4910811,"lower":4204917,"count":1384,"preSum":2768},{"ndv":1384,"upper":5182179,"lower":4910812,"count":1384,"preSum":4152},{"ndv":1384,"upper":5433182,"lower":5182180,"count":1384,"preSum":5536},{"ndv":1384,"upper":5723512,"lower":5433225,"count":1384,"preSum":6920},{"ndv":1384,"upper":6036886,"lower":5723513,"count":1384,"preSum":8304},{"ndv":1384,"upper":6248369,"lower":6036887,"count":1384,"preSum":9688},{"ndv":1384,"upper":6470368,"lower":6248414,"count":1384,"preSum":11072},{"ndv":1384,"upper":6629528,"lower":6470369,"count":1384,"preSum":12456},{"ndv":1384,"upper":6834207,"lower":6629530,"count":1384,"preSum":13840},{"ndv":1384,"upper":6999839,"lower":6834208,"count":1384,"preSum":15224},{"ndv":1384,"upper":7192444,"lower":6999840,"count":1384,"preSum":16608},{"ndv":1384,"upper":7360845,"lower":7192445,"count":1384,"preSum":17992},{"ndv":1384,"upper":7538353,"lower":7360852,"count":1384,"preSum":19376},{"ndv":1384,"upper":7741345,"lower":7538354,"count":1384,"preSum":20760},{"ndv":1384,"upper":7897214,"lower":7741346,"count":1384,"preSum":22144},{"ndv":1384,"upper":8066484,"lower":7897215,"count":1384,"preSum":23528},{"ndv":1384,"upper":8280095,"lower":8066485,"count":1384,"preSum":24912},{"ndv":1384,"upper":8406272,"lower":8280096,"count":1384,"preSum":26296},{"ndv":1384,"upper":8549690,"lower":8406273,"count":1384,"preSum":27680},{"ndv":1384,"upper":8709682,"lower":8549741,"count":1384,"preSum":29064},{"ndv":1384,"upper":8909373,"lower":8709683,"count":1384,"preSum":30448},{"ndv":1384,"upper":9081053,"lower":8909374,"count":1384,"preSum":31832},{"ndv":1384,"upper":9212777,"lower":9081054,"count":1384,"preSum":33216},{"ndv":1384,"upper":9364888,"lower":9212778,"count":1384,"preSum":34600},{"ndv":1384,"upper":9584949,"lower":9364889,"count":1384,"preSum":35984},{"ndv":1384,"upper":9777931,"lower":9584950,"count":1384,"preSum":37368},{"ndv":1384,"upper":9969882,"lower":9777945,"count":1384,"preSum":38752},{"ndv":1384,"upper":10136127,"lower":9970222,"count":1384,"preSum":40136},{"ndv":1384,"upper":10316049,"lower":10150238,"count":1384,"preSum":41520},{"ndv":1384,"upper":10482010,"lower":10316050,"count":1384,"preSum":42904},{"ndv":1384,"upper":10647164,"lower":10482059,"count":1384,"preSum":44288},{"ndv":1384,"upper":10835097,"lower":10647298,"count":1384,"preSum":45672},{"ndv":1384,"upper":11002062,"lower":10835098,"count":1384,"preSum":47056},{"ndv":1384,"upper":11138834,"lower":11002521,"count":1384,"preSum":48440},{"ndv":1384,"upper":11352970,"lower":11138835,"count":1384,"preSum":49824},{"ndv":1384,"upper":11576039,"lower":11353014,"count":1384,"preSum":51208},{"ndv":1384,"upper":11732864,"lower":11576040,"count":1384,"preSum":52592},{"ndv":1384,"upper":11885823,"lower":11732893,"count":1384,"preSum":53976},{"ndv":1384,"upper":12054076,"lower":11886067,"count":1384,"preSum":55360},{"ndv":1384,"upper":12205361,"lower":12054077,"count":1384,"preSum":56744},{"ndv":1384,"upper":12341019,"lower":12205362,"count":1384,"preSum":58128},{"ndv":1384,"upper":12482009,"lower":12341020,"count":1384,"preSum":59512},{"ndv":1384,"upper":12656507,"lower":12482391,"count":1384,"preSum":60896},{"ndv":1384,"upper":12872946,"lower":12656508,"count":1384,"preSum":62280},{"ndv":1384,"upper":13087096,"lower":12872947,"count":1384,"preSum":63664},{"ndv":1384,"upper":13253257,"lower":13087097,"count":1384,"preSum":65048},{"ndv":1384,"upper":13393957,"lower":13253258,"count":1384,"preSum":66432},{"ndv":1384,"upper":13560024,"lower":13393958,"count":1384,"preSum":67816},{"ndv":1384,"upper":13715881,"lower":13560025,"count":1384,"preSum":69200},{"ndv":1384,"upper":13878150,"lower":13715882,"count":1384,"preSum":70584},{"ndv":1384,"upper":14013314,"lower":13878151,"count":1384,"preSum":71968},{"ndv":1384,"upper":14159173,"lower":14013355,"count":1384,"preSum":73352},{"ndv":1384,"upper":14280696,"lower":14162897,"count":1384,"preSum":74736},{"ndv":1384,"upper":14425306,"lower":14280697,"count":1384,"preSum":76120},{"ndv":1384,"upper":14570021,"lower":14425307,"count":1384,"preSum":77504},{"ndv":1384,"upper":14747518,"lower":14570022,"count":1384,"preSum":78888},{"ndv":1384,"upper":14919648,"lower":14747522,"count":1384,"preSum":80272},{"ndv":1384,"upper":15066472,"lower":14919649,"count":1384,"preSum":81656},{"ndv":1384,"upper":15229815,"lower":15069118,"count":1384,"preSum":83040},{"ndv":1384,"upper":15407646,"lower":15229816,"count":1384,"preSum":84424},{"ndv":1384,"upper":15566750,"lower":15407647,"count":1384,"preSum":85808},{"ndv":1382,"upper":15785297,"lower":15567344,"count":1382,"preSum":87192}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,0,0.009150696),('jala_wms_prod','shipment_detail','inventorysts',7,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[81869,14,170,212,4,6,5509],"valueArr":["","XS","Z01","Z04","Z09","Z89","ZP"],"type":"String","sampleRate":1.0}',790,0.009150696),('jala_wms_prod','shipment_detail','isgift',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','isvirtualbom',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','itemcode',6185,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":270,"upper":"502112103","lower":"1101028722","count":1159,"preSum":0},{"ndv":20,"upper":"502191330","lower":"502112104","count":1084,"preSum":1159},{"ndv":17,"upper":"502191608","lower":"502191340","count":1118,"preSum":2243},{"ndv":8,"upper":"502200305","lower":"502191612","count":1231,"preSum":3361},{"ndv":5,"upper":"502200404","lower":"502200306","count":1520,"preSum":4592},{"ndv":5,"upper":"502201703","lower":"502200407","count":1720,"preSum":6112},{"ndv":5,"upper":"502202001","lower":"502201905","count":1074,"preSum":7832},{"ndv":5,"upper":"502203501","lower":"502202401","count":1221,"preSum":8906},{"ndv":8,"upper":"502220501","lower":"502203501T","count":1185,"preSum":10127},{"ndv":28,"upper":"502250302","lower":"502220502","count":1148,"preSum":11312},{"ndv":16,"upper":"502471400","lower":"502250502","count":1147,"preSum":12460},{"ndv":9,"upper":"502479300","lower":"502471600","count":1072,"preSum":13607},{"ndv":21,"upper":"502499002","lower":"502481001","count":1072,"preSum":14679},{"ndv":26,"upper":"502514206","lower":"502499102","count":1120,"preSum":15751},{"ndv":21,"upper":"502523908","lower":"502520700","count":1199,"preSum":16871},{"ndv":18,"upper":"502540302","lower":"502524002","count":1107,"preSum":18070},{"ndv":41,"upper":"502561100","lower":"502542201","count":1069,"preSum":19177},{"ndv":22,"upper":"502576100","lower":"502561200","count":1126,"preSum":20246},{"ndv":18,"upper":"502582805","lower":"502576102","count":1687,"preSum":21372},{"ndv":15,"upper":"502586901","lower":"502582903","count":1524,"preSum":23059},{"ndv":9,"upper":"502588501","lower":"502587900","count":1211,"preSum":24583},{"ndv":33,"upper":"502597300","lower":"502588502","count":1447,"preSum":25794},{"ndv":48,"upper":"502622207","lower":"502597301","count":1476,"preSum":27241},{"ndv":8,"upper":"502640804","lower":"502622208","count":1412,"preSum":28717},{"ndv":5,"upper":"502642604","lower":"502640805","count":1887,"preSum":30129},{"ndv":10,"upper":"502645000","lower":"502643500","count":1204,"preSum":32016},{"ndv":64,"upper":"502671702","lower":"502646400","count":1103,"preSum":33220},{"ndv":30,"upper":"502684503","lower":"502671800","count":1153,"preSum":34323},{"ndv":6,"upper":"502692900","lower":"502684505","count":1215,"preSum":35476},{"ndv":7,"upper":"502694100","lower":"502693400","count":1252,"preSum":36691},{"ndv":24,"upper":"502699002","lower":"502694200","count":1139,"preSum":37943},{"ndv":5,"upper":"502699201","lower":"502699100","count":1087,"preSum":39082},{"ndv":7,"upper":"502699402","lower":"502699202","count":1350,"preSum":40169},{"ndv":48,"upper":"502710700","lower":"502700101","count":1071,"preSum":41519},{"ndv":27,"upper":"502724501","lower":"502711200","count":1085,"preSum":42590},{"ndv":15,"upper":"502730200","lower":"502724601","count":1122,"preSum":43675},{"ndv":8,"upper":"502732000","lower":"502730300","count":1080,"preSum":44797},{"ndv":29,"upper":"502750100","lower":"502732200","count":1235,"preSum":45877},{"ndv":7,"upper":"502751500","lower":"502750101","count":1084,"preSum":47112},{"ndv":8,"upper":"502754500","lower":"502753800","count":1135,"preSum":48196},{"ndv":8,"upper":"502755000","lower":"502754501","count":1156,"preSum":49331},{"ndv":3,"upper":"502755300","lower":"502755100","count":1657,"preSum":50487},{"ndv":11,"upper":"502758000","lower":"502755400","count":1072,"preSum":52144},{"ndv":27,"upper":"502765200","lower":"502759200","count":1147,"preSum":53216},{"ndv":29,"upper":"502787600","lower":"502765800","count":1629,"preSum":54363},{"ndv":34,"upper":"502904900","lower":"502787700","count":1116,"preSum":55992},{"ndv":23,"upper":"502976583","lower":"502905100","count":1160,"preSum":57108},{"ndv":2,"upper":"502976673","lower":"502976671","count":1515,"preSum":58268},{"ndv":47,"upper":"505000405","lower":"502977051","count":1068,"preSum":59783},{"ndv":173,"upper":"512000100","lower":"505000500","count":1100,"preSum":60851},{"ndv":30,"upper":"512009700","lower":"512000200","count":1069,"preSum":61951},{"ndv":58,"upper":"6164823","lower":"512009800","count":1066,"preSum":63020},{"ndv":18,"upper":"6165082","lower":"6164838","count":1338,"preSum":64086},{"ndv":19,"upper":"6165195","lower":"6165084","count":1586,"preSum":65424},{"ndv":33,"upper":"6165472","lower":"6165196","count":1068,"preSum":67010},{"ndv":11,"upper":"6200262","lower":"6165473","count":118,"preSum":68078}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[989,1368,2428,2147,1445,2201,1019,1692,1242,1455,1182,1061,1140,1009],"valueArr":["502477901","502536603","502668704","502668804","502668904","502669004","502693900","502697804","502700002","502725500","502755900","502762700","502791100","6165273"],"type":"String","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','itemlistprice',1146,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":15,"upper":0.9100,"lower":0.0100,"count":901,"preSum":0},{"ndv":14,"upper":1.9100,"lower":1.0000,"count":1207,"preSum":901},{"ndv":16,"upper":5.0000,"lower":1.9500,"count":776,"preSum":2108},{"ndv":18,"upper":15.0000,"lower":5.3900,"count":1285,"preSum":2884},{"ndv":2,"upper":18.0000,"lower":16.0000,"count":1208,"preSum":4169},{"ndv":3,"upper":20.0000,"lower":19.0000,"count":1116,"preSum":5377},{"ndv":5,"upper":25.0000,"lower":22.0000,"count":1515,"preSum":6493},{"ndv":4,"upper":29.0000,"lower":26.0000,"count":1567,"preSum":8008},{"ndv":4,"upper":32.0000,"lower":29.8000,"count":1041,"preSum":9575},{"ndv":3,"upper":35.0000,"lower":33.0000,"count":1289,"preSum":10616},{"ndv":2,"upper":38.0000,"lower":36.0000,"count":1364,"preSum":11905},{"ndv":1,"upper":39.0000,"lower":39.0000,"count":1474,"preSum":13269},{"ndv":5,"upper":43.0000,"lower":39.6000,"count":879,"preSum":14743},{"ndv":3,"upper":49.0000,"lower":46.0000,"count":983,"preSum":15622},{"ndv":3,"upper":52.0000,"lower":50.0000,"count":861,"preSum":16605},{"ndv":5,"upper":55.0000,"lower":52.1700,"count":834,"preSum":17466},{"ndv":4,"upper":58.0000,"lower":55.2000,"count":1404,"preSum":18300},{"ndv":4,"upper":62.0000,"lower":58.8000,"count":1242,"preSum":19704},{"ndv":9,"upper":69.0000,"lower":62.2700,"count":1151,"preSum":20946},{"ndv":6,"upper":73.0000,"lower":69.3000,"count":1857,"preSum":22097},{"ndv":10,"upper":80.0000,"lower":73.5000,"count":1189,"preSum":23954},{"ndv":2,"upper":85.0000,"lower":83.4900,"count":834,"preSum":25143},{"ndv":4,"upper":90.0000,"lower":86.0000,"count":844,"preSum":25977},{"ndv":5,"upper":98.0000,"lower":92.0000,"count":1126,"preSum":26821},{"ndv":4,"upper":105.0000,"lower":99.0000,"count":1108,"preSum":27947},{"ndv":4,"upper":110.0000,"lower":106.0000,"count":1419,"preSum":29055},{"ndv":3,"upper":118.0000,"lower":112.0000,"count":1399,"preSum":30474},{"ndv":11,"upper":135.0000,"lower":118.5000,"count":913,"preSum":31873},{"ndv":1,"upper":139.0000,"lower":139.0000,"count":1173,"preSum":32786},{"ndv":10,"upper":150.0000,"lower":140.0000,"count":1017,"preSum":33959},{"ndv":4,"upper":158.0000,"lower":154.0000,"count":1590,"preSum":34976},{"ndv":17,"upper":179.0000,"lower":158.2000,"count":823,"preSum":36566},{"ndv":7,"upper":198.0000,"lower":181.0000,"count":1336,"preSum":37389},{"ndv":6,"upper":210.0000,"lower":199.0000,"count":1121,"preSum":38725},{"ndv":8,"upper":240.0000,"lower":218.0000,"count":1073,"preSum":39846},{"ndv":6,"upper":263.0000,"lower":242.0000,"count":779,"preSum":40919},{"ndv":4,"upper":280.0000,"lower":268.0000,"count":847,"preSum":41698},{"ndv":9,"upper":320.0000,"lower":283.0000,"count":972,"preSum":42545},{"ndv":11,"upper":370.0000,"lower":325.0000,"count":1228,"preSum":43517},{"ndv":14,"upper":450.0000,"lower":375.0000,"count":743,"preSum":44745},{"ndv":12,"upper":543.0000,"lower":456.5000,"count":737,"preSum":45488},{"ndv":26,"upper":1060.0000,"lower":550.0000,"count":782,"preSum":46225},{"ndv":9,"upper":2670.0000,"lower":1080.0000,"count":77,"preSum":47007}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[1578,3159,1788,10877,1757,1695,1844,2223,2129,3722,2731,1593,2213,4070],"valueArr":[0.0000,12.0000,45.0000,48.0000,59.0000,68.0000,75.0000,88.0000,128.0000,138.0000,145.0000,168.0000,180.0000,220.0000],"type":"Double","sampleRate":1.0}',111,0.009150696),('jala_wms_prod','shipment_detail','itemname',7415,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":101,"upper":"春夏南非复活草恒润保湿原液水(清爽型)(升级版)60mL","lower":" 自然堂舒缓润养卸妆膏100mL(王者荣耀限量礼盒)","count":1117,"preSum":0},{"ndv":205,"upper":"珀芙研水润平衡保湿霜10g中小样","lower":"春夏南非复活草恒润保湿原液水(清爽型)130mL(升级版)","count":1115,"preSum":1117},{"ndv":30,"upper":"珀芙研舒缓修护三联袋(2g洁面+2mL水+2g霜/自产)袋装","lower":"珀芙研水润平衡保湿霜80g","count":1118,"preSum":2232},{"ndv":116,"upper":"自然堂2022头皮护理干发帽(美妆店/蓝色)","lower":"珀芙研舒缓修护三联袋(洁水霜/自产)袋装","count":1461,"preSum":3350},{"ndv":42,"upper":"自然堂亲肤倍呵防晒乳SPF50+PA+++10mL中小样","lower":"自然堂2022版购物袋-中号(双面印)","count":1256,"preSum":4811},{"ndv":13,"upper":"自然堂冰川水水光面膜(新规版)28mL×5片装","lower":"自然堂亲肤倍呵防晒乳SPF50+PA+++50mL","count":1271,"preSum":6067},{"ndv":31,"upper":"自然堂凝时小紫瓶精华液礼盒(品牌礼盒)","lower":"自然堂冰川水水光面膜28mL 1片装","count":1199,"preSum":7338},{"ndv":23,"upper":"自然堂凝时肌活修纹精华霜SPF35PA++(修纹BB)(2022版)30mL","lower":"自然堂凝时水乳90mL精选套装","count":1152,"preSum":8537},{"ndv":11,"upper":"自然堂凝时鲜颜冰肌水160mL","lower":"自然堂凝时肌活修纹精华霜SPF35PA++(修纹BB)30mL(2022版)","count":1564,"preSum":9689},{"ndv":17,"upper":"自然堂凝时鲜颜小紫瓶肌活霜50g","lower":"自然堂凝时鲜颜冰肌水160mL试用装","count":1377,"preSum":11253},{"ndv":5,"upper":"自然堂凝时鲜颜洁面霜(体验装)60g中小样","lower":"自然堂凝时鲜颜小紫瓶肌活霜50g(欣昱玻璃瓶)","count":1754,"preSum":12630},{"ndv":14,"upper":"自然堂凝时鲜颜肌活乳液(2022升级)120mL","lower":"自然堂凝时鲜颜洁面霜125g","count":1428,"preSum":14384},{"ndv":14,"upper":"自然堂凝时鲜颜肌活修护体验装三件套(霜版)中小样","lower":"自然堂凝时鲜颜肌活乳液(2022升级)15mL中小样","count":1920,"preSum":15812},{"ndv":20,"upper":"自然堂凝时鲜颜肌活修护小紫瓶精华液第五代(2023)10mL小规格产品","lower":"自然堂凝时鲜颜肌活修护体验装四件套(乳液版)中小样","count":1570,"preSum":17732},{"ndv":7,"upper":"自然堂凝时鲜颜肌活修护小紫瓶精华液第五代50mL","lower":"自然堂凝时鲜颜肌活修护小紫瓶精华液第五代(2023)50mL","count":1650,"preSum":19302},{"ndv":16,"upper":"自然堂凝时鲜颜肌活冰肌水(清润型)(2023升级)160mL","lower":"自然堂凝时鲜颜肌活修护小紫瓶精华液第五代7mL中小样","count":1346,"preSum":20952},{"ndv":7,"upper":"自然堂凝时鲜颜肌活精华液(2023)40mL","lower":"自然堂凝时鲜颜肌活冰肌水(滋润型)(2023升级)160mL","count":1583,"preSum":22298},{"ndv":6,"upper":"自然堂凝润滋养护手霜(20210716加花盒)50g","lower":"自然堂凝时鲜颜肌活精华液(2023)7.5mL中小样","count":1382,"preSum":23881},{"ndv":58,"upper":"自然堂多肽抗皱美颈霜60g类产品","lower":"自然堂凝润滋养护手霜50g(20210716加花盒)","count":1521,"preSum":25263},{"ndv":10,"upper":"自然堂头皮护理敏感头皮保湿洗发露550mL","lower":"自然堂多肽紧致美颈霜60g(暂定名)类产品","count":1151,"preSum":26784},{"ndv":7,"upper":"自然堂头皮护理敏感头皮止痒洗发露+精华乳洗护两联包(5mL+5mL)两件套袋装","lower":"自然堂头皮护理敏感头皮保湿洗发露半成品","count":1208,"preSum":27935},{"ndv":15,"upper":"自然堂娇颜亮润四件套(标签升级)中小样","lower":"自然堂头皮护理敏感头皮止痒洗发露40mL(经销商大会版)中小样","count":1241,"preSum":29143},{"ndv":6,"upper":"自然堂娇颜亮润美白4件套(洁水乳精)","lower":"自然堂娇颜亮润焕采眼霜(抖拼快专售)15g","count":1391,"preSum":30384},{"ndv":11,"upper":"自然堂嫩白保湿乳35mL中小样","lower":"自然堂娇颜亮润美白四件套(2022抖音超品日礼盒)","count":1204,"preSum":31775},{"ndv":11,"upper":"自然堂嫩白保湿霜(粉盖)15g中小样","lower":"自然堂嫩白保湿乳35mL小规格产品","count":1155,"preSum":32979},{"ndv":17,"upper":"自然堂定制随包卡片(硕齐京东)","lower":"自然堂嫩白保湿霜15g中小样","count":1123,"preSum":34134},{"ndv":39,"upper":"自然堂弹嫩紧致抗皱柔肤液160mL","lower":"自然堂定制随包卡片(硕齐天猫)","count":1167,"preSum":35257},{"ndv":40,"upper":"自然堂微精华喜雪高保湿乳(2022标签升级)110mL","lower":"自然堂弹嫩紧致抗皱柔肤液160ml塑料瓶","count":1131,"preSum":36424},{"ndv":70,"upper":"自然堂抗光老防晒美白组合(2023版)","lower":"自然堂微精华喜雪高保湿乳1.5mL袋装","count":1130,"preSum":37555},{"ndv":25,"upper":"自然堂果酸细致焕肤面膜(绿色盖膜/纸卡版)6g 1颗装中小样","lower":"自然堂抗痘修护安瓶精华液半成品","count":1264,"preSum":38685},{"ndv":31,"upper":"自然堂水光充盈保湿体验装四件套(配方升级)中小样","lower":"自然堂果酸细致焕肤面膜(绿色盖膜/纸卡版/升级版)6g 1颗装中小样","count":1331,"preSum":39949},{"ndv":21,"upper":"自然堂水润保湿柔肤乳100mL","lower":"自然堂水光充盈保湿水(配方升级)35mL中小样","count":1311,"preSum":41280},{"ndv":13,"upper":"自然堂泛醇安瓶面膜(升级版) 安瓶1.5mL+面膜28mL 5片装","lower":"自然堂水润保湿柔肤水(2022升级版)135mL","count":1130,"preSum":42591},{"ndv":41,"upper":"自然堂滚轮按摩仪","lower":"自然堂泛醇舒缓保湿安瓶面膜 安瓶1.5mL+面膜28mL 1片装","count":1436,"preSum":43721},{"ndv":30,"upper":"自然堂烟酰胺细致提亮安瓶面膜(新规版) 1.5mL+33mL×5片装","lower":"自然堂炫彩盈润高显色唇膏#103贝母白3.2g试用装","count":1949,"preSum":45157},{"ndv":70,"upper":"自然堂男士咖啡因活力紧致精华乳(2022版)70mL","lower":"自然堂烟酰胺细致提亮安瓶面膜(无防腐) 安瓶1.5mL+面膜33mL 5片装","count":1160,"preSum":47106},{"ndv":30,"upper":"自然堂男士喜马拉雅冰川保湿露(新标签版)20mL中小样","lower":"自然堂男士咖啡因活力紧致精华乳(新标签版)20mL中小样","count":1309,"preSum":48266},{"ndv":33,"upper":"自然堂男士喜马拉雅龙血能量劲爽醒肤面膜(2022版)22mL 1片装类产品","lower":"自然堂男士喜马拉雅冰川保湿露(航天版)70mL","count":1308,"preSum":49575},{"ndv":67,"upper":"自然堂粉钻紧致细嫩玫瑰霜(美ONE定制)15g中小样","lower":"自然堂男士喜马拉雅龙血能量劲爽醒肤面膜22mL*1PCS(201906)","count":1132,"preSum":50883},{"ndv":35,"upper":"自然堂纯粹滋润冰肌水(2022升级版)60mL中小样","lower":"自然堂粉钻紧致细嫩玫瑰霜(美ONE定制)15g小规格产品","count":1290,"preSum":52015},{"ndv":23,"upper":"自然堂美白淡斑两步曲面膜(1.5mL+26mL)*5PCS(2022版)","lower":"自然堂纯粹滋润冰肌水(2022升级版)90mL","count":1154,"preSum":53305},{"ndv":38,"upper":"自然堂蓝铜肽抗皱紧致安瓶面膜安瓶1.5mL+面膜33mL5片装","lower":"自然堂美白淡斑两步曲面膜(1.5mL+26mL)*5片装(2022版)","count":1251,"preSum":54459},{"ndv":36,"upper":"自然堂酵母原液修护安瓶精华液(第二代)1.5mL*7PCS类产品","lower":"自然堂虾青素焕亮紧致面膜(新规版)33mL×5片装","count":1229,"preSum":55710},{"ndv":70,"upper":"自然堂雪域百合补水面膜(2022二版)26mL 1片装","lower":"自然堂酵母原液修护安瓶精华液1.5mL 28支装","count":1387,"preSum":56939},{"ndv":10,"upper":"自然堂雪域百合补水面膜26mL*5PCS(2022二版)","lower":"自然堂雪域百合补水面膜(2022二版)26mL 5片装","count":1174,"preSum":58326},{"ndv":37,"upper":"自然堂雪域精粹纯粹滋润洗颜霜(配方技术升级)125g","lower":"自然堂雪域百合补水面膜26mL*5片装(2022二版)","count":1364,"preSum":59500},{"ndv":31,"upper":"自然堂雪域紫草细致毛孔面膜(2022二版)26mL 1片装","lower":"自然堂雪域精粹纯粹滋润洗颜霜(配方技术升级)60g中小样","count":1203,"preSum":60864},{"ndv":15,"upper":"自然堂雪域紫草细致毛孔面膜26mL×5片装","lower":"自然堂雪域紫草细致毛孔面膜(2022二版)26mL×6片装","count":1118,"preSum":62067},{"ndv":21,"upper":"自然堂雪松精油活颜御龄体验装四件套(霜版)中小样","lower":"自然堂雪域补水保湿水乳套装","count":1175,"preSum":63185},{"ndv":27,"upper":"自然堂雪松精油活颜御龄霜50g","lower":"自然堂雪松精油活颜御龄体验装四件套(霜版)花盒+丝带(2020)","count":1188,"preSum":64360},{"ndv":51,"upper":"自然堂雪润皙白多重防晒隔离霜(淡紫色)SPF32PA+++(新规版)30mL","lower":"自然堂雪松精油活颜御龄霜5g中小样","count":1180,"preSum":65548},{"ndv":28,"upper":"自然堂雪肌发光美白水20mL中小样","lower":"自然堂雪润皙白多重防晒隔离霜(淡紫色)SPF32PA+++(软管二代)30mL","count":1118,"preSum":66728},{"ndv":21,"upper":"自然堂雪茶平衡保湿面膜26mL*1PCS(2021版)","lower":"自然堂雪肌系列折页","count":1273,"preSum":67846},{"ndv":12,"upper":"自然堂雪莲舒缓保湿面膜(2022版)26mL 1片装","lower":"自然堂雪茶平衡保湿面膜26mL*1PCS(2022版)中小样","count":1207,"preSum":69119},{"ndv":32,"upper":"鸟窝特价筐","lower":"自然堂雪莲舒缓保湿面膜26mL*1PCS(2021版)","count":1022,"preSum":70326}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[1009,1140,988,1455,1182,1019,1061,1242,987,1642,1494,1532,1138,1337],"valueArr":["自然堂2022版购物袋-中号","自然堂III型重组胶原蛋白修护冻干面膜0.65g×5片装","自然堂凝时鲜颜肌活冰肌水(清润型)(2023升级)60mL","自然堂喜马拉雅茶泥净颜清洁面膜100g","自然堂头皮护理敏感头皮修护精华液20mL中小样","自然堂头皮护理敏感头皮止痒洗发露550mL","自然堂头皮护理洗护精旅行装(40mL+40mL+20mL)三件套","自然堂植物补水面膜21片装(2022二版)","自然堂羽感致护防晒乳SPF50+PA+++(新规版)50mL","自然堂雪域百合补水面膜(2022二版)26mL×5片装","自然堂雪域紫草细致毛孔面膜(2022二版)26mL×5片装","自然堂雪域龙胆亮润面膜(2022二版)26mL×5片装","自然堂雪茶平衡保湿面膜(2022二版)26mL×5片装","自然堂雪莲舒缓保湿面膜(2022二版)26mL×5片装"],"type":"String","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','itemnetprice',807,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":14.9000,"lower":14.9000,"count":1,"preSum":0},{"ndv":1,"upper":53.7400,"lower":53.7400,"count":1,"preSum":1},{"ndv":1,"upper":60.3900,"lower":60.3900,"count":1,"preSum":2},{"ndv":1,"upper":74.2400,"lower":74.2400,"count":1,"preSum":3},{"ndv":1,"upper":86.0200,"lower":86.0200,"count":2,"preSum":4},{"ndv":1,"upper":104.3400,"lower":104.3400,"count":1,"preSum":6},{"ndv":1,"upper":128.3000,"lower":128.3000,"count":1,"preSum":7},{"ndv":1,"upper":140.8400,"lower":140.8400,"count":1,"preSum":8},{"ndv":1,"upper":144.1300,"lower":144.1300,"count":1,"preSum":9},{"ndv":1,"upper":144.9900,"lower":144.9900,"count":1,"preSum":10},{"ndv":1,"upper":151.6800,"lower":151.6800,"count":1,"preSum":11},{"ndv":1,"upper":161.3300,"lower":161.3300,"count":1,"preSum":12},{"ndv":1,"upper":164.9800,"lower":164.9800,"count":1,"preSum":13},{"ndv":1,"upper":166.9800,"lower":166.9800,"count":2,"preSum":14},{"ndv":1,"upper":167.2500,"lower":167.2500,"count":1,"preSum":16},{"ndv":1,"upper":249.0800,"lower":249.0800,"count":1,"preSum":17},{"ndv":1,"upper":252.0000,"lower":252.0000,"count":2,"preSum":18},{"ndv":1,"upper":252.8000,"lower":252.8000,"count":1,"preSum":20},{"ndv":1,"upper":273.4000,"lower":273.4000,"count":1,"preSum":21},{"ndv":1,"upper":293.0000,"lower":293.0000,"count":1,"preSum":22},{"ndv":1,"upper":294.4600,"lower":294.4600,"count":1,"preSum":23},{"ndv":1,"upper":320.2700,"lower":320.2700,"count":1,"preSum":24},{"ndv":1,"upper":322.6700,"lower":322.6700,"count":1,"preSum":25},{"ndv":1,"upper":324.6700,"lower":324.6700,"count":1,"preSum":26},{"ndv":1,"upper":331.2000,"lower":331.2000,"count":1,"preSum":27},{"ndv":1,"upper":367.5000,"lower":367.5000,"count":1,"preSum":28},{"ndv":1,"upper":433.7600,"lower":433.7600,"count":1,"preSum":29},{"ndv":1,"upper":445.5000,"lower":445.5000,"count":1,"preSum":30},{"ndv":1,"upper":522.1100,"lower":522.1100,"count":1,"preSum":31},{"ndv":1,"upper":562.3200,"lower":562.3200,"count":1,"preSum":32},{"ndv":1,"upper":630.0000,"lower":630.0000,"count":1,"preSum":33},{"ndv":1,"upper":806.4000,"lower":806.4000,"count":1,"preSum":34},{"ndv":1,"upper":821.6300,"lower":821.6300,"count":1,"preSum":35},{"ndv":1,"upper":950.4000,"lower":950.4000,"count":1,"preSum":36},{"ndv":1,"upper":955.2000,"lower":955.2000,"count":2,"preSum":37},{"ndv":1,"upper":1185.0000,"lower":1185.0000,"count":1,"preSum":39},{"ndv":1,"upper":1782.0000,"lower":1782.0000,"count":1,"preSum":40},{"ndv":1,"upper":2457.9900,"lower":2457.9900,"count":1,"preSum":41},{"ndv":1,"upper":2654.4000,"lower":2654.4000,"count":1,"preSum":42},{"ndv":1,"upper":2958.6500,"lower":2958.6500,"count":1,"preSum":43},{"ndv":1,"upper":3186.5400,"lower":3186.5400,"count":1,"preSum":44},{"ndv":1,"upper":3758.4000,"lower":3758.4000,"count":1,"preSum":45},{"ndv":1,"upper":4023.0000,"lower":4023.0000,"count":1,"preSum":46},{"ndv":1,"upper":4468.8000,"lower":4468.8000,"count":1,"preSum":47},{"ndv":1,"upper":7593.6000,"lower":7593.6000,"count":1,"preSum":48},{"ndv":1,"upper":9979.2000,"lower":9979.2000,"count":2,"preSum":49},{"ndv":1,"upper":11443.2000,"lower":11443.2000,"count":1,"preSum":51},{"ndv":1,"upper":11672.1600,"lower":11672.1600,"count":1,"preSum":52},{"ndv":1,"upper":22857.6000,"lower":22857.6000,"count":1,"preSum":53},{"ndv":1,"upper":57782.2000,"lower":57782.2000,"count":1,"preSum":54}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[88489,3],"valueArr":[0.0000,2822.4000],"type":"Double","sampleRate":1.0}',27,0.009150696),('jala_wms_prod','shipment_detail','lastupdated',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','lastupdatedby',49,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"40721814","lower":"40721814","count":2,"preSum":0},{"ndv":1,"upper":"gth","lower":"gth","count":2,"preSum":2},{"ndv":1,"upper":"hxy","lower":"hxy","count":1,"preSum":4},{"ndv":1,"upper":"jx","lower":"jx","count":1,"preSum":5},{"ndv":1,"upper":"LCQ","lower":"LCQ","count":1,"preSum":6}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[3,3,7,8,407,6,3,34,5,87970,107,5,3,6],"valueArr":["0220006","10000004","1000004","JQQ","LL","PZ","TTXLHJ","XCY1","YBJ","api","lhj","yj","zhaohongyan","zjf"],"type":"String","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','lot',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[34,9018,78340],"valueArr":["","19","null"],"type":"String","sampleRate":1.0}',1182,0.009150696),('jala_wms_prod','shipment_detail','manufacturedate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Date","sampleRate":1.0}','{"countArr":[88574],"valueArr":[-1],"type":"Date","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','manufacturer',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[554,12,5],"valueArr":["1000","1050","2000"],"type":"String","sampleRate":1.0}',88003,0.009150696),('jala_wms_prod','shipment_detail','maxbatches',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88490,84],"valueArr":[0,2],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','movereason',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','originalorderlinenum',455,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":3055088,"lower":3055088,"count":1,"preSum":0},{"ndv":1,"upper":3146522,"lower":3146522,"count":1,"preSum":1},{"ndv":1,"upper":3212051,"lower":3212051,"count":1,"preSum":2},{"ndv":1,"upper":3212342,"lower":3212342,"count":1,"preSum":3},{"ndv":1,"upper":3412199,"lower":3412199,"count":1,"preSum":4},{"ndv":1,"upper":3412200,"lower":3412200,"count":1,"preSum":5},{"ndv":1,"upper":3470136,"lower":3470136,"count":1,"preSum":6},{"ndv":1,"upper":3470140,"lower":3470140,"count":1,"preSum":7},{"ndv":1,"upper":3470143,"lower":3470143,"count":1,"preSum":8},{"ndv":1,"upper":3470148,"lower":3470148,"count":1,"preSum":9},{"ndv":1,"upper":3470152,"lower":3470152,"count":1,"preSum":10},{"ndv":1,"upper":3470154,"lower":3470154,"count":1,"preSum":11},{"ndv":1,"upper":3982691,"lower":3982691,"count":1,"preSum":12},{"ndv":1,"upper":3982693,"lower":3982693,"count":1,"preSum":13},{"ndv":1,"upper":3982696,"lower":3982696,"count":1,"preSum":14},{"ndv":1,"upper":5370139,"lower":5370139,"count":1,"preSum":15},{"ndv":1,"upper":5370141,"lower":5370141,"count":1,"preSum":16},{"ndv":1,"upper":5370145,"lower":5370145,"count":1,"preSum":17},{"ndv":1,"upper":5370147,"lower":5370147,"count":1,"preSum":18},{"ndv":1,"upper":5370150,"lower":5370150,"count":1,"preSum":19},{"ndv":1,"upper":5370154,"lower":5370154,"count":1,"preSum":20},{"ndv":1,"upper":5370157,"lower":5370157,"count":1,"preSum":21},{"ndv":1,"upper":6404949,"lower":6404949,"count":1,"preSum":22},{"ndv":1,"upper":6404954,"lower":6404954,"count":1,"preSum":23},{"ndv":1,"upper":11313095,"lower":11313095,"count":1,"preSum":24}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88549],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','originalshipmentcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','packingclass',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[3154,453],"valueArr":["","CS"],"type":"String","sampleRate":1.0}',84967,0.009150696),('jala_wms_prod','shipment_detail','packingcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[88574],"valueArr":["STD"],"type":"String","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','picklocs',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','picklpn',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','pickparentlpn',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','pickupquantity',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":6,"lower":6,"count":2,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88572],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','plqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','processstamp',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','processtype',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"CANCEL","lower":"CANCEL","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[88572],"valueArr":["NORMAL"],"type":"String","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','purchaseordercode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','qtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','quantity',3639,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":13,"lower":11,"count":57,"preSum":0},{"ndv":2,"upper":15,"lower":14,"count":101,"preSum":57},{"ndv":1,"upper":16,"lower":16,"count":44,"preSum":158},{"ndv":3,"upper":20,"lower":17,"count":163,"preSum":202},{"ndv":1,"upper":21,"lower":21,"count":39,"preSum":365},{"ndv":3,"upper":25,"lower":22,"count":68,"preSum":404},{"ndv":3,"upper":28,"lower":26,"count":37,"preSum":472},{"ndv":2,"upper":30,"lower":29,"count":75,"preSum":509},{"ndv":3,"upper":33,"lower":31,"count":42,"preSum":584},{"ndv":3,"upper":36,"lower":34,"count":61,"preSum":626},{"ndv":4,"upper":40,"lower":37,"count":52,"preSum":687},{"ndv":7,"upper":47,"lower":41,"count":38,"preSum":739},{"ndv":2,"upper":50,"lower":49,"count":60,"preSum":777},{"ndv":8,"upper":60,"lower":51,"count":81,"preSum":837},{"ndv":9,"upper":69,"lower":61,"count":37,"preSum":918},{"ndv":7,"upper":78,"lower":70,"count":39,"preSum":955},{"ndv":2,"upper":80,"lower":79,"count":40,"preSum":994},{"ndv":10,"upper":96,"lower":81,"count":121,"preSum":1034},{"ndv":3,"upper":100,"lower":98,"count":55,"preSum":1155},{"ndv":10,"upper":120,"lower":101,"count":49,"preSum":1210},{"ndv":5,"upper":133,"lower":124,"count":38,"preSum":1259},{"ndv":6,"upper":144,"lower":136,"count":82,"preSum":1297},{"ndv":10,"upper":168,"lower":145,"count":42,"preSum":1379},{"ndv":6,"upper":192,"lower":170,"count":71,"preSum":1421},{"ndv":5,"upper":200,"lower":194,"count":50,"preSum":1492},{"ndv":10,"upper":240,"lower":205,"count":71,"preSum":1542},{"ndv":11,"upper":288,"lower":245,"count":39,"preSum":1613},{"ndv":12,"upper":336,"lower":290,"count":44,"preSum":1652},{"ndv":11,"upper":385,"lower":337,"count":37,"preSum":1696},{"ndv":10,"upper":450,"lower":400,"count":38,"preSum":1733},{"ndv":10,"upper":480,"lower":454,"count":73,"preSum":1771},{"ndv":9,"upper":554,"lower":489,"count":37,"preSum":1844},{"ndv":11,"upper":640,"lower":560,"count":37,"preSum":1881},{"ndv":17,"upper":768,"lower":643,"count":37,"preSum":1918},{"ndv":20,"upper":960,"lower":792,"count":59,"preSum":1955},{"ndv":11,"upper":1200,"lower":1000,"count":45,"preSum":2014},{"ndv":19,"upper":1620,"lower":1205,"count":37,"preSum":2059},{"ndv":14,"upper":1920,"lower":1650,"count":39,"preSum":2096},{"ndv":19,"upper":2400,"lower":1944,"count":44,"preSum":2135},{"ndv":20,"upper":3600,"lower":2418,"count":38,"preSum":2179},{"ndv":19,"upper":5000,"lower":3840,"count":38,"preSum":2217},{"ndv":25,"upper":7740,"lower":5040,"count":37,"preSum":2255},{"ndv":32,"upper":36000,"lower":8304,"count":37,"preSum":2292},{"ndv":9,"upper":204000,"lower":36864,"count":9,"preSum":2329}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[53363,17125,3291,6655,1395,1983,280,332,139,551,502,133,240,247],"valueArr":[1,2,3,4,5,6,7,8,9,10,12,18,24,48],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','quantityum',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"CS","lower":"CS","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[88544,28],"valueArr":["EA","MP"],"type":"String","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','referencecrossdockcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','replenishmentrule',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','requestcancelqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','requestqty',3757,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":13,"lower":0,"count":59,"preSum":0},{"ndv":2,"upper":15,"lower":14,"count":101,"preSum":59},{"ndv":1,"upper":16,"lower":16,"count":44,"preSum":160},{"ndv":3,"upper":20,"lower":17,"count":163,"preSum":204},{"ndv":1,"upper":21,"lower":21,"count":39,"preSum":367},{"ndv":3,"upper":25,"lower":22,"count":68,"preSum":406},{"ndv":4,"upper":29,"lower":26,"count":41,"preSum":474},{"ndv":1,"upper":30,"lower":30,"count":70,"preSum":515},{"ndv":3,"upper":33,"lower":31,"count":42,"preSum":585},{"ndv":3,"upper":36,"lower":34,"count":61,"preSum":627},{"ndv":4,"upper":40,"lower":37,"count":52,"preSum":688},{"ndv":7,"upper":47,"lower":41,"count":38,"preSum":740},{"ndv":2,"upper":50,"lower":49,"count":60,"preSum":778},{"ndv":8,"upper":60,"lower":51,"count":81,"preSum":838},{"ndv":12,"upper":72,"lower":61,"count":53,"preSum":919},{"ndv":7,"upper":80,"lower":74,"count":54,"preSum":972},{"ndv":10,"upper":96,"lower":81,"count":121,"preSum":1026},{"ndv":3,"upper":100,"lower":98,"count":55,"preSum":1147},{"ndv":10,"upper":120,"lower":101,"count":50,"preSum":1202},{"ndv":10,"upper":144,"lower":124,"count":107,"preSum":1252},{"ndv":10,"upper":168,"lower":145,"count":42,"preSum":1359},{"ndv":4,"upper":192,"lower":170,"count":69,"preSum":1401},{"ndv":5,"upper":200,"lower":194,"count":51,"preSum":1470},{"ndv":8,"upper":240,"lower":205,"count":68,"preSum":1521},{"ndv":10,"upper":288,"lower":245,"count":38,"preSum":1589},{"ndv":13,"upper":336,"lower":290,"count":45,"preSum":1627},{"ndv":12,"upper":385,"lower":337,"count":38,"preSum":1672},{"ndv":10,"upper":447,"lower":399,"count":37,"preSum":1710},{"ndv":10,"upper":480,"lower":450,"count":72,"preSum":1747},{"ndv":9,"upper":554,"lower":489,"count":37,"preSum":1819},{"ndv":12,"upper":639,"lower":558,"count":37,"preSum":1856},{"ndv":16,"upper":766,"lower":640,"count":37,"preSum":1893},{"ndv":20,"upper":960,"lower":768,"count":62,"preSum":1930},{"ndv":10,"upper":1200,"lower":1000,"count":44,"preSum":1992},{"ndv":19,"upper":1600,"lower":1205,"count":37,"preSum":2036},{"ndv":15,"upper":1920,"lower":1620,"count":40,"preSum":2073},{"ndv":19,"upper":2400,"lower":1944,"count":44,"preSum":2113},{"ndv":22,"upper":3600,"lower":2418,"count":40,"preSum":2157},{"ndv":20,"upper":5000,"lower":3840,"count":39,"preSum":2197},{"ndv":26,"upper":7740,"lower":5040,"count":37,"preSum":2236},{"ndv":32,"upper":30000,"lower":8304,"count":37,"preSum":2273},{"ndv":11,"upper":204000,"lower":36000,"count":11,"preSum":2310}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[53361,17124,3292,6655,1396,1999,280,332,139,551,502,133,240,249],"valueArr":[1,2,3,4,5,6,7,8,9,10,12,18,24,48],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','returnqty',13,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":1,"lower":1,"count":1,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88570,3],"valueArr":[0,1080],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','samplesize',62,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":6.0,"lower":6.0,"count":2,"preSum":0},{"ndv":1,"upper":7.0,"lower":7.0,"count":2,"preSum":2},{"ndv":1,"upper":9.0,"lower":9.0,"count":1,"preSum":4},{"ndv":1,"upper":10.0,"lower":10.0,"count":2,"preSum":5},{"ndv":1,"upper":11.0,"lower":11.0,"count":1,"preSum":7},{"ndv":1,"upper":12.0,"lower":12.0,"count":2,"preSum":8},{"ndv":1,"upper":13.0,"lower":13.0,"count":1,"preSum":10},{"ndv":1,"upper":16.0,"lower":16.0,"count":1,"preSum":11},{"ndv":1,"upper":32.0,"lower":32.0,"count":2,"preSum":12}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[88182,229,11,6,4,10,4,22,4,13,31,37,7],"valueArr":[0.0,1.0,2.0,3.0,4.0,5.0,8.0,20.0,50.0,80.0,125.0,200.0,315.0],"type":"Double","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','shelflifests',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36],"valueArr":[""],"type":"String","sampleRate":1.0}',88538,0.009150696),('jala_wms_prod','shipment_detail','shipmentcode',145241,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":639,"upper":"CK0001203905","lower":"0001622095","count":1379,"preSum":0},{"ndv":228,"upper":"CK0001318576","lower":"CK0001203910","count":1379,"preSum":1379},{"ndv":221,"upper":"CK0001430000","lower":"CK0001318928","count":1386,"preSum":2758},{"ndv":251,"upper":"CK0001476392","lower":"CK0001430052","count":1382,"preSum":4144},{"ndv":192,"upper":"CK0001503987","lower":"CK0001476401","count":1384,"preSum":5526},{"ndv":185,"upper":"CK0001534271","lower":"CK0001504015","count":1388,"preSum":6910},{"ndv":142,"upper":"CKH00000010974","lower":"CK0001534521","count":1381,"preSum":8298},{"ndv":475,"upper":"PJX2302755669172600","lower":"CKH00000011027","count":1382,"preSum":9679},{"ndv":482,"upper":"PJX2304779511101120","lower":"PJX2302755748482610","count":1381,"preSum":11061},{"ndv":466,"upper":"PJX2304787032612713","lower":"PJX2304779515841121","count":1381,"preSum":12442},{"ndv":411,"upper":"PJX2305792981410522","lower":"PJX2304787032732713","count":1382,"preSum":13823},{"ndv":407,"upper":"PJX2305796630261217","lower":"PJX2305792983580522","count":1384,"preSum":15205},{"ndv":426,"upper":"PJX2305799857361809","lower":"PJX2305796630611217","count":1379,"preSum":16589},{"ndv":479,"upper":"PJX2305803721352603","lower":"PJX2305799889221810","count":1380,"preSum":17968},{"ndv":459,"upper":"PJX2306812145060117","lower":"PJX2305803723492604","count":1379,"preSum":19348},{"ndv":452,"upper":"POD2305794885570916","lower":"PJX2306812151310117","count":1380,"preSum":20727},{"ndv":404,"upper":"PSD2212725946741310","lower":"POD2305794886230917","count":1380,"preSum":22107},{"ndv":358,"upper":"PSD2304784485082123","lower":"PSD2212727222701615","count":1380,"preSum":23487},{"ndv":357,"upper":"PSD2304785484882410","lower":"PSD2304784487032123","count":1384,"preSum":24867},{"ndv":370,"upper":"PSD2304786442722610","lower":"PSD2304785485172410","count":1380,"preSum":26251},{"ndv":399,"upper":"PSD2304787918142822","lower":"PSD2304786442822610","count":1381,"preSum":27631},{"ndv":384,"upper":"PSD2305789075850110","lower":"PSD2304787918182822","count":1379,"preSum":29012},{"ndv":345,"upper":"PSD2305791394030313","lower":"PSD2305789075880110","count":1386,"preSum":30391},{"ndv":322,"upper":"PSD2305792721770513","lower":"PSD2305791394050313","count":1380,"preSum":31777},{"ndv":430,"upper":"PSD2305793740850712","lower":"PSD2305792721780513","count":1384,"preSum":33157},{"ndv":406,"upper":"PSD2305794870350916","lower":"PSD2305793740860712","count":1383,"preSum":34541},{"ndv":372,"upper":"PSD2305796046171116","lower":"PSD2305794870420916","count":1380,"preSum":35924},{"ndv":348,"upper":"PSD2305797284451400","lower":"PSD2305796048931116","count":1379,"preSum":37304},{"ndv":351,"upper":"PSD2305798091331513","lower":"PSD2305797284611400","count":1385,"preSum":38683},{"ndv":401,"upper":"PSD2305799962501813","lower":"PSD2305798091341513","count":1379,"preSum":40068},{"ndv":336,"upper":"PSD2305800863152010","lower":"PSD2305799962531813","count":1379,"preSum":41447},{"ndv":273,"upper":"PSD2305801388572103","lower":"PSD2305800863212010","count":1384,"preSum":42826},{"ndv":324,"upper":"PSD2305802370222302","lower":"PSD2305801388592103","count":1379,"preSum":44210},{"ndv":443,"upper":"PSD2305803756032609","lower":"PSD2305802370232302","count":1380,"preSum":45589},{"ndv":381,"upper":"PSD2305808328072900","lower":"PSD2305803756062609","count":1379,"preSum":46969},{"ndv":403,"upper":"PSD2305809308053012","lower":"PSD2305808328112900","count":1391,"preSum":48348},{"ndv":424,"upper":"PSD2306811982140114","lower":"PSD2305809308373012","count":1381,"preSum":49739},{"ndv":464,"upper":"PTB2303759815120421","lower":"PSD2306811988630114","count":1381,"preSum":51120},{"ndv":653,"upper":"PTB2303771757382420","lower":"PTB2303759815900421","count":1391,"preSum":52501},{"ndv":587,"upper":"PTB2304780902191420","lower":"PTB2303771759172420","count":1380,"preSum":53892},{"ndv":662,"upper":"PTB2304785163192312","lower":"PTB2304780902941420","count":1380,"preSum":55272},{"ndv":540,"upper":"PTB2304786954402710","lower":"PTB2304785166902312","count":1379,"preSum":56652},{"ndv":545,"upper":"PTB2305788687370106","lower":"PTB2304786954622710","count":1379,"preSum":58031},{"ndv":603,"upper":"PTB2305790071240221","lower":"PTB2305788687530106","count":1382,"preSum":59410},{"ndv":467,"upper":"PTB2305790775740310","lower":"PTB2305790071260221","count":1379,"preSum":60792},{"ndv":473,"upper":"PTB2305791474710316","lower":"PTB2305790775750310","count":1383,"preSum":62171},{"ndv":490,"upper":"PTB2305792371340420","lower":"PTB2305791476960316","count":1388,"preSum":63554},{"ndv":530,"upper":"PTB2305794991660921","lower":"PTB2305792371650420","count":1379,"preSum":64942},{"ndv":534,"upper":"PTB2305796863541309","lower":"PTB2305794991690921","count":1382,"preSum":66321},{"ndv":657,"upper":"PTB2305799236221705","lower":"PTB2305796900261310","count":1379,"preSum":67703},{"ndv":571,"upper":"PTB2305801037262016","lower":"PTB2305799262671709","count":1379,"preSum":69082},{"ndv":707,"upper":"PTB2305803724452604","lower":"PTB2305801037602016","count":1381,"preSum":70461},{"ndv":540,"upper":"PTB2305804673462710","lower":"PTB2305803724692605","count":1379,"preSum":71842},{"ndv":518,"upper":"PTB2305805170092711","lower":"PTB2305804673632710","count":1379,"preSum":73221},{"ndv":518,"upper":"PTB2305805717482712","lower":"PTB2305805170172711","count":1380,"preSum":74600},{"ndv":569,"upper":"PTB2305806430372716","lower":"PTB2305805717542712","count":1380,"preSum":75980},{"ndv":566,"upper":"PTB2305807088922721","lower":"PTB2305806430382716","count":1380,"preSum":77360},{"ndv":502,"upper":"PTB2305807882352820","lower":"PTB2305807089402721","count":1382,"preSum":78740},{"ndv":517,"upper":"PTB2305808494042910","lower":"PTB2305807882422820","count":1381,"preSum":80122},{"ndv":578,"upper":"PTB2305809733953101","lower":"PTB2305808494112910","count":1380,"preSum":81503},{"ndv":522,"upper":"PTB2305810490813120","lower":"PTB2305809734043101","count":1379,"preSum":82883},{"ndv":558,"upper":"PTB2305811200073123","lower":"PTB2305810491173120","count":1381,"preSum":84262},{"ndv":495,"upper":"PTB2306812029530114","lower":"PTB2305811200113123","count":1379,"preSum":85643},{"ndv":538,"upper":"VP.0314.103","lower":"PTB2306812035040114","count":1212,"preSum":87022}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[32,34,35,32,101,34,41,31],"valueArr":["1800000295-W013","1800000342-W028-1","202210自然堂品牌-销售因素退货1127","202302自然堂品牌-销售因素退货","202304自然堂品牌-销售因素退货","4800119760","4903448464-1029","CKH00000005209"],"type":"String","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','shipmentid',145367,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":438,"upper":1399382,"lower":1243547,"count":1387,"preSum":0},{"ndv":308,"upper":2496248,"lower":1399484,"count":1385,"preSum":1387},{"ndv":413,"upper":2797959,"lower":2496265,"count":1381,"preSum":2772},{"ndv":467,"upper":2948691,"lower":2797960,"count":1379,"preSum":4153},{"ndv":568,"upper":3099782,"lower":2949380,"count":1380,"preSum":5532},{"ndv":462,"upper":3301685,"lower":3099786,"count":1382,"preSum":6912},{"ndv":478,"upper":3530951,"lower":3301699,"count":1383,"preSum":8294},{"ndv":514,"upper":3642093,"lower":3531350,"count":1385,"preSum":9677},{"ndv":481,"upper":3755628,"lower":3642297,"count":1382,"preSum":11062},{"ndv":424,"upper":3824571,"lower":3755931,"count":1379,"preSum":12444},{"ndv":379,"upper":3876576,"lower":3824602,"count":1379,"preSum":13823},{"ndv":389,"upper":3929420,"lower":3876577,"count":1379,"preSum":15202},{"ndv":457,"upper":3999968,"lower":3929421,"count":1379,"preSum":16581},{"ndv":374,"upper":4061582,"lower":3999970,"count":1379,"preSum":17960},{"ndv":366,"upper":4122110,"lower":4061631,"count":1386,"preSum":19339},{"ndv":420,"upper":4188468,"lower":4122197,"count":1381,"preSum":20725},{"ndv":473,"upper":4235990,"lower":4188478,"count":1380,"preSum":22106},{"ndv":395,"upper":4289102,"lower":4236177,"count":1382,"preSum":23486},{"ndv":454,"upper":4437608,"lower":4289104,"count":1391,"preSum":24868},{"ndv":466,"upper":4470355,"lower":4437611,"count":1381,"preSum":26259},{"ndv":446,"upper":4506576,"lower":4470356,"count":1379,"preSum":27640},{"ndv":431,"upper":4553573,"lower":4506577,"count":1381,"preSum":29019},{"ndv":494,"upper":4614077,"lower":4553582,"count":1379,"preSum":30400},{"ndv":434,"upper":4664793,"lower":4614093,"count":1382,"preSum":31779},{"ndv":408,"upper":4698038,"lower":4664794,"count":1379,"preSum":33161},{"ndv":418,"upper":4752152,"lower":4698047,"count":1379,"preSum":34540},{"ndv":435,"upper":4852278,"lower":4752345,"count":1383,"preSum":35919},{"ndv":433,"upper":4915759,"lower":4852279,"count":1380,"preSum":37302},{"ndv":422,"upper":4978709,"lower":4915766,"count":1379,"preSum":38682},{"ndv":456,"upper":5036044,"lower":4978726,"count":1380,"preSum":40061},{"ndv":365,"upper":5087389,"lower":5036047,"count":1384,"preSum":41441},{"ndv":428,"upper":5132249,"lower":5087390,"count":1382,"preSum":42825},{"ndv":421,"upper":5189892,"lower":5132259,"count":1379,"preSum":44207},{"ndv":412,"upper":5243473,"lower":5190868,"count":1381,"preSum":45586},{"ndv":402,"upper":5291609,"lower":5243476,"count":1385,"preSum":46967},{"ndv":467,"upper":5330181,"lower":5291611,"count":1379,"preSum":48352},{"ndv":402,"upper":5394764,"lower":5330272,"count":1381,"preSum":49731},{"ndv":504,"upper":5473523,"lower":5394771,"count":1380,"preSum":51112},{"ndv":423,"upper":5524824,"lower":5473524,"count":1380,"preSum":52492},{"ndv":370,"upper":5573703,"lower":5524829,"count":1380,"preSum":53872},{"ndv":447,"upper":5628084,"lower":5573723,"count":1380,"preSum":55252},{"ndv":364,"upper":5666216,"lower":5628097,"count":1380,"preSum":56632},{"ndv":396,"upper":5705694,"lower":5666353,"count":1386,"preSum":58012},{"ndv":408,"upper":5743429,"lower":5705724,"count":1379,"preSum":59398},{"ndv":464,"upper":5811123,"lower":5743578,"count":1379,"preSum":60777},{"ndv":496,"upper":5885002,"lower":5811127,"count":1382,"preSum":62156},{"ndv":434,"upper":5961557,"lower":5885007,"count":1379,"preSum":63538},{"ndv":504,"upper":6012800,"lower":5961564,"count":1382,"preSum":64917},{"ndv":513,"upper":6065934,"lower":6012802,"count":1381,"preSum":66299},{"ndv":499,"upper":6117554,"lower":6065936,"count":1381,"preSum":67680},{"ndv":544,"upper":6177349,"lower":6117555,"count":1379,"preSum":69061},{"ndv":581,"upper":6236421,"lower":6177406,"count":1379,"preSum":70440},{"ndv":458,"upper":6282559,"lower":6236424,"count":1380,"preSum":71819},{"ndv":479,"upper":6327887,"lower":6282564,"count":1379,"preSum":73199},{"ndv":497,"upper":6369544,"lower":6327889,"count":1379,"preSum":74578},{"ndv":392,"upper":6409687,"lower":6371204,"count":1386,"preSum":75957},{"ndv":500,"upper":6458981,"lower":6409688,"count":1380,"preSum":77343},{"ndv":494,"upper":6521554,"lower":6458984,"count":1379,"preSum":78723},{"ndv":471,"upper":6577226,"lower":6521642,"count":1379,"preSum":80102},{"ndv":511,"upper":6628027,"lower":6577255,"count":1383,"preSum":81481},{"ndv":538,"upper":6683979,"lower":6628063,"count":1387,"preSum":82864},{"ndv":454,"upper":6737401,"lower":6683985,"count":1379,"preSum":84251},{"ndv":447,"upper":6789107,"lower":6737417,"count":1379,"preSum":85630},{"ndv":463,"upper":6859092,"lower":6789114,"count":1225,"preSum":87009}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[41,35,32,34,32,31,34,101],"valueArr":[1470056,1841878,1923930,2127359,3302918,3586403,3612508,5464080],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','shipqty',3542,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":13,"lower":11,"count":54,"preSum":0},{"ndv":2,"upper":15,"lower":14,"count":101,"preSum":54},{"ndv":1,"upper":16,"lower":16,"count":40,"preSum":155},{"ndv":2,"upper":18,"lower":17,"count":149,"preSum":195},{"ndv":2,"upper":20,"lower":19,"count":117,"preSum":344},{"ndv":1,"upper":21,"lower":21,"count":39,"preSum":461},{"ndv":3,"upper":25,"lower":22,"count":61,"preSum":500},{"ndv":4,"upper":29,"lower":26,"count":37,"preSum":561},{"ndv":1,"upper":30,"lower":30,"count":66,"preSum":598},{"ndv":3,"upper":33,"lower":31,"count":38,"preSum":664},{"ndv":3,"upper":36,"lower":34,"count":59,"preSum":702},{"ndv":4,"upper":40,"lower":37,"count":50,"preSum":761},{"ndv":7,"upper":47,"lower":41,"count":37,"preSum":811},{"ndv":2,"upper":50,"lower":49,"count":55,"preSum":848},{"ndv":8,"upper":60,"lower":51,"count":81,"preSum":903},{"ndv":12,"upper":72,"lower":61,"count":50,"preSum":984},{"ndv":5,"upper":80,"lower":76,"count":44,"preSum":1034},{"ndv":10,"upper":96,"lower":81,"count":117,"preSum":1078},{"ndv":3,"upper":100,"lower":98,"count":51,"preSum":1195},{"ndv":9,"upper":120,"lower":101,"count":45,"preSum":1246},{"ndv":9,"upper":144,"lower":124,"count":88,"preSum":1291},{"ndv":9,"upper":168,"lower":145,"count":40,"preSum":1379},{"ndv":4,"upper":192,"lower":170,"count":66,"preSum":1419},{"ndv":9,"upper":234,"lower":195,"count":36,"preSum":1485},{"ndv":3,"upper":240,"lower":238,"count":53,"preSum":1521},{"ndv":10,"upper":288,"lower":245,"count":36,"preSum":1574},{"ndv":12,"upper":336,"lower":290,"count":38,"preSum":1610},{"ndv":11,"upper":385,"lower":337,"count":36,"preSum":1648},{"ndv":9,"upper":447,"lower":399,"count":36,"preSum":1684},{"ndv":10,"upper":480,"lower":450,"count":71,"preSum":1720},{"ndv":8,"upper":558,"lower":492,"count":36,"preSum":1791},{"ndv":10,"upper":640,"lower":560,"count":36,"preSum":1827},{"ndv":15,"upper":798,"lower":648,"count":37,"preSum":1863},{"ndv":17,"upper":960,"lower":804,"count":51,"preSum":1900},{"ndv":10,"upper":1200,"lower":1000,"count":42,"preSum":1951},{"ndv":18,"upper":1599,"lower":1205,"count":36,"preSum":1993},{"ndv":14,"upper":1920,"lower":1600,"count":38,"preSum":2029},{"ndv":17,"upper":2400,"lower":1944,"count":41,"preSum":2067},{"ndv":22,"upper":3600,"lower":2418,"count":40,"preSum":2108},{"ndv":20,"upper":5000,"lower":3840,"count":39,"preSum":2148},{"ndv":25,"upper":7740,"lower":5040,"count":36,"preSum":2187},{"ndv":31,"upper":30000,"lower":8304,"count":36,"preSum":2223},{"ndv":11,"upper":204000,"lower":36000,"count":11,"preSum":2259}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[6136,49800,16110,3081,5892,1284,1846,269,291,133,498,488,231,245],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,12,24,48],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','shortallocqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','shortpackingqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','shortpickqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','sourceordercode',131754,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":531,"upper":"1840138430288332588","lower":"106583141855946","count":1221,"preSum":0},{"ndv":529,"upper":"1871952853638166269","lower":"1840156502689036482","count":1222,"preSum":1221},{"ndv":505,"upper":"1877536560104748193","lower":"1872031044106069668","count":1225,"preSum":2443},{"ndv":453,"upper":"1879944927628914783","lower":"1877549055358180181","count":1222,"preSum":3668},{"ndv":418,"upper":"1880910408935830177","lower":"1879953891489510984","count":1222,"preSum":4890},{"ndv":424,"upper":"1885604952577416395","lower":"1880916675025846089","count":1222,"preSum":6112},{"ndv":481,"upper":"1889929093335012197","lower":"1885616331341338781","count":1222,"preSum":7334},{"ndv":536,"upper":"1896060792809665950","lower":"1889933268447986983","count":1221,"preSum":8556},{"ndv":471,"upper":"1896719846289028579","lower":"1896070008977635354","count":1222,"preSum":9777},{"ndv":446,"upper":"1896960973283009496","lower":"1896720672678803184","count":1223,"preSum":10999},{"ndv":449,"upper":"1897131183880107492","lower":"1896961118275476680","count":1228,"preSum":12222},{"ndv":463,"upper":"1898521539399833385","lower":"1897132299865326369","count":1221,"preSum":13450},{"ndv":528,"upper":"1901598567620427485","lower":"1898526111986594476","count":1221,"preSum":14671},{"ndv":470,"upper":"1903795610715163575","lower":"1901601942340583655","count":1221,"preSum":15892},{"ndv":426,"upper":"23042580889303","lower":"1903798344416247060","count":1226,"preSum":17113},{"ndv":402,"upper":"23050488654013","lower":"23042581581944","count":1224,"preSum":18339},{"ndv":387,"upper":"23051302378506","lower":"230504SYS3PHS8!OFG136893122206581","count":1222,"preSum":19563},{"ndv":410,"upper":"23052025930780","lower":"23051303893127","count":1224,"preSum":20785},{"ndv":430,"upper":"23052978328416","lower":"23052031258980","count":1232,"preSum":22009},{"ndv":428,"upper":"2314900062893997","lower":"23052981541616","count":1226,"preSum":23241},{"ndv":379,"upper":"262893992009","lower":"2314900063453170","count":1225,"preSum":24467},{"ndv":410,"upper":"269255061551","lower":"262912447653","count":1224,"preSum":25692},{"ndv":388,"upper":"271416067035","lower":"269255555945","count":1223,"preSum":26916},{"ndv":410,"upper":"273448935474","lower":"271416251001","count":1221,"preSum":28139},{"ndv":412,"upper":"3213449640916254101","lower":"273450281331","count":1221,"preSum":29360},{"ndv":514,"upper":"3255028310090603708","lower":"3213455832443774725","count":1223,"preSum":30581},{"ndv":507,"upper":"3298013966156329435","lower":"3255101532986204200","count":1224,"preSum":31804},{"ndv":500,"upper":"3312051698914789000","lower":"3298018322554624218","count":1221,"preSum":33028},{"ndv":476,"upper":"3320074261717677541","lower":"3312052308556263801","count":1222,"preSum":34249},{"ndv":484,"upper":"3325828500140546925","lower":"3320125200490762221","count":1225,"preSum":35471},{"ndv":504,"upper":"3329243929651742935","lower":"3325835557150056351","count":1222,"preSum":36696},{"ndv":432,"upper":"3330459505194030347","lower":"3329245693274793226","count":1221,"preSum":37918},{"ndv":416,"upper":"3330755678116875612","lower":"3330460081969986806","count":1222,"preSum":39139},{"ndv":444,"upper":"3334565556696871727","lower":"3330756075060068244","count":1221,"preSum":40361},{"ndv":455,"upper":"3341136602452562836","lower":"3334567359696745830","count":1221,"preSum":41582},{"ndv":464,"upper":"3345915168370885965","lower":"3341136962972195522","count":1221,"preSum":42803},{"ndv":525,"upper":"3350795223448998745","lower":"3345915672987736752","count":1223,"preSum":44024},{"ndv":471,"upper":"3355991748063996011","lower":"3350804186104043925","count":1221,"preSum":45247},{"ndv":575,"upper":"3363370768716378926","lower":"3356009532277714527","count":1225,"preSum":46468},{"ndv":467,"upper":"3364213788142344829","lower":"3363370768717378926","count":1223,"preSum":47693},{"ndv":436,"upper":"3364541101872949311","lower":"3364216416175621627","count":1223,"preSum":48916},{"ndv":448,"upper":"3364795074644221843","lower":"3364549481824102049","count":1222,"preSum":50139},{"ndv":434,"upper":"3365149682769180451","lower":"3364795651005414837","count":1221,"preSum":51361},{"ndv":475,"upper":"3367207908110272327","lower":"3365151267301571926","count":1225,"preSum":52582},{"ndv":514,"upper":"3370725579501265819","lower":"3367228611808390954","count":1221,"preSum":53807},{"ndv":508,"upper":"3373427342370413401","lower":"3370729034583939037","count":1224,"preSum":55028},{"ndv":507,"upper":"3376110423134727320","lower":"3373427811754798919","count":1222,"preSum":56252},{"ndv":306,"upper":"6917883572180817009","lower":"3376128314504785033","count":1224,"preSum":57474},{"ndv":269,"upper":"6917965439856678850","lower":"6917883577673782873","count":1224,"preSum":58698},{"ndv":255,"upper":"6918055224802023004","lower":"6917965882848842837","count":1232,"preSum":59922},{"ndv":289,"upper":"6918111250317251980","lower":"6918056144878376369","count":1223,"preSum":61154},{"ndv":268,"upper":"6918160873046414639","lower":"6918111278416991824","count":1222,"preSum":62377},{"ndv":296,"upper":"6918226694982604101","lower":"6918161278900508035","count":1228,"preSum":63599},{"ndv":308,"upper":"6918291141043295406","lower":"6918226817654002947","count":1224,"preSum":64827},{"ndv":334,"upper":"6918351361539577475","lower":"6918291148880156330","count":1227,"preSum":66051},{"ndv":277,"upper":"6918427573522077260","lower":"6918351842142983580","count":1226,"preSum":67278},{"ndv":281,"upper":"6918491158745257428","lower":"6918427657763165660","count":1225,"preSum":68504},{"ndv":262,"upper":"6918575256826484073","lower":"6918491168953013975","count":1224,"preSum":69729},{"ndv":239,"upper":"6918625812019025859","lower":"6918575307383117770","count":1226,"preSum":70953},{"ndv":245,"upper":"6918661486596396336","lower":"6918625934729942233","count":1221,"preSum":72179},{"ndv":341,"upper":"6918788117817857390","lower":"6918661772552837082","count":1226,"preSum":73400},{"ndv":311,"upper":"6918877994546435233","lower":"6918788128578934729","count":1222,"preSum":74626},{"ndv":322,"upper":"6918955499828352701","lower":"6918878795380561888","count":1225,"preSum":75848},{"ndv":335,"upper":"SRE20230525000923385","lower":"6918955516098516897","count":1068,"preSum":77073}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[9114,21,18,17,17,17,22,18],"valueArr":["","1878804770888254881","1885530073030324567","1901278920473952572","23052339951932","3364453579920471632","3364679873287697330","6918545942559725477"],"type":"String","sampleRate":1.0}',1189,0.009150696),('jala_wms_prod','shipment_detail','splitqty',83,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":30,"lower":30,"count":1,"preSum":0},{"ndv":1,"upper":48,"lower":48,"count":1,"preSum":1},{"ndv":1,"upper":96,"lower":96,"count":1,"preSum":2},{"ndv":1,"upper":144,"lower":144,"count":1,"preSum":3},{"ndv":1,"upper":2016,"lower":2016,"count":1,"preSum":4}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88559,3,7],"valueArr":[0,5,6],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','status',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[100],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','totalvolume',32237,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":10,"upper":10.1200,"lower":1.0000,"count":991,"preSum":0},{"ndv":3,"upper":14.0800,"lower":12.7460,"count":1019,"preSum":991},{"ndv":49,"upper":83.7200,"lower":17.2720,"count":1059,"preSum":2010},{"ndv":6,"upper":98.4050,"lower":85.6730,"count":1094,"preSum":3069},{"ndv":27,"upper":128.0300,"lower":99.2900,"count":1545,"preSum":4163},{"ndv":7,"upper":132.6450,"lower":129.3860,"count":1170,"preSum":5708},{"ndv":19,"upper":152.7550,"lower":133.0270,"count":1128,"preSum":6878},{"ndv":13,"upper":175.0000,"lower":154.1400,"count":1234,"preSum":8006},{"ndv":22,"upper":200.8910,"lower":175.5450,"count":987,"preSum":9240},{"ndv":21,"upper":229.4300,"lower":202.5870,"count":1010,"preSum":10227},{"ndv":12,"upper":239.7780,"lower":230.4670,"count":1154,"preSum":11237},{"ndv":2,"upper":240.8700,"lower":240.8250,"count":985,"preSum":12391},{"ndv":14,"upper":256.0600,"lower":241.6030,"count":1180,"preSum":13376},{"ndv":15,"upper":273.7080,"lower":257.0190,"count":1398,"preSum":14556},{"ndv":20,"upper":289.7750,"lower":275.4800,"count":1756,"preSum":15954},{"ndv":16,"upper":305.2500,"lower":290.4000,"count":1361,"preSum":17710},{"ndv":10,"upper":316.9960,"lower":305.5100,"count":979,"preSum":19071},{"ndv":17,"upper":331.6130,"lower":318.3040,"count":1344,"preSum":20050},{"ndv":34,"upper":365.9720,"lower":333.4440,"count":966,"preSum":21394},{"ndv":13,"upper":385.5000,"lower":366.1350,"count":1219,"preSum":22360},{"ndv":32,"upper":423.3060,"lower":385.6720,"count":1525,"preSum":23579},{"ndv":29,"upper":458.8600,"lower":424.3200,"count":1607,"preSum":25104},{"ndv":13,"upper":473.6160,"lower":460.2280,"count":970,"preSum":26711},{"ndv":17,"upper":492.4770,"lower":475.2000,"count":1112,"preSum":27681},{"ndv":1,"upper":493.2180,"lower":493.2180,"count":1000,"preSum":28793},{"ndv":11,"upper":505.5980,"lower":494.5350,"count":966,"preSum":29793},{"ndv":23,"upper":535.0120,"lower":505.8900,"count":1371,"preSum":30759},{"ndv":8,"upper":545.4430,"lower":536.2150,"count":1242,"preSum":32130},{"ndv":4,"upper":549.4230,"lower":546.6500,"count":1196,"preSum":33372},{"ndv":19,"upper":569.5160,"lower":549.7880,"count":971,"preSum":34568},{"ndv":19,"upper":589.1150,"lower":570.3960,"count":1490,"preSum":35539},{"ndv":17,"upper":604.9160,"lower":589.5020,"count":969,"preSum":37029},{"ndv":17,"upper":633.9920,"lower":604.9180,"count":1022,"preSum":37998},{"ndv":26,"upper":670.6250,"lower":636.6080,"count":965,"preSum":39020},{"ndv":15,"upper":694.0730,"lower":672.7830,"count":1050,"preSum":39985},{"ndv":52,"upper":783.0270,"lower":695.3580,"count":995,"preSum":41035},{"ndv":47,"upper":857.2660,"lower":784.4780,"count":1013,"preSum":42030},{"ndv":52,"upper":949.3130,"lower":857.6660,"count":1083,"preSum":43043},{"ndv":76,"upper":1090.7400,"lower":950.2950,"count":990,"preSum":44126},{"ndv":56,"upper":1193.0150,"lower":1090.8860,"count":1358,"preSum":45116},{"ndv":39,"upper":1289.3400,"lower":1202.3820,"count":1058,"preSum":46474},{"ndv":67,"upper":1504.0160,"lower":1291.8780,"count":974,"preSum":47532},{"ndv":192,"upper":2148.5700,"lower":1506.7500,"count":965,"preSum":48506},{"ndv":12,"upper":2204.4750,"lower":2148.5750,"count":974,"preSum":49471},{"ndv":42,"upper":2350.3520,"lower":2214.4000,"count":1295,"preSum":50445},{"ndv":114,"upper":2865.4170,"lower":2353.4340,"count":978,"preSum":51740},{"ndv":187,"upper":3921.4780,"lower":2866.6300,"count":986,"preSum":52718},{"ndv":104,"upper":4700.7040,"lower":3924.2340,"count":1188,"preSum":53704},{"ndv":55,"upper":5161.7280,"lower":4712.0400,"count":1168,"preSum":54892},{"ndv":131,"upper":6446.7000,"lower":5173.2480,"count":1176,"preSum":56060},{"ndv":120,"upper":8037.1200,"lower":6455.3680,"count":964,"preSum":57236},{"ndv":296,"upper":13861.1260,"lower":8051.3840,"count":965,"preSum":58200},{"ndv":346,"upper":30396.5850,"lower":13870.4400,"count":965,"preSum":59165},{"ndv":580,"upper":215221.5360,"lower":30510.9200,"count":964,"preSum":60130},{"ndv":466,"upper":2304960000.0000,"lower":215908.7040,"count":549,"preSum":61094}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[2827,1057,1359,1367,1147,1297,1080,3480,2829,1087,1049,2165,1642,4545],"valueArr":[0.0000,157.4480,220.3070,327.1360,440.6140,554.1320,584.4300,752.0080,762.7730,872.8270,1060.3700,1525.5460,2580.8640,3051.0920],"type":"Double","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','totalweight',26628,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":26,"upper":8.0000,"lower":0.1000,"count":1126,"preSum":0},{"ndv":31,"upper":15.0000,"lower":8.3040,"count":1125,"preSum":1126},{"ndv":46,"upper":27.7770,"lower":15.2770,"count":1112,"preSum":2251},{"ndv":13,"upper":31.1110,"lower":27.7780,"count":1216,"preSum":3363},{"ndv":20,"upper":36.0000,"lower":31.2500,"count":1234,"preSum":4579},{"ndv":16,"upper":38.5710,"lower":36.1100,"count":1388,"preSum":5813},{"ndv":15,"upper":41.6670,"lower":38.8880,"count":1680,"preSum":7201},{"ndv":41,"upper":56.5000,"lower":42.0000,"count":1144,"preSum":8881},{"ndv":19,"upper":62.2220,"lower":57.5000,"count":1308,"preSum":10025},{"ndv":23,"upper":70.0000,"lower":62.5000,"count":1083,"preSum":11333},{"ndv":15,"upper":73.0000,"lower":70.1400,"count":1274,"preSum":12416},{"ndv":7,"upper":75.5560,"lower":73.3340,"count":1405,"preSum":13690},{"ndv":23,"upper":81.2500,"lower":75.6660,"count":1319,"preSum":15095},{"ndv":15,"upper":86.0000,"lower":82.1430,"count":1517,"preSum":16414},{"ndv":33,"upper":96.8750,"lower":86.4570,"count":1081,"preSum":17931},{"ndv":14,"upper":102.0830,"lower":97.0000,"count":1355,"preSum":19012},{"ndv":21,"upper":108.3330,"lower":103.0000,"count":1429,"preSum":20367},{"ndv":23,"upper":116.6660,"lower":108.3400,"count":1090,"preSum":21796},{"ndv":13,"upper":122.0000,"lower":116.6670,"count":1526,"preSum":22886},{"ndv":28,"upper":133.3330,"lower":122.2160,"count":1305,"preSum":24412},{"ndv":15,"upper":139.0630,"lower":133.3340,"count":1522,"preSum":25717},{"ndv":19,"upper":146.0000,"lower":139.1300,"count":1122,"preSum":27239},{"ndv":32,"upper":160.0000,"lower":147.0000,"count":1309,"preSum":28361},{"ndv":18,"upper":165.0000,"lower":160.4160,"count":1373,"preSum":29670},{"ndv":12,"upper":168.7500,"lower":166.0000,"count":1307,"preSum":31043},{"ndv":7,"upper":172.0000,"lower":168.8880,"count":1085,"preSum":32350},{"ndv":12,"upper":180.0000,"lower":172.5000,"count":1155,"preSum":33435},{"ndv":35,"upper":193.7500,"lower":180.5600,"count":1572,"preSum":34590},{"ndv":18,"upper":200.0000,"lower":194.0000,"count":1099,"preSum":36162},{"ndv":34,"upper":216.0000,"lower":200.0010,"count":1272,"preSum":37261},{"ndv":32,"upper":229.1670,"lower":216.5140,"count":1251,"preSum":38533},{"ndv":22,"upper":239.5830,"lower":230.0000,"count":1131,"preSum":39784},{"ndv":25,"upper":250.0000,"lower":240.0000,"count":1340,"preSum":40915},{"ndv":23,"upper":262.5000,"lower":251.0000,"count":1751,"preSum":42255},{"ndv":16,"upper":270.0000,"lower":263.4710,"count":1083,"preSum":44006},{"ndv":23,"upper":289.5830,"lower":270.8330,"count":1111,"preSum":45089},{"ndv":43,"upper":315.0000,"lower":290.0000,"count":1123,"preSum":46200},{"ndv":48,"upper":350.0000,"lower":316.6650,"count":1151,"preSum":47323},{"ndv":20,"upper":363.0000,"lower":350.0010,"count":1101,"preSum":48474},{"ndv":22,"upper":375.0000,"lower":364.0000,"count":1099,"preSum":49575},{"ndv":33,"upper":391.6670,"lower":377.7740,"count":1770,"preSum":50674},{"ndv":87,"upper":466.6660,"lower":391.6680,"count":1103,"preSum":52444},{"ndv":45,"upper":508.3320,"lower":466.6670,"count":1201,"preSum":53547},{"ndv":60,"upper":566.6660,"lower":508.3340,"count":1145,"preSum":54748},{"ndv":42,"upper":630.0000,"lower":566.6700,"count":1149,"preSum":55893},{"ndv":33,"upper":666.6650,"lower":631.2510,"count":1186,"preSum":57042},{"ndv":59,"upper":733.3330,"lower":666.6680,"count":1370,"preSum":58228},{"ndv":80,"upper":854.1650,"lower":737.4960,"count":1081,"preSum":59598},{"ndv":149,"upper":1100.0000,"lower":856.0000,"count":1123,"preSum":60679},{"ndv":106,"upper":1300.0000,"lower":1105.0000,"count":1423,"preSum":61802},{"ndv":80,"upper":1466.6660,"lower":1300.0020,"count":1164,"preSum":63225},{"ndv":202,"upper":2133.3280,"lower":1467.0000,"count":1081,"preSum":64389},{"ndv":241,"upper":3400.0000,"lower":2133.3360,"count":1081,"preSum":65470},{"ndv":406,"upper":8400.0000,"lower":3408.0000,"count":1088,"preSum":66551},{"ndv":647,"upper":100912.5000,"lower":8400.0240,"count":1081,"preSum":67639},{"ndv":367,"upper":10800000.0000,"lower":101000.1600,"count":426,"preSum":68720}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[1666,1533,945,1100,1098,766,1197,1637,839,801,1068,1680,1906,3192],"valueArr":[0.0000,93.7500,99.0000,114.5830,147.9170,175.0000,195.0000,210.4170,227.0830,277.0830,333.3340,420.8340,780.0000,841.6680],"type":"Double","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','umqtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','unitqty',68,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":6,"lower":6,"count":1,"preSum":0},{"ndv":1,"upper":24,"lower":24,"count":1,"preSum":1},{"ndv":1,"upper":48,"lower":48,"count":1,"preSum":2},{"ndv":1,"upper":72,"lower":72,"count":1,"preSum":3}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88544,26],"valueArr":[1,3],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','unitqtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','uploadrequired',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','userdef1',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[66,230,333],"valueArr":["KG","PCS","ST2"],"type":"String","sampleRate":1.0}',87945,0.009150696),('jala_wms_prod','shipment_detail','userdef2',1074,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":5,"upper":"0.28","lower":"0","count":816,"preSum":0},{"ndv":52,"upper":"1.79","lower":"0.32","count":710,"preSum":816},{"ndv":1,"upper":"1.91","lower":"1.91","count":1000,"preSum":1526},{"ndv":9,"upper":"1060","lower":"1.95","count":725,"preSum":2526},{"ndv":9,"upper":"110","lower":"1060.00","count":1191,"preSum":3251},{"ndv":7,"upper":"118","lower":"110.00","count":1512,"preSum":4442},{"ndv":11,"upper":"128.00","lower":"118.00","count":848,"preSum":5954},{"ndv":10,"upper":"139","lower":"1280.00","count":1682,"preSum":6802},{"ndv":11,"upper":"15","lower":"1390.00","count":1145,"preSum":8484},{"ndv":2,"upper":"150","lower":"15.00","count":798,"preSum":9629},{"ndv":4,"upper":"158","lower":"150.00","count":1239,"preSum":10427},{"ndv":5,"upper":"16","lower":"158.00","count":998,"preSum":11666},{"ndv":4,"upper":"168","lower":"16.00","count":1632,"preSum":12664},{"ndv":12,"upper":"18","lower":"168.00","count":1125,"preSum":14296},{"ndv":10,"upper":"190.00","lower":"18.00","count":833,"preSum":15421},{"ndv":3,"upper":"198.00","lower":"195","count":726,"preSum":16254},{"ndv":5,"upper":"2.18","lower":"1980.00","count":708,"preSum":16980},{"ndv":2,"upper":"20","lower":"2.25","count":991,"preSum":17688},{"ndv":14,"upper":"22","lower":"20.00","count":716,"preSum":18679},{"ndv":10,"upper":"240","lower":"22.00","count":1232,"preSum":19395},{"ndv":4,"upper":"25","lower":"240.00","count":1240,"preSum":20627},{"ndv":8,"upper":"260.00","lower":"25.00","count":848,"preSum":21867},{"ndv":11,"upper":"280","lower":"263","count":751,"preSum":22715},{"ndv":5,"upper":"29","lower":"280.00","count":1267,"preSum":23466},{"ndv":14,"upper":"32","lower":"29.00","count":1336,"preSum":24733},{"ndv":5,"upper":"33","lower":"320","count":1051,"preSum":26069},{"ndv":8,"upper":"35","lower":"33.00","count":723,"preSum":27120},{"ndv":4,"upper":"36","lower":"35.00","count":714,"preSum":27843},{"ndv":4,"upper":"370","lower":"36.00","count":1096,"preSum":28557},{"ndv":5,"upper":"380","lower":"370.00","count":756,"preSum":29653},{"ndv":15,"upper":"40","lower":"380.00","count":1031,"preSum":30409},{"ndv":12,"upper":"43","lower":"40.00","count":725,"preSum":31440},{"ndv":10,"upper":"49","lower":"45.00","count":1052,"preSum":32165},{"ndv":7,"upper":"50","lower":"49.00","count":833,"preSum":33217},{"ndv":16,"upper":"543","lower":"50.00","count":1130,"preSum":34050},{"ndv":3,"upper":"550","lower":"55","count":710,"preSum":35180},{"ndv":1,"upper":"58","lower":"58","count":1278,"preSum":35890},{"ndv":14,"upper":"62","lower":"58.00","count":1610,"preSum":37168},{"ndv":10,"upper":"660.00","lower":"62.00","count":812,"preSum":38778},{"ndv":6,"upper":"69","lower":"67","count":710,"preSum":39590},{"ndv":13,"upper":"78","lower":"690","count":893,"preSum":40300},{"ndv":9,"upper":"85","lower":"78.00","count":1521,"preSum":41193},{"ndv":8,"upper":"9","lower":"85.00","count":793,"preSum":42714},{"ndv":11,"upper":"98","lower":"9.00","count":1158,"preSum":43507},{"ndv":3,"upper":"99.00","lower":"98.00","count":531,"preSum":44665}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[3125,2043,3626,2354,1870,3699,1423,1784,10721,1697,1549,1428,1824,2173],"valueArr":["12","128","138","145","180","220","39","45","48","59","68","73","75","88"],"type":"String","sampleRate":1.0}',4062,0.009150696),('jala_wms_prod','shipment_detail','userdef3',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','userdef4',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','userdef5',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[80,48],"valueArr":["","0"],"type":"String","sampleRate":1.0}',88446,0.009150696),('jala_wms_prod','shipment_detail','userdef6',1098,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":7,"upper":" 沪G妆网备字2022004082","lower":" 沪G妆网备字2020004753","count":662,"preSum":0},{"ndv":7,"upper":"国妆特字G20152356","lower":" 沪G妆网备字2022004387","count":741,"preSum":662},{"ndv":5,"upper":"国妆特字G20160746","lower":"国妆特字G20152457","count":930,"preSum":1403},{"ndv":1,"upper":"国妆特字G20160747","lower":"国妆特字G20160747","count":757,"preSum":2333},{"ndv":2,"upper":"国妆特字G20170188","lower":"国妆特字G20160748","count":1023,"preSum":3090},{"ndv":6,"upper":"国妆特字G20170298","lower":"国妆特字G20170236","count":638,"preSum":4113},{"ndv":22,"upper":"国妆特字G20210512","lower":"国妆特字G20170557","count":624,"preSum":4751},{"ndv":3,"upper":"国妆特字G20212184","lower":"国妆特字G20210992","count":641,"preSum":5375},{"ndv":12,"upper":"沪G妆网备字2017012855","lower":"国妆特字G20212656","count":725,"preSum":6016},{"ndv":13,"upper":"沪G妆网备字2018002786","lower":"沪G妆网备字2017013271","count":693,"preSum":6741},{"ndv":8,"upper":"沪G妆网备字2018004480","lower":"沪G妆网备字2018002854","count":646,"preSum":7434},{"ndv":24,"upper":"沪G妆网备字2018011637","lower":"沪G妆网备字2018004880","count":744,"preSum":8080},{"ndv":19,"upper":"沪G妆网备字2019011817","lower":"沪G妆网备字2018011922","count":766,"preSum":8824},{"ndv":5,"upper":"沪G妆网备字2019012155","lower":"沪G妆网备字2019011818","count":702,"preSum":9590},{"ndv":14,"upper":"沪G妆网备字2019024172","lower":"沪G妆网备字2019012367","count":753,"preSum":10292},{"ndv":14,"upper":"沪G妆网备字2019026142","lower":"沪G妆网备字2019025317","count":890,"preSum":11045},{"ndv":10,"upper":"沪G妆网备字2020004852","lower":"沪G妆网备字2019026478","count":675,"preSum":11935},{"ndv":18,"upper":"沪G妆网备字2020012153","lower":"沪G妆网备字2020004858","count":1071,"preSum":12610},{"ndv":29,"upper":"沪G妆网备字2020019253","lower":"沪G妆网备字2020012555","count":637,"preSum":13681},{"ndv":5,"upper":"沪G妆网备字2020021207","lower":"沪G妆网备字2020019254","count":1233,"preSum":14318},{"ndv":13,"upper":"沪G妆网备字2020029583","lower":"沪G妆网备字2020021209","count":609,"preSum":15551},{"ndv":15,"upper":"沪G妆网备字2020029630","lower":"沪G妆网备字2020029591","count":591,"preSum":16160},{"ndv":18,"upper":"沪G妆网备字2021009165","lower":"沪G妆网备字2020030090","count":677,"preSum":16751},{"ndv":28,"upper":"沪G妆网备字2021506149","lower":"沪G妆网备字2021009303","count":594,"preSum":17428},{"ndv":33,"upper":"沪G妆网备字2021514376","lower":"沪G妆网备字2021506150","count":771,"preSum":18022},{"ndv":5,"upper":"沪G妆网备字2021521123","lower":"沪G妆网备字2021514381","count":1315,"preSum":18793},{"ndv":4,"upper":"沪G妆网备字2021521129","lower":"沪G妆网备字2021521124","count":631,"preSum":20108},{"ndv":3,"upper":"沪G妆网备字2021521133","lower":"沪G妆网备字2021521131","count":718,"preSum":20739},{"ndv":11,"upper":"沪G妆网备字2022004082","lower":"沪G妆网备字2022002101","count":707,"preSum":21457},{"ndv":7,"upper":"沪G妆网备字2022005879","lower":"沪G妆网备字2022004221","count":653,"preSum":22164},{"ndv":7,"upper":"沪G妆网备字2022006971","lower":"沪G妆网备字2022006052","count":945,"preSum":22817},{"ndv":17,"upper":"沪G妆网备字2022009151","lower":"沪G妆网备字2022007241","count":1396,"preSum":23762},{"ndv":10,"upper":"沪G妆网备字2022009964","lower":"沪G妆网备字2022009352","count":650,"preSum":25158},{"ndv":2,"upper":"沪G妆网备字2022009971","lower":"沪G妆网备字2022009965","count":840,"preSum":25808},{"ndv":11,"upper":"沪G妆网备字2022011184","lower":"沪G妆网备字2022009974","count":1176,"preSum":26648},{"ndv":3,"upper":"沪G妆网备字2022012103","lower":"沪G妆网备字2022012099","count":748,"preSum":27824},{"ndv":2,"upper":"沪G妆网备字2022012511","lower":"沪G妆网备字2022012192","count":1160,"preSum":28572},{"ndv":10,"upper":"沪G妆网备字2022016022","lower":"沪G妆网备字2022012563","count":723,"preSum":29732},{"ndv":2,"upper":"沪G妆网备字2022016024","lower":"沪G妆网备字2022016023","count":762,"preSum":30455},{"ndv":4,"upper":"沪G妆网备字2022016859","lower":"沪G妆网备字2022016025","count":661,"preSum":31217},{"ndv":2,"upper":"沪G妆网备字2022016861","lower":"沪G妆网备字2022016860","count":626,"preSum":31878},{"ndv":7,"upper":"沪G妆网备字2022018784","lower":"沪G妆网备字2022016862","count":599,"preSum":32504},{"ndv":9,"upper":"沪G妆网备字2023000736","lower":"沪G妆网备字2022019199","count":955,"preSum":33103},{"ndv":3,"upper":"沪G妆网备字2023000773","lower":"沪G妆网备字2023000741","count":1239,"preSum":34058},{"ndv":2,"upper":"沪G妆网备字2023001317","lower":"沪G妆网备字2023000865","count":1198,"preSum":35297},{"ndv":1,"upper":"沪G妆网备字2023002839","lower":"沪G妆网备字2023002839","count":1207,"preSum":36495},{"ndv":4,"upper":"黑械注准20212140027","lower":"沪G妆网备字2023002840","count":75,"preSum":37702}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[24337,1455,1373,1223,3265,2829,2303,2515,2382,1439,1375,1357,1587,1817],"valueArr":[""," 沪G妆网备字2022006688","沪G妆网备字2018014969","沪G妆网备字2018015896","沪G妆网备字2021501304","沪G妆网备字2021501306","沪G妆网备字2021501307","沪G妆网备字2021501765","沪G妆网备字2021501766","沪G妆网备字2021521014","沪G妆网备字2022000191","沪G妆网备字2022004670","沪G妆网备字2022015936","沪G妆网备字2023000771"],"type":"String","sampleRate":1.0}',1540,0.009150696),('jala_wms_prod','shipment_detail','userdef7',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','userdef8',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,88574,0.009150696),('jala_wms_prod','shipment_detail','version',26,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":3,"lower":3,"count":2,"preSum":0},{"ndv":1,"upper":7,"lower":7,"count":1,"preSum":2},{"ndv":1,"upper":9,"lower":9,"count":1,"preSum":3}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88542,25,3],"valueArr":[0,1,2],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','warehousecode',11,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[2992,6032,13126,1103,49674,12775,3,954,1255,519,141],"valueArr":["021DC1","022DC","027DC","028DC","573DC","763DC","763DCA","SH01","SH02","SH03","TEST01"],"type":"String","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','warehousetransferdtlid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[88574],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_detail','waveid',46523,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":201,"upper":46268,"lower":676,"count":1269,"preSum":0},{"ndv":113,"upper":476780,"lower":55440,"count":1277,"preSum":1269},{"ndv":231,"upper":564640,"lower":477104,"count":1268,"preSum":2546},{"ndv":307,"upper":590868,"lower":564735,"count":1269,"preSum":3814},{"ndv":355,"upper":635224,"lower":590870,"count":1267,"preSum":5083},{"ndv":276,"upper":676087,"lower":635239,"count":1271,"preSum":6350},{"ndv":279,"upper":708334,"lower":676150,"count":1269,"preSum":7621},{"ndv":280,"upper":723389,"lower":708525,"count":1265,"preSum":8890},{"ndv":315,"upper":742154,"lower":723392,"count":1269,"preSum":10155},{"ndv":240,"upper":749672,"lower":742187,"count":1292,"preSum":11424},{"ndv":165,"upper":755109,"lower":749700,"count":1267,"preSum":12716},{"ndv":185,"upper":761875,"lower":755133,"count":1266,"preSum":13983},{"ndv":237,"upper":769438,"lower":761878,"count":1303,"preSum":15249},{"ndv":182,"upper":774511,"lower":769439,"count":1266,"preSum":16552},{"ndv":192,"upper":783457,"lower":774513,"count":1270,"preSum":17818},{"ndv":209,"upper":790974,"lower":783458,"count":1265,"preSum":19088},{"ndv":192,"upper":795766,"lower":790979,"count":1271,"preSum":20353},{"ndv":220,"upper":801922,"lower":795789,"count":1272,"preSum":21624},{"ndv":189,"upper":809024,"lower":801925,"count":1265,"preSum":22896},{"ndv":241,"upper":812151,"lower":809025,"count":1266,"preSum":24161},{"ndv":175,"upper":817300,"lower":812201,"count":1268,"preSum":25427},{"ndv":183,"upper":820525,"lower":817303,"count":1265,"preSum":26695},{"ndv":176,"upper":823169,"lower":820528,"count":1270,"preSum":27960},{"ndv":160,"upper":825697,"lower":823172,"count":1265,"preSum":29230},{"ndv":142,"upper":827721,"lower":825724,"count":1266,"preSum":30495},{"ndv":173,"upper":833823,"lower":827726,"count":1271,"preSum":31761},{"ndv":168,"upper":843966,"lower":833841,"count":1268,"preSum":33032},{"ndv":174,"upper":853843,"lower":843973,"count":1269,"preSum":34300},{"ndv":197,"upper":863986,"lower":853844,"count":1266,"preSum":35569},{"ndv":192,"upper":872240,"lower":863993,"count":1270,"preSum":36835},{"ndv":183,"upper":879735,"lower":872241,"count":1276,"preSum":38105},{"ndv":169,"upper":885175,"lower":879739,"count":1270,"preSum":39381},{"ndv":196,"upper":895050,"lower":885179,"count":1266,"preSum":40651},{"ndv":178,"upper":903078,"lower":895054,"count":1281,"preSum":41917},{"ndv":176,"upper":909619,"lower":903083,"count":1270,"preSum":43198},{"ndv":195,"upper":914583,"lower":909620,"count":1274,"preSum":44468},{"ndv":177,"upper":925228,"lower":914586,"count":1279,"preSum":45742},{"ndv":239,"upper":932324,"lower":925248,"count":1265,"preSum":47021},{"ndv":213,"upper":937154,"lower":932328,"count":1265,"preSum":48286},{"ndv":176,"upper":944356,"lower":937160,"count":1277,"preSum":49551},{"ndv":209,"upper":952342,"lower":944420,"count":1269,"preSum":50828},{"ndv":172,"upper":958425,"lower":952343,"count":1293,"preSum":52097},{"ndv":120,"upper":963044,"lower":958426,"count":1291,"preSum":53390},{"ndv":162,"upper":968367,"lower":963045,"count":1266,"preSum":54681},{"ndv":244,"upper":979659,"lower":968371,"count":1273,"preSum":55947},{"ndv":233,"upper":992546,"lower":979839,"count":1272,"preSum":57220},{"ndv":199,"upper":1003968,"lower":992549,"count":1269,"preSum":58492},{"ndv":207,"upper":1013756,"lower":1004005,"count":1266,"preSum":59761},{"ndv":234,"upper":1019023,"lower":1013771,"count":1268,"preSum":61027},{"ndv":193,"upper":1025407,"lower":1019024,"count":1266,"preSum":62295},{"ndv":184,"upper":1029130,"lower":1025458,"count":1270,"preSum":63561},{"ndv":203,"upper":1034857,"lower":1029145,"count":1300,"preSum":64831},{"ndv":223,"upper":1039483,"lower":1034862,"count":1274,"preSum":66131},{"ndv":223,"upper":1042315,"lower":1039523,"count":1269,"preSum":67405},{"ndv":105,"upper":1043045,"lower":1042343,"count":1265,"preSum":68674},{"ndv":197,"upper":1044131,"lower":1043084,"count":1279,"preSum":69939},{"ndv":189,"upper":1045966,"lower":1044132,"count":1283,"preSum":71218},{"ndv":157,"upper":1048174,"lower":1045967,"count":1267,"preSum":72501},{"ndv":176,"upper":1049385,"lower":1048182,"count":1296,"preSum":73768},{"ndv":167,"upper":1050913,"lower":1049386,"count":1267,"preSum":75064},{"ndv":208,"upper":1052178,"lower":1050921,"count":1271,"preSum":76331},{"ndv":254,"upper":1054685,"lower":1052179,"count":1271,"preSum":77602},{"ndv":256,"upper":1058082,"lower":1054755,"count":1268,"preSum":78873},{"ndv":196,"upper":1079298,"lower":1058118,"count":801,"preSum":80141}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[6198,135,94,110,123,159,98,108,101,93,100,101,96,116],"valueArr":[0,755541,774691,807179,824994,832167,841185,853957,875514,889159,907400,929788,944624,1029143],"type":"Int","sampleRate":1.0}',0,0.009150696),('jala_wms_prod','shipment_header','actualdeliverydate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Date","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[-1],"type":"Date","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','actualshipdatetime',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','actualtotalweight',9962,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":57,"upper":0.094000,"lower":0.002000,"count":1048,"preSum":0},{"ndv":26,"upper":0.120000,"lower":0.095000,"count":1104,"preSum":1048},{"ndv":24,"upper":0.144000,"lower":0.121000,"count":1054,"preSum":2152},{"ndv":16,"upper":0.160000,"lower":0.145000,"count":1228,"preSum":3206},{"ndv":21,"upper":0.180000,"lower":0.161000,"count":1053,"preSum":4434},{"ndv":29,"upper":0.210000,"lower":0.181000,"count":1338,"preSum":5487},{"ndv":20,"upper":0.230000,"lower":0.211000,"count":1297,"preSum":6825},{"ndv":30,"upper":0.260000,"lower":0.231000,"count":1188,"preSum":8122},{"ndv":30,"upper":0.290000,"lower":0.261000,"count":1068,"preSum":9310},{"ndv":20,"upper":0.310000,"lower":0.291000,"count":1357,"preSum":10378},{"ndv":18,"upper":0.329000,"lower":0.311000,"count":1043,"preSum":11735},{"ndv":16,"upper":0.346000,"lower":0.331000,"count":1074,"preSum":12778},{"ndv":18,"upper":0.365000,"lower":0.347000,"count":1179,"preSum":13852},{"ndv":15,"upper":0.380000,"lower":0.366000,"count":1360,"preSum":15031},{"ndv":29,"upper":0.410000,"lower":0.381000,"count":1276,"preSum":16391},{"ndv":20,"upper":0.430000,"lower":0.411000,"count":1194,"preSum":17667},{"ndv":20,"upper":0.450000,"lower":0.431000,"count":1131,"preSum":18861},{"ndv":20,"upper":0.470000,"lower":0.451000,"count":1044,"preSum":19992},{"ndv":48,"upper":0.520000,"lower":0.471000,"count":1133,"preSum":21036},{"ndv":59,"upper":0.580000,"lower":0.521000,"count":1186,"preSum":22169},{"ndv":29,"upper":0.613000,"lower":0.581000,"count":1040,"preSum":23355},{"ndv":10,"upper":0.623000,"lower":0.614000,"count":1099,"preSum":24395},{"ndv":27,"upper":0.650000,"lower":0.624000,"count":1130,"preSum":25494},{"ndv":38,"upper":0.692000,"lower":0.651000,"count":1061,"preSum":26624},{"ndv":66,"upper":0.766000,"lower":0.693000,"count":1041,"preSum":27685},{"ndv":31,"upper":0.800000,"lower":0.767000,"count":1053,"preSum":28726},{"ndv":55,"upper":0.860000,"lower":0.801000,"count":1161,"preSum":29779},{"ndv":27,"upper":0.887000,"lower":0.861000,"count":1076,"preSum":30940},{"ndv":14,"upper":0.902000,"lower":0.888000,"count":1055,"preSum":32016},{"ndv":38,"upper":0.940000,"lower":0.903000,"count":1144,"preSum":33071},{"ndv":30,"upper":0.970000,"lower":0.941000,"count":1188,"preSum":34215},{"ndv":33,"upper":1.004000,"lower":0.971000,"count":1042,"preSum":35403},{"ndv":36,"upper":1.040000,"lower":1.005000,"count":1131,"preSum":36445},{"ndv":44,"upper":1.085000,"lower":1.041000,"count":1043,"preSum":37576},{"ndv":49,"upper":1.135000,"lower":1.086000,"count":1060,"preSum":38619},{"ndv":69,"upper":1.210000,"lower":1.136000,"count":1125,"preSum":39679},{"ndv":81,"upper":1.300000,"lower":1.211000,"count":1111,"preSum":40804},{"ndv":53,"upper":1.356000,"lower":1.302000,"count":1045,"preSum":41915},{"ndv":71,"upper":1.430000,"lower":1.357000,"count":1085,"preSum":42960},{"ndv":102,"upper":1.550000,"lower":1.431000,"count":1081,"preSum":44045},{"ndv":85,"upper":1.652000,"lower":1.551000,"count":1055,"preSum":45126},{"ndv":62,"upper":1.728000,"lower":1.653000,"count":1039,"preSum":46181},{"ndv":39,"upper":1.770000,"lower":1.729000,"count":1088,"preSum":47220},{"ndv":64,"upper":1.842000,"lower":1.771000,"count":1103,"preSum":48308},{"ndv":12,"upper":1.854000,"lower":1.843000,"count":1066,"preSum":49411},{"ndv":26,"upper":1.880000,"lower":1.855000,"count":1061,"preSum":50477},{"ndv":52,"upper":1.937000,"lower":1.881000,"count":1047,"preSum":51538},{"ndv":71,"upper":2.030000,"lower":1.938000,"count":1075,"preSum":52585},{"ndv":93,"upper":2.160000,"lower":2.031000,"count":1104,"preSum":53660},{"ndv":74,"upper":2.274000,"lower":2.161000,"count":1055,"preSum":54764},{"ndv":37,"upper":2.327000,"lower":2.276000,"count":1071,"preSum":55819},{"ndv":62,"upper":2.399000,"lower":2.328000,"count":1053,"preSum":56890},{"ndv":53,"upper":2.469000,"lower":2.400000,"count":1072,"preSum":57943},{"ndv":47,"upper":2.530000,"lower":2.470000,"count":1063,"preSum":59015},{"ndv":100,"upper":2.690000,"lower":2.531000,"count":1062,"preSum":60078},{"ndv":12,"upper":2.702000,"lower":2.691000,"count":1079,"preSum":61140},{"ndv":133,"upper":3.230000,"lower":2.703000,"count":1040,"preSum":62219},{"ndv":228,"upper":4.282000,"lower":3.234000,"count":1130,"preSum":63259},{"ndv":52,"upper":4.470000,"lower":4.283000,"count":1044,"preSum":64389},{"ndv":819,"upper":2123.852000,"lower":4.480000,"count":1018,"preSum":65433}],"maxBucketSize":64,"type":"Double","sampleRate":0.9618625}','{"countArr":[9756,485,453,533,592,497,601,1693,538,501,549,607,653,945],"valueArr":[0.000000,0.200000,0.320000,0.330000,0.350000,0.400000,0.590000,0.593000,0.600000,0.840000,0.890000,0.900000,1.060000,4.305000],"type":"Double","sampleRate":0.9618625319816094}',15147,0.02436278),('jala_wms_prod','shipment_header','agentcode',20,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"MC","lower":"MC","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1638,1335,9,48,126,646,29,2417,423,85761,64],"valueArr":["","1753","JD","QCS","全品牌","春夏","植物智慧","珀芙研","美素","自然堂","莎辛那"],"type":"String","sampleRate":0.9618625319816094}',7504,0.02436278),('jala_wms_prod','shipment_header','allocatecomplete',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','allowconsolidate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[1],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','auditedat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('jala_wms_prod','shipment_header','auditedby',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','auditopinion',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','auditstatus',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[-2],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','backorderid',315,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":1264882,"lower":1264882,"count":1,"preSum":0},{"ndv":1,"upper":1328221,"lower":1328221,"count":1,"preSum":1},{"ndv":1,"upper":1363032,"lower":1363032,"count":1,"preSum":2},{"ndv":1,"upper":1367447,"lower":1367447,"count":1,"preSum":3},{"ndv":1,"upper":1367448,"lower":1367448,"count":1,"preSum":4},{"ndv":1,"upper":1369308,"lower":1369308,"count":1,"preSum":5},{"ndv":1,"upper":1381675,"lower":1381675,"count":1,"preSum":6},{"ndv":1,"upper":1407465,"lower":1407465,"count":1,"preSum":7},{"ndv":1,"upper":1466183,"lower":1466183,"count":1,"preSum":8},{"ndv":1,"upper":1504067,"lower":1504067,"count":1,"preSum":9},{"ndv":1,"upper":1974062,"lower":1974062,"count":1,"preSum":10},{"ndv":1,"upper":2472918,"lower":2472918,"count":1,"preSum":11},{"ndv":1,"upper":2604627,"lower":2604627,"count":1,"preSum":12},{"ndv":1,"upper":2606735,"lower":2606735,"count":1,"preSum":13},{"ndv":1,"upper":2607548,"lower":2607548,"count":1,"preSum":14},{"ndv":1,"upper":2607708,"lower":2607708,"count":1,"preSum":15},{"ndv":1,"upper":2646589,"lower":2646589,"count":1,"preSum":16},{"ndv":1,"upper":2794231,"lower":2794231,"count":1,"preSum":17},{"ndv":1,"upper":2943130,"lower":2943130,"count":1,"preSum":18},{"ndv":1,"upper":2946811,"lower":2946811,"count":1,"preSum":19},{"ndv":1,"upper":3418355,"lower":3418355,"count":1,"preSum":20},{"ndv":1,"upper":4235346,"lower":4235346,"count":1,"preSum":21},{"ndv":1,"upper":4264774,"lower":4264774,"count":1,"preSum":22},{"ndv":1,"upper":4265112,"lower":4265112,"count":1,"preSum":23},{"ndv":1,"upper":4446063,"lower":4446063,"count":1,"preSum":24},{"ndv":1,"upper":4446209,"lower":4446209,"count":1,"preSum":25},{"ndv":1,"upper":4999335,"lower":4999335,"count":1,"preSum":26},{"ndv":1,"upper":5541738,"lower":5541738,"count":1,"preSum":27},{"ndv":1,"upper":5642632,"lower":5642632,"count":1,"preSum":28},{"ndv":1,"upper":5835871,"lower":5835871,"count":1,"preSum":29}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[99971],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','bulkmaterials',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[57],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99944,0.02436278),('jala_wms_prod','shipment_header','carriercode',46,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"0000111","lower":"0000111","count":1,"preSum":0},{"ndv":1,"upper":"DISTRIBUTOR_1710055","lower":"DISTRIBUTOR_1710055","count":3,"preSum":1},{"ndv":1,"upper":"other","lower":"other","count":5,"preSum":4},{"ndv":1,"upper":"ZT","lower":"ZT","count":4,"preSum":9},{"ndv":1,"upper":"上海天翼物流股份有限公司","lower":"上海天翼物流股份有限公司","count":1,"preSum":13},{"ndv":1,"upper":"干线-华夏龙","lower":"干线-华夏龙","count":1,"preSum":14},{"ndv":1,"upper":"干线-盐城","lower":"干线-盐城","count":4,"preSum":15},{"ndv":1,"upper":"干线-铭创","lower":"干线-铭创","count":1,"preSum":19}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[55,108,1591,73141,132,455,248,15924,501,7010,44,6,14,24],"valueArr":["","EMS","OTHER","SF","SF1","SF2","SF3","ZTO","ZTOKY","shunfeng","上海恒兴国际物流有限公司","干线-溢宇","深圳市华夏龙供应链管理有限公司","深圳市顺丰综合物流服务有限公司"],"type":"String","sampleRate":0.9618625319816094}',728,0.02436278),('jala_wms_prod','shipment_header','carrierservice',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[61717,15660,6277,1195,864],"valueArr":["CAINIAO","DOUYIN","JD","KUAISHOU","PINDUODUO"],"type":"String","sampleRate":0.9618625319816094}',14288,0.02436278),('jala_wms_prod','shipment_header','checkbusinessscope',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','closeshipment',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[98563,12],"valueArr":[0,1],"type":"Int","sampleRate":0.9618625319816094}',1426,0.02436278),('jala_wms_prod','shipment_header','code',4056659,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1556,"upper":"CK0001182088","lower":"0001622094","count":1563,"preSum":0},{"ndv":1563,"upper":"CK0001490734","lower":"CK0001182092","count":1563,"preSum":1563},{"ndv":1563,"upper":"PJD2304784741732216","lower":"CK0001490789","count":1563,"preSum":3126},{"ndv":1563,"upper":"PJX2302755575782520","lower":"PJD2304784969012223","count":1563,"preSum":4689},{"ndv":1563,"upper":"PJX2304784168422111","lower":"PJX2302755575842520","count":1563,"preSum":6252},{"ndv":1563,"upper":"PJX2305792852660517","lower":"PJX2304784170782112","count":1563,"preSum":7815},{"ndv":1563,"upper":"PJX2305798102201513","lower":"PJX2305792852700517","count":1563,"preSum":9378},{"ndv":1563,"upper":"PJX2305803200802500","lower":"PJX2305798102211513","count":1563,"preSum":10941},{"ndv":1563,"upper":"PJX2306814015300322","lower":"PJX2305803200812500","count":1563,"preSum":12504},{"ndv":1563,"upper":"PJX2306819288341321","lower":"PJX2306814039350322","count":1563,"preSum":14067},{"ndv":1563,"upper":"PJX2306825824111918","lower":"PJX2306819290131321","count":1563,"preSum":15630},{"ndv":1563,"upper":"POD2305792269560416","lower":"PJX2306825825691918","count":1563,"preSum":17193},{"ndv":1563,"upper":"POD2306815551960611","lower":"POD2305792288510416","count":1563,"preSum":18756},{"ndv":1563,"upper":"PSD2304783592211923","lower":"POD2306815552190611","count":1563,"preSum":20319},{"ndv":1563,"upper":"PSD2304785587022415","lower":"PSD2304783595161923","count":1563,"preSum":21882},{"ndv":1563,"upper":"PSD2304787432372800","lower":"PSD2304785587032415","count":1563,"preSum":23445},{"ndv":1563,"upper":"PSD2305789573430209","lower":"PSD2304787432382800","count":1563,"preSum":25008},{"ndv":1563,"upper":"PSD2305793483700622","lower":"PSD2305789605510210","count":1563,"preSum":26571},{"ndv":1563,"upper":"PSD2305795450081016","lower":"PSD2305793483790622","count":1563,"preSum":28134},{"ndv":1563,"upper":"PSD2305797691701418","lower":"PSD2305795454021016","count":1563,"preSum":29697},{"ndv":1563,"upper":"PSD2305800437831912","lower":"PSD2305797692481418","count":1563,"preSum":31260},{"ndv":1563,"upper":"PSD2305802670242320","lower":"PSD2305800449941912","count":1563,"preSum":32823},{"ndv":1563,"upper":"PSD2305807435802813","lower":"PSD2305802684092321","count":1563,"preSum":34386},{"ndv":1563,"upper":"PSD2305810859123121","lower":"PSD2305807435842813","count":1563,"preSum":35949},{"ndv":1563,"upper":"PSD2306814246340402","lower":"PSD2305810873393121","count":1563,"preSum":37512},{"ndv":1563,"upper":"PSD2306816683280814","lower":"PSD2306814247780402","count":1563,"preSum":39075},{"ndv":1563,"upper":"PSD2306818784591220","lower":"PSD2306816683290814","count":1563,"preSum":40638},{"ndv":1563,"upper":"PSD2306821121101610","lower":"PSD2306818784611220","count":1563,"preSum":42201},{"ndv":1563,"upper":"PSD2306824267341817","lower":"PSD2306821121111610","count":1563,"preSum":43764},{"ndv":1563,"upper":"PSD2306827341062222","lower":"PSD2306824267431817","count":1563,"preSum":45327},{"ndv":1563,"upper":"PTB2302755699342602","lower":"PSD2306827341832222","count":1563,"preSum":46890},{"ndv":1563,"upper":"PTB2303766986991218","lower":"PTB2302755699752602","count":1563,"preSum":48453},{"ndv":1563,"upper":"PTB2304779649491204","lower":"PTB2303766987611218","count":1563,"preSum":50016},{"ndv":1563,"upper":"PTB2304784072712109","lower":"PTB2304779649641205","count":1563,"preSum":51579},{"ndv":1563,"upper":"PTB2304786671952614","lower":"PTB2304784073502109","count":1563,"preSum":53142},{"ndv":1563,"upper":"PTB2305788791420106","lower":"PTB2304786671972614","count":1563,"preSum":54705},{"ndv":1563,"upper":"PTB2305790449090309","lower":"PTB2305788791500106","count":1563,"preSum":56268},{"ndv":1563,"upper":"PTB2305791287310311","lower":"PTB2305790449130309","count":1563,"preSum":57831},{"ndv":1563,"upper":"PTB2305792915400521","lower":"PTB2305791303500311","count":1563,"preSum":59394},{"ndv":1563,"upper":"PTB2305795619371022","lower":"PTB2305792915520521","count":1563,"preSum":60957},{"ndv":1563,"upper":"PTB2305797854091500","lower":"PTB2305795620411022","count":1563,"preSum":62520},{"ndv":1563,"upper":"PTB2305799290641709","lower":"PTB2305797854391500","count":1563,"preSum":64083},{"ndv":1563,"upper":"PTB2305801469102110","lower":"PTB2305799292111709","count":1563,"preSum":65646},{"ndv":1563,"upper":"PTB2305803576792522","lower":"PTB2305801481782111","count":1563,"preSum":67209},{"ndv":1563,"upper":"PTB2305804711842710","lower":"PTB2305803577402522","count":1563,"preSum":68772},{"ndv":1563,"upper":"PTB2305805449052711","lower":"PTB2305804711852710","count":1563,"preSum":70335},{"ndv":1563,"upper":"PTB2305806128452713","lower":"PTB2305805449322711","count":1563,"preSum":71898},{"ndv":1563,"upper":"PTB2305806824312717","lower":"PTB2305806128572713","count":1563,"preSum":73461},{"ndv":1563,"upper":"PTB2305807873362820","lower":"PTB2305806824352717","count":1563,"preSum":75024},{"ndv":1563,"upper":"PTB2305809004133000","lower":"PTB2305807874572820","count":1563,"preSum":76587},{"ndv":1563,"upper":"PTB2305810287353117","lower":"PTB2305809004243000","count":1563,"preSum":78150},{"ndv":1563,"upper":"PTB2305811198223123","lower":"PTB2305810287403117","count":1563,"preSum":79713},{"ndv":1563,"upper":"PTB2306812485330200","lower":"PTB2305811216043123","count":1563,"preSum":81276},{"ndv":1563,"upper":"PTB2306813719870314","lower":"PTB2306812485340200","count":1563,"preSum":82839},{"ndv":1563,"upper":"PTB2306815226650519","lower":"PTB2306813719910314","count":1563,"preSum":84402},{"ndv":1563,"upper":"PTB2306817295170917","lower":"PTB2306815228690519","count":1563,"preSum":85965},{"ndv":1563,"upper":"PTB2306819095391313","lower":"PTB2306817296270917","count":1563,"preSum":87528},{"ndv":1563,"upper":"PTB2306820635471522","lower":"PTB2306819095401313","count":1563,"preSum":89091},{"ndv":1563,"upper":"PTB2306821855171622","lower":"PTB2306820635491522","count":1563,"preSum":90654},{"ndv":1563,"upper":"PTB2306822953031721","lower":"PTB2306821855201622","count":1563,"preSum":92217},{"ndv":1563,"upper":"PTB2306824514221821","lower":"PTB2306822953041721","count":1563,"preSum":93780},{"ndv":1563,"upper":"PTB2306825761171916","lower":"PTB2306824514291821","count":1563,"preSum":95343},{"ndv":1563,"upper":"PTB2306827242642215","lower":"PTB2306825762441916","count":1563,"preSum":96906},{"ndv":1532,"upper":"福袋wms其它出库-w009","lower":"PTB2306827242782215","count":1532,"preSum":98469}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,0,0.02436278),('jala_wms_prod','shipment_header','codrequired',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','codvalue',79498,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":107,"upper":9.9000,"lower":0.0100,"count":2010,"preSum":0},{"ndv":108,"upper":17.4600,"lower":9.9100,"count":1096,"preSum":2010},{"ndv":120,"upper":22.4000,"lower":17.5000,"count":1101,"preSum":3106},{"ndv":169,"upper":28.4000,"lower":22.4100,"count":1088,"preSum":4207},{"ndv":137,"upper":33.6000,"lower":28.4700,"count":1100,"preSum":5295},{"ndv":136,"upper":39.7600,"lower":33.8000,"count":1108,"preSum":6395},{"ndv":236,"upper":46.6300,"lower":39.7700,"count":1088,"preSum":7503},{"ndv":179,"upper":49.0000,"lower":46.6400,"count":1090,"preSum":8591},{"ndv":259,"upper":52.6300,"lower":49.0100,"count":1090,"preSum":9681},{"ndv":200,"upper":56.9300,"lower":52.6700,"count":1092,"preSum":10771},{"ndv":65,"upper":58.0000,"lower":56.9500,"count":1178,"preSum":11863},{"ndv":61,"upper":59.0000,"lower":58.0100,"count":1453,"preSum":13041},{"ndv":218,"upper":62.6500,"lower":59.0100,"count":1088,"preSum":14494},{"ndv":208,"upper":65.5500,"lower":62.6800,"count":1141,"preSum":15582},{"ndv":198,"upper":68.0000,"lower":65.5600,"count":1390,"preSum":16723},{"ndv":65,"upper":69.3000,"lower":68.0100,"count":1471,"preSum":18113},{"ndv":195,"upper":71.7200,"lower":69.3100,"count":1091,"preSum":19584},{"ndv":101,"upper":73.2100,"lower":71.7300,"count":1088,"preSum":20675},{"ndv":173,"upper":76.0000,"lower":73.2200,"count":1195,"preSum":21763},{"ndv":209,"upper":79.1200,"lower":76.0100,"count":1098,"preSum":22958},{"ndv":301,"upper":84.0000,"lower":79.1300,"count":1407,"preSum":24056},{"ndv":266,"upper":88.0200,"lower":84.0100,"count":1125,"preSum":25463},{"ndv":54,"upper":89.0000,"lower":88.0300,"count":1398,"preSum":26588},{"ndv":293,"upper":94.7000,"lower":89.0100,"count":1088,"preSum":27986},{"ndv":187,"upper":98.6500,"lower":94.7200,"count":1089,"preSum":29074},{"ndv":310,"upper":106.0000,"lower":98.6600,"count":1220,"preSum":30163},{"ndv":270,"upper":112.0000,"lower":106.0100,"count":1139,"preSum":31383},{"ndv":250,"upper":117.0000,"lower":112.0100,"count":1154,"preSum":32522},{"ndv":49,"upper":118.0000,"lower":117.0100,"count":1171,"preSum":33676},{"ndv":367,"upper":126.6200,"lower":118.0100,"count":1088,"preSum":34847},{"ndv":135,"upper":130.0000,"lower":126.6500,"count":1098,"preSum":35935},{"ndv":359,"upper":138.0000,"lower":130.0100,"count":1133,"preSum":37033},{"ndv":175,"upper":142.1800,"lower":138.0100,"count":1091,"preSum":38166},{"ndv":184,"upper":145.0000,"lower":142.1900,"count":1884,"preSum":39257},{"ndv":182,"upper":149.0000,"lower":145.0100,"count":1154,"preSum":41141},{"ndv":318,"upper":158.0000,"lower":149.0100,"count":1563,"preSum":42295},{"ndv":139,"upper":161.6200,"lower":158.0200,"count":1088,"preSum":43858},{"ndv":186,"upper":168.0000,"lower":161.6500,"count":1213,"preSum":44946},{"ndv":343,"upper":178.0000,"lower":168.0100,"count":1236,"preSum":46159},{"ndv":389,"upper":188.0000,"lower":178.0100,"count":1129,"preSum":47395},{"ndv":271,"upper":198.0000,"lower":188.0100,"count":1723,"preSum":48524},{"ndv":176,"upper":205.8300,"lower":198.0300,"count":1088,"preSum":50247},{"ndv":75,"upper":209.0000,"lower":205.8700,"count":1216,"preSum":51335},{"ndv":320,"upper":222.4800,"lower":209.1200,"count":1089,"preSum":52551},{"ndv":396,"upper":234.8000,"lower":222.5000,"count":1089,"preSum":53640},{"ndv":291,"upper":249.0000,"lower":234.8100,"count":1139,"preSum":54729},{"ndv":147,"upper":258.0000,"lower":249.0100,"count":1439,"preSum":55868},{"ndv":205,"upper":269.0000,"lower":258.0800,"count":1261,"preSum":57307},{"ndv":152,"upper":279.0000,"lower":269.0700,"count":1115,"preSum":58568},{"ndv":228,"upper":295.8000,"lower":279.0100,"count":1100,"preSum":59683},{"ndv":273,"upper":322.0000,"lower":295.8300,"count":1105,"preSum":60783},{"ndv":313,"upper":348.0000,"lower":322.0100,"count":1211,"preSum":61888},{"ndv":246,"upper":373.7400,"lower":348.3800,"count":1088,"preSum":63099},{"ndv":332,"upper":421.0000,"lower":373.8000,"count":1090,"preSum":64187},{"ndv":312,"upper":482.2000,"lower":421.0500,"count":1088,"preSum":65277},{"ndv":233,"upper":530.0000,"lower":482.7400,"count":1185,"preSum":66365},{"ndv":426,"upper":691.0000,"lower":530.5000,"count":1094,"preSum":67550},{"ndv":463,"upper":19845.0000,"lower":692.1800,"count":962,"preSum":68644}],"maxBucketSize":64,"type":"Double","sampleRate":0.9618625}','{"countArr":[6563,1403,2005,1374,1347,3148,2905,1301,1238,1327,2579,1384,1959,1862],"valueArr":[0.0000,68.7300,79.0000,85.0000,88.0000,99.0000,108.0000,128.0000,165.0000,170.0000,288.0000,289.0000,398.0000,540.0000],"type":"Double","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','companycode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[4350,270,95381],"valueArr":["JALA01","JALA02","JALA11"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','companytype',12,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"MC","lower":"MC","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1636,9,48],"valueArr":["","JD","QCS"],"type":"String","sampleRate":0.9618625319816094}',98307,0.02436278),('jala_wms_prod','shipment_header','componentscraprate',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','confirmedat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','consolidated',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','created',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','createdby',18,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"gth","lower":"gth","count":1,"preSum":0},{"ndv":1,"upper":"zjf","lower":"zjf","count":1,"preSum":1}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[7,42,3,99884,60,3],"valueArr":["LL","XCY1","YBJ","api","lhj","yj"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','deiverywindow',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','deletedimension',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[53,4],"valueArr":["","X"],"type":"String","sampleRate":0.9618625319816094}',99944,0.02436278),('jala_wms_prod','shipment_header','deliverynote',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','disabledcarriercodes',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','erpordercode',121379,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":177,"upper":"10000272846","lower":"0001622094","count":181,"preSum":0},{"ndv":181,"upper":"10000283492","lower":"10000272918","count":181,"preSum":181},{"ndv":179,"upper":"10000292278","lower":"10000283494","count":181,"preSum":362},{"ndv":179,"upper":"2082670","lower":"10000292280","count":181,"preSum":543},{"ndv":181,"upper":"23042164922064","lower":"2104218","count":181,"preSum":724},{"ndv":181,"upper":"23042358352745","lower":"23042165818874","count":181,"preSum":905},{"ndv":181,"upper":"23042566617374","lower":"23042358863635","count":181,"preSum":1086},{"ndv":181,"upper":"23042640068456","lower":"23042566927603","count":181,"preSum":1267},{"ndv":181,"upper":"23042815282947","lower":"23042641021319","count":181,"preSum":1448},{"ndv":181,"upper":"23043040586702","lower":"23042818243147","count":181,"preSum":1629},{"ndv":181,"upper":"23050266632572","lower":"23043042479818","count":181,"preSum":1810},{"ndv":181,"upper":"23050453002373","lower":"23050267004553","count":181,"preSum":1991},{"ndv":181,"upper":"23050646482143","lower":"23050453159873","count":181,"preSum":2172},{"ndv":181,"upper":"23050911745129","lower":"23050649439618","count":181,"preSum":2353},{"ndv":181,"upper":"23051054115935","lower":"23050911849379","count":181,"preSum":2534},{"ndv":181,"upper":"23051192462429","lower":"23051054133375","count":181,"preSum":2715},{"ndv":181,"upper":"23051330970846","lower":"23051197985839","count":181,"preSum":2896},{"ndv":181,"upper":"23051509628329","lower":"23051331443546","count":181,"preSum":3077},{"ndv":181,"upper":"23051690618154","lower":"23051510117653","count":181,"preSum":3258},{"ndv":181,"upper":"23051861738603","lower":"23051690749977","count":181,"preSum":3439},{"ndv":181,"upper":"23052018969076","lower":"23051861934403","count":181,"preSum":3620},{"ndv":181,"upper":"23052271106735","lower":"23052019236376","count":181,"preSum":3801},{"ndv":181,"upper":"23052479111946","lower":"23052271419654","count":181,"preSum":3982},{"ndv":181,"upper":"23052623868239","lower":"23052480362126","count":181,"preSum":4163},{"ndv":181,"upper":"23052839895812","lower":"23052624425029","count":181,"preSum":4344},{"ndv":181,"upper":"23053012462010","lower":"23052848414712","count":181,"preSum":4525},{"ndv":181,"upper":"23053161050965","lower":"23053013348549","count":181,"preSum":4706},{"ndv":181,"upper":"23060155844953","lower":"23053161744865","count":181,"preSum":4887},{"ndv":181,"upper":"23060290553066","lower":"23060160559012","count":181,"preSum":5068},{"ndv":181,"upper":"23060426941268","lower":"23060290583766","count":181,"preSum":5249},{"ndv":181,"upper":"23060666065143","lower":"23060426945668","count":181,"preSum":5430},{"ndv":181,"upper":"23060851822269","lower":"23060666380228","count":181,"preSum":5611},{"ndv":181,"upper":"23061022236627","lower":"23060852753369","count":181,"preSum":5792},{"ndv":181,"upper":"23061232978129","lower":"23061022973327","count":181,"preSum":5973},{"ndv":181,"upper":"23061374694064","lower":"23061233449784","count":181,"preSum":6154},{"ndv":181,"upper":"23061570333337","lower":"23061379981157","count":181,"preSum":6335},{"ndv":181,"upper":"23061702908313","lower":"23061570811202","count":181,"preSum":6516},{"ndv":181,"upper":"23061805079805","lower":"23061703134113","count":181,"preSum":6697},{"ndv":181,"upper":"23061890242485","lower":"23061806402260","count":181,"preSum":6878},{"ndv":181,"upper":"23062006197459","lower":"23061890381156","count":181,"preSum":7059},{"ndv":181,"upper":"23062314907906","lower":"23062008552459","count":181,"preSum":7240},{"ndv":181,"upper":"23062641456265","lower":"23062316757406","count":181,"preSum":7421},{"ndv":180,"upper":"40000198040","lower":"23062642898165","count":181,"preSum":7602},{"ndv":179,"upper":"40000208772","lower":"40000198047","count":181,"preSum":7783},{"ndv":181,"upper":"40000221006","lower":"40000208792","count":181,"preSum":7964},{"ndv":181,"upper":"40000231919","lower":"40000221014","count":181,"preSum":8145},{"ndv":181,"upper":"CK0001181748","lower":"40000231928","count":181,"preSum":8326},{"ndv":178,"upper":"CK0001209645","lower":"CK0001181750","count":181,"preSum":8507},{"ndv":180,"upper":"CK0001265472","lower":"CK0001209646","count":181,"preSum":8688},{"ndv":181,"upper":"CK0001303367","lower":"CK0001268729","count":181,"preSum":8869},{"ndv":181,"upper":"CK0001351565","lower":"CK0001303399","count":181,"preSum":9050},{"ndv":180,"upper":"CK0001398414","lower":"CK0001351576","count":181,"preSum":9231},{"ndv":181,"upper":"CK0001446898","lower":"CK0001398439","count":181,"preSum":9412},{"ndv":181,"upper":"CK0001466891","lower":"CK0001446908","count":181,"preSum":9593},{"ndv":181,"upper":"CK0001482734","lower":"CK0001466892","count":181,"preSum":9774},{"ndv":181,"upper":"CK0001492075","lower":"CK0001482751","count":181,"preSum":9955},{"ndv":180,"upper":"CK0001504667","lower":"CK0001492261","count":181,"preSum":10136},{"ndv":180,"upper":"CK0001521946","lower":"CK0001504670","count":181,"preSum":10317},{"ndv":181,"upper":"CK0001530290","lower":"CK0001521947","count":181,"preSum":10498},{"ndv":181,"upper":"CK0001543239","lower":"CK0001530339","count":181,"preSum":10679},{"ndv":181,"upper":"CK0001560203","lower":"CK0001543408","count":181,"preSum":10860},{"ndv":181,"upper":"CK0001575094","lower":"CK0001560209","count":181,"preSum":11041},{"ndv":181,"upper":"CKH00000009403","lower":"CK0001575096","count":181,"preSum":11222},{"ndv":126,"upper":"CKH00000015274","lower":"CKH00000009412","count":126,"preSum":11403}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[88363,3],"valueArr":["","1200009297"],"type":"String","sampleRate":0.9618625319816094}',106,0.02436278),('jala_wms_prod','shipment_header','erporderid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','erpordertype',16,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"MM011","lower":"MM011","count":1,"preSum":0},{"ndv":1,"upper":"MM021","lower":"MM021","count":2,"preSum":1}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[9,57,1282,118,95363,3052],"valueArr":["MM018","PP001","QM001","SDI17","deliveryorder","stockout"],"type":"String","sampleRate":0.9618625319816094}',117,0.02436278),('jala_wms_prod','shipment_header','finalshipment',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[39,18],"valueArr":["","X"],"type":"String","sampleRate":0.9618625319816094}',99944,0.02436278),('jala_wms_prod','shipment_header','fromwarehousecode',18,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"W005","lower":"W005","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[28,126,31,39,1199,27,4,3,46],"valueArr":["","D001","D002","D003","D011","W002","W007","W009","W028"],"type":"String","sampleRate":0.9618625319816094}',98497,0.02436278),('jala_wms_prod','shipment_header','groupindex',1557,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":14,"lower":14,"count":2804,"preSum":0},{"ndv":1,"upper":15,"lower":15,"count":2724,"preSum":2804},{"ndv":1,"upper":16,"lower":16,"count":2647,"preSum":5528},{"ndv":1,"upper":17,"lower":17,"count":2542,"preSum":8175},{"ndv":1,"upper":18,"lower":18,"count":2544,"preSum":10717},{"ndv":1,"upper":19,"lower":19,"count":2469,"preSum":13261},{"ndv":1,"upper":20,"lower":20,"count":2382,"preSum":15730},{"ndv":2,"upper":22,"lower":21,"count":1358,"preSum":18112},{"ndv":2,"upper":24,"lower":23,"count":1300,"preSum":19470},{"ndv":2,"upper":26,"lower":25,"count":1133,"preSum":20770},{"ndv":2,"upper":28,"lower":27,"count":1017,"preSum":21903},{"ndv":2,"upper":30,"lower":29,"count":912,"preSum":22920},{"ndv":2,"upper":32,"lower":31,"count":880,"preSum":23832},{"ndv":2,"upper":34,"lower":33,"count":865,"preSum":24712},{"ndv":2,"upper":36,"lower":35,"count":788,"preSum":25577},{"ndv":3,"upper":39,"lower":37,"count":1109,"preSum":26365},{"ndv":3,"upper":42,"lower":40,"count":1084,"preSum":27474},{"ndv":3,"upper":45,"lower":43,"count":1050,"preSum":28558},{"ndv":3,"upper":48,"lower":46,"count":962,"preSum":29608},{"ndv":3,"upper":51,"lower":49,"count":974,"preSum":30570},{"ndv":3,"upper":54,"lower":52,"count":889,"preSum":31544},{"ndv":3,"upper":57,"lower":55,"count":889,"preSum":32433},{"ndv":3,"upper":60,"lower":58,"count":876,"preSum":33322},{"ndv":3,"upper":63,"lower":61,"count":790,"preSum":34198},{"ndv":3,"upper":66,"lower":64,"count":774,"preSum":34988},{"ndv":3,"upper":69,"lower":67,"count":761,"preSum":35762},{"ndv":4,"upper":73,"lower":70,"count":1003,"preSum":36523},{"ndv":4,"upper":77,"lower":74,"count":938,"preSum":37526},{"ndv":4,"upper":81,"lower":78,"count":965,"preSum":38464},{"ndv":4,"upper":85,"lower":82,"count":926,"preSum":39429},{"ndv":4,"upper":89,"lower":86,"count":893,"preSum":40355},{"ndv":4,"upper":93,"lower":90,"count":852,"preSum":41248},{"ndv":4,"upper":97,"lower":94,"count":876,"preSum":42100},{"ndv":7,"upper":104,"lower":98,"count":790,"preSum":42976},{"ndv":16,"upper":120,"lower":105,"count":785,"preSum":43766},{"ndv":23,"upper":143,"lower":121,"count":765,"preSum":44551},{"ndv":38,"upper":181,"lower":144,"count":764,"preSum":45316},{"ndv":90,"upper":271,"lower":182,"count":759,"preSum":46080},{"ndv":153,"upper":426,"lower":272,"count":760,"preSum":46839},{"ndv":327,"upper":996,"lower":427,"count":712,"preSum":47599}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6479,6046,3757,3593,3564,3440,3233,3352,3221,3193,3068,2937,2911,2896],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','groupnum',252,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":14,"lower":14,"count":429,"preSum":0},{"ndv":1,"upper":15,"lower":15,"count":426,"preSum":429},{"ndv":1,"upper":16,"lower":16,"count":361,"preSum":855},{"ndv":1,"upper":17,"lower":17,"count":349,"preSum":1216},{"ndv":1,"upper":18,"lower":18,"count":339,"preSum":1565},{"ndv":1,"upper":19,"lower":19,"count":323,"preSum":1904},{"ndv":1,"upper":20,"lower":20,"count":337,"preSum":2227},{"ndv":1,"upper":21,"lower":21,"count":312,"preSum":2564},{"ndv":1,"upper":22,"lower":22,"count":346,"preSum":2876},{"ndv":1,"upper":23,"lower":23,"count":303,"preSum":3222},{"ndv":1,"upper":24,"lower":24,"count":294,"preSum":3525},{"ndv":1,"upper":25,"lower":25,"count":257,"preSum":3819},{"ndv":1,"upper":26,"lower":26,"count":266,"preSum":4076},{"ndv":1,"upper":27,"lower":27,"count":261,"preSum":4342},{"ndv":1,"upper":28,"lower":28,"count":230,"preSum":4603},{"ndv":1,"upper":29,"lower":29,"count":205,"preSum":4833},{"ndv":1,"upper":30,"lower":30,"count":206,"preSum":5038},{"ndv":1,"upper":31,"lower":31,"count":180,"preSum":5244},{"ndv":1,"upper":32,"lower":32,"count":193,"preSum":5424},{"ndv":1,"upper":33,"lower":33,"count":192,"preSum":5617},{"ndv":1,"upper":34,"lower":34,"count":205,"preSum":5809},{"ndv":1,"upper":35,"lower":35,"count":163,"preSum":6014},{"ndv":1,"upper":36,"lower":36,"count":159,"preSum":6177},{"ndv":1,"upper":37,"lower":37,"count":187,"preSum":6336},{"ndv":1,"upper":38,"lower":38,"count":175,"preSum":6523},{"ndv":2,"upper":40,"lower":39,"count":300,"preSum":6698},{"ndv":1,"upper":41,"lower":41,"count":154,"preSum":6998},{"ndv":2,"upper":43,"lower":42,"count":277,"preSum":7152},{"ndv":2,"upper":45,"lower":44,"count":243,"preSum":7429},{"ndv":2,"upper":47,"lower":46,"count":178,"preSum":7672},{"ndv":2,"upper":49,"lower":48,"count":154,"preSum":7850},{"ndv":2,"upper":51,"lower":50,"count":159,"preSum":8004},{"ndv":3,"upper":54,"lower":52,"count":199,"preSum":8163},{"ndv":3,"upper":57,"lower":55,"count":204,"preSum":8362},{"ndv":4,"upper":61,"lower":58,"count":193,"preSum":8566},{"ndv":4,"upper":65,"lower":62,"count":159,"preSum":8759},{"ndv":5,"upper":70,"lower":66,"count":156,"preSum":8918},{"ndv":6,"upper":76,"lower":71,"count":156,"preSum":9074},{"ndv":12,"upper":88,"lower":77,"count":155,"preSum":9230},{"ndv":21,"upper":109,"lower":89,"count":151,"preSum":9385},{"ndv":34,"upper":181,"lower":110,"count":58,"preSum":9536}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6479,61860,6524,4417,2938,2557,1089,924,781,668,633,537,526,474],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','hostcompanycode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2771,269,95375],"valueArr":["JALA01","JALA02","JALA11"],"type":"String","sampleRate":0.9618625319816094}',1586,0.02436278),('jala_wms_prod','shipment_header','hxqty',20,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":1,"lower":1,"count":1,"preSum":0},{"ndv":1,"upper":2,"lower":2,"count":1,"preSum":1}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[99999],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','id',4013259,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1563,"upper":2320037,"lower":1243547,"count":1563,"preSum":0},{"ndv":1563,"upper":2854825,"lower":2320039,"count":1563,"preSum":1563},{"ndv":1563,"upper":3018683,"lower":2854829,"count":1563,"preSum":3126},{"ndv":1563,"upper":3267347,"lower":3018686,"count":1563,"preSum":4689},{"ndv":1563,"upper":3570762,"lower":3267352,"count":1563,"preSum":6252},{"ndv":1563,"upper":3725443,"lower":3570764,"count":1563,"preSum":7815},{"ndv":1563,"upper":3840245,"lower":3731625,"count":1563,"preSum":9378},{"ndv":1563,"upper":3933386,"lower":3840248,"count":1563,"preSum":10941},{"ndv":1563,"upper":4032802,"lower":3933387,"count":1563,"preSum":12504},{"ndv":1563,"upper":4127019,"lower":4032807,"count":1563,"preSum":14067},{"ndv":1563,"upper":4208308,"lower":4127023,"count":1563,"preSum":15630},{"ndv":1563,"upper":4294785,"lower":4208311,"count":1563,"preSum":17193},{"ndv":1563,"upper":4478565,"lower":4294787,"count":1563,"preSum":18756},{"ndv":1563,"upper":4543626,"lower":4478567,"count":1563,"preSum":20319},{"ndv":1563,"upper":4616053,"lower":4543639,"count":1563,"preSum":21882},{"ndv":1563,"upper":4682676,"lower":4616055,"count":1563,"preSum":23445},{"ndv":1563,"upper":4772414,"lower":4682682,"count":1563,"preSum":25008},{"ndv":1563,"upper":4897135,"lower":4772431,"count":1563,"preSum":26571},{"ndv":1563,"upper":4996102,"lower":4897137,"count":1563,"preSum":28134},{"ndv":1563,"upper":5079992,"lower":4996106,"count":1563,"preSum":29697},{"ndv":1563,"upper":5154802,"lower":5080026,"count":1563,"preSum":31260},{"ndv":1563,"upper":5237738,"lower":5154803,"count":1563,"preSum":32823},{"ndv":1563,"upper":5320607,"lower":5237750,"count":1563,"preSum":34386},{"ndv":1563,"upper":5409469,"lower":5320620,"count":1563,"preSum":35949},{"ndv":1563,"upper":5478824,"lower":5409472,"count":1563,"preSum":37512},{"ndv":1563,"upper":5558259,"lower":5478828,"count":1563,"preSum":39075},{"ndv":1563,"upper":5655872,"lower":5558346,"count":1563,"preSum":40638},{"ndv":1563,"upper":5741191,"lower":5655875,"count":1563,"preSum":42201},{"ndv":1563,"upper":5824365,"lower":5741192,"count":1563,"preSum":43764},{"ndv":1563,"upper":5912718,"lower":5824391,"count":1563,"preSum":45327},{"ndv":1563,"upper":5996901,"lower":5912724,"count":1563,"preSum":46890},{"ndv":1563,"upper":6063189,"lower":5996908,"count":1563,"preSum":48453},{"ndv":1563,"upper":6138100,"lower":6063193,"count":1563,"preSum":50016},{"ndv":1563,"upper":6197258,"lower":6138139,"count":1563,"preSum":51579},{"ndv":1563,"upper":6265766,"lower":6197259,"count":1563,"preSum":53142},{"ndv":1563,"upper":6332967,"lower":6265777,"count":1563,"preSum":54705},{"ndv":1563,"upper":6406748,"lower":6332970,"count":1563,"preSum":56268},{"ndv":1563,"upper":6481181,"lower":6406822,"count":1563,"preSum":57831},{"ndv":1563,"upper":6559013,"lower":6481199,"count":1563,"preSum":59394},{"ndv":1563,"upper":6635519,"lower":6559016,"count":1563,"preSum":60957},{"ndv":1563,"upper":6709433,"lower":6635532,"count":1563,"preSum":62520},{"ndv":1563,"upper":6790495,"lower":6709437,"count":1563,"preSum":64083},{"ndv":1563,"upper":6863630,"lower":6790497,"count":1563,"preSum":65646},{"ndv":1563,"upper":6944790,"lower":6863638,"count":1563,"preSum":67209},{"ndv":1563,"upper":7024344,"lower":6944793,"count":1563,"preSum":68772},{"ndv":1563,"upper":7091282,"lower":7024356,"count":1563,"preSum":70335},{"ndv":1563,"upper":7171908,"lower":7091284,"count":1563,"preSum":71898},{"ndv":1563,"upper":7264317,"lower":7171920,"count":1563,"preSum":73461},{"ndv":1563,"upper":7341643,"lower":7264355,"count":1563,"preSum":75024},{"ndv":1563,"upper":7422568,"lower":7341644,"count":1563,"preSum":76587},{"ndv":1563,"upper":7504425,"lower":7422576,"count":1563,"preSum":78150},{"ndv":1563,"upper":7587833,"lower":7504429,"count":1563,"preSum":79713},{"ndv":1563,"upper":7664924,"lower":7587845,"count":1563,"preSum":81276},{"ndv":1563,"upper":7735933,"lower":7664938,"count":1563,"preSum":82839},{"ndv":1563,"upper":7815122,"lower":7735976,"count":1563,"preSum":84402},{"ndv":1563,"upper":7889073,"lower":7815124,"count":1563,"preSum":85965},{"ndv":1563,"upper":7969114,"lower":7889076,"count":1563,"preSum":87528},{"ndv":1563,"upper":8033738,"lower":7969118,"count":1563,"preSum":89091},{"ndv":1563,"upper":8109820,"lower":8033766,"count":1563,"preSum":90654},{"ndv":1563,"upper":8180750,"lower":8109821,"count":1563,"preSum":92217},{"ndv":1563,"upper":8260166,"lower":8180792,"count":1563,"preSum":93780},{"ndv":1563,"upper":8354855,"lower":8260170,"count":1563,"preSum":95343},{"ndv":1563,"upper":8431067,"lower":8354863,"count":1563,"preSum":96906},{"ndv":1532,"upper":8531756,"lower":8431206,"count":1532,"preSum":98469}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}',null,0,0.02436278),('jala_wms_prod','shipment_header','insurerequired',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','invoicecontent',11797,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=06D532496252","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=008032557584","count":18,"preSum":0},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=0iuw32506176","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=078n32688115","count":18,"preSum":18},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=11A932564637","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=0J7O32625717","count":18,"preSum":36},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=172532522036","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=12Pn32548699","count":18,"preSum":54},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=1G0732678714","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=178V32566640","count":18,"preSum":72},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=1Ub732598604","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=1G1p32673567","count":18,"preSum":90},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=236332367326","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=1Ul032637067","count":18,"preSum":108},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=29s432510267","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=23Pq32481723","count":18,"preSum":126},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=2m0d32521103","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=2agz32499602","count":18,"preSum":144},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=32g332653704","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=2Nf932551579","count":18,"preSum":162},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=396532584579","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=32Y532551711","count":18,"preSum":180},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=3G7R32637308","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=398732629375","count":18,"preSum":198},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=401432608420","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=3HwT32672052","count":18,"preSum":216},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=45L632631572","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=40o632637126","count":18,"preSum":234},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=4c1232496880","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=462f32627167","count":18,"preSum":252},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=4yP232523331","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=4d7C32552734","count":18,"preSum":270},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=56vx32679410","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=4zkT32672521","count":18,"preSum":288},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=5E3632541499","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=572232582187","count":18,"preSum":306},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=5Y2z32508052","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=5E8G32506189","count":18,"preSum":324},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=683t32520613","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=5yb732427445","count":18,"preSum":342},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=6g9032497272","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=68U832608168","count":18,"preSum":360},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=6zh932562973","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=6Gq232614929","count":18,"preSum":378},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=784X32680395","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=70ko32630090","count":18,"preSum":396},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=7H1b32494097","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=787032672244","count":18,"preSum":414},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=7Y6132561532","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=7I0832683621","count":18,"preSum":432},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=871y32506119","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=7Yee32643036","count":18,"preSum":450},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=8EB332564366","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=876632563898","count":18,"preSum":468},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=907f32542757","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=8ER232626905","count":18,"preSum":486},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=949432534730","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=90Gm32637164","count":18,"preSum":504},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=9EkL32582446","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=94B532644121","count":18,"preSum":522},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=9Z2632502300","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=9EvO32538207","count":18,"preSum":540},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=AbxV32645782","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=9z3G32677051","count":18,"preSum":558},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=B3b532552013","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=Ac1932545250","count":18,"preSum":576},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Bt8n32590024","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=b3jm32564776","count":18,"preSum":594},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=cuS232535551","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=BV5832545301","count":18,"preSum":612},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=da8432669307","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=CW3l32686982","count":18,"preSum":630},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=E87d32603593","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=DC1a32580008","count":18,"preSum":648},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=eR2632534712","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=e8c532525939","count":18,"preSum":666},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=G0R032492470","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=ESeu32505570","count":18,"preSum":684},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=gIcY32541416","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=g10232382077","count":18,"preSum":702},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=H7ej32501364","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=Gm3w32642175","count":18,"preSum":720},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=i40932608153","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=hBA932582261","count":18,"preSum":738},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=j49032682225","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=i42832568721","count":18,"preSum":756},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=k27S32678095","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=j52032557585","count":18,"preSum":774},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=L0CM32659807","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=k33432680023","count":18,"preSum":792},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=m11Q32662388","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=l18g32501359","count":18,"preSum":810},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Mrme32417406","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=M20b32567132","count":18,"preSum":828},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=nj7X32565954","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=msug32535828","count":18,"preSum":846},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Odr132537530","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=nLoX32637179","count":18,"preSum":864},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=P9ea32680345","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=oDU832620560","count":18,"preSum":882},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Q53432624640","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=pAy732661853","count":18,"preSum":900},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=QWt132678212","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=q54L32580120","count":18,"preSum":918},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=rw7H32673474","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=qZ1H32634442","count":18,"preSum":936},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Sn7f32506191","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=RX7932501012","count":18,"preSum":954},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=tg6a32607288","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=spuX32642858","count":18,"preSum":972},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=UN4932550386","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=tH4132613460","count":18,"preSum":990},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=VIRy32540409","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=Uqp132578223","count":18,"preSum":1008},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=W8QY32559316","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=VK3532563862","count":18,"preSum":1026},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=X67232603590","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=wB1u32685036","count":18,"preSum":1044},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Y1c032574150","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=X67832684049","count":18,"preSum":1062},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Z01y32438604","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=y4s432579457","count":18,"preSum":1080},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=ZunD32497786","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=z06P32541614","count":18,"preSum":1098},{"ndv":1,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=zZK732649202","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=zZK732649202","count":1,"preSum":1116}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',98854,0.02436278),('jala_wms_prod','shipment_header','invoiceheader',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','invoicerequired',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','invoicetype',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','itemcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','lastupdated',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','lastupdatedby',121,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":"1000003","lower":"02700010","count":6,"preSum":0},{"ndv":1,"upper":"1000004","lower":"1000004","count":4,"preSum":6},{"ndv":2,"upper":"chendaolong","lower":"bry","count":16,"preSum":10},{"ndv":2,"upper":"CSS","lower":"CN","count":8,"preSum":26},{"ndv":2,"upper":"DH","lower":"CXN","count":4,"preSum":34},{"ndv":1,"upper":"gth","lower":"gth","count":13,"preSum":38},{"ndv":3,"upper":"LL","lower":"jiyinghao","count":12,"preSum":51},{"ndv":1,"upper":"LML","lower":"LML","count":16,"preSum":63},{"ndv":1,"upper":"lxp","lower":"lxp","count":11,"preSum":79},{"ndv":2,"upper":"lyg","lower":"LY","count":6,"preSum":90},{"ndv":1,"upper":"LYM","lower":"LYM","count":6,"preSum":96},{"ndv":1,"upper":"MLP","lower":"MLP","count":23,"preSum":102},{"ndv":4,"upper":"sfzhaohuqi","lower":"PZ","count":4,"preSum":125},{"ndv":1,"upper":"SHB","lower":"SHB","count":9,"preSum":129},{"ndv":1,"upper":"suchenbo","lower":"suchenbo","count":8,"preSum":138},{"ndv":1,"upper":"sunyingying","lower":"sunyingying","count":7,"preSum":146},{"ndv":2,"upper":"wangyong","lower":"sw","count":4,"preSum":153},{"ndv":1,"upper":"WQ","lower":"WQ","count":25,"preSum":157},{"ndv":1,"upper":"XCY","lower":"XCY","count":5,"preSum":182},{"ndv":1,"upper":"YBJ","lower":"YBJ","count":4,"preSum":187},{"ndv":1,"upper":"yj","lower":"yj","count":5,"preSum":191},{"ndv":2,"upper":"ZH","lower":"yxy","count":4,"preSum":196},{"ndv":2,"upper":"zjf","lower":"zhangkeming","count":8,"preSum":200}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[193,35,35,186,69,43,151,66,98770,63,60,34,53,35],"valueArr":["BMJ","HP","JQQ","LSH","WK","XCY1","YJR","ZLF","api","gzj","lhj","liyinghao","shenmengliang","zhangguishun"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','lastwaveid',35103,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":161,"upper":554473,"lower":667,"count":247,"preSum":0},{"ndv":126,"upper":686871,"lower":554474,"count":247,"preSum":247},{"ndv":125,"upper":741796,"lower":686872,"count":243,"preSum":494},{"ndv":128,"upper":749124,"lower":741799,"count":247,"preSum":737},{"ndv":63,"upper":752552,"lower":749144,"count":254,"preSum":984},{"ndv":82,"upper":766996,"lower":752556,"count":243,"preSum":1238},{"ndv":101,"upper":774106,"lower":767001,"count":248,"preSum":1481},{"ndv":99,"upper":787652,"lower":774160,"count":244,"preSum":1729},{"ndv":85,"upper":790848,"lower":787653,"count":244,"preSum":1973},{"ndv":93,"upper":796852,"lower":790915,"count":243,"preSum":2217},{"ndv":130,"upper":807509,"lower":797410,"count":243,"preSum":2460},{"ndv":110,"upper":818455,"lower":807510,"count":243,"preSum":2703},{"ndv":40,"upper":819811,"lower":818456,"count":243,"preSum":2946},{"ndv":72,"upper":820731,"lower":819870,"count":250,"preSum":3189},{"ndv":62,"upper":822121,"lower":820732,"count":246,"preSum":3439},{"ndv":80,"upper":826571,"lower":822123,"count":243,"preSum":3685},{"ndv":118,"upper":840339,"lower":826572,"count":246,"preSum":3928},{"ndv":58,"upper":848957,"lower":840340,"count":243,"preSum":4174},{"ndv":97,"upper":871276,"lower":850177,"count":249,"preSum":4417},{"ndv":79,"upper":878982,"lower":871277,"count":253,"preSum":4666},{"ndv":88,"upper":888439,"lower":878983,"count":244,"preSum":4919},{"ndv":102,"upper":906774,"lower":888441,"count":257,"preSum":5163},{"ndv":104,"upper":923645,"lower":906777,"count":243,"preSum":5420},{"ndv":116,"upper":935051,"lower":923646,"count":249,"preSum":5663},{"ndv":125,"upper":950615,"lower":935052,"count":246,"preSum":5912},{"ndv":90,"upper":962950,"lower":950724,"count":245,"preSum":6158},{"ndv":84,"upper":974544,"lower":963647,"count":244,"preSum":6403},{"ndv":135,"upper":995726,"lower":974560,"count":249,"preSum":6647},{"ndv":79,"upper":1006315,"lower":995855,"count":253,"preSum":6896},{"ndv":92,"upper":1015708,"lower":1006318,"count":243,"preSum":7149},{"ndv":117,"upper":1021777,"lower":1015709,"count":243,"preSum":7392},{"ndv":91,"upper":1028243,"lower":1021778,"count":243,"preSum":7635},{"ndv":103,"upper":1031884,"lower":1028245,"count":243,"preSum":7878},{"ndv":100,"upper":1037011,"lower":1031888,"count":244,"preSum":8121},{"ndv":79,"upper":1038215,"lower":1037067,"count":244,"preSum":8365},{"ndv":71,"upper":1041397,"lower":1038216,"count":245,"preSum":8609},{"ndv":82,"upper":1042905,"lower":1041409,"count":247,"preSum":8854},{"ndv":30,"upper":1043017,"lower":1042907,"count":243,"preSum":9101},{"ndv":111,"upper":1045090,"lower":1043071,"count":244,"preSum":9344},{"ndv":83,"upper":1047617,"lower":1045091,"count":245,"preSum":9588},{"ndv":38,"upper":1048906,"lower":1047620,"count":245,"preSum":9833},{"ndv":96,"upper":1051513,"lower":1048909,"count":244,"preSum":10078},{"ndv":109,"upper":1053072,"lower":1051514,"count":244,"preSum":10322},{"ndv":105,"upper":1057713,"lower":1053073,"count":243,"preSum":10566},{"ndv":149,"upper":1070475,"lower":1057719,"count":247,"preSum":10809},{"ndv":85,"upper":1074655,"lower":1070527,"count":243,"preSum":11056},{"ndv":120,"upper":1095472,"lower":1074662,"count":252,"preSum":11299},{"ndv":68,"upper":1106461,"lower":1095483,"count":244,"preSum":11551},{"ndv":111,"upper":1127309,"lower":1106465,"count":254,"preSum":11795},{"ndv":93,"upper":1145273,"lower":1127310,"count":244,"preSum":12049},{"ndv":117,"upper":1162150,"lower":1145275,"count":247,"preSum":12293},{"ndv":114,"upper":1176544,"lower":1162151,"count":243,"preSum":12540},{"ndv":114,"upper":1186044,"lower":1176546,"count":243,"preSum":12783},{"ndv":120,"upper":1189281,"lower":1186045,"count":245,"preSum":13026},{"ndv":123,"upper":1194516,"lower":1189283,"count":250,"preSum":13271},{"ndv":86,"upper":1197990,"lower":1194517,"count":255,"preSum":13521},{"ndv":108,"upper":1203024,"lower":1198031,"count":249,"preSum":13776},{"ndv":109,"upper":1207404,"lower":1203025,"count":253,"preSum":14025},{"ndv":109,"upper":1212918,"lower":1207405,"count":243,"preSum":14278},{"ndv":58,"upper":1213472,"lower":1212919,"count":243,"preSum":14521},{"ndv":126,"upper":1225047,"lower":1213474,"count":245,"preSum":14764},{"ndv":117,"upper":1256327,"lower":1225049,"count":243,"preSum":15009},{"ndv":140,"upper":1303778,"lower":1256590,"count":238,"preSum":15252}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[84092,58,38,33,32,30,45,32,70,50,31],"valueArr":[0,767240,767251,818705,898400,961794,1041136,1047764,1060758,1186390,1205889],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','leadingsts',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":400,"lower":400,"count":2,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6391,5,28,93575],"valueArr":[100,300,600,900],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','loadid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','lockcode',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[8,71,639,14],"valueArr":["","MSG_WBLL_0005","MSG_WBLL_0010","等待获取电子面单号"],"type":"String","sampleRate":0.9618625319816094}',99269,0.02436278),('jala_wms_prod','shipment_header','logisticsservices',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','manufacturer',18,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"2000","lower":"2000","count":1,"preSum":0},{"ndv":1,"upper":"2030","lower":"2030","count":1,"preSum":1}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1355,3],"valueArr":["1000","1050"],"type":"String","sampleRate":0.9618625319816094}',98641,0.02436278),('jala_wms_prod','shipment_header','materialdocumentyear',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','neworderdate',165,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":29,"upper":"1850821117174874112","lower":"1850708966988840960","count":1040,"preSum":0},{"ndv":8,"upper":"1850847505453940736","lower":"1850823316198129664","count":1163,"preSum":1040},{"ndv":5,"upper":"1850858500570218496","lower":"1850849704477196288","count":993,"preSum":2203},{"ndv":10,"upper":"1850880490802774016","lower":"1850860699593474048","count":979,"preSum":3196},{"ndv":13,"upper":"1850911277128351744","lower":"1850882689826029568","count":1016,"preSum":4175},{"ndv":10,"upper":"1850933267360907264","lower":"1850913476151607296","count":1134,"preSum":5191},{"ndv":5,"upper":"1850944262477185024","lower":"1850935466384162816","count":1064,"preSum":6325},{"ndv":3,"upper":"1850950859546951680","lower":"1850946461500440576","count":1021,"preSum":7389},{"ndv":2,"upper":"1850955257593462784","lower":"1850953058570207232","count":1413,"preSum":8410},{"ndv":2,"upper":"1850959655639973888","lower":"1850957456616718336","count":1367,"preSum":9823},{"ndv":2,"upper":"1850964053686484992","lower":"1850961854663229440","count":1897,"preSum":11190},{"ndv":2,"upper":"1850968451732996096","lower":"1850966252709740544","count":1722,"preSum":13087},{"ndv":1,"upper":"1850970650756251648","lower":"1850970650756251648","count":1473,"preSum":14809},{"ndv":2,"upper":"1850975048802762752","lower":"1850972849779507200","count":1307,"preSum":16282},{"ndv":1,"upper":"1850981645872529408","lower":"1850981645872529408","count":1159,"preSum":17589},{"ndv":1,"upper":"1850983844895784960","lower":"1850983844895784960","count":1399,"preSum":18748},{"ndv":1,"upper":"1850988242942296064","lower":"1850988242942296064","count":1203,"preSum":20147},{"ndv":2,"upper":"1850992640988807168","lower":"1850990441965551616","count":1799,"preSum":21350},{"ndv":2,"upper":"1850997039035318272","lower":"1850994840012062720","count":1649,"preSum":23149},{"ndv":1,"upper":"1850999238058573824","lower":"1850999238058573824","count":1008,"preSum":24798},{"ndv":1,"upper":"1851001437081829376","lower":"1851001437081829376","count":1210,"preSum":25806},{"ndv":1,"upper":"1851003636105084928","lower":"1851003636105084928","count":1093,"preSum":27016},{"ndv":1,"upper":"1851005835128340480","lower":"1851005835128340480","count":1033,"preSum":28109},{"ndv":2,"upper":"1851010233174851584","lower":"1851008034151596032","count":1986,"preSum":29142},{"ndv":2,"upper":"1851014631221362688","lower":"1851012432198107136","count":1885,"preSum":31128},{"ndv":1,"upper":"1851019029267873792","lower":"1851019029267873792","count":1048,"preSum":33013},{"ndv":2,"upper":"1851023427314384896","lower":"1851021228291129344","count":1804,"preSum":34061},{"ndv":2,"upper":"1851027825360896000","lower":"1851025626337640448","count":1813,"preSum":35865},{"ndv":2,"upper":"1851032223407407104","lower":"1851030024384151552","count":1835,"preSum":37678},{"ndv":2,"upper":"1851036621453918208","lower":"1851034422430662656","count":1526,"preSum":39513},{"ndv":1,"upper":"1851043218523684864","lower":"1851043218523684864","count":1412,"preSum":41039},{"ndv":1,"upper":"1851045417546940416","lower":"1851045417546940416","count":1408,"preSum":42451},{"ndv":1,"upper":"1851058611686473728","lower":"1851058611686473728","count":1519,"preSum":43859},{"ndv":1,"upper":"1851060810709729280","lower":"1851060810709729280","count":1306,"preSum":45378},{"ndv":1,"upper":"1851063009732984832","lower":"1851063009732984832","count":1354,"preSum":46684},{"ndv":1,"upper":"1851065208756240384","lower":"1851065208756240384","count":967,"preSum":48038},{"ndv":2,"upper":"1851069606802751488","lower":"1851067407779495936","count":1773,"preSum":49005},{"ndv":2,"upper":"1851074004849262592","lower":"1851071805826007040","count":1846,"preSum":50778},{"ndv":1,"upper":"1851076203872518144","lower":"1851076203872518144","count":977,"preSum":52624},{"ndv":1,"upper":"1851078402895773696","lower":"1851078402895773696","count":1223,"preSum":53601},{"ndv":2,"upper":"1851093796058562560","lower":"1851080601919029248","count":2081,"preSum":54824},{"ndv":2,"upper":"1851098194105073664","lower":"1851095995081818112","count":1189,"preSum":56905},{"ndv":2,"upper":"1851102592151584768","lower":"1851100393128329216","count":984,"preSum":58094},{"ndv":2,"upper":"1851106990198095872","lower":"1851104791174840320","count":1172,"preSum":59078},{"ndv":2,"upper":"1851111388244606976","lower":"1851109189221351424","count":1090,"preSum":60250},{"ndv":1,"upper":"1851113587267862528","lower":"1851113587267862528","count":135,"preSum":61340}],"maxBucketSize":64,"type":"Date","sampleRate":0.9618625}','{"countArr":[1558,3128,1888,7101,2249,3414,2507,1924,1705,2085,2718,2422,3700,2127],"valueArr":[-1,1850986043919040512,1851016830244618240,1851038820477173760,1851041019500429312,1851047616570195968,1851052014616707072,1851054213639962624,1851056412663218176,1851082800942284800,1851084999965540352,1851087198988795904,1851089398012051456,1851091597035307008],"type":"Date","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','orderdate',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','originalorderid',249,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":1264825,"lower":1264825,"count":1,"preSum":0},{"ndv":1,"upper":1273722,"lower":1273722,"count":1,"preSum":1},{"ndv":1,"upper":1273743,"lower":1273743,"count":1,"preSum":2},{"ndv":1,"upper":1273747,"lower":1273747,"count":2,"preSum":3},{"ndv":1,"upper":1336188,"lower":1336188,"count":1,"preSum":5},{"ndv":1,"upper":1337189,"lower":1337189,"count":1,"preSum":6},{"ndv":1,"upper":1346415,"lower":1346415,"count":1,"preSum":7},{"ndv":1,"upper":1347128,"lower":1347128,"count":1,"preSum":8},{"ndv":1,"upper":1347131,"lower":1347131,"count":1,"preSum":9},{"ndv":1,"upper":1398851,"lower":1398851,"count":1,"preSum":10},{"ndv":1,"upper":1492889,"lower":1492889,"count":1,"preSum":11},{"ndv":1,"upper":2604100,"lower":2604100,"count":1,"preSum":12},{"ndv":1,"upper":2646282,"lower":2646282,"count":1,"preSum":13},{"ndv":1,"upper":2700631,"lower":2700631,"count":1,"preSum":14},{"ndv":1,"upper":2722610,"lower":2722610,"count":1,"preSum":15},{"ndv":1,"upper":3121239,"lower":3121239,"count":1,"preSum":16},{"ndv":1,"upper":3302048,"lower":3302048,"count":1,"preSum":17},{"ndv":1,"upper":4152939,"lower":4152939,"count":1,"preSum":18},{"ndv":1,"upper":4176632,"lower":4176632,"count":1,"preSum":19},{"ndv":1,"upper":4229092,"lower":4229092,"count":1,"preSum":20},{"ndv":1,"upper":4229420,"lower":4229420,"count":1,"preSum":21},{"ndv":1,"upper":4960907,"lower":4960907,"count":2,"preSum":22},{"ndv":1,"upper":4971652,"lower":4971652,"count":1,"preSum":24},{"ndv":1,"upper":5175078,"lower":5175078,"count":2,"preSum":25},{"ndv":1,"upper":5488127,"lower":5488127,"count":1,"preSum":27},{"ndv":1,"upper":5737664,"lower":5737664,"count":1,"preSum":28},{"ndv":1,"upper":5798389,"lower":5798389,"count":1,"preSum":29}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[99971],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','packagecentercode',1624,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":5,"upper":"三水","lower":"三亚","count":6,"preSum":0},{"ndv":4,"upper":"中山转","lower":"上饶转","count":6,"preSum":6},{"ndv":3,"upper":"义乌转","lower":"中山转台山","count":6,"preSum":12},{"ndv":5,"upper":"侯马转新绛","lower":"乌市转奎屯","count":6,"preSum":18},{"ndv":5,"upper":"兰州","lower":"信阳转固始","count":8,"preSum":24},{"ndv":2,"upper":"北京","lower":"兰州转","count":7,"preSum":32},{"ndv":4,"upper":"南京雨花区","lower":"北京郊","count":6,"preSum":39},{"ndv":3,"upper":"南充转邻水","lower":"南充转","count":7,"preSum":45},{"ndv":4,"upper":"南昌转南城","lower":"南宁转","count":6,"preSum":52},{"ndv":4,"upper":"南通","lower":"南昌转南昌县","count":6,"preSum":58},{"ndv":5,"upper":"合肥","lower":"南通转海安","count":10,"preSum":64},{"ndv":6,"upper":"吉安转崇义","lower":"合肥转含山","count":6,"preSum":74},{"ndv":4,"upper":"唐山转","lower":"呼市","count":6,"preSum":80},{"ndv":3,"upper":"大同转","lower":"嘉兴转","count":6,"preSum":86},{"ndv":5,"upper":"太原转五台","lower":"大庆","count":6,"preSum":92},{"ndv":4,"upper":"宁波","lower":"太原转交城","count":6,"preSum":98},{"ndv":3,"upper":"安阳","lower":"宁波转","count":6,"preSum":104},{"ndv":4,"upper":"巴南转","lower":"宝鸡","count":8,"preSum":110},{"ndv":5,"upper":"平凉","lower":"常州转","count":6,"preSum":118},{"ndv":5,"upper":"徐州","lower":"广州转四会","count":6,"preSum":124},{"ndv":4,"upper":"惠州转","lower":"徐州转丰县","count":8,"preSum":130},{"ndv":4,"upper":"成都转","lower":"惠州转惠东","count":6,"preSum":138},{"ndv":6,"upper":"新乡转","lower":"成都转大邑","count":8,"preSum":144},{"ndv":6,"upper":"昆常","lower":"新乡转台前","count":8,"preSum":152},{"ndv":4,"upper":"昆明转广南","lower":"昆常转","count":6,"preSum":160},{"ndv":4,"upper":"晋城转","lower":"昆明转梁河","count":6,"preSum":166},{"ndv":3,"upper":"株洲","lower":"杭州","count":6,"preSum":172},{"ndv":3,"upper":"武汉","lower":"桂林","count":6,"preSum":178},{"ndv":2,"upper":"武汉转仙桃","lower":"武汉转","count":6,"preSum":184},{"ndv":4,"upper":"江宁","lower":"武汉转天门","count":6,"preSum":190},{"ndv":3,"upper":"沪东","lower":"沈阳转","count":6,"preSum":196},{"ndv":5,"upper":"洛阳转","lower":"泉州石狮","count":7,"preSum":202},{"ndv":5,"upper":"济宁转鱼台","lower":"济南转","count":6,"preSum":209},{"ndv":5,"upper":"淮安转","lower":"浦东孙桥","count":6,"preSum":215},{"ndv":4,"upper":"深圳转","lower":"淮安转灌南","count":7,"preSum":221},{"ndv":5,"upper":"滕州","lower":"温州转","count":6,"preSum":228},{"ndv":6,"upper":"漯河转项城","lower":"漯河","count":6,"preSum":234},{"ndv":3,"upper":"潮汕转","lower":"潍坊转","count":7,"preSum":240},{"ndv":3,"upper":"益阳","lower":"潮汕转五华","count":6,"preSum":247},{"ndv":4,"upper":"石市","lower":"盐城","count":6,"preSum":253},{"ndv":4,"upper":"福州","lower":"石市新河","count":6,"preSum":259},{"ndv":3,"upper":"自贡转","lower":"福州转霞浦","count":7,"preSum":265},{"ndv":4,"upper":"芜湖转","lower":"自贡转屏山","count":6,"preSum":272},{"ndv":6,"upper":"萧山转","lower":"苍南","count":6,"preSum":278},{"ndv":6,"upper":"衡阳转","lower":"萧山转临安","count":8,"preSum":284},{"ndv":5,"upper":"西宁转","lower":"衡阳转临武","count":6,"preSum":292},{"ndv":2,"upper":"西安蓝田","lower":"西安","count":6,"preSum":298},{"ndv":2,"upper":"西安转合阳","lower":"西安转","count":6,"preSum":304},{"ndv":5,"upper":"贵阳转","lower":"西安转大荔","count":6,"preSum":310},{"ndv":3,"upper":"贵阳转龙里","lower":"贵阳转凯里","count":6,"preSum":316},{"ndv":4,"upper":"邢邯转","lower":"赤峰巴林右旗","count":7,"preSum":322},{"ndv":6,"upper":"郴州","lower":"邢邯转涉县","count":6,"preSum":329},{"ndv":3,"upper":"重庆垫江","lower":"鄂州转阳新","count":6,"preSum":335},{"ndv":3,"upper":"银川转","lower":"重庆大坪","count":7,"preSum":341},{"ndv":4,"upper":"长沙转","lower":"银川转鄂托克旗","count":10,"preSum":348},{"ndv":3,"upper":"长沙郊浏阳","lower":"长沙转长沙","count":6,"preSum":358},{"ndv":3,"upper":"驻马店","lower":"青岛转","count":7,"preSum":364}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[27,10,159,10,7,7,9,7,7,16,7,10,7001],"valueArr":["","东莞","义乌","京南","佛山","包头转","天津转","广州转","沈阳","沪西","郑州转","鄂州转","顺丰速运"],"type":"String","sampleRate":0.9618625319816094}',92353,0.02436278),('jala_wms_prod','shipment_header','packagecentername',4751,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":22,"upper":"三明转明溪","lower":"","count":62,"preSum":0},{"ndv":17,"upper":"临沂转","lower":"三明转永安","count":65,"preSum":62},{"ndv":18,"upper":"乌市转","lower":"临沂转临沭","count":63,"preSum":127},{"ndv":30,"upper":"乐清","lower":"乌市转乌苏","count":65,"preSum":190},{"ndv":23,"upper":"京南转高碑店","lower":"九江","count":64,"preSum":255},{"ndv":27,"upper":"信阳转固始","lower":"京南郊","count":63,"preSum":319},{"ndv":11,"upper":"兰州永登","lower":"信阳转息县","count":63,"preSum":382},{"ndv":10,"upper":"北京","lower":"兰州转","count":77,"preSum":445},{"ndv":10,"upper":"南京转天长","lower":"北京小红门","count":63,"preSum":522},{"ndv":20,"upper":"南宁转","lower":"南京转溪县","count":87,"preSum":585},{"ndv":31,"upper":"南昌转高安","lower":"南宁转上林","count":62,"preSum":672},{"ndv":17,"upper":"厦门转","lower":"南昌进贤县","count":73,"preSum":734},{"ndv":14,"upper":"合肥转庐江","lower":"厦门转上杭","count":62,"preSum":807},{"ndv":24,"upper":"吉林","lower":"合肥转肥东","count":62,"preSum":869},{"ndv":16,"upper":"哈市","lower":"吉林永吉","count":75,"preSum":931},{"ndv":22,"upper":"唐山转青龙","lower":"哈市转","count":63,"preSum":1006},{"ndv":12,"upper":"大连开发区","lower":"商丘","count":67,"preSum":1069},{"ndv":21,"upper":"太原","lower":"大连瓦房店","count":63,"preSum":1136},{"ndv":16,"upper":"宁波转余姚","lower":"太原转","count":64,"preSum":1199},{"ndv":15,"upper":"岑溪转博白","lower":"宁波转象山","count":65,"preSum":1263},{"ndv":10,"upper":"常州转","lower":"岑溪转容县","count":71,"preSum":1328},{"ndv":30,"upper":"广州转郁南","lower":"常州转扬中","count":62,"preSum":1399},{"ndv":14,"upper":"德阳","lower":"广州转阳山","count":62,"preSum":1461},{"ndv":10,"upper":"成都华阳","lower":"怀化","count":69,"preSum":1523},{"ndv":24,"upper":"抚顺","lower":"成都大丰","count":65,"preSum":1592},{"ndv":24,"upper":"无锡","lower":"拉萨转","count":90,"preSum":1657},{"ndv":6,"upper":"昆常转","lower":"无锡转","count":73,"preSum":1747},{"ndv":22,"upper":"昆明转砚山","lower":"昆明转","count":62,"preSum":1820},{"ndv":23,"upper":"柳州转","lower":"昆明转罗平","count":65,"preSum":1882},{"ndv":18,"upper":"武汉","lower":"柳州转三江","count":66,"preSum":1947},{"ndv":14,"upper":"沈阳","lower":"武汉转","count":93,"preSum":2013},{"ndv":20,"upper":"沧衡转河间","lower":"沈阳转","count":63,"preSum":2106},{"ndv":11,"upper":"泉州石狮","lower":"沧衡转泊头","count":63,"preSum":2169},{"ndv":14,"upper":"洛阳转","lower":"泉州转","count":74,"preSum":2232},{"ndv":12,"upper":"济南转肥城","lower":"济南转","count":64,"preSum":2306},{"ndv":24,"upper":"海口","lower":"济南转茌平","count":67,"preSum":2370},{"ndv":14,"upper":"淮安转","lower":"海口乐东县","count":66,"preSum":2437},{"ndv":24,"upper":"温江","lower":"淮安转宝应","count":64,"preSum":2503},{"ndv":30,"upper":"漯河转永城","lower":"湖州","count":62,"preSum":2567},{"ndv":19,"upper":"潍坊转莱州","lower":"漯河转汝南","count":66,"preSum":2629},{"ndv":12,"upper":"珠海转","lower":"潍坊转青州","count":76,"preSum":2695},{"ndv":16,"upper":"石市","lower":"益阳","count":82,"preSum":2771},{"ndv":26,"upper":"聊城","lower":"石市井陉","count":63,"preSum":2853},{"ndv":16,"upper":"芜湖转南陵","lower":"自贡转","count":63,"preSum":2916},{"ndv":25,"upper":"莱阳转","lower":"芜湖转宁国","count":62,"preSum":2979},{"ndv":17,"upper":"蚌埠转寿县","lower":"莱阳转招远","count":62,"preSum":3041},{"ndv":29,"upper":"衡阳转溆浦","lower":"蚌埠转怀远","count":62,"preSum":3103},{"ndv":21,"upper":"西宁转","lower":"衡阳转炎陵","count":62,"preSum":3165},{"ndv":10,"upper":"西安三森","lower":"西宁转同仁","count":62,"preSum":3227},{"ndv":22,"upper":"西安转富平","lower":"西安兴平","count":62,"preSum":3289},{"ndv":28,"upper":"贵阳转修文","lower":"西安转山阳","count":62,"preSum":3351},{"ndv":35,"upper":"遵义","lower":"贵阳转兴仁","count":66,"preSum":3413},{"ndv":15,"upper":"郑州港区转","lower":"邢邯转","count":67,"preSum":3479},{"ndv":11,"upper":"郑州转","lower":"郑州港卢氏","count":79,"preSum":3546},{"ndv":15,"upper":"重庆","lower":"郫县","count":71,"preSum":3625},{"ndv":17,"upper":"长春","lower":"重庆云阳","count":84,"preSum":3696},{"ndv":19,"upper":"长沙郊","lower":"长春转","count":78,"preSum":3780},{"ndv":11,"upper":"齐齐哈尔","lower":"长沙郊平江","count":52,"preSum":3858}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[161,79,173,79,77,58,106,59,88,500,114,75,146,6855],"valueArr":["东莞","中山转","义乌","京南","佛山","天津转","广州转","成都","沪西","浦东分拨中心","深圳转","鄂州转","(V)、△△","(V)、△△、∫"],"type":"String","sampleRate":0.9618625319816094}',87521,0.02436278),('jala_wms_prod','shipment_header','payno',2300274,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1484,"upper":"1832796696057094168","lower":"100441022058559!FP099111129996578","count":1488,"preSum":0},{"ndv":1488,"upper":"1870914072078718963","lower":"1832801844266336280","count":1488,"preSum":1488},{"ndv":1487,"upper":"1878563534491514493","lower":"1870915838900151970","count":1488,"preSum":2976},{"ndv":1488,"upper":"1880530357673255970","lower":"1878565514951295680","count":1488,"preSum":4464},{"ndv":1487,"upper":"1886573463828438884","lower":"1880537955827870398","count":1488,"preSum":5952},{"ndv":1487,"upper":"1891617386250503291","lower":"1886573642968694487","count":1488,"preSum":7440},{"ndv":1487,"upper":"1896297672938324060","lower":"1891617421264297999","count":1488,"preSum":8928},{"ndv":1487,"upper":"1896932895443324474","lower":"1896297744703205393","count":1488,"preSum":10416},{"ndv":1485,"upper":"1897159911391977078","lower":"1896933075205745186","count":1488,"preSum":11904},{"ndv":1486,"upper":"1899880248729178380","lower":"1897159911558262388","count":1488,"preSum":13392},{"ndv":1487,"upper":"1903179900573515760","lower":"1899881113496508775","count":1488,"preSum":14880},{"ndv":1488,"upper":"1906452120502540768","lower":"1903182026331931066","count":1488,"preSum":16368},{"ndv":1487,"upper":"1911852949699587799","lower":"1906452228701774495","count":1488,"preSum":17856},{"ndv":1487,"upper":"1915038300444831789","lower":"1911858169226630586","count":1488,"preSum":19344},{"ndv":1488,"upper":"1917194269746866291","lower":"1915040388757471789","count":1488,"preSum":20832},{"ndv":1488,"upper":"1920912277996478287","lower":"1917195636641733393","count":1488,"preSum":22320},{"ndv":1487,"upper":"23042577504774","lower":"1920915192436995579","count":1488,"preSum":23808},{"ndv":1488,"upper":"23050999937184","lower":"23042578879844","count":1488,"preSum":25296},{"ndv":1488,"upper":"23052207024716","lower":"230510-020599315363899","count":1488,"preSum":26784},{"ndv":1488,"upper":"23060345827289","lower":"23052214902216","count":1488,"preSum":28272},{"ndv":1488,"upper":"23061661983868","lower":"23060345941735","count":1488,"preSum":29760},{"ndv":1488,"upper":"2311400211532013","lower":"23061662381768","count":1488,"preSum":31248},{"ndv":1487,"upper":"265109333115","lower":"2311400220662942","count":1488,"preSum":32736},{"ndv":1488,"upper":"271354654999","lower":"265121474335","count":1488,"preSum":34224},{"ndv":1487,"upper":"273652656707","lower":"271357049749","count":1488,"preSum":35712},{"ndv":1487,"upper":"275952971620","lower":"273652670410","count":1488,"preSum":37200},{"ndv":1488,"upper":"3216250756380122640","lower":"275954711457","count":1488,"preSum":38688},{"ndv":1488,"upper":"3253389915328772966","lower":"3216280708884438531","count":1488,"preSum":40176},{"ndv":1488,"upper":"3303233535067337330","lower":"3253394379555697754","count":1488,"preSum":41664},{"ndv":1486,"upper":"3316790414389889312","lower":"3303234219367598236","count":1488,"preSum":43152},{"ndv":1487,"upper":"3324843001075210158","lower":"3316791099092567425","count":1488,"preSum":44640},{"ndv":1485,"upper":"3329766468219849727","lower":"3324846206548751613","count":1488,"preSum":46128},{"ndv":1486,"upper":"3330725331991742448","lower":"3329766468232630755","count":1488,"preSum":47616},{"ndv":1487,"upper":"3335242791101210534","lower":"3330725617326611401","count":1488,"preSum":49104},{"ndv":1487,"upper":"3342451248808912215","lower":"3335244015638576434","count":1488,"preSum":50592},{"ndv":1488,"upper":"3348816265556925210","lower":"3342451287310895604","count":1488,"preSum":52080},{"ndv":1487,"upper":"3353116359969470244","lower":"3348822459373553628","count":1488,"preSum":53568},{"ndv":1487,"upper":"3360427886170082604","lower":"3353118591755637038","count":1488,"preSum":55056},{"ndv":1487,"upper":"3364122168698182337","lower":"3360431163950684002","count":1488,"preSum":56544},{"ndv":1484,"upper":"3364668794474229004","lower":"3364122169573681207","count":1488,"preSum":58032},{"ndv":1484,"upper":"3365067567026386163","lower":"3364668859558505045","count":1488,"preSum":59520},{"ndv":1486,"upper":"3367758457938200922","lower":"3365068215676692337","count":1488,"preSum":61008},{"ndv":1487,"upper":"3371323467724740322","lower":"3367766593621231455","count":1488,"preSum":62496},{"ndv":1486,"upper":"3374711209087921150","lower":"3371325159468704049","count":1488,"preSum":63984},{"ndv":1486,"upper":"3378245655807206345","lower":"3374713873685823049","count":1488,"preSum":65472},{"ndv":1487,"upper":"3382461252151375702","lower":"3378246517737930306","count":1488,"preSum":66960},{"ndv":1487,"upper":"3389513149652996348","lower":"3382465464002934131","count":1488,"preSum":68448},{"ndv":1488,"upper":"3395248130692842601","lower":"3389515921178741823","count":1488,"preSum":69936},{"ndv":1487,"upper":"3398021103902802007","lower":"3395251766420358615","count":1488,"preSum":71424},{"ndv":1487,"upper":"3400202739026952945","lower":"3398021388956795402","count":1488,"preSum":72912},{"ndv":1488,"upper":"3402294913041316618","lower":"3400203565788352452","count":1488,"preSum":74400},{"ndv":1487,"upper":"3408325382768461156","lower":"3402296282880252556","count":1488,"preSum":75888},{"ndv":1488,"upper":"6917841557550602009","lower":"3408327792453859017","count":1488,"preSum":77376},{"ndv":1485,"upper":"6918025457652995233","lower":"6917842073163536334","count":1488,"preSum":78864},{"ndv":1486,"upper":"6918177551963854376","lower":"6918025705434649833","count":1488,"preSum":80352},{"ndv":1488,"upper":"6918330850433766892","lower":"6918177745710224832","count":1488,"preSum":81840},{"ndv":1487,"upper":"6918511796987237907","lower":"6918331157666928560","count":1488,"preSum":83328},{"ndv":1484,"upper":"6918702940928153306","lower":"6918511842102482787","count":1488,"preSum":84816},{"ndv":1487,"upper":"6918920943156270532","lower":"6918702983504795070","count":1488,"preSum":86304},{"ndv":1488,"upper":"6919067064000452504","lower":"6918920968230868445","count":1488,"preSum":87792},{"ndv":1488,"upper":"6919248606522709645","lower":"6919067420611384915","count":1488,"preSum":89280},{"ndv":1488,"upper":"6919410566841701488","lower":"6919248639676912891","count":1488,"preSum":90768},{"ndv":1488,"upper":"6919562240896472971","lower":"6919410614726629151","count":1488,"preSum":92256},{"ndv":1450,"upper":"XXY2023052337","lower":"6919562578720004018","count":1451,"preSum":93744}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[3220],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',1586,0.02436278),('jala_wms_prod','shipment_header','paystatus',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[3086,9329],"valueArr":[0,1],"type":"Int","sampleRate":0.9618625319816094}',87586,0.02436278),('jala_wms_prod','shipment_header','paytime',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','paytype',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','poddatetime',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','podstatus',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','portcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','postreceipton',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','primarywaybillcode',2777362,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1520,"upper":"75577115307801","lower":"031946331476","count":1520,"preSum":0},{"ndv":1520,"upper":"75609867528957","lower":"75577128587604","count":1520,"preSum":1520},{"ndv":1520,"upper":"75610298521318","lower":"75609867885291","count":1520,"preSum":3040},{"ndv":1520,"upper":"78342272388997","lower":"75610298740297","count":1520,"preSum":4560},{"ndv":1520,"upper":"78682559277507","lower":"78342290034657","count":1520,"preSum":6080},{"ndv":1520,"upper":"78686354848192","lower":"78682561735349","count":1520,"preSum":7600},{"ndv":1520,"upper":"78689757222243","lower":"78686368198035","count":1520,"preSum":9120},{"ndv":1520,"upper":"78692274987244","lower":"78689757690630","count":1520,"preSum":10640},{"ndv":1520,"upper":"78694703065521","lower":"78692278022140","count":1520,"preSum":12160},{"ndv":1520,"upper":"78697058275300","lower":"78694713435595","count":1520,"preSum":13680},{"ndv":1520,"upper":"78700375091497","lower":"78697058569015","count":1520,"preSum":15200},{"ndv":1520,"upper":"SF1375279537564","lower":"78700376961511","count":1520,"preSum":16720},{"ndv":1520,"upper":"SF1375574789248","lower":"SF1375279719587","count":1520,"preSum":18240},{"ndv":1520,"upper":"SF1375722856798","lower":"SF1375574934668","count":1520,"preSum":19760},{"ndv":1520,"upper":"SF1376010036345","lower":"SF1375722888112","count":1520,"preSum":21280},{"ndv":1520,"upper":"SF1381232462440","lower":"SF1376010036796","count":1520,"preSum":22800},{"ndv":1520,"upper":"SF1383847090763","lower":"SF1381236552944","count":1520,"preSum":24320},{"ndv":1520,"upper":"SF1385935434940","lower":"SF1383848339741","count":1520,"preSum":25840},{"ndv":1520,"upper":"SF1388130663542","lower":"SF1385935634146","count":1520,"preSum":27360},{"ndv":1520,"upper":"SF1602943676177","lower":"SF1388134725747","count":1520,"preSum":28880},{"ndv":1520,"upper":"SF1603441758884","lower":"SF1602947806833","count":1520,"preSum":30400},{"ndv":1520,"upper":"SF1603721006282","lower":"SF1603441761479","count":1520,"preSum":31920},{"ndv":1520,"upper":"SF1603999020069","lower":"SF1603721095400","count":1520,"preSum":33440},{"ndv":1520,"upper":"SF1610651652055","lower":"SF1603999220607","count":1520,"preSum":34960},{"ndv":1520,"upper":"SF1613243623132","lower":"SF1610652272128","count":1520,"preSum":36480},{"ndv":1520,"upper":"SF1615578649010","lower":"SF1613245929241","count":1520,"preSum":38000},{"ndv":1520,"upper":"SF1618058976036","lower":"SF1615579522109","count":1520,"preSum":39520},{"ndv":1520,"upper":"SF1621422488761","lower":"SF1618059374169","count":1520,"preSum":41040},{"ndv":1520,"upper":"SF1623419488676","lower":"SF1621422527612","count":1520,"preSum":42560},{"ndv":1520,"upper":"SF1625476887717","lower":"SF1623419738956","count":1520,"preSum":44080},{"ndv":1520,"upper":"SF1629405820781","lower":"SF1625476887814","count":1520,"preSum":45600},{"ndv":1520,"upper":"SF1630983404832","lower":"SF1629407388802","count":1520,"preSum":47120},{"ndv":1520,"upper":"SF1633186294127","lower":"SF1630983504850","count":1520,"preSum":48640},{"ndv":1520,"upper":"SF1635386324652","lower":"SF1633188154637","count":1520,"preSum":50160},{"ndv":1520,"upper":"SF1637584534694","lower":"SF1635387254657","count":1520,"preSum":51680},{"ndv":1520,"upper":"SF1639787754240","lower":"SF1637584944218","count":1520,"preSum":53200},{"ndv":1520,"upper":"SF1642291809190","lower":"SF1639788374816","count":1520,"preSum":54720},{"ndv":1520,"upper":"SF1644967529307","lower":"SF1642292486175","count":1520,"preSum":56240},{"ndv":1520,"upper":"SF1647473870006","lower":"SF1644969573122","count":1520,"preSum":57760},{"ndv":1520,"upper":"SF1650140306581","lower":"SF1647475912043","count":1520,"preSum":59280},{"ndv":1520,"upper":"SF1652741603244","lower":"SF1650140413697","count":1520,"preSum":60800},{"ndv":1520,"upper":"SF1655242137058","lower":"SF1652741767421","count":1520,"preSum":62320},{"ndv":1520,"upper":"SF1657841581447","lower":"SF1655242212476","count":1520,"preSum":63840},{"ndv":1520,"upper":"SF1660684244909","lower":"SF1657841955023","count":1520,"preSum":65360},{"ndv":1520,"upper":"SF1662040500892","lower":"SF1660684245128","count":1520,"preSum":66880},{"ndv":1520,"upper":"SF1664485487178","lower":"SF1662047106416","count":1520,"preSum":68400},{"ndv":1520,"upper":"SF1667613564314","lower":"SF1664485646244","count":1520,"preSum":69920},{"ndv":1520,"upper":"SF1669684640851","lower":"SF1667613892481","count":1520,"preSum":71440},{"ndv":1520,"upper":"SF1673902240446","lower":"SF1669684653071","count":1520,"preSum":72960},{"ndv":1520,"upper":"SF1675944144677","lower":"SF1673902270240","count":1520,"preSum":74480},{"ndv":1520,"upper":"SF1678927670867","lower":"SF1675944146075","count":1520,"preSum":76000},{"ndv":1520,"upper":"SF1681632385091","lower":"SF1678927827018","count":1520,"preSum":77520},{"ndv":1520,"upper":"SF1682896404956","lower":"SF1681641457424","count":1520,"preSum":79040},{"ndv":1520,"upper":"SF1685681797485","lower":"SF1682896431059","count":1520,"preSum":80560},{"ndv":1520,"upper":"SF1687670000648","lower":"SF1685682091625","count":1520,"preSum":82080},{"ndv":1520,"upper":"SF1690567618549","lower":"SF1687670010271","count":1520,"preSum":83600},{"ndv":1520,"upper":"SF1693434968742","lower":"SF1690568259047","count":1520,"preSum":85120},{"ndv":1520,"upper":"SF1696059591564","lower":"SF1693435079562","count":1520,"preSum":86640},{"ndv":1520,"upper":"SF1698988890960","lower":"SF1696061063549","count":1520,"preSum":88160},{"ndv":1520,"upper":"SF1831791157206","lower":"SF1698992911347","count":1520,"preSum":89680},{"ndv":1520,"upper":"SF1832262929954","lower":"SF1831791180140","count":1520,"preSum":91200},{"ndv":1520,"upper":"SF1832779013016","lower":"SF1832262944374","count":1520,"preSum":92720},{"ndv":1520,"upper":"SF1833283129071","lower":"SF1832779037521","count":1520,"preSum":94240},{"ndv":1503,"upper":"SF7607172447695","lower":"SF1833283593644","count":1503,"preSum":95760}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1107],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',1631,0.02436278),('jala_wms_prod','shipment_header','printdataid',1423470,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1340,"upper":"6402ca7e2b98cd70e0713719","lower":"639bb6322f046a24bf50dc52","count":1340,"preSum":0},{"ndv":1340,"upper":"640afd522173a9388e2bd79e","lower":"6402ca7e612c5a5b766252aa","count":1340,"preSum":1340},{"ndv":1340,"upper":"641ffcb8c98eb1686dd21879","lower":"640afd52e403523f28baa949","count":1340,"preSum":2680},{"ndv":1340,"upper":"643766de62d7b11237189fa0","lower":"641ffcbcc98eb1686dd2187d","count":1340,"preSum":4020},{"ndv":1340,"upper":"643f3619d5b7790c20587659","lower":"643766de62d7b11237189fa1","count":1340,"preSum":5360},{"ndv":1340,"upper":"64426107fb2a0e77594173d1","lower":"643f3619d5b7790c2058765a","count":1340,"preSum":6700},{"ndv":1340,"upper":"6445c7ba30728460dfb0ed28","lower":"64426107fb2a0e77594173d3","count":1340,"preSum":8040},{"ndv":1340,"upper":"6447cdaea042ae62dcc65d79","lower":"6445c7bfefdeec64826d7c89","count":1340,"preSum":9380},{"ndv":1340,"upper":"644b2a08b7356506a9801ece","lower":"6447cdb220399d364108d2e8","count":1340,"preSum":10720},{"ndv":1340,"upper":"644c98a5a3fda2138c01cc81","lower":"644b2a09b7356506a9801ed0","count":1340,"preSum":12060},{"ndv":1340,"upper":"644f3a8a3460f001876b50dd","lower":"644c98a5b7356506a989cfe4","count":1340,"preSum":13400},{"ndv":1340,"upper":"645113053460f00187745aaf","lower":"644f3a8ccb08c42cd06ebfe4","count":1340,"preSum":14740},{"ndv":1340,"upper":"6451c76c3460f0018778305b","lower":"645113063460f00187745ab2","count":1340,"preSum":16080},{"ndv":1340,"upper":"64520685cb08c42cd082896d","lower":"6451c76ccb08c42cd07d646a","count":1340,"preSum":17420},{"ndv":1340,"upper":"645348d13460f0018784cfcf","lower":"64520685cb08c42cd0828970","count":1340,"preSum":18760},{"ndv":1340,"upper":"6455b70573f6dd1883aed3c0","lower":"64534b26a34628313f100da0","count":1340,"preSum":20100},{"ndv":1340,"upper":"6457d47773f6dd1883b65030","lower":"6455b71532445e3aa1391b9e","count":1340,"preSum":21440},{"ndv":1340,"upper":"645a370c8338b44f591196be","lower":"6457d47773f6dd1883b65031","count":1340,"preSum":22780},{"ndv":1340,"upper":"645c4c3c0f60720169d3ba12","lower":"645a370cbb419d6e2361b34c","count":1340,"preSum":24120},{"ndv":1340,"upper":"645e2a514985200561dbe2f5","lower":"645c4c3c0f60720169d3ba15","count":1340,"preSum":25460},{"ndv":1340,"upper":"646071f5977ac2612ded8a9b","lower":"645e2a51a8e5fa4520e308bc","count":1340,"preSum":26800},{"ndv":1340,"upper":"6462a337977ac2612df8dc65","lower":"646071f661a80428444903e2","count":1340,"preSum":28140},{"ndv":1340,"upper":"6463bcc8977ac2612d00b1f6","lower":"6462d6f351c41f0befc5469a","count":1340,"preSum":29480},{"ndv":1340,"upper":"646586af51c41f0befd6f17f","lower":"6463bccc51c41f0befcb4f43","count":1340,"preSum":30820},{"ndv":1340,"upper":"6467c2922af2e71c128d396a","lower":"646586af51c41f0befd6f183","count":1340,"preSum":32160},{"ndv":1340,"upper":"6469c303cbe08c3cf12f288b","lower":"6467c292cbe08c3cf1238579","count":1340,"preSum":33500},{"ndv":1340,"upper":"646c51c0cbe08c3cf13ab7f9","lower":"6469c3042af2e71c129a6a45","count":1340,"preSum":34840},{"ndv":1340,"upper":"646edd4f7d6bcb3ea52f4ee3","lower":"646c51c12af2e71c12a588e3","count":1340,"preSum":36180},{"ndv":1340,"upper":"647173b486c6db1296cfa9ed","lower":"646edd4f7d6bcb3ea52f4ee4","count":1340,"preSum":37520},{"ndv":1340,"upper":"647188b386c6db1296d04fae","lower":"647173b533db057bab9d80cb","count":1340,"preSum":38860},{"ndv":1340,"upper":"6471971acf891a6b00d4a8b8","lower":"647188b3cf891a6b00d3bc50","count":1340,"preSum":40200},{"ndv":1340,"upper":"6471a759cf891a6b00d52b20","lower":"6471971acf891a6b00d4a8b9","count":1340,"preSum":41540},{"ndv":1340,"upper":"6471ca1bcf891a6b00d626ee","lower":"6471a759cf891a6b00d52b27","count":1340,"preSum":42880},{"ndv":1340,"upper":"6472a8f76efccc79a04e3779","lower":"6471ca1bcf891a6b00d626f2","count":1340,"preSum":44220},{"ndv":1340,"upper":"6473485d5de7ab60bd08f087","lower":"6472a8f86efccc79a04e377b","count":1340,"preSum":45560},{"ndv":1340,"upper":"64745b9ccf891a6b00dd6866","lower":"6473485d5de7ab60bd08f08b","count":1340,"preSum":46900},{"ndv":1340,"upper":"6475a029c18c6a210a6e5d7a","lower":"64745ba233db057baba791f1","count":1340,"preSum":48240},{"ndv":1340,"upper":"6476e1dfb7fd9828da95d71e","lower":"6475a02a6e1ab418fa0d08b0","count":1340,"preSum":49580},{"ndv":1340,"upper":"6477479ab7fd9828da97dbaa","lower":"6476e563336e123e3d8f7786","count":1340,"preSum":50920},{"ndv":1340,"upper":"64777e4994303d3cf5a870ae","lower":"6477479c1a16033c58f86bda","count":1340,"preSum":52260},{"ndv":1340,"upper":"647861b4b7fd9828daa7feb6","lower":"64777e4a319c102daf44167b","count":1340,"preSum":53600},{"ndv":1340,"upper":"64795ece336e123e3da7da0f","lower":"647861b4b7fd9828daa7feb7","count":1340,"preSum":54940},{"ndv":1340,"upper":"647a918989776c5eee537c5b","lower":"64795ece9c699e237b19a7b3","count":1340,"preSum":56280},{"ndv":1340,"upper":"647b6aaa8249d352cdbf98cd","lower":"647a9189e544c00c27ac4758","count":1340,"preSum":57620},{"ndv":1340,"upper":"647cbe56e544c00c27ae0811","lower":"647b6aaa8249d352cdbf98ce","count":1340,"preSum":58960},{"ndv":1340,"upper":"647e9585e544c00c27afdcfe","lower":"647cbf0a89776c5eee5564a9","count":1340,"preSum":60300},{"ndv":1340,"upper":"6480021289776c5eee587816","lower":"647e9586003af203fdb3c34f","count":1340,"preSum":61640},{"ndv":1340,"upper":"648295433564ac52a4f8e186","lower":"6480021589776c5eee58781b","count":1340,"preSum":62980},{"ndv":1340,"upper":"6484761e78ec172fd604d108","lower":"648295433564ac52a4f8e187","count":1340,"preSum":64320},{"ndv":1340,"upper":"6486aef22d006360fe0735dd","lower":"648476322d006360fe056fff","count":1340,"preSum":65660},{"ndv":1340,"upper":"64887b23acc9a26ca987d341","lower":"6486aef26f06004a70c348a0","count":1340,"preSum":67000},{"ndv":1340,"upper":"648af19c1d13f33ef2649cb1","lower":"64887b23acc9a26ca987d342","count":1340,"preSum":68340},{"ndv":1340,"upper":"648b3eeb4e8d7266e6ee52e2","lower":"648af19c1d13f33ef2649cb3","count":1340,"preSum":69680},{"ndv":1340,"upper":"648c2ebc2625d24e22e5ea7c","lower":"648b3eee4e8d7266e6ee52e5","count":1340,"preSum":71020},{"ndv":1340,"upper":"648d09fddbb472367eb71b54","lower":"648c2ebc2625d24e22e5ea7f","count":1340,"preSum":72360},{"ndv":1340,"upper":"648db69cacc9a26ca98d69f0","lower":"648d09fddbb472367eb71b5a","count":1340,"preSum":73700},{"ndv":1340,"upper":"648e85aadbb472367eb80b42","lower":"648db69d2625d24e22e7a0c3","count":1340,"preSum":75040},{"ndv":1340,"upper":"648efa662625d24e22e91179","lower":"648e85ab1d13f33ef268a039","count":1340,"preSum":76380},{"ndv":1340,"upper":"648f340bdbb472367eb8e0e7","lower":"648efa66acc9a26ca98ed374","count":1340,"preSum":77720},{"ndv":1340,"upper":"64904a7c1d13f33ef26bc578","lower":"648f34a91d13f33ef269ac6e","count":1340,"preSum":79060},{"ndv":1340,"upper":"6491bb9f2625d24e22ed403f","lower":"64904a7cacc9a26ca9911671","count":1340,"preSum":80400},{"ndv":1340,"upper":"64953acaacc9a26ca996be2b","lower":"6491bb9f2625d24e22ed4040","count":1340,"preSum":81740},{"ndv":1340,"upper":"6498f63edbb472367ebbca81","lower":"64953ad12625d24e22f12d97","count":1340,"preSum":83080},{"ndv":1293,"upper":"649cc6111d13f33ef279061d","lower":"6498f708dbb472367ebbcabb","count":1293,"preSum":84420}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,14288,0.02436278),('jala_wms_prod','shipment_header','priority',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','processstamp',224832,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1204,"upper":"2023-02-26 10:56:00","lower":"2022-09-05 11:36:00","count":1458,"preSum":0},{"ndv":856,"upper":"2023-03-07 10:41:01","lower":"2023-02-26 10:57:00","count":1458,"preSum":1458},{"ndv":1038,"upper":"2023-03-20 10:07:01","lower":"2023-03-07 10:46:01","count":1458,"preSum":2916},{"ndv":1083,"upper":"2023-04-09 11:04:00","lower":"2023-03-20 10:08:00","count":1458,"preSum":4374},{"ndv":1014,"upper":"2023-04-17 10:26:00","lower":"2023-04-09 11:05:00","count":1458,"preSum":5832},{"ndv":1068,"upper":"2023-04-21 09:58:00","lower":"2023-04-17 10:32:00","count":1458,"preSum":7290},{"ndv":828,"upper":"2023-04-23 09:21:00","lower":"2023-04-21 10:00:00","count":1460,"preSum":8748},{"ndv":857,"upper":"2023-04-25 10:37:00","lower":"2023-04-23 09:23:00","count":1458,"preSum":10208},{"ndv":776,"upper":"2023-04-26 17:05:00","lower":"2023-04-25 10:39:03","count":1458,"preSum":11666},{"ndv":758,"upper":"2023-04-28 15:20:05","lower":"2023-04-26 17:05:03","count":1459,"preSum":13124},{"ndv":855,"upper":"2023-04-29 21:22:00","lower":"2023-04-28 15:20:11","count":1458,"preSum":14583},{"ndv":702,"upper":"2023-05-01 15:52:09","lower":"2023-04-29 21:28:36","count":1458,"preSum":16041},{"ndv":687,"upper":"2023-05-03 10:03:01","lower":"2023-05-01 15:53:03","count":1460,"preSum":17499},{"ndv":432,"upper":"2023-05-03 15:57:00","lower":"2023-05-03 10:04:02","count":1461,"preSum":18959},{"ndv":539,"upper":"2023-05-04 11:20:02","lower":"2023-05-03 15:57:01","count":1458,"preSum":20420},{"ndv":624,"upper":"2023-05-05 10:15:05","lower":"2023-05-04 11:20:03","count":1459,"preSum":21878},{"ndv":751,"upper":"2023-05-06 18:19:00","lower":"2023-05-05 10:16:06","count":1458,"preSum":23337},{"ndv":667,"upper":"2023-05-08 15:32:00","lower":"2023-05-06 18:20:00","count":1458,"preSum":24795},{"ndv":734,"upper":"2023-05-10 11:27:11","lower":"2023-05-08 15:33:00","count":1461,"preSum":26253},{"ndv":730,"upper":"2023-05-11 15:13:07","lower":"2023-05-10 11:27:24","count":1464,"preSum":27714},{"ndv":763,"upper":"2023-05-12 20:11:11","lower":"2023-05-11 15:14:04","count":1459,"preSum":29178},{"ndv":693,"upper":"2023-05-14 14:17:00","lower":"2023-05-12 20:13:05","count":1458,"preSum":30637},{"ndv":703,"upper":"2023-05-16 09:40:00","lower":"2023-05-14 14:18:00","count":1464,"preSum":32095},{"ndv":601,"upper":"2023-05-17 12:52:00","lower":"2023-05-16 09:41:00","count":1463,"preSum":33559},{"ndv":651,"upper":"2023-05-18 11:19:13","lower":"2023-05-17 12:53:00","count":1458,"preSum":35022},{"ndv":758,"upper":"2023-05-19 17:18:06","lower":"2023-05-18 11:20:06","count":1458,"preSum":36480},{"ndv":769,"upper":"2023-05-21 13:54:05","lower":"2023-05-19 17:23:11","count":1458,"preSum":37938},{"ndv":615,"upper":"2023-05-23 10:12:09","lower":"2023-05-21 13:55:00","count":1462,"preSum":39396},{"ndv":673,"upper":"2023-05-24 18:07:00","lower":"2023-05-23 10:14:19","count":1458,"preSum":40858},{"ndv":584,"upper":"2023-05-26 14:49:07","lower":"2023-05-24 18:08:00","count":1458,"preSum":42316},{"ndv":725,"upper":"2023-05-28 14:13:00","lower":"2023-05-26 14:50:00","count":1459,"preSum":43774},{"ndv":656,"upper":"2023-05-30 16:19:01","lower":"2023-05-28 14:18:00","count":1461,"preSum":45233},{"ndv":677,"upper":"2023-05-31 23:01:00","lower":"2023-05-30 16:22:00","count":1458,"preSum":46694},{"ndv":344,"upper":"2023-06-01 04:25:00","lower":"2023-05-31 23:02:00","count":1458,"preSum":48152},{"ndv":418,"upper":"2023-06-01 10:29:00","lower":"2023-06-01 04:26:00","count":1464,"preSum":49610},{"ndv":422,"upper":"2023-06-01 13:25:01","lower":"2023-06-01 10:30:01","count":1461,"preSum":51074},{"ndv":344,"upper":"2023-06-01 15:28:01","lower":"2023-06-01 13:25:30","count":1459,"preSum":52535},{"ndv":352,"upper":"2023-06-01 17:39:30","lower":"2023-06-01 15:28:31","count":1459,"preSum":53994},{"ndv":451,"upper":"2023-06-01 21:19:00","lower":"2023-06-01 17:40:00","count":1460,"preSum":55453},{"ndv":624,"upper":"2023-06-02 09:20:07","lower":"2023-06-01 21:20:00","count":1458,"preSum":56913},{"ndv":624,"upper":"2023-06-02 15:47:01","lower":"2023-06-02 09:20:13","count":1459,"preSum":58371},{"ndv":740,"upper":"2023-06-03 09:38:01","lower":"2023-06-02 15:47:02","count":1458,"preSum":59830},{"ndv":633,"upper":"2023-06-03 17:16:01","lower":"2023-06-03 09:38:02","count":1458,"preSum":61288},{"ndv":712,"upper":"2023-06-04 15:40:01","lower":"2023-06-03 17:17:01","count":1458,"preSum":62746},{"ndv":778,"upper":"2023-06-05 16:36:01","lower":"2023-06-04 15:41:00","count":1459,"preSum":64204},{"ndv":679,"upper":"2023-06-06 16:42:01","lower":"2023-06-05 16:36:02","count":1459,"preSum":65663},{"ndv":824,"upper":"2023-06-08 09:22:03","lower":"2023-06-06 16:43:00","count":1458,"preSum":67122},{"ndv":775,"upper":"2023-06-09 16:17:00","lower":"2023-06-08 09:23:00","count":1458,"preSum":68580},{"ndv":797,"upper":"2023-06-11 13:04:01","lower":"2023-06-09 16:18:01","count":1458,"preSum":70038},{"ndv":864,"upper":"2023-06-12 20:54:00","lower":"2023-06-11 13:07:00","count":1458,"preSum":71496},{"ndv":709,"upper":"2023-06-14 10:44:01","lower":"2023-06-12 21:01:17","count":1458,"preSum":72954},{"ndv":820,"upper":"2023-06-15 18:27:01","lower":"2023-06-14 10:47:00","count":1458,"preSum":74412},{"ndv":634,"upper":"2023-06-16 14:23:07","lower":"2023-06-15 18:28:01","count":1464,"preSum":75870},{"ndv":536,"upper":"2023-06-16 21:32:01","lower":"2023-06-16 14:23:08","count":1458,"preSum":77334},{"ndv":499,"upper":"2023-06-17 13:43:01","lower":"2023-06-16 21:33:01","count":1462,"preSum":78792},{"ndv":560,"upper":"2023-06-18 09:46:03","lower":"2023-06-17 13:44:01","count":1458,"preSum":80254},{"ndv":508,"upper":"2023-06-18 16:40:01","lower":"2023-06-18 09:47:01","count":1461,"preSum":81712},{"ndv":499,"upper":"2023-06-19 09:42:02","lower":"2023-06-18 16:41:01","count":1459,"preSum":83173},{"ndv":447,"upper":"2023-06-19 14:45:07","lower":"2023-06-19 09:43:01","count":1459,"preSum":84632},{"ndv":561,"upper":"2023-06-20 10:06:01","lower":"2023-06-19 14:45:08","count":1458,"preSum":86091},{"ndv":584,"upper":"2023-06-21 10:19:01","lower":"2023-06-20 10:07:01","count":1458,"preSum":87549},{"ndv":808,"upper":"2023-06-23 16:25:01","lower":"2023-06-21 10:19:02","count":1458,"preSum":89007},{"ndv":828,"upper":"2023-06-26 13:34:01","lower":"2023-06-23 16:26:01","count":1458,"preSum":90465},{"ndv":828,"upper":"2023-06-28 23:32:22","lower":"2023-06-26 13:35:01","count":1360,"preSum":91923}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[20,28,20,19,21,19,21,26,19,24,29,22,25],"valueArr":["2022-11-22 14:07:01","2023-04-14 09:34:00","2023-04-22 10:17:00","2023-05-11 16:35:04","2023-05-30 14:03:00","2023-05-31 04:25:00","2023-06-01 00:57:00","2023-06-01 14:25:01","2023-06-01 16:33:00","2023-06-01 18:12:01","2023-06-01 18:43:45","2023-06-01 18:52:16","2023-06-01 18:55:01"],"type":"String","sampleRate":0.9618625319816094}',6425,0.02436278),('jala_wms_prod','shipment_header','processtype',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[32,4872,95081,16],"valueArr":["ABNORMAL","CANCEL","NORMAL","PENDING"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','purchaseordercode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[5],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99996,0.02436278),('jala_wms_prod','shipment_header','qtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','realuserid',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','receipcompany',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','rejectionnote',969,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":"1:您好!受防疫措施变化影响,该目的地暂时无法提供此产品寄递服务,带来不便请您理解。(BPS5481) 50001 业务服务错误,SubCode:2136","lower":"14023 商家未开通电子面单服务;log_id: 2023022314302067B840CB4BE8FE02325A","count":3,"preSum":0},{"ndv":2,"upper":"1:您好!该目的地暂不提供寄递服务,您可更换地址重新下单,带来不便请您理解。(BPS8565) 15 Remote service error,SubCode:sf_response_fail-8177","lower":"1:您好!受防疫措施变化影响,该目的地暂时无法提供此产品寄递服务,带来不便请您理解。(BPS5552) 50001 业务服务错误,SubCode:2136","count":3,"preSum":3},{"ndv":3,"upper":"20063 收方地址不详细,请填写更为详细的地址后重新下单。;log_id: 20230524094244AB2E5504D6EC814D6046","lower":"20063 收方地址不详细,请填写更为详细的地址后重新下单。;log_id: 2023051110341689D709C8F6AF868E836F","count":3,"preSum":6},{"ndv":3,"upper":"20063 收方地址不详细,请填写更为详细的地址后重新下单。;log_id: 20230620142025A7D4522922B2681BB763","lower":"20063 收方地址不详细,请填写更为详细的地址后重新下单。;log_id: 202306100922047D73A4FB5C72F876E288","count":3,"preSum":9},{"ndv":3,"upper":"70006 收方地址不详细,请填写更为详细的地址后重新下单。","lower":"20064 收方地址存在双重目的地,请核实后重新填写地址下单。;log_id: 20230502095559D5D1AF1BF12920093D8D","count":3,"preSum":12},{"ndv":3,"upper":"[isv.oaid-invalid]:参数oaid无效,tid:3263044644040400448 15 Remote service error,SubCode:isv.oaid-invalid","lower":"70006 收方地址存在双重目的地,请核实后重新填写地址下单。","count":3,"preSum":15},{"ndv":3,"upper":"[订单23042554318434已被取消,不能查询/打印面单]","lower":"[isv.oaid-invalid]:参数oaid无效,tid:3305371431843590122 15 Remote service error,SubCode:isv.oaid-invalid","count":3,"preSum":18},{"ndv":3,"upper":"[订单23051588573938已被取消,不能查询/打印面单]","lower":"[订单23050425739823已被取消,不能查询/打印面单]","count":3,"preSum":21},{"ndv":3,"upper":"[订单23052481484666已被取消,不能查询/打印面单]","lower":"[订单23052369563209已被取消,不能查询/打印面单]","count":3,"preSum":24},{"ndv":3,"upper":"到方电话或手机不合法","lower":"[订单23060252090657已被取消,不能查询/打印面单]","count":4,"preSum":27},{"ndv":3,"upper":"当前所选地址超出服务范围,请检查地址或联系您的服务网点 15 Remote service error,SubCode:ADDRESS_NOT_REACHABLE","lower":"商家请求参数错误,固话和手机只能包含+、-、空格、单引号、数字、英文逗号、中文逗号 15 Remote service error,SubCode:phone or mobile illegal","count":5,"preSum":31},{"ndv":2,"upper":"整单短拣","lower":"必填参数tel为空","count":5,"preSum":36},{"ndv":2,"upper":"订单明细[502547800]未指定分配规则,并且货品没有默认规则","lower":"联系人手机为空;","count":3,"preSum":41},{"ndv":2,"upper":"货品[502191390] [自然堂雪润皙白晶澈淡斑精华液40mL]缺货[1]","lower":"货品[28685] [28685]缺货[2]","count":3,"preSum":44},{"ndv":3,"upper":"货品[502200305] [自然堂凝时鲜颜肌活乳液(2022升级)120mL]缺货[3]","lower":"货品[502191612] [自然堂雪润皙白多重防晒隔离霜(淡绿色)SPF35PA+++(新版)30mL]缺货[1]","count":3,"preSum":47},{"ndv":2,"upper":"货品[502200404] [自然堂凝时鲜颜小紫瓶肌活霜50g]缺货[28]","lower":"货品[502200404] [自然堂凝时鲜颜小紫瓶肌活霜50g]缺货[1]","count":3,"preSum":50},{"ndv":3,"upper":"货品[502203504] [自然堂凝时鲜颜肌活冰肌水(滋润型)(2023升级)160mL]缺货[1]","lower":"货品[502201910] [自然堂凝时鲜颜肌活精华液(2023)40mL]缺货[1]","count":3,"preSum":53},{"ndv":3,"upper":"货品[502477902] [自然堂凝时鲜颜肌活氨基酸洁面霜(2023升级)60g中小样]缺货[2]","lower":"货品[502240703] [自然堂弹嫩紧致抗皱眼霜15g]缺货[1]","count":3,"preSum":56},{"ndv":3,"upper":"货品[502524002] [自然堂男士喜马拉雅龙血能量控油醒肤洁面乳(201806)50mL中小样]缺货[1]","lower":"货品[502502302] [自然堂惊鸿魅眼纤长睫毛膏8.5g]缺货[1]","count":3,"preSum":59},{"ndv":3,"upper":"货品[502568301] [自然堂炫彩盈润高显色唇膏#205树莓色3.2g]缺货[1]","lower":"货品[502534501] [自然堂雪松精油活颜御龄体验装四件套(霜版)中小样]缺货[1]","count":3,"preSum":62},{"ndv":2,"upper":"货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(02代) 安瓶1.5mL+面膜33mL×5片装]缺货[1]","lower":"货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(02代) 安瓶1.5mL+面膜33mL×5片装]缺货[10]","count":3,"preSum":65},{"ndv":2,"upper":"货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(02代) 安瓶1.5mL+面膜33mL×5片装]缺货[5]","lower":"货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(02代) 安瓶1.5mL+面膜33mL×5片装]缺货[3]","count":3,"preSum":68},{"ndv":3,"upper":"货品[502582805] [自然堂烟酰胺细致提亮安瓶面膜(无防腐) 安瓶1.5mL+面膜33mL 5片装]缺货[1]","lower":"货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(安瓶1.5mL+面膜33mL)*5PCS(02代)]缺货[1]","count":4,"preSum":71},{"ndv":3,"upper":"货品[502589301] [自然堂雪润冰肌水晶透焕亮面膜24mL*1PCS(2022版)中小样]缺货[1]","lower":"货品[502586901] [自然堂多肽抗皱美颈霜60g类产品]缺货[1]","count":3,"preSum":75},{"ndv":3,"upper":"货品[502622207] [自然堂凝时鲜颜肌活修护小紫瓶精华液50mL(第五代)]缺货[1]","lower":"货品[5025982001] [自然堂羽感致护防晒乳SPF50+PA+++50mL(2020版)优惠套装]缺货[1]","count":3,"preSum":78},{"ndv":3,"upper":"货品[502643500] [自然堂弹嫩紧致抗皱精华液7.5mL中小样]缺货[1]","lower":"货品[502623401] [自然堂男士喜马拉雅冰川保湿爽肤水120mL(2022版)]缺货[24]","count":3,"preSum":81},{"ndv":3,"upper":"货品[502668804] [自然堂雪域紫草细致毛孔面膜(2022二版)26mL×5片装]缺货[1]","lower":"货品[502643601] [自然堂雪松精油活颜御龄精华液7.5mL中小样(2022版)]缺货[1]","count":3,"preSum":84},{"ndv":3,"upper":"货品[502684505] [自然堂果酸细致焕肤面膜(绿色盖膜/纸卡版/升级版)6g 1颗装中小样]缺货[2]","lower":"货品[502668904] [自然堂雪茶平衡保湿面面膜26mL*5PCS(2022二版)]缺货[2]","count":4,"preSum":87},{"ndv":2,"upper":"货品[502692900] [自然堂娇颜亮润四件套(标签升级)中小样]缺货[1]","lower":"货品[502684505] [自然堂果酸细致焕肤面膜(绿色盖膜/纸卡版/升级版)6g 1颗装中小样]缺货[5]","count":4,"preSum":91},{"ndv":2,"upper":"货品[502700002] [自然堂植物补水面膜21片装(2022二版)]缺货[1]","lower":"货品[502699002] [自然堂雪域百合补水面膜(2022二版)26mL 1片装]缺货[1]","count":4,"preSum":95},{"ndv":3,"upper":"货品[502700101] [自然堂植物补水面膜套装40PCS(2022版)]缺货[1]","lower":"货品[502700002] [自然堂植物补水面膜21片装(2022二版)]缺货[2]","count":5,"preSum":99},{"ndv":3,"upper":"货品[502731300] [自然堂敏感头皮止痒洗发露+精华乳旅行装(40mL+40mL)两件套]缺货[1]","lower":"货品[502725500] [自然堂喜马拉雅茶泥净颜清洁面膜100g]缺货[2]","count":4,"preSum":104},{"ndv":2,"upper":"货品[502750100] [自然堂凝时鲜颜肌活修护小紫瓶精华液第五代7mL中小样]缺货[1]","lower":"货品[502732000] [自然堂舒缓润养卸妆膏100mL]缺货[3]","count":3,"preSum":108},{"ndv":3,"upper":"货品[502751500] [自然堂雪肌追光美白焕颜三件套]缺货[3]","lower":"货品[502750100] [自然堂凝时鲜颜肌活修护小紫瓶精华液第五代7mL中小样]缺货[3]","count":3,"preSum":111},{"ndv":3,"upper":"货品[502764100] [自然堂纯粹滋润冰肌水(2022升级版)60mL中小样]缺货[1]","lower":"货品[502755300] [自然堂嫩白保湿乳35mL中小样]缺货[1]","count":3,"preSum":114},{"ndv":3,"upper":"货品[502845500] [自然堂凝时鲜颜肌活修护体验装三件套(霜版)中小样]缺货[1]","lower":"货品[502764100] [自然堂纯粹滋润冰肌水(2022升级版)60mL中小样]缺货[2]","count":3,"preSum":117},{"ndv":3,"upper":"货品[502974012] [自然堂雪润皙白晶澈冰肌水(新规版)60mL]缺货[1]","lower":"货品[502903300] [自然堂小紫瓶告白礼盒(2023版)]缺货[1]","count":3,"preSum":120},{"ndv":3,"upper":"货品[502976673] [自然堂凝时鲜颜肌活冰肌水(清润型)(2023升级)60mL]缺货[1]","lower":"货品[502974752] [自然堂雪域精粹纯粹滋润精华液10mL(体验装)]缺货[2]","count":3,"preSum":123},{"ndv":3,"upper":"货品[512007100] [珀芙研集护保湿舒色面膜22mL*1PCS非卖商品]缺货[16]","lower":"货品[502978212] [自然堂雪域精粹纯粹滋润洗颜霜(配方技术升级)60g中小样]缺货[1]","count":3,"preSum":126},{"ndv":2,"upper":"货品[512007100] [珀芙研集护保湿舒色面膜22mL*1PCS非卖商品]缺货[3]","lower":"货品[512007100] [珀芙研集护保湿舒色面膜22mL*1PCS非卖商品]缺货[2]","count":4,"preSum":129},{"ndv":3,"upper":"货品[6165102] [自然堂王一博拍立得明信片C线上]缺货[1]","lower":"货品[512007100] [珀芙研集护保湿舒色面膜22mL*1PCS非卖商品]缺货[6]","count":3,"preSum":133},{"ndv":3,"upper":"顺丰接口返回:错误码:20063:错误信息:收方地址不详细,请填写更为详细的地址后重新下单。","lower":"货品[6165273] [自然堂2022版购物袋-中号]缺货[1]","count":5,"preSum":136}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[8,8,6,5,703,8,5,6,4,4,6,4,8,6],"valueArr":["","1:尊敬的客户,您好!受目的地疫情影响,暂时无法提供寄递服务,带来不便请您理解。(BPS4600)","1:您好!受防疫措施变化影响,该目的地暂时无法提供此产品寄递服务,带来不便请您理解。(BPS5485) 50001 业务服务错误,SubCode:2136","收方地址存在双重目的地,请核实后重新填写地址下单。 15 Remote service error,SubCode:sf_response_fail-20064","未匹配到快递","电子面单账户余额不足 15 Remote service error,SubCode:waybill account not enough","货品[28554] [28554]缺货[1]","货品[28554] [28554]缺货[2]","货品[28554] [28554]缺货[3]","货品[28685] [28685]缺货[1]","货品[28685] [28685]缺货[3]","货品[502476708] [自然堂冰川水水光面膜(新规版)28mL×5片装]缺货[2]","货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(02代) 安瓶1.5mL+面膜33mL×5片装]缺货[2]","货品[502789400] [自然堂凝时小紫瓶精华液礼盒(品牌礼盒)]缺货[1]"],"type":"String","sampleRate":0.9618625319816094}',99079,0.02436278),('jala_wms_prod','shipment_header','requesteddeliverydate',28,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"1850341730105163776","lower":"1850341730105163776","count":2,"preSum":0},{"ndv":1,"upper":"1850370317407485952","lower":"1850370317407485952","count":2,"preSum":2},{"ndv":1,"upper":"1850396705686552576","lower":"1850396705686552576","count":1,"preSum":4},{"ndv":1,"upper":"1850403302756319232","lower":"1850403302756319232","count":1,"preSum":5},{"ndv":1,"upper":"1850484666616774656","lower":"1850484666616774656","count":1,"preSum":6}],"maxBucketSize":64,"type":"Date","sampleRate":0.9618625}','{"countArr":[99994],"valueArr":[-1],"type":"Date","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','requesteddeliverytype',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":["0"],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','reserveno',547,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":7215671,"lower":7215671,"count":1,"preSum":0},{"ndv":1,"upper":7422404,"lower":7422404,"count":1,"preSum":1},{"ndv":1,"upper":7462720,"lower":7462720,"count":1,"preSum":2},{"ndv":1,"upper":7462882,"lower":7462882,"count":1,"preSum":3},{"ndv":1,"upper":7463303,"lower":7463303,"count":1,"preSum":4},{"ndv":1,"upper":7478217,"lower":7478217,"count":1,"preSum":5},{"ndv":1,"upper":7479200,"lower":7479200,"count":1,"preSum":6},{"ndv":1,"upper":7480942,"lower":7480942,"count":1,"preSum":7},{"ndv":1,"upper":7480943,"lower":7480943,"count":1,"preSum":8},{"ndv":1,"upper":7480944,"lower":7480944,"count":1,"preSum":9},{"ndv":1,"upper":7489524,"lower":7489524,"count":1,"preSum":10},{"ndv":1,"upper":7489531,"lower":7489531,"count":1,"preSum":11},{"ndv":1,"upper":7495129,"lower":7495129,"count":1,"preSum":12},{"ndv":1,"upper":7495131,"lower":7495131,"count":1,"preSum":13},{"ndv":1,"upper":7503197,"lower":7503197,"count":1,"preSum":14},{"ndv":1,"upper":7521807,"lower":7521807,"count":1,"preSum":15},{"ndv":1,"upper":7523093,"lower":7523093,"count":1,"preSum":16},{"ndv":1,"upper":7524334,"lower":7524334,"count":1,"preSum":17},{"ndv":1,"upper":7524338,"lower":7524338,"count":1,"preSum":18},{"ndv":1,"upper":7524366,"lower":7524366,"count":1,"preSum":19},{"ndv":1,"upper":7524367,"lower":7524367,"count":1,"preSum":20},{"ndv":1,"upper":7524370,"lower":7524370,"count":1,"preSum":21},{"ndv":1,"upper":7524382,"lower":7524382,"count":1,"preSum":22},{"ndv":1,"upper":7524387,"lower":7524387,"count":1,"preSum":23},{"ndv":1,"upper":7524946,"lower":7524946,"count":1,"preSum":24},{"ndv":1,"upper":7546682,"lower":7546682,"count":1,"preSum":25},{"ndv":1,"upper":7563935,"lower":7563935,"count":1,"preSum":26},{"ndv":1,"upper":7571640,"lower":7571640,"count":1,"preSum":27},{"ndv":1,"upper":7572239,"lower":7572239,"count":1,"preSum":28},{"ndv":1,"upper":7572248,"lower":7572248,"count":1,"preSum":29},{"ndv":1,"upper":7637286,"lower":7637286,"count":1,"preSum":30},{"ndv":1,"upper":7731423,"lower":7731423,"count":1,"preSum":31},{"ndv":1,"upper":7731429,"lower":7731429,"count":1,"preSum":32},{"ndv":1,"upper":7989650,"lower":7989650,"count":1,"preSum":33},{"ndv":1,"upper":8071202,"lower":8071202,"count":2,"preSum":34},{"ndv":1,"upper":8176545,"lower":8176545,"count":1,"preSum":36},{"ndv":1,"upper":8219003,"lower":8219003,"count":1,"preSum":37},{"ndv":1,"upper":8223789,"lower":8223789,"count":1,"preSum":38},{"ndv":1,"upper":8224561,"lower":8224561,"count":1,"preSum":39},{"ndv":1,"upper":8226906,"lower":8226906,"count":1,"preSum":40},{"ndv":1,"upper":8317169,"lower":8317169,"count":1,"preSum":41},{"ndv":1,"upper":8346611,"lower":8346611,"count":1,"preSum":42},{"ndv":1,"upper":8427343,"lower":8427343,"count":1,"preSum":43},{"ndv":1,"upper":8522276,"lower":8522276,"count":1,"preSum":44},{"ndv":1,"upper":8530228,"lower":8530228,"count":1,"preSum":45},{"ndv":1,"upper":8530229,"lower":8530229,"count":1,"preSum":46},{"ndv":1,"upper":8534590,"lower":8534590,"count":1,"preSum":47},{"ndv":1,"upper":8554342,"lower":8554342,"count":1,"preSum":48},{"ndv":1,"upper":8555618,"lower":8555618,"count":1,"preSum":49},{"ndv":1,"upper":8560929,"lower":8560929,"count":1,"preSum":50},{"ndv":1,"upper":8564714,"lower":8564714,"count":1,"preSum":51},{"ndv":1,"upper":8572382,"lower":8572382,"count":1,"preSum":52},{"ndv":1,"upper":8572384,"lower":8572384,"count":1,"preSum":53}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[3],"valueArr":[8208697],"type":"Int","sampleRate":0.9618625319816094}',99944,0.02436278),('jala_wms_prod','shipment_header','route',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','routecode',77146,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":121,"upper":"(W31)024BE-000","lower":"(02)591TD-010","count":121,"preSum":0},{"ndv":121,"upper":"010WB-HG-134同","lower":"(W4)558D-008同","count":121,"preSum":121},{"ndv":119,"upper":"020RD-GD-EKBL034同","lower":"010WB-HK-083","count":121,"preSum":242},{"ndv":118,"upper":"021WG1-K-308同","lower":"020RD-GF-102B","count":121,"preSum":363},{"ndv":119,"upper":"022FB-048同","lower":"021WG1-KA-501","count":121,"preSum":484},{"ndv":119,"upper":"023W-DE-033","lower":"022FJ-012","count":121,"preSum":605},{"ndv":118,"upper":"025WA-GC-024同","lower":"023W-DE-042","count":121,"preSum":726},{"ndv":118,"upper":"027VC-077店","lower":"025WA-GC-051A","count":121,"preSum":847},{"ndv":116,"upper":"028W-N011-002","lower":"027VC-086A","count":121,"preSum":968},{"ndv":116,"upper":"029WA-EJ-022","lower":"028W-N028-000A","count":121,"preSum":1089},{"ndv":118,"upper":"029WE-GT-004","lower":"029WA-EJ-023","count":121,"preSum":1210},{"ndv":117,"upper":"121- 02-05 D30","lower":"029WE-GT-007","count":121,"preSum":1331},{"ndv":120,"upper":"235- 11-13 79","lower":"121- 03-04 59","count":121,"preSum":1452},{"ndv":120,"upper":"310EA-004同","lower":"235- 21-05 007","count":121,"preSum":1573},{"ndv":116,"upper":"313BG-027","lower":"310EGL-003","count":121,"preSum":1694},{"ndv":119,"upper":"319VA-L-010","lower":"313CA-070","count":121,"preSum":1815},{"ndv":117,"upper":"354DLD007-000","lower":"319VA-N-012","count":121,"preSum":1936},{"ndv":120,"upper":"371EJ-F16-004","lower":"354N-019","count":121,"preSum":2057},{"ndv":121,"upper":"377C-204同","lower":"371EL-A15-037A同","count":121,"preSum":2178},{"ndv":119,"upper":"396AD-003同","lower":"377C-205","count":121,"preSum":2299},{"ndv":119,"upper":"418VA-M-032","lower":"396AF-001","count":121,"preSum":2420},{"ndv":120,"upper":"433B-044","lower":"419D-044","count":121,"preSum":2541},{"ndv":120,"upper":"452AJ-000店","lower":"433C-039","count":121,"preSum":2662},{"ndv":117,"upper":"471- C-76 34B","lower":"452DLD079-000","count":121,"preSum":2783},{"ndv":119,"upper":"476BB-003","lower":"471- D-11 10F","count":121,"preSum":2904},{"ndv":120,"upper":"512DLD01Z-000A","lower":"476BE-DLD008000","count":121,"preSum":3025},{"ndv":117,"upper":"516TH-009同","lower":"512DLD02J-000","count":121,"preSum":3146},{"ndv":119,"upper":"531AH-034","lower":"516U-068同","count":121,"preSum":3267},{"ndv":120,"upper":"535WA-KE-010","lower":"531AK-004同","count":121,"preSum":3388},{"ndv":115,"upper":"551","lower":"535WA-KK-028","count":121,"preSum":3509},{"ndv":118,"upper":"559J-020B","lower":"551-564GD-019","count":121,"preSum":3630},{"ndv":121,"upper":"571WB-HL-028","lower":"561A-007同","count":121,"preSum":3751},{"ndv":120,"upper":"574WA-EU-C37-028","lower":"571WB-HN-058","count":121,"preSum":3872},{"ndv":117,"upper":"579W-JE-A7-015同","lower":"574WA-EV-B31-055","count":121,"preSum":3993},{"ndv":116,"upper":"595CQ-035A","lower":"579W-JE-A7-023","count":121,"preSum":4114},{"ndv":118,"upper":"631- H157-10 12","lower":"595CU-061同","count":121,"preSum":4235},{"ndv":118,"upper":"685- 70-1 505","lower":"631- I303-11 77","count":121,"preSum":4356},{"ndv":119,"upper":"714G-003","lower":"691A-202","count":121,"preSum":4477},{"ndv":118,"upper":"722G-014同","lower":"714G-045","count":121,"preSum":4598},{"ndv":117,"upper":"7311LD-059同","lower":"722G-022同","count":121,"preSum":4719},{"ndv":118,"upper":"736D023-000","lower":"7311LH-012同","count":121,"preSum":4840},{"ndv":117,"upper":"745VA-H-034","lower":"736D037-000","count":121,"preSum":4961},{"ndv":119,"upper":"753-753EB-012","lower":"745VA-J-045","count":121,"preSum":5082},{"ndv":116,"upper":"755WF-AL-128C","lower":"753-753TH-010","count":121,"preSum":5203},{"ndv":118,"upper":"757WA-BD-003C","lower":"755WF-AM-WAL017D","count":121,"preSum":5324},{"ndv":117,"upper":"760BC-A3-008B","lower":"757WA-BG-036D","count":121,"preSum":5445},{"ndv":120,"upper":"769WB-UB-010B","lower":"760BE-3-008B","count":121,"preSum":5566},{"ndv":117,"upper":"771AS-001","lower":"769WB-ZHEC-011A","count":121,"preSum":5687},{"ndv":118,"upper":"774D029-009","lower":"771BC-010","count":121,"preSum":5808},{"ndv":117,"upper":"791- 27 MD1","lower":"774D029-015","count":121,"preSum":5929},{"ndv":119,"upper":"797ZHN-022","lower":"791- 29 TS02","count":121,"preSum":6050},{"ndv":119,"upper":"818AD-021","lower":"797ZHN-031","count":121,"preSum":6171},{"ndv":116,"upper":"831J-025","lower":"818B-011","count":121,"preSum":6292},{"ndv":114,"upper":"851AG-002同","lower":"831J-051","count":121,"preSum":6413},{"ndv":113,"upper":"857DLD017000-DLD017000","lower":"851AG-012同","count":121,"preSum":6534},{"ndv":116,"upper":"871Z020-010","lower":"857DLD018-002","count":121,"preSum":6655},{"ndv":119,"upper":"879VA-E-009","lower":"871Z027-012","count":121,"preSum":6776},{"ndv":116,"upper":"901BB-008同","lower":"879VA-JC-004同","count":121,"preSum":6897},{"ndv":116,"upper":"917DLD041-000","lower":"901C- 23-01 LSA2","count":121,"preSum":7018},{"ndv":116,"upper":"934KB-002","lower":"917DLD045-999","count":121,"preSum":7139},{"ndv":117,"upper":"951CAL-009","lower":"934M-102","count":121,"preSum":7260},{"ndv":118,"upper":"992AD-036","lower":"951CB-005","count":121,"preSum":7381},{"ndv":116,"upper":"T10-A-512GQ-077","lower":"993","count":121,"preSum":7502},{"ndv":82,"upper":"ZW5-519C-067","lower":"T14-A-512THH-008","count":83,"preSum":7623}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[28,3,3,3,3,3,3,3,3,5,3,3,3],"valueArr":["","010W-010","053","376D035000-D006000","431ZHF-012","512","738DLD004-000","755W-BF-051","755WM-DTL-008同","769WF-769","790- 01-17 E1","892DLD003-000","953VA-C-014"],"type":"String","sampleRate":0.9618625319816094}',92229,0.02436278),('jala_wms_prod','shipment_header','scheduledshipdate',384,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":"1850348327174930432","lower":"1850330734988886016","count":23,"preSum":0},{"ndv":5,"upper":"1850363720337719296","lower":"1850350526198185984","count":13,"preSum":23},{"ndv":4,"upper":"1850376914477252608","lower":"1850365919360974848","count":11,"preSum":36},{"ndv":4,"upper":"1850398904709808128","lower":"1850383511547019264","count":13,"preSum":47},{"ndv":1,"upper":"1850401103733063680","lower":"1850401103733063680","count":11,"preSum":60},{"ndv":4,"upper":"1850427492012130304","lower":"1850407700802830336","count":11,"preSum":71},{"ndv":2,"upper":"1850436288105152512","lower":"1850434089081896960","count":15,"preSum":82},{"ndv":5,"upper":"1850464875407474688","lower":"1850442885174919168","count":22,"preSum":97},{"ndv":1,"upper":"1850467074430730240","lower":"1850467074430730240","count":14,"preSum":119},{"ndv":3,"upper":"1850480268570263552","lower":"1850473671500496896","count":27,"preSum":133},{"ndv":1,"upper":"1850482467593519104","lower":"1850482467593519104","count":23,"preSum":160},{"ndv":2,"upper":"1850500059779563520","lower":"1850497860756307968","count":20,"preSum":183},{"ndv":4,"upper":"1850530846105141248","lower":"1850511054895841280","count":23,"preSum":203},{"ndv":1,"upper":"1850546239267930112","lower":"1850546239267930112","count":14,"preSum":226},{"ndv":1,"upper":"1850566030477230080","lower":"1850566030477230080","count":24,"preSum":240},{"ndv":3,"upper":"1850581423640018944","lower":"1850577025593507840","count":18,"preSum":264},{"ndv":3,"upper":"1850592418756296704","lower":"1850585821686530048","count":14,"preSum":282},{"ndv":4,"upper":"1850623205081874432","lower":"1850596816802807808","count":11,"preSum":296},{"ndv":2,"upper":"1850700170895818752","lower":"1850625404105129984","count":22,"preSum":307},{"ndv":3,"upper":"1850715564058607616","lower":"1850711166012096512","count":22,"preSum":329},{"ndv":3,"upper":"1850724360151629824","lower":"1850719962105118720","count":14,"preSum":351},{"ndv":2,"upper":"1850730957221396480","lower":"1850728758198140928","count":20,"preSum":365},{"ndv":5,"upper":"1850785932802785280","lower":"1850759544523718656","count":15,"preSum":385},{"ndv":1,"upper":"1850794728895807488","lower":"1850794728895807488","count":20,"preSum":400},{"ndv":3,"upper":"1850810122058596352","lower":"1850801325965574144","count":15,"preSum":420},{"ndv":3,"upper":"1850849704477196288","lower":"1850814520105107456","count":15,"preSum":435},{"ndv":4,"upper":"1850862898616729600","lower":"1850854102523707392","count":16,"preSum":450},{"ndv":1,"upper":"1850865097639985152","lower":"1850865097639985152","count":21,"preSum":466},{"ndv":4,"upper":"1850880490802774016","lower":"1850869495686496256","count":34,"preSum":487},{"ndv":7,"upper":"1850928869314396160","lower":"1850884888849285120","count":30,"preSum":521},{"ndv":4,"upper":"1850944262477185024","lower":"1850933267360907264","count":28,"preSum":551},{"ndv":5,"upper":"1850972849779507200","lower":"1850959655639973888","count":12,"preSum":579},{"ndv":4,"upper":"1851010233174851584","lower":"1850999238058573824","count":30,"preSum":591},{"ndv":5,"upper":"1851038820477173760","lower":"1851012432198107136","count":15,"preSum":621},{"ndv":5,"upper":"1851071805826007040","lower":"1851054213639962624","count":11,"preSum":636},{"ndv":1,"upper":"1851074004849262592","lower":"1851074004849262592","count":17,"preSum":647},{"ndv":7,"upper":"1851104791174840320","lower":"1851078402895773696","count":27,"preSum":664},{"ndv":3,"upper":"1851124582384140288","lower":"1851106990198095872","count":8,"preSum":691}],"maxBucketSize":64,"type":"Date","sampleRate":0.9618625}','{"countArr":[98808,58,29,60,29,33,28,26,29,45,52,72,33],"valueArr":[-1,1850370317407485952,1850385710570274816,1850420894942363648,1850451681267941376,1850515452942352384,1850779335733018624,1850825515221385216,1850913476151607296,1850975048802762752,1851025626337640448,1851041019500429312,1851089398012051456],"type":"Date","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','secondsectioncode',11448,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":11,"upper":"01-11","lower":"01-01C","count":55,"preSum":0},{"ndv":12,"upper":"01-21","lower":"01-12","count":57,"preSum":55},{"ndv":27,"upper":"01-64","lower":"01-23","count":55,"preSum":112},{"ndv":17,"upper":"02-05","lower":"01-67","count":54,"preSum":167},{"ndv":22,"upper":"03-02","lower":"02-06","count":55,"preSum":221},{"ndv":9,"upper":"03-12","lower":"03-04","count":58,"preSum":276},{"ndv":23,"upper":"04-05","lower":"03-13","count":57,"preSum":334},{"ndv":22,"upper":"05-02","lower":"04-06","count":56,"preSum":391},{"ndv":7,"upper":"05-09","lower":"05-03","count":56,"preSum":447},{"ndv":19,"upper":"06-03","lower":"05-10","count":60,"preSum":503},{"ndv":11,"upper":"06-16","lower":"06-04","count":54,"preSum":563},{"ndv":17,"upper":"07-07","lower":"06-18","count":55,"preSum":617},{"ndv":27,"upper":"08-A","lower":"07-09","count":56,"preSum":672},{"ndv":24,"upper":"1","lower":"08E-13","count":54,"preSum":728},{"ndv":21,"upper":"10-07","lower":"1-01","count":54,"preSum":782},{"ndv":30,"upper":"11-02","lower":"10-08","count":55,"preSum":836},{"ndv":25,"upper":"12-02","lower":"11-03","count":60,"preSum":891},{"ndv":25,"upper":"13-00","lower":"12-03","count":54,"preSum":951},{"ndv":24,"upper":"14-06","lower":"13-02","count":59,"preSum":1005},{"ndv":31,"upper":"152","lower":"14-09","count":54,"preSum":1064},{"ndv":18,"upper":"17-03","lower":"16","count":54,"preSum":1118},{"ndv":23,"upper":"18-02","lower":"17-04","count":56,"preSum":1172},{"ndv":33,"upper":"2-1","lower":"18-04","count":58,"preSum":1228},{"ndv":31,"upper":"21-02","lower":"2-10","count":56,"preSum":1286},{"ndv":20,"upper":"22-03","lower":"21-03","count":54,"preSum":1342},{"ndv":24,"upper":"24-06","lower":"22-05","count":54,"preSum":1396},{"ndv":35,"upper":"29","lower":"24-09","count":56,"preSum":1450},{"ndv":19,"upper":"30-05","lower":"29-01","count":54,"preSum":1506},{"ndv":29,"upper":"36","lower":"30-15","count":59,"preSum":1560},{"ndv":22,"upper":"4-6","lower":"36-01","count":56,"preSum":1619},{"ndv":40,"upper":"445","lower":"4-60","count":54,"preSum":1675},{"ndv":41,"upper":"490","lower":"448","count":54,"preSum":1729},{"ndv":21,"upper":"51-01","lower":"490-95","count":55,"preSum":1783},{"ndv":29,"upper":"57-06","lower":"51-05","count":54,"preSum":1838},{"ndv":37,"upper":"65-23","lower":"57-12","count":54,"preSum":1892},{"ndv":31,"upper":"70-20","lower":"65-44","count":54,"preSum":1946},{"ndv":38,"upper":"765","lower":"70-25","count":54,"preSum":2000},{"ndv":40,"upper":"823","lower":"771","count":55,"preSum":2054},{"ndv":28,"upper":"A-09","lower":"84","count":56,"preSum":2109},{"ndv":30,"upper":"A-700","lower":"A-1","count":54,"preSum":2165},{"ndv":36,"upper":"A28","lower":"A-89","count":54,"preSum":2219},{"ndv":39,"upper":"B-03","lower":"A29","count":55,"preSum":2273},{"ndv":30,"upper":"B-85","lower":"B-04","count":54,"preSum":2328},{"ndv":43,"upper":"B39","lower":"B-S40","count":54,"preSum":2382},{"ndv":38,"upper":"C-04","lower":"B4","count":55,"preSum":2436},{"ndv":37,"upper":"C07","lower":"C-05","count":54,"preSum":2491},{"ndv":44,"upper":"C51","lower":"C07-01","count":55,"preSum":2545},{"ndv":42,"upper":"D-06","lower":"C57","count":54,"preSum":2600},{"ndv":36,"upper":"D15","lower":"D-08","count":54,"preSum":2654},{"ndv":38,"upper":"D50-62","lower":"D21","count":54,"preSum":2708},{"ndv":39,"upper":"E-202","lower":"D52","count":54,"preSum":2762},{"ndv":37,"upper":"E21-22","lower":"E-203","count":54,"preSum":2816},{"ndv":43,"upper":"F23-01","lower":"E21-23","count":54,"preSum":2870},{"ndv":40,"upper":"G141","lower":"F27","count":54,"preSum":2924},{"ndv":36,"upper":"H90","lower":"G293","count":56,"preSum":2978},{"ndv":36,"upper":"K03","lower":"H99-10","count":55,"preSum":3034},{"ndv":42,"upper":"L4","lower":"K04-20","count":54,"preSum":3089},{"ndv":37,"upper":"M99-08","lower":"L67-07","count":55,"preSum":3143},{"ndv":36,"upper":"R-07","lower":"M99-09","count":54,"preSum":3198},{"ndv":37,"upper":"T-07","lower":"R-1B","count":54,"preSum":3252},{"ndv":34,"upper":"Y-01","lower":"T-08","count":58,"preSum":3306},{"ndv":35,"upper":"ZH-034","lower":"Y-03","count":50,"preSum":3364}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[17,15,19,17,16,16,18,15,19,19,20,20],"valueArr":["01-01","01-02","01-03","03-01","03-03","04-01","05-01","06-02","09-01","11-01","12-01","13-01"],"type":"String","sampleRate":0.9618625319816094}',96376,0.02436278),('jala_wms_prod','shipment_header','secondwaybillcodes',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','sellerto',997,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":5,"upper":"1000262","lower":"1000198","count":42,"preSum":0},{"ndv":6,"upper":"1000291","lower":"1000264","count":33,"preSum":42},{"ndv":2,"upper":"1000309","lower":"1000299","count":35,"preSum":75},{"ndv":2,"upper":"1000319","lower":"1000318","count":42,"preSum":110},{"ndv":7,"upper":"1000351","lower":"1000331","count":30,"preSum":152},{"ndv":8,"upper":"1000370","lower":"1000355","count":32,"preSum":182},{"ndv":3,"upper":"1000389","lower":"1000375","count":31,"preSum":214},{"ndv":1,"upper":"1000390","lower":"1000390","count":30,"preSum":245},{"ndv":7,"upper":"1000413","lower":"1000395","count":53,"preSum":275},{"ndv":6,"upper":"1000438","lower":"1000414","count":34,"preSum":328},{"ndv":6,"upper":"1000457","lower":"1000439","count":32,"preSum":362},{"ndv":5,"upper":"1000482","lower":"1000465","count":30,"preSum":394},{"ndv":6,"upper":"1000500","lower":"1000484","count":30,"preSum":424},{"ndv":5,"upper":"1000529","lower":"1000501","count":32,"preSum":454},{"ndv":8,"upper":"1000605","lower":"1000532","count":34,"preSum":486},{"ndv":4,"upper":"1000698","lower":"1000608","count":52,"preSum":520},{"ndv":6,"upper":"1000818","lower":"1000724","count":45,"preSum":572},{"ndv":4,"upper":"1000848","lower":"1000832","count":31,"preSum":617},{"ndv":4,"upper":"1000901","lower":"1000861","count":42,"preSum":648},{"ndv":5,"upper":"1001005","lower":"1000928","count":32,"preSum":690},{"ndv":9,"upper":"1001067","lower":"1001006","count":30,"preSum":722},{"ndv":3,"upper":"1001080","lower":"1001078","count":35,"preSum":752},{"ndv":4,"upper":"1001085","lower":"1001081","count":55,"preSum":787},{"ndv":10,"upper":"1001184","lower":"1001088","count":31,"preSum":842},{"ndv":17,"upper":"1001390","lower":"1001208","count":30,"preSum":873},{"ndv":19,"upper":"1001629","lower":"1001392","count":34,"preSum":903},{"ndv":7,"upper":"1001772","lower":"1001655","count":46,"preSum":937},{"ndv":9,"upper":"1001856","lower":"1001781","count":33,"preSum":983},{"ndv":11,"upper":"1002043","lower":"1001865","count":33,"preSum":1016},{"ndv":8,"upper":"1002075","lower":"1002047","count":41,"preSum":1049},{"ndv":4,"upper":"1002098","lower":"1002083","count":31,"preSum":1090},{"ndv":8,"upper":"1002173","lower":"1002099","count":31,"preSum":1121},{"ndv":7,"upper":"1002229","lower":"1002178","count":40,"preSum":1152},{"ndv":2,"upper":"1002257","lower":"1002256","count":31,"preSum":1192},{"ndv":6,"upper":"1002312","lower":"1002277","count":32,"preSum":1223},{"ndv":6,"upper":"1002430","lower":"1002341","count":39,"preSum":1255},{"ndv":13,"upper":"1002535","lower":"1002441","count":30,"preSum":1294},{"ndv":12,"upper":"1002658","lower":"1002563","count":41,"preSum":1324},{"ndv":4,"upper":"1002679","lower":"1002660","count":43,"preSum":1365},{"ndv":13,"upper":"1002789","lower":"1002680","count":32,"preSum":1408},{"ndv":9,"upper":"1002831","lower":"1002794","count":30,"preSum":1440},{"ndv":9,"upper":"1002952","lower":"1002835","count":33,"preSum":1470},{"ndv":10,"upper":"9992","lower":"1002953","count":46,"preSum":1503},{"ndv":8,"upper":"D017","lower":"C001","count":37,"preSum":1549},{"ndv":8,"upper":"R15E","lower":"DJ01","count":30,"preSum":1586},{"ndv":7,"upper":"S004-1000","lower":"R18A","count":41,"preSum":1616},{"ndv":3,"upper":"S007-1000","lower":"S005-1000","count":41,"preSum":1657},{"ndv":2,"upper":"S102-1000","lower":"S101-1000","count":33,"preSum":1698},{"ndv":1,"upper":"S103-1000","lower":"S103-1000","count":30,"preSum":1731},{"ndv":2,"upper":"S106-1000","lower":"S104-1000","count":35,"preSum":1761},{"ndv":4,"upper":"S112-1000","lower":"S107-1000","count":51,"preSum":1796},{"ndv":2,"upper":"S115-1000","lower":"S113-1000","count":38,"preSum":1847}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[426,45,33,32,37,96,154,33,144,61,60,35,47,33],"valueArr":["","1000183","1000292","1000313","1000650","1000746","1000767","1000792","1002333","1002871","9914","9998","S001-1000","S105-1000"],"type":"String","sampleRate":0.9618625319816094}',96880,0.02436278),('jala_wms_prod','shipment_header','servicemode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','sfweightprocess',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[7149,68608],"valueArr":["N","Y"],"type":"String","sampleRate":0.9618625319816094}',24244,0.02436278),('jala_wms_prod','shipment_header','shipdock',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory1',20,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"23","lower":"23","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[96083,67,1213,412,60,60,14,81,4,177,153],"valueArr":["","10","A","B","C","D","E","G","K","Q","Z"],"type":"String","sampleRate":0.9618625319816094}',1676,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory2',19,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"23","lower":"23","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[96132,148,375,70,5,29,1474,4,52,35],"valueArr":["","同城","商超","屈臣氏","特通","电商","美妆","美妆-KA","美妆-RKA","货架"],"type":"String","sampleRate":0.9618625319816094}',1676,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory3',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[26,2094],"valueArr":["","3"],"type":"String","sampleRate":0.9618625319816094}',97881,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory4',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[23,81755,12772],"valueArr":["","自营","非自营"],"type":"String","sampleRate":0.9618625319816094}',5451,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory5',192,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":10,"upper":"全品牌-人资福利店铺(日常)","lower":"Chando-LazadaMYHimalaya(日常)","count":266,"preSum":0},{"ndv":9,"upper":"春夏-天猫旗舰店(日常)","lower":"全品牌-优礼汇特通店铺(日常)","count":459,"preSum":266},{"ndv":6,"upper":"植物智慧-天猫旗舰店(日常)","lower":"春夏-天猫旗舰店(派样)","count":228,"preSum":725},{"ndv":3,"upper":"珀芙研-云店(日常)","lower":"植物智慧-抖音美妆官方店(日常)","count":218,"preSum":953},{"ndv":6,"upper":"珀芙研-抖音小店(日常)","lower":"珀芙研-京东POP旗舰店(日常)","count":385,"preSum":1171},{"ndv":3,"upper":"珀芙研-蘑菇街旗舰店(日常)","lower":"珀芙研-泛斯特店(日常)","count":646,"preSum":1556},{"ndv":2,"upper":"美素-天猫旗舰店(日常)","lower":"美素-京东POP官方旗舰店(日常)","count":331,"preSum":2202},{"ndv":6,"upper":"自然堂-云店(官方商城)(日常)","lower":"美素-天猫旗舰店(派样)","count":415,"preSum":2533},{"ndv":3,"upper":"自然堂-京东POP旗舰店(派样)","lower":"自然堂-云店(美妆2.0)(日常)","count":262,"preSum":2948},{"ndv":1,"upper":"自然堂-京东乐肤迪官方旗舰店(日常)","lower":"自然堂-京东乐肤迪官方旗舰店(日常)","count":224,"preSum":3210},{"ndv":1,"upper":"自然堂-京东充花专卖店(日常)","lower":"自然堂-京东充花专卖店(日常)","count":335,"preSum":3434},{"ndv":1,"upper":"自然堂-京东彧弈美妆专营店(日常)","lower":"自然堂-京东彧弈美妆专营店(日常)","count":320,"preSum":3769},{"ndv":2,"upper":"自然堂-京东悦悦美铺化妆品专营店(日常)","lower":"自然堂-京东思琪化妆品专营店(日常)","count":293,"preSum":4089},{"ndv":5,"upper":"自然堂-京东每妆护肤旗舰店(日常)","lower":"自然堂-京东晟妆专卖店(日常)","count":299,"preSum":4382},{"ndv":2,"upper":"自然堂-京东然美专卖店(日常)","lower":"自然堂-京东泽品美妆化妆品专营店(日常)","count":355,"preSum":4681},{"ndv":1,"upper":"自然堂-京东硕齐化妆品专营店(日常)","lower":"自然堂-京东硕齐化妆品专营店(日常)","count":323,"preSum":5036},{"ndv":1,"upper":"自然堂-京东美姿专卖店(日常)","lower":"自然堂-京东美姿专卖店(日常)","count":675,"preSum":5359},{"ndv":1,"upper":"自然堂-京东美爆化妆品专营店(日常)","lower":"自然堂-京东美爆化妆品专营店(日常)","count":424,"preSum":6034},{"ndv":4,"upper":"自然堂-品牌专卖1店(日常)","lower":"自然堂-京东美轩美妆(日常)","count":261,"preSum":6458},{"ndv":1,"upper":"自然堂-品牌专卖2店(日常)","lower":"自然堂-品牌专卖2店(日常)","count":430,"preSum":6719},{"ndv":6,"upper":"自然堂-天猫伊恋化妆品专营店(日常)","lower":"自然堂-品牌专卖3店(日常)","count":566,"preSum":7149},{"ndv":2,"upper":"自然堂-天猫俏美人专卖店(日常)","lower":"自然堂-天猫优购化妆品专营店(日常)","count":340,"preSum":7715},{"ndv":2,"upper":"自然堂-天猫名轩专卖店(日常)","lower":"自然堂-天猫博美化妆品专营店(日常)","count":556,"preSum":8055},{"ndv":1,"upper":"自然堂-天猫思琪化妆品专营店(日常)","lower":"自然堂-天猫思琪化妆品专营店(日常)","count":634,"preSum":8611},{"ndv":1,"upper":"自然堂-天猫杰宸专卖店(日常)","lower":"自然堂-天猫杰宸专卖店(日常)","count":716,"preSum":9245},{"ndv":1,"upper":"自然堂-天猫永信化妆品专营店(日常)","lower":"自然堂-天猫永信化妆品专营店(日常)","count":222,"preSum":9961},{"ndv":1,"upper":"自然堂-天猫泽品化妆品专营店(日常)","lower":"自然堂-天猫泽品化妆品专营店(日常)","count":222,"preSum":10183},{"ndv":2,"upper":"自然堂-天猫硕齐化妆品专营店(日常)","lower":"自然堂-天猫男士旗舰店(派样)","count":485,"preSum":10405},{"ndv":3,"upper":"自然堂-小红书旗舰店(日常)","lower":"自然堂-小程序官方商城(日常)","count":528,"preSum":10890},{"ndv":2,"upper":"自然堂-抖音CHANDO男士旗舰店(日常)","lower":"自然堂-快手官方旗舰店(派样)","count":587,"preSum":11418},{"ndv":2,"upper":"自然堂-抖音官方旗舰店(派样)","lower":"自然堂-抖音CHANDO男士旗舰店(派样)","count":594,"preSum":12005},{"ndv":4,"upper":"自然堂-拼多多奕初专卖店(日常)","lower":"自然堂-抖音美妆旗舰店(派样)","count":229,"preSum":12599},{"ndv":14,"upper":"自然堂-淘宝zhangmin811028(日常)","lower":"自然堂-拼多多尧美专卖店(日常)","count":265,"preSum":12828},{"ndv":3,"upper":"自然堂-考拉旗舰店(日常)","lower":"自然堂-淘宝化妆品折扣店(日常)","count":302,"preSum":13093},{"ndv":4,"upper":"莎辛那-天猫旗舰店(派样)","lower":"自然堂-蘑菇街旗舰店(日常)","count":205,"preSum":13395}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2115,1175,1282,1083,6924,45974,1311,1650,1174,2211,1046,835,11289,2932],"valueArr":["","珀芙研-天猫旗舰店(日常)","自然堂-京东POP旗舰店(日常)","自然堂-京东京品美妆专卖店(日常)","自然堂-唯品会自营旗舰店(中国)(日常)","自然堂-天猫旗舰店(日常)","自然堂-天猫旗舰店(派样)","自然堂-天猫朵纯专卖店(日常)","自然堂-天猫然美专卖店(日常)","自然堂-天猫男士旗舰店(日常)","自然堂-天猫门萨专卖店(日常)","自然堂-快手官方旗舰店(日常)","自然堂-抖音官方旗舰店(日常)","自然堂-抖音美妆旗舰店(日常)"],"type":"String","sampleRate":0.9618625319816094}',5400,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory6',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory7',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory8',45,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"2C单票>30件单波1单波次","lower":"","count":34,"preSum":0},{"ndv":1,"upper":"2C国际单出库波次","lower":"2C国际单出库波次","count":159,"preSum":34},{"ndv":2,"upper":"2C提总波次(预付款已付尾款)","lower":"2C提总单波次(预付款未付尾款)","count":201,"preSum":193},{"ndv":1,"upper":"2C提总波次(预售已付尾款)","lower":"2C提总波次(预售已付尾款)","count":160,"preSum":394},{"ndv":1,"upper":"2C散单波次(预付款已付尾款)\\t","lower":"2C散单波次(预付款已付尾款)\\t","count":28,"preSum":554},{"ndv":1,"upper":"2C散单波次(预付款已付尾款)","lower":"2C散单波次(预付款已付尾款)","count":51,"preSum":582},{"ndv":1,"upper":"2C散单波次(预售已付尾款)","lower":"2C散单波次(预售已付尾款)","count":140,"preSum":633},{"ndv":1,"upper":"2C散单波次(预售未付尾款)","lower":"2C散单波次(预售未付尾款)","count":51,"preSum":773},{"ndv":3,"upper":"新1.0-2C提总波次(存储区出库)","lower":"2C调拨出库波次","count":126,"preSum":824},{"ndv":2,"upper":"春夏2C非天猫提总波次","lower":"春夏2C天猫散单波次","count":153,"preSum":950},{"ndv":1,"upper":"珀芙研2C正常提总波次","lower":"珀芙研2C正常提总波次","count":124,"preSum":1103},{"ndv":4,"upper":"自然堂2C唯品会提总波次","lower":"珀芙研2C正常散单波次","count":55,"preSum":1227},{"ndv":1,"upper":"自然堂2C唯品会散单波次","lower":"自然堂2C唯品会散单波次","count":162,"preSum":1282},{"ndv":1,"upper":"自然堂2C正常散单波次","lower":"自然堂2C正常散单波次","count":117,"preSum":1444},{"ndv":1,"upper":"自然堂2C预付款散单已付尾款波次","lower":"自然堂2C预付款散单已付尾款波次","count":125,"preSum":1561}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[24270,393,5721,318,2100,3221,45747,325,609,4176,763,783,507,553],"valueArr":["2C提总单波次","2C提总单波次(预付款已付尾款)","2C提总波次","2C提总波次(预付款未付尾款)","2C提总波次(预售未付尾款)","2C提总波次(存储区出库)","2C散单波次","2C预包单提总单波次","提总-2C预付款已付尾款指定库位发货波次","提总-自然堂2C预付款已付尾款指定库位发货波次","提总-自然堂618指定库位发货波次","自然堂2C正常提总波次","自然堂2C预付款提总已付尾款波次","自然堂2C预付款提总未付尾款波次"],"type":"String","sampleRate":0.9618625319816094}',8829,0.02436278),('jala_wms_prod','shipment_header','shipmentnote',2522375,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1455,"upper":"JD20230536183063220;","lower":"01仓的产品请不要发超允收期(效期1/3-3个月)的产品","count":1511,"preSum":0},{"ndv":1511,"upper":"JX07230553279191226;","lower":"JD20230536631975406;","count":1511,"preSum":1511},{"ndv":1511,"upper":"JX10230544614844604;","lower":"JX07230553323668828;","count":1511,"preSum":3022},{"ndv":1511,"upper":"JX12230659373287001;","lower":"JX10230544614844904;","count":1511,"preSum":4533},{"ndv":1511,"upper":"JX15230541585052302;","lower":"JX12230659427547906;","count":1511,"preSum":6044},{"ndv":1511,"upper":"JX18230405537350025;","lower":"JX15230541630711406;","count":1511,"preSum":7555},{"ndv":1511,"upper":"JX20230535610442703;","lower":"JX18230405572657830;","count":1511,"preSum":9066},{"ndv":1511,"upper":"JX21230643455930610;","lower":"JX20230535638302507;","count":1511,"preSum":10577},{"ndv":1511,"upper":"JX23230526366145631;","lower":"JX21230643468227912;","count":1511,"preSum":12088},{"ndv":1501,"upper":"OD10230645410084804;","lower":"JX23230526366151531;","count":1511,"preSum":13599},{"ndv":1511,"upper":"OD16230504336266729;","lower":"OD10230645481902515;","count":1511,"preSum":15110},{"ndv":1509,"upper":"SD00230526646133109;","lower":"OD16230504336267429;","count":1511,"preSum":16621},{"ndv":1511,"upper":"SD01230436562440229;","lower":"SD00230526653561710;","count":1511,"preSum":18132},{"ndv":1511,"upper":"SD01230649495391316;","lower":"SD01230436562440329;","count":1511,"preSum":19643},{"ndv":1511,"upper":"SD03230609578925622;","lower":"SD01230649495400016;","count":1511,"preSum":21154},{"ndv":1510,"upper":"SD09230550262141223;","lower":"SD03230609598349227;","count":1511,"preSum":22665},{"ndv":1511,"upper":"SD11230419535194525;","lower":"SD09230550582823202;","count":1511,"preSum":24176},{"ndv":1511,"upper":"SD12230506680406713;","lower":"SD11230419535195125;","count":1511,"preSum":25687},{"ndv":1511,"upper":"SD13230534687696614;","lower":"SD12230506680407413;","count":1511,"preSum":27198},{"ndv":1511,"upper":"SD14230525281050226;","lower":"SD13230534787222416;","count":1511,"preSum":28709},{"ndv":1511,"upper":"SD15230529920417617;","lower":"SD14230526623141605;","count":1511,"preSum":30220},{"ndv":1509,"upper":"SD16230544337076329;","lower":"SD15230530796505716;","count":1511,"preSum":31731},{"ndv":1511,"upper":"SD17230559319934227;","lower":"SD16230544353742131;","count":1511,"preSum":33242},{"ndv":1511,"upper":"SD19230401537548725;","lower":"SD17230559319935027;","count":1511,"preSum":34753},{"ndv":1511,"upper":"SD20230509942427917;","lower":"SD19230404510404721;","count":1511,"preSum":36264},{"ndv":1511,"upper":"SD21230548265665723;","lower":"SD20230510258796222;","count":1511,"preSum":37775},{"ndv":1511,"upper":"SD22230529283786826;","lower":"SD21230548265665823;","count":1511,"preSum":39286},{"ndv":1511,"upper":"SD23230524260747722;","lower":"SD22230529283788426;","count":1511,"preSum":40797},{"ndv":1511,"upper":"SDC1123040516565822;","lower":"SD23230524260747822;","count":1511,"preSum":42308},{"ndv":1511,"upper":"TB00230613550538219;","lower":"SDC1123040516566022;","count":1511,"preSum":43819},{"ndv":1511,"upper":"TB04230512331028729;","lower":"TB00230613550538919;","count":1511,"preSum":45330},{"ndv":1511,"upper":"TB08230422458785514;","lower":"TB04230513284882327;","count":1511,"preSum":46841},{"ndv":1511,"upper":"TB09230510634913607;","lower":"TB08230422505595521;","count":1511,"preSum":48352},{"ndv":1511,"upper":"TB09230541288643027;","lower":"TB09230510634916507;","count":1511,"preSum":49863},{"ndv":1511,"upper":"TB09230553292722627;","lower":"TB09230541288643227;","count":1511,"preSum":51374},{"ndv":1511,"upper":"TB10230419547434727;","lower":"TB09230553292724827;","count":1511,"preSum":52885},{"ndv":1509,"upper":"TB10230516300318527;","lower":"TB10230419547436627;","count":1511,"preSum":54396},{"ndv":1503,"upper":"TB10230531305394927;","lower":"TB10230516300336527;","count":1511,"preSum":55907},{"ndv":1511,"upper":"TB10230545310518327;","lower":"TB10230531305397227;","count":1511,"preSum":57418},{"ndv":1511,"upper":"TB10230604595087426;","lower":"TB10230545310529627;","count":1511,"preSum":58929},{"ndv":1509,"upper":"TB11230507686568414;","lower":"TB10230604595088726;","count":1511,"preSum":60440},{"ndv":1510,"upper":"TB11230655565714820;","lower":"TB11230508315875727;","count":1511,"preSum":61951},{"ndv":1509,"upper":"TB12230557333461929;","lower":"TB11230655575064121;","count":1511,"preSum":63462},{"ndv":1511,"upper":"TB13230507664600311;","lower":"TB12230558095195019;","count":1511,"preSum":64973},{"ndv":1511,"upper":"TB14230228121516825;","lower":"TB13230507664600411;","count":1511,"preSum":66484},{"ndv":1511,"upper":"TB14230640535806318;","lower":"TB14230228121517625;","count":1511,"preSum":67995},{"ndv":1510,"upper":"TB15230623460068711;","lower":"TB14230640535808718;","count":1511,"preSum":69506},{"ndv":1510,"upper":"TB16230558275778325;","lower":"TB15230623466291112;","count":1511,"preSum":71017},{"ndv":1511,"upper":"TB17230528337625029;","lower":"TB16230558319460627;","count":1511,"preSum":72528},{"ndv":1510,"upper":"TB18230525327402128;","lower":"TB17230528578851901;","count":1511,"preSum":74039},{"ndv":1511,"upper":"TB19230519938625317;","lower":"TB18230525579160801;","count":1511,"preSum":75550},{"ndv":1511,"upper":"TB20230349335599123;","lower":"TB19230519938625917;","count":1511,"preSum":77061},{"ndv":1511,"upper":"TB20230534821533516;","lower":"TB20230349340643324;","count":1511,"preSum":78572},{"ndv":1511,"upper":"TB20230629487025415;","lower":"TB20230534821535316;","count":1511,"preSum":80083},{"ndv":1511,"upper":"TB21230501721888715;","lower":"TB20230629487033615;","count":1511,"preSum":81594},{"ndv":1511,"upper":"TB21230534677305312;","lower":"TB21230501721889815;","count":1511,"preSum":83105},{"ndv":1511,"upper":"TB21230628380051601;","lower":"TB21230534677305412;","count":1511,"preSum":84616},{"ndv":1511,"upper":"TB22230419408353205;","lower":"TB21230628380058001;","count":1511,"preSum":86127},{"ndv":1511,"upper":"TB22230526834119716;","lower":"TB22230419450286312;","count":1511,"preSum":87638},{"ndv":1509,"upper":"TB22230616394594002;","lower":"TB22230526834120016;","count":1511,"preSum":89149},{"ndv":1511,"upper":"TB23230225106541922;","lower":"TB22230616394600502;","count":1511,"preSum":90660},{"ndv":1510,"upper":"TB23230540653238709;","lower":"TB23230225106542422;","count":1511,"preSum":92171},{"ndv":1511,"upper":"TB23230637474978913;","lower":"TB23230540653239109;","count":1511,"preSum":93682},{"ndv":1253,"upper":"(面贴膜)4送1配送;","lower":"TB23230637510188416;","count":1460,"preSum":95193}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[15,14,222,29,11,14,27,25,38,10,21,44,24],"valueArr":["","京东POP","日常配发","本地零售还货0401-0414 & 3月借货补货单","本地零售还货0415-0428借货补货单","本地零售还货0429-0512借货补货单","本地零售还货0513-0526&0527-0609&0501-0526借货补货单","本地零售还货0527-0609换货&0610-0623还货借货补货单","本地零售还货4月&0429-0512&0513-0526借货补货单","活动备货","美妆 自然堂2023彩妆陈列- 眉笔、眼线笔物料配发","营运部调拨","营运部调拨需求"],"type":"String","sampleRate":0.9618625319816094}',2854,0.02436278),('jala_wms_prod','shipment_header','shipmentsubtype',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[148,89044,10809],"valueArr":["","NORMAL_ORDER","PRE_WAREHOUSE"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','shipmenttype',36,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"BFCK","lower":"BFCK","count":4,"preSum":0},{"ndv":1,"upper":"CGTH","lower":"CGTH","count":4,"preSum":4},{"ndv":1,"upper":"CTCK","lower":"CTCK","count":1,"preSum":8},{"ndv":1,"upper":"MM010","lower":"MM010","count":1,"preSum":9},{"ndv":1,"upper":"NBL","lower":"NBL","count":2,"preSum":10},{"ndv":1,"upper":"SAP-MM011","lower":"SAP-MM011","count":1,"preSum":12}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[57,2614,425,95405,5,13,13,60,578,681,5,9,18,105],"valueArr":["261","B2BCK","DBCK","JYCK","PTCK","QTCK","UB","XSCK","Z01","Z04","Z09","Z21","Z89","ZOR"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','shipobjtype',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":["TO_C"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','shipto',14217,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":21,"upper":"1001006","lower":"1000255","count":36,"preSum":0},{"ndv":19,"upper":"1001259","lower":"1001041","count":39,"preSum":36},{"ndv":25,"upper":"1002054","lower":"1001267","count":36,"preSum":75},{"ndv":19,"upper":"1002479","lower":"1002061","count":37,"preSum":111},{"ndv":25,"upper":"1002953","lower":"1002492","count":36,"preSum":148},{"ndv":8,"upper":"2000031","lower":"1002959","count":42,"preSum":184},{"ndv":7,"upper":"2000253","lower":"2000032","count":55,"preSum":226},{"ndv":3,"upper":"2000257","lower":"2000254","count":46,"preSum":281},{"ndv":27,"upper":"20010313","lower":"2000402","count":36,"preSum":327},{"ndv":19,"upper":"20020188","lower":"20010350","count":36,"preSum":363},{"ndv":24,"upper":"20023013","lower":"20020205","count":36,"preSum":399},{"ndv":34,"upper":"20027246","lower":"20023016","count":36,"preSum":435},{"ndv":31,"upper":"2005746","lower":"20028083","count":36,"preSum":471},{"ndv":26,"upper":"20319002","lower":"2005747","count":36,"preSum":507},{"ndv":33,"upper":"20536117","lower":"20350001","count":36,"preSum":543},{"ndv":32,"upper":"20591030","lower":"20536118","count":36,"preSum":579},{"ndv":31,"upper":"20733021","lower":"20592006","count":36,"preSum":615},{"ndv":28,"upper":"20760206","lower":"20734113","count":36,"preSum":651},{"ndv":31,"upper":"20825002","lower":"20769133","count":36,"preSum":687},{"ndv":27,"upper":"20999051","lower":"20825005","count":36,"preSum":723},{"ndv":33,"upper":"80271012","lower":"80101310","count":36,"preSum":759},{"ndv":29,"upper":"80292098","lower":"80271013","count":36,"preSum":795},{"ndv":31,"upper":"83111424","lower":"80292101","count":36,"preSum":831},{"ndv":23,"upper":"83131842","lower":"83111456","count":36,"preSum":867},{"ndv":32,"upper":"83171720","lower":"83140396","count":36,"preSum":903},{"ndv":30,"upper":"83511787","lower":"83171723","count":36,"preSum":939},{"ndv":33,"upper":"83711972","lower":"83511788","count":36,"preSum":975},{"ndv":31,"upper":"83772225","lower":"83711994","count":36,"preSum":1011},{"ndv":33,"upper":"83942419","lower":"83772250","count":36,"preSum":1047},{"ndv":31,"upper":"84160882","lower":"83942424","count":36,"preSum":1083},{"ndv":33,"upper":"84310933","lower":"84170031","count":36,"preSum":1119},{"ndv":34,"upper":"84770895","lower":"84310938","count":36,"preSum":1155},{"ndv":35,"upper":"85190348","lower":"84820423","count":36,"preSum":1191},{"ndv":33,"upper":"85371781","lower":"85190712","count":36,"preSum":1227},{"ndv":33,"upper":"85530749","lower":"85371793","count":36,"preSum":1263},{"ndv":32,"upper":"85610746","lower":"85530750","count":37,"preSum":1299},{"ndv":36,"upper":"85763179","lower":"85630405","count":36,"preSum":1336},{"ndv":33,"upper":"85963059","lower":"85771360","count":37,"preSum":1372},{"ndv":33,"upper":"87130945","lower":"85963067","count":36,"preSum":1409},{"ndv":35,"upper":"87301303","lower":"87130949","count":36,"preSum":1445},{"ndv":33,"upper":"87500019","lower":"87301311","count":36,"preSum":1481},{"ndv":34,"upper":"87570027","lower":"87520006","count":37,"preSum":1517},{"ndv":35,"upper":"87690235","lower":"87570029","count":36,"preSum":1554},{"ndv":32,"upper":"87760007","lower":"87690264","count":36,"preSum":1590},{"ndv":35,"upper":"88182089","lower":"87790034","count":36,"preSum":1626},{"ndv":33,"upper":"88392094","lower":"88182099","count":36,"preSum":1662},{"ndv":32,"upper":"88710163","lower":"88392114","count":38,"preSum":1698},{"ndv":33,"upper":"89132232","lower":"88720001","count":36,"preSum":1736},{"ndv":34,"upper":"89721864","lower":"89132248","count":36,"preSum":1772},{"ndv":11,"upper":"D017","lower":"89730005","count":44,"preSum":1808},{"ndv":13,"upper":"R18A","lower":"DJ01","count":36,"preSum":1852},{"ndv":15,"upper":"S002-1000","lower":"R18C","count":36,"preSum":1888},{"ndv":3,"upper":"S005-1000","lower":"S003-1000","count":40,"preSum":1924},{"ndv":4,"upper":"S102-1000","lower":"S007-1000","count":51,"preSum":1964},{"ndv":3,"upper":"S107-1000","lower":"S104-1000","count":51,"preSum":2015},{"ndv":4,"upper":"S113-1000","lower":"S108-1000","count":50,"preSum":2066},{"ndv":14,"upper":"TC20913072","lower":"S115-1000","count":36,"preSum":2116},{"ndv":36,"upper":"TC84310623","lower":"TC80101305","count":36,"preSum":2152},{"ndv":34,"upper":"TC85790617","lower":"TC84710525","count":36,"preSum":2188},{"ndv":32,"upper":"TC87930642","lower":"TC85792392","count":36,"preSum":2224},{"ndv":22,"upper":"TC89942082","lower":"TC87931532","count":23,"preSum":2260}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[95859,29,28,29,25,25,27,65,28,39,47,30,33],"valueArr":["","2000250","2000251","2000256","2000258","2000259","2000287","2005821","9992","9998","S001-1000","S103-1000","S105-1000"],"type":"String","sampleRate":0.9618625319816094}',1454,0.02436278),('jala_wms_prod','shipment_header','shiptoaddress1',2174001,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1532,"upper":"#4BK0gUqoG9FQjDEFMZq9bxZ5tkxoiJ70qE7jbiEq#uwdKVab1wdQXSOUjJFDNy+Rjes+AwsQs1pD3DQLDWG01sWBsrfhv6uC/4dFs0S0bwz8ySL66iu4tZFDVzi74ZR","lower":"##+9nL+7Q3xGbB2c+KyXNvTurcjmzLW7DrQD50IF+/XIkr50dNkkGKWdXVi/U9INNBRvj0Om06vEANMLdPWm1WFCa42DDdmUXdnH3Zd+MkWldRcbw1lpgn3FMn2BkTJB","count":1532,"preSum":0},{"ndv":1531,"upper":"#A42e5x6hDGHA1koASea0#YK++PU++O5L/s6QrQ5WefW+zo8bEKEijA7Cnd1gea6T7dJO50Tq2zUEQcbBxNgQnXLVjqlYou5e2Y/llsL84Hu3SZ+wFaH0EL/V/p6o5t0","lower":"#4BK0TmQOfK+dn6KQ4BK0gUqolNsYFuFsL6uLzsPaRhlsIajw2wWrEysuV/3poQ6y8tm+meOvWup7dIf+9AsCxOs54BK0gUqoT8a1#018f81tFdTDlNzfZT6NLlF6eVC","count":1532,"preSum":1532},{"ndv":1532,"upper":"#d9828vrfG9FQFdw+C8PetkxoOHVIsMHH3Fe752re3JrMfobI#U3Sr2BlbXBh7yJph7DwwzdnCszArMkQwgloAi+X0NapYLUejF6mUiKxcp1McK4ag00gjIV5KzHKe/N","lower":"#A42e64TbgUqoOh3c6UeYD8sAaEg+Rukh#/OUILF+MrAwp9RXo8aTdYcO6EnwrIqypKjIOxMW/aUsifVOitJXNn7O0cLkFXvrRnZO/sA8I4vSaWbyhWoQa0rdTHVXrss","count":1532,"preSum":3064},{"ndv":1532,"upper":"#Gln/sZh9dViAOh1MTo8FN7O5H0GMvaf3wZURxKbMHiRVNAyWdHWeWSaDWOQlPKxl#S2H53Bsg9VXmVwqrQE4dakN4Cj+f+QgMMzfjOpSz6yhClnp9X92Ov41/9GR4xa","lower":"#d982XIom8K/BLr+lYIobPOUVmR3bqnxd#YamEnu9aJN08ASgBf5m6FUZKwkBXJg7pcmJvErG7XDhSEUpdQv7+9syMgSPIKHmnr1e7ZZpf8VLCP8eV8eiy9l9yTCRd0Z","count":1532,"preSum":4596},{"ndv":1532,"upper":"#jPHUmgqgoTLIDOZkwMOQ65b5970qVEJNXIIBtVd5TcoC0Fg9AGcbmjCsc0hWxWht#mji3JFp7fksWF9gz612C0EHRSq0OQLQl8TM6segJQjYYpFyaXZ14LEso0ZMc8U","lower":"#GLrSpSeoLG2c2YNgBL/BD0Zos90y8cohvwXH+y0Wgo2pRWK/#Fhmr6RMcAlRVE5t+Bvw//k5jJArW6/XmTZvL+keLfiIJer9xU/7QN4IyNI2vu8EJwdo1NjHAO33V77","count":1532,"preSum":6128},{"ndv":1532,"upper":"#MXO9ItseBEEZeLZcHLLGaotyFuFsYfI1I5W9CcWw5+xROXTeyYL64GLn3JrM#gfbpH10qpFBgXFIZtau1AbHS15dsnNTz3OjB+wfdxpWBOJrxrqM9IgSZT3/mI2uaJ1","lower":"#jPHUmgqgoTLIDOZkwMOQi6YoDaSfkDTH8PmFJIwWVGwjwt2WfvoFI8Wy2+6cALkNt72bzW35#HrV6NTrxxBv3KQ7FeGite7rHGlA9jFgZugpO5aS8g9EYZfRX3F1VXn","count":1532,"preSum":7660},{"ndv":1532,"upper":"#Pw7xATKg3tS5IYqxtKmQevC7qq1TTFhU77UkiDykplZr#9irjK01yPdMC7ajex+Pz9ES0Zg5WyBPhpMDJXlgXKuohruXcJ4pfxuMsaKi6J4nuncHRz4/8tNeWvVrdrX","lower":"#mxRp9XLZM9e2KYsdbiEqPJnBE5kwDcNoikPU7xkZX2I3ArfsFHj2DcNoikPU7xkZX2I3Arfso4c5YIobyjs2YfI1#n0vt+wgXx8DZtvQbyekI39pFe881m198tPKIo7","count":1532,"preSum":9192},{"ndv":1529,"upper":"#t+89EqndlxJ3ovovYXtY+A+62VP0N2HrZBFwTR7+TSgp0hAv3Pg2N9wyOWnYtWSMIqWG#zIwF0QWGAIraa6lIpxDgz7R2OWSjep4uY0I1gCZdrvcryrlJBJcLbVYU0S","lower":"#Pw7xcO82lqG9kPCLGPViDa7LCophWGnXZRrJwFiR4VZ+ORhMQ+KD#3guKploXd75mtD0dyaUFNz3rouDYRxpI57cNojNB8oIwQachwp1JH3+hOg4+6YkbFphWMlX7Is","count":1532,"preSum":10724},{"ndv":1532,"upper":"#W1LNeYfCfK+d8jL6eqmRQKXRdLiObeBz7XfpvpFmtkxo7GLuvF83#9KCQ/YUKiphEv+t0K7nlW60XIPj/SFggN2P96asfLrnje8uOlyvnL42pZ/wUIb1U1Bwwv3Bc6B","lower":"#t+AEHJPaFOhUqJQp+2WL0Zufy8VN1LZIRbMZ#9rrj+rSTaFlckRhCkoTlt/4UlWsxIxn4ZM1IWU4abOMyUfkc83AI2OqrBhQsrkWPrjZSjESr8Zp4E35wbZDgk6d3fR","count":1532,"preSum":12256},{"ndv":1530,"upper":"#ZdFArEW9kyGkkB8qTale0vav#iMd3MybaUmTxmBoZPotSaweFo40ZL1WCplQ31QDIdi/rSmx8UUGkUOuy/xcW6u98U5KpEv2wZEdGRluiONcwSaQDF6NMyigZOAC2Iz","lower":"#W1LNoCZ68ipEY1acn0FrSDOky69QqDkuc0/PRWK/FRIyD1pyHFk5SMSDwcBYkiDesbO5#ZOwcQRC02b2pi+tVKR53LiQ4KdkhJ9DUqDmGaAxK+S90SCR+WGk7jYivZO","count":1532,"preSum":13788},{"ndv":1528,"upper":"~EXPYSES3xGtpEXPYSES3xGtpyYo7qyqgrPi+PbF5kvLZyfTj7stM1ka6e3P1mEnBd7EJYWZ/1ka6KwB31ka6~Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Nj","lower":"#ZdFArxK3tY0CtkxoYfI1#w78a4F//kAXNleTvzQlvSvwsXPBhfB45fvXhVWtZ6wg9ds6PpdIb0gxncKt+3PlHtTqHOhE63FyESZLI3yAwwGsJ8AIq0CbfoXfZlQUd8P","count":1532,"preSum":15320},{"ndv":1523,"upper":"三*街道**路龙湖星**栋","lower":"~EXPYTuDVxGtpgX4XYWZ/MiTwhfp79aY9eZuexT22~Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Njc5NDAxMjM5MjU4MzY3MDISMDI1Zing3yC3FMAcnFMZXp","count":1532,"preSum":16852},{"ndv":1476,"upper":"东**镇森林大第*-*-***","lower":"三*街道**路龙湖星**栋****室","count":1532,"preSum":18384},{"ndv":1491,"upper":"东湖风**街道马鞍山森**园山**村**号东湖小白","lower":"东**镇武清区东**镇","count":1532,"preSum":19916},{"ndv":1504,"upper":"九**街道青岛市李沧区**路**号*园美墅北门小媳妇铁锅炖鱼前台","lower":"东湖风景区街道东**路**号院西门","count":1532,"preSum":21448},{"ndv":1497,"upper":"产业集聚区**路鑫和美林郡旁边超市","lower":"九**街道香江**城香江翡翠**号楼","count":1532,"preSum":22980},{"ndv":1497,"upper":"八*镇二**路**街西*巷巷口","lower":"产业集聚区华**店向南第一个公交站牌对面仓库(栅栏门)请进最里面一个仓库","count":1532,"preSum":24512},{"ndv":1500,"upper":"凤*街道**街***号贵州特色**店","lower":"八*镇八**镇**街","count":1532,"preSum":26044},{"ndv":1504,"upper":"北*镇伟业**号广东美的厨房电器制造**公司","lower":"凤*街道**街**号张姨保管车","count":1532,"preSum":27576},{"ndv":1495,"upper":"南*园乡南二环****号贺**园","lower":"北*镇佛山市顺德北滘雅居乐英伦首府**栋***","count":1532,"preSum":29108},{"ndv":1495,"upper":"卢**街道大瓦**路福悦四季***单元****","lower":"南*园乡朝阳**街长**园南区**楼","count":1532,"preSum":30640},{"ndv":1500,"upper":"吉林省.长春市.榆树市.红星乡郝家村四平台屯","lower":"卢**街道梅**路**号**幢*-***","count":1532,"preSum":32172},{"ndv":1479,"upper":"四*街道海亮首府","lower":"吉林省.长春市.经济技术开发区.东方广场街道六合一方B区B26栋","count":1532,"preSum":33704},{"ndv":1459,"upper":"坂*街道中浩二**号航嘉**园宿舍**栋","lower":"四*街道鞍**路****单元***户","count":1532,"preSum":35236},{"ndv":1507,"upper":"城*镇河南省濮阳市**县**镇**路增运食品","lower":"坂*街道五**村**路**号*座","count":1532,"preSum":36768},{"ndv":1513,"upper":"大*街道远洋新干线","lower":"城*镇河南省濮阳市**县**镇丁**村","count":1532,"preSum":38300},{"ndv":1458,"upper":"太原经济技术开发区唐槐**园区汾东大**号太**院菜鸟驿站","lower":"大*街道通**道**号海聚**广场大丰海聚**城**栋****室","count":1532,"preSum":39832},{"ndv":1502,"upper":"安徽省.宣城市.宣州区.西林街道金碧花园4栋","lower":"太原经济技术开发区坤泽翰林华**号楼","count":1532,"preSum":41364},{"ndv":1488,"upper":"小*街道红联**路海**村*-***","lower":"安徽省.宣城市.宣州区.鳌峰街道宛溪新村9栋401室","count":1532,"preSum":42896},{"ndv":1469,"upper":"岜盆乡弄洞村姑辽屯","lower":"小*街道红联振**路***号","count":1532,"preSum":44428},{"ndv":1508,"upper":"广东东莞市东坑镇东兴中路125号锦绣豪园11栋906","lower":"岣*乡**村神皇山金杯水电","count":1532,"preSum":45960},{"ndv":1522,"upper":"广东省.广州市.荔湾区.桥中街道悦江上品-B2栋804","lower":"广东东莞市东坑镇东坑镇东兴路碧桂园豪庭2期22栋","count":1532,"preSum":47492},{"ndv":1463,"upper":"库木德尔**街道新疆喀什克孜**路***号喀什地区水利**楼","lower":"广东省.广州市.荔湾区.白鹤洞街道珠江金茂府3栋二单元2206房(送货上门)","count":1532,"preSum":49024},{"ndv":1513,"upper":"徐霞客镇璜溪绿洲**号","lower":"库木德尔**街道解**路***号明**城","count":1532,"preSum":50556},{"ndv":1503,"upper":"新**街道太和电子**楼*区**号","lower":"得*乡云南省宣威市**乡**中学","count":1532,"preSum":52088},{"ndv":1489,"upper":"新*镇龙**路**号*城大**院导诊台","lower":"新**街道富华新天**单元****室","count":1532,"preSum":53620},{"ndv":1484,"upper":"曹*镇**路***弄*-****","lower":"新*镇,**村,新世界**广场,玩具专柜","count":1532,"preSum":55152},{"ndv":1502,"upper":"林口彝族**乡丫口上","lower":"曹*镇**路***弄佳伟景苑**号楼***","count":1532,"preSum":56684},{"ndv":1500,"upper":"梧*街道**街祝**城三**号**号**单元**层***号","lower":"林口镇林*县农业技术推广中**楼窗台","count":1532,"preSum":58216},{"ndv":1504,"upper":"永*县**园区**镇桥南天立**园北区","lower":"梧*街道**路*****单元。","count":1532,"preSum":59748},{"ndv":1492,"upper":"江苏淮安市清江浦区和平镇江苏省淮安市清江浦区6路前齐","lower":"永*街**园东**城凤仪**街**座***","count":1532,"preSum":61280},{"ndv":1474,"upper":"沙*街道**路**号成都市九天家私**公司","lower":"江苏淮安市清河区徐杨乡清荷家苑3区6幢2单元503","count":1532,"preSum":62812},{"ndv":1461,"upper":"河北省石家庄市鹿泉区石获北路30号中兴物流园1号库3层东跨","lower":"沙*街道**路**号新南**楼","count":1533,"preSum":64344},{"ndv":1454,"upper":"泾*镇世**园***单元****","lower":"河北省秦皇岛市昌黎县广缘超市自然堂专柜","count":1532,"preSum":65877},{"ndv":1503,"upper":"浙江金华市义乌市福田街道宗宅b区31栋阳光幼儿园","lower":"泾*镇大**路体委对面彬彬批**楼上","count":1532,"preSum":67409},{"ndv":1494,"upper":"渭**街道甘肃省兰**城关区**大学兰大二分部**院**号楼","lower":"浙江金华市义乌市稠江街道大路金10幢2单元足康","count":1532,"preSum":68941},{"ndv":1499,"upper":"湖南省.长沙市.长沙县.湘龙街道湖南省长沙市长沙县湘龙街道恒广国际景园一区物业办公用房","lower":"渭**街道甘肃省兰**城关区**大学医学校区","count":1532,"preSum":70473},{"ndv":1489,"upper":"烔*镇康盛**厂","lower":"湖南省.长沙市.长沙县.黄兴镇大众村,龙峰安置区","count":1532,"preSum":72005},{"ndv":1487,"upper":"瑶*镇南关**楼巷","lower":"烟*街**园南区**栋***","count":1532,"preSum":73537},{"ndv":1490,"upper":"盐*街道好*对面***—*—**—*","lower":"瑶沟乡工业园区666号万鑫电子厂请放前台谢谢","count":1532,"preSum":75069},{"ndv":1493,"upper":"福**街道庄**路新**园*塔**楼","lower":"盐*街道新区管委会**路与**路交叉口广汽三菱售后","count":1532,"preSum":76601},{"ndv":1483,"upper":"筼*街道**路***号****室**大厦","lower":"福**街道开发区舟山**号大平工程**院**楼","count":1532,"preSum":78133},{"ndv":1498,"upper":"肥*镇河北省邯郸**乡区前**村","lower":"筼*街道**路***号****室门口鞋柜","count":1532,"preSum":79665},{"ndv":1502,"upper":"荔*街道华商**号广州华**院","lower":"育**街道**街****单元**号","count":1532,"preSum":81197},{"ndv":1510,"upper":"裴*乡穰**路翰林公馆","lower":"荔*街道华商**号广州华**院菜鸟驿站","count":1532,"preSum":82729},{"ndv":1497,"upper":"解*街道**路荆沙**城","lower":"裴*乡翰林公馆","count":1532,"preSum":84261},{"ndv":1497,"upper":"辽宁省.大连市.瓦房店市.文兰街道香悦山10号楼1单元901","lower":"解*街道**路金沙阳**栋****","count":1532,"preSum":85793},{"ndv":1454,"upper":"重庆市.重庆市.涪陵区.李渡街道重庆市涪陵区马鞍盛世华府2栋","lower":"辽宁省.大连市.瓦房店市.新华街道瓦房店新华办事处德林衔一段3号6单元彩票站","count":1532,"preSum":87325},{"ndv":1489,"upper":"银*街道银**街**号中油集团测井**公司大**公司解释**中心","lower":"重庆市.重庆市.涪陵区.李渡街道长江师范学院聚仕兰庭小区","count":1532,"preSum":88857},{"ndv":1504,"upper":"陈**街道重庆市沙坪坝陈**街*大学**路**号重庆商务职**院","lower":"银*街道银浪温**园*****单元***室","count":1532,"preSum":90389},{"ndv":1483,"upper":"青*镇福州泰全电机**公司","lower":"陈**街道重庆警**院家属区","count":1532,"preSum":91921},{"ndv":1491,"upper":"高*镇衢**道***号蓬莱阳**幢***","lower":"青*镇翡丽**栋北门好生活超市","count":1532,"preSum":93453},{"ndv":1486,"upper":"黑龙江省.哈尔滨市.南岗区.哈西街道哈西大街928号巴黎第五区14-1-1004","lower":"高*镇观音溪","count":1532,"preSum":94985},{"ndv":1433,"upper":"龟山小区一号楼401","lower":"黑龙江省.哈尔滨市.南岗区.曲线街道77号2号楼3单元502室","count":1477,"preSum":96517}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[78,54,46,27,43,116,46,27,31,83,26,45,26],"valueArr":["","上海市上海市奉贤区奉柘公路3289号","上海市上海市奉贤区岚丰路900号","四川省成都市龙泉驿区成都市龙泉驿区车城大道999号宝湾物流园9号仓库","四海大道1666号义乌公路港2期26栋","四海大道盛辉物流园区分拨中心二楼2-6号","天津市天津市津南区天津市津南区小站镇小站工业区11号路安博物流园1号库C分区","广东省佛山市三水区佛山市三水区乐平镇创新大道西10号-6号仓库","广东省清远市清城区广东省清远市清城区广东锦邦冷链物流园二楼7号库","浙江省嘉兴市海盐县澉浦镇长墙山工业园(澉浦工业园)纬二路天玺物流园2号","湖北省武汉市洪山区武汉市江夏济开发区庙山大道旁普洛斯江夏物流园一期B5","湖北省武汉市蔡甸区武汉市蔡甸区星光大道77号","陕西省咸阳市秦都区陕西省咸阳市秦都区天马大道万纬西安万中轻物流园A-4库屈臣氏仓库"],"type":"String","sampleRate":0.9618625319816094}',1359,0.02436278),('jala_wms_prod','shipment_header','shiptoaddress2',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[31],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99970,0.02436278),('jala_wms_prod','shipment_header','shiptoaddresslat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','shiptoaddresslng',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('jala_wms_prod','shipment_header','shiptoattentionto',287722,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1028,"upper":"#1gt9unDb#zS14vbwqOCYgGlUON1FyOB8WILR6kLB2DEZU84eIJRI8ErLPJB5ll7O6vVrH1/Qsu0PFtdAFklfJHrmN9DqzSMU0cM5/jmN22BQdTuZd1qE=*CgkIARCtH","lower":"","count":1103,"preSum":0},{"ndv":1102,"upper":"#5mhVoH85#Ce3j9hEdD29n4gY1dF3NwojJTPqFjfC2OkZJnhiU/lB8vW3rNKg+ZygBeyWnXvXiwO0BW/QSFC+8vRj+G9GJV1QqJKRs1aZN66EIrFym0yY=*CgkIARCtH","lower":"#1GvwFpft#dBN7EinkZsurkdz0SwEqwF6jFLM3vo4HQ7cHqwhS5SpnmJjIJHEBl3hKTr935vTr7TmM9ZtdQGhITdyDWML6FZWXEWe2usDhDuQwIA1gUYI=*CgkIARCtH","count":1103,"preSum":1103},{"ndv":1100,"upper":"#9xN/Z06F#Cv3i3FC5hiceaxKw/U2SF/QGqUQI44NR/AneQRC8+pPMv2ZBoASlcyIuLzKuIUBWV+5q7L737VLn0GuGdSkNDFQgLY9/Dw6Ki4/pMQY56mQ=*CgkIARCtH","lower":"#5mhVoH85#eNml8gwO47osupKz8gxNPCdc4ZW6vsa1Fm0K9jv9OxvyDl2wTOn2Z32KsKZoAXOvAOmQULIPiRKxvxFFLF3G30LgqHzj32whyjH3uFRbCE0=*CgkIARCtH","count":1103,"preSum":2206},{"ndv":1103,"upper":"#buxT#gJZIxTL0KxuYIos8DzBhj/eFoOzy9bOwPmMjjX8XlwyU2iQ/jaM85hZAv7RokZ4wMHpl3sNgcSpimMSbMXMCkhCREYEflYpXImSaLCQ=*CgkIARCtHCABKAESP","lower":"#9XYX#aAnmAoqc2hr3UApaVMEdBFu2YlmIYn9DiDYsqmLzrqJdA/v1PH1pwtK75LX03ODT5JLdd/cgjREfEwyfCKXt4V0tGEGl43fxhtEpVAU=*CgkIARCtHCABKAESP","count":1103,"preSum":3309},{"ndv":1103,"upper":"#E2Wv#3b9h55W/heu6QnmxiGFm273gKPCb7IEFTSLOQ+akFSIMjzinE2zoEaoyAfvTNuY8CiLE4uqrbQuuDnJERUivNXAqK0TGJYh53cLzZcI=*CgkIARCtHCABKAESP","lower":"#BV22CQou#Lybp7Bp2vKeYK7xXhmtwk+CG6VuGu58354W6lERyfOU7132vax7xnyLEoL36A59DzAtYBaXsVdNEndF9Go+9tXxql64EC3eDsqXG3yB98R8=*CgkIARCtH","count":1103,"preSum":4412},{"ndv":1103,"upper":"#G4Va#O/XRg2Gk/9PWtQjl2hM5KTsGeKzPzI61JJuqYPrP2obpCA6FI4QdJmNcojOjAM2+Cpr3SrKFT5bPxaz5T5jWq0Ojcu35XpVqhtnbXwk=*CgkIARCtHCABKAESP","lower":"#e3pj#pIa7/I5zjli3icCjraaFiHDDysrm2DLgft2fg8Uljwwpga12vXR8LBTvFXvthwYysaTSKOkvPCwVSQX3Sr1JxWToHgf70hHrv8HwXjA=*CgkIARCtHCABKAESP","count":1103,"preSum":5515},{"ndv":1103,"upper":"#hYzKGkmIGkmI#Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Njc5NDAxMjM5MjU4MzY3MDISIKEOSpmDHDsGLLNw8mlBfMaq+uqAV5oXc3tzl6rj+Fn0GhI8lD","lower":"#G4Va#pUAGIbbXhJ1yM/fLVfMnN1dE3Xe03CNYc9TXdTagL1ayw15Ax60Ox1WhVQ2PDruOHYADj1PDgWQXgnVU3EjObLJsxs5aZaTRlNtdjLA=*CgkIARCtHCABKAESP","count":1103,"preSum":6618},{"ndv":1103,"upper":"#KAZ1QEcz#xdDMe9YtetmZd5KDft7OGd7Bm++slhDBik7/Jcz+bPwZieqPJmd5VrARExX1Z53gKboiDgqO2E16ZEZAWaTt7uaqddkPHGk5uNW560u5X5E=*CgkIARCtH","lower":"#hYzKhYzKhYzK#Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Njc5NDAxMjM5MjU4MzY3MDISIIO4k86Nd3zIGnrNid34l/AlfdlaHzl8z4k+E6sr7VihGhLSym","count":1103,"preSum":7721},{"ndv":1103,"upper":"#mF4Y/YT+d3Pk#Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Njc5NDAxMjM5MjU4MzY3MDISIHkTUdnueJa1JCmpmhFLeQwhLArCsF9RQbAD559XIOEUGhK2Jp","lower":"#KAZ1tHNK#dgMIJ+4tuQO7V/bGxRaD1l4rfVAIAkPmSCRVyRuILvfhUr6b68NV+boDiEMd3kDLhl7TQvBGIBNRiCNmHvpZLNE0YJjyKP0qu9wtWR6IfdQ=*CgkIARCtH","count":1103,"preSum":8824},{"ndv":1103,"upper":"#obS7#7dEJmwM8BRZW8eWXQ+6UvKs3A7iqQv3pqKxUJFhx+rw1Orzv4jtgajiZluMf7V3eJ2MEZD8WJvY7zDDYfcnhPG/2IwH2JOPV1qN3Jsc=*CgkIARCtHCABKAESP","lower":"#mF4Y/YT+d3Pk#Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Njc5NDAxMjM5MjU4MzY3MDISIP53m289plc0KlUYu1f+tx0e6AF9zyPMa4Kscaj396sXGhLSym","count":1103,"preSum":9927},{"ndv":1102,"upper":"#qEd9#z6Qfa6lCNLWM4Keac7164h2mwIpjgOuRQYgocz7RsycrStpFjhZNLHUjJS7SgS0+4Az7EpY4xN/IsKzS15y/esT7chLIvl4rGMfkLIg=*CgkIARCtHCABKAESP","lower":"#obU1j279#qxRs3gdYuzkkZrkw5MumRA4wnDQhaZU6xcsOwShuzBPHUAELwbHp/TtwpeC7BH4Jq3euaK2xkYPkZup04SKEawZ2kc2QRqp3Fdy/hJVuFQ8=*CgkIARCtH","count":1103,"preSum":11030},{"ndv":1102,"upper":"#SN2HolXU#oFXB+rVImOfu1Zm+AqYLdVn7VsN8A0ZKgywXdz/Qdu/xC0pEkhD28KOSve0TXTbeY6h2+5wtIwv4AVFwAQrYAxj/IRARnAmLJZQMxrPsbuo=*CgkIARCtH","lower":"#QeN4MAh2#BWqtuRo8uEMMXrqiGtyjIsJq0CmjA/e5iX99RL3//bMf8Y4MxY8CxQb79HeNLleJF8cGHrWonrRMPPZyTzcTkSuOUJ2O+Ydrc7EsKxzj/pc=*CgkIARCtH","count":1103,"preSum":12133},{"ndv":1103,"upper":"#uR3YUmpw#Bc5gR3Ni6O9PHsVXPx3THKYuPJXbrytA+yaNNJZMV/W/emp6imA/fByoyuYQt0rl9nAWheLBcrq8FnpCFaya0D9SrJchJg7pb6XOm+WGYFM=*CgkIARCtH","lower":"#sn8b#LyPBJMQZ/vr5zoInNKOUhK9LfiuapF6W0RcW0cD/c2g7CVX25vzM1HXCfmaPCj44nt9JEDruRWaK8ufS83lGLZ0fHxuAcYjC/KWABIk=*CgkIARCtHCABKAESP","count":1103,"preSum":13236},{"ndv":1103,"upper":"#wwTjMbFe#U0sJZ8Y1RKz8iEn5b/OHTjYXU2k+EMDEBF6+2ykw/N6hv0Ly/ScApiFCoc/KZEgIvpZWTfnjSqXePUHKIpzRYT0XQSmGpP8d14AggI3VrQk=*CgkIARCtH","lower":"#uR3YzVlI#zgS4gYuvz+V3hzE772vFYABYDHXtWeMu2fsRILCuU/K1kbRo7HN9Ym61UAwwCVQDuTIdROHgeAOHyS+MxUQQEKTut5I3hyyyhleMDPm67zI=*CgkIARCtH","count":1103,"preSum":14339},{"ndv":1103,"upper":"#Z9UTgHt7#meIADWicL6DX+wfQujINSWvCWYaJk95EvTuFcQMxeM+LMqo1t+7BTy/hf6CYrApYIMyFzrd6OYsI4cbuf95V80xF/v/GjjDQu/dmNla7cCA=*CgkIARCtH","lower":"#wWwi#LRtwzjg0/ds6ciy86mjQsq02pQOk8DWKc+TppsKFr9ygdELwp+cjLMu7YBHTO8mZcjtEw1HVgmofK/xanjf7YaAwq+wjU20UP18Rr8s=*CgkIARCtHCABKAESP","count":1103,"preSum":15442},{"ndv":473,"upper":"T**","lower":"#ZA6z#HaYcADtZ4mYEDZiiqSt30w2UBGdvishY9Hq5JTx10Gh/DrheVfjM63mLC1YZcCK8pC7I27w/pgR3i3xKcjwViHzFrwma6/BQqt+pT/w=*CgkIARCtHCABKAESP","count":1122,"preSum":16545},{"ndv":853,"upper":"丁**","lower":"tang","count":1337,"preSum":17667},{"ndv":216,"upper":"于**","lower":"丁一","count":1154,"preSum":19004},{"ndv":245,"upper":"何**","lower":"于**********","count":1635,"preSum":20158},{"ndv":276,"upper":"克**","lower":"何七夕","count":1104,"preSum":21793},{"ndv":189,"upper":"刘*","lower":"兔*","count":1183,"preSum":22897},{"ndv":546,"upper":"卡**","lower":"刘东","count":1103,"preSum":24080},{"ndv":174,"upper":"司**","lower":"卡卡","count":1125,"preSum":25183},{"ndv":491,"upper":"和*","lower":"司团庄","count":1104,"preSum":26308},{"ndv":246,"upper":"夏*","lower":"和**","count":1108,"preSum":27412},{"ndv":170,"upper":"姜*","lower":"夏**","count":1106,"preSum":28520},{"ndv":96,"upper":"孙**","lower":"姜**","count":1363,"preSum":29626},{"ndv":221,"upper":"宋会英","lower":"孙丁蓉","count":1103,"preSum":30989},{"ndv":394,"upper":"岳**","lower":"宋伟","count":1135,"preSum":32092},{"ndv":218,"upper":"廖**","lower":"岳凤英","count":1208,"preSum":33227},{"ndv":597,"upper":"彭*","lower":"廖东婷","count":1115,"preSum":34435},{"ndv":328,"upper":"戴**","lower":"彭**","count":1134,"preSum":35550},{"ndv":238,"upper":"易**","lower":"戴初","count":1162,"preSum":36684},{"ndv":160,"upper":"曾**","lower":"易丽","count":1177,"preSum":37846},{"ndv":503,"upper":"李春雨","lower":"曾s","count":1103,"preSum":39023},{"ndv":538,"upper":"杨牢巴","lower":"李春香","count":1144,"preSum":40126},{"ndv":346,"upper":"梁**","lower":"杨玉华","count":1341,"preSum":41270},{"ndv":276,"upper":"殷**","lower":"梁丽丽","count":1140,"preSum":42611},{"ndv":195,"upper":"沈**","lower":"殷丽平","count":1301,"preSum":43751},{"ndv":223,"upper":"潘**","lower":"沈丽","count":1260,"preSum":45052},{"ndv":305,"upper":"王原红","lower":"潘丽君","count":1103,"preSum":46312},{"ndv":557,"upper":"瓜**","lower":"王厦兰","count":1107,"preSum":47415},{"ndv":196,"upper":"石**","lower":"瓜瓜","count":1241,"preSum":48522},{"ndv":261,"upper":"笑**","lower":"石亚平","count":1115,"preSum":49763},{"ndv":154,"upper":"罗**","lower":"笑***","count":1178,"preSum":50878},{"ndv":250,"upper":"胡**","lower":"罗***","count":1807,"preSum":52056},{"ndv":312,"upper":"范**","lower":"胡丹","count":1275,"preSum":53863},{"ndv":203,"upper":"蒋**","lower":"范丽","count":1236,"preSum":55138},{"ndv":209,"upper":"袁**","lower":"蒋万秀","count":1126,"preSum":56374},{"ndv":228,"upper":"谢**","lower":"袁***","count":1425,"preSum":57500},{"ndv":299,"upper":"赵士敏","lower":"谢三坤","count":1103,"preSum":58925},{"ndv":333,"upper":"邱**","lower":"赵声勇","count":1223,"preSum":60028},{"ndv":141,"upper":"郑志军","lower":"邱丹","count":1103,"preSum":61251},{"ndv":211,"upper":"金**","lower":"郑恒","count":1271,"preSum":62354},{"ndv":216,"upper":"阿**","lower":"金一百","count":1135,"preSum":63625},{"ndv":477,"upper":"隆**","lower":"阿****","count":1105,"preSum":64760},{"ndv":173,"upper":"韩国栋","lower":"隆晓燕","count":1103,"preSum":65865},{"ndv":133,"upper":"马**","lower":"韩培爱","count":1174,"preSum":66968},{"ndv":225,"upper":"魏**","lower":"马***","count":1119,"preSum":68142},{"ndv":357,"upper":"龙仙桃","lower":"魏丹丹","count":1103,"preSum":69261},{"ndv":65,"upper":"~**","lower":"龙会兰","count":179,"preSum":70364}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2769,1192,1138,1858,3803,858,758,3934,1802,764,4012,1001,2799,1411],"valueArr":["刘**","吴**","周**","小**","张**","徐**","朱**","李**","杨**","林**","王**","赵**","陈**","黄**"],"type":"String","sampleRate":0.9618625319816094}',1359,0.02436278),('jala_wms_prod','shipment_header','shiptocaid',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','shiptocity',1429,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":20,"upper":"中山市","lower":"","count":1638,"preSum":0},{"ndv":15,"upper":"丽江市","lower":"丰台","count":1147,"preSum":1638},{"ndv":19,"upper":"亳州市","lower":"乌兰察布","count":1278,"preSum":2785},{"ndv":13,"upper":"信阳市","lower":"仙桃市","count":1301,"preSum":4063},{"ndv":12,"upper":"内江市","lower":"儋州市","count":1160,"preSum":5364},{"ndv":13,"upper":"南京市","lower":"凉山","count":1729,"preSum":6524},{"ndv":7,"upper":"南平市","lower":"南充","count":1179,"preSum":8253},{"ndv":5,"upper":"南通市","lower":"南开区","count":1236,"preSum":9432},{"ndv":6,"upper":"县","lower":"南阳市","count":1118,"preSum":10668},{"ndv":14,"upper":"吕梁市","lower":"双河市","count":1157,"preSum":11786},{"ndv":12,"upper":"咸宁市","lower":"吴忠","count":1185,"preSum":12943},{"ndv":6,"upper":"唐山市","lower":"咸阳市","count":1291,"preSum":14128},{"ndv":7,"upper":"嘉兴市","lower":"商丘","count":1190,"preSum":15419},{"ndv":19,"upper":"大连市","lower":"嘉定区","count":1272,"preSum":16609},{"ndv":3,"upper":"天津市","lower":"天水市","count":1169,"preSum":17881},{"ndv":11,"upper":"孝感市","lower":"天门市","count":1181,"preSum":19050},{"ndv":4,"upper":"宁波市","lower":"宁德市","count":1293,"preSum":20231},{"ndv":12,"upper":"宜昌市","lower":"安庆","count":1375,"preSum":21524},{"ndv":10,"upper":"宿迁市","lower":"宜春市","count":1336,"preSum":22899},{"ndv":18,"upper":"常州市","lower":"密云区","count":1316,"preSum":24235},{"ndv":17,"upper":"廊坊市","lower":"常德","count":1363,"preSum":25551},{"ndv":15,"upper":"徐州市","lower":"延安","count":1362,"preSum":26914},{"ndv":18,"upper":"惠州市","lower":"徐汇","count":1762,"preSum":28276},{"ndv":13,"upper":"揭阳市","lower":"成都","count":1304,"preSum":30038},{"ndv":9,"upper":"无锡市","lower":"攀枝花市","count":1333,"preSum":31342},{"ndv":6,"upper":"昆明市","lower":"日喀则地区","count":1187,"preSum":32675},{"ndv":21,"upper":"朔州市","lower":"昌吉回族自治州","count":1148,"preSum":33862},{"ndv":19,"upper":"桂林市","lower":"朝阳区","count":1357,"preSum":35010},{"ndv":15,"upper":"汉中市","lower":"梅州市","count":1202,"preSum":36367},{"ndv":7,"upper":"沈阳市","lower":"汕头市","count":1827,"preSum":37569},{"ndv":13,"upper":"泉州市","lower":"沙坪坝","count":1334,"preSum":39396},{"ndv":10,"upper":"济南市","lower":"泰安市","count":1848,"preSum":40730},{"ndv":18,"upper":"淮北市","lower":"济宁市","count":1243,"preSum":42578},{"ndv":12,"upper":"温州市","lower":"淮南","count":1626,"preSum":43821},{"ndv":12,"upper":"滁州市","lower":"渭南","count":1350,"preSum":45447},{"ndv":12,"upper":"潮州市","lower":"滨州","count":1236,"preSum":46797},{"ndv":13,"upper":"玉溪市","lower":"澄迈县","count":1170,"preSum":48033},{"ndv":19,"upper":"盐城市","lower":"珠海","count":1357,"preSum":49203},{"ndv":15,"upper":"福州市","lower":"盘锦市","count":2021,"preSum":50560},{"ndv":12,"upper":"绵阳市","lower":"秀山县","count":1158,"preSum":52581},{"ndv":13,"upper":"茂名市","lower":"聊城","count":1318,"preSum":53739},{"ndv":9,"upper":"萍乡市","lower":"荆州","count":1190,"preSum":55057},{"ndv":13,"upper":"襄阳市","lower":"营口市","count":1421,"preSum":56247},{"ndv":14,"upper":"贵阳市","lower":"西双版纳","count":1143,"preSum":57668},{"ndv":12,"upper":"运城市","lower":"贺州市","count":1282,"preSum":58811},{"ndv":10,"upper":"邢台市","lower":"连云港市","count":1320,"preSum":60093},{"ndv":14,"upper":"金华市","lower":"那曲市","count":2082,"preSum":61413},{"ndv":20,"upper":"镇江市","lower":"金山","count":1250,"preSum":63495},{"ndv":6,"upper":"长沙市","lower":"长宁区","count":1793,"preSum":64745},{"ndv":19,"upper":"阿拉善盟","lower":"长治","count":1122,"preSum":66538},{"ndv":12,"upper":"青岛市","lower":"阿拉尔市","count":1178,"preSum":67660},{"ndv":15,"upper":"鹰潭市","lower":"青浦","count":1209,"preSum":68838},{"ndv":18,"upper":"黔西南布依族苗族自治州","lower":"黄冈","count":1174,"preSum":70047},{"ndv":3,"upper":"龙岩市","lower":"齐齐哈尔","count":300,"preSum":71221}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[3126,1919,1183,2332,1273,2693,2136,1729,1660,2936,1767,1219,1487,1667],"valueArr":["上海市","东莞市","佛山市","北京市","合肥市","广州市","成都市","杭州市","武汉市","深圳市","苏州市","西安市","郑州市","重庆市"],"type":"String","sampleRate":0.9618625319816094}',1353,0.02436278),('jala_wms_prod','shipment_header','shiptocitycode',390,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":4,"upper":"130100","lower":"","count":1603,"preSum":0},{"ndv":4,"upper":"130500","lower":"130200","count":1076,"preSum":1603},{"ndv":4,"upper":"130900","lower":"130600","count":1140,"preSum":2679},{"ndv":4,"upper":"140200","lower":"131000","count":1107,"preSum":3819},{"ndv":9,"upper":"141100","lower":"140300","count":1015,"preSum":4926},{"ndv":7,"upper":"150700","lower":"150100","count":1063,"preSum":5941},{"ndv":6,"upper":"210100","lower":"150800","count":1025,"preSum":7004},{"ndv":7,"upper":"210800","lower":"210200","count":1050,"preSum":8029},{"ndv":7,"upper":"220100","lower":"210900","count":1105,"preSum":9079},{"ndv":9,"upper":"230100","lower":"220200","count":1221,"preSum":10184},{"ndv":13,"upper":"310000","lower":"230200","count":1630,"preSum":11405},{"ndv":2,"upper":"320300","lower":"320200","count":1252,"preSum":13035},{"ndv":2,"upper":"320600","lower":"320400","count":1008,"preSum":14287},{"ndv":3,"upper":"320900","lower":"320700","count":1021,"preSum":15295},{"ndv":4,"upper":"321300","lower":"321000","count":1208,"preSum":16316},{"ndv":2,"upper":"330400","lower":"330300","count":1477,"preSum":17524},{"ndv":3,"upper":"330700","lower":"330500","count":1672,"preSum":19001},{"ndv":4,"upper":"331100","lower":"330800","count":987,"preSum":20673},{"ndv":5,"upper":"340600","lower":"340200","count":1100,"preSum":21660},{"ndv":5,"upper":"341200","lower":"340700","count":1256,"preSum":22760},{"ndv":5,"upper":"341800","lower":"341300","count":1165,"preSum":24016},{"ndv":2,"upper":"350200","lower":"350100","count":1524,"preSum":25181},{"ndv":3,"upper":"350500","lower":"350300","count":1124,"preSum":26705},{"ndv":5,"upper":"360100","lower":"350600","count":1392,"preSum":27829},{"ndv":6,"upper":"360700","lower":"360200","count":1090,"preSum":29221},{"ndv":4,"upper":"361100","lower":"360800","count":1003,"preSum":30311},{"ndv":2,"upper":"370200","lower":"370100","count":1472,"preSum":31314},{"ndv":5,"upper":"370700","lower":"370300","count":1177,"preSum":32786},{"ndv":5,"upper":"371300","lower":"370800","count":1243,"preSum":33963},{"ndv":5,"upper":"410200","lower":"371400","count":996,"preSum":35206},{"ndv":5,"upper":"410700","lower":"410300","count":1124,"preSum":36202},{"ndv":6,"upper":"411300","lower":"410800","count":1155,"preSum":37326},{"ndv":3,"upper":"411600","lower":"411400","count":1033,"preSum":38481},{"ndv":5,"upper":"420500","lower":"411700","count":983,"preSum":39514},{"ndv":5,"upper":"421000","lower":"420600","count":1029,"preSum":40497},{"ndv":9,"upper":"430200","lower":"421100","count":1068,"preSum":41526},{"ndv":5,"upper":"430700","lower":"430300","count":1101,"preSum":42594},{"ndv":7,"upper":"433100","lower":"430800","count":1043,"preSum":43695},{"ndv":4,"upper":"440700","lower":"440200","count":1098,"preSum":44738},{"ndv":4,"upper":"441300","lower":"440800","count":1296,"preSum":45836},{"ndv":6,"upper":"441900","lower":"441400","count":1546,"preSum":47132},{"ndv":5,"upper":"450100","lower":"442000","count":1455,"preSum":48678},{"ndv":7,"upper":"450800","lower":"450200","count":1015,"preSum":50133},{"ndv":8,"upper":"460200","lower":"450900","count":994,"preSum":51148},{"ndv":19,"upper":"510500","lower":"460400","count":1033,"preSum":52142},{"ndv":7,"upper":"511300","lower":"510600","count":1159,"preSum":53175},{"ndv":10,"upper":"513400","lower":"511400","count":1019,"preSum":54334},{"ndv":4,"upper":"520400","lower":"520100","count":983,"preSum":55353},{"ndv":7,"upper":"530400","lower":"520500","count":1007,"preSum":56336},{"ndv":9,"upper":"532800","lower":"530500","count":978,"preSum":57343},{"ndv":16,"upper":"610600","lower":"532900","count":1055,"preSum":58321},{"ndv":9,"upper":"620500","lower":"610700","count":1059,"preSum":59376},{"ndv":18,"upper":"640100","lower":"620600","count":1070,"preSum":60435},{"ndv":20,"upper":"659002","lower":"640200","count":984,"preSum":61505},{"ndv":6,"upper":"659010","lower":"659003","count":18,"preSum":62489}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1077,1583,1395,986,1201,1340,1526,1078,2499,2655,1082,1965,938,1123],"valueArr":["320100","320500","330100","330200","340100","410100","420100","430100","440100","440300","440600","510100","530100","610100"],"type":"String","sampleRate":0.9618625319816094}',17046,0.02436278),('jala_wms_prod','shipment_header','shiptocountry',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[97400,13],"valueArr":["","中国"],"type":"String","sampleRate":0.9618625319816094}',2588,0.02436278),('jala_wms_prod','shipment_header','shiptocountrycode',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[9,82947],"valueArr":["","0"],"type":"String","sampleRate":0.9618625319816094}',17045,0.02436278),('jala_wms_prod','shipment_header','shiptodistrict',6813,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":70,"upper":"丛台区","lower":"","count":1419,"preSum":0},{"ndv":54,"upper":"东西湖区","lower":"东丰县","count":1525,"preSum":1419},{"ndv":50,"upper":"临川区","lower":"东辽县","count":1451,"preSum":2944},{"ndv":71,"upper":"九龙坡区","lower":"临平区","count":1499,"preSum":4395},{"ndv":67,"upper":"仁寿县","lower":"九龙街道","count":1405,"preSum":5894},{"ndv":43,"upper":"佛冈县","lower":"仁怀市","count":1416,"preSum":7299},{"ndv":67,"upper":"兴化市","lower":"佛坪县","count":1454,"preSum":8715},{"ndv":79,"upper":"包河区","lower":"兴县","count":1450,"preSum":10169},{"ndv":76,"upper":"南山区","lower":"化州市","count":1415,"preSum":11619},{"ndv":54,"upper":"博罗县","lower":"南岔区","count":1418,"preSum":13034},{"ndv":50,"upper":"古冶区","lower":"博野县","count":1405,"preSum":14452},{"ndv":64,"upper":"吴兴区","lower":"古县","count":1417,"preSum":15857},{"ndv":63,"upper":"嘉陵区","lower":"吴堡县","count":1412,"preSum":17274},{"ndv":50,"upper":"城阳区","lower":"嘉鱼县","count":1453,"preSum":18686},{"ndv":75,"upper":"大邑县","lower":"堆龙德庆区","count":1419,"preSum":20139},{"ndv":50,"upper":"奎文区","lower":"大鹏新区","count":1447,"preSum":21558},{"ndv":64,"upper":"安宁市","lower":"如东县","count":1405,"preSum":23005},{"ndv":57,"upper":"宝山区","lower":"安定","count":1633,"preSum":24410},{"ndv":60,"upper":"小店区","lower":"宝山路街道","count":1407,"preSum":26043},{"ndv":69,"upper":"崇阳县","lower":"小昆山镇","count":1405,"preSum":27450},{"ndv":58,"upper":"平城区","lower":"崔各庄地区","count":1451,"preSum":28855},{"ndv":66,"upper":"库尔勒市","lower":"平塘县","count":1404,"preSum":30306},{"ndv":76,"upper":"彭州市","lower":"库车县","count":1421,"preSum":31710},{"ndv":59,"upper":"惠城区","lower":"彭水苗族土家族自治县","count":1404,"preSum":33131},{"ndv":41,"upper":"拱墅区","lower":"惠安县","count":1480,"preSum":34535},{"ndv":52,"upper":"新干县","lower":"拱辰街道","count":1410,"preSum":36015},{"ndv":69,"upper":"昌平区","lower":"新平彝族傣族自治县","count":1507,"preSum":37425},{"ndv":62,"upper":"望城区","lower":"昌江区","count":1461,"preSum":38932},{"ndv":62,"upper":"枣阳市","lower":"望奎县","count":1435,"preSum":40393},{"ndv":51,"upper":"梁溪区","lower":"柏乡县","count":1444,"preSum":41828},{"ndv":58,"upper":"武昌区","lower":"梅列区","count":1485,"preSum":43272},{"ndv":63,"upper":"汉南区","lower":"武江区","count":1431,"preSum":44757},{"ndv":33,"upper":"江州区","lower":"汉台区","count":1419,"preSum":46188},{"ndv":62,"upper":"沙雅县","lower":"江干区","count":1406,"preSum":47607},{"ndv":66,"upper":"津南区","lower":"沛县","count":1443,"preSum":49013},{"ndv":49,"upper":"海拉尔区","lower":"津市市","count":1423,"preSum":50456},{"ndv":31,"upper":"涧西区","lower":"海晏县","count":1458,"preSum":51879},{"ndv":50,"upper":"温岭市","lower":"涪城区","count":1465,"preSum":53337},{"ndv":46,"upper":"滨海新区","lower":"温江区","count":1499,"preSum":54802},{"ndv":61,"upper":"点军区","lower":"滨湖区","count":1403,"preSum":56301},{"ndv":65,"upper":"璧山区","lower":"烈山区","count":1438,"preSum":57704},{"ndv":61,"upper":"相城区","lower":"璧泉街道","count":1470,"preSum":59142},{"ndv":72,"upper":"福山区","lower":"相山区","count":1423,"preSum":60612},{"ndv":48,"upper":"简阳市","lower":"福泉市","count":1441,"preSum":62035},{"ndv":68,"upper":"美兰区","lower":"管城回族区","count":1444,"preSum":63476},{"ndv":56,"upper":"芦淞区","lower":"美姑县","count":1437,"preSum":64920},{"ndv":58,"upper":"莱山区","lower":"芦溪","count":1451,"preSum":66357},{"ndv":38,"upper":"蕉城区","lower":"莱州市","count":1442,"preSum":67808},{"ndv":34,"upper":"襄州区","lower":"蕉岭县","count":1432,"preSum":69250},{"ndv":38,"upper":"西青区","lower":"襄汾县","count":1421,"preSum":70682},{"ndv":53,"upper":"越秀区","lower":"覃塘区","count":1476,"preSum":72103},{"ndv":66,"upper":"道里区","lower":"越秀路街道","count":1436,"preSum":73579},{"ndv":49,"upper":"鄞州区","lower":"遵化市","count":1411,"preSum":75015},{"ndv":47,"upper":"金牛区","lower":"鄠邑区","count":1527,"preSum":76426},{"ndv":54,"upper":"镜湖区","lower":"金盏地区","count":1444,"preSum":77953},{"ndv":45,"upper":"闻喜县","lower":"长丰县","count":1411,"preSum":79397},{"ndv":68,"upper":"雁山区","lower":"闽侯县","count":1404,"preSum":80808},{"ndv":44,"upper":"青浦区","lower":"雁峰区","count":1512,"preSum":82212},{"ndv":38,"upper":"颍上县","lower":"青田县","count":1434,"preSum":83724},{"ndv":67,"upper":"魏都区","lower":"颍东区","count":1418,"preSum":85158},{"ndv":42,"upper":"黄州区","lower":"鱼台县","count":1451,"preSum":86576},{"ndv":60,"upper":"龙港市","lower":"黄平县","count":1440,"preSum":88027},{"ndv":12,"upper":"龙马潭区","lower":"龙游县","count":279,"preSum":89467}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[498,929,494,404,888,436,620,458,705,440,636,528,668],"valueArr":["义乌市","其他区","南海区","天河区","宝安区","昆山市","朝阳区","洪山区","浦东新区","番禺区","白云区","龙华区","龙岗区"],"type":"String","sampleRate":0.9618625319816094}',2551,0.02436278),('jala_wms_prod','shipment_header','shiptodistrictcode',3471,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":35,"upper":"130105","lower":"110101","count":1188,"preSum":0},{"ndv":58,"upper":"130481","lower":"130107","count":1212,"preSum":1188},{"ndv":71,"upper":"130903","lower":"130502","count":1200,"preSum":2400},{"ndv":47,"upper":"140213","lower":"130921","count":1234,"preSum":3600},{"ndv":101,"upper":"150103","lower":"140214","count":1196,"preSum":4834},{"ndv":86,"upper":"152522","lower":"150104","count":1187,"preSum":6030},{"ndv":32,"upper":"210281","lower":"152523","count":1200,"preSum":7217},{"ndv":78,"upper":"220102","lower":"210283","count":1256,"preSum":8417},{"ndv":60,"upper":"230102","lower":"220103","count":1197,"preSum":9673},{"ndv":104,"upper":"231222","lower":"230103","count":1194,"preSum":10870},{"ndv":32,"upper":"320111","lower":"231223","count":1288,"preSum":12064},{"ndv":12,"upper":"320281","lower":"320113","count":1241,"preSum":13352},{"ndv":17,"upper":"320481","lower":"320282","count":1201,"preSum":14593},{"ndv":8,"upper":"320585","lower":"320505","count":1197,"preSum":15794},{"ndv":23,"upper":"320904","lower":"320602","count":1215,"preSum":16991},{"ndv":25,"upper":"321302","lower":"320921","count":1203,"preSum":18206},{"ndv":12,"upper":"330110","lower":"321311","count":1425,"preSum":19409},{"ndv":15,"upper":"330283","lower":"330111","count":1193,"preSum":20834},{"ndv":17,"upper":"330481","lower":"330302","count":1299,"preSum":22027},{"ndv":20,"upper":"330783","lower":"330482","count":1275,"preSum":23326},{"ndv":30,"upper":"340102","lower":"330784","count":1272,"preSum":24601},{"ndv":20,"upper":"340322","lower":"340103","count":1198,"preSum":25873},{"ndv":42,"upper":"341122","lower":"340323","count":1195,"preSum":27071},{"ndv":23,"upper":"341523","lower":"341124","count":1194,"preSum":28266},{"ndv":23,"upper":"350121","lower":"341524","count":1193,"preSum":29460},{"ndv":19,"upper":"350402","lower":"350122","count":1192,"preSum":30653},{"ndv":40,"upper":"350725","lower":"350403","count":1188,"preSum":31845},{"ndv":33,"upper":"360302","lower":"350781","count":1215,"preSum":33033},{"ndv":54,"upper":"360902","lower":"360313","count":1219,"preSum":34248},{"ndv":37,"upper":"370112","lower":"360921","count":1204,"preSum":35467},{"ndv":25,"upper":"370403","lower":"370113","count":1206,"preSum":36671},{"ndv":41,"upper":"370832","lower":"370404","count":1204,"preSum":37877},{"ndv":42,"upper":"371502","lower":"370881","count":1257,"preSum":39081},{"ndv":27,"upper":"410105","lower":"371521","count":1352,"preSum":40338},{"ndv":35,"upper":"410411","lower":"410106","count":1197,"preSum":41690},{"ndv":56,"upper":"411103","lower":"410421","count":1214,"preSum":42887},{"ndv":41,"upper":"411528","lower":"411104","count":1227,"preSum":44101},{"ndv":26,"upper":"420106","lower":"411602","count":1222,"preSum":45328},{"ndv":32,"upper":"420581","lower":"420107","count":1192,"preSum":46550},{"ndv":39,"upper":"421124","lower":"420582","count":1197,"preSum":47742},{"ndv":30,"upper":"430105","lower":"421125","count":1210,"preSum":48939},{"ndv":33,"upper":"430503","lower":"430111","count":1199,"preSum":50149},{"ndv":56,"upper":"431125","lower":"430511","count":1189,"preSum":51348},{"ndv":34,"upper":"440114","lower":"431126","count":1394,"preSum":52537},{"ndv":19,"upper":"440311","lower":"440115","count":1265,"preSum":53931},{"ndv":18,"upper":"440783","lower":"440402","count":1224,"preSum":55196},{"ndv":27,"upper":"441322","lower":"440784","count":1288,"preSum":56420},{"ndv":36,"upper":"445103","lower":"441323","count":1232,"preSum":57708},{"ndv":28,"upper":"450221","lower":"445122","count":1208,"preSum":58940},{"ndv":67,"upper":"451103","lower":"450222","count":1190,"preSum":60148},{"ndv":71,"upper":"500152","lower":"451121","count":1194,"preSum":61338},{"ndv":25,"upper":"510115","lower":"500153","count":1279,"preSum":62532},{"ndv":42,"upper":"510727","lower":"510121","count":1188,"preSum":63811},{"ndv":56,"upper":"511622","lower":"510781","count":1189,"preSum":64999},{"ndv":81,"upper":"520222","lower":"511623","count":1194,"preSum":66188},{"ndv":76,"upper":"530103","lower":"520302","count":1315,"preSum":67382},{"ndv":38,"upper":"530623","lower":"530111","count":1194,"preSum":68697},{"ndv":119,"upper":"540426","lower":"530624","count":1187,"preSum":69891},{"ndv":26,"upper":"610302","lower":"540502","count":1221,"preSum":71078},{"ndv":89,"upper":"620103","lower":"610303","count":1228,"preSum":72299},{"ndv":111,"upper":"640104","lower":"620104","count":1249,"preSum":73527},{"ndv":113,"upper":"659010","lower":"640105","count":1170,"preSum":74776}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1173,384,482,325,429,372,550,403,792,591,412,447,319,330],"valueArr":["","320583","330782","340104","420111","440106","440111","440113","440306","440307","440309","440605","440606","510116"],"type":"String","sampleRate":0.9618625319816094}',17046,0.02436278),('jala_wms_prod','shipment_header','shiptoemailaddress',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','shiptofaxnum',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','shiptoid',694795,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":947,"upper":"10ZU50R26CUTTB5Oe4nU7Le7Fn47H84QYyQ1SSeyYy8OapCvKsGbcE2MfJC38BAw2X8pjyg","lower":"100951SwpNDU6uEf8Oa76lRtibdRic4Zibkwbkk3kotOygsbwJJBzzPShul9iaibeOzVWHYqstGU","count":955,"preSum":0},{"ndv":948,"upper":"11Zge5NwRuVNaN1DE6Xm29SpeVw6Qh6FUAiaGaHe1SCp8bUSx8OagevjU28dmXIB5Cwehjlr","lower":"10zu5gexMntx4UIK1stSHplXsbeWcAMhOibU0cHBQL6hB1XKrgDcGWcjZW4361Sq9nFP8OaY","count":955,"preSum":955},{"ndv":949,"upper":"12zWc65rg1B9lp423X1ANzl45Kdib8cSQIKDg1SBjQZ0pIZ9FwjFSbqjldhoGXKVcAUE8Oao","lower":"11ZGZ54qagYFe6rTT0LU91SdXH8MeTrxZSP1Tx9FIJ8OaN8e2e489BLSH2IvUXmzKEiaBSlr","count":955,"preSum":1910},{"ndv":952,"upper":"13yl0vf5OgvXG8cBSfNPdrV5vMu9UO5gouU4WmOtr3AsVB65BxXp1SOeST5oPxl3pws8OaN","lower":"12zWDi5aKM21eYHgePKJ6376BFdN2pBicokNZ1S4NhGibZlH4otgyZZAqq8mlicS7HrS8Oab1BB","count":955,"preSum":2865},{"ndv":950,"upper":"14xLF5x35bhsO1lhbPbBrLibMD1ScqiaUmZ4LZBfibFa85faffXdxzgZ48Jt8h6Mfu8Oaias3a7","lower":"13YMVwu5FDeLS51mIN3zOfgDdyB1SSpwGxhNaTqno8Oagszic18s0S4gSlto7Esic7TuyDRGib","count":955,"preSum":3820},{"ndv":948,"upper":"15xYZRgGt522FtjESwkoEwSe4QyVeYHRPPCo1tk1S4FLfWxGs5aZ4IgC3HJFrSnEky8OaJL","lower":"14xmadHV5wcJdb7qeap2nakzWJIjMj0lOFUk8yl8IuawFOqvPic9q1Srw18EcEHPGY8Oa5B0","count":955,"preSum":4775},{"ndv":953,"upper":"16xGdc6iaR5D7mTQmGkia1StSu1L8dxpFFCAM9GzOlbWDnxiao185fXBXSsSibaZBw8OavaF5Dj","lower":"15xzicyDB53SKwXblqaAdGhS8sEgtPjhgm6fF3ZGAhlBcBu5IiaKLSA0qOUjGGdX1SVf8OaHK","count":955,"preSum":5730},{"ndv":947,"upper":"17Wt6vQwTex5WRvgdvM23JZyS3qfD30w1okUl1Skh2icSDN8CKkwY2DpFh2aL88OaCiaibXSKw","lower":"16XGXDTVH65DofBK2VNia1SJc8FnCVZm63tTnxUz8OaN1aWFL9jibIhgeNhahm0SPzjVvUibxk","count":955,"preSum":6685},{"ndv":946,"upper":"18vXAg1GKFWn55aRqMia1BeUTkc6zLSKlvrva21SsIMEHzLIqic5Qhkf9NAYIhVX8Oa6iaDaj5","lower":"17wTFlia03y5lgb7KjjvQSy7PwrcwonkPI1SLyu1kibbibxv7jOj7QicEcE4P9aT18OazdG7PFa","count":955,"preSum":7640},{"ndv":951,"upper":"19uacLhbCm33059F3ISoicldiciaWNDibsXxb2cKC1S1dw5HMQcrvkRaTVf3Jkr8OaSYIBnkzjn","lower":"18vxPUoUsIgL5XQ3sNcFbIZ0dSaCd1LAnn4066ddtJKgNP7u49tTS4MlicP22h1Sme8Oaiaq5","count":955,"preSum":8595},{"ndv":949,"upper":"1aiaTO32NmwsVQibtNRnLB21IhyEIedDicN4VvvU51S7hnPoiaq8Oa9s6J0sDCrlWhyNGrfA7PJ","lower":"19uAZE96DSequ5e1SlEgZ1J54FtP0DRq9PlMktSIjRmGNKC9xOqydkpk9pBevL28OapE07k","count":955,"preSum":9550},{"ndv":951,"upper":"1aYbIEFssbBs99WQgDAOuh7CpCRiakPxH6Q3tw5ia1SS8OaFiadqaz3TQLYynuXmlB2K8EfLyD","lower":"1AiavI2HlesQ5Y53saQaRbza6lhAicqiaMKBaMo8i1SbCzrwTKM8OazQvWGkGQaQEe87hLMbguk","count":955,"preSum":10505},{"ndv":948,"upper":"1bibDBhY8Xh5z0ib4whs8ianzQTMERJ6HZkCZFRnP51ShTMx0mt8OavpXevialoy8tMaJP2PNdO","lower":"1aYcbbIzXDu7QWhFF2w40PkZXhnwzjgWJJaCrv5nx1SCo8OaUAhuqzxVic44hM9AFQmkUuaY","count":955,"preSum":11460},{"ndv":950,"upper":"1bXUnyfys2g1rAXzXyMvhUk1eUoWKcbHd253SU1S65og8OaL1BtjOib4XCBc3p6ICZZcPWAw","lower":"1BibIBVNnSlD40i5cvCNBLKX301om3S8ocBqNadNRa1S0uZXyC28OamoPCBq5ELh1hv8OH7FS","count":955,"preSum":12415},{"ndv":951,"upper":"1cibXajpxVNiaQib62ics8gJeuSAxt8RJ0SdaRmZY591SkmUKua8OaLQ5r7pR28QS3pk6RaicDKs","lower":"1bxv7yCvd73mPW809iciaP1mzxZXvaNpDCEVleEJF5XG7R1LnERATbaM6NwYzB1Srr8OauFbA","count":955,"preSum":13370},{"ndv":950,"upper":"1CXawv2eWExzwiai5bWibvMkZEAIgzuSzeZMVN1SrKi8OacrR8j7reutuiaXc9fGYXeWjibzJzfNj","lower":"1cibXQhvv2hPviarLeT4eoHApUaXBic8pyNG8qEjX5C1SWAWYnF8Oahmaqu8Xwk6EkDicQunBMA","count":955,"preSum":14325},{"ndv":949,"upper":"1dI7IbXGEYL56Ghw5zWe46c1SUnu0H8b2Cd3Xnlg5UicLI8OaIibf68PJTwPRSjZ4Ol76Gs5x","lower":"1cxB06iccZILYPE5zCsGtwVwIhC5IHKiaK9Gnz0m2Q31S4a40TiaXVLU6jwu7GmmHs8OaE1oHG","count":955,"preSum":15280},{"ndv":952,"upper":"1dXXtlVcscr2wTWLPRl5xvDyxqfZEXk6JcXqA51SpXbFbx8OaC1dgib0KHFO0GcXrpZdx7Yr","lower":"1DI7lvy7ica5c6Byia1SToXFy8OamMmfcFW5sbZ05TIcQgNNkTfPccEtb6mMabOwxBNylNklm","count":955,"preSum":16235},{"ndv":951,"upper":"1Eibr6S7RI6HOlSUrW5aaUcb4ibhG3Clnx75T8Ks0N1S538uO7g8Oaf1yL3PDRoMNzHG410lia","lower":"1dXYze66E5K2MN9TCU6VsD5Ya0RXYxSut7Z9N5I1S0NTlg8OaYthBGvHuPWzpvj12YXkTC4","count":955,"preSum":17190},{"ndv":952,"upper":"1EYq5LMKlFjialHMWG5rMwbCfVv1hWqhJUTKej11SWdoHZVrI42V6TtUMwS8OaZ81aZIFjVE","lower":"1EibrVDr8cG2QvsD8S56UV1OKXSpI8DvyyyZC0vs3w1STRgCclE8OaibiaED2eHpYMZvIW6PHK","count":955,"preSum":18145},{"ndv":949,"upper":"1FicVhRkzic2XDH2X4F5HuHt7qO4jTPlg7cpCz8GFj41S6SwJ7H8OaP2SfmoOfBsGZb3rtE0b","lower":"1eYrkezTjh3TlTMURG9rdjHEDaRiaKtJjCHcaX5IzGicB1SN3dEJv48UPChS8OaticyRZaKk8H","count":955,"preSum":19100},{"ndv":948,"upper":"1FyZVJ4bohzDEws4V3d5DTcWKSHjAIoJcI5PS1c21S7toWNAUa7EAtsbU47ibLZ8DcZ8OaFk","lower":"1FicVSxoicibib8ewZe5WGuZLgzYPcF1QC2KeZibzlG1SkuxxIQ8OaQyszl5qNeDyQJF1icDIqmjO","count":955,"preSum":20055},{"ndv":949,"upper":"1gj9WzKiaZy995aMTRoq3IhiczPKsuVeynAoCFMIDeIGk2r1SEpP8OaCJKCMDEqryS89iaOYp7","lower":"1fZ057YqPibH4dTLDcGo7fVXHnK38GuicgdG6LSc1SHtwiaV8OayiauIFlFWBfXsbPvkDu5LbXd","count":955,"preSum":21010},{"ndv":949,"upper":"1gYXsE6pOjNxBicmSEbd3rUPMpC1Ae5CwbAxc5Y1SR1LyyHnX8OaaMWRRb3YNCblvjVWwfIp","lower":"1Gj9zbg77icQ05fJzpPF91SwHD4epNsWPuXKmNT7Lnoz5HQWvRRk8Oa01SIhyibKsLCqHYBn1","count":955,"preSum":21965},{"ndv":951,"upper":"1hISd8n7dh56kibC1Vnw8F5WB3xSDTGoo1SAGxFgnVoxibx07A8OaN16PiaBia5ZJLdEnOA7ejq","lower":"1GYxZpK5eHVibVYyH4Al5cFTVibTJZv7dQVXhLh1SCW77sXL3YibwicvKEL9a73hDb8OaoV9XMq","count":955,"preSum":22920},{"ndv":949,"upper":"1hxwfaPVG1QgGX3j5g7kmJf9TrfUibicpic17ibWklSNTUi5bEQaZibkV6WMsQi1Sb8OaM1pKlwm9o","lower":"1hIsQ32mNxLKP6sw2917dn56xuNibeVPgG9IUX7jslXqqKAO1SbelMAtDjvYu8OaWJQp465x","count":955,"preSum":23875},{"ndv":949,"upper":"1iaQrsicmDBl8BYFlZjPPGUvxlTvst5JMFoI6L3YT1SPH2m2Q7g8Oa8P3bcvhlF8Tt4cQYKES","lower":"1HxwPvzTOZqC7KMTy4g9C5eyEbW26iav4TttHvr9Fxpu5LVLEesRiaxFg0KXM1P1S68OasqVs","count":955,"preSum":24830},{"ndv":952,"upper":"1ibpTmQkXAPUcLFUQ1SnPicicKhicSfyY5xXLcxPl5wibLyF11SYRpnKXM8OaV8pVugNGZmTk7eI","lower":"1iaqsFValsebasaWLNib5yDbUQMbFNdrhWUf6gAi5cOajps0x1StQGiaROD8Oa69D7YKAdqdVOia","count":955,"preSum":25785},{"ndv":948,"upper":"1icOy9ltpDiam8F3q3N2mytu0bEY5NrwicfbdZzKrdF1SPJh7ND8OaM0pia7lw7S2YKv8rdibn4z","lower":"1ibptTnibZ6EpKXHvicVlljNBTCJ7ppENPRTzZUdY5n3QvtQc1SEXLqNaf8OacIt1iaPYe70R8k","count":955,"preSum":26740},{"ndv":952,"upper":"1Iys3jaHo7s9KicYSIOcvp5Ru8XLsnIQmOrXNxVFbypOMsJ99iaP6ic8Xia1SuNBDO38OaLGbv0","lower":"1icoYIPYsza0jWYpMdZojBmnkraufY0CpgCKNd6jsV5eGh7SL1SfAibyC8OaR9NPV4UAhicvdib","count":955,"preSum":27695},{"ndv":949,"upper":"1JKJzOOsiafcfQtYlEBky3t51SP8Oa23AHlt2DPk18GibRx0zrOqA5NBPF4OjnqgY0xYA0qDF","lower":"1IysPeadicEIwV9MzIomuW5rZztha4ewufrhK4Pn02DxoibziaGFNYoUEKi1SbzT2kP8OaHRECx","count":955,"preSum":28650},{"ndv":951,"upper":"1k1SP5NQuiaTmUHQwicfJHiadstRWSSue1SZ57fpU15E5AUcZOWo98OaQ2dUE7icy4zBZp8m5vib","lower":"1jKk4XW4IrCXrr3mcQUyhXHS5C7pSENFDETkTHCAnbq5eWX9BD1SP8Oavvm5SvZqVy3WlgL","count":955,"preSum":29605},{"ndv":950,"upper":"1kjfufjjTSz9YmbgaGibQy9oO7T00TCdxIBLblEfjpL8s5srC21Sg8OaEEgfC50TDdFTfNhx","lower":"1k1sz5U3LOicLNL47f7rFuupSeaNZ7NA29hWeRQzAqZ5Fibjjsq1SrfVGEDGs8OapYq4uRMFW","count":955,"preSum":30560},{"ndv":949,"upper":"1kzia1KRXg6knwU4iamgibd1kpFX97KBiazULOGwmTnVUBPF5zS1SibOblZ2mRKrJLTq8OaGKj8D","lower":"1KJgm0FqUdjdib5W1jNGPsw5D1SwhWeMTl74BQaGP5icesn398OatlRtCRibkhfxXVwqibccwKb","count":955,"preSum":31515},{"ndv":950,"upper":"1LIjbFz5HRQyPcfn65zZ2557nr1SfkX4yIztpUrp8I525Zxj36AJ8Oaiaggj4payWow9BfiaQ","lower":"1KziauF6ibH2ak8jEYdO6B5J5ib3LClp4Ew5mfuKSYfFa7tL01Sm4HicFyvafgGherDv8Oal5yq","count":955,"preSum":32470},{"ndv":946,"upper":"1LXN2BfOxYIoALkauS5mje6M15Y41S5hl7JwaRhu8Oam4tHZ6a0K2XrvsBCXxDGNl14aHmf","lower":"1lIJp23zb4EKj15E4K83Cs5E1SYnMl5PARtWYYHd1wxvLbdrf3AmWd8OaL8Hlqzn2BQ4icx6","count":955,"preSum":33425},{"ndv":951,"upper":"1mIgfNhWZ3P7GthxnyIaaZ5ATpyjsynVudpqrhZBELuch161SYJBnDk8Oas5YTrlpf0tCYT","lower":"1LXn37KxIZgic3DepTgydLHeK5QicsCoJ9p3Pg1SJNqtmZZSSZ8UR8DU8OaPWxiarl8XvIwowW","count":955,"preSum":34380},{"ndv":946,"upper":"1mYSH1OQXaJNYgxdgZFAn5VgXucp9j8n5p5OhWR1SoPQcmiacvfv5N78OaOlVoxYsv6lMzgY","lower":"1mIhgvxWQrWMAu1Jx3EXTu5kRJpPppzuyBl3iaVgKUxbSB3s1SQUqa48OafHTXbNu0EAdEBG","count":955,"preSum":35335},{"ndv":948,"upper":"1nIE75RMTnsaqNAQm05MFTh1SQETyARTibXk2TSyttr1b7UuQnh8kOIU8OaCiaST8lKiaqmcQia","lower":"1mySiaIcrOBCIgHMxicwBusIx0eagLvS5Yb4SfhbXCPNc4ianiar31SQb39KzgfSwz58OaedUrs","count":955,"preSum":36290},{"ndv":950,"upper":"1Nzicntiandw99v1miaKYdzRN215XPLnGtEhFAtdRjZrF4MnO1SRG0HbB43ibpXMANia8OaZUepN","lower":"1NIEahJ1fYrNSP8PBZ5GeMd1Scj9rP8OaOacADpjHclbXxNQOS05cYMibglBXQQpgkhefIBI","count":955,"preSum":37245},{"ndv":952,"upper":"1oJFxVm8aIpKyx512Hq51zuK1SvxCjuIcsSuiaLx1NQnKj9v1hULKInzi8OaczY2JWGHNKCCj","lower":"1nzIm44gUw46cSVMzMTo8D5IWksk77b9JwRPKQFXaF9JRehRcI4vBS1SLiaT6AnXhsn18Oan","count":955,"preSum":38200},{"ndv":945,"upper":"1oYwxnGjWWe6I3c52PQrqyImmKwElBs9yCuWV55LRvicEhrX9q05Wtg1Sv1pogS9P8OaOtaib","lower":"1ojg4KUwzPRhQ5qOVPqONMyGqAT1Iy6uhxzJBQLAicPBib5o4f1SrCCUD8OaTbBKtI5CkGDPB","count":955,"preSum":39155},{"ndv":950,"upper":"1pIFibIU6hT1tboeYBK5oxi1SbTRTQFCnUDEqq9952trQNZJ7Pibslo6p48Oa57BOu9vA4ialJj","lower":"1oyy9SibOL2cUwx915tfwichyFz1SxmZJWrRpFPbWpdSVktn0dSxhi5aT9kDusrOh1S8Oaz3F8","count":955,"preSum":40110},{"ndv":951,"upper":"1pXVKRxRI7n6hD9PXkotzpCYSXKmwWpRSgj5ib1S2iczt5fa0B5R8ruYMk8OabJ7afUPX9pxf","lower":"1pIfXITBRDpqpNgTxuJWyL50Qo7wxGNgx0mSmia8GovUTo1SNdesqMnMvl8Oawb27VzA5cNq","count":955,"preSum":41065},{"ndv":948,"upper":"1QiaNPVibzibYQtgq62ZsLAznulvTw5CqWCKziaEh1SlARLKuaK8OamgLbWLey5icHhm2CoClaEe","lower":"1pXVWicdv5FZWGgKbQBicbzlwwaM9w8icvr5vA1S7zSsuicYd6Tp3oAo2d8OaRgBBhPW3mKPWFib","count":955,"preSum":42020},{"ndv":951,"upper":"1QyG9gZkyclPAXib7W4c511TsDmBlt81Sye7UH0s9PoECoxGpSW8c6kIFxMuK9ePH9h8OaIv","lower":"1QianzVfr7ZIf8ibCcfq3CShBJWia25LvXyiaicic1SDy88wsTy8Oar2pL4GtiaWFwajEx1zdIrtma","count":955,"preSum":42975},{"ndv":948,"upper":"1RiaWt0jJ0ImibicK6XNicYHZs2Osod5WNgBRx4TQ1S3UdJ0jia8OaM191icIvwPzdVT1x4eSVvTz","lower":"1qYh4CibSGkKf3ia2Q0kPS8VCmqpjdPiaryuwH5Kj0deLlq11Sdwo9QuS4w8OaibJdJkyv5usGia","count":955,"preSum":43930},{"ndv":949,"upper":"1RYIYFRH3BYvNvCAR1Mdqs5LnjFnge9p1S8uHTHxy8OaEYISlAuHxOjpVD3fl83ibpHDT6QE","lower":"1rIaWyWvTwwkoGkJo0xK2Y59mibpUeXWH7UhIKrRd1SAt2mqNI2rGusC4law8OaRRvJSdpFk","count":955,"preSum":44885},{"ndv":950,"upper":"1sicnAFnjve5DG44DIMibRZXA8EVUJlBj0eibt6XYP5KayNwh1SnwYrLZfrD18Oar6pNgdS2eib","lower":"1RYkEgpQJ0bAWEWdUuJ5MYxKWw2pye85BibnbmG1SeQMKHIlt3EIa8OalQe225A3eQvHYF5K","count":955,"preSum":45840},{"ndv":954,"upper":"1SYHW6HXW449Qh4FdPLia5bffA8tibeWp1STR9FFm8OaBSqCZNOCzxX4DPBV4eNqGtqth2g84","lower":"1SicoHO4k4rnfx1NOWd7ibwmS1G9YPCS5cm3JKm8mj11SEibSni8OaasYDfvW3kgNTzTmBS3ibGO","count":955,"preSum":46795},{"ndv":948,"upper":"1tIofic5lJEGPTUk9O9Via5yVS1XqNDRcJ13sBTx5ow6eWgahZkjIai1SbTMjQ8Oaxu3xtw8My","lower":"1SYiaGkCYS6GdpfzorFlgEahLia1cc4d5Nia1Ca1Sv4HGxeicIq8OaWA2xFnPQLN9C7WSBMbHKq","count":955,"preSum":47750},{"ndv":950,"upper":"1TZ6xxpM1B57EYUQoXtGYj4lGZSLXDZnAH1SYY8GWT8Oa21qkL1F2cE8UxAicJ4AYwYibdRNc","lower":"1tIoONt2ibKAQJKzAYBPia5dFwgNcOo3CUOial4zKMiatOKoiaTaic81SFdNAh8Oa02A8Gmn6A1iaq","count":955,"preSum":48705},{"ndv":952,"upper":"1ujYjU3Uo49LdeSaDmtbU2yP9W25U3VCU2JZqi5cUVBfQyCwYf1ShxevC1iahic8OaibKA3s9nZ","lower":"1TZaVsuDoD26RSMbRIwto3k876jp9CG0U5LwModd1St8Oa2bicZuOygB2LiakWQd8PT9CI7IB","count":955,"preSum":49660},{"ndv":948,"upper":"1uZOY1mAgLzdricfIbfv9icRFU9j55onaaibf8yq1Sn54yhhbXsSAibbP6Z9o3s8Oaj1w5tEoLib","lower":"1ujYu76WsGZk2iaOCY06jkH0Gm5P3rVGiawpoi5cNWm6dUGySt1SFXXAGUrdt5h8Oa5iaWgaNLY","count":955,"preSum":50615},{"ndv":953,"upper":"1VIwYUWazqXaNfn7bvQvB55AD7BJCCjxY2Ma1SqiaaW67ibXT1IIWRp9ZHniaIt2G8OaNAq6jj","lower":"1uZOZT1Kic3F5r2kyH3Hy1vsLttn5Bo3hRnLpGVt1Sxp1XgCFRqVCYt5U00v74k8Oa7ibH2Zm","count":955,"preSum":51570},{"ndv":948,"upper":"1VZcTU2qnZFsbcRg74xXPspwGic7nbyxfzj5gcwr1S6c58OahlCfwlp0Q8y0W58ziaPouoAWz","lower":"1vIxaQxtgr6ibKSwNBBe7V5PK8IXpzJ3mmumsQOzfkdjl4Kiap1iah95sqGBhA1S9d8OaFicQCp","count":955,"preSum":52525},{"ndv":950,"upper":"1wJEuALO5hurJNcgXb5mlkvg1SLib75lowM5R7VwDIXMczoagVEJQKzRKvDHRicIm8OaQaGRw","lower":"1vZdTDHb9EmfZyTTeY2xwzpicBfWIJZq7oaOC9n5hVwi1SalqwibxbqJ9wdicXJa8OavPD45WqO","count":955,"preSum":53480},{"ndv":949,"upper":"1X105W1S13XGdIuZIFjWeRialKFYql99ibWs1nFV8Oa61gP31DBkQUA1IdbShibeQ1RnoflwRn","lower":"1wjfFImDuOtFKWibmiaHjhmhVibp9gqBkBt3pldSC96Iw5XLZm1SHOcynPwz97LLh8OazscfSV","count":955,"preSum":54435},{"ndv":953,"upper":"1xKaH26evB0PyljuQfGdOA0b5kcJcr17hPS28J5mb1S1DKlY1EDG10ia8dMZZnhW2B8OaRQy","lower":"1X13r51I1Sn14WCGfJ5wUKCLiciaBGVhHRxmVsRG8OaSmbJjsD6aqV6ov9fXCQQHmcolkNLoA","count":955,"preSum":55390},{"ndv":951,"upper":"1xzyGpDtUE2l9Jxq59bKibM9KLIffFianBib2TDx3YYYCPR2Y6FNIFr5f9oic0D5i1Sa8Oa6AV5m","lower":"1xKaibwcXEibGqtESLZzSGf25Z5CxfbE9bJaiaSRs1SfK0nH5LI0YSRYoYSR9RhtpP8OacRWHl","count":955,"preSum":56345},{"ndv":952,"upper":"1yjQzr1vFgskGnSgQtpc27vTUZib6W59SI7o5nh5FU6s444cOb1SibYYkPJ2s1ic3gZ8OaEmZX","lower":"1XZypfrEX5qeFOwJibG5fksJ51r1vZYsMQr9R5Kk1SxtVzVbGg1IUFic3eZicwMNXIZ8OasdR4","count":955,"preSum":57300},{"ndv":948,"upper":"1YZed3CD5tpJzib3fIrlftX3HfSlJqQoHhEfeL5w1SdicWt8OaOzHjCq7Y4Un8P6BI2bMVER6","lower":"1YJRPkIwaah5ZGEuRCBbic65JhdqIXo11Sl4sGQxi8OaaCic0qIfxQpP55QLo9TE94z0N8icZOq","count":955,"preSum":58255},{"ndv":953,"upper":"1ZJ8kevVooM55ETfCPshF48r1Sk1rpbYOSvVKJaUPW8OaI1wgDaf9UVPQT0nWP1ICuls562","lower":"1YzFsG3GniaOAk8RPDX568oevn3w8gj4NlC3PPa1S05LCWkhxzicGjibiaHNcwMU0SMX8OaQCXT","count":955,"preSum":59210},{"ndv":924,"upper":"1ZzYOyEEHJ1hB5gJbQ297RKTuq8qJQDDW8vuic5I1SsNxPhniaIKCLOnfgZjcWZChjSs8OaIn","lower":"1zJ9f6Dpw3KcD5iaTPTicAR81SIIHic8pHXibTZGt7jibBxQaTeByK14O9r6NYP2pLmB8Oa43GQ3","count":932,"preSum":60165}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[37282,3,3,3,3,3,3,3,3,3,3,3,3],"valueArr":["","10l75qrHFENk1S3UVZhEoRyUauFhhD8nhnhJIfy9icnHwlkVOYPnXg8OamiadQOtOlDmvTkqg","1Bo4FhOU50e6iaeM1SCokKQ9ASANK0BTkNu72a3QSq4iaqJRbP1F7nx0r8OaMZvwvheGeFghf","1DfHnI9I4bItt8rUJ56wtH1SvyeLpicibB9nwiavJN03CAZB8OaFdicLBencK3kXu0HnppKHeVF","1GtL9yxJUozicnRQO10i5bhDmb1S38jnc5lvyOSXNQf8qGhCae32k7ibiajSWs8Oakq73p8LvkC","1LMejH5Uo1B1SIkctqfb1PzCP511SB3p6ic6XygC8FaicPV8OaHwbmnm7VOzJTOW7gJic3vDLR","1SiceW87FnAEnrTzQn2qibIU99M5zmqp5JYNz53T45i1ScGUu968OaLbLYTUyibo1sb77nZrRbR","1UoMVqLjfm5oBoalcmTJSYT8bT5WJCXHpJT1S6AmYrCrPYCuWY8ue25Oy8OaoUrNhpz6I0n","1bUG6LkZjs2PGKvCVxT25QkTqiaAAxiaKkk1SxefKR7P8Oao2UO07WU5K3ic9PrPXHU5EqgSDn","1icejum1GOTQwd3kXhnO7aRQrN9z1LJOjSrxID6Jq85Gx1S4oUv8OalHt4CZiaiaoc3ff0NKpY","1joAWUPhMHg5N452uuTJfrLJ0Wo6eas0iaKkDrINwribL37nHI1SmfqWq8OasRybrK3NDicRRG","1kiccOoJ3uV4KzROMsrPxWDyZEVbGAve1n9dhWO0rD53MTGib1SCA8OaS68a29fTUU2OCEGZ2","1qGKTL0x7F2W5mVAdm995Qpib1SBAscVicyibnXvW6RgspZ6vCXTSdfRbDB8OaUCbyXBowNvaV"],"type":"String","sampleRate":0.9618625319816094}',1586,0.02436278),('jala_wms_prod','shipment_header','shiptomobile',347406,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1484,"upper":"$2Xq/kbqzPz5Y8Hj+4+BjMDXKSJ3ZNVLr/KVHTbzCjJA=$QS3tt3yv+Aaba/YauQ+ounk3axu4EMhb1Nwk6frtiHo49Mf1wcx3mJhfwGyf4lwV4XIP7v+lyYc9PJOOHr","lower":"","count":1486,"preSum":0},{"ndv":1485,"upper":"$89QhKQEElQMMnCPycqL4wMb9/Mts1Mtm+zb4iHbW0fc=$sqNo2dxCdm6hwlC3tyHGIxAfv0ibv+FwfZJ77wRbiOYohgIBz1zkIvuUE+ywKk+MEqfZKLWUH9su3UnxeR","lower":"$2XSrlhBF9mCAJ4Uvs4H+4Qdxd8EAL1UUOwGQzyK2FB0=$4JzQFS/vr83U1lZCIij7OEk7zuJiMXXLD+mB1EPfgnEGmfoYM2iakDqkUKmN7iW3awVPIViD+F76TXUaec","count":1486,"preSum":1486},{"ndv":1484,"upper":"$boPAiAXyVKkpvPlIlVYJa629pEfAhp/hxna5/PZpW0U=$cF1njEniSTTCnqm65PxaTy9QMyIq1JaY/PN3AHYkwZVvsvNbemxkWSCf4FPvbUe9I+yxGigBueK6ic4mXL","lower":"$89v0XYlPsPCA2aLbB7NXfGiw9Ix7vrfZNRuwVIRf4ko=$I+y97QTpEu+ZYFs9aXXuV/KYqm2zM06Od9ccF17rO9RCBTBrejtVsrvtd7k318CyyGHUVpyuXmgUiqsumX","count":1486,"preSum":2972},{"ndv":1486,"upper":"$eG/qWFjyradE1P3TXOcAQn81DjZOOD+EH6lY/qHbm5w=$GLmrX5wb8Mxlh+DiLSWDXHo+qBNpjtLRxXjhjSVmTLGGb34k/5TrWwU00cofjXH+8TUkD36DmfBtQya05n","lower":"$BopuWlRu9i3ELJoSKVQkUB+G86R68OuNy5JbZHMCBhM=$Ma4HFUY6nITdD2w4S/sbBZIJhjQJNPuI/Tss2CqqkMKl2/jlOGn2cFvuumCad8vlpanJyIeYjoo+id27ep","count":1486,"preSum":4458},{"ndv":1485,"upper":"$H7IMSrBfxjuY59eqt1WlcGtznX/lz7R6tDToHQB8sdc=$IKbaySGOFn1xKuyB1BkLUtqK3en4O/f722Xh3LlqkTqD0FBbU6PpARK1RxBWdjLIvz5ShqxoJ9blAjkif/","lower":"$eg0lAOm1Q8qXJ7EZ7OEprSuwpXFpLTf69hSozQBATco=$YbrYLkBPMxPWcd/Tyj5qo9jZ+rQO1qi7FEJOX5u0hFzoTQiGFec/npi1SzuvK9uHtTJwvou18plvd2/Emv","count":1486,"preSum":5944},{"ndv":1485,"upper":"$JyYAZWvoDmXTfIG94KyX4cfEInbDwY7JMwfvOAzO+Rg=$jUTnHtY/rpnGg7Z5woYvlWQQ039IAPdSLWdxvEJG9Nqj2g2SwCs+LtDmNNZA56NyrIyUfDe9Ynb82y0wkg","lower":"$h7KrR4HpJBNMWb0RKrxqptsNBAl2HPOr1HnMLK0TIpQ=$3731mzE/BVU8EwVulJWo4xOgUDbveJ00KPTjJ41Y05uv0IVwhW8upxjj+CYw6EAda+Yd9nINWAFFFY7zn4","count":1486,"preSum":7430},{"ndv":1486,"upper":"$MqlextcepAdFG3NRFhrg3igRLPdR0yPXz8oJMKXJDns=$TYlJbLGRpiOG7irbdC5CaTj9UJ+a6fxG87ggDnCP1DAKhw/b+EF1ySn2D/uMkclVDm2EeB3RHBQt7V+2ZB","lower":"$jYZXcBYzmLoIADqh9zHDySMrHMxHrN3KUifdWhH+8yQ=$39V3pKFf4LwhrijaWawf5Nvti6U2CveqTMkX44KytZF1fCQQjcSrFwenRyATGnheIqAu/hS79iYS3xaTAG","count":1486,"preSum":8916},{"ndv":1486,"upper":"$pG3/br/G4a/UDIcrVTNiCcsNRApjMMLF0me5w1M/W60=$3VJNNJ6Afa43KVACvnFnarxlsUjCNZAW3s849nQZkJL7lPDWFs4FZYqXmbc2WiWYl15gFuQMgsAjY5K9eO","lower":"$MQm8GVlS+P7jVVfYPf06RrTzZHsHxlcIl9z35XgcqRI=$baTzs9YUxlo1pAOEDNdfQbNj9VRZjbJ2yh4RfoGaBe9IMXIibpfTlrdI1iFJX7BDwBO9TgAJ+yJTqlfHpH","count":1486,"preSum":10402},{"ndv":1486,"upper":"$S4z1LTxAM5r259Qnn1ObyVCh5WfJ3L/GIDpXo84VNRA=$J3uNlrcwHjrryHk/KpwCzazfY0CjLKuN9FOzJFkiLnjS/z1LXfg3lS04On89o4fkzSWNmm2k6U/Qv3Entb","lower":"$pg7kHCV1i1XPo46rzlrdiJArHdPBb08dZYKt/1by22w=$6Kfm2UDLaQM4PKoImYm9ML+/UDufWyAxnTyH80USLSRWb9YVUMFfE5XeczrV3BCl/fjvFNqN90aJl7naKn","count":1486,"preSum":11888},{"ndv":1486,"upper":"$uQic6Ia3uoeX1n/4q8vxrzzqTP4DWG9RVNmqUy0jIwY=$KYid4oHyMGRX8/MXZzxchdKkYrzJm7TxsaMAGzlkdtAcawl7kGHLkb0V5v0UTRTSlyoRtQXKstei4FU+eb","lower":"$S5+Q8T2X5QnsTzzzrsW9hVc56tMUUL/mBD5QpxqerIE=$IYQtbR73iJOVrNWjZxeIvMDFpa4UBrA/HzVTwSN4Khoy+0BSAtPTGfm73NEQOjeGcGSKcm6MmUoJsEo9AF","count":1486,"preSum":13374},{"ndv":1485,"upper":"$XK2n9rVmEAm9yVLUsmAw4FfNijTUOYI4DEmnbJLA+Yk=$NQEhx9V+PQKHw0idIcCsjYNlwpkf8qrWwMOiJhccRZlu5HJmgS8i4qxWiZe0wC+wGPrEBUFK2w9vFM9UQU","lower":"$UqkgyAaOFuMzlMNDf+QQQAqeEaDKINTdkwPQB8xA684=$Ehmra0nPWdQir7ukI0ng9ptzgYlx4xHbKIWI+1L+qkdnViUucwKRyh+ZbAjvP35390Dk7DZr1403BBjpjx","count":1486,"preSum":14860},{"ndv":1347,"upper":"*******0027","lower":"$Xk4YqAo0JFGk$AgAAAAH8Ui4GxyzlawDai7uc8CH2GWLc93X3FfYmD/c=$12$$","count":1493,"preSum":16346},{"ndv":224,"upper":"*******0252","lower":"*******0028","count":1489,"preSum":17839},{"ndv":253,"upper":"*******0507","lower":"*******0253","count":1491,"preSum":19328},{"ndv":216,"upper":"*******0725","lower":"*******0508","count":1495,"preSum":20819},{"ndv":221,"upper":"*******0947","lower":"*******0726","count":1487,"preSum":22314},{"ndv":227,"upper":"*******1175","lower":"*******0948","count":1493,"preSum":23801},{"ndv":229,"upper":"*******1405","lower":"*******1176","count":1490,"preSum":25294},{"ndv":254,"upper":"*******1662","lower":"*******1406","count":1490,"preSum":26784},{"ndv":244,"upper":"*******1907","lower":"*******1663","count":1496,"preSum":28274},{"ndv":226,"upper":"*******2135","lower":"*******1908","count":1490,"preSum":29770},{"ndv":226,"upper":"*******2361","lower":"*******2136","count":1489,"preSum":31260},{"ndv":269,"upper":"*******2634","lower":"*******2362","count":1488,"preSum":32749},{"ndv":226,"upper":"*******2860","lower":"*******2635","count":1491,"preSum":34237},{"ndv":230,"upper":"*******3092","lower":"*******2861","count":1491,"preSum":35728},{"ndv":238,"upper":"*******3331","lower":"*******3093","count":1491,"preSum":37219},{"ndv":260,"upper":"*******3592","lower":"*******3332","count":1491,"preSum":38710},{"ndv":245,"upper":"*******3837","lower":"*******3593","count":1488,"preSum":40201},{"ndv":268,"upper":"*******4110","lower":"*******3839","count":1488,"preSum":41689},{"ndv":340,"upper":"*******4453","lower":"*******4111","count":1486,"preSum":43177},{"ndv":330,"upper":"*******4791","lower":"*******4455","count":1486,"preSum":44663},{"ndv":289,"upper":"*******5083","lower":"*******4792","count":1486,"preSum":46149},{"ndv":226,"upper":"*******5310","lower":"*******5084","count":1486,"preSum":47635},{"ndv":249,"upper":"*******5562","lower":"*******5311","count":1486,"preSum":49121},{"ndv":235,"upper":"*******5798","lower":"*******5563","count":1488,"preSum":50607},{"ndv":226,"upper":"*******6025","lower":"*******5799","count":1489,"preSum":52095},{"ndv":238,"upper":"*******6264","lower":"*******6026","count":1486,"preSum":53584},{"ndv":253,"upper":"*******6520","lower":"*******6265","count":1496,"preSum":55070},{"ndv":217,"upper":"*******6737","lower":"*******6521","count":1495,"preSum":56566},{"ndv":222,"upper":"*******6960","lower":"*******6738","count":1488,"preSum":58061},{"ndv":232,"upper":"*******7192","lower":"*******6961","count":1491,"preSum":59549},{"ndv":265,"upper":"*******7458","lower":"*******7193","count":1489,"preSum":61040},{"ndv":243,"upper":"*******7702","lower":"*******7459","count":1486,"preSum":62529},{"ndv":234,"upper":"*******7936","lower":"*******7703","count":1489,"preSum":64015},{"ndv":230,"upper":"*******8166","lower":"*******7937","count":1493,"preSum":65504},{"ndv":231,"upper":"*******8399","lower":"*******8167","count":1491,"preSum":66997},{"ndv":259,"upper":"*******8660","lower":"*******8400","count":1498,"preSum":68488},{"ndv":214,"upper":"*******8875","lower":"*******8661","count":1486,"preSum":69986},{"ndv":224,"upper":"*******9099","lower":"*******8876","count":1497,"preSum":71472},{"ndv":233,"upper":"*******9332","lower":"*******9100","count":1491,"preSum":72969},{"ndv":262,"upper":"*******9598","lower":"*******9333","count":1490,"preSum":74460},{"ndv":221,"upper":"*******9819","lower":"*******9599","count":1490,"preSum":75950},{"ndv":454,"upper":"131****8792","lower":"*******9820","count":1486,"preSum":77440},{"ndv":1465,"upper":"136****7219","lower":"131****8905","count":1486,"preSum":78926},{"ndv":1460,"upper":"139****8890","lower":"136****7256","count":1486,"preSum":80412},{"ndv":1454,"upper":"15259116829","lower":"139****8908","count":1486,"preSum":81898},{"ndv":1454,"upper":"159****7791","lower":"15259120432","count":1486,"preSum":83384},{"ndv":1460,"upper":"182****3290","lower":"159****7800","count":1486,"preSum":84870},{"ndv":1472,"upper":"187****4401","lower":"182****3301","count":1486,"preSum":86356},{"ndv":1465,"upper":"3065370e78dd8d57feef8ba8406c5877ee20b6d8f80e275f91bc6559047d68b6ca2068","lower":"187****4585","count":1486,"preSum":87842},{"ndv":1481,"upper":"3464624db9a68c255313266346e7cee6077e2926a34b3992ccfa47b1ed56ce4b97f6be","lower":"3065370e790ad723962407eafc765c46de57418bd01484ed142d83db8014eda6db1278","count":1486,"preSum":89328},{"ndv":1478,"upper":"3864308d0bf308ee056247dbab2d3982b53bd9174892d50f16d252aa7ca3bf0b73fc7e","lower":"3464624dbcbb7016ee130fed98a6ea96b09ab71eceb139c3eb5863f7c70b9e6f8027e1","count":1486,"preSum":90814},{"ndv":1478,"upper":"636366ccf6f2cbc7d63092c505acfd9fc1b0de0aa6054765d3c00b4c3f32d843a1e4d7","lower":"3864318d13259b8f868f57dc39f2fb503f8e7d30caa52da3747c8c5f328f54743d893e","count":1486,"preSum":92300},{"ndv":1265,"upper":"刘桂平","lower":"636431cd1ae4f720bb9db50f63baba191e74de87851521b29ac9d1d1ab8803c9549114","count":1275,"preSum":93786}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[43,18,18,20,19,18,18,18,18,116],"valueArr":["(021)6056 2952","*******0251","*******0328","*******0521","*******0800","*******1760","*******2082","*******3007","*******8810","15857945451"],"type":"String","sampleRate":0.9618625319816094}',4634,0.02436278),('jala_wms_prod','shipment_header','shiptoname',13135,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":26,"upper":"【H】佳乐家超市青岛即墨店","lower":"1+1化妆品店","count":35,"preSum":0},{"ndv":31,"upper":"【H】步步高怀化店","lower":"【H】佳华深圳松岗店","count":36,"preSum":35},{"ndv":28,"upper":"万众城万盛","lower":"【H】步步高湘潭华隆店","count":35,"preSum":71},{"ndv":26,"upper":"上海自备仓B2B(顺丰)","lower":"万利化妆品行","count":55,"preSum":106},{"ndv":27,"upper":"中心日化(劳动南路店)","lower":"上饶亿升购物广场","count":35,"preSum":161},{"ndv":31,"upper":"丽客隆长水店","lower":"中心日化(车站西路店)","count":35,"preSum":196},{"ndv":21,"upper":"亚泰超市","lower":"丽洁日用化妆品商店","count":35,"preSum":231},{"ndv":6,"upper":"京东成都仓","lower":"亨达平山生活广场","count":39,"preSum":266},{"ndv":13,"upper":"仟丽店","lower":"京东昆山仓","count":35,"preSum":305},{"ndv":32,"upper":"佳美日化","lower":"仟仟万家超市南宁钦州店","count":36,"preSum":340},{"ndv":25,"upper":"全福元中心店","lower":"佳美茗妆","count":35,"preSum":376},{"ndv":29,"upper":"内蒙古勤获-内蒙古呼和浩特市赛罕区","lower":"全美美妆","count":36,"preSum":411},{"ndv":26,"upper":"北京汇杰思创商贸有限公司(自然堂美妆RKA)","lower":"内蒙古粉蝶商贸有限责任公司(自然堂美妆店)","count":35,"preSum":447},{"ndv":27,"upper":"华东洗化美妆店","lower":"北京美创美捷-北京市大兴区","count":35,"preSum":482},{"ndv":31,"upper":"南宁市兴宁区搜美丽化妆品零售店","lower":"华丽港商场","count":35,"preSum":517},{"ndv":30,"upper":"古里单色系","lower":"南宁市嘉燕商贸有限公司(自然堂现代货架)","count":35,"preSum":552},{"ndv":23,"upper":"周记日化馨园店","lower":"句容元丰商场","count":35,"preSum":587},{"ndv":30,"upper":"嘉人时尚苑","lower":"呵美小栈珊美店","count":35,"preSum":622},{"ndv":28,"upper":"大世界购物广场","lower":"嘉兰氏美妆","count":35,"preSum":657},{"ndv":32,"upper":"天天靓妆","lower":"大同南郊.诚信日化","count":35,"preSum":692},{"ndv":18,"upper":"天津蓟州区孟祥萍化妆品店","lower":"天奕名妆","count":35,"preSum":727},{"ndv":30,"upper":"娇兰佳人","lower":"天美化妆品","count":35,"preSum":762},{"ndv":31,"upper":"家凤日化","lower":"娇兰美妆解放路店","count":35,"preSum":797},{"ndv":26,"upper":"屈臣氏-北京仓","lower":"家宜多购物广场","count":43,"preSum":832},{"ndv":2,"upper":"屈臣氏-沈阳仓","lower":"屈臣氏-昆山仓","count":40,"preSum":875},{"ndv":16,"upper":"常平百花","lower":"屈臣氏-郑州仓","count":36,"preSum":915},{"ndv":31,"upper":"康缇","lower":"平凉澳亚化妆城","count":35,"preSum":951},{"ndv":29,"upper":"心雨日化","lower":"康缇化妆品(万达店)","count":39,"preSum":986},{"ndv":31,"upper":"成都仓B2B自营库区(顺丰)-1000","lower":"忆莎美妆","count":57,"preSum":1025},{"ndv":29,"upper":"新世纪重庆南川商都","lower":"成都彭氏商贸有限公司(自然堂现代货架)","count":35,"preSum":1082},{"ndv":30,"upper":"新疆赛波尔供应链有限公司(自然堂商超)","lower":"新世纪重庆大坪商都","count":36,"preSum":1117},{"ndv":28,"upper":"普丽生(人民路店)","lower":"新疆赛波尔供应链有限公司(自然堂美妆店)","count":35,"preSum":1153},{"ndv":34,"upper":"梅婷化妆品店","lower":"景德镇金鼎百货","count":35,"preSum":1188},{"ndv":31,"upper":"武商量贩武汉黄陂店","lower":"梦之岛南宁钦州店","count":35,"preSum":1223},{"ndv":7,"upper":"武汉仓电商自营库区(顺丰)-1000","lower":"武商量贩沙市店","count":49,"preSum":1258},{"ndv":26,"upper":"汇都商贸","lower":"武汉市兰丹尼商贸有限公司(自然堂现代货架)","count":35,"preSum":1307},{"ndv":14,"upper":"沈阳加露-辽宁省沈阳市大东区","lower":"江北百货大楼","count":39,"preSum":1342},{"ndv":28,"upper":"济南仓B2B自营库区(顺丰)-1000","lower":"沈阳碧茜经贸有限公司(自然堂现代货架)","count":44,"preSum":1381},{"ndv":28,"upper":"清溪欧珀莱","lower":"济南嘉华购物广场","count":35,"preSum":1425},{"ndv":9,"upper":"温州弘方化妆品有限公司(自然堂美妆店)","lower":"清秀佳人","count":35,"preSum":1460},{"ndv":31,"upper":"爱尚彩妆","lower":"温泉美丽99","count":35,"preSum":1495},{"ndv":30,"upper":"璐璐自然堂专卖","lower":"爱尚百货","count":35,"preSum":1530},{"ndv":13,"upper":"百伦百货资阳简阳店","lower":"甘南妍妆化妆品店","count":35,"preSum":1565},{"ndv":29,"upper":"真女人","lower":"百佳日化","count":35,"preSum":1600},{"ndv":26,"upper":"筠连四季美人","lower":"真女人二店","count":35,"preSum":1635},{"ndv":32,"upper":"美丽缘","lower":"简微妆行(中山二店)","count":35,"preSum":1670},{"ndv":34,"upper":"美购","lower":"美之泉","count":35,"preSum":1705},{"ndv":28,"upper":"自然堂吾悦广场店","lower":"美迪康化妆品店","count":36,"preSum":1740},{"ndv":29,"upper":"茗雪妆品4店(步行街)","lower":"自然堂(益和北路店)","count":35,"preSum":1776},{"ndv":30,"upper":"蓬朗自然堂","lower":"荔波县香江大道22号自然茗妆","count":35,"preSum":1811},{"ndv":17,"upper":"西安仓电商自营库区(顺丰)-1000","lower":"藁城信誉楼商厦","count":37,"preSum":1846},{"ndv":27,"upper":"辽阳市鑫浩翔商贸有限公司(自然堂美妆店)","lower":"西施小铺","count":35,"preSum":1883},{"ndv":17,"upper":"郑州仓B2B自营库区(顺丰)-1000","lower":"达旗春雷化妆世景园店","count":39,"preSum":1918},{"ndv":31,"upper":"鑫业美妆","lower":"郑州佳之浩企业管理咨询有限公司(自然堂美妆店)","count":35,"preSum":1957},{"ndv":18,"upper":"银泰舟山店","lower":"鑫林洗化2店","count":35,"preSum":1992},{"ndv":18,"upper":"闵家镇江南","lower":"销售退货仓(电商零售)","count":35,"preSum":2027},{"ndv":27,"upper":"青岛福兴祥商业有限公司(自然堂商超)","lower":"闽清阿容","count":38,"preSum":2062},{"ndv":29,"upper":"馨雅日化轮胎厂店","lower":"青春化妆品店","count":35,"preSum":2100},{"ndv":31,"upper":"黄毅燕","lower":"马连道万家上品折扣店","count":35,"preSum":2135},{"ndv":9,"upper":"龙河美肤宝","lower":"黑水亚欧化妆品店","count":16,"preSum":2170}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[95377,65,31,47,30,29,25,25,28,29,27,39,28],"valueArr":["","伽蓝集团","嘉兴仓B2B自营库区(顺丰)-1000","嘉兴仓电商自营库区(顺丰)-1000","天津仓B2B自营库区(顺丰)-1000","屈臣氏-南海仓","屈臣氏-厦门仓","屈臣氏-天津仓","屈臣氏-成都仓","屈臣氏-武汉仓","屈臣氏-西安仓","珀芙研-个人","自然堂-个人"],"type":"String","sampleRate":0.9618625319816094}',2035,0.02436278),('jala_wms_prod','shipment_header','shiptophonenum',159048,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":260,"upper":"$06X2ZJM4t4A41IwgivVGfLHDHxCOnUjIMRMxONpcyUw=$sjAZih8iinxBBhoXMFn8taL6EtYH7tABQvYA29F15IRaGWtXj22/y63aHEbwtmBIzLgDb6+sGxhThZmuTt","lower":"##+4C/wpiOfs69e2y5aLb/sDkYftRE9FFzgBSsKS4VqRx8tepLsgJ9GbzMhTQ5j0dAoSGplVWere37V7szuUhsX6M5CGrTBH/ijPamhbmS*CgkIARCtHCABKAESPgo8T","count":260,"preSum":0},{"ndv":260,"upper":"$3fBsSY6Zci5krp8oGlkblUGlYQKvclrLllwgM95PsK8=$Iotuw/RSoTcvZrqimCxorZrznGsrYIbODmp8Vm1Wfvd8YPdRF8ID0Lrg319lrdR97FrZ9I8OuzeAFAskji","lower":"$07RoGAn+PibBYQMBmm7ifioCIB+Zqo+WhdjACbc9r8k=$9/ukKj80LEOO28GHawdgSVGShBcvft3Xdr55bMeALSVkK1IIbFJEOsdrhuPgxrpgWcWF6H+mx9MPl8Uwyw","count":260,"preSum":260},{"ndv":260,"upper":"$6GYl+2viwoEtcrKfhleSna4b4aMVO3VKg71190aW+1g=$sjPrf89kNLNnvaMokbYcCxbzlicPsM3VcJXMMpJnaN9dHJwQPEJbAZKKzwTqBM8/FiBEv97qJLl8m+PKna","lower":"$3fMKQOzn26IGymGtBjPv/2udFj2Z7dCVB+IoiwrHJ3o=$sfz4DjnBur+yggNR4u/QlV9Y6TLBRFszd0HYbOjvB8DYjJvGBR0tcZC0nc/g1ozqZwB8pI8ZJnFokAy0Zt","count":260,"preSum":520},{"ndv":260,"upper":"$9MoxkCqhnOoG4SK8asq4jG/2F920ecGsPocjV+5k93E=$eyZ0dlvIDyBUfYRAEU992fUY0DLwa4tLtDN5m15nnY+/wiwmCvOBj4Z7Fs+2paTfUkJzbSMZAeZ15Kva3X","lower":"$6HsS35KJ3jfO8UMMyePuDxkfQ5cp2PVEAzmXso0s8/A=$9Dp8hEpJYhvLS+dnNNGUcTHMuFi8lpargbcxgSptuAWKo6D2ggBmL+4bEvyo5+PGsUJoPmHG5Z8ZJ+z7QY","count":260,"preSum":780},{"ndv":259,"upper":"$bcP9s5UcXMktVl9eGpWeAPuqyWW4cWju1UaZs5ZU/KM=$y2zReZ2GS/H5EL4B/UUeZsASHwde6gfTL373bwsBfBybTt5SRqCOWJXOLOtpLsqZogbxZit0nXka4SLljJ","lower":"$9MSnT6x9FImuVKeqKz2Xt6LURFAAp3XElNECJdY/PBs=$AnucWbQf4iuAYeR0/9XmdWHnh0HdOaYMHW7kA6dCmcUABhQf5qgtrLs4OBOorN/QvCQhscEvb4JavI3umO","count":260,"preSum":1040},{"ndv":260,"upper":"$CQ2yMudELcW66tZu5sHnOi3G3ThwojOUFG1Vz8jDMDM=$11a/+s4r0SmcX4RlXrRco5CZ2Yv9pRsZy+Z7au4Z1IFwndmLzpKaYC+yXNGraSMAiG5TdNsHRxM5uO6kIe","lower":"$bD7iR66rZwUAEO8LBsqMeW8yqmjtcSSyM2yWpIZYvdg=$Ndk9g+iok7m8f2uPpKJjKQFUg6Iif5ZpBVlkZ1ELRo0e1kaxSgjnINAyGCpkls0dU086oXDqnVCIcrGnpt","count":260,"preSum":1300},{"ndv":260,"upper":"$eiJ5jLV/lb8kXC2y3upelqUSct/1eWZy2a+46Ei4n2o=$dwl/MlnYJSbadZ3QmR3a4e+pfGsnCLVS4/Vir/NqS/QmPgfebdHOFJtMwFvQuzLUVrA13G5NB9JZIqPe5I","lower":"$cQ5U9edR8o0gN2aSWquRiMgY+NbBKDNTMkG4hFwfaJk=$Om9Uf9ZYH1r2JBmCQP/5c+2GPiGIy2P41KGISNRIUFLc8XVbatJEWOmy3Smr2E3ezE3ydXLA183NWmk6Kt","count":260,"preSum":1560},{"ndv":260,"upper":"$g6Q28m64eDMa$AgAAAAId/dYGEUoT3wAvFAOya962lDQlxJEa/bnsxEE=$13$$","lower":"$eIJt+jAwtMUzM/4qy38+q0mmo8KlPtjzVe+Qy0K5e0Y=$eUG04q03B3GmptIoJU5fJJkBnu1tyusCz91EruNv+I8jn4EfJ+uVB8sRC6N40YsUriO4apuE1t3EggJtkB","count":260,"preSum":1820},{"ndv":260,"upper":"$hXDotXDiLpiYbcR0iFibW/EwRdnaDy1JHv0imr93xCo=$UMnmNU8UmeC6t6Qf+sqcFWGx2r8Im4d+LAZPaULBgbsnnpmiPYh9fJkxAjSDFd45yvQ09NsD+7qsvuOTKT","lower":"$g7m4vJVBZbOfWhJPwn6WfHo9ZguHzmq79sEje+Vxeuw=$TygItqG5cXRMacWfx8S2ndpCmIUcezrQl6MC6BOXAgP4oZx6KxTFJ/k/4laQ+CYuz3JFJP4aAnSuBtv7aE","count":260,"preSum":2080},{"ndv":260,"upper":"$JLOFBjFCvBovO+D0GH0njAiLdxKztEmdcNEUzDtHRTw=$0qGCcyleCOizBzpimyNoqtLFDGSrN1IsPloK64Dek4NbEv7zobhWTY88mC2HeN2n3ZolqGd6+Rzzgb1Fg/","lower":"$hxJkCO5IYFWSkYqoKqJRTxhB4x9sRnTkalByt9F3bVY=$4fDPdbsG+SVK076/pxxCorv67Kk5GmdIgfSANVlGe1j5JYuSY+FQWA0G8nHAJolIkmSIa4ufBP93LkRnnj","count":260,"preSum":2340},{"ndv":260,"upper":"$L435T2zFF/FOl2Nhl5BeNBngubnzVggB0qBDcSf6GfU=$KqPL5ixH+013xg2p6jFEh+b2J6sa7osprCwOsCrqn9mhnW4hh38aG+o6Vssvu72u0P1I/qAO/cgtS0pPUP","lower":"$JLpTZZihuX4Udk/oeXNo8CRJw/LVTDp6XK+8InePjdM=$FIGVYG0KAryhPw6iI7EbZx2ycu0InbHIn+gYBaS0ynWAcJLIHJgYAYhzmOUKZw/mdtuGr1iP4YbygGfaOT","count":260,"preSum":2600},{"ndv":259,"upper":"$MUaLelJMsSxA6LPIyvU204S08kvypb5nduvFgUHOC7A=$uWckS3CI43kzZeRBWRGBkr/wYCRrkI1rIaTdIG7Urzi03DCfMFsy/YordrwRK5+zvO5poENNLA4Or2F2/t","lower":"$L4efcoHYcOcVO8h+miOaahO64Miy0Aw+Lbhrqvr+PWg=$61aBQMRO5K2bvu4yoBITc86G1r/YCaXy8nvSeOKSX8HA5t2k5WmZDiqgopTcbvF3pkn6VpQrqG0IuxxlFs","count":260,"preSum":2860},{"ndv":260,"upper":"$oClcgW4Mbzj8S3WY3WbmEd/8TBkyG0nwAe3pqNfhq+E=$0kDAm78u1pD+X0qEoFK3qDO6oT3yECD8tLZFoBxJ/E/6y560oc9TKAuCaxzzmQ27A3JZn5JjsJQ7w49jJj","lower":"$mUbLp75oBDWaZLh38SB8yVyoYORhLQYvYqiMoXe5SJs=$+aKulDdrAQm8aUocHvRoDK77959QUiNIoFBCpXPqGbArJ1JnkPIo9W5OlzO0Kw0Uag+VjTW0dCPvy6A4O2","count":260,"preSum":3120},{"ndv":260,"upper":"$px2EG5zTd0qCRTgjR8nh5AFREbMksdHAuNycdrXQzBQ=$TscqcPbgEkBj7J1x5mZWE1H0gTmlJUqgshnd6xZ/THYEedVcALw97OQCYvcL1ic1rynLzqoWX4t7Qqu/te","lower":"$OCsC/WfaSObycmVnLaAZPhNGAuryiyUW4iE9UGR1EyY=$p2XGQ6pJkyOQwUa9EFyDhoGHgLrimUm3qfHBkTwUwkxFLoyVgLFQWhDh2vRMPYsRMdtPnZrWSRT649FFC2","count":260,"preSum":3380},{"ndv":260,"upper":"$RJfS4TE2Rh6WpRVjhmiq/IoiGXDcy4I0uXTTCsryfBI=$p/8dk1iEBmqvIwjYT4irRxTcsSX825akko5N5cazC/gtHByuZGg1RpxuFuCGR+5KPLzLiDhji0wkhGfrg2","lower":"$px5A+s5um6CVckbq+0P1JcM8zY1wOxb/XZbFyz/7sJ4=$SmhSwZbbx/urf1N94+0IVfa+3ZoSafJAwiK1iuq+WUJXTKHuy0N5EOOk5XlnbuNYjbTRQTiKjh8S8Gl4Hr","count":260,"preSum":3640},{"ndv":260,"upper":"$TaV9GkV5RhwFhHd69m8tyrdNrtlyYY97TJGN0YewKkg=$vLxo8dTHrLbh5Kk182RAqmNW7dxWh8z9ApA/aKh/UvhUQn0twHQI7To5Pz/jeZ/7m7eqBBT81DEjq7EmdH","lower":"$RJpQ7+thiMMZaFh703nEq9B64TR7gHUTCpHb/FwMXwQ=$r9ZP+WaBrPTN2OwP3I793MnHjpsNBwLQLezte2EMPNiE+kczf8ZKwNfaLa6KYYFRfVUDh63dTusbaldcQq","count":260,"preSum":3900},{"ndv":260,"upper":"$UvEvcrn743PQrbgkQMoJID+0ZE60hCBbIDVVsFrFJ2s=$sFq1/+UlTCMfCuewW5TvUl4X0ost8HUTP5zVxSa8wTyPpfXIn900+WGbSw2Iciq61YL5+VYz0mgl0d6/BW","lower":"$TAYaQcVQHQcvKZEM/T+KTXqB1H1ZS1mHMruUPg8TDqc=$o24sQF9EINfL/VjfB3VqfjNI/TUm5aukBQaHwphf/rc7UB4blvXfiehGWu4nL3UqJprI1UgNhgpikoRr8a","count":260,"preSum":4160},{"ndv":260,"upper":"$WMgt8AiCJn42TH7UUGaAiQ9zcqpLcVEsvKllA3cyzmQ=$skdpRJab4UO/sLirclKhcHOW67ooIkTijCfj70ko8Y0rfeKictpvvcTWWzDQaBo3OvF4E0N7OlzEmY2A/2","lower":"$uVI5vakqSf/Q9LfRQTQpIFleKja5N1BDhP2xyRTcXbc=$FsSwRkyHWj9fgOCgv8xoyZiG2DwKUUj8FU8bdTfOmybpZiGUK2BOUPj0KvGWTLZFWNHEpE/HBvSllDsea+","count":260,"preSum":4420},{"ndv":260,"upper":"$Y54FTQY0I5vs/Yerr6T3PrQ/17SYbb+imUf404WPhMQ=$JVOF4iWgFVcGOyDwsV3PwQhex7VXsHv7z7mJDtcStuH20uNh6FW5cvB0FpSYvLUS6l6GGPliI5LqfxVTwp","lower":"$wMt4iKb4F7Wx$AgAAAAG9yicGPXI/NADcOjrkUnoSvOc9YOhcr/v63lE=$10$$","count":260,"preSum":4680},{"ndv":260,"upper":"$zpbfq5gHY/24CJ4O0ogIRHhuAnRMb1KPp/9ZPMPn8Xc=$QyJDKptZZqi0DdMzg+BNlMmqseZfVBJkTJZ4Ve0/jqJIPeQuh0GevkjLcSvIz5RmweOWQJkamQdiTtYlmH","lower":"$y55MqcF6lDmFwgE8w2Z5/jqGm1V1NhHgdQ0T7Efjk5A=$N3EOAihgLUuJX4E+fJZHI1Y7bQ+FqQwIMa2CVKpS+rQt8Rotlc7y7VVqsBNGU8Jm0Cs4jgZ4BjCAj2ZXUc","count":260,"preSum":4940},{"ndv":236,"upper":"*******0366","lower":"$ZpgBVZV6f9KFV4N2KGvXoTAQj5bG3dn1XjR/uKu2oME=$QypNS4xeN9/UrbPbpFeDnnrO2CnvjxW7BLxJ8lvoKLx+1btu2kvy/59QUJFk2yCndTWwkLBsjA1vBgIAbs","count":260,"preSum":5200},{"ndv":246,"upper":"*******2872","lower":"*******0375","count":260,"preSum":5460},{"ndv":247,"upper":"*******5307","lower":"*******2882","count":260,"preSum":5720},{"ndv":248,"upper":"*******7887","lower":"*******5321","count":261,"preSum":5980},{"ndv":241,"upper":"*******9957","lower":"*******7889","count":260,"preSum":6241},{"ndv":162,"upper":"13262808783","lower":"*******9966","count":261,"preSum":6501},{"ndv":223,"upper":"13526221881","lower":"13263999999","count":260,"preSum":6762},{"ndv":215,"upper":"13650148898","lower":"13526522353","count":260,"preSum":7022},{"ndv":219,"upper":"13778481216","lower":"13651566432","count":260,"preSum":7282},{"ndv":238,"upper":"13904762488","lower":"13778888617","count":260,"preSum":7542},{"ndv":210,"upper":"13998489569","lower":"13904990501","count":260,"preSum":7802},{"ndv":181,"upper":"15127919955","lower":"13998788200","count":260,"preSum":8062},{"ndv":211,"upper":"15310158512","lower":"15128020339","count":260,"preSum":8322},{"ndv":199,"upper":"15810030742","lower":"15311514176","count":265,"preSum":8582},{"ndv":196,"upper":"15930191591","lower":"15810552837","count":260,"preSum":8847},{"ndv":203,"upper":"17816625069","lower":"15930312022","count":265,"preSum":9107},{"ndv":186,"upper":"18216222840","lower":"17837078389","count":260,"preSum":9372},{"ndv":191,"upper":"18502314175","lower":"18216271713","count":260,"preSum":9632},{"ndv":195,"upper":"18721599242","lower":"18503150896","count":260,"preSum":9892},{"ndv":198,"upper":"18932970331","lower":"18721852974","count":261,"preSum":10152},{"ndv":235,"upper":"303439049716e7b3c50c9b8036977c0bea0c354a971757d6c5208bb043fd415ee1791a","lower":"18935525969","count":260,"preSum":10413},{"ndv":259,"upper":"31306110a22b6fd9236eacd9a5cec065b690809fdc82ed200900b3049b08181feeab72","lower":"30346104a00ad55e5d621e9c36830251ef67f84d9785c59d854880d618f2fe81eca31f","count":260,"preSum":10673},{"ndv":260,"upper":"3162651be8003f6ed3313a7e9a4d57db2e653948d825f0192d9fe8e8614466182f74e1","lower":"31306110a86d1237fe3f028b0525e2075e146f3be33af3ddf92b64d49ac630b621a617","count":260,"preSum":10933},{"ndv":260,"upper":"3236372676b48d3993d275205890966dd874155a4b4130e8819e9468e0de1ad7c35d54","lower":"3162651beae97e0126b5297d527dfe02c35c395aed9e992daa0704f7a08b9d36b20c6e","count":260,"preSum":11193},{"ndv":258,"upper":"33316331c60830896e5cae3950509e41895292780f65004691393b6d5f580cf5f46e30","lower":"323637267ee2e60fd97c285ec91deca8f49cc244a7eef44b5a6b65f57cca311556f14b","count":260,"preSum":11453},{"ndv":260,"upper":"3364343d4707ef48e23b1d42f409eaa4ad97cb2eb98e17e8b88edc11e727606a86e0b2","lower":"33316331cbecab43ac42c7853de7a11c3ebed7074f7fa058b20162e7c630786369c0ca","count":260,"preSum":11713},{"ndv":259,"upper":"343932492f4797a3b661d3f210632778c821220f3802c77ad1d6fd225b670c976587fa","lower":"3364353d5379d526809802b86f1bc1b6ec5a54f901e99494ae1e06ff3b5c876c8f8781","count":260,"preSum":11973},{"ndv":258,"upper":"35326352c0810ddaa0e5cfe83a04df6c3de4c0805d7e03586fe41db44384aa1618a526","lower":"3439344947c3edc2c7aae83d6f675c41d39fc8bf7baf4a5413b55930cd7588ed36a9e0","count":260,"preSum":12233},{"ndv":258,"upper":"3564365d6234a011399ee3c35eccd0c6bef45ca14ccebfc8e73534fa797cc3a446dbc9","lower":"35326452de3a91d8647b0fd798e9a18e06de295decef88243fd884ec03e80bebe3fba4","count":260,"preSum":12493},{"ndv":259,"upper":"363830680112150c342489c3e78eb0d86b253cc909d84948f5c9b674e09fd95d75f2ee","lower":"3564365d63d1016f730cf2e2b2209ef55dc95faee5c624947052247c9961b23ef33a27","count":260,"preSum":12753},{"ndv":260,"upper":"37336673f90e05e575ce688683cb9207772100061790f8a485e8121027c3841d1f546c","lower":"36383068036ba9bda06d5b3ea0f59e4ae15a4d9a420bf3293177a5f06dd35bb4dde60b","count":260,"preSum":13013},{"ndv":258,"upper":"3766657fe441549dc39590067220e2991bb314a4b959b1908333ed707ff25e971f809c","lower":"3734307401800946dee85c15400d757dfb8c1bfcb94609085a8a011492e42d04c25e4f","count":260,"preSum":13273},{"ndv":257,"upper":"3861338a335e68ff9eef823fe85eb4bc05314ccc85ef45da2236f8e76c43d1273e8445","lower":"3766657fe584fcc401b2809c47554e15107f9a8568b1df619808e4df23f860d8502bcf","count":260,"preSum":13533},{"ndv":259,"upper":"39356495dfd54819c543e99f6e1287e60561f77e7d9e5a1f3484d701b3ce9227edd4d7","lower":"3861338a3969ae5aff133beb3855d15c86f68dab9fff5ba947e46f9a3547c0f9d414fb","count":260,"preSum":13793},{"ndv":260,"upper":"613163a1c35703cdd11d6e60d2bcd8d6910d70c2082c7e63ae280f97bf58917ef718e2","lower":"39356595e131a744902e22899213d73af0c0212d34112d29414a47d34d8294db75c10c","count":260,"preSum":14053},{"ndv":260,"upper":"616336ac6df660206cf384b75641ff661035cfbc1f736793a552ed7f5f81d85e9e2832","lower":"613163a1c66d94c9a9e7949deb4cfbc4d1cfd32a68afef78a1c0109694fc3d753b4d87","count":260,"preSum":14313},{"ndv":256,"upper":"623763b7cacacfc4d951238fd7e2827f6c9e946707a0e31cd81ea9d07412a1b8382361","lower":"616337ac74d383b8d85ef44c9de64e4906509c31f08e2c72594734633ddb7b08dc7681","count":260,"preSum":14573},{"ndv":255,"upper":"633230c204ee9ea749ea80a9811579592ba56a628cf762802ad54379f1e231ad13078e","lower":"623764b7da748445671293daf137b9b5fde3f8d52b748db44288a2453dda3896e503f2","count":260,"preSum":14833},{"ndv":260,"upper":"636431cd1ae4f720bb9db50f63baba191e74de87851521b29ac9d1d1ab8803c9549114","lower":"633230c20fb8df06f56582e2a19d6586dca89d85b90eaa9d5e1fccc0bcdfc318450106","count":260,"preSum":15093},{"ndv":258,"upper":"643832d82fa76f0a1de5b53ecf009de2882e9ccdfad682c7ce1396157c1cdcd074d828","lower":"636431cd1d2a845740cef7c073ebf701984cc08b54cbeaf757ee39bf4a7c9a3c892d27","count":260,"preSum":15353},{"ndv":257,"upper":"653236e26f967d7a79e6312e5af0f27b9b29af5fed6e20fe25019b76a40c5d5adfaf78","lower":"643833d830743378ad0210324ba12191453e567168b8af366d37b5301427406a843cac","count":260,"preSum":15613},{"ndv":258,"upper":"656334ec4e32757f6cd1adf87fcce45ddcc7ef65a3344f2222035eaf068fe9bda7b5df","lower":"653238e284473a833a62330a488f4d815c33c46b1641bb02943daf06e7196ec4a24de8","count":260,"preSum":15873},{"ndv":259,"upper":"663664f6d652b1d84292368e1a90c66b2f2a84c81027c202cc19c03a095b76cb5d3828","lower":"656335ec539121fe5ae08ce1228beddc699b8fa7375b4cb5c323779d14e6af399a0e22","count":260,"preSum":16133},{"ndv":232,"upper":"测试","lower":"663664f6dd15314c9ea8dc204a724b042fa31e73d86c2a7d6aa79ed77a1416eb3db8d3","count":235,"preSum":16393}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[89,43,25,29,28,27,25,29,47,32,27,52,116,26],"valueArr":["","(021)6056 2952","022-58669903-680","027-87027020-627","028-88454296-610","029-33636453","0592-7276810","0757-81285355","13240073725","13611795239","15002119948","15220297985","15857945451","18681250538"],"type":"String","sampleRate":0.9618625319816094}',82778,0.02436278),('jala_wms_prod','shipment_header','shiptopostalcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','shiptostate',73,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":"上海市","lower":"","count":885,"preSum":0},{"ndv":4,"upper":"内蒙古自治区","lower":"上海省","count":1601,"preSum":885},{"ndv":1,"upper":"北京","lower":"北京","count":1984,"preSum":2486},{"ndv":1,"upper":"北京市","lower":"北京市","count":596,"preSum":4470},{"ndv":2,"upper":"吉林省","lower":"吉林","count":1353,"preSum":5066},{"ndv":2,"upper":"天津","lower":"四川","count":1139,"preSum":6419},{"ndv":3,"upper":"宁夏回族自治区","lower":"天津市","count":802,"preSum":7558},{"ndv":2,"upper":"山东","lower":"安徽","count":598,"preSum":8360},{"ndv":2,"upper":"山西省","lower":"山西","count":1826,"preSum":8958},{"ndv":1,"upper":"广东","lower":"广东","count":1295,"preSum":10784},{"ndv":2,"upper":"广西壮族自治区","lower":"广西","count":2531,"preSum":12079},{"ndv":2,"upper":"新疆维吾尔自治区","lower":"新疆","count":969,"preSum":14610},{"ndv":2,"upper":"江西","lower":"江苏","count":600,"preSum":15579},{"ndv":2,"upper":"河南","lower":"河北","count":733,"preSum":16179},{"ndv":3,"upper":"海南省","lower":"浙江","count":945,"preSum":16912},{"ndv":2,"upper":"湖南","lower":"湖北","count":536,"preSum":17857},{"ndv":2,"upper":"甘肃省","lower":"甘肃","count":1268,"preSum":18393},{"ndv":5,"upper":"贵州省","lower":"福建","count":2131,"preSum":19661},{"ndv":2,"upper":"辽宁省","lower":"辽宁","count":2538,"preSum":21792},{"ndv":1,"upper":"重庆","lower":"重庆","count":1196,"preSum":24330},{"ndv":1,"upper":"重庆市","lower":"重庆市","count":594,"preSum":25526},{"ndv":2,"upper":"陕西省","lower":"陕西","count":2507,"preSum":26120},{"ndv":4,"upper":"黑龙江省","lower":"青海","count":1756,"preSum":28627}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2440,2557,4519,4849,4723,12068,7324,2765,3455,5468,6880,4159,3523,3527],"valueArr":["上海","云南省","四川省","安徽省","山东省","广东省","江苏省","江西省","河北省","河南省","浙江省","湖北省","湖南省","福建省"],"type":"String","sampleRate":0.9618625319816094}',1361,0.02436278),('jala_wms_prod','shipment_header','shiptostatecode',32,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"11","lower":"","count":612,"preSum":0},{"ndv":1,"upper":"12","lower":"12","count":333,"preSum":612},{"ndv":1,"upper":"14","lower":"14","count":1613,"preSum":945},{"ndv":1,"upper":"15","lower":"15","count":1370,"preSum":2558},{"ndv":1,"upper":"21","lower":"21","count":2284,"preSum":3928},{"ndv":1,"upper":"22","lower":"22","count":1239,"preSum":6212},{"ndv":1,"upper":"23","lower":"23","count":1342,"preSum":7451},{"ndv":1,"upper":"31","lower":"31","count":859,"preSum":8793},{"ndv":1,"upper":"46","lower":"46","count":507,"preSum":9652},{"ndv":1,"upper":"50","lower":"50","count":574,"preSum":10159},{"ndv":1,"upper":"52","lower":"52","count":1664,"preSum":10733},{"ndv":2,"upper":"61","lower":"54","count":2391,"preSum":12397},{"ndv":1,"upper":"62","lower":"62","count":1143,"preSum":14788},{"ndv":2,"upper":"64","lower":"63","count":663,"preSum":15931},{"ndv":1,"upper":"65","lower":"65","count":828,"preSum":16594}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[3383,7149,6517,4722,3413,2720,4662,5258,3987,3461,10975,2299,4461,2526],"valueArr":["13","32","33","34","35","36","37","41","42","43","44","45","51","53"],"type":"String","sampleRate":0.9618625319816094}',17046,0.02436278),('jala_wms_prod','shipment_header','shiptotown',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[31],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99970,0.02436278),('jala_wms_prod','shipment_header','shiptotowncode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[82955],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',17046,0.02436278),('jala_wms_prod','shipment_header','shortaddress',62799,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":138,"upper":"(W86)024CQ-047","lower":"(01)591Z666-005同","count":146,"preSum":0},{"ndv":141,"upper":"010WE-ABJ-015","lower":"(W86)024CQ-072","count":146,"preSum":146},{"ndv":143,"upper":"020W-CM-505","lower":"010WE-ABJ-033","count":146,"preSum":292},{"ndv":141,"upper":"021WG-BDA-021","lower":"020W-CU-111B","count":146,"preSum":438},{"ndv":145,"upper":"022HH-M5-006","lower":"021WG-BHBL-703B","count":146,"preSum":584},{"ndv":142,"upper":"023W-Z023-000","lower":"022HK-011","count":146,"preSum":730},{"ndv":143,"upper":"028W-AD-301店","lower":"023W-Z031-014","count":146,"preSum":876},{"ndv":139,"upper":"028WA-NC-043","lower":"028W-AD-503","count":146,"preSum":1022},{"ndv":139,"upper":"052HA-009","lower":"028WA-NCA-021","count":147,"preSum":1168},{"ndv":36,"upper":"101B-","lower":"052KT-005","count":155,"preSum":1315},{"ndv":49,"upper":"161-","lower":"101B- 04-06 B01","count":174,"preSum":1470},{"ndv":33,"upper":"215-","lower":"161- 170 07","count":149,"preSum":1644},{"ndv":35,"upper":"245-","lower":"215- 131 614","count":165,"preSum":1793},{"ndv":37,"upper":"281-","lower":"245- 71 D78","count":180,"preSum":1958},{"ndv":79,"upper":"310U-003","lower":"281- A-38 081","count":146,"preSum":2138},{"ndv":123,"upper":"314DE-014同","lower":"310V-013","count":146,"preSum":2284},{"ndv":125,"upper":"320B-","lower":"314DE-018","count":150,"preSum":2430},{"ndv":67,"upper":"351QA-021","lower":"321-","count":146,"preSum":2580},{"ndv":78,"upper":"361- Y5 5555","lower":"351Z005-003","count":164,"preSum":2726},{"ndv":119,"upper":"372BM-201","lower":"361D-","count":146,"preSum":2890},{"ndv":111,"upper":"391AA-504","lower":"372CA-401","count":146,"preSum":3036},{"ndv":103,"upper":"410-","lower":"391AAL-000店","count":172,"preSum":3182},{"ndv":85,"upper":"425B-","lower":"410- C-S24 11 [R1]","count":146,"preSum":3354},{"ndv":94,"upper":"451-","lower":"427G-056","count":153,"preSum":3500},{"ndv":79,"upper":"461E-","lower":"451- 41-02 XA4 [A3]","count":147,"preSum":3653},{"ndv":96,"upper":"481-","lower":"461E- 65-13 R03","count":153,"preSum":3800},{"ndv":97,"upper":"513BM-D3-011","lower":"481- E02 800","count":146,"preSum":3953},{"ndv":130,"upper":"520-","lower":"513BM-D3-023同","count":149,"preSum":4099},{"ndv":108,"upper":"531TQ-048同","lower":"520- 01-25 018","count":146,"preSum":4248},{"ndv":132,"upper":"537-537Z043","lower":"531TQ-055","count":146,"preSum":4394},{"ndv":103,"upper":"551GD-B3-003同","lower":"537-537ZHC-009","count":146,"preSum":4540},{"ndv":132,"upper":"566H-008同","lower":"551HD-B14-016","count":146,"preSum":4686},{"ndv":105,"upper":"573N005-000","lower":"566ZHC-007","count":146,"preSum":4832},{"ndv":98,"upper":"576FE-002B同","lower":"573N020-000","count":146,"preSum":4978},{"ndv":112,"upper":"585-","lower":"576FJ-037同","count":161,"preSum":5124},{"ndv":84,"upper":"595AI-033同","lower":"585- 15-5 B00 [B05]","count":146,"preSum":5285},{"ndv":82,"upper":"601-","lower":"595AK-002A","count":173,"preSum":5431},{"ndv":25,"upper":"631-","lower":"601- 225 13 [A05]","count":153,"preSum":5604},{"ndv":89,"upper":"663AH-008同","lower":"631- D259 203","count":146,"preSum":5757},{"ndv":78,"upper":"700Y-","lower":"663AH-024","count":150,"preSum":5903},{"ndv":75,"upper":"713E-022","lower":"701-","count":146,"preSum":6053},{"ndv":142,"upper":"7311PL-039","lower":"713E-035","count":146,"preSum":6199},{"ndv":113,"upper":"741-","lower":"7311PM-061","count":147,"preSum":6345},{"ndv":137,"upper":"754DE-027","lower":"741- 03 D3","count":146,"preSum":6492},{"ndv":138,"upper":"755WE-KBA-TPL009C","lower":"754DH-001","count":146,"preSum":6638},{"ndv":142,"upper":"757WA-AS-006C","lower":"755WE-KBB-009B","count":146,"preSum":6784},{"ndv":124,"upper":"760- 01-37 15","lower":"757WA-AU-016B","count":146,"preSum":6930},{"ndv":144,"upper":"769WB-QN-010","lower":"760- 01-42 72","count":146,"preSum":7076},{"ndv":135,"upper":"769WM-SF-073B","lower":"769WB-QS-006B","count":146,"preSum":7222},{"ndv":142,"upper":"775D054-007","lower":"769ZPWB-VM-M7-MK016C","count":146,"preSum":7368},{"ndv":92,"upper":"792VA-AF-028","lower":"775DC-015","count":146,"preSum":7514},{"ndv":95,"upper":"802-","lower":"792VA-C-028","count":164,"preSum":7660},{"ndv":80,"upper":"818AB-032","lower":"802- E14 27V","count":146,"preSum":7824},{"ndv":86,"upper":"831V-061","lower":"818AD-032","count":146,"preSum":7970},{"ndv":55,"upper":"851-","lower":"831ZPVA","count":171,"preSum":8116},{"ndv":105,"upper":"871AS-008同","lower":"851- A2 022","count":146,"preSum":8287},{"ndv":127,"upper":"891","lower":"871AT-034","count":146,"preSum":8433},{"ndv":67,"upper":"902-","lower":"891- 03-02 32","count":152,"preSum":8579},{"ndv":100,"upper":"932EB-000","lower":"902AB-027","count":146,"preSum":8731},{"ndv":85,"upper":"954AE-003","lower":"932K-012","count":146,"preSum":8877},{"ndv":89,"upper":"B38-J-021LM-013","lower":"954JT-AL-AL016","count":146,"preSum":9023},{"ndv":138,"upper":"XY6-519BL-082","lower":"B40-G-021K-209","count":146,"preSum":9169},{"ndv":15,"upper":"ZW8-519L-063同","lower":"XY6-519BL-085","count":15,"preSum":9315}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[88033,94,145,64,80,78,61,93,57,73,60,54,78,57],"valueArr":["","110-","121-","130-","145-","235-","300-","361- Y5 555","430-","501-","590-","700-","805-","891-"],"type":"String","sampleRate":0.9618625319816094}',1644,0.02436278),('jala_wms_prod','shipment_header','shortaddresscode',162328,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":302,"upper":"(TA)024TA-012","lower":"(01)591Z666-005同","count":318,"preSum":0},{"ndv":277,"upper":"010WB-BAK-007","lower":"(TB)024TB-022同","count":318,"preSum":318},{"ndv":300,"upper":"020RD-NC-068A","lower":"010WB-BAK-028","count":318,"preSum":636},{"ndv":293,"upper":"021WF-Z496-016B","lower":"020RD-NC-NGAL000","count":318,"preSum":954},{"ndv":308,"upper":"022BTA-011","lower":"021WG-580ZHK-001","count":318,"preSum":1272},{"ndv":301,"upper":"023W-023","lower":"022CA-009","count":320,"preSum":1590},{"ndv":309,"upper":"025WD-TZ-051","lower":"023W-BE-002同","count":318,"preSum":1910},{"ndv":284,"upper":"028W-BAC-409","lower":"025WD-UD","count":318,"preSum":2228},{"ndv":301,"upper":"028WA-D104-002","lower":"028W-BAF-012","count":318,"preSum":2546},{"ndv":290,"upper":"029WE-DAA-067","lower":"028WA-D124-000","count":318,"preSum":2864},{"ndv":245,"upper":"101A-","lower":"029WE-DB-082","count":344,"preSum":3182},{"ndv":21,"upper":"221-","lower":"101B-","count":323,"preSum":3526},{"ndv":20,"upper":"310-","lower":"230-","count":332,"preSum":3849},{"ndv":297,"upper":"312Z044-000","lower":"310A-","count":318,"preSum":4181},{"ndv":307,"upper":"319VA-EC-017","lower":"312Z045-000","count":318,"preSum":4499},{"ndv":214,"upper":"352DLD013-000","lower":"319VA-G-007同","count":319,"preSum":4817},{"ndv":262,"upper":"370D009-000","lower":"352DLD017-000","count":318,"preSum":5136},{"ndv":282,"upper":"372DLD035-000","lower":"370D011-001B","count":318,"preSum":5454},{"ndv":285,"upper":"377FN-017同","lower":"372DLD036-000D","count":318,"preSum":5772},{"ndv":262,"upper":"394AF-203同","lower":"377FN-019同","count":318,"preSum":6090},{"ndv":228,"upper":"411BBL-002","lower":"394AH-101同","count":318,"preSum":6408},{"ndv":251,"upper":"431EQ-048","lower":"411BC-036","count":318,"preSum":6726},{"ndv":256,"upper":"451LU-015店","lower":"431ES-009","count":318,"preSum":7044},{"ndv":213,"upper":"471CN-A3-017","lower":"451Q-002","count":318,"preSum":7362},{"ndv":251,"upper":"510E-B10-045","lower":"471CV-052","count":318,"preSum":7680},{"ndv":278,"upper":"513UD-H6-302同","lower":"510EB-C06-024同","count":318,"preSum":7998},{"ndv":298,"upper":"517B-004同","lower":"513V-G10-151同","count":318,"preSum":8316},{"ndv":279,"upper":"527DLD008-000","lower":"517B-036","count":318,"preSum":8634},{"ndv":271,"upper":"532W-HI-015","lower":"527DLD015-000","count":318,"preSum":8952},{"ndv":307,"upper":"537-537LC-024","lower":"532W-HL-006","count":318,"preSum":9270},{"ndv":258,"upper":"551BA-B1-024同","lower":"537-537LD-021","count":318,"preSum":9588},{"ndv":297,"upper":"553KF-005同","lower":"551BD-B12-102","count":318,"preSum":9906},{"ndv":286,"upper":"564VA-B-004同","lower":"553MA-007同","count":318,"preSum":10224},{"ndv":251,"upper":"571WB-LK-047","lower":"564VA-B-010同","count":318,"preSum":10542},{"ndv":289,"upper":"574W-LAB-015","lower":"571WB-MP-018","count":318,"preSum":10860},{"ndv":261,"upper":"576SD-012","lower":"574W-LB-A22-108","count":318,"preSum":11178},{"ndv":296,"upper":"579WA-SD-B36-011","lower":"576SD-013","count":318,"preSum":11496},{"ndv":211,"upper":"595HC-004A","lower":"579WA-SD-B36-014","count":318,"preSum":11814},{"ndv":167,"upper":"631-","lower":"595HD-001B","count":338,"preSum":12132},{"ndv":252,"upper":"668B-006A","lower":"631W-AD-005","count":318,"preSum":12470},{"ndv":167,"upper":"711G-011","lower":"668B-009B","count":318,"preSum":12788},{"ndv":289,"upper":"717BF-023","lower":"711G-022","count":318,"preSum":13106},{"ndv":292,"upper":"7311DA-086","lower":"717D-024","count":318,"preSum":13424},{"ndv":299,"upper":"736AH-047","lower":"7311DA-088","count":318,"preSum":13742},{"ndv":266,"upper":"750AB-016A","lower":"736AH-055","count":318,"preSum":14060},{"ndv":290,"upper":"755W-HA-BGL001B","lower":"750AD-006A","count":318,"preSum":14378},{"ndv":294,"upper":"755WM-F009-000","lower":"755W-HB-029","count":318,"preSum":14696},{"ndv":297,"upper":"759VA-AF-008","lower":"755WM-FC-005B","count":318,"preSum":15014},{"ndv":275,"upper":"769WB-QB-003C同","lower":"759VA-AJ-013","count":318,"preSum":15332},{"ndv":290,"upper":"771CS-043同","lower":"769WB-QB-005B","count":318,"preSum":15650},{"ndv":303,"upper":"779AD-026","lower":"771CS-062同","count":318,"preSum":15968},{"ndv":238,"upper":"794A-045","lower":"779AE-001","count":318,"preSum":16286},{"ndv":261,"upper":"802-","lower":"794AC-006","count":344,"preSum":16604},{"ndv":221,"upper":"825B-009","lower":"805A-","count":318,"preSum":16948},{"ndv":222,"upper":"835-","lower":"825B-107","count":320,"preSum":17266},{"ndv":213,"upper":"855","lower":"835D-015","count":318,"preSum":17586},{"ndv":255,"upper":"871KB-015","lower":"855A-004","count":318,"preSum":17904},{"ndv":295,"upper":"891ZPVA-011","lower":"871KF-033","count":318,"preSum":18222},{"ndv":221,"upper":"912MA-001","lower":"892-","count":318,"preSum":18540},{"ndv":257,"upper":"932DLD029-000","lower":"912MA-007同","count":318,"preSum":18858},{"ndv":249,"upper":"954AC-026","lower":"932DLD032-000","count":318,"preSum":19176},{"ndv":252,"upper":"997","lower":"954ADL-004同","count":320,"preSum":19494},{"ndv":303,"upper":"WG-VL-021Z427-018","lower":"997AB-008A","count":318,"preSum":19814},{"ndv":153,"upper":"ZW8-519L-063同","lower":"WG-VL-021Z455-040","count":159,"preSum":20132}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[94,145,64,80,78,61,57,73,60,53,54,78,57],"valueArr":["110-","121-","130-","145-","235-","300-","430-","501-","590-","600-","700-","805-","891-"],"type":"String","sampleRate":0.9618625319816094}',78756,0.02436278),('jala_wms_prod','shipment_header','shortalloc',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','shortpacking',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','shortpick',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','signvalue',103408,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":600,"upper":"502112103:1|502589202:2|502764100:1","lower":"","count":1186,"preSum":0},{"ndv":415,"upper":"502112204:1|502484903:2|502487704:1|502645000:1|502975522:1","lower":"502112103:1|502589202:2|502764100:1|6165296:1","count":1190,"preSum":1186},{"ndv":302,"upper":"502191320:1|502191340:1|502191390:1|502503901:3|502513906:4","lower":"502112204:1|502484903:2|502487704:1|502645000:1|502975524:1","count":1180,"preSum":2376},{"ndv":480,"upper":"502191513:2","lower":"502191320:1|502191340:1|502699002:4","count":1362,"preSum":3556},{"ndv":212,"upper":"502191602:1","lower":"502191513:2|502191530:1|502684503:1","count":1222,"preSum":4918},{"ndv":256,"upper":"502191612:1","lower":"502191602:1|502191612:1","count":1320,"preSum":6140},{"ndv":259,"upper":"502200305:1|502200404:1|502201703:1|502201910:1|502477901:2|502536603:1|502562203:1|502640804:1|502699200:3|502976673:2|50298546","lower":"502191612:1|502200305:1|502201701:1|502202401:1|502588501:1|502640802:2|502642510:2|6165273:1","count":1200,"preSum":7460},{"ndv":385,"upper":"502200305:1|502201910:1|502583416:1|502640802:1|502642509:3|502681400:1","lower":"502200305:1|502200404:1|502201703:1|502201910:1|502477901:2|502536603:1|502562203:1|502640804:1|502699201:3|502976673:2|50298546","count":1180,"preSum":8660},{"ndv":331,"upper":"502200306:1|502200408:1|502201703:1|502201910:1|502477902:2|502493702:1|502589104:1|502589403:2|502640805:2|502642510:2|50284550","lower":"502200305:1|502201910:1|502583416:1|502640805:1|502642510:3","count":1190,"preSum":9840},{"ndv":19,"upper":"502200306:1|502200408:1|502201703:1|502201910:1|502536603:1|502562203:1|502640806:2|502668704:1|502699002:1|502845500:1|50297667","lower":"502200306:1|502200408:1|502201703:1|502201910:1|502477902:2|502493702:1|502640805:2|502642510:2|502699002:7|502845500:1|50297667","count":1279,"preSum":11030},{"ndv":413,"upper":"502200306:1|502201910:1|502642510:2|502845500:1","lower":"502200306:1|502200408:1|502201703:1|502201910:1|502536603:1|502640805:3|502668704:1|502699002:1|502845500:1|502976673:3|6165273:","count":1183,"preSum":12309},{"ndv":526,"upper":"502200408:1|502640805:1|502699102:1","lower":"502200306:1|502201910:1|502642510:2|502845500:1|6164964:1","count":1237,"preSum":13492},{"ndv":280,"upper":"502201906:1|502588103:1|502750104:5","lower":"502200408:1|502640805:1|502699102:1|502700002:2","count":1184,"preSum":14729},{"ndv":192,"upper":"502202405:1|502477902:1","lower":"502201906:1|502588103:1|502750104:5|502754400:1|502765800:1|502775500:2|502775700:2","count":1421,"preSum":15913},{"ndv":332,"upper":"502220203:1|502220401:1|502220501:1|502220602:1|502477901:1|502487704:1|502699002:1|502764100:1","lower":"502202405:1|502477902:1|502481603:1|502754400:2","count":1181,"preSum":17334},{"ndv":312,"upper":"502220402:1","lower":"502220203:1|502220401:1|502220501:1|502220602:1|502477901:1|502487704:2|502699002:1","count":1235,"preSum":18515},{"ndv":319,"upper":"502240403:1|502240503:1|502643500:4|6163780:1","lower":"502220402:1|502220501:1","count":1180,"preSum":19750},{"ndv":742,"upper":"502250801:1|502977111:1","lower":"502240403:1|502240503:1|502643501:1|502750900:1|502751000:4|502835600:2","count":1184,"preSum":20930},{"ndv":308,"upper":"502476708:4","lower":"502250801:1|502985192:1","count":1337,"preSum":22114},{"ndv":228,"upper":"502481803:1|502624601:1","lower":"502476708:4|502484903:2|502487704:1|502511201:1|502645000:1|502975522:1","count":1196,"preSum":23451},{"ndv":289,"upper":"502511201:1|502764100:1","lower":"502481803:1|502624601:1|502671602:1|502671702:1|502699402:2","count":1223,"preSum":24647},{"ndv":446,"upper":"502520703:1|502977111:1","lower":"502511201:1|502764100:1|502767800:1|502835600:1","count":1183,"preSum":25870},{"ndv":235,"upper":"502523708:1|502540302:1","lower":"502520703:2|502588502:2","count":1322,"preSum":27053},{"ndv":183,"upper":"502523908:1","lower":"502523708:1|502540302:1|502542201:2|502597300:1|502624601:2|502740801:1|502757900:2|502787600:4","count":1341,"preSum":28375},{"ndv":281,"upper":"502536603:1|502692501:1|502699201:7|502715101:1|502754601:1|502754801:1|6165273:1","lower":"502523908:1|502524002:1","count":1270,"preSum":29716},{"ndv":69,"upper":"502536901:1|502699102:2","lower":"502536603:1|502692501:1|502699201:7|502715101:1|502754601:1|502754801:1|6165273:2","count":1207,"preSum":30986},{"ndv":290,"upper":"502543602:1|502672802:1","lower":"502536901:1|502699102:2|502700002:1","count":1198,"preSum":32193},{"ndv":401,"upper":"502575902:1|502576003:1|502576102:1|502580502:5|502658601:4","lower":"502543602:1|502672802:1|502764000:1","count":1181,"preSum":33391},{"ndv":229,"upper":"502582805:1|502582904:2|502611102:1","lower":"502575902:1|502576003:1|502576102:1|502580502:7|502658601:1","count":1180,"preSum":34572},{"ndv":199,"upper":"502582805:5|6165113:1|6165115:1","lower":"502582805:1|502582904:2|502755500:3","count":1230,"preSum":35752},{"ndv":310,"upper":"502586202:1","lower":"502582805:5|6165114:1","count":1180,"preSum":36982},{"ndv":72,"upper":"502588103:2","lower":"502586202:1|502586303:1|502645000:2|502760900:1","count":1189,"preSum":38162},{"ndv":378,"upper":"502597300:1|502750104:1|502787600:4","lower":"502588103:2|502588300:2|502588400:2","count":1180,"preSum":39351},{"ndv":24,"upper":"502597300:1|502787600:5","lower":"502597300:1|502750104:1|502787600:5","count":1184,"preSum":40531},{"ndv":292,"upper":"502622207:1|502642604:4|502750100:2","lower":"502597300:1|502787600:5|502985463:1","count":1228,"preSum":41715},{"ndv":169,"upper":"502642604:1|502731301:1|502791100:2|502904900:1","lower":"502622207:1|502642604:4|502750100:2|502750104:1","count":1180,"preSum":42943},{"ndv":129,"upper":"502651401:1|502699002:3|6165469:1","lower":"502642604:1|502750104:1","count":1180,"preSum":44123},{"ndv":142,"upper":"502668704:1|502668804:1|502668904:1|502669004:2|502697804:1","lower":"502651401:1|502699200:1|502764100:1","count":1230,"preSum":45303},{"ndv":146,"upper":"502668704:1|502699102:3","lower":"502668704:1|502668804:1|502668904:1|502669004:2|502697804:1|502699002:6|502699402:6","count":1479,"preSum":46533},{"ndv":190,"upper":"502668704:4|502668804:2|502669004:2|502699200:2","lower":"502668704:1|502699102:3|502725500:1","count":1272,"preSum":48012},{"ndv":65,"upper":"502668704:6|502699002:6","lower":"502668704:4|502668804:2|502669004:2|502699200:2|6165273:1","count":1181,"preSum":49284},{"ndv":198,"upper":"502671602:1|502671702:1|502672104:1|502672304:1|502692900:1|502699002:2|502754501:1|502754701:1|502754901:1","lower":"502668704:6|502699200:2","count":1180,"preSum":50465},{"ndv":134,"upper":"502672104:1|502672400:1|502692900:1","lower":"502671602:1|502671702:1|502684503:5|502699002:2|502725500:1|502754501:1|502754701:1|502754901:1","count":1181,"preSum":51645},{"ndv":154,"upper":"502684505:5|502725500:1","lower":"502672104:1|502672400:1|502754000:1","count":1628,"preSum":52826},{"ndv":122,"upper":"502693700:1|502731300:1","lower":"502684505:5|502725500:1|502729900:1|502788100:1","count":1300,"preSum":54454},{"ndv":58,"upper":"502693900:1|502694000:1|502762700:1|6165195:1","lower":"502693700:1|502731300:1|502755900:1","count":1423,"preSum":55754},{"ndv":39,"upper":"502693900:2|502755900:1|502762700:1|6165082:1|6165195:1","lower":"502693900:1|502694000:1|502762700:1|6165296:1","count":1352,"preSum":57177},{"ndv":68,"upper":"502694100:2|502755900:1|502762701:1|6165195:1","lower":"502693900:2|502755900:1|502762700:1|6165195:1","count":1181,"preSum":58529},{"ndv":277,"upper":"502703500:1","lower":"502694200:1","count":1194,"preSum":59710},{"ndv":122,"upper":"502724700:1","lower":"502703501:1","count":1256,"preSum":60904},{"ndv":9,"upper":"502725500:1","lower":"502724700:1|502725500:1","count":1291,"preSum":62160},{"ndv":241,"upper":"502736100:2","lower":"502725500:1|502732000:1|502736100:2|502776700:2","count":1188,"preSum":63451},{"ndv":87,"upper":"502750104:3","lower":"502736100:2|502750104:2|502755900:2","count":1384,"preSum":64639},{"ndv":96,"upper":"502755500:2|502976583:1","lower":"502750104:3|502754400:6|6165091:1","count":1215,"preSum":66023},{"ndv":93,"upper":"502775500:2|502775700:2|502775800:1","lower":"502755500:2|6164659:1","count":1202,"preSum":67238},{"ndv":64,"upper":"502791100:2","lower":"502775500:2|502775700:2|502775800:1|502787600:2","count":1365,"preSum":68440},{"ndv":42,"upper":"502985463:1","lower":"502791100:20|6165091:2|6165275:2","count":1243,"preSum":69805},{"ndv":502,"upper":"512000300:2|512007100:6|512015800:6|6165349:1","lower":"502985463:2","count":1181,"preSum":71048},{"ndv":322,"upper":"512004300:1","lower":"512000300:3|512001202:25","count":1187,"preSum":72229},{"ndv":98,"upper":"6165097:1","lower":"512004300:16|512006900:4|512020100:1|6165349:1","count":1207,"preSum":73416},{"ndv":393,"upper":"自然堂雪肌美白保湿洁面霜120g:336","lower":"6165115:1","count":890,"preSum":74623}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[886,931,959,1085,728,908,888,931,1110,2396,4027,865,3920,1280],"valueArr":["502220203:1","502476708:10","502523708:1|502740801:2","502536603:1|502692900:1|502715300:1|502755100:2|502755300:2|502755400:2","502536603:1|502692900:1|502715300:1|502755101:2|502755301:2|502755401:2","502582805:2","502582805:6","502586901:1|502588103:1|502622207:1|502642604:6","502668704:4|502668804:2|502669004:2|502699402:2","502668704:4|502668804:4|502668904:4|502669004:4|502697804:4","502700002:1","502700002:2","502725500:2","502791100:6"],"type":"String","sampleRate":0.9618625319816094}',3574,0.02436278),('jala_wms_prod','shipment_header','sourceerp',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[98415,1469],"valueArr":["QIMEN","SAP"],"type":"String","sampleRate":0.9618625319816094}',117,0.02436278),('jala_wms_prod','shipment_header','sourceerpcode',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[95364,3051],"valueArr":["JALA-ECS","JALA-YPH"],"type":"String","sampleRate":0.9618625319816094}',1586,0.02436278),('jala_wms_prod','shipment_header','sourceordercode',2299540,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1484,"upper":"1832796696057094168","lower":"100441022058559!FP099111129996578","count":1488,"preSum":0},{"ndv":1488,"upper":"1870914072078718963","lower":"1832801844266336280","count":1488,"preSum":1488},{"ndv":1487,"upper":"1878563534491514493","lower":"1870915838900151970","count":1488,"preSum":2976},{"ndv":1488,"upper":"1880530357673255970","lower":"1878565514951295680","count":1488,"preSum":4464},{"ndv":1487,"upper":"1886573463828438884","lower":"1880537955827870398","count":1488,"preSum":5952},{"ndv":1487,"upper":"1891617386250503291","lower":"1886573642968694487","count":1488,"preSum":7440},{"ndv":1487,"upper":"1896297672938324060","lower":"1891617421264297999","count":1488,"preSum":8928},{"ndv":1487,"upper":"1896932895443324474","lower":"1896297744703205393","count":1488,"preSum":10416},{"ndv":1485,"upper":"1897159911391977078","lower":"1896933075205745186","count":1488,"preSum":11904},{"ndv":1486,"upper":"1899880248729178380","lower":"1897159911558262388","count":1488,"preSum":13392},{"ndv":1487,"upper":"1903179900573515760","lower":"1899881113496508775","count":1488,"preSum":14880},{"ndv":1488,"upper":"1906452120502540768","lower":"1903182026331931066","count":1488,"preSum":16368},{"ndv":1487,"upper":"1911852949699587799","lower":"1906452228701774495","count":1488,"preSum":17856},{"ndv":1487,"upper":"1915038300444831789","lower":"1911858169226630586","count":1488,"preSum":19344},{"ndv":1488,"upper":"1917194269746866291","lower":"1915040388757471789","count":1488,"preSum":20832},{"ndv":1488,"upper":"1920912277996478287","lower":"1917195636641733393","count":1488,"preSum":22320},{"ndv":1487,"upper":"23042577504774","lower":"1920915192436995579","count":1488,"preSum":23808},{"ndv":1488,"upper":"23050999937184","lower":"23042578879844","count":1488,"preSum":25296},{"ndv":1488,"upper":"23052207024716","lower":"230510-020599315363899","count":1488,"preSum":26784},{"ndv":1488,"upper":"23060345827289","lower":"23052214902216","count":1488,"preSum":28272},{"ndv":1488,"upper":"23061661983868","lower":"23060345941735","count":1488,"preSum":29760},{"ndv":1488,"upper":"2311400211532013","lower":"23061662381768","count":1488,"preSum":31248},{"ndv":1487,"upper":"265109333115","lower":"2311400220662942","count":1488,"preSum":32736},{"ndv":1488,"upper":"271354654999","lower":"265121474335","count":1488,"preSum":34224},{"ndv":1487,"upper":"273652656707","lower":"271357049749","count":1488,"preSum":35712},{"ndv":1487,"upper":"275952971620","lower":"273652670410","count":1488,"preSum":37200},{"ndv":1488,"upper":"3216250756380122640","lower":"275954711457","count":1488,"preSum":38688},{"ndv":1488,"upper":"3253389915328772966","lower":"3216280708884438531","count":1488,"preSum":40176},{"ndv":1488,"upper":"3303233535067337330","lower":"3253394379555697754","count":1488,"preSum":41664},{"ndv":1486,"upper":"3316790414389889312","lower":"3303234219367598236","count":1488,"preSum":43152},{"ndv":1487,"upper":"3324843001075210158","lower":"3316791099092567425","count":1488,"preSum":44640},{"ndv":1485,"upper":"3329766468219849727","lower":"3324846206548751613","count":1488,"preSum":46128},{"ndv":1486,"upper":"3330725331991742448","lower":"3329766468232630755","count":1488,"preSum":47616},{"ndv":1487,"upper":"3335242791101210534","lower":"3330725617326611401","count":1488,"preSum":49104},{"ndv":1487,"upper":"3342451248808912215","lower":"3335244015638576434","count":1488,"preSum":50592},{"ndv":1488,"upper":"3348816265556925210","lower":"3342451287310895604","count":1488,"preSum":52080},{"ndv":1487,"upper":"3353116359969470244","lower":"3348822459373553628","count":1488,"preSum":53568},{"ndv":1487,"upper":"3360427886170082604","lower":"3353118591755637038","count":1488,"preSum":55056},{"ndv":1487,"upper":"3364122168698182337","lower":"3360431163950684002","count":1488,"preSum":56544},{"ndv":1484,"upper":"3364668794474229004","lower":"3364122169573681207","count":1488,"preSum":58032},{"ndv":1484,"upper":"3365067567026386163","lower":"3364668859558505045","count":1488,"preSum":59520},{"ndv":1486,"upper":"3367758457938200922","lower":"3365068215676692337","count":1488,"preSum":61008},{"ndv":1487,"upper":"3371323467724740322","lower":"3367766593621231455","count":1488,"preSum":62496},{"ndv":1486,"upper":"3374711209087921150","lower":"3371325159468704049","count":1488,"preSum":63984},{"ndv":1486,"upper":"3378245655807206345","lower":"3374713873685823049","count":1488,"preSum":65472},{"ndv":1487,"upper":"3382461252151375702","lower":"3378246517737930306","count":1488,"preSum":66960},{"ndv":1487,"upper":"3389513149652996348","lower":"3382465464002934131","count":1488,"preSum":68448},{"ndv":1488,"upper":"3395248130692842601","lower":"3389515921178741823","count":1488,"preSum":69936},{"ndv":1487,"upper":"3398021103902802007","lower":"3395251766420358615","count":1488,"preSum":71424},{"ndv":1487,"upper":"3400202739026952945","lower":"3398021388956795402","count":1488,"preSum":72912},{"ndv":1488,"upper":"3402294913041316618","lower":"3400203565788352452","count":1488,"preSum":74400},{"ndv":1487,"upper":"3408325382768461156","lower":"3402296282880252556","count":1488,"preSum":75888},{"ndv":1488,"upper":"6917841557550602009","lower":"3408327792453859017","count":1488,"preSum":77376},{"ndv":1485,"upper":"6918025457652995233","lower":"6917842073163536334","count":1488,"preSum":78864},{"ndv":1486,"upper":"6918177551963854376","lower":"6918025705434649833","count":1488,"preSum":80352},{"ndv":1488,"upper":"6918330850433766892","lower":"6918177745710224832","count":1488,"preSum":81840},{"ndv":1487,"upper":"6918511796987237907","lower":"6918331157666928560","count":1488,"preSum":83328},{"ndv":1484,"upper":"6918702940928153306","lower":"6918511842102482787","count":1488,"preSum":84816},{"ndv":1487,"upper":"6918920943156270532","lower":"6918702983504795070","count":1488,"preSum":86304},{"ndv":1488,"upper":"6919067064000452504","lower":"6918920968230868445","count":1488,"preSum":87792},{"ndv":1488,"upper":"6919248606522709645","lower":"6919067420611384915","count":1488,"preSum":89280},{"ndv":1488,"upper":"6919410566841701488","lower":"6919248639676912891","count":1488,"preSum":90768},{"ndv":1488,"upper":"6919562240896472971","lower":"6919410614726629151","count":1488,"preSum":92256},{"ndv":1450,"upper":"XXY2023052337","lower":"6919562578720004018","count":1451,"preSum":93744}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[177],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',4629,0.02436278),('jala_wms_prod','shipment_header','sourceplatform',9,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[11,5614,15670,6295,1197,6918,879,61751,92],"valueArr":["","*","DOUYIN","JD","KUAISHOU","MP","PDD","TB","VIP"],"type":"String","sampleRate":0.9618625319816094}',1574,0.02436278),('jala_wms_prod','shipment_header','splitorderidentification',1016,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"2585938","lower":"2459261","count":2,"preSum":0},{"ndv":2,"upper":"2602225","lower":"2586005","count":2,"preSum":2},{"ndv":2,"upper":"2602228","lower":"2602227","count":2,"preSum":4},{"ndv":2,"upper":"2602369","lower":"2602236","count":2,"preSum":6},{"ndv":1,"upper":"2604100","lower":"2604100","count":2,"preSum":8},{"ndv":2,"upper":"2605022","lower":"2605021","count":2,"preSum":10},{"ndv":2,"upper":"2605025","lower":"2605023","count":2,"preSum":12},{"ndv":1,"upper":"2605099","lower":"2605099","count":2,"preSum":14},{"ndv":2,"upper":"2605666","lower":"2605665","count":2,"preSum":16},{"ndv":2,"upper":"2645301","lower":"2605677","count":2,"preSum":18},{"ndv":1,"upper":"2646282","lower":"2646282","count":2,"preSum":20},{"ndv":2,"upper":"2700631","lower":"2683155","count":2,"preSum":22},{"ndv":2,"upper":"2776471","lower":"2722610","count":2,"preSum":24},{"ndv":2,"upper":"2828385","lower":"2781296","count":2,"preSum":26},{"ndv":2,"upper":"2943564","lower":"2942732","count":2,"preSum":28},{"ndv":2,"upper":"3038058","lower":"3038057","count":3,"preSum":30},{"ndv":2,"upper":"3233189","lower":"3121239","count":2,"preSum":33},{"ndv":2,"upper":"3302917","lower":"3302048","count":2,"preSum":35},{"ndv":2,"upper":"3412927","lower":"3395747","count":2,"preSum":37},{"ndv":2,"upper":"3412948","lower":"3412936","count":2,"preSum":39},{"ndv":2,"upper":"3412971","lower":"3412959","count":2,"preSum":41},{"ndv":2,"upper":"3413051","lower":"3412993","count":2,"preSum":43},{"ndv":2,"upper":"3413116","lower":"3413055","count":2,"preSum":45},{"ndv":2,"upper":"3531920","lower":"3421876","count":2,"preSum":47},{"ndv":2,"upper":"3531985","lower":"3531981","count":2,"preSum":49},{"ndv":2,"upper":"3970683","lower":"3532154","count":2,"preSum":51},{"ndv":2,"upper":"3971926","lower":"3971925","count":2,"preSum":53},{"ndv":2,"upper":"3973028","lower":"3973025","count":2,"preSum":55},{"ndv":1,"upper":"3973072","lower":"3973072","count":2,"preSum":57},{"ndv":2,"upper":"4176632","lower":"4152939","count":2,"preSum":59},{"ndv":2,"upper":"4218528","lower":"4218526","count":2,"preSum":61},{"ndv":2,"upper":"4227811","lower":"4225496","count":2,"preSum":63},{"ndv":2,"upper":"4229420","lower":"4229092","count":2,"preSum":65},{"ndv":2,"upper":"4422425","lower":"4229940","count":2,"preSum":67},{"ndv":2,"upper":"4960907","lower":"4438806","count":3,"preSum":69},{"ndv":2,"upper":"4992776","lower":"4971652","count":2,"preSum":72},{"ndv":2,"upper":"4997567","lower":"4992777","count":2,"preSum":74},{"ndv":1,"upper":"5175078","lower":"5175078","count":2,"preSum":76},{"ndv":2,"upper":"5488127","lower":"5473702","count":2,"preSum":78},{"ndv":2,"upper":"5531409","lower":"5531397","count":2,"preSum":80},{"ndv":2,"upper":"5533274","lower":"5531507","count":2,"preSum":82},{"ndv":2,"upper":"5533284","lower":"5533279","count":2,"preSum":84},{"ndv":2,"upper":"5535303","lower":"5533285","count":2,"preSum":86},{"ndv":2,"upper":"5592320","lower":"5590095","count":2,"preSum":88},{"ndv":2,"upper":"5599061","lower":"5599059","count":2,"preSum":90},{"ndv":2,"upper":"5599071","lower":"5599069","count":3,"preSum":92},{"ndv":2,"upper":"5798389","lower":"5737664","count":2,"preSum":95},{"ndv":2,"upper":"5837619","lower":"5831069","count":2,"preSum":97},{"ndv":2,"upper":"5839168","lower":"5839166","count":2,"preSum":99},{"ndv":2,"upper":"5839201","lower":"5839192","count":2,"preSum":101},{"ndv":2,"upper":"5839204","lower":"5839203","count":2,"preSum":103},{"ndv":2,"upper":"5843201","lower":"5839205","count":2,"preSum":105},{"ndv":2,"upper":"7502017","lower":"5843777","count":2,"preSum":107},{"ndv":2,"upper":"7773520","lower":"7773519","count":2,"preSum":109},{"ndv":2,"upper":"8343228","lower":"8223662","count":2,"preSum":111}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,99888,0.02436278),('jala_wms_prod','shipment_header','stageloc',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','stamp',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','stampindex',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','statusflow',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":["default"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','stopseq',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','storecode',183,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"75201","lower":"","count":308,"preSum":0},{"ndv":5,"upper":"75304","lower":"75201-1","count":208,"preSum":308},{"ndv":1,"upper":"75420","lower":"75420","count":494,"preSum":516},{"ndv":1,"upper":"75424","lower":"75424","count":344,"preSum":1010},{"ndv":3,"upper":"75429","lower":"75424-1","count":260,"preSum":1354},{"ndv":5,"upper":"75450","lower":"75435","count":343,"preSum":1614},{"ndv":2,"upper":"75452","lower":"75451","count":539,"preSum":1957},{"ndv":8,"upper":"75474","lower":"75453","count":358,"preSum":2496},{"ndv":6,"upper":"75480","lower":"75474-1","count":265,"preSum":2854},{"ndv":2,"upper":"75485-1","lower":"75481","count":586,"preSum":3119},{"ndv":3,"upper":"75495","lower":"75492-1","count":458,"preSum":3705},{"ndv":1,"upper":"75496","lower":"75496","count":285,"preSum":4163},{"ndv":3,"upper":"75501","lower":"75499","count":491,"preSum":4448},{"ndv":1,"upper":"75502","lower":"75502","count":436,"preSum":4939},{"ndv":1,"upper":"75506","lower":"75506","count":316,"preSum":5375},{"ndv":1,"upper":"75507","lower":"75507","count":275,"preSum":5691},{"ndv":1,"upper":"75508","lower":"75508","count":204,"preSum":5966},{"ndv":1,"upper":"75511","lower":"75511","count":653,"preSum":6170},{"ndv":2,"upper":"75514","lower":"75513","count":694,"preSum":6823},{"ndv":1,"upper":"75515","lower":"75515","count":323,"preSum":7517},{"ndv":2,"upper":"75517","lower":"75516","count":592,"preSum":7840},{"ndv":2,"upper":"75519","lower":"75518","count":549,"preSum":8432},{"ndv":1,"upper":"75520","lower":"75520","count":213,"preSum":8981},{"ndv":2,"upper":"75522","lower":"75521","count":363,"preSum":9194},{"ndv":4,"upper":"75530","lower":"75523","count":207,"preSum":9557},{"ndv":2,"upper":"75539","lower":"75536","count":244,"preSum":9764},{"ndv":1,"upper":"75541","lower":"75541","count":420,"preSum":10008},{"ndv":8,"upper":"75549","lower":"75541-1","count":214,"preSum":10428},{"ndv":5,"upper":"75571","lower":"75552-1","count":218,"preSum":10642},{"ndv":3,"upper":"75577-1","lower":"75572","count":205,"preSum":10860},{"ndv":6,"upper":"75602","lower":"75578","count":802,"preSum":11065},{"ndv":17,"upper":"75662","lower":"75604","count":424,"preSum":11867},{"ndv":9,"upper":"75689","lower":"75668","count":291,"preSum":12291}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[44603,1268,1227,1175,11212,995,6924,1014,833,1123,680,1578,2151,2932],"valueArr":["75202","75202-1","75216","75438","75485","75489","75492","75494","75500","75505","75510","75512","75552","75577"],"type":"String","sampleRate":0.9618625319816094}',9704,0.02436278),('jala_wms_prod','shipment_header','storename',160,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":10,"upper":"全品牌-人资福利店铺","lower":"Chando-LazadaMYHimalaya","count":266,"preSum":0},{"ndv":9,"upper":"春夏-天猫旗舰店","lower":"全品牌-优礼汇特通店铺","count":469,"preSum":266},{"ndv":2,"upper":"春夏-抖音小店","lower":"春夏-快手品牌官方店","count":196,"preSum":735},{"ndv":4,"upper":"珀芙研-云店","lower":"植物智慧-天猫旗舰店","count":240,"preSum":931},{"ndv":5,"upper":"珀芙研-抖音小店","lower":"珀芙研-京东POP旗舰店","count":287,"preSum":1171},{"ndv":3,"upper":"珀芙研-蘑菇街旗舰店","lower":"珀芙研-泛斯特店","count":646,"preSum":1458},{"ndv":2,"upper":"美素-天猫旗舰店","lower":"美素-京东POP官方旗舰店","count":371,"preSum":2104},{"ndv":4,"upper":"自然堂-云店(官方商城)","lower":"美素-抖音小店","count":375,"preSum":2475},{"ndv":3,"upper":"自然堂-京东乐肤迪官方旗舰店","lower":"自然堂-云店(美妆2.0)","count":349,"preSum":2850},{"ndv":1,"upper":"自然堂-京东充花专卖店","lower":"自然堂-京东充花专卖店","count":343,"preSum":3199},{"ndv":1,"upper":"自然堂-京东彧弈美妆专营店","lower":"自然堂-京东彧弈美妆专营店","count":338,"preSum":3542},{"ndv":2,"upper":"自然堂-京东悦悦美铺化妆品专营店","lower":"自然堂-京东思琪化妆品专营店","count":303,"preSum":3880},{"ndv":5,"upper":"自然堂-京东每妆护肤旗舰店","lower":"自然堂-京东晟妆专卖店","count":331,"preSum":4183},{"ndv":2,"upper":"自然堂-京东然美专卖店","lower":"自然堂-京东泽品美妆化妆品专营店","count":383,"preSum":4514},{"ndv":1,"upper":"自然堂-京东硕齐化妆品专营店","lower":"自然堂-京东硕齐化妆品专营店","count":328,"preSum":4897},{"ndv":1,"upper":"自然堂-京东美姿专卖店","lower":"自然堂-京东美姿专卖店","count":748,"preSum":5225},{"ndv":1,"upper":"自然堂-京东美爆化妆品专营店","lower":"自然堂-京东美爆化妆品专营店","count":432,"preSum":5973},{"ndv":4,"upper":"自然堂-品牌专卖1店","lower":"自然堂-京东美轩美妆","count":304,"preSum":6405},{"ndv":1,"upper":"自然堂-品牌专卖2店","lower":"自然堂-品牌专卖2店","count":432,"preSum":6709},{"ndv":5,"upper":"自然堂-天猫伊恋化妆品专营店","lower":"自然堂-品牌专卖3店","count":581,"preSum":7141},{"ndv":2,"upper":"自然堂-天猫俏美人专卖店","lower":"自然堂-天猫优购化妆品专营店","count":362,"preSum":7722},{"ndv":2,"upper":"自然堂-天猫名轩专卖店","lower":"自然堂-天猫博美化妆品专营店","count":591,"preSum":8084},{"ndv":1,"upper":"自然堂-天猫思琪化妆品专营店","lower":"自然堂-天猫思琪化妆品专营店","count":700,"preSum":8675},{"ndv":1,"upper":"自然堂-天猫永信化妆品专营店","lower":"自然堂-天猫永信化妆品专营店","count":247,"preSum":9375},{"ndv":1,"upper":"自然堂-天猫泽品化妆品专营店","lower":"自然堂-天猫泽品化妆品专营店","count":243,"preSum":9622},{"ndv":1,"upper":"自然堂-天猫硕齐化妆品专营店","lower":"自然堂-天猫硕齐化妆品专营店","count":457,"preSum":9865},{"ndv":2,"upper":"自然堂-小红书旗舰店","lower":"自然堂-小程序官方商城","count":528,"preSum":10322},{"ndv":1,"upper":"自然堂-抖音CHANDO男士旗舰店","lower":"自然堂-抖音CHANDO男士旗舰店","count":434,"preSum":10850},{"ndv":16,"upper":"自然堂-淘宝e购女孩","lower":"自然堂-拼多多丽友专卖店","count":194,"preSum":11284},{"ndv":3,"upper":"自然堂-淘宝美丽会客厅","lower":"自然堂-淘宝zhangmin811028","count":195,"preSum":11478},{"ndv":1,"upper":"自然堂-考拉旗舰店","lower":"自然堂-考拉旗舰店","count":249,"preSum":11673},{"ndv":3,"upper":"莎辛那-天猫旗舰店","lower":"自然堂-蘑菇街旗舰店","count":205,"preSum":11922}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[3064,1273,1474,1142,6928,49240,1729,758,1250,2317,1093,1012,11899,3121],"valueArr":["","珀芙研-天猫旗舰店","自然堂-京东POP旗舰店","自然堂-京东京品美妆专卖店","自然堂-唯品会自营旗舰店(中国)","自然堂-天猫旗舰店","自然堂-天猫朵纯专卖店","自然堂-天猫杰宸专卖店","自然堂-天猫然美专卖店","自然堂-天猫男士旗舰店","自然堂-天猫门萨专卖店","自然堂-快手官方旗舰店","自然堂-抖音官方旗舰店","自然堂-抖音美妆旗舰店"],"type":"String","sampleRate":0.9618625319816094}',1574,0.02436278),('jala_wms_prod','shipment_header','temperaturecontrol',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[98443],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',1558,0.02436278),('jala_wms_prod','shipment_header','templevel',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','text',11,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"二次取样","lower":"二次取样","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[4,57],"valueArr":["","0"],"type":"String","sampleRate":0.9618625319816094}',99939,0.02436278),('jala_wms_prod','shipment_header','thirdsectioncode',14698,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":11,"upper":"004","lower":"00","count":66,"preSum":0},{"ndv":10,"upper":"009","lower":"005","count":62,"preSum":66},{"ndv":13,"upper":"017","lower":"010","count":60,"preSum":128},{"ndv":26,"upper":"023-090-999 06","lower":"018","count":58,"preSum":188},{"ndv":41,"upper":"02A","lower":"0230-008-999 02","count":58,"preSum":246},{"ndv":25,"upper":"043","lower":"02D","count":58,"preSum":304},{"ndv":31,"upper":"063","lower":"044","count":58,"preSum":362},{"ndv":22,"upper":"08","lower":"065","count":75,"preSum":420},{"ndv":21,"upper":"096","lower":"080","count":59,"preSum":495},{"ndv":26,"upper":"105","lower":"098","count":61,"preSum":554},{"ndv":17,"upper":"112","lower":"1053","count":60,"preSum":615},{"ndv":27,"upper":"13","lower":"1120","count":74,"preSum":675},{"ndv":24,"upper":"15","lower":"1304","count":71,"preSum":749},{"ndv":24,"upper":"170","lower":"150","count":58,"preSum":820},{"ndv":28,"upper":"201","lower":"170P","count":59,"preSum":878},{"ndv":23,"upper":"22","lower":"202","count":79,"preSum":937},{"ndv":22,"upper":"24","lower":"221","count":60,"preSum":1016},{"ndv":17,"upper":"267","lower":"240","count":58,"preSum":1076},{"ndv":18,"upper":"3","lower":"26A","count":59,"preSum":1134},{"ndv":20,"upper":"318","lower":"30","count":58,"preSum":1193},{"ndv":15,"upper":"338","lower":"319","count":58,"preSum":1251},{"ndv":33,"upper":"35A","lower":"339","count":58,"preSum":1309},{"ndv":22,"upper":"38","lower":"35B","count":64,"preSum":1367},{"ndv":34,"upper":"404","lower":"384","count":60,"preSum":1431},{"ndv":22,"upper":"427-015-999 10","lower":"405","count":58,"preSum":1491},{"ndv":24,"upper":"44","lower":"427-020-999 02","count":59,"preSum":1549},{"ndv":31,"upper":"49","lower":"444","count":62,"preSum":1608},{"ndv":27,"upper":"515","lower":"490","count":58,"preSum":1670},{"ndv":39,"upper":"537-021-001 13","lower":"516","count":58,"preSum":1728},{"ndv":40,"upper":"555","lower":"537-022-002","count":66,"preSum":1786},{"ndv":29,"upper":"59","lower":"5555","count":64,"preSum":1852},{"ndv":34,"upper":"61","lower":"591","count":64,"preSum":1916},{"ndv":20,"upper":"65","lower":"6101","count":60,"preSum":1980},{"ndv":17,"upper":"67A","lower":"656","count":58,"preSum":2040},{"ndv":22,"upper":"714-014-999 06","lower":"67M","count":58,"preSum":2098},{"ndv":38,"upper":"731-091-999 01","lower":"714-022-999 01","count":58,"preSum":2156},{"ndv":37,"upper":"769-081-999 01","lower":"731-113-999","count":58,"preSum":2214},{"ndv":34,"upper":"7777","lower":"769-082-999 09","count":58,"preSum":2272},{"ndv":24,"upper":"800","lower":"779","count":58,"preSum":2330},{"ndv":33,"upper":"832","lower":"8001","count":58,"preSum":2388},{"ndv":27,"upper":"871-019-999 06","lower":"834-083-999 03","count":58,"preSum":2446},{"ndv":25,"upper":"8893","lower":"871-020-999 01","count":58,"preSum":2504},{"ndv":26,"upper":"920","lower":"8898","count":58,"preSum":2562},{"ndv":26,"upper":"98A","lower":"921","count":58,"preSum":2620},{"ndv":28,"upper":"A04","lower":"99","count":58,"preSum":2678},{"ndv":36,"upper":"A17-064-002","lower":"A05","count":58,"preSum":2736},{"ndv":43,"upper":"A60","lower":"A17-128-999 01","count":58,"preSum":2794},{"ndv":51,"upper":"B004","lower":"A61","count":58,"preSum":2852},{"ndv":36,"upper":"B25","lower":"B006","count":58,"preSum":2910},{"ndv":51,"upper":"C05","lower":"B25B","count":58,"preSum":2968},{"ndv":42,"upper":"C88","lower":"C06","count":58,"preSum":3026},{"ndv":49,"upper":"D5","lower":"C99","count":59,"preSum":3084},{"ndv":37,"upper":"DS70","lower":"D51","count":58,"preSum":3143},{"ndv":45,"upper":"F04","lower":"DS72","count":58,"preSum":3201},{"ndv":48,"upper":"G11","lower":"F09","count":59,"preSum":3259},{"ndv":52,"upper":"HM","lower":"G12","count":58,"preSum":3318},{"ndv":51,"upper":"K55C","lower":"HNZ","count":58,"preSum":3376},{"ndv":52,"upper":"N03","lower":"K58","count":58,"preSum":3434},{"ndv":49,"upper":"S4","lower":"N05","count":58,"preSum":3492},{"ndv":51,"upper":"W2","lower":"S5","count":58,"preSum":3550},{"ndv":52,"upper":"Y149","lower":"W25","count":58,"preSum":3608},{"ndv":35,"upper":"ZZZ","lower":"Y2","count":39,"preSum":3666}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[32,29,35,33,35,38,32,34,28,30,35,27,30],"valueArr":["01","02","03","04","05","06","10","11","12","16","18","20","55"],"type":"String","sampleRate":0.9618625319816094}',95878,0.02436278),('jala_wms_prod','shipment_header','thrureceiptcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','totalcases',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalconqty',1339,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":7,"lower":7,"count":13,"preSum":0},{"ndv":1,"upper":13,"lower":13,"count":10,"preSum":13},{"ndv":1,"upper":15,"lower":15,"count":12,"preSum":23},{"ndv":1,"upper":16,"lower":16,"count":12,"preSum":35},{"ndv":1,"upper":17,"lower":17,"count":10,"preSum":47},{"ndv":1,"upper":18,"lower":18,"count":11,"preSum":57},{"ndv":1,"upper":19,"lower":19,"count":8,"preSum":68},{"ndv":2,"upper":22,"lower":21,"count":8,"preSum":76},{"ndv":2,"upper":24,"lower":23,"count":11,"preSum":84},{"ndv":1,"upper":25,"lower":25,"count":8,"preSum":95},{"ndv":2,"upper":27,"lower":26,"count":8,"preSum":103},{"ndv":2,"upper":30,"lower":28,"count":11,"preSum":111},{"ndv":3,"upper":33,"lower":31,"count":8,"preSum":122},{"ndv":3,"upper":36,"lower":34,"count":10,"preSum":130},{"ndv":3,"upper":39,"lower":37,"count":8,"preSum":140},{"ndv":4,"upper":45,"lower":40,"count":11,"preSum":148},{"ndv":4,"upper":49,"lower":46,"count":11,"preSum":159},{"ndv":1,"upper":50,"lower":50,"count":7,"preSum":170},{"ndv":2,"upper":52,"lower":51,"count":8,"preSum":177},{"ndv":2,"upper":55,"lower":54,"count":7,"preSum":185},{"ndv":3,"upper":58,"lower":56,"count":9,"preSum":192},{"ndv":3,"upper":61,"lower":59,"count":7,"preSum":201},{"ndv":2,"upper":63,"lower":62,"count":9,"preSum":208},{"ndv":3,"upper":67,"lower":65,"count":9,"preSum":217},{"ndv":3,"upper":71,"lower":68,"count":7,"preSum":226},{"ndv":3,"upper":75,"lower":72,"count":7,"preSum":233},{"ndv":5,"upper":80,"lower":76,"count":8,"preSum":240},{"ndv":5,"upper":87,"lower":82,"count":8,"preSum":248},{"ndv":4,"upper":91,"lower":88,"count":7,"preSum":256},{"ndv":6,"upper":97,"lower":92,"count":7,"preSum":263},{"ndv":4,"upper":102,"lower":98,"count":7,"preSum":270},{"ndv":4,"upper":110,"lower":103,"count":7,"preSum":277},{"ndv":4,"upper":118,"lower":114,"count":7,"preSum":284},{"ndv":6,"upper":129,"lower":120,"count":7,"preSum":291},{"ndv":6,"upper":147,"lower":131,"count":7,"preSum":298},{"ndv":6,"upper":160,"lower":148,"count":9,"preSum":305},{"ndv":6,"upper":173,"lower":161,"count":7,"preSum":314},{"ndv":5,"upper":185,"lower":175,"count":7,"preSum":321},{"ndv":6,"upper":204,"lower":188,"count":7,"preSum":328},{"ndv":7,"upper":227,"lower":208,"count":7,"preSum":335},{"ndv":5,"upper":250,"lower":235,"count":7,"preSum":342},{"ndv":7,"upper":275,"lower":257,"count":7,"preSum":349},{"ndv":7,"upper":347,"lower":276,"count":7,"preSum":356},{"ndv":5,"upper":370,"lower":348,"count":7,"preSum":363},{"ndv":7,"upper":414,"lower":384,"count":7,"preSum":370},{"ndv":7,"upper":479,"lower":420,"count":7,"preSum":377},{"ndv":7,"upper":543,"lower":491,"count":7,"preSum":384},{"ndv":7,"upper":666,"lower":556,"count":7,"preSum":391},{"ndv":7,"upper":849,"lower":699,"count":7,"preSum":398},{"ndv":7,"upper":1163,"lower":861,"count":7,"preSum":405},{"ndv":7,"upper":1818,"lower":1191,"count":7,"preSum":412},{"ndv":7,"upper":2631,"lower":1963,"count":7,"preSum":419},{"ndv":3,"upper":4068,"lower":3008,"count":3,"preSum":426}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[98947,273,86,50,33,40,16,23,16,18,19,15,21,15],"valueArr":[0,1,2,3,4,5,6,8,9,10,11,12,14,20],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalcontainers',197,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":12,"lower":12,"count":19,"preSum":0},{"ndv":1,"upper":15,"lower":15,"count":11,"preSum":19},{"ndv":1,"upper":16,"lower":16,"count":3,"preSum":30},{"ndv":1,"upper":17,"lower":17,"count":8,"preSum":33},{"ndv":1,"upper":18,"lower":18,"count":5,"preSum":41},{"ndv":2,"upper":20,"lower":19,"count":6,"preSum":46},{"ndv":1,"upper":21,"lower":21,"count":4,"preSum":52},{"ndv":1,"upper":22,"lower":22,"count":4,"preSum":56},{"ndv":2,"upper":24,"lower":23,"count":3,"preSum":60},{"ndv":1,"upper":25,"lower":25,"count":2,"preSum":63},{"ndv":2,"upper":27,"lower":26,"count":4,"preSum":65},{"ndv":2,"upper":29,"lower":28,"count":2,"preSum":69},{"ndv":1,"upper":30,"lower":30,"count":2,"preSum":71},{"ndv":2,"upper":33,"lower":32,"count":6,"preSum":73},{"ndv":2,"upper":40,"lower":34,"count":2,"preSum":79},{"ndv":2,"upper":47,"lower":46,"count":2,"preSum":81},{"ndv":2,"upper":57,"lower":53,"count":2,"preSum":83},{"ndv":2,"upper":67,"lower":65,"count":2,"preSum":85},{"ndv":2,"upper":70,"lower":68,"count":3,"preSum":87},{"ndv":2,"upper":94,"lower":74,"count":2,"preSum":90},{"ndv":2,"upper":120,"lower":99,"count":2,"preSum":92},{"ndv":2,"upper":196,"lower":134,"count":2,"preSum":94},{"ndv":1,"upper":233,"lower":233,"count":1,"preSum":96}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6247,92283,463,263,163,118,141,47,39,32,33,34,20,21],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,13,14],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalgroupconts',176,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":14,"lower":14,"count":12,"preSum":0},{"ndv":1,"upper":15,"lower":15,"count":6,"preSum":12},{"ndv":2,"upper":17,"lower":16,"count":7,"preSum":18},{"ndv":1,"upper":18,"lower":18,"count":3,"preSum":25},{"ndv":1,"upper":20,"lower":20,"count":3,"preSum":28},{"ndv":1,"upper":21,"lower":21,"count":3,"preSum":31},{"ndv":1,"upper":22,"lower":22,"count":3,"preSum":34},{"ndv":2,"upper":24,"lower":23,"count":3,"preSum":37},{"ndv":1,"upper":25,"lower":25,"count":2,"preSum":40},{"ndv":2,"upper":27,"lower":26,"count":3,"preSum":42},{"ndv":2,"upper":29,"lower":28,"count":2,"preSum":45},{"ndv":1,"upper":30,"lower":30,"count":2,"preSum":47},{"ndv":1,"upper":33,"lower":33,"count":5,"preSum":49},{"ndv":2,"upper":40,"lower":34,"count":2,"preSum":54},{"ndv":2,"upper":47,"lower":46,"count":2,"preSum":56},{"ndv":2,"upper":65,"lower":53,"count":2,"preSum":58},{"ndv":2,"upper":68,"lower":67,"count":2,"preSum":60},{"ndv":1,"upper":70,"lower":70,"count":2,"preSum":62},{"ndv":2,"upper":94,"lower":74,"count":2,"preSum":64},{"ndv":2,"upper":120,"lower":99,"count":2,"preSum":66},{"ndv":2,"upper":196,"lower":134,"count":2,"preSum":68},{"ndv":1,"upper":233,"lower":233,"count":1,"preSum":70}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6247,92398,447,252,148,109,136,43,38,27,29,25,15,16],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totallines',120,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":15,"lower":0,"count":112,"preSum":0},{"ndv":1,"upper":16,"lower":16,"count":81,"preSum":112},{"ndv":1,"upper":17,"lower":17,"count":84,"preSum":193},{"ndv":1,"upper":18,"lower":18,"count":65,"preSum":277},{"ndv":1,"upper":19,"lower":19,"count":48,"preSum":342},{"ndv":1,"upper":20,"lower":20,"count":43,"preSum":390},{"ndv":1,"upper":21,"lower":21,"count":39,"preSum":433},{"ndv":1,"upper":22,"lower":22,"count":26,"preSum":472},{"ndv":1,"upper":23,"lower":23,"count":35,"preSum":498},{"ndv":1,"upper":24,"lower":24,"count":26,"preSum":533},{"ndv":1,"upper":25,"lower":25,"count":16,"preSum":559},{"ndv":1,"upper":26,"lower":26,"count":18,"preSum":575},{"ndv":1,"upper":27,"lower":27,"count":17,"preSum":593},{"ndv":1,"upper":28,"lower":28,"count":14,"preSum":610},{"ndv":1,"upper":29,"lower":29,"count":18,"preSum":624},{"ndv":1,"upper":30,"lower":30,"count":13,"preSum":642},{"ndv":1,"upper":31,"lower":31,"count":16,"preSum":655},{"ndv":1,"upper":32,"lower":32,"count":13,"preSum":671},{"ndv":2,"upper":34,"lower":33,"count":16,"preSum":684},{"ndv":2,"upper":36,"lower":35,"count":23,"preSum":700},{"ndv":3,"upper":39,"lower":37,"count":13,"preSum":723},{"ndv":1,"upper":40,"lower":40,"count":16,"preSum":736},{"ndv":3,"upper":43,"lower":41,"count":14,"preSum":752},{"ndv":2,"upper":45,"lower":44,"count":14,"preSum":766},{"ndv":4,"upper":50,"lower":46,"count":13,"preSum":780},{"ndv":6,"upper":58,"lower":51,"count":13,"preSum":793},{"ndv":8,"upper":76,"lower":59,"count":14,"preSum":806},{"ndv":2,"upper":96,"lower":85,"count":2,"preSum":820}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[31033,21232,11437,9767,9725,5918,2724,1769,1016,776,703,624,2250,205],"valueArr":[1,2,3,4,5,6,7,8,9,10,11,12,13,14],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalqty',4605,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":13,"lower":0,"count":1076,"preSum":0},{"ndv":1,"upper":14,"lower":14,"count":685,"preSum":1076},{"ndv":1,"upper":16,"lower":16,"count":744,"preSum":1761},{"ndv":1,"upper":17,"lower":17,"count":924,"preSum":2505},{"ndv":1,"upper":18,"lower":18,"count":319,"preSum":3429},{"ndv":1,"upper":19,"lower":19,"count":260,"preSum":3748},{"ndv":1,"upper":21,"lower":21,"count":131,"preSum":4008},{"ndv":1,"upper":22,"lower":22,"count":117,"preSum":4139},{"ndv":2,"upper":24,"lower":23,"count":156,"preSum":4256},{"ndv":4,"upper":28,"lower":25,"count":141,"preSum":4412},{"ndv":4,"upper":32,"lower":29,"count":125,"preSum":4553},{"ndv":5,"upper":37,"lower":33,"count":124,"preSum":4678},{"ndv":5,"upper":42,"lower":38,"count":116,"preSum":4802},{"ndv":6,"upper":48,"lower":43,"count":146,"preSum":4918},{"ndv":8,"upper":56,"lower":49,"count":116,"preSum":5064},{"ndv":15,"upper":71,"lower":57,"count":120,"preSum":5180},{"ndv":9,"upper":80,"lower":72,"count":127,"preSum":5300},{"ndv":16,"upper":96,"lower":81,"count":116,"preSum":5427},{"ndv":21,"upper":118,"lower":97,"count":116,"preSum":5543},{"ndv":7,"upper":125,"lower":119,"count":125,"preSum":5659},{"ndv":28,"upper":156,"lower":126,"count":122,"preSum":5784},{"ndv":34,"upper":192,"lower":157,"count":132,"preSum":5906},{"ndv":8,"upper":200,"lower":193,"count":123,"preSum":6038},{"ndv":45,"upper":250,"lower":201,"count":118,"preSum":6161},{"ndv":47,"upper":310,"lower":251,"count":124,"preSum":6279},{"ndv":18,"upper":339,"lower":311,"count":116,"preSum":6403},{"ndv":59,"upper":457,"lower":340,"count":116,"preSum":6519},{"ndv":60,"upper":600,"lower":458,"count":122,"preSum":6635},{"ndv":72,"upper":840,"lower":608,"count":119,"preSum":6757},{"ndv":44,"upper":1236,"lower":847,"count":118,"preSum":6876},{"ndv":82,"upper":2400,"lower":1260,"count":120,"preSum":6994},{"ndv":83,"upper":5220,"lower":2404,"count":116,"preSum":7114},{"ndv":108,"upper":30296,"lower":5252,"count":116,"preSum":7230},{"ndv":34,"upper":600000,"lower":30732,"count":35,"preSum":7346}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[16285,19254,8949,7479,5745,9549,3607,3712,5245,4883,1393,1429,2056,3034],"valueArr":[1,2,3,4,5,6,7,8,9,10,11,12,15,20],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalvalue',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0.0000],"type":"Double","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalvolume',100371,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":34,"upper":98.4050,"lower":1.0000,"count":1308,"preSum":0},{"ndv":60,"upper":203.9490,"lower":99.2900,"count":1321,"preSum":1308},{"ndv":39,"upper":255.9070,"lower":205.8720,"count":1227,"preSum":2629},{"ndv":72,"upper":319.8530,"lower":256.0600,"count":1978,"preSum":3856},{"ndv":136,"upper":418.2780,"lower":320.3910,"count":1310,"preSum":5834},{"ndv":102,"upper":492.4770,"lower":418.6000,"count":1384,"preSum":7144},{"ndv":54,"upper":535.0120,"lower":493.2180,"count":1306,"preSum":8528},{"ndv":49,"upper":554.1320,"lower":535.5110,"count":1204,"preSum":9834},{"ndv":37,"upper":574.3250,"lower":555.7490,"count":1396,"preSum":11038},{"ndv":69,"upper":605.9880,"lower":575.9130,"count":1174,"preSum":12434},{"ndv":79,"upper":639.2230,"lower":606.4120,"count":1173,"preSum":13608},{"ndv":126,"upper":694.7190,"lower":639.4460,"count":1184,"preSum":14781},{"ndv":71,"upper":720.1130,"lower":695.3190,"count":1173,"preSum":15965},{"ndv":88,"upper":752.0080,"lower":720.2660,"count":1177,"preSum":17138},{"ndv":46,"upper":772.1450,"lower":753.3750,"count":1176,"preSum":18315},{"ndv":145,"upper":825.2350,"lower":773.0070,"count":1172,"preSum":19491},{"ndv":172,"upper":887.1950,"lower":826.1140,"count":1173,"preSum":20663},{"ndv":56,"upper":908.6990,"lower":887.8300,"count":1172,"preSum":21836},{"ndv":203,"upper":1002.8560,"lower":908.8030,"count":1177,"preSum":23008},{"ndv":199,"upper":1081.1810,"lower":1003.3480,"count":1175,"preSum":24185},{"ndv":84,"upper":1117.0860,"lower":1081.2220,"count":1203,"preSum":25360},{"ndv":174,"upper":1185.7310,"lower":1117.1590,"count":1223,"preSum":26563},{"ndv":100,"upper":1226.9300,"lower":1185.9020,"count":1172,"preSum":27786},{"ndv":195,"upper":1308.3850,"lower":1226.9630,"count":1208,"preSum":28958},{"ndv":242,"upper":1423.4300,"lower":1309.0900,"count":1254,"preSum":30166},{"ndv":366,"upper":1585.8640,"lower":1424.2060,"count":1174,"preSum":31420},{"ndv":346,"upper":1741.8100,"lower":1586.0100,"count":1172,"preSum":32594},{"ndv":369,"upper":1917.5730,"lower":1742.2760,"count":1178,"preSum":33766},{"ndv":299,"upper":2057.5110,"lower":1918.1900,"count":1174,"preSum":34944},{"ndv":321,"upper":2211.5090,"lower":2057.7230,"count":1180,"preSum":36118},{"ndv":285,"upper":2357.0670,"lower":2211.8270,"count":1175,"preSum":37298},{"ndv":338,"upper":2527.8980,"lower":2358.1360,"count":1172,"preSum":38473},{"ndv":115,"upper":2586.6240,"lower":2528.5050,"count":1276,"preSum":39645},{"ndv":327,"upper":2755.8640,"lower":2587.4640,"count":1232,"preSum":40921},{"ndv":296,"upper":2914.8540,"lower":2757.0860,"count":1564,"preSum":42153},{"ndv":98,"upper":2967.8460,"lower":2914.9820,"count":1655,"preSum":43717},{"ndv":336,"upper":3197.5570,"lower":2967.8810,"count":1180,"preSum":45372},{"ndv":507,"upper":3525.5280,"lower":3198.9240,"count":1226,"preSum":46552},{"ndv":334,"upper":3802.1240,"lower":3525.5560,"count":1172,"preSum":47778},{"ndv":431,"upper":4203.1170,"lower":3805.1870,"count":1174,"preSum":48950},{"ndv":185,"upper":4408.9500,"lower":4204.3350,"count":1419,"preSum":50124},{"ndv":141,"upper":4576.6380,"lower":4409.1020,"count":1633,"preSum":51543},{"ndv":257,"upper":4936.9760,"lower":4580.1640,"count":1181,"preSum":53176},{"ndv":248,"upper":5349.4740,"lower":4939.9800,"count":1527,"preSum":54357},{"ndv":202,"upper":5729.6170,"lower":5351.3580,"count":1173,"preSum":55884},{"ndv":70,"upper":5875.8800,"lower":5729.6460,"count":1175,"preSum":57057},{"ndv":118,"upper":6131.4950,"lower":5879.1140,"count":1215,"preSum":58232},{"ndv":80,"upper":6334.1450,"lower":6131.9400,"count":1198,"preSum":59447},{"ndv":60,"upper":6466.5600,"lower":6339.9580,"count":1189,"preSum":60645},{"ndv":82,"upper":6623.3860,"lower":6467.1610,"count":1193,"preSum":61834},{"ndv":84,"upper":6858.3700,"lower":6629.5240,"count":1978,"preSum":63027},{"ndv":288,"upper":7627.7300,"lower":6859.6580,"count":1175,"preSum":65005},{"ndv":236,"upper":8394.2520,"lower":7629.3290,"count":1555,"preSum":66180},{"ndv":237,"upper":9232.8970,"lower":8395.1550,"count":1172,"preSum":67735},{"ndv":366,"upper":10830.8960,"lower":9237.5880,"count":1173,"preSum":68907},{"ndv":407,"upper":12971.8100,"lower":10833.0000,"count":1172,"preSum":70080},{"ndv":696,"upper":24903.7680,"lower":12977.2040,"count":1172,"preSum":71252},{"ndv":966,"upper":114154.3380,"lower":25018.3200,"count":1181,"preSum":72424},{"ndv":993,"upper":2035981.4400,"lower":114268.7500,"count":1172,"preSum":73605},{"ndv":207,"upper":2304960000.0000,"lower":2049274.0800,"count":208,"preSum":74777}],"maxBucketSize":64,"type":"Double","sampleRate":0.9618625}','{"countArr":[2232,990,1204,3921,933,4042,1511,1379,1020,1570,1115,1283,1085,2731],"valueArr":[0.0000,385.5000,738.2020,1060.3700,1195.3200,2204.4750,2350.3520,3169.9790,5482.1190,6358.2440,7051.0560,7736.0400,7904.1340,15255.4600],"type":"Double","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalweight',106428,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":83,"upper":35.0000,"lower":0.1350,"count":1276,"preSum":0},{"ndv":74,"upper":58.3330,"lower":36.0000,"count":1266,"preSum":1276},{"ndv":43,"upper":70.8330,"lower":58.3340,"count":1306,"preSum":2542},{"ndv":62,"upper":81.2500,"lower":70.8340,"count":1298,"preSum":3848},{"ndv":94,"upper":102.9160,"lower":81.5830,"count":1261,"preSum":5146},{"ndv":66,"upper":118.7500,"lower":103.0000,"count":1268,"preSum":6407},{"ndv":65,"upper":131.0000,"lower":119.0280,"count":1272,"preSum":7675},{"ndv":69,"upper":143.7500,"lower":131.1100,"count":1582,"preSum":8947},{"ndv":99,"upper":160.0000,"lower":144.0000,"count":1298,"preSum":10529},{"ndv":153,"upper":185.4170,"lower":160.4160,"count":1274,"preSum":11827},{"ndv":168,"upper":211.0000,"lower":185.5000,"count":1283,"preSum":13101},{"ndv":112,"upper":227.9170,"lower":211.1090,"count":1315,"preSum":14384},{"ndv":128,"upper":241.6670,"lower":228.0000,"count":1279,"preSum":15699},{"ndv":56,"upper":248.7510,"lower":241.8040,"count":1265,"preSum":16978},{"ndv":82,"upper":258.3330,"lower":248.8330,"count":1266,"preSum":18243},{"ndv":67,"upper":266.7500,"lower":258.3340,"count":1449,"preSum":19509},{"ndv":137,"upper":285.0000,"lower":266.7750,"count":1262,"preSum":20958},{"ndv":125,"upper":298.7480,"lower":285.1660,"count":1264,"preSum":22220},{"ndv":74,"upper":310.0000,"lower":298.7500,"count":1291,"preSum":23484},{"ndv":86,"upper":319.4440,"lower":310.3380,"count":1683,"preSum":24775},{"ndv":169,"upper":340.0000,"lower":319.4450,"count":1283,"preSum":26458},{"ndv":119,"upper":354.7500,"lower":340.2500,"count":1339,"preSum":27741},{"ndv":136,"upper":372.0000,"lower":354.8890,"count":1338,"preSum":29080},{"ndv":283,"upper":408.3320,"lower":372.0800,"count":1266,"preSum":30418},{"ndv":310,"upper":456.3330,"lower":408.3330,"count":1279,"preSum":31684},{"ndv":253,"upper":500.0000,"lower":456.5760,"count":1424,"preSum":32963},{"ndv":204,"upper":533.3320,"lower":500.0100,"count":1362,"preSum":34387},{"ndv":332,"upper":575.0000,"lower":533.3330,"count":1264,"preSum":35749},{"ndv":222,"upper":608.3340,"lower":575.6950,"count":1267,"preSum":37013},{"ndv":265,"upper":650.0010,"lower":608.8610,"count":1691,"preSum":38280},{"ndv":442,"upper":728.7490,"lower":650.1010,"count":1267,"preSum":39971},{"ndv":331,"upper":784.2780,"lower":728.7500,"count":1260,"preSum":41238},{"ndv":169,"upper":814.5810,"lower":784.3040,"count":1262,"preSum":42498},{"ndv":201,"upper":846.5830,"lower":814.5840,"count":1272,"preSum":43760},{"ndv":151,"upper":868.0550,"lower":846.6660,"count":1353,"preSum":45032},{"ndv":262,"upper":906.8050,"lower":868.1660,"count":1264,"preSum":46385},{"ndv":368,"upper":956.0000,"lower":907.0000,"count":1285,"preSum":47649},{"ndv":105,"upper":970.6950,"lower":956.1120,"count":1261,"preSum":48934},{"ndv":346,"upper":1016.6680,"lower":970.8280,"count":1262,"preSum":50195},{"ndv":429,"upper":1085.0000,"lower":1016.7750,"count":1260,"preSum":51457},{"ndv":390,"upper":1153.4330,"lower":1085.1100,"count":1260,"preSum":52717},{"ndv":239,"upper":1197.9150,"lower":1153.5670,"count":1260,"preSum":53977},{"ndv":389,"upper":1262.5020,"lower":1198.0000,"count":1597,"preSum":55237},{"ndv":455,"upper":1360.4160,"lower":1262.7770,"count":1260,"preSum":56834},{"ndv":550,"upper":1465.8300,"lower":1360.4170,"count":1260,"preSum":58094},{"ndv":259,"upper":1524.0000,"lower":1465.8330,"count":1266,"preSum":59354},{"ndv":204,"upper":1572.2140,"lower":1524.1380,"count":1260,"preSum":60620},{"ndv":251,"upper":1626.9980,"lower":1572.5000,"count":1260,"preSum":61880},{"ndv":164,"upper":1675.0000,"lower":1627.5820,"count":1420,"preSum":63140},{"ndv":310,"upper":1758.8900,"lower":1675.4990,"count":1367,"preSum":64560},{"ndv":207,"upper":1831.9420,"lower":1758.8920,"count":1261,"preSum":65927},{"ndv":219,"upper":1909.8010,"lower":1832.8120,"count":1260,"preSum":67188},{"ndv":181,"upper":1988.2840,"lower":1909.8270,"count":1479,"preSum":68448},{"ndv":239,"upper":2104.1700,"lower":1988.5710,"count":1346,"preSum":69927},{"ndv":185,"upper":2202.5900,"lower":2104.5000,"count":1403,"preSum":71273},{"ndv":210,"upper":2342.6130,"lower":2203.7260,"count":1292,"preSum":72676},{"ndv":334,"upper":2646.2890,"lower":2343.4160,"count":1260,"preSum":73968},{"ndv":495,"upper":3366.6720,"lower":2646.3720,"count":1332,"preSum":75228},{"ndv":529,"upper":5315.0000,"lower":3367.7370,"count":1260,"preSum":76560},{"ndv":1033,"upper":26183.9520,"lower":5323.3310,"count":1260,"preSum":77820},{"ndv":1048,"upper":410066.4080,"lower":26190.4160,"count":1260,"preSum":79080},{"ndv":263,"upper":106233375.0000,"lower":413900.0800,"count":264,"preSum":80340}],"maxBucketSize":64,"type":"Double","sampleRate":0.9618625}','{"countArr":[917,1666,2254,1261,2194,1283,1882,1311,1152,756,907,1085,1062,1667],"valueArr":[0.0000,490.0000,508.3340,600.0000,780.0000,799.9980,837.5000,1758.1140,1800.0000,2148.5900,2250.0000,2545.8350,3900.0000,4208.3400],"type":"Double","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','towarehousecode',55,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"C001","lower":"C001","count":2,"preSum":0},{"ndv":1,"upper":"C002","lower":"C002","count":2,"preSum":2},{"ndv":1,"upper":"C003","lower":"C003","count":4,"preSum":4},{"ndv":2,"upper":"D004","lower":"D001","count":2,"preSum":8},{"ndv":1,"upper":"D007","lower":"D007","count":3,"preSum":10},{"ndv":1,"upper":"D011","lower":"D011","count":2,"preSum":13},{"ndv":1,"upper":"JD01","lower":"JD01","count":6,"preSum":15},{"ndv":1,"upper":"JD02","lower":"JD02","count":5,"preSum":21},{"ndv":1,"upper":"JD08","lower":"JD08","count":2,"preSum":26},{"ndv":1,"upper":"S003","lower":"S003","count":4,"preSum":28},{"ndv":1,"upper":"S004","lower":"S004","count":13,"preSum":32},{"ndv":1,"upper":"S106","lower":"S106","count":13,"preSum":45},{"ndv":1,"upper":"S108","lower":"S108","count":3,"preSum":58},{"ndv":1,"upper":"S109","lower":"S109","count":9,"preSum":61},{"ndv":1,"upper":"S113","lower":"S113","count":15,"preSum":70},{"ndv":1,"upper":"W002","lower":"W002","count":10,"preSum":85},{"ndv":1,"upper":"W005","lower":"W005","count":3,"preSum":95},{"ndv":1,"upper":"W007","lower":"W007","count":3,"preSum":98},{"ndv":2,"upper":"W013","lower":"W009","count":3,"preSum":101},{"ndv":1,"upper":"W028","lower":"W028","count":10,"preSum":104}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2644,23,47,16,23,17,16,18,30,22,35,16,24,24],"valueArr":["","D017","S001","S002","S005","S007","S101","S102","S103","S104","S105","S107","S112","S115"],"type":"String","sampleRate":0.9618625319816094}',96932,0.02436278),('jala_wms_prod','shipment_header','trackingtype',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','trailingsts',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6391,5,3,28,93574],"valueArr":[100,300,400,600,900],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','twovotesystem',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','updatereason',11,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"质检已处理","lower":"质检已处理","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[25,4],"valueArr":["ZXL后台刷掉标记回传","已回传"],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','uploadbatch',422855,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1297,"upper":"2023-02-26 09:26:01","lower":"2022-09-05 11:36:01","count":1460,"preSum":0},{"ndv":1077,"upper":"2023-03-07 10:10:02","lower":"2023-02-26 09:27:00","count":1460,"preSum":1460},{"ndv":1129,"upper":"2023-03-20 09:49:00","lower":"2023-03-07 10:10:05","count":1460,"preSum":2920},{"ndv":1172,"upper":"2023-04-09 10:43:00","lower":"2023-03-20 09:50:00","count":1460,"preSum":4380},{"ndv":1128,"upper":"2023-04-17 09:49:08","lower":"2023-04-09 10:44:00","count":1461,"preSum":5840},{"ndv":1112,"upper":"2023-04-21 09:36:03","lower":"2023-04-17 09:51:01","count":1460,"preSum":7301},{"ndv":1002,"upper":"2023-04-22 18:47:10","lower":"2023-04-21 09:36:04","count":1460,"preSum":8761},{"ndv":986,"upper":"2023-04-25 10:18:11","lower":"2023-04-22 18:49:02","count":1460,"preSum":10221},{"ndv":1064,"upper":"2023-04-26 17:03:06","lower":"2023-04-25 10:19:02","count":1461,"preSum":11681},{"ndv":1009,"upper":"2023-04-28 15:20:06","lower":"2023-04-26 17:05:04","count":1460,"preSum":13142},{"ndv":1016,"upper":"2023-04-29 21:30:26","lower":"2023-04-28 15:20:13","count":1461,"preSum":14602},{"ndv":1068,"upper":"2023-05-01 15:57:11","lower":"2023-04-29 21:32:30","count":1460,"preSum":16063},{"ndv":1082,"upper":"2023-05-03 10:05:08","lower":"2023-05-01 15:59:10","count":1460,"preSum":17523},{"ndv":771,"upper":"2023-05-03 15:57:07","lower":"2023-05-03 10:06:05","count":1460,"preSum":18983},{"ndv":918,"upper":"2023-05-04 11:22:02","lower":"2023-05-03 15:57:08","count":1460,"preSum":20443},{"ndv":1091,"upper":"2023-05-05 10:20:09","lower":"2023-05-04 11:22:03","count":1460,"preSum":21903},{"ndv":980,"upper":"2023-05-06 18:23:00","lower":"2023-05-05 10:20:11","count":1462,"preSum":23363},{"ndv":1030,"upper":"2023-05-08 15:40:04","lower":"2023-05-06 18:26:00","count":1460,"preSum":24825},{"ndv":1023,"upper":"2023-05-10 11:02:20","lower":"2023-05-08 15:41:02","count":1460,"preSum":26285},{"ndv":935,"upper":"2023-05-11 14:54:33","lower":"2023-05-10 11:03:09","count":1461,"preSum":27745},{"ndv":1083,"upper":"2023-05-12 19:06:11","lower":"2023-05-11 14:54:34","count":1460,"preSum":29206},{"ndv":1190,"upper":"2023-05-14 13:50:22","lower":"2023-05-12 19:09:11","count":1460,"preSum":30666},{"ndv":1023,"upper":"2023-05-16 09:16:01","lower":"2023-05-14 13:50:24","count":1460,"preSum":32126},{"ndv":1031,"upper":"2023-05-17 12:35:05","lower":"2023-05-16 09:17:01","count":1460,"preSum":33586},{"ndv":1117,"upper":"2023-05-18 11:08:19","lower":"2023-05-17 12:35:06","count":1460,"preSum":35046},{"ndv":949,"upper":"2023-05-19 16:32:12","lower":"2023-05-18 11:08:20","count":1461,"preSum":36506},{"ndv":1048,"upper":"2023-05-21 13:11:11","lower":"2023-05-19 16:33:09","count":1461,"preSum":37967},{"ndv":1106,"upper":"2023-05-23 09:50:18","lower":"2023-05-21 13:12:09","count":1460,"preSum":39428},{"ndv":1147,"upper":"2023-05-24 16:52:11","lower":"2023-05-23 09:52:15","count":1460,"preSum":40888},{"ndv":884,"upper":"2023-05-26 14:18:01","lower":"2023-05-24 16:52:12","count":1461,"preSum":42348},{"ndv":1037,"upper":"2023-05-28 13:19:06","lower":"2023-05-26 14:18:02","count":1460,"preSum":43809},{"ndv":1273,"upper":"2023-05-30 15:55:26","lower":"2023-05-28 13:20:02","count":1460,"preSum":45269},{"ndv":1171,"upper":"2023-05-31 22:47:05","lower":"2023-05-30 15:56:21","count":1461,"preSum":46729},{"ndv":785,"upper":"2023-06-01 03:57:07","lower":"2023-05-31 22:47:06","count":1460,"preSum":48190},{"ndv":928,"upper":"2023-06-01 10:09:12","lower":"2023-06-01 03:57:08","count":1460,"preSum":49650},{"ndv":1082,"upper":"2023-06-01 13:11:13","lower":"2023-06-01 10:10:06","count":1460,"preSum":51110},{"ndv":1217,"upper":"2023-06-01 15:46:08","lower":"2023-06-01 13:11:16","count":1460,"preSum":52570},{"ndv":1331,"upper":"2023-06-01 18:54:45","lower":"2023-06-01 15:46:11","count":1460,"preSum":54030},{"ndv":1352,"upper":"2023-06-01 21:56:01","lower":"2023-06-01 18:54:54","count":1460,"preSum":55490},{"ndv":1342,"upper":"2023-06-02 06:57:28","lower":"2023-06-01 21:56:14","count":1460,"preSum":56950},{"ndv":950,"upper":"2023-06-02 14:40:02","lower":"2023-06-02 06:58:09","count":1460,"preSum":58410},{"ndv":725,"upper":"2023-06-03 04:39:01","lower":"2023-06-02 14:40:03","count":1463,"preSum":59870},{"ndv":694,"upper":"2023-06-03 15:45:01","lower":"2023-06-03 04:45:01","count":1460,"preSum":61333},{"ndv":718,"upper":"2023-06-04 14:16:04","lower":"2023-06-03 15:46:02","count":1460,"preSum":62793},{"ndv":704,"upper":"2023-06-05 14:30:01","lower":"2023-06-04 14:17:01","count":1460,"preSum":64253},{"ndv":714,"upper":"2023-06-06 15:31:01","lower":"2023-06-05 14:32:01","count":1462,"preSum":65713},{"ndv":788,"upper":"2023-06-07 17:43:01","lower":"2023-06-06 15:32:01","count":1461,"preSum":67175},{"ndv":783,"upper":"2023-06-09 14:56:02","lower":"2023-06-07 17:44:01","count":1460,"preSum":68636},{"ndv":769,"upper":"2023-06-11 11:01:01","lower":"2023-06-09 14:58:01","count":1461,"preSum":70096},{"ndv":805,"upper":"2023-06-12 17:44:01","lower":"2023-06-11 11:02:02","count":1460,"preSum":71557},{"ndv":739,"upper":"2023-06-14 10:13:58","lower":"2023-06-12 17:46:01","count":1460,"preSum":73017},{"ndv":815,"upper":"2023-06-15 17:12:02","lower":"2023-06-14 10:13:59","count":1460,"preSum":74477},{"ndv":746,"upper":"2023-06-16 13:46:05","lower":"2023-06-15 17:13:01","count":1460,"preSum":75937},{"ndv":671,"upper":"2023-06-16 20:44:01","lower":"2023-06-16 13:46:06","count":1463,"preSum":77397},{"ndv":660,"upper":"2023-06-17 13:23:01","lower":"2023-06-16 20:44:20","count":1460,"preSum":78860},{"ndv":703,"upper":"2023-06-18 09:33:11","lower":"2023-06-17 13:23:04","count":1460,"preSum":80320},{"ndv":693,"upper":"2023-06-18 16:07:03","lower":"2023-06-18 09:34:03","count":1460,"preSum":81780},{"ndv":689,"upper":"2023-06-19 09:30:03","lower":"2023-06-18 16:08:01","count":1460,"preSum":83240},{"ndv":647,"upper":"2023-06-19 14:42:10","lower":"2023-06-19 09:30:04","count":1460,"preSum":84700},{"ndv":719,"upper":"2023-06-20 09:55:04","lower":"2023-06-19 14:42:11","count":1460,"preSum":86160},{"ndv":714,"upper":"2023-06-21 09:57:02","lower":"2023-06-20 09:55:05","count":1461,"preSum":87620},{"ndv":897,"upper":"2023-06-23 15:23:01","lower":"2023-06-21 09:57:03","count":1460,"preSum":89081},{"ndv":890,"upper":"2023-06-26 11:50:01","lower":"2023-06-23 15:27:01","count":1460,"preSum":90541},{"ndv":900,"upper":"2023-06-28 23:32:23","lower":"2023-06-26 11:51:01","count":1405,"preSum":92001}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[14,13,14,15,15,15,14,13,13,16,13,13,16],"valueArr":["","2023-06-05 09:30:01","2023-06-05 16:19:01","2023-06-05 17:07:03","2023-06-05 17:11:04","2023-06-06 08:55:02","2023-06-06 09:52:19","2023-06-06 14:00:01","2023-06-09 11:33:04","2023-06-09 17:15:01","2023-06-10 08:51:01","2023-06-19 14:39:12","2023-06-25 18:37:01"],"type":"String","sampleRate":0.9618625319816094}',6411,0.02436278),('jala_wms_prod','shipment_header','uploadrequired',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[99996,5],"valueArr":[0,1],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','uploadture',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[98669,30],"valueArr":[0,1],"type":"Int","sampleRate":0.9618625319816094}',1302,0.02436278),('jala_wms_prod','shipment_header','userdef1',22,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"2023-05-09","lower":"2023-05-09","count":1,"preSum":0},{"ndv":1,"upper":"2023-05-22","lower":"2023-05-22","count":1,"preSum":1},{"ndv":1,"upper":"A63778","lower":"A63778","count":2,"preSum":2}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[93938,1206,41,4,113,59],"valueArr":["0","A49977","A56685_1","A58804","A61584","A63780_1"],"type":"String","sampleRate":0.9618625319816094}',4636,0.02436278),('jala_wms_prod','shipment_header','userdef2',8,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"G","lower":"G","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[438,359,282,9,1405,418,144],"valueArr":["","10","11","12","A","B","Z"],"type":"String","sampleRate":0.9618625319816094}',96944,0.02436278),('jala_wms_prod','shipment_header','userdef3',26405,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":36,"upper":"CXDS-DL22110471055","lower":"1000651","count":40,"preSum":0},{"ndv":40,"upper":"DB000032751","lower":"CXDS-DL22110471056","count":40,"preSum":40},{"ndv":40,"upper":"DB000035723","lower":"DB000032762","count":40,"preSum":80},{"ndv":39,"upper":"DB000038973","lower":"DB000035782","count":40,"preSum":120},{"ndv":40,"upper":"DB000042166","lower":"DB000038974","count":40,"preSum":160},{"ndv":38,"upper":"DB000045597","lower":"DB000043009","count":40,"preSum":200},{"ndv":40,"upper":"DB000046092","lower":"DB000045598","count":40,"preSum":240},{"ndv":40,"upper":"DB000047589","lower":"DB000046161","count":40,"preSum":280},{"ndv":40,"upper":"JLCS-JX23032619010","lower":"DB000047597","count":40,"preSum":320},{"ndv":38,"upper":"JLCS-JX23041958398","lower":"JLCS-JX23032958559","count":40,"preSum":360},{"ndv":40,"upper":"JLCS-JX23042672013","lower":"JLCS-JX23041958758","count":40,"preSum":400},{"ndv":40,"upper":"JLCS-JX23050677737","lower":"JLCS-JX23042778152","count":40,"preSum":440},{"ndv":40,"upper":"JLCS-JX23051892773","lower":"JLCS-JX23050677809","count":40,"preSum":480},{"ndv":40,"upper":"JLCS-JX23053023198","lower":"JLCS-JX23051912825","count":40,"preSum":520},{"ndv":40,"upper":"JLCS-JX23061441914","lower":"JLCS-JX23053023410","count":40,"preSum":560},{"ndv":39,"upper":"JLCS-JX23061681792","lower":"JLCS-JX23061442214","count":40,"preSum":600},{"ndv":40,"upper":"JLMK-DL23040426856","lower":"JLCS-JX23061684460","count":40,"preSum":640},{"ndv":38,"upper":"MFDD-NB22112239346","lower":"JLMK-DL23040750385","count":40,"preSum":680},{"ndv":40,"upper":"MFDD-NB23010579031","lower":"MFDD-NB22112239347","count":40,"preSum":720},{"ndv":39,"upper":"MFDD-NB23040323892","lower":"MFDD-NB23010579037","count":40,"preSum":760},{"ndv":39,"upper":"MFDD-NB23051914604","lower":"MFDD-NB23040641056","count":40,"preSum":800},{"ndv":40,"upper":"MSCS-JX23010254795","lower":"MFDD-NB23051914735","count":40,"preSum":840},{"ndv":35,"upper":"ZRCS-JX22110825698","lower":"MSCS-JX23010254810","count":40,"preSum":880},{"ndv":40,"upper":"ZRCS-JX23010576718","lower":"ZRCS-JX22111572614","count":40,"preSum":920},{"ndv":40,"upper":"ZRCS-JX23010796514","lower":"ZRCS-JX23010576752","count":40,"preSum":960},{"ndv":40,"upper":"ZRCS-JX23030668972","lower":"ZRCS-JX23010797907","count":40,"preSum":1000},{"ndv":40,"upper":"ZRCS-JX23032259738","lower":"ZRCS-JX23030771763","count":40,"preSum":1040},{"ndv":40,"upper":"ZRCS-JX23040320208","lower":"ZRCS-JX23032260836","count":40,"preSum":1080},{"ndv":40,"upper":"ZRCS-JX23040635959","lower":"ZRCS-JX23040320473","count":40,"preSum":1120},{"ndv":40,"upper":"ZRCS-JX23041070558","lower":"ZRCS-JX23040636151","count":40,"preSum":1160},{"ndv":40,"upper":"ZRCS-JX23041396988","lower":"ZRCS-JX23041070635","count":40,"preSum":1200},{"ndv":40,"upper":"ZRCS-JX23041849439","lower":"ZRCS-JX23041397281","count":40,"preSum":1240},{"ndv":40,"upper":"ZRCS-JX23042425522","lower":"ZRCS-JX23041854186","count":40,"preSum":1280},{"ndv":40,"upper":"ZRCS-JX23042670593","lower":"ZRCS-JX23042426695","count":40,"preSum":1320},{"ndv":40,"upper":"ZRCS-JX23042828621","lower":"ZRCS-JX23042671893","count":40,"preSum":1360},{"ndv":40,"upper":"ZRCS-JX23050894512","lower":"ZRCS-JX23042828678","count":40,"preSum":1400},{"ndv":40,"upper":"ZRCS-JX23051346509","lower":"ZRCS-JX23050911136","count":40,"preSum":1440},{"ndv":40,"upper":"ZRCS-JX23052227178","lower":"ZRCS-JX23051554998","count":40,"preSum":1480},{"ndv":40,"upper":"ZRCS-JX23052568859","lower":"ZRCS-JX23052228410","count":40,"preSum":1520},{"ndv":39,"upper":"ZRCS-JX23053019779","lower":"ZRCS-JX23052569692","count":40,"preSum":1560},{"ndv":40,"upper":"ZRCS-JX23053150401","lower":"ZRCS-JX23053020681","count":40,"preSum":1600},{"ndv":40,"upper":"ZRCS-JX23061334541","lower":"ZRCS-JX23053150993","count":40,"preSum":1640},{"ndv":40,"upper":"ZRCS-JX23061610107","lower":"ZRCS-JX23061335155","count":40,"preSum":1680},{"ndv":39,"upper":"ZRCS-JX23062133017","lower":"ZRCS-JX23061611207","count":40,"preSum":1720},{"ndv":40,"upper":"ZRDS-DL23032852701","lower":"ZRCS-JX23062133072","count":40,"preSum":1760},{"ndv":39,"upper":"ZRMK-DL23042827658","lower":"ZRDS-DL23032852702","count":40,"preSum":1800},{"ndv":40,"upper":"ZRTC-JH23042794685","lower":"ZRMK-DL23042827773","count":40,"preSum":1840},{"ndv":40,"upper":"ZRTC-JH23052915928","lower":"ZRTC-JH23042794690","count":40,"preSum":1880},{"ndv":40,"upper":"ZRTC-JH23061563195","lower":"ZRTC-JH23052915930","count":40,"preSum":1920},{"ndv":40,"upper":"ZRTC-JH23062866833","lower":"ZRTC-JH23061563210","count":40,"preSum":1960},{"ndv":40,"upper":"ZRWS-DL22111810808","lower":"ZRTC-JH23062866886","count":40,"preSum":2000},{"ndv":40,"upper":"ZRWS-DL23020347512","lower":"ZRWS-DL22111899518","count":40,"preSum":2040},{"ndv":40,"upper":"ZRWS-DL23042823287","lower":"ZRWS-DL23020347994","count":40,"preSum":2080},{"ndv":40,"upper":"ZRZS-DL23010469247","lower":"ZRWS-DL23042824131","count":40,"preSum":2120},{"ndv":40,"upper":"ZRZS-JX23021867221","lower":"ZRZS-DL23021063580","count":40,"preSum":2160},{"ndv":40,"upper":"ZRZS-JX23040431205","lower":"ZRZS-JX23022034091","count":40,"preSum":2200},{"ndv":40,"upper":"ZRZS-JX23041850390","lower":"ZRZS-JX23040431206","count":40,"preSum":2240},{"ndv":40,"upper":"ZRZS-JX23042787846","lower":"ZRZS-JX23041853056","count":40,"preSum":2280},{"ndv":40,"upper":"ZRZS-JX23050997661","lower":"ZRZS-JX23042788841","count":40,"preSum":2320},{"ndv":40,"upper":"ZRZS-JX23051669318","lower":"ZRZS-JX23050999668","count":40,"preSum":2360},{"ndv":40,"upper":"ZRZS-JX23052449375","lower":"ZRZS-JX23051669331","count":40,"preSum":2400},{"ndv":40,"upper":"ZRZS-JX23060259746","lower":"ZRZS-JX23052453872","count":40,"preSum":2440},{"ndv":40,"upper":"ZRZS-JX23062024798","lower":"ZRZS-JX23060259799","count":40,"preSum":2480},{"ndv":27,"upper":"ZWCS-JX23051025592","lower":"ZRZS-JX23062024825","count":27,"preSum":2520}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[138,5,10,9,10,4,4,4,11,5,3,3,3],"valueArr":["","1000183","1000650","1000767","1001005","1001483","1001871","1002479","D017","DW02","S115-1000","ZRCS-JX23040112356","ZRCS-JX23040321713"],"type":"String","sampleRate":0.9618625319816094}',97245,0.02436278),('jala_wms_prod','shipment_header','userdef4',4030,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":7,"upper":"DB000025224","lower":"DB000024877","count":7,"preSum":0},{"ndv":7,"upper":"DB000025284","lower":"DB000025225","count":7,"preSum":7},{"ndv":7,"upper":"DB000025401","lower":"DB000025292","count":7,"preSum":14},{"ndv":7,"upper":"DB000025449","lower":"DB000025404","count":7,"preSum":21},{"ndv":7,"upper":"DB000025856","lower":"DB000025450","count":7,"preSum":28},{"ndv":7,"upper":"DB000026017","lower":"DB000025866","count":7,"preSum":35},{"ndv":6,"upper":"DB000026226","lower":"DB000026148","count":7,"preSum":42},{"ndv":7,"upper":"DB000026296","lower":"DB000026233","count":7,"preSum":49},{"ndv":7,"upper":"DB000026434","lower":"DB000026405","count":7,"preSum":56},{"ndv":7,"upper":"DB000027313","lower":"DB000026460","count":7,"preSum":63},{"ndv":7,"upper":"DB000027620","lower":"DB000027395","count":7,"preSum":70},{"ndv":7,"upper":"DB000027770","lower":"DB000027661","count":7,"preSum":77},{"ndv":7,"upper":"DB000027886","lower":"DB000027771","count":7,"preSum":84},{"ndv":7,"upper":"DB000028715","lower":"DB000028116","count":7,"preSum":91},{"ndv":7,"upper":"DB000029286","lower":"DB000028745","count":7,"preSum":98},{"ndv":7,"upper":"DB000030189","lower":"DB000029289","count":7,"preSum":105},{"ndv":7,"upper":"DB000030601","lower":"DB000030311","count":7,"preSum":112},{"ndv":7,"upper":"DB000030869","lower":"DB000030604","count":7,"preSum":119},{"ndv":7,"upper":"DB000032773","lower":"DB000031311","count":7,"preSum":126},{"ndv":7,"upper":"DB000032813","lower":"DB000032774","count":7,"preSum":133},{"ndv":7,"upper":"DB000032921","lower":"DB000032885","count":7,"preSum":140},{"ndv":7,"upper":"DB000034108","lower":"DB000032934","count":7,"preSum":147},{"ndv":7,"upper":"DB000035260","lower":"DB000034880","count":7,"preSum":154},{"ndv":7,"upper":"DB000035578","lower":"DB000035261","count":7,"preSum":161},{"ndv":7,"upper":"DB000035909","lower":"DB000035719","count":7,"preSum":168},{"ndv":7,"upper":"DB000036611","lower":"DB000035933","count":7,"preSum":175},{"ndv":7,"upper":"DB000036854","lower":"DB000036613","count":7,"preSum":182},{"ndv":6,"upper":"DB000037072","lower":"DB000036862","count":7,"preSum":189},{"ndv":7,"upper":"DB000037338","lower":"DB000037086","count":7,"preSum":196},{"ndv":7,"upper":"DB000038536","lower":"DB000037574","count":7,"preSum":203},{"ndv":7,"upper":"DB000039923","lower":"DB000038973","count":7,"preSum":210},{"ndv":7,"upper":"DB000041046","lower":"DB000039997","count":7,"preSum":217},{"ndv":7,"upper":"DB000041153","lower":"DB000041061","count":7,"preSum":224},{"ndv":7,"upper":"DB000041952","lower":"DB000041438","count":7,"preSum":231},{"ndv":7,"upper":"DB000042072","lower":"DB000041953","count":7,"preSum":238},{"ndv":7,"upper":"DB000043009","lower":"DB000042073","count":7,"preSum":245},{"ndv":7,"upper":"DB000043511","lower":"DB000043470","count":7,"preSum":252},{"ndv":7,"upper":"DB000043906","lower":"DB000043533","count":7,"preSum":259},{"ndv":7,"upper":"DB000044256","lower":"DB000043942","count":7,"preSum":266},{"ndv":6,"upper":"DB000044881","lower":"DB000044315","count":7,"preSum":273},{"ndv":6,"upper":"DB000045504","lower":"DB000045047","count":7,"preSum":280},{"ndv":7,"upper":"DB000045658","lower":"DB000045505","count":7,"preSum":287},{"ndv":7,"upper":"DB000045826","lower":"DB000045659","count":7,"preSum":294},{"ndv":7,"upper":"DB000045874","lower":"DB000045855","count":7,"preSum":301},{"ndv":7,"upper":"DB000045907","lower":"DB000045882","count":7,"preSum":308},{"ndv":7,"upper":"DB000045988","lower":"DB000045910","count":7,"preSum":315},{"ndv":7,"upper":"DB000046085","lower":"DB000046032","count":7,"preSum":322},{"ndv":7,"upper":"DB000046204","lower":"DB000046090","count":7,"preSum":329},{"ndv":7,"upper":"DB000046246","lower":"DB000046218","count":7,"preSum":336},{"ndv":7,"upper":"DB000046273","lower":"DB000046251","count":7,"preSum":343},{"ndv":7,"upper":"DB000046451","lower":"DB000046274","count":7,"preSum":350},{"ndv":7,"upper":"DB000047019","lower":"DB000046460","count":7,"preSum":357},{"ndv":7,"upper":"DB000047589","lower":"DB000047021","count":7,"preSum":364},{"ndv":7,"upper":"DB000047903","lower":"DB000047597","count":7,"preSum":371},{"ndv":7,"upper":"DB000047982","lower":"DB000047906","count":7,"preSum":378},{"ndv":5,"upper":"DB000048155","lower":"DB000047987","count":5,"preSum":385}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2517],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',97094,0.02436278),('jala_wms_prod','shipment_header','userdef5',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[101],"valueArr":["0"],"type":"String","sampleRate":0.9618625319816094}',99900,0.02436278),('jala_wms_prod','shipment_header','userdef6',2341430,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1489,"upper":"JD23230606524443117;","lower":"JD00230301336668924;","count":1490,"preSum":0},{"ndv":1490,"upper":"JX08230535628531406;","lower":"JD23230611438829907;","count":1490,"preSum":1490},{"ndv":1490,"upper":"JX11230253128035326;","lower":"JX08230535640432008;","count":1490,"preSum":2980},{"ndv":1490,"upper":"JX13230532164408620;","lower":"JX11230253128036326;","count":1490,"preSum":4470},{"ndv":1490,"upper":"JX15230648584268523;","lower":"JX13230532164408720;","count":1490,"preSum":5960},{"ndv":1490,"upper":"JX18230558037649518;","lower":"JX15230648600098627;","count":1490,"preSum":7450},{"ndv":1490,"upper":"JX20230614486258715;","lower":"JX18230558258508122;","count":1490,"preSum":8940},{"ndv":1490,"upper":"JX22230348292134615;","lower":"JX20230614486265915;","count":1490,"preSum":10430},{"ndv":1490,"upper":"JX23230614406567203;","lower":"JX22230348314374519;","count":1490,"preSum":11920},{"ndv":1490,"upper":"OD13230502343893030;","lower":"JX23230614415865704;","count":1490,"preSum":13410},{"ndv":1490,"upper":"OD17230618518949017;","lower":"OD13230503016295818;","count":1490,"preSum":14900},{"ndv":1490,"upper":"SD00230551669984812;","lower":"OD17230619391410902;","count":1490,"preSum":16390},{"ndv":1490,"upper":"SD01230519613057404;","lower":"SD00230551737108116;","count":1490,"preSum":17880},{"ndv":1490,"upper":"SD02230516742477716;","lower":"SD01230519613057504;","count":1490,"preSum":19370},{"ndv":1490,"upper":"SD06230451540019826;","lower":"SD02230516742477816;","count":1490,"preSum":20860},{"ndv":1489,"upper":"SD10230401556784028;","lower":"SD06230451540019926;","count":1490,"preSum":22350},{"ndv":1490,"upper":"SD11230511629326506;","lower":"SD10230401556784228;","count":1490,"preSum":23840},{"ndv":1490,"upper":"SD12230534351439331;","lower":"SD11230511629327206;","count":1490,"preSum":25330},{"ndv":1490,"upper":"SD13230559352186431;","lower":"SD12230534351440131;","count":1490,"preSum":26820},{"ndv":1490,"upper":"SD14230544269481024;","lower":"SD13230559352187331;","count":1490,"preSum":28310},{"ndv":1490,"upper":"SD15230549675150212;","lower":"SD14230544269481524;","count":1490,"preSum":29800},{"ndv":1488,"upper":"SD16230559264237123;","lower":"SD15230549675150912;","count":1490,"preSum":31290},{"ndv":1490,"upper":"SD17230621412997304;","lower":"SD16230559264237523;","count":1490,"preSum":32780},{"ndv":1490,"upper":"SD19230446550966727;SD19230454551230727;","lower":"SD17230621412998004;","count":1490,"preSum":34270},{"ndv":1490,"upper":"SD20230524820596116;","lower":"SD19230446550973627;SD19230446550977927;","count":1490,"preSum":35760},{"ndv":1490,"upper":"SD21230551950362317;","lower":"SD20230525258901522;","count":1490,"preSum":37250},{"ndv":1490,"upper":"SD22230534645053108;","lower":"SD21230551950362517;","count":1490,"preSum":38740},{"ndv":1490,"upper":"SD23230526330134728;","lower":"SD22230534691458614;","count":1490,"preSum":40230},{"ndv":1490,"upper":"SDC1123061499244316;","lower":"SD23230526330134828;","count":1490,"preSum":41720},{"ndv":1490,"upper":"TB00230613550536519;","lower":"SDC1123061499540016;","count":1490,"preSum":43210},{"ndv":1490,"upper":"TB03230653384893802;","lower":"TB00230613550536819;","count":1490,"preSum":44700},{"ndv":1490,"upper":"TB08230401494235519;","lower":"TB03230653602067228;","count":1490,"preSum":46190},{"ndv":1490,"upper":"TB09230504575707801;","lower":"TB08230401540166926;","count":1490,"preSum":47680},{"ndv":1490,"upper":"TB09230540603683803;","lower":"TB09230504601778703;","count":1490,"preSum":49170},{"ndv":1490,"upper":"TB09230552292315727;","lower":"TB09230540603683903;","count":1490,"preSum":50660},{"ndv":1490,"upper":"TB10230404471758716;","lower":"TB09230552292315927;","count":1490,"preSum":52150},{"ndv":1488,"upper":"TB10230513582968302;","lower":"TB10230404471759416;","count":1490,"preSum":53640},{"ndv":1482,"upper":"TB10230529304818427;","lower":"TB10230513582973502;","count":1490,"preSum":55130},{"ndv":1490,"upper":"TB10230543309812327;","lower":"TB10230529304818727;","count":1490,"preSum":56620},{"ndv":1490,"upper":"TB10230558315054127;","lower":"TB10230543309812527;","count":1490,"preSum":58110},{"ndv":1488,"upper":"TB11230457541641426;","lower":"TB10230558315054227;","count":1490,"preSum":59600},{"ndv":1489,"upper":"TB11230640499661716;","lower":"TB11230457541643626;","count":1490,"preSum":61090},{"ndv":1488,"upper":"TB12230537615516004;","lower":"TB11230640499662716;","count":1490,"preSum":62580},{"ndv":1490,"upper":"TB13230443564735029;","lower":"TB12230537615516604;","count":1490,"preSum":64070},{"ndv":1490,"upper":"TB13230637534666618;","lower":"TB13230444441939611;","count":1490,"preSum":65560},{"ndv":1490,"upper":"TB14230613389239002;","lower":"TB13230637534668718;","count":1490,"preSum":67050},{"ndv":1489,"upper":"TB15230552681692013;","lower":"TB14230613389247102;","count":1490,"preSum":68540},{"ndv":1489,"upper":"TB16230527336811029;","lower":"TB15230552681692713;","count":1490,"preSum":70030},{"ndv":1490,"upper":"TB17230437566044029;","lower":"TB16230527336812029;","count":1490,"preSum":71520},{"ndv":1490,"upper":"TB18230404502877220;","lower":"TB17230437566044629;","count":1490,"preSum":73010},{"ndv":1489,"upper":"TB19230404481786217;","lower":"TB18230404537345425;","count":1490,"preSum":74500},{"ndv":1490,"upper":"TB19230652520499517;","lower":"TB19230404503115720;","count":1490,"preSum":75990},{"ndv":1490,"upper":"TB20230522356683731;","lower":"TB19230652520499717;","count":1490,"preSum":77480},{"ndv":1490,"upper":"TB20230610520751117;","lower":"TB20230522356696131;","count":1490,"preSum":78970},{"ndv":1490,"upper":"TB21230349313925419;","lower":"TB20230610520752617;","count":1490,"preSum":80460},{"ndv":1490,"upper":"TB21230526826277316;","lower":"TB21230349313929719;","count":1490,"preSum":81950},{"ndv":1490,"upper":"TB21230601444155008;","lower":"TB21230526826278016;","count":1490,"preSum":83440},{"ndv":1490,"upper":"TB21230655522683717;","lower":"TB21230601444155408;","count":1490,"preSum":84930},{"ndv":1490,"upper":"TB22230514593565202;","lower":"TB21230655522685017;","count":1490,"preSum":86420},{"ndv":1488,"upper":"TB22230555272022624;","lower":"TB22230514593566702;","count":1490,"preSum":87910},{"ndv":1490,"upper":"TB22230640394940102;","lower":"TB22230555277509125;","count":1490,"preSum":89400},{"ndv":1490,"upper":"TB23230515612101603;","lower":"TB22230640394940202;","count":1490,"preSum":90890},{"ndv":1489,"upper":"TB23230613593843025;","lower":"TB23230515612101903;","count":1490,"preSum":92380},{"ndv":1450,"upper":"TBC2023030243636108;","lower":"TB23230614395426202;","count":1450,"preSum":93870}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,4681,0.02436278),('jala_wms_prod','shipment_header','userdef7',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[79],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99922,0.02436278),('jala_wms_prod','shipment_header','userdef8',35,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"763DCA","lower":"763DCA","count":1,"preSum":0},{"ndv":1,"upper":"BD02","lower":"BD02","count":2,"preSum":1},{"ndv":1,"upper":"D005","lower":"D005","count":1,"preSum":3},{"ndv":1,"upper":"D008","lower":"D008","count":1,"preSum":4}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[5,549,8875,18765,253,52268,16649,314,177,139,381,40],"valueArr":["","021DC1","022DC","027DC","028DC","573DC","763DC","D001","D002","D003","D011","W007"],"type":"String","sampleRate":0.9618625319816094}',1581,0.02436278),('jala_wms_prod','shipment_header','version',147,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":12,"lower":12,"count":2,"preSum":0},{"ndv":1,"upper":14,"lower":14,"count":1,"preSum":2},{"ndv":1,"upper":15,"lower":15,"count":1,"preSum":3},{"ndv":1,"upper":17,"lower":17,"count":2,"preSum":4},{"ndv":1,"upper":21,"lower":21,"count":1,"preSum":6},{"ndv":1,"upper":24,"lower":24,"count":2,"preSum":7},{"ndv":1,"upper":25,"lower":25,"count":2,"preSum":9},{"ndv":1,"upper":27,"lower":27,"count":1,"preSum":11},{"ndv":1,"upper":28,"lower":28,"count":1,"preSum":12},{"ndv":1,"upper":29,"lower":29,"count":1,"preSum":13},{"ndv":1,"upper":32,"lower":32,"count":1,"preSum":14},{"ndv":1,"upper":37,"lower":37,"count":1,"preSum":15},{"ndv":1,"upper":44,"lower":44,"count":1,"preSum":16},{"ndv":1,"upper":55,"lower":55,"count":1,"preSum":17},{"ndv":1,"upper":69,"lower":69,"count":1,"preSum":18},{"ndv":1,"upper":100,"lower":100,"count":1,"preSum":19},{"ndv":1,"upper":127,"lower":127,"count":1,"preSum":20},{"ndv":1,"upper":136,"lower":136,"count":1,"preSum":21},{"ndv":1,"upper":173,"lower":173,"count":1,"preSum":22},{"ndv":1,"upper":207,"lower":207,"count":1,"preSum":23}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[645,33487,62342,2657,331,149,149,76,45,23,16,41,8,8],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,13,22],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','vipshopcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','warehousecode',16,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"763DCA","lower":"763DCA","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[549,8875,18765,253,52268,16649,471,1968,100,102],"valueArr":["021DC1","022DC","027DC","028DC","573DC","763DC","SH01","SH02","SH03","TEST01"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','warehousetransfercode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[24],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99977,0.02436278),('jala_wms_prod','shipment_header','warehousetransferid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','waveid',186631,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":860,"upper":558951,"lower":676,"count":1448,"preSum":0},{"ndv":779,"upper":587542,"lower":558952,"count":1448,"preSum":1448},{"ndv":820,"upper":648153,"lower":587564,"count":1448,"preSum":2896},{"ndv":835,"upper":702992,"lower":648204,"count":1448,"preSum":4344},{"ndv":749,"upper":728329,"lower":702993,"count":1448,"preSum":5792},{"ndv":751,"upper":747100,"lower":728331,"count":1449,"preSum":7240},{"ndv":484,"upper":755745,"lower":747102,"count":1450,"preSum":8689},{"ndv":552,"upper":767379,"lower":755746,"count":1448,"preSum":10139},{"ndv":588,"upper":778429,"lower":767380,"count":1449,"preSum":11587},{"ndv":494,"upper":789617,"lower":778468,"count":1448,"preSum":13036},{"ndv":620,"upper":799796,"lower":789618,"count":1450,"preSum":14484},{"ndv":537,"upper":809391,"lower":799800,"count":1448,"preSum":15934},{"ndv":596,"upper":818659,"lower":809428,"count":1448,"preSum":17382},{"ndv":370,"upper":821497,"lower":818662,"count":1449,"preSum":18830},{"ndv":447,"upper":825177,"lower":821513,"count":1449,"preSum":20279},{"ndv":507,"upper":831213,"lower":825178,"count":1448,"preSum":21728},{"ndv":546,"upper":844777,"lower":831218,"count":1449,"preSum":23176},{"ndv":501,"upper":857728,"lower":844791,"count":1478,"preSum":24625},{"ndv":516,"upper":872247,"lower":858226,"count":1448,"preSum":26103},{"ndv":489,"upper":883376,"lower":872249,"count":1467,"preSum":27551},{"ndv":559,"upper":895087,"lower":883377,"count":1470,"preSum":29018},{"ndv":538,"upper":907398,"lower":895088,"count":1457,"preSum":30488},{"ndv":565,"upper":919941,"lower":907399,"count":1448,"preSum":31945},{"ndv":514,"upper":929460,"lower":919942,"count":1454,"preSum":33393},{"ndv":507,"upper":936560,"lower":929470,"count":1450,"preSum":34847},{"ndv":638,"upper":950704,"lower":936562,"count":1468,"preSum":36297},{"ndv":520,"upper":960112,"lower":950706,"count":1453,"preSum":37765},{"ndv":544,"upper":974604,"lower":960113,"count":1448,"preSum":39218},{"ndv":660,"upper":989256,"lower":974607,"count":1448,"preSum":40666},{"ndv":568,"upper":1002435,"lower":989257,"count":1452,"preSum":42114},{"ndv":487,"upper":1014725,"lower":1002452,"count":1453,"preSum":43566},{"ndv":517,"upper":1023671,"lower":1014726,"count":1449,"preSum":45019},{"ndv":441,"upper":1030879,"lower":1023672,"count":1448,"preSum":46468},{"ndv":440,"upper":1037143,"lower":1030882,"count":1450,"preSum":47916},{"ndv":459,"upper":1042284,"lower":1037167,"count":1451,"preSum":49366},{"ndv":359,"upper":1043858,"lower":1042285,"count":1450,"preSum":50817},{"ndv":488,"upper":1047101,"lower":1043861,"count":1458,"preSum":52267},{"ndv":281,"upper":1048815,"lower":1047102,"count":1468,"preSum":53725},{"ndv":327,"upper":1051032,"lower":1048816,"count":1449,"preSum":55193},{"ndv":298,"upper":1052299,"lower":1051033,"count":1449,"preSum":56642},{"ndv":529,"upper":1056090,"lower":1052302,"count":1450,"preSum":58091},{"ndv":711,"upper":1060484,"lower":1056091,"count":1448,"preSum":59541},{"ndv":540,"upper":1065790,"lower":1060485,"count":1451,"preSum":60989},{"ndv":587,"upper":1073877,"lower":1065791,"count":1465,"preSum":62440},{"ndv":650,"upper":1089232,"lower":1073886,"count":1448,"preSum":63905},{"ndv":508,"upper":1100582,"lower":1089288,"count":1448,"preSum":65353},{"ndv":590,"upper":1117213,"lower":1100590,"count":1453,"preSum":66801},{"ndv":554,"upper":1132813,"lower":1117218,"count":1448,"preSum":68254},{"ndv":539,"upper":1147057,"lower":1132867,"count":1468,"preSum":69702},{"ndv":617,"upper":1162029,"lower":1147098,"count":1449,"preSum":71170},{"ndv":603,"upper":1171508,"lower":1162030,"count":1449,"preSum":72619},{"ndv":569,"upper":1184419,"lower":1171519,"count":1449,"preSum":74068},{"ndv":598,"upper":1188402,"lower":1184421,"count":1454,"preSum":75517},{"ndv":682,"upper":1194229,"lower":1188416,"count":1449,"preSum":76971},{"ndv":507,"upper":1198132,"lower":1194239,"count":1459,"preSum":78420},{"ndv":643,"upper":1203173,"lower":1198133,"count":1449,"preSum":79879},{"ndv":606,"upper":1209219,"lower":1203175,"count":1450,"preSum":81328},{"ndv":654,"upper":1213184,"lower":1209220,"count":1461,"preSum":82778},{"ndv":542,"upper":1217689,"lower":1213185,"count":1455,"preSum":84239},{"ndv":490,"upper":1223121,"lower":1217690,"count":1449,"preSum":85694},{"ndv":544,"upper":1236281,"lower":1223122,"count":1450,"preSum":87143},{"ndv":551,"upper":1266450,"lower":1236282,"count":1448,"preSum":88593},{"ndv":565,"upper":1286753,"lower":1266451,"count":1449,"preSum":90041},{"ndv":543,"upper":1303781,"lower":1286754,"count":1181,"preSum":91490}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6503,59,54,65,61,55,67,65,92,62,64,57,57,69],"valueArr":[0,767248,775305,827927,878945,889087,929365,1038461,1044344,1074488,1197226,1204888,1213220,1299931],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','zxqty',1339,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":7,"lower":7,"count":13,"preSum":0},{"ndv":1,"upper":13,"lower":13,"count":10,"preSum":13},{"ndv":1,"upper":15,"lower":15,"count":12,"preSum":23},{"ndv":1,"upper":16,"lower":16,"count":12,"preSum":35},{"ndv":1,"upper":17,"lower":17,"count":10,"preSum":47},{"ndv":1,"upper":18,"lower":18,"count":11,"preSum":57},{"ndv":1,"upper":19,"lower":19,"count":8,"preSum":68},{"ndv":2,"upper":22,"lower":21,"count":8,"preSum":76},{"ndv":2,"upper":24,"lower":23,"count":11,"preSum":84},{"ndv":1,"upper":25,"lower":25,"count":8,"preSum":95},{"ndv":2,"upper":27,"lower":26,"count":8,"preSum":103},{"ndv":2,"upper":30,"lower":28,"count":11,"preSum":111},{"ndv":3,"upper":33,"lower":31,"count":8,"preSum":122},{"ndv":3,"upper":36,"lower":34,"count":10,"preSum":130},{"ndv":3,"upper":39,"lower":37,"count":8,"preSum":140},{"ndv":4,"upper":45,"lower":40,"count":11,"preSum":148},{"ndv":4,"upper":49,"lower":46,"count":11,"preSum":159},{"ndv":1,"upper":50,"lower":50,"count":7,"preSum":170},{"ndv":2,"upper":52,"lower":51,"count":8,"preSum":177},{"ndv":2,"upper":55,"lower":54,"count":7,"preSum":185},{"ndv":3,"upper":58,"lower":56,"count":9,"preSum":192},{"ndv":3,"upper":61,"lower":59,"count":7,"preSum":201},{"ndv":2,"upper":63,"lower":62,"count":9,"preSum":208},{"ndv":3,"upper":67,"lower":65,"count":9,"preSum":217},{"ndv":3,"upper":71,"lower":68,"count":7,"preSum":226},{"ndv":3,"upper":75,"lower":72,"count":7,"preSum":233},{"ndv":5,"upper":80,"lower":76,"count":8,"preSum":240},{"ndv":5,"upper":87,"lower":82,"count":8,"preSum":248},{"ndv":4,"upper":91,"lower":88,"count":7,"preSum":256},{"ndv":6,"upper":97,"lower":92,"count":7,"preSum":263},{"ndv":4,"upper":102,"lower":98,"count":7,"preSum":270},{"ndv":4,"upper":110,"lower":103,"count":7,"preSum":277},{"ndv":4,"upper":118,"lower":114,"count":7,"preSum":284},{"ndv":6,"upper":129,"lower":120,"count":7,"preSum":291},{"ndv":6,"upper":147,"lower":131,"count":7,"preSum":298},{"ndv":6,"upper":160,"lower":148,"count":9,"preSum":305},{"ndv":6,"upper":173,"lower":161,"count":7,"preSum":314},{"ndv":5,"upper":185,"lower":175,"count":7,"preSum":321},{"ndv":6,"upper":204,"lower":188,"count":7,"preSum":328},{"ndv":7,"upper":227,"lower":208,"count":7,"preSum":335},{"ndv":5,"upper":250,"lower":235,"count":7,"preSum":342},{"ndv":7,"upper":275,"lower":257,"count":7,"preSum":349},{"ndv":7,"upper":347,"lower":276,"count":7,"preSum":356},{"ndv":5,"upper":370,"lower":348,"count":7,"preSum":363},{"ndv":7,"upper":414,"lower":384,"count":7,"preSum":370},{"ndv":7,"upper":479,"lower":420,"count":7,"preSum":377},{"ndv":7,"upper":543,"lower":491,"count":7,"preSum":384},{"ndv":7,"upper":666,"lower":556,"count":7,"preSum":391},{"ndv":7,"upper":849,"lower":699,"count":7,"preSum":398},{"ndv":7,"upper":1163,"lower":861,"count":7,"preSum":405},{"ndv":7,"upper":1818,"lower":1191,"count":7,"preSum":412},{"ndv":7,"upper":2631,"lower":1963,"count":7,"preSum":419},{"ndv":3,"upper":4068,"lower":3008,"count":3,"preSum":426}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[98947,273,86,51,33,39,16,23,16,18,19,15,21,15],"valueArr":[0,1,2,3,4,5,6,8,9,10,11,12,14,20],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipping_container_detail','actualbarcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','agingdate',732,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":88,"upper":"1850269162337730560","lower":"-1","count":999,"preSum":0},{"ndv":21,"upper":"1850357123267952640","lower":"1850271361360986112","count":1103,"preSum":999},{"ndv":31,"upper":"1850434089081896960","lower":"1850359322291208192","count":1129,"preSum":2102},{"ndv":12,"upper":"1850460477360963584","lower":"1850436288105152512","count":1110,"preSum":3231},{"ndv":6,"upper":"1850473671500496896","lower":"1850462676384219136","count":1062,"preSum":4341},{"ndv":8,"upper":"1850493462709796864","lower":"1850475870523752448","count":1032,"preSum":5403},{"ndv":11,"upper":"1850517651965607936","lower":"1850495661733052416","count":996,"preSum":6435},{"ndv":21,"upper":"1850568229500485632","lower":"1850519850988863488","count":1241,"preSum":7431},{"ndv":21,"upper":"1850614408988852224","lower":"1850570428523741184","count":1057,"preSum":8672},{"ndv":21,"upper":"1850733156244652032","lower":"1850616608012107776","count":1326,"preSum":9729},{"ndv":18,"upper":"1850796927919063040","lower":"1850739753314418688","count":1343,"preSum":11055},{"ndv":10,"upper":"1850818918151618560","lower":"1850799126942318592","count":1122,"preSum":12398},{"ndv":3,"upper":"1850825515221385216","lower":"1850821117174874112","count":1133,"preSum":13520},{"ndv":2,"upper":"1850829913267896320","lower":"1850827714244640768","count":1110,"preSum":14653},{"ndv":1,"upper":"1850840908384174080","lower":"1850840908384174080","count":1122,"preSum":15763},{"ndv":3,"upper":"1850847505453940736","lower":"1850843107407429632","count":1187,"preSum":16885},{"ndv":6,"upper":"1850860699593474048","lower":"1850849704477196288","count":1611,"preSum":18072},{"ndv":4,"upper":"1850869495686496256","lower":"1850862898616729600","count":1377,"preSum":19683},{"ndv":3,"upper":"1850876092756262912","lower":"1850871694709751808","count":1273,"preSum":21060},{"ndv":4,"upper":"1850884888849285120","lower":"1850878291779518464","count":1256,"preSum":22333},{"ndv":5,"upper":"1850895883965562880","lower":"1850887087872540672","count":1071,"preSum":23589},{"ndv":4,"upper":"1850904680058585088","lower":"1850898082988818432","count":999,"preSum":24660},{"ndv":2,"upper":"1850911277128351744","lower":"1850906879081840640","count":1461,"preSum":25659},{"ndv":3,"upper":"1850917874198118400","lower":"1850913476151607296","count":1318,"preSum":27120},{"ndv":7,"upper":"1850933267360907264","lower":"1850920073221373952","count":1596,"preSum":28438},{"ndv":2,"upper":"1850937665407418368","lower":"1850935466384162816","count":1722,"preSum":30034},{"ndv":2,"upper":"1850944262477185024","lower":"1850939864430673920","count":1383,"preSum":31756},{"ndv":2,"upper":"1850948660523696128","lower":"1850946461500440576","count":2114,"preSum":33139},{"ndv":2,"upper":"1850959655639973888","lower":"1850950859546951680","count":1975,"preSum":35253},{"ndv":1,"upper":"1850961854663229440","lower":"1850961854663229440","count":1314,"preSum":37228},{"ndv":1,"upper":"1850964053686484992","lower":"1850964053686484992","count":1103,"preSum":38542},{"ndv":2,"upper":"1850968451732996096","lower":"1850966252709740544","count":1240,"preSum":39645},{"ndv":2,"upper":"1850975048802762752","lower":"1850970650756251648","count":1824,"preSum":40885},{"ndv":3,"upper":"1850990441965551616","lower":"1850981645872529408","count":1315,"preSum":42709},{"ndv":3,"upper":"1850997039035318272","lower":"1850992640988807168","count":1783,"preSum":44024},{"ndv":2,"upper":"1851001437081829376","lower":"1850999238058573824","count":1596,"preSum":45807},{"ndv":2,"upper":"1851010233174851584","lower":"1851005835128340480","count":1807,"preSum":47403},{"ndv":2,"upper":"1851016830244618240","lower":"1851012432198107136","count":1906,"preSum":49210},{"ndv":1,"upper":"1851019029267873792","lower":"1851019029267873792","count":1333,"preSum":51116},{"ndv":1,"upper":"1851027825360896000","lower":"1851027825360896000","count":1295,"preSum":52449},{"ndv":2,"upper":"1851034422430662656","lower":"1851032223407407104","count":1294,"preSum":53744},{"ndv":2,"upper":"1851038820477173760","lower":"1851036621453918208","count":1351,"preSum":55038},{"ndv":1,"upper":"1851041019500429312","lower":"1851041019500429312","count":1011,"preSum":56389},{"ndv":3,"upper":"1851047616570195968","lower":"1851043218523684864","count":1394,"preSum":57400},{"ndv":2,"upper":"1851054213639962624","lower":"1851052014616707072","count":1064,"preSum":58794},{"ndv":2,"upper":"1851058611686473728","lower":"1851056412663218176","count":1178,"preSum":59858},{"ndv":3,"upper":"1851065208756240384","lower":"1851060810709729280","count":1009,"preSum":61036},{"ndv":5,"upper":"1851076203872518144","lower":"1851067407779495936","count":1005,"preSum":62045},{"ndv":3,"upper":"1851082800942284800","lower":"1851078402895773696","count":327,"preSum":63050}],"maxBucketSize":64,"type":"Date","sampleRate":1.0}','{"countArr":[1580,2675,1491,1534,1528,1659,1471,2684,1572,1782,1962,3140,1548,2610],"valueArr":[1850942063453929472,1850953058570207232,1850955257593462784,1850957456616718336,1850972849779507200,1850986043919040512,1850988242942296064,1851003636105084928,1851008034151596032,1851014631221362688,1851021228291129344,1851023427314384896,1851025626337640448,1851030024384151552],"type":"Date","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','attribute1',53,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"分仓退回","lower":"分仓退回","count":1,"preSum":0},{"ndv":1,"upper":"医药渠道","lower":"医药渠道","count":1,"preSum":1},{"ndv":1,"upper":"破损退回","lower":"破损退回","count":1,"preSum":2}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[484,3172,13,40,49,5,4,6,541,55,14],"valueArr":["(空白)","0","W028调入","分仓","商超渠道","大客户渠道","总仓","本地零售渠道","电商渠道","美妆渠道","货架渠道"],"type":"String","sampleRate":1.0}',86227,0.007226729),('jala_wms_prod','shipping_container_detail','attribute2',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','attribute3',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','attribute4',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','attribute5',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','attribute6',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','attribute7',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','attribute8',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','attributeid',116861,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":930,"upper":27295,"lower":1542,"count":1379,"preSum":0},{"ndv":825,"upper":61910,"lower":27298,"count":1379,"preSum":1379},{"ndv":852,"upper":116024,"lower":61930,"count":1379,"preSum":2758},{"ndv":430,"upper":125404,"lower":116031,"count":1384,"preSum":4137},{"ndv":238,"upper":126254,"lower":125412,"count":1379,"preSum":5521},{"ndv":339,"upper":133051,"lower":126257,"count":1387,"preSum":6900},{"ndv":426,"upper":143722,"lower":133053,"count":1380,"preSum":8287},{"ndv":477,"upper":156328,"lower":143724,"count":1379,"preSum":9667},{"ndv":589,"upper":165785,"lower":156329,"count":1384,"preSum":11046},{"ndv":374,"upper":168340,"lower":165787,"count":1380,"preSum":12430},{"ndv":190,"upper":169008,"lower":168341,"count":1385,"preSum":13810},{"ndv":253,"upper":172261,"lower":169013,"count":1386,"preSum":15195},{"ndv":538,"upper":177947,"lower":172262,"count":1449,"preSum":16581},{"ndv":381,"upper":181260,"lower":177949,"count":1389,"preSum":18030},{"ndv":154,"upper":182495,"lower":181271,"count":1382,"preSum":19419},{"ndv":162,"upper":183231,"lower":182496,"count":1379,"preSum":20801},{"ndv":125,"upper":183726,"lower":183233,"count":1379,"preSum":22180},{"ndv":166,"upper":184359,"lower":183778,"count":1401,"preSum":23559},{"ndv":169,"upper":185048,"lower":184361,"count":1382,"preSum":24960},{"ndv":219,"upper":187184,"lower":185049,"count":1379,"preSum":26342},{"ndv":251,"upper":188597,"lower":187186,"count":1383,"preSum":27721},{"ndv":146,"upper":189832,"lower":188606,"count":1381,"preSum":29104},{"ndv":92,"upper":189975,"lower":189833,"count":1406,"preSum":30485},{"ndv":90,"upper":190134,"lower":189976,"count":1381,"preSum":31891},{"ndv":88,"upper":190312,"lower":190135,"count":1381,"preSum":33272},{"ndv":89,"upper":190440,"lower":190313,"count":1386,"preSum":34653},{"ndv":182,"upper":191516,"lower":190441,"count":1384,"preSum":36039},{"ndv":286,"upper":192853,"lower":191517,"count":1423,"preSum":37423},{"ndv":212,"upper":194254,"lower":192854,"count":1441,"preSum":38846},{"ndv":169,"upper":195743,"lower":194256,"count":1387,"preSum":40287},{"ndv":506,"upper":200223,"lower":195748,"count":1393,"preSum":41674},{"ndv":179,"upper":202096,"lower":200225,"count":1383,"preSum":43067},{"ndv":244,"upper":204030,"lower":202104,"count":1388,"preSum":44450},{"ndv":316,"upper":207067,"lower":204043,"count":1383,"preSum":45838},{"ndv":222,"upper":210136,"lower":207069,"count":1422,"preSum":47221},{"ndv":143,"upper":210958,"lower":210137,"count":1380,"preSum":48643},{"ndv":213,"upper":302487,"lower":210959,"count":1379,"preSum":50023},{"ndv":133,"upper":303752,"lower":302495,"count":1404,"preSum":51402},{"ndv":107,"upper":304984,"lower":303753,"count":1381,"preSum":52806},{"ndv":277,"upper":404340,"lower":304987,"count":1433,"preSum":54187},{"ndv":235,"upper":406844,"lower":404341,"count":1381,"preSum":55620},{"ndv":145,"upper":407639,"lower":406847,"count":1383,"preSum":57001},{"ndv":131,"upper":408551,"lower":407640,"count":1435,"preSum":58384},{"ndv":148,"upper":409667,"lower":408553,"count":1389,"preSum":59819},{"ndv":206,"upper":411362,"lower":409668,"count":1380,"preSum":61208},{"ndv":173,"upper":413540,"lower":411363,"count":1379,"preSum":62588},{"ndv":200,"upper":415764,"lower":413541,"count":1419,"preSum":63967},{"ndv":168,"upper":416749,"lower":415766,"count":1409,"preSum":65386},{"ndv":232,"upper":418644,"lower":416760,"count":1390,"preSum":66795},{"ndv":186,"upper":419880,"lower":418646,"count":1414,"preSum":68185},{"ndv":97,"upper":420610,"lower":419881,"count":1417,"preSum":69599},{"ndv":277,"upper":421722,"lower":420612,"count":1395,"preSum":71016},{"ndv":107,"upper":422713,"lower":421723,"count":1397,"preSum":72411},{"ndv":203,"upper":424378,"lower":422753,"count":1403,"preSum":73808},{"ndv":166,"upper":425937,"lower":424382,"count":1413,"preSum":75211},{"ndv":124,"upper":426717,"lower":425942,"count":1427,"preSum":76624},{"ndv":241,"upper":429510,"lower":426737,"count":1384,"preSum":78051},{"ndv":269,"upper":432925,"lower":429512,"count":1379,"preSum":79435},{"ndv":126,"upper":433766,"lower":432942,"count":1385,"preSum":80814},{"ndv":207,"upper":437635,"lower":433767,"count":1394,"preSum":82199},{"ndv":178,"upper":440768,"lower":437636,"count":1444,"preSum":83593},{"ndv":225,"upper":445251,"lower":440772,"count":1459,"preSum":85037},{"ndv":321,"upper":453267,"lower":445253,"count":1383,"preSum":86496},{"ndv":89,"upper":456727,"lower":453362,"count":329,"preSum":87879}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[158,184,177,169,165,145,176,164,142,142,144,152,344,143],"valueArr":[182267,188250,189786,206517,206534,303733,303734,401917,411714,415956,420342,420609,421718,422354],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','batch',22648,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":119,"upper":"113F11671","lower":"01208","count":1354,"preSum":0},{"ndv":66,"upper":"123E41491","lower":"113F20831","count":1396,"preSum":1354},{"ndv":113,"upper":"172E42491","lower":"123E42271","count":1371,"preSum":2750},{"ndv":112,"upper":"173E34001","lower":"172E44881","count":1325,"preSum":4121},{"ndv":29,"upper":"173F11552","lower":"173E40421","count":1346,"preSum":5446},{"ndv":148,"upper":"182F25011","lower":"173F11591","count":1334,"preSum":6792},{"ndv":90,"upper":"183F20402","lower":"182F25201","count":1327,"preSum":8126},{"ndv":203,"upper":"193CS0021","lower":"183F20461","count":1329,"preSum":9453},{"ndv":55,"upper":"193F21152","lower":"193CS0041","count":1343,"preSum":10782},{"ndv":165,"upper":"20260409","lower":"193F21161","count":1329,"preSum":12125},{"ndv":142,"upper":"24N10","lower":"20260505","count":1326,"preSum":13454},{"ndv":303,"upper":"27L01","lower":"24P06","count":1328,"preSum":14780},{"ndv":202,"upper":"29821","lower":"27L02","count":1327,"preSum":16108},{"ndv":218,"upper":"2XE22","lower":"29824","count":1346,"preSum":17435},{"ndv":119,"upper":"2XR22","lower":"2XE25","count":1343,"preSum":18781},{"ndv":102,"upper":"2Y502","lower":"2XR23","count":1353,"preSum":20124},{"ndv":58,"upper":"2YB21","lower":"2Y506","count":1328,"preSum":21477},{"ndv":70,"upper":"2YK07","lower":"2YB24","count":1328,"preSum":22805},{"ndv":54,"upper":"2YQ05","lower":"2YK08","count":1366,"preSum":24133},{"ndv":79,"upper":"2Z101","lower":"2YQ07","count":1346,"preSum":25499},{"ndv":72,"upper":"2Z908","lower":"2Z102","count":1337,"preSum":26845},{"ndv":68,"upper":"2ZM31","lower":"2Z910","count":1353,"preSum":28182},{"ndv":57,"upper":"31527","lower":"2ZM37","count":1350,"preSum":29535},{"ndv":59,"upper":"31V25","lower":"31604","count":1383,"preSum":30885},{"ndv":117,"upper":"32A06","lower":"31W01","count":1362,"preSum":32268},{"ndv":55,"upper":"32U08","lower":"32A09","count":1359,"preSum":33630},{"ndv":46,"upper":"33705","lower":"32U09","count":1343,"preSum":34989},{"ndv":57,"upper":"33E01","lower":"33706","count":1352,"preSum":36332},{"ndv":39,"upper":"33J04","lower":"33E06","count":1376,"preSum":37684},{"ndv":37,"upper":"33P06","lower":"33J09","count":1361,"preSum":39060},{"ndv":34,"upper":"33S29","lower":"33P07","count":1364,"preSum":40421},{"ndv":48,"upper":"34324","lower":"33S63","count":1487,"preSum":41785},{"ndv":44,"upper":"34902","lower":"343240629","count":1354,"preSum":43272},{"ndv":36,"upper":"34C09","lower":"34903","count":1326,"preSum":44626},{"ndv":44,"upper":"34G25","lower":"34C21","count":1333,"preSum":45952},{"ndv":48,"upper":"34NT1","lower":"34G26","count":1367,"preSum":47285},{"ndv":42,"upper":"34T01","lower":"34P01","count":1396,"preSum":48652},{"ndv":26,"upper":"35201","lower":"34T06","count":1362,"preSum":50048},{"ndv":44,"upper":"35622","lower":"35202","count":1349,"preSum":51410},{"ndv":43,"upper":"35C06","lower":"35637","count":1428,"preSum":52759},{"ndv":43,"upper":"35R20","lower":"35C09","count":1342,"preSum":54187},{"ndv":181,"upper":"552302111","lower":"35S06","count":1328,"preSum":55529},{"ndv":108,"upper":"632301122","lower":"552302112","count":1341,"preSum":56857},{"ndv":144,"upper":"732303031","lower":"632301131","count":1335,"preSum":58198},{"ndv":50,"upper":"732305041","lower":"732303041","count":1384,"preSum":59533},{"ndv":105,"upper":"752212192","lower":"732305042","count":1383,"preSum":60917},{"ndv":71,"upper":"752306023","lower":"752212211","count":1410,"preSum":62300},{"ndv":130,"upper":"772304192","lower":"752306071","count":1355,"preSum":63710},{"ndv":129,"upper":"792212301","lower":"772304193","count":1326,"preSum":65065},{"ndv":56,"upper":"792305261","lower":"792212311","count":1332,"preSum":66391},{"ndv":172,"upper":"CS2991472","lower":"792305271","count":1330,"preSum":67723},{"ndv":143,"upper":"CS2992621","lower":"CS2991492","count":1331,"preSum":69053},{"ndv":69,"upper":"CS3990041","lower":"CS2992622","count":1326,"preSum":70384},{"ndv":55,"upper":"CS3990271","lower":"CS3990042","count":1339,"preSum":71710},{"ndv":151,"upper":"EK2991501","lower":"CS3990273","count":1338,"preSum":73049},{"ndv":89,"upper":"EK2992482","lower":"EK2991511","count":1344,"preSum":74387},{"ndv":109,"upper":"EK2993724","lower":"EK2992491","count":1334,"preSum":75731},{"ndv":45,"upper":"EK3990112","lower":"EK2993742","count":1337,"preSum":77065},{"ndv":33,"upper":"EK3990261","lower":"EK3990113","count":1453,"preSum":78402},{"ndv":28,"upper":"EK3990393","lower":"EK3990262","count":1436,"preSum":79855},{"ndv":106,"upper":"JL3WB0032","lower":"EK3990401","count":1347,"preSum":81291},{"ndv":136,"upper":"P01E29201","lower":"JL3WB0033","count":1428,"preSum":82638},{"ndv":122,"upper":"ZH","lower":"P01E29202","count":686,"preSum":84066}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[327,671,463,780,408,369,769,212,203,200,214,264,641,336],"valueArr":["2208","2210","2211","2212","2302","2303","2304","2YH21","34F08","752304211","772305071","772305091","JALA","N12012"],"type":"String","sampleRate":1.0}',4,0.007226729),('jala_wms_prod','shipping_container_detail','checkingmethod',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','companycode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[10287,1397,78929],"valueArr":["JALA01","JALA02","JALA11"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','containercode',635368,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":685,"upper":"021DC1-45416","lower":"021DC1-0011","count":1410,"preSum":0},{"ndv":681,"upper":"022DC-104264","lower":"021DC1-45420","count":1409,"preSum":1410},{"ndv":946,"upper":"022DC-170367","lower":"022DC-104269","count":1412,"preSum":2819},{"ndv":948,"upper":"022DC-257646","lower":"022DC-170368","count":1409,"preSum":4231},{"ndv":942,"upper":"022DC-320216","lower":"022DC-257647","count":1409,"preSum":5640},{"ndv":1014,"upper":"022DC-77584","lower":"022DC-320217","count":1409,"preSum":7049},{"ndv":957,"upper":"027DC-127724","lower":"022DC-77586","count":1409,"preSum":8458},{"ndv":912,"upper":"027DC-203693","lower":"027DC-128075","count":1409,"preSum":9867},{"ndv":947,"upper":"027DC-280270","lower":"027DC-203694","count":1409,"preSum":11276},{"ndv":964,"upper":"027DC-350617","lower":"027DC-280535","count":1409,"preSum":12685},{"ndv":982,"upper":"027DC-423793","lower":"027DC-350621","count":1409,"preSum":14094},{"ndv":1037,"upper":"027DC-484412","lower":"027DC-423794","count":1409,"preSum":15503},{"ndv":959,"upper":"027DC-564371","lower":"027DC-484413","count":1409,"preSum":16912},{"ndv":992,"upper":"027DC-632138","lower":"027DC-566146","count":1409,"preSum":18321},{"ndv":946,"upper":"027DC-680769","lower":"027DC-632145","count":1409,"preSum":19730},{"ndv":926,"upper":"028DC-24875","lower":"027DC-680771","count":1410,"preSum":21139},{"ndv":855,"upper":"573DC-1022015","lower":"028DC-24902","count":1409,"preSum":22549},{"ndv":846,"upper":"573DC-1075329","lower":"573DC-102305","count":1411,"preSum":23958},{"ndv":777,"upper":"573DC-1130428","lower":"573DC-1075331","count":1411,"preSum":25369},{"ndv":835,"upper":"573DC-1184313","lower":"573DC-1130770","count":1410,"preSum":26780},{"ndv":816,"upper":"573DC-1244282","lower":"573DC-1184486","count":1409,"preSum":28190},{"ndv":830,"upper":"573DC-1309323","lower":"573DC-1244291","count":1409,"preSum":29599},{"ndv":832,"upper":"573DC-1354413","lower":"573DC-1309327","count":1409,"preSum":31008},{"ndv":901,"upper":"573DC-1409140","lower":"573DC-1354415","count":1412,"preSum":32417},{"ndv":938,"upper":"573DC-1473152","lower":"573DC-1409141","count":1409,"preSum":33829},{"ndv":866,"upper":"573DC-1517368","lower":"573DC-1473153","count":1410,"preSum":35238},{"ndv":885,"upper":"573DC-1579063","lower":"573DC-1518085","count":1412,"preSum":36648},{"ndv":926,"upper":"573DC-1634171","lower":"573DC-1579064","count":1409,"preSum":38060},{"ndv":808,"upper":"573DC-1700637","lower":"573DC-1634172","count":1409,"preSum":39469},{"ndv":886,"upper":"573DC-1744367","lower":"573DC-1700638","count":1409,"preSum":40878},{"ndv":842,"upper":"573DC-1794922","lower":"573DC-1744368","count":1409,"preSum":42287},{"ndv":775,"upper":"573DC-1828994","lower":"573DC-1794923","count":1411,"preSum":43696},{"ndv":805,"upper":"573DC-186216","lower":"573DC-1828995","count":1409,"preSum":45107},{"ndv":820,"upper":"573DC-1899988","lower":"573DC-1862232","count":1409,"preSum":46516},{"ndv":926,"upper":"573DC-1954558","lower":"573DC-1899989","count":1409,"preSum":47925},{"ndv":809,"upper":"573DC-218689","lower":"573DC-1954560","count":1409,"preSum":49334},{"ndv":820,"upper":"573DC-267160","lower":"573DC-218691","count":1409,"preSum":50743},{"ndv":797,"upper":"573DC-313801","lower":"573DC-267161","count":1409,"preSum":52152},{"ndv":868,"upper":"573DC-350245","lower":"573DC-313805","count":1413,"preSum":53561},{"ndv":831,"upper":"573DC-408113","lower":"573DC-350246","count":1411,"preSum":54974},{"ndv":733,"upper":"573DC-448411","lower":"573DC-408114","count":1409,"preSum":56385},{"ndv":805,"upper":"573DC-491023","lower":"573DC-448413","count":1409,"preSum":57794},{"ndv":872,"upper":"573DC-550619","lower":"573DC-491025","count":1409,"preSum":59203},{"ndv":792,"upper":"573DC-582719","lower":"573DC-550620","count":1410,"preSum":60612},{"ndv":835,"upper":"573DC-636814","lower":"573DC-582721","count":1410,"preSum":62022},{"ndv":788,"upper":"573DC-686695","lower":"573DC-637323","count":1409,"preSum":63432},{"ndv":742,"upper":"573DC-72838","lower":"573DC-686698","count":1410,"preSum":64841},{"ndv":719,"upper":"573DC-763101","lower":"573DC-72839","count":1409,"preSum":66251},{"ndv":803,"upper":"573DC-813960","lower":"573DC-763105","count":1409,"preSum":67660},{"ndv":828,"upper":"573DC-859694","lower":"573DC-813962","count":1411,"preSum":69069},{"ndv":836,"upper":"573DC-911189","lower":"573DC-859695","count":1410,"preSum":70480},{"ndv":731,"upper":"573DC-960764","lower":"573DC-911190","count":1409,"preSum":71890},{"ndv":704,"upper":"573DC-997353","lower":"573DC-960765","count":1410,"preSum":73299},{"ndv":923,"upper":"763DC-172707","lower":"573DC-997354","count":1409,"preSum":74709},{"ndv":984,"upper":"763DC-25275","lower":"763DC-172711","count":1410,"preSum":76118},{"ndv":933,"upper":"763DC-319824","lower":"763DC-25279","count":1410,"preSum":77528},{"ndv":953,"upper":"763DC-389428","lower":"763DC-319825","count":1409,"preSum":78938},{"ndv":983,"upper":"763DC-441929","lower":"763DC-389429","count":1409,"preSum":80347},{"ndv":946,"upper":"763DC-526742","lower":"763DC-441932","count":1409,"preSum":81756},{"ndv":955,"upper":"763DC-588742","lower":"763DC-526743","count":1409,"preSum":83165},{"ndv":991,"upper":"763DC-652961","lower":"763DC-588743","count":1409,"preSum":84574},{"ndv":874,"upper":"SH01-19162","lower":"763DC-652962","count":1409,"preSum":85983},{"ndv":506,"upper":"SH02-16512","lower":"SH01-19164","count":1415,"preSum":87392},{"ndv":517,"upper":"TEST01-0807","lower":"SH02-16513","count":1329,"preSum":88807}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[23,29,24,23,23,26,29,39,48,53,83,38,39],"valueArr":["SH01-0189","SH01-0194","SH02-0088","SH02-30487","SH03-0020","SH03-0892","SH03-1367","SH03-2031","SH03-2043","SH03-2186","SH03-2354","SH03-2393","SH03-2605"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','containerid',636130,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":641,"upper":1069642,"lower":1017411,"count":1411,"preSum":0},{"ndv":572,"upper":1105452,"lower":1069644,"count":1411,"preSum":1411},{"ndv":790,"upper":1168181,"lower":1105453,"count":1409,"preSum":2822},{"ndv":966,"upper":1225849,"lower":1168190,"count":1410,"preSum":4231},{"ndv":909,"upper":1314495,"lower":1225850,"count":1409,"preSum":5641},{"ndv":823,"upper":1377711,"lower":1314498,"count":1409,"preSum":7050},{"ndv":881,"upper":1450832,"lower":1377715,"count":1409,"preSum":8459},{"ndv":797,"upper":1534380,"lower":1450833,"count":1409,"preSum":9868},{"ndv":686,"upper":1581197,"lower":1534807,"count":1409,"preSum":11277},{"ndv":798,"upper":1636512,"lower":1581198,"count":1409,"preSum":12686},{"ndv":883,"upper":1718734,"lower":1636515,"count":1411,"preSum":14095},{"ndv":882,"upper":1776442,"lower":1718735,"count":1409,"preSum":15506},{"ndv":792,"upper":1828390,"lower":1776499,"count":1410,"preSum":16915},{"ndv":883,"upper":1888747,"lower":1828392,"count":1409,"preSum":18325},{"ndv":902,"upper":2020079,"lower":1888749,"count":1409,"preSum":19734},{"ndv":769,"upper":2068479,"lower":2020080,"count":1410,"preSum":21143},{"ndv":867,"upper":2121373,"lower":2068480,"count":1410,"preSum":22553},{"ndv":918,"upper":2200900,"lower":2121374,"count":1410,"preSum":23963},{"ndv":880,"upper":2262859,"lower":2201626,"count":1411,"preSum":25373},{"ndv":839,"upper":2306295,"lower":2262860,"count":1411,"preSum":26784},{"ndv":822,"upper":2359613,"lower":2306296,"count":1409,"preSum":28195},{"ndv":870,"upper":2472089,"lower":2359617,"count":1409,"preSum":29604},{"ndv":810,"upper":2513411,"lower":2472092,"count":1409,"preSum":31013},{"ndv":852,"upper":2577532,"lower":2513412,"count":1409,"preSum":32422},{"ndv":877,"upper":2634737,"lower":2577535,"count":1410,"preSum":33831},{"ndv":848,"upper":2692964,"lower":2634738,"count":1412,"preSum":35241},{"ndv":800,"upper":2744768,"lower":2693837,"count":1409,"preSum":36653},{"ndv":785,"upper":2791155,"lower":2744770,"count":1410,"preSum":38062},{"ndv":827,"upper":2862484,"lower":2791156,"count":1409,"preSum":39472},{"ndv":858,"upper":2903252,"lower":2862485,"count":1409,"preSum":40881},{"ndv":881,"upper":2960032,"lower":2903254,"count":1410,"preSum":42290},{"ndv":829,"upper":3023610,"lower":2960033,"count":1412,"preSum":43700},{"ndv":818,"upper":3086045,"lower":3023611,"count":1409,"preSum":45112},{"ndv":825,"upper":3130659,"lower":3086046,"count":1412,"preSum":46521},{"ndv":741,"upper":3186902,"lower":3130660,"count":1410,"preSum":47933},{"ndv":880,"upper":3238142,"lower":3186904,"count":1410,"preSum":49343},{"ndv":865,"upper":3296653,"lower":3238143,"count":1409,"preSum":50753},{"ndv":788,"upper":3365939,"lower":3296654,"count":1414,"preSum":52162},{"ndv":1015,"upper":3455641,"lower":3365940,"count":1409,"preSum":53576},{"ndv":854,"upper":3519361,"lower":3455645,"count":1410,"preSum":54985},{"ndv":963,"upper":3574180,"lower":3519362,"count":1409,"preSum":56395},{"ndv":867,"upper":3624960,"lower":3574184,"count":1409,"preSum":57804},{"ndv":910,"upper":3729579,"lower":3624961,"count":1410,"preSum":59213},{"ndv":884,"upper":3796090,"lower":3729580,"count":1409,"preSum":60623},{"ndv":907,"upper":3855502,"lower":3796091,"count":1410,"preSum":62032},{"ndv":844,"upper":3912991,"lower":3855504,"count":1411,"preSum":63442},{"ndv":977,"upper":3997055,"lower":3912992,"count":1410,"preSum":64853},{"ndv":892,"upper":4070357,"lower":3997056,"count":1410,"preSum":66263},{"ndv":976,"upper":4139580,"lower":4070360,"count":1409,"preSum":67673},{"ndv":838,"upper":4199895,"lower":4139581,"count":1409,"preSum":69082},{"ndv":947,"upper":4254586,"lower":4199896,"count":1409,"preSum":70491},{"ndv":914,"upper":4325896,"lower":4254587,"count":1411,"preSum":71900},{"ndv":952,"upper":4396127,"lower":4325899,"count":1409,"preSum":73311},{"ndv":830,"upper":4464014,"lower":4396128,"count":1410,"preSum":74720},{"ndv":905,"upper":4538396,"lower":4464410,"count":1410,"preSum":76130},{"ndv":898,"upper":4594740,"lower":4538397,"count":1409,"preSum":77540},{"ndv":895,"upper":4651540,"lower":4594750,"count":1409,"preSum":78949},{"ndv":847,"upper":4695984,"lower":4651541,"count":1409,"preSum":80358},{"ndv":837,"upper":4735855,"lower":4696035,"count":1409,"preSum":81767},{"ndv":887,"upper":4788072,"lower":4735862,"count":1410,"preSum":83176},{"ndv":884,"upper":4841884,"lower":4788073,"count":1409,"preSum":84586},{"ndv":943,"upper":4897450,"lower":4841887,"count":1409,"preSum":85995},{"ndv":930,"upper":4969475,"lower":4897451,"count":1409,"preSum":87404},{"ndv":835,"upper":5026088,"lower":4969478,"count":1323,"preSum":88813}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[23,29,24,23,26,29,39,48,53,23,83,38,39],"valueArr":[1017420,1017437,1017444,1017726,1084713,1106993,1330122,1337341,1625204,2850546,2936847,3184115,4929438],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','convertedqty',5010,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":0,"lower":0,"count":45,"preSum":0},{"ndv":1,"upper":11,"lower":11,"count":72,"preSum":45},{"ndv":1,"upper":13,"lower":13,"count":49,"preSum":117},{"ndv":1,"upper":14,"lower":14,"count":57,"preSum":166},{"ndv":1,"upper":15,"lower":15,"count":79,"preSum":223},{"ndv":1,"upper":16,"lower":16,"count":64,"preSum":302},{"ndv":1,"upper":17,"lower":17,"count":44,"preSum":366},{"ndv":2,"upper":20,"lower":19,"count":96,"preSum":410},{"ndv":1,"upper":21,"lower":21,"count":35,"preSum":506},{"ndv":2,"upper":23,"lower":22,"count":50,"preSum":541},{"ndv":1,"upper":25,"lower":25,"count":36,"preSum":591},{"ndv":3,"upper":28,"lower":26,"count":41,"preSum":627},{"ndv":3,"upper":32,"lower":29,"count":45,"preSum":668},{"ndv":3,"upper":35,"lower":33,"count":50,"preSum":713},{"ndv":1,"upper":36,"lower":36,"count":60,"preSum":763},{"ndv":4,"upper":40,"lower":37,"count":57,"preSum":823},{"ndv":2,"upper":42,"lower":41,"count":69,"preSum":880},{"ndv":5,"upper":47,"lower":43,"count":41,"preSum":949},{"ndv":1,"upper":48,"lower":48,"count":50,"preSum":990},{"ndv":3,"upper":51,"lower":49,"count":36,"preSum":1040},{"ndv":6,"upper":57,"lower":52,"count":35,"preSum":1076},{"ndv":5,"upper":62,"lower":58,"count":38,"preSum":1111},{"ndv":7,"upper":69,"lower":63,"count":35,"preSum":1149},{"ndv":5,"upper":74,"lower":70,"count":35,"preSum":1184},{"ndv":6,"upper":80,"lower":75,"count":44,"preSum":1219},{"ndv":11,"upper":95,"lower":81,"count":35,"preSum":1263},{"ndv":3,"upper":100,"lower":96,"count":59,"preSum":1298},{"ndv":15,"upper":121,"lower":101,"count":34,"preSum":1357},{"ndv":12,"upper":144,"lower":126,"count":35,"preSum":1391},{"ndv":13,"upper":170,"lower":145,"count":35,"preSum":1426},{"ndv":8,"upper":192,"lower":176,"count":37,"preSum":1461},{"ndv":18,"upper":224,"lower":194,"count":34,"preSum":1498},{"ndv":7,"upper":252,"lower":230,"count":34,"preSum":1532},{"ndv":13,"upper":311,"lower":263,"count":34,"preSum":1566},{"ndv":20,"upper":390,"lower":312,"count":34,"preSum":1600},{"ndv":23,"upper":466,"lower":394,"count":34,"preSum":1634},{"ndv":15,"upper":531,"lower":471,"count":34,"preSum":1668},{"ndv":16,"upper":600,"lower":534,"count":36,"preSum":1702},{"ndv":22,"upper":750,"lower":605,"count":34,"preSum":1738},{"ndv":27,"upper":960,"lower":761,"count":37,"preSum":1772},{"ndv":8,"upper":1008,"lower":972,"count":35,"preSum":1809},{"ndv":17,"upper":1152,"lower":1011,"count":45,"preSum":1844},{"ndv":20,"upper":1364,"lower":1184,"count":34,"preSum":1889},{"ndv":26,"upper":1728,"lower":1388,"count":38,"preSum":1923},{"ndv":12,"upper":2016,"lower":1736,"count":35,"preSum":1961},{"ndv":11,"upper":2352,"lower":2064,"count":55,"preSum":1996},{"ndv":20,"upper":3840,"lower":2400,"count":38,"preSum":2051},{"ndv":29,"upper":10080,"lower":4032,"count":36,"preSum":2089},{"ndv":9,"upper":20160,"lower":10200,"count":15,"preSum":2125}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[56468,17746,3087,5718,1458,1698,296,413,147,592,493,110,162,85],"valueArr":[1,2,3,4,5,6,7,8,9,10,12,18,24,30],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','convertedqtyum',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"PL","lower":"PL","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[2098,79076,9437],"valueArr":["CS","EA","MP"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','created',29265,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":284,"upper":"1850483145829253120","lower":"1850357916578611200","count":1401,"preSum":0},{"ndv":220,"upper":"1850710012192620544","lower":"1850483727646326784","count":1415,"preSum":1401},{"ndv":219,"upper":"1850828658130812928","lower":"1850712266496802816","count":1425,"preSum":2816},{"ndv":137,"upper":"1850854731182768128","lower":"1850828915392643072","count":1393,"preSum":4241},{"ndv":186,"upper":"1850887995788361728","lower":"1850854738799624192","count":1408,"preSum":5634},{"ndv":235,"upper":"1850925220840341504","lower":"1850888012867567616","count":1407,"preSum":7042},{"ndv":161,"upper":"1850942649263980544","lower":"1850925356769345536","count":1401,"preSum":8449},{"ndv":161,"upper":"1850953834231234560","lower":"1850942654431363072","count":1410,"preSum":9850},{"ndv":86,"upper":"1850958152753741824","lower":"1850953851478212608","count":1408,"preSum":11260},{"ndv":84,"upper":"1850962421917679616","lower":"1850958157317144576","count":1398,"preSum":12668},{"ndv":107,"upper":"1850965169472012288","lower":"1850962438325796864","count":1396,"preSum":14066},{"ndv":160,"upper":"1850969261250445312","lower":"1850965187792732160","count":1396,"preSum":15462},{"ndv":132,"upper":"1850971527516782592","lower":"1850969261334331392","count":1423,"preSum":16858},{"ndv":123,"upper":"1850973622873620480","lower":"1850971545887834112","count":1406,"preSum":18281},{"ndv":155,"upper":"1850982255623667712","lower":"1850973631698436096","count":1408,"preSum":19687},{"ndv":73,"upper":"1850984439044112384","lower":"1850982258089918464","count":1392,"preSum":21095},{"ndv":74,"upper":"1850986648670568448","lower":"1850984449966080000","count":1409,"preSum":22487},{"ndv":64,"upper":"1850986987452891136","lower":"1850986648687345664","count":1421,"preSum":23896},{"ndv":65,"upper":"1850988805599789056","lower":"1850986998995615744","count":1407,"preSum":25317},{"ndv":71,"upper":"1850989217899872256","lower":"1850988805616566272","count":1417,"preSum":26724},{"ndv":84,"upper":"1850991500674990080","lower":"1850989217916649472","count":1407,"preSum":28141},{"ndv":108,"upper":"1850995450149076992","lower":"1850991501178306560","count":1395,"preSum":29548},{"ndv":92,"upper":"1850997758459117568","lower":"1850995478267691008","count":1398,"preSum":30943},{"ndv":97,"upper":"1851000440213209088","lower":"1850997779564855296","count":1399,"preSum":32341},{"ndv":109,"upper":"1851004138532372480","lower":"1851000462157807616","count":1407,"preSum":33740},{"ndv":99,"upper":"1851006528396460032","lower":"1851004216881971200","count":1394,"preSum":35147},{"ndv":93,"upper":"1851008790166503424","lower":"1851006537842032640","count":1402,"preSum":36541},{"ndv":98,"upper":"1851011129262735360","lower":"1851008793622609920","count":1398,"preSum":37943},{"ndv":154,"upper":"1851015189567111168","lower":"1851011160954896384","count":1400,"preSum":39341},{"ndv":102,"upper":"1851016150297608192","lower":"1851015216645537792","count":1396,"preSum":40741},{"ndv":85,"upper":"1851017833891233792","lower":"1851016150649929728","count":1393,"preSum":42137},{"ndv":99,"upper":"1851020153223905280","lower":"1851017833908011008","count":1406,"preSum":43530},{"ndv":155,"upper":"1851024133417074688","lower":"1851020153257459712","count":1451,"preSum":44936},{"ndv":83,"upper":"1851026301150822400","lower":"1851024134440484864","count":1414,"preSum":46387},{"ndv":65,"upper":"1851028554851024896","lower":"1851026303549964288","count":1396,"preSum":47801},{"ndv":102,"upper":"1851030977028030464","lower":"1851028554968465408","count":1393,"preSum":49197},{"ndv":131,"upper":"1851034929538793472","lower":"1851030980970676224","count":1414,"preSum":50590},{"ndv":112,"upper":"1851037678418526208","lower":"1851034932256702464","count":1397,"preSum":52004},{"ndv":94,"upper":"1851041709681541120","lower":"1851037679995584512","count":1392,"preSum":53401},{"ndv":109,"upper":"1851044200846458880","lower":"1851041720871944192","count":1408,"preSum":54793},{"ndv":112,"upper":"1851046063402647552","lower":"1851044202155081728","count":1405,"preSum":56201},{"ndv":96,"upper":"1851047739849179136","lower":"1851046063436201984","count":1409,"preSum":57606},{"ndv":138,"upper":"1851049119255101440","lower":"1851047739865956352","count":1397,"preSum":59015},{"ndv":64,"upper":"1851052131956555776","lower":"1851049121805238272","count":1428,"preSum":60412},{"ndv":76,"upper":"1851052473876217856","lower":"1851052144052928512","count":1400,"preSum":61840},{"ndv":56,"upper":"1851052757998370816","lower":"1851052476459909120","count":1410,"preSum":63240},{"ndv":72,"upper":"1851053130502897664","lower":"1851052761303482368","count":1436,"preSum":64650},{"ndv":92,"upper":"1851053465023807488","lower":"1851053136962125824","count":1392,"preSum":66086},{"ndv":85,"upper":"1851054879359893504","lower":"1851053466869301248","count":1412,"preSum":67478},{"ndv":96,"upper":"1851055369321709568","lower":"1851054879376670720","count":1419,"preSum":68890},{"ndv":109,"upper":"1851057201678909440","lower":"1851055370294788096","count":1403,"preSum":70309},{"ndv":86,"upper":"1851059249589780480","lower":"1851057211896233984","count":1404,"preSum":71712},{"ndv":85,"upper":"1851061436449554432","lower":"1851059258750140416","count":1412,"preSum":73116},{"ndv":99,"upper":"1851064004303126528","lower":"1851061443613425664","count":1407,"preSum":74528},{"ndv":111,"upper":"1851066081523793920","lower":"1851064007239139328","count":1440,"preSum":75935},{"ndv":150,"upper":"1851070270878515200","lower":"1851066085835538432","count":1424,"preSum":77375},{"ndv":96,"upper":"1851072456127676416","lower":"1851070271029510144","count":1393,"preSum":78799},{"ndv":85,"upper":"1851074672985112576","lower":"1851072456932982784","count":1417,"preSum":80192},{"ndv":93,"upper":"1851076899237789696","lower":"1851074673219993600","count":1418,"preSum":81609},{"ndv":95,"upper":"1851079314016043008","lower":"1851076899875323904","count":1401,"preSum":83027},{"ndv":145,"upper":"1851081737635889152","lower":"1851079318998876160","count":1394,"preSum":84428},{"ndv":186,"upper":"1851084000009912320","lower":"1851081738172760064","count":1415,"preSum":85822},{"ndv":140,"upper":"1851085701991366656","lower":"1851084000647446528","count":1405,"preSum":87237},{"ndv":13,"upper":"1851085881222365184","lower":"1851085702997999616","count":404,"preSum":88642}],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}','{"countArr":[124,104,111,94,95,139,125,131,165,118,121,103,137],"valueArr":[1850956333113671680,1850988801187381248,1851004691677184000,1851013319914160128,1851018158161264640,1851046371197452288,1851049180139618304,1851049254999556096,1851052311070113792,1851052775329234944,1851052778466574336,1851064264735850496,1851070286867202048],"type":"Timestamp","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','createdby',601,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"000002","lower":"000002","count":1103,"preSum":0},{"ndv":1,"upper":"000003","lower":"000003","count":1473,"preSum":1103},{"ndv":1,"upper":"000004","lower":"000004","count":1223,"preSum":2576},{"ndv":8,"upper":"000093","lower":"000005","count":329,"preSum":3799},{"ndv":18,"upper":"02700001","lower":"01393919","count":589,"preSum":4128},{"ndv":1,"upper":"02700003","lower":"02700003","count":857,"preSum":4717},{"ndv":2,"upper":"02700009","lower":"02700004","count":1027,"preSum":5574},{"ndv":25,"upper":"10000007","lower":"02700020","count":336,"preSum":6601},{"ndv":7,"upper":"1000003","lower":"10000012","count":716,"preSum":6937},{"ndv":1,"upper":"1000004","lower":"1000004","count":389,"preSum":7653},{"ndv":20,"upper":"10001","lower":"1000005","count":2203,"preSum":8042},{"ndv":2,"upper":"10003","lower":"10002","count":1573,"preSum":10245},{"ndv":2,"upper":"10005","lower":"10004","count":542,"preSum":11818},{"ndv":3,"upper":"10008","lower":"10006","count":406,"preSum":12360},{"ndv":1,"upper":"10009","lower":"10009","count":368,"preSum":12766},{"ndv":14,"upper":"41512820","lower":"10103","count":928,"preSum":13134},{"ndv":14,"upper":"42085600","lower":"41762287","count":533,"preSum":14062},{"ndv":10,"upper":"42196770","lower":"42089966","count":1494,"preSum":14595},{"ndv":23,"upper":"gth","lower":"42196820","count":574,"preSum":16089},{"ndv":1,"upper":"hxy","lower":"hxy","count":1092,"preSum":16663},{"ndv":5,"upper":"LL","lower":"JQQ","count":595,"preSum":17755},{"ndv":3,"upper":"lyg","lower":"LQ101","count":779,"preSum":18350},{"ndv":7,"upper":"YBJ","lower":"PZ","count":385,"preSum":19129},{"ndv":6,"upper":"zjf","lower":"yj","count":481,"preSum":19514},{"ndv":3,"upper":"Zz","lower":"ZRX","count":91,"preSum":19995}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[2766,4250,2084,2491,7860,2782,2376,2996,2941,3299,6953,9399,18102,2228],"valueArr":["000001","0220005","0220006","02700005","02700010","10000002","10000004","40401644","40721814","41157743","41509297","41580109","42008280","yxy"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','crossdockmode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[90613],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','csqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[90613],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','expirationdate',2327,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":189,"upper":"1852641908430471168","lower":"-1","count":1266,"preSum":0},{"ndv":87,"upper":"1852925582430437376","lower":"1852644107453726720","count":1383,"preSum":1266},{"ndv":41,"upper":"1853037732616470528","lower":"1852927781453692928","count":1371,"preSum":2649},{"ndv":45,"upper":"1853145484755992576","lower":"1853039931639726080","count":1375,"preSum":4020},{"ndv":10,"upper":"1853176271081570304","lower":"1853147683779248128","count":1385,"preSum":5395},{"ndv":15,"upper":"1853209256430403584","lower":"1853178470104825856","count":1349,"preSum":6780},{"ndv":13,"upper":"1853240042755981312","lower":"1853211455453659136","count":1303,"preSum":8129},{"ndv":11,"upper":"1853264232011792384","lower":"1853242241779236864","count":1484,"preSum":9432},{"ndv":6,"upper":"1853277426151325696","lower":"1853266431035047936","count":1404,"preSum":10916},{"ndv":7,"upper":"1853292819314114560","lower":"1853279625174581248","count":1387,"preSum":12320},{"ndv":11,"upper":"1853325804662947840","lower":"1853295018337370112","count":1287,"preSum":13707},{"ndv":18,"upper":"1853367586104803328","lower":"1853328003686203392","count":1286,"preSum":14994},{"ndv":12,"upper":"1853466542151303168","lower":"1853369785128058880","count":1386,"preSum":16280},{"ndv":31,"upper":"1853554503081525248","lower":"1853468741174558720","count":1414,"preSum":17666},{"ndv":13,"upper":"1853594085500125184","lower":"1853556702104780800","count":1298,"preSum":19080},{"ndv":15,"upper":"1853627070848958464","lower":"1853596284523380736","count":1413,"preSum":20378},{"ndv":5,"upper":"1853638065965236224","lower":"1853629269872214016","count":1516,"preSum":21791},{"ndv":9,"upper":"1853660056197791744","lower":"1853640264988491776","count":1347,"preSum":23307},{"ndv":8,"upper":"1853682046430347264","lower":"1853664454244302848","count":1288,"preSum":24654},{"ndv":6,"upper":"1853695240569880576","lower":"1853684245453602816","count":1276,"preSum":25942},{"ndv":12,"upper":"1853728225918713856","lower":"1853697439593136128","count":1539,"preSum":27218},{"ndv":5,"upper":"1853741420058247168","lower":"1853732623965224960","count":1304,"preSum":28757},{"ndv":7,"upper":"1853759012244291584","lower":"1853743619081502720","count":1364,"preSum":30061},{"ndv":14,"upper":"1853789798569869312","lower":"1853761211267547136","count":1359,"preSum":31425},{"ndv":42,"upper":"1853895351686135808","lower":"1853791997593124864","count":1275,"preSum":32784},{"ndv":57,"upper":"1854040487221002240","lower":"1853897550709391360","count":1348,"preSum":34059},{"ndv":18,"upper":"1854088865732624384","lower":"1854042686244257792","count":1268,"preSum":35407},{"ndv":11,"upper":"1854113054988435456","lower":"1854091064755879936","count":1425,"preSum":36675},{"ndv":5,"upper":"1854124050104713216","lower":"1854115254011691008","count":1338,"preSum":38100},{"ndv":6,"upper":"1854137244244246528","lower":"1854126249127968768","count":1270,"preSum":39438},{"ndv":4,"upper":"1854148239360524288","lower":"1854139443267502080","count":1323,"preSum":40708},{"ndv":6,"upper":"1854161433500057600","lower":"1854150438383779840","count":1592,"preSum":42031},{"ndv":5,"upper":"1854174627639590912","lower":"1854163632523313152","count":1358,"preSum":43623},{"ndv":5,"upper":"1854185622755868672","lower":"1854176826662846464","count":1300,"preSum":44981},{"ndv":8,"upper":"1854203214941913088","lower":"1854187821779124224","count":1271,"preSum":46281},{"ndv":8,"upper":"1854225205174468608","lower":"1854205413965168640","count":1425,"preSum":47552},{"ndv":9,"upper":"1854244996383768576","lower":"1854227404197724160","count":1494,"preSum":48977},{"ndv":7,"upper":"1854260389546557440","lower":"1854247195407024128","count":1297,"preSum":50471},{"ndv":8,"upper":"1854277981732601856","lower":"1854262588569812992","count":1532,"preSum":51768},{"ndv":9,"upper":"1854370340709335040","lower":"1854280180755857408","count":1267,"preSum":53300},{"ndv":13,"upper":"1854420918244212736","lower":"1854372539732590592","count":1441,"preSum":54567},{"ndv":10,"upper":"1854447306523279360","lower":"1854423117267468288","count":1408,"preSum":56008},{"ndv":13,"upper":"1854484689918623744","lower":"1854453903593046016","count":1489,"preSum":57416},{"ndv":5,"upper":"1854504481127923712","lower":"1854486888941879296","count":1487,"preSum":58905},{"ndv":5,"upper":"1854515476244201472","lower":"1854506680151179264","count":1648,"preSum":60392},{"ndv":4,"upper":"1854524272337223680","lower":"1854517675267457024","count":1464,"preSum":62040},{"ndv":4,"upper":"1854533068430245888","lower":"1854526471360479232","count":1416,"preSum":63504},{"ndv":3,"upper":"1854539665500012544","lower":"1854535267453501440","count":1303,"preSum":64920},{"ndv":4,"upper":"1854548461593034752","lower":"1854541864523268096","count":1362,"preSum":66223},{"ndv":6,"upper":"1854561655732568064","lower":"1854550660616290304","count":1294,"preSum":67585},{"ndv":4,"upper":"1854574849872101376","lower":"1854563854755823616","count":1340,"preSum":68879},{"ndv":5,"upper":"1854585844988379136","lower":"1854577048895356928","count":1479,"preSum":70219},{"ndv":3,"upper":"1854592442058145792","lower":"1854588044011634688","count":1488,"preSum":71698},{"ndv":4,"upper":"1854603437174423552","lower":"1854594641081401344","count":1642,"preSum":73186},{"ndv":5,"upper":"1854616631313956864","lower":"1854605636197679104","count":1510,"preSum":74828},{"ndv":4,"upper":"1854645218616279040","lower":"1854618830337212416","count":1572,"preSum":76338},{"ndv":4,"upper":"1854656213732556800","lower":"1854649616662790144","count":1490,"preSum":77910},{"ndv":10,"upper":"1854680402988367872","lower":"1854658412755812352","count":1286,"preSum":79400},{"ndv":24,"upper":"1876129675823022080","lower":"1854682602011623424","count":308,"preSum":80686}],"maxBucketSize":64,"type":"Date","sampleRate":1.0}','{"countArr":[821,781,760,662,590,635,722,791,608,808,642,584,592,623],"valueArr":[1853303814430392320,1853673250337325056,1853730424941969408,1853748017128013824,1854572650848845824,1854599039127912448,1854612233267445760,1854621029360467968,1854623228383723520,1854625427406979072,1854629825453490176,1854640820569767936,1854647417639534592,9147934544073064448],"type":"Date","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','id',7163996,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1416,"upper":2639593,"lower":2395035,"count":1416,"preSum":0},{"ndv":1416,"upper":2902278,"lower":2639594,"count":1416,"preSum":1416},{"ndv":1416,"upper":3165094,"lower":2902279,"count":1416,"preSum":2832},{"ndv":1416,"upper":3331105,"lower":3165101,"count":1416,"preSum":4248},{"ndv":1416,"upper":3553642,"lower":3331108,"count":1416,"preSum":5664},{"ndv":1416,"upper":3754789,"lower":3553647,"count":1416,"preSum":7080},{"ndv":1416,"upper":3952342,"lower":3754853,"count":1416,"preSum":8496},{"ndv":1416,"upper":4154046,"lower":3952345,"count":1416,"preSum":9912},{"ndv":1416,"upper":4436767,"lower":4154047,"count":1416,"preSum":11328},{"ndv":1416,"upper":4638990,"lower":4436775,"count":1416,"preSum":12744},{"ndv":1416,"upper":4913868,"lower":4638993,"count":1416,"preSum":14160},{"ndv":1416,"upper":5164470,"lower":4913869,"count":1416,"preSum":15576},{"ndv":1416,"upper":5350597,"lower":5164472,"count":1416,"preSum":16992},{"ndv":1416,"upper":5578973,"lower":5350617,"count":1416,"preSum":18408},{"ndv":1416,"upper":5836037,"lower":5578980,"count":1416,"preSum":19824},{"ndv":1416,"upper":6032889,"lower":5836038,"count":1416,"preSum":21240},{"ndv":1416,"upper":6208952,"lower":6032890,"count":1416,"preSum":22656},{"ndv":1416,"upper":6464089,"lower":6208959,"count":1416,"preSum":24072},{"ndv":1416,"upper":6672690,"lower":6464091,"count":1416,"preSum":25488},{"ndv":1416,"upper":6872902,"lower":6672692,"count":1416,"preSum":26904},{"ndv":1416,"upper":7064153,"lower":6872906,"count":1416,"preSum":28320},{"ndv":1416,"upper":7370630,"lower":7064156,"count":1416,"preSum":29736},{"ndv":1416,"upper":7551934,"lower":7370632,"count":1416,"preSum":31152},{"ndv":1416,"upper":7787511,"lower":7551941,"count":1416,"preSum":32568},{"ndv":1416,"upper":8004445,"lower":7787513,"count":1416,"preSum":33984},{"ndv":1416,"upper":8214899,"lower":8004446,"count":1416,"preSum":35400},{"ndv":1416,"upper":8417067,"lower":8219876,"count":1416,"preSum":36816},{"ndv":1416,"upper":8578303,"lower":8417072,"count":1416,"preSum":38232},{"ndv":1416,"upper":8871429,"lower":8578307,"count":1416,"preSum":39648},{"ndv":1416,"upper":9050556,"lower":8872064,"count":1416,"preSum":41064},{"ndv":1416,"upper":9228956,"lower":9050558,"count":1416,"preSum":42480},{"ndv":1416,"upper":9421422,"lower":9228961,"count":1416,"preSum":43896},{"ndv":1416,"upper":9650939,"lower":9421426,"count":1416,"preSum":45312},{"ndv":1416,"upper":9848459,"lower":9650943,"count":1416,"preSum":46728},{"ndv":1416,"upper":10071433,"lower":9848461,"count":1416,"preSum":48144},{"ndv":1416,"upper":10250748,"lower":10071436,"count":1416,"preSum":49560},{"ndv":1416,"upper":10460071,"lower":10250749,"count":1416,"preSum":50976},{"ndv":1416,"upper":10683875,"lower":10460073,"count":1416,"preSum":52392},{"ndv":1416,"upper":10875509,"lower":10683884,"count":1416,"preSum":53808},{"ndv":1416,"upper":11150753,"lower":10875510,"count":1416,"preSum":55224},{"ndv":1416,"upper":11328573,"lower":11150754,"count":1416,"preSum":56640},{"ndv":1416,"upper":11495252,"lower":11328576,"count":1416,"preSum":58056},{"ndv":1416,"upper":11775890,"lower":11495254,"count":1416,"preSum":59472},{"ndv":1416,"upper":11994020,"lower":11775899,"count":1416,"preSum":60888},{"ndv":1416,"upper":12235300,"lower":11994021,"count":1416,"preSum":62304},{"ndv":1416,"upper":12422928,"lower":12235301,"count":1416,"preSum":63720},{"ndv":1416,"upper":12667815,"lower":12422930,"count":1416,"preSum":65136},{"ndv":1416,"upper":12885483,"lower":12667816,"count":1416,"preSum":66552},{"ndv":1416,"upper":13083580,"lower":12885484,"count":1416,"preSum":67968},{"ndv":1416,"upper":13257868,"lower":13088321,"count":1416,"preSum":69384},{"ndv":1416,"upper":13449663,"lower":13257875,"count":1416,"preSum":70800},{"ndv":1416,"upper":13663655,"lower":13449669,"count":1416,"preSum":72216},{"ndv":1416,"upper":13893163,"lower":13663673,"count":1416,"preSum":73632},{"ndv":1416,"upper":14116026,"lower":13893168,"count":1416,"preSum":75048},{"ndv":1416,"upper":14361589,"lower":14116027,"count":1416,"preSum":76464},{"ndv":1416,"upper":14551446,"lower":14361649,"count":1416,"preSum":77880},{"ndv":1416,"upper":14750263,"lower":14551449,"count":1416,"preSum":79296},{"ndv":1416,"upper":14903418,"lower":14750264,"count":1416,"preSum":80712},{"ndv":1416,"upper":15039912,"lower":14903421,"count":1416,"preSum":82128},{"ndv":1416,"upper":15204270,"lower":15039917,"count":1416,"preSum":83544},{"ndv":1416,"upper":15407062,"lower":15204272,"count":1416,"preSum":84960},{"ndv":1416,"upper":15595582,"lower":15407076,"count":1416,"preSum":86376},{"ndv":1416,"upper":15791772,"lower":15595587,"count":1416,"preSum":87792},{"ndv":1405,"upper":16034467,"lower":15791778,"count":1405,"preSum":89208}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,0,0.007226729),('jala_wms_prod','shipping_container_detail','inventorysts',14,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"XS","lower":"XS","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[23,90589],"valueArr":["QC","ZP"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','isgift',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[90613],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.007226729); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('jala_wms_prod','shipping_container_detail','itemcode',4042,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":89,"upper":"502112104","lower":"1300369502","count":1129,"preSum":0},{"ndv":22,"upper":"502191390","lower":"502112201","count":1121,"preSum":1129},{"ndv":14,"upper":"502191612","lower":"502191510","count":1159,"preSum":2250},{"ndv":9,"upper":"502200306","lower":"502191613","count":1820,"preSum":3409},{"ndv":8,"upper":"502201701","lower":"502200400","count":1601,"preSum":5229},{"ndv":5,"upper":"502201906","lower":"502201701T","count":1194,"preSum":6830},{"ndv":3,"upper":"502202401","lower":"502201910","count":1159,"preSum":8024},{"ndv":5,"upper":"502203504","lower":"502202405","count":1124,"preSum":9183},{"ndv":6,"upper":"502220502","lower":"502220202","count":1131,"preSum":10307},{"ndv":26,"upper":"502250504","lower":"502220601","count":1111,"preSum":11438},{"ndv":20,"upper":"502471603","lower":"502250601","count":1193,"preSum":12549},{"ndv":5,"upper":"502477901","lower":"502471604","count":1286,"preSum":13742},{"ndv":10,"upper":"502484903","lower":"502477902","count":1193,"preSum":15028},{"ndv":37,"upper":"502514005","lower":"502485002","count":1168,"preSum":16221},{"ndv":24,"upper":"502523708","lower":"502514100","count":1854,"preSum":17389},{"ndv":21,"upper":"502540302","lower":"502523902","count":1460,"preSum":19243},{"ndv":33,"upper":"502561000","lower":"502542201","count":1111,"preSum":20703},{"ndv":29,"upper":"502576003","lower":"502561100","count":1127,"preSum":21814},{"ndv":22,"upper":"502583416","lower":"502576100","count":1346,"preSum":22941},{"ndv":14,"upper":"502588103","lower":"502585900","count":1236,"preSum":24287},{"ndv":23,"upper":"502589202","lower":"502588300","count":1113,"preSum":25523},{"ndv":31,"upper":"502600400","lower":"502589302","count":1121,"preSum":26636},{"ndv":34,"upper":"502622207","lower":"502600405","count":1170,"preSum":27757},{"ndv":11,"upper":"502640804","lower":"502622208","count":1223,"preSum":28927},{"ndv":6,"upper":"502642604","lower":"502640805","count":1860,"preSum":30150},{"ndv":11,"upper":"502645000","lower":"502642700","count":1196,"preSum":32010},{"ndv":54,"upper":"502671602","lower":"502646400","count":1126,"preSum":33206},{"ndv":21,"upper":"502672902","lower":"502671700","count":1134,"preSum":34332},{"ndv":17,"upper":"502692900","lower":"502673002","count":1639,"preSum":35466},{"ndv":6,"upper":"502694000","lower":"502693400","count":1185,"preSum":37105},{"ndv":28,"upper":"502699102","lower":"502694100","count":1198,"preSum":38290},{"ndv":8,"upper":"502699401","lower":"502699200","count":1119,"preSum":39488},{"ndv":23,"upper":"502703400","lower":"502699402","count":1123,"preSum":40607},{"ndv":47,"upper":"502715300","lower":"502703500","count":1688,"preSum":41730},{"ndv":18,"upper":"502729300","lower":"502715800","count":1132,"preSum":43418},{"ndv":12,"upper":"502731300","lower":"502729701","count":1378,"preSum":44550},{"ndv":22,"upper":"502740801","lower":"502731301","count":1432,"preSum":45928},{"ndv":8,"upper":"502750900","lower":"502748003","count":1169,"preSum":47360},{"ndv":11,"upper":"502754400","lower":"502751000","count":1266,"preSum":48529},{"ndv":10,"upper":"502755000","lower":"502754500","count":1266,"preSum":49795},{"ndv":3,"upper":"502755200","lower":"502755100","count":1120,"preSum":51061},{"ndv":3,"upper":"502755400","lower":"502755300","count":1405,"preSum":52181},{"ndv":27,"upper":"502763000","lower":"502755401","count":1114,"preSum":53586},{"ndv":13,"upper":"502767800","lower":"502763100","count":1141,"preSum":54700},{"ndv":23,"upper":"502787600","lower":"502768500","count":1621,"preSum":55841},{"ndv":12,"upper":"502791100","lower":"502787800","count":1257,"preSum":57462},{"ndv":33,"upper":"502962100","lower":"502791200","count":1113,"preSum":58719},{"ndv":18,"upper":"502976583","lower":"502962211","count":1151,"preSum":59832},{"ndv":11,"upper":"502985463","lower":"502976671","count":1199,"preSum":60983},{"ndv":195,"upper":"512000300","lower":"503024900","count":1118,"preSum":62182},{"ndv":25,"upper":"512005303","lower":"512000301","count":1110,"preSum":63300},{"ndv":48,"upper":"6163864","lower":"512006900","count":1114,"preSum":64410},{"ndv":24,"upper":"6164941","lower":"6164153","count":1114,"preSum":65524},{"ndv":21,"upper":"6165115","lower":"6164945","count":1117,"preSum":66638},{"ndv":20,"upper":"6165272","lower":"6165121","count":1196,"preSum":67755},{"ndv":8,"upper":"6165296","lower":"6165273","count":1294,"preSum":68951},{"ndv":50,"upper":"6200262","lower":"6165304","count":763,"preSum":70245}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[1404,1393,2276,1879,1116,1885,1090,1505,1019,1446,1371,1046,1070,1105],"valueArr":["502536603","502582805","502668704","502668804","502668904","502669004","502693900","502697804","502699002","502700002","502725500","502755900","502762700","502976673"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','itemheight',471,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":18,"upper":12.5000,"lower":0.0010,"count":701,"preSum":0},{"ndv":11,"upper":18.0000,"lower":13.0000,"count":411,"preSum":701},{"ndv":5,"upper":18.9000,"lower":18.5000,"count":519,"preSum":1112},{"ndv":2,"upper":19.2600,"lower":19.2000,"count":594,"preSum":1631},{"ndv":2,"upper":21.0000,"lower":20.0000,"count":948,"preSum":2225},{"ndv":1,"upper":22.0000,"lower":22.0000,"count":776,"preSum":3173},{"ndv":8,"upper":25.3000,"lower":22.2000,"count":425,"preSum":3949},{"ndv":4,"upper":30.5000,"lower":28.0000,"count":453,"preSum":4374},{"ndv":11,"upper":37.0000,"lower":31.0000,"count":418,"preSum":4827},{"ndv":5,"upper":40.5000,"lower":38.0000,"count":442,"preSum":5245},{"ndv":7,"upper":47.0000,"lower":41.0000,"count":420,"preSum":5687},{"ndv":7,"upper":54.0000,"lower":48.0000,"count":672,"preSum":6107},{"ndv":4,"upper":57.0000,"lower":55.0000,"count":431,"preSum":6779},{"ndv":3,"upper":60.0000,"lower":58.9200,"count":830,"preSum":7210},{"ndv":7,"upper":66.0000,"lower":61.0000,"count":997,"preSum":8040},{"ndv":4,"upper":72.0000,"lower":67.0000,"count":609,"preSum":9037},{"ndv":5,"upper":76.0000,"lower":73.0000,"count":449,"preSum":9646},{"ndv":5,"upper":78.0000,"lower":76.8100,"count":409,"preSum":10095},{"ndv":3,"upper":80.0000,"lower":78.3900,"count":550,"preSum":10504},{"ndv":5,"upper":81.9400,"lower":80.5000,"count":519,"preSum":11054},{"ndv":10,"upper":87.0000,"lower":81.9500,"count":447,"preSum":11573},{"ndv":5,"upper":95.0000,"lower":88.0000,"count":946,"preSum":12020},{"ndv":8,"upper":112.0000,"lower":100.0000,"count":578,"preSum":12966},{"ndv":3,"upper":116.0000,"lower":113.3000,"count":583,"preSum":13544},{"ndv":4,"upper":120.0000,"lower":118.0000,"count":559,"preSum":14127},{"ndv":5,"upper":125.0000,"lower":120.4800,"count":691,"preSum":14686},{"ndv":5,"upper":130.0000,"lower":126.0000,"count":691,"preSum":15377},{"ndv":3,"upper":135.0000,"lower":131.0000,"count":555,"preSum":16068},{"ndv":4,"upper":138.0000,"lower":136.2300,"count":643,"preSum":16623},{"ndv":5,"upper":146.0000,"lower":140.0000,"count":456,"preSum":17266},{"ndv":4,"upper":150.0000,"lower":147.0000,"count":936,"preSum":17722},{"ndv":8,"upper":160.0000,"lower":151.0000,"count":479,"preSum":18658},{"ndv":1,"upper":161.0000,"lower":161.0000,"count":756,"preSum":19137},{"ndv":5,"upper":167.0000,"lower":162.1100,"count":482,"preSum":19893},{"ndv":3,"upper":170.0000,"lower":168.0000,"count":1101,"preSum":20375},{"ndv":4,"upper":174.0000,"lower":172.0000,"count":437,"preSum":21476},{"ndv":1,"upper":175.0000,"lower":175.0000,"count":848,"preSum":21913},{"ndv":2,"upper":176.0000,"lower":175.9000,"count":570,"preSum":22761},{"ndv":2,"upper":178.0000,"lower":176.5300,"count":422,"preSum":23331},{"ndv":2,"upper":180.0000,"lower":179.0200,"count":517,"preSum":23753},{"ndv":7,"upper":187.0000,"lower":181.0000,"count":751,"preSum":24270},{"ndv":22,"upper":530.0000,"lower":189.0000,"count":394,"preSum":25021}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[44954,973,1193,1011,1371,1037,1318,2256,1085,1626,2545,3493,1065,1271],"valueArr":[0.0000,3.8000,35.0000,69.0000,74.0000,94.0400,105.0000,107.2000,139.0000,166.0000,171.0000,175.4700,184.0000,198.0000],"type":"Double","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','itemlength',430,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":6,"upper":9.0500,"lower":2.5000,"count":348,"preSum":0},{"ndv":16,"upper":23.5900,"lower":9.7000,"count":548,"preSum":348},{"ndv":4,"upper":25.0000,"lower":23.9000,"count":491,"preSum":896},{"ndv":4,"upper":26.0000,"lower":25.2000,"count":368,"preSum":1387},{"ndv":5,"upper":27.0000,"lower":26.3000,"count":670,"preSum":1755},{"ndv":7,"upper":30.7400,"lower":27.2000,"count":565,"preSum":2425},{"ndv":1,"upper":31.0000,"lower":31.0000,"count":767,"preSum":2990},{"ndv":4,"upper":36.0000,"lower":33.0000,"count":455,"preSum":3757},{"ndv":5,"upper":37.0000,"lower":36.2000,"count":1125,"preSum":4212},{"ndv":4,"upper":39.0000,"lower":37.0700,"count":334,"preSum":5337},{"ndv":3,"upper":40.0000,"lower":39.4700,"count":490,"preSum":5671},{"ndv":1,"upper":41.0000,"lower":41.0000,"count":875,"preSum":6161},{"ndv":2,"upper":42.0000,"lower":41.5000,"count":472,"preSum":7036},{"ndv":3,"upper":43.0000,"lower":42.5000,"count":625,"preSum":7508},{"ndv":4,"upper":45.0000,"lower":43.5000,"count":665,"preSum":8133},{"ndv":2,"upper":46.0000,"lower":45.5000,"count":352,"preSum":8798},{"ndv":3,"upper":49.0000,"lower":46.5000,"count":344,"preSum":9150},{"ndv":5,"upper":51.0000,"lower":49.1300,"count":451,"preSum":9494},{"ndv":6,"upper":55.0000,"lower":51.7000,"count":336,"preSum":9945},{"ndv":5,"upper":59.0000,"lower":57.0000,"count":331,"preSum":10281},{"ndv":1,"upper":60.0000,"lower":60.0000,"count":331,"preSum":10612},{"ndv":2,"upper":61.0000,"lower":60.5900,"count":454,"preSum":10943},{"ndv":7,"upper":66.0000,"lower":62.0000,"count":645,"preSum":11397},{"ndv":1,"upper":67.0000,"lower":67.0000,"count":646,"preSum":12042},{"ndv":7,"upper":72.0000,"lower":67.9400,"count":617,"preSum":12688},{"ndv":4,"upper":76.0000,"lower":73.0000,"count":555,"preSum":13305},{"ndv":1,"upper":77.0000,"lower":77.0000,"count":480,"preSum":13860},{"ndv":3,"upper":78.5000,"lower":78.0000,"count":325,"preSum":14340},{"ndv":4,"upper":81.0000,"lower":79.0000,"count":471,"preSum":14665},{"ndv":9,"upper":93.5000,"lower":82.0000,"count":401,"preSum":15136},{"ndv":8,"upper":109.5000,"lower":94.0000,"count":563,"preSum":15537},{"ndv":5,"upper":114.0000,"lower":110.0000,"count":724,"preSum":16100},{"ndv":4,"upper":119.0000,"lower":115.0000,"count":602,"preSum":16824},{"ndv":7,"upper":132.0000,"lower":122.0000,"count":687,"preSum":17426},{"ndv":4,"upper":139.0000,"lower":134.0000,"count":330,"preSum":18113},{"ndv":11,"upper":161.0000,"lower":140.0000,"count":916,"preSum":18443},{"ndv":8,"upper":178.0000,"lower":162.5000,"count":324,"preSum":19359},{"ndv":11,"upper":215.0000,"lower":178.0200,"count":335,"preSum":19683},{"ndv":13,"upper":280.0000,"lower":235.0000,"count":378,"preSum":20018},{"ndv":12,"upper":770.0000,"lower":285.0000,"count":277,"preSum":20396}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[44824,1233,1037,2267,1503,3592,2899,2394,1798,1060,3493,1147,1141,1552],"valueArr":[0.0000,23.0000,25.5300,38.3000,47.0000,50.0000,56.0000,74.0000,120.0000,123.0000,124.7100,125.0000,133.0000,138.0000],"type":"Double","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','itemname',5393,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":127,"upper":"春夏多肽柔肤精华露130mL(新法规)","lower":" 自然堂舒缓润养卸妆膏100mL(王者荣耀限量礼盒)","count":1164,"preSum":0},{"ndv":149,"upper":"珀芙研电商包裹卡(20221109)","lower":"春夏多肽柔肤精华露8mL中小样","count":1182,"preSum":1164},{"ndv":19,"upper":"珀芙研舒缓保湿洁面乳100g","lower":"珀芙研舒缓保湿体验装四件套中小样","count":1245,"preSum":2346},{"ndv":99,"upper":"美素雪颜晶透莹润焕采隔离霜(淡紫色)SPF20PA++30g","lower":"珀芙研舒缓保湿洁面乳15g中小样","count":1173,"preSum":3591},{"ndv":15,"upper":"自然堂2022版购物袋-中号","lower":"美素雪颜晶透莹润焕采隔离霜(淡绿色)SPF20PA++30g","count":1320,"preSum":4764},{"ndv":58,"upper":"自然堂亲肤倍呵防晒乳SPF50+PA+++10mL中小样","lower":"自然堂2022版购物袋-中号(双面印)","count":1426,"preSum":6084},{"ndv":13,"upper":"自然堂冰川水水光面膜(新规版)28mL×5片装","lower":"自然堂亲肤倍呵防晒乳SPF50+PA+++50mL","count":1279,"preSum":7510},{"ndv":47,"upper":"自然堂凝时精华鲜注面膜(2022二版)30mL×5片装","lower":"自然堂冰川水水光面膜28mL 1片装","count":1591,"preSum":8789},{"ndv":19,"upper":"自然堂凝时鲜颜冰肌水160mL","lower":"自然堂凝时精华鲜注面膜(2022版)30mL×3片装","count":1641,"preSum":10380},{"ndv":13,"upper":"自然堂凝时鲜颜小紫瓶肌活霜50g","lower":"自然堂凝时鲜颜冰肌水160mL试用装","count":1391,"preSum":12021},{"ndv":4,"upper":"自然堂凝时鲜颜洁面霜(体验装)60g中小样","lower":"自然堂凝时鲜颜小紫瓶肌活霜50g(欣昱玻璃瓶)","count":1402,"preSum":13412},{"ndv":12,"upper":"自然堂凝时鲜颜肌活乳液(2022升级)15mL中小样","lower":"自然堂凝时鲜颜洁面霜(新装箱)30g中小样","count":1275,"preSum":14814},{"ndv":9,"upper":"自然堂凝时鲜颜肌活修护体验装三件套(2020乳版)中小样","lower":"自然堂凝时鲜颜肌活乳液(2022升级)90mL","count":1184,"preSum":16089},{"ndv":7,"upper":"自然堂凝时鲜颜肌活修护小紫瓶眼霜15g","lower":"自然堂凝时鲜颜肌活修护体验装三件套(乳液版)中小样","count":1265,"preSum":17273},{"ndv":13,"upper":"自然堂凝时鲜颜肌活修护小紫瓶精华液第五代(2023)10mL小规格产品","lower":"自然堂凝时鲜颜肌活修护小紫瓶精华液(新装箱)7.5mL中小样","count":1165,"preSum":18538},{"ndv":9,"upper":"自然堂凝时鲜颜肌活修护小紫瓶精华液第五代50mL","lower":"自然堂凝时鲜颜肌活修护小紫瓶精华液第五代(2023)50mL","count":1419,"preSum":19703},{"ndv":15,"upper":"自然堂凝时鲜颜肌活冰肌水(清润型)(2023升级)160mL","lower":"自然堂凝时鲜颜肌活修护小紫瓶精华液第五代7mL中小样","count":1292,"preSum":21122},{"ndv":6,"upper":"自然堂凝时鲜颜肌活眼部精华乳18mL类产品","lower":"自然堂凝时鲜颜肌活冰肌水(滋润型)(2023升级)160mL","count":1177,"preSum":22414},{"ndv":3,"upper":"自然堂凝时鲜颜肌活精华液(2023)7.5mL中小样","lower":"自然堂凝时鲜颜肌活精华抗皱三件套(水乳精套2023)","count":1253,"preSum":23591},{"ndv":5,"upper":"自然堂凝润滋养护手霜(20210716加花盒)50g","lower":"自然堂凝时鲜颜肌活霜(2023升级)50g","count":1177,"preSum":24844},{"ndv":47,"upper":"自然堂多肽抗皱美颈霜60g类产品","lower":"自然堂凝润滋养护手霜50g(20210716加花盒)","count":1193,"preSum":26021},{"ndv":11,"upper":"自然堂头皮护理敏感头皮保湿洗发露550mL","lower":"自然堂多肽紧致美颈霜60g(暂定名)类产品","count":1221,"preSum":27214},{"ndv":5,"upper":"自然堂头皮护理敏感头皮止痒洗发露+精华乳洗护两联包(5mL+5mL)两件套袋装","lower":"自然堂头皮护理敏感头皮修护精华液120mL","count":1305,"preSum":28435},{"ndv":12,"upper":"自然堂娇颜亮润焕采眼霜(抖拼快专售)15g","lower":"自然堂头皮护理敏感头皮止痒洗发露550mL(经销商大会版)试用装","count":1167,"preSum":29740},{"ndv":10,"upper":"自然堂娇颜亮润美白4件套(洁水乳精)","lower":"自然堂娇颜亮润系列嫩白保湿乳(假金盖)35mL","count":1768,"preSum":30907},{"ndv":9,"upper":"自然堂嫩白保湿乳(粉盖)35mL中小样","lower":"自然堂娇颜亮润美白体验装四件套(抖拼快专售)中小样","count":1191,"preSum":32675},{"ndv":10,"upper":"自然堂嫩白保湿霜(假金盖)15g中小样","lower":"自然堂嫩白保湿乳115mL(抖拼快专售)","count":1244,"preSum":33866},{"ndv":15,"upper":"自然堂定制随包卡片(每妆)","lower":"自然堂嫩白保湿霜(抖拼快专售)50g","count":1177,"preSum":35110},{"ndv":34,"upper":"自然堂弹嫩紧致抗皱会员礼盒类产品","lower":"自然堂定制随包卡片(然美新版)","count":1189,"preSum":36287},{"ndv":29,"upper":"自然堂弹嫩细致洁颜霜(新标签版)50g","lower":"自然堂弹嫩紧致抗皱修护晚安霜(2021)15g中小样","count":1237,"preSum":37476},{"ndv":46,"upper":"自然堂感光无瑕持妆粉底液(干皮)#B02自然白15mL柜台试用装","lower":"自然堂弹嫩细致洁颜霜120g","count":1164,"preSum":38713},{"ndv":40,"upper":"自然堂敏感头皮止痒洗发露+精华乳旅行装(40mL+40mL)两件套(第2版)","lower":"自然堂感光无瑕持妆粉底液(干皮)#B02自然白30mL","count":1206,"preSum":39877},{"ndv":42,"upper":"自然堂氨基酸洁面乳150g(线上专售)","lower":"自然堂敏肌舒缓修护冻干面膜0.52g×5片装","count":1235,"preSum":41083},{"ndv":13,"upper":"自然堂水光充盈保湿精华液10mL中小样","lower":"自然堂氨基酸温和卸妆水400mL","count":1225,"preSum":42318},{"ndv":15,"upper":"自然堂水润保湿洗颜霜(混合偏油肤质适用)(配方升级新标签版)100g","lower":"自然堂水光充盈保湿精华液35mL","count":1477,"preSum":43543},{"ndv":55,"upper":"自然堂滚轮按摩仪","lower":"自然堂水润保湿霜(2022升级版)50g","count":1769,"preSum":45020},{"ndv":30,"upper":"自然堂烟酰胺细致提亮安瓶面膜(无防腐) 安瓶1.5mL+面膜33mL 5片装","lower":"自然堂炫彩盈润高显色唇膏#101千禧粉3.2g","count":1411,"preSum":46789},{"ndv":45,"upper":"自然堂男士冰川透爽活力沐浴露550mL","lower":"自然堂烟酰胺细致提亮面膜(新规版)33mL 5片装","count":1164,"preSum":48200},{"ndv":35,"upper":"自然堂男士喜马拉雅冰川保湿露(2022版)70mL","lower":"自然堂男士净油洁面乳160mL","count":1251,"preSum":49364},{"ndv":5,"upper":"自然堂男士喜马拉雅冰川滋润霜50g","lower":"自然堂男士喜马拉雅冰川保湿露(新标签版)20mL中小样","count":1178,"preSum":50615},{"ndv":24,"upper":"自然堂男士喜马拉雅龙血能量洁面护肤套装(202005)","lower":"自然堂男士喜马拉雅冰川滋润霜50g(201806)","count":1169,"preSum":51793},{"ndv":53,"upper":"自然堂粉钻紧致细嫩玫瑰水55mL(美ONE定制)小规格产品","lower":"自然堂男士喜马拉雅龙血能量润肤霜(201806)50g","count":1204,"preSum":52962},{"ndv":27,"upper":"自然堂纯粹滋润冰肌水(2022升级版)60mL中小样","lower":"自然堂粉钻紧致细嫩玫瑰霜(美ONE定制)15g中小样","count":1315,"preSum":54166},{"ndv":22,"upper":"自然堂美白淡斑两步曲面膜(1.5mL+26mL)*5PCS(2022版)","lower":"自然堂纯粹滋润冰肌水(2022升级版)90mL","count":1275,"preSum":55481},{"ndv":32,"upper":"自然堂蓝铜肽抗皱紧致安瓶面膜安瓶1.5mL+面膜33mL5片装","lower":"自然堂美白淡斑两步曲面膜(1.5mL+26mL)*5片装","count":1221,"preSum":56756},{"ndv":29,"upper":"自然堂酵母原液修护安瓶精华液(第二代)1.5mL*7PCS类产品","lower":"自然堂虾青素焕亮紧致面膜(新规版)33mL×5片装","count":1442,"preSum":57977},{"ndv":57,"upper":"自然堂雪域百合补水面膜(2022二版)26mL 1片装","lower":"自然堂酵母原液修护安瓶精华液1.5mL 28支装","count":1716,"preSum":59419},{"ndv":28,"upper":"自然堂雪域精粹纯粹滋润乳液(2022标签升级)120mL","lower":"自然堂雪域百合补水面膜(2022版)26mL×3片装","count":1214,"preSum":61135},{"ndv":25,"upper":"自然堂雪域精粹纯粹滋润精华液(升级版)10mL中小样","lower":"自然堂雪域精粹纯粹滋润乳液(2022标签升级)90mL","count":1197,"preSum":62349},{"ndv":21,"upper":"自然堂雪域紫草细致毛孔面膜26mL*5PCS(2022二版)","lower":"自然堂雪域精粹纯粹滋润精华液10mL(2022/1)中小样","count":1653,"preSum":63546},{"ndv":24,"upper":"自然堂雪松精油活颜御龄体验装四件套(霜版)中小样","lower":"自然堂雪域紫草细致毛孔面膜26mL*5片装(2022二版)","count":1170,"preSum":65199},{"ndv":23,"upper":"自然堂雪松精油活颜御龄霜50g","lower":"自然堂雪松精油活颜御龄光感霜1.5g袋装","count":1258,"preSum":66369},{"ndv":41,"upper":"自然堂雪润皙白多重防晒隔离霜(淡紫色)SPF32PA+++(新规版)30mL","lower":"自然堂雪松精油活颜御龄霜5g中小样","count":1245,"preSum":67627},{"ndv":31,"upper":"自然堂雪肌发光美白水20mL中小样","lower":"自然堂雪润皙白多重防晒隔离霜(淡紫色)SPF32PA+++(软管二代)30mL","count":1309,"preSum":68872},{"ndv":17,"upper":"自然堂雪茶平衡保湿面膜(2022二版)26mL×5片装","lower":"自然堂雪肌美白保湿洁面霜120g","count":1816,"preSum":70181},{"ndv":14,"upper":"自然堂雪莲舒缓保湿面膜(2022二版)26mL 1片装","lower":"自然堂雪茶平衡保湿面膜(2022版)26mL 1片装","count":1349,"preSum":71997},{"ndv":24,"upper":"鸟窝特价筐","lower":"自然堂雪莲舒缓保湿面膜(2022二版)26mL×6片装","count":1135,"preSum":73346}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[948,1105,1371,1046,1090,1070,1446,948,1127,1296,970,1302,1270,1143],"valueArr":["自然堂III型重组胶原蛋白修护冻干面膜0.65g×5片装","自然堂凝时鲜颜肌活冰肌水(清润型)(2023升级)60mL","自然堂喜马拉雅茶泥净颜清洁面膜100g","自然堂头皮护理敏感头皮修护精华液20mL中小样","自然堂头皮护理敏感头皮止痒洗发露550mL","自然堂头皮护理洗护精旅行装(40mL+40mL+20mL)三件套","自然堂植物补水面膜21片装(2022二版)","自然堂烟酰胺细致提亮安瓶面膜(新规版) 1.5mL+33mL×5片装","自然堂羽感致护防晒乳SPF50+PA+++(新规版)50mL","自然堂雪域百合补水面膜(2022二版)26mL×5片装","自然堂雪域百合补水面膜26mL*5PCS(2022二版)","自然堂雪域紫草细致毛孔面膜(2022二版)26mL×5片装","自然堂雪域龙胆亮润面膜(2022二版)26mL×5片装","自然堂雪莲舒缓保湿面膜(2022二版)26mL×5片装"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','itemvalue',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[90613],"valueArr":[0.0000],"type":"Double","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','itemvolume',1498,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":8,"upper":8.6360,"lower":3.8550,"count":871,"preSum":0},{"ndv":6,"upper":12.7460,"lower":9.5250,"count":1076,"preSum":871},{"ndv":42,"upper":67.3660,"lower":12.8450,"count":798,"preSum":1947},{"ndv":6,"upper":73.2270,"lower":67.5290,"count":1076,"preSum":2745},{"ndv":22,"upper":112.3820,"lower":74.1950,"count":1124,"preSum":3821},{"ndv":12,"upper":129.5300,"lower":115.8930,"count":838,"preSum":4945},{"ndv":2,"upper":132.6450,"lower":131.4400,"count":1070,"preSum":5783},{"ndv":5,"upper":136.8320,"lower":132.8250,"count":1255,"preSum":6853},{"ndv":5,"upper":145.6190,"lower":140.8330,"count":898,"preSum":8108},{"ndv":3,"upper":152.7550,"lower":147.1610,"count":925,"preSum":9006},{"ndv":4,"upper":175.0000,"lower":157.4490,"count":1433,"preSum":9931},{"ndv":19,"upper":224.4820,"lower":175.5450,"count":1024,"preSum":11364},{"ndv":2,"upper":229.4300,"lower":228.9750,"count":812,"preSum":12388},{"ndv":6,"upper":239.7780,"lower":230.4670,"count":1446,"preSum":13200},{"ndv":1,"upper":240.8700,"lower":240.8700,"count":935,"preSum":14646},{"ndv":15,"upper":279.1100,"lower":241.6030,"count":900,"preSum":15581},{"ndv":19,"upper":305.2500,"lower":281.5520,"count":1022,"preSum":16481},{"ndv":4,"upper":319.8530,"lower":306.1700,"count":875,"preSum":17503},{"ndv":10,"upper":331.6130,"lower":323.8510,"count":1199,"preSum":18378},{"ndv":25,"upper":376.9430,"lower":333.9470,"count":801,"preSum":19577},{"ndv":12,"upper":409.7410,"lower":381.3330,"count":880,"preSum":20378},{"ndv":4,"upper":423.3060,"lower":411.6660,"count":1390,"preSum":21258},{"ndv":15,"upper":460.2280,"lower":423.6440,"count":980,"preSum":22648},{"ndv":7,"upper":473.6160,"lower":461.9650,"count":805,"preSum":23628},{"ndv":9,"upper":493.2180,"lower":474.9410,"count":1759,"preSum":24433},{"ndv":5,"upper":504.6880,"lower":494.5350,"count":1089,"preSum":26192},{"ndv":12,"upper":530.1850,"lower":505.5980,"count":1661,"preSum":27281},{"ndv":2,"upper":536.2150,"lower":535.0120,"count":1003,"preSum":28942},{"ndv":6,"upper":545.4430,"lower":536.5470,"count":813,"preSum":29945},{"ndv":4,"upper":553.6000,"lower":549.4230,"count":859,"preSum":30758},{"ndv":7,"upper":565.7890,"lower":557.3480,"count":843,"preSum":31617},{"ndv":7,"upper":584.4300,"lower":570.4920,"count":1691,"preSum":32460},{"ndv":3,"upper":590.1210,"lower":585.0000,"count":1175,"preSum":34151},{"ndv":9,"upper":610.1650,"lower":591.8710,"count":997,"preSum":35326},{"ndv":3,"upper":613.1860,"lower":610.9900,"count":808,"preSum":36323},{"ndv":22,"upper":676.5450,"lower":614.7970,"count":1896,"preSum":37131},{"ndv":13,"upper":710.1980,"lower":685.8370,"count":837,"preSum":39027},{"ndv":6,"upper":741.5570,"lower":711.1930,"count":827,"preSum":39864},{"ndv":20,"upper":822.8510,"lower":743.9250,"count":1029,"preSum":40691},{"ndv":8,"upper":872.8270,"lower":829.6170,"count":1229,"preSum":41720},{"ndv":16,"upper":954.9410,"lower":876.8830,"count":1520,"preSum":42949},{"ndv":15,"upper":1081.1810,"lower":971.1700,"count":822,"preSum":44469},{"ndv":12,"upper":1231.2000,"lower":1089.4630,"count":818,"preSum":45291},{"ndv":7,"upper":1289.3400,"lower":1239.4840,"count":1137,"preSum":46109},{"ndv":19,"upper":2865.4170,"lower":1290.0190,"count":902,"preSum":47246},{"ndv":25,"upper":5150.4790,"lower":3008.6780,"count":1090,"preSum":48148},{"ndv":33,"upper":7197.6670,"lower":5185.1830,"count":869,"preSum":49238},{"ndv":64,"upper":460992.0000,"lower":7318.3590,"count":732,"preSum":50107}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[3714,2873,3324,2227,2525,1733,1781,1404,1375,3917,8765,2089,1449,2598],"valueArr":[0.0000,98.4050,128.0300,157.4480,220.3070,273.7080,289.7750,327.1360,554.1320,752.0080,762.7730,1175.1760,2204.4750,2580.8640],"type":"Double","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','itemweight',1689,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":29,"upper":5.6130,"lower":0.1000,"count":1079,"preSum":0},{"ndv":34,"upper":12.5000,"lower":5.7060,"count":1128,"preSum":1079},{"ndv":13,"upper":17.3610,"lower":12.6110,"count":1333,"preSum":2207},{"ndv":22,"upper":23.7500,"lower":17.5000,"count":1054,"preSum":3540},{"ndv":14,"upper":30.0000,"lower":25.0000,"count":1100,"preSum":4594},{"ndv":12,"upper":33.7500,"lower":30.2080,"count":1059,"preSum":5694},{"ndv":5,"upper":35.0000,"lower":34.0000,"count":1379,"preSum":6753},{"ndv":10,"upper":37.3890,"lower":35.4160,"count":1685,"preSum":8132},{"ndv":6,"upper":38.5710,"lower":37.5000,"count":1450,"preSum":9817},{"ndv":8,"upper":40.0000,"lower":38.8880,"count":1129,"preSum":11267},{"ndv":7,"upper":41.6670,"lower":40.3330,"count":1378,"preSum":12396},{"ndv":23,"upper":55.0000,"lower":42.2220,"count":1241,"preSum":13774},{"ndv":9,"upper":60.0000,"lower":56.0000,"count":1075,"preSum":15015},{"ndv":8,"upper":64.0000,"lower":60.4160,"count":1026,"preSum":16090},{"ndv":16,"upper":72.9160,"lower":64.1670,"count":1033,"preSum":17116},{"ndv":3,"upper":75.0000,"lower":73.0000,"count":1038,"preSum":18149},{"ndv":13,"upper":81.2500,"lower":76.0000,"count":1081,"preSum":19187},{"ndv":8,"upper":85.0000,"lower":82.1430,"count":1114,"preSum":20268},{"ndv":21,"upper":97.9130,"lower":85.3130,"count":1066,"preSum":21382},{"ndv":3,"upper":99.0000,"lower":97.9170,"count":1477,"preSum":22448},{"ndv":9,"upper":105.0000,"lower":100.0000,"count":1095,"preSum":23925},{"ndv":6,"upper":108.3330,"lower":105.5550,"count":1178,"preSum":25020},{"ndv":13,"upper":118.7500,"lower":109.0000,"count":1281,"preSum":26198},{"ndv":11,"upper":130.0000,"lower":120.8330,"count":1026,"preSum":27479},{"ndv":7,"upper":135.0000,"lower":131.0000,"count":1031,"preSum":28505},{"ndv":11,"upper":143.7500,"lower":135.4170,"count":1536,"preSum":29536},{"ndv":20,"upper":160.0000,"lower":144.0000,"count":1095,"preSum":31072},{"ndv":9,"upper":164.5830,"lower":160.4160,"count":1091,"preSum":32167},{"ndv":7,"upper":168.7500,"lower":165.0000,"count":1253,"preSum":33258},{"ndv":8,"upper":172.9170,"lower":169.0000,"count":1417,"preSum":34511},{"ndv":18,"upper":187.5000,"lower":174.0000,"count":1156,"preSum":35928},{"ndv":11,"upper":193.7500,"lower":188.0000,"count":1123,"preSum":37084},{"ndv":17,"upper":211.7500,"lower":195.8330,"count":1044,"preSum":38207},{"ndv":10,"upper":219.0000,"lower":212.5000,"count":1134,"preSum":39251},{"ndv":9,"upper":225.0000,"lower":220.0000,"count":1314,"preSum":40385},{"ndv":2,"upper":229.1660,"lower":227.0830,"count":1050,"preSum":41699},{"ndv":13,"upper":240.0000,"lower":229.1670,"count":1035,"preSum":42749},{"ndv":4,"upper":243.7500,"lower":241.6660,"count":1039,"preSum":43784},{"ndv":5,"upper":250.0000,"lower":245.0000,"count":1230,"preSum":44823},{"ndv":5,"upper":254.1660,"lower":251.0000,"count":1109,"preSum":46053},{"ndv":9,"upper":262.5000,"lower":254.1670,"count":1598,"preSum":47162},{"ndv":7,"upper":268.7500,"lower":264.5830,"count":1212,"preSum":48760},{"ndv":6,"upper":277.0830,"lower":269.0000,"count":1631,"preSum":49972},{"ndv":5,"upper":287.5000,"lower":279.1670,"count":1090,"preSum":51603},{"ndv":16,"upper":312.5000,"lower":289.0000,"count":1037,"preSum":52693},{"ndv":25,"upper":356.2500,"lower":314.5830,"count":1082,"preSum":53730},{"ndv":10,"upper":366.0000,"lower":358.3330,"count":1350,"preSum":54812},{"ndv":16,"upper":391.6670,"lower":366.6600,"count":1352,"preSum":56162},{"ndv":40,"upper":630.0000,"lower":393.7500,"count":1041,"preSum":57514},{"ndv":14,"upper":683.3330,"lower":633.7440,"count":1024,"preSum":58555},{"ndv":9,"upper":733.3330,"lower":687.5000,"count":1665,"preSum":59579},{"ndv":7,"upper":837.5000,"lower":763.0000,"count":1502,"preSum":61244},{"ndv":51,"upper":1300.0000,"lower":840.0000,"count":1380,"preSum":62746},{"ndv":54,"upper":1866.6670,"lower":1301.0000,"count":1079,"preSum":64126},{"ndv":21,"upper":18500.0000,"lower":1883.3330,"count":199,"preSum":65205}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[1444,1318,1668,1151,1458,1594,1190,1015,1139,1458,1011,2686,6073,2004],"valueArr":[0.0000,14.5830,37.7780,70.8330,86.0000,93.7500,114.5830,133.3330,147.9170,166.6670,175.0000,195.0000,210.4170,300.0000],"type":"Double","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','itemwidth',356,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":5,"upper":3.1000,"lower":0.0900,"count":319,"preSum":0},{"ndv":1,"upper":3.1900,"lower":3.1900,"count":556,"preSum":319},{"ndv":11,"upper":15.0000,"lower":3.8000,"count":540,"preSum":875},{"ndv":10,"upper":21.0000,"lower":15.1100,"count":402,"preSum":1415},{"ndv":2,"upper":22.0000,"lower":21.8000,"count":822,"preSum":1817},{"ndv":5,"upper":23.5900,"lower":22.8000,"count":409,"preSum":2639},{"ndv":8,"upper":24.9200,"lower":23.9000,"count":322,"preSum":3048},{"ndv":2,"upper":25.5000,"lower":25.1000,"count":526,"preSum":3370},{"ndv":7,"upper":27.0000,"lower":25.5200,"count":721,"preSum":3896},{"ndv":7,"upper":29.0000,"lower":27.2800,"count":890,"preSum":4617},{"ndv":2,"upper":29.4000,"lower":29.2000,"count":384,"preSum":5507},{"ndv":3,"upper":30.0000,"lower":29.8000,"count":924,"preSum":5891},{"ndv":2,"upper":30.5000,"lower":30.3000,"count":320,"preSum":6815},{"ndv":1,"upper":30.7400,"lower":30.7400,"count":429,"preSum":7135},{"ndv":3,"upper":33.0000,"lower":32.0000,"count":321,"preSum":7564},{"ndv":1,"upper":34.0000,"lower":34.0000,"count":519,"preSum":7885},{"ndv":6,"upper":37.0000,"lower":34.5000,"count":764,"preSum":8404},{"ndv":3,"upper":37.7900,"lower":37.0700,"count":401,"preSum":9168},{"ndv":1,"upper":38.0000,"lower":38.0000,"count":503,"preSum":9569},{"ndv":7,"upper":40.0000,"lower":38.3500,"count":475,"preSum":10072},{"ndv":1,"upper":41.0000,"lower":41.0000,"count":612,"preSum":10547},{"ndv":2,"upper":42.0000,"lower":41.5000,"count":591,"preSum":11159},{"ndv":1,"upper":43.0000,"lower":43.0000,"count":388,"preSum":11750},{"ndv":5,"upper":45.0000,"lower":43.0300,"count":732,"preSum":12138},{"ndv":4,"upper":48.0000,"lower":46.0000,"count":658,"preSum":12870},{"ndv":4,"upper":51.0000,"lower":49.0000,"count":394,"preSum":13528},{"ndv":2,"upper":54.0000,"lower":53.0000,"count":948,"preSum":13922},{"ndv":2,"upper":55.0000,"lower":54.3600,"count":321,"preSum":14870},{"ndv":7,"upper":61.0000,"lower":56.5000,"count":425,"preSum":15191},{"ndv":10,"upper":66.0000,"lower":61.9000,"count":826,"preSum":15616},{"ndv":1,"upper":67.0000,"lower":67.0000,"count":484,"preSum":16442},{"ndv":9,"upper":72.0000,"lower":67.2900,"count":1011,"preSum":16926},{"ndv":2,"upper":75.0000,"lower":73.0000,"count":340,"preSum":17937},{"ndv":2,"upper":77.0000,"lower":76.0000,"count":482,"preSum":18277},{"ndv":13,"upper":126.0000,"lower":80.0000,"count":319,"preSum":18759},{"ndv":8,"upper":175.0000,"lower":139.0000,"count":333,"preSum":19078},{"ndv":10,"upper":218.0000,"lower":178.0000,"count":329,"preSum":19411},{"ndv":7,"upper":235.0000,"lower":220.0000,"count":333,"preSum":19740},{"ndv":6,"upper":455.0000,"lower":239.0000,"count":90,"preSum":20073}],"maxBucketSize":64,"type":"Double","sampleRate":1.0}','{"countArr":[44804,1349,973,1497,3486,1037,1705,2835,1777,2267,1452,2078,2811,2379],"valueArr":[0.0000,3.5900,7.0000,25.0000,25.2000,25.5300,31.0000,35.0000,36.0000,38.3000,47.0000,50.0000,56.0000,74.0000],"type":"Double","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','lastupdated',976467,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":982,"upper":"1850483148731711488","lower":"1850357916578611200","count":1391,"preSum":0},{"ndv":1072,"upper":"1850710217981952000","lower":"1850483149033701376","count":1391,"preSum":1391},{"ndv":1073,"upper":"1850828385970814976","lower":"1850710348072484864","count":1398,"preSum":2782},{"ndv":674,"upper":"1850854738799624192","lower":"1850828423501447168","count":1401,"preSum":4180},{"ndv":967,"upper":"1850888028000616448","lower":"1850854738950619136","count":1391,"preSum":5581},{"ndv":1056,"upper":"1850925216897695744","lower":"1850888028034170880","count":1391,"preSum":6972},{"ndv":1249,"upper":"1850942752276086784","lower":"1850925217602338816","count":1391,"preSum":8363},{"ndv":1033,"upper":"1850953834231234560","lower":"1850942752326418432","count":1435,"preSum":9754},{"ndv":594,"upper":"1850958230834905088","lower":"1850953860672126976","count":1410,"preSum":11189},{"ndv":910,"upper":"1850962421917679616","lower":"1850958234727219200","count":1399,"preSum":12599},{"ndv":909,"upper":"1850965383498956800","lower":"1850962466125643776","count":1391,"preSum":13998},{"ndv":991,"upper":"1850969431438524416","lower":"1850965383566065664","count":1391,"preSum":15389},{"ndv":730,"upper":"1850971618667397120","lower":"1850969434575863808","count":1391,"preSum":16780},{"ndv":747,"upper":"1850973755598176256","lower":"1850971621620187136","count":1410,"preSum":18171},{"ndv":914,"upper":"1850982251110596608","lower":"1850973755614953472","count":1405,"preSum":19581},{"ndv":695,"upper":"1850984477178724352","lower":"1850982255623667712","count":1398,"preSum":20986},{"ndv":921,"upper":"1850986647898816512","lower":"1850984477229056000","count":1395,"preSum":22384},{"ndv":251,"upper":"1850986983845789696","lower":"1850986648670568448","count":1409,"preSum":23779},{"ndv":579,"upper":"1850988836805410816","lower":"1850986984097447936","count":1410,"preSum":25188},{"ndv":373,"upper":"1850989233888559104","lower":"1850988840479621120","count":1395,"preSum":26598},{"ndv":900,"upper":"1850991501178306560","lower":"1850989234274435072","count":1398,"preSum":27993},{"ndv":935,"upper":"1850995432029683712","lower":"1850991501362855936","count":1396,"preSum":29391},{"ndv":760,"upper":"1850997766092750848","lower":"1850995432247787520","count":1391,"preSum":30787},{"ndv":893,"upper":"1851000348794159104","lower":"1850997766377963520","count":1391,"preSum":32178},{"ndv":1008,"upper":"1851002746509983744","lower":"1851000348844490752","count":1391,"preSum":33569},{"ndv":907,"upper":"1851006496737853440","lower":"1851002746543538176","count":1391,"preSum":34960},{"ndv":810,"upper":"1851008740975706112","lower":"1851006496838516736","count":1391,"preSum":36351},{"ndv":857,"upper":"1851010971741454336","lower":"1851008740992483328","count":1391,"preSum":37742},{"ndv":906,"upper":"1851013613632880640","lower":"1851010972227993600","count":1395,"preSum":39133},{"ndv":855,"upper":"1851015918218379264","lower":"1851013615545483264","count":1391,"preSum":40528},{"ndv":551,"upper":"1851017853604462592","lower":"1851015918268710912","count":1392,"preSum":41919},{"ndv":923,"upper":"1851019972214521856","lower":"1851017855030525952","count":1391,"preSum":43311},{"ndv":911,"upper":"1851022354478530560","lower":"1851019972315185152","count":1391,"preSum":44702},{"ndv":673,"upper":"1851026269425106944","lower":"1851022356407910400","count":1408,"preSum":46093},{"ndv":597,"upper":"1851028411523268608","lower":"1851026270683398144","count":1425,"preSum":47501},{"ndv":871,"upper":"1851030736962846720","lower":"1851028432712892416","count":1391,"preSum":48926},{"ndv":1022,"upper":"1851033275791835136","lower":"1851030737684267008","count":1402,"preSum":50317},{"ndv":848,"upper":"1851037380354506752","lower":"1851033278778179584","count":1391,"preSum":51719},{"ndv":871,"upper":"1851039856436707328","lower":"1851037380388061184","count":1436,"preSum":53110},{"ndv":479,"upper":"1851043883505418240","lower":"1851039856654811136","count":1397,"preSum":54546},{"ndv":403,"upper":"1851044725738438656","lower":"1851043884763709440","count":1444,"preSum":55943},{"ndv":416,"upper":"1851046737645404160","lower":"1851044731593687040","count":1391,"preSum":57387},{"ndv":939,"upper":"1851049115379564544","lower":"1851046737678958592","count":1392,"preSum":58778},{"ndv":257,"upper":"1851052109374423040","lower":"1851049115413118976","count":1423,"preSum":60170},{"ndv":352,"upper":"1851052457451323392","lower":"1851052109391200256","count":1404,"preSum":61593},{"ndv":345,"upper":"1851052784841916416","lower":"1851052483573448704","count":1391,"preSum":62997},{"ndv":461,"upper":"1851053130502897664","lower":"1851052784925802496","count":1418,"preSum":64388},{"ndv":448,"upper":"1851053465023807488","lower":"1851053131375312896","count":1405,"preSum":65806},{"ndv":592,"upper":"1851054909709877248","lower":"1851053465158025216","count":1421,"preSum":67211},{"ndv":836,"upper":"1851055475991248896","lower":"1851054909793763328","count":1391,"preSum":68632},{"ndv":840,"upper":"1851057201678909440","lower":"1851055476494565376","count":1395,"preSum":70023},{"ndv":863,"upper":"1851059234490286080","lower":"1851057202148671488","count":1400,"preSum":71418},{"ndv":880,"upper":"1851059931986264064","lower":"1851059235144597504","count":1391,"preSum":72818},{"ndv":730,"upper":"1851063877802917888","lower":"1851059935157157888","count":1405,"preSum":74209},{"ndv":934,"upper":"1851065958597132288","lower":"1851063893019852800","count":1404,"preSum":75614},{"ndv":1017,"upper":"1851068633053134848","lower":"1851065958983008256","count":1404,"preSum":77018},{"ndv":852,"upper":"1851070908010070016","lower":"1851068638186962944","count":1391,"preSum":78422},{"ndv":946,"upper":"1851074628575821824","lower":"1851070912523141120","count":1391,"preSum":79813},{"ndv":853,"upper":"1851076856539774976","lower":"1851074628693262336","count":1400,"preSum":81204},{"ndv":1011,"upper":"1851079198051926016","lower":"1851076856774656000","count":1391,"preSum":82604},{"ndv":1066,"upper":"1851081476431413248","lower":"1851079200904052736","count":1391,"preSum":83995},{"ndv":986,"upper":"1851083855574859776","lower":"1851081477068947456","count":1409,"preSum":85386},{"ndv":572,"upper":"1851085655048716288","lower":"1851083863963467776","count":1406,"preSum":86795},{"ndv":441,"upper":"1851086480085090304","lower":"1851085658672594944","count":803,"preSum":88201}],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}','{"countArr":[124,104,111,95,139,125,131,165,118,121,92,103,89,92],"valueArr":[1850956333113671680,1850988801187381248,1851004691677184000,1851018158161264640,1851046371197452288,1851049180139618304,1851049254999556096,1851052311070113792,1851052775329234944,1851052778466574336,1851053178250854400,1851064264735850496,1851072405963800576,1851072456932982784],"type":"Timestamp","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','lastupdatedby',545,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"000002","lower":"000002","count":1009,"preSum":0},{"ndv":1,"upper":"000003","lower":"000003","count":1463,"preSum":1009},{"ndv":1,"upper":"000004","lower":"000004","count":1199,"preSum":2472},{"ndv":5,"upper":"000088","lower":"000005","count":352,"preSum":3671},{"ndv":12,"upper":"0220012","lower":"000089","count":363,"preSum":4023},{"ndv":5,"upper":"0220017","lower":"0220013","count":372,"preSum":4386},{"ndv":9,"upper":"02700001","lower":"0220018","count":608,"preSum":4758},{"ndv":1,"upper":"02700003","lower":"02700003","count":843,"preSum":5366},{"ndv":1,"upper":"02700009","lower":"02700009","count":1026,"preSum":6209},{"ndv":9,"upper":"02700028","lower":"02700020","count":370,"preSum":7235},{"ndv":21,"upper":"10000007","lower":"02700029","count":400,"preSum":7605},{"ndv":5,"upper":"10000016","lower":"10000012","count":422,"preSum":8005},{"ndv":4,"upper":"1000005","lower":"10000022","count":345,"preSum":8427},{"ndv":7,"upper":"1000012","lower":"1000006","count":356,"preSum":8772},{"ndv":10,"upper":"1000017","lower":"1000013","count":395,"preSum":9128},{"ndv":5,"upper":"10003","lower":"1000018","count":1735,"preSum":9523},{"ndv":2,"upper":"10005","lower":"10004","count":538,"preSum":11258},{"ndv":3,"upper":"10008","lower":"10006","count":404,"preSum":11796},{"ndv":1,"upper":"10009","lower":"10009","count":368,"preSum":12200},{"ndv":21,"upper":"41512820","lower":"10103","count":398,"preSum":12568},{"ndv":16,"upper":"42043184","lower":"41762241","count":384,"preSum":12966},{"ndv":9,"upper":"42145422","lower":"42080021","count":346,"preSum":13350},{"ndv":4,"upper":"42196770","lower":"42152732","count":1562,"preSum":13696},{"ndv":17,"upper":"57302020","lower":"42196820","count":341,"preSum":15258},{"ndv":9,"upper":"BXH","lower":"57302021","count":384,"preSum":15599},{"ndv":4,"upper":"gth","lower":"CN","count":378,"preSum":15983},{"ndv":1,"upper":"hxy","lower":"hxy","count":1016,"preSum":16361},{"ndv":5,"upper":"LL","lower":"JQQ","count":575,"preSum":17377},{"ndv":4,"upper":"lyg","lower":"LQ101","count":954,"preSum":17952},{"ndv":9,"upper":"YBJ","lower":"MLP","count":367,"preSum":18906},{"ndv":2,"upper":"yxy","lower":"yj","count":1526,"preSum":19273},{"ndv":5,"upper":"ZHC01","lower":"YYJ","count":473,"preSum":20799},{"ndv":3,"upper":"ZRX","lower":"zjf","count":498,"preSum":21272},{"ndv":1,"upper":"ZXL","lower":"ZXL","count":2,"preSum":21770}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[2728,4180,1561,2097,7860,2632,2187,1938,2988,2941,3298,6936,9393,18102],"valueArr":["000001","0220005","0220006","02700005","02700010","10000002","10000004","10001","40401644","40721814","41157743","41509297","41580109","42008280"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','lot',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','lpn',18591,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":14,"upper":"0220903680002","lower":",","count":18,"preSum":0},{"ndv":14,"upper":"0220909HB0005","lower":"0220903680003","count":18,"preSum":18},{"ndv":18,"upper":"0220914V00011","lower":"0220911590002","count":18,"preSum":36},{"ndv":16,"upper":"0220917HV0002","lower":"0220915830015","count":18,"preSum":54},{"ndv":17,"upper":"0220921HB0009","lower":"0220917S30028","count":18,"preSum":72},{"ndv":15,"upper":"0220927880016","lower":"0220921HY0002","count":18,"preSum":90},{"ndv":14,"upper":"0221006HA0007","lower":"0220927HH0012","count":18,"preSum":108},{"ndv":18,"upper":"0221009650002","lower":"0221006HA0013","count":18,"preSum":126},{"ndv":16,"upper":"0221015HQ0014","lower":"0221009HQ0005","count":18,"preSum":144},{"ndv":17,"upper":"0221018HA0019","lower":"0221015HR0002","count":18,"preSum":162},{"ndv":15,"upper":"0221021HG0012","lower":"0221018HA0022","count":18,"preSum":180},{"ndv":17,"upper":"0221024610009","lower":"0221021HG0013","count":18,"preSum":198},{"ndv":18,"upper":"0221024T40014","lower":"0221024L20003","count":18,"preSum":216},{"ndv":16,"upper":"0221025T30012","lower":"0221024T50038","count":18,"preSum":234},{"ndv":17,"upper":"0221028T50026","lower":"0221025T50007","count":18,"preSum":252},{"ndv":16,"upper":"0221101790002","lower":"0221028T50027","count":18,"preSum":270},{"ndv":17,"upper":"0221104S70003","lower":"0221101880010","count":18,"preSum":288},{"ndv":16,"upper":"0221108700006","lower":"0221105HA0002","count":18,"preSum":306},{"ndv":17,"upper":"0221114HR0005","lower":"0221108790025","count":18,"preSum":324},{"ndv":17,"upper":"0221117HX0001","lower":"0221114L20002","count":19,"preSum":342},{"ndv":17,"upper":"0221122HR0006","lower":"0221117T10006","count":19,"preSum":361},{"ndv":16,"upper":"0221126HF0012","lower":"0221122HR0009","count":18,"preSum":380},{"ndv":18,"upper":"0221129L40003","lower":"0221126HF0015","count":18,"preSum":398},{"ndv":18,"upper":"0221130550007","lower":"0221129L40008","count":18,"preSum":416},{"ndv":18,"upper":"0221130T30024","lower":"0221130550008","count":18,"preSum":434},{"ndv":18,"upper":"0221201T30014","lower":"0221130T30025","count":18,"preSum":452},{"ndv":18,"upper":"0221203L40066","lower":"0221201T30016","count":18,"preSum":470},{"ndv":18,"upper":"0221209L40069","lower":"0221203L40110","count":18,"preSum":488},{"ndv":18,"upper":"0221212HV0006","lower":"0221209L40076","count":18,"preSum":506},{"ndv":15,"upper":"0221216T50014","lower":"0221212L40001","count":18,"preSum":524},{"ndv":17,"upper":"0221224T20001","lower":"0221216T50034","count":18,"preSum":542},{"ndv":18,"upper":"0230109HZ0003","lower":"0221225T30001","count":18,"preSum":560},{"ndv":16,"upper":"0230129HA0008","lower":"0230109L30064","count":19,"preSum":578},{"ndv":17,"upper":"0230213HI0001","lower":"0230129HA0015","count":18,"preSum":597},{"ndv":14,"upper":"0230222L40008","lower":"0230213HI0011","count":18,"preSum":615},{"ndv":16,"upper":"0230302T50020","lower":"0230222T30033","count":18,"preSum":633},{"ndv":17,"upper":"0230309550008","lower":"0230302T50025","count":18,"preSum":651},{"ndv":16,"upper":"0230311L40048","lower":"0230309HU0002","count":18,"preSum":669},{"ndv":17,"upper":"0230316L20002","lower":"0230311L40051","count":19,"preSum":687},{"ndv":17,"upper":"0230320L40103","lower":"0230317S70028","count":18,"preSum":706},{"ndv":18,"upper":"0230324L20004","lower":"0230320L40111","count":18,"preSum":724},{"ndv":18,"upper":"0230330HY0014","lower":"0230324L20007","count":18,"preSum":742},{"ndv":17,"upper":"0230401HR0002","lower":"0230330HY0020","count":18,"preSum":760},{"ndv":17,"upper":"0230403L50003","lower":"0230401HR0009","count":18,"preSum":778},{"ndv":13,"upper":"0230407L20003","lower":"0230404510005","count":18,"preSum":796},{"ndv":18,"upper":"0230411HH0002","lower":"0230408690001","count":18,"preSum":814},{"ndv":17,"upper":"0230413550014","lower":"0230411HH0010","count":18,"preSum":832},{"ndv":17,"upper":"0230422L10003","lower":"0230413HH0012","count":18,"preSum":850},{"ndv":16,"upper":"0230429HF0010","lower":"0230423HA0004","count":18,"preSum":868},{"ndv":16,"upper":"0230505HF0008","lower":"0230503HB0009","count":18,"preSum":886},{"ndv":15,"upper":"0230509L20002","lower":"0230505S30004","count":18,"preSum":904},{"ndv":16,"upper":"0230517L40050","lower":"0230509T20043","count":18,"preSum":922},{"ndv":12,"upper":"0290131Q00001","lower":"0230518HA0008","count":19,"preSum":940},{"ndv":17,"upper":"12162","lower":"0521028HY0010","count":18,"preSum":959},{"ndv":18,"upper":"12836","lower":"1221101HW0001","count":18,"preSum":977},{"ndv":15,"upper":"13255","lower":"13","count":19,"preSum":995},{"ndv":15,"upper":"14359","lower":"13297","count":18,"preSum":1014},{"ndv":15,"upper":"15193","lower":"14370","count":18,"preSum":1032},{"ndv":15,"upper":"15566","lower":"15194","count":18,"preSum":1050},{"ndv":15,"upper":"16262","lower":"1561","count":19,"preSum":1068},{"ndv":12,"upper":"16360","lower":"16270","count":20,"preSum":1087},{"ndv":17,"upper":"821319","lower":"16376","count":18,"preSum":1107},{"ndv":7,"upper":"o64664","lower":"82565","count":11,"preSum":1125}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[4,4,4,4,6,1157,5,5,7,16,4,4,4],"valueArr":["021DCQQ-SS03-08-136","0221010540001","0230217L20002","0230223L20004","0230309HU0005","1","16311","16434","16479","2","2435","5","760"],"type":"String","sampleRate":1.0}',88253,0.007226729),('jala_wms_prod','shipping_container_detail','manufacturedate',2903,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":246,"upper":"1849521494430842880","lower":"-1","count":1271,"preSum":0},{"ndv":106,"upper":"1849901925454053376","lower":"1849523693454098432","count":1233,"preSum":1271},{"ndv":88,"upper":"1850157012151697408","lower":"1849904124477308928","count":1256,"preSum":2504},{"ndv":22,"upper":"1850214186756341760","lower":"1850159211174952960","count":1239,"preSum":3760},{"ndv":26,"upper":"1850277958430752768","lower":"1850216385779597312","count":1489,"preSum":4999},{"ndv":26,"upper":"1850343929128419328","lower":"1850280157454008320","count":1243,"preSum":6488},{"ndv":23,"upper":"1850398904709808128","lower":"1850348327174930432","count":1273,"preSum":7731},{"ndv":8,"upper":"1850425292988874752","lower":"1850401103733063680","count":1344,"preSum":9004},{"ndv":5,"upper":"1850436288105152512","lower":"1850427492012130304","count":1318,"preSum":10348},{"ndv":8,"upper":"1850453880291196928","lower":"1850438487128408064","count":1363,"preSum":11666},{"ndv":3,"upper":"1850460477360963584","lower":"1850456079314452480","count":1304,"preSum":13029},{"ndv":3,"upper":"1850467074430730240","lower":"1850462676384219136","count":1460,"preSum":14333},{"ndv":4,"upper":"1850475870523752448","lower":"1850469273453985792","count":1395,"preSum":15793},{"ndv":5,"upper":"1850489064663285760","lower":"1850478069547008000","count":1386,"preSum":17188},{"ndv":4,"upper":"1850497860756307968","lower":"1850491263686541312","count":1258,"preSum":18574},{"ndv":4,"upper":"1850506656849330176","lower":"1850500059779563520","count":1614,"preSum":19832},{"ndv":5,"upper":"1850517651965607936","lower":"1850508855872585728","count":1335,"preSum":21446},{"ndv":3,"upper":"1850524249035374592","lower":"1850519850988863488","count":1530,"preSum":22781},{"ndv":3,"upper":"1850530846105141248","lower":"1850526448058630144","count":1289,"preSum":24311},{"ndv":4,"upper":"1850539642198163456","lower":"1850533045128396800","count":1627,"preSum":25600},{"ndv":4,"upper":"1850548438291185664","lower":"1850541841221419008","count":1220,"preSum":27227},{"ndv":5,"upper":"1850566030477230080","lower":"1850550637314441216","count":1381,"preSum":28447},{"ndv":5,"upper":"1850577025593507840","lower":"1850568229500485632","count":1541,"preSum":29828},{"ndv":7,"upper":"1850592418756296704","lower":"1850579224616763392","count":1408,"preSum":31369},{"ndv":6,"upper":"1850605612895830016","lower":"1850594617779552256","count":1400,"preSum":32777},{"ndv":7,"upper":"1850621006058618880","lower":"1850607811919085568","count":1561,"preSum":34177},{"ndv":6,"upper":"1850708966988840960","lower":"1850623205081874432","count":1374,"preSum":35738},{"ndv":3,"upper":"1850715564058607616","lower":"1850711166012096512","count":1283,"preSum":37112},{"ndv":12,"upper":"1850761743546974208","lower":"1850717763081863168","count":1434,"preSum":38395},{"ndv":6,"upper":"1850777136709763072","lower":"1850763942570229760","count":1249,"preSum":39829},{"ndv":5,"upper":"1850790330849296384","lower":"1850781534756274176","count":1278,"preSum":41078},{"ndv":7,"upper":"1850805724012085248","lower":"1850792529872551936","count":1252,"preSum":42356},{"ndv":11,"upper":"1850829913267896320","lower":"1850807923035340800","count":1743,"preSum":43608},{"ndv":4,"upper":"1850847505453940736","lower":"1850840908384174080","count":1478,"preSum":45351},{"ndv":3,"upper":"1850854102523707392","lower":"1850849704477196288","count":1501,"preSum":46829},{"ndv":3,"upper":"1850860699593474048","lower":"1850856301546962944","count":1234,"preSum":48330},{"ndv":3,"upper":"1850867296663240704","lower":"1850862898616729600","count":1256,"preSum":49564},{"ndv":3,"upper":"1850873893733007360","lower":"1850869495686496256","count":1353,"preSum":50820},{"ndv":3,"upper":"1850880490802774016","lower":"1850876092756262912","count":1359,"preSum":52173},{"ndv":3,"upper":"1850887087872540672","lower":"1850882689826029568","count":1696,"preSum":53532},{"ndv":3,"upper":"1850893684942307328","lower":"1850889286895796224","count":1835,"preSum":55228},{"ndv":5,"upper":"1850906879081840640","lower":"1850898082988818432","count":1460,"preSum":57063},{"ndv":3,"upper":"1850917874198118400","lower":"1850911277128351744","count":1580,"preSum":58523},{"ndv":4,"upper":"1850926670291140608","lower":"1850920073221373952","count":1589,"preSum":60103},{"ndv":2,"upper":"1850933267360907264","lower":"1850928869314396160","count":1232,"preSum":61692},{"ndv":2,"upper":"1850939864430673920","lower":"1850937665407418368","count":1227,"preSum":62924},{"ndv":3,"upper":"1850953058570207232","lower":"1850944262477185024","count":1745,"preSum":64151},{"ndv":3,"upper":"1850961854663229440","lower":"1850957456616718336","count":1313,"preSum":65896},{"ndv":2,"upper":"1850966252709740544","lower":"1850964053686484992","count":1337,"preSum":67209},{"ndv":2,"upper":"1850972849779507200","lower":"1850970650756251648","count":1221,"preSum":68546},{"ndv":4,"upper":"1850990441965551616","lower":"1850975048802762752","count":1761,"preSum":69767},{"ndv":3,"upper":"1851001437081829376","lower":"1850992640988807168","count":1639,"preSum":71528},{"ndv":3,"upper":"1851010233174851584","lower":"1851003636105084928","count":1233,"preSum":73167},{"ndv":4,"upper":"1851019029267873792","lower":"1851012432198107136","count":1248,"preSum":74400},{"ndv":8,"upper":"1851036621453918208","lower":"1851021228291129344","count":1221,"preSum":75648},{"ndv":126,"upper":"1854577048895356928","lower":"1851038820477173760","count":1155,"preSum":76869}],"maxBucketSize":64,"type":"Date","sampleRate":1.0}','{"countArr":[909,889,857,1283,769,892,782,781,1017,861,1060,768,823,898],"valueArr":[1850561632430718976,1850895883965562880,1850915675174862848,1850931068337651712,1850935466384162816,1850942063453929472,1850948660523696128,1850950859546951680,1850955257593462784,1850968451732996096,1850988242942296064,1850994840012062720,1850999238058573824,1851005835128340480],"type":"Date","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','originalpickloc',37631,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":50,"upper":"021DCQQ-M11-01-02-04","lower":"021DCQQ-M03-13","count":1216,"preSum":0},{"ndv":194,"upper":"022DCX-1A-02A29","lower":"021DCQQ-M11-01-03-03","count":1211,"preSum":1216},{"ndv":447,"upper":"022DCX-1D-01A14","lower":"022DCX-1A-02A41","count":1212,"preSum":2427},{"ndv":83,"upper":"022DCX-1D-04A02","lower":"022DCX-1D-01A15","count":1218,"preSum":3639},{"ndv":89,"upper":"022DCX-1D-06A24","lower":"022DCX-1D-04A03","count":1213,"preSum":4857},{"ndv":85,"upper":"022DCX-1D-08A41","lower":"022DCX-1D-06A25","count":1211,"preSum":6070},{"ndv":72,"upper":"022DCX-1D-13A16","lower":"022DCX-1D-08A42","count":1286,"preSum":7281},{"ndv":365,"upper":"1A-11A019","lower":"022DCX-1E-04A11","count":1212,"preSum":8567},{"ndv":389,"upper":"1P-01A008","lower":"1A-11A022","count":1234,"preSum":9779},{"ndv":69,"upper":"1P-05A002","lower":"1P-01A009","count":1397,"preSum":11013},{"ndv":8,"upper":"1P-05A010","lower":"1P-05A003","count":1395,"preSum":12410},{"ndv":11,"upper":"1P-05A023","lower":"1P-05A011","count":1523,"preSum":13805},{"ndv":18,"upper":"1P-05A041","lower":"1P-05A024","count":1336,"preSum":15328},{"ndv":9,"upper":"1P-06A008","lower":"1P-05A042","count":1602,"preSum":16664},{"ndv":8,"upper":"1P-06A019","lower":"1P-06A009","count":1397,"preSum":18266},{"ndv":4,"upper":"1P-06A023","lower":"1P-06A020","count":1448,"preSum":19663},{"ndv":5,"upper":"1P-06A032","lower":"1P-06A026","count":1436,"preSum":21111},{"ndv":8,"upper":"1P-06A040","lower":"1P-06A033","count":1482,"preSum":22547},{"ndv":8,"upper":"1P-07A005","lower":"1P-06A041","count":1296,"preSum":24029},{"ndv":16,"upper":"1P-07A023","lower":"1P-07A006","count":1214,"preSum":25325},{"ndv":16,"upper":"1P-07A039","lower":"1P-07A024","count":1224,"preSum":26539},{"ndv":33,"upper":"1P-08A030","lower":"1P-07A041","count":1248,"preSum":27763},{"ndv":122,"upper":"1Q-03D026","lower":"1P-08A031","count":1213,"preSum":29011},{"ndv":120,"upper":"1Q-06A001","lower":"1Q-03D029","count":1298,"preSum":30224},{"ndv":14,"upper":"1Q-06A022","lower":"1Q-06A002","count":1243,"preSum":31522},{"ndv":81,"upper":"1Q-07A081","lower":"1Q-06A024","count":1214,"preSum":32765},{"ndv":12,"upper":"1Q-07A094","lower":"1Q-07A082","count":1502,"preSum":33979},{"ndv":215,"upper":"1Q-08E096","lower":"1Q-07A095","count":1259,"preSum":35481},{"ndv":162,"upper":"1Q-10A014","lower":"1Q-09A001","count":1230,"preSum":36740},{"ndv":150,"upper":"1Q-10E083","lower":"1Q-10A017","count":1275,"preSum":37970},{"ndv":25,"upper":"1Q-11A035","lower":"1Q-10E084","count":1214,"preSum":39245},{"ndv":16,"upper":"1Q-11A085","lower":"1Q-11A036","count":1262,"preSum":40459},{"ndv":50,"upper":"1Q-12A038","lower":"1Q-11A086","count":1232,"preSum":41721},{"ndv":17,"upper":"1Q-12A092","lower":"1Q-12A047","count":1274,"preSum":42953},{"ndv":30,"upper":"1Q-12E085","lower":"1Q-12A093","count":1225,"preSum":44227},{"ndv":24,"upper":"1Q-13A060","lower":"1Q-12E089","count":1226,"preSum":45452},{"ndv":30,"upper":"1Q-13E073","lower":"1Q-13A061","count":1215,"preSum":46678},{"ndv":271,"upper":"2C-AA08-0000","lower":"1Q-13E074","count":1236,"preSum":47893},{"ndv":138,"upper":"2C-AD08-0103","lower":"2C-AA10-0000","count":1216,"preSum":49129},{"ndv":172,"upper":"2C-AL01-0000","lower":"2C-AD08-0202","count":1215,"preSum":50345},{"ndv":327,"upper":"763DCA-2C-01B057","lower":"2C-AL02-0000","count":1211,"preSum":51560},{"ndv":340,"upper":"763DCA-2I-01A11","lower":"763DCA-2C-01B058","count":1215,"preSum":52771},{"ndv":37,"upper":"763DCA-2I-02A10","lower":"763DCA-2I-01A12","count":1227,"preSum":53986},{"ndv":28,"upper":"763DCA-2I-03A02","lower":"763DCA-2I-02A11","count":1249,"preSum":55213},{"ndv":55,"upper":"763DCA-2I-04A24","lower":"763DCA-2I-03A03","count":1228,"preSum":56462},{"ndv":62,"upper":"763DCA-2I-06A17","lower":"763DCA-2I-04A25","count":1212,"preSum":57690},{"ndv":231,"upper":"A0117","lower":"763DCA-2I-06A18","count":1212,"preSum":58902},{"ndv":333,"upper":"B-04-068","lower":"A0118","count":1211,"preSum":60114},{"ndv":295,"upper":"BLS-07-A02","lower":"B-04-070","count":1251,"preSum":61325},{"ndv":118,"upper":"BLS-19-A04","lower":"BLS-07-A03","count":1213,"preSum":62576},{"ndv":256,"upper":"BT1-08-A34","lower":"BLS-19-A21","count":1211,"preSum":63789},{"ndv":439,"upper":"CH-0319A4","lower":"BT1-08-A34-01","count":1216,"preSum":65000},{"ndv":295,"upper":"CLS-06-A28","lower":"CH-0319C4","count":1217,"preSum":66216},{"ndv":77,"upper":"CT-07-A02","lower":"CLS-06-A31","count":1346,"preSum":67433},{"ndv":34,"upper":"CT-08-A05","lower":"CT-07-A03","count":1217,"preSum":68779},{"ndv":62,"upper":"CT-09-A13","lower":"CT-08-A06","count":1221,"preSum":69996},{"ndv":51,"upper":"CT-10-A20","lower":"CT-09-A14","count":1296,"preSum":71217},{"ndv":38,"upper":"CT-11-A33","lower":"CT-10-A21","count":1328,"preSum":72513},{"ndv":99,"upper":"D-02-092","lower":"CT-11-A34","count":1211,"preSum":73841},{"ndv":433,"upper":"H03-01-05","lower":"D-02-097","count":1211,"preSum":75052},{"ndv":188,"upper":"ZWY001","lower":"H03-02-02","count":1190,"preSum":76263}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[847,587,978,674,704,721,838,584,649,1058,695,851,1062,2912],"valueArr":["1P-05A022","1P-05A044","1P-06A003","1P-06A012","1P-06A014","1P-06A016","1P-06A024","1P-06A025","1P-06A028","1P-06A043","1P-07A013","1Q-07A087","763DCA-2C-YB01","YSDD-01A001"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','packingclass',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','packingcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[90613],"valueArr":["STD"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','plqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[90613],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','processstamp',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','qtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[90613],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','quantity',5263,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":0,"lower":0,"count":45,"preSum":0},{"ndv":1,"upper":11,"lower":11,"count":57,"preSum":45},{"ndv":1,"upper":13,"lower":13,"count":42,"preSum":102},{"ndv":1,"upper":14,"lower":14,"count":45,"preSum":144},{"ndv":1,"upper":15,"lower":15,"count":70,"preSum":189},{"ndv":1,"upper":16,"lower":16,"count":63,"preSum":259},{"ndv":2,"upper":19,"lower":17,"count":54,"preSum":322},{"ndv":1,"upper":20,"lower":20,"count":90,"preSum":376},{"ndv":2,"upper":22,"lower":21,"count":56,"preSum":466},{"ndv":2,"upper":25,"lower":23,"count":47,"preSum":522},{"ndv":4,"upper":29,"lower":26,"count":47,"preSum":569},{"ndv":1,"upper":30,"lower":30,"count":64,"preSum":616},{"ndv":4,"upper":34,"lower":31,"count":48,"preSum":680},{"ndv":2,"upper":36,"lower":35,"count":79,"preSum":728},{"ndv":4,"upper":40,"lower":37,"count":57,"preSum":807},{"ndv":3,"upper":43,"lower":41,"count":48,"preSum":864},{"ndv":6,"upper":50,"lower":44,"count":66,"preSum":912},{"ndv":10,"upper":60,"lower":51,"count":60,"preSum":978},{"ndv":10,"upper":71,"lower":61,"count":44,"preSum":1038},{"ndv":3,"upper":74,"lower":72,"count":42,"preSum":1082},{"ndv":13,"upper":90,"lower":75,"count":46,"preSum":1124},{"ndv":4,"upper":96,"lower":91,"count":129,"preSum":1170},{"ndv":4,"upper":102,"lower":97,"count":44,"preSum":1299},{"ndv":12,"upper":120,"lower":103,"count":53,"preSum":1343},{"ndv":12,"upper":144,"lower":121,"count":109,"preSum":1396},{"ndv":12,"upper":170,"lower":149,"count":42,"preSum":1505},{"ndv":9,"upper":192,"lower":174,"count":90,"preSum":1547},{"ndv":13,"upper":216,"lower":194,"count":43,"preSum":1637},{"ndv":7,"upper":240,"lower":218,"count":75,"preSum":1680},{"ndv":15,"upper":288,"lower":245,"count":72,"preSum":1755},{"ndv":11,"upper":336,"lower":300,"count":59,"preSum":1827},{"ndv":17,"upper":400,"lower":337,"count":56,"preSum":1886},{"ndv":24,"upper":474,"lower":401,"count":42,"preSum":1942},{"ndv":10,"upper":522,"lower":476,"count":42,"preSum":1984},{"ndv":20,"upper":600,"lower":528,"count":58,"preSum":2026},{"ndv":16,"upper":672,"lower":605,"count":46,"preSum":2084},{"ndv":17,"upper":816,"lower":680,"count":43,"preSum":2130},{"ndv":23,"upper":960,"lower":825,"count":44,"preSum":2173},{"ndv":8,"upper":1008,"lower":972,"count":42,"preSum":2217},{"ndv":19,"upper":1152,"lower":1011,"count":52,"preSum":2259},{"ndv":10,"upper":1260,"lower":1182,"count":50,"preSum":2311},{"ndv":22,"upper":1440,"lower":1267,"count":57,"preSum":2361},{"ndv":24,"upper":1740,"lower":1444,"count":42,"preSum":2418},{"ndv":14,"upper":2016,"lower":1761,"count":44,"preSum":2460},{"ndv":12,"upper":2352,"lower":2064,"count":61,"preSum":2504},{"ndv":17,"upper":3168,"lower":2400,"count":42,"preSum":2565},{"ndv":29,"upper":7200,"lower":3240,"count":42,"preSum":2607},{"ndv":20,"upper":20160,"lower":7218,"count":34,"preSum":2649}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[54362,17511,3632,5613,1404,2087,270,531,148,560,721,143,517,431],"valueArr":[1,2,3,4,5,6,7,8,9,10,12,18,24,48],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','receiptcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','receiptdetailid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[802],"valueArr":[0],"type":"Int","sampleRate":1.0}',89811,0.007226729),('jala_wms_prod','shipping_container_detail','receiptid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[802],"valueArr":[0],"type":"Int","sampleRate":1.0}',89811,0.007226729),('jala_wms_prod','shipping_container_detail','scannedqty',4996,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":9,"lower":9,"count":47,"preSum":0},{"ndv":2,"upper":13,"lower":11,"count":33,"preSum":47},{"ndv":2,"upper":15,"lower":14,"count":46,"preSum":80},{"ndv":2,"upper":17,"lower":16,"count":39,"preSum":126},{"ndv":1,"upper":18,"lower":18,"count":67,"preSum":165},{"ndv":2,"upper":20,"lower":19,"count":37,"preSum":232},{"ndv":3,"upper":23,"lower":21,"count":33,"preSum":269},{"ndv":4,"upper":28,"lower":25,"count":39,"preSum":302},{"ndv":2,"upper":30,"lower":29,"count":47,"preSum":341},{"ndv":6,"upper":36,"lower":31,"count":75,"preSum":388},{"ndv":3,"upper":41,"lower":39,"count":31,"preSum":463},{"ndv":5,"upper":46,"lower":42,"count":32,"preSum":494},{"ndv":6,"upper":53,"lower":47,"count":31,"preSum":526},{"ndv":6,"upper":60,"lower":54,"count":35,"preSum":557},{"ndv":10,"upper":72,"lower":61,"count":51,"preSum":592},{"ndv":11,"upper":85,"lower":73,"count":31,"preSum":643},{"ndv":9,"upper":102,"lower":88,"count":33,"preSum":674},{"ndv":11,"upper":120,"lower":103,"count":42,"preSum":707},{"ndv":11,"upper":144,"lower":121,"count":103,"preSum":749},{"ndv":11,"upper":174,"lower":150,"count":31,"preSum":852},{"ndv":7,"upper":192,"lower":176,"count":85,"preSum":883},{"ndv":12,"upper":216,"lower":194,"count":36,"preSum":968},{"ndv":6,"upper":240,"lower":218,"count":69,"preSum":1004},{"ndv":11,"upper":288,"lower":248,"count":67,"preSum":1073},{"ndv":11,"upper":336,"lower":300,"count":55,"preSum":1140},{"ndv":14,"upper":398,"lower":337,"count":31,"preSum":1195},{"ndv":14,"upper":434,"lower":401,"count":31,"preSum":1226},{"ndv":11,"upper":480,"lower":435,"count":34,"preSum":1257},{"ndv":10,"upper":534,"lower":490,"count":31,"preSum":1291},{"ndv":15,"upper":600,"lower":536,"count":37,"preSum":1322},{"ndv":10,"upper":640,"lower":605,"count":34,"preSum":1359},{"ndv":11,"upper":720,"lower":642,"count":32,"preSum":1393},{"ndv":19,"upper":894,"lower":729,"count":31,"preSum":1425},{"ndv":13,"upper":972,"lower":900,"count":59,"preSum":1456},{"ndv":23,"upper":1152,"lower":975,"count":54,"preSum":1515},{"ndv":10,"upper":1260,"lower":1182,"count":49,"preSum":1569},{"ndv":20,"upper":1440,"lower":1267,"count":55,"preSum":1618},{"ndv":22,"upper":1728,"lower":1444,"count":40,"preSum":1673},{"ndv":14,"upper":2016,"lower":1736,"count":44,"preSum":1713},{"ndv":10,"upper":2304,"lower":2064,"count":34,"preSum":1757},{"ndv":3,"upper":2448,"lower":2352,"count":31,"preSum":1791},{"ndv":12,"upper":3072,"lower":2504,"count":31,"preSum":1822},{"ndv":24,"upper":6600,"lower":3168,"count":31,"preSum":1853},{"ndv":19,"upper":14400,"lower":6675,"count":36,"preSum":1884},{"ndv":3,"upper":20160,"lower":15552,"count":4,"preSum":1920}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[45242,29715,8153,1928,1329,610,556,95,194,177,196,143,232,119],"valueArr":[0,1,2,3,4,5,6,7,8,10,12,24,48,96],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','shelflifests',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[8,90605],"valueArr":["GQ","ZC"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','shipmentallocid',6138410,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1405,"upper":272177,"lower":3888,"count":1413,"preSum":0},{"ndv":1405,"upper":511884,"lower":272178,"count":1413,"preSum":1413},{"ndv":1394,"upper":783905,"lower":511885,"count":1413,"preSum":2826},{"ndv":1413,"upper":952428,"lower":783909,"count":1413,"preSum":4239},{"ndv":1387,"upper":1177670,"lower":952441,"count":1413,"preSum":5652},{"ndv":1390,"upper":1377429,"lower":1177671,"count":1413,"preSum":7065},{"ndv":1404,"upper":1595938,"lower":1377442,"count":1413,"preSum":8478},{"ndv":1404,"upper":1829417,"lower":1595944,"count":1413,"preSum":9891},{"ndv":1413,"upper":2117890,"lower":1829418,"count":1413,"preSum":11304},{"ndv":1413,"upper":2317350,"lower":2117894,"count":1413,"preSum":12717},{"ndv":1402,"upper":2600868,"lower":2317351,"count":1413,"preSum":14130},{"ndv":1403,"upper":2851349,"lower":2600869,"count":1413,"preSum":15543},{"ndv":1407,"upper":3053143,"lower":2851355,"count":1413,"preSum":16956},{"ndv":1401,"upper":3295407,"lower":3053151,"count":1413,"preSum":18369},{"ndv":1404,"upper":3670131,"lower":3295415,"count":1413,"preSum":19782},{"ndv":1413,"upper":3873478,"lower":3670133,"count":1413,"preSum":21195},{"ndv":1413,"upper":4057876,"lower":3873480,"count":1413,"preSum":22608},{"ndv":1413,"upper":4320872,"lower":4057886,"count":1413,"preSum":24021},{"ndv":1413,"upper":4539882,"lower":4320873,"count":1413,"preSum":25434},{"ndv":1413,"upper":4744812,"lower":4539883,"count":1413,"preSum":26847},{"ndv":1403,"upper":4939848,"lower":4744813,"count":1413,"preSum":28260},{"ndv":1410,"upper":5187258,"lower":4939853,"count":1413,"preSum":29673},{"ndv":1413,"upper":5371384,"lower":5187264,"count":1413,"preSum":31086},{"ndv":1413,"upper":5604564,"lower":5371392,"count":1413,"preSum":32499},{"ndv":1405,"upper":5823788,"lower":5604567,"count":1413,"preSum":33912},{"ndv":1409,"upper":6053470,"lower":5823790,"count":1413,"preSum":35325},{"ndv":1411,"upper":6253532,"lower":6053472,"count":1413,"preSum":36738},{"ndv":1407,"upper":6433011,"lower":6253533,"count":1413,"preSum":38151},{"ndv":1389,"upper":6718833,"lower":6433019,"count":1413,"preSum":39564},{"ndv":1411,"upper":6940254,"lower":6718834,"count":1413,"preSum":40977},{"ndv":1413,"upper":7133143,"lower":6940265,"count":1413,"preSum":42390},{"ndv":1411,"upper":7355560,"lower":7133145,"count":1413,"preSum":43803},{"ndv":1403,"upper":7580455,"lower":7355563,"count":1413,"preSum":45216},{"ndv":1413,"upper":7778003,"lower":7580459,"count":1413,"preSum":46629},{"ndv":1413,"upper":8024605,"lower":7778007,"count":1413,"preSum":48042},{"ndv":1412,"upper":8204259,"lower":8024606,"count":1413,"preSum":49455},{"ndv":1413,"upper":8419545,"lower":8204271,"count":1413,"preSum":50868},{"ndv":1411,"upper":8666779,"lower":8419592,"count":1413,"preSum":52281},{"ndv":1402,"upper":8859549,"lower":8666780,"count":1413,"preSum":53694},{"ndv":1412,"upper":9129172,"lower":8859553,"count":1413,"preSum":55107},{"ndv":1400,"upper":9310152,"lower":9129176,"count":1413,"preSum":56520},{"ndv":1408,"upper":9484945,"lower":9310153,"count":1413,"preSum":57933},{"ndv":1404,"upper":9801887,"lower":9484947,"count":1413,"preSum":59346},{"ndv":1413,"upper":10051234,"lower":9801900,"count":1413,"preSum":60759},{"ndv":1413,"upper":10312175,"lower":10051237,"count":1413,"preSum":62172},{"ndv":1413,"upper":10538124,"lower":10312178,"count":1413,"preSum":63585},{"ndv":1408,"upper":10789408,"lower":10541161,"count":1413,"preSum":64998},{"ndv":1406,"upper":11016199,"lower":10789411,"count":1413,"preSum":66411},{"ndv":1413,"upper":11265965,"lower":11016209,"count":1413,"preSum":67824},{"ndv":1410,"upper":11460124,"lower":11265966,"count":1413,"preSum":69237},{"ndv":1409,"upper":11655868,"lower":11460128,"count":1413,"preSum":70650},{"ndv":1413,"upper":11892848,"lower":11655869,"count":1413,"preSum":72063},{"ndv":1413,"upper":12139316,"lower":11892849,"count":1413,"preSum":73476},{"ndv":1413,"upper":12374581,"lower":12139325,"count":1413,"preSum":74889},{"ndv":1407,"upper":12624590,"lower":12374583,"count":1413,"preSum":76302},{"ndv":1405,"upper":12829600,"lower":12624592,"count":1413,"preSum":77715},{"ndv":1412,"upper":13026839,"lower":12829613,"count":1413,"preSum":79128},{"ndv":1413,"upper":13188566,"lower":13026844,"count":1413,"preSum":80541},{"ndv":1413,"upper":13326292,"lower":13188567,"count":1413,"preSum":81954},{"ndv":1412,"upper":13503077,"lower":13326293,"count":1413,"preSum":83367},{"ndv":1403,"upper":13716613,"lower":13503097,"count":1413,"preSum":84780},{"ndv":1408,"upper":13910545,"lower":13716614,"count":1413,"preSum":86193},{"ndv":1395,"upper":14117385,"lower":13910626,"count":1413,"preSum":87606},{"ndv":1392,"upper":14391195,"lower":14137599,"count":1392,"preSum":89019}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[69,7,7,15,9,9,18,22,8,7,7,9,7,8],"valueArr":[0,62508,297597,653428,1011357,1229108,1307921,3152837,3505643,4922756,6691430,6691432,8490275,13691345],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','shipmentcode',584063,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":428,"upper":"CK0001245644","lower":"10000268184-1","count":1408,"preSum":0},{"ndv":389,"upper":"CK0001349900","lower":"CK0001245729","count":1413,"preSum":1408},{"ndv":403,"upper":"CK0001446015","lower":"CK0001350024","count":1411,"preSum":2821},{"ndv":435,"upper":"CK0001485447","lower":"CK0001446016","count":1410,"preSum":4232},{"ndv":480,"upper":"CK0001511610","lower":"CK0001485449","count":1413,"preSum":5642},{"ndv":489,"upper":"CK0001540297","lower":"CK0001511613","count":1409,"preSum":7055},{"ndv":463,"upper":"CKH00000008190","lower":"CK0001540299","count":1410,"preSum":8464},{"ndv":446,"upper":"PJD2304787320092721","lower":"CKH00000008254","count":1408,"preSum":9874},{"ndv":906,"upper":"PJX2303763875350812","lower":"PJD2304787570332810","count":1409,"preSum":11282},{"ndv":887,"upper":"PJX2304785848592423","lower":"PJX2303763876090812","count":1408,"preSum":12691},{"ndv":835,"upper":"PJX2305793847950716","lower":"PJX2304785854202423","count":1408,"preSum":14099},{"ndv":808,"upper":"PJX2305798055061512","lower":"PJX2305793848570716","count":1408,"preSum":15507},{"ndv":827,"upper":"PJX2305802018882212","lower":"PJX2305798064061512","count":1408,"preSum":16915},{"ndv":893,"upper":"PJX2306811714300110","lower":"PJX2305802027392212","count":1409,"preSum":18323},{"ndv":888,"upper":"PJX2306816525790808","lower":"PJX2306811714370110","count":1408,"preSum":19732},{"ndv":905,"upper":"PJX2306821040451609","lower":"PJX2306816525830808","count":1408,"preSum":21140},{"ndv":836,"upper":"POD2305797360151409","lower":"PJX2306821040591609","count":1408,"preSum":22548},{"ndv":872,"upper":"PSD2212731446732822","lower":"POD2305797517991413","count":1409,"preSum":23956},{"ndv":676,"upper":"PSD2304784340312116","lower":"PSD2212731451902823","count":1408,"preSum":25365},{"ndv":755,"upper":"PSD2304786140302515","lower":"PSD2304784343122116","count":1409,"preSum":26773},{"ndv":745,"upper":"PSD2304787669422813","lower":"PSD2304786141842515","count":1411,"preSum":28182},{"ndv":828,"upper":"PSD2305789103320111","lower":"PSD2304787669462813","count":1408,"preSum":29593},{"ndv":769,"upper":"PSD2305791527820317","lower":"PSD2305789103570111","count":1411,"preSum":31001},{"ndv":821,"upper":"PSD2305793236970610","lower":"PSD2305791530150317","count":1408,"preSum":32412},{"ndv":807,"upper":"PSD2305794663700909","lower":"PSD2305793236980610","count":1408,"preSum":33820},{"ndv":810,"upper":"PSD2305796316791203","lower":"PSD2305794664170909","count":1409,"preSum":35228},{"ndv":703,"upper":"PSD2305797513361413","lower":"PSD2305796316851203","count":1408,"preSum":36637},{"ndv":751,"upper":"PSD2305799451331713","lower":"PSD2305797514881413","count":1409,"preSum":38045},{"ndv":706,"upper":"PSD2305801009112015","lower":"PSD2305799451341713","count":1410,"preSum":39454},{"ndv":672,"upper":"PSD2305801958232210","lower":"PSD2305801009132015","count":1408,"preSum":40864},{"ndv":789,"upper":"PSD2305803366662512","lower":"PSD2305801958442210","count":1412,"preSum":42272},{"ndv":720,"upper":"PSD2305808221072821","lower":"PSD2305803366682512","count":1409,"preSum":43684},{"ndv":799,"upper":"PSD2305809592333021","lower":"PSD2305808221122821","count":1409,"preSum":45093},{"ndv":803,"upper":"PSD2306812221740118","lower":"PSD2305809592383021","count":1408,"preSum":46502},{"ndv":793,"upper":"PSD2306814295000408","lower":"PSD2306812225100118","count":1409,"preSum":47910},{"ndv":812,"upper":"PSD2306816089780709","lower":"PSD2306814295020408","count":1412,"preSum":49319},{"ndv":792,"upper":"PSD2306817401340923","lower":"PSD2306816099470709","count":1409,"preSum":50731},{"ndv":761,"upper":"PSD2306818419911200","lower":"PSD2306817401350923","count":1408,"preSum":52140},{"ndv":835,"upper":"PSD2306819789351423","lower":"PSD2306818421191200","count":1409,"preSum":53548},{"ndv":928,"upper":"PTB2303758578630315","lower":"PSD2306819789371423","count":1408,"preSum":54957},{"ndv":991,"upper":"PTB2303770884492212","lower":"PTB2303758578710315","count":1408,"preSum":56365},{"ndv":975,"upper":"PTB2304783348451912","lower":"PTB2303770888982212","count":1409,"preSum":57773},{"ndv":1026,"upper":"PTB2304786933332710","lower":"PTB2304783366261913","count":1410,"preSum":59182},{"ndv":902,"upper":"PTB2305789438820123","lower":"PTB2304786934302710","count":1409,"preSum":60592},{"ndv":912,"upper":"PTB2305790775540310","lower":"PTB2305789469810200","count":1408,"preSum":62001},{"ndv":935,"upper":"PTB2305791630140320","lower":"PTB2305790775890310","count":1408,"preSum":63409},{"ndv":889,"upper":"PTB2305793188100609","lower":"PTB2305791630290320","count":1409,"preSum":64817},{"ndv":967,"upper":"PTB2305795678971100","lower":"PTB2305793191160609","count":1411,"preSum":66226},{"ndv":958,"upper":"PTB2305798605791614","lower":"PTB2305795679041100","count":1410,"preSum":67637},{"ndv":952,"upper":"PTB2305800228471823","lower":"PTB2305798605801614","count":1408,"preSum":69047},{"ndv":1041,"upper":"PTB2305802670362320","lower":"PTB2305800236331823","count":1408,"preSum":70455},{"ndv":994,"upper":"PTB2305804627512710","lower":"PTB2305802672332321","count":1410,"preSum":71863},{"ndv":953,"upper":"PTB2305805342762711","lower":"PTB2305804629612710","count":1411,"preSum":73273},{"ndv":981,"upper":"PTB2305806025802713","lower":"PTB2305805343732711","count":1408,"preSum":74684},{"ndv":967,"upper":"PTB2305806920502718","lower":"PTB2305806028432713","count":1409,"preSum":76092},{"ndv":978,"upper":"PTB2305808337872900","lower":"PTB2305806920792718","count":1408,"preSum":77501},{"ndv":989,"upper":"PTB2305810212993116","lower":"PTB2305808340252900","count":1409,"preSum":78909},{"ndv":913,"upper":"PTB2305811133883123","lower":"PTB2305810213353116","count":1409,"preSum":80318},{"ndv":941,"upper":"PTB2306812316190121","lower":"PTB2305811134313123","count":1409,"preSum":81727},{"ndv":950,"upper":"PTB2306813725410314","lower":"PTB2306812316480121","count":1408,"preSum":83136},{"ndv":973,"upper":"PTB2306815593660612","lower":"PTB2306813726330314","count":1408,"preSum":84544},{"ndv":973,"upper":"PTB2306817566391011","lower":"PTB2306815593860612","count":1408,"preSum":85952},{"ndv":1005,"upper":"PTB2306819369421400","lower":"PTB2306817566641011","count":1408,"preSum":87360},{"ndv":904,"upper":"W028调拨嘉兴0607","lower":"PTB2306819369541400","count":1336,"preSum":88768}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[39,29,39,53,83,38,26,29,27,30,39,29,48],"valueArr":["1200009643_W007","202212自然堂品牌-销售因素退货","202302自然堂品牌-销售因素退货","202303自然堂品牌-销售因素退货报废","202304自然堂品牌-销售因素退货","4800122994","4903586838-1","CK0001181974","CK0001388941","CK0001513773","CK0001513854","CK0001531159","W028法规品调拨福利仓明细0328"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','shipmentdetailid',4998484,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1141,"upper":3369621,"lower":3032777,"count":1413,"preSum":0},{"ndv":1226,"upper":4432329,"lower":3369622,"count":1414,"preSum":1413},{"ndv":1340,"upper":4997620,"lower":4459561,"count":1413,"preSum":2827},{"ndv":1411,"upper":5252200,"lower":4997904,"count":1413,"preSum":4240},{"ndv":1362,"upper":5613272,"lower":5253298,"count":1413,"preSum":5653},{"ndv":1300,"upper":6004724,"lower":5613286,"count":1413,"preSum":7066},{"ndv":1360,"upper":6338025,"lower":6004727,"count":1413,"preSum":8479},{"ndv":1398,"upper":6575447,"lower":6338038,"count":1413,"preSum":9892},{"ndv":1403,"upper":6839019,"lower":6575595,"count":1413,"preSum":11305},{"ndv":1413,"upper":7037291,"lower":6839477,"count":1413,"preSum":12718},{"ndv":1373,"upper":7322424,"lower":7037302,"count":1413,"preSum":14131},{"ndv":1396,"upper":7569622,"lower":7322428,"count":1413,"preSum":15544},{"ndv":1394,"upper":7748411,"lower":7569638,"count":1413,"preSum":16957},{"ndv":1400,"upper":7947605,"lower":7748412,"count":1413,"preSum":18370},{"ndv":1396,"upper":8240012,"lower":7947606,"count":1413,"preSum":19783},{"ndv":1413,"upper":8453002,"lower":8241475,"count":1413,"preSum":21196},{"ndv":1400,"upper":8655120,"lower":8453004,"count":1413,"preSum":22609},{"ndv":1409,"upper":8842036,"lower":8655121,"count":1413,"preSum":24022},{"ndv":1411,"upper":9041836,"lower":8842041,"count":1413,"preSum":25435},{"ndv":1410,"upper":9232250,"lower":9041985,"count":1413,"preSum":26848},{"ndv":1390,"upper":9437718,"lower":9232258,"count":1413,"preSum":28261},{"ndv":1406,"upper":9709256,"lower":9437723,"count":1413,"preSum":29674},{"ndv":1411,"upper":9888778,"lower":9709362,"count":1413,"preSum":31087},{"ndv":1409,"upper":10126019,"lower":9888779,"count":1413,"preSum":32500},{"ndv":1404,"upper":10355027,"lower":10126022,"count":1413,"preSum":33913},{"ndv":1406,"upper":10563922,"lower":10355028,"count":1413,"preSum":35326},{"ndv":1402,"upper":10773922,"lower":10565374,"count":1413,"preSum":36739},{"ndv":1411,"upper":10964850,"lower":10773982,"count":1413,"preSum":38152},{"ndv":1374,"upper":11222948,"lower":10964851,"count":1413,"preSum":39565},{"ndv":1408,"upper":11388290,"lower":11222956,"count":1413,"preSum":40978},{"ndv":1413,"upper":11552889,"lower":11388294,"count":1413,"preSum":42391},{"ndv":1410,"upper":11772013,"lower":11552891,"count":1413,"preSum":43804},{"ndv":1390,"upper":12021092,"lower":11772015,"count":1413,"preSum":45217},{"ndv":1412,"upper":12212608,"lower":12021155,"count":1413,"preSum":46630},{"ndv":1413,"upper":12437837,"lower":12212615,"count":1413,"preSum":48043},{"ndv":1378,"upper":12600995,"lower":12437839,"count":1413,"preSum":49456},{"ndv":1403,"upper":12804436,"lower":12600996,"count":1413,"preSum":50869},{"ndv":1404,"upper":13037342,"lower":12804736,"count":1413,"preSum":52282},{"ndv":1404,"upper":13256476,"lower":13037343,"count":1413,"preSum":53695},{"ndv":1413,"upper":13452469,"lower":13257258,"count":1413,"preSum":55108},{"ndv":1413,"upper":13655615,"lower":13452470,"count":1413,"preSum":56521},{"ndv":1412,"upper":13881901,"lower":13656117,"count":1413,"preSum":57934},{"ndv":1406,"upper":14159142,"lower":13881904,"count":1413,"preSum":59347},{"ndv":1405,"upper":14393254,"lower":14159143,"count":1413,"preSum":60760},{"ndv":1400,"upper":14566985,"lower":14393375,"count":1413,"preSum":62173},{"ndv":1407,"upper":14795160,"lower":14566993,"count":1413,"preSum":63586},{"ndv":1403,"upper":14988745,"lower":14795162,"count":1413,"preSum":64999},{"ndv":1408,"upper":15187960,"lower":14988746,"count":1413,"preSum":66412},{"ndv":1403,"upper":15387821,"lower":15188439,"count":1413,"preSum":67825},{"ndv":1406,"upper":15569051,"lower":15387860,"count":1413,"preSum":69238},{"ndv":1403,"upper":15771007,"lower":15569052,"count":1413,"preSum":70651},{"ndv":1410,"upper":15979514,"lower":15771011,"count":1413,"preSum":72064},{"ndv":1411,"upper":16175189,"lower":15979699,"count":1413,"preSum":73477},{"ndv":1411,"upper":16417458,"lower":16175199,"count":1413,"preSum":74890},{"ndv":1404,"upper":16631698,"lower":16417754,"count":1413,"preSum":76303},{"ndv":1392,"upper":16833898,"lower":16631700,"count":1413,"preSum":77716},{"ndv":1411,"upper":17029808,"lower":16834056,"count":1413,"preSum":79129},{"ndv":1399,"upper":17184936,"lower":17029810,"count":1413,"preSum":80542},{"ndv":1405,"upper":17322941,"lower":17184942,"count":1413,"preSum":81955},{"ndv":1407,"upper":17496407,"lower":17322960,"count":1413,"preSum":83368},{"ndv":1391,"upper":17693019,"lower":17496571,"count":1413,"preSum":84781},{"ndv":1401,"upper":17878875,"lower":17693121,"count":1413,"preSum":86194},{"ndv":1359,"upper":18059252,"lower":17878939,"count":1413,"preSum":87607},{"ndv":1412,"upper":18374248,"lower":18059472,"count":1412,"preSum":89020}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[14,15,15,14,18,13,14,13,24,27,14],"valueArr":[3034168,3034877,4813543,5764015,5881145,6141216,6513024,7089355,7899365,11210846,12456892],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','shipmentid',583821,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":453,"upper":1477764,"lower":1244829,"count":1410,"preSum":0},{"ndv":421,"upper":2452717,"lower":1477772,"count":1415,"preSum":1410},{"ndv":606,"upper":2830036,"lower":2453554,"count":1408,"preSum":2825},{"ndv":939,"upper":2984957,"lower":2830065,"count":1411,"preSum":4233},{"ndv":807,"upper":3216834,"lower":2984982,"count":1409,"preSum":5644},{"ndv":719,"upper":3510042,"lower":3217093,"count":1408,"preSum":7053},{"ndv":801,"upper":3679734,"lower":3510044,"count":1410,"preSum":8461},{"ndv":729,"upper":3788397,"lower":3679746,"count":1408,"preSum":9871},{"ndv":679,"upper":3873222,"lower":3788398,"count":1409,"preSum":11279},{"ndv":770,"upper":3937281,"lower":3873265,"count":1408,"preSum":12688},{"ndv":834,"upper":4043159,"lower":3937282,"count":1408,"preSum":14096},{"ndv":786,"upper":4126125,"lower":4043233,"count":1408,"preSum":15504},{"ndv":715,"upper":4186642,"lower":4126174,"count":1408,"preSum":16912},{"ndv":810,"upper":4246222,"lower":4186675,"count":1408,"preSum":18320},{"ndv":837,"upper":4426983,"lower":4246591,"count":1408,"preSum":19728},{"ndv":770,"upper":4479832,"lower":4427000,"count":1408,"preSum":21136},{"ndv":865,"upper":4534963,"lower":4479914,"count":1408,"preSum":22544},{"ndv":892,"upper":4587576,"lower":4534979,"count":1408,"preSum":23952},{"ndv":875,"upper":4647575,"lower":4587584,"count":1408,"preSum":25360},{"ndv":867,"upper":4701992,"lower":4647756,"count":1408,"preSum":26768},{"ndv":820,"upper":4766843,"lower":4702164,"count":1408,"preSum":28176},{"ndv":821,"upper":4884143,"lower":4766844,"count":1410,"preSum":29584},{"ndv":847,"upper":4944470,"lower":4884144,"count":1408,"preSum":30994},{"ndv":805,"upper":5021904,"lower":4944471,"count":1408,"preSum":32402},{"ndv":857,"upper":5090758,"lower":5021905,"count":1408,"preSum":33810},{"ndv":811,"upper":5154066,"lower":5090760,"count":1410,"preSum":35218},{"ndv":755,"upper":5220919,"lower":5154429,"count":1408,"preSum":36628},{"ndv":793,"upper":5279823,"lower":5220993,"count":1408,"preSum":38036},{"ndv":763,"upper":5349792,"lower":5279824,"count":1411,"preSum":39444},{"ndv":723,"upper":5396109,"lower":5349794,"count":1409,"preSum":40855},{"ndv":896,"upper":5460797,"lower":5396110,"count":1408,"preSum":42264},{"ndv":778,"upper":5536713,"lower":5461020,"count":1410,"preSum":43672},{"ndv":759,"upper":5614633,"lower":5536857,"count":1411,"preSum":45082},{"ndv":803,"upper":5667518,"lower":5614634,"count":1409,"preSum":46493},{"ndv":751,"upper":5729210,"lower":5667521,"count":1410,"preSum":47902},{"ndv":836,"upper":5784935,"lower":5729211,"count":1408,"preSum":49312},{"ndv":803,"upper":5851899,"lower":5785522,"count":1409,"preSum":50720},{"ndv":767,"upper":5940305,"lower":5851920,"count":1408,"preSum":52129},{"ndv":922,"upper":6016237,"lower":5940318,"count":1408,"preSum":53537},{"ndv":926,"upper":6082477,"lower":6016280,"count":1408,"preSum":54945},{"ndv":995,"upper":6151813,"lower":6082524,"count":1409,"preSum":56353},{"ndv":963,"upper":6236397,"lower":6151869,"count":1408,"preSum":57762},{"ndv":914,"upper":6325583,"lower":6236547,"count":1408,"preSum":59170},{"ndv":873,"upper":6398366,"lower":6325613,"count":1408,"preSum":60578},{"ndv":870,"upper":6451049,"lower":6398369,"count":1409,"preSum":61986},{"ndv":827,"upper":6535209,"lower":6451055,"count":1408,"preSum":63395},{"ndv":832,"upper":6602774,"lower":6535212,"count":1408,"preSum":64803},{"ndv":885,"upper":6665645,"lower":6603298,"count":1408,"preSum":66211},{"ndv":893,"upper":6728484,"lower":6665754,"count":1408,"preSum":67619},{"ndv":858,"upper":6786207,"lower":6728600,"count":1408,"preSum":69027},{"ndv":856,"upper":6857638,"lower":6786301,"count":1408,"preSum":70435},{"ndv":904,"upper":6934407,"lower":6857640,"count":1408,"preSum":71843},{"ndv":917,"upper":7009127,"lower":6934421,"count":1408,"preSum":73251},{"ndv":834,"upper":7085666,"lower":7009278,"count":1409,"preSum":74659},{"ndv":830,"upper":7158663,"lower":7085670,"count":1408,"preSum":76068},{"ndv":881,"upper":7229672,"lower":7158689,"count":1408,"preSum":77476},{"ndv":855,"upper":7291401,"lower":7229676,"count":1408,"preSum":78884},{"ndv":828,"upper":7342611,"lower":7291403,"count":1409,"preSum":80292},{"ndv":842,"upper":7389373,"lower":7342734,"count":1410,"preSum":81701},{"ndv":869,"upper":7444612,"lower":7389381,"count":1410,"preSum":83111},{"ndv":835,"upper":7510739,"lower":7444615,"count":1408,"preSum":84521},{"ndv":858,"upper":7574522,"lower":7510747,"count":1410,"preSum":85929},{"ndv":845,"upper":7634921,"lower":7574524,"count":1410,"preSum":87339},{"ndv":859,"upper":7729234,"lower":7634992,"count":1355,"preSum":88749}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[29,26,29,27,39,48,53,30,39,83,38,29,39],"valueArr":[1247166,1839917,2564489,2721760,3302918,3313027,3953572,5344364,5345123,5464080,5730137,5968945,7610766],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','status',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[90613],"valueArr":[300],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','taskcreated',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[90613],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','transcontcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','twicecheckingstatus',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','umqtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[90613],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','unitqty',49,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":18,"lower":18,"count":14,"preSum":0},{"ndv":1,"upper":30,"lower":30,"count":7,"preSum":14},{"ndv":1,"upper":72,"lower":72,"count":14,"preSum":21},{"ndv":1,"upper":100,"lower":100,"count":3,"preSum":35},{"ndv":1,"upper":120,"lower":120,"count":3,"preSum":38},{"ndv":1,"upper":150,"lower":150,"count":6,"preSum":41},{"ndv":1,"upper":180,"lower":180,"count":12,"preSum":47},{"ndv":2,"upper":240,"lower":192,"count":5,"preSum":59},{"ndv":2,"upper":300,"lower":280,"count":5,"preSum":64},{"ndv":1,"upper":800,"lower":800,"count":3,"preSum":69},{"ndv":1,"upper":2352,"lower":2352,"count":2,"preSum":72}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[87431,40,911,28,411,198,17,214,34,415,30,767,18,25],"valueArr":[1,2,3,4,6,8,10,12,20,24,36,48,50,400],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','unitqtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[90613],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','userdef1',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','userdef2',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','userdef3',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','userdef4',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','userdef5',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','userdef6',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','userdef7',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','userdef8',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,90613,0.007226729),('jala_wms_prod','shipping_container_detail','version',1568,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":12,"lower":11,"count":4,"preSum":0},{"ndv":2,"upper":15,"lower":14,"count":4,"preSum":4},{"ndv":3,"upper":19,"lower":16,"count":3,"preSum":8},{"ndv":2,"upper":21,"lower":20,"count":4,"preSum":11},{"ndv":2,"upper":24,"lower":22,"count":3,"preSum":15},{"ndv":1,"upper":25,"lower":25,"count":3,"preSum":18},{"ndv":2,"upper":27,"lower":26,"count":3,"preSum":21},{"ndv":1,"upper":28,"lower":28,"count":3,"preSum":24},{"ndv":2,"upper":34,"lower":30,"count":3,"preSum":27},{"ndv":2,"upper":37,"lower":36,"count":4,"preSum":30},{"ndv":3,"upper":48,"lower":38,"count":3,"preSum":34},{"ndv":1,"upper":49,"lower":49,"count":3,"preSum":37},{"ndv":2,"upper":51,"lower":50,"count":3,"preSum":40},{"ndv":3,"upper":57,"lower":52,"count":4,"preSum":43},{"ndv":3,"upper":60,"lower":58,"count":3,"preSum":47},{"ndv":2,"upper":68,"lower":62,"count":3,"preSum":50},{"ndv":2,"upper":70,"lower":69,"count":3,"preSum":53},{"ndv":3,"upper":75,"lower":71,"count":3,"preSum":56},{"ndv":2,"upper":81,"lower":78,"count":3,"preSum":59},{"ndv":3,"upper":90,"lower":82,"count":4,"preSum":62},{"ndv":2,"upper":98,"lower":94,"count":3,"preSum":66},{"ndv":2,"upper":101,"lower":100,"count":3,"preSum":69},{"ndv":3,"upper":107,"lower":103,"count":3,"preSum":72},{"ndv":3,"upper":113,"lower":109,"count":3,"preSum":75},{"ndv":3,"upper":127,"lower":115,"count":3,"preSum":78},{"ndv":3,"upper":147,"lower":129,"count":3,"preSum":81},{"ndv":3,"upper":166,"lower":155,"count":3,"preSum":84},{"ndv":2,"upper":177,"lower":170,"count":4,"preSum":87},{"ndv":3,"upper":199,"lower":180,"count":3,"preSum":91},{"ndv":3,"upper":233,"lower":220,"count":3,"preSum":94},{"ndv":3,"upper":251,"lower":245,"count":3,"preSum":97},{"ndv":3,"upper":314,"lower":258,"count":3,"preSum":100},{"ndv":3,"upper":333,"lower":330,"count":3,"preSum":103},{"ndv":3,"upper":383,"lower":364,"count":3,"preSum":106},{"ndv":3,"upper":519,"lower":474,"count":3,"preSum":109},{"ndv":3,"upper":537,"lower":522,"count":3,"preSum":112},{"ndv":3,"upper":689,"lower":553,"count":3,"preSum":115},{"ndv":3,"upper":829,"lower":753,"count":3,"preSum":118},{"ndv":3,"upper":877,"lower":846,"count":3,"preSum":121},{"ndv":3,"upper":905,"lower":887,"count":3,"preSum":124},{"ndv":3,"upper":1041,"lower":914,"count":3,"preSum":127}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[86636,3293,348,75,52,11,16,9,7,7,8,4,13,4],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,13,29,73],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','warehousecode',10,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[2529,6700,12816,1184,51600,12329,1446,1167,730,112],"valueArr":["021DC1","022DC","027DC","028DC","573DC","763DC","SH01","SH02","SH03","TEST01"],"type":"String","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_detail','waveid',17261,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":190,"upper":59226,"lower":0,"count":1397,"preSum":0},{"ndv":171,"upper":433615,"lower":59405,"count":1394,"preSum":1397},{"ndv":172,"upper":560145,"lower":436070,"count":1396,"preSum":2791},{"ndv":145,"upper":586112,"lower":560147,"count":1398,"preSum":4187},{"ndv":179,"upper":654971,"lower":586905,"count":1394,"preSum":5585},{"ndv":181,"upper":696573,"lower":654974,"count":1394,"preSum":6979},{"ndv":175,"upper":722038,"lower":696576,"count":1395,"preSum":8373},{"ndv":179,"upper":743897,"lower":722039,"count":1461,"preSum":9768},{"ndv":92,"upper":752462,"lower":743898,"count":1395,"preSum":11229},{"ndv":83,"upper":759973,"lower":752591,"count":1439,"preSum":12624},{"ndv":129,"upper":770861,"lower":759976,"count":1395,"preSum":14063},{"ndv":142,"upper":781590,"lower":770871,"count":1394,"preSum":15458},{"ndv":111,"upper":788563,"lower":781604,"count":1393,"preSum":16852},{"ndv":110,"upper":795177,"lower":788626,"count":1425,"preSum":18245},{"ndv":116,"upper":807354,"lower":795259,"count":1422,"preSum":19670},{"ndv":85,"upper":812445,"lower":807413,"count":1399,"preSum":21092},{"ndv":73,"upper":818749,"lower":812485,"count":1394,"preSum":22491},{"ndv":68,"upper":821553,"lower":818750,"count":1411,"preSum":23885},{"ndv":73,"upper":824996,"lower":821706,"count":1406,"preSum":25296},{"ndv":76,"upper":828037,"lower":825006,"count":1395,"preSum":26702},{"ndv":103,"upper":836767,"lower":828064,"count":1402,"preSum":28097},{"ndv":86,"upper":848067,"lower":836840,"count":1401,"preSum":29499},{"ndv":102,"upper":856852,"lower":848811,"count":1426,"preSum":30900},{"ndv":103,"upper":871211,"lower":856868,"count":1393,"preSum":32326},{"ndv":103,"upper":879652,"lower":871270,"count":1398,"preSum":33719},{"ndv":107,"upper":888784,"lower":879655,"count":1399,"preSum":35117},{"ndv":90,"upper":898335,"lower":888930,"count":1465,"preSum":36516},{"ndv":110,"upper":907893,"lower":898364,"count":1438,"preSum":37981},{"ndv":108,"upper":919890,"lower":907978,"count":1396,"preSum":39419},{"ndv":117,"upper":927262,"lower":919903,"count":1397,"preSum":40815},{"ndv":84,"upper":932142,"lower":927265,"count":1400,"preSum":42212},{"ndv":106,"upper":940663,"lower":932173,"count":1397,"preSum":43612},{"ndv":105,"upper":952203,"lower":940671,"count":1406,"preSum":45009},{"ndv":86,"upper":958874,"lower":952204,"count":1409,"preSum":46415},{"ndv":70,"upper":967460,"lower":959021,"count":1399,"preSum":47824},{"ndv":117,"upper":978125,"lower":967534,"count":1395,"preSum":49223},{"ndv":138,"upper":990982,"lower":978175,"count":1409,"preSum":50618},{"ndv":116,"upper":1003882,"lower":991026,"count":1406,"preSum":52027},{"ndv":102,"upper":1016290,"lower":1003888,"count":1399,"preSum":53433},{"ndv":104,"upper":1025384,"lower":1016820,"count":1393,"preSum":54832},{"ndv":77,"upper":1029330,"lower":1025591,"count":1414,"preSum":56225},{"ndv":89,"upper":1034886,"lower":1029438,"count":1405,"preSum":57639},{"ndv":131,"upper":1041541,"lower":1034888,"count":1399,"preSum":59044},{"ndv":74,"upper":1043088,"lower":1041542,"count":1393,"preSum":60443},{"ndv":85,"upper":1045214,"lower":1043094,"count":1398,"preSum":61836},{"ndv":66,"upper":1047613,"lower":1045226,"count":1419,"preSum":63234},{"ndv":70,"upper":1049442,"lower":1047615,"count":1430,"preSum":64653},{"ndv":72,"upper":1051737,"lower":1049520,"count":1408,"preSum":66083},{"ndv":71,"upper":1053341,"lower":1051744,"count":1406,"preSum":67491},{"ndv":114,"upper":1058202,"lower":1053345,"count":1398,"preSum":68897},{"ndv":116,"upper":1062470,"lower":1058207,"count":1397,"preSum":70295},{"ndv":102,"upper":1070426,"lower":1062471,"count":1396,"preSum":71692},{"ndv":114,"upper":1078226,"lower":1070445,"count":1399,"preSum":73088},{"ndv":126,"upper":1098118,"lower":1079628,"count":1398,"preSum":74487},{"ndv":109,"upper":1108687,"lower":1098129,"count":1407,"preSum":75885},{"ndv":126,"upper":1126030,"lower":1108701,"count":1395,"preSum":77292},{"ndv":108,"upper":1137148,"lower":1126373,"count":1420,"preSum":78687},{"ndv":108,"upper":1145671,"lower":1137269,"count":1395,"preSum":80107},{"ndv":105,"upper":1153736,"lower":1145903,"count":1424,"preSum":81502},{"ndv":96,"upper":1165061,"lower":1153785,"count":1441,"preSum":82926},{"ndv":132,"upper":1175156,"lower":1165106,"count":1399,"preSum":84367},{"ndv":154,"upper":1184139,"lower":1175157,"count":1428,"preSum":85766},{"ndv":104,"upper":1187990,"lower":1184193,"count":1393,"preSum":87194},{"ndv":23,"upper":1190287,"lower":1187992,"count":561,"preSum":88587}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[103,107,102,123,105,123,125,109,111,106,103,111,137],"valueArr":[794318,808376,813427,827927,903110,1031853,1041821,1042378,1044344,1057595,1104867,1128985,1129078],"type":"Int","sampleRate":1.0}',0,0.007226729),('jala_wms_prod','shipping_container_header','actprocessstamp',1163,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":11,"upper":"2023-05-26 23:30:58","lower":"2023-05-26 23:30:00","count":437,"preSum":0},{"ndv":21,"upper":"2023-05-27 23:30:39","lower":"2023-05-26 23:31:38","count":387,"preSum":437},{"ndv":21,"upper":"2023-05-28 23:31:00","lower":"2023-05-27 23:30:56","count":412,"preSum":824},{"ndv":19,"upper":"2023-05-29 23:31:32","lower":"2023-05-28 23:31:19","count":385,"preSum":1236},{"ndv":21,"upper":"2023-05-30 23:31:25","lower":"2023-05-29 23:31:39","count":399,"preSum":1621},{"ndv":11,"upper":"2023-05-31 23:30:06","lower":"2023-05-30 23:31:46","count":386,"preSum":2020},{"ndv":5,"upper":"2023-05-31 23:31:50","lower":"2023-05-31 23:30:21","count":461,"preSum":2406},{"ndv":14,"upper":"2023-06-01 23:30:00","lower":"2023-05-31 23:32:26","count":411,"preSum":2867},{"ndv":3,"upper":"2023-06-01 23:35:01","lower":"2023-06-01 23:31:03","count":432,"preSum":3278},{"ndv":14,"upper":"2023-06-01 23:45:40","lower":"2023-06-01 23:35:51","count":427,"preSum":3710},{"ndv":22,"upper":"2023-06-02 23:30:03","lower":"2023-06-01 23:45:46","count":378,"preSum":4137},{"ndv":5,"upper":"2023-06-02 23:31:36","lower":"2023-06-02 23:30:37","count":617,"preSum":4515},{"ndv":15,"upper":"2023-06-02 23:36:21","lower":"2023-06-02 23:31:46","count":388,"preSum":5132},{"ndv":14,"upper":"2023-06-03 23:30:43","lower":"2023-06-02 23:36:22","count":466,"preSum":5520},{"ndv":7,"upper":"2023-06-03 23:32:06","lower":"2023-06-03 23:30:44","count":392,"preSum":5986},{"ndv":14,"upper":"2023-06-04 23:30:12","lower":"2023-06-03 23:32:43","count":403,"preSum":6378},{"ndv":5,"upper":"2023-06-04 23:30:44","lower":"2023-06-04 23:30:16","count":405,"preSum":6781},{"ndv":8,"upper":"2023-06-04 23:33:15","lower":"2023-06-04 23:30:47","count":385,"preSum":7186},{"ndv":21,"upper":"2023-06-05 23:31:16","lower":"2023-06-04 23:33:19","count":467,"preSum":7571},{"ndv":12,"upper":"2023-06-06 23:30:08","lower":"2023-06-05 23:31:43","count":380,"preSum":8038},{"ndv":6,"upper":"2023-06-06 23:32:00","lower":"2023-06-06 23:30:18","count":380,"preSum":8418},{"ndv":26,"upper":"2023-06-07 23:30:24","lower":"2023-06-06 23:32:08","count":409,"preSum":8798},{"ndv":17,"upper":"2023-06-08 23:30:00","lower":"2023-06-07 23:30:25","count":467,"preSum":9207},{"ndv":12,"upper":"2023-06-08 23:31:00","lower":"2023-06-08 23:30:04","count":385,"preSum":9674},{"ndv":18,"upper":"2023-06-09 23:30:00","lower":"2023-06-08 23:31:12","count":404,"preSum":10059},{"ndv":14,"upper":"2023-06-09 23:31:42","lower":"2023-06-09 23:30:08","count":415,"preSum":10463},{"ndv":15,"upper":"2023-06-10 23:30:09","lower":"2023-06-09 23:31:51","count":436,"preSum":10878},{"ndv":25,"upper":"2023-06-11 23:30:04","lower":"2023-06-10 23:30:10","count":387,"preSum":11314},{"ndv":8,"upper":"2023-06-11 23:31:05","lower":"2023-06-11 23:30:09","count":404,"preSum":11701},{"ndv":23,"upper":"2023-06-12 23:30:18","lower":"2023-06-11 23:31:18","count":422,"preSum":12105},{"ndv":21,"upper":"2023-06-13 23:30:00","lower":"2023-06-12 23:30:26","count":451,"preSum":12527},{"ndv":11,"upper":"2023-06-13 23:31:07","lower":"2023-06-13 23:30:08","count":377,"preSum":12978},{"ndv":21,"upper":"2023-06-14 23:30:20","lower":"2023-06-13 23:31:19","count":407,"preSum":13355},{"ndv":19,"upper":"2023-06-15 23:30:20","lower":"2023-06-14 23:30:32","count":391,"preSum":13762},{"ndv":19,"upper":"2023-06-16 23:30:00","lower":"2023-06-15 23:30:25","count":445,"preSum":14153},{"ndv":10,"upper":"2023-06-16 23:31:21","lower":"2023-06-16 23:30:17","count":494,"preSum":14598},{"ndv":11,"upper":"2023-06-16 23:33:40","lower":"2023-06-16 23:31:22","count":434,"preSum":15092},{"ndv":20,"upper":"2023-06-16 23:35:34","lower":"2023-06-16 23:34:01","count":469,"preSum":15526},{"ndv":9,"upper":"2023-06-17 23:31:28","lower":"2023-06-17 23:30:22","count":533,"preSum":15995},{"ndv":6,"upper":"2023-06-17 23:33:39","lower":"2023-06-17 23:32:26","count":378,"preSum":16528},{"ndv":15,"upper":"2023-06-18 23:30:00","lower":"2023-06-17 23:33:58","count":412,"preSum":16906},{"ndv":5,"upper":"2023-06-18 23:30:43","lower":"2023-06-18 23:30:17","count":410,"preSum":17318},{"ndv":8,"upper":"2023-06-18 23:33:33","lower":"2023-06-18 23:31:04","count":421,"preSum":17728},{"ndv":11,"upper":"2023-06-18 23:35:42","lower":"2023-06-18 23:33:54","count":407,"preSum":18149},{"ndv":9,"upper":"2023-06-19 23:30:51","lower":"2023-06-18 23:35:53","count":449,"preSum":18556},{"ndv":10,"upper":"2023-06-19 23:34:06","lower":"2023-06-19 23:31:22","count":456,"preSum":19005},{"ndv":7,"upper":"2023-06-19 23:36:28","lower":"2023-06-19 23:34:44","count":441,"preSum":19461},{"ndv":20,"upper":"2023-06-20 23:30:21","lower":"2023-06-19 23:36:51","count":383,"preSum":19902},{"ndv":9,"upper":"2023-06-20 23:31:05","lower":"2023-06-20 23:30:23","count":380,"preSum":20285},{"ndv":6,"upper":"2023-06-20 23:32:20","lower":"2023-06-20 23:31:32","count":420,"preSum":20665},{"ndv":16,"upper":"2023-06-21 23:30:27","lower":"2023-06-20 23:32:32","count":377,"preSum":21085},{"ndv":15,"upper":"2023-06-21 23:31:36","lower":"2023-06-21 23:30:29","count":407,"preSum":21462},{"ndv":22,"upper":"2023-06-22 23:30:51","lower":"2023-06-21 23:31:49","count":387,"preSum":21869},{"ndv":21,"upper":"2023-06-23 23:30:41","lower":"2023-06-22 23:30:58","count":380,"preSum":22256},{"ndv":26,"upper":"2023-06-24 23:30:40","lower":"2023-06-23 23:30:56","count":404,"preSum":22636},{"ndv":24,"upper":"2023-06-25 23:31:34","lower":"2023-06-24 23:30:49","count":386,"preSum":23040},{"ndv":23,"upper":"2023-06-27 23:30:07","lower":"2023-06-26 23:30:00","count":376,"preSum":23426},{"ndv":25,"upper":"2023-06-28 23:31:03","lower":"2023-06-27 23:30:11","count":219,"preSum":23802}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[370,623,373,359,1328,896,650,380,434,329,335,348,399,413],"valueArr":["2023-06-01 23:30:01","2023-06-01 23:31:19","2023-06-01 23:31:35","2023-06-01 23:33:15","2023-06-01 23:33:44","2023-06-01 23:38:03","2023-06-01 23:43:04","2023-06-02 23:30:12","2023-06-02 23:32:21","2023-06-02 23:34:03","2023-06-17 23:30:00","2023-06-17 23:30:29","2023-06-18 23:31:12","2023-06-19 23:31:27"],"type":"String","sampleRate":0.8206422281854961}',68743,0.037085027),('jala_wms_prod','shipping_container_header','actualcontainertype',114,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"027DCNB2","lower":"027DCNB1","count":704,"preSum":0},{"ndv":8,"upper":"027DCNZRT5S","lower":"027DCNB3","count":470,"preSum":704},{"ndv":6,"upper":"1300851100","lower":"1300152801","count":1128,"preSum":1174},{"ndv":4,"upper":"1300951500","lower":"1300852000","count":1057,"preSum":2302},{"ndv":2,"upper":"1300951700","lower":"1300951600","count":1913,"preSum":3359},{"ndv":1,"upper":"1301003700","lower":"1301003700","count":1135,"preSum":5272},{"ndv":1,"upper":"1301162700","lower":"1301162700","count":1785,"preSum":6407},{"ndv":1,"upper":"1301162800","lower":"1301162800","count":690,"preSum":8192},{"ndv":1,"upper":"1301162900","lower":"1301162900","count":712,"preSum":8882},{"ndv":1,"upper":"1301163100","lower":"1301163100","count":1350,"preSum":9594},{"ndv":3,"upper":"1301165500","lower":"1301165300","count":674,"preSum":10944},{"ndv":3,"upper":"1301166200","lower":"1301165600","count":1276,"preSum":11618},{"ndv":3,"upper":"2B0004","lower":"1301166800","count":583,"preSum":12894},{"ndv":2,"upper":"2B0006","lower":"2B0005","count":837,"preSum":13477},{"ndv":1,"upper":"2B0008","lower":"2B0008","count":546,"preSum":14314},{"ndv":5,"upper":"2CCX01","lower":"2B001","count":781,"preSum":14860},{"ndv":11,"upper":"2CPFY1","lower":"2CCX02","count":901,"preSum":15641},{"ndv":1,"upper":"2CPFY2","lower":"2CPFY2","count":866,"preSum":16542},{"ndv":5,"upper":"2CVIP1","lower":"2CPFY3","count":466,"preSum":17408},{"ndv":1,"upper":"2CVIP2","lower":"2CVIP2","count":469,"preSum":17874},{"ndv":1,"upper":"2CVIP3","lower":"2CVIP3","count":1747,"preSum":18343},{"ndv":1,"upper":"2CVIP4","lower":"2CVIP4","count":587,"preSum":20090},{"ndv":1,"upper":"2CVIP5","lower":"2CVIP5","count":727,"preSum":20677},{"ndv":1,"upper":"2CVIP6","lower":"2CVIP6","count":799,"preSum":21404},{"ndv":3,"upper":"2CZRT4","lower":"2CZRT1S","count":1232,"preSum":22203},{"ndv":1,"upper":"2CZRT5","lower":"2CZRT5","count":701,"preSum":23435},{"ndv":4,"upper":"CC123456","lower":"2CZRTQP1","count":1108,"preSum":24136},{"ndv":1,"upper":"CDOne","lower":"CDOne","count":1158,"preSum":25244},{"ndv":3,"upper":"CS","lower":"CDTHREE","count":1405,"preSum":26402},{"ndv":2,"upper":"JALA1000","lower":"HB1","count":1955,"preSum":27807},{"ndv":2,"upper":"YXWX01","lower":"WPHB","count":26,"preSum":29762}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[1953,3951,2885,3523,9962,5707,2277,2929,2034,6265,6335,3253,6700,9137],"valueArr":["1300951100","1300951200","1300951300","1300951400","1301166300","1301166400","1301166500","1301166600","2CZRT0","2CZRT1","2CZRT2","2CZRT3","2CZRT3S","2CZRT5S"],"type":"String","sampleRate":0.8206422281854961}',3302,0.037085027),('jala_wms_prod','shipping_container_header','actualshipdatetime',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','actualweight',15162,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":57,"upper":0.0950,"lower":0.0000,"count":1196,"preSum":0},{"ndv":28,"upper":0.1230,"lower":0.0960,"count":1141,"preSum":1196},{"ndv":20,"upper":0.1450,"lower":0.1240,"count":1193,"preSum":2337},{"ndv":25,"upper":0.1700,"lower":0.1460,"count":1267,"preSum":3530},{"ndv":22,"upper":0.1910,"lower":0.1710,"count":1144,"preSum":4797},{"ndv":22,"upper":0.2140,"lower":0.1920,"count":1183,"preSum":5941},{"ndv":13,"upper":0.2270,"lower":0.2150,"count":1171,"preSum":7124},{"ndv":25,"upper":0.2520,"lower":0.2280,"count":1177,"preSum":8295},{"ndv":27,"upper":0.2800,"lower":0.2530,"count":1191,"preSum":9472},{"ndv":29,"upper":0.3100,"lower":0.2810,"count":1355,"preSum":10663},{"ndv":16,"upper":0.3270,"lower":0.3110,"count":1141,"preSum":12018},{"ndv":22,"upper":0.3520,"lower":0.3280,"count":1179,"preSum":13159},{"ndv":15,"upper":0.3670,"lower":0.3530,"count":1147,"preSum":14338},{"ndv":13,"upper":0.3800,"lower":0.3680,"count":1205,"preSum":15485},{"ndv":20,"upper":0.4000,"lower":0.3810,"count":1246,"preSum":16690},{"ndv":22,"upper":0.4220,"lower":0.4010,"count":1150,"preSum":17936},{"ndv":18,"upper":0.4400,"lower":0.4230,"count":1155,"preSum":19086},{"ndv":21,"upper":0.4620,"lower":0.4410,"count":1163,"preSum":20241},{"ndv":45,"upper":0.5100,"lower":0.4630,"count":1145,"preSum":21404},{"ndv":55,"upper":0.5700,"lower":0.5110,"count":1254,"preSum":22549},{"ndv":36,"upper":0.6100,"lower":0.5710,"count":1235,"preSum":23803},{"ndv":18,"upper":0.6290,"lower":0.6120,"count":1156,"preSum":25038},{"ndv":26,"upper":0.6550,"lower":0.6300,"count":1146,"preSum":26194},{"ndv":45,"upper":0.7060,"lower":0.6560,"count":1138,"preSum":27340},{"ndv":70,"upper":0.7900,"lower":0.7070,"count":1194,"preSum":28478},{"ndv":43,"upper":0.8400,"lower":0.7910,"count":1449,"preSum":29672},{"ndv":37,"upper":0.8800,"lower":0.8410,"count":1279,"preSum":31121},{"ndv":11,"upper":0.8920,"lower":0.8810,"count":1140,"preSum":32400},{"ndv":25,"upper":0.9200,"lower":0.8930,"count":1165,"preSum":33540},{"ndv":28,"upper":0.9500,"lower":0.9210,"count":1176,"preSum":34705},{"ndv":37,"upper":0.9900,"lower":0.9510,"count":1207,"preSum":35881},{"ndv":39,"upper":1.0310,"lower":0.9910,"count":1171,"preSum":37088},{"ndv":40,"upper":1.0730,"lower":1.0320,"count":1169,"preSum":38259},{"ndv":56,"upper":1.1300,"lower":1.0740,"count":1223,"preSum":39428},{"ndv":65,"upper":1.2000,"lower":1.1310,"count":1227,"preSum":40651},{"ndv":70,"upper":1.2860,"lower":1.2010,"count":1138,"preSum":41878},{"ndv":59,"upper":1.3500,"lower":1.2870,"count":1189,"preSum":43016},{"ndv":82,"upper":1.4440,"lower":1.3510,"count":1138,"preSum":44205},{"ndv":105,"upper":1.5800,"lower":1.4450,"count":1150,"preSum":45343},{"ndv":82,"upper":1.6900,"lower":1.5820,"count":1169,"preSum":46493},{"ndv":41,"upper":1.7400,"lower":1.6920,"count":1144,"preSum":47662},{"ndv":53,"upper":1.8000,"lower":1.7410,"count":1224,"preSum":48806},{"ndv":45,"upper":1.8490,"lower":1.8020,"count":1192,"preSum":50030},{"ndv":17,"upper":1.8680,"lower":1.8500,"count":1174,"preSum":51222},{"ndv":26,"upper":1.9000,"lower":1.8690,"count":1155,"preSum":52396},{"ndv":62,"upper":1.9900,"lower":1.9010,"count":1159,"preSum":53551},{"ndv":68,"upper":2.1160,"lower":1.9910,"count":1160,"preSum":54710},{"ndv":68,"upper":2.2110,"lower":2.1170,"count":1155,"preSum":55870},{"ndv":51,"upper":2.3060,"lower":2.2120,"count":1188,"preSum":57025},{"ndv":41,"upper":2.3610,"lower":2.3070,"count":1139,"preSum":58213},{"ndv":39,"upper":2.4190,"lower":2.3630,"count":1166,"preSum":59352},{"ndv":54,"upper":2.5000,"lower":2.4200,"count":1149,"preSum":60518},{"ndv":96,"upper":2.6900,"lower":2.5010,"count":1199,"preSum":61667},{"ndv":14,"upper":2.7040,"lower":2.6910,"count":1171,"preSum":62866},{"ndv":143,"upper":3.2100,"lower":2.7050,"count":1162,"preSum":64037},{"ndv":226,"upper":3.9000,"lower":3.2120,"count":1156,"preSum":65199},{"ndv":101,"upper":4.3000,"lower":3.9010,"count":1254,"preSum":66355},{"ndv":319,"upper":5.6080,"lower":4.3080,"count":1137,"preSum":67609},{"ndv":463,"upper":6.9420,"lower":5.6090,"count":1137,"preSum":68746},{"ndv":554,"upper":9.0000,"lower":6.9480,"count":1140,"preSum":69883},{"ndv":624,"upper":11.3000,"lower":9.0100,"count":1143,"preSum":71023},{"ndv":429,"upper":107.3200,"lower":11.3010,"count":592,"preSum":72166}],"maxBucketSize":64,"type":"Double","sampleRate":0.82064223}','{"countArr":[466,436,495,443,566,443,588,443,1735,571,452,665,681,796],"valueArr":[0.1500,0.2000,0.3000,0.3200,0.3300,0.3400,0.3500,0.5900,0.5930,0.6000,0.8900,0.9000,1.0600,4.3050],"type":"Double","sampleRate":0.8206422281854961}',18463,0.037085027),('jala_wms_prod','shipping_container_header','cagecode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[5,13,5],"valueArr":["LC01","Lc01","lc01"],"type":"String","sampleRate":0.8206422281854961}',99978,0.037085027),('jala_wms_prod','shipping_container_header','cageid',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":100007,"lower":100007,"count":2,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[99978,5,3,13],"valueArr":[0,5,18,100005],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','carriercode',29,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"other","lower":"other","count":9,"preSum":0},{"ndv":1,"upper":"上海中集公联集装箱储运有限公司","lower":"上海中集公联集装箱储运有限公司","count":1,"preSum":9},{"ndv":1,"upper":"上海达赛物流有限公司","lower":"上海达赛物流有限公司","count":15,"preSum":10},{"ndv":1,"upper":"干线-溢宇","lower":"干线-溢宇","count":1,"preSum":25},{"ndv":1,"upper":"深圳市华夏龙供应链管理有限公司","lower":"深圳市华夏龙供应链管理有限公司","count":2,"preSum":26}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[26,18,45,1344,68598,90,697,1835,191,15553,4109,7260,100,23],"valueArr":["","0000111","EMS","OTHER","SF","SF1","SF2","SF3","ZT","ZTO","ZTOKY","shunfeng","上海恒兴国际物流有限公司","深圳市顺丰综合物流服务有限公司"],"type":"String","sampleRate":0.8206422281854961}',84,0.037085027),('jala_wms_prod','shipping_container_header','carrierservice',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[55741,14938,5851,1127,753],"valueArr":["CAINIAO","DOUYIN","JD","KUAISHOU","PINDUODUO"],"type":"String","sampleRate":0.8206422281854961}',21591,0.037085027),('jala_wms_prod','shipping_container_header','checkat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','checkby',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','checkedtype',9,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":3,"lower":3,"count":1,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[13,55845,44062,80],"valueArr":[0,1,4,5],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','code',2666031,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1563,"upper":"021DC1-62726","lower":"021DC1-0011","count":1563,"preSum":0},{"ndv":1563,"upper":"022DC-128700","lower":"021DC1-6294","count":1563,"preSum":1563},{"ndv":1563,"upper":"022DC-185246","lower":"022DC-128701","count":1563,"preSum":3126},{"ndv":1563,"upper":"022DC-257916","lower":"022DC-185247","count":1563,"preSum":4689},{"ndv":1563,"upper":"022DC-32622","lower":"022DC-257917","count":1563,"preSum":6252},{"ndv":1563,"upper":"022DC-396059","lower":"022DC-326227","count":1563,"preSum":7815},{"ndv":1563,"upper":"022DC-5589","lower":"022DC-396062","count":1563,"preSum":9378},{"ndv":1563,"upper":"022DC-99038","lower":"022DC-5591","count":1563,"preSum":10941},{"ndv":1563,"upper":"027DC-172340","lower":"022DC-99040","count":1563,"preSum":12504},{"ndv":1563,"upper":"027DC-234728","lower":"027DC-172341","count":1563,"preSum":14067},{"ndv":1563,"upper":"027DC-288836","lower":"027DC-234729","count":1563,"preSum":15630},{"ndv":1563,"upper":"027DC-343012","lower":"027DC-288838","count":1563,"preSum":17193},{"ndv":1563,"upper":"027DC-416250","lower":"027DC-343013","count":1563,"preSum":18756},{"ndv":1563,"upper":"027DC-492304","lower":"027DC-416254","count":1563,"preSum":20319},{"ndv":1563,"upper":"027DC-557628","lower":"027DC-49247","count":1563,"preSum":21882},{"ndv":1563,"upper":"027DC-615509","lower":"027DC-557630","count":1563,"preSum":23445},{"ndv":1563,"upper":"027DC-680151","lower":"027DC-615510","count":1563,"preSum":25008},{"ndv":1563,"upper":"027DC-749787","lower":"027DC-680152","count":1563,"preSum":26571},{"ndv":1563,"upper":"027DC-815329","lower":"027DC-749792","count":1563,"preSum":28134},{"ndv":1563,"upper":"028DC-30847","lower":"027DC-815779","count":1563,"preSum":29697},{"ndv":1563,"upper":"573DC-103688","lower":"028DC-30848","count":1563,"preSum":31260},{"ndv":1563,"upper":"573DC-1107443","lower":"573DC-103691","count":1563,"preSum":32823},{"ndv":1563,"upper":"573DC-1182665","lower":"573DC-1107446","count":1563,"preSum":34386},{"ndv":1563,"upper":"573DC-1254276","lower":"573DC-1182666","count":1563,"preSum":35949},{"ndv":1563,"upper":"573DC-1331820","lower":"573DC-1254277","count":1563,"preSum":37512},{"ndv":1563,"upper":"573DC-1397934","lower":"573DC-1331821","count":1563,"preSum":39075},{"ndv":1563,"upper":"573DC-1456078","lower":"573DC-1397946","count":1563,"preSum":40638},{"ndv":1563,"upper":"573DC-1503764","lower":"573DC-1456088","count":1563,"preSum":42201},{"ndv":1563,"upper":"573DC-1583391","lower":"573DC-1503768","count":1563,"preSum":43764},{"ndv":1563,"upper":"573DC-1659951","lower":"573DC-1583392","count":1563,"preSum":45327},{"ndv":1563,"upper":"573DC-174186","lower":"573DC-1659953","count":1563,"preSum":46890},{"ndv":1563,"upper":"573DC-1801868","lower":"573DC-1741869","count":1563,"preSum":48453},{"ndv":1563,"upper":"573DC-1861496","lower":"573DC-1801930","count":1563,"preSum":50016},{"ndv":1563,"upper":"573DC-1937745","lower":"573DC-1861499","count":1563,"preSum":51579},{"ndv":1563,"upper":"573DC-2021285","lower":"573DC-1937747","count":1563,"preSum":53142},{"ndv":1563,"upper":"573DC-208193","lower":"573DC-2021287","count":1563,"preSum":54705},{"ndv":1563,"upper":"573DC-2150398","lower":"573DC-208194","count":1563,"preSum":56268},{"ndv":1563,"upper":"573DC-2232844","lower":"573DC-2150399","count":1563,"preSum":57831},{"ndv":1563,"upper":"573DC-229585","lower":"573DC-2232849","count":1563,"preSum":59394},{"ndv":1563,"upper":"573DC-2360060","lower":"573DC-229587","count":1563,"preSum":60957},{"ndv":1563,"upper":"573DC-258338","lower":"573DC-2360061","count":1563,"preSum":62520},{"ndv":1563,"upper":"573DC-313658","lower":"573DC-258339","count":1563,"preSum":64083},{"ndv":1563,"upper":"573DC-369186","lower":"573DC-313659","count":1563,"preSum":65646},{"ndv":1563,"upper":"573DC-44983","lower":"573DC-36919","count":1563,"preSum":67209},{"ndv":1563,"upper":"573DC-516469","lower":"573DC-44984","count":1563,"preSum":68772},{"ndv":1563,"upper":"573DC-570612","lower":"573DC-516470","count":1563,"preSum":70335},{"ndv":1563,"upper":"573DC-645185","lower":"573DC-570615","count":1563,"preSum":71898},{"ndv":1563,"upper":"573DC-712359","lower":"573DC-645186","count":1563,"preSum":73461},{"ndv":1563,"upper":"573DC-777205","lower":"573DC-712360","count":1563,"preSum":75024},{"ndv":1563,"upper":"573DC-83290","lower":"573DC-777206","count":1563,"preSum":76587},{"ndv":1563,"upper":"573DC-894028","lower":"573DC-83291","count":1563,"preSum":78150},{"ndv":1563,"upper":"573DC-952181","lower":"573DC-894029","count":1563,"preSum":79713},{"ndv":1563,"upper":"763DC-111287","lower":"573DC-952182","count":1563,"preSum":81276},{"ndv":1563,"upper":"763DC-184969","lower":"763DC-111288","count":1563,"preSum":82839},{"ndv":1563,"upper":"763DC-248414","lower":"763DC-184970","count":1563,"preSum":84402},{"ndv":1563,"upper":"763DC-304861","lower":"763DC-248418","count":1563,"preSum":85965},{"ndv":1563,"upper":"763DC-371951","lower":"763DC-304862","count":1563,"preSum":87528},{"ndv":1563,"upper":"763DC-430579","lower":"763DC-371952","count":1563,"preSum":89091},{"ndv":1563,"upper":"763DC-499281","lower":"763DC-430581","count":1563,"preSum":90654},{"ndv":1563,"upper":"763DC-581811","lower":"763DC-499288","count":1563,"preSum":92217},{"ndv":1563,"upper":"763DC-652343","lower":"763DC-581813","count":1563,"preSum":93780},{"ndv":1563,"upper":"763DC-717007","lower":"763DC-652344","count":1563,"preSum":95343},{"ndv":1563,"upper":"SH01-23857","lower":"763DC-717009","count":1563,"preSum":96906},{"ndv":1532,"upper":"SH03-2658","lower":"SH01-23858","count":1532,"preSum":98469}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,0,0.037085027),('jala_wms_prod','shipping_container_header','companycode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[10639,354,89008],"valueArr":["JALA01","JALA02","JALA11"],"type":"String","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','containertype',75,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"027DCNB1","lower":"027DCNB1","count":59,"preSum":0},{"ndv":4,"upper":"1300951400","lower":"1300851000","count":38,"preSum":59},{"ndv":2,"upper":"1300951700","lower":"1300951600","count":9,"preSum":97},{"ndv":1,"upper":"1301003700","lower":"1301003700","count":30,"preSum":106},{"ndv":1,"upper":"1301162700","lower":"1301162700","count":88,"preSum":136},{"ndv":1,"upper":"1301162800","lower":"1301162800","count":12,"preSum":224},{"ndv":3,"upper":"2B0005","lower":"1301166600","count":18,"preSum":236},{"ndv":3,"upper":"2B003","lower":"2B001","count":23,"preSum":254},{"ndv":3,"upper":"2CMSF4","lower":"2CCX05S","count":17,"preSum":277},{"ndv":2,"upper":"2CPFY4","lower":"2CPFY3","count":13,"preSum":294},{"ndv":2,"upper":"2CVIP3","lower":"2CSXN02","count":50,"preSum":307},{"ndv":2,"upper":"2CZRT1","lower":"2CVIP6","count":22,"preSum":357},{"ndv":1,"upper":"2CZRT2","lower":"2CZRT2","count":17,"preSum":379},{"ndv":1,"upper":"2CZRT3","lower":"2CZRT3","count":20,"preSum":396},{"ndv":1,"upper":"2CZRT3S","lower":"2CZRT3S","count":47,"preSum":416},{"ndv":2,"upper":"2CZRT5","lower":"2CZRT4","count":40,"preSum":463},{"ndv":1,"upper":"2CZRT5S","lower":"2CZRT5S","count":15,"preSum":503},{"ndv":1,"upper":"CDTHREE","lower":"CDTHREE","count":20,"preSum":518}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[92606,480,398,103,121,164,670,503,199,772,968,98,982,1399],"valueArr":["","027DCNB2","027DCNB3","1300951200","1301163100","2B0004","2B0006","2B0008","2B004","CC123456","CDONE","CDTWO","CS","JALA1000"],"type":"String","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','countindex',1220,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":14,"lower":14,"count":81,"preSum":0},{"ndv":1,"upper":15,"lower":15,"count":84,"preSum":81},{"ndv":1,"upper":16,"lower":16,"count":60,"preSum":165},{"ndv":1,"upper":17,"lower":17,"count":60,"preSum":225},{"ndv":1,"upper":18,"lower":18,"count":54,"preSum":285},{"ndv":1,"upper":19,"lower":19,"count":46,"preSum":339},{"ndv":1,"upper":20,"lower":20,"count":49,"preSum":385},{"ndv":1,"upper":21,"lower":21,"count":36,"preSum":434},{"ndv":1,"upper":22,"lower":22,"count":37,"preSum":470},{"ndv":1,"upper":23,"lower":23,"count":42,"preSum":507},{"ndv":1,"upper":24,"lower":24,"count":35,"preSum":549},{"ndv":1,"upper":25,"lower":25,"count":33,"preSum":584},{"ndv":1,"upper":26,"lower":26,"count":27,"preSum":617},{"ndv":2,"upper":28,"lower":27,"count":43,"preSum":644},{"ndv":2,"upper":30,"lower":29,"count":37,"preSum":687},{"ndv":2,"upper":32,"lower":31,"count":32,"preSum":724},{"ndv":2,"upper":34,"lower":33,"count":36,"preSum":756},{"ndv":2,"upper":36,"lower":35,"count":37,"preSum":792},{"ndv":2,"upper":38,"lower":37,"count":38,"preSum":829},{"ndv":2,"upper":40,"lower":39,"count":29,"preSum":867},{"ndv":3,"upper":43,"lower":41,"count":28,"preSum":896},{"ndv":3,"upper":46,"lower":44,"count":33,"preSum":924},{"ndv":3,"upper":49,"lower":47,"count":32,"preSum":957},{"ndv":2,"upper":51,"lower":50,"count":26,"preSum":989},{"ndv":3,"upper":54,"lower":52,"count":29,"preSum":1015},{"ndv":4,"upper":58,"lower":55,"count":34,"preSum":1044},{"ndv":4,"upper":62,"lower":59,"count":32,"preSum":1078},{"ndv":4,"upper":66,"lower":63,"count":28,"preSum":1110},{"ndv":6,"upper":72,"lower":67,"count":28,"preSum":1138},{"ndv":5,"upper":77,"lower":73,"count":29,"preSum":1166},{"ndv":4,"upper":81,"lower":78,"count":27,"preSum":1195},{"ndv":6,"upper":87,"lower":82,"count":30,"preSum":1222},{"ndv":6,"upper":93,"lower":88,"count":26,"preSum":1252},{"ndv":4,"upper":97,"lower":94,"count":27,"preSum":1278},{"ndv":12,"upper":110,"lower":98,"count":27,"preSum":1305},{"ndv":17,"upper":134,"lower":111,"count":26,"preSum":1332},{"ndv":16,"upper":150,"lower":135,"count":26,"preSum":1358},{"ndv":19,"upper":196,"lower":151,"count":26,"preSum":1384},{"ndv":14,"upper":212,"lower":197,"count":26,"preSum":1410},{"ndv":18,"upper":240,"lower":213,"count":26,"preSum":1436},{"ndv":17,"upper":259,"lower":241,"count":26,"preSum":1462},{"ndv":16,"upper":277,"lower":260,"count":27,"preSum":1488},{"ndv":19,"upper":362,"lower":278,"count":26,"preSum":1515},{"ndv":23,"upper":397,"lower":363,"count":26,"preSum":1541},{"ndv":26,"upper":670,"lower":398,"count":26,"preSum":1567},{"ndv":26,"upper":710,"lower":672,"count":26,"preSum":1593},{"ndv":8,"upper":1112,"lower":711,"count":8,"preSum":1619}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[92252,1511,1052,793,611,502,338,302,279,208,168,144,119,95],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','counttotal',182,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":15,"lower":15,"count":124,"preSum":0},{"ndv":1,"upper":16,"lower":16,"count":82,"preSum":124},{"ndv":1,"upper":17,"lower":17,"count":127,"preSum":206},{"ndv":1,"upper":18,"lower":18,"count":111,"preSum":333},{"ndv":1,"upper":19,"lower":19,"count":125,"preSum":444},{"ndv":1,"upper":20,"lower":20,"count":94,"preSum":569},{"ndv":1,"upper":21,"lower":21,"count":114,"preSum":663},{"ndv":1,"upper":22,"lower":22,"count":87,"preSum":777},{"ndv":1,"upper":23,"lower":23,"count":85,"preSum":864},{"ndv":2,"upper":25,"lower":24,"count":99,"preSum":949},{"ndv":1,"upper":26,"lower":26,"count":72,"preSum":1048},{"ndv":1,"upper":27,"lower":27,"count":62,"preSum":1120},{"ndv":1,"upper":28,"lower":28,"count":57,"preSum":1182},{"ndv":2,"upper":30,"lower":29,"count":123,"preSum":1239},{"ndv":2,"upper":32,"lower":31,"count":85,"preSum":1362},{"ndv":1,"upper":33,"lower":33,"count":48,"preSum":1447},{"ndv":2,"upper":35,"lower":34,"count":46,"preSum":1495},{"ndv":3,"upper":38,"lower":36,"count":69,"preSum":1541},{"ndv":3,"upper":41,"lower":39,"count":50,"preSum":1610},{"ndv":2,"upper":43,"lower":42,"count":48,"preSum":1660},{"ndv":3,"upper":46,"lower":44,"count":51,"preSum":1708},{"ndv":4,"upper":50,"lower":47,"count":70,"preSum":1759},{"ndv":2,"upper":52,"lower":51,"count":50,"preSum":1829},{"ndv":5,"upper":57,"lower":53,"count":63,"preSum":1879},{"ndv":5,"upper":62,"lower":58,"count":53,"preSum":1942},{"ndv":3,"upper":65,"lower":63,"count":55,"preSum":1995},{"ndv":5,"upper":70,"lower":66,"count":54,"preSum":2050},{"ndv":4,"upper":76,"lower":72,"count":59,"preSum":2104},{"ndv":6,"upper":83,"lower":77,"count":49,"preSum":2163},{"ndv":9,"upper":94,"lower":84,"count":47,"preSum":2212},{"ndv":7,"upper":106,"lower":97,"count":55,"preSum":2259},{"ndv":8,"upper":119,"lower":108,"count":47,"preSum":2314},{"ndv":4,"upper":130,"lower":120,"count":52,"preSum":2361},{"ndv":6,"upper":156,"lower":132,"count":48,"preSum":2413},{"ndv":11,"upper":195,"lower":159,"count":51,"preSum":2461},{"ndv":7,"upper":247,"lower":196,"count":49,"preSum":2512},{"ndv":3,"upper":269,"lower":250,"count":54,"preSum":2561},{"ndv":4,"upper":308,"lower":282,"count":50,"preSum":2615},{"ndv":4,"upper":336,"lower":316,"count":48,"preSum":2665},{"ndv":5,"upper":620,"lower":349,"count":49,"preSum":2713},{"ndv":3,"upper":1086,"lower":677,"count":58,"preSum":2762},{"ndv":1,"upper":1113,"lower":1113,"count":56,"preSum":2820},{"ndv":1,"upper":1427,"lower":1427,"count":22,"preSum":2876}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[90721,903,738,673,671,879,399,337,428,311,348,217,206,272],"valueArr":[1,2,3,4,5,6,7,8,9,10,11,12,13,14],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','created',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','createdby',468,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"000002","lower":"000002","count":1614,"preSum":0},{"ndv":1,"upper":"000004","lower":"000004","count":2007,"preSum":1614},{"ndv":7,"upper":"000088","lower":"000005","count":432,"preSum":3621},{"ndv":12,"upper":"0220006","lower":"000089","count":2328,"preSum":4053},{"ndv":4,"upper":"0220013","lower":"0220008","count":447,"preSum":6381},{"ndv":4,"upper":"0220017","lower":"0220014","count":558,"preSum":6828},{"ndv":15,"upper":"0220080","lower":"0220018","count":415,"preSum":7386},{"ndv":5,"upper":"02700003","lower":"0220088","count":1748,"preSum":7801},{"ndv":1,"upper":"02700009","lower":"02700009","count":1791,"preSum":9549},{"ndv":6,"upper":"02700025","lower":"02700020","count":404,"preSum":11340},{"ndv":10,"upper":"02700035","lower":"02700026","count":389,"preSum":11744},{"ndv":31,"upper":"10000013","lower":"02700037","count":480,"preSum":12133},{"ndv":6,"upper":"1000003","lower":"10000014","count":448,"preSum":12613},{"ndv":8,"upper":"10000108","lower":"1000004","count":397,"preSum":13061},{"ndv":5,"upper":"10000131","lower":"10000114","count":387,"preSum":13458},{"ndv":11,"upper":"1000019","lower":"10000134","count":394,"preSum":13845},{"ndv":2,"upper":"10001","lower":"1000020","count":1140,"preSum":14239},{"ndv":1,"upper":"10003","lower":"10003","count":1450,"preSum":15379},{"ndv":2,"upper":"10005","lower":"10004","count":551,"preSum":16829},{"ndv":4,"upper":"10009","lower":"10006","count":535,"preSum":17380},{"ndv":27,"upper":"41762241","lower":"10102","count":386,"preSum":17915},{"ndv":16,"upper":"42035274","lower":"41762287","count":467,"preSum":18301},{"ndv":8,"upper":"42111479","lower":"42043184","count":474,"preSum":18768},{"ndv":20,"upper":"57302008","lower":"42111665","count":421,"preSum":19242},{"ndv":20,"upper":"BXH","lower":"57302009","count":693,"preSum":19663},{"ndv":4,"upper":"hxy","lower":"CN","count":955,"preSum":20356},{"ndv":7,"upper":"lyg","lower":"JQQ","count":827,"preSum":21311},{"ndv":8,"upper":"yxy","lower":"PZ","count":677,"preSum":22138},{"ndv":3,"upper":"zhaolingling","lower":"YYJ","count":736,"preSum":22815},{"ndv":2,"upper":"ZHC01","lower":"ZHC","count":552,"preSum":23551},{"ndv":2,"upper":"ZRX","lower":"zjf","count":383,"preSum":24103},{"ndv":2,"upper":"zyr","lower":"ZY","count":2,"preSum":24486}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[2684,2228,6229,2285,11357,2823,2927,2927,3552,2599,8070,10002,14865,2965],"valueArr":["000001","000003","0220005","02700005","02700010","10000002","10000004","40401644","40721814","41157743","41509297","41580109","42008280","42196770"],"type":"String","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','doubleoqcby',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','erpordertype',6,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[8,53,66,199,88965,10696],"valueArr":["MM018","PP001","QM001","SDI17","deliveryorder","stockout"],"type":"String","sampleRate":0.8206422281854961}',14,0.037085027),('jala_wms_prod','shipping_container_header','groupindex',1328,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":15,"lower":0,"count":2781,"preSum":0},{"ndv":1,"upper":16,"lower":16,"count":2673,"preSum":2781},{"ndv":1,"upper":17,"lower":17,"count":2554,"preSum":5454},{"ndv":1,"upper":18,"lower":18,"count":2386,"preSum":8008},{"ndv":1,"upper":19,"lower":19,"count":2332,"preSum":10394},{"ndv":1,"upper":20,"lower":20,"count":2273,"preSum":12726},{"ndv":1,"upper":21,"lower":21,"count":735,"preSum":14999},{"ndv":1,"upper":22,"lower":22,"count":729,"preSum":15734},{"ndv":2,"upper":24,"lower":23,"count":1321,"preSum":16463},{"ndv":2,"upper":26,"lower":25,"count":1138,"preSum":17784},{"ndv":2,"upper":28,"lower":27,"count":946,"preSum":18922},{"ndv":2,"upper":30,"lower":29,"count":968,"preSum":19868},{"ndv":2,"upper":32,"lower":31,"count":915,"preSum":20836},{"ndv":2,"upper":34,"lower":33,"count":845,"preSum":21751},{"ndv":2,"upper":36,"lower":35,"count":864,"preSum":22596},{"ndv":2,"upper":38,"lower":37,"count":802,"preSum":23460},{"ndv":2,"upper":40,"lower":39,"count":797,"preSum":24262},{"ndv":2,"upper":42,"lower":41,"count":784,"preSum":25059},{"ndv":2,"upper":44,"lower":43,"count":757,"preSum":25843},{"ndv":2,"upper":46,"lower":45,"count":724,"preSum":26600},{"ndv":3,"upper":49,"lower":47,"count":1029,"preSum":27324},{"ndv":3,"upper":52,"lower":50,"count":983,"preSum":28353},{"ndv":3,"upper":55,"lower":53,"count":937,"preSum":29336},{"ndv":3,"upper":58,"lower":56,"count":920,"preSum":30273},{"ndv":3,"upper":61,"lower":59,"count":888,"preSum":31193},{"ndv":3,"upper":64,"lower":62,"count":833,"preSum":32081},{"ndv":3,"upper":67,"lower":65,"count":823,"preSum":32914},{"ndv":3,"upper":70,"lower":68,"count":755,"preSum":33737},{"ndv":3,"upper":73,"lower":71,"count":769,"preSum":34492},{"ndv":3,"upper":76,"lower":74,"count":736,"preSum":35261},{"ndv":4,"upper":80,"lower":77,"count":920,"preSum":35997},{"ndv":3,"upper":83,"lower":81,"count":720,"preSum":36917},{"ndv":4,"upper":87,"lower":84,"count":897,"preSum":37637},{"ndv":4,"upper":91,"lower":88,"count":861,"preSum":38534},{"ndv":4,"upper":95,"lower":92,"count":822,"preSum":39395},{"ndv":4,"upper":99,"lower":96,"count":798,"preSum":40217},{"ndv":12,"upper":111,"lower":100,"count":715,"preSum":41015},{"ndv":24,"upper":135,"lower":112,"count":713,"preSum":41730},{"ndv":31,"upper":166,"lower":136,"count":712,"preSum":42443},{"ndv":77,"upper":243,"lower":167,"count":714,"preSum":43155},{"ndv":162,"upper":406,"lower":244,"count":711,"preSum":43869},{"ndv":201,"upper":642,"lower":407,"count":711,"preSum":44580},{"ndv":136,"upper":931,"lower":643,"count":166,"preSum":45291}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[13391,3841,3615,3497,3430,3257,3165,3157,3090,2981,2788,2818,2821,2693],"valueArr":[1,2,3,4,5,6,7,8,9,10,11,12,13,14],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','groupnum',206,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":15,"lower":0,"count":567,"preSum":0},{"ndv":1,"upper":16,"lower":16,"count":400,"preSum":567},{"ndv":1,"upper":17,"lower":17,"count":397,"preSum":967},{"ndv":1,"upper":18,"lower":18,"count":413,"preSum":1364},{"ndv":1,"upper":19,"lower":19,"count":336,"preSum":1777},{"ndv":1,"upper":20,"lower":20,"count":340,"preSum":2113},{"ndv":1,"upper":21,"lower":21,"count":323,"preSum":2453},{"ndv":1,"upper":22,"lower":22,"count":296,"preSum":2776},{"ndv":1,"upper":23,"lower":23,"count":279,"preSum":3072},{"ndv":1,"upper":24,"lower":24,"count":308,"preSum":3351},{"ndv":1,"upper":25,"lower":25,"count":247,"preSum":3659},{"ndv":1,"upper":26,"lower":26,"count":235,"preSum":3906},{"ndv":1,"upper":27,"lower":27,"count":246,"preSum":4141},{"ndv":1,"upper":28,"lower":28,"count":218,"preSum":4387},{"ndv":1,"upper":29,"lower":29,"count":202,"preSum":4605},{"ndv":1,"upper":30,"lower":30,"count":196,"preSum":4807},{"ndv":1,"upper":31,"lower":31,"count":210,"preSum":5003},{"ndv":1,"upper":32,"lower":32,"count":197,"preSum":5213},{"ndv":1,"upper":33,"lower":33,"count":233,"preSum":5410},{"ndv":1,"upper":34,"lower":34,"count":199,"preSum":5643},{"ndv":1,"upper":35,"lower":35,"count":185,"preSum":5842},{"ndv":1,"upper":36,"lower":36,"count":185,"preSum":6027},{"ndv":1,"upper":37,"lower":37,"count":165,"preSum":6212},{"ndv":1,"upper":38,"lower":38,"count":153,"preSum":6377},{"ndv":2,"upper":40,"lower":39,"count":271,"preSum":6530},{"ndv":2,"upper":42,"lower":41,"count":253,"preSum":6801},{"ndv":2,"upper":44,"lower":43,"count":270,"preSum":7054},{"ndv":2,"upper":46,"lower":45,"count":206,"preSum":7324},{"ndv":2,"upper":48,"lower":47,"count":184,"preSum":7530},{"ndv":2,"upper":50,"lower":49,"count":147,"preSum":7714},{"ndv":3,"upper":53,"lower":51,"count":206,"preSum":7861},{"ndv":3,"upper":56,"lower":54,"count":200,"preSum":8067},{"ndv":4,"upper":60,"lower":57,"count":198,"preSum":8267},{"ndv":3,"upper":63,"lower":61,"count":152,"preSum":8465},{"ndv":5,"upper":68,"lower":64,"count":161,"preSum":8617},{"ndv":7,"upper":75,"lower":69,"count":151,"preSum":8778},{"ndv":10,"upper":85,"lower":76,"count":163,"preSum":8929},{"ndv":12,"upper":97,"lower":86,"count":156,"preSum":9092},{"ndv":37,"upper":168,"lower":98,"count":106,"preSum":9248}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[64730,7264,5037,3549,2907,1318,1066,958,896,687,610,552,561,512],"valueArr":[1,2,3,4,5,6,7,8,9,10,11,12,13,14],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','handoverat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','handoverby',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[15,41],"valueArr":["02700002","40721814"],"type":"String","sampleRate":0.8206422281854961}',99945,0.037085027),('jala_wms_prod','shipping_container_header','handoverconfirmat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','handoverconfirmby',90,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":"0220012","lower":"0220003","count":44,"preSum":0},{"ndv":1,"upper":"0220019","lower":"0220019","count":42,"preSum":44},{"ndv":2,"upper":"0220058","lower":"0220031","count":22,"preSum":86},{"ndv":4,"upper":"02700001","lower":"0220087","count":59,"preSum":108},{"ndv":2,"upper":"02700003","lower":"02700002","count":16,"preSum":167},{"ndv":1,"upper":"02700237","lower":"02700237","count":56,"preSum":183},{"ndv":1,"upper":"02700239","lower":"02700239","count":19,"preSum":239},{"ndv":1,"upper":"02700240","lower":"02700240","count":73,"preSum":258},{"ndv":1,"upper":"02700242","lower":"02700242","count":56,"preSum":331},{"ndv":1,"upper":"02700244","lower":"02700244","count":57,"preSum":387},{"ndv":1,"upper":"02700251","lower":"02700251","count":72,"preSum":444},{"ndv":1,"upper":"02700252","lower":"02700252","count":25,"preSum":516},{"ndv":1,"upper":"02700254","lower":"02700254","count":65,"preSum":541},{"ndv":1,"upper":"02700256","lower":"02700256","count":47,"preSum":606},{"ndv":5,"upper":"40858179","lower":"02700257","count":43,"preSum":653},{"ndv":2,"upper":"41072349","lower":"40859561","count":50,"preSum":696},{"ndv":2,"upper":"41412544","lower":"41306222","count":41,"preSum":746},{"ndv":4,"upper":"41851520","lower":"41580039","count":30,"preSum":787},{"ndv":2,"upper":"41927002","lower":"41896759","count":52,"preSum":817},{"ndv":2,"upper":"42080021","lower":"42043184","count":46,"preSum":869},{"ndv":1,"upper":"42111479","lower":"42111479","count":18,"preSum":915},{"ndv":4,"upper":"42165775","lower":"42126804","count":23,"preSum":933},{"ndv":2,"upper":"42196773","lower":"42196764","count":7,"preSum":956}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[89,88,120,100,164,85,92,171,82,148,74,84,80,77],"valueArr":["02700231","02700232","02700234","02700236","02700241","02700245","02700246","02700247","02700248","02700249","02700255","42035274","42104983","42152732"],"type":"String","sampleRate":0.8206422281854961}',97584,0.037085027),('jala_wms_prod','shipping_container_header','height',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.82064223}','{"countArr":[100001],"valueArr":[0.0000],"type":"Double","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','hxqty',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":1,"lower":1,"count":2,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[972],"valueArr":[0],"type":"Int","sampleRate":0.8206422281854961}',99027,0.037085027),('jala_wms_prod','shipping_container_header','id',2664344,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1563,"upper":1081522,"lower":1017411,"count":1563,"preSum":0},{"ndv":1563,"upper":1150728,"lower":1081523,"count":1563,"preSum":1563},{"ndv":1563,"upper":1229759,"lower":1150730,"count":1563,"preSum":3126},{"ndv":1563,"upper":1316332,"lower":1229761,"count":1563,"preSum":4689},{"ndv":1563,"upper":1391064,"lower":1316333,"count":1563,"preSum":6252},{"ndv":1563,"upper":1459627,"lower":1391100,"count":1563,"preSum":7815},{"ndv":1563,"upper":1524800,"lower":1459628,"count":1563,"preSum":9378},{"ndv":1563,"upper":1596036,"lower":1524803,"count":1563,"preSum":10941},{"ndv":1563,"upper":1666201,"lower":1596038,"count":1563,"preSum":12504},{"ndv":1563,"upper":1737798,"lower":1666202,"count":1563,"preSum":14067},{"ndv":1563,"upper":1801641,"lower":1737799,"count":1563,"preSum":15630},{"ndv":1563,"upper":1866101,"lower":1801642,"count":1563,"preSum":17193},{"ndv":1563,"upper":1934225,"lower":1866103,"count":1563,"preSum":18756},{"ndv":1563,"upper":2057146,"lower":1934226,"count":1563,"preSum":20319},{"ndv":1563,"upper":2124316,"lower":2057147,"count":1563,"preSum":21882},{"ndv":1563,"upper":2203863,"lower":2124317,"count":1563,"preSum":23445},{"ndv":1563,"upper":2281687,"lower":2203864,"count":1563,"preSum":25008},{"ndv":1563,"upper":2346073,"lower":2281688,"count":1563,"preSum":26571},{"ndv":1563,"upper":2457135,"lower":2346074,"count":1563,"preSum":28134},{"ndv":1563,"upper":2520199,"lower":2457136,"count":1563,"preSum":29697},{"ndv":1563,"upper":2591772,"lower":2520201,"count":1563,"preSum":31260},{"ndv":1563,"upper":2653732,"lower":2591773,"count":1563,"preSum":32823},{"ndv":1563,"upper":2725794,"lower":2653735,"count":1563,"preSum":34386},{"ndv":1563,"upper":2803971,"lower":2725795,"count":1563,"preSum":35949},{"ndv":1563,"upper":2851265,"lower":2803975,"count":1563,"preSum":37512},{"ndv":1563,"upper":2919996,"lower":2851266,"count":1563,"preSum":39075},{"ndv":1563,"upper":2975499,"lower":2919998,"count":1563,"preSum":40638},{"ndv":1563,"upper":3033853,"lower":2976099,"count":1563,"preSum":42201},{"ndv":1563,"upper":3101443,"lower":3033855,"count":1563,"preSum":43764},{"ndv":1563,"upper":3166262,"lower":3101444,"count":1563,"preSum":45327},{"ndv":1563,"upper":3228138,"lower":3166263,"count":1563,"preSum":46890},{"ndv":1563,"upper":3297526,"lower":3228139,"count":1563,"preSum":48453},{"ndv":1563,"upper":3371635,"lower":3297532,"count":1563,"preSum":50016},{"ndv":1563,"upper":3460501,"lower":3371636,"count":1563,"preSum":51579},{"ndv":1563,"upper":3545573,"lower":3460503,"count":1563,"preSum":53142},{"ndv":1563,"upper":3634286,"lower":3545577,"count":1563,"preSum":54705},{"ndv":1563,"upper":3718373,"lower":3634287,"count":1563,"preSum":56268},{"ndv":1563,"upper":3808355,"lower":3718375,"count":1563,"preSum":57831},{"ndv":1563,"upper":3885300,"lower":3808356,"count":1563,"preSum":59394},{"ndv":1563,"upper":3956053,"lower":3885301,"count":1563,"preSum":60957},{"ndv":1563,"upper":4037593,"lower":3958525,"count":1563,"preSum":62520},{"ndv":1563,"upper":4106211,"lower":4037594,"count":1563,"preSum":64083},{"ndv":1563,"upper":4174578,"lower":4106213,"count":1563,"preSum":65646},{"ndv":1563,"upper":4243652,"lower":4174579,"count":1563,"preSum":67209},{"ndv":1563,"upper":4326243,"lower":4243653,"count":1563,"preSum":68772},{"ndv":1563,"upper":4398974,"lower":4326244,"count":1563,"preSum":70335},{"ndv":1563,"upper":4478716,"lower":4398975,"count":1563,"preSum":71898},{"ndv":1563,"upper":4576457,"lower":4478717,"count":1563,"preSum":73461},{"ndv":1563,"upper":4640299,"lower":4576458,"count":1563,"preSum":75024},{"ndv":1563,"upper":4707339,"lower":4640300,"count":1563,"preSum":76587},{"ndv":1563,"upper":4778049,"lower":4707340,"count":1563,"preSum":78150},{"ndv":1563,"upper":4845166,"lower":4778051,"count":1563,"preSum":79713},{"ndv":1563,"upper":4936796,"lower":4845167,"count":1563,"preSum":81276},{"ndv":1563,"upper":5019304,"lower":4936798,"count":1563,"preSum":82839},{"ndv":1563,"upper":5109296,"lower":5019305,"count":1563,"preSum":84402},{"ndv":1563,"upper":5172380,"lower":5109297,"count":1563,"preSum":85965},{"ndv":1563,"upper":5249546,"lower":5172381,"count":1563,"preSum":87528},{"ndv":1563,"upper":5322055,"lower":5249792,"count":1563,"preSum":89091},{"ndv":1563,"upper":5416720,"lower":5322056,"count":1563,"preSum":90654},{"ndv":1563,"upper":5483475,"lower":5416721,"count":1563,"preSum":92217},{"ndv":1563,"upper":5558664,"lower":5483477,"count":1563,"preSum":93780},{"ndv":1563,"upper":5642762,"lower":5558666,"count":1563,"preSum":95343},{"ndv":1563,"upper":5711721,"lower":5642763,"count":1563,"preSum":96906},{"ndv":1532,"upper":5801008,"lower":5711723,"count":1532,"preSum":98469}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}',null,0,0.037085027),('jala_wms_prod','shipping_container_header','issubscribe',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[30123,68600,1278],"valueArr":[0,1,999],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','lastupdated',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','lastupdatedby',527,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"000003","lower":"000002","count":790,"preSum":0},{"ndv":8,"upper":"000088","lower":"000004","count":313,"preSum":790},{"ndv":14,"upper":"0220011","lower":"000089","count":468,"preSum":1103},{"ndv":2,"upper":"0220013","lower":"0220012","count":286,"preSum":1571},{"ndv":3,"upper":"0220016","lower":"0220014","count":361,"preSum":1857},{"ndv":2,"upper":"0220018","lower":"0220017","count":384,"preSum":2218},{"ndv":16,"upper":"0220080","lower":"0220019","count":292,"preSum":2602},{"ndv":8,"upper":"02700003","lower":"0220087","count":931,"preSum":2894},{"ndv":5,"upper":"02700024","lower":"02700020","count":332,"preSum":3825},{"ndv":6,"upper":"02700030","lower":"02700025","count":280,"preSum":4157},{"ndv":10,"upper":"02700042","lower":"02700031","count":272,"preSum":4437},{"ndv":23,"upper":"02700234","lower":"02700043","count":349,"preSum":4709},{"ndv":5,"upper":"02700241","lower":"02700236","count":412,"preSum":5058},{"ndv":4,"upper":"02700246","lower":"02700242","count":290,"preSum":5470},{"ndv":3,"upper":"02700249","lower":"02700247","count":401,"preSum":5760},{"ndv":5,"upper":"02700256","lower":"02700251","count":283,"preSum":6161},{"ndv":8,"upper":"10000013","lower":"02700257","count":319,"preSum":6444},{"ndv":4,"upper":"10000022","lower":"10000014","count":294,"preSum":6763},{"ndv":4,"upper":"1000005","lower":"10000027","count":355,"preSum":7057},{"ndv":9,"upper":"1000012","lower":"1000006","count":360,"preSum":7412},{"ndv":7,"upper":"1000014","lower":"1000013","count":283,"preSum":7772},{"ndv":5,"upper":"1000018","lower":"10000140","count":303,"preSum":8055},{"ndv":3,"upper":"10001","lower":"1000019","count":861,"preSum":8358},{"ndv":1,"upper":"10003","lower":"10003","count":968,"preSum":9219},{"ndv":2,"upper":"10005","lower":"10004","count":353,"preSum":10187},{"ndv":23,"upper":"41412544","lower":"10006","count":273,"preSum":10540},{"ndv":2,"upper":"41762241","lower":"41512820","count":272,"preSum":10813},{"ndv":11,"upper":"41927293","lower":"41762287","count":282,"preSum":11085},{"ndv":6,"upper":"42043184","lower":"41940218","count":306,"preSum":11367},{"ndv":7,"upper":"42111479","lower":"42080021","count":345,"preSum":11673},{"ndv":11,"upper":"42196807","lower":"42111665","count":271,"preSum":12018},{"ndv":14,"upper":"57302013","lower":"42196820","count":345,"preSum":12289},{"ndv":16,"upper":"BMJ","lower":"57302014","count":545,"preSum":12634},{"ndv":1,"upper":"BXH","lower":"BXH","count":362,"preSum":13179},{"ndv":8,"upper":"HP","lower":"chendaolong","count":331,"preSum":13541},{"ndv":7,"upper":"LQ101","lower":"hxy","count":350,"preSum":13872},{"ndv":8,"upper":"shenmengliang","lower":"LSH","count":274,"preSum":14222},{"ndv":11,"upper":"YJR","lower":"suchenbo","count":395,"preSum":14496},{"ndv":1,"upper":"yxy","lower":"yxy","count":647,"preSum":14891},{"ndv":5,"upper":"zhaolingling","lower":"YYJ","count":776,"preSum":15538},{"ndv":2,"upper":"ZHC01","lower":"ZHC","count":552,"preSum":16314},{"ndv":3,"upper":"ZRX","lower":"zjf","count":451,"preSum":16866},{"ndv":2,"upper":"zyr","lower":"ZY","count":2,"preSum":17317}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[1920,6113,2065,1602,1717,11247,2823,2927,1393,2458,3533,5229,8397,31258],"valueArr":["000001","0220005","0220006","02700005","02700009","02700010","10000002","10000004","40401644","41157743","41509297","41580109","42008280","api"],"type":"String","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','length',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.82064223}','{"countArr":[100001],"valueArr":[0.0000],"type":"Double","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','loadid',6687,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":25,"upper":185,"lower":64,"count":43,"preSum":0},{"ndv":25,"upper":767,"lower":246,"count":43,"preSum":43},{"ndv":29,"upper":1215,"lower":896,"count":44,"preSum":86},{"ndv":28,"upper":1509,"lower":1216,"count":45,"preSum":130},{"ndv":27,"upper":2127,"lower":1510,"count":43,"preSum":175},{"ndv":34,"upper":2385,"lower":2128,"count":43,"preSum":218},{"ndv":20,"upper":2526,"lower":2407,"count":43,"preSum":261},{"ndv":8,"upper":2564,"lower":2527,"count":47,"preSum":304},{"ndv":8,"upper":2584,"lower":2569,"count":51,"preSum":351},{"ndv":6,"upper":2601,"lower":2585,"count":50,"preSum":402},{"ndv":8,"upper":2613,"lower":2603,"count":52,"preSum":452},{"ndv":15,"upper":2805,"lower":2619,"count":43,"preSum":504},{"ndv":20,"upper":3197,"lower":2810,"count":43,"preSum":547},{"ndv":29,"upper":3576,"lower":3198,"count":43,"preSum":590},{"ndv":24,"upper":100551,"lower":3577,"count":43,"preSum":633},{"ndv":32,"upper":101402,"lower":100571,"count":43,"preSum":676},{"ndv":30,"upper":101652,"lower":101404,"count":43,"preSum":719},{"ndv":40,"upper":102224,"lower":101725,"count":45,"preSum":762},{"ndv":26,"upper":102913,"lower":102275,"count":43,"preSum":807},{"ndv":32,"upper":103476,"lower":102919,"count":43,"preSum":850},{"ndv":24,"upper":104269,"lower":103497,"count":44,"preSum":893},{"ndv":17,"upper":104605,"lower":104272,"count":49,"preSum":937},{"ndv":15,"upper":104819,"lower":104638,"count":46,"preSum":986},{"ndv":22,"upper":104993,"lower":104841,"count":44,"preSum":1032},{"ndv":28,"upper":105269,"lower":105010,"count":43,"preSum":1076},{"ndv":22,"upper":105530,"lower":105276,"count":44,"preSum":1119},{"ndv":21,"upper":105703,"lower":105538,"count":45,"preSum":1163},{"ndv":22,"upper":105994,"lower":105705,"count":43,"preSum":1208},{"ndv":25,"upper":106177,"lower":105996,"count":47,"preSum":1251},{"ndv":33,"upper":106541,"lower":106178,"count":43,"preSum":1298},{"ndv":26,"upper":106688,"lower":106545,"count":46,"preSum":1341},{"ndv":15,"upper":106788,"lower":106691,"count":43,"preSum":1387},{"ndv":17,"upper":200052,"lower":106790,"count":43,"preSum":1430},{"ndv":22,"upper":200245,"lower":200053,"count":56,"preSum":1473},{"ndv":27,"upper":300385,"lower":200257,"count":44,"preSum":1529},{"ndv":21,"upper":300507,"lower":300386,"count":43,"preSum":1573},{"ndv":27,"upper":300665,"lower":300511,"count":44,"preSum":1616},{"ndv":19,"upper":300769,"lower":300666,"count":43,"preSum":1660},{"ndv":17,"upper":300915,"lower":300770,"count":43,"preSum":1703},{"ndv":19,"upper":301084,"lower":300916,"count":44,"preSum":1746},{"ndv":27,"upper":301226,"lower":301085,"count":43,"preSum":1790},{"ndv":17,"upper":301281,"lower":301227,"count":45,"preSum":1833},{"ndv":23,"upper":301434,"lower":301317,"count":43,"preSum":1878},{"ndv":19,"upper":301663,"lower":301443,"count":46,"preSum":1921},{"ndv":25,"upper":301889,"lower":301664,"count":50,"preSum":1967},{"ndv":20,"upper":302009,"lower":301897,"count":48,"preSum":2017},{"ndv":19,"upper":302114,"lower":302010,"count":43,"preSum":2065},{"ndv":21,"upper":302296,"lower":302117,"count":43,"preSum":2108},{"ndv":30,"upper":302527,"lower":302299,"count":46,"preSum":2151},{"ndv":23,"upper":302675,"lower":302536,"count":43,"preSum":2197},{"ndv":27,"upper":302857,"lower":302683,"count":45,"preSum":2240},{"ndv":9,"upper":302897,"lower":302858,"count":43,"preSum":2285},{"ndv":17,"upper":302976,"lower":302898,"count":43,"preSum":2328},{"ndv":27,"upper":303187,"lower":302984,"count":45,"preSum":2371},{"ndv":28,"upper":303515,"lower":303190,"count":43,"preSum":2416},{"ndv":24,"upper":303855,"lower":303526,"count":43,"preSum":2459},{"ndv":27,"upper":304132,"lower":303861,"count":45,"preSum":2502},{"ndv":17,"upper":304159,"lower":304134,"count":50,"preSum":2547},{"ndv":20,"upper":304328,"lower":304161,"count":45,"preSum":2597},{"ndv":15,"upper":304467,"lower":304329,"count":44,"preSum":2642},{"ndv":29,"upper":304699,"lower":304468,"count":45,"preSum":2686},{"ndv":2,"upper":304710,"lower":304704,"count":4,"preSum":2731}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[96965,32,17,28,17,17,22,17,19,19,17,22,19,55],"valueArr":[0,2560,2607,2821,3195,100828,104721,104809,300568,300657,300695,301009,301123,304333],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','multipacking',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','oqcbench',546,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":14,"upper":"02","lower":"","count":634,"preSum":0},{"ndv":7,"upper":"04","lower":"020","count":738,"preSum":634},{"ndv":4,"upper":"07","lower":"05","count":858,"preSum":1372},{"ndv":1,"upper":"09","lower":"09","count":694,"preSum":2230},{"ndv":7,"upper":"12","lower":"10 ","count":1136,"preSum":2924},{"ndv":5,"upper":"15","lower":"123","count":678,"preSum":4060},{"ndv":3,"upper":"18","lower":"16","count":638,"preSum":4738},{"ndv":4,"upper":"21","lower":"19","count":640,"preSum":5376},{"ndv":11,"upper":"2C#10","lower":"22","count":633,"preSum":6016},{"ndv":4,"upper":"4","lower":"2C08","count":751,"preSum":6649},{"ndv":4,"upper":"5","lower":"4.","count":787,"preSum":7400},{"ndv":7,"upper":"9","lower":"57","count":1231,"preSum":8187},{"ndv":11,"upper":"B07","lower":"954","count":630,"preSum":9418},{"ndv":13,"upper":"C01","lower":"B08","count":854,"preSum":10048},{"ndv":3,"upper":"C03","lower":"C02","count":1029,"preSum":10902},{"ndv":2,"upper":"C05","lower":"C04","count":634,"preSum":11931},{"ndv":2,"upper":"C07","lower":"c06","count":730,"preSum":12565},{"ndv":3,"upper":"C10","lower":"C08","count":1099,"preSum":13295},{"ndv":1,"upper":"C11","lower":"C11","count":679,"preSum":14394},{"ndv":3,"upper":"C13","lower":"C11.","count":812,"preSum":15073},{"ndv":3,"upper":"C15","lower":"C14","count":731,"preSum":15885},{"ndv":2,"upper":"C17","lower":"C16","count":1240,"preSum":16616},{"ndv":2,"upper":"C19","lower":"C18","count":647,"preSum":17856},{"ndv":5,"upper":"C7","lower":"C20","count":630,"preSum":18503},{"ndv":21,"upper":"FHT1-2","lower":"CC0","count":772,"preSum":19133},{"ndv":4,"upper":"FHT1-4","lower":"FHT1-2FHT1-2","count":1006,"preSum":19905},{"ndv":2,"upper":"FHT1-6","lower":"FHT1-5","count":748,"preSum":20911},{"ndv":2,"upper":"FHT10-2","lower":"FHT10-1","count":1067,"preSum":21659},{"ndv":9,"upper":"FHT2-1","lower":"FHT10-3","count":726,"preSum":22726},{"ndv":2,"upper":"FHT2-2","lower":"FHT2-1FHT2-1","count":770,"preSum":23452},{"ndv":2,"upper":"FHT2-4","lower":"FHT2-3","count":1125,"preSum":24222},{"ndv":4,"upper":"FHT2-6","lower":"FHT2-4FHT2-4","count":639,"preSum":25347},{"ndv":11,"upper":"FHT5-1","lower":"FHT3-1","count":784,"preSum":25986},{"ndv":2,"upper":"FHT5-2","lower":"FHT5-1FHT5-1FHT5-1","count":743,"preSum":26770},{"ndv":4,"upper":"FHT5-6","lower":"FHT5-3","count":1071,"preSum":27513},{"ndv":2,"upper":"FHT6-1","lower":"Fht51","count":784,"preSum":28584},{"ndv":3,"upper":"FHT6-3","lower":"FHT6-2","count":854,"preSum":29368},{"ndv":4,"upper":"FHT7-2","lower":"FHT6-4","count":1178,"preSum":30222},{"ndv":1,"upper":"FHT7-3","lower":"FHT7-3","count":792,"preSum":31400},{"ndv":1,"upper":"FHT7-4","lower":"FHT7-4","count":718,"preSum":32192},{"ndv":5,"upper":"FHT8-2","lower":"FHT7-5","count":1330,"preSum":32910},{"ndv":2,"upper":"FHT8-4","lower":"FHT8-3FHT8-3","count":624,"preSum":34240},{"ndv":3,"upper":"FHT8-6","lower":"FHT8-5","count":862,"preSum":34864},{"ndv":3,"upper":"FHT9-3","lower":"FHT9-1","count":1014,"preSum":35726},{"ndv":11,"upper":"JALA02","lower":"FHT9-4","count":641,"preSum":36740},{"ndv":8,"upper":"JALA10","lower":"JALA03","count":689,"preSum":37381},{"ndv":10,"upper":"JALA19","lower":"JALA11","count":655,"preSum":38070},{"ndv":12,"upper":"PJX2305799811681807","lower":"JALA19JALA19","count":653,"preSum":38725},{"ndv":64,"upper":"后天0230401.。","lower":"PSD2304785072882309","count":525,"preSum":39378}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[1050,942,2694,1083,1759,2122,991,996,892,1030,978,837,848,43784],"valueArr":["01","08","1","10","2","3","6","8","FHT1-1","FHT10-5","FHT10-6","FHT7-1","FHT8-3","RF_ACTIVITY"],"type":"String","sampleRate":0.8206422281854961}',92,0.037085027),('jala_wms_prod','shipping_container_header','oqcby',589,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":12,"upper":"000053","lower":"000002","count":1014,"preSum":0},{"ndv":5,"upper":"000058","lower":"000054","count":984,"preSum":1014},{"ndv":8,"upper":"000068","lower":"000059","count":1405,"preSum":1998},{"ndv":3,"upper":"000071","lower":"000069","count":1015,"preSum":3403},{"ndv":3,"upper":"000074","lower":"000072","count":945,"preSum":4418},{"ndv":15,"upper":"000095","lower":"000075","count":1665,"preSum":5363},{"ndv":8,"upper":"0220013","lower":"000096","count":966,"preSum":7028},{"ndv":2,"upper":"0220015","lower":"0220014","count":1282,"preSum":7994},{"ndv":4,"upper":"0220019","lower":"0220016","count":1197,"preSum":9276},{"ndv":13,"upper":"0220033","lower":"0220020","count":1386,"preSum":10473},{"ndv":8,"upper":"0220044","lower":"0220034","count":1093,"preSum":11859},{"ndv":8,"upper":"0220061","lower":"0220049","count":1005,"preSum":12952},{"ndv":15,"upper":"02700002","lower":"0220064","count":1174,"preSum":13957},{"ndv":14,"upper":"02700028","lower":"02700003","count":954,"preSum":15131},{"ndv":15,"upper":"02700054","lower":"02700029","count":1317,"preSum":16085},{"ndv":5,"upper":"02700061","lower":"02700057","count":1148,"preSum":17402},{"ndv":3,"upper":"02700067","lower":"02700062","count":1001,"preSum":18550},{"ndv":5,"upper":"02700074","lower":"02700070","count":1084,"preSum":19551},{"ndv":14,"upper":"02700095","lower":"02700075","count":1249,"preSum":20635},{"ndv":6,"upper":"02700104","lower":"02700097","count":1036,"preSum":21884},{"ndv":5,"upper":"02700109","lower":"02700105","count":1010,"preSum":22920},{"ndv":9,"upper":"02700118","lower":"02700110","count":1013,"preSum":23930},{"ndv":23,"upper":"10000000","lower":"02700119","count":948,"preSum":24943},{"ndv":9,"upper":"10000013","lower":"10000001","count":1104,"preSum":25891},{"ndv":3,"upper":"10000016","lower":"10000014","count":1381,"preSum":26995},{"ndv":13,"upper":"1000010","lower":"10000018","count":1059,"preSum":28376},{"ndv":18,"upper":"10000125","lower":"10000102","count":987,"preSum":29435},{"ndv":22,"upper":"10103","lower":"10000126","count":1215,"preSum":30422},{"ndv":5,"upper":"10109","lower":"10104","count":953,"preSum":31637},{"ndv":9,"upper":"10122","lower":"10110","count":1060,"preSum":32590},{"ndv":5,"upper":"10127","lower":"10123","count":1321,"preSum":33650},{"ndv":4,"upper":"10131","lower":"10128","count":1263,"preSum":34971},{"ndv":3,"upper":"10134","lower":"10132","count":1063,"preSum":36234},{"ndv":5,"upper":"10139","lower":"10135","count":991,"preSum":37297},{"ndv":5,"upper":"10144","lower":"10140","count":1080,"preSum":38288},{"ndv":5,"upper":"10149","lower":"10145","count":966,"preSum":39368},{"ndv":34,"upper":"10196","lower":"10150","count":951,"preSum":40334},{"ndv":7,"upper":"10203","lower":"10197","count":1379,"preSum":41285},{"ndv":3,"upper":"10207","lower":"10204","count":971,"preSum":42664},{"ndv":6,"upper":"10214","lower":"10209","count":1110,"preSum":43635},{"ndv":5,"upper":"10219","lower":"10215","count":998,"preSum":44745},{"ndv":9,"upper":"41551742","lower":"10220","count":1090,"preSum":45743},{"ndv":3,"upper":"41762241","lower":"41635019","count":1120,"preSum":46833},{"ndv":3,"upper":"41804927","lower":"41762287","count":962,"preSum":47953},{"ndv":4,"upper":"41825114","lower":"41807962","count":962,"preSum":48915},{"ndv":3,"upper":"41851520","lower":"41827355","count":946,"preSum":49877},{"ndv":12,"upper":"42080021","lower":"41885059","count":1236,"preSum":50823},{"ndv":7,"upper":"42116830","lower":"42082311","count":1178,"preSum":52059},{"ndv":3,"upper":"42126799","lower":"42122431","count":1202,"preSum":53237},{"ndv":4,"upper":"42151366","lower":"42128675","count":1111,"preSum":54439},{"ndv":33,"upper":"57302026","lower":"42152732","count":947,"preSum":55550},{"ndv":9,"upper":"BXH","lower":"57302027","count":1073,"preSum":56497},{"ndv":23,"upper":"suchenbo","lower":"chendaolong","count":943,"preSum":57570},{"ndv":14,"upper":"ZHC01","lower":"sw","count":1138,"preSum":58513},{"ndv":4,"upper":"ZY","lower":"zjf","count":654,"preSum":59651}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[2420,1188,916,1000,1278,1354,2805,1186,2095,3537,3427,5927,914,11557],"valueArr":["000085","0220046","0220047","0220048","02700055","02700063","02700069","02700090","10000006","40721814","41149494","41392574","41412544","41813574"],"type":"String","sampleRate":0.8206422281854961}',92,0.037085027),('jala_wms_prod','shipping_container_header','oqcendat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','oqcstartat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','packagecollection',784011,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1133,"upper":"2023-03-05 07:38:26","lower":"2023-01-31 18:40:46","count":1380,"preSum":0},{"ndv":1279,"upper":"2023-03-15 10:36:43","lower":"2023-03-05 07:38:33","count":1380,"preSum":1380},{"ndv":1170,"upper":"2023-04-01 10:11:32","lower":"2023-03-15 10:38:30","count":1380,"preSum":2760},{"ndv":1232,"upper":"2023-04-14 15:51:48","lower":"2023-04-01 10:12:06","count":1380,"preSum":4140},{"ndv":1282,"upper":"2023-04-18 19:57:44","lower":"2023-04-14 15:51:50","count":1380,"preSum":5520},{"ndv":1174,"upper":"2023-04-21 19:37:58","lower":"2023-04-18 19:59:33","count":1380,"preSum":6900},{"ndv":1277,"upper":"2023-04-23 20:05:39","lower":"2023-04-21 19:37:59","count":1380,"preSum":8280},{"ndv":1262,"upper":"2023-04-25 19:07:56","lower":"2023-04-23 20:06:30","count":1380,"preSum":9660},{"ndv":1242,"upper":"2023-04-27 19:31:01","lower":"2023-04-25 19:07:57","count":1383,"preSum":11040},{"ndv":1229,"upper":"2023-04-28 20:03:22","lower":"2023-04-27 19:31:25","count":1380,"preSum":12423},{"ndv":1185,"upper":"2023-04-29 21:56:16","lower":"2023-04-28 20:03:24","count":1380,"preSum":13803},{"ndv":1169,"upper":"2023-05-01 14:52:44","lower":"2023-04-29 21:56:31","count":1381,"preSum":15183},{"ndv":1303,"upper":"2023-05-03 09:05:32","lower":"2023-05-01 14:52:45","count":1380,"preSum":16564},{"ndv":1186,"upper":"2023-05-03 16:17:34","lower":"2023-05-03 09:06:29","count":1380,"preSum":17944},{"ndv":1237,"upper":"2023-05-03 21:24:59","lower":"2023-05-03 16:17:35","count":1380,"preSum":19324},{"ndv":1219,"upper":"2023-05-04 18:58:32","lower":"2023-05-03 21:25:03","count":1380,"preSum":20704},{"ndv":1311,"upper":"2023-05-05 23:17:03","lower":"2023-05-04 18:58:36","count":1380,"preSum":22084},{"ndv":1281,"upper":"2023-05-07 14:49:47","lower":"2023-05-05 23:23:02","count":1380,"preSum":23464},{"ndv":1265,"upper":"2023-05-09 13:47:57","lower":"2023-05-07 14:49:48","count":1380,"preSum":24844},{"ndv":1258,"upper":"2023-05-10 18:32:18","lower":"2023-05-09 13:48:01","count":1381,"preSum":26224},{"ndv":1247,"upper":"2023-05-12 09:56:33","lower":"2023-05-10 18:32:19","count":1381,"preSum":27605},{"ndv":1274,"upper":"2023-05-13 16:31:46","lower":"2023-05-12 09:56:34","count":1380,"preSum":28986},{"ndv":1291,"upper":"2023-05-15 12:48:54","lower":"2023-05-13 16:31:53","count":1380,"preSum":30366},{"ndv":1223,"upper":"2023-05-16 15:06:57","lower":"2023-05-15 12:48:55","count":1380,"preSum":31746},{"ndv":1206,"upper":"2023-05-17 17:03:19","lower":"2023-05-16 15:07:13","count":1380,"preSum":33126},{"ndv":1181,"upper":"2023-05-18 14:01:52","lower":"2023-05-17 17:04:13","count":1381,"preSum":34506},{"ndv":1180,"upper":"2023-05-19 17:16:57","lower":"2023-05-18 14:01:54","count":1380,"preSum":35887},{"ndv":1285,"upper":"2023-05-21 12:52:15","lower":"2023-05-19 17:17:28","count":1380,"preSum":37267},{"ndv":1267,"upper":"2023-05-22 15:16:39","lower":"2023-05-21 12:54:04","count":1380,"preSum":38647},{"ndv":1237,"upper":"2023-05-23 19:28:50","lower":"2023-05-22 15:16:50","count":1381,"preSum":40027},{"ndv":1266,"upper":"2023-05-25 17:17:20","lower":"2023-05-23 19:29:12","count":1380,"preSum":41408},{"ndv":1264,"upper":"2023-05-27 18:10:46","lower":"2023-05-25 17:18:27","count":1380,"preSum":42788},{"ndv":1261,"upper":"2023-05-30 14:34:34","lower":"2023-05-27 18:11:12","count":1381,"preSum":44168},{"ndv":1213,"upper":"2023-05-31 23:20:28","lower":"2023-05-30 14:34:35","count":1380,"preSum":45549},{"ndv":1282,"upper":"2023-06-01 06:37:17","lower":"2023-05-31 23:20:39","count":1380,"preSum":46929},{"ndv":1233,"upper":"2023-06-01 11:10:01","lower":"2023-06-01 06:37:32","count":1380,"preSum":48309},{"ndv":1257,"upper":"2023-06-01 15:23:22","lower":"2023-06-01 11:10:03","count":1380,"preSum":49689},{"ndv":1202,"upper":"2023-06-01 18:04:35","lower":"2023-06-01 15:23:23","count":1380,"preSum":51069},{"ndv":1163,"upper":"2023-06-01 21:15:21","lower":"2023-06-01 18:04:49","count":1380,"preSum":52449},{"ndv":1132,"upper":"2023-06-02 01:10:36","lower":"2023-06-01 21:15:25","count":1380,"preSum":53829},{"ndv":1263,"upper":"2023-06-02 08:03:44","lower":"2023-06-02 01:12:16","count":1380,"preSum":55209},{"ndv":1272,"upper":"2023-06-02 14:48:42","lower":"2023-06-02 08:03:48","count":1380,"preSum":56589},{"ndv":1232,"upper":"2023-06-02 19:54:57","lower":"2023-06-02 14:49:58","count":1380,"preSum":57969},{"ndv":1266,"upper":"2023-06-03 14:49:32","lower":"2023-06-02 19:54:59","count":1380,"preSum":59349},{"ndv":1312,"upper":"2023-06-04 14:01:43","lower":"2023-06-03 14:49:33","count":1380,"preSum":60729},{"ndv":1311,"upper":"2023-06-05 14:49:57","lower":"2023-06-04 14:03:07","count":1380,"preSum":62109},{"ndv":1301,"upper":"2023-06-06 18:35:17","lower":"2023-06-05 14:49:59","count":1380,"preSum":63489},{"ndv":1270,"upper":"2023-06-08 11:09:40","lower":"2023-06-06 18:35:25","count":1380,"preSum":64869},{"ndv":1314,"upper":"2023-06-09 17:15:14","lower":"2023-06-08 11:09:43","count":1380,"preSum":66249},{"ndv":1302,"upper":"2023-06-11 15:09:01","lower":"2023-06-09 17:16:05","count":1380,"preSum":67629},{"ndv":1325,"upper":"2023-06-12 19:42:13","lower":"2023-06-11 15:10:11","count":1380,"preSum":69009},{"ndv":1283,"upper":"2023-06-14 14:59:09","lower":"2023-06-12 19:42:25","count":1380,"preSum":70389},{"ndv":1270,"upper":"2023-06-16 11:35:15","lower":"2023-06-14 14:59:25","count":1380,"preSum":71769},{"ndv":1238,"upper":"2023-06-16 19:08:33","lower":"2023-06-16 11:35:17","count":1380,"preSum":73149},{"ndv":1245,"upper":"2023-06-17 11:21:45","lower":"2023-06-16 19:08:34","count":1380,"preSum":74529},{"ndv":1160,"upper":"2023-06-17 17:52:17","lower":"2023-06-17 11:21:51","count":1380,"preSum":75909},{"ndv":1268,"upper":"2023-06-18 14:37:22","lower":"2023-06-17 17:52:38","count":1380,"preSum":77289},{"ndv":1274,"upper":"2023-06-18 20:19:22","lower":"2023-06-18 14:37:23","count":1380,"preSum":78669},{"ndv":1258,"upper":"2023-06-19 14:14:01","lower":"2023-06-18 20:19:26","count":1380,"preSum":80049},{"ndv":1240,"upper":"2023-06-19 19:44:05","lower":"2023-06-19 14:14:02","count":1380,"preSum":81429},{"ndv":1288,"upper":"2023-06-20 16:40:41","lower":"2023-06-19 19:44:56","count":1380,"preSum":82809},{"ndv":1262,"upper":"2023-06-22 11:33:10","lower":"2023-06-20 16:40:49","count":1380,"preSum":84189},{"ndv":1349,"upper":"2023-06-25 14:12:55","lower":"2023-06-22 11:33:30","count":1380,"preSum":85569},{"ndv":1277,"upper":"2023-06-28 21:29:52","lower":"2023-06-25 14:14:57","count":1348,"preSum":86949}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[20,17,19,18,17,21,21,16,21,15,20,57,41,20],"valueArr":["2023-02-21 19:36:39","2023-02-23 19:12:18","2023-03-20 20:19:39","2023-04-01 13:33:48","2023-04-12 17:33:03","2023-04-13 17:44:59","2023-04-17 14:10:15","2023-04-25 23:04:44","2023-04-30 14:53:52","2023-06-02 15:27:22","2023-06-04 23:37:20","2023-06-17 01:25:21","2023-06-17 09:23:58","2023-06-20 08:45:14"],"type":"String","sampleRate":0.8206422281854961}',11381,0.037085027),('jala_wms_prod','shipping_container_header','packagedelivery',475636,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":775,"upper":"2023-03-01 14:29:40","lower":"2023-02-09 17:20:50","count":939,"preSum":0},{"ndv":907,"upper":"2023-03-08 08:28:02","lower":"2023-03-01 14:42:23","count":932,"preSum":939},{"ndv":860,"upper":"2023-03-16 14:42:14","lower":"2023-03-08 08:28:15","count":931,"preSum":1871},{"ndv":863,"upper":"2023-03-27 08:58:09","lower":"2023-03-16 14:42:23","count":931,"preSum":2802},{"ndv":872,"upper":"2023-04-10 07:56:15","lower":"2023-03-27 09:42:21","count":931,"preSum":3733},{"ndv":883,"upper":"2023-04-16 07:37:14","lower":"2023-04-10 07:58:59","count":931,"preSum":4664},{"ndv":907,"upper":"2023-04-19 08:01:12","lower":"2023-04-16 07:37:48","count":931,"preSum":5595},{"ndv":874,"upper":"2023-04-22 07:37:40","lower":"2023-04-19 08:01:23","count":931,"preSum":6526},{"ndv":881,"upper":"2023-04-23 08:52:54","lower":"2023-04-22 07:38:02","count":931,"preSum":7457},{"ndv":892,"upper":"2023-04-24 17:36:24","lower":"2023-04-23 08:53:01","count":931,"preSum":8388},{"ndv":893,"upper":"2023-04-26 08:53:48","lower":"2023-04-24 17:45:28","count":931,"preSum":9319},{"ndv":885,"upper":"2023-04-27 14:03:14","lower":"2023-04-26 08:53:54","count":931,"preSum":10250},{"ndv":881,"upper":"2023-04-29 07:30:10","lower":"2023-04-27 14:03:16","count":931,"preSum":11181},{"ndv":860,"upper":"2023-04-29 21:45:25","lower":"2023-04-29 07:30:13","count":933,"preSum":12112},{"ndv":846,"upper":"2023-04-30 12:47:17","lower":"2023-04-29 21:45:31","count":931,"preSum":13045},{"ndv":883,"upper":"2023-05-01 09:08:44","lower":"2023-04-30 12:47:38","count":932,"preSum":13976},{"ndv":859,"upper":"2023-05-02 08:07:06","lower":"2023-05-01 09:09:06","count":931,"preSum":14908},{"ndv":842,"upper":"2023-05-03 07:53:23","lower":"2023-05-02 08:07:11","count":931,"preSum":15839},{"ndv":851,"upper":"2023-05-04 07:30:08","lower":"2023-05-03 07:53:29","count":931,"preSum":16770},{"ndv":824,"upper":"2023-05-04 08:39:17","lower":"2023-05-04 07:30:16","count":931,"preSum":17701},{"ndv":896,"upper":"2023-05-05 06:54:53","lower":"2023-05-04 08:39:44","count":931,"preSum":18632},{"ndv":820,"upper":"2023-05-05 08:18:05","lower":"2023-05-05 06:57:58","count":931,"preSum":19563},{"ndv":878,"upper":"2023-05-06 06:46:11","lower":"2023-05-05 08:18:15","count":931,"preSum":20494},{"ndv":864,"upper":"2023-05-06 09:31:13","lower":"2023-05-06 06:47:38","count":931,"preSum":21425},{"ndv":908,"upper":"2023-05-07 08:46:00","lower":"2023-05-06 09:32:13","count":931,"preSum":22356},{"ndv":883,"upper":"2023-05-08 08:51:48","lower":"2023-05-07 08:46:58","count":931,"preSum":23287},{"ndv":910,"upper":"2023-05-09 09:38:52","lower":"2023-05-08 08:51:51","count":931,"preSum":24218},{"ndv":865,"upper":"2023-05-10 13:23:56","lower":"2023-05-09 09:41:07","count":931,"preSum":25149},{"ndv":889,"upper":"2023-05-11 14:09:09","lower":"2023-05-10 13:24:48","count":931,"preSum":26080},{"ndv":883,"upper":"2023-05-12 13:00:45","lower":"2023-05-11 14:09:21","count":931,"preSum":27011},{"ndv":883,"upper":"2023-05-13 11:08:49","lower":"2023-05-12 13:04:17","count":931,"preSum":27942},{"ndv":894,"upper":"2023-05-14 13:37:43","lower":"2023-05-13 11:09:20","count":931,"preSum":28873},{"ndv":880,"upper":"2023-05-15 14:33:15","lower":"2023-05-14 13:38:40","count":931,"preSum":29804},{"ndv":878,"upper":"2023-05-16 14:44:16","lower":"2023-05-15 14:35:38","count":931,"preSum":30735},{"ndv":894,"upper":"2023-05-17 13:08:09","lower":"2023-05-16 14:45:34","count":931,"preSum":31666},{"ndv":876,"upper":"2023-05-18 09:38:05","lower":"2023-05-17 13:10:48","count":931,"preSum":32597},{"ndv":870,"upper":"2023-05-19 07:51:57","lower":"2023-05-18 09:39:24","count":931,"preSum":33528},{"ndv":855,"upper":"2023-05-19 13:41:42","lower":"2023-05-19 07:51:58","count":931,"preSum":34459},{"ndv":867,"upper":"2023-05-20 09:01:04","lower":"2023-05-19 13:43:54","count":931,"preSum":35390},{"ndv":873,"upper":"2023-05-21 08:26:25","lower":"2023-05-20 09:01:08","count":931,"preSum":36321},{"ndv":881,"upper":"2023-05-22 08:33:01","lower":"2023-05-21 08:26:59","count":931,"preSum":37252},{"ndv":892,"upper":"2023-05-23 08:08:48","lower":"2023-05-22 08:33:04","count":931,"preSum":38183},{"ndv":886,"upper":"2023-05-24 07:43:24","lower":"2023-05-23 08:08:50","count":931,"preSum":39114},{"ndv":892,"upper":"2023-05-25 07:12:41","lower":"2023-05-24 07:43:50","count":931,"preSum":40045},{"ndv":877,"upper":"2023-05-26 07:59:12","lower":"2023-05-25 07:13:14","count":931,"preSum":40976},{"ndv":881,"upper":"2023-05-27 11:01:14","lower":"2023-05-26 07:59:13","count":931,"preSum":41907},{"ndv":862,"upper":"2023-05-29 07:20:57","lower":"2023-05-27 11:02:43","count":931,"preSum":42838},{"ndv":854,"upper":"2023-05-30 15:32:09","lower":"2023-05-29 07:21:50","count":931,"preSum":43769},{"ndv":852,"upper":"2023-06-02 10:35:12","lower":"2023-05-30 15:32:13","count":931,"preSum":44700},{"ndv":842,"upper":"2023-06-04 09:16:18","lower":"2023-06-02 10:41:15","count":931,"preSum":45631},{"ndv":887,"upper":"2023-06-06 10:17:44","lower":"2023-06-04 09:16:35","count":931,"preSum":46562},{"ndv":902,"upper":"2023-06-09 07:20:08","lower":"2023-06-06 10:18:16","count":931,"preSum":47493},{"ndv":894,"upper":"2023-06-13 05:10:18","lower":"2023-06-09 07:21:53","count":931,"preSum":48424},{"ndv":875,"upper":"2023-06-16 11:02:31","lower":"2023-06-13 05:19:36","count":932,"preSum":49355},{"ndv":853,"upper":"2023-06-19 06:17:14","lower":"2023-06-16 11:02:33","count":931,"preSum":50287},{"ndv":852,"upper":"2023-06-20 08:40:41","lower":"2023-06-19 06:17:21","count":931,"preSum":51218},{"ndv":882,"upper":"2023-06-20 15:35:43","lower":"2023-06-20 08:41:04","count":931,"preSum":52149},{"ndv":861,"upper":"2023-06-21 07:57:51","lower":"2023-06-20 15:35:45","count":932,"preSum":53080},{"ndv":862,"upper":"2023-06-21 12:56:04","lower":"2023-06-21 07:57:53","count":931,"preSum":54012},{"ndv":888,"upper":"2023-06-22 08:10:22","lower":"2023-06-21 12:56:11","count":931,"preSum":54943},{"ndv":890,"upper":"2023-06-23 07:49:25","lower":"2023-06-22 08:10:27","count":931,"preSum":55874},{"ndv":886,"upper":"2023-06-24 15:35:40","lower":"2023-06-23 07:49:38","count":931,"preSum":56805},{"ndv":906,"upper":"2023-06-26 14:19:24","lower":"2023-06-24 15:39:17","count":931,"preSum":57736},{"ndv":868,"upper":"2023-06-28 21:03:57","lower":"2023-06-26 14:23:24","count":900,"preSum":58667}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[17,17,21,14,21,23,18,15,14],"valueArr":["2023-04-03 08:02:40","2023-04-14 13:25:47","2023-04-15 16:33:33","2023-04-21 17:05:40","2023-05-03 10:53:23","2023-05-04 07:44:49","2023-05-26 13:03:26","2023-06-01 15:41:26","2023-06-15 16:04:09"],"type":"String","sampleRate":0.8206422281854961}',40274,0.037085027),('jala_wms_prod','shipping_container_header','packagereceipt',884902,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1178,"upper":"2023-03-06 08:55:42","lower":"2023-02-08 09:12:11","count":1338,"preSum":0},{"ndv":1285,"upper":"2023-03-15 13:28:20","lower":"2023-03-06 08:56:05","count":1338,"preSum":1338},{"ndv":1222,"upper":"2023-03-31 10:35:18","lower":"2023-03-15 13:31:46","count":1338,"preSum":2676},{"ndv":1277,"upper":"2023-04-15 10:11:51","lower":"2023-03-31 10:40:34","count":1338,"preSum":4014},{"ndv":1299,"upper":"2023-04-19 19:08:35","lower":"2023-04-15 10:11:58","count":1338,"preSum":5352},{"ndv":1268,"upper":"2023-04-23 09:43:14","lower":"2023-04-19 19:13:31","count":1338,"preSum":6690},{"ndv":1266,"upper":"2023-04-25 11:38:04","lower":"2023-04-23 09:43:48","count":1338,"preSum":8028},{"ndv":1279,"upper":"2023-04-27 13:55:33","lower":"2023-04-25 11:38:26","count":1339,"preSum":9366},{"ndv":1276,"upper":"2023-04-29 13:31:55","lower":"2023-04-27 13:56:12","count":1338,"preSum":10705},{"ndv":1226,"upper":"2023-04-30 17:07:02","lower":"2023-04-29 13:33:24","count":1338,"preSum":12043},{"ndv":1237,"upper":"2023-05-02 09:08:00","lower":"2023-04-30 17:07:06","count":1338,"preSum":13381},{"ndv":1234,"upper":"2023-05-03 15:41:10","lower":"2023-05-02 09:08:18","count":1338,"preSum":14719},{"ndv":1255,"upper":"2023-05-04 11:18:45","lower":"2023-05-03 15:41:47","count":1338,"preSum":16057},{"ndv":1277,"upper":"2023-05-05 09:23:23","lower":"2023-05-04 11:19:04","count":1338,"preSum":17395},{"ndv":1288,"upper":"2023-05-05 21:02:39","lower":"2023-05-05 09:23:46","count":1338,"preSum":18733},{"ndv":1301,"upper":"2023-05-06 22:04:58","lower":"2023-05-05 21:05:12","count":1338,"preSum":20071},{"ndv":1297,"upper":"2023-05-08 12:32:25","lower":"2023-05-06 22:05:28","count":1338,"preSum":21409},{"ndv":1280,"upper":"2023-05-10 09:27:24","lower":"2023-05-08 12:33:18","count":1339,"preSum":22747},{"ndv":1281,"upper":"2023-05-11 18:08:23","lower":"2023-05-10 09:28:12","count":1338,"preSum":24086},{"ndv":1277,"upper":"2023-05-13 10:34:51","lower":"2023-05-11 18:09:13","count":1338,"preSum":25424},{"ndv":1300,"upper":"2023-05-14 19:15:33","lower":"2023-05-13 10:35:59","count":1338,"preSum":26762},{"ndv":1293,"upper":"2023-05-16 10:57:43","lower":"2023-05-14 19:15:37","count":1338,"preSum":28100},{"ndv":1288,"upper":"2023-05-17 16:58:06","lower":"2023-05-16 10:58:36","count":1338,"preSum":29438},{"ndv":1269,"upper":"2023-05-18 18:14:24","lower":"2023-05-17 16:58:51","count":1338,"preSum":30776},{"ndv":1261,"upper":"2023-05-19 16:23:52","lower":"2023-05-18 18:17:10","count":1338,"preSum":32114},{"ndv":1256,"upper":"2023-05-20 17:15:06","lower":"2023-05-19 16:23:55","count":1338,"preSum":33452},{"ndv":1284,"upper":"2023-05-22 09:51:39","lower":"2023-05-20 17:15:25","count":1338,"preSum":34790},{"ndv":1300,"upper":"2023-05-23 13:13:58","lower":"2023-05-22 09:52:00","count":1338,"preSum":36128},{"ndv":1276,"upper":"2023-05-24 16:50:32","lower":"2023-05-23 13:14:09","count":1339,"preSum":37466},{"ndv":1292,"upper":"2023-05-26 11:44:19","lower":"2023-05-24 16:50:42","count":1338,"preSum":38805},{"ndv":1229,"upper":"2023-05-28 10:42:06","lower":"2023-05-26 11:45:28","count":1338,"preSum":40143},{"ndv":1224,"upper":"2023-05-31 12:34:48","lower":"2023-05-28 10:42:18","count":1338,"preSum":41481},{"ndv":1254,"upper":"2023-06-02 08:40:27","lower":"2023-05-31 12:36:21","count":1338,"preSum":42819},{"ndv":1205,"upper":"2023-06-02 10:24:03","lower":"2023-06-02 08:40:32","count":1338,"preSum":44157},{"ndv":1249,"upper":"2023-06-02 15:02:19","lower":"2023-06-02 10:24:05","count":1338,"preSum":45495},{"ndv":1262,"upper":"2023-06-02 18:55:39","lower":"2023-06-02 15:02:33","count":1338,"preSum":46833},{"ndv":1231,"upper":"2023-06-03 09:09:01","lower":"2023-06-02 18:55:59","count":1338,"preSum":48171},{"ndv":1156,"upper":"2023-06-03 10:25:17","lower":"2023-06-03 09:09:03","count":1338,"preSum":49509},{"ndv":1237,"upper":"2023-06-03 13:26:10","lower":"2023-06-03 10:25:21","count":1338,"preSum":50847},{"ndv":1243,"upper":"2023-06-03 17:58:07","lower":"2023-06-03 13:26:39","count":1338,"preSum":52185},{"ndv":1289,"upper":"2023-06-04 09:27:17","lower":"2023-06-03 17:58:32","count":1338,"preSum":53523},{"ndv":1250,"upper":"2023-06-04 13:57:01","lower":"2023-06-04 09:27:26","count":1338,"preSum":54861},{"ndv":1299,"upper":"2023-06-05 08:56:05","lower":"2023-06-04 13:57:12","count":1338,"preSum":56199},{"ndv":1279,"upper":"2023-06-05 16:54:44","lower":"2023-06-05 08:56:27","count":1338,"preSum":57537},{"ndv":1306,"upper":"2023-06-06 16:23:41","lower":"2023-06-05 16:55:24","count":1338,"preSum":58875},{"ndv":1291,"upper":"2023-06-07 18:37:55","lower":"2023-06-06 16:24:02","count":1338,"preSum":60213},{"ndv":1296,"upper":"2023-06-09 09:15:05","lower":"2023-06-07 18:38:33","count":1339,"preSum":61551},{"ndv":1278,"upper":"2023-06-10 13:22:17","lower":"2023-06-09 09:15:10","count":1338,"preSum":62890},{"ndv":1306,"upper":"2023-06-12 08:17:20","lower":"2023-06-10 13:25:33","count":1338,"preSum":64228},{"ndv":1298,"upper":"2023-06-13 13:39:58","lower":"2023-06-12 08:17:52","count":1338,"preSum":65566},{"ndv":1302,"upper":"2023-06-14 21:48:32","lower":"2023-06-13 13:42:38","count":1338,"preSum":66904},{"ndv":1270,"upper":"2023-06-16 15:47:52","lower":"2023-06-14 21:51:25","count":1338,"preSum":68242},{"ndv":1266,"upper":"2023-06-17 15:47:30","lower":"2023-06-16 15:48:20","count":1338,"preSum":69580},{"ndv":1258,"upper":"2023-06-18 10:09:19","lower":"2023-06-17 15:47:43","count":1338,"preSum":70918},{"ndv":1260,"upper":"2023-06-18 18:14:01","lower":"2023-06-18 10:09:24","count":1338,"preSum":72256},{"ndv":1251,"upper":"2023-06-19 11:24:02","lower":"2023-06-18 18:14:32","count":1338,"preSum":73594},{"ndv":1260,"upper":"2023-06-19 19:37:43","lower":"2023-06-19 11:24:06","count":1338,"preSum":74932},{"ndv":1258,"upper":"2023-06-20 11:13:17","lower":"2023-06-19 19:40:03","count":1338,"preSum":76270},{"ndv":1281,"upper":"2023-06-20 19:39:48","lower":"2023-06-20 11:14:03","count":1338,"preSum":77608},{"ndv":1290,"upper":"2023-06-21 13:00:40","lower":"2023-06-20 19:40:27","count":1338,"preSum":78946},{"ndv":1297,"upper":"2023-06-22 10:40:43","lower":"2023-06-21 13:02:49","count":1338,"preSum":80284},{"ndv":1287,"upper":"2023-06-23 14:28:27","lower":"2023-06-22 10:41:19","count":1338,"preSum":81622},{"ndv":1309,"upper":"2023-06-25 18:20:08","lower":"2023-06-23 14:28:42","count":1338,"preSum":82960},{"ndv":1308,"upper":"2023-06-28 21:58:00","lower":"2023-06-25 18:20:35","count":1333,"preSum":84298}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[13,18,17,21,23,21,12,12,13,12,14],"valueArr":["2023-03-01 14:46:59","2023-04-03 10:32:04","2023-04-14 13:51:04","2023-04-15 16:37:06","2023-05-04 10:52:38","2023-05-08 11:59:15","2023-05-15 09:10:01","2023-05-30 16:23:21","2023-05-31 11:54:14","2023-06-01 16:00:21","2023-06-04 19:45:05"],"type":"String","sampleRate":0.8206422281854961}',14194,0.037085027),('jala_wms_prod','shipping_container_header','packagetransfer',66305,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":102,"upper":"2023-05-25 02:56:24","lower":"2023-04-20 01:44:04","count":156,"preSum":0},{"ndv":105,"upper":"2023-05-27 21:11:42","lower":"2023-05-25 03:02:42","count":156,"preSum":156},{"ndv":82,"upper":"2023-05-30 17:47:22","lower":"2023-05-27 21:58:13","count":156,"preSum":312},{"ndv":82,"upper":"2023-06-01 02:09:58","lower":"2023-05-30 21:35:56","count":156,"preSum":468},{"ndv":105,"upper":"2023-06-02 19:19:25","lower":"2023-06-01 02:11:08","count":156,"preSum":624},{"ndv":104,"upper":"2023-06-07 22:51:17","lower":"2023-06-02 19:23:43","count":156,"preSum":780},{"ndv":133,"upper":"2023-06-09 01:00:12","lower":"2023-06-07 23:07:08","count":156,"preSum":936},{"ndv":148,"upper":"2023-06-09 07:27:02","lower":"2023-06-09 01:01:14","count":156,"preSum":1092},{"ndv":155,"upper":"2023-06-09 19:14:41","lower":"2023-06-09 07:30:04","count":156,"preSum":1248},{"ndv":153,"upper":"2023-06-09 23:03:57","lower":"2023-06-09 19:20:11","count":156,"preSum":1404},{"ndv":148,"upper":"2023-06-10 21:06:23","lower":"2023-06-09 23:06:09","count":156,"preSum":1560},{"ndv":150,"upper":"2023-06-11 16:24:49","lower":"2023-06-10 21:06:50","count":156,"preSum":1716},{"ndv":149,"upper":"2023-06-12 15:20:28","lower":"2023-06-11 16:29:01","count":156,"preSum":1872},{"ndv":147,"upper":"2023-06-12 20:45:01","lower":"2023-06-12 15:24:22","count":156,"preSum":2028},{"ndv":142,"upper":"2023-06-13 16:21:28","lower":"2023-06-12 20:45:04","count":156,"preSum":2184},{"ndv":146,"upper":"2023-06-13 21:07:14","lower":"2023-06-13 16:21:53","count":156,"preSum":2340},{"ndv":137,"upper":"2023-06-14 16:57:05","lower":"2023-06-13 21:07:22","count":156,"preSum":2496},{"ndv":132,"upper":"2023-06-15 01:49:41","lower":"2023-06-14 16:57:06","count":156,"preSum":2652},{"ndv":132,"upper":"2023-06-15 20:58:37","lower":"2023-06-15 01:59:16","count":158,"preSum":2808},{"ndv":130,"upper":"2023-06-16 12:37:45","lower":"2023-06-15 20:58:56","count":156,"preSum":2966},{"ndv":132,"upper":"2023-06-16 19:15:56","lower":"2023-06-16 12:37:47","count":156,"preSum":3122},{"ndv":118,"upper":"2023-06-16 23:55:43","lower":"2023-06-16 19:15:57","count":156,"preSum":3278},{"ndv":140,"upper":"2023-06-17 10:50:30","lower":"2023-06-16 23:55:55","count":156,"preSum":3434},{"ndv":134,"upper":"2023-06-17 18:39:21","lower":"2023-06-17 10:50:37","count":156,"preSum":3590},{"ndv":155,"upper":"2023-06-17 21:56:17","lower":"2023-06-17 18:42:00","count":156,"preSum":3746},{"ndv":116,"upper":"2023-06-18 09:59:58","lower":"2023-06-17 21:56:49","count":156,"preSum":3902},{"ndv":144,"upper":"2023-06-18 15:19:25","lower":"2023-06-18 09:59:59","count":156,"preSum":4058},{"ndv":153,"upper":"2023-06-18 18:25:18","lower":"2023-06-18 15:19:53","count":156,"preSum":4214},{"ndv":152,"upper":"2023-06-18 21:27:18","lower":"2023-06-18 18:25:21","count":156,"preSum":4370},{"ndv":152,"upper":"2023-06-18 22:09:58","lower":"2023-06-18 21:27:33","count":156,"preSum":4526},{"ndv":148,"upper":"2023-06-19 11:05:54","lower":"2023-06-18 22:09:59","count":156,"preSum":4682},{"ndv":149,"upper":"2023-06-19 15:20:38","lower":"2023-06-19 11:05:55","count":156,"preSum":4838},{"ndv":153,"upper":"2023-06-19 20:20:45","lower":"2023-06-19 15:23:42","count":156,"preSum":4994},{"ndv":148,"upper":"2023-06-20 00:14:52","lower":"2023-06-19 20:20:56","count":156,"preSum":5150},{"ndv":149,"upper":"2023-06-20 17:29:11","lower":"2023-06-20 00:16:28","count":156,"preSum":5306},{"ndv":150,"upper":"2023-06-20 21:04:11","lower":"2023-06-20 17:29:28","count":156,"preSum":5462},{"ndv":136,"upper":"2023-06-21 14:24:56","lower":"2023-06-20 21:04:38","count":156,"preSum":5618},{"ndv":124,"upper":"2023-06-21 14:50:08","lower":"2023-06-21 14:24:58","count":156,"preSum":5774},{"ndv":123,"upper":"2023-06-21 15:44:53","lower":"2023-06-21 14:50:09","count":156,"preSum":5930},{"ndv":105,"upper":"2023-06-21 16:29:37","lower":"2023-06-21 15:44:54","count":157,"preSum":6086},{"ndv":110,"upper":"2023-06-21 17:45:04","lower":"2023-06-21 16:29:40","count":159,"preSum":6243},{"ndv":115,"upper":"2023-06-21 19:30:16","lower":"2023-06-21 17:45:42","count":160,"preSum":6402},{"ndv":109,"upper":"2023-06-21 21:05:54","lower":"2023-06-21 19:35:13","count":156,"preSum":6562},{"ndv":123,"upper":"2023-06-22 00:23:46","lower":"2023-06-21 21:06:06","count":156,"preSum":6718},{"ndv":136,"upper":"2023-06-22 05:22:07","lower":"2023-06-22 00:23:52","count":156,"preSum":6874},{"ndv":145,"upper":"2023-06-22 09:59:07","lower":"2023-06-22 05:23:10","count":156,"preSum":7030},{"ndv":139,"upper":"2023-06-22 14:18:28","lower":"2023-06-22 09:59:09","count":156,"preSum":7186},{"ndv":137,"upper":"2023-06-22 21:04:43","lower":"2023-06-22 14:18:38","count":156,"preSum":7342},{"ndv":153,"upper":"2023-06-23 11:44:04","lower":"2023-06-22 21:33:45","count":156,"preSum":7498},{"ndv":148,"upper":"2023-06-23 16:03:20","lower":"2023-06-23 11:44:29","count":156,"preSum":7654},{"ndv":154,"upper":"2023-06-23 21:01:09","lower":"2023-06-23 16:03:23","count":156,"preSum":7810},{"ndv":155,"upper":"2023-06-24 11:19:01","lower":"2023-06-23 21:01:33","count":157,"preSum":7966},{"ndv":138,"upper":"2023-06-24 17:13:19","lower":"2023-06-24 11:19:04","count":156,"preSum":8123},{"ndv":122,"upper":"2023-06-24 20:19:54","lower":"2023-06-24 17:13:49","count":159,"preSum":8279},{"ndv":99,"upper":"2023-06-25 14:15:55","lower":"2023-06-24 20:19:55","count":156,"preSum":8438},{"ndv":141,"upper":"2023-06-25 18:17:29","lower":"2023-06-25 14:18:16","count":156,"preSum":8594},{"ndv":111,"upper":"2023-06-25 22:34:25","lower":"2023-06-25 18:29:22","count":156,"preSum":8750},{"ndv":142,"upper":"2023-06-26 14:32:19","lower":"2023-06-25 22:34:35","count":156,"preSum":8906},{"ndv":153,"upper":"2023-06-26 17:57:58","lower":"2023-06-26 14:32:27","count":156,"preSum":9062},{"ndv":113,"upper":"2023-06-26 20:54:30","lower":"2023-06-26 17:58:03","count":156,"preSum":9218},{"ndv":146,"upper":"2023-06-27 17:04:04","lower":"2023-06-26 20:54:32","count":156,"preSum":9374},{"ndv":122,"upper":"2023-06-28 13:20:30","lower":"2023-06-27 17:04:45","count":156,"preSum":9530},{"ndv":156,"upper":"2023-06-28 18:28:25","lower":"2023-06-28 13:24:24","count":156,"preSum":9686},{"ndv":68,"upper":"2023-06-28 23:31:52","lower":"2023-06-28 18:30:26","count":85,"preSum":9842}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[14,17,27,21,15,22,16,76,16,21,31,16,18,18],"valueArr":["2023-04-20 01:38:52","2023-06-16 13:38:38","2023-06-16 13:48:40","2023-06-16 13:49:00","2023-06-21 14:16:50","2023-06-21 15:38:13","2023-06-21 20:36:05","2023-06-21 20:36:11","2023-06-22 12:00:04","2023-06-22 18:48:22","2023-06-23 11:59:30","2023-06-23 18:41:45","2023-06-24 18:51:48","2023-06-28 11:50:17"],"type":"String","sampleRate":0.8206422281854961}',89746,0.037085027),('jala_wms_prod','shipping_container_header','packedat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','packedby',537,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":11,"upper":"000057","lower":"000002","count":921,"preSum":0},{"ndv":2,"upper":"000060","lower":"000059","count":688,"preSum":921},{"ndv":7,"upper":"000069","lower":"000061","count":1121,"preSum":1609},{"ndv":4,"upper":"000073","lower":"000070","count":1111,"preSum":2730},{"ndv":16,"upper":"0220011","lower":"000074","count":862,"preSum":3841},{"ndv":3,"upper":"0220014","lower":"0220012","count":781,"preSum":4703},{"ndv":3,"upper":"0220017","lower":"0220015","count":697,"preSum":5484},{"ndv":2,"upper":"0220019","lower":"0220018","count":721,"preSum":6181},{"ndv":14,"upper":"0220048","lower":"0220020","count":780,"preSum":6902},{"ndv":16,"upper":"02700020","lower":"0220049","count":688,"preSum":7682},{"ndv":11,"upper":"02700031","lower":"02700021","count":745,"preSum":8370},{"ndv":12,"upper":"02700054","lower":"02700032","count":1161,"preSum":9115},{"ndv":3,"upper":"02700058","lower":"02700055","count":768,"preSum":10276},{"ndv":5,"upper":"02700063","lower":"02700059","count":1017,"preSum":11044},{"ndv":3,"upper":"02700069","lower":"02700064","count":885,"preSum":12061},{"ndv":4,"upper":"02700073","lower":"02700070","count":732,"preSum":12946},{"ndv":4,"upper":"02700077","lower":"02700074","count":725,"preSum":13678},{"ndv":15,"upper":"02700102","lower":"02700082","count":932,"preSum":14403},{"ndv":5,"upper":"02700107","lower":"02700103","count":1014,"preSum":15335},{"ndv":6,"upper":"02700113","lower":"02700108","count":758,"preSum":16349},{"ndv":5,"upper":"02700118","lower":"02700114","count":727,"preSum":17107},{"ndv":16,"upper":"02700141","lower":"02700119","count":692,"preSum":17834},{"ndv":14,"upper":"10000012","lower":"02700145","count":909,"preSum":18526},{"ndv":3,"upper":"10000016","lower":"10000013","count":991,"preSum":19435},{"ndv":7,"upper":"1000005","lower":"10000018","count":783,"preSum":20426},{"ndv":14,"upper":"10000113","lower":"1000006","count":814,"preSum":21209},{"ndv":17,"upper":"1000014","lower":"10000114","count":726,"preSum":22023},{"ndv":13,"upper":"10103","lower":"10000140","count":863,"preSum":22749},{"ndv":4,"upper":"10108","lower":"10104","count":887,"preSum":23612},{"ndv":9,"upper":"10121","lower":"10109","count":815,"preSum":24499},{"ndv":3,"upper":"10124","lower":"10122","count":838,"preSum":25314},{"ndv":3,"upper":"10127","lower":"10125","count":794,"preSum":26152},{"ndv":3,"upper":"10130","lower":"10128","count":870,"preSum":26946},{"ndv":2,"upper":"10132","lower":"10131","count":726,"preSum":27816},{"ndv":2,"upper":"10134","lower":"10133","count":730,"preSum":28542},{"ndv":5,"upper":"10139","lower":"10135","count":991,"preSum":29272},{"ndv":3,"upper":"10142","lower":"10140","count":744,"preSum":30263},{"ndv":4,"upper":"10146","lower":"10143","count":771,"preSum":31007},{"ndv":4,"upper":"10150","lower":"10147","count":687,"preSum":31778},{"ndv":19,"upper":"10173","lower":"10151","count":684,"preSum":32465},{"ndv":20,"upper":"10202","lower":"10174","count":836,"preSum":33149},{"ndv":2,"upper":"10205","lower":"10204","count":768,"preSum":33985},{"ndv":5,"upper":"10212","lower":"10207","count":821,"preSum":34753},{"ndv":5,"upper":"10217","lower":"10213","count":746,"preSum":35574},{"ndv":2,"upper":"10219","lower":"10218","count":744,"preSum":36320},{"ndv":12,"upper":"41641876","lower":"10220","count":691,"preSum":37064},{"ndv":6,"upper":"41814985","lower":"41762287","count":879,"preSum":37755},{"ndv":11,"upper":"42034700","lower":"41825114","count":748,"preSum":38634},{"ndv":9,"upper":"42116830","lower":"42035274","count":907,"preSum":39382},{"ndv":21,"upper":"57302005","lower":"42125184","count":701,"preSum":40289},{"ndv":25,"upper":"BMJ","lower":"57302006","count":811,"preSum":40990},{"ndv":11,"upper":"LQ101","lower":"BXH","count":693,"preSum":41801},{"ndv":15,"upper":"ZHC01","lower":"LSH","count":939,"preSum":42494},{"ndv":3,"upper":"ZRX","lower":"zjf","count":334,"preSum":43433}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[660,1188,891,532,654,914,577,677,836,713,648,614,895,855],"valueArr":["000058","0220046","0220047","10000015","10203","41412544","41551742","41762241","41796292","41851520","42080021","42082311","42122431","42128675"],"type":"String","sampleRate":0.8206422281854961}',45580,0.037085027),('jala_wms_prod','shipping_container_header','parent',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','pickcompletedat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','picurls',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','pidids',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','printdataid',902614,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1226,"upper":"640ddf9caa61f61634b046c4","lower":"639c1a5f2f046a24bf50ec6b","count":1226,"preSum":0},{"ndv":1226,"upper":"6425b33dda72983721c4a357","lower":"640ddf9daa61f61634b046ca","count":1226,"preSum":1226},{"ndv":1226,"upper":"6438319a24fdce25c8cc66af","lower":"6425b4620f472611fedca97c","count":1226,"preSum":2452},{"ndv":1226,"upper":"643e3b4de2de734f0f6fe183","lower":"643832c37867d072f629cbd6","count":1226,"preSum":3678},{"ndv":1226,"upper":"6442383ffb2a0e77593e16d7","lower":"643e3c78308949792f644742","count":1226,"preSum":4904},{"ndv":1226,"upper":"6445078cb581804328a00e56","lower":"6442383ffb2a0e77593e16d8","count":1226,"preSum":6130},{"ndv":1226,"upper":"64477ba720399d3641062921","lower":"6445078d8688a16be9a102ba","count":1226,"preSum":7356},{"ndv":1226,"upper":"644a812ea3fda2138cf6b1a2","lower":"64477ba820399d364106292d","count":1226,"preSum":8582},{"ndv":1226,"upper":"644b9ddea3fda2138cfd176b","lower":"644a812ecbee2f774a22bf68","count":1226,"preSum":9808},{"ndv":1226,"upper":"644dde7ab7356506a990cd7f","lower":"644ba036b7356506a984bf95","count":1226,"preSum":11034},{"ndv":1226,"upper":"644ff27ca34628313ff38833","lower":"644dde7ab7356506a990cd80","count":1226,"preSum":12260},{"ndv":1226,"upper":"6451bbd6a34628313ffbda2e","lower":"644ff3a93460f001876ee273","count":1226,"preSum":13486},{"ndv":1226,"upper":"6451d207cb08c42cd07e9ea8","lower":"6451bbd93460f001877785d9","count":1226,"preSum":14712},{"ndv":1226,"upper":"6452687a3460f00187814bb6","lower":"6451d2083460f0018779e58f","count":1226,"preSum":15938},{"ndv":1226,"upper":"6453bf20cb08c42cd08cd8fa","lower":"6452688ea34628313f07bedc","count":1226,"preSum":17164},{"ndv":1226,"upper":"6455d7dd73f6dd1883af6747","lower":"6453bf233460f0018788a310","count":1226,"preSum":18390},{"ndv":1226,"upper":"6457a9151da8e849241ce832","lower":"6455d9041da8e84924152f9f","count":1226,"preSum":19616},{"ndv":1226,"upper":"645a023c8338b44f590fe8c0","lower":"6457aa3f32445e3aa1428f52","count":1226,"preSum":20842},{"ndv":1226,"upper":"645bc0cdbb419d6e236a5437","lower":"645a023cbb419d6e235ff7b6","count":1226,"preSum":22068},{"ndv":1226,"upper":"645dbb00bfd01960ddd0fb51","lower":"645bc0cdbb419d6e236a5438","count":1226,"preSum":23294},{"ndv":1226,"upper":"645fc6d8977ac2612de89a75","lower":"645dbb00bfd01960ddd0fb52","count":1226,"preSum":24520},{"ndv":1226,"upper":"64618eb751c41f0befbe36a8","lower":"645fc6d951c41f0befb6d5ae","count":1226,"preSum":25746},{"ndv":1226,"upper":"646388f261a80428445e1ec0","lower":"64618ec6977ac2612df1a6cb","count":1226,"preSum":26972},{"ndv":1226,"upper":"6464528251c41f0befcf834a","lower":"646388f261a80428445e1ec1","count":1226,"preSum":28198},{"ndv":1226,"upper":"6465f4d761a80428446eda4c","lower":"6464528261a8042844636254","count":1226,"preSum":29424},{"ndv":1226,"upper":"64684a9d2af2e71c12903e0d","lower":"6465f4d761a80428446eda58","count":1226,"preSum":30650},{"ndv":1226,"upper":"64699898cbe08c3cf12dad73","lower":"64684a9dcbe08c3cf1256fa8","count":1226,"preSum":31876},{"ndv":1226,"upper":"646b7338cbe08c3cf1367598","lower":"646998992af2e71c1298b831","count":1226,"preSum":33102},{"ndv":1226,"upper":"646e2a04a14209152ea6847d","lower":"646b7339cbe08c3cf13675a7","count":1226,"preSum":34328},{"ndv":1226,"upper":"6470d9f0cf891a6b00d0c475","lower":"646e2a04ae4e8a0e04e07fef","count":1226,"preSum":35554},{"ndv":1226,"upper":"6471872133db057bab9df0d3","lower":"6470db1233db057bab9a19c4","count":1226,"preSum":36780},{"ndv":1226,"upper":"647198a633db057bab9e9971","lower":"6471876633db057bab9df1bb","count":1226,"preSum":38006},{"ndv":1226,"upper":"6471ac04cf891a6b00d54c47","lower":"647198a633db057bab9e9972","count":1226,"preSum":39232},{"ndv":1226,"upper":"6471d5f033db057baba07c1a","lower":"6471ac0a33db057bab9f7417","count":1226,"preSum":40458},{"ndv":1226,"upper":"6473487186c6db1296d7526e","lower":"6471d5f233db057baba07c30","count":1226,"preSum":41684},{"ndv":1226,"upper":"6474658bcf891a6b00dd7ad3","lower":"64734871cf891a6b00da107a","count":1226,"preSum":42910},{"ndv":1226,"upper":"6475da346e1ab418fa0df22e","lower":"6474658c33db057baba92490","count":1226,"preSum":44136},{"ndv":1226,"upper":"64770cc3319c102daf40c235","lower":"6475daca6bcf597b4f1fb43d","count":1226,"preSum":45362},{"ndv":1226,"upper":"64774a0e336e123e3d918a1b","lower":"64770cc3336e123e3d909dd6","count":1226,"preSum":46588},{"ndv":1226,"upper":"6477758cb7fd9828da9b4bf5","lower":"64774a0e94303d3cf5a26d95","count":1226,"preSum":47814},{"ndv":1226,"upper":"6478470f9c699e237b135c8e","lower":"6477758d1a16033c58faebaf","count":1226,"preSum":49040},{"ndv":1226,"upper":"6478ee48e6bcca6422d5d601","lower":"64784710336e123e3da189cd","count":1226,"preSum":50266},{"ndv":1226,"upper":"647a02072e32ff02e0db84ee","lower":"6478ef6f336e123e3da6f5f6","count":1226,"preSum":51492},{"ndv":1226,"upper":"647b406b8249d352cdbf8b5e","lower":"647a02072e32ff02e0db84f2","count":1226,"preSum":52718},{"ndv":1226,"upper":"647c8aeb003af203fdb20212","lower":"647b406c8249d352cdbf8b61","count":1226,"preSum":53944},{"ndv":1226,"upper":"647e643689776c5eee571944","lower":"647c8aeb8249d352cdc0c99b","count":1226,"preSum":55170},{"ndv":1226,"upper":"648044d2f99b45077b2936b9","lower":"647e64368daffd7f59a8e042","count":1226,"preSum":56396},{"ndv":1226,"upper":"6482949278ec172fd6035399","lower":"648044d2fae5a94ae68dc1d2","count":1226,"preSum":57622},{"ndv":1226,"upper":"64846ce178ec172fd604d046","lower":"648294932d006360fe04056c","count":1226,"preSum":58848},{"ndv":1226,"upper":"64861c1e2d006360fe06f0b8","lower":"64846ce178ec172fd604d047","count":1226,"preSum":60074},{"ndv":1226,"upper":"6488372facc9a26ca987c5f1","lower":"64861c1e6f06004a70c30e51","count":1226,"preSum":61300},{"ndv":1226,"upper":"648b07de2625d24e22e42407","lower":"6488372fdbb472367eb2306a","count":1226,"preSum":62526},{"ndv":1226,"upper":"648b9af24e8d7266e6eefe7a","lower":"648b07de4e8d7266e6ee1324","count":1226,"preSum":63752},{"ndv":1226,"upper":"648c61902625d24e22e6137a","lower":"648b9af2dbb472367eb52a16","count":1226,"preSum":64978},{"ndv":1226,"upper":"648d13b8acc9a26ca98cc622","lower":"648c6190dbb472367eb63dbb","count":1226,"preSum":66204},{"ndv":1226,"upper":"648dc66f1d13f33ef26813c5","lower":"648d13b91d13f33ef26762c6","count":1226,"preSum":67430},{"ndv":1226,"upper":"648e7906acc9a26ca98def28","lower":"648dc7091d13f33ef26813da","count":1226,"preSum":68656},{"ndv":1226,"upper":"648ed36bacc9a26ca98e900c","lower":"648e7906acc9a26ca98def2d","count":1226,"preSum":69882},{"ndv":1226,"upper":"648f2b482625d24e22e944f2","lower":"648ed3702625d24e22e8cf2e","count":1226,"preSum":71108},{"ndv":1226,"upper":"648ffdd8dbb472367eb97050","lower":"648f2b482625d24e22e944fc","count":1226,"preSum":72334},{"ndv":1226,"upper":"64916f5bacc9a26ca992ba8a","lower":"648ffde0acc9a26ca990b146","count":1226,"preSum":73560},{"ndv":1226,"upper":"6493d096dbb472367ebacad3","lower":"64916f5bdbb472367eba2145","count":1226,"preSum":74786},{"ndv":1226,"upper":"649718e92625d24e22f2ae7c","lower":"6493d14a1d13f33ef2703892","count":1226,"preSum":76012},{"ndv":1172,"upper":"649beb86dbb472367ebc7be5","lower":"64971a3aacc9a26ca9983728","count":1172,"preSum":77238}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,21591,0.037085027),('jala_wms_prod','shipping_container_header','processstamp',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','qtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','scaledat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('jala_wms_prod','shipping_container_header','scaledby',215,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":8,"upper":"000019","lower":"000001","count":355,"preSum":0},{"ndv":12,"upper":"000071","lower":"000024","count":473,"preSum":355},{"ndv":8,"upper":"000084","lower":"000072","count":301,"preSum":828},{"ndv":2,"upper":"000087","lower":"000086","count":404,"preSum":1129},{"ndv":6,"upper":"000095","lower":"000088","count":965,"preSum":1533},{"ndv":7,"upper":"0220014","lower":"000097","count":601,"preSum":2498},{"ndv":1,"upper":"0220015","lower":"0220015","count":385,"preSum":3099},{"ndv":7,"upper":"0220026","lower":"0220017","count":397,"preSum":3484},{"ndv":5,"upper":"0220033","lower":"0220029","count":855,"preSum":3881},{"ndv":4,"upper":"0220039","lower":"0220034","count":326,"preSum":4736},{"ndv":3,"upper":"0220042","lower":"0220040","count":325,"preSum":5062},{"ndv":2,"upper":"0220044","lower":"0220043","count":429,"preSum":5387},{"ndv":2,"upper":"0220048","lower":"0220047","count":596,"preSum":5816},{"ndv":6,"upper":"0220054","lower":"0220049","count":322,"preSum":6412},{"ndv":10,"upper":"0220081","lower":"0220060","count":340,"preSum":6734},{"ndv":7,"upper":"02700001","lower":"0220084","count":573,"preSum":7074},{"ndv":1,"upper":"02700002","lower":"02700002","count":342,"preSum":7647},{"ndv":5,"upper":"02700017","lower":"02700003","count":407,"preSum":7989},{"ndv":2,"upper":"02700050","lower":"02700022","count":1136,"preSum":8396},{"ndv":1,"upper":"02700051","lower":"02700051","count":1399,"preSum":9532},{"ndv":1,"upper":"02700055","lower":"02700055","count":1041,"preSum":10931},{"ndv":4,"upper":"02700062","lower":"02700056","count":464,"preSum":11972},{"ndv":1,"upper":"02700063","lower":"02700063","count":949,"preSum":12436},{"ndv":3,"upper":"02700071","lower":"02700066","count":927,"preSum":13385},{"ndv":2,"upper":"02700090","lower":"02700078","count":1177,"preSum":14312},{"ndv":1,"upper":"02700095","lower":"02700095","count":423,"preSum":15489},{"ndv":1,"upper":"02700096","lower":"02700096","count":473,"preSum":15912},{"ndv":14,"upper":"1000005","lower":"02700097","count":312,"preSum":16385},{"ndv":4,"upper":"10000103","lower":"1000006","count":412,"preSum":16697},{"ndv":1,"upper":"10000104","lower":"10000104","count":449,"preSum":17109},{"ndv":2,"upper":"10000110","lower":"10000105","count":379,"preSum":17558},{"ndv":10,"upper":"41551742","lower":"10000168","count":383,"preSum":17937},{"ndv":5,"upper":"42126799","lower":"41580109","count":451,"preSum":18320},{"ndv":5,"upper":"ZRX","lower":"42151366","count":181,"preSum":18771}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[2109,2420,1615,1681,1777,2504,1610,2312,2596,3537,3419,5814,11484,26328],"valueArr":["000067","000085","0220007","0220061","02700052","02700069","02700076","10000006","10000101","40721814","41149494","41392574","41813574","api"],"type":"String","sampleRate":0.8206422281854961}',11843,0.037085027),('jala_wms_prod','shipping_container_header','scannedserialnum',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','secondoqcbench',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','secondoqcby',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','secondoqcendat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','secondoqcstartat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','sfregisterroute',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[867,65296,33838],"valueArr":[-1,0,1],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','shipcontmastercode',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[98293,1457,7,151],"valueArr":["","出库箱主表-拆开","出库箱主表-拆开(加中包)","出库箱主表-拆开(非屈臣氏)"],"type":"String","sampleRate":0.8206422281854961}',93,0.037085027),('jala_wms_prod','shipping_container_header','shipmentcode',1813859,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1047,"upper":"CK0001283833","lower":"0001908728","count":1558,"preSum":0},{"ndv":1085,"upper":"CK0001429009","lower":"CK0001283838","count":1558,"preSum":1558},{"ndv":1123,"upper":"CK0001488699","lower":"CK0001429013","count":1558,"preSum":3116},{"ndv":1080,"upper":"CK0001517626","lower":"CK0001488716","count":1559,"preSum":4674},{"ndv":1017,"upper":"CK0001541208","lower":"CK0001517628","count":1558,"preSum":6233},{"ndv":1031,"upper":"CKH00000006832","lower":"CK0001541547","count":1558,"preSum":7791},{"ndv":1197,"upper":"PJD2304785283392317","lower":"CKH00000006833","count":1558,"preSum":9349},{"ndv":1552,"upper":"PJX2303762983710713","lower":"PJD2304785314982319","count":1558,"preSum":10907},{"ndv":1553,"upper":"PJX2304786537842613","lower":"PJX2303762984250713","count":1558,"preSum":12465},{"ndv":1558,"upper":"PJX2305794319710816","lower":"PJX2304786538712613","count":1558,"preSum":14023},{"ndv":1558,"upper":"PJX2305799243731707","lower":"PJX2305794319760816","count":1558,"preSum":15581},{"ndv":1558,"upper":"PJX2305806377442715","lower":"PJX2305799244671707","count":1558,"preSum":17139},{"ndv":1558,"upper":"PJX2306814931650510","lower":"PJX2305806391202715","count":1558,"preSum":18697},{"ndv":1558,"upper":"PJX2306821737701620","lower":"PJX2306814932540510","count":1558,"preSum":20255},{"ndv":1558,"upper":"PJX2306828409572610","lower":"PJX2306821744051621","count":1558,"preSum":21813},{"ndv":1558,"upper":"POD2305803318552510","lower":"PJX2306828409602610","count":1558,"preSum":23371},{"ndv":1552,"upper":"POD2306826334492014","lower":"POD2305803319112510","count":1558,"preSum":24929},{"ndv":1557,"upper":"PSD2304784554482208","lower":"POD2306826366302015","count":1558,"preSum":26487},{"ndv":1558,"upper":"PSD2304786286092522","lower":"PSD2304784556092209","count":1558,"preSum":28045},{"ndv":1558,"upper":"PSD2304788477123001","lower":"PSD2304786286122522","count":1558,"preSum":29603},{"ndv":1558,"upper":"PSD2305791953430408","lower":"PSD2304788477373001","count":1558,"preSum":31161},{"ndv":1558,"upper":"PSD2305793753850712","lower":"PSD2305791954940408","count":1558,"preSum":32719},{"ndv":1558,"upper":"PSD2305795803231110","lower":"PSD2305793753880712","count":1558,"preSum":34277},{"ndv":1558,"upper":"PSD2305798092981513","lower":"PSD2305795803251110","count":1558,"preSum":35835},{"ndv":1558,"upper":"PSD2305800555381916","lower":"PSD2305798093131513","count":1558,"preSum":37393},{"ndv":1558,"upper":"PSD2305802595962317","lower":"PSD2305800555401916","count":1558,"preSum":38951},{"ndv":1558,"upper":"PSD2305808329222900","lower":"PSD2305802595992317","count":1558,"preSum":40509},{"ndv":1558,"upper":"PSD2306812005410114","lower":"PSD2305808329232900","count":1558,"preSum":42067},{"ndv":1558,"upper":"PSD2306815480930609","lower":"PSD2306812005440114","count":1558,"preSum":43625},{"ndv":1558,"upper":"PSD2306817664651015","lower":"PSD2306815483860609","count":1558,"preSum":45183},{"ndv":1558,"upper":"PSD2306820039991515","lower":"PSD2306817664681015","count":1558,"preSum":46741},{"ndv":1557,"upper":"PSD2306823633311811","lower":"PSD2306820040061515","count":1558,"preSum":48299},{"ndv":1558,"upper":"PSD2306826824332102","lower":"PSD2306823633331811","count":1558,"preSum":49857},{"ndv":1558,"upper":"PTB2303758187220221","lower":"PSD2306826824532102","count":1558,"preSum":51415},{"ndv":1558,"upper":"PTB2303772935612721","lower":"PTB2303758188450221","count":1558,"preSum":52973},{"ndv":1558,"upper":"PTB2304781998971710","lower":"PTB2303772937052721","count":1558,"preSum":54531},{"ndv":1558,"upper":"PTB2304785896772500","lower":"PTB2304781999801710","count":1558,"preSum":56089},{"ndv":1558,"upper":"PTB2304788145742912","lower":"PTB2304785897952500","count":1558,"preSum":57647},{"ndv":1558,"upper":"PTB2305790284140309","lower":"PTB2304788146072912","count":1558,"preSum":59205},{"ndv":1558,"upper":"PTB2305791076680310","lower":"PTB2305790284150309","count":1558,"preSum":60763},{"ndv":1558,"upper":"PTB2305792298540417","lower":"PTB2305791076720310","count":1558,"preSum":62321},{"ndv":1558,"upper":"PTB2305794878720916","lower":"PTB2305792301440417","count":1558,"preSum":63879},{"ndv":1558,"upper":"PTB2305797258071400","lower":"PTB2305794878890916","count":1558,"preSum":65437},{"ndv":1558,"upper":"PTB2305799039211700","lower":"PTB2305797258211400","count":1558,"preSum":66995},{"ndv":1558,"upper":"PTB2305800512471915","lower":"PTB2305799039401700","count":1558,"preSum":68553},{"ndv":1558,"upper":"PTB2305802635982319","lower":"PTB2305800512501915","count":1558,"preSum":70111},{"ndv":1558,"upper":"PTB2305804534622710","lower":"PTB2305802638662319","count":1558,"preSum":71669},{"ndv":1558,"upper":"PTB2305805445112711","lower":"PTB2305804534682710","count":1558,"preSum":73227},{"ndv":1558,"upper":"PTB2305806448642716","lower":"PTB2305805445162711","count":1558,"preSum":74785},{"ndv":1558,"upper":"PTB2305807695652819","lower":"PTB2305806449402716","count":1558,"preSum":76343},{"ndv":1558,"upper":"PTB2305808842012919","lower":"PTB2305807696592819","count":1558,"preSum":77901},{"ndv":1558,"upper":"PTB2305810405703120","lower":"PTB2305808843002919","count":1558,"preSum":79459},{"ndv":1558,"upper":"PTB2305811198243123","lower":"PTB2305810406323120","count":1558,"preSum":81017},{"ndv":1558,"upper":"PTB2306812392580122","lower":"PTB2305811199133123","count":1558,"preSum":82575},{"ndv":1558,"upper":"PTB2306813790790316","lower":"PTB2306812395170122","count":1558,"preSum":84133},{"ndv":1558,"upper":"PTB2306815440990607","lower":"PTB2306813791820316","count":1558,"preSum":85691},{"ndv":1558,"upper":"PTB2306817699051016","lower":"PTB2306815441370607","count":1558,"preSum":87249},{"ndv":1558,"upper":"PTB2306820058451515","lower":"PTB2306817700751016","count":1558,"preSum":88807},{"ndv":1558,"upper":"PTB2306821329211613","lower":"PTB2306820058491515","count":1558,"preSum":90365},{"ndv":1558,"upper":"PTB2306822353521710","lower":"PTB2306821330081613","count":1558,"preSum":91923},{"ndv":1558,"upper":"PTB2306823695651811","lower":"PTB2306822355251710","count":1558,"preSum":93481},{"ndv":1558,"upper":"PTB2306825067651900","lower":"PTB2306823695891811","count":1558,"preSum":95039},{"ndv":1558,"upper":"PTB2306826678772023","lower":"PTB2306825067701900","count":1558,"preSum":96597},{"ndv":1552,"upper":"zutaochuku0524","lower":"PTB2306826679202023","count":1552,"preSum":98155}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[19,18,22,17,21,21,23,20,19,17,19,22,56],"valueArr":["CK0001419223","CK0001450608","CK0001462989","CK0001464756","CK0001465437","CK0001495698","CK0001496915","CK0001497073","CK0001507862","CK0001509210","CK0001509215","CK0001513854","CK0001564582"],"type":"String","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','shipmentid',1814550,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":971,"upper":1654312,"lower":1244829,"count":1558,"preSum":0},{"ndv":1273,"upper":2806363,"lower":1655672,"count":1558,"preSum":1558},{"ndv":1480,"upper":2997541,"lower":2806477,"count":1558,"preSum":3116},{"ndv":1416,"upper":3240110,"lower":2997570,"count":1558,"preSum":4674},{"ndv":1449,"upper":3559382,"lower":3244850,"count":1558,"preSum":6232},{"ndv":1475,"upper":3710119,"lower":3559427,"count":1558,"preSum":7790},{"ndv":1475,"upper":3805543,"lower":3710144,"count":1558,"preSum":9348},{"ndv":1526,"upper":3896838,"lower":3805545,"count":1558,"preSum":10906},{"ndv":1527,"upper":3988533,"lower":3896881,"count":1558,"preSum":12464},{"ndv":1472,"upper":4084923,"lower":3988542,"count":1558,"preSum":14022},{"ndv":1447,"upper":4156353,"lower":4084926,"count":1558,"preSum":15580},{"ndv":1504,"upper":4220220,"lower":4156361,"count":1558,"preSum":17138},{"ndv":1476,"upper":4298576,"lower":4220235,"count":1558,"preSum":18696},{"ndv":1519,"upper":4469059,"lower":4298579,"count":1558,"preSum":20254},{"ndv":1556,"upper":4543873,"lower":4469060,"count":1558,"preSum":21812},{"ndv":1558,"upper":4613910,"lower":4543876,"count":1558,"preSum":23370},{"ndv":1556,"upper":4679015,"lower":4613963,"count":1558,"preSum":24928},{"ndv":1532,"upper":4759274,"lower":4679202,"count":1559,"preSum":26486},{"ndv":1531,"upper":4878702,"lower":4759276,"count":1558,"preSum":28045},{"ndv":1518,"upper":4956631,"lower":4878865,"count":1558,"preSum":29603},{"ndv":1528,"upper":5042844,"lower":4957321,"count":1558,"preSum":31161},{"ndv":1531,"upper":5120740,"lower":5042845,"count":1558,"preSum":32719},{"ndv":1510,"upper":5208593,"lower":5120811,"count":1558,"preSum":34277},{"ndv":1554,"upper":5297266,"lower":5208594,"count":1558,"preSum":35835},{"ndv":1509,"upper":5347430,"lower":5297328,"count":1558,"preSum":37393},{"ndv":1509,"upper":5422196,"lower":5347437,"count":1558,"preSum":38951},{"ndv":1493,"upper":5487047,"lower":5422197,"count":1558,"preSum":40509},{"ndv":1496,"upper":5557101,"lower":5487053,"count":1558,"preSum":42067},{"ndv":1529,"upper":5638924,"lower":5557104,"count":1558,"preSum":43625},{"ndv":1558,"upper":5713669,"lower":5638952,"count":1558,"preSum":45183},{"ndv":1502,"upper":5779115,"lower":5713695,"count":1558,"preSum":46741},{"ndv":1504,"upper":5868473,"lower":5779159,"count":1558,"preSum":48299},{"ndv":1467,"upper":5950558,"lower":5868648,"count":1558,"preSum":49857},{"ndv":1533,"upper":6032373,"lower":5950566,"count":1558,"preSum":51415},{"ndv":1551,"upper":6116881,"lower":6032414,"count":1558,"preSum":52973},{"ndv":1547,"upper":6204146,"lower":6116953,"count":1558,"preSum":54531},{"ndv":1539,"upper":6302691,"lower":6204149,"count":1558,"preSum":56089},{"ndv":1544,"upper":6385470,"lower":6302818,"count":1558,"preSum":57647},{"ndv":1474,"upper":6472451,"lower":6385523,"count":1558,"preSum":59205},{"ndv":1498,"upper":6553645,"lower":6472453,"count":1558,"preSum":60763},{"ndv":1496,"upper":6615013,"lower":6553834,"count":1558,"preSum":62321},{"ndv":1553,"upper":6683020,"lower":6615028,"count":1558,"preSum":63879},{"ndv":1530,"upper":6761881,"lower":6683036,"count":1558,"preSum":65437},{"ndv":1557,"upper":6840657,"lower":6761893,"count":1558,"preSum":66995},{"ndv":1554,"upper":6932036,"lower":6840664,"count":1558,"preSum":68553},{"ndv":1551,"upper":7015869,"lower":6932048,"count":1558,"preSum":70111},{"ndv":1548,"upper":7104323,"lower":7015886,"count":1558,"preSum":71669},{"ndv":1525,"upper":7206396,"lower":7104368,"count":1558,"preSum":73227},{"ndv":1516,"upper":7282509,"lower":7206397,"count":1558,"preSum":74785},{"ndv":1551,"upper":7354124,"lower":7282513,"count":1558,"preSum":76343},{"ndv":1548,"upper":7434712,"lower":7354131,"count":1558,"preSum":77901},{"ndv":1493,"upper":7516442,"lower":7434931,"count":1558,"preSum":79459},{"ndv":1426,"upper":7615783,"lower":7516465,"count":1562,"preSum":81017},{"ndv":1542,"upper":7695932,"lower":7615796,"count":1558,"preSum":82579},{"ndv":1472,"upper":7770613,"lower":7695934,"count":1558,"preSum":84137},{"ndv":1508,"upper":7838765,"lower":7770626,"count":1558,"preSum":85695},{"ndv":1555,"upper":7918155,"lower":7838772,"count":1558,"preSum":87253},{"ndv":1556,"upper":7987617,"lower":7918158,"count":1558,"preSum":88811},{"ndv":1558,"upper":8066558,"lower":7987629,"count":1558,"preSum":90369},{"ndv":1558,"upper":8140246,"lower":8066566,"count":1558,"preSum":91927},{"ndv":1538,"upper":8219097,"lower":8140249,"count":1558,"preSum":93485},{"ndv":1535,"upper":8313758,"lower":8219108,"count":1558,"preSum":95043},{"ndv":1548,"upper":8390070,"lower":8313762,"count":1558,"preSum":96601},{"ndv":1506,"upper":8517611,"lower":8390071,"count":1548,"preSum":98159}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[19,18,22,17,21,21,23,20,19,17,19,22,56],"valueArr":[3026955,3331637,3563976,3589105,3592284,4268532,4317246,4417259,5080287,5132246,5132250,5345123,8172035],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','sourceerp',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[99661,326],"valueArr":["QIMEN","SAP"],"type":"String","sampleRate":0.8206422281854961}',14,0.037085027),('jala_wms_prod','shipping_container_header','stagedat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','stagedby',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[7,8,8],"valueArr":["LQ101","ZHC01","ZRX"],"type":"String","sampleRate":0.8206422281854961}',99978,0.037085027),('jala_wms_prod','shipping_container_header','stageloc',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','status',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[62,99939],"valueArr":[600,900],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','statusflow',17,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"BCAL","lower":"BCAL","count":1,"preSum":0},{"ndv":1,"upper":"JHJFY","lower":"JHJFY","count":2,"preSum":1}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[8,56977,27,6,2416,5,7923,849,31691,3,93],"valueArr":["2BDB","2C","2CLS","2CNQ","2CQZ","B-ZT","B2B","B2C","NoQC","QCOrderNoCK","default"],"type":"String","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','stopseq',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','storecode',191,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"","lower":"","count":271,"preSum":0},{"ndv":2,"upper":"75201-1","lower":"75201","count":235,"preSum":271},{"ndv":5,"upper":"75304","lower":"75216-1","count":214,"preSum":506},{"ndv":2,"upper":"75420","lower":"75304-1","count":509,"preSum":720},{"ndv":1,"upper":"75424","lower":"75424","count":324,"preSum":1229},{"ndv":3,"upper":"75429","lower":"75424-1","count":297,"preSum":1553},{"ndv":6,"upper":"75450","lower":"75430","count":255,"preSum":1850},{"ndv":2,"upper":"75452","lower":"75451","count":436,"preSum":2105},{"ndv":5,"upper":"75465","lower":"75453","count":199,"preSum":2541},{"ndv":4,"upper":"75476","lower":"75471","count":211,"preSum":2740},{"ndv":4,"upper":"75480","lower":"75476-1","count":251,"preSum":2951},{"ndv":4,"upper":"75485-1","lower":"75481","count":689,"preSum":3202},{"ndv":2,"upper":"75495","lower":"75493","count":455,"preSum":3891},{"ndv":1,"upper":"75496","lower":"75496","count":242,"preSum":4346},{"ndv":3,"upper":"75501","lower":"75499","count":427,"preSum":4588},{"ndv":1,"upper":"75502","lower":"75502","count":381,"preSum":5015},{"ndv":1,"upper":"75506","lower":"75506","count":326,"preSum":5396},{"ndv":1,"upper":"75507","lower":"75507","count":264,"preSum":5722},{"ndv":1,"upper":"75508","lower":"75508","count":208,"preSum":5986},{"ndv":1,"upper":"75511","lower":"75511","count":611,"preSum":6194},{"ndv":2,"upper":"75514","lower":"75513","count":671,"preSum":6805},{"ndv":1,"upper":"75515","lower":"75515","count":396,"preSum":7476},{"ndv":1,"upper":"75516","lower":"75516","count":202,"preSum":7872},{"ndv":1,"upper":"75517","lower":"75517","count":377,"preSum":8074},{"ndv":2,"upper":"75519","lower":"75518","count":453,"preSum":8451},{"ndv":1,"upper":"75520","lower":"75520","count":245,"preSum":8904},{"ndv":2,"upper":"75522","lower":"75521","count":412,"preSum":9149},{"ndv":6,"upper":"75536","lower":"75523","count":333,"preSum":9561},{"ndv":3,"upper":"75541","lower":"75537","count":483,"preSum":9894},{"ndv":8,"upper":"75549","lower":"75541-1","count":195,"preSum":10377},{"ndv":7,"upper":"75572","lower":"75552-1","count":217,"preSum":10572},{"ndv":1,"upper":"75577-1","lower":"75577-1","count":244,"preSum":10789},{"ndv":6,"upper":"75602","lower":"75578","count":721,"preSum":11033},{"ndv":18,"upper":"75662","lower":"75604","count":461,"preSum":11754},{"ndv":10,"upper":"75689","lower":"75668","count":155,"preSum":12215}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[40842,1269,1001,1112,10715,876,7215,936,859,1042,675,1478,1974,2666],"valueArr":["75202","75202-1","75216","75438","75485","75489","75492","75494","75500","75505","75510","75512","75552","75577"],"type":"String","sampleRate":0.8206422281854961}',14971,0.037085027),('jala_wms_prod','shipping_container_header','systemcreated',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[7447,92554],"valueArr":[0,1],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','taskcreated',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','totalconqty',1167,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":12,"lower":12,"count":11,"preSum":0},{"ndv":1,"upper":14,"lower":14,"count":12,"preSum":11},{"ndv":1,"upper":15,"lower":15,"count":16,"preSum":23},{"ndv":1,"upper":16,"lower":16,"count":13,"preSum":39},{"ndv":1,"upper":17,"lower":17,"count":11,"preSum":52},{"ndv":2,"upper":19,"lower":18,"count":18,"preSum":63},{"ndv":1,"upper":20,"lower":20,"count":11,"preSum":81},{"ndv":1,"upper":21,"lower":21,"count":11,"preSum":92},{"ndv":1,"upper":22,"lower":22,"count":14,"preSum":103},{"ndv":1,"upper":23,"lower":23,"count":10,"preSum":117},{"ndv":2,"upper":25,"lower":24,"count":18,"preSum":127},{"ndv":1,"upper":26,"lower":26,"count":12,"preSum":145},{"ndv":2,"upper":28,"lower":27,"count":19,"preSum":157},{"ndv":2,"upper":30,"lower":29,"count":13,"preSum":176},{"ndv":2,"upper":32,"lower":31,"count":13,"preSum":189},{"ndv":3,"upper":35,"lower":33,"count":13,"preSum":202},{"ndv":2,"upper":37,"lower":36,"count":12,"preSum":215},{"ndv":3,"upper":40,"lower":38,"count":23,"preSum":227},{"ndv":3,"upper":43,"lower":41,"count":12,"preSum":250},{"ndv":2,"upper":45,"lower":44,"count":12,"preSum":262},{"ndv":3,"upper":48,"lower":46,"count":13,"preSum":274},{"ndv":2,"upper":50,"lower":49,"count":20,"preSum":287},{"ndv":3,"upper":53,"lower":51,"count":13,"preSum":307},{"ndv":3,"upper":56,"lower":54,"count":11,"preSum":320},{"ndv":3,"upper":60,"lower":58,"count":14,"preSum":331},{"ndv":3,"upper":64,"lower":62,"count":13,"preSum":345},{"ndv":4,"upper":68,"lower":65,"count":10,"preSum":358},{"ndv":4,"upper":72,"lower":69,"count":10,"preSum":368},{"ndv":4,"upper":76,"lower":73,"count":11,"preSum":378},{"ndv":4,"upper":80,"lower":77,"count":10,"preSum":389},{"ndv":5,"upper":86,"lower":81,"count":10,"preSum":399},{"ndv":6,"upper":93,"lower":87,"count":10,"preSum":409},{"ndv":4,"upper":100,"lower":94,"count":10,"preSum":419},{"ndv":7,"upper":108,"lower":101,"count":10,"preSum":429},{"ndv":8,"upper":120,"lower":110,"count":12,"preSum":439},{"ndv":7,"upper":134,"lower":121,"count":11,"preSum":451},{"ndv":7,"upper":144,"lower":135,"count":10,"preSum":462},{"ndv":7,"upper":160,"lower":145,"count":10,"preSum":472},{"ndv":6,"upper":173,"lower":162,"count":10,"preSum":482},{"ndv":6,"upper":184,"lower":175,"count":10,"preSum":492},{"ndv":9,"upper":199,"lower":188,"count":10,"preSum":502},{"ndv":8,"upper":212,"lower":200,"count":10,"preSum":512},{"ndv":9,"upper":235,"lower":213,"count":10,"preSum":522},{"ndv":7,"upper":255,"lower":236,"count":10,"preSum":532},{"ndv":8,"upper":282,"lower":261,"count":11,"preSum":542},{"ndv":7,"upper":330,"lower":300,"count":10,"preSum":553},{"ndv":9,"upper":384,"lower":332,"count":10,"preSum":563},{"ndv":8,"upper":422,"lower":385,"count":10,"preSum":573},{"ndv":9,"upper":462,"lower":427,"count":10,"preSum":583},{"ndv":10,"upper":565,"lower":463,"count":10,"preSum":593},{"ndv":9,"upper":694,"lower":568,"count":10,"preSum":603},{"ndv":10,"upper":937,"lower":699,"count":10,"preSum":613},{"ndv":10,"upper":1317,"lower":939,"count":10,"preSum":623},{"ndv":7,"upper":5260,"lower":1521,"count":7,"preSum":633}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[963,416,106,51,58,38,28,36,33,26,36,25,17],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,13],"type":"Int","sampleRate":0.8206422281854961}',97528,0.037085027),('jala_wms_prod','shipping_container_header','totalqty',3890,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":11,"lower":0,"count":1331,"preSum":0},{"ndv":1,"upper":13,"lower":13,"count":1022,"preSum":1331},{"ndv":1,"upper":14,"lower":14,"count":811,"preSum":2353},{"ndv":1,"upper":16,"lower":16,"count":733,"preSum":3164},{"ndv":1,"upper":17,"lower":17,"count":1080,"preSum":3897},{"ndv":1,"upper":18,"lower":18,"count":348,"preSum":4977},{"ndv":1,"upper":19,"lower":19,"count":274,"preSum":5325},{"ndv":1,"upper":21,"lower":21,"count":226,"preSum":5599},{"ndv":2,"upper":23,"lower":22,"count":210,"preSum":5825},{"ndv":3,"upper":27,"lower":25,"count":222,"preSum":6035},{"ndv":3,"upper":30,"lower":28,"count":314,"preSum":6257},{"ndv":4,"upper":34,"lower":31,"count":233,"preSum":6571},{"ndv":4,"upper":38,"lower":35,"count":209,"preSum":6804},{"ndv":4,"upper":42,"lower":39,"count":235,"preSum":7013},{"ndv":5,"upper":47,"lower":43,"count":183,"preSum":7248},{"ndv":1,"upper":48,"lower":48,"count":1272,"preSum":7431},{"ndv":6,"upper":54,"lower":49,"count":211,"preSum":8703},{"ndv":8,"upper":62,"lower":55,"count":213,"preSum":8914},{"ndv":10,"upper":72,"lower":63,"count":219,"preSum":9127},{"ndv":20,"upper":92,"lower":73,"count":179,"preSum":9346},{"ndv":16,"upper":108,"lower":93,"count":178,"preSum":9525},{"ndv":34,"upper":144,"lower":109,"count":188,"preSum":9703},{"ndv":44,"upper":192,"lower":145,"count":190,"preSum":9891},{"ndv":32,"upper":238,"lower":193,"count":195,"preSum":10081},{"ndv":52,"upper":336,"lower":239,"count":188,"preSum":10276},{"ndv":45,"upper":480,"lower":342,"count":203,"preSum":10464},{"ndv":78,"upper":984,"lower":483,"count":179,"preSum":10667},{"ndv":107,"upper":2400,"lower":990,"count":179,"preSum":10846},{"ndv":133,"upper":6329,"lower":2430,"count":178,"preSum":11025},{"ndv":167,"upper":53760,"lower":6456,"count":178,"preSum":11203},{"ndv":10,"upper":395070,"lower":59805,"count":10,"preSum":11381}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[14804,18064,8414,7271,5008,9948,3217,3923,4681,4995,2259,1806,2747,1473],"valueArr":[1,2,3,4,5,6,7,8,9,10,12,15,20,24],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','totalvalue',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.82064223}','{"countArr":[100001],"valueArr":[0.0000],"type":"Double","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','totalvolume',94449,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":26,"upper":98.4050,"lower":6.5400,"count":1335,"preSum":0},{"ndv":57,"upper":203.9490,"lower":99.2900,"count":1244,"preSum":1335},{"ndv":56,"upper":279.1100,"lower":205.8720,"count":1274,"preSum":2579},{"ndv":52,"upper":319.8530,"lower":281.5520,"count":1554,"preSum":3853},{"ndv":113,"upper":418.2780,"lower":320.3910,"count":1315,"preSum":5407},{"ndv":94,"upper":492.4770,"lower":418.6000,"count":1351,"preSum":6722},{"ndv":53,"upper":535.0120,"lower":493.1430,"count":1284,"preSum":8073},{"ndv":49,"upper":560.1380,"lower":535.9180,"count":1931,"preSum":9357},{"ndv":57,"upper":589.1150,"lower":561.0800,"count":1306,"preSum":11288},{"ndv":73,"upper":617.9250,"lower":590.1210,"count":1223,"preSum":12594},{"ndv":118,"upper":672.7300,"lower":618.3870,"count":1391,"preSum":13817},{"ndv":101,"upper":717.2890,"lower":672.7560,"count":1225,"preSum":15208},{"ndv":110,"upper":755.8760,"lower":717.4570,"count":1320,"preSum":16433},{"ndv":53,"upper":774.7900,"lower":756.4500,"count":1333,"preSum":17753},{"ndv":182,"upper":846.6690,"lower":774.9500,"count":1243,"preSum":19086},{"ndv":122,"upper":890.9660,"lower":847.1810,"count":1240,"preSum":20329},{"ndv":165,"upper":963.8710,"lower":891.2320,"count":1222,"preSum":21569},{"ndv":201,"upper":1041.2540,"lower":963.9740,"count":1296,"preSum":22791},{"ndv":167,"upper":1115.7030,"lower":1041.3400,"count":1216,"preSum":24087},{"ndv":125,"upper":1168.0480,"lower":1115.7740,"count":1217,"preSum":25303},{"ndv":88,"upper":1203.6790,"lower":1168.2270,"count":1217,"preSum":26520},{"ndv":94,"upper":1246.9280,"lower":1204.1010,"count":1217,"preSum":27737},{"ndv":237,"upper":1358.3180,"lower":1247.0690,"count":1223,"preSum":28954},{"ndv":232,"upper":1472.2740,"lower":1359.0950,"count":1251,"preSum":30177},{"ndv":423,"upper":1665.9050,"lower":1472.3650,"count":1216,"preSum":31428},{"ndv":291,"upper":1809.4200,"lower":1666.4840,"count":1219,"preSum":32644},{"ndv":409,"upper":2022.7360,"lower":1809.5260,"count":1216,"preSum":33863},{"ndv":299,"upper":2164.6800,"lower":2023.2920,"count":1217,"preSum":35079},{"ndv":326,"upper":2332.3110,"lower":2164.9490,"count":1219,"preSum":36296},{"ndv":346,"upper":2520.4780,"lower":2332.4610,"count":1221,"preSum":37515},{"ndv":104,"upper":2586.6240,"lower":2521.0900,"count":1307,"preSum":38736},{"ndv":310,"upper":2786.9520,"lower":2587.4640,"count":1305,"preSum":40043},{"ndv":238,"upper":2914.8540,"lower":2787.2580,"count":1230,"preSum":41348},{"ndv":293,"upper":3093.8770,"lower":2915.0040,"count":1216,"preSum":42578},{"ndv":507,"upper":3440.5890,"lower":3095.6920,"count":1220,"preSum":43794},{"ndv":435,"upper":3778.6120,"lower":3443.4190,"count":1449,"preSum":45014},{"ndv":448,"upper":4196.2970,"lower":3781.9870,"count":1216,"preSum":46463},{"ndv":258,"upper":4480.4690,"lower":4197.2510,"count":1252,"preSum":47679},{"ndv":170,"upper":4721.6150,"lower":4481.0630,"count":1216,"preSum":48931},{"ndv":271,"upper":5157.3600,"lower":4723.8890,"count":1316,"preSum":50147},{"ndv":181,"upper":5482.1190,"lower":5160.9580,"count":1814,"preSum":51463},{"ndv":185,"upper":5845.1570,"lower":5483.3230,"count":1732,"preSum":53277},{"ndv":129,"upper":6106.6800,"lower":5847.6690,"count":1302,"preSum":55009},{"ndv":75,"upper":6306.9340,"lower":6108.7240,"count":1247,"preSum":56311},{"ndv":87,"upper":6508.3830,"lower":6317.7290,"count":1256,"preSum":57558},{"ndv":106,"upper":6713.3190,"lower":6508.8320,"count":1516,"preSum":58814},{"ndv":354,"upper":7627.7300,"lower":6713.3560,"count":1222,"preSum":60330},{"ndv":102,"upper":7904.1340,"lower":7629.3290,"count":1622,"preSum":61552},{"ndv":248,"upper":8665.3210,"lower":7905.1630,"count":1217,"preSum":63174},{"ndv":245,"upper":9538.1480,"lower":8667.5770,"count":1236,"preSum":64391},{"ndv":553,"upper":11864.5970,"lower":9541.2990,"count":1221,"preSum":65627},{"ndv":428,"upper":14099.8300,"lower":11865.6950,"count":1216,"preSum":66848},{"ndv":648,"upper":18307.5840,"lower":14102.1120,"count":1282,"preSum":68064},{"ndv":691,"upper":22671.6720,"lower":18313.0920,"count":1280,"preSum":69346},{"ndv":584,"upper":26814.2700,"lower":22672.4850,"count":1226,"preSum":70626},{"ndv":415,"upper":30970.3680,"lower":26821.6360,"count":1543,"preSum":71852},{"ndv":439,"upper":36613.1040,"lower":31000.2900,"count":1282,"preSum":73395},{"ndv":489,"upper":47415.6800,"lower":36640.7200,"count":1328,"preSum":74677},{"ndv":626,"upper":495525.8880,"lower":47446.5660,"count":1216,"preSum":76005},{"ndv":579,"upper":2304960000.0000,"lower":498075.8400,"count":597,"preSum":77221}],"maxBucketSize":64,"type":"Double","sampleRate":0.82064223}','{"countArr":[1612,925,1161,3343,3674,1160,957,1028,1038,1571,1028,1164,1162,2360],"valueArr":[0.0000,385.5000,738.2020,1060.3700,2204.4750,2350.3520,2967.8460,3169.9790,4408.9500,6358.2440,6858.3700,7051.0560,7736.0400,15255.4600],"type":"Double","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','totalweight',96607,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":112,"upper":0.1900,"lower":0.0000,"count":1354,"preSum":0},{"ndv":119,"upper":0.3090,"lower":0.1910,"count":1319,"preSum":1354},{"ndv":66,"upper":0.3750,"lower":0.3100,"count":1317,"preSum":2673},{"ndv":160,"upper":0.5370,"lower":0.3760,"count":1310,"preSum":3990},{"ndv":217,"upper":0.7860,"lower":0.5380,"count":1309,"preSum":5300},{"ndv":144,"upper":0.9470,"lower":0.7870,"count":1309,"preSum":6609},{"ndv":311,"upper":1.2930,"lower":0.9480,"count":1309,"preSum":7918},{"ndv":412,"upper":1.8250,"lower":1.2940,"count":1307,"preSum":9227},{"ndv":743,"upper":5.2480,"lower":1.8260,"count":1308,"preSum":10534},{"ndv":766,"upper":9.4000,"lower":5.2490,"count":1307,"preSum":11842},{"ndv":568,"upper":33.3330,"lower":9.4020,"count":1383,"preSum":13149},{"ndv":76,"upper":60.0000,"lower":34.0000,"count":1384,"preSum":14532},{"ndv":55,"upper":75.0000,"lower":60.4160,"count":1309,"preSum":15916},{"ndv":80,"upper":96.3330,"lower":75.5560,"count":1360,"preSum":17225},{"ndv":97,"upper":122.0000,"lower":96.6670,"count":1330,"preSum":18585},{"ndv":58,"upper":135.4170,"lower":122.1420,"count":1360,"preSum":19915},{"ndv":65,"upper":147.9170,"lower":135.5280,"count":1381,"preSum":21275},{"ndv":124,"upper":172.9160,"lower":148.4720,"count":1313,"preSum":22656},{"ndv":197,"upper":210.2780,"lower":172.9170,"count":1323,"preSum":23969},{"ndv":112,"upper":229.1670,"lower":210.4160,"count":1443,"preSum":25292},{"ndv":142,"upper":248.0000,"lower":229.9980,"count":1353,"preSum":26735},{"ndv":111,"upper":264.4440,"lower":248.1950,"count":1312,"preSum":28088},{"ndv":86,"upper":279.7910,"lower":264.4720,"count":1319,"preSum":29400},{"ndv":167,"upper":300.0000,"lower":279.7920,"count":1613,"preSum":30719},{"ndv":146,"upper":319.2350,"lower":300.0280,"count":1311,"preSum":32332},{"ndv":74,"upper":329.1670,"lower":319.2360,"count":1327,"preSum":33643},{"ndv":107,"upper":345.8340,"lower":329.2660,"count":1307,"preSum":34970},{"ndv":154,"upper":370.8340,"lower":346.0000,"count":1359,"preSum":36277},{"ndv":302,"upper":420.5560,"lower":371.0000,"count":1307,"preSum":37636},{"ndv":303,"upper":484.7500,"lower":420.7750,"count":1308,"preSum":38943},{"ndv":206,"upper":529.4420,"lower":484.8320,"count":1307,"preSum":40251},{"ndv":226,"upper":566.6660,"lower":529.7220,"count":1328,"preSum":41558},{"ndv":264,"upper":611.4170,"lower":566.8880,"count":1391,"preSum":42886},{"ndv":371,"upper":684.0830,"lower":611.5560,"count":1320,"preSum":44277},{"ndv":394,"upper":762.8330,"lower":684.2500,"count":1307,"preSum":45597},{"ndv":240,"upper":820.1410,"lower":763.0000,"count":1348,"preSum":46904},{"ndv":207,"upper":858.3330,"lower":820.7480,"count":1309,"preSum":48252},{"ndv":208,"upper":901.3060,"lower":859.0000,"count":1307,"preSum":49561},{"ndv":288,"upper":951.9330,"lower":901.4440,"count":1342,"preSum":50868},{"ndv":373,"upper":1018.0290,"lower":952.0000,"count":1307,"preSum":52210},{"ndv":369,"upper":1100.0000,"lower":1018.6670,"count":1418,"preSum":53517},{"ndv":360,"upper":1177.3330,"lower":1100.0840,"count":1308,"preSum":54935},{"ndv":409,"upper":1262.5020,"lower":1177.4390,"count":1597,"preSum":56243},{"ndv":551,"upper":1424.0000,"lower":1263.4150,"count":1350,"preSum":57840},{"ndv":309,"upper":1513.9170,"lower":1424.0800,"count":1328,"preSum":59190},{"ndv":210,"upper":1575.0000,"lower":1513.9880,"count":1338,"preSum":60518},{"ndv":226,"upper":1639.5830,"lower":1575.1660,"count":1329,"preSum":61856},{"ndv":171,"upper":1699.9980,"lower":1640.0810,"count":1386,"preSum":63185},{"ndv":265,"upper":1795.8330,"lower":1700.0000,"count":1421,"preSum":64571},{"ndv":271,"upper":1917.8330,"lower":1795.8340,"count":1459,"preSum":65992},{"ndv":145,"upper":2000.0000,"lower":1919.5830,"count":1316,"preSum":67451},{"ndv":203,"upper":2104.1700,"lower":2000.0040,"count":1322,"preSum":68767},{"ndv":133,"upper":2187.8060,"lower":2104.5000,"count":1575,"preSum":70089},{"ndv":202,"upper":2342.6130,"lower":2187.8330,"count":1406,"preSum":71664},{"ndv":419,"upper":2752.6640,"lower":2342.6390,"count":1307,"preSum":73070},{"ndv":496,"upper":3500.0000,"lower":2757.2080,"count":1310,"preSum":74377},{"ndv":605,"upper":4997.0000,"lower":3504.8660,"count":1307,"preSum":75687},{"ndv":648,"upper":6552.5200,"lower":4997.9190,"count":1307,"preSum":76994},{"ndv":539,"upper":8263.3280,"lower":6554.8330,"count":1307,"preSum":78301},{"ndv":322,"upper":9360.0000,"lower":8266.6660,"count":1309,"preSum":79608},{"ndv":554,"upper":14588.5000,"lower":9364.1650,"count":1307,"preSum":80917},{"ndv":1084,"upper":4335199.8800,"lower":14608.5000,"count":1307,"preSum":82224},{"ndv":45,"upper":1300951200.0000,"lower":4384700.0640,"count":54,"preSum":83531}],"maxBucketSize":64,"type":"Double","sampleRate":0.82064223}','{"countArr":[810,1089,2021,894,1472,1162,1485,651,1237,1191,1021,892,1232,1259],"valueArr":[266.6660,490.0000,508.3340,600.0000,780.0000,799.9980,837.5000,964.1660,1758.1140,1800.0000,2250.0000,2545.8350,3900.0000,4208.3400],"type":"Double","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','transcontcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','uploadbatch',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','userdef1',995,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"","lower":"","count":22,"preSum":0},{"ndv":13,"upper":"1000889","lower":"1000277","count":19,"preSum":22},{"ndv":5,"upper":"1001060","lower":"1000901","count":18,"preSum":41},{"ndv":9,"upper":"1001257","lower":"1001063","count":19,"preSum":59},{"ndv":9,"upper":"1001485","lower":"1001259","count":19,"preSum":78},{"ndv":13,"upper":"1002190","lower":"1001521","count":19,"preSum":97},{"ndv":9,"upper":"1002623","lower":"1002282","count":17,"preSum":116},{"ndv":14,"upper":"2000027","lower":"1002640","count":17,"preSum":133},{"ndv":5,"upper":"2000032","lower":"2000028","count":17,"preSum":150},{"ndv":6,"upper":"2000251","lower":"2000033","count":23,"preSum":167},{"ndv":3,"upper":"2000255","lower":"2000253","count":17,"preSum":190},{"ndv":3,"upper":"2000258","lower":"2000256","count":17,"preSum":207},{"ndv":2,"upper":"2000287","lower":"2000259","count":23,"preSum":224},{"ndv":14,"upper":"2001958","lower":"2000402","count":17,"preSum":247},{"ndv":14,"upper":"2005634","lower":"2002091","count":17,"preSum":264},{"ndv":12,"upper":"C001","lower":"2005679","count":17,"preSum":281},{"ndv":7,"upper":"D004-1000","lower":"C002","count":19,"preSum":298},{"ndv":6,"upper":"DW07","lower":"D005-1000","count":18,"preSum":317},{"ndv":4,"upper":"S002-1000","lower":"JD08","count":26,"preSum":335},{"ndv":2,"upper":"S004-1000","lower":"S003-1000","count":28,"preSum":361},{"ndv":1,"upper":"S005-1000","lower":"S005-1000","count":21,"preSum":389},{"ndv":2,"upper":"S104-1000","lower":"S101-1000","count":24,"preSum":410},{"ndv":2,"upper":"S107-1000","lower":"S106-1000","count":33,"preSum":434},{"ndv":3,"upper":"S112-1000","lower":"S108-1000","count":36,"preSum":467},{"ndv":2,"upper":"S115-1000","lower":"S113-1000","count":35,"preSum":503},{"ndv":6,"upper":"上海自备仓B2B(顺丰)","lower":"上海公共平台仓4号库","count":28,"preSum":538},{"ndv":5,"upper":"京东固安仓","lower":"东方美谷奉贤集合店","count":18,"preSum":566},{"ndv":4,"upper":"京东昆山仓","lower":"京东广州仓-佛山市三水区","count":20,"preSum":584},{"ndv":7,"upper":"北京华星-天津市武清区","lower":"京东武汉仓","count":18,"preSum":604},{"ndv":12,"upper":"唯品西北仓","lower":"北京华星-浙江省嘉兴市平湖市","count":17,"preSum":622},{"ndv":2,"upper":"嘉兴仓B2B自营库区(顺丰)-1000","lower":"唯品西南仓","count":23,"preSum":639},{"ndv":4,"upper":"天津仓B2B自营库区(顺丰)-1000","lower":"嘉兴仓电商自营库区(顺丰)-2030","count":25,"preSum":662},{"ndv":5,"upper":"屈臣氏-南海仓","lower":"天津仓电商自营库区(顺丰)-1000","count":25,"preSum":687},{"ndv":2,"upper":"屈臣氏-天津仓","lower":"屈臣氏-厦门仓","count":27,"preSum":712},{"ndv":2,"upper":"屈臣氏-昆山仓","lower":"屈臣氏-成都仓","count":32,"preSum":739},{"ndv":1,"upper":"屈臣氏-武汉仓","lower":"屈臣氏-武汉仓","count":18,"preSum":771},{"ndv":3,"upper":"屈臣氏-郑州仓","lower":"屈臣氏-沈阳仓","count":20,"preSum":789},{"ndv":9,"upper":"广州明购网络科技有限公司(自然堂现代货架)","lower":"山东有容商贸有限公司(自然堂现代货架)","count":17,"preSum":809},{"ndv":3,"upper":"微信公众号-珀芙研微信商城","lower":"广西怡亚通大泽深度供应链管理有限公司海南分公司(自然堂商超)","count":17,"preSum":826},{"ndv":3,"upper":"无锡苏易祥贸易有限公司(自然堂现代货架)","lower":"成都仓B2B自营库区(顺丰)-1000","count":17,"preSum":843},{"ndv":4,"upper":"武汉仓电商自营库区(顺丰)-1000","lower":"昆明悦容堂-云南省昆明市呈贡县","count":32,"preSum":860},{"ndv":8,"upper":"沈阳仓B2B自营库区(顺丰)-1000","lower":"武汉美诵化妆品有限公司(自然堂货架服务商)","count":20,"preSum":892},{"ndv":3,"upper":"淮北市逸风商贸有限公司(自然堂现代货架)","lower":"济南仓B2B自营库区(顺丰)-1000","count":17,"preSum":912},{"ndv":3,"upper":"清远仓电商自营库区(顺丰)-1000","lower":"深圳茂华-广东省深圳市宝安区","count":23,"preSum":929},{"ndv":5,"upper":"福建三福服饰有限公司(自然堂大客户KA)","lower":"濮阳市华龙区万光物资供应部(珀芙研个人)","count":19,"preSum":952},{"ndv":7,"upper":"西安仓B2B自营库区(顺丰)-1000","lower":"福建三福服饰有限公司(自然堂美妆KA)","count":22,"preSum":971},{"ndv":2,"upper":"西安奕涛商贸有限公司(自然堂现代货架)","lower":"西安仓电商自营库区(顺丰)-1000","count":17,"preSum":993},{"ndv":7,"upper":"郑州盛妆贸易有限公司(自然堂现代货架)","lower":"西昌市金利美商贸有限公司(自然堂现代货架)","count":17,"preSum":1010},{"ndv":2,"upper":"销售退货仓(电商)","lower":"钱桥仓电商自营库区(东臻)-1000","count":24,"preSum":1027},{"ndv":4,"upper":"青岛福兴祥商业有限公司-山东(自然堂美妆店)","lower":"长沙仓B2B自营库区(顺丰)-1000","count":17,"preSum":1051},{"ndv":2,"upper":"鲁勇(珀芙研个人)","lower":"青岛福兴祥商业有限公司(自然堂商超)","count":7,"preSum":1068}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[47,49,46,24,35,24,26,36,43,27,46,47],"valueArr":["2005821","9910","9998","D017","S001-1000","S007-1000","S102-1000","S103-1000","S105-1000","伽蓝集团","嘉兴仓电商自营库区(顺丰)-1000","珀芙研-个人"],"type":"String","sampleRate":0.8206422281854961}',98476,0.037085027),('jala_wms_prod','shipping_container_header','userdef2',19,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"D001中转区","lower":"D001中转区","count":1,"preSum":0},{"ndv":1,"upper":"D001委外直发1","lower":"D001委外直发1","count":1,"preSum":1}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[283,191,7,26,30,116,12],"valueArr":["D001","D001ZCJ","D001商品拣货区B","D001商品拣货区C","D001商品拣货区D","D001商品零拣区","D001存储区"],"type":"String","sampleRate":0.8206422281854961}',99334,0.037085027),('jala_wms_prod','shipping_container_header','userdef3',1090,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":9,"upper":"108","lower":"100","count":129,"preSum":0},{"ndv":12,"upper":"119","lower":"109","count":122,"preSum":129},{"ndv":14,"upper":"133","lower":"120","count":130,"preSum":251},{"ndv":13,"upper":"146","lower":"134","count":126,"preSum":381},{"ndv":4,"upper":"15","lower":"147","count":596,"preSum":507},{"ndv":11,"upper":"16","lower":"150","count":513,"preSum":1103},{"ndv":11,"upper":"17","lower":"160","count":414,"preSum":1616},{"ndv":11,"upper":"18","lower":"170","count":319,"preSum":2030},{"ndv":11,"upper":"19","lower":"180","count":258,"preSum":2349},{"ndv":11,"upper":"20","lower":"190","count":323,"preSum":2607},{"ndv":11,"upper":"21","lower":"200","count":212,"preSum":2930},{"ndv":11,"upper":"22","lower":"210","count":180,"preSum":3142},{"ndv":11,"upper":"23","lower":"220","count":141,"preSum":3322},{"ndv":9,"upper":"24","lower":"230","count":239,"preSum":3463},{"ndv":9,"upper":"25","lower":"240","count":122,"preSum":3702},{"ndv":11,"upper":"26","lower":"250","count":152,"preSum":3824},{"ndv":10,"upper":"27","lower":"260","count":120,"preSum":3976},{"ndv":10,"upper":"28","lower":"270","count":123,"preSum":4096},{"ndv":17,"upper":"30","lower":"280","count":216,"preSum":4219},{"ndv":18,"upper":"32","lower":"300","count":180,"preSum":4435},{"ndv":13,"upper":"34","lower":"320","count":152,"preSum":4615},{"ndv":10,"upper":"36","lower":"35","count":233,"preSum":4767},{"ndv":18,"upper":"38","lower":"360","count":151,"preSum":5000},{"ndv":16,"upper":"40","lower":"383","count":146,"preSum":5151},{"ndv":9,"upper":"42","lower":"400","count":142,"preSum":5297},{"ndv":11,"upper":"45","lower":"426","count":152,"preSum":5439},{"ndv":5,"upper":"48","lower":"454","count":241,"preSum":5591},{"ndv":3,"upper":"50","lower":"484","count":132,"preSum":5832},{"ndv":3,"upper":"52","lower":"51","count":130,"preSum":5964},{"ndv":11,"upper":"546","lower":"521","count":120,"preSum":6094},{"ndv":12,"upper":"56","lower":"548","count":138,"preSum":6214},{"ndv":8,"upper":"58","lower":"560","count":122,"preSum":6352},{"ndv":4,"upper":"62","lower":"59","count":130,"preSum":6474},{"ndv":4,"upper":"66","lower":"63","count":157,"preSum":6604},{"ndv":12,"upper":"71","lower":"67","count":145,"preSum":6761},{"ndv":23,"upper":"75","lower":"713","count":137,"preSum":6906},{"ndv":10,"upper":"80","lower":"751","count":140,"preSum":7043},{"ndv":6,"upper":"85","lower":"804","count":125,"preSum":7183},{"ndv":5,"upper":"90","lower":"86","count":129,"preSum":7308},{"ndv":12,"upper":"96","lower":"903","count":128,"preSum":7437},{"ndv":3,"upper":"99","lower":"97","count":60,"preSum":7565}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[7831,1957,984,1019,623,597,9391,5922,5403,3125,3653,2141,2756,1673],"valueArr":["1","10","11","12","13","14","2","3","4","5","6","7","8","9"],"type":"String","sampleRate":0.8206422281854961}',45301,0.037085027),('jala_wms_prod','shipping_container_header','userdef4',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','userdef5',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','userdef6',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','userdef7',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','userdef8',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','version',7,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":1,"lower":1,"count":1,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[100000],"valueArr":[0],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','videofilename',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}',null,100001,0.037085027),('jala_wms_prod','shipping_container_header','warehousecode',9,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[2075,10444,18096,1307,50687,15675,708,938,71],"valueArr":["021DC1","022DC","027DC","028DC","573DC","763DC","SH01","SH02","SH03"],"type":"String","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','waveid',23835,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":376,"upper":338131,"lower":687,"count":1554,"preSum":0},{"ndv":369,"upper":559333,"lower":338132,"count":1547,"preSum":1554},{"ndv":217,"upper":592087,"lower":559355,"count":1544,"preSum":3101},{"ndv":265,"upper":663345,"lower":592088,"count":1544,"preSum":4645},{"ndv":263,"upper":709165,"lower":663352,"count":1546,"preSum":6189},{"ndv":256,"upper":730211,"lower":709184,"count":1548,"preSum":7735},{"ndv":269,"upper":746484,"lower":730212,"count":1549,"preSum":9283},{"ndv":180,"upper":755627,"lower":746498,"count":1572,"preSum":10832},{"ndv":222,"upper":767290,"lower":755668,"count":1555,"preSum":12404},{"ndv":216,"upper":777488,"lower":767292,"count":1545,"preSum":13959},{"ndv":254,"upper":787585,"lower":777501,"count":1559,"preSum":15504},{"ndv":197,"upper":793582,"lower":787645,"count":1544,"preSum":17063},{"ndv":188,"upper":803071,"lower":793604,"count":1547,"preSum":18607},{"ndv":153,"upper":811902,"lower":803072,"count":1555,"preSum":20154},{"ndv":129,"upper":819673,"lower":811920,"count":1553,"preSum":21709},{"ndv":109,"upper":822125,"lower":819674,"count":1556,"preSum":23262},{"ndv":137,"upper":826565,"lower":822133,"count":1577,"preSum":24818},{"ndv":159,"upper":834956,"lower":826566,"count":1565,"preSum":26395},{"ndv":166,"upper":847010,"lower":835215,"count":1546,"preSum":27960},{"ndv":192,"upper":859958,"lower":847027,"count":1562,"preSum":29506},{"ndv":181,"upper":874190,"lower":859962,"count":1544,"preSum":31068},{"ndv":191,"upper":883948,"lower":874191,"count":1544,"preSum":32612},{"ndv":217,"upper":895951,"lower":883950,"count":1548,"preSum":34156},{"ndv":167,"upper":910604,"lower":896089,"count":1552,"preSum":35704},{"ndv":179,"upper":919718,"lower":910610,"count":1558,"preSum":37256},{"ndv":228,"upper":928902,"lower":919719,"count":1583,"preSum":38814},{"ndv":188,"upper":935087,"lower":928903,"count":1555,"preSum":40397},{"ndv":213,"upper":945227,"lower":935088,"count":1548,"preSum":41952},{"ndv":190,"upper":957222,"lower":945298,"count":1553,"preSum":43500},{"ndv":144,"upper":966805,"lower":957263,"count":1550,"preSum":45053},{"ndv":244,"upper":979731,"lower":966861,"count":1551,"preSum":46603},{"ndv":240,"upper":995182,"lower":979753,"count":1547,"preSum":48154},{"ndv":211,"upper":1007749,"lower":995183,"count":1586,"preSum":49701},{"ndv":186,"upper":1019624,"lower":1007782,"count":1558,"preSum":51287},{"ndv":183,"upper":1028575,"lower":1019625,"count":1544,"preSum":52845},{"ndv":194,"upper":1036722,"lower":1028577,"count":1580,"preSum":54389},{"ndv":194,"upper":1041570,"lower":1036734,"count":1548,"preSum":55969},{"ndv":98,"upper":1043294,"lower":1041571,"count":1570,"preSum":57517},{"ndv":113,"upper":1046390,"lower":1043301,"count":1549,"preSum":59087},{"ndv":95,"upper":1048667,"lower":1046532,"count":1555,"preSum":60636},{"ndv":117,"upper":1050953,"lower":1048683,"count":1548,"preSum":62191},{"ndv":121,"upper":1052453,"lower":1050972,"count":1563,"preSum":63739},{"ndv":130,"upper":1056400,"lower":1052473,"count":1545,"preSum":65302},{"ndv":175,"upper":1060825,"lower":1056511,"count":1560,"preSum":66847},{"ndv":179,"upper":1070616,"lower":1060841,"count":1549,"preSum":68407},{"ndv":151,"upper":1080486,"lower":1070820,"count":1545,"preSum":69956},{"ndv":158,"upper":1099906,"lower":1080487,"count":1544,"preSum":71501},{"ndv":223,"upper":1117233,"lower":1099927,"count":1551,"preSum":73045},{"ndv":184,"upper":1132054,"lower":1117234,"count":1554,"preSum":74596},{"ndv":181,"upper":1146900,"lower":1132060,"count":1546,"preSum":76150},{"ndv":216,"upper":1162158,"lower":1146905,"count":1550,"preSum":77696},{"ndv":217,"upper":1174485,"lower":1162160,"count":1548,"preSum":79246},{"ndv":296,"upper":1185941,"lower":1174506,"count":1544,"preSum":80794},{"ndv":164,"upper":1191626,"lower":1185998,"count":1575,"preSum":82338},{"ndv":185,"upper":1195170,"lower":1191628,"count":1564,"preSum":83913},{"ndv":149,"upper":1201072,"lower":1195172,"count":1566,"preSum":85477},{"ndv":140,"upper":1205343,"lower":1201155,"count":1566,"preSum":87043},{"ndv":153,"upper":1211698,"lower":1205409,"count":1550,"preSum":88609},{"ndv":163,"upper":1215842,"lower":1211700,"count":1547,"preSum":90159},{"ndv":155,"upper":1222280,"lower":1215859,"count":1544,"preSum":91706},{"ndv":145,"upper":1234690,"lower":1222282,"count":1554,"preSum":93250},{"ndv":188,"upper":1260447,"lower":1234692,"count":1557,"preSum":94804},{"ndv":209,"upper":1287122,"lower":1260992,"count":1564,"preSum":96361},{"ndv":182,"upper":1303367,"lower":1287266,"count":882,"preSum":97925}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[93,81,80,78,77,94,119,87,77,85,88,84,74,77],"valueArr":[0,767248,769482,814459,846737,898828,936560,982709,1051251,1119163,1153201,1188180,1197226,1261300],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','waybillcode',2426357,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1533,"upper":"279526056908","lower":"031949796097","count":1533,"preSum":0},{"ndv":1533,"upper":"32001963425900000003","lower":"279526056926","count":1533,"preSum":1533},{"ndv":1533,"upper":"32001993640700000006","lower":"32001963427200000003","count":1533,"preSum":3066},{"ndv":1533,"upper":"73503086055333","lower":"32001993640700000007","count":1533,"preSum":4599},{"ndv":1533,"upper":"75609819799162","lower":"73503131835487","count":1533,"preSum":6132},{"ndv":1533,"upper":"75610197153216","lower":"75609819808322","count":1533,"preSum":7665},{"ndv":1533,"upper":"75911005598000","lower":"75610197458139","count":1533,"preSum":9198},{"ndv":1533,"upper":"78681939396293","lower":"75911013043113","count":1533,"preSum":10731},{"ndv":1533,"upper":"78685976626368","lower":"78681939402189","count":1533,"preSum":12264},{"ndv":1533,"upper":"78689360006948","lower":"78685980769225","count":1533,"preSum":13797},{"ndv":1533,"upper":"78691971957665","lower":"78689375653663","count":1533,"preSum":15330},{"ndv":1533,"upper":"78694868569442","lower":"78691972189856","count":1533,"preSum":16863},{"ndv":1533,"upper":"78697384715516","lower":"78694869923080","count":1533,"preSum":18396},{"ndv":1533,"upper":"SF1374634923795","lower":"78697387251164","count":1533,"preSum":19929},{"ndv":1533,"upper":"SF1375334209707","lower":"SF1374635976055","count":1533,"preSum":21462},{"ndv":1533,"upper":"SF1375645238014","lower":"SF1375334210048","count":1533,"preSum":22995},{"ndv":1533,"upper":"SF1375887694617","lower":"SF1375645240597","count":1533,"preSum":24528},{"ndv":1533,"upper":"SF1380378498368","lower":"SF1375887756477","count":1533,"preSum":26061},{"ndv":1533,"upper":"SF1383430359347","lower":"SF1380378498861","count":1533,"preSum":27594},{"ndv":1533,"upper":"SF1385815898063","lower":"SF1383430639148","count":1533,"preSum":29127},{"ndv":1533,"upper":"SF1388259509541","lower":"SF1385815945942","count":1533,"preSum":30660},{"ndv":1533,"upper":"SF1603228077582","lower":"SF1388260559944","count":1533,"preSum":32193},{"ndv":1533,"upper":"SF1603509494438","lower":"SF1603228332013","count":1533,"preSum":33726},{"ndv":1533,"upper":"SF1603779079337","lower":"SF1603509494456","count":1533,"preSum":35259},{"ndv":1533,"upper":"SF1604102699900","lower":"SF1603782110915","count":1533,"preSum":36792},{"ndv":1533,"upper":"SF1612023802090","lower":"SF1604102705107","count":1533,"preSum":38325},{"ndv":1533,"upper":"SF1614694887003","lower":"SF1612025359018","count":1533,"preSum":39858},{"ndv":1533,"upper":"SF1617386599981","lower":"SF1614701361027","count":1533,"preSum":41391},{"ndv":1533,"upper":"SF1620684949596","lower":"SF1617387624043","count":1533,"preSum":42924},{"ndv":1533,"upper":"SF1623407487794","lower":"SF1620691799217","count":1533,"preSum":44457},{"ndv":1533,"upper":"SF1626404063048","lower":"SF1623407743982","count":1533,"preSum":45990},{"ndv":1533,"upper":"SF1629631011247","lower":"SF1626404067743","count":1533,"preSum":47523},{"ndv":1533,"upper":"SF1631631184574","lower":"SF1629631040160","count":1533,"preSum":49056},{"ndv":1533,"upper":"SF1634166284092","lower":"SF1631633344669","count":1533,"preSum":50589},{"ndv":1533,"upper":"SF1636640814332","lower":"SF1634166524713","count":1533,"preSum":52122},{"ndv":1533,"upper":"SF1639187164675","lower":"SF1636641234873","count":1533,"preSum":53655},{"ndv":1533,"upper":"SF1641952139178","lower":"SF1639187984698","count":1533,"preSum":55188},{"ndv":1533,"upper":"SF1644782332170","lower":"SF1641952182178","count":1533,"preSum":56721},{"ndv":1533,"upper":"SF1647560369151","lower":"SF1644784901120","count":1533,"preSum":58254},{"ndv":1533,"upper":"SF1650346220432","lower":"SF1647560541151","count":1533,"preSum":59787},{"ndv":1533,"upper":"SF1653244434667","lower":"SF1650346351595","count":1533,"preSum":61320},{"ndv":1533,"upper":"SF1655964975786","lower":"SF1653244438125","count":1533,"preSum":62853},{"ndv":1533,"upper":"SF1658740658575","lower":"SF1655965713736","count":1533,"preSum":64386},{"ndv":1533,"upper":"SF1661449837480","lower":"SF1658740665052","count":1533,"preSum":65919},{"ndv":1533,"upper":"SF1663474449860","lower":"SF1661450108833","count":1533,"preSum":67452},{"ndv":1533,"upper":"SF1666489871922","lower":"SF1663474593998","count":1533,"preSum":68985},{"ndv":1533,"upper":"SF1669631674457","lower":"SF1666489873842","count":1533,"preSum":70518},{"ndv":1533,"upper":"SF1672986293818","lower":"SF1669631825593","count":1533,"preSum":72051},{"ndv":1533,"upper":"SF1675947124172","lower":"SF1672986713308","count":1533,"preSum":73584},{"ndv":1533,"upper":"SF1678948264552","lower":"SF1675947600982","count":1533,"preSum":75117},{"ndv":1533,"upper":"SF1681827116876","lower":"SF1678948269334","count":1533,"preSum":76650},{"ndv":1533,"upper":"SF1683675320514","lower":"SF1681827193299","count":1533,"preSum":78183},{"ndv":1533,"upper":"SF1686867550407","lower":"SF1683675328944","count":1533,"preSum":79716},{"ndv":1533,"upper":"SF1689153573426","lower":"SF1686867791508","count":1533,"preSum":81249},{"ndv":1533,"upper":"SF1692199728843","lower":"SF1689156232707","count":1533,"preSum":82782},{"ndv":1533,"upper":"SF1695046746343","lower":"SF1692199734247","count":1533,"preSum":84315},{"ndv":1533,"upper":"SF1698284326442","lower":"SF1695051249149","count":1533,"preSum":85848},{"ndv":1533,"upper":"SF1831673309691","lower":"SF1698285837508","count":1533,"preSum":87381},{"ndv":1533,"upper":"SF1832043135339","lower":"SF1831673311467","count":1533,"preSum":88914},{"ndv":1533,"upper":"SF1832445508617","lower":"SF1832043159387","count":1533,"preSum":90447},{"ndv":1533,"upper":"SF1833068822593","lower":"SF1832445732635","count":1533,"preSum":91980},{"ndv":1533,"upper":"SF1833521916446","lower":"SF1833068858066","count":1533,"preSum":93513},{"ndv":1533,"upper":"SF2031850089503","lower":"SF1833522020245","count":1533,"preSum":95046},{"ndv":1489,"upper":"SF7607172431782","lower":"SF2031850091924","count":1489,"preSum":96579}],"maxBucketSize":64,"type":"String","sampleRate":0.82064223}','{"countArr":[1072,3],"valueArr":["","1"],"type":"String","sampleRate":0.8206422281854961}',858,0.037085027),('jala_wms_prod','shipping_container_header','width',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.82064223}','{"countArr":[100001],"valueArr":[0.0000],"type":"Double","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','ztoregisterroute',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[30,92084,7887],"valueArr":[-1,0,1],"type":"Int","sampleRate":0.8206422281854961}',0,0.037085027),('jala_wms_prod','shipping_container_header','zxqty',1167,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":12,"lower":12,"count":11,"preSum":0},{"ndv":1,"upper":14,"lower":14,"count":12,"preSum":11},{"ndv":1,"upper":15,"lower":15,"count":16,"preSum":23},{"ndv":1,"upper":16,"lower":16,"count":13,"preSum":39},{"ndv":1,"upper":17,"lower":17,"count":11,"preSum":52},{"ndv":2,"upper":19,"lower":18,"count":18,"preSum":63},{"ndv":1,"upper":20,"lower":20,"count":11,"preSum":81},{"ndv":1,"upper":21,"lower":21,"count":11,"preSum":92},{"ndv":1,"upper":22,"lower":22,"count":14,"preSum":103},{"ndv":1,"upper":23,"lower":23,"count":10,"preSum":117},{"ndv":2,"upper":25,"lower":24,"count":18,"preSum":127},{"ndv":1,"upper":26,"lower":26,"count":12,"preSum":145},{"ndv":2,"upper":28,"lower":27,"count":19,"preSum":157},{"ndv":2,"upper":30,"lower":29,"count":13,"preSum":176},{"ndv":2,"upper":32,"lower":31,"count":13,"preSum":189},{"ndv":3,"upper":35,"lower":33,"count":13,"preSum":202},{"ndv":2,"upper":37,"lower":36,"count":12,"preSum":215},{"ndv":3,"upper":40,"lower":38,"count":23,"preSum":227},{"ndv":3,"upper":43,"lower":41,"count":12,"preSum":250},{"ndv":2,"upper":45,"lower":44,"count":12,"preSum":262},{"ndv":3,"upper":48,"lower":46,"count":13,"preSum":274},{"ndv":2,"upper":50,"lower":49,"count":20,"preSum":287},{"ndv":3,"upper":53,"lower":51,"count":13,"preSum":307},{"ndv":3,"upper":56,"lower":54,"count":11,"preSum":320},{"ndv":3,"upper":60,"lower":58,"count":14,"preSum":331},{"ndv":3,"upper":64,"lower":62,"count":13,"preSum":345},{"ndv":4,"upper":68,"lower":65,"count":10,"preSum":358},{"ndv":4,"upper":72,"lower":69,"count":10,"preSum":368},{"ndv":4,"upper":76,"lower":73,"count":11,"preSum":378},{"ndv":4,"upper":80,"lower":77,"count":10,"preSum":389},{"ndv":5,"upper":86,"lower":81,"count":10,"preSum":399},{"ndv":6,"upper":93,"lower":87,"count":10,"preSum":409},{"ndv":4,"upper":100,"lower":94,"count":10,"preSum":419},{"ndv":7,"upper":108,"lower":101,"count":10,"preSum":429},{"ndv":8,"upper":120,"lower":110,"count":12,"preSum":439},{"ndv":7,"upper":134,"lower":121,"count":11,"preSum":451},{"ndv":7,"upper":144,"lower":135,"count":10,"preSum":462},{"ndv":7,"upper":160,"lower":145,"count":10,"preSum":472},{"ndv":6,"upper":173,"lower":162,"count":10,"preSum":482},{"ndv":6,"upper":184,"lower":175,"count":10,"preSum":492},{"ndv":9,"upper":199,"lower":188,"count":10,"preSum":502},{"ndv":8,"upper":212,"lower":200,"count":10,"preSum":512},{"ndv":9,"upper":235,"lower":213,"count":10,"preSum":522},{"ndv":7,"upper":255,"lower":236,"count":10,"preSum":532},{"ndv":8,"upper":282,"lower":261,"count":11,"preSum":542},{"ndv":7,"upper":330,"lower":300,"count":10,"preSum":553},{"ndv":9,"upper":384,"lower":332,"count":10,"preSum":563},{"ndv":8,"upper":422,"lower":385,"count":10,"preSum":573},{"ndv":9,"upper":462,"lower":427,"count":10,"preSum":583},{"ndv":10,"upper":565,"lower":463,"count":10,"preSum":593},{"ndv":9,"upper":694,"lower":568,"count":10,"preSum":603},{"ndv":10,"upper":937,"lower":699,"count":10,"preSum":613},{"ndv":10,"upper":1317,"lower":939,"count":10,"preSum":623},{"ndv":7,"upper":5260,"lower":1521,"count":7,"preSum":633}],"maxBucketSize":64,"type":"Int","sampleRate":0.82064223}','{"countArr":[963,417,105,51,58,38,28,36,33,26,36,25,17],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,13],"type":"Int","sampleRate":0.8206422281854961}',97528,0.037085027),('jala_wms_prod','task_detail','agingdate',914,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":92,"upper":"1850271361360986112","lower":"-1","count":1231,"preSum":0},{"ndv":29,"upper":"1850376914477252608","lower":"1850273560384241664","count":1086,"preSum":1231},{"ndv":25,"upper":"1850438487128408064","lower":"1850379113500508160","count":1098,"preSum":2317},{"ndv":11,"upper":"1850462676384219136","lower":"1850440686151663616","count":1331,"preSum":3415},{"ndv":8,"upper":"1850480268570263552","lower":"1850464875407474688","count":1200,"preSum":4746},{"ndv":6,"upper":"1850495661733052416","lower":"1850482467593519104","count":1195,"preSum":5946},{"ndv":5,"upper":"1850506656849330176","lower":"1850497860756307968","count":1092,"preSum":7141},{"ndv":6,"upper":"1850519850988863488","lower":"1850508855872585728","count":1093,"preSum":8233},{"ndv":10,"upper":"1850541841221419008","lower":"1850522050012119040","count":1071,"preSum":9326},{"ndv":11,"upper":"1850570428523741184","lower":"1850544040244674560","count":1084,"preSum":10397},{"ndv":16,"upper":"1850605612895830016","lower":"1850572627546996736","count":1074,"preSum":11481},{"ndv":17,"upper":"1850715564058607616","lower":"1850607811919085568","count":1116,"preSum":12555},{"ndv":18,"upper":"1850770539639996416","lower":"1850717763081863168","count":1195,"preSum":13671},{"ndv":12,"upper":"1850796927919063040","lower":"1850772738663251968","count":1270,"preSum":14866},{"ndv":8,"upper":"1850814520105107456","lower":"1850799126942318592","count":1130,"preSum":16136},{"ndv":5,"upper":"1850825515221385216","lower":"1850816719128363008","count":1299,"preSum":17266},{"ndv":3,"upper":"1850840908384174080","lower":"1850827714244640768","count":1745,"preSum":18565},{"ndv":3,"upper":"1850847505453940736","lower":"1850843107407429632","count":1132,"preSum":20310},{"ndv":6,"upper":"1850860699593474048","lower":"1850849704477196288","count":1608,"preSum":21442},{"ndv":4,"upper":"1850869495686496256","lower":"1850862898616729600","count":1324,"preSum":23050},{"ndv":3,"upper":"1850876092756262912","lower":"1850871694709751808","count":1344,"preSum":24374},{"ndv":4,"upper":"1850884888849285120","lower":"1850878291779518464","count":1238,"preSum":25718},{"ndv":5,"upper":"1850895883965562880","lower":"1850887087872540672","count":1114,"preSum":26956},{"ndv":5,"upper":"1850906879081840640","lower":"1850898082988818432","count":1611,"preSum":28070},{"ndv":2,"upper":"1850913476151607296","lower":"1850911277128351744","count":1194,"preSum":29681},{"ndv":4,"upper":"1850922272244629504","lower":"1850915675174862848","count":1209,"preSum":30875},{"ndv":5,"upper":"1850933267360907264","lower":"1850924471267885056","count":1140,"preSum":32084},{"ndv":2,"upper":"1850937665407418368","lower":"1850935466384162816","count":1466,"preSum":33224},{"ndv":2,"upper":"1850944262477185024","lower":"1850939864430673920","count":1315,"preSum":34690},{"ndv":2,"upper":"1850948660523696128","lower":"1850946461500440576","count":1993,"preSum":36005},{"ndv":2,"upper":"1850959655639973888","lower":"1850950859546951680","count":1966,"preSum":37998},{"ndv":2,"upper":"1850966252709740544","lower":"1850964053686484992","count":1516,"preSum":39964},{"ndv":2,"upper":"1850970650756251648","lower":"1850968451732996096","count":1188,"preSum":41480},{"ndv":2,"upper":"1850981645872529408","lower":"1850975048802762752","count":1066,"preSum":42668},{"ndv":2,"upper":"1850986043919040512","lower":"1850983844895784960","count":1830,"preSum":43734},{"ndv":1,"upper":"1850988242942296064","lower":"1850988242942296064","count":1176,"preSum":45564},{"ndv":4,"upper":"1850997039035318272","lower":"1850990441965551616","count":2220,"preSum":46740},{"ndv":2,"upper":"1851001437081829376","lower":"1850999238058573824","count":1408,"preSum":48960},{"ndv":2,"upper":"1851010233174851584","lower":"1851005835128340480","count":1644,"preSum":50368},{"ndv":1,"upper":"1851012432198107136","lower":"1851012432198107136","count":1145,"preSum":52012},{"ndv":2,"upper":"1851027825360896000","lower":"1851016830244618240","count":2230,"preSum":53157},{"ndv":2,"upper":"1851034422430662656","lower":"1851032223407407104","count":1489,"preSum":55387},{"ndv":2,"upper":"1851038820477173760","lower":"1851036621453918208","count":1636,"preSum":56876},{"ndv":3,"upper":"1851045417546940416","lower":"1851041019500429312","count":1764,"preSum":58512},{"ndv":2,"upper":"1851052014616707072","lower":"1851047616570195968","count":1615,"preSum":60276},{"ndv":2,"upper":"1851056412663218176","lower":"1851054213639962624","count":1096,"preSum":61891},{"ndv":2,"upper":"1851060810709729280","lower":"1851058611686473728","count":1434,"preSum":62987},{"ndv":3,"upper":"1851067407779495936","lower":"1851063009732984832","count":1234,"preSum":64421},{"ndv":3,"upper":"1851074004849262592","lower":"1851069606802751488","count":1149,"preSum":65655},{"ndv":4,"upper":"1851082800942284800","lower":"1851076203872518144","count":1100,"preSum":66804},{"ndv":4,"upper":"1854528670383734784","lower":"1851084999965540352","count":268,"preSum":67904}],"maxBucketSize":64,"type":"Date","sampleRate":1.0}','{"countArr":[1578,2270,1380,1363,1316,1397,2431,1407,1852,1460,1948,2868,1343,2725],"valueArr":[1850942063453929472,1850953058570207232,1850955257593462784,1850957456616718336,1850961854663229440,1850972849779507200,1851003636105084928,1851008034151596032,1851014631221362688,1851019029267873792,1851021228291129344,1851023427314384896,1851025626337640448,1851030024384151552],"type":"Date","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','assigneduser',18,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"WX","lower":"WX","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[8],"valueArr":["zhaozhujun"],"type":"String","sampleRate":1.0}',93501,0.006721839),('jala_wms_prod','task_detail','attribute1',50,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"W009调入","lower":"W009调入","count":4,"preSum":0},{"ndv":1,"upper":"分仓近效期","lower":"分仓近效期","count":2,"preSum":4},{"ndv":1,"upper":"分仓退回","lower":"分仓退回","count":4,"preSum":6},{"ndv":1,"upper":"医药渠道","lower":"医药渠道","count":4,"preSum":10},{"ndv":1,"upper":"大客户渠道","lower":"大客户渠道","count":5,"preSum":14},{"ndv":1,"upper":"电商渠道—西安仓退错批次","lower":"电商渠道—西安仓退错批次","count":1,"preSum":19},{"ndv":1,"upper":"破损退回","lower":"破损退回","count":5,"preSum":20},{"ndv":1,"upper":"美妆店渠道","lower":"美妆店渠道","count":3,"preSum":25},{"ndv":1,"upper":"领料退库","lower":"领料退库","count":1,"preSum":28}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[320,2590,10,83,21,53,6,10,6,8679,109,64,6],"valueArr":["(空白)","0","W028调入","分仓","分仓过期","商超渠道","总仓","总仓过期","本地零售渠道","电商渠道","美妆渠道","货架渠道","质量召回"],"type":"String","sampleRate":1.0}',81524,0.006721839),('jala_wms_prod','task_detail','attribute2',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','attribute3',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','attribute4',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','attribute5',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','attribute6',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','attribute7',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','attribute8',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','attributeid',168883,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":972,"upper":33979,"lower":1542,"count":1429,"preSum":0},{"ndv":932,"upper":56378,"lower":33980,"count":1429,"preSum":1429},{"ndv":646,"upper":64221,"lower":56379,"count":1431,"preSum":2858},{"ndv":785,"upper":75435,"lower":64222,"count":1428,"preSum":4289},{"ndv":932,"upper":101804,"lower":75441,"count":1428,"preSum":5717},{"ndv":963,"upper":124966,"lower":101805,"count":1431,"preSum":7145},{"ndv":272,"upper":125949,"lower":124967,"count":1428,"preSum":8576},{"ndv":494,"upper":132710,"lower":125950,"count":1428,"preSum":10004},{"ndv":554,"upper":140801,"lower":132746,"count":1438,"preSum":11432},{"ndv":548,"upper":147189,"lower":140803,"count":1431,"preSum":12870},{"ndv":634,"upper":160095,"lower":147191,"count":1441,"preSum":14301},{"ndv":580,"upper":167799,"lower":160099,"count":1442,"preSum":15742},{"ndv":232,"upper":168799,"lower":167801,"count":1430,"preSum":17184},{"ndv":195,"upper":169948,"lower":168800,"count":1437,"preSum":18614},{"ndv":584,"upper":176300,"lower":169950,"count":1428,"preSum":20051},{"ndv":414,"upper":180664,"lower":176307,"count":1428,"preSum":21479},{"ndv":182,"upper":182546,"lower":180679,"count":1433,"preSum":22907},{"ndv":152,"upper":183301,"lower":182548,"count":1431,"preSum":24340},{"ndv":181,"upper":184062,"lower":183302,"count":1443,"preSum":25771},{"ndv":110,"upper":184570,"lower":184121,"count":1434,"preSum":27214},{"ndv":204,"upper":186002,"lower":184571,"count":1428,"preSum":28648},{"ndv":204,"upper":188123,"lower":186024,"count":1429,"preSum":30076},{"ndv":210,"upper":189344,"lower":188127,"count":1435,"preSum":31505},{"ndv":109,"upper":189912,"lower":189348,"count":1447,"preSum":32940},{"ndv":96,"upper":190056,"lower":189914,"count":1434,"preSum":34387},{"ndv":90,"upper":190257,"lower":190057,"count":1428,"preSum":35821},{"ndv":106,"upper":190410,"lower":190260,"count":1473,"preSum":37249},{"ndv":213,"upper":191492,"lower":190411,"count":1431,"preSum":38722},{"ndv":273,"upper":192997,"lower":191493,"count":1431,"preSum":40153},{"ndv":166,"upper":194915,"lower":193069,"count":1503,"preSum":41584},{"ndv":363,"upper":198774,"lower":194924,"count":1430,"preSum":43087},{"ndv":255,"upper":201850,"lower":198777,"count":1436,"preSum":44517},{"ndv":202,"upper":203634,"lower":201851,"count":1438,"preSum":45953},{"ndv":308,"upper":206524,"lower":203635,"count":1428,"preSum":47391},{"ndv":290,"upper":210135,"lower":206532,"count":1480,"preSum":48819},{"ndv":182,"upper":211008,"lower":210136,"count":1461,"preSum":50299},{"ndv":292,"upper":303700,"lower":211009,"count":1443,"preSum":51760},{"ndv":117,"upper":304916,"lower":303725,"count":1447,"preSum":53203},{"ndv":306,"upper":404165,"lower":304957,"count":1439,"preSum":54650},{"ndv":211,"upper":406020,"lower":404175,"count":1432,"preSum":56089},{"ndv":214,"upper":407644,"lower":406022,"count":1444,"preSum":57521},{"ndv":164,"upper":408637,"lower":407645,"count":1432,"preSum":58965},{"ndv":167,"upper":410084,"lower":408639,"count":1428,"preSum":60397},{"ndv":202,"upper":411714,"lower":410088,"count":1444,"preSum":61825},{"ndv":219,"upper":414459,"lower":411715,"count":1442,"preSum":63269},{"ndv":174,"upper":416059,"lower":414463,"count":1441,"preSum":64711},{"ndv":247,"upper":417306,"lower":416073,"count":1437,"preSum":66152},{"ndv":267,"upper":418925,"lower":417307,"count":1430,"preSum":67589},{"ndv":163,"upper":420031,"lower":418926,"count":1450,"preSum":69019},{"ndv":176,"upper":421198,"lower":420032,"count":1429,"preSum":70469},{"ndv":220,"upper":421911,"lower":421199,"count":1431,"preSum":71898},{"ndv":216,"upper":423280,"lower":421912,"count":1445,"preSum":73329},{"ndv":222,"upper":425644,"lower":423286,"count":1429,"preSum":74774},{"ndv":140,"upper":426586,"lower":425650,"count":1451,"preSum":76203},{"ndv":212,"upper":428082,"lower":426587,"count":1435,"preSum":77654},{"ndv":312,"upper":431474,"lower":428087,"count":1428,"preSum":79089},{"ndv":201,"upper":433591,"lower":431498,"count":1432,"preSum":80517},{"ndv":201,"upper":436508,"lower":433593,"count":1450,"preSum":81949},{"ndv":182,"upper":438608,"lower":436509,"count":1435,"preSum":83399},{"ndv":173,"upper":441124,"lower":438609,"count":1429,"preSum":84834},{"ndv":183,"upper":444000,"lower":441130,"count":1436,"preSum":86263},{"ndv":310,"upper":449010,"lower":444020,"count":1428,"preSum":87699},{"ndv":297,"upper":453704,"lower":449019,"count":1436,"preSum":89127},{"ndv":214,"upper":459127,"lower":453710,"count":791,"preSum":90563}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[165,163,160,122,134,168,126,121,123,177,152,286,137,122],"valueArr":[182267,188250,189005,190037,206517,206534,210159,302246,411425,415956,420609,421718,425937,445251],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','batch',20545,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":123,"upper":"113F20931","lower":"01208","count":1272,"preSum":0},{"ndv":68,"upper":"123E43231","lower":"113F21581","count":1310,"preSum":1272},{"ndv":117,"upper":"172E57281","lower":"123E43232","count":1258,"preSum":2582},{"ndv":93,"upper":"173E40602","lower":"172E57601","count":1341,"preSum":3840},{"ndv":35,"upper":"173F11901","lower":"173E40611","count":1250,"preSum":5181},{"ndv":145,"upper":"182F26041","lower":"173F11951","count":1256,"preSum":6431},{"ndv":88,"upper":"183F21131","lower":"182F26051","count":1287,"preSum":7687},{"ndv":168,"upper":"193E40301","lower":"183F21201","count":1270,"preSum":8974},{"ndv":53,"upper":"193F21361","lower":"193E40302","count":1260,"preSum":10244},{"ndv":165,"upper":"212212301","lower":"193F21381","count":1251,"preSum":11504},{"ndv":189,"upper":"26927","lower":"212212302","count":1268,"preSum":12755},{"ndv":243,"upper":"283E11501","lower":"26A01","count":1316,"preSum":14023},{"ndv":198,"upper":"29Q21","lower":"283E11502","count":1250,"preSum":15339},{"ndv":167,"upper":"2XM06","lower":"29Q27","count":1250,"preSum":16589},{"ndv":72,"upper":"2XU29","lower":"2XM08","count":1276,"preSum":17839},{"ndv":101,"upper":"2Y827","lower":"2XUL0","count":1250,"preSum":19115},{"ndv":59,"upper":"2YG08","lower":"2Y830","count":1254,"preSum":20365},{"ndv":51,"upper":"2YM06","lower":"2YG09","count":1357,"preSum":21619},{"ndv":81,"upper":"2YU07","lower":"2YM08","count":1268,"preSum":22976},{"ndv":51,"upper":"2Z407","lower":"2YU21","count":1251,"preSum":24244},{"ndv":76,"upper":"2ZH08","lower":"2Z408","count":1261,"preSum":25495},{"ndv":53,"upper":"2ZV21","lower":"2ZH22","count":1303,"preSum":26756},{"ndv":56,"upper":"31A07","lower":"2ZV22","count":1252,"preSum":28059},{"ndv":78,"upper":"322304063","lower":"31A08","count":1254,"preSum":29311},{"ndv":80,"upper":"32M04","lower":"322304071","count":1260,"preSum":30565},{"ndv":50,"upper":"33505","lower":"32M08","count":1263,"preSum":31825},{"ndv":45,"upper":"33C21","lower":"33506","count":1255,"preSum":33088},{"ndv":57,"upper":"33J02","lower":"33C27","count":1317,"preSum":34343},{"ndv":34,"upper":"33P06","lower":"33J04","count":1279,"preSum":35660},{"ndv":34,"upper":"33W09","lower":"33P07","count":1358,"preSum":36939},{"ndv":36,"upper":"34422","lower":"33W27","count":1277,"preSum":38297},{"ndv":43,"upper":"34A05","lower":"34424","count":1260,"preSum":39574},{"ndv":45,"upper":"34E06","lower":"34A06","count":1254,"preSum":40834},{"ndv":42,"upper":"34K09","lower":"34E08","count":1280,"preSum":42088},{"ndv":54,"upper":"34R08","lower":"34K10","count":1268,"preSum":43368},{"ndv":37,"upper":"34V02","lower":"34R09","count":1303,"preSum":44636},{"ndv":36,"upper":"35408","lower":"34V04","count":1251,"preSum":45939},{"ndv":28,"upper":"35805","lower":"35421","count":1302,"preSum":47190},{"ndv":34,"upper":"35C20","lower":"35808","count":1284,"preSum":48492},{"ndv":53,"upper":"35S29","lower":"35C22","count":1256,"preSum":49776},{"ndv":160,"upper":"552302111","lower":"35T08","count":1289,"preSum":51032},{"ndv":80,"upper":"632301081","lower":"552302152","count":1269,"preSum":52321},{"ndv":123,"upper":"732301122","lower":"632301082","count":1250,"preSum":53590},{"ndv":44,"upper":"732304231","lower":"732301311","count":1266,"preSum":54840},{"ndv":33,"upper":"732305182","lower":"732304251","count":1295,"preSum":56106},{"ndv":103,"upper":"752302061","lower":"732305191","count":1306,"preSum":57401},{"ndv":74,"upper":"772210313","lower":"752302071","count":1257,"preSum":58707},{"ndv":92,"upper":"772305071","lower":"772211011","count":1264,"preSum":59964},{"ndv":105,"upper":"792301051","lower":"772305081","count":1276,"preSum":61228},{"ndv":80,"upper":"812211091","lower":"792301061","count":1257,"preSum":62504},{"ndv":171,"upper":"CS2992012","lower":"812211101","count":1254,"preSum":63761},{"ndv":101,"upper":"CS2992711","lower":"CS2992022","count":1257,"preSum":65015},{"ndv":78,"upper":"CS3990121","lower":"CS2992721","count":1279,"preSum":66272},{"ndv":60,"upper":"CS3990421","lower":"CS3990122","count":1252,"preSum":67551},{"ndv":130,"upper":"EK2991591","lower":"CS3990422","count":1261,"preSum":68803},{"ndv":80,"upper":"EK2992591","lower":"EK2991592","count":1250,"preSum":70064},{"ndv":105,"upper":"EK2993782","lower":"EK2992592","count":1258,"preSum":71314},{"ndv":37,"upper":"EK3990131","lower":"EK2993783","count":1273,"preSum":72572},{"ndv":27,"upper":"EK3990261","lower":"EK3990132","count":1277,"preSum":73845},{"ndv":27,"upper":"EK3990402","lower":"EK3990262","count":1250,"preSum":75122},{"ndv":58,"upper":"J01E27951","lower":"EK3990405","count":1260,"preSum":76372},{"ndv":106,"upper":"L82207081","lower":"J01E29652","count":1259,"preSum":77632},{"ndv":183,"upper":"XL2990065","lower":"L82207091","count":1101,"preSum":78891}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[248,334,504,295,751,407,383,678,204,228,207,206,946,8122],"valueArr":["2207","2208","2210","2211","2212","2302","2303","2304","34324","34F24","34M30","EK3990391","JALA","N12012"],"type":"String","sampleRate":1.0}',5,0.006721839),('jala_wms_prod','task_detail','companycode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[16197,974,76339],"valueArr":["JALA01","JALA02","JALA11"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','confirmedat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','confirmedby',693,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":21,"upper":"000051","lower":"000008","count":1031,"preSum":0},{"ndv":8,"upper":"000060","lower":"000052","count":1253,"preSum":1031},{"ndv":4,"upper":"000064","lower":"000061","count":1063,"preSum":2284},{"ndv":4,"upper":"000068","lower":"000065","count":1049,"preSum":3347},{"ndv":15,"upper":"000084","lower":"000069","count":1006,"preSum":4396},{"ndv":5,"upper":"000095","lower":"000085","count":1010,"preSum":5402},{"ndv":17,"upper":"0220017","lower":"000097","count":1017,"preSum":6412},{"ndv":18,"upper":"0220038","lower":"0220018","count":1066,"preSum":7429},{"ndv":11,"upper":"0220049","lower":"0220039","count":1109,"preSum":8495},{"ndv":25,"upper":"0220097","lower":"0220050","count":1469,"preSum":9604},{"ndv":16,"upper":"02700030","lower":"0220099","count":1088,"preSum":11073},{"ndv":19,"upper":"02700056","lower":"02700032","count":1566,"preSum":12161},{"ndv":9,"upper":"02700065","lower":"02700057","count":1083,"preSum":13727},{"ndv":3,"upper":"02700068","lower":"02700066","count":1254,"preSum":14810},{"ndv":9,"upper":"02700077","lower":"02700069","count":1029,"preSum":16064},{"ndv":18,"upper":"02700098","lower":"02700078","count":1023,"preSum":17093},{"ndv":10,"upper":"02700118","lower":"02700101","count":1031,"preSum":18116},{"ndv":15,"upper":"02700135","lower":"02700119","count":1310,"preSum":19147},{"ndv":4,"upper":"02700139","lower":"02700136","count":1097,"preSum":20457},{"ndv":6,"upper":"02700145","lower":"02700140","count":1010,"preSum":21554},{"ndv":9,"upper":"02700156","lower":"02700146","count":1036,"preSum":22564},{"ndv":31,"upper":"10000003","lower":"02700157","count":1006,"preSum":23600},{"ndv":11,"upper":"10000018","lower":"10000006","count":1310,"preSum":24606},{"ndv":4,"upper":"10000023","lower":"10000019","count":1094,"preSum":25916},{"ndv":3,"upper":"10000026","lower":"10000024","count":1232,"preSum":27010},{"ndv":14,"upper":"10000166","lower":"10000027","count":1191,"preSum":28242},{"ndv":6,"upper":"10012","lower":"10000168","count":1407,"preSum":29433},{"ndv":2,"upper":"10014","lower":"10013","count":1281,"preSum":30840},{"ndv":2,"upper":"10016","lower":"10015","count":1300,"preSum":32121},{"ndv":3,"upper":"10019","lower":"10017","count":1412,"preSum":33421},{"ndv":3,"upper":"10022","lower":"10020","count":1416,"preSum":34833},{"ndv":3,"upper":"10025","lower":"10023","count":1286,"preSum":36249},{"ndv":3,"upper":"10028","lower":"10026","count":1104,"preSum":37535},{"ndv":4,"upper":"10032","lower":"10029","count":1195,"preSum":38639},{"ndv":5,"upper":"10037","lower":"10033","count":1141,"preSum":39834},{"ndv":9,"upper":"10046","lower":"10038","count":1043,"preSum":40975},{"ndv":10,"upper":"10056","lower":"10047","count":1010,"preSum":42018},{"ndv":23,"upper":"10081","lower":"10057","count":1003,"preSum":43028},{"ndv":23,"upper":"10204","lower":"10086","count":1092,"preSum":44031},{"ndv":30,"upper":"41428116","lower":"10205","count":1715,"preSum":45123},{"ndv":10,"upper":"41827355","lower":"41512820","count":1020,"preSum":46838},{"ndv":8,"upper":"42032315","lower":"41829032","count":1186,"preSum":47858},{"ndv":7,"upper":"42089063","lower":"42034700","count":1566,"preSum":49044},{"ndv":8,"upper":"42126799","lower":"42089966","count":1033,"preSum":50610},{"ndv":1,"upper":"42127969","lower":"42127969","count":1040,"preSum":51643},{"ndv":2,"upper":"42132989","lower":"42128445","count":1173,"preSum":52683},{"ndv":2,"upper":"42149881","lower":"42133390","count":1354,"preSum":53856},{"ndv":9,"upper":"42196744","lower":"42151366","count":1297,"preSum":55210},{"ndv":6,"upper":"42196812","lower":"42196747","count":1212,"preSum":56507},{"ndv":19,"upper":"57302036","lower":"42196820","count":1015,"preSum":57719},{"ndv":27,"upper":"LL","lower":"57302037","count":1510,"preSum":58734},{"ndv":10,"upper":"RY","lower":"LQ101","count":1083,"preSum":60244},{"ndv":15,"upper":"YBJ","lower":"SHB","count":1349,"preSum":61327},{"ndv":4,"upper":"YYJ","lower":"YF","count":1186,"preSum":62676},{"ndv":6,"upper":"ZRX","lower":"zhangkeming","count":174,"preSum":63862}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[1999,2234,1680,3064,2145,1079,1099,1591,1406,1441,1633,2168,1108,6826],"valueArr":["0220078","40721814","41003009","41306222","41826343","41896759","41940218","42078907","42111665","42126804","42138044","42144832","WJH","api"],"type":"String","sampleRate":1.0}',1,0.006721839),('jala_wms_prod','task_detail','convertedqty',3849,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":11,"lower":11,"count":76,"preSum":0},{"ndv":1,"upper":13,"lower":13,"count":72,"preSum":76},{"ndv":1,"upper":14,"lower":14,"count":71,"preSum":148},{"ndv":1,"upper":15,"lower":15,"count":115,"preSum":219},{"ndv":1,"upper":16,"lower":16,"count":73,"preSum":334},{"ndv":1,"upper":17,"lower":17,"count":38,"preSum":407},{"ndv":2,"upper":21,"lower":19,"count":71,"preSum":445},{"ndv":2,"upper":23,"lower":22,"count":44,"preSum":516},{"ndv":1,"upper":24,"lower":24,"count":93,"preSum":560},{"ndv":1,"upper":25,"lower":25,"count":53,"preSum":653},{"ndv":2,"upper":27,"lower":26,"count":43,"preSum":706},{"ndv":2,"upper":29,"lower":28,"count":43,"preSum":749},{"ndv":2,"upper":32,"lower":31,"count":52,"preSum":792},{"ndv":2,"upper":34,"lower":33,"count":34,"preSum":844},{"ndv":2,"upper":36,"lower":35,"count":69,"preSum":878},{"ndv":3,"upper":39,"lower":37,"count":36,"preSum":947},{"ndv":1,"upper":40,"lower":40,"count":73,"preSum":983},{"ndv":2,"upper":42,"lower":41,"count":53,"preSum":1056},{"ndv":5,"upper":47,"lower":43,"count":36,"preSum":1109},{"ndv":1,"upper":48,"lower":48,"count":68,"preSum":1145},{"ndv":2,"upper":50,"lower":49,"count":51,"preSum":1213},{"ndv":6,"upper":56,"lower":51,"count":60,"preSum":1264},{"ndv":4,"upper":60,"lower":57,"count":32,"preSum":1324},{"ndv":5,"upper":65,"lower":61,"count":32,"preSum":1356},{"ndv":5,"upper":70,"lower":66,"count":33,"preSum":1388},{"ndv":2,"upper":72,"lower":71,"count":64,"preSum":1421},{"ndv":7,"upper":80,"lower":73,"count":76,"preSum":1485},{"ndv":10,"upper":90,"lower":81,"count":46,"preSum":1561},{"ndv":8,"upper":103,"lower":92,"count":32,"preSum":1607},{"ndv":12,"upper":120,"lower":104,"count":35,"preSum":1639},{"ndv":19,"upper":149,"lower":122,"count":32,"preSum":1674},{"ndv":9,"upper":162,"lower":150,"count":33,"preSum":1706},{"ndv":20,"upper":210,"lower":165,"count":33,"preSum":1739},{"ndv":27,"upper":300,"lower":211,"count":35,"preSum":1772},{"ndv":28,"upper":454,"lower":309,"count":32,"preSum":1807},{"ndv":18,"upper":582,"lower":466,"count":32,"preSum":1839},{"ndv":30,"upper":994,"lower":588,"count":32,"preSum":1871},{"ndv":32,"upper":1474,"lower":1002,"count":32,"preSum":1903},{"ndv":29,"upper":2278,"lower":1513,"count":32,"preSum":1935},{"ndv":25,"upper":162397,"lower":2353,"count":29,"preSum":1967}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[60495,16853,2867,5708,1520,1631,338,369,221,790,355,120,118,129],"valueArr":[1,2,3,4,5,6,7,8,9,10,12,18,20,30],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','convertedqtyum',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[1654,90340,1488,28],"valueArr":["CS","EA","MP","PL"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','coverreson',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[108],"valueArr":[""],"type":"String","sampleRate":1.0}',93402,0.006721839),('jala_wms_prod','task_detail','created',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','createdby',156,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"000002","lower":"000002","count":996,"preSum":0},{"ndv":1,"upper":"000003","lower":"000003","count":1184,"preSum":996},{"ndv":1,"upper":"000004","lower":"000004","count":1592,"preSum":2180},{"ndv":9,"upper":"0220003","lower":"000006","count":346,"preSum":3772},{"ndv":1,"upper":"0220006","lower":"0220006","count":1615,"preSum":4118},{"ndv":4,"upper":"02700003","lower":"0220009","count":1217,"preSum":5733},{"ndv":1,"upper":"02700009","lower":"02700009","count":1161,"preSum":6950},{"ndv":14,"upper":"1000003","lower":"02700020","count":750,"preSum":8111},{"ndv":1,"upper":"1000004","lower":"1000004","count":350,"preSum":8861},{"ndv":4,"upper":"10001","lower":"1000006","count":1454,"preSum":9211},{"ndv":2,"upper":"10003","lower":"10002","count":1024,"preSum":10665},{"ndv":2,"upper":"10005","lower":"10004","count":338,"preSum":11689},{"ndv":4,"upper":"10009","lower":"10006","count":629,"preSum":12027},{"ndv":12,"upper":"41512820","lower":"20001","count":816,"preSum":12656},{"ndv":2,"upper":"42085600","lower":"41580442","count":611,"preSum":13472},{"ndv":5,"upper":"gth","lower":"42104883","count":338,"preSum":14083},{"ndv":2,"upper":"hxy","lower":"GY","count":923,"preSum":14421},{"ndv":3,"upper":"LL","lower":"lh","count":747,"preSum":15344},{"ndv":2,"upper":"lyg","lower":"lxp","count":581,"preSum":16091},{"ndv":6,"upper":"WJH","lower":"PZ","count":1067,"preSum":16672},{"ndv":3,"upper":"YBJ","lower":"XCY","count":459,"preSum":17739},{"ndv":2,"upper":"yxy","lower":"yj","count":1915,"preSum":18198},{"ndv":1,"upper":"zhaolingling","lower":"zhaolingling","count":371,"preSum":20113},{"ndv":1,"upper":"zjf","lower":"zjf","count":198,"preSum":20484}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[2272,4556,2686,8298,2130,2317,2538,2403,2950,7638,9805,16258,2151,6826],"valueArr":["000001","0220005","02700005","02700010","10000002","10000004","40401644","40721814","41157743","41509297","41580109","42008280","42196770","api"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','csqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93510],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','currentloc',7093,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":10,"upper":"3QA0408","lower":"021DCQQ-M12-01-01-01","count":15,"preSum":0},{"ndv":9,"upper":"3QD0506","lower":"3QA0411","count":16,"preSum":15},{"ndv":14,"upper":"A0105","lower":"3QD0511","count":15,"preSum":31},{"ndv":15,"upper":"A0326","lower":"A0110","count":15,"preSum":46},{"ndv":15,"upper":"A0511","lower":"A0330","count":15,"preSum":61},{"ndv":14,"upper":"B0615","lower":"A0709","count":15,"preSum":76},{"ndv":9,"upper":"B0713","lower":"B0617","count":15,"preSum":91},{"ndv":13,"upper":"B1202","lower":"B0723","count":15,"preSum":106},{"ndv":12,"upper":"BT1-02-A29","lower":"B1203","count":15,"preSum":121},{"ndv":11,"upper":"BT1-07-A11","lower":"BT1-02-A33","count":15,"preSum":136},{"ndv":12,"upper":"C-03-032","lower":"BT1-07-A15","count":15,"preSum":151},{"ndv":11,"upper":"CH-0511C2","lower":"C-04-108","count":15,"preSum":166},{"ndv":13,"upper":"CH-0619E10","lower":"CH-0511D3","count":15,"preSum":181},{"ndv":10,"upper":"D002-QM001","lower":"CLS-02-A36","count":16,"preSum":196},{"ndv":12,"upper":"D0300","lower":"D0116","count":15,"preSum":212},{"ndv":14,"upper":"D0347","lower":"D0301","count":15,"preSum":227},{"ndv":13,"upper":"D0443","lower":"D0350","count":15,"preSum":242},{"ndv":14,"upper":"D0533","lower":"D0503","count":15,"preSum":257},{"ndv":10,"upper":"D0644","lower":"D0534","count":15,"preSum":272},{"ndv":9,"upper":"DD06","lower":"D0645","count":21,"preSum":287},{"ndv":8,"upper":"DL02-1","lower":"DH02-03","count":17,"preSum":308},{"ndv":13,"upper":"DL10-2","lower":"DL02-3","count":15,"preSum":325},{"ndv":7,"upper":"DL13-3","lower":"DL11-1","count":15,"preSum":340},{"ndv":6,"upper":"JALASH","lower":"DL14-2","count":15,"preSum":355},{"ndv":5,"upper":"T03-02","lower":"QZ001","count":16,"preSum":370},{"ndv":6,"upper":"T03-14","lower":"T03-03","count":17,"preSum":386},{"ndv":5,"upper":"T03-22","lower":"T03-15","count":15,"preSum":403},{"ndv":5,"upper":"T03-27","lower":"T03-23","count":15,"preSum":418},{"ndv":4,"upper":"T03-31","lower":"T03-28","count":15,"preSum":433},{"ndv":6,"upper":"T04-08","lower":"T03-32","count":18,"preSum":448},{"ndv":6,"upper":"T04-30","lower":"T04-09","count":19,"preSum":466},{"ndv":5,"upper":"T05-08","lower":"T05-01","count":15,"preSum":485},{"ndv":9,"upper":"T05-27","lower":"T05-12","count":15,"preSum":500},{"ndv":8,"upper":"T06-04","lower":"T05-31","count":16,"preSum":515},{"ndv":5,"upper":"T06-14","lower":"T06-07","count":18,"preSum":531},{"ndv":6,"upper":"T07-01","lower":"T06-16","count":16,"preSum":549},{"ndv":5,"upper":"T07-14","lower":"T07-03","count":15,"preSum":565},{"ndv":6,"upper":"T07-24","lower":"T07-15","count":15,"preSum":580},{"ndv":5,"upper":"T07-34","lower":"T07-28","count":15,"preSum":595},{"ndv":7,"upper":"T08-27","lower":"T08-02","count":15,"preSum":610},{"ndv":8,"upper":"T09-17","lower":"T08-28","count":19,"preSum":625},{"ndv":7,"upper":"T11-24","lower":"T09-18","count":16,"preSum":644},{"ndv":5,"upper":"T13-35","lower":"T12-15","count":15,"preSum":660},{"ndv":13,"upper":"TH04-19-02","lower":"T13-50","count":16,"preSum":675},{"ndv":11,"upper":"TH07-11-01","lower":"TH04-21-01","count":15,"preSum":691},{"ndv":12,"upper":"TH08-03-02","lower":"TH07-14-02","count":16,"preSum":706},{"ndv":11,"upper":"TH09-02-02","lower":"TH08-04-02","count":16,"preSum":722},{"ndv":6,"upper":"TH09-09-01","lower":"TH09-04-02","count":15,"preSum":738},{"ndv":10,"upper":"TH10-02-02","lower":"TH09-09-02","count":19,"preSum":753},{"ndv":10,"upper":"TH11-04-01","lower":"TH10-03-02","count":15,"preSum":772},{"ndv":2,"upper":"TH11-05-02","lower":"TH11-04-02","count":15,"preSum":787},{"ndv":12,"upper":"TH12-09-02","lower":"TH11-06-02","count":15,"preSum":802},{"ndv":6,"upper":"TH13-03-02","lower":"TH12-16-01","count":15,"preSum":817},{"ndv":12,"upper":"TH14-14-02","lower":"TH13-05-01","count":16,"preSum":832},{"ndv":12,"upper":"TH15-13-01","lower":"TH14-19-01","count":15,"preSum":848},{"ndv":11,"upper":"TH16-24-01","lower":"TH15-14-01","count":15,"preSum":863},{"ndv":9,"upper":"TH17-08-02","lower":"TH16-24-02","count":16,"preSum":878},{"ndv":13,"upper":"TH18-14-01","lower":"TH17-21-02","count":15,"preSum":894},{"ndv":14,"upper":"TH20-03-01","lower":"TH18-14-02","count":17,"preSum":909},{"ndv":4,"upper":"TH27-06-02","lower":"TH20-04-03","count":6,"preSum":926}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[28,31,65,22,17,64,11,339,12,17,798,6826,12],"valueArr":["021DCQQ-SS03-08-127","1Z-10A45","2C-TH","2QB09","763DCA-XYTB2B-SH01","763DCA-XYTB2C-SH01","D002-QZ001","LOST12","T03-19","T12-01","T15-25","TH01","ZWY01"],"type":"String","sampleRate":1.0}',84336,0.006721839),('jala_wms_prod','task_detail','currentlpn',2192,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"021DC1-0033","lower":",","count":2,"preSum":0},{"ndv":2,"upper":"0220909HH0005","lower":"021DC1-0039","count":2,"preSum":2},{"ndv":2,"upper":"0220909HI0007","lower":"0220909HI0006","count":2,"preSum":4},{"ndv":2,"upper":"0220913HB0007","lower":"0220912HB000S","count":2,"preSum":6},{"ndv":2,"upper":"0220926HG0004","lower":"0220925HH0015","count":2,"preSum":8},{"ndv":2,"upper":"0220927HY0014","lower":"0220926HQ0004","count":2,"preSum":10},{"ndv":2,"upper":"0220929H20002","lower":"0220927HY0015","count":2,"preSum":12},{"ndv":2,"upper":"0221004HA0002","lower":"0220930HZ0014","count":2,"preSum":14},{"ndv":2,"upper":"0221004HS0002","lower":"0221004HD0010","count":2,"preSum":16},{"ndv":2,"upper":"0221005HA0015","lower":"0221004HZ0010","count":2,"preSum":18},{"ndv":2,"upper":"0221017L30003","lower":"0221005HZ0004","count":2,"preSum":20},{"ndv":2,"upper":"0221022HB0011","lower":"0221018S30002","count":2,"preSum":22},{"ndv":2,"upper":"0221025HI0008","lower":"0221023HS0003","count":2,"preSum":24},{"ndv":2,"upper":"0221102HY0004","lower":"0221031HA0012","count":2,"preSum":26},{"ndv":2,"upper":"0221110L30002","lower":"0221109HB0003","count":2,"preSum":28},{"ndv":2,"upper":"0221110L30004","lower":"0221110L30003","count":2,"preSum":30},{"ndv":2,"upper":"0221111L30002","lower":"0221110L30006","count":2,"preSum":32},{"ndv":2,"upper":"0221119S70011","lower":"0221116HA0008","count":2,"preSum":34},{"ndv":2,"upper":"0221120T30003","lower":"0221120T10014","count":2,"preSum":36},{"ndv":2,"upper":"0221120T30008","lower":"0221120T30004","count":2,"preSum":38},{"ndv":2,"upper":"0221120T30014","lower":"0221120T30013","count":2,"preSum":40},{"ndv":2,"upper":"0221120T30022","lower":"0221120T30021","count":2,"preSum":42},{"ndv":2,"upper":"0221120T30029","lower":"0221120T30023","count":2,"preSum":44},{"ndv":2,"upper":"0221123S70021","lower":"0221122S70009","count":2,"preSum":46},{"ndv":2,"upper":"0221126T50012","lower":"0221123S70024","count":2,"preSum":48},{"ndv":2,"upper":"0221129HG0001","lower":"0221126T50040","count":2,"preSum":50},{"ndv":2,"upper":"0221203T50019","lower":"0221203T50014","count":2,"preSum":52},{"ndv":2,"upper":"0221203T50025","lower":"0221203T50024","count":2,"preSum":54},{"ndv":2,"upper":"0221204T50026","lower":"0221204T50023","count":2,"preSum":56},{"ndv":2,"upper":"0221224T30003","lower":"0221213HX0003","count":2,"preSum":58},{"ndv":2,"upper":"0221230HT0003","lower":"0221225HS0001","count":2,"preSum":60},{"ndv":2,"upper":"0221231HT0003","lower":"0221230HV0007","count":2,"preSum":62},{"ndv":2,"upper":"0230105HB0013","lower":"0221231HT0004","count":2,"preSum":64},{"ndv":2,"upper":"0230105T20008","lower":"0230105T20002","count":2,"preSum":66},{"ndv":2,"upper":"0230221T30015","lower":"0230221T30014","count":2,"preSum":68},{"ndv":2,"upper":"0230301HY0014","lower":"0230301HQ0002","count":2,"preSum":70},{"ndv":2,"upper":"0230306T50004","lower":"0230303HS0010","count":2,"preSum":72},{"ndv":2,"upper":"0230404HA0003","lower":"0230402HD0001","count":2,"preSum":74},{"ndv":2,"upper":"0230408HA0003","lower":"0230407L20003","count":2,"preSum":76},{"ndv":2,"upper":"0230409HC0021","lower":"0230409HB0007","count":2,"preSum":78},{"ndv":2,"upper":"0230411HY0008","lower":"0230410HI0005","count":2,"preSum":80},{"ndv":2,"upper":"0230412HC0012","lower":"0230412HC0002","count":2,"preSum":82},{"ndv":2,"upper":"0230414HS0006","lower":"0230412HC0014","count":2,"preSum":84},{"ndv":2,"upper":"0230414HS0011","lower":"0230414HS0009","count":2,"preSum":86},{"ndv":2,"upper":"0230427L30003","lower":"0230415HC0004","count":2,"preSum":88},{"ndv":2,"upper":"0230515HX0002","lower":"0230515HX0001","count":2,"preSum":90},{"ndv":2,"upper":"0230515HX0007","lower":"0230515HX0006","count":2,"preSum":92},{"ndv":2,"upper":"11994","lower":"119164","count":2,"preSum":94},{"ndv":2,"upper":"123435","lower":"12199","count":2,"preSum":96},{"ndv":2,"upper":"12623","lower":"12348","count":2,"preSum":98},{"ndv":2,"upper":"15547","lower":"14056","count":2,"preSum":100},{"ndv":2,"upper":"30381","lower":"16233","count":2,"preSum":102},{"ndv":2,"upper":"9409","lower":"310992","count":2,"preSum":104}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[13,7,3,3],"valueArr":["1","112976","30864","486"],"type":"String","sampleRate":1.0}',93378,0.006721839),('jala_wms_prod','task_detail','expirationdate',2919,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":234,"upper":"1852641908430471168","lower":"-1","count":1305,"preSum":0},{"ndv":85,"upper":"1852925582430437376","lower":"1852644107453726720","count":1309,"preSum":1305},{"ndv":40,"upper":"1853028936523448320","lower":"1852927781453692928","count":1215,"preSum":2614},{"ndv":40,"upper":"1853130091593203712","lower":"1853031135546703872","count":1221,"preSum":3829},{"ndv":16,"upper":"1853176271081570304","lower":"1853132290616459264","count":1536,"preSum":5050},{"ndv":16,"upper":"1853211455453659136","lower":"1853178470104825856","count":1205,"preSum":6586},{"ndv":16,"upper":"1853248838849003520","lower":"1853213654476914688","count":1407,"preSum":7791},{"ndv":10,"upper":"1853270829081559040","lower":"1853251037872259072","count":1437,"preSum":9198},{"ndv":5,"upper":"1853281824197836800","lower":"1853273028104814592","count":1191,"preSum":10635},{"ndv":10,"upper":"1853310411500158976","lower":"1853284023221092352","count":1349,"preSum":11826},{"ndv":15,"upper":"1853345595872247808","lower":"1853312610523414528","count":1267,"preSum":13175},{"ndv":17,"upper":"1853457746058280960","lower":"1853347794895503360","count":1354,"preSum":14442},{"ndv":24,"upper":"1853528114802458624","lower":"1853459945081536512","count":1264,"preSum":15796},{"ndv":20,"upper":"1853574294290825216","lower":"1853530313825714176","count":1383,"preSum":17060},{"ndv":18,"upper":"1853624871825702912","lower":"1853585289407102976","count":1241,"preSum":18443},{"ndv":6,"upper":"1853638065965236224","lower":"1853627070848958464","count":1409,"preSum":19684},{"ndv":9,"upper":"1853664454244302848","lower":"1853640264988491776","count":1348,"preSum":21093},{"ndv":10,"upper":"1853688643500113920","lower":"1853666653267558400","count":1484,"preSum":22441},{"ndv":11,"upper":"1853715031779180544","lower":"1853690842523369472","count":1271,"preSum":23925},{"ndv":5,"upper":"1853734822988480512","lower":"1853717230802436096","count":1234,"preSum":25196},{"ndv":4,"upper":"1853743619081502720","lower":"1853737022011736064","count":1234,"preSum":26430},{"ndv":6,"upper":"1853759012244291584","lower":"1853745818104758272","count":1321,"preSum":27664},{"ndv":12,"upper":"1853785400523358208","lower":"1853761211267547136","count":1251,"preSum":28985},{"ndv":37,"upper":"1853877759500091392","lower":"1853787599546613760","count":1199,"preSum":30236},{"ndv":53,"upper":"1854022895034957824","lower":"1853879958523346944","count":1238,"preSum":31435},{"ndv":25,"upper":"1854086666709368832","lower":"1854027293081468928","count":1247,"preSum":32673},{"ndv":11,"upper":"1854110855965179904","lower":"1854088865732624384","count":1239,"preSum":33920},{"ndv":6,"upper":"1854124050104713216","lower":"1854113054988435456","count":1434,"preSum":35159},{"ndv":8,"upper":"1854143841314013184","lower":"1854126249127968768","count":1425,"preSum":36593},{"ndv":6,"upper":"1854159234476802048","lower":"1854148239360524288","count":1255,"preSum":38018},{"ndv":5,"upper":"1854170229593079808","lower":"1854161433500057600","count":1428,"preSum":39273},{"ndv":8,"upper":"1854190020802379776","lower":"1854174627639590912","count":1385,"preSum":40701},{"ndv":10,"upper":"1854212011034935296","lower":"1854192219825635328","count":1304,"preSum":42086},{"ndv":8,"upper":"1854234001267490816","lower":"1854218608104701952","count":1230,"preSum":43390},{"ndv":6,"upper":"1854247195407024128","lower":"1854236200290746368","count":1195,"preSum":44620},{"ndv":8,"upper":"1854264787593068544","lower":"1854249394430279680","count":1230,"preSum":45815},{"ndv":6,"upper":"1854277981732601856","lower":"1854266986616324096","count":1288,"preSum":47045},{"ndv":11,"upper":"1854374738755846144","lower":"1854280180755857408","count":1195,"preSum":48333},{"ndv":12,"upper":"1854423117267468288","lower":"1854376937779101696","count":1320,"preSum":49528},{"ndv":10,"upper":"1854453903593046016","lower":"1854425316290723840","count":1271,"preSum":50848},{"ndv":11,"upper":"1854484689918623744","lower":"1854456102616301568","count":1314,"preSum":52119},{"ndv":5,"upper":"1854504481127923712","lower":"1854486888941879296","count":1211,"preSum":53433},{"ndv":4,"upper":"1854513277220945920","lower":"1854506680151179264","count":1238,"preSum":54644},{"ndv":4,"upper":"1854522073313968128","lower":"1854515476244201472","count":1461,"preSum":55882},{"ndv":4,"upper":"1854530869406990336","lower":"1854524272337223680","count":1323,"preSum":57343},{"ndv":3,"upper":"1854537466476756992","lower":"1854533068430245888","count":1236,"preSum":58666},{"ndv":5,"upper":"1854548461593034752","lower":"1854539665500012544","count":1548,"preSum":59902},{"ndv":7,"upper":"1854563854755823616","lower":"1854550660616290304","count":1499,"preSum":61450},{"ndv":5,"upper":"1854581446941868032","lower":"1854566053779079168","count":1370,"preSum":62949},{"ndv":3,"upper":"1854588044011634688","lower":"1854583645965123584","count":1291,"preSum":64319},{"ndv":3,"upper":"1854594641081401344","lower":"1854590243034890240","count":1237,"preSum":65610},{"ndv":3,"upper":"1854603437174423552","lower":"1854596840104656896","count":1200,"preSum":66847},{"ndv":3,"upper":"1854610034244190208","lower":"1854605636197679104","count":1216,"preSum":68047},{"ndv":5,"upper":"1854629825453490176","lower":"1854614432290701312","count":1589,"preSum":69263},{"ndv":3,"upper":"1854645218616279040","lower":"1854640820569767936","count":1440,"preSum":70852},{"ndv":3,"upper":"1854656213732556800","lower":"1854651815686045696","count":1200,"preSum":72292},{"ndv":5,"upper":"1854669407872090112","lower":"1854658412755812352","count":1311,"preSum":73492},{"ndv":18,"upper":"1854717786383712256","lower":"1854671606895345664","count":1242,"preSum":74803},{"ndv":12,"upper":"1876129675823022080","lower":"1854719985406967808","count":124,"preSum":76045}],"maxBucketSize":64,"type":"Date","sampleRate":1.0}','{"countArr":[851,682,728,614,579,606,630,742,620,577,654,594,606,8858],"valueArr":[1853303814430392320,1853673250337325056,1853730424941969408,1853748017128013824,1854132846197735424,1854572650848845824,1854599039127912448,1854612233267445760,1854621029360467968,1854623228383723520,1854625427406979072,1854647417639534592,1854649616662790144,9147934544073064448],"type":"Date","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','finishrebatch',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93510],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','frominventoryid',328683,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1117,"upper":221864,"lower":11955,"count":1435,"preSum":0},{"ndv":1300,"upper":421582,"lower":221866,"count":1435,"preSum":1435},{"ndv":1407,"upper":601280,"lower":421583,"count":1436,"preSum":2870},{"ndv":1352,"upper":786634,"lower":601321,"count":1435,"preSum":4306},{"ndv":1378,"upper":1090727,"lower":786635,"count":1437,"preSum":5741},{"ndv":1025,"upper":1190366,"lower":1091481,"count":1440,"preSum":7178},{"ndv":493,"upper":1237474,"lower":1190367,"count":1436,"preSum":8618},{"ndv":609,"upper":1309737,"lower":1237475,"count":1440,"preSum":10054},{"ndv":902,"upper":1395567,"lower":1309764,"count":1438,"preSum":11494},{"ndv":847,"upper":1473147,"lower":1397190,"count":1435,"preSum":12932},{"ndv":506,"upper":1498452,"lower":1473185,"count":1446,"preSum":14367},{"ndv":566,"upper":1543832,"lower":1498462,"count":1438,"preSum":15813},{"ndv":643,"upper":1589774,"lower":1543840,"count":1477,"preSum":17251},{"ndv":285,"upper":1593419,"lower":1589776,"count":1444,"preSum":18728},{"ndv":329,"upper":1595815,"lower":1593421,"count":1443,"preSum":20172},{"ndv":355,"upper":1611871,"lower":1595817,"count":1439,"preSum":21615},{"ndv":270,"upper":1616472,"lower":1611873,"count":1459,"preSum":23054},{"ndv":363,"upper":1635796,"lower":1616493,"count":1436,"preSum":24513},{"ndv":327,"upper":1661491,"lower":1636030,"count":1435,"preSum":25949},{"ndv":353,"upper":1680787,"lower":1661493,"count":1454,"preSum":27384},{"ndv":330,"upper":1702600,"lower":1681058,"count":1463,"preSum":28838},{"ndv":316,"upper":1722548,"lower":1702651,"count":1437,"preSum":30301},{"ndv":332,"upper":1805056,"lower":1722589,"count":1438,"preSum":31738},{"ndv":227,"upper":1819242,"lower":1805102,"count":1443,"preSum":33176},{"ndv":135,"upper":1824720,"lower":1819247,"count":1437,"preSum":34619},{"ndv":159,"upper":1834728,"lower":1824723,"count":1449,"preSum":36056},{"ndv":302,"upper":1905141,"lower":1834855,"count":1445,"preSum":37505},{"ndv":232,"upper":1928834,"lower":1905194,"count":1441,"preSum":38950},{"ndv":389,"upper":1949547,"lower":1928837,"count":1459,"preSum":40391},{"ndv":209,"upper":1969726,"lower":1949697,"count":1438,"preSum":41850},{"ndv":314,"upper":1988891,"lower":1969773,"count":1435,"preSum":43288},{"ndv":344,"upper":2008130,"lower":1988918,"count":1435,"preSum":44723},{"ndv":236,"upper":2026408,"lower":2008137,"count":1440,"preSum":46158},{"ndv":248,"upper":2040752,"lower":2026448,"count":1435,"preSum":47598},{"ndv":390,"upper":2067298,"lower":2040787,"count":1494,"preSum":49033},{"ndv":313,"upper":2078001,"lower":2067355,"count":1444,"preSum":50527},{"ndv":423,"upper":2099973,"lower":2078005,"count":1440,"preSum":51971},{"ndv":348,"upper":2118972,"lower":2099980,"count":1440,"preSum":53411},{"ndv":307,"upper":2136091,"lower":2119045,"count":1436,"preSum":54851},{"ndv":396,"upper":2148808,"lower":2136092,"count":1442,"preSum":56287},{"ndv":367,"upper":2177392,"lower":2148858,"count":1446,"preSum":57729},{"ndv":323,"upper":2194376,"lower":2177545,"count":1461,"preSum":59175},{"ndv":322,"upper":2216809,"lower":2194435,"count":1439,"preSum":60636},{"ndv":376,"upper":2239848,"lower":2216885,"count":1453,"preSum":62075},{"ndv":211,"upper":2250868,"lower":2240015,"count":1436,"preSum":63528},{"ndv":332,"upper":2268403,"lower":2251014,"count":1436,"preSum":64964},{"ndv":234,"upper":2280537,"lower":2268409,"count":1437,"preSum":66400},{"ndv":198,"upper":2291425,"lower":2280671,"count":1440,"preSum":67837},{"ndv":207,"upper":2294646,"lower":2291714,"count":1437,"preSum":69277},{"ndv":153,"upper":2295812,"lower":2294647,"count":1441,"preSum":70714},{"ndv":178,"upper":2302714,"lower":2295863,"count":1435,"preSum":72155},{"ndv":207,"upper":2309815,"lower":2302905,"count":1438,"preSum":73590},{"ndv":253,"upper":2326676,"lower":2309940,"count":1436,"preSum":75028},{"ndv":265,"upper":2349024,"lower":2326677,"count":1451,"preSum":76464},{"ndv":301,"upper":2378802,"lower":2349027,"count":1445,"preSum":77915},{"ndv":360,"upper":2404034,"lower":2378816,"count":1435,"preSum":79360},{"ndv":237,"upper":2428023,"lower":2404258,"count":1438,"preSum":80795},{"ndv":362,"upper":2458936,"lower":2428083,"count":1436,"preSum":82233},{"ndv":285,"upper":2475779,"lower":2458987,"count":1435,"preSum":83669},{"ndv":271,"upper":2498215,"lower":2475781,"count":1441,"preSum":85104},{"ndv":306,"upper":2522335,"lower":2498234,"count":1484,"preSum":86545},{"ndv":266,"upper":2541583,"lower":2522389,"count":1436,"preSum":88029},{"ndv":374,"upper":2565594,"lower":2541680,"count":1442,"preSum":89465},{"ndv":130,"upper":2575805,"lower":2565600,"count":911,"preSum":90907}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[111,113,149,87,93,134,99,278,95,102,106,85,133,107],"valueArr":[1594591,1595113,1595171,1683202,1704220,1822636,2029201,2131041,2285304,2301235,2315191,2322060,2369110,2461754],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','fromloc',37217,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":132,"upper":"021DCQQ-SS03-03-40","lower":"021DCQQ-M03-13","count":1155,"preSum":0},{"ndv":264,"upper":"022DCX-1B-04A05","lower":"021DCQQ-SS03-03-41","count":1156,"preSum":1155},{"ndv":219,"upper":"022DCX-1D-02A39","lower":"022DCX-1B-04A06","count":1180,"preSum":2311},{"ndv":69,"upper":"022DCX-1D-04A32","lower":"022DCX-1D-02A40","count":1177,"preSum":3491},{"ndv":96,"upper":"022DCX-1D-07A16","lower":"022DCX-1D-04A34","count":1167,"preSum":4668},{"ndv":98,"upper":"022DCX-1D-10A32","lower":"022DCX-1D-07A17","count":1154,"preSum":5835},{"ndv":70,"upper":"022DCX-1E-10B34","lower":"022DCX-1D-10A33","count":1155,"preSum":6989},{"ndv":513,"upper":"1B-11A023","lower":"022DCX-1E-10B35","count":1155,"preSum":8144},{"ndv":146,"upper":"1P-03A027","lower":"1B-11A024","count":1156,"preSum":9299},{"ndv":13,"upper":"1P-05A007","lower":"1P-03A028","count":1191,"preSum":10455},{"ndv":7,"upper":"1P-05A014","lower":"1P-05A008","count":1256,"preSum":11646},{"ndv":9,"upper":"1P-05A025","lower":"1P-05A015","count":1223,"preSum":12902},{"ndv":18,"upper":"1P-05A043","lower":"1P-05A026","count":1363,"preSum":14125},{"ndv":6,"upper":"1P-06A006","lower":"1P-05A044","count":1349,"preSum":15488},{"ndv":8,"upper":"1P-06A017","lower":"1P-06A007","count":1189,"preSum":16837},{"ndv":4,"upper":"1P-06A021","lower":"1P-06A018","count":1211,"preSum":18026},{"ndv":4,"upper":"1P-06A027","lower":"1P-06A022","count":1421,"preSum":19237},{"ndv":4,"upper":"1P-06A032","lower":"1P-06A028","count":1258,"preSum":20658},{"ndv":8,"upper":"1P-06A040","lower":"1P-06A033","count":1458,"preSum":21916},{"ndv":8,"upper":"1P-07A005","lower":"1P-06A041","count":1270,"preSum":23374},{"ndv":17,"upper":"1P-07A024","lower":"1P-07A006","count":1568,"preSum":24644},{"ndv":32,"upper":"1P-08A012","lower":"1P-07A025","count":1593,"preSum":26212},{"ndv":63,"upper":"1Q-02B037","lower":"1P-08A013","count":1158,"preSum":27805},{"ndv":143,"upper":"1Q-05A057","lower":"1Q-02B052","count":1193,"preSum":28963},{"ndv":61,"upper":"1Q-06A008","lower":"1Q-05A058","count":1180,"preSum":30156},{"ndv":51,"upper":"1Q-06D011","lower":"1Q-06A010","count":1155,"preSum":31336},{"ndv":41,"upper":"1Q-07A091","lower":"1Q-06D013","count":1165,"preSum":32491},{"ndv":75,"upper":"1Q-08B016","lower":"1Q-07A092","count":1155,"preSum":33656},{"ndv":215,"upper":"1Q-09D095","lower":"1Q-08B017","count":1156,"preSum":34811},{"ndv":119,"upper":"1Q-10C062","lower":"1Q-09D096","count":1156,"preSum":35967},{"ndv":88,"upper":"1Q-11A005","lower":"1Q-10C065","count":1187,"preSum":37123},{"ndv":19,"upper":"1Q-11A072","lower":"1Q-11A006","count":1302,"preSum":38310},{"ndv":45,"upper":"1Q-12A023","lower":"1Q-11A073","count":1211,"preSum":39612},{"ndv":18,"upper":"1Q-12A083","lower":"1Q-12A024","count":1212,"preSum":40823},{"ndv":8,"upper":"1Q-12A095","lower":"1Q-12A084","count":1165,"preSum":42035},{"ndv":37,"upper":"1Q-13A024","lower":"1Q-12A096","count":1332,"preSum":43200},{"ndv":22,"upper":"1Q-13A095","lower":"1Q-13A025","count":1311,"preSum":44532},{"ndv":250,"upper":"2C-AA06-0000","lower":"1Q-13A096","count":1155,"preSum":45843},{"ndv":75,"upper":"2C-AC11-0201","lower":"2C-AA07-0000","count":1154,"preSum":46998},{"ndv":213,"upper":"2C-AH10-0000","lower":"2C-AC11-0203","count":1261,"preSum":48152},{"ndv":221,"upper":"763DCA-2C-01A033","lower":"2C-AJ01-0000","count":1164,"preSum":49413},{"ndv":362,"upper":"763DCA-2I-01A11","lower":"763DCA-2C-01A035","count":1170,"preSum":50577},{"ndv":37,"upper":"763DCA-2I-02A11","lower":"763DCA-2I-01A12","count":1177,"preSum":51747},{"ndv":31,"upper":"763DCA-2I-03A06","lower":"763DCA-2I-02A12","count":1155,"preSum":52924},{"ndv":66,"upper":"763DCA-2I-05A08","lower":"763DCA-2I-03A08","count":1166,"preSum":54079},{"ndv":70,"upper":"763DCA-2I-07A15","lower":"763DCA-2I-05A10","count":1166,"preSum":55245},{"ndv":368,"upper":"B-01-096","lower":"763DCA-2I-07A16","count":1154,"preSum":56411},{"ndv":379,"upper":"BLS-05-A39","lower":"B-01-101","count":1164,"preSum":57565},{"ndv":105,"upper":"BLS-13-A03","lower":"BLS-06-A01","count":1167,"preSum":58729},{"ndv":167,"upper":"BT1-04-A33-01","lower":"BLS-13-A07","count":1154,"preSum":59896},{"ndv":432,"upper":"CH-0316A5","lower":"BT1-04-A33-02","count":1160,"preSum":61050},{"ndv":240,"upper":"CH-0517A4","lower":"CH-0316C2","count":1155,"preSum":62210},{"ndv":136,"upper":"CT-06-A06","lower":"CH-0517A5","count":1178,"preSum":63365},{"ndv":29,"upper":"CT-07-A18","lower":"CT-06-A08","count":1171,"preSum":64543},{"ndv":46,"upper":"CT-08-B04","lower":"CT-07-A19","count":1177,"preSum":65714},{"ndv":51,"upper":"CT-09-A30","lower":"CT-08-B05","count":1180,"preSum":66891},{"ndv":37,"upper":"CT-10-A22","lower":"CT-09-A31","count":1174,"preSum":68071},{"ndv":35,"upper":"CT-11-A31","lower":"CT-10-A23","count":1246,"preSum":69245},{"ndv":29,"upper":"CT-11-A64","lower":"CT-11-A33","count":1167,"preSum":70491},{"ndv":497,"upper":"QC001","lower":"CZ01-1","count":1160,"preSum":71658},{"ndv":163,"upper":"ZWYJH","lower":"QF0117","count":999,"preSum":72818}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[723,931,540,812,706,811,603,1112,765,837,859,7858,935,2201],"valueArr":["1P-05A022","1P-06A003","1P-06A012","1P-06A014","1P-06A016","1P-06A024","1P-06A025","1P-06A043","1P-07A013","1Q-07A087","763DCA-2C-YB01","RECV-01","TH01","YSDD-01A001"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','fromlpn',178230,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":120,"upper":"0221010HV0001","lower":"","count":139,"preSum":0},{"ndv":109,"upper":"0221115S70027","lower":"0221010S60001","count":139,"preSum":139},{"ndv":111,"upper":"0221216550018","lower":"0221115T30030","count":139,"preSum":278},{"ndv":123,"upper":"0230214HZ0001","lower":"0221216550022","count":139,"preSum":417},{"ndv":120,"upper":"0230331L40061","lower":"0230214HZ0007","count":139,"preSum":556},{"ndv":118,"upper":"0230515HX0007","lower":"0230331L40063","count":141,"preSum":695},{"ndv":133,"upper":"11979","lower":"0230516HC0003","count":139,"preSum":836},{"ndv":123,"upper":"16484","lower":"11988","count":139,"preSum":975},{"ndv":135,"upper":"573DC-39182","lower":"2022112302","count":139,"preSum":1114},{"ndv":139,"upper":"573DC-73571","lower":"573DC-39183","count":139,"preSum":1253},{"ndv":139,"upper":"763DC-14470","lower":"573DC-73572","count":139,"preSum":1392},{"ndv":135,"upper":"SH03-109068","lower":"763DC-14471","count":139,"preSum":1531},{"ndv":139,"upper":"SH03-120176","lower":"SH03-109069","count":139,"preSum":1670},{"ndv":139,"upper":"SH03-127803","lower":"SH03-120177","count":139,"preSum":1809},{"ndv":139,"upper":"SH03-147825","lower":"SH03-127804","count":139,"preSum":1948},{"ndv":139,"upper":"SH03-156618","lower":"SH03-147826","count":139,"preSum":2087},{"ndv":139,"upper":"SH03-177215","lower":"SH03-156619","count":139,"preSum":2226},{"ndv":139,"upper":"SH03-189960","lower":"SH03-177216","count":139,"preSum":2365},{"ndv":139,"upper":"SH03-204381","lower":"SH03-189961","count":139,"preSum":2504},{"ndv":139,"upper":"SH03-222791","lower":"SH03-204382","count":139,"preSum":2643},{"ndv":139,"upper":"SH03-23761","lower":"SH03-222792","count":139,"preSum":2782},{"ndv":139,"upper":"SH03-24622","lower":"SH03-23762","count":139,"preSum":2921},{"ndv":139,"upper":"SH03-2560","lower":"SH03-24623","count":139,"preSum":3060},{"ndv":139,"upper":"SH03-280070","lower":"SH03-2561","count":139,"preSum":3199},{"ndv":139,"upper":"SH03-295998","lower":"SH03-280071","count":139,"preSum":3338},{"ndv":139,"upper":"SH03-312066","lower":"SH03-295999","count":139,"preSum":3477},{"ndv":139,"upper":"SH03-318528","lower":"SH03-312067","count":139,"preSum":3616},{"ndv":139,"upper":"SH03-325568","lower":"SH03-318529","count":139,"preSum":3755},{"ndv":139,"upper":"SH03-339081","lower":"SH03-325569","count":139,"preSum":3894},{"ndv":139,"upper":"SH03-358903","lower":"SH03-339082","count":139,"preSum":4033},{"ndv":139,"upper":"SH03-36735","lower":"SH03-358904","count":139,"preSum":4172},{"ndv":139,"upper":"SH03-381489","lower":"SH03-36736","count":139,"preSum":4311},{"ndv":139,"upper":"SH03-398882","lower":"SH03-381490","count":139,"preSum":4450},{"ndv":139,"upper":"SH03-414141","lower":"SH03-398883","count":139,"preSum":4589},{"ndv":139,"upper":"SH03-423552","lower":"SH03-414142","count":139,"preSum":4728},{"ndv":139,"upper":"SH03-425863","lower":"SH03-423553","count":139,"preSum":4867},{"ndv":139,"upper":"SH03-44224","lower":"SH03-425864","count":139,"preSum":5006},{"ndv":139,"upper":"SH03-466361","lower":"SH03-44225","count":139,"preSum":5145},{"ndv":139,"upper":"SH03-487379","lower":"SH03-466362","count":139,"preSum":5284},{"ndv":139,"upper":"SH03-494949","lower":"SH03-487380","count":139,"preSum":5423},{"ndv":139,"upper":"SH03-513494","lower":"SH03-494950","count":139,"preSum":5562},{"ndv":139,"upper":"SH03-535007","lower":"SH03-513495","count":139,"preSum":5701},{"ndv":139,"upper":"SH03-543200","lower":"SH03-535008","count":139,"preSum":5840},{"ndv":139,"upper":"SH03-557177","lower":"SH03-543201","count":139,"preSum":5979},{"ndv":139,"upper":"SH03-57451","lower":"SH03-557178","count":139,"preSum":6118},{"ndv":139,"upper":"SH03-583858","lower":"SH03-57452","count":139,"preSum":6257},{"ndv":139,"upper":"SH03-609527","lower":"SH03-583859","count":139,"preSum":6396},{"ndv":139,"upper":"SH03-623434","lower":"SH03-609528","count":139,"preSum":6535},{"ndv":139,"upper":"SH03-638886","lower":"SH03-623435","count":139,"preSum":6674},{"ndv":139,"upper":"SH03-651571","lower":"SH03-638887","count":139,"preSum":6813},{"ndv":139,"upper":"SH03-671536","lower":"SH03-651572","count":139,"preSum":6952},{"ndv":139,"upper":"SH03-698993","lower":"SH03-671537","count":139,"preSum":7091},{"ndv":139,"upper":"SH03-740154","lower":"SH03-701420","count":139,"preSum":7230},{"ndv":139,"upper":"SH03-761658","lower":"SH03-740155","count":139,"preSum":7369},{"ndv":139,"upper":"SH03-782985","lower":"SH03-761659","count":139,"preSum":7508},{"ndv":139,"upper":"SH03-795617","lower":"SH03-782987","count":139,"preSum":7647},{"ndv":139,"upper":"SH03-804933","lower":"SH03-795618","count":139,"preSum":7786},{"ndv":139,"upper":"SH03-819936","lower":"SH03-804934","count":139,"preSum":7925},{"ndv":139,"upper":"SH03-834338","lower":"SH03-819937","count":139,"preSum":8064},{"ndv":139,"upper":"SH03-865782","lower":"SH03-834339","count":139,"preSum":8203},{"ndv":139,"upper":"SH03-882068","lower":"SH03-865783","count":139,"preSum":8342},{"ndv":139,"upper":"SH03-900896","lower":"SH03-882069","count":139,"preSum":8481},{"ndv":139,"upper":"SH03-918333","lower":"SH03-900897","count":139,"preSum":8620},{"ndv":106,"upper":",","lower":"SH03-918334","count":110,"preSum":8759}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[6,6,874,7,7,7,7,15],"valueArr":["0221117HQ0001","0230202Q00008","1","1230513HC0002","1290102Q00015","16360","16479","2"],"type":"String","sampleRate":1.0}',83712,0.006721839),('jala_wms_prod','task_detail','fromqty',17,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":144,"lower":144,"count":1,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93509],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','fromzone',81,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"022DCX-1A","lower":"022DCX-1A","count":448,"preSum":0},{"ndv":1,"upper":"022DCX-1B","lower":"022DCX-1B","count":313,"preSum":448},{"ndv":2,"upper":"022DCX-1E","lower":"022DCX-1C","count":419,"preSum":761},{"ndv":2,"upper":"027DCN-BT1","lower":"027DCN-BH","count":566,"preSum":1180},{"ndv":2,"upper":"1A","lower":"027DCN-LK","count":510,"preSum":1746},{"ndv":1,"upper":"1B","lower":"1B","count":588,"preSum":2256},{"ndv":2,"upper":"763DCA-YSDD","lower":"1O","count":182,"preSum":2844},{"ndv":1,"upper":"D001","lower":"D001","count":633,"preSum":3026},{"ndv":2,"upper":"D001ZCJ","lower":"D001CZ","count":138,"preSum":3659},{"ndv":6,"upper":"D001商品零拣区","lower":"D001中外运拣货","count":199,"preSum":3797},{"ndv":2,"upper":"D001存储区","lower":"D001委外直发1","count":181,"preSum":3996},{"ndv":2,"upper":"D002拣货区域","lower":"D002存储区域","count":132,"preSum":4177},{"ndv":1,"upper":"D002拣货区域-1","lower":"D002拣货区域-1","count":152,"preSum":4309},{"ndv":4,"upper":"D011区域-1","lower":"D002拣货区域-2","count":208,"preSum":4461},{"ndv":1,"upper":"D011区域-2","lower":"D011区域-2","count":274,"preSum":4669},{"ndv":1,"upper":"D011存储区域","lower":"D011存储区域","count":124,"preSum":4943},{"ndv":5,"upper":"W007","lower":"LOST","count":173,"preSum":5067},{"ndv":2,"upper":"W013","lower":"W009","count":555,"preSum":5240},{"ndv":1,"upper":"W028","lower":"W028","count":246,"preSum":5795}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[5390,787,1902,7316,2782,826,26101,18787,711,10045,935,2201,854,974],"valueArr":["022DCX-1D","027DCN-BT2","027DCN-CH","027DCN-CT","027DCN-LSCC","028DCI-JAB2B","1P","1Q","763DCA-JLB2B","763DCA-JLB2C","TH01","YSDD","货主1000区域","货主1001区域"],"type":"String","sampleRate":1.0}',7858,0.006721839),('jala_wms_prod','task_detail','groupindex',1785,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":10,"lower":10,"count":2371,"preSum":0},{"ndv":1,"upper":15,"lower":15,"count":2351,"preSum":2371},{"ndv":1,"upper":16,"lower":16,"count":2271,"preSum":4722},{"ndv":1,"upper":17,"lower":17,"count":2075,"preSum":6993},{"ndv":1,"upper":18,"lower":18,"count":2172,"preSum":9068},{"ndv":1,"upper":19,"lower":19,"count":2068,"preSum":11240},{"ndv":1,"upper":20,"lower":20,"count":1960,"preSum":13308},{"ndv":1,"upper":21,"lower":21,"count":664,"preSum":15268},{"ndv":1,"upper":22,"lower":22,"count":651,"preSum":15932},{"ndv":2,"upper":24,"lower":23,"count":1087,"preSum":16583},{"ndv":2,"upper":26,"lower":25,"count":851,"preSum":17670},{"ndv":2,"upper":28,"lower":27,"count":782,"preSum":18521},{"ndv":2,"upper":30,"lower":29,"count":841,"preSum":19303},{"ndv":2,"upper":32,"lower":31,"count":845,"preSum":20144},{"ndv":2,"upper":34,"lower":33,"count":949,"preSum":20989},{"ndv":2,"upper":36,"lower":35,"count":924,"preSum":21938},{"ndv":2,"upper":38,"lower":37,"count":872,"preSum":22862},{"ndv":2,"upper":40,"lower":39,"count":862,"preSum":23734},{"ndv":2,"upper":42,"lower":41,"count":809,"preSum":24596},{"ndv":2,"upper":44,"lower":43,"count":707,"preSum":25405},{"ndv":3,"upper":47,"lower":45,"count":737,"preSum":26112},{"ndv":3,"upper":50,"lower":48,"count":770,"preSum":26849},{"ndv":3,"upper":53,"lower":51,"count":895,"preSum":27619},{"ndv":3,"upper":56,"lower":54,"count":947,"preSum":28514},{"ndv":3,"upper":59,"lower":57,"count":760,"preSum":29461},{"ndv":3,"upper":62,"lower":60,"count":762,"preSum":30221},{"ndv":3,"upper":65,"lower":63,"count":654,"preSum":30983},{"ndv":4,"upper":69,"lower":66,"count":874,"preSum":31637},{"ndv":3,"upper":72,"lower":70,"count":713,"preSum":32511},{"ndv":3,"upper":75,"lower":73,"count":700,"preSum":33224},{"ndv":4,"upper":79,"lower":76,"count":798,"preSum":33924},{"ndv":4,"upper":83,"lower":80,"count":728,"preSum":34722},{"ndv":4,"upper":87,"lower":84,"count":816,"preSum":35450},{"ndv":4,"upper":91,"lower":88,"count":847,"preSum":36266},{"ndv":4,"upper":95,"lower":92,"count":647,"preSum":37113},{"ndv":5,"upper":100,"lower":96,"count":748,"preSum":37760},{"ndv":17,"upper":117,"lower":101,"count":645,"preSum":38508},{"ndv":31,"upper":148,"lower":118,"count":648,"preSum":39153},{"ndv":44,"upper":192,"lower":149,"count":647,"preSum":39801},{"ndv":270,"upper":837,"lower":193,"count":644,"preSum":40448},{"ndv":16,"upper":940,"lower":838,"count":55,"preSum":41092}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[9173,10507,3273,3026,2920,2900,2915,2651,2642,2487,2593,2411,2454,2411],"valueArr":[0,1,2,3,4,5,6,7,8,9,11,12,13,14],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','groupnum',128,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":14,"lower":14,"count":409,"preSum":0},{"ndv":1,"upper":15,"lower":15,"count":340,"preSum":409},{"ndv":1,"upper":16,"lower":16,"count":381,"preSum":749},{"ndv":1,"upper":17,"lower":17,"count":347,"preSum":1130},{"ndv":1,"upper":18,"lower":18,"count":366,"preSum":1477},{"ndv":1,"upper":19,"lower":19,"count":443,"preSum":1843},{"ndv":1,"upper":20,"lower":20,"count":150,"preSum":2286},{"ndv":1,"upper":21,"lower":21,"count":258,"preSum":2436},{"ndv":1,"upper":22,"lower":22,"count":337,"preSum":2694},{"ndv":1,"upper":23,"lower":23,"count":197,"preSum":3031},{"ndv":2,"upper":25,"lower":24,"count":261,"preSum":3228},{"ndv":1,"upper":26,"lower":26,"count":145,"preSum":3489},{"ndv":1,"upper":27,"lower":27,"count":206,"preSum":3634},{"ndv":2,"upper":29,"lower":28,"count":451,"preSum":3840},{"ndv":1,"upper":30,"lower":30,"count":205,"preSum":4291},{"ndv":1,"upper":31,"lower":31,"count":194,"preSum":4496},{"ndv":1,"upper":32,"lower":32,"count":258,"preSum":4690},{"ndv":1,"upper":33,"lower":33,"count":333,"preSum":4948},{"ndv":1,"upper":34,"lower":34,"count":139,"preSum":5281},{"ndv":1,"upper":35,"lower":35,"count":188,"preSum":5420},{"ndv":2,"upper":37,"lower":36,"count":221,"preSum":5608},{"ndv":1,"upper":38,"lower":38,"count":191,"preSum":5829},{"ndv":2,"upper":40,"lower":39,"count":240,"preSum":6020},{"ndv":2,"upper":42,"lower":41,"count":170,"preSum":6260},{"ndv":2,"upper":44,"lower":43,"count":208,"preSum":6430},{"ndv":2,"upper":46,"lower":45,"count":187,"preSum":6638},{"ndv":2,"upper":48,"lower":47,"count":188,"preSum":6825},{"ndv":2,"upper":50,"lower":49,"count":186,"preSum":7013},{"ndv":3,"upper":53,"lower":51,"count":184,"preSum":7199},{"ndv":2,"upper":55,"lower":54,"count":140,"preSum":7383},{"ndv":3,"upper":58,"lower":56,"count":140,"preSum":7523},{"ndv":4,"upper":62,"lower":59,"count":169,"preSum":7663},{"ndv":3,"upper":66,"lower":63,"count":139,"preSum":7832},{"ndv":5,"upper":71,"lower":67,"count":151,"preSum":7971},{"ndv":6,"upper":77,"lower":72,"count":139,"preSum":8122},{"ndv":9,"upper":87,"lower":78,"count":142,"preSum":8261},{"ndv":10,"upper":112,"lower":88,"count":142,"preSum":8403},{"ndv":9,"upper":143,"lower":120,"count":106,"preSum":8545}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[9173,50777,7738,4754,2984,2897,1309,1232,915,641,753,627,516,543],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','id',7418372,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1462,"upper":299188,"lower":5707,"count":1462,"preSum":0},{"ndv":1462,"upper":497225,"lower":299189,"count":1462,"preSum":1462},{"ndv":1462,"upper":713445,"lower":497226,"count":1462,"preSum":2924},{"ndv":1462,"upper":924029,"lower":713446,"count":1462,"preSum":4386},{"ndv":1462,"upper":1261434,"lower":924030,"count":1462,"preSum":5848},{"ndv":1462,"upper":1520915,"lower":1261435,"count":1462,"preSum":7310},{"ndv":1462,"upper":1738883,"lower":1520916,"count":1462,"preSum":8772},{"ndv":1462,"upper":2006124,"lower":1743177,"count":1462,"preSum":10234},{"ndv":1462,"upper":2243639,"lower":2011847,"count":1462,"preSum":11696},{"ndv":1462,"upper":2465140,"lower":2243640,"count":1462,"preSum":13158},{"ndv":1462,"upper":2652118,"lower":2465141,"count":1462,"preSum":14620},{"ndv":1462,"upper":2902043,"lower":2652119,"count":1462,"preSum":16082},{"ndv":1462,"upper":3175209,"lower":2902044,"count":1462,"preSum":17544},{"ndv":1462,"upper":3437099,"lower":3175210,"count":1462,"preSum":19006},{"ndv":1462,"upper":3603721,"lower":3437100,"count":1462,"preSum":20468},{"ndv":1462,"upper":3940224,"lower":3603722,"count":1462,"preSum":21930},{"ndv":1462,"upper":4131156,"lower":3940225,"count":1462,"preSum":23392},{"ndv":1462,"upper":4471256,"lower":4131157,"count":1462,"preSum":24854},{"ndv":1462,"upper":4785509,"lower":4471257,"count":1462,"preSum":26316},{"ndv":1462,"upper":5026644,"lower":4785510,"count":1462,"preSum":27778},{"ndv":1462,"upper":5220034,"lower":5026645,"count":1462,"preSum":29240},{"ndv":1462,"upper":5707123,"lower":5220035,"count":1462,"preSum":30702},{"ndv":1462,"upper":5910882,"lower":5707124,"count":1462,"preSum":32164},{"ndv":1462,"upper":6146747,"lower":5910883,"count":1462,"preSum":33626},{"ndv":1462,"upper":6420432,"lower":6146748,"count":1462,"preSum":35088},{"ndv":1462,"upper":6670624,"lower":6420433,"count":1462,"preSum":36550},{"ndv":1462,"upper":6904234,"lower":6670625,"count":1462,"preSum":38012},{"ndv":1462,"upper":7118891,"lower":6904235,"count":1462,"preSum":39474},{"ndv":1462,"upper":7348999,"lower":7118892,"count":1462,"preSum":40936},{"ndv":1462,"upper":7564428,"lower":7349000,"count":1462,"preSum":42398},{"ndv":1462,"upper":7798032,"lower":7564429,"count":1462,"preSum":43860},{"ndv":1462,"upper":8052717,"lower":7798033,"count":1462,"preSum":45322},{"ndv":1462,"upper":8317216,"lower":8052718,"count":1462,"preSum":46784},{"ndv":1462,"upper":8528245,"lower":8317217,"count":1462,"preSum":48246},{"ndv":1462,"upper":8798076,"lower":8528246,"count":1462,"preSum":49708},{"ndv":1462,"upper":9021720,"lower":8798077,"count":1462,"preSum":51170},{"ndv":1462,"upper":9267614,"lower":9021721,"count":1462,"preSum":52632},{"ndv":1462,"upper":9487017,"lower":9267615,"count":1462,"preSum":54094},{"ndv":1462,"upper":9764272,"lower":9487018,"count":1462,"preSum":55556},{"ndv":1462,"upper":9981697,"lower":9764273,"count":1462,"preSum":57018},{"ndv":1462,"upper":10239591,"lower":9981698,"count":1462,"preSum":58480},{"ndv":1462,"upper":10508745,"lower":10239592,"count":1462,"preSum":59942},{"ndv":1462,"upper":10788580,"lower":10508746,"count":1462,"preSum":61404},{"ndv":1462,"upper":11046593,"lower":10788581,"count":1462,"preSum":62866},{"ndv":1462,"upper":11312478,"lower":11046594,"count":1462,"preSum":64328},{"ndv":1462,"upper":11507620,"lower":11312479,"count":1462,"preSum":65790},{"ndv":1462,"upper":11762435,"lower":11507621,"count":1462,"preSum":67252},{"ndv":1462,"upper":11983176,"lower":11762436,"count":1462,"preSum":68714},{"ndv":1462,"upper":12260070,"lower":11983177,"count":1462,"preSum":70176},{"ndv":1462,"upper":12501353,"lower":12260071,"count":1462,"preSum":71638},{"ndv":1462,"upper":12761240,"lower":12501354,"count":1462,"preSum":73100},{"ndv":1462,"upper":13031417,"lower":12761241,"count":1462,"preSum":74562},{"ndv":1462,"upper":13258386,"lower":13031418,"count":1462,"preSum":76024},{"ndv":1462,"upper":13474681,"lower":13258387,"count":1462,"preSum":77486},{"ndv":1462,"upper":13683641,"lower":13474682,"count":1462,"preSum":78948},{"ndv":1462,"upper":13840758,"lower":13683642,"count":1462,"preSum":80410},{"ndv":1462,"upper":14019084,"lower":13840759,"count":1462,"preSum":81872},{"ndv":1462,"upper":14212501,"lower":14019085,"count":1462,"preSum":83334},{"ndv":1462,"upper":14477424,"lower":14212502,"count":1462,"preSum":84796},{"ndv":1462,"upper":14704317,"lower":14477425,"count":1462,"preSum":86258},{"ndv":1462,"upper":15077147,"lower":14704318,"count":1462,"preSum":87720},{"ndv":1462,"upper":15336728,"lower":15077148,"count":1462,"preSum":89182},{"ndv":1462,"upper":15589315,"lower":15336729,"count":1462,"preSum":90644},{"ndv":1404,"upper":15831750,"lower":15589316,"count":1404,"preSum":92106}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,0,0.006721839),('jala_wms_prod','task_detail','internaltasktype',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[7858,253,84337,1062],"valueArr":["RECEIPT","REPLENISHMENT","SHIPMENT","TRANSFER"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','intransitlocked',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[84590,8920],"valueArr":[0,1],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','inventorysts',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[11,11,93488],"valueArr":["DJ","QC","ZP"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','itemcode',5653,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":118,"upper":"502112203","lower":"1216183800","count":1220,"preSum":0},{"ndv":31,"upper":"502191513","lower":"502112204","count":1226,"preSum":1220},{"ndv":15,"upper":"502191712","lower":"502191520","count":1163,"preSum":2446},{"ndv":4,"upper":"502200306","lower":"502200300","count":1576,"preSum":3609},{"ndv":10,"upper":"502201701","lower":"502200400","count":1667,"preSum":5185},{"ndv":5,"upper":"502202001","lower":"502201902","count":1151,"preSum":6852},{"ndv":8,"upper":"502203504","lower":"502202401","count":1367,"preSum":8003},{"ndv":7,"upper":"502220502","lower":"502220201","count":1209,"preSum":9370},{"ndv":34,"upper":"502250601","lower":"502220601","count":1177,"preSum":10579},{"ndv":25,"upper":"502476706","lower":"502250700","count":1201,"preSum":11756},{"ndv":2,"upper":"502477902","lower":"502476708","count":1218,"preSum":12957},{"ndv":26,"upper":"502499000","lower":"502478103","count":1148,"preSum":14175},{"ndv":35,"upper":"502520701","lower":"502499002","count":1150,"preSum":15323},{"ndv":24,"upper":"502523708","lower":"502520703","count":1241,"preSum":16473},{"ndv":23,"upper":"502540302","lower":"502523901T","count":1580,"preSum":17714},{"ndv":44,"upper":"502562203","lower":"502542200","count":1740,"preSum":19294},{"ndv":57,"upper":"502582804","lower":"502564102","count":1216,"preSum":21034},{"ndv":17,"upper":"502586901","lower":"502582900","count":1619,"preSum":22250},{"ndv":9,"upper":"502588502","lower":"502588102","count":1159,"preSum":23869},{"ndv":34,"upper":"502597300","lower":"502588700","count":1449,"preSum":25028},{"ndv":59,"upper":"502622207","lower":"502597301","count":1351,"preSum":26477},{"ndv":11,"upper":"502640804","lower":"502622208","count":1234,"preSum":27828},{"ndv":4,"upper":"502642510","lower":"502640805","count":1182,"preSum":29062},{"ndv":7,"upper":"502643601","lower":"502642601","count":1171,"preSum":30244},{"ndv":10,"upper":"502646402","lower":"502643602","count":1164,"preSum":31415},{"ndv":67,"upper":"502671602","lower":"502646500","count":1157,"preSum":32579},{"ndv":19,"upper":"502672802","lower":"502671700","count":1188,"preSum":33736},{"ndv":27,"upper":"502692900","lower":"502672900","count":1782,"preSum":34924},{"ndv":6,"upper":"502693900","lower":"502693400","count":1348,"preSum":36706},{"ndv":34,"upper":"502699102","lower":"502694000","count":1680,"preSum":38054},{"ndv":9,"upper":"502699402","lower":"502699200","count":1910,"preSum":39734},{"ndv":57,"upper":"502711602","lower":"502700000","count":1170,"preSum":41644},{"ndv":32,"upper":"502724601","lower":"502711603","count":1163,"preSum":42814},{"ndv":13,"upper":"502730100","lower":"502724700","count":1229,"preSum":43977},{"ndv":10,"upper":"502732000","lower":"502730200","count":1199,"preSum":45206},{"ndv":18,"upper":"502740801","lower":"502732200","count":1262,"preSum":46405},{"ndv":5,"upper":"502750104","lower":"502740900","count":1295,"preSum":47667},{"ndv":11,"upper":"502754100","lower":"502750105","count":1169,"preSum":48962},{"ndv":11,"upper":"502754801","lower":"502754200","count":1264,"preSum":50131},{"ndv":4,"upper":"502755100","lower":"502754900","count":1156,"preSum":51395},{"ndv":3,"upper":"502755300","lower":"502755101","count":1247,"preSum":52551},{"ndv":7,"upper":"502755900","lower":"502755301","count":1936,"preSum":53798},{"ndv":30,"upper":"502762700","lower":"502756000","count":1201,"preSum":55734},{"ndv":11,"upper":"502765800","lower":"502762701","count":1225,"preSum":56935},{"ndv":25,"upper":"502777101","lower":"502766000","count":1163,"preSum":58160},{"ndv":18,"upper":"502789400","lower":"502777200","count":1235,"preSum":59323},{"ndv":26,"upper":"502834500","lower":"502789500","count":1162,"preSum":60558},{"ndv":19,"upper":"502974753","lower":"502835600","count":1264,"preSum":61720},{"ndv":15,"upper":"502976671","lower":"502974891","count":1262,"preSum":62984},{"ndv":53,"upper":"505000504","lower":"502976691","count":1155,"preSum":64246},{"ndv":130,"upper":"505041600","lower":"505000603","count":1152,"preSum":65401},{"ndv":76,"upper":"512002000","lower":"505043200","count":1163,"preSum":66553},{"ndv":39,"upper":"6023226","lower":"512002100","count":1155,"preSum":67716},{"ndv":70,"upper":"6164916","lower":"6160272","count":1363,"preSum":68871},{"ndv":33,"upper":"6165195","lower":"6164917","count":1778,"preSum":70234},{"ndv":29,"upper":"6165471","lower":"6165202","count":1183,"preSum":72012},{"ndv":14,"upper":"9999050048","lower":"6165472","count":217,"preSum":73195}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[971,979,1415,1709,2367,1911,1203,2056,1519,890,1674,1385,1121,898],"valueArr":["502201703","502477901","502536603","502582805","502668704","502668804","502668904","502669004","502697804","502699002","502700002","502725500","502976673","6165273"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','itemname',7167,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":178,"upper":"春夏弹嫩焕颜精华液(新法规)40mL","lower":" 自然堂舒缓润养卸妆膏100mL(王者荣耀限量礼盒)","count":1208,"preSum":0},{"ndv":149,"upper":"珀芙研水润平衡洁面乳100g","lower":"春夏无瑕裸透气垫粉凝霜组合装#01象牙色15g×2个装","count":1235,"preSum":1208},{"ndv":25,"upper":"珀芙研舒缓保湿洁面乳15g中小样","lower":"珀芙研水润平衡洁面乳15g中小样","count":1294,"preSum":2443},{"ndv":121,"upper":"自然堂2020维A霜托架(美妆店1.8米)","lower":"珀芙研舒缓修护三联袋(2g洁面+2mL水+2g霜/自产)袋装","count":1208,"preSum":3737},{"ndv":27,"upper":"自然堂III型重组胶原蛋白修护冻干面膜0.65g×5片装","lower":"自然堂2020雪肌/小紫瓶/安瓶亚克力贴(美妆店1.5米A类店)","count":1428,"preSum":4945},{"ndv":19,"upper":"自然堂亲肤倍呵防晒乳SPF50+PA+++50mL","lower":"自然堂III型重组胶原蛋白修护面膜27mL×5片装","count":1379,"preSum":6373},{"ndv":16,"upper":"自然堂冰川水水光面膜28mL*5片装","lower":"自然堂亲肤倍呵防晒乳优惠装","count":1233,"preSum":7752},{"ndv":43,"upper":"自然堂凝时精华鲜注面膜(2022二版)30mL 5片装","lower":"自然堂冰川水水光面膜28mL×3片装","count":1239,"preSum":8985},{"ndv":14,"upper":"自然堂凝时鲜颜冰肌水(体验装)60mL中小样","lower":"自然堂凝时精华鲜注面膜(2022二版)30mL×3片装","count":1313,"preSum":10224},{"ndv":16,"upper":"自然堂凝时鲜颜小紫瓶精华抗皱臻选六件套(2022洁水乳精眼霜眼膜套)","lower":"自然堂凝时鲜颜冰肌水(滋润型)(体验装)60mL中小样","count":1209,"preSum":11537},{"ndv":8,"upper":"自然堂凝时鲜颜小紫瓶肌活霜第五代(2022升级)15g中小样","lower":"自然堂凝时鲜颜小紫瓶肌活霜(云雾)50g","count":1577,"preSum":12746},{"ndv":5,"upper":"自然堂凝时鲜颜洁面霜125g","lower":"自然堂凝时鲜颜小紫瓶肌活霜第五代(2022升级)50g","count":1221,"preSum":14323},{"ndv":18,"upper":"自然堂凝时鲜颜肌活乳液120mL","lower":"自然堂凝时鲜颜洁面霜125g假样","count":1230,"preSum":15544},{"ndv":22,"upper":"自然堂凝时鲜颜肌活修护小紫瓶精华液7mL(第五代)中小样","lower":"自然堂凝时鲜颜肌活乳液120mL(2022升级)","count":1333,"preSum":16774},{"ndv":7,"upper":"自然堂凝时鲜颜肌活修护小紫瓶精华液第五代(2023/派样装)7mL中小样","lower":"自然堂凝时鲜颜肌活修护小紫瓶精华液7mL(第五代/派样装)中小样","count":1679,"preSum":18107},{"ndv":22,"upper":"自然堂凝时鲜颜肌活修护眼霜5g(新装箱/常规)中小样","lower":"自然堂凝时鲜颜肌活修护小紫瓶精华液第五代(派样装)7mL中小样","count":1242,"preSum":19786},{"ndv":10,"upper":"自然堂凝时鲜颜肌活氨基酸洁面霜(2023升级)60g中小样","lower":"自然堂凝时鲜颜肌活修护眼霜5g中小样","count":1218,"preSum":21028},{"ndv":7,"upper":"自然堂凝时鲜颜肌活霜(2023升级)15g中小样","lower":"自然堂凝时鲜颜肌活眼部精华乳18mL类产品","count":1252,"preSum":22246},{"ndv":6,"upper":"自然堂凝润滋养护手霜(20210716加花盒)50g","lower":"自然堂凝时鲜颜肌活霜(2023升级)50g","count":1233,"preSum":23498},{"ndv":52,"upper":"自然堂多肽抗皱美颈霜60g类产品","lower":"自然堂凝润滋养护手霜50g(20210716加花盒)","count":1449,"preSum":24731},{"ndv":14,"upper":"自然堂头皮护理敏感头皮修护精华液120mL","lower":"自然堂多肽紧致美颈霜60g(暂定名)类产品","count":1384,"preSum":26180},{"ndv":3,"upper":"自然堂头皮护理敏感头皮净护精华乳550mL","lower":"自然堂头皮护理敏感头皮修护精华液20mL中小样","count":1445,"preSum":27564},{"ndv":3,"upper":"自然堂头皮护理洗护精旅行装(40mL+40mL+20mL)三件套","lower":"自然堂头皮护理敏感头皮止痒洗发露+精华乳洗护两联包(5mL+5mL)两件套袋装","count":1820,"preSum":29009},{"ndv":14,"upper":"自然堂娇颜亮润焕采眼霜(抖拼快专售)15g","lower":"自然堂头皮护理洗护精旅行装(40mL+40mL+20mL)三件套(第2版)","count":1215,"preSum":30829},{"ndv":12,"upper":"自然堂娇颜亮润美白4件套(洁水乳精)","lower":"自然堂娇颜亮润焕采眼霜15g(抖拼快专售)","count":1670,"preSum":32044},{"ndv":14,"upper":"自然堂嫩白保湿乳(粉盖)35mL中小样","lower":"自然堂娇颜亮润美白体验装四件套(抖拼快专售)中小样","count":1265,"preSum":33714},{"ndv":10,"upper":"自然堂嫩白保湿精华液10mL小规格产品","lower":"自然堂嫩白保湿乳115mL(抖拼快专售)","count":1274,"preSum":34979},{"ndv":17,"upper":"自然堂定制随包卡片(朵纯新版)","lower":"自然堂嫩白保湿精华液35mL(抖拼快专售)","count":1412,"preSum":36253},{"ndv":42,"upper":"自然堂弹嫩紧致抗皱修护晚安霜50g","lower":"自然堂定制随包卡片(每妆)","count":1246,"preSum":37665},{"ndv":28,"upper":"自然堂弹嫩细致洁颜霜120g","lower":"自然堂弹嫩紧致抗皱护肤品套装(气色液+乳液+精华液)","count":1248,"preSum":38911},{"ndv":71,"upper":"自然堂感光无瑕持妆粉底液(油皮)#B03米杏色30mL","lower":"自然堂弹嫩细致洁颜霜125g","count":1218,"preSum":40159},{"ndv":45,"upper":"自然堂果酸细致焕肤面膜(绿色盖膜/纸卡版)6g 1颗装中小样","lower":"自然堂感光无瑕持妆粉底液(油皮)#B04暖沙色30mL","count":1432,"preSum":41377},{"ndv":41,"upper":"自然堂水光充盈保湿乳115mL(新规升级版)","lower":"自然堂果酸细致焕肤面膜(绿色盖膜/纸卡版/升级版)6g 1颗装中小样","count":1220,"preSum":42809},{"ndv":22,"upper":"自然堂水光充盈四件套(洁水乳霜/抖拼快专供/配方升级)","lower":"自然堂水光充盈保湿乳35mL中小样","count":1244,"preSum":44029},{"ndv":14,"upper":"自然堂水润保湿霜(2022升级版)50g","lower":"自然堂水光充盈洁水乳霜礼盒","count":1380,"preSum":45273},{"ndv":58,"upper":"自然堂滚轮按摩仪","lower":"自然堂水润保湿霜50g","count":1587,"preSum":46653},{"ndv":44,"upper":"自然堂烟酰胺细致提亮安瓶面膜(无防腐) 安瓶1.5mL+面膜33mL 5片装","lower":"自然堂炫彩盈润高显色唇膏#101千禧粉3.2g","count":1742,"preSum":48240},{"ndv":55,"upper":"自然堂男士咖啡因活力氨基酸洁面乳(2022版)120g","lower":"自然堂烟酰胺细致提亮面膜(新规版)33mL 5片装","count":1237,"preSum":49982},{"ndv":37,"upper":"自然堂男士喜马拉雅冰川保湿露(新标签版)20mL中小样","lower":"自然堂男士咖啡因活力氨基酸洁面乳120g","count":1843,"preSum":51219},{"ndv":31,"upper":"自然堂男士喜马拉雅龙血能量劲爽醒肤面膜(2022版)22mL 1片装类产品","lower":"自然堂男士喜马拉雅冰川保湿露20mL(新标签版)中小样","count":1718,"preSum":53062},{"ndv":67,"upper":"自然堂粉钻紧致细嫩玫瑰水(美ONE定制)55mL中小样","lower":"自然堂男士喜马拉雅龙血能量劲爽醒肤面膜22mL*1PCS(201906)","count":1286,"preSum":54780},{"ndv":32,"upper":"自然堂纯粹滋润冰肌水(2022升级版)60mL中小样","lower":"自然堂粉钻紧致细嫩玫瑰水110mL(美ONE定制)","count":1887,"preSum":56066},{"ndv":28,"upper":"自然堂美白淡斑两步曲面膜(1.5mL+26mL)*5PCS(2022版)","lower":"自然堂纯粹滋润冰肌水(2022升级版)90mL","count":1341,"preSum":57953},{"ndv":34,"upper":"自然堂蓝铜肽抗皱紧致安瓶面膜安瓶1.5mL+面膜33mL5片装","lower":"自然堂美白淡斑两步曲面膜(1.5mL+26mL)*5片装(2022版)","count":1372,"preSum":59294},{"ndv":32,"upper":"自然堂酵母原液修护安瓶精华液(第二代)1.5mL*7PCS类产品","lower":"自然堂虾青素焕亮紧致面膜(新规版)33mL×5片装","count":1510,"preSum":60666},{"ndv":65,"upper":"自然堂雪域百合补水面膜(2022二版)26mL 1片装","lower":"自然堂酵母原液修护安瓶精华液1.5mL 28支装","count":1692,"preSum":62176},{"ndv":41,"upper":"自然堂雪域精粹纯粹滋润乳液(2022标签升级)120mL","lower":"自然堂雪域百合补水面膜(2022二版)26mL 5片装","count":1253,"preSum":63868},{"ndv":36,"upper":"自然堂雪域精粹纯粹滋润精华液10mL(2022/1)中小样","lower":"自然堂雪域精粹纯粹滋润乳液(2022标签升级)90mL","count":1270,"preSum":65121},{"ndv":26,"upper":"自然堂雪域紫草细致毛孔面膜26mL*5PCS(2022二版)","lower":"自然堂雪域精粹纯粹滋润精华液10mL(体验装)","count":1470,"preSum":66391},{"ndv":24,"upper":"自然堂雪松精油活颜御龄光感霜1.5g袋装","lower":"自然堂雪域紫草细致毛孔面膜26mL*5片装(2022二版)","count":1216,"preSum":67861},{"ndv":31,"upper":"自然堂雪松精油精华鲜注面膜(2022版)30mL×5片装","lower":"自然堂雪松精油活颜御龄光感霜50g","count":1209,"preSum":69077},{"ndv":45,"upper":"自然堂雪润皙白多重防晒隔离霜(淡绿色)SPF35PA+++(新版)30mL","lower":"自然堂雪松精油精华鲜注面膜30mL 5片装","count":1337,"preSum":70286},{"ndv":28,"upper":"自然堂雪肌美白保湿洁面霜120g","lower":"自然堂雪润皙白多重防晒隔离霜(淡绿色)SPF35PA+++(软管二代)30mL","count":1211,"preSum":71623},{"ndv":18,"upper":"自然堂雪茶平衡保湿面膜(2022二版)26mL×5片装","lower":"自然堂雪肌美白保湿洁面霜20g中小样","count":1509,"preSum":72834},{"ndv":11,"upper":"自然堂雪莲舒缓保湿面膜(2021版)26mL 1片装","lower":"自然堂雪茶平衡保湿面膜(2022版)26mL×5片装","count":1209,"preSum":74343},{"ndv":13,"upper":"自然堂雪莲舒缓保湿面膜26mL*5PCS(2022二版)","lower":"自然堂雪莲舒缓保湿面膜(2021版)26mL×3片装","count":1310,"preSum":75552},{"ndv":25,"upper":"香薰套装","lower":"自然堂雪莲舒缓保湿面膜26mL*5片装(2021版)","count":412,"preSum":76862}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[898,879,892,971,1121,1385,1674,1075,1059,1162,1185,1369,1442,1124],"valueArr":["自然堂2022版购物袋-中号","自然堂凝时鲜颜肌活乳液(2023升级)120mL","自然堂凝时鲜颜肌活修护体验装三件套(霜版)中小样","自然堂凝时鲜颜肌活冰肌水(清润型)(2023升级)160mL","自然堂凝时鲜颜肌活冰肌水(清润型)(2023升级)60mL","自然堂喜马拉雅茶泥净颜清洁面膜100g","自然堂植物补水面膜21片装(2022二版)","自然堂烟酰胺细致提亮安瓶面膜(新规版) 1.5mL+33mL×5片装","自然堂羽感致护防晒乳SPF50+PA+++(新规版)50mL","自然堂雪域百合补水面膜(2022二版)26mL×5片装","自然堂雪域百合补水面膜26mL*5PCS(2022二版)","自然堂雪域紫草细致毛孔面膜(2022二版)26mL×5片装","自然堂雪域龙胆亮润面膜(2022二版)26mL×5片装","自然堂雪莲舒缓保湿面膜(2022二版)26mL×5片装"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','lastupdated',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','lastupdatedby',156,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"000002","lower":"000002","count":996,"preSum":0},{"ndv":1,"upper":"000003","lower":"000003","count":1184,"preSum":996},{"ndv":1,"upper":"000004","lower":"000004","count":1592,"preSum":2180},{"ndv":9,"upper":"0220003","lower":"000006","count":346,"preSum":3772},{"ndv":1,"upper":"0220006","lower":"0220006","count":1615,"preSum":4118},{"ndv":4,"upper":"02700003","lower":"0220009","count":1217,"preSum":5733},{"ndv":1,"upper":"02700009","lower":"02700009","count":1161,"preSum":6950},{"ndv":14,"upper":"1000003","lower":"02700020","count":750,"preSum":8111},{"ndv":1,"upper":"1000004","lower":"1000004","count":350,"preSum":8861},{"ndv":4,"upper":"10001","lower":"1000006","count":1454,"preSum":9211},{"ndv":2,"upper":"10003","lower":"10002","count":1024,"preSum":10665},{"ndv":2,"upper":"10005","lower":"10004","count":338,"preSum":11689},{"ndv":4,"upper":"10009","lower":"10006","count":629,"preSum":12027},{"ndv":12,"upper":"41512820","lower":"20001","count":816,"preSum":12656},{"ndv":2,"upper":"42085600","lower":"41580442","count":611,"preSum":13472},{"ndv":5,"upper":"gth","lower":"42104883","count":338,"preSum":14083},{"ndv":2,"upper":"hxy","lower":"GY","count":923,"preSum":14421},{"ndv":3,"upper":"LL","lower":"lh","count":747,"preSum":15344},{"ndv":2,"upper":"lyg","lower":"lxp","count":581,"preSum":16091},{"ndv":6,"upper":"WJH","lower":"PZ","count":1067,"preSum":16672},{"ndv":3,"upper":"YBJ","lower":"XCY","count":459,"preSum":17739},{"ndv":2,"upper":"yxy","lower":"yj","count":1915,"preSum":18198},{"ndv":1,"upper":"zhaolingling","lower":"zhaolingling","count":371,"preSum":20113},{"ndv":1,"upper":"zjf","lower":"zjf","count":198,"preSum":20484}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[2272,4556,2686,8298,2130,2317,2538,2403,2950,7638,9805,16258,2151,6826],"valueArr":["000001","0220005","02700005","02700010","10000002","10000004","40401644","40721814","41157743","41509297","41580109","42008280","42196770","api"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','lot',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','manufacturedate',3530,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":288,"upper":"1849519295407587328","lower":"-1","count":1160,"preSum":0},{"ndv":96,"upper":"1849884333268008960","lower":"1849521494430842880","count":1161,"preSum":1160},{"ndv":85,"upper":"1850132822895886336","lower":"1849886532291264512","count":1155,"preSum":2321},{"ndv":25,"upper":"1850189997500530688","lower":"1850137220942397440","count":1167,"preSum":3476},{"ndv":28,"upper":"1850262565267963904","lower":"1850194395547041792","count":1205,"preSum":4643},{"ndv":20,"upper":"1850315341826097152","lower":"1850264764291219456","count":1199,"preSum":5848},{"ndv":26,"upper":"1850379113500508160","lower":"1850317540849352704","count":1157,"preSum":7047},{"ndv":15,"upper":"1850412098849341440","lower":"1850381312523763712","count":1247,"preSum":8204},{"ndv":6,"upper":"1850431890058641408","lower":"1850418695919108096","count":1161,"preSum":9451},{"ndv":6,"upper":"1850445084198174720","lower":"1850434089081896960","count":1217,"preSum":10612},{"ndv":6,"upper":"1850460477360963584","lower":"1850447283221430272","count":1396,"preSum":11829},{"ndv":3,"upper":"1850467074430730240","lower":"1850462676384219136","count":1287,"preSum":13225},{"ndv":4,"upper":"1850475870523752448","lower":"1850469273453985792","count":1320,"preSum":14512},{"ndv":5,"upper":"1850489064663285760","lower":"1850478069547008000","count":1186,"preSum":15832},{"ndv":6,"upper":"1850502258802819072","lower":"1850491263686541312","count":1439,"preSum":17018},{"ndv":3,"upper":"1850508855872585728","lower":"1850504457826074624","count":1156,"preSum":18457},{"ndv":5,"upper":"1850519850988863488","lower":"1850511054895841280","count":1457,"preSum":19613},{"ndv":4,"upper":"1850528647081885696","lower":"1850522050012119040","count":1529,"preSum":21070},{"ndv":4,"upper":"1850537443174907904","lower":"1850530846105141248","count":1393,"preSum":22599},{"ndv":5,"upper":"1850548438291185664","lower":"1850539642198163456","count":1274,"preSum":23992},{"ndv":4,"upper":"1850563831453974528","lower":"1850550637314441216","count":1152,"preSum":25266},{"ndv":5,"upper":"1850574826570252288","lower":"1850566030477230080","count":1179,"preSum":26418},{"ndv":6,"upper":"1850588020709785600","lower":"1850577025593507840","count":1296,"preSum":27597},{"ndv":5,"upper":"1850599015826063360","lower":"1850590219733041152","count":1202,"preSum":28893},{"ndv":7,"upper":"1850614408988852224","lower":"1850601214849318912","count":1380,"preSum":30095},{"ndv":5,"upper":"1850625404105129984","lower":"1850616608012107776","count":1189,"preSum":31475},{"ndv":7,"upper":"1850713365035352064","lower":"1850700170895818752","count":1608,"preSum":32664},{"ndv":7,"upper":"1850728758198140928","lower":"1850715564058607616","count":1212,"preSum":34272},{"ndv":11,"upper":"1850772738663251968","lower":"1850730957221396480","count":1263,"preSum":35484},{"ndv":8,"upper":"1850790330849296384","lower":"1850774937686507520","count":1338,"preSum":36747},{"ndv":7,"upper":"1850805724012085248","lower":"1850792529872551936","count":1250,"preSum":38085},{"ndv":11,"upper":"1850829913267896320","lower":"1850807923035340800","count":1612,"preSum":39335},{"ndv":4,"upper":"1850847505453940736","lower":"1850840908384174080","count":1227,"preSum":40947},{"ndv":3,"upper":"1850854102523707392","lower":"1850849704477196288","count":1500,"preSum":42174},{"ndv":4,"upper":"1850862898616729600","lower":"1850856301546962944","count":1460,"preSum":43674},{"ndv":3,"upper":"1850869495686496256","lower":"1850865097639985152","count":1160,"preSum":45134},{"ndv":4,"upper":"1850878291779518464","lower":"1850871694709751808","count":1657,"preSum":46294},{"ndv":3,"upper":"1850884888849285120","lower":"1850880490802774016","count":1659,"preSum":47951},{"ndv":3,"upper":"1850891485919051776","lower":"1850887087872540672","count":1480,"preSum":49610},{"ndv":2,"upper":"1850895883965562880","lower":"1850893684942307328","count":1299,"preSum":51090},{"ndv":5,"upper":"1850906879081840640","lower":"1850898082988818432","count":1398,"preSum":52389},{"ndv":3,"upper":"1850917874198118400","lower":"1850911277128351744","count":1534,"preSum":53787},{"ndv":4,"upper":"1850926670291140608","lower":"1850920073221373952","count":1196,"preSum":55321},{"ndv":3,"upper":"1850937665407418368","lower":"1850928869314396160","count":1630,"preSum":56517},{"ndv":3,"upper":"1850946461500440576","lower":"1850939864430673920","count":1582,"preSum":58147},{"ndv":4,"upper":"1850961854663229440","lower":"1850953058570207232","count":1689,"preSum":59729},{"ndv":3,"upper":"1850968451732996096","lower":"1850964053686484992","count":1795,"preSum":61418},{"ndv":3,"upper":"1850975048802762752","lower":"1850970650756251648","count":1152,"preSum":63213},{"ndv":3,"upper":"1850992640988807168","lower":"1850983844895784960","count":1812,"preSum":64365},{"ndv":2,"upper":"1850997039035318272","lower":"1850994840012062720","count":1401,"preSum":66177},{"ndv":2,"upper":"1851003636105084928","lower":"1851001437081829376","count":1268,"preSum":67578},{"ndv":4,"upper":"1851016830244618240","lower":"1851010233174851584","count":1458,"preSum":68846},{"ndv":6,"upper":"1851030024384151552","lower":"1851019029267873792","count":1186,"preSum":70304},{"ndv":8,"upper":"1851047616570195968","lower":"1851032223407407104","count":1338,"preSum":71490},{"ndv":102,"upper":"1854508879174434816","lower":"1851052014616707072","count":890,"preSum":72828}],"maxBucketSize":64,"type":"Date","sampleRate":1.0}','{"countArr":[8375,1001,738,1096,714,825,823,720,1101,1027,804,787,1019,762],"valueArr":[1850456079314452480,1850561632430718976,1850915675174862848,1850931068337651712,1850935466384162816,1850942063453929472,1850948660523696128,1850950859546951680,1850955257593462784,1850988242942296064,1850990441965551616,1850999238058573824,1851005835128340480,1851008034151596032],"type":"Date","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','packingcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[93510],"valueArr":["STD"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','pickdroploc',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[253],"valueArr":["RPLN-01"],"type":"String","sampleRate":1.0}',93257,0.006721839),('jala_wms_prod','task_detail','pickingcartcode',962,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"","lower":"","count":1,"preSum":0},{"ndv":1,"upper":"IB00001 ","lower":"IB00001 ","count":2,"preSum":1},{"ndv":1,"upper":"IB00007","lower":"IB00007","count":1,"preSum":3},{"ndv":1,"upper":"IB00021","lower":"IB00021","count":1,"preSum":4},{"ndv":1,"upper":"IB00023","lower":"IB00023","count":1,"preSum":5},{"ndv":1,"upper":"IB00032","lower":"IB00032","count":1,"preSum":6},{"ndv":1,"upper":"IB00040","lower":"IB00040","count":1,"preSum":7},{"ndv":1,"upper":"IB00042","lower":"IB00042","count":1,"preSum":8},{"ndv":1,"upper":"IB00044","lower":"IB00044","count":1,"preSum":9},{"ndv":1,"upper":"IB00052","lower":"IB00052","count":1,"preSum":10},{"ndv":1,"upper":"IB00054","lower":"IB00054","count":1,"preSum":11},{"ndv":1,"upper":"IB00083","lower":"IB00083","count":1,"preSum":12},{"ndv":1,"upper":"IB00084","lower":"IB00084","count":2,"preSum":13},{"ndv":1,"upper":"IB00086","lower":"IB00086","count":1,"preSum":15},{"ndv":1,"upper":"IB00088","lower":"IB00088","count":1,"preSum":16},{"ndv":1,"upper":"IB00092","lower":"IB00092","count":1,"preSum":17},{"ndv":1,"upper":"IB00095","lower":"IB00095","count":1,"preSum":18},{"ndv":1,"upper":"IB00097","lower":"IB00097","count":2,"preSum":19},{"ndv":1,"upper":"IB00105","lower":"IB00105","count":1,"preSum":21},{"ndv":1,"upper":"IB00124","lower":"IB00124","count":1,"preSum":22},{"ndv":1,"upper":"IB00136","lower":"IB00136","count":2,"preSum":23},{"ndv":1,"upper":"IB00141","lower":"IB00141","count":1,"preSum":25},{"ndv":1,"upper":"IB00142","lower":"IB00142","count":2,"preSum":26},{"ndv":1,"upper":"IB00147","lower":"IB00147","count":1,"preSum":28},{"ndv":1,"upper":"IB00148","lower":"IB00148","count":1,"preSum":29},{"ndv":1,"upper":"IB00150","lower":"IB00150","count":1,"preSum":30},{"ndv":1,"upper":"IB00151","lower":"IB00151","count":2,"preSum":31},{"ndv":1,"upper":"IB00152","lower":"IB00152","count":1,"preSum":33},{"ndv":1,"upper":"IB00166","lower":"IB00166","count":1,"preSum":34},{"ndv":1,"upper":"IB00184","lower":"IB00184","count":1,"preSum":35},{"ndv":1,"upper":"IB00192","lower":"IB00192","count":1,"preSum":36},{"ndv":1,"upper":"IB00194","lower":"IB00194","count":1,"preSum":37},{"ndv":1,"upper":"IB00196","lower":"IB00196","count":1,"preSum":38},{"ndv":1,"upper":"IB00211","lower":"IB00211","count":1,"preSum":39},{"ndv":1,"upper":"IB00218","lower":"IB00218","count":1,"preSum":40},{"ndv":1,"upper":"IB00221","lower":"IB00221","count":1,"preSum":41},{"ndv":1,"upper":"IB00237","lower":"IB00237","count":1,"preSum":42},{"ndv":1,"upper":"IB00259","lower":"IB00259","count":1,"preSum":43},{"ndv":1,"upper":"IB00276","lower":"IB00276","count":1,"preSum":44},{"ndv":1,"upper":"IB00284","lower":"IB00284","count":1,"preSum":45},{"ndv":1,"upper":"IB00294","lower":"IB00294","count":1,"preSum":46},{"ndv":1,"upper":"IB00302","lower":"IB00302","count":1,"preSum":47},{"ndv":1,"upper":"IB00355","lower":"IB00355","count":1,"preSum":48},{"ndv":1,"upper":"IB00357","lower":"IB00357","count":1,"preSum":49},{"ndv":1,"upper":"IB00366","lower":"IB00366","count":1,"preSum":50},{"ndv":1,"upper":"IB00396","lower":"IB00396","count":1,"preSum":51},{"ndv":1,"upper":"IB00398","lower":"IB00398","count":1,"preSum":52},{"ndv":1,"upper":"IB00403","lower":"IB00403","count":1,"preSum":53},{"ndv":1,"upper":"IB00404","lower":"IB00404","count":1,"preSum":54},{"ndv":1,"upper":"IB00410","lower":"IB00410","count":1,"preSum":55},{"ndv":1,"upper":"IB00436","lower":"IB00436","count":1,"preSum":56},{"ndv":1,"upper":"IB00461","lower":"IB00461","count":1,"preSum":57},{"ndv":1,"upper":"IB00483","lower":"IB00483","count":1,"preSum":58},{"ndv":1,"upper":"IB00492","lower":"IB00492","count":1,"preSum":59},{"ndv":1,"upper":"IB00496","lower":"IB00496","count":1,"preSum":60}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[365,22,31,29,6,3,4,3,20,6,24,5,12],"valueArr":["IB00001","IB00003","IB00004","IB00005","IB00008","IB0001","IB00012","IB00104","IB00210","IB00293","IB00309","IB00399","IB00440"],"type":"String","sampleRate":1.0}',92919,0.006721839),('jala_wms_prod','task_detail','pickingcartpos',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[172],"valueArr":[""],"type":"String","sampleRate":1.0}',93338,0.006721839),('jala_wms_prod','task_detail','plqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93510],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','processstamp',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','qtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93510],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','rebinshortqty',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','referencecode',144256,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":101,"upper":"60120558","lower":"1200008498","count":1452,"preSum":0},{"ndv":212,"upper":"CK0001351410","lower":"60132615","count":1448,"preSum":1452},{"ndv":249,"upper":"CK0001475896","lower":"CK0001351414","count":1449,"preSum":2900},{"ndv":193,"upper":"CK0001513914","lower":"CK0001476224","count":1452,"preSum":4349},{"ndv":187,"upper":"CK0001547638","lower":"CK0001513934","count":1454,"preSum":5801},{"ndv":168,"upper":"CKH00000011897","lower":"CK0001547645","count":1475,"preSum":7255},{"ndv":254,"upper":"OD6624881","lower":"CKH00000011908","count":1460,"preSum":8730},{"ndv":270,"upper":"OD6715240","lower":"OD6625166","count":1456,"preSum":10190},{"ndv":332,"upper":"OD6842822","lower":"OD6715307","count":1448,"preSum":11646},{"ndv":343,"upper":"OD6936250","lower":"OD6843111","count":1454,"preSum":13094},{"ndv":329,"upper":"OD7006668","lower":"OD6936263","count":1449,"preSum":14548},{"ndv":489,"upper":"PJD2306823739271812","lower":"OD7006711","count":1451,"preSum":15997},{"ndv":489,"upper":"PJX2304783219561904","lower":"PJD2306823814491812","count":1452,"preSum":17448},{"ndv":438,"upper":"PJX2305792388340421","lower":"PJX2304783220481904","count":1448,"preSum":18900},{"ndv":406,"upper":"PJX2305797003801313","lower":"PJX2305792399480421","count":1452,"preSum":20348},{"ndv":478,"upper":"PJX2305802407242309","lower":"PJX2305797006831313","count":1449,"preSum":21800},{"ndv":491,"upper":"PJX2306812729810209","lower":"PJX2305802410722309","count":1448,"preSum":23249},{"ndv":469,"upper":"PJX2306818063681111","lower":"PJX2306812729840209","count":1448,"preSum":24697},{"ndv":439,"upper":"PJX2306822980231722","lower":"PJX2306818073321112","count":1449,"preSum":26145},{"ndv":397,"upper":"POD2305797924041508","lower":"PJX2306823003131722","count":1448,"preSum":27594},{"ndv":599,"upper":"POD2306817255980916","lower":"POD2305797948031509","count":1451,"preSum":29042},{"ndv":500,"upper":"PSD2304784239352114","lower":"POD2306817275310917","count":1452,"preSum":30493},{"ndv":302,"upper":"PSD2304785183992313","lower":"PSD2304784239512114","count":1449,"preSum":31945},{"ndv":433,"upper":"PSD2304786844012623","lower":"PSD2304785184002313","count":1449,"preSum":33394},{"ndv":313,"upper":"PSD2304788609303010","lower":"PSD2304786844022623","count":1450,"preSum":34843},{"ndv":380,"upper":"PSD2305791359070313","lower":"PSD2304788609323010","count":1457,"preSum":36293},{"ndv":426,"upper":"PSD2305793502520622","lower":"PSD2305791415780314","count":1448,"preSum":37750},{"ndv":456,"upper":"PSD2305794974720920","lower":"PSD2305793502600622","count":1450,"preSum":39198},{"ndv":366,"upper":"PSD2305796640401217","lower":"PSD2305794977720920","count":1449,"preSum":40648},{"ndv":348,"upper":"PSD2305798040621511","lower":"PSD2305796640771217","count":1453,"preSum":42097},{"ndv":395,"upper":"PSD2305800763642002","lower":"PSD2305798044891511","count":1452,"preSum":43550},{"ndv":351,"upper":"PSD2305802008802211","lower":"PSD2305800763792002","count":1454,"preSum":45002},{"ndv":442,"upper":"PSD2305803761562609","lower":"PSD2305802008812211","count":1459,"preSum":46456},{"ndv":462,"upper":"PSD2305809039663002","lower":"PSD2305803762232609","count":1450,"preSum":47915},{"ndv":471,"upper":"PSD2306812163330117","lower":"PSD2305809039743002","count":1459,"preSum":49365},{"ndv":420,"upper":"PSD2306814844950503","lower":"PSD2306812163410117","count":1450,"preSum":50824},{"ndv":390,"upper":"PSD2306817173660913","lower":"PSD2306814845090503","count":1452,"preSum":52274},{"ndv":441,"upper":"PSD2306818386861123","lower":"PSD2306817173670913","count":1452,"preSum":53726},{"ndv":427,"upper":"PSD2306819636861416","lower":"PSD2306818386941123","count":1453,"preSum":55178},{"ndv":434,"upper":"PSD2306822133751701","lower":"PSD2306819636881416","count":1453,"preSum":56631},{"ndv":431,"upper":"PTB2302754975532411","lower":"PSD2306822133761701","count":1449,"preSum":58084},{"ndv":698,"upper":"PTB2304777586640719","lower":"PTB2302755009992412","count":1449,"preSum":59533},{"ndv":681,"upper":"PTB2304785058812309","lower":"PTB2304777611100721","count":1448,"preSum":60982},{"ndv":639,"upper":"PTB2304787838412819","lower":"PTB2304785058942309","count":1448,"preSum":62430},{"ndv":492,"upper":"PTB2305790473880309","lower":"PTB2304787839642819","count":1450,"preSum":63878},{"ndv":523,"upper":"PTB2305791244580311","lower":"PTB2305790474100309","count":1448,"preSum":65328},{"ndv":586,"upper":"PTB2305794696450910","lower":"PTB2305791244980311","count":1448,"preSum":66776},{"ndv":613,"upper":"PTB2305797698661418","lower":"PTB2305794696690910","count":1449,"preSum":68224},{"ndv":616,"upper":"PTB2305799588171718","lower":"PTB2305797698721418","count":1448,"preSum":69673},{"ndv":642,"upper":"PTB2305802077112215","lower":"PTB2305799589211718","count":1449,"preSum":71121},{"ndv":667,"upper":"PTB2305804557612710","lower":"PTB2305802077172215","count":1448,"preSum":72570},{"ndv":512,"upper":"PTB2305805518372711","lower":"PTB2305804558152710","count":1451,"preSum":74018},{"ndv":532,"upper":"PTB2305806567632717","lower":"PTB2305805518522711","count":1448,"preSum":75469},{"ndv":591,"upper":"PTB2305808125082820","lower":"PTB2305806567862717","count":1452,"preSum":76917},{"ndv":543,"upper":"PTB2305809847443109","lower":"PTB2305808125272820","count":1448,"preSum":78369},{"ndv":616,"upper":"PTB2305811022653122","lower":"PTB2305809847653109","count":1448,"preSum":79817},{"ndv":501,"upper":"PTB2306811893780112","lower":"PTB2305811022683122","count":1448,"preSum":81265},{"ndv":584,"upper":"PTB2306813397490300","lower":"PTB2306811896640112","count":1454,"preSum":82713},{"ndv":603,"upper":"PTB2306814988960512","lower":"PTB2306813397900300","count":1449,"preSum":84167},{"ndv":659,"upper":"PTB2306817197260914","lower":"PTB2306814989300512","count":1451,"preSum":85616},{"ndv":661,"upper":"PTB2306819258941319","lower":"PTB2306817199260914","count":1449,"preSum":87067},{"ndv":620,"upper":"PTB2306821320491613","lower":"PTB2306819265851320","count":1448,"preSum":88516},{"ndv":582,"upper":"PTB2306823189461800","lower":"PTB2306821320581613","count":1451,"preSum":89964},{"ndv":289,"upper":"领料退回0113-W007","lower":"PTB2306823190691800","count":1196,"preSum":91415}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[34,34,91,37,76,57,60,65,35,34,54,35,34],"valueArr":["1200009643_W007","1800000289-2","202210自然堂品牌-销售因素退货1127","202211自然堂品牌-销售因素退货","202302自然堂品牌-销售因素退货","202303自然堂品牌-销售因素退货报废","202304自然堂品牌-销售因素退货","23年2C退货4月30日-5月1日报废","23年2C退货6月11日良品","2C退货12月2日报废","2C退货1月8日报废","CK0001191239","CK0001475596"],"type":"String","sampleRate":1.0}',253,0.006721839),('jala_wms_prod','task_detail','referencecontcode',302463,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":182,"upper":"021DC1-74281","lower":"021DC1-0016","count":1451,"preSum":0},{"ndv":401,"upper":"022DC-140026","lower":"021DC1-74285","count":1432,"preSum":1451},{"ndv":523,"upper":"022DC-225037","lower":"022DC-140027","count":1433,"preSum":2883},{"ndv":475,"upper":"022DC-291919","lower":"022DC-225039","count":1432,"preSum":4316},{"ndv":652,"upper":"022DC-36346","lower":"022DC-291920","count":1431,"preSum":5748},{"ndv":595,"upper":"027DC-112250","lower":"022DC-36347","count":1432,"preSum":7179},{"ndv":583,"upper":"027DC-198564","lower":"027DC-112251","count":1432,"preSum":8611},{"ndv":498,"upper":"027DC-265074","lower":"027DC-198565","count":1432,"preSum":10043},{"ndv":549,"upper":"027DC-325912","lower":"027DC-265077","count":1440,"preSum":11475},{"ndv":528,"upper":"027DC-421720","lower":"027DC-325913","count":1434,"preSum":12915},{"ndv":570,"upper":"027DC-494140","lower":"027DC-421721","count":1431,"preSum":14349},{"ndv":540,"upper":"027DC-566274","lower":"027DC-497152","count":1431,"preSum":15780},{"ndv":666,"upper":"027DC-633615","lower":"027DC-566275","count":1432,"preSum":17211},{"ndv":526,"upper":"027DC-698449","lower":"027DC-633616","count":1431,"preSum":18643},{"ndv":524,"upper":"027DC-81894","lower":"027DC-698450","count":1434,"preSum":20074},{"ndv":319,"upper":"573DC-1010692","lower":"027DC-81895","count":1432,"preSum":21508},{"ndv":473,"upper":"573DC-1064742","lower":"573DC-1010853","count":1436,"preSum":22940},{"ndv":451,"upper":"573DC-112354","lower":"573DC-1065259","count":1431,"preSum":24376},{"ndv":488,"upper":"573DC-1187955","lower":"573DC-1123922","count":1431,"preSum":25807},{"ndv":597,"upper":"573DC-1263119","lower":"573DC-1187962","count":1432,"preSum":27238},{"ndv":464,"upper":"573DC-1325260","lower":"573DC-1263120","count":1433,"preSum":28670},{"ndv":426,"upper":"573DC-1380045","lower":"573DC-1325261","count":1434,"preSum":30103},{"ndv":541,"upper":"573DC-1451168","lower":"573DC-1380047","count":1438,"preSum":31537},{"ndv":549,"upper":"573DC-1520511","lower":"573DC-1451169","count":1434,"preSum":32975},{"ndv":558,"upper":"573DC-157205","lower":"573DC-1520512","count":1432,"preSum":34409},{"ndv":479,"upper":"573DC-1645039","lower":"573DC-157215","count":1435,"preSum":35841},{"ndv":502,"upper":"573DC-1699248","lower":"573DC-1645107","count":1432,"preSum":37276},{"ndv":386,"upper":"573DC-1765589","lower":"573DC-1699271","count":1431,"preSum":38708},{"ndv":395,"upper":"573DC-1820855","lower":"573DC-1765600","count":1436,"preSum":40139},{"ndv":418,"upper":"573DC-1854410","lower":"573DC-1821190","count":1438,"preSum":41575},{"ndv":431,"upper":"573DC-1901899","lower":"573DC-1855257","count":1431,"preSum":43013},{"ndv":440,"upper":"573DC-1961134","lower":"573DC-1901900","count":1434,"preSum":44444},{"ndv":421,"upper":"573DC-2038751","lower":"573DC-1961135","count":1431,"preSum":45878},{"ndv":527,"upper":"573DC-2106231","lower":"573DC-2038796","count":1433,"preSum":47309},{"ndv":383,"upper":"573DC-217799","lower":"573DC-2106232","count":1434,"preSum":48742},{"ndv":396,"upper":"573DC-258641","lower":"573DC-217800","count":1432,"preSum":50176},{"ndv":393,"upper":"573DC-313291","lower":"573DC-258642","count":1432,"preSum":51608},{"ndv":376,"upper":"573DC-362749","lower":"573DC-313292","count":1431,"preSum":53040},{"ndv":401,"upper":"573DC-420319","lower":"573DC-362750","count":1431,"preSum":54471},{"ndv":374,"upper":"573DC-487136","lower":"573DC-420324","count":1432,"preSum":55902},{"ndv":607,"upper":"573DC-550547","lower":"573DC-487153","count":1442,"preSum":57334},{"ndv":340,"upper":"573DC-596935","lower":"573DC-550548","count":1436,"preSum":58776},{"ndv":378,"upper":"573DC-648366","lower":"573DC-596936","count":1432,"preSum":60212},{"ndv":369,"upper":"573DC-694752","lower":"573DC-648367","count":1435,"preSum":61644},{"ndv":455,"upper":"573DC-733744","lower":"573DC-694754","count":1433,"preSum":63079},{"ndv":404,"upper":"573DC-781586","lower":"573DC-7338","count":1433,"preSum":64512},{"ndv":379,"upper":"573DC-824323","lower":"573DC-781587","count":1431,"preSum":65945},{"ndv":570,"upper":"573DC-898052","lower":"573DC-824324","count":1431,"preSum":67376},{"ndv":418,"upper":"573DC-967870","lower":"573DC-898054","count":1434,"preSum":68807},{"ndv":381,"upper":"763DC-112192","lower":"573DC-967872","count":1433,"preSum":70241},{"ndv":594,"upper":"763DC-206447","lower":"763DC-112193","count":1431,"preSum":71674},{"ndv":519,"upper":"763DC-289343","lower":"763DC-206837","count":1432,"preSum":73105},{"ndv":526,"upper":"763DC-372166","lower":"763DC-289344","count":1433,"preSum":74537},{"ndv":620,"upper":"763DC-436528","lower":"763DC-372167","count":1431,"preSum":75970},{"ndv":520,"upper":"763DC-521331","lower":"763DC-436529","count":1432,"preSum":77401},{"ndv":593,"upper":"763DC-609153","lower":"763DC-521332","count":1433,"preSum":78833},{"ndv":566,"upper":"763DC-71175","lower":"763DC-609154","count":1433,"preSum":80266},{"ndv":453,"upper":"SH02-10846","lower":"763DC-71176","count":1434,"preSum":81699},{"ndv":628,"upper":"SH03-136585","lower":"SH02-10847","count":1431,"preSum":83133},{"ndv":1287,"upper":"SH03-274375","lower":"SH03-136586","count":1431,"preSum":84564},{"ndv":1431,"upper":"SH03-414149","lower":"SH03-274376","count":1431,"preSum":85995},{"ndv":1431,"upper":"SH03-567023","lower":"SH03-414150","count":1431,"preSum":87426},{"ndv":1431,"upper":"SH03-770143","lower":"SH03-567024","count":1431,"preSum":88857},{"ndv":1274,"upper":"TEST01-0040","lower":"SH03-770144","count":1284,"preSum":90288}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[33,33,33,33,34,35,34,33,91,37,76,57,60,34],"valueArr":["021DC1-5545","027DC-332936","028DC-38418","573DC-1065143","SH01-42074","SH01-6457","SH03-0299","SH03-0521","SH03-0893","SH03-1085","SH03-2031","SH03-2186","SH03-2354","SH03-2605"],"type":"String","sampleRate":1.0}',1315,0.006721839),('jala_wms_prod','task_detail','referencecontid',301930,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1434,"upper":214704,"lower":2218,"count":1434,"preSum":0},{"ndv":1434,"upper":383240,"lower":218118,"count":1434,"preSum":1434},{"ndv":1434,"upper":581735,"lower":383241,"count":1434,"preSum":2868},{"ndv":1434,"upper":778440,"lower":581736,"count":1434,"preSum":4302},{"ndv":734,"upper":1047528,"lower":778441,"count":1439,"preSum":5736},{"ndv":559,"upper":1107537,"lower":1048010,"count":1435,"preSum":7175},{"ndv":691,"upper":1171292,"lower":1107538,"count":1434,"preSum":8610},{"ndv":758,"upper":1243147,"lower":1171293,"count":1434,"preSum":10044},{"ndv":794,"upper":1332015,"lower":1243745,"count":1434,"preSum":11478},{"ndv":464,"upper":1409720,"lower":1332016,"count":1434,"preSum":12912},{"ndv":566,"upper":1499561,"lower":1409794,"count":1435,"preSum":14346},{"ndv":465,"upper":1552008,"lower":1499562,"count":1434,"preSum":15781},{"ndv":328,"upper":1605207,"lower":1552009,"count":1438,"preSum":17215},{"ndv":550,"upper":1679919,"lower":1605208,"count":1434,"preSum":18653},{"ndv":445,"upper":1738510,"lower":1679920,"count":1434,"preSum":20087},{"ndv":311,"upper":1797654,"lower":1738511,"count":1434,"preSum":21521},{"ndv":402,"upper":1879568,"lower":1797666,"count":1437,"preSum":22955},{"ndv":434,"upper":2013764,"lower":1879569,"count":1434,"preSum":24392},{"ndv":418,"upper":2078294,"lower":2013765,"count":1434,"preSum":25826},{"ndv":426,"upper":2159285,"lower":2078300,"count":1435,"preSum":27260},{"ndv":449,"upper":2226951,"lower":2159286,"count":1435,"preSum":28695},{"ndv":417,"upper":2309875,"lower":2226952,"count":1436,"preSum":30130},{"ndv":476,"upper":2437343,"lower":2309876,"count":1441,"preSum":31566},{"ndv":475,"upper":2495301,"lower":2437347,"count":1438,"preSum":33007},{"ndv":478,"upper":2565803,"lower":2495302,"count":1437,"preSum":34445},{"ndv":378,"upper":2635054,"lower":2565804,"count":1434,"preSum":35882},{"ndv":406,"upper":2699716,"lower":2635055,"count":1434,"preSum":37316},{"ndv":463,"upper":2749808,"lower":2699971,"count":1434,"preSum":38750},{"ndv":376,"upper":2803685,"lower":2749867,"count":1434,"preSum":40184},{"ndv":373,"upper":2869526,"lower":2806144,"count":1436,"preSum":41618},{"ndv":426,"upper":2917296,"lower":2869554,"count":1434,"preSum":43054},{"ndv":557,"upper":3007376,"lower":2917297,"count":1436,"preSum":44488},{"ndv":465,"upper":3072228,"lower":3007377,"count":1442,"preSum":45924},{"ndv":466,"upper":3135637,"lower":3073543,"count":1437,"preSum":47366},{"ndv":441,"upper":3197196,"lower":3135638,"count":1434,"preSum":48803},{"ndv":498,"upper":3263670,"lower":3197356,"count":1434,"preSum":50237},{"ndv":450,"upper":3334656,"lower":3263672,"count":1434,"preSum":51671},{"ndv":508,"upper":3412738,"lower":3334686,"count":1435,"preSum":53105},{"ndv":529,"upper":3505039,"lower":3413643,"count":1439,"preSum":54540},{"ndv":467,"upper":3576410,"lower":3505040,"count":1435,"preSum":55979},{"ndv":525,"upper":3657774,"lower":3576429,"count":1434,"preSum":57414},{"ndv":525,"upper":3749799,"lower":3657775,"count":1434,"preSum":58848},{"ndv":454,"upper":3817916,"lower":3749800,"count":1434,"preSum":60282},{"ndv":460,"upper":3896274,"lower":3817917,"count":1434,"preSum":61716},{"ndv":509,"upper":3972615,"lower":3896469,"count":1437,"preSum":63150},{"ndv":520,"upper":4047012,"lower":3974400,"count":1437,"preSum":64587},{"ndv":548,"upper":4133109,"lower":4047013,"count":1443,"preSum":66024},{"ndv":526,"upper":4202893,"lower":4133121,"count":1456,"preSum":67467},{"ndv":599,"upper":4291494,"lower":4203651,"count":1437,"preSum":68923},{"ndv":499,"upper":4368036,"lower":4291495,"count":1436,"preSum":70360},{"ndv":460,"upper":4438375,"lower":4368037,"count":1434,"preSum":71796},{"ndv":626,"upper":4518564,"lower":4438376,"count":1445,"preSum":73230},{"ndv":496,"upper":4594930,"lower":4521803,"count":1434,"preSum":74675},{"ndv":468,"upper":4659112,"lower":4594931,"count":1435,"preSum":76109},{"ndv":512,"upper":4719514,"lower":4659113,"count":1435,"preSum":77544},{"ndv":535,"upper":4763001,"lower":4719515,"count":1437,"preSum":78979},{"ndv":480,"upper":4815326,"lower":4763002,"count":1435,"preSum":80416},{"ndv":455,"upper":4877364,"lower":4815380,"count":1439,"preSum":81851},{"ndv":514,"upper":4957142,"lower":4877365,"count":1436,"preSum":83290},{"ndv":472,"upper":5021637,"lower":4957143,"count":1435,"preSum":84726},{"ndv":533,"upper":5143477,"lower":5022721,"count":1436,"preSum":86161},{"ndv":533,"upper":5236588,"lower":5143478,"count":1434,"preSum":87597},{"ndv":394,"upper":5292383,"lower":5236734,"count":1436,"preSum":89031},{"ndv":353,"upper":5343888,"lower":5292386,"count":1270,"preSum":90467}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[1315,35,34,91,37,76,34,57,60,34],"valueArr":[0,1027078,1050886,1084714,1091787,1330122,1487370,1625204,2936847,4929438],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','referenceid',144865,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":220,"upper":44872,"lower":114,"count":1462,"preSum":0},{"ndv":272,"upper":77935,"lower":44999,"count":1448,"preSum":1462},{"ndv":250,"upper":200110,"lower":77936,"count":1455,"preSum":2910},{"ndv":328,"upper":242726,"lower":200950,"count":1448,"preSum":4365},{"ndv":292,"upper":410711,"lower":242727,"count":1448,"preSum":5813},{"ndv":342,"upper":471192,"lower":410712,"count":1448,"preSum":7261},{"ndv":182,"upper":1870408,"lower":471193,"count":1448,"preSum":8709},{"ndv":378,"upper":2839666,"lower":1870409,"count":1449,"preSum":10157},{"ndv":575,"upper":3097125,"lower":2841663,"count":1448,"preSum":11606},{"ndv":477,"upper":3478087,"lower":3097661,"count":1448,"preSum":13054},{"ndv":536,"upper":3687674,"lower":3478592,"count":1449,"preSum":14502},{"ndv":471,"upper":3797120,"lower":3687675,"count":1456,"preSum":15951},{"ndv":409,"upper":3865321,"lower":3797125,"count":1458,"preSum":17407},{"ndv":408,"upper":3940660,"lower":3865334,"count":1448,"preSum":18865},{"ndv":543,"upper":4055151,"lower":3941831,"count":1452,"preSum":20313},{"ndv":360,"upper":4113236,"lower":4055207,"count":1448,"preSum":21765},{"ndv":390,"upper":4218845,"lower":4113546,"count":1453,"preSum":23213},{"ndv":406,"upper":4277363,"lower":4218846,"count":1448,"preSum":24666},{"ndv":441,"upper":4453434,"lower":4277367,"count":1450,"preSum":26114},{"ndv":405,"upper":4533162,"lower":4453537,"count":1454,"preSum":27564},{"ndv":434,"upper":4598582,"lower":4534000,"count":1448,"preSum":29018},{"ndv":493,"upper":4662181,"lower":4598691,"count":1448,"preSum":30466},{"ndv":423,"upper":4818717,"lower":4662203,"count":1449,"preSum":31914},{"ndv":551,"upper":4895985,"lower":4818723,"count":1451,"preSum":33363},{"ndv":415,"upper":4976088,"lower":4895990,"count":1448,"preSum":34814},{"ndv":423,"upper":5069787,"lower":4976089,"count":1448,"preSum":36262},{"ndv":366,"upper":5139146,"lower":5069789,"count":1448,"preSum":37710},{"ndv":495,"upper":5213213,"lower":5139281,"count":1448,"preSum":39158},{"ndv":428,"upper":5285359,"lower":5213225,"count":1449,"preSum":40606},{"ndv":353,"upper":5341436,"lower":5285375,"count":1451,"preSum":42055},{"ndv":372,"upper":5397822,"lower":5341478,"count":1449,"preSum":43506},{"ndv":578,"upper":5483172,"lower":5397884,"count":1448,"preSum":44955},{"ndv":494,"upper":5585877,"lower":5484587,"count":1449,"preSum":46403},{"ndv":482,"upper":5663230,"lower":5585888,"count":1448,"preSum":47852},{"ndv":424,"upper":5724645,"lower":5663306,"count":1457,"preSum":49300},{"ndv":483,"upper":5801601,"lower":5724647,"count":1448,"preSum":50757},{"ndv":455,"upper":5877401,"lower":5801640,"count":1451,"preSum":52205},{"ndv":493,"upper":5972762,"lower":5877557,"count":1448,"preSum":53656},{"ndv":495,"upper":6069385,"lower":5972894,"count":1450,"preSum":55104},{"ndv":519,"upper":6152844,"lower":6069435,"count":1451,"preSum":56554},{"ndv":570,"upper":6266067,"lower":6153121,"count":1448,"preSum":58005},{"ndv":509,"upper":6359324,"lower":6266068,"count":1448,"preSum":59453},{"ndv":505,"upper":6436386,"lower":6359878,"count":1451,"preSum":60901},{"ndv":536,"upper":6530430,"lower":6436675,"count":1450,"preSum":62352},{"ndv":505,"upper":6597402,"lower":6530437,"count":1448,"preSum":63802},{"ndv":511,"upper":6667606,"lower":6597519,"count":1449,"preSum":65250},{"ndv":496,"upper":6724225,"lower":6667637,"count":1449,"preSum":66699},{"ndv":490,"upper":6785550,"lower":6724325,"count":1449,"preSum":68148},{"ndv":561,"upper":6876727,"lower":6785601,"count":1449,"preSum":69597},{"ndv":509,"upper":6962849,"lower":6876862,"count":1448,"preSum":71046},{"ndv":528,"upper":7051696,"lower":6962931,"count":1450,"preSum":72494},{"ndv":599,"upper":7140609,"lower":7051697,"count":1449,"preSum":73944},{"ndv":496,"upper":7224382,"lower":7140656,"count":1450,"preSum":75393},{"ndv":473,"upper":7295849,"lower":7224436,"count":1457,"preSum":76843},{"ndv":519,"upper":7366345,"lower":7296343,"count":1448,"preSum":78300},{"ndv":531,"upper":7412465,"lower":7366367,"count":1449,"preSum":79748},{"ndv":462,"upper":7478846,"lower":7412525,"count":1448,"preSum":81197},{"ndv":496,"upper":7550400,"lower":7478847,"count":1453,"preSum":82645},{"ndv":479,"upper":7630601,"lower":7550402,"count":1449,"preSum":84098},{"ndv":518,"upper":7700134,"lower":7631053,"count":1451,"preSum":85547},{"ndv":492,"upper":7811105,"lower":7700144,"count":1448,"preSum":86998},{"ndv":556,"upper":7902595,"lower":7811118,"count":1448,"preSum":88446},{"ndv":441,"upper":7958396,"lower":7903205,"count":1452,"preSum":89894},{"ndv":328,"upper":8017592,"lower":7958433,"count":1265,"preSum":91346}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[253,34,54,65,35,35,34,91,37,76,34,57,60,34],"valueArr":[0,474,100123,200111,300301,1273748,1390070,1841878,2147562,3302918,3744920,3953572,5464080,7610766],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','referencelineid',5188968,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1314,"upper":151343,"lower":188,"count":1455,"preSum":0},{"ndv":1396,"upper":306888,"lower":151344,"count":1455,"preSum":1455},{"ndv":1431,"upper":488373,"lower":306889,"count":1455,"preSum":2910},{"ndv":1455,"upper":758486,"lower":488374,"count":1455,"preSum":4365},{"ndv":1445,"upper":1216297,"lower":758487,"count":1455,"preSum":5820},{"ndv":1446,"upper":1501675,"lower":1216298,"count":1455,"preSum":7275},{"ndv":1313,"upper":3447713,"lower":1507278,"count":1455,"preSum":8730},{"ndv":1289,"upper":4963034,"lower":3447714,"count":1455,"preSum":10185},{"ndv":1448,"upper":5341695,"lower":4963035,"count":1455,"preSum":11640},{"ndv":1397,"upper":5927974,"lower":5342115,"count":1456,"preSum":13095},{"ndv":1451,"upper":6303008,"lower":5927987,"count":1455,"preSum":14551},{"ndv":1431,"upper":6560724,"lower":6303009,"count":1455,"preSum":16006},{"ndv":1444,"upper":6781054,"lower":6561076,"count":1455,"preSum":17461},{"ndv":1432,"upper":7015533,"lower":6781055,"count":1455,"preSum":18916},{"ndv":1421,"upper":7275768,"lower":7015534,"count":1455,"preSum":20371},{"ndv":1447,"upper":7505947,"lower":7275769,"count":1455,"preSum":21826},{"ndv":1451,"upper":7801105,"lower":7505949,"count":1455,"preSum":23281},{"ndv":1450,"upper":8003138,"lower":7801106,"count":1455,"preSum":24736},{"ndv":1454,"upper":8319510,"lower":8003139,"count":1455,"preSum":26191},{"ndv":1450,"upper":8558809,"lower":8319511,"count":1455,"preSum":27646},{"ndv":1416,"upper":8858321,"lower":8560082,"count":1455,"preSum":29101},{"ndv":1437,"upper":9054717,"lower":8858322,"count":1455,"preSum":30556},{"ndv":1450,"upper":9417246,"lower":9055171,"count":1455,"preSum":32011},{"ndv":1451,"upper":9702422,"lower":9417247,"count":1455,"preSum":33466},{"ndv":1445,"upper":9939370,"lower":9707573,"count":1455,"preSum":34921},{"ndv":1428,"upper":10216085,"lower":9939371,"count":1455,"preSum":36376},{"ndv":1435,"upper":10472644,"lower":10216086,"count":1455,"preSum":37831},{"ndv":1450,"upper":10720999,"lower":10472645,"count":1455,"preSum":39286},{"ndv":1452,"upper":10929749,"lower":10721000,"count":1455,"preSum":40741},{"ndv":1447,"upper":11141025,"lower":10929759,"count":1455,"preSum":42196},{"ndv":1451,"upper":11360880,"lower":11141026,"count":1455,"preSum":43651},{"ndv":1450,"upper":11586440,"lower":11360882,"count":1455,"preSum":45106},{"ndv":1442,"upper":11877933,"lower":11586443,"count":1455,"preSum":46561},{"ndv":1448,"upper":12151045,"lower":11877934,"count":1455,"preSum":48016},{"ndv":1450,"upper":12388217,"lower":12151046,"count":1455,"preSum":49471},{"ndv":1444,"upper":12618074,"lower":12388218,"count":1455,"preSum":50926},{"ndv":1443,"upper":12846264,"lower":12618075,"count":1455,"preSum":52381},{"ndv":1435,"upper":13098436,"lower":12846265,"count":1455,"preSum":53836},{"ndv":1453,"upper":13382345,"lower":13098437,"count":1455,"preSum":55291},{"ndv":1452,"upper":13625816,"lower":13382346,"count":1455,"preSum":56746},{"ndv":1453,"upper":13897812,"lower":13625817,"count":1455,"preSum":58201},{"ndv":1454,"upper":14240202,"lower":13897813,"count":1455,"preSum":59656},{"ndv":1453,"upper":14474600,"lower":14240203,"count":1455,"preSum":61111},{"ndv":1454,"upper":14763881,"lower":14474601,"count":1455,"preSum":62566},{"ndv":1440,"upper":14953363,"lower":14763882,"count":1455,"preSum":64021},{"ndv":1453,"upper":15174346,"lower":14953364,"count":1455,"preSum":65476},{"ndv":1448,"upper":15344798,"lower":15174347,"count":1455,"preSum":66931},{"ndv":1452,"upper":15539524,"lower":15344802,"count":1455,"preSum":68386},{"ndv":1445,"upper":15783351,"lower":15539624,"count":1455,"preSum":69841},{"ndv":1452,"upper":16045373,"lower":15783538,"count":1455,"preSum":71296},{"ndv":1448,"upper":16277133,"lower":16045523,"count":1455,"preSum":72751},{"ndv":1447,"upper":16559676,"lower":16277774,"count":1455,"preSum":74206},{"ndv":1448,"upper":16789279,"lower":16559681,"count":1455,"preSum":75661},{"ndv":1437,"upper":17007019,"lower":16789280,"count":1455,"preSum":77116},{"ndv":1437,"upper":17241088,"lower":17007660,"count":1455,"preSum":78571},{"ndv":1452,"upper":17392531,"lower":17241089,"count":1455,"preSum":80026},{"ndv":1449,"upper":17570614,"lower":17392532,"count":1455,"preSum":81481},{"ndv":1441,"upper":17781243,"lower":17570615,"count":1455,"preSum":82936},{"ndv":1437,"upper":18016613,"lower":17781244,"count":1455,"preSum":84391},{"ndv":1452,"upper":18249987,"lower":18016627,"count":1455,"preSum":85846},{"ndv":1444,"upper":18567485,"lower":18249988,"count":1455,"preSum":87301},{"ndv":1453,"upper":18843721,"lower":18567486,"count":1455,"preSum":88756},{"ndv":1451,"upper":19060568,"lower":18843722,"count":1455,"preSum":90211},{"ndv":1413,"upper":19324995,"lower":19060569,"count":1417,"preSum":91666}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[253,14,14,11,19,10,13,32,20,11,17,13],"valueArr":[0,104129,3034168,3088828,3108302,3363490,3488695,5659996,5884049,6467576,13068173,17054654],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','referenceordertype',45,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"","lower":"","count":1,"preSum":0},{"ndv":1,"upper":"BFCK","lower":"BFCK","count":1,"preSum":1},{"ndv":1,"upper":"WWCK","lower":"WWCK","count":5,"preSum":2}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[176,6626,945,231,75835,6,9,11,606,7558,56,6,60,63],"valueArr":["261","B2BCK","DBCK","DBRK","JYCK","NB","PKCK","PTCK","QTCK","THRK","UB","XSCK","ZOR","ZRE"],"type":"String","sampleRate":1.0}',1315,0.006721839),('jala_wms_prod','task_detail','referencereqid',7371496,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1441,"upper":70286,"lower":97,"count":1462,"preSum":0},{"ndv":1462,"upper":149771,"lower":70287,"count":1462,"preSum":1462},{"ndv":1462,"upper":284702,"lower":149772,"count":1462,"preSum":2924},{"ndv":1459,"upper":376039,"lower":284703,"count":1462,"preSum":4386},{"ndv":1440,"upper":533517,"lower":376046,"count":1462,"preSum":5848},{"ndv":1462,"upper":683770,"lower":533526,"count":1462,"preSum":7310},{"ndv":1459,"upper":792138,"lower":683771,"count":1462,"preSum":8772},{"ndv":1462,"upper":1008790,"lower":792139,"count":1462,"preSum":10234},{"ndv":1459,"upper":1139326,"lower":1008792,"count":1462,"preSum":11696},{"ndv":1462,"upper":1281283,"lower":1139327,"count":1462,"preSum":13158},{"ndv":1462,"upper":1506181,"lower":1281284,"count":1462,"preSum":14620},{"ndv":1462,"upper":1753320,"lower":1506182,"count":1462,"preSum":16082},{"ndv":1462,"upper":2013973,"lower":1753324,"count":1462,"preSum":17544},{"ndv":1462,"upper":2262729,"lower":2013974,"count":1462,"preSum":19006},{"ndv":1462,"upper":2521508,"lower":2262738,"count":1462,"preSum":20468},{"ndv":1462,"upper":2765485,"lower":2521509,"count":1462,"preSum":21930},{"ndv":1462,"upper":3032930,"lower":2765486,"count":1462,"preSum":23392},{"ndv":1462,"upper":3289729,"lower":3032941,"count":1462,"preSum":24854},{"ndv":1462,"upper":3689597,"lower":3289730,"count":1462,"preSum":26316},{"ndv":1462,"upper":3964538,"lower":3689598,"count":1462,"preSum":27778},{"ndv":1462,"upper":4299089,"lower":3964539,"count":1462,"preSum":29240},{"ndv":1462,"upper":4472738,"lower":4301137,"count":1462,"preSum":30702},{"ndv":1462,"upper":4837310,"lower":4472739,"count":1462,"preSum":32164},{"ndv":1462,"upper":5151572,"lower":4837317,"count":1462,"preSum":33626},{"ndv":1462,"upper":5394686,"lower":5151586,"count":1462,"preSum":35088},{"ndv":1462,"upper":5634068,"lower":5394687,"count":1462,"preSum":36550},{"ndv":1462,"upper":5893372,"lower":5634080,"count":1462,"preSum":38012},{"ndv":1462,"upper":6169221,"lower":5897118,"count":1462,"preSum":39474},{"ndv":1462,"upper":6365525,"lower":6169222,"count":1462,"preSum":40936},{"ndv":1462,"upper":6579158,"lower":6365526,"count":1462,"preSum":42398},{"ndv":1462,"upper":6841709,"lower":6579159,"count":1462,"preSum":43860},{"ndv":1462,"upper":7129202,"lower":6841710,"count":1462,"preSum":45322},{"ndv":1462,"upper":7411464,"lower":7129203,"count":1462,"preSum":46784},{"ndv":1462,"upper":7681791,"lower":7411466,"count":1462,"preSum":48246},{"ndv":1462,"upper":7933796,"lower":7681803,"count":1462,"preSum":49708},{"ndv":1462,"upper":8197217,"lower":7933797,"count":1462,"preSum":51170},{"ndv":1462,"upper":8444334,"lower":8197218,"count":1462,"preSum":52632},{"ndv":1462,"upper":8698227,"lower":8444335,"count":1462,"preSum":54094},{"ndv":1462,"upper":8982254,"lower":8698228,"count":1462,"preSum":55556},{"ndv":1462,"upper":9202411,"lower":8982255,"count":1462,"preSum":57018},{"ndv":1462,"upper":9439737,"lower":9204262,"count":1462,"preSum":58480},{"ndv":1462,"upper":9755378,"lower":9439738,"count":1462,"preSum":59942},{"ndv":1462,"upper":10021499,"lower":9755386,"count":1462,"preSum":61404},{"ndv":1462,"upper":10348885,"lower":10021503,"count":1462,"preSum":62866},{"ndv":1462,"upper":10635761,"lower":10348890,"count":1462,"preSum":64328},{"ndv":1462,"upper":10900950,"lower":10635764,"count":1462,"preSum":65790},{"ndv":1462,"upper":11162486,"lower":10900956,"count":1462,"preSum":67252},{"ndv":1462,"upper":11416429,"lower":11162487,"count":1462,"preSum":68714},{"ndv":1462,"upper":11721639,"lower":11416430,"count":1462,"preSum":70176},{"ndv":1462,"upper":11973535,"lower":11721640,"count":1462,"preSum":71638},{"ndv":1462,"upper":12233669,"lower":11973544,"count":1462,"preSum":73100},{"ndv":1462,"upper":12519531,"lower":12233678,"count":1462,"preSum":74562},{"ndv":1462,"upper":12773589,"lower":12519532,"count":1462,"preSum":76024},{"ndv":1462,"upper":13010161,"lower":12773595,"count":1462,"preSum":77486},{"ndv":1462,"upper":13236633,"lower":13010167,"count":1462,"preSum":78948},{"ndv":1462,"upper":13390470,"lower":13236653,"count":1462,"preSum":80410},{"ndv":1462,"upper":13580953,"lower":13390473,"count":1462,"preSum":81872},{"ndv":1462,"upper":13799677,"lower":13580968,"count":1462,"preSum":83334},{"ndv":1462,"upper":14053747,"lower":13799678,"count":1462,"preSum":84796},{"ndv":1462,"upper":14320644,"lower":14053748,"count":1462,"preSum":86258},{"ndv":1462,"upper":14712425,"lower":14320645,"count":1462,"preSum":87720},{"ndv":1462,"upper":14991729,"lower":14712426,"count":1462,"preSum":89182},{"ndv":1462,"upper":15245121,"lower":14991994,"count":1462,"preSum":90644},{"ndv":1404,"upper":15487031,"lower":15245122,"count":1404,"preSum":92106}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}',null,0,0.006721839); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('jala_wms_prod','task_detail','relayat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','relayby',14,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"daishanlin","lower":"daishanlin","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[4,6,10,53,48,12,11,8,72,7,10,7,3],"valueArr":["02700028","02700029","02700030","CSS","MQ","PAH","WHW","ZBZ","chenshigang","gzj","lbt","lxp","zlw"],"type":"String","sampleRate":1.0}',93257,0.006721839),('jala_wms_prod','task_detail','shelflifests',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[38,93472],"valueArr":["GQ","ZC"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','status',17,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":100,"lower":100,"count":1,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93509],"valueArr":[900],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','taskcode',147958,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":259,"upper":"10198927","lower":"10000499","count":1451,"preSum":0},{"ndv":183,"upper":"10390036","lower":"102","count":1457,"preSum":1451},{"ndv":220,"upper":"10614135","lower":"10395235","count":1454,"preSum":2908},{"ndv":244,"upper":"10817729","lower":"10617652","count":1451,"preSum":4362},{"ndv":343,"upper":"11036103","lower":"108207","count":1457,"preSum":5813},{"ndv":195,"upper":"11253348","lower":"11042164","count":1452,"preSum":7270},{"ndv":202,"upper":"11449178","lower":"11257134","count":1467,"preSum":8722},{"ndv":248,"upper":"11704130","lower":"11449876","count":1454,"preSum":10189},{"ndv":155,"upper":"11930576","lower":"11705143","count":1504,"preSum":11643},{"ndv":265,"upper":"12188982","lower":"1193068","count":1455,"preSum":13147},{"ndv":196,"upper":"12407592","lower":"12194977","count":1467,"preSum":14602},{"ndv":224,"upper":"12629825","lower":"124155","count":1462,"preSum":16069},{"ndv":162,"upper":"12848229","lower":"12644970","count":1451,"preSum":17531},{"ndv":100,"upper":"13083256","lower":"12849832","count":1449,"preSum":18982},{"ndv":105,"upper":"13295348","lower":"13086950","count":1455,"preSum":20431},{"ndv":116,"upper":"13562589","lower":"13296552","count":1461,"preSum":21886},{"ndv":111,"upper":"13816286","lower":"13568345","count":1456,"preSum":23347},{"ndv":103,"upper":"14053478","lower":"13831585","count":1450,"preSum":24803},{"ndv":146,"upper":"14303386","lower":"14073614","count":1468,"preSum":26253},{"ndv":107,"upper":"14568761","lower":"14305443","count":1467,"preSum":27721},{"ndv":116,"upper":"14767677","lower":"14568771","count":1459,"preSum":29188},{"ndv":123,"upper":"14977599","lower":"14767765","count":1468,"preSum":30647},{"ndv":101,"upper":"15122499","lower":"149776","count":1453,"preSum":32115},{"ndv":75,"upper":"15306392","lower":"15133095","count":1455,"preSum":33568},{"ndv":134,"upper":"15512161","lower":"15309654","count":1449,"preSum":35023},{"ndv":90,"upper":"15786457","lower":"15513336","count":1466,"preSum":36472},{"ndv":140,"upper":"15983726","lower":"15787761","count":1467,"preSum":37938},{"ndv":89,"upper":"16356747","lower":"15999799","count":1459,"preSum":39405},{"ndv":86,"upper":"16638793","lower":"16360114","count":1461,"preSum":40864},{"ndv":78,"upper":"16883366","lower":"16652040","count":1474,"preSum":42325},{"ndv":234,"upper":"1797","lower":"16883537","count":1463,"preSum":43799},{"ndv":589,"upper":"2462706","lower":"1800000289-2","count":1461,"preSum":45262},{"ndv":462,"upper":"284498","lower":"2465233","count":1448,"preSum":46723},{"ndv":349,"upper":"3191059","lower":"284499","count":1456,"preSum":48171},{"ndv":258,"upper":"3393643","lower":"3191098","count":1450,"preSum":49627},{"ndv":409,"upper":"3653871","lower":"3393648","count":1448,"preSum":51077},{"ndv":309,"upper":"3863580","lower":"365570","count":1452,"preSum":52525},{"ndv":263,"upper":"4059899","lower":"3864886","count":1454,"preSum":53977},{"ndv":255,"upper":"4242452","lower":"4059913","count":1450,"preSum":55431},{"ndv":362,"upper":"4448389","lower":"4244158","count":1456,"preSum":56881},{"ndv":160,"upper":"4678498","lower":"4448802","count":1454,"preSum":58337},{"ndv":126,"upper":"4908479","lower":"4678537","count":1457,"preSum":59791},{"ndv":262,"upper":"5105913","lower":"4913459","count":1449,"preSum":61248},{"ndv":225,"upper":"5366723","lower":"5107194","count":1451,"preSum":62697},{"ndv":203,"upper":"5581363","lower":"5371748","count":1457,"preSum":64148},{"ndv":342,"upper":"5820736","lower":"5581641","count":1449,"preSum":65605},{"ndv":233,"upper":"6036552","lower":"5824033","count":1458,"preSum":67054},{"ndv":207,"upper":"6294055","lower":"6039775","count":1454,"preSum":68512},{"ndv":253,"upper":"6507935","lower":"6294315","count":1451,"preSum":69966},{"ndv":175,"upper":"669039","lower":"6510987","count":1448,"preSum":71417},{"ndv":297,"upper":"7014270","lower":"669040","count":1455,"preSum":72865},{"ndv":320,"upper":"7319325","lower":"7024139","count":1464,"preSum":74320},{"ndv":246,"upper":"7516125","lower":"7321888","count":1460,"preSum":75784},{"ndv":252,"upper":"7751936","lower":"7520497","count":1462,"preSum":77244},{"ndv":230,"upper":"7983777","lower":"7752559","count":1466,"preSum":78706},{"ndv":176,"upper":"8217179","lower":"7987534","count":1449,"preSum":80172},{"ndv":159,"upper":"8424806","lower":"8221388","count":1464,"preSum":81621},{"ndv":79,"upper":"8636798","lower":"8425252","count":1450,"preSum":83085},{"ndv":88,"upper":"8871894","lower":"8637305","count":1452,"preSum":84535},{"ndv":100,"upper":"9079750","lower":"8874254","count":1451,"preSum":85987},{"ndv":99,"upper":"9345836","lower":"9079764","count":1451,"preSum":87438},{"ndv":106,"upper":"9611755","lower":"9345952","count":1449,"preSum":88889},{"ndv":106,"upper":"9862503","lower":"9612095","count":1469,"preSum":90338},{"ndv":56,"upper":"W028法规品调拨福利仓明细0328","lower":"9864903","count":825,"preSum":91807}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[71,88,93,94,68,97,91,76,66,66,68],"valueArr":["11920561","12084122","12517314","12709077","12892750","13755999","202210自然堂品牌-销售因素退货1127","202302自然堂品牌-销售因素退货","6481910","7591204","8631913"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','taskid',148021,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":352,"upper":67222,"lower":2016,"count":1448,"preSum":0},{"ndv":1034,"upper":193620,"lower":67223,"count":1448,"preSum":1448},{"ndv":1285,"upper":359609,"lower":193621,"count":1448,"preSum":2896},{"ndv":951,"upper":465131,"lower":359610,"count":1474,"preSum":4344},{"ndv":989,"upper":610971,"lower":465132,"count":1448,"preSum":5818},{"ndv":325,"upper":658795,"lower":610972,"count":1462,"preSum":7266},{"ndv":372,"upper":705935,"lower":658815,"count":1464,"preSum":8728},{"ndv":434,"upper":767415,"lower":705937,"count":1448,"preSum":10192},{"ndv":368,"upper":805798,"lower":767612,"count":1451,"preSum":11640},{"ndv":229,"upper":833445,"lower":805953,"count":1449,"preSum":13091},{"ndv":202,"upper":846540,"lower":833446,"count":1466,"preSum":14540},{"ndv":89,"upper":854463,"lower":846708,"count":1461,"preSum":16006},{"ndv":98,"upper":867898,"lower":854641,"count":1459,"preSum":17467},{"ndv":181,"upper":880489,"lower":868477,"count":1458,"preSum":18926},{"ndv":98,"upper":892011,"lower":881082,"count":1478,"preSum":20384},{"ndv":91,"upper":907634,"lower":892336,"count":1466,"preSum":21862},{"ndv":146,"upper":917823,"lower":907635,"count":1448,"preSum":23328},{"ndv":98,"upper":1006432,"lower":917828,"count":1464,"preSum":24776},{"ndv":91,"upper":1016206,"lower":1006888,"count":1461,"preSum":26240},{"ndv":65,"upper":1019412,"lower":1016395,"count":1458,"preSum":27701},{"ndv":72,"upper":1023535,"lower":1019439,"count":1449,"preSum":29159},{"ndv":87,"upper":1102129,"lower":1023539,"count":1459,"preSum":30608},{"ndv":107,"upper":1114426,"lower":1102130,"count":1449,"preSum":32067},{"ndv":206,"upper":1129196,"lower":1115726,"count":1453,"preSum":33516},{"ndv":97,"upper":1145297,"lower":1129337,"count":1471,"preSum":34969},{"ndv":125,"upper":1156434,"lower":1146465,"count":1453,"preSum":36440},{"ndv":148,"upper":1168753,"lower":1156973,"count":1452,"preSum":37893},{"ndv":102,"upper":1180934,"lower":1169107,"count":1457,"preSum":39345},{"ndv":84,"upper":1190739,"lower":1181194,"count":1455,"preSum":40802},{"ndv":150,"upper":1204137,"lower":1191308,"count":1449,"preSum":42257},{"ndv":174,"upper":1213453,"lower":1204140,"count":1456,"preSum":43706},{"ndv":194,"upper":1226011,"lower":1213945,"count":1464,"preSum":45162},{"ndv":122,"upper":1240294,"lower":1226013,"count":1456,"preSum":46626},{"ndv":168,"upper":1248766,"lower":1240465,"count":1452,"preSum":48082},{"ndv":133,"upper":1262704,"lower":1249263,"count":1468,"preSum":49534},{"ndv":137,"upper":1277693,"lower":1262705,"count":1475,"preSum":51002},{"ndv":147,"upper":1294178,"lower":1277947,"count":1456,"preSum":52477},{"ndv":172,"upper":1310990,"lower":1294513,"count":1451,"preSum":53933},{"ndv":144,"upper":1320297,"lower":1311484,"count":1472,"preSum":55384},{"ndv":96,"upper":1327029,"lower":1320773,"count":1471,"preSum":56856},{"ndv":108,"upper":1337186,"lower":1327761,"count":1464,"preSum":58327},{"ndv":87,"upper":1342521,"lower":1337261,"count":1461,"preSum":59791},{"ndv":65,"upper":1344069,"lower":1342522,"count":1467,"preSum":61252},{"ndv":98,"upper":1347700,"lower":1344089,"count":1460,"preSum":62719},{"ndv":64,"upper":1350478,"lower":1347718,"count":1470,"preSum":64179},{"ndv":76,"upper":1352823,"lower":1350544,"count":1450,"preSum":65649},{"ndv":76,"upper":1356638,"lower":1352934,"count":1453,"preSum":67099},{"ndv":81,"upper":1363230,"lower":1356639,"count":1461,"preSum":68552},{"ndv":91,"upper":1373639,"lower":1363241,"count":1448,"preSum":70013},{"ndv":85,"upper":1383918,"lower":1373640,"count":1448,"preSum":71461},{"ndv":162,"upper":1404280,"lower":1383929,"count":1462,"preSum":72909},{"ndv":210,"upper":1416716,"lower":1404391,"count":1454,"preSum":74371},{"ndv":119,"upper":1436425,"lower":1416717,"count":1458,"preSum":75825},{"ndv":171,"upper":1449090,"lower":1437131,"count":1451,"preSum":77283},{"ndv":138,"upper":1460324,"lower":1449125,"count":1472,"preSum":78734},{"ndv":131,"upper":1467566,"lower":1460656,"count":1455,"preSum":80206},{"ndv":161,"upper":1484042,"lower":1467627,"count":1468,"preSum":81661},{"ndv":84,"upper":1495188,"lower":1484099,"count":1448,"preSum":83129},{"ndv":89,"upper":1505823,"lower":1495479,"count":1468,"preSum":84577},{"ndv":78,"upper":1513015,"lower":1505838,"count":1476,"preSum":86045},{"ndv":118,"upper":1522258,"lower":1513305,"count":1450,"preSum":87521},{"ndv":127,"upper":1527925,"lower":1522419,"count":1455,"preSum":88971},{"ndv":88,"upper":1532928,"lower":1527965,"count":1461,"preSum":90426},{"ndv":37,"upper":1536214,"lower":1533039,"count":745,"preSum":91887}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[91,76,66,66,68,71,88,93,94,68,97],"valueArr":[364819,761896,1018808,1125329,1182413,1342524,1343111,1348128,1349914,1352108,1374468],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','tasktype',6,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[36670,8416,7858,253,39251,1062],"valueArr":["BATCH_PICK","ORDER_PICK","PUTAWAY","REPLENISHMENT","Sorting_while_picking","TRANSFER"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','toinventoryid',83952,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":133,"upper":161435,"lower":41775,"count":142,"preSum":0},{"ndv":118,"upper":251690,"lower":170377,"count":145,"preSum":142},{"ndv":93,"upper":279463,"lower":251692,"count":142,"preSum":287},{"ndv":90,"upper":298796,"lower":279467,"count":142,"preSum":429},{"ndv":97,"upper":366667,"lower":298857,"count":142,"preSum":571},{"ndv":68,"upper":377536,"lower":367000,"count":142,"preSum":713},{"ndv":83,"upper":391776,"lower":377537,"count":146,"preSum":855},{"ndv":60,"upper":406448,"lower":391781,"count":143,"preSum":1001},{"ndv":58,"upper":425385,"lower":406452,"count":145,"preSum":1144},{"ndv":62,"upper":444869,"lower":425387,"count":145,"preSum":1289},{"ndv":71,"upper":464958,"lower":445136,"count":143,"preSum":1434},{"ndv":69,"upper":495902,"lower":465119,"count":144,"preSum":1577},{"ndv":83,"upper":509974,"lower":495904,"count":142,"preSum":1721},{"ndv":50,"upper":536926,"lower":509977,"count":142,"preSum":1863},{"ndv":69,"upper":558363,"lower":536933,"count":144,"preSum":2005},{"ndv":62,"upper":573659,"lower":558365,"count":145,"preSum":2149},{"ndv":77,"upper":607108,"lower":573661,"count":143,"preSum":2294},{"ndv":68,"upper":642868,"lower":607110,"count":142,"preSum":2437},{"ndv":89,"upper":663740,"lower":643133,"count":142,"preSum":2579},{"ndv":91,"upper":680179,"lower":663742,"count":142,"preSum":2721},{"ndv":91,"upper":691791,"lower":680188,"count":144,"preSum":2863},{"ndv":104,"upper":705543,"lower":691796,"count":142,"preSum":3007},{"ndv":92,"upper":729967,"lower":705544,"count":142,"preSum":3149},{"ndv":99,"upper":775861,"lower":730033,"count":142,"preSum":3291},{"ndv":85,"upper":786435,"lower":775981,"count":143,"preSum":3433},{"ndv":96,"upper":820639,"lower":786441,"count":144,"preSum":3576},{"ndv":93,"upper":855449,"lower":820665,"count":142,"preSum":3720},{"ndv":89,"upper":889242,"lower":855647,"count":143,"preSum":3862},{"ndv":81,"upper":1007127,"lower":889246,"count":144,"preSum":4005},{"ndv":100,"upper":1027960,"lower":1007129,"count":142,"preSum":4149},{"ndv":110,"upper":1058536,"lower":1027961,"count":142,"preSum":4291},{"ndv":93,"upper":1092268,"lower":1058538,"count":142,"preSum":4433},{"ndv":99,"upper":1127953,"lower":1092269,"count":142,"preSum":4575},{"ndv":89,"upper":1146773,"lower":1127993,"count":142,"preSum":4717},{"ndv":97,"upper":1180635,"lower":1146780,"count":146,"preSum":4859},{"ndv":96,"upper":1225733,"lower":1180637,"count":142,"preSum":5005},{"ndv":120,"upper":1241414,"lower":1225738,"count":142,"preSum":5147},{"ndv":105,"upper":1274387,"lower":1241942,"count":143,"preSum":5289},{"ndv":99,"upper":1313349,"lower":1274508,"count":143,"preSum":5432},{"ndv":91,"upper":1334321,"lower":1313354,"count":142,"preSum":5575},{"ndv":82,"upper":1368741,"lower":1334869,"count":142,"preSum":5717},{"ndv":124,"upper":1382631,"lower":1368743,"count":143,"preSum":5859},{"ndv":117,"upper":1408420,"lower":1382934,"count":142,"preSum":6002},{"ndv":98,"upper":1441605,"lower":1408422,"count":142,"preSum":6144},{"ndv":98,"upper":1479703,"lower":1445005,"count":142,"preSum":6286},{"ndv":115,"upper":1525133,"lower":1479739,"count":142,"preSum":6428},{"ndv":99,"upper":1597755,"lower":1525487,"count":142,"preSum":6570},{"ndv":116,"upper":1664818,"lower":1597757,"count":142,"preSum":6712},{"ndv":102,"upper":1803692,"lower":1666791,"count":142,"preSum":6854},{"ndv":138,"upper":1903877,"lower":1803826,"count":142,"preSum":6996},{"ndv":97,"upper":1938456,"lower":1903878,"count":142,"preSum":7138},{"ndv":92,"upper":1998394,"lower":1938460,"count":142,"preSum":7280},{"ndv":107,"upper":2069197,"lower":1998396,"count":142,"preSum":7422},{"ndv":95,"upper":2101632,"lower":2073000,"count":142,"preSum":7564},{"ndv":100,"upper":2134175,"lower":2101674,"count":142,"preSum":7706},{"ndv":100,"upper":2183016,"lower":2134176,"count":143,"preSum":7848},{"ndv":87,"upper":2233152,"lower":2183033,"count":142,"preSum":7991},{"ndv":103,"upper":2271509,"lower":2233154,"count":143,"preSum":8133},{"ndv":93,"upper":2386620,"lower":2271511,"count":142,"preSum":8276},{"ndv":79,"upper":2403829,"lower":2386622,"count":143,"preSum":8418},{"ndv":96,"upper":2455824,"lower":2403833,"count":143,"preSum":8561},{"ndv":108,"upper":2497144,"lower":2455826,"count":142,"preSum":8704},{"ndv":95,"upper":2557725,"lower":2497145,"count":144,"preSum":8846},{"ndv":36,"upper":2569872,"lower":2557784,"count":40,"preSum":8990}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[84337,12,13,12,11,12,11,13,15,12,20,12],"valueArr":[0,45705,405438,406483,425089,426283,463313,495918,782477,1046033,2073119,2469569],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','toloc',7072,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":10,"upper":"3QA0408","lower":"021DCQQ-M12-01-01-01","count":15,"preSum":0},{"ndv":9,"upper":"3QD0506","lower":"3QA0411","count":16,"preSum":15},{"ndv":14,"upper":"A0105","lower":"3QD0511","count":15,"preSum":31},{"ndv":15,"upper":"A0326","lower":"A0110","count":15,"preSum":46},{"ndv":15,"upper":"A0511","lower":"A0330","count":15,"preSum":61},{"ndv":14,"upper":"B0615","lower":"A0709","count":15,"preSum":76},{"ndv":9,"upper":"B0713","lower":"B0617","count":15,"preSum":91},{"ndv":13,"upper":"B1202","lower":"B0723","count":15,"preSum":106},{"ndv":12,"upper":"BT1-02-A29","lower":"B1203","count":15,"preSum":121},{"ndv":11,"upper":"BT1-07-A11","lower":"BT1-02-A33","count":15,"preSum":136},{"ndv":12,"upper":"C-03-032","lower":"BT1-07-A15","count":15,"preSum":151},{"ndv":11,"upper":"CH-0511C2","lower":"C-04-108","count":15,"preSum":166},{"ndv":13,"upper":"CH-0619E10","lower":"CH-0511D3","count":15,"preSum":181},{"ndv":10,"upper":"D002-QM001","lower":"CLS-02-A36","count":16,"preSum":196},{"ndv":12,"upper":"D0300","lower":"D0116","count":15,"preSum":212},{"ndv":14,"upper":"D0347","lower":"D0301","count":15,"preSum":227},{"ndv":13,"upper":"D0443","lower":"D0350","count":15,"preSum":242},{"ndv":14,"upper":"D0533","lower":"D0503","count":15,"preSum":257},{"ndv":10,"upper":"D0644","lower":"D0534","count":15,"preSum":272},{"ndv":9,"upper":"DD06","lower":"D0645","count":21,"preSum":287},{"ndv":8,"upper":"DL02-1","lower":"DH02-03","count":17,"preSum":308},{"ndv":13,"upper":"DL10-2","lower":"DL02-3","count":15,"preSum":325},{"ndv":7,"upper":"DL13-3","lower":"DL11-1","count":15,"preSum":340},{"ndv":6,"upper":"JALASH","lower":"DL14-2","count":15,"preSum":355},{"ndv":5,"upper":"T03-02","lower":"QZ001","count":16,"preSum":370},{"ndv":6,"upper":"T03-14","lower":"T03-03","count":17,"preSum":386},{"ndv":5,"upper":"T03-22","lower":"T03-15","count":15,"preSum":403},{"ndv":5,"upper":"T03-27","lower":"T03-23","count":15,"preSum":418},{"ndv":4,"upper":"T03-31","lower":"T03-28","count":15,"preSum":433},{"ndv":6,"upper":"T04-08","lower":"T03-32","count":18,"preSum":448},{"ndv":6,"upper":"T04-30","lower":"T04-09","count":19,"preSum":466},{"ndv":5,"upper":"T05-08","lower":"T05-01","count":15,"preSum":485},{"ndv":9,"upper":"T05-27","lower":"T05-12","count":15,"preSum":500},{"ndv":8,"upper":"T06-04","lower":"T05-31","count":16,"preSum":515},{"ndv":5,"upper":"T06-14","lower":"T06-07","count":18,"preSum":531},{"ndv":6,"upper":"T07-01","lower":"T06-16","count":16,"preSum":549},{"ndv":5,"upper":"T07-14","lower":"T07-03","count":15,"preSum":565},{"ndv":6,"upper":"T07-24","lower":"T07-15","count":15,"preSum":580},{"ndv":5,"upper":"T07-34","lower":"T07-28","count":15,"preSum":595},{"ndv":7,"upper":"T08-27","lower":"T08-02","count":15,"preSum":610},{"ndv":8,"upper":"T09-17","lower":"T08-28","count":19,"preSum":625},{"ndv":7,"upper":"T11-24","lower":"T09-18","count":16,"preSum":644},{"ndv":5,"upper":"T13-35","lower":"T12-15","count":15,"preSum":660},{"ndv":12,"upper":"TH04-19-02","lower":"T13-50","count":15,"preSum":675},{"ndv":11,"upper":"TH07-11-01","lower":"TH04-21-01","count":15,"preSum":690},{"ndv":12,"upper":"TH08-03-02","lower":"TH07-14-02","count":16,"preSum":705},{"ndv":11,"upper":"TH09-02-02","lower":"TH08-04-02","count":16,"preSum":721},{"ndv":6,"upper":"TH09-09-01","lower":"TH09-04-02","count":15,"preSum":737},{"ndv":10,"upper":"TH10-02-02","lower":"TH09-09-02","count":19,"preSum":752},{"ndv":10,"upper":"TH11-04-01","lower":"TH10-03-02","count":15,"preSum":771},{"ndv":2,"upper":"TH11-05-02","lower":"TH11-04-02","count":15,"preSum":786},{"ndv":12,"upper":"TH12-09-02","lower":"TH11-06-02","count":15,"preSum":801},{"ndv":6,"upper":"TH13-03-02","lower":"TH12-16-01","count":15,"preSum":816},{"ndv":12,"upper":"TH14-14-02","lower":"TH13-05-01","count":16,"preSum":831},{"ndv":12,"upper":"TH15-13-01","lower":"TH14-19-01","count":15,"preSum":847},{"ndv":11,"upper":"TH16-24-01","lower":"TH15-14-01","count":15,"preSum":862},{"ndv":9,"upper":"TH17-08-02","lower":"TH16-24-02","count":16,"preSum":877},{"ndv":13,"upper":"TH18-14-01","lower":"TH17-21-02","count":15,"preSum":893},{"ndv":14,"upper":"TH20-03-01","lower":"TH18-14-02","count":17,"preSum":908},{"ndv":4,"upper":"TH27-06-02","lower":"TH20-04-03","count":6,"preSum":925}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[28,31,65,22,17,64,11,339,12,17,798,6826,12],"valueArr":["021DCQQ-SS03-08-127","1Z-10A45","2C-TH","2QB09","763DCA-XYTB2B-SH01","763DCA-XYTB2C-SH01","D002-QZ001","LOST12","T03-19","T12-01","T15-25","TH01","ZWY01"],"type":"String","sampleRate":1.0}',84337,0.006721839),('jala_wms_prod','task_detail','tolpn',2192,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"021DC1-0033","lower":",","count":2,"preSum":0},{"ndv":2,"upper":"0220909HH0005","lower":"021DC1-0039","count":2,"preSum":2},{"ndv":2,"upper":"0220909HI0007","lower":"0220909HI0006","count":2,"preSum":4},{"ndv":2,"upper":"0220913HB0007","lower":"0220912HB000S","count":2,"preSum":6},{"ndv":2,"upper":"0220926HG0004","lower":"0220925HH0015","count":2,"preSum":8},{"ndv":2,"upper":"0220927HY0014","lower":"0220926HQ0004","count":2,"preSum":10},{"ndv":2,"upper":"0220929H20002","lower":"0220927HY0015","count":2,"preSum":12},{"ndv":2,"upper":"0221004HA0002","lower":"0220930HZ0014","count":2,"preSum":14},{"ndv":2,"upper":"0221004HS0002","lower":"0221004HD0010","count":2,"preSum":16},{"ndv":2,"upper":"0221005HA0015","lower":"0221004HZ0010","count":2,"preSum":18},{"ndv":2,"upper":"0221017L30003","lower":"0221005HZ0004","count":2,"preSum":20},{"ndv":2,"upper":"0221022HB0011","lower":"0221018S30002","count":2,"preSum":22},{"ndv":2,"upper":"0221025HI0008","lower":"0221023HS0003","count":2,"preSum":24},{"ndv":2,"upper":"0221102HY0004","lower":"0221031HA0012","count":2,"preSum":26},{"ndv":2,"upper":"0221110L30002","lower":"0221109HB0003","count":2,"preSum":28},{"ndv":2,"upper":"0221110L30004","lower":"0221110L30003","count":2,"preSum":30},{"ndv":2,"upper":"0221111L30002","lower":"0221110L30006","count":2,"preSum":32},{"ndv":2,"upper":"0221119S70011","lower":"0221116HA0008","count":2,"preSum":34},{"ndv":2,"upper":"0221120T30003","lower":"0221120T10014","count":2,"preSum":36},{"ndv":2,"upper":"0221120T30008","lower":"0221120T30004","count":2,"preSum":38},{"ndv":2,"upper":"0221120T30014","lower":"0221120T30013","count":2,"preSum":40},{"ndv":2,"upper":"0221120T30022","lower":"0221120T30021","count":2,"preSum":42},{"ndv":2,"upper":"0221120T30029","lower":"0221120T30023","count":2,"preSum":44},{"ndv":2,"upper":"0221123S70021","lower":"0221122S70009","count":2,"preSum":46},{"ndv":2,"upper":"0221126T50012","lower":"0221123S70024","count":2,"preSum":48},{"ndv":2,"upper":"0221129HG0001","lower":"0221126T50040","count":2,"preSum":50},{"ndv":2,"upper":"0221203T50019","lower":"0221203T50014","count":2,"preSum":52},{"ndv":2,"upper":"0221203T50025","lower":"0221203T50024","count":2,"preSum":54},{"ndv":2,"upper":"0221204T50026","lower":"0221204T50023","count":2,"preSum":56},{"ndv":2,"upper":"0221224T30003","lower":"0221213HX0003","count":2,"preSum":58},{"ndv":2,"upper":"0221230HT0003","lower":"0221225HS0001","count":2,"preSum":60},{"ndv":2,"upper":"0221231HT0003","lower":"0221230HV0007","count":2,"preSum":62},{"ndv":2,"upper":"0230105HB0013","lower":"0221231HT0004","count":2,"preSum":64},{"ndv":2,"upper":"0230105T20008","lower":"0230105T20002","count":2,"preSum":66},{"ndv":2,"upper":"0230221T30015","lower":"0230221T30014","count":2,"preSum":68},{"ndv":2,"upper":"0230301HY0014","lower":"0230301HQ0002","count":2,"preSum":70},{"ndv":2,"upper":"0230306T50004","lower":"0230303HS0010","count":2,"preSum":72},{"ndv":2,"upper":"0230404HA0003","lower":"0230402HD0001","count":2,"preSum":74},{"ndv":2,"upper":"0230408HA0003","lower":"0230407L20003","count":2,"preSum":76},{"ndv":2,"upper":"0230409HC0021","lower":"0230409HB0007","count":2,"preSum":78},{"ndv":2,"upper":"0230411HY0008","lower":"0230410HI0005","count":2,"preSum":80},{"ndv":2,"upper":"0230412HC0012","lower":"0230412HC0002","count":2,"preSum":82},{"ndv":2,"upper":"0230414HS0006","lower":"0230412HC0014","count":2,"preSum":84},{"ndv":2,"upper":"0230414HS0011","lower":"0230414HS0009","count":2,"preSum":86},{"ndv":2,"upper":"0230427L30003","lower":"0230415HC0004","count":2,"preSum":88},{"ndv":2,"upper":"0230515HX0002","lower":"0230515HX0001","count":2,"preSum":90},{"ndv":2,"upper":"0230515HX0007","lower":"0230515HX0006","count":2,"preSum":92},{"ndv":2,"upper":"11994","lower":"119164","count":2,"preSum":94},{"ndv":2,"upper":"123435","lower":"12199","count":2,"preSum":96},{"ndv":2,"upper":"12623","lower":"12348","count":2,"preSum":98},{"ndv":2,"upper":"15547","lower":"14056","count":2,"preSum":100},{"ndv":2,"upper":"30381","lower":"16233","count":2,"preSum":102},{"ndv":2,"upper":"9409","lower":"310992","count":2,"preSum":104}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[13,7,3,3],"valueArr":["1","112976","30864","486"],"type":"String","sampleRate":1.0}',93378,0.006721839),('jala_wms_prod','task_detail','toqty',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93510],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','totalqty',4886,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":11,"lower":11,"count":52,"preSum":0},{"ndv":1,"upper":13,"lower":13,"count":50,"preSum":52},{"ndv":1,"upper":14,"lower":14,"count":55,"preSum":102},{"ndv":1,"upper":15,"lower":15,"count":95,"preSum":157},{"ndv":1,"upper":16,"lower":16,"count":64,"preSum":252},{"ndv":2,"upper":19,"lower":17,"count":48,"preSum":316},{"ndv":1,"upper":20,"lower":20,"count":94,"preSum":364},{"ndv":1,"upper":21,"lower":21,"count":44,"preSum":458},{"ndv":3,"upper":25,"lower":22,"count":70,"preSum":502},{"ndv":3,"upper":28,"lower":26,"count":46,"preSum":572},{"ndv":2,"upper":30,"lower":29,"count":86,"preSum":618},{"ndv":3,"upper":33,"lower":31,"count":54,"preSum":704},{"ndv":3,"upper":36,"lower":34,"count":64,"preSum":758},{"ndv":4,"upper":40,"lower":37,"count":86,"preSum":822},{"ndv":5,"upper":45,"lower":41,"count":46,"preSum":908},{"ndv":5,"upper":51,"lower":46,"count":46,"preSum":954},{"ndv":8,"upper":60,"lower":52,"count":52,"preSum":1000},{"ndv":10,"upper":70,"lower":61,"count":52,"preSum":1052},{"ndv":3,"upper":73,"lower":71,"count":46,"preSum":1104},{"ndv":8,"upper":83,"lower":74,"count":45,"preSum":1150},{"ndv":9,"upper":96,"lower":84,"count":125,"preSum":1195},{"ndv":11,"upper":108,"lower":97,"count":53,"preSum":1320},{"ndv":8,"upper":120,"lower":110,"count":45,"preSum":1373},{"ndv":15,"upper":144,"lower":122,"count":97,"preSum":1418},{"ndv":14,"upper":168,"lower":145,"count":51,"preSum":1515},{"ndv":5,"upper":180,"lower":170,"count":60,"preSum":1566},{"ndv":6,"upper":192,"lower":183,"count":45,"preSum":1626},{"ndv":9,"upper":216,"lower":198,"count":48,"preSum":1671},{"ndv":11,"upper":240,"lower":220,"count":65,"preSum":1719},{"ndv":15,"upper":294,"lower":244,"count":44,"preSum":1784},{"ndv":10,"upper":336,"lower":300,"count":55,"preSum":1828},{"ndv":12,"upper":400,"lower":348,"count":58,"preSum":1883},{"ndv":16,"upper":480,"lower":406,"count":65,"preSum":1941},{"ndv":12,"upper":528,"lower":486,"count":44,"preSum":2006},{"ndv":18,"upper":640,"lower":540,"count":61,"preSum":2050},{"ndv":11,"upper":720,"lower":643,"count":48,"preSum":2111},{"ndv":29,"upper":960,"lower":728,"count":59,"preSum":2159},{"ndv":23,"upper":1152,"lower":969,"count":44,"preSum":2218},{"ndv":18,"upper":1344,"lower":1165,"count":46,"preSum":2262},{"ndv":9,"upper":1440,"lower":1372,"count":48,"preSum":2308},{"ndv":21,"upper":1728,"lower":1442,"count":81,"preSum":2356},{"ndv":20,"upper":2016,"lower":1736,"count":75,"preSum":2437},{"ndv":12,"upper":2352,"lower":2023,"count":74,"preSum":2512},{"ndv":26,"upper":3360,"lower":2353,"count":44,"preSum":2586},{"ndv":17,"upper":4320,"lower":3456,"count":45,"preSum":2630},{"ndv":31,"upper":8400,"lower":4332,"count":44,"preSum":2675},{"ndv":20,"upper":14400,"lower":8430,"count":45,"preSum":2719},{"ndv":11,"upper":162397,"lower":15000,"count":18,"preSum":2764}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[59015,16619,3570,5607,1450,1802,288,324,205,743,444,135,207,319],"valueArr":[1,2,3,4,5,6,7,8,9,10,12,18,24,48],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','tozone',45,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"027DCN-2CTH","lower":"027DCN-2CTH","count":20,"preSum":0},{"ndv":1,"upper":"027DCN-BT2","lower":"027DCN-BT2","count":9,"preSum":20},{"ndv":2,"upper":"027DCN-CH","lower":"027DCN-CC","count":24,"preSum":29},{"ndv":1,"upper":"027DCN-LSCC","lower":"027DCN-LSCC","count":5,"preSum":53},{"ndv":1,"upper":"027DCN-YC","lower":"027DCN-YC","count":7,"preSum":58},{"ndv":1,"upper":"028DCI-JAB2B","lower":"028DCI-JAB2B","count":22,"preSum":65},{"ndv":1,"upper":"763DCA-JLB2B","lower":"763DCA-JLB2B","count":17,"preSum":87},{"ndv":1,"upper":"D001ZCJ","lower":"D001ZCJ","count":7,"preSum":104},{"ndv":1,"upper":"D001中转区","lower":"D001中转区","count":12,"preSum":111},{"ndv":1,"upper":"D002拣货区域","lower":"D002拣货区域","count":15,"preSum":123},{"ndv":1,"upper":"D002拣货区域-1","lower":"D002拣货区域-1","count":23,"preSum":138},{"ndv":1,"upper":"D011区域-1","lower":"D011区域-1","count":6,"preSum":161},{"ndv":1,"upper":"W009","lower":"W009","count":11,"preSum":167},{"ndv":1,"upper":"货主1001区域","lower":"货主1001区域","count":1,"preSum":178}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[32,28,109,96,55,32,41,31,339,6826,41,798,537,29],"valueArr":["022DCX-1Z","027DCN-BT1","763DCA-JLB2C","D001","D001商品零拣区","D002拣货区域-2","D003存储区域","D011区域-2","LOST","TH01","W007","W013","W028","货主1000区域"],"type":"String","sampleRate":1.0}',84337,0.006721839),('jala_wms_prod','task_detail','transcontcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','umqtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93510],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','unitqty',91,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":40,"lower":5,"count":6,"preSum":0},{"ndv":1,"upper":50,"lower":50,"count":15,"preSum":6},{"ndv":1,"upper":72,"lower":72,"count":12,"preSum":21},{"ndv":1,"upper":96,"lower":96,"count":10,"preSum":33},{"ndv":1,"upper":120,"lower":120,"count":14,"preSum":43},{"ndv":2,"upper":192,"lower":160,"count":6,"preSum":57},{"ndv":1,"upper":200,"lower":200,"count":13,"preSum":63},{"ndv":1,"upper":240,"lower":240,"count":18,"preSum":76},{"ndv":2,"upper":288,"lower":280,"count":15,"preSum":94},{"ndv":1,"upper":400,"lower":400,"count":16,"preSum":109},{"ndv":1,"upper":432,"lower":432,"count":3,"preSum":125},{"ndv":3,"upper":2016,"lower":1000,"count":15,"preSum":128},{"ndv":1,"upper":2352,"lower":2352,"count":15,"preSum":143}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[90340,63,1103,49,368,52,59,110,33,272,31,28,779,65],"valueArr":[1,2,3,4,6,8,10,12,20,24,30,36,48,180],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','unitqtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93510],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','userdef1',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','userdef2',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','userdef3',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','userdef4',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','userdef5',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','userdef6',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','userdef7',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','userdef8',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,93510,0.006721839),('jala_wms_prod','task_detail','version',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[93510],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','warehousecode',10,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[1891,6602,13427,848,48612,10986,1151,896,9079,18],"valueArr":["021DC1","022DC","027DC","028DC","573DC","763DC","SH01","SH02","SH03","TEST01"],"type":"String","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','task_detail','waveid',146746,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":262,"upper":45700,"lower":668,"count":1437,"preSum":0},{"ndv":997,"upper":166229,"lower":45701,"count":1437,"preSum":1437},{"ndv":1268,"upper":327543,"lower":166230,"count":1445,"preSum":2874},{"ndv":830,"upper":414258,"lower":328514,"count":1437,"preSum":4319},{"ndv":945,"upper":517604,"lower":414259,"count":1437,"preSum":5756},{"ndv":412,"upper":573991,"lower":517605,"count":1447,"preSum":7193},{"ndv":274,"upper":611473,"lower":574460,"count":1437,"preSum":8640},{"ndv":459,"upper":673371,"lower":612280,"count":1505,"preSum":10077},{"ndv":353,"upper":709686,"lower":673377,"count":1439,"preSum":11582},{"ndv":206,"upper":732824,"lower":709737,"count":1439,"preSum":13021},{"ndv":178,"upper":747015,"lower":732954,"count":1450,"preSum":14460},{"ndv":69,"upper":754334,"lower":747117,"count":1467,"preSum":15910},{"ndv":78,"upper":765302,"lower":754341,"count":1457,"preSum":17377},{"ndv":148,"upper":773568,"lower":765457,"count":1460,"preSum":18834},{"ndv":68,"upper":781582,"lower":773624,"count":1439,"preSum":20294},{"ndv":67,"upper":793443,"lower":781590,"count":1439,"preSum":21733},{"ndv":129,"upper":800831,"lower":793444,"count":1448,"preSum":23172},{"ndv":86,"upper":810219,"lower":801381,"count":1464,"preSum":24620},{"ndv":67,"upper":818748,"lower":810272,"count":1441,"preSum":26084},{"ndv":58,"upper":822122,"lower":818838,"count":1458,"preSum":27525},{"ndv":62,"upper":825321,"lower":822139,"count":1448,"preSum":28983},{"ndv":66,"upper":838717,"lower":825327,"count":1445,"preSum":30431},{"ndv":92,"upper":850217,"lower":838721,"count":1472,"preSum":31876},{"ndv":185,"upper":861650,"lower":850372,"count":1439,"preSum":33348},{"ndv":72,"upper":875227,"lower":862052,"count":1448,"preSum":34787},{"ndv":107,"upper":884672,"lower":875516,"count":1453,"preSum":36235},{"ndv":135,"upper":895169,"lower":884766,"count":1444,"preSum":37688},{"ndv":91,"upper":906777,"lower":895171,"count":1476,"preSum":39132},{"ndv":94,"upper":916549,"lower":906797,"count":1437,"preSum":40608},{"ndv":115,"upper":926065,"lower":916553,"count":1455,"preSum":42045},{"ndv":144,"upper":934530,"lower":926100,"count":1447,"preSum":43500},{"ndv":165,"upper":944356,"lower":934798,"count":1462,"preSum":44947},{"ndv":140,"upper":957144,"lower":944479,"count":1446,"preSum":46409},{"ndv":121,"upper":964459,"lower":957154,"count":1440,"preSum":47855},{"ndv":114,"upper":977101,"lower":964629,"count":1449,"preSum":49295},{"ndv":133,"upper":988934,"lower":977275,"count":1447,"preSum":50744},{"ndv":135,"upper":1003232,"lower":989238,"count":1467,"preSum":52191},{"ndv":126,"upper":1017823,"lower":1003255,"count":1467,"preSum":53658},{"ndv":136,"upper":1025735,"lower":1017857,"count":1492,"preSum":55125},{"ndv":109,"upper":1031853,"lower":1025769,"count":1449,"preSum":56617},{"ndv":80,"upper":1039055,"lower":1031855,"count":1466,"preSum":58066},{"ndv":58,"upper":1042377,"lower":1039056,"count":1468,"preSum":59532},{"ndv":53,"upper":1044129,"lower":1042378,"count":1443,"preSum":61000},{"ndv":88,"upper":1047613,"lower":1044133,"count":1440,"preSum":62443},{"ndv":50,"upper":1049759,"lower":1047617,"count":1445,"preSum":63883},{"ndv":62,"upper":1051629,"lower":1049766,"count":1443,"preSum":65328},{"ndv":62,"upper":1054901,"lower":1051638,"count":1445,"preSum":66771},{"ndv":71,"upper":1060809,"lower":1054954,"count":1447,"preSum":68216},{"ndv":78,"upper":1069945,"lower":1060812,"count":1442,"preSum":69663},{"ndv":71,"upper":1078684,"lower":1070247,"count":1437,"preSum":71105},{"ndv":149,"upper":1098175,"lower":1078716,"count":1462,"preSum":72542},{"ndv":197,"upper":1108707,"lower":1098771,"count":1437,"preSum":74004},{"ndv":108,"upper":1127290,"lower":1109278,"count":1440,"preSum":75441},{"ndv":127,"upper":1137332,"lower":1127292,"count":1454,"preSum":76881},{"ndv":156,"upper":1148454,"lower":1138141,"count":1438,"preSum":78335},{"ndv":121,"upper":1155741,"lower":1148953,"count":1451,"preSum":79773},{"ndv":127,"upper":1169476,"lower":1155798,"count":1437,"preSum":81224},{"ndv":70,"upper":1178485,"lower":1169590,"count":1441,"preSum":82661},{"ndv":68,"upper":1186946,"lower":1178487,"count":1451,"preSum":84102},{"ndv":56,"upper":1193233,"lower":1186962,"count":1462,"preSum":85553},{"ndv":97,"upper":1199494,"lower":1193279,"count":1442,"preSum":87015},{"ndv":116,"upper":1204159,"lower":1199607,"count":1463,"preSum":88457},{"ndv":65,"upper":1208812,"lower":1204163,"count":1460,"preSum":89920},{"ndv":27,"upper":1211561,"lower":1209112,"count":571,"preSum":91380}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[114,122,99,115,108,117,114,154,156,114,102,141,103],"valueArr":[753635,814480,821553,834593,904519,907883,929365,1044344,1058074,1082450,1155328,1188509,1205207],"type":"Int","sampleRate":1.0}',0,0.006721839),('jala_wms_prod','ttx_user','authtype',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"normal","lower":"normal","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[1628],"valueArr":["normal,ldap"],"type":"String","sampleRate":1.0}',0,1.0),('jala_wms_prod','ttx_user','code',1610,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":26,"upper":"000026","lower":"000001","count":26,"preSum":0},{"ndv":26,"upper":"000052","lower":"000027","count":26,"preSum":26},{"ndv":26,"upper":"000078","lower":"000053","count":26,"preSum":52},{"ndv":26,"upper":"000104","lower":"000079","count":26,"preSum":78},{"ndv":26,"upper":"01407372","lower":"000105","count":26,"preSum":104},{"ndv":26,"upper":"0220024","lower":"01425588","count":26,"preSum":130},{"ndv":26,"upper":"0220050","lower":"0220025","count":26,"preSum":156},{"ndv":26,"upper":"0220076","lower":"0220051","count":26,"preSum":182},{"ndv":26,"upper":"0220102","lower":"0220077","count":26,"preSum":208},{"ndv":26,"upper":"02700026","lower":"02700001","count":26,"preSum":234},{"ndv":26,"upper":"02700052","lower":"02700027","count":26,"preSum":260},{"ndv":26,"upper":"02700078","lower":"02700053","count":26,"preSum":286},{"ndv":26,"upper":"02700104","lower":"02700079","count":26,"preSum":312},{"ndv":26,"upper":"02700130","lower":"02700105","count":26,"preSum":338},{"ndv":26,"upper":"02700156","lower":"02700131","count":26,"preSum":364},{"ndv":26,"upper":"02700182","lower":"02700157","count":26,"preSum":390},{"ndv":26,"upper":"02700208","lower":"02700183","count":26,"preSum":416},{"ndv":26,"upper":"02700234","lower":"02700209","count":26,"preSum":442},{"ndv":26,"upper":"02700260","lower":"02700235","count":26,"preSum":468},{"ndv":26,"upper":"10000014","lower":"02700261","count":26,"preSum":494},{"ndv":26,"upper":"10000104","lower":"10000015","count":26,"preSum":520},{"ndv":26,"upper":"10000129","lower":"10000105","count":26,"preSum":546},{"ndv":26,"upper":"10000152","lower":"1000013","count":26,"preSum":572},{"ndv":26,"upper":"10002","lower":"10000153","count":26,"preSum":598},{"ndv":26,"upper":"10028","lower":"10003","count":26,"preSum":624},{"ndv":26,"upper":"10054","lower":"10029","count":26,"preSum":650},{"ndv":26,"upper":"10080","lower":"10055","count":26,"preSum":676},{"ndv":26,"upper":"10106","lower":"10081","count":26,"preSum":702},{"ndv":26,"upper":"10132","lower":"10107","count":26,"preSum":728},{"ndv":26,"upper":"10158","lower":"10133","count":26,"preSum":754},{"ndv":26,"upper":"10184","lower":"10159","count":26,"preSum":780},{"ndv":26,"upper":"10211","lower":"10185","count":26,"preSum":806},{"ndv":26,"upper":"10237","lower":"10212","count":26,"preSum":832},{"ndv":26,"upper":"10264","lower":"10238","count":26,"preSum":858},{"ndv":26,"upper":"10290","lower":"10265","count":26,"preSum":884},{"ndv":26,"upper":"10316","lower":"10291","count":26,"preSum":910},{"ndv":26,"upper":"10343","lower":"10317","count":26,"preSum":936},{"ndv":26,"upper":"10369","lower":"10344","count":26,"preSum":962},{"ndv":26,"upper":"10395","lower":"10370","count":26,"preSum":988},{"ndv":26,"upper":"10421","lower":"10396","count":26,"preSum":1014},{"ndv":26,"upper":"10449","lower":"10422","count":26,"preSum":1040},{"ndv":26,"upper":"10477","lower":"10451","count":26,"preSum":1066},{"ndv":26,"upper":"1401994","lower":"10478","count":26,"preSum":1092},{"ndv":26,"upper":"40583674","lower":"144510","count":26,"preSum":1118},{"ndv":26,"upper":"41306222","lower":"40647690","count":26,"preSum":1144},{"ndv":26,"upper":"41804927","lower":"41317999","count":26,"preSum":1170},{"ndv":26,"upper":"42078720","lower":"41807962","count":26,"preSum":1196},{"ndv":26,"upper":"42141583","lower":"42078907","count":26,"preSum":1222},{"ndv":26,"upper":"42196770","lower":"42144832","count":26,"preSum":1248},{"ndv":26,"upper":"57302013","lower":"42196773","count":26,"preSum":1274},{"ndv":26,"upper":"57302039","lower":"57302014","count":26,"preSum":1300},{"ndv":26,"upper":"CFM1","lower":"57302040","count":26,"preSum":1326},{"ndv":26,"upper":"FBB","lower":"chendaolong","count":26,"preSum":1352},{"ndv":26,"upper":"huxueyun","lower":"FGQ","count":26,"preSum":1378},{"ndv":26,"upper":"liukeyang","lower":"HWJ","count":26,"preSum":1404},{"ndv":26,"upper":"PAH","lower":"liuxiaojiao","count":26,"preSum":1430},{"ndv":26,"upper":"SFJSB","lower":"pj","count":26,"preSum":1456},{"ndv":26,"upper":"SSQ","lower":"SFKFA","count":26,"preSum":1482},{"ndv":26,"upper":"WHW","lower":"suchenbo","count":26,"preSum":1508},{"ndv":26,"upper":"xieying","lower":"WJ","count":26,"preSum":1534},{"ndv":26,"upper":"ZBZ","lower":"xuxingliang","count":26,"preSum":1560},{"ndv":26,"upper":"ZJ","lower":"ZCJ","count":26,"preSum":1586},{"ndv":18,"upper":"ZZZ","lower":"zjf","count":18,"preSum":1612}],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,0,1.0),('jala_wms_prod','ttx_user','created',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','createdby',14,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"admin","lower":"admin","count":1,"preSum":0},{"ndv":1,"upper":"Zz","lower":"Zz","count":2,"preSum":1},{"ndv":1,"upper":"_system_","lower":"_system_","count":2,"preSum":3}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[7,1117,9,4,5,76,36,5,21,337,3,5],"valueArr":["CFM","HQP","JALA-ADMIN","JZJ","LCQ","PZ","TTXLHJ","XCY","ZB","ZXL","jx","lhj"],"type":"String","sampleRate":1.0}',0,1.0),('jala_wms_prod','ttx_user','department',11,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"1","lower":"1","count":1,"preSum":0},{"ndv":1,"upper":"2","lower":"2","count":2,"preSum":1},{"ndv":1,"upper":"200005","lower":"200005","count":2,"preSum":3},{"ndv":1,"upper":"4","lower":"4","count":1,"preSum":5}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[4,3,701,98,267,18,197],"valueArr":["100004","200006","嘉兴仓","天津分仓","武汉仓","清远仓","清远分仓"],"type":"String","sampleRate":1.0}',336,1.0),('jala_wms_prod','ttx_user','email',11,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"2350560685@qq.com","lower":"2350560685@qq.com","count":1,"preSum":0},{"ndv":1,"upper":"chenhaitao@jala.com.cn","lower":"chenhaitao@jala.com.cn","count":1,"preSum":1},{"ndv":1,"upper":"chenxiangda1@sf-express.com","lower":"chenxiangda1@sf-express.com","count":1,"preSum":2},{"ndv":1,"upper":"laylaxue@sf-express.com","lower":"laylaxue@sf-express.com","count":2,"preSum":3},{"ndv":1,"upper":"scwang@ittx.com.cn","lower":"scwang@ittx.com.cn","count":1,"preSum":5},{"ndv":1,"upper":"zhangcheng3@jala.com.cn","lower":"zhangcheng3@jala.com.cn","count":1,"preSum":6},{"ndv":1,"upper":"zhuzhongwang@sf-express.com","lower":"zhuzhongwang@sf-express.com","count":1,"preSum":7}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[261],"valueArr":[""],"type":"String","sampleRate":1.0}',1361,1.0),('jala_wms_prod','ttx_user','gauthenabled',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[1630],"valueArr":[0],"type":"Int","sampleRate":1.0}',0,1.0),('jala_wms_prod','ttx_user','gauthsecretkey',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','inited',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[453,1177],"valueArr":[0,1],"type":"Int","sampleRate":1.0}',0,1.0),('jala_wms_prod','ttx_user','isdeveloper',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[1601,29],"valueArr":[0,1],"type":"Int","sampleRate":1.0}',0,1.0),('jala_wms_prod','ttx_user','lastloginin',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','lastupdated',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','lastupdatedby',1426,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":21,"upper":"000021","lower":"000001","count":21,"preSum":0},{"ndv":21,"upper":"000042","lower":"000022","count":21,"preSum":21},{"ndv":21,"upper":"000063","lower":"000043","count":21,"preSum":42},{"ndv":21,"upper":"000084","lower":"000064","count":21,"preSum":63},{"ndv":21,"upper":"000105","lower":"000085","count":21,"preSum":84},{"ndv":21,"upper":"01425588","lower":"000106","count":21,"preSum":105},{"ndv":21,"upper":"0220020","lower":"01431786","count":21,"preSum":126},{"ndv":21,"upper":"0220041","lower":"0220021","count":21,"preSum":147},{"ndv":21,"upper":"0220062","lower":"0220042","count":21,"preSum":168},{"ndv":21,"upper":"0220083","lower":"0220063","count":21,"preSum":189},{"ndv":21,"upper":"02700004","lower":"0220084","count":21,"preSum":210},{"ndv":21,"upper":"02700027","lower":"02700005","count":21,"preSum":231},{"ndv":21,"upper":"02700048","lower":"02700028","count":21,"preSum":252},{"ndv":21,"upper":"02700069","lower":"02700049","count":21,"preSum":273},{"ndv":21,"upper":"02700090","lower":"02700070","count":21,"preSum":294},{"ndv":21,"upper":"02700111","lower":"02700091","count":21,"preSum":315},{"ndv":21,"upper":"02700132","lower":"02700112","count":21,"preSum":336},{"ndv":21,"upper":"02700153","lower":"02700133","count":21,"preSum":357},{"ndv":21,"upper":"02700174","lower":"02700154","count":21,"preSum":378},{"ndv":21,"upper":"02700195","lower":"02700175","count":21,"preSum":399},{"ndv":21,"upper":"02700216","lower":"02700196","count":21,"preSum":420},{"ndv":21,"upper":"02700237","lower":"02700217","count":21,"preSum":441},{"ndv":21,"upper":"02700258","lower":"02700238","count":21,"preSum":462},{"ndv":21,"upper":"10000013","lower":"02700260","count":21,"preSum":483},{"ndv":21,"upper":"1000008","lower":"10000014","count":21,"preSum":504},{"ndv":21,"upper":"1000012","lower":"1000009","count":21,"preSum":525},{"ndv":21,"upper":"1000014","lower":"10000120","count":21,"preSum":546},{"ndv":21,"upper":"10001","lower":"10000140","count":21,"preSum":567},{"ndv":21,"upper":"10022","lower":"10002","count":21,"preSum":588},{"ndv":21,"upper":"10043","lower":"10023","count":21,"preSum":609},{"ndv":21,"upper":"10064","lower":"10044","count":21,"preSum":630},{"ndv":21,"upper":"10085","lower":"10065","count":21,"preSum":651},{"ndv":21,"upper":"10106","lower":"10086","count":21,"preSum":672},{"ndv":21,"upper":"10127","lower":"10107","count":21,"preSum":693},{"ndv":21,"upper":"10148","lower":"10128","count":21,"preSum":714},{"ndv":21,"upper":"10169","lower":"10149","count":21,"preSum":735},{"ndv":21,"upper":"10190","lower":"10170","count":21,"preSum":756},{"ndv":21,"upper":"10212","lower":"10191","count":21,"preSum":777},{"ndv":21,"upper":"10303","lower":"10213","count":21,"preSum":798},{"ndv":21,"upper":"20010","lower":"10304","count":21,"preSum":819},{"ndv":21,"upper":"41056973","lower":"20011","count":21,"preSum":840},{"ndv":21,"upper":"41392574","lower":"41072349","count":21,"preSum":861},{"ndv":21,"upper":"41804927","lower":"41412544","count":21,"preSum":882},{"ndv":21,"upper":"42035274","lower":"41807962","count":21,"preSum":903},{"ndv":21,"upper":"42127969","lower":"42040625","count":21,"preSum":924},{"ndv":21,"upper":"42196712","lower":"42128445","count":21,"preSum":945},{"ndv":21,"upper":"57302005","lower":"42196724","count":21,"preSum":966},{"ndv":21,"upper":"57302026","lower":"57302006","count":21,"preSum":987},{"ndv":21,"upper":"57302047","lower":"57302027","count":21,"preSum":1008},{"ndv":21,"upper":"cht","lower":"57302048","count":21,"preSum":1029},{"ndv":21,"upper":"fumin","lower":"chuyunfei","count":21,"preSum":1050},{"ndv":21,"upper":"HWJ","lower":"fuzhi","count":21,"preSum":1071},{"ndv":19,"upper":"liduoxia","lower":"hxy","count":21,"preSum":1092},{"ndv":21,"upper":"LYM","lower":"lihu","count":21,"preSum":1113},{"ndv":21,"upper":"SF41574317","lower":"LZP","count":21,"preSum":1134},{"ndv":21,"upper":"sfyangzhifeng","lower":"SF41627719","count":21,"preSum":1155},{"ndv":21,"upper":"sxh","lower":"sfyejianni","count":21,"preSum":1176},{"ndv":20,"upper":"WJS","lower":"syy","count":21,"preSum":1197},{"ndv":20,"upper":"XCY1","lower":"WJW","count":21,"preSum":1218},{"ndv":21,"upper":"YXH","lower":"xiajinshuang","count":21,"preSum":1239},{"ndv":21,"upper":"zhaoxiaoling","lower":"yxp","count":21,"preSum":1260},{"ndv":21,"upper":"zyr","lower":"zhaoyijue","count":21,"preSum":1281},{"ndv":4,"upper":"_system_","lower":"Zz","count":4,"preSum":1302}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[3,282,8,31],"valueArr":["CFM","HQP","PZ","ZXL"],"type":"String","sampleRate":1.0}',0,1.0),('jala_wms_prod','ttx_user','name',1586,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":26,"upper":"000035","lower":"000002","count":26,"preSum":0},{"ndv":26,"upper":"000061","lower":"000036","count":26,"preSum":26},{"ndv":26,"upper":"000088","lower":"000062","count":26,"preSum":52},{"ndv":26,"upper":"000114","lower":"000089","count":26,"preSum":78},{"ndv":26,"upper":"02700114","lower":"000115","count":26,"preSum":104},{"ndv":26,"upper":"02700151","lower":"02700115","count":26,"preSum":130},{"ndv":26,"upper":"02700177","lower":"02700152","count":26,"preSum":156},{"ndv":26,"upper":"02700204","lower":"02700178","count":26,"preSum":182},{"ndv":26,"upper":"02700230","lower":"02700205","count":26,"preSum":208},{"ndv":26,"upper":"02700256","lower":"02700231","count":26,"preSum":234},{"ndv":26,"upper":"2CIB2号","lower":"02700257","count":26,"preSum":260},{"ndv":26,"upper":"2COB117号","lower":"2CIB3号","count":26,"preSum":286},{"ndv":26,"upper":"2COB140号","lower":"2COB118号","count":26,"preSum":312},{"ndv":26,"upper":"2COB164号","lower":"2COB141号","count":26,"preSum":338},{"ndv":26,"upper":"2COB188号","lower":"2COB165号","count":26,"preSum":364},{"ndv":26,"upper":"2COB211号","lower":"2COB189号","count":26,"preSum":390},{"ndv":26,"upper":"2COB235号","lower":"2COB212号","count":26,"preSum":416},{"ndv":26,"upper":"2COB259号","lower":"2COB236号","count":26,"preSum":442},{"ndv":26,"upper":"2COB283号","lower":"2COB25号","count":26,"preSum":468},{"ndv":26,"upper":"2COB306号","lower":"2COB284号","count":26,"preSum":494},{"ndv":26,"upper":"2COB330号","lower":"2COB307号","count":26,"preSum":520},{"ndv":26,"upper":"2COB354号","lower":"2COB331号","count":26,"preSum":546},{"ndv":26,"upper":"2COB378号","lower":"2COB355号","count":26,"preSum":572},{"ndv":26,"upper":"2COB400号","lower":"2COB379号","count":26,"preSum":598},{"ndv":26,"upper":"2COB424号","lower":"2COB401号","count":26,"preSum":624},{"ndv":26,"upper":"2COB44号","lower":"2COB425号","count":26,"preSum":650},{"ndv":26,"upper":"2COB475号","lower":"2COB451号","count":26,"preSum":676},{"ndv":26,"upper":"2COB49号","lower":"2COB476号","count":26,"preSum":702},{"ndv":26,"upper":"2COB71号","lower":"2COB4号","count":26,"preSum":728},{"ndv":26,"upper":"2COB95号","lower":"2COB72号","count":26,"preSum":754},{"ndv":26,"upper":"B仓临时工25","lower":"2COB96号","count":26,"preSum":780},{"ndv":26,"upper":"B仓临时工49","lower":"B仓临时工26","count":26,"preSum":806},{"ndv":26,"upper":"SF41732833","lower":"B仓临时工5","count":26,"preSum":832},{"ndv":26,"upper":"TTXZLY","lower":"SF41784589","count":26,"preSum":858},{"ndv":25,"upper":"临时22","lower":"WJ","count":26,"preSum":884},{"ndv":26,"upper":"临时46","lower":"临时23","count":26,"preSum":910},{"ndv":26,"upper":"临时7","lower":"临时47","count":26,"preSum":936},{"ndv":26,"upper":"临时工2","lower":"临时70","count":26,"preSum":962},{"ndv":26,"upper":"临时工43","lower":"临时工20","count":26,"preSum":988},{"ndv":26,"upper":"临时工67","lower":"临时工44","count":26,"preSum":1014},{"ndv":25,"upper":"候尧邺","lower":"临时工68","count":26,"preSum":1040},{"ndv":26,"upper":"刘珍珍","lower":"倪文兴","count":27,"preSum":1066},{"ndv":26,"upper":"吴守春","lower":"刘琦","count":26,"preSum":1093},{"ndv":24,"upper":"姚本金","lower":"吴彪","count":26,"preSum":1119},{"ndv":25,"upper":"师云鹏","lower":"姜喜超","count":26,"preSum":1145},{"ndv":26,"upper":"张成","lower":"常峰","count":26,"preSum":1171},{"ndv":25,"upper":"徐星亮","lower":"张敏","count":26,"preSum":1197},{"ndv":25,"upper":"朱明芳","lower":"徐柏杨","count":26,"preSum":1223},{"ndv":26,"upper":"李永强","lower":"朱昰宸","count":26,"preSum":1249},{"ndv":24,"upper":"杨文斌","lower":"李泱泱","count":26,"preSum":1275},{"ndv":26,"upper":"楚云飞","lower":"杨新安","count":26,"preSum":1301},{"ndv":26,"upper":"潘安徽","lower":"楚云飞1","count":26,"preSum":1327},{"ndv":25,"upper":"王宏涛","lower":"潘小燕","count":26,"preSum":1353},{"ndv":25,"upper":"田亚迪","lower":"王家豪","count":26,"preSum":1379},{"ndv":26,"upper":"罗玲艳","lower":"田维东","count":26,"preSum":1405},{"ndv":26,"upper":"蔡","lower":"罗菊英","count":26,"preSum":1431},{"ndv":26,"upper":"谢罗曼","lower":"蔡凤伟","count":26,"preSum":1457},{"ndv":23,"upper":"邓欢","lower":"谢英","count":26,"preSum":1483},{"ndv":23,"upper":"陆婕","lower":"邱正伟","count":26,"preSum":1509},{"ndv":24,"upper":"陈树新","lower":"陆江珊","count":26,"preSum":1535},{"ndv":24,"upper":"马剑","lower":"陈桂柳","count":27,"preSum":1561},{"ndv":26,"upper":"黄涛","lower":"马小艳","count":26,"preSum":1588},{"ndv":13,"upper":"龚小双","lower":"黄秋萍","count":13,"preSum":1614}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[3],"valueArr":["舒悟"],"type":"String","sampleRate":1.0}',0,1.0),('jala_wms_prod','ttx_user','orgcode',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"root","lower":"root","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[1628],"valueArr":["JALA"],"type":"String","sampleRate":1.0}',0,1.0),('jala_wms_prod','ttx_user','phone',22,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"13564258894","lower":"13564258894","count":1,"preSum":0},{"ndv":1,"upper":"13800066611","lower":"13800066611","count":1,"preSum":1},{"ndv":1,"upper":"13901974267","lower":"13901974267","count":1,"preSum":2},{"ndv":1,"upper":"15019313655","lower":"15019313655","count":1,"preSum":3},{"ndv":1,"upper":"15556958589","lower":"15556958589","count":1,"preSum":4},{"ndv":1,"upper":"15675191455","lower":"15675191455","count":1,"preSum":5},{"ndv":1,"upper":"15827124647","lower":"15827124647","count":1,"preSum":6},{"ndv":1,"upper":"15897658470","lower":"15897658470","count":1,"preSum":7},{"ndv":1,"upper":"17621402999","lower":"17621402999","count":1,"preSum":8},{"ndv":1,"upper":"17621996568","lower":"17621996568","count":1,"preSum":9},{"ndv":1,"upper":"17816625069","lower":"17816625069","count":1,"preSum":10},{"ndv":1,"upper":"17821983668","lower":"17821983668","count":2,"preSum":11},{"ndv":1,"upper":"18278367719","lower":"18278367719","count":1,"preSum":13},{"ndv":1,"upper":"18888888888","lower":"18888888888","count":1,"preSum":14}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[259],"valueArr":[""],"type":"String","sampleRate":1.0}',1356,1.0),('jala_wms_prod','ttx_user','portal',20,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"dev,biz,mgnt","lower":"dev,biz,mgnt","count":1,"preSum":0},{"ndv":1,"upper":"dev,biz,mgnt,ops","lower":"dev,biz,mgnt,ops","count":2,"preSum":1},{"ndv":1,"upper":"dev,mgnt,ops,biz","lower":"dev,mgnt,ops,biz","count":1,"preSum":3},{"ndv":1,"upper":"dev,ops,mgnt","lower":"dev,ops,mgnt","count":2,"preSum":4},{"ndv":1,"upper":"dev,ops,mgnt,biz","lower":"dev,ops,mgnt,biz","count":1,"preSum":6},{"ndv":1,"upper":"mgnt,biz,dev,ops","lower":"mgnt,biz,dev,ops","count":1,"preSum":7},{"ndv":1,"upper":"mgnt,dev","lower":"mgnt,dev","count":1,"preSum":8},{"ndv":1,"upper":"mgnt,dev,biz,ops","lower":"mgnt,dev,biz,ops","count":1,"preSum":9},{"ndv":1,"upper":"mgnt,ops,biz,dev","lower":"mgnt,ops,biz,dev","count":1,"preSum":10},{"ndv":1,"upper":"ops,biz","lower":"ops,biz","count":2,"preSum":11},{"ndv":1,"upper":"ops,mgnt,biz,dev","lower":"ops,mgnt,biz,dev","count":1,"preSum":13},{"ndv":1,"upper":"ops,mgnt,dev","lower":"ops,mgnt,dev","count":1,"preSum":14}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[20,1577,5,4,5,3],"valueArr":["","biz","biz,dev,mgnt,ops","biz,dev,ops,mgnt","dev,biz,ops,mgnt","mgnt"],"type":"String","sampleRate":1.0}',1,1.0),('jala_wms_prod','ttx_user','portraiturl',32,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"63b555ca7e696a66aeff45d7","lower":"63b555ca7e696a66aeff45d7","count":1,"preSum":0},{"ndv":1,"upper":"642aa1cd4e5d8e5e2b8d3c70","lower":"642aa1cd4e5d8e5e2b8d3c70","count":1,"preSum":1},{"ndv":1,"upper":"64377b2ed3077d5773c4f54e","lower":"64377b2ed3077d5773c4f54e","count":1,"preSum":2},{"ndv":1,"upper":"64377b6a70a7ce3011bf64ca","lower":"64377b6a70a7ce3011bf64ca","count":1,"preSum":3},{"ndv":1,"upper":"6438d372da9bec0d95310710","lower":"6438d372da9bec0d95310710","count":1,"preSum":4},{"ndv":1,"upper":"643b9365b537435e2d7d588c","lower":"643b9365b537435e2d7d588c","count":1,"preSum":5},{"ndv":1,"upper":"643d3135a333d74861535f3c","lower":"643d3135a333d74861535f3c","count":1,"preSum":6},{"ndv":1,"upper":"643fc2e3d790b0446e49f550","lower":"643fc2e3d790b0446e49f550","count":1,"preSum":7},{"ndv":1,"upper":"6440b0642b7baf6cbbe71e44","lower":"6440b0642b7baf6cbbe71e44","count":1,"preSum":8},{"ndv":1,"upper":"6440b4f5eb614d062b6d0846","lower":"6440b4f5eb614d062b6d0846","count":1,"preSum":9},{"ndv":1,"upper":"6440e4c50fddb95c82c75d73","lower":"6440e4c50fddb95c82c75d73","count":1,"preSum":10},{"ndv":1,"upper":"64427a90fb2a0e77594201f5","lower":"64427a90fb2a0e77594201f5","count":1,"preSum":11},{"ndv":1,"upper":"64434a44843f4b426c458e1a","lower":"64434a44843f4b426c458e1a","count":1,"preSum":12},{"ndv":1,"upper":"6450901aa34628313ff6fb4a","lower":"6450901aa34628313ff6fb4a","count":1,"preSum":13},{"ndv":1,"upper":"64560eb473f6dd1883b150b6","lower":"64560eb473f6dd1883b150b6","count":1,"preSum":14},{"ndv":1,"upper":"6456157873f6dd1883b16e70","lower":"6456157873f6dd1883b16e70","count":1,"preSum":15},{"ndv":1,"upper":"646f046aa14209152eab5831","lower":"646f046aa14209152eab5831","count":1,"preSum":16},{"ndv":1,"upper":"64702195cf891a6b00cce9f9","lower":"64702195cf891a6b00cce9f9","count":1,"preSum":17},{"ndv":1,"upper":"648c1bf91d13f33ef2663a16","lower":"648c1bf91d13f33ef2663a16","count":1,"preSum":18},{"ndv":1,"upper":"http://101.132.172.192/asset/img/defaultAvatar.svg","lower":"http://101.132.172.192/asset/img/defaultAvatar.svg","count":1,"preSum":19}],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,1610,1.0),('jala_wms_prod','ttx_user','status',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[84,1546],"valueArr":[0,1],"type":"Int","sampleRate":1.0}',0,1.0),('jala_wms_prod','ttx_user','taobaousernick',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','type',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"ADMIN","lower":"ADMIN","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[1628],"valueArr":["USER"],"type":"String","sampleRate":1.0}',0,1.0),('jala_wms_prod','ttx_user','userdef1',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','userdef2',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','userdef3',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','userdef4',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','userdef5',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','userdef6',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','userdef7',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','userdef8',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}',null,1630,1.0),('jala_wms_prod','ttx_user','version',318,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":12,"lower":12,"count":16,"preSum":0},{"ndv":2,"upper":15,"lower":13,"count":18,"preSum":16},{"ndv":2,"upper":18,"lower":17,"count":20,"preSum":34},{"ndv":2,"upper":20,"lower":19,"count":19,"preSum":54},{"ndv":3,"upper":23,"lower":21,"count":28,"preSum":73},{"ndv":3,"upper":26,"lower":24,"count":23,"preSum":101},{"ndv":2,"upper":28,"lower":27,"count":19,"preSum":124},{"ndv":3,"upper":31,"lower":29,"count":19,"preSum":143},{"ndv":2,"upper":33,"lower":32,"count":15,"preSum":162},{"ndv":2,"upper":35,"lower":34,"count":14,"preSum":177},{"ndv":3,"upper":38,"lower":36,"count":18,"preSum":191},{"ndv":2,"upper":40,"lower":39,"count":20,"preSum":209},{"ndv":2,"upper":42,"lower":41,"count":14,"preSum":229},{"ndv":3,"upper":45,"lower":43,"count":14,"preSum":243},{"ndv":4,"upper":49,"lower":46,"count":17,"preSum":257},{"ndv":4,"upper":53,"lower":50,"count":19,"preSum":274},{"ndv":5,"upper":58,"lower":54,"count":21,"preSum":293},{"ndv":3,"upper":61,"lower":59,"count":18,"preSum":314},{"ndv":3,"upper":64,"lower":62,"count":18,"preSum":332},{"ndv":3,"upper":67,"lower":65,"count":15,"preSum":350},{"ndv":4,"upper":71,"lower":68,"count":19,"preSum":365},{"ndv":3,"upper":74,"lower":72,"count":19,"preSum":384},{"ndv":3,"upper":77,"lower":75,"count":14,"preSum":403},{"ndv":3,"upper":80,"lower":78,"count":16,"preSum":417},{"ndv":3,"upper":83,"lower":81,"count":15,"preSum":433},{"ndv":4,"upper":87,"lower":84,"count":16,"preSum":448},{"ndv":4,"upper":91,"lower":88,"count":17,"preSum":464},{"ndv":4,"upper":95,"lower":92,"count":18,"preSum":481},{"ndv":4,"upper":99,"lower":96,"count":15,"preSum":499},{"ndv":5,"upper":104,"lower":100,"count":17,"preSum":514},{"ndv":4,"upper":108,"lower":105,"count":15,"preSum":531},{"ndv":5,"upper":114,"lower":109,"count":16,"preSum":546},{"ndv":6,"upper":120,"lower":115,"count":15,"preSum":562},{"ndv":5,"upper":127,"lower":121,"count":14,"preSum":577},{"ndv":5,"upper":132,"lower":128,"count":16,"preSum":591},{"ndv":5,"upper":137,"lower":133,"count":15,"preSum":607},{"ndv":7,"upper":146,"lower":139,"count":18,"preSum":622},{"ndv":5,"upper":154,"lower":147,"count":15,"preSum":640},{"ndv":6,"upper":161,"lower":155,"count":15,"preSum":655},{"ndv":9,"upper":171,"lower":162,"count":15,"preSum":670},{"ndv":8,"upper":180,"lower":172,"count":14,"preSum":685},{"ndv":8,"upper":190,"lower":181,"count":16,"preSum":699},{"ndv":10,"upper":202,"lower":191,"count":14,"preSum":715},{"ndv":11,"upper":219,"lower":203,"count":16,"preSum":729},{"ndv":10,"upper":233,"lower":220,"count":14,"preSum":745},{"ndv":11,"upper":256,"lower":236,"count":14,"preSum":759},{"ndv":9,"upper":286,"lower":265,"count":15,"preSum":773},{"ndv":9,"upper":300,"lower":287,"count":15,"preSum":788},{"ndv":12,"upper":339,"lower":306,"count":14,"preSum":803},{"ndv":12,"upper":383,"lower":343,"count":14,"preSum":817},{"ndv":12,"upper":453,"lower":384,"count":14,"preSum":831},{"ndv":14,"upper":583,"lower":466,"count":14,"preSum":845},{"ndv":14,"upper":1014,"lower":610,"count":14,"preSum":859},{"ndv":3,"upper":1387,"lower":1133,"count":3,"preSum":873}],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[322,70,62,45,43,36,29,21,18,26,26,19,17,20],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,14,16],"type":"Int","sampleRate":1.0}',0,1.0),('jala_wms_prod','ttx_user','wxavatarurl',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[266],"valueArr":[""],"type":"String","sampleRate":1.0}',1364,1.0),('jala_wms_prod','ttx_user','wxnickname',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[266],"valueArr":[""],"type":"String","sampleRate":1.0}',1364,1.0),('jala_wms_prod','ttx_user','wxopenid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[266],"valueArr":[""],"type":"String","sampleRate":1.0}',1364,1.0),('jala_wms_prod','ttx_user','wxsessionkey',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[266],"valueArr":[""],"type":"String","sampleRate":1.0}',1364,1.0),('jala_wms_prod','warehouse','acctcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','address1',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"奉贤区奉柘公路3289号","lower":"奉贤区奉柘公路3289号","count":2,"preSum":0},{"ndv":1,"upper":"广东省清远市清城区锦邦冷链物流园二楼7号库","lower":"广东省清远市清城区锦邦冷链物流园二楼7号库","count":1,"preSum":2},{"ndv":1,"upper":"湖北省武汉市蔡甸区星光大道77号武汉吉行天下物流有限公司","lower":"湖北省武汉市蔡甸区星光大道77号武汉吉行天下物流有限公司","count":1,"preSum":3}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[6],"valueArr":[""],"type":"String","sampleRate":1.0}',2,1.0),('jala_wms_prod','warehouse','address2',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[8],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','attentionto',7,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"伽蓝物流","lower":"伽蓝物流","count":1,"preSum":0},{"ndv":1,"upper":"伽蓝电商物流中心","lower":"伽蓝电商物流中心","count":1,"preSum":1},{"ndv":1,"upper":"毕如艳","lower":"毕如艳","count":1,"preSum":2},{"ndv":1,"upper":"自然堂官方旗舰店","lower":"自然堂官方旗舰店","count":1,"preSum":3}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[6],"valueArr":[""],"type":"String","sampleRate":1.0}',2,1.0),('jala_wms_prod','warehouse','authorigin',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','city',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"上海市","lower":"上海市","count":2,"preSum":0},{"ndv":1,"upper":"武汉市","lower":"武汉市","count":1,"preSum":2},{"ndv":1,"upper":"清远市","lower":"清远市","count":1,"preSum":3}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[6],"valueArr":[""],"type":"String","sampleRate":1.0}',2,1.0),('jala_wms_prod','warehouse','citycode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"420100","lower":"420100","count":1,"preSum":0},{"ndv":1,"upper":"441800","lower":"441800","count":1,"preSum":1}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[6],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','code',12,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"022DC","lower":"021DC1","count":2,"preSum":0},{"ndv":2,"upper":"028DC","lower":"027DC","count":2,"preSum":2},{"ndv":2,"upper":"763DC","lower":"573DC","count":2,"preSum":4},{"ndv":2,"upper":"SH01","lower":"763DCA1","count":2,"preSum":6},{"ndv":2,"upper":"SH03","lower":"SH02","count":2,"preSum":8},{"ndv":2,"upper":"TEST02","lower":"TEST01","count":2,"preSum":10}],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,0,1.0),('jala_wms_prod','warehouse','country',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"中国","lower":"中国","count":2,"preSum":0}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[6],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','countrycode',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[7,4],"valueArr":["","0"],"type":"String","sampleRate":1.0}',1,1.0),('jala_wms_prod','warehouse','created',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"Timestamp","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','createdby',6,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"admin","lower":"admin","count":2,"preSum":0},{"ndv":1,"upper":"LCQ","lower":"LCQ","count":1,"preSum":2},{"ndv":1,"upper":"lhj","lower":"lhj","count":1,"preSum":3},{"ndv":1,"upper":"LY","lower":"LY","count":2,"preSum":4},{"ndv":1,"upper":"XCY1","lower":"XCY1","count":1,"preSum":6}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[5],"valueArr":["XCY"],"type":"String","sampleRate":1.0}',0,1.0),('jala_wms_prod','warehouse','district',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"奉贤区","lower":"奉贤区","count":1,"preSum":0},{"ndv":1,"upper":"清城区","lower":"清城区","count":1,"preSum":1},{"ndv":1,"upper":"蔡甸区","lower":"蔡甸区","count":1,"preSum":2}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[6],"valueArr":[""],"type":"String","sampleRate":1.0}',3,1.0),('jala_wms_prod','warehouse','districtcode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"420114","lower":"420114","count":1,"preSum":0},{"ndv":1,"upper":"441802","lower":"441802","count":1,"preSum":1}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[6],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','email',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[8],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','faxnum',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[8],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','hostcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[8],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','lastupdated',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"Timestamp","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','lastupdatedby',9,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"admin","lower":"admin","count":1,"preSum":0},{"ndv":1,"upper":"JALA-ADMIN","lower":"JALA-ADMIN","count":1,"preSum":1},{"ndv":1,"upper":"LCQ","lower":"LCQ","count":1,"preSum":2},{"ndv":1,"upper":"lhj","lower":"lhj","count":1,"preSum":3},{"ndv":1,"upper":"LY","lower":"LY","count":2,"preSum":4},{"ndv":1,"upper":"PZ","lower":"PZ","count":1,"preSum":6}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[5],"valueArr":["XCY"],"type":"String","sampleRate":1.0}',0,1.0),('jala_wms_prod','warehouse','lat',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":0.0,"lower":0.0,"count":1,"preSum":0},{"ndv":1,"upper":23.663748483201413,"lower":23.663748483201413,"count":1,"preSum":1},{"ndv":1,"upper":30.480629125730015,"lower":30.480629125730015,"count":1,"preSum":2},{"ndv":1,"upper":30.874255229073135,"lower":30.874255229073135,"count":2,"preSum":3}],"maxBucketSize":8,"type":"Double","sampleRate":1.0}',null,7,1.0),('jala_wms_prod','warehouse','lng',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":0.0,"lower":0.0,"count":1,"preSum":0},{"ndv":1,"upper":113.25618889657149,"lower":113.25618889657149,"count":1,"preSum":1},{"ndv":1,"upper":114.0263809637943,"lower":114.0263809637943,"count":1,"preSum":2},{"ndv":1,"upper":121.5454165502098,"lower":121.5454165502098,"count":2,"preSum":3}],"maxBucketSize":8,"type":"Double","sampleRate":1.0}',null,7,1.0),('jala_wms_prod','warehouse','mobile',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"15021093616","lower":"15021093616","count":1,"preSum":0},{"ndv":1,"upper":"15855454699","lower":"15855454699","count":1,"preSum":1}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[7],"valueArr":[""],"type":"String","sampleRate":1.0}',3,1.0),('jala_wms_prod','warehouse','name',12,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"上海岚丰退货仓","lower":"上海岚丰路总仓","count":2,"preSum":0},{"ndv":2,"upper":"伽蓝嘉兴仓","lower":"上海钱桥总仓","count":2,"preSum":2},{"ndv":2,"upper":"伽蓝奉贤钱桥仓上海分仓","lower":"伽蓝天津仓","count":2,"preSum":4},{"ndv":2,"upper":"伽蓝武汉仓","lower":"伽蓝成都仓","count":2,"preSum":6},{"ndv":2,"upper":"测试仓库","lower":"伽蓝清远清城仓","count":2,"preSum":8},{"ndv":2,"upper":"生产环境测试仓","lower":"测试仓库2","count":2,"preSum":10}],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,0,1.0),('jala_wms_prod','warehouse','orgcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[12],"valueArr":["JALA"],"type":"String","sampleRate":1.0}',0,1.0),('jala_wms_prod','warehouse','phonenum',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"0573-86683602","lower":"0573-86683602","count":1,"preSum":0},{"ndv":1,"upper":"15002119948","lower":"15002119948","count":1,"preSum":1},{"ndv":1,"upper":"15021093616","lower":"15021093616","count":1,"preSum":2}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[6],"valueArr":[""],"type":"String","sampleRate":1.0}',3,1.0),('jala_wms_prod','warehouse','postalcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[8],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','qrcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[8],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','state',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"上海","lower":"上海","count":2,"preSum":0},{"ndv":1,"upper":"广东省","lower":"广东省","count":1,"preSum":2},{"ndv":1,"upper":"湖北省","lower":"湖北省","count":1,"preSum":3}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[6],"valueArr":[""],"type":"String","sampleRate":1.0}',2,1.0),('jala_wms_prod','warehouse','statecode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"42","lower":"42","count":1,"preSum":0},{"ndv":1,"upper":"44","lower":"44","count":1,"preSum":1}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[6],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','status',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"Int","sampleRate":1.0}','{"countArr":[12],"valueArr":[1],"type":"Int","sampleRate":1.0}',0,1.0),('jala_wms_prod','warehouse','tenantid',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','tenantmobile',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','tenantnickname',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','town',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[8],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','towncode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[8],"valueArr":[""],"type":"String","sampleRate":1.0}',4,1.0),('jala_wms_prod','warehouse','userdef1',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"3","lower":"3","count":2,"preSum":0}],"maxBucketSize":8,"type":"String","sampleRate":1.0}','{"countArr":[9],"valueArr":["2"],"type":"String","sampleRate":1.0}',1,1.0),('jala_wms_prod','warehouse','userdef2',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','userdef3',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('jala_wms_prod','warehouse','userdef4',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','userdef5',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','userdef6',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','userdef7',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','userdef8',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":8,"type":"String","sampleRate":1.0}',null,12,1.0),('jala_wms_prod','warehouse','version',9,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":1,"lower":0,"count":3,"preSum":0},{"ndv":2,"upper":4,"lower":3,"count":3,"preSum":3},{"ndv":2,"upper":22,"lower":5,"count":2,"preSum":6},{"ndv":1,"upper":33,"lower":33,"count":1,"preSum":8}],"maxBucketSize":8,"type":"Int","sampleRate":1.0}','{"countArr":[3],"valueArr":[2],"type":"Int","sampleRate":1.0}',0,1.0); - DELETE FROM metadb.ndv_sketch_statistics WHERE `SCHEMA_NAME` = 'jala_wms_prod' AND `TABLE_NAME` in ('ttx_user','task_detail','shipment_detail','item','shipping_container_header','item_packing_detail','warehouse','shipment_header','shipping_container_detail'); - INSERT INTO metadb.ndv_sketch_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAMES`, `SHARD_PART`, `DN_CARDINALITY`, `COMPOSITE_CARDINALITY`, `SKETCH_BYTES`, `SKETCH_TYPE`, `GMT_CREATED`) VALUES ('jala_wms_prod','item','code','jala_wms_prod_p00000_group:item_dyhk',60177,54780,'','HYPER_LOG_LOG',from_unixtime(1687975802)),('jala_wms_prod','item','code,companycode','jala_wms_prod_p00000_group:item_dyhk',-1,162987,'','HYPER_LOG_LOG',from_unixtime(1687975802)),('jala_wms_prod','item','code,companycode,warehousecode','jala_wms_prod_p00000_group:item_dyhk',-1,1056727,'','HYPER_LOG_LOG',from_unixtime(1687975803)),('jala_wms_prod','item','collectdatetime','jala_wms_prod_p00000_group:item_dyhk',0,1,'','HYPER_LOG_LOG',from_unixtime(1687975803)),('jala_wms_prod','item','id','jala_wms_prod_p00000_group:item_dyhk',896770,1023626,'','HYPER_LOG_LOG',from_unixtime(1687975803)),('jala_wms_prod','item_packing_detail','companycode,itemcode','jala_wms_prod_p00000_group:item_packing_detail_uoxr',-1,162404,'','HYPER_LOG_LOG',from_unixtime(1687975610)),('jala_wms_prod','item_packing_detail','companycode,itemcode,packingcode,unitcode,warehousecode','jala_wms_prod_p00000_group:item_packing_detail_uoxr',-1,5226395,'','HYPER_LOG_LOG',from_unixtime(1687975618)),('jala_wms_prod','item_packing_detail','companycode,itemcode,packingcode,warehousecode','jala_wms_prod_p00000_group:item_packing_detail_uoxr',-1,1043477,'','HYPER_LOG_LOG',from_unixtime(1687975615)),('jala_wms_prod','item_packing_detail','companycode,itemcode,warehousecode','jala_wms_prod_p00000_group:item_packing_detail_uoxr',-1,1043155,'','HYPER_LOG_LOG',from_unixtime(1687975612)),('jala_wms_prod','item_packing_detail','headerid','jala_wms_prod_p00000_group:item_packing_detail_uoxr',1056508,1044399,'','HYPER_LOG_LOG',from_unixtime(1687975603)),('jala_wms_prod','item_packing_detail','id','jala_wms_prod_p00000_group:item_packing_detail_uoxr',4510163,5234908,'','HYPER_LOG_LOG',from_unixtime(1688148313)),('jala_wms_prod','item_packing_detail','itemcode','jala_wms_prod_p00000_group:item_packing_detail_uoxr',62897,54780,'','HYPER_LOG_LOG',from_unixtime(1687975608)),('jala_wms_prod','shipping_container_header','actualshipdatetime','jala_wms_prod_p00000_group:shipping_container_header_oltr',1878070,1786717,'','HYPER_LOG_LOG',from_unixtime(1687975353)),('jala_wms_prod','shipping_container_header','cagecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',516,4,'','HYPER_LOG_LOG',from_unixtime(1687975378)),('jala_wms_prod','shipping_container_header','cagecode,status,warehousecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',-1,4,'','HYPER_LOG_LOG',from_unixtime(1687975380)),('jala_wms_prod','shipping_container_header','cagecode,warehousecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',-1,4,'','HYPER_LOG_LOG',from_unixtime(1687975379)),('jala_wms_prod','shipping_container_header','cageid','jala_wms_prod_p00000_group:shipping_container_header_oltr',30,26,'','HYPER_LOG_LOG',from_unixtime(1687975410)),('jala_wms_prod','shipping_container_header','code','jala_wms_prod_p00000_group:shipping_container_header_oltr',4519503,4266826,'','HYPER_LOG_LOG',from_unixtime(1687975357)),('jala_wms_prod','shipping_container_header','code,warehousecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',-1,4291650,'','HYPER_LOG_LOG',from_unixtime(1687975358)),('jala_wms_prod','shipping_container_header','companycode,status,warehousecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',-1,32,'','HYPER_LOG_LOG',from_unixtime(1687975367)),('jala_wms_prod','shipping_container_header','id','jala_wms_prod_p00000_group:shipping_container_header_oltr',4120120,4320687,'','HYPER_LOG_LOG',from_unixtime(1687975417)),('jala_wms_prod','shipping_container_header','loadid','jala_wms_prod_p00000_group:shipping_container_header_oltr',16417,14944,'','HYPER_LOG_LOG',from_unixtime(1687975406)),('jala_wms_prod','shipping_container_header','oqcendat','jala_wms_prod_p00000_group:shipping_container_header_oltr',2044125,1737615,'','HYPER_LOG_LOG',from_unixtime(1687975341)),('jala_wms_prod','shipping_container_header','pickcompletedat','jala_wms_prod_p00000_group:shipping_container_header_oltr',1335663,973108,'','HYPER_LOG_LOG',from_unixtime(1687975337)),('jala_wms_prod','shipping_container_header','scaledat','jala_wms_prod_p00000_group:shipping_container_header_oltr',1831626,1746714,'','HYPER_LOG_LOG',from_unixtime(1687975345)),('jala_wms_prod','shipping_container_header','shipmentcode','jala_wms_prod_p00000_group:shipping_container_header_oltr',4321751,3988158,'','HYPER_LOG_LOG',from_unixtime(1687975389)),('jala_wms_prod','shipping_container_header','shipmentcode,warehousecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',-1,4020442,'','HYPER_LOG_LOG',from_unixtime(1687975391)),('jala_wms_prod','shipping_container_header','shipmentid','jala_wms_prod_p00000_group:shipping_container_header_oltr',4304648,3996028,'','HYPER_LOG_LOG',from_unixtime(1687975384)),('jala_wms_prod','shipping_container_header','stagedat','jala_wms_prod_p00000_group:shipping_container_header_oltr',1887621,1775514,'','HYPER_LOG_LOG',from_unixtime(1687975349)),('jala_wms_prod','shipping_container_header','stageloc','jala_wms_prod_p00000_group:shipping_container_header_oltr',0,1,'','HYPER_LOG_LOG',from_unixtime(1687975414)),('jala_wms_prod','shipping_container_header','stageloc,status,warehousecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',-1,1,'','HYPER_LOG_LOG',from_unixtime(1687975416)),('jala_wms_prod','shipping_container_header','stageloc,warehousecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',-1,1,'','HYPER_LOG_LOG',from_unixtime(1687975415)),('jala_wms_prod','shipping_container_header','status,transcontcode,warehousecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',-1,1,'','HYPER_LOG_LOG',from_unixtime(1687975374)),('jala_wms_prod','shipping_container_header','status,warehousecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',-1,23,'','HYPER_LOG_LOG',from_unixtime(1687975365)),('jala_wms_prod','shipping_container_header','transcontcode','jala_wms_prod_p00000_group:shipping_container_header_oltr',0,1,'','HYPER_LOG_LOG',from_unixtime(1687975371)),('jala_wms_prod','shipping_container_header','transcontcode,warehousecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',-1,1,'','HYPER_LOG_LOG',from_unixtime(1687975372)),('jala_wms_prod','shipping_container_header','warehousecode','jala_wms_prod_p00000_group:shipping_container_header_oltr',13384279,10,'','HYPER_LOG_LOG',from_unixtime(1687975359)),('jala_wms_prod','shipping_container_header','warehousecode,waybillcode','jala_wms_prod_p00000_group:shipping_container_header_oltr',-1,4197914,'','HYPER_LOG_LOG',from_unixtime(1687975402)),('jala_wms_prod','shipping_container_header','waveid','jala_wms_prod_p00000_group:shipping_container_header_oltr',133380,144150,'','HYPER_LOG_LOG',from_unixtime(1687975395)),('jala_wms_prod','shipping_container_header','waybillcode','jala_wms_prod_p00000_group:shipping_container_header_oltr',4505324,4158497,'','HYPER_LOG_LOG',from_unixtime(1687975400)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',9198,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',126809,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',251724,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',1264642,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',136510,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',267612,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',862514,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',281186,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',604639,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','confirmedat','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',13,2727163,'','HYPER_LOG_LOG',from_unixtime(1688148189)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',1661,9517,'','HYPER_LOG_LOG',from_unixtime(1688148086)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',1714,9517,'','HYPER_LOG_LOG',from_unixtime(1688148086)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,9517,'','HYPER_LOG_LOG',from_unixtime(1688148086)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',91,9517,'','HYPER_LOG_LOG',from_unixtime(1688148086)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',15905,9517,'','HYPER_LOG_LOG',from_unixtime(1688148086)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',1268,9517,'','HYPER_LOG_LOG',from_unixtime(1688148086)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',27,9517,'','HYPER_LOG_LOG',from_unixtime(1688148086)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',59,9517,'','HYPER_LOG_LOG',from_unixtime(1688148085)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',1700,9517,'','HYPER_LOG_LOG',from_unixtime(1688148085)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',3742,9517,'','HYPER_LOG_LOG',from_unixtime(1688148086)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,9517,'','HYPER_LOG_LOG',from_unixtime(1688148086)),('jala_wms_prod','task_detail','currentloc','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',1,9517,'','HYPER_LOG_LOG',from_unixtime(1688148086)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,9645,'','HYPER_LOG_LOG',from_unixtime(1688148089)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','currentloc,status,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,9620,'','HYPER_LOG_LOG',from_unixtime(1688148094)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',6802,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',79051,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',7976,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',124247,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',73779,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',18368,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',58942,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',1106698,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',31853,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)),('jala_wms_prod','task_detail','frominventoryid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',13,1596291,'','HYPER_LOG_LOG',from_unixtime(1688148179)); - INSERT INTO metadb.ndv_sketch_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAMES`, `SHARD_PART`, `DN_CARDINALITY`, `COMPOSITE_CARDINALITY`, `SKETCH_BYTES`, `SKETCH_TYPE`, `GMT_CREATED`) VALUES ('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','frominventoryid,status','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,1617375,'','HYPER_LOG_LOG',from_unixtime(1688148183)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',92457,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',154305,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',276255,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',8128095,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',132875,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',1112616,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',1885475,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',1356017,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',2075106,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','id','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',283,15615365,'','HYPER_LOG_LOG',from_unixtime(1688148211)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,itemcode,referenceid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,14345836,'','HYPER_LOG_LOG',from_unixtime(1688148135)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,4116685,'','HYPER_LOG_LOG',from_unixtime(1688148173)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,5081370,'','HYPER_LOG_LOG',from_unixtime(1688148147)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referencecontid,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,5179177,'','HYPER_LOG_LOG',from_unixtime(1688148153)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,referenceid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,4137184,'','HYPER_LOG_LOG',from_unixtime(1688148129)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','internaltasktype,taskcode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,1369099,'','HYPER_LOG_LOG',from_unixtime(1688148112)),('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',185,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)),('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',1,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)),('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)),('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',2,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)); - INSERT INTO metadb.ndv_sketch_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAMES`, `SHARD_PART`, `DN_CARDINALITY`, `COMPOSITE_CARDINALITY`, `SKETCH_BYTES`, `SKETCH_TYPE`, `GMT_CREATED`) VALUES ('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',931,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)),('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',2,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)),('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',28,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)),('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',32,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)),('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',2,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)),('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',313,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)),('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)),('jala_wms_prod','task_detail','pickingcartcode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',0,419,'','HYPER_LOG_LOG',from_unixtime(1688148195)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,418,'','HYPER_LOG_LOG',from_unixtime(1688148198)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','pickingcartcode,status,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,526,'','HYPER_LOG_LOG',from_unixtime(1688148203)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',6148,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',8848,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',28335,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',1990002,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',25924,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',398919,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',786433,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',169515,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',560434,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',108,4178686,'','HYPER_LOG_LOG',from_unixtime(1688148162)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,4195029,'','HYPER_LOG_LOG',from_unixtime(1688148167)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',11029,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',19854,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',29777,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',1982663,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',26012,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',409088,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',600740,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',869229,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',961565,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referencecontid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',108,4909220,'','HYPER_LOG_LOG',from_unixtime(1688148142)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',7598,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',8433,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',29683,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',2051792,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',24622,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',271022,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',755530,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',162481,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',663893,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referenceid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',107,4171626,'','HYPER_LOG_LOG',from_unixtime(1688148124)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',95566,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',81336,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',294364,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',8491374,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',85055,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',1077115,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',1977922,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',940374,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',2186969,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','referencelineid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',283,15233716,'','HYPER_LOG_LOG',from_unixtime(1688148208)),('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',8681,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)),('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',24838,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)),('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)),('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',28596,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)),('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',219519,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)),('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',28884,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)),('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',21673,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)),('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',38634,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)); - INSERT INTO metadb.ndv_sketch_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAMES`, `SHARD_PART`, `DN_CARDINALITY`, `COMPOSITE_CARDINALITY`, `SKETCH_BYTES`, `SKETCH_TYPE`, `GMT_CREATED`) VALUES ('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',954176,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)),('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',146235,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)),('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)),('jala_wms_prod','task_detail','taskcode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',12,1358980,'','HYPER_LOG_LOG',from_unixtime(1688148101)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskcode,warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',-1,1352906,'','HYPER_LOG_LOG',from_unixtime(1688148106)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',10005,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',25888,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',23718,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',142551,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',30841,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',25991,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',91499,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',634075,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',62750,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','taskid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',12,1357075,'','HYPER_LOG_LOG',from_unixtime(1688148080)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',33447,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',62083,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',97695,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',4908264,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',84034,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',891150,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',1586014,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',2283486,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',1750373,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','warehousecode','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',235,10,'','HYPER_LOG_LOG',from_unixtime(1688148075)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00003',10453,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00007',5467,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00000_group:task_detail_list_3fzi_z7m6_00011',-1,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00000',3841,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00004',75183,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00001_group:task_detail_list_3fzi_z7m6_00008',10690,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00001',18957,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00005',63909,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00002_group:task_detail_list_3fzi_z7m6_00009',883406,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00002',86871,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00006',-1,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)),('jala_wms_prod','task_detail','waveid','jala_wms_prod_p00003_group:task_detail_list_3fzi_z7m6_00010',12,1194144,'','HYPER_LOG_LOG',from_unixtime(1688148117)); - reload statistics; - set session ENABLE_BKA_JOIN = 'true'; - set session ENABLE_SPM = 'TRUE'; - set session ENABLE_AUTO_USE_COLUMNS_PARTITION = 'true'; - set session CONN_POOL_XPROTO_PURE_ASYNC_MPP = 'true'; - set session RECORD_SQL = 'TRUE'; - set session CONN_POOL_XPROTO_CHUNK_RESULT = 'true'; - set session ENABLE_SCALE_OUT_FEATURE = 'true'; - set session MAX_PHYSICAL_PARTITION_COUNT = '8192'; - set session FORBID_EXECUTE_DML_ALL = 'FALSE'; - set session AUTO_PARTITION_PARTITIONS = '32'; - set session GROUP_SEQ_CHECK_INTERVAL = '5'; - set session CONN_POOL_XPROTO_SLOW_THRESH = '1000'; - set session GROUP_PARALLELISM = '8'; - set session MPP_RPC_LOCAL_ENABLED = 'false'; - set session CONN_POOL_MAX_POOL_SIZE = '60'; - set session SQL_DELAY_CUTOFF = '2'; - set session CONN_POOL_PROPERTIES = 'connectTimeout=5000;characterEncoding=utf8;autoReconnect=true;failOverReadOnly=false;socketTimeout=12000;rewriteBatchedStatements=true;useServerPrepStmts=false;useSSL=false'; - set session PARTITIONS_HEATMAP_COLLECTION_MAX_SINGLE_LOGIC_SCHEMA_COUNT = '500'; - set session CONN_POOL_XPROTO_MAX_PACKET_SIZE = '67108864'; - set session CONN_POOL_XPROTO_DIRECT_WRITE = 'false'; - set session CONN_POOL_XPROTO_MAX_SESSION_PER_CLIENT = '1024'; - set session STATISTIC_COLLECTOR_FROM_RULE = 'true'; - set session CONN_POOL_BLOCK_TIMEOUT = '5000'; - set session MPP_TABLESCAN_CONNECTION_STRATEGY = '0'; - set session CONN_POOL_IDLE_TIMEOUT = '60'; - set session CONN_POOL_XPROTO_XPLAN_EXPEND_STAR = 'true'; - set session CONN_POOL_XPROTO_STORAGE_DB_PORT = '0'; - set session MAX_PARTITION_COLUMN_COUNT = '5'; - set session PROCESS_AUTO_INCREMENT_BY_SEQUENCE = 'true'; - set session ALLOW_SIMPLE_SEQUENCE = 'false'; - set session PURGE_TRANS_BEFORE = '604801'; - set session SHOW_TABLE_GROUP_NAME = 'false'; - set session ENABLE_CONST_EXPR_EVAL_CACHE = 'true'; - set session SOCKET_TIMEOUT = '900000'; - set session ENABLE_INTERVAL_ENUMERATION_IN_PRUNING = 'true'; - set session CONN_POOL_XPROTO_META_DB_PORT = '0'; - set session CONN_POOL_MIN_POOL_SIZE = '5'; - set session ENABLE_ALTER_DDL = 'true'; - set session CONN_POOL_XPROTO_PLAN_CACHE = 'true'; - set session MAX_ENUMERABLE_INTERVAL_LENGTH = '32'; - set session CONN_POOL_XPROTO_MAX_CLIENT_PER_INST = '32'; - set session ENABLE_SELF_CROSS_JOIN = 'true'; - set session CONN_POOL_XPROTO_FLAG = '0'; - set session SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE = 'false'; - set session FORCE_APPLY_CACHE = 'TRUE'; - set session CONN_POOL_XPROTO_XPLAN_TABLE_SCAN = 'false'; - set session ENABLE_MPP = 'true'; - set session CONN_POOL_MAX_WAIT_THREAD_COUNT = '0'; - set session CONN_POOL_XPROTO_CONFIG = ''; - set session CONN_POOL_XPROTO_MAX_POOLED_SESSION_PER_INST = '512'; - set session CONN_POOL_XPROTO_SESSION_AGING_TIME = '600000'; - set session CONN_POOL_XPROTO_MIN_POOLED_SESSION_PER_INST = '32'; - set session SQL_SIMPLE_MAX_LENGTH = '1005'; - set session ENABLE_CDC_META_BUILD_SNAPSHOT = 'true'; - set session CHOOSE_STREAMING = 'true'; - set session ENABLE_RUNTIME_FILTER = 'false'; - set session ENABLE_AUTO_MERGE_INTERVALS_IN_PRUNING = 'true'; - set session WORKLOAD_OSS_NET_THRESHOLD = '2'; - set session MAX_IN_SUBQUERY_PRUNING_SIZE = '8192'; - set session CONN_POOL_XPROTO_QUERY_TOKEN = '10000'; - set session HINT_PARSER_FLAG = 'TRUE'; - set session ENABLE_AUTO_USE_RANGE_FOR_TIME_INDEX = 'false'; - set session GET_TSO_TIMEOUT = '5000'; - set session LOGICAL_DB_TIME_ZONE = '+08:00'; - set session STORAGE_SUPPORTS_BLOOM_FILTER = 'true'; - set session INIT_CONCURRENT_POOL_EVERY_CONNECTION = 'false'; - set session COLLATION_SERVER = 'utf8mb4_general_ci'; - set session SINGLE_GROUP_STORAGE_INST_LIST = 'polardbx-storage-0-master'; - set session CONN_POOL_XPROTO_CHECKER = 'true'; - set session ENABLE_RUNTIME_FILTER_XXHASH = 'true'; - set session USE_FAST_SINGLE_POINT_INTERVAL_MERGING = 'false'; - set session CONN_POOL_XPROTO_AUTH = 'true'; - set session ENABLE_DDL = 'TRUE'; - set session DEFAULT_PARTITION_MODE = 'drds'; - set session CONN_POOL_XPROTO_PIPE_BUFFER_SIZE = '268435456'; - set session PURGE_TRANS_INTERVAL = '86401'; - set session CONN_POOL_XPROTO_FEEDBACK = 'true'; - set session CONN_POOL_XPROTO_MESSAGE_TIMESTAMP = 'true'; - set session PARALLELISM = '-1'; - set session PARTITION_PRUNING_STEP_COUNT_LIMIT = '1024'; - set session ENABLE_FORBID_PUSH_DML_WITH_HINT = 'FALSE'; - set session ENABLE_MASTER_MPP = 'true'; - set session SHARD_DB_COUNT_EACH_STORAGE_INST = '2'; - set session PLAN_EXTERNALIZE_TEST = 'TRUE'; - set session NET_WRITE_TIMEOUT = '28800'; - set session CONN_POOL_XPROTO_XPLAN = 'true'; - set session CDC_STARTUP_MODE = '1'; - set session CONN_POOL_XPROTO_TRX_LEAK_CHECK = 'false'; - set session RETRY_ERROR_SQL_ON_OLD_SERVER = 'true'; - set session MAX_LOGICAL_DB_COUNT = '2048'; - set session CONN_POOL_XPROTO_AUTO_COMMIT_OPTIMIZE = 'true'; - set session SHOW_HASH_PARTITIONS_BY_RANGE = 'false'; diff --git a/polardbx-test/src/test/resources/statistics/dump/tablelookupCost.yml b/polardbx-test/src/test/resources/statistics/dump/tablelookupCost.yml deleted file mode 100644 index 457c1c361..000000000 --- a/polardbx-test/src/test/resources/statistics/dump/tablelookupCost.yml +++ /dev/null @@ -1,112 +0,0 @@ -- - SQL: | - select `id`, `shipmentCategory3`, `code`, `fromwarehouseCode`, `userDef8`, `erpOrderCode`, `userDef3`, `shipmentCategory2`, `shipmentType`, `companyCode`, `carrierCode`, `signValue`, `trackingType`, `primaryWaybillCode`, `waveId`, `storeName`, `shipmentCategory5`, `groupNum`, `groupIndex`, `shipToState`, `shipToCity`, `lastWaveId`, `shipmentCategory8`, `shipToAddress1`, `qtyRatio`, `totalQty`, `totalLines`, `created`, `payTime`, `shipToName`, `sellerTo`, `agentCode`, `shipToAttentionTo`, `consolidated`, `sourcePlatform`, `userDef4`, `shipmentNote`, `leadingSts`, `trailingSts`, `processType`, `text`, `rejectionNote`, `userDef1`, `sourceOrderCode`, `shipmentSubType`, `payStatus` from `shipment_header` where 1 = 1 and companyCode in ('JALA01') and processType in ('NORMAL') and leadingSts >= '100' and leadingSts <= '100' and trailingSts >= '100' and trailingSts <= '100' and warehouseCode = '022DC' and shipObjType = 'TO_C' and warehouseCode in ('022DC', '*') and companyCode in ('JALA11', 'JALA01', '*') and shipment_header.companyCode in ('JALA11', 'JALA01', '*') and shipment_header.warehouseCode in ('022DC', '022DC', '*') order by shipmentCategory2 asc limit 0, 100; - PLAN: | - Limit - MppExchange - LogicalView(tableNames=[[shipment_header]]) - - CATALOG: | - set global AUTO_PARTITION_PARTITIONS = '32'; - CREATE DATABASE IF NOT EXISTS `jala_wms_prod` CHARACTER SET `utf8mb4` COLLATE `utf8mb4_general_ci` MODE = 'auto'; - use jala_wms_prod; - CREATE TABLE IF NOT EXISTS `shipment_header` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `warehouseCode` varchar(50) NOT NULL, `companyCode` varchar(50) NOT NULL, `loadId` bigint(20) DEFAULT '0', `code` varchar(50) NOT NULL, `erpOrderCode` varchar(50) DEFAULT NULL, `erpOrderType` varchar(50) DEFAULT NULL, `erpOrderId` bigint(20) DEFAULT NULL, `leadingSts` int(11) NOT NULL DEFAULT '100', `trailingSts` int(11) NOT NULL DEFAULT '100', `shipmentType` varchar(50) NOT NULL, `route` varchar(50) DEFAULT NULL, `sourcePlatform` varchar(50) DEFAULT NULL, `sourceOrderCode` varchar(1500) DEFAULT NULL, `sourceErp` varchar(50) DEFAULT NULL, `shipTo` varchar(50) DEFAULT NULL, `sellerTo` varchar(50) DEFAULT NULL, `shipToName` varchar(50) DEFAULT NULL, `shipToID` varchar(300) DEFAULT NULL, `shipToCAID` varchar(300) DEFAULT NULL, `shipToAddress1` varchar(1500) DEFAULT NULL, `shipToAddress2` varchar(1500) DEFAULT NULL, `shipToDistrict` varchar(500) DEFAULT NULL, `shipToTown` varchar(500) DEFAULT NULL, `shipToCity` varchar(500) DEFAULT NULL, `shipToState` varchar(500) DEFAULT NULL, `shipToCountry` varchar(500) DEFAULT NULL, `shipToCountryCode` varchar(50) DEFAULT NULL, `shipToStateCode` varchar(50) DEFAULT NULL, `shipToCityCode` varchar(50) DEFAULT NULL, `shipToDistrictCode` varchar(50) DEFAULT NULL, `shipToTownCode` varchar(50) DEFAULT NULL, `shipToPostalCode` varchar(50) DEFAULT NULL, `shipToAttentionTo` varchar(1500) DEFAULT NULL, `shipToPhoneNum` varchar(500) DEFAULT NULL, `shipToMobile` varchar(1500) DEFAULT NULL, `shipToFaxNum` varchar(50) DEFAULT NULL, `shipToEmailAddress` varchar(500) DEFAULT NULL, `priority` int(11) DEFAULT NULL, `requestedDeliveryDate` date DEFAULT NULL, `requestedDeliveryType` varchar(20) DEFAULT NULL, `scheduledShipDate` date DEFAULT NULL, `actualShipDateTime` datetime DEFAULT NULL, `actualDeliveryDate` date DEFAULT NULL, `deliveryNote` varchar(200) DEFAULT NULL, `rejectionNote` varchar(500) DEFAULT NULL, `waveId` bigint(20) DEFAULT NULL, `shipDock` varchar(50) DEFAULT NULL, `allocateComplete` int(11) DEFAULT NULL, `totalWeight` decimal(15, 4) DEFAULT NULL, `qtyRatio` int(11) DEFAULT '0', `totalQty` bigint(20) DEFAULT '0', `totalVolume` decimal(15, 4) DEFAULT NULL, `totalLines` int(11) DEFAULT NULL, `totalContainers` int(11) DEFAULT NULL, `totalCases` int(11) DEFAULT NULL, `totalGroupConts` int(11) DEFAULT '0', `totalValue` decimal(15, 4) DEFAULT NULL, `carrierCode` varchar(50) DEFAULT NULL, `carrierService` varchar(50) DEFAULT NULL, `backOrderId` bigint(20) DEFAULT NULL, `processType` varchar(50) DEFAULT NULL, `lastWaveId` bigint(20) DEFAULT NULL, `groupNum` int(11) DEFAULT NULL, `groupIndex` int(11) DEFAULT NULL, `signValue` text, `shipmentSubType` varchar(50) DEFAULT NULL, `shipmentCategory1` varchar(50) DEFAULT NULL, `shipmentCategory2` varchar(50) DEFAULT NULL, `shipmentCategory3` varchar(50) DEFAULT NULL, `shipmentCategory4` varchar(50) DEFAULT NULL, `shipmentCategory5` varchar(50) DEFAULT NULL, `shipmentCategory6` varchar(50) DEFAULT NULL, `shipmentCategory7` varchar(50) DEFAULT NULL, `shipmentCategory8` varchar(50) DEFAULT NULL, `shipmentNote` varchar(500) DEFAULT NULL, `stopSeq` int(11) DEFAULT NULL, `codRequired` int(11) DEFAULT NULL, `codValue` decimal(15, 4) DEFAULT NULL, `deiveryWindow` varchar(100) DEFAULT NULL, `allowConsolidate` int(11) DEFAULT NULL, `consolidated` int(11) DEFAULT NULL, `invoiceRequired` int(11) DEFAULT NULL, `invoiceType` varchar(100) DEFAULT NULL, `invoiceHeader` varchar(100) DEFAULT NULL, `invoiceContent` varchar(200) DEFAULT NULL, `hostCompanyCode` varchar(50) DEFAULT NULL, `uploadRequired` int(11) DEFAULT '0', `uploadBatch` varchar(200) DEFAULT NULL, `statusFlow` varchar(50) DEFAULT NULL, `storeCode` varchar(50) DEFAULT NULL, `storeName` varchar(50) DEFAULT NULL, `primaryWaybillCode` varchar(50) DEFAULT NULL, `secondWaybillCodes` varchar(200) DEFAULT NULL, `routeCode` varchar(50) DEFAULT NULL, `shortAddress` varchar(50) DEFAULT NULL, `podStatus` varchar(50) DEFAULT NULL, `podDatetime` datetime DEFAULT NULL, `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `finalshipment` varchar(255) DEFAULT NULL, `bulkmaterials` varchar(255) DEFAULT NULL, `componentscraprate` varchar(255) DEFAULT NULL, `text` varchar(255) DEFAULT NULL, `reserveNo` int(11) DEFAULT NULL, `createdBy` varchar(50) DEFAULT NULL, `lastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `lastUpdatedBy` varchar(50) DEFAULT NULL, `version` int(11) DEFAULT '0', `userDef1` varchar(50) DEFAULT NULL, `userDef2` varchar(50) DEFAULT NULL, `userDef3` varchar(50) DEFAULT NULL, `userDef4` varchar(50) DEFAULT NULL, `userDef5` varchar(50) DEFAULT NULL, `userDef6` varchar(500) DEFAULT NULL, `userDef7` varchar(50) DEFAULT NULL, `userDef8` varchar(50) DEFAULT NULL, `processStamp` varchar(50) DEFAULT NULL, `payTime` datetime DEFAULT NULL, `payNo` varchar(800) DEFAULT NULL, `lockCode` varchar(50) DEFAULT NULL, `shipToAddressLng` varchar(50) DEFAULT NULL, `shipToAddressLat` varchar(50) DEFAULT NULL, `shortPick` int(11) DEFAULT '0', `shortAlloc` int(11) DEFAULT '0', `portCode` varchar(50) DEFAULT NULL, `packageCenterCode` varchar(50) DEFAULT NULL, `packageCenterName` varchar(50) DEFAULT NULL, `stamp` varchar(50) DEFAULT NULL, `stampIndex` varchar(50) DEFAULT NULL, `thruReceiptCode` varchar(50) DEFAULT NULL, `stageLoc` varchar(50) DEFAULT NULL, `insureRequired` int(11) DEFAULT '0', `originalOrderId` bigint(20) DEFAULT '0', `shortPacking` int(11) DEFAULT '0', `printDataId` varchar(100) DEFAULT NULL, `disabledCarrierCodes` varchar(100) DEFAULT NULL, `realUserId` varchar(100) DEFAULT NULL, `logisticsServices` varchar(100) DEFAULT NULL, `trackingType` int(11) DEFAULT '0', `shortAddressCode` varchar(50) DEFAULT NULL, `secondSectionCode` varchar(50) DEFAULT NULL, `thirdSectionCode` varchar(50) DEFAULT NULL, `servicemode` varchar(50) DEFAULT NULL, `payType` varchar(50) DEFAULT NULL, `receipcompany` varchar(50) DEFAULT NULL, `vipshopCode` varchar(50) DEFAULT NULL, `payStatus` int(11) DEFAULT '0', `warehouseTransferId` bigint(20) DEFAULT '0', `warehouseTransferCode` varchar(50) DEFAULT NULL, `shipObjType` varchar(50) DEFAULT NULL, `auditStatus` int(11) DEFAULT '-2', `auditedBy` varchar(50) DEFAULT NULL, `auditedAt` datetime DEFAULT NULL, `auditOpinion` varchar(200) DEFAULT NULL, `tempLevel` varchar(50) DEFAULT NULL, `checkBusinessScope` int(11) DEFAULT '0', `twoVoteSystem` int(11) DEFAULT '0', `materialdocumentyear` varchar(50) DEFAULT NULL, `itemCode` varchar(50) DEFAULT NULL, `confirmedAt` varchar(50) DEFAULT NULL, `postReceiptOn` varchar(50) DEFAULT NULL, `manufacturer` varchar(50) DEFAULT NULL, `towarehouseCode` varchar(50) DEFAULT NULL, `fromwarehouseCode` varchar(50) DEFAULT NULL, `orderDate` varchar(50) DEFAULT NULL, `purchaseOrderCode` varchar(50) DEFAULT NULL, `zxQty` int(11) DEFAULT NULL, `hxQty` int(11) DEFAULT NULL, `totalconQty` int(11) DEFAULT NULL, `deletedimension` varchar(255) DEFAULT NULL, `sourceErpCode` varchar(50) DEFAULT NULL, `uploadture` int(11) DEFAULT NULL, `updatereason` varchar(200) DEFAULT NULL, `closeShipment` int(2) DEFAULT NULL, `splitOrderIdentification` varchar(50) DEFAULT NULL, `temperatureControl` int(2) DEFAULT NULL, `newOrderDate` date DEFAULT NULL, `sfWeightProcess` varchar(5) DEFAULT NULL, `companyType` varchar(50) DEFAULT NULL, `agentCode` varchar(50) DEFAULT NULL, `actualTotalWeight` decimal(15, 6) DEFAULT NULL, PRIMARY KEY USING BTREE (`id`), GLOBAL INDEX `gsi_id`(`id`) COVERING (`warehouseCode`) PARTITION BY KEY (`id`) PARTITIONS 16, GLOBAL INDEX `gsi_wid`(`waveId`) COVERING (`warehouseCode`) PARTITION BY KEY (`waveId`) PARTITIONS 16, UNIQUE KEY `idx1` USING BTREE (`code`, `warehouseCode`, `companyCode`), KEY `idx2` USING BTREE (`waveId`), KEY `idx3` USING BTREE (`loadId`), KEY `idx4` USING BTREE (`erpOrderCode`, `warehouseCode`), KEY `idx6` USING BTREE (`primaryWaybillCode`, `warehouseCode`), KEY `idx_splitOrderIdentification` (`splitOrderIdentification`), KEY `__advise_index_shipment_header_list_carriercode` (`carrierCode`, `warehouseCode`), KEY `_local_idx10` USING BTREE (`warehouseTransferId`), KEY `_local_idx11` USING BTREE (`warehouseTransferCode`, `warehouseCode`, `companyCode`), KEY `_local_idx8` USING BTREE (`stamp`, `warehouseCode`), KEY `idxCreaedWarehouseCode` (`created`, `warehouseCode`), KEY `idexLeadTrailSts` (`leadingSts`, `trailingSts`), KEY `local_idx_primaryWaybillCode` (`primaryWaybillCode`, `secondWaybillCodes`, `trailingSts`), KEY `local_idx_trailingSts` (`trailingSts`, `created`), KEY `auto_shard_key_warehousecode` USING BTREE (`warehouseCode`) ) ENGINE = InnoDB AUTO_INCREMENT = 8838148 DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC PARTITION BY LIST COLUMNS (`warehouseCode`) SUBPARTITION BY KEY (`id`) ( PARTITION `p1` VALUES IN ('021DC1') ( SUBPARTITION `p1sp1`, SUBPARTITION `p1sp2`, SUBPARTITION `p1sp3`, SUBPARTITION `p1sp4` ), PARTITION `p2` VALUES IN ('022DC') ( SUBPARTITION `p2sp1`, SUBPARTITION `p2sp2`, SUBPARTITION `p2sp3`, SUBPARTITION `p2sp4` ), PARTITION `p3` VALUES IN ('027DC') ( SUBPARTITION `p3sp1`, SUBPARTITION `p3sp2`, SUBPARTITION `p3sp3`, SUBPARTITION `p3sp4` ), PARTITION `p4` VALUES IN ('028DC') ( SUBPARTITION `p4sp1`, SUBPARTITION `p4sp2`, SUBPARTITION `p4sp3`, SUBPARTITION `p4sp4` ), PARTITION `p5` VALUES IN ('573DC') ( SUBPARTITION `p5sp1`, SUBPARTITION `p5sp2`, SUBPARTITION `p5sp3`, SUBPARTITION `p5sp4` ), PARTITION `p6` VALUES IN ('763DC') ( SUBPARTITION `p6sp1`, SUBPARTITION `p6sp2`, SUBPARTITION `p6sp3`, SUBPARTITION `p6sp4` ), PARTITION `p7` VALUES IN ('763DCA') ( SUBPARTITION `p7sp1`, SUBPARTITION `p7sp2`, SUBPARTITION `p7sp3`, SUBPARTITION `p7sp4` ), PARTITION `p8` VALUES IN ('SH01') ( SUBPARTITION `p8sp1`, SUBPARTITION `p8sp2`, SUBPARTITION `p8sp3`, SUBPARTITION `p8sp4` ), PARTITION `p9` VALUES IN ('SH02') ( SUBPARTITION `p9sp1`, SUBPARTITION `p9sp2`, SUBPARTITION `p9sp3`, SUBPARTITION `p9sp4` ), PARTITION `p10` VALUES IN ('SH03') ( SUBPARTITION `p10sp1`, SUBPARTITION `p10sp2`, SUBPARTITION `p10sp3`, SUBPARTITION `p10sp4` ), PARTITION `p11` VALUES IN ('TEST01') ( SUBPARTITION `p11sp1`, SUBPARTITION `p11sp2`, SUBPARTITION `p11sp3`, SUBPARTITION `p11sp4` ), PARTITION `p12` VALUES IN (DEFAULT) ( SUBPARTITION `p12sp1`, SUBPARTITION `p12sp2`, SUBPARTITION `p12sp3`, SUBPARTITION `p12sp4` ) ); - DELETE FROM metadb.table_statistics WHERE `SCHEMA_NAME` = 'jala_wms_prod' AND `TABLE_NAME` in ('shipment_header'); - INSERT INTO metadb.table_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `ROW_COUNT`) VALUES ('jala_wms_prod','shipment_header',4236337); - DELETE FROM metadb.column_statistics WHERE `SCHEMA_NAME` = 'jala_wms_prod' AND `TABLE_NAME` in ('shipment_header'); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('jala_wms_prod','shipment_header','actualdeliverydate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Date","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[-1],"type":"Date","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','actualshipdatetime',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','actualtotalweight',9962,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":57,"upper":0.094000,"lower":0.002000,"count":1048,"preSum":0},{"ndv":26,"upper":0.120000,"lower":0.095000,"count":1104,"preSum":1048},{"ndv":24,"upper":0.144000,"lower":0.121000,"count":1054,"preSum":2152},{"ndv":16,"upper":0.160000,"lower":0.145000,"count":1228,"preSum":3206},{"ndv":21,"upper":0.180000,"lower":0.161000,"count":1053,"preSum":4434},{"ndv":29,"upper":0.210000,"lower":0.181000,"count":1338,"preSum":5487},{"ndv":20,"upper":0.230000,"lower":0.211000,"count":1297,"preSum":6825},{"ndv":30,"upper":0.260000,"lower":0.231000,"count":1188,"preSum":8122},{"ndv":30,"upper":0.290000,"lower":0.261000,"count":1068,"preSum":9310},{"ndv":20,"upper":0.310000,"lower":0.291000,"count":1357,"preSum":10378},{"ndv":18,"upper":0.329000,"lower":0.311000,"count":1043,"preSum":11735},{"ndv":16,"upper":0.346000,"lower":0.331000,"count":1074,"preSum":12778},{"ndv":18,"upper":0.365000,"lower":0.347000,"count":1179,"preSum":13852},{"ndv":15,"upper":0.380000,"lower":0.366000,"count":1360,"preSum":15031},{"ndv":29,"upper":0.410000,"lower":0.381000,"count":1276,"preSum":16391},{"ndv":20,"upper":0.430000,"lower":0.411000,"count":1194,"preSum":17667},{"ndv":20,"upper":0.450000,"lower":0.431000,"count":1131,"preSum":18861},{"ndv":20,"upper":0.470000,"lower":0.451000,"count":1044,"preSum":19992},{"ndv":48,"upper":0.520000,"lower":0.471000,"count":1133,"preSum":21036},{"ndv":59,"upper":0.580000,"lower":0.521000,"count":1186,"preSum":22169},{"ndv":29,"upper":0.613000,"lower":0.581000,"count":1040,"preSum":23355},{"ndv":10,"upper":0.623000,"lower":0.614000,"count":1099,"preSum":24395},{"ndv":27,"upper":0.650000,"lower":0.624000,"count":1130,"preSum":25494},{"ndv":38,"upper":0.692000,"lower":0.651000,"count":1061,"preSum":26624},{"ndv":66,"upper":0.766000,"lower":0.693000,"count":1041,"preSum":27685},{"ndv":31,"upper":0.800000,"lower":0.767000,"count":1053,"preSum":28726},{"ndv":55,"upper":0.860000,"lower":0.801000,"count":1161,"preSum":29779},{"ndv":27,"upper":0.887000,"lower":0.861000,"count":1076,"preSum":30940},{"ndv":14,"upper":0.902000,"lower":0.888000,"count":1055,"preSum":32016},{"ndv":38,"upper":0.940000,"lower":0.903000,"count":1144,"preSum":33071},{"ndv":30,"upper":0.970000,"lower":0.941000,"count":1188,"preSum":34215},{"ndv":33,"upper":1.004000,"lower":0.971000,"count":1042,"preSum":35403},{"ndv":36,"upper":1.040000,"lower":1.005000,"count":1131,"preSum":36445},{"ndv":44,"upper":1.085000,"lower":1.041000,"count":1043,"preSum":37576},{"ndv":49,"upper":1.135000,"lower":1.086000,"count":1060,"preSum":38619},{"ndv":69,"upper":1.210000,"lower":1.136000,"count":1125,"preSum":39679},{"ndv":81,"upper":1.300000,"lower":1.211000,"count":1111,"preSum":40804},{"ndv":53,"upper":1.356000,"lower":1.302000,"count":1045,"preSum":41915},{"ndv":71,"upper":1.430000,"lower":1.357000,"count":1085,"preSum":42960},{"ndv":102,"upper":1.550000,"lower":1.431000,"count":1081,"preSum":44045},{"ndv":85,"upper":1.652000,"lower":1.551000,"count":1055,"preSum":45126},{"ndv":62,"upper":1.728000,"lower":1.653000,"count":1039,"preSum":46181},{"ndv":39,"upper":1.770000,"lower":1.729000,"count":1088,"preSum":47220},{"ndv":64,"upper":1.842000,"lower":1.771000,"count":1103,"preSum":48308},{"ndv":12,"upper":1.854000,"lower":1.843000,"count":1066,"preSum":49411},{"ndv":26,"upper":1.880000,"lower":1.855000,"count":1061,"preSum":50477},{"ndv":52,"upper":1.937000,"lower":1.881000,"count":1047,"preSum":51538},{"ndv":71,"upper":2.030000,"lower":1.938000,"count":1075,"preSum":52585},{"ndv":93,"upper":2.160000,"lower":2.031000,"count":1104,"preSum":53660},{"ndv":74,"upper":2.274000,"lower":2.161000,"count":1055,"preSum":54764},{"ndv":37,"upper":2.327000,"lower":2.276000,"count":1071,"preSum":55819},{"ndv":62,"upper":2.399000,"lower":2.328000,"count":1053,"preSum":56890},{"ndv":53,"upper":2.469000,"lower":2.400000,"count":1072,"preSum":57943},{"ndv":47,"upper":2.530000,"lower":2.470000,"count":1063,"preSum":59015},{"ndv":100,"upper":2.690000,"lower":2.531000,"count":1062,"preSum":60078},{"ndv":12,"upper":2.702000,"lower":2.691000,"count":1079,"preSum":61140},{"ndv":133,"upper":3.230000,"lower":2.703000,"count":1040,"preSum":62219},{"ndv":228,"upper":4.282000,"lower":3.234000,"count":1130,"preSum":63259},{"ndv":52,"upper":4.470000,"lower":4.283000,"count":1044,"preSum":64389},{"ndv":819,"upper":2123.852000,"lower":4.480000,"count":1018,"preSum":65433}],"maxBucketSize":64,"type":"Double","sampleRate":0.9618625}','{"countArr":[9756,485,453,533,592,497,601,1693,538,501,549,607,653,945],"valueArr":[0.000000,0.200000,0.320000,0.330000,0.350000,0.400000,0.590000,0.593000,0.600000,0.840000,0.890000,0.900000,1.060000,4.305000],"type":"Double","sampleRate":0.9618625319816094}',15147,0.02436278),('jala_wms_prod','shipment_header','agentcode',20,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"MC","lower":"MC","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1638,1335,9,48,126,646,29,2417,423,85761,64],"valueArr":["","1753","JD","QCS","全品牌","春夏","植物智慧","珀芙研","美素","自然堂","莎辛那"],"type":"String","sampleRate":0.9618625319816094}',7504,0.02436278),('jala_wms_prod','shipment_header','allocatecomplete',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','allowconsolidate',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[1],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','auditedat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','auditedby',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','auditopinion',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','auditstatus',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[-2],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','backorderid',315,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":1264882,"lower":1264882,"count":1,"preSum":0},{"ndv":1,"upper":1328221,"lower":1328221,"count":1,"preSum":1},{"ndv":1,"upper":1363032,"lower":1363032,"count":1,"preSum":2},{"ndv":1,"upper":1367447,"lower":1367447,"count":1,"preSum":3},{"ndv":1,"upper":1367448,"lower":1367448,"count":1,"preSum":4},{"ndv":1,"upper":1369308,"lower":1369308,"count":1,"preSum":5},{"ndv":1,"upper":1381675,"lower":1381675,"count":1,"preSum":6},{"ndv":1,"upper":1407465,"lower":1407465,"count":1,"preSum":7},{"ndv":1,"upper":1466183,"lower":1466183,"count":1,"preSum":8},{"ndv":1,"upper":1504067,"lower":1504067,"count":1,"preSum":9},{"ndv":1,"upper":1974062,"lower":1974062,"count":1,"preSum":10},{"ndv":1,"upper":2472918,"lower":2472918,"count":1,"preSum":11},{"ndv":1,"upper":2604627,"lower":2604627,"count":1,"preSum":12},{"ndv":1,"upper":2606735,"lower":2606735,"count":1,"preSum":13},{"ndv":1,"upper":2607548,"lower":2607548,"count":1,"preSum":14},{"ndv":1,"upper":2607708,"lower":2607708,"count":1,"preSum":15},{"ndv":1,"upper":2646589,"lower":2646589,"count":1,"preSum":16},{"ndv":1,"upper":2794231,"lower":2794231,"count":1,"preSum":17},{"ndv":1,"upper":2943130,"lower":2943130,"count":1,"preSum":18},{"ndv":1,"upper":2946811,"lower":2946811,"count":1,"preSum":19},{"ndv":1,"upper":3418355,"lower":3418355,"count":1,"preSum":20},{"ndv":1,"upper":4235346,"lower":4235346,"count":1,"preSum":21},{"ndv":1,"upper":4264774,"lower":4264774,"count":1,"preSum":22},{"ndv":1,"upper":4265112,"lower":4265112,"count":1,"preSum":23},{"ndv":1,"upper":4446063,"lower":4446063,"count":1,"preSum":24},{"ndv":1,"upper":4446209,"lower":4446209,"count":1,"preSum":25},{"ndv":1,"upper":4999335,"lower":4999335,"count":1,"preSum":26},{"ndv":1,"upper":5541738,"lower":5541738,"count":1,"preSum":27},{"ndv":1,"upper":5642632,"lower":5642632,"count":1,"preSum":28},{"ndv":1,"upper":5835871,"lower":5835871,"count":1,"preSum":29}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[99971],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','bulkmaterials',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[57],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99944,0.02436278),('jala_wms_prod','shipment_header','carriercode',46,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"0000111","lower":"0000111","count":1,"preSum":0},{"ndv":1,"upper":"DISTRIBUTOR_1710055","lower":"DISTRIBUTOR_1710055","count":3,"preSum":1},{"ndv":1,"upper":"other","lower":"other","count":5,"preSum":4},{"ndv":1,"upper":"ZT","lower":"ZT","count":4,"preSum":9},{"ndv":1,"upper":"上海天翼物流股份有限公司","lower":"上海天翼物流股份有限公司","count":1,"preSum":13},{"ndv":1,"upper":"干线-华夏龙","lower":"干线-华夏龙","count":1,"preSum":14},{"ndv":1,"upper":"干线-盐城","lower":"干线-盐城","count":4,"preSum":15},{"ndv":1,"upper":"干线-铭创","lower":"干线-铭创","count":1,"preSum":19}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[55,108,1591,73141,132,455,248,15924,501,7010,44,6,14,24],"valueArr":["","EMS","OTHER","SF","SF1","SF2","SF3","ZTO","ZTOKY","shunfeng","上海恒兴国际物流有限公司","干线-溢宇","深圳市华夏龙供应链管理有限公司","深圳市顺丰综合物流服务有限公司"],"type":"String","sampleRate":0.9618625319816094}',728,0.02436278),('jala_wms_prod','shipment_header','carrierservice',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[61717,15660,6277,1195,864],"valueArr":["CAINIAO","DOUYIN","JD","KUAISHOU","PINDUODUO"],"type":"String","sampleRate":0.9618625319816094}',14288,0.02436278),('jala_wms_prod','shipment_header','checkbusinessscope',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','closeshipment',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[98563,12],"valueArr":[0,1],"type":"Int","sampleRate":0.9618625319816094}',1426,0.02436278),('jala_wms_prod','shipment_header','code',4056659,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1556,"upper":"CK0001182088","lower":"0001622094","count":1563,"preSum":0},{"ndv":1563,"upper":"CK0001490734","lower":"CK0001182092","count":1563,"preSum":1563},{"ndv":1563,"upper":"PJD2304784741732216","lower":"CK0001490789","count":1563,"preSum":3126},{"ndv":1563,"upper":"PJX2302755575782520","lower":"PJD2304784969012223","count":1563,"preSum":4689},{"ndv":1563,"upper":"PJX2304784168422111","lower":"PJX2302755575842520","count":1563,"preSum":6252},{"ndv":1563,"upper":"PJX2305792852660517","lower":"PJX2304784170782112","count":1563,"preSum":7815},{"ndv":1563,"upper":"PJX2305798102201513","lower":"PJX2305792852700517","count":1563,"preSum":9378},{"ndv":1563,"upper":"PJX2305803200802500","lower":"PJX2305798102211513","count":1563,"preSum":10941},{"ndv":1563,"upper":"PJX2306814015300322","lower":"PJX2305803200812500","count":1563,"preSum":12504},{"ndv":1563,"upper":"PJX2306819288341321","lower":"PJX2306814039350322","count":1563,"preSum":14067},{"ndv":1563,"upper":"PJX2306825824111918","lower":"PJX2306819290131321","count":1563,"preSum":15630},{"ndv":1563,"upper":"POD2305792269560416","lower":"PJX2306825825691918","count":1563,"preSum":17193},{"ndv":1563,"upper":"POD2306815551960611","lower":"POD2305792288510416","count":1563,"preSum":18756},{"ndv":1563,"upper":"PSD2304783592211923","lower":"POD2306815552190611","count":1563,"preSum":20319},{"ndv":1563,"upper":"PSD2304785587022415","lower":"PSD2304783595161923","count":1563,"preSum":21882},{"ndv":1563,"upper":"PSD2304787432372800","lower":"PSD2304785587032415","count":1563,"preSum":23445},{"ndv":1563,"upper":"PSD2305789573430209","lower":"PSD2304787432382800","count":1563,"preSum":25008},{"ndv":1563,"upper":"PSD2305793483700622","lower":"PSD2305789605510210","count":1563,"preSum":26571},{"ndv":1563,"upper":"PSD2305795450081016","lower":"PSD2305793483790622","count":1563,"preSum":28134},{"ndv":1563,"upper":"PSD2305797691701418","lower":"PSD2305795454021016","count":1563,"preSum":29697},{"ndv":1563,"upper":"PSD2305800437831912","lower":"PSD2305797692481418","count":1563,"preSum":31260},{"ndv":1563,"upper":"PSD2305802670242320","lower":"PSD2305800449941912","count":1563,"preSum":32823},{"ndv":1563,"upper":"PSD2305807435802813","lower":"PSD2305802684092321","count":1563,"preSum":34386},{"ndv":1563,"upper":"PSD2305810859123121","lower":"PSD2305807435842813","count":1563,"preSum":35949},{"ndv":1563,"upper":"PSD2306814246340402","lower":"PSD2305810873393121","count":1563,"preSum":37512},{"ndv":1563,"upper":"PSD2306816683280814","lower":"PSD2306814247780402","count":1563,"preSum":39075},{"ndv":1563,"upper":"PSD2306818784591220","lower":"PSD2306816683290814","count":1563,"preSum":40638},{"ndv":1563,"upper":"PSD2306821121101610","lower":"PSD2306818784611220","count":1563,"preSum":42201},{"ndv":1563,"upper":"PSD2306824267341817","lower":"PSD2306821121111610","count":1563,"preSum":43764},{"ndv":1563,"upper":"PSD2306827341062222","lower":"PSD2306824267431817","count":1563,"preSum":45327},{"ndv":1563,"upper":"PTB2302755699342602","lower":"PSD2306827341832222","count":1563,"preSum":46890},{"ndv":1563,"upper":"PTB2303766986991218","lower":"PTB2302755699752602","count":1563,"preSum":48453},{"ndv":1563,"upper":"PTB2304779649491204","lower":"PTB2303766987611218","count":1563,"preSum":50016},{"ndv":1563,"upper":"PTB2304784072712109","lower":"PTB2304779649641205","count":1563,"preSum":51579},{"ndv":1563,"upper":"PTB2304786671952614","lower":"PTB2304784073502109","count":1563,"preSum":53142},{"ndv":1563,"upper":"PTB2305788791420106","lower":"PTB2304786671972614","count":1563,"preSum":54705},{"ndv":1563,"upper":"PTB2305790449090309","lower":"PTB2305788791500106","count":1563,"preSum":56268},{"ndv":1563,"upper":"PTB2305791287310311","lower":"PTB2305790449130309","count":1563,"preSum":57831},{"ndv":1563,"upper":"PTB2305792915400521","lower":"PTB2305791303500311","count":1563,"preSum":59394},{"ndv":1563,"upper":"PTB2305795619371022","lower":"PTB2305792915520521","count":1563,"preSum":60957},{"ndv":1563,"upper":"PTB2305797854091500","lower":"PTB2305795620411022","count":1563,"preSum":62520},{"ndv":1563,"upper":"PTB2305799290641709","lower":"PTB2305797854391500","count":1563,"preSum":64083},{"ndv":1563,"upper":"PTB2305801469102110","lower":"PTB2305799292111709","count":1563,"preSum":65646},{"ndv":1563,"upper":"PTB2305803576792522","lower":"PTB2305801481782111","count":1563,"preSum":67209},{"ndv":1563,"upper":"PTB2305804711842710","lower":"PTB2305803577402522","count":1563,"preSum":68772},{"ndv":1563,"upper":"PTB2305805449052711","lower":"PTB2305804711852710","count":1563,"preSum":70335},{"ndv":1563,"upper":"PTB2305806128452713","lower":"PTB2305805449322711","count":1563,"preSum":71898},{"ndv":1563,"upper":"PTB2305806824312717","lower":"PTB2305806128572713","count":1563,"preSum":73461},{"ndv":1563,"upper":"PTB2305807873362820","lower":"PTB2305806824352717","count":1563,"preSum":75024},{"ndv":1563,"upper":"PTB2305809004133000","lower":"PTB2305807874572820","count":1563,"preSum":76587},{"ndv":1563,"upper":"PTB2305810287353117","lower":"PTB2305809004243000","count":1563,"preSum":78150},{"ndv":1563,"upper":"PTB2305811198223123","lower":"PTB2305810287403117","count":1563,"preSum":79713},{"ndv":1563,"upper":"PTB2306812485330200","lower":"PTB2305811216043123","count":1563,"preSum":81276},{"ndv":1563,"upper":"PTB2306813719870314","lower":"PTB2306812485340200","count":1563,"preSum":82839},{"ndv":1563,"upper":"PTB2306815226650519","lower":"PTB2306813719910314","count":1563,"preSum":84402},{"ndv":1563,"upper":"PTB2306817295170917","lower":"PTB2306815228690519","count":1563,"preSum":85965},{"ndv":1563,"upper":"PTB2306819095391313","lower":"PTB2306817296270917","count":1563,"preSum":87528},{"ndv":1563,"upper":"PTB2306820635471522","lower":"PTB2306819095401313","count":1563,"preSum":89091},{"ndv":1563,"upper":"PTB2306821855171622","lower":"PTB2306820635491522","count":1563,"preSum":90654},{"ndv":1563,"upper":"PTB2306822953031721","lower":"PTB2306821855201622","count":1563,"preSum":92217},{"ndv":1563,"upper":"PTB2306824514221821","lower":"PTB2306822953041721","count":1563,"preSum":93780},{"ndv":1563,"upper":"PTB2306825761171916","lower":"PTB2306824514291821","count":1563,"preSum":95343},{"ndv":1563,"upper":"PTB2306827242642215","lower":"PTB2306825762441916","count":1563,"preSum":96906},{"ndv":1532,"upper":"福袋wms其它出库-w009","lower":"PTB2306827242782215","count":1532,"preSum":98469}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,0,0.02436278),('jala_wms_prod','shipment_header','codrequired',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','codvalue',79498,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":107,"upper":9.9000,"lower":0.0100,"count":2010,"preSum":0},{"ndv":108,"upper":17.4600,"lower":9.9100,"count":1096,"preSum":2010},{"ndv":120,"upper":22.4000,"lower":17.5000,"count":1101,"preSum":3106},{"ndv":169,"upper":28.4000,"lower":22.4100,"count":1088,"preSum":4207},{"ndv":137,"upper":33.6000,"lower":28.4700,"count":1100,"preSum":5295},{"ndv":136,"upper":39.7600,"lower":33.8000,"count":1108,"preSum":6395},{"ndv":236,"upper":46.6300,"lower":39.7700,"count":1088,"preSum":7503},{"ndv":179,"upper":49.0000,"lower":46.6400,"count":1090,"preSum":8591},{"ndv":259,"upper":52.6300,"lower":49.0100,"count":1090,"preSum":9681},{"ndv":200,"upper":56.9300,"lower":52.6700,"count":1092,"preSum":10771},{"ndv":65,"upper":58.0000,"lower":56.9500,"count":1178,"preSum":11863},{"ndv":61,"upper":59.0000,"lower":58.0100,"count":1453,"preSum":13041},{"ndv":218,"upper":62.6500,"lower":59.0100,"count":1088,"preSum":14494},{"ndv":208,"upper":65.5500,"lower":62.6800,"count":1141,"preSum":15582},{"ndv":198,"upper":68.0000,"lower":65.5600,"count":1390,"preSum":16723},{"ndv":65,"upper":69.3000,"lower":68.0100,"count":1471,"preSum":18113},{"ndv":195,"upper":71.7200,"lower":69.3100,"count":1091,"preSum":19584},{"ndv":101,"upper":73.2100,"lower":71.7300,"count":1088,"preSum":20675},{"ndv":173,"upper":76.0000,"lower":73.2200,"count":1195,"preSum":21763},{"ndv":209,"upper":79.1200,"lower":76.0100,"count":1098,"preSum":22958},{"ndv":301,"upper":84.0000,"lower":79.1300,"count":1407,"preSum":24056},{"ndv":266,"upper":88.0200,"lower":84.0100,"count":1125,"preSum":25463},{"ndv":54,"upper":89.0000,"lower":88.0300,"count":1398,"preSum":26588},{"ndv":293,"upper":94.7000,"lower":89.0100,"count":1088,"preSum":27986},{"ndv":187,"upper":98.6500,"lower":94.7200,"count":1089,"preSum":29074},{"ndv":310,"upper":106.0000,"lower":98.6600,"count":1220,"preSum":30163},{"ndv":270,"upper":112.0000,"lower":106.0100,"count":1139,"preSum":31383},{"ndv":250,"upper":117.0000,"lower":112.0100,"count":1154,"preSum":32522},{"ndv":49,"upper":118.0000,"lower":117.0100,"count":1171,"preSum":33676},{"ndv":367,"upper":126.6200,"lower":118.0100,"count":1088,"preSum":34847},{"ndv":135,"upper":130.0000,"lower":126.6500,"count":1098,"preSum":35935},{"ndv":359,"upper":138.0000,"lower":130.0100,"count":1133,"preSum":37033},{"ndv":175,"upper":142.1800,"lower":138.0100,"count":1091,"preSum":38166},{"ndv":184,"upper":145.0000,"lower":142.1900,"count":1884,"preSum":39257},{"ndv":182,"upper":149.0000,"lower":145.0100,"count":1154,"preSum":41141},{"ndv":318,"upper":158.0000,"lower":149.0100,"count":1563,"preSum":42295},{"ndv":139,"upper":161.6200,"lower":158.0200,"count":1088,"preSum":43858},{"ndv":186,"upper":168.0000,"lower":161.6500,"count":1213,"preSum":44946},{"ndv":343,"upper":178.0000,"lower":168.0100,"count":1236,"preSum":46159},{"ndv":389,"upper":188.0000,"lower":178.0100,"count":1129,"preSum":47395},{"ndv":271,"upper":198.0000,"lower":188.0100,"count":1723,"preSum":48524},{"ndv":176,"upper":205.8300,"lower":198.0300,"count":1088,"preSum":50247},{"ndv":75,"upper":209.0000,"lower":205.8700,"count":1216,"preSum":51335},{"ndv":320,"upper":222.4800,"lower":209.1200,"count":1089,"preSum":52551},{"ndv":396,"upper":234.8000,"lower":222.5000,"count":1089,"preSum":53640},{"ndv":291,"upper":249.0000,"lower":234.8100,"count":1139,"preSum":54729},{"ndv":147,"upper":258.0000,"lower":249.0100,"count":1439,"preSum":55868},{"ndv":205,"upper":269.0000,"lower":258.0800,"count":1261,"preSum":57307},{"ndv":152,"upper":279.0000,"lower":269.0700,"count":1115,"preSum":58568},{"ndv":228,"upper":295.8000,"lower":279.0100,"count":1100,"preSum":59683},{"ndv":273,"upper":322.0000,"lower":295.8300,"count":1105,"preSum":60783},{"ndv":313,"upper":348.0000,"lower":322.0100,"count":1211,"preSum":61888},{"ndv":246,"upper":373.7400,"lower":348.3800,"count":1088,"preSum":63099},{"ndv":332,"upper":421.0000,"lower":373.8000,"count":1090,"preSum":64187},{"ndv":312,"upper":482.2000,"lower":421.0500,"count":1088,"preSum":65277},{"ndv":233,"upper":530.0000,"lower":482.7400,"count":1185,"preSum":66365},{"ndv":426,"upper":691.0000,"lower":530.5000,"count":1094,"preSum":67550},{"ndv":463,"upper":19845.0000,"lower":692.1800,"count":962,"preSum":68644}],"maxBucketSize":64,"type":"Double","sampleRate":0.9618625}','{"countArr":[6563,1403,2005,1374,1347,3148,2905,1301,1238,1327,2579,1384,1959,1862],"valueArr":[0.0000,68.7300,79.0000,85.0000,88.0000,99.0000,108.0000,128.0000,165.0000,170.0000,288.0000,289.0000,398.0000,540.0000],"type":"Double","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','companycode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[4350,270,95381],"valueArr":["JALA01","JALA02","JALA11"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','companytype',12,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"MC","lower":"MC","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1636,9,48],"valueArr":["","JD","QCS"],"type":"String","sampleRate":0.9618625319816094}',98307,0.02436278),('jala_wms_prod','shipment_header','componentscraprate',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','confirmedat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','consolidated',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','created',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','createdby',18,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"gth","lower":"gth","count":1,"preSum":0},{"ndv":1,"upper":"zjf","lower":"zjf","count":1,"preSum":1}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[7,42,3,99884,60,3],"valueArr":["LL","XCY1","YBJ","api","lhj","yj"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','deiverywindow',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','deletedimension',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[53,4],"valueArr":["","X"],"type":"String","sampleRate":0.9618625319816094}',99944,0.02436278),('jala_wms_prod','shipment_header','deliverynote',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','disabledcarriercodes',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','erpordercode',121379,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":177,"upper":"10000272846","lower":"0001622094","count":181,"preSum":0},{"ndv":181,"upper":"10000283492","lower":"10000272918","count":181,"preSum":181},{"ndv":179,"upper":"10000292278","lower":"10000283494","count":181,"preSum":362},{"ndv":179,"upper":"2082670","lower":"10000292280","count":181,"preSum":543},{"ndv":181,"upper":"23042164922064","lower":"2104218","count":181,"preSum":724},{"ndv":181,"upper":"23042358352745","lower":"23042165818874","count":181,"preSum":905},{"ndv":181,"upper":"23042566617374","lower":"23042358863635","count":181,"preSum":1086},{"ndv":181,"upper":"23042640068456","lower":"23042566927603","count":181,"preSum":1267},{"ndv":181,"upper":"23042815282947","lower":"23042641021319","count":181,"preSum":1448},{"ndv":181,"upper":"23043040586702","lower":"23042818243147","count":181,"preSum":1629},{"ndv":181,"upper":"23050266632572","lower":"23043042479818","count":181,"preSum":1810},{"ndv":181,"upper":"23050453002373","lower":"23050267004553","count":181,"preSum":1991},{"ndv":181,"upper":"23050646482143","lower":"23050453159873","count":181,"preSum":2172},{"ndv":181,"upper":"23050911745129","lower":"23050649439618","count":181,"preSum":2353},{"ndv":181,"upper":"23051054115935","lower":"23050911849379","count":181,"preSum":2534},{"ndv":181,"upper":"23051192462429","lower":"23051054133375","count":181,"preSum":2715},{"ndv":181,"upper":"23051330970846","lower":"23051197985839","count":181,"preSum":2896},{"ndv":181,"upper":"23051509628329","lower":"23051331443546","count":181,"preSum":3077},{"ndv":181,"upper":"23051690618154","lower":"23051510117653","count":181,"preSum":3258},{"ndv":181,"upper":"23051861738603","lower":"23051690749977","count":181,"preSum":3439},{"ndv":181,"upper":"23052018969076","lower":"23051861934403","count":181,"preSum":3620},{"ndv":181,"upper":"23052271106735","lower":"23052019236376","count":181,"preSum":3801},{"ndv":181,"upper":"23052479111946","lower":"23052271419654","count":181,"preSum":3982},{"ndv":181,"upper":"23052623868239","lower":"23052480362126","count":181,"preSum":4163},{"ndv":181,"upper":"23052839895812","lower":"23052624425029","count":181,"preSum":4344},{"ndv":181,"upper":"23053012462010","lower":"23052848414712","count":181,"preSum":4525},{"ndv":181,"upper":"23053161050965","lower":"23053013348549","count":181,"preSum":4706},{"ndv":181,"upper":"23060155844953","lower":"23053161744865","count":181,"preSum":4887},{"ndv":181,"upper":"23060290553066","lower":"23060160559012","count":181,"preSum":5068},{"ndv":181,"upper":"23060426941268","lower":"23060290583766","count":181,"preSum":5249},{"ndv":181,"upper":"23060666065143","lower":"23060426945668","count":181,"preSum":5430},{"ndv":181,"upper":"23060851822269","lower":"23060666380228","count":181,"preSum":5611},{"ndv":181,"upper":"23061022236627","lower":"23060852753369","count":181,"preSum":5792},{"ndv":181,"upper":"23061232978129","lower":"23061022973327","count":181,"preSum":5973},{"ndv":181,"upper":"23061374694064","lower":"23061233449784","count":181,"preSum":6154},{"ndv":181,"upper":"23061570333337","lower":"23061379981157","count":181,"preSum":6335},{"ndv":181,"upper":"23061702908313","lower":"23061570811202","count":181,"preSum":6516},{"ndv":181,"upper":"23061805079805","lower":"23061703134113","count":181,"preSum":6697},{"ndv":181,"upper":"23061890242485","lower":"23061806402260","count":181,"preSum":6878},{"ndv":181,"upper":"23062006197459","lower":"23061890381156","count":181,"preSum":7059},{"ndv":181,"upper":"23062314907906","lower":"23062008552459","count":181,"preSum":7240},{"ndv":181,"upper":"23062641456265","lower":"23062316757406","count":181,"preSum":7421},{"ndv":180,"upper":"40000198040","lower":"23062642898165","count":181,"preSum":7602},{"ndv":179,"upper":"40000208772","lower":"40000198047","count":181,"preSum":7783},{"ndv":181,"upper":"40000221006","lower":"40000208792","count":181,"preSum":7964},{"ndv":181,"upper":"40000231919","lower":"40000221014","count":181,"preSum":8145},{"ndv":181,"upper":"CK0001181748","lower":"40000231928","count":181,"preSum":8326},{"ndv":178,"upper":"CK0001209645","lower":"CK0001181750","count":181,"preSum":8507},{"ndv":180,"upper":"CK0001265472","lower":"CK0001209646","count":181,"preSum":8688},{"ndv":181,"upper":"CK0001303367","lower":"CK0001268729","count":181,"preSum":8869},{"ndv":181,"upper":"CK0001351565","lower":"CK0001303399","count":181,"preSum":9050},{"ndv":180,"upper":"CK0001398414","lower":"CK0001351576","count":181,"preSum":9231},{"ndv":181,"upper":"CK0001446898","lower":"CK0001398439","count":181,"preSum":9412},{"ndv":181,"upper":"CK0001466891","lower":"CK0001446908","count":181,"preSum":9593},{"ndv":181,"upper":"CK0001482734","lower":"CK0001466892","count":181,"preSum":9774},{"ndv":181,"upper":"CK0001492075","lower":"CK0001482751","count":181,"preSum":9955},{"ndv":180,"upper":"CK0001504667","lower":"CK0001492261","count":181,"preSum":10136},{"ndv":180,"upper":"CK0001521946","lower":"CK0001504670","count":181,"preSum":10317},{"ndv":181,"upper":"CK0001530290","lower":"CK0001521947","count":181,"preSum":10498},{"ndv":181,"upper":"CK0001543239","lower":"CK0001530339","count":181,"preSum":10679},{"ndv":181,"upper":"CK0001560203","lower":"CK0001543408","count":181,"preSum":10860},{"ndv":181,"upper":"CK0001575094","lower":"CK0001560209","count":181,"preSum":11041},{"ndv":181,"upper":"CKH00000009403","lower":"CK0001575096","count":181,"preSum":11222},{"ndv":126,"upper":"CKH00000015274","lower":"CKH00000009412","count":126,"preSum":11403}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[88363,3],"valueArr":["","1200009297"],"type":"String","sampleRate":0.9618625319816094}',106,0.02436278),('jala_wms_prod','shipment_header','erporderid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','erpordertype',16,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"MM011","lower":"MM011","count":1,"preSum":0},{"ndv":1,"upper":"MM021","lower":"MM021","count":2,"preSum":1}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[9,57,1282,118,95363,3052],"valueArr":["MM018","PP001","QM001","SDI17","deliveryorder","stockout"],"type":"String","sampleRate":0.9618625319816094}',117,0.02436278),('jala_wms_prod','shipment_header','finalshipment',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[39,18],"valueArr":["","X"],"type":"String","sampleRate":0.9618625319816094}',99944,0.02436278),('jala_wms_prod','shipment_header','fromwarehousecode',18,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"W005","lower":"W005","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[28,126,31,39,1199,27,4,3,46],"valueArr":["","D001","D002","D003","D011","W002","W007","W009","W028"],"type":"String","sampleRate":0.9618625319816094}',98497,0.02436278),('jala_wms_prod','shipment_header','groupindex',1557,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":14,"lower":14,"count":2804,"preSum":0},{"ndv":1,"upper":15,"lower":15,"count":2724,"preSum":2804},{"ndv":1,"upper":16,"lower":16,"count":2647,"preSum":5528},{"ndv":1,"upper":17,"lower":17,"count":2542,"preSum":8175},{"ndv":1,"upper":18,"lower":18,"count":2544,"preSum":10717},{"ndv":1,"upper":19,"lower":19,"count":2469,"preSum":13261},{"ndv":1,"upper":20,"lower":20,"count":2382,"preSum":15730},{"ndv":2,"upper":22,"lower":21,"count":1358,"preSum":18112},{"ndv":2,"upper":24,"lower":23,"count":1300,"preSum":19470},{"ndv":2,"upper":26,"lower":25,"count":1133,"preSum":20770},{"ndv":2,"upper":28,"lower":27,"count":1017,"preSum":21903},{"ndv":2,"upper":30,"lower":29,"count":912,"preSum":22920},{"ndv":2,"upper":32,"lower":31,"count":880,"preSum":23832},{"ndv":2,"upper":34,"lower":33,"count":865,"preSum":24712},{"ndv":2,"upper":36,"lower":35,"count":788,"preSum":25577},{"ndv":3,"upper":39,"lower":37,"count":1109,"preSum":26365},{"ndv":3,"upper":42,"lower":40,"count":1084,"preSum":27474},{"ndv":3,"upper":45,"lower":43,"count":1050,"preSum":28558},{"ndv":3,"upper":48,"lower":46,"count":962,"preSum":29608},{"ndv":3,"upper":51,"lower":49,"count":974,"preSum":30570},{"ndv":3,"upper":54,"lower":52,"count":889,"preSum":31544},{"ndv":3,"upper":57,"lower":55,"count":889,"preSum":32433},{"ndv":3,"upper":60,"lower":58,"count":876,"preSum":33322},{"ndv":3,"upper":63,"lower":61,"count":790,"preSum":34198},{"ndv":3,"upper":66,"lower":64,"count":774,"preSum":34988},{"ndv":3,"upper":69,"lower":67,"count":761,"preSum":35762},{"ndv":4,"upper":73,"lower":70,"count":1003,"preSum":36523},{"ndv":4,"upper":77,"lower":74,"count":938,"preSum":37526},{"ndv":4,"upper":81,"lower":78,"count":965,"preSum":38464},{"ndv":4,"upper":85,"lower":82,"count":926,"preSum":39429},{"ndv":4,"upper":89,"lower":86,"count":893,"preSum":40355},{"ndv":4,"upper":93,"lower":90,"count":852,"preSum":41248},{"ndv":4,"upper":97,"lower":94,"count":876,"preSum":42100},{"ndv":7,"upper":104,"lower":98,"count":790,"preSum":42976},{"ndv":16,"upper":120,"lower":105,"count":785,"preSum":43766},{"ndv":23,"upper":143,"lower":121,"count":765,"preSum":44551},{"ndv":38,"upper":181,"lower":144,"count":764,"preSum":45316},{"ndv":90,"upper":271,"lower":182,"count":759,"preSum":46080},{"ndv":153,"upper":426,"lower":272,"count":760,"preSum":46839},{"ndv":327,"upper":996,"lower":427,"count":712,"preSum":47599}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6479,6046,3757,3593,3564,3440,3233,3352,3221,3193,3068,2937,2911,2896],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','groupnum',252,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":14,"lower":14,"count":429,"preSum":0},{"ndv":1,"upper":15,"lower":15,"count":426,"preSum":429},{"ndv":1,"upper":16,"lower":16,"count":361,"preSum":855},{"ndv":1,"upper":17,"lower":17,"count":349,"preSum":1216},{"ndv":1,"upper":18,"lower":18,"count":339,"preSum":1565},{"ndv":1,"upper":19,"lower":19,"count":323,"preSum":1904},{"ndv":1,"upper":20,"lower":20,"count":337,"preSum":2227},{"ndv":1,"upper":21,"lower":21,"count":312,"preSum":2564},{"ndv":1,"upper":22,"lower":22,"count":346,"preSum":2876},{"ndv":1,"upper":23,"lower":23,"count":303,"preSum":3222},{"ndv":1,"upper":24,"lower":24,"count":294,"preSum":3525},{"ndv":1,"upper":25,"lower":25,"count":257,"preSum":3819},{"ndv":1,"upper":26,"lower":26,"count":266,"preSum":4076},{"ndv":1,"upper":27,"lower":27,"count":261,"preSum":4342},{"ndv":1,"upper":28,"lower":28,"count":230,"preSum":4603},{"ndv":1,"upper":29,"lower":29,"count":205,"preSum":4833},{"ndv":1,"upper":30,"lower":30,"count":206,"preSum":5038},{"ndv":1,"upper":31,"lower":31,"count":180,"preSum":5244},{"ndv":1,"upper":32,"lower":32,"count":193,"preSum":5424},{"ndv":1,"upper":33,"lower":33,"count":192,"preSum":5617},{"ndv":1,"upper":34,"lower":34,"count":205,"preSum":5809},{"ndv":1,"upper":35,"lower":35,"count":163,"preSum":6014},{"ndv":1,"upper":36,"lower":36,"count":159,"preSum":6177},{"ndv":1,"upper":37,"lower":37,"count":187,"preSum":6336},{"ndv":1,"upper":38,"lower":38,"count":175,"preSum":6523},{"ndv":2,"upper":40,"lower":39,"count":300,"preSum":6698},{"ndv":1,"upper":41,"lower":41,"count":154,"preSum":6998},{"ndv":2,"upper":43,"lower":42,"count":277,"preSum":7152},{"ndv":2,"upper":45,"lower":44,"count":243,"preSum":7429},{"ndv":2,"upper":47,"lower":46,"count":178,"preSum":7672},{"ndv":2,"upper":49,"lower":48,"count":154,"preSum":7850},{"ndv":2,"upper":51,"lower":50,"count":159,"preSum":8004},{"ndv":3,"upper":54,"lower":52,"count":199,"preSum":8163},{"ndv":3,"upper":57,"lower":55,"count":204,"preSum":8362},{"ndv":4,"upper":61,"lower":58,"count":193,"preSum":8566},{"ndv":4,"upper":65,"lower":62,"count":159,"preSum":8759},{"ndv":5,"upper":70,"lower":66,"count":156,"preSum":8918},{"ndv":6,"upper":76,"lower":71,"count":156,"preSum":9074},{"ndv":12,"upper":88,"lower":77,"count":155,"preSum":9230},{"ndv":21,"upper":109,"lower":89,"count":151,"preSum":9385},{"ndv":34,"upper":181,"lower":110,"count":58,"preSum":9536}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6479,61860,6524,4417,2938,2557,1089,924,781,668,633,537,526,474],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','hostcompanycode',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2771,269,95375],"valueArr":["JALA01","JALA02","JALA11"],"type":"String","sampleRate":0.9618625319816094}',1586,0.02436278),('jala_wms_prod','shipment_header','hxqty',20,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":1,"lower":1,"count":1,"preSum":0},{"ndv":1,"upper":2,"lower":2,"count":1,"preSum":1}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[99999],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','id',4013259,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1563,"upper":2320037,"lower":1243547,"count":1563,"preSum":0},{"ndv":1563,"upper":2854825,"lower":2320039,"count":1563,"preSum":1563},{"ndv":1563,"upper":3018683,"lower":2854829,"count":1563,"preSum":3126},{"ndv":1563,"upper":3267347,"lower":3018686,"count":1563,"preSum":4689},{"ndv":1563,"upper":3570762,"lower":3267352,"count":1563,"preSum":6252},{"ndv":1563,"upper":3725443,"lower":3570764,"count":1563,"preSum":7815},{"ndv":1563,"upper":3840245,"lower":3731625,"count":1563,"preSum":9378},{"ndv":1563,"upper":3933386,"lower":3840248,"count":1563,"preSum":10941},{"ndv":1563,"upper":4032802,"lower":3933387,"count":1563,"preSum":12504},{"ndv":1563,"upper":4127019,"lower":4032807,"count":1563,"preSum":14067},{"ndv":1563,"upper":4208308,"lower":4127023,"count":1563,"preSum":15630},{"ndv":1563,"upper":4294785,"lower":4208311,"count":1563,"preSum":17193},{"ndv":1563,"upper":4478565,"lower":4294787,"count":1563,"preSum":18756},{"ndv":1563,"upper":4543626,"lower":4478567,"count":1563,"preSum":20319},{"ndv":1563,"upper":4616053,"lower":4543639,"count":1563,"preSum":21882},{"ndv":1563,"upper":4682676,"lower":4616055,"count":1563,"preSum":23445},{"ndv":1563,"upper":4772414,"lower":4682682,"count":1563,"preSum":25008},{"ndv":1563,"upper":4897135,"lower":4772431,"count":1563,"preSum":26571},{"ndv":1563,"upper":4996102,"lower":4897137,"count":1563,"preSum":28134},{"ndv":1563,"upper":5079992,"lower":4996106,"count":1563,"preSum":29697},{"ndv":1563,"upper":5154802,"lower":5080026,"count":1563,"preSum":31260},{"ndv":1563,"upper":5237738,"lower":5154803,"count":1563,"preSum":32823},{"ndv":1563,"upper":5320607,"lower":5237750,"count":1563,"preSum":34386},{"ndv":1563,"upper":5409469,"lower":5320620,"count":1563,"preSum":35949},{"ndv":1563,"upper":5478824,"lower":5409472,"count":1563,"preSum":37512},{"ndv":1563,"upper":5558259,"lower":5478828,"count":1563,"preSum":39075},{"ndv":1563,"upper":5655872,"lower":5558346,"count":1563,"preSum":40638},{"ndv":1563,"upper":5741191,"lower":5655875,"count":1563,"preSum":42201},{"ndv":1563,"upper":5824365,"lower":5741192,"count":1563,"preSum":43764},{"ndv":1563,"upper":5912718,"lower":5824391,"count":1563,"preSum":45327},{"ndv":1563,"upper":5996901,"lower":5912724,"count":1563,"preSum":46890},{"ndv":1563,"upper":6063189,"lower":5996908,"count":1563,"preSum":48453},{"ndv":1563,"upper":6138100,"lower":6063193,"count":1563,"preSum":50016},{"ndv":1563,"upper":6197258,"lower":6138139,"count":1563,"preSum":51579},{"ndv":1563,"upper":6265766,"lower":6197259,"count":1563,"preSum":53142},{"ndv":1563,"upper":6332967,"lower":6265777,"count":1563,"preSum":54705},{"ndv":1563,"upper":6406748,"lower":6332970,"count":1563,"preSum":56268},{"ndv":1563,"upper":6481181,"lower":6406822,"count":1563,"preSum":57831},{"ndv":1563,"upper":6559013,"lower":6481199,"count":1563,"preSum":59394},{"ndv":1563,"upper":6635519,"lower":6559016,"count":1563,"preSum":60957},{"ndv":1563,"upper":6709433,"lower":6635532,"count":1563,"preSum":62520},{"ndv":1563,"upper":6790495,"lower":6709437,"count":1563,"preSum":64083},{"ndv":1563,"upper":6863630,"lower":6790497,"count":1563,"preSum":65646},{"ndv":1563,"upper":6944790,"lower":6863638,"count":1563,"preSum":67209},{"ndv":1563,"upper":7024344,"lower":6944793,"count":1563,"preSum":68772},{"ndv":1563,"upper":7091282,"lower":7024356,"count":1563,"preSum":70335},{"ndv":1563,"upper":7171908,"lower":7091284,"count":1563,"preSum":71898},{"ndv":1563,"upper":7264317,"lower":7171920,"count":1563,"preSum":73461},{"ndv":1563,"upper":7341643,"lower":7264355,"count":1563,"preSum":75024},{"ndv":1563,"upper":7422568,"lower":7341644,"count":1563,"preSum":76587},{"ndv":1563,"upper":7504425,"lower":7422576,"count":1563,"preSum":78150},{"ndv":1563,"upper":7587833,"lower":7504429,"count":1563,"preSum":79713},{"ndv":1563,"upper":7664924,"lower":7587845,"count":1563,"preSum":81276},{"ndv":1563,"upper":7735933,"lower":7664938,"count":1563,"preSum":82839},{"ndv":1563,"upper":7815122,"lower":7735976,"count":1563,"preSum":84402},{"ndv":1563,"upper":7889073,"lower":7815124,"count":1563,"preSum":85965},{"ndv":1563,"upper":7969114,"lower":7889076,"count":1563,"preSum":87528},{"ndv":1563,"upper":8033738,"lower":7969118,"count":1563,"preSum":89091},{"ndv":1563,"upper":8109820,"lower":8033766,"count":1563,"preSum":90654},{"ndv":1563,"upper":8180750,"lower":8109821,"count":1563,"preSum":92217},{"ndv":1563,"upper":8260166,"lower":8180792,"count":1563,"preSum":93780},{"ndv":1563,"upper":8354855,"lower":8260170,"count":1563,"preSum":95343},{"ndv":1563,"upper":8431067,"lower":8354863,"count":1563,"preSum":96906},{"ndv":1532,"upper":8531756,"lower":8431206,"count":1532,"preSum":98469}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}',null,0,0.02436278),('jala_wms_prod','shipment_header','insurerequired',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','invoicecontent',11797,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=06D532496252","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=008032557584","count":18,"preSum":0},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=0iuw32506176","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=078n32688115","count":18,"preSum":18},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=11A932564637","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=0J7O32625717","count":18,"preSum":36},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=172532522036","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=12Pn32548699","count":18,"preSum":54},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=1G0732678714","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=178V32566640","count":18,"preSum":72},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=1Ub732598604","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=1G1p32673567","count":18,"preSum":90},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=236332367326","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=1Ul032637067","count":18,"preSum":108},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=29s432510267","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=23Pq32481723","count":18,"preSum":126},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=2m0d32521103","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=2agz32499602","count":18,"preSum":144},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=32g332653704","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=2Nf932551579","count":18,"preSum":162},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=396532584579","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=32Y532551711","count":18,"preSum":180},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=3G7R32637308","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=398732629375","count":18,"preSum":198},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=401432608420","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=3HwT32672052","count":18,"preSum":216},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=45L632631572","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=40o632637126","count":18,"preSum":234},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=4c1232496880","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=462f32627167","count":18,"preSum":252},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=4yP232523331","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=4d7C32552734","count":18,"preSum":270},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=56vx32679410","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=4zkT32672521","count":18,"preSum":288},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=5E3632541499","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=572232582187","count":18,"preSum":306},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=5Y2z32508052","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=5E8G32506189","count":18,"preSum":324},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=683t32520613","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=5yb732427445","count":18,"preSum":342},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=6g9032497272","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=68U832608168","count":18,"preSum":360},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=6zh932562973","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=6Gq232614929","count":18,"preSum":378},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=784X32680395","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=70ko32630090","count":18,"preSum":396},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=7H1b32494097","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=787032672244","count":18,"preSum":414},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=7Y6132561532","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=7I0832683621","count":18,"preSum":432},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=871y32506119","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=7Yee32643036","count":18,"preSum":450},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=8EB332564366","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=876632563898","count":18,"preSum":468},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=907f32542757","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=8ER232626905","count":18,"preSum":486},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=949432534730","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=90Gm32637164","count":18,"preSum":504},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=9EkL32582446","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=94B532644121","count":18,"preSum":522},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=9Z2632502300","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=9EvO32538207","count":18,"preSum":540},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=AbxV32645782","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=9z3G32677051","count":18,"preSum":558},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=B3b532552013","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=Ac1932545250","count":18,"preSum":576},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Bt8n32590024","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=b3jm32564776","count":18,"preSum":594},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=cuS232535551","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=BV5832545301","count":18,"preSum":612},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=da8432669307","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=CW3l32686982","count":18,"preSum":630},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=E87d32603593","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=DC1a32580008","count":18,"preSum":648},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=eR2632534712","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=e8c532525939","count":18,"preSum":666},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=G0R032492470","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=ESeu32505570","count":18,"preSum":684},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=gIcY32541416","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=g10232382077","count":18,"preSum":702},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=H7ej32501364","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=Gm3w32642175","count":18,"preSum":720},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=i40932608153","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=hBA932582261","count":18,"preSum":738},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=j49032682225","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=i42832568721","count":18,"preSum":756},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=k27S32678095","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=j52032557585","count":18,"preSum":774},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=L0CM32659807","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=k33432680023","count":18,"preSum":792},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=m11Q32662388","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=l18g32501359","count":18,"preSum":810},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Mrme32417406","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=M20b32567132","count":18,"preSum":828},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=nj7X32565954","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=msug32535828","count":18,"preSum":846},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Odr132537530","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=nLoX32637179","count":18,"preSum":864},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=P9ea32680345","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=oDU832620560","count":18,"preSum":882},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Q53432624640","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=pAy732661853","count":18,"preSum":900},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=QWt132678212","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=q54L32580120","count":18,"preSum":918},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=rw7H32673474","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=qZ1H32634442","count":18,"preSum":936},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Sn7f32506191","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=RX7932501012","count":18,"preSum":954},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=tg6a32607288","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=spuX32642858","count":18,"preSum":972},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=UN4932550386","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=tH4132613460","count":18,"preSum":990},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=VIRy32540409","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=Uqp132578223","count":18,"preSum":1008},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=W8QY32559316","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=VK3532563862","count":18,"preSum":1026},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=X67232603590","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=wB1u32685036","count":18,"preSum":1044},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Y1c032574150","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=X67832684049","count":18,"preSum":1062},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=Z01y32438604","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=y4s432579457","count":18,"preSum":1080},{"ndv":18,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=ZunD32497786","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=z06P32541614","count":18,"preSum":1098},{"ndv":1,"upper":"http://ec.jala.com.cn/eis-api/qr.service?id=zZK732649202","lower":"http://ec.jala.com.cn/eis-api/qr.service?id=zZK732649202","count":1,"preSum":1116}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',98854,0.02436278),('jala_wms_prod','shipment_header','invoiceheader',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','invoicerequired',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','invoicetype',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','itemcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','lastupdated',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','lastupdatedby',121,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":"1000003","lower":"02700010","count":6,"preSum":0},{"ndv":1,"upper":"1000004","lower":"1000004","count":4,"preSum":6},{"ndv":2,"upper":"chendaolong","lower":"bry","count":16,"preSum":10},{"ndv":2,"upper":"CSS","lower":"CN","count":8,"preSum":26},{"ndv":2,"upper":"DH","lower":"CXN","count":4,"preSum":34},{"ndv":1,"upper":"gth","lower":"gth","count":13,"preSum":38},{"ndv":3,"upper":"LL","lower":"jiyinghao","count":12,"preSum":51},{"ndv":1,"upper":"LML","lower":"LML","count":16,"preSum":63},{"ndv":1,"upper":"lxp","lower":"lxp","count":11,"preSum":79},{"ndv":2,"upper":"lyg","lower":"LY","count":6,"preSum":90},{"ndv":1,"upper":"LYM","lower":"LYM","count":6,"preSum":96},{"ndv":1,"upper":"MLP","lower":"MLP","count":23,"preSum":102},{"ndv":4,"upper":"sfzhaohuqi","lower":"PZ","count":4,"preSum":125},{"ndv":1,"upper":"SHB","lower":"SHB","count":9,"preSum":129},{"ndv":1,"upper":"suchenbo","lower":"suchenbo","count":8,"preSum":138},{"ndv":1,"upper":"sunyingying","lower":"sunyingying","count":7,"preSum":146},{"ndv":2,"upper":"wangyong","lower":"sw","count":4,"preSum":153},{"ndv":1,"upper":"WQ","lower":"WQ","count":25,"preSum":157},{"ndv":1,"upper":"XCY","lower":"XCY","count":5,"preSum":182},{"ndv":1,"upper":"YBJ","lower":"YBJ","count":4,"preSum":187},{"ndv":1,"upper":"yj","lower":"yj","count":5,"preSum":191},{"ndv":2,"upper":"ZH","lower":"yxy","count":4,"preSum":196},{"ndv":2,"upper":"zjf","lower":"zhangkeming","count":8,"preSum":200}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[193,35,35,186,69,43,151,66,98770,63,60,34,53,35],"valueArr":["BMJ","HP","JQQ","LSH","WK","XCY1","YJR","ZLF","api","gzj","lhj","liyinghao","shenmengliang","zhangguishun"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','lastwaveid',35103,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":161,"upper":554473,"lower":667,"count":247,"preSum":0},{"ndv":126,"upper":686871,"lower":554474,"count":247,"preSum":247},{"ndv":125,"upper":741796,"lower":686872,"count":243,"preSum":494},{"ndv":128,"upper":749124,"lower":741799,"count":247,"preSum":737},{"ndv":63,"upper":752552,"lower":749144,"count":254,"preSum":984},{"ndv":82,"upper":766996,"lower":752556,"count":243,"preSum":1238},{"ndv":101,"upper":774106,"lower":767001,"count":248,"preSum":1481},{"ndv":99,"upper":787652,"lower":774160,"count":244,"preSum":1729},{"ndv":85,"upper":790848,"lower":787653,"count":244,"preSum":1973},{"ndv":93,"upper":796852,"lower":790915,"count":243,"preSum":2217},{"ndv":130,"upper":807509,"lower":797410,"count":243,"preSum":2460},{"ndv":110,"upper":818455,"lower":807510,"count":243,"preSum":2703},{"ndv":40,"upper":819811,"lower":818456,"count":243,"preSum":2946},{"ndv":72,"upper":820731,"lower":819870,"count":250,"preSum":3189},{"ndv":62,"upper":822121,"lower":820732,"count":246,"preSum":3439},{"ndv":80,"upper":826571,"lower":822123,"count":243,"preSum":3685},{"ndv":118,"upper":840339,"lower":826572,"count":246,"preSum":3928},{"ndv":58,"upper":848957,"lower":840340,"count":243,"preSum":4174},{"ndv":97,"upper":871276,"lower":850177,"count":249,"preSum":4417},{"ndv":79,"upper":878982,"lower":871277,"count":253,"preSum":4666},{"ndv":88,"upper":888439,"lower":878983,"count":244,"preSum":4919},{"ndv":102,"upper":906774,"lower":888441,"count":257,"preSum":5163},{"ndv":104,"upper":923645,"lower":906777,"count":243,"preSum":5420},{"ndv":116,"upper":935051,"lower":923646,"count":249,"preSum":5663},{"ndv":125,"upper":950615,"lower":935052,"count":246,"preSum":5912},{"ndv":90,"upper":962950,"lower":950724,"count":245,"preSum":6158},{"ndv":84,"upper":974544,"lower":963647,"count":244,"preSum":6403},{"ndv":135,"upper":995726,"lower":974560,"count":249,"preSum":6647},{"ndv":79,"upper":1006315,"lower":995855,"count":253,"preSum":6896},{"ndv":92,"upper":1015708,"lower":1006318,"count":243,"preSum":7149},{"ndv":117,"upper":1021777,"lower":1015709,"count":243,"preSum":7392},{"ndv":91,"upper":1028243,"lower":1021778,"count":243,"preSum":7635},{"ndv":103,"upper":1031884,"lower":1028245,"count":243,"preSum":7878},{"ndv":100,"upper":1037011,"lower":1031888,"count":244,"preSum":8121},{"ndv":79,"upper":1038215,"lower":1037067,"count":244,"preSum":8365},{"ndv":71,"upper":1041397,"lower":1038216,"count":245,"preSum":8609},{"ndv":82,"upper":1042905,"lower":1041409,"count":247,"preSum":8854},{"ndv":30,"upper":1043017,"lower":1042907,"count":243,"preSum":9101},{"ndv":111,"upper":1045090,"lower":1043071,"count":244,"preSum":9344},{"ndv":83,"upper":1047617,"lower":1045091,"count":245,"preSum":9588},{"ndv":38,"upper":1048906,"lower":1047620,"count":245,"preSum":9833},{"ndv":96,"upper":1051513,"lower":1048909,"count":244,"preSum":10078},{"ndv":109,"upper":1053072,"lower":1051514,"count":244,"preSum":10322},{"ndv":105,"upper":1057713,"lower":1053073,"count":243,"preSum":10566},{"ndv":149,"upper":1070475,"lower":1057719,"count":247,"preSum":10809},{"ndv":85,"upper":1074655,"lower":1070527,"count":243,"preSum":11056},{"ndv":120,"upper":1095472,"lower":1074662,"count":252,"preSum":11299},{"ndv":68,"upper":1106461,"lower":1095483,"count":244,"preSum":11551},{"ndv":111,"upper":1127309,"lower":1106465,"count":254,"preSum":11795},{"ndv":93,"upper":1145273,"lower":1127310,"count":244,"preSum":12049},{"ndv":117,"upper":1162150,"lower":1145275,"count":247,"preSum":12293},{"ndv":114,"upper":1176544,"lower":1162151,"count":243,"preSum":12540},{"ndv":114,"upper":1186044,"lower":1176546,"count":243,"preSum":12783},{"ndv":120,"upper":1189281,"lower":1186045,"count":245,"preSum":13026},{"ndv":123,"upper":1194516,"lower":1189283,"count":250,"preSum":13271},{"ndv":86,"upper":1197990,"lower":1194517,"count":255,"preSum":13521},{"ndv":108,"upper":1203024,"lower":1198031,"count":249,"preSum":13776},{"ndv":109,"upper":1207404,"lower":1203025,"count":253,"preSum":14025},{"ndv":109,"upper":1212918,"lower":1207405,"count":243,"preSum":14278},{"ndv":58,"upper":1213472,"lower":1212919,"count":243,"preSum":14521},{"ndv":126,"upper":1225047,"lower":1213474,"count":245,"preSum":14764},{"ndv":117,"upper":1256327,"lower":1225049,"count":243,"preSum":15009},{"ndv":140,"upper":1303778,"lower":1256590,"count":238,"preSum":15252}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[84092,58,38,33,32,30,45,32,70,50,31],"valueArr":[0,767240,767251,818705,898400,961794,1041136,1047764,1060758,1186390,1205889],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','leadingsts',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":400,"lower":400,"count":2,"preSum":0}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6391,5,28,93575],"valueArr":[100,300,600,900],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','loadid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','lockcode',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[8,71,639,14],"valueArr":["","MSG_WBLL_0005","MSG_WBLL_0010","等待获取电子面单号"],"type":"String","sampleRate":0.9618625319816094}',99269,0.02436278),('jala_wms_prod','shipment_header','logisticsservices',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','manufacturer',18,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"2000","lower":"2000","count":1,"preSum":0},{"ndv":1,"upper":"2030","lower":"2030","count":1,"preSum":1}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1355,3],"valueArr":["1000","1050"],"type":"String","sampleRate":0.9618625319816094}',98641,0.02436278),('jala_wms_prod','shipment_header','materialdocumentyear',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','neworderdate',165,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":29,"upper":"1850821117174874112","lower":"1850708966988840960","count":1040,"preSum":0},{"ndv":8,"upper":"1850847505453940736","lower":"1850823316198129664","count":1163,"preSum":1040},{"ndv":5,"upper":"1850858500570218496","lower":"1850849704477196288","count":993,"preSum":2203},{"ndv":10,"upper":"1850880490802774016","lower":"1850860699593474048","count":979,"preSum":3196},{"ndv":13,"upper":"1850911277128351744","lower":"1850882689826029568","count":1016,"preSum":4175},{"ndv":10,"upper":"1850933267360907264","lower":"1850913476151607296","count":1134,"preSum":5191},{"ndv":5,"upper":"1850944262477185024","lower":"1850935466384162816","count":1064,"preSum":6325},{"ndv":3,"upper":"1850950859546951680","lower":"1850946461500440576","count":1021,"preSum":7389},{"ndv":2,"upper":"1850955257593462784","lower":"1850953058570207232","count":1413,"preSum":8410},{"ndv":2,"upper":"1850959655639973888","lower":"1850957456616718336","count":1367,"preSum":9823},{"ndv":2,"upper":"1850964053686484992","lower":"1850961854663229440","count":1897,"preSum":11190},{"ndv":2,"upper":"1850968451732996096","lower":"1850966252709740544","count":1722,"preSum":13087},{"ndv":1,"upper":"1850970650756251648","lower":"1850970650756251648","count":1473,"preSum":14809},{"ndv":2,"upper":"1850975048802762752","lower":"1850972849779507200","count":1307,"preSum":16282},{"ndv":1,"upper":"1850981645872529408","lower":"1850981645872529408","count":1159,"preSum":17589},{"ndv":1,"upper":"1850983844895784960","lower":"1850983844895784960","count":1399,"preSum":18748},{"ndv":1,"upper":"1850988242942296064","lower":"1850988242942296064","count":1203,"preSum":20147},{"ndv":2,"upper":"1850992640988807168","lower":"1850990441965551616","count":1799,"preSum":21350},{"ndv":2,"upper":"1850997039035318272","lower":"1850994840012062720","count":1649,"preSum":23149},{"ndv":1,"upper":"1850999238058573824","lower":"1850999238058573824","count":1008,"preSum":24798},{"ndv":1,"upper":"1851001437081829376","lower":"1851001437081829376","count":1210,"preSum":25806},{"ndv":1,"upper":"1851003636105084928","lower":"1851003636105084928","count":1093,"preSum":27016},{"ndv":1,"upper":"1851005835128340480","lower":"1851005835128340480","count":1033,"preSum":28109},{"ndv":2,"upper":"1851010233174851584","lower":"1851008034151596032","count":1986,"preSum":29142},{"ndv":2,"upper":"1851014631221362688","lower":"1851012432198107136","count":1885,"preSum":31128},{"ndv":1,"upper":"1851019029267873792","lower":"1851019029267873792","count":1048,"preSum":33013},{"ndv":2,"upper":"1851023427314384896","lower":"1851021228291129344","count":1804,"preSum":34061},{"ndv":2,"upper":"1851027825360896000","lower":"1851025626337640448","count":1813,"preSum":35865},{"ndv":2,"upper":"1851032223407407104","lower":"1851030024384151552","count":1835,"preSum":37678},{"ndv":2,"upper":"1851036621453918208","lower":"1851034422430662656","count":1526,"preSum":39513},{"ndv":1,"upper":"1851043218523684864","lower":"1851043218523684864","count":1412,"preSum":41039},{"ndv":1,"upper":"1851045417546940416","lower":"1851045417546940416","count":1408,"preSum":42451},{"ndv":1,"upper":"1851058611686473728","lower":"1851058611686473728","count":1519,"preSum":43859},{"ndv":1,"upper":"1851060810709729280","lower":"1851060810709729280","count":1306,"preSum":45378},{"ndv":1,"upper":"1851063009732984832","lower":"1851063009732984832","count":1354,"preSum":46684},{"ndv":1,"upper":"1851065208756240384","lower":"1851065208756240384","count":967,"preSum":48038},{"ndv":2,"upper":"1851069606802751488","lower":"1851067407779495936","count":1773,"preSum":49005},{"ndv":2,"upper":"1851074004849262592","lower":"1851071805826007040","count":1846,"preSum":50778},{"ndv":1,"upper":"1851076203872518144","lower":"1851076203872518144","count":977,"preSum":52624},{"ndv":1,"upper":"1851078402895773696","lower":"1851078402895773696","count":1223,"preSum":53601},{"ndv":2,"upper":"1851093796058562560","lower":"1851080601919029248","count":2081,"preSum":54824},{"ndv":2,"upper":"1851098194105073664","lower":"1851095995081818112","count":1189,"preSum":56905},{"ndv":2,"upper":"1851102592151584768","lower":"1851100393128329216","count":984,"preSum":58094},{"ndv":2,"upper":"1851106990198095872","lower":"1851104791174840320","count":1172,"preSum":59078},{"ndv":2,"upper":"1851111388244606976","lower":"1851109189221351424","count":1090,"preSum":60250},{"ndv":1,"upper":"1851113587267862528","lower":"1851113587267862528","count":135,"preSum":61340}],"maxBucketSize":64,"type":"Date","sampleRate":0.9618625}','{"countArr":[1558,3128,1888,7101,2249,3414,2507,1924,1705,2085,2718,2422,3700,2127],"valueArr":[-1,1850986043919040512,1851016830244618240,1851038820477173760,1851041019500429312,1851047616570195968,1851052014616707072,1851054213639962624,1851056412663218176,1851082800942284800,1851084999965540352,1851087198988795904,1851089398012051456,1851091597035307008],"type":"Date","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','orderdate',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','originalorderid',249,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":1264825,"lower":1264825,"count":1,"preSum":0},{"ndv":1,"upper":1273722,"lower":1273722,"count":1,"preSum":1},{"ndv":1,"upper":1273743,"lower":1273743,"count":1,"preSum":2},{"ndv":1,"upper":1273747,"lower":1273747,"count":2,"preSum":3},{"ndv":1,"upper":1336188,"lower":1336188,"count":1,"preSum":5},{"ndv":1,"upper":1337189,"lower":1337189,"count":1,"preSum":6},{"ndv":1,"upper":1346415,"lower":1346415,"count":1,"preSum":7},{"ndv":1,"upper":1347128,"lower":1347128,"count":1,"preSum":8},{"ndv":1,"upper":1347131,"lower":1347131,"count":1,"preSum":9},{"ndv":1,"upper":1398851,"lower":1398851,"count":1,"preSum":10},{"ndv":1,"upper":1492889,"lower":1492889,"count":1,"preSum":11},{"ndv":1,"upper":2604100,"lower":2604100,"count":1,"preSum":12},{"ndv":1,"upper":2646282,"lower":2646282,"count":1,"preSum":13},{"ndv":1,"upper":2700631,"lower":2700631,"count":1,"preSum":14},{"ndv":1,"upper":2722610,"lower":2722610,"count":1,"preSum":15},{"ndv":1,"upper":3121239,"lower":3121239,"count":1,"preSum":16},{"ndv":1,"upper":3302048,"lower":3302048,"count":1,"preSum":17},{"ndv":1,"upper":4152939,"lower":4152939,"count":1,"preSum":18},{"ndv":1,"upper":4176632,"lower":4176632,"count":1,"preSum":19},{"ndv":1,"upper":4229092,"lower":4229092,"count":1,"preSum":20},{"ndv":1,"upper":4229420,"lower":4229420,"count":1,"preSum":21},{"ndv":1,"upper":4960907,"lower":4960907,"count":2,"preSum":22},{"ndv":1,"upper":4971652,"lower":4971652,"count":1,"preSum":24},{"ndv":1,"upper":5175078,"lower":5175078,"count":2,"preSum":25},{"ndv":1,"upper":5488127,"lower":5488127,"count":1,"preSum":27},{"ndv":1,"upper":5737664,"lower":5737664,"count":1,"preSum":28},{"ndv":1,"upper":5798389,"lower":5798389,"count":1,"preSum":29}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[99971],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','packagecentercode',1624,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":5,"upper":"三水","lower":"三亚","count":6,"preSum":0},{"ndv":4,"upper":"中山转","lower":"上饶转","count":6,"preSum":6},{"ndv":3,"upper":"义乌转","lower":"中山转台山","count":6,"preSum":12},{"ndv":5,"upper":"侯马转新绛","lower":"乌市转奎屯","count":6,"preSum":18},{"ndv":5,"upper":"兰州","lower":"信阳转固始","count":8,"preSum":24},{"ndv":2,"upper":"北京","lower":"兰州转","count":7,"preSum":32},{"ndv":4,"upper":"南京雨花区","lower":"北京郊","count":6,"preSum":39},{"ndv":3,"upper":"南充转邻水","lower":"南充转","count":7,"preSum":45},{"ndv":4,"upper":"南昌转南城","lower":"南宁转","count":6,"preSum":52},{"ndv":4,"upper":"南通","lower":"南昌转南昌县","count":6,"preSum":58},{"ndv":5,"upper":"合肥","lower":"南通转海安","count":10,"preSum":64},{"ndv":6,"upper":"吉安转崇义","lower":"合肥转含山","count":6,"preSum":74},{"ndv":4,"upper":"唐山转","lower":"呼市","count":6,"preSum":80},{"ndv":3,"upper":"大同转","lower":"嘉兴转","count":6,"preSum":86},{"ndv":5,"upper":"太原转五台","lower":"大庆","count":6,"preSum":92},{"ndv":4,"upper":"宁波","lower":"太原转交城","count":6,"preSum":98},{"ndv":3,"upper":"安阳","lower":"宁波转","count":6,"preSum":104},{"ndv":4,"upper":"巴南转","lower":"宝鸡","count":8,"preSum":110},{"ndv":5,"upper":"平凉","lower":"常州转","count":6,"preSum":118},{"ndv":5,"upper":"徐州","lower":"广州转四会","count":6,"preSum":124},{"ndv":4,"upper":"惠州转","lower":"徐州转丰县","count":8,"preSum":130},{"ndv":4,"upper":"成都转","lower":"惠州转惠东","count":6,"preSum":138},{"ndv":6,"upper":"新乡转","lower":"成都转大邑","count":8,"preSum":144},{"ndv":6,"upper":"昆常","lower":"新乡转台前","count":8,"preSum":152},{"ndv":4,"upper":"昆明转广南","lower":"昆常转","count":6,"preSum":160},{"ndv":4,"upper":"晋城转","lower":"昆明转梁河","count":6,"preSum":166},{"ndv":3,"upper":"株洲","lower":"杭州","count":6,"preSum":172},{"ndv":3,"upper":"武汉","lower":"桂林","count":6,"preSum":178},{"ndv":2,"upper":"武汉转仙桃","lower":"武汉转","count":6,"preSum":184},{"ndv":4,"upper":"江宁","lower":"武汉转天门","count":6,"preSum":190},{"ndv":3,"upper":"沪东","lower":"沈阳转","count":6,"preSum":196},{"ndv":5,"upper":"洛阳转","lower":"泉州石狮","count":7,"preSum":202},{"ndv":5,"upper":"济宁转鱼台","lower":"济南转","count":6,"preSum":209},{"ndv":5,"upper":"淮安转","lower":"浦东孙桥","count":6,"preSum":215},{"ndv":4,"upper":"深圳转","lower":"淮安转灌南","count":7,"preSum":221},{"ndv":5,"upper":"滕州","lower":"温州转","count":6,"preSum":228},{"ndv":6,"upper":"漯河转项城","lower":"漯河","count":6,"preSum":234},{"ndv":3,"upper":"潮汕转","lower":"潍坊转","count":7,"preSum":240},{"ndv":3,"upper":"益阳","lower":"潮汕转五华","count":6,"preSum":247},{"ndv":4,"upper":"石市","lower":"盐城","count":6,"preSum":253},{"ndv":4,"upper":"福州","lower":"石市新河","count":6,"preSum":259},{"ndv":3,"upper":"自贡转","lower":"福州转霞浦","count":7,"preSum":265},{"ndv":4,"upper":"芜湖转","lower":"自贡转屏山","count":6,"preSum":272},{"ndv":6,"upper":"萧山转","lower":"苍南","count":6,"preSum":278},{"ndv":6,"upper":"衡阳转","lower":"萧山转临安","count":8,"preSum":284},{"ndv":5,"upper":"西宁转","lower":"衡阳转临武","count":6,"preSum":292},{"ndv":2,"upper":"西安蓝田","lower":"西安","count":6,"preSum":298},{"ndv":2,"upper":"西安转合阳","lower":"西安转","count":6,"preSum":304},{"ndv":5,"upper":"贵阳转","lower":"西安转大荔","count":6,"preSum":310},{"ndv":3,"upper":"贵阳转龙里","lower":"贵阳转凯里","count":6,"preSum":316},{"ndv":4,"upper":"邢邯转","lower":"赤峰巴林右旗","count":7,"preSum":322},{"ndv":6,"upper":"郴州","lower":"邢邯转涉县","count":6,"preSum":329},{"ndv":3,"upper":"重庆垫江","lower":"鄂州转阳新","count":6,"preSum":335},{"ndv":3,"upper":"银川转","lower":"重庆大坪","count":7,"preSum":341},{"ndv":4,"upper":"长沙转","lower":"银川转鄂托克旗","count":10,"preSum":348},{"ndv":3,"upper":"长沙郊浏阳","lower":"长沙转长沙","count":6,"preSum":358},{"ndv":3,"upper":"驻马店","lower":"青岛转","count":7,"preSum":364}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[27,10,159,10,7,7,9,7,7,16,7,10,7001],"valueArr":["","东莞","义乌","京南","佛山","包头转","天津转","广州转","沈阳","沪西","郑州转","鄂州转","顺丰速运"],"type":"String","sampleRate":0.9618625319816094}',92353,0.02436278),('jala_wms_prod','shipment_header','packagecentername',4751,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":22,"upper":"三明转明溪","lower":"","count":62,"preSum":0},{"ndv":17,"upper":"临沂转","lower":"三明转永安","count":65,"preSum":62},{"ndv":18,"upper":"乌市转","lower":"临沂转临沭","count":63,"preSum":127},{"ndv":30,"upper":"乐清","lower":"乌市转乌苏","count":65,"preSum":190},{"ndv":23,"upper":"京南转高碑店","lower":"九江","count":64,"preSum":255},{"ndv":27,"upper":"信阳转固始","lower":"京南郊","count":63,"preSum":319},{"ndv":11,"upper":"兰州永登","lower":"信阳转息县","count":63,"preSum":382},{"ndv":10,"upper":"北京","lower":"兰州转","count":77,"preSum":445},{"ndv":10,"upper":"南京转天长","lower":"北京小红门","count":63,"preSum":522},{"ndv":20,"upper":"南宁转","lower":"南京转溪县","count":87,"preSum":585},{"ndv":31,"upper":"南昌转高安","lower":"南宁转上林","count":62,"preSum":672},{"ndv":17,"upper":"厦门转","lower":"南昌进贤县","count":73,"preSum":734},{"ndv":14,"upper":"合肥转庐江","lower":"厦门转上杭","count":62,"preSum":807},{"ndv":24,"upper":"吉林","lower":"合肥转肥东","count":62,"preSum":869},{"ndv":16,"upper":"哈市","lower":"吉林永吉","count":75,"preSum":931},{"ndv":22,"upper":"唐山转青龙","lower":"哈市转","count":63,"preSum":1006},{"ndv":12,"upper":"大连开发区","lower":"商丘","count":67,"preSum":1069},{"ndv":21,"upper":"太原","lower":"大连瓦房店","count":63,"preSum":1136},{"ndv":16,"upper":"宁波转余姚","lower":"太原转","count":64,"preSum":1199},{"ndv":15,"upper":"岑溪转博白","lower":"宁波转象山","count":65,"preSum":1263},{"ndv":10,"upper":"常州转","lower":"岑溪转容县","count":71,"preSum":1328},{"ndv":30,"upper":"广州转郁南","lower":"常州转扬中","count":62,"preSum":1399},{"ndv":14,"upper":"德阳","lower":"广州转阳山","count":62,"preSum":1461},{"ndv":10,"upper":"成都华阳","lower":"怀化","count":69,"preSum":1523},{"ndv":24,"upper":"抚顺","lower":"成都大丰","count":65,"preSum":1592},{"ndv":24,"upper":"无锡","lower":"拉萨转","count":90,"preSum":1657},{"ndv":6,"upper":"昆常转","lower":"无锡转","count":73,"preSum":1747},{"ndv":22,"upper":"昆明转砚山","lower":"昆明转","count":62,"preSum":1820},{"ndv":23,"upper":"柳州转","lower":"昆明转罗平","count":65,"preSum":1882},{"ndv":18,"upper":"武汉","lower":"柳州转三江","count":66,"preSum":1947},{"ndv":14,"upper":"沈阳","lower":"武汉转","count":93,"preSum":2013},{"ndv":20,"upper":"沧衡转河间","lower":"沈阳转","count":63,"preSum":2106},{"ndv":11,"upper":"泉州石狮","lower":"沧衡转泊头","count":63,"preSum":2169},{"ndv":14,"upper":"洛阳转","lower":"泉州转","count":74,"preSum":2232},{"ndv":12,"upper":"济南转肥城","lower":"济南转","count":64,"preSum":2306},{"ndv":24,"upper":"海口","lower":"济南转茌平","count":67,"preSum":2370},{"ndv":14,"upper":"淮安转","lower":"海口乐东县","count":66,"preSum":2437},{"ndv":24,"upper":"温江","lower":"淮安转宝应","count":64,"preSum":2503},{"ndv":30,"upper":"漯河转永城","lower":"湖州","count":62,"preSum":2567},{"ndv":19,"upper":"潍坊转莱州","lower":"漯河转汝南","count":66,"preSum":2629},{"ndv":12,"upper":"珠海转","lower":"潍坊转青州","count":76,"preSum":2695},{"ndv":16,"upper":"石市","lower":"益阳","count":82,"preSum":2771},{"ndv":26,"upper":"聊城","lower":"石市井陉","count":63,"preSum":2853},{"ndv":16,"upper":"芜湖转南陵","lower":"自贡转","count":63,"preSum":2916},{"ndv":25,"upper":"莱阳转","lower":"芜湖转宁国","count":62,"preSum":2979},{"ndv":17,"upper":"蚌埠转寿县","lower":"莱阳转招远","count":62,"preSum":3041},{"ndv":29,"upper":"衡阳转溆浦","lower":"蚌埠转怀远","count":62,"preSum":3103},{"ndv":21,"upper":"西宁转","lower":"衡阳转炎陵","count":62,"preSum":3165},{"ndv":10,"upper":"西安三森","lower":"西宁转同仁","count":62,"preSum":3227},{"ndv":22,"upper":"西安转富平","lower":"西安兴平","count":62,"preSum":3289},{"ndv":28,"upper":"贵阳转修文","lower":"西安转山阳","count":62,"preSum":3351},{"ndv":35,"upper":"遵义","lower":"贵阳转兴仁","count":66,"preSum":3413},{"ndv":15,"upper":"郑州港区转","lower":"邢邯转","count":67,"preSum":3479},{"ndv":11,"upper":"郑州转","lower":"郑州港卢氏","count":79,"preSum":3546},{"ndv":15,"upper":"重庆","lower":"郫县","count":71,"preSum":3625},{"ndv":17,"upper":"长春","lower":"重庆云阳","count":84,"preSum":3696},{"ndv":19,"upper":"长沙郊","lower":"长春转","count":78,"preSum":3780},{"ndv":11,"upper":"齐齐哈尔","lower":"长沙郊平江","count":52,"preSum":3858}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[161,79,173,79,77,58,106,59,88,500,114,75,146,6855],"valueArr":["东莞","中山转","义乌","京南","佛山","天津转","广州转","成都","沪西","浦东分拨中心","深圳转","鄂州转","(V)、△△","(V)、△△、∫"],"type":"String","sampleRate":0.9618625319816094}',87521,0.02436278),('jala_wms_prod','shipment_header','payno',2300274,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1484,"upper":"1832796696057094168","lower":"100441022058559!FP099111129996578","count":1488,"preSum":0},{"ndv":1488,"upper":"1870914072078718963","lower":"1832801844266336280","count":1488,"preSum":1488},{"ndv":1487,"upper":"1878563534491514493","lower":"1870915838900151970","count":1488,"preSum":2976},{"ndv":1488,"upper":"1880530357673255970","lower":"1878565514951295680","count":1488,"preSum":4464},{"ndv":1487,"upper":"1886573463828438884","lower":"1880537955827870398","count":1488,"preSum":5952},{"ndv":1487,"upper":"1891617386250503291","lower":"1886573642968694487","count":1488,"preSum":7440},{"ndv":1487,"upper":"1896297672938324060","lower":"1891617421264297999","count":1488,"preSum":8928},{"ndv":1487,"upper":"1896932895443324474","lower":"1896297744703205393","count":1488,"preSum":10416},{"ndv":1485,"upper":"1897159911391977078","lower":"1896933075205745186","count":1488,"preSum":11904},{"ndv":1486,"upper":"1899880248729178380","lower":"1897159911558262388","count":1488,"preSum":13392},{"ndv":1487,"upper":"1903179900573515760","lower":"1899881113496508775","count":1488,"preSum":14880},{"ndv":1488,"upper":"1906452120502540768","lower":"1903182026331931066","count":1488,"preSum":16368},{"ndv":1487,"upper":"1911852949699587799","lower":"1906452228701774495","count":1488,"preSum":17856},{"ndv":1487,"upper":"1915038300444831789","lower":"1911858169226630586","count":1488,"preSum":19344},{"ndv":1488,"upper":"1917194269746866291","lower":"1915040388757471789","count":1488,"preSum":20832},{"ndv":1488,"upper":"1920912277996478287","lower":"1917195636641733393","count":1488,"preSum":22320},{"ndv":1487,"upper":"23042577504774","lower":"1920915192436995579","count":1488,"preSum":23808},{"ndv":1488,"upper":"23050999937184","lower":"23042578879844","count":1488,"preSum":25296},{"ndv":1488,"upper":"23052207024716","lower":"230510-020599315363899","count":1488,"preSum":26784},{"ndv":1488,"upper":"23060345827289","lower":"23052214902216","count":1488,"preSum":28272},{"ndv":1488,"upper":"23061661983868","lower":"23060345941735","count":1488,"preSum":29760},{"ndv":1488,"upper":"2311400211532013","lower":"23061662381768","count":1488,"preSum":31248},{"ndv":1487,"upper":"265109333115","lower":"2311400220662942","count":1488,"preSum":32736},{"ndv":1488,"upper":"271354654999","lower":"265121474335","count":1488,"preSum":34224},{"ndv":1487,"upper":"273652656707","lower":"271357049749","count":1488,"preSum":35712},{"ndv":1487,"upper":"275952971620","lower":"273652670410","count":1488,"preSum":37200},{"ndv":1488,"upper":"3216250756380122640","lower":"275954711457","count":1488,"preSum":38688},{"ndv":1488,"upper":"3253389915328772966","lower":"3216280708884438531","count":1488,"preSum":40176},{"ndv":1488,"upper":"3303233535067337330","lower":"3253394379555697754","count":1488,"preSum":41664},{"ndv":1486,"upper":"3316790414389889312","lower":"3303234219367598236","count":1488,"preSum":43152},{"ndv":1487,"upper":"3324843001075210158","lower":"3316791099092567425","count":1488,"preSum":44640},{"ndv":1485,"upper":"3329766468219849727","lower":"3324846206548751613","count":1488,"preSum":46128},{"ndv":1486,"upper":"3330725331991742448","lower":"3329766468232630755","count":1488,"preSum":47616},{"ndv":1487,"upper":"3335242791101210534","lower":"3330725617326611401","count":1488,"preSum":49104},{"ndv":1487,"upper":"3342451248808912215","lower":"3335244015638576434","count":1488,"preSum":50592},{"ndv":1488,"upper":"3348816265556925210","lower":"3342451287310895604","count":1488,"preSum":52080},{"ndv":1487,"upper":"3353116359969470244","lower":"3348822459373553628","count":1488,"preSum":53568},{"ndv":1487,"upper":"3360427886170082604","lower":"3353118591755637038","count":1488,"preSum":55056},{"ndv":1487,"upper":"3364122168698182337","lower":"3360431163950684002","count":1488,"preSum":56544},{"ndv":1484,"upper":"3364668794474229004","lower":"3364122169573681207","count":1488,"preSum":58032},{"ndv":1484,"upper":"3365067567026386163","lower":"3364668859558505045","count":1488,"preSum":59520},{"ndv":1486,"upper":"3367758457938200922","lower":"3365068215676692337","count":1488,"preSum":61008},{"ndv":1487,"upper":"3371323467724740322","lower":"3367766593621231455","count":1488,"preSum":62496},{"ndv":1486,"upper":"3374711209087921150","lower":"3371325159468704049","count":1488,"preSum":63984},{"ndv":1486,"upper":"3378245655807206345","lower":"3374713873685823049","count":1488,"preSum":65472},{"ndv":1487,"upper":"3382461252151375702","lower":"3378246517737930306","count":1488,"preSum":66960},{"ndv":1487,"upper":"3389513149652996348","lower":"3382465464002934131","count":1488,"preSum":68448},{"ndv":1488,"upper":"3395248130692842601","lower":"3389515921178741823","count":1488,"preSum":69936},{"ndv":1487,"upper":"3398021103902802007","lower":"3395251766420358615","count":1488,"preSum":71424},{"ndv":1487,"upper":"3400202739026952945","lower":"3398021388956795402","count":1488,"preSum":72912},{"ndv":1488,"upper":"3402294913041316618","lower":"3400203565788352452","count":1488,"preSum":74400},{"ndv":1487,"upper":"3408325382768461156","lower":"3402296282880252556","count":1488,"preSum":75888},{"ndv":1488,"upper":"6917841557550602009","lower":"3408327792453859017","count":1488,"preSum":77376},{"ndv":1485,"upper":"6918025457652995233","lower":"6917842073163536334","count":1488,"preSum":78864},{"ndv":1486,"upper":"6918177551963854376","lower":"6918025705434649833","count":1488,"preSum":80352},{"ndv":1488,"upper":"6918330850433766892","lower":"6918177745710224832","count":1488,"preSum":81840},{"ndv":1487,"upper":"6918511796987237907","lower":"6918331157666928560","count":1488,"preSum":83328},{"ndv":1484,"upper":"6918702940928153306","lower":"6918511842102482787","count":1488,"preSum":84816},{"ndv":1487,"upper":"6918920943156270532","lower":"6918702983504795070","count":1488,"preSum":86304},{"ndv":1488,"upper":"6919067064000452504","lower":"6918920968230868445","count":1488,"preSum":87792},{"ndv":1488,"upper":"6919248606522709645","lower":"6919067420611384915","count":1488,"preSum":89280},{"ndv":1488,"upper":"6919410566841701488","lower":"6919248639676912891","count":1488,"preSum":90768},{"ndv":1488,"upper":"6919562240896472971","lower":"6919410614726629151","count":1488,"preSum":92256},{"ndv":1450,"upper":"XXY2023052337","lower":"6919562578720004018","count":1451,"preSum":93744}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[3220],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',1586,0.02436278),('jala_wms_prod','shipment_header','paystatus',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[3086,9329],"valueArr":[0,1],"type":"Int","sampleRate":0.9618625319816094}',87586,0.02436278),('jala_wms_prod','shipment_header','paytime',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','paytype',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','poddatetime',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Timestamp","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','podstatus',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','portcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','postreceipton',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','primarywaybillcode',2777362,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1520,"upper":"75577115307801","lower":"031946331476","count":1520,"preSum":0},{"ndv":1520,"upper":"75609867528957","lower":"75577128587604","count":1520,"preSum":1520},{"ndv":1520,"upper":"75610298521318","lower":"75609867885291","count":1520,"preSum":3040},{"ndv":1520,"upper":"78342272388997","lower":"75610298740297","count":1520,"preSum":4560},{"ndv":1520,"upper":"78682559277507","lower":"78342290034657","count":1520,"preSum":6080},{"ndv":1520,"upper":"78686354848192","lower":"78682561735349","count":1520,"preSum":7600},{"ndv":1520,"upper":"78689757222243","lower":"78686368198035","count":1520,"preSum":9120},{"ndv":1520,"upper":"78692274987244","lower":"78689757690630","count":1520,"preSum":10640},{"ndv":1520,"upper":"78694703065521","lower":"78692278022140","count":1520,"preSum":12160},{"ndv":1520,"upper":"78697058275300","lower":"78694713435595","count":1520,"preSum":13680},{"ndv":1520,"upper":"78700375091497","lower":"78697058569015","count":1520,"preSum":15200},{"ndv":1520,"upper":"SF1375279537564","lower":"78700376961511","count":1520,"preSum":16720},{"ndv":1520,"upper":"SF1375574789248","lower":"SF1375279719587","count":1520,"preSum":18240},{"ndv":1520,"upper":"SF1375722856798","lower":"SF1375574934668","count":1520,"preSum":19760},{"ndv":1520,"upper":"SF1376010036345","lower":"SF1375722888112","count":1520,"preSum":21280},{"ndv":1520,"upper":"SF1381232462440","lower":"SF1376010036796","count":1520,"preSum":22800},{"ndv":1520,"upper":"SF1383847090763","lower":"SF1381236552944","count":1520,"preSum":24320},{"ndv":1520,"upper":"SF1385935434940","lower":"SF1383848339741","count":1520,"preSum":25840},{"ndv":1520,"upper":"SF1388130663542","lower":"SF1385935634146","count":1520,"preSum":27360},{"ndv":1520,"upper":"SF1602943676177","lower":"SF1388134725747","count":1520,"preSum":28880},{"ndv":1520,"upper":"SF1603441758884","lower":"SF1602947806833","count":1520,"preSum":30400},{"ndv":1520,"upper":"SF1603721006282","lower":"SF1603441761479","count":1520,"preSum":31920},{"ndv":1520,"upper":"SF1603999020069","lower":"SF1603721095400","count":1520,"preSum":33440},{"ndv":1520,"upper":"SF1610651652055","lower":"SF1603999220607","count":1520,"preSum":34960},{"ndv":1520,"upper":"SF1613243623132","lower":"SF1610652272128","count":1520,"preSum":36480},{"ndv":1520,"upper":"SF1615578649010","lower":"SF1613245929241","count":1520,"preSum":38000},{"ndv":1520,"upper":"SF1618058976036","lower":"SF1615579522109","count":1520,"preSum":39520},{"ndv":1520,"upper":"SF1621422488761","lower":"SF1618059374169","count":1520,"preSum":41040},{"ndv":1520,"upper":"SF1623419488676","lower":"SF1621422527612","count":1520,"preSum":42560},{"ndv":1520,"upper":"SF1625476887717","lower":"SF1623419738956","count":1520,"preSum":44080},{"ndv":1520,"upper":"SF1629405820781","lower":"SF1625476887814","count":1520,"preSum":45600},{"ndv":1520,"upper":"SF1630983404832","lower":"SF1629407388802","count":1520,"preSum":47120},{"ndv":1520,"upper":"SF1633186294127","lower":"SF1630983504850","count":1520,"preSum":48640},{"ndv":1520,"upper":"SF1635386324652","lower":"SF1633188154637","count":1520,"preSum":50160},{"ndv":1520,"upper":"SF1637584534694","lower":"SF1635387254657","count":1520,"preSum":51680},{"ndv":1520,"upper":"SF1639787754240","lower":"SF1637584944218","count":1520,"preSum":53200},{"ndv":1520,"upper":"SF1642291809190","lower":"SF1639788374816","count":1520,"preSum":54720},{"ndv":1520,"upper":"SF1644967529307","lower":"SF1642292486175","count":1520,"preSum":56240},{"ndv":1520,"upper":"SF1647473870006","lower":"SF1644969573122","count":1520,"preSum":57760},{"ndv":1520,"upper":"SF1650140306581","lower":"SF1647475912043","count":1520,"preSum":59280},{"ndv":1520,"upper":"SF1652741603244","lower":"SF1650140413697","count":1520,"preSum":60800},{"ndv":1520,"upper":"SF1655242137058","lower":"SF1652741767421","count":1520,"preSum":62320},{"ndv":1520,"upper":"SF1657841581447","lower":"SF1655242212476","count":1520,"preSum":63840},{"ndv":1520,"upper":"SF1660684244909","lower":"SF1657841955023","count":1520,"preSum":65360},{"ndv":1520,"upper":"SF1662040500892","lower":"SF1660684245128","count":1520,"preSum":66880},{"ndv":1520,"upper":"SF1664485487178","lower":"SF1662047106416","count":1520,"preSum":68400},{"ndv":1520,"upper":"SF1667613564314","lower":"SF1664485646244","count":1520,"preSum":69920},{"ndv":1520,"upper":"SF1669684640851","lower":"SF1667613892481","count":1520,"preSum":71440},{"ndv":1520,"upper":"SF1673902240446","lower":"SF1669684653071","count":1520,"preSum":72960},{"ndv":1520,"upper":"SF1675944144677","lower":"SF1673902270240","count":1520,"preSum":74480},{"ndv":1520,"upper":"SF1678927670867","lower":"SF1675944146075","count":1520,"preSum":76000},{"ndv":1520,"upper":"SF1681632385091","lower":"SF1678927827018","count":1520,"preSum":77520},{"ndv":1520,"upper":"SF1682896404956","lower":"SF1681641457424","count":1520,"preSum":79040},{"ndv":1520,"upper":"SF1685681797485","lower":"SF1682896431059","count":1520,"preSum":80560},{"ndv":1520,"upper":"SF1687670000648","lower":"SF1685682091625","count":1520,"preSum":82080},{"ndv":1520,"upper":"SF1690567618549","lower":"SF1687670010271","count":1520,"preSum":83600},{"ndv":1520,"upper":"SF1693434968742","lower":"SF1690568259047","count":1520,"preSum":85120},{"ndv":1520,"upper":"SF1696059591564","lower":"SF1693435079562","count":1520,"preSum":86640},{"ndv":1520,"upper":"SF1698988890960","lower":"SF1696061063549","count":1520,"preSum":88160},{"ndv":1520,"upper":"SF1831791157206","lower":"SF1698992911347","count":1520,"preSum":89680},{"ndv":1520,"upper":"SF1832262929954","lower":"SF1831791180140","count":1520,"preSum":91200},{"ndv":1520,"upper":"SF1832779013016","lower":"SF1832262944374","count":1520,"preSum":92720},{"ndv":1520,"upper":"SF1833283129071","lower":"SF1832779037521","count":1520,"preSum":94240},{"ndv":1503,"upper":"SF7607172447695","lower":"SF1833283593644","count":1503,"preSum":95760}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1107],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',1631,0.02436278),('jala_wms_prod','shipment_header','printdataid',1423470,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1340,"upper":"6402ca7e2b98cd70e0713719","lower":"639bb6322f046a24bf50dc52","count":1340,"preSum":0},{"ndv":1340,"upper":"640afd522173a9388e2bd79e","lower":"6402ca7e612c5a5b766252aa","count":1340,"preSum":1340},{"ndv":1340,"upper":"641ffcb8c98eb1686dd21879","lower":"640afd52e403523f28baa949","count":1340,"preSum":2680},{"ndv":1340,"upper":"643766de62d7b11237189fa0","lower":"641ffcbcc98eb1686dd2187d","count":1340,"preSum":4020},{"ndv":1340,"upper":"643f3619d5b7790c20587659","lower":"643766de62d7b11237189fa1","count":1340,"preSum":5360},{"ndv":1340,"upper":"64426107fb2a0e77594173d1","lower":"643f3619d5b7790c2058765a","count":1340,"preSum":6700},{"ndv":1340,"upper":"6445c7ba30728460dfb0ed28","lower":"64426107fb2a0e77594173d3","count":1340,"preSum":8040},{"ndv":1340,"upper":"6447cdaea042ae62dcc65d79","lower":"6445c7bfefdeec64826d7c89","count":1340,"preSum":9380},{"ndv":1340,"upper":"644b2a08b7356506a9801ece","lower":"6447cdb220399d364108d2e8","count":1340,"preSum":10720},{"ndv":1340,"upper":"644c98a5a3fda2138c01cc81","lower":"644b2a09b7356506a9801ed0","count":1340,"preSum":12060},{"ndv":1340,"upper":"644f3a8a3460f001876b50dd","lower":"644c98a5b7356506a989cfe4","count":1340,"preSum":13400},{"ndv":1340,"upper":"645113053460f00187745aaf","lower":"644f3a8ccb08c42cd06ebfe4","count":1340,"preSum":14740},{"ndv":1340,"upper":"6451c76c3460f0018778305b","lower":"645113063460f00187745ab2","count":1340,"preSum":16080},{"ndv":1340,"upper":"64520685cb08c42cd082896d","lower":"6451c76ccb08c42cd07d646a","count":1340,"preSum":17420},{"ndv":1340,"upper":"645348d13460f0018784cfcf","lower":"64520685cb08c42cd0828970","count":1340,"preSum":18760},{"ndv":1340,"upper":"6455b70573f6dd1883aed3c0","lower":"64534b26a34628313f100da0","count":1340,"preSum":20100},{"ndv":1340,"upper":"6457d47773f6dd1883b65030","lower":"6455b71532445e3aa1391b9e","count":1340,"preSum":21440},{"ndv":1340,"upper":"645a370c8338b44f591196be","lower":"6457d47773f6dd1883b65031","count":1340,"preSum":22780},{"ndv":1340,"upper":"645c4c3c0f60720169d3ba12","lower":"645a370cbb419d6e2361b34c","count":1340,"preSum":24120},{"ndv":1340,"upper":"645e2a514985200561dbe2f5","lower":"645c4c3c0f60720169d3ba15","count":1340,"preSum":25460},{"ndv":1340,"upper":"646071f5977ac2612ded8a9b","lower":"645e2a51a8e5fa4520e308bc","count":1340,"preSum":26800},{"ndv":1340,"upper":"6462a337977ac2612df8dc65","lower":"646071f661a80428444903e2","count":1340,"preSum":28140},{"ndv":1340,"upper":"6463bcc8977ac2612d00b1f6","lower":"6462d6f351c41f0befc5469a","count":1340,"preSum":29480},{"ndv":1340,"upper":"646586af51c41f0befd6f17f","lower":"6463bccc51c41f0befcb4f43","count":1340,"preSum":30820},{"ndv":1340,"upper":"6467c2922af2e71c128d396a","lower":"646586af51c41f0befd6f183","count":1340,"preSum":32160},{"ndv":1340,"upper":"6469c303cbe08c3cf12f288b","lower":"6467c292cbe08c3cf1238579","count":1340,"preSum":33500},{"ndv":1340,"upper":"646c51c0cbe08c3cf13ab7f9","lower":"6469c3042af2e71c129a6a45","count":1340,"preSum":34840},{"ndv":1340,"upper":"646edd4f7d6bcb3ea52f4ee3","lower":"646c51c12af2e71c12a588e3","count":1340,"preSum":36180},{"ndv":1340,"upper":"647173b486c6db1296cfa9ed","lower":"646edd4f7d6bcb3ea52f4ee4","count":1340,"preSum":37520},{"ndv":1340,"upper":"647188b386c6db1296d04fae","lower":"647173b533db057bab9d80cb","count":1340,"preSum":38860},{"ndv":1340,"upper":"6471971acf891a6b00d4a8b8","lower":"647188b3cf891a6b00d3bc50","count":1340,"preSum":40200},{"ndv":1340,"upper":"6471a759cf891a6b00d52b20","lower":"6471971acf891a6b00d4a8b9","count":1340,"preSum":41540},{"ndv":1340,"upper":"6471ca1bcf891a6b00d626ee","lower":"6471a759cf891a6b00d52b27","count":1340,"preSum":42880},{"ndv":1340,"upper":"6472a8f76efccc79a04e3779","lower":"6471ca1bcf891a6b00d626f2","count":1340,"preSum":44220},{"ndv":1340,"upper":"6473485d5de7ab60bd08f087","lower":"6472a8f86efccc79a04e377b","count":1340,"preSum":45560},{"ndv":1340,"upper":"64745b9ccf891a6b00dd6866","lower":"6473485d5de7ab60bd08f08b","count":1340,"preSum":46900},{"ndv":1340,"upper":"6475a029c18c6a210a6e5d7a","lower":"64745ba233db057baba791f1","count":1340,"preSum":48240},{"ndv":1340,"upper":"6476e1dfb7fd9828da95d71e","lower":"6475a02a6e1ab418fa0d08b0","count":1340,"preSum":49580},{"ndv":1340,"upper":"6477479ab7fd9828da97dbaa","lower":"6476e563336e123e3d8f7786","count":1340,"preSum":50920},{"ndv":1340,"upper":"64777e4994303d3cf5a870ae","lower":"6477479c1a16033c58f86bda","count":1340,"preSum":52260},{"ndv":1340,"upper":"647861b4b7fd9828daa7feb6","lower":"64777e4a319c102daf44167b","count":1340,"preSum":53600},{"ndv":1340,"upper":"64795ece336e123e3da7da0f","lower":"647861b4b7fd9828daa7feb7","count":1340,"preSum":54940},{"ndv":1340,"upper":"647a918989776c5eee537c5b","lower":"64795ece9c699e237b19a7b3","count":1340,"preSum":56280},{"ndv":1340,"upper":"647b6aaa8249d352cdbf98cd","lower":"647a9189e544c00c27ac4758","count":1340,"preSum":57620},{"ndv":1340,"upper":"647cbe56e544c00c27ae0811","lower":"647b6aaa8249d352cdbf98ce","count":1340,"preSum":58960},{"ndv":1340,"upper":"647e9585e544c00c27afdcfe","lower":"647cbf0a89776c5eee5564a9","count":1340,"preSum":60300},{"ndv":1340,"upper":"6480021289776c5eee587816","lower":"647e9586003af203fdb3c34f","count":1340,"preSum":61640},{"ndv":1340,"upper":"648295433564ac52a4f8e186","lower":"6480021589776c5eee58781b","count":1340,"preSum":62980},{"ndv":1340,"upper":"6484761e78ec172fd604d108","lower":"648295433564ac52a4f8e187","count":1340,"preSum":64320},{"ndv":1340,"upper":"6486aef22d006360fe0735dd","lower":"648476322d006360fe056fff","count":1340,"preSum":65660},{"ndv":1340,"upper":"64887b23acc9a26ca987d341","lower":"6486aef26f06004a70c348a0","count":1340,"preSum":67000},{"ndv":1340,"upper":"648af19c1d13f33ef2649cb1","lower":"64887b23acc9a26ca987d342","count":1340,"preSum":68340},{"ndv":1340,"upper":"648b3eeb4e8d7266e6ee52e2","lower":"648af19c1d13f33ef2649cb3","count":1340,"preSum":69680},{"ndv":1340,"upper":"648c2ebc2625d24e22e5ea7c","lower":"648b3eee4e8d7266e6ee52e5","count":1340,"preSum":71020},{"ndv":1340,"upper":"648d09fddbb472367eb71b54","lower":"648c2ebc2625d24e22e5ea7f","count":1340,"preSum":72360},{"ndv":1340,"upper":"648db69cacc9a26ca98d69f0","lower":"648d09fddbb472367eb71b5a","count":1340,"preSum":73700},{"ndv":1340,"upper":"648e85aadbb472367eb80b42","lower":"648db69d2625d24e22e7a0c3","count":1340,"preSum":75040},{"ndv":1340,"upper":"648efa662625d24e22e91179","lower":"648e85ab1d13f33ef268a039","count":1340,"preSum":76380},{"ndv":1340,"upper":"648f340bdbb472367eb8e0e7","lower":"648efa66acc9a26ca98ed374","count":1340,"preSum":77720},{"ndv":1340,"upper":"64904a7c1d13f33ef26bc578","lower":"648f34a91d13f33ef269ac6e","count":1340,"preSum":79060},{"ndv":1340,"upper":"6491bb9f2625d24e22ed403f","lower":"64904a7cacc9a26ca9911671","count":1340,"preSum":80400},{"ndv":1340,"upper":"64953acaacc9a26ca996be2b","lower":"6491bb9f2625d24e22ed4040","count":1340,"preSum":81740},{"ndv":1340,"upper":"6498f63edbb472367ebbca81","lower":"64953ad12625d24e22f12d97","count":1340,"preSum":83080},{"ndv":1293,"upper":"649cc6111d13f33ef279061d","lower":"6498f708dbb472367ebbcabb","count":1293,"preSum":84420}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,14288,0.02436278),('jala_wms_prod','shipment_header','priority',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','processstamp',224832,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1204,"upper":"2023-02-26 10:56:00","lower":"2022-09-05 11:36:00","count":1458,"preSum":0},{"ndv":856,"upper":"2023-03-07 10:41:01","lower":"2023-02-26 10:57:00","count":1458,"preSum":1458},{"ndv":1038,"upper":"2023-03-20 10:07:01","lower":"2023-03-07 10:46:01","count":1458,"preSum":2916},{"ndv":1083,"upper":"2023-04-09 11:04:00","lower":"2023-03-20 10:08:00","count":1458,"preSum":4374},{"ndv":1014,"upper":"2023-04-17 10:26:00","lower":"2023-04-09 11:05:00","count":1458,"preSum":5832},{"ndv":1068,"upper":"2023-04-21 09:58:00","lower":"2023-04-17 10:32:00","count":1458,"preSum":7290},{"ndv":828,"upper":"2023-04-23 09:21:00","lower":"2023-04-21 10:00:00","count":1460,"preSum":8748},{"ndv":857,"upper":"2023-04-25 10:37:00","lower":"2023-04-23 09:23:00","count":1458,"preSum":10208},{"ndv":776,"upper":"2023-04-26 17:05:00","lower":"2023-04-25 10:39:03","count":1458,"preSum":11666},{"ndv":758,"upper":"2023-04-28 15:20:05","lower":"2023-04-26 17:05:03","count":1459,"preSum":13124},{"ndv":855,"upper":"2023-04-29 21:22:00","lower":"2023-04-28 15:20:11","count":1458,"preSum":14583},{"ndv":702,"upper":"2023-05-01 15:52:09","lower":"2023-04-29 21:28:36","count":1458,"preSum":16041},{"ndv":687,"upper":"2023-05-03 10:03:01","lower":"2023-05-01 15:53:03","count":1460,"preSum":17499},{"ndv":432,"upper":"2023-05-03 15:57:00","lower":"2023-05-03 10:04:02","count":1461,"preSum":18959},{"ndv":539,"upper":"2023-05-04 11:20:02","lower":"2023-05-03 15:57:01","count":1458,"preSum":20420},{"ndv":624,"upper":"2023-05-05 10:15:05","lower":"2023-05-04 11:20:03","count":1459,"preSum":21878},{"ndv":751,"upper":"2023-05-06 18:19:00","lower":"2023-05-05 10:16:06","count":1458,"preSum":23337},{"ndv":667,"upper":"2023-05-08 15:32:00","lower":"2023-05-06 18:20:00","count":1458,"preSum":24795},{"ndv":734,"upper":"2023-05-10 11:27:11","lower":"2023-05-08 15:33:00","count":1461,"preSum":26253},{"ndv":730,"upper":"2023-05-11 15:13:07","lower":"2023-05-10 11:27:24","count":1464,"preSum":27714},{"ndv":763,"upper":"2023-05-12 20:11:11","lower":"2023-05-11 15:14:04","count":1459,"preSum":29178},{"ndv":693,"upper":"2023-05-14 14:17:00","lower":"2023-05-12 20:13:05","count":1458,"preSum":30637},{"ndv":703,"upper":"2023-05-16 09:40:00","lower":"2023-05-14 14:18:00","count":1464,"preSum":32095},{"ndv":601,"upper":"2023-05-17 12:52:00","lower":"2023-05-16 09:41:00","count":1463,"preSum":33559},{"ndv":651,"upper":"2023-05-18 11:19:13","lower":"2023-05-17 12:53:00","count":1458,"preSum":35022},{"ndv":758,"upper":"2023-05-19 17:18:06","lower":"2023-05-18 11:20:06","count":1458,"preSum":36480},{"ndv":769,"upper":"2023-05-21 13:54:05","lower":"2023-05-19 17:23:11","count":1458,"preSum":37938},{"ndv":615,"upper":"2023-05-23 10:12:09","lower":"2023-05-21 13:55:00","count":1462,"preSum":39396},{"ndv":673,"upper":"2023-05-24 18:07:00","lower":"2023-05-23 10:14:19","count":1458,"preSum":40858},{"ndv":584,"upper":"2023-05-26 14:49:07","lower":"2023-05-24 18:08:00","count":1458,"preSum":42316},{"ndv":725,"upper":"2023-05-28 14:13:00","lower":"2023-05-26 14:50:00","count":1459,"preSum":43774},{"ndv":656,"upper":"2023-05-30 16:19:01","lower":"2023-05-28 14:18:00","count":1461,"preSum":45233},{"ndv":677,"upper":"2023-05-31 23:01:00","lower":"2023-05-30 16:22:00","count":1458,"preSum":46694},{"ndv":344,"upper":"2023-06-01 04:25:00","lower":"2023-05-31 23:02:00","count":1458,"preSum":48152},{"ndv":418,"upper":"2023-06-01 10:29:00","lower":"2023-06-01 04:26:00","count":1464,"preSum":49610},{"ndv":422,"upper":"2023-06-01 13:25:01","lower":"2023-06-01 10:30:01","count":1461,"preSum":51074},{"ndv":344,"upper":"2023-06-01 15:28:01","lower":"2023-06-01 13:25:30","count":1459,"preSum":52535},{"ndv":352,"upper":"2023-06-01 17:39:30","lower":"2023-06-01 15:28:31","count":1459,"preSum":53994},{"ndv":451,"upper":"2023-06-01 21:19:00","lower":"2023-06-01 17:40:00","count":1460,"preSum":55453},{"ndv":624,"upper":"2023-06-02 09:20:07","lower":"2023-06-01 21:20:00","count":1458,"preSum":56913},{"ndv":624,"upper":"2023-06-02 15:47:01","lower":"2023-06-02 09:20:13","count":1459,"preSum":58371},{"ndv":740,"upper":"2023-06-03 09:38:01","lower":"2023-06-02 15:47:02","count":1458,"preSum":59830},{"ndv":633,"upper":"2023-06-03 17:16:01","lower":"2023-06-03 09:38:02","count":1458,"preSum":61288},{"ndv":712,"upper":"2023-06-04 15:40:01","lower":"2023-06-03 17:17:01","count":1458,"preSum":62746},{"ndv":778,"upper":"2023-06-05 16:36:01","lower":"2023-06-04 15:41:00","count":1459,"preSum":64204},{"ndv":679,"upper":"2023-06-06 16:42:01","lower":"2023-06-05 16:36:02","count":1459,"preSum":65663},{"ndv":824,"upper":"2023-06-08 09:22:03","lower":"2023-06-06 16:43:00","count":1458,"preSum":67122},{"ndv":775,"upper":"2023-06-09 16:17:00","lower":"2023-06-08 09:23:00","count":1458,"preSum":68580},{"ndv":797,"upper":"2023-06-11 13:04:01","lower":"2023-06-09 16:18:01","count":1458,"preSum":70038},{"ndv":864,"upper":"2023-06-12 20:54:00","lower":"2023-06-11 13:07:00","count":1458,"preSum":71496},{"ndv":709,"upper":"2023-06-14 10:44:01","lower":"2023-06-12 21:01:17","count":1458,"preSum":72954},{"ndv":820,"upper":"2023-06-15 18:27:01","lower":"2023-06-14 10:47:00","count":1458,"preSum":74412},{"ndv":634,"upper":"2023-06-16 14:23:07","lower":"2023-06-15 18:28:01","count":1464,"preSum":75870},{"ndv":536,"upper":"2023-06-16 21:32:01","lower":"2023-06-16 14:23:08","count":1458,"preSum":77334},{"ndv":499,"upper":"2023-06-17 13:43:01","lower":"2023-06-16 21:33:01","count":1462,"preSum":78792},{"ndv":560,"upper":"2023-06-18 09:46:03","lower":"2023-06-17 13:44:01","count":1458,"preSum":80254},{"ndv":508,"upper":"2023-06-18 16:40:01","lower":"2023-06-18 09:47:01","count":1461,"preSum":81712},{"ndv":499,"upper":"2023-06-19 09:42:02","lower":"2023-06-18 16:41:01","count":1459,"preSum":83173},{"ndv":447,"upper":"2023-06-19 14:45:07","lower":"2023-06-19 09:43:01","count":1459,"preSum":84632},{"ndv":561,"upper":"2023-06-20 10:06:01","lower":"2023-06-19 14:45:08","count":1458,"preSum":86091},{"ndv":584,"upper":"2023-06-21 10:19:01","lower":"2023-06-20 10:07:01","count":1458,"preSum":87549},{"ndv":808,"upper":"2023-06-23 16:25:01","lower":"2023-06-21 10:19:02","count":1458,"preSum":89007},{"ndv":828,"upper":"2023-06-26 13:34:01","lower":"2023-06-23 16:26:01","count":1458,"preSum":90465},{"ndv":828,"upper":"2023-06-28 23:32:22","lower":"2023-06-26 13:35:01","count":1360,"preSum":91923}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[20,28,20,19,21,19,21,26,19,24,29,22,25],"valueArr":["2022-11-22 14:07:01","2023-04-14 09:34:00","2023-04-22 10:17:00","2023-05-11 16:35:04","2023-05-30 14:03:00","2023-05-31 04:25:00","2023-06-01 00:57:00","2023-06-01 14:25:01","2023-06-01 16:33:00","2023-06-01 18:12:01","2023-06-01 18:43:45","2023-06-01 18:52:16","2023-06-01 18:55:01"],"type":"String","sampleRate":0.9618625319816094}',6425,0.02436278),('jala_wms_prod','shipment_header','processtype',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[32,4872,95081,16],"valueArr":["ABNORMAL","CANCEL","NORMAL","PENDING"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','purchaseordercode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[5],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99996,0.02436278),('jala_wms_prod','shipment_header','qtyratio',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','realuserid',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','receipcompany',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','rejectionnote',969,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":"1:您好!受防疫措施变化影响,该目的地暂时无法提供此产品寄递服务,带来不便请您理解。(BPS5481) 50001 业务服务错误,SubCode:2136","lower":"14023 商家未开通电子面单服务;log_id: 2023022314302067B840CB4BE8FE02325A","count":3,"preSum":0},{"ndv":2,"upper":"1:您好!该目的地暂不提供寄递服务,您可更换地址重新下单,带来不便请您理解。(BPS8565) 15 Remote service error,SubCode:sf_response_fail-8177","lower":"1:您好!受防疫措施变化影响,该目的地暂时无法提供此产品寄递服务,带来不便请您理解。(BPS5552) 50001 业务服务错误,SubCode:2136","count":3,"preSum":3},{"ndv":3,"upper":"20063 收方地址不详细,请填写更为详细的地址后重新下单。;log_id: 20230524094244AB2E5504D6EC814D6046","lower":"20063 收方地址不详细,请填写更为详细的地址后重新下单。;log_id: 2023051110341689D709C8F6AF868E836F","count":3,"preSum":6},{"ndv":3,"upper":"20063 收方地址不详细,请填写更为详细的地址后重新下单。;log_id: 20230620142025A7D4522922B2681BB763","lower":"20063 收方地址不详细,请填写更为详细的地址后重新下单。;log_id: 202306100922047D73A4FB5C72F876E288","count":3,"preSum":9},{"ndv":3,"upper":"70006 收方地址不详细,请填写更为详细的地址后重新下单。","lower":"20064 收方地址存在双重目的地,请核实后重新填写地址下单。;log_id: 20230502095559D5D1AF1BF12920093D8D","count":3,"preSum":12},{"ndv":3,"upper":"[isv.oaid-invalid]:参数oaid无效,tid:3263044644040400448 15 Remote service error,SubCode:isv.oaid-invalid","lower":"70006 收方地址存在双重目的地,请核实后重新填写地址下单。","count":3,"preSum":15},{"ndv":3,"upper":"[订单23042554318434已被取消,不能查询/打印面单]","lower":"[isv.oaid-invalid]:参数oaid无效,tid:3305371431843590122 15 Remote service error,SubCode:isv.oaid-invalid","count":3,"preSum":18},{"ndv":3,"upper":"[订单23051588573938已被取消,不能查询/打印面单]","lower":"[订单23050425739823已被取消,不能查询/打印面单]","count":3,"preSum":21},{"ndv":3,"upper":"[订单23052481484666已被取消,不能查询/打印面单]","lower":"[订单23052369563209已被取消,不能查询/打印面单]","count":3,"preSum":24},{"ndv":3,"upper":"到方电话或手机不合法","lower":"[订单23060252090657已被取消,不能查询/打印面单]","count":4,"preSum":27},{"ndv":3,"upper":"当前所选地址超出服务范围,请检查地址或联系您的服务网点 15 Remote service error,SubCode:ADDRESS_NOT_REACHABLE","lower":"商家请求参数错误,固话和手机只能包含+、-、空格、单引号、数字、英文逗号、中文逗号 15 Remote service error,SubCode:phone or mobile illegal","count":5,"preSum":31},{"ndv":2,"upper":"整单短拣","lower":"必填参数tel为空","count":5,"preSum":36},{"ndv":2,"upper":"订单明细[502547800]未指定分配规则,并且货品没有默认规则","lower":"联系人手机为空;","count":3,"preSum":41},{"ndv":2,"upper":"货品[502191390] [自然堂雪润皙白晶澈淡斑精华液40mL]缺货[1]","lower":"货品[28685] [28685]缺货[2]","count":3,"preSum":44},{"ndv":3,"upper":"货品[502200305] [自然堂凝时鲜颜肌活乳液(2022升级)120mL]缺货[3]","lower":"货品[502191612] [自然堂雪润皙白多重防晒隔离霜(淡绿色)SPF35PA+++(新版)30mL]缺货[1]","count":3,"preSum":47},{"ndv":2,"upper":"货品[502200404] [自然堂凝时鲜颜小紫瓶肌活霜50g]缺货[28]","lower":"货品[502200404] [自然堂凝时鲜颜小紫瓶肌活霜50g]缺货[1]","count":3,"preSum":50},{"ndv":3,"upper":"货品[502203504] [自然堂凝时鲜颜肌活冰肌水(滋润型)(2023升级)160mL]缺货[1]","lower":"货品[502201910] [自然堂凝时鲜颜肌活精华液(2023)40mL]缺货[1]","count":3,"preSum":53},{"ndv":3,"upper":"货品[502477902] [自然堂凝时鲜颜肌活氨基酸洁面霜(2023升级)60g中小样]缺货[2]","lower":"货品[502240703] [自然堂弹嫩紧致抗皱眼霜15g]缺货[1]","count":3,"preSum":56},{"ndv":3,"upper":"货品[502524002] [自然堂男士喜马拉雅龙血能量控油醒肤洁面乳(201806)50mL中小样]缺货[1]","lower":"货品[502502302] [自然堂惊鸿魅眼纤长睫毛膏8.5g]缺货[1]","count":3,"preSum":59},{"ndv":3,"upper":"货品[502568301] [自然堂炫彩盈润高显色唇膏#205树莓色3.2g]缺货[1]","lower":"货品[502534501] [自然堂雪松精油活颜御龄体验装四件套(霜版)中小样]缺货[1]","count":3,"preSum":62},{"ndv":2,"upper":"货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(02代) 安瓶1.5mL+面膜33mL×5片装]缺货[1]","lower":"货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(02代) 安瓶1.5mL+面膜33mL×5片装]缺货[10]","count":3,"preSum":65},{"ndv":2,"upper":"货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(02代) 安瓶1.5mL+面膜33mL×5片装]缺货[5]","lower":"货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(02代) 安瓶1.5mL+面膜33mL×5片装]缺货[3]","count":3,"preSum":68},{"ndv":3,"upper":"货品[502582805] [自然堂烟酰胺细致提亮安瓶面膜(无防腐) 安瓶1.5mL+面膜33mL 5片装]缺货[1]","lower":"货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(安瓶1.5mL+面膜33mL)*5PCS(02代)]缺货[1]","count":4,"preSum":71},{"ndv":3,"upper":"货品[502589301] [自然堂雪润冰肌水晶透焕亮面膜24mL*1PCS(2022版)中小样]缺货[1]","lower":"货品[502586901] [自然堂多肽抗皱美颈霜60g类产品]缺货[1]","count":3,"preSum":75},{"ndv":3,"upper":"货品[502622207] [自然堂凝时鲜颜肌活修护小紫瓶精华液50mL(第五代)]缺货[1]","lower":"货品[5025982001] [自然堂羽感致护防晒乳SPF50+PA+++50mL(2020版)优惠套装]缺货[1]","count":3,"preSum":78},{"ndv":3,"upper":"货品[502643500] [自然堂弹嫩紧致抗皱精华液7.5mL中小样]缺货[1]","lower":"货品[502623401] [自然堂男士喜马拉雅冰川保湿爽肤水120mL(2022版)]缺货[24]","count":3,"preSum":81},{"ndv":3,"upper":"货品[502668804] [自然堂雪域紫草细致毛孔面膜(2022二版)26mL×5片装]缺货[1]","lower":"货品[502643601] [自然堂雪松精油活颜御龄精华液7.5mL中小样(2022版)]缺货[1]","count":3,"preSum":84},{"ndv":3,"upper":"货品[502684505] [自然堂果酸细致焕肤面膜(绿色盖膜/纸卡版/升级版)6g 1颗装中小样]缺货[2]","lower":"货品[502668904] [自然堂雪茶平衡保湿面面膜26mL*5PCS(2022二版)]缺货[2]","count":4,"preSum":87},{"ndv":2,"upper":"货品[502692900] [自然堂娇颜亮润四件套(标签升级)中小样]缺货[1]","lower":"货品[502684505] [自然堂果酸细致焕肤面膜(绿色盖膜/纸卡版/升级版)6g 1颗装中小样]缺货[5]","count":4,"preSum":91},{"ndv":2,"upper":"货品[502700002] [自然堂植物补水面膜21片装(2022二版)]缺货[1]","lower":"货品[502699002] [自然堂雪域百合补水面膜(2022二版)26mL 1片装]缺货[1]","count":4,"preSum":95},{"ndv":3,"upper":"货品[502700101] [自然堂植物补水面膜套装40PCS(2022版)]缺货[1]","lower":"货品[502700002] [自然堂植物补水面膜21片装(2022二版)]缺货[2]","count":5,"preSum":99},{"ndv":3,"upper":"货品[502731300] [自然堂敏感头皮止痒洗发露+精华乳旅行装(40mL+40mL)两件套]缺货[1]","lower":"货品[502725500] [自然堂喜马拉雅茶泥净颜清洁面膜100g]缺货[2]","count":4,"preSum":104},{"ndv":2,"upper":"货品[502750100] [自然堂凝时鲜颜肌活修护小紫瓶精华液第五代7mL中小样]缺货[1]","lower":"货品[502732000] [自然堂舒缓润养卸妆膏100mL]缺货[3]","count":3,"preSum":108},{"ndv":3,"upper":"货品[502751500] [自然堂雪肌追光美白焕颜三件套]缺货[3]","lower":"货品[502750100] [自然堂凝时鲜颜肌活修护小紫瓶精华液第五代7mL中小样]缺货[3]","count":3,"preSum":111},{"ndv":3,"upper":"货品[502764100] [自然堂纯粹滋润冰肌水(2022升级版)60mL中小样]缺货[1]","lower":"货品[502755300] [自然堂嫩白保湿乳35mL中小样]缺货[1]","count":3,"preSum":114},{"ndv":3,"upper":"货品[502845500] [自然堂凝时鲜颜肌活修护体验装三件套(霜版)中小样]缺货[1]","lower":"货品[502764100] [自然堂纯粹滋润冰肌水(2022升级版)60mL中小样]缺货[2]","count":3,"preSum":117},{"ndv":3,"upper":"货品[502974012] [自然堂雪润皙白晶澈冰肌水(新规版)60mL]缺货[1]","lower":"货品[502903300] [自然堂小紫瓶告白礼盒(2023版)]缺货[1]","count":3,"preSum":120},{"ndv":3,"upper":"货品[502976673] [自然堂凝时鲜颜肌活冰肌水(清润型)(2023升级)60mL]缺货[1]","lower":"货品[502974752] [自然堂雪域精粹纯粹滋润精华液10mL(体验装)]缺货[2]","count":3,"preSum":123},{"ndv":3,"upper":"货品[512007100] [珀芙研集护保湿舒色面膜22mL*1PCS非卖商品]缺货[16]","lower":"货品[502978212] [自然堂雪域精粹纯粹滋润洗颜霜(配方技术升级)60g中小样]缺货[1]","count":3,"preSum":126},{"ndv":2,"upper":"货品[512007100] [珀芙研集护保湿舒色面膜22mL*1PCS非卖商品]缺货[3]","lower":"货品[512007100] [珀芙研集护保湿舒色面膜22mL*1PCS非卖商品]缺货[2]","count":4,"preSum":129},{"ndv":3,"upper":"货品[6165102] [自然堂王一博拍立得明信片C线上]缺货[1]","lower":"货品[512007100] [珀芙研集护保湿舒色面膜22mL*1PCS非卖商品]缺货[6]","count":3,"preSum":133},{"ndv":3,"upper":"顺丰接口返回:错误码:20063:错误信息:收方地址不详细,请填写更为详细的地址后重新下单。","lower":"货品[6165273] [自然堂2022版购物袋-中号]缺货[1]","count":5,"preSum":136}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[8,8,6,5,703,8,5,6,4,4,6,4,8,6],"valueArr":["","1:尊敬的客户,您好!受目的地疫情影响,暂时无法提供寄递服务,带来不便请您理解。(BPS4600)","1:您好!受防疫措施变化影响,该目的地暂时无法提供此产品寄递服务,带来不便请您理解。(BPS5485) 50001 业务服务错误,SubCode:2136","收方地址存在双重目的地,请核实后重新填写地址下单。 15 Remote service error,SubCode:sf_response_fail-20064","未匹配到快递","电子面单账户余额不足 15 Remote service error,SubCode:waybill account not enough","货品[28554] [28554]缺货[1]","货品[28554] [28554]缺货[2]","货品[28554] [28554]缺货[3]","货品[28685] [28685]缺货[1]","货品[28685] [28685]缺货[3]","货品[502476708] [自然堂冰川水水光面膜(新规版)28mL×5片装]缺货[2]","货品[502582804] [自然堂烟酰胺细致提亮安瓶面膜(02代) 安瓶1.5mL+面膜33mL×5片装]缺货[2]","货品[502789400] [自然堂凝时小紫瓶精华液礼盒(品牌礼盒)]缺货[1]"],"type":"String","sampleRate":0.9618625319816094}',99079,0.02436278),('jala_wms_prod','shipment_header','requesteddeliverydate',28,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"1850341730105163776","lower":"1850341730105163776","count":2,"preSum":0},{"ndv":1,"upper":"1850370317407485952","lower":"1850370317407485952","count":2,"preSum":2},{"ndv":1,"upper":"1850396705686552576","lower":"1850396705686552576","count":1,"preSum":4},{"ndv":1,"upper":"1850403302756319232","lower":"1850403302756319232","count":1,"preSum":5},{"ndv":1,"upper":"1850484666616774656","lower":"1850484666616774656","count":1,"preSum":6}],"maxBucketSize":64,"type":"Date","sampleRate":0.9618625}','{"countArr":[99994],"valueArr":[-1],"type":"Date","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','requesteddeliverytype',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":["0"],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','reserveno',547,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":7215671,"lower":7215671,"count":1,"preSum":0},{"ndv":1,"upper":7422404,"lower":7422404,"count":1,"preSum":1},{"ndv":1,"upper":7462720,"lower":7462720,"count":1,"preSum":2},{"ndv":1,"upper":7462882,"lower":7462882,"count":1,"preSum":3},{"ndv":1,"upper":7463303,"lower":7463303,"count":1,"preSum":4},{"ndv":1,"upper":7478217,"lower":7478217,"count":1,"preSum":5},{"ndv":1,"upper":7479200,"lower":7479200,"count":1,"preSum":6},{"ndv":1,"upper":7480942,"lower":7480942,"count":1,"preSum":7},{"ndv":1,"upper":7480943,"lower":7480943,"count":1,"preSum":8},{"ndv":1,"upper":7480944,"lower":7480944,"count":1,"preSum":9},{"ndv":1,"upper":7489524,"lower":7489524,"count":1,"preSum":10},{"ndv":1,"upper":7489531,"lower":7489531,"count":1,"preSum":11},{"ndv":1,"upper":7495129,"lower":7495129,"count":1,"preSum":12},{"ndv":1,"upper":7495131,"lower":7495131,"count":1,"preSum":13},{"ndv":1,"upper":7503197,"lower":7503197,"count":1,"preSum":14},{"ndv":1,"upper":7521807,"lower":7521807,"count":1,"preSum":15},{"ndv":1,"upper":7523093,"lower":7523093,"count":1,"preSum":16},{"ndv":1,"upper":7524334,"lower":7524334,"count":1,"preSum":17},{"ndv":1,"upper":7524338,"lower":7524338,"count":1,"preSum":18},{"ndv":1,"upper":7524366,"lower":7524366,"count":1,"preSum":19},{"ndv":1,"upper":7524367,"lower":7524367,"count":1,"preSum":20},{"ndv":1,"upper":7524370,"lower":7524370,"count":1,"preSum":21},{"ndv":1,"upper":7524382,"lower":7524382,"count":1,"preSum":22},{"ndv":1,"upper":7524387,"lower":7524387,"count":1,"preSum":23},{"ndv":1,"upper":7524946,"lower":7524946,"count":1,"preSum":24},{"ndv":1,"upper":7546682,"lower":7546682,"count":1,"preSum":25},{"ndv":1,"upper":7563935,"lower":7563935,"count":1,"preSum":26},{"ndv":1,"upper":7571640,"lower":7571640,"count":1,"preSum":27},{"ndv":1,"upper":7572239,"lower":7572239,"count":1,"preSum":28},{"ndv":1,"upper":7572248,"lower":7572248,"count":1,"preSum":29},{"ndv":1,"upper":7637286,"lower":7637286,"count":1,"preSum":30},{"ndv":1,"upper":7731423,"lower":7731423,"count":1,"preSum":31},{"ndv":1,"upper":7731429,"lower":7731429,"count":1,"preSum":32},{"ndv":1,"upper":7989650,"lower":7989650,"count":1,"preSum":33},{"ndv":1,"upper":8071202,"lower":8071202,"count":2,"preSum":34},{"ndv":1,"upper":8176545,"lower":8176545,"count":1,"preSum":36},{"ndv":1,"upper":8219003,"lower":8219003,"count":1,"preSum":37},{"ndv":1,"upper":8223789,"lower":8223789,"count":1,"preSum":38},{"ndv":1,"upper":8224561,"lower":8224561,"count":1,"preSum":39},{"ndv":1,"upper":8226906,"lower":8226906,"count":1,"preSum":40},{"ndv":1,"upper":8317169,"lower":8317169,"count":1,"preSum":41},{"ndv":1,"upper":8346611,"lower":8346611,"count":1,"preSum":42},{"ndv":1,"upper":8427343,"lower":8427343,"count":1,"preSum":43},{"ndv":1,"upper":8522276,"lower":8522276,"count":1,"preSum":44},{"ndv":1,"upper":8530228,"lower":8530228,"count":1,"preSum":45},{"ndv":1,"upper":8530229,"lower":8530229,"count":1,"preSum":46},{"ndv":1,"upper":8534590,"lower":8534590,"count":1,"preSum":47},{"ndv":1,"upper":8554342,"lower":8554342,"count":1,"preSum":48},{"ndv":1,"upper":8555618,"lower":8555618,"count":1,"preSum":49},{"ndv":1,"upper":8560929,"lower":8560929,"count":1,"preSum":50},{"ndv":1,"upper":8564714,"lower":8564714,"count":1,"preSum":51},{"ndv":1,"upper":8572382,"lower":8572382,"count":1,"preSum":52},{"ndv":1,"upper":8572384,"lower":8572384,"count":1,"preSum":53}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[3],"valueArr":[8208697],"type":"Int","sampleRate":0.9618625319816094}',99944,0.02436278),('jala_wms_prod','shipment_header','route',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','routecode',77146,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":121,"upper":"(W31)024BE-000","lower":"(02)591TD-010","count":121,"preSum":0},{"ndv":121,"upper":"010WB-HG-134同","lower":"(W4)558D-008同","count":121,"preSum":121},{"ndv":119,"upper":"020RD-GD-EKBL034同","lower":"010WB-HK-083","count":121,"preSum":242},{"ndv":118,"upper":"021WG1-K-308同","lower":"020RD-GF-102B","count":121,"preSum":363},{"ndv":119,"upper":"022FB-048同","lower":"021WG1-KA-501","count":121,"preSum":484},{"ndv":119,"upper":"023W-DE-033","lower":"022FJ-012","count":121,"preSum":605},{"ndv":118,"upper":"025WA-GC-024同","lower":"023W-DE-042","count":121,"preSum":726},{"ndv":118,"upper":"027VC-077店","lower":"025WA-GC-051A","count":121,"preSum":847},{"ndv":116,"upper":"028W-N011-002","lower":"027VC-086A","count":121,"preSum":968},{"ndv":116,"upper":"029WA-EJ-022","lower":"028W-N028-000A","count":121,"preSum":1089},{"ndv":118,"upper":"029WE-GT-004","lower":"029WA-EJ-023","count":121,"preSum":1210},{"ndv":117,"upper":"121- 02-05 D30","lower":"029WE-GT-007","count":121,"preSum":1331},{"ndv":120,"upper":"235- 11-13 79","lower":"121- 03-04 59","count":121,"preSum":1452},{"ndv":120,"upper":"310EA-004同","lower":"235- 21-05 007","count":121,"preSum":1573},{"ndv":116,"upper":"313BG-027","lower":"310EGL-003","count":121,"preSum":1694},{"ndv":119,"upper":"319VA-L-010","lower":"313CA-070","count":121,"preSum":1815},{"ndv":117,"upper":"354DLD007-000","lower":"319VA-N-012","count":121,"preSum":1936},{"ndv":120,"upper":"371EJ-F16-004","lower":"354N-019","count":121,"preSum":2057},{"ndv":121,"upper":"377C-204同","lower":"371EL-A15-037A同","count":121,"preSum":2178},{"ndv":119,"upper":"396AD-003同","lower":"377C-205","count":121,"preSum":2299},{"ndv":119,"upper":"418VA-M-032","lower":"396AF-001","count":121,"preSum":2420},{"ndv":120,"upper":"433B-044","lower":"419D-044","count":121,"preSum":2541},{"ndv":120,"upper":"452AJ-000店","lower":"433C-039","count":121,"preSum":2662},{"ndv":117,"upper":"471- C-76 34B","lower":"452DLD079-000","count":121,"preSum":2783},{"ndv":119,"upper":"476BB-003","lower":"471- D-11 10F","count":121,"preSum":2904},{"ndv":120,"upper":"512DLD01Z-000A","lower":"476BE-DLD008000","count":121,"preSum":3025},{"ndv":117,"upper":"516TH-009同","lower":"512DLD02J-000","count":121,"preSum":3146},{"ndv":119,"upper":"531AH-034","lower":"516U-068同","count":121,"preSum":3267},{"ndv":120,"upper":"535WA-KE-010","lower":"531AK-004同","count":121,"preSum":3388},{"ndv":115,"upper":"551","lower":"535WA-KK-028","count":121,"preSum":3509},{"ndv":118,"upper":"559J-020B","lower":"551-564GD-019","count":121,"preSum":3630},{"ndv":121,"upper":"571WB-HL-028","lower":"561A-007同","count":121,"preSum":3751},{"ndv":120,"upper":"574WA-EU-C37-028","lower":"571WB-HN-058","count":121,"preSum":3872},{"ndv":117,"upper":"579W-JE-A7-015同","lower":"574WA-EV-B31-055","count":121,"preSum":3993},{"ndv":116,"upper":"595CQ-035A","lower":"579W-JE-A7-023","count":121,"preSum":4114},{"ndv":118,"upper":"631- H157-10 12","lower":"595CU-061同","count":121,"preSum":4235},{"ndv":118,"upper":"685- 70-1 505","lower":"631- I303-11 77","count":121,"preSum":4356},{"ndv":119,"upper":"714G-003","lower":"691A-202","count":121,"preSum":4477},{"ndv":118,"upper":"722G-014同","lower":"714G-045","count":121,"preSum":4598},{"ndv":117,"upper":"7311LD-059同","lower":"722G-022同","count":121,"preSum":4719},{"ndv":118,"upper":"736D023-000","lower":"7311LH-012同","count":121,"preSum":4840},{"ndv":117,"upper":"745VA-H-034","lower":"736D037-000","count":121,"preSum":4961},{"ndv":119,"upper":"753-753EB-012","lower":"745VA-J-045","count":121,"preSum":5082},{"ndv":116,"upper":"755WF-AL-128C","lower":"753-753TH-010","count":121,"preSum":5203},{"ndv":118,"upper":"757WA-BD-003C","lower":"755WF-AM-WAL017D","count":121,"preSum":5324},{"ndv":117,"upper":"760BC-A3-008B","lower":"757WA-BG-036D","count":121,"preSum":5445},{"ndv":120,"upper":"769WB-UB-010B","lower":"760BE-3-008B","count":121,"preSum":5566},{"ndv":117,"upper":"771AS-001","lower":"769WB-ZHEC-011A","count":121,"preSum":5687},{"ndv":118,"upper":"774D029-009","lower":"771BC-010","count":121,"preSum":5808},{"ndv":117,"upper":"791- 27 MD1","lower":"774D029-015","count":121,"preSum":5929},{"ndv":119,"upper":"797ZHN-022","lower":"791- 29 TS02","count":121,"preSum":6050},{"ndv":119,"upper":"818AD-021","lower":"797ZHN-031","count":121,"preSum":6171},{"ndv":116,"upper":"831J-025","lower":"818B-011","count":121,"preSum":6292},{"ndv":114,"upper":"851AG-002同","lower":"831J-051","count":121,"preSum":6413},{"ndv":113,"upper":"857DLD017000-DLD017000","lower":"851AG-012同","count":121,"preSum":6534},{"ndv":116,"upper":"871Z020-010","lower":"857DLD018-002","count":121,"preSum":6655},{"ndv":119,"upper":"879VA-E-009","lower":"871Z027-012","count":121,"preSum":6776},{"ndv":116,"upper":"901BB-008同","lower":"879VA-JC-004同","count":121,"preSum":6897},{"ndv":116,"upper":"917DLD041-000","lower":"901C- 23-01 LSA2","count":121,"preSum":7018},{"ndv":116,"upper":"934KB-002","lower":"917DLD045-999","count":121,"preSum":7139},{"ndv":117,"upper":"951CAL-009","lower":"934M-102","count":121,"preSum":7260},{"ndv":118,"upper":"992AD-036","lower":"951CB-005","count":121,"preSum":7381},{"ndv":116,"upper":"T10-A-512GQ-077","lower":"993","count":121,"preSum":7502},{"ndv":82,"upper":"ZW5-519C-067","lower":"T14-A-512THH-008","count":83,"preSum":7623}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[28,3,3,3,3,3,3,3,3,5,3,3,3],"valueArr":["","010W-010","053","376D035000-D006000","431ZHF-012","512","738DLD004-000","755W-BF-051","755WM-DTL-008同","769WF-769","790- 01-17 E1","892DLD003-000","953VA-C-014"],"type":"String","sampleRate":0.9618625319816094}',92229,0.02436278),('jala_wms_prod','shipment_header','scheduledshipdate',384,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":"1850348327174930432","lower":"1850330734988886016","count":23,"preSum":0},{"ndv":5,"upper":"1850363720337719296","lower":"1850350526198185984","count":13,"preSum":23},{"ndv":4,"upper":"1850376914477252608","lower":"1850365919360974848","count":11,"preSum":36},{"ndv":4,"upper":"1850398904709808128","lower":"1850383511547019264","count":13,"preSum":47},{"ndv":1,"upper":"1850401103733063680","lower":"1850401103733063680","count":11,"preSum":60},{"ndv":4,"upper":"1850427492012130304","lower":"1850407700802830336","count":11,"preSum":71},{"ndv":2,"upper":"1850436288105152512","lower":"1850434089081896960","count":15,"preSum":82},{"ndv":5,"upper":"1850464875407474688","lower":"1850442885174919168","count":22,"preSum":97},{"ndv":1,"upper":"1850467074430730240","lower":"1850467074430730240","count":14,"preSum":119},{"ndv":3,"upper":"1850480268570263552","lower":"1850473671500496896","count":27,"preSum":133},{"ndv":1,"upper":"1850482467593519104","lower":"1850482467593519104","count":23,"preSum":160},{"ndv":2,"upper":"1850500059779563520","lower":"1850497860756307968","count":20,"preSum":183},{"ndv":4,"upper":"1850530846105141248","lower":"1850511054895841280","count":23,"preSum":203},{"ndv":1,"upper":"1850546239267930112","lower":"1850546239267930112","count":14,"preSum":226},{"ndv":1,"upper":"1850566030477230080","lower":"1850566030477230080","count":24,"preSum":240},{"ndv":3,"upper":"1850581423640018944","lower":"1850577025593507840","count":18,"preSum":264},{"ndv":3,"upper":"1850592418756296704","lower":"1850585821686530048","count":14,"preSum":282},{"ndv":4,"upper":"1850623205081874432","lower":"1850596816802807808","count":11,"preSum":296},{"ndv":2,"upper":"1850700170895818752","lower":"1850625404105129984","count":22,"preSum":307},{"ndv":3,"upper":"1850715564058607616","lower":"1850711166012096512","count":22,"preSum":329},{"ndv":3,"upper":"1850724360151629824","lower":"1850719962105118720","count":14,"preSum":351},{"ndv":2,"upper":"1850730957221396480","lower":"1850728758198140928","count":20,"preSum":365},{"ndv":5,"upper":"1850785932802785280","lower":"1850759544523718656","count":15,"preSum":385},{"ndv":1,"upper":"1850794728895807488","lower":"1850794728895807488","count":20,"preSum":400},{"ndv":3,"upper":"1850810122058596352","lower":"1850801325965574144","count":15,"preSum":420},{"ndv":3,"upper":"1850849704477196288","lower":"1850814520105107456","count":15,"preSum":435},{"ndv":4,"upper":"1850862898616729600","lower":"1850854102523707392","count":16,"preSum":450},{"ndv":1,"upper":"1850865097639985152","lower":"1850865097639985152","count":21,"preSum":466},{"ndv":4,"upper":"1850880490802774016","lower":"1850869495686496256","count":34,"preSum":487},{"ndv":7,"upper":"1850928869314396160","lower":"1850884888849285120","count":30,"preSum":521},{"ndv":4,"upper":"1850944262477185024","lower":"1850933267360907264","count":28,"preSum":551},{"ndv":5,"upper":"1850972849779507200","lower":"1850959655639973888","count":12,"preSum":579},{"ndv":4,"upper":"1851010233174851584","lower":"1850999238058573824","count":30,"preSum":591},{"ndv":5,"upper":"1851038820477173760","lower":"1851012432198107136","count":15,"preSum":621},{"ndv":5,"upper":"1851071805826007040","lower":"1851054213639962624","count":11,"preSum":636},{"ndv":1,"upper":"1851074004849262592","lower":"1851074004849262592","count":17,"preSum":647},{"ndv":7,"upper":"1851104791174840320","lower":"1851078402895773696","count":27,"preSum":664},{"ndv":3,"upper":"1851124582384140288","lower":"1851106990198095872","count":8,"preSum":691}],"maxBucketSize":64,"type":"Date","sampleRate":0.9618625}','{"countArr":[98808,58,29,60,29,33,28,26,29,45,52,72,33],"valueArr":[-1,1850370317407485952,1850385710570274816,1850420894942363648,1850451681267941376,1850515452942352384,1850779335733018624,1850825515221385216,1850913476151607296,1850975048802762752,1851025626337640448,1851041019500429312,1851089398012051456],"type":"Date","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','secondsectioncode',11448,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":11,"upper":"01-11","lower":"01-01C","count":55,"preSum":0},{"ndv":12,"upper":"01-21","lower":"01-12","count":57,"preSum":55},{"ndv":27,"upper":"01-64","lower":"01-23","count":55,"preSum":112},{"ndv":17,"upper":"02-05","lower":"01-67","count":54,"preSum":167},{"ndv":22,"upper":"03-02","lower":"02-06","count":55,"preSum":221},{"ndv":9,"upper":"03-12","lower":"03-04","count":58,"preSum":276},{"ndv":23,"upper":"04-05","lower":"03-13","count":57,"preSum":334},{"ndv":22,"upper":"05-02","lower":"04-06","count":56,"preSum":391},{"ndv":7,"upper":"05-09","lower":"05-03","count":56,"preSum":447},{"ndv":19,"upper":"06-03","lower":"05-10","count":60,"preSum":503},{"ndv":11,"upper":"06-16","lower":"06-04","count":54,"preSum":563},{"ndv":17,"upper":"07-07","lower":"06-18","count":55,"preSum":617},{"ndv":27,"upper":"08-A","lower":"07-09","count":56,"preSum":672},{"ndv":24,"upper":"1","lower":"08E-13","count":54,"preSum":728},{"ndv":21,"upper":"10-07","lower":"1-01","count":54,"preSum":782},{"ndv":30,"upper":"11-02","lower":"10-08","count":55,"preSum":836},{"ndv":25,"upper":"12-02","lower":"11-03","count":60,"preSum":891},{"ndv":25,"upper":"13-00","lower":"12-03","count":54,"preSum":951},{"ndv":24,"upper":"14-06","lower":"13-02","count":59,"preSum":1005},{"ndv":31,"upper":"152","lower":"14-09","count":54,"preSum":1064},{"ndv":18,"upper":"17-03","lower":"16","count":54,"preSum":1118},{"ndv":23,"upper":"18-02","lower":"17-04","count":56,"preSum":1172},{"ndv":33,"upper":"2-1","lower":"18-04","count":58,"preSum":1228},{"ndv":31,"upper":"21-02","lower":"2-10","count":56,"preSum":1286},{"ndv":20,"upper":"22-03","lower":"21-03","count":54,"preSum":1342},{"ndv":24,"upper":"24-06","lower":"22-05","count":54,"preSum":1396},{"ndv":35,"upper":"29","lower":"24-09","count":56,"preSum":1450},{"ndv":19,"upper":"30-05","lower":"29-01","count":54,"preSum":1506},{"ndv":29,"upper":"36","lower":"30-15","count":59,"preSum":1560},{"ndv":22,"upper":"4-6","lower":"36-01","count":56,"preSum":1619},{"ndv":40,"upper":"445","lower":"4-60","count":54,"preSum":1675},{"ndv":41,"upper":"490","lower":"448","count":54,"preSum":1729},{"ndv":21,"upper":"51-01","lower":"490-95","count":55,"preSum":1783},{"ndv":29,"upper":"57-06","lower":"51-05","count":54,"preSum":1838},{"ndv":37,"upper":"65-23","lower":"57-12","count":54,"preSum":1892},{"ndv":31,"upper":"70-20","lower":"65-44","count":54,"preSum":1946},{"ndv":38,"upper":"765","lower":"70-25","count":54,"preSum":2000},{"ndv":40,"upper":"823","lower":"771","count":55,"preSum":2054},{"ndv":28,"upper":"A-09","lower":"84","count":56,"preSum":2109},{"ndv":30,"upper":"A-700","lower":"A-1","count":54,"preSum":2165},{"ndv":36,"upper":"A28","lower":"A-89","count":54,"preSum":2219},{"ndv":39,"upper":"B-03","lower":"A29","count":55,"preSum":2273},{"ndv":30,"upper":"B-85","lower":"B-04","count":54,"preSum":2328},{"ndv":43,"upper":"B39","lower":"B-S40","count":54,"preSum":2382},{"ndv":38,"upper":"C-04","lower":"B4","count":55,"preSum":2436},{"ndv":37,"upper":"C07","lower":"C-05","count":54,"preSum":2491},{"ndv":44,"upper":"C51","lower":"C07-01","count":55,"preSum":2545},{"ndv":42,"upper":"D-06","lower":"C57","count":54,"preSum":2600},{"ndv":36,"upper":"D15","lower":"D-08","count":54,"preSum":2654},{"ndv":38,"upper":"D50-62","lower":"D21","count":54,"preSum":2708},{"ndv":39,"upper":"E-202","lower":"D52","count":54,"preSum":2762},{"ndv":37,"upper":"E21-22","lower":"E-203","count":54,"preSum":2816},{"ndv":43,"upper":"F23-01","lower":"E21-23","count":54,"preSum":2870},{"ndv":40,"upper":"G141","lower":"F27","count":54,"preSum":2924},{"ndv":36,"upper":"H90","lower":"G293","count":56,"preSum":2978},{"ndv":36,"upper":"K03","lower":"H99-10","count":55,"preSum":3034},{"ndv":42,"upper":"L4","lower":"K04-20","count":54,"preSum":3089},{"ndv":37,"upper":"M99-08","lower":"L67-07","count":55,"preSum":3143},{"ndv":36,"upper":"R-07","lower":"M99-09","count":54,"preSum":3198},{"ndv":37,"upper":"T-07","lower":"R-1B","count":54,"preSum":3252},{"ndv":34,"upper":"Y-01","lower":"T-08","count":58,"preSum":3306},{"ndv":35,"upper":"ZH-034","lower":"Y-03","count":50,"preSum":3364}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[17,15,19,17,16,16,18,15,19,19,20,20],"valueArr":["01-01","01-02","01-03","03-01","03-03","04-01","05-01","06-02","09-01","11-01","12-01","13-01"],"type":"String","sampleRate":0.9618625319816094}',96376,0.02436278),('jala_wms_prod','shipment_header','secondwaybillcodes',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','sellerto',997,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":5,"upper":"1000262","lower":"1000198","count":42,"preSum":0},{"ndv":6,"upper":"1000291","lower":"1000264","count":33,"preSum":42},{"ndv":2,"upper":"1000309","lower":"1000299","count":35,"preSum":75},{"ndv":2,"upper":"1000319","lower":"1000318","count":42,"preSum":110},{"ndv":7,"upper":"1000351","lower":"1000331","count":30,"preSum":152},{"ndv":8,"upper":"1000370","lower":"1000355","count":32,"preSum":182},{"ndv":3,"upper":"1000389","lower":"1000375","count":31,"preSum":214},{"ndv":1,"upper":"1000390","lower":"1000390","count":30,"preSum":245},{"ndv":7,"upper":"1000413","lower":"1000395","count":53,"preSum":275},{"ndv":6,"upper":"1000438","lower":"1000414","count":34,"preSum":328},{"ndv":6,"upper":"1000457","lower":"1000439","count":32,"preSum":362},{"ndv":5,"upper":"1000482","lower":"1000465","count":30,"preSum":394},{"ndv":6,"upper":"1000500","lower":"1000484","count":30,"preSum":424},{"ndv":5,"upper":"1000529","lower":"1000501","count":32,"preSum":454},{"ndv":8,"upper":"1000605","lower":"1000532","count":34,"preSum":486},{"ndv":4,"upper":"1000698","lower":"1000608","count":52,"preSum":520},{"ndv":6,"upper":"1000818","lower":"1000724","count":45,"preSum":572},{"ndv":4,"upper":"1000848","lower":"1000832","count":31,"preSum":617},{"ndv":4,"upper":"1000901","lower":"1000861","count":42,"preSum":648},{"ndv":5,"upper":"1001005","lower":"1000928","count":32,"preSum":690},{"ndv":9,"upper":"1001067","lower":"1001006","count":30,"preSum":722},{"ndv":3,"upper":"1001080","lower":"1001078","count":35,"preSum":752},{"ndv":4,"upper":"1001085","lower":"1001081","count":55,"preSum":787},{"ndv":10,"upper":"1001184","lower":"1001088","count":31,"preSum":842},{"ndv":17,"upper":"1001390","lower":"1001208","count":30,"preSum":873},{"ndv":19,"upper":"1001629","lower":"1001392","count":34,"preSum":903},{"ndv":7,"upper":"1001772","lower":"1001655","count":46,"preSum":937},{"ndv":9,"upper":"1001856","lower":"1001781","count":33,"preSum":983},{"ndv":11,"upper":"1002043","lower":"1001865","count":33,"preSum":1016},{"ndv":8,"upper":"1002075","lower":"1002047","count":41,"preSum":1049},{"ndv":4,"upper":"1002098","lower":"1002083","count":31,"preSum":1090},{"ndv":8,"upper":"1002173","lower":"1002099","count":31,"preSum":1121},{"ndv":7,"upper":"1002229","lower":"1002178","count":40,"preSum":1152},{"ndv":2,"upper":"1002257","lower":"1002256","count":31,"preSum":1192},{"ndv":6,"upper":"1002312","lower":"1002277","count":32,"preSum":1223},{"ndv":6,"upper":"1002430","lower":"1002341","count":39,"preSum":1255},{"ndv":13,"upper":"1002535","lower":"1002441","count":30,"preSum":1294},{"ndv":12,"upper":"1002658","lower":"1002563","count":41,"preSum":1324},{"ndv":4,"upper":"1002679","lower":"1002660","count":43,"preSum":1365},{"ndv":13,"upper":"1002789","lower":"1002680","count":32,"preSum":1408},{"ndv":9,"upper":"1002831","lower":"1002794","count":30,"preSum":1440},{"ndv":9,"upper":"1002952","lower":"1002835","count":33,"preSum":1470},{"ndv":10,"upper":"9992","lower":"1002953","count":46,"preSum":1503},{"ndv":8,"upper":"D017","lower":"C001","count":37,"preSum":1549},{"ndv":8,"upper":"R15E","lower":"DJ01","count":30,"preSum":1586},{"ndv":7,"upper":"S004-1000","lower":"R18A","count":41,"preSum":1616},{"ndv":3,"upper":"S007-1000","lower":"S005-1000","count":41,"preSum":1657},{"ndv":2,"upper":"S102-1000","lower":"S101-1000","count":33,"preSum":1698},{"ndv":1,"upper":"S103-1000","lower":"S103-1000","count":30,"preSum":1731},{"ndv":2,"upper":"S106-1000","lower":"S104-1000","count":35,"preSum":1761},{"ndv":4,"upper":"S112-1000","lower":"S107-1000","count":51,"preSum":1796},{"ndv":2,"upper":"S115-1000","lower":"S113-1000","count":38,"preSum":1847}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[426,45,33,32,37,96,154,33,144,61,60,35,47,33],"valueArr":["","1000183","1000292","1000313","1000650","1000746","1000767","1000792","1002333","1002871","9914","9998","S001-1000","S105-1000"],"type":"String","sampleRate":0.9618625319816094}',96880,0.02436278),('jala_wms_prod','shipment_header','servicemode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','sfweightprocess',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[7149,68608],"valueArr":["N","Y"],"type":"String","sampleRate":0.9618625319816094}',24244,0.02436278),('jala_wms_prod','shipment_header','shipdock',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory1',20,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"23","lower":"23","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[96083,67,1213,412,60,60,14,81,4,177,153],"valueArr":["","10","A","B","C","D","E","G","K","Q","Z"],"type":"String","sampleRate":0.9618625319816094}',1676,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory2',19,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"23","lower":"23","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[96132,148,375,70,5,29,1474,4,52,35],"valueArr":["","同城","商超","屈臣氏","特通","电商","美妆","美妆-KA","美妆-RKA","货架"],"type":"String","sampleRate":0.9618625319816094}',1676,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory3',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[26,2094],"valueArr":["","3"],"type":"String","sampleRate":0.9618625319816094}',97881,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory4',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[23,81755,12772],"valueArr":["","自营","非自营"],"type":"String","sampleRate":0.9618625319816094}',5451,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory5',192,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":10,"upper":"全品牌-人资福利店铺(日常)","lower":"Chando-LazadaMYHimalaya(日常)","count":266,"preSum":0},{"ndv":9,"upper":"春夏-天猫旗舰店(日常)","lower":"全品牌-优礼汇特通店铺(日常)","count":459,"preSum":266},{"ndv":6,"upper":"植物智慧-天猫旗舰店(日常)","lower":"春夏-天猫旗舰店(派样)","count":228,"preSum":725},{"ndv":3,"upper":"珀芙研-云店(日常)","lower":"植物智慧-抖音美妆官方店(日常)","count":218,"preSum":953},{"ndv":6,"upper":"珀芙研-抖音小店(日常)","lower":"珀芙研-京东POP旗舰店(日常)","count":385,"preSum":1171},{"ndv":3,"upper":"珀芙研-蘑菇街旗舰店(日常)","lower":"珀芙研-泛斯特店(日常)","count":646,"preSum":1556},{"ndv":2,"upper":"美素-天猫旗舰店(日常)","lower":"美素-京东POP官方旗舰店(日常)","count":331,"preSum":2202},{"ndv":6,"upper":"自然堂-云店(官方商城)(日常)","lower":"美素-天猫旗舰店(派样)","count":415,"preSum":2533},{"ndv":3,"upper":"自然堂-京东POP旗舰店(派样)","lower":"自然堂-云店(美妆2.0)(日常)","count":262,"preSum":2948},{"ndv":1,"upper":"自然堂-京东乐肤迪官方旗舰店(日常)","lower":"自然堂-京东乐肤迪官方旗舰店(日常)","count":224,"preSum":3210},{"ndv":1,"upper":"自然堂-京东充花专卖店(日常)","lower":"自然堂-京东充花专卖店(日常)","count":335,"preSum":3434},{"ndv":1,"upper":"自然堂-京东彧弈美妆专营店(日常)","lower":"自然堂-京东彧弈美妆专营店(日常)","count":320,"preSum":3769},{"ndv":2,"upper":"自然堂-京东悦悦美铺化妆品专营店(日常)","lower":"自然堂-京东思琪化妆品专营店(日常)","count":293,"preSum":4089},{"ndv":5,"upper":"自然堂-京东每妆护肤旗舰店(日常)","lower":"自然堂-京东晟妆专卖店(日常)","count":299,"preSum":4382},{"ndv":2,"upper":"自然堂-京东然美专卖店(日常)","lower":"自然堂-京东泽品美妆化妆品专营店(日常)","count":355,"preSum":4681},{"ndv":1,"upper":"自然堂-京东硕齐化妆品专营店(日常)","lower":"自然堂-京东硕齐化妆品专营店(日常)","count":323,"preSum":5036},{"ndv":1,"upper":"自然堂-京东美姿专卖店(日常)","lower":"自然堂-京东美姿专卖店(日常)","count":675,"preSum":5359},{"ndv":1,"upper":"自然堂-京东美爆化妆品专营店(日常)","lower":"自然堂-京东美爆化妆品专营店(日常)","count":424,"preSum":6034},{"ndv":4,"upper":"自然堂-品牌专卖1店(日常)","lower":"自然堂-京东美轩美妆(日常)","count":261,"preSum":6458},{"ndv":1,"upper":"自然堂-品牌专卖2店(日常)","lower":"自然堂-品牌专卖2店(日常)","count":430,"preSum":6719},{"ndv":6,"upper":"自然堂-天猫伊恋化妆品专营店(日常)","lower":"自然堂-品牌专卖3店(日常)","count":566,"preSum":7149},{"ndv":2,"upper":"自然堂-天猫俏美人专卖店(日常)","lower":"自然堂-天猫优购化妆品专营店(日常)","count":340,"preSum":7715},{"ndv":2,"upper":"自然堂-天猫名轩专卖店(日常)","lower":"自然堂-天猫博美化妆品专营店(日常)","count":556,"preSum":8055},{"ndv":1,"upper":"自然堂-天猫思琪化妆品专营店(日常)","lower":"自然堂-天猫思琪化妆品专营店(日常)","count":634,"preSum":8611},{"ndv":1,"upper":"自然堂-天猫杰宸专卖店(日常)","lower":"自然堂-天猫杰宸专卖店(日常)","count":716,"preSum":9245},{"ndv":1,"upper":"自然堂-天猫永信化妆品专营店(日常)","lower":"自然堂-天猫永信化妆品专营店(日常)","count":222,"preSum":9961},{"ndv":1,"upper":"自然堂-天猫泽品化妆品专营店(日常)","lower":"自然堂-天猫泽品化妆品专营店(日常)","count":222,"preSum":10183},{"ndv":2,"upper":"自然堂-天猫硕齐化妆品专营店(日常)","lower":"自然堂-天猫男士旗舰店(派样)","count":485,"preSum":10405},{"ndv":3,"upper":"自然堂-小红书旗舰店(日常)","lower":"自然堂-小程序官方商城(日常)","count":528,"preSum":10890},{"ndv":2,"upper":"自然堂-抖音CHANDO男士旗舰店(日常)","lower":"自然堂-快手官方旗舰店(派样)","count":587,"preSum":11418},{"ndv":2,"upper":"自然堂-抖音官方旗舰店(派样)","lower":"自然堂-抖音CHANDO男士旗舰店(派样)","count":594,"preSum":12005},{"ndv":4,"upper":"自然堂-拼多多奕初专卖店(日常)","lower":"自然堂-抖音美妆旗舰店(派样)","count":229,"preSum":12599},{"ndv":14,"upper":"自然堂-淘宝zhangmin811028(日常)","lower":"自然堂-拼多多尧美专卖店(日常)","count":265,"preSum":12828},{"ndv":3,"upper":"自然堂-考拉旗舰店(日常)","lower":"自然堂-淘宝化妆品折扣店(日常)","count":302,"preSum":13093},{"ndv":4,"upper":"莎辛那-天猫旗舰店(派样)","lower":"自然堂-蘑菇街旗舰店(日常)","count":205,"preSum":13395}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2115,1175,1282,1083,6924,45974,1311,1650,1174,2211,1046,835,11289,2932],"valueArr":["","珀芙研-天猫旗舰店(日常)","自然堂-京东POP旗舰店(日常)","自然堂-京东京品美妆专卖店(日常)","自然堂-唯品会自营旗舰店(中国)(日常)","自然堂-天猫旗舰店(日常)","自然堂-天猫旗舰店(派样)","自然堂-天猫朵纯专卖店(日常)","自然堂-天猫然美专卖店(日常)","自然堂-天猫男士旗舰店(日常)","自然堂-天猫门萨专卖店(日常)","自然堂-快手官方旗舰店(日常)","自然堂-抖音官方旗舰店(日常)","自然堂-抖音美妆旗舰店(日常)"],"type":"String","sampleRate":0.9618625319816094}',5400,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory6',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory7',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','shipmentcategory8',45,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"2C单票>30件单波1单波次","lower":"","count":34,"preSum":0},{"ndv":1,"upper":"2C国际单出库波次","lower":"2C国际单出库波次","count":159,"preSum":34},{"ndv":2,"upper":"2C提总波次(预付款已付尾款)","lower":"2C提总单波次(预付款未付尾款)","count":201,"preSum":193},{"ndv":1,"upper":"2C提总波次(预售已付尾款)","lower":"2C提总波次(预售已付尾款)","count":160,"preSum":394},{"ndv":1,"upper":"2C散单波次(预付款已付尾款)\\t","lower":"2C散单波次(预付款已付尾款)\\t","count":28,"preSum":554},{"ndv":1,"upper":"2C散单波次(预付款已付尾款)","lower":"2C散单波次(预付款已付尾款)","count":51,"preSum":582},{"ndv":1,"upper":"2C散单波次(预售已付尾款)","lower":"2C散单波次(预售已付尾款)","count":140,"preSum":633},{"ndv":1,"upper":"2C散单波次(预售未付尾款)","lower":"2C散单波次(预售未付尾款)","count":51,"preSum":773},{"ndv":3,"upper":"新1.0-2C提总波次(存储区出库)","lower":"2C调拨出库波次","count":126,"preSum":824},{"ndv":2,"upper":"春夏2C非天猫提总波次","lower":"春夏2C天猫散单波次","count":153,"preSum":950},{"ndv":1,"upper":"珀芙研2C正常提总波次","lower":"珀芙研2C正常提总波次","count":124,"preSum":1103},{"ndv":4,"upper":"自然堂2C唯品会提总波次","lower":"珀芙研2C正常散单波次","count":55,"preSum":1227},{"ndv":1,"upper":"自然堂2C唯品会散单波次","lower":"自然堂2C唯品会散单波次","count":162,"preSum":1282},{"ndv":1,"upper":"自然堂2C正常散单波次","lower":"自然堂2C正常散单波次","count":117,"preSum":1444},{"ndv":1,"upper":"自然堂2C预付款散单已付尾款波次","lower":"自然堂2C预付款散单已付尾款波次","count":125,"preSum":1561}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[24270,393,5721,318,2100,3221,45747,325,609,4176,763,783,507,553],"valueArr":["2C提总单波次","2C提总单波次(预付款已付尾款)","2C提总波次","2C提总波次(预付款未付尾款)","2C提总波次(预售未付尾款)","2C提总波次(存储区出库)","2C散单波次","2C预包单提总单波次","提总-2C预付款已付尾款指定库位发货波次","提总-自然堂2C预付款已付尾款指定库位发货波次","提总-自然堂618指定库位发货波次","自然堂2C正常提总波次","自然堂2C预付款提总已付尾款波次","自然堂2C预付款提总未付尾款波次"],"type":"String","sampleRate":0.9618625319816094}',8829,0.02436278),('jala_wms_prod','shipment_header','shipmentnote',2522375,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1455,"upper":"JD20230536183063220;","lower":"01仓的产品请不要发超允收期(效期1/3-3个月)的产品","count":1511,"preSum":0},{"ndv":1511,"upper":"JX07230553279191226;","lower":"JD20230536631975406;","count":1511,"preSum":1511},{"ndv":1511,"upper":"JX10230544614844604;","lower":"JX07230553323668828;","count":1511,"preSum":3022},{"ndv":1511,"upper":"JX12230659373287001;","lower":"JX10230544614844904;","count":1511,"preSum":4533},{"ndv":1511,"upper":"JX15230541585052302;","lower":"JX12230659427547906;","count":1511,"preSum":6044},{"ndv":1511,"upper":"JX18230405537350025;","lower":"JX15230541630711406;","count":1511,"preSum":7555},{"ndv":1511,"upper":"JX20230535610442703;","lower":"JX18230405572657830;","count":1511,"preSum":9066},{"ndv":1511,"upper":"JX21230643455930610;","lower":"JX20230535638302507;","count":1511,"preSum":10577},{"ndv":1511,"upper":"JX23230526366145631;","lower":"JX21230643468227912;","count":1511,"preSum":12088},{"ndv":1501,"upper":"OD10230645410084804;","lower":"JX23230526366151531;","count":1511,"preSum":13599},{"ndv":1511,"upper":"OD16230504336266729;","lower":"OD10230645481902515;","count":1511,"preSum":15110},{"ndv":1509,"upper":"SD00230526646133109;","lower":"OD16230504336267429;","count":1511,"preSum":16621},{"ndv":1511,"upper":"SD01230436562440229;","lower":"SD00230526653561710;","count":1511,"preSum":18132},{"ndv":1511,"upper":"SD01230649495391316;","lower":"SD01230436562440329;","count":1511,"preSum":19643},{"ndv":1511,"upper":"SD03230609578925622;","lower":"SD01230649495400016;","count":1511,"preSum":21154},{"ndv":1510,"upper":"SD09230550262141223;","lower":"SD03230609598349227;","count":1511,"preSum":22665},{"ndv":1511,"upper":"SD11230419535194525;","lower":"SD09230550582823202;","count":1511,"preSum":24176},{"ndv":1511,"upper":"SD12230506680406713;","lower":"SD11230419535195125;","count":1511,"preSum":25687},{"ndv":1511,"upper":"SD13230534687696614;","lower":"SD12230506680407413;","count":1511,"preSum":27198},{"ndv":1511,"upper":"SD14230525281050226;","lower":"SD13230534787222416;","count":1511,"preSum":28709},{"ndv":1511,"upper":"SD15230529920417617;","lower":"SD14230526623141605;","count":1511,"preSum":30220},{"ndv":1509,"upper":"SD16230544337076329;","lower":"SD15230530796505716;","count":1511,"preSum":31731},{"ndv":1511,"upper":"SD17230559319934227;","lower":"SD16230544353742131;","count":1511,"preSum":33242},{"ndv":1511,"upper":"SD19230401537548725;","lower":"SD17230559319935027;","count":1511,"preSum":34753},{"ndv":1511,"upper":"SD20230509942427917;","lower":"SD19230404510404721;","count":1511,"preSum":36264},{"ndv":1511,"upper":"SD21230548265665723;","lower":"SD20230510258796222;","count":1511,"preSum":37775},{"ndv":1511,"upper":"SD22230529283786826;","lower":"SD21230548265665823;","count":1511,"preSum":39286},{"ndv":1511,"upper":"SD23230524260747722;","lower":"SD22230529283788426;","count":1511,"preSum":40797},{"ndv":1511,"upper":"SDC1123040516565822;","lower":"SD23230524260747822;","count":1511,"preSum":42308},{"ndv":1511,"upper":"TB00230613550538219;","lower":"SDC1123040516566022;","count":1511,"preSum":43819},{"ndv":1511,"upper":"TB04230512331028729;","lower":"TB00230613550538919;","count":1511,"preSum":45330},{"ndv":1511,"upper":"TB08230422458785514;","lower":"TB04230513284882327;","count":1511,"preSum":46841},{"ndv":1511,"upper":"TB09230510634913607;","lower":"TB08230422505595521;","count":1511,"preSum":48352},{"ndv":1511,"upper":"TB09230541288643027;","lower":"TB09230510634916507;","count":1511,"preSum":49863},{"ndv":1511,"upper":"TB09230553292722627;","lower":"TB09230541288643227;","count":1511,"preSum":51374},{"ndv":1511,"upper":"TB10230419547434727;","lower":"TB09230553292724827;","count":1511,"preSum":52885},{"ndv":1509,"upper":"TB10230516300318527;","lower":"TB10230419547436627;","count":1511,"preSum":54396},{"ndv":1503,"upper":"TB10230531305394927;","lower":"TB10230516300336527;","count":1511,"preSum":55907},{"ndv":1511,"upper":"TB10230545310518327;","lower":"TB10230531305397227;","count":1511,"preSum":57418},{"ndv":1511,"upper":"TB10230604595087426;","lower":"TB10230545310529627;","count":1511,"preSum":58929},{"ndv":1509,"upper":"TB11230507686568414;","lower":"TB10230604595088726;","count":1511,"preSum":60440},{"ndv":1510,"upper":"TB11230655565714820;","lower":"TB11230508315875727;","count":1511,"preSum":61951},{"ndv":1509,"upper":"TB12230557333461929;","lower":"TB11230655575064121;","count":1511,"preSum":63462},{"ndv":1511,"upper":"TB13230507664600311;","lower":"TB12230558095195019;","count":1511,"preSum":64973},{"ndv":1511,"upper":"TB14230228121516825;","lower":"TB13230507664600411;","count":1511,"preSum":66484},{"ndv":1511,"upper":"TB14230640535806318;","lower":"TB14230228121517625;","count":1511,"preSum":67995},{"ndv":1510,"upper":"TB15230623460068711;","lower":"TB14230640535808718;","count":1511,"preSum":69506},{"ndv":1510,"upper":"TB16230558275778325;","lower":"TB15230623466291112;","count":1511,"preSum":71017},{"ndv":1511,"upper":"TB17230528337625029;","lower":"TB16230558319460627;","count":1511,"preSum":72528},{"ndv":1510,"upper":"TB18230525327402128;","lower":"TB17230528578851901;","count":1511,"preSum":74039},{"ndv":1511,"upper":"TB19230519938625317;","lower":"TB18230525579160801;","count":1511,"preSum":75550},{"ndv":1511,"upper":"TB20230349335599123;","lower":"TB19230519938625917;","count":1511,"preSum":77061},{"ndv":1511,"upper":"TB20230534821533516;","lower":"TB20230349340643324;","count":1511,"preSum":78572},{"ndv":1511,"upper":"TB20230629487025415;","lower":"TB20230534821535316;","count":1511,"preSum":80083},{"ndv":1511,"upper":"TB21230501721888715;","lower":"TB20230629487033615;","count":1511,"preSum":81594},{"ndv":1511,"upper":"TB21230534677305312;","lower":"TB21230501721889815;","count":1511,"preSum":83105},{"ndv":1511,"upper":"TB21230628380051601;","lower":"TB21230534677305412;","count":1511,"preSum":84616},{"ndv":1511,"upper":"TB22230419408353205;","lower":"TB21230628380058001;","count":1511,"preSum":86127},{"ndv":1511,"upper":"TB22230526834119716;","lower":"TB22230419450286312;","count":1511,"preSum":87638},{"ndv":1509,"upper":"TB22230616394594002;","lower":"TB22230526834120016;","count":1511,"preSum":89149},{"ndv":1511,"upper":"TB23230225106541922;","lower":"TB22230616394600502;","count":1511,"preSum":90660},{"ndv":1510,"upper":"TB23230540653238709;","lower":"TB23230225106542422;","count":1511,"preSum":92171},{"ndv":1511,"upper":"TB23230637474978913;","lower":"TB23230540653239109;","count":1511,"preSum":93682},{"ndv":1253,"upper":"(面贴膜)4送1配送;","lower":"TB23230637510188416;","count":1460,"preSum":95193}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[15,14,222,29,11,14,27,25,38,10,21,44,24],"valueArr":["","京东POP","日常配发","本地零售还货0401-0414 & 3月借货补货单","本地零售还货0415-0428借货补货单","本地零售还货0429-0512借货补货单","本地零售还货0513-0526&0527-0609&0501-0526借货补货单","本地零售还货0527-0609换货&0610-0623还货借货补货单","本地零售还货4月&0429-0512&0513-0526借货补货单","活动备货","美妆 自然堂2023彩妆陈列- 眉笔、眼线笔物料配发","营运部调拨","营运部调拨需求"],"type":"String","sampleRate":0.9618625319816094}',2854,0.02436278),('jala_wms_prod','shipment_header','shipmentsubtype',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[148,89044,10809],"valueArr":["","NORMAL_ORDER","PRE_WAREHOUSE"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('jala_wms_prod','shipment_header','shipmenttype',36,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"BFCK","lower":"BFCK","count":4,"preSum":0},{"ndv":1,"upper":"CGTH","lower":"CGTH","count":4,"preSum":4},{"ndv":1,"upper":"CTCK","lower":"CTCK","count":1,"preSum":8},{"ndv":1,"upper":"MM010","lower":"MM010","count":1,"preSum":9},{"ndv":1,"upper":"NBL","lower":"NBL","count":2,"preSum":10},{"ndv":1,"upper":"SAP-MM011","lower":"SAP-MM011","count":1,"preSum":12}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[57,2614,425,95405,5,13,13,60,578,681,5,9,18,105],"valueArr":["261","B2BCK","DBCK","JYCK","PTCK","QTCK","UB","XSCK","Z01","Z04","Z09","Z21","Z89","ZOR"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','shipobjtype',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":["TO_C"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','shipto',14217,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":21,"upper":"1001006","lower":"1000255","count":36,"preSum":0},{"ndv":19,"upper":"1001259","lower":"1001041","count":39,"preSum":36},{"ndv":25,"upper":"1002054","lower":"1001267","count":36,"preSum":75},{"ndv":19,"upper":"1002479","lower":"1002061","count":37,"preSum":111},{"ndv":25,"upper":"1002953","lower":"1002492","count":36,"preSum":148},{"ndv":8,"upper":"2000031","lower":"1002959","count":42,"preSum":184},{"ndv":7,"upper":"2000253","lower":"2000032","count":55,"preSum":226},{"ndv":3,"upper":"2000257","lower":"2000254","count":46,"preSum":281},{"ndv":27,"upper":"20010313","lower":"2000402","count":36,"preSum":327},{"ndv":19,"upper":"20020188","lower":"20010350","count":36,"preSum":363},{"ndv":24,"upper":"20023013","lower":"20020205","count":36,"preSum":399},{"ndv":34,"upper":"20027246","lower":"20023016","count":36,"preSum":435},{"ndv":31,"upper":"2005746","lower":"20028083","count":36,"preSum":471},{"ndv":26,"upper":"20319002","lower":"2005747","count":36,"preSum":507},{"ndv":33,"upper":"20536117","lower":"20350001","count":36,"preSum":543},{"ndv":32,"upper":"20591030","lower":"20536118","count":36,"preSum":579},{"ndv":31,"upper":"20733021","lower":"20592006","count":36,"preSum":615},{"ndv":28,"upper":"20760206","lower":"20734113","count":36,"preSum":651},{"ndv":31,"upper":"20825002","lower":"20769133","count":36,"preSum":687},{"ndv":27,"upper":"20999051","lower":"20825005","count":36,"preSum":723},{"ndv":33,"upper":"80271012","lower":"80101310","count":36,"preSum":759},{"ndv":29,"upper":"80292098","lower":"80271013","count":36,"preSum":795},{"ndv":31,"upper":"83111424","lower":"80292101","count":36,"preSum":831},{"ndv":23,"upper":"83131842","lower":"83111456","count":36,"preSum":867},{"ndv":32,"upper":"83171720","lower":"83140396","count":36,"preSum":903},{"ndv":30,"upper":"83511787","lower":"83171723","count":36,"preSum":939},{"ndv":33,"upper":"83711972","lower":"83511788","count":36,"preSum":975},{"ndv":31,"upper":"83772225","lower":"83711994","count":36,"preSum":1011},{"ndv":33,"upper":"83942419","lower":"83772250","count":36,"preSum":1047},{"ndv":31,"upper":"84160882","lower":"83942424","count":36,"preSum":1083},{"ndv":33,"upper":"84310933","lower":"84170031","count":36,"preSum":1119},{"ndv":34,"upper":"84770895","lower":"84310938","count":36,"preSum":1155},{"ndv":35,"upper":"85190348","lower":"84820423","count":36,"preSum":1191},{"ndv":33,"upper":"85371781","lower":"85190712","count":36,"preSum":1227},{"ndv":33,"upper":"85530749","lower":"85371793","count":36,"preSum":1263},{"ndv":32,"upper":"85610746","lower":"85530750","count":37,"preSum":1299},{"ndv":36,"upper":"85763179","lower":"85630405","count":36,"preSum":1336},{"ndv":33,"upper":"85963059","lower":"85771360","count":37,"preSum":1372},{"ndv":33,"upper":"87130945","lower":"85963067","count":36,"preSum":1409},{"ndv":35,"upper":"87301303","lower":"87130949","count":36,"preSum":1445},{"ndv":33,"upper":"87500019","lower":"87301311","count":36,"preSum":1481},{"ndv":34,"upper":"87570027","lower":"87520006","count":37,"preSum":1517},{"ndv":35,"upper":"87690235","lower":"87570029","count":36,"preSum":1554},{"ndv":32,"upper":"87760007","lower":"87690264","count":36,"preSum":1590},{"ndv":35,"upper":"88182089","lower":"87790034","count":36,"preSum":1626},{"ndv":33,"upper":"88392094","lower":"88182099","count":36,"preSum":1662},{"ndv":32,"upper":"88710163","lower":"88392114","count":38,"preSum":1698},{"ndv":33,"upper":"89132232","lower":"88720001","count":36,"preSum":1736},{"ndv":34,"upper":"89721864","lower":"89132248","count":36,"preSum":1772},{"ndv":11,"upper":"D017","lower":"89730005","count":44,"preSum":1808},{"ndv":13,"upper":"R18A","lower":"DJ01","count":36,"preSum":1852},{"ndv":15,"upper":"S002-1000","lower":"R18C","count":36,"preSum":1888},{"ndv":3,"upper":"S005-1000","lower":"S003-1000","count":40,"preSum":1924},{"ndv":4,"upper":"S102-1000","lower":"S007-1000","count":51,"preSum":1964},{"ndv":3,"upper":"S107-1000","lower":"S104-1000","count":51,"preSum":2015},{"ndv":4,"upper":"S113-1000","lower":"S108-1000","count":50,"preSum":2066},{"ndv":14,"upper":"TC20913072","lower":"S115-1000","count":36,"preSum":2116},{"ndv":36,"upper":"TC84310623","lower":"TC80101305","count":36,"preSum":2152},{"ndv":34,"upper":"TC85790617","lower":"TC84710525","count":36,"preSum":2188},{"ndv":32,"upper":"TC87930642","lower":"TC85792392","count":36,"preSum":2224},{"ndv":22,"upper":"TC89942082","lower":"TC87931532","count":23,"preSum":2260}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[95859,29,28,29,25,25,27,65,28,39,47,30,33],"valueArr":["","2000250","2000251","2000256","2000258","2000259","2000287","2005821","9992","9998","S001-1000","S103-1000","S105-1000"],"type":"String","sampleRate":0.9618625319816094}',1454,0.02436278),('jala_wms_prod','shipment_header','shiptoaddress1',2174001,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1532,"upper":"#4BK0gUqoG9FQjDEFMZq9bxZ5tkxoiJ70qE7jbiEq#uwdKVab1wdQXSOUjJFDNy+Rjes+AwsQs1pD3DQLDWG01sWBsrfhv6uC/4dFs0S0bwz8ySL66iu4tZFDVzi74ZR","lower":"##+9nL+7Q3xGbB2c+KyXNvTurcjmzLW7DrQD50IF+/XIkr50dNkkGKWdXVi/U9INNBRvj0Om06vEANMLdPWm1WFCa42DDdmUXdnH3Zd+MkWldRcbw1lpgn3FMn2BkTJB","count":1532,"preSum":0},{"ndv":1531,"upper":"#A42e5x6hDGHA1koASea0#YK++PU++O5L/s6QrQ5WefW+zo8bEKEijA7Cnd1gea6T7dJO50Tq2zUEQcbBxNgQnXLVjqlYou5e2Y/llsL84Hu3SZ+wFaH0EL/V/p6o5t0","lower":"#4BK0TmQOfK+dn6KQ4BK0gUqolNsYFuFsL6uLzsPaRhlsIajw2wWrEysuV/3poQ6y8tm+meOvWup7dIf+9AsCxOs54BK0gUqoT8a1#018f81tFdTDlNzfZT6NLlF6eVC","count":1532,"preSum":1532},{"ndv":1532,"upper":"#d9828vrfG9FQFdw+C8PetkxoOHVIsMHH3Fe752re3JrMfobI#U3Sr2BlbXBh7yJph7DwwzdnCszArMkQwgloAi+X0NapYLUejF6mUiKxcp1McK4ag00gjIV5KzHKe/N","lower":"#A42e64TbgUqoOh3c6UeYD8sAaEg+Rukh#/OUILF+MrAwp9RXo8aTdYcO6EnwrIqypKjIOxMW/aUsifVOitJXNn7O0cLkFXvrRnZO/sA8I4vSaWbyhWoQa0rdTHVXrss","count":1532,"preSum":3064},{"ndv":1532,"upper":"#Gln/sZh9dViAOh1MTo8FN7O5H0GMvaf3wZURxKbMHiRVNAyWdHWeWSaDWOQlPKxl#S2H53Bsg9VXmVwqrQE4dakN4Cj+f+QgMMzfjOpSz6yhClnp9X92Ov41/9GR4xa","lower":"#d982XIom8K/BLr+lYIobPOUVmR3bqnxd#YamEnu9aJN08ASgBf5m6FUZKwkBXJg7pcmJvErG7XDhSEUpdQv7+9syMgSPIKHmnr1e7ZZpf8VLCP8eV8eiy9l9yTCRd0Z","count":1532,"preSum":4596},{"ndv":1532,"upper":"#jPHUmgqgoTLIDOZkwMOQ65b5970qVEJNXIIBtVd5TcoC0Fg9AGcbmjCsc0hWxWht#mji3JFp7fksWF9gz612C0EHRSq0OQLQl8TM6segJQjYYpFyaXZ14LEso0ZMc8U","lower":"#GLrSpSeoLG2c2YNgBL/BD0Zos90y8cohvwXH+y0Wgo2pRWK/#Fhmr6RMcAlRVE5t+Bvw//k5jJArW6/XmTZvL+keLfiIJer9xU/7QN4IyNI2vu8EJwdo1NjHAO33V77","count":1532,"preSum":6128},{"ndv":1532,"upper":"#MXO9ItseBEEZeLZcHLLGaotyFuFsYfI1I5W9CcWw5+xROXTeyYL64GLn3JrM#gfbpH10qpFBgXFIZtau1AbHS15dsnNTz3OjB+wfdxpWBOJrxrqM9IgSZT3/mI2uaJ1","lower":"#jPHUmgqgoTLIDOZkwMOQi6YoDaSfkDTH8PmFJIwWVGwjwt2WfvoFI8Wy2+6cALkNt72bzW35#HrV6NTrxxBv3KQ7FeGite7rHGlA9jFgZugpO5aS8g9EYZfRX3F1VXn","count":1532,"preSum":7660},{"ndv":1532,"upper":"#Pw7xATKg3tS5IYqxtKmQevC7qq1TTFhU77UkiDykplZr#9irjK01yPdMC7ajex+Pz9ES0Zg5WyBPhpMDJXlgXKuohruXcJ4pfxuMsaKi6J4nuncHRz4/8tNeWvVrdrX","lower":"#mxRp9XLZM9e2KYsdbiEqPJnBE5kwDcNoikPU7xkZX2I3ArfsFHj2DcNoikPU7xkZX2I3Arfso4c5YIobyjs2YfI1#n0vt+wgXx8DZtvQbyekI39pFe881m198tPKIo7","count":1532,"preSum":9192},{"ndv":1529,"upper":"#t+89EqndlxJ3ovovYXtY+A+62VP0N2HrZBFwTR7+TSgp0hAv3Pg2N9wyOWnYtWSMIqWG#zIwF0QWGAIraa6lIpxDgz7R2OWSjep4uY0I1gCZdrvcryrlJBJcLbVYU0S","lower":"#Pw7xcO82lqG9kPCLGPViDa7LCophWGnXZRrJwFiR4VZ+ORhMQ+KD#3guKploXd75mtD0dyaUFNz3rouDYRxpI57cNojNB8oIwQachwp1JH3+hOg4+6YkbFphWMlX7Is","count":1532,"preSum":10724},{"ndv":1532,"upper":"#W1LNeYfCfK+d8jL6eqmRQKXRdLiObeBz7XfpvpFmtkxo7GLuvF83#9KCQ/YUKiphEv+t0K7nlW60XIPj/SFggN2P96asfLrnje8uOlyvnL42pZ/wUIb1U1Bwwv3Bc6B","lower":"#t+AEHJPaFOhUqJQp+2WL0Zufy8VN1LZIRbMZ#9rrj+rSTaFlckRhCkoTlt/4UlWsxIxn4ZM1IWU4abOMyUfkc83AI2OqrBhQsrkWPrjZSjESr8Zp4E35wbZDgk6d3fR","count":1532,"preSum":12256},{"ndv":1530,"upper":"#ZdFArEW9kyGkkB8qTale0vav#iMd3MybaUmTxmBoZPotSaweFo40ZL1WCplQ31QDIdi/rSmx8UUGkUOuy/xcW6u98U5KpEv2wZEdGRluiONcwSaQDF6NMyigZOAC2Iz","lower":"#W1LNoCZ68ipEY1acn0FrSDOky69QqDkuc0/PRWK/FRIyD1pyHFk5SMSDwcBYkiDesbO5#ZOwcQRC02b2pi+tVKR53LiQ4KdkhJ9DUqDmGaAxK+S90SCR+WGk7jYivZO","count":1532,"preSum":13788},{"ndv":1528,"upper":"~EXPYSES3xGtpEXPYSES3xGtpyYo7qyqgrPi+PbF5kvLZyfTj7stM1ka6e3P1mEnBd7EJYWZ/1ka6KwB31ka6~Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Nj","lower":"#ZdFArxK3tY0CtkxoYfI1#w78a4F//kAXNleTvzQlvSvwsXPBhfB45fvXhVWtZ6wg9ds6PpdIb0gxncKt+3PlHtTqHOhE63FyESZLI3yAwwGsJ8AIq0CbfoXfZlQUd8P","count":1532,"preSum":15320},{"ndv":1523,"upper":"三*街道**路龙湖星**栋","lower":"~EXPYTuDVxGtpgX4XYWZ/MiTwhfp79aY9eZuexT22~Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Njc5NDAxMjM5MjU4MzY3MDISMDI1Zing3yC3FMAcnFMZXp","count":1532,"preSum":16852},{"ndv":1476,"upper":"东**镇森林大第*-*-***","lower":"三*街道**路龙湖星**栋****室","count":1532,"preSum":18384},{"ndv":1491,"upper":"东湖风**街道马鞍山森**园山**村**号东湖小白","lower":"东**镇武清区东**镇","count":1532,"preSum":19916},{"ndv":1504,"upper":"九**街道青岛市李沧区**路**号*园美墅北门小媳妇铁锅炖鱼前台","lower":"东湖风景区街道东**路**号院西门","count":1532,"preSum":21448},{"ndv":1497,"upper":"产业集聚区**路鑫和美林郡旁边超市","lower":"九**街道香江**城香江翡翠**号楼","count":1532,"preSum":22980},{"ndv":1497,"upper":"八*镇二**路**街西*巷巷口","lower":"产业集聚区华**店向南第一个公交站牌对面仓库(栅栏门)请进最里面一个仓库","count":1532,"preSum":24512},{"ndv":1500,"upper":"凤*街道**街***号贵州特色**店","lower":"八*镇八**镇**街","count":1532,"preSum":26044},{"ndv":1504,"upper":"北*镇伟业**号广东美的厨房电器制造**公司","lower":"凤*街道**街**号张姨保管车","count":1532,"preSum":27576},{"ndv":1495,"upper":"南*园乡南二环****号贺**园","lower":"北*镇佛山市顺德北滘雅居乐英伦首府**栋***","count":1532,"preSum":29108},{"ndv":1495,"upper":"卢**街道大瓦**路福悦四季***单元****","lower":"南*园乡朝阳**街长**园南区**楼","count":1532,"preSum":30640},{"ndv":1500,"upper":"吉林省.长春市.榆树市.红星乡郝家村四平台屯","lower":"卢**街道梅**路**号**幢*-***","count":1532,"preSum":32172},{"ndv":1479,"upper":"四*街道海亮首府","lower":"吉林省.长春市.经济技术开发区.东方广场街道六合一方B区B26栋","count":1532,"preSum":33704},{"ndv":1459,"upper":"坂*街道中浩二**号航嘉**园宿舍**栋","lower":"四*街道鞍**路****单元***户","count":1532,"preSum":35236},{"ndv":1507,"upper":"城*镇河南省濮阳市**县**镇**路增运食品","lower":"坂*街道五**村**路**号*座","count":1532,"preSum":36768},{"ndv":1513,"upper":"大*街道远洋新干线","lower":"城*镇河南省濮阳市**县**镇丁**村","count":1532,"preSum":38300},{"ndv":1458,"upper":"太原经济技术开发区唐槐**园区汾东大**号太**院菜鸟驿站","lower":"大*街道通**道**号海聚**广场大丰海聚**城**栋****室","count":1532,"preSum":39832},{"ndv":1502,"upper":"安徽省.宣城市.宣州区.西林街道金碧花园4栋","lower":"太原经济技术开发区坤泽翰林华**号楼","count":1532,"preSum":41364},{"ndv":1488,"upper":"小*街道红联**路海**村*-***","lower":"安徽省.宣城市.宣州区.鳌峰街道宛溪新村9栋401室","count":1532,"preSum":42896},{"ndv":1469,"upper":"岜盆乡弄洞村姑辽屯","lower":"小*街道红联振**路***号","count":1532,"preSum":44428},{"ndv":1508,"upper":"广东东莞市东坑镇东兴中路125号锦绣豪园11栋906","lower":"岣*乡**村神皇山金杯水电","count":1532,"preSum":45960},{"ndv":1522,"upper":"广东省.广州市.荔湾区.桥中街道悦江上品-B2栋804","lower":"广东东莞市东坑镇东坑镇东兴路碧桂园豪庭2期22栋","count":1532,"preSum":47492},{"ndv":1463,"upper":"库木德尔**街道新疆喀什克孜**路***号喀什地区水利**楼","lower":"广东省.广州市.荔湾区.白鹤洞街道珠江金茂府3栋二单元2206房(送货上门)","count":1532,"preSum":49024},{"ndv":1513,"upper":"徐霞客镇璜溪绿洲**号","lower":"库木德尔**街道解**路***号明**城","count":1532,"preSum":50556},{"ndv":1503,"upper":"新**街道太和电子**楼*区**号","lower":"得*乡云南省宣威市**乡**中学","count":1532,"preSum":52088},{"ndv":1489,"upper":"新*镇龙**路**号*城大**院导诊台","lower":"新**街道富华新天**单元****室","count":1532,"preSum":53620},{"ndv":1484,"upper":"曹*镇**路***弄*-****","lower":"新*镇,**村,新世界**广场,玩具专柜","count":1532,"preSum":55152},{"ndv":1502,"upper":"林口彝族**乡丫口上","lower":"曹*镇**路***弄佳伟景苑**号楼***","count":1532,"preSum":56684},{"ndv":1500,"upper":"梧*街道**街祝**城三**号**号**单元**层***号","lower":"林口镇林*县农业技术推广中**楼窗台","count":1532,"preSum":58216},{"ndv":1504,"upper":"永*县**园区**镇桥南天立**园北区","lower":"梧*街道**路*****单元。","count":1532,"preSum":59748},{"ndv":1492,"upper":"江苏淮安市清江浦区和平镇江苏省淮安市清江浦区6路前齐","lower":"永*街**园东**城凤仪**街**座***","count":1532,"preSum":61280},{"ndv":1474,"upper":"沙*街道**路**号成都市九天家私**公司","lower":"江苏淮安市清河区徐杨乡清荷家苑3区6幢2单元503","count":1532,"preSum":62812},{"ndv":1461,"upper":"河北省石家庄市鹿泉区石获北路30号中兴物流园1号库3层东跨","lower":"沙*街道**路**号新南**楼","count":1533,"preSum":64344},{"ndv":1454,"upper":"泾*镇世**园***单元****","lower":"河北省秦皇岛市昌黎县广缘超市自然堂专柜","count":1532,"preSum":65877},{"ndv":1503,"upper":"浙江金华市义乌市福田街道宗宅b区31栋阳光幼儿园","lower":"泾*镇大**路体委对面彬彬批**楼上","count":1532,"preSum":67409},{"ndv":1494,"upper":"渭**街道甘肃省兰**城关区**大学兰大二分部**院**号楼","lower":"浙江金华市义乌市稠江街道大路金10幢2单元足康","count":1532,"preSum":68941},{"ndv":1499,"upper":"湖南省.长沙市.长沙县.湘龙街道湖南省长沙市长沙县湘龙街道恒广国际景园一区物业办公用房","lower":"渭**街道甘肃省兰**城关区**大学医学校区","count":1532,"preSum":70473},{"ndv":1489,"upper":"烔*镇康盛**厂","lower":"湖南省.长沙市.长沙县.黄兴镇大众村,龙峰安置区","count":1532,"preSum":72005},{"ndv":1487,"upper":"瑶*镇南关**楼巷","lower":"烟*街**园南区**栋***","count":1532,"preSum":73537},{"ndv":1490,"upper":"盐*街道好*对面***—*—**—*","lower":"瑶沟乡工业园区666号万鑫电子厂请放前台谢谢","count":1532,"preSum":75069},{"ndv":1493,"upper":"福**街道庄**路新**园*塔**楼","lower":"盐*街道新区管委会**路与**路交叉口广汽三菱售后","count":1532,"preSum":76601},{"ndv":1483,"upper":"筼*街道**路***号****室**大厦","lower":"福**街道开发区舟山**号大平工程**院**楼","count":1532,"preSum":78133},{"ndv":1498,"upper":"肥*镇河北省邯郸**乡区前**村","lower":"筼*街道**路***号****室门口鞋柜","count":1532,"preSum":79665},{"ndv":1502,"upper":"荔*街道华商**号广州华**院","lower":"育**街道**街****单元**号","count":1532,"preSum":81197},{"ndv":1510,"upper":"裴*乡穰**路翰林公馆","lower":"荔*街道华商**号广州华**院菜鸟驿站","count":1532,"preSum":82729},{"ndv":1497,"upper":"解*街道**路荆沙**城","lower":"裴*乡翰林公馆","count":1532,"preSum":84261},{"ndv":1497,"upper":"辽宁省.大连市.瓦房店市.文兰街道香悦山10号楼1单元901","lower":"解*街道**路金沙阳**栋****","count":1532,"preSum":85793},{"ndv":1454,"upper":"重庆市.重庆市.涪陵区.李渡街道重庆市涪陵区马鞍盛世华府2栋","lower":"辽宁省.大连市.瓦房店市.新华街道瓦房店新华办事处德林衔一段3号6单元彩票站","count":1532,"preSum":87325},{"ndv":1489,"upper":"银*街道银**街**号中油集团测井**公司大**公司解释**中心","lower":"重庆市.重庆市.涪陵区.李渡街道长江师范学院聚仕兰庭小区","count":1532,"preSum":88857},{"ndv":1504,"upper":"陈**街道重庆市沙坪坝陈**街*大学**路**号重庆商务职**院","lower":"银*街道银浪温**园*****单元***室","count":1532,"preSum":90389},{"ndv":1483,"upper":"青*镇福州泰全电机**公司","lower":"陈**街道重庆警**院家属区","count":1532,"preSum":91921},{"ndv":1491,"upper":"高*镇衢**道***号蓬莱阳**幢***","lower":"青*镇翡丽**栋北门好生活超市","count":1532,"preSum":93453},{"ndv":1486,"upper":"黑龙江省.哈尔滨市.南岗区.哈西街道哈西大街928号巴黎第五区14-1-1004","lower":"高*镇观音溪","count":1532,"preSum":94985},{"ndv":1433,"upper":"龟山小区一号楼401","lower":"黑龙江省.哈尔滨市.南岗区.曲线街道77号2号楼3单元502室","count":1477,"preSum":96517}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[78,54,46,27,43,116,46,27,31,83,26,45,26],"valueArr":["","上海市上海市奉贤区奉柘公路3289号","上海市上海市奉贤区岚丰路900号","四川省成都市龙泉驿区成都市龙泉驿区车城大道999号宝湾物流园9号仓库","四海大道1666号义乌公路港2期26栋","四海大道盛辉物流园区分拨中心二楼2-6号","天津市天津市津南区天津市津南区小站镇小站工业区11号路安博物流园1号库C分区","广东省佛山市三水区佛山市三水区乐平镇创新大道西10号-6号仓库","广东省清远市清城区广东省清远市清城区广东锦邦冷链物流园二楼7号库","浙江省嘉兴市海盐县澉浦镇长墙山工业园(澉浦工业园)纬二路天玺物流园2号","湖北省武汉市洪山区武汉市江夏济开发区庙山大道旁普洛斯江夏物流园一期B5","湖北省武汉市蔡甸区武汉市蔡甸区星光大道77号","陕西省咸阳市秦都区陕西省咸阳市秦都区天马大道万纬西安万中轻物流园A-4库屈臣氏仓库"],"type":"String","sampleRate":0.9618625319816094}',1359,0.02436278),('jala_wms_prod','shipment_header','shiptoaddress2',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[31],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99970,0.02436278),('jala_wms_prod','shipment_header','shiptoaddresslat',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','shiptoaddresslng',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','shiptoattentionto',287722,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1028,"upper":"#1gt9unDb#zS14vbwqOCYgGlUON1FyOB8WILR6kLB2DEZU84eIJRI8ErLPJB5ll7O6vVrH1/Qsu0PFtdAFklfJHrmN9DqzSMU0cM5/jmN22BQdTuZd1qE=*CgkIARCtH","lower":"","count":1103,"preSum":0},{"ndv":1102,"upper":"#5mhVoH85#Ce3j9hEdD29n4gY1dF3NwojJTPqFjfC2OkZJnhiU/lB8vW3rNKg+ZygBeyWnXvXiwO0BW/QSFC+8vRj+G9GJV1QqJKRs1aZN66EIrFym0yY=*CgkIARCtH","lower":"#1GvwFpft#dBN7EinkZsurkdz0SwEqwF6jFLM3vo4HQ7cHqwhS5SpnmJjIJHEBl3hKTr935vTr7TmM9ZtdQGhITdyDWML6FZWXEWe2usDhDuQwIA1gUYI=*CgkIARCtH","count":1103,"preSum":1103},{"ndv":1100,"upper":"#9xN/Z06F#Cv3i3FC5hiceaxKw/U2SF/QGqUQI44NR/AneQRC8+pPMv2ZBoASlcyIuLzKuIUBWV+5q7L737VLn0GuGdSkNDFQgLY9/Dw6Ki4/pMQY56mQ=*CgkIARCtH","lower":"#5mhVoH85#eNml8gwO47osupKz8gxNPCdc4ZW6vsa1Fm0K9jv9OxvyDl2wTOn2Z32KsKZoAXOvAOmQULIPiRKxvxFFLF3G30LgqHzj32whyjH3uFRbCE0=*CgkIARCtH","count":1103,"preSum":2206},{"ndv":1103,"upper":"#buxT#gJZIxTL0KxuYIos8DzBhj/eFoOzy9bOwPmMjjX8XlwyU2iQ/jaM85hZAv7RokZ4wMHpl3sNgcSpimMSbMXMCkhCREYEflYpXImSaLCQ=*CgkIARCtHCABKAESP","lower":"#9XYX#aAnmAoqc2hr3UApaVMEdBFu2YlmIYn9DiDYsqmLzrqJdA/v1PH1pwtK75LX03ODT5JLdd/cgjREfEwyfCKXt4V0tGEGl43fxhtEpVAU=*CgkIARCtHCABKAESP","count":1103,"preSum":3309},{"ndv":1103,"upper":"#E2Wv#3b9h55W/heu6QnmxiGFm273gKPCb7IEFTSLOQ+akFSIMjzinE2zoEaoyAfvTNuY8CiLE4uqrbQuuDnJERUivNXAqK0TGJYh53cLzZcI=*CgkIARCtHCABKAESP","lower":"#BV22CQou#Lybp7Bp2vKeYK7xXhmtwk+CG6VuGu58354W6lERyfOU7132vax7xnyLEoL36A59DzAtYBaXsVdNEndF9Go+9tXxql64EC3eDsqXG3yB98R8=*CgkIARCtH","count":1103,"preSum":4412},{"ndv":1103,"upper":"#G4Va#O/XRg2Gk/9PWtQjl2hM5KTsGeKzPzI61JJuqYPrP2obpCA6FI4QdJmNcojOjAM2+Cpr3SrKFT5bPxaz5T5jWq0Ojcu35XpVqhtnbXwk=*CgkIARCtHCABKAESP","lower":"#e3pj#pIa7/I5zjli3icCjraaFiHDDysrm2DLgft2fg8Uljwwpga12vXR8LBTvFXvthwYysaTSKOkvPCwVSQX3Sr1JxWToHgf70hHrv8HwXjA=*CgkIARCtHCABKAESP","count":1103,"preSum":5515},{"ndv":1103,"upper":"#hYzKGkmIGkmI#Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Njc5NDAxMjM5MjU4MzY3MDISIKEOSpmDHDsGLLNw8mlBfMaq+uqAV5oXc3tzl6rj+Fn0GhI8lD","lower":"#G4Va#pUAGIbbXhJ1yM/fLVfMnN1dE3Xe03CNYc9TXdTagL1ayw15Ax60Ox1WhVQ2PDruOHYADj1PDgWQXgnVU3EjObLJsxs5aZaTRlNtdjLA=*CgkIARCtHCABKAESP","count":1103,"preSum":6618},{"ndv":1103,"upper":"#KAZ1QEcz#xdDMe9YtetmZd5KDft7OGd7Bm++slhDBik7/Jcz+bPwZieqPJmd5VrARExX1Z53gKboiDgqO2E16ZEZAWaTt7uaqddkPHGk5uNW560u5X5E=*CgkIARCtH","lower":"#hYzKhYzKhYzK#Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Njc5NDAxMjM5MjU4MzY3MDISIIO4k86Nd3zIGnrNid34l/AlfdlaHzl8z4k+E6sr7VihGhLSym","count":1103,"preSum":7721},{"ndv":1103,"upper":"#mF4Y/YT+d3Pk#Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Njc5NDAxMjM5MjU4MzY3MDISIHkTUdnueJa1JCmpmhFLeQwhLArCsF9RQbAD559XIOEUGhK2Jp","lower":"#KAZ1tHNK#dgMIJ+4tuQO7V/bGxRaD1l4rfVAIAkPmSCRVyRuILvfhUr6b68NV+boDiEMd3kDLhl7TQvBGIBNRiCNmHvpZLNE0YJjyKP0qu9wtWR6IfdQ=*CgkIARCtH","count":1103,"preSum":8824},{"ndv":1103,"upper":"#obS7#7dEJmwM8BRZW8eWXQ+6UvKs3A7iqQv3pqKxUJFhx+rw1Orzv4jtgajiZluMf7V3eJ2MEZD8WJvY7zDDYfcnhPG/2IwH2JOPV1qN3Jsc=*CgkIARCtHCABKAESP","lower":"#mF4Y/YT+d3Pk#Ci1tZXJjaGFudC5vcGVuLnNlY3JldC5rZXkua3M2Njc5NDAxMjM5MjU4MzY3MDISIP53m289plc0KlUYu1f+tx0e6AF9zyPMa4Kscaj396sXGhLSym","count":1103,"preSum":9927},{"ndv":1102,"upper":"#qEd9#z6Qfa6lCNLWM4Keac7164h2mwIpjgOuRQYgocz7RsycrStpFjhZNLHUjJS7SgS0+4Az7EpY4xN/IsKzS15y/esT7chLIvl4rGMfkLIg=*CgkIARCtHCABKAESP","lower":"#obU1j279#qxRs3gdYuzkkZrkw5MumRA4wnDQhaZU6xcsOwShuzBPHUAELwbHp/TtwpeC7BH4Jq3euaK2xkYPkZup04SKEawZ2kc2QRqp3Fdy/hJVuFQ8=*CgkIARCtH","count":1103,"preSum":11030},{"ndv":1102,"upper":"#SN2HolXU#oFXB+rVImOfu1Zm+AqYLdVn7VsN8A0ZKgywXdz/Qdu/xC0pEkhD28KOSve0TXTbeY6h2+5wtIwv4AVFwAQrYAxj/IRARnAmLJZQMxrPsbuo=*CgkIARCtH","lower":"#QeN4MAh2#BWqtuRo8uEMMXrqiGtyjIsJq0CmjA/e5iX99RL3//bMf8Y4MxY8CxQb79HeNLleJF8cGHrWonrRMPPZyTzcTkSuOUJ2O+Ydrc7EsKxzj/pc=*CgkIARCtH","count":1103,"preSum":12133},{"ndv":1103,"upper":"#uR3YUmpw#Bc5gR3Ni6O9PHsVXPx3THKYuPJXbrytA+yaNNJZMV/W/emp6imA/fByoyuYQt0rl9nAWheLBcrq8FnpCFaya0D9SrJchJg7pb6XOm+WGYFM=*CgkIARCtH","lower":"#sn8b#LyPBJMQZ/vr5zoInNKOUhK9LfiuapF6W0RcW0cD/c2g7CVX25vzM1HXCfmaPCj44nt9JEDruRWaK8ufS83lGLZ0fHxuAcYjC/KWABIk=*CgkIARCtHCABKAESP","count":1103,"preSum":13236},{"ndv":1103,"upper":"#wwTjMbFe#U0sJZ8Y1RKz8iEn5b/OHTjYXU2k+EMDEBF6+2ykw/N6hv0Ly/ScApiFCoc/KZEgIvpZWTfnjSqXePUHKIpzRYT0XQSmGpP8d14AggI3VrQk=*CgkIARCtH","lower":"#uR3YzVlI#zgS4gYuvz+V3hzE772vFYABYDHXtWeMu2fsRILCuU/K1kbRo7HN9Ym61UAwwCVQDuTIdROHgeAOHyS+MxUQQEKTut5I3hyyyhleMDPm67zI=*CgkIARCtH","count":1103,"preSum":14339},{"ndv":1103,"upper":"#Z9UTgHt7#meIADWicL6DX+wfQujINSWvCWYaJk95EvTuFcQMxeM+LMqo1t+7BTy/hf6CYrApYIMyFzrd6OYsI4cbuf95V80xF/v/GjjDQu/dmNla7cCA=*CgkIARCtH","lower":"#wWwi#LRtwzjg0/ds6ciy86mjQsq02pQOk8DWKc+TppsKFr9ygdELwp+cjLMu7YBHTO8mZcjtEw1HVgmofK/xanjf7YaAwq+wjU20UP18Rr8s=*CgkIARCtHCABKAESP","count":1103,"preSum":15442},{"ndv":473,"upper":"T**","lower":"#ZA6z#HaYcADtZ4mYEDZiiqSt30w2UBGdvishY9Hq5JTx10Gh/DrheVfjM63mLC1YZcCK8pC7I27w/pgR3i3xKcjwViHzFrwma6/BQqt+pT/w=*CgkIARCtHCABKAESP","count":1122,"preSum":16545},{"ndv":853,"upper":"丁**","lower":"tang","count":1337,"preSum":17667},{"ndv":216,"upper":"于**","lower":"丁一","count":1154,"preSum":19004},{"ndv":245,"upper":"何**","lower":"于**********","count":1635,"preSum":20158},{"ndv":276,"upper":"克**","lower":"何七夕","count":1104,"preSum":21793},{"ndv":189,"upper":"刘*","lower":"兔*","count":1183,"preSum":22897},{"ndv":546,"upper":"卡**","lower":"刘东","count":1103,"preSum":24080},{"ndv":174,"upper":"司**","lower":"卡卡","count":1125,"preSum":25183},{"ndv":491,"upper":"和*","lower":"司团庄","count":1104,"preSum":26308},{"ndv":246,"upper":"夏*","lower":"和**","count":1108,"preSum":27412},{"ndv":170,"upper":"姜*","lower":"夏**","count":1106,"preSum":28520},{"ndv":96,"upper":"孙**","lower":"姜**","count":1363,"preSum":29626},{"ndv":221,"upper":"宋会英","lower":"孙丁蓉","count":1103,"preSum":30989},{"ndv":394,"upper":"岳**","lower":"宋伟","count":1135,"preSum":32092},{"ndv":218,"upper":"廖**","lower":"岳凤英","count":1208,"preSum":33227},{"ndv":597,"upper":"彭*","lower":"廖东婷","count":1115,"preSum":34435},{"ndv":328,"upper":"戴**","lower":"彭**","count":1134,"preSum":35550},{"ndv":238,"upper":"易**","lower":"戴初","count":1162,"preSum":36684},{"ndv":160,"upper":"曾**","lower":"易丽","count":1177,"preSum":37846},{"ndv":503,"upper":"李春雨","lower":"曾s","count":1103,"preSum":39023},{"ndv":538,"upper":"杨牢巴","lower":"李春香","count":1144,"preSum":40126},{"ndv":346,"upper":"梁**","lower":"杨玉华","count":1341,"preSum":41270},{"ndv":276,"upper":"殷**","lower":"梁丽丽","count":1140,"preSum":42611},{"ndv":195,"upper":"沈**","lower":"殷丽平","count":1301,"preSum":43751},{"ndv":223,"upper":"潘**","lower":"沈丽","count":1260,"preSum":45052},{"ndv":305,"upper":"王原红","lower":"潘丽君","count":1103,"preSum":46312},{"ndv":557,"upper":"瓜**","lower":"王厦兰","count":1107,"preSum":47415},{"ndv":196,"upper":"石**","lower":"瓜瓜","count":1241,"preSum":48522},{"ndv":261,"upper":"笑**","lower":"石亚平","count":1115,"preSum":49763},{"ndv":154,"upper":"罗**","lower":"笑***","count":1178,"preSum":50878},{"ndv":250,"upper":"胡**","lower":"罗***","count":1807,"preSum":52056},{"ndv":312,"upper":"范**","lower":"胡丹","count":1275,"preSum":53863},{"ndv":203,"upper":"蒋**","lower":"范丽","count":1236,"preSum":55138},{"ndv":209,"upper":"袁**","lower":"蒋万秀","count":1126,"preSum":56374},{"ndv":228,"upper":"谢**","lower":"袁***","count":1425,"preSum":57500},{"ndv":299,"upper":"赵士敏","lower":"谢三坤","count":1103,"preSum":58925},{"ndv":333,"upper":"邱**","lower":"赵声勇","count":1223,"preSum":60028},{"ndv":141,"upper":"郑志军","lower":"邱丹","count":1103,"preSum":61251},{"ndv":211,"upper":"金**","lower":"郑恒","count":1271,"preSum":62354},{"ndv":216,"upper":"阿**","lower":"金一百","count":1135,"preSum":63625},{"ndv":477,"upper":"隆**","lower":"阿****","count":1105,"preSum":64760},{"ndv":173,"upper":"韩国栋","lower":"隆晓燕","count":1103,"preSum":65865},{"ndv":133,"upper":"马**","lower":"韩培爱","count":1174,"preSum":66968},{"ndv":225,"upper":"魏**","lower":"马***","count":1119,"preSum":68142},{"ndv":357,"upper":"龙仙桃","lower":"魏丹丹","count":1103,"preSum":69261},{"ndv":65,"upper":"~**","lower":"龙会兰","count":179,"preSum":70364}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2769,1192,1138,1858,3803,858,758,3934,1802,764,4012,1001,2799,1411],"valueArr":["刘**","吴**","周**","小**","张**","徐**","朱**","李**","杨**","林**","王**","赵**","陈**","黄**"],"type":"String","sampleRate":0.9618625319816094}',1359,0.02436278),('jala_wms_prod','shipment_header','shiptocaid',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','shiptocity',1429,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":20,"upper":"中山市","lower":"","count":1638,"preSum":0},{"ndv":15,"upper":"丽江市","lower":"丰台","count":1147,"preSum":1638},{"ndv":19,"upper":"亳州市","lower":"乌兰察布","count":1278,"preSum":2785},{"ndv":13,"upper":"信阳市","lower":"仙桃市","count":1301,"preSum":4063},{"ndv":12,"upper":"内江市","lower":"儋州市","count":1160,"preSum":5364},{"ndv":13,"upper":"南京市","lower":"凉山","count":1729,"preSum":6524},{"ndv":7,"upper":"南平市","lower":"南充","count":1179,"preSum":8253},{"ndv":5,"upper":"南通市","lower":"南开区","count":1236,"preSum":9432},{"ndv":6,"upper":"县","lower":"南阳市","count":1118,"preSum":10668},{"ndv":14,"upper":"吕梁市","lower":"双河市","count":1157,"preSum":11786},{"ndv":12,"upper":"咸宁市","lower":"吴忠","count":1185,"preSum":12943},{"ndv":6,"upper":"唐山市","lower":"咸阳市","count":1291,"preSum":14128},{"ndv":7,"upper":"嘉兴市","lower":"商丘","count":1190,"preSum":15419},{"ndv":19,"upper":"大连市","lower":"嘉定区","count":1272,"preSum":16609},{"ndv":3,"upper":"天津市","lower":"天水市","count":1169,"preSum":17881},{"ndv":11,"upper":"孝感市","lower":"天门市","count":1181,"preSum":19050},{"ndv":4,"upper":"宁波市","lower":"宁德市","count":1293,"preSum":20231},{"ndv":12,"upper":"宜昌市","lower":"安庆","count":1375,"preSum":21524},{"ndv":10,"upper":"宿迁市","lower":"宜春市","count":1336,"preSum":22899},{"ndv":18,"upper":"常州市","lower":"密云区","count":1316,"preSum":24235},{"ndv":17,"upper":"廊坊市","lower":"常德","count":1363,"preSum":25551},{"ndv":15,"upper":"徐州市","lower":"延安","count":1362,"preSum":26914},{"ndv":18,"upper":"惠州市","lower":"徐汇","count":1762,"preSum":28276},{"ndv":13,"upper":"揭阳市","lower":"成都","count":1304,"preSum":30038},{"ndv":9,"upper":"无锡市","lower":"攀枝花市","count":1333,"preSum":31342},{"ndv":6,"upper":"昆明市","lower":"日喀则地区","count":1187,"preSum":32675},{"ndv":21,"upper":"朔州市","lower":"昌吉回族自治州","count":1148,"preSum":33862},{"ndv":19,"upper":"桂林市","lower":"朝阳区","count":1357,"preSum":35010},{"ndv":15,"upper":"汉中市","lower":"梅州市","count":1202,"preSum":36367},{"ndv":7,"upper":"沈阳市","lower":"汕头市","count":1827,"preSum":37569},{"ndv":13,"upper":"泉州市","lower":"沙坪坝","count":1334,"preSum":39396},{"ndv":10,"upper":"济南市","lower":"泰安市","count":1848,"preSum":40730},{"ndv":18,"upper":"淮北市","lower":"济宁市","count":1243,"preSum":42578},{"ndv":12,"upper":"温州市","lower":"淮南","count":1626,"preSum":43821},{"ndv":12,"upper":"滁州市","lower":"渭南","count":1350,"preSum":45447},{"ndv":12,"upper":"潮州市","lower":"滨州","count":1236,"preSum":46797},{"ndv":13,"upper":"玉溪市","lower":"澄迈县","count":1170,"preSum":48033},{"ndv":19,"upper":"盐城市","lower":"珠海","count":1357,"preSum":49203},{"ndv":15,"upper":"福州市","lower":"盘锦市","count":2021,"preSum":50560},{"ndv":12,"upper":"绵阳市","lower":"秀山县","count":1158,"preSum":52581},{"ndv":13,"upper":"茂名市","lower":"聊城","count":1318,"preSum":53739},{"ndv":9,"upper":"萍乡市","lower":"荆州","count":1190,"preSum":55057},{"ndv":13,"upper":"襄阳市","lower":"营口市","count":1421,"preSum":56247},{"ndv":14,"upper":"贵阳市","lower":"西双版纳","count":1143,"preSum":57668},{"ndv":12,"upper":"运城市","lower":"贺州市","count":1282,"preSum":58811},{"ndv":10,"upper":"邢台市","lower":"连云港市","count":1320,"preSum":60093},{"ndv":14,"upper":"金华市","lower":"那曲市","count":2082,"preSum":61413},{"ndv":20,"upper":"镇江市","lower":"金山","count":1250,"preSum":63495},{"ndv":6,"upper":"长沙市","lower":"长宁区","count":1793,"preSum":64745},{"ndv":19,"upper":"阿拉善盟","lower":"长治","count":1122,"preSum":66538},{"ndv":12,"upper":"青岛市","lower":"阿拉尔市","count":1178,"preSum":67660},{"ndv":15,"upper":"鹰潭市","lower":"青浦","count":1209,"preSum":68838},{"ndv":18,"upper":"黔西南布依族苗族自治州","lower":"黄冈","count":1174,"preSum":70047},{"ndv":3,"upper":"龙岩市","lower":"齐齐哈尔","count":300,"preSum":71221}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[3126,1919,1183,2332,1273,2693,2136,1729,1660,2936,1767,1219,1487,1667],"valueArr":["上海市","东莞市","佛山市","北京市","合肥市","广州市","成都市","杭州市","武汉市","深圳市","苏州市","西安市","郑州市","重庆市"],"type":"String","sampleRate":0.9618625319816094}',1353,0.02436278),('jala_wms_prod','shipment_header','shiptocitycode',390,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":4,"upper":"130100","lower":"","count":1603,"preSum":0},{"ndv":4,"upper":"130500","lower":"130200","count":1076,"preSum":1603},{"ndv":4,"upper":"130900","lower":"130600","count":1140,"preSum":2679},{"ndv":4,"upper":"140200","lower":"131000","count":1107,"preSum":3819},{"ndv":9,"upper":"141100","lower":"140300","count":1015,"preSum":4926},{"ndv":7,"upper":"150700","lower":"150100","count":1063,"preSum":5941},{"ndv":6,"upper":"210100","lower":"150800","count":1025,"preSum":7004},{"ndv":7,"upper":"210800","lower":"210200","count":1050,"preSum":8029},{"ndv":7,"upper":"220100","lower":"210900","count":1105,"preSum":9079},{"ndv":9,"upper":"230100","lower":"220200","count":1221,"preSum":10184},{"ndv":13,"upper":"310000","lower":"230200","count":1630,"preSum":11405},{"ndv":2,"upper":"320300","lower":"320200","count":1252,"preSum":13035},{"ndv":2,"upper":"320600","lower":"320400","count":1008,"preSum":14287},{"ndv":3,"upper":"320900","lower":"320700","count":1021,"preSum":15295},{"ndv":4,"upper":"321300","lower":"321000","count":1208,"preSum":16316},{"ndv":2,"upper":"330400","lower":"330300","count":1477,"preSum":17524},{"ndv":3,"upper":"330700","lower":"330500","count":1672,"preSum":19001},{"ndv":4,"upper":"331100","lower":"330800","count":987,"preSum":20673},{"ndv":5,"upper":"340600","lower":"340200","count":1100,"preSum":21660},{"ndv":5,"upper":"341200","lower":"340700","count":1256,"preSum":22760},{"ndv":5,"upper":"341800","lower":"341300","count":1165,"preSum":24016},{"ndv":2,"upper":"350200","lower":"350100","count":1524,"preSum":25181},{"ndv":3,"upper":"350500","lower":"350300","count":1124,"preSum":26705},{"ndv":5,"upper":"360100","lower":"350600","count":1392,"preSum":27829},{"ndv":6,"upper":"360700","lower":"360200","count":1090,"preSum":29221},{"ndv":4,"upper":"361100","lower":"360800","count":1003,"preSum":30311},{"ndv":2,"upper":"370200","lower":"370100","count":1472,"preSum":31314},{"ndv":5,"upper":"370700","lower":"370300","count":1177,"preSum":32786},{"ndv":5,"upper":"371300","lower":"370800","count":1243,"preSum":33963},{"ndv":5,"upper":"410200","lower":"371400","count":996,"preSum":35206},{"ndv":5,"upper":"410700","lower":"410300","count":1124,"preSum":36202},{"ndv":6,"upper":"411300","lower":"410800","count":1155,"preSum":37326},{"ndv":3,"upper":"411600","lower":"411400","count":1033,"preSum":38481},{"ndv":5,"upper":"420500","lower":"411700","count":983,"preSum":39514},{"ndv":5,"upper":"421000","lower":"420600","count":1029,"preSum":40497},{"ndv":9,"upper":"430200","lower":"421100","count":1068,"preSum":41526},{"ndv":5,"upper":"430700","lower":"430300","count":1101,"preSum":42594},{"ndv":7,"upper":"433100","lower":"430800","count":1043,"preSum":43695},{"ndv":4,"upper":"440700","lower":"440200","count":1098,"preSum":44738},{"ndv":4,"upper":"441300","lower":"440800","count":1296,"preSum":45836},{"ndv":6,"upper":"441900","lower":"441400","count":1546,"preSum":47132},{"ndv":5,"upper":"450100","lower":"442000","count":1455,"preSum":48678},{"ndv":7,"upper":"450800","lower":"450200","count":1015,"preSum":50133},{"ndv":8,"upper":"460200","lower":"450900","count":994,"preSum":51148},{"ndv":19,"upper":"510500","lower":"460400","count":1033,"preSum":52142},{"ndv":7,"upper":"511300","lower":"510600","count":1159,"preSum":53175},{"ndv":10,"upper":"513400","lower":"511400","count":1019,"preSum":54334},{"ndv":4,"upper":"520400","lower":"520100","count":983,"preSum":55353},{"ndv":7,"upper":"530400","lower":"520500","count":1007,"preSum":56336},{"ndv":9,"upper":"532800","lower":"530500","count":978,"preSum":57343},{"ndv":16,"upper":"610600","lower":"532900","count":1055,"preSum":58321},{"ndv":9,"upper":"620500","lower":"610700","count":1059,"preSum":59376},{"ndv":18,"upper":"640100","lower":"620600","count":1070,"preSum":60435},{"ndv":20,"upper":"659002","lower":"640200","count":984,"preSum":61505},{"ndv":6,"upper":"659010","lower":"659003","count":18,"preSum":62489}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1077,1583,1395,986,1201,1340,1526,1078,2499,2655,1082,1965,938,1123],"valueArr":["320100","320500","330100","330200","340100","410100","420100","430100","440100","440300","440600","510100","530100","610100"],"type":"String","sampleRate":0.9618625319816094}',17046,0.02436278),('jala_wms_prod','shipment_header','shiptocountry',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[97400,13],"valueArr":["","中国"],"type":"String","sampleRate":0.9618625319816094}',2588,0.02436278),('jala_wms_prod','shipment_header','shiptocountrycode',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[9,82947],"valueArr":["","0"],"type":"String","sampleRate":0.9618625319816094}',17045,0.02436278),('jala_wms_prod','shipment_header','shiptodistrict',6813,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":70,"upper":"丛台区","lower":"","count":1419,"preSum":0},{"ndv":54,"upper":"东西湖区","lower":"东丰县","count":1525,"preSum":1419},{"ndv":50,"upper":"临川区","lower":"东辽县","count":1451,"preSum":2944},{"ndv":71,"upper":"九龙坡区","lower":"临平区","count":1499,"preSum":4395},{"ndv":67,"upper":"仁寿县","lower":"九龙街道","count":1405,"preSum":5894},{"ndv":43,"upper":"佛冈县","lower":"仁怀市","count":1416,"preSum":7299},{"ndv":67,"upper":"兴化市","lower":"佛坪县","count":1454,"preSum":8715},{"ndv":79,"upper":"包河区","lower":"兴县","count":1450,"preSum":10169},{"ndv":76,"upper":"南山区","lower":"化州市","count":1415,"preSum":11619},{"ndv":54,"upper":"博罗县","lower":"南岔区","count":1418,"preSum":13034},{"ndv":50,"upper":"古冶区","lower":"博野县","count":1405,"preSum":14452},{"ndv":64,"upper":"吴兴区","lower":"古县","count":1417,"preSum":15857},{"ndv":63,"upper":"嘉陵区","lower":"吴堡县","count":1412,"preSum":17274},{"ndv":50,"upper":"城阳区","lower":"嘉鱼县","count":1453,"preSum":18686},{"ndv":75,"upper":"大邑县","lower":"堆龙德庆区","count":1419,"preSum":20139},{"ndv":50,"upper":"奎文区","lower":"大鹏新区","count":1447,"preSum":21558},{"ndv":64,"upper":"安宁市","lower":"如东县","count":1405,"preSum":23005},{"ndv":57,"upper":"宝山区","lower":"安定","count":1633,"preSum":24410},{"ndv":60,"upper":"小店区","lower":"宝山路街道","count":1407,"preSum":26043},{"ndv":69,"upper":"崇阳县","lower":"小昆山镇","count":1405,"preSum":27450},{"ndv":58,"upper":"平城区","lower":"崔各庄地区","count":1451,"preSum":28855},{"ndv":66,"upper":"库尔勒市","lower":"平塘县","count":1404,"preSum":30306},{"ndv":76,"upper":"彭州市","lower":"库车县","count":1421,"preSum":31710},{"ndv":59,"upper":"惠城区","lower":"彭水苗族土家族自治县","count":1404,"preSum":33131},{"ndv":41,"upper":"拱墅区","lower":"惠安县","count":1480,"preSum":34535},{"ndv":52,"upper":"新干县","lower":"拱辰街道","count":1410,"preSum":36015},{"ndv":69,"upper":"昌平区","lower":"新平彝族傣族自治县","count":1507,"preSum":37425},{"ndv":62,"upper":"望城区","lower":"昌江区","count":1461,"preSum":38932},{"ndv":62,"upper":"枣阳市","lower":"望奎县","count":1435,"preSum":40393},{"ndv":51,"upper":"梁溪区","lower":"柏乡县","count":1444,"preSum":41828},{"ndv":58,"upper":"武昌区","lower":"梅列区","count":1485,"preSum":43272},{"ndv":63,"upper":"汉南区","lower":"武江区","count":1431,"preSum":44757},{"ndv":33,"upper":"江州区","lower":"汉台区","count":1419,"preSum":46188},{"ndv":62,"upper":"沙雅县","lower":"江干区","count":1406,"preSum":47607},{"ndv":66,"upper":"津南区","lower":"沛县","count":1443,"preSum":49013},{"ndv":49,"upper":"海拉尔区","lower":"津市市","count":1423,"preSum":50456},{"ndv":31,"upper":"涧西区","lower":"海晏县","count":1458,"preSum":51879},{"ndv":50,"upper":"温岭市","lower":"涪城区","count":1465,"preSum":53337},{"ndv":46,"upper":"滨海新区","lower":"温江区","count":1499,"preSum":54802},{"ndv":61,"upper":"点军区","lower":"滨湖区","count":1403,"preSum":56301},{"ndv":65,"upper":"璧山区","lower":"烈山区","count":1438,"preSum":57704},{"ndv":61,"upper":"相城区","lower":"璧泉街道","count":1470,"preSum":59142},{"ndv":72,"upper":"福山区","lower":"相山区","count":1423,"preSum":60612},{"ndv":48,"upper":"简阳市","lower":"福泉市","count":1441,"preSum":62035},{"ndv":68,"upper":"美兰区","lower":"管城回族区","count":1444,"preSum":63476},{"ndv":56,"upper":"芦淞区","lower":"美姑县","count":1437,"preSum":64920},{"ndv":58,"upper":"莱山区","lower":"芦溪","count":1451,"preSum":66357},{"ndv":38,"upper":"蕉城区","lower":"莱州市","count":1442,"preSum":67808},{"ndv":34,"upper":"襄州区","lower":"蕉岭县","count":1432,"preSum":69250},{"ndv":38,"upper":"西青区","lower":"襄汾县","count":1421,"preSum":70682},{"ndv":53,"upper":"越秀区","lower":"覃塘区","count":1476,"preSum":72103},{"ndv":66,"upper":"道里区","lower":"越秀路街道","count":1436,"preSum":73579},{"ndv":49,"upper":"鄞州区","lower":"遵化市","count":1411,"preSum":75015},{"ndv":47,"upper":"金牛区","lower":"鄠邑区","count":1527,"preSum":76426},{"ndv":54,"upper":"镜湖区","lower":"金盏地区","count":1444,"preSum":77953},{"ndv":45,"upper":"闻喜县","lower":"长丰县","count":1411,"preSum":79397},{"ndv":68,"upper":"雁山区","lower":"闽侯县","count":1404,"preSum":80808},{"ndv":44,"upper":"青浦区","lower":"雁峰区","count":1512,"preSum":82212},{"ndv":38,"upper":"颍上县","lower":"青田县","count":1434,"preSum":83724},{"ndv":67,"upper":"魏都区","lower":"颍东区","count":1418,"preSum":85158},{"ndv":42,"upper":"黄州区","lower":"鱼台县","count":1451,"preSum":86576},{"ndv":60,"upper":"龙港市","lower":"黄平县","count":1440,"preSum":88027},{"ndv":12,"upper":"龙马潭区","lower":"龙游县","count":279,"preSum":89467}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[498,929,494,404,888,436,620,458,705,440,636,528,668],"valueArr":["义乌市","其他区","南海区","天河区","宝安区","昆山市","朝阳区","洪山区","浦东新区","番禺区","白云区","龙华区","龙岗区"],"type":"String","sampleRate":0.9618625319816094}',2551,0.02436278),('jala_wms_prod','shipment_header','shiptodistrictcode',3471,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":35,"upper":"130105","lower":"110101","count":1188,"preSum":0},{"ndv":58,"upper":"130481","lower":"130107","count":1212,"preSum":1188},{"ndv":71,"upper":"130903","lower":"130502","count":1200,"preSum":2400},{"ndv":47,"upper":"140213","lower":"130921","count":1234,"preSum":3600},{"ndv":101,"upper":"150103","lower":"140214","count":1196,"preSum":4834},{"ndv":86,"upper":"152522","lower":"150104","count":1187,"preSum":6030},{"ndv":32,"upper":"210281","lower":"152523","count":1200,"preSum":7217},{"ndv":78,"upper":"220102","lower":"210283","count":1256,"preSum":8417},{"ndv":60,"upper":"230102","lower":"220103","count":1197,"preSum":9673},{"ndv":104,"upper":"231222","lower":"230103","count":1194,"preSum":10870},{"ndv":32,"upper":"320111","lower":"231223","count":1288,"preSum":12064},{"ndv":12,"upper":"320281","lower":"320113","count":1241,"preSum":13352},{"ndv":17,"upper":"320481","lower":"320282","count":1201,"preSum":14593},{"ndv":8,"upper":"320585","lower":"320505","count":1197,"preSum":15794},{"ndv":23,"upper":"320904","lower":"320602","count":1215,"preSum":16991},{"ndv":25,"upper":"321302","lower":"320921","count":1203,"preSum":18206},{"ndv":12,"upper":"330110","lower":"321311","count":1425,"preSum":19409},{"ndv":15,"upper":"330283","lower":"330111","count":1193,"preSum":20834},{"ndv":17,"upper":"330481","lower":"330302","count":1299,"preSum":22027},{"ndv":20,"upper":"330783","lower":"330482","count":1275,"preSum":23326},{"ndv":30,"upper":"340102","lower":"330784","count":1272,"preSum":24601},{"ndv":20,"upper":"340322","lower":"340103","count":1198,"preSum":25873},{"ndv":42,"upper":"341122","lower":"340323","count":1195,"preSum":27071},{"ndv":23,"upper":"341523","lower":"341124","count":1194,"preSum":28266},{"ndv":23,"upper":"350121","lower":"341524","count":1193,"preSum":29460},{"ndv":19,"upper":"350402","lower":"350122","count":1192,"preSum":30653},{"ndv":40,"upper":"350725","lower":"350403","count":1188,"preSum":31845},{"ndv":33,"upper":"360302","lower":"350781","count":1215,"preSum":33033},{"ndv":54,"upper":"360902","lower":"360313","count":1219,"preSum":34248},{"ndv":37,"upper":"370112","lower":"360921","count":1204,"preSum":35467},{"ndv":25,"upper":"370403","lower":"370113","count":1206,"preSum":36671},{"ndv":41,"upper":"370832","lower":"370404","count":1204,"preSum":37877},{"ndv":42,"upper":"371502","lower":"370881","count":1257,"preSum":39081},{"ndv":27,"upper":"410105","lower":"371521","count":1352,"preSum":40338},{"ndv":35,"upper":"410411","lower":"410106","count":1197,"preSum":41690},{"ndv":56,"upper":"411103","lower":"410421","count":1214,"preSum":42887},{"ndv":41,"upper":"411528","lower":"411104","count":1227,"preSum":44101},{"ndv":26,"upper":"420106","lower":"411602","count":1222,"preSum":45328},{"ndv":32,"upper":"420581","lower":"420107","count":1192,"preSum":46550},{"ndv":39,"upper":"421124","lower":"420582","count":1197,"preSum":47742},{"ndv":30,"upper":"430105","lower":"421125","count":1210,"preSum":48939},{"ndv":33,"upper":"430503","lower":"430111","count":1199,"preSum":50149},{"ndv":56,"upper":"431125","lower":"430511","count":1189,"preSum":51348},{"ndv":34,"upper":"440114","lower":"431126","count":1394,"preSum":52537},{"ndv":19,"upper":"440311","lower":"440115","count":1265,"preSum":53931},{"ndv":18,"upper":"440783","lower":"440402","count":1224,"preSum":55196},{"ndv":27,"upper":"441322","lower":"440784","count":1288,"preSum":56420},{"ndv":36,"upper":"445103","lower":"441323","count":1232,"preSum":57708},{"ndv":28,"upper":"450221","lower":"445122","count":1208,"preSum":58940},{"ndv":67,"upper":"451103","lower":"450222","count":1190,"preSum":60148},{"ndv":71,"upper":"500152","lower":"451121","count":1194,"preSum":61338},{"ndv":25,"upper":"510115","lower":"500153","count":1279,"preSum":62532},{"ndv":42,"upper":"510727","lower":"510121","count":1188,"preSum":63811},{"ndv":56,"upper":"511622","lower":"510781","count":1189,"preSum":64999},{"ndv":81,"upper":"520222","lower":"511623","count":1194,"preSum":66188},{"ndv":76,"upper":"530103","lower":"520302","count":1315,"preSum":67382},{"ndv":38,"upper":"530623","lower":"530111","count":1194,"preSum":68697},{"ndv":119,"upper":"540426","lower":"530624","count":1187,"preSum":69891},{"ndv":26,"upper":"610302","lower":"540502","count":1221,"preSum":71078},{"ndv":89,"upper":"620103","lower":"610303","count":1228,"preSum":72299},{"ndv":111,"upper":"640104","lower":"620104","count":1249,"preSum":73527},{"ndv":113,"upper":"659010","lower":"640105","count":1170,"preSum":74776}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[1173,384,482,325,429,372,550,403,792,591,412,447,319,330],"valueArr":["","320583","330782","340104","420111","440106","440111","440113","440306","440307","440309","440605","440606","510116"],"type":"String","sampleRate":0.9618625319816094}',17046,0.02436278),('jala_wms_prod','shipment_header','shiptoemailaddress',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','shiptofaxnum',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','shiptoid',694795,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":947,"upper":"10ZU50R26CUTTB5Oe4nU7Le7Fn47H84QYyQ1SSeyYy8OapCvKsGbcE2MfJC38BAw2X8pjyg","lower":"100951SwpNDU6uEf8Oa76lRtibdRic4Zibkwbkk3kotOygsbwJJBzzPShul9iaibeOzVWHYqstGU","count":955,"preSum":0},{"ndv":948,"upper":"11Zge5NwRuVNaN1DE6Xm29SpeVw6Qh6FUAiaGaHe1SCp8bUSx8OagevjU28dmXIB5Cwehjlr","lower":"10zu5gexMntx4UIK1stSHplXsbeWcAMhOibU0cHBQL6hB1XKrgDcGWcjZW4361Sq9nFP8OaY","count":955,"preSum":955},{"ndv":949,"upper":"12zWc65rg1B9lp423X1ANzl45Kdib8cSQIKDg1SBjQZ0pIZ9FwjFSbqjldhoGXKVcAUE8Oao","lower":"11ZGZ54qagYFe6rTT0LU91SdXH8MeTrxZSP1Tx9FIJ8OaN8e2e489BLSH2IvUXmzKEiaBSlr","count":955,"preSum":1910},{"ndv":952,"upper":"13yl0vf5OgvXG8cBSfNPdrV5vMu9UO5gouU4WmOtr3AsVB65BxXp1SOeST5oPxl3pws8OaN","lower":"12zWDi5aKM21eYHgePKJ6376BFdN2pBicokNZ1S4NhGibZlH4otgyZZAqq8mlicS7HrS8Oab1BB","count":955,"preSum":2865},{"ndv":950,"upper":"14xLF5x35bhsO1lhbPbBrLibMD1ScqiaUmZ4LZBfibFa85faffXdxzgZ48Jt8h6Mfu8Oaias3a7","lower":"13YMVwu5FDeLS51mIN3zOfgDdyB1SSpwGxhNaTqno8Oagszic18s0S4gSlto7Esic7TuyDRGib","count":955,"preSum":3820},{"ndv":948,"upper":"15xYZRgGt522FtjESwkoEwSe4QyVeYHRPPCo1tk1S4FLfWxGs5aZ4IgC3HJFrSnEky8OaJL","lower":"14xmadHV5wcJdb7qeap2nakzWJIjMj0lOFUk8yl8IuawFOqvPic9q1Srw18EcEHPGY8Oa5B0","count":955,"preSum":4775},{"ndv":953,"upper":"16xGdc6iaR5D7mTQmGkia1StSu1L8dxpFFCAM9GzOlbWDnxiao185fXBXSsSibaZBw8OavaF5Dj","lower":"15xzicyDB53SKwXblqaAdGhS8sEgtPjhgm6fF3ZGAhlBcBu5IiaKLSA0qOUjGGdX1SVf8OaHK","count":955,"preSum":5730},{"ndv":947,"upper":"17Wt6vQwTex5WRvgdvM23JZyS3qfD30w1okUl1Skh2icSDN8CKkwY2DpFh2aL88OaCiaibXSKw","lower":"16XGXDTVH65DofBK2VNia1SJc8FnCVZm63tTnxUz8OaN1aWFL9jibIhgeNhahm0SPzjVvUibxk","count":955,"preSum":6685},{"ndv":946,"upper":"18vXAg1GKFWn55aRqMia1BeUTkc6zLSKlvrva21SsIMEHzLIqic5Qhkf9NAYIhVX8Oa6iaDaj5","lower":"17wTFlia03y5lgb7KjjvQSy7PwrcwonkPI1SLyu1kibbibxv7jOj7QicEcE4P9aT18OazdG7PFa","count":955,"preSum":7640},{"ndv":951,"upper":"19uacLhbCm33059F3ISoicldiciaWNDibsXxb2cKC1S1dw5HMQcrvkRaTVf3Jkr8OaSYIBnkzjn","lower":"18vxPUoUsIgL5XQ3sNcFbIZ0dSaCd1LAnn4066ddtJKgNP7u49tTS4MlicP22h1Sme8Oaiaq5","count":955,"preSum":8595},{"ndv":949,"upper":"1aiaTO32NmwsVQibtNRnLB21IhyEIedDicN4VvvU51S7hnPoiaq8Oa9s6J0sDCrlWhyNGrfA7PJ","lower":"19uAZE96DSequ5e1SlEgZ1J54FtP0DRq9PlMktSIjRmGNKC9xOqydkpk9pBevL28OapE07k","count":955,"preSum":9550},{"ndv":951,"upper":"1aYbIEFssbBs99WQgDAOuh7CpCRiakPxH6Q3tw5ia1SS8OaFiadqaz3TQLYynuXmlB2K8EfLyD","lower":"1AiavI2HlesQ5Y53saQaRbza6lhAicqiaMKBaMo8i1SbCzrwTKM8OazQvWGkGQaQEe87hLMbguk","count":955,"preSum":10505},{"ndv":948,"upper":"1bibDBhY8Xh5z0ib4whs8ianzQTMERJ6HZkCZFRnP51ShTMx0mt8OavpXevialoy8tMaJP2PNdO","lower":"1aYcbbIzXDu7QWhFF2w40PkZXhnwzjgWJJaCrv5nx1SCo8OaUAhuqzxVic44hM9AFQmkUuaY","count":955,"preSum":11460},{"ndv":950,"upper":"1bXUnyfys2g1rAXzXyMvhUk1eUoWKcbHd253SU1S65og8OaL1BtjOib4XCBc3p6ICZZcPWAw","lower":"1BibIBVNnSlD40i5cvCNBLKX301om3S8ocBqNadNRa1S0uZXyC28OamoPCBq5ELh1hv8OH7FS","count":955,"preSum":12415},{"ndv":951,"upper":"1cibXajpxVNiaQib62ics8gJeuSAxt8RJ0SdaRmZY591SkmUKua8OaLQ5r7pR28QS3pk6RaicDKs","lower":"1bxv7yCvd73mPW809iciaP1mzxZXvaNpDCEVleEJF5XG7R1LnERATbaM6NwYzB1Srr8OauFbA","count":955,"preSum":13370},{"ndv":950,"upper":"1CXawv2eWExzwiai5bWibvMkZEAIgzuSzeZMVN1SrKi8OacrR8j7reutuiaXc9fGYXeWjibzJzfNj","lower":"1cibXQhvv2hPviarLeT4eoHApUaXBic8pyNG8qEjX5C1SWAWYnF8Oahmaqu8Xwk6EkDicQunBMA","count":955,"preSum":14325},{"ndv":949,"upper":"1dI7IbXGEYL56Ghw5zWe46c1SUnu0H8b2Cd3Xnlg5UicLI8OaIibf68PJTwPRSjZ4Ol76Gs5x","lower":"1cxB06iccZILYPE5zCsGtwVwIhC5IHKiaK9Gnz0m2Q31S4a40TiaXVLU6jwu7GmmHs8OaE1oHG","count":955,"preSum":15280},{"ndv":952,"upper":"1dXXtlVcscr2wTWLPRl5xvDyxqfZEXk6JcXqA51SpXbFbx8OaC1dgib0KHFO0GcXrpZdx7Yr","lower":"1DI7lvy7ica5c6Byia1SToXFy8OamMmfcFW5sbZ05TIcQgNNkTfPccEtb6mMabOwxBNylNklm","count":955,"preSum":16235},{"ndv":951,"upper":"1Eibr6S7RI6HOlSUrW5aaUcb4ibhG3Clnx75T8Ks0N1S538uO7g8Oaf1yL3PDRoMNzHG410lia","lower":"1dXYze66E5K2MN9TCU6VsD5Ya0RXYxSut7Z9N5I1S0NTlg8OaYthBGvHuPWzpvj12YXkTC4","count":955,"preSum":17190},{"ndv":952,"upper":"1EYq5LMKlFjialHMWG5rMwbCfVv1hWqhJUTKej11SWdoHZVrI42V6TtUMwS8OaZ81aZIFjVE","lower":"1EibrVDr8cG2QvsD8S56UV1OKXSpI8DvyyyZC0vs3w1STRgCclE8OaibiaED2eHpYMZvIW6PHK","count":955,"preSum":18145},{"ndv":949,"upper":"1FicVhRkzic2XDH2X4F5HuHt7qO4jTPlg7cpCz8GFj41S6SwJ7H8OaP2SfmoOfBsGZb3rtE0b","lower":"1eYrkezTjh3TlTMURG9rdjHEDaRiaKtJjCHcaX5IzGicB1SN3dEJv48UPChS8OaticyRZaKk8H","count":955,"preSum":19100},{"ndv":948,"upper":"1FyZVJ4bohzDEws4V3d5DTcWKSHjAIoJcI5PS1c21S7toWNAUa7EAtsbU47ibLZ8DcZ8OaFk","lower":"1FicVSxoicibib8ewZe5WGuZLgzYPcF1QC2KeZibzlG1SkuxxIQ8OaQyszl5qNeDyQJF1icDIqmjO","count":955,"preSum":20055},{"ndv":949,"upper":"1gj9WzKiaZy995aMTRoq3IhiczPKsuVeynAoCFMIDeIGk2r1SEpP8OaCJKCMDEqryS89iaOYp7","lower":"1fZ057YqPibH4dTLDcGo7fVXHnK38GuicgdG6LSc1SHtwiaV8OayiauIFlFWBfXsbPvkDu5LbXd","count":955,"preSum":21010},{"ndv":949,"upper":"1gYXsE6pOjNxBicmSEbd3rUPMpC1Ae5CwbAxc5Y1SR1LyyHnX8OaaMWRRb3YNCblvjVWwfIp","lower":"1Gj9zbg77icQ05fJzpPF91SwHD4epNsWPuXKmNT7Lnoz5HQWvRRk8Oa01SIhyibKsLCqHYBn1","count":955,"preSum":21965},{"ndv":951,"upper":"1hISd8n7dh56kibC1Vnw8F5WB3xSDTGoo1SAGxFgnVoxibx07A8OaN16PiaBia5ZJLdEnOA7ejq","lower":"1GYxZpK5eHVibVYyH4Al5cFTVibTJZv7dQVXhLh1SCW77sXL3YibwicvKEL9a73hDb8OaoV9XMq","count":955,"preSum":22920},{"ndv":949,"upper":"1hxwfaPVG1QgGX3j5g7kmJf9TrfUibicpic17ibWklSNTUi5bEQaZibkV6WMsQi1Sb8OaM1pKlwm9o","lower":"1hIsQ32mNxLKP6sw2917dn56xuNibeVPgG9IUX7jslXqqKAO1SbelMAtDjvYu8OaWJQp465x","count":955,"preSum":23875},{"ndv":949,"upper":"1iaQrsicmDBl8BYFlZjPPGUvxlTvst5JMFoI6L3YT1SPH2m2Q7g8Oa8P3bcvhlF8Tt4cQYKES","lower":"1HxwPvzTOZqC7KMTy4g9C5eyEbW26iav4TttHvr9Fxpu5LVLEesRiaxFg0KXM1P1S68OasqVs","count":955,"preSum":24830},{"ndv":952,"upper":"1ibpTmQkXAPUcLFUQ1SnPicicKhicSfyY5xXLcxPl5wibLyF11SYRpnKXM8OaV8pVugNGZmTk7eI","lower":"1iaqsFValsebasaWLNib5yDbUQMbFNdrhWUf6gAi5cOajps0x1StQGiaROD8Oa69D7YKAdqdVOia","count":955,"preSum":25785},{"ndv":948,"upper":"1icOy9ltpDiam8F3q3N2mytu0bEY5NrwicfbdZzKrdF1SPJh7ND8OaM0pia7lw7S2YKv8rdibn4z","lower":"1ibptTnibZ6EpKXHvicVlljNBTCJ7ppENPRTzZUdY5n3QvtQc1SEXLqNaf8OacIt1iaPYe70R8k","count":955,"preSum":26740},{"ndv":952,"upper":"1Iys3jaHo7s9KicYSIOcvp5Ru8XLsnIQmOrXNxVFbypOMsJ99iaP6ic8Xia1SuNBDO38OaLGbv0","lower":"1icoYIPYsza0jWYpMdZojBmnkraufY0CpgCKNd6jsV5eGh7SL1SfAibyC8OaR9NPV4UAhicvdib","count":955,"preSum":27695},{"ndv":949,"upper":"1JKJzOOsiafcfQtYlEBky3t51SP8Oa23AHlt2DPk18GibRx0zrOqA5NBPF4OjnqgY0xYA0qDF","lower":"1IysPeadicEIwV9MzIomuW5rZztha4ewufrhK4Pn02DxoibziaGFNYoUEKi1SbzT2kP8OaHRECx","count":955,"preSum":28650},{"ndv":951,"upper":"1k1SP5NQuiaTmUHQwicfJHiadstRWSSue1SZ57fpU15E5AUcZOWo98OaQ2dUE7icy4zBZp8m5vib","lower":"1jKk4XW4IrCXrr3mcQUyhXHS5C7pSENFDETkTHCAnbq5eWX9BD1SP8Oavvm5SvZqVy3WlgL","count":955,"preSum":29605},{"ndv":950,"upper":"1kjfufjjTSz9YmbgaGibQy9oO7T00TCdxIBLblEfjpL8s5srC21Sg8OaEEgfC50TDdFTfNhx","lower":"1k1sz5U3LOicLNL47f7rFuupSeaNZ7NA29hWeRQzAqZ5Fibjjsq1SrfVGEDGs8OapYq4uRMFW","count":955,"preSum":30560},{"ndv":949,"upper":"1kzia1KRXg6knwU4iamgibd1kpFX97KBiazULOGwmTnVUBPF5zS1SibOblZ2mRKrJLTq8OaGKj8D","lower":"1KJgm0FqUdjdib5W1jNGPsw5D1SwhWeMTl74BQaGP5icesn398OatlRtCRibkhfxXVwqibccwKb","count":955,"preSum":31515},{"ndv":950,"upper":"1LIjbFz5HRQyPcfn65zZ2557nr1SfkX4yIztpUrp8I525Zxj36AJ8Oaiaggj4payWow9BfiaQ","lower":"1KziauF6ibH2ak8jEYdO6B5J5ib3LClp4Ew5mfuKSYfFa7tL01Sm4HicFyvafgGherDv8Oal5yq","count":955,"preSum":32470},{"ndv":946,"upper":"1LXN2BfOxYIoALkauS5mje6M15Y41S5hl7JwaRhu8Oam4tHZ6a0K2XrvsBCXxDGNl14aHmf","lower":"1lIJp23zb4EKj15E4K83Cs5E1SYnMl5PARtWYYHd1wxvLbdrf3AmWd8OaL8Hlqzn2BQ4icx6","count":955,"preSum":33425},{"ndv":951,"upper":"1mIgfNhWZ3P7GthxnyIaaZ5ATpyjsynVudpqrhZBELuch161SYJBnDk8Oas5YTrlpf0tCYT","lower":"1LXn37KxIZgic3DepTgydLHeK5QicsCoJ9p3Pg1SJNqtmZZSSZ8UR8DU8OaPWxiarl8XvIwowW","count":955,"preSum":34380},{"ndv":946,"upper":"1mYSH1OQXaJNYgxdgZFAn5VgXucp9j8n5p5OhWR1SoPQcmiacvfv5N78OaOlVoxYsv6lMzgY","lower":"1mIhgvxWQrWMAu1Jx3EXTu5kRJpPppzuyBl3iaVgKUxbSB3s1SQUqa48OafHTXbNu0EAdEBG","count":955,"preSum":35335},{"ndv":948,"upper":"1nIE75RMTnsaqNAQm05MFTh1SQETyARTibXk2TSyttr1b7UuQnh8kOIU8OaCiaST8lKiaqmcQia","lower":"1mySiaIcrOBCIgHMxicwBusIx0eagLvS5Yb4SfhbXCPNc4ianiar31SQb39KzgfSwz58OaedUrs","count":955,"preSum":36290},{"ndv":950,"upper":"1Nzicntiandw99v1miaKYdzRN215XPLnGtEhFAtdRjZrF4MnO1SRG0HbB43ibpXMANia8OaZUepN","lower":"1NIEahJ1fYrNSP8PBZ5GeMd1Scj9rP8OaOacADpjHclbXxNQOS05cYMibglBXQQpgkhefIBI","count":955,"preSum":37245},{"ndv":952,"upper":"1oJFxVm8aIpKyx512Hq51zuK1SvxCjuIcsSuiaLx1NQnKj9v1hULKInzi8OaczY2JWGHNKCCj","lower":"1nzIm44gUw46cSVMzMTo8D5IWksk77b9JwRPKQFXaF9JRehRcI4vBS1SLiaT6AnXhsn18Oan","count":955,"preSum":38200},{"ndv":945,"upper":"1oYwxnGjWWe6I3c52PQrqyImmKwElBs9yCuWV55LRvicEhrX9q05Wtg1Sv1pogS9P8OaOtaib","lower":"1ojg4KUwzPRhQ5qOVPqONMyGqAT1Iy6uhxzJBQLAicPBib5o4f1SrCCUD8OaTbBKtI5CkGDPB","count":955,"preSum":39155},{"ndv":950,"upper":"1pIFibIU6hT1tboeYBK5oxi1SbTRTQFCnUDEqq9952trQNZJ7Pibslo6p48Oa57BOu9vA4ialJj","lower":"1oyy9SibOL2cUwx915tfwichyFz1SxmZJWrRpFPbWpdSVktn0dSxhi5aT9kDusrOh1S8Oaz3F8","count":955,"preSum":40110},{"ndv":951,"upper":"1pXVKRxRI7n6hD9PXkotzpCYSXKmwWpRSgj5ib1S2iczt5fa0B5R8ruYMk8OabJ7afUPX9pxf","lower":"1pIfXITBRDpqpNgTxuJWyL50Qo7wxGNgx0mSmia8GovUTo1SNdesqMnMvl8Oawb27VzA5cNq","count":955,"preSum":41065},{"ndv":948,"upper":"1QiaNPVibzibYQtgq62ZsLAznulvTw5CqWCKziaEh1SlARLKuaK8OamgLbWLey5icHhm2CoClaEe","lower":"1pXVWicdv5FZWGgKbQBicbzlwwaM9w8icvr5vA1S7zSsuicYd6Tp3oAo2d8OaRgBBhPW3mKPWFib","count":955,"preSum":42020},{"ndv":951,"upper":"1QyG9gZkyclPAXib7W4c511TsDmBlt81Sye7UH0s9PoECoxGpSW8c6kIFxMuK9ePH9h8OaIv","lower":"1QianzVfr7ZIf8ibCcfq3CShBJWia25LvXyiaicic1SDy88wsTy8Oar2pL4GtiaWFwajEx1zdIrtma","count":955,"preSum":42975},{"ndv":948,"upper":"1RiaWt0jJ0ImibicK6XNicYHZs2Osod5WNgBRx4TQ1S3UdJ0jia8OaM191icIvwPzdVT1x4eSVvTz","lower":"1qYh4CibSGkKf3ia2Q0kPS8VCmqpjdPiaryuwH5Kj0deLlq11Sdwo9QuS4w8OaibJdJkyv5usGia","count":955,"preSum":43930},{"ndv":949,"upper":"1RYIYFRH3BYvNvCAR1Mdqs5LnjFnge9p1S8uHTHxy8OaEYISlAuHxOjpVD3fl83ibpHDT6QE","lower":"1rIaWyWvTwwkoGkJo0xK2Y59mibpUeXWH7UhIKrRd1SAt2mqNI2rGusC4law8OaRRvJSdpFk","count":955,"preSum":44885},{"ndv":950,"upper":"1sicnAFnjve5DG44DIMibRZXA8EVUJlBj0eibt6XYP5KayNwh1SnwYrLZfrD18Oar6pNgdS2eib","lower":"1RYkEgpQJ0bAWEWdUuJ5MYxKWw2pye85BibnbmG1SeQMKHIlt3EIa8OalQe225A3eQvHYF5K","count":955,"preSum":45840},{"ndv":954,"upper":"1SYHW6HXW449Qh4FdPLia5bffA8tibeWp1STR9FFm8OaBSqCZNOCzxX4DPBV4eNqGtqth2g84","lower":"1SicoHO4k4rnfx1NOWd7ibwmS1G9YPCS5cm3JKm8mj11SEibSni8OaasYDfvW3kgNTzTmBS3ibGO","count":955,"preSum":46795},{"ndv":948,"upper":"1tIofic5lJEGPTUk9O9Via5yVS1XqNDRcJ13sBTx5ow6eWgahZkjIai1SbTMjQ8Oaxu3xtw8My","lower":"1SYiaGkCYS6GdpfzorFlgEahLia1cc4d5Nia1Ca1Sv4HGxeicIq8OaWA2xFnPQLN9C7WSBMbHKq","count":955,"preSum":47750},{"ndv":950,"upper":"1TZ6xxpM1B57EYUQoXtGYj4lGZSLXDZnAH1SYY8GWT8Oa21qkL1F2cE8UxAicJ4AYwYibdRNc","lower":"1tIoONt2ibKAQJKzAYBPia5dFwgNcOo3CUOial4zKMiatOKoiaTaic81SFdNAh8Oa02A8Gmn6A1iaq","count":955,"preSum":48705},{"ndv":952,"upper":"1ujYjU3Uo49LdeSaDmtbU2yP9W25U3VCU2JZqi5cUVBfQyCwYf1ShxevC1iahic8OaibKA3s9nZ","lower":"1TZaVsuDoD26RSMbRIwto3k876jp9CG0U5LwModd1St8Oa2bicZuOygB2LiakWQd8PT9CI7IB","count":955,"preSum":49660},{"ndv":948,"upper":"1uZOY1mAgLzdricfIbfv9icRFU9j55onaaibf8yq1Sn54yhhbXsSAibbP6Z9o3s8Oaj1w5tEoLib","lower":"1ujYu76WsGZk2iaOCY06jkH0Gm5P3rVGiawpoi5cNWm6dUGySt1SFXXAGUrdt5h8Oa5iaWgaNLY","count":955,"preSum":50615},{"ndv":953,"upper":"1VIwYUWazqXaNfn7bvQvB55AD7BJCCjxY2Ma1SqiaaW67ibXT1IIWRp9ZHniaIt2G8OaNAq6jj","lower":"1uZOZT1Kic3F5r2kyH3Hy1vsLttn5Bo3hRnLpGVt1Sxp1XgCFRqVCYt5U00v74k8Oa7ibH2Zm","count":955,"preSum":51570},{"ndv":948,"upper":"1VZcTU2qnZFsbcRg74xXPspwGic7nbyxfzj5gcwr1S6c58OahlCfwlp0Q8y0W58ziaPouoAWz","lower":"1vIxaQxtgr6ibKSwNBBe7V5PK8IXpzJ3mmumsQOzfkdjl4Kiap1iah95sqGBhA1S9d8OaFicQCp","count":955,"preSum":52525},{"ndv":950,"upper":"1wJEuALO5hurJNcgXb5mlkvg1SLib75lowM5R7VwDIXMczoagVEJQKzRKvDHRicIm8OaQaGRw","lower":"1vZdTDHb9EmfZyTTeY2xwzpicBfWIJZq7oaOC9n5hVwi1SalqwibxbqJ9wdicXJa8OavPD45WqO","count":955,"preSum":53480},{"ndv":949,"upper":"1X105W1S13XGdIuZIFjWeRialKFYql99ibWs1nFV8Oa61gP31DBkQUA1IdbShibeQ1RnoflwRn","lower":"1wjfFImDuOtFKWibmiaHjhmhVibp9gqBkBt3pldSC96Iw5XLZm1SHOcynPwz97LLh8OazscfSV","count":955,"preSum":54435},{"ndv":953,"upper":"1xKaH26evB0PyljuQfGdOA0b5kcJcr17hPS28J5mb1S1DKlY1EDG10ia8dMZZnhW2B8OaRQy","lower":"1X13r51I1Sn14WCGfJ5wUKCLiciaBGVhHRxmVsRG8OaSmbJjsD6aqV6ov9fXCQQHmcolkNLoA","count":955,"preSum":55390},{"ndv":951,"upper":"1xzyGpDtUE2l9Jxq59bKibM9KLIffFianBib2TDx3YYYCPR2Y6FNIFr5f9oic0D5i1Sa8Oa6AV5m","lower":"1xKaibwcXEibGqtESLZzSGf25Z5CxfbE9bJaiaSRs1SfK0nH5LI0YSRYoYSR9RhtpP8OacRWHl","count":955,"preSum":56345},{"ndv":952,"upper":"1yjQzr1vFgskGnSgQtpc27vTUZib6W59SI7o5nh5FU6s444cOb1SibYYkPJ2s1ic3gZ8OaEmZX","lower":"1XZypfrEX5qeFOwJibG5fksJ51r1vZYsMQr9R5Kk1SxtVzVbGg1IUFic3eZicwMNXIZ8OasdR4","count":955,"preSum":57300},{"ndv":948,"upper":"1YZed3CD5tpJzib3fIrlftX3HfSlJqQoHhEfeL5w1SdicWt8OaOzHjCq7Y4Un8P6BI2bMVER6","lower":"1YJRPkIwaah5ZGEuRCBbic65JhdqIXo11Sl4sGQxi8OaaCic0qIfxQpP55QLo9TE94z0N8icZOq","count":955,"preSum":58255},{"ndv":953,"upper":"1ZJ8kevVooM55ETfCPshF48r1Sk1rpbYOSvVKJaUPW8OaI1wgDaf9UVPQT0nWP1ICuls562","lower":"1YzFsG3GniaOAk8RPDX568oevn3w8gj4NlC3PPa1S05LCWkhxzicGjibiaHNcwMU0SMX8OaQCXT","count":955,"preSum":59210},{"ndv":924,"upper":"1ZzYOyEEHJ1hB5gJbQ297RKTuq8qJQDDW8vuic5I1SsNxPhniaIKCLOnfgZjcWZChjSs8OaIn","lower":"1zJ9f6Dpw3KcD5iaTPTicAR81SIIHic8pHXibTZGt7jibBxQaTeByK14O9r6NYP2pLmB8Oa43GQ3","count":932,"preSum":60165}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[37282,3,3,3,3,3,3,3,3,3,3,3,3],"valueArr":["","10l75qrHFENk1S3UVZhEoRyUauFhhD8nhnhJIfy9icnHwlkVOYPnXg8OamiadQOtOlDmvTkqg","1Bo4FhOU50e6iaeM1SCokKQ9ASANK0BTkNu72a3QSq4iaqJRbP1F7nx0r8OaMZvwvheGeFghf","1DfHnI9I4bItt8rUJ56wtH1SvyeLpicibB9nwiavJN03CAZB8OaFdicLBencK3kXu0HnppKHeVF","1GtL9yxJUozicnRQO10i5bhDmb1S38jnc5lvyOSXNQf8qGhCae32k7ibiajSWs8Oakq73p8LvkC","1LMejH5Uo1B1SIkctqfb1PzCP511SB3p6ic6XygC8FaicPV8OaHwbmnm7VOzJTOW7gJic3vDLR","1SiceW87FnAEnrTzQn2qibIU99M5zmqp5JYNz53T45i1ScGUu968OaLbLYTUyibo1sb77nZrRbR","1UoMVqLjfm5oBoalcmTJSYT8bT5WJCXHpJT1S6AmYrCrPYCuWY8ue25Oy8OaoUrNhpz6I0n","1bUG6LkZjs2PGKvCVxT25QkTqiaAAxiaKkk1SxefKR7P8Oao2UO07WU5K3ic9PrPXHU5EqgSDn","1icejum1GOTQwd3kXhnO7aRQrN9z1LJOjSrxID6Jq85Gx1S4oUv8OalHt4CZiaiaoc3ff0NKpY","1joAWUPhMHg5N452uuTJfrLJ0Wo6eas0iaKkDrINwribL37nHI1SmfqWq8OasRybrK3NDicRRG","1kiccOoJ3uV4KzROMsrPxWDyZEVbGAve1n9dhWO0rD53MTGib1SCA8OaS68a29fTUU2OCEGZ2","1qGKTL0x7F2W5mVAdm995Qpib1SBAscVicyibnXvW6RgspZ6vCXTSdfRbDB8OaUCbyXBowNvaV"],"type":"String","sampleRate":0.9618625319816094}',1586,0.02436278),('jala_wms_prod','shipment_header','shiptomobile',347406,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1484,"upper":"$2Xq/kbqzPz5Y8Hj+4+BjMDXKSJ3ZNVLr/KVHTbzCjJA=$QS3tt3yv+Aaba/YauQ+ounk3axu4EMhb1Nwk6frtiHo49Mf1wcx3mJhfwGyf4lwV4XIP7v+lyYc9PJOOHr","lower":"","count":1486,"preSum":0},{"ndv":1485,"upper":"$89QhKQEElQMMnCPycqL4wMb9/Mts1Mtm+zb4iHbW0fc=$sqNo2dxCdm6hwlC3tyHGIxAfv0ibv+FwfZJ77wRbiOYohgIBz1zkIvuUE+ywKk+MEqfZKLWUH9su3UnxeR","lower":"$2XSrlhBF9mCAJ4Uvs4H+4Qdxd8EAL1UUOwGQzyK2FB0=$4JzQFS/vr83U1lZCIij7OEk7zuJiMXXLD+mB1EPfgnEGmfoYM2iakDqkUKmN7iW3awVPIViD+F76TXUaec","count":1486,"preSum":1486},{"ndv":1484,"upper":"$boPAiAXyVKkpvPlIlVYJa629pEfAhp/hxna5/PZpW0U=$cF1njEniSTTCnqm65PxaTy9QMyIq1JaY/PN3AHYkwZVvsvNbemxkWSCf4FPvbUe9I+yxGigBueK6ic4mXL","lower":"$89v0XYlPsPCA2aLbB7NXfGiw9Ix7vrfZNRuwVIRf4ko=$I+y97QTpEu+ZYFs9aXXuV/KYqm2zM06Od9ccF17rO9RCBTBrejtVsrvtd7k318CyyGHUVpyuXmgUiqsumX","count":1486,"preSum":2972},{"ndv":1486,"upper":"$eG/qWFjyradE1P3TXOcAQn81DjZOOD+EH6lY/qHbm5w=$GLmrX5wb8Mxlh+DiLSWDXHo+qBNpjtLRxXjhjSVmTLGGb34k/5TrWwU00cofjXH+8TUkD36DmfBtQya05n","lower":"$BopuWlRu9i3ELJoSKVQkUB+G86R68OuNy5JbZHMCBhM=$Ma4HFUY6nITdD2w4S/sbBZIJhjQJNPuI/Tss2CqqkMKl2/jlOGn2cFvuumCad8vlpanJyIeYjoo+id27ep","count":1486,"preSum":4458},{"ndv":1485,"upper":"$H7IMSrBfxjuY59eqt1WlcGtznX/lz7R6tDToHQB8sdc=$IKbaySGOFn1xKuyB1BkLUtqK3en4O/f722Xh3LlqkTqD0FBbU6PpARK1RxBWdjLIvz5ShqxoJ9blAjkif/","lower":"$eg0lAOm1Q8qXJ7EZ7OEprSuwpXFpLTf69hSozQBATco=$YbrYLkBPMxPWcd/Tyj5qo9jZ+rQO1qi7FEJOX5u0hFzoTQiGFec/npi1SzuvK9uHtTJwvou18plvd2/Emv","count":1486,"preSum":5944},{"ndv":1485,"upper":"$JyYAZWvoDmXTfIG94KyX4cfEInbDwY7JMwfvOAzO+Rg=$jUTnHtY/rpnGg7Z5woYvlWQQ039IAPdSLWdxvEJG9Nqj2g2SwCs+LtDmNNZA56NyrIyUfDe9Ynb82y0wkg","lower":"$h7KrR4HpJBNMWb0RKrxqptsNBAl2HPOr1HnMLK0TIpQ=$3731mzE/BVU8EwVulJWo4xOgUDbveJ00KPTjJ41Y05uv0IVwhW8upxjj+CYw6EAda+Yd9nINWAFFFY7zn4","count":1486,"preSum":7430},{"ndv":1486,"upper":"$MqlextcepAdFG3NRFhrg3igRLPdR0yPXz8oJMKXJDns=$TYlJbLGRpiOG7irbdC5CaTj9UJ+a6fxG87ggDnCP1DAKhw/b+EF1ySn2D/uMkclVDm2EeB3RHBQt7V+2ZB","lower":"$jYZXcBYzmLoIADqh9zHDySMrHMxHrN3KUifdWhH+8yQ=$39V3pKFf4LwhrijaWawf5Nvti6U2CveqTMkX44KytZF1fCQQjcSrFwenRyATGnheIqAu/hS79iYS3xaTAG","count":1486,"preSum":8916},{"ndv":1486,"upper":"$pG3/br/G4a/UDIcrVTNiCcsNRApjMMLF0me5w1M/W60=$3VJNNJ6Afa43KVACvnFnarxlsUjCNZAW3s849nQZkJL7lPDWFs4FZYqXmbc2WiWYl15gFuQMgsAjY5K9eO","lower":"$MQm8GVlS+P7jVVfYPf06RrTzZHsHxlcIl9z35XgcqRI=$baTzs9YUxlo1pAOEDNdfQbNj9VRZjbJ2yh4RfoGaBe9IMXIibpfTlrdI1iFJX7BDwBO9TgAJ+yJTqlfHpH","count":1486,"preSum":10402},{"ndv":1486,"upper":"$S4z1LTxAM5r259Qnn1ObyVCh5WfJ3L/GIDpXo84VNRA=$J3uNlrcwHjrryHk/KpwCzazfY0CjLKuN9FOzJFkiLnjS/z1LXfg3lS04On89o4fkzSWNmm2k6U/Qv3Entb","lower":"$pg7kHCV1i1XPo46rzlrdiJArHdPBb08dZYKt/1by22w=$6Kfm2UDLaQM4PKoImYm9ML+/UDufWyAxnTyH80USLSRWb9YVUMFfE5XeczrV3BCl/fjvFNqN90aJl7naKn","count":1486,"preSum":11888},{"ndv":1486,"upper":"$uQic6Ia3uoeX1n/4q8vxrzzqTP4DWG9RVNmqUy0jIwY=$KYid4oHyMGRX8/MXZzxchdKkYrzJm7TxsaMAGzlkdtAcawl7kGHLkb0V5v0UTRTSlyoRtQXKstei4FU+eb","lower":"$S5+Q8T2X5QnsTzzzrsW9hVc56tMUUL/mBD5QpxqerIE=$IYQtbR73iJOVrNWjZxeIvMDFpa4UBrA/HzVTwSN4Khoy+0BSAtPTGfm73NEQOjeGcGSKcm6MmUoJsEo9AF","count":1486,"preSum":13374},{"ndv":1485,"upper":"$XK2n9rVmEAm9yVLUsmAw4FfNijTUOYI4DEmnbJLA+Yk=$NQEhx9V+PQKHw0idIcCsjYNlwpkf8qrWwMOiJhccRZlu5HJmgS8i4qxWiZe0wC+wGPrEBUFK2w9vFM9UQU","lower":"$UqkgyAaOFuMzlMNDf+QQQAqeEaDKINTdkwPQB8xA684=$Ehmra0nPWdQir7ukI0ng9ptzgYlx4xHbKIWI+1L+qkdnViUucwKRyh+ZbAjvP35390Dk7DZr1403BBjpjx","count":1486,"preSum":14860},{"ndv":1347,"upper":"*******0027","lower":"$Xk4YqAo0JFGk$AgAAAAH8Ui4GxyzlawDai7uc8CH2GWLc93X3FfYmD/c=$12$$","count":1493,"preSum":16346},{"ndv":224,"upper":"*******0252","lower":"*******0028","count":1489,"preSum":17839},{"ndv":253,"upper":"*******0507","lower":"*******0253","count":1491,"preSum":19328},{"ndv":216,"upper":"*******0725","lower":"*******0508","count":1495,"preSum":20819},{"ndv":221,"upper":"*******0947","lower":"*******0726","count":1487,"preSum":22314},{"ndv":227,"upper":"*******1175","lower":"*******0948","count":1493,"preSum":23801},{"ndv":229,"upper":"*******1405","lower":"*******1176","count":1490,"preSum":25294},{"ndv":254,"upper":"*******1662","lower":"*******1406","count":1490,"preSum":26784},{"ndv":244,"upper":"*******1907","lower":"*******1663","count":1496,"preSum":28274},{"ndv":226,"upper":"*******2135","lower":"*******1908","count":1490,"preSum":29770},{"ndv":226,"upper":"*******2361","lower":"*******2136","count":1489,"preSum":31260},{"ndv":269,"upper":"*******2634","lower":"*******2362","count":1488,"preSum":32749},{"ndv":226,"upper":"*******2860","lower":"*******2635","count":1491,"preSum":34237},{"ndv":230,"upper":"*******3092","lower":"*******2861","count":1491,"preSum":35728},{"ndv":238,"upper":"*******3331","lower":"*******3093","count":1491,"preSum":37219},{"ndv":260,"upper":"*******3592","lower":"*******3332","count":1491,"preSum":38710},{"ndv":245,"upper":"*******3837","lower":"*******3593","count":1488,"preSum":40201},{"ndv":268,"upper":"*******4110","lower":"*******3839","count":1488,"preSum":41689},{"ndv":340,"upper":"*******4453","lower":"*******4111","count":1486,"preSum":43177},{"ndv":330,"upper":"*******4791","lower":"*******4455","count":1486,"preSum":44663},{"ndv":289,"upper":"*******5083","lower":"*******4792","count":1486,"preSum":46149},{"ndv":226,"upper":"*******5310","lower":"*******5084","count":1486,"preSum":47635},{"ndv":249,"upper":"*******5562","lower":"*******5311","count":1486,"preSum":49121},{"ndv":235,"upper":"*******5798","lower":"*******5563","count":1488,"preSum":50607},{"ndv":226,"upper":"*******6025","lower":"*******5799","count":1489,"preSum":52095},{"ndv":238,"upper":"*******6264","lower":"*******6026","count":1486,"preSum":53584},{"ndv":253,"upper":"*******6520","lower":"*******6265","count":1496,"preSum":55070},{"ndv":217,"upper":"*******6737","lower":"*******6521","count":1495,"preSum":56566},{"ndv":222,"upper":"*******6960","lower":"*******6738","count":1488,"preSum":58061},{"ndv":232,"upper":"*******7192","lower":"*******6961","count":1491,"preSum":59549},{"ndv":265,"upper":"*******7458","lower":"*******7193","count":1489,"preSum":61040},{"ndv":243,"upper":"*******7702","lower":"*******7459","count":1486,"preSum":62529},{"ndv":234,"upper":"*******7936","lower":"*******7703","count":1489,"preSum":64015},{"ndv":230,"upper":"*******8166","lower":"*******7937","count":1493,"preSum":65504},{"ndv":231,"upper":"*******8399","lower":"*******8167","count":1491,"preSum":66997},{"ndv":259,"upper":"*******8660","lower":"*******8400","count":1498,"preSum":68488},{"ndv":214,"upper":"*******8875","lower":"*******8661","count":1486,"preSum":69986},{"ndv":224,"upper":"*******9099","lower":"*******8876","count":1497,"preSum":71472},{"ndv":233,"upper":"*******9332","lower":"*******9100","count":1491,"preSum":72969},{"ndv":262,"upper":"*******9598","lower":"*******9333","count":1490,"preSum":74460},{"ndv":221,"upper":"*******9819","lower":"*******9599","count":1490,"preSum":75950},{"ndv":454,"upper":"131****8792","lower":"*******9820","count":1486,"preSum":77440},{"ndv":1465,"upper":"136****7219","lower":"131****8905","count":1486,"preSum":78926},{"ndv":1460,"upper":"139****8890","lower":"136****7256","count":1486,"preSum":80412},{"ndv":1454,"upper":"15259116829","lower":"139****8908","count":1486,"preSum":81898},{"ndv":1454,"upper":"159****7791","lower":"15259120432","count":1486,"preSum":83384},{"ndv":1460,"upper":"182****3290","lower":"159****7800","count":1486,"preSum":84870},{"ndv":1472,"upper":"187****4401","lower":"182****3301","count":1486,"preSum":86356},{"ndv":1465,"upper":"3065370e78dd8d57feef8ba8406c5877ee20b6d8f80e275f91bc6559047d68b6ca2068","lower":"187****4585","count":1486,"preSum":87842},{"ndv":1481,"upper":"3464624db9a68c255313266346e7cee6077e2926a34b3992ccfa47b1ed56ce4b97f6be","lower":"3065370e790ad723962407eafc765c46de57418bd01484ed142d83db8014eda6db1278","count":1486,"preSum":89328},{"ndv":1478,"upper":"3864308d0bf308ee056247dbab2d3982b53bd9174892d50f16d252aa7ca3bf0b73fc7e","lower":"3464624dbcbb7016ee130fed98a6ea96b09ab71eceb139c3eb5863f7c70b9e6f8027e1","count":1486,"preSum":90814},{"ndv":1478,"upper":"636366ccf6f2cbc7d63092c505acfd9fc1b0de0aa6054765d3c00b4c3f32d843a1e4d7","lower":"3864318d13259b8f868f57dc39f2fb503f8e7d30caa52da3747c8c5f328f54743d893e","count":1486,"preSum":92300},{"ndv":1265,"upper":"刘桂平","lower":"636431cd1ae4f720bb9db50f63baba191e74de87851521b29ac9d1d1ab8803c9549114","count":1275,"preSum":93786}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[43,18,18,20,19,18,18,18,18,116],"valueArr":["(021)6056 2952","*******0251","*******0328","*******0521","*******0800","*******1760","*******2082","*******3007","*******8810","15857945451"],"type":"String","sampleRate":0.9618625319816094}',4634,0.02436278),('jala_wms_prod','shipment_header','shiptoname',13135,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":26,"upper":"【H】佳乐家超市青岛即墨店","lower":"1+1化妆品店","count":35,"preSum":0},{"ndv":31,"upper":"【H】步步高怀化店","lower":"【H】佳华深圳松岗店","count":36,"preSum":35},{"ndv":28,"upper":"万众城万盛","lower":"【H】步步高湘潭华隆店","count":35,"preSum":71},{"ndv":26,"upper":"上海自备仓B2B(顺丰)","lower":"万利化妆品行","count":55,"preSum":106},{"ndv":27,"upper":"中心日化(劳动南路店)","lower":"上饶亿升购物广场","count":35,"preSum":161},{"ndv":31,"upper":"丽客隆长水店","lower":"中心日化(车站西路店)","count":35,"preSum":196},{"ndv":21,"upper":"亚泰超市","lower":"丽洁日用化妆品商店","count":35,"preSum":231},{"ndv":6,"upper":"京东成都仓","lower":"亨达平山生活广场","count":39,"preSum":266},{"ndv":13,"upper":"仟丽店","lower":"京东昆山仓","count":35,"preSum":305},{"ndv":32,"upper":"佳美日化","lower":"仟仟万家超市南宁钦州店","count":36,"preSum":340},{"ndv":25,"upper":"全福元中心店","lower":"佳美茗妆","count":35,"preSum":376},{"ndv":29,"upper":"内蒙古勤获-内蒙古呼和浩特市赛罕区","lower":"全美美妆","count":36,"preSum":411},{"ndv":26,"upper":"北京汇杰思创商贸有限公司(自然堂美妆RKA)","lower":"内蒙古粉蝶商贸有限责任公司(自然堂美妆店)","count":35,"preSum":447},{"ndv":27,"upper":"华东洗化美妆店","lower":"北京美创美捷-北京市大兴区","count":35,"preSum":482},{"ndv":31,"upper":"南宁市兴宁区搜美丽化妆品零售店","lower":"华丽港商场","count":35,"preSum":517},{"ndv":30,"upper":"古里单色系","lower":"南宁市嘉燕商贸有限公司(自然堂现代货架)","count":35,"preSum":552},{"ndv":23,"upper":"周记日化馨园店","lower":"句容元丰商场","count":35,"preSum":587},{"ndv":30,"upper":"嘉人时尚苑","lower":"呵美小栈珊美店","count":35,"preSum":622},{"ndv":28,"upper":"大世界购物广场","lower":"嘉兰氏美妆","count":35,"preSum":657},{"ndv":32,"upper":"天天靓妆","lower":"大同南郊.诚信日化","count":35,"preSum":692},{"ndv":18,"upper":"天津蓟州区孟祥萍化妆品店","lower":"天奕名妆","count":35,"preSum":727},{"ndv":30,"upper":"娇兰佳人","lower":"天美化妆品","count":35,"preSum":762},{"ndv":31,"upper":"家凤日化","lower":"娇兰美妆解放路店","count":35,"preSum":797},{"ndv":26,"upper":"屈臣氏-北京仓","lower":"家宜多购物广场","count":43,"preSum":832},{"ndv":2,"upper":"屈臣氏-沈阳仓","lower":"屈臣氏-昆山仓","count":40,"preSum":875},{"ndv":16,"upper":"常平百花","lower":"屈臣氏-郑州仓","count":36,"preSum":915},{"ndv":31,"upper":"康缇","lower":"平凉澳亚化妆城","count":35,"preSum":951},{"ndv":29,"upper":"心雨日化","lower":"康缇化妆品(万达店)","count":39,"preSum":986},{"ndv":31,"upper":"成都仓B2B自营库区(顺丰)-1000","lower":"忆莎美妆","count":57,"preSum":1025},{"ndv":29,"upper":"新世纪重庆南川商都","lower":"成都彭氏商贸有限公司(自然堂现代货架)","count":35,"preSum":1082},{"ndv":30,"upper":"新疆赛波尔供应链有限公司(自然堂商超)","lower":"新世纪重庆大坪商都","count":36,"preSum":1117},{"ndv":28,"upper":"普丽生(人民路店)","lower":"新疆赛波尔供应链有限公司(自然堂美妆店)","count":35,"preSum":1153},{"ndv":34,"upper":"梅婷化妆品店","lower":"景德镇金鼎百货","count":35,"preSum":1188},{"ndv":31,"upper":"武商量贩武汉黄陂店","lower":"梦之岛南宁钦州店","count":35,"preSum":1223},{"ndv":7,"upper":"武汉仓电商自营库区(顺丰)-1000","lower":"武商量贩沙市店","count":49,"preSum":1258},{"ndv":26,"upper":"汇都商贸","lower":"武汉市兰丹尼商贸有限公司(自然堂现代货架)","count":35,"preSum":1307},{"ndv":14,"upper":"沈阳加露-辽宁省沈阳市大东区","lower":"江北百货大楼","count":39,"preSum":1342},{"ndv":28,"upper":"济南仓B2B自营库区(顺丰)-1000","lower":"沈阳碧茜经贸有限公司(自然堂现代货架)","count":44,"preSum":1381},{"ndv":28,"upper":"清溪欧珀莱","lower":"济南嘉华购物广场","count":35,"preSum":1425},{"ndv":9,"upper":"温州弘方化妆品有限公司(自然堂美妆店)","lower":"清秀佳人","count":35,"preSum":1460},{"ndv":31,"upper":"爱尚彩妆","lower":"温泉美丽99","count":35,"preSum":1495},{"ndv":30,"upper":"璐璐自然堂专卖","lower":"爱尚百货","count":35,"preSum":1530},{"ndv":13,"upper":"百伦百货资阳简阳店","lower":"甘南妍妆化妆品店","count":35,"preSum":1565},{"ndv":29,"upper":"真女人","lower":"百佳日化","count":35,"preSum":1600},{"ndv":26,"upper":"筠连四季美人","lower":"真女人二店","count":35,"preSum":1635},{"ndv":32,"upper":"美丽缘","lower":"简微妆行(中山二店)","count":35,"preSum":1670},{"ndv":34,"upper":"美购","lower":"美之泉","count":35,"preSum":1705},{"ndv":28,"upper":"自然堂吾悦广场店","lower":"美迪康化妆品店","count":36,"preSum":1740},{"ndv":29,"upper":"茗雪妆品4店(步行街)","lower":"自然堂(益和北路店)","count":35,"preSum":1776},{"ndv":30,"upper":"蓬朗自然堂","lower":"荔波县香江大道22号自然茗妆","count":35,"preSum":1811},{"ndv":17,"upper":"西安仓电商自营库区(顺丰)-1000","lower":"藁城信誉楼商厦","count":37,"preSum":1846},{"ndv":27,"upper":"辽阳市鑫浩翔商贸有限公司(自然堂美妆店)","lower":"西施小铺","count":35,"preSum":1883},{"ndv":17,"upper":"郑州仓B2B自营库区(顺丰)-1000","lower":"达旗春雷化妆世景园店","count":39,"preSum":1918},{"ndv":31,"upper":"鑫业美妆","lower":"郑州佳之浩企业管理咨询有限公司(自然堂美妆店)","count":35,"preSum":1957},{"ndv":18,"upper":"银泰舟山店","lower":"鑫林洗化2店","count":35,"preSum":1992},{"ndv":18,"upper":"闵家镇江南","lower":"销售退货仓(电商零售)","count":35,"preSum":2027},{"ndv":27,"upper":"青岛福兴祥商业有限公司(自然堂商超)","lower":"闽清阿容","count":38,"preSum":2062},{"ndv":29,"upper":"馨雅日化轮胎厂店","lower":"青春化妆品店","count":35,"preSum":2100},{"ndv":31,"upper":"黄毅燕","lower":"马连道万家上品折扣店","count":35,"preSum":2135},{"ndv":9,"upper":"龙河美肤宝","lower":"黑水亚欧化妆品店","count":16,"preSum":2170}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[95377,65,31,47,30,29,25,25,28,29,27,39,28],"valueArr":["","伽蓝集团","嘉兴仓B2B自营库区(顺丰)-1000","嘉兴仓电商自营库区(顺丰)-1000","天津仓B2B自营库区(顺丰)-1000","屈臣氏-南海仓","屈臣氏-厦门仓","屈臣氏-天津仓","屈臣氏-成都仓","屈臣氏-武汉仓","屈臣氏-西安仓","珀芙研-个人","自然堂-个人"],"type":"String","sampleRate":0.9618625319816094}',2035,0.02436278),('jala_wms_prod','shipment_header','shiptophonenum',159048,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":260,"upper":"$06X2ZJM4t4A41IwgivVGfLHDHxCOnUjIMRMxONpcyUw=$sjAZih8iinxBBhoXMFn8taL6EtYH7tABQvYA29F15IRaGWtXj22/y63aHEbwtmBIzLgDb6+sGxhThZmuTt","lower":"##+4C/wpiOfs69e2y5aLb/sDkYftRE9FFzgBSsKS4VqRx8tepLsgJ9GbzMhTQ5j0dAoSGplVWere37V7szuUhsX6M5CGrTBH/ijPamhbmS*CgkIARCtHCABKAESPgo8T","count":260,"preSum":0},{"ndv":260,"upper":"$3fBsSY6Zci5krp8oGlkblUGlYQKvclrLllwgM95PsK8=$Iotuw/RSoTcvZrqimCxorZrznGsrYIbODmp8Vm1Wfvd8YPdRF8ID0Lrg319lrdR97FrZ9I8OuzeAFAskji","lower":"$07RoGAn+PibBYQMBmm7ifioCIB+Zqo+WhdjACbc9r8k=$9/ukKj80LEOO28GHawdgSVGShBcvft3Xdr55bMeALSVkK1IIbFJEOsdrhuPgxrpgWcWF6H+mx9MPl8Uwyw","count":260,"preSum":260},{"ndv":260,"upper":"$6GYl+2viwoEtcrKfhleSna4b4aMVO3VKg71190aW+1g=$sjPrf89kNLNnvaMokbYcCxbzlicPsM3VcJXMMpJnaN9dHJwQPEJbAZKKzwTqBM8/FiBEv97qJLl8m+PKna","lower":"$3fMKQOzn26IGymGtBjPv/2udFj2Z7dCVB+IoiwrHJ3o=$sfz4DjnBur+yggNR4u/QlV9Y6TLBRFszd0HYbOjvB8DYjJvGBR0tcZC0nc/g1ozqZwB8pI8ZJnFokAy0Zt","count":260,"preSum":520},{"ndv":260,"upper":"$9MoxkCqhnOoG4SK8asq4jG/2F920ecGsPocjV+5k93E=$eyZ0dlvIDyBUfYRAEU992fUY0DLwa4tLtDN5m15nnY+/wiwmCvOBj4Z7Fs+2paTfUkJzbSMZAeZ15Kva3X","lower":"$6HsS35KJ3jfO8UMMyePuDxkfQ5cp2PVEAzmXso0s8/A=$9Dp8hEpJYhvLS+dnNNGUcTHMuFi8lpargbcxgSptuAWKo6D2ggBmL+4bEvyo5+PGsUJoPmHG5Z8ZJ+z7QY","count":260,"preSum":780},{"ndv":259,"upper":"$bcP9s5UcXMktVl9eGpWeAPuqyWW4cWju1UaZs5ZU/KM=$y2zReZ2GS/H5EL4B/UUeZsASHwde6gfTL373bwsBfBybTt5SRqCOWJXOLOtpLsqZogbxZit0nXka4SLljJ","lower":"$9MSnT6x9FImuVKeqKz2Xt6LURFAAp3XElNECJdY/PBs=$AnucWbQf4iuAYeR0/9XmdWHnh0HdOaYMHW7kA6dCmcUABhQf5qgtrLs4OBOorN/QvCQhscEvb4JavI3umO","count":260,"preSum":1040},{"ndv":260,"upper":"$CQ2yMudELcW66tZu5sHnOi3G3ThwojOUFG1Vz8jDMDM=$11a/+s4r0SmcX4RlXrRco5CZ2Yv9pRsZy+Z7au4Z1IFwndmLzpKaYC+yXNGraSMAiG5TdNsHRxM5uO6kIe","lower":"$bD7iR66rZwUAEO8LBsqMeW8yqmjtcSSyM2yWpIZYvdg=$Ndk9g+iok7m8f2uPpKJjKQFUg6Iif5ZpBVlkZ1ELRo0e1kaxSgjnINAyGCpkls0dU086oXDqnVCIcrGnpt","count":260,"preSum":1300},{"ndv":260,"upper":"$eiJ5jLV/lb8kXC2y3upelqUSct/1eWZy2a+46Ei4n2o=$dwl/MlnYJSbadZ3QmR3a4e+pfGsnCLVS4/Vir/NqS/QmPgfebdHOFJtMwFvQuzLUVrA13G5NB9JZIqPe5I","lower":"$cQ5U9edR8o0gN2aSWquRiMgY+NbBKDNTMkG4hFwfaJk=$Om9Uf9ZYH1r2JBmCQP/5c+2GPiGIy2P41KGISNRIUFLc8XVbatJEWOmy3Smr2E3ezE3ydXLA183NWmk6Kt","count":260,"preSum":1560},{"ndv":260,"upper":"$g6Q28m64eDMa$AgAAAAId/dYGEUoT3wAvFAOya962lDQlxJEa/bnsxEE=$13$$","lower":"$eIJt+jAwtMUzM/4qy38+q0mmo8KlPtjzVe+Qy0K5e0Y=$eUG04q03B3GmptIoJU5fJJkBnu1tyusCz91EruNv+I8jn4EfJ+uVB8sRC6N40YsUriO4apuE1t3EggJtkB","count":260,"preSum":1820},{"ndv":260,"upper":"$hXDotXDiLpiYbcR0iFibW/EwRdnaDy1JHv0imr93xCo=$UMnmNU8UmeC6t6Qf+sqcFWGx2r8Im4d+LAZPaULBgbsnnpmiPYh9fJkxAjSDFd45yvQ09NsD+7qsvuOTKT","lower":"$g7m4vJVBZbOfWhJPwn6WfHo9ZguHzmq79sEje+Vxeuw=$TygItqG5cXRMacWfx8S2ndpCmIUcezrQl6MC6BOXAgP4oZx6KxTFJ/k/4laQ+CYuz3JFJP4aAnSuBtv7aE","count":260,"preSum":2080},{"ndv":260,"upper":"$JLOFBjFCvBovO+D0GH0njAiLdxKztEmdcNEUzDtHRTw=$0qGCcyleCOizBzpimyNoqtLFDGSrN1IsPloK64Dek4NbEv7zobhWTY88mC2HeN2n3ZolqGd6+Rzzgb1Fg/","lower":"$hxJkCO5IYFWSkYqoKqJRTxhB4x9sRnTkalByt9F3bVY=$4fDPdbsG+SVK076/pxxCorv67Kk5GmdIgfSANVlGe1j5JYuSY+FQWA0G8nHAJolIkmSIa4ufBP93LkRnnj","count":260,"preSum":2340},{"ndv":260,"upper":"$L435T2zFF/FOl2Nhl5BeNBngubnzVggB0qBDcSf6GfU=$KqPL5ixH+013xg2p6jFEh+b2J6sa7osprCwOsCrqn9mhnW4hh38aG+o6Vssvu72u0P1I/qAO/cgtS0pPUP","lower":"$JLpTZZihuX4Udk/oeXNo8CRJw/LVTDp6XK+8InePjdM=$FIGVYG0KAryhPw6iI7EbZx2ycu0InbHIn+gYBaS0ynWAcJLIHJgYAYhzmOUKZw/mdtuGr1iP4YbygGfaOT","count":260,"preSum":2600},{"ndv":259,"upper":"$MUaLelJMsSxA6LPIyvU204S08kvypb5nduvFgUHOC7A=$uWckS3CI43kzZeRBWRGBkr/wYCRrkI1rIaTdIG7Urzi03DCfMFsy/YordrwRK5+zvO5poENNLA4Or2F2/t","lower":"$L4efcoHYcOcVO8h+miOaahO64Miy0Aw+Lbhrqvr+PWg=$61aBQMRO5K2bvu4yoBITc86G1r/YCaXy8nvSeOKSX8HA5t2k5WmZDiqgopTcbvF3pkn6VpQrqG0IuxxlFs","count":260,"preSum":2860},{"ndv":260,"upper":"$oClcgW4Mbzj8S3WY3WbmEd/8TBkyG0nwAe3pqNfhq+E=$0kDAm78u1pD+X0qEoFK3qDO6oT3yECD8tLZFoBxJ/E/6y560oc9TKAuCaxzzmQ27A3JZn5JjsJQ7w49jJj","lower":"$mUbLp75oBDWaZLh38SB8yVyoYORhLQYvYqiMoXe5SJs=$+aKulDdrAQm8aUocHvRoDK77959QUiNIoFBCpXPqGbArJ1JnkPIo9W5OlzO0Kw0Uag+VjTW0dCPvy6A4O2","count":260,"preSum":3120},{"ndv":260,"upper":"$px2EG5zTd0qCRTgjR8nh5AFREbMksdHAuNycdrXQzBQ=$TscqcPbgEkBj7J1x5mZWE1H0gTmlJUqgshnd6xZ/THYEedVcALw97OQCYvcL1ic1rynLzqoWX4t7Qqu/te","lower":"$OCsC/WfaSObycmVnLaAZPhNGAuryiyUW4iE9UGR1EyY=$p2XGQ6pJkyOQwUa9EFyDhoGHgLrimUm3qfHBkTwUwkxFLoyVgLFQWhDh2vRMPYsRMdtPnZrWSRT649FFC2","count":260,"preSum":3380},{"ndv":260,"upper":"$RJfS4TE2Rh6WpRVjhmiq/IoiGXDcy4I0uXTTCsryfBI=$p/8dk1iEBmqvIwjYT4irRxTcsSX825akko5N5cazC/gtHByuZGg1RpxuFuCGR+5KPLzLiDhji0wkhGfrg2","lower":"$px5A+s5um6CVckbq+0P1JcM8zY1wOxb/XZbFyz/7sJ4=$SmhSwZbbx/urf1N94+0IVfa+3ZoSafJAwiK1iuq+WUJXTKHuy0N5EOOk5XlnbuNYjbTRQTiKjh8S8Gl4Hr","count":260,"preSum":3640},{"ndv":260,"upper":"$TaV9GkV5RhwFhHd69m8tyrdNrtlyYY97TJGN0YewKkg=$vLxo8dTHrLbh5Kk182RAqmNW7dxWh8z9ApA/aKh/UvhUQn0twHQI7To5Pz/jeZ/7m7eqBBT81DEjq7EmdH","lower":"$RJpQ7+thiMMZaFh703nEq9B64TR7gHUTCpHb/FwMXwQ=$r9ZP+WaBrPTN2OwP3I793MnHjpsNBwLQLezte2EMPNiE+kczf8ZKwNfaLa6KYYFRfVUDh63dTusbaldcQq","count":260,"preSum":3900},{"ndv":260,"upper":"$UvEvcrn743PQrbgkQMoJID+0ZE60hCBbIDVVsFrFJ2s=$sFq1/+UlTCMfCuewW5TvUl4X0ost8HUTP5zVxSa8wTyPpfXIn900+WGbSw2Iciq61YL5+VYz0mgl0d6/BW","lower":"$TAYaQcVQHQcvKZEM/T+KTXqB1H1ZS1mHMruUPg8TDqc=$o24sQF9EINfL/VjfB3VqfjNI/TUm5aukBQaHwphf/rc7UB4blvXfiehGWu4nL3UqJprI1UgNhgpikoRr8a","count":260,"preSum":4160},{"ndv":260,"upper":"$WMgt8AiCJn42TH7UUGaAiQ9zcqpLcVEsvKllA3cyzmQ=$skdpRJab4UO/sLirclKhcHOW67ooIkTijCfj70ko8Y0rfeKictpvvcTWWzDQaBo3OvF4E0N7OlzEmY2A/2","lower":"$uVI5vakqSf/Q9LfRQTQpIFleKja5N1BDhP2xyRTcXbc=$FsSwRkyHWj9fgOCgv8xoyZiG2DwKUUj8FU8bdTfOmybpZiGUK2BOUPj0KvGWTLZFWNHEpE/HBvSllDsea+","count":260,"preSum":4420},{"ndv":260,"upper":"$Y54FTQY0I5vs/Yerr6T3PrQ/17SYbb+imUf404WPhMQ=$JVOF4iWgFVcGOyDwsV3PwQhex7VXsHv7z7mJDtcStuH20uNh6FW5cvB0FpSYvLUS6l6GGPliI5LqfxVTwp","lower":"$wMt4iKb4F7Wx$AgAAAAG9yicGPXI/NADcOjrkUnoSvOc9YOhcr/v63lE=$10$$","count":260,"preSum":4680},{"ndv":260,"upper":"$zpbfq5gHY/24CJ4O0ogIRHhuAnRMb1KPp/9ZPMPn8Xc=$QyJDKptZZqi0DdMzg+BNlMmqseZfVBJkTJZ4Ve0/jqJIPeQuh0GevkjLcSvIz5RmweOWQJkamQdiTtYlmH","lower":"$y55MqcF6lDmFwgE8w2Z5/jqGm1V1NhHgdQ0T7Efjk5A=$N3EOAihgLUuJX4E+fJZHI1Y7bQ+FqQwIMa2CVKpS+rQt8Rotlc7y7VVqsBNGU8Jm0Cs4jgZ4BjCAj2ZXUc","count":260,"preSum":4940},{"ndv":236,"upper":"*******0366","lower":"$ZpgBVZV6f9KFV4N2KGvXoTAQj5bG3dn1XjR/uKu2oME=$QypNS4xeN9/UrbPbpFeDnnrO2CnvjxW7BLxJ8lvoKLx+1btu2kvy/59QUJFk2yCndTWwkLBsjA1vBgIAbs","count":260,"preSum":5200},{"ndv":246,"upper":"*******2872","lower":"*******0375","count":260,"preSum":5460},{"ndv":247,"upper":"*******5307","lower":"*******2882","count":260,"preSum":5720},{"ndv":248,"upper":"*******7887","lower":"*******5321","count":261,"preSum":5980},{"ndv":241,"upper":"*******9957","lower":"*******7889","count":260,"preSum":6241},{"ndv":162,"upper":"13262808783","lower":"*******9966","count":261,"preSum":6501},{"ndv":223,"upper":"13526221881","lower":"13263999999","count":260,"preSum":6762},{"ndv":215,"upper":"13650148898","lower":"13526522353","count":260,"preSum":7022},{"ndv":219,"upper":"13778481216","lower":"13651566432","count":260,"preSum":7282},{"ndv":238,"upper":"13904762488","lower":"13778888617","count":260,"preSum":7542},{"ndv":210,"upper":"13998489569","lower":"13904990501","count":260,"preSum":7802},{"ndv":181,"upper":"15127919955","lower":"13998788200","count":260,"preSum":8062},{"ndv":211,"upper":"15310158512","lower":"15128020339","count":260,"preSum":8322},{"ndv":199,"upper":"15810030742","lower":"15311514176","count":265,"preSum":8582},{"ndv":196,"upper":"15930191591","lower":"15810552837","count":260,"preSum":8847},{"ndv":203,"upper":"17816625069","lower":"15930312022","count":265,"preSum":9107},{"ndv":186,"upper":"18216222840","lower":"17837078389","count":260,"preSum":9372},{"ndv":191,"upper":"18502314175","lower":"18216271713","count":260,"preSum":9632},{"ndv":195,"upper":"18721599242","lower":"18503150896","count":260,"preSum":9892},{"ndv":198,"upper":"18932970331","lower":"18721852974","count":261,"preSum":10152},{"ndv":235,"upper":"303439049716e7b3c50c9b8036977c0bea0c354a971757d6c5208bb043fd415ee1791a","lower":"18935525969","count":260,"preSum":10413},{"ndv":259,"upper":"31306110a22b6fd9236eacd9a5cec065b690809fdc82ed200900b3049b08181feeab72","lower":"30346104a00ad55e5d621e9c36830251ef67f84d9785c59d854880d618f2fe81eca31f","count":260,"preSum":10673},{"ndv":260,"upper":"3162651be8003f6ed3313a7e9a4d57db2e653948d825f0192d9fe8e8614466182f74e1","lower":"31306110a86d1237fe3f028b0525e2075e146f3be33af3ddf92b64d49ac630b621a617","count":260,"preSum":10933},{"ndv":260,"upper":"3236372676b48d3993d275205890966dd874155a4b4130e8819e9468e0de1ad7c35d54","lower":"3162651beae97e0126b5297d527dfe02c35c395aed9e992daa0704f7a08b9d36b20c6e","count":260,"preSum":11193},{"ndv":258,"upper":"33316331c60830896e5cae3950509e41895292780f65004691393b6d5f580cf5f46e30","lower":"323637267ee2e60fd97c285ec91deca8f49cc244a7eef44b5a6b65f57cca311556f14b","count":260,"preSum":11453},{"ndv":260,"upper":"3364343d4707ef48e23b1d42f409eaa4ad97cb2eb98e17e8b88edc11e727606a86e0b2","lower":"33316331cbecab43ac42c7853de7a11c3ebed7074f7fa058b20162e7c630786369c0ca","count":260,"preSum":11713},{"ndv":259,"upper":"343932492f4797a3b661d3f210632778c821220f3802c77ad1d6fd225b670c976587fa","lower":"3364353d5379d526809802b86f1bc1b6ec5a54f901e99494ae1e06ff3b5c876c8f8781","count":260,"preSum":11973},{"ndv":258,"upper":"35326352c0810ddaa0e5cfe83a04df6c3de4c0805d7e03586fe41db44384aa1618a526","lower":"3439344947c3edc2c7aae83d6f675c41d39fc8bf7baf4a5413b55930cd7588ed36a9e0","count":260,"preSum":12233},{"ndv":258,"upper":"3564365d6234a011399ee3c35eccd0c6bef45ca14ccebfc8e73534fa797cc3a446dbc9","lower":"35326452de3a91d8647b0fd798e9a18e06de295decef88243fd884ec03e80bebe3fba4","count":260,"preSum":12493},{"ndv":259,"upper":"363830680112150c342489c3e78eb0d86b253cc909d84948f5c9b674e09fd95d75f2ee","lower":"3564365d63d1016f730cf2e2b2209ef55dc95faee5c624947052247c9961b23ef33a27","count":260,"preSum":12753},{"ndv":260,"upper":"37336673f90e05e575ce688683cb9207772100061790f8a485e8121027c3841d1f546c","lower":"36383068036ba9bda06d5b3ea0f59e4ae15a4d9a420bf3293177a5f06dd35bb4dde60b","count":260,"preSum":13013},{"ndv":258,"upper":"3766657fe441549dc39590067220e2991bb314a4b959b1908333ed707ff25e971f809c","lower":"3734307401800946dee85c15400d757dfb8c1bfcb94609085a8a011492e42d04c25e4f","count":260,"preSum":13273},{"ndv":257,"upper":"3861338a335e68ff9eef823fe85eb4bc05314ccc85ef45da2236f8e76c43d1273e8445","lower":"3766657fe584fcc401b2809c47554e15107f9a8568b1df619808e4df23f860d8502bcf","count":260,"preSum":13533},{"ndv":259,"upper":"39356495dfd54819c543e99f6e1287e60561f77e7d9e5a1f3484d701b3ce9227edd4d7","lower":"3861338a3969ae5aff133beb3855d15c86f68dab9fff5ba947e46f9a3547c0f9d414fb","count":260,"preSum":13793},{"ndv":260,"upper":"613163a1c35703cdd11d6e60d2bcd8d6910d70c2082c7e63ae280f97bf58917ef718e2","lower":"39356595e131a744902e22899213d73af0c0212d34112d29414a47d34d8294db75c10c","count":260,"preSum":14053},{"ndv":260,"upper":"616336ac6df660206cf384b75641ff661035cfbc1f736793a552ed7f5f81d85e9e2832","lower":"613163a1c66d94c9a9e7949deb4cfbc4d1cfd32a68afef78a1c0109694fc3d753b4d87","count":260,"preSum":14313},{"ndv":256,"upper":"623763b7cacacfc4d951238fd7e2827f6c9e946707a0e31cd81ea9d07412a1b8382361","lower":"616337ac74d383b8d85ef44c9de64e4906509c31f08e2c72594734633ddb7b08dc7681","count":260,"preSum":14573},{"ndv":255,"upper":"633230c204ee9ea749ea80a9811579592ba56a628cf762802ad54379f1e231ad13078e","lower":"623764b7da748445671293daf137b9b5fde3f8d52b748db44288a2453dda3896e503f2","count":260,"preSum":14833},{"ndv":260,"upper":"636431cd1ae4f720bb9db50f63baba191e74de87851521b29ac9d1d1ab8803c9549114","lower":"633230c20fb8df06f56582e2a19d6586dca89d85b90eaa9d5e1fccc0bcdfc318450106","count":260,"preSum":15093},{"ndv":258,"upper":"643832d82fa76f0a1de5b53ecf009de2882e9ccdfad682c7ce1396157c1cdcd074d828","lower":"636431cd1d2a845740cef7c073ebf701984cc08b54cbeaf757ee39bf4a7c9a3c892d27","count":260,"preSum":15353},{"ndv":257,"upper":"653236e26f967d7a79e6312e5af0f27b9b29af5fed6e20fe25019b76a40c5d5adfaf78","lower":"643833d830743378ad0210324ba12191453e567168b8af366d37b5301427406a843cac","count":260,"preSum":15613},{"ndv":258,"upper":"656334ec4e32757f6cd1adf87fcce45ddcc7ef65a3344f2222035eaf068fe9bda7b5df","lower":"653238e284473a833a62330a488f4d815c33c46b1641bb02943daf06e7196ec4a24de8","count":260,"preSum":15873},{"ndv":259,"upper":"663664f6d652b1d84292368e1a90c66b2f2a84c81027c202cc19c03a095b76cb5d3828","lower":"656335ec539121fe5ae08ce1228beddc699b8fa7375b4cb5c323779d14e6af399a0e22","count":260,"preSum":16133},{"ndv":232,"upper":"测试","lower":"663664f6dd15314c9ea8dc204a724b042fa31e73d86c2a7d6aa79ed77a1416eb3db8d3","count":235,"preSum":16393}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[89,43,25,29,28,27,25,29,47,32,27,52,116,26],"valueArr":["","(021)6056 2952","022-58669903-680","027-87027020-627","028-88454296-610","029-33636453","0592-7276810","0757-81285355","13240073725","13611795239","15002119948","15220297985","15857945451","18681250538"],"type":"String","sampleRate":0.9618625319816094}',82778,0.02436278),('jala_wms_prod','shipment_header','shiptopostalcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','shiptostate',73,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":"上海市","lower":"","count":885,"preSum":0},{"ndv":4,"upper":"内蒙古自治区","lower":"上海省","count":1601,"preSum":885},{"ndv":1,"upper":"北京","lower":"北京","count":1984,"preSum":2486},{"ndv":1,"upper":"北京市","lower":"北京市","count":596,"preSum":4470},{"ndv":2,"upper":"吉林省","lower":"吉林","count":1353,"preSum":5066},{"ndv":2,"upper":"天津","lower":"四川","count":1139,"preSum":6419},{"ndv":3,"upper":"宁夏回族自治区","lower":"天津市","count":802,"preSum":7558},{"ndv":2,"upper":"山东","lower":"安徽","count":598,"preSum":8360},{"ndv":2,"upper":"山西省","lower":"山西","count":1826,"preSum":8958},{"ndv":1,"upper":"广东","lower":"广东","count":1295,"preSum":10784},{"ndv":2,"upper":"广西壮族自治区","lower":"广西","count":2531,"preSum":12079},{"ndv":2,"upper":"新疆维吾尔自治区","lower":"新疆","count":969,"preSum":14610},{"ndv":2,"upper":"江西","lower":"江苏","count":600,"preSum":15579},{"ndv":2,"upper":"河南","lower":"河北","count":733,"preSum":16179},{"ndv":3,"upper":"海南省","lower":"浙江","count":945,"preSum":16912},{"ndv":2,"upper":"湖南","lower":"湖北","count":536,"preSum":17857},{"ndv":2,"upper":"甘肃省","lower":"甘肃","count":1268,"preSum":18393},{"ndv":5,"upper":"贵州省","lower":"福建","count":2131,"preSum":19661},{"ndv":2,"upper":"辽宁省","lower":"辽宁","count":2538,"preSum":21792},{"ndv":1,"upper":"重庆","lower":"重庆","count":1196,"preSum":24330},{"ndv":1,"upper":"重庆市","lower":"重庆市","count":594,"preSum":25526},{"ndv":2,"upper":"陕西省","lower":"陕西","count":2507,"preSum":26120},{"ndv":4,"upper":"黑龙江省","lower":"青海","count":1756,"preSum":28627}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2440,2557,4519,4849,4723,12068,7324,2765,3455,5468,6880,4159,3523,3527],"valueArr":["上海","云南省","四川省","安徽省","山东省","广东省","江苏省","江西省","河北省","河南省","浙江省","湖北省","湖南省","福建省"],"type":"String","sampleRate":0.9618625319816094}',1361,0.02436278),('jala_wms_prod','shipment_header','shiptostatecode',32,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"11","lower":"","count":612,"preSum":0},{"ndv":1,"upper":"12","lower":"12","count":333,"preSum":612},{"ndv":1,"upper":"14","lower":"14","count":1613,"preSum":945},{"ndv":1,"upper":"15","lower":"15","count":1370,"preSum":2558},{"ndv":1,"upper":"21","lower":"21","count":2284,"preSum":3928},{"ndv":1,"upper":"22","lower":"22","count":1239,"preSum":6212},{"ndv":1,"upper":"23","lower":"23","count":1342,"preSum":7451},{"ndv":1,"upper":"31","lower":"31","count":859,"preSum":8793},{"ndv":1,"upper":"46","lower":"46","count":507,"preSum":9652},{"ndv":1,"upper":"50","lower":"50","count":574,"preSum":10159},{"ndv":1,"upper":"52","lower":"52","count":1664,"preSum":10733},{"ndv":2,"upper":"61","lower":"54","count":2391,"preSum":12397},{"ndv":1,"upper":"62","lower":"62","count":1143,"preSum":14788},{"ndv":2,"upper":"64","lower":"63","count":663,"preSum":15931},{"ndv":1,"upper":"65","lower":"65","count":828,"preSum":16594}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[3383,7149,6517,4722,3413,2720,4662,5258,3987,3461,10975,2299,4461,2526],"valueArr":["13","32","33","34","35","36","37","41","42","43","44","45","51","53"],"type":"String","sampleRate":0.9618625319816094}',17046,0.02436278),('jala_wms_prod','shipment_header','shiptotown',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[31],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99970,0.02436278),('jala_wms_prod','shipment_header','shiptotowncode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[82955],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',17046,0.02436278),('jala_wms_prod','shipment_header','shortaddress',62799,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":138,"upper":"(W86)024CQ-047","lower":"(01)591Z666-005同","count":146,"preSum":0},{"ndv":141,"upper":"010WE-ABJ-015","lower":"(W86)024CQ-072","count":146,"preSum":146},{"ndv":143,"upper":"020W-CM-505","lower":"010WE-ABJ-033","count":146,"preSum":292},{"ndv":141,"upper":"021WG-BDA-021","lower":"020W-CU-111B","count":146,"preSum":438},{"ndv":145,"upper":"022HH-M5-006","lower":"021WG-BHBL-703B","count":146,"preSum":584},{"ndv":142,"upper":"023W-Z023-000","lower":"022HK-011","count":146,"preSum":730},{"ndv":143,"upper":"028W-AD-301店","lower":"023W-Z031-014","count":146,"preSum":876},{"ndv":139,"upper":"028WA-NC-043","lower":"028W-AD-503","count":146,"preSum":1022},{"ndv":139,"upper":"052HA-009","lower":"028WA-NCA-021","count":147,"preSum":1168},{"ndv":36,"upper":"101B-","lower":"052KT-005","count":155,"preSum":1315},{"ndv":49,"upper":"161-","lower":"101B- 04-06 B01","count":174,"preSum":1470},{"ndv":33,"upper":"215-","lower":"161- 170 07","count":149,"preSum":1644},{"ndv":35,"upper":"245-","lower":"215- 131 614","count":165,"preSum":1793},{"ndv":37,"upper":"281-","lower":"245- 71 D78","count":180,"preSum":1958},{"ndv":79,"upper":"310U-003","lower":"281- A-38 081","count":146,"preSum":2138},{"ndv":123,"upper":"314DE-014同","lower":"310V-013","count":146,"preSum":2284},{"ndv":125,"upper":"320B-","lower":"314DE-018","count":150,"preSum":2430},{"ndv":67,"upper":"351QA-021","lower":"321-","count":146,"preSum":2580},{"ndv":78,"upper":"361- Y5 5555","lower":"351Z005-003","count":164,"preSum":2726},{"ndv":119,"upper":"372BM-201","lower":"361D-","count":146,"preSum":2890},{"ndv":111,"upper":"391AA-504","lower":"372CA-401","count":146,"preSum":3036},{"ndv":103,"upper":"410-","lower":"391AAL-000店","count":172,"preSum":3182},{"ndv":85,"upper":"425B-","lower":"410- C-S24 11 [R1]","count":146,"preSum":3354},{"ndv":94,"upper":"451-","lower":"427G-056","count":153,"preSum":3500},{"ndv":79,"upper":"461E-","lower":"451- 41-02 XA4 [A3]","count":147,"preSum":3653},{"ndv":96,"upper":"481-","lower":"461E- 65-13 R03","count":153,"preSum":3800},{"ndv":97,"upper":"513BM-D3-011","lower":"481- E02 800","count":146,"preSum":3953},{"ndv":130,"upper":"520-","lower":"513BM-D3-023同","count":149,"preSum":4099},{"ndv":108,"upper":"531TQ-048同","lower":"520- 01-25 018","count":146,"preSum":4248},{"ndv":132,"upper":"537-537Z043","lower":"531TQ-055","count":146,"preSum":4394},{"ndv":103,"upper":"551GD-B3-003同","lower":"537-537ZHC-009","count":146,"preSum":4540},{"ndv":132,"upper":"566H-008同","lower":"551HD-B14-016","count":146,"preSum":4686},{"ndv":105,"upper":"573N005-000","lower":"566ZHC-007","count":146,"preSum":4832},{"ndv":98,"upper":"576FE-002B同","lower":"573N020-000","count":146,"preSum":4978},{"ndv":112,"upper":"585-","lower":"576FJ-037同","count":161,"preSum":5124},{"ndv":84,"upper":"595AI-033同","lower":"585- 15-5 B00 [B05]","count":146,"preSum":5285},{"ndv":82,"upper":"601-","lower":"595AK-002A","count":173,"preSum":5431},{"ndv":25,"upper":"631-","lower":"601- 225 13 [A05]","count":153,"preSum":5604},{"ndv":89,"upper":"663AH-008同","lower":"631- D259 203","count":146,"preSum":5757},{"ndv":78,"upper":"700Y-","lower":"663AH-024","count":150,"preSum":5903},{"ndv":75,"upper":"713E-022","lower":"701-","count":146,"preSum":6053},{"ndv":142,"upper":"7311PL-039","lower":"713E-035","count":146,"preSum":6199},{"ndv":113,"upper":"741-","lower":"7311PM-061","count":147,"preSum":6345},{"ndv":137,"upper":"754DE-027","lower":"741- 03 D3","count":146,"preSum":6492},{"ndv":138,"upper":"755WE-KBA-TPL009C","lower":"754DH-001","count":146,"preSum":6638},{"ndv":142,"upper":"757WA-AS-006C","lower":"755WE-KBB-009B","count":146,"preSum":6784},{"ndv":124,"upper":"760- 01-37 15","lower":"757WA-AU-016B","count":146,"preSum":6930},{"ndv":144,"upper":"769WB-QN-010","lower":"760- 01-42 72","count":146,"preSum":7076},{"ndv":135,"upper":"769WM-SF-073B","lower":"769WB-QS-006B","count":146,"preSum":7222},{"ndv":142,"upper":"775D054-007","lower":"769ZPWB-VM-M7-MK016C","count":146,"preSum":7368},{"ndv":92,"upper":"792VA-AF-028","lower":"775DC-015","count":146,"preSum":7514},{"ndv":95,"upper":"802-","lower":"792VA-C-028","count":164,"preSum":7660},{"ndv":80,"upper":"818AB-032","lower":"802- E14 27V","count":146,"preSum":7824},{"ndv":86,"upper":"831V-061","lower":"818AD-032","count":146,"preSum":7970},{"ndv":55,"upper":"851-","lower":"831ZPVA","count":171,"preSum":8116},{"ndv":105,"upper":"871AS-008同","lower":"851- A2 022","count":146,"preSum":8287},{"ndv":127,"upper":"891","lower":"871AT-034","count":146,"preSum":8433},{"ndv":67,"upper":"902-","lower":"891- 03-02 32","count":152,"preSum":8579},{"ndv":100,"upper":"932EB-000","lower":"902AB-027","count":146,"preSum":8731},{"ndv":85,"upper":"954AE-003","lower":"932K-012","count":146,"preSum":8877},{"ndv":89,"upper":"B38-J-021LM-013","lower":"954JT-AL-AL016","count":146,"preSum":9023},{"ndv":138,"upper":"XY6-519BL-082","lower":"B40-G-021K-209","count":146,"preSum":9169},{"ndv":15,"upper":"ZW8-519L-063同","lower":"XY6-519BL-085","count":15,"preSum":9315}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[88033,94,145,64,80,78,61,93,57,73,60,54,78,57],"valueArr":["","110-","121-","130-","145-","235-","300-","361- Y5 555","430-","501-","590-","700-","805-","891-"],"type":"String","sampleRate":0.9618625319816094}',1644,0.02436278),('jala_wms_prod','shipment_header','shortaddresscode',162328,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":302,"upper":"(TA)024TA-012","lower":"(01)591Z666-005同","count":318,"preSum":0},{"ndv":277,"upper":"010WB-BAK-007","lower":"(TB)024TB-022同","count":318,"preSum":318},{"ndv":300,"upper":"020RD-NC-068A","lower":"010WB-BAK-028","count":318,"preSum":636},{"ndv":293,"upper":"021WF-Z496-016B","lower":"020RD-NC-NGAL000","count":318,"preSum":954},{"ndv":308,"upper":"022BTA-011","lower":"021WG-580ZHK-001","count":318,"preSum":1272},{"ndv":301,"upper":"023W-023","lower":"022CA-009","count":320,"preSum":1590},{"ndv":309,"upper":"025WD-TZ-051","lower":"023W-BE-002同","count":318,"preSum":1910},{"ndv":284,"upper":"028W-BAC-409","lower":"025WD-UD","count":318,"preSum":2228},{"ndv":301,"upper":"028WA-D104-002","lower":"028W-BAF-012","count":318,"preSum":2546},{"ndv":290,"upper":"029WE-DAA-067","lower":"028WA-D124-000","count":318,"preSum":2864},{"ndv":245,"upper":"101A-","lower":"029WE-DB-082","count":344,"preSum":3182},{"ndv":21,"upper":"221-","lower":"101B-","count":323,"preSum":3526},{"ndv":20,"upper":"310-","lower":"230-","count":332,"preSum":3849},{"ndv":297,"upper":"312Z044-000","lower":"310A-","count":318,"preSum":4181},{"ndv":307,"upper":"319VA-EC-017","lower":"312Z045-000","count":318,"preSum":4499},{"ndv":214,"upper":"352DLD013-000","lower":"319VA-G-007同","count":319,"preSum":4817},{"ndv":262,"upper":"370D009-000","lower":"352DLD017-000","count":318,"preSum":5136},{"ndv":282,"upper":"372DLD035-000","lower":"370D011-001B","count":318,"preSum":5454},{"ndv":285,"upper":"377FN-017同","lower":"372DLD036-000D","count":318,"preSum":5772},{"ndv":262,"upper":"394AF-203同","lower":"377FN-019同","count":318,"preSum":6090},{"ndv":228,"upper":"411BBL-002","lower":"394AH-101同","count":318,"preSum":6408},{"ndv":251,"upper":"431EQ-048","lower":"411BC-036","count":318,"preSum":6726},{"ndv":256,"upper":"451LU-015店","lower":"431ES-009","count":318,"preSum":7044},{"ndv":213,"upper":"471CN-A3-017","lower":"451Q-002","count":318,"preSum":7362},{"ndv":251,"upper":"510E-B10-045","lower":"471CV-052","count":318,"preSum":7680},{"ndv":278,"upper":"513UD-H6-302同","lower":"510EB-C06-024同","count":318,"preSum":7998},{"ndv":298,"upper":"517B-004同","lower":"513V-G10-151同","count":318,"preSum":8316},{"ndv":279,"upper":"527DLD008-000","lower":"517B-036","count":318,"preSum":8634},{"ndv":271,"upper":"532W-HI-015","lower":"527DLD015-000","count":318,"preSum":8952},{"ndv":307,"upper":"537-537LC-024","lower":"532W-HL-006","count":318,"preSum":9270},{"ndv":258,"upper":"551BA-B1-024同","lower":"537-537LD-021","count":318,"preSum":9588},{"ndv":297,"upper":"553KF-005同","lower":"551BD-B12-102","count":318,"preSum":9906},{"ndv":286,"upper":"564VA-B-004同","lower":"553MA-007同","count":318,"preSum":10224},{"ndv":251,"upper":"571WB-LK-047","lower":"564VA-B-010同","count":318,"preSum":10542},{"ndv":289,"upper":"574W-LAB-015","lower":"571WB-MP-018","count":318,"preSum":10860},{"ndv":261,"upper":"576SD-012","lower":"574W-LB-A22-108","count":318,"preSum":11178},{"ndv":296,"upper":"579WA-SD-B36-011","lower":"576SD-013","count":318,"preSum":11496},{"ndv":211,"upper":"595HC-004A","lower":"579WA-SD-B36-014","count":318,"preSum":11814},{"ndv":167,"upper":"631-","lower":"595HD-001B","count":338,"preSum":12132},{"ndv":252,"upper":"668B-006A","lower":"631W-AD-005","count":318,"preSum":12470},{"ndv":167,"upper":"711G-011","lower":"668B-009B","count":318,"preSum":12788},{"ndv":289,"upper":"717BF-023","lower":"711G-022","count":318,"preSum":13106},{"ndv":292,"upper":"7311DA-086","lower":"717D-024","count":318,"preSum":13424},{"ndv":299,"upper":"736AH-047","lower":"7311DA-088","count":318,"preSum":13742},{"ndv":266,"upper":"750AB-016A","lower":"736AH-055","count":318,"preSum":14060},{"ndv":290,"upper":"755W-HA-BGL001B","lower":"750AD-006A","count":318,"preSum":14378},{"ndv":294,"upper":"755WM-F009-000","lower":"755W-HB-029","count":318,"preSum":14696},{"ndv":297,"upper":"759VA-AF-008","lower":"755WM-FC-005B","count":318,"preSum":15014},{"ndv":275,"upper":"769WB-QB-003C同","lower":"759VA-AJ-013","count":318,"preSum":15332},{"ndv":290,"upper":"771CS-043同","lower":"769WB-QB-005B","count":318,"preSum":15650},{"ndv":303,"upper":"779AD-026","lower":"771CS-062同","count":318,"preSum":15968},{"ndv":238,"upper":"794A-045","lower":"779AE-001","count":318,"preSum":16286},{"ndv":261,"upper":"802-","lower":"794AC-006","count":344,"preSum":16604},{"ndv":221,"upper":"825B-009","lower":"805A-","count":318,"preSum":16948},{"ndv":222,"upper":"835-","lower":"825B-107","count":320,"preSum":17266},{"ndv":213,"upper":"855","lower":"835D-015","count":318,"preSum":17586},{"ndv":255,"upper":"871KB-015","lower":"855A-004","count":318,"preSum":17904},{"ndv":295,"upper":"891ZPVA-011","lower":"871KF-033","count":318,"preSum":18222},{"ndv":221,"upper":"912MA-001","lower":"892-","count":318,"preSum":18540},{"ndv":257,"upper":"932DLD029-000","lower":"912MA-007同","count":318,"preSum":18858},{"ndv":249,"upper":"954AC-026","lower":"932DLD032-000","count":318,"preSum":19176},{"ndv":252,"upper":"997","lower":"954ADL-004同","count":320,"preSum":19494},{"ndv":303,"upper":"WG-VL-021Z427-018","lower":"997AB-008A","count":318,"preSum":19814},{"ndv":153,"upper":"ZW8-519L-063同","lower":"WG-VL-021Z455-040","count":159,"preSum":20132}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[94,145,64,80,78,61,57,73,60,53,54,78,57],"valueArr":["110-","121-","130-","145-","235-","300-","430-","501-","590-","600-","700-","805-","891-"],"type":"String","sampleRate":0.9618625319816094}',78756,0.02436278),('jala_wms_prod','shipment_header','shortalloc',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','shortpacking',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','shortpick',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','signvalue',103408,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":600,"upper":"502112103:1|502589202:2|502764100:1","lower":"","count":1186,"preSum":0},{"ndv":415,"upper":"502112204:1|502484903:2|502487704:1|502645000:1|502975522:1","lower":"502112103:1|502589202:2|502764100:1|6165296:1","count":1190,"preSum":1186},{"ndv":302,"upper":"502191320:1|502191340:1|502191390:1|502503901:3|502513906:4","lower":"502112204:1|502484903:2|502487704:1|502645000:1|502975524:1","count":1180,"preSum":2376},{"ndv":480,"upper":"502191513:2","lower":"502191320:1|502191340:1|502699002:4","count":1362,"preSum":3556},{"ndv":212,"upper":"502191602:1","lower":"502191513:2|502191530:1|502684503:1","count":1222,"preSum":4918},{"ndv":256,"upper":"502191612:1","lower":"502191602:1|502191612:1","count":1320,"preSum":6140},{"ndv":259,"upper":"502200305:1|502200404:1|502201703:1|502201910:1|502477901:2|502536603:1|502562203:1|502640804:1|502699200:3|502976673:2|50298546","lower":"502191612:1|502200305:1|502201701:1|502202401:1|502588501:1|502640802:2|502642510:2|6165273:1","count":1200,"preSum":7460},{"ndv":385,"upper":"502200305:1|502201910:1|502583416:1|502640802:1|502642509:3|502681400:1","lower":"502200305:1|502200404:1|502201703:1|502201910:1|502477901:2|502536603:1|502562203:1|502640804:1|502699201:3|502976673:2|50298546","count":1180,"preSum":8660},{"ndv":331,"upper":"502200306:1|502200408:1|502201703:1|502201910:1|502477902:2|502493702:1|502589104:1|502589403:2|502640805:2|502642510:2|50284550","lower":"502200305:1|502201910:1|502583416:1|502640805:1|502642510:3","count":1190,"preSum":9840},{"ndv":19,"upper":"502200306:1|502200408:1|502201703:1|502201910:1|502536603:1|502562203:1|502640806:2|502668704:1|502699002:1|502845500:1|50297667","lower":"502200306:1|502200408:1|502201703:1|502201910:1|502477902:2|502493702:1|502640805:2|502642510:2|502699002:7|502845500:1|50297667","count":1279,"preSum":11030},{"ndv":413,"upper":"502200306:1|502201910:1|502642510:2|502845500:1","lower":"502200306:1|502200408:1|502201703:1|502201910:1|502536603:1|502640805:3|502668704:1|502699002:1|502845500:1|502976673:3|6165273:","count":1183,"preSum":12309},{"ndv":526,"upper":"502200408:1|502640805:1|502699102:1","lower":"502200306:1|502201910:1|502642510:2|502845500:1|6164964:1","count":1237,"preSum":13492},{"ndv":280,"upper":"502201906:1|502588103:1|502750104:5","lower":"502200408:1|502640805:1|502699102:1|502700002:2","count":1184,"preSum":14729},{"ndv":192,"upper":"502202405:1|502477902:1","lower":"502201906:1|502588103:1|502750104:5|502754400:1|502765800:1|502775500:2|502775700:2","count":1421,"preSum":15913},{"ndv":332,"upper":"502220203:1|502220401:1|502220501:1|502220602:1|502477901:1|502487704:1|502699002:1|502764100:1","lower":"502202405:1|502477902:1|502481603:1|502754400:2","count":1181,"preSum":17334},{"ndv":312,"upper":"502220402:1","lower":"502220203:1|502220401:1|502220501:1|502220602:1|502477901:1|502487704:2|502699002:1","count":1235,"preSum":18515},{"ndv":319,"upper":"502240403:1|502240503:1|502643500:4|6163780:1","lower":"502220402:1|502220501:1","count":1180,"preSum":19750},{"ndv":742,"upper":"502250801:1|502977111:1","lower":"502240403:1|502240503:1|502643501:1|502750900:1|502751000:4|502835600:2","count":1184,"preSum":20930},{"ndv":308,"upper":"502476708:4","lower":"502250801:1|502985192:1","count":1337,"preSum":22114},{"ndv":228,"upper":"502481803:1|502624601:1","lower":"502476708:4|502484903:2|502487704:1|502511201:1|502645000:1|502975522:1","count":1196,"preSum":23451},{"ndv":289,"upper":"502511201:1|502764100:1","lower":"502481803:1|502624601:1|502671602:1|502671702:1|502699402:2","count":1223,"preSum":24647},{"ndv":446,"upper":"502520703:1|502977111:1","lower":"502511201:1|502764100:1|502767800:1|502835600:1","count":1183,"preSum":25870},{"ndv":235,"upper":"502523708:1|502540302:1","lower":"502520703:2|502588502:2","count":1322,"preSum":27053},{"ndv":183,"upper":"502523908:1","lower":"502523708:1|502540302:1|502542201:2|502597300:1|502624601:2|502740801:1|502757900:2|502787600:4","count":1341,"preSum":28375},{"ndv":281,"upper":"502536603:1|502692501:1|502699201:7|502715101:1|502754601:1|502754801:1|6165273:1","lower":"502523908:1|502524002:1","count":1270,"preSum":29716},{"ndv":69,"upper":"502536901:1|502699102:2","lower":"502536603:1|502692501:1|502699201:7|502715101:1|502754601:1|502754801:1|6165273:2","count":1207,"preSum":30986},{"ndv":290,"upper":"502543602:1|502672802:1","lower":"502536901:1|502699102:2|502700002:1","count":1198,"preSum":32193},{"ndv":401,"upper":"502575902:1|502576003:1|502576102:1|502580502:5|502658601:4","lower":"502543602:1|502672802:1|502764000:1","count":1181,"preSum":33391},{"ndv":229,"upper":"502582805:1|502582904:2|502611102:1","lower":"502575902:1|502576003:1|502576102:1|502580502:7|502658601:1","count":1180,"preSum":34572},{"ndv":199,"upper":"502582805:5|6165113:1|6165115:1","lower":"502582805:1|502582904:2|502755500:3","count":1230,"preSum":35752},{"ndv":310,"upper":"502586202:1","lower":"502582805:5|6165114:1","count":1180,"preSum":36982},{"ndv":72,"upper":"502588103:2","lower":"502586202:1|502586303:1|502645000:2|502760900:1","count":1189,"preSum":38162},{"ndv":378,"upper":"502597300:1|502750104:1|502787600:4","lower":"502588103:2|502588300:2|502588400:2","count":1180,"preSum":39351},{"ndv":24,"upper":"502597300:1|502787600:5","lower":"502597300:1|502750104:1|502787600:5","count":1184,"preSum":40531},{"ndv":292,"upper":"502622207:1|502642604:4|502750100:2","lower":"502597300:1|502787600:5|502985463:1","count":1228,"preSum":41715},{"ndv":169,"upper":"502642604:1|502731301:1|502791100:2|502904900:1","lower":"502622207:1|502642604:4|502750100:2|502750104:1","count":1180,"preSum":42943},{"ndv":129,"upper":"502651401:1|502699002:3|6165469:1","lower":"502642604:1|502750104:1","count":1180,"preSum":44123},{"ndv":142,"upper":"502668704:1|502668804:1|502668904:1|502669004:2|502697804:1","lower":"502651401:1|502699200:1|502764100:1","count":1230,"preSum":45303},{"ndv":146,"upper":"502668704:1|502699102:3","lower":"502668704:1|502668804:1|502668904:1|502669004:2|502697804:1|502699002:6|502699402:6","count":1479,"preSum":46533},{"ndv":190,"upper":"502668704:4|502668804:2|502669004:2|502699200:2","lower":"502668704:1|502699102:3|502725500:1","count":1272,"preSum":48012},{"ndv":65,"upper":"502668704:6|502699002:6","lower":"502668704:4|502668804:2|502669004:2|502699200:2|6165273:1","count":1181,"preSum":49284},{"ndv":198,"upper":"502671602:1|502671702:1|502672104:1|502672304:1|502692900:1|502699002:2|502754501:1|502754701:1|502754901:1","lower":"502668704:6|502699200:2","count":1180,"preSum":50465},{"ndv":134,"upper":"502672104:1|502672400:1|502692900:1","lower":"502671602:1|502671702:1|502684503:5|502699002:2|502725500:1|502754501:1|502754701:1|502754901:1","count":1181,"preSum":51645},{"ndv":154,"upper":"502684505:5|502725500:1","lower":"502672104:1|502672400:1|502754000:1","count":1628,"preSum":52826},{"ndv":122,"upper":"502693700:1|502731300:1","lower":"502684505:5|502725500:1|502729900:1|502788100:1","count":1300,"preSum":54454},{"ndv":58,"upper":"502693900:1|502694000:1|502762700:1|6165195:1","lower":"502693700:1|502731300:1|502755900:1","count":1423,"preSum":55754},{"ndv":39,"upper":"502693900:2|502755900:1|502762700:1|6165082:1|6165195:1","lower":"502693900:1|502694000:1|502762700:1|6165296:1","count":1352,"preSum":57177},{"ndv":68,"upper":"502694100:2|502755900:1|502762701:1|6165195:1","lower":"502693900:2|502755900:1|502762700:1|6165195:1","count":1181,"preSum":58529},{"ndv":277,"upper":"502703500:1","lower":"502694200:1","count":1194,"preSum":59710},{"ndv":122,"upper":"502724700:1","lower":"502703501:1","count":1256,"preSum":60904},{"ndv":9,"upper":"502725500:1","lower":"502724700:1|502725500:1","count":1291,"preSum":62160},{"ndv":241,"upper":"502736100:2","lower":"502725500:1|502732000:1|502736100:2|502776700:2","count":1188,"preSum":63451},{"ndv":87,"upper":"502750104:3","lower":"502736100:2|502750104:2|502755900:2","count":1384,"preSum":64639},{"ndv":96,"upper":"502755500:2|502976583:1","lower":"502750104:3|502754400:6|6165091:1","count":1215,"preSum":66023},{"ndv":93,"upper":"502775500:2|502775700:2|502775800:1","lower":"502755500:2|6164659:1","count":1202,"preSum":67238},{"ndv":64,"upper":"502791100:2","lower":"502775500:2|502775700:2|502775800:1|502787600:2","count":1365,"preSum":68440},{"ndv":42,"upper":"502985463:1","lower":"502791100:20|6165091:2|6165275:2","count":1243,"preSum":69805},{"ndv":502,"upper":"512000300:2|512007100:6|512015800:6|6165349:1","lower":"502985463:2","count":1181,"preSum":71048},{"ndv":322,"upper":"512004300:1","lower":"512000300:3|512001202:25","count":1187,"preSum":72229},{"ndv":98,"upper":"6165097:1","lower":"512004300:16|512006900:4|512020100:1|6165349:1","count":1207,"preSum":73416},{"ndv":393,"upper":"自然堂雪肌美白保湿洁面霜120g:336","lower":"6165115:1","count":890,"preSum":74623}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[886,931,959,1085,728,908,888,931,1110,2396,4027,865,3920,1280],"valueArr":["502220203:1","502476708:10","502523708:1|502740801:2","502536603:1|502692900:1|502715300:1|502755100:2|502755300:2|502755400:2","502536603:1|502692900:1|502715300:1|502755101:2|502755301:2|502755401:2","502582805:2","502582805:6","502586901:1|502588103:1|502622207:1|502642604:6","502668704:4|502668804:2|502669004:2|502699402:2","502668704:4|502668804:4|502668904:4|502669004:4|502697804:4","502700002:1","502700002:2","502725500:2","502791100:6"],"type":"String","sampleRate":0.9618625319816094}',3574,0.02436278),('jala_wms_prod','shipment_header','sourceerp',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[98415,1469],"valueArr":["QIMEN","SAP"],"type":"String","sampleRate":0.9618625319816094}',117,0.02436278),('jala_wms_prod','shipment_header','sourceerpcode',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[95364,3051],"valueArr":["JALA-ECS","JALA-YPH"],"type":"String","sampleRate":0.9618625319816094}',1586,0.02436278),('jala_wms_prod','shipment_header','sourceordercode',2299540,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1484,"upper":"1832796696057094168","lower":"100441022058559!FP099111129996578","count":1488,"preSum":0},{"ndv":1488,"upper":"1870914072078718963","lower":"1832801844266336280","count":1488,"preSum":1488},{"ndv":1487,"upper":"1878563534491514493","lower":"1870915838900151970","count":1488,"preSum":2976},{"ndv":1488,"upper":"1880530357673255970","lower":"1878565514951295680","count":1488,"preSum":4464},{"ndv":1487,"upper":"1886573463828438884","lower":"1880537955827870398","count":1488,"preSum":5952},{"ndv":1487,"upper":"1891617386250503291","lower":"1886573642968694487","count":1488,"preSum":7440},{"ndv":1487,"upper":"1896297672938324060","lower":"1891617421264297999","count":1488,"preSum":8928},{"ndv":1487,"upper":"1896932895443324474","lower":"1896297744703205393","count":1488,"preSum":10416},{"ndv":1485,"upper":"1897159911391977078","lower":"1896933075205745186","count":1488,"preSum":11904},{"ndv":1486,"upper":"1899880248729178380","lower":"1897159911558262388","count":1488,"preSum":13392},{"ndv":1487,"upper":"1903179900573515760","lower":"1899881113496508775","count":1488,"preSum":14880},{"ndv":1488,"upper":"1906452120502540768","lower":"1903182026331931066","count":1488,"preSum":16368},{"ndv":1487,"upper":"1911852949699587799","lower":"1906452228701774495","count":1488,"preSum":17856},{"ndv":1487,"upper":"1915038300444831789","lower":"1911858169226630586","count":1488,"preSum":19344},{"ndv":1488,"upper":"1917194269746866291","lower":"1915040388757471789","count":1488,"preSum":20832},{"ndv":1488,"upper":"1920912277996478287","lower":"1917195636641733393","count":1488,"preSum":22320},{"ndv":1487,"upper":"23042577504774","lower":"1920915192436995579","count":1488,"preSum":23808},{"ndv":1488,"upper":"23050999937184","lower":"23042578879844","count":1488,"preSum":25296},{"ndv":1488,"upper":"23052207024716","lower":"230510-020599315363899","count":1488,"preSum":26784},{"ndv":1488,"upper":"23060345827289","lower":"23052214902216","count":1488,"preSum":28272},{"ndv":1488,"upper":"23061661983868","lower":"23060345941735","count":1488,"preSum":29760},{"ndv":1488,"upper":"2311400211532013","lower":"23061662381768","count":1488,"preSum":31248},{"ndv":1487,"upper":"265109333115","lower":"2311400220662942","count":1488,"preSum":32736},{"ndv":1488,"upper":"271354654999","lower":"265121474335","count":1488,"preSum":34224},{"ndv":1487,"upper":"273652656707","lower":"271357049749","count":1488,"preSum":35712},{"ndv":1487,"upper":"275952971620","lower":"273652670410","count":1488,"preSum":37200},{"ndv":1488,"upper":"3216250756380122640","lower":"275954711457","count":1488,"preSum":38688},{"ndv":1488,"upper":"3253389915328772966","lower":"3216280708884438531","count":1488,"preSum":40176},{"ndv":1488,"upper":"3303233535067337330","lower":"3253394379555697754","count":1488,"preSum":41664},{"ndv":1486,"upper":"3316790414389889312","lower":"3303234219367598236","count":1488,"preSum":43152},{"ndv":1487,"upper":"3324843001075210158","lower":"3316791099092567425","count":1488,"preSum":44640},{"ndv":1485,"upper":"3329766468219849727","lower":"3324846206548751613","count":1488,"preSum":46128},{"ndv":1486,"upper":"3330725331991742448","lower":"3329766468232630755","count":1488,"preSum":47616},{"ndv":1487,"upper":"3335242791101210534","lower":"3330725617326611401","count":1488,"preSum":49104},{"ndv":1487,"upper":"3342451248808912215","lower":"3335244015638576434","count":1488,"preSum":50592},{"ndv":1488,"upper":"3348816265556925210","lower":"3342451287310895604","count":1488,"preSum":52080},{"ndv":1487,"upper":"3353116359969470244","lower":"3348822459373553628","count":1488,"preSum":53568},{"ndv":1487,"upper":"3360427886170082604","lower":"3353118591755637038","count":1488,"preSum":55056},{"ndv":1487,"upper":"3364122168698182337","lower":"3360431163950684002","count":1488,"preSum":56544},{"ndv":1484,"upper":"3364668794474229004","lower":"3364122169573681207","count":1488,"preSum":58032},{"ndv":1484,"upper":"3365067567026386163","lower":"3364668859558505045","count":1488,"preSum":59520},{"ndv":1486,"upper":"3367758457938200922","lower":"3365068215676692337","count":1488,"preSum":61008},{"ndv":1487,"upper":"3371323467724740322","lower":"3367766593621231455","count":1488,"preSum":62496},{"ndv":1486,"upper":"3374711209087921150","lower":"3371325159468704049","count":1488,"preSum":63984},{"ndv":1486,"upper":"3378245655807206345","lower":"3374713873685823049","count":1488,"preSum":65472},{"ndv":1487,"upper":"3382461252151375702","lower":"3378246517737930306","count":1488,"preSum":66960},{"ndv":1487,"upper":"3389513149652996348","lower":"3382465464002934131","count":1488,"preSum":68448},{"ndv":1488,"upper":"3395248130692842601","lower":"3389515921178741823","count":1488,"preSum":69936},{"ndv":1487,"upper":"3398021103902802007","lower":"3395251766420358615","count":1488,"preSum":71424},{"ndv":1487,"upper":"3400202739026952945","lower":"3398021388956795402","count":1488,"preSum":72912},{"ndv":1488,"upper":"3402294913041316618","lower":"3400203565788352452","count":1488,"preSum":74400},{"ndv":1487,"upper":"3408325382768461156","lower":"3402296282880252556","count":1488,"preSum":75888},{"ndv":1488,"upper":"6917841557550602009","lower":"3408327792453859017","count":1488,"preSum":77376},{"ndv":1485,"upper":"6918025457652995233","lower":"6917842073163536334","count":1488,"preSum":78864},{"ndv":1486,"upper":"6918177551963854376","lower":"6918025705434649833","count":1488,"preSum":80352},{"ndv":1488,"upper":"6918330850433766892","lower":"6918177745710224832","count":1488,"preSum":81840},{"ndv":1487,"upper":"6918511796987237907","lower":"6918331157666928560","count":1488,"preSum":83328},{"ndv":1484,"upper":"6918702940928153306","lower":"6918511842102482787","count":1488,"preSum":84816},{"ndv":1487,"upper":"6918920943156270532","lower":"6918702983504795070","count":1488,"preSum":86304},{"ndv":1488,"upper":"6919067064000452504","lower":"6918920968230868445","count":1488,"preSum":87792},{"ndv":1488,"upper":"6919248606522709645","lower":"6919067420611384915","count":1488,"preSum":89280},{"ndv":1488,"upper":"6919410566841701488","lower":"6919248639676912891","count":1488,"preSum":90768},{"ndv":1488,"upper":"6919562240896472971","lower":"6919410614726629151","count":1488,"preSum":92256},{"ndv":1450,"upper":"XXY2023052337","lower":"6919562578720004018","count":1451,"preSum":93744}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[177],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',4629,0.02436278),('jala_wms_prod','shipment_header','sourceplatform',9,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[11,5614,15670,6295,1197,6918,879,61751,92],"valueArr":["","*","DOUYIN","JD","KUAISHOU","MP","PDD","TB","VIP"],"type":"String","sampleRate":0.9618625319816094}',1574,0.02436278),('jala_wms_prod','shipment_header','splitorderidentification',1016,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"2585938","lower":"2459261","count":2,"preSum":0},{"ndv":2,"upper":"2602225","lower":"2586005","count":2,"preSum":2},{"ndv":2,"upper":"2602228","lower":"2602227","count":2,"preSum":4},{"ndv":2,"upper":"2602369","lower":"2602236","count":2,"preSum":6},{"ndv":1,"upper":"2604100","lower":"2604100","count":2,"preSum":8},{"ndv":2,"upper":"2605022","lower":"2605021","count":2,"preSum":10},{"ndv":2,"upper":"2605025","lower":"2605023","count":2,"preSum":12},{"ndv":1,"upper":"2605099","lower":"2605099","count":2,"preSum":14},{"ndv":2,"upper":"2605666","lower":"2605665","count":2,"preSum":16},{"ndv":2,"upper":"2645301","lower":"2605677","count":2,"preSum":18},{"ndv":1,"upper":"2646282","lower":"2646282","count":2,"preSum":20},{"ndv":2,"upper":"2700631","lower":"2683155","count":2,"preSum":22},{"ndv":2,"upper":"2776471","lower":"2722610","count":2,"preSum":24},{"ndv":2,"upper":"2828385","lower":"2781296","count":2,"preSum":26},{"ndv":2,"upper":"2943564","lower":"2942732","count":2,"preSum":28},{"ndv":2,"upper":"3038058","lower":"3038057","count":3,"preSum":30},{"ndv":2,"upper":"3233189","lower":"3121239","count":2,"preSum":33},{"ndv":2,"upper":"3302917","lower":"3302048","count":2,"preSum":35},{"ndv":2,"upper":"3412927","lower":"3395747","count":2,"preSum":37},{"ndv":2,"upper":"3412948","lower":"3412936","count":2,"preSum":39},{"ndv":2,"upper":"3412971","lower":"3412959","count":2,"preSum":41},{"ndv":2,"upper":"3413051","lower":"3412993","count":2,"preSum":43},{"ndv":2,"upper":"3413116","lower":"3413055","count":2,"preSum":45},{"ndv":2,"upper":"3531920","lower":"3421876","count":2,"preSum":47},{"ndv":2,"upper":"3531985","lower":"3531981","count":2,"preSum":49},{"ndv":2,"upper":"3970683","lower":"3532154","count":2,"preSum":51},{"ndv":2,"upper":"3971926","lower":"3971925","count":2,"preSum":53},{"ndv":2,"upper":"3973028","lower":"3973025","count":2,"preSum":55},{"ndv":1,"upper":"3973072","lower":"3973072","count":2,"preSum":57},{"ndv":2,"upper":"4176632","lower":"4152939","count":2,"preSum":59},{"ndv":2,"upper":"4218528","lower":"4218526","count":2,"preSum":61},{"ndv":2,"upper":"4227811","lower":"4225496","count":2,"preSum":63},{"ndv":2,"upper":"4229420","lower":"4229092","count":2,"preSum":65},{"ndv":2,"upper":"4422425","lower":"4229940","count":2,"preSum":67},{"ndv":2,"upper":"4960907","lower":"4438806","count":3,"preSum":69},{"ndv":2,"upper":"4992776","lower":"4971652","count":2,"preSum":72},{"ndv":2,"upper":"4997567","lower":"4992777","count":2,"preSum":74},{"ndv":1,"upper":"5175078","lower":"5175078","count":2,"preSum":76},{"ndv":2,"upper":"5488127","lower":"5473702","count":2,"preSum":78},{"ndv":2,"upper":"5531409","lower":"5531397","count":2,"preSum":80},{"ndv":2,"upper":"5533274","lower":"5531507","count":2,"preSum":82},{"ndv":2,"upper":"5533284","lower":"5533279","count":2,"preSum":84},{"ndv":2,"upper":"5535303","lower":"5533285","count":2,"preSum":86},{"ndv":2,"upper":"5592320","lower":"5590095","count":2,"preSum":88},{"ndv":2,"upper":"5599061","lower":"5599059","count":2,"preSum":90},{"ndv":2,"upper":"5599071","lower":"5599069","count":3,"preSum":92},{"ndv":2,"upper":"5798389","lower":"5737664","count":2,"preSum":95},{"ndv":2,"upper":"5837619","lower":"5831069","count":2,"preSum":97},{"ndv":2,"upper":"5839168","lower":"5839166","count":2,"preSum":99},{"ndv":2,"upper":"5839201","lower":"5839192","count":2,"preSum":101},{"ndv":2,"upper":"5839204","lower":"5839203","count":2,"preSum":103},{"ndv":2,"upper":"5843201","lower":"5839205","count":2,"preSum":105},{"ndv":2,"upper":"7502017","lower":"5843777","count":2,"preSum":107},{"ndv":2,"upper":"7773520","lower":"7773519","count":2,"preSum":109},{"ndv":2,"upper":"8343228","lower":"8223662","count":2,"preSum":111}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,99888,0.02436278),('jala_wms_prod','shipment_header','stageloc',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','stamp',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','stampindex',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','statusflow',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":["default"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','stopseq',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','storecode',183,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"75201","lower":"","count":308,"preSum":0},{"ndv":5,"upper":"75304","lower":"75201-1","count":208,"preSum":308},{"ndv":1,"upper":"75420","lower":"75420","count":494,"preSum":516},{"ndv":1,"upper":"75424","lower":"75424","count":344,"preSum":1010},{"ndv":3,"upper":"75429","lower":"75424-1","count":260,"preSum":1354},{"ndv":5,"upper":"75450","lower":"75435","count":343,"preSum":1614},{"ndv":2,"upper":"75452","lower":"75451","count":539,"preSum":1957},{"ndv":8,"upper":"75474","lower":"75453","count":358,"preSum":2496},{"ndv":6,"upper":"75480","lower":"75474-1","count":265,"preSum":2854},{"ndv":2,"upper":"75485-1","lower":"75481","count":586,"preSum":3119},{"ndv":3,"upper":"75495","lower":"75492-1","count":458,"preSum":3705},{"ndv":1,"upper":"75496","lower":"75496","count":285,"preSum":4163},{"ndv":3,"upper":"75501","lower":"75499","count":491,"preSum":4448},{"ndv":1,"upper":"75502","lower":"75502","count":436,"preSum":4939},{"ndv":1,"upper":"75506","lower":"75506","count":316,"preSum":5375},{"ndv":1,"upper":"75507","lower":"75507","count":275,"preSum":5691},{"ndv":1,"upper":"75508","lower":"75508","count":204,"preSum":5966},{"ndv":1,"upper":"75511","lower":"75511","count":653,"preSum":6170},{"ndv":2,"upper":"75514","lower":"75513","count":694,"preSum":6823},{"ndv":1,"upper":"75515","lower":"75515","count":323,"preSum":7517},{"ndv":2,"upper":"75517","lower":"75516","count":592,"preSum":7840},{"ndv":2,"upper":"75519","lower":"75518","count":549,"preSum":8432},{"ndv":1,"upper":"75520","lower":"75520","count":213,"preSum":8981},{"ndv":2,"upper":"75522","lower":"75521","count":363,"preSum":9194},{"ndv":4,"upper":"75530","lower":"75523","count":207,"preSum":9557},{"ndv":2,"upper":"75539","lower":"75536","count":244,"preSum":9764},{"ndv":1,"upper":"75541","lower":"75541","count":420,"preSum":10008},{"ndv":8,"upper":"75549","lower":"75541-1","count":214,"preSum":10428},{"ndv":5,"upper":"75571","lower":"75552-1","count":218,"preSum":10642},{"ndv":3,"upper":"75577-1","lower":"75572","count":205,"preSum":10860},{"ndv":6,"upper":"75602","lower":"75578","count":802,"preSum":11065},{"ndv":17,"upper":"75662","lower":"75604","count":424,"preSum":11867},{"ndv":9,"upper":"75689","lower":"75668","count":291,"preSum":12291}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[44603,1268,1227,1175,11212,995,6924,1014,833,1123,680,1578,2151,2932],"valueArr":["75202","75202-1","75216","75438","75485","75489","75492","75494","75500","75505","75510","75512","75552","75577"],"type":"String","sampleRate":0.9618625319816094}',9704,0.02436278),('jala_wms_prod','shipment_header','storename',160,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":10,"upper":"全品牌-人资福利店铺","lower":"Chando-LazadaMYHimalaya","count":266,"preSum":0},{"ndv":9,"upper":"春夏-天猫旗舰店","lower":"全品牌-优礼汇特通店铺","count":469,"preSum":266},{"ndv":2,"upper":"春夏-抖音小店","lower":"春夏-快手品牌官方店","count":196,"preSum":735},{"ndv":4,"upper":"珀芙研-云店","lower":"植物智慧-天猫旗舰店","count":240,"preSum":931},{"ndv":5,"upper":"珀芙研-抖音小店","lower":"珀芙研-京东POP旗舰店","count":287,"preSum":1171},{"ndv":3,"upper":"珀芙研-蘑菇街旗舰店","lower":"珀芙研-泛斯特店","count":646,"preSum":1458},{"ndv":2,"upper":"美素-天猫旗舰店","lower":"美素-京东POP官方旗舰店","count":371,"preSum":2104},{"ndv":4,"upper":"自然堂-云店(官方商城)","lower":"美素-抖音小店","count":375,"preSum":2475},{"ndv":3,"upper":"自然堂-京东乐肤迪官方旗舰店","lower":"自然堂-云店(美妆2.0)","count":349,"preSum":2850},{"ndv":1,"upper":"自然堂-京东充花专卖店","lower":"自然堂-京东充花专卖店","count":343,"preSum":3199},{"ndv":1,"upper":"自然堂-京东彧弈美妆专营店","lower":"自然堂-京东彧弈美妆专营店","count":338,"preSum":3542},{"ndv":2,"upper":"自然堂-京东悦悦美铺化妆品专营店","lower":"自然堂-京东思琪化妆品专营店","count":303,"preSum":3880},{"ndv":5,"upper":"自然堂-京东每妆护肤旗舰店","lower":"自然堂-京东晟妆专卖店","count":331,"preSum":4183},{"ndv":2,"upper":"自然堂-京东然美专卖店","lower":"自然堂-京东泽品美妆化妆品专营店","count":383,"preSum":4514},{"ndv":1,"upper":"自然堂-京东硕齐化妆品专营店","lower":"自然堂-京东硕齐化妆品专营店","count":328,"preSum":4897},{"ndv":1,"upper":"自然堂-京东美姿专卖店","lower":"自然堂-京东美姿专卖店","count":748,"preSum":5225},{"ndv":1,"upper":"自然堂-京东美爆化妆品专营店","lower":"自然堂-京东美爆化妆品专营店","count":432,"preSum":5973},{"ndv":4,"upper":"自然堂-品牌专卖1店","lower":"自然堂-京东美轩美妆","count":304,"preSum":6405},{"ndv":1,"upper":"自然堂-品牌专卖2店","lower":"自然堂-品牌专卖2店","count":432,"preSum":6709},{"ndv":5,"upper":"自然堂-天猫伊恋化妆品专营店","lower":"自然堂-品牌专卖3店","count":581,"preSum":7141},{"ndv":2,"upper":"自然堂-天猫俏美人专卖店","lower":"自然堂-天猫优购化妆品专营店","count":362,"preSum":7722},{"ndv":2,"upper":"自然堂-天猫名轩专卖店","lower":"自然堂-天猫博美化妆品专营店","count":591,"preSum":8084},{"ndv":1,"upper":"自然堂-天猫思琪化妆品专营店","lower":"自然堂-天猫思琪化妆品专营店","count":700,"preSum":8675},{"ndv":1,"upper":"自然堂-天猫永信化妆品专营店","lower":"自然堂-天猫永信化妆品专营店","count":247,"preSum":9375},{"ndv":1,"upper":"自然堂-天猫泽品化妆品专营店","lower":"自然堂-天猫泽品化妆品专营店","count":243,"preSum":9622},{"ndv":1,"upper":"自然堂-天猫硕齐化妆品专营店","lower":"自然堂-天猫硕齐化妆品专营店","count":457,"preSum":9865},{"ndv":2,"upper":"自然堂-小红书旗舰店","lower":"自然堂-小程序官方商城","count":528,"preSum":10322},{"ndv":1,"upper":"自然堂-抖音CHANDO男士旗舰店","lower":"自然堂-抖音CHANDO男士旗舰店","count":434,"preSum":10850},{"ndv":16,"upper":"自然堂-淘宝e购女孩","lower":"自然堂-拼多多丽友专卖店","count":194,"preSum":11284},{"ndv":3,"upper":"自然堂-淘宝美丽会客厅","lower":"自然堂-淘宝zhangmin811028","count":195,"preSum":11478},{"ndv":1,"upper":"自然堂-考拉旗舰店","lower":"自然堂-考拉旗舰店","count":249,"preSum":11673},{"ndv":3,"upper":"莎辛那-天猫旗舰店","lower":"自然堂-蘑菇街旗舰店","count":205,"preSum":11922}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[3064,1273,1474,1142,6928,49240,1729,758,1250,2317,1093,1012,11899,3121],"valueArr":["","珀芙研-天猫旗舰店","自然堂-京东POP旗舰店","自然堂-京东京品美妆专卖店","自然堂-唯品会自营旗舰店(中国)","自然堂-天猫旗舰店","自然堂-天猫朵纯专卖店","自然堂-天猫杰宸专卖店","自然堂-天猫然美专卖店","自然堂-天猫男士旗舰店","自然堂-天猫门萨专卖店","自然堂-快手官方旗舰店","自然堂-抖音官方旗舰店","自然堂-抖音美妆旗舰店"],"type":"String","sampleRate":0.9618625319816094}',1574,0.02436278),('jala_wms_prod','shipment_header','temperaturecontrol',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[98443],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',1558,0.02436278),('jala_wms_prod','shipment_header','templevel',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','text',11,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"二次取样","lower":"二次取样","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[4,57],"valueArr":["","0"],"type":"String","sampleRate":0.9618625319816094}',99939,0.02436278),('jala_wms_prod','shipment_header','thirdsectioncode',14698,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":11,"upper":"004","lower":"00","count":66,"preSum":0},{"ndv":10,"upper":"009","lower":"005","count":62,"preSum":66},{"ndv":13,"upper":"017","lower":"010","count":60,"preSum":128},{"ndv":26,"upper":"023-090-999 06","lower":"018","count":58,"preSum":188},{"ndv":41,"upper":"02A","lower":"0230-008-999 02","count":58,"preSum":246},{"ndv":25,"upper":"043","lower":"02D","count":58,"preSum":304},{"ndv":31,"upper":"063","lower":"044","count":58,"preSum":362},{"ndv":22,"upper":"08","lower":"065","count":75,"preSum":420},{"ndv":21,"upper":"096","lower":"080","count":59,"preSum":495},{"ndv":26,"upper":"105","lower":"098","count":61,"preSum":554},{"ndv":17,"upper":"112","lower":"1053","count":60,"preSum":615},{"ndv":27,"upper":"13","lower":"1120","count":74,"preSum":675},{"ndv":24,"upper":"15","lower":"1304","count":71,"preSum":749},{"ndv":24,"upper":"170","lower":"150","count":58,"preSum":820},{"ndv":28,"upper":"201","lower":"170P","count":59,"preSum":878},{"ndv":23,"upper":"22","lower":"202","count":79,"preSum":937},{"ndv":22,"upper":"24","lower":"221","count":60,"preSum":1016},{"ndv":17,"upper":"267","lower":"240","count":58,"preSum":1076},{"ndv":18,"upper":"3","lower":"26A","count":59,"preSum":1134},{"ndv":20,"upper":"318","lower":"30","count":58,"preSum":1193},{"ndv":15,"upper":"338","lower":"319","count":58,"preSum":1251},{"ndv":33,"upper":"35A","lower":"339","count":58,"preSum":1309},{"ndv":22,"upper":"38","lower":"35B","count":64,"preSum":1367},{"ndv":34,"upper":"404","lower":"384","count":60,"preSum":1431},{"ndv":22,"upper":"427-015-999 10","lower":"405","count":58,"preSum":1491},{"ndv":24,"upper":"44","lower":"427-020-999 02","count":59,"preSum":1549},{"ndv":31,"upper":"49","lower":"444","count":62,"preSum":1608},{"ndv":27,"upper":"515","lower":"490","count":58,"preSum":1670},{"ndv":39,"upper":"537-021-001 13","lower":"516","count":58,"preSum":1728},{"ndv":40,"upper":"555","lower":"537-022-002","count":66,"preSum":1786},{"ndv":29,"upper":"59","lower":"5555","count":64,"preSum":1852},{"ndv":34,"upper":"61","lower":"591","count":64,"preSum":1916},{"ndv":20,"upper":"65","lower":"6101","count":60,"preSum":1980},{"ndv":17,"upper":"67A","lower":"656","count":58,"preSum":2040},{"ndv":22,"upper":"714-014-999 06","lower":"67M","count":58,"preSum":2098},{"ndv":38,"upper":"731-091-999 01","lower":"714-022-999 01","count":58,"preSum":2156},{"ndv":37,"upper":"769-081-999 01","lower":"731-113-999","count":58,"preSum":2214},{"ndv":34,"upper":"7777","lower":"769-082-999 09","count":58,"preSum":2272},{"ndv":24,"upper":"800","lower":"779","count":58,"preSum":2330},{"ndv":33,"upper":"832","lower":"8001","count":58,"preSum":2388},{"ndv":27,"upper":"871-019-999 06","lower":"834-083-999 03","count":58,"preSum":2446},{"ndv":25,"upper":"8893","lower":"871-020-999 01","count":58,"preSum":2504},{"ndv":26,"upper":"920","lower":"8898","count":58,"preSum":2562},{"ndv":26,"upper":"98A","lower":"921","count":58,"preSum":2620},{"ndv":28,"upper":"A04","lower":"99","count":58,"preSum":2678},{"ndv":36,"upper":"A17-064-002","lower":"A05","count":58,"preSum":2736},{"ndv":43,"upper":"A60","lower":"A17-128-999 01","count":58,"preSum":2794},{"ndv":51,"upper":"B004","lower":"A61","count":58,"preSum":2852},{"ndv":36,"upper":"B25","lower":"B006","count":58,"preSum":2910},{"ndv":51,"upper":"C05","lower":"B25B","count":58,"preSum":2968},{"ndv":42,"upper":"C88","lower":"C06","count":58,"preSum":3026},{"ndv":49,"upper":"D5","lower":"C99","count":59,"preSum":3084},{"ndv":37,"upper":"DS70","lower":"D51","count":58,"preSum":3143},{"ndv":45,"upper":"F04","lower":"DS72","count":58,"preSum":3201},{"ndv":48,"upper":"G11","lower":"F09","count":59,"preSum":3259},{"ndv":52,"upper":"HM","lower":"G12","count":58,"preSum":3318},{"ndv":51,"upper":"K55C","lower":"HNZ","count":58,"preSum":3376},{"ndv":52,"upper":"N03","lower":"K58","count":58,"preSum":3434},{"ndv":49,"upper":"S4","lower":"N05","count":58,"preSum":3492},{"ndv":51,"upper":"W2","lower":"S5","count":58,"preSum":3550},{"ndv":52,"upper":"Y149","lower":"W25","count":58,"preSum":3608},{"ndv":35,"upper":"ZZZ","lower":"Y2","count":39,"preSum":3666}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[32,29,35,33,35,38,32,34,28,30,35,27,30],"valueArr":["01","02","03","04","05","06","10","11","12","16","18","20","55"],"type":"String","sampleRate":0.9618625319816094}',95878,0.02436278),('jala_wms_prod','shipment_header','thrureceiptcode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[30],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','totalcases',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalconqty',1339,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":7,"lower":7,"count":13,"preSum":0},{"ndv":1,"upper":13,"lower":13,"count":10,"preSum":13},{"ndv":1,"upper":15,"lower":15,"count":12,"preSum":23},{"ndv":1,"upper":16,"lower":16,"count":12,"preSum":35},{"ndv":1,"upper":17,"lower":17,"count":10,"preSum":47},{"ndv":1,"upper":18,"lower":18,"count":11,"preSum":57},{"ndv":1,"upper":19,"lower":19,"count":8,"preSum":68},{"ndv":2,"upper":22,"lower":21,"count":8,"preSum":76},{"ndv":2,"upper":24,"lower":23,"count":11,"preSum":84},{"ndv":1,"upper":25,"lower":25,"count":8,"preSum":95},{"ndv":2,"upper":27,"lower":26,"count":8,"preSum":103},{"ndv":2,"upper":30,"lower":28,"count":11,"preSum":111},{"ndv":3,"upper":33,"lower":31,"count":8,"preSum":122},{"ndv":3,"upper":36,"lower":34,"count":10,"preSum":130},{"ndv":3,"upper":39,"lower":37,"count":8,"preSum":140},{"ndv":4,"upper":45,"lower":40,"count":11,"preSum":148},{"ndv":4,"upper":49,"lower":46,"count":11,"preSum":159},{"ndv":1,"upper":50,"lower":50,"count":7,"preSum":170},{"ndv":2,"upper":52,"lower":51,"count":8,"preSum":177},{"ndv":2,"upper":55,"lower":54,"count":7,"preSum":185},{"ndv":3,"upper":58,"lower":56,"count":9,"preSum":192},{"ndv":3,"upper":61,"lower":59,"count":7,"preSum":201},{"ndv":2,"upper":63,"lower":62,"count":9,"preSum":208},{"ndv":3,"upper":67,"lower":65,"count":9,"preSum":217},{"ndv":3,"upper":71,"lower":68,"count":7,"preSum":226},{"ndv":3,"upper":75,"lower":72,"count":7,"preSum":233},{"ndv":5,"upper":80,"lower":76,"count":8,"preSum":240},{"ndv":5,"upper":87,"lower":82,"count":8,"preSum":248},{"ndv":4,"upper":91,"lower":88,"count":7,"preSum":256},{"ndv":6,"upper":97,"lower":92,"count":7,"preSum":263},{"ndv":4,"upper":102,"lower":98,"count":7,"preSum":270},{"ndv":4,"upper":110,"lower":103,"count":7,"preSum":277},{"ndv":4,"upper":118,"lower":114,"count":7,"preSum":284},{"ndv":6,"upper":129,"lower":120,"count":7,"preSum":291},{"ndv":6,"upper":147,"lower":131,"count":7,"preSum":298},{"ndv":6,"upper":160,"lower":148,"count":9,"preSum":305},{"ndv":6,"upper":173,"lower":161,"count":7,"preSum":314},{"ndv":5,"upper":185,"lower":175,"count":7,"preSum":321},{"ndv":6,"upper":204,"lower":188,"count":7,"preSum":328},{"ndv":7,"upper":227,"lower":208,"count":7,"preSum":335},{"ndv":5,"upper":250,"lower":235,"count":7,"preSum":342},{"ndv":7,"upper":275,"lower":257,"count":7,"preSum":349},{"ndv":7,"upper":347,"lower":276,"count":7,"preSum":356},{"ndv":5,"upper":370,"lower":348,"count":7,"preSum":363},{"ndv":7,"upper":414,"lower":384,"count":7,"preSum":370},{"ndv":7,"upper":479,"lower":420,"count":7,"preSum":377},{"ndv":7,"upper":543,"lower":491,"count":7,"preSum":384},{"ndv":7,"upper":666,"lower":556,"count":7,"preSum":391},{"ndv":7,"upper":849,"lower":699,"count":7,"preSum":398},{"ndv":7,"upper":1163,"lower":861,"count":7,"preSum":405},{"ndv":7,"upper":1818,"lower":1191,"count":7,"preSum":412},{"ndv":7,"upper":2631,"lower":1963,"count":7,"preSum":419},{"ndv":3,"upper":4068,"lower":3008,"count":3,"preSum":426}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[98947,273,86,50,33,40,16,23,16,18,19,15,21,15],"valueArr":[0,1,2,3,4,5,6,8,9,10,11,12,14,20],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalcontainers',197,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":12,"lower":12,"count":19,"preSum":0},{"ndv":1,"upper":15,"lower":15,"count":11,"preSum":19},{"ndv":1,"upper":16,"lower":16,"count":3,"preSum":30},{"ndv":1,"upper":17,"lower":17,"count":8,"preSum":33},{"ndv":1,"upper":18,"lower":18,"count":5,"preSum":41},{"ndv":2,"upper":20,"lower":19,"count":6,"preSum":46},{"ndv":1,"upper":21,"lower":21,"count":4,"preSum":52},{"ndv":1,"upper":22,"lower":22,"count":4,"preSum":56},{"ndv":2,"upper":24,"lower":23,"count":3,"preSum":60},{"ndv":1,"upper":25,"lower":25,"count":2,"preSum":63},{"ndv":2,"upper":27,"lower":26,"count":4,"preSum":65},{"ndv":2,"upper":29,"lower":28,"count":2,"preSum":69},{"ndv":1,"upper":30,"lower":30,"count":2,"preSum":71},{"ndv":2,"upper":33,"lower":32,"count":6,"preSum":73},{"ndv":2,"upper":40,"lower":34,"count":2,"preSum":79},{"ndv":2,"upper":47,"lower":46,"count":2,"preSum":81},{"ndv":2,"upper":57,"lower":53,"count":2,"preSum":83},{"ndv":2,"upper":67,"lower":65,"count":2,"preSum":85},{"ndv":2,"upper":70,"lower":68,"count":3,"preSum":87},{"ndv":2,"upper":94,"lower":74,"count":2,"preSum":90},{"ndv":2,"upper":120,"lower":99,"count":2,"preSum":92},{"ndv":2,"upper":196,"lower":134,"count":2,"preSum":94},{"ndv":1,"upper":233,"lower":233,"count":1,"preSum":96}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6247,92283,463,263,163,118,141,47,39,32,33,34,20,21],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,13,14],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalgroupconts',176,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":14,"lower":14,"count":12,"preSum":0},{"ndv":1,"upper":15,"lower":15,"count":6,"preSum":12},{"ndv":2,"upper":17,"lower":16,"count":7,"preSum":18},{"ndv":1,"upper":18,"lower":18,"count":3,"preSum":25},{"ndv":1,"upper":20,"lower":20,"count":3,"preSum":28},{"ndv":1,"upper":21,"lower":21,"count":3,"preSum":31},{"ndv":1,"upper":22,"lower":22,"count":3,"preSum":34},{"ndv":2,"upper":24,"lower":23,"count":3,"preSum":37},{"ndv":1,"upper":25,"lower":25,"count":2,"preSum":40},{"ndv":2,"upper":27,"lower":26,"count":3,"preSum":42},{"ndv":2,"upper":29,"lower":28,"count":2,"preSum":45},{"ndv":1,"upper":30,"lower":30,"count":2,"preSum":47},{"ndv":1,"upper":33,"lower":33,"count":5,"preSum":49},{"ndv":2,"upper":40,"lower":34,"count":2,"preSum":54},{"ndv":2,"upper":47,"lower":46,"count":2,"preSum":56},{"ndv":2,"upper":65,"lower":53,"count":2,"preSum":58},{"ndv":2,"upper":68,"lower":67,"count":2,"preSum":60},{"ndv":1,"upper":70,"lower":70,"count":2,"preSum":62},{"ndv":2,"upper":94,"lower":74,"count":2,"preSum":64},{"ndv":2,"upper":120,"lower":99,"count":2,"preSum":66},{"ndv":2,"upper":196,"lower":134,"count":2,"preSum":68},{"ndv":1,"upper":233,"lower":233,"count":1,"preSum":70}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6247,92398,447,252,148,109,136,43,38,27,29,25,15,16],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totallines',120,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":15,"lower":0,"count":112,"preSum":0},{"ndv":1,"upper":16,"lower":16,"count":81,"preSum":112},{"ndv":1,"upper":17,"lower":17,"count":84,"preSum":193},{"ndv":1,"upper":18,"lower":18,"count":65,"preSum":277},{"ndv":1,"upper":19,"lower":19,"count":48,"preSum":342},{"ndv":1,"upper":20,"lower":20,"count":43,"preSum":390},{"ndv":1,"upper":21,"lower":21,"count":39,"preSum":433},{"ndv":1,"upper":22,"lower":22,"count":26,"preSum":472},{"ndv":1,"upper":23,"lower":23,"count":35,"preSum":498},{"ndv":1,"upper":24,"lower":24,"count":26,"preSum":533},{"ndv":1,"upper":25,"lower":25,"count":16,"preSum":559},{"ndv":1,"upper":26,"lower":26,"count":18,"preSum":575},{"ndv":1,"upper":27,"lower":27,"count":17,"preSum":593},{"ndv":1,"upper":28,"lower":28,"count":14,"preSum":610},{"ndv":1,"upper":29,"lower":29,"count":18,"preSum":624},{"ndv":1,"upper":30,"lower":30,"count":13,"preSum":642},{"ndv":1,"upper":31,"lower":31,"count":16,"preSum":655},{"ndv":1,"upper":32,"lower":32,"count":13,"preSum":671},{"ndv":2,"upper":34,"lower":33,"count":16,"preSum":684},{"ndv":2,"upper":36,"lower":35,"count":23,"preSum":700},{"ndv":3,"upper":39,"lower":37,"count":13,"preSum":723},{"ndv":1,"upper":40,"lower":40,"count":16,"preSum":736},{"ndv":3,"upper":43,"lower":41,"count":14,"preSum":752},{"ndv":2,"upper":45,"lower":44,"count":14,"preSum":766},{"ndv":4,"upper":50,"lower":46,"count":13,"preSum":780},{"ndv":6,"upper":58,"lower":51,"count":13,"preSum":793},{"ndv":8,"upper":76,"lower":59,"count":14,"preSum":806},{"ndv":2,"upper":96,"lower":85,"count":2,"preSum":820}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[31033,21232,11437,9767,9725,5918,2724,1769,1016,776,703,624,2250,205],"valueArr":[1,2,3,4,5,6,7,8,9,10,11,12,13,14],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalqty',4605,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":13,"lower":0,"count":1076,"preSum":0},{"ndv":1,"upper":14,"lower":14,"count":685,"preSum":1076},{"ndv":1,"upper":16,"lower":16,"count":744,"preSum":1761},{"ndv":1,"upper":17,"lower":17,"count":924,"preSum":2505},{"ndv":1,"upper":18,"lower":18,"count":319,"preSum":3429},{"ndv":1,"upper":19,"lower":19,"count":260,"preSum":3748},{"ndv":1,"upper":21,"lower":21,"count":131,"preSum":4008},{"ndv":1,"upper":22,"lower":22,"count":117,"preSum":4139},{"ndv":2,"upper":24,"lower":23,"count":156,"preSum":4256},{"ndv":4,"upper":28,"lower":25,"count":141,"preSum":4412},{"ndv":4,"upper":32,"lower":29,"count":125,"preSum":4553},{"ndv":5,"upper":37,"lower":33,"count":124,"preSum":4678},{"ndv":5,"upper":42,"lower":38,"count":116,"preSum":4802},{"ndv":6,"upper":48,"lower":43,"count":146,"preSum":4918},{"ndv":8,"upper":56,"lower":49,"count":116,"preSum":5064},{"ndv":15,"upper":71,"lower":57,"count":120,"preSum":5180},{"ndv":9,"upper":80,"lower":72,"count":127,"preSum":5300},{"ndv":16,"upper":96,"lower":81,"count":116,"preSum":5427},{"ndv":21,"upper":118,"lower":97,"count":116,"preSum":5543},{"ndv":7,"upper":125,"lower":119,"count":125,"preSum":5659},{"ndv":28,"upper":156,"lower":126,"count":122,"preSum":5784},{"ndv":34,"upper":192,"lower":157,"count":132,"preSum":5906},{"ndv":8,"upper":200,"lower":193,"count":123,"preSum":6038},{"ndv":45,"upper":250,"lower":201,"count":118,"preSum":6161},{"ndv":47,"upper":310,"lower":251,"count":124,"preSum":6279},{"ndv":18,"upper":339,"lower":311,"count":116,"preSum":6403},{"ndv":59,"upper":457,"lower":340,"count":116,"preSum":6519},{"ndv":60,"upper":600,"lower":458,"count":122,"preSum":6635},{"ndv":72,"upper":840,"lower":608,"count":119,"preSum":6757},{"ndv":44,"upper":1236,"lower":847,"count":118,"preSum":6876},{"ndv":82,"upper":2400,"lower":1260,"count":120,"preSum":6994},{"ndv":83,"upper":5220,"lower":2404,"count":116,"preSum":7114},{"ndv":108,"upper":30296,"lower":5252,"count":116,"preSum":7230},{"ndv":34,"upper":600000,"lower":30732,"count":35,"preSum":7346}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[16285,19254,8949,7479,5745,9549,3607,3712,5245,4883,1393,1429,2056,3034],"valueArr":[1,2,3,4,5,6,7,8,9,10,11,12,15,20],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalvalue',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0.0000],"type":"Double","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalvolume',100371,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":34,"upper":98.4050,"lower":1.0000,"count":1308,"preSum":0},{"ndv":60,"upper":203.9490,"lower":99.2900,"count":1321,"preSum":1308},{"ndv":39,"upper":255.9070,"lower":205.8720,"count":1227,"preSum":2629},{"ndv":72,"upper":319.8530,"lower":256.0600,"count":1978,"preSum":3856},{"ndv":136,"upper":418.2780,"lower":320.3910,"count":1310,"preSum":5834},{"ndv":102,"upper":492.4770,"lower":418.6000,"count":1384,"preSum":7144},{"ndv":54,"upper":535.0120,"lower":493.2180,"count":1306,"preSum":8528},{"ndv":49,"upper":554.1320,"lower":535.5110,"count":1204,"preSum":9834},{"ndv":37,"upper":574.3250,"lower":555.7490,"count":1396,"preSum":11038},{"ndv":69,"upper":605.9880,"lower":575.9130,"count":1174,"preSum":12434},{"ndv":79,"upper":639.2230,"lower":606.4120,"count":1173,"preSum":13608},{"ndv":126,"upper":694.7190,"lower":639.4460,"count":1184,"preSum":14781},{"ndv":71,"upper":720.1130,"lower":695.3190,"count":1173,"preSum":15965},{"ndv":88,"upper":752.0080,"lower":720.2660,"count":1177,"preSum":17138},{"ndv":46,"upper":772.1450,"lower":753.3750,"count":1176,"preSum":18315},{"ndv":145,"upper":825.2350,"lower":773.0070,"count":1172,"preSum":19491},{"ndv":172,"upper":887.1950,"lower":826.1140,"count":1173,"preSum":20663},{"ndv":56,"upper":908.6990,"lower":887.8300,"count":1172,"preSum":21836},{"ndv":203,"upper":1002.8560,"lower":908.8030,"count":1177,"preSum":23008},{"ndv":199,"upper":1081.1810,"lower":1003.3480,"count":1175,"preSum":24185},{"ndv":84,"upper":1117.0860,"lower":1081.2220,"count":1203,"preSum":25360},{"ndv":174,"upper":1185.7310,"lower":1117.1590,"count":1223,"preSum":26563},{"ndv":100,"upper":1226.9300,"lower":1185.9020,"count":1172,"preSum":27786},{"ndv":195,"upper":1308.3850,"lower":1226.9630,"count":1208,"preSum":28958},{"ndv":242,"upper":1423.4300,"lower":1309.0900,"count":1254,"preSum":30166},{"ndv":366,"upper":1585.8640,"lower":1424.2060,"count":1174,"preSum":31420},{"ndv":346,"upper":1741.8100,"lower":1586.0100,"count":1172,"preSum":32594},{"ndv":369,"upper":1917.5730,"lower":1742.2760,"count":1178,"preSum":33766},{"ndv":299,"upper":2057.5110,"lower":1918.1900,"count":1174,"preSum":34944},{"ndv":321,"upper":2211.5090,"lower":2057.7230,"count":1180,"preSum":36118},{"ndv":285,"upper":2357.0670,"lower":2211.8270,"count":1175,"preSum":37298},{"ndv":338,"upper":2527.8980,"lower":2358.1360,"count":1172,"preSum":38473},{"ndv":115,"upper":2586.6240,"lower":2528.5050,"count":1276,"preSum":39645},{"ndv":327,"upper":2755.8640,"lower":2587.4640,"count":1232,"preSum":40921},{"ndv":296,"upper":2914.8540,"lower":2757.0860,"count":1564,"preSum":42153},{"ndv":98,"upper":2967.8460,"lower":2914.9820,"count":1655,"preSum":43717},{"ndv":336,"upper":3197.5570,"lower":2967.8810,"count":1180,"preSum":45372},{"ndv":507,"upper":3525.5280,"lower":3198.9240,"count":1226,"preSum":46552},{"ndv":334,"upper":3802.1240,"lower":3525.5560,"count":1172,"preSum":47778},{"ndv":431,"upper":4203.1170,"lower":3805.1870,"count":1174,"preSum":48950},{"ndv":185,"upper":4408.9500,"lower":4204.3350,"count":1419,"preSum":50124},{"ndv":141,"upper":4576.6380,"lower":4409.1020,"count":1633,"preSum":51543},{"ndv":257,"upper":4936.9760,"lower":4580.1640,"count":1181,"preSum":53176},{"ndv":248,"upper":5349.4740,"lower":4939.9800,"count":1527,"preSum":54357},{"ndv":202,"upper":5729.6170,"lower":5351.3580,"count":1173,"preSum":55884},{"ndv":70,"upper":5875.8800,"lower":5729.6460,"count":1175,"preSum":57057},{"ndv":118,"upper":6131.4950,"lower":5879.1140,"count":1215,"preSum":58232},{"ndv":80,"upper":6334.1450,"lower":6131.9400,"count":1198,"preSum":59447},{"ndv":60,"upper":6466.5600,"lower":6339.9580,"count":1189,"preSum":60645},{"ndv":82,"upper":6623.3860,"lower":6467.1610,"count":1193,"preSum":61834},{"ndv":84,"upper":6858.3700,"lower":6629.5240,"count":1978,"preSum":63027},{"ndv":288,"upper":7627.7300,"lower":6859.6580,"count":1175,"preSum":65005},{"ndv":236,"upper":8394.2520,"lower":7629.3290,"count":1555,"preSum":66180},{"ndv":237,"upper":9232.8970,"lower":8395.1550,"count":1172,"preSum":67735},{"ndv":366,"upper":10830.8960,"lower":9237.5880,"count":1173,"preSum":68907},{"ndv":407,"upper":12971.8100,"lower":10833.0000,"count":1172,"preSum":70080},{"ndv":696,"upper":24903.7680,"lower":12977.2040,"count":1172,"preSum":71252},{"ndv":966,"upper":114154.3380,"lower":25018.3200,"count":1181,"preSum":72424},{"ndv":993,"upper":2035981.4400,"lower":114268.7500,"count":1172,"preSum":73605},{"ndv":207,"upper":2304960000.0000,"lower":2049274.0800,"count":208,"preSum":74777}],"maxBucketSize":64,"type":"Double","sampleRate":0.9618625}','{"countArr":[2232,990,1204,3921,933,4042,1511,1379,1020,1570,1115,1283,1085,2731],"valueArr":[0.0000,385.5000,738.2020,1060.3700,1195.3200,2204.4750,2350.3520,3169.9790,5482.1190,6358.2440,7051.0560,7736.0400,7904.1340,15255.4600],"type":"Double","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','totalweight',106428,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":83,"upper":35.0000,"lower":0.1350,"count":1276,"preSum":0},{"ndv":74,"upper":58.3330,"lower":36.0000,"count":1266,"preSum":1276},{"ndv":43,"upper":70.8330,"lower":58.3340,"count":1306,"preSum":2542},{"ndv":62,"upper":81.2500,"lower":70.8340,"count":1298,"preSum":3848},{"ndv":94,"upper":102.9160,"lower":81.5830,"count":1261,"preSum":5146},{"ndv":66,"upper":118.7500,"lower":103.0000,"count":1268,"preSum":6407},{"ndv":65,"upper":131.0000,"lower":119.0280,"count":1272,"preSum":7675},{"ndv":69,"upper":143.7500,"lower":131.1100,"count":1582,"preSum":8947},{"ndv":99,"upper":160.0000,"lower":144.0000,"count":1298,"preSum":10529},{"ndv":153,"upper":185.4170,"lower":160.4160,"count":1274,"preSum":11827},{"ndv":168,"upper":211.0000,"lower":185.5000,"count":1283,"preSum":13101},{"ndv":112,"upper":227.9170,"lower":211.1090,"count":1315,"preSum":14384},{"ndv":128,"upper":241.6670,"lower":228.0000,"count":1279,"preSum":15699},{"ndv":56,"upper":248.7510,"lower":241.8040,"count":1265,"preSum":16978},{"ndv":82,"upper":258.3330,"lower":248.8330,"count":1266,"preSum":18243},{"ndv":67,"upper":266.7500,"lower":258.3340,"count":1449,"preSum":19509},{"ndv":137,"upper":285.0000,"lower":266.7750,"count":1262,"preSum":20958},{"ndv":125,"upper":298.7480,"lower":285.1660,"count":1264,"preSum":22220},{"ndv":74,"upper":310.0000,"lower":298.7500,"count":1291,"preSum":23484},{"ndv":86,"upper":319.4440,"lower":310.3380,"count":1683,"preSum":24775},{"ndv":169,"upper":340.0000,"lower":319.4450,"count":1283,"preSum":26458},{"ndv":119,"upper":354.7500,"lower":340.2500,"count":1339,"preSum":27741},{"ndv":136,"upper":372.0000,"lower":354.8890,"count":1338,"preSum":29080},{"ndv":283,"upper":408.3320,"lower":372.0800,"count":1266,"preSum":30418},{"ndv":310,"upper":456.3330,"lower":408.3330,"count":1279,"preSum":31684},{"ndv":253,"upper":500.0000,"lower":456.5760,"count":1424,"preSum":32963},{"ndv":204,"upper":533.3320,"lower":500.0100,"count":1362,"preSum":34387},{"ndv":332,"upper":575.0000,"lower":533.3330,"count":1264,"preSum":35749},{"ndv":222,"upper":608.3340,"lower":575.6950,"count":1267,"preSum":37013},{"ndv":265,"upper":650.0010,"lower":608.8610,"count":1691,"preSum":38280},{"ndv":442,"upper":728.7490,"lower":650.1010,"count":1267,"preSum":39971},{"ndv":331,"upper":784.2780,"lower":728.7500,"count":1260,"preSum":41238},{"ndv":169,"upper":814.5810,"lower":784.3040,"count":1262,"preSum":42498},{"ndv":201,"upper":846.5830,"lower":814.5840,"count":1272,"preSum":43760},{"ndv":151,"upper":868.0550,"lower":846.6660,"count":1353,"preSum":45032},{"ndv":262,"upper":906.8050,"lower":868.1660,"count":1264,"preSum":46385},{"ndv":368,"upper":956.0000,"lower":907.0000,"count":1285,"preSum":47649},{"ndv":105,"upper":970.6950,"lower":956.1120,"count":1261,"preSum":48934},{"ndv":346,"upper":1016.6680,"lower":970.8280,"count":1262,"preSum":50195},{"ndv":429,"upper":1085.0000,"lower":1016.7750,"count":1260,"preSum":51457},{"ndv":390,"upper":1153.4330,"lower":1085.1100,"count":1260,"preSum":52717},{"ndv":239,"upper":1197.9150,"lower":1153.5670,"count":1260,"preSum":53977},{"ndv":389,"upper":1262.5020,"lower":1198.0000,"count":1597,"preSum":55237},{"ndv":455,"upper":1360.4160,"lower":1262.7770,"count":1260,"preSum":56834},{"ndv":550,"upper":1465.8300,"lower":1360.4170,"count":1260,"preSum":58094},{"ndv":259,"upper":1524.0000,"lower":1465.8330,"count":1266,"preSum":59354},{"ndv":204,"upper":1572.2140,"lower":1524.1380,"count":1260,"preSum":60620},{"ndv":251,"upper":1626.9980,"lower":1572.5000,"count":1260,"preSum":61880},{"ndv":164,"upper":1675.0000,"lower":1627.5820,"count":1420,"preSum":63140},{"ndv":310,"upper":1758.8900,"lower":1675.4990,"count":1367,"preSum":64560},{"ndv":207,"upper":1831.9420,"lower":1758.8920,"count":1261,"preSum":65927},{"ndv":219,"upper":1909.8010,"lower":1832.8120,"count":1260,"preSum":67188},{"ndv":181,"upper":1988.2840,"lower":1909.8270,"count":1479,"preSum":68448},{"ndv":239,"upper":2104.1700,"lower":1988.5710,"count":1346,"preSum":69927},{"ndv":185,"upper":2202.5900,"lower":2104.5000,"count":1403,"preSum":71273},{"ndv":210,"upper":2342.6130,"lower":2203.7260,"count":1292,"preSum":72676},{"ndv":334,"upper":2646.2890,"lower":2343.4160,"count":1260,"preSum":73968},{"ndv":495,"upper":3366.6720,"lower":2646.3720,"count":1332,"preSum":75228},{"ndv":529,"upper":5315.0000,"lower":3367.7370,"count":1260,"preSum":76560},{"ndv":1033,"upper":26183.9520,"lower":5323.3310,"count":1260,"preSum":77820},{"ndv":1048,"upper":410066.4080,"lower":26190.4160,"count":1260,"preSum":79080},{"ndv":263,"upper":106233375.0000,"lower":413900.0800,"count":264,"preSum":80340}],"maxBucketSize":64,"type":"Double","sampleRate":0.9618625}','{"countArr":[917,1666,2254,1261,2194,1283,1882,1311,1152,756,907,1085,1062,1667],"valueArr":[0.0000,490.0000,508.3340,600.0000,780.0000,799.9980,837.5000,1758.1140,1800.0000,2148.5900,2250.0000,2545.8350,3900.0000,4208.3400],"type":"Double","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','towarehousecode',55,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"C001","lower":"C001","count":2,"preSum":0},{"ndv":1,"upper":"C002","lower":"C002","count":2,"preSum":2},{"ndv":1,"upper":"C003","lower":"C003","count":4,"preSum":4},{"ndv":2,"upper":"D004","lower":"D001","count":2,"preSum":8},{"ndv":1,"upper":"D007","lower":"D007","count":3,"preSum":10},{"ndv":1,"upper":"D011","lower":"D011","count":2,"preSum":13},{"ndv":1,"upper":"JD01","lower":"JD01","count":6,"preSum":15},{"ndv":1,"upper":"JD02","lower":"JD02","count":5,"preSum":21},{"ndv":1,"upper":"JD08","lower":"JD08","count":2,"preSum":26},{"ndv":1,"upper":"S003","lower":"S003","count":4,"preSum":28},{"ndv":1,"upper":"S004","lower":"S004","count":13,"preSum":32},{"ndv":1,"upper":"S106","lower":"S106","count":13,"preSum":45},{"ndv":1,"upper":"S108","lower":"S108","count":3,"preSum":58},{"ndv":1,"upper":"S109","lower":"S109","count":9,"preSum":61},{"ndv":1,"upper":"S113","lower":"S113","count":15,"preSum":70},{"ndv":1,"upper":"W002","lower":"W002","count":10,"preSum":85},{"ndv":1,"upper":"W005","lower":"W005","count":3,"preSum":95},{"ndv":1,"upper":"W007","lower":"W007","count":3,"preSum":98},{"ndv":2,"upper":"W013","lower":"W009","count":3,"preSum":101},{"ndv":1,"upper":"W028","lower":"W028","count":10,"preSum":104}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2644,23,47,16,23,17,16,18,30,22,35,16,24,24],"valueArr":["","D017","S001","S002","S005","S007","S101","S102","S103","S104","S105","S107","S112","S115"],"type":"String","sampleRate":0.9618625319816094}',96932,0.02436278),('jala_wms_prod','shipment_header','trackingtype',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','trailingsts',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6391,5,3,28,93574],"valueArr":[100,300,400,600,900],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','twovotesystem',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','updatereason',11,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"质检已处理","lower":"质检已处理","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[25,4],"valueArr":["ZXL后台刷掉标记回传","已回传"],"type":"String","sampleRate":0.9618625319816094}',99971,0.02436278),('jala_wms_prod','shipment_header','uploadbatch',422855,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1297,"upper":"2023-02-26 09:26:01","lower":"2022-09-05 11:36:01","count":1460,"preSum":0},{"ndv":1077,"upper":"2023-03-07 10:10:02","lower":"2023-02-26 09:27:00","count":1460,"preSum":1460},{"ndv":1129,"upper":"2023-03-20 09:49:00","lower":"2023-03-07 10:10:05","count":1460,"preSum":2920},{"ndv":1172,"upper":"2023-04-09 10:43:00","lower":"2023-03-20 09:50:00","count":1460,"preSum":4380},{"ndv":1128,"upper":"2023-04-17 09:49:08","lower":"2023-04-09 10:44:00","count":1461,"preSum":5840},{"ndv":1112,"upper":"2023-04-21 09:36:03","lower":"2023-04-17 09:51:01","count":1460,"preSum":7301},{"ndv":1002,"upper":"2023-04-22 18:47:10","lower":"2023-04-21 09:36:04","count":1460,"preSum":8761},{"ndv":986,"upper":"2023-04-25 10:18:11","lower":"2023-04-22 18:49:02","count":1460,"preSum":10221},{"ndv":1064,"upper":"2023-04-26 17:03:06","lower":"2023-04-25 10:19:02","count":1461,"preSum":11681},{"ndv":1009,"upper":"2023-04-28 15:20:06","lower":"2023-04-26 17:05:04","count":1460,"preSum":13142},{"ndv":1016,"upper":"2023-04-29 21:30:26","lower":"2023-04-28 15:20:13","count":1461,"preSum":14602},{"ndv":1068,"upper":"2023-05-01 15:57:11","lower":"2023-04-29 21:32:30","count":1460,"preSum":16063},{"ndv":1082,"upper":"2023-05-03 10:05:08","lower":"2023-05-01 15:59:10","count":1460,"preSum":17523},{"ndv":771,"upper":"2023-05-03 15:57:07","lower":"2023-05-03 10:06:05","count":1460,"preSum":18983},{"ndv":918,"upper":"2023-05-04 11:22:02","lower":"2023-05-03 15:57:08","count":1460,"preSum":20443},{"ndv":1091,"upper":"2023-05-05 10:20:09","lower":"2023-05-04 11:22:03","count":1460,"preSum":21903},{"ndv":980,"upper":"2023-05-06 18:23:00","lower":"2023-05-05 10:20:11","count":1462,"preSum":23363},{"ndv":1030,"upper":"2023-05-08 15:40:04","lower":"2023-05-06 18:26:00","count":1460,"preSum":24825},{"ndv":1023,"upper":"2023-05-10 11:02:20","lower":"2023-05-08 15:41:02","count":1460,"preSum":26285},{"ndv":935,"upper":"2023-05-11 14:54:33","lower":"2023-05-10 11:03:09","count":1461,"preSum":27745},{"ndv":1083,"upper":"2023-05-12 19:06:11","lower":"2023-05-11 14:54:34","count":1460,"preSum":29206},{"ndv":1190,"upper":"2023-05-14 13:50:22","lower":"2023-05-12 19:09:11","count":1460,"preSum":30666},{"ndv":1023,"upper":"2023-05-16 09:16:01","lower":"2023-05-14 13:50:24","count":1460,"preSum":32126},{"ndv":1031,"upper":"2023-05-17 12:35:05","lower":"2023-05-16 09:17:01","count":1460,"preSum":33586},{"ndv":1117,"upper":"2023-05-18 11:08:19","lower":"2023-05-17 12:35:06","count":1460,"preSum":35046},{"ndv":949,"upper":"2023-05-19 16:32:12","lower":"2023-05-18 11:08:20","count":1461,"preSum":36506},{"ndv":1048,"upper":"2023-05-21 13:11:11","lower":"2023-05-19 16:33:09","count":1461,"preSum":37967},{"ndv":1106,"upper":"2023-05-23 09:50:18","lower":"2023-05-21 13:12:09","count":1460,"preSum":39428},{"ndv":1147,"upper":"2023-05-24 16:52:11","lower":"2023-05-23 09:52:15","count":1460,"preSum":40888},{"ndv":884,"upper":"2023-05-26 14:18:01","lower":"2023-05-24 16:52:12","count":1461,"preSum":42348},{"ndv":1037,"upper":"2023-05-28 13:19:06","lower":"2023-05-26 14:18:02","count":1460,"preSum":43809},{"ndv":1273,"upper":"2023-05-30 15:55:26","lower":"2023-05-28 13:20:02","count":1460,"preSum":45269},{"ndv":1171,"upper":"2023-05-31 22:47:05","lower":"2023-05-30 15:56:21","count":1461,"preSum":46729},{"ndv":785,"upper":"2023-06-01 03:57:07","lower":"2023-05-31 22:47:06","count":1460,"preSum":48190},{"ndv":928,"upper":"2023-06-01 10:09:12","lower":"2023-06-01 03:57:08","count":1460,"preSum":49650},{"ndv":1082,"upper":"2023-06-01 13:11:13","lower":"2023-06-01 10:10:06","count":1460,"preSum":51110},{"ndv":1217,"upper":"2023-06-01 15:46:08","lower":"2023-06-01 13:11:16","count":1460,"preSum":52570},{"ndv":1331,"upper":"2023-06-01 18:54:45","lower":"2023-06-01 15:46:11","count":1460,"preSum":54030},{"ndv":1352,"upper":"2023-06-01 21:56:01","lower":"2023-06-01 18:54:54","count":1460,"preSum":55490},{"ndv":1342,"upper":"2023-06-02 06:57:28","lower":"2023-06-01 21:56:14","count":1460,"preSum":56950},{"ndv":950,"upper":"2023-06-02 14:40:02","lower":"2023-06-02 06:58:09","count":1460,"preSum":58410},{"ndv":725,"upper":"2023-06-03 04:39:01","lower":"2023-06-02 14:40:03","count":1463,"preSum":59870},{"ndv":694,"upper":"2023-06-03 15:45:01","lower":"2023-06-03 04:45:01","count":1460,"preSum":61333},{"ndv":718,"upper":"2023-06-04 14:16:04","lower":"2023-06-03 15:46:02","count":1460,"preSum":62793},{"ndv":704,"upper":"2023-06-05 14:30:01","lower":"2023-06-04 14:17:01","count":1460,"preSum":64253},{"ndv":714,"upper":"2023-06-06 15:31:01","lower":"2023-06-05 14:32:01","count":1462,"preSum":65713},{"ndv":788,"upper":"2023-06-07 17:43:01","lower":"2023-06-06 15:32:01","count":1461,"preSum":67175},{"ndv":783,"upper":"2023-06-09 14:56:02","lower":"2023-06-07 17:44:01","count":1460,"preSum":68636},{"ndv":769,"upper":"2023-06-11 11:01:01","lower":"2023-06-09 14:58:01","count":1461,"preSum":70096},{"ndv":805,"upper":"2023-06-12 17:44:01","lower":"2023-06-11 11:02:02","count":1460,"preSum":71557},{"ndv":739,"upper":"2023-06-14 10:13:58","lower":"2023-06-12 17:46:01","count":1460,"preSum":73017},{"ndv":815,"upper":"2023-06-15 17:12:02","lower":"2023-06-14 10:13:59","count":1460,"preSum":74477},{"ndv":746,"upper":"2023-06-16 13:46:05","lower":"2023-06-15 17:13:01","count":1460,"preSum":75937},{"ndv":671,"upper":"2023-06-16 20:44:01","lower":"2023-06-16 13:46:06","count":1463,"preSum":77397},{"ndv":660,"upper":"2023-06-17 13:23:01","lower":"2023-06-16 20:44:20","count":1460,"preSum":78860},{"ndv":703,"upper":"2023-06-18 09:33:11","lower":"2023-06-17 13:23:04","count":1460,"preSum":80320},{"ndv":693,"upper":"2023-06-18 16:07:03","lower":"2023-06-18 09:34:03","count":1460,"preSum":81780},{"ndv":689,"upper":"2023-06-19 09:30:03","lower":"2023-06-18 16:08:01","count":1460,"preSum":83240},{"ndv":647,"upper":"2023-06-19 14:42:10","lower":"2023-06-19 09:30:04","count":1460,"preSum":84700},{"ndv":719,"upper":"2023-06-20 09:55:04","lower":"2023-06-19 14:42:11","count":1460,"preSum":86160},{"ndv":714,"upper":"2023-06-21 09:57:02","lower":"2023-06-20 09:55:05","count":1461,"preSum":87620},{"ndv":897,"upper":"2023-06-23 15:23:01","lower":"2023-06-21 09:57:03","count":1460,"preSum":89081},{"ndv":890,"upper":"2023-06-26 11:50:01","lower":"2023-06-23 15:27:01","count":1460,"preSum":90541},{"ndv":900,"upper":"2023-06-28 23:32:23","lower":"2023-06-26 11:51:01","count":1405,"preSum":92001}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[14,13,14,15,15,15,14,13,13,16,13,13,16],"valueArr":["","2023-06-05 09:30:01","2023-06-05 16:19:01","2023-06-05 17:07:03","2023-06-05 17:11:04","2023-06-06 08:55:02","2023-06-06 09:52:19","2023-06-06 14:00:01","2023-06-09 11:33:04","2023-06-09 17:15:01","2023-06-10 08:51:01","2023-06-19 14:39:12","2023-06-25 18:37:01"],"type":"String","sampleRate":0.9618625319816094}',6411,0.02436278),('jala_wms_prod','shipment_header','uploadrequired',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[99996,5],"valueArr":[0,1],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','uploadture',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[98669,30],"valueArr":[0,1],"type":"Int","sampleRate":0.9618625319816094}',1302,0.02436278),('jala_wms_prod','shipment_header','userdef1',22,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"2023-05-09","lower":"2023-05-09","count":1,"preSum":0},{"ndv":1,"upper":"2023-05-22","lower":"2023-05-22","count":1,"preSum":1},{"ndv":1,"upper":"A63778","lower":"A63778","count":2,"preSum":2}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[93938,1206,41,4,113,59],"valueArr":["0","A49977","A56685_1","A58804","A61584","A63780_1"],"type":"String","sampleRate":0.9618625319816094}',4636,0.02436278),('jala_wms_prod','shipment_header','userdef2',8,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"G","lower":"G","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[438,359,282,9,1405,418,144],"valueArr":["","10","11","12","A","B","Z"],"type":"String","sampleRate":0.9618625319816094}',96944,0.02436278),('jala_wms_prod','shipment_header','userdef3',26405,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":36,"upper":"CXDS-DL22110471055","lower":"1000651","count":40,"preSum":0},{"ndv":40,"upper":"DB000032751","lower":"CXDS-DL22110471056","count":40,"preSum":40},{"ndv":40,"upper":"DB000035723","lower":"DB000032762","count":40,"preSum":80},{"ndv":39,"upper":"DB000038973","lower":"DB000035782","count":40,"preSum":120},{"ndv":40,"upper":"DB000042166","lower":"DB000038974","count":40,"preSum":160},{"ndv":38,"upper":"DB000045597","lower":"DB000043009","count":40,"preSum":200},{"ndv":40,"upper":"DB000046092","lower":"DB000045598","count":40,"preSum":240},{"ndv":40,"upper":"DB000047589","lower":"DB000046161","count":40,"preSum":280},{"ndv":40,"upper":"JLCS-JX23032619010","lower":"DB000047597","count":40,"preSum":320},{"ndv":38,"upper":"JLCS-JX23041958398","lower":"JLCS-JX23032958559","count":40,"preSum":360},{"ndv":40,"upper":"JLCS-JX23042672013","lower":"JLCS-JX23041958758","count":40,"preSum":400},{"ndv":40,"upper":"JLCS-JX23050677737","lower":"JLCS-JX23042778152","count":40,"preSum":440},{"ndv":40,"upper":"JLCS-JX23051892773","lower":"JLCS-JX23050677809","count":40,"preSum":480},{"ndv":40,"upper":"JLCS-JX23053023198","lower":"JLCS-JX23051912825","count":40,"preSum":520},{"ndv":40,"upper":"JLCS-JX23061441914","lower":"JLCS-JX23053023410","count":40,"preSum":560},{"ndv":39,"upper":"JLCS-JX23061681792","lower":"JLCS-JX23061442214","count":40,"preSum":600},{"ndv":40,"upper":"JLMK-DL23040426856","lower":"JLCS-JX23061684460","count":40,"preSum":640},{"ndv":38,"upper":"MFDD-NB22112239346","lower":"JLMK-DL23040750385","count":40,"preSum":680},{"ndv":40,"upper":"MFDD-NB23010579031","lower":"MFDD-NB22112239347","count":40,"preSum":720},{"ndv":39,"upper":"MFDD-NB23040323892","lower":"MFDD-NB23010579037","count":40,"preSum":760},{"ndv":39,"upper":"MFDD-NB23051914604","lower":"MFDD-NB23040641056","count":40,"preSum":800},{"ndv":40,"upper":"MSCS-JX23010254795","lower":"MFDD-NB23051914735","count":40,"preSum":840},{"ndv":35,"upper":"ZRCS-JX22110825698","lower":"MSCS-JX23010254810","count":40,"preSum":880},{"ndv":40,"upper":"ZRCS-JX23010576718","lower":"ZRCS-JX22111572614","count":40,"preSum":920},{"ndv":40,"upper":"ZRCS-JX23010796514","lower":"ZRCS-JX23010576752","count":40,"preSum":960},{"ndv":40,"upper":"ZRCS-JX23030668972","lower":"ZRCS-JX23010797907","count":40,"preSum":1000},{"ndv":40,"upper":"ZRCS-JX23032259738","lower":"ZRCS-JX23030771763","count":40,"preSum":1040},{"ndv":40,"upper":"ZRCS-JX23040320208","lower":"ZRCS-JX23032260836","count":40,"preSum":1080},{"ndv":40,"upper":"ZRCS-JX23040635959","lower":"ZRCS-JX23040320473","count":40,"preSum":1120},{"ndv":40,"upper":"ZRCS-JX23041070558","lower":"ZRCS-JX23040636151","count":40,"preSum":1160},{"ndv":40,"upper":"ZRCS-JX23041396988","lower":"ZRCS-JX23041070635","count":40,"preSum":1200},{"ndv":40,"upper":"ZRCS-JX23041849439","lower":"ZRCS-JX23041397281","count":40,"preSum":1240},{"ndv":40,"upper":"ZRCS-JX23042425522","lower":"ZRCS-JX23041854186","count":40,"preSum":1280},{"ndv":40,"upper":"ZRCS-JX23042670593","lower":"ZRCS-JX23042426695","count":40,"preSum":1320},{"ndv":40,"upper":"ZRCS-JX23042828621","lower":"ZRCS-JX23042671893","count":40,"preSum":1360},{"ndv":40,"upper":"ZRCS-JX23050894512","lower":"ZRCS-JX23042828678","count":40,"preSum":1400},{"ndv":40,"upper":"ZRCS-JX23051346509","lower":"ZRCS-JX23050911136","count":40,"preSum":1440},{"ndv":40,"upper":"ZRCS-JX23052227178","lower":"ZRCS-JX23051554998","count":40,"preSum":1480},{"ndv":40,"upper":"ZRCS-JX23052568859","lower":"ZRCS-JX23052228410","count":40,"preSum":1520},{"ndv":39,"upper":"ZRCS-JX23053019779","lower":"ZRCS-JX23052569692","count":40,"preSum":1560},{"ndv":40,"upper":"ZRCS-JX23053150401","lower":"ZRCS-JX23053020681","count":40,"preSum":1600},{"ndv":40,"upper":"ZRCS-JX23061334541","lower":"ZRCS-JX23053150993","count":40,"preSum":1640},{"ndv":40,"upper":"ZRCS-JX23061610107","lower":"ZRCS-JX23061335155","count":40,"preSum":1680},{"ndv":39,"upper":"ZRCS-JX23062133017","lower":"ZRCS-JX23061611207","count":40,"preSum":1720},{"ndv":40,"upper":"ZRDS-DL23032852701","lower":"ZRCS-JX23062133072","count":40,"preSum":1760},{"ndv":39,"upper":"ZRMK-DL23042827658","lower":"ZRDS-DL23032852702","count":40,"preSum":1800},{"ndv":40,"upper":"ZRTC-JH23042794685","lower":"ZRMK-DL23042827773","count":40,"preSum":1840},{"ndv":40,"upper":"ZRTC-JH23052915928","lower":"ZRTC-JH23042794690","count":40,"preSum":1880},{"ndv":40,"upper":"ZRTC-JH23061563195","lower":"ZRTC-JH23052915930","count":40,"preSum":1920},{"ndv":40,"upper":"ZRTC-JH23062866833","lower":"ZRTC-JH23061563210","count":40,"preSum":1960},{"ndv":40,"upper":"ZRWS-DL22111810808","lower":"ZRTC-JH23062866886","count":40,"preSum":2000},{"ndv":40,"upper":"ZRWS-DL23020347512","lower":"ZRWS-DL22111899518","count":40,"preSum":2040},{"ndv":40,"upper":"ZRWS-DL23042823287","lower":"ZRWS-DL23020347994","count":40,"preSum":2080},{"ndv":40,"upper":"ZRZS-DL23010469247","lower":"ZRWS-DL23042824131","count":40,"preSum":2120},{"ndv":40,"upper":"ZRZS-JX23021867221","lower":"ZRZS-DL23021063580","count":40,"preSum":2160},{"ndv":40,"upper":"ZRZS-JX23040431205","lower":"ZRZS-JX23022034091","count":40,"preSum":2200},{"ndv":40,"upper":"ZRZS-JX23041850390","lower":"ZRZS-JX23040431206","count":40,"preSum":2240},{"ndv":40,"upper":"ZRZS-JX23042787846","lower":"ZRZS-JX23041853056","count":40,"preSum":2280},{"ndv":40,"upper":"ZRZS-JX23050997661","lower":"ZRZS-JX23042788841","count":40,"preSum":2320},{"ndv":40,"upper":"ZRZS-JX23051669318","lower":"ZRZS-JX23050999668","count":40,"preSum":2360},{"ndv":40,"upper":"ZRZS-JX23052449375","lower":"ZRZS-JX23051669331","count":40,"preSum":2400},{"ndv":40,"upper":"ZRZS-JX23060259746","lower":"ZRZS-JX23052453872","count":40,"preSum":2440},{"ndv":40,"upper":"ZRZS-JX23062024798","lower":"ZRZS-JX23060259799","count":40,"preSum":2480},{"ndv":27,"upper":"ZWCS-JX23051025592","lower":"ZRZS-JX23062024825","count":27,"preSum":2520}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[138,5,10,9,10,4,4,4,11,5,3,3,3],"valueArr":["","1000183","1000650","1000767","1001005","1001483","1001871","1002479","D017","DW02","S115-1000","ZRCS-JX23040112356","ZRCS-JX23040321713"],"type":"String","sampleRate":0.9618625319816094}',97245,0.02436278),('jala_wms_prod','shipment_header','userdef4',4030,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":7,"upper":"DB000025224","lower":"DB000024877","count":7,"preSum":0},{"ndv":7,"upper":"DB000025284","lower":"DB000025225","count":7,"preSum":7},{"ndv":7,"upper":"DB000025401","lower":"DB000025292","count":7,"preSum":14},{"ndv":7,"upper":"DB000025449","lower":"DB000025404","count":7,"preSum":21},{"ndv":7,"upper":"DB000025856","lower":"DB000025450","count":7,"preSum":28},{"ndv":7,"upper":"DB000026017","lower":"DB000025866","count":7,"preSum":35},{"ndv":6,"upper":"DB000026226","lower":"DB000026148","count":7,"preSum":42},{"ndv":7,"upper":"DB000026296","lower":"DB000026233","count":7,"preSum":49},{"ndv":7,"upper":"DB000026434","lower":"DB000026405","count":7,"preSum":56},{"ndv":7,"upper":"DB000027313","lower":"DB000026460","count":7,"preSum":63},{"ndv":7,"upper":"DB000027620","lower":"DB000027395","count":7,"preSum":70},{"ndv":7,"upper":"DB000027770","lower":"DB000027661","count":7,"preSum":77},{"ndv":7,"upper":"DB000027886","lower":"DB000027771","count":7,"preSum":84},{"ndv":7,"upper":"DB000028715","lower":"DB000028116","count":7,"preSum":91},{"ndv":7,"upper":"DB000029286","lower":"DB000028745","count":7,"preSum":98},{"ndv":7,"upper":"DB000030189","lower":"DB000029289","count":7,"preSum":105},{"ndv":7,"upper":"DB000030601","lower":"DB000030311","count":7,"preSum":112},{"ndv":7,"upper":"DB000030869","lower":"DB000030604","count":7,"preSum":119},{"ndv":7,"upper":"DB000032773","lower":"DB000031311","count":7,"preSum":126},{"ndv":7,"upper":"DB000032813","lower":"DB000032774","count":7,"preSum":133},{"ndv":7,"upper":"DB000032921","lower":"DB000032885","count":7,"preSum":140},{"ndv":7,"upper":"DB000034108","lower":"DB000032934","count":7,"preSum":147},{"ndv":7,"upper":"DB000035260","lower":"DB000034880","count":7,"preSum":154},{"ndv":7,"upper":"DB000035578","lower":"DB000035261","count":7,"preSum":161},{"ndv":7,"upper":"DB000035909","lower":"DB000035719","count":7,"preSum":168},{"ndv":7,"upper":"DB000036611","lower":"DB000035933","count":7,"preSum":175},{"ndv":7,"upper":"DB000036854","lower":"DB000036613","count":7,"preSum":182},{"ndv":6,"upper":"DB000037072","lower":"DB000036862","count":7,"preSum":189},{"ndv":7,"upper":"DB000037338","lower":"DB000037086","count":7,"preSum":196},{"ndv":7,"upper":"DB000038536","lower":"DB000037574","count":7,"preSum":203},{"ndv":7,"upper":"DB000039923","lower":"DB000038973","count":7,"preSum":210},{"ndv":7,"upper":"DB000041046","lower":"DB000039997","count":7,"preSum":217},{"ndv":7,"upper":"DB000041153","lower":"DB000041061","count":7,"preSum":224},{"ndv":7,"upper":"DB000041952","lower":"DB000041438","count":7,"preSum":231},{"ndv":7,"upper":"DB000042072","lower":"DB000041953","count":7,"preSum":238},{"ndv":7,"upper":"DB000043009","lower":"DB000042073","count":7,"preSum":245},{"ndv":7,"upper":"DB000043511","lower":"DB000043470","count":7,"preSum":252},{"ndv":7,"upper":"DB000043906","lower":"DB000043533","count":7,"preSum":259},{"ndv":7,"upper":"DB000044256","lower":"DB000043942","count":7,"preSum":266},{"ndv":6,"upper":"DB000044881","lower":"DB000044315","count":7,"preSum":273},{"ndv":6,"upper":"DB000045504","lower":"DB000045047","count":7,"preSum":280},{"ndv":7,"upper":"DB000045658","lower":"DB000045505","count":7,"preSum":287},{"ndv":7,"upper":"DB000045826","lower":"DB000045659","count":7,"preSum":294},{"ndv":7,"upper":"DB000045874","lower":"DB000045855","count":7,"preSum":301},{"ndv":7,"upper":"DB000045907","lower":"DB000045882","count":7,"preSum":308},{"ndv":7,"upper":"DB000045988","lower":"DB000045910","count":7,"preSum":315},{"ndv":7,"upper":"DB000046085","lower":"DB000046032","count":7,"preSum":322},{"ndv":7,"upper":"DB000046204","lower":"DB000046090","count":7,"preSum":329},{"ndv":7,"upper":"DB000046246","lower":"DB000046218","count":7,"preSum":336},{"ndv":7,"upper":"DB000046273","lower":"DB000046251","count":7,"preSum":343},{"ndv":7,"upper":"DB000046451","lower":"DB000046274","count":7,"preSum":350},{"ndv":7,"upper":"DB000047019","lower":"DB000046460","count":7,"preSum":357},{"ndv":7,"upper":"DB000047589","lower":"DB000047021","count":7,"preSum":364},{"ndv":7,"upper":"DB000047903","lower":"DB000047597","count":7,"preSum":371},{"ndv":7,"upper":"DB000047982","lower":"DB000047906","count":7,"preSum":378},{"ndv":5,"upper":"DB000048155","lower":"DB000047987","count":5,"preSum":385}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[2517],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',97094,0.02436278),('jala_wms_prod','shipment_header','userdef5',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[101],"valueArr":["0"],"type":"String","sampleRate":0.9618625319816094}',99900,0.02436278),('jala_wms_prod','shipment_header','userdef6',2341430,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1489,"upper":"JD23230606524443117;","lower":"JD00230301336668924;","count":1490,"preSum":0},{"ndv":1490,"upper":"JX08230535628531406;","lower":"JD23230611438829907;","count":1490,"preSum":1490},{"ndv":1490,"upper":"JX11230253128035326;","lower":"JX08230535640432008;","count":1490,"preSum":2980},{"ndv":1490,"upper":"JX13230532164408620;","lower":"JX11230253128036326;","count":1490,"preSum":4470},{"ndv":1490,"upper":"JX15230648584268523;","lower":"JX13230532164408720;","count":1490,"preSum":5960},{"ndv":1490,"upper":"JX18230558037649518;","lower":"JX15230648600098627;","count":1490,"preSum":7450},{"ndv":1490,"upper":"JX20230614486258715;","lower":"JX18230558258508122;","count":1490,"preSum":8940},{"ndv":1490,"upper":"JX22230348292134615;","lower":"JX20230614486265915;","count":1490,"preSum":10430},{"ndv":1490,"upper":"JX23230614406567203;","lower":"JX22230348314374519;","count":1490,"preSum":11920},{"ndv":1490,"upper":"OD13230502343893030;","lower":"JX23230614415865704;","count":1490,"preSum":13410},{"ndv":1490,"upper":"OD17230618518949017;","lower":"OD13230503016295818;","count":1490,"preSum":14900},{"ndv":1490,"upper":"SD00230551669984812;","lower":"OD17230619391410902;","count":1490,"preSum":16390},{"ndv":1490,"upper":"SD01230519613057404;","lower":"SD00230551737108116;","count":1490,"preSum":17880},{"ndv":1490,"upper":"SD02230516742477716;","lower":"SD01230519613057504;","count":1490,"preSum":19370},{"ndv":1490,"upper":"SD06230451540019826;","lower":"SD02230516742477816;","count":1490,"preSum":20860},{"ndv":1489,"upper":"SD10230401556784028;","lower":"SD06230451540019926;","count":1490,"preSum":22350},{"ndv":1490,"upper":"SD11230511629326506;","lower":"SD10230401556784228;","count":1490,"preSum":23840},{"ndv":1490,"upper":"SD12230534351439331;","lower":"SD11230511629327206;","count":1490,"preSum":25330},{"ndv":1490,"upper":"SD13230559352186431;","lower":"SD12230534351440131;","count":1490,"preSum":26820},{"ndv":1490,"upper":"SD14230544269481024;","lower":"SD13230559352187331;","count":1490,"preSum":28310},{"ndv":1490,"upper":"SD15230549675150212;","lower":"SD14230544269481524;","count":1490,"preSum":29800},{"ndv":1488,"upper":"SD16230559264237123;","lower":"SD15230549675150912;","count":1490,"preSum":31290},{"ndv":1490,"upper":"SD17230621412997304;","lower":"SD16230559264237523;","count":1490,"preSum":32780},{"ndv":1490,"upper":"SD19230446550966727;SD19230454551230727;","lower":"SD17230621412998004;","count":1490,"preSum":34270},{"ndv":1490,"upper":"SD20230524820596116;","lower":"SD19230446550973627;SD19230446550977927;","count":1490,"preSum":35760},{"ndv":1490,"upper":"SD21230551950362317;","lower":"SD20230525258901522;","count":1490,"preSum":37250},{"ndv":1490,"upper":"SD22230534645053108;","lower":"SD21230551950362517;","count":1490,"preSum":38740},{"ndv":1490,"upper":"SD23230526330134728;","lower":"SD22230534691458614;","count":1490,"preSum":40230},{"ndv":1490,"upper":"SDC1123061499244316;","lower":"SD23230526330134828;","count":1490,"preSum":41720},{"ndv":1490,"upper":"TB00230613550536519;","lower":"SDC1123061499540016;","count":1490,"preSum":43210},{"ndv":1490,"upper":"TB03230653384893802;","lower":"TB00230613550536819;","count":1490,"preSum":44700},{"ndv":1490,"upper":"TB08230401494235519;","lower":"TB03230653602067228;","count":1490,"preSum":46190},{"ndv":1490,"upper":"TB09230504575707801;","lower":"TB08230401540166926;","count":1490,"preSum":47680},{"ndv":1490,"upper":"TB09230540603683803;","lower":"TB09230504601778703;","count":1490,"preSum":49170},{"ndv":1490,"upper":"TB09230552292315727;","lower":"TB09230540603683903;","count":1490,"preSum":50660},{"ndv":1490,"upper":"TB10230404471758716;","lower":"TB09230552292315927;","count":1490,"preSum":52150},{"ndv":1488,"upper":"TB10230513582968302;","lower":"TB10230404471759416;","count":1490,"preSum":53640},{"ndv":1482,"upper":"TB10230529304818427;","lower":"TB10230513582973502;","count":1490,"preSum":55130},{"ndv":1490,"upper":"TB10230543309812327;","lower":"TB10230529304818727;","count":1490,"preSum":56620},{"ndv":1490,"upper":"TB10230558315054127;","lower":"TB10230543309812527;","count":1490,"preSum":58110},{"ndv":1488,"upper":"TB11230457541641426;","lower":"TB10230558315054227;","count":1490,"preSum":59600},{"ndv":1489,"upper":"TB11230640499661716;","lower":"TB11230457541643626;","count":1490,"preSum":61090},{"ndv":1488,"upper":"TB12230537615516004;","lower":"TB11230640499662716;","count":1490,"preSum":62580},{"ndv":1490,"upper":"TB13230443564735029;","lower":"TB12230537615516604;","count":1490,"preSum":64070},{"ndv":1490,"upper":"TB13230637534666618;","lower":"TB13230444441939611;","count":1490,"preSum":65560},{"ndv":1490,"upper":"TB14230613389239002;","lower":"TB13230637534668718;","count":1490,"preSum":67050},{"ndv":1489,"upper":"TB15230552681692013;","lower":"TB14230613389247102;","count":1490,"preSum":68540},{"ndv":1489,"upper":"TB16230527336811029;","lower":"TB15230552681692713;","count":1490,"preSum":70030},{"ndv":1490,"upper":"TB17230437566044029;","lower":"TB16230527336812029;","count":1490,"preSum":71520},{"ndv":1490,"upper":"TB18230404502877220;","lower":"TB17230437566044629;","count":1490,"preSum":73010},{"ndv":1489,"upper":"TB19230404481786217;","lower":"TB18230404537345425;","count":1490,"preSum":74500},{"ndv":1490,"upper":"TB19230652520499517;","lower":"TB19230404503115720;","count":1490,"preSum":75990},{"ndv":1490,"upper":"TB20230522356683731;","lower":"TB19230652520499717;","count":1490,"preSum":77480},{"ndv":1490,"upper":"TB20230610520751117;","lower":"TB20230522356696131;","count":1490,"preSum":78970},{"ndv":1490,"upper":"TB21230349313925419;","lower":"TB20230610520752617;","count":1490,"preSum":80460},{"ndv":1490,"upper":"TB21230526826277316;","lower":"TB21230349313929719;","count":1490,"preSum":81950},{"ndv":1490,"upper":"TB21230601444155008;","lower":"TB21230526826278016;","count":1490,"preSum":83440},{"ndv":1490,"upper":"TB21230655522683717;","lower":"TB21230601444155408;","count":1490,"preSum":84930},{"ndv":1490,"upper":"TB22230514593565202;","lower":"TB21230655522685017;","count":1490,"preSum":86420},{"ndv":1488,"upper":"TB22230555272022624;","lower":"TB22230514593566702;","count":1490,"preSum":87910},{"ndv":1490,"upper":"TB22230640394940102;","lower":"TB22230555277509125;","count":1490,"preSum":89400},{"ndv":1490,"upper":"TB23230515612101603;","lower":"TB22230640394940202;","count":1490,"preSum":90890},{"ndv":1489,"upper":"TB23230613593843025;","lower":"TB23230515612101903;","count":1490,"preSum":92380},{"ndv":1450,"upper":"TBC2023030243636108;","lower":"TB23230614395426202;","count":1450,"preSum":93870}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,4681,0.02436278),('jala_wms_prod','shipment_header','userdef7',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[79],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99922,0.02436278),('jala_wms_prod','shipment_header','userdef8',35,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"763DCA","lower":"763DCA","count":1,"preSum":0},{"ndv":1,"upper":"BD02","lower":"BD02","count":2,"preSum":1},{"ndv":1,"upper":"D005","lower":"D005","count":1,"preSum":3},{"ndv":1,"upper":"D008","lower":"D008","count":1,"preSum":4}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[5,549,8875,18765,253,52268,16649,314,177,139,381,40],"valueArr":["","021DC1","022DC","027DC","028DC","573DC","763DC","D001","D002","D003","D011","W007"],"type":"String","sampleRate":0.9618625319816094}',1581,0.02436278),('jala_wms_prod','shipment_header','version',147,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":12,"lower":12,"count":2,"preSum":0},{"ndv":1,"upper":14,"lower":14,"count":1,"preSum":2},{"ndv":1,"upper":15,"lower":15,"count":1,"preSum":3},{"ndv":1,"upper":17,"lower":17,"count":2,"preSum":4},{"ndv":1,"upper":21,"lower":21,"count":1,"preSum":6},{"ndv":1,"upper":24,"lower":24,"count":2,"preSum":7},{"ndv":1,"upper":25,"lower":25,"count":2,"preSum":9},{"ndv":1,"upper":27,"lower":27,"count":1,"preSum":11},{"ndv":1,"upper":28,"lower":28,"count":1,"preSum":12},{"ndv":1,"upper":29,"lower":29,"count":1,"preSum":13},{"ndv":1,"upper":32,"lower":32,"count":1,"preSum":14},{"ndv":1,"upper":37,"lower":37,"count":1,"preSum":15},{"ndv":1,"upper":44,"lower":44,"count":1,"preSum":16},{"ndv":1,"upper":55,"lower":55,"count":1,"preSum":17},{"ndv":1,"upper":69,"lower":69,"count":1,"preSum":18},{"ndv":1,"upper":100,"lower":100,"count":1,"preSum":19},{"ndv":1,"upper":127,"lower":127,"count":1,"preSum":20},{"ndv":1,"upper":136,"lower":136,"count":1,"preSum":21},{"ndv":1,"upper":173,"lower":173,"count":1,"preSum":22},{"ndv":1,"upper":207,"lower":207,"count":1,"preSum":23}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[645,33487,62342,2657,331,149,149,76,45,23,16,41,8,8],"valueArr":[0,1,2,3,4,5,6,7,8,9,10,11,13,22],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','vipshopcode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}',null,100001,0.02436278),('jala_wms_prod','shipment_header','warehousecode',16,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"763DCA","lower":"763DCA","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[549,8875,18765,253,52268,16649,471,1968,100,102],"valueArr":["021DC1","022DC","027DC","028DC","573DC","763DC","SH01","SH02","SH03","TEST01"],"type":"String","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','warehousetransfercode',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9618625}','{"countArr":[24],"valueArr":[""],"type":"String","sampleRate":0.9618625319816094}',99977,0.02436278),('jala_wms_prod','shipment_header','warehousetransferid',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[100001],"valueArr":[0],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','waveid',186631,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":860,"upper":558951,"lower":676,"count":1448,"preSum":0},{"ndv":779,"upper":587542,"lower":558952,"count":1448,"preSum":1448},{"ndv":820,"upper":648153,"lower":587564,"count":1448,"preSum":2896},{"ndv":835,"upper":702992,"lower":648204,"count":1448,"preSum":4344},{"ndv":749,"upper":728329,"lower":702993,"count":1448,"preSum":5792},{"ndv":751,"upper":747100,"lower":728331,"count":1449,"preSum":7240},{"ndv":484,"upper":755745,"lower":747102,"count":1450,"preSum":8689},{"ndv":552,"upper":767379,"lower":755746,"count":1448,"preSum":10139},{"ndv":588,"upper":778429,"lower":767380,"count":1449,"preSum":11587},{"ndv":494,"upper":789617,"lower":778468,"count":1448,"preSum":13036},{"ndv":620,"upper":799796,"lower":789618,"count":1450,"preSum":14484},{"ndv":537,"upper":809391,"lower":799800,"count":1448,"preSum":15934},{"ndv":596,"upper":818659,"lower":809428,"count":1448,"preSum":17382},{"ndv":370,"upper":821497,"lower":818662,"count":1449,"preSum":18830},{"ndv":447,"upper":825177,"lower":821513,"count":1449,"preSum":20279},{"ndv":507,"upper":831213,"lower":825178,"count":1448,"preSum":21728},{"ndv":546,"upper":844777,"lower":831218,"count":1449,"preSum":23176},{"ndv":501,"upper":857728,"lower":844791,"count":1478,"preSum":24625},{"ndv":516,"upper":872247,"lower":858226,"count":1448,"preSum":26103},{"ndv":489,"upper":883376,"lower":872249,"count":1467,"preSum":27551},{"ndv":559,"upper":895087,"lower":883377,"count":1470,"preSum":29018},{"ndv":538,"upper":907398,"lower":895088,"count":1457,"preSum":30488},{"ndv":565,"upper":919941,"lower":907399,"count":1448,"preSum":31945},{"ndv":514,"upper":929460,"lower":919942,"count":1454,"preSum":33393},{"ndv":507,"upper":936560,"lower":929470,"count":1450,"preSum":34847},{"ndv":638,"upper":950704,"lower":936562,"count":1468,"preSum":36297},{"ndv":520,"upper":960112,"lower":950706,"count":1453,"preSum":37765},{"ndv":544,"upper":974604,"lower":960113,"count":1448,"preSum":39218},{"ndv":660,"upper":989256,"lower":974607,"count":1448,"preSum":40666},{"ndv":568,"upper":1002435,"lower":989257,"count":1452,"preSum":42114},{"ndv":487,"upper":1014725,"lower":1002452,"count":1453,"preSum":43566},{"ndv":517,"upper":1023671,"lower":1014726,"count":1449,"preSum":45019},{"ndv":441,"upper":1030879,"lower":1023672,"count":1448,"preSum":46468},{"ndv":440,"upper":1037143,"lower":1030882,"count":1450,"preSum":47916},{"ndv":459,"upper":1042284,"lower":1037167,"count":1451,"preSum":49366},{"ndv":359,"upper":1043858,"lower":1042285,"count":1450,"preSum":50817},{"ndv":488,"upper":1047101,"lower":1043861,"count":1458,"preSum":52267},{"ndv":281,"upper":1048815,"lower":1047102,"count":1468,"preSum":53725},{"ndv":327,"upper":1051032,"lower":1048816,"count":1449,"preSum":55193},{"ndv":298,"upper":1052299,"lower":1051033,"count":1449,"preSum":56642},{"ndv":529,"upper":1056090,"lower":1052302,"count":1450,"preSum":58091},{"ndv":711,"upper":1060484,"lower":1056091,"count":1448,"preSum":59541},{"ndv":540,"upper":1065790,"lower":1060485,"count":1451,"preSum":60989},{"ndv":587,"upper":1073877,"lower":1065791,"count":1465,"preSum":62440},{"ndv":650,"upper":1089232,"lower":1073886,"count":1448,"preSum":63905},{"ndv":508,"upper":1100582,"lower":1089288,"count":1448,"preSum":65353},{"ndv":590,"upper":1117213,"lower":1100590,"count":1453,"preSum":66801},{"ndv":554,"upper":1132813,"lower":1117218,"count":1448,"preSum":68254},{"ndv":539,"upper":1147057,"lower":1132867,"count":1468,"preSum":69702},{"ndv":617,"upper":1162029,"lower":1147098,"count":1449,"preSum":71170},{"ndv":603,"upper":1171508,"lower":1162030,"count":1449,"preSum":72619},{"ndv":569,"upper":1184419,"lower":1171519,"count":1449,"preSum":74068},{"ndv":598,"upper":1188402,"lower":1184421,"count":1454,"preSum":75517},{"ndv":682,"upper":1194229,"lower":1188416,"count":1449,"preSum":76971},{"ndv":507,"upper":1198132,"lower":1194239,"count":1459,"preSum":78420},{"ndv":643,"upper":1203173,"lower":1198133,"count":1449,"preSum":79879},{"ndv":606,"upper":1209219,"lower":1203175,"count":1450,"preSum":81328},{"ndv":654,"upper":1213184,"lower":1209220,"count":1461,"preSum":82778},{"ndv":542,"upper":1217689,"lower":1213185,"count":1455,"preSum":84239},{"ndv":490,"upper":1223121,"lower":1217690,"count":1449,"preSum":85694},{"ndv":544,"upper":1236281,"lower":1223122,"count":1450,"preSum":87143},{"ndv":551,"upper":1266450,"lower":1236282,"count":1448,"preSum":88593},{"ndv":565,"upper":1286753,"lower":1266451,"count":1449,"preSum":90041},{"ndv":543,"upper":1303781,"lower":1286754,"count":1181,"preSum":91490}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[6503,59,54,65,61,55,67,65,92,62,64,57,57,69],"valueArr":[0,767248,775305,827927,878945,889087,929365,1038461,1044344,1074488,1197226,1204888,1213220,1299931],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278),('jala_wms_prod','shipment_header','zxqty',1339,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":7,"lower":7,"count":13,"preSum":0},{"ndv":1,"upper":13,"lower":13,"count":10,"preSum":13},{"ndv":1,"upper":15,"lower":15,"count":12,"preSum":23},{"ndv":1,"upper":16,"lower":16,"count":12,"preSum":35},{"ndv":1,"upper":17,"lower":17,"count":10,"preSum":47},{"ndv":1,"upper":18,"lower":18,"count":11,"preSum":57},{"ndv":1,"upper":19,"lower":19,"count":8,"preSum":68},{"ndv":2,"upper":22,"lower":21,"count":8,"preSum":76},{"ndv":2,"upper":24,"lower":23,"count":11,"preSum":84},{"ndv":1,"upper":25,"lower":25,"count":8,"preSum":95},{"ndv":2,"upper":27,"lower":26,"count":8,"preSum":103},{"ndv":2,"upper":30,"lower":28,"count":11,"preSum":111},{"ndv":3,"upper":33,"lower":31,"count":8,"preSum":122},{"ndv":3,"upper":36,"lower":34,"count":10,"preSum":130},{"ndv":3,"upper":39,"lower":37,"count":8,"preSum":140},{"ndv":4,"upper":45,"lower":40,"count":11,"preSum":148},{"ndv":4,"upper":49,"lower":46,"count":11,"preSum":159},{"ndv":1,"upper":50,"lower":50,"count":7,"preSum":170},{"ndv":2,"upper":52,"lower":51,"count":8,"preSum":177},{"ndv":2,"upper":55,"lower":54,"count":7,"preSum":185},{"ndv":3,"upper":58,"lower":56,"count":9,"preSum":192},{"ndv":3,"upper":61,"lower":59,"count":7,"preSum":201},{"ndv":2,"upper":63,"lower":62,"count":9,"preSum":208},{"ndv":3,"upper":67,"lower":65,"count":9,"preSum":217},{"ndv":3,"upper":71,"lower":68,"count":7,"preSum":226},{"ndv":3,"upper":75,"lower":72,"count":7,"preSum":233},{"ndv":5,"upper":80,"lower":76,"count":8,"preSum":240},{"ndv":5,"upper":87,"lower":82,"count":8,"preSum":248},{"ndv":4,"upper":91,"lower":88,"count":7,"preSum":256},{"ndv":6,"upper":97,"lower":92,"count":7,"preSum":263},{"ndv":4,"upper":102,"lower":98,"count":7,"preSum":270},{"ndv":4,"upper":110,"lower":103,"count":7,"preSum":277},{"ndv":4,"upper":118,"lower":114,"count":7,"preSum":284},{"ndv":6,"upper":129,"lower":120,"count":7,"preSum":291},{"ndv":6,"upper":147,"lower":131,"count":7,"preSum":298},{"ndv":6,"upper":160,"lower":148,"count":9,"preSum":305},{"ndv":6,"upper":173,"lower":161,"count":7,"preSum":314},{"ndv":5,"upper":185,"lower":175,"count":7,"preSum":321},{"ndv":6,"upper":204,"lower":188,"count":7,"preSum":328},{"ndv":7,"upper":227,"lower":208,"count":7,"preSum":335},{"ndv":5,"upper":250,"lower":235,"count":7,"preSum":342},{"ndv":7,"upper":275,"lower":257,"count":7,"preSum":349},{"ndv":7,"upper":347,"lower":276,"count":7,"preSum":356},{"ndv":5,"upper":370,"lower":348,"count":7,"preSum":363},{"ndv":7,"upper":414,"lower":384,"count":7,"preSum":370},{"ndv":7,"upper":479,"lower":420,"count":7,"preSum":377},{"ndv":7,"upper":543,"lower":491,"count":7,"preSum":384},{"ndv":7,"upper":666,"lower":556,"count":7,"preSum":391},{"ndv":7,"upper":849,"lower":699,"count":7,"preSum":398},{"ndv":7,"upper":1163,"lower":861,"count":7,"preSum":405},{"ndv":7,"upper":1818,"lower":1191,"count":7,"preSum":412},{"ndv":7,"upper":2631,"lower":1963,"count":7,"preSum":419},{"ndv":3,"upper":4068,"lower":3008,"count":3,"preSum":426}],"maxBucketSize":64,"type":"Int","sampleRate":0.9618625}','{"countArr":[98947,273,86,51,33,39,16,23,16,18,19,15,21,15],"valueArr":[0,1,2,3,4,5,6,8,9,10,11,12,14,20],"type":"Int","sampleRate":0.9618625319816094}',0,0.02436278); - DELETE FROM metadb.ndv_sketch_statistics WHERE `SCHEMA_NAME` = 'jala_wms_prod' AND `TABLE_NAME` in ('shipment_header'); - reload statistics; - set session ENABLE_BKA_JOIN = 'true'; - set session ENABLE_SPM = 'TRUE'; - set session ENABLE_AUTO_USE_COLUMNS_PARTITION = 'true'; - set session CONN_POOL_XPROTO_PURE_ASYNC_MPP = 'true'; - set session RECORD_SQL = 'TRUE'; - set session CONN_POOL_XPROTO_CHUNK_RESULT = 'true'; - set session ENABLE_SCALE_OUT_FEATURE = 'true'; - set session MAX_PHYSICAL_PARTITION_COUNT = '8192'; - set session FORBID_EXECUTE_DML_ALL = 'FALSE'; - set session AUTO_PARTITION_PARTITIONS = '32'; - set session GROUP_SEQ_CHECK_INTERVAL = '5'; - set session CONN_POOL_XPROTO_SLOW_THRESH = '1000'; - set session GROUP_PARALLELISM = '8'; - set session MPP_RPC_LOCAL_ENABLED = 'false'; - set session CONN_POOL_MAX_POOL_SIZE = '60'; - set session SQL_DELAY_CUTOFF = '2'; - set session CONN_POOL_PROPERTIES = 'connectTimeout=5000;characterEncoding=utf8;autoReconnect=true;failOverReadOnly=false;socketTimeout=12000;rewriteBatchedStatements=true;useServerPrepStmts=false;useSSL=false'; - set session PARTITIONS_HEATMAP_COLLECTION_MAX_SINGLE_LOGIC_SCHEMA_COUNT = '500'; - set session CONN_POOL_XPROTO_MAX_PACKET_SIZE = '67108864'; - set session CONN_POOL_XPROTO_DIRECT_WRITE = 'false'; - set session CONN_POOL_XPROTO_MAX_SESSION_PER_CLIENT = '1024'; - set session STATISTIC_COLLECTOR_FROM_RULE = 'true'; - set session CONN_POOL_BLOCK_TIMEOUT = '5000'; - set session MPP_TABLESCAN_CONNECTION_STRATEGY = '0'; - set session CONN_POOL_IDLE_TIMEOUT = '60'; - set session CONN_POOL_XPROTO_XPLAN_EXPEND_STAR = 'true'; - set session CONN_POOL_XPROTO_STORAGE_DB_PORT = '0'; - set session MAX_PARTITION_COLUMN_COUNT = '5'; - set session PROCESS_AUTO_INCREMENT_BY_SEQUENCE = 'true'; - set session ALLOW_SIMPLE_SEQUENCE = 'false'; - set session PURGE_TRANS_BEFORE = '604801'; - set session SHOW_TABLE_GROUP_NAME = 'false'; - set session ENABLE_CONST_EXPR_EVAL_CACHE = 'true'; - set session SOCKET_TIMEOUT = '900000'; - set session ENABLE_INTERVAL_ENUMERATION_IN_PRUNING = 'true'; - set session CONN_POOL_XPROTO_META_DB_PORT = '0'; - set session CONN_POOL_MIN_POOL_SIZE = '5'; - set session ENABLE_ALTER_DDL = 'true'; - set session CONN_POOL_XPROTO_PLAN_CACHE = 'true'; - set session MAX_ENUMERABLE_INTERVAL_LENGTH = '32'; - set session CONN_POOL_XPROTO_MAX_CLIENT_PER_INST = '32'; - set session ENABLE_SELF_CROSS_JOIN = 'true'; - set session CONN_POOL_XPROTO_FLAG = '0'; - set session SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE = 'false'; - set session FORCE_APPLY_CACHE = 'TRUE'; - set session CONN_POOL_XPROTO_XPLAN_TABLE_SCAN = 'false'; - set session ENABLE_MPP = 'true'; - set session CONN_POOL_MAX_WAIT_THREAD_COUNT = '0'; - set session CONN_POOL_XPROTO_CONFIG = ''; - set session CONN_POOL_XPROTO_MAX_POOLED_SESSION_PER_INST = '512'; - set session CONN_POOL_XPROTO_SESSION_AGING_TIME = '600000'; - set session CONN_POOL_XPROTO_MIN_POOLED_SESSION_PER_INST = '32'; - set session SQL_SIMPLE_MAX_LENGTH = '1005'; - set session ENABLE_CDC_META_BUILD_SNAPSHOT = 'true'; - set session CHOOSE_STREAMING = 'true'; - set session ENABLE_RUNTIME_FILTER = 'false'; - set session ENABLE_AUTO_MERGE_INTERVALS_IN_PRUNING = 'true'; - set session WORKLOAD_OSS_NET_THRESHOLD = '2'; - set session MAX_IN_SUBQUERY_PRUNING_SIZE = '8192'; - set session CONN_POOL_XPROTO_QUERY_TOKEN = '10000'; - set session HINT_PARSER_FLAG = 'TRUE'; - set session ENABLE_AUTO_USE_RANGE_FOR_TIME_INDEX = 'false'; - set session GET_TSO_TIMEOUT = '5000'; - set session LOGICAL_DB_TIME_ZONE = '+08:00'; - set session STORAGE_SUPPORTS_BLOOM_FILTER = 'true'; - set session INIT_CONCURRENT_POOL_EVERY_CONNECTION = 'false'; - set session COLLATION_SERVER = 'utf8mb4_general_ci'; - set session SINGLE_GROUP_STORAGE_INST_LIST = 'polardbx-storage-0-master'; - set session CONN_POOL_XPROTO_CHECKER = 'true'; - set session ENABLE_RUNTIME_FILTER_XXHASH = 'true'; - set session USE_FAST_SINGLE_POINT_INTERVAL_MERGING = 'false'; - set session CONN_POOL_XPROTO_AUTH = 'true'; - set session ENABLE_DDL = 'TRUE'; - set session DEFAULT_PARTITION_MODE = 'drds'; - set session CONN_POOL_XPROTO_PIPE_BUFFER_SIZE = '268435456'; - set session PURGE_TRANS_INTERVAL = '86401'; - set session CONN_POOL_XPROTO_FEEDBACK = 'true'; - set session CONN_POOL_XPROTO_MESSAGE_TIMESTAMP = 'true'; - set session PARALLELISM = '-1'; - set session PARTITION_PRUNING_STEP_COUNT_LIMIT = '1024'; - set session ENABLE_FORBID_PUSH_DML_WITH_HINT = 'FALSE'; - set session ENABLE_MASTER_MPP = 'true'; - set session SHARD_DB_COUNT_EACH_STORAGE_INST = '2'; - set session PLAN_EXTERNALIZE_TEST = 'TRUE'; - set session NET_WRITE_TIMEOUT = '28800'; - set session CONN_POOL_XPROTO_XPLAN = 'true'; - set session CDC_STARTUP_MODE = '1'; - set session CONN_POOL_XPROTO_TRX_LEAK_CHECK = 'false'; - set session RETRY_ERROR_SQL_ON_OLD_SERVER = 'true'; - set session MAX_LOGICAL_DB_COUNT = '2048'; - set session CONN_POOL_XPROTO_AUTO_COMMIT_OPTIMIZE = 'true'; - set session SHOW_HASH_PARTITIONS_BY_RANGE = 'false'; diff --git a/polardbx-test/src/test/resources/statistics/special/histogram_predicate.yml b/polardbx-test/src/test/resources/statistics/special/histogram_predicate.yml deleted file mode 100644 index cf45b3341..000000000 --- a/polardbx-test/src/test/resources/statistics/special/histogram_predicate.yml +++ /dev/null @@ -1,204 +0,0 @@ -- STATISTIC_TRACE: | - Catalog:gdcams_tp,mk_cu_elec_cust_mr_comp_view,ele_user_category - Action:getCardinality - StatisticValue:9 - - Catalog:gdcams_tp,mk_cu_elec_cust_mr_comp_view,dis_order_num - Action:getCardinality - StatisticValue:4 - - MULTI[71] - Catalog:gdcams_tp,mk_cu_elec_cust_mr_comp_view,MP_SUPPLY_ORG_NO - Action:getCardinality - StatisticValue:1449 - CACHE_LINE, modify by 2023-11-30 02:03:44 - - MULTI[10] - Catalog:gdcams_tp,mk_run_meter_day_energy - Action:getRowCount - StatisticValue:1124532105 - CACHE_LINE, modify by 2023-12-05 09:57:48 - - MULTI[12] - Catalog:gdcams_tp,mk_run_meter_day_energy,RUN_METER_ID - Action:getCardinality - StatisticValue:57584 - CACHE_LINE, modify by 2023-12-05 09:57:48 - - MULTI[42] - Catalog:gdcams_tp,mk_cu_elec_cust_mr_comp_view,dis_order_num,1 - Action:getFrequency - StatisticValue:40710368 - ndv small enough to use histogram - Catalog:gdcams_tp,mk_cu_elec_cust_mr_comp_view,dis_order_num,1_1 - Action:getRangeCount - StatisticValue:40710368 - (long) (rangeCountInHistogram[107762] /sample rate[0.0026470406]) - CACHE_LINE, modify by 2023-11-30 02:03:44 - - MULTI[11] - Catalog:gdcams_tp,eu_org_rela,ORG_DESCENDANT_NO - Action:getCardinality - StatisticValue:11617 - CACHE_LINE, modify by 2023-12-01 11:25:08 - - MULTI[33] - Catalog:gdcams_tp,mk_cu_elec_cust_mr_comp_view - Action:getRowCount - StatisticValue:40870170 - CACHE_LINE, modify by 2023-11-30 02:03:44 - - MULTI[42] - Catalog:gdcams_tp,mk_cu_elec_cust_mr_comp_view,ele_user_category,11 - Action:getFrequency - StatisticValue:15488 - ndv small enough to use histogram - Catalog:gdcams_tp,mk_cu_elec_cust_mr_comp_view,ele_user_category,11_11 - Action:getRangeCount - StatisticValue:15488 - (long) (rangeCountInHistogram[41] /sample rate[0.0026470406]) - CACHE_LINE, modify by 2023-11-30 02:03:44 - - MULTI[22] - Catalog:gdcams_tp,mk_run_meter_day_energy,data_time,2023-12-07 00:00:00_2023-12-08 00:00:00 - Action:datetimeTypeCompensation - StatisticValue:81892745 - normal val:1 - compensation value 2023-12-04 00:00:00_2023-12-05 00:00:00:81892744 - - MULTI[60] - Catalog:gdcams_tp,eu_org_rela,org_no,0306 - Action:getFrequency - StatisticValue:743.0 - topN count(743)/sample rate(1.0) - TOP_N, modify by 1970-01-21 00:36:41 - - MULTI[5] - Catalog:gdcams_tp,mk_cu_elec_cust_mr_comp_view,MR_RUN_METER_ID - Action:getCardinality - StatisticValue:11048772 - CACHE_LINE, modify by 2023-11-30 02:03:44 - - MULTI[28] - Catalog:gdcams_tp,eu_org_rela - Action:getRowCount - StatisticValue:63542 - CACHE_LINE, modify by 2023-12-01 11:25:08 - SQL: | - /*TDDL:ENABLE_RUNTIME_FILTER=false*/select da.TM_COMM_ADDR as tmCommAddr, da.ELEC_CUST_NO as elecCustNo, da.ELEC_CUST_NAME as elecCustName, da.ELE_USER_CATEGORY as elecUserCategory, da.ELEC_ADDR as elecAddr, da.CONTRACT_CAP as contractCap, da.MR_RUN_METER_ID as runMeterId, da.MR_ASSETS_NO as assetsNo, da.MR_COMM_ADDR1 as commAddr1, da.MP_SUPPLY_ORG_NO as orgNo, da.MP_SUPPLY_ORG_NAME as orgName, da.MP_DC_NAME as pOrgName, da.LINE_NO as lineNo, da.LINE_NAME as lineName, da.MP_METERING_POINT_NUMBER as meteringPointNumber, da.MP_NAME as mpName, da.MP_MR_MODE_CODE as mrModeCode, da.MR_TOTAL_FACTOR as totalFactor, da.MP_WIRE_MODE_CODE as meterConnection, da.FACTORY_SHORT_NAME as factoryName, da.EQU_STATUS_CODE as meterRunStatus, da.METER_CATE_CODE as meterType, da.MP_DC_NAME as mpDcName, da.MP_DIS_ORG_SHORT_NAME as mpDisOrgName, da.MP_TOWN_ORG_SHORT_NAME as mpTownOrgName, '/' as regionType, d.DATA_TIME as dataTime, d.PREPOSITION_TIME as prepositionTime, d.PAP_T as papT, d.PAP_PE as papPe, d.PAP_B as papB, d.PAP_V as papV, d.PAP_PO as papPo, d.PRP_T as prpT, d.PRP_PE as prpPe, d.PRP_B as prpB, d.PRP_V as prpV, d.PRP_PO as prpPo, d.NAP_T as napT, d.NAP_PE as napPe, d.NAP_B as napB, d.NAP_V as napV, d.NAP_PO as napPo, d.RRP_T as rrpT, d.RRP_PE as rrpPe, d.RRP_B as rrpB, d.RRP_V as rrpV, d.RRP_PO as rrpPo from MK_CU_ELEC_CUST_MR_COMP_VIEW da join EU_ORG_RELA jg on jg.ORG_DESCENDANT_NO = da.MP_SUPPLY_ORG_NO and jg.ORG_NO ='0306' join MK_RUN_METER_DAY_ENERGY d on da.MR_RUN_METER_ID = d.RUN_METER_ID and d.DATA_TIME >= str_to_date('2023-12-07', '%Y-%m-%d %H:%i:%s') and d.DATA_TIME <= str_to_date('2023-12-08', '%Y-%m-%d %H:%i:%s') where da.DIS_ORDER_NUM = 1 and da.ELE_USER_CATEGORY in ('11') order by da.MR_RUN_METER_ID limit 0,20 - PLAN: | - PhysicalProject - TopN - MppExchange - TopN - HashJoin - LogicalView(tableNames=[[MK_RUN_METER_DAY_ENERGY]]) - MppExchange - LogicalView(tableNames=[[MK_CU_ELEC_CUST_MR_COMP_VIEW, EU_ORG_RELA]]) - CLEAN: | - set global CACHELINE_INDICATE_UPDATE_TIME = 0; - - CATALOG: | - set global CACHELINE_INDICATE_UPDATE_TIME = 1702080000; - set global ENABLE_CACHELINE_COMPENSATION = true; - set global AUTO_PARTITION_PARTITIONS = '16'; - CREATE DATABASE IF NOT EXISTS `gdcams_tp` CHARACTER SET `utf8mb4` COLLATE `utf8mb4_general_ci` MODE 'auto' MODE = 'auto'; - use gdcams_tp; - CREATE TABLE IF NOT EXISTS `eu_org_rela` ( `ORG_NO` varchar(40) NOT NULL, `ORG_DESCENDANT_NO` varchar(40) NOT NULL, `DISTANCE` int(11) DEFAULT NULL, `ORG_RELA_TYPE` varchar(16) NOT NULL, `TENANT_ID` varchar(38) NOT NULL, PRIMARY KEY USING BTREE (`ORG_NO`, `ORG_DESCENDANT_NO`, `ORG_RELA_TYPE`, `TENANT_ID`), KEY `ORG_NO_DISTANCE_KEY` USING BTREE (`ORG_NO`, `DISTANCE`, `ORG_DESCENDANT_NO`, `ORG_RELA_TYPE`, `TENANT_ID`) ) BROADCAST ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; - CREATE TABLE IF NOT EXISTS `mk_cu_elec_cust_mr_comp_view` ( `MR_RUN_METER_ID` varchar(16) NOT NULL, `ELEC_CUST_NO` varchar(20) NOT NULL, `CUST_NO` varchar(20) NOT NULL, `ELEC_CUST_NAME` varchar(128) NOT NULL, `ELEC_ADDR` varchar(128) DEFAULT NULL, `ELEC_SORT_CODE` varchar(8) NOT NULL, `VOLT_CODE` varchar(8) NOT NULL, `TRADE_SORT_CODE` varchar(8) DEFAULT NULL, `ELE_USER_CATEGORY` varchar(8) NOT NULL, `SUPPLY_ORG_NAME` varchar(128) NOT NULL, `SUPPLY_ORG_NO` varchar(20) DEFAULT NULL, `CONTRACT_CAP` decimal(14, 2) DEFAULT NULL, `RUN_CAP` decimal(14, 2) DEFAULT NULL, `LOAD_ATTR_CODE` varchar(8) DEFAULT NULL, `HIGH_ENC_TRADE_CODE` varchar(8) DEFAULT NULL, `BUILD_DATE` datetime DEFAULT NULL, `POWER_DATE` datetime DEFAULT NULL, `CANCEL_ELEC_DATE` datetime DEFAULT NULL, `POWER_TYPE_CODE` varchar(8) DEFAULT NULL, `AREA_CODE` varchar(8) NOT NULL, `HARMONIC_CUST_FLAG` varchar(8) DEFAULT NULL, `IMPACT_LOAD_FLAG` varchar(8) DEFAULT NULL, `STEP_SORT` varchar(8) DEFAULT NULL, `MARKET_CUST_FLAG` varchar(8) DEFAULT NULL, `NEW_INDUSTRY_CODE` varchar(8) DEFAULT NULL, `HIGH_RELIBILITY_FLAG` varchar(8) DEFAULT NULL, `LNG` varchar(32) DEFAULT NULL, `LAT` varchar(32) DEFAULT NULL, `NINE_ELEC_SORT_CODE` varchar(8) DEFAULT NULL, `NEW_INFRASTRUCT_SIGN` varchar(8) DEFAULT NULL, `CUST_STATUS_CODE` varchar(8) NOT NULL, `SUPPLY_CODE` varchar(8) DEFAULT NULL, `ATTR_CODE` varchar(8) DEFAULT NULL, `TQ_TA_ID` varchar(16) DEFAULT NULL, `TQ_TA_NO` varchar(20) DEFAULT NULL, `TQ_TA_NAME` varchar(128) DEFAULT NULL, `TQ_TA_TYPE` varchar(8) DEFAULT NULL, `TQ_AREA_ATTR_CODE` varchar(8) DEFAULT NULL, `TQ_TA_ADDR` varchar(128) DEFAULT NULL, `TQ_LL_EXAM_TYPE` varchar(8) DEFAULT NULL, `TQ_RUN_STATUS_CODE` varchar(8) DEFAULT NULL, `CHARGE_PILE_FLAG` varchar(8) DEFAULT NULL, `CHARGPILE_USER_CATE_CODE` varchar(8) DEFAULT NULL, `MP_MR_EQU_SORT_CODE` varchar(8) DEFAULT NULL, `MP_ELEC_SORT_CODE` varchar(8) NOT NULL, `MP_METERING_POINT_NUMBER` varchar(20) NOT NULL, `MP_NAME` varchar(128) DEFAULT NULL, `MP_MR_MODE_CODE` varchar(8) NOT NULL, `MP_MR_VOLT_CODE` varchar(8) DEFAULT NULL, `MP_USEAGE_CODE` varchar(8) DEFAULT NULL, `MP_ADDR` varchar(128) DEFAULT NULL, `MP_POSITION_CODE` varchar(8) DEFAULT NULL, `MP_WIRE_MODE_CODE` varchar(8) DEFAULT NULL, `MP_PT_RATIO_CODE` varchar(8) DEFAULT NULL, `MP_CT_RATIO_CODE` varchar(8) DEFAULT NULL, `MP_GRID_PQ_MR_DIRECTION` varchar(8) DEFAULT NULL, `MP_TIDE_DIRECT_CODE` varchar(8) DEFAULT NULL, `MP_RUN_DATE` datetime DEFAULT NULL, `MP_PRICE_CODE` varchar(8) NOT NULL, `MP_MP_STATUS_CODE` varchar(8) DEFAULT NULL, `MP_TRADE_SORT_CODE` varchar(8) DEFAULT NULL, `MP_TS_BILL_FLAG` varchar(8) DEFAULT NULL, `MP_MAIN_AND_ASSIST_FLAG` varchar(8) DEFAULT NULL, `MP_ER_TYPE` varchar(8) DEFAULT NULL, `MP_ELEC_CUST_NO` varchar(20) NOT NULL, `MP_SUPPLY_ORG_NO` varchar(20) NOT NULL, `MP_SUPPLY_ORG_NAME` varchar(128) NOT NULL, `MP_DC_NAME` varchar(128) DEFAULT NULL, `MP_DC_NO` varchar(128) DEFAULT NULL, `MP_DIS_ORG_NO` varchar(20) DEFAULT NULL, `MP_DIS_ORG_SHORT_NAME` varchar(128) DEFAULT NULL, `MP_TOWN_ORG_NO` varchar(20) DEFAULT NULL, `MP_TOWN_ORG_SHORT_NAME` varchar(128) DEFAULT NULL, `ORG_PATH` varchar(256) NOT NULL, `MR_EQU_ID` varchar(16) DEFAULT NULL, `MR_ASSETS_NO` varchar(32) DEFAULT NULL, `MR_MADE_NO` varchar(32) DEFAULT NULL, `MR_TOTAL_FACTOR` decimal(12, 3) NOT NULL, `MR_READ_ORDER` decimal(5, 0) DEFAULT NULL, `MR_METER_DIGITS_CODE` varchar(8) DEFAULT NULL, `MR_TIME_DIGIT_CODE` varchar(8) DEFAULT NULL, `MR_MA_AUXIL_TABLE_SIGNS` varchar(8) NOT NULL, `MR_COMM_ADDR1` varchar(32) DEFAULT NULL, `MR_COMM_ADDR2` varchar(32) DEFAULT NULL, `MR_COMM_PROTOCOL_CODE` varchar(128) DEFAULT NULL, `MR_BAUD_RATE` varchar(32) DEFAULT NULL, `MR_COMM_MODE_CODE` varchar(128) DEFAULT NULL, `MR_PARAM_ID` varchar(16) DEFAULT NULL, `MR_OPER_COMM_PROTOCOL` varchar(8) DEFAULT NULL, `MR_OPER_COMM_MODE` varchar(8) DEFAULT NULL, `DIS_ORDER_NUM` decimal(5, 0) NOT NULL, `CREATE_TIME` datetime NOT NULL, `OPERATED_TIME` datetime NOT NULL, `FACTORY_SHORT_NAME` varchar(32) DEFAULT NULL, `EQU_TYPE_CODE` varchar(8) DEFAULT NULL, `ARRIVE_BATCH` varchar(20) NOT NULL, `EQU_STATUS_CODE` varchar(8) NOT NULL, `MADE_DATE` datetime DEFAULT NULL, `FILE_DATE` datetime DEFAULT NULL, `FIRST_OPER_DATE` datetime DEFAULT NULL, `COMM_MODULA_TYPE_CODE` varchar(128) DEFAULT NULL, `METER_SELF_FACTOR` decimal(12, 3) DEFAULT NULL, `RV_CODE` varchar(8) DEFAULT NULL, `STAND_CURR_CODE` varchar(8) DEFAULT NULL, `PHASE_LINE_CODE` varchar(8) DEFAULT NULL, `METER_CATE_CODE` varchar(8) DEFAULT NULL, `ACCESS_MODE_CODE` varchar(8) DEFAULT NULL, `TS_FLAG` varchar(8) DEFAULT NULL, `EQU_MODEL_CODE` varchar(32) DEFAULT NULL, `PRE_LEVEL_CODE` varchar(8) DEFAULT NULL, `PR_CODE` varchar(8) NOT NULL DEFAULT '1', `MR_RUN_TERM_ID` varchar(16) NOT NULL, `TM_COMM_ADDR` varchar(128) DEFAULT NULL, `TM_ASSETS_NO` varchar(32) DEFAULT NULL, `TM_EQU_SORT_CODE` varchar(8) DEFAULT NULL, `TM_FACTORY_SHORT_NAME` varchar(32) DEFAULT NULL, `TM_UP_PROTOCOL_CODE` varchar(128) DEFAULT NULL, `TM_MAIN_TERM_FLAG` varchar(8) DEFAULT NULL, `TM_EQU_STATUS_CODE` varchar(8) NOT NULL, `EQU_ID` varchar(16) NOT NULL, `POWER_LINE_SEGM_ID` varchar(16) DEFAULT NULL, `LINE_NO` varchar(20) DEFAULT NULL, `LINE_NAME` varchar(128) DEFAULT NULL, `SUBS_ID` varchar(16) DEFAULT NULL, `SUBS_NO` varchar(20) DEFAULT NULL, `SUBS_NAME` varchar(128) DEFAULT NULL, `MP_ELE_CAPACITY` decimal(14, 2) DEFAULT NULL, `TM_FACTORY_ID` varchar(16) DEFAULT NULL, `TM_TERM_TYPE` varchar(8) DEFAULT NULL, `TERM_USEAGE` varchar(8) DEFAULT NULL, `USE_GRID_DIRECTION` varchar(8) DEFAULT NULL, `TM_COMM_MODULA_TYPE_CODE` varchar(128) DEFAULT NULL, `SUBS_TYPE_CODE` varchar(8) DEFAULT NULL, `MARKET_ATTR_SORT_CODE` varchar(8) DEFAULT NULL, `RECORD_STATUS` varchar(8) DEFAULT NULL, `RECORD_DELETE_DATE` datetime DEFAULT NULL, `ZERO_PQ_FLAG` varchar(8) DEFAULT NULL, PRIMARY KEY (`MP_SUPPLY_ORG_NO`, `MR_RUN_METER_ID`, `ELEC_CUST_NO`, `MP_METERING_POINT_NUMBER`, `DIS_ORDER_NUM`), KEY `idx_mk_cu_elec_cust_mr_comp_view` (`MP_SUPPLY_ORG_NO`, `LINE_NO`, `ELEC_CUST_NO`, `ELE_USER_CATEGORY`, `MP_METERING_POINT_NUMBER`, `MR_ASSETS_NO`, `DIS_ORDER_NUM`), KEY `idx2_mk_cu_elec_cust_mr_comp_view` (`ELEC_CUST_NO`), KEY `idx3_mk_cu_elec_cust_mr_comp_view` (`MP_SUPPLY_ORG_NO`, `ELEC_CUST_NO`), KEY `idx4_mk_cu_elec_cust_mr_comp_view` (`MP_SUPPLY_ORG_NO`, `TM_COMM_ADDR`, `MR_READ_ORDER`), KEY `idx5_mk_cu_elec_cust_mr_comp_view` (`AREA_CODE`), KEY `idx6_MK_CU_ELEC_CUST_MR_COMP_VIEW` (`MP_METERING_POINT_NUMBER`), KEY `auto_shard_key_mr_run_meter_id` USING BTREE (`MR_RUN_METER_ID`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY (`MR_RUN_METER_ID`) PARTITIONS 16; - CREATE TABLE IF NOT EXISTS `mk_run_meter_day_energy` ( `RUN_METER_ID` varchar(16) NOT NULL, `DATA_TIME` datetime NOT NULL, `PREPOSITION_TIME` datetime DEFAULT NULL, `PAP_T` decimal(15, 4) DEFAULT NULL, `PAP_PE` decimal(15, 4) DEFAULT NULL, `PAP_B` decimal(15, 4) DEFAULT NULL, `PAP_V` decimal(15, 4) DEFAULT NULL, `PAP_PO` decimal(15, 4) DEFAULT NULL, `PRP_T` decimal(15, 4) DEFAULT NULL, `PRP_PE` decimal(15, 4) DEFAULT NULL, `PRP_B` decimal(15, 4) DEFAULT NULL, `PRP_V` decimal(15, 4) DEFAULT NULL, `PRP_PO` decimal(15, 4) DEFAULT NULL, `NAP_T` decimal(15, 4) DEFAULT NULL, `NAP_PE` decimal(15, 4) DEFAULT NULL, `NAP_B` decimal(15, 4) DEFAULT NULL, `NAP_V` decimal(15, 4) DEFAULT NULL, `NAP_PO` decimal(15, 4) DEFAULT NULL, `RRP_T` decimal(15, 4) DEFAULT NULL, `RRP_PE` decimal(15, 4) DEFAULT NULL, `RRP_B` decimal(15, 4) DEFAULT NULL, `RRP_V` decimal(15, 4) DEFAULT NULL, `RRP_PO` decimal(15, 4) DEFAULT NULL, `QUAD_1_R` decimal(15, 4) DEFAULT NULL, `QUAD_2_R` decimal(15, 4) DEFAULT NULL, `QUAD_3_R` decimal(15, 4) DEFAULT NULL, `QUAD_4_R` decimal(15, 4) DEFAULT NULL, `DATA_SOURCE_CODE` varchar(8) DEFAULT NULL, `AREA_CODE` varchar(8) DEFAULT NULL, `LOAD_TIME` datetime DEFAULT NULL, `DATA_PART` int(11) NOT NULL, PRIMARY KEY (`RUN_METER_ID`, `DATA_TIME`, `DATA_PART`), KEY `auto_shard_key_data_time` USING BTREE (`DATA_TIME`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 PARTITION BY KEY (`RUN_METER_ID`) PARTITIONS 16 SUBPARTITION BY RANGE COLUMNS (`DATA_TIME`) ( SUBPARTITION `sp1` VALUES LESS THAN ('2023-03-01 00:00:00'), SUBPARTITION `sp2` VALUES LESS THAN ('2023-04-01 00:00:00'), SUBPARTITION `sp3` VALUES LESS THAN ('2023-05-01 00:00:00'), SUBPARTITION `sp4` VALUES LESS THAN ('2023-06-01 00:00:00'), SUBPARTITION `sp5` VALUES LESS THAN ('2023-07-01 00:00:00'), SUBPARTITION `sp6` VALUES LESS THAN ('2023-08-01 00:00:00'), SUBPARTITION `sp7` VALUES LESS THAN ('2023-09-01 00:00:00'), SUBPARTITION `sp8` VALUES LESS THAN ('2023-10-01 00:00:00'), SUBPARTITION `sp9` VALUES LESS THAN ('2023-11-01 00:00:00'), SUBPARTITION `sp10` VALUES LESS THAN ('2023-12-01 00:00:00'), SUBPARTITION `sp11` VALUES LESS THAN ('2024-01-01 00:00:00'), SUBPARTITION `sp12` VALUES LESS THAN ('2024-02-01 00:00:00'), SUBPARTITION `sp13` VALUES LESS THAN ('2024-03-01 00:00:00'), SUBPARTITION `sp14` VALUES LESS THAN ('2024-04-01 00:00:00') ); - DELETE FROM metadb.table_statistics WHERE `SCHEMA_NAME` = 'gdcams_tp' AND `TABLE_NAME` in ('eu_org_rela','mk_cu_elec_cust_mr_comp_view','mk_run_meter_day_energy'); - INSERT INTO metadb.table_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `ROW_COUNT`) VALUES ('gdcams_tp','eu_org_rela',63542),('gdcams_tp','mk_cu_elec_cust_mr_comp_view',40870170),('gdcams_tp','mk_run_meter_day_energy',1124532105); - DELETE FROM metadb.column_statistics WHERE `SCHEMA_NAME` = 'gdcams_tp' AND `TABLE_NAME` in ('eu_org_rela','mk_cu_elec_cust_mr_comp_view','mk_run_meter_day_energy'); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('gdcams_tp','eu_org_rela','distance',8,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Int","sampleRate":1.0}','{"countArr":[11631,11440,11331,11290,10505,7015,235,95],"valueArr":[0,1,2,3,4,5,6,7],"type":"Int","sampleRate":1.0}',0,1.0),('gdcams_tp','eu_org_rela','org_descendant_no',11617,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":198,"upper":"0302101301","lower":"00","count":994,"preSum":0},{"ndv":186,"upper":"030217","lower":"0302101302","count":996,"preSum":994},{"ndv":197,"upper":"0304030903","lower":"03021701","count":998,"preSum":1990},{"ndv":197,"upper":"0305230411","lower":"0304030904","count":997,"preSum":2988},{"ndv":176,"upper":"0305470106","lower":"0305230412","count":998,"preSum":3985},{"ndv":172,"upper":"03054805","lower":"0305470107","count":996,"preSum":4983},{"ndv":170,"upper":"0305490714","lower":"03054806","count":995,"preSum":5979},{"ndv":175,"upper":"03060415","lower":"03054908","count":996,"preSum":6974},{"ndv":172,"upper":"0306121732","lower":"03060416","count":996,"preSum":7970},{"ndv":170,"upper":"0306131804","lower":"0306121733","count":998,"preSum":8966},{"ndv":170,"upper":"0306150725","lower":"0306131805","count":994,"preSum":9964},{"ndv":183,"upper":"0307021805","lower":"0306150726","count":998,"preSum":10958},{"ndv":174,"upper":"0307051401","lower":"03070219","count":996,"preSum":11956},{"ndv":177,"upper":"0307130601","lower":"0307051402","count":996,"preSum":12952},{"ndv":177,"upper":"03071802","lower":"0307130602","count":995,"preSum":13948},{"ndv":204,"upper":"0308023404","lower":"030719","count":994,"preSum":14943},{"ndv":186,"upper":"03081409","lower":"0308023405","count":993,"preSum":15937},{"ndv":188,"upper":"03082022","lower":"0308140906","count":995,"preSum":16930},{"ndv":182,"upper":"03083411","lower":"0308202201","count":993,"preSum":17925},{"ndv":180,"upper":"0309082102","lower":"030836","count":995,"preSum":18918},{"ndv":178,"upper":"03091029","lower":"03090822","count":993,"preSum":19913},{"ndv":183,"upper":"0312030402","lower":"03091030","count":998,"preSum":20906},{"ndv":179,"upper":"0312091601","lower":"03120305","count":998,"preSum":21904},{"ndv":174,"upper":"03121207","lower":"0312091602","count":996,"preSum":22902},{"ndv":183,"upper":"0313041804","lower":"0312120701","count":997,"preSum":23898},{"ndv":182,"upper":"0313142304","lower":"0313041805","count":998,"preSum":24895},{"ndv":194,"upper":"03140313","lower":"03131424","count":997,"preSum":25893},{"ndv":179,"upper":"03140710","lower":"0314031301","count":997,"preSum":26890},{"ndv":185,"upper":"0314140201","lower":"03140711","count":998,"preSum":27887},{"ndv":183,"upper":"0315021801","lower":"0314140202","count":994,"preSum":28885},{"ndv":182,"upper":"0315042602","lower":"0315021802","count":993,"preSum":29879},{"ndv":184,"upper":"0316011120","lower":"03150427","count":996,"preSum":30872},{"ndv":173,"upper":"0316091306","lower":"03160112","count":996,"preSum":31868},{"ndv":177,"upper":"0316101302","lower":"03160914","count":995,"preSum":32864},{"ndv":186,"upper":"0316250307","lower":"0316101303","count":995,"preSum":33859},{"ndv":193,"upper":"0316260404","lower":"03162504","count":998,"preSum":34854},{"ndv":185,"upper":"0317040801","lower":"0316260405","count":995,"preSum":35852},{"ndv":182,"upper":"0317100802","lower":"03170409","count":995,"preSum":36847},{"ndv":194,"upper":"0318211301","lower":"0317100902","count":997,"preSum":37842},{"ndv":179,"upper":"0318270302","lower":"0318211302","count":996,"preSum":38839},{"ndv":179,"upper":"0318820108","lower":"0318270303","count":995,"preSum":39835},{"ndv":182,"upper":"0319080209","lower":"0318820109","count":996,"preSum":40830},{"ndv":191,"upper":"0319160303","lower":"0319080210","count":993,"preSum":41826},{"ndv":191,"upper":"0319260208","lower":"0319160304","count":993,"preSum":42819},{"ndv":190,"upper":"031937","lower":"0319260209","count":995,"preSum":43812},{"ndv":191,"upper":"0319630104","lower":"03193701","count":997,"preSum":44807},{"ndv":178,"upper":"0319700602","lower":"0319630105","count":998,"preSum":45804},{"ndv":175,"upper":"03197309","lower":"0319700603","count":997,"preSum":46802},{"ndv":176,"upper":"03198101","lower":"0319730901","count":996,"preSum":47799},{"ndv":185,"upper":"03202702","lower":"03198102","count":993,"preSum":48795},{"ndv":201,"upper":"03510304","lower":"03202703","count":996,"preSum":49788},{"ndv":176,"upper":"03510917","lower":"03510305","count":995,"preSum":50784},{"ndv":181,"upper":"0351880407","lower":"0351091701","count":995,"preSum":51779},{"ndv":175,"upper":"03520309","lower":"0351880408","count":995,"preSum":52774},{"ndv":174,"upper":"0352062601","lower":"0352030901","count":998,"preSum":53769},{"ndv":173,"upper":"0352072405","lower":"0352062602","count":997,"preSum":54767},{"ndv":200,"upper":"03521601","lower":"03520725","count":993,"preSum":55764},{"ndv":188,"upper":"0353062002","lower":"03521602","count":993,"preSum":56757},{"ndv":186,"upper":"03570201010131","lower":"03530621","count":998,"preSum":57750},{"ndv":164,"upper":"0800031101","lower":"03570201010132","count":997,"preSum":58748},{"ndv":176,"upper":"080011110206","lower":"08000312","count":998,"preSum":59745},{"ndv":161,"upper":"08001311","lower":"080011110207","count":995,"preSum":60743},{"ndv":175,"upper":"080033","lower":"0800131101","count":993,"preSum":61738},{"ndv":174,"upper":"DZHYJFTP","lower":"080034","count":811,"preSum":62731}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[],"valueArr":[],"type":"String","sampleRate":1.0}',0,1.0),('gdcams_tp','eu_org_rela','org_no',16017,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":23,"upper":"030202","lower":"0301","count":520,"preSum":0},{"ndv":214,"upper":"030213","lower":"03020201","count":511,"preSum":520},{"ndv":237,"upper":"0304","lower":"03021302","count":656,"preSum":1031},{"ndv":230,"upper":"030522","lower":"030401","count":537,"preSum":1687},{"ndv":193,"upper":"0305460707","lower":"03052201","count":508,"preSum":2224},{"ndv":184,"upper":"0305471706","lower":"03054608","count":508,"preSum":2732},{"ndv":169,"upper":"030549","lower":"03054718","count":556,"preSum":3240},{"ndv":230,"upper":"030612","lower":"03054901","count":678,"preSum":3796},{"ndv":181,"upper":"030613","lower":"03061203","count":552,"preSum":4474},{"ndv":224,"upper":"0306140511","lower":"03061301","count":508,"preSum":5026},{"ndv":222,"upper":"030702","lower":"0306140512","count":577,"preSum":5534},{"ndv":196,"upper":"0307050805","lower":"03070201","count":508,"preSum":6111},{"ndv":191,"upper":"030713","lower":"03070509","count":544,"preSum":6619},{"ndv":234,"upper":"0308010102","lower":"03071301","count":508,"preSum":7163},{"ndv":198,"upper":"030810","lower":"03080103","count":572,"preSum":7671},{"ndv":229,"upper":"0308150601","lower":"03081002","count":508,"preSum":8243},{"ndv":190,"upper":"030828","lower":"0308150602","count":528,"preSum":8751},{"ndv":222,"upper":"0309026501","lower":"03082801","count":508,"preSum":9279},{"ndv":177,"upper":"030910","lower":"0309026502","count":512,"preSum":9787},{"ndv":167,"upper":"0312","lower":"03091001","count":806,"preSum":10299},{"ndv":186,"upper":"031206","lower":"031201","count":508,"preSum":11105},{"ndv":189,"upper":"03121129","lower":"03120601","count":524,"preSum":11613},{"ndv":203,"upper":"0313041404","lower":"0312112906","count":508,"preSum":12137},{"ndv":223,"upper":"031316","lower":"0313041405","count":527,"preSum":12645},{"ndv":227,"upper":"031405","lower":"03131602","count":541,"preSum":13172},{"ndv":195,"upper":"03140807","lower":"03140501","count":512,"preSum":13713},{"ndv":223,"upper":"03141426","lower":"0314080702","count":508,"preSum":14225},{"ndv":36,"upper":"03150202","lower":"031415","count":508,"preSum":14733},{"ndv":242,"upper":"03150433","lower":"0315020201","count":508,"preSum":15241},{"ndv":182,"upper":"0316011206","lower":"0315043301","count":508,"preSum":15749},{"ndv":181,"upper":"03160916","lower":"031601121","count":512,"preSum":16257},{"ndv":176,"upper":"03161015","lower":"0316091601","count":508,"preSum":16769},{"ndv":189,"upper":"03162506","lower":"0316101501","count":508,"preSum":17277},{"ndv":232,"upper":"0316261104","lower":"0316250601","count":508,"preSum":17785},{"ndv":109,"upper":"03170309","lower":"0316261105","count":508,"preSum":18293},{"ndv":195,"upper":"031710","lower":"03170310","count":531,"preSum":18801},{"ndv":226,"upper":"031823","lower":"03171005","count":531,"preSum":19332},{"ndv":208,"upper":"031881","lower":"03182301","count":569,"preSum":19863},{"ndv":240,"upper":"03190503","lower":"03188101","count":510,"preSum":20432},{"ndv":198,"upper":"03191303","lower":"0319050301","count":508,"preSum":20942},{"ndv":204,"upper":"031924","lower":"0319130301","count":514,"preSum":21450},{"ndv":204,"upper":"0319350205","lower":"03192401","count":508,"preSum":21964},{"ndv":218,"upper":"03196301","lower":"0319350206","count":517,"preSum":22472},{"ndv":198,"upper":"03197010","lower":"0319630101","count":508,"preSum":22989},{"ndv":177,"upper":"031974","lower":"0319701001","count":512,"preSum":23497},{"ndv":172,"upper":"0320","lower":"03197401","count":730,"preSum":24009},{"ndv":205,"upper":"0320310102","lower":"032006","count":508,"preSum":24739},{"ndv":161,"upper":"0351","lower":"0320310103","count":691,"preSum":25247},{"ndv":157,"upper":"03510913","lower":"035101","count":509,"preSum":25938},{"ndv":215,"upper":"035202","lower":"0351091301","count":583,"preSum":26447},{"ndv":224,"upper":"035206","lower":"03520201","count":637,"preSum":27030},{"ndv":221,"upper":"0352071302","lower":"03520601","count":508,"preSum":27667},{"ndv":214,"upper":"03521515","lower":"0352071303","count":508,"preSum":28175},{"ndv":105,"upper":"035304","lower":"0352151501","count":547,"preSum":28683},{"ndv":257,"upper":"035329","lower":"03530401","count":512,"preSum":29230},{"ndv":33,"upper":"0357020101","lower":"03532901","count":545,"preSum":29742},{"ndv":244,"upper":"0800050401","lower":"035702010101","count":508,"preSum":30287},{"ndv":182,"upper":"080011210202","lower":"0800050402","count":508,"preSum":30795},{"ndv":161,"upper":"080015","lower":"080011210203","count":533,"preSum":31303},{"ndv":214,"upper":"0800834005","lower":"08001501","count":508,"preSum":31836},{"ndv":80,"upper":"DZHYJFTP","lower":"0800834006","count":141,"preSum":32344}],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[11333,11332,709,743,620,660,462,460,545,912,541,1360,710,670],"valueArr":["00","03","0305","0306","0307","0308","0309","0313","0314","0316","0318","0319","0352","0800"],"type":"String","sampleRate":1.0}',0,1.0),('gdcams_tp','eu_org_rela','org_rela_type',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[63542],"valueArr":["admin"],"type":"String","sampleRate":1.0}',0,1.0),('gdcams_tp','eu_org_rela','tenant_id',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":1.0}','{"countArr":[63542],"valueArr":["LSPT"],"type":"String","sampleRate":1.0}',0,1.0),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','access_mode_code',29,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"2.0","lower":"2.0","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[95907,2276],"valueArr":["1","2"],"type":"String","sampleRate":0.924351804778851}',1817,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','area_code',19,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"030400","lower":"030400","count":2912,"preSum":0},{"ndv":1,"upper":"031500","lower":"031500","count":2652,"preSum":2912},{"ndv":1,"upper":"031600","lower":"031600","count":3071,"preSum":5564},{"ndv":1,"upper":"031700","lower":"031700","count":3270,"preSum":8635},{"ndv":1,"upper":"035300","lower":"035300","count":3086,"preSum":11905}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[4032,5972,10034,6679,6095,6323,5211,8653,4635,5282,8073,4160,3307,6554],"valueArr":["030200","030500","030600","030700","030800","030900","031200","031300","031400","031800","031900","032000","035100","035200"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','arrive_batch',34706,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":185,"upper":"03201601220039","lower":" ","count":1498,"preSum":0},{"ndv":80,"upper":"03201604070006","lower":"03201601250004","count":1505,"preSum":1498},{"ndv":61,"upper":"03201604290018","lower":"03201604070011","count":1512,"preSum":3003},{"ndv":76,"upper":"03201606060049","lower":"03201604290023","count":1508,"preSum":4515},{"ndv":67,"upper":"03201607050040","lower":"03201606070038","count":1508,"preSum":6023},{"ndv":102,"upper":"03201609050029","lower":"03201607050053","count":1504,"preSum":7531},{"ndv":63,"upper":"03201609260101","lower":"03201609050030","count":1507,"preSum":9035},{"ndv":66,"upper":"03201610130011","lower":"03201609260120","count":1535,"preSum":10542},{"ndv":71,"upper":"03201610270101","lower":"03201610130014","count":1502,"preSum":12077},{"ndv":60,"upper":"03201611030102","lower":"03201610270147","count":1512,"preSum":13579},{"ndv":84,"upper":"03201611200002","lower":"03201611030123","count":1500,"preSum":15091},{"ndv":63,"upper":"03201612130038","lower":"03201611200003","count":1549,"preSum":16591},{"ndv":76,"upper":"03201701180023","lower":"03201612130050","count":1517,"preSum":18140},{"ndv":84,"upper":"03201703230004","lower":"03201701180029","count":1507,"preSum":19657},{"ndv":77,"upper":"03201705080022","lower":"03201703230012","count":1555,"preSum":21164},{"ndv":68,"upper":"03201705190028","lower":"03201705080032","count":1505,"preSum":22719},{"ndv":63,"upper":"03201706010042","lower":"03201705190030","count":1575,"preSum":24224},{"ndv":100,"upper":"03201706160048","lower":"03201706010046","count":1505,"preSum":25799},{"ndv":109,"upper":"03201707100070","lower":"03201706160066","count":1505,"preSum":27304},{"ndv":112,"upper":"03201708090059","lower":"03201707100073","count":1537,"preSum":28809},{"ndv":42,"upper":"03201708160022","lower":"03201708090061","count":1539,"preSum":30346},{"ndv":50,"upper":"03201708240021","lower":"03201708160024","count":1599,"preSum":31885},{"ndv":44,"upper":"03201708310032","lower":"03201708240026","count":1501,"preSum":33484},{"ndv":49,"upper":"03201709070022","lower":"03201708310040","count":1504,"preSum":34985},{"ndv":49,"upper":"03201709140046","lower":"03201709070023","count":1515,"preSum":36489},{"ndv":48,"upper":"03201709210009","lower":"03201709140047","count":1568,"preSum":38004},{"ndv":48,"upper":"03201709280043","lower":"03201709210021","count":1498,"preSum":39572},{"ndv":48,"upper":"03201710090041","lower":"03201709280057","count":1523,"preSum":41070},{"ndv":49,"upper":"03201710160023","lower":"03201710100009","count":1498,"preSum":42593},{"ndv":60,"upper":"03201710240046","lower":"03201710160033","count":1509,"preSum":44091},{"ndv":75,"upper":"03201711020053","lower":"03201710240047","count":1535,"preSum":45600},{"ndv":66,"upper":"03201711170015","lower":"03201711020054","count":1511,"preSum":47135},{"ndv":118,"upper":"03201712250043","lower":"03201711170020","count":1507,"preSum":48646},{"ndv":65,"upper":"03201801180022","lower":"03201712250055","count":1520,"preSum":50153},{"ndv":58,"upper":"03201801310033","lower":"03201801180060","count":1529,"preSum":51673},{"ndv":36,"upper":"03201802120019","lower":"03201801310049","count":1503,"preSum":53202},{"ndv":55,"upper":"03201803130026","lower":"03201802220024","count":1613,"preSum":54705},{"ndv":58,"upper":"03201803260017","lower":"03201803140005","count":1597,"preSum":56318},{"ndv":71,"upper":"03201804170012","lower":"03201803270005","count":1544,"preSum":57915},{"ndv":101,"upper":"03201806220043","lower":"03201804170017","count":1509,"preSum":59459},{"ndv":130,"upper":"03201808270021","lower":"03201806250037","count":1574,"preSum":60968},{"ndv":205,"upper":"03201901040067","lower":"03201808270037","count":1503,"preSum":62542},{"ndv":318,"upper":"20111024846","lower":"03201901050003","count":1518,"preSum":64045},{"ndv":319,"upper":"201405051780","lower":"201110261306","count":1530,"preSum":65563},{"ndv":245,"upper":"201504291261","lower":"201405051781","count":1557,"preSum":67093},{"ndv":268,"upper":"2021908091466456","lower":"201505041709","count":1506,"preSum":68650},{"ndv":222,"upper":"2021910301676711","lower":"2021908091467495","count":1503,"preSum":70156},{"ndv":114,"upper":"2022001162205908","lower":"2021910301676874","count":1512,"preSum":71659},{"ndv":131,"upper":"2022007285255885","lower":"2022001162205940","count":1503,"preSum":73171},{"ndv":101,"upper":"2022009286101720","lower":"2022007285256166","count":1508,"preSum":74674},{"ndv":195,"upper":"2022103037728453","lower":"2022009286101770","count":1504,"preSum":76182},{"ndv":128,"upper":"2022104278685010","lower":"2022103037728485","count":1505,"preSum":77686},{"ndv":188,"upper":"2022107292563142","lower":"2022104278686263","count":1505,"preSum":79191},{"ndv":174,"upper":"2022109234717665","lower":"2022107292563936","count":1523,"preSum":80696},{"ndv":117,"upper":"2022111105916358","lower":"2022109234718167","count":1518,"preSum":82219},{"ndv":153,"upper":"2022201247917161","lower":"2022111155958531","count":1498,"preSum":83737},{"ndv":157,"upper":"2022204292148473","lower":"2022201247941348","count":1511,"preSum":85235},{"ndv":107,"upper":"2022206133179560","lower":"2022204292148495","count":1514,"preSum":86746},{"ndv":69,"upper":"2022207214745309","lower":"2022206133276893","count":1505,"preSum":88260},{"ndv":78,"upper":"2022209085648135","lower":"2022207274880083","count":1518,"preSum":89765},{"ndv":87,"upper":"2022210106160271","lower":"2022209085648544","count":1512,"preSum":91283},{"ndv":81,"upper":"2022211176611380","lower":"2022210106162005","count":1505,"preSum":92795},{"ndv":168,"upper":"2022305151041316","lower":"2022211186618428","count":1499,"preSum":94300},{"ndv":20,"upper":"无","lower":"2022305171060827","count":38,"preSum":95799}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[328,201,215,294,211,294,621,207,463,216,246,254,390,224],"valueArr":["03201603280042","03201604280047","03201610090075","03201610140055","03201610170061","03201612090011","03201612200046","03201701040003","03201705050018","03201709110044","03201709280003","03201710100023","03201808270007","20111129884"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','attr_code',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[153,301,96644,14],"valueArr":["1","2","3","4"],"type":"String","sampleRate":0.924351804778851}',2889,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','build_date',1173455,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":379,"upper":"1825231083550015488","lower":"-1","count":1213,"preSum":0},{"ndv":574,"upper":"1828745122712387584","lower":"1825250874759315456","count":1298,"preSum":1213},{"ndv":208,"upper":"1829323465828597760","lower":"1828751719782154240","count":1216,"preSum":2511},{"ndv":238,"upper":"1829978774758752256","lower":"1829325664851853312","count":1303,"preSum":3727},{"ndv":305,"upper":"1830774821177262080","lower":"1829979411772866560","count":1213,"preSum":5030},{"ndv":392,"upper":"1831689614851571712","lower":"1830777020200517632","count":1216,"preSum":6243},{"ndv":260,"upper":"1832265758944526336","lower":"1831691813874827264","count":1234,"preSum":7459},{"ndv":233,"upper":"1832817713781669888","lower":"1832266402115878912","count":1265,"preSum":8693},{"ndv":319,"upper":"1833442236386246656","lower":"1832819912804925440","count":1213,"preSum":9958},{"ndv":452,"upper":"1834027801489965056","lower":"1833444435409502208","count":1213,"preSum":11171},{"ndv":466,"upper":"1834656097223311360","lower":"1834029375595479040","count":1506,"preSum":12384},{"ndv":386,"upper":"1835149777944182784","lower":"1834659026307121152","count":1221,"preSum":13890},{"ndv":288,"upper":"1835188260851154944","lower":"1835149804284411904","count":1217,"preSum":15111},{"ndv":493,"upper":"1835656652804587520","lower":"1835188902646775808","count":1220,"preSum":16328},{"ndv":575,"upper":"1836084391718158336","lower":"1835658851827843072","count":1213,"preSum":17548},{"ndv":731,"upper":"1836619824990519296","lower":"1836084422756007936","count":1217,"preSum":18761},{"ndv":730,"upper":"1837026644292796416","lower":"1836620844273500160","count":1216,"preSum":19978},{"ndv":593,"upper":"1837470846990417920","lower":"1837027253205073920","count":1295,"preSum":21194},{"ndv":287,"upper":"1837745724897361920","lower":"1837471546365444096","count":1228,"preSum":22489},{"ndv":168,"upper":"1837921716567801856","lower":"1837752963779526656","count":1333,"preSum":23717},{"ndv":177,"upper":"1838014005734539264","lower":"1837922257112924160","count":1236,"preSum":25050},{"ndv":608,"upper":"1838398834804260864","lower":"1838014075544535040","count":1215,"preSum":26286},{"ndv":355,"upper":"1838661181892460544","lower":"1838399845832851456","count":1213,"preSum":27501},{"ndv":412,"upper":"1838996969129771008","lower":"1838667115641438208","count":1217,"preSum":28714},{"ndv":290,"upper":"1839164094897192960","lower":"1838997571129835520","count":1280,"preSum":29931},{"ndv":538,"upper":"1839434574757625856","lower":"1839164804103667712","count":1216,"preSum":31211},{"ndv":517,"upper":"1839747964008923136","lower":"1839435219153715200","count":1213,"preSum":32427},{"ndv":643,"upper":"1840050301269180416","lower":"1839748009441624064","count":1214,"preSum":33640},{"ndv":735,"upper":"1840447683706224640","lower":"1840051088741367808","count":1213,"preSum":34854},{"ndv":1006,"upper":"1840983392158482432","lower":"1840448324478435328","count":1213,"preSum":36067},{"ndv":1054,"upper":"1841337437016555520","lower":"1840983681699676160","count":1213,"preSum":37280},{"ndv":944,"upper":"1841764548445470720","lower":"1841337724561260544","count":1213,"preSum":38493},{"ndv":842,"upper":"1842132776292188160","lower":"1841765539408510976","count":1216,"preSum":39706},{"ndv":762,"upper":"1842516194817474560","lower":"1842133526971940864","count":1213,"preSum":40922},{"ndv":792,"upper":"1842927369199812608","lower":"1842516211141705728","count":1213,"preSum":42135},{"ndv":832,"upper":"1843293860571119616","lower":"1842927552474120192","count":1215,"preSum":43348},{"ndv":797,"upper":"1843752691608584192","lower":"1843294487451795456","count":1213,"preSum":44563},{"ndv":991,"upper":"1844170214623674368","lower":"1843753456431529984","count":1213,"preSum":45776},{"ndv":1065,"upper":"1844524262266765312","lower":"1844170251600658432","count":1213,"preSum":46989},{"ndv":1071,"upper":"1844836066759016448","lower":"1844530468494508032","count":1216,"preSum":48202},{"ndv":1049,"upper":"1845115633998495744","lower":"1844836112661479424","count":1213,"preSum":49418},{"ndv":1003,"upper":"1845434097803984896","lower":"1845115676193193984","count":1213,"preSum":50631},{"ndv":1065,"upper":"1845691784567455744","lower":"1845434101260091392","count":1213,"preSum":51844},{"ndv":1021,"upper":"1845948852671086592","lower":"1845691802015760384","count":1214,"preSum":53057},{"ndv":1028,"upper":"1846213165092700160","lower":"1845949156590354432","count":1213,"preSum":54271},{"ndv":1022,"upper":"1846456816876126208","lower":"1846213463290937344","count":1213,"preSum":55484},{"ndv":1014,"upper":"1846712254603460608","lower":"1846456845397393408","count":1213,"preSum":56697},{"ndv":1032,"upper":"1846951938592079872","lower":"1846712258076344320","count":1213,"preSum":57910},{"ndv":1029,"upper":"1847270349666779136","lower":"1846951941830082560","count":1213,"preSum":59123},{"ndv":1013,"upper":"1847517086947999744","lower":"1847270440498626560","count":1213,"preSum":60336},{"ndv":1004,"upper":"1847761098720149504","lower":"1847517092803248128","count":1215,"preSum":61549},{"ndv":976,"upper":"1848101588275560448","lower":"1847761099206688768","count":1213,"preSum":62764},{"ndv":1038,"upper":"1848357008873357312","lower":"1848101984150749184","count":1213,"preSum":63977},{"ndv":1010,"upper":"1848570362564968448","lower":"1848357029526110208","count":1213,"preSum":65190},{"ndv":1045,"upper":"1848790354229198848","lower":"1848570376708161536","count":1213,"preSum":66403},{"ndv":1046,"upper":"1849128880028254208","lower":"1848790381005635584","count":1213,"preSum":67616},{"ndv":1003,"upper":"1849381402882080768","lower":"1849128932306059264","count":1213,"preSum":68829},{"ndv":1031,"upper":"1849627807085232128","lower":"1849381407143493632","count":1213,"preSum":70042},{"ndv":984,"upper":"1849926853142249472","lower":"1849627834331430912","count":1213,"preSum":71255},{"ndv":1019,"upper":"1850188601300615168","lower":"1849926895118843904","count":1213,"preSum":72468},{"ndv":1044,"upper":"1850410656478527488","lower":"1850188829269426176","count":1213,"preSum":73681},{"ndv":985,"upper":"1850721081195757568","lower":"1850410668759449600","count":1213,"preSum":74894},{"ndv":1079,"upper":"1851029007567421440","lower":"1850721123591782400","count":1213,"preSum":76107},{"ndv":242,"upper":"1851092908929712128","lower":"1851029040266215424","count":276,"preSum":77320}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.9243518}','{"countArr":[2362,975,478,3392,1720,1450,1433,2512,639,1530,1914,1972,723,1305],"valueArr":[1738180555045863424,1783638757694504960,1811364042900504576,1820511979643600896,1829659916386697216,1829739081223897088,1830293235084296192,1831597255874838528,1834283487654313984,1836978265781174272,1837611584478773248,1837752321967128576,1837893059455483904,1839159696850681856],"type":"Datetime","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','cancel_elec_date',267,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"1840827913587392512","lower":"1840827913587392512","count":2,"preSum":0},{"ndv":1,"upper":"1843646567328776192","lower":"1843646567328776192","count":1,"preSum":2},{"ndv":1,"upper":"1843728202560700416","lower":"1843728202560700416","count":1,"preSum":3},{"ndv":1,"upper":"1843736938859724800","lower":"1843736938859724800","count":1,"preSum":4},{"ndv":1,"upper":"1843751972134453248","lower":"1843751972134453248","count":1,"preSum":5},{"ndv":1,"upper":"1843822820975443968","lower":"1843822820975443968","count":1,"preSum":6},{"ndv":1,"upper":"1843904013691518976","lower":"1843904013691518976","count":1,"preSum":7},{"ndv":1,"upper":"1844205440200605696","lower":"1844205440200605696","count":1,"preSum":8},{"ndv":1,"upper":"1844737071957147648","lower":"1844737071957147648","count":1,"preSum":9},{"ndv":1,"upper":"1846885797203017728","lower":"1846885797203017728","count":2,"preSum":10},{"ndv":1,"upper":"1850282948125786112","lower":"1850282948125786112","count":1,"preSum":12}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.9243518}','{"countArr":[99985,3],"valueArr":[-1,1843646263292067840],"type":"Datetime","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','charge_pile_flag',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[97592,561],"valueArr":["0","1"],"type":"String","sampleRate":0.924351804778851}',1848,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','chargpile_user_cate_code',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1661,542,6,13],"valueArr":["1","2","3","4"],"type":"String","sampleRate":0.924351804778851}',97779,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','comm_modula_type_code',27,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"02,21","lower":"01,21","count":31,"preSum":0},{"ndv":2,"upper":"13","lower":"03,21","count":14,"preSum":31},{"ndv":1,"upper":"18","lower":"18","count":41,"preSum":45},{"ndv":1,"upper":"2","lower":"2","count":120,"preSum":86},{"ndv":1,"upper":"3.0","lower":"3.0","count":39,"preSum":206},{"ndv":2,"upper":"5","lower":"4.0","count":27,"preSum":245},{"ndv":1,"upper":"8","lower":"8","count":90,"preSum":272},{"ndv":1,"upper":"9","lower":"9","count":32,"preSum":362},{"ndv":1,"upper":"无","lower":"无","count":22,"preSum":394},{"ndv":1,"upper":"无载波通","lower":"无载波通","count":63,"preSum":416}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[783,587,10380,651,10698,2320,140,2611,8974,510,965,20397,301,16780],"valueArr":["0","01","02","03","1","10","15","16","17","20","21","3","4","7"],"type":"String","sampleRate":0.924351804778851}',23425,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','contract_cap',11855,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":9,"upper":0.40,"lower":0.00,"count":228,"preSum":0},{"ndv":3,"upper":0.55,"lower":0.43,"count":340,"preSum":228},{"ndv":2,"upper":0.66,"lower":0.60,"count":204,"preSum":568},{"ndv":17,"upper":1.32,"lower":0.70,"count":212,"preSum":772},{"ndv":7,"upper":1.60,"lower":1.34,"count":212,"preSum":984},{"ndv":21,"upper":2.50,"lower":1.61,"count":454,"preSum":1196},{"ndv":21,"upper":3.60,"lower":2.56,"count":220,"preSum":1650},{"ndv":38,"upper":5.50,"lower":3.67,"count":215,"preSum":1870},{"ndv":8,"upper":5.90,"lower":5.58,"count":821,"preSum":2085},{"ndv":11,"upper":6.60,"lower":5.94,"count":273,"preSum":2906},{"ndv":6,"upper":7.00,"lower":6.70,"count":1064,"preSum":3179},{"ndv":20,"upper":9.00,"lower":7.05,"count":754,"preSum":4243},{"ndv":27,"upper":11.00,"lower":9.10,"count":364,"preSum":4997},{"ndv":23,"upper":13.00,"lower":11.30,"count":330,"preSum":5361},{"ndv":12,"upper":14.00,"lower":13.10,"count":861,"preSum":5691},{"ndv":22,"upper":16.00,"lower":14.10,"count":271,"preSum":6552},{"ndv":20,"upper":18.00,"lower":16.10,"count":362,"preSum":6823},{"ndv":32,"upper":22.00,"lower":18.10,"count":310,"preSum":7185},{"ndv":16,"upper":25.00,"lower":22.05,"count":390,"preSum":7495},{"ndv":20,"upper":29.00,"lower":25.20,"count":233,"preSum":7885},{"ndv":5,"upper":30.00,"lower":29.25,"count":580,"preSum":8118},{"ndv":24,"upper":37.00,"lower":30.40,"count":206,"preSum":8698},{"ndv":11,"upper":40.00,"lower":37.06,"count":230,"preSum":8904},{"ndv":29,"upper":49.00,"lower":40.95,"count":235,"preSum":9134},{"ndv":5,"upper":50.00,"lower":49.36,"count":268,"preSum":9369},{"ndv":33,"upper":70.00,"lower":51.00,"count":220,"preSum":9637},{"ndv":16,"upper":85.00,"lower":71.00,"count":205,"preSum":9857},{"ndv":19,"upper":100.00,"lower":86.00,"count":308,"preSum":10062},{"ndv":34,"upper":200.00,"lower":100.44,"count":398,"preSum":10370},{"ndv":8,"upper":250.00,"lower":201.00,"count":248,"preSum":10768},{"ndv":8,"upper":315.00,"lower":256.00,"count":206,"preSum":11016},{"ndv":18,"upper":500.00,"lower":320.00,"count":396,"preSum":11222},{"ndv":10,"upper":630.00,"lower":500.85,"count":230,"preSum":11618},{"ndv":21,"upper":960.00,"lower":640.00,"count":200,"preSum":11848},{"ndv":33,"upper":1600.00,"lower":965.00,"count":254,"preSum":12048},{"ndv":57,"upper":3490.00,"lower":1615.00,"count":199,"preSum":12302},{"ndv":115,"upper":29480.00,"lower":3500.00,"count":199,"preSum":12501},{"ndv":15,"upper":1118000.00,"lower":30150.00,"count":17,"preSum":12700}],"maxBucketSize":64,"type":"Double","sampleRate":0.9243518}','{"countArr":[4179,3864,8234,2726,4453,18236,1069,9628,16242,9274,5043,1270,1645,1153],"valueArr":[1.00,1.10,2.00,2.20,3.00,4.00,4.40,5.00,6.00,8.00,10.00,12.00,15.00,20.00],"type":"Double","sampleRate":0.924351804778851}',268,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','create_time',727566,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":77,"upper":"1843856884344291328","lower":"1843694713392070656","count":1848,"preSum":0},{"ndv":2,"upper":"1843857561355288576","lower":"1843857465372835840","count":1988,"preSum":1848},{"ndv":66,"upper":"1843930604236701696","lower":"1843864455700545536","count":2272,"preSum":3836},{"ndv":2,"upper":"1843930659148529664","lower":"1843930633814933504","count":2157,"preSum":6108},{"ndv":1,"upper":"1843930688860979200","lower":"1843930688860979200","count":1908,"preSum":8265},{"ndv":629,"upper":"1844178847440830464","lower":"1843932179516620800","count":681,"preSum":10173},{"ndv":580,"upper":"1844374330025181184","lower":"1844178847843483648","count":681,"preSum":10854},{"ndv":619,"upper":"1844585704810610688","lower":"1844374495951847424","count":681,"preSum":11535},{"ndv":603,"upper":"1844750794679648256","lower":"1844585766835978240","count":681,"preSum":12216},{"ndv":604,"upper":"1844940030049517568","lower":"1844750870864986112","count":681,"preSum":12897},{"ndv":591,"upper":"1845084949175074816","lower":"1844942071333388288","count":682,"preSum":13578},{"ndv":550,"upper":"1845247539574472704","lower":"1845084979525058560","count":681,"preSum":14260},{"ndv":591,"upper":"1845403704082038784","lower":"1845247611565506560","count":681,"preSum":14941},{"ndv":598,"upper":"1845564456403206144","lower":"1845403786458169344","count":681,"preSum":15622},{"ndv":590,"upper":"1845696020411842560","lower":"1845564457812492288","count":681,"preSum":16303},{"ndv":575,"upper":"1845838903068590080","lower":"1845698028946587648","count":681,"preSum":16984},{"ndv":575,"upper":"1845975720107442176","lower":"1845838914862972928","count":681,"preSum":17665},{"ndv":572,"upper":"1846148849886822400","lower":"1845975810150760448","count":682,"preSum":18346},{"ndv":559,"upper":"1846278725151227904","lower":"1846148863191154688","count":681,"preSum":19028},{"ndv":584,"upper":"1846396725938356224","lower":"1846278731308466176","count":681,"preSum":19709},{"ndv":577,"upper":"1846533761768882176","lower":"1846396729662898176","count":682,"preSum":20390},{"ndv":550,"upper":"1846666154739761152","lower":"1846533789384179712","count":681,"preSum":21072},{"ndv":590,"upper":"1846830732954042368","lower":"1846667798386835456","count":681,"preSum":21753},{"ndv":562,"upper":"1846951603014205440","lower":"1846830914751954944","count":681,"preSum":22434},{"ndv":417,"upper":"1847090513178525696","lower":"1846951807796903936","count":681,"preSum":23115},{"ndv":566,"upper":"1847257159503446016","lower":"1847090515057573888","count":681,"preSum":23796},{"ndv":591,"upper":"1847431402501439488","lower":"1847257250754723840","count":683,"preSum":24477},{"ndv":530,"upper":"1847547420255191040","lower":"1847431404011388928","count":681,"preSum":25160},{"ndv":552,"upper":"1847666663948812288","lower":"1847547447803379712","count":681,"preSum":25841},{"ndv":559,"upper":"1847802939335245824","lower":"1847666665056108544","count":681,"preSum":26522},{"ndv":546,"upper":"1847978439986905088","lower":"1847802941868605440","count":681,"preSum":27203},{"ndv":582,"upper":"1848209331623821312","lower":"1847978860826591232","count":681,"preSum":27884},{"ndv":566,"upper":"1848346139972075520","lower":"1848209333972631552","count":681,"preSum":28565},{"ndv":580,"upper":"1848475968797147136","lower":"1848346185337667584","count":681,"preSum":29246},{"ndv":556,"upper":"1848579397179670528","lower":"1848475969099137024","count":681,"preSum":29927},{"ndv":604,"upper":"1848715052194988032","lower":"1848579400266678272","count":681,"preSum":30608},{"ndv":576,"upper":"1848902247170179072","lower":"1848715093332721664","count":682,"preSum":31289},{"ndv":582,"upper":"1849076271695265792","lower":"1848902248562688000","count":681,"preSum":31971},{"ndv":525,"upper":"1849203437372178432","lower":"1849076424569257984","count":681,"preSum":32652},{"ndv":573,"upper":"1849352980734672896","lower":"1849203645728423936","count":681,"preSum":33333},{"ndv":551,"upper":"1849485227391451136","lower":"1849352985180635136","count":681,"preSum":34014},{"ndv":580,"upper":"1849629904237232128","lower":"1849485229337608192","count":681,"preSum":34695},{"ndv":546,"upper":"1849808341623111680","lower":"1849629913263374336","count":681,"preSum":35376},{"ndv":565,"upper":"1849977803097767936","lower":"1849808386267283456","count":681,"preSum":36057},{"ndv":546,"upper":"1850120348968681472","lower":"1849977815714234368","count":682,"preSum":36738},{"ndv":584,"upper":"1850254362014646272","lower":"1850120443474739200","count":681,"preSum":37420},{"ndv":573,"upper":"1850380223179128832","lower":"1850254380519915520","count":681,"preSum":38101},{"ndv":577,"upper":"1850524919838801920","lower":"1850380300421431296","count":681,"preSum":38782},{"ndv":527,"upper":"1850718408769798144","lower":"1850524951564517376","count":681,"preSum":39463},{"ndv":605,"upper":"1850889933405814784","lower":"1850718418215370752","count":681,"preSum":40144},{"ndv":586,"upper":"1851046118297698304","lower":"1850889953236484096","count":681,"preSum":40825},{"ndv":147,"upper":"1851345723220557824","lower":"1851046125058916352","count":1827,"preSum":41506},{"ndv":1,"upper":"1851345723656765440","lower":"1851345723656765440","count":189,"preSum":43333}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.9243518}','{"countArr":[2592,6285,3353,3764,4747,4285,5233,2546,4404,4618,4484,3294,2355,4519],"valueArr":[1843646706697109504,1843646893544964096,1843646895558230016,1843857255137542144,1843857460457111552,1843857639268679680,1843857676212109312,1843930463123537920,1843930504043167744,1843930527917146112,1843930583986601984,1843930672872292352,1843930763955798016,1843930776589041664],"type":"Datetime","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','cust_no',10199176,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1559,"upper":"03001248607","lower":"004086303","count":1562,"preSum":0},{"ndv":1543,"upper":"03002109157","lower":"03001248793","count":1562,"preSum":1562},{"ndv":1549,"upper":"03002935635","lower":"03002109606","count":1562,"preSum":3124},{"ndv":1533,"upper":"03003802257","lower":"03002936454","count":1562,"preSum":4686},{"ndv":1537,"upper":"03004730307","lower":"03003802490","count":1562,"preSum":6248},{"ndv":1540,"upper":"03005731403","lower":"03004730682","count":1562,"preSum":7810},{"ndv":1558,"upper":"03006783802","lower":"03005731423","count":1562,"preSum":9372},{"ndv":1560,"upper":"03015832387","lower":"03006784918","count":1562,"preSum":10934},{"ndv":1555,"upper":"03017030350","lower":"03015834446","count":1562,"preSum":12496},{"ndv":1561,"upper":"03018347919","lower":"03017032098","count":1562,"preSum":14058},{"ndv":1559,"upper":"03019600392","lower":"03018348355","count":1562,"preSum":15620},{"ndv":1550,"upper":"030200000459405","lower":"03019600394","count":1562,"preSum":17182},{"ndv":1550,"upper":"03020090042","lower":"030200000459596","count":1562,"preSum":18744},{"ndv":1561,"upper":"03021035045","lower":"03020090060","count":1562,"preSum":20306},{"ndv":1561,"upper":"03021862801","lower":"03021035759","count":1562,"preSum":21868},{"ndv":1561,"upper":"03022715962","lower":"03021863566","count":1562,"preSum":23430},{"ndv":1559,"upper":"03023585360","lower":"03022716057","count":1562,"preSum":24992},{"ndv":1555,"upper":"03024489033","lower":"03023588355","count":1562,"preSum":26554},{"ndv":1554,"upper":"03025337035","lower":"03024490283","count":1562,"preSum":28116},{"ndv":1553,"upper":"03026150949","lower":"03025337354","count":1562,"preSum":29678},{"ndv":1544,"upper":"03027060745","lower":"03026151627","count":1562,"preSum":31240},{"ndv":1544,"upper":"030400000233051","lower":"03027061128","count":1562,"preSum":32802},{"ndv":1555,"upper":"030500000155691","lower":"030400000233564","count":1562,"preSum":34364},{"ndv":1561,"upper":"030500000853653","lower":"030500000155777","count":1562,"preSum":35926},{"ndv":1557,"upper":"030500001589022","lower":"030500000854577","count":1562,"preSum":37488},{"ndv":1561,"upper":"030600000167259","lower":"030500001589475","count":1562,"preSum":39050},{"ndv":1543,"upper":"030600000899598","lower":"030600000168588","count":1562,"preSum":40612},{"ndv":1558,"upper":"030600001709879","lower":"030600000899883","count":1562,"preSum":42174},{"ndv":1541,"upper":"030600002462638","lower":"030600001710700","count":1562,"preSum":43736},{"ndv":1559,"upper":"030700000430909","lower":"030600002462807","count":1562,"preSum":45298},{"ndv":1557,"upper":"030700001100779","lower":"030700000431051","count":1562,"preSum":46860},{"ndv":1560,"upper":"030700001802524","lower":"030700001100938","count":1562,"preSum":48422},{"ndv":1560,"upper":"030800000308271","lower":"030700001802532","count":1562,"preSum":49984},{"ndv":1561,"upper":"030800001032156","lower":"030800000308284","count":1562,"preSum":51546},{"ndv":1558,"upper":"030800001745817","lower":"030800001032604","count":1562,"preSum":53108},{"ndv":1559,"upper":"030900000357811","lower":"030800001746448","count":1562,"preSum":54670},{"ndv":1560,"upper":"030900001026716","lower":"030900000357985","count":1562,"preSum":56232},{"ndv":1553,"upper":"030900001666303","lower":"030900001027178","count":1562,"preSum":57794},{"ndv":1553,"upper":"031200000339171","lower":"030900001666393","count":1562,"preSum":59356},{"ndv":1558,"upper":"031200001087339","lower":"031200000339268","count":1562,"preSum":60918},{"ndv":1558,"upper":"031300000008894","lower":"031200001087429","count":1562,"preSum":62480},{"ndv":1534,"upper":"031300000663468","lower":"031300000009071","count":1562,"preSum":64042},{"ndv":1544,"upper":"031300001299694","lower":"031300000663989","count":1562,"preSum":65604},{"ndv":1541,"upper":"031304125497661","lower":"031300001299903","count":1562,"preSum":67166},{"ndv":1555,"upper":"031400000501055","lower":"031304127094323","count":1562,"preSum":68728},{"ndv":1558,"upper":"031400001335053","lower":"031400000501169","count":1562,"preSum":70290},{"ndv":1557,"upper":"031500000398203","lower":"031400001336815","count":1562,"preSum":71852},{"ndv":1561,"upper":"031600000190738","lower":"031500000398618","count":1562,"preSum":73414},{"ndv":1546,"upper":"031600000999104","lower":"031600000191877","count":1562,"preSum":74976},{"ndv":1558,"upper":"031700000628236","lower":"031600001000208","count":1562,"preSum":76538},{"ndv":1549,"upper":"031800000308773","lower":"031700000630868","count":1562,"preSum":78100},{"ndv":1547,"upper":"031800000996009","lower":"031800000308787","count":1562,"preSum":79662},{"ndv":1552,"upper":"031900000103825","lower":"031800000996977","count":1562,"preSum":81224},{"ndv":1541,"upper":"031900000838222","lower":"031900000103946","count":1562,"preSum":82786},{"ndv":1542,"upper":"031900001578849","lower":"031900000838400","count":1562,"preSum":84348},{"ndv":1548,"upper":"031971036130461","lower":"031900001580208","count":1562,"preSum":85910},{"ndv":1555,"upper":"032000000660040","lower":"031971036130495","count":1562,"preSum":87472},{"ndv":1560,"upper":"035100000227417","lower":"032000000662556","count":1562,"preSum":89034},{"ndv":1560,"upper":"035100000903298","lower":"035100000227940","count":1562,"preSum":90596},{"ndv":1560,"upper":"035200000401421","lower":"035100000903365","count":1562,"preSum":92158},{"ndv":1557,"upper":"035200001044434","lower":"035200000402036","count":1562,"preSum":93720},{"ndv":1558,"upper":"035200001650932","lower":"035200001044669","count":1562,"preSum":95282},{"ndv":1559,"upper":"035300000308018","lower":"035200001651078","count":1562,"preSum":96844},{"ndv":1515,"upper":"1000000026659780","lower":"035300000308056","count":1520,"preSum":98406}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[6,6,8,6,6,6,8,7,10,6,6],"valueArr":["03","03003732194","030400000417674","031200001424934","031300000237715","031300000504998","031300000595412","031300000801123","031300000851696","031400000435385","031900000690878"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','cust_status_code',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[99834,3,8,13,143],"valueArr":["1","2","3","4","5"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','dis_order_num',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.9243518}','{"countArr":[99610,290,98,3],"valueArr":[1,2,3,4],"type":"Double","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','elec_addr',1296993,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1099,"upper":"一号***********九幢","lower":"\\"仙**************4\\"","count":1142,"preSum":0},{"ndv":934,"upper":"世纪*********04","lower":"一四*******4房","count":1142,"preSum":1142},{"ndv":928,"upper":"丝厂*****号铺","lower":"世纪*********07","count":1142,"preSum":2284},{"ndv":765,"upper":"义**台","lower":"丝织*******之七","count":1143,"preSum":3426},{"ndv":795,"upper":"云南********************农村","lower":"义**坝","count":1142,"preSum":4569},{"ndv":968,"upper":"佗城***公变","lower":"云南********************号地","count":1156,"preSum":5711},{"ndv":975,"upper":"内蒙********************************************************g)","lower":"佗城**公变","count":1142,"preSum":6867},{"ndv":419,"upper":"内蒙***************************办公","lower":"内蒙******************************************************06","count":1142,"preSum":8009},{"ndv":477,"upper":"内蒙********************4号","lower":"内蒙***************************号房","count":1150,"preSum":9151},{"ndv":728,"upper":"冈州*************05","lower":"内蒙********************4幢","count":1142,"preSum":10301},{"ndv":928,"upper":"华星**********D房","lower":"冈州*************08","count":1142,"preSum":11443},{"ndv":809,"upper":"南港***4号","lower":"华景**********号房","count":1142,"preSum":12585},{"ndv":958,"upper":"吉大*****************))","lower":"南港**9号","count":1142,"preSum":13727},{"ndv":868,"upper":"咸宁**********************报)","lower":"吉大*********************))","count":1142,"preSum":14869},{"ndv":688,"upper":"四川*****************************桩)","lower":"咸宁*********************04","count":1142,"preSum":16011},{"ndv":560,"upper":"四川******************角兰","lower":"四川*****************************线)","count":1142,"preSum":17153},{"ndv":596,"upper":"四川*****政村","lower":"四川******************路东","count":1142,"preSum":18295},{"ndv":839,"upper":"城北**下坑","lower":"四川*****教坡","count":1142,"preSum":19437},{"ndv":993,"upper":"大祯******6号","lower":"城北**咀村","count":1142,"preSum":20579},{"ndv":831,"upper":"安徽*************************4号","lower":"大福*********************照明","count":1142,"preSum":21721},{"ndv":849,"upper":"宜春***********************06","lower":"安徽*************************4座","count":1142,"preSum":22863},{"ndv":787,"upper":"山东*****************************9房","lower":"宜春***********************24","count":1142,"preSum":24005},{"ndv":559,"upper":"山东*****************二队","lower":"山东*****************************亭)","count":1142,"preSum":25147},{"ndv":800,"upper":"山湖********14","lower":"山东*****************五村","count":1142,"preSum":26289},{"ndv":584,"upper":"山西*******************山村","lower":"山湖*******7号","count":1143,"preSum":27431},{"ndv":695,"upper":"岗**七","lower":"山西*******************新寨","count":1142,"preSum":28574},{"ndv":655,"upper":"巴彦**************前面","lower":"岗**东","count":1142,"preSum":29716},{"ndv":710,"upper":"平***路","lower":"巴彦**************厂]","count":1143,"preSum":30858},{"ndv":863,"upper":"广东*****************6房","lower":"平***队","count":1142,"preSum":32001},{"ndv":752,"upper":"广西*************************8房","lower":"广东*****************6楼","count":1142,"preSum":33143},{"ndv":550,"upper":"广西*****************坡村","lower":"广西*************************9卡","count":1142,"preSum":34285},{"ndv":919,"upper":"张家************屋后","lower":"广西*****************塘村","count":1142,"preSum":35427},{"ndv":983,"upper":"文明******07","lower":"张家***********3号","count":1142,"preSum":36569},{"ndv":912,"upper":"新疆************************************04","lower":"文明*****07","count":1142,"preSum":37711},{"ndv":801,"upper":"旧经******4房","lower":"新疆************************************07","count":1142,"preSum":38853},{"ndv":906,"upper":"松坑****旁边","lower":"旧自*****06","count":1142,"preSum":39995},{"ndv":919,"upper":"梅溪***3号","lower":"松坑**埔唇","count":1142,"preSum":41137},{"ndv":875,"upper":"民权************8房","lower":"梅瑶**7号","count":1142,"preSum":42279},{"ndv":941,"upper":"江苏********东路","lower":"民权************6房","count":1142,"preSum":43421},{"ndv":764,"upper":"江西***********豪村","lower":"江苏********仔村","count":1145,"preSum":44563},{"ndv":803,"upper":"河北**********************43","lower":"江西***********贵坑","count":1142,"preSum":45708},{"ndv":819,"upper":"河南******************************************6房","lower":"河北**********************4号","count":1142,"preSum":46850},{"ndv":705,"upper":"河南**********山前","lower":"河南*****************************************04","count":1142,"preSum":47992},{"ndv":965,"upper":"浮湖***客户","lower":"河南**********木生","count":1142,"preSum":49134},{"ndv":895,"upper":"湖北********************************4号","lower":"浮石***4)","count":1147,"preSum":50276},{"ndv":635,"upper":"湖南****************07","lower":"湖北********************************6号","count":1142,"preSum":51423},{"ndv":951,"upper":"灰窑****9号","lower":"湖南****************3房","count":1142,"preSum":52565},{"ndv":827,"upper":"甘南************************9号","lower":"灰窑***6号","count":1142,"preSum":53707},{"ndv":492,"upper":"甘肃************************04","lower":"甘南***********************03","count":1146,"preSum":54849},{"ndv":560,"upper":"甘肃***********地下","lower":"甘肃************************05","count":1142,"preSum":55995},{"ndv":873,"upper":"监利******西村","lower":"甘肃***********地里","count":1142,"preSum":57137},{"ndv":887,"upper":"福建***********************2)","lower":"监利******长岭","count":1142,"preSum":58279},{"ndv":904,"upper":"红河*********西村","lower":"福建***********************4房","count":1142,"preSum":59421},{"ndv":680,"upper":"绵阳**马村","lower":"红河*********西路","count":1142,"preSum":60563},{"ndv":951,"upper":"荣成***************7房","lower":"绵阳**高村","count":1142,"preSum":61705},{"ndv":967,"upper":"西岸****塘村","lower":"荣成***************8房","count":1142,"preSum":62847},{"ndv":792,"upper":"贵州*************************08","lower":"西岸**2号","count":1143,"preSum":63989},{"ndv":624,"upper":"辽宁************************电桩","lower":"贵州*************************09","count":1142,"preSum":65132},{"ndv":716,"upper":"通城******公变","lower":"辽宁************************站)","count":1145,"preSum":66274},{"ndv":958,"upper":"长洲*******门)","lower":"通城******新村","count":1142,"preSum":67419},{"ndv":845,"upper":"陕西****************六队","lower":"长洲******2号","count":1142,"preSum":68561},{"ndv":944,"upper":"马南******6号","lower":"陕西****************出岗","count":1142,"preSum":69703},{"ndv":829,"upper":"黑龙***********************7房","lower":"马南******德)","count":1142,"preSum":70845},{"ndv":856,"upper":":雷********9号","lower":"黑龙***********************8号","count":1100,"preSum":71987}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[35,38,30,28,28,31,54,34,30,32,29,42,33,36],"valueArr":["上**村","下**村","内蒙*******************************04","内蒙*************************07","内蒙************************07","大***村","大**村","山西********************00","山西*******************07","山西******************06","山西*****************07","甘肃**********************************号房","甘肃**************************07","老隆***公变"],"type":"String","sampleRate":0.924351804778851}',26434,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','elec_cust_name',726251,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":891,"upper":"东莞***********合社","lower":" **威","count":1561,"preSum":0},{"ndv":362,"upper":"中山*******公司","lower":"东莞***********员会","count":1512,"preSum":1561},{"ndv":810,"upper":"何*","lower":"中山*******具厂","count":1517,"preSum":3073},{"ndv":428,"upper":"何*霖","lower":"何** ","count":1500,"preSum":4590},{"ndv":526,"upper":"佛山***********公司","lower":"何*霞","count":1572,"preSum":6090},{"ndv":694,"upper":"具*花","lower":"佛山***********出所","count":1500,"preSum":7662},{"ndv":741,"upper":"刘*健","lower":"典*","count":1503,"preSum":9162},{"ndv":281,"upper":"刘*波","lower":"刘*儒","count":1503,"preSum":10665},{"ndv":547,"upper":"包*芳","lower":"刘*泰","count":1500,"preSum":12168},{"ndv":824,"upper":"卢翠**丘忠","lower":"包*辉","count":1500,"preSum":13668},{"ndv":614,"upper":"叶国****)*","lower":"卢耀**厂)","count":1500,"preSum":15168},{"ndv":563,"upper":"吴*得","lower":"叶国*****)B","count":1502,"preSum":16668},{"ndv":341,"upper":"吴*龙","lower":"吴*微","count":1502,"preSum":18170},{"ndv":582,"upper":"唐*妹","lower":"吴世******店)","count":1500,"preSum":19672},{"ndv":872,"upper":"孙*","lower":"唐*姐","count":1511,"preSum":21172},{"ndv":1068,"upper":"市**局","lower":"孙**厂","count":1503,"preSum":22683},{"ndv":577,"upper":"康*雪","lower":"市**行","count":1500,"preSum":24186},{"ndv":542,"upper":"张*华","lower":"康*颜","count":1563,"preSum":25686},{"ndv":285,"upper":"张*灵","lower":"张*协","count":1507,"preSum":27249},{"ndv":483,"upper":"彭*明","lower":"张*灿","count":1508,"preSum":28756},{"ndv":712,"upper":"惠州*****************3房","lower":"彭*星","count":1503,"preSum":30264},{"ndv":611,"upper":"揭阳*******公司","lower":"惠州*****************4房","count":1503,"preSum":31767},{"ndv":877,"upper":"曾*","lower":"揭阳*******具厂","count":1531,"preSum":33270},{"ndv":553,"upper":"朱*南","lower":"曾** ","count":1501,"preSum":34801},{"ndv":504,"upper":"李*勤","lower":"朱*卫","count":1502,"preSum":36302},{"ndv":206,"upper":"李*明","lower":"李*包","count":1551,"preSum":37804},{"ndv":234,"upper":"李*能","lower":"李*昕","count":1501,"preSum":39355},{"ndv":553,"upper":"杨*中","lower":"李*臣","count":1501,"preSum":40856},{"ndv":407,"upper":"杨*裕","lower":"杨*丰","count":1500,"preSum":42357},{"ndv":409,"upper":"林*惠","lower":"杨*西","count":1502,"preSum":43857},{"ndv":314,"upper":"林*鑫","lower":"林*想","count":1500,"preSum":45359},{"ndv":543,"upper":"梁*开","lower":"林*钊","count":1504,"preSum":46859},{"ndv":286,"upper":"梁*辉","lower":"梁*弋","count":1533,"preSum":48363},{"ndv":830,"upper":"民生***************2)","lower":"梁*达","count":1500,"preSum":49896},{"ndv":648,"upper":"沈*如","lower":"民生**************5)","count":1500,"preSum":51396},{"ndv":789,"upper":"温伟***宅)","lower":"沈*妹","count":1500,"preSum":52896},{"ndv":772,"upper":"王*兰","lower":"温坤**54","count":1500,"preSum":54396},{"ndv":512,"upper":"珠海****************小组","lower":"王*兴","count":1500,"preSum":55896},{"ndv":798,"upper":"程*亮","lower":"珠海***************公司","count":1500,"preSum":57396},{"ndv":773,"upper":"罗*斯","lower":"程*传","count":1500,"preSum":58896},{"ndv":642,"upper":"肖*","lower":"罗*新","count":1500,"preSum":60396},{"ndv":683,"upper":"苏*毅","lower":"肖**厂","count":1500,"preSum":61896},{"ndv":784,"upper":"葛*","lower":"苏*毛","count":1501,"preSum":63396},{"ndv":694,"upper":"蔡*辉","lower":"葛*云","count":1509,"preSum":64897},{"ndv":839,"upper":"许*春","lower":"蔡*达","count":1501,"preSum":66406},{"ndv":560,"upper":"谢*照","lower":"许*晖","count":1500,"preSum":67907},{"ndv":685,"upper":"赖*喜","lower":"谢*燕","count":1503,"preSum":69407},{"ndv":754,"upper":"邓*","lower":"赖*四","count":1513,"preSum":70910},{"ndv":632,"upper":"邱*俊","lower":"邓** ","count":1500,"preSum":72423},{"ndv":667,"upper":"郑*心","lower":"邱*保","count":1500,"preSum":73923},{"ndv":542,"upper":"郭*胜","lower":"郑*忍","count":1503,"preSum":75423},{"ndv":577,"upper":"钟*锋","lower":"郭*腾","count":1508,"preSum":76926},{"ndv":775,"upper":"陈*中","lower":"钟*键","count":1505,"preSum":78434},{"ndv":220,"upper":"陈*娟","lower":"陈*丰","count":1530,"preSum":79939},{"ndv":195,"upper":"陈*权","lower":"陈*娣","count":1534,"preSum":81469},{"ndv":187,"upper":"陈*生","lower":"陈*李","count":1551,"preSum":83003},{"ndv":220,"upper":"陈*锋","lower":"陈*用","count":1515,"preSum":84554},{"ndv":797,"upper":"颜*儿","lower":"陈*锐","count":1500,"preSum":86069},{"ndv":953,"upper":"鸿**司","lower":"颜*兆","count":1500,"preSum":87569},{"ndv":437,"upper":"黄*坚","lower":"鸿城*******业)","count":1509,"preSum":89069},{"ndv":206,"upper":"黄*松","lower":"黄*坤","count":1526,"preSum":90578},{"ndv":259,"upper":"黄*英","lower":"黄*极","count":1513,"preSum":92104},{"ndv":490,"upper":"黎*朱","lower":"黄*茂","count":1500,"preSum":93617},{"ndv":464,"upper":"(石***************理所","lower":"黎*权","count":828,"preSum":95117}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[230,260,186,297,310,519,212,268,189,241,654,172,179,339],"valueArr":["东莞*********公司","中国***************公司","中国************公司","刘*","张*","李*","杨*","林*","梁*","王*","陈*","陈*华","陈*明","黄*"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','elec_cust_no',11794161,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1558,"upper":"0302000232014172","lower":"0302000000000012","count":1563,"preSum":0},{"ndv":1560,"upper":"0302100017183882","lower":"0302000232019505","count":1563,"preSum":1563},{"ndv":1561,"upper":"0304002033510049","lower":"0302100017185543","count":1563,"preSum":3126},{"ndv":1563,"upper":"0304020041754043","lower":"0304002033510503","count":1563,"preSum":4689},{"ndv":1563,"upper":"0305000990183727","lower":"0304020043095067","count":1563,"preSum":6252},{"ndv":1563,"upper":"0305002641122102","lower":"0305000990183980","count":1563,"preSum":7815},{"ndv":1563,"upper":"0305004887001301","lower":"0305002641122409","count":1563,"preSum":9378},{"ndv":1563,"upper":"0305480008238434","lower":"0305004889106601","count":1563,"preSum":10941},{"ndv":1562,"upper":"0306120139099150","lower":"0305480008308607","count":1563,"preSum":12504},{"ndv":1561,"upper":"0306140074233087","lower":"0306120139099988","count":1563,"preSum":14067},{"ndv":1563,"upper":"0307002000154016","lower":"0306140074741322","count":1563,"preSum":15630},{"ndv":1562,"upper":"0307005000756788","lower":"0307002000154550","count":1563,"preSum":17193},{"ndv":1563,"upper":"0307007000392705","lower":"0307005000757894","count":1563,"preSum":18756},{"ndv":1563,"upper":"0307050057386469","lower":"0307007000392828","count":1563,"preSum":20319},{"ndv":1563,"upper":"0308000800149001","lower":"0307050060178220","count":1563,"preSum":21882},{"ndv":1563,"upper":"0308000804292759","lower":"0308000800149026","count":1563,"preSum":23445},{"ndv":1563,"upper":"0308000805287060","lower":"0308000804292845","count":1563,"preSum":25008},{"ndv":1562,"upper":"0308100006220219","lower":"0308000805287374","count":1563,"preSum":26571},{"ndv":1561,"upper":"0309000191641916","lower":"0308100006408770","count":1563,"preSum":28134},{"ndv":1563,"upper":"0309001001612852","lower":"0309000192202608","count":1563,"preSum":29697},{"ndv":1563,"upper":"0309008001713308","lower":"0309001001613062","count":1563,"preSum":31260},{"ndv":1562,"upper":"0309020257918875","lower":"0309008001800703","count":1563,"preSum":32823},{"ndv":1559,"upper":"0312000011035929","lower":"0309020258894505","count":1563,"preSum":34386},{"ndv":1563,"upper":"0312000080236570","lower":"0312000011036078","count":1563,"preSum":35949},{"ndv":1561,"upper":"0312009900285147","lower":"0312000080236578","count":1563,"preSum":37512},{"ndv":1561,"upper":"0313000030009905","lower":"0312009900286819","count":1563,"preSum":39075},{"ndv":1562,"upper":"0313001301042355","lower":"0313000030234127","count":1563,"preSum":40638},{"ndv":1563,"upper":"0313006044024916","lower":"0313001301042573","count":1563,"preSum":42201},{"ndv":1563,"upper":"0313020007880009","lower":"0313006044025794","count":1563,"preSum":43764},{"ndv":1563,"upper":"0313030266379810","lower":"0313020008210601","count":1563,"preSum":45327},{"ndv":1559,"upper":"0313140163040325","lower":"0313030266403430","count":1563,"preSum":46890},{"ndv":1559,"upper":"0314002134006214","lower":"0313140163041894","count":1563,"preSum":48453},{"ndv":1561,"upper":"0314006014107169","lower":"0314002134006356","count":1563,"preSum":50016},{"ndv":1554,"upper":"0314070066260875","lower":"0314006014108140","count":1563,"preSum":51579},{"ndv":1559,"upper":"0315002122005539","lower":"0314070068437565","count":1563,"preSum":53142},{"ndv":1563,"upper":"0315040065448957","lower":"0315002122006330","count":1563,"preSum":54705},{"ndv":1561,"upper":"0316001623281661","lower":"0315040065483493","count":1563,"preSum":56268},{"ndv":1558,"upper":"0316260216610895","lower":"0316001623282178","count":1563,"preSum":57831},{"ndv":1562,"upper":"0317001700321201","lower":"0316260217448998","count":1563,"preSum":59394},{"ndv":1561,"upper":"0317070185588166","lower":"0317001700321364","count":1563,"preSum":60957},{"ndv":1563,"upper":"0318002302020040","lower":"0317070185588179","count":1563,"preSum":62520},{"ndv":1562,"upper":"0318009900098886","lower":"0318002302020312","count":1563,"preSum":64083},{"ndv":1563,"upper":"0318010280860569","lower":"0318009900100505","count":1563,"preSum":65646},{"ndv":1562,"upper":"0319002002153050","lower":"0318010280860716","count":1563,"preSum":67209},{"ndv":1563,"upper":"0319007000197634","lower":"0319002003095000","count":1563,"preSum":68772},{"ndv":1563,"upper":"0319009000770331","lower":"0319007000197699","count":1563,"preSum":70335},{"ndv":1562,"upper":"0319009900850758","lower":"0319009000770816","count":1563,"preSum":71898},{"ndv":1563,"upper":"0319360011292539","lower":"0319009900851457","count":1563,"preSum":73461},{"ndv":1563,"upper":"0320002002020192","lower":"0319360011346832","count":1563,"preSum":75024},{"ndv":1563,"upper":"0320005083005102","lower":"0320002002020244","count":1563,"preSum":76587},{"ndv":1563,"upper":"0320210138709543","lower":"0320005083006808","count":1563,"preSum":78150},{"ndv":1562,"upper":"0351005107306251","lower":"0320210138968675","count":1563,"preSum":79713},{"ndv":1561,"upper":"0351009800167610","lower":"0351005107306617","count":1563,"preSum":81276},{"ndv":1563,"upper":"0352003040069217","lower":"0351009800167828","count":1563,"preSum":82839},{"ndv":1563,"upper":"0352006110501769","lower":"0352003040101190","count":1563,"preSum":84402},{"ndv":1563,"upper":"0352007231304085","lower":"0352006110602611","count":1563,"preSum":85965},{"ndv":1563,"upper":"0352060024628105","lower":"0352007231404012","count":1563,"preSum":87528},{"ndv":1563,"upper":"0353000050015971","lower":"0352060024961484","count":1563,"preSum":89091},{"ndv":1563,"upper":"0353000200006086","lower":"0353000050016101","count":1563,"preSum":90654},{"ndv":1561,"upper":"061100100029429","lower":"0353000200006885","count":1563,"preSum":92217},{"ndv":1563,"upper":"062270002729743","lower":"061100100030018","count":1563,"preSum":93780},{"ndv":1563,"upper":"062970000202702","lower":"062270002730669","count":1563,"preSum":95343},{"ndv":1563,"upper":"063504080100232","lower":"062970000203093","count":1563,"preSum":96906},{"ndv":1502,"upper":"9001563970","lower":"063504080100294","count":1502,"preSum":98469}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[3,3,3,3,3,4,4,4,3],"valueArr":["0302000205005414","0302000232004398","0302000232004403","0309009900097795","0314002611000257","0314003828030009","0314005121044001","0317009800000085","0318002508010049"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','elec_sort_code',9,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1425,2259,3223,5618,84584,49,1774,133,936],"valueArr":["100","200","260","300","500","600","700","800","900"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','ele_user_category',9,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1737,25,38,96832,280,253,3,750,83],"valueArr":["10","100","11","20","40","45","50","60","80"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','equ_id',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[100001],"valueArr":["null"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','equ_model_code',1342,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":9,"upper":"00000021","lower":"00000011","count":872,"preSum":0},{"ndv":4,"upper":"0000007","lower":"0000004","count":1120,"preSum":872},{"ndv":3,"upper":"000025","lower":"000022","count":965,"preSum":1992},{"ndv":13,"upper":"00010036","lower":"0000262","count":1050,"preSum":2957},{"ndv":21,"upper":"000226","lower":"00010045","count":1467,"preSum":4007},{"ndv":18,"upper":"00113128","lower":"000227","count":1900,"preSum":5474},{"ndv":23,"upper":"110649","lower":"00407","count":905,"preSum":7374},{"ndv":32,"upper":"30001305","lower":"113","count":1420,"preSum":8279},{"ndv":18,"upper":"41132","lower":"30001555","count":955,"preSum":9699},{"ndv":12,"upper":"DDSK1710-Z","lower":"43134","count":1167,"preSum":10654},{"ndv":15,"upper":"XH000000000000000000000000006425","lower":"F0024","count":1012,"preSum":11821},{"ndv":10,"upper":"XH000000000000000000000000007955","lower":"XH000000000000000000000000006466","count":1123,"preSum":12833},{"ndv":3,"upper":"XH000000000000000000000000008110","lower":"XH000000000000000000000000007960","count":971,"preSum":13956},{"ndv":8,"upper":"XH000000000000000000000000008391","lower":"XH000000000000000000000000008215","count":897,"preSum":14927},{"ndv":5,"upper":"XH000000000000000000000000008796","lower":"XH000000000000000000000000008638","count":1418,"preSum":15824},{"ndv":1,"upper":"XH000000000000000000000000008811","lower":"XH000000000000000000000000008811","count":1142,"preSum":17242},{"ndv":2,"upper":"XH000000000000000000000000008836","lower":"XH000000000000000000000000008816","count":983,"preSum":18384},{"ndv":3,"upper":"XH000000000000000000000000008906","lower":"XH000000000000000000000000008866","count":1358,"preSum":19367},{"ndv":6,"upper":"XH000000000000001000000000015000","lower":"XH000000000000000000000000008941","count":978,"preSum":20725},{"ndv":4,"upper":"XH000000000000001000000000045000","lower":"XH000000000000001000000000025000","count":982,"preSum":21703},{"ndv":2,"upper":"XH000000000000001000000000045007","lower":"XH000000000000001000000000045004","count":1143,"preSum":22685},{"ndv":6,"upper":"XH000004","lower":"XH000000000000001000000000050001","count":1417,"preSum":23828},{"ndv":5,"upper":"XH005017","lower":"XH000005","count":2357,"preSum":25245},{"ndv":2,"upper":"XH005031","lower":"XH005030","count":1602,"preSum":27602},{"ndv":1,"upper":"XH005032","lower":"XH005032","count":999,"preSum":29204},{"ndv":2,"upper":"XH005055","lower":"XH005035","count":1183,"preSum":30203},{"ndv":1,"upper":"XH005061","lower":"XH005061","count":1002,"preSum":31386},{"ndv":3,"upper":"XH005075","lower":"XH005065","count":861,"preSum":32388},{"ndv":2,"upper":"XH005095","lower":"XH005076","count":923,"preSum":33249},{"ndv":8,"upper":"XH005460","lower":"XH005096","count":1036,"preSum":34172},{"ndv":1,"upper":"XH005461","lower":"XH005461","count":1608,"preSum":35208},{"ndv":1,"upper":"XH005465","lower":"XH005465","count":1502,"preSum":36816},{"ndv":3,"upper":"XH005565","lower":"XH005500","count":844,"preSum":38318},{"ndv":4,"upper":"XH005635","lower":"XH005570","count":967,"preSum":39162},{"ndv":5,"upper":"XH005715","lower":"XH005645","count":1036,"preSum":40129},{"ndv":4,"upper":"XH075003","lower":"XH050002","count":1118,"preSum":41165},{"ndv":2,"upper":"XH075006","lower":"XH075004","count":899,"preSum":42283},{"ndv":3,"upper":"XH090003","lower":"XH077077","count":1623,"preSum":43182},{"ndv":2,"upper":"XH095008","lower":"XH092078","count":957,"preSum":44805},{"ndv":3,"upper":"XH105007","lower":"XH100003","count":1441,"preSum":45762},{"ndv":5,"upper":"XH140002","lower":"XH122077","count":1160,"preSum":47203},{"ndv":5,"upper":"XH150002","lower":"XH142077","count":1367,"preSum":48363},{"ndv":10,"upper":"XH220002","lower":"XH160003","count":1227,"preSum":49730},{"ndv":7,"upper":"XH300002","lower":"XH222079","count":844,"preSum":50957},{"ndv":20,"upper":"XH950002","lower":"XH360002","count":1013,"preSum":51801},{"ndv":6,"upper":"XH997097","lower":"XH950003","count":726,"preSum":52814}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[2744,1878,4234,3542,2158,4839,2101,5877,2982,1991,2207,1921,2501,7406],"valueArr":["099666","999937","XH005004","XH005016","XH005060","XH005470","XH005475","XH005485","XH005515","XH005555","XH035002","XH040002","XH195002","XH990002"],"type":"String","sampleRate":0.924351804778851}',80,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','equ_status_code',65,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"0","lower":"0","count":1,"preSum":0},{"ndv":1,"upper":"35","lower":"35","count":1,"preSum":1},{"ndv":1,"upper":"61","lower":"61","count":1,"preSum":2}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[3,3,98737,26,386,825,18],"valueArr":["20","40","50","60","66","75","80"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','equ_type_code',36,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"0610000","lower":"0610000","count":1,"preSum":0},{"ndv":1,"upper":"0620000","lower":"0620000","count":2,"preSum":1},{"ndv":1,"upper":"0731000","lower":"0731000","count":4,"preSum":3},{"ndv":1,"upper":"2630000","lower":"2630000","count":5,"preSum":7}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[6914,5414,24141,582,49707,704,455,637,1171,8428,1040,728,54,14],"valueArr":["0112010","0112020","0112030","0112040","0113000","0132000","0132020","0133000","0133030","0135000","0330000","0430000","0530000","0732000"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','factory_short_name',373,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":7,"upper":"北京博纳","lower":"ABB(埃尔斯特)ELSTER","count":527,"preSum":0},{"ndv":4,"upper":"北京博纳电气股份有限公司","lower":"北京博纳1","count":1018,"preSum":527},{"ndv":3,"upper":"北京煜邦电力技术有限公司","lower":"北京振中电子技术有限公司","count":564,"preSum":1545},{"ndv":1,"upper":"北京煜邦电力技术股份有限公司","lower":"北京煜邦电力技术股份有限公司","count":666,"preSum":2109},{"ndv":1,"upper":"华立仪表集团股份有限公司","lower":"华立仪表集团股份有限公司","count":1313,"preSum":2775},{"ndv":5,"upper":"威胜信息","lower":"华立科技有限公司","count":735,"preSum":4088},{"ndv":1,"upper":"宁夏隆基宁光","lower":"宁夏隆基宁光","count":1562,"preSum":4823},{"ndv":5,"upper":"宁波伟吉电力科技有限公司","lower":"宁波三星电器股份有限公司","count":647,"preSum":6385},{"ndv":9,"upper":"恒业电子","lower":"宁波迦南","count":690,"preSum":7032},{"ndv":2,"upper":"新宇能","lower":"惠州中城电子科技有限公司","count":1100,"preSum":7722},{"ndv":2,"upper":"杭州炬华","lower":"杭州华隆电子技术有限公司(终端仪 ","count":761,"preSum":8822},{"ndv":2,"upper":"杭州炬华科技股份有限公司","lower":"杭州炬华科技有限公司","count":1789,"preSum":9583},{"ndv":2,"upper":"杭州西力电能表制造有限公司","lower":"杭州百富电子技术有限公司","count":693,"preSum":11372},{"ndv":1,"upper":"正泰仪器","lower":"正泰仪器","count":599,"preSum":12065},{"ndv":1,"upper":"江苏林洋","lower":"江苏林洋","count":2419,"preSum":12664},{"ndv":1,"upper":"江苏林洋电子有限公司","lower":"江苏林洋电子有限公司","count":988,"preSum":15083},{"ndv":1,"upper":"江苏林洋电子股份有限公司","lower":"江苏林洋电子股份有限公司","count":1630,"preSum":16071},{"ndv":1,"upper":"河南许继仪有限公司","lower":"河南许继仪有限公司","count":1237,"preSum":17701},{"ndv":3,"upper":"浙江万胜","lower":"河南许继电能仪表有限公司","count":1502,"preSum":18938},{"ndv":4,"upper":"浙江华立科技股份有限公司","lower":"浙江万胜电力仪表有限公司","count":1020,"preSum":20440},{"ndv":3,"upper":"浙江正泰仪器仪表有限责任公司","lower":"浙江晨泰","count":1128,"preSum":21460},{"ndv":2,"upper":"海兴电力","lower":"浙江正泰电器股份有限公司","count":1830,"preSum":22588},{"ndv":12,"upper":"深圳科陆电子有限公司","lower":"深圳华立南方电子技术有限公司","count":831,"preSum":24418},{"ndv":1,"upper":"深圳科陆电子科技股份有限公司","lower":"深圳科陆电子科技股份有限公司","count":639,"preSum":25249},{"ndv":5,"upper":"烟台威思顿","lower":"深圳航天泰瑞捷电子有限公司","count":1123,"preSum":25888},{"ndv":2,"upper":"西力智能","lower":"盛帆","count":573,"preSum":27011},{"ndv":1,"upper":"许继仪表","lower":"许继仪表","count":677,"preSum":27584},{"ndv":5,"upper":"长沙威胜电子有限公司","lower":"许继仪表有限公司","count":935,"preSum":28261},{"ndv":1,"upper":"青岛乾程","lower":"青岛乾程","count":973,"preSum":29196},{"ndv":3,"upper":"青岛鼎信","lower":"青岛乾程电子科技有限公司","count":2434,"preSum":30169}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[10089,4173,4612,3240,6571,2810,2476,4843,5970,7187,3121,5421,4275,2584],"valueArr":["三星","华立","华立科技股份有限公司","威胜集团","威胜集团有限公司","宁夏隆基宁光仪表有限公司","宁波三星","杭州海兴电力科技股份有限公司","江苏林洋能源股份有限公司","河南许继仪表有限公司","浙江晨泰科技股份有限公司","深圳市科陆电子科技股份有限公司","深圳深宝电器仪表有限公司","深圳科陆"],"type":"String","sampleRate":0.924351804778851}',26,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','file_date',64469,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":893,"upper":"1842058703323267072","lower":"-1","count":1498,"preSum":0},{"ndv":949,"upper":"1843061391775236096","lower":"1842058749796155392","count":1498,"preSum":1498},{"ndv":942,"upper":"1843866830012153856","lower":"1843062021692588032","count":1498,"preSum":2996},{"ndv":197,"upper":"1844418330539065344","lower":"1843866851101114368","count":1498,"preSum":4494},{"ndv":74,"upper":"1844546207888703488","lower":"1844418331830910976","count":1529,"preSum":5992},{"ndv":81,"upper":"1844636083904577536","lower":"1844547974999310336","count":1576,"preSum":7521},{"ndv":65,"upper":"1844708657460150272","lower":"1844636486037667840","count":1567,"preSum":9097},{"ndv":94,"upper":"1844805626346078208","lower":"1844708953578012672","count":1501,"preSum":10664},{"ndv":88,"upper":"1844917361983881216","lower":"1844805640237613056","count":1613,"preSum":12165},{"ndv":62,"upper":"1844959713649754112","lower":"1844917438487986176","count":1512,"preSum":13778},{"ndv":59,"upper":"1844988505852215296","lower":"1844961288308916224","count":1500,"preSum":15290},{"ndv":72,"upper":"1845014822559678464","lower":"1844990045279223808","count":1524,"preSum":16790},{"ndv":72,"upper":"1845038764921978880","lower":"1845016293049106432","count":1580,"preSum":18314},{"ndv":86,"upper":"1845096057537560576","lower":"1845038880785432576","count":1606,"preSum":19894},{"ndv":80,"upper":"1845247635573702656","lower":"1845097717357871104","count":1533,"preSum":21500},{"ndv":72,"upper":"1845357577626451968","lower":"1845247741437935616","count":1535,"preSum":23033},{"ndv":88,"upper":"1845502686502322176","lower":"1845357651496534016","count":1521,"preSum":24568},{"ndv":64,"upper":"1845533497473630208","lower":"1845502826139090944","count":1502,"preSum":26089},{"ndv":63,"upper":"1845566507669520384","lower":"1845533503530205184","count":1510,"preSum":27591},{"ndv":73,"upper":"1845594639889858560","lower":"1845566524530622464","count":1499,"preSum":29101},{"ndv":97,"upper":"1845628147882524672","lower":"1845594704163373056","count":1506,"preSum":30600},{"ndv":112,"upper":"1845689651663208448","lower":"1845628156489236480","count":1529,"preSum":32106},{"ndv":75,"upper":"1845740258944090112","lower":"1845689799252377600","count":1547,"preSum":33635},{"ndv":63,"upper":"1845757923037282304","lower":"1845740320986234880","count":1575,"preSum":35182},{"ndv":41,"upper":"1845775102738694144","lower":"1845757952263192576","count":1523,"preSum":36757},{"ndv":47,"upper":"1845791023695921152","lower":"1845775276500320256","count":1511,"preSum":38280},{"ndv":46,"upper":"1845814544681664512","lower":"1845793042817089536","count":1521,"preSum":39791},{"ndv":42,"upper":"1845821744305143808","lower":"1845814547013697536","count":1530,"preSum":41312},{"ndv":49,"upper":"1845838715230879744","lower":"1845821778715213824","count":1636,"preSum":42842},{"ndv":44,"upper":"1845863470080196608","lower":"1845838759589838848","count":1545,"preSum":44478},{"ndv":71,"upper":"1845885084922544128","lower":"1845863497175400448","count":1524,"preSum":46023},{"ndv":50,"upper":"1845898620243542016","lower":"1845885313713438720","count":1516,"preSum":47547},{"ndv":59,"upper":"1845917988985765888","lower":"1845898639101132800","count":1525,"preSum":49063},{"ndv":73,"upper":"1845944452225433600","lower":"1845918069197635584","count":1539,"preSum":50588},{"ndv":96,"upper":"1846001534169513984","lower":"1845944454792347648","count":1586,"preSum":52127},{"ndv":91,"upper":"1846149201084284928","lower":"1846001539185901568","count":1512,"preSum":53713},{"ndv":61,"upper":"1846190709426618368","lower":"1846149384996126720","count":1505,"preSum":55225},{"ndv":46,"upper":"1846223591511687168","lower":"1846190761469542400","count":1514,"preSum":56730},{"ndv":44,"upper":"1846285823289327616","lower":"1846226327372300288","count":1531,"preSum":58244},{"ndv":51,"upper":"1846322555560919040","lower":"1846292121607208960","count":1599,"preSum":59775},{"ndv":63,"upper":"1846356142792376320","lower":"1846322582740008960","count":1529,"preSum":61374},{"ndv":89,"upper":"1846445653400485888","lower":"1846357756408233984","count":1499,"preSum":62903},{"ndv":101,"upper":"1846597465747226624","lower":"1846445654222569472","count":1524,"preSum":64402},{"ndv":148,"upper":"1846782199471276032","lower":"1846597780605239296","count":1498,"preSum":65926},{"ndv":245,"upper":"1847356039683375104","lower":"1846782559493554176","count":1512,"preSum":67424},{"ndv":267,"upper":"1847615617507524608","lower":"1847356040824225792","count":1508,"preSum":68936},{"ndv":189,"upper":"1847833780941750272","lower":"1847615619353018368","count":1499,"preSum":70444},{"ndv":125,"upper":"1848299956490731520","lower":"1847833784062312448","count":1505,"preSum":71943},{"ndv":121,"upper":"1848493393496244224","lower":"1848299957983903744","count":1520,"preSum":73448},{"ndv":129,"upper":"1848671189170388992","lower":"1848493401012436992","count":1511,"preSum":74968},{"ndv":183,"upper":"1849067370375544832","lower":"1848671190395125760","count":1534,"preSum":76479},{"ndv":148,"upper":"1849241024711360512","lower":"1849067371231182848","count":1505,"preSum":78013},{"ndv":194,"upper":"1849421303732240384","lower":"1849241026808512512","count":1506,"preSum":79518},{"ndv":154,"upper":"1849535892922826752","lower":"1849421305896501248","count":1500,"preSum":81024},{"ndv":129,"upper":"1849649980860530688","lower":"1849541927922302976","count":1499,"preSum":82524},{"ndv":149,"upper":"1849944679487897600","lower":"1849649987873406976","count":1513,"preSum":84023},{"ndv":146,"upper":"1850125154986754048","lower":"1849944682071588864","count":1517,"preSum":85536},{"ndv":109,"upper":"1850217380148412416","lower":"1850125163375362048","count":1519,"preSum":87053},{"ndv":64,"upper":"1850311579099201536","lower":"1850217430077407232","count":1514,"preSum":88572},{"ndv":74,"upper":"1850404475735375872","lower":"1850311721403547648","count":1506,"preSum":90086},{"ndv":88,"upper":"1850485331699171328","lower":"1850404483587112960","count":1501,"preSum":91592},{"ndv":93,"upper":"1850615578075594752","lower":"1850485820100706304","count":1515,"preSum":93093},{"ndv":153,"upper":"1851136571684683776","lower":"1850619923894632448","count":1256,"preSum":94608}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.9243518}','{"countArr":[328,197,201,211,215,294,294,621,207,463,216,246,254,390],"valueArr":[1844523812670930944,1844568103883636736,1844756927221858304,1844972483661266944,1844977252836573184,1844981683934199808,1845095644314730496,1845128465565614080,1845229759852707840,1845509480352055296,1845816940401000448,1845834923647172608,1845867873294090240,1846725526455058432],"type":"Datetime","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','first_oper_date',1986764,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":932,"upper":"1843012385594408960","lower":"1738180548955734016","count":1348,"preSum":0},{"ndv":1065,"upper":"1844416464644210688","lower":"1843017485868072960","count":1346,"preSum":1348},{"ndv":1315,"upper":"1844756891972927488","lower":"1844416511821742080","count":1346,"preSum":2694},{"ndv":1319,"upper":"1844898005505802240","lower":"1844756907944837120","count":1346,"preSum":4040},{"ndv":1320,"upper":"1844976897914568704","lower":"1844898008928354304","count":1346,"preSum":5386},{"ndv":1315,"upper":"1845034362093961216","lower":"1844976920295374848","count":1347,"preSum":6732},{"ndv":1313,"upper":"1845086805020377088","lower":"1845034362127515648","count":1346,"preSum":8079},{"ndv":1280,"upper":"1845221336129994752","lower":"1845086810691076096","count":1346,"preSum":9425},{"ndv":1218,"upper":"1845462097501093888","lower":"1845221350273187840","count":1348,"preSum":10771},{"ndv":1285,"upper":"1845619644652584960","lower":"1845462727317782528","count":1346,"preSum":12119},{"ndv":1267,"upper":"1845709501961863168","lower":"1845619753553494016","count":1346,"preSum":13465},{"ndv":1109,"upper":"1845757448594391040","lower":"1845709502800723968","count":1346,"preSum":14811},{"ndv":1078,"upper":"1845793153781596160","lower":"1845757449215148032","count":1346,"preSum":16157},{"ndv":1089,"upper":"1845823485847273472","lower":"1845793202485854208","count":1346,"preSum":17503},{"ndv":1078,"upper":"1845837392313843712","lower":"1845823493514461184","count":1346,"preSum":18849},{"ndv":1059,"upper":"1845878521742753792","lower":"1845837412027072512","count":1346,"preSum":20195},{"ndv":1075,"upper":"1845896661503574016","lower":"1845878525987389440","count":1346,"preSum":21541},{"ndv":1032,"upper":"1845909623010230272","lower":"1845896668415787008","count":1346,"preSum":22887},{"ndv":1005,"upper":"1845928902682214400","lower":"1845909626214678528","count":1347,"preSum":24233},{"ndv":1023,"upper":"1845944319752536064","lower":"1845928911523807232","count":1347,"preSum":25580},{"ndv":1007,"upper":"1845957608733671424","lower":"1845944328292139008","count":1348,"preSum":26927},{"ndv":1026,"upper":"1845966488561778688","lower":"1845957617172611072","count":1350,"preSum":28275},{"ndv":975,"upper":"1845975664490971136","lower":"1845966492554756096","count":1349,"preSum":29625},{"ndv":1009,"upper":"1845991323690074112","lower":"1845975666521014272","count":1348,"preSum":30974},{"ndv":1058,"upper":"1846010980429987840","lower":"1845991332397449216","count":1346,"preSum":32322},{"ndv":967,"upper":"1846027947983503360","lower":"1846010982728466432","count":1346,"preSum":33668},{"ndv":982,"upper":"1846047641331302400","lower":"1846027955784908800","count":1346,"preSum":35014},{"ndv":1032,"upper":"1846177590230908928","lower":"1846047645609492480","count":1346,"preSum":36360},{"ndv":1057,"upper":"1846290140536766464","lower":"1846177593955450880","count":1347,"preSum":37706},{"ndv":1060,"upper":"1846333956719378432","lower":"1846290167699079168","count":1346,"preSum":39053},{"ndv":1012,"upper":"1846377938828656640","lower":"1846333980492693504","count":1346,"preSum":40399},{"ndv":977,"upper":"1846398062226833408","lower":"1846377965403766784","count":1346,"preSum":41745},{"ndv":1004,"upper":"1846439879303495680","lower":"1846398070380560384","count":1346,"preSum":43091},{"ndv":1045,"upper":"1846475177844539392","lower":"1846439910827884544","count":1346,"preSum":44437},{"ndv":1065,"upper":"1846582506007035904","lower":"1846475185159405568","count":1346,"preSum":45783},{"ndv":1097,"upper":"1846716628708884480","lower":"1846582509731577856","count":1346,"preSum":47129},{"ndv":1082,"upper":"1846857436393111552","lower":"1846716659075645440","count":1346,"preSum":48475},{"ndv":1085,"upper":"1847059232461946880","lower":"1846857436527329280","count":1346,"preSum":49821},{"ndv":1180,"upper":"1847287955912130560","lower":"1847059263684345856","count":1346,"preSum":51167},{"ndv":1159,"upper":"1847488239833710592","lower":"1847287959536009216","count":1346,"preSum":52513},{"ndv":1065,"upper":"1847642091602051072","lower":"1847488443743993856","count":1346,"preSum":53859},{"ndv":1064,"upper":"1847767341757104128","lower":"1847642099336347648","count":1346,"preSum":55205},{"ndv":1046,"upper":"1847866416116531200","lower":"1847767389958045696","count":1346,"preSum":56551},{"ndv":1162,"upper":"1848211673605734400","lower":"1847866416418521088","count":1346,"preSum":57897},{"ndv":1129,"upper":"1848365989633196032","lower":"1848211877482463232","count":1346,"preSum":59243},{"ndv":1101,"upper":"1848493730886057984","lower":"1848366227332792320","count":1348,"preSum":60589},{"ndv":1112,"upper":"1848631524912529408","lower":"1848493739811536896","count":1347,"preSum":61937},{"ndv":1103,"upper":"1848717936399745024","lower":"1848631533838008320","count":1347,"preSum":63284},{"ndv":1157,"upper":"1848992243294142464","lower":"1848718075013103616","count":1346,"preSum":64631},{"ndv":1152,"upper":"1849212625414520832","lower":"1848992310990209024","count":1346,"preSum":65977},{"ndv":1103,"upper":"1849414892520472576","lower":"1849212706146484224","count":1348,"preSum":67323},{"ndv":1121,"upper":"1849538130818891776","lower":"1849414893543882752","count":1346,"preSum":68671},{"ndv":1008,"upper":"1849612908112117760","lower":"1849538181620301824","count":1346,"preSum":70017},{"ndv":1007,"upper":"1849695941355896832","lower":"1849612908179226624","count":1346,"preSum":71363},{"ndv":1092,"upper":"1849993058653831168","lower":"1849695950549811200","count":1346,"preSum":72709},{"ndv":1066,"upper":"1850151080080441344","lower":"1849993079440801792","count":1347,"preSum":74055},{"ndv":1065,"upper":"1850265549481705472","lower":"1850151133197107200","count":1346,"preSum":75402},{"ndv":1058,"upper":"1850342922176692224","lower":"1850265551545303040","count":1346,"preSum":76748},{"ndv":998,"upper":"1850406294654025728","lower":"1850342922294132736","count":1346,"preSum":78094},{"ndv":1012,"upper":"1850511728769499136","lower":"1850406294771466240","count":1347,"preSum":79440},{"ndv":960,"upper":"1850551394939961344","lower":"1850511730682101760","count":1347,"preSum":80787},{"ndv":1008,"upper":"1850718582179102720","lower":"1850551399184596992","count":1346,"preSum":82134},{"ndv":1150,"upper":"1850947477327314944","lower":"1850718596557176832","count":1346,"preSum":83480},{"ndv":1028,"upper":"1851242070610542592","lower":"1850947495731920896","count":1265,"preSum":84826}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.9243518}','{"countArr":[12656,69,51,40,24,13,94,16,878,14,13,15,13,14],"valueArr":[-1,1837752321967128576,1839346613827403776,1839362006990192640,1839364206013448192,1839445569873903616,1839554427044757504,1839554446757986304,1839607563792941056,1839944748152913920,1845374136570871808,1845979637335719936,1847525546926276608,1850962664180678656],"type":"Datetime","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','harmonic_cust_flag',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','high_enc_trade_code',32,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"105","lower":"105","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100000,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','high_relibility_flag',29,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"on","lower":"on","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[99470,69],"valueArr":["0","1"],"type":"String","sampleRate":0.924351804778851}',461,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','impact_load_flag',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[226,3],"valueArr":["0","1"],"type":"String","sampleRate":0.924351804778851}',99772,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','lat',12405,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":37,"upper":"21***********04","lower":"11***************81","count":60,"preSum":0},{"ndv":17,"upper":"21***********24","lower":"21***********05","count":57,"preSum":60},{"ndv":19,"upper":"21***********46","lower":"21***********25","count":57,"preSum":117},{"ndv":23,"upper":"21***********73","lower":"21***********47","count":60,"preSum":174},{"ndv":24,"upper":"21**********01","lower":"21***********74","count":57,"preSum":234},{"ndv":31,"upper":"21*******44","lower":"21**********06","count":59,"preSum":291},{"ndv":22,"upper":"21*****26","lower":"21*******75","count":60,"preSum":350},{"ndv":23,"upper":"21*****55","lower":"21*****27","count":61,"preSum":410},{"ndv":18,"upper":"21*****78","lower":"21*****56","count":57,"preSum":471},{"ndv":17,"upper":"21*****99","lower":"21*****79","count":57,"preSum":528},{"ndv":31,"upper":"22**************05","lower":"21****02","count":64,"preSum":585},{"ndv":8,"upper":"22**************16","lower":"22**************06","count":60,"preSum":649},{"ndv":8,"upper":"22**************28","lower":"22**************17","count":61,"preSum":709},{"ndv":9,"upper":"22**************43","lower":"22**************32","count":62,"preSum":770},{"ndv":9,"upper":"22**************55","lower":"22**************44","count":61,"preSum":832},{"ndv":8,"upper":"22**************66","lower":"22**************56","count":58,"preSum":893},{"ndv":8,"upper":"22**************77","lower":"22**************67","count":67,"preSum":951},{"ndv":11,"upper":"22**************94","lower":"22**************78","count":64,"preSum":1018},{"ndv":14,"upper":"22*************14","lower":"22**************96","count":58,"preSum":1082},{"ndv":22,"upper":"22*************39","lower":"22*************15","count":61,"preSum":1140},{"ndv":20,"upper":"22*************62","lower":"22*************41","count":58,"preSum":1201},{"ndv":16,"upper":"22*************82","lower":"22*************63","count":57,"preSum":1259},{"ndv":25,"upper":"22************51","lower":"22*************83","count":57,"preSum":1316},{"ndv":49,"upper":"22*******43","lower":"22************54","count":57,"preSum":1373},{"ndv":49,"upper":"22*****00","lower":"22*******44","count":59,"preSum":1430},{"ndv":6,"upper":"22*****06","lower":"22*****01","count":60,"preSum":1489},{"ndv":7,"upper":"22*****14","lower":"22*****07","count":63,"preSum":1549},{"ndv":7,"upper":"22*****23","lower":"22*****15","count":62,"preSum":1612},{"ndv":7,"upper":"22*****32","lower":"22*****24","count":65,"preSum":1674},{"ndv":8,"upper":"22*****42","lower":"22*****33","count":62,"preSum":1739},{"ndv":6,"upper":"22*****48","lower":"22*****43","count":57,"preSum":1801},{"ndv":7,"upper":"22*****57","lower":"22*****49","count":57,"preSum":1858},{"ndv":7,"upper":"22*****64","lower":"22*****58","count":63,"preSum":1915},{"ndv":7,"upper":"22*****71","lower":"22*****65","count":59,"preSum":1978},{"ndv":6,"upper":"22*****77","lower":"22*****72","count":65,"preSum":2037},{"ndv":7,"upper":"22*****84","lower":"22*****78","count":65,"preSum":2102},{"ndv":6,"upper":"22*****91","lower":"22*****85","count":63,"preSum":2167},{"ndv":7,"upper":"22*****99","lower":"22*****92","count":63,"preSum":2230},{"ndv":35,"upper":"22****72","lower":"22****01","count":58,"preSum":2293},{"ndv":35,"upper":"23**************04","lower":"22****73","count":58,"preSum":2351},{"ndv":9,"upper":"23**************16","lower":"23**************05","count":57,"preSum":2409},{"ndv":11,"upper":"23**************33","lower":"23**************17","count":59,"preSum":2466},{"ndv":13,"upper":"23**************51","lower":"23**************34","count":57,"preSum":2525},{"ndv":13,"upper":"23**************67","lower":"23**************52","count":57,"preSum":2582},{"ndv":10,"upper":"23**************83","lower":"23**************68","count":59,"preSum":2639},{"ndv":11,"upper":"23**************97","lower":"23**************84","count":59,"preSum":2698},{"ndv":24,"upper":"23*************27","lower":"23**************98","count":62,"preSum":2757},{"ndv":27,"upper":"23*************58","lower":"23*************28","count":57,"preSum":2819},{"ndv":31,"upper":"23*************97","lower":"23*************59","count":58,"preSum":2876},{"ndv":47,"upper":"23*******04","lower":"23*************98","count":57,"preSum":2934},{"ndv":31,"upper":"23*******49","lower":"23*******06","count":58,"preSum":2991},{"ndv":25,"upper":"23*******85","lower":"23*******51","count":59,"preSum":3049},{"ndv":35,"upper":"23*****08","lower":"23*******88","count":59,"preSum":3108},{"ndv":22,"upper":"23*****34","lower":"23*****09","count":60,"preSum":3167},{"ndv":17,"upper":"23*****51","lower":"23*****35","count":62,"preSum":3227},{"ndv":19,"upper":"23*****72","lower":"23*****53","count":59,"preSum":3289},{"ndv":22,"upper":"23*****97","lower":"23*****73","count":61,"preSum":3348},{"ndv":48,"upper":"24*************03","lower":"23*****98","count":57,"preSum":3409},{"ndv":43,"upper":"24***********85","lower":"24*************22","count":57,"preSum":3466},{"ndv":47,"upper":"24*****72","lower":"24***********88","count":57,"preSum":3523},{"ndv":33,"upper":"高德******58","lower":"24*****75","count":37,"preSum":3580}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[18,17,16,16,17,55,23,16,18,19,18,22,20],"valueArr":["22**************25","22**************95","22*****11","22*****17","22*****21","22*****29","22*****31","22*****35","22*****41","22*****54","22*****56","22*****89","22*****94"],"type":"String","sampleRate":0.924351804778851}',96109,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','line_name',30006,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":41,"upper":"10*********7)","lower":" 1********3 ","count":1405,"preSum":0},{"ndv":23,"upper":"10********2)","lower":"10*********8)","count":1976,"preSum":1405},{"ndv":18,"upper":"10********4)","lower":"10********20","count":1612,"preSum":3381},{"ndv":12,"upper":"10********6)","lower":"10********41","count":1419,"preSum":4993},{"ndv":11,"upper":"10********88","lower":"10********62","count":1381,"preSum":6412},{"ndv":9,"upper":"10*******04","lower":"10********9)","count":1567,"preSum":7793},{"ndv":7,"upper":"10*******11","lower":"10*******05","count":1792,"preSum":9360},{"ndv":7,"upper":"10*******18","lower":"10*******12","count":1581,"preSum":11152},{"ndv":21,"upper":"10*******36","lower":"10*******19","count":1390,"preSum":12733},{"ndv":78,"upper":"10******01","lower":"10*******37","count":1954,"preSum":14123},{"ndv":4,"upper":"10******16","lower":"10******02","count":1834,"preSum":16077},{"ndv":3,"upper":"10******19","lower":"10******17","count":1777,"preSum":17911},{"ndv":6,"upper":"10******23","lower":"10******1A","count":1666,"preSum":19688},{"ndv":4,"upper":"10******27","lower":"10******24","count":1410,"preSum":21354},{"ndv":8,"upper":"10******35","lower":"10******28","count":1438,"preSum":22764},{"ndv":25,"upper":"10******56","lower":"10******36","count":1413,"preSum":24202},{"ndv":78,"upper":"10******F5","lower":"10******57","count":1470,"preSum":25615},{"ndv":58,"upper":"10*****F3","lower":"10******F6","count":1573,"preSum":27085},{"ndv":23,"upper":"10*****镇线","lower":"10*****F4","count":1421,"preSum":28658},{"ndv":59,"upper":"10****甲线","lower":"10****6线","count":1575,"preSum":30079},{"ndv":81,"upper":"10***和线","lower":"10****界线","count":1401,"preSum":31654},{"ndv":50,"upper":"10***富线","lower":"10***嘉线","count":1393,"preSum":33055},{"ndv":78,"upper":"10***景线","lower":"10***察线","count":1405,"preSum":34448},{"ndv":69,"upper":"10***溪线","lower":"10***月线","count":1435,"preSum":35853},{"ndv":99,"upper":"10***近线","lower":"10***滨线","count":1377,"preSum":37288},{"ndv":110,"upper":"70***乙线","lower":"10***进干","count":1451,"preSum":38665},{"ndv":131,"upper":"70**播线","lower":"70***乡线","count":1377,"preSum":40116},{"ndv":157,"upper":"71********古线","lower":"70**教线","count":1377,"preSum":41493},{"ndv":118,"upper":"71****丁线","lower":"71********场线","count":1383,"preSum":42870},{"ndv":86,"upper":"71**区线","lower":"71****丙线","count":1397,"preSum":44253},{"ndv":140,"upper":"71**灯线","lower":"71**升线","count":1379,"preSum":45650},{"ndv":194,"upper":"72*******闸线","lower":"71**灵线","count":1386,"preSum":47029},{"ndv":103,"upper":"72**塘线","lower":"72*******阳线","count":1404,"preSum":48415},{"ndv":195,"upper":"73*******碣线","lower":"72**夏线","count":1377,"preSum":49819},{"ndv":162,"upper":"F***线","lower":"73*******祥线","count":1462,"preSum":51196},{"ndv":113,"upper":"F0**洋线","lower":"F*0","count":1378,"preSum":52658},{"ndv":134,"upper":"F1*******亩线","lower":"F0**洛线","count":1400,"preSum":54036},{"ndv":141,"upper":"F1****一线","lower":"F1*******亮线","count":1396,"preSum":55436},{"ndv":81,"upper":"F1**威线","lower":"F1****丁线","count":1377,"preSum":56832},{"ndv":135,"upper":"F2********城线","lower":"F1**宁线","count":1380,"preSum":58209},{"ndv":156,"upper":"F2***园线","lower":"F2********子线","count":1380,"preSum":59589},{"ndv":166,"upper":"F7**甲线","lower":"F2***坪线","count":1392,"preSum":60969},{"ndv":214,"upper":"东山**81","lower":"F8***乙线","count":1394,"preSum":62361},{"ndv":250,"upper":"仁居***42","lower":"东岭**02","count":1381,"preSum":63755},{"ndv":224,"upper":"凯茵****13","lower":"仁里**61","count":1383,"preSum":65136},{"ndv":216,"upper":"占陇****33","lower":"凯茵****14","count":1383,"preSum":66519},{"ndv":228,"upper":"坝圩**31","lower":"占陇****34","count":1382,"preSum":67902},{"ndv":187,"upper":"大坝*****41","lower":"坝湖**26","count":1377,"preSum":69284},{"ndv":187,"upper":"小***6","lower":"大坝****31","count":1401,"preSum":70661},{"ndv":261,"upper":"惠*线","lower":"小*线","count":1381,"preSum":72062},{"ndv":167,"upper":"新昌*********18","lower":"惠城******45","count":1391,"preSum":73443},{"ndv":207,"upper":"桂园*********64","lower":"新昌*********19","count":1381,"preSum":74834},{"ndv":222,"upper":"永益****07","lower":"桂园**07","count":1378,"preSum":76215},{"ndv":180,"upper":"流沙****2J","lower":"永益****08","count":1381,"preSum":77593},{"ndv":211,"upper":"玉泉****04","lower":"流沙****2K","count":1381,"preSum":78974},{"ndv":256,"upper":"程府**99","lower":"玉泉****13","count":1382,"preSum":80355},{"ndv":209,"upper":"荷塘*********23","lower":"程江**25","count":1379,"preSum":81737},{"ndv":215,"upper":"郭城****JB","lower":"荷塘*********24","count":1383,"preSum":83116},{"ndv":192,"upper":"锦霖****15","lower":"郭城****JC","count":1383,"preSum":84499},{"ndv":268,"upper":"高平****08","lower":"锦霖****19","count":1379,"preSum":85882},{"ndv":154,"upper":"龙黄**25","lower":"高平****10","count":842,"preSum":87261}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[798,883,793,898,889,882,779,824,879,924,870,822,816,841],"valueArr":["10********1)","10******03","10******04","10******05","10******06","10******07","10******09","10******10","10******11","10******12","10******13","10******14","10******15","10****乙线"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','line_no',87181,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":283,"upper":"030200090001841","lower":"0011111129266791","count":1558,"preSum":0},{"ndv":272,"upper":"03040010017","lower":"030200090001845","count":1562,"preSum":1558},{"ndv":338,"upper":"030500000025","lower":"03040010018","count":1576,"preSum":3120},{"ndv":241,"upper":"0305000515001715","lower":"030500000026","count":1556,"preSum":4696},{"ndv":242,"upper":"030500112108","lower":"0305000515001716","count":1587,"preSum":6252},{"ndv":363,"upper":"03060006000922","lower":"030500112109","count":1556,"preSum":7839},{"ndv":360,"upper":"0306001042721","lower":"03060006000924","count":1556,"preSum":9395},{"ndv":447,"upper":"03060041033710","lower":"0306001042722","count":1561,"preSum":10951},{"ndv":372,"upper":"03060066637","lower":"03060041033713","count":1560,"preSum":12512},{"ndv":294,"upper":"03070020DHZD-707","lower":"03060066638","count":1567,"preSum":14072},{"ndv":275,"upper":"030700600207","lower":"03070020DQZ-710","count":1560,"preSum":15639},{"ndv":203,"upper":"030700801123","lower":"030700600208","count":1560,"preSum":17199},{"ndv":197,"upper":"0308002133","lower":"030700801144","count":1578,"preSum":18759},{"ndv":154,"upper":"030800LZBH1402","lower":"0308002153","count":1556,"preSum":20337},{"ndv":170,"upper":"030800xw32070110","lower":"030800LZBH1403","count":1561,"preSum":21893},{"ndv":200,"upper":"030900090002624","lower":"030800xw32070210","count":1557,"preSum":23454},{"ndv":179,"upper":"03090050066","lower":"030900090002625","count":1562,"preSum":25011},{"ndv":171,"upper":"0312001283002085","lower":"03090050069","count":1560,"preSum":26573},{"ndv":220,"upper":"031200B40B04__","lower":"0312001283002135","count":1563,"preSum":28133},{"ndv":266,"upper":"031300090001549","lower":"031200B40B05__","count":1560,"preSum":29696},{"ndv":312,"upper":"0313001325003778","lower":"031300090001550","count":1556,"preSum":31256},{"ndv":294,"upper":"0313006006211502","lower":"0313001325004165","count":1557,"preSum":32812},{"ndv":282,"upper":"031300ZD0002168","lower":"0313006006221404","count":1556,"preSum":34369},{"ndv":259,"upper":"031400302523","lower":"031300ZD0002169","count":1564,"preSum":35925},{"ndv":188,"upper":"03150006000001","lower":"031400302529","count":1567,"preSum":37489},{"ndv":252,"upper":"031600BD702","lower":"03150006000002","count":1556,"preSum":39056},{"ndv":267,"upper":"031600ZD0001857","lower":"031600BD703","count":1562,"preSum":40612},{"ndv":251,"upper":"031700BSF01","lower":"031600ZD0001858","count":1559,"preSum":42174},{"ndv":251,"upper":"0318001801003267","lower":"031700BSF05","count":1556,"preSum":43733},{"ndv":205,"upper":"03180051530007","lower":"0318001801003557","count":1558,"preSum":45289},{"ndv":268,"upper":"0319001920005105","lower":"03180051530008","count":1556,"preSum":46847},{"ndv":382,"upper":"031900500400000216","lower":"0319001920005108","count":1557,"preSum":48403},{"ndv":482,"upper":"031900501700000334","lower":"031900500400000224","count":1557,"preSum":49960},{"ndv":435,"upper":"031900502900000417","lower":"031900501800000101","count":1556,"preSum":51517},{"ndv":457,"upper":"0320002000175975","lower":"031900502900000421","count":1566,"preSum":53073},{"ndv":449,"upper":"0351000021","lower":"0320002000175978","count":1557,"preSum":54639},{"ndv":248,"upper":"0351005121090169","lower":"0351000022","count":1557,"preSum":56196},{"ndv":265,"upper":"0352003030FL50","lower":"0351005121090172","count":1556,"preSum":57753},{"ndv":184,"upper":"0352007030F2M0","lower":"0352003030FL70","count":1560,"preSum":59309},{"ndv":158,"upper":"035300090000189","lower":"03520070405420","count":1559,"preSum":60869},{"ndv":236,"upper":"035300ZD0000342","lower":"035300090000190","count":1562,"preSum":62428},{"ndv":241,"upper":"1111111112051568","lower":"035300ZD0000347","count":1560,"preSum":63990},{"ndv":257,"upper":"1111111112916595","lower":"1111111112051570","count":1558,"preSum":65550},{"ndv":264,"upper":"1111111116996594","lower":"1111111112926599","count":1558,"preSum":67108},{"ndv":283,"upper":"1111111126691770","lower":"1111111116996596","count":1556,"preSum":68666},{"ndv":332,"upper":"1111111129111785","lower":"1111111126691773","count":1556,"preSum":70222},{"ndv":308,"upper":"1111111129581998","lower":"1111111129111787","count":1557,"preSum":71778},{"ndv":296,"upper":"352220831143200","lower":"1111111129582000","count":1567,"preSum":73335},{"ndv":357,"upper":"357000340636601","lower":"352220833989500","count":1561,"preSum":74902},{"ndv":350,"upper":"361221970090800","lower":"357000352281301","count":1556,"preSum":76463},{"ndv":305,"upper":"371221275650300","lower":"361221977598800","count":1565,"preSum":78019},{"ndv":287,"upper":"377220705792100","lower":"371221279714100","count":1557,"preSum":79584},{"ndv":242,"upper":"384221087309700","lower":"377220714876200","count":1562,"preSum":81141},{"ndv":205,"upper":"393000773602401","lower":"384221112268900","count":1575,"preSum":82703},{"ndv":190,"upper":"399220387144300","lower":"393000788792701","count":1562,"preSum":84278},{"ndv":214,"upper":"409000018453101","lower":"399220387202500","count":1560,"preSum":85840},{"ndv":231,"upper":"420220588205800","lower":"409000018453801","count":1558,"preSum":87400},{"ndv":228,"upper":"431480328790100","lower":"420220608036100","count":1558,"preSum":88958},{"ndv":258,"upper":"448220686877600","lower":"431480329341100","count":1558,"preSum":90516},{"ndv":201,"upper":"465220274267200","lower":"448220688634500","count":1559,"preSum":92074},{"ndv":239,"upper":"476220335315000","lower":"465220274270800","count":1566,"preSum":93633},{"ndv":334,"upper":"483221912653100","lower":"476220358073200","count":1556,"preSum":95199},{"ndv":441,"upper":"917220530980100","lower":"483221919910400","count":1563,"preSum":96755},{"ndv":287,"upper":"铁场变电站F20","lower":"917220587081600","count":1206,"preSum":98318}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[51,47,43,44,47,51,52,48,48,46],"valueArr":["030800NT07","03090081903","031400090001116","031800090002338","035100090000561","035200090001335","035300B50LG521","1111111112321596","393000725442001","451001012334801"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','lng',3475,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":14,"upper":"11**************14","lower":"10******91","count":47,"preSum":0},{"ndv":11,"upper":"11**************26","lower":"11**************15","count":44,"preSum":47},{"ndv":11,"upper":"11**************38","lower":"11**************27","count":41,"preSum":91},{"ndv":13,"upper":"11**************54","lower":"11**************39","count":42,"preSum":132},{"ndv":10,"upper":"11**************65","lower":"11**************55","count":41,"preSum":174},{"ndv":12,"upper":"11**************78","lower":"11**************66","count":42,"preSum":215},{"ndv":11,"upper":"11**************92","lower":"11**************79","count":41,"preSum":257},{"ndv":19,"upper":"11*************36","lower":"11**************93","count":41,"preSum":298},{"ndv":29,"upper":"11***********02","lower":"11*************37","count":42,"preSum":339},{"ndv":12,"upper":"11***********14","lower":"11***********03","count":41,"preSum":381},{"ndv":15,"upper":"11***********29","lower":"11***********15","count":43,"preSum":422},{"ndv":11,"upper":"11***********41","lower":"11***********3\\"","count":41,"preSum":465},{"ndv":12,"upper":"11***********53","lower":"11***********42","count":48,"preSum":506},{"ndv":10,"upper":"11***********64","lower":"11***********54","count":41,"preSum":554},{"ndv":11,"upper":"11***********76","lower":"11***********65","count":43,"preSum":595},{"ndv":9,"upper":"11***********85","lower":"11***********77","count":42,"preSum":638},{"ndv":10,"upper":"11***********95","lower":"11***********86","count":41,"preSum":680},{"ndv":26,"upper":"11**********95","lower":"11***********96","count":42,"preSum":721},{"ndv":19,"upper":"11*******11","lower":"11**********96","count":42,"preSum":763},{"ndv":11,"upper":"11*******24","lower":"11*******12","count":43,"preSum":805},{"ndv":17,"upper":"11*******44","lower":"11*******25","count":43,"preSum":848},{"ndv":20,"upper":"11*******67","lower":"11*******45","count":41,"preSum":891},{"ndv":16,"upper":"11*******86","lower":"11*******68","count":41,"preSum":932},{"ndv":13,"upper":"11******01","lower":"11*******87","count":43,"preSum":973},{"ndv":3,"upper":"11******04","lower":"11******02","count":55,"preSum":1016},{"ndv":2,"upper":"11******06","lower":"11******05","count":45,"preSum":1071},{"ndv":3,"upper":"11******09","lower":"11******07","count":55,"preSum":1116},{"ndv":5,"upper":"11******14","lower":"11******10","count":59,"preSum":1171},{"ndv":3,"upper":"11******17","lower":"11******15","count":54,"preSum":1230},{"ndv":4,"upper":"11******21","lower":"11******18","count":47,"preSum":1284},{"ndv":3,"upper":"11******24","lower":"11******22","count":56,"preSum":1331},{"ndv":3,"upper":"11******28","lower":"11******25","count":50,"preSum":1387},{"ndv":3,"upper":"11******31","lower":"11******29","count":52,"preSum":1437},{"ndv":3,"upper":"11******34","lower":"11******32","count":49,"preSum":1489},{"ndv":2,"upper":"11******36","lower":"11******35","count":44,"preSum":1538},{"ndv":3,"upper":"11******39","lower":"11******37","count":56,"preSum":1582},{"ndv":4,"upper":"11******44","lower":"11******40","count":51,"preSum":1638},{"ndv":3,"upper":"11******47","lower":"11******45","count":44,"preSum":1689},{"ndv":3,"upper":"11******51","lower":"11******48","count":56,"preSum":1733},{"ndv":3,"upper":"11******55","lower":"11******52","count":51,"preSum":1789},{"ndv":2,"upper":"11******57","lower":"11******56","count":47,"preSum":1840},{"ndv":3,"upper":"11******61","lower":"11******58","count":49,"preSum":1887},{"ndv":3,"upper":"11******64","lower":"11******62","count":48,"preSum":1936},{"ndv":3,"upper":"11******67","lower":"11******65","count":54,"preSum":1984},{"ndv":4,"upper":"11******72","lower":"11******68","count":59,"preSum":2038},{"ndv":3,"upper":"11******77","lower":"11******73","count":43,"preSum":2097},{"ndv":4,"upper":"11******81","lower":"11******78","count":42,"preSum":2140},{"ndv":4,"upper":"11******86","lower":"11******82","count":51,"preSum":2182},{"ndv":3,"upper":"11******89","lower":"11******87","count":45,"preSum":2233},{"ndv":4,"upper":"11******93","lower":"11******90","count":52,"preSum":2278},{"ndv":3,"upper":"11******96","lower":"11******94","count":53,"preSum":2330},{"ndv":3,"upper":"11******99","lower":"11******97","count":42,"preSum":2383},{"ndv":21,"upper":"11*****32","lower":"11*****01","count":42,"preSum":2425},{"ndv":22,"upper":"11*****63","lower":"11*****34","count":41,"preSum":2467},{"ndv":23,"upper":"11*****96","lower":"11*****64","count":42,"preSum":2508},{"ndv":32,"upper":"高德********62","lower":"11*****97","count":41,"preSum":2550},{"ndv":4,"upper":"高德*******92","lower":"高德********65","count":4,"preSum":2591}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[65,514,326,175,29,27,28,55,25,28,25],"valueArr":["11**************96","11**************97","11**************98","11**************99","11******27","11******43","11******53","11******69","11******74","11******75","11******83"],"type":"String","sampleRate":0.924351804778851}',96109,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','load_attr_code',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[153,301,96644,14],"valueArr":["1","2","3","4"],"type":"String","sampleRate":0.924351804778851}',2889,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','made_date',18229,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":287,"upper":"1841369715222511616","lower":"-1","count":1362,"preSum":0},{"ndv":155,"upper":"1842803478385131520","lower":"1841371914245767168","count":1365,"preSum":1362},{"ndv":116,"upper":"1843610519919919104","lower":"1842805677408387072","count":1370,"preSum":2727},{"ndv":82,"upper":"1844061319687307264","lower":"1843612718943174656","count":1413,"preSum":4097},{"ndv":50,"upper":"1844428556570984448","lower":"1844072314803585024","count":1369,"preSum":5510},{"ndv":25,"upper":"1844498925315162112","lower":"1844437352664006656","count":1367,"preSum":6879},{"ndv":16,"upper":"1844560497966317568","lower":"1844501124338417664","count":1502,"preSum":8246},{"ndv":18,"upper":"1844615473547706368","lower":"1844562696989573120","count":1482,"preSum":9748},{"ndv":18,"upper":"1844674847175606272","lower":"1844617672570961920","count":1396,"preSum":11230},{"ndv":26,"upper":"1844789196384894976","lower":"1844677046198861824","count":1450,"preSum":12626},{"ndv":29,"upper":"1844914540710461440","lower":"1844793594431406080","count":1485,"preSum":14076},{"ndv":9,"upper":"1844940928989528064","lower":"1844916739733716992","count":1477,"preSum":15561},{"ndv":10,"upper":"1844965118245339136","lower":"1844943128012783616","count":1371,"preSum":17038},{"ndv":12,"upper":"1845000302617427968","lower":"1844967317268594688","count":1462,"preSum":18409},{"ndv":14,"upper":"1845037686012772352","lower":"1845002501640683520","count":1377,"preSum":19871},{"ndv":19,"upper":"1845086064524394496","lower":"1845039885036027904","count":1535,"preSum":21248},{"ndv":19,"upper":"1845218005919727616","lower":"1845088263547650048","count":1419,"preSum":22783},{"ndv":45,"upper":"1845393927780171776","lower":"1845220204942983168","count":1398,"preSum":24202},{"ndv":22,"upper":"1845466495547604992","lower":"1845396126803427328","count":1361,"preSum":25600},{"ndv":10,"upper":"1845497281873182720","lower":"1845468694570860544","count":1475,"preSum":26961},{"ndv":11,"upper":"1845523670152249344","lower":"1845499480896438272","count":1431,"preSum":28436},{"ndv":15,"upper":"1845556655501082624","lower":"1845525869175504896","count":1494,"preSum":29867},{"ndv":19,"upper":"1845605034012704768","lower":"1845558854524338176","count":1370,"preSum":31361},{"ndv":27,"upper":"1845675402756882432","lower":"1845607233035960320","count":1398,"preSum":32731},{"ndv":12,"upper":"1845723781268504576","lower":"1845677601780137984","count":1420,"preSum":34129},{"ndv":6,"upper":"1845739174431293440","lower":"1845725980291760128","count":1361,"preSum":35549},{"ndv":8,"upper":"1845763363687104512","lower":"1845741373454548992","count":1410,"preSum":36910},{"ndv":6,"upper":"1845783154896404480","lower":"1845765562710360064","count":1482,"preSum":38320},{"ndv":7,"upper":"1845798548059193344","lower":"1845785353919660032","count":1382,"preSum":39802},{"ndv":8,"upper":"1845816140245237760","lower":"1845800747082448896","count":1489,"preSum":41184},{"ndv":13,"upper":"1845853523640582144","lower":"1845818339268493312","count":1465,"preSum":42673},{"ndv":8,"upper":"1845871115826626560","lower":"1845855722663837696","count":1473,"preSum":44138},{"ndv":13,"upper":"1845899703128948736","lower":"1845873314849882112","count":1368,"preSum":45611},{"ndv":29,"upper":"1845985465035915264","lower":"1845901902152204288","count":1378,"preSum":46979},{"ndv":23,"upper":"1846049236710326272","lower":"1845989863082426368","count":1516,"preSum":48357},{"ndv":13,"upper":"1846159187873103872","lower":"1846051435733581824","count":1429,"preSum":49873},{"ndv":12,"upper":"1846207566384726016","lower":"1846161386896359424","count":1364,"preSum":51302},{"ndv":23,"upper":"1846306522431225856","lower":"1846209765407981568","count":1377,"preSum":52666},{"ndv":23,"upper":"1846376891175403520","lower":"1846308721454481408","count":1398,"preSum":54043},{"ndv":43,"upper":"1846568206198636544","lower":"1846379090198659072","count":1381,"preSum":55441},{"ndv":21,"upper":"1846623181780025344","lower":"1846570405221892096","count":1444,"preSum":56822},{"ndv":86,"upper":"1847073981547413504","lower":"1846625380803280896","count":1369,"preSum":58266},{"ndv":200,"upper":"1847527776366624768","lower":"1847091573733457920","count":1364,"preSum":59635},{"ndv":234,"upper":"1847718992706273280","lower":"1847529890279063552","count":1367,"preSum":60999},{"ndv":105,"upper":"1847871141570412544","lower":"1847719025639948288","count":1369,"preSum":62366},{"ndv":113,"upper":"1848359267975823360","lower":"1847872946698190848","count":1368,"preSum":63735},{"ndv":108,"upper":"1848514979179790336","lower":"1848359316831076352","count":1378,"preSum":65103},{"ndv":142,"upper":"1848870583547199488","lower":"1848515016207106048","count":1381,"preSum":66481},{"ndv":139,"upper":"1849073628998533120","lower":"1848880012258705408","count":1375,"preSum":67862},{"ndv":131,"upper":"1849210203472396288","lower":"1849073843059032064","count":1358,"preSum":69237},{"ndv":173,"upper":"1849396827435040768","lower":"1849212504148803584","count":1362,"preSum":70595},{"ndv":150,"upper":"1849485164527222784","lower":"1849396842970742784","count":1384,"preSum":71957},{"ndv":111,"upper":"1849595059167559680","lower":"1849485270777331712","count":1368,"preSum":73341},{"ndv":134,"upper":"1849805977528827904","lower":"1849595078947897344","count":1367,"preSum":74709},{"ndv":152,"upper":"1850043855634694144","lower":"1849806124446908416","count":1362,"preSum":76076},{"ndv":113,"upper":"1850133539870212096","lower":"1850043869073244160","count":1370,"preSum":77438},{"ndv":74,"upper":"1850197711396012032","lower":"1850133552419569664","count":1379,"preSum":78808},{"ndv":61,"upper":"1850313923815800832","lower":"1850199432822259712","count":1364,"preSum":80187},{"ndv":72,"upper":"1850390764454936576","lower":"1850316488464924672","count":1363,"preSum":81551},{"ndv":77,"upper":"1850469965363150848","lower":"1850390770712838144","count":1374,"preSum":82914},{"ndv":84,"upper":"1850588721410211840","lower":"1850469997961281536","count":1362,"preSum":84288},{"ndv":152,"upper":"1851132324297572352","lower":"1850588756910800896","count":1241,"preSum":85650}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.9243518}','{"countArr":[1761,638,579,868,1015,644,1586,629,1076,721,1175,748,857,813],"valueArr":[1844859565129072640,1845094860617416704,1845211408849960960,1845492883826671616,1845703990059204608,1845719383221993472,1845774358803382272,1845827135361515520,1845844727547559936,1845919494338248704,1846126202524270592,1846134998617292800,1846196571268448256,1846266940012625920],"type":"Datetime","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','market_attr_sort_code',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[5],"valueArr":["03"],"type":"String","sampleRate":0.924351804778851}',99996,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','market_cust_flag',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','meter_cate_code',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"2","lower":"2","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[85316,11185],"valueArr":["1","3"],"type":"String","sampleRate":0.924351804778851}',3498,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','meter_self_factor',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.9243518}','{"countArr":[25,96490],"valueArr":[0.000,1.000],"type":"Double","sampleRate":0.924351804778851}',3486,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_addr',1112404,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":594,"upper":"0妈脱敏-1","lower":"\\t新脱敏8号","count":1182,"preSum":0},{"ndv":849,"upper":"17脱敏4号","lower":"0妈脱敏-2","count":1183,"preSum":1182},{"ndv":539,"upper":"36脱敏2号","lower":"17脱敏5号","count":1184,"preSum":2365},{"ndv":827,"upper":"D1脱敏17","lower":"36脱敏36","count":1183,"preSum":3549},{"ndv":689,"upper":"三埠脱敏82","lower":"D2脱敏01","count":1182,"preSum":4732},{"ndv":842,"upper":"下义脱敏5点","lower":"三埠脱敏83","count":1182,"preSum":5914},{"ndv":833,"upper":"东城脱敏02","lower":"下义脱敏6号","count":1193,"preSum":7096},{"ndv":596,"upper":"东莞脱敏04","lower":"东城脱敏03","count":1218,"preSum":8289},{"ndv":558,"upper":"中兴脱敏店]","lower":"东莞脱敏05","count":1182,"preSum":9507},{"ndv":613,"upper":"丰顺脱敏工村","lower":"中兴脱敏开发","count":1182,"preSum":10689},{"ndv":819,"upper":"云岩脱敏背岭","lower":"丰顺脱敏底街","count":1182,"preSum":11871},{"ndv":870,"upper":"佛冈脱敏 ","lower":"云岩脱敏背村","count":1182,"preSum":13053},{"ndv":649,"upper":"光明脱敏西园","lower":"佛冈脱敏01","count":1183,"preSum":14235},{"ndv":946,"upper":"凤仪脱敏营村","lower":"光明脱敏路8","count":1182,"preSum":15418},{"ndv":846,"upper":"北潮脱敏8号","lower":"凤光脱敏光一","count":1182,"preSum":16600},{"ndv":863,"upper":"南山脱敏8箱","lower":"北澳脱敏4号","count":1182,"preSum":17782},{"ndv":541,"upper":"南街脱敏4房","lower":"南山脱敏9箱","count":1182,"preSum":18964},{"ndv":847,"upper":"古水脱敏头村","lower":"南街脱敏7卡","count":1182,"preSum":20146},{"ndv":945,"upper":"四九脱敏安村","lower":"古水脱敏头西","count":1182,"preSum":21328},{"ndv":786,"upper":"坪石脱敏05","lower":"四九脱敏开村","count":1182,"preSum":22510},{"ndv":855,"upper":"塘边脱敏一台","lower":"坪石脱敏1号","count":1183,"preSum":23692},{"ndv":762,"upper":"大布脱敏制厂","lower":"塘边脱敏垌村","count":1182,"preSum":24875},{"ndv":862,"upper":"太阳脱敏太阳","lower":"大布脱敏唐屋","count":1182,"preSum":26057},{"ndv":827,"upper":"宾亨脱敏17","lower":"太阳脱敏阳升","count":1182,"preSum":27239},{"ndv":900,"upper":"岭海脱敏2房","lower":"宾亨脱敏2号","count":1183,"preSum":28421},{"ndv":845,"upper":"广东脱敏 ","lower":"岭背脱敏7号","count":1202,"preSum":29604},{"ndv":68,"upper":"广东脱敏11","lower":"广东脱敏 B","count":1210,"preSum":30806},{"ndv":96,"upper":"广东脱敏3号","lower":"广东脱敏12","count":1227,"preSum":32016},{"ndv":82,"upper":"广东脱敏5)","lower":"广东脱敏3室","count":1185,"preSum":33243},{"ndv":96,"upper":"广东脱敏95","lower":"广东脱敏6#","count":1182,"preSum":34428},{"ndv":343,"upper":"广东脱敏公寓","lower":"广东脱敏97","count":1185,"preSum":35610},{"ndv":292,"upper":"广东脱敏园)","lower":"广东脱敏公屋","count":1183,"preSum":36795},{"ndv":324,"upper":"广东脱敏山村","lower":"广东脱敏园仔","count":1224,"preSum":37978},{"ndv":353,"upper":"广东脱敏楼F","lower":"广东脱敏山楼","count":1182,"preSum":39202},{"ndv":495,"upper":"广东脱敏角)","lower":"广东脱敏楼G","count":1182,"preSum":40384},{"ndv":703,"upper":"开平脱敏1房","lower":"广东脱敏誉)","count":1183,"preSum":41566},{"ndv":702,"upper":"惠州脱敏08","lower":"开平脱敏2号","count":1185,"preSum":42749},{"ndv":715,"upper":"文化脱敏变台","lower":"惠州脱敏09","count":1183,"preSum":43934},{"ndv":826,"upper":"新宁脱敏96","lower":"文化脱敏口侧","count":1182,"preSum":45117},{"ndv":868,"upper":"旧郎脱敏东江","lower":"新宁脱敏龙村","count":1182,"preSum":46299},{"ndv":946,"upper":"李妙脱敏妙坤","lower":"旧郎脱敏南塘","count":1182,"preSum":47481},{"ndv":891,"upper":"桔城脱敏0)","lower":"李宅脱敏宅村","count":1182,"preSum":48663},{"ndv":728,"upper":"榄溪脱敏台变","lower":"桔城脱敏2)","count":1182,"preSum":49845},{"ndv":930,"upper":"永厚脱敏下街","lower":"榄滩脱敏滩村","count":1182,"preSum":51027},{"ndv":917,"upper":"沙湾脱敏5号","lower":"永合脱敏02","count":1182,"preSum":52209},{"ndv":737,"upper":"泰星脱敏号房","lower":"沙溪脱敏01","count":1182,"preSum":53391},{"ndv":839,"upper":"清水脱敏清水","lower":"泰景脱敏1房","count":1184,"preSum":54573},{"ndv":837,"upper":"潮州脱敏03","lower":"清湖脱敏13","count":1182,"preSum":55757},{"ndv":704,"upper":"环溪脱敏9号","lower":"潮州脱敏04","count":1182,"preSum":56939},{"ndv":464,"upper":"电机脱敏二幢","lower":"环球脱敏变台","count":1182,"preSum":58121},{"ndv":856,"upper":"石板脱敏2号","lower":"电杆脱敏杆厂","count":1182,"preSum":59303},{"ndv":808,"upper":"禾仔脱敏苏)","lower":"石板脱敏4号","count":1182,"preSum":60485},{"ndv":892,"upper":"纪家脱敏郎村","lower":"禾化脱敏化村","count":1182,"preSum":61667},{"ndv":914,"upper":"聚龙脱敏02","lower":"纪家脱敏鉴村","count":1182,"preSum":62849},{"ndv":853,"upper":"荣堂脱敏-1","lower":"聚龙脱敏04","count":1182,"preSum":64031},{"ndv":966,"upper":"西河脱敏山下","lower":"荣堂脱敏15","count":1182,"preSum":65213},{"ndv":710,"upper":"赤岗脱敏大地","lower":"西河脱敏岭北","count":1182,"preSum":66395},{"ndv":927,"upper":"郭田脱敏台变","lower":"赤岗脱敏大田","count":1185,"preSum":67577},{"ndv":856,"upper":"铁场脱敏公变","lower":"郭田脱敏衣寨","count":1190,"preSum":68762},{"ndv":841,"upper":"阳山脱敏华庭","lower":"铁场脱敏墟镇","count":1183,"preSum":69952},{"ndv":859,"upper":"韶关脱敏02","lower":"阳山脱敏变)","count":1190,"preSum":71135},{"ndv":860,"upper":"高联脱敏胜村","lower":"韶关脱敏03","count":1182,"preSum":72325},{"ndv":862,"upper":"黄茅脱敏黄茅","lower":"高联脱敏迁村","count":1183,"preSum":73507},{"ndv":712,"upper":"??脱敏??","lower":"黄茶脱敏坝村","count":946,"preSum":74690}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1462,1687,1629,1362,994,498,451,1149,415,1157,1073,669,1243,10576],"valueArr":["-脱敏-","广东脱敏01","广东脱敏02","广东脱敏03","广东脱敏04","广东脱敏05","广东脱敏1号","广东脱敏1房","广东脱敏2号","广东脱敏2房","广东脱敏3房","广东脱敏4房","广东脱敏号房","脱敏"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_ct_ratio_code',120,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"01","lower":"01","count":33,"preSum":0},{"ndv":1,"upper":"02","lower":"02","count":17,"preSum":33},{"ndv":1,"upper":"04","lower":"04","count":15,"preSum":50},{"ndv":1,"upper":"06","lower":"06","count":35,"preSum":65},{"ndv":2,"upper":"13","lower":"08","count":45,"preSum":100},{"ndv":1,"upper":"19","lower":"19","count":37,"preSum":145},{"ndv":1,"upper":"21","lower":"21","count":24,"preSum":182},{"ndv":1,"upper":"25","lower":"25","count":48,"preSum":206},{"ndv":2,"upper":"27","lower":"26","count":6,"preSum":254},{"ndv":4,"upper":"44","lower":"28","count":9,"preSum":260},{"ndv":1,"upper":"45","lower":"45","count":8,"preSum":269},{"ndv":2,"upper":"47","lower":"46","count":31,"preSum":277},{"ndv":2,"upper":"50","lower":"49","count":6,"preSum":308},{"ndv":2,"upper":"70","lower":"61","count":6,"preSum":314},{"ndv":1,"upper":"73","lower":"73","count":9,"preSum":320},{"ndv":1,"upper":"88","lower":"88","count":1,"preSum":329}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[61,197,219,192,638,269,561,211,191,322,121,91,217,130],"valueArr":["03","05","07","09","10","11","12","14","15","16","17","18","20","23"],"type":"String","sampleRate":0.924351804778851}',96251,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_dc_name',19,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"云浮","lower":"云浮","count":3086,"preSum":0},{"ndv":1,"upper":"汕尾","lower":"汕尾","count":2652,"preSum":3086},{"ndv":1,"upper":"河源","lower":"河源","count":3071,"preSum":5738},{"ndv":1,"upper":"珠海","lower":"珠海","count":2912,"preSum":8809},{"ndv":1,"upper":"阳江","lower":"阳江","count":3270,"preSum":11721}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[8073,4160,10034,8653,6554,4635,5972,6679,5282,6095,3307,5211,6323,4032],"valueArr":["东莞","中山","佛山","惠州","揭阳","梅州","汕头","江门","清远","湛江","潮州","肇庆","茂名","韶关"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_dc_no',19,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"0304","lower":"0304","count":2912,"preSum":0},{"ndv":1,"upper":"0315","lower":"0315","count":2652,"preSum":2912},{"ndv":1,"upper":"0316","lower":"0316","count":3071,"preSum":5564},{"ndv":1,"upper":"0317","lower":"0317","count":3270,"preSum":8635},{"ndv":1,"upper":"0353","lower":"0353","count":3086,"preSum":11905}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[4032,5972,10034,6679,6095,6323,5211,8653,4635,5282,8073,4160,3307,6554],"valueArr":["0302","0305","0306","0307","0308","0309","0312","0313","0314","0318","0319","0320","0351","0352"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_dis_org_no',142,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":4,"upper":"030210","lower":"030202","count":1871,"preSum":0},{"ndv":3,"upper":"030215","lower":"030213","count":1393,"preSum":1871},{"ndv":3,"upper":"030401","lower":"030216","count":1245,"preSum":3264},{"ndv":2,"upper":"030403","lower":"030402","count":2317,"preSum":4509},{"ndv":3,"upper":"030523","lower":"030431","count":1210,"preSum":6826},{"ndv":4,"upper":"030547","lower":"030526","count":2068,"preSum":8036},{"ndv":1,"upper":"030549","lower":"030549","count":1265,"preSum":10104},{"ndv":1,"upper":"030614","lower":"030614","count":1458,"preSum":11369},{"ndv":2,"upper":"030702","lower":"030615","count":2196,"preSum":12827},{"ndv":2,"upper":"030705","lower":"030704","count":1580,"preSum":15023},{"ndv":2,"upper":"030714","lower":"030713","count":1291,"preSum":16603},{"ndv":2,"upper":"030801","lower":"030715","count":1386,"preSum":17894},{"ndv":2,"upper":"030810","lower":"030802","count":2080,"preSum":19280},{"ndv":2,"upper":"030815","lower":"030814","count":1208,"preSum":21360},{"ndv":3,"upper":"030908","lower":"030828","count":1774,"preSum":22568},{"ndv":1,"upper":"030909","lower":"030909","count":1377,"preSum":24342},{"ndv":2,"upper":"030915","lower":"030910","count":1272,"preSum":25719},{"ndv":1,"upper":"030916","lower":"030916","count":1160,"preSum":26991},{"ndv":2,"upper":"031203","lower":"031202","count":1997,"preSum":28151},{"ndv":3,"upper":"031206","lower":"031204","count":1259,"preSum":30148},{"ndv":2,"upper":"031210","lower":"031209","count":1190,"preSum":31407},{"ndv":3,"upper":"031303","lower":"031211","count":1937,"preSum":32597},{"ndv":1,"upper":"031306","lower":"031306","count":1217,"preSum":34534},{"ndv":2,"upper":"031316","lower":"031313","count":1163,"preSum":35751},{"ndv":2,"upper":"031403","lower":"031401","count":1255,"preSum":36914},{"ndv":2,"upper":"031406","lower":"031405","count":1241,"preSum":38169},{"ndv":3,"upper":"031410","lower":"031407","count":1611,"preSum":39410},{"ndv":2,"upper":"031502","lower":"031414","count":1621,"preSum":41021},{"ndv":3,"upper":"031510","lower":"031503","count":1143,"preSum":42642},{"ndv":3,"upper":"031609","lower":"031511","count":1387,"preSum":43785},{"ndv":3,"upper":"031626","lower":"031610","count":1416,"preSum":45172},{"ndv":2,"upper":"031704","lower":"031633","count":1765,"preSum":46588},{"ndv":3,"upper":"031707","lower":"031705","count":1345,"preSum":48353},{"ndv":2,"upper":"031821","lower":"031710","count":1372,"preSum":49698},{"ndv":4,"upper":"031827","lower":"031823","count":1524,"preSum":51070},{"ndv":2,"upper":"031882","lower":"031881","count":1357,"preSum":52594},{"ndv":2,"upper":"031971","lower":"031970","count":1893,"preSum":53951},{"ndv":2,"upper":"031973","lower":"031972","count":1188,"preSum":55844},{"ndv":2,"upper":"031975","lower":"031974","count":1752,"preSum":57032},{"ndv":3,"upper":"032014","lower":"031976","count":1157,"preSum":58784},{"ndv":5,"upper":"032019","lower":"032015","count":1318,"preSum":59941},{"ndv":8,"upper":"032027","lower":"032020","count":1390,"preSum":61259},{"ndv":11,"upper":"035105","lower":"032028","count":2173,"preSum":62649},{"ndv":3,"upper":"035202","lower":"035115","count":1696,"preSum":64822},{"ndv":2,"upper":"035207","lower":"035203","count":2302,"preSum":66518},{"ndv":2,"upper":"035301","lower":"035215","count":1248,"preSum":68820},{"ndv":2,"upper":"035305","lower":"035304","count":1217,"preSum":70068},{"ndv":2,"upper":"035313","lower":"035306","count":1293,"preSum":71285}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1537,1623,3484,2655,1484,1558,1543,1918,1592,1591,1873,2448,1460,2645],"valueArr":["030548","030603","030612","030613","030706","030820","030902","031302","031304","031314","031801","031969","035109","035206"],"type":"String","sampleRate":0.924351804778851}',12,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_dis_org_short_name',138,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"三水","lower":"三乡供电分局","count":1847,"preSum":0},{"ndv":6,"upper":"东源","lower":"三角供电分局","count":1538,"preSum":1847},{"ndv":1,"upper":"东莞东北区","lower":"东莞东北区","count":1169,"preSum":3385},{"ndv":2,"upper":"东莞东南区","lower":"东莞东区","count":1633,"preSum":4554},{"ndv":2,"upper":"东莞虎门","lower":"东莞南区(新)","count":1164,"preSum":6187},{"ndv":2,"upper":"东莞西区","lower":"东莞西北区","count":1188,"preSum":7351},{"ndv":3,"upper":"乐昌","lower":"东莞长安(新)","count":1728,"preSum":8539},{"ndv":4,"upper":"五华","lower":"乳源","count":2052,"preSum":10267},{"ndv":4,"upper":"佛冈","lower":"五桂山供电分局","count":1360,"preSum":12319},{"ndv":2,"upper":"兴宁","lower":"信宜","count":1686,"preSum":13679},{"ndv":1,"upper":"化州","lower":"化州","count":1377,"preSum":15365},{"ndv":5,"upper":"南雄","lower":"南区供电分局","count":1166,"preSum":16742},{"ndv":3,"upper":"和平","lower":"古镇供电分局","count":1352,"preSum":17908},{"ndv":2,"upper":"坡头","lower":"四会","count":1293,"preSum":19260},{"ndv":2,"upper":"大亚湾","lower":"坦洲供电分局","count":1451,"preSum":20553},{"ndv":4,"upper":"始兴","lower":"大埔","count":1178,"preSum":22004},{"ndv":5,"upper":"广宁","lower":"封开","count":1280,"preSum":23182},{"ndv":1,"upper":"开平","lower":"开平","count":1383,"preSum":24462},{"ndv":3,"upper":"怀集","lower":"徐闻","count":1898,"preSum":25845},{"ndv":2,"upper":"惠来","lower":"恩平","count":1666,"preSum":27743},{"ndv":1,"upper":"惠阳","lower":"惠阳","count":1217,"preSum":29409},{"ndv":1,"upper":"揭东","lower":"揭东","count":1187,"preSum":30626},{"ndv":2,"upper":"斗门","lower":"揭西","count":1599,"preSum":31813},{"ndv":3,"upper":"新兴","lower":"新丰","count":1958,"preSum":33412},{"ndv":3,"upper":"梅县","lower":"曲江","count":1260,"preSum":35370},{"ndv":1,"upper":"榕城","lower":"榕城","count":1115,"preSum":36630},{"ndv":4,"upper":"汕尾陆丰","lower":"横栏供电分局","count":2009,"preSum":37745},{"ndv":4,"upper":"海陵岛","lower":"汕尾陆河","count":1170,"preSum":39754},{"ndv":3,"upper":"源城","lower":"清新","count":1587,"preSum":40924},{"ndv":1,"upper":"潮南","lower":"潮南","count":1265,"preSum":42511},{"ndv":1,"upper":"潮安","lower":"潮安","count":1460,"preSum":43776},{"ndv":2,"upper":"澄海","lower":"潮州湘桥","count":1606,"preSum":45236},{"ndv":3,"upper":"电白","lower":"濠江","count":1567,"preSum":46842},{"ndv":3,"upper":"端州","lower":"石岐供电分局","count":1155,"preSum":48409},{"ndv":3,"upper":"罗定","lower":"紫金","count":1524,"preSum":49564},{"ndv":2,"upper":"英德","lower":"翁源","count":1386,"preSum":51088},{"ndv":1,"upper":"茂南","lower":"茂南","count":1160,"preSum":52474},{"ndv":2,"upper":"蓬江","lower":"茂港","count":1231,"preSum":53634},{"ndv":6,"upper":"连平","lower":"蕉岭","count":1422,"preSum":54865},{"ndv":2,"upper":"郁南","lower":"遂溪","count":1405,"preSum":56287},{"ndv":3,"upper":"金湾","lower":"金平","count":1548,"preSum":57692},{"ndv":3,"upper":"阳山","lower":"阜沙供电分局","count":1315,"preSum":59240},{"ndv":2,"upper":"阳西","lower":"阳春","count":1563,"preSum":60555},{"ndv":1,"upper":"雷州","lower":"雷州","count":1182,"preSum":62118},{"ndv":2,"upper":"香洲","lower":"饶平","count":2476,"preSum":63300},{"ndv":2,"upper":"高要","lower":"高明","count":1893,"preSum":65776},{"ndv":3,"upper":"黄圃供电分局","lower":"鹤山","count":1226,"preSum":67669},{"ndv":3,"upper":"龙湖","lower":"鼎湖","count":1834,"preSum":68895},{"ndv":1,"upper":"龙门","lower":"龙门","count":495,"preSum":70729}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[2448,3484,1592,1484,2706,1558,1591,1918,2645,1873,1537,1623,2655,1543],"valueArr":["东莞城区","南海","博罗","台山","城区","廉江","惠东","惠城","普宁","清城","潮阳","禅城","顺德","高州"],"type":"String","sampleRate":0.924351804778851}',120,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_elec_cust_no',11794161,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1558,"upper":"0302000232014172","lower":"0302000000000012","count":1563,"preSum":0},{"ndv":1560,"upper":"0302100017183882","lower":"0302000232019505","count":1563,"preSum":1563},{"ndv":1561,"upper":"0304002033510049","lower":"0302100017185543","count":1563,"preSum":3126},{"ndv":1563,"upper":"0304020041754043","lower":"0304002033510503","count":1563,"preSum":4689},{"ndv":1563,"upper":"0305000990183727","lower":"0304020043095067","count":1563,"preSum":6252},{"ndv":1563,"upper":"0305002641122102","lower":"0305000990183980","count":1563,"preSum":7815},{"ndv":1563,"upper":"0305004887001301","lower":"0305002641122409","count":1563,"preSum":9378},{"ndv":1563,"upper":"0305480008238434","lower":"0305004889106601","count":1563,"preSum":10941},{"ndv":1562,"upper":"0306120139099150","lower":"0305480008308607","count":1563,"preSum":12504},{"ndv":1561,"upper":"0306140074233087","lower":"0306120139099988","count":1563,"preSum":14067},{"ndv":1563,"upper":"0307002000154016","lower":"0306140074741322","count":1563,"preSum":15630},{"ndv":1562,"upper":"0307005000756788","lower":"0307002000154550","count":1563,"preSum":17193},{"ndv":1563,"upper":"0307007000392705","lower":"0307005000757894","count":1563,"preSum":18756},{"ndv":1563,"upper":"0307050057386469","lower":"0307007000392828","count":1563,"preSum":20319},{"ndv":1563,"upper":"0308000800149001","lower":"0307050060178220","count":1563,"preSum":21882},{"ndv":1563,"upper":"0308000804292759","lower":"0308000800149026","count":1563,"preSum":23445},{"ndv":1563,"upper":"0308000805287060","lower":"0308000804292845","count":1563,"preSum":25008},{"ndv":1562,"upper":"0308100006220219","lower":"0308000805287374","count":1563,"preSum":26571},{"ndv":1561,"upper":"0309000191641916","lower":"0308100006408770","count":1563,"preSum":28134},{"ndv":1563,"upper":"0309001001612852","lower":"0309000192202608","count":1563,"preSum":29697},{"ndv":1563,"upper":"0309008001713308","lower":"0309001001613062","count":1563,"preSum":31260},{"ndv":1562,"upper":"0309020257918875","lower":"0309008001800703","count":1563,"preSum":32823},{"ndv":1559,"upper":"0312000011035929","lower":"0309020258894505","count":1563,"preSum":34386},{"ndv":1563,"upper":"0312000080236570","lower":"0312000011036078","count":1563,"preSum":35949},{"ndv":1561,"upper":"0312009900285147","lower":"0312000080236578","count":1563,"preSum":37512},{"ndv":1561,"upper":"0313000030009905","lower":"0312009900286819","count":1563,"preSum":39075},{"ndv":1562,"upper":"0313001301042355","lower":"0313000030234127","count":1563,"preSum":40638},{"ndv":1563,"upper":"0313006044024916","lower":"0313001301042573","count":1563,"preSum":42201},{"ndv":1563,"upper":"0313020007880009","lower":"0313006044025794","count":1563,"preSum":43764},{"ndv":1563,"upper":"0313030266379810","lower":"0313020008210601","count":1563,"preSum":45327},{"ndv":1559,"upper":"0313140163040325","lower":"0313030266403430","count":1563,"preSum":46890},{"ndv":1559,"upper":"0314002134006214","lower":"0313140163041894","count":1563,"preSum":48453},{"ndv":1561,"upper":"0314006014107169","lower":"0314002134006356","count":1563,"preSum":50016},{"ndv":1554,"upper":"0314070066260875","lower":"0314006014108140","count":1563,"preSum":51579},{"ndv":1559,"upper":"0315002122005539","lower":"0314070068437565","count":1563,"preSum":53142},{"ndv":1563,"upper":"0315040065448957","lower":"0315002122006330","count":1563,"preSum":54705},{"ndv":1561,"upper":"0316001623281661","lower":"0315040065483493","count":1563,"preSum":56268},{"ndv":1558,"upper":"0316260216610895","lower":"0316001623282178","count":1563,"preSum":57831},{"ndv":1562,"upper":"0317001700321201","lower":"0316260217448998","count":1563,"preSum":59394},{"ndv":1561,"upper":"0317070185588166","lower":"0317001700321364","count":1563,"preSum":60957},{"ndv":1563,"upper":"0318002302020040","lower":"0317070185588179","count":1563,"preSum":62520},{"ndv":1562,"upper":"0318009900098886","lower":"0318002302020312","count":1563,"preSum":64083},{"ndv":1563,"upper":"0318010280860569","lower":"0318009900100505","count":1563,"preSum":65646},{"ndv":1562,"upper":"0319002002153050","lower":"0318010280860716","count":1563,"preSum":67209},{"ndv":1563,"upper":"0319007000197634","lower":"0319002003095000","count":1563,"preSum":68772},{"ndv":1563,"upper":"0319009000770331","lower":"0319007000197699","count":1563,"preSum":70335},{"ndv":1562,"upper":"0319009900850758","lower":"0319009000770816","count":1563,"preSum":71898},{"ndv":1563,"upper":"0319360011292539","lower":"0319009900851457","count":1563,"preSum":73461},{"ndv":1563,"upper":"0320002002020192","lower":"0319360011346832","count":1563,"preSum":75024},{"ndv":1563,"upper":"0320005083005102","lower":"0320002002020244","count":1563,"preSum":76587},{"ndv":1563,"upper":"0320210138709543","lower":"0320005083006808","count":1563,"preSum":78150},{"ndv":1562,"upper":"0351005107306251","lower":"0320210138968675","count":1563,"preSum":79713},{"ndv":1561,"upper":"0351009800167610","lower":"0351005107306617","count":1563,"preSum":81276},{"ndv":1563,"upper":"0352003040069217","lower":"0351009800167828","count":1563,"preSum":82839},{"ndv":1563,"upper":"0352006110501769","lower":"0352003040101190","count":1563,"preSum":84402},{"ndv":1563,"upper":"0352007231304085","lower":"0352006110602611","count":1563,"preSum":85965},{"ndv":1563,"upper":"0352060024628105","lower":"0352007231404012","count":1563,"preSum":87528},{"ndv":1563,"upper":"0353000050015971","lower":"0352060024961484","count":1563,"preSum":89091},{"ndv":1563,"upper":"0353000200006086","lower":"0353000050016101","count":1563,"preSum":90654},{"ndv":1561,"upper":"061100100029429","lower":"0353000200006885","count":1563,"preSum":92217},{"ndv":1563,"upper":"062270002729743","lower":"061100100030018","count":1563,"preSum":93780},{"ndv":1563,"upper":"062970000202702","lower":"062270002730669","count":1563,"preSum":95343},{"ndv":1563,"upper":"063504080100232","lower":"062970000203093","count":1563,"preSum":96906},{"ndv":1502,"upper":"9001563970","lower":"063504080100294","count":1502,"preSum":98469}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[3,3,3,3,3,4,4,4,3],"valueArr":["0302000205005414","0302000232004398","0302000232004403","0309009900097795","0314002611000257","0314003828030009","0314005121044001","0317009800000085","0318002508010049"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_elec_sort_code',9,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1425,2259,3223,5618,84584,49,1774,133,936],"valueArr":["100","200","260","300","500","600","700","800","900"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_ele_capacity',8666,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":7,"upper":0.33,"lower":0.00,"count":246,"preSum":0},{"ndv":6,"upper":0.55,"lower":0.37,"count":436,"preSum":246},{"ndv":2,"upper":0.66,"lower":0.60,"count":203,"preSum":682},{"ndv":17,"upper":1.32,"lower":0.70,"count":217,"preSum":885},{"ndv":7,"upper":1.60,"lower":1.34,"count":233,"preSum":1102},{"ndv":20,"upper":2.50,"lower":1.62,"count":523,"preSum":1335},{"ndv":19,"upper":3.60,"lower":2.56,"count":221,"preSum":1858},{"ndv":15,"upper":4.40,"lower":3.65,"count":1140,"preSum":2079},{"ndv":31,"upper":5.90,"lower":4.42,"count":935,"preSum":3219},{"ndv":11,"upper":6.60,"lower":5.94,"count":274,"preSum":4154},{"ndv":21,"upper":9.00,"lower":6.70,"count":761,"preSum":4428},{"ndv":21,"upper":11.00,"lower":9.10,"count":346,"preSum":5189},{"ndv":17,"upper":13.00,"lower":11.10,"count":307,"preSum":5535},{"ndv":10,"upper":14.00,"lower":13.10,"count":858,"preSum":5842},{"ndv":10,"upper":16.00,"lower":14.10,"count":257,"preSum":6700},{"ndv":13,"upper":17.60,"lower":16.10,"count":219,"preSum":6957},{"ndv":2,"upper":18.00,"lower":17.65,"count":267,"preSum":7176},{"ndv":26,"upper":22.00,"lower":18.10,"count":295,"preSum":7443},{"ndv":12,"upper":25.00,"lower":22.05,"count":396,"preSum":7738},{"ndv":16,"upper":29.00,"lower":25.20,"count":220,"preSum":8134},{"ndv":6,"upper":30.00,"lower":29.04,"count":565,"preSum":8354},{"ndv":21,"upper":37.00,"lower":30.40,"count":204,"preSum":8919},{"ndv":10,"upper":40.00,"lower":37.35,"count":234,"preSum":9123},{"ndv":25,"upper":49.00,"lower":40.95,"count":234,"preSum":9357},{"ndv":5,"upper":50.00,"lower":49.36,"count":285,"preSum":9591},{"ndv":30,"upper":70.00,"lower":51.00,"count":226,"preSum":9876},{"ndv":16,"upper":85.00,"lower":71.00,"count":207,"preSum":10102},{"ndv":16,"upper":100.00,"lower":86.00,"count":308,"preSum":10309},{"ndv":31,"upper":190.00,"lower":100.44,"count":201,"preSum":10617},{"ndv":8,"upper":215.00,"lower":195.00,"count":201,"preSum":10818},{"ndv":5,"upper":250.00,"lower":225.00,"count":245,"preSum":11019},{"ndv":11,"upper":315.00,"lower":256.00,"count":224,"preSum":11264},{"ndv":16,"upper":500.00,"lower":320.00,"count":387,"preSum":11488},{"ndv":10,"upper":630.00,"lower":515.00,"count":247,"preSum":11875},{"ndv":10,"upper":800.00,"lower":640.00,"count":210,"preSum":12122},{"ndv":23,"upper":1430.00,"lower":815.00,"count":208,"preSum":12332},{"ndv":61,"upper":4200.00,"lower":1494.00,"count":201,"preSum":12540},{"ndv":64,"upper":999999.00,"lower":4250.00,"count":108,"preSum":12741}],"maxBucketSize":64,"type":"Double","sampleRate":0.9243518}','{"countArr":[4715,3858,8455,2724,4841,17248,8989,15989,1074,9156,4953,1142,1665,1198],"valueArr":[1.00,1.10,2.00,2.20,3.00,4.00,5.00,6.00,7.00,8.00,10.00,12.00,15.00,20.00],"type":"Double","sampleRate":0.924351804778851}',1145,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_er_type',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_grid_pq_mr_direction',30,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"321","lower":"321","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[434,176,99],"valueArr":["1","121","221"],"type":"String","sampleRate":0.924351804778851}',99291,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_main_and_assist_flag',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_metering_point_number',12165112,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1559,"upper":"03020003190000901","lower":"03020000000000122","count":1563,"preSum":0},{"ndv":1563,"upper":"03040020256382201","lower":"03020003190190871","count":1563,"preSum":1563},{"ndv":1563,"upper":"03050009101630911","lower":"03040020257130401","count":1563,"preSum":3126},{"ndv":1563,"upper":"03050026311067921","lower":"03050009101729611","count":1563,"preSum":4689},{"ndv":1563,"upper":"03050047455057041","lower":"03050026311073591","count":1563,"preSum":6252},{"ndv":1563,"upper":"03070007830287501","lower":"03050047456030011","count":1563,"preSum":7815},{"ndv":1563,"upper":"03070050000809261","lower":"03070007830291841","count":1563,"preSum":9378},{"ndv":1563,"upper":"03070070001636031","lower":"03070050000815031","count":1563,"preSum":10941},{"ndv":1563,"upper":"03080008002027211","lower":"03070070001636511","count":1563,"preSum":12504},{"ndv":1563,"upper":"03080008043304461","lower":"03080008002027831","count":1563,"preSum":14067},{"ndv":1563,"upper":"03080008053906851","lower":"03080008043305061","count":1563,"preSum":15630},{"ndv":1563,"upper":"03090010001078471","lower":"03080008053910311","count":1563,"preSum":17193},{"ndv":1563,"upper":"03090050073365601","lower":"03090010001091111","count":1563,"preSum":18756},{"ndv":1563,"upper":"03090080033032141","lower":"03090050081161401","count":1563,"preSum":20319},{"ndv":1563,"upper":"03120000090063791","lower":"03090080033040891","count":1563,"preSum":21882},{"ndv":1563,"upper":"03120000802291951","lower":"03120000090073641","count":1563,"preSum":23445},{"ndv":1563,"upper":"03120099003105581","lower":"03120000802292731","count":1563,"preSum":25008},{"ndv":1562,"upper":"03130013010269251","lower":"03120099003105721","count":1563,"preSum":26571},{"ndv":1563,"upper":"03130060440068641","lower":"03130013010271731","count":1563,"preSum":28134},{"ndv":1563,"upper":"03140011010963341","lower":"03130060440068991","count":1563,"preSum":29697},{"ndv":1558,"upper":"03140051130100361","lower":"03140011010964301","count":1563,"preSum":31260},{"ndv":1561,"upper":"03140081285100511","lower":"03140051130100761","count":1563,"preSum":32823},{"ndv":1563,"upper":"03150081130090551","lower":"03140081285200011","count":1563,"preSum":34386},{"ndv":1563,"upper":"03160016227812031","lower":"03150081130090621","count":1563,"preSum":35949},{"ndv":1563,"upper":"03170011281481981","lower":"03160016227818021","count":1563,"preSum":37512},{"ndv":1561,"upper":"03170099994523211","lower":"03170011281488171","count":1563,"preSum":39075},{"ndv":1563,"upper":"03180024030107061","lower":"03170099994533631","count":1563,"preSum":40638},{"ndv":1562,"upper":"03180099009023551","lower":"03180024030108181","count":1563,"preSum":42201},{"ndv":1563,"upper":"03190065003722601","lower":"03180099009039931","count":1563,"preSum":43764},{"ndv":1563,"upper":"03190084000962211","lower":"03190065003722701","count":1563,"preSum":45327},{"ndv":1563,"upper":"03190099004594591","lower":"03190084000971271","count":1563,"preSum":46890},{"ndv":1563,"upper":"03200020023351731","lower":"03190099004603371","count":1563,"preSum":48453},{"ndv":1563,"upper":"03200099001361061","lower":"03200020023365231","count":1563,"preSum":50016},{"ndv":1563,"upper":"03510051074760191","lower":"03200099001376541","count":1563,"preSum":51579},{"ndv":1563,"upper":"03518830541020031","lower":"03510051074769451","count":1563,"preSum":53142},{"ndv":1563,"upper":"03520050722001321","lower":"03518830542154021","count":1563,"preSum":54705},{"ndv":1563,"upper":"03520071504013791","lower":"03520050726000231","count":1563,"preSum":56268},{"ndv":1563,"upper":"03530000000280241","lower":"03520071505001451","count":1563,"preSum":57831},{"ndv":1563,"upper":"03530000505464491","lower":"03530000000280951","count":1563,"preSum":59394},{"ndv":1563,"upper":"0611200020113711","lower":"03530000505465881","count":1563,"preSum":60957},{"ndv":1563,"upper":"0623500012741701","lower":"0611200020113981","count":1563,"preSum":62520},{"ndv":1563,"upper":"0634369364008201","lower":"0623500012746601","count":1563,"preSum":64083},{"ndv":1563,"upper":"0646200001686821","lower":"0634369365091601","count":1563,"preSum":65646},{"ndv":1563,"upper":"110789310","lower":"0646200001691721","count":1563,"preSum":67209},{"ndv":1563,"upper":"1111111112824386","lower":"110806547","count":1563,"preSum":68772},{"ndv":1563,"upper":"1111111114060132","lower":"1111111112824586","count":1563,"preSum":70335},{"ndv":1563,"upper":"1111111115043566","lower":"1111111114060154","count":1563,"preSum":71898},{"ndv":1562,"upper":"1111111115995581","lower":"1111111115043957","count":1563,"preSum":73461},{"ndv":1562,"upper":"1111111117000703","lower":"1111111115996277","count":1563,"preSum":75024},{"ndv":1563,"upper":"1111111118164114","lower":"1111111117000761","count":1563,"preSum":76587},{"ndv":1561,"upper":"1111111119076181","lower":"1111111118164885","count":1563,"preSum":78150},{"ndv":1556,"upper":"1111111126552878","lower":"1111111119077163","count":1563,"preSum":79713},{"ndv":1559,"upper":"1111111127741046","lower":"1111111126553340","count":1563,"preSum":81276},{"ndv":1562,"upper":"1111111129078317","lower":"1111111127741535","count":1563,"preSum":82839},{"ndv":1563,"upper":"1111111130440571","lower":"1111111129080725","count":1563,"preSum":84402},{"ndv":1562,"upper":"1111111131684624","lower":"1111111130441147","count":1563,"preSum":85965},{"ndv":1562,"upper":"1111111132829285","lower":"1111111131686288","count":1563,"preSum":87528},{"ndv":1563,"upper":"17412910","lower":"1111111132830839","count":1563,"preSum":89091},{"ndv":1559,"upper":"2111111135012008","lower":"17412946","count":1563,"preSum":90654},{"ndv":1559,"upper":"2111111136724271","lower":"2111111135012883","count":1563,"preSum":92217},{"ndv":1549,"upper":"2111111138478409","lower":"2111111136724280","count":1563,"preSum":93780},{"ndv":1557,"upper":"44902505","lower":"2111111138479285","count":1563,"preSum":95343},{"ndv":1563,"upper":"71184627","lower":"44951701","count":1563,"preSum":96906},{"ndv":1532,"upper":"99968788","lower":"71247384","count":1532,"preSum":98469}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_mp_status_code',29,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"3","lower":"3","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[99866,127],"valueArr":["1","2"],"type":"String","sampleRate":0.924351804778851}',7,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_mr_equ_sort_code',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_mr_mode_code',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"03","lower":"03","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1083,1634,97282],"valueArr":["1","2","3"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_mr_volt_code',40,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"01","lower":"01","count":2,"preSum":0},{"ndv":1,"upper":"14","lower":"14","count":2,"preSum":2},{"ndv":1,"upper":"20","lower":"20","count":1,"preSum":4},{"ndv":1,"upper":"3","lower":"3","count":2,"preSum":5},{"ndv":1,"upper":"33","lower":"33","count":2,"preSum":7}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[86917,11001,4,1900,13,14,13,8,78],"valueArr":["02","03","04","08","09","10","12","13","29"],"type":"String","sampleRate":0.924351804778851}',44,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_name',5215,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":30,"upper":"严脱敏","lower":" 脱敏","count":336,"preSum":0},{"ndv":28,"upper":"伍脱敏","lower":"丰脱敏","count":359,"preSum":336},{"ndv":6,"upper":"何脱敏","lower":"伟脱敏","count":530,"preSum":695},{"ndv":8,"upper":"俞脱敏","lower":"佘脱敏","count":299,"preSum":1225},{"ndv":22,"upper":"冯脱敏","lower":"信脱敏","count":446,"preSum":1524},{"ndv":23,"upper":"南脱敏","lower":"冲脱敏","count":340,"preSum":1970},{"ndv":14,"upper":"发脱敏","lower":"博脱敏","count":301,"preSum":2310},{"ndv":5,"upper":"叶脱敏","lower":"叙脱敏","count":444,"preSum":2611},{"ndv":10,"upper":"周脱敏","lower":"司脱敏","count":521,"preSum":3055},{"ndv":33,"upper":"始脱敏","lower":"和脱敏","count":302,"preSum":3576},{"ndv":14,"upper":"宋脱敏","lower":"姚脱敏","count":335,"preSum":3878},{"ndv":39,"upper":"差脱敏","lower":"宏脱敏","count":298,"preSum":4213},{"ndv":19,"upper":"廖脱敏","lower":"巴脱敏","count":476,"preSum":4511},{"ndv":5,"upper":"徐脱敏","lower":"建脱敏","count":477,"preSum":4987},{"ndv":21,"upper":"揭脱敏","lower":"御脱敏","count":326,"preSum":5464},{"ndv":21,"upper":"易脱敏","lower":"摩脱敏","count":330,"preSum":5790},{"ndv":11,"upper":"曾脱敏","lower":"星脱敏","count":500,"preSum":6120},{"ndv":3,"upper":"朱脱敏","lower":"有脱敏","count":309,"preSum":6620},{"ndv":3,"upper":"杨脱敏","lower":"朴脱敏","count":701,"preSum":6929},{"ndv":22,"upper":"横脱敏","lower":"松脱敏","count":298,"preSum":7630},{"ndv":14,"upper":"汕脱敏","lower":"欣脱敏","count":472,"preSum":7928},{"ndv":1,"upper":"江脱敏","lower":"江脱敏","count":334,"preSum":8400},{"ndv":17,"upper":"海脱敏","lower":"池脱敏","count":318,"preSum":8734},{"ndv":10,"upper":"温脱敏","lower":"涂脱敏","count":362,"preSum":9052},{"ndv":13,"upper":"潮脱敏","lower":"港脱敏","count":309,"preSum":9414},{"ndv":19,"upper":"王脱敏","lower":"澄脱敏","count":724,"preSum":9723},{"ndv":3,"upper":"珠脱敏","lower":"现脱敏","count":382,"preSum":10447},{"ndv":34,"upper":"秦脱敏","lower":"班脱敏","count":304,"preSum":10829},{"ndv":27,"upper":"罗脱敏","lower":"程脱敏","count":722,"preSum":11133},{"ndv":11,"upper":"肖脱敏","lower":"美脱敏","count":373,"preSum":11855},{"ndv":16,"upper":"花脱敏","lower":"育脱敏","count":301,"preSum":12228},{"ndv":5,"upper":"茂脱敏","lower":"苏脱敏","count":331,"preSum":12529},{"ndv":9,"upper":"董脱敏","lower":"范脱敏","count":323,"preSum":12860},{"ndv":6,"upper":"蔡脱敏","lower":"蒂脱敏","count":409,"preSum":13183},{"ndv":21,"upper":"许脱敏","lower":"蔺脱敏","count":520,"preSum":13592},{"ndv":5,"upper":"谢脱敏","lower":"诸脱敏","count":433,"preSum":14112},{"ndv":9,"upper":"赖脱敏","lower":"谭脱敏","count":447,"preSum":14545},{"ndv":14,"upper":"通脱敏","lower":"赵脱敏","count":298,"preSum":14992},{"ndv":7,"upper":"邓脱敏","lower":"速脱敏","count":370,"preSum":15290},{"ndv":7,"upper":"邹脱敏","lower":"邝脱敏","count":348,"preSum":15660},{"ndv":4,"upper":"郑脱敏","lower":"郁脱敏","count":439,"preSum":16008},{"ndv":11,"upper":"钟脱敏","lower":"郝脱敏","count":655,"preSum":16447},{"ndv":22,"upper":"阳脱敏","lower":"钢脱敏","count":371,"preSum":17102},{"ndv":17,"upper":"韦脱敏","lower":"阿脱敏","count":316,"preSum":17473},{"ndv":12,"upper":"马脱敏","lower":"韩脱敏","count":397,"preSum":17789},{"ndv":12,"upper":"鹤脱敏","lower":"骆脱敏","count":348,"preSum":18186},{"ndv":5,"upper":"黎脱敏","lower":"鹿脱敏","count":335,"preSum":18534},{"ndv":6,"upper":"?脱敏","lower":"默脱敏","count":158,"preSum":18869}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[63729,697,750,926,1080,748,3997,1157,844,1560,875,771,2270,1570],"valueArr":["0脱敏","东脱敏","中脱敏","佛脱敏","刘脱敏","吴脱敏","广脱敏","张脱敏","惠脱敏","李脱敏","林脱敏","梁脱敏","陈脱敏","黄脱敏"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_position_code',6,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[15,13,49,331,18,69786],"valueArr":["01","02","03","05","1","2"],"type":"String","sampleRate":0.924351804778851}',29789,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_price_code',1492,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"1","lower":"03","count":190,"preSum":0},{"ndv":7,"upper":"10551864","lower":"10010517","count":52,"preSum":190},{"ndv":31,"upper":"11091875","lower":"10556863","count":48,"preSum":242},{"ndv":16,"upper":"11451867","lower":"11281867","count":50,"preSum":290},{"ndv":14,"upper":"11866870","lower":"11451868","count":55,"preSum":340},{"ndv":21,"upper":"12391867","lower":"11966867","count":51,"preSum":395},{"ndv":6,"upper":"31002003","lower":"12496873","count":119,"preSum":446},{"ndv":3,"upper":"31002016","lower":"31002012","count":107,"preSum":565},{"ndv":6,"upper":"31002083","lower":"31002020","count":50,"preSum":672},{"ndv":1,"upper":"31002085","lower":"31002085","count":204,"preSum":722},{"ndv":2,"upper":"31002099","lower":"31002096","count":51,"preSum":926},{"ndv":10,"upper":"32001011","lower":"31002203","count":70,"preSum":977},{"ndv":3,"upper":"32001021","lower":"32001015","count":66,"preSum":1047},{"ndv":3,"upper":"32001099","lower":"32001042","count":50,"preSum":1113},{"ndv":1,"upper":"32002002","lower":"32002002","count":131,"preSum":1163},{"ndv":10,"upper":"32004004","lower":"32002003","count":59,"preSum":1294},{"ndv":2,"upper":"32601001","lower":"32101004","count":103,"preSum":1353},{"ndv":2,"upper":"32601009","lower":"32601003","count":120,"preSum":1456},{"ndv":1,"upper":"32601013","lower":"32601013","count":48,"preSum":1576},{"ndv":5,"upper":"32602004","lower":"32601037","count":75,"preSum":1624},{"ndv":3,"upper":"32602010","lower":"32602006","count":97,"preSum":1699},{"ndv":13,"upper":"33001008","lower":"32602013","count":242,"preSum":1796},{"ndv":1,"upper":"33002001","lower":"33002001","count":214,"preSum":2038},{"ndv":7,"upper":"35001005","lower":"33002003","count":50,"preSum":2252},{"ndv":2,"upper":"35001007","lower":"35001006","count":182,"preSum":2302},{"ndv":7,"upper":"35002001","lower":"35001008","count":51,"preSum":2484},{"ndv":2,"upper":"36001002","lower":"35002002","count":139,"preSum":2535},{"ndv":4,"upper":"37001002","lower":"36001007","count":91,"preSum":2674},{"ndv":3,"upper":"37002101","lower":"37002001","count":91,"preSum":2765},{"ndv":1,"upper":"38001001","lower":"38001001","count":110,"preSum":2856},{"ndv":15,"upper":"39003416","lower":"38001002","count":48,"preSum":2966},{"ndv":2,"upper":"39004086","lower":"39004081","count":7,"preSum":3014}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[925,698,315,1704,1059,338,546,679,5025,79865,3389,361,489,1587],"valueArr":["00000000","31002001","31002002","32001001","32001002","32002001","32601005","32601010","33001001","35001001","35001002","35001016","36001001","37001001"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_pt_ratio_code',92,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"09","lower":"09","count":1,"preSum":0},{"ndv":1,"upper":"13","lower":"13","count":1,"preSum":1},{"ndv":1,"upper":"16","lower":"16","count":1,"preSum":2},{"ndv":1,"upper":"25","lower":"25","count":1,"preSum":3}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[978,11,8,58,6,5],"valueArr":["02","05","08","11","12","15"],"type":"String","sampleRate":0.924351804778851}',98931,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_run_date',443668,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":89,"upper":"1821522430829527040","lower":"1739490067304415232","count":727,"preSum":0},{"ndv":294,"upper":"1825300352782565376","lower":"1821573008364404736","count":728,"preSum":727},{"ndv":383,"upper":"1827868811945050112","lower":"1825306949852332032","count":727,"preSum":1455},{"ndv":242,"upper":"1828930940177481728","lower":"1827871010968305664","count":728,"preSum":2182},{"ndv":111,"upper":"1829225609293725696","lower":"1828933139200737280","count":727,"preSum":2910},{"ndv":123,"upper":"1829511482316947456","lower":"1829227808316981248","count":727,"preSum":3637},{"ndv":155,"upper":"1829977675247124480","lower":"1829513681340203008","count":879,"preSum":4364},{"ndv":201,"upper":"1830428475014512640","lower":"1829978862017052672","count":746,"preSum":5243},{"ndv":190,"upper":"1830980429851656192","lower":"1830434883911024640","count":727,"preSum":5989},{"ndv":258,"upper":"1831556573944610816","lower":"1830982628874911744","count":800,"preSum":6716},{"ndv":153,"upper":"1831934805944565760","lower":"1831560971991121920","count":726,"preSum":7516},{"ndv":161,"upper":"1832273455525920768","lower":"1831937004967821312","count":734,"preSum":8242},{"ndv":132,"upper":"1832631896316575744","lower":"1832275654549176320","count":726,"preSum":8976},{"ndv":155,"upper":"1832950754688630784","lower":"1832634095339831296","count":732,"preSum":9702},{"ndv":180,"upper":"1833245423804874752","lower":"1832952107016126464","count":763,"preSum":10434},{"ndv":252,"upper":"1833723950304067584","lower":"1833320190595563520","count":726,"preSum":11197},{"ndv":308,"upper":"1834070057525706752","lower":"1833726368169328640","count":726,"preSum":11923},{"ndv":278,"upper":"1834470279758217216","lower":"1834071761822416896","count":726,"preSum":12649},{"ndv":156,"upper":"1834650599665172480","lower":"1834471981504790528","count":727,"preSum":13375},{"ndv":260,"upper":"1834993647293038592","lower":"1834658476551307264","count":726,"preSum":14102},{"ndv":187,"upper":"1835151770809008128","lower":"1834995846316294144","count":728,"preSum":14828},{"ndv":117,"upper":"1835158642756681728","lower":"1835151839528484864","count":728,"preSum":15556},{"ndv":340,"upper":"1835415859758104576","lower":"1835158711476158464","count":726,"preSum":16284},{"ndv":260,"upper":"1835655553292959744","lower":"1835418058781360128","count":734,"preSum":17010},{"ndv":349,"upper":"1835856982460858368","lower":"1835657752316215296","count":726,"preSum":17744},{"ndv":369,"upper":"1836194313990569984","lower":"1835857318693044224","count":737,"preSum":18470},{"ndv":470,"upper":"1836528565525413888","lower":"1836204380722823168","count":727,"preSum":19207},{"ndv":354,"upper":"1836763616620052480","lower":"1836530764548669440","count":726,"preSum":19934},{"ndv":508,"upper":"1837027280417718272","lower":"1836763708542418944","count":726,"preSum":20660},{"ndv":461,"upper":"1837350404061396992","lower":"1837027458272985088","count":726,"preSum":21386},{"ndv":175,"upper":"1837526922083434496","lower":"1837351000222990336","count":726,"preSum":22112},{"ndv":187,"upper":"1837700644920623104","lower":"1837528183126097920","count":727,"preSum":22838},{"ndv":150,"upper":"1837810596083400704","lower":"1837701908463091712","count":797,"preSum":23565},{"ndv":74,"upper":"1837920617056174080","lower":"1837812795106656256","count":864,"preSum":24362},{"ndv":128,"upper":"1837988786777096192","lower":"1837921707357110272","count":755,"preSum":25226},{"ndv":127,"upper":"1838056886688022528","lower":"1837989942928605184","count":738,"preSum":25981},{"ndv":389,"upper":"1838309774362411008","lower":"1838056956498018304","count":729,"preSum":26719},{"ndv":374,"upper":"1838583650132688896","lower":"1838315494822641664","count":726,"preSum":27448},{"ndv":117,"upper":"1838661618083299328","lower":"1838583698467848192","count":1099,"preSum":28174},{"ndv":370,"upper":"1838970713172606976","lower":"1838667175099891712","count":726,"preSum":29273},{"ndv":323,"upper":"1839160358544080896","lower":"1838970764477333504","count":726,"preSum":29999},{"ndv":11,"upper":"1839165194408820736","lower":"1839160363828903936","count":742,"preSum":30725},{"ndv":343,"upper":"1839347713339031552","lower":"1839166330998095872","count":726,"preSum":31467},{"ndv":341,"upper":"1839522880526745600","lower":"1839348850683281408","count":726,"preSum":32193},{"ndv":313,"upper":"1839646780501786624","lower":"1839523635199475712","count":760,"preSum":32919},{"ndv":391,"upper":"1839928070056706048","lower":"1839647978931879936","count":726,"preSum":33679},{"ndv":344,"upper":"1840062395897085952","lower":"1839928070207700992","count":730,"preSum":34405},{"ndv":381,"upper":"1840269104083107840","lower":"1840064030467686400","count":727,"preSum":35135},{"ndv":585,"upper":"1840644820876394496","lower":"1840270224146825216","count":726,"preSum":35862},{"ndv":608,"upper":"1840937006310359040","lower":"1840644889679757312","count":726,"preSum":36588},{"ndv":626,"upper":"1841163551054495744","lower":"1840937094273302528","count":726,"preSum":37314},{"ndv":637,"upper":"1841368125614850048","lower":"1841163569425547264","count":726,"preSum":38040},{"ndv":627,"upper":"1841633817610158080","lower":"1841368126420156416","count":726,"preSum":38766},{"ndv":471,"upper":"1841869389654130688","lower":"1841633831031930880","count":726,"preSum":39492},{"ndv":513,"upper":"1842089407893471232","lower":"1841869466980319232","count":726,"preSum":40218},{"ndv":475,"upper":"1842309797664260096","lower":"1842089442404204544","count":726,"preSum":40944},{"ndv":459,"upper":"1842566060260196352","lower":"1842310939840348160","count":726,"preSum":41670},{"ndv":478,"upper":"1842810503877885952","lower":"1842566107353841664","count":726,"preSum":42396},{"ndv":482,"upper":"1843021746173640704","lower":"1842810586790887424","count":727,"preSum":43122},{"ndv":502,"upper":"1843264105037692928","lower":"1843021749763964928","count":726,"preSum":43849},{"ndv":481,"upper":"1843528056547835904","lower":"1843264173757169664","count":730,"preSum":44575},{"ndv":462,"upper":"1843797506522087424","lower":"1843529408975994880","count":726,"preSum":45305},{"ndv":263,"upper":"1920814927887466496","lower":"1843797507830710272","count":375,"preSum":46031}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.9243518}','{"countArr":[31708,2341,976,3368,1715,1448,1427,2528,636,1534,1915,1971,724,1304],"valueArr":[-1,1738106881676673024,1783633260136366080,1820438312364539904,1829586249107636224,1829737981712269312,1830287737526157312,1831596156363210752,1834282937898500096,1836904598502113280,1837606086920634368,1837746824408989696,1837819392176422912,1839156398315798528],"type":"Datetime","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_supply_org_name',1319,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":11,"upper":"三埠供电所","lower":"丁堡供电所","count":1430,"preSum":0},{"ndv":24,"upper":"东区供电分局","lower":"三排供电所","count":1630,"preSum":1430},{"ndv":17,"upper":"东简供电所","lower":"东升供电分局","count":1457,"preSum":3060},{"ndv":10,"upper":"丰城供电所","lower":"东里供电所","count":1393,"preSum":4517},{"ndv":17,"upper":"乐平供电所","lower":"丰稔供电所","count":1559,"preSum":5910},{"ndv":23,"upper":"云潭供电所","lower":"乐民供电所","count":1419,"preSum":7469},{"ndv":19,"upper":"会城供电所","lower":"云澳供电所","count":1804,"preSum":8888},{"ndv":22,"upper":"兴城供电所","lower":"伦教供电所","count":1523,"preSum":10692},{"ndv":13,"upper":"前山营业所","lower":"兴宁大坪供电所","count":1755,"preSum":12215},{"ndv":9,"upper":"十里亭供电所","lower":"前詹供电所","count":1434,"preSum":13970},{"ndv":12,"upper":"南头供电分局","lower":"华侨供电所","count":1480,"preSum":15404},{"ndv":7,"upper":"南水供电所","lower":"南屏供电所","count":1427,"preSum":16884},{"ndv":13,"upper":"厚街供电服务中心","lower":"南海供电局","count":1623,"preSum":18311},{"ndv":24,"upper":"同庆供电所","lower":"双华供电所","count":1394,"preSum":19934},{"ndv":24,"upper":"坑口中心供电所(广宁)","lower":"后宅供电所","count":1406,"preSum":21328},{"ndv":13,"upper":"城南供电所","lower":"坝仔供电所","count":1705,"preSum":22734},{"ndv":18,"upper":"大坡供电所","lower":"城口供电所","count":1397,"preSum":24439},{"ndv":11,"upper":"大朗供电服务中心","lower":"大坪供电所","count":1584,"preSum":25836},{"ndv":19,"upper":"太和供电所","lower":"大柘供电所","count":1557,"preSum":27420},{"ndv":14,"upper":"客路供电所","lower":"太平供电所","count":1399,"preSum":28977},{"ndv":20,"upper":"常平供电服务中心","lower":"寨岗大麦山供电所","count":1511,"preSum":30376},{"ndv":15,"upper":"开发区供电所","lower":"平冈供电所","count":1617,"preSum":31887},{"ndv":14,"upper":"拱北营业所","lower":"彭寨供电所","count":1497,"preSum":33504},{"ndv":16,"upper":"新兴新城供电所","lower":"振文供电所","count":1429,"preSum":35001},{"ndv":21,"upper":"明城供电所","lower":"新兴水台供电所","count":1476,"preSum":36430},{"ndv":18,"upper":"杏坛供电所","lower":"星子供电所","count":1483,"preSum":37906},{"ndv":21,"upper":"柏塘供电所","lower":"杜步供电所","count":1392,"preSum":39389},{"ndv":21,"upper":"棉北供电所","lower":"树仔供电所","count":1412,"preSum":40781},{"ndv":10,"upper":"横沥供电服务中心","lower":"棉洋供电所","count":1569,"preSum":42193},{"ndv":14,"upper":"水步供电所","lower":"横河供电所","count":1475,"preSum":43762},{"ndv":15,"upper":"江海直管","lower":"水车供电所","count":1525,"preSum":45237},{"ndv":17,"upper":"沙扒供电所","lower":"江湖供电所","count":1405,"preSum":46762},{"ndv":14,"upper":"河唇供电所","lower":"沙浦供电所","count":1556,"preSum":48167},{"ndv":20,"upper":"流沙东供电所","lower":"河头供电所","count":1507,"preSum":49723},{"ndv":11,"upper":"海陵岛供电服务中心","lower":"流沙北供电所","count":1400,"preSum":51230},{"ndv":14,"upper":"湘桥供电局","lower":"浸潭供电所","count":1829,"preSum":52630},{"ndv":24,"upper":"潮安沙溪供电所","lower":"湘桥意溪供电所","count":1404,"preSum":54459},{"ndv":14,"upper":"濠广供电所","lower":"潮安浮洋供电所","count":1434,"preSum":55863},{"ndv":12,"upper":"王村港供电所","lower":"濠滨供电所","count":1397,"preSum":57297},{"ndv":24,"upper":"白蕉供电所","lower":"珠海供电局","count":1700,"preSum":58694},{"ndv":14,"upper":"石望供电所","lower":"白诸中心供电所","count":1438,"preSum":60394},{"ndv":15,"upper":"碣石供电所","lower":"石板供电所","count":1405,"preSum":61832},{"ndv":15,"upper":"紫市供电所","lower":"磐东供电所","count":1396,"preSum":63237},{"ndv":25,"upper":"罗定罗平供电所","lower":"紫金供电局","count":1413,"preSum":64633},{"ndv":14,"upper":"老隆供电所","lower":"罗定罗镜供电所","count":1458,"preSum":66046},{"ndv":19,"upper":"草潭供电所","lower":"联安供电所","count":1411,"preSum":67504},{"ndv":12,"upper":"营业部","lower":"荷城供电所","count":1439,"preSum":68915},{"ndv":11,"upper":"螺溪供电所","lower":"营仔供电所","count":1428,"preSum":70354},{"ndv":11,"upper":"覃巴供电所","lower":"袂花供电所","count":1398,"preSum":71782},{"ndv":26,"upper":"连江口供电所","lower":"覃斗供电所","count":1403,"preSum":73180},{"ndv":26,"upper":"里水供电所","lower":"迳头供电所","count":1570,"preSum":74583},{"ndv":24,"upper":"锡场供电所","lower":"里湖供电所","count":1417,"preSum":76153},{"ndv":12,"upper":"长沙供电所","lower":"锦和供电所","count":1392,"preSum":77570},{"ndv":14,"upper":"陈村供电所","lower":"长潭供电所","count":1505,"preSum":78962},{"ndv":24,"upper":"饶平三饶供电所","lower":"陈江供电所","count":1414,"preSum":80467},{"ndv":19,"upper":"香洲营业所","lower":"饶平上饶供电所","count":1436,"preSum":81881},{"ndv":18,"upper":"高潭供电所","lower":"马冈供电所","count":1409,"preSum":83317},{"ndv":22,"upper":"黄岗中心供电所","lower":"高莞供电所","count":1727,"preSum":84726},{"ndv":19,"upper":"龙塘供电所","lower":"黄岭供电所","count":1446,"preSum":86453},{"ndv":16,"upper":"龙颈供电所","lower":"龙头供电所","count":1139,"preSum":87899}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[566,579,554,1831,1149,715,790,555,674,646,643,721,672,868],"valueArr":["东城中心供电所","东城供电所","台城营业所","城区供电所","城区供电服务中心","城郊供电所","大沥供电所","容桂供电所","桂城供电所","江南供电所","海滨供电所","淡水供电所","西区供电所","西南供电所"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_supply_org_no',1449,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":28,"upper":"03021011","lower":"030202","count":1650,"preSum":0},{"ndv":21,"upper":"03021507","lower":"03021012","count":1430,"preSum":1650},{"ndv":22,"upper":"03040105","lower":"03021509","count":1437,"preSum":3080},{"ndv":9,"upper":"03040304","lower":"03040106","count":1480,"preSum":4517},{"ndv":10,"upper":"03052308","lower":"03040306","count":1406,"preSum":5997},{"ndv":14,"upper":"03054709","lower":"03052603","count":1519,"preSum":7403},{"ndv":14,"upper":"03054812","lower":"03054710","count":1414,"preSum":8922},{"ndv":12,"upper":"03054910","lower":"03054813","count":1475,"preSum":10336},{"ndv":11,"upper":"03061213","lower":"03054911","count":1580,"preSum":11811},{"ndv":5,"upper":"03061311","lower":"03061214","count":1714,"preSum":13391},{"ndv":7,"upper":"03061318","lower":"03061312","count":1533,"preSum":15105},{"ndv":16,"upper":"03070207","lower":"03061319","count":1456,"preSum":16638},{"ndv":13,"upper":"03070408","lower":"03070211","count":1440,"preSum":18094},{"ndv":25,"upper":"03070614","lower":"03070410","count":1463,"preSum":19534},{"ndv":18,"upper":"03071316","lower":"03070615","count":1446,"preSum":20997},{"ndv":7,"upper":"03080105","lower":"030714","count":1488,"preSum":22443},{"ndv":18,"upper":"03081015","lower":"03080106","count":1424,"preSum":23931},{"ndv":21,"upper":"03081415","lower":"03081016","count":1505,"preSum":25355},{"ndv":21,"upper":"03082032","lower":"03081417","count":1409,"preSum":26860},{"ndv":18,"upper":"03082825","lower":"03082033","count":1442,"preSum":28269},{"ndv":23,"upper":"03090256","lower":"03083004","count":1426,"preSum":29711},{"ndv":25,"upper":"03090902","lower":"03090257","count":1464,"preSum":31137},{"ndv":21,"upper":"03091006","lower":"03090903","count":1537,"preSum":32601},{"ndv":23,"upper":"03091612","lower":"03091017","count":1460,"preSum":34138},{"ndv":14,"upper":"03120305","lower":"03091613","count":1504,"preSum":35598},{"ndv":15,"upper":"03120607","lower":"03120308","count":1780,"preSum":37102},{"ndv":21,"upper":"03130202","lower":"03120907","count":1445,"preSum":38882},{"ndv":7,"upper":"03130223","lower":"03130210","count":1453,"preSum":40327},{"ndv":15,"upper":"03130415","lower":"03130225","count":1826,"preSum":41780},{"ndv":20,"upper":"03131312","lower":"03130418","count":1507,"preSum":43606},{"ndv":20,"upper":"03131423","lower":"03131317","count":1751,"preSum":45113},{"ndv":14,"upper":"03140117","lower":"03131602","count":1419,"preSum":46864},{"ndv":26,"upper":"03140617","lower":"03140118","count":1447,"preSum":48283},{"ndv":35,"upper":"03141009","lower":"03140619","count":1525,"preSum":49730},{"ndv":27,"upper":"03150219","lower":"03141010","count":1442,"preSum":51255},{"ndv":29,"upper":"03150420","lower":"03150221","count":1633,"preSum":52697},{"ndv":27,"upper":"03160922","lower":"03151003","count":1449,"preSum":54330},{"ndv":49,"upper":"03162614","lower":"03160923","count":1427,"preSum":55779},{"ndv":20,"upper":"03170430","lower":"03163302","count":1765,"preSum":57206},{"ndv":22,"upper":"03171015","lower":"03170507","count":1407,"preSum":58971},{"ndv":9,"upper":"03180107","lower":"03171016","count":1705,"preSum":60378},{"ndv":22,"upper":"03182601","lower":"03180108","count":1448,"preSum":62083},{"ndv":25,"upper":"03188116","lower":"03182602","count":1482,"preSum":63531},{"ndv":22,"upper":"03196906","lower":"03188117","count":1636,"preSum":65013},{"ndv":6,"upper":"03197111","lower":"03196914","count":1518,"preSum":66649},{"ndv":11,"upper":"03197309","lower":"03197112","count":1447,"preSum":68167},{"ndv":5,"upper":"03197506","lower":"03197310","count":1773,"preSum":69614},{"ndv":5,"upper":"032014","lower":"03197507","count":1629,"preSum":71387},{"ndv":6,"upper":"032020","lower":"032015","count":1503,"preSum":73016},{"ndv":9,"upper":"032029","lower":"032021","count":1556,"preSum":74519},{"ndv":24,"upper":"03510525","lower":"032030","count":1413,"preSum":76075},{"ndv":16,"upper":"03510917","lower":"03510526","count":1467,"preSum":77488},{"ndv":12,"upper":"03520218","lower":"03510918","count":1671,"preSum":78955},{"ndv":16,"upper":"03520316","lower":"03520224","count":1542,"preSum":80626},{"ndv":15,"upper":"03520619","lower":"03520603","count":1519,"preSum":82168},{"ndv":14,"upper":"03520707","lower":"03520620","count":1461,"preSum":83687},{"ndv":24,"upper":"03521519","lower":"03520709","count":1509,"preSum":85148},{"ndv":24,"upper":"03530423","lower":"03521524","count":1420,"preSum":86657},{"ndv":33,"upper":"03531318","lower":"03530424","count":1443,"preSum":88077},{"ndv":6,"upper":"03531324","lower":"03531319","count":238,"preSum":89520}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[643,1259,790,674,555,868,506,554,572,566,671,721,715,1149],"valueArr":["03052307","03060306","03061211","03061218","03061320","03061405","03061507","03070624","03091616","03120926","03130309","03130616","03171013","03196901"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_tide_direct_code',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[100001],"valueArr":["1"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_town_org_no',1085,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":25,"upper":"03021011","lower":"03020203","count":1645,"preSum":0},{"ndv":20,"upper":"03021507","lower":"03021012","count":1430,"preSum":1645},{"ndv":20,"upper":"03040105","lower":"03021509","count":1422,"preSum":3075},{"ndv":9,"upper":"03040304","lower":"03040106","count":1479,"preSum":4497},{"ndv":9,"upper":"03052308","lower":"03040306","count":1406,"preSum":5976},{"ndv":13,"upper":"03054708","lower":"03052603","count":1381,"preSum":7382},{"ndv":14,"upper":"03054811","lower":"03054709","count":1451,"preSum":8763},{"ndv":12,"upper":"03054909","lower":"03054812","count":1406,"preSum":10214},{"ndv":9,"upper":"03061212","lower":"03054910","count":1388,"preSum":11620},{"ndv":5,"upper":"03061217","lower":"03061213","count":1627,"preSum":13008},{"ndv":5,"upper":"03061315","lower":"03061311","count":1342,"preSum":14635},{"ndv":8,"upper":"03061409","lower":"03061316","count":1344,"preSum":15977},{"ndv":19,"upper":"03070219","lower":"03061410","count":1694,"preSum":17321},{"ndv":21,"upper":"03070516","lower":"03070402","count":1579,"preSum":19015},{"ndv":25,"upper":"03071316","lower":"03070601","count":1825,"preSum":20594},{"ndv":6,"upper":"03080105","lower":"03071408","count":1485,"preSum":22419},{"ndv":18,"upper":"03081015","lower":"03080106","count":1424,"preSum":23904},{"ndv":20,"upper":"03081414","lower":"03081016","count":1386,"preSum":25328},{"ndv":19,"upper":"03082022","lower":"03081415","count":1443,"preSum":26714},{"ndv":18,"upper":"03082823","lower":"03082027","count":1358,"preSum":28157},{"ndv":19,"upper":"03090249","lower":"03082824","count":1344,"preSum":29515},{"ndv":28,"upper":"03090827","lower":"03090250","count":1497,"preSum":30859},{"ndv":17,"upper":"03090927","lower":"03090901","count":1348,"preSum":32356},{"ndv":22,"upper":"03091601","lower":"03090928","count":1373,"preSum":33704},{"ndv":16,"upper":"03120217","lower":"03091603","count":1355,"preSum":35077},{"ndv":14,"upper":"03120407","lower":"03120225","count":1437,"preSum":36432},{"ndv":10,"upper":"03121009","lower":"03120408","count":1414,"preSum":37869},{"ndv":17,"upper":"03130212","lower":"03121010","count":1418,"preSum":39283},{"ndv":5,"upper":"03130225","lower":"03130214","count":1455,"preSum":40701},{"ndv":12,"upper":"03130415","lower":"03130310","count":1414,"preSum":42156},{"ndv":18,"upper":"03131310","lower":"03130418","count":1337,"preSum":43570},{"ndv":19,"upper":"03131418","lower":"03131311","count":1402,"preSum":44907},{"ndv":8,"upper":"03140109","lower":"03131419","count":1370,"preSum":46309},{"ndv":26,"upper":"03140523","lower":"03140110","count":1355,"preSum":47679},{"ndv":26,"upper":"03140811","lower":"03140524","count":1361,"preSum":49034},{"ndv":30,"upper":"03141407","lower":"03140812","count":1515,"preSum":50395},{"ndv":25,"upper":"03150304","lower":"03141409","count":1351,"preSum":51910},{"ndv":21,"upper":"03151106","lower":"03150305","count":1368,"preSum":53261},{"ndv":31,"upper":"03161011","lower":"03151109","count":1346,"preSum":54629},{"ndv":42,"upper":"03163304","lower":"03161013","count":1705,"preSum":55975},{"ndv":18,"upper":"03170507","lower":"03163305","count":1399,"preSum":57680},{"ndv":23,"upper":"03180101","lower":"03170631","count":1526,"preSum":59079},{"ndv":6,"upper":"03180107","lower":"03180102","count":1428,"preSum":60605},{"ndv":17,"upper":"03182312","lower":"03180108","count":1339,"preSum":62033},{"ndv":24,"upper":"03188109","lower":"03182501","count":1352,"preSum":63372},{"ndv":24,"upper":"03196903","lower":"03188110","count":1343,"preSum":64724},{"ndv":7,"upper":"03197011","lower":"03196904","count":1632,"preSum":66067},{"ndv":8,"upper":"03197211","lower":"03197110","count":1353,"preSum":67699},{"ndv":6,"upper":"03197401","lower":"03197212","count":1405,"preSum":69052},{"ndv":5,"upper":"03197508","lower":"03197402","count":1351,"preSum":70457},{"ndv":16,"upper":"03510522","lower":"03197601","count":1342,"preSum":71808},{"ndv":16,"upper":"03510915","lower":"03510524","count":1444,"preSum":73150},{"ndv":9,"upper":"03520202","lower":"03510916","count":1375,"preSum":74594},{"ndv":18,"upper":"03520310","lower":"03520205","count":1436,"preSum":75969},{"ndv":10,"upper":"03520609","lower":"03520311","count":1365,"preSum":77405},{"ndv":17,"upper":"03520633","lower":"03520611","count":1534,"preSum":78770},{"ndv":14,"upper":"03520723","lower":"03520634","count":1381,"preSum":80304},{"ndv":23,"upper":"03530126","lower":"03520724","count":1352,"preSum":81685},{"ndv":28,"upper":"03530601","lower":"03530402","count":1498,"preSum":83037},{"ndv":26,"upper":"03531324","lower":"03530602","count":1010,"preSum":84535}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[643,1259,790,674,555,868,506,554,572,566,672,721,715,1149],"valueArr":["03052307","03060306","03061211","03061218","03061320","03061405","03061507","03070624","03091616","03120926","03130309","03130616","03171013","03196901"],"type":"String","sampleRate":0.924351804778851}',4212,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_town_org_short_name',1005,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":16,"upper":"三灶","lower":"lygds","count":1373,"preSum":0},{"ndv":21,"upper":"东山","lower":"三甲","count":1352,"preSum":1373},{"ndv":15,"upper":"两英","lower":"东岸","count":1472,"preSum":2725},{"ndv":19,"upper":"乐从","lower":"中垌","count":1545,"preSum":4197},{"ndv":11,"upper":"云城东安","lower":"乐城","count":1566,"preSum":5742},{"ndv":19,"upper":"企水","lower":"云城腰古","count":1308,"preSum":7308},{"ndv":15,"upper":"公庄","lower":"企石供电服务中心","count":1304,"preSum":8616},{"ndv":16,"upper":"凤岗中心","lower":"公白","count":1377,"preSum":9920},{"ndv":9,"upper":"勒流","lower":"凤岗供电服务中心","count":1419,"preSum":11297},{"ndv":9,"upper":"华侨","lower":"北和","count":1571,"preSum":12716},{"ndv":12,"upper":"南岸中心","lower":"华城","count":1446,"preSum":14287},{"ndv":9,"upper":"南郊","lower":"南庄","count":1437,"preSum":15733},{"ndv":19,"upper":"叶潭","lower":"博罗龙华","count":1331,"preSum":17170},{"ndv":20,"upper":"唐家湾","lower":"司前","count":1436,"preSum":18501},{"ndv":21,"upper":"城东","lower":"四九","count":1340,"preSum":19937},{"ndv":9,"upper":"塘厦供电服务中心","lower":"城北","count":1473,"preSum":21277},{"ndv":17,"upper":"大岭山供电服务中心(新)","lower":"塘口","count":1563,"preSum":22750},{"ndv":17,"upper":"大湾","lower":"大崀","count":1323,"preSum":24313},{"ndv":10,"upper":"太平","lower":"大溪","count":1484,"preSum":25636},{"ndv":17,"upper":"寮步供电服务中心","lower":"好义","count":1575,"preSum":27120},{"ndv":19,"upper":"平山","lower":"小三江福堂","count":1412,"preSum":28695},{"ndv":16,"upper":"怀城中心","lower":"平沙","count":1433,"preSum":30107},{"ndv":10,"upper":"振文","lower":"思劳","count":1365,"preSum":31540},{"ndv":15,"upper":"新安","lower":"捷胜","count":1326,"preSum":32905},{"ndv":12,"upper":"春城","lower":"新宝","count":1309,"preSum":34231},{"ndv":20,"upper":"杨和","lower":"春湾","count":1305,"preSum":35540},{"ndv":25,"upper":"桥头供电服务中心","lower":"杨家","count":1390,"preSum":36845},{"ndv":17,"upper":"榕东","lower":"梁化","count":1454,"preSum":38235},{"ndv":12,"upper":"水东","lower":"樟木头供电服务中心","count":1490,"preSum":39689},{"ndv":15,"upper":"江北","lower":"水口","count":1638,"preSum":41179},{"ndv":14,"upper":"汤塘龙山","lower":"江南","count":1459,"preSum":42817},{"ndv":19,"upper":"河南岸","lower":"汤西","count":1694,"preSum":44276},{"ndv":21,"upper":"洲心","lower":"河口","count":1647,"preSum":45970},{"ndv":10,"upper":"海安","lower":"洲瑞","count":1320,"preSum":47617},{"ndv":13,"upper":"湖寮","lower":"海宴","count":1342,"preSum":48937},{"ndv":19,"upper":"潮安古巷","lower":"湖镇","count":1372,"preSum":50279},{"ndv":16,"upper":"澄华","lower":"潮安官塘","count":1422,"preSum":51651},{"ndv":10,"upper":"狮山","lower":"澜河中心","count":1330,"preSum":53073},{"ndv":23,"upper":"白盆珠","lower":"玉窖","count":1322,"preSum":54403},{"ndv":13,"upper":"石岭","lower":"白石","count":1315,"preSum":55725},{"ndv":15,"upper":"石鼓","lower":"石扇","count":1332,"preSum":57040},{"ndv":13,"upper":"稔山","lower":"石龙供电服务中心(新)","count":1380,"preSum":58372},{"ndv":20,"upper":"罗定罗城","lower":"稔村","count":1443,"preSum":59752},{"ndv":9,"upper":"老隆","lower":"罗定船步","count":1355,"preSum":61195},{"ndv":19,"upper":"茂港小良","lower":"联安","count":1310,"preSum":62550},{"ndv":16,"upper":"营业部","lower":"茂港沙院","count":1339,"preSum":63860},{"ndv":9,"upper":"虎门供电服务中心(新)","lower":"营仔","count":1349,"preSum":65199},{"ndv":14,"upper":"观珠","lower":"蚬冈","count":1398,"preSum":66548},{"ndv":23,"upper":"连平上坪","lower":"观音阁","count":1309,"preSum":67946},{"ndv":15,"upper":"里水","lower":"连江口","count":1399,"preSum":69255},{"ndv":22,"upper":"铜盂","lower":"里洞","count":1415,"preSum":70654},{"ndv":12,"upper":"长岐","lower":"银江","count":1328,"preSum":72069},{"ndv":13,"upper":"陇田","lower":"长岗中心","count":1363,"preSum":73397},{"ndv":16,"upper":"霖磐","lower":"陈店","count":1308,"preSum":74760},{"ndv":27,"upper":"饶平黄冈","lower":"霞洞","count":1558,"preSum":76068},{"ndv":14,"upper":"高埔","lower":"香坪","count":1368,"preSum":77626},{"ndv":22,"upper":"黄埠","lower":"高埗供电服务中心(新)","count":1370,"preSum":78994},{"ndv":17,"upper":"龙仙","lower":"黄岗中心","count":1387,"preSum":80364},{"ndv":15,"upper":"龙田","lower":"龙口","count":1318,"preSum":81751},{"ndv":5,"upper":"龙颈","lower":"龙窝","count":321,"preSum":83069}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[579,566,554,572,1149,1259,715,790,555,674,721,506,672,868],"valueArr":["东城","东城中心","台城营业所","城区","城区供电服务中心(新)","城区服务点","城郊","大沥","容桂","桂城","淡水","荷城","西区","西南"],"type":"String","sampleRate":0.924351804778851}',6431,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_trade_sort_code',339,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":4,"upper":"IA0300","lower":" IC4110","count":264,"preSum":0},{"ndv":1,"upper":"IA0500","lower":"IA0500","count":154,"preSum":264},{"ndv":1,"upper":"IA0502","lower":"IA0502","count":152,"preSum":418},{"ndv":4,"upper":"IC1312","lower":"IB0620","count":310,"preSum":570},{"ndv":4,"upper":"IC1710","lower":"IC1410","count":227,"preSum":880},{"ndv":1,"upper":"IC1811","lower":"IC1811","count":165,"preSum":1107},{"ndv":1,"upper":"IC1910","lower":"IC1910","count":114,"preSum":1272},{"ndv":1,"upper":"IC2001","lower":"IC2001","count":129,"preSum":1386},{"ndv":2,"upper":"IC2210","lower":"IC2100","count":119,"preSum":1515},{"ndv":2,"upper":"IC2410","lower":"IC2310","count":97,"preSum":1634},{"ndv":11,"upper":"IC2912","lower":"IC2411","count":95,"preSum":1731},{"ndv":1,"upper":"IC2913","lower":"IC2913","count":254,"preSum":1826},{"ndv":4,"upper":"IC3024","lower":"IC3000","count":107,"preSum":2080},{"ndv":5,"upper":"IC3301","lower":"IC3123","count":116,"preSum":2187},{"ndv":8,"upper":"IC3810","lower":"IC3401","count":166,"preSum":2303},{"ndv":3,"upper":"IC3911","lower":"IC3811","count":76,"preSum":2469},{"ndv":3,"upper":"IC4110","lower":"IC3912","count":245,"preSum":2545},{"ndv":2,"upper":"IC4300","lower":"IC4220","count":87,"preSum":2790},{"ndv":5,"upper":"ID4600","lower":"ID4422","count":93,"preSum":2877},{"ndv":1,"upper":"IE4700","lower":"IE4700","count":228,"preSum":2970},{"ndv":3,"upper":"IE5000","lower":"IE4800","count":124,"preSum":3198},{"ndv":8,"upper":"IG5900","lower":"IG5300","count":131,"preSum":3322},{"ndv":3,"upper":"II6401","lower":"IG6000","count":78,"preSum":3453},{"ndv":3,"upper":"IK7000","lower":"II6500","count":218,"preSum":3531},{"ndv":1,"upper":"IL7100","lower":"IL7100","count":247,"preSum":3749},{"ndv":1,"upper":"IL7101","lower":"IL7101","count":112,"preSum":3996},{"ndv":3,"upper":"IM7900","lower":"IM7500","count":321,"preSum":4108},{"ndv":2,"upper":"IM8400","lower":"IM7902","count":130,"preSum":4429},{"ndv":1,"upper":"IM8402","lower":"IM8402","count":147,"preSum":4559},{"ndv":4,"upper":"U9901","lower":"IM8500","count":75,"preSum":4706},{"ndv":2,"upper":"Y0200","lower":"Y0100","count":16,"preSum":4781}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[615,863,502,547,363,4038,856,572,871,712,483,461,39113,45055],"valueArr":["I00000","IA0100","IA0400","IC3300","ID4420","IF5100","IF5101","IH6100","II6300","IM7903","IM8000","IM9300","IY0100","IY0200"],"type":"String","sampleRate":0.924351804778851}',153,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_ts_bill_flag',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[98069,1887],"valueArr":["0","1"],"type":"String","sampleRate":0.924351804778851}',45,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_useage_code',98,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"12","lower":"12","count":1,"preSum":0},{"ndv":1,"upper":"130","lower":"130","count":1,"preSum":1},{"ndv":1,"upper":"250","lower":"250","count":2,"preSum":2},{"ndv":1,"upper":"260","lower":"260","count":2,"preSum":4},{"ndv":1,"upper":"320","lower":"320","count":1,"preSum":6},{"ndv":1,"upper":"330","lower":"330","count":1,"preSum":7}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[3,99093,3,4,710,75,22,21,29,24],"valueArr":["11","110","120","200","210","220","230","312","410","430"],"type":"String","sampleRate":0.924351804778851}',9,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mp_wire_mode_code',32,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"1 ","lower":"1 ","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[41,7,86896,1004,11873],"valueArr":["01","03","1","2","3"],"type":"String","sampleRate":0.924351804778851}',179,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_assets_no',11101882,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1561,"upper":"03001DY00000011700354146","lower":"001528097","count":1562,"preSum":0},{"ndv":1561,"upper":"03001DY00000011701255042","lower":"03001DY00000011700354372","count":1562,"preSum":1562},{"ndv":1558,"upper":"03001DY00000011701968697","lower":"03001DY00000011701256016","count":1562,"preSum":3124},{"ndv":1562,"upper":"03001DY00000011800175398","lower":"03001DY00000011701970103","count":1562,"preSum":4686},{"ndv":1562,"upper":"03001DY00000021700281071","lower":"03001DY00000011800176098","count":1562,"preSum":6248},{"ndv":1561,"upper":"03001DY00000021701229092","lower":"03001DY00000021700281101","count":1562,"preSum":7810},{"ndv":1562,"upper":"03001DY00000021701938010","lower":"03001DY00000021701229657","count":1562,"preSum":9372},{"ndv":1556,"upper":"03001DY00000021702638023","lower":"03001DY00000021701938186","count":1562,"preSum":10934},{"ndv":1561,"upper":"03001DY00000021703307018","lower":"03001DY00000021702638050","count":1562,"preSum":12496},{"ndv":1561,"upper":"03001DY00000021703978186","lower":"03001DY00000021703308103","count":1562,"preSum":14058},{"ndv":1562,"upper":"03001DY00000021900145931","lower":"03001DY00000021703978357","count":1562,"preSum":15620},{"ndv":1561,"upper":"03001DY00000031700589692","lower":"03001DY00000021900145938","count":1562,"preSum":17182},{"ndv":1562,"upper":"03001DY00000041700009930","lower":"03001DY00000031700589698","count":1562,"preSum":18744},{"ndv":1560,"upper":"03001DY00000041701185018","lower":"03001DY00000041700010525","count":1562,"preSum":20306},{"ndv":1559,"upper":"03001DY00000041900040139","lower":"03001DY00000041701185263","count":1562,"preSum":21868},{"ndv":1561,"upper":"03001DY00000051800079004","lower":"03001DY00000041900040287","count":1562,"preSum":23430},{"ndv":1562,"upper":"03001DY00000061800123778","lower":"03001DY00000051800079142","count":1562,"preSum":24992},{"ndv":1562,"upper":"03001DY00000071800090340","lower":"03001DY00000061800123869","count":1562,"preSum":26554},{"ndv":1559,"upper":"03001DY00000081700525258","lower":"03001DY00000071800090556","count":1562,"preSum":28116},{"ndv":1560,"upper":"03001DY00000081701225333","lower":"03001DY00000081700525324","count":1562,"preSum":29678},{"ndv":1562,"upper":"03001DY00000081701976096","lower":"03001DY00000081701225594","count":1562,"preSum":31240},{"ndv":1561,"upper":"03001DY00000091700074695","lower":"03001DY00000081701976934","count":1562,"preSum":32802},{"ndv":1562,"upper":"03001DY00000091700767521","lower":"03001DY00000091700074701","count":1562,"preSum":34364},{"ndv":1562,"upper":"03001DY00000091701450991","lower":"03001DY00000091700768077","count":1562,"preSum":35926},{"ndv":1561,"upper":"03001DY00000101700033577","lower":"03001DY00000091701451131","count":1562,"preSum":37488},{"ndv":1562,"upper":"03001DY00000101700791512","lower":"03001DY00000101700033682","count":1562,"preSum":39050},{"ndv":1562,"upper":"03001DY00000111700301861","lower":"03001DY00000101700792670","count":1562,"preSum":40612},{"ndv":1561,"upper":"03001DY00000111700997299","lower":"03001DY00000111700302392","count":1562,"preSum":42174},{"ndv":1561,"upper":"03001DY00000121700531864","lower":"03001DY00000111700998301","count":1562,"preSum":43736},{"ndv":1562,"upper":"03001DY00011042000053730","lower":"03001DY00000121700532023","count":1562,"preSum":45298},{"ndv":1562,"upper":"03001DY00012132100024438","lower":"03001DY00011042000054186","count":1562,"preSum":46860},{"ndv":1562,"upper":"03001DY00012422000156989","lower":"03001DY00012132100024449","count":1562,"preSum":48422},{"ndv":1558,"upper":"03001DY00012442000153801","lower":"03001DY00012422000157153","count":1562,"preSum":49984},{"ndv":1562,"upper":"03001DY00012472000135845","lower":"03001DY00012442000153837","count":1562,"preSum":51546},{"ndv":1535,"upper":"03001SF00000211900053444","lower":"03001DY00012472000135859","count":1562,"preSum":53108},{"ndv":1534,"upper":"03001SF00000231700248967","lower":"03001SF00000211900053938","count":1562,"preSum":54670},{"ndv":1535,"upper":"03001SF00000261700031695","lower":"03001SF00000231700249401","count":1562,"preSum":56232},{"ndv":1526,"upper":"03001SF00012222100039962","lower":"03001SF00000261700032075","count":1562,"preSum":57794},{"ndv":1494,"upper":"03001SG00011312000008730","lower":"03001SF00012222100040463","count":1562,"preSum":59356},{"ndv":1531,"upper":"03051DY00000001600030709","lower":"03001SG00011312000009049","count":1562,"preSum":60918},{"ndv":1562,"upper":"03061DD00000001601281721","lower":"03051DY00000001600031041","count":1562,"preSum":62480},{"ndv":1558,"upper":"03131DD00000001600000692","lower":"03061DD00000001601286693","count":1562,"preSum":64042},{"ndv":1562,"upper":"03141DY20000000116013021","lower":"03131DD00000001600000906","count":1562,"preSum":65604},{"ndv":1558,"upper":"03181DF00000001600195776","lower":"03141DY20000000116013193","count":1562,"preSum":67166},{"ndv":1562,"upper":"03191DY00000001603984393","lower":"03181DF00000001600195940","count":1562,"preSum":68728},{"ndv":1560,"upper":"03201DD00000001600822964","lower":"03191DY00000001603984605","count":1562,"preSum":70290},{"ndv":1559,"upper":"03521DY00000001600823430","lower":"03201DD00000001600823250","count":1562,"preSum":71852},{"ndv":1561,"upper":"03591DY00000002207673847","lower":"03521DY00000001600823930","count":1562,"preSum":73414},{"ndv":1562,"upper":"03591DY00000002208310099","lower":"03591DY00000002207674484","count":1562,"preSum":74976},{"ndv":1562,"upper":"03591DY00000002209003706","lower":"03591DY00000002208310448","count":1562,"preSum":76538},{"ndv":1562,"upper":"03591DY00000002209779287","lower":"03591DY00000002209004566","count":1562,"preSum":78100},{"ndv":1562,"upper":"03591DY00000002210527334","lower":"03591DY00000002209780089","count":1562,"preSum":79662},{"ndv":1542,"upper":"03591SF00000002201143412","lower":"03591DY00000002210527597","count":1562,"preSum":81224},{"ndv":1527,"upper":"117000203040","lower":"03591SF00000002201144959","count":1562,"preSum":82786},{"ndv":1561,"upper":"124160025478","lower":"117000203608","count":1562,"preSum":84348},{"ndv":1562,"upper":"1310701398783","lower":"124160025953","count":1562,"preSum":85910},{"ndv":1560,"upper":"151481636028","lower":"1310701398886","count":1562,"preSum":87472},{"ndv":1562,"upper":"502201601611","lower":"151481636686","count":1562,"preSum":89034},{"ndv":1560,"upper":"A16402543A","lower":"502201601955","count":1562,"preSum":90596},{"ndv":1561,"upper":"JBD6515042412","lower":"A16402680A","count":1562,"preSum":92158},{"ndv":1562,"upper":"JD02358784","lower":"JBD6515043097","count":1562,"preSum":93720},{"ndv":1560,"upper":"V401000122601","lower":"JD02359083","count":1562,"preSum":95282},{"ndv":1562,"upper":"ZD001194755","lower":"V401000122872","count":1562,"preSum":96844},{"ndv":1553,"upper":"ZUE02036","lower":"ZD001194861","count":1553,"preSum":98406}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[5,5,5,6,5,6,5,5],"valueArr":["001524907","03001SF00000251700266815","03001SG00000311700028938","03001SG00012612000009498","03591SF00000002200987602","03591SF00000002201278026","03591SF00000002201287710","SX1008355"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_baud_rate',59,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"01;04","lower":"01;04","count":1,"preSum":0},{"ndv":1,"upper":"03","lower":"03","count":2,"preSum":1},{"ndv":1,"upper":"1","lower":"1","count":1,"preSum":3},{"ndv":1,"upper":"308","lower":"308","count":2,"preSum":4}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[2024,107,579,73486,9157,57,813,23,4,55],"valueArr":["01","01;02","01;02;04","02","04","05","1200","14","24","2400"],"type":"String","sampleRate":0.924351804778851}',13690,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_comm_addr1',10722947,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1556,"upper":"000001534775","lower":"-111;021703265664","count":1560,"preSum":0},{"ndv":1557,"upper":"000002238820","lower":"000001534934","count":1560,"preSum":1560},{"ndv":1560,"upper":"000006019357","lower":"000002238905","count":1560,"preSum":3120},{"ndv":1560,"upper":"000016607886","lower":"000006019703","count":1560,"preSum":4680},{"ndv":1556,"upper":"001600032522","lower":"000016608404","count":1560,"preSum":6240},{"ndv":1558,"upper":"001601134605","lower":"001600032530","count":1560,"preSum":7800},{"ndv":1556,"upper":"001602631514","lower":"001601137145","count":1560,"preSum":9360},{"ndv":1559,"upper":"001603793092","lower":"001602631634","count":1560,"preSum":10920},{"ndv":1549,"upper":"002106810786","lower":"001603793527","count":1560,"preSum":12480},{"ndv":1522,"upper":"002201376235","lower":"002106811229","count":1560,"preSum":14040},{"ndv":1555,"upper":"002208045930","lower":"002201378113","count":1560,"preSum":15600},{"ndv":1560,"upper":"002208685516","lower":"002208046196","count":1560,"preSum":17160},{"ndv":1560,"upper":"002209384290","lower":"002208685733","count":1560,"preSum":18720},{"ndv":1560,"upper":"002210225077","lower":"002209385955","count":1560,"preSum":20280},{"ndv":1559,"upper":"0048","lower":"002210225130","count":1560,"preSum":21840},{"ndv":1560,"upper":"011700090882","lower":"00516006153","count":1560,"preSum":23400},{"ndv":1558,"upper":"011700812407","lower":"011700091793","count":1560,"preSum":24960},{"ndv":1556,"upper":"011701783366","lower":"011700812926","count":1560,"preSum":26520},{"ndv":1560,"upper":"011800080296","lower":"011701783559","count":1560,"preSum":28080},{"ndv":1560,"upper":"012000071551","lower":"011800081224","count":1560,"preSum":29640},{"ndv":1560,"upper":"021700355959","lower":"012000071631","count":1560,"preSum":31200},{"ndv":1559,"upper":"021701327621","lower":"021700356125","count":1560,"preSum":32760},{"ndv":1560,"upper":"021702018810","lower":"021701327628","count":1560,"preSum":34320},{"ndv":1554,"upper":"021702719794","lower":"021702019259","count":1560,"preSum":35880},{"ndv":1559,"upper":"021703389077","lower":"021702719818","count":1560,"preSum":37440},{"ndv":1559,"upper":"021704055944","lower":"021703389124","count":1560,"preSum":39000},{"ndv":1560,"upper":"021900224751","lower":"021704056239","count":1560,"preSum":40560},{"ndv":1559,"upper":"031700364332","lower":"021900225347","count":1560,"preSum":42120},{"ndv":1560,"upper":"031900026912","lower":"031700364490","count":1560,"preSum":43680},{"ndv":1559,"upper":"041700344649","lower":"031900027259","count":1560,"preSum":45240},{"ndv":1558,"upper":"041701494222","lower":"041700345174","count":1560,"preSum":46800},{"ndv":1557,"upper":"051600031070","lower":"041701494321","count":1560,"preSum":48360},{"ndv":1559,"upper":"051800052010","lower":"051600031463","count":1560,"preSum":49920},{"ndv":1560,"upper":"061700320272","lower":"051800052331","count":1560,"preSum":51480},{"ndv":1560,"upper":"071700219098","lower":"061700320448","count":1560,"preSum":53040},{"ndv":1557,"upper":"081700248557","lower":"071700219604","count":1560,"preSum":54600},{"ndv":1559,"upper":"081701022543","lower":"081700249338","count":1560,"preSum":56160},{"ndv":1560,"upper":"081701728435","lower":"081701022889","count":1560,"preSum":57720},{"ndv":1559,"upper":"081800093392","lower":"081701728567","count":1560,"preSum":59280},{"ndv":1560,"upper":"091700548195","lower":"081800093447","count":1560,"preSum":60840},{"ndv":1560,"upper":"091701183535","lower":"091700548624","count":1560,"preSum":62400},{"ndv":1560,"upper":"091701884731","lower":"091701183929","count":1560,"preSum":63960},{"ndv":1559,"upper":"101700399238","lower":"091701885836","count":1560,"preSum":65520},{"ndv":1560,"upper":"111603269383","lower":"101700399250","count":1560,"preSum":67080},{"ndv":1560,"upper":"111700541458","lower":"111603269503","count":1560,"preSum":68640},{"ndv":1559,"upper":"112100053271","lower":"111700544405","count":1560,"preSum":70200},{"ndv":1560,"upper":"121700026695","lower":"112100053612","count":1560,"preSum":71760},{"ndv":1559,"upper":"122100147218","lower":"121700026967","count":1560,"preSum":73320},{"ndv":1559,"upper":"124160030401","lower":"122100147354","count":1560,"preSum":74880},{"ndv":1560,"upper":"132100131501","lower":"124160031049","count":1560,"preSum":76440},{"ndv":1558,"upper":"160513000661","lower":"132100132309","count":1560,"preSum":78000},{"ndv":1553,"upper":"211700207427","lower":"160513000853","count":1560,"preSum":79560},{"ndv":1528,"upper":"218000056591","lower":"211700208088","count":1560,"preSum":81120},{"ndv":1529,"upper":"222100073216","lower":"218000056800","count":1560,"preSum":82680},{"ndv":1528,"upper":"241900046090","lower":"222100073551","count":1560,"preSum":84240},{"ndv":1537,"upper":"271700085911","lower":"241900047132","count":1560,"preSum":85800},{"ndv":1540,"upper":"331603764790","lower":"271700085971","count":1560,"preSum":87360},{"ndv":1559,"upper":"412000232558","lower":"331603764823","count":1560,"preSum":88920},{"ndv":1557,"upper":"432000088672","lower":"412000232710","count":1560,"preSum":90480},{"ndv":1556,"upper":"445300000609","lower":"432000089820","count":1560,"preSum":92040},{"ndv":1556,"upper":"452000078314","lower":"44530000087F","count":1560,"preSum":93600},{"ndv":1558,"upper":"512000075497","lower":"452000078980","count":1560,"preSum":95160},{"ndv":1518,"upper":"702000052932","lower":"512000075591","count":1560,"preSum":96720},{"ndv":1532,"upper":"未填地址","lower":"702000053302","count":1538,"preSum":98280}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[5,5,6,5,5,5,5,5,6,6,10],"valueArr":["000001524907","002200987602","002201278026","002201287710","1","100835","251700266815","311700028938","612000009498","9","计量柜内"],"type":"String","sampleRate":0.924351804778851}',120,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_comm_addr2',32,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"211900053444","lower":"211900053444","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100000,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_comm_mode_code',116,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":"01/02/03","lower":"01,02","count":6,"preSum":0},{"ndv":1,"upper":"0102","lower":"0102","count":8,"preSum":6},{"ndv":2,"upper":"01;03;02","lower":"01;02;03;04","count":21,"preSum":14},{"ndv":1,"upper":"02;01","lower":"02;01","count":55,"preSum":35},{"ndv":1,"upper":"02;01;03","lower":"02;01;03","count":39,"preSum":90},{"ndv":1,"upper":"02;01;04","lower":"02;01;04","count":57,"preSum":129},{"ndv":3,"upper":"03;04","lower":"02;03;04","count":10,"preSum":186},{"ndv":1,"upper":"06","lower":"06","count":37,"preSum":196},{"ndv":2,"upper":"1","lower":"09","count":10,"preSum":233},{"ndv":1,"upper":"3","lower":"3","count":16,"preSum":243},{"ndv":2,"upper":"7","lower":"3.0","count":7,"preSum":259},{"ndv":2,"upper":"DL/T645-2007规约","lower":"8","count":36,"preSum":266},{"ndv":1,"upper":"null","lower":"null","count":43,"preSum":302}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1149,1521,4471,1394,6373,257,85,3642,137,74,284,92,429,78],"valueArr":["01","01;02","01;02;03","01;02;04","02","02;03","02;03;01","03","03;01;02","03;02;01","04","05","07","10"],"type":"String","sampleRate":0.924351804778851}',79670,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_comm_protocol_code',78,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"14;04","lower":"14;04","count":1,"preSum":0},{"ndv":1,"upper":"15","lower":"15","count":1,"preSum":1},{"ndv":1,"upper":"19","lower":"19","count":1,"preSum":2}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[35,9,29578,331,48819,112,53,144,11,71,11],"valueArr":["01;04","03","1","13","14","14;1","14;4","1;4","2","22","3"],"type":"String","sampleRate":0.924351804778851}',20824,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_equ_id',10927589,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1560,"upper":"031300005950233","lower":"030200000253033","count":1562,"preSum":0},{"ndv":1560,"upper":"035200000295929","lower":"031300005950457","count":1562,"preSum":1562},{"ndv":1560,"upper":"1000000000884717","lower":"035200000296361","count":1562,"preSum":3124},{"ndv":1562,"upper":"1000000003427288","lower":"1000000000885893","count":1562,"preSum":4686},{"ndv":1561,"upper":"1000000004462156","lower":"1000000003427830","count":1562,"preSum":6248},{"ndv":1562,"upper":"1000000005630399","lower":"1000000004462979","count":1562,"preSum":7810},{"ndv":1561,"upper":"1000000006891190","lower":"1000000005633348","count":1562,"preSum":9372},{"ndv":1562,"upper":"1000000008586782","lower":"1000000006891327","count":1562,"preSum":10934},{"ndv":1560,"upper":"1000000010482104","lower":"1000000008586834","count":1562,"preSum":12496},{"ndv":1558,"upper":"1000000011795700","lower":"1000000010482110","count":1562,"preSum":14058},{"ndv":1562,"upper":"1000000013068235","lower":"1000000011796112","count":1562,"preSum":15620},{"ndv":1562,"upper":"1000000014478177","lower":"1000000013069758","count":1562,"preSum":17182},{"ndv":1562,"upper":"1000000015382795","lower":"1000000014478185","count":1562,"preSum":18744},{"ndv":1561,"upper":"1000000016908810","lower":"1000000015383058","count":1562,"preSum":20306},{"ndv":1561,"upper":"1000000018328214","lower":"1000000016908933","count":1562,"preSum":21868},{"ndv":1561,"upper":"1000000019264889","lower":"1000000018330098","count":1562,"preSum":23430},{"ndv":1561,"upper":"1000000020559684","lower":"1000000019265341","count":1562,"preSum":24992},{"ndv":1559,"upper":"1000000022600811","lower":"1000000020559879","count":1562,"preSum":26554},{"ndv":1562,"upper":"1000000024326653","lower":"1000000022601266","count":1562,"preSum":28116},{"ndv":1558,"upper":"1000000025650401","lower":"1000000024326761","count":1562,"preSum":29678},{"ndv":1559,"upper":"1000000026986707","lower":"1000000025650535","count":1562,"preSum":31240},{"ndv":1560,"upper":"1000000028798837","lower":"1000000026986823","count":1562,"preSum":32802},{"ndv":1560,"upper":"1000000030734157","lower":"1000000028799027","count":1562,"preSum":34364},{"ndv":1556,"upper":"1000000032628817","lower":"1000000030734850","count":1562,"preSum":35926},{"ndv":1559,"upper":"1000000033755945","lower":"1000000032628904","count":1562,"preSum":37488},{"ndv":1559,"upper":"1000000034875312","lower":"1000000033755960","count":1562,"preSum":39050},{"ndv":1562,"upper":"1000000035869572","lower":"1000000034876664","count":1562,"preSum":40612},{"ndv":1554,"upper":"1000000036787914","lower":"1000000035870100","count":1562,"preSum":42174},{"ndv":1558,"upper":"1000000037777048","lower":"1000000036788176","count":1562,"preSum":43736},{"ndv":1561,"upper":"1000000039010162","lower":"1000000037778758","count":1562,"preSum":45298},{"ndv":1559,"upper":"1000000040170845","lower":"1000000039015319","count":1562,"preSum":46860},{"ndv":1554,"upper":"1000000041003963","lower":"1000000040172425","count":1562,"preSum":48422},{"ndv":1561,"upper":"1000000042101497","lower":"1000000041004096","count":1562,"preSum":49984},{"ndv":1562,"upper":"1000000043295960","lower":"1000000042101523","count":1562,"preSum":51546},{"ndv":1562,"upper":"1000000044570020","lower":"1000000043296562","count":1562,"preSum":53108},{"ndv":1560,"upper":"1000000045892430","lower":"1000000044570025","count":1562,"preSum":54670},{"ndv":1552,"upper":"1000000047826838","lower":"1000000045893674","count":1562,"preSum":56232},{"ndv":1554,"upper":"1000000049749647","lower":"1000000047827172","count":1562,"preSum":57794},{"ndv":1556,"upper":"1000000051319824","lower":"1000000049750274","count":1562,"preSum":59356},{"ndv":1561,"upper":"1000000052434107","lower":"1000000051320349","count":1562,"preSum":60918},{"ndv":1556,"upper":"1000000053776727","lower":"1000000052434113","count":1562,"preSum":62480},{"ndv":1555,"upper":"1000000054696274","lower":"1000000053776762","count":1562,"preSum":64042},{"ndv":1553,"upper":"1000000055702573","lower":"1000000054696617","count":1562,"preSum":65604},{"ndv":1557,"upper":"1000000057496378","lower":"1000000055702934","count":1562,"preSum":67166},{"ndv":1552,"upper":"1000000059351871","lower":"1000000057497156","count":1562,"preSum":68728},{"ndv":1557,"upper":"1000000060316343","lower":"1000000059353741","count":1562,"preSum":70290},{"ndv":1550,"upper":"1000000063872250","lower":"1000000060317187","count":1562,"preSum":71852},{"ndv":1552,"upper":"1000000065852353","lower":"1000000063872626","count":1562,"preSum":73414},{"ndv":1557,"upper":"1000000067619387","lower":"1000000065852604","count":1562,"preSum":74976},{"ndv":1557,"upper":"1000000070100154","lower":"1000000067619533","count":1562,"preSum":76538},{"ndv":1557,"upper":"1000000071387787","lower":"1000000070100408","count":1562,"preSum":78100},{"ndv":1556,"upper":"1000000072768154","lower":"1000000071388154","count":1562,"preSum":79662},{"ndv":1552,"upper":"1000000073660570","lower":"1000000072768440","count":1562,"preSum":81224},{"ndv":1539,"upper":"1000000074599993","lower":"1000000073662122","count":1562,"preSum":82786},{"ndv":1544,"upper":"1000000075429426","lower":"1000000074600004","count":1562,"preSum":84348},{"ndv":1556,"upper":"1000000076326432","lower":"1000000075429753","count":1562,"preSum":85910},{"ndv":1550,"upper":"1000000077555117","lower":"1000000076331304","count":1562,"preSum":87472},{"ndv":1539,"upper":"1000000178728607","lower":"1000000077555133","count":1562,"preSum":89034},{"ndv":1554,"upper":"1000000180274917","lower":"1000000178728933","count":1562,"preSum":90596},{"ndv":1546,"upper":"1000000181403567","lower":"1000000180275200","count":1562,"preSum":92158},{"ndv":1557,"upper":"1000000182370350","lower":"1000000181404144","count":1562,"preSum":93720},{"ndv":1556,"upper":"1000000183499786","lower":"1000000182370401","count":1562,"preSum":95282},{"ndv":1559,"upper":"1000000184718848","lower":"1000000183501456","count":1562,"preSum":96844},{"ndv":1535,"upper":"1002000189302502","lower":"1000000184719003","count":1553,"preSum":98406}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[5,5,5,5,6,5,6,5],"valueArr":["031700002916020","031800002975200","1000000044783597","1000000057006046","1000000074613955","1000000179588463","1000000185820329","1000000186418791"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_made_no',8639570,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1532,"upper":"001601140837","lower":"--0000000049671","count":1533,"preSum":0},{"ndv":1522,"upper":"002107020706","lower":"001601140973","count":1533,"preSum":1533},{"ndv":1489,"upper":"002207482104","lower":"002107020915","count":1533,"preSum":3066},{"ndv":1532,"upper":"002208118407","lower":"002207482627","count":1533,"preSum":4599},{"ndv":1533,"upper":"002208768775","lower":"002208118911","count":1533,"preSum":6132},{"ndv":1533,"upper":"002209445580","lower":"002208768800","count":1533,"preSum":7665},{"ndv":1533,"upper":"002210264969","lower":"002209445584","count":1533,"preSum":9198},{"ndv":1531,"upper":"010000054299","lower":"002210265068","count":1533,"preSum":10731},{"ndv":1533,"upper":"011900378817","lower":"010000054415","count":1533,"preSum":12264},{"ndv":1533,"upper":"021700220873","lower":"011900379792","count":1533,"preSum":13797},{"ndv":1532,"upper":"021701462869","lower":"021700221552","count":1533,"preSum":15330},{"ndv":1533,"upper":"021702636356","lower":"021701464412","count":1533,"preSum":16863},{"ndv":1533,"upper":"021703335292","lower":"021702637086","count":1533,"preSum":18396},{"ndv":1533,"upper":"021900186409","lower":"021703335609","count":1533,"preSum":19929},{"ndv":1532,"upper":"03001DY00000011700311022","lower":"021900187165","count":1533,"preSum":21462},{"ndv":1532,"upper":"03001DY00000011701206540","lower":"03001DY00000011700312064","count":1533,"preSum":22995},{"ndv":1529,"upper":"03001DY00000011701914743","lower":"03001DY00000011701207702","count":1533,"preSum":24528},{"ndv":1533,"upper":"03001DY00000011800111203","lower":"03001DY00000011701915645","count":1533,"preSum":26061},{"ndv":1533,"upper":"03001DY00000021702041440","lower":"03001DY00000011800111217","count":1533,"preSum":27594},{"ndv":1525,"upper":"03001DY00000021704057811","lower":"03001DY00000021702041853","count":1533,"preSum":29127},{"ndv":1532,"upper":"03001DY00000031700523538","lower":"03001DY00000021704057819","count":1533,"preSum":30660},{"ndv":1533,"upper":"03001DY00000041700392032","lower":"03001DY00000031700523590","count":1533,"preSum":32193},{"ndv":1529,"upper":"03001DY00000051700340498","lower":"03001DY00000041700392988","count":1533,"preSum":33726},{"ndv":1533,"upper":"03001DY00000071800236479","lower":"03001DY00000051700340740","count":1533,"preSum":35259},{"ndv":1528,"upper":"03001DY00000081701178930","lower":"03001DY00000071800237717","count":1533,"preSum":36792},{"ndv":1533,"upper":"03001DY00000091700297102","lower":"03001DY00000081701179895","count":1533,"preSum":38325},{"ndv":1533,"upper":"03001DY00000091701423857","lower":"03001DY00000091700297171","count":1533,"preSum":39858},{"ndv":1533,"upper":"03001DY00000101700253884","lower":"03001DY00000091701424173","count":1533,"preSum":41391},{"ndv":1533,"upper":"03001DY00000111700228895","lower":"03001DY00000101700254021","count":1533,"preSum":42924},{"ndv":1532,"upper":"03001DY00000111700885940","lower":"03001DY00000111700229115","count":1533,"preSum":44457},{"ndv":1530,"upper":"03001SF00000211700263818","lower":"03001DY00000111700886561","count":1533,"preSum":45990},{"ndv":1499,"upper":"03001SF00000251700004571","lower":"03001SF00000211700263845","count":1533,"preSum":47523},{"ndv":1516,"upper":"03061DY00000001603810429","lower":"03001SF00000251700004846","count":1533,"preSum":49056},{"ndv":1530,"upper":"03131SD00000001600304551","lower":"03061DY00000001603810549","count":1533,"preSum":50589},{"ndv":1533,"upper":"031800243847","lower":"03131SD00000001600304710","count":1533,"preSum":52122},{"ndv":1532,"upper":"031900021780","lower":"031800243909","count":1533,"preSum":53655},{"ndv":1533,"upper":"03201SD00000001600069834","lower":"031900022144","count":1533,"preSum":55188},{"ndv":1528,"upper":"041701369755","lower":"03201SD00000001601113414","count":1533,"preSum":56721},{"ndv":1532,"upper":"051600102393","lower":"041701369847","count":1533,"preSum":58254},{"ndv":1533,"upper":"061700213923","lower":"051600102431","count":1533,"preSum":59787},{"ndv":1533,"upper":"071700290722","lower":"061700214044","count":1533,"preSum":61320},{"ndv":1533,"upper":"081701302172","lower":"071700290724","count":1533,"preSum":62853},{"ndv":1532,"upper":"081900006613","lower":"081701303130","count":1533,"preSum":64386},{"ndv":1533,"upper":"091701293504","lower":"081900007067","count":1533,"preSum":65919},{"ndv":1532,"upper":"101700972953","lower":"091701293729","count":1533,"preSum":67452},{"ndv":1532,"upper":"117000012572","lower":"101700973386","count":1533,"preSum":68985},{"ndv":1532,"upper":"122100120715","lower":"117000013239","count":1533,"preSum":70518},{"ndv":1532,"upper":"124160014943","lower":"122100120929","count":1533,"preSum":72051},{"ndv":1533,"upper":"1310701150652","lower":"124160015551","count":1533,"preSum":73584},{"ndv":1533,"upper":"134170110825","lower":"1310701150916","count":1533,"preSum":75117},{"ndv":1532,"upper":"160311033949","lower":"134170110891","count":1533,"preSum":76650},{"ndv":1532,"upper":"201200000240","lower":"160311034279","count":1533,"preSum":78183},{"ndv":1525,"upper":"211700221254","lower":"201200000611","count":1533,"preSum":79716},{"ndv":1498,"upper":"221900060427","lower":"211700221835","count":1533,"preSum":81249},{"ndv":1500,"upper":"241900005880","lower":"221900060558","count":1533,"preSum":82782},{"ndv":1513,"upper":"311700053226","lower":"241900006081","count":1533,"preSum":84315},{"ndv":1517,"upper":"412000130819","lower":"311700053386","count":1533,"preSum":85848},{"ndv":1533,"upper":"422000379504","lower":"412000130836","count":1533,"preSum":87381},{"ndv":1528,"upper":"452000028805","lower":"422000379506","count":1533,"preSum":88914},{"ndv":1533,"upper":"512000007882","lower":"452000029124","count":1533,"preSum":90447},{"ndv":1485,"upper":"702616002695","lower":"512000008495","count":1533,"preSum":91980},{"ndv":1530,"upper":"JD01690066","lower":"702616002806","count":1533,"preSum":93513},{"ndv":1533,"upper":"JD02473376","lower":"JD01691525","count":1533,"preSum":95046},{"ndv":1530,"upper":"ZM20604237","lower":"JD02474118","count":1530,"preSum":96579}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[5,5,6,5,5,5,6,5],"valueArr":["000040000000000302984874","002200987602","002201278026","002201287710","03001SF00000251700266815","311700028938","612000009498","809016220941"],"type":"String","sampleRate":0.924351804778851}',1850,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_ma_auxil_table_signs',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[71,99930],"valueArr":["0","1"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_meter_digits_code',41,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"32","lower":"32","count":1,"preSum":0},{"ndv":1,"upper":"42","lower":"42","count":2,"preSum":1}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[108,22,374,134,5,1520,5794,79624,23,559,91,313,236],"valueArr":["41","50","51","52","6.2","60","61","62","63","64","70","82","99"],"type":"String","sampleRate":0.924351804778851}',11195,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_oper_comm_mode',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_oper_comm_protocol',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_param_id',8097,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":28,"upper":"030000000000762","lower":"030000000000004","count":1413,"preSum":0},{"ndv":72,"upper":"030000000004558","lower":"030000000000765","count":1443,"preSum":1413},{"ndv":60,"upper":"030000000009274","lower":"030000000004568","count":1197,"preSum":2856},{"ndv":175,"upper":"1111111111401637","lower":"030000000009299","count":1275,"preSum":4053},{"ndv":83,"upper":"1111111111646639","lower":"1111111111406314","count":1695,"preSum":5328},{"ndv":7,"upper":"1111111111676645","lower":"1111111111651315","count":1394,"preSum":7023},{"ndv":24,"upper":"1111111111721641","lower":"1111111111676646","count":1241,"preSum":8417},{"ndv":37,"upper":"1111111111861641","lower":"1111111111721642","count":1456,"preSum":9658},{"ndv":56,"upper":"1111111112066644","lower":"1111111111866315","count":1271,"preSum":11114},{"ndv":21,"upper":"1111111112156644","lower":"1111111112071195","count":1545,"preSum":12385},{"ndv":26,"upper":"1111111112231641","lower":"1111111112156645","count":1285,"preSum":13930},{"ndv":11,"upper":"1111111112271641","lower":"1111111112241315","count":1302,"preSum":15215},{"ndv":14,"upper":"1111111112336641","lower":"1111111112276642","count":1303,"preSum":16517},{"ndv":10,"upper":"1111111112356641","lower":"1111111112336642","count":1705,"preSum":17820},{"ndv":41,"upper":"1111111112496642","lower":"1111111112361315","count":1256,"preSum":19525},{"ndv":17,"upper":"1111111112551641","lower":"1111111112496643","count":1264,"preSum":20781},{"ndv":24,"upper":"1111111112646641","lower":"1111111112556315","count":1200,"preSum":22045},{"ndv":35,"upper":"1111111112766197","lower":"1111111112651196","count":1196,"preSum":23245},{"ndv":38,"upper":"1111111112897255","lower":"1111111112766315","count":1257,"preSum":24441},{"ndv":19,"upper":"1111111112992255","lower":"1111111112901315","count":1560,"preSum":25698},{"ndv":19,"upper":"1111111113057257","lower":"1111111112992256","count":1233,"preSum":27258},{"ndv":9,"upper":"1111111113077256","lower":"1111111113062255","count":1316,"preSum":28491},{"ndv":5,"upper":"1111111113092255","lower":"1111111113082255","count":1196,"preSum":29807},{"ndv":6,"upper":"1111111113127255","lower":"1111111113092257","count":1239,"preSum":31003},{"ndv":8,"upper":"1111111113182256","lower":"1111111113142255","count":1198,"preSum":32242},{"ndv":11,"upper":"1111111113227255","lower":"1111111113182257","count":1532,"preSum":33440},{"ndv":21,"upper":"1111111113327255","lower":"1111111113232255","count":1212,"preSum":34972},{"ndv":16,"upper":"1111111113472255","lower":"1111111113342255","count":1447,"preSum":36184},{"ndv":21,"upper":"1111111113632255","lower":"1111111113472256","count":1411,"preSum":37631},{"ndv":9,"upper":"1111111113682255","lower":"1111111113642255","count":1552,"preSum":39042},{"ndv":9,"upper":"1111111113722259","lower":"1111111113687255","count":1516,"preSum":40594},{"ndv":21,"upper":"1111111113817259","lower":"1111111113727259","count":1202,"preSum":42110},{"ndv":15,"upper":"1111111113902259","lower":"1111111113822259","count":1469,"preSum":43312},{"ndv":9,"upper":"1111111113987259","lower":"1111111113907259","count":1208,"preSum":44781},{"ndv":12,"upper":"1111111114082259","lower":"1111111113992259","count":1217,"preSum":45989},{"ndv":8,"upper":"1111111114137259","lower":"1111111114097259","count":1381,"preSum":47206},{"ndv":19,"upper":"1111111114297259","lower":"1111111114162259","count":1206,"preSum":48587},{"ndv":78,"upper":"1111111115047262","lower":"1111111114302259","count":1198,"preSum":49793},{"ndv":58,"upper":"1111111115232261","lower":"1111111115057259","count":1342,"preSum":50991},{"ndv":17,"upper":"1111111115312264","lower":"1111111115237262","count":1512,"preSum":52333},{"ndv":16,"upper":"1111111115402265","lower":"1111111115317264","count":1291,"preSum":53845},{"ndv":21,"upper":"1111111115522264","lower":"1111111115407264","count":1354,"preSum":55136},{"ndv":16,"upper":"1111111115697265","lower":"1111111115527264","count":1250,"preSum":56490},{"ndv":10,"upper":"1111111115767264","lower":"1111111115702264","count":1196,"preSum":57740},{"ndv":6,"upper":"1111111115812264","lower":"1111111115777264","count":1266,"preSum":58936},{"ndv":21,"upper":"1111111115927264","lower":"1111111115817265","count":1819,"preSum":60202},{"ndv":32,"upper":"1111111116177264","lower":"1111111115932264","count":1397,"preSum":62021},{"ndv":84,"upper":"1111111116427264","lower":"1111111116182264","count":1278,"preSum":63418},{"ndv":46,"upper":"1111111116517268","lower":"1111111116432264","count":1225,"preSum":64696},{"ndv":25,"upper":"1111111116607264","lower":"1111111116517269","count":1591,"preSum":65921},{"ndv":61,"upper":"3111111116732266","lower":"1111111116617264","count":1668,"preSum":67512},{"ndv":13,"upper":"3111111116797264","lower":"3111111116737265","count":1228,"preSum":69180},{"ndv":6,"upper":"3111111116832264","lower":"3111111116802265","count":1788,"preSum":70408},{"ndv":7,"upper":"3111111116847264","lower":"3111111116832265","count":1268,"preSum":72196},{"ndv":13,"upper":"3111111116927264","lower":"3111111116847265","count":1201,"preSum":73464},{"ndv":46,"upper":"3111111117237265","lower":"3111111116942264","count":1205,"preSum":74665},{"ndv":57,"upper":"3111191116832264","lower":"3111111117237266","count":647,"preSum":75870}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1801,2158,1806,1380,2158,3042,1164,1300,1379,1484,1345,1902,1232,1330],"valueArr":["1111111112281641","1111111112391642","1111111113077257","1111111113117256","1111111113117257","1111111113267256","1111111113292255","1111111113292256","1111111113307255","1111111113622255","1111111113847259","1111111113932259","1111111114037259","1111111114142259"],"type":"String","sampleRate":0.924351804778851}',3,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_read_order',3030,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":8,"lower":5,"count":1483,"preSum":0},{"ndv":2,"upper":17,"lower":13,"count":1476,"preSum":1483},{"ndv":2,"upper":19,"lower":18,"count":1468,"preSum":2959},{"ndv":2,"upper":21,"lower":20,"count":1414,"preSum":4427},{"ndv":3,"upper":24,"lower":22,"count":2051,"preSum":5841},{"ndv":3,"upper":27,"lower":25,"count":1941,"preSum":7892},{"ndv":3,"upper":30,"lower":28,"count":1795,"preSum":9833},{"ndv":3,"upper":33,"lower":31,"count":1785,"preSum":11628},{"ndv":3,"upper":36,"lower":34,"count":1740,"preSum":13413},{"ndv":3,"upper":39,"lower":37,"count":1694,"preSum":15153},{"ndv":3,"upper":42,"lower":40,"count":1622,"preSum":16847},{"ndv":3,"upper":45,"lower":43,"count":1635,"preSum":18469},{"ndv":3,"upper":48,"lower":46,"count":1593,"preSum":20104},{"ndv":3,"upper":51,"lower":49,"count":1546,"preSum":21697},{"ndv":3,"upper":54,"lower":52,"count":1620,"preSum":23243},{"ndv":3,"upper":57,"lower":55,"count":1524,"preSum":24863},{"ndv":3,"upper":60,"lower":58,"count":1501,"preSum":26387},{"ndv":3,"upper":63,"lower":61,"count":1460,"preSum":27888},{"ndv":3,"upper":66,"lower":64,"count":1382,"preSum":29348},{"ndv":3,"upper":69,"lower":67,"count":1421,"preSum":30730},{"ndv":3,"upper":72,"lower":70,"count":1370,"preSum":32151},{"ndv":4,"upper":76,"lower":73,"count":1687,"preSum":33521},{"ndv":4,"upper":80,"lower":77,"count":1675,"preSum":35208},{"ndv":4,"upper":84,"lower":81,"count":1650,"preSum":36883},{"ndv":4,"upper":88,"lower":85,"count":1636,"preSum":38533},{"ndv":4,"upper":92,"lower":89,"count":1576,"preSum":40169},{"ndv":4,"upper":96,"lower":93,"count":1528,"preSum":41745},{"ndv":4,"upper":100,"lower":97,"count":1485,"preSum":43273},{"ndv":4,"upper":104,"lower":101,"count":1417,"preSum":44758},{"ndv":4,"upper":108,"lower":105,"count":1398,"preSum":46175},{"ndv":5,"upper":113,"lower":109,"count":1676,"preSum":47573},{"ndv":5,"upper":118,"lower":114,"count":1694,"preSum":49249},{"ndv":5,"upper":123,"lower":119,"count":1571,"preSum":50943},{"ndv":5,"upper":128,"lower":124,"count":1520,"preSum":52514},{"ndv":5,"upper":133,"lower":129,"count":1442,"preSum":54034},{"ndv":5,"upper":138,"lower":134,"count":1471,"preSum":55476},{"ndv":6,"upper":144,"lower":139,"count":1609,"preSum":56947},{"ndv":6,"upper":150,"lower":145,"count":1495,"preSum":58556},{"ndv":6,"upper":156,"lower":151,"count":1461,"preSum":60051},{"ndv":7,"upper":163,"lower":157,"count":1518,"preSum":61512},{"ndv":7,"upper":170,"lower":164,"count":1473,"preSum":63030},{"ndv":7,"upper":177,"lower":171,"count":1439,"preSum":64503},{"ndv":8,"upper":185,"lower":178,"count":1494,"preSum":65942},{"ndv":8,"upper":193,"lower":186,"count":1450,"preSum":67436},{"ndv":9,"upper":202,"lower":194,"count":1453,"preSum":68886},{"ndv":10,"upper":212,"lower":203,"count":1503,"preSum":70339},{"ndv":11,"upper":223,"lower":213,"count":1424,"preSum":71842},{"ndv":12,"upper":235,"lower":224,"count":1495,"preSum":73266},{"ndv":13,"upper":248,"lower":236,"count":1458,"preSum":74761},{"ndv":14,"upper":262,"lower":249,"count":1377,"preSum":76219},{"ndv":17,"upper":279,"lower":263,"count":1431,"preSum":77596},{"ndv":20,"upper":299,"lower":280,"count":1389,"preSum":79027},{"ndv":24,"upper":323,"lower":300,"count":1402,"preSum":80416},{"ndv":31,"upper":354,"lower":324,"count":1390,"preSum":81818},{"ndv":40,"upper":394,"lower":355,"count":1395,"preSum":83208},{"ndv":66,"upper":460,"lower":395,"count":1372,"preSum":84603},{"ndv":202,"upper":663,"lower":461,"count":1370,"preSum":85975},{"ndv":145,"upper":1149,"lower":665,"count":215,"preSum":87345}],"maxBucketSize":64,"type":"Double","sampleRate":0.9243518}','{"countArr":[1659,1008,930,854,768,869,774,842,812,797,785,793,769,764],"valueArr":[0,1,2,3,4,6,7,9,10,11,12,14,15,16],"type":"Double","sampleRate":0.924351804778851}',17,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_run_meter_id',11048772,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1548,"upper":"030200000792343","lower":"030200000001480","count":1562,"preSum":0},{"ndv":1556,"upper":"030400000266412","lower":"030200000792459","count":1562,"preSum":1562},{"ndv":1558,"upper":"030500000209290","lower":"030400000267095","count":1562,"preSum":3124},{"ndv":1562,"upper":"030500000863995","lower":"030500000214030","count":1562,"preSum":4686},{"ndv":1562,"upper":"030500001635254","lower":"030500000864010","count":1562,"preSum":6248},{"ndv":1561,"upper":"030600000326490","lower":"030500001635651","count":1562,"preSum":7810},{"ndv":1552,"upper":"030600001202359","lower":"030600000326576","count":1562,"preSum":9372},{"ndv":1554,"upper":"030600002025108","lower":"030600001202441","count":1562,"preSum":10934},{"ndv":1554,"upper":"030600002969158","lower":"030600002025811","count":1562,"preSum":12496},{"ndv":1560,"upper":"030700000180745","lower":"030600002969583","count":1562,"preSum":14058},{"ndv":1562,"upper":"030700001185471","lower":"030700000181026","count":1562,"preSum":15620},{"ndv":1562,"upper":"030700001821792","lower":"030700001185556","count":1562,"preSum":17182},{"ndv":1561,"upper":"030800000237889","lower":"030700001822503","count":1562,"preSum":18744},{"ndv":1561,"upper":"030800000923026","lower":"030800000238776","count":1562,"preSum":20306},{"ndv":1560,"upper":"030800001653950","lower":"030800000923276","count":1562,"preSum":21868},{"ndv":1561,"upper":"030900000252397","lower":"030800001654394","count":1562,"preSum":23430},{"ndv":1558,"upper":"030900000933423","lower":"030900000253683","count":1562,"preSum":24992},{"ndv":1558,"upper":"030900001722348","lower":"030900000934457","count":1562,"preSum":26554},{"ndv":1560,"upper":"031200002191558","lower":"030900001722513","count":1562,"preSum":28116},{"ndv":1561,"upper":"031200003018265","lower":"031200002191973","count":1562,"preSum":29678},{"ndv":1559,"upper":"031300000049637","lower":"031200003018482","count":1562,"preSum":31240},{"ndv":1561,"upper":"031300000889908","lower":"031300000051970","count":1562,"preSum":32802},{"ndv":1562,"upper":"031300001571743","lower":"031300000890058","count":1562,"preSum":34364},{"ndv":1559,"upper":"031400000364716","lower":"031300001571790","count":1562,"preSum":35926},{"ndv":1556,"upper":"031400001114156","lower":"031400000365234","count":1562,"preSum":37488},{"ndv":1549,"upper":"031500000151833","lower":"031400001114157","count":1562,"preSum":39050},{"ndv":1559,"upper":"031600000014406","lower":"031500000151834","count":1562,"preSum":40612},{"ndv":1559,"upper":"031600000891548","lower":"031600000014867","count":1562,"preSum":42174},{"ndv":1561,"upper":"031700000500575","lower":"031600000891584","count":1562,"preSum":43736},{"ndv":1558,"upper":"031800000527291","lower":"031700000501463","count":1562,"preSum":45298},{"ndv":1562,"upper":"031800001392125","lower":"031800000527523","count":1562,"preSum":46860},{"ndv":1559,"upper":"031900000151589","lower":"031800001393190","count":1562,"preSum":48422},{"ndv":1554,"upper":"031900000932516","lower":"031900000151632","count":1562,"preSum":49984},{"ndv":1558,"upper":"031900001620305","lower":"031900000932931","count":1562,"preSum":51546},{"ndv":1555,"upper":"031900002334544","lower":"031900001620479","count":1562,"preSum":53108},{"ndv":1560,"upper":"032000001166017","lower":"031900002334547","count":1562,"preSum":54670},{"ndv":1561,"upper":"035100000188912","lower":"032000001166101","count":1562,"preSum":56232},{"ndv":1560,"upper":"035100000830362","lower":"035100000188950","count":1562,"preSum":57794},{"ndv":1558,"upper":"035200000468870","lower":"035100000830944","count":1562,"preSum":59356},{"ndv":1562,"upper":"035200001113760","lower":"035200000470150","count":1562,"preSum":60918},{"ndv":1561,"upper":"035200001917786","lower":"035200001113916","count":1562,"preSum":62480},{"ndv":1560,"upper":"035300000464241","lower":"035200001918786","count":1562,"preSum":64042},{"ndv":1562,"upper":"107455409","lower":"035300000464894","count":1562,"preSum":65604},{"ndv":1559,"upper":"1111111113417727","lower":"107455457","count":1562,"preSum":67166},{"ndv":1561,"upper":"1111111115010827","lower":"1111111113418061","count":1562,"preSum":68728},{"ndv":1557,"upper":"1111111116047531","lower":"1111111115010846","count":1562,"preSum":70290},{"ndv":1562,"upper":"1111111117194272","lower":"1111111116047541","count":1562,"preSum":71852},{"ndv":1555,"upper":"1111111118495772","lower":"1111111117194757","count":1562,"preSum":73414},{"ndv":1555,"upper":"1111111119756914","lower":"1111111118496612","count":1562,"preSum":74976},{"ndv":1551,"upper":"1111111121018733","lower":"1111111119760569","count":1562,"preSum":76538},{"ndv":1548,"upper":"1111111128825959","lower":"1111111121018904","count":1562,"preSum":78100},{"ndv":1548,"upper":"1111111130115744","lower":"1111111128827867","count":1562,"preSum":79662},{"ndv":1549,"upper":"1111111131634540","lower":"1111111130116078","count":1562,"preSum":81224},{"ndv":1556,"upper":"1111111133142450","lower":"1111111131634823","count":1562,"preSum":82786},{"ndv":1558,"upper":"12405954","lower":"1111111133142823","count":1562,"preSum":84348},{"ndv":1555,"upper":"1511111140907122","lower":"124063064","count":1562,"preSum":85910},{"ndv":1558,"upper":"1511111142059149","lower":"1511111140908048","count":1562,"preSum":87472},{"ndv":1540,"upper":"1511111143155657","lower":"1511111142059417","count":1562,"preSum":89034},{"ndv":1523,"upper":"1511111144187610","lower":"1511111143156755","count":1562,"preSum":90596},{"ndv":1538,"upper":"21536981","lower":"1511111144188514","count":1562,"preSum":92158},{"ndv":1561,"upper":"50047775","lower":"21542339","count":1562,"preSum":93720},{"ndv":1562,"upper":"75333898","lower":"50053087","count":1562,"preSum":95282},{"ndv":1562,"upper":"JL1133521","lower":"75340548","count":1562,"preSum":96844},{"ndv":1553,"upper":"JL999139","lower":"JL1133554","count":1553,"preSum":98406}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[6,5,5,5,5,5,5,6],"valueArr":["031400001431403","031700000747333","031800001629590","1111111116753783","1111111128449284","1511111144262727","1511111144672740","1511111144847886"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_run_term_id',1800084,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1437,"upper":"035188000528337","lower":"030200001298899","count":1562,"preSum":0},{"ndv":1196,"upper":"1111111115996902","lower":"035188000528615","count":1562,"preSum":1562},{"ndv":1159,"upper":"1111111117328020","lower":"1111111115996927","count":1563,"preSum":3124},{"ndv":1056,"upper":"1111111117365241","lower":"1111111117328022","count":1562,"preSum":4687},{"ndv":1188,"upper":"1111111117540827","lower":"1111111117365258","count":1562,"preSum":6249},{"ndv":1224,"upper":"1111111117600721","lower":"1111111117540908","count":1565,"preSum":7811},{"ndv":1126,"upper":"1111111117749711","lower":"1111111117600723","count":1563,"preSum":9376},{"ndv":1228,"upper":"1111111117945136","lower":"1111111117749712","count":1562,"preSum":10939},{"ndv":1137,"upper":"1111111118012751","lower":"1111111117945141","count":1562,"preSum":12501},{"ndv":1159,"upper":"1111111118253131","lower":"1111111118012752","count":1562,"preSum":14063},{"ndv":1151,"upper":"1111111118831106","lower":"1111111118253186","count":1562,"preSum":15625},{"ndv":1158,"upper":"1111111119242948","lower":"1111111118831142","count":1562,"preSum":17187},{"ndv":1195,"upper":"1111111119581678","lower":"1111111119242949","count":1562,"preSum":18749},{"ndv":1139,"upper":"1111111119899015","lower":"1111111119581695","count":1562,"preSum":20311},{"ndv":1169,"upper":"1111111119988608","lower":"1111111119899019","count":1562,"preSum":21873},{"ndv":1148,"upper":"1111111119999354","lower":"1111111119988611","count":1562,"preSum":23435},{"ndv":1153,"upper":"1111111120042378","lower":"1111111119999358","count":1562,"preSum":24997},{"ndv":1146,"upper":"1111111120084860","lower":"1111111120042393","count":1562,"preSum":26559},{"ndv":1153,"upper":"1111111120130427","lower":"1111111120084862","count":1562,"preSum":28121},{"ndv":1158,"upper":"1111111120172240","lower":"1111111120130837","count":1563,"preSum":29683},{"ndv":1167,"upper":"1111111120228834","lower":"1111111120172246","count":1562,"preSum":31246},{"ndv":1189,"upper":"1111111120264389","lower":"1111111120228848","count":1562,"preSum":32808},{"ndv":1182,"upper":"1111111120290786","lower":"1111111120264419","count":1564,"preSum":34370},{"ndv":1147,"upper":"1111111120311701","lower":"1111111120290797","count":1562,"preSum":35934},{"ndv":1120,"upper":"1111111120333862","lower":"1111111120311702","count":1562,"preSum":37496},{"ndv":1105,"upper":"1111111120355318","lower":"1111111120333873","count":1562,"preSum":39058},{"ndv":1164,"upper":"1111111120390524","lower":"1111111120355319","count":1562,"preSum":40620},{"ndv":1137,"upper":"1111111120423885","lower":"1111111120390538","count":1562,"preSum":42182},{"ndv":1116,"upper":"1111111120444937","lower":"1111111120423903","count":1562,"preSum":43744},{"ndv":1146,"upper":"1111111120471747","lower":"1111111120444946","count":1562,"preSum":45306},{"ndv":1182,"upper":"1111111120513548","lower":"1111111120471755","count":1562,"preSum":46868},{"ndv":1168,"upper":"1111111120553131","lower":"1111111120513561","count":1562,"preSum":48430},{"ndv":1172,"upper":"1111111120593097","lower":"1111111120553135","count":1562,"preSum":49992},{"ndv":1165,"upper":"1111111120642931","lower":"1111111120593113","count":1562,"preSum":51554},{"ndv":1150,"upper":"1111111120687622","lower":"1111111120642939","count":1562,"preSum":53116},{"ndv":1076,"upper":"1111111120745765","lower":"1111111120687628","count":1562,"preSum":54678},{"ndv":1180,"upper":"1111111120809331","lower":"1111111120745772","count":1562,"preSum":56240},{"ndv":1179,"upper":"1111111120863716","lower":"1111111120809389","count":1563,"preSum":57802},{"ndv":1174,"upper":"1111111120949004","lower":"1111111120863745","count":1565,"preSum":59365},{"ndv":1200,"upper":"1111111121036338","lower":"1111111120949007","count":1564,"preSum":60930},{"ndv":1157,"upper":"1111111121105312","lower":"1111111121036725","count":1562,"preSum":62494},{"ndv":1160,"upper":"1111111121201150","lower":"1111111121105394","count":1563,"preSum":64056},{"ndv":1178,"upper":"1111111121436393","lower":"1111111121201175","count":1563,"preSum":65619},{"ndv":1158,"upper":"1111111128311182","lower":"1111111121437363","count":1562,"preSum":67182},{"ndv":1149,"upper":"1111111128949518","lower":"1111111128311369","count":1562,"preSum":68744},{"ndv":1152,"upper":"1111111129711420","lower":"1111111128949522","count":1562,"preSum":70306},{"ndv":1175,"upper":"1111111130458414","lower":"1111111129712568","count":1562,"preSum":71868},{"ndv":1139,"upper":"1111111131592489","lower":"1111111130458497","count":1562,"preSum":73430},{"ndv":1146,"upper":"1111111132316902","lower":"1111111131592728","count":1562,"preSum":74992},{"ndv":1197,"upper":"1111111133207817","lower":"1111111132317216","count":1562,"preSum":76554},{"ndv":1187,"upper":"1511111140205768","lower":"1111111133207860","count":1564,"preSum":78116},{"ndv":1187,"upper":"1511111140636850","lower":"1511111140206421","count":1562,"preSum":79680},{"ndv":1170,"upper":"1511111141025503","lower":"1511111140636864","count":1562,"preSum":81242},{"ndv":1186,"upper":"1511111141491917","lower":"1511111141025521","count":1562,"preSum":82804},{"ndv":1152,"upper":"1511111141895010","lower":"1511111141492206","count":1562,"preSum":84366},{"ndv":1127,"upper":"1511111142306761","lower":"1511111141895011","count":1562,"preSum":85928},{"ndv":1107,"upper":"1511111142696792","lower":"1511111142307259","count":1562,"preSum":87490},{"ndv":1111,"upper":"1511111143102857","lower":"1511111142697025","count":1564,"preSum":89052},{"ndv":1157,"upper":"1511111143499394","lower":"1511111143103601","count":1562,"preSum":90616},{"ndv":1152,"upper":"1511111143758487","lower":"1511111143499395","count":1562,"preSum":92178},{"ndv":1194,"upper":"1511111144062087","lower":"1511111143758551","count":1562,"preSum":93740},{"ndv":1164,"upper":"1511111144188497","lower":"1511111144062341","count":1562,"preSum":95302},{"ndv":1232,"upper":"1511111144412538","lower":"1511111144188499","count":1562,"preSum":96864},{"ndv":1143,"upper":"1511111145311836","lower":"1511111144412540","count":1538,"preSum":98426}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[9,9,9,10],"valueArr":["1111111119999101","1111111120622766","1111111120879223","1511111142034639"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_time_digit_code',15,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"62.0","lower":"62.0","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1019,846,69,2319,5945,2496,54,15359,12197,41687,599,296,175,3466],"valueArr":["40","41","42","50","51","52","6.2","60","61","62","64","70","82","99"],"type":"String","sampleRate":0.924351804778851}',13472,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','mr_total_factor',239,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":4,"upper":10.000,"lower":3.000,"count":41,"preSum":0},{"ndv":2,"upper":50.000,"lower":24.000,"count":40,"preSum":41},{"ndv":1,"upper":120.000,"lower":120.000,"count":61,"preSum":81},{"ndv":1,"upper":150.000,"lower":150.000,"count":75,"preSum":142},{"ndv":1,"upper":160.000,"lower":160.000,"count":32,"preSum":217},{"ndv":1,"upper":240.000,"lower":240.000,"count":23,"preSum":249},{"ndv":2,"upper":500.000,"lower":250.000,"count":14,"preSum":272},{"ndv":1,"upper":800.000,"lower":800.000,"count":26,"preSum":286},{"ndv":3,"upper":1500.000,"lower":1050.000,"count":77,"preSum":312},{"ndv":2,"upper":2000.000,"lower":1600.000,"count":44,"preSum":389},{"ndv":2,"upper":3000.000,"lower":2400.000,"count":39,"preSum":433},{"ndv":2,"upper":4000.000,"lower":3500.000,"count":22,"preSum":472},{"ndv":1,"upper":6000.000,"lower":6000.000,"count":21,"preSum":494},{"ndv":2,"upper":8000.000,"lower":7000.000,"count":29,"preSum":515},{"ndv":2,"upper":12000.000,"lower":10000.000,"count":36,"preSum":544},{"ndv":5,"upper":40000.000,"lower":20000.000,"count":13,"preSum":580},{"ndv":2,"upper":60000.000,"lower":50000.000,"count":28,"preSum":593},{"ndv":3,"upper":110000.000,"lower":80000.000,"count":12,"preSum":621},{"ndv":4,"upper":1320000.000,"lower":132000.000,"count":5,"preSum":633}],"maxBucketSize":64,"type":"Double","sampleRate":0.9243518}','{"countArr":[763,96140,87,520,170,479,148,120,246,221,137,98,120,114],"valueArr":[0.000,1.000,15.000,20.000,30.000,40.000,60.000,80.000,100.000,200.000,300.000,400.000,600.000,1000.000],"type":"Double","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','new_industry_code',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','new_infrastruct_sign',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','nine_elec_sort_code',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','operated_time',1983673,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":664,"upper":"1843857561355288576","lower":"1843645821044654080","count":1393,"preSum":0},{"ndv":236,"upper":"1843930763955798016","lower":"1843864050245566464","count":1375,"preSum":1393},{"ndv":1138,"upper":"1844090575226142720","lower":"1843932226241167360","count":1349,"preSum":2768},{"ndv":1153,"upper":"1844372190342938624","lower":"1844090584604606464","count":1349,"preSum":4117},{"ndv":1132,"upper":"1844568386260959232","lower":"1844372225440874496","count":1349,"preSum":5466},{"ndv":1148,"upper":"1844746009700204544","lower":"1844568553982787584","count":1350,"preSum":6815},{"ndv":1165,"upper":"1844917822552014848","lower":"1844746202369753088","count":1349,"preSum":8165},{"ndv":1156,"upper":"1845060318141612032","lower":"1844917831578157056","count":1349,"preSum":9514},{"ndv":1149,"upper":"1845227820205211648","lower":"1845060332821676032","count":1350,"preSum":10863},{"ndv":1126,"upper":"1845333525876703232","lower":"1845228186082738176","count":1350,"preSum":12213},{"ndv":1131,"upper":"1845434569864511488","lower":"1845333529701908480","count":1349,"preSum":13563},{"ndv":1128,"upper":"1845518220660834304","lower":"1845434570451714048","count":1349,"preSum":14912},{"ndv":1153,"upper":"1845623294938578944","lower":"1845518256043982848","count":1350,"preSum":16261},{"ndv":1167,"upper":"1845724699351318528","lower":"1845623301951455232","count":1350,"preSum":17611},{"ndv":1158,"upper":"1845815065245122560","lower":"1845724757148827648","count":1349,"preSum":18961},{"ndv":1154,"upper":"1845909155915759616","lower":"1845815098883440640","count":1349,"preSum":20310},{"ndv":1180,"upper":"1845991036262809600","lower":"1845909169069096960","count":1350,"preSum":21659},{"ndv":1186,"upper":"1846142638659469312","lower":"1845991045658050560","count":1349,"preSum":23009},{"ndv":1191,"upper":"1846230798533918720","lower":"1846142642165907456","count":1349,"preSum":24358},{"ndv":1164,"upper":"1846347673234309120","lower":"1846237274035978240","count":1349,"preSum":25707},{"ndv":1164,"upper":"1846461073977245696","lower":"1846348869382701056","count":1353,"preSum":27056},{"ndv":1105,"upper":"1846584281825017856","lower":"1846461073994022912","count":1349,"preSum":28409},{"ndv":961,"upper":"1846663417671188480","lower":"1846584299122327552","count":1351,"preSum":29758},{"ndv":1189,"upper":"1846815565411254272","lower":"1846663463003226112","count":1349,"preSum":31109},{"ndv":1091,"upper":"1846940472052809728","lower":"1846815568414375936","count":1351,"preSum":32458},{"ndv":1056,"upper":"1847134534278053888","lower":"1846940472069586944","count":1349,"preSum":33809},{"ndv":1139,"upper":"1847290598088769536","lower":"1847136154957119488","count":1350,"preSum":35158},{"ndv":1162,"upper":"1847405008149020672","lower":"1847290665113747456","count":1350,"preSum":36508},{"ndv":1028,"upper":"1847558524524036096","lower":"1847405018097909760","count":1350,"preSum":37858},{"ndv":1089,"upper":"1847718837819015168","lower":"1847558524540813312","count":1349,"preSum":39208},{"ndv":1102,"upper":"1847869006854225920","lower":"1847718888502984704","count":1350,"preSum":40557},{"ndv":1120,"upper":"1848154478801321984","lower":"1847869092770349056","count":1349,"preSum":41907},{"ndv":1052,"upper":"1848282424467783680","lower":"1848154480764256256","count":1349,"preSum":43256},{"ndv":1086,"upper":"1848396651320836096","lower":"1848282514108448768","count":1349,"preSum":44605},{"ndv":1045,"upper":"1848488997412667392","lower":"1848396655229927424","count":1349,"preSum":45954},{"ndv":1021,"upper":"1848579441253416960","lower":"1848489000919105536","count":1349,"preSum":47303},{"ndv":1112,"upper":"1848693268590624768","lower":"1848579521129742336","count":1349,"preSum":48652},{"ndv":949,"upper":"1848779245279510528","lower":"1848693282666708992","count":1351,"preSum":50001},{"ndv":1154,"upper":"1848987731531661312","lower":"1848779249306042368","count":1349,"preSum":51352},{"ndv":1002,"upper":"1849116320017154048","lower":"1848987805368188928","count":1409,"preSum":52701},{"ndv":1021,"upper":"1849239014146572288","lower":"1849116990115938304","count":1349,"preSum":54110},{"ndv":1153,"upper":"1849365961468018688","lower":"1849239019599167488","count":1349,"preSum":55459},{"ndv":1147,"upper":"1849468048596008960","lower":"1849365974470361088","count":1349,"preSum":56808},{"ndv":1094,"upper":"1849564720676208640","lower":"1849468817076387840","count":1351,"preSum":58157},{"ndv":1077,"upper":"1849636370327273472","lower":"1849564751428845568","count":1349,"preSum":59508},{"ndv":1092,"upper":"1849711702594027520","lower":"1849636395560206336","count":1349,"preSum":60857},{"ndv":894,"upper":"1849889479410581504","lower":"1849711715143385088","count":1350,"preSum":62206},{"ndv":1123,"upper":"1849997585180262400","lower":"1849889499157364736","count":1349,"preSum":63556},{"ndv":1172,"upper":"1850094367788761088","lower":"1849997639035125760","count":1349,"preSum":64905},{"ndv":1070,"upper":"1850181985641693184","lower":"1850094374600310784","count":1349,"preSum":66254},{"ndv":1115,"upper":"1850255000622596096","lower":"1850181991094288384","count":1349,"preSum":67603},{"ndv":1108,"upper":"1850319059774603264","lower":"1850255019664736256","count":1349,"preSum":68952},{"ndv":1078,"upper":"1850382394251542528","lower":"1850320405709979648","count":1349,"preSum":70301},{"ndv":1040,"upper":"1850424031073796096","lower":"1850382407086112768","count":1349,"preSum":71650},{"ndv":1071,"upper":"1850496795067547648","lower":"1850428150366863360","count":1349,"preSum":72999},{"ndv":1034,"upper":"1850537460841316352","lower":"1850496795084324864","count":1349,"preSum":74348},{"ndv":1033,"upper":"1850584877380927488","lower":"1850537481041084416","count":1349,"preSum":75697},{"ndv":1034,"upper":"1850725444010115072","lower":"1850584929574846464","count":1349,"preSum":77046},{"ndv":1156,"upper":"1850831019440078848","lower":"1850725445486510080","count":1350,"preSum":78395},{"ndv":1141,"upper":"1850901870176894976","lower":"1850831045360877568","count":1349,"preSum":79745},{"ndv":1118,"upper":"1850962949376573440","lower":"1850902484457881600","count":1349,"preSum":81094},{"ndv":1127,"upper":"1851020222933237760","lower":"1850962960030105600","count":1349,"preSum":82443},{"ndv":1124,"upper":"1851064115066306560","lower":"1851020231422509056","count":1349,"preSum":83792},{"ndv":979,"upper":"1851243681844035584","lower":"1851064116123271168","count":1164,"preSum":85141}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.9243518}','{"countArr":[1698,906,1282,1511,1675,1108,495,893,450,571,446,502,1333,826],"valueArr":[1843646895558230016,1843856884344291328,1843857255137542144,1843857460457111552,1843857639268679680,1843857676212109312,1843930504043167744,1843930527917146112,1843930583986601984,1843930672872292352,1843930688860979200,1843930776589041664,1849061344435765248,1849696862156619776],"type":"Datetime","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','org_path',1371,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":29,"upper":"00/03/0302/030210/03021011","lower":"00/03/0302/030202","count":1650,"preSum":0},{"ndv":21,"upper":"00/03/0302/030215/03021507","lower":"00/03/0302/030210/03021012","count":1431,"preSum":1650},{"ndv":24,"upper":"00/03/0304/030401/03040105","lower":"00/03/0302/030215/03021509","count":1437,"preSum":3081},{"ndv":9,"upper":"00/03/0304/030403/03040304","lower":"00/03/0304/030401/03040106","count":1479,"preSum":4518},{"ndv":9,"upper":"00/03/0305/030523/03052308","lower":"00/03/0304/030403/03040306","count":1406,"preSum":5997},{"ndv":14,"upper":"00/03/0305/030547/03054709","lower":"00/03/0305/030526/03052603","count":1519,"preSum":7403},{"ndv":14,"upper":"00/03/0305/030548/03054812","lower":"00/03/0305/030547/03054710","count":1414,"preSum":8922},{"ndv":12,"upper":"00/03/0305/030549/03054910","lower":"00/03/0305/030548/03054813","count":1475,"preSum":10336},{"ndv":11,"upper":"00/03/0306/030612/03061213","lower":"00/03/0305/030549/03054911","count":1580,"preSum":11811},{"ndv":5,"upper":"00/03/0306/030613/03061311","lower":"00/03/0306/030612/03061214","count":1714,"preSum":13391},{"ndv":7,"upper":"00/03/0306/030613/03061318","lower":"00/03/0306/030613/03061312","count":1533,"preSum":15105},{"ndv":15,"upper":"00/03/0307/030702/03070207","lower":"00/03/0306/030613/03061319","count":1455,"preSum":16638},{"ndv":13,"upper":"00/03/0307/030704/03070408","lower":"00/03/0307/030702/03070211","count":1441,"preSum":18093},{"ndv":25,"upper":"00/03/0307/030706/03070614","lower":"00/03/0307/030704/03070410","count":1463,"preSum":19534},{"ndv":18,"upper":"00/03/0307/030713/03071316","lower":"00/03/0307/030706/03070615","count":1446,"preSum":20997},{"ndv":8,"upper":"00/03/0308/030801/03080105","lower":"00/03/0307/030714","count":1489,"preSum":22443},{"ndv":18,"upper":"00/03/0308/030810/03081015","lower":"00/03/0308/030801/03080106","count":1424,"preSum":23932},{"ndv":21,"upper":"00/03/0308/030814/03081415","lower":"00/03/0308/030810/03081016","count":1505,"preSum":25356},{"ndv":20,"upper":"00/03/0308/030820/03082032","lower":"00/03/0308/030814/03081417","count":1408,"preSum":26861},{"ndv":18,"upper":"00/03/0308/030828/03082825","lower":"00/03/0308/030820/03082033","count":1442,"preSum":28269},{"ndv":23,"upper":"00/03/0309/030902/03090256","lower":"00/03/0308/030830/03083004","count":1427,"preSum":29711},{"ndv":25,"upper":"00/03/0309/030909/03090902","lower":"00/03/0309/030902/03090257","count":1463,"preSum":31138},{"ndv":21,"upper":"00/03/0309/030910/03091006","lower":"00/03/0309/030909/03090903","count":1537,"preSum":32601},{"ndv":23,"upper":"00/03/0309/030916/03091612","lower":"00/03/0309/030910/03091017","count":1460,"preSum":34138},{"ndv":13,"upper":"00/03/0312/031203/03120305","lower":"00/03/0309/030916/03091613","count":1504,"preSum":35598},{"ndv":14,"upper":"00/03/0312/031206/03120607","lower":"00/03/0312/031203/03120308","count":1780,"preSum":37102},{"ndv":20,"upper":"00/03/0313/031302/03130202","lower":"00/03/0312/031209/03120907","count":1445,"preSum":38882},{"ndv":7,"upper":"00/03/0313/031302/03130223","lower":"00/03/0313/031302/03130210","count":1453,"preSum":40327},{"ndv":14,"upper":"00/03/0313/031304/03130415","lower":"00/03/0313/031302/03130225","count":1824,"preSum":41780},{"ndv":20,"upper":"00/03/0313/031313/03131312","lower":"00/03/0313/031304/03130418","count":1508,"preSum":43604},{"ndv":20,"upper":"00/03/0313/031314/03131423","lower":"00/03/0313/031313/03131317","count":1751,"preSum":45112},{"ndv":14,"upper":"00/03/0314/031401/03140117","lower":"00/03/0313/031316/03131602","count":1419,"preSum":46863},{"ndv":26,"upper":"00/03/0314/031406/03140617","lower":"00/03/0314/031401/03140118","count":1441,"preSum":48282},{"ndv":34,"upper":"00/03/0314/031410/03141009","lower":"00/03/0314/031406/03140619","count":1531,"preSum":49723},{"ndv":27,"upper":"00/03/0315/031502/03150219","lower":"00/03/0314/031410/03141010","count":1442,"preSum":51254},{"ndv":28,"upper":"00/03/0315/031504/03150420","lower":"00/03/0315/031502/03150221","count":1633,"preSum":52696},{"ndv":29,"upper":"00/03/0316/031609/03160922","lower":"00/03/0315/031510/03151003","count":1449,"preSum":54329},{"ndv":50,"upper":"00/03/0316/031626/03162614","lower":"00/03/0316/031609/03160923","count":1427,"preSum":55778},{"ndv":20,"upper":"00/03/0317/031704/03170430","lower":"00/03/0316/031633/03163302","count":1765,"preSum":57205},{"ndv":21,"upper":"00/03/0317/031710/03171015","lower":"00/03/0317/031705/03170507","count":1407,"preSum":58970},{"ndv":9,"upper":"00/03/0318/031801/03180107","lower":"00/03/0317/031710/03171016","count":1705,"preSum":60377},{"ndv":21,"upper":"00/03/0318/031826/03182601","lower":"00/03/0318/031801/03180108","count":1448,"preSum":62082},{"ndv":25,"upper":"00/03/0318/031881/03188116","lower":"00/03/0318/031826/03182602","count":1482,"preSum":63530},{"ndv":23,"upper":"00/03/0319/031969/03196906","lower":"00/03/0318/031881/03188117","count":1636,"preSum":65012},{"ndv":6,"upper":"00/03/0319/031971/03197111","lower":"00/03/0319/031969/03196914","count":1518,"preSum":66648},{"ndv":10,"upper":"00/03/0319/031973/03197309","lower":"00/03/0319/031971/03197112","count":1447,"preSum":68166},{"ndv":5,"upper":"00/03/0319/031975/03197506","lower":"00/03/0319/031973/03197310","count":1773,"preSum":69613},{"ndv":5,"upper":"00/03/0320/032014","lower":"00/03/0319/031975/03197507","count":1629,"preSum":71386},{"ndv":6,"upper":"00/03/0320/032020","lower":"00/03/0320/032015","count":1503,"preSum":73015},{"ndv":9,"upper":"00/03/0320/032029","lower":"00/03/0320/032021","count":1556,"preSum":74518},{"ndv":24,"upper":"00/03/0351/035105/03510525","lower":"00/03/0320/032030","count":1413,"preSum":76074},{"ndv":16,"upper":"00/03/0351/035109/03510917","lower":"00/03/0351/035105/03510526","count":1467,"preSum":77487},{"ndv":12,"upper":"00/03/0352/035202/03520218","lower":"00/03/0351/035109/03510918","count":1671,"preSum":78954},{"ndv":16,"upper":"00/03/0352/035203/03520316","lower":"00/03/0352/035202/03520224","count":1542,"preSum":80625},{"ndv":15,"upper":"00/03/0352/035206/03520619","lower":"00/03/0352/035206/03520603","count":1519,"preSum":82167},{"ndv":14,"upper":"00/03/0352/035207/03520707","lower":"00/03/0352/035206/03520620","count":1461,"preSum":83686},{"ndv":24,"upper":"00/03/0352/035215/03521519","lower":"00/03/0352/035207/03520709","count":1509,"preSum":85147},{"ndv":24,"upper":"00/03/0353/035304/03530423","lower":"00/03/0352/035215/03521524","count":1421,"preSum":86656},{"ndv":33,"upper":"00/03/0353/035313/03531318","lower":"00/03/0353/035304/03530424","count":1442,"preSum":88077},{"ndv":6,"upper":"00/03/0353/035313/03531324","lower":"00/03/0353/035313/03531319","count":238,"preSum":89519}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[643,1259,790,674,555,868,506,554,572,566,672,721,715,1149],"valueArr":["00/03/0305/030523/03052307","00/03/0306/030603/03060306","00/03/0306/030612/03061211","00/03/0306/030612/03061218","00/03/0306/030613/03061320","00/03/0306/030614/03061405","00/03/0306/030615/03061507","00/03/0307/030706/03070624","00/03/0309/030916/03091616","00/03/0312/031209/03120926","00/03/0313/031303/03130309","00/03/0313/031306/03130616","00/03/0317/031710/03171013","00/03/0319/031969/03196901"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','phase_line_code',31,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"3","lower":"3","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[86767,488,10932,9],"valueArr":["01","02","03","1"],"type":"String","sampleRate":0.924351804778851}',1804,0.0026470406); - INSERT INTO metadb.column_statistics (`SCHEMA_NAME`, `TABLE_NAME`, `COLUMN_NAME`, `CARDINALITY`, `CMSKETCH`, `HISTOGRAM`, `TOPN`, `NULL_COUNT`, `SAMPLE_RATE`) VALUES ('gdcams_tp','mk_cu_elec_cust_mr_comp_view','power_date',1047865,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":360,"upper":"1825176107968626688","lower":"1739491166816043008","count":1367,"preSum":0},{"ndv":567,"upper":"1828778108061220864","lower":"1825202496247693312","count":1227,"preSum":1367},{"ndv":218,"upper":"1829387237503008768","lower":"1828780307084476416","count":1227,"preSum":2594},{"ndv":256,"upper":"1830086526898274304","lower":"1829389436526264320","count":1229,"preSum":3821},{"ndv":310,"upper":"1830928752805150720","lower":"1830088725921529856","count":1227,"preSum":5050},{"ndv":373,"upper":"1831831008396181504","lower":"1830933150851661824","count":1227,"preSum":6277},{"ndv":233,"upper":"1832316336479404032","lower":"1831831374407925760","count":1244,"preSum":7504},{"ndv":298,"upper":"1833031019037458432","lower":"1832318535502659584","count":1236,"preSum":8748},{"ndv":353,"upper":"1833703920153657344","lower":"1833037616107225088","count":1228,"preSum":9984},{"ndv":458,"upper":"1834379020293111808","lower":"1833704553728442368","count":1228,"preSum":11212},{"ndv":407,"upper":"1834841558088679424","lower":"1834379802883129344","count":1227,"preSum":12440},{"ndv":328,"upper":"1835155893977612288","lower":"1834841591894769664","count":1240,"preSum":13667},{"ndv":434,"upper":"1835463138758098944","lower":"1835155896125095936","count":1240,"preSum":14907},{"ndv":540,"upper":"1835867759037120512","lower":"1835463911566999552","count":1229,"preSum":16147},{"ndv":725,"upper":"1836487883595186176","lower":"1835868482487451648","count":1227,"preSum":17376},{"ndv":743,"upper":"1836859518525374464","lower":"1836487952314662912","count":1229,"preSum":18603},{"ndv":644,"upper":"1837438612455555072","lower":"1836860749419380736","count":1227,"preSum":19832},{"ndv":297,"upper":"1837745724897361920","lower":"1837438859298734080","count":1301,"preSum":21059},{"ndv":185,"upper":"1837928243827572736","lower":"1837752963779526656","count":1283,"preSum":22360},{"ndv":239,"upper":"1838073379362439168","lower":"1837928276039827456","count":1228,"preSum":23643},{"ndv":659,"upper":"1838568159594938368","lower":"1838073952958676992","count":1229,"preSum":24871},{"ndv":206,"upper":"1838711096106549248","lower":"1838568828016001024","count":1229,"preSum":26100},{"ndv":590,"upper":"1839161895873937408","lower":"1838711744562724864","count":1616,"preSum":27329},{"ndv":440,"upper":"1839410385501814784","lower":"1839163055347335168","count":1233,"preSum":28945},{"ndv":508,"upper":"1839727044850614272","lower":"1839411318415687680","count":1229,"preSum":30178},{"ndv":655,"upper":"1840052500292435968","lower":"1839729243873869824","count":1230,"preSum":31407},{"ndv":766,"upper":"1840479879485718528","lower":"1840053136853565440","count":1227,"preSum":32637},{"ndv":1033,"upper":"1841044818428428288","lower":"1840480172868894720","count":1227,"preSum":33864},{"ndv":1054,"upper":"1841395113008300032","lower":"1841044967493992448","count":1227,"preSum":35091},{"ndv":916,"upper":"1841852064628473856","lower":"1841396103501578240","count":1227,"preSum":36318},{"ndv":857,"upper":"1842244926478221312","lower":"1841852311337435136","count":1230,"preSum":37545},{"ndv":797,"upper":"1842664939920031744","lower":"1842245574598852608","count":1229,"preSum":38775},{"ndv":809,"upper":"1843062963129286656","lower":"1842665563243937792","count":1231,"preSum":40004},{"ndv":812,"upper":"1843475282925715456","lower":"1843063614336925696","count":1227,"preSum":41235},{"ndv":832,"upper":"1843900790989651968","lower":"1843476379501330432","count":1227,"preSum":42462},{"ndv":1016,"upper":"1844220373516681216","lower":"1843901537642872832","count":1227,"preSum":43689},{"ndv":1082,"upper":"1844590607448670208","lower":"1844220376503025664","count":1227,"preSum":44916},{"ndv":1095,"upper":"1844862960116170752","lower":"1844592133386797056","count":1227,"preSum":46143},{"ndv":1086,"upper":"1845100377284804608","lower":"1844862962934743040","count":1228,"preSum":47370},{"ndv":1046,"upper":"1845385972812873728","lower":"1845100378660536320","count":1227,"preSum":48598},{"ndv":1100,"upper":"1845626050831187968","lower":"1845386136373952512","count":1228,"preSum":49825},{"ndv":1065,"upper":"1845832537893502976","lower":"1845626054941605888","count":1227,"preSum":51053},{"ndv":1076,"upper":"1846012727793811456","lower":"1845832590775287808","count":1227,"preSum":52280},{"ndv":1064,"upper":"1846254771346866176","lower":"1846012774937788416","count":1227,"preSum":53507},{"ndv":1094,"upper":"1846461605211013120","lower":"1846254781782294528","count":1227,"preSum":54734},{"ndv":1019,"upper":"1846683270217990144","lower":"1846461698978873344","count":1228,"preSum":55961},{"ndv":429,"upper":"1846920049919524864","lower":"1846683570832146432","count":1235,"preSum":57189},{"ndv":346,"upper":"1847210870745071616","lower":"1846920700607070208","count":1227,"preSum":58424},{"ndv":347,"upper":"1847452213547368448","lower":"1847210998570680320","count":1232,"preSum":59651},{"ndv":336,"upper":"1847655210881646592","lower":"1847452832022659072","count":1227,"preSum":60883},{"ndv":368,"upper":"1847855253278425088","lower":"1847655575953866752","count":1227,"preSum":62110},{"ndv":467,"upper":"1848228468756578304","lower":"1847855321997901824","count":1232,"preSum":63337},{"ndv":530,"upper":"1848459366198411264","lower":"1848229087231868928","count":1227,"preSum":64569},{"ndv":570,"upper":"1848650681221644288","lower":"1848459948166479872","count":1229,"preSum":65796},{"ndv":666,"upper":"1848908585417834496","lower":"1848651299696934912","count":1228,"preSum":67025},{"ndv":768,"upper":"1849179688048525312","lower":"1848910165965799424","count":1227,"preSum":68253},{"ndv":761,"upper":"1849417109545680896","lower":"1849180645826232320","count":1227,"preSum":69480},{"ndv":855,"upper":"1849662943474483200","lower":"1849417142194143232","count":1227,"preSum":70707},{"ndv":903,"upper":"1849979632787390464","lower":"1849662987833442304","count":1227,"preSum":71934},{"ndv":974,"upper":"1850227380895875072","lower":"1849979637552119808","count":1228,"preSum":73161},{"ndv":983,"upper":"1850434089081896960","lower":"1850228342968549376","count":1228,"preSum":74389},{"ndv":946,"upper":"1850712158149541888","lower":"1850435229429268480","count":1227,"preSum":75617},{"ndv":1055,"upper":"1851003636105084928","lower":"1850712165665734656","count":1227,"preSum":76844},{"ndv":353,"upper":"1929840818839879680","lower":"1851004239547990016","count":411,"preSum":78071}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.9243518}','{"countArr":[709,2281,952,2948,1629,1388,1362,2406,596,1481,1865,1916,710,1276],"valueArr":[-1,1738180555045863424,1783638757694504960,1820511979643600896,1829659916386697216,1829739081223897088,1830293235084296192,1831597255874838528,1834283487654313984,1836978265781174272,1837611584478773248,1837752321967128576,1837893059455483904,1839159696850681856],"type":"Datetime","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','power_line_segm_id',87767,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":244,"upper":"030200000000946","lower":"0011111129266770","count":1559,"preSum":0},{"ndv":286,"upper":"030400000000374","lower":"030200000000950","count":1556,"preSum":1559},{"ndv":373,"upper":"030400000001961","lower":"030400000000375","count":1561,"preSum":3115},{"ndv":263,"upper":"030500000000747","lower":"030400000001964","count":1566,"preSum":4676},{"ndv":232,"upper":"030500000001361","lower":"030500000000748","count":1557,"preSum":6242},{"ndv":328,"upper":"030600000000308","lower":"030500000001362","count":1561,"preSum":7799},{"ndv":407,"upper":"030600000001266","lower":"030600000000310","count":1558,"preSum":9360},{"ndv":387,"upper":"030600000002248","lower":"030600000001267","count":1565,"preSum":10918},{"ndv":381,"upper":"030600000003261","lower":"030600000002249","count":1556,"preSum":12483},{"ndv":354,"upper":"030600000004229","lower":"030600000003262","count":1562,"preSum":14039},{"ndv":273,"upper":"030700000000453","lower":"030600000004230","count":1558,"preSum":15601},{"ndv":236,"upper":"030700000000945","lower":"030700000000454","count":1559,"preSum":17159},{"ndv":220,"upper":"030700000001459","lower":"030700000000947","count":1566,"preSum":18718},{"ndv":234,"upper":"030800000000131","lower":"030700000001460","count":1568,"preSum":20284},{"ndv":157,"upper":"030800000000513","lower":"030800000000132","count":1573,"preSum":21852},{"ndv":140,"upper":"030800000001115","lower":"030800000000515","count":1556,"preSum":23425},{"ndv":186,"upper":"030900000000128","lower":"030800000001116","count":1571,"preSum":24981},{"ndv":185,"upper":"030900000000691","lower":"030900000000129","count":1561,"preSum":26552},{"ndv":177,"upper":"030900000001156","lower":"030900000000696","count":1563,"preSum":28113},{"ndv":226,"upper":"031200000000237","lower":"030900000001157","count":1558,"preSum":29676},{"ndv":230,"upper":"031200000000708","lower":"031200000000238","count":1556,"preSum":31234},{"ndv":227,"upper":"031300000000023","lower":"031200000000710","count":1558,"preSum":32790},{"ndv":293,"upper":"031300000000833","lower":"031300000000026","count":1562,"preSum":34348},{"ndv":284,"upper":"031300000001582","lower":"031300000000834","count":1564,"preSum":35910},{"ndv":322,"upper":"031300000002361","lower":"031300000001584","count":1560,"preSum":37474},{"ndv":257,"upper":"031400000000331","lower":"031300000002362","count":1557,"preSum":39034},{"ndv":203,"upper":"031400000000987","lower":"031400000000333","count":1558,"preSum":40591},{"ndv":233,"upper":"031500000000132","lower":"031400000000988","count":1565,"preSum":42149},{"ndv":233,"upper":"031600000000306","lower":"031500000000133","count":1576,"preSum":43714},{"ndv":279,"upper":"031700000000108","lower":"031600000000307","count":1557,"preSum":45290},{"ndv":270,"upper":"031700000000772","lower":"031700000000111","count":1562,"preSum":46847},{"ndv":200,"upper":"031800000000482","lower":"031700000000773","count":1570,"preSum":48409},{"ndv":219,"upper":"031800000001338","lower":"031800000000483","count":1556,"preSum":49979},{"ndv":264,"upper":"031900000000277","lower":"031800000001340","count":1556,"preSum":51535},{"ndv":468,"upper":"031900000001665","lower":"031900000000278","count":1561,"preSum":53091},{"ndv":432,"upper":"031900000002742","lower":"031900000001666","count":1557,"preSum":54652},{"ndv":433,"upper":"031900000004248","lower":"031900000002777","count":1556,"preSum":56209},{"ndv":437,"upper":"032000000000214","lower":"031900000004250","count":1556,"preSum":57765},{"ndv":440,"upper":"032000000001179","lower":"032000000000216","count":1559,"preSum":59321},{"ndv":385,"upper":"035100000000130","lower":"032000000001180","count":1568,"preSum":60880},{"ndv":237,"upper":"035100000000525","lower":"035100000000131","count":1568,"preSum":62448},{"ndv":199,"upper":"035200000000822","lower":"035100000000528","count":1563,"preSum":64016},{"ndv":148,"upper":"035200000001065","lower":"035200000000826","count":1559,"preSum":65579},{"ndv":250,"upper":"035200000002006","lower":"035200000001066","count":1575,"preSum":67138},{"ndv":201,"upper":"035300000000338","lower":"035200000002007","count":1558,"preSum":68713},{"ndv":292,"upper":"1111111111551559","lower":"035300000000339","count":1562,"preSum":70271},{"ndv":249,"upper":"1111111111986561","lower":"1111111111551560","count":1560,"preSum":71833},{"ndv":254,"upper":"1111111112381578","lower":"1111111111986562","count":1561,"preSum":73393},{"ndv":295,"upper":"1111111113076586","lower":"1111111112381579","count":1560,"preSum":74954},{"ndv":255,"upper":"1111111114076579","lower":"1111111113076587","count":1558,"preSum":76514},{"ndv":256,"upper":"1111111115961600","lower":"1111111114081577","count":1556,"preSum":78072},{"ndv":283,"upper":"1111111117371596","lower":"1111111115991580","count":1559,"preSum":79628},{"ndv":260,"upper":"1111111118786606","lower":"1111111117376589","count":1557,"preSum":81187},{"ndv":277,"upper":"1111111119911600","lower":"1111111118791590","count":1560,"preSum":82744},{"ndv":264,"upper":"1111111120891592","lower":"1111111119911601","count":1559,"preSum":84304},{"ndv":285,"upper":"1111111122496598","lower":"1111111120901592","count":1556,"preSum":85863},{"ndv":267,"upper":"1111111124186772","lower":"1111111122496599","count":1556,"preSum":87419},{"ndv":286,"upper":"1111111125936782","lower":"1111111124186776","count":1556,"preSum":88975},{"ndv":295,"upper":"1111111126831775","lower":"1111111125941776","count":1561,"preSum":90531},{"ndv":289,"upper":"1111111127471777","lower":"1111111126836769","count":1557,"preSum":92092},{"ndv":297,"upper":"1111111128321835","lower":"1111111127471779","count":1562,"preSum":93649},{"ndv":340,"upper":"1111111129256788","lower":"1111111128321843","count":1558,"preSum":95211},{"ndv":307,"upper":"1111111129586810","lower":"1111111129256791","count":1576,"preSum":96769},{"ndv":246,"upper":"NFDWGD2020955570","lower":"1111111129586812","count":1179,"preSum":98345}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[51,48,47,43,44,47,51,46,52,48],"valueArr":["030800000000157","030900000000703","030900000001361","031400000000128","031800000001690","035100000000166","035200000001305","035300000000181","035300000000299","1111111112321596"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','power_type_code',8,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"30","lower":"30","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[66494,32918,26,15,30,21,3],"valueArr":["10","11","12","20","21","22","32"],"type":"String","sampleRate":0.924351804778851}',492,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','pre_level_code',15,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"17","lower":"17","count":2,"preSum":0},{"ndv":1,"upper":"20","lower":"20","count":2,"preSum":2},{"ndv":1,"upper":"24","lower":"24","count":2,"preSum":4},{"ndv":1,"upper":"50","lower":"50","count":2,"preSum":6}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[12,369,78435,9,4,641,9136,3,8402,1144,37],"valueArr":["09","14","15","21","22","23","36","39","47","51","54"],"type":"String","sampleRate":0.924351804778851}',1801,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','pr_code',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[99997,4],"valueArr":["1","2"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','record_delete_date',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Datetime","sampleRate":0.9243518}','{"countArr":[100001],"valueArr":[-1],"type":"Datetime","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','record_status',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[100001],"valueArr":["1"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','run_cap',11930,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":14,"upper":0.33,"lower":0.00,"count":295,"preSum":0},{"ndv":6,"upper":0.55,"lower":0.38,"count":389,"preSum":295},{"ndv":2,"upper":0.66,"lower":0.60,"count":205,"preSum":684},{"ndv":17,"upper":1.32,"lower":0.70,"count":221,"preSum":889},{"ndv":8,"upper":1.60,"lower":1.34,"count":217,"preSum":1110},{"ndv":22,"upper":2.50,"lower":1.61,"count":467,"preSum":1327},{"ndv":21,"upper":3.60,"lower":2.56,"count":222,"preSum":1794},{"ndv":38,"upper":5.50,"lower":3.67,"count":217,"preSum":2016},{"ndv":8,"upper":5.90,"lower":5.58,"count":821,"preSum":2233},{"ndv":12,"upper":6.60,"lower":5.94,"count":275,"preSum":3054},{"ndv":6,"upper":7.00,"lower":6.70,"count":1056,"preSum":3329},{"ndv":20,"upper":9.00,"lower":7.05,"count":753,"preSum":4385},{"ndv":26,"upper":11.00,"lower":9.10,"count":362,"preSum":5138},{"ndv":23,"upper":13.00,"lower":11.30,"count":333,"preSum":5500},{"ndv":12,"upper":14.00,"lower":13.10,"count":862,"preSum":5833},{"ndv":22,"upper":16.00,"lower":14.10,"count":272,"preSum":6695},{"ndv":20,"upper":18.00,"lower":16.10,"count":357,"preSum":6967},{"ndv":33,"upper":22.00,"lower":18.10,"count":308,"preSum":7324},{"ndv":16,"upper":25.00,"lower":22.05,"count":393,"preSum":7632},{"ndv":20,"upper":29.00,"lower":25.20,"count":232,"preSum":8025},{"ndv":5,"upper":30.00,"lower":29.25,"count":570,"preSum":8257},{"ndv":24,"upper":37.00,"lower":30.40,"count":200,"preSum":8827},{"ndv":10,"upper":40.00,"lower":37.35,"count":227,"preSum":9027},{"ndv":29,"upper":49.00,"lower":40.95,"count":234,"preSum":9254},{"ndv":5,"upper":50.00,"lower":49.36,"count":256,"preSum":9488},{"ndv":33,"upper":70.00,"lower":51.00,"count":220,"preSum":9744},{"ndv":17,"upper":86.00,"lower":71.00,"count":200,"preSum":9964},{"ndv":18,"upper":100.00,"lower":87.00,"count":299,"preSum":10164},{"ndv":32,"upper":200.00,"lower":100.44,"count":385,"preSum":10463},{"ndv":8,"upper":250.00,"lower":201.00,"count":240,"preSum":10848},{"ndv":8,"upper":315.00,"lower":256.00,"count":206,"preSum":11088},{"ndv":20,"upper":500.00,"lower":320.00,"count":407,"preSum":11294},{"ndv":10,"upper":630.00,"lower":500.85,"count":231,"preSum":11701},{"ndv":20,"upper":965.80,"lower":640.00,"count":200,"preSum":11932},{"ndv":27,"upper":1600.00,"lower":1000.00,"count":231,"preSum":12132},{"ndv":59,"upper":3715.00,"lower":1615.00,"count":200,"preSum":12363},{"ndv":119,"upper":1118000.00,"lower":3800.00,"count":194,"preSum":12563}],"maxBucketSize":64,"type":"Double","sampleRate":0.9243518}','{"countArr":[4287,3885,8286,2725,4496,18174,1071,9606,16166,9241,5016,1257,1627,1144],"valueArr":[1.00,1.10,2.00,2.20,3.00,4.00,4.40,5.00,6.00,8.00,10.00,12.00,15.00,20.00],"type":"Double","sampleRate":0.924351804778851}',263,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','rv_code',5,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[86802,10843,60,5,490],"valueArr":["1","2","3","4","5"],"type":"String","sampleRate":0.924351804778851}',1801,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','stand_curr_code',72,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"04","lower":"04","count":1,"preSum":0},{"ndv":1,"upper":"08","lower":"08","count":3,"preSum":1},{"ndv":1,"upper":"10","lower":"10","count":2,"preSum":4},{"ndv":1,"upper":"16","lower":"16","count":2,"preSum":6},{"ndv":1,"upper":"21","lower":"21","count":6,"preSum":8},{"ndv":1,"upper":"32","lower":"32","count":4,"preSum":14},{"ndv":1,"upper":"37","lower":"37","count":9,"preSum":18},{"ndv":1,"upper":"38","lower":"38","count":2,"preSum":27},{"ndv":1,"upper":"40","lower":"40","count":8,"preSum":29},{"ndv":1,"upper":"57","lower":"57","count":3,"preSum":37},{"ndv":1,"upper":"59","lower":"59","count":5,"preSum":40},{"ndv":1,"upper":"60","lower":"60","count":1,"preSum":45},{"ndv":1,"upper":"78","lower":"78","count":2,"preSum":46}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1861,26,17,36,906,8344,4689,7294,65396,20,106,4051,4331,1075],"valueArr":["02","12","13","14","17","22","27","53","73","76","79","82","83","84"],"type":"String","sampleRate":0.924351804778851}',1801,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','step_sort',33,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":" ","lower":" ","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[14463,877,302,41,81319,2341],"valueArr":["F","G","H","T","Y","Z"],"type":"String","sampleRate":0.924351804778851}',657,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','subs_id',3194,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":37,"upper":"030200022944","lower":"03020000057","count":1556,"preSum":0},{"ndv":48,"upper":"030200S1028104","lower":"030200022945","count":1533,"preSum":1556},{"ndv":39,"upper":"0304001007","lower":"030200S1028105","count":1553,"preSum":3089},{"ndv":31,"upper":"0304001042","lower":"0304001008","count":1538,"preSum":4642},{"ndv":19,"upper":"030500000289","lower":"0304005176","count":1601,"preSum":6180},{"ndv":24,"upper":"03050005150014","lower":"030500000314","count":1519,"preSum":7781},{"ndv":21,"upper":"0305001134","lower":"03050005150016","count":1591,"preSum":9300},{"ndv":35,"upper":"03060006141","lower":"0305001136","count":1541,"preSum":10891},{"ndv":27,"upper":"030600062020","lower":"03060006142","count":1543,"preSum":12432},{"ndv":37,"upper":"030600063013","lower":"030600062021","count":1563,"preSum":13975},{"ndv":30,"upper":"030600064005","lower":"030600063014","count":1580,"preSum":15538},{"ndv":29,"upper":"0306000689117","lower":"030600064006","count":1520,"preSum":17118},{"ndv":41,"upper":"030600069303","lower":"0306000689123","count":1547,"preSum":18638},{"ndv":42,"upper":"03070020DQD","lower":"030600069305","count":1525,"preSum":20185},{"ndv":36,"upper":"0307005001-01","lower":"03070020GZD","count":1608,"preSum":21710},{"ndv":30,"upper":"0307006012","lower":"0307005002-01","count":1565,"preSum":23318},{"ndv":23,"upper":"03070070U","lower":"0307006015","count":1546,"preSum":24883},{"ndv":30,"upper":"03080060000051","lower":"03070070W","count":1546,"preSum":26429},{"ndv":24,"upper":"030800LJYW","lower":"03080060000069","count":1586,"preSum":27975},{"ndv":21,"upper":"030800WCBP","lower":"030800LJYZ","count":1519,"preSum":29561},{"ndv":18,"upper":"03090000064","lower":"030800WCCQ","count":1565,"preSum":31080},{"ndv":29,"upper":"03090010002","lower":"03090000067","count":1596,"preSum":32645},{"ndv":17,"upper":"03090051004","lower":"03090010005","count":1565,"preSum":34241},{"ndv":20,"upper":"03090080001","lower":"03090051010","count":1574,"preSum":35806},{"ndv":29,"upper":"03120011004","lower":"03090080002","count":1562,"preSum":37380},{"ndv":49,"upper":"031200B30O","lower":"03120011005","count":1566,"preSum":38942},{"ndv":31,"upper":"031200HJ002","lower":"031200B30P","count":1551,"preSum":40508},{"ndv":29,"upper":"03130000000047","lower":"031200HJ003","count":1613,"preSum":42059},{"ndv":27,"upper":"03130010000023","lower":"03130000000048","count":1590,"preSum":43672},{"ndv":27,"upper":"03130050000007","lower":"03130010000050","count":1553,"preSum":45262},{"ndv":23,"upper":"03130071000001","lower":"03130050000008","count":1540,"preSum":46815},{"ndv":25,"upper":"03130090000001","lower":"03130071000002","count":1560,"preSum":48355},{"ndv":42,"upper":"031400200022","lower":"03130090000002","count":1522,"preSum":49915},{"ndv":34,"upper":"03140060000037","lower":"031400200024","count":1526,"preSum":51437},{"ndv":25,"upper":"03140082000","lower":"03140060000039","count":1556,"preSum":52963},{"ndv":23,"upper":"03150081189215","lower":"03150000000001","count":1588,"preSum":54519},{"ndv":30,"upper":"031600HPRS","lower":"03150081189216","count":1542,"preSum":56107},{"ndv":46,"upper":"031600ZJNG","lower":"031600HPSL","count":1561,"preSum":57649},{"ndv":32,"upper":"03170035","lower":"03170001","count":1567,"preSum":59210},{"ndv":23,"upper":"031800180032","lower":"03170037","count":1532,"preSum":60777},{"ndv":37,"upper":"0318005093","lower":"031800180071","count":1567,"preSum":62309},{"ndv":26,"upper":"0318005179","lower":"0318005095","count":1519,"preSum":63876},{"ndv":44,"upper":"031900000394","lower":"0318005180","count":1534,"preSum":65395},{"ndv":37,"upper":"03190019009313","lower":"031900000395","count":1556,"preSum":66929},{"ndv":30,"upper":"03190050050003","lower":"03190019009314","count":1516,"preSum":68485},{"ndv":38,"upper":"03190050170002","lower":"03190050060001","count":1563,"preSum":70001},{"ndv":32,"upper":"03190050270004","lower":"03190050170003","count":1521,"preSum":71564},{"ndv":32,"upper":"0320002000080009","lower":"03190050280001","count":1564,"preSum":73085},{"ndv":40,"upper":"0320002000207942","lower":"0320002000080012","count":1536,"preSum":74649},{"ndv":44,"upper":"03510001","lower":"0320002000208218","count":1576,"preSum":76185},{"ndv":25,"upper":"035100512106","lower":"03510004","count":1553,"preSum":77761},{"ndv":25,"upper":"03520011013","lower":"035100512107","count":1551,"preSum":79314},{"ndv":15,"upper":"0352001116","lower":"03520011028","count":1568,"preSum":80865},{"ndv":16,"upper":"0352002218","lower":"0352001117","count":1526,"preSum":82433},{"ndv":32,"upper":"03530060000012","lower":"0352002221","count":1563,"preSum":83959},{"ndv":30,"upper":"035300B30XY","lower":"03530060000013","count":1528,"preSum":85522},{"ndv":35,"upper":"2222222322362782","lower":"035300B4001","count":1520,"preSum":87050},{"ndv":58,"upper":"2222222322842724","lower":"2222222322372724","count":1542,"preSum":88570},{"ndv":48,"upper":"2222222323442723","lower":"2222222322847723","count":1542,"preSum":90112},{"ndv":54,"upper":"2222222323932724","lower":"2222222323447723","count":1542,"preSum":91654},{"ndv":68,"upper":"2222222324552724","lower":"2222222323932725","count":1518,"preSum":93196},{"ndv":87,"upper":"2222222325292724","lower":"2222222324557723","count":1532,"preSum":94714},{"ndv":54,"upper":"2222222326677738","lower":"2222222325302724","count":716,"preSum":96246}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[265,192,195,218,208,254,215,242,205,197,195,237,215,201],"valueArr":["030500000285","0307006003","0308008","030800LJAP","03130040000002","031800180033","0318005061","035100510042","0352001102","03520011027","0352001113","0352001118","0352002220","2222222322852723"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','subs_name',2961,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":26,"upper":"110kV东湖变电站","lower":"10kV新城开关站","count":1656,"preSum":0},{"ndv":29,"upper":"110kV仁化变电站","lower":"110kV东湖站","count":1534,"preSum":1656},{"ndv":27,"upper":"110kV前进变电站","lower":"110kV今古洲站","count":1517,"preSum":3190},{"ndv":30,"upper":"110kV南调变电站","lower":"110kV化州变电站","count":1648,"preSum":4707},{"ndv":25,"upper":"110kV合山变电站","lower":"110kV南郊变电站","count":1550,"preSum":6355},{"ndv":33,"upper":"110kV城月变电站","lower":"110kV合山站","count":1509,"preSum":7905},{"ndv":17,"upper":"110kV大塘变电站","lower":"110kV城西变电站","count":1537,"preSum":9414},{"ndv":27,"upper":"110kV小市变电站","lower":"110kV大岭变电站","count":1508,"preSum":10951},{"ndv":33,"upper":"110kV所城变电站","lower":"110kV小良变电站","count":1531,"preSum":12459},{"ndv":24,"upper":"110kV时代变电站","lower":"110kV扬子坑变电站","count":1533,"preSum":13990},{"ndv":28,"upper":"110kV桂头变电站","lower":"110kV旺沙变电站","count":1511,"preSum":15523},{"ndv":22,"upper":"110kV横溪变电站","lower":"110kV桂山变电站","count":1505,"preSum":17034},{"ndv":28,"upper":"110kV沙塘站","lower":"110kV横溪电厂","count":1508,"preSum":18539},{"ndv":23,"upper":"110kV洲心变电站","lower":"110kV沙沥变电站","count":1526,"preSum":20047},{"ndv":20,"upper":"110kV滘头站","lower":"110kV浈阳变电站","count":1545,"preSum":21573},{"ndv":29,"upper":"110kV白云变电站","lower":"110kV滨海变电站","count":1513,"preSum":23118},{"ndv":22,"upper":"110kV福地变电站","lower":"110kV白土变电站","count":1539,"preSum":24631},{"ndv":33,"upper":"110kV联盛站","lower":"110kV福堂变电站","count":1513,"preSum":26170},{"ndv":32,"upper":"110kV螺岛变电站","lower":"110kV聚龙站","count":1509,"preSum":27683},{"ndv":26,"upper":"110kV金叶变电站","lower":"110kV西埚变电站","count":1562,"preSum":29192},{"ndv":24,"upper":"110kV长廊变电站","lower":"110kV金塘变电站","count":1518,"preSum":30754},{"ndv":28,"upper":"110kV飞鼠田变电站","lower":"110kV长沙站","count":1575,"preSum":32272},{"ndv":32,"upper":"110kV黄坑变电站","lower":"110kV香洲变电站","count":1622,"preSum":33847},{"ndv":27,"upper":"220kV丰港变电站","lower":"110kV黄坡变电站","count":1525,"preSum":35469},{"ndv":36,"upper":"220kV天泰变电站","lower":"220kV乐桥变电站","count":1549,"preSum":36994},{"ndv":45,"upper":"220kV河东变电站","lower":"220kV奎阁变电站","count":1664,"preSum":38543},{"ndv":49,"upper":"220kV醒狮变电站","lower":"220kV河源变电站","count":1609,"preSum":40207},{"ndv":56,"upper":"35kV壶垌变电站","lower":"220kV金山变电站","count":1527,"preSum":41816},{"ndv":55,"upper":"35kV火电厂变电站","lower":"35kV大万山岛站","count":1522,"preSum":43343},{"ndv":61,"upper":"三山变电站","lower":"35kV热水变电站","count":1517,"preSum":44865},{"ndv":37,"upper":"东岸变电站","lower":"三村变电站","count":1616,"preSum":46382},{"ndv":28,"upper":"丹阳变电站","lower":"东平变电站","count":1510,"preSum":47998},{"ndv":31,"upper":"仁德变电站","lower":"主山变电站","count":1568,"preSum":49508},{"ndv":34,"upper":"兰花变电站","lower":"仙庵变电站","count":1549,"preSum":51076},{"ndv":32,"upper":"北山变电站","lower":"共联变电站","count":1506,"preSum":52625},{"ndv":30,"upper":"南溪变电站","lower":"北帝变电站","count":1537,"preSum":54131},{"ndv":33,"upper":"同沙变电站","lower":"南社变电站","count":1512,"preSum":55668},{"ndv":27,"upper":"坑塘变电站","lower":"同益变电站","count":1505,"preSum":57180},{"ndv":28,"upper":"大州变电站","lower":"坑田变电站","count":1549,"preSum":58685},{"ndv":31,"upper":"安山变电站","lower":"大旺变电站","count":1577,"preSum":60234},{"ndv":38,"upper":"小迳变电站","lower":"安流变电站","count":1507,"preSum":61811},{"ndv":40,"upper":"平西变电站","lower":"尖岗变电站","count":1548,"preSum":63318},{"ndv":37,"upper":"扶大变电站","lower":"平远变电站","count":1598,"preSum":64866},{"ndv":32,"upper":"新陂变电站","lower":"拱北变电站","count":1545,"preSum":66464},{"ndv":28,"upper":"望牛墩变电站","lower":"旗乐变电站","count":1513,"preSum":68009},{"ndv":39,"upper":"桥头变电站","lower":"朝东变电站","count":1588,"preSum":69522},{"ndv":25,"upper":"横江变电站","lower":"桥梓变电站","count":1528,"preSum":71110},{"ndv":45,"upper":"沙涌变电站","lower":"横沙变电站","count":1513,"preSum":72638},{"ndv":41,"upper":"海唇变电站","lower":"沙溪变电站","count":1528,"preSum":74151},{"ndv":27,"upper":"溪角变电站","lower":"海洲变电站","count":1539,"preSum":75679},{"ndv":33,"upper":"瑞颜变电站","lower":"溶洲变电站","count":1504,"preSum":77218},{"ndv":34,"upper":"盘古变电站","lower":"瑶上变电站","count":1632,"preSum":78722},{"ndv":35,"upper":"程江变电站","lower":"睦岗变电站","count":1570,"preSum":80354},{"ndv":34,"upper":"罗阳变电站","lower":"稔塘变电站","count":1513,"preSum":81924},{"ndv":30,"upper":"茶园变电站","lower":"羊额变电站","count":1503,"preSum":83437},{"ndv":36,"upper":"西桠变电站","lower":"茶洞变电站","count":1509,"preSum":84940},{"ndv":36,"upper":"通门变电站","lower":"西河变电站","count":1514,"preSum":86449},{"ndv":30,"upper":"金融变电站","lower":"逢涌变电站","count":1511,"preSum":87963},{"ndv":34,"upper":"长美变电站","lower":"金装变电站","count":1571,"preSum":89474},{"ndv":32,"upper":"飞鹅亭变电站","lower":"长龙变电站","count":1582,"preSum":91045},{"ndv":23,"upper":"鸡啼岗变电站","lower":"香山变电站","count":1518,"preSum":92627},{"ndv":26,"upper":"龙山变电站","lower":"鸡山变电站","count":1519,"preSum":94145},{"ndv":15,"upper":"(旧)110kV芝北变电站","lower":"龙村变电站","count":521,"preSum":95664}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[541,265,216,383,218,281,387,277,220,219,237,266,306],"valueArr":["110kV东城变电站","110kV关埠变电站","110kV南龙变电站","110kV城东变电站","110kV安铺变电站","110kV附城变电站","城东变电站","城西变电站","沙田变电站","河口变电站","流沙变电站","莲塘变电站","西南变电站"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','subs_no',3209,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":39,"upper":"030200020135","lower":"000000000000000","count":1536,"preSum":0},{"ndv":51,"upper":"030200S1023204","lower":"030200020186","count":1523,"preSum":1536},{"ndv":54,"upper":"03040004009240","lower":"030200S1023205","count":1594,"preSum":3059},{"ndv":31,"upper":"0304001033","lower":"03040004009242","count":1587,"preSum":4653},{"ndv":25,"upper":"030500000182","lower":"0304001034","count":1572,"preSum":6240},{"ndv":30,"upper":"03050005150004","lower":"030500000183","count":1583,"preSum":7812},{"ndv":19,"upper":"0305001106","lower":"03050005150008","count":1523,"preSum":9395},{"ndv":28,"upper":"03051","lower":"0305001108","count":1543,"preSum":10918},{"ndv":36,"upper":"030600062004","lower":"0305112","count":1532,"preSum":12461},{"ndv":28,"upper":"030600062038","lower":"030600062005","count":1525,"preSum":13993},{"ndv":35,"upper":"030600063025","lower":"030600062039","count":1615,"preSum":15518},{"ndv":28,"upper":"030600064015","lower":"030600063026","count":1552,"preSum":17133},{"ndv":39,"upper":"0306000689183","lower":"030600064016","count":1523,"preSum":18685},{"ndv":38,"upper":"030600069329","lower":"0306000689184","count":1555,"preSum":20208},{"ndv":66,"upper":"03070020DQD","lower":"030600069331","count":1576,"preSum":21763},{"ndv":37,"upper":"0307003025","lower":"03070020GZD","count":1531,"preSum":23339},{"ndv":29,"upper":"0307006009","lower":"0307003030","count":1525,"preSum":24870},{"ndv":24,"upper":"03070070Q","lower":"0307006010","count":1605,"preSum":26395},{"ndv":36,"upper":"03080060000036","lower":"03070070R","count":1602,"preSum":28000},{"ndv":27,"upper":"030800LJQP","lower":"03080060000040","count":1559,"preSum":29602},{"ndv":22,"upper":"030800SXNC","lower":"030800LJSJ","count":1555,"preSum":31161},{"ndv":17,"upper":"030800x1","lower":"030800SXPS","count":1568,"preSum":32716},{"ndv":27,"upper":"030900092347","lower":"030800x2","count":1557,"preSum":34284},{"ndv":23,"upper":"03090020008","lower":"030900092350","count":1617,"preSum":35841},{"ndv":21,"upper":"03090070005","lower":"03090020010","count":1575,"preSum":37458},{"ndv":26,"upper":"03120010A","lower":"03090070006","count":1527,"preSum":39033},{"ndv":44,"upper":"0312008001","lower":"03120010B","count":1523,"preSum":40560},{"ndv":36,"upper":"031200B40A","lower":"0312008002","count":1529,"preSum":42083},{"ndv":31,"upper":"031200HJ005","lower":"031200B40B","count":1540,"preSum":43612},{"ndv":33,"upper":"03130000000049","lower":"031200HJ006","count":1517,"preSum":45152},{"ndv":25,"upper":"03130010000023","lower":"03130000000050","count":1520,"preSum":46669},{"ndv":49,"upper":"03130040000007","lower":"03130010000050","count":1518,"preSum":48189},{"ndv":21,"upper":"03130060000006","lower":"03130040000008","count":1545,"preSum":49707},{"ndv":28,"upper":"03130080000008","lower":"03130060000007","count":1571,"preSum":51252},{"ndv":31,"upper":"031400110000","lower":"03130080000009","count":1526,"preSum":52823},{"ndv":44,"upper":"03140040007","lower":"031400110001","count":1525,"preSum":54349},{"ndv":34,"upper":"03140060002","lower":"03140040008","count":1543,"preSum":55874},{"ndv":24,"upper":"03150010000002","lower":"03140060003","count":1630,"preSum":57417},{"ndv":23,"upper":"03150081189218","lower":"03150010000006","count":1599,"preSum":59047},{"ndv":34,"upper":"031600HY","lower":"03150081189219","count":1565,"preSum":60646},{"ndv":51,"upper":"031600ZJHY","lower":"031600JH","count":1521,"preSum":62211},{"ndv":29,"upper":"031700203","lower":"031600ZJNG","count":1553,"preSum":63732},{"ndv":33,"upper":"03170060000093","lower":"031700204","count":1643,"preSum":65285},{"ndv":44,"upper":"0318005054","lower":"03170060000116","count":1517,"preSum":66928},{"ndv":25,"upper":"0318005144","lower":"0318005055","count":1523,"preSum":68445},{"ndv":38,"upper":"0318008103","lower":"0318005145","count":1520,"preSum":69968},{"ndv":34,"upper":"03190019009268","lower":"0318008107","count":1523,"preSum":71488},{"ndv":40,"upper":"03190050010005","lower":"03190019009269","count":1598,"preSum":73011},{"ndv":32,"upper":"03190050120001","lower":"03190050020002","count":1587,"preSum":74609},{"ndv":35,"upper":"03190050230001","lower":"03190050120002","count":1588,"preSum":76196},{"ndv":45,"upper":"031900DGlZ20191223","lower":"03190050230002","count":1531,"preSum":77784},{"ndv":52,"upper":"0320002000080014","lower":"031900DGNZ20161229","count":1625,"preSum":79315},{"ndv":41,"upper":"0320002000209281","lower":"0320002000080016","count":1521,"preSum":80940},{"ndv":46,"upper":"03510001","lower":"0320002000209282","count":1541,"preSum":82461},{"ndv":25,"upper":"035100512105","lower":"03510004","count":1531,"preSum":84002},{"ndv":27,"upper":"0352001101","lower":"035100512106","count":1536,"preSum":85533},{"ndv":16,"upper":"0352001115","lower":"03520011010","count":1529,"preSum":87069},{"ndv":19,"upper":"035200180301","lower":"0352001116","count":1526,"preSum":88598},{"ndv":24,"upper":"035200520240","lower":"035200180801","count":1529,"preSum":90124},{"ndv":33,"upper":"035300B10T","lower":"035200522235","count":1516,"preSum":91653},{"ndv":30,"upper":"035300B5003","lower":"035300B10Z","count":1639,"preSum":93169},{"ndv":58,"upper":"393480089448300","lower":"035300B5004","count":1523,"preSum":94808},{"ndv":38,"upper":"zoulubiandianzhan","lower":"400220005200100","count":631,"preSum":96331}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[265,192,195,218,208,201,254,215,242,205,197,195,237,215],"valueArr":["030500000285","0307006003","0308008","030800LJAP","03130040000002","03150020161208","031800180033","0318005061","035100510042","0352001102","03520011027","0352001113","0352001118","0352002220"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','subs_type_code',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[99991,6,4],"valueArr":["1","2","3"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','supply_code',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','supply_org_name',1319,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":11,"upper":"三埠供电所","lower":"丁堡供电所","count":1430,"preSum":0},{"ndv":24,"upper":"东区供电分局","lower":"三排供电所","count":1630,"preSum":1430},{"ndv":17,"upper":"东简供电所","lower":"东升供电分局","count":1457,"preSum":3060},{"ndv":10,"upper":"丰城供电所","lower":"东里供电所","count":1393,"preSum":4517},{"ndv":17,"upper":"乐平供电所","lower":"丰稔供电所","count":1559,"preSum":5910},{"ndv":23,"upper":"云潭供电所","lower":"乐民供电所","count":1419,"preSum":7469},{"ndv":19,"upper":"会城供电所","lower":"云澳供电所","count":1804,"preSum":8888},{"ndv":22,"upper":"兴城供电所","lower":"伦教供电所","count":1523,"preSum":10692},{"ndv":13,"upper":"前山营业所","lower":"兴宁大坪供电所","count":1755,"preSum":12215},{"ndv":9,"upper":"十里亭供电所","lower":"前詹供电所","count":1434,"preSum":13970},{"ndv":12,"upper":"南头供电分局","lower":"华侨供电所","count":1480,"preSum":15404},{"ndv":7,"upper":"南水供电所","lower":"南屏供电所","count":1427,"preSum":16884},{"ndv":13,"upper":"厚街供电服务中心","lower":"南海供电局","count":1623,"preSum":18311},{"ndv":24,"upper":"同庆供电所","lower":"双华供电所","count":1394,"preSum":19934},{"ndv":24,"upper":"坑口中心供电所(广宁)","lower":"后宅供电所","count":1406,"preSum":21328},{"ndv":13,"upper":"城南供电所","lower":"坝仔供电所","count":1705,"preSum":22734},{"ndv":18,"upper":"大坡供电所","lower":"城口供电所","count":1397,"preSum":24439},{"ndv":11,"upper":"大朗供电服务中心","lower":"大坪供电所","count":1584,"preSum":25836},{"ndv":19,"upper":"太和供电所","lower":"大柘供电所","count":1557,"preSum":27420},{"ndv":14,"upper":"客路供电所","lower":"太平供电所","count":1399,"preSum":28977},{"ndv":20,"upper":"常平供电服务中心","lower":"寨岗大麦山供电所","count":1511,"preSum":30376},{"ndv":15,"upper":"开发区供电所","lower":"平冈供电所","count":1617,"preSum":31887},{"ndv":14,"upper":"拱北营业所","lower":"彭寨供电所","count":1497,"preSum":33504},{"ndv":16,"upper":"新兴新城供电所","lower":"振文供电所","count":1429,"preSum":35001},{"ndv":21,"upper":"明城供电所","lower":"新兴水台供电所","count":1476,"preSum":36430},{"ndv":18,"upper":"杏坛供电所","lower":"星子供电所","count":1483,"preSum":37906},{"ndv":21,"upper":"柏塘供电所","lower":"杜步供电所","count":1392,"preSum":39389},{"ndv":21,"upper":"棉北供电所","lower":"树仔供电所","count":1412,"preSum":40781},{"ndv":10,"upper":"横沥供电服务中心","lower":"棉洋供电所","count":1569,"preSum":42193},{"ndv":14,"upper":"水步供电所","lower":"横河供电所","count":1475,"preSum":43762},{"ndv":15,"upper":"江海直管","lower":"水车供电所","count":1525,"preSum":45237},{"ndv":17,"upper":"沙扒供电所","lower":"江湖供电所","count":1405,"preSum":46762},{"ndv":14,"upper":"河唇供电所","lower":"沙浦供电所","count":1556,"preSum":48167},{"ndv":20,"upper":"流沙东供电所","lower":"河头供电所","count":1507,"preSum":49723},{"ndv":11,"upper":"海陵岛供电服务中心","lower":"流沙北供电所","count":1400,"preSum":51230},{"ndv":14,"upper":"湘桥供电局","lower":"浸潭供电所","count":1829,"preSum":52630},{"ndv":24,"upper":"潮安沙溪供电所","lower":"湘桥意溪供电所","count":1404,"preSum":54459},{"ndv":14,"upper":"濠广供电所","lower":"潮安浮洋供电所","count":1434,"preSum":55863},{"ndv":12,"upper":"王村港供电所","lower":"濠滨供电所","count":1397,"preSum":57297},{"ndv":24,"upper":"白蕉供电所","lower":"珠海供电局","count":1700,"preSum":58694},{"ndv":14,"upper":"石望供电所","lower":"白诸中心供电所","count":1438,"preSum":60394},{"ndv":15,"upper":"碣石供电所","lower":"石板供电所","count":1405,"preSum":61832},{"ndv":15,"upper":"紫市供电所","lower":"磐东供电所","count":1396,"preSum":63237},{"ndv":25,"upper":"罗定罗平供电所","lower":"紫金供电局","count":1413,"preSum":64633},{"ndv":14,"upper":"老隆供电所","lower":"罗定罗镜供电所","count":1458,"preSum":66046},{"ndv":19,"upper":"草潭供电所","lower":"联安供电所","count":1411,"preSum":67504},{"ndv":12,"upper":"营业部","lower":"荷城供电所","count":1439,"preSum":68915},{"ndv":11,"upper":"螺溪供电所","lower":"营仔供电所","count":1428,"preSum":70354},{"ndv":11,"upper":"覃巴供电所","lower":"袂花供电所","count":1398,"preSum":71782},{"ndv":26,"upper":"连江口供电所","lower":"覃斗供电所","count":1403,"preSum":73180},{"ndv":26,"upper":"里水供电所","lower":"迳头供电所","count":1570,"preSum":74583},{"ndv":24,"upper":"锡场供电所","lower":"里湖供电所","count":1417,"preSum":76153},{"ndv":12,"upper":"长沙供电所","lower":"锦和供电所","count":1392,"preSum":77570},{"ndv":14,"upper":"陈村供电所","lower":"长潭供电所","count":1505,"preSum":78962},{"ndv":24,"upper":"饶平三饶供电所","lower":"陈江供电所","count":1414,"preSum":80467},{"ndv":19,"upper":"香洲营业所","lower":"饶平上饶供电所","count":1436,"preSum":81881},{"ndv":18,"upper":"高潭供电所","lower":"马冈供电所","count":1409,"preSum":83317},{"ndv":22,"upper":"黄岗中心供电所","lower":"高莞供电所","count":1727,"preSum":84726},{"ndv":19,"upper":"龙塘供电所","lower":"黄岭供电所","count":1446,"preSum":86453},{"ndv":16,"upper":"龙颈供电所","lower":"龙头供电所","count":1139,"preSum":87899}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[566,579,554,1831,1149,715,790,555,674,646,643,721,672,868],"valueArr":["东城中心供电所","东城供电所","台城营业所","城区供电所","城区供电服务中心","城郊供电所","大沥供电所","容桂供电所","桂城供电所","江南供电所","海滨供电所","淡水供电所","西区供电所","西南供电所"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','supply_org_no',1371,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":29,"upper":"03021011","lower":"030202","count":1650,"preSum":0},{"ndv":21,"upper":"03021507","lower":"03021012","count":1431,"preSum":1650},{"ndv":24,"upper":"03040105","lower":"03021509","count":1437,"preSum":3081},{"ndv":9,"upper":"03040304","lower":"03040106","count":1479,"preSum":4518},{"ndv":9,"upper":"03052308","lower":"03040306","count":1406,"preSum":5997},{"ndv":14,"upper":"03054709","lower":"03052603","count":1519,"preSum":7403},{"ndv":14,"upper":"03054812","lower":"03054710","count":1414,"preSum":8922},{"ndv":12,"upper":"03054910","lower":"03054813","count":1475,"preSum":10336},{"ndv":11,"upper":"03061213","lower":"03054911","count":1580,"preSum":11811},{"ndv":5,"upper":"03061311","lower":"03061214","count":1714,"preSum":13391},{"ndv":7,"upper":"03061318","lower":"03061312","count":1533,"preSum":15105},{"ndv":15,"upper":"03070207","lower":"03061319","count":1455,"preSum":16638},{"ndv":13,"upper":"03070408","lower":"03070211","count":1441,"preSum":18093},{"ndv":25,"upper":"03070614","lower":"03070410","count":1463,"preSum":19534},{"ndv":18,"upper":"03071316","lower":"03070615","count":1446,"preSum":20997},{"ndv":8,"upper":"03080105","lower":"030714","count":1489,"preSum":22443},{"ndv":18,"upper":"03081015","lower":"03080106","count":1424,"preSum":23932},{"ndv":21,"upper":"03081415","lower":"03081016","count":1505,"preSum":25356},{"ndv":20,"upper":"03082032","lower":"03081417","count":1408,"preSum":26861},{"ndv":18,"upper":"03082825","lower":"03082033","count":1442,"preSum":28269},{"ndv":23,"upper":"03090256","lower":"03083004","count":1427,"preSum":29711},{"ndv":25,"upper":"03090902","lower":"03090257","count":1463,"preSum":31138},{"ndv":21,"upper":"03091006","lower":"03090903","count":1537,"preSum":32601},{"ndv":23,"upper":"03091612","lower":"03091017","count":1460,"preSum":34138},{"ndv":13,"upper":"03120305","lower":"03091613","count":1504,"preSum":35598},{"ndv":14,"upper":"03120607","lower":"03120308","count":1780,"preSum":37102},{"ndv":20,"upper":"03130202","lower":"03120907","count":1445,"preSum":38882},{"ndv":7,"upper":"03130223","lower":"03130210","count":1453,"preSum":40327},{"ndv":14,"upper":"03130415","lower":"03130225","count":1824,"preSum":41780},{"ndv":20,"upper":"03131312","lower":"03130418","count":1508,"preSum":43604},{"ndv":20,"upper":"03131423","lower":"03131317","count":1751,"preSum":45112},{"ndv":14,"upper":"03140117","lower":"03131602","count":1419,"preSum":46863},{"ndv":26,"upper":"03140617","lower":"03140118","count":1441,"preSum":48282},{"ndv":34,"upper":"03141009","lower":"03140619","count":1531,"preSum":49723},{"ndv":27,"upper":"03150219","lower":"03141010","count":1442,"preSum":51254},{"ndv":28,"upper":"03150420","lower":"03150221","count":1633,"preSum":52696},{"ndv":29,"upper":"03160922","lower":"03151003","count":1449,"preSum":54329},{"ndv":50,"upper":"03162614","lower":"03160923","count":1427,"preSum":55778},{"ndv":20,"upper":"03170430","lower":"03163302","count":1765,"preSum":57205},{"ndv":21,"upper":"03171015","lower":"03170507","count":1407,"preSum":58970},{"ndv":9,"upper":"03180107","lower":"03171016","count":1705,"preSum":60377},{"ndv":21,"upper":"03182601","lower":"03180108","count":1448,"preSum":62082},{"ndv":25,"upper":"03188116","lower":"03182602","count":1482,"preSum":63530},{"ndv":23,"upper":"03196906","lower":"03188117","count":1636,"preSum":65012},{"ndv":6,"upper":"03197111","lower":"03196914","count":1518,"preSum":66648},{"ndv":10,"upper":"03197309","lower":"03197112","count":1447,"preSum":68166},{"ndv":5,"upper":"03197506","lower":"03197310","count":1773,"preSum":69613},{"ndv":5,"upper":"032014","lower":"03197507","count":1629,"preSum":71386},{"ndv":6,"upper":"032020","lower":"032015","count":1503,"preSum":73015},{"ndv":9,"upper":"032029","lower":"032021","count":1556,"preSum":74518},{"ndv":24,"upper":"03510525","lower":"032030","count":1413,"preSum":76074},{"ndv":16,"upper":"03510917","lower":"03510526","count":1467,"preSum":77487},{"ndv":12,"upper":"03520218","lower":"03510918","count":1671,"preSum":78954},{"ndv":16,"upper":"03520316","lower":"03520224","count":1542,"preSum":80625},{"ndv":15,"upper":"03520619","lower":"03520603","count":1519,"preSum":82167},{"ndv":14,"upper":"03520707","lower":"03520620","count":1461,"preSum":83686},{"ndv":24,"upper":"03521519","lower":"03520709","count":1509,"preSum":85147},{"ndv":24,"upper":"03530423","lower":"03521524","count":1421,"preSum":86656},{"ndv":33,"upper":"03531318","lower":"03530424","count":1442,"preSum":88077},{"ndv":6,"upper":"03531324","lower":"03531319","count":238,"preSum":89519}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[643,1259,790,674,555,868,506,554,572,566,672,721,715,1149],"valueArr":["03052307","03060306","03061211","03061218","03061320","03061405","03061507","03070624","03091616","03120926","03130309","03130616","03171013","03196901"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','term_useage',29,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"1","lower":"1","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[7,235],"valueArr":["2","3"],"type":"String","sampleRate":0.924351804778851}',99758,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tm_assets_no',1802857,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1473,"upper":"03001ZJ00000011700000277","lower":"013131ZJ00000001600447943","count":1562,"preSum":0},{"ndv":1153,"upper":"03001ZJ00000011700011932","lower":"03001ZJ00000011700000281","count":1562,"preSum":1562},{"ndv":1126,"upper":"03001ZJ00000011700023246","lower":"03001ZJ00000011700011946","count":1563,"preSum":3124},{"ndv":1125,"upper":"03001ZJ00000011700032819","lower":"03001ZJ00000011700023249","count":1562,"preSum":4687},{"ndv":1129,"upper":"03001ZJ00000011700050590","lower":"03001ZJ00000011700032840","count":1562,"preSum":6249},{"ndv":1113,"upper":"03001ZJ00000011800009902","lower":"03001ZJ00000011700050594","count":1562,"preSum":7811},{"ndv":1143,"upper":"03001ZJ00000011800027429","lower":"03001ZJ00000011800009903","count":1563,"preSum":9373},{"ndv":1181,"upper":"03001ZJ00000011900011735","lower":"03001ZJ00000011800027450","count":1562,"preSum":10936},{"ndv":1128,"upper":"03001ZJ00000012000001088","lower":"03001ZJ00000011900011740","count":1563,"preSum":12498},{"ndv":1080,"upper":"03001ZJ00000012000011786","lower":"03001ZJ00000012000001095","count":1563,"preSum":14061},{"ndv":1107,"upper":"03001ZJ00000021700001645","lower":"03001ZJ00000012000011797","count":1563,"preSum":15624},{"ndv":1112,"upper":"03001ZJ00000021700009320","lower":"03001ZJ00000021700001653","count":1563,"preSum":17187},{"ndv":1129,"upper":"03001ZJ00000021700020758","lower":"03001ZJ00000021700009330","count":1562,"preSum":18750},{"ndv":1116,"upper":"03001ZJ00000021700028975","lower":"03001ZJ00000021700020761","count":1564,"preSum":20312},{"ndv":1090,"upper":"03001ZJ00000021800006599","lower":"03001ZJ00000021700028979","count":1562,"preSum":21876},{"ndv":1146,"upper":"03001ZJ00000021900006506","lower":"03001ZJ00000021800006644","count":1562,"preSum":23438},{"ndv":1166,"upper":"03001ZJ00000022000002600","lower":"03001ZJ00000021900006512","count":1563,"preSum":25000},{"ndv":1111,"upper":"03001ZJ00000031707001117","lower":"03001ZJ00000022000002610","count":1562,"preSum":26563},{"ndv":1177,"upper":"03001ZJ00000031707007473","lower":"03001ZJ00000031707001119","count":1562,"preSum":28125},{"ndv":1182,"upper":"03001ZJ00000031710002707","lower":"03001ZJ00000031707007475","count":1562,"preSum":29687},{"ndv":1203,"upper":"03001ZJ00000031710009949","lower":"03001ZJ00000031710002708","count":1562,"preSum":31249},{"ndv":1201,"upper":"03001ZJ00000031721001600","lower":"03001ZJ00000031710009950","count":1562,"preSum":32811},{"ndv":1097,"upper":"03001ZJ00000031800009846","lower":"03001ZJ00000031721001602","count":1562,"preSum":34373},{"ndv":1160,"upper":"03001ZJ00000031900003495","lower":"03001ZJ00000031800009847","count":1562,"preSum":35935},{"ndv":1092,"upper":"03001ZJ00000032000002501","lower":"03001ZJ00000031900003515","count":1562,"preSum":37497},{"ndv":1148,"upper":"03001ZJ00000041700004055","lower":"03001ZJ00000032000002507","count":1562,"preSum":39059},{"ndv":1212,"upper":"03001ZJ00000041700018172","lower":"03001ZJ00000041700004058","count":1562,"preSum":40621},{"ndv":1126,"upper":"03001ZJ00000041700023639","lower":"03001ZJ00000041700018174","count":1562,"preSum":42183},{"ndv":1216,"upper":"03001ZJ00000041800001491","lower":"03001ZJ00000041700023647","count":1562,"preSum":43745},{"ndv":1166,"upper":"03001ZJ00000041900002796","lower":"03001ZJ00000041800001509","count":1563,"preSum":45307},{"ndv":1121,"upper":"03001ZJ00000042000000659","lower":"03001ZJ00000041900002797","count":1562,"preSum":46870},{"ndv":1134,"upper":"03001ZJ00000051700006114","lower":"03001ZJ00000042000000668","count":1566,"preSum":48432},{"ndv":1141,"upper":"03001ZJ00000051700014962","lower":"03001ZJ00000051700006122","count":1562,"preSum":49998},{"ndv":1138,"upper":"03001ZJ00000051800000553","lower":"03001ZJ00000051700014965","count":1562,"preSum":51560},{"ndv":1134,"upper":"03001ZJ00000051800007348","lower":"03001ZJ00000051800000554","count":1564,"preSum":53122},{"ndv":1125,"upper":"03001ZJ00000051900006915","lower":"03001ZJ00000051800007350","count":1562,"preSum":54686},{"ndv":1238,"upper":"03001ZP00000041800008572","lower":"03001ZJ00000051900006919","count":1562,"preSum":56248},{"ndv":1141,"upper":"03061ZJ00000001500111816","lower":"03001ZP00000041800009071","count":1562,"preSum":57810},{"ndv":1243,"upper":"03061ZJ00000001604783483","lower":"03061ZJ00000001601664195","count":1562,"preSum":59372},{"ndv":1206,"upper":"03061ZJ00000001702283500","lower":"03061ZJ00000001604783489","count":1562,"preSum":60934},{"ndv":1259,"upper":"03131ZJ00000001701523478","lower":"03061ZJ00000001702283501","count":1564,"preSum":62496},{"ndv":1213,"upper":"03141ZJ00000000516000434","lower":"03131ZJ00000001701523484","count":1564,"preSum":64060},{"ndv":1143,"upper":"03141ZJ00000008017000962","lower":"03141ZJ00000000516000437","count":1562,"preSum":65624},{"ndv":1205,"upper":"03181ZJ00000001603503508","lower":"03141ZJ00000008017000965","count":1562,"preSum":67186},{"ndv":1184,"upper":"03191ZJ00000001700000281","lower":"03181ZJ00000001603503514","count":1562,"preSum":68748},{"ndv":1133,"upper":"03201ZJ00000001601446365","lower":"03191ZJ00000001700000289","count":1562,"preSum":70310},{"ndv":1262,"upper":"03511ZJ00000001602730192","lower":"03201ZJ00000001601446422","count":1562,"preSum":71872},{"ndv":1093,"upper":"03521ZJ00000001601012652","lower":"03511ZJ00000001602730200","count":1562,"preSum":73434},{"ndv":1082,"upper":"03521ZJ00000001701439594","lower":"03521ZJ00000001601012654","count":1565,"preSum":74996},{"ndv":1233,"upper":"03591ZJ00000002100291493","lower":"03521ZJ00000001701439595","count":1563,"preSum":76561},{"ndv":1172,"upper":"03591ZJ00000002100299850","lower":"03591ZJ00000002100291505","count":1562,"preSum":78124},{"ndv":1142,"upper":"03591ZJ00000002200320697","lower":"03591ZJ00000002100299856","count":1562,"preSum":79686},{"ndv":1143,"upper":"03591ZJ00000002300336298","lower":"03591ZJ00000002200320718","count":1563,"preSum":81248},{"ndv":1148,"upper":"143170000128","lower":"03591ZJ00000002300336362","count":1562,"preSum":82811},{"ndv":1189,"upper":"172170003400","lower":"143170000189","count":1562,"preSum":84373},{"ndv":1187,"upper":"440960000027","lower":"172170003402","count":1563,"preSum":85935},{"ndv":1245,"upper":"440960017249","lower":"440960000039","count":1562,"preSum":87498},{"ndv":1140,"upper":"441542170229","lower":"440960017254","count":1563,"preSum":89060},{"ndv":1173,"upper":"CJ4877","lower":"441542170230","count":1562,"preSum":90623},{"ndv":1212,"upper":"J17514900A","lower":"CJ4891","count":1562,"preSum":92185},{"ndv":1146,"upper":"J17792591A","lower":"J17514911A","count":1563,"preSum":93747},{"ndv":1183,"upper":"JJ01082209","lower":"J17792592A","count":1563,"preSum":95310},{"ndv":1256,"upper":"JP01071370","lower":"JJ01082213","count":1562,"preSum":96873},{"ndv":1107,"upper":"ZTP00011575","lower":"JP01072283","count":1529,"preSum":98435}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[10,9,9,9],"valueArr":["03001ZJ00000031900000102","03001ZJ00000041700024334","J17514525A","ZJZ00007034"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tm_comm_addr',1792510,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1170,"upper":"440281008906","lower":"00000001","count":1561,"preSum":0},{"ndv":1114,"upper":"4405102257FA","lower":"440281008910","count":1561,"preSum":1561},{"ndv":1102,"upper":"440514840657","lower":"440510225800","count":1561,"preSum":3122},{"ndv":1215,"upper":"4406001514E0","lower":"440514840676","count":1562,"preSum":4683},{"ndv":1255,"upper":"4406001C2F37","lower":"4406001516B9","count":1561,"preSum":6245},{"ndv":1154,"upper":"44070300A05F","lower":"4406001C2F4A","count":1561,"preSum":7806},{"ndv":1248,"upper":"440703010544","lower":"44070300A064","count":1561,"preSum":9367},{"ndv":1173,"upper":"440877002205","lower":"440703010547","count":1561,"preSum":10928},{"ndv":1192,"upper":"440960010450","lower":"440877002206","count":1562,"preSum":12489},{"ndv":1198,"upper":"440960019145","lower":"440960010460","count":1562,"preSum":14051},{"ndv":1161,"upper":"4412030032A3","lower":"440960019151","count":1561,"preSum":15613},{"ndv":1256,"upper":"441345000741","lower":"4412030032AA","count":1561,"preSum":17174},{"ndv":1262,"upper":"441357006817","lower":"44134500074D","count":1561,"preSum":18735},{"ndv":1152,"upper":"441426009EE6","lower":"441357006862","count":1561,"preSum":20296},{"ndv":1159,"upper":"441547171360","lower":"441426009F05","count":1561,"preSum":21857},{"ndv":1204,"upper":"441803035340","lower":"441547171364","count":1562,"preSum":23418},{"ndv":1178,"upper":"441941005893","lower":"441803035342","count":1561,"preSum":24980},{"ndv":1127,"upper":"44200000B68E","lower":"441941005914","count":1561,"preSum":26541},{"ndv":1250,"upper":"444922000152","lower":"44200000B68F","count":1562,"preSum":28102},{"ndv":1127,"upper":"44520009C50A","lower":"444922000162","count":1561,"preSum":29664},{"ndv":1070,"upper":"445281086D74","lower":"44520009C50B","count":1561,"preSum":31225},{"ndv":1140,"upper":"445303001736","lower":"445281086D76","count":1561,"preSum":32786},{"ndv":1160,"upper":"44711700148C","lower":"445303001738","count":1561,"preSum":34347},{"ndv":1154,"upper":"447117004270","lower":"447117001490","count":1561,"preSum":35908},{"ndv":1116,"upper":"44711700719E","lower":"447117004278","count":1561,"preSum":37469},{"ndv":1102,"upper":"44711700ADDD","lower":"4471170071A0","count":1561,"preSum":39030},{"ndv":1134,"upper":"447118000BB4","lower":"44711700ADDF","count":1562,"preSum":40591},{"ndv":1190,"upper":"44711800548B","lower":"447118000BB5","count":1561,"preSum":42153},{"ndv":1131,"upper":"447119001CF5","lower":"44711800548E","count":1561,"preSum":43714},{"ndv":1139,"upper":"447119003BCE","lower":"447119001CF9","count":1561,"preSum":45275},{"ndv":1105,"upper":"447120001306","lower":"447119003BCF","count":1562,"preSum":46836},{"ndv":1094,"upper":"447120003BD8","lower":"44712000130A","count":1561,"preSum":48398},{"ndv":1139,"upper":"4471220522FC","lower":"447120003BE1","count":1561,"preSum":49959},{"ndv":1094,"upper":"4472170019D4","lower":"447217000001","count":1562,"preSum":51520},{"ndv":1080,"upper":"4472170047F2","lower":"4472170019D5","count":1561,"preSum":53082},{"ndv":1174,"upper":"4472170069AD","lower":"4472170047F3","count":1561,"preSum":54643},{"ndv":1065,"upper":"447218000ED2","lower":"4472170069AE","count":1561,"preSum":56204},{"ndv":1144,"upper":"447219000D97","lower":"447218000ED6","count":1562,"preSum":57765},{"ndv":1159,"upper":"44722000026E","lower":"447219000D9C","count":1561,"preSum":59327},{"ndv":1128,"upper":"44722000184C","lower":"44722000026F","count":1561,"preSum":60888},{"ndv":1130,"upper":"4473173D06C2","lower":"44722000184E","count":1563,"preSum":62449},{"ndv":1173,"upper":"4473173D1FA7","lower":"4473173D06C9","count":1561,"preSum":64012},{"ndv":1195,"upper":"4473175B0CA6","lower":"4473173D1FA9","count":1562,"preSum":65573},{"ndv":1200,"upper":"4473175B28EF","lower":"4473175B0CA8","count":1561,"preSum":67135},{"ndv":1196,"upper":"447317C90A2A","lower":"4473175B28F0","count":1561,"preSum":68696},{"ndv":1097,"upper":"447318002CBB","lower":"447317C90A36","count":1561,"preSum":70257},{"ndv":1143,"upper":"44731900103C","lower":"447318002CBC","count":1561,"preSum":71818},{"ndv":1100,"upper":"447320000C00","lower":"44731900103F","count":1562,"preSum":73379},{"ndv":1127,"upper":"447417000D35","lower":"447320000C04","count":1561,"preSum":74941},{"ndv":1225,"upper":"447417004348","lower":"447417000D3C","count":1561,"preSum":76502},{"ndv":1124,"upper":"447417005A60","lower":"447417004360","count":1561,"preSum":78063},{"ndv":1187,"upper":"44741800013E","lower":"447417005A63","count":1561,"preSum":79624},{"ndv":1154,"upper":"447419000205","lower":"447418000141","count":1561,"preSum":81185},{"ndv":1140,"upper":"4474190024BF","lower":"44741900020B","count":1561,"preSum":82746},{"ndv":1152,"upper":"4475170010F4","lower":"4474190024C0","count":1561,"preSum":84307},{"ndv":1133,"upper":"447517002537","lower":"4475170010F5","count":1561,"preSum":85868},{"ndv":1148,"upper":"4475170051BA","lower":"44751700253C","count":1564,"preSum":87429},{"ndv":1114,"upper":"447518001381","lower":"4475170051BF","count":1561,"preSum":88993},{"ndv":1140,"upper":"447519000FAD","lower":"44751800138C","count":1562,"preSum":90554},{"ndv":1114,"upper":"447619001096","lower":"447519000FB1","count":1561,"preSum":92116},{"ndv":1201,"upper":"447720047A60","lower":"4476190010AE","count":1561,"preSum":93677},{"ndv":1179,"upper":"447820049859","lower":"447720047A63","count":1562,"preSum":95238},{"ndv":1499,"upper":"449220005A54","lower":"447820049863","count":1561,"preSum":96800},{"ndv":1318,"upper":"95291469","lower":"449220005B25","count":1531,"preSum":98361}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[21,9,9,10,9,47],"valueArr":["1","440456005750","440851004525","447319000066","447417005F0E","jyzdplzcjl"],"type":"String","sampleRate":0.924351804778851}',4,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tm_comm_modula_type_code',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tm_equ_sort_code',6,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1922,730,96936,48,99,266],"valueArr":["03","04","05","06","07","26"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tm_equ_status_code',1,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[100001],"valueArr":["1"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tm_factory_id',461,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":"0000000000000045","lower":"0000000000000008","count":351,"preSum":0},{"ndv":11,"upper":"0000000000000159","lower":"0000000000000080","count":621,"preSum":351},{"ndv":9,"upper":"0000000000000290","lower":"0000000000000175","count":308,"preSum":972},{"ndv":7,"upper":"0000000000000371","lower":"0000000000000291","count":812,"preSum":1280},{"ndv":9,"upper":"030200000000200","lower":"0000000000000413","count":901,"preSum":2092},{"ndv":2,"upper":"030200000000243","lower":"030200000000205","count":1110,"preSum":2993},{"ndv":2,"upper":"030200000000297","lower":"030200000000293","count":678,"preSum":4103},{"ndv":6,"upper":"030200000000995","lower":"030200000000371","count":1257,"preSum":4781},{"ndv":4,"upper":"0313000000017","lower":"030200000001021","count":342,"preSum":6038},{"ndv":2,"upper":"0811111113261116","lower":"0811111111406118","count":602,"preSum":6380},{"ndv":2,"upper":"1111111111111535","lower":"1111111111111534","count":954,"preSum":6982},{"ndv":1,"upper":"1111111111121112","lower":"1111111111121112","count":1250,"preSum":7936},{"ndv":4,"upper":"1111111111201126","lower":"1111111111166141","count":670,"preSum":9186},{"ndv":3,"upper":"1111111111216135","lower":"1111111111211180","count":376,"preSum":9856},{"ndv":3,"upper":"1111111111221124","lower":"1111111111216183","count":504,"preSum":10232},{"ndv":4,"upper":"1111111111406114","lower":"1111111111231112","count":665,"preSum":10736},{"ndv":2,"upper":"1111111111581114","lower":"1111111111521114","count":1199,"preSum":11401},{"ndv":9,"upper":"1111111112281115","lower":"1111111111611114","count":497,"preSum":12600},{"ndv":1,"upper":"1111111112476117","lower":"1111111112476117","count":535,"preSum":13097},{"ndv":3,"upper":"3111111116051152","lower":"1111111113901130","count":673,"preSum":13632},{"ndv":1,"upper":"3111111116311148","lower":"3111111116311148","count":205,"preSum":14305}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[3921,1639,3687,13274,12804,1544,13915,5742,4447,3585,6667,7768,4218,2251],"valueArr":["0000000000000046","0000000000000380","1111111111161112","1111111111176135","1111111111191113","1111111111216277","1111111111411114","1111111111516114","1111111111736114","1111111112046116","1111111112076116","1111111112081115","1111111112126118","1111111112226119"],"type":"String","sampleRate":0.924351804778851}',29,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tm_factory_short_name',427,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":11,"upper":"华立科技有限公司","lower":"JSLY","count":642,"preSum":0},{"ndv":4,"upper":"宁波三星电器股份有限公司","lower":"华立集团股份有限公司","count":737,"preSum":642},{"ndv":6,"upper":"广东卓维网络有限公司","lower":"宁波三星电气有限公司","count":184,"preSum":1379},{"ndv":10,"upper":"杭州炬华","lower":"广东南方电力集团科技发展有限公司","count":596,"preSum":1563},{"ndv":4,"upper":"江苏林洋电子股份有限公司","lower":"杭州炬华科技有限公司","count":635,"preSum":2159},{"ndv":4,"upper":"浙江华立科技有限公司","lower":"江苏祥源电气设备有限公司","count":752,"preSum":2794},{"ndv":1,"upper":"浙江华立科技股份有限公司","lower":"浙江华立科技股份有限公司","count":1102,"preSum":3546},{"ndv":3,"upper":"海兴电力","lower":"浙江正泰","count":537,"preSum":4648},{"ndv":3,"upper":"深圳友讯达","lower":"深圳农电电气有限公司","count":211,"preSum":5185},{"ndv":8,"upper":"深圳浩宁达仪表股份有限公司","lower":"深圳奇辉电气有限公司","count":861,"preSum":5396},{"ndv":3,"upper":"深圳科陆电子有限公司","lower":"深圳浩宁达电能仪表制造有限公司","count":305,"preSum":6257},{"ndv":4,"upper":"湖南威胜信息技术有限公司","lower":"深圳科陆电子科技股份有限公司","count":1356,"preSum":6562},{"ndv":2,"upper":"烟台威思顿","lower":"烟台东方威思顿电气有限公司","count":742,"preSum":7918},{"ndv":2,"upper":"长沙威胜信息技术有限公司CDMA","lower":"盛帆","count":1126,"preSum":8660},{"ndv":1,"upper":"长沙威胜电子有限公司","lower":"长沙威胜电子有限公司","count":337,"preSum":9786},{"ndv":3,"upper":"青岛鼎信","lower":"青岛东软","count":649,"preSum":10123},{"ndv":2,"upper":"鼎信信息","lower":"青岛鼎信科技股份有限公司","count":16,"preSum":10772}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[12804,1250,7768,5742,8677,1610,6711,4040,4084,13915,1639,14343,2251,4350],"valueArr":["三星","光一科技股份有限公司","华立","华立科技股份有限公司","威胜信息","威胜集团有限公司","宁波三星","杭州海兴电力科技股份有限公司","江苏林洋","江苏林洋能源股份有限公司","浙江正泰仪器仪表有限责任公司","深圳市科陆电子科技股份有限公司","深圳科陆","长沙威胜信息技术有限公司"],"type":"String","sampleRate":0.924351804778851}',29,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tm_main_term_flag',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[381,3598],"valueArr":["0","1"],"type":"String","sampleRate":0.924351804778851}',96022,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tm_term_type',10,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"0610000","lower":"0610000","count":2,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1922,728,91829,123,4984,46,33,66,268],"valueArr":["0330000","0430000","0530000","05300001","0540000","0620000","0731000","0732000","2630000"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tm_up_protocol_code',124,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"01","lower":"01","count":4,"preSum":0},{"ndv":1,"upper":"04","lower":"04","count":1,"preSum":4},{"ndv":1,"upper":"04;11","lower":"04;11","count":1,"preSum":5},{"ndv":1,"upper":"17","lower":"17","count":6,"preSum":6},{"ndv":1,"upper":"17;19","lower":"17;19","count":2,"preSum":12},{"ndv":1,"upper":"1;11","lower":"1;11","count":8,"preSum":14},{"ndv":1,"upper":"2","lower":"2","count":1,"preSum":22},{"ndv":1,"upper":"21","lower":"21","count":1,"preSum":23},{"ndv":1,"upper":"6","lower":"6","count":1,"preSum":24}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[145,902,69203,850,1131,13,4223,111,77,30,5107,102,81,5122],"valueArr":["05","1","11","11.0","11;9","13;14","14","16","19","1;2","4","9","Q/CSG 11","Q/CSG 11109004-2013"],"type":"String","sampleRate":0.924351804778851}',12879,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tq_area_attr_code',4,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[5455,9847,29401,53934],"valueArr":["1","2","3","4"],"type":"String","sampleRate":0.924351804778851}',1364,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tq_ll_exam_type',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tq_run_status_code',3,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[98769,574,9],"valueArr":["01","02","03"],"type":"String","sampleRate":0.924351804778851}',649,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tq_ta_addr',366609,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":185,"upper":"10**********1变","lower":" *****************************压器","count":836,"preSum":0},{"ndv":274,"upper":"G2*********************台变","lower":"10**********1杆","count":836,"preSum":836},{"ndv":411,"upper":"下**梅","lower":"G2********************电站","count":837,"preSum":1672},{"ndv":403,"upper":"东莞***********************g)","lower":"下**民","count":837,"preSum":2509},{"ndv":362,"upper":"中***段","lower":"东莞***********************公司","count":836,"preSum":3346},{"ndv":513,"upper":"云浮***********中旁","lower":"中***泊","count":836,"preSum":4182},{"ndv":472,"upper":"侨光***山庄","lower":"云浮**********公司","count":837,"preSum":5018},{"ndv":469,"upper":"凯*城","lower":"侨社*****箱变","count":840,"preSum":5855},{"ndv":433,"upper":"南*村","lower":"凯尊***宅变","count":849,"preSum":6695},{"ndv":438,"upper":"台山******坑村","lower":"南*江","count":836,"preSum":7544},{"ndv":488,"upper":"圩*","lower":"台山******学村","count":846,"preSum":8380},{"ndv":451,"upper":"大*","lower":"圩***东","count":870,"preSum":9226},{"ndv":467,"upper":"宅梧****林村","lower":"大***中","count":838,"preSum":10096},{"ndv":381,"upper":"岐*村","lower":"宅梧****背村","count":838,"preSum":10934},{"ndv":372,"upper":"广东********************* ","lower":"岐北****校边","count":842,"preSum":11772},{"ndv":241,"upper":"广东****************************************地区","lower":"广东*********************#1","count":845,"preSum":12614},{"ndv":190,"upper":"广东***********************************房)","lower":"广东****************************************地块","count":877,"preSum":13459},{"ndv":168,"upper":"广东********************************站)","lower":"广东***********************************支线","count":846,"preSum":14336},{"ndv":183,"upper":"广东*****************************9号","lower":"广东********************************箱变","count":840,"preSum":15182},{"ndv":154,"upper":"广东****************************电站","lower":"广东*****************************g)","count":849,"preSum":16022},{"ndv":187,"upper":"广东**************************南侧","lower":"广东****************************电)","count":839,"preSum":16871},{"ndv":168,"upper":"广东*************************大观","lower":"广东**************************南段","count":837,"preSum":17710},{"ndv":143,"upper":"广东************************地段","lower":"广东*************************委会","count":838,"preSum":18547},{"ndv":189,"upper":"广东***********************宅)","lower":"广东************************地)","count":865,"preSum":19385},{"ndv":198,"upper":"广东**********************地块","lower":"广东***********************安村","count":856,"preSum":20250},{"ndv":210,"upper":"广东*********************园内","lower":"广东**********************地段","count":836,"preSum":21106},{"ndv":202,"upper":"广东********************二期","lower":"广东*********************园旁","count":838,"preSum":21942},{"ndv":200,"upper":"广东********************路侧","lower":"广东********************五巷","count":836,"preSum":22780},{"ndv":258,"upper":"广东*******************所前","lower":"广东********************路北","count":836,"preSum":23616},{"ndv":240,"upper":"广东******************园)","lower":"广东*******************所旁","count":836,"preSum":24452},{"ndv":274,"upper":"广东*****************1栋","lower":"广东******************园侧","count":836,"preSum":25288},{"ndv":232,"upper":"广东*****************店边","lower":"广东*****************1)","count":837,"preSum":26124},{"ndv":284,"upper":"广东****************公坑","lower":"广东*****************庙村","count":836,"preSum":26961},{"ndv":235,"upper":"广东****************播村","lower":"广东****************公寓","count":837,"preSum":27797},{"ndv":295,"upper":"广东***************4杆","lower":"广东****************支线","count":836,"preSum":28634},{"ndv":282,"upper":"广东***************材城","lower":"广东***************4栋","count":839,"preSum":29470},{"ndv":318,"upper":"广东**************变侧","lower":"广东***************村口","count":837,"preSum":30309},{"ndv":317,"upper":"广东*************2号","lower":"广东**************口村","count":839,"preSum":31146},{"ndv":255,"upper":"广东*************心村","lower":"广东*************2杆","count":838,"preSum":31985},{"ndv":322,"upper":"广东************农场","lower":"广东*************心站","count":838,"preSum":32823},{"ndv":315,"upper":"广东************箱变","lower":"广东************冲村","count":853,"preSum":33661},{"ndv":299,"upper":"广东***********坡村","lower":"广东************粮仓","count":840,"preSum":34514},{"ndv":301,"upper":"广东***********琅路","lower":"广东***********坡镇","count":836,"preSum":35354},{"ndv":349,"upper":"广东**********大里","lower":"广东***********理区","count":836,"preSum":36190},{"ndv":383,"upper":"广东*********新村","lower":"广东**********大镇","count":840,"preSum":37026},{"ndv":315,"upper":"广东********梓村","lower":"广东*********旧围","count":837,"preSum":37866},{"ndv":281,"upper":"广东*****湾镇","lower":"广东********梓镇","count":839,"preSum":38703},{"ndv":457,"upper":"惠*市","lower":"广东*****源县","count":841,"preSum":39542},{"ndv":458,"upper":"新*新","lower":"惠*路","count":839,"preSum":40383},{"ndv":461,"upper":"月***村","lower":"新*村","count":836,"preSum":41222},{"ndv":500,"upper":"梅花********湾村","lower":"月***边","count":838,"preSum":42058},{"ndv":489,"upper":"汕尾********东村","lower":"梅花*******家村","count":836,"preSum":42896},{"ndv":472,"upper":"洪冠***台变","lower":"汕尾********坝墟","count":837,"preSum":43732},{"ndv":516,"upper":"漱云***湖村","lower":"洪厝**用台","count":836,"preSum":44569},{"ndv":485,"upper":"登云*******公变","lower":"潘*","count":837,"preSum":45405},{"ndv":417,"upper":"碧桥***公变","lower":"登云******公变","count":836,"preSum":46242},{"ndv":494,"upper":"羊梅***台变","lower":"碧水****************压器","count":837,"preSum":47078},{"ndv":489,"upper":"荔*","lower":"羊角******边村","count":838,"preSum":47915},{"ndv":457,"upper":"谢*","lower":"荔***变","count":839,"preSum":48753},{"ndv":490,"upper":"里湖***内村","lower":"谢***元","count":836,"preSum":49592},{"ndv":419,"upper":"长*里","lower":"里湖***用台","count":836,"preSum":50428},{"ndv":523,"upper":"顿岗**村村","lower":"长*镇","count":836,"preSum":51264},{"ndv":461,"upper":"黄***变","lower":"顿岗**留村","count":838,"preSum":52100},{"ndv":294,"upper":"5*区","lower":"黄***台","count":527,"preSum":52938}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[1140,88,69,75,79,87,76,69,73,93,113,498,103],"valueArr":["*","10**************压器","10********台变","10*******台变","10******台变","广东***************************房)","广东**************************房)","广东************************房)","广东**********************电房","广东***************员会","广东**************委会","广东*************委会","广东*****城区"],"type":"String","sampleRate":0.924351804778851}',43973,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tq_ta_id',1590542,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1134,"upper":"02900000185","lower":"020000002820","count":1551,"preSum":0},{"ndv":1091,"upper":"043071091050085","lower":"029000001858","count":1551,"preSum":1551},{"ndv":1023,"upper":"0513009047","lower":"043071093010037","count":1551,"preSum":3102},{"ndv":1054,"upper":"059000015258","lower":"0513009048","count":1552,"preSum":4653},{"ndv":1096,"upper":"059000030113","lower":"059000015259","count":1551,"preSum":6205},{"ndv":1108,"upper":"061000000290","lower":"059000030120","count":1551,"preSum":7756},{"ndv":1175,"upper":"064001000083","lower":"061000000295","count":1551,"preSum":9307},{"ndv":1170,"upper":"0663002846","lower":"064001000088","count":1551,"preSum":10858},{"ndv":1090,"upper":"069000055969","lower":"0663002849","count":1551,"preSum":12409},{"ndv":1087,"upper":"07209042","lower":"069000056158","count":1551,"preSum":13960},{"ndv":1062,"upper":"07605149","lower":"07209046","count":1551,"preSum":15511},{"ndv":1048,"upper":"0770S157","lower":"07605155","count":1551,"preSum":17062},{"ndv":1151,"upper":"082118","lower":"0770S159","count":1551,"preSum":18613},{"ndv":1130,"upper":"08C18078","lower":"082120","count":1552,"preSum":20164},{"ndv":1187,"upper":"08o1338","lower":"08C18086","count":1551,"preSum":21716},{"ndv":1124,"upper":"090000005916","lower":"08o1340","count":1552,"preSum":23267},{"ndv":1151,"upper":"095060003028","lower":"090000005965","count":1551,"preSum":24819},{"ndv":1182,"upper":"098260000014","lower":"095060003029","count":1552,"preSum":26370},{"ndv":1197,"upper":"120000002140","lower":"098260000026","count":1551,"preSum":27922},{"ndv":1025,"upper":"120000038607","lower":"120000002142","count":1551,"preSum":29473},{"ndv":1137,"upper":"129017046","lower":"120000038667","count":1551,"preSum":31024},{"ndv":1087,"upper":"131000046819","lower":"129017057","count":1552,"preSum":32575},{"ndv":1232,"upper":"137100000309","lower":"131000046923","count":1551,"preSum":34127},{"ndv":1095,"upper":"13ZD0000038417","lower":"137100000312","count":1551,"preSum":35678},{"ndv":1136,"upper":"145026000070","lower":"13ZD0000038572","count":1551,"preSum":37229},{"ndv":1075,"upper":"149000029713","lower":"145026000071","count":1551,"preSum":38780},{"ndv":1101,"upper":"1521M10010371","lower":"149000029714","count":1551,"preSum":40331},{"ndv":1186,"upper":"16LY11BG24","lower":"1521M20010051","count":1551,"preSum":41882},{"ndv":1187,"upper":"17B044","lower":"16LY11BG50","count":1551,"preSum":43433},{"ndv":1189,"upper":"1809018621","lower":"17B048","count":1551,"preSum":44984},{"ndv":1172,"upper":"189000010075","lower":"1809018623","count":1551,"preSum":46535},{"ndv":1128,"upper":"18ZD9000042053","lower":"189000010076","count":1551,"preSum":48086},{"ndv":1045,"upper":"19189000038370","lower":"18ZD9000042139","count":1555,"preSum":49637},{"ndv":1085,"upper":"195007200955","lower":"19189000038532","count":1551,"preSum":51192},{"ndv":1153,"upper":"199000013767","lower":"195007201183","count":1551,"preSum":52743},{"ndv":1161,"upper":"202000184332","lower":"199000013770","count":1552,"preSum":54294},{"ndv":1206,"upper":"209000025811","lower":"202000184334","count":1551,"preSum":55846},{"ndv":1023,"upper":"2222222222890416","lower":"209000025835","count":1551,"preSum":57397},{"ndv":1037,"upper":"2222222223094746","lower":"2222222222890440","count":1551,"preSum":58948},{"ndv":1097,"upper":"2222222223166824","lower":"2222222223094766","count":1552,"preSum":60499},{"ndv":1096,"upper":"2222222223291546","lower":"2222222223166844","count":1551,"preSum":62051},{"ndv":1105,"upper":"2222222223850089","lower":"2222222223291562","count":1551,"preSum":63602},{"ndv":1098,"upper":"2222222225199865","lower":"2222222223850122","count":1552,"preSum":65153},{"ndv":1111,"upper":"2222222227504801","lower":"2222222225199911","count":1551,"preSum":66705},{"ndv":1037,"upper":"2222222228570818","lower":"2222222227504833","count":1553,"preSum":68256},{"ndv":1126,"upper":"2222222229065460","lower":"2222222228570819","count":1551,"preSum":69809},{"ndv":1085,"upper":"2222222231245194","lower":"2222222229065501","count":1551,"preSum":71360},{"ndv":1064,"upper":"2222222231685357","lower":"2222222231245204","count":1551,"preSum":72911},{"ndv":1039,"upper":"2222222232615634","lower":"2222222231685369","count":1553,"preSum":74462},{"ndv":1042,"upper":"2222222233346254","lower":"2222222232615642","count":1551,"preSum":76015},{"ndv":1062,"upper":"2222222234226524","lower":"2222222233346390","count":1552,"preSum":77566},{"ndv":1115,"upper":"2222222234432462","lower":"2222222234226664","count":1551,"preSum":79118},{"ndv":1070,"upper":"2222222234906794","lower":"2222222234432501","count":1552,"preSum":80669},{"ndv":1085,"upper":"2222222235181838","lower":"2222222234911461","count":1551,"preSum":82221},{"ndv":1056,"upper":"2222222235288100","lower":"2222222235181934","count":1552,"preSum":83772},{"ndv":1072,"upper":"2222222235369382","lower":"2222222235288128","count":1551,"preSum":85324},{"ndv":1090,"upper":"2222222235442216","lower":"2222222235369396","count":1551,"preSum":86875},{"ndv":1133,"upper":"2222222235619562","lower":"2222222235442271","count":1551,"preSum":88426},{"ndv":1100,"upper":"515121006064","lower":"2222222235619596","count":1552,"preSum":89977},{"ndv":1083,"upper":"523060006089","lower":"515121006065","count":1551,"preSum":91529},{"ndv":1033,"upper":"526180000016","lower":"523060006098","count":1551,"preSum":93080},{"ndv":1106,"upper":"529000014002","lower":"526180000024","count":1552,"preSum":94631},{"ndv":1087,"upper":"53000000014609","lower":"529000014003","count":1552,"preSum":96183},{"ndv":1149,"upper":"53ZQ0000013211","lower":"53000000014611","count":1516,"preSum":97735}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[11,13,10,10,15,11,11,10,10],"valueArr":["089000024500","16010900002488","2222222222830082","2222222222845386","2222222223143334","2222222231925505","2222222232757012","2222222233226195","2222222235332941"],"type":"String","sampleRate":0.924351804778851}',649,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tq_ta_name',557737,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":269,"upper":"10************************压器","lower":" *********************************************0)","count":1353,"preSum":0},{"ndv":51,"upper":"10********************压器","lower":"10************************台区","count":1391,"preSum":1353},{"ndv":127,"upper":"10*************台变","lower":"10********************台变","count":1410,"preSum":2744},{"ndv":42,"upper":"10***********压器","lower":"10*************干变","count":1499,"preSum":4154},{"ndv":39,"upper":"10*********压器","lower":"10***********变箱","count":1292,"preSum":5653},{"ndv":50,"upper":"10*******公变","lower":"10*********变 ","count":1299,"preSum":6945},{"ndv":50,"upper":"10*****公变","lower":"10*******公用","count":1288,"preSum":8244},{"ndv":349,"upper":"G1******************************压器","lower":"10*****压器","count":1289,"preSum":9532},{"ndv":234,"upper":"G5***************************压器","lower":"G1******************************器 ","count":1279,"preSum":10821},{"ndv":669,"upper":"三甲*****台变","lower":"G5***************************口村","count":1279,"preSum":12100},{"ndv":544,"upper":"下中***台变","lower":"三甲***台变","count":1279,"preSum":13379},{"ndv":629,"upper":"东塘***************1)","lower":"下丰***台变","count":1279,"preSum":14658},{"ndv":410,"upper":"东莞*****************台区","lower":"东塘********台变","count":1283,"preSum":15937},{"ndv":437,"upper":"中山************************压器","lower":"东莞*****************台架","count":1286,"preSum":17220},{"ndv":567,"upper":"乌塘**台变","lower":"中山************************变)","count":1279,"preSum":18506},{"ndv":671,"upper":"交警****箱变","lower":"乌廖*****箱变","count":1281,"preSum":19785},{"ndv":605,"upper":"佳兆**********宅变","lower":"交警***台变","count":1286,"preSum":21066},{"ndv":503,"upper":"八联***台变","lower":"佳兆********宅变","count":1279,"preSum":22352},{"ndv":707,"upper":"凤埠****台变","lower":"八角****台变","count":1282,"preSum":23631},{"ndv":676,"upper":"北潭**公变","lower":"凤壶******台变","count":1279,"preSum":24913},{"ndv":592,"upper":"南***1","lower":"北澳*****#1","count":1279,"preSum":26192},{"ndv":578,"upper":"博罗*************箱变","lower":"南***2","count":1279,"preSum":27471},{"ndv":663,"upper":"同安******台变","lower":"博罗************专变","count":1280,"preSum":28750},{"ndv":650,"upper":"四五********压器","lower":"同安*****台变","count":1281,"preSum":30030},{"ndv":588,"upper":"坡石*****台变","lower":"四伙**公变","count":1279,"preSum":31311},{"ndv":631,"upper":"墟***变","lower":"坡石****台变","count":1280,"preSum":32590},{"ndv":505,"upper":"大岭**台变","lower":"墟**3","count":1280,"preSum":33870},{"ndv":655,"upper":"太平***台变","lower":"大岭**心)","count":1282,"preSum":35150},{"ndv":656,"upper":"客都******箱变","lower":"太平***箱变","count":1280,"preSum":36432},{"ndv":629,"upper":"山下**台变","lower":"客鱼***台变","count":1283,"preSum":37712},{"ndv":644,"upper":"市场****箱变","lower":"山东*************公司","count":1279,"preSum":38995},{"ndv":680,"upper":"康丽*****压器","lower":"市场***台变","count":1279,"preSum":40274},{"ndv":600,"upper":"思劳***台变","lower":"康乐**#1","count":1280,"preSum":41553},{"ndv":410,"upper":"惠州***********公变","lower":"思可**台变","count":1292,"preSum":42833},{"ndv":664,"upper":"新*","lower":"惠州***********公司","count":1308,"preSum":44125},{"ndv":485,"upper":"新开**公变","lower":"新**#","count":1279,"preSum":45433},{"ndv":593,"upper":"时代**********2变","lower":"新德******公变","count":1286,"preSum":46712},{"ndv":575,"upper":"曹二******箱变","lower":"时代**********压器","count":1279,"preSum":47998},{"ndv":663,"upper":"枚坝**台变","lower":"曹二****箱变","count":1279,"preSum":49277},{"ndv":636,"upper":"梧桐******宅变","lower":"果***变","count":1288,"preSum":50556},{"ndv":621,"upper":"水关****用台","lower":"梨***变","count":1286,"preSum":51844},{"ndv":620,"upper":"江坝****台变","lower":"水冲****月)","count":1279,"preSum":53130},{"ndv":609,"upper":"河西**公变","lower":"江坳**台变","count":1280,"preSum":54409},{"ndv":649,"upper":"海湾******压器","lower":"河西**台变","count":1280,"preSum":55689},{"ndv":664,"upper":"滨河************压器","lower":"海湾****公变","count":1283,"preSum":56969},{"ndv":689,"upper":"玖龙*****宅变","lower":"滨河***********压器","count":1279,"preSum":58252},{"ndv":621,"upper":"白**变","lower":"玖龙****宅变","count":1288,"preSum":59531},{"ndv":597,"upper":"石岭*******压器","lower":"白**站","count":1279,"preSum":60819},{"ndv":552,"upper":"神洲**********压器","lower":"石岭*******台变","count":1279,"preSum":62098},{"ndv":683,"upper":"糖厂**用台","lower":"祠***变","count":1279,"preSum":63377},{"ndv":660,"upper":"美的***********压器","lower":"糖房**台变","count":1281,"preSum":64656},{"ndv":641,"upper":"船塘********公变","lower":"美的*********压器","count":1295,"preSum":65937},{"ndv":623,"upper":"荷兰*******宅变","lower":"船塘*******公变","count":1286,"preSum":67232},{"ndv":630,"upper":"西***台","lower":"荷兰******住宅","count":1284,"preSum":68518},{"ndv":668,"upper":"豪景***********压器","lower":"西***所","count":1281,"preSum":69802},{"ndv":576,"upper":"连平*******台区","lower":"豪景*****公变","count":1319,"preSum":71083},{"ndv":577,"upper":"金宝*******宅变","lower":"连平*******工厂","count":1280,"preSum":72402},{"ndv":593,"upper":"铜锣*****总表","lower":"金宝*******箱变","count":1281,"preSum":73682},{"ndv":546,"upper":"长滩**台变","lower":"铜鼓**台变","count":1279,"preSum":74963},{"ndv":626,"upper":"雍景***************************信)","lower":"长潭***电站","count":1280,"preSum":76242},{"ndv":682,"upper":"骏景**************压器","lower":"雍景***********压器","count":1282,"preSum":77522},{"ndv":641,"upper":"黄***变","lower":"骏景*************压器","count":1325,"preSum":78804},{"ndv":524,"upper":"龙江***************压器","lower":"黄***架","count":1279,"preSum":80129},{"ndv":190,"upper":"¥1*****************压器","lower":"龙江*************压器","count":391,"preSum":81408}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[529,778,915,1696,1211,1599,1000,803,1116,1421,1383,1823,1763,1516],"valueArr":["10*******************压器","10******************压器","10*****************压器","10****************压器","10***************压器","10**************压器","10*************压器","10************压器","10***********台变","10**********台变","10*********台变","10********台变","10*******台变","10******台变"],"type":"String","sampleRate":0.924351804778851}',649,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tq_ta_no',1588712,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1134,"upper":"02900000185","lower":"020000002820","count":1551,"preSum":0},{"ndv":1091,"upper":"043071086030074","lower":"029000001858","count":1551,"preSum":1551},{"ndv":1023,"upper":"0512008080","lower":"043071091050085","count":1551,"preSum":3102},{"ndv":1054,"upper":"059000015256","lower":"0513009031","count":1551,"preSum":4653},{"ndv":1095,"upper":"059000030104","lower":"059000015257","count":1551,"preSum":6204},{"ndv":1109,"upper":"061000000284","lower":"059000030107","count":1552,"preSum":7755},{"ndv":1177,"upper":"064001000083","lower":"061000000289","count":1553,"preSum":9307},{"ndv":1170,"upper":"0663002846","lower":"064001000088","count":1551,"preSum":10860},{"ndv":1090,"upper":"069000055969","lower":"0663002849","count":1551,"preSum":12411},{"ndv":1087,"upper":"07209042","lower":"069000056158","count":1551,"preSum":13962},{"ndv":1062,"upper":"07605149","lower":"07209046","count":1551,"preSum":15513},{"ndv":1048,"upper":"0770S157","lower":"07605155","count":1551,"preSum":17064},{"ndv":1151,"upper":"082118","lower":"0770S159","count":1551,"preSum":18615},{"ndv":1130,"upper":"08C18078","lower":"082120","count":1552,"preSum":20166},{"ndv":1187,"upper":"08o1338","lower":"08C18086","count":1551,"preSum":21718},{"ndv":1124,"upper":"090000005916","lower":"08o1340","count":1552,"preSum":23269},{"ndv":1151,"upper":"095060003028","lower":"090000005965","count":1551,"preSum":24821},{"ndv":1182,"upper":"098260000014","lower":"095060003029","count":1552,"preSum":26372},{"ndv":1197,"upper":"120000002140","lower":"098260000026","count":1551,"preSum":27924},{"ndv":1025,"upper":"120000038607","lower":"120000002142","count":1551,"preSum":29475},{"ndv":1137,"upper":"129017046","lower":"120000038667","count":1551,"preSum":31026},{"ndv":1087,"upper":"131000046819","lower":"129017057","count":1552,"preSum":32577},{"ndv":1232,"upper":"137100000309","lower":"131000046923","count":1551,"preSum":34129},{"ndv":1095,"upper":"13ZD0000038417","lower":"137100000312","count":1551,"preSum":35680},{"ndv":1136,"upper":"145026000070","lower":"13ZD0000038572","count":1551,"preSum":37231},{"ndv":1075,"upper":"149000029713","lower":"145026000071","count":1551,"preSum":38782},{"ndv":1101,"upper":"1521M10010371","lower":"149000029714","count":1551,"preSum":40333},{"ndv":1186,"upper":"16LY11BG24","lower":"1521M20010051","count":1551,"preSum":41884},{"ndv":1187,"upper":"17B044","lower":"16LY11BG50","count":1551,"preSum":43435},{"ndv":1189,"upper":"1809018621","lower":"17B048","count":1551,"preSum":44986},{"ndv":1172,"upper":"189000010075","lower":"1809018623","count":1551,"preSum":46537},{"ndv":1128,"upper":"18ZD9000042053","lower":"189000010076","count":1551,"preSum":48088},{"ndv":1045,"upper":"19189000038370","lower":"18ZD9000042139","count":1555,"preSum":49639},{"ndv":1085,"upper":"195007200448","lower":"19189000038532","count":1551,"preSum":51194},{"ndv":1153,"upper":"199000013766","lower":"195007200955","count":1551,"preSum":52745},{"ndv":1162,"upper":"202000184332","lower":"199000013767","count":1553,"preSum":54296},{"ndv":1206,"upper":"209000025811","lower":"202000184334","count":1551,"preSum":55849},{"ndv":1023,"upper":"2222222222890397","lower":"209000025835","count":1551,"preSum":57400},{"ndv":1038,"upper":"2222222223094707","lower":"2222222222890407","count":1551,"preSum":58951},{"ndv":1096,"upper":"2222222223166825","lower":"2222222223094727","count":1552,"preSum":60502},{"ndv":1096,"upper":"2222222223291547","lower":"2222222223166845","count":1551,"preSum":62054},{"ndv":1105,"upper":"2222222223850090","lower":"2222222223291563","count":1551,"preSum":63605},{"ndv":1097,"upper":"2222222225199866","lower":"2222222223850123","count":1551,"preSum":65156},{"ndv":1111,"upper":"2222222227504801","lower":"2222222225199912","count":1551,"preSum":66707},{"ndv":1037,"upper":"2222222228570818","lower":"2222222227504834","count":1553,"preSum":68258},{"ndv":1127,"upper":"2222222229065538","lower":"2222222228570819","count":1552,"preSum":69811},{"ndv":1084,"upper":"2222222231245140","lower":"2222222229065543","count":1551,"preSum":71363},{"ndv":1064,"upper":"2222222231685350","lower":"2222222231245194","count":1551,"preSum":72914},{"ndv":1041,"upper":"2222222232615635","lower":"2222222231685358","count":1555,"preSum":74465},{"ndv":1042,"upper":"2222222233346398","lower":"2222222232615643","count":1551,"preSum":76020},{"ndv":1061,"upper":"2222222234226672","lower":"2222222233346561","count":1551,"preSum":77571},{"ndv":1114,"upper":"2222222234431935","lower":"2222222234226677","count":1551,"preSum":79122},{"ndv":1072,"upper":"2222222234901670","lower":"2222222234432005","count":1551,"preSum":80673},{"ndv":1083,"upper":"2222222235181957","lower":"2222222234901676","count":1551,"preSum":82224},{"ndv":1056,"upper":"2222222235288149","lower":"2222222235182064","count":1552,"preSum":83775},{"ndv":1072,"upper":"2222222235369397","lower":"2222222235288159","count":1551,"preSum":85327},{"ndv":1092,"upper":"2222222235442816","lower":"2222222235369412","count":1551,"preSum":86878},{"ndv":1132,"upper":"2222222235619845","lower":"2222222235442820","count":1551,"preSum":88429},{"ndv":1098,"upper":"515121006065","lower":"2222222235619868","count":1551,"preSum":89980},{"ndv":1084,"upper":"523060006103","lower":"515121006066","count":1551,"preSum":91531},{"ndv":1033,"upper":"526180000025","lower":"523060006105","count":1552,"preSum":93082},{"ndv":1106,"upper":"529000014029","lower":"526180000026","count":1551,"preSum":94634},{"ndv":1086,"upper":"53000000014611","lower":"529000014037","count":1553,"preSum":96185},{"ndv":1148,"upper":"53ZQ0000013211","lower":"53000000014613","count":1513,"preSum":97738}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[11,13,10,10,15,11,11,10,10],"valueArr":["089000024500","16010900002488","2222222222830083","2222222222845387","2222222223143335","2222222231925505","2222222232757013","2222222233226196","2222222235332942"],"type":"String","sampleRate":0.924351804778851}',649,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','tq_ta_type',2,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[97659,1693],"valueArr":["01","02"],"type":"String","sampleRate":0.924351804778851}',649,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','trade_sort_code',435,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":6,"upper":"IA0300","lower":"00000","count":260,"preSum":0},{"ndv":1,"upper":"IA0500","lower":"IA0500","count":159,"preSum":260},{"ndv":1,"upper":"IA0502","lower":"IA0502","count":157,"preSum":419},{"ndv":4,"upper":"IC1312","lower":"IB0620","count":301,"preSum":576},{"ndv":4,"upper":"IC1710","lower":"IC1410","count":232,"preSum":877},{"ndv":1,"upper":"IC1811","lower":"IC1811","count":164,"preSum":1109},{"ndv":1,"upper":"IC1910","lower":"IC1910","count":114,"preSum":1273},{"ndv":1,"upper":"IC2001","lower":"IC2001","count":121,"preSum":1387},{"ndv":2,"upper":"IC2210","lower":"IC2100","count":116,"preSum":1508},{"ndv":2,"upper":"IC2410","lower":"IC2310","count":95,"preSum":1624},{"ndv":11,"upper":"IC2912","lower":"IC2411","count":93,"preSum":1719},{"ndv":1,"upper":"IC2913","lower":"IC2913","count":248,"preSum":1812},{"ndv":4,"upper":"IC3024","lower":"IC3000","count":106,"preSum":2060},{"ndv":5,"upper":"IC3301","lower":"IC3123","count":131,"preSum":2166},{"ndv":8,"upper":"IC3810","lower":"IC3401","count":175,"preSum":2297},{"ndv":2,"upper":"IC3910","lower":"IC3811","count":81,"preSum":2472},{"ndv":4,"upper":"IC4110","lower":"IC3911","count":276,"preSum":2553},{"ndv":2,"upper":"IC4300","lower":"IC4220","count":89,"preSum":2829},{"ndv":5,"upper":"ID4600","lower":"ID4422","count":81,"preSum":2918},{"ndv":1,"upper":"IE4700","lower":"IE4700","count":228,"preSum":2999},{"ndv":3,"upper":"IE5000","lower":"IE4800","count":124,"preSum":3227},{"ndv":8,"upper":"IG5900","lower":"IG5300","count":134,"preSum":3351},{"ndv":3,"upper":"II6401","lower":"IG6000","count":81,"preSum":3485},{"ndv":3,"upper":"IK7000","lower":"II6500","count":218,"preSum":3566},{"ndv":1,"upper":"IL7100","lower":"IL7100","count":243,"preSum":3784},{"ndv":1,"upper":"IL7101","lower":"IL7101","count":112,"preSum":4027},{"ndv":3,"upper":"IM7900","lower":"IM7500","count":318,"preSum":4139},{"ndv":2,"upper":"IM8400","lower":"IM7902","count":138,"preSum":4457},{"ndv":1,"upper":"IM8402","lower":"IM8402","count":150,"preSum":4595},{"ndv":6,"upper":"Y0100","lower":"IM8500","count":76,"preSum":4745},{"ndv":2,"upper":"考核户","lower":"Y0200","count":5,"preSum":4821}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[738,859,498,529,369,4040,826,586,867,727,492,452,38666,44827],"valueArr":["I00000","IA0100","IA0400","IC3300","ID4420","IF5100","IF5101","IH6100","II6300","IM7903","IM8000","IM9300","IY0100","IY0200"],"type":"String","sampleRate":0.924351804778851}',699,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','ts_flag',34,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"是","lower":"是","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[6880,63678,83,307,23260,1681,417],"valueArr":["0","1","1.0","40","62","64","82"],"type":"String","sampleRate":0.924351804778851}',3694,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','use_grid_direction',30,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"321","lower":"321","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[434,176,99],"valueArr":["1","121","221"],"type":"String","sampleRate":0.924351804778851}',99291,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','volt_code',27,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"13","lower":"13","count":2,"preSum":0},{"ndv":1,"upper":"交流220V","lower":"交流220V","count":2,"preSum":2},{"ndv":1,"upper":"交流380V","lower":"交流380V","count":1,"preSum":4}],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}','{"countArr":[86797,10409,2756,7,15,12],"valueArr":["02","03","08","09","10","12"],"type":"String","sampleRate":0.924351804778851}',0,0.0026470406),('gdcams_tp','mk_cu_elec_cust_mr_comp_view','zero_pq_flag',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"String","sampleRate":0.9243518}',null,100001,0.0026470406),('gdcams_tp','mk_run_meter_day_energy','area_code',20,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"030400","lower":"030400","count":1984,"preSum":0},{"ndv":1,"upper":"031500","lower":"031500","count":2602,"preSum":1984},{"ndv":1,"upper":"031700","lower":"031700","count":3114,"preSum":4586},{"ndv":1,"upper":"032000","lower":"032000","count":2790,"preSum":7700},{"ndv":1,"upper":"035100","lower":"035100","count":2409,"preSum":10490},{"ndv":1,"upper":"035300","lower":"035300","count":2425,"preSum":12899}],"maxBucketSize":64,"type":"String","sampleRate":0.851152}','{"countArr":[3353,5872,12741,9554,5295,6089,4946,5744,6254,5693,3181,4761,5832,5291],"valueArr":["030200","030500","0306","030600","030700","030800","030900","031200","031300","031400","031600","031800","031900","035200"],"type":"String","sampleRate":0.8511520227425546}',71,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','data_part',512,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":4,"upper":20230604,"lower":20230601,"count":920,"preSum":0},{"ndv":4,"upper":20230608,"lower":20230605,"count":920,"preSum":920},{"ndv":4,"upper":20230612,"lower":20230609,"count":915,"preSum":1840},{"ndv":4,"upper":20230616,"lower":20230613,"count":929,"preSum":2755},{"ndv":4,"upper":20230620,"lower":20230617,"count":913,"preSum":3684},{"ndv":4,"upper":20230624,"lower":20230621,"count":919,"preSum":4597},{"ndv":4,"upper":20230628,"lower":20230625,"count":898,"preSum":5516},{"ndv":4,"upper":20230702,"lower":20230629,"count":805,"preSum":6414},{"ndv":5,"upper":20230707,"lower":20230703,"count":953,"preSum":7219},{"ndv":5,"upper":20230712,"lower":20230708,"count":977,"preSum":8172},{"ndv":5,"upper":20230717,"lower":20230713,"count":964,"preSum":9149},{"ndv":5,"upper":20230722,"lower":20230718,"count":956,"preSum":10113},{"ndv":5,"upper":20230727,"lower":20230723,"count":918,"preSum":11069},{"ndv":26,"upper":20230822,"lower":20230728,"count":800,"preSum":11987},{"ndv":10,"upper":20231101,"lower":20230823,"count":3364,"preSum":12787},{"ndv":4,"upper":20231109,"lower":20231105,"count":2224,"preSum":16151},{"ndv":4,"upper":20231113,"lower":20231110,"count":3506,"preSum":18375},{"ndv":1,"upper":20231116,"lower":20231116,"count":2932,"preSum":21881},{"ndv":1,"upper":20231122,"lower":20231122,"count":3343,"preSum":24813},{"ndv":1,"upper":20231123,"lower":20231123,"count":2969,"preSum":28156},{"ndv":1,"upper":20231124,"lower":20231124,"count":3105,"preSum":31125},{"ndv":1,"upper":20231125,"lower":20231125,"count":3324,"preSum":34230},{"ndv":1,"upper":20231126,"lower":20231126,"count":3320,"preSum":37554},{"ndv":1,"upper":20231127,"lower":20231127,"count":3345,"preSum":40874},{"ndv":1,"upper":20231129,"lower":20231129,"count":3312,"preSum":44219},{"ndv":1,"upper":20231130,"lower":20231130,"count":3325,"preSum":47531},{"ndv":1,"upper":20231201,"lower":20231201,"count":165,"preSum":50856}],"maxBucketSize":64,"type":"Int","sampleRate":0.851152}','{"countArr":[3525,3438,3461,3450,3396,3467,3458,3450,3372,3357,3649,3674,3643,3640],"valueArr":[202311,20231108,20231114,20231115,20231117,20231118,20231119,20231120,20231121,20231128,20231202,20231203,20231204,20231205],"type":"Int","sampleRate":0.8511520227425546}',0,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','data_source_code',139,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1,"upper":"4","lower":"4","count":1,"preSum":0}],"maxBucketSize":64,"type":"String","sampleRate":0.851152}','{"countArr":[12740],"valueArr":["1"],"type":"String","sampleRate":0.8511520227425546}',87260,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','data_time',618,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":4,"upper":"1851058611686473728","lower":"1851052014616707072","count":920,"preSum":0},{"ndv":4,"upper":"1851067407779495936","lower":"1851060810709729280","count":920,"preSum":920},{"ndv":4,"upper":"1851076203872518144","lower":"1851069606802751488","count":915,"preSum":1840},{"ndv":4,"upper":"1851084999965540352","lower":"1851078402895773696","count":929,"preSum":2755},{"ndv":4,"upper":"1851093796058562560","lower":"1851087198988795904","count":913,"preSum":3684},{"ndv":4,"upper":"1851102592151584768","lower":"1851095995081818112","count":919,"preSum":4597},{"ndv":4,"upper":"1851111388244606976","lower":"1851104791174840320","count":898,"preSum":5516},{"ndv":4,"upper":"1851124582384140288","lower":"1851113587267862528","count":805,"preSum":6414},{"ndv":5,"upper":"1851135577500418048","lower":"1851126781407395840","count":953,"preSum":7219},{"ndv":5,"upper":"1851146572616695808","lower":"1851137776523673600","count":977,"preSum":8172},{"ndv":5,"upper":"1851157567732973568","lower":"1851148771639951360","count":964,"preSum":9149},{"ndv":5,"upper":"1851168562849251328","lower":"1851159766756229120","count":956,"preSum":10113},{"ndv":5,"upper":"1851179557965529088","lower":"1851170761872506880","count":918,"preSum":11069},{"ndv":22,"upper":"1851230135500406784","lower":"1851181756988784640","count":792,"preSum":11987},{"ndv":20,"upper":"1851417052477128704","lower":"1851232334523662336","count":3053,"preSum":12779},{"ndv":3,"upper":"1851421450523639808","lower":"1851418205675847680","count":2103,"preSum":15832},{"ndv":5,"upper":"1851430246616662016","lower":"1851423649546895360","count":3502,"preSum":17935},{"ndv":4,"upper":"1851436843686428672","lower":"1851431399815380992","count":2939,"preSum":21437},{"ndv":1,"upper":"1851450037825961984","lower":"1851450037825961984","count":3343,"preSum":24376},{"ndv":1,"upper":"1851452236849217536","lower":"1851452236849217536","count":2969,"preSum":27719},{"ndv":1,"upper":"1851454435872473088","lower":"1851454435872473088","count":3105,"preSum":30688},{"ndv":1,"upper":"1851456634895728640","lower":"1851456634895728640","count":3324,"preSum":33793},{"ndv":1,"upper":"1851458833918984192","lower":"1851458833918984192","count":3320,"preSum":37117},{"ndv":1,"upper":"1851461032942239744","lower":"1851461032942239744","count":3345,"preSum":40437},{"ndv":1,"upper":"1851465430988750848","lower":"1851465430988750848","count":3312,"preSum":43782},{"ndv":1,"upper":"1851467630012006400","lower":"1851467630012006400","count":3325,"preSum":47094},{"ndv":1,"upper":"1851474227081773056","lower":"1851474227081773056","count":165,"preSum":50419}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.851152}','{"countArr":[3353,4050,3459,3449,3396,3467,3458,3450,3372,3357,3649,3674,3643,3640],"valueArr":[1851403858337595392,1851419251500384256,1851432445639917568,1851434644663173120,1851439042709684224,1851441241732939776,1851443440756195328,1851445639779450880,1851447838802706432,1851463231965495296,1851476426105028608,1851478625128284160,1851480824151539712,1851483023174795264],"type":"Datetime","sampleRate":0.8511520227425546}',0,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','load_time',7850919,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1088,"upper":"1851065449307963392","lower":"1851052157172711424","count":1558,"preSum":0},{"ndv":1148,"upper":"1851080999203504128","lower":"1851065449324740608","count":1558,"preSum":1558},{"ndv":1225,"upper":"1851096211356909568","lower":"1851080999220281344","count":1558,"preSum":3116},{"ndv":1163,"upper":"1851111588161912832","lower":"1851096214276145152","count":1558,"preSum":4674},{"ndv":1165,"upper":"1851133578948116480","lower":"1851111588279353344","count":1559,"preSum":6232},{"ndv":1195,"upper":"1851151737885294592","lower":"1851133579065556992","count":1558,"preSum":7791},{"ndv":1177,"upper":"1851170934761717760","lower":"1851151865509576704","count":1558,"preSum":9349},{"ndv":1275,"upper":"1851188597244297216","lower":"1851170934929489920","count":1558,"preSum":10907},{"ndv":1430,"upper":"1851417492124073984","lower":"1851188597294628864","count":1558,"preSum":12465},{"ndv":1487,"upper":"1851419658968629248","lower":"1851417492543504384","count":1558,"preSum":14023},{"ndv":728,"upper":"1851420010904289280","lower":"1851419659136401408","count":1562,"preSum":15581},{"ndv":1271,"upper":"1851422719334154240","lower":"1851420010921066496","count":1558,"preSum":17143},{"ndv":1413,"upper":"1851424050723684352","lower":"1851422719350931456","count":1558,"preSum":18701},{"ndv":1417,"upper":"1851431073146208256","lower":"1851424051528990720","count":1558,"preSum":20259},{"ndv":1211,"upper":"1851431789248118784","lower":"1851431073917960192","count":1558,"preSum":21817},{"ndv":1364,"upper":"1851432645171347456","lower":"1851431789768212480","count":1558,"preSum":23375},{"ndv":1323,"upper":"1851432842488184832","lower":"1851432645238456320","count":1558,"preSum":24933},{"ndv":1392,"upper":"1851433101964607488","lower":"1851432842538516480","count":1558,"preSum":26491},{"ndv":1050,"upper":"1851434802687770624","lower":"1851433101981384704","count":1558,"preSum":28049},{"ndv":816,"upper":"1851434830487617536","lower":"1851434802704547840","count":1559,"preSum":29607},{"ndv":1152,"upper":"1851437005871775744","lower":"1851434830504394752","count":1560,"preSum":31166},{"ndv":1417,"upper":"1851439276164644864","lower":"1851437006005993472","count":1558,"preSum":32726},{"ndv":1395,"upper":"1851439412429193216","lower":"1851439276181422080","count":1558,"preSum":34284},{"ndv":1439,"upper":"1851439656369913856","lower":"1851439412496302080","count":1558,"preSum":35842},{"ndv":1209,"upper":"1851441392325230592","lower":"1851439656772567040","count":1559,"preSum":37400},{"ndv":837,"upper":"1851441418732568576","lower":"1851441392342007808","count":1559,"preSum":38959},{"ndv":1085,"upper":"1851443586483093504","lower":"1851441418749345792","count":1558,"preSum":40518},{"ndv":878,"upper":"1851443615608340480","lower":"1851443586533425152","count":1558,"preSum":42076},{"ndv":1009,"upper":"1851443665956765696","lower":"1851443615625117696","count":1558,"preSum":43634},{"ndv":884,"upper":"1851445805018251264","lower":"1851443665973542912","count":1558,"preSum":45192},{"ndv":896,"upper":"1851445838186807296","lower":"1851445805035028480","count":1558,"preSum":46750},{"ndv":1038,"upper":"1851448001810137088","lower":"1851445838203584512","count":1559,"preSum":48308},{"ndv":987,"upper":"1851448038166364160","lower":"1851448001826914304","count":1558,"preSum":49867},{"ndv":1043,"upper":"1851450201085050880","lower":"1851448038183141376","count":1558,"preSum":51425},{"ndv":902,"upper":"1851450227324616704","lower":"1851450201118605312","count":1558,"preSum":52983},{"ndv":904,"upper":"1851452527967469568","lower":"1851450227358171136","count":1562,"preSum":54541},{"ndv":276,"upper":"1851452532967079936","lower":"1851452527984246784","count":1559,"preSum":56103},{"ndv":526,"upper":"1851455083657560064","lower":"1851452532983857152","count":1563,"preSum":57662},{"ndv":356,"upper":"1851455090905317376","lower":"1851455083674337280","count":1561,"preSum":59225},{"ndv":800,"upper":"1851456795755675648","lower":"1851455090922094592","count":1559,"preSum":60786},{"ndv":936,"upper":"1851456826625753088","lower":"1851456795772452864","count":1558,"preSum":62345},{"ndv":1133,"upper":"1851458989242449920","lower":"1851456826642530304","count":1558,"preSum":63903},{"ndv":828,"upper":"1851459013804294144","lower":"1851458989276004352","count":1558,"preSum":65461},{"ndv":1141,"upper":"1851461184960593920","lower":"1851459013821071360","count":1558,"preSum":67019},{"ndv":965,"upper":"1851461220612177920","lower":"1851461185027702784","count":1558,"preSum":68577},{"ndv":1319,"upper":"1851461843449544704","lower":"1851461220628955136","count":1559,"preSum":70135},{"ndv":1494,"upper":"1851462377283780608","lower":"1851461844003192832","count":1558,"preSum":71694},{"ndv":1372,"upper":"1851463402807885824","lower":"1851462378172973056","count":1558,"preSum":73252},{"ndv":1370,"upper":"1851463647352586240","lower":"1851463402891771904","count":1558,"preSum":74810},{"ndv":1412,"upper":"1851464046549663744","lower":"1851463647402917888","count":1558,"preSum":76368},{"ndv":1011,"upper":"1851465595808120832","lower":"1851464047052980224","count":1559,"preSum":77926},{"ndv":933,"upper":"1851465628238479360","lower":"1851465595824898048","count":1558,"preSum":79485},{"ndv":1076,"upper":"1851467794479054848","lower":"1851465628255256576","count":1559,"preSum":81043},{"ndv":934,"upper":"1851467827580502016","lower":"1851467794512609280","count":1560,"preSum":82602},{"ndv":1113,"upper":"1851476578173714432","lower":"1851467827647610880","count":1559,"preSum":84162},{"ndv":850,"upper":"1851476603138211840","lower":"1851476578190491648","count":1558,"preSum":85721},{"ndv":1103,"upper":"1851478770838405120","lower":"1851476603154989056","count":1559,"preSum":87279},{"ndv":835,"upper":"1851478795467358208","lower":"1851478770855182336","count":1561,"preSum":88838},{"ndv":987,"upper":"1851478837360066560","lower":"1851478795484135424","count":1558,"preSum":90399},{"ndv":1001,"upper":"1851480985430917120","lower":"1851478837410398208","count":1558,"preSum":91957},{"ndv":920,"upper":"1851481014891708416","lower":"1851480985447694336","count":1559,"preSum":93515},{"ndv":1129,"upper":"1851483177021865984","lower":"1851481014908485632","count":1558,"preSum":95074},{"ndv":843,"upper":"1851483202657452032","lower":"1851483177088974848","count":1560,"preSum":96632},{"ndv":1082,"upper":"1851483675103854592","lower":"1851483202674229248","count":1466,"preSum":98192}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.851152}','{"countArr":[25,25,26,33,20,30,22,29,32,71,15,15],"valueArr":[1851147429076795392,1851153198509719552,1851166397296541696,1851168593551556608,1851175194379419648,1851179593029910528,1851182610865192960,1851223566415036416,1851233186336473088,1851315897407373312,1851452527262826496,1851452531725565952],"type":"Datetime","sampleRate":0.8511520227425546}',0,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','nap_b',66861,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":0.0500,"lower":0.0300,"count":20,"preSum":0},{"ndv":1,"upper":0.0700,"lower":0.0700,"count":14,"preSum":20},{"ndv":4,"upper":0.1300,"lower":0.0900,"count":29,"preSum":34},{"ndv":3,"upper":0.1800,"lower":0.1600,"count":25,"preSum":63},{"ndv":3,"upper":0.2100,"lower":0.1900,"count":28,"preSum":88},{"ndv":4,"upper":0.3300,"lower":0.2200,"count":19,"preSum":116},{"ndv":3,"upper":0.4100,"lower":0.3700,"count":23,"preSum":135},{"ndv":4,"upper":0.4900,"lower":0.4200,"count":19,"preSum":158},{"ndv":3,"upper":0.5500,"lower":0.5000,"count":14,"preSum":177},{"ndv":4,"upper":0.5900,"lower":0.5600,"count":28,"preSum":191},{"ndv":2,"upper":0.6700,"lower":0.6000,"count":14,"preSum":219},{"ndv":3,"upper":0.8000,"lower":0.6900,"count":14,"preSum":233},{"ndv":2,"upper":1.1100,"lower":1.0200,"count":20,"preSum":247},{"ndv":7,"upper":1.7500,"lower":1.2900,"count":17,"preSum":267},{"ndv":2,"upper":1.9800,"lower":1.8100,"count":18,"preSum":284},{"ndv":1,"upper":2.0400,"lower":2.0400,"count":14,"preSum":302},{"ndv":8,"upper":2.3500,"lower":2.2700,"count":17,"preSum":316},{"ndv":2,"upper":2.6400,"lower":2.5400,"count":22,"preSum":333},{"ndv":11,"upper":3.3400,"lower":3.0900,"count":14,"preSum":355},{"ndv":14,"upper":3.9300,"lower":3.3500,"count":14,"preSum":369},{"ndv":8,"upper":8.6800,"lower":3.9400,"count":14,"preSum":383},{"ndv":6,"upper":11.3500,"lower":8.7300,"count":15,"preSum":397},{"ndv":10,"upper":11.4700,"lower":11.3600,"count":14,"preSum":412},{"ndv":10,"upper":14.7070,"lower":11.4800,"count":14,"preSum":426},{"ndv":11,"upper":30.3000,"lower":15.0520,"count":18,"preSum":440},{"ndv":11,"upper":38.9570,"lower":32.3550,"count":14,"preSum":458},{"ndv":14,"upper":48.7500,"lower":39.2630,"count":14,"preSum":472},{"ndv":12,"upper":53.2020,"lower":48.8600,"count":14,"preSum":486},{"ndv":14,"upper":76.6210,"lower":56.6080,"count":14,"preSum":500},{"ndv":14,"upper":94.5880,"lower":76.7380,"count":14,"preSum":514},{"ndv":12,"upper":120.6400,"lower":95.0490,"count":14,"preSum":528},{"ndv":11,"upper":549.9900,"lower":132.1600,"count":14,"preSum":542},{"ndv":14,"upper":654.8200,"lower":551.1600,"count":14,"preSum":556},{"ndv":14,"upper":1448.2400,"lower":1288.4200,"count":14,"preSum":570},{"ndv":14,"upper":1508.4400,"lower":1449.0500,"count":14,"preSum":584},{"ndv":14,"upper":1614.1400,"lower":1512.7000,"count":14,"preSum":598},{"ndv":14,"upper":1768.2600,"lower":1615.2000,"count":14,"preSum":612},{"ndv":14,"upper":2185.6000,"lower":1821.0300,"count":14,"preSum":626},{"ndv":13,"upper":2672.6500,"lower":2390.0100,"count":14,"preSum":640},{"ndv":13,"upper":3100.3300,"lower":2691.0000,"count":14,"preSum":654},{"ndv":14,"upper":4016.2400,"lower":3108.7300,"count":14,"preSum":668},{"ndv":14,"upper":4659.8000,"lower":4034.7100,"count":14,"preSum":682},{"ndv":14,"upper":5192.8800,"lower":4696.4200,"count":14,"preSum":696},{"ndv":14,"upper":6344.4900,"lower":5220.6900,"count":14,"preSum":710},{"ndv":14,"upper":11729.5800,"lower":6346.6600,"count":14,"preSum":724},{"ndv":14,"upper":11937.7200,"lower":11757.8000,"count":14,"preSum":738},{"ndv":14,"upper":17883.7400,"lower":11964.8100,"count":14,"preSum":752},{"ndv":14,"upper":23804.8600,"lower":17887.8400,"count":14,"preSum":766},{"ndv":14,"upper":28460.5000,"lower":23810.2500,"count":14,"preSum":780},{"ndv":14,"upper":29031.9800,"lower":28486.1100,"count":14,"preSum":794},{"ndv":14,"upper":32708.3300,"lower":29040.3700,"count":14,"preSum":808},{"ndv":14,"upper":33063.1600,"lower":32736.6100,"count":14,"preSum":822},{"ndv":2,"upper":230167.1400,"lower":230043.7400,"count":2,"preSum":836}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[88320,80,99,22,20,40,20,41,29,26,19,23,19],"valueArr":[0.0000,0.0100,0.0200,0.0400,0.0800,0.3500,0.3900,0.4000,0.4500,0.5100,1.1000,61.4200,121.9900],"type":"Double","sampleRate":0.8511520227425546}',10405,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','nap_pe',40156,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":4,"upper":4.3380,"lower":0.1500,"count":5,"preSum":0},{"ndv":5,"upper":8.5620,"lower":4.7050,"count":5,"preSum":5},{"ndv":5,"upper":11.4450,"lower":9.3700,"count":5,"preSum":10},{"ndv":5,"upper":19.6690,"lower":14.5930,"count":5,"preSum":15},{"ndv":5,"upper":29.8030,"lower":19.7310,"count":5,"preSum":20},{"ndv":5,"upper":37.5500,"lower":31.3500,"count":5,"preSum":25},{"ndv":5,"upper":45.2850,"lower":38.5560,"count":5,"preSum":30},{"ndv":5,"upper":47.3570,"lower":45.8890,"count":5,"preSum":35},{"ndv":5,"upper":58.6620,"lower":47.3840,"count":5,"preSum":40},{"ndv":5,"upper":67.0350,"lower":60.8570,"count":5,"preSum":45},{"ndv":5,"upper":74.8520,"lower":68.3530,"count":5,"preSum":50},{"ndv":5,"upper":80.5010,"lower":75.5770,"count":5,"preSum":55},{"ndv":5,"upper":82.9540,"lower":80.7700,"count":5,"preSum":60},{"ndv":5,"upper":89.1680,"lower":86.3810,"count":5,"preSum":65},{"ndv":5,"upper":96.0750,"lower":91.1630,"count":5,"preSum":70},{"ndv":5,"upper":335.4500,"lower":333.4600,"count":5,"preSum":75},{"ndv":5,"upper":337.6100,"lower":335.7600,"count":5,"preSum":80},{"ndv":5,"upper":894.7400,"lower":338.2600,"count":5,"preSum":85},{"ndv":5,"upper":897.6100,"lower":895.1500,"count":5,"preSum":90},{"ndv":5,"upper":1473.8700,"lower":899.5300,"count":5,"preSum":95},{"ndv":5,"upper":1545.3900,"lower":1481.6800,"count":5,"preSum":100},{"ndv":5,"upper":1612.4400,"lower":1559.9600,"count":5,"preSum":105},{"ndv":5,"upper":1674.7400,"lower":1635.7800,"count":5,"preSum":110},{"ndv":5,"upper":1734.2300,"lower":1691.9200,"count":5,"preSum":115},{"ndv":5,"upper":1871.6300,"lower":1736.7200,"count":5,"preSum":120},{"ndv":5,"upper":2032.8400,"lower":1927.2200,"count":5,"preSum":125},{"ndv":5,"upper":2555.6000,"lower":2085.3000,"count":5,"preSum":130},{"ndv":5,"upper":2655.3300,"lower":2567.5300,"count":5,"preSum":135},{"ndv":4,"upper":2691.3600,"lower":2665.8300,"count":5,"preSum":140},{"ndv":5,"upper":2792.7800,"lower":2708.9700,"count":5,"preSum":145},{"ndv":5,"upper":3216.8200,"lower":2822.4600,"count":6,"preSum":150},{"ndv":5,"upper":3254.2500,"lower":3219.5300,"count":5,"preSum":156},{"ndv":5,"upper":3297.1700,"lower":3260.5200,"count":5,"preSum":161},{"ndv":5,"upper":3542.9500,"lower":3319.5600,"count":5,"preSum":166},{"ndv":5,"upper":4318.0200,"lower":3697.4400,"count":5,"preSum":171},{"ndv":5,"upper":4402.5800,"lower":4321.8100,"count":5,"preSum":176},{"ndv":5,"upper":4800.3400,"lower":4603.7500,"count":5,"preSum":181},{"ndv":5,"upper":4964.0700,"lower":4843.8500,"count":5,"preSum":186},{"ndv":5,"upper":5123.4500,"lower":5033.8000,"count":5,"preSum":191},{"ndv":5,"upper":5207.8600,"lower":5141.3600,"count":5,"preSum":196},{"ndv":5,"upper":5362.4200,"lower":5254.6600,"count":5,"preSum":201},{"ndv":5,"upper":5508.3900,"lower":5413.4600,"count":5,"preSum":206},{"ndv":5,"upper":9921.9900,"lower":5531.6800,"count":5,"preSum":211},{"ndv":5,"upper":10390.2000,"lower":9923.5900,"count":5,"preSum":216},{"ndv":5,"upper":10469.6900,"lower":10400.6700,"count":5,"preSum":221},{"ndv":5,"upper":10510.3200,"lower":10475.3100,"count":5,"preSum":226},{"ndv":5,"upper":10576.4400,"lower":10522.4900,"count":5,"preSum":231},{"ndv":5,"upper":11630.5400,"lower":10589.8300,"count":5,"preSum":236},{"ndv":5,"upper":11761.0600,"lower":11644.6200,"count":5,"preSum":241},{"ndv":5,"upper":11895.6900,"lower":11784.7800,"count":5,"preSum":246},{"ndv":5,"upper":12000.4900,"lower":11916.1400,"count":5,"preSum":251},{"ndv":2,"upper":12034.8900,"lower":12021.2300,"count":2,"preSum":256}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[91628,12,17,3,29,29,6,4,10,5,6,3,23,3],"valueArr":[0.0000,0.0100,0.0200,0.0300,0.2800,0.3500,0.3600,0.3800,0.5400,1.9300,14.4000,16.1300,17.4800,93.4000],"type":"Double","sampleRate":0.8511520227425546}',7965,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','nap_po',62898,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":0.0600,"lower":0.0400,"count":18,"preSum":0},{"ndv":2,"upper":0.0800,"lower":0.0700,"count":13,"preSum":18},{"ndv":4,"upper":0.1600,"lower":0.1000,"count":16,"preSum":31},{"ndv":1,"upper":0.1800,"lower":0.1800,"count":13,"preSum":47},{"ndv":1,"upper":0.2100,"lower":0.2100,"count":18,"preSum":60},{"ndv":3,"upper":0.3000,"lower":0.2300,"count":15,"preSum":78},{"ndv":4,"upper":0.3500,"lower":0.3100,"count":24,"preSum":93},{"ndv":5,"upper":0.3900,"lower":0.3600,"count":15,"preSum":117},{"ndv":2,"upper":0.4100,"lower":0.4000,"count":13,"preSum":132},{"ndv":3,"upper":0.5800,"lower":0.5100,"count":15,"preSum":145},{"ndv":2,"upper":0.8300,"lower":0.7600,"count":28,"preSum":160},{"ndv":3,"upper":0.9200,"lower":0.8700,"count":13,"preSum":188},{"ndv":1,"upper":1.0100,"lower":1.0100,"count":16,"preSum":201},{"ndv":3,"upper":1.1100,"lower":1.0700,"count":15,"preSum":217},{"ndv":3,"upper":1.2300,"lower":1.1400,"count":24,"preSum":232},{"ndv":6,"upper":2.1700,"lower":1.6300,"count":13,"preSum":256},{"ndv":7,"upper":2.2900,"lower":2.1900,"count":16,"preSum":269},{"ndv":3,"upper":2.4900,"lower":2.4400,"count":20,"preSum":285},{"ndv":1,"upper":2.5100,"lower":2.5100,"count":19,"preSum":305},{"ndv":3,"upper":3.0600,"lower":2.7400,"count":28,"preSum":324},{"ndv":11,"upper":5.1400,"lower":3.1200,"count":13,"preSum":352},{"ndv":13,"upper":5.2800,"lower":5.1600,"count":13,"preSum":365},{"ndv":2,"upper":5.7700,"lower":5.3000,"count":13,"preSum":378},{"ndv":10,"upper":7.5700,"lower":5.9700,"count":13,"preSum":391},{"ndv":13,"upper":7.7800,"lower":7.5800,"count":13,"preSum":404},{"ndv":9,"upper":9.2200,"lower":7.7900,"count":13,"preSum":417},{"ndv":9,"upper":9.7500,"lower":9.2300,"count":15,"preSum":430},{"ndv":11,"upper":18.0000,"lower":14.6600,"count":17,"preSum":445},{"ndv":13,"upper":27.8240,"lower":18.6530,"count":13,"preSum":462},{"ndv":12,"upper":46.7810,"lower":28.0440,"count":13,"preSum":475},{"ndv":13,"upper":58.7500,"lower":46.9360,"count":13,"preSum":488},{"ndv":11,"upper":59.1200,"lower":58.7700,"count":13,"preSum":501},{"ndv":13,"upper":69.4050,"lower":59.1300,"count":13,"preSum":514},{"ndv":13,"upper":86.3210,"lower":70.0290,"count":13,"preSum":527},{"ndv":10,"upper":112.5500,"lower":91.9510,"count":14,"preSum":540},{"ndv":3,"upper":231.3400,"lower":174.9600,"count":13,"preSum":554},{"ndv":10,"upper":351.6400,"lower":246.4600,"count":13,"preSum":567},{"ndv":13,"upper":1025.1800,"lower":351.7200,"count":13,"preSum":580},{"ndv":13,"upper":2661.7600,"lower":1025.7400,"count":13,"preSum":593},{"ndv":13,"upper":3320.4900,"lower":2685.6800,"count":13,"preSum":606},{"ndv":13,"upper":4023.8100,"lower":3374.1800,"count":13,"preSum":619},{"ndv":12,"upper":4249.2600,"lower":4045.5000,"count":13,"preSum":632},{"ndv":13,"upper":4640.7200,"lower":4423.3500,"count":13,"preSum":645},{"ndv":13,"upper":4954.2500,"lower":4660.1400,"count":13,"preSum":658},{"ndv":12,"upper":5780.6200,"lower":4986.2100,"count":13,"preSum":671},{"ndv":13,"upper":6901.2000,"lower":5784.0800,"count":13,"preSum":684},{"ndv":13,"upper":7468.7300,"lower":6927.7100,"count":13,"preSum":697},{"ndv":13,"upper":8907.8100,"lower":7522.5900,"count":13,"preSum":710},{"ndv":13,"upper":20313.1100,"lower":8956.8500,"count":13,"preSum":723},{"ndv":13,"upper":21077.7000,"lower":20428.4900,"count":13,"preSum":736},{"ndv":13,"upper":38955.7100,"lower":21123.0300,"count":13,"preSum":749},{"ndv":13,"upper":40156.3700,"lower":39017.1400,"count":13,"preSum":762},{"ndv":13,"upper":64475.5700,"lower":50401.1600,"count":13,"preSum":775},{"ndv":13,"upper":64866.4500,"lower":64481.8200,"count":13,"preSum":788},{"ndv":13,"upper":78105.0200,"lower":64893.9300,"count":13,"preSum":801},{"ndv":8,"upper":78375.0500,"lower":78134.8700,"count":8,"preSum":814}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[83823,313,38,46,26,25,26,24,24,24,25,31,23],"valueArr":[0.0000,0.0100,0.0200,0.0300,0.0500,0.0900,0.1700,0.1900,0.4400,0.5000,1.0500,3.3600,15.2900],"type":"Double","sampleRate":0.8511520227425546}',14731,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','nap_t',75507,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":0.0800,"lower":0.0400,"count":21,"preSum":0},{"ndv":3,"upper":0.1200,"lower":0.1000,"count":21,"preSum":21},{"ndv":4,"upper":0.1900,"lower":0.1400,"count":28,"preSum":42},{"ndv":3,"upper":0.2500,"lower":0.2200,"count":31,"preSum":70},{"ndv":2,"upper":0.3100,"lower":0.3000,"count":31,"preSum":101},{"ndv":6,"upper":0.4400,"lower":0.3300,"count":21,"preSum":132},{"ndv":3,"upper":0.5100,"lower":0.4600,"count":34,"preSum":153},{"ndv":2,"upper":0.5800,"lower":0.5200,"count":20,"preSum":187},{"ndv":2,"upper":0.6400,"lower":0.6100,"count":31,"preSum":207},{"ndv":5,"upper":0.7900,"lower":0.6800,"count":38,"preSum":238},{"ndv":4,"upper":0.9200,"lower":0.8600,"count":23,"preSum":276},{"ndv":7,"upper":1.0800,"lower":0.9300,"count":30,"preSum":299},{"ndv":1,"upper":1.1000,"lower":1.1000,"count":26,"preSum":329},{"ndv":2,"upper":1.1500,"lower":1.1100,"count":20,"preSum":355},{"ndv":2,"upper":1.1900,"lower":1.1600,"count":21,"preSum":375},{"ndv":3,"upper":1.4400,"lower":1.2500,"count":23,"preSum":396},{"ndv":5,"upper":1.8300,"lower":1.4700,"count":23,"preSum":419},{"ndv":2,"upper":1.9500,"lower":1.8600,"count":26,"preSum":442},{"ndv":4,"upper":2.5000,"lower":1.9700,"count":24,"preSum":468},{"ndv":2,"upper":2.6850,"lower":2.5100,"count":20,"preSum":492},{"ndv":5,"upper":3.2200,"lower":2.7400,"count":29,"preSum":512},{"ndv":3,"upper":3.3600,"lower":3.3000,"count":21,"preSum":541},{"ndv":1,"upper":3.4600,"lower":3.4600,"count":20,"preSum":562},{"ndv":2,"upper":3.7400,"lower":3.6500,"count":21,"preSum":582},{"ndv":6,"upper":5.7700,"lower":4.3420,"count":36,"preSum":603},{"ndv":6,"upper":7.1200,"lower":5.9700,"count":28,"preSum":639},{"ndv":18,"upper":12.5900,"lower":7.7800,"count":20,"preSum":667},{"ndv":18,"upper":14.2400,"lower":12.6100,"count":20,"preSum":687},{"ndv":19,"upper":18.4200,"lower":14.2800,"count":20,"preSum":707},{"ndv":20,"upper":21.1700,"lower":18.4600,"count":20,"preSum":727},{"ndv":17,"upper":37.3690,"lower":21.2800,"count":20,"preSum":747},{"ndv":17,"upper":44.3700,"lower":37.4740,"count":30,"preSum":767},{"ndv":20,"upper":49.4600,"lower":45.8220,"count":20,"preSum":797},{"ndv":18,"upper":63.0380,"lower":49.5000,"count":20,"preSum":817},{"ndv":20,"upper":97.2120,"lower":66.4260,"count":20,"preSum":837},{"ndv":5,"upper":108.3800,"lower":98.1080,"count":29,"preSum":857},{"ndv":17,"upper":145.0000,"lower":117.6000,"count":20,"preSum":886},{"ndv":6,"upper":424.1400,"lower":145.0400,"count":29,"preSum":906},{"ndv":15,"upper":1244.2600,"lower":441.0700,"count":20,"preSum":935},{"ndv":20,"upper":2515.9800,"lower":1246.1300,"count":20,"preSum":955},{"ndv":20,"upper":5775.2800,"lower":2521.3300,"count":20,"preSum":975},{"ndv":20,"upper":6507.2900,"lower":5797.4600,"count":20,"preSum":995},{"ndv":20,"upper":7850.4100,"lower":6510.0400,"count":20,"preSum":1015},{"ndv":19,"upper":10810.4600,"lower":7962.8400,"count":20,"preSum":1035},{"ndv":19,"upper":12819.3200,"lower":10877.6500,"count":20,"preSum":1055},{"ndv":20,"upper":17180.9100,"lower":12841.2300,"count":20,"preSum":1075},{"ndv":20,"upper":20927.3800,"lower":17321.9600,"count":20,"preSum":1095},{"ndv":20,"upper":42515.8800,"lower":21017.9800,"count":20,"preSum":1115},{"ndv":20,"upper":44390.6200,"lower":43590.1100,"count":20,"preSum":1135},{"ndv":20,"upper":50914.1000,"lower":44405.7000,"count":20,"preSum":1155},{"ndv":20,"upper":83980.4700,"lower":51412.2400,"count":20,"preSum":1175},{"ndv":20,"upper":90722.7000,"lower":84015.7100,"count":20,"preSum":1195},{"ndv":20,"upper":109199.9200,"lower":90763.4400,"count":20,"preSum":1215},{"ndv":3,"upper":230834.1800,"lower":109236.3000,"count":3,"preSum":1235}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[90997,294,95,125,82,45,47,30,36,45,41,29,29],"valueArr":[0.0000,0.0100,0.0200,0.0300,0.0500,0.0600,0.0700,0.2100,0.2800,0.3500,0.4000,0.4500,0.5000],"type":"Double","sampleRate":0.8511520227425546}',6868,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','nap_v',59034,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":0.0600,"lower":0.0300,"count":10,"preSum":0},{"ndv":2,"upper":0.1100,"lower":0.0800,"count":9,"preSum":10},{"ndv":2,"upper":0.2000,"lower":0.1300,"count":8,"preSum":19},{"ndv":2,"upper":0.8300,"lower":0.4100,"count":11,"preSum":27},{"ndv":4,"upper":1.9600,"lower":1.6500,"count":14,"preSum":38},{"ndv":4,"upper":2.9400,"lower":2.0600,"count":9,"preSum":52},{"ndv":4,"upper":5.2900,"lower":3.5800,"count":8,"preSum":61},{"ndv":8,"upper":5.6200,"lower":5.3200,"count":8,"preSum":69},{"ndv":8,"upper":5.7400,"lower":5.6400,"count":8,"preSum":77},{"ndv":3,"upper":6.7300,"lower":5.7440,"count":8,"preSum":85},{"ndv":6,"upper":7.9200,"lower":6.7400,"count":11,"preSum":93},{"ndv":7,"upper":8.0400,"lower":7.9400,"count":9,"preSum":104},{"ndv":7,"upper":9.2000,"lower":8.0500,"count":8,"preSum":113},{"ndv":7,"upper":10.4800,"lower":9.3200,"count":8,"preSum":121},{"ndv":8,"upper":10.6600,"lower":10.5100,"count":8,"preSum":129},{"ndv":8,"upper":12.5510,"lower":10.6800,"count":8,"preSum":137},{"ndv":7,"upper":17.6000,"lower":14.5000,"count":8,"preSum":145},{"ndv":8,"upper":23.3570,"lower":18.9260,"count":8,"preSum":153},{"ndv":8,"upper":28.3600,"lower":25.1030,"count":8,"preSum":161},{"ndv":8,"upper":28.5600,"lower":28.3700,"count":8,"preSum":169},{"ndv":8,"upper":35.4910,"lower":28.5700,"count":8,"preSum":177},{"ndv":3,"upper":40.0500,"lower":36.1980,"count":8,"preSum":185},{"ndv":8,"upper":43.8840,"lower":40.0600,"count":8,"preSum":193},{"ndv":6,"upper":49.2070,"lower":44.0290,"count":8,"preSum":201},{"ndv":4,"upper":53.9540,"lower":49.3420,"count":8,"preSum":209},{"ndv":8,"upper":69.7670,"lower":55.2290,"count":8,"preSum":217},{"ndv":8,"upper":83.7720,"lower":71.2820,"count":8,"preSum":225},{"ndv":8,"upper":93.6930,"lower":84.0180,"count":8,"preSum":233},{"ndv":8,"upper":107.5400,"lower":96.7230,"count":8,"preSum":241},{"ndv":8,"upper":118.9800,"lower":107.5500,"count":8,"preSum":249},{"ndv":8,"upper":124.7100,"lower":120.0200,"count":8,"preSum":257},{"ndv":8,"upper":132.3600,"lower":125.1300,"count":8,"preSum":265},{"ndv":8,"upper":161.7400,"lower":132.4600,"count":8,"preSum":273},{"ndv":4,"upper":216.8800,"lower":199.1800,"count":8,"preSum":281},{"ndv":8,"upper":240.0200,"lower":222.3400,"count":8,"preSum":289},{"ndv":8,"upper":254.1700,"lower":241.5500,"count":8,"preSum":297},{"ndv":6,"upper":316.9300,"lower":254.9000,"count":8,"preSum":305},{"ndv":6,"upper":328.3800,"lower":317.0000,"count":8,"preSum":313},{"ndv":7,"upper":357.9800,"lower":351.8600,"count":8,"preSum":321},{"ndv":8,"upper":422.8800,"lower":360.8400,"count":8,"preSum":329},{"ndv":8,"upper":435.3800,"lower":424.1300,"count":8,"preSum":337},{"ndv":8,"upper":473.8100,"lower":436.5300,"count":8,"preSum":345},{"ndv":8,"upper":486.9900,"lower":477.8800,"count":8,"preSum":353},{"ndv":8,"upper":501.0100,"lower":487.0500,"count":8,"preSum":361},{"ndv":8,"upper":597.8100,"lower":593.4200,"count":8,"preSum":369},{"ndv":8,"upper":646.6300,"lower":598.1800,"count":8,"preSum":377},{"ndv":6,"upper":651.4200,"lower":647.3000,"count":8,"preSum":385},{"ndv":6,"upper":655.8200,"lower":652.5900,"count":8,"preSum":393},{"ndv":7,"upper":711.8100,"lower":655.9100,"count":8,"preSum":401},{"ndv":6,"upper":722.5900,"lower":715.0200,"count":8,"preSum":409},{"ndv":8,"upper":940.6500,"lower":724.3200,"count":8,"preSum":417},{"ndv":8,"upper":978.0600,"lower":960.0800,"count":8,"preSum":425},{"ndv":8,"upper":1001.1500,"lower":980.9200,"count":8,"preSum":433},{"ndv":8,"upper":1614.4100,"lower":1003.2900,"count":8,"preSum":441},{"ndv":8,"upper":1629.2400,"lower":1614.9100,"count":8,"preSum":449},{"ndv":8,"upper":1746.0600,"lower":1631.6900,"count":8,"preSum":457},{"ndv":8,"upper":1748.1200,"lower":1746.1400,"count":8,"preSum":465},{"ndv":8,"upper":1916.3200,"lower":1748.4000,"count":8,"preSum":473},{"ndv":8,"upper":1920.4300,"lower":1916.8000,"count":8,"preSum":481},{"ndv":8,"upper":1924.2600,"lower":1920.9600,"count":8,"preSum":489},{"ndv":5,"upper":2245.8400,"lower":1924.9200,"count":5,"preSum":497}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[80481,62,24,35,25,18,19,8,17,10,23,8,12,9],"valueArr":[0.0000,0.0100,0.0200,0.0400,0.0500,0.0700,0.2200,0.4700,0.9700,1.7200,14.1900,15.3500,36.6700,106.7500],"type":"Double","sampleRate":0.8511520227425546}',18748,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','pap_b',11016405,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":68,"upper":0.7900,"lower":0.0300,"count":1410,"preSum":0},{"ndv":101,"upper":1.9600,"lower":0.8000,"count":1408,"preSum":1410},{"ndv":187,"upper":4.5800,"lower":1.9700,"count":1400,"preSum":2818},{"ndv":217,"upper":8.2100,"lower":4.5990,"count":1400,"preSum":4218},{"ndv":395,"upper":13.8400,"lower":8.2200,"count":1399,"preSum":5618},{"ndv":501,"upper":21.9600,"lower":13.8500,"count":1399,"preSum":7017},{"ndv":527,"upper":33.9900,"lower":21.9800,"count":1402,"preSum":8416},{"ndv":623,"upper":50.5600,"lower":34.0000,"count":1395,"preSum":9818},{"ndv":647,"upper":73.8200,"lower":50.5800,"count":1395,"preSum":11213},{"ndv":791,"upper":100.4400,"lower":73.8500,"count":1395,"preSum":12608},{"ndv":816,"upper":135.6800,"lower":100.4800,"count":1395,"preSum":14003},{"ndv":842,"upper":180.2300,"lower":135.6900,"count":1396,"preSum":15398},{"ndv":883,"upper":224.8500,"lower":180.2400,"count":1396,"preSum":16794},{"ndv":862,"upper":272.2200,"lower":224.8800,"count":1395,"preSum":18190},{"ndv":858,"upper":326.7500,"lower":272.2300,"count":1397,"preSum":19585},{"ndv":970,"upper":386.2500,"lower":326.8000,"count":1395,"preSum":20982},{"ndv":968,"upper":458.9400,"lower":386.2900,"count":1404,"preSum":22377},{"ndv":1015,"upper":527.6000,"lower":458.9500,"count":1395,"preSum":23781},{"ndv":1060,"upper":602.8400,"lower":527.6200,"count":1395,"preSum":25176},{"ndv":1098,"upper":696.6000,"lower":602.8600,"count":1395,"preSum":26571},{"ndv":1058,"upper":775.4100,"lower":696.6100,"count":1395,"preSum":27966},{"ndv":1093,"upper":853.0900,"lower":775.4800,"count":1407,"preSum":29361},{"ndv":1144,"upper":944.8600,"lower":853.1100,"count":1395,"preSum":30768},{"ndv":1112,"upper":1041.2400,"lower":944.8900,"count":1395,"preSum":32163},{"ndv":1158,"upper":1165.3900,"lower":1041.2800,"count":1395,"preSum":33558},{"ndv":1100,"upper":1275.6400,"lower":1165.4200,"count":1395,"preSum":34953},{"ndv":1182,"upper":1379.2100,"lower":1275.7200,"count":1395,"preSum":36348},{"ndv":1208,"upper":1496.3300,"lower":1379.2800,"count":1395,"preSum":37743},{"ndv":1201,"upper":1602.2100,"lower":1496.3500,"count":1395,"preSum":39138},{"ndv":1195,"upper":1705.2200,"lower":1602.2400,"count":1395,"preSum":40533},{"ndv":1209,"upper":1833.8700,"lower":1705.2600,"count":1396,"preSum":41928},{"ndv":1221,"upper":1970.0000,"lower":1833.9900,"count":1409,"preSum":43324},{"ndv":1195,"upper":2115.6400,"lower":1970.1000,"count":1395,"preSum":44733},{"ndv":1216,"upper":2241.2600,"lower":2115.6700,"count":1395,"preSum":46128},{"ndv":1251,"upper":2391.1500,"lower":2241.3400,"count":1395,"preSum":47523},{"ndv":1221,"upper":2519.6100,"lower":2391.1600,"count":1395,"preSum":48918},{"ndv":1243,"upper":2643.0200,"lower":2519.7000,"count":1403,"preSum":50313},{"ndv":1227,"upper":2806.6900,"lower":2643.3400,"count":1395,"preSum":51716},{"ndv":1274,"upper":2981.4100,"lower":2806.7000,"count":1395,"preSum":53111},{"ndv":1302,"upper":3114.8600,"lower":2981.4600,"count":1395,"preSum":54506},{"ndv":1317,"upper":3286.9800,"lower":3114.9500,"count":1395,"preSum":55901},{"ndv":1276,"upper":3470.0000,"lower":3287.2500,"count":1395,"preSum":57296},{"ndv":1261,"upper":3674.9400,"lower":3470.1100,"count":1395,"preSum":58691},{"ndv":1241,"upper":3869.8900,"lower":3675.1300,"count":1395,"preSum":60086},{"ndv":1312,"upper":4113.1500,"lower":3869.9400,"count":1395,"preSum":61481},{"ndv":1287,"upper":4360.8500,"lower":4113.2800,"count":1395,"preSum":62876},{"ndv":1261,"upper":4569.4300,"lower":4360.8600,"count":1395,"preSum":64271},{"ndv":1318,"upper":4804.2100,"lower":4569.7600,"count":1395,"preSum":65666},{"ndv":1287,"upper":5115.5900,"lower":4804.6500,"count":1395,"preSum":67061},{"ndv":1245,"upper":5418.9000,"lower":5115.6100,"count":1396,"preSum":68456},{"ndv":1276,"upper":5777.3900,"lower":5419.0400,"count":1395,"preSum":69852},{"ndv":1296,"upper":6181.9100,"lower":5777.9300,"count":1395,"preSum":71247},{"ndv":1315,"upper":6652.6200,"lower":6182.2400,"count":1395,"preSum":72642},{"ndv":1330,"upper":7099.9300,"lower":6652.6600,"count":1395,"preSum":74037},{"ndv":1330,"upper":7647.0800,"lower":7100.7100,"count":1395,"preSum":75432},{"ndv":1358,"upper":8259.0300,"lower":7647.4600,"count":1395,"preSum":76827},{"ndv":1309,"upper":9010.7400,"lower":8259.0600,"count":1395,"preSum":78222},{"ndv":1323,"upper":9999.7200,"lower":9011.1500,"count":1395,"preSum":79617},{"ndv":1370,"upper":11275.7000,"lower":10001.3100,"count":1395,"preSum":81012},{"ndv":1321,"upper":13253.3700,"lower":11278.7600,"count":1398,"preSum":82407},{"ndv":1360,"upper":15952.4300,"lower":13254.0700,"count":1395,"preSum":83805},{"ndv":1301,"upper":20401.7300,"lower":15952.4800,"count":1395,"preSum":85200},{"ndv":1349,"upper":36865.6800,"lower":20406.7500,"count":1397,"preSum":86595},{"ndv":1193,"upper":270846.4400,"lower":36865.9800,"count":1242,"preSum":87992}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[6307,238,76,82,55,65,71,91,87,64,53,96,58],"valueArr":[0.0000,0.0100,0.0200,0.0800,0.1200,0.3000,0.3800,0.5100,0.5200,0.5500,0.6100,0.7400,1.0100],"type":"Double","sampleRate":0.8511520227425546}',3424,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','pap_pe',2801404,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":51,"upper":0.6600,"lower":0.0500,"count":398,"preSum":0},{"ndv":57,"upper":1.6000,"lower":0.6800,"count":384,"preSum":398},{"ndv":83,"upper":3.0100,"lower":1.6100,"count":382,"preSum":782},{"ndv":105,"upper":4.8500,"lower":3.0300,"count":396,"preSum":1164},{"ndv":132,"upper":6.6900,"lower":4.8600,"count":385,"preSum":1560},{"ndv":151,"upper":9.1200,"lower":6.7000,"count":381,"preSum":1945},{"ndv":163,"upper":11.9500,"lower":9.1300,"count":386,"preSum":2326},{"ndv":144,"upper":14.0800,"lower":11.9600,"count":385,"preSum":2712},{"ndv":211,"upper":18.2200,"lower":14.0900,"count":383,"preSum":3097},{"ndv":225,"upper":24.8100,"lower":18.2300,"count":381,"preSum":3480},{"ndv":201,"upper":29.9900,"lower":24.8400,"count":381,"preSum":3861},{"ndv":234,"upper":37.1900,"lower":30.0000,"count":399,"preSum":4242},{"ndv":263,"upper":44.6400,"lower":37.2100,"count":381,"preSum":4641},{"ndv":295,"upper":55.0100,"lower":44.6600,"count":383,"preSum":5022},{"ndv":268,"upper":66.7900,"lower":55.0200,"count":382,"preSum":5405},{"ndv":299,"upper":80.4900,"lower":66.8000,"count":381,"preSum":5787},{"ndv":321,"upper":96.0400,"lower":80.5000,"count":381,"preSum":6168},{"ndv":297,"upper":110.4900,"lower":96.0700,"count":381,"preSum":6549},{"ndv":297,"upper":131.6500,"lower":110.5000,"count":381,"preSum":6930},{"ndv":332,"upper":146.7100,"lower":131.9300,"count":381,"preSum":7311},{"ndv":268,"upper":158.9000,"lower":146.7500,"count":381,"preSum":7692},{"ndv":323,"upper":178.0000,"lower":158.9900,"count":381,"preSum":8073},{"ndv":326,"upper":199.9600,"lower":178.1200,"count":381,"preSum":8454},{"ndv":329,"upper":223.5200,"lower":199.9700,"count":382,"preSum":8835},{"ndv":330,"upper":249.1900,"lower":223.8200,"count":381,"preSum":9217},{"ndv":334,"upper":273.1000,"lower":249.6700,"count":381,"preSum":9598},{"ndv":315,"upper":293.2800,"lower":273.1500,"count":381,"preSum":9979},{"ndv":345,"upper":320.1900,"lower":293.3400,"count":381,"preSum":10360},{"ndv":329,"upper":350.8300,"lower":320.3800,"count":381,"preSum":10741},{"ndv":336,"upper":379.7500,"lower":350.9300,"count":381,"preSum":11122},{"ndv":345,"upper":405.7100,"lower":379.8200,"count":392,"preSum":11503},{"ndv":348,"upper":436.7800,"lower":405.7300,"count":381,"preSum":11895},{"ndv":329,"upper":475.8800,"lower":437.0600,"count":381,"preSum":12276},{"ndv":343,"upper":528.3000,"lower":475.9700,"count":381,"preSum":12657},{"ndv":370,"upper":589.4400,"lower":528.4300,"count":381,"preSum":13038},{"ndv":338,"upper":663.0900,"lower":589.4600,"count":381,"preSum":13419},{"ndv":368,"upper":745.1900,"lower":663.1400,"count":381,"preSum":13800},{"ndv":372,"upper":880.1200,"lower":746.4100,"count":381,"preSum":14181},{"ndv":344,"upper":979.8900,"lower":880.2500,"count":381,"preSum":14562},{"ndv":293,"upper":1075.2400,"lower":979.9700,"count":384,"preSum":14943},{"ndv":366,"upper":1236.7800,"lower":1075.2700,"count":381,"preSum":15327},{"ndv":356,"upper":1384.6300,"lower":1236.9600,"count":381,"preSum":15708},{"ndv":353,"upper":1596.0200,"lower":1384.8300,"count":381,"preSum":16089},{"ndv":353,"upper":1799.6600,"lower":1597.0300,"count":381,"preSum":16470},{"ndv":356,"upper":1950.8600,"lower":1801.3000,"count":381,"preSum":16851},{"ndv":293,"upper":2107.2000,"lower":1950.9600,"count":381,"preSum":17232},{"ndv":377,"upper":2436.1500,"lower":2107.5800,"count":381,"preSum":17613},{"ndv":350,"upper":2639.1700,"lower":2436.1900,"count":381,"preSum":17994},{"ndv":379,"upper":2881.5900,"lower":2639.2400,"count":381,"preSum":18375},{"ndv":378,"upper":3147.0100,"lower":2881.7400,"count":381,"preSum":18756},{"ndv":297,"upper":3313.1000,"lower":3147.5800,"count":381,"preSum":19137},{"ndv":344,"upper":3640.2900,"lower":3313.9300,"count":381,"preSum":19518},{"ndv":362,"upper":4011.3900,"lower":3640.6100,"count":381,"preSum":19899},{"ndv":327,"upper":4367.8700,"lower":4011.5700,"count":381,"preSum":20280},{"ndv":355,"upper":4930.5200,"lower":4369.8100,"count":381,"preSum":20661},{"ndv":377,"upper":5568.0200,"lower":4933.8700,"count":381,"preSum":21042},{"ndv":380,"upper":6534.3700,"lower":5569.4300,"count":381,"preSum":21423},{"ndv":380,"upper":7513.1700,"lower":6543.5600,"count":381,"preSum":21804},{"ndv":381,"upper":8882.0500,"lower":7514.6400,"count":381,"preSum":22185},{"ndv":381,"upper":10451.0600,"lower":8890.2000,"count":381,"preSum":22566},{"ndv":380,"upper":12927.3400,"lower":10455.1900,"count":381,"preSum":22947},{"ndv":377,"upper":17640.8000,"lower":12929.4100,"count":381,"preSum":23328},{"ndv":359,"upper":31257.4700,"lower":17650.3800,"count":381,"preSum":23709},{"ndv":209,"upper":109425.6500,"lower":31266.6400,"count":233,"preSum":24090}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[72751,97,57,31,44,48,67,33,29,29,29,29,31,29],"valueArr":[0.0000,0.0100,0.0200,0.0300,0.0400,0.1900,0.2100,0.2700,0.4000,6.1700,10.3300,30.1500,39.4800,853.0800],"type":"Double","sampleRate":0.8511520227425546}',2374,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','pap_po',9815470,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":66,"upper":0.7900,"lower":0.0500,"count":1253,"preSum":0},{"ndv":106,"upper":2.0900,"lower":0.8100,"count":1250,"preSum":1253},{"ndv":213,"upper":5.8800,"lower":2.1100,"count":1251,"preSum":2503},{"ndv":248,"upper":10.7900,"lower":5.8900,"count":1251,"preSum":3754},{"ndv":343,"upper":17.7500,"lower":10.8100,"count":1250,"preSum":5005},{"ndv":478,"upper":28.4600,"lower":17.7600,"count":1259,"preSum":6255},{"ndv":575,"upper":44.2000,"lower":28.5100,"count":1250,"preSum":7514},{"ndv":514,"upper":63.6300,"lower":44.2200,"count":1250,"preSum":8764},{"ndv":665,"upper":93.1600,"lower":63.9500,"count":1250,"preSum":10014},{"ndv":735,"upper":128.2500,"lower":93.1800,"count":1250,"preSum":11264},{"ndv":713,"upper":168.5800,"lower":128.3200,"count":1250,"preSum":12514},{"ndv":814,"upper":218.2100,"lower":168.6100,"count":1250,"preSum":13764},{"ndv":846,"upper":284.3400,"lower":218.2900,"count":1252,"preSum":15014},{"ndv":796,"upper":356.8200,"lower":284.3800,"count":1250,"preSum":16266},{"ndv":839,"upper":436.8300,"lower":356.8900,"count":1250,"preSum":17516},{"ndv":865,"upper":514.7000,"lower":436.9200,"count":1264,"preSum":18766},{"ndv":848,"upper":591.0500,"lower":514.7300,"count":1256,"preSum":20030},{"ndv":882,"upper":684.4600,"lower":591.1100,"count":1263,"preSum":21286},{"ndv":952,"upper":800.2900,"lower":684.6000,"count":1250,"preSum":22549},{"ndv":888,"upper":915.3400,"lower":800.3500,"count":1250,"preSum":23799},{"ndv":1003,"upper":1049.7900,"lower":915.4300,"count":1251,"preSum":25049},{"ndv":947,"upper":1184.2200,"lower":1049.9200,"count":1250,"preSum":26300},{"ndv":990,"upper":1326.3300,"lower":1184.2400,"count":1250,"preSum":27550},{"ndv":1078,"upper":1472.0900,"lower":1326.3400,"count":1250,"preSum":28800},{"ndv":1048,"upper":1621.2100,"lower":1472.2200,"count":1250,"preSum":30050},{"ndv":1042,"upper":1755.3100,"lower":1621.2900,"count":1250,"preSum":31300},{"ndv":1074,"upper":1900.9700,"lower":1755.7700,"count":1250,"preSum":32550},{"ndv":1085,"upper":2066.3300,"lower":1901.0100,"count":1250,"preSum":33800},{"ndv":1091,"upper":2200.3500,"lower":2066.3900,"count":1250,"preSum":35050},{"ndv":1088,"upper":2361.6200,"lower":2200.3900,"count":1250,"preSum":36300},{"ndv":1165,"upper":2529.8700,"lower":2362.0600,"count":1250,"preSum":37550},{"ndv":1119,"upper":2707.3900,"lower":2529.8900,"count":1250,"preSum":38800},{"ndv":1134,"upper":2898.1700,"lower":2707.4800,"count":1250,"preSum":40050},{"ndv":1124,"upper":3080.9500,"lower":2898.3000,"count":1250,"preSum":41300},{"ndv":1101,"upper":3270.2600,"lower":3081.0900,"count":1250,"preSum":42550},{"ndv":1133,"upper":3490.4600,"lower":3270.4200,"count":1250,"preSum":43800},{"ndv":1173,"upper":3688.5200,"lower":3490.7900,"count":1250,"preSum":45050},{"ndv":1088,"upper":3901.5400,"lower":3689.7200,"count":1250,"preSum":46300},{"ndv":1133,"upper":4133.7700,"lower":3902.4500,"count":1250,"preSum":47550},{"ndv":1136,"upper":4371.2800,"lower":4133.9200,"count":1250,"preSum":48800},{"ndv":1141,"upper":4616.5400,"lower":4371.4100,"count":1250,"preSum":50050},{"ndv":1163,"upper":4893.6700,"lower":4616.6500,"count":1250,"preSum":51300},{"ndv":1188,"upper":5138.4900,"lower":4893.8600,"count":1250,"preSum":52550},{"ndv":1161,"upper":5385.7600,"lower":5138.6800,"count":1251,"preSum":53800},{"ndv":1198,"upper":5671.5100,"lower":5385.8600,"count":1250,"preSum":55051},{"ndv":1174,"upper":6044.9900,"lower":5671.6300,"count":1250,"preSum":56301},{"ndv":1160,"upper":6391.3700,"lower":6045.3200,"count":1250,"preSum":57551},{"ndv":1132,"upper":6720.5900,"lower":6392.0200,"count":1250,"preSum":58801},{"ndv":1180,"upper":7081.4200,"lower":6721.6100,"count":1250,"preSum":60051},{"ndv":1205,"upper":7485.7100,"lower":7081.9200,"count":1250,"preSum":61301},{"ndv":1128,"upper":7942.1700,"lower":7486.0000,"count":1250,"preSum":62551},{"ndv":1209,"upper":8444.7400,"lower":7942.8300,"count":1250,"preSum":63801},{"ndv":1208,"upper":9017.4700,"lower":8445.3300,"count":1250,"preSum":65051},{"ndv":1154,"upper":9649.9700,"lower":9018.5900,"count":1250,"preSum":66301},{"ndv":1202,"upper":10363.7800,"lower":9650.3000,"count":1250,"preSum":67551},{"ndv":1207,"upper":11146.5900,"lower":10364.7500,"count":1250,"preSum":68801},{"ndv":1199,"upper":12253.1200,"lower":11146.8600,"count":1250,"preSum":70051},{"ndv":1202,"upper":13475.4600,"lower":12253.5200,"count":1250,"preSum":71301},{"ndv":1183,"upper":15009.2200,"lower":13476.2800,"count":1250,"preSum":72551},{"ndv":1128,"upper":16941.0800,"lower":15009.2800,"count":1250,"preSum":73801},{"ndv":1218,"upper":20675.4600,"lower":16941.3300,"count":1250,"preSum":75051},{"ndv":1193,"upper":27034.7600,"lower":20677.3900,"count":1250,"preSum":76301},{"ndv":1162,"upper":48155.0800,"lower":27039.0200,"count":1250,"preSum":77551},{"ndv":1115,"upper":471062.4800,"lower":48162.5900,"count":1140,"preSum":78801}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[15536,73,96,48,73,67,66,49,48,64,49,49,61,57],"valueArr":[0.0000,0.0100,0.0200,0.0300,0.0400,0.0800,0.3000,0.5200,0.7100,0.7800,0.8000,0.8400,1.2800,1.4400],"type":"Double","sampleRate":0.8511520227425546}',3724,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','pap_t',13385313,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":70,"upper":0.9000,"lower":0.0200,"count":1453,"preSum":0},{"ndv":127,"upper":2.3700,"lower":0.9100,"count":1452,"preSum":1453},{"ndv":268,"upper":9.0000,"lower":2.4000,"count":1453,"preSum":2905},{"ndv":297,"upper":20.1200,"lower":9.0300,"count":1464,"preSum":4358},{"ndv":431,"upper":38.5200,"lower":20.1400,"count":1446,"preSum":5822},{"ndv":646,"upper":64.8400,"lower":38.5500,"count":1457,"preSum":7268},{"ndv":686,"upper":103.5300,"lower":64.8600,"count":1446,"preSum":8725},{"ndv":633,"upper":164.6300,"lower":103.6400,"count":1446,"preSum":10171},{"ndv":904,"upper":249.6000,"lower":164.6500,"count":1446,"preSum":11617},{"ndv":818,"upper":359.5300,"lower":249.6600,"count":1455,"preSum":13063},{"ndv":910,"upper":490.3400,"lower":359.6000,"count":1447,"preSum":14518},{"ndv":961,"upper":663.1800,"lower":490.5200,"count":1452,"preSum":15965},{"ndv":907,"upper":872.3200,"lower":663.4500,"count":1446,"preSum":17417},{"ndv":1086,"upper":1074.4500,"lower":872.3700,"count":1446,"preSum":18863},{"ndv":975,"upper":1287.3500,"lower":1074.5900,"count":1446,"preSum":20309},{"ndv":1053,"upper":1498.0900,"lower":1288.4400,"count":1446,"preSum":21755},{"ndv":1082,"upper":1759.8500,"lower":1498.3600,"count":1446,"preSum":23201},{"ndv":1094,"upper":2023.0500,"lower":1759.9900,"count":1446,"preSum":24647},{"ndv":1154,"upper":2300.2100,"lower":2023.2800,"count":1446,"preSum":26093},{"ndv":1175,"upper":2602.2600,"lower":2300.2900,"count":1446,"preSum":27539},{"ndv":1198,"upper":2875.4800,"lower":2602.4000,"count":1463,"preSum":28985},{"ndv":1298,"upper":3285.1600,"lower":2876.1000,"count":1446,"preSum":30448},{"ndv":1231,"upper":3566.5200,"lower":3285.3200,"count":1446,"preSum":31894},{"ndv":1202,"upper":3875.6800,"lower":3566.8300,"count":1446,"preSum":33340},{"ndv":1244,"upper":4189.3900,"lower":3875.8100,"count":1446,"preSum":34786},{"ndv":1257,"upper":4554.7100,"lower":4189.9100,"count":1446,"preSum":36232},{"ndv":1293,"upper":4896.2100,"lower":4554.8800,"count":1446,"preSum":37678},{"ndv":1329,"upper":5257.6100,"lower":4896.2400,"count":1446,"preSum":39124},{"ndv":1334,"upper":5586.5700,"lower":5257.6200,"count":1446,"preSum":40570},{"ndv":1358,"upper":5947.7900,"lower":5586.6900,"count":1446,"preSum":42016},{"ndv":1348,"upper":6365.7200,"lower":5947.8000,"count":1446,"preSum":43462},{"ndv":1255,"upper":6761.1700,"lower":6366.4900,"count":1446,"preSum":44908},{"ndv":1317,"upper":7179.2500,"lower":6761.5600,"count":1446,"preSum":46354},{"ndv":1338,"upper":7577.1300,"lower":7179.2700,"count":1446,"preSum":47800},{"ndv":1361,"upper":8063.8100,"lower":7577.2700,"count":1446,"preSum":49246},{"ndv":1310,"upper":8582.0900,"lower":8064.2900,"count":1446,"preSum":50692},{"ndv":1351,"upper":9040.2400,"lower":8582.4400,"count":1446,"preSum":52138},{"ndv":1310,"upper":9515.2400,"lower":9040.3800,"count":1446,"preSum":53584},{"ndv":1338,"upper":10033.9000,"lower":9515.7900,"count":1446,"preSum":55030},{"ndv":1363,"upper":10621.5200,"lower":10034.7400,"count":1446,"preSum":56476},{"ndv":1357,"upper":11157.4800,"lower":10621.5400,"count":1446,"preSum":57922},{"ndv":1308,"upper":11689.6500,"lower":11157.7200,"count":1446,"preSum":59368},{"ndv":1381,"upper":12374.8800,"lower":11690.7500,"count":1446,"preSum":60814},{"ndv":1362,"upper":12916.1800,"lower":12375.5500,"count":1446,"preSum":62260},{"ndv":1362,"upper":13675.0600,"lower":12916.6400,"count":1446,"preSum":63706},{"ndv":1371,"upper":14548.0200,"lower":13675.1500,"count":1446,"preSum":65152},{"ndv":1351,"upper":15218.7100,"lower":14548.2400,"count":1446,"preSum":66598},{"ndv":1371,"upper":16067.1900,"lower":15219.5300,"count":1446,"preSum":68044},{"ndv":1357,"upper":17021.0800,"lower":16068.2100,"count":1446,"preSum":69490},{"ndv":1411,"upper":17916.5000,"lower":17021.6500,"count":1446,"preSum":70936},{"ndv":1398,"upper":18910.9300,"lower":17916.5200,"count":1446,"preSum":72382},{"ndv":1395,"upper":20138.1200,"lower":18911.8500,"count":1446,"preSum":73828},{"ndv":1394,"upper":21484.9300,"lower":20138.8300,"count":1446,"preSum":75274},{"ndv":1282,"upper":23124.2600,"lower":21487.2200,"count":1446,"preSum":76720},{"ndv":1420,"upper":25159.6000,"lower":23124.3700,"count":1446,"preSum":78166},{"ndv":1358,"upper":27031.0900,"lower":25160.9200,"count":1446,"preSum":79612},{"ndv":1391,"upper":29211.9300,"lower":27031.9800,"count":1446,"preSum":81058},{"ndv":1355,"upper":32287.5100,"lower":29212.8600,"count":1461,"preSum":82504},{"ndv":1430,"upper":35811.4500,"lower":32289.9800,"count":1446,"preSum":83965},{"ndv":1400,"upper":41628.6900,"lower":35815.9500,"count":1446,"preSum":85411},{"ndv":1384,"upper":49413.6600,"lower":41637.4200,"count":1446,"preSum":86857},{"ndv":1375,"upper":63941.3800,"lower":49419.1700,"count":1446,"preSum":88303},{"ndv":1381,"upper":116352.3900,"lower":63941.8900,"count":1446,"preSum":89749},{"ndv":1250,"upper":929808.6100,"lower":116361.4000,"count":1298,"preSum":91195}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[5007,105,71,93,59,79,65,87,87,65,61,70,59],"valueArr":[0.0000,0.0100,0.0500,0.3300,0.3400,0.3800,0.4500,0.5100,0.7400,0.7900,0.8000,0.8400,1.2100],"type":"Double","sampleRate":0.8511520227425546}',1600,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','pap_v',10768602,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":77,"upper":0.9000,"lower":0.0500,"count":1356,"preSum":0},{"ndv":148,"upper":2.8600,"lower":0.9100,"count":1352,"preSum":1356},{"ndv":218,"upper":6.0200,"lower":2.8700,"count":1366,"preSum":2708},{"ndv":301,"upper":11.5600,"lower":6.0300,"count":1352,"preSum":4074},{"ndv":421,"upper":20.2500,"lower":11.5800,"count":1355,"preSum":5426},{"ndv":479,"upper":33.2800,"lower":20.2600,"count":1368,"preSum":6781},{"ndv":638,"upper":54.6200,"lower":33.3200,"count":1349,"preSum":8149},{"ndv":722,"upper":80.8500,"lower":54.6600,"count":1353,"preSum":9498},{"ndv":617,"upper":109.7900,"lower":80.9100,"count":1350,"preSum":10851},{"ndv":760,"upper":145.8900,"lower":109.9600,"count":1349,"preSum":12201},{"ndv":789,"upper":184.5700,"lower":145.9400,"count":1349,"preSum":13550},{"ndv":894,"upper":246.4500,"lower":184.6200,"count":1349,"preSum":14899},{"ndv":808,"upper":303.9000,"lower":246.5000,"count":1349,"preSum":16248},{"ndv":917,"upper":363.9900,"lower":303.9100,"count":1350,"preSum":17597},{"ndv":950,"upper":430.4000,"lower":364.0700,"count":1349,"preSum":18947},{"ndv":997,"upper":489.2100,"lower":430.4100,"count":1349,"preSum":20296},{"ndv":868,"upper":557.1800,"lower":489.4200,"count":1349,"preSum":21645},{"ndv":995,"upper":634.3900,"lower":557.2500,"count":1368,"preSum":22994},{"ndv":1094,"upper":705.3600,"lower":634.4400,"count":1349,"preSum":24362},{"ndv":1081,"upper":781.9700,"lower":705.3700,"count":1362,"preSum":25711},{"ndv":1043,"upper":855.0400,"lower":782.0200,"count":1349,"preSum":27073},{"ndv":1089,"upper":937.8700,"lower":855.0500,"count":1350,"preSum":28422},{"ndv":1164,"upper":1022.1100,"lower":937.8800,"count":1349,"preSum":29772},{"ndv":1126,"upper":1093.3900,"lower":1022.3700,"count":1349,"preSum":31121},{"ndv":1095,"upper":1177.6800,"lower":1093.4200,"count":1349,"preSum":32470},{"ndv":1163,"upper":1270.3600,"lower":1177.7500,"count":1350,"preSum":33819},{"ndv":1165,"upper":1371.4800,"lower":1270.3800,"count":1349,"preSum":35169},{"ndv":1167,"upper":1464.5500,"lower":1371.5300,"count":1349,"preSum":36518},{"ndv":1170,"upper":1556.5400,"lower":1464.5600,"count":1349,"preSum":37867},{"ndv":1193,"upper":1649.0500,"lower":1556.6800,"count":1349,"preSum":39216},{"ndv":1121,"upper":1745.3700,"lower":1649.0900,"count":1349,"preSum":40565},{"ndv":1200,"upper":1864.3500,"lower":1745.4000,"count":1349,"preSum":41914},{"ndv":1197,"upper":1998.4800,"lower":1864.4300,"count":1349,"preSum":43263},{"ndv":1198,"upper":2103.9800,"lower":1998.7500,"count":1349,"preSum":44612},{"ndv":1227,"upper":2239.3600,"lower":2104.0700,"count":1349,"preSum":45961},{"ndv":1161,"upper":2346.3700,"lower":2239.7700,"count":1349,"preSum":47310},{"ndv":1234,"upper":2489.6900,"lower":2346.4900,"count":1349,"preSum":48659},{"ndv":1181,"upper":2623.2900,"lower":2489.7300,"count":1349,"preSum":50008},{"ndv":1180,"upper":2787.7100,"lower":2623.3400,"count":1352,"preSum":51357},{"ndv":1218,"upper":2940.1200,"lower":2787.7200,"count":1349,"preSum":52709},{"ndv":1175,"upper":3103.2700,"lower":2940.3300,"count":1349,"preSum":54058},{"ndv":1176,"upper":3272.7900,"lower":3103.8300,"count":1349,"preSum":55407},{"ndv":1223,"upper":3438.1900,"lower":3273.0300,"count":1349,"preSum":56756},{"ndv":1211,"upper":3639.9100,"lower":3438.4100,"count":1349,"preSum":58105},{"ndv":1266,"upper":3834.2500,"lower":3640.0300,"count":1349,"preSum":59454},{"ndv":1294,"upper":4057.1100,"lower":3834.2800,"count":1349,"preSum":60803},{"ndv":1269,"upper":4315.8500,"lower":4057.1800,"count":1349,"preSum":62152},{"ndv":1181,"upper":4588.8500,"lower":4315.8600,"count":1349,"preSum":63501},{"ndv":1263,"upper":4831.8600,"lower":4588.8800,"count":1349,"preSum":64850},{"ndv":1296,"upper":5107.6800,"lower":4831.9200,"count":1349,"preSum":66199},{"ndv":1228,"upper":5425.6100,"lower":5107.8200,"count":1349,"preSum":67548},{"ndv":1288,"upper":5750.2500,"lower":5426.0400,"count":1349,"preSum":68897},{"ndv":1241,"upper":6208.7200,"lower":5750.4900,"count":1349,"preSum":70246},{"ndv":1286,"upper":6629.3000,"lower":6208.8900,"count":1349,"preSum":71595},{"ndv":1243,"upper":7150.8500,"lower":6629.3100,"count":1349,"preSum":72944},{"ndv":1308,"upper":7632.7900,"lower":7150.8600,"count":1349,"preSum":74293},{"ndv":1313,"upper":8277.4700,"lower":7633.0100,"count":1349,"preSum":75642},{"ndv":1332,"upper":9135.2800,"lower":8277.5700,"count":1349,"preSum":76991},{"ndv":1222,"upper":10315.4600,"lower":9135.5100,"count":1349,"preSum":78340},{"ndv":1257,"upper":11835.1700,"lower":10315.6200,"count":1349,"preSum":79689},{"ndv":1319,"upper":14297.7900,"lower":11835.7000,"count":1349,"preSum":81038},{"ndv":1308,"upper":18956.1000,"lower":14301.5800,"count":1349,"preSum":82387},{"ndv":1235,"upper":31743.0500,"lower":18961.2500,"count":1349,"preSum":83736},{"ndv":1199,"upper":266206.2800,"lower":31748.6400,"count":1247,"preSum":85085}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[8882,131,115,68,115,74,88,71,70,43,62,45,40],"valueArr":[0.0000,0.0100,0.0200,0.0300,0.0400,0.0600,0.0800,0.0900,0.1700,0.1800,0.2000,1.6700,24.1000],"type":"Double","sampleRate":0.8511520227425546}',3865,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','preposition_time',9221393,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":1508,"upper":"1851065426071519232","lower":"1851052153146179584","count":1560,"preSum":0},{"ndv":1508,"upper":"1851080858711097344","lower":"1851065426155405312","count":1560,"preSum":1560},{"ndv":1513,"upper":"1851096159045550080","lower":"1851080861093462016","count":1560,"preSum":3120},{"ndv":1507,"upper":"1851111538736234496","lower":"1851096159213322240","count":1560,"preSum":4680},{"ndv":1521,"upper":"1851131427756703744","lower":"1851111538954338304","count":1560,"preSum":6240},{"ndv":1517,"upper":"1851151115802902528","lower":"1851131428058693632","count":1560,"preSum":7800},{"ndv":1524,"upper":"1851168722333466624","lower":"1851151116440436736","count":1560,"preSum":9360},{"ndv":1530,"upper":"1851186341061066752","lower":"1851168722836783104","count":1560,"preSum":10920},{"ndv":1466,"upper":"1851417472075300864","lower":"1851186341111398400","count":1560,"preSum":12480},{"ndv":1485,"upper":"1851417946736295936","lower":"1851417472192741376","count":1560,"preSum":14040},{"ndv":1084,"upper":"1851419898262061056","lower":"1851417948464349184","count":1560,"preSum":15600},{"ndv":1460,"upper":"1851420616628895744","lower":"1851419898597605376","count":1560,"preSum":17160},{"ndv":1524,"upper":"1851423870955814912","lower":"1851420620672204800","count":1560,"preSum":18720},{"ndv":1476,"upper":"1851424871599308800","lower":"1851423871056478208","count":1560,"preSum":20280},{"ndv":1362,"upper":"1851431766145892352","lower":"1851424871733526528","count":1560,"preSum":21840},{"ndv":1401,"upper":"1851432626112430080","lower":"1851431766196224000","count":1560,"preSum":23400},{"ndv":1348,"upper":"1851432835609526272","lower":"1851432626263425024","count":1560,"preSum":24960},{"ndv":1364,"upper":"1851433071832727552","lower":"1851432835659857920","count":1560,"preSum":26520},{"ndv":1136,"upper":"1851434799181332480","lower":"1851433071899836416","count":1560,"preSum":28080},{"ndv":792,"upper":"1851434826863738880","lower":"1851434799198109696","count":1562,"preSum":29640},{"ndv":1109,"upper":"1851436999899086848","lower":"1851434826880516096","count":1560,"preSum":31202},{"ndv":1344,"upper":"1851439200818167808","lower":"1851436999966195712","count":1560,"preSum":32762},{"ndv":1309,"upper":"1851439321781895168","lower":"1851439200851722240","count":1560,"preSum":34322},{"ndv":1378,"upper":"1851439576929796096","lower":"1851439321899335680","count":1560,"preSum":35882},{"ndv":1268,"upper":"1851441389221445632","lower":"1851439577030459392","count":1562,"preSum":37442},{"ndv":803,"upper":"1851441415930773504","lower":"1851441389238222848","count":1560,"preSum":39004},{"ndv":1049,"upper":"1851443580929835008","lower":"1851441415964327936","count":1560,"preSum":40564},{"ndv":845,"upper":"1851443612789768192","lower":"1851443580946612224","count":1561,"preSum":42124},{"ndv":958,"upper":"1851443656007876608","lower":"1851443612940763136","count":1560,"preSum":43685},{"ndv":874,"upper":"1851445802233233408","lower":"1851443656041431040","count":1561,"preSum":45245},{"ndv":867,"upper":"1851445832734212096","lower":"1851445802283565056","count":1560,"preSum":46806},{"ndv":1030,"upper":"1851447998924455936","lower":"1851445832784543744","count":1560,"preSum":48366},{"ndv":963,"upper":"1851448032965427200","lower":"1851447998941233152","count":1561,"preSum":49926},{"ndv":1062,"upper":"1851450198518136832","lower":"1851448033049313280","count":1560,"preSum":51487},{"ndv":868,"upper":"1851450223667183616","lower":"1851450198534914048","count":1561,"preSum":53047},{"ndv":1097,"upper":"1851452387709943808","lower":"1851450223717515264","count":1562,"preSum":54608},{"ndv":811,"upper":"1851452495620997120","lower":"1851452387726721024","count":1563,"preSum":56170},{"ndv":1136,"upper":"1851454592991100928","lower":"1851452495637774336","count":1560,"preSum":57733},{"ndv":942,"upper":"1851454632534999040","lower":"1851454593007878144","count":1560,"preSum":59293},{"ndv":1155,"upper":"1851456792651890688","lower":"1851454632551776256","count":1564,"preSum":60853},{"ndv":878,"upper":"1851456822699884544","lower":"1851456792735776768","count":1561,"preSum":62417},{"ndv":1139,"upper":"1851458986440654848","lower":"1851456822716661760","count":1560,"preSum":63978},{"ndv":826,"upper":"1851459010968944640","lower":"1851458986490986496","count":1560,"preSum":65538},{"ndv":1118,"upper":"1851461180413968384","lower":"1851459011103162368","count":1562,"preSum":67098},{"ndv":939,"upper":"1851461216283656192","lower":"1851461180430745600","count":1562,"preSum":68660},{"ndv":1266,"upper":"1851461799291912192","lower":"1851461216384319488","count":1560,"preSum":70222},{"ndv":1475,"upper":"1851462302675501056","lower":"1851461799359021056","count":1560,"preSum":71782},{"ndv":1373,"upper":"1851463396096999424","lower":"1851462302910382080","count":1561,"preSum":73342},{"ndv":1343,"upper":"1851463608513331200","lower":"1851463396113776640","count":1561,"preSum":74903},{"ndv":1403,"upper":"1851464026786103296","lower":"1851463608731435008","count":1560,"preSum":76464},{"ndv":1044,"upper":"1851465593476087808","lower":"1851464026920321024","count":1563,"preSum":78024},{"ndv":910,"upper":"1851465624815927296","lower":"1851465593492865024","count":1562,"preSum":79587},{"ndv":1057,"upper":"1851467792264462336","lower":"1851465624849481728","count":1561,"preSum":81149},{"ndv":906,"upper":"1851467823939846144","lower":"1851467792281239552","count":1560,"preSum":82710},{"ndv":1074,"upper":"1851476576495992832","lower":"1851467823956623360","count":1564,"preSum":84270},{"ndv":807,"upper":"1851476601728925696","lower":"1851476576546324480","count":1561,"preSum":85834},{"ndv":1081,"upper":"1851478769294901248","lower":"1851476601745702912","count":1560,"preSum":87395},{"ndv":771,"upper":"1851478794443948032","lower":"1851478769311678464","count":1560,"preSum":88955},{"ndv":935,"upper":"1851478834122063872","lower":"1851478794460725248","count":1560,"preSum":90515},{"ndv":984,"upper":"1851480984743051264","lower":"1851478834155618304","count":1560,"preSum":92075},{"ndv":886,"upper":"1851481013599862784","lower":"1851480984759828480","count":1560,"preSum":93635},{"ndv":1064,"upper":"1851483175813906432","lower":"1851481013633417216","count":1560,"preSum":95195},{"ndv":803,"upper":"1851483200677740544","lower":"1851483175847460864","count":1560,"preSum":96755},{"ndv":1002,"upper":"1851483675070300160","lower":"1851483200711294976","count":1495,"preSum":98315}],"maxBucketSize":64,"type":"Datetime","sampleRate":0.851152}','{"countArr":[71,9,9,9,9,9,9,10,9,9,9,9,10,10],"valueArr":[-1,1851434790171967488,1851434815136464896,1851434826159095808,1851447990468739072,1851452392172683264,1851465575943897088,1851476571144060928,1851476572318466048,1851476608053936128,1851478782716674048,1851478798923464704,1851480984977932288,1851483183011332096],"type":"Datetime","sampleRate":0.8511520227425546}',0,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','prp_b',48147,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":5,"upper":0.8100,"lower":0.7600,"count":6,"preSum":0},{"ndv":3,"upper":0.8500,"lower":0.8200,"count":6,"preSum":6},{"ndv":6,"upper":9.3020,"lower":0.8600,"count":6,"preSum":12},{"ndv":3,"upper":9.3900,"lower":9.3300,"count":6,"preSum":18},{"ndv":5,"upper":9.4500,"lower":9.4100,"count":7,"preSum":24},{"ndv":6,"upper":13.4400,"lower":9.8700,"count":6,"preSum":31},{"ndv":6,"upper":15.2500,"lower":13.4670,"count":6,"preSum":37},{"ndv":6,"upper":20.8860,"lower":15.3600,"count":6,"preSum":43},{"ndv":6,"upper":26.8650,"lower":23.1040,"count":6,"preSum":49},{"ndv":6,"upper":36.4200,"lower":29.6150,"count":6,"preSum":55},{"ndv":6,"upper":43.7720,"lower":36.9200,"count":6,"preSum":61},{"ndv":6,"upper":48.5900,"lower":45.1380,"count":6,"preSum":67},{"ndv":6,"upper":52.4580,"lower":48.9040,"count":6,"preSum":73},{"ndv":6,"upper":59.6870,"lower":52.6540,"count":6,"preSum":79},{"ndv":6,"upper":70.1490,"lower":61.0070,"count":6,"preSum":85},{"ndv":6,"upper":74.9600,"lower":71.8220,"count":6,"preSum":91},{"ndv":6,"upper":75.6900,"lower":75.0000,"count":6,"preSum":97},{"ndv":6,"upper":81.0600,"lower":75.7400,"count":6,"preSum":103},{"ndv":6,"upper":87.7510,"lower":81.1100,"count":6,"preSum":109},{"ndv":6,"upper":96.7100,"lower":90.2220,"count":6,"preSum":115},{"ndv":6,"upper":97.6000,"lower":97.2200,"count":6,"preSum":121},{"ndv":6,"upper":98.2800,"lower":97.6900,"count":6,"preSum":127},{"ndv":6,"upper":99.3350,"lower":98.3400,"count":6,"preSum":133},{"ndv":6,"upper":139.2000,"lower":124.3000,"count":6,"preSum":139},{"ndv":6,"upper":139.7200,"lower":139.3300,"count":6,"preSum":145},{"ndv":6,"upper":140.0000,"lower":139.8200,"count":6,"preSum":151},{"ndv":6,"upper":178.3600,"lower":140.0500,"count":6,"preSum":157},{"ndv":6,"upper":180.0300,"lower":178.6900,"count":6,"preSum":163},{"ndv":6,"upper":182.1700,"lower":180.3000,"count":6,"preSum":169},{"ndv":6,"upper":204.0100,"lower":182.4000,"count":6,"preSum":175},{"ndv":6,"upper":205.7300,"lower":204.2900,"count":6,"preSum":181},{"ndv":6,"upper":315.7100,"lower":206.0500,"count":6,"preSum":187},{"ndv":6,"upper":319.7000,"lower":316.2300,"count":6,"preSum":193},{"ndv":6,"upper":321.9500,"lower":320.0100,"count":6,"preSum":199},{"ndv":6,"upper":346.1300,"lower":322.6800,"count":6,"preSum":205},{"ndv":6,"upper":407.3100,"lower":346.3400,"count":6,"preSum":211},{"ndv":6,"upper":409.7600,"lower":407.6400,"count":6,"preSum":217},{"ndv":6,"upper":551.0100,"lower":409.9400,"count":6,"preSum":223},{"ndv":5,"upper":634.5600,"lower":552.2700,"count":6,"preSum":229},{"ndv":6,"upper":645.7800,"lower":636.4200,"count":6,"preSum":235},{"ndv":6,"upper":768.6700,"lower":648.5300,"count":6,"preSum":241},{"ndv":6,"upper":775.9700,"lower":769.3400,"count":6,"preSum":247},{"ndv":6,"upper":780.0900,"lower":776.5200,"count":6,"preSum":253},{"ndv":6,"upper":831.2000,"lower":780.6800,"count":6,"preSum":259},{"ndv":6,"upper":835.5000,"lower":832.3700,"count":6,"preSum":265},{"ndv":6,"upper":839.9100,"lower":835.9800,"count":6,"preSum":271},{"ndv":6,"upper":1044.6400,"lower":840.3000,"count":6,"preSum":277},{"ndv":6,"upper":2618.2400,"lower":2615.6900,"count":6,"preSum":283},{"ndv":6,"upper":2619.3900,"lower":2618.4800,"count":6,"preSum":289},{"ndv":6,"upper":2621.4500,"lower":2619.4300,"count":6,"preSum":295},{"ndv":6,"upper":3898.0600,"lower":2621.7000,"count":6,"preSum":301},{"ndv":6,"upper":3914.9000,"lower":3900.2400,"count":6,"preSum":307},{"ndv":6,"upper":3937.0100,"lower":3919.1300,"count":6,"preSum":313},{"ndv":2,"upper":3944.4100,"lower":3940.0500,"count":2,"preSum":319}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[8,3,16,3],"valueArr":[0.0000,0.8700,1.0500,9.3800],"type":"Double","sampleRate":0.8511520227425546}',99650,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','prp_pe',32207,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":3,"upper":0.4500,"lower":0.1080,"count":5,"preSum":0},{"ndv":3,"upper":2.3570,"lower":0.4600,"count":4,"preSum":5},{"ndv":4,"upper":3.6790,"lower":2.5600,"count":4,"preSum":9},{"ndv":4,"upper":6.8300,"lower":5.4290,"count":4,"preSum":13},{"ndv":4,"upper":6.8900,"lower":6.8400,"count":5,"preSum":17},{"ndv":3,"upper":6.9300,"lower":6.9100,"count":4,"preSum":22},{"ndv":4,"upper":8.0720,"lower":7.5800,"count":4,"preSum":26},{"ndv":4,"upper":13.4300,"lower":9.1880,"count":4,"preSum":30},{"ndv":4,"upper":21.5810,"lower":13.5100,"count":4,"preSum":34},{"ndv":4,"upper":27.1140,"lower":24.7860,"count":4,"preSum":38},{"ndv":4,"upper":32.2300,"lower":27.1250,"count":4,"preSum":42},{"ndv":4,"upper":32.6200,"lower":32.3580,"count":4,"preSum":46},{"ndv":4,"upper":36.0600,"lower":33.4530,"count":4,"preSum":50},{"ndv":4,"upper":42.3540,"lower":37.6050,"count":4,"preSum":54},{"ndv":4,"upper":46.4210,"lower":42.5740,"count":4,"preSum":58},{"ndv":4,"upper":47.1370,"lower":46.5700,"count":4,"preSum":62},{"ndv":4,"upper":54.5950,"lower":47.1700,"count":4,"preSum":66},{"ndv":4,"upper":56.6700,"lower":56.4960,"count":4,"preSum":70},{"ndv":4,"upper":57.0980,"lower":56.8700,"count":4,"preSum":74},{"ndv":4,"upper":57.2900,"lower":57.1000,"count":4,"preSum":78},{"ndv":4,"upper":64.8760,"lower":62.7670,"count":4,"preSum":82},{"ndv":4,"upper":71.2790,"lower":68.5800,"count":4,"preSum":86},{"ndv":4,"upper":77.2530,"lower":74.4990,"count":4,"preSum":90},{"ndv":4,"upper":82.1390,"lower":78.2220,"count":4,"preSum":94},{"ndv":4,"upper":88.8800,"lower":86.9340,"count":4,"preSum":98},{"ndv":4,"upper":90.0200,"lower":89.4600,"count":4,"preSum":102},{"ndv":4,"upper":90.4100,"lower":90.1100,"count":4,"preSum":106},{"ndv":4,"upper":90.7040,"lower":90.4600,"count":4,"preSum":110},{"ndv":3,"upper":90.9700,"lower":90.8100,"count":4,"preSum":114},{"ndv":4,"upper":91.3860,"lower":91.0600,"count":4,"preSum":118},{"ndv":4,"upper":94.7930,"lower":92.9230,"count":4,"preSum":122},{"ndv":4,"upper":99.5140,"lower":95.5390,"count":4,"preSum":126},{"ndv":4,"upper":100.1600,"lower":99.5310,"count":4,"preSum":130},{"ndv":4,"upper":118.2400,"lower":100.3800,"count":4,"preSum":134},{"ndv":4,"upper":119.4000,"lower":118.4700,"count":4,"preSum":138},{"ndv":4,"upper":153.5000,"lower":119.5700,"count":4,"preSum":142},{"ndv":4,"upper":178.6600,"lower":162.2100,"count":4,"preSum":146},{"ndv":4,"upper":179.8400,"lower":178.9500,"count":4,"preSum":150},{"ndv":4,"upper":180.9900,"lower":180.1100,"count":4,"preSum":154},{"ndv":4,"upper":202.5700,"lower":181.6200,"count":4,"preSum":158},{"ndv":4,"upper":205.0000,"lower":203.4000,"count":4,"preSum":162},{"ndv":3,"upper":205.3300,"lower":205.2000,"count":4,"preSum":166},{"ndv":4,"upper":205.7800,"lower":205.5100,"count":4,"preSum":170},{"ndv":4,"upper":207.5300,"lower":205.8500,"count":4,"preSum":174},{"ndv":4,"upper":439.1000,"lower":207.7000,"count":4,"preSum":178},{"ndv":3,"upper":674.5800,"lower":440.2300,"count":4,"preSum":182},{"ndv":4,"upper":683.7100,"lower":677.4000,"count":4,"preSum":186},{"ndv":4,"upper":691.9400,"lower":686.7000,"count":4,"preSum":190},{"ndv":4,"upper":729.2200,"lower":694.8900,"count":4,"preSum":194},{"ndv":4,"upper":735.8400,"lower":730.6600,"count":4,"preSum":198},{"ndv":4,"upper":741.3100,"lower":737.0900,"count":4,"preSum":202},{"ndv":4,"upper":746.6900,"lower":742.3000,"count":4,"preSum":206},{"ndv":4,"upper":750.4200,"lower":747.4200,"count":4,"preSum":210},{"ndv":4,"upper":1009.9000,"lower":751.0500,"count":4,"preSum":214}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[119,3,4,3,4],"valueArr":[0.0000,0.4200,0.4400,0.4700,6.9400],"type":"Double","sampleRate":0.8511520227425546}',99650,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','prp_po',51063,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":6,"upper":5.0700,"lower":0.0300,"count":6,"preSum":0},{"ndv":6,"upper":5.3340,"lower":5.1150,"count":6,"preSum":6},{"ndv":6,"upper":5.6400,"lower":5.3800,"count":6,"preSum":12},{"ndv":6,"upper":10.6430,"lower":5.7000,"count":6,"preSum":18},{"ndv":4,"upper":15.7900,"lower":11.0270,"count":6,"preSum":24},{"ndv":5,"upper":15.9100,"lower":15.8200,"count":6,"preSum":30},{"ndv":6,"upper":16.6440,"lower":15.9200,"count":6,"preSum":36},{"ndv":6,"upper":25.6170,"lower":16.9730,"count":6,"preSum":42},{"ndv":6,"upper":29.5240,"lower":25.9000,"count":6,"preSum":48},{"ndv":6,"upper":36.8090,"lower":31.0840,"count":6,"preSum":54},{"ndv":6,"upper":41.9260,"lower":37.2300,"count":6,"preSum":60},{"ndv":6,"upper":46.3700,"lower":41.9450,"count":6,"preSum":66},{"ndv":6,"upper":49.0770,"lower":46.5200,"count":6,"preSum":72},{"ndv":6,"upper":59.6480,"lower":49.2700,"count":6,"preSum":78},{"ndv":6,"upper":67.3400,"lower":60.9450,"count":6,"preSum":84},{"ndv":6,"upper":70.4160,"lower":67.4610,"count":6,"preSum":90},{"ndv":6,"upper":76.2250,"lower":71.1060,"count":6,"preSum":96},{"ndv":6,"upper":86.2170,"lower":76.9440,"count":6,"preSum":102},{"ndv":6,"upper":93.4990,"lower":86.3370,"count":6,"preSum":108},{"ndv":6,"upper":115.8200,"lower":93.7720,"count":6,"preSum":114},{"ndv":6,"upper":116.7700,"lower":115.9100,"count":6,"preSum":120},{"ndv":6,"upper":122.0900,"lower":116.9700,"count":6,"preSum":126},{"ndv":6,"upper":122.7500,"lower":122.2100,"count":6,"preSum":132},{"ndv":5,"upper":123.4100,"lower":122.8500,"count":6,"preSum":138},{"ndv":6,"upper":173.1100,"lower":123.5300,"count":6,"preSum":144},{"ndv":6,"upper":185.2200,"lower":182.2900,"count":6,"preSum":150},{"ndv":6,"upper":187.6200,"lower":185.5400,"count":6,"preSum":156},{"ndv":6,"upper":238.8700,"lower":188.7000,"count":6,"preSum":162},{"ndv":6,"upper":240.0500,"lower":239.0400,"count":6,"preSum":168},{"ndv":6,"upper":257.6100,"lower":240.1500,"count":6,"preSum":174},{"ndv":6,"upper":261.5300,"lower":258.0700,"count":6,"preSum":180},{"ndv":6,"upper":265.1400,"lower":261.9700,"count":6,"preSum":186},{"ndv":6,"upper":472.9800,"lower":265.6700,"count":6,"preSum":192},{"ndv":6,"upper":481.0600,"lower":475.8200,"count":6,"preSum":198},{"ndv":6,"upper":484.5500,"lower":481.9000,"count":6,"preSum":204},{"ndv":6,"upper":623.9400,"lower":484.9700,"count":6,"preSum":210},{"ndv":6,"upper":665.7000,"lower":624.2200,"count":6,"preSum":216},{"ndv":6,"upper":701.8000,"lower":695.3300,"count":6,"preSum":222},{"ndv":6,"upper":710.5000,"lower":703.2400,"count":6,"preSum":228},{"ndv":6,"upper":715.2800,"lower":711.3800,"count":6,"preSum":234},{"ndv":5,"upper":740.1200,"lower":715.6600,"count":6,"preSum":240},{"ndv":6,"upper":747.0900,"lower":741.1900,"count":6,"preSum":246},{"ndv":6,"upper":822.5900,"lower":748.4400,"count":6,"preSum":252},{"ndv":6,"upper":827.4200,"lower":823.1200,"count":6,"preSum":258},{"ndv":6,"upper":1058.6200,"lower":828.0400,"count":6,"preSum":264},{"ndv":6,"upper":1148.1900,"lower":1060.3100,"count":6,"preSum":270},{"ndv":6,"upper":1157.5300,"lower":1151.2200,"count":6,"preSum":276},{"ndv":6,"upper":1289.1700,"lower":1158.4800,"count":6,"preSum":282},{"ndv":6,"upper":6041.0700,"lower":1292.2600,"count":6,"preSum":288},{"ndv":6,"upper":6048.2200,"lower":6043.0700,"count":6,"preSum":294},{"ndv":6,"upper":6053.8900,"lower":6049.5200,"count":6,"preSum":300},{"ndv":6,"upper":6237.4600,"lower":6054.8100,"count":6,"preSum":306},{"ndv":6,"upper":6277.7200,"lower":6253.1800,"count":6,"preSum":312},{"ndv":6,"upper":6313.0100,"lower":6283.9000,"count":6,"preSum":318},{"ndv":4,"upper":6338.7500,"lower":6319.5300,"count":4,"preSum":324}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[4,16,3],"valueArr":[0.0000,0.1600,0.6400],"type":"Double","sampleRate":0.8511520227425546}',99650,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','prp_t',734879,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":14,"upper":0.6400,"lower":0.0300,"count":96,"preSum":0},{"ndv":28,"upper":3.9400,"lower":0.7060,"count":82,"preSum":96},{"ndv":48,"upper":9.3800,"lower":3.9430,"count":86,"preSum":178},{"ndv":67,"upper":21.3700,"lower":9.5000,"count":83,"preSum":264},{"ndv":65,"upper":41.7700,"lower":21.4900,"count":82,"preSum":347},{"ndv":79,"upper":51.6600,"lower":41.7910,"count":82,"preSum":429},{"ndv":55,"upper":76.8800,"lower":51.6900,"count":82,"preSum":511},{"ndv":57,"upper":98.7400,"lower":76.9170,"count":82,"preSum":593},{"ndv":75,"upper":117.7800,"lower":98.8190,"count":82,"preSum":675},{"ndv":73,"upper":156.0300,"lower":117.8300,"count":91,"preSum":757},{"ndv":64,"upper":182.7000,"lower":156.7100,"count":82,"preSum":848},{"ndv":74,"upper":229.7500,"lower":183.1100,"count":82,"preSum":930},{"ndv":75,"upper":289.2800,"lower":229.8900,"count":82,"preSum":1012},{"ndv":77,"upper":321.2100,"lower":289.5400,"count":82,"preSum":1094},{"ndv":82,"upper":365.7000,"lower":321.5300,"count":82,"preSum":1176},{"ndv":67,"upper":408.5100,"lower":365.9000,"count":82,"preSum":1258},{"ndv":67,"upper":454.6100,"lower":412.0900,"count":83,"preSum":1340},{"ndv":82,"upper":525.5800,"lower":455.6000,"count":82,"preSum":1423},{"ndv":82,"upper":628.4200,"lower":527.1500,"count":82,"preSum":1505},{"ndv":66,"upper":690.4900,"lower":628.9100,"count":82,"preSum":1587},{"ndv":82,"upper":748.4300,"lower":691.0800,"count":82,"preSum":1669},{"ndv":76,"upper":845.1100,"lower":748.5300,"count":82,"preSum":1751},{"ndv":82,"upper":908.1100,"lower":847.2600,"count":82,"preSum":1833},{"ndv":80,"upper":1071.2400,"lower":911.4200,"count":82,"preSum":1915},{"ndv":82,"upper":1186.7800,"lower":1072.3700,"count":82,"preSum":1997},{"ndv":67,"upper":1233.4000,"lower":1187.7300,"count":82,"preSum":2079},{"ndv":82,"upper":1304.5300,"lower":1233.9600,"count":82,"preSum":2161},{"ndv":82,"upper":1504.9700,"lower":1305.4500,"count":82,"preSum":2243},{"ndv":81,"upper":1620.3400,"lower":1506.5700,"count":82,"preSum":2325},{"ndv":81,"upper":1904.3100,"lower":1622.1000,"count":82,"preSum":2407},{"ndv":80,"upper":2124.3700,"lower":1910.0600,"count":82,"preSum":2489},{"ndv":82,"upper":2280.6200,"lower":2126.2200,"count":82,"preSum":2571},{"ndv":64,"upper":2476.3000,"lower":2282.0200,"count":82,"preSum":2653},{"ndv":69,"upper":2834.4500,"lower":2477.3000,"count":82,"preSum":2735},{"ndv":71,"upper":3009.6000,"lower":2835.3100,"count":82,"preSum":2817},{"ndv":82,"upper":3231.4500,"lower":3017.1700,"count":82,"preSum":2899},{"ndv":82,"upper":3619.7400,"lower":3232.6900,"count":82,"preSum":2981},{"ndv":82,"upper":3972.0100,"lower":3620.8000,"count":82,"preSum":3063},{"ndv":81,"upper":4266.0400,"lower":3973.7600,"count":82,"preSum":3145},{"ndv":78,"upper":4663.4800,"lower":4267.6300,"count":82,"preSum":3227},{"ndv":81,"upper":5086.2200,"lower":4679.3000,"count":82,"preSum":3309},{"ndv":82,"upper":6335.4400,"lower":5091.6600,"count":82,"preSum":3391},{"ndv":80,"upper":7136.5200,"lower":6392.7800,"count":82,"preSum":3473},{"ndv":81,"upper":7493.8200,"lower":7136.8900,"count":82,"preSum":3555},{"ndv":76,"upper":8050.4800,"lower":7494.7200,"count":83,"preSum":3637},{"ndv":81,"upper":8656.1100,"lower":8072.2100,"count":82,"preSum":3720},{"ndv":82,"upper":9142.1300,"lower":8656.6300,"count":82,"preSum":3802},{"ndv":82,"upper":9866.6700,"lower":9146.6300,"count":82,"preSum":3884},{"ndv":81,"upper":10513.6600,"lower":9871.5100,"count":82,"preSum":3966},{"ndv":81,"upper":11014.5800,"lower":10515.9200,"count":82,"preSum":4048},{"ndv":82,"upper":12137.8000,"lower":11021.8900,"count":82,"preSum":4130},{"ndv":82,"upper":14047.9900,"lower":12151.0000,"count":82,"preSum":4212},{"ndv":82,"upper":17674.7300,"lower":14051.8700,"count":82,"preSum":4294},{"ndv":80,"upper":20858.6100,"lower":17676.9700,"count":82,"preSum":4376},{"ndv":82,"upper":24477.7700,"lower":20955.1300,"count":82,"preSum":4458},{"ndv":71,"upper":32936.4300,"lower":24498.4300,"count":82,"preSum":4540},{"ndv":70,"upper":46408.0900,"lower":33384.9200,"count":82,"preSum":4622},{"ndv":81,"upper":49972.4300,"lower":46554.9200,"count":82,"preSum":4704},{"ndv":82,"upper":59430.7200,"lower":49995.7600,"count":82,"preSum":4786},{"ndv":72,"upper":76496.0300,"lower":59573.8800,"count":82,"preSum":4868},{"ndv":62,"upper":99199.8800,"lower":76560.4000,"count":82,"preSum":4950},{"ndv":76,"upper":168492.9000,"lower":99426.8600,"count":82,"preSum":5032},{"ndv":81,"upper":381649.6400,"lower":168534.1700,"count":82,"preSum":5114},{"ndv":25,"upper":515521.9000,"lower":382110.1000,"count":25,"preSum":5196}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[409,19,19,21,20,22,26,22,26,26],"valueArr":[0.0000,0.7900,1.2800,12.5700,15.0900,283.8100,1104.9700,7304.3300,10878.4100,25104.3900],"type":"Double","sampleRate":0.8511520227425546}',94170,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','prp_v',46960,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":5,"upper":3.7300,"lower":0.9240,"count":5,"preSum":0},{"ndv":5,"upper":4.6560,"lower":3.7500,"count":5,"preSum":5},{"ndv":5,"upper":4.8600,"lower":4.6700,"count":5,"preSum":10},{"ndv":5,"upper":5.0400,"lower":4.8900,"count":5,"preSum":15},{"ndv":4,"upper":5.9310,"lower":5.1000,"count":5,"preSum":20},{"ndv":5,"upper":8.4100,"lower":6.1450,"count":5,"preSum":25},{"ndv":5,"upper":8.4900,"lower":8.4200,"count":5,"preSum":30},{"ndv":5,"upper":8.5600,"lower":8.5000,"count":5,"preSum":35},{"ndv":5,"upper":8.6100,"lower":8.5700,"count":5,"preSum":40},{"ndv":5,"upper":10.3200,"lower":8.6200,"count":5,"preSum":45},{"ndv":5,"upper":10.4200,"lower":10.3300,"count":5,"preSum":50},{"ndv":3,"upper":10.4800,"lower":10.4500,"count":5,"preSum":55},{"ndv":5,"upper":14.0600,"lower":10.5000,"count":5,"preSum":60},{"ndv":4,"upper":14.7600,"lower":14.6700,"count":5,"preSum":65},{"ndv":4,"upper":14.8000,"lower":14.7700,"count":5,"preSum":70},{"ndv":4,"upper":14.8500,"lower":14.8100,"count":5,"preSum":75},{"ndv":5,"upper":20.8200,"lower":17.2400,"count":5,"preSum":80},{"ndv":5,"upper":23.3780,"lower":21.6740,"count":5,"preSum":85},{"ndv":5,"upper":27.4100,"lower":23.7750,"count":5,"preSum":90},{"ndv":5,"upper":32.2600,"lower":27.5340,"count":5,"preSum":95},{"ndv":5,"upper":36.7980,"lower":34.1080,"count":5,"preSum":100},{"ndv":5,"upper":48.1430,"lower":37.2800,"count":5,"preSum":105},{"ndv":3,"upper":48.2000,"lower":48.1700,"count":6,"preSum":110},{"ndv":5,"upper":51.9860,"lower":48.3830,"count":5,"preSum":116},{"ndv":5,"upper":55.2000,"lower":52.5040,"count":5,"preSum":121},{"ndv":5,"upper":55.6300,"lower":55.2600,"count":5,"preSum":126},{"ndv":4,"upper":56.0800,"lower":55.7800,"count":5,"preSum":131},{"ndv":5,"upper":56.5600,"lower":56.1800,"count":5,"preSum":136},{"ndv":4,"upper":56.6400,"lower":56.6100,"count":5,"preSum":141},{"ndv":4,"upper":56.7400,"lower":56.6600,"count":6,"preSum":146},{"ndv":5,"upper":56.8600,"lower":56.7600,"count":5,"preSum":152},{"ndv":5,"upper":57.1200,"lower":56.8900,"count":5,"preSum":157},{"ndv":5,"upper":57.3900,"lower":57.1800,"count":5,"preSum":162},{"ndv":5,"upper":60.8400,"lower":58.3110,"count":5,"preSum":167},{"ndv":5,"upper":73.7260,"lower":64.6520,"count":5,"preSum":172},{"ndv":5,"upper":78.5650,"lower":77.5700,"count":5,"preSum":177},{"ndv":5,"upper":83.7800,"lower":78.6310,"count":5,"preSum":182},{"ndv":5,"upper":87.7100,"lower":84.1500,"count":5,"preSum":187},{"ndv":5,"upper":96.6970,"lower":88.2200,"count":5,"preSum":192},{"ndv":5,"upper":107.7800,"lower":97.5760,"count":5,"preSum":197},{"ndv":5,"upper":159.7600,"lower":155.1200,"count":5,"preSum":202},{"ndv":5,"upper":162.3700,"lower":160.3000,"count":5,"preSum":207},{"ndv":5,"upper":164.4800,"lower":162.8100,"count":5,"preSum":212},{"ndv":5,"upper":206.7100,"lower":164.7500,"count":5,"preSum":217},{"ndv":5,"upper":327.7900,"lower":207.0000,"count":5,"preSum":222},{"ndv":5,"upper":329.1500,"lower":328.1200,"count":5,"preSum":227},{"ndv":5,"upper":330.6000,"lower":329.3300,"count":5,"preSum":232},{"ndv":5,"upper":331.3400,"lower":330.7600,"count":5,"preSum":237},{"ndv":5,"upper":333.2000,"lower":332.6400,"count":5,"preSum":242},{"ndv":5,"upper":389.3500,"lower":387.3400,"count":5,"preSum":247},{"ndv":5,"upper":394.2000,"lower":391.0300,"count":5,"preSum":252},{"ndv":5,"upper":397.3700,"lower":394.8100,"count":5,"preSum":257},{"ndv":5,"upper":570.3200,"lower":397.9700,"count":5,"preSum":262},{"ndv":5,"upper":677.7400,"lower":674.0800,"count":5,"preSum":267},{"ndv":5,"upper":680.4000,"lower":678.1800,"count":5,"preSum":272},{"ndv":5,"upper":682.5500,"lower":680.9500,"count":5,"preSum":277},{"ndv":5,"upper":684.2100,"lower":682.8700,"count":5,"preSum":282},{"ndv":5,"upper":821.6700,"lower":684.8700,"count":5,"preSum":287},{"ndv":5,"upper":828.6300,"lower":822.5400,"count":5,"preSum":292},{"ndv":5,"upper":5838.5700,"lower":829.4300,"count":5,"preSum":297},{"ndv":5,"upper":5853.9100,"lower":5845.8800,"count":5,"preSum":302},{"ndv":5,"upper":5863.2400,"lower":5855.1500,"count":5,"preSum":307},{"ndv":5,"upper":5871.6100,"lower":5864.7800,"count":5,"preSum":312},{"ndv":3,"upper":5877.2600,"lower":5873.6300,"count":3,"preSum":317}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[24,4,3],"valueArr":[0.0000,48.1900,48.2100],"type":"Double","sampleRate":0.8511520227425546}',99650,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','quad_1_r',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}',null,100001,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','quad_2_r',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}',null,100001,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','quad_3_r',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}',null,100001,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','quad_4_r',0,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}',null,100001,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','rrp_b',11249,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":0.5580,"lower":0.3010,"count":2,"preSum":0},{"ndv":2,"upper":4.5250,"lower":4.0250,"count":2,"preSum":2},{"ndv":2,"upper":7.2490,"lower":7.0070,"count":2,"preSum":4},{"ndv":2,"upper":11.7040,"lower":10.9060,"count":2,"preSum":6},{"ndv":2,"upper":13.8060,"lower":13.7230,"count":2,"preSum":8},{"ndv":2,"upper":14.8200,"lower":13.9110,"count":2,"preSum":10},{"ndv":2,"upper":19.1590,"lower":17.3560,"count":2,"preSum":12},{"ndv":2,"upper":22.0730,"lower":19.4060,"count":2,"preSum":14},{"ndv":2,"upper":24.3380,"lower":22.5290,"count":2,"preSum":16},{"ndv":2,"upper":24.6420,"lower":24.4320,"count":2,"preSum":18},{"ndv":2,"upper":27.3190,"lower":24.8930,"count":2,"preSum":20},{"ndv":2,"upper":29.9210,"lower":28.1600,"count":2,"preSum":22},{"ndv":2,"upper":36.0600,"lower":31.0950,"count":2,"preSum":24},{"ndv":2,"upper":41.3620,"lower":39.6860,"count":2,"preSum":26},{"ndv":2,"upper":44.7490,"lower":43.2020,"count":2,"preSum":28},{"ndv":2,"upper":47.3380,"lower":46.2880,"count":2,"preSum":30},{"ndv":2,"upper":47.8690,"lower":47.6670,"count":2,"preSum":32},{"ndv":2,"upper":49.7950,"lower":49.4500,"count":2,"preSum":34},{"ndv":2,"upper":53.5130,"lower":50.4690,"count":2,"preSum":36},{"ndv":2,"upper":55.5300,"lower":55.0180,"count":2,"preSum":38},{"ndv":2,"upper":63.3830,"lower":60.8590,"count":2,"preSum":40},{"ndv":2,"upper":64.5580,"lower":64.5290,"count":2,"preSum":42},{"ndv":2,"upper":69.2400,"lower":66.0510,"count":2,"preSum":44},{"ndv":2,"upper":70.7660,"lower":69.2490,"count":2,"preSum":46},{"ndv":2,"upper":73.0220,"lower":71.5830,"count":2,"preSum":48},{"ndv":2,"upper":77.4800,"lower":77.2220,"count":2,"preSum":50},{"ndv":2,"upper":80.8750,"lower":79.5340,"count":2,"preSum":52},{"ndv":2,"upper":82.9410,"lower":81.9920,"count":2,"preSum":54},{"ndv":2,"upper":87.5790,"lower":84.7600,"count":2,"preSum":56},{"ndv":2,"upper":89.0540,"lower":88.4290,"count":2,"preSum":58},{"ndv":2,"upper":90.4380,"lower":90.2940,"count":2,"preSum":60},{"ndv":2,"upper":91.8980,"lower":90.6070,"count":2,"preSum":62},{"ndv":2,"upper":93.9070,"lower":92.1590,"count":2,"preSum":64},{"ndv":2,"upper":95.5920,"lower":94.7450,"count":2,"preSum":66},{"ndv":2,"upper":96.0650,"lower":95.9690,"count":2,"preSum":68},{"ndv":1,"upper":96.1590,"lower":96.1590,"count":1,"preSum":70}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[180,16,17,3,16,18,10],"valueArr":[0.0000,0.0100,0.0300,0.1200,0.3100,0.4800,1.4700],"type":"Double","sampleRate":0.8511520227425546}',99670,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','rrp_pe',11307,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":1.2040,"lower":0.7850,"count":2,"preSum":0},{"ndv":1,"upper":1.6100,"lower":1.6100,"count":2,"preSum":2},{"ndv":2,"upper":4.3370,"lower":3.1260,"count":2,"preSum":4},{"ndv":2,"upper":12.7770,"lower":6.8530,"count":2,"preSum":6},{"ndv":2,"upper":14.9790,"lower":14.3870,"count":2,"preSum":8},{"ndv":2,"upper":20.6350,"lower":17.8350,"count":2,"preSum":10},{"ndv":2,"upper":23.6290,"lower":23.1380,"count":2,"preSum":12},{"ndv":2,"upper":27.9830,"lower":27.8440,"count":2,"preSum":14},{"ndv":2,"upper":33.8450,"lower":33.0430,"count":2,"preSum":16},{"ndv":2,"upper":35.8530,"lower":35.5430,"count":2,"preSum":18},{"ndv":2,"upper":36.9020,"lower":35.9560,"count":2,"preSum":20},{"ndv":2,"upper":44.2350,"lower":38.7520,"count":2,"preSum":22},{"ndv":2,"upper":47.6070,"lower":45.4730,"count":2,"preSum":24},{"ndv":2,"upper":49.3780,"lower":48.1090,"count":2,"preSum":26},{"ndv":2,"upper":49.9310,"lower":49.8840,"count":2,"preSum":28},{"ndv":2,"upper":50.6290,"lower":50.5380,"count":2,"preSum":30},{"ndv":2,"upper":51.6000,"lower":51.3510,"count":2,"preSum":32},{"ndv":2,"upper":52.0350,"lower":51.9360,"count":2,"preSum":34},{"ndv":2,"upper":53.0320,"lower":52.3210,"count":2,"preSum":36},{"ndv":2,"upper":54.0840,"lower":53.6620,"count":2,"preSum":38},{"ndv":2,"upper":55.1560,"lower":55.1480,"count":2,"preSum":40},{"ndv":2,"upper":55.6640,"lower":55.4370,"count":2,"preSum":42},{"ndv":2,"upper":62.8620,"lower":60.4190,"count":2,"preSum":44},{"ndv":2,"upper":66.3280,"lower":65.7790,"count":2,"preSum":46},{"ndv":2,"upper":69.4010,"lower":68.6360,"count":2,"preSum":48},{"ndv":2,"upper":70.6140,"lower":69.6430,"count":2,"preSum":50},{"ndv":2,"upper":72.1070,"lower":71.5750,"count":2,"preSum":52},{"ndv":2,"upper":76.7020,"lower":76.7010,"count":2,"preSum":54},{"ndv":2,"upper":79.4770,"lower":77.4720,"count":2,"preSum":56},{"ndv":2,"upper":82.7260,"lower":82.5860,"count":2,"preSum":58},{"ndv":2,"upper":85.3190,"lower":84.1880,"count":2,"preSum":60},{"ndv":2,"upper":86.8520,"lower":85.9990,"count":2,"preSum":62},{"ndv":2,"upper":88.2520,"lower":87.5560,"count":2,"preSum":64},{"ndv":2,"upper":90.7850,"lower":90.3270,"count":2,"preSum":66},{"ndv":2,"upper":92.8260,"lower":92.2910,"count":2,"preSum":68},{"ndv":2,"upper":98.1610,"lower":96.5690,"count":2,"preSum":70},{"ndv":1,"upper":99.7710,"lower":99.7710,"count":1,"preSum":72}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[217,16,17,8],"valueArr":[0.0000,0.0100,0.0300,1.6000],"type":"Double","sampleRate":0.8511520227425546}',99670,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','rrp_po',11322,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":1.7190,"lower":0.1000,"count":2,"preSum":0},{"ndv":1,"upper":2.9400,"lower":2.9400,"count":2,"preSum":2},{"ndv":2,"upper":5.1050,"lower":4.0850,"count":2,"preSum":4},{"ndv":2,"upper":5.6830,"lower":5.1980,"count":2,"preSum":6},{"ndv":2,"upper":9.4550,"lower":8.9890,"count":2,"preSum":8},{"ndv":2,"upper":13.2040,"lower":10.1040,"count":2,"preSum":10},{"ndv":2,"upper":17.1530,"lower":15.8640,"count":2,"preSum":12},{"ndv":2,"upper":23.7660,"lower":20.9530,"count":2,"preSum":14},{"ndv":2,"upper":26.5390,"lower":25.1890,"count":2,"preSum":16},{"ndv":2,"upper":28.8080,"lower":27.3260,"count":2,"preSum":18},{"ndv":2,"upper":30.6440,"lower":29.5090,"count":2,"preSum":20},{"ndv":2,"upper":34.3390,"lower":31.2380,"count":2,"preSum":22},{"ndv":2,"upper":35.0050,"lower":34.6300,"count":2,"preSum":24},{"ndv":2,"upper":36.6730,"lower":36.1730,"count":2,"preSum":26},{"ndv":2,"upper":38.2380,"lower":37.9300,"count":2,"preSum":28},{"ndv":2,"upper":41.5130,"lower":39.6310,"count":2,"preSum":30},{"ndv":2,"upper":43.6480,"lower":42.5300,"count":2,"preSum":32},{"ndv":2,"upper":46.3170,"lower":45.5830,"count":2,"preSum":34},{"ndv":2,"upper":48.6310,"lower":46.8470,"count":2,"preSum":36},{"ndv":2,"upper":50.3410,"lower":50.2210,"count":2,"preSum":38},{"ndv":2,"upper":53.8060,"lower":51.7890,"count":2,"preSum":40},{"ndv":2,"upper":57.5230,"lower":55.1020,"count":2,"preSum":42},{"ndv":2,"upper":57.8520,"lower":57.7630,"count":2,"preSum":44},{"ndv":2,"upper":62.8240,"lower":60.5450,"count":2,"preSum":46},{"ndv":2,"upper":66.3260,"lower":63.9860,"count":2,"preSum":48},{"ndv":2,"upper":69.0500,"lower":68.7690,"count":2,"preSum":50},{"ndv":2,"upper":75.3500,"lower":74.7960,"count":2,"preSum":52},{"ndv":2,"upper":77.7050,"lower":76.5210,"count":2,"preSum":54},{"ndv":2,"upper":79.2900,"lower":78.2350,"count":2,"preSum":56},{"ndv":2,"upper":80.4120,"lower":80.1250,"count":2,"preSum":58},{"ndv":2,"upper":81.7120,"lower":80.9520,"count":2,"preSum":60},{"ndv":2,"upper":84.7820,"lower":83.7150,"count":2,"preSum":62},{"ndv":2,"upper":87.9610,"lower":87.5100,"count":2,"preSum":64},{"ndv":2,"upper":90.0900,"lower":88.7820,"count":2,"preSum":66},{"ndv":2,"upper":91.8350,"lower":91.3300,"count":2,"preSum":68},{"ndv":2,"upper":94.3910,"lower":93.0680,"count":2,"preSum":70},{"ndv":2,"upper":97.3750,"lower":95.2430,"count":2,"preSum":72}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[144,35,13,15,3,3,18,18,8],"valueArr":[0.0000,0.0100,0.0200,0.0700,0.1800,0.2200,0.2300,0.2500,2.8600],"type":"Double","sampleRate":0.8511520227425546}',99670,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','rrp_t',73951,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":0.0800,"lower":0.0600,"count":17,"preSum":0},{"ndv":1,"upper":0.0900,"lower":0.0900,"count":14,"preSum":17},{"ndv":2,"upper":0.1200,"lower":0.1000,"count":23,"preSum":31},{"ndv":4,"upper":0.1900,"lower":0.1400,"count":20,"preSum":54},{"ndv":5,"upper":0.2700,"lower":0.2200,"count":13,"preSum":74},{"ndv":2,"upper":0.3200,"lower":0.3150,"count":17,"preSum":87},{"ndv":1,"upper":0.3800,"lower":0.3800,"count":16,"preSum":104},{"ndv":2,"upper":0.4200,"lower":0.4100,"count":16,"preSum":120},{"ndv":3,"upper":0.5000,"lower":0.4300,"count":13,"preSum":136},{"ndv":2,"upper":0.6100,"lower":0.5500,"count":17,"preSum":149},{"ndv":1,"upper":0.6200,"lower":0.6200,"count":15,"preSum":166},{"ndv":3,"upper":0.9300,"lower":0.7400,"count":14,"preSum":181},{"ndv":1,"upper":0.9500,"lower":0.9500,"count":13,"preSum":195},{"ndv":3,"upper":1.0300,"lower":0.9600,"count":20,"preSum":208},{"ndv":2,"upper":1.1700,"lower":1.0500,"count":16,"preSum":228},{"ndv":10,"upper":2.5700,"lower":1.8460,"count":14,"preSum":244},{"ndv":7,"upper":4.9100,"lower":2.6200,"count":13,"preSum":258},{"ndv":5,"upper":9.1340,"lower":5.9300,"count":13,"preSum":271},{"ndv":5,"upper":10.6900,"lower":9.2710,"count":18,"preSum":284},{"ndv":13,"upper":27.9200,"lower":11.3860,"count":13,"preSum":302},{"ndv":13,"upper":46.1650,"lower":27.9790,"count":13,"preSum":315},{"ndv":10,"upper":56.9760,"lower":47.7000,"count":13,"preSum":328},{"ndv":7,"upper":63.1100,"lower":57.0570,"count":13,"preSum":341},{"ndv":11,"upper":72.6400,"lower":63.1210,"count":24,"preSum":354},{"ndv":12,"upper":90.4440,"lower":77.9000,"count":13,"preSum":378},{"ndv":13,"upper":92.6600,"lower":90.5500,"count":13,"preSum":391},{"ndv":12,"upper":99.6500,"lower":93.0000,"count":13,"preSum":404},{"ndv":13,"upper":110.5700,"lower":99.9650,"count":13,"preSum":417},{"ndv":13,"upper":148.7700,"lower":111.1000,"count":13,"preSum":430},{"ndv":8,"upper":178.6200,"lower":149.0700,"count":13,"preSum":443},{"ndv":13,"upper":203.4000,"lower":186.7600,"count":13,"preSum":456},{"ndv":13,"upper":204.8200,"lower":203.4600,"count":13,"preSum":469},{"ndv":13,"upper":215.5300,"lower":205.2900,"count":13,"preSum":482},{"ndv":13,"upper":240.7600,"lower":216.4400,"count":13,"preSum":495},{"ndv":13,"upper":305.3600,"lower":241.0100,"count":13,"preSum":508},{"ndv":13,"upper":320.4500,"lower":308.8500,"count":13,"preSum":521},{"ndv":13,"upper":355.3200,"lower":321.8500,"count":13,"preSum":534},{"ndv":3,"upper":504.9500,"lower":356.6400,"count":13,"preSum":547},{"ndv":13,"upper":540.6700,"lower":510.7400,"count":13,"preSum":560},{"ndv":8,"upper":971.1100,"lower":582.0100,"count":13,"preSum":573},{"ndv":13,"upper":1103.2600,"lower":971.6200,"count":13,"preSum":586},{"ndv":13,"upper":1270.0200,"lower":1106.2100,"count":13,"preSum":599},{"ndv":13,"upper":1303.0700,"lower":1273.0800,"count":13,"preSum":612},{"ndv":13,"upper":2111.6900,"lower":1387.0600,"count":13,"preSum":625},{"ndv":13,"upper":2148.5800,"lower":2114.1500,"count":13,"preSum":638},{"ndv":13,"upper":2934.9800,"lower":2153.5400,"count":13,"preSum":651},{"ndv":13,"upper":3051.5100,"lower":2937.9400,"count":13,"preSum":664},{"ndv":13,"upper":3112.4400,"lower":3066.3600,"count":13,"preSum":677},{"ndv":13,"upper":3645.3000,"lower":3115.5400,"count":13,"preSum":690},{"ndv":13,"upper":3656.6700,"lower":3646.1000,"count":13,"preSum":703},{"ndv":13,"upper":4492.9300,"lower":3656.8200,"count":13,"preSum":716},{"ndv":13,"upper":4848.3600,"lower":4495.3100,"count":13,"preSum":729},{"ndv":13,"upper":4879.4100,"lower":4852.7500,"count":13,"preSum":742},{"ndv":13,"upper":5355.4100,"lower":4881.1300,"count":13,"preSum":755},{"ndv":13,"upper":10439.3600,"lower":5359.7700,"count":13,"preSum":768},{"ndv":13,"upper":10549.6800,"lower":10446.7400,"count":13,"preSum":781},{"ndv":11,"upper":805585.3100,"lower":11469.4900,"count":11,"preSum":794}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[4473,84,68,67,24,29,21,21,25,18,17,24,18,19],"valueArr":[0.0000,0.0100,0.0200,0.0300,0.0400,0.0500,0.0700,0.1100,0.2500,0.4700,0.6500,0.6700,0.7100,3.2700],"type":"Double","sampleRate":0.8511520227425546}',94288,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','rrp_v',11584,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":2,"upper":0.8020,"lower":0.0200,"count":2,"preSum":0},{"ndv":2,"upper":10.3210,"lower":6.8410,"count":2,"preSum":2},{"ndv":2,"upper":13.4610,"lower":12.6620,"count":2,"preSum":4},{"ndv":2,"upper":17.0430,"lower":14.1220,"count":2,"preSum":6},{"ndv":2,"upper":20.1110,"lower":18.7560,"count":2,"preSum":8},{"ndv":2,"upper":24.2290,"lower":20.4030,"count":2,"preSum":10},{"ndv":2,"upper":26.2050,"lower":25.5830,"count":2,"preSum":12},{"ndv":2,"upper":31.8340,"lower":30.5950,"count":2,"preSum":14},{"ndv":2,"upper":32.5940,"lower":32.5680,"count":2,"preSum":16},{"ndv":2,"upper":33.9810,"lower":33.8310,"count":2,"preSum":18},{"ndv":2,"upper":35.4480,"lower":34.1860,"count":2,"preSum":20},{"ndv":2,"upper":35.8750,"lower":35.8110,"count":2,"preSum":22},{"ndv":2,"upper":37.2390,"lower":36.7780,"count":2,"preSum":24},{"ndv":2,"upper":40.2550,"lower":38.3080,"count":2,"preSum":26},{"ndv":2,"upper":45.1890,"lower":41.2390,"count":2,"preSum":28},{"ndv":2,"upper":45.6030,"lower":45.3840,"count":2,"preSum":30},{"ndv":2,"upper":51.1770,"lower":46.6910,"count":2,"preSum":32},{"ndv":2,"upper":53.9570,"lower":52.3070,"count":2,"preSum":34},{"ndv":2,"upper":56.3430,"lower":56.2520,"count":2,"preSum":36},{"ndv":2,"upper":58.5340,"lower":57.6810,"count":2,"preSum":38},{"ndv":2,"upper":59.7200,"lower":59.0350,"count":2,"preSum":40},{"ndv":2,"upper":59.9540,"lower":59.7480,"count":2,"preSum":42},{"ndv":2,"upper":62.6750,"lower":62.5370,"count":2,"preSum":44},{"ndv":2,"upper":64.9710,"lower":64.4770,"count":2,"preSum":46},{"ndv":2,"upper":66.4610,"lower":65.0770,"count":2,"preSum":48},{"ndv":2,"upper":71.5610,"lower":71.0650,"count":2,"preSum":50},{"ndv":2,"upper":74.7950,"lower":72.5400,"count":2,"preSum":52},{"ndv":2,"upper":76.3120,"lower":74.8860,"count":2,"preSum":54},{"ndv":2,"upper":77.7700,"lower":76.4820,"count":2,"preSum":56},{"ndv":2,"upper":80.6040,"lower":78.9270,"count":2,"preSum":58},{"ndv":2,"upper":85.1170,"lower":83.3210,"count":2,"preSum":60},{"ndv":2,"upper":88.2150,"lower":87.6910,"count":2,"preSum":62},{"ndv":2,"upper":92.5000,"lower":90.9950,"count":2,"preSum":64},{"ndv":2,"upper":94.3380,"lower":94.0220,"count":2,"preSum":66},{"ndv":2,"upper":95.6640,"lower":95.5380,"count":2,"preSum":68},{"ndv":2,"upper":99.7660,"lower":97.0460,"count":2,"preSum":70}],"maxBucketSize":64,"type":"Double","sampleRate":0.851152}','{"countArr":[259],"valueArr":[0.0000],"type":"Double","sampleRate":0.8511520227425546}',99670,1.0447812E-4),('gdcams_tp','mk_run_meter_day_energy','run_meter_id',57584,'AAAAAAAAAAAAAAABAAAAAQAAAABdjWq5AAAAAAAAAAA=','{"buckets":[{"ndv":195,"upper":"030200001043843","lower":"030200000194550","count":1564,"preSum":0},{"ndv":142,"upper":"030500000081310","lower":"030200001072605","count":1562,"preSum":1564},{"ndv":197,"upper":"030500000743378","lower":"030500000081617","count":1565,"preSum":3126},{"ndv":111,"upper":"030500001600568","lower":"030500000743759","count":1569,"preSum":4691},{"ndv":198,"upper":"030600000048710","lower":"030500001600640","count":1575,"preSum":6260},{"ndv":112,"upper":"030600000401786","lower":"030600000048941","count":1584,"preSum":7835},{"ndv":84,"upper":"030600000566577","lower":"030600000404042","count":1575,"preSum":9419},{"ndv":89,"upper":"030600000801504","lower":"030600000566622","count":1568,"preSum":10994},{"ndv":88,"upper":"030600001066544","lower":"030600000801508","count":1570,"preSum":12562},{"ndv":135,"upper":"030600001361674","lower":"030600001067678","count":1568,"preSum":14132},{"ndv":111,"upper":"030600001540447","lower":"030600001361951","count":1562,"preSum":15700},{"ndv":135,"upper":"030600001820551","lower":"030600001553697","count":1574,"preSum":17262},{"ndv":86,"upper":"030600002030879","lower":"030600001829647","count":1561,"preSum":18836},{"ndv":108,"upper":"030600002233574","lower":"030600002030957","count":1582,"preSum":20397},{"ndv":120,"upper":"030600002563939","lower":"030600002233615","count":1565,"preSum":21979},{"ndv":181,"upper":"030600003202607","lower":"030600002564018","count":1562,"preSum":23544},{"ndv":176,"upper":"030700000750585","lower":"030600003202896","count":1568,"preSum":25106},{"ndv":158,"upper":"030700001841773","lower":"030700000750999","count":1562,"preSum":26674},{"ndv":143,"upper":"030800000440304","lower":"030700001841942","count":1570,"preSum":28236},{"ndv":159,"upper":"030800001057379","lower":"030800000440412","count":1580,"preSum":29806},{"ndv":113,"upper":"030800001702778","lower":"030800001057568","count":1567,"preSum":31386},{"ndv":155,"upper":"030900000777781","lower":"030800001703986","count":1562,"preSum":32953},{"ndv":187,"upper":"030900001630034","lower":"030900000778021","count":1561,"preSum":34515},{"ndv":183,"upper":"031200002236167","lower":"030900001648470","count":1567,"preSum":36076},{"ndv":134,"upper":"031200002814650","lower":"031200002236800","count":1563,"preSum":37643},{"ndv":172,"upper":"031200003418089","lower":"031200002814817","count":1576,"preSum":39206},{"ndv":186,"upper":"031300000935334","lower":"031200003418481","count":1567,"preSum":40782},{"ndv":173,"upper":"031300001901393","lower":"031300000936545","count":1563,"preSum":42349},{"ndv":148,"upper":"031400000711020","lower":"031300001901536","count":1568,"preSum":43912},{"ndv":130,"upper":"031400001279878","lower":"031400000711553","count":1580,"preSum":45480},{"ndv":154,"upper":"031500000049077","lower":"031400001280368","count":1575,"preSum":47060},{"ndv":133,"upper":"031500000958043","lower":"031500000049207","count":1565,"preSum":48635},{"ndv":189,"upper":"031600000788981","lower":"031500000958198","count":1573,"preSum":50200},{"ndv":163,"upper":"031700000443788","lower":"031600000789295","count":1563,"preSum":51773},{"ndv":256,"upper":"031800000787424","lower":"031700000443826","count":1563,"preSum":53336},{"ndv":186,"upper":"031800001612069","lower":"031800000787982","count":1569,"preSum":54899},{"ndv":146,"upper":"031900000597702","lower":"031800001612364","count":1570,"preSum":56468},{"ndv":195,"upper":"031900001389651","lower":"031900000597820","count":1569,"preSum":58038},{"ndv":192,"upper":"032000000586093","lower":"031900001389700","count":1564,"preSum":59607},{"ndv":232,"upper":"035100000243635","lower":"032000000586118","count":1565,"preSum":61171},{"ndv":157,"upper":"035200000001298","lower":"035100000244279","count":1574,"preSum":62736},{"ndv":181,"upper":"035200000809214","lower":"035200000001481","count":1562,"preSum":64310},{"ndv":172,"upper":"035200001874705","lower":"035200000809230","count":1568,"preSum":65872},{"ndv":190,"upper":"035300000773021","lower":"035200001875768","count":1566,"preSum":67440},{"ndv":132,"upper":"1111111112739444","lower":"035300000773183","count":1561,"preSum":69006},{"ndv":145,"upper":"1111111114479573","lower":"1111111112740721","count":1563,"preSum":70567},{"ndv":178,"upper":"1111111115645075","lower":"1111111114479592","count":1562,"preSum":72130},{"ndv":178,"upper":"1111111116449256","lower":"1111111115645527","count":1563,"preSum":73692},{"ndv":154,"upper":"1111111118011117","lower":"1111111116449643","count":1570,"preSum":75255},{"ndv":203,"upper":"1111111119468205","lower":"1111111118011247","count":1574,"preSum":76825},{"ndv":209,"upper":"1111111120915400","lower":"1111111119468651","count":1578,"preSum":78399},{"ndv":194,"upper":"1111111128591297","lower":"1111111120917750","count":1571,"preSum":79977},{"ndv":132,"upper":"1111111129684821","lower":"1111111128591847","count":1561,"preSum":81548},{"ndv":227,"upper":"1111111132090693","lower":"1111111129684863","count":1565,"preSum":83109},{"ndv":179,"upper":"1111111133677861","lower":"1111111132282542","count":1561,"preSum":84674},{"ndv":141,"upper":"136755092","lower":"1111111133678114","count":1574,"preSum":86235},{"ndv":199,"upper":"1511111141027340","lower":"136814276","count":1576,"preSum":87809},{"ndv":196,"upper":"1511111142382233","lower":"1511111141030777","count":1577,"preSum":89385},{"ndv":164,"upper":"1511111144009490","lower":"1511111142382892","count":1568,"preSum":90962},{"ndv":270,"upper":"189837","lower":"1511111144009542","count":1562,"preSum":92530},{"ndv":211,"upper":"41793252","lower":"19001805","count":1562,"preSum":94092},{"ndv":140,"upper":"58790209","lower":"41793307","count":1561,"preSum":95654},{"ndv":179,"upper":"83067509","lower":"5882426","count":1563,"preSum":97215},{"ndv":105,"upper":"LWK848","lower":"83082339","count":1103,"preSum":98778}],"maxBucketSize":64,"type":"String","sampleRate":0.851152}','{"countArr":[30,30,30,30],"valueArr":["030600001393185","030600001472166","030600001555082","030600001647081"],"type":"String","sampleRate":0.8511520227425546}',0,1.0447812E-4); - DELETE FROM metadb.ndv_sketch_statistics WHERE `SCHEMA_NAME` = 'gdcams_tp' AND `TABLE_NAME` in ('eu_org_rela','mk_cu_elec_cust_mr_comp_view','mk_run_meter_day_energy'); - reload statistics; - set session ENABLE_BKA_JOIN = 'true'; - set session CONN_POOL_XPROTO_XPLAN_TABLE_SCAN = 'false'; - set session ENABLE_MPP = 'true'; - set session ENABLE_AUTO_USE_COLUMNS_PARTITION = 'true'; - set session CONN_POOL_MAX_WAIT_THREAD_COUNT = '0'; - set session CONN_POOL_XPROTO_CONFIG = ''; - set session CONN_POOL_XPROTO_SESSION_AGING_TIME = '600000'; - set session CONN_POOL_XPROTO_PURE_ASYNC_MPP = 'true'; - set session CONN_POOL_XPROTO_MAX_POOLED_SESSION_PER_INST = '1024'; - set session DATABASE_DEFAULT_SINGLE = 'false'; - set session CONN_POOL_XPROTO_MIN_POOLED_SESSION_PER_INST = '32'; - set session CONN_POOL_XPROTO_CHUNK_RESULT = 'true'; - set session ENABLE_SCALE_OUT_FEATURE = 'true'; - set session XPROTO_MAX_DN_WAIT_CONNECTION = '4000'; - set session ENABLE_CDC_META_BUILD_SNAPSHOT = 'true'; - set session CHOOSE_STREAMING = 'true'; - set session MAX_PHYSICAL_PARTITION_COUNT = '8192'; - set session TX_ISOLATION = 'READ-COMMITTED'; - set session AUTO_PARTITION_PARTITIONS = '16'; - set session ENABLE_AUTO_MERGE_INTERVALS_IN_PRUNING = 'true'; - set session CONN_POOL_XPROTO_SLOW_THRESH = '1000'; - set session ALLOW_GROUP_PARALLELISM_WITHOUT_SHARE_READVIEW = 'true'; - set session MAX_IN_SUBQUERY_PRUNING_SIZE = '8192'; - set session CONN_POOL_XPROTO_QUERY_TOKEN = '10000'; - set session GROUP_PARALLELISM = '8'; - set session MPP_RPC_LOCAL_ENABLED = 'true'; - set session CONN_POOL_MAX_POOL_SIZE = '120'; - set session ENABLE_AUTO_USE_RANGE_FOR_TIME_INDEX = 'false'; - set session LOGICAL_DB_TIME_ZONE = 'SYSTEM'; - set session STORAGE_SUPPORTS_BLOOM_FILTER = 'true'; - set session CONN_POOL_PROPERTIES = 'connectTimeout=10000;characterEncoding=utf8;autoReconnect=true;failOverReadOnly=false;socketTimeout=900000;rewriteBatchedStatements=true;useServerPreStmts=false;useSSL=false'; - set session INIT_CONCURRENT_POOL_EVERY_CONNECTION = 'false'; - set session COLLATION_SERVER = 'utf8mb4_general_ci'; - set session MPP_TASK_MAX_RUN_TIME = '3600000'; - set session TRANSACTION_POLICY = 'XA'; - set session SINGLE_GROUP_STORAGE_INST_LIST = 'pxc-xdb-s-pxcunr5ct83vbmm7t010f'; - set session CONN_POOL_XPROTO_MAX_PACKET_SIZE = '268435456'; - set session CONN_POOL_XPROTO_CHECKER = 'true'; - set session XPROTO_MAX_DN_CONCURRENT = '4000'; - set session ENABLE_RUNTIME_FILTER_XXHASH = 'true'; - set session CONN_POOL_XPROTO_MAX_SESSION_PER_CLIENT = '1024'; - set session CONN_POOL_XPROTO_DIRECT_WRITE = 'false'; - set session ENABLE_BKA_PRUNING = 'true'; - set session STATISTIC_COLLECTOR_FROM_RULE = 'true'; - set session CONN_POOL_XPROTO_AUTH = 'true'; - set session USE_FAST_SINGLE_POINT_INTERVAL_MERGING = 'false'; - set session CONN_POOL_BLOCK_TIMEOUT = '20000'; - set session ALLOW_MOVING_BALANCED_SINGLE_TABLE = 'false'; - set session MPP_TABLESCAN_CONNECTION_STRATEGY = '0'; - set session ENABLE_LOWER_CASE_TABLE_NAMES = 'true'; - set session CONN_POOL_IDLE_TIMEOUT = '60'; - set session CONN_POOL_XPROTO_XPLAN_EXPEND_STAR = 'true'; - set session CONN_POOL_XPROTO_STORAGE_DB_PORT = '0'; - set session ENABLE_DDL = 'true'; - set session MAX_PARTITION_COLUMN_COUNT = '5'; - set session DEFAULT_PARTITION_MODE = 'drds'; - set session CONN_POOL_XPROTO_PIPE_BUFFER_SIZE = '268435456'; - set session PROCESS_AUTO_INCREMENT_BY_SEQUENCE = 'true'; - set session ALLOW_SIMPLE_SEQUENCE = 'false'; - set session TRANSACTION_ISOLATION = 'READ-COMMITTED'; - set session CONN_POOL_XPROTO_FEEDBACK = 'true'; - set session SHOW_TABLE_GROUP_NAME = 'false'; - set session ENABLE_CONST_EXPR_EVAL_CACHE = 'true'; - set session CONN_POOL_XPROTO_MESSAGE_TIMESTAMP = 'true'; - set session ENABLE_INTERVAL_ENUMERATION_IN_PRUNING = 'true'; - set session PARTITION_PRUNING_STEP_COUNT_LIMIT = '1024'; - set session CONN_POOL_XPROTO_META_DB_PORT = '0'; - set session ENABLE_HLL = 'false'; - set session ENABLE_MASTER_MPP = 'false'; - set session CONN_POOL_MIN_POOL_SIZE = '2'; - set session ENABLE_ALTER_DDL = 'true'; - set session CONN_POOL_XPROTO_PLAN_CACHE = 'true'; - set session MAX_ENUMERABLE_INTERVAL_LENGTH = '32'; - set session CONN_POOL_XPROTO_MAX_CLIENT_PER_INST = '32'; - set session NET_WRITE_TIMEOUT = '28800'; - set session ENABLE_PARTITIONS_HEATMAP_COLLECTION = 'false'; - set session CONN_POOL_XPROTO_XPLAN = 'true'; - set session ENABLE_SELF_CROSS_JOIN = 'true'; - set session CDC_STARTUP_MODE = '1'; - set session CONN_POOL_XPROTO_TRX_LEAK_CHECK = 'false'; - set session CONN_POOL_XPROTO_FLAG = '0'; - set session ENABLE_START_UP_COST = 'true'; - set session ENABLE_LV_SUBQUERY_UNWRAP = 'false'; - set session RETRY_ERROR_SQL_ON_OLD_SERVER = 'true'; - set session SCALE_OUT_DROP_DATABASE_AFTER_SWITCH_DATASOURCE = 'true'; - set session MAX_LOGICAL_DB_COUNT = '32'; - set session CONN_POOL_XPROTO_AUTO_COMMIT_OPTIMIZE = 'true'; - set session SHOW_HASH_PARTITIONS_BY_RANGE = 'false'; \ No newline at end of file diff --git a/polardbx-test/src/test/resources/statistics/special/intosubquery.yml b/polardbx-test/src/test/resources/statistics/special/intosubquery.yml index b2a8ee1c3..891a254ba 100644 --- a/polardbx-test/src/test/resources/statistics/special/intosubquery.yml +++ b/polardbx-test/src/test/resources/statistics/special/intosubquery.yml @@ -3,56 +3,18 @@ MULTI[10] Catalog:product_identity_service_prod,identity_code_info,status,-2 Action:getFrequency - StatisticValue:1 - ndv small enough to use histogram - Catalog:product_identity_service_prod,identity_code_info,status,-2_-2 - Action:getRangeCount - StatisticValue:1 - (long) (rangeCountInHistogram[0] /sample rate[1.0]) - CACHE_LINE, modify by 2023-11-02 13:22:10 + StatisticValue:634035138 MULTI[10] Catalog:product_identity_service_prod,identity_code_info,del_flag,1 Action:getFrequency StatisticValue:10000 - ndv small enough to use histogram - Catalog:product_identity_service_prod,identity_code_info,del_flag,1_1 - Action:getRangeCount - StatisticValue:10000 - (long) (rangeCountInHistogram[10000] /sample rate[1.0]) - CACHE_LINE, modify by 2023-11-02 13:22:10 MULTI[3] Catalog:product_identity_service_prod,identity_code_info,status,1-1-2 Action:getFrequency - StatisticValue:10002 - sum - HISTOGRAM, modify by 1970-01-01 07:59:59 - Catalog:product_identity_service_prod,identity_code_info,status,1 - StatisticValue:10000 - ndv small enough to use histogram - Catalog:product_identity_service_prod,identity_code_info,status,1_1 - Action:getRangeCount - StatisticValue:10000 - (long) (rangeCountInHistogram[10000] /sample rate[1.0]) - CACHE_LINE, modify by 2023-11-02 13:22:10 - Catalog:product_identity_service_prod,identity_code_info,status,-1 - StatisticValue:1 - ndv small enough to use histogram - Catalog:product_identity_service_prod,identity_code_info,status,-1_-1 - Action:getRangeCount - StatisticValue:1 - (long) (rangeCountInHistogram[0] /sample rate[1.0]) - CACHE_LINE, modify by 2023-11-02 13:22:10 - Catalog:product_identity_service_prod,identity_code_info,status,-2 - StatisticValue:1 - ndv small enough to use histogram - Catalog:product_identity_service_prod,identity_code_info,status,-2_-2 - Action:getRangeCount - StatisticValue:1 - (long) (rangeCountInHistogram[0] /sample rate[1.0]) - CACHE_LINE, modify by 2023-11-02 13:22:10 - + StatisticValue:1268080276 + MULTI[4] Catalog:product_identity_service_prod,identity_code_info Action:getRowCount @@ -62,50 +24,22 @@ MULTI[10] Catalog:product_identity_service_prod,identity_code_info,status,-1 Action:getFrequency - StatisticValue:1 - ndv small enough to use histogram - Catalog:product_identity_service_prod,identity_code_info,status,-1_-1 - Action:getRangeCount - StatisticValue:1 - (long) (rangeCountInHistogram[0] /sample rate[1.0]) - CACHE_LINE, modify by 2023-11-02 13:22:10 - - MULTI[6] - Catalog:product_identity_service_prod,identity_code_info,status - Action:getCardinality - StatisticValue:1 - CACHE_LINE, modify by 2023-11-02 13:22:10 - - MULTI[7] - Catalog:product_identity_service_prod,identity_code_info,identity_code - Action:getCardinality - StatisticValue:24779 - CACHE_LINE, modify by 2023-11-02 13:22:10 + StatisticValue:634035138 MULTI[10] Catalog:product_identity_service_prod,identity_code_info,status,1 Action:getFrequency StatisticValue:10000 - ndv small enough to use histogram - Catalog:product_identity_service_prod,identity_code_info,status,1_1 - Action:getRangeCount - StatisticValue:10000 - (long) (rangeCountInHistogram[10000] /sample rate[1.0]) - CACHE_LINE, modify by 2023-11-02 13:22:10 - Catalog:product_identity_service_prod,identity_code_info,del_flag + Catalog:product_identity_service_prod,identity_code_info,status Action:getCardinality StatisticValue:1 SQL: | - SELECT id,identity_code,identity_code_md5,sku_code,verify_num,verify_last_time,status,batch_num,operation_log_id,del_flag,version,last_operator,last_operator_id,update_time,creator,creator_id,created_time FROM identity_code_info WHERE del_flag=1 AND identity_code IN ('40/JxLg763EFYOx80h7Up79AhsWpYMDTcwp3BqxEFg0=','putUsbowaef+cV5wiFfhsvjZ1+Rrfe6HcOm0Qyyw8cA=','OYk1Z51Pi5KzfE01SkUJWXBGQ4eeWqvhb0Y1RvNi6BQ=','Si3A9PeQuuTRkRVPnxWGmODkWHHxMmTh71zKjeLd1U0=','O5RNkdAwdtdei5li/zaZRyKUC7SawUbwpePfTcbErFc=','jmbw0+WWooHKIQeJ7Lb3QXMexx/0z3KffM53Rcre/yA=','pVyVRrYhheN9KZZsM+Qdx7z2biBvNWwfZjIV/JBVXM4=','yvRnEu1ArrS/+U3F2WWJS2s8jon+Pqh91kTtS7IFJ8k=','HTRdHC4fYA3Csc3Vm/DD0KNyudr5RAiNbOQkdToeSXM=','UiH/6Sigtl73IZtMU+olPiJN8wU7NvqxV6tIKz+2vZw=','wqd/oSNR9+Keg2ZocPnHpd41xWZ0jKzoXHzRQ5FJaHw=','64cm5ojpCvR4rJ+og4YS2zHbsHYDKobDNII1SBuSh/c=') AND status IN (1,-1,-2) + /*TDDL:IN_SUB_QUERY_THRESHOLD=1000*/SELECT id,identity_code,identity_code_md5,sku_code,verify_num,verify_last_time,status,batch_num,operation_log_id,del_flag,version,last_operator,last_operator_id,update_time,creator,creator_id,created_time FROM identity_code_info WHERE del_flag=1 AND identity_code IN ('40/JxLg763EFYOx80h7Up79AhsWpYMDTcwp3BqxEFg0=','putUsbowaef+cV5wiFfhsvjZ1+Rrfe6HcOm0Qyyw8cA=','OYk1Z51Pi5KzfE01SkUJWXBGQ4eeWqvhb0Y1RvNi6BQ=','Si3A9PeQuuTRkRVPnxWGmODkWHHxMmTh71zKjeLd1U0=','O5RNkdAwdtdei5li/zaZRyKUC7SawUbwpePfTcbErFc=','jmbw0+WWooHKIQeJ7Lb3QXMexx/0z3KffM53Rcre/yA=','pVyVRrYhheN9KZZsM+Qdx7z2biBvNWwfZjIV/JBVXM4=','yvRnEu1ArrS/+U3F2WWJS2s8jon+Pqh91kTtS7IFJ8k=','HTRdHC4fYA3Csc3Vm/DD0KNyudr5RAiNbOQkdToeSXM=','UiH/6Sigtl73IZtMU+olPiJN8wU7NvqxV6tIKz+2vZw=','wqd/oSNR9+Keg2ZocPnHpd41xWZ0jKzoXHzRQ5FJaHw=','64cm5ojpCvR4rJ+og4YS2zHbsHYDKobDNII1SBuSh/c=') AND status IN (1,-1,-2) PLAN: | - PhysicalProject - BKAJoin - HashAgg - LogicalDynamicValues - Gather - LogicalView(tableNames=[[identity_code_info]]) + Gather + LogicalView(tableNames=[[identity_code_info]]) CATALOG: | set global AUTO_PARTITION_PARTITIONS = '16'; diff --git a/polardbx-transaction/pom.xml b/polardbx-transaction/pom.xml index ed86e7b5b..1dbdfcb41 100644 --- a/polardbx-transaction/pom.xml +++ b/polardbx-transaction/pom.xml @@ -31,7 +31,6 @@ org.mockito mockito-inline - ${mockito.verison} test diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/ColumnarTsoManager.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/ColumnarTsoManager.java index dad367f37..f0da8dbb8 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/ColumnarTsoManager.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/ColumnarTsoManager.java @@ -143,4 +143,15 @@ public synchronized void resetColumnarTsoUpdateInterval(int intervalMs) { } } + + @Override + protected void doDestroy() { + if (columnarTsoUpdateTaskExecutor != null) { + columnarTsoUpdateTaskExecutor.shutdown(); + } + + if (columnarTsoPurgeTaskExecutor != null) { + columnarTsoPurgeTaskExecutor.shutdown(); + } + } } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/DeadlockManager.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/DeadlockManager.java new file mode 100644 index 000000000..8c4684091 --- /dev/null +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/DeadlockManager.java @@ -0,0 +1,110 @@ +package com.alibaba.polardbx.transaction; + +import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.executor.utils.transaction.DeadlockParser; +import com.alibaba.polardbx.gms.metadb.trx.DeadlocksAccessor; +import com.alibaba.polardbx.gms.topology.DbTopologyManager; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; +import java.util.concurrent.atomic.AtomicReference; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.alibaba.polardbx.executor.handler.LogicalShowLocalDeadlocksHandler.SHOW_ENGINE_INNODB_STATUS; +import static com.alibaba.polardbx.gms.topology.SystemDbHelper.DEFAULT_DB_NAME; + +public class DeadlockManager { + protected static final Logger logger = LoggerFactory.getLogger(DeadlockManager.class); + private static final Object MONITOR = new Object(); + private static final AtomicReference LOCAL_DEADLOCK = new AtomicReference<>(null); + private static final Pattern PATTERN = + Pattern.compile(".*Error occurs when execute on GROUP .* ATOM '(.*?)#(.*?)#.*'"); + + static { + try { + (new Thread(() -> { + try { + while (true) { + synchronized (MONITOR) { + MONITOR.wait(1000 * 60 * 10); + } + if (null != LOCAL_DEADLOCK.get()) { + // Record local deadlock into meta db. + recordLocalDeadlock(); + LOCAL_DEADLOCK.set(null); + } + // Clean deadlock logs if necessary. + cleanDeadlockLogs(); + } + } catch (Throwable t) { + logger.error("deadlock recorder failed, exit.", t); + } + }, "Deadlock-Log-Recorder")).start(); + } catch (Throwable t) { + logger.error("init deadlock recorder failed.", t); + } + } + + private static void cleanDeadlockLogs() { + if (!ExecUtils.hasLeadership(DEFAULT_DB_NAME)) { + return; + } + try (Connection connection = MetaDbUtil.getConnection()) { + DeadlocksAccessor deadlocksAccessor = new DeadlocksAccessor(); + deadlocksAccessor.setConnection(connection); + deadlocksAccessor.rotate(); + } catch (Exception e) { + logger.error("record local deadlock failed.", e); + } + } + + protected static void recordLocalDeadlock() { + Matcher matcher = PATTERN.matcher(LOCAL_DEADLOCK.get()); + if (matcher.find()) { + // Only fetch this dn. + String dn = matcher.group(2); + try (Connection conn = DbTopologyManager.getConnectionForStorage(dn); + Statement stmt = conn.createStatement()) { + final ResultSet rs = stmt.executeQuery(SHOW_ENGINE_INNODB_STATUS); + if (rs.next()) { + final String status = rs.getString("Status"); + if (null != status) { + // Parse the {status} to get deadlock information, + final String deadlockLog = DeadlockParser.parseLocalDeadlock(status); + try (Connection connection = MetaDbUtil.getConnection()) { + DeadlocksAccessor deadlocksAccessor = new DeadlocksAccessor(); + deadlocksAccessor.setConnection(connection); + deadlocksAccessor.recordDeadlock(dn, "LOCAL", deadlockLog); + } catch (Exception e) { + logger.error("record local deadlock failed.", e); + } + } + } + } catch (Exception e) { + throw new RuntimeException( + "Failed to fetch deadlock information on dn " + dn, e); + } + } + } + + private static final DeadlockManager INSTANCE = new DeadlockManager(); + + public static DeadlockManager getInstance() { + return INSTANCE; + } + + public static void recordLocalDeadlock(String errMsg) { + LOCAL_DEADLOCK.set(errMsg); + synchronized (MONITOR) { + MONITOR.notify(); + } + } + + private DeadlockManager() { + } +} diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/TransactionManager.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/TransactionManager.java index 4e69c6b30..dcc9af738 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/TransactionManager.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/TransactionManager.java @@ -44,6 +44,7 @@ import com.alibaba.polardbx.transaction.async.AsyncTaskQueue; import com.alibaba.polardbx.transaction.async.DeadlockDetectionTaskWrapper; import com.alibaba.polardbx.transaction.async.RotateGlobalTxLogTaskWrapper; +import com.alibaba.polardbx.transaction.async.SyncPointTaskWrapper; import com.alibaba.polardbx.transaction.async.TransactionIdleTimeoutTaskWrapper; import com.alibaba.polardbx.transaction.async.TransactionStatisticsTaskWrapper; import com.alibaba.polardbx.transaction.log.GlobalTxLogManager; @@ -56,8 +57,10 @@ import com.alibaba.polardbx.transaction.trx.BestEffortTransaction; import com.alibaba.polardbx.transaction.trx.CobarStyleTransaction; import com.alibaba.polardbx.transaction.trx.ITsoTransaction; +import com.alibaba.polardbx.transaction.trx.IgnoreBinlogTransaction; import com.alibaba.polardbx.transaction.trx.MppReadOnlyTransaction; import com.alibaba.polardbx.transaction.trx.ReadOnlyTsoTransaction; +import com.alibaba.polardbx.transaction.trx.SyncPointTransaction; import com.alibaba.polardbx.transaction.trx.TsoTransaction; import com.alibaba.polardbx.transaction.trx.XATransaction; import com.alibaba.polardbx.transaction.trx.XATsoTransaction; @@ -117,7 +120,9 @@ public class TransactionManager extends AbstractLifecycle implements ITransactio private static TransactionIdleTimeoutTaskWrapper transactionIdleTimeoutTask; - private TimerTask mdlDeadlockDetectionTask; + private static SyncPointTaskWrapper syncPointTask; + + private static TimerTask mdlDeadlockDetectionTask; private TimerTask killTimeoutTransactionTask; // Since heartbeat task must run on PolarDB-X instances, only one task is need @@ -172,9 +177,7 @@ protected void doInit() { } // Schedule timer tasks. - scheduleDeadlockDetectionTask(); - scheduleTransactionStatisticsTask(); - scheduleTransactionIdleTimeoutTask(); + scheduleTimerTask(); } public static TransactionManager getInstance(String schema) { @@ -250,15 +253,17 @@ public ITransaction createTransaction(TransactionClass trxConfig, ExecutionConte case XA: // 如果启用了 DRDS XA 事务,定期检查 XA RECOVER enableXaRecoverScan(); - if (storageManager.isSupportMarkDistributed() && executionContext.isEnableXaTso()) { + if ((supportXaTso() || InstanceVersion.isMYSQL80()) + && executionContext.isEnableXaTso()) { trx = new XATsoTransaction(executionContext, this); } else { trx = new XATransaction(executionContext, this); } break; case TSO: - enableXaRecoverScan(); - if (executionContext.enableAsyncCommit() && supportAsyncCommit()) { + if (storageManager.isSupportSyncPoint() && executionContext.isMarkSyncPoint()) { + trx = new SyncPointTransaction(executionContext, this); + } else if (executionContext.enableAsyncCommit() && supportAsyncCommit()) { trx = new AsyncCommitTransaction(executionContext, this); } else { trx = new TsoTransaction(executionContext, this); @@ -297,12 +302,12 @@ public ITransaction createTransaction(TransactionClass trxConfig, ExecutionConte case ARCHIVE: trx = new ArchiveTransaction(executionContext, this); break; + case IGNORE_BINLOG_TRANSACTION: + trx = new IgnoreBinlogTransaction(executionContext, this); + break; default: throw new AssertionError("TransactionType: " + trxConfig.name() + " not supported"); } - enableKillTimeoutTransaction(); - // Schedule log cleaning task. - enableLogCleanTask(); // 配置会在执行器里设置 return trx; @@ -375,7 +380,7 @@ private void scheduleTransactionIdleTimeoutTask() { new TransactionIdleTimeoutTaskWrapper(properties, executor.getAsyncQueue()); } catch (Throwable t) { transactionIdleTimeoutTask = null; - TransactionLogger.warn("Failed to init deadlock detection task."); + TransactionLogger.warn("Failed to init transaction idle timeout task."); } } } @@ -398,6 +403,21 @@ public void scheduleTransactionStatisticsTask() { } } + public void scheduleSyncPointTask() { + if (null == syncPointTask) { + synchronized (TransactionManager.class) { + if (null == syncPointTask) { + try { + syncPointTask = new SyncPointTaskWrapper(properties, executor.getAsyncQueue()); + } catch (Throwable t) { + syncPointTask = null; + TransactionLogger.warn("Failed to init sync point task."); + } + } + } + } + } + public void enableXaRecoverScan() { // stop xa schedule work if (!ConfigDataMode.needDNResource() || SystemDbHelper.isDBBuildInExceptCdc(schemaName)) { @@ -449,7 +469,7 @@ void enableMdlDeadlockDetection() { return; } if (mdlDeadlockDetectionTask == null) { - synchronized (this) { + synchronized (TransactionManager.class) { if (mdlDeadlockDetectionTask == null) { AsyncTaskQueue asyncQueue = executor.getAsyncQueue(); @@ -457,8 +477,11 @@ void enableMdlDeadlockDetection() { 5 * paramManager.getInt(ConnectionParams.DEADLOCK_DETECTION_INTERVAL); // reuse this variable int mdlWaitTimeoutInSec = paramManager.getInt(ConnectionParams.PHYSICAL_DDL_MDL_WAITING_TIMEOUT); // reuse this variable + // keySet is a shadow copy of schemaMap's key, which can refer to comment keySet + // So if any schema removed or added, they will be mapped into mdlDeadlockDetectionTask mdlDeadlockDetectionTask = - asyncQueue.scheduleMdlDeadlockDetectionTask(executor, interval, mdlWaitTimeoutInSec); + asyncQueue.scheduleMdlDeadlockDetectionTask(executor, interval, schemaMap.keySet(), + mdlWaitTimeoutInSec); } } } @@ -663,6 +686,12 @@ public void resetAllTimerTasks() { } else { transactionIdleTimeoutTask.resetTask(); } + + if (null == syncPointTask) { + scheduleSyncPointTask(); + } else { + syncPointTask.resetTask(); + } } } @@ -688,10 +717,6 @@ public boolean supportAsyncCommit() { return storageManager.supportAsyncCommit(); } - @Override - public boolean support2pcOpt() { - return storageManager.support2pcOpt(); - } public static boolean isExceedAsyncCommitTaskLimit() { return asyncCommitTasks.get() >= InstConfUtil.getInt(ConnectionParams.ASYNC_COMMIT_TASK_LIMIT); @@ -717,4 +742,19 @@ public static void turnOffAutoSavepointOpt() throws SQLException { MetaDbUtil.setGlobal(properties); } + @Override + public void scheduleTimerTask() { + enableXaRecoverScan(); + enableKillTimeoutTransaction(); + enableLogCleanTask(); + scheduleDeadlockDetectionTask(); + scheduleTransactionStatisticsTask(); + scheduleTransactionIdleTimeoutTask(); + scheduleSyncPointTask(); + } + + @Override + public boolean supportXaTso() { + return storageManager.isSupportMarkDistributed(); + } } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/AsyncTaskQueue.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/AsyncTaskQueue.java index 3646fc639..fb6b6cf9b 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/AsyncTaskQueue.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/AsyncTaskQueue.java @@ -30,6 +30,7 @@ import com.alibaba.polardbx.transaction.TransactionLogger; import com.alibaba.polardbx.transaction.log.GlobalTxLogManager; +import java.util.Collection; import java.util.Map; import java.util.Timer; import java.util.TimerTask; @@ -70,7 +71,7 @@ public TimerTask scheduleXARecoverTask(TransactionExecutor te, int interval, boo @Override public void run() { if (!task.schedule()) { - logger.warn("Ignore re-submit XA recover task"); + logger.debug("Ignore re-submit XA recover task"); return; } @@ -140,7 +141,7 @@ public TimerTask scheduleDeadlockDetectionTask(final int interval, final Runnabl @Override public void run() { if (!task.schedule()) { - logger.warn("Ignore re-submit deadlock detection task"); + logger.debug("Ignore re-submit deadlock detection task"); return; } @@ -172,12 +173,7 @@ public boolean cancel() { timer.scheduleAtFixedRate(timerTask, 0, interval); TransactionLogger.warn(schema + ": Scheduled deadlock detection task."); - EventLogger.log(EventType.DEAD_LOCK_DETECTION, String.format( - "Deadlock detection task for schema:%s is online", - schema - )); - - EventLogger.log(EventType.DEAD_LOCK_DETECTION, String.format( + EventLogger.log(EventType.TRX_INFO, String.format( "Deadlock detection task for schema:%s is online", schema )); @@ -209,7 +205,7 @@ public void run() { timer.scheduleAtFixedRate(timerTask, 0, intervalInMs); TransactionLogger.warn("Scheduled kill timeout transaction task"); - EventLogger.log(EventType.DEAD_LOCK_DETECTION, String.format( + EventLogger.log(EventType.TRX_INFO, String.format( "Kill timeout transaction task for schema:%s is online", schema )); @@ -218,8 +214,9 @@ public void run() { } public TimerTask scheduleMdlDeadlockDetectionTask(TransactionExecutor te, int intervalInMs, + Collection allSchema, int mdlWaitTimeoutInSec) { - final MdlDeadlockDetectionTask detectTask = new MdlDeadlockDetectionTask(schema, te, mdlWaitTimeoutInSec); + final MdlDeadlockDetectionTask detectTask = new MdlDeadlockDetectionTask(schema, allSchema, te, mdlWaitTimeoutInSec); final ScheduleAsyncTask task = ScheduleAsyncTask.build(detectTask); TimerTask timerTask = new TimerTask() { @@ -242,7 +239,7 @@ public void run() { timer.scheduleAtFixedRate(timerTask, 0, intervalInMs); TransactionLogger.warn("Scheduled MDL deadlock detection task"); - EventLogger.log(EventType.DEAD_LOCK_DETECTION, String.format( + EventLogger.log(EventType.TRX_INFO, String.format( "MDL Deadlock detection task for schema:%s is online", schema )); @@ -379,6 +376,50 @@ public boolean cancel() { return timerTask; } + public TimerTask scheduleSyncPointTask(final long interval, final Runnable rawTask) { + final ScheduleAsyncTask task = ScheduleAsyncTask.build(rawTask); + + final TimerTask timerTask = new TimerTask() { + + @Override + public void run() { + if (!task.schedule()) { + logger.warn("Ignore re-submit sync point task"); + return; + } + + try { + executor.submit(schema, null, task); + } catch (Throwable e) { + task.cancel(); + logger.error("Submit sync point task failed", e); + } + } + + @Override + public boolean cancel() { + try { + // Cancel the async task in case that + // it is already submitted but not yet executed. + task.cancel(); + } catch (Throwable t) { + // Ignore. + logger.error("Cancel transaction statistics task failed", t); + } + final boolean returnVal = super.cancel(); + // Release space of cancelled timer task. + timer.purge(); + return returnVal; + } + }; + + timer.scheduleAtFixedRate(timerTask, 0, interval); + + TransactionLogger.info(schema + ": Scheduled sync point task."); + + return timerTask; + } + public TimerTask scheduleTransactionIdleTimeoutTask(final int interval, final Runnable rawTask) { final ScheduleAsyncTask task = ScheduleAsyncTask.build(rawTask); diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/DeadlockDetectionTask.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/DeadlockDetectionTask.java index 58727b5bb..0bb2f8ea0 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/DeadlockDetectionTask.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/DeadlockDetectionTask.java @@ -20,27 +20,34 @@ import com.alibaba.polardbx.common.eventlogger.EventType; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.mock.MockStatus; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.executor.common.StorageInfoManager; import com.alibaba.polardbx.executor.sync.ISyncAction; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.executor.utils.transaction.DeadlockParser; -import com.alibaba.polardbx.executor.utils.transaction.GroupConnPair; import com.alibaba.polardbx.executor.utils.transaction.LocalTransaction; +import com.alibaba.polardbx.executor.utils.transaction.TransactionUtils; import com.alibaba.polardbx.executor.utils.transaction.TrxLock; import com.alibaba.polardbx.executor.utils.transaction.TrxLookupSet; import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.metadb.trx.DeadlocksAccessor; import com.alibaba.polardbx.gms.sync.SyncScope; import com.alibaba.polardbx.gms.topology.DbTopologyManager; +import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.transaction.TransactionLogger; +import com.alibaba.polardbx.transaction.log.GlobalTxLogManager; import com.alibaba.polardbx.transaction.sync.FetchTransForDeadlockDetectionSyncAction; import com.alibaba.polardbx.transaction.utils.DiGraph; +import lombok.Data; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Triple; @@ -49,11 +56,15 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; import static com.alibaba.polardbx.gms.topology.SystemDbHelper.DEFAULT_DB_NAME; @@ -68,58 +79,49 @@ public class DeadlockDetectionTask implements Runnable { private static final Logger logger = LoggerFactory.getLogger(DeadlockDetectionTask.class); - private static final String SQL_QUERY_DEADLOCKS_80 = + /** + * Query all unique lock and how many trx are waiting for them respectively. + */ + protected static final String SQL_QUERY_HOTSPOT_LOCK = "SELECT " - /* Transaction information of waiting transaction. */ - + "trx_a.TRX_MYSQL_THREAD_ID AS waiting_conn_id, " - + "trx_a.TRX_STATE AS waiting_state, " - + "trx_a.TRX_QUERY AS waiting_physical_sql, " - + "trx_a.TRX_OPERATION_STATE AS waiting_operation_state, " - + "trx_a.TRX_TABLES_IN_USE AS waiting_tables_in_use, " - + "trx_a.TRX_TABLES_LOCKED AS waiting_tables_locked, " - + "trx_a.TRX_LOCK_STRUCTS AS waiting_lock_structs, " - + "trx_a.TRX_LOCK_MEMORY_BYTES AS waiting_heap_size, " - + "trx_a.TRX_ROWS_LOCKED AS waiting_row_locks, " - /* Lock information of waiting transaction. */ - + "locks_a.ENGINE_LOCK_ID AS waiting_lock_id, " - + "locks_a.LOCK_MODE AS waiting_lock_mode, " - + "locks_a.LOCK_TYPE AS waiting_lock_type, " - + "locks_a.OBJECT_NAME AS waiting_lock_physical_table, " - + "locks_a.INDEX_NAME AS waiting_lock_index, " - + "locks_a.LOCK_DATA AS waiting_lock_data, " - /* Transaction information of blocking transaction. */ - + "trx_b.TRX_MYSQL_THREAD_ID AS blocking_conn_id, " - + "trx_b.TRX_STATE AS blocking_state, " - + "trx_b.TRX_QUERY AS blocking_physical_sql, " - + "trx_b.TRX_OPERATION_STATE AS blocking_operation_state, " - + "trx_b.TRX_TABLES_IN_USE AS blocking_tables_in_use, " - + "trx_b.TRX_TABLES_LOCKED AS blocking_tables_locked, " - + "trx_b.TRX_LOCK_STRUCTS AS blocking_lock_structs, " - + "trx_b.TRX_LOCK_MEMORY_BYTES AS blocking_heap_size, " - + "trx_b.TRX_ROWS_LOCKED AS blocking_row_locks, " - /* Lock information of blocking transaction. */ - + "locks_b.ENGINE_LOCK_ID AS blocking_lock_id, " - + "locks_b.LOCK_MODE AS blocking_lock_mode, " - + "locks_b.LOCK_TYPE AS blocking_lock_type, " - + "locks_b.OBJECT_NAME AS blocking_lock_physical_table, " - + "locks_b.INDEX_NAME AS blocking_lock_index, " - + "locks_b.LOCK_DATA AS blocking_lock_data " + + "COUNT(0) AS cnt, SUBSTRING_INDEX(TRX_REQUESTED_LOCK_ID, ':', -3) AS lock_id " + + "FROM INFORMATION_SCHEMA.innodb_trx " + + "GROUP BY lock_id"; + + protected static final String SQL_QUERY_HOTSPOT_LOCK_80 = + "SELECT " + + "COUNT(0) AS cnt, SUBSTRING_INDEX(SUBSTRING_INDEX(TRX_REQUESTED_LOCK_ID, ':', -4), ':', 3) AS lock_id " + + "FROM INFORMATION_SCHEMA.innodb_trx " + + "GROUP BY lock_id"; + + /** + * Query all local trx, including waiting and blocking trx. + */ + protected static final String SQL_QUERY_TRX_80 = + "SELECT " + + "TRX_ID AS trx_id, " + + "TRX_MYSQL_THREAD_ID AS conn_id, " + + "TRX_STATE AS state, " + + "TRX_QUERY AS physical_sql, " + + "TRX_OPERATION_STATE AS operation_state, " + + "TRX_TABLES_IN_USE AS tables_in_use, " + + "TRX_TABLES_LOCKED AS tables_locked, " + + "TRX_LOCK_STRUCTS AS lock_structs, " + + "TRX_LOCK_MEMORY_BYTES AS heap_size, " + + "TRX_ROWS_LOCKED AS row_locks " + + "FROM information_schema.INNODB_TRX "; + + /** + * Query all blocking and waiting trx. + */ + protected static final String SQL_QUERY_LOCK_WAITS_80 = + "SELECT " + + "REQUESTING_ENGINE_TRANSACTION_ID AS waiting_trx_id, " + + "BLOCKING_ENGINE_TRANSACTION_ID AS blocking_trx_id " + "FROM " - + "performance_schema.DATA_LOCK_WAITS AS lock_waits, " - /* trx_a requesting locks_a, is blocked by trx_b holding locks_b */ - + "performance_schema.DATA_LOCKS AS locks_a, performance_schema.DATA_LOCKS AS locks_b, " - + "information_schema.INNODB_TRX AS trx_a, information_schema.INNODB_TRX AS trx_b " - + "WHERE " - /* Filter the non-direct-blocking trx. Trx which is waiting a lock should not block others. */ - + "trx_b.trx_state != 'LOCK WAIT' " - + "AND " - /* Join innodb_trx to get the trx information. */ - + "trx_a.trx_id = lock_waits.REQUESTING_ENGINE_TRANSACTION_ID AND trx_b.trx_id = lock_waits.BLOCKING_ENGINE_TRANSACTION_ID " - + "AND " - /* Join innodb_locks to get the lock information. */ - + "lock_waits.REQUESTING_ENGINE_LOCK_ID = locks_a.ENGINE_LOCK_ID AND lock_waits.BLOCKING_ENGINE_LOCK_ID = locks_b.ENGINE_LOCK_ID"; + + "performance_schema.DATA_LOCK_WAITS AS lock_waits "; - private static final String SQL_QUERY_DEADLOCKS = + protected static final String SQL_QUERY_DEADLOCKS = "SELECT " /* Transaction information of waiting transaction. */ + "trx_a.TRX_MYSQL_THREAD_ID AS waiting_conn_id, " @@ -176,14 +178,19 @@ public class DeadlockDetectionTask implements Runnable { /* Join innodb_locks to get the lock information. */ + "lock_waits.requested_lock_id = locks_a.lock_id AND lock_waits.blocking_lock_id = locks_b.lock_id"; + private static final AtomicLong SKIP = new AtomicLong(0L); private final Collection allSchemas; private static Class killSyncActionClass; static { // 只有server支持 try { - killSyncActionClass = - Class.forName("com.alibaba.polardbx.server.response.KillSyncAction"); + if (MockStatus.isMock()) { + killSyncActionClass = null; + } else { + killSyncActionClass = + Class.forName("com.alibaba.polardbx.server.response.KillSyncAction"); + } } catch (ClassNotFoundException e) { throw new TddlRuntimeException(ErrorCode.ERR_CONFIG, e, e.getMessage()); } @@ -201,28 +208,114 @@ public DeadlockDetectionTask(Collection allSchemas) { * @param lookupSet a transaction lookup set which contains all transactions * @param graph a wait-for graph containing "trx a is waiting for trx b"-like information */ - public void fetchLockWaits(TGroupDataSource dataSource, - Collection groupNames, - TrxLookupSet lookupSet, - DiGraph graph) { - boolean isMySQL80 = ExecUtils.isMysql80Version(); - String deadLocksSql = isMySQL80 ? SQL_QUERY_DEADLOCKS_80 : SQL_QUERY_DEADLOCKS; + protected void fetchLockWaits(TGroupDataSource dataSource, + Collection groupNames, + TrxLookupSet lookupSet, + DiGraph graph) { + if (InstanceVersion.isMYSQL80()) { + // Do join in CN. + // local trx id -> local trx + Map localTrxInfoMap = new HashMap<>(); + long maxFetchRows = DynamicConfig.getInstance().getDeadlockDetection80FetchTrxRows(); + + // 1. Fetch all local trx info. + maxFetchRows = Math.max(maxFetchRows, 1L); + Set blockingTrxSet = new HashSet<>(); + try (final Connection conn = createPhysicalConnectionForLeaderStorage(dataSource); + final Statement stmt = conn.createStatement(); + final ResultSet rs = stmt.executeQuery(SQL_QUERY_TRX_80 + " LIMIT " + maxFetchRows)) { + while (rs.next()) { + LocalTrxInfo localTrxInfo = new LocalTrxInfo( + rs.getLong("trx_id"), + rs.getLong("conn_id"), + rs.getString("state"), + rs.getString("physical_sql"), + rs.getString("operation_state"), + rs.getInt("tables_in_use"), + rs.getInt("tables_locked"), + rs.getInt("lock_structs"), + rs.getInt("heap_size"), + rs.getInt("row_locks") + ); + localTrxInfoMap.put(localTrxInfo.getTrxId(), localTrxInfo); + // Record trx holding locks but not waiting any other locks. + if (!localTrxInfo.getState().equalsIgnoreCase("LOCK WAIT") + && localTrxInfo.getRowLocks() > 0) { + blockingTrxSet.add(localTrxInfo.getTrxId()); + } + } + } catch (SQLException ex) { + final String dnId = dataSource.getMasterSourceAddress(); + throw new RuntimeException("Failed to fetch trx info on data source " + dnId, ex); + } - try (final Connection conn = createPhysicalConnectionForLeaderStorage(dataSource); - final Statement stmt = conn.createStatement(); - final ResultSet rs = stmt.executeQuery(deadLocksSql)) { + // 2. Fetch waiting trx info. + if (!blockingTrxSet.isEmpty()) { + try (final Connection conn = createPhysicalConnectionForLeaderStorage(dataSource); + final Statement stmt = conn.createStatement(); + final ResultSet rs = stmt.executeQuery(SQL_QUERY_LOCK_WAITS_80)) { + while (rs.next()) { + final long waitingTrxId = rs.getLong("waiting_trx_id"); + final long blockingTrxId = rs.getLong("blocking_trx_id"); + if (!blockingTrxSet.contains(blockingTrxId)) { + continue; + } + final LocalTrxInfo waitingTrxInfo = localTrxInfoMap.get(waitingTrxId); + final LocalTrxInfo blockingTrxInfo = localTrxInfoMap.get(blockingTrxId); + if (null == waitingTrxInfo || null == blockingTrxInfo) { + continue; + } + // Update the wait-for graph and the lookup set + // Get the waiting and blocking transaction + final long waiting = waitingTrxInfo.getConnId(); + final long blocking = blockingTrxInfo.getConnId(); + final Triple waitingAndBlockingTrx = + lookupSet.getWaitingAndBlockingTrx(groupNames, waiting, blocking); + final TrxLookupSet.Transaction waitingTrx = waitingAndBlockingTrx.getLeft(); + final TrxLookupSet.Transaction blockingTrx = waitingAndBlockingTrx.getMiddle(); + + if (null != waitingTrx && null != blockingTrx) { + // Update the wait-for graph and the lookup set + graph.addDiEdge(waitingTrx, blockingTrx); + + try { + // Get the group which the waiting and blocking thread id are in + final String groupName = waitingAndBlockingTrx.getRight(); + + // Get the waiting local transaction of this group + final LocalTransaction waitingLocalTrx = waitingTrx.getLocalTransaction(groupName); + extractTrx80(waitingTrxInfo, waitingLocalTrx); + + // Get the blocking local transaction of this group + final LocalTransaction blockingLocalTrx = blockingTrx.getLocalTransaction(groupName); + extractTrx80(blockingTrxInfo, blockingLocalTrx); + } catch (Throwable t) { + // Ignore. + logger.warn("Get lock-wait message failed.", t); + } + } + } + } catch (SQLException ex) { + final String dnId = dataSource.getMasterSourceAddress(); + throw new RuntimeException("Failed to fetch lock waits on data source " + dnId, ex); + } + } + } else { + try (final Connection conn = createPhysicalConnectionForLeaderStorage(dataSource); + final Statement stmt = conn.createStatement(); + final ResultSet rs = stmt.executeQuery(SQL_QUERY_DEADLOCKS)) { - while (rs.next()) { - // Get the waiting and blocking connection id of DN - final long waiting = rs.getLong("waiting_conn_id"); - final long blocking = rs.getLong("blocking_conn_id"); + while (rs.next()) { + // Get the waiting and blocking connection id of DN + final long waiting = rs.getLong("waiting_conn_id"); + final long blocking = rs.getLong("blocking_conn_id"); - // Get the waiting and blocking transaction - final Triple waitingAndBlockingTrx = - lookupSet.getWaitingAndBlockingTrx(groupNames, waiting, blocking); + // Get the waiting and blocking transaction + final Triple waitingAndBlockingTrx = + lookupSet.getWaitingAndBlockingTrx(groupNames, waiting, blocking); - final TrxLookupSet.Transaction waitingTrx = waitingAndBlockingTrx.getLeft(); - final TrxLookupSet.Transaction blockingTrx = waitingAndBlockingTrx.getMiddle(); + final TrxLookupSet.Transaction waitingTrx = waitingAndBlockingTrx.getLeft(); + final TrxLookupSet.Transaction blockingTrx = waitingAndBlockingTrx.getMiddle(); if (null != waitingTrx && null != blockingTrx) { // Update the wait-for graph and the lookup set @@ -231,27 +324,28 @@ public void fetchLockWaits(TGroupDataSource dataSource, // Get the group which the waiting and blocking thread id are in final String groupName = waitingAndBlockingTrx.getRight(); - // Get the waiting local transaction of this group - final LocalTransaction waitingLocalTrx = waitingTrx.getLocalTransaction(groupName); - extractWaitingTrx(rs, waitingLocalTrx, isMySQL80); - - // Get the blocking local transaction of this group - final LocalTransaction blockingLocalTrx = blockingTrx.getLocalTransaction(groupName); - extractBlockingTrx(rs, blockingLocalTrx, isMySQL80); - } catch (Throwable t) { - // Ignore. - logger.warn("Get lock-wait message failed.", t); + // Get the waiting local transaction of this group + final LocalTransaction waitingLocalTrx = waitingTrx.getLocalTransaction(groupName); + extractWaitingTrx(rs, waitingLocalTrx); + + // Get the blocking local transaction of this group + final LocalTransaction blockingLocalTrx = blockingTrx.getLocalTransaction(groupName); + extractBlockingTrx(rs, blockingLocalTrx); + } catch (Throwable t) { + // Ignore. + logger.warn("Get lock-wait message failed.", t); + } } } + } catch (SQLException ex) { + final String dnId = dataSource.getMasterSourceAddress(); + throw new RuntimeException("Failed to fetch lock waits on data source " + dnId, ex); } - } catch (SQLException ex) { - final String dnId = dataSource.getMasterSourceAddress(); - throw new RuntimeException("Failed to fetch lock waits on data source " + dnId, ex); } } - private void extractBlockingTrx(ResultSet rs, LocalTransaction blockingLocalTrx, boolean isMySQL80) + private void extractBlockingTrx(ResultSet rs, LocalTransaction blockingLocalTrx) throws SQLException { if (!blockingLocalTrx.isUpdated()) { blockingLocalTrx.setState(rs.getString("blocking_state")); @@ -269,31 +363,20 @@ private void extractBlockingTrx(ResultSet rs, LocalTransaction blockingLocalTrx, blockingLocalTrx.setUpdated(true); } // Update holding-lock information of blocking transaction - if (isMySQL80) { - blockingLocalTrx.addHoldingTrxLock(new TrxLock( - rs.getString("blocking_lock_id"), - rs.getString("blocking_lock_mode"), - rs.getString("blocking_lock_type"), - rs.getString("blocking_lock_physical_table"), - rs.getString("blocking_lock_index"), - rs.getString("blocking_lock_data") - )); - } else { - blockingLocalTrx.addHoldingTrxLock(new TrxLock( - rs.getString("blocking_lock_id"), - rs.getString("blocking_lock_mode"), - rs.getString("blocking_lock_type"), - rs.getString("blocking_lock_physical_table"), - rs.getString("blocking_lock_index"), - rs.getInt("blocking_lock_space"), - rs.getInt("blocking_lock_page"), - rs.getInt("blocking_lock_rec"), - rs.getString("blocking_lock_data") - )); - } + blockingLocalTrx.addHoldingTrxLock(new TrxLock( + rs.getString("blocking_lock_id"), + rs.getString("blocking_lock_mode"), + rs.getString("blocking_lock_type"), + rs.getString("blocking_lock_physical_table"), + rs.getString("blocking_lock_index"), + rs.getInt("blocking_lock_space"), + rs.getInt("blocking_lock_page"), + rs.getInt("blocking_lock_rec"), + rs.getString("blocking_lock_data") + )); } - private void extractWaitingTrx(ResultSet rs, LocalTransaction waitingLocalTrx, boolean isMySQL80) + private void extractWaitingTrx(ResultSet rs, LocalTransaction waitingLocalTrx) throws SQLException { if (!waitingLocalTrx.isUpdated()) { waitingLocalTrx.setState(rs.getString("waiting_state")); @@ -312,59 +395,46 @@ private void extractWaitingTrx(ResultSet rs, LocalTransaction waitingLocalTrx, b } if (null == waitingLocalTrx.getWaitingTrxLock()) { - // Update waiting-lock information of this local transaction - if (isMySQL80) { - waitingLocalTrx.setWaitingTrxLock(new TrxLock( - rs.getString("waiting_lock_id"), - rs.getString("waiting_lock_mode"), - rs.getString("waiting_lock_type"), - rs.getString("waiting_lock_physical_table"), - rs.getString("waiting_lock_index"), - null, - null, - null, - rs.getString("waiting_lock_data") - )); - } else { - waitingLocalTrx.setWaitingTrxLock(new TrxLock( - rs.getString("waiting_lock_id"), - rs.getString("waiting_lock_mode"), - rs.getString("waiting_lock_type"), - rs.getString("waiting_lock_physical_table"), - rs.getString("waiting_lock_index"), - rs.getInt("waiting_lock_space"), - rs.getInt("waiting_lock_page"), - rs.getInt("waiting_lock_rec"), - rs.getString("waiting_lock_data") - )); - } + waitingLocalTrx.setWaitingTrxLock(new TrxLock( + rs.getString("waiting_lock_id"), + rs.getString("waiting_lock_mode"), + rs.getString("waiting_lock_type"), + rs.getString("waiting_lock_physical_table"), + rs.getString("waiting_lock_index"), + rs.getInt("waiting_lock_space"), + rs.getInt("waiting_lock_page"), + rs.getInt("waiting_lock_rec"), + rs.getString("waiting_lock_data") + )); + } + } + + private void extractTrx80(LocalTrxInfo info, LocalTransaction waitingLocalTrx) { + if (!waitingLocalTrx.isUpdated()) { + waitingLocalTrx.setState(info.getState()); + final String physicalSql = info.getPhysicalSql(); + // Record a truncated SQL + waitingLocalTrx.setPhysicalSql( + physicalSql == null ? null : physicalSql.substring(0, min(4096, physicalSql.length()))); + waitingLocalTrx.setOperationState(info.getOperationState()); + waitingLocalTrx.setTablesInUse(info.getTablesInUse()); + waitingLocalTrx.setTablesLocked(info.getTablesLocked()); + waitingLocalTrx.setLockStructs(info.getLockStructs()); + waitingLocalTrx.setHeapSize(info.getHeapSize()); + waitingLocalTrx.setRowLocks(info.getRowLocks()); + waitingLocalTrx.setUpdated(true); } } /** * Fetch all transactions on the instance. */ - private TrxLookupSet fetchTransInfo() { + public static TrxLookupSet fetchTransInfo() { final TrxLookupSet lookupSet = new TrxLookupSet(); final List>> results = SyncManagerHelper.sync(new FetchTransForDeadlockDetectionSyncAction(null), DEFAULT_DB_NAME, SyncScope.CURRENT_ONLY); - for (final List> result : results) { - if (result == null) { - continue; - } - for (final Map row : result) { - final Long transId = (Long) row.get("TRANS_ID"); - final String group = (String) row.get("GROUP"); - final long connId = (Long) row.get("CONN_ID"); - final long frontendConnId = (Long) row.get("FRONTEND_CONN_ID"); - final Long startTime = (Long) row.get("START_TIME"); - final String sql = (String) row.get("SQL"); - final GroupConnPair entry = new GroupConnPair(group, connId); - lookupSet.addNewTransaction(entry, transId); - lookupSet.updateTransaction(transId, frontendConnId, sql, startTime); - } - } + TransactionUtils.updateTrxLookupSet(results, lookupSet); return lookupSet; } @@ -390,7 +460,12 @@ public void run() { return; } - if (ExecUtils.isMysql80Version() && !InstConfUtil.getBool(ConnectionParams.ENABLE_DEADLOCK_DETECTION_80)) { + if (InstanceVersion.isMYSQL80() && !InstConfUtil.getBool(ConnectionParams.ENABLE_DEADLOCK_DETECTION_80)) { + return; + } + + if (SKIP.get() > 0) { + SKIP.decrementAndGet(); return; } @@ -420,6 +495,10 @@ public void run() { final Set groupNames = groupDataSources.stream().map(TGroupDataSource::getDbGroupKey).collect(Collectors.toSet()); + if (maybeTooManyDataLockWaits(groupDataSource)) { + return; + } + // Fetch lock-wait information for this DN, // and update the lookup set and the graph with the information fetchLockWaits(groupDataSource, groupNames, lookupSet, graph); @@ -437,7 +516,12 @@ public void run() { // TODO: kill transaction by some priority, such as create time, or prefer to kill internal transaction. // The index of the transaction to be killed in the cycle - final int indexOfToKillTrx = 0; + int indexOfToKillTrx = 0; + for (int i = 0; i < cycle.size(); i++) { + if (!cycle.get(i).isDdl()) { + indexOfToKillTrx = i; + } + } final TrxLookupSet.Transaction toKillTrx = cycle.get(indexOfToKillTrx); simpleDeadlockLog .append(String.format(" Will rollback %s", Long.toHexString(toKillTrx.getTransactionId()))); @@ -445,6 +529,15 @@ public void run() { // Store deadlock log in StorageInfoManager so that executor can access it StorageInfoManager.updateDeadlockInfo(fullDeadlockLog.toString()); + // Record deadlock in meta db. + try (Connection connection = MetaDbUtil.getConnection()) { + DeadlocksAccessor deadlocksAccessor = new DeadlocksAccessor(); + deadlocksAccessor.setConnection(connection); + deadlocksAccessor.recordDeadlock(GlobalTxLogManager.getCurrentServerAddr(), "GLOBAL", + fullDeadlockLog.toString()); + } catch (Exception e) { + logger.error(e); + } TransactionLogger.warn(simpleDeadlockLog.toString()); logger.warn(simpleDeadlockLog.toString()); @@ -458,6 +551,37 @@ public void run() { } } + protected boolean maybeTooManyDataLockWaits(TGroupDataSource dataSource) { + // Estimate row count of data_lock_waits records, if too many, skip this round of detection. + // Or it may cause DN hang for a long time. + String sql = InstanceVersion.isMYSQL80() ? SQL_QUERY_HOTSPOT_LOCK_80 : SQL_QUERY_HOTSPOT_LOCK; + long estimateRowCount = 0; + try (final Connection conn = createPhysicalConnectionForLeaderStorage(dataSource); + final Statement stmt = conn.createStatement(); + final ResultSet rs = stmt.executeQuery(sql)) { + while (rs.next()) { + String lockId = rs.getString("lock_id"); + if (null != lockId && !"NULL".equalsIgnoreCase(lockId)) { + long cnt = rs.getLong("cnt"); + estimateRowCount += cnt * (cnt - 1) / 2; + } + if (estimateRowCount > DynamicConfig.getInstance().getDeadlockDetectionDataLockWaitsThreshold()) { + final String dnId = dataSource.getMasterSourceAddress(); + String errMsg = "[" + dnId + "] Too many data_lock_waits records: " + estimateRowCount + + ", skip deadlock detection task."; + TransactionLogger.warn(errMsg); + EventLogger.log(EventType.DEAD_LOCK_DETECTION, errMsg); + SKIP.set(DynamicConfig.getInstance().getDeadlockDetectionSkipRound()); + return true; + } + } + } catch (SQLException ex) { + final String dnId = dataSource.getMasterSourceAddress(); + throw new RuntimeException("Failed to estimate row count on data source " + dnId, ex); + } + return false; + } + private boolean hasLeadership() { return !allSchemas.isEmpty() && ExecUtils.hasLeadership(allSchemas.iterator().next()); } @@ -466,4 +590,33 @@ public static Connection createPhysicalConnectionForLeaderStorage(TGroupDataSour String masterDnId = dataSource.getMasterDNId(); return DbTopologyManager.getConnectionForStorage(masterDnId); } + + @Data + private static class LocalTrxInfo { + private final Long trxId; + private final Long connId; + private final String state; + private final String physicalSql; + private final String operationState; + private final Integer tablesInUse; + private final Integer tablesLocked; + private final Integer lockStructs; + private final Integer heapSize; + private final Integer rowLocks; + + public LocalTrxInfo(Long trxId, Long connId, String state, String physicalSql, String operationState, + Integer tablesInUse, Integer tablesLocked, Integer lockStructs, Integer heapSize, + Integer rowLocks) { + this.trxId = trxId; + this.connId = connId; + this.state = state; + this.physicalSql = physicalSql; + this.operationState = operationState; + this.tablesInUse = tablesInUse; + this.tablesLocked = tablesLocked; + this.lockStructs = lockStructs; + this.heapSize = heapSize; + this.rowLocks = rowLocks; + } + } } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/KillTimeoutTransactionTask.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/KillTimeoutTransactionTask.java index 46ea38ca7..ec99857db 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/KillTimeoutTransactionTask.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/KillTimeoutTransactionTask.java @@ -26,7 +26,7 @@ * @version 1.0 */ public class KillTimeoutTransactionTask implements Runnable { - private static final Logger logger = LoggerFactory.getLogger(DeadlockDetectionTask.class); + private static final Logger logger = LoggerFactory.getLogger(KillTimeoutTransactionTask.class); private final String db; diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/MdlDeadlockDetectionTask.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/MdlDeadlockDetectionTask.java index a1dc3fcc7..df71a6f00 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/MdlDeadlockDetectionTask.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/MdlDeadlockDetectionTask.java @@ -24,6 +24,8 @@ import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.common.utils.logger.MDC; +import com.alibaba.polardbx.config.ConfigDataMode; import com.alibaba.polardbx.executor.common.StorageInfoManager; import com.alibaba.polardbx.executor.sync.ISyncAction; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; @@ -33,15 +35,19 @@ import com.alibaba.polardbx.executor.utils.transaction.LocalTransaction; import com.alibaba.polardbx.executor.utils.transaction.TrxLock; import com.alibaba.polardbx.executor.utils.transaction.TrxLookupSet; +import com.alibaba.polardbx.gms.metadb.trx.DeadlocksAccessor; import com.alibaba.polardbx.gms.sync.SyncScope; +import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.statistics.SQLRecorderLogger; import com.alibaba.polardbx.transaction.TransactionExecutor; import com.alibaba.polardbx.transaction.TransactionLogger; import com.alibaba.polardbx.transaction.TransactionManager; -import com.alibaba.polardbx.transaction.sync.FetchTransForDeadlockDetectionSyncAction; +import com.alibaba.polardbx.transaction.log.GlobalTxLogManager; import com.alibaba.polardbx.transaction.utils.DiGraph; import com.google.common.collect.ImmutableSet; +import org.apache.calcite.sql.SqlIdentifier; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -53,6 +59,7 @@ import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -67,7 +74,6 @@ import static com.alibaba.polardbx.gms.topology.SystemDbHelper.DEFAULT_DB_NAME; import static com.alibaba.polardbx.gms.util.GroupInfoUtil.buildGroupNameFromPhysicalDb; import static com.alibaba.polardbx.gms.util.GroupInfoUtil.buildPhysicalDbNameFromGroupName; -import static java.lang.Math.min; /** * activates if these conditions are met: @@ -92,6 +98,12 @@ public class MdlDeadlockDetectionTask implements Runnable { private static Class killSyncActionClass; + private static final String PENDING_STATUS = "PENDING"; + + private static final String GRANTED_STATUS = "GRANTED"; + + private Collection allSchema; + private static final Set DDL_WAIT_MDL_LOCK_TYPE = ImmutableSet.of( "EXCLUSIVE", // for general online ddl: add column, drop column @@ -134,10 +146,27 @@ public class MdlDeadlockDetectionTask implements Runnable { + "AND " + "(`pt`.`PROCESSLIST_ID` != `gt`.`PROCESSLIST_ID`)"; + private static final String SELECT_MDL_WAITING_ONLY = + "select " + + "`g`.`OBJECT_SCHEMA` AS `object_schema`," + + "`g`.`OBJECT_NAME` AS `object_name`," + + "`g`.`OBJECT_TYPE` AS `object_type`," + + "`g`.`LOCK_TYPE` AS `lock_type`," + + "`g`.`LOCK_STATUS` AS `lock_status`," + + "`g`.`OWNER_THREAD_ID` AS `owner_thread_id` " + + "from `performance_schema`.`metadata_locks` `g` "; + + private static final String SELECT_THREADS_ONLY = + "select " + + "`t`.`THREAD_ID` AS `thread_id`," + + "`t`.`PROCESSLIST_ID` AS `processlist_id`," + + "`t`.`PROCESSLIST_INFO` AS `processlist_info`," + + "`t`.`PROCESSLIST_TIME` AS `processlist_time` " + + "from `performance_schema`.`threads` `t` "; /** * DDL will wait for MDL for some seconds, then kill the query which held the MDL */ - private long MDL_WAIT_TIMEOUT; + private static AtomicLong MDL_WAIT_TIMEOUT = new AtomicLong(15); static { // 只有server支持,这里是暂时改法,后续要将这段逻辑解耦 @@ -149,10 +178,125 @@ public class MdlDeadlockDetectionTask implements Runnable { } } - public MdlDeadlockDetectionTask(String db, TransactionExecutor executor, int mdlWaitTimeoutInSec) { + public MdlDeadlockDetectionTask(String db, Collection allSchema, TransactionExecutor executor, + int mdlWaitTimeoutInSec) { this.db = db; this.executor = executor; - this.MDL_WAIT_TIMEOUT = mdlWaitTimeoutInSec; + this.allSchema = allSchema; + MDL_WAIT_TIMEOUT.set(mdlWaitTimeoutInSec); + } + + private static class DbTableName { + String dbName; + String tableName; + String objectType; + + static String phyTableNameFormat = "%s.%s"; + + public DbTableName(String dbName, String tableName, String objectType) { + this.dbName = dbName; + this.tableName = tableName; + this.objectType = objectType; + } + + public Boolean isTable() { + return objectType.equalsIgnoreCase("TABLE"); + } + + public String getPhyTableName() { + return String.format(phyTableNameFormat, SqlIdentifier.surroundWithBacktick(dbName), + SqlIdentifier.surroundWithBacktick(tableName)); + } + + } + + private static class MdlLockInfo { + String lockStatus; + String lockType; + Long threadId; + + public MdlLockInfo(String lockStatus, String lockType, Long threadId) { + this.lockStatus = lockStatus; + this.lockType = lockType; + this.threadId = threadId; + } + } + + private static class ProcessInfo { + Long processId; + Object processInfo; + Long runningTime; + + public ProcessInfo(Long processId, Object processInfo, Long runningTime) { + this.processId = processId; + this.processInfo = processInfo; + this.runningTime = runningTime; + } + } + + private static class MdlLockInfoSet { + Map> mdlLockInfoMap; + Boolean markForMdlWaiting; + + MdlLockInfoSet() { + this.mdlLockInfoMap = new HashMap<>(); + this.markForMdlWaiting = false; + } + + public void append(MdlLockInfo mdlLockInfo) { + if (!this.mdlLockInfoMap.containsKey(mdlLockInfo.lockType)) { + this.mdlLockInfoMap.put(mdlLockInfo.lockType, new ArrayList<>()); + } + this.mdlLockInfoMap.get(mdlLockInfo.lockType).add(mdlLockInfo); + if (this.markForMdlWaiting == false && DDL_WAIT_MDL_LOCK_TYPE.contains(mdlLockInfo.lockType) + && mdlLockInfo.lockStatus.equalsIgnoreCase(PENDING_STATUS)) { + this.markForMdlWaiting = true; + } + } + + public List fetchWaitForInfoList(DbTableName dbTableName) { + List waitInfoList = new ArrayList<>(); + MdlLockInfo waitingMdlLockInfo = null; + for (String lockType : this.mdlLockInfoMap.keySet()) { + if (DDL_WAIT_MDL_LOCK_TYPE.contains(lockType)) { + if (waitingMdlLockInfo == null) { + List mdlLockInfos = this.mdlLockInfoMap.get(lockType); + for (MdlLockInfo mdlLockInfo : mdlLockInfos) { + if (mdlLockInfo.lockStatus.equalsIgnoreCase(PENDING_STATUS)) { + waitingMdlLockInfo = mdlLockInfo; + } + } + } + } + } + for (String lockType : this.mdlLockInfoMap.keySet()) { + if (waitingMdlLockInfo != null && !DDL_WAIT_MDL_LOCK_TYPE.contains(lockType)) { + List mdlLockInfos = this.mdlLockInfoMap.get(lockType); + for (MdlLockInfo mdlLockInfo : mdlLockInfos) { + if (mdlLockInfo.lockStatus.equalsIgnoreCase(GRANTED_STATUS) + && !waitingMdlLockInfo.threadId.equals(mdlLockInfo.threadId)) { + MdlWaitInfo mdlWaitInfo = new MdlWaitInfo( + waitingMdlLockInfo.threadId, + mdlLockInfo.threadId, + waitingMdlLockInfo.lockType, + mdlLockInfo.lockType, + -1L, + "", + "", + dbTableName.dbName, + dbTableName.tableName, + null); + waitInfoList.add(mdlWaitInfo); + } + } + } + } + return waitInfoList; + } + + public Boolean getMarkForMdlWaiting() { + return this.markForMdlWaiting; + } } /** @@ -168,49 +312,114 @@ public MdlDeadlockDetectionTask(String db, TransactionExecutor executor, int mdl * @param mysqlConn2DatasourceMap is updated in this method * @param mdlWaitInfoList is updated in this method */ - public void fetchMetaDataLockWaits(TGroupDataSource dataSource, - Collection groupNames, - DiGraph graph, - TrxLookupSet lookupSet, - Map mysqlConn2DatasourceMap, - List mdlWaitInfoList) { + public static void fetchMetaDataLockWaits(String dn, TGroupDataSource dataSource, + Collection groupNames, + DiGraph graph, + TrxLookupSet lookupSet, + Map mysqlConn2DatasourceMap, + List mdlWaitInfoList) { + Long startMoment = System.currentTimeMillis(); + Long fetchMdlMoment = startMoment; + Long processMdlMoment = startMoment; + Long fetchProcessMoment = startMoment; + Long processProcessMoment = startMoment; + Long finalMoment = startMoment; + int mdlCount = 0; + int processCount = 0; final Map ddlTrxMap = new HashMap<>(); final Set phyDbNames = groupNames.stream().map(o -> buildPhysicalDbNameFromGroupName(o).toUpperCase()).collect( Collectors.toSet()); String masterDnId = dataSource.getMasterDNId(); + List mdlWaitInfoOnDataSource = new ArrayList<>(); try (final Connection conn = DeadlockDetectionTask.createPhysicalConnectionForLeaderStorage(dataSource); Statement stmt = conn.createStatement()) { - final ResultSet rs = stmt.executeQuery(SELECT_PERFORMANCE_SCHEMA_METALOCKS); - while (rs.next()) { +// final ResultSet rs = stmt.executeQuery(SELECT_PERFORMANCE_SCHEMA_METALOCKS); + Map objectMdlMap = new HashMap<>(); + Boolean markForFetchThreadInfo = false; + Map dbTableNameMap = new HashMap<>(); + try (final ResultSet rs = stmt.executeQuery(SELECT_MDL_WAITING_ONLY)) { + while (rs.next()) { + mdlCount++; + final String objectSchema = rs.getString("object_schema"); + final String objectName = rs.getString("object_name"); + final String objectType = rs.getString("object_type"); + final String lockStatus = rs.getString("lock_status"); + final String lockType = rs.getString("lock_type"); + final Long threadId = rs.getLong("owner_thread_id"); + DbTableName dbTableName = new DbTableName(objectSchema, objectName, objectType); + if (!dbTableName.isTable()) { + continue; + } + String phyTableName = dbTableName.getPhyTableName(); + if (!objectMdlMap.containsKey(phyTableName)) { + objectMdlMap.put(phyTableName, new MdlLockInfoSet()); + dbTableNameMap.put(phyTableName, dbTableName); + } + objectMdlMap.get(phyTableName).append(new MdlLockInfo(lockStatus, lockType, threadId)); + } + } + fetchMdlMoment = System.currentTimeMillis(); + for (String phyTableName : objectMdlMap.keySet()) { + MdlLockInfoSet mdlLockInfoSet = objectMdlMap.get(phyTableName); + if (mdlLockInfoSet.getMarkForMdlWaiting()) { + // short-way for non-ddl-waiting occasion. + markForFetchThreadInfo = true; + DbTableName dbTableName = dbTableNameMap.get(phyTableName); + mdlWaitInfoOnDataSource.addAll(mdlLockInfoSet.fetchWaitForInfoList(dbTableName)); + } + } + + processMdlMoment = System.currentTimeMillis(); + fetchProcessMoment = processMdlMoment; + if (markForFetchThreadInfo) { + Map processInfoMap = new HashMap(); + try (final ResultSet rs2 = stmt.executeQuery(SELECT_THREADS_ONLY)) { + while (rs2.next()) { + processCount++; + final Long threadId = rs2.getLong("thread_id"); + final Long processId = rs2.getLong("processlist_id"); + // getString processlist_info is very costly + final Object processInfo = rs2.getObject("processlist_info"); + final Long processTime = rs2.getLong("processlist_time"); + processInfoMap.put(threadId, new ProcessInfo(processId, processInfo, processTime)); + } + } + fetchProcessMoment = System.currentTimeMillis(); + for (MdlWaitInfo mdlWaitInfo : mdlWaitInfoOnDataSource) { + // update thread id => process id, and update process info, and more. + mdlWaitInfo.updateProcessInfo(processInfoMap.get(mdlWaitInfo.waiting), + processInfoMap.get(mdlWaitInfo.blocking), dataSource); + } + } + + processProcessMoment = System.currentTimeMillis(); + + for (MdlWaitInfo mdlWaitInfo : mdlWaitInfoOnDataSource) { // Get the waiting and blocking processlist id - final long waiting = rs.getLong("waiting_pid"); - final long blocking = rs.getLong("blocking_pid"); + final long waiting = mdlWaitInfo.waiting; + final long blocking = mdlWaitInfo.blocking; // Update mysqlConn2DatasourceMap mysqlConn2DatasourceMap.put(waiting, dataSource); mysqlConn2DatasourceMap.put(blocking, dataSource); - final String waitingQuery = rs.getString("waiting_query"); - final long waitingQuerySecs = rs.getLong("waiting_query_secs"); - final String waitingLockType = rs.getString("waiting_lock_type"); - final String blockingLockType = rs.getString("blocking_lock_type"); - final String physicalDbName = rs.getString("object_schema"); - final String blockingQuery = rs.getString("blocking_query"); - final String physicalTableName = rs.getString("object_name"); + final Object waitingQuery = mdlWaitInfo.waitingQuery; + final long waitingQuerySecs = mdlWaitInfo.waitingQuerySecs; + final String waitingLockType = mdlWaitInfo.waitingLockType; + final String blockingLockType = mdlWaitInfo.blockingLockType; + final String physicalDbName = mdlWaitInfo.phyDbName; + final Object blockingQuery = mdlWaitInfo.blockingQuery; + final String physicalTableName = mdlWaitInfo.phyTableName; // Update mdlWaitInfoList, it is used to do the following thing: // If A is waiting for EXCLUSIVE MDL blocked by B, and B is holding a non-EXCLUSIVE MDL lock // Then we kill B - if (waitingQuerySecs >= MDL_WAIT_TIMEOUT && + if (waitingQuerySecs >= MDL_WAIT_TIMEOUT.get() && DDL_WAIT_MDL_LOCK_TYPE.contains(waitingLockType.toUpperCase()) && !DDL_WAIT_MDL_LOCK_TYPE.contains(blockingLockType.toUpperCase()) && phyDbNames.contains(physicalDbName.toUpperCase())) { - MdlWaitInfo mdlInfo = - new MdlWaitInfo(waiting, blocking, waitingLockType, waitingQuerySecs, waitingQuery, - blockingQuery, physicalDbName, physicalTableName, dataSource); - - mdlWaitInfoList.add(mdlInfo); + mdlWaitInfoList.add(mdlWaitInfo); } // The wait-block relation is not so accurate. @@ -222,7 +431,8 @@ public void fetchMetaDataLockWaits(TGroupDataSource dataSource, // Get the waiting and blocking transaction final Triple waitingAndBlockingTrx = - lookupSet.getWaitingAndBlockingTrx(groupNames, waiting, blocking); + lookupSet.getWaitingAndBlockingTrx( + Collections.singletonList(buildGroupNameFromPhysicalDb(physicalDbName)), waiting, blocking); // Update waiting trx/DDL TrxLookupSet.Transaction waitingTrx = waitingAndBlockingTrx.getLeft(); @@ -247,12 +457,12 @@ public void fetchMetaDataLockWaits(TGroupDataSource dataSource, } // Update other information of waiting trx if (null != waitingQuery) { - final String truncatedSql = waitingQuery.substring(0, min(waitingQuery.length(), 4096)); + final Object truncatedSql = waitingQuery; waitingLocalTrx.setPhysicalSql(truncatedSql); } final String physicalTable = String.format("`%s`.`%s`", - rs.getString("object_schema"), rs.getString("object_name")); + mdlWaitInfo.phyDbName, mdlWaitInfo.phyTableName); if (null == waitingLocalTrx.getWaitingTrxLock()) { // A lock id represents a unique lock, // and we use {schema.table:lock type} to represent an MDL lock id @@ -276,7 +486,7 @@ public void fetchMetaDataLockWaits(TGroupDataSource dataSource, // Note that this fake transaction should have only one local transaction blockingLocalTrx = blockingTrx.getLocalTransaction(FAKE_GROUP_FOR_DDL); - final long blockingQuerySecs = rs.getLong("blocking_query_secs"); + final long blockingQuerySecs = mdlWaitInfo.waitingQuerySecs; final Long startTime = System.currentTimeMillis() - blockingQuerySecs * 1000; blockingTrx.setStartTime(startTime); } else { @@ -285,7 +495,7 @@ public void fetchMetaDataLockWaits(TGroupDataSource dataSource, } // Update other information of blocking trx if (null != blockingQuery && null == blockingLocalTrx.getPhysicalSql()) { - final String truncatedSql = blockingQuery.substring(0, min(blockingQuery.length(), 4096)); + final Object truncatedSql = blockingQuery; blockingLocalTrx.setPhysicalSql(truncatedSql); } @@ -295,10 +505,25 @@ public void fetchMetaDataLockWaits(TGroupDataSource dataSource, blockingLocalTrx.addHoldingTrxLock(new TrxLock(lockId, blockingLockType, physicalTable)); graph.addDiEdge(waitingTrx, blockingTrx); } + finalMoment = System.currentTimeMillis(); + if (mdlWaitInfoList.size() > 0 || mdlCount > 100 || processCount > 100 || finalMoment - startMoment > 10) { + String logInfo = String.format( + "mdl detection task fetch mdl cost total %d ms on dn %s(%s), fetch %d mdl, fetch %d process, generate %d mdl wait info: -----with %d ms on fetch mdl, %d ms on process mdl, %d ms on fetch process, %d ms on process process, %d ms on deadlock detect", + finalMoment - startMoment, dataSource.getMasterDNId(), dn, mdlCount, processCount, + mdlWaitInfoList.size(), + fetchMdlMoment - startMoment, processMdlMoment - fetchMdlMoment, + fetchProcessMoment - processMdlMoment, + processProcessMoment - fetchProcessMoment, + finalMoment - processProcessMoment); + SQLRecorderLogger.ddlLogger.warn(logInfo); + } } catch (SQLException ex) { final String dnId = dataSource.getMasterSourceAddress(); - throw new RuntimeException( - String.format("Failed to fetch lock waits on data source %s. msg:%s", dnId, ex.getMessage()), ex); + final String logInfo = + String.format("Failed to fetch lock waits on data source %s. msg:%s", dnId, + Optional.of(ex.getMessage()).orElse(" unknown cause")); + SQLRecorderLogger.ddlLogger.error(logInfo); + throw new RuntimeException(logInfo, ex); } } @@ -306,37 +531,11 @@ public void fetchMetaDataLockWaits(TGroupDataSource dataSource, * @return Whether the blocking lock should block the waiting lock. * For example, SHARED_WRITE should NOT block SHARED_WRITE. */ - private boolean notBlockMdlType(String waitingLockType, String blockingLockType) { + private static boolean notBlockMdlType(String waitingLockType, String blockingLockType) { final Set notBlockMdlType = ImmutableSet.of("SHARED_WRITE", "SHARED_READ"); return notBlockMdlType.contains(waitingLockType) && notBlockMdlType.contains(blockingLockType); } - /** - * Fetch all transactions on the given db - */ - public TrxLookupSet fetchTransInfo(String db) { - final TrxLookupSet lookupSet = new TrxLookupSet(); - final List>> results = - SyncManagerHelper.sync(new FetchTransForDeadlockDetectionSyncAction(db), db, SyncScope.NOT_COLUMNAR_SLAVE); - for (List> result : results) { - if (result == null) { - continue; - } - for (Map row : result) { - final Long transId = (Long) row.get("TRANS_ID"); - final String group = (String) row.get("GROUP"); - final long connId = (Long) row.get("CONN_ID"); - final long frontendConnId = (Long) row.get("FRONTEND_CONN_ID"); - final Long startTime = (Long) row.get("START_TIME"); - final String sql = (String) row.get("SQL"); - final GroupConnPair entry = new GroupConnPair(group, connId); - lookupSet.addNewTransaction(entry, transId); - lookupSet.updateTransaction(transId, frontendConnId, sql, startTime); - } - } - return lookupSet; - } - private void killByFrontendConnId(long frontendConnId) { ISyncAction killSyncAction; try { @@ -364,9 +563,32 @@ private void killByBackendConnId(final Long backendConnId, final TGroupDataSourc } } + private void killByBackendConnIds(final List backendConnIds, final TGroupDataSource dataSource) { + if (backendConnIds == null || null == dataSource) { + return; + } + String masterDnId = dataSource.getMasterDNId(); + try (Connection conn = DeadlockDetectionTask.createPhysicalConnectionForLeaderStorage(dataSource); + Statement stmt = conn.createStatement()) { + List sqls = new ArrayList<>(); + for (Long backendConnId : backendConnIds) { + sqls.add(String.format("kill %s", backendConnId)); + } + stmt.executeUpdate(StringUtils.join(sqls, ";")); + } catch (SQLException ex) { + final String dnId = dataSource.getMasterSourceAddress(); + throw new RuntimeException("Failed to kill connection on datasource " + dnId, ex); + } + } + @Override public void run() { + MDC.put(MDC.MDC_KEY_APP, DEFAULT_DB_NAME); + if (!ConfigDataMode.isPolarDbX()) { + cancel(); + } + boolean hasLeadership = ExecUtils.hasLeadership(db); if (!hasLeadership) { @@ -374,34 +596,34 @@ public void run() { return; } - if (!runningCountByDb.containsKey(db)) { - runningCountByDb.put(db, new AtomicLong(0)); + if (!runningCountByDb.containsKey(DEFAULT_DB_NAME)) { + runningCountByDb.put(DEFAULT_DB_NAME, new AtomicLong(0)); } int phyiscalMdlWaitTimeout = DynamicConfig.getInstance().getPhyiscalMdlWaitTimeout(); if (phyiscalMdlWaitTimeout <= 0) { - if (runningCountByDb.get(db).get() > 0L) { + if (runningCountByDb.get(DEFAULT_DB_NAME).get() > 0L) { EventLogger.log(EventType.DEAD_LOCK_DETECTION, - String.format("mdl detection has been shutdown for db %s!", db)); - runningCountByDb.get(db).set(-1L); + String.format("mdl detection has been shutdown for db %s!", DEFAULT_DB_NAME)); + runningCountByDb.get(DEFAULT_DB_NAME).set(-1L); } TransactionLogger.debug("Skip MDL deadlock detection task since dn mdl wait timeout is negative or zero"); return; } else { - MDL_WAIT_TIMEOUT = Math.max(phyiscalMdlWaitTimeout, 5); - long runningCount = runningCountByDb.get(db).get(); + MDL_WAIT_TIMEOUT.set(Math.max(phyiscalMdlWaitTimeout, 5)); + long runningCount = runningCountByDb.get(DEFAULT_DB_NAME).get(); if (runningCount < 0L) { EventLogger.log(EventType.DEAD_LOCK_DETECTION, - String.format("mdl detection has been launched for db %s, wait timeout %s s!", db, + String.format("mdl detection has been launched for db %s, wait timeout %s s!", DEFAULT_DB_NAME, MDL_WAIT_TIMEOUT)); - runningCountByDb.get(db).set(1L); + runningCountByDb.get(DEFAULT_DB_NAME).set(1L); } else { if (runningCount % 100L == 0) { EventLogger.log(EventType.DEAD_LOCK_DETECTION, String.format("mdl detection has been running for db %s, running count %d, wait timeout %s s!", - db, runningCount, MDL_WAIT_TIMEOUT)); + DEFAULT_DB_NAME, runningCount, MDL_WAIT_TIMEOUT)); } - runningCountByDb.get(db).incrementAndGet(); + runningCountByDb.get(DEFAULT_DB_NAME).incrementAndGet(); } } @@ -421,16 +643,17 @@ private void detectMetaDataDeadLock() { final DiGraph graph = new DiGraph<>(); // Get all global transaction information - final TrxLookupSet lookupSet = fetchTransInfo(db); + final TrxLookupSet lookupSet = DeadlockDetectionTask.fetchTransInfo(); // Get all group data sources, and group by DN's ID (host:port) - final Map> instId2GroupList = ExecUtils.getInstId2GroupList(db); + final Map> instId2GroupList = ExecUtils.getInstId2GroupList(allSchema); final Map mysqlConn2DatasourceMap = new HashMap<>(); List mdlWaitInfoList = new ArrayList<>(); // For each DN, find the lock-wait information and add it to the graph - for (final List groupDataSources : instId2GroupList.values()) { + for (String dn : instId2GroupList.keySet()) { + final List groupDataSources = instId2GroupList.get(dn); if (CollectionUtils.isNotEmpty(groupDataSources)) { // Since all data sources are in the same DN, any data source is ok final TGroupDataSource groupDataSource = groupDataSources.get(0); @@ -441,7 +664,7 @@ private void detectMetaDataDeadLock() { // Fetch MDL-lock-wait information for this DN, // and update the graph, the lookup set, the mysqlConn2GroupMap, and the mdlWaitInfoList - fetchMetaDataLockWaits(groupDataSource, groupNames, + fetchMetaDataLockWaits(dn, groupDataSource, groupNames, graph, lookupSet, mysqlConn2DatasourceMap, mdlWaitInfoList); } } @@ -498,6 +721,16 @@ private void detectMetaDataDeadLock() { // Store deadlock log in StorageInfoManager so that executor can access it StorageInfoManager.updateMdlDeadlockInfo(fullDeadlockLog.toString()); + + // Record deadlock in meta db. + try (Connection connection = MetaDbUtil.getConnection()) { + DeadlocksAccessor deadlocksAccessor = new DeadlocksAccessor(); + deadlocksAccessor.setConnection(connection); + deadlocksAccessor.recordDeadlock(GlobalTxLogManager.getCurrentServerAddr(), "MDL", + fullDeadlockLog.toString()); + } catch (Exception e) { + logger.error(e); + } }); if (CollectionUtils.isNotEmpty(mdlWaitInfoList)) { @@ -561,10 +794,11 @@ private static class MdlWaitInfo { long waiting; long blocking; String waitingLockType; + String blockingLockType; long waitingQuerySecs; - String waitingQuery; + Object waitingQuery; - String blockingQuery; + Object blockingQuery; TGroupDataSource dataSource; String phyDbName; @@ -574,6 +808,7 @@ private static class MdlWaitInfo { public MdlWaitInfo(final long waiting, final long blocking, final String waitingLockType, + final String blockingLockType, final long waitingQuerySecs, final String waitingQuery, final String blockingQuery, @@ -583,6 +818,7 @@ public MdlWaitInfo(final long waiting, this.waiting = waiting; this.blocking = blocking; this.waitingLockType = waitingLockType; + this.blockingLockType = blockingLockType; this.waitingQuerySecs = waitingQuerySecs; this.waitingQuery = Optional.ofNullable(waitingQuery).orElse(""); this.blockingQuery = Optional.ofNullable(blockingQuery).orElse(""); @@ -590,9 +826,31 @@ public MdlWaitInfo(final long waiting, this.phyTableName = phyTableName; this.dataSource = dataSource; } + + public void updateProcessInfo(ProcessInfo waitingProcessInfo, ProcessInfo blockingProcessInfo, + TGroupDataSource dataSource) { + if (waitingProcessInfo != null) { + if (waitingProcessInfo.processInfo != null) { + this.waitingQuery = waitingProcessInfo.processInfo; + } + this.waitingQuerySecs = waitingProcessInfo.runningTime; + this.waiting = waitingProcessInfo.processId; + } else { + this.waiting = -1L; + } + if (blockingProcessInfo != null) { + if (blockingProcessInfo.processInfo != null) { + this.blockingQuery = blockingProcessInfo.processInfo; + } + this.blocking = blockingProcessInfo.processId; + } else { + this.blocking = -1L; + } + this.dataSource = dataSource; + } } - private static String formatProcessInfo(String processInfo) { - return processInfo.replace("\n", "\\n"); + private static String formatProcessInfo(Object processInfo) { + return Optional.ofNullable(processInfo).orElse("").toString().replace("\n", "\\n"); } } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/PurgeColumnarTsoTimerTask.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/PurgeColumnarTsoTimerTask.java index bdd07d118..cb0688ae0 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/PurgeColumnarTsoTimerTask.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/PurgeColumnarTsoTimerTask.java @@ -38,6 +38,8 @@ public void run() { return; } + logger.warn("Start to fetch columnar purge tso"); + Long minSnapshotTime; try { minSnapshotTime = ColumnarTransactionUtils.getMinColumnarSnapshotTime(); @@ -55,6 +57,17 @@ public void run() { } catch (Throwable t) { logger.error(String.format("Failed to purge columnar tso: %d", minSnapshotTime), t); } + + try { + int updateRows = ColumnarTransactionUtils.updateColumnarPurgeWatermark(minSnapshotTime); + if (updateRows > 0) { + logger.warn(String.format("Update columnar purge watermark: %d", minSnapshotTime)); + } else { + logger.warn("Columnar purge watermark remains the same"); + } + } catch (Throwable t) { + logger.error(String.format("Failed to update columnar purge watermark: %d", minSnapshotTime), t); + } } catch (Throwable t) { logger.error("Columnar tso purge task failed unexpectedly!", t); } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/RotateGlobalTxLogTask.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/RotateGlobalTxLogTask.java index 14df34485..04d4a5ba9 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/RotateGlobalTxLogTask.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/RotateGlobalTxLogTask.java @@ -18,8 +18,8 @@ import com.alibaba.polardbx.common.IdGenerator; import com.alibaba.polardbx.common.jdbc.IDataSource; -import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.AsyncUtils; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; @@ -35,8 +35,6 @@ import java.util.ArrayList; import java.util.Calendar; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentLinkedQueue; @@ -44,7 +42,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Collectors; public class RotateGlobalTxLogTask implements Runnable { @@ -119,8 +116,9 @@ public void run() { logger.error("Interrupted when waiting XA recover task", e); } - if (TransactionManager.getInstance(schema).isFirstRecover()) { - // Still not finished, skip rotating trx log. + if (null == TransactionManager.getInstance(schema) || + TransactionManager.getInstance(schema).isFirstRecover()) { + // Still not finished, or db is dropped, skip rotating trx log. logger.warn("Wait XA recover task timeout, skip this round of trx log rotating."); return; } @@ -207,7 +205,7 @@ private int doRotate() { } try { - int count = GlobalTxLogManager.rotate(datasource, beforeTxid, nextTxid); + int count = GlobalTxLogManager.rotateWithTimeout(datasource, beforeTxid, nextTxid); purgedCount.addAndGet(count); } catch (Exception e) { logger.error("Rotate transaction log failed on group " @@ -229,7 +227,7 @@ private int doRotate() { globalLock.lock(); try { - int count = GlobalTxLogManager.rotate(datasource, beforeTxid, nextTxid); + int count = GlobalTxLogManager.rotateWithTimeout(datasource, beforeTxid, nextTxid); purgedCount.addAndGet(count); Thread.sleep(1000); } catch (Exception e) { diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/ScanBestEffortPreparedTask.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/ScanBestEffortPreparedTask.java index 0c7624b00..ce303baf6 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/ScanBestEffortPreparedTask.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/ScanBestEffortPreparedTask.java @@ -18,6 +18,7 @@ import com.alibaba.polardbx.common.jdbc.IConnection; import com.alibaba.polardbx.common.jdbc.IDataSource; +import com.alibaba.polardbx.common.type.TransactionType; import com.alibaba.polardbx.common.utils.Pair; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; @@ -28,7 +29,6 @@ import com.alibaba.polardbx.transaction.TransactionLogger; import com.alibaba.polardbx.transaction.TransactionManager; import com.alibaba.polardbx.transaction.TransactionState; -import com.alibaba.polardbx.common.type.TransactionType; import com.alibaba.polardbx.transaction.log.ConnectionContext; import com.alibaba.polardbx.transaction.log.GlobalTxLog; import com.alibaba.polardbx.transaction.log.GlobalTxLogManager; @@ -147,7 +147,7 @@ private boolean rollBackOrForward(PreparedBestEffortTrans trans, IConnection con final String primaryGroup = schemaAndGroup.getValue(); GlobalTxLogManager txLog = TransactionManager.getInstance(schema).getGlobalTxLogManager(); - GlobalTxLog tx = txLog.get(primaryGroup, trans.transId); + GlobalTxLog tx = txLog.getWithTimeout(primaryGroup, trans.transId); if (tx != null) { if (tx.getState() == TransactionState.ABORTED) { TransactionLogger.warn(tx.getTxid(), "Roll back best-effort transaction"); @@ -176,8 +176,8 @@ private boolean rollBackOrForward(PreparedBestEffortTrans trans, IConnection con // Write transaction log to the primary group of this transaction IDataSource dataSource = txLog.getTransactionExecutor().getGroupExecutor(primaryGroup).getDataSource(); try (IConnection conn2 = dataSource.getConnection()) { - txLog.append(trans.transId, TransactionType.BED, TransactionState.ABORTED, new ConnectionContext(), - conn2); + GlobalTxLogManager.appendWithSocketTimeout(trans.transId, TransactionType.BED, TransactionState.ABORTED, + new ConnectionContext(), conn2); // Successfully set the transaction to ABORT state, so roll it back TransactionLogger.warn(trans.transId, "Abort best-effort transaction and roll back"); return tryRollback(trans.transId, conn); diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/SyncPointTask.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/SyncPointTask.java new file mode 100644 index 000000000..fe1976aa4 --- /dev/null +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/SyncPointTask.java @@ -0,0 +1,29 @@ +package com.alibaba.polardbx.transaction.async; + +import com.alibaba.polardbx.common.trx.ISyncPointExecutor; +import com.alibaba.polardbx.common.utils.logger.Logger; +import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.utils.ExecUtils; + +import static com.alibaba.polardbx.gms.topology.SystemDbHelper.DEFAULT_DB_NAME; + +/** + * @author yaozhili + */ +public class SyncPointTask implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(SyncPointTask.class); + + @Override + public void run() { + if (!ExecUtils.hasLeadership(DEFAULT_DB_NAME)) { + return; + } + + ISyncPointExecutor executor = ExecutorContext.getContext(DEFAULT_DB_NAME).getSyncPointExecutor(); + boolean success = executor.execute(); + if (!success) { + logger.warn("Trigger sync point trx failed."); + } + } +} diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/SyncPointTaskWrapper.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/SyncPointTaskWrapper.java new file mode 100644 index 000000000..8910d4c65 --- /dev/null +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/SyncPointTaskWrapper.java @@ -0,0 +1,62 @@ +package com.alibaba.polardbx.transaction.async; + +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.transaction.utils.ParamValidationUtils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TimerTask; + +import static com.alibaba.polardbx.common.constants.ServerVariables.MODIFIABLE_SYNC_POINT_PARAM; + +public class SyncPointTaskWrapper extends BaseTimerTaskWrapper { + + public SyncPointTaskWrapper(Map properties, AsyncTaskQueue asyncTaskQueue) { + super(properties, asyncTaskQueue); + // Enable an active task when this timer task wrapper is created. + resetTask(); + } + + @Override + Set getParamsDef() { + return MODIFIABLE_SYNC_POINT_PARAM; + } + + @Override + void validateParams(Map newParams) { + for (Map.Entry keyAndVal : newParams.entrySet()) { + final String key = keyAndVal.getKey(); + final String val = keyAndVal.getValue(); + ParamValidationUtils.validateSyncPointParam(key, val); + } + } + + @Override + Map getNewParams() { + final Map newParam = new HashMap<>(2); + newParam.put(ConnectionProperties.ENABLE_SYNC_POINT, + String.valueOf(DynamicConfig.getInstance().isEnableSyncPoint())); + newParam.put(ConnectionProperties.SYNC_POINT_TASK_INTERVAL, + String.valueOf(DynamicConfig.getInstance().getSyncPointTaskInterval())); + return newParam; + } + + @Override + TimerTask createTask(Map newParam) { + if (ConfigDataMode.isFastMock()) { + return null; + } + + final boolean enable = DynamicConfig.getInstance().isEnableSyncPoint(); + if (!enable) { + return null; + } + + final long interval = Long.parseLong(newParam.get(ConnectionProperties.SYNC_POINT_TASK_INTERVAL)); + + return asyncTaskQueue.scheduleSyncPointTask(interval, getTask(new SyncPointTask())); + } +} diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/TransactionStatisticsTaskWrapper.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/TransactionStatisticsTaskWrapper.java index 638694762..85c8c6489 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/TransactionStatisticsTaskWrapper.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/TransactionStatisticsTaskWrapper.java @@ -69,7 +69,7 @@ public TimerTask createTask(Map newParam) { @Override protected Map getNewParams() { - final Map newParam = new HashMap<>(1); + final Map newParam = new HashMap<>(2); newParam.put(ConnectionProperties.TRANSACTION_STATISTICS_TASK_INTERVAL, String.valueOf(DynamicConfig.getInstance().getTransactionStatisticsTaskInterval())); newParam.put(ConnectionProperties.ENABLE_TRANSACTION_STATISTICS, diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/UpdateColumnarTsoTimerTask.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/UpdateColumnarTsoTimerTask.java index c349af5c1..d1cbb10e7 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/UpdateColumnarTsoTimerTask.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/UpdateColumnarTsoTimerTask.java @@ -16,11 +16,14 @@ package com.alibaba.polardbx.transaction.async; +import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; +import com.alibaba.polardbx.executor.gms.ColumnarManager; import com.alibaba.polardbx.executor.gms.util.ColumnarTransactionUtils; import com.alibaba.polardbx.executor.sync.ColumnarSnapshotUpdateSyncAction; import com.alibaba.polardbx.executor.sync.SyncManagerHelper; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.sync.SyncScope; import com.alibaba.polardbx.gms.topology.SystemDbHelper; import com.alibaba.polardbx.gms.util.SyncUtil; @@ -35,13 +38,20 @@ public void run() { if (!SyncUtil.isNodeWithSmallestId()) { return; } - - Long latestTso = ColumnarTransactionUtils.getLatestTsoFromGms(); - + Long latestTso; + int tsoUpdateDelay = InstConfUtil.getInt(ConnectionParams.COLUMNAR_TSO_UPDATE_DELAY); + if (tsoUpdateDelay > 0) { + latestTso = ColumnarTransactionUtils.getLatestTsoFromGmsWithDelay( + 1000L * tsoUpdateDelay // convert milliseconds to microseconds + ); + } else { + latestTso = ColumnarTransactionUtils.getLatestTsoFromGms(); + } logger.warn("update the columnar tso: " + latestTso); if (latestTso != null) { try { + ColumnarManager.getInstance().setLatestTso(latestTso); SyncManagerHelper.sync(new ColumnarSnapshotUpdateSyncAction(latestTso), SystemDbHelper.DEFAULT_DB_NAME, SyncScope.CURRENT_ONLY); } catch (Throwable t) { diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/XARecoverTask.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/XARecoverTask.java index a237d1e7a..15d0ad9bd 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/XARecoverTask.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/async/XARecoverTask.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.transaction.async; +import com.alibaba.polardbx.common.constants.TransactionAttribute; import com.alibaba.polardbx.common.eventlogger.EventLogger; import com.alibaba.polardbx.common.eventlogger.EventType; import com.alibaba.polardbx.common.exception.TddlRuntimeException; @@ -214,20 +215,31 @@ private void recoverInstance(IDataSource dataSource, Set groups) { Pair schemaAndGroup = serverConfigManager.findGroupByUniqueId(transInfo.primaryGroupUid, schemaAndGroupsCache); - if (2 == transInfo.formatId) { + TransactionAttribute.FormatId id = TransactionAttribute.FormatId.fromId((int) formatID); + if (null == id) { + continue; + } + switch (id) { + case NORMAL: + case ARCHIVE: + case IGNORE_BINLOG: + if (groups.contains(transInfo.getGroup()) || null == schemaAndGroup) { + PreparedXATrans entry = new PreparedXATrans(formatID, gtridLength, bqualLength, data); + preparedTrans.compute(transInfo.getGroup(), (gp, trans) -> { + if (trans == null) { + trans = new HashSet<>(); + } + trans.add(entry); + return trans; + }); + } + break; + case RECOVER: recoverTrans.add(new PreparedXATrans(formatID, gtridLength, bqualLength, data)); + break; + default: } - if (1 == transInfo.formatId && (groups.contains(transInfo.getGroup()) || null == schemaAndGroup)) { - PreparedXATrans entry = new PreparedXATrans(formatID, gtridLength, bqualLength, data); - preparedTrans.compute(transInfo.getGroup(), (gp, trans) -> { - if (trans == null) { - trans = new HashSet<>(); - } - trans.add(entry); - return trans; - }); - } } rs.close(); @@ -341,7 +353,7 @@ private boolean rollBackOrForward(PreparedXATrans trans, Statement stmt, XAUtils final String schema = schemaAndGroup.getKey(); final String primaryGroup = schemaAndGroup.getValue(); GlobalTxLogManager primaryGroupTxLogMgr = TransactionManager.getInstance(schema).getGlobalTxLogManager(); - GlobalTxLog txLog = primaryGroupTxLogMgr.get(primaryGroup, transInfo, schema); + GlobalTxLog txLog = primaryGroupTxLogMgr.getWithTimeout(primaryGroup, transInfo.transId); if (txLog != null) { /* Case 1: Trx log is found. @@ -370,7 +382,8 @@ private boolean rollBackOrForward(PreparedXATrans trans, Statement stmt, XAUtils // Process primary group first to check whether it is a v2 trx log. IDataSource primaryDatasource = primaryGroupTxLogMgr.getDatasource(primaryGroup); - GlobalTxLog v2TxLog = GlobalTxLogManager.getV2(primaryDatasource, transInfo.transId, supportAsyncCommit); + GlobalTxLog v2TxLog = + GlobalTxLogManager.getV2WithTimeout(primaryDatasource, transInfo.transId, supportAsyncCommit); assert primaryDatasource instanceof TGroupDataSource; String primaryId = ((TGroupDataSource) primaryDatasource).getMasterSourceAddress(); if (null == v2TxLog) { @@ -411,7 +424,7 @@ private boolean rollBackOrForward(PreparedXATrans trans, Statement stmt, XAUtils // Get async commit trx log from this DN. GlobalTxLog asyncCommitTxLog = - GlobalTxLogManager.getV2(groupDataSource, transInfo.transId, supportAsyncCommit); + GlobalTxLogManager.getV2WithTimeout(groupDataSource, transInfo.transId, supportAsyncCommit); if (null == asyncCommitTxLog) { noLogDataSources.add(groupDataSource); @@ -504,7 +517,9 @@ private boolean tryRollback(PreparedXATrans trans, Statement stmt, XAUtils.XATra } catch (SQLException ex) { logger.info("XA ROLLBACK error: " + ex.getMessage()); TransactionLogger.warn(id, "XA ROLLBACK error: {0} {1}", ex.getMessage(), trans.toXid()); - EventLogger.log(EventType.TRX_RECOVER, "XA ROLLBACK error for " + schema + ": " + ex.getMessage()); + if (!ex.getMessage().contains("Unknown XID")) { + EventLogger.log(EventType.TRX_RECOVER, "XA ROLLBACK error for " + schema + ": " + ex.getMessage()); + } errorCallback.run(); @@ -546,7 +561,7 @@ private boolean appendLogAndRollback(PreparedXATrans trans, Statement stmt, XAUt for (Pair logConn : logConns) { try { logConn.getKey().executeLater("xa begin " + logConn.getValue()); - GlobalTxLogManager.appendV2WithLockWaitTimeout(trxId, 0, logConn.getKey()); + GlobalTxLogManager.appendV2WithTimeout(trxId, 0, logConn.getKey()); } catch (Throwable t) { logger.error("Append aborted log to primary v2 commit log table failed", t); rollbackLogConns(logConns); @@ -567,7 +582,7 @@ private boolean appendLogAndRollback(PreparedXATrans trans, Statement stmt, XAUt try { conn.executeLater("xa begin " + xid); - GlobalTxLogManager.appendWithLockWaitTimeout(transInfo.transId, TransactionType.XA, + GlobalTxLogManager.appendWithTimeout(transInfo.transId, TransactionType.XA, TransactionState.ABORTED, new ConnectionContext(), conn); } catch (Throwable t) { logger.error("Append aborted log to normal commit log table failed", t); @@ -627,8 +642,8 @@ private boolean appendLogPrimaryAndRollback(PreparedXATrans trans, Statement stm try { conn.executeLater("xa begin " + xid); try { - GlobalTxLogManager.appendV2WithLockWaitTimeout(trxId, 0, conn); - GlobalTxLogManager.appendWithLockWaitTimeout(trxId, TransactionType.XA, + GlobalTxLogManager.appendV2WithTimeout(trxId, 0, conn); + GlobalTxLogManager.appendWithTimeout(trxId, TransactionType.XA, TransactionState.ABORTED, new ConnectionContext(), conn); } catch (com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException e) { // Duplicate entry. @@ -650,7 +665,7 @@ private boolean appendLogPrimaryAndRollback(PreparedXATrans trans, Statement stm conn.createStatement().execute("xa commit " + xid); } - String info = "[Async Commit][Recover] roll back TSO transaction " + transInfo.transId + String info = "[Recover] appendLogPrimaryAndRollback TSO transaction " + transInfo.transId + (error.get() ? " fail" : " succeed"); logger.info(info); TransactionLogger.warn(transInfo.transId, info); @@ -790,7 +805,9 @@ private static boolean tryCommit0(Statement stmt, String sql) { } catch (SQLException ex) { logger.error("XA COMMIT error", ex); TransactionLogger.error("XA COMMIT error", ex); - EventLogger.log(EventType.TRX_RECOVER, "Error executing " + sql + ": " + ex.getMessage()); + if (!ex.getMessage().contains("Unknown XID")) { + EventLogger.log(EventType.TRX_RECOVER, "Error executing " + sql + ": " + ex.getMessage()); + } if (ex.getErrorCode() == ErrorCode.ER_XAER_RMFAIL.getCode()) { return true; // Maybe not prepared yet. Ignore such exceptions } else if (ex.getErrorCode() == ErrorCode.ER_XAER_NOTA.getCode()) { diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/connection/TransactionConnectionHolder.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/connection/TransactionConnectionHolder.java index 14d21312b..d5187b901 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/connection/TransactionConnectionHolder.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/connection/TransactionConnectionHolder.java @@ -385,6 +385,8 @@ public IConnection getConnection(String schema, String group, Long grpConnId, ID boolean hasParticipant = hasParticipant(group, grpConnId); boolean shouldParticipate = shouldParticipateTransaction(rw, hasParticipant); boolean supportGroupMultiWrite = supportGroupMultiWriteConns(); + boolean needSetFlashbackArea = executionContext.isFlashbackArea() && rw == ITransaction.RW.READ + && executionContext.getStorageInfo(schema).isSupportFlashbackArea(); if (hasParticipant) { // // 如果已存在写连接 优先复用写连接 @@ -399,14 +401,16 @@ public IConnection getConnection(String schema, String group, Long grpConnId, ID //groupWriteConn = writeConns.get(0); groupWriteConn = writeConnCtx.getDefaultWriteConn(); if (reuseWriteConn(schema, group, rw, groupWriteConn)) { - return wrapWithAutoSavepoint(groupWriteConn.connection, rw); + return wrapWithAutoSavepoint(groupWriteConn.connection, rw) + .enableFlashbackArea(needSetFlashbackArea); } } else { HeldConnection freeWriteConn = findFreeWriteConn(group, grpConnId, writeConnCtx); if (freeWriteConn != null) { // Find free write conn from write conns if (reuseWriteConn(group, schema, rw, freeWriteConn)) { - return wrapWithAutoSavepoint(freeWriteConn.connection, rw); + return wrapWithAutoSavepoint(freeWriteConn.connection, rw) + .enableFlashbackArea(needSetFlashbackArea); } } else { // No find any free conn from write conns, all writeConns are using @@ -423,7 +427,8 @@ public IConnection getConnection(String schema, String group, Long grpConnId, ID final IConnection conn = reuseFreeReadConn(schema, group, grpConnId, groupHeldReadConns, freeReadConn, rw, shouldParticipate, ds); - return wrapWithAutoSavepoint(conn, rw); + return wrapWithAutoSavepoint(conn, rw) + .enableFlashbackArea(needSetFlashbackArea); } // Try to create new connection. @@ -432,7 +437,8 @@ public IConnection getConnection(String schema, String group, Long grpConnId, ID // Using extra connection final IConnection conn = beginTrxInNewConn(schema, group, null, ds, rw, groupHeldReadConns, shouldParticipate); - return wrapWithAutoSavepoint(conn, rw); + return wrapWithAutoSavepoint(conn, rw) + .enableFlashbackArea(needSetFlashbackArea); } if (groupHeldReadConns.size() >= 1) { if (shouldParticipate) { @@ -449,7 +455,8 @@ public IConnection getConnection(String schema, String group, Long grpConnId, ID final IConnection conn = beginTrxInNewConn(schema, group, grpConnId, ds, rw, groupHeldReadConns, shouldParticipate); - return wrapWithAutoSavepoint(conn, rw); + return wrapWithAutoSavepoint(conn, rw) + .enableFlashbackArea(needSetFlashbackArea); } finally { lock.unlock(); } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/jdbc/DeferredConnection.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/jdbc/DeferredConnection.java index a2d17f35e..3ae207ff2 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/jdbc/DeferredConnection.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/jdbc/DeferredConnection.java @@ -739,4 +739,15 @@ public void forceRollback() throws SQLException { conn.forceRollback(); } } + + @Override + public IConnection enableFlashbackArea(boolean enable) throws SQLException { + conn.enableFlashbackArea(enable); + return this; + } + + @Override + public void disableFlashbackArea() throws SQLException { + conn.disableFlashbackArea(); + } } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/log/GlobalTxLogManager.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/log/GlobalTxLogManager.java index a48027d50..ed0ccbab7 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/log/GlobalTxLogManager.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/log/GlobalTxLogManager.java @@ -39,8 +39,8 @@ import com.alibaba.polardbx.gms.config.impl.InstConfUtil; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.group.jdbc.TGroupDataSource; +import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; import com.alibaba.polardbx.rpc.compatible.XPreparedStatement; -import com.alibaba.polardbx.transaction.trx.AsyncCommitTransaction; import com.alibaba.polardbx.transaction.TransactionExecutor; import com.alibaba.polardbx.transaction.TransactionLogger; import com.alibaba.polardbx.transaction.TransactionManager; @@ -48,6 +48,7 @@ import com.alibaba.polardbx.transaction.utils.XAUtils; import com.google.protobuf.ByteString; import com.alibaba.polardbx.transaction.jdbc.DeferredConnection; +import com.alibaba.polardbx.transaction.trx.AsyncCommitTransaction; import java.sql.Connection; import java.sql.PreparedStatement; @@ -82,8 +83,10 @@ import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.SELECT_BY_ID_V2; import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.SELECT_BY_ID_V2_ARCHIVE; import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.SET_DISTRIBUTED_TRX_ID; +import static com.alibaba.polardbx.common.trx.TrxLogTableConstants.TRX_LOG_SOCKET_TIMEOUT; import static com.alibaba.polardbx.common.utils.LockUtil.wrapWithInnodbLockWaitTimeout; import static com.alibaba.polardbx.common.utils.LockUtil.wrapWithLockWaitTimeout; +import static com.alibaba.polardbx.common.utils.LockUtil.wrapWithSocketTimeout; public class GlobalTxLogManager extends AbstractLifecycle { @@ -118,6 +121,10 @@ public void doInit() { } } + public static String getCurrentServerAddr() { + return currentServerAddr; + } + public void setTransactionExecutor(TransactionExecutor executor) { this.executor = executor; } @@ -132,11 +139,11 @@ public TransactionExecutor getTransactionExecutor() { public boolean appendTrxLog(long txid, TransactionType type, TransactionState state, ConnectionContext context, IConnection conn) throws SQLException { if (0 == DynamicConfig.getInstance().getTrxLogMethod()) { - append(txid, type, state, context, conn); + appendWithSocketTimeout(txid, type, state, context, conn); return false; } else { // Use 1 to represent XA transaction. - appendV2(txid, 1, conn); + appendV2WithSocketTimeout(txid, 1, conn); long lastLogTime = TransactionAttribute.LAST_LOG_TRX_LOG_V2.get(); if (TransactionManager.shouldWriteEventLog(lastLogTime) && TransactionAttribute.LAST_LOG_TRX_LOG_V2.compareAndSet(lastLogTime, System.nanoTime())) { @@ -152,10 +159,10 @@ public boolean appendTrxLog(long txid, TransactionType type, TransactionState st public boolean appendTrxLog(long txid, TransactionType type, TransactionState state, ConnectionContext context, long commitTimestamp, IConnection conn) throws SQLException { if (0 == DynamicConfig.getInstance().getTrxLogMethod()) { - append(txid, type, state, context, commitTimestamp, conn); + appendWithSocketTimeout(txid, type, state, context, commitTimestamp, conn); return false; } else { - appendV2(txid, commitTimestamp, conn); + appendV2WithSocketTimeout(txid, commitTimestamp, conn); long lastLogTime = TransactionAttribute.LAST_LOG_TRX_LOG_V2.get(); if (TransactionManager.shouldWriteEventLog(lastLogTime) && TransactionAttribute.LAST_LOG_TRX_LOG_V2.compareAndSet(lastLogTime, System.nanoTime())) { @@ -165,8 +172,16 @@ public boolean appendTrxLog(long txid, TransactionType type, TransactionState st } } - public static void append(long txid, TransactionType type, TransactionState state, ConnectionContext context, - IConnection conn) throws SQLException { + public static void appendWithSocketTimeout(long txid, TransactionType type, TransactionState state, + ConnectionContext context, IConnection conn) throws SQLException { + wrapWithSocketTimeout(conn, TRX_LOG_SOCKET_TIMEOUT, TGroupDirectConnection.socketTimeoutExecutor, () -> { + append(txid, type, state, context, conn); + return null; + }); + } + + private static void append(long txid, TransactionType type, TransactionState state, ConnectionContext context, + IConnection conn) throws SQLException { try (PreparedStatement ps = conn.prepareStatement(APPEND_TRX)) { if (ps.isWrapperFor(XPreparedStatement.class)) { ps.unwrap(XPreparedStatement.class).setGalaxyDigest(APPEND_TRX_DIGEST); @@ -181,8 +196,17 @@ public static void append(long txid, TransactionType type, TransactionState stat } } - public static void append(long txid, TransactionType type, TransactionState state, ConnectionContext context, - long commitTimestamp, IConnection conn) throws SQLException { + public static void appendWithSocketTimeout(long txid, TransactionType type, TransactionState state, + ConnectionContext context, + long commitTimestamp, IConnection conn) throws SQLException { + wrapWithSocketTimeout(conn, TRX_LOG_SOCKET_TIMEOUT, TGroupDirectConnection.socketTimeoutExecutor, () -> { + append(txid, type, state, context, commitTimestamp, conn); + return null; + }); + } + + private static void append(long txid, TransactionType type, TransactionState state, ConnectionContext context, + long commitTimestamp, IConnection conn) throws SQLException { try (PreparedStatement ps = conn.prepareStatement(TrxLogTableConstants.APPEND_TRX_WITH_TS)) { if (ps.isWrapperFor(XPreparedStatement.class)) { ps.unwrap(XPreparedStatement.class).setGalaxyDigest(APPEND_TRX_WITH_TS_DIGEST); @@ -198,15 +222,14 @@ public static void append(long txid, TransactionType type, TransactionState stat } } - public static void appendWithLockWaitTimeout(long txid, TransactionType type, TransactionState state, - ConnectionContext context, - IConnection conn) throws SQLException { + public static void appendWithTimeout(long txid, TransactionType type, TransactionState state, + ConnectionContext context, IConnection conn) throws SQLException { AtomicReference exception = new AtomicReference<>(); wrapWithLockWaitTimeout(conn, 3, () -> { try { wrapWithInnodbLockWaitTimeout(conn, 3, () -> { try { - append(txid, type, state, context, conn); + appendWithSocketTimeout(txid, type, state, context, conn); } catch (SQLException e) { logger.error(e); exception.set(e); @@ -222,7 +245,15 @@ public static void appendWithLockWaitTimeout(long txid, TransactionType type, Tr } } - public static void appendV2(long txid, long commitTimestamp, IConnection conn) throws SQLException { + public static void appendV2WithSocketTimeout(long txid, long commitTimestamp, IConnection conn) + throws SQLException { + wrapWithSocketTimeout(conn, TRX_LOG_SOCKET_TIMEOUT, TGroupDirectConnection.socketTimeoutExecutor, () -> { + appendV2(txid, commitTimestamp, conn); + return null; + }); + } + + private static void appendV2(long txid, long commitTimestamp, IConnection conn) throws SQLException { try (PreparedStatement ps = conn.prepareStatement(TrxLogTableConstants.APPEND_TRX_V2)) { ps.setLong(1, txid); ps.setLong(2, commitTimestamp); @@ -247,8 +278,8 @@ private static void handleV2LogError() throws SQLException { // First error in 10 min, reset err cnt. appendV2FailedCnt.set(0); } - // 10 err occurs in the last 10 min, switch to legacy method for safety. - if (appendV2FailedCnt.incrementAndGet() == 10) { + // 100 errors occur in the last 10 min, switch to legacy method for safety. + if (appendV2FailedCnt.incrementAndGet() == 100) { try { if (0 == DynamicConfig.getInstance().getTrxLogMethod()) { return; @@ -268,14 +299,14 @@ public static void turnOffNewTrxLogMethod() throws SQLException { MetaDbUtil.setGlobal(properties); } - public static void appendV2WithLockWaitTimeout(long txid, long commitTimestamp, IConnection conn) + public static void appendV2WithTimeout(long txid, long commitTimestamp, IConnection conn) throws SQLException { AtomicReference exception = new AtomicReference<>(); wrapWithLockWaitTimeout(conn, 3, () -> { try { wrapWithInnodbLockWaitTimeout(conn, 3, () -> { try { - appendV2(txid, commitTimestamp, conn); + appendV2WithSocketTimeout(txid, commitTimestamp, conn); } catch (SQLException e) { logger.error(e); exception.set(e); @@ -293,124 +324,10 @@ public static void appendV2WithLockWaitTimeout(long txid, long commitTimestamp, } } - public GlobalTxLog get(String primaryGroup, XAUtils.XATransInfo transInfo, String schema) throws SQLException { - IDataSource dataSource = executor.getGroupExecutor(primaryGroup).getDataSource(); - try (IConnection conn = dataSource.getConnection()) { - if (TransactionManager.getInstance(schema).support2pcOpt()) { - try (Statement stmt = conn.createStatement()) { - ResultSet rs = stmt.executeQuery(String.format("call dbms_xa.find_by_xid('%s', '%s', 1)", - transInfo.gtrid, XAUtils.toBqualString(primaryGroup, 0L))); - if (rs.next()) { - String status = rs.getString("Status"); - String tso = rs.getString("GCN"); - String csr = rs.getString("CSR"); - - TransactionLogger.warn("Found 2pc opt trx log, status " + status + ", tso " + tso + ", csr " + csr - + ", gtrid " + transInfo.gtrid + ", bqual " + transInfo.trimedBqual); - - if ("ATTACHED".equalsIgnoreCase(status)) { - GlobalTxLog trans = new GlobalTxLog(); - trans.setGroup(primaryGroup); - trans.setTxid(transInfo.transId); - trans.setState(TransactionState.ATTACHED); - return trans; - } else if ("ROLLBACK".equalsIgnoreCase(status)) { - GlobalTxLog trans = new GlobalTxLog(); - trans.setGroup(primaryGroup); - trans.setTxid(transInfo.transId); - trans.setState(TransactionState.ABORTED); - return trans; - } else if ("COMMIT".equalsIgnoreCase(status)) { - GlobalTxLog trans = new GlobalTxLog(); - trans.setGroup(primaryGroup); - trans.setTxid(transInfo.transId); - if ("ASSIGNED_GCN".equalsIgnoreCase(csr)) { - trans.setType(TransactionType.TSO); - if (!"18446744073709551615".equals(tso)) { - trans.setCommitTimestamp(Long.valueOf(tso)); - } - } else { - trans.setType(TransactionType.XA); - } - trans.setState(TransactionState.SUCCEED); - return trans; - } - } - - rs = stmt.executeQuery(String.format("call dbms_xa.find_by_xid('%s', '%s', 1)", - transInfo.gtrid, XAUtils.toBqualString(primaryGroup))); - if (rs.next()) { - String status = rs.getString("Status"); - String tso = rs.getString("GCN"); - String csr = rs.getString("CSR"); - - TransactionLogger.warn("Found 2pc opt trx log, status " + status + ", tso " + tso + ", csr " + csr - + ", gtrid " + transInfo.gtrid + ", bqual " + transInfo.trimedBqual); - - if ("ATTACHED".equalsIgnoreCase(status)) { - GlobalTxLog trans = new GlobalTxLog(); - trans.setGroup(primaryGroup); - trans.setTxid(transInfo.transId); - trans.setState(TransactionState.ATTACHED); - return trans; - } else if ("ROLLBACK".equalsIgnoreCase(status)) { - GlobalTxLog trans = new GlobalTxLog(); - trans.setGroup(primaryGroup); - trans.setTxid(transInfo.transId); - trans.setState(TransactionState.ABORTED); - return trans; - } else if ("COMMIT".equalsIgnoreCase(status)) { - GlobalTxLog trans = new GlobalTxLog(); - trans.setGroup(primaryGroup); - trans.setTxid(transInfo.transId); - if ("ASSIGNED_GCN".equalsIgnoreCase(csr)) { - trans.setType(TransactionType.TSO); - if (!"18446744073709551615".equals(tso)) { - trans.setCommitTimestamp(Long.valueOf(tso)); - } - } else { - trans.setType(TransactionType.XA); - } - trans.setState(TransactionState.SUCCEED); - return trans; - } - } - } - } - - try (PreparedStatement ps = conn.prepareStatement(SELECT_BY_ID)) { - if (ps.isWrapperFor(XPreparedStatement.class)) { - ps.unwrap(XPreparedStatement.class).setGalaxyDigest(SELECT_BY_ID_DIGEST); - } - ps.setObject(1, new TableName(GLOBAL_TX_LOG_TABLE)); - ps.setLong(2, transInfo.transId); - try (ResultSet rs = ps.executeQuery()) { - if (rs.next()) { - GlobalTxLog trans = new GlobalTxLog(); - trans.setGroup(primaryGroup); - trans.setTxid(transInfo.transId); - trans.setType(TransactionType.valueOf(rs.getString(1))); - trans.setState(TransactionState.valueOf(rs.getString(2))); - trans.setServerAddr(rs.getString(3)); - trans.setContext(JSON.parseObject(rs.getString(4), ConnectionContext.class)); - long commitTimestamp = rs.getLong(5); - if (commitTimestamp > 0) { // zero for NULL - trans.setCommitTimestamp(commitTimestamp); - } - return trans; - } - } - } - } - return null; - } - - public GlobalTxLog get(String primaryGroup, long txid) throws SQLException { + public GlobalTxLog get(String primaryGroup, long txid, IConnection conn) throws SQLException { AtomicReference exception = new AtomicReference<>(); AtomicReference trans = new AtomicReference<>(); - IDataSource dataSource = executor.getGroupExecutor(primaryGroup).getDataSource(); - try (IConnection conn = dataSource.getConnection(); - PreparedStatement ps = conn.prepareStatement(SELECT_BY_ID)) { + try (PreparedStatement ps = conn.prepareStatement(SELECT_BY_ID)) { wrapWithLockWaitTimeout(conn, 3, () -> { try { if (ps.isWrapperFor(XPreparedStatement.class)) { @@ -446,14 +363,29 @@ public GlobalTxLog get(String primaryGroup, long txid) throws SQLException { return trans.get(); } + public GlobalTxLog getWithTimeout(String primaryGroup, long txid) throws SQLException { + IDataSource dataSource = executor.getGroupExecutor(primaryGroup).getDataSource(); + try (IConnection conn = dataSource.getConnection()) { + return wrapWithSocketTimeout(conn, TRX_LOG_SOCKET_TIMEOUT, TGroupDirectConnection.socketTimeoutExecutor, + () -> get(primaryGroup, txid, conn)); + } + } + + public static GlobalTxLog getV2WithTimeout(IDataSource dataSource, long txid, boolean dn57) throws SQLException { + try (DeferredConnection conn = new DeferredConnection(dataSource.getConnection(), + InstConfUtil.getBool(ConnectionParams.USING_RDS_RESULT_SKIP))) { + return wrapWithSocketTimeout(conn, TRX_LOG_SOCKET_TIMEOUT, TGroupDirectConnection.socketTimeoutExecutor, + () -> getV2(conn, txid, dn57)); + } + } + /** * Get trx log V2, either an async commit log, or a new trx log. */ - public static GlobalTxLog getV2(IDataSource dataSource, long txid, boolean dn57) throws SQLException { + public static GlobalTxLog getV2(DeferredConnection conn, long txid, boolean dn57) throws SQLException { AtomicReference exception = new AtomicReference<>(); AtomicReference trans = new AtomicReference<>(); - try (DeferredConnection conn = new DeferredConnection(dataSource.getConnection(), - InstConfUtil.getBool(ConnectionParams.USING_RDS_RESULT_SKIP))) { + try { wrapWithLockWaitTimeout(conn, 3, () -> { try (Statement stmt = conn.createStatement()) { conn.executeLater("begin"); @@ -510,6 +442,8 @@ public static GlobalTxLog getV2(IDataSource dataSource, long txid, boolean dn57) } } }); + } catch (Throwable t) { + throw t; } // Re-throw error. @@ -519,8 +453,19 @@ public static GlobalTxLog getV2(IDataSource dataSource, long txid, boolean dn57) return trans.get(); } - public static int rotate(IDataSource dataSource, long beforeTxid, long nextTxid) { + public static int rotateWithTimeout(IDataSource dataSource, long beforeTxid, long nextTxid) { try (IConnection connection = dataSource.getConnection()) { + return wrapWithSocketTimeout(connection, TRX_LOG_SOCKET_TIMEOUT, + TGroupDirectConnection.socketTimeoutExecutor, + () -> rotate(connection, beforeTxid, nextTxid)); + } catch (Throwable e) { + throw new TddlRuntimeException(ErrorCode.ERR_TRANS_LOG, e, + "Rotate global transaction log with " + beforeTxid + " failed"); + } + } + + public static int rotate(IConnection connection, long beforeTxid, long nextTxid) { + try { AtomicLong dropped = new AtomicLong(); LockUtil.wrapWithLockWaitTimeout(connection, 10, () -> { try (Statement stmt = connection.createStatement()) { @@ -566,6 +511,7 @@ public static int rotate(IDataSource dataSource, long beforeTxid, long nextTxid) TransactionLogger.error("Rotate global transaction log with " + beforeTxid + " failed", e); } }); + return dropped.intValue(); } catch (SQLException e) { throw new TddlRuntimeException(ErrorCode.ERR_TRANS_LOG, e, @@ -574,15 +520,29 @@ public static int rotate(IDataSource dataSource, long beforeTxid, long nextTxid) } public static void createTables(IDataSource dataSource, long initTxid, Set dnSet) { - try (Connection conn = dataSource.getConnection(); - Statement stmt = conn.createStatement()) { - String instanceId = ((TGroupDataSource) dataSource).getMasterSourceAddress(); - if (dnSet.add(instanceId)) { - // One table only for each DN. - createGlobalTxLogTableV2(stmt); + AtomicReference exception = new AtomicReference<>(null); + try (Connection conn = dataSource.getConnection()) { + wrapWithSocketTimeout(conn, TRX_LOG_SOCKET_TIMEOUT, TGroupDirectConnection.socketTimeoutExecutor, () -> { + wrapWithLockWaitTimeout(conn, 10, () -> { + String instanceId = ((TGroupDataSource) dataSource).getMasterSourceAddress(); + try (Statement stmt = conn.createStatement()) { + if (dnSet.add(instanceId)) { + // One table only for each DN. + createGlobalTxLogTableV2(stmt); + } + createGlobalTxLogTable(stmt, initTxid); + createRedoLogTable(stmt); + } catch (SQLException t) { + exception.set(t); + } + }); + return null; + }); + + if (null != exception.get()) { + // Rethrow exception. + throw exception.get(); } - createGlobalTxLogTable(stmt, initTxid); - createRedoLogTable(stmt); } catch (SQLException ex) { throw new TddlRuntimeException(ErrorCode.ERR_TRANS_LOG, ex, "Failed to create transaction log tables: " + ex.getMessage()); @@ -592,7 +552,7 @@ public static void createTables(IDataSource dataSource, long initTxid, Set { if (fetchSql) { result.addRow(new Object[] { - tran.getId(), group, connId, frontendConnId, tran.getStartTimeInMs(), sqlSubString}); + tran.getId(), group, connId, frontendConnId, tran.getStartTimeInMs(), sqlSubString, isDdl}); } else { - result.addRow(new Object[] {tran.getId(), group, connId, frontendConnId, tran.getStartTimeInMs()}); + result.addRow( + new Object[] {tran.getId(), group, connId, frontendConnId, tran.getStartTimeInMs(), isDdl}); } }); } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/sync/FetchTransForDeadlockDetectionSyncAction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/sync/FetchTransForDeadlockDetectionSyncAction.java index 6000dddd5..bb0f559c9 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/sync/FetchTransForDeadlockDetectionSyncAction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/sync/FetchTransForDeadlockDetectionSyncAction.java @@ -20,12 +20,15 @@ import com.alibaba.polardbx.executor.cursor.ResultCursor; import com.alibaba.polardbx.executor.cursor.impl.ArrayResultCursor; import com.alibaba.polardbx.executor.sync.ISyncAction; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.core.datatype.DataTypes; import com.alibaba.polardbx.optimizer.utils.ITransaction; import com.alibaba.polardbx.transaction.TransactionManager; import java.util.Collection; +import static com.alibaba.polardbx.optimizer.utils.ExecutionPlanProperties.DDL_STATEMENT; + /** * @author zhuangtianyi */ @@ -51,6 +54,7 @@ public ResultCursor sync() { result.addColumn("FRONTEND_CONN_ID", DataTypes.LongType); result.addColumn("START_TIME", DataTypes.LongType); result.addColumn("SQL", DataTypes.StringType); + result.addColumn("DDL", DataTypes.BooleanType); final long beforeTimeMillis = System.currentTimeMillis() - 1000L; final long beforeTxid = IdGenerator.assembleId(beforeTimeMillis, 0, 0); @@ -66,6 +70,9 @@ public ResultCursor sync() { long frontendConnId = tran.getExecutionContext().getConnId(); final String sql = tran.getExecutionContext().getOriginSql(); final String truncatedSql = (sql == null) ? "" : sql.substring(0, Math.min(sql.length(), 4096)); + ExecutionContext ec = tran.getExecutionContext(); + final boolean isDdl; + isDdl = null != ec && null != ec.getFinalPlan() && ec.getFinalPlan().is(DDL_STATEMENT); tran.getConnectionHolder().handleConnIds((group, connId) -> { result.addRow(new Object[] { @@ -74,7 +81,8 @@ public ResultCursor sync() { connId, frontendConnId, tran.getStartTimeInMs(), - truncatedSql}); + truncatedSql, + isDdl}); }); } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AbstractTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AbstractTransaction.java index 870627a72..1a1d61326 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AbstractTransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AbstractTransaction.java @@ -65,6 +65,7 @@ import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.StampedLock; import java.util.regex.Pattern; @@ -628,6 +629,10 @@ protected final void beforeWriteCommitLog() { protected final Collection> acquireSharedLock() { // Acquire lock of primary schema. List> locks = new ArrayList<>(otherSchemas.size() + 1); + if (null == primarySchema) { + // This transaction has no write connection, so no need to acquire distributed lock. + return locks; + } acquireSchemaLock(locks, primarySchema); // Acquire locks of other schemas. for (String schema : otherSchemas) { @@ -665,6 +670,35 @@ public boolean isDistributed() { return true; } + @Override + public void clearFlashbackArea() { + try { + AtomicReference error = new AtomicReference<>(null); + forEachHeldConnection(new TransactionConnectionHolder.Action() { + @Override + public boolean condition(TransactionConnectionHolder.HeldConnection heldConn) { + // For all connections. + return true; + } + + @Override + public void execute(TransactionConnectionHolder.HeldConnection heldConn) { + try { + heldConn.getRawConnection().disableFlashbackArea(); + } catch (Throwable t) { + error.set(t); + } + } + }); + if (null != error.get()) { + throw error.get(); + } + } catch (Throwable t) { + // For safety, prevent trx from continuing. + setCrucialError(ErrorCode.ERR_FLASHBACK_AREA, t.getMessage()); + } + } + @Override public boolean handleStatementError(Throwable t) { lock.lock(); diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AsyncCommitTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AsyncCommitTransaction.java index 381e49ce9..0532969c7 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AsyncCommitTransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AsyncCommitTransaction.java @@ -21,7 +21,6 @@ import com.alibaba.polardbx.common.jdbc.IConnection; import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; import com.alibaba.polardbx.common.properties.ConnectionParams; -import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.common.utils.thread.LockUtils; @@ -188,8 +187,7 @@ protected void prepareParticipatedConn(TransactionConnectionHolder.HeldConnectio } catch (Throwable e) { final IConnection conn = heldConn.getRawConnection(); final String group = heldConn.getGroup(); - throw new TddlRuntimeException(ERR_TRANS_COMMIT, e, - "XA PREPARE failed: " + getXid(group, conn)); + throw new TddlRuntimeException(ERR_TRANS_COMMIT, e, "XA PREPARE failed: " + getXid(group, conn)); } } @@ -256,7 +254,8 @@ public void execute(TransactionConnectionHolder.HeldConnection heldConn) { }); } - private void commitOneBranch(TransactionConnectionHolder.HeldConnection heldConn) { + @Override + protected void beforeCommitOneBranchHook(TransactionConnectionHolder.HeldConnection heldConn) { IConnection conn = heldConn.getRawConnection(); if (heldConn.isDnLeader()) { try { @@ -267,31 +266,6 @@ private void commitOneBranch(TransactionConnectionHolder.HeldConnection heldConn throw new TddlRuntimeException(ERR_TRANS_COMMIT, e); } } - - // XA transaction must be 'PREPARED' state here. - String xid = getXid(heldConn.getGroup(), conn); - try (Statement stmt = conn.createStatement()) { - try { - final XConnection xConnection; - if (conn.isWrapperFor(XConnection.class) && - (xConnection = conn.unwrap(XConnection.class)).supportMessageTimestamp()) { - conn.flushUnsent(); - xaCommitXConn(xConnection, xid); - } else { - stmt.execute(getXACommitWithTsoSql(xid)); - } - heldConn.setCommitted(true); - } catch (SQLException ex) { - if (ex.getErrorCode() == ErrorCode.ER_XAER_NOTA.getCode()) { - logger.warn("XA COMMIT got ER_XAER_NOTA: " + xid, ex); - } else { - throw GeneralUtil.nestedException(ex); - } - } - } catch (Throwable e) { - // discard connection if something failed. - conn.discard(e); - } } private void commitConnectionsAsyncInner() { diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AutoCommitSingleShardTsoTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AutoCommitSingleShardTsoTransaction.java index cd42c908e..995ac5a16 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AutoCommitSingleShardTsoTransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AutoCommitSingleShardTsoTransaction.java @@ -92,7 +92,8 @@ public IConnection getConnection(String schemaName, String group, IDataSource ds sendSnapshotSeq(conn); } - return conn; + boolean needSetFlashbackArea = executionContext.isFlashbackArea() && rw == ITransaction.RW.READ; + return conn.enableFlashbackArea(needSetFlashbackArea); } @Override diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AutoCommitTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AutoCommitTransaction.java index 87970ff51..0af606865 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AutoCommitTransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/AutoCommitTransaction.java @@ -35,10 +35,11 @@ import com.alibaba.polardbx.optimizer.OptimizerContext; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.utils.IConnectionHolder; +import com.alibaba.polardbx.optimizer.utils.ITransaction; import com.alibaba.polardbx.rpc.pool.XConnection; import com.alibaba.polardbx.stats.TransactionStatistics; -import com.alibaba.polardbx.transaction.connection.AutoCommitConnectionHolder; import com.alibaba.polardbx.transaction.async.AsyncTaskQueue; +import com.alibaba.polardbx.transaction.connection.AutoCommitConnectionHolder; import org.checkerframework.checker.nullness.qual.Nullable; import java.sql.SQLException; @@ -77,9 +78,15 @@ public TransactionType getType() { @Override public IConnection getConnection(String schemaName, String groupName, IDataSource ds, RW rw, ExecutionContext ec) throws SQLException { + if (rw.equals(RW.WRITE) && executionContext.isEnableExternalConsistencyForWriteTrx() && ec.isUserSql()) { + throw new TddlRuntimeException(ErrorCode.ERR_TRANS, + "Should not get write connection when ENABLE_EXTERNAL_CONSISTENCY_FOR_WRITE_TRX is true"); + } MasterSlave masterSlave = ExecUtils.getMasterSlave(false, rw.equals(RW.WRITE), ec); IConnection connection = getRealConnection(schemaName, groupName, ds, masterSlave); - return sendLsn(connection, schemaName, groupName, masterSlave, () -> -1L); + boolean needSetFlashbackArea = executionContext.isFlashbackArea() && rw == ITransaction.RW.READ; + return sendLsn(connection, schemaName, groupName, masterSlave, () -> -1L) + .enableFlashbackArea(needSetFlashbackArea); } protected IConnection getRealConnection( @@ -179,7 +186,7 @@ public void close() { //We should execute rollback before recycle the connections into pool. The reasons as followed: //1. releases any database locks currently held for TSO_READONLY&AUTO_COMMIT_SINGLE_SHARD; //2. check the connection is used by other users or not, thus the rollback will failed. we will - //disard the connection. + //discard the connection. AsyncTaskQueue asyncQueue = getManager().getTransactionExecutor().getAsyncQueue(); try { ch.forEachConnection(asyncQueue, (conn) -> { diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/BaseTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/BaseTransaction.java index 56f06a4b2..704328636 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/BaseTransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/BaseTransaction.java @@ -251,7 +251,9 @@ public InventoryMode getInventoryMode() { @Override public void setInventoryMode(InventoryMode inventoryMode) { if (inventoryMode != null && !getTransactionClass().isA(SUPPORT_INVENTORY_TRANSACTION)) { - throw new UnsupportedOperationException("Don't support the Inventory Hint on current Transaction Policy!"); + throw new UnsupportedOperationException( + "Don't support the Inventory Hint on current Transaction Policy, current transaction type is " + + getTransactionClass()); } else { this.inventoryMode = inventoryMode; } @@ -315,11 +317,16 @@ private void updateStatisticsWhenClosed() { return; } + if (stat.startTime <= 0) { + return; + } + stat.durationTime = System.nanoTime() - stat.startTime; final long durationTimeInMs = stat.durationTime / 1000000; if (DynamicConfig.getInstance().isEnableTransactionStatistics() - && DynamicConfig.getInstance().getSlowTransThreshold() < durationTimeInMs) { + && DynamicConfig.getInstance().getSlowTransThreshold() < durationTimeInMs + && executionContext.isUserSql()) { stat.finishTimeInMs = stat.startTimeInMs + durationTimeInMs; stat.readOnly = !isRwTransaction(); stat.transactionType = getType(); diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/BestEffortTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/BestEffortTransaction.java index bb667ac57..2d7eed90f 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/BestEffortTransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/BestEffortTransaction.java @@ -28,10 +28,10 @@ import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.common.utils.thread.LockUtils; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.transaction.connection.TransactionConnectionHolder; import com.alibaba.polardbx.transaction.TransactionLogger; import com.alibaba.polardbx.transaction.TransactionManager; import com.alibaba.polardbx.transaction.TransactionState; +import com.alibaba.polardbx.transaction.connection.TransactionConnectionHolder; import com.alibaba.polardbx.transaction.jdbc.SavePoint; import com.alibaba.polardbx.transaction.log.GlobalTxLogManager; import com.alibaba.polardbx.transaction.log.RedoLogManager; @@ -147,7 +147,8 @@ private void commitCrossGroupTrans() { * 写入 global_tx_log 状态为 SUCCEED (还未提交) */ try { - GlobalTxLogManager.append(id, getType(), TransactionState.SUCCEED, connectionContext, primaryConnection); + GlobalTxLogManager.appendWithSocketTimeout(id, getType(), TransactionState.SUCCEED, connectionContext, + primaryConnection); } catch (SQLIntegrityConstraintViolationException ex) { // 被抢占 Rollback 了,停止提交 throw new TddlRuntimeException(ErrorCode.ERR_TRANS, "Transaction ID exists. Commit interrupted"); diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/ITsoTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/ITsoTransaction.java index 0af9119c4..9b21360ce 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/ITsoTransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/ITsoTransaction.java @@ -37,7 +37,8 @@ public interface ITsoTransaction extends IMppTsoTransaction { TransactionManager getManager(); @Override - default long nextTimestamp(Consumer updateGetTsoTime) { + default long + nextTimestamp(Consumer updateGetTsoTime) { long getTsoStartTime = System.nanoTime(); long tso = getManager().getTimestampOracle().nextTimestamp(); updateGetTsoTime.accept(System.nanoTime() - getTsoStartTime); diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/IgnoreBinlogTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/IgnoreBinlogTransaction.java new file mode 100644 index 000000000..6ea2771bf --- /dev/null +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/IgnoreBinlogTransaction.java @@ -0,0 +1,50 @@ +package com.alibaba.polardbx.transaction.trx; + +import com.alibaba.polardbx.common.jdbc.IConnection; +import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.transaction.TransactionManager; +import com.alibaba.polardbx.transaction.utils.XAUtils; + +/** + * This transaction is used for archive operations, its xa format id is 3. + * + * @author yaozhili + */ +public class IgnoreBinlogTransaction extends TsoTransaction { + private final static long IGNORE_BINLOG_FORMAT_ID = 4; + private final static String TRX_LOG_PREFIX = + "[" + ITransactionPolicy.TransactionClass.IGNORE_BINLOG_TRANSACTION + "]"; + + public IgnoreBinlogTransaction(ExecutionContext executionContext, + TransactionManager manager) { + super(executionContext, manager); + } + + @Override + protected String getXid(String group, IConnection conn) { + if (conn.getTrxXid() != null) { + return conn.getTrxXid(); + } + conn.setInShareReadView(shareReadView); + String xid; + if (shareReadView) { + xid = XAUtils.toXidStringWithFormatId(id, group, primaryGroupUid, getReadViewSeq(group), + IGNORE_BINLOG_FORMAT_ID); + } else { + xid = XAUtils.toXidStringWithFormatId(id, group, primaryGroupUid, IGNORE_BINLOG_FORMAT_ID); + } + conn.setTrxXid(xid); + return xid; + } + + @Override + public ITransactionPolicy.TransactionClass getTransactionClass() { + return ITransactionPolicy.TransactionClass.IGNORE_BINLOG_TRANSACTION; + } + + @Override + protected String getTrxLoggerPrefix() { + return TRX_LOG_PREFIX; + } +} diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/MppReadOnlyTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/MppReadOnlyTransaction.java index 53317b194..b57f8a403 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/MppReadOnlyTransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/MppReadOnlyTransaction.java @@ -29,6 +29,7 @@ import com.alibaba.polardbx.executor.utils.ExecUtils; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.optimizer.utils.IMppReadOnlyTransaction; +import com.alibaba.polardbx.optimizer.utils.ITransaction; import com.alibaba.polardbx.transaction.jdbc.DeferredConnection; import java.sql.SQLException; @@ -106,7 +107,8 @@ public IConnection getConnection(String schemaName, String groupName, IDataSourc } else { sendSnapshotSeq(connection); } - return connection; + boolean needSetFlashbackArea = executionContext.isFlashbackArea() && rw == ITransaction.RW.READ; + return connection.enableFlashbackArea(needSetFlashbackArea); } @Override diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/ReadOnlyTsoTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/ReadOnlyTsoTransaction.java index 3c49b6028..78a2cb0f3 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/ReadOnlyTsoTransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/ReadOnlyTsoTransaction.java @@ -117,7 +117,9 @@ public IConnection getConnection(String schemaName, String group, IDataSource ds } conn = sendLsn(conn, schemaName, group, masterSlave, this::getSnapshotSeq); sendSnapshotSeq(conn); - return conn; + + boolean needSetFlashbackArea = executionContext.isFlashbackArea() && rw == ITransaction.RW.READ; + return conn.enableFlashbackArea(needSetFlashbackArea); } @Override diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/SyncPointTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/SyncPointTransaction.java new file mode 100644 index 000000000..7169784ab --- /dev/null +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/SyncPointTransaction.java @@ -0,0 +1,136 @@ +package com.alibaba.polardbx.transaction.trx; + +import com.alibaba.polardbx.common.exception.TddlRuntimeException; +import com.alibaba.polardbx.common.exception.code.ErrorCode; +import com.alibaba.polardbx.common.jdbc.IConnection; +import com.alibaba.polardbx.common.utils.GeneralUtil; +import com.alibaba.polardbx.common.utils.thread.LockUtils; +import com.alibaba.polardbx.optimizer.OptimizerContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.rpc.pool.XConnection; +import com.alibaba.polardbx.stats.TransactionStatistics; +import com.alibaba.polardbx.transaction.TransactionManager; +import com.alibaba.polardbx.transaction.connection.TransactionConnectionHolder; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author wuzhe + */ +public class SyncPointTransaction extends TsoTransaction { + private final static String MARK_SYNC_POINT_SQL = "set enable_polarx_mark_sync_point = true"; + private final AtomicInteger commitPartitions = new AtomicInteger(0); + + public SyncPointTransaction(ExecutionContext executionContext, + TransactionManager manager) { + super(executionContext, manager); + } + + @Override + public void commit() { + long commitStartTime = System.nanoTime(); + lock.lock(); + try { + checkTerminated(); + checkCanContinue(); + + Optional.ofNullable(OptimizerContext.getTransStat(primarySchema)) + .ifPresent(s -> s.countCrossGroup.incrementAndGet()); + + this.txSharedLocks = acquireSharedLock(); + try { + // Force commit in complete 2PC process. + commitMultiShardTrx(); + } finally { + LockUtils.releaseReadStampLocks(txSharedLocks); + } + } catch (Throwable t) { + Optional.ofNullable(OptimizerContext.getTransStat(statisticSchema)) + .ifPresent(s -> s.countCommitError.incrementAndGet()); + stat.setIfUnknown(TransactionStatistics.Status.COMMIT_FAIL); + throw t; + } finally { + stat.setIfUnknown(TransactionStatistics.Status.COMMIT); + stat.commitTime = System.nanoTime() - commitStartTime; + lock.unlock(); + } + } + + @Override + protected void beforeCommitOneBranchHook(TransactionConnectionHolder.HeldConnection heldConn) { + IConnection conn = heldConn.getRawConnection(); + try { + conn.executeLater(MARK_SYNC_POINT_SQL); + } catch (SQLException ex) { + throw GeneralUtil.nestedException(ex); + } + } + + @Override + protected void executeXaCommit(IConnection conn, String xid, Statement stmt) { + try { + if (conn.isWrapperFor(XConnection.class)) { + XConnection xConnection = conn.unwrap(XConnection.class); + conn.unwrap(XConnection.class).getSession().setChunkResult(false); + // X-Connection pipeline. + conn.flushUnsent(); + xConnection.setLazyCommitSeq(commitTimestamp); + try (Statement xStmt = xConnection.createStatement(); + ResultSet rs = xStmt.executeQuery("XA COMMIT " + xid);) { + if (-1 != commitPartitions.get() && rs.next() && 0 == rs.getInt(1)) { + // Commit sync point successfully. + commitPartitions.getAndIncrement(); + } else { + // Commit failed. + commitPartitions.set(-1); + } + } + if (shareReadView) { + xConnection.execUpdate(TURN_OFF_TXN_GROUP_SQL, null, true); + } + } else { + // JDBC multi-statement. + stmt.execute(getXACommitWithTsoSql(xid)); + + if (stmt.getMoreResults()) { + try (ResultSet rs = stmt.getResultSet()) { + if (-1 != commitPartitions.get() && rs.next() && 0 == rs.getInt(1)) { + // Commit sync point successfully. + commitPartitions.getAndIncrement(); + } else { + // Commit failed. + commitPartitions.set(-1); + } + } + } else { + throw new TddlRuntimeException(ErrorCode.ERR_TRANS_COMMIT, + "XA COMMIT failed: " + xid + ", not found result set for xa commit sync point"); + } + + if (stmt.getMoreResults()) { + throw new TddlRuntimeException(ErrorCode.ERR_TRANS_COMMIT, + "XA COMMIT failed: " + xid + ", found result set for set innodb_transaction_group"); + } + + if (stmt.getMoreResults() || stmt.getUpdateCount() != -1) { + throw new TddlRuntimeException(ErrorCode.ERR_TRANS_COMMIT, + "XA COMMIT failed: " + xid + ", found more than 3 results"); + } + } + } catch (Throwable t) { + throw new TddlRuntimeException(ErrorCode.ERR_TRANS_COMMIT, t, "XA COMMIT failed: " + xid); + } + } + + public int getNumberOfPartitions() { + return commitPartitions.get(); + } + + public long getCommitTso() { + return commitTimestamp; + } +} diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/TsoTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/TsoTransaction.java index 949fab12c..b30fc4e71 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/TsoTransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/TsoTransaction.java @@ -362,20 +362,24 @@ public void execute(TransactionConnectionHolder.HeldConnection heldConn) { }); } - private void commitOneBranch(TransactionConnectionHolder.HeldConnection heldConn) { + /** + * Before sending commit_seq and xa commit, do something in this connection. + * Useful for some trx with TSO features. + */ + protected void beforeCommitOneBranchHook(TransactionConnectionHolder.HeldConnection heldConn) { + } + + /** + * Commit a single trx branch in a connection. + */ + protected void commitOneBranch(TransactionConnectionHolder.HeldConnection heldConn) { + beforeCommitOneBranchHook(heldConn); IConnection conn = heldConn.getRawConnection(); // XA transaction must be 'PREPARED' state here. String xid = getXid(heldConn.getGroup(), conn); try (Statement stmt = conn.createStatement()) { try { - final XConnection xConnection; - if (conn.isWrapperFor(XConnection.class) && - (xConnection = conn.unwrap(XConnection.class)).supportMessageTimestamp()) { - conn.flushUnsent(); - xaCommitXConn(xConnection, xid); - } else { - stmt.execute(getXACommitWithTsoSql(xid)); - } + executeXaCommit(conn, xid, stmt); heldConn.setCommitted(true); } catch (SQLException ex) { if (ex.getErrorCode() == ErrorCode.ER_XAER_NOTA.getCode()) { @@ -387,14 +391,26 @@ private void commitOneBranch(TransactionConnectionHolder.HeldConnection heldConn } catch (Throwable e) { // discard connection if something failed. conn.discard(e); + throw new TddlRuntimeException(ERR_TRANS_COMMIT, e, + "XA COMMIT failed: " + getXid(heldConn.getGroup(), conn)); } } - protected void xaCommitXConn(XConnection xConnection, String xid) throws SQLException { - xConnection.setLazyCommitSeq(commitTimestamp); - xConnection.execUpdate("XA COMMIT " + xid); - if (shareReadView) { - xConnection.execUpdate(TURN_OFF_TXN_GROUP_SQL, null, true); + /** + * Send innodb_commit_seq and execute XA COMMIT [xid]. + */ + protected void executeXaCommit(IConnection conn, String xid, Statement stmt) throws SQLException { + final XConnection xConnection; + if (conn.isWrapperFor(XConnection.class) && + (xConnection = conn.unwrap(XConnection.class)).supportMessageTimestamp()) { + conn.flushUnsent(); + xConnection.setLazyCommitSeq(commitTimestamp); + xConnection.execUpdate("XA COMMIT " + xid); + if (shareReadView) { + xConnection.execUpdate(TURN_OFF_TXN_GROUP_SQL, null, true); + } + } else { + stmt.execute(getXACommitWithTsoSql(xid)); } } @@ -419,4 +435,8 @@ public ITransactionPolicy.TransactionClass getTransactionClass() { return ITransactionPolicy.TransactionClass.TSO; } + public long getCommitTso() { + return commitTimestamp; + } + } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/XATransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/XATransaction.java index 09a4b4446..4498e3955 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/XATransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/XATransaction.java @@ -25,11 +25,11 @@ import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; import com.alibaba.polardbx.optimizer.context.ExecutionContext; -import com.alibaba.polardbx.transaction.connection.TransactionConnectionHolder; import com.alibaba.polardbx.transaction.TransactionLogger; import com.alibaba.polardbx.transaction.TransactionManager; import com.alibaba.polardbx.transaction.TransactionState; import com.alibaba.polardbx.transaction.async.AsyncTaskQueue; +import com.alibaba.polardbx.transaction.connection.TransactionConnectionHolder; import com.alibaba.polardbx.transaction.jdbc.SavePoint; import com.alibaba.polardbx.transaction.utils.XAUtils; @@ -52,6 +52,10 @@ public class XATransaction extends ShareReadViewTransaction { public XATransaction(ExecutionContext executionContext, TransactionManager manager) { super(executionContext, manager); + if (executionContext.isEnableExternalConsistencyForWriteTrx() && executionContext.isUserSql()) { + throw new TddlRuntimeException(ErrorCode.ERR_TRANS, + "Should not create XATransaction when ENABLE_EXTERNAL_CONSISTENCY_FOR_WRITE_TRX is true"); + } } @Override diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/XATsoTransaction.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/XATsoTransaction.java index 2fa0562b4..4d105a6e7 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/XATsoTransaction.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/trx/XATsoTransaction.java @@ -21,22 +21,16 @@ import com.alibaba.polardbx.common.eventlogger.EventType; import com.alibaba.polardbx.common.jdbc.IConnection; import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; -import com.alibaba.polardbx.common.properties.ConnectionParams; import com.alibaba.polardbx.common.properties.ConnectionProperties; -import com.alibaba.polardbx.common.properties.DynamicConfig; import com.alibaba.polardbx.common.utils.logger.Logger; import com.alibaba.polardbx.common.utils.logger.LoggerFactory; -import com.alibaba.polardbx.gms.config.impl.InstConfUtil; -import com.alibaba.polardbx.gms.metadb.MetaDbDataSource; -import com.alibaba.polardbx.gms.topology.InstConfigAccessor; -import com.alibaba.polardbx.gms.util.InstIdUtil; +import com.alibaba.polardbx.common.utils.version.InstanceVersion; import com.alibaba.polardbx.gms.util.MetaDbUtil; import com.alibaba.polardbx.optimizer.context.ExecutionContext; import com.alibaba.polardbx.rpc.pool.XConnection; import com.alibaba.polardbx.transaction.TransactionManager; import com.alibaba.polardbx.transaction.jdbc.SavePoint; -import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import java.util.concurrent.atomic.AtomicLong; @@ -130,6 +124,11 @@ public void sendSnapshotSeq(IConnection conn) { } public void setInnodbMarkDistributed(IConnection conn) throws SQLException { + if (InstanceVersion.isMYSQL80()) { + // For 8.0, no need to send innodb_mark_distributed, + // because TSO read transactions will always wait for prepared XA transactions. + return; + } XConnection xConnection; if (conn.isWrapperFor(XConnection.class) && (xConnection = conn.unwrap(XConnection.class)).supportMarkDistributed()) { @@ -145,27 +144,9 @@ public void commit() { try { super.commit(); } catch (Throwable t) { - long lastErrTime = xaTsoFailedLastTime.get(); - if ((System.nanoTime() - lastErrTime) / 1000000000 > 60 - && xaTsoFailedLastTime.compareAndSet(lastErrTime, System.nanoTime())) { - // First error in 1 min, reset err cnt. - xaTsoFailedLastTime.set(0); - } - // 30 err occurs in the last 1 min, switch to XA for safety. - if (xaTsoFailedCnt.incrementAndGet() == 30) { - try { - if (!InstConfUtil.getBool(ConnectionParams.ENABLE_XA_TSO)) { - return; - } - - EventLogger.log(EventType.TRX_ERR, - "Error: 30 errors occurred within 1 min, disable XaTsoTrx"); - - disable(); - } finally { - xaTsoFailedCnt.set(0); - } - } + logger.error("XA_TSO Error.", t); + EventLogger.log(EventType.TRX_ERR, "XA_TSO Error: " + t.getMessage()); + throw t; } } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/utils/ParamValidationUtils.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/utils/ParamValidationUtils.java index 8458204b2..1ed67363b 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/utils/ParamValidationUtils.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/utils/ParamValidationUtils.java @@ -17,31 +17,31 @@ package com.alibaba.polardbx.transaction.utils; import com.alibaba.polardbx.common.async.AsyncTaskUtils; -import com.alibaba.polardbx.common.async.TimeInterval; import com.alibaba.polardbx.common.exception.TddlRuntimeException; import com.alibaba.polardbx.common.exception.code.ErrorCode; -import com.alibaba.polardbx.common.properties.BooleanConfigParam; import com.alibaba.polardbx.common.utils.Assert; import com.alibaba.polardbx.common.utils.GeneralUtil; import com.alibaba.polardbx.config.ConfigDataMode; -import java.time.LocalTime; import java.util.Map; import java.util.Properties; import java.util.Set; import static com.alibaba.polardbx.common.constants.ServerVariables.MODIFIABLE_DEADLOCK_DETECTION_PARAM; import static com.alibaba.polardbx.common.constants.ServerVariables.MODIFIABLE_PURGE_TRANS_PARAM; +import static com.alibaba.polardbx.common.constants.ServerVariables.MODIFIABLE_SYNC_POINT_PARAM; import static com.alibaba.polardbx.common.constants.ServerVariables.MODIFIABLE_TIMER_TASK_PARAM; import static com.alibaba.polardbx.common.constants.ServerVariables.MODIFIABLE_TRANSACTION_STATISTICS_PARAM; import static com.alibaba.polardbx.common.constants.ServerVariables.MODIFIABLE_TRX_IDLE_TIMEOUT_PARAM; -import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_DEADLOCK_DETECTION; import static com.alibaba.polardbx.common.properties.ConnectionProperties.DEADLOCK_DETECTION_INTERVAL; +import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_DEADLOCK_DETECTION; +import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_SYNC_POINT; import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_TRANSACTION_STATISTICS; import static com.alibaba.polardbx.common.properties.ConnectionProperties.ENABLE_TRX_IDLE_TIMEOUT_TASK; import static com.alibaba.polardbx.common.properties.ConnectionProperties.PURGE_TRANS_BEFORE; import static com.alibaba.polardbx.common.properties.ConnectionProperties.PURGE_TRANS_INTERVAL; import static com.alibaba.polardbx.common.properties.ConnectionProperties.PURGE_TRANS_START_TIME; +import static com.alibaba.polardbx.common.properties.ConnectionProperties.SYNC_POINT_TASK_INTERVAL; import static com.alibaba.polardbx.common.properties.ConnectionProperties.TRANSACTION_STATISTICS_TASK_INTERVAL; import static com.alibaba.polardbx.common.properties.ConnectionProperties.TRX_IDLE_TIMEOUT_TASK_INTERVAL; @@ -143,6 +143,27 @@ public static void validateTransactionIdleTimeoutParam(String parameter, String throw new TddlRuntimeException(ErrorCode.ERR_VALIDATE, "Unknown transaction statistics parameter " + parameter); } + public static void validateSyncPointParam(String parameter, String value) { + if (ENABLE_SYNC_POINT.equals(parameter)) { + final Boolean boolVal = GeneralUtil.convertStringToBoolean(value); + if (boolVal == null) { + throw new TddlRuntimeException(ErrorCode.ERR_VALIDATE, + "invalid parameter: " + parameter + ", it should be TRUE/FALSE"); + } + return; + } + if (SYNC_POINT_TASK_INTERVAL.equals(parameter)) { + final int intVal = Integer.parseInt(value); + if (intVal < 1000) { + throw new TddlRuntimeException(ErrorCode.ERR_VALIDATE, + "invalid parameter: " + parameter + ", it should >= 1000(ms)"); + } + return; + } + + throw new TddlRuntimeException(ErrorCode.ERR_VALIDATE, "Unknown sync point task parameter " + parameter); + } + public static boolean isIdentical(Map newParam, Map oldParam, Set paramNames) { for (String paramName : paramNames) { @@ -172,6 +193,10 @@ public static boolean isTimerTaskParam(String parameter, String value) { validateTransactionIdleTimeoutParam(parameter, value); } + if (MODIFIABLE_SYNC_POINT_PARAM.contains(parameter)) { + validateSyncPointParam(parameter, value); + } + return false; } diff --git a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/utils/XAUtils.java b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/utils/XAUtils.java index 5b8de0ce4..723c3b62c 100644 --- a/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/utils/XAUtils.java +++ b/polardbx-transaction/src/main/java/com/alibaba/polardbx/transaction/utils/XAUtils.java @@ -16,6 +16,7 @@ package com.alibaba.polardbx.transaction.utils; +import com.alibaba.polardbx.common.constants.TransactionAttribute; import com.alibaba.polardbx.common.exception.code.ErrorCode; import com.alibaba.polardbx.common.jdbc.IConnection; import com.alibaba.polardbx.common.jdbc.IDataSource; @@ -239,9 +240,16 @@ public String toString() { } public static XATransInfo parseXid(long formatID, int gtridLength, int bqualLength, byte[] data) { - if (formatID == 1) { - byte[] gtridData = Arrays.copyOfRange(data, 0, gtridLength); - byte[] bqualData = Arrays.copyOfRange(data, gtridLength, gtridLength + bqualLength); + TransactionAttribute.FormatId id = TransactionAttribute.FormatId.fromId((int) formatID); + if (null == id) { + return null; + } + byte[] gtridData = Arrays.copyOfRange(data, 0, gtridLength); + byte[] bqualData = Arrays.copyOfRange(data, gtridLength, gtridLength + bqualLength); + switch (id) { + case NORMAL: + case ARCHIVE: + case IGNORE_BINLOG: if (ExecUtils.checkGtridPrefix(gtridData)) { int atSymbolIndex = ArrayUtils.indexOf(gtridData, (byte) '@'); String txid = new String(gtridData, 5, atSymbolIndex - 5); @@ -251,11 +259,7 @@ public static XATransInfo parseXid(long formatID, int gtridLength, int bqualLeng } else { return null; } - } else if (formatID == 2) { - // For XA trx generated by recover task. - byte[] gtridData = Arrays.copyOfRange(data, 0, gtridLength); - byte[] bqualData = Arrays.copyOfRange(data, gtridLength, gtridLength + bqualLength); - + case RECOVER: int atSymbolIndex = ArrayUtils.indexOf(gtridData, (byte) '@'); if (atSymbolIndex == ArrayUtils.INDEX_NOT_FOUND) { return null; @@ -269,8 +273,9 @@ public static XATransInfo parseXid(long formatID, int gtridLength, int bqualLeng String gtrid = new String(gtridData); String bqual = new String(bqualData); return new XATransInfo(gtrid, bqual); + default: + return null; } - return null; } /** diff --git a/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/ColumnarTsoManagerTest.java b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/ColumnarTsoManagerTest.java new file mode 100644 index 000000000..0ac5240f9 --- /dev/null +++ b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/ColumnarTsoManagerTest.java @@ -0,0 +1,234 @@ +package com.alibaba.polardbx.transaction; + +import com.alibaba.polardbx.common.properties.ConnectionParams; +import com.alibaba.polardbx.common.utils.thread.NamedThreadFactory; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.executor.gms.ColumnarManager; +import com.alibaba.polardbx.executor.gms.util.ColumnarTransactionUtils; +import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.gms.config.impl.InstConfUtil; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigAccessor; +import com.alibaba.polardbx.gms.metadb.table.ColumnarConfigRecord; +import com.alibaba.polardbx.gms.util.MetaDbUtil; +import org.jetbrains.annotations.NotNull; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.sql.Connection; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicLong; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; + +public class ColumnarTsoManagerTest { + + private final AtomicLong purgeWatermark = new AtomicLong(0); + private final AtomicLong nextTso = new AtomicLong(1); + private final ScheduledExecutorService executorService1 = + new MockScheduledExecutorService("ColumnarTsoPurgeTaskExecutor"); + private final ScheduledExecutorService executorService2 = + new MockScheduledExecutorService("ColumnarTsoUpdateTaskExecutor"); + + @Before + public void setUp() { + ColumnarTsoManager.INSTANCE.destroy(); + ColumnarManager.getInstance().reload(); + } + + @Test + public void test() throws InterruptedException { + try (MockedStatic instConfUtilMockedStatic = Mockito.mockStatic(InstConfUtil.class)) { + instConfUtilMockedStatic.when(() -> InstConfUtil.getInt(ConnectionParams.COLUMNAR_TSO_UPDATE_INTERVAL)) + .thenReturn(500); + instConfUtilMockedStatic.when(() -> InstConfUtil.getInt(ConnectionParams.COLUMNAR_TSO_PURGE_INTERVAL)) + .thenReturn(800); + ConfigDataMode.setMode(ConfigDataMode.Mode.GMS); + ColumnarTsoManager columnarTsoManager; + try (MockedStatic executorsMockedStatic = Mockito.mockStatic(Executors.class, + Mockito.CALLS_REAL_METHODS)) { + executorsMockedStatic.when(() -> Executors.newSingleThreadScheduledExecutor(any())) + .thenReturn(executorService1) + .thenReturn(executorService2); + columnarTsoManager = ColumnarTsoManager.getInstance(); + } + Thread.sleep(10000); + Assert.assertTrue(purgeWatermark.get() > 0); + columnarTsoManager.resetColumnarTsoPurgeInterval(10); + columnarTsoManager.resetColumnarTsoUpdateInterval(10); + Thread.sleep(3333); + Assert.assertTrue(purgeWatermark.get() > 300); + } + } + + @After + public void tearDown() { + ColumnarTsoManager.INSTANCE.destroy(); + ColumnarManager.getInstance().reload(); + } + + class MockScheduledExecutorService implements ScheduledExecutorService { + private final ScheduledExecutorService executorService; + + public MockScheduledExecutorService(String threadName) { + executorService = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory(threadName)); + } + + @NotNull + @Override + public ScheduledFuture schedule(@NotNull Runnable command, long delay, @NotNull TimeUnit unit) { + return executorService.schedule(command, delay, unit); + } + + @NotNull + @Override + public ScheduledFuture schedule(@NotNull Callable callable, long delay, @NotNull TimeUnit unit) { + return executorService.schedule(callable, delay, unit); + } + + @NotNull + @Override + public ScheduledFuture scheduleAtFixedRate(@NotNull Runnable command, long initialDelay, long period, + @NotNull TimeUnit unit) { + return executorService.scheduleAtFixedRate(() -> { + try (MockedStatic instConfUtilMockedStatic = Mockito.mockStatic(InstConfUtil.class); + MockedStatic ctUtilsMockedStatic = Mockito.mockStatic( + ColumnarTransactionUtils.class); + MockedStatic execUtilsMockedStatic = Mockito.mockStatic(ExecUtils.class); + MockedStatic metaDbUtilMockedStatic = Mockito.mockStatic(MetaDbUtil.class); + MockedConstruction ccaCtor = Mockito.mockConstruction( + ColumnarConfigAccessor.class, + (mock, context) -> { + Mockito.when(mock.queryGlobalByConfigKey(anyString())) + .thenAnswer(invocation -> { + if (purgeWatermark.get() == 0L) { + return Collections.emptyList(); + } + ColumnarConfigRecord configRecord = new ColumnarConfigRecord(); + configRecord.configValue = String.valueOf(purgeWatermark.get()); + return Collections.singletonList(configRecord); + }); + Mockito.when(mock.updateGlobalParamValue(anyString(), anyString())) + .thenAnswer(invocation -> { + long newValue = Long.parseLong(invocation.getArgument(1, String.class)); + purgeWatermark.set(newValue); + return 1; + }); + })) { + metaDbUtilMockedStatic.when(MetaDbUtil::getConnection).thenReturn(Mockito.mock(Connection.class)); + instConfUtilMockedStatic.when(() -> InstConfUtil.getInt(ConnectionParams.COLUMNAR_TSO_UPDATE_DELAY)) + .thenReturn(1000); + ctUtilsMockedStatic.when(() -> ColumnarTransactionUtils.getLatestTsoFromGmsWithDelay(anyLong())) + .thenAnswer(invocation -> nextTso.getAndIncrement()); + ctUtilsMockedStatic.when(ColumnarTransactionUtils::getMinColumnarSnapshotTime).thenCallRealMethod(); + ctUtilsMockedStatic.when(() -> ColumnarTransactionUtils.updateColumnarPurgeWatermark(anyLong())) + .thenCallRealMethod(); + execUtilsMockedStatic.when(() -> ExecUtils.hasLeadership(any())).thenReturn(true); + + command.run(); + } + }, initialDelay, period, unit); + } + + @NotNull + @Override + public ScheduledFuture scheduleWithFixedDelay(@NotNull Runnable command, long initialDelay, long delay, + @NotNull TimeUnit unit) { + return executorService.scheduleWithFixedDelay(command, initialDelay, delay, unit); + } + + @Override + public void shutdown() { + executorService.shutdown(); + } + + @NotNull + @Override + public List shutdownNow() { + return executorService.shutdownNow(); + } + + @Override + public boolean isShutdown() { + return executorService.isShutdown(); + } + + @Override + public boolean isTerminated() { + return executorService.isTerminated(); + } + + @Override + public boolean awaitTermination(long timeout, @NotNull TimeUnit unit) throws InterruptedException { + return executorService.awaitTermination(timeout, unit); + } + + @NotNull + @Override + public Future submit(@NotNull Callable task) { + return executorService.submit(task); + } + + @NotNull + @Override + public Future submit(@NotNull Runnable task, T result) { + return executorService.submit(task, result); + } + + @NotNull + @Override + public Future submit(@NotNull Runnable task) { + return executorService.submit(task); + } + + @NotNull + @Override + public List> invokeAll(@NotNull Collection> tasks) + throws InterruptedException { + return executorService.invokeAll(tasks); + } + + @NotNull + @Override + public List> invokeAll(@NotNull Collection> tasks, long timeout, + @NotNull TimeUnit unit) throws InterruptedException { + return executorService.invokeAll(tasks, timeout, unit); + } + + @NotNull + @Override + public T invokeAny(@NotNull Collection> tasks) + throws InterruptedException, ExecutionException { + return executorService.invokeAny(tasks); + } + + @Override + public T invokeAny(@NotNull Collection> tasks, long timeout, @NotNull TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + return executorService.invokeAny(tasks, timeout, unit); + } + + @Override + public void execute(@NotNull Runnable command) { + executorService.execute(command); + } + } +} \ No newline at end of file diff --git a/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/async/DeadlockDetectionTest.java b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/async/DeadlockDetectionTest.java new file mode 100644 index 000000000..16ce1469b --- /dev/null +++ b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/async/DeadlockDetectionTest.java @@ -0,0 +1,267 @@ +package com.alibaba.polardbx.transaction.async; + +import com.alibaba.polardbx.common.mock.MockStatus; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.common.utils.version.InstanceVersion; +import com.alibaba.polardbx.executor.utils.transaction.GroupConnPair; +import com.alibaba.polardbx.executor.utils.transaction.TrxLookupSet; +import com.alibaba.polardbx.group.jdbc.TGroupDataSource; +import com.alibaba.polardbx.rpc.compatible.ArrayResultSet; +import com.alibaba.polardbx.transaction.utils.DiGraph; +import com.google.common.collect.ImmutableList; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; + +import static com.alibaba.polardbx.transaction.async.DeadlockDetectionTask.SQL_QUERY_DEADLOCKS; +import static com.alibaba.polardbx.transaction.async.DeadlockDetectionTask.SQL_QUERY_LOCK_WAITS_80; +import static com.alibaba.polardbx.transaction.async.DeadlockDetectionTask.SQL_QUERY_TRX_80; + +public class DeadlockDetectionTest { + @Test + public void test1() throws SQLException { + DynamicConfig.getInstance().loadValue(null, ConnectionProperties.DEADLOCK_DETECTION_80_FETCH_TRX_ROWS, "5"); + InstanceVersion.setMYSQL80(true); + MockStatus.setMock(true); + DeadlockDetectionTask task = new DeadlockDetectionTask(new ArrayList<>()); + + try (MockedStatic deadlockDetectionTaskMockedStatic = + Mockito.mockStatic(DeadlockDetectionTask.class)) { + Connection connection = Mockito.mock(Connection.class); + Statement stmt = Mockito.mock(Statement.class); + TrxLookupSet lookupSet = new TrxLookupSet(); + addTrx(lookupSet, 10000L, "test_group_00000", 100L, 1000L, 1L, "waiting_sql"); + addTrx(lookupSet, 20000L, "test_group_00000", 200L, 2000L, 2L, "blocking_sql"); + + deadlockDetectionTaskMockedStatic + .when(() -> DeadlockDetectionTask.createPhysicalConnectionForLeaderStorage(Mockito.any())) + .thenReturn(connection); + Mockito.when(connection.createStatement()).thenReturn(stmt); + Mockito.when(stmt.executeQuery(Mockito.anyString())) + .thenAnswer( + invocation -> { + String sql = invocation.getArgument(0); + if (sql.contains(SQL_QUERY_TRX_80)) { + ArrayResultSet rs = getTrx80Rs(); + rs.getRows().add(new Object[] { + 1, 100, "LOCK WAIT", "waiting_physical_sql", "operation_state", 6, 7, 8, 9, 10 + }); + rs.getRows().add(new Object[] { + 2, 200, "NULL", "blocking_physical_sql", "operation_state", 6, 7, 8, 9, 10 + }); + return rs; + } else if (sql.contains(SQL_QUERY_LOCK_WAITS_80)) { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("waiting_trx_id"); + rs.getColumnName().add("blocking_trx_id"); + rs.getRows().add(new Object[] { + 1, 2 + }); + return rs; + } else { + return null; + } + } + ); + DiGraph graph = new DiGraph<>(); + task.fetchLockWaits(Mockito.mock(TGroupDataSource.class), ImmutableList.of("test_group_00000"), lookupSet, + graph); + TrxLookupSet.Transaction trx1 = lookupSet.getTransaction(10000L); + TrxLookupSet.Transaction trx2 = lookupSet.getTransaction(20000L); + Assert.assertEquals("waiting_physical_sql", trx1.getLocalTransaction("test_group_00000").getPhysicalSql()); + Assert.assertEquals("blocking_physical_sql", trx2.getLocalTransaction("test_group_00000").getPhysicalSql()); + System.out.println(graph); + } + } + + @Test + public void test2() throws SQLException { + DynamicConfig.getInstance().loadValue(null, ConnectionProperties.DEADLOCK_DETECTION_80_FETCH_TRX_ROWS, "5"); + InstanceVersion.setMYSQL80(false); + MockStatus.setMock(true); + DeadlockDetectionTask task = new DeadlockDetectionTask(new ArrayList<>()); + + try (MockedStatic deadlockDetectionTaskMockedStatic = + Mockito.mockStatic(DeadlockDetectionTask.class)) { + Connection connection = Mockito.mock(Connection.class); + Statement stmt = Mockito.mock(Statement.class); + TrxLookupSet lookupSet = new TrxLookupSet(); + addTrx(lookupSet, 10000L, "test_group_00000", 100L, 1000L, 1L, "waiting_sql"); + addTrx(lookupSet, 20000L, "test_group_00000", 200L, 2000L, 2L, "blocking_sql"); + + deadlockDetectionTaskMockedStatic + .when(() -> DeadlockDetectionTask.createPhysicalConnectionForLeaderStorage(Mockito.any())) + .thenReturn(connection); + Mockito.when(connection.createStatement()).thenReturn(stmt); + Mockito.when(stmt.executeQuery(Mockito.anyString())) + .thenAnswer( + invocation -> { + String sql = invocation.getArgument(0); + if (sql.contains(SQL_QUERY_DEADLOCKS)) { + return getDeadlocksRs(); + } else { + return null; + } + } + ); + DiGraph graph = new DiGraph<>(); + task.fetchLockWaits(Mockito.mock(TGroupDataSource.class), ImmutableList.of("test_group_00000"), lookupSet, + graph); + TrxLookupSet.Transaction trx1 = lookupSet.getTransaction(10000L); + TrxLookupSet.Transaction trx2 = lookupSet.getTransaction(20000L); + Assert.assertEquals("waiting_physical_sql", trx1.getLocalTransaction("test_group_00000").getPhysicalSql()); + Assert.assertEquals("blocking_physical_sql", trx2.getLocalTransaction("test_group_00000").getPhysicalSql()); + System.out.println(graph); + } + } + + @Test + public void test3() throws SQLException { + DynamicConfig.getInstance() + .loadValue(null, ConnectionProperties.DEADLOCK_DETECTION_DATA_LOCK_WAITS_THRESHOLD, "50000"); + InstanceVersion.setMYSQL80(true); + MockStatus.setMock(true); + DeadlockDetectionTask task = new DeadlockDetectionTask(new ArrayList<>()); + + try (MockedStatic deadlockDetectionTaskMockedStatic = + Mockito.mockStatic(DeadlockDetectionTask.class)) { + Connection connection = Mockito.mock(Connection.class); + Statement stmt = Mockito.mock(Statement.class); + deadlockDetectionTaskMockedStatic + .when(() -> DeadlockDetectionTask.createPhysicalConnectionForLeaderStorage(Mockito.any())) + .thenReturn(connection); + Mockito.when(connection.createStatement()).thenReturn(stmt); + Mockito.when(stmt.executeQuery(Mockito.anyString())) + .thenReturn(getHotspotRs1()); + + Assert.assertFalse(task.maybeTooManyDataLockWaits(Mockito.mock(TGroupDataSource.class))); + } + } + + @Test + public void test4() throws SQLException { + DynamicConfig.getInstance() + .loadValue(null, ConnectionProperties.DEADLOCK_DETECTION_DATA_LOCK_WAITS_THRESHOLD, "50000"); + InstanceVersion.setMYSQL80(false); + MockStatus.setMock(true); + DeadlockDetectionTask task = new DeadlockDetectionTask(new ArrayList<>()); + + try (MockedStatic deadlockDetectionTaskMockedStatic = + Mockito.mockStatic(DeadlockDetectionTask.class)) { + Connection connection = Mockito.mock(Connection.class); + Statement stmt = Mockito.mock(Statement.class); + deadlockDetectionTaskMockedStatic + .when(() -> DeadlockDetectionTask.createPhysicalConnectionForLeaderStorage(Mockito.any())) + .thenReturn(connection); + Mockito.when(connection.createStatement()).thenReturn(stmt); + Mockito.when(stmt.executeQuery(Mockito.anyString())) + .thenReturn(getHotspotRs2()); + + Assert.assertTrue(task.maybeTooManyDataLockWaits(Mockito.mock(TGroupDataSource.class))); + } + } + + @NotNull + private static ArrayResultSet getTrx80Rs() { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("trx_id"); + rs.getColumnName().add("conn_id"); + rs.getColumnName().add("state"); + rs.getColumnName().add("physical_sql"); + rs.getColumnName().add("operation_state"); + rs.getColumnName().add("tables_in_use"); + rs.getColumnName().add("tables_locked"); + rs.getColumnName().add("lock_structs"); + rs.getColumnName().add("heap_size"); + rs.getColumnName().add("row_locks"); + return rs; + } + + @NotNull + private static ArrayResultSet getDeadlocksRs() { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("waiting_conn_id"); + rs.getColumnName().add("blocking_conn_id"); + rs.getColumnName().add("waiting_state"); + rs.getColumnName().add("waiting_physical_sql"); + rs.getColumnName().add("waiting_operation_state"); + rs.getColumnName().add("waiting_tables_in_use"); + rs.getColumnName().add("waiting_tables_locked"); + rs.getColumnName().add("waiting_lock_structs"); + rs.getColumnName().add("waiting_heap_size"); + rs.getColumnName().add("waiting_row_locks"); + rs.getColumnName().add("waiting_lock_id"); + rs.getColumnName().add("waiting_lock_mode"); + rs.getColumnName().add("waiting_lock_type"); + rs.getColumnName().add("waiting_lock_physical_table"); + rs.getColumnName().add("waiting_lock_index"); + rs.getColumnName().add("waiting_lock_space"); + rs.getColumnName().add("waiting_lock_page"); + rs.getColumnName().add("waiting_lock_rec"); + rs.getColumnName().add("waiting_lock_data"); + rs.getColumnName().add("blocking_state"); + rs.getColumnName().add("blocking_physical_sql"); + rs.getColumnName().add("blocking_operation_state"); + rs.getColumnName().add("blocking_tables_in_use"); + rs.getColumnName().add("blocking_tables_locked"); + rs.getColumnName().add("blocking_lock_structs"); + rs.getColumnName().add("blocking_heap_size"); + rs.getColumnName().add("blocking_row_locks"); + rs.getColumnName().add("blocking_lock_id"); + rs.getColumnName().add("blocking_lock_mode"); + rs.getColumnName().add("blocking_lock_type"); + rs.getColumnName().add("blocking_lock_physical_table"); + rs.getColumnName().add("blocking_lock_index"); + rs.getColumnName().add("blocking_lock_space"); + rs.getColumnName().add("blocking_lock_page"); + rs.getColumnName().add("blocking_lock_rec"); + rs.getColumnName().add("blocking_lock_data"); + rs.getRows().add(new Object[] { + 100, 200, + "LOCK WAIT", "waiting_physical_sql", "operation_state", 6, 7, 8, 9, 10, "lock_id", "RECORD LOCK", + "X GAP", "physical_table", "PRIMARY", 100, 50, 25, 1234567, + "NULL", "blocking_physical_sql", "operation_state", 6, 7, 8, 9, 10, "lock_id", "RECORD LOCK", + "X GAP", "physical_table", "PRIMARY", 100, 50, 25, 1234567 + }); + return rs; + } + + @NotNull + private static ArrayResultSet getHotspotRs1() { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("cnt"); + rs.getColumnName().add("lock_id"); + rs.getRows().add(new Object[] { + 60000, "NULL", + 100, "1:1000" + }); + return rs; + } + + @NotNull + private static ArrayResultSet getHotspotRs2() { + ArrayResultSet rs = new ArrayResultSet(); + rs.getColumnName().add("cnt"); + rs.getColumnName().add("lock_id"); + rs.getRows().add(new Object[] { + 60000, "1:1000", + 100, "NULL" + }); + return rs; + } + + private static void addTrx(TrxLookupSet lookupSet, Long transId, String group, long connId, long frontendConnId, + Long startTime, String sql) { + final GroupConnPair entry = new GroupConnPair(group, connId); + lookupSet.addNewTransaction(entry, transId); + lookupSet.updateTransaction(transId, frontendConnId, sql, startTime, false); + } +} diff --git a/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/jdbc/DeferredConnectionTest.java b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/jdbc/DeferredConnectionTest.java new file mode 100644 index 000000000..b373565b7 --- /dev/null +++ b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/jdbc/DeferredConnectionTest.java @@ -0,0 +1,54 @@ +package com.alibaba.polardbx.transaction.jdbc; + +import com.alibaba.polardbx.common.jdbc.IConnection; +import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; +import com.alibaba.polardbx.rpc.pool.XConnection; +import org.junit.Test; + +import java.sql.SQLException; +import java.sql.Statement; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class DeferredConnectionTest { + @Test + public void testFlashbackArea() throws SQLException { + XConnection xConn = mock(XConnection.class); + TGroupDirectConnection tGroupDirectConnection = mock(TGroupDirectConnection.class); + when(tGroupDirectConnection.unwrap(XConnection.class)).thenReturn(xConn); + when(tGroupDirectConnection.isWrapperFor(XConnection.class)).thenReturn(true); + when(tGroupDirectConnection.enableFlashbackArea(anyBoolean())).thenCallRealMethod(); + DeferredConnection deferredConnection = new DeferredConnection(tGroupDirectConnection, false); + when(deferredConnection.unwrap(XConnection.class)).thenReturn(xConn); + when(xConn.supportFlashbackArea()).thenReturn(true); + doNothing().when(xConn).setLazyFlashbackArea(); + + IConnection result = deferredConnection.enableFlashbackArea(true); + + assertEquals(deferredConnection, result); + verify(xConn).setLazyFlashbackArea(); + + IConnection iConnection = mock(IConnection.class); + doCallRealMethod().when(iConnection).enableFlashbackArea(true); + doCallRealMethod().when(iConnection).disableFlashbackArea(); + when(tGroupDirectConnection.isWrapperFor(XConnection.class)).thenReturn(false); + deferredConnection = new DeferredConnection(iConnection, false); + + result = deferredConnection.enableFlashbackArea(true); + + assertEquals(deferredConnection, result); + verify(iConnection).executeLater(any()); + + Statement stmt = mock(Statement.class); + when(iConnection.createStatement()).thenReturn(stmt); + deferredConnection.disableFlashbackArea(); + verify(stmt).execute(any()); + } +} diff --git a/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/log/GlobalTxLogManagerTest.java b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/log/GlobalTxLogManagerTest.java new file mode 100644 index 000000000..4a6b1d490 --- /dev/null +++ b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/log/GlobalTxLogManagerTest.java @@ -0,0 +1,500 @@ +package com.alibaba.polardbx.transaction.log; + +import com.alibaba.polardbx.common.jdbc.BytesSql; +import com.alibaba.polardbx.common.jdbc.IConnection; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.common.properties.DynamicConfig; +import com.alibaba.polardbx.common.type.TransactionType; +import com.alibaba.polardbx.common.utils.InstanceRole; +import com.alibaba.polardbx.config.ConfigDataMode; +import com.alibaba.polardbx.group.jdbc.TGroupDataSource; +import com.alibaba.polardbx.group.jdbc.TGroupDirectConnection; +import com.alibaba.polardbx.transaction.TransactionState; +import org.junit.Test; +import org.mockito.MockedStatic; + +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class GlobalTxLogManagerTest { + @Test + public void testLegacyTrxLogAppend() throws SQLException { + DynamicConfig.getInstance().loadValue(null, ConnectionProperties.TRX_LOG_METHOD, "0"); + PreparedStatement stmt = mock(PreparedStatement.class); + MockConnection connection = new MockConnection(stmt); + GlobalTxLogManager.appendWithSocketTimeout(1, TransactionType.XA, TransactionState.SUCCEED, null, connection); + assertTrue(connection.hasSetNetworkTimeout); + assertEquals(0, connection.networkTimeout); + } + + @Test + public void testLegacyTrxLogAppendTso() throws SQLException { + DynamicConfig.getInstance().loadValue(null, ConnectionProperties.TRX_LOG_METHOD, "0"); + PreparedStatement stmt = mock(PreparedStatement.class); + MockConnection connection = new MockConnection(stmt); + GlobalTxLogManager.appendWithSocketTimeout(1, TransactionType.XA, TransactionState.SUCCEED, null, 1L, + connection); + assertTrue(connection.hasSetNetworkTimeout); + assertEquals(0, connection.networkTimeout); + } + + @Test + public void testNewTrxLogAppend() throws SQLException { + DynamicConfig.getInstance().loadValue(null, ConnectionProperties.TRX_LOG_METHOD, "1"); + PreparedStatement stmt = mock(PreparedStatement.class); + MockConnection connection = new MockConnection(stmt); + GlobalTxLogManager.appendV2WithSocketTimeout(1, 1L, connection); + assertTrue(connection.hasSetNetworkTimeout); + assertEquals(0, connection.networkTimeout); + } + + @Test + public void testNewTrxLogAppendWithLockWaitTimeout() throws SQLException { + DynamicConfig.getInstance().loadValue(null, ConnectionProperties.TRX_LOG_METHOD, "1"); + PreparedStatement stmt = mock(PreparedStatement.class); + MockConnection connection = new MockConnection(stmt); + GlobalTxLogManager.appendV2WithSocketTimeout(1, 1L, connection); + assertTrue(connection.hasSetNetworkTimeout); + assertEquals(0, connection.networkTimeout); + } + + @Test + public void testAppendWithLockWaitTimeout() throws SQLException { + PreparedStatement preparedStatement = mock(PreparedStatement.class); + Statement stmt = mock(Statement.class); + ResultSet rs = mock(ResultSet.class); + when(stmt.executeQuery(any())).thenReturn(rs); + MockConnection connection = new MockConnection(preparedStatement, stmt); + GlobalTxLogManager.appendWithTimeout(1, TransactionType.XA, TransactionState.SUCCEED, null, connection); + assertTrue(connection.hasSetNetworkTimeout); + assertEquals(0, connection.networkTimeout); + } + + @Test + public void testAppendV2WithLockWaitTimeout() throws Exception { + PreparedStatement preparedStatement = mock(PreparedStatement.class); + Statement stmt = mock(Statement.class); + ResultSet rs = mock(ResultSet.class); + when(stmt.executeQuery(any())).thenReturn(rs); + MockConnection connection = new MockConnection(preparedStatement, stmt); + GlobalTxLogManager.appendV2WithTimeout(1, 1, connection); + assertTrue(connection.hasSetNetworkTimeout); + assertEquals(0, connection.networkTimeout); + } + + @Test + public void testCreateTables() throws SQLException { + try (MockedStatic mockedStatic = mockStatic(GlobalTxLogManager.class)) { + mockedStatic.when(() -> GlobalTxLogManager.createGlobalTxLogTable(any(), anyLong())) + .then(invocation -> null); + mockedStatic.when(() -> GlobalTxLogManager.createTables(any(), anyLong(), any())).thenCallRealMethod(); + + PreparedStatement preparedStatement = mock(PreparedStatement.class); + Statement stmt = mock(Statement.class); + ResultSet rs = mock(ResultSet.class); + when(stmt.executeQuery(any())).thenReturn(rs); + MockConnection connection = new MockConnection(preparedStatement, stmt); + TGroupDataSource dataSource = mock(TGroupDataSource.class); + TGroupDirectConnection tGroupDirectConnection = new TGroupDirectConnection(dataSource, connection); + when(dataSource.getConnection()).thenReturn(tGroupDirectConnection); + ConfigDataMode.setInstanceRole(InstanceRole.FAST_MOCK); + + GlobalTxLogManager.createTables(dataSource, 1000L, new HashSet<>()); + assertEquals(0, connection.networkTimeout); + } finally { + ConfigDataMode.setInstanceRole(InstanceRole.MASTER); + } + } + + private static class MockConnection implements IConnection { + public boolean hasSetNetworkTimeout = false; + public int networkTimeout = 0; + public PreparedStatement prepareStmt; + public Statement stmt; + + MockConnection(PreparedStatement prepareStmt) { + this.prepareStmt = prepareStmt; + } + + MockConnection(PreparedStatement prepareStmt, Statement stmt) { + this.prepareStmt = prepareStmt; + this.stmt = stmt; + } + + @Override + public void setEncoding(String encoding) throws SQLException { + + } + + @Override + public String getEncoding() { + return null; + } + + @Override + public void setSqlMode(String sqlMode) { + + } + + @Override + public String getSqlMode() { + return null; + } + + @Override + public void setStressTestValid(boolean stressTestValid) { + + } + + @Override + public boolean isStressTestValid() { + return false; + } + + @Override + public boolean isBytesSqlSupported() throws SQLException { + return false; + } + + @Override + public PreparedStatement prepareStatement(BytesSql sql, byte[] hint) throws SQLException { + return prepareStmt; + } + + @Override + public Statement createStatement() throws SQLException { + return stmt; + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + return prepareStmt; + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + return null; + } + + @Override + public String nativeSQL(String sql) throws SQLException { + return null; + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + + } + + @Override + public boolean getAutoCommit() throws SQLException { + return false; + } + + @Override + public void commit() throws SQLException { + + } + + @Override + public void rollback() throws SQLException { + + } + + @Override + public void close() throws SQLException { + + } + + @Override + public boolean isClosed() throws SQLException { + return false; + } + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + return null; + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLException { + + } + + @Override + public boolean isReadOnly() throws SQLException { + return false; + } + + @Override + public void setCatalog(String catalog) throws SQLException { + + } + + @Override + public String getCatalog() throws SQLException { + return null; + } + + @Override + public void setTransactionIsolation(int level) throws SQLException { + + } + + @Override + public int getTransactionIsolation() throws SQLException { + return 0; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return null; + } + + @Override + public void clearWarnings() throws SQLException { + + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + return stmt; + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException { + return prepareStmt; + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException { + return null; + } + + @Override + public Map> getTypeMap() throws SQLException { + return null; + } + + @Override + public void setTypeMap(Map> map) throws SQLException { + + } + + @Override + public void setHoldability(int holdability) throws SQLException { + + } + + @Override + public int getHoldability() throws SQLException { + return 0; + } + + @Override + public Savepoint setSavepoint() throws SQLException { + return null; + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + return null; + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + return stmt; + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return prepareStmt; + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + return prepareStmt; + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + return prepareStmt; + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + return prepareStmt; + } + + @Override + public Clob createClob() throws SQLException { + return null; + } + + @Override + public Blob createBlob() throws SQLException { + return null; + } + + @Override + public NClob createNClob() throws SQLException { + return null; + } + + @Override + public SQLXML createSQLXML() throws SQLException { + return null; + } + + @Override + public boolean isValid(int timeout) throws SQLException { + return false; + } + + @Override + public void setClientInfo(String name, String value) throws SQLClientInfoException { + + } + + @Override + public void setClientInfo(Properties properties) throws SQLClientInfoException { + + } + + @Override + public String getClientInfo(String name) throws SQLException { + return null; + } + + @Override + public Properties getClientInfo() throws SQLException { + return null; + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + return null; + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + return null; + } + + @Override + public void setSchema(String schema) throws SQLException { + + } + + @Override + public String getSchema() throws SQLException { + return null; + } + + @Override + public void abort(Executor executor) throws SQLException { + + } + + @Override + public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { + hasSetNetworkTimeout = true; + networkTimeout = milliseconds; + } + + @Override + public int getNetworkTimeout() throws SQLException { + return networkTimeout; + } + + @Override + public Map getServerVariables() { + return null; + } + + @Override + public void setServerVariables(Map serverVariables) throws SQLException { + + } + + @Override + public void executeLater(String sql) throws SQLException { + + } + + @Override + public void flushUnsent() throws SQLException { + + } + + @Override + public void forceRollback() throws SQLException { + + } + + @Override + public void discard(Throwable t) { + + } + + @Override + public void kill() throws SQLException { + + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } + } +} diff --git a/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/sync/MockSyncManager.java b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/sync/MockSyncManager.java new file mode 100644 index 000000000..a2ca6a692 --- /dev/null +++ b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/sync/MockSyncManager.java @@ -0,0 +1,32 @@ +package com.alibaba.polardbx.transaction.sync; + +import com.alibaba.polardbx.common.model.lifecycle.AbstractLifecycle; +import com.alibaba.polardbx.executor.cursor.ResultCursor; +import com.alibaba.polardbx.executor.sync.ISyncManager; +import com.alibaba.polardbx.executor.utils.ExecUtils; +import com.alibaba.polardbx.gms.sync.IGmsSyncAction; +import com.alibaba.polardbx.gms.sync.ISyncResultHandler; +import com.alibaba.polardbx.gms.sync.SyncScope; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class MockSyncManager extends AbstractLifecycle implements ISyncManager { + @Override + public List>> sync(IGmsSyncAction action, String schemaName, SyncScope scope, + boolean throwExceptions) { + return Collections.singletonList(ExecUtils.resultSetToList((ResultCursor) action.sync())); + } + + @Override + public void sync(IGmsSyncAction action, String schemaName, SyncScope scope, ISyncResultHandler handler, + boolean throwExceptions) { + action.sync(); + } + + @Override + public List> sync(IGmsSyncAction action, String schemaName, String serverKey) { + return ExecUtils.resultSetToList((ResultCursor) action.sync()); + } +} diff --git a/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/sync/SyncActionTest.java b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/sync/SyncActionTest.java index afd59e55a..37eac7281 100644 --- a/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/sync/SyncActionTest.java +++ b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/sync/SyncActionTest.java @@ -16,22 +16,38 @@ package com.alibaba.polardbx.transaction.sync; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.Feature; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.polardbx.executor.cursor.ResultCursor; import com.alibaba.polardbx.executor.sync.CreateProcedureSyncAction; import com.alibaba.polardbx.executor.sync.CreateStoredFunctionSyncAction; +import com.alibaba.polardbx.executor.sync.DropDbRelatedProcedureSyncAction; import com.alibaba.polardbx.executor.sync.DropProcedureSyncAction; import com.alibaba.polardbx.executor.sync.DropStoredFunctionSyncAction; -import com.alibaba.polardbx.executor.sync.DropDbRelatedProcedureSyncAction; import com.alibaba.polardbx.gms.node.StorageStatus; import com.alibaba.polardbx.gms.sync.RefreshStorageStatusSyncAction; +import com.alibaba.polardbx.optimizer.context.DdlContext; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.core.row.Row; +import com.alibaba.polardbx.optimizer.utils.IConnectionHolder; +import com.alibaba.polardbx.optimizer.utils.ITransaction; +import com.alibaba.polardbx.transaction.TransactionManager; import org.junit.Assert; import org.junit.Test; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.parser.Feature; -import com.alibaba.fastjson.serializer.SerializerFeature; +import org.mockito.MockedStatic; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.BiConsumer; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; public class SyncActionTest { @@ -158,4 +174,54 @@ public void testFetchTimerTaskInfoSyncAction() { (FetchTimerTaskInfoSyncAction) JSON.parse(data, Feature.SupportAutoType); Assert.assertEquals(obj.getSchemaName(), action.getSchemaName()); } + + @Test + public void testFetchAllTransSyncAction() { + try (MockedStatic transactionManagerMockedStatic = + mockStatic(TransactionManager.class);) { + TransactionManager transactionManager = mock(TransactionManager.class); + transactionManagerMockedStatic.when((() -> TransactionManager.getInstance(any()))) + .thenReturn(transactionManager); + ConcurrentMap transactions = new ConcurrentHashMap<>(); + when(transactionManager.getTransactions()).thenReturn(transactions); + ITransaction tran = mock(ITransaction.class); + transactions.put(1024L, tran); + ExecutionContext ec = new ExecutionContext(); + when(tran.getExecutionContext()).thenReturn(ec); + when(tran.getStartTimeInMs()).thenReturn(System.currentTimeMillis()); + when(tran.getId()).thenReturn(1024L); + ec.setConnId(10001L); + ec.setOriginSql("SELECT * FROM TB1"); + ec.setDdlContext(null); + IConnectionHolder connectionHolder = mock(IConnectionHolder.class); + when(tran.getConnectionHolder()).thenReturn(connectionHolder); + doAnswer((invocation) -> { + BiConsumer consumer = invocation.getArgument(0, BiConsumer.class); + consumer.accept("test_group", 10001L); + return null; + }).when(connectionHolder).handleConnIds(any()); + + FetchAllTransSyncAction action = new FetchAllTransSyncAction("test_schema", true); + ResultCursor cursor = action.sync(); + Row row = cursor.next(); + Assert.assertEquals(Long.valueOf(1024L), row.getLong(0)); + Assert.assertEquals("test_group", row.getString(1)); + Assert.assertEquals(Long.valueOf(10001L), row.getLong(2)); + Assert.assertEquals(Long.valueOf(10001L), row.getLong(3)); + Assert.assertFalse(row.getBoolean(6)); + System.out.println(row); + + ec.setDdlContext(new DdlContext()); + action = new FetchAllTransSyncAction("test_schema", false); + cursor = action.sync(); + row = cursor.next(); + Assert.assertEquals(Long.valueOf(1024L), row.getLong(0)); + Assert.assertEquals("test_group", row.getString(1)); + Assert.assertEquals(Long.valueOf(10001L), row.getLong(2)); + Assert.assertEquals(Long.valueOf(10001L), row.getLong(3)); + Assert.assertTrue(row.getBoolean(5)); + System.out.println(row); + } + + } } diff --git a/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/trx/IgnoreBinlogTransactionTest.java b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/trx/IgnoreBinlogTransactionTest.java new file mode 100644 index 000000000..cecfb154f --- /dev/null +++ b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/trx/IgnoreBinlogTransactionTest.java @@ -0,0 +1,63 @@ +package com.alibaba.polardbx.transaction.trx; + +import com.alibaba.polardbx.common.jdbc.IConnection; +import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.optimizer.utils.ITransaction; +import com.alibaba.polardbx.transaction.TransactionManager; +import org.junit.Assert; +import org.junit.Test; + +import java.sql.Connection; + +import static org.mockito.Mockito.mock; + +public class IgnoreBinlogTransactionTest { + @Test + public void testShareReadview() { + TransactionManager transactionManager = new MockTransactionManager(); + ExecutionContext ec = new ExecutionContext(); + ec.setTxIsolation(Connection.TRANSACTION_REPEATABLE_READ); + ec.setShareReadView(true); + ITransaction trx = + transactionManager.createTransaction(ITransactionPolicy.TransactionClass.IGNORE_BINLOG_TRANSACTION, ec); + Assert.assertTrue(trx instanceof IgnoreBinlogTransaction); + Assert.assertEquals(ITransactionPolicy.TransactionClass.IGNORE_BINLOG_TRANSACTION, trx.getTransactionClass()); + Assert.assertTrue(((IgnoreBinlogTransaction) trx).getTrxLoggerPrefix() + .contains(ITransactionPolicy.TransactionClass.IGNORE_BINLOG_TRANSACTION.name())); + IConnection connection = mock(IConnection.class); + String xid = ((IgnoreBinlogTransaction) trx).getXid("group", connection); + Assert.assertTrue(xid.endsWith("'group@0000', 4")); + xid = ((IgnoreBinlogTransaction) trx).getXid("group", connection); + Assert.assertTrue(xid.endsWith("'group@0001', 4")); + } + + @Test + public void testNoShareReadview() { + TransactionManager transactionManager = new MockTransactionManager(); + ExecutionContext ec = new ExecutionContext(); + ec.setTxIsolation(Connection.TRANSACTION_REPEATABLE_READ); + ec.setShareReadView(false); + ITransaction trx = + transactionManager.createTransaction(ITransactionPolicy.TransactionClass.IGNORE_BINLOG_TRANSACTION, ec); + Assert.assertTrue(trx instanceof IgnoreBinlogTransaction); + Assert.assertEquals(ITransactionPolicy.TransactionClass.IGNORE_BINLOG_TRANSACTION, trx.getTransactionClass()); + Assert.assertTrue(((IgnoreBinlogTransaction) trx).getTrxLoggerPrefix() + .contains(ITransactionPolicy.TransactionClass.IGNORE_BINLOG_TRANSACTION.name())); + IConnection connection = mock(IConnection.class); + String xid = ((IgnoreBinlogTransaction) trx).getXid("group", connection); + Assert.assertTrue(xid.endsWith("'group', 4")); + xid = ((IgnoreBinlogTransaction) trx).getXid("group", connection); + Assert.assertTrue(xid.endsWith("'group', 4")); + } + + private static class MockTransactionManager extends TransactionManager { + public void enableKillTimeoutTransaction() { + // do nothing + } + + public void enableLogCleanTask() { + // do nothing + } + } +} diff --git a/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/trx/SyncPointTransactionTest.java b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/trx/SyncPointTransactionTest.java new file mode 100644 index 000000000..edbf37bb7 --- /dev/null +++ b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/trx/SyncPointTransactionTest.java @@ -0,0 +1,37 @@ +package com.alibaba.polardbx.transaction.trx; + +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.transaction.TransactionManager; +import com.alibaba.polardbx.transaction.tso.ClusterTimestampOracle; +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class SyncPointTransactionTest { + @Test + public void testSyncPoint() throws NoSuchFieldException, IllegalAccessException { + ExecutionContext ctx = new ExecutionContext(); + TransactionManager transactionManager = mock(TransactionManager.class); + ClusterTimestampOracle tso = mock(ClusterTimestampOracle.class); + when(transactionManager.getTimestampOracle()).thenReturn(tso); + + SyncPointTransaction syncPointTransaction = new SyncPointTransaction(ctx, transactionManager); + String primarySchema = "test_primary_schema"; + setParentVar(syncPointTransaction, AbstractTransaction.class, "primarySchema", primarySchema); + } + + private static void setInstanceVar(Object obj, String fieldName, Object value) + throws NoSuchFieldException, IllegalAccessException { + java.lang.reflect.Field field = obj.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + field.set(obj, value); + } + + private static void setParentVar(Object obj, Class parentClass, String fieldName, Object value) + throws NoSuchFieldException, IllegalAccessException { + java.lang.reflect.Field field = parentClass.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(obj, value); + } +} diff --git a/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/tso/SessionTest.java b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/tso/SessionTest.java new file mode 100644 index 000000000..c25fa56b8 --- /dev/null +++ b/polardbx-transaction/src/test/java/com/alibaba/polardbx/transaction/tso/SessionTest.java @@ -0,0 +1,67 @@ +package com.alibaba.polardbx.transaction.tso; + +import com.alibaba.polardbx.common.jdbc.ITransactionPolicy; +import com.alibaba.polardbx.common.properties.ConnectionProperties; +import com.alibaba.polardbx.executor.common.ExecutorContext; +import com.alibaba.polardbx.executor.common.StorageInfoManager; +import com.alibaba.polardbx.executor.mpp.Session; +import com.alibaba.polardbx.optimizer.context.ExecutionContext; +import com.alibaba.polardbx.transaction.ColumnarTransaction; +import com.alibaba.polardbx.transaction.TransactionManager; +import com.alibaba.polardbx.transaction.trx.AutoCommitSingleShardTsoTransaction; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.sql.SQLException; +import java.util.HashMap; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +public class SessionTest { + + @Test + public void testColumnarGetTso() throws SQLException { + ExecutionContext context = new ExecutionContext(); + context.getExtraCmds().put(ConnectionProperties.SNAPSHOT_TS, 1); + ColumnarTransaction transaction = mock(ColumnarTransaction.class); + Mockito.when(transaction.getTransactionClass()).thenReturn( + ITransactionPolicy.TransactionClass.COLUMNAR_READ_ONLY_TRANSACTION); + context.setTransaction(transaction); + Session session = new Session("session", context); + session.generateTsoInfo(); + Assert.assertTrue(session.getTsoTime() == 1L); + } + + @Test + public void testNonColumnarGetTso() throws SQLException { + + ExecutionContext executionContext = new ExecutionContext("polardbx"); + executionContext.getExtraCmds().put(ConnectionProperties.SNAPSHOT_TS, 1); + executionContext.getExtraCmds().put(ConnectionProperties.ENABLE_CONSISTENT_REPLICA_READ, true); + + ExecutorContext ec = mock(ExecutorContext.class); + + TransactionManager transactionManager = spy(new TransactionManager()); + StorageInfoManager mockStorageManager = mock(StorageInfoManager.class); + transactionManager.prepare("polardbx", new HashMap<>(), mockStorageManager); + when(mockStorageManager.supportTso()).thenReturn(true); + when(ec.getStorageInfoManager()).thenReturn(mockStorageManager); + + try (MockedStatic mockedEc = mockStatic(ExecutorContext.class)) { + mockedEc.when(() -> ExecutorContext.getContext(any())).thenReturn(ec); + AutoCommitSingleShardTsoTransaction transaction = spy(new AutoCommitSingleShardTsoTransaction( + executionContext, transactionManager, false, true)); + executionContext.setTransaction(transaction); + Session session = new Session("session", executionContext); + session.generateTsoInfo(); + Assert.assertTrue(session.getTsoTime() == 1L); + } + } + +} diff --git a/polardbx-transaction/src/test/resources/META-INF/services/com.alibaba.polardbx.executor.sync.ISyncManager b/polardbx-transaction/src/test/resources/META-INF/services/com.alibaba.polardbx.executor.sync.ISyncManager new file mode 100644 index 000000000..7a5e7efe8 --- /dev/null +++ b/polardbx-transaction/src/test/resources/META-INF/services/com.alibaba.polardbx.executor.sync.ISyncManager @@ -0,0 +1 @@ +com.alibaba.polardbx.transaction.sync.MockSyncManager \ No newline at end of file diff --git a/pom.xml b/pom.xml index b70150ea7..64f1db172 100644 --- a/pom.xml +++ b/pom.xml @@ -60,23 +60,23 @@ ${polardbx.version}-SNAPSHOT 1.7.21 - 1.1 - 1.2.16 - 1.2.8 - 2.4.21 - 5.1.49 + 1.2.3 + 2.1.9 + 2.5.6.SEC03 + 5.1.40.13 + 4.12 1.18.10 - 2.13.3 + 2.13.1 0.2 1.6.4 - 1.7.26 + 1.7.9 3.1.0 2.9.5 1.8 - 1.31 + 1.21 1.0.11-SNAPSHOT 0.17 @@ -87,15 +87,14 @@ 5.1.0 1 3 - 0.16 - 1.6 + 0.21 0.7 1.30 1.17.0 false false generate-sources - 0.9.31 + 1.2.1 1.11.0-SNAPSHOT @@ -105,7 +104,7 @@ 1.4 3.8.1 1.11 - 9.1.6 + 9.1.3 1.3.9 1.4.185 0.9.0 @@ -115,7 +114,7 @@ 0.4.1 0.8 0.1 - 3.0.8 + 3.1.6 1.1 1.3 1.1.9 @@ -143,33 +142,33 @@ 1.9.13 0.0.2-SNAPSHOT 1.0.2 - 2.2 + 1.1 0.2.8 1.4.01 + 9.4.20.v20190813 3.12.4 2.5.6.SEC03 2.0.2 3.16 1.9.3 + 0.8.7 - 1.9.4 + 1.9.2 2.6 - 2.7 - 1.6 - 30.1.1-jre + 2.4 + 1.3.1 + 27.0.1-jre 1.2.83 1.2.8 3.1 - 2.0.2 2.3.4.726 8.8.13-0-0 4.1.44.Final 3.11.1 1.4 1.30.0 - 3.2.4 2.5 @@ -177,9 +176,8 @@ 1.6 2.9.9 1.21 - 3.0.0 3.0.3 - 2.8.2 + 3.10.2 0.17.3 1.1.0 2.9.3 @@ -209,7 +207,52 @@ + + + com.aliyun.oss + aliyun-sdk-oss + ${aliyun-sdk-oss.version} + + + commons-logging + commons-logging + + + + org.jdom + jdom2 + + + + org.codehaus.jettison + jettison + + + + com.aliyun + aliyun-java-sdk-ram + + + com.aliyun + aliyun-java-sdk-sts + + + com.aliyun + aliyun-java-sdk-ecs + + + com.aliyun + aliyun-java-sdk-kms + + + org.apache.httpcomponents + httpclient + + + + + com.alibaba.wisp wisp-api @@ -219,6 +262,12 @@ commons-beanutils commons-beanutils ${commons-beanutils.version} + + + commons-logging + commons-logging + + @@ -232,10 +281,9 @@ ${commons-io.version} - commons-pool - commons-pool - ${commons-pool.version} - provided + commons-fileupload + commons-fileupload + ${fileupload.version} com.google.guava @@ -247,6 +295,16 @@ fastjson ${fastjson.version} + + com.taobao.diamond + diamond-client + ${diamond_version} + + + com.alibaba + druid + ${druid.version} + io.netty @@ -287,6 +345,45 @@ tests test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mysql @@ -295,40 +392,24 @@ - org.slf4j - slf4j-api - ${slf4j_version} - provided + ch.qos.logback + logback-classic + ${logback_version} org.slf4j jcl-over-slf4j ${slf4j_version} - provided org.slf4j - slf4j-log4j12 + slf4j-api ${slf4j_version} - provided - - - commons-logging - commons-logging-api - ${jcl_version} - provided - - - log4j - log4j - ${log4j_version} - provided - ch.qos.logback - logback-classic - ${logback_version} - provided + org.slf4j + log4j-over-slf4j + ${slf4j_version} @@ -338,6 +419,12 @@ ${junit_version} test + + org.apache.ibatis + ibatis-sqlmap + ${ibatis-sqlmap.version} + test + org.projectlombok lombok @@ -396,29 +483,16 @@ ${mockito.verison} test - - net.bytebuddy - byte-buddy-agent - ${byte-buddy.version} - - - org.hamcrest - hamcrest - ${hamcrest.version} - test - - - - org.apache.arrow - arrow-vector - ${arrow.version} - - - org.apache.arrow - arrow-memory-netty - ${arrow.version} - runtime - + + + + + + + + + + io.dropwizard.metrics metrics-core @@ -438,10 +512,130 @@ - net.bytebuddy - byte-buddy-agent - ${byte-buddy.version} + org.apache.hadoop + hadoop-common + ${hadoop.version} + + + javax.servlet + javax.servlet-api + + + org.eclipse.jetty + jetty-webapp + + + com.sun.jersey + jersey-servlet + + + org.apache.curator + curator-client + + + + + + + + + + + + + + + org.eclipse.jetty + jetty-util + + + org.eclipse.jetty + jetty-servlet + + + javax.servlet.jsp + jsp-api + + + commons-logging + commons-logging + + + org.apache.curator + curator-recipes + + + org.apache.kerby + kerb-simplekdc + + + commons-logging + commons-logging-api + + + jetty + org.eclipse.jetty + + + org.eclipse.jetty + jetty-server + + + org.eclipse.jetty + servlet-api-2.5 + + + com.sun.jersey + jersey-core + + + com.sun.jersey + jersey-json + + + com.sun.jersey + jersey-server + + + org.apache.avro + avro + + + + + + + dnsjava + dnsjava + + + org.eclipse.jdt + core + + + org.apache.avro + avro-ipc + + + net.sf.kosmosfs + kfs + + + com.jcraft + jsch + + + org.apache.zookeeper + zookeeper + + + + org.slf4j + slf4j-log4j12 + + + @@ -512,7 +706,8 @@ maven-surefire-plugin 3.0.0-M4 - -javaagent:${project.basedir}/target/byte-buddy-agent-${byte-buddy.version}.jar + -javaagent:${project.basedir}/../script/byte-buddy-agent-${byte-buddy.version}.jar + **/*Test.java @@ -583,28 +778,6 @@ resolveCiFriendliesOnly - - org.apache.maven.plugins - maven-dependency-plugin - - - copy - process-resources - - copy - - - - - net.bytebuddy - byte-buddy-agent - ${project.build.directory} - - - - - - src/main/java src/test/java diff --git a/script/byte-buddy-agent-1.9.3.jar b/script/byte-buddy-agent-1.9.3.jar new file mode 100644 index 000000000..51a0bd48f Binary files /dev/null and b/script/byte-buddy-agent-1.9.3.jar differ